Merge "Using ULS in Special:PageLanguage"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 16 Sep 2014 13:16:19 +0000 (13:16 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 16 Sep 2014 13:16:19 +0000 (13:16 +0000)
2395 files changed:
.gitignore
.jscsrc
.travis.yml
CREDITS
RELEASE-NOTES-1.24
api.php
assets/file-type-icons/COPYING [new file with mode: 0644]
assets/file-type-icons/fileicon-c.png [new file with mode: 0644]
assets/file-type-icons/fileicon-cpp.png [new file with mode: 0644]
assets/file-type-icons/fileicon-deb.png [new file with mode: 0644]
assets/file-type-icons/fileicon-djvu.png [new file with mode: 0644]
assets/file-type-icons/fileicon-djvu.xcf [new file with mode: 0644]
assets/file-type-icons/fileicon-dvi.png [new file with mode: 0644]
assets/file-type-icons/fileicon-exe.png [new file with mode: 0644]
assets/file-type-icons/fileicon-h.png [new file with mode: 0644]
assets/file-type-icons/fileicon-html.png [new file with mode: 0644]
assets/file-type-icons/fileicon-iso.png [new file with mode: 0644]
assets/file-type-icons/fileicon-java.png [new file with mode: 0644]
assets/file-type-icons/fileicon-mid.png [new file with mode: 0644]
assets/file-type-icons/fileicon-mov.png [new file with mode: 0644]
assets/file-type-icons/fileicon-o.png [new file with mode: 0644]
assets/file-type-icons/fileicon-ogg.png [new file with mode: 0644]
assets/file-type-icons/fileicon-ogg.xcf [new file with mode: 0644]
assets/file-type-icons/fileicon-pdf.png [new file with mode: 0644]
assets/file-type-icons/fileicon-ps.png [new file with mode: 0644]
assets/file-type-icons/fileicon-psd.png [new file with mode: 0644]
assets/file-type-icons/fileicon-rm.png [new file with mode: 0644]
assets/file-type-icons/fileicon-rpm.png [new file with mode: 0644]
assets/file-type-icons/fileicon-svg.png [new file with mode: 0644]
assets/file-type-icons/fileicon-tar.png [new file with mode: 0644]
assets/file-type-icons/fileicon-tex.png [new file with mode: 0644]
assets/file-type-icons/fileicon-ttf.png [new file with mode: 0644]
assets/file-type-icons/fileicon-txt.png [new file with mode: 0644]
assets/file-type-icons/fileicon-xcf.png [new file with mode: 0644]
assets/file-type-icons/fileicon.png [new file with mode: 0644]
assets/licenses/cc-0.png [new file with mode: 0644]
assets/licenses/cc-by-nc-sa.png [new file with mode: 0644]
assets/licenses/cc-by-sa.png [new file with mode: 0644]
assets/licenses/cc-by.png [new file with mode: 0644]
assets/licenses/gnu-fdl.png [new file with mode: 0644]
assets/licenses/public-domain.png [new file with mode: 0644]
assets/mediawiki.png [new file with mode: 0644]
assets/poweredby_mediawiki_88x31.png [new file with mode: 0644]
docs/export-0.9.xsd [new file with mode: 0644]
docs/export-demo.xml
docs/hooks.txt
docs/kss/Makefile
docs/kss/scripts/kss-node-check.sh [new file with mode: 0755]
docs/kss/scripts/nodecheck.sh [deleted file]
docs/kss/styleguide-template/index.html
docs/kss/styleguide-template/public/kss.less
docs/uidesign/confirmable.html [new file with mode: 0644]
docs/uidesign/design.html
extensions/README
images/README
img_auth.php
includes/AjaxDispatcher.php
includes/AjaxResponse.php
includes/AutoLoader.php
includes/Block.php
includes/CacheHelper.php [deleted file]
includes/Category.php
includes/CategoryFinder.php [new file with mode: 0644]
includes/CategoryViewer.php
includes/Categoryfinder.php [deleted file]
includes/ChangeTags.php
includes/ChangesFeed.php [deleted file]
includes/Collation.php
includes/Cookie.php
includes/DefaultSettings.php
includes/Defines.php
includes/EditPage.php
includes/Export.php
includes/Fallback.php
includes/Feed.php
includes/FeedUtils.php
includes/ForkController.php
includes/FormOptions.php
includes/GitInfo.php
includes/GlobalFunctions.php
includes/HistoryBlob.php
includes/Hooks.php
includes/Html.php
includes/HtmlFormatter.php
includes/HttpFunctions.php
includes/Import.php
includes/Init.php [deleted file]
includes/Licenses.php
includes/Linker.php
includes/MWNamespace.php [new file with mode: 0644]
includes/MWTimestamp.php
includes/MagicWord.php
includes/MediaWiki.php [new file with mode: 0644]
includes/Message.php
includes/MessageBlobStore.php
includes/MimeMagic.php
includes/Namespace.php [deleted file]
includes/OutputPage.php
includes/PHPVersionError.php
includes/Pager.php [deleted file]
includes/Preferences.php
includes/PrefixSearch.php
includes/ProtectionForm.php
includes/Revision.php
includes/Sanitizer.php
includes/Setup.php
includes/SiteConfiguration.php
includes/SiteStats.php
includes/Skin.php [deleted file]
includes/SkinTemplate.php [deleted file]
includes/SquidPurgeClient.php
includes/StatCounter.php
includes/Status.php
includes/StubObject.php
includes/Title.php
includes/User.php
includes/UserArrayFromResult.php
includes/UserMailer.php [deleted file]
includes/UserRightsProxy.php
includes/WatchedItem.php
includes/WebRequest.php
includes/WebResponse.php
includes/WebStart.php
includes/Wiki.php [deleted file]
includes/Xml.php
includes/actions/Action.php
includes/actions/CachedAction.php
includes/actions/CreditsAction.php
includes/actions/DeleteAction.php
includes/actions/EditAction.php
includes/actions/FormAction.php
includes/actions/FormlessAction.php
includes/actions/HistoryAction.php
includes/actions/InfoAction.php
includes/actions/ProtectAction.php
includes/actions/RawAction.php
includes/actions/RevertAction.php
includes/actions/RollbackAction.php
includes/actions/SubmitAction.php [new file with mode: 0644]
includes/actions/UnprotectAction.php [new file with mode: 0644]
includes/actions/UnwatchAction.php [new file with mode: 0644]
includes/actions/WatchAction.php
includes/api/ApiBase.php
includes/api/ApiBlock.php
includes/api/ApiClearHasMsg.php [new file with mode: 0644]
includes/api/ApiComparePages.php
includes/api/ApiCreateAccount.php
includes/api/ApiDelete.php
includes/api/ApiEditPage.php
includes/api/ApiEmailUser.php
includes/api/ApiExpandTemplates.php
includes/api/ApiFeedContributions.php
includes/api/ApiFeedRecentChanges.php
includes/api/ApiFeedWatchlist.php
includes/api/ApiFileRevert.php
includes/api/ApiFormatBase.php
includes/api/ApiFormatDbg.php
includes/api/ApiFormatDump.php
includes/api/ApiFormatFeedWrapper.php [new file with mode: 0644]
includes/api/ApiFormatJson.php
includes/api/ApiFormatTxt.php
includes/api/ApiFormatWddx.php
includes/api/ApiFormatYaml.php
includes/api/ApiHelp.php
includes/api/ApiImageRotate.php
includes/api/ApiImport.php
includes/api/ApiLogin.php
includes/api/ApiLogout.php
includes/api/ApiMain.php
includes/api/ApiModuleManager.php
includes/api/ApiMove.php
includes/api/ApiOptions.php
includes/api/ApiPageSet.php
includes/api/ApiParamInfo.php
includes/api/ApiParse.php
includes/api/ApiPatrol.php
includes/api/ApiProtect.php
includes/api/ApiPurge.php
includes/api/ApiQuery.php
includes/api/ApiQueryAllCategories.php
includes/api/ApiQueryAllImages.php
includes/api/ApiQueryAllLinks.php
includes/api/ApiQueryAllMessages.php
includes/api/ApiQueryAllPages.php
includes/api/ApiQueryAllUsers.php
includes/api/ApiQueryBacklinks.php
includes/api/ApiQueryBase.php
includes/api/ApiQueryBlocks.php
includes/api/ApiQueryCategories.php
includes/api/ApiQueryCategoryInfo.php
includes/api/ApiQueryCategoryMembers.php
includes/api/ApiQueryContributors.php
includes/api/ApiQueryDeletedrevs.php
includes/api/ApiQueryDuplicateFiles.php
includes/api/ApiQueryExtLinksUsage.php
includes/api/ApiQueryExternalLinks.php
includes/api/ApiQueryFilearchive.php
includes/api/ApiQueryIWBacklinks.php
includes/api/ApiQueryIWLinks.php
includes/api/ApiQueryImageInfo.php
includes/api/ApiQueryImages.php
includes/api/ApiQueryInfo.php
includes/api/ApiQueryLangBacklinks.php
includes/api/ApiQueryLangLinks.php
includes/api/ApiQueryLinks.php
includes/api/ApiQueryLogEvents.php
includes/api/ApiQueryProtectedTitles.php
includes/api/ApiQueryQueryPage.php
includes/api/ApiQueryRandom.php
includes/api/ApiQueryRecentChanges.php
includes/api/ApiQueryRevisions.php
includes/api/ApiQuerySearch.php
includes/api/ApiQuerySiteinfo.php
includes/api/ApiQueryStashImageInfo.php
includes/api/ApiQueryTags.php
includes/api/ApiQueryTokens.php [new file with mode: 0644]
includes/api/ApiQueryUserContributions.php
includes/api/ApiQueryUserInfo.php
includes/api/ApiQueryUsers.php
includes/api/ApiQueryWatchlist.php
includes/api/ApiQueryWatchlistRaw.php
includes/api/ApiResult.php
includes/api/ApiRevisionDelete.php
includes/api/ApiRollback.php
includes/api/ApiSetNotificationTimestamp.php
includes/api/ApiTokens.php
includes/api/ApiUnblock.php
includes/api/ApiUndelete.php
includes/api/ApiUpload.php
includes/api/ApiUserrights.php
includes/api/ApiWatch.php
includes/cache/CacheDependency.php
includes/cache/CacheHelper.php [new file with mode: 0644]
includes/cache/LinkBatch.php
includes/cache/LinkCache.php
includes/cache/LocalisationCache.php
includes/cache/MapCacheLRU.php
includes/cache/MessageCache.php
includes/cache/bloom/BloomCache.php [new file with mode: 0644]
includes/cache/bloom/BloomCacheRedis.php [new file with mode: 0644]
includes/cache/bloom/BloomFilters.php [new file with mode: 0644]
includes/changes/ChangesFeed.php [new file with mode: 0644]
includes/changes/ChangesList.php
includes/changes/EnhancedChangesList.php
includes/changes/OldChangesList.php
includes/changes/RecentChange.php
includes/clientpool/RedisConnectionPool.php
includes/config/Config.php
includes/config/ConfigException.php
includes/config/ConfigFactory.php
includes/config/GlobalVarConfig.php
includes/config/MutableConfig.php [new file with mode: 0644]
includes/content/AbstractContent.php
includes/content/CodeContentHandler.php [new file with mode: 0644]
includes/content/ContentHandler.php
includes/content/CssContent.php
includes/content/CssContentHandler.php
includes/content/JavaScriptContent.php
includes/content/JavaScriptContentHandler.php
includes/content/JsonContent.php [new file with mode: 0644]
includes/content/JsonContentHandler.php [new file with mode: 0644]
includes/content/MessageContent.php
includes/content/TextContent.php
includes/content/TextContentHandler.php
includes/content/WikitextContent.php
includes/content/WikitextContentHandler.php
includes/context/ContextSource.php
includes/context/DerivativeContext.php
includes/context/RequestContext.php
includes/db/Database.php
includes/db/DatabaseMssql.php
includes/db/DatabaseMysqlBase.php
includes/db/DatabaseMysqli.php
includes/db/DatabaseOracle.php
includes/db/DatabasePostgres.php
includes/db/DatabaseSqlite.php
includes/db/DatabaseUtility.php
includes/db/IORMTable.php
includes/db/LBFactory.php
includes/db/LBFactoryMulti.php
includes/db/LoadBalancer.php
includes/db/LoadMonitor.php
includes/db/ORMTable.php
includes/debug/Debug.php [deleted file]
includes/debug/MWDebug.php [new file with mode: 0644]
includes/deferred/DataUpdate.php
includes/deferred/DeferredUpdates.php
includes/deferred/LinksUpdate.php
includes/deferred/SearchUpdate.php
includes/deferred/SqlDataUpdate.php
includes/deferred/ViewCountUpdate.php
includes/diff/DifferenceEngine.php
includes/exception/BadTitleError.php
includes/exception/ErrorPageError.php
includes/exception/MWException.php
includes/exception/UserNotLoggedIn.php
includes/externalstore/ExternalStore.php
includes/externalstore/ExternalStoreDB.php
includes/filebackend/FSFile.php
includes/filebackend/FSFileBackend.php
includes/filebackend/FileBackend.php
includes/filebackend/FileBackendStore.php
includes/filebackend/README
includes/filebackend/SwiftFileBackend.php
includes/filebackend/filejournal/FileJournal.php
includes/filebackend/lockmanager/DBLockManager.php
includes/filebackend/lockmanager/LockManagerGroup.php
includes/filebackend/lockmanager/MemcLockManager.php
includes/filebackend/lockmanager/RedisLockManager.php
includes/filerepo/FileRepo.php
includes/filerepo/LocalRepo.php
includes/filerepo/RepoGroup.php
includes/filerepo/file/ArchivedFile.php
includes/filerepo/file/File.php
includes/filerepo/file/LocalFile.php
includes/filerepo/file/OldLocalFile.php
includes/gallery/ImageGalleryBase.php
includes/gallery/PackedImageGallery.php
includes/htmlform/HTMLAutoCompleteSelectField.php [new file with mode: 0644]
includes/htmlform/HTMLCheckField.php
includes/htmlform/HTMLCheckMatrix.php
includes/htmlform/HTMLEditTools.php
includes/htmlform/HTMLForm.php
includes/htmlform/HTMLFormField.php
includes/htmlform/HTMLFormFieldCloner.php
includes/htmlform/HTMLHiddenField.php
includes/htmlform/HTMLInfoField.php
includes/htmlform/HTMLMultiSelectField.php
includes/htmlform/HTMLSelectField.php
includes/htmlform/HTMLSelectLimitField.php [new file with mode: 0644]
includes/htmlform/HTMLTextAreaField.php
includes/htmlform/HTMLTextField.php
includes/installer/DatabaseInstaller.php
includes/installer/DatabaseUpdater.php
includes/installer/Installer.php
includes/installer/LocalSettingsGenerator.php
includes/installer/MssqlInstaller.php
includes/installer/MssqlUpdater.php
includes/installer/MysqlInstaller.php
includes/installer/MysqlUpdater.php
includes/installer/PostgresInstaller.php
includes/installer/PostgresUpdater.php
includes/installer/SqliteUpdater.php
includes/installer/WebInstaller.php
includes/installer/WebInstallerOutput.php
includes/installer/WebInstallerPage.php
includes/installer/i18n/ar.json
includes/installer/i18n/av.json [new file with mode: 0644]
includes/installer/i18n/be-tarask.json
includes/installer/i18n/bg.json
includes/installer/i18n/bn.json
includes/installer/i18n/br.json
includes/installer/i18n/bto.json [new file with mode: 0644]
includes/installer/i18n/ca.json
includes/installer/i18n/ce.json
includes/installer/i18n/cs.json
includes/installer/i18n/da.json
includes/installer/i18n/de.json
includes/installer/i18n/en-gb.json
includes/installer/i18n/en.json
includes/installer/i18n/eo.json
includes/installer/i18n/es.json
includes/installer/i18n/et.json
includes/installer/i18n/fa.json
includes/installer/i18n/fi.json
includes/installer/i18n/fr.json
includes/installer/i18n/gl.json
includes/installer/i18n/haw.json
includes/installer/i18n/he.json
includes/installer/i18n/ia.json
includes/installer/i18n/id.json
includes/installer/i18n/it.json
includes/installer/i18n/ja.json
includes/installer/i18n/ko.json
includes/installer/i18n/lb.json
includes/installer/i18n/lzh.json
includes/installer/i18n/mk.json
includes/installer/i18n/ms.json
includes/installer/i18n/mt.json
includes/installer/i18n/nap.json
includes/installer/i18n/nb.json
includes/installer/i18n/ne.json
includes/installer/i18n/nl.json
includes/installer/i18n/no.json [deleted file]
includes/installer/i18n/oc.json
includes/installer/i18n/pa.json
includes/installer/i18n/pl.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/sc.json
includes/installer/i18n/sco.json
includes/installer/i18n/sl.json
includes/installer/i18n/sv.json
includes/installer/i18n/tr.json
includes/installer/i18n/uk.json
includes/installer/i18n/zh-hans.json
includes/installer/i18n/zh-hant.json
includes/interwiki/Interwiki.php
includes/jobqueue/Job.php
includes/jobqueue/JobQueueFederated.php
includes/jobqueue/JobQueueRedis.php
includes/jobqueue/JobRunner.php [new file with mode: 0644]
includes/jobqueue/aggregator/JobQueueAggregatorMemc.php
includes/jobqueue/aggregator/JobQueueAggregatorRedis.php
includes/jobqueue/jobs/DoubleRedirectJob.php
includes/jobqueue/jobs/DuplicateJob.php
includes/jobqueue/jobs/NullJob.php
includes/jobqueue/jobs/UploadFromUrlJob.php
includes/libs/CSSJanus.php
includes/libs/CSSMin.php
includes/libs/IEContentAnalyzer.php
includes/libs/MultiHttpClient.php
includes/libs/lessc.inc.php
includes/logging/LogEntry.php
includes/logging/LogEventsList.php
includes/logging/LogFormatter.php
includes/logging/LogPage.php
includes/logging/LogPager.php
includes/mail/EmailNotification.php [new file with mode: 0644]
includes/mail/MailAddress.php [new file with mode: 0644]
includes/mail/UserMailer.php [new file with mode: 0644]
includes/media/Bitmap.php
includes/media/BitmapMetadataHandler.php
includes/media/DjVu.php
includes/media/DjVuImage.php
includes/media/Exif.php
includes/media/ExifBitmap.php
includes/media/FormatMetadata.php
includes/media/IPTC.php
includes/media/Jpeg.php
includes/media/JpegMetadataExtractor.php
includes/media/MediaHandler.php
includes/media/MediaTransformOutput.php
includes/media/PNG.php
includes/media/PNGMetadataExtractor.php
includes/media/SVG.php
includes/media/TransformationalImageHandler.php [new file with mode: 0644]
includes/media/XCF.php
includes/media/XMP.php
includes/media/XMPInfo.php
includes/mime.info
includes/mime.types
includes/normal/UtfNormalBench.php
includes/normal/UtfNormalMemStress.php
includes/objectcache/BagOStuff.php
includes/objectcache/MemcachedBagOStuff.php
includes/objectcache/MemcachedClient.php
includes/objectcache/MemcachedPeclBagOStuff.php
includes/objectcache/MultiWriteBagOStuff.php
includes/objectcache/ObjectCache.php
includes/objectcache/RedisBagOStuff.php
includes/objectcache/SqlBagOStuff.php
includes/objectcache/WinCacheBagOStuff.php
includes/page/Article.php
includes/page/ImagePage.php
includes/page/WikiFilePage.php
includes/page/WikiPage.php
includes/pager/AlphabeticPager.php [new file with mode: 0644]
includes/pager/IndexPager.php [new file with mode: 0644]
includes/pager/Pager.php [new file with mode: 0644]
includes/pager/ReverseChronologicalPager.php [new file with mode: 0644]
includes/pager/TablePager.php [new file with mode: 0644]
includes/parser/CacheTime.php
includes/parser/CoreParserFunctions.php
includes/parser/CoreTagHooks.php
includes/parser/DateFormatter.php
includes/parser/LinkHolderArray.php
includes/parser/MWTidy.php [new file with mode: 0644]
includes/parser/Parser.php
includes/parser/ParserCache.php
includes/parser/ParserDiffTest.php
includes/parser/ParserOptions.php
includes/parser/ParserOutput.php
includes/parser/Preprocessor.php
includes/parser/Preprocessor_DOM.php
includes/parser/Preprocessor_Hash.php
includes/parser/StripState.php
includes/parser/Tidy.php [deleted file]
includes/password/BcryptPassword.php [new file with mode: 0644]
includes/password/EncryptedPassword.php [new file with mode: 0644]
includes/password/InvalidPassword.php [new file with mode: 0644]
includes/password/LayeredParameterizedPassword.php [new file with mode: 0644]
includes/password/MWOldPassword.php [new file with mode: 0644]
includes/password/MWSaltedPassword.php [new file with mode: 0644]
includes/password/ParameterizedPassword.php [new file with mode: 0644]
includes/password/Password.php [new file with mode: 0644]
includes/password/PasswordError.php [new file with mode: 0644]
includes/password/PasswordFactory.php [new file with mode: 0644]
includes/password/Pbkdf2Password.php [new file with mode: 0644]
includes/poolcounter/PoolCounter.php
includes/poolcounter/PoolCounterRedis.php
includes/poolcounter/PoolCounterWork.php
includes/poolcounter/PoolCounterWorkViaCallback.php [new file with mode: 0644]
includes/poolcounter/PoolWorkArticleView.php
includes/profiler/Profiler.php
includes/profiler/ProfilerMwprof.php
includes/profiler/ProfilerSimpleUDP.php
includes/profiler/ProfilerStandard.php
includes/rcfeed/MachineReadableRCFeedFormatter.php
includes/rcfeed/RCFeedEngine.php
includes/resourceloader/DerivativeResourceLoaderContext.php [new file with mode: 0644]
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderContext.php
includes/resourceloader/ResourceLoaderEditToolbarModule.php [new file with mode: 0644]
includes/resourceloader/ResourceLoaderFileModule.php
includes/resourceloader/ResourceLoaderFilePath.php [new file with mode: 0644]
includes/resourceloader/ResourceLoaderLESSFunctions.php
includes/resourceloader/ResourceLoaderLanguageDataModule.php
includes/resourceloader/ResourceLoaderLanguageNamesModule.php
includes/resourceloader/ResourceLoaderModule.php
includes/resourceloader/ResourceLoaderSiteModule.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php
includes/resourceloader/ResourceLoaderUserGroupsModule.php
includes/resourceloader/ResourceLoaderUserModule.php
includes/resourceloader/ResourceLoaderUserTokensModule.php
includes/resourceloader/ResourceLoaderWikiModule.php
includes/revisiondelete/RevDelArchiveItem.php [new file with mode: 0644]
includes/revisiondelete/RevDelArchiveList.php [new file with mode: 0644]
includes/revisiondelete/RevDelArchivedFileItem.php [new file with mode: 0644]
includes/revisiondelete/RevDelArchivedFileList.php [new file with mode: 0644]
includes/revisiondelete/RevDelArchivedRevisionItem.php [new file with mode: 0644]
includes/revisiondelete/RevDelFileItem.php [new file with mode: 0644]
includes/revisiondelete/RevDelFileList.php [new file with mode: 0644]
includes/revisiondelete/RevDelItem.php [new file with mode: 0644]
includes/revisiondelete/RevDelList.php [new file with mode: 0644]
includes/revisiondelete/RevDelLogItem.php [new file with mode: 0644]
includes/revisiondelete/RevDelLogList.php [new file with mode: 0644]
includes/revisiondelete/RevDelRevisionItem.php [new file with mode: 0644]
includes/revisiondelete/RevDelRevisionList.php [new file with mode: 0644]
includes/revisiondelete/RevisionDelete.php [deleted file]
includes/revisiondelete/RevisionDeleteAbstracts.php [deleted file]
includes/revisiondelete/RevisionDeleter.php
includes/search/SearchEngine.php
includes/search/SearchHighlighter.php
includes/search/SearchMssql.php
includes/search/SearchMySQL.php
includes/search/SearchOracle.php
includes/search/SearchPostgres.php
includes/search/SearchResult.php
includes/search/SearchResultSet.php
includes/search/SearchSqlite.php
includes/site/MediaWikiSite.php
includes/site/Site.php
includes/site/SiteList.php
includes/site/SiteSQLStore.php
includes/skins/Skin.php [new file with mode: 0644]
includes/skins/SkinException.php [new file with mode: 0644]
includes/skins/SkinFactory.php [new file with mode: 0644]
includes/skins/SkinFallback.php [new file with mode: 0644]
includes/skins/SkinFallbackTemplate.php [new file with mode: 0644]
includes/skins/SkinTemplate.php [new file with mode: 0644]
includes/specialpage/ChangesListSpecialPage.php
includes/specialpage/ImageQueryPage.php
includes/specialpage/QueryPage.php
includes/specialpage/RedirectSpecialPage.php
includes/specialpage/SpecialPage.php
includes/specialpage/SpecialPageFactory.php
includes/specialpage/WantedQueryPage.php
includes/specials/SpecialActiveusers.php
includes/specials/SpecialAllMessages.php
includes/specials/SpecialAllPages.php
includes/specials/SpecialBlock.php
includes/specials/SpecialBlockList.php
includes/specials/SpecialBooksources.php
includes/specials/SpecialCategories.php
includes/specials/SpecialChangeEmail.php
includes/specials/SpecialChangePassword.php
includes/specials/SpecialContributions.php
includes/specials/SpecialDeletedContributions.php
includes/specials/SpecialEditWatchlist.php
includes/specials/SpecialEmailuser.php
includes/specials/SpecialExpandTemplates.php
includes/specials/SpecialExport.php
includes/specials/SpecialFileDuplicateSearch.php
includes/specials/SpecialFilepath.php
includes/specials/SpecialImport.php
includes/specials/SpecialJavaScriptTest.php
includes/specials/SpecialLinkSearch.php
includes/specials/SpecialListDuplicatedFiles.php
includes/specials/SpecialListfiles.php
includes/specials/SpecialListgrouprights.php
includes/specials/SpecialListusers.php
includes/specials/SpecialLockdb.php
includes/specials/SpecialLog.php
includes/specials/SpecialMIMEsearch.php
includes/specials/SpecialMergeHistory.php
includes/specials/SpecialMovepage.php
includes/specials/SpecialMyLanguage.php [new file with mode: 0644]
includes/specials/SpecialNewimages.php
includes/specials/SpecialNewpages.php
includes/specials/SpecialPageLanguage.php
includes/specials/SpecialPagesWithProp.php
includes/specials/SpecialPasswordReset.php
includes/specials/SpecialProtectedpages.php
includes/specials/SpecialProtectedtitles.php
includes/specials/SpecialRandomInCategory.php
includes/specials/SpecialRandompage.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialRecentchangeslinked.php
includes/specials/SpecialRedirect.php
includes/specials/SpecialResetTokens.php
includes/specials/SpecialRevisiondelete.php
includes/specials/SpecialRunJobs.php
includes/specials/SpecialSearch.php
includes/specials/SpecialSpecialpages.php
includes/specials/SpecialStatistics.php
includes/specials/SpecialTrackingCategories.php
includes/specials/SpecialUnblock.php
includes/specials/SpecialUndelete.php
includes/specials/SpecialUnlockdb.php
includes/specials/SpecialUnusedimages.php
includes/specials/SpecialUnwatchedpages.php
includes/specials/SpecialUpload.php
includes/specials/SpecialUploadStash.php
includes/specials/SpecialUserlogin.php
includes/specials/SpecialUserrights.php
includes/specials/SpecialVersion.php
includes/specials/SpecialWantedfiles.php
includes/specials/SpecialWantedpages.php
includes/specials/SpecialWatchlist.php
includes/specials/SpecialWhatlinkshere.php
includes/specials/SpecialWithoutinterwiki.php
includes/templates/NoLocalSettings.php
includes/templates/Usercreate.php
includes/templates/Userlogin.php
includes/title/MediaWikiPageLinkRenderer.php
includes/title/MediaWikiTitleCodec.php
includes/title/PageLinkRenderer.php
includes/title/TitleFormatter.php
includes/title/TitleParser.php
includes/title/TitleValue.php
includes/upload/UploadBase.php
includes/upload/UploadFromChunks.php
includes/upload/UploadStash.php
includes/utils/ArrayUtils.php
includes/utils/Cdb.php
includes/utils/CdbPHP.php
includes/utils/IP.php
includes/utils/MWCryptHKDF.php
includes/utils/MWCryptRand.php
includes/utils/MWFunction.php
includes/utils/StringUtils.php
includes/utils/UIDGenerator.php
includes/utils/ZipDirectoryReader.php
index.php
languages/Language.php
languages/LanguageConverter.php
languages/Names.php
languages/classes/LanguageIu.php
languages/classes/LanguageKk.php
languages/classes/LanguageKu.php
languages/classes/LanguageShi.php
languages/classes/LanguageSr.php
languages/classes/LanguageZh.php
languages/i18n/ace.json
languages/i18n/aeb.json
languages/i18n/af.json
languages/i18n/aln.json
languages/i18n/am.json
languages/i18n/an.json
languages/i18n/ang.json
languages/i18n/anp.json
languages/i18n/ar.json
languages/i18n/arc.json
languages/i18n/arn.json
languages/i18n/arq.json
languages/i18n/ary.json
languages/i18n/arz.json
languages/i18n/as.json
languages/i18n/ast.json
languages/i18n/avk.json
languages/i18n/az.json
languages/i18n/azb.json
languages/i18n/ba.json
languages/i18n/bar.json
languages/i18n/bbc-latn.json
languages/i18n/bcc.json
languages/i18n/bcl.json
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bg.json
languages/i18n/bho.json
languages/i18n/bjn.json
languages/i18n/bn.json
languages/i18n/bo.json
languages/i18n/bpy.json
languages/i18n/bqi.json
languages/i18n/br.json
languages/i18n/brh.json
languages/i18n/bs.json
languages/i18n/bto.json [new file with mode: 0644]
languages/i18n/ca.json
languages/i18n/cdo.json
languages/i18n/ce.json
languages/i18n/ceb.json
languages/i18n/ch.json
languages/i18n/ckb.json
languages/i18n/co.json
languages/i18n/cps.json
languages/i18n/crh-cyrl.json
languages/i18n/crh-latn.json
languages/i18n/cs.json
languages/i18n/csb.json
languages/i18n/cu.json
languages/i18n/cv.json
languages/i18n/cy.json
languages/i18n/da.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/dsb.json
languages/i18n/dtp.json
languages/i18n/dv.json
languages/i18n/egl.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/ext.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fit.json
languages/i18n/fo.json
languages/i18n/fr.json
languages/i18n/frp.json
languages/i18n/frr.json
languages/i18n/fur.json
languages/i18n/fy.json
languages/i18n/ga.json
languages/i18n/gag.json
languages/i18n/gan-hans.json
languages/i18n/gan-hant.json
languages/i18n/gd.json
languages/i18n/gl.json
languages/i18n/gom-latn.json
languages/i18n/grc.json
languages/i18n/gsw.json
languages/i18n/gu.json
languages/i18n/gv.json
languages/i18n/ha.json
languages/i18n/hak.json
languages/i18n/haw.json
languages/i18n/he.json
languages/i18n/hi.json
languages/i18n/hif-latn.json
languages/i18n/hil.json
languages/i18n/hr.json
languages/i18n/hrx.json
languages/i18n/hsb.json
languages/i18n/ht.json
languages/i18n/hu.json
languages/i18n/hy.json
languages/i18n/ia.json
languages/i18n/id.json
languages/i18n/ie.json
languages/i18n/ig.json
languages/i18n/ilo.json
languages/i18n/inh.json
languages/i18n/io.json
languages/i18n/is.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/jam.json
languages/i18n/jut.json
languages/i18n/jv.json
languages/i18n/ka.json
languages/i18n/kaa.json
languages/i18n/kab.json
languages/i18n/kbd-cyrl.json
languages/i18n/khw.json
languages/i18n/kiu.json
languages/i18n/kk-arab.json
languages/i18n/kk-cyrl.json
languages/i18n/kk-latn.json
languages/i18n/km.json
languages/i18n/kn.json
languages/i18n/ko.json
languages/i18n/koi.json
languages/i18n/krc.json
languages/i18n/kri.json
languages/i18n/ksh.json
languages/i18n/ku-latn.json
languages/i18n/kw.json
languages/i18n/ky.json
languages/i18n/la.json
languages/i18n/lad.json
languages/i18n/lb.json
languages/i18n/lez.json
languages/i18n/lfn.json
languages/i18n/lg.json
languages/i18n/li.json
languages/i18n/lij.json
languages/i18n/liv.json
languages/i18n/lmo.json
languages/i18n/ln.json
languages/i18n/lo.json
languages/i18n/loz.json
languages/i18n/lrc.json
languages/i18n/lt.json
languages/i18n/ltg.json
languages/i18n/lus.json
languages/i18n/lv.json
languages/i18n/lzh.json
languages/i18n/lzz.json
languages/i18n/mai.json
languages/i18n/map-bms.json
languages/i18n/mdf.json
languages/i18n/mg.json
languages/i18n/mhr.json
languages/i18n/min.json
languages/i18n/mk.json
languages/i18n/ml.json
languages/i18n/mn.json
languages/i18n/mr.json
languages/i18n/mrj.json
languages/i18n/ms.json
languages/i18n/mt.json
languages/i18n/mwl.json
languages/i18n/my.json
languages/i18n/myv.json
languages/i18n/mzn.json
languages/i18n/nah.json
languages/i18n/nan.json
languages/i18n/nap.json
languages/i18n/nb.json
languages/i18n/nds-nl.json
languages/i18n/nds.json
languages/i18n/ne.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/nso.json
languages/i18n/oc.json
languages/i18n/or.json
languages/i18n/os.json
languages/i18n/pa.json
languages/i18n/pam.json
languages/i18n/pcd.json
languages/i18n/pdc.json
languages/i18n/pfl.json
languages/i18n/pl.json
languages/i18n/pms.json
languages/i18n/pnb.json
languages/i18n/pnt.json
languages/i18n/prg.json
languages/i18n/ps.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/qu.json
languages/i18n/qug.json
languages/i18n/rgn.json
languages/i18n/rif.json
languages/i18n/rm.json
languages/i18n/ro.json
languages/i18n/roa-tara.json
languages/i18n/ru.json
languages/i18n/rue.json
languages/i18n/rup.json
languages/i18n/sa.json
languages/i18n/sah.json
languages/i18n/sat.json
languages/i18n/sc.json
languages/i18n/scn.json
languages/i18n/sco.json
languages/i18n/sd.json
languages/i18n/sdc.json
languages/i18n/se.json
languages/i18n/sei.json
languages/i18n/sgs.json
languages/i18n/sh.json
languages/i18n/shi.json
languages/i18n/si.json
languages/i18n/sk.json
languages/i18n/sl.json
languages/i18n/sli.json
languages/i18n/so.json
languages/i18n/sq.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/srn.json
languages/i18n/stq.json
languages/i18n/su.json
languages/i18n/sv.json
languages/i18n/sw.json
languages/i18n/szl.json
languages/i18n/ta.json
languages/i18n/tcy.json
languages/i18n/te.json
languages/i18n/tet.json
languages/i18n/tg-cyrl.json
languages/i18n/tg-latn.json
languages/i18n/th.json
languages/i18n/tk.json
languages/i18n/tl.json
languages/i18n/tly.json
languages/i18n/to.json
languages/i18n/tpi.json
languages/i18n/tr.json
languages/i18n/tru.json
languages/i18n/ts.json
languages/i18n/tt-cyrl.json
languages/i18n/tt-latn.json
languages/i18n/tyv.json
languages/i18n/tzm.json
languages/i18n/ug-arab.json
languages/i18n/uk.json
languages/i18n/ur.json
languages/i18n/uz.json
languages/i18n/vec.json
languages/i18n/vep.json
languages/i18n/vi.json
languages/i18n/vmf.json
languages/i18n/vo.json
languages/i18n/vot.json
languages/i18n/vro.json
languages/i18n/wa.json
languages/i18n/war.json
languages/i18n/wo.json
languages/i18n/wuu.json
languages/i18n/xal.json
languages/i18n/xmf.json
languages/i18n/yi.json
languages/i18n/yo.json
languages/i18n/yue.json
languages/i18n/zea.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesArq.php
languages/messages/MessagesBar.php
languages/messages/MessagesCkb.php
languages/messages/MessagesCrh_cyrl.php
languages/messages/MessagesCrh_latn.php
languages/messages/MessagesCs.php
languages/messages/MessagesDsb.php
languages/messages/MessagesEn.php
languages/messages/MessagesFa.php
languages/messages/MessagesFrp.php
languages/messages/MessagesHsb.php
languages/messages/MessagesKk_arab.php
languages/messages/MessagesKk_cyrl.php
languages/messages/MessagesKk_latn.php
languages/messages/MessagesKsh.php
languages/messages/MessagesLb.php
languages/messages/MessagesLzh.php
languages/messages/MessagesNds.php
languages/messages/MessagesNds_nl.php
languages/messages/MessagesOs.php
languages/messages/MessagesPdc.php
languages/messages/MessagesPfl.php
languages/messages/MessagesRu.php
languages/messages/MessagesSr_ec.php
languages/messages/MessagesSv.php
languages/messages/MessagesTt_cyrl.php
languages/messages/MessagesTt_latn.php
languages/messages/MessagesVmf.php
languages/utils/CLDRPluralRuleConverter.php
load.php
maintenance/Maintenance.php
maintenance/README
maintenance/archives/patch-fa_major_mime-chemical.sql [new file with mode: 0644]
maintenance/archives/patch-hitcounter.sql
maintenance/archives/patch-il_from_namespace.sql [new file with mode: 0644]
maintenance/archives/patch-img_major_mime-chemical.sql [new file with mode: 0644]
maintenance/archives/patch-mimesearch-indexes.sql
maintenance/archives/patch-oi_major_mime-chemical.sql [new file with mode: 0644]
maintenance/archives/patch-pl_from_namespace.sql [new file with mode: 0644]
maintenance/archives/patch-profiling.sql
maintenance/archives/patch-restructure.sql [deleted file]
maintenance/archives/patch-tl_from_namespace.sql [new file with mode: 0644]
maintenance/archives/upgradeLogging.php
maintenance/backupTextPass.inc
maintenance/benchmarks/benchmarkParse.php
maintenance/checkSyntax.php
maintenance/cleanupRemovedModules.php
maintenance/cleanupTitles.php
maintenance/commandLine.inc
maintenance/compareParserCache.php
maintenance/convertLinks.php
maintenance/deleteEqualMessages.php
maintenance/dev/includes/router.php
maintenance/dictionary/mediawiki.dic
maintenance/doMaintenance.php
maintenance/edit.php
maintenance/eraseArchivedFile.php
maintenance/findHooks.php
maintenance/findMissingFiles.php [new file with mode: 0644]
maintenance/fixDoubleRedirects.php
maintenance/generateJsonI18n.php
maintenance/getConfiguration.php
maintenance/importDump.php
maintenance/importTextFile.php [deleted file]
maintenance/install.php
maintenance/interwiki.list
maintenance/interwiki.sql
maintenance/jsduck/config.json
maintenance/language/generateCollationData.php
maintenance/language/languages.inc
maintenance/mctest.php
maintenance/mssql/archives/patch-fa_major_mime-chemical.sql [new file with mode: 0644]
maintenance/mssql/archives/patch-img_major_mime-chemical.sql [new file with mode: 0644]
maintenance/mssql/archives/patch-oi_major_mime-chemical.sql [new file with mode: 0644]
maintenance/mssql/tables.sql
maintenance/mssql/update-keys.sql [new file with mode: 0644]
maintenance/namespaceDupes.php
maintenance/nextJobDB.php [deleted file]
maintenance/parse.php
maintenance/populateBacklinkNamespace.php [new file with mode: 0644]
maintenance/populateBloomCache.php [new file with mode: 0644]
maintenance/postgres/tables.sql
maintenance/preprocessorFuzzTest.php
maintenance/purgeChangedPages.php
maintenance/purgeOldText.inc
maintenance/refreshImageMetadata.php
maintenance/resources/update-oojs-ui.sh
maintenance/resources/update-oojs.sh
maintenance/runJobs.php
maintenance/showJobs.php
maintenance/sql.php
maintenance/sqlite.inc
maintenance/storage/compressOld.php
maintenance/storage/recompressTracked.php
maintenance/storage/resolveStubs.php
maintenance/syncFileBackend.php
maintenance/tables.sql
maintenance/undelete.php
maintenance/update-keys.sql [new file with mode: 0644]
maintenance/update.php
maintenance/updateCollation.php
maintenance/userOptions.inc
maintenance/wrapOldPasswords.php [new file with mode: 0644]
mw-config/config-cc.css [new file with mode: 0644]
mw-config/config.css [new file with mode: 0644]
mw-config/config.js [new file with mode: 0644]
mw-config/images/ajax-loader.gif [new file with mode: 0644]
mw-config/images/bullet.gif [new file with mode: 0644]
mw-config/images/critical-32.png [new file with mode: 0644]
mw-config/images/download-32.png [new file with mode: 0644]
mw-config/images/info-32.png [new file with mode: 0644]
mw-config/images/installer-logo.png [new file with mode: 0644]
mw-config/images/tick-32.png [new file with mode: 0644]
mw-config/images/warning-32.png [new file with mode: 0644]
mw-config/index.php
profileinfo.php
resources/Resources.php
resources/lib/es5-shim/es5-shim.js
resources/lib/jquery/jquery.cookie.js
resources/lib/moment/lang/ar-ma.js [deleted file]
resources/lib/moment/lang/ar-sa.js [deleted file]
resources/lib/moment/lang/ar.js [deleted file]
resources/lib/moment/lang/az.js [deleted file]
resources/lib/moment/lang/bg.js [deleted file]
resources/lib/moment/lang/bn.js [deleted file]
resources/lib/moment/lang/br.js [deleted file]
resources/lib/moment/lang/bs.js [deleted file]
resources/lib/moment/lang/ca.js [deleted file]
resources/lib/moment/lang/cs.js [deleted file]
resources/lib/moment/lang/cv.js [deleted file]
resources/lib/moment/lang/cy.js [deleted file]
resources/lib/moment/lang/da.js [deleted file]
resources/lib/moment/lang/de-at.js [deleted file]
resources/lib/moment/lang/de.js [deleted file]
resources/lib/moment/lang/el.js [deleted file]
resources/lib/moment/lang/en-au.js [deleted file]
resources/lib/moment/lang/en-ca.js [deleted file]
resources/lib/moment/lang/en-gb.js [deleted file]
resources/lib/moment/lang/eo.js [deleted file]
resources/lib/moment/lang/es.js [deleted file]
resources/lib/moment/lang/et.js [deleted file]
resources/lib/moment/lang/eu.js [deleted file]
resources/lib/moment/lang/fa.js [deleted file]
resources/lib/moment/lang/fi.js [deleted file]
resources/lib/moment/lang/fo.js [deleted file]
resources/lib/moment/lang/fr-ca.js [deleted file]
resources/lib/moment/lang/fr.js [deleted file]
resources/lib/moment/lang/gl.js [deleted file]
resources/lib/moment/lang/he.js [deleted file]
resources/lib/moment/lang/hi.js [deleted file]
resources/lib/moment/lang/hr.js [deleted file]
resources/lib/moment/lang/hu.js [deleted file]
resources/lib/moment/lang/hy-am.js [deleted file]
resources/lib/moment/lang/id.js [deleted file]
resources/lib/moment/lang/is.js [deleted file]
resources/lib/moment/lang/it.js [deleted file]
resources/lib/moment/lang/ja.js [deleted file]
resources/lib/moment/lang/ka.js [deleted file]
resources/lib/moment/lang/km.js [deleted file]
resources/lib/moment/lang/ko.js [deleted file]
resources/lib/moment/lang/lb.js [deleted file]
resources/lib/moment/lang/lt.js [deleted file]
resources/lib/moment/lang/lv.js [deleted file]
resources/lib/moment/lang/mk.js [deleted file]
resources/lib/moment/lang/ml.js [deleted file]
resources/lib/moment/lang/mr.js [deleted file]
resources/lib/moment/lang/ms-my.js [deleted file]
resources/lib/moment/lang/nb.js [deleted file]
resources/lib/moment/lang/ne.js [deleted file]
resources/lib/moment/lang/nl.js [deleted file]
resources/lib/moment/lang/nn.js [deleted file]
resources/lib/moment/lang/pl.js [deleted file]
resources/lib/moment/lang/pt-br.js [deleted file]
resources/lib/moment/lang/pt.js [deleted file]
resources/lib/moment/lang/ro.js [deleted file]
resources/lib/moment/lang/ru.js [deleted file]
resources/lib/moment/lang/sk.js [deleted file]
resources/lib/moment/lang/sl.js [deleted file]
resources/lib/moment/lang/sq.js [deleted file]
resources/lib/moment/lang/sr-cyrl.js [deleted file]
resources/lib/moment/lang/sr.js [deleted file]
resources/lib/moment/lang/sv.js [deleted file]
resources/lib/moment/lang/ta.js [deleted file]
resources/lib/moment/lang/th.js [deleted file]
resources/lib/moment/lang/tl-ph.js [deleted file]
resources/lib/moment/lang/tr.js [deleted file]
resources/lib/moment/lang/tzm-latn.js [deleted file]
resources/lib/moment/lang/tzm.js [deleted file]
resources/lib/moment/lang/uk.js [deleted file]
resources/lib/moment/lang/uz.js [deleted file]
resources/lib/moment/lang/vi.js [deleted file]
resources/lib/moment/lang/zh-cn.js [deleted file]
resources/lib/moment/lang/zh-tw.js [deleted file]
resources/lib/moment/locale/af.js [new file with mode: 0644]
resources/lib/moment/locale/ar-ma.js [new file with mode: 0644]
resources/lib/moment/locale/ar-sa.js [new file with mode: 0644]
resources/lib/moment/locale/ar.js [new file with mode: 0644]
resources/lib/moment/locale/az.js [new file with mode: 0644]
resources/lib/moment/locale/be.js [new file with mode: 0644]
resources/lib/moment/locale/bg.js [new file with mode: 0644]
resources/lib/moment/locale/bn.js [new file with mode: 0644]
resources/lib/moment/locale/bo.js [new file with mode: 0644]
resources/lib/moment/locale/br.js [new file with mode: 0644]
resources/lib/moment/locale/bs.js [new file with mode: 0644]
resources/lib/moment/locale/ca.js [new file with mode: 0644]
resources/lib/moment/locale/cs.js [new file with mode: 0644]
resources/lib/moment/locale/cv.js [new file with mode: 0644]
resources/lib/moment/locale/cy.js [new file with mode: 0644]
resources/lib/moment/locale/da.js [new file with mode: 0644]
resources/lib/moment/locale/de-at.js [new file with mode: 0644]
resources/lib/moment/locale/de.js [new file with mode: 0644]
resources/lib/moment/locale/el.js [new file with mode: 0644]
resources/lib/moment/locale/en-au.js [new file with mode: 0644]
resources/lib/moment/locale/en-ca.js [new file with mode: 0644]
resources/lib/moment/locale/en-gb.js [new file with mode: 0644]
resources/lib/moment/locale/eo.js [new file with mode: 0644]
resources/lib/moment/locale/es.js [new file with mode: 0644]
resources/lib/moment/locale/et.js [new file with mode: 0644]
resources/lib/moment/locale/eu.js [new file with mode: 0644]
resources/lib/moment/locale/fa.js [new file with mode: 0644]
resources/lib/moment/locale/fi.js [new file with mode: 0644]
resources/lib/moment/locale/fo.js [new file with mode: 0644]
resources/lib/moment/locale/fr-ca.js [new file with mode: 0644]
resources/lib/moment/locale/fr.js [new file with mode: 0644]
resources/lib/moment/locale/gl.js [new file with mode: 0644]
resources/lib/moment/locale/he.js [new file with mode: 0644]
resources/lib/moment/locale/hi.js [new file with mode: 0644]
resources/lib/moment/locale/hr.js [new file with mode: 0644]
resources/lib/moment/locale/hu.js [new file with mode: 0644]
resources/lib/moment/locale/hy-am.js [new file with mode: 0644]
resources/lib/moment/locale/id.js [new file with mode: 0644]
resources/lib/moment/locale/is.js [new file with mode: 0644]
resources/lib/moment/locale/it.js [new file with mode: 0644]
resources/lib/moment/locale/ja.js [new file with mode: 0644]
resources/lib/moment/locale/ka.js [new file with mode: 0644]
resources/lib/moment/locale/km.js [new file with mode: 0644]
resources/lib/moment/locale/ko.js [new file with mode: 0644]
resources/lib/moment/locale/lb.js [new file with mode: 0644]
resources/lib/moment/locale/lt.js [new file with mode: 0644]
resources/lib/moment/locale/lv.js [new file with mode: 0644]
resources/lib/moment/locale/mk.js [new file with mode: 0644]
resources/lib/moment/locale/ml.js [new file with mode: 0644]
resources/lib/moment/locale/mr.js [new file with mode: 0644]
resources/lib/moment/locale/ms-my.js [new file with mode: 0644]
resources/lib/moment/locale/my.js [new file with mode: 0644]
resources/lib/moment/locale/nb.js [new file with mode: 0644]
resources/lib/moment/locale/ne.js [new file with mode: 0644]
resources/lib/moment/locale/nl.js [new file with mode: 0644]
resources/lib/moment/locale/nn.js [new file with mode: 0644]
resources/lib/moment/locale/pl.js [new file with mode: 0644]
resources/lib/moment/locale/pt-br.js [new file with mode: 0644]
resources/lib/moment/locale/pt.js [new file with mode: 0644]
resources/lib/moment/locale/ro.js [new file with mode: 0644]
resources/lib/moment/locale/ru.js [new file with mode: 0644]
resources/lib/moment/locale/sk.js [new file with mode: 0644]
resources/lib/moment/locale/sl.js [new file with mode: 0644]
resources/lib/moment/locale/sq.js [new file with mode: 0644]
resources/lib/moment/locale/sr-cyrl.js [new file with mode: 0644]
resources/lib/moment/locale/sr.js [new file with mode: 0644]
resources/lib/moment/locale/sv.js [new file with mode: 0644]
resources/lib/moment/locale/ta.js [new file with mode: 0644]
resources/lib/moment/locale/th.js [new file with mode: 0644]
resources/lib/moment/locale/tl-ph.js [new file with mode: 0644]
resources/lib/moment/locale/tr.js [new file with mode: 0644]
resources/lib/moment/locale/tzm-latn.js [new file with mode: 0644]
resources/lib/moment/locale/tzm.js [new file with mode: 0644]
resources/lib/moment/locale/uk.js [new file with mode: 0644]
resources/lib/moment/locale/uz.js [new file with mode: 0644]
resources/lib/moment/locale/vi.js [new file with mode: 0644]
resources/lib/moment/locale/zh-cn.js [new file with mode: 0644]
resources/lib/moment/locale/zh-tw.js [new file with mode: 0644]
resources/lib/moment/moment.js
resources/lib/oojs-ui/i18n/ar.json
resources/lib/oojs-ui/i18n/arq.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ast.json
resources/lib/oojs-ui/i18n/br.json
resources/lib/oojs-ui/i18n/ca.json
resources/lib/oojs-ui/i18n/cs.json
resources/lib/oojs-ui/i18n/de.json
resources/lib/oojs-ui/i18n/el.json
resources/lib/oojs-ui/i18n/en.json
resources/lib/oojs-ui/i18n/es.json
resources/lib/oojs-ui/i18n/et.json
resources/lib/oojs-ui/i18n/fa.json
resources/lib/oojs-ui/i18n/fi.json
resources/lib/oojs-ui/i18n/fr.json
resources/lib/oojs-ui/i18n/gd.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/gl.json
resources/lib/oojs-ui/i18n/gu.json
resources/lib/oojs-ui/i18n/he.json
resources/lib/oojs-ui/i18n/hr.json
resources/lib/oojs-ui/i18n/hu.json
resources/lib/oojs-ui/i18n/ia.json
resources/lib/oojs-ui/i18n/ilo.json
resources/lib/oojs-ui/i18n/it.json
resources/lib/oojs-ui/i18n/ja.json
resources/lib/oojs-ui/i18n/kn.json
resources/lib/oojs-ui/i18n/ko.json
resources/lib/oojs-ui/i18n/lb.json
resources/lib/oojs-ui/i18n/lv.json
resources/lib/oojs-ui/i18n/mk.json
resources/lib/oojs-ui/i18n/ms.json
resources/lib/oojs-ui/i18n/nb.json
resources/lib/oojs-ui/i18n/nl.json
resources/lib/oojs-ui/i18n/om.json
resources/lib/oojs-ui/i18n/pl.json
resources/lib/oojs-ui/i18n/pt.json
resources/lib/oojs-ui/i18n/qqq.json
resources/lib/oojs-ui/i18n/ro.json
resources/lib/oojs-ui/i18n/ru.json
resources/lib/oojs-ui/i18n/sl.json
resources/lib/oojs-ui/i18n/sq.json
resources/lib/oojs-ui/i18n/sr-ec.json
resources/lib/oojs-ui/i18n/sv.json
resources/lib/oojs-ui/i18n/sw.json
resources/lib/oojs-ui/i18n/tr.json
resources/lib/oojs-ui/i18n/uk.json
resources/lib/oojs-ui/i18n/vi.json
resources/lib/oojs-ui/i18n/yi.json
resources/lib/oojs-ui/i18n/yue.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/zh-hans.json
resources/lib/oojs-ui/i18n/zh-hant.json
resources/lib/oojs-ui/images/anchor.png [new file with mode: 0644]
resources/lib/oojs-ui/images/anchor.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/accept.png
resources/lib/oojs-ui/images/icons/accept.svg
resources/lib/oojs-ui/images/icons/add-item.png
resources/lib/oojs-ui/images/icons/add-item.svg
resources/lib/oojs-ui/images/icons/advanced.png
resources/lib/oojs-ui/images/icons/advanced.svg
resources/lib/oojs-ui/images/icons/alert.png
resources/lib/oojs-ui/images/icons/alert.svg
resources/lib/oojs-ui/images/icons/arched-arrow-ltr.png
resources/lib/oojs-ui/images/icons/arched-arrow-ltr.svg
resources/lib/oojs-ui/images/icons/arched-arrow-rtl.png
resources/lib/oojs-ui/images/icons/arched-arrow-rtl.svg
resources/lib/oojs-ui/images/icons/check.png
resources/lib/oojs-ui/images/icons/clear.png
resources/lib/oojs-ui/images/icons/clear.svg
resources/lib/oojs-ui/images/icons/close.png
resources/lib/oojs-ui/images/icons/close.svg
resources/lib/oojs-ui/images/icons/code.png
resources/lib/oojs-ui/images/icons/collapse.png
resources/lib/oojs-ui/images/icons/collapse.svg
resources/lib/oojs-ui/images/icons/comment.png
resources/lib/oojs-ui/images/icons/comment.svg
resources/lib/oojs-ui/images/icons/expand.png
resources/lib/oojs-ui/images/icons/expand.svg
resources/lib/oojs-ui/images/icons/help.png
resources/lib/oojs-ui/images/icons/help.svg
resources/lib/oojs-ui/images/icons/history.png
resources/lib/oojs-ui/images/icons/history.svg
resources/lib/oojs-ui/images/icons/info.png
resources/lib/oojs-ui/images/icons/info.svg
resources/lib/oojs-ui/images/icons/link.png
resources/lib/oojs-ui/images/icons/link.svg
resources/lib/oojs-ui/images/icons/menu.png
resources/lib/oojs-ui/images/icons/menu.svg
resources/lib/oojs-ui/images/icons/move-ltr.png
resources/lib/oojs-ui/images/icons/move-ltr.svg
resources/lib/oojs-ui/images/icons/move-rtl.png
resources/lib/oojs-ui/images/icons/move-rtl.svg
resources/lib/oojs-ui/images/icons/picture.png
resources/lib/oojs-ui/images/icons/picture.svg
resources/lib/oojs-ui/images/icons/remove-item.png
resources/lib/oojs-ui/images/icons/remove-item.svg
resources/lib/oojs-ui/images/icons/remove.png
resources/lib/oojs-ui/images/icons/remove.svg
resources/lib/oojs-ui/images/icons/search.png
resources/lib/oojs-ui/images/icons/search.svg
resources/lib/oojs-ui/images/icons/settings.png
resources/lib/oojs-ui/images/icons/settings.svg
resources/lib/oojs-ui/images/icons/tag.png
resources/lib/oojs-ui/images/icons/tag.svg
resources/lib/oojs-ui/images/icons/window.png
resources/lib/oojs-ui/images/icons/window.svg
resources/lib/oojs-ui/images/indicators/alert.png
resources/lib/oojs-ui/images/indicators/alert.svg
resources/lib/oojs-ui/images/indicators/arrow-down.png
resources/lib/oojs-ui/images/indicators/arrow-down.svg
resources/lib/oojs-ui/images/indicators/arrow-ltr.png
resources/lib/oojs-ui/images/indicators/arrow-rtl.png
resources/lib/oojs-ui/images/indicators/arrow-up.png
resources/lib/oojs-ui/images/indicators/arrow-up.svg
resources/lib/oojs-ui/images/indicators/required.png
resources/lib/oojs-ui/images/tail.svg [deleted file]
resources/lib/oojs-ui/images/textures/transparency.png
resources/lib/oojs-ui/images/textures/transparency.svg [new file with mode: 0644]
resources/lib/oojs-ui/oojs-ui-agora.css [deleted file]
resources/lib/oojs-ui/oojs-ui-apex.css
resources/lib/oojs-ui/oojs-ui-apex.rtl.css [new file with mode: 0644]
resources/lib/oojs-ui/oojs-ui-minerva.css [new file with mode: 0644]
resources/lib/oojs-ui/oojs-ui-minerva.rtl.css [new file with mode: 0644]
resources/lib/oojs-ui/oojs-ui.js
resources/lib/oojs-ui/oojs-ui.rtl.css [new file with mode: 0644]
resources/lib/oojs-ui/oojs-ui.svg.css
resources/lib/oojs-ui/oojs-ui.svg.rtl.css [new file with mode: 0644]
resources/lib/oojs-ui/themes/agora/images/icons/check.svg [deleted file]
resources/lib/oojs-ui/themes/minerva/images/icons/check.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/minerva/images/icons/check.svg [new file with mode: 0644]
resources/lib/oojs/oojs.jquery.js [new file with mode: 0644]
resources/lib/oojs/oojs.js [deleted file]
resources/lib/sinonjs/sinon-1.10.3.js [new file with mode: 0644]
resources/lib/sinonjs/sinon-1.9.0.js [deleted file]
resources/lib/sinonjs/sinon-ie-1.10.3.js [new file with mode: 0644]
resources/lib/sinonjs/sinon-ie-1.9.0.js [deleted file]
resources/src/es5-skip.js
resources/src/jquery.json-deprecate.js
resources/src/jquery.ui-themes/vector/images/close.png [deleted file]
resources/src/jquery.ui-themes/vector/images/titlebar-fade.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-anim_basic_16x16.gif [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-bg_flat_70_000000_40x100.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-icons_2694e8_256x240.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-icons_2e83ff_256x240.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-icons_3d80b3_256x240.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-icons_666666_256x240.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-icons_72a7cf_256x240.png [deleted file]
resources/src/jquery.ui-themes/vector/images/ui-icons_ffffff_256x240.png [deleted file]
resources/src/jquery.ui-themes/vector/jquery.ui.accordion.css [deleted file]
resources/src/jquery.ui-themes/vector/jquery.ui.autocomplete.css [deleted file]
resources/src/jquery.ui-themes/vector/jquery.ui.button.css [deleted file]
resources/src/jquery.ui-themes/vector/jquery.ui.core.css [deleted file]
resources/src/jquery.ui-themes/vector/jquery.ui.datepicker.css [deleted file]
resources/src/jquery.ui-themes/vector/jquery.ui.dialog.css [deleted file]
resources/src/jquery.ui-themes/vector/jquery.ui.progressbar.css [deleted file]
resources/src/jquery.ui-themes/vector/jquery.ui.resizable.css [deleted file]
resources/src/jquery.ui-themes/vector/jquery.ui.selectable.css [deleted file]
resources/src/jquery.ui-themes/vector/jquery.ui.slider.css [deleted file]
resources/src/jquery.ui-themes/vector/jquery.ui.tabs.css [deleted file]
resources/src/jquery.ui-themes/vector/jquery.ui.theme.css [deleted file]
resources/src/jquery/jquery.accessKeyLabel.js
resources/src/jquery/jquery.arrowSteps.js
resources/src/jquery/jquery.autoEllipsis.js
resources/src/jquery/jquery.byteLimit.js
resources/src/jquery/jquery.colorUtil.js
resources/src/jquery/jquery.confirmable.css [new file with mode: 0644]
resources/src/jquery/jquery.confirmable.js [new file with mode: 0644]
resources/src/jquery/jquery.confirmable.mediawiki.js [new file with mode: 0644]
resources/src/jquery/jquery.farbtastic.js
resources/src/jquery/jquery.hidpi.js
resources/src/jquery/jquery.makeCollapsible.js
resources/src/jquery/jquery.mwExtension.js
resources/src/jquery/jquery.suggestions.css
resources/src/jquery/jquery.suggestions.js
resources/src/jquery/jquery.tablesorter.js
resources/src/jquery/jquery.textSelection.js
resources/src/mediawiki.action/images/nextredirect-ltr.png [new file with mode: 0644]
resources/src/mediawiki.action/images/nextredirect-rtl.png [new file with mode: 0644]
resources/src/mediawiki.action/images/redirect-ltr.png [new file with mode: 0644]
resources/src/mediawiki.action/images/redirect-rtl.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.css [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js
resources/src/mediawiki.action/mediawiki.action.edit.js
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_bold.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_headline.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_italic.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_link.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_nowiki.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/be-tarask/button_bold.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/be-tarask/button_italic.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/be-tarask/button_link.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/de/button_bold.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/de/button_italic.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_bold.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_extlink.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_headline.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_hr.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_image.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_italic.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_link.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_media.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_nowiki.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_sig.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_bold.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_headline.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_italic.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_link.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_nowiki.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ksh/LICENSE [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ksh/button_italic.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/LICENSE [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/button_bold.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/button_italic.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/button_link.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.toolbar/mediawiki.action.edit.toolbar.less [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.view.metadata.css [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.view.metadata.js
resources/src/mediawiki.action/mediawiki.action.view.redirect.js [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.view.redirectPage.css [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.view.redirectToFragment.js [deleted file]
resources/src/mediawiki.api/mediawiki.api.edit.js
resources/src/mediawiki.api/mediawiki.api.js
resources/src/mediawiki.hidpi-skip.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/fi.js
resources/src/mediawiki.language/languages/he.js
resources/src/mediawiki.language/languages/hy.js
resources/src/mediawiki.language/languages/la.js
resources/src/mediawiki.language/languages/os.js
resources/src/mediawiki.language/languages/ru.js
resources/src/mediawiki.language/languages/uk.js
resources/src/mediawiki.language/mediawiki.language.fallback.js [new file with mode: 0644]
resources/src/mediawiki.language/mediawiki.language.init.js
resources/src/mediawiki.language/mediawiki.language.js
resources/src/mediawiki.language/mediawiki.language.numbers.js
resources/src/mediawiki.legacy/ajax.js [new file with mode: 0644]
resources/src/mediawiki.legacy/commonPrint.css [new file with mode: 0644]
resources/src/mediawiki.legacy/images/ajax-loader.gif [new file with mode: 0644]
resources/src/mediawiki.legacy/images/checker.png [new file with mode: 0644]
resources/src/mediawiki.legacy/images/feed-icon.png [new file with mode: 0644]
resources/src/mediawiki.legacy/images/feed-icon.svg [new file with mode: 0644]
resources/src/mediawiki.legacy/images/help-question-hover.gif [new file with mode: 0644]
resources/src/mediawiki.legacy/images/help-question.gif [new file with mode: 0644]
resources/src/mediawiki.legacy/images/question.png [new file with mode: 0644]
resources/src/mediawiki.legacy/images/question.svg [new file with mode: 0644]
resources/src/mediawiki.legacy/images/spinner.gif [new file with mode: 0644]
resources/src/mediawiki.legacy/oldshared.css [new file with mode: 0644]
resources/src/mediawiki.legacy/protect.js [new file with mode: 0644]
resources/src/mediawiki.legacy/shared.css [new file with mode: 0644]
resources/src/mediawiki.legacy/wikibits.js [new file with mode: 0644]
resources/src/mediawiki.less/mediawiki.mixins.less
resources/src/mediawiki.less/mediawiki.ui/mixins.less [new file with mode: 0644]
resources/src/mediawiki.less/mediawiki.ui/variables.less [new file with mode: 0644]
resources/src/mediawiki.page/mediawiki.page.image.pagination.js
resources/src/mediawiki.page/mediawiki.page.ready.js
resources/src/mediawiki.page/mediawiki.page.watch.ajax.js
resources/src/mediawiki.skinning/content.css [new file with mode: 0644]
resources/src/mediawiki.skinning/content.externallinks.css [new file with mode: 0755]
resources/src/mediawiki.skinning/content.parsoid.less
resources/src/mediawiki.skinning/elements.css [new file with mode: 0644]
resources/src/mediawiki.skinning/images/audio-ltr.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/audio-ltr.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/images/audio-rtl.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/audio-rtl.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/images/chat-ltr.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/chat-ltr.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/images/chat-rtl.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/chat-rtl.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/images/document-ltr.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/document-ltr.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/images/document-rtl.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/document-rtl.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/images/external link icons.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/images/external-ltr.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/external-ltr.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/images/external-rtl.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/external-rtl.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/images/ftp-ltr.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/ftp-ltr.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/images/ftp-rtl.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/ftp-rtl.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/images/magnify-clip-ltr.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/magnify-clip-rtl.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/mail.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/mail.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/images/video.png [new file with mode: 0644]
resources/src/mediawiki.skinning/images/video.svg [new file with mode: 0644]
resources/src/mediawiki.skinning/interface.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.css
resources/src/mediawiki.special/mediawiki.special.import.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.preferences.css
resources/src/mediawiki.special/mediawiki.special.search.js
resources/src/mediawiki.special/mediawiki.special.upload.js
resources/src/mediawiki.special/mediawiki.special.userlogin.common.css
resources/src/mediawiki.special/mediawiki.special.userlogin.common.js
resources/src/mediawiki.special/mediawiki.special.userlogin.login.css
resources/src/mediawiki.ui/components/anchors.less [new file with mode: 0644]
resources/src/mediawiki.ui/components/buttons.less [new file with mode: 0644]
resources/src/mediawiki.ui/components/checkbox.less [new file with mode: 0644]
resources/src/mediawiki.ui/components/default/buttons.less [deleted file]
resources/src/mediawiki.ui/components/default/forms.less [deleted file]
resources/src/mediawiki.ui/components/forms.less [new file with mode: 0644]
resources/src/mediawiki.ui/components/images/checked.png [new file with mode: 0644]
resources/src/mediawiki.ui/components/images/checked.svg [new file with mode: 0644]
resources/src/mediawiki.ui/components/inputs.less [new file with mode: 0644]
resources/src/mediawiki.ui/components/utilities.less
resources/src/mediawiki.ui/components/vector/buttons.less [deleted file]
resources/src/mediawiki.ui/components/vector/containers.less [deleted file]
resources/src/mediawiki.ui/components/vector/forms.less [deleted file]
resources/src/mediawiki.ui/default.less
resources/src/mediawiki.ui/mixins/effects.less [deleted file]
resources/src/mediawiki.ui/mixins/forms.less [deleted file]
resources/src/mediawiki.ui/mixins/type.less [deleted file]
resources/src/mediawiki.ui/mixins/utilities.less [deleted file]
resources/src/mediawiki.ui/settings/colors.less [deleted file]
resources/src/mediawiki.ui/settings/typography.less [deleted file]
resources/src/mediawiki.ui/vector.less [deleted file]
resources/src/mediawiki/images/arrow-sort-ascending.png [new file with mode: 0644]
resources/src/mediawiki/images/arrow-sort-ascending.svg [new file with mode: 0644]
resources/src/mediawiki/images/arrow-sort-descending.png [new file with mode: 0644]
resources/src/mediawiki/images/arrow-sort-descending.svg [new file with mode: 0644]
resources/src/mediawiki/images/pager-arrow-disabled-fastforward-ltr.png [new file with mode: 0644]
resources/src/mediawiki/images/pager-arrow-disabled-fastforward-rtl.png [new file with mode: 0644]
resources/src/mediawiki/images/pager-arrow-disabled-forward-ltr.png [new file with mode: 0644]
resources/src/mediawiki/images/pager-arrow-disabled-forward-rtl.png [new file with mode: 0644]
resources/src/mediawiki/images/pager-arrow-fastforward-ltr.png [new file with mode: 0644]
resources/src/mediawiki/images/pager-arrow-fastforward-rtl.png [new file with mode: 0644]
resources/src/mediawiki/images/pager-arrow-forward-ltr.png [new file with mode: 0644]
resources/src/mediawiki/images/pager-arrow-forward-rtl.png [new file with mode: 0644]
resources/src/mediawiki/mediawiki.Title.js
resources/src/mediawiki/mediawiki.content.json.css [new file with mode: 0644]
resources/src/mediawiki/mediawiki.debug.js
resources/src/mediawiki/mediawiki.debug.profile.js
resources/src/mediawiki/mediawiki.feedback.js
resources/src/mediawiki/mediawiki.htmlform.js
resources/src/mediawiki/mediawiki.inspect.js
resources/src/mediawiki/mediawiki.jqueryMsg.js
resources/src/mediawiki/mediawiki.js
resources/src/mediawiki/mediawiki.notification.css
resources/src/mediawiki/mediawiki.notification.js
resources/src/mediawiki/mediawiki.notify.js
resources/src/mediawiki/mediawiki.pager.tablePager.less [new file with mode: 0644]
resources/src/mediawiki/mediawiki.toc.js
resources/src/mediawiki/mediawiki.user.js
resources/src/polyfill-object-create.js [new file with mode: 0644]
resources/src/startup.js
skins/.gitignore
skins/MonoBook/COPYING [deleted file]
skins/MonoBook/IE60Fixes.css [deleted file]
skins/MonoBook/IE70Fixes.css [deleted file]
skins/MonoBook/MonoBook.php [deleted file]
skins/MonoBook/MonoBookTemplate.php [deleted file]
skins/MonoBook/SkinMonoBook.php [deleted file]
skins/MonoBook/audio.png [deleted file]
skins/MonoBook/bullet.gif [deleted file]
skins/MonoBook/discussionitem_icon.gif [deleted file]
skins/MonoBook/document.png [deleted file]
skins/MonoBook/external-ltr.png [deleted file]
skins/MonoBook/external-rtl.png [deleted file]
skins/MonoBook/file_icon.gif [deleted file]
skins/MonoBook/headbg.jpg [deleted file]
skins/MonoBook/i18n/aln.json [deleted file]
skins/MonoBook/i18n/an.json [deleted file]
skins/MonoBook/i18n/ar.json [deleted file]
skins/MonoBook/i18n/arz.json [deleted file]
skins/MonoBook/i18n/ast.json [deleted file]
skins/MonoBook/i18n/az.json [deleted file]
skins/MonoBook/i18n/bcc.json [deleted file]
skins/MonoBook/i18n/bcl.json [deleted file]
skins/MonoBook/i18n/be-tarask.json [deleted file]
skins/MonoBook/i18n/be.json [deleted file]
skins/MonoBook/i18n/bg.json [deleted file]
skins/MonoBook/i18n/bn.json [deleted file]
skins/MonoBook/i18n/br.json [deleted file]
skins/MonoBook/i18n/bs.json [deleted file]
skins/MonoBook/i18n/ca.json [deleted file]
skins/MonoBook/i18n/ce.json [deleted file]
skins/MonoBook/i18n/ckb.json [deleted file]
skins/MonoBook/i18n/crh-cyrl.json [deleted file]
skins/MonoBook/i18n/crh-latn.json [deleted file]
skins/MonoBook/i18n/cs.json [deleted file]
skins/MonoBook/i18n/da.json [deleted file]
skins/MonoBook/i18n/de.json [deleted file]
skins/MonoBook/i18n/diq.json [deleted file]
skins/MonoBook/i18n/dsb.json [deleted file]
skins/MonoBook/i18n/el.json [deleted file]
skins/MonoBook/i18n/en.json [deleted file]
skins/MonoBook/i18n/eo.json [deleted file]
skins/MonoBook/i18n/es.json [deleted file]
skins/MonoBook/i18n/et.json [deleted file]
skins/MonoBook/i18n/eu.json [deleted file]
skins/MonoBook/i18n/ext.json [deleted file]
skins/MonoBook/i18n/fa.json [deleted file]
skins/MonoBook/i18n/fi.json [deleted file]
skins/MonoBook/i18n/fr.json [deleted file]
skins/MonoBook/i18n/frp.json [deleted file]
skins/MonoBook/i18n/fur.json [deleted file]
skins/MonoBook/i18n/ga.json [deleted file]
skins/MonoBook/i18n/gan-hans.json [deleted file]
skins/MonoBook/i18n/gan-hant.json [deleted file]
skins/MonoBook/i18n/gd.json [deleted file]
skins/MonoBook/i18n/gl.json [deleted file]
skins/MonoBook/i18n/hak.json [deleted file]
skins/MonoBook/i18n/he.json [deleted file]
skins/MonoBook/i18n/hi.json [deleted file]
skins/MonoBook/i18n/hr.json [deleted file]
skins/MonoBook/i18n/hsb.json [deleted file]
skins/MonoBook/i18n/hu.json [deleted file]
skins/MonoBook/i18n/hy.json [deleted file]
skins/MonoBook/i18n/ia.json [deleted file]
skins/MonoBook/i18n/id.json [deleted file]
skins/MonoBook/i18n/is.json [deleted file]
skins/MonoBook/i18n/it.json [deleted file]
skins/MonoBook/i18n/ja.json [deleted file]
skins/MonoBook/i18n/ka.json [deleted file]
skins/MonoBook/i18n/kk-arab.json [deleted file]
skins/MonoBook/i18n/kk-cyrl.json [deleted file]
skins/MonoBook/i18n/kk-latn.json [deleted file]
skins/MonoBook/i18n/km.json [deleted file]
skins/MonoBook/i18n/ko.json [deleted file]
skins/MonoBook/i18n/krc.json [deleted file]
skins/MonoBook/i18n/ksh.json [deleted file]
skins/MonoBook/i18n/ku-latn.json [deleted file]
skins/MonoBook/i18n/lb.json [deleted file]
skins/MonoBook/i18n/lt.json [deleted file]
skins/MonoBook/i18n/lzh.json [deleted file]
skins/MonoBook/i18n/mg.json [deleted file]
skins/MonoBook/i18n/min.json [deleted file]
skins/MonoBook/i18n/mk.json [deleted file]
skins/MonoBook/i18n/ml.json [deleted file]
skins/MonoBook/i18n/mr.json [deleted file]
skins/MonoBook/i18n/ms.json [deleted file]
skins/MonoBook/i18n/mt.json [deleted file]
skins/MonoBook/i18n/mwl.json [deleted file]
skins/MonoBook/i18n/nb.json [deleted file]
skins/MonoBook/i18n/nds-nl.json [deleted file]
skins/MonoBook/i18n/nds.json [deleted file]
skins/MonoBook/i18n/ne.json [deleted file]
skins/MonoBook/i18n/new.json [deleted file]
skins/MonoBook/i18n/nl.json [deleted file]
skins/MonoBook/i18n/nn.json [deleted file]
skins/MonoBook/i18n/nv.json [deleted file]
skins/MonoBook/i18n/oc.json [deleted file]
skins/MonoBook/i18n/os.json [deleted file]
skins/MonoBook/i18n/pa.json [deleted file]
skins/MonoBook/i18n/pam.json [deleted file]
skins/MonoBook/i18n/pdt.json [deleted file]
skins/MonoBook/i18n/pl.json [deleted file]
skins/MonoBook/i18n/pms.json [deleted file]
skins/MonoBook/i18n/ps.json [deleted file]
skins/MonoBook/i18n/pt-br.json [deleted file]
skins/MonoBook/i18n/pt.json [deleted file]
skins/MonoBook/i18n/qqq.json [deleted file]
skins/MonoBook/i18n/qu.json [deleted file]
skins/MonoBook/i18n/rm.json [deleted file]
skins/MonoBook/i18n/ro.json [deleted file]
skins/MonoBook/i18n/roa-tara.json [deleted file]
skins/MonoBook/i18n/ru.json [deleted file]
skins/MonoBook/i18n/sa.json [deleted file]
skins/MonoBook/i18n/sah.json [deleted file]
skins/MonoBook/i18n/scn.json [deleted file]
skins/MonoBook/i18n/si.json [deleted file]
skins/MonoBook/i18n/sk.json [deleted file]
skins/MonoBook/i18n/sq.json [deleted file]
skins/MonoBook/i18n/sr-ec.json [deleted file]
skins/MonoBook/i18n/sr-el.json [deleted file]
skins/MonoBook/i18n/stq.json [deleted file]
skins/MonoBook/i18n/su.json [deleted file]
skins/MonoBook/i18n/sv.json [deleted file]
skins/MonoBook/i18n/te.json [deleted file]
skins/MonoBook/i18n/th.json [deleted file]
skins/MonoBook/i18n/tl.json [deleted file]
skins/MonoBook/i18n/tr.json [deleted file]
skins/MonoBook/i18n/tt-cyrl.json [deleted file]
skins/MonoBook/i18n/tt-latn.json [deleted file]
skins/MonoBook/i18n/tyv.json [deleted file]
skins/MonoBook/i18n/ug-arab.json [deleted file]
skins/MonoBook/i18n/uk.json [deleted file]
skins/MonoBook/i18n/vep.json [deleted file]
skins/MonoBook/i18n/vi.json [deleted file]
skins/MonoBook/i18n/vmf.json [deleted file]
skins/MonoBook/i18n/vo.json [deleted file]
skins/MonoBook/i18n/vro.json [deleted file]
skins/MonoBook/i18n/wa.json [deleted file]
skins/MonoBook/i18n/wo.json [deleted file]
skins/MonoBook/i18n/yi.json [deleted file]
skins/MonoBook/i18n/yue.json [deleted file]
skins/MonoBook/i18n/zh-hans.json [deleted file]
skins/MonoBook/i18n/zh-hant.json [deleted file]
skins/MonoBook/link_icon.gif [deleted file]
skins/MonoBook/lock_icon.gif [deleted file]
skins/MonoBook/magnify-clip.png [deleted file]
skins/MonoBook/mail_icon.gif [deleted file]
skins/MonoBook/main.css [deleted file]
skins/MonoBook/news_icon.png [deleted file]
skins/MonoBook/required.gif [deleted file]
skins/MonoBook/user.gif [deleted file]
skins/MonoBook/video.png [deleted file]
skins/MonoBook/wiki-indexed.png [deleted file]
skins/MonoBook/wiki.png [deleted file]
skins/README [new file with mode: 0644]
skins/Vector/COPYING [deleted file]
skins/Vector/SkinVector.php [deleted file]
skins/Vector/Vector.php [deleted file]
skins/Vector/VectorTemplate.php [deleted file]
skins/Vector/collapsibleTabs.js [deleted file]
skins/Vector/components/animations.less [deleted file]
skins/Vector/components/common.less [deleted file]
skins/Vector/components/externalLinks.less [deleted file]
skins/Vector/components/footer.less [deleted file]
skins/Vector/components/navigation.less [deleted file]
skins/Vector/components/notifications.less [deleted file]
skins/Vector/components/personalMenu.less [deleted file]
skins/Vector/components/search.less [deleted file]
skins/Vector/components/tabs.less [deleted file]
skins/Vector/components/watchstar.less [deleted file]
skins/Vector/csshover.htc [deleted file]
skins/Vector/csshover.min.htc [deleted file]
skins/Vector/i18n/ab.json [deleted file]
skins/Vector/i18n/ace.json [deleted file]
skins/Vector/i18n/ady-cyrl.json [deleted file]
skins/Vector/i18n/aeb.json [deleted file]
skins/Vector/i18n/af.json [deleted file]
skins/Vector/i18n/aln.json [deleted file]
skins/Vector/i18n/am.json [deleted file]
skins/Vector/i18n/an.json [deleted file]
skins/Vector/i18n/ang.json [deleted file]
skins/Vector/i18n/ar.json [deleted file]
skins/Vector/i18n/arc.json [deleted file]
skins/Vector/i18n/arn.json [deleted file]
skins/Vector/i18n/aro.json [deleted file]
skins/Vector/i18n/arq.json [deleted file]
skins/Vector/i18n/ary.json [deleted file]
skins/Vector/i18n/arz.json [deleted file]
skins/Vector/i18n/as.json [deleted file]
skins/Vector/i18n/ase.json [deleted file]
skins/Vector/i18n/ast.json [deleted file]
skins/Vector/i18n/av.json [deleted file]
skins/Vector/i18n/avk.json [deleted file]
skins/Vector/i18n/az.json [deleted file]
skins/Vector/i18n/azb.json [deleted file]
skins/Vector/i18n/ba.json [deleted file]
skins/Vector/i18n/ban.json [deleted file]
skins/Vector/i18n/bar.json [deleted file]
skins/Vector/i18n/bbc-latn.json [deleted file]
skins/Vector/i18n/bcc.json [deleted file]
skins/Vector/i18n/bcl.json [deleted file]
skins/Vector/i18n/be-tarask.json [deleted file]
skins/Vector/i18n/be.json [deleted file]
skins/Vector/i18n/bew.json [deleted file]
skins/Vector/i18n/bg.json [deleted file]
skins/Vector/i18n/bho.json [deleted file]
skins/Vector/i18n/bi.json [deleted file]
skins/Vector/i18n/bjn.json [deleted file]
skins/Vector/i18n/bm.json [deleted file]
skins/Vector/i18n/bn.json [deleted file]
skins/Vector/i18n/bo.json [deleted file]
skins/Vector/i18n/bpy.json [deleted file]
skins/Vector/i18n/br.json [deleted file]
skins/Vector/i18n/brh.json [deleted file]
skins/Vector/i18n/bs.json [deleted file]
skins/Vector/i18n/bug.json [deleted file]
skins/Vector/i18n/bxr.json [deleted file]
skins/Vector/i18n/ca.json [deleted file]
skins/Vector/i18n/cdo.json [deleted file]
skins/Vector/i18n/ce.json [deleted file]
skins/Vector/i18n/ceb.json [deleted file]
skins/Vector/i18n/ckb.json [deleted file]
skins/Vector/i18n/co.json [deleted file]
skins/Vector/i18n/cps.json [deleted file]
skins/Vector/i18n/crh-cyrl.json [deleted file]
skins/Vector/i18n/crh-latn.json [deleted file]
skins/Vector/i18n/cs.json [deleted file]
skins/Vector/i18n/csb.json [deleted file]
skins/Vector/i18n/cu.json [deleted file]
skins/Vector/i18n/cv.json [deleted file]
skins/Vector/i18n/cy.json [deleted file]
skins/Vector/i18n/da.json [deleted file]
skins/Vector/i18n/de.json [deleted file]
skins/Vector/i18n/diq.json [deleted file]
skins/Vector/i18n/dsb.json [deleted file]
skins/Vector/i18n/dtp.json [deleted file]
skins/Vector/i18n/dv.json [deleted file]
skins/Vector/i18n/ee.json [deleted file]
skins/Vector/i18n/egl.json [deleted file]
skins/Vector/i18n/el.json [deleted file]
skins/Vector/i18n/en.json [deleted file]
skins/Vector/i18n/eo.json [deleted file]
skins/Vector/i18n/es-formal.json [deleted file]
skins/Vector/i18n/es.json [deleted file]
skins/Vector/i18n/esu.json [deleted file]
skins/Vector/i18n/et.json [deleted file]
skins/Vector/i18n/eu.json [deleted file]
skins/Vector/i18n/ext.json [deleted file]
skins/Vector/i18n/fa.json [deleted file]
skins/Vector/i18n/ff.json [deleted file]
skins/Vector/i18n/fi.json [deleted file]
skins/Vector/i18n/fit.json [deleted file]
skins/Vector/i18n/fo.json [deleted file]
skins/Vector/i18n/fr.json [deleted file]
skins/Vector/i18n/frc.json [deleted file]
skins/Vector/i18n/frp.json [deleted file]
skins/Vector/i18n/frr.json [deleted file]
skins/Vector/i18n/fur.json [deleted file]
skins/Vector/i18n/fy.json [deleted file]
skins/Vector/i18n/ga.json [deleted file]
skins/Vector/i18n/gag.json [deleted file]
skins/Vector/i18n/gan-hans.json [deleted file]
skins/Vector/i18n/gan-hant.json [deleted file]
skins/Vector/i18n/gd.json [deleted file]
skins/Vector/i18n/gl.json [deleted file]
skins/Vector/i18n/gom-deva.json [deleted file]
skins/Vector/i18n/gom-latn.json [deleted file]
skins/Vector/i18n/grc.json [deleted file]
skins/Vector/i18n/gsw.json [deleted file]
skins/Vector/i18n/gu.json [deleted file]
skins/Vector/i18n/guc.json [deleted file]
skins/Vector/i18n/gv.json [deleted file]
skins/Vector/i18n/ha.json [deleted file]
skins/Vector/i18n/hak.json [deleted file]
skins/Vector/i18n/haw.json [deleted file]
skins/Vector/i18n/he.json [deleted file]
skins/Vector/i18n/hi.json [deleted file]
skins/Vector/i18n/hif-latn.json [deleted file]
skins/Vector/i18n/hil.json [deleted file]
skins/Vector/i18n/hr.json [deleted file]
skins/Vector/i18n/hrx.json [deleted file]
skins/Vector/i18n/hsb.json [deleted file]
skins/Vector/i18n/hsn.json [deleted file]
skins/Vector/i18n/ht.json [deleted file]
skins/Vector/i18n/hu-formal.json [deleted file]
skins/Vector/i18n/hu.json [deleted file]
skins/Vector/i18n/hy.json [deleted file]
skins/Vector/i18n/ia.json [deleted file]
skins/Vector/i18n/id.json [deleted file]
skins/Vector/i18n/ie.json [deleted file]
skins/Vector/i18n/ig.json [deleted file]
skins/Vector/i18n/ike-latn.json [deleted file]
skins/Vector/i18n/ilo.json [deleted file]
skins/Vector/i18n/inh.json [deleted file]
skins/Vector/i18n/io.json [deleted file]
skins/Vector/i18n/is.json [deleted file]
skins/Vector/i18n/it.json [deleted file]
skins/Vector/i18n/izh.json [deleted file]
skins/Vector/i18n/ja.json [deleted file]
skins/Vector/i18n/jam.json [deleted file]
skins/Vector/i18n/jbo.json [deleted file]
skins/Vector/i18n/jv.json [deleted file]
skins/Vector/i18n/ka.json [deleted file]
skins/Vector/i18n/kaa.json [deleted file]
skins/Vector/i18n/kab.json [deleted file]
skins/Vector/i18n/kbd-cyrl.json [deleted file]
skins/Vector/i18n/kg.json [deleted file]
skins/Vector/i18n/khw.json [deleted file]
skins/Vector/i18n/ki.json [deleted file]
skins/Vector/i18n/kiu.json [deleted file]
skins/Vector/i18n/kk-cyrl.json [deleted file]
skins/Vector/i18n/kl.json [deleted file]
skins/Vector/i18n/km.json [deleted file]
skins/Vector/i18n/kn.json [deleted file]
skins/Vector/i18n/ko.json [deleted file]
skins/Vector/i18n/koi.json [deleted file]
skins/Vector/i18n/krc.json [deleted file]
skins/Vector/i18n/kri.json [deleted file]
skins/Vector/i18n/ks-arab.json [deleted file]
skins/Vector/i18n/ksh.json [deleted file]
skins/Vector/i18n/ku-latn.json [deleted file]
skins/Vector/i18n/kv.json [deleted file]
skins/Vector/i18n/kw.json [deleted file]
skins/Vector/i18n/ky.json [deleted file]
skins/Vector/i18n/la.json [deleted file]
skins/Vector/i18n/lad.json [deleted file]
skins/Vector/i18n/lb.json [deleted file]
skins/Vector/i18n/lez.json [deleted file]
skins/Vector/i18n/lg.json [deleted file]
skins/Vector/i18n/li.json [deleted file]
skins/Vector/i18n/lij.json [deleted file]
skins/Vector/i18n/liv.json [deleted file]
skins/Vector/i18n/lmo.json [deleted file]
skins/Vector/i18n/ln.json [deleted file]
skins/Vector/i18n/lrc.json [deleted file]
skins/Vector/i18n/lt.json [deleted file]
skins/Vector/i18n/ltg.json [deleted file]
skins/Vector/i18n/lus.json [deleted file]
skins/Vector/i18n/luz.json [deleted file]
skins/Vector/i18n/lv.json [deleted file]
skins/Vector/i18n/lzh.json [deleted file]
skins/Vector/i18n/lzz.json [deleted file]
skins/Vector/i18n/mai.json [deleted file]
skins/Vector/i18n/map-bms.json [deleted file]
skins/Vector/i18n/mdf.json [deleted file]
skins/Vector/i18n/mg.json [deleted file]
skins/Vector/i18n/mhr.json [deleted file]
skins/Vector/i18n/mi.json [deleted file]
skins/Vector/i18n/mic.json [deleted file]
skins/Vector/i18n/min.json [deleted file]
skins/Vector/i18n/mk.json [deleted file]
skins/Vector/i18n/ml.json [deleted file]
skins/Vector/i18n/mn.json [deleted file]
skins/Vector/i18n/mnc.json [deleted file]
skins/Vector/i18n/mr.json [deleted file]
skins/Vector/i18n/mrj.json [deleted file]
skins/Vector/i18n/ms.json [deleted file]
skins/Vector/i18n/mt.json [deleted file]
skins/Vector/i18n/mui.json [deleted file]
skins/Vector/i18n/my.json [deleted file]
skins/Vector/i18n/myv.json [deleted file]
skins/Vector/i18n/mzn.json [deleted file]
skins/Vector/i18n/nah.json [deleted file]
skins/Vector/i18n/nan.json [deleted file]
skins/Vector/i18n/nap.json [deleted file]
skins/Vector/i18n/nb.json [deleted file]
skins/Vector/i18n/nds-nl.json [deleted file]
skins/Vector/i18n/nds.json [deleted file]
skins/Vector/i18n/ne.json [deleted file]
skins/Vector/i18n/new.json [deleted file]
skins/Vector/i18n/nl.json [deleted file]
skins/Vector/i18n/nn.json [deleted file]
skins/Vector/i18n/nov.json [deleted file]
skins/Vector/i18n/nrm.json [deleted file]
skins/Vector/i18n/nso.json [deleted file]
skins/Vector/i18n/oc.json [deleted file]
skins/Vector/i18n/or.json [deleted file]
skins/Vector/i18n/os.json [deleted file]
skins/Vector/i18n/pa.json [deleted file]
skins/Vector/i18n/pam.json [deleted file]
skins/Vector/i18n/pbb.json [deleted file]
skins/Vector/i18n/pcd.json [deleted file]
skins/Vector/i18n/pdc.json [deleted file]
skins/Vector/i18n/pfl.json [deleted file]
skins/Vector/i18n/pi.json [deleted file]
skins/Vector/i18n/pih.json [deleted file]
skins/Vector/i18n/pl.json [deleted file]
skins/Vector/i18n/pms.json [deleted file]
skins/Vector/i18n/pnb.json [deleted file]
skins/Vector/i18n/pnt.json [deleted file]
skins/Vector/i18n/ppl.json [deleted file]
skins/Vector/i18n/prg.json [deleted file]
skins/Vector/i18n/ps.json [deleted file]
skins/Vector/i18n/pt-br.json [deleted file]
skins/Vector/i18n/pt.json [deleted file]
skins/Vector/i18n/qqq.json [deleted file]
skins/Vector/i18n/qu.json [deleted file]
skins/Vector/i18n/qug.json [deleted file]
skins/Vector/i18n/rap.json [deleted file]
skins/Vector/i18n/rgn.json [deleted file]
skins/Vector/i18n/rif.json [deleted file]
skins/Vector/i18n/rm.json [deleted file]
skins/Vector/i18n/rmf.json [deleted file]
skins/Vector/i18n/ro.json [deleted file]
skins/Vector/i18n/roa-tara.json [deleted file]
skins/Vector/i18n/ru.json [deleted file]
skins/Vector/i18n/rue.json [deleted file]
skins/Vector/i18n/rup.json [deleted file]
skins/Vector/i18n/rw.json [deleted file]
skins/Vector/i18n/ryu.json [deleted file]
skins/Vector/i18n/sa.json [deleted file]
skins/Vector/i18n/sah.json [deleted file]
skins/Vector/i18n/sat.json [deleted file]
skins/Vector/i18n/saz.json [deleted file]
skins/Vector/i18n/sc.json [deleted file]
skins/Vector/i18n/scn.json [deleted file]
skins/Vector/i18n/sco.json [deleted file]
skins/Vector/i18n/sd.json [deleted file]
skins/Vector/i18n/sdc.json [deleted file]
skins/Vector/i18n/sdh.json [deleted file]
skins/Vector/i18n/se.json [deleted file]
skins/Vector/i18n/sg.json [deleted file]
skins/Vector/i18n/sgs.json [deleted file]
skins/Vector/i18n/sh.json [deleted file]
skins/Vector/i18n/shi.json [deleted file]
skins/Vector/i18n/shn.json [deleted file]
skins/Vector/i18n/si.json [deleted file]
skins/Vector/i18n/sk.json [deleted file]
skins/Vector/i18n/sl.json [deleted file]
skins/Vector/i18n/sli.json [deleted file]
skins/Vector/i18n/sly.json [deleted file]
skins/Vector/i18n/so.json [deleted file]
skins/Vector/i18n/sq.json [deleted file]
skins/Vector/i18n/sr-ec.json [deleted file]
skins/Vector/i18n/sr-el.json [deleted file]
skins/Vector/i18n/ss.json [deleted file]
skins/Vector/i18n/stq.json [deleted file]
skins/Vector/i18n/su.json [deleted file]
skins/Vector/i18n/sv.json [deleted file]
skins/Vector/i18n/sw.json [deleted file]
skins/Vector/i18n/szl.json [deleted file]
skins/Vector/i18n/ta.json [deleted file]
skins/Vector/i18n/tcy.json [deleted file]
skins/Vector/i18n/te.json [deleted file]
skins/Vector/i18n/tet.json [deleted file]
skins/Vector/i18n/tg-cyrl.json [deleted file]
skins/Vector/i18n/tg-latn.json [deleted file]
skins/Vector/i18n/th.json [deleted file]
skins/Vector/i18n/tk.json [deleted file]
skins/Vector/i18n/tl.json [deleted file]
skins/Vector/i18n/tly.json [deleted file]
skins/Vector/i18n/tpi.json [deleted file]
skins/Vector/i18n/tr.json [deleted file]
skins/Vector/i18n/tru.json [deleted file]
skins/Vector/i18n/ts.json [deleted file]
skins/Vector/i18n/tt-cyrl.json [deleted file]
skins/Vector/i18n/tt-latn.json [deleted file]
skins/Vector/i18n/tyv.json [deleted file]
skins/Vector/i18n/tzm.json [deleted file]
skins/Vector/i18n/udm.json [deleted file]
skins/Vector/i18n/ug-arab.json [deleted file]
skins/Vector/i18n/uk.json [deleted file]
skins/Vector/i18n/ur.json [deleted file]
skins/Vector/i18n/uz.json [deleted file]
skins/Vector/i18n/vec.json [deleted file]
skins/Vector/i18n/vep.json [deleted file]
skins/Vector/i18n/vi.json [deleted file]
skins/Vector/i18n/vls.json [deleted file]
skins/Vector/i18n/vmf.json [deleted file]
skins/Vector/i18n/vo.json [deleted file]
skins/Vector/i18n/vot.json [deleted file]
skins/Vector/i18n/vro.json [deleted file]
skins/Vector/i18n/wa.json [deleted file]
skins/Vector/i18n/war.json [deleted file]
skins/Vector/i18n/wo.json [deleted file]
skins/Vector/i18n/wuu.json [deleted file]
skins/Vector/i18n/xal.json [deleted file]
skins/Vector/i18n/xh.json [deleted file]
skins/Vector/i18n/xmf.json [deleted file]
skins/Vector/i18n/yi.json [deleted file]
skins/Vector/i18n/yo.json [deleted file]
skins/Vector/i18n/yue.json [deleted file]
skins/Vector/i18n/za.json [deleted file]
skins/Vector/i18n/zea.json [deleted file]
skins/Vector/i18n/zh-hans.json [deleted file]
skins/Vector/i18n/zh-hant.json [deleted file]
skins/Vector/images/arrow-collapsed-ltr.png [deleted file]
skins/Vector/images/arrow-collapsed-ltr.svg [deleted file]
skins/Vector/images/arrow-collapsed-rtl.png [deleted file]
skins/Vector/images/arrow-collapsed-rtl.svg [deleted file]
skins/Vector/images/arrow-down-focus-icon.png [deleted file]
skins/Vector/images/arrow-down-focus-icon.svg [deleted file]
skins/Vector/images/arrow-down-icon.png [deleted file]
skins/Vector/images/arrow-down-icon.svg [deleted file]
skins/Vector/images/arrow-expanded.png [deleted file]
skins/Vector/images/arrow-expanded.svg [deleted file]
skins/Vector/images/bullet-icon.png [deleted file]
skins/Vector/images/external-link-ltr-icon.png [deleted file]
skins/Vector/images/external-link-ltr-icon.svg [deleted file]
skins/Vector/images/external-link-rtl-icon.png [deleted file]
skins/Vector/images/external-link-rtl-icon.svg [deleted file]
skins/Vector/images/link-icon.png [deleted file]
skins/Vector/images/magnify-clip.png [deleted file]
skins/Vector/images/page-fade.png [deleted file]
skins/Vector/images/portal-break-ltr.png [deleted file]
skins/Vector/images/portal-break-rtl.png [deleted file]
skins/Vector/images/portal-break.png [deleted file]
skins/Vector/images/preferences/break.png [deleted file]
skins/Vector/images/preferences/fade.png [deleted file]
skins/Vector/images/search-fade.png [deleted file]
skins/Vector/images/search-ltr.png [deleted file]
skins/Vector/images/search-ltr.svg [deleted file]
skins/Vector/images/search-rtl.png [deleted file]
skins/Vector/images/search-rtl.svg [deleted file]
skins/Vector/images/tab-break.png [deleted file]
skins/Vector/images/tab-current-fade.png [deleted file]
skins/Vector/images/tab-normal-fade.png [deleted file]
skins/Vector/images/unwatch-icon-hl.png [deleted file]
skins/Vector/images/unwatch-icon-hl.svg [deleted file]
skins/Vector/images/unwatch-icon.png [deleted file]
skins/Vector/images/unwatch-icon.svg [deleted file]
skins/Vector/images/user-icon.png [deleted file]
skins/Vector/images/user-icon.svg [deleted file]
skins/Vector/images/watch-icon-hl.png [deleted file]
skins/Vector/images/watch-icon-hl.svg [deleted file]
skins/Vector/images/watch-icon-loading.png [deleted file]
skins/Vector/images/watch-icon-loading.svg [deleted file]
skins/Vector/images/watch-icon.png [deleted file]
skins/Vector/images/watch-icon.svg [deleted file]
skins/Vector/screen-hd.less [deleted file]
skins/Vector/screen.less [deleted file]
skins/Vector/special.less [deleted file]
skins/Vector/special.preferences.less [deleted file]
skins/Vector/variables.less [deleted file]
skins/Vector/vector.js [deleted file]
skins/common/IEFixes.js [deleted file]
skins/common/ajax.js [changed from file to symlink]
skins/common/commonContent.css [deleted file]
skins/common/commonElements.css [deleted file]
skins/common/commonInterface.css [deleted file]
skins/common/commonPrint.css [deleted file]
skins/common/config-cc.css [deleted file]
skins/common/config.css [deleted file]
skins/common/config.js [deleted file]
skins/common/feed.css [deleted file]
skins/common/images/Arr_.png [deleted file]
skins/common/images/Arr_d.png [deleted file]
skins/common/images/Arr_l.png [deleted file]
skins/common/images/Arr_r.png [deleted file]
skins/common/images/Arr_u.png [deleted file]
skins/common/images/Checker-16x16.png [deleted file]
skins/common/images/Zoom_sans.gif [deleted file]
skins/common/images/add.png [deleted file]
skins/common/images/ajax-loader.gif [deleted file]
skins/common/images/ar/button_bold.png [deleted file]
skins/common/images/ar/button_headline.png [deleted file]
skins/common/images/ar/button_italic.png [deleted file]
skins/common/images/ar/button_link.png [deleted file]
skins/common/images/ar/button_nowiki.png [deleted file]
skins/common/images/arrow_disabled_first_25.png [deleted file]
skins/common/images/arrow_disabled_last_25.png [deleted file]
skins/common/images/arrow_disabled_left_25.png [deleted file]
skins/common/images/arrow_disabled_right_25.png [deleted file]
skins/common/images/arrow_first_25.png [deleted file]
skins/common/images/arrow_last_25.png [deleted file]
skins/common/images/arrow_left_25.png [deleted file]
skins/common/images/arrow_right_25.png [deleted file]
skins/common/images/be-tarask/button_bold.png [deleted file]
skins/common/images/be-tarask/button_italic.png [deleted file]
skins/common/images/be-tarask/button_link.png [deleted file]
skins/common/images/button_bold.png [deleted file]
skins/common/images/button_extlink.png [deleted file]
skins/common/images/button_headline.png [deleted file]
skins/common/images/button_hr.png [deleted file]
skins/common/images/button_image.png [deleted file]
skins/common/images/button_italic.png [deleted file]
skins/common/images/button_link.png [deleted file]
skins/common/images/button_media.png [deleted file]
skins/common/images/button_nowiki.png [deleted file]
skins/common/images/button_sig.png [deleted file]
skins/common/images/button_template.png [deleted file]
skins/common/images/cc-0.png [deleted file]
skins/common/images/cc-by-nc-sa.png [deleted file]
skins/common/images/cc-by-sa.png [deleted file]
skins/common/images/cc-by.png [deleted file]
skins/common/images/closewindow.png [deleted file]
skins/common/images/closewindow19x19.png [deleted file]
skins/common/images/critical-32.png [deleted file]
skins/common/images/cyrl/LICENSE [deleted file]
skins/common/images/cyrl/button_bold.png [deleted file]
skins/common/images/cyrl/button_italic.png [deleted file]
skins/common/images/cyrl/button_link.png [deleted file]
skins/common/images/de/button_bold.png [deleted file]
skins/common/images/de/button_italic.png [deleted file]
skins/common/images/diffunderline.gif [deleted file]
skins/common/images/download-32.png [deleted file]
skins/common/images/fa/button_bold.png [deleted file]
skins/common/images/fa/button_headline.png [deleted file]
skins/common/images/fa/button_italic.png [deleted file]
skins/common/images/fa/button_link.png [deleted file]
skins/common/images/fa/button_nowiki.png [deleted file]
skins/common/images/feed-icon.png [deleted file]
skins/common/images/feed-icon.svg [deleted file]
skins/common/images/gnu-fdl.png [deleted file]
skins/common/images/help-question-hover.gif [deleted file]
skins/common/images/help-question.gif [deleted file]
skins/common/images/icons/COPYING [deleted file]
skins/common/images/icons/fileicon-c.png [deleted file]
skins/common/images/icons/fileicon-cpp.png [deleted file]
skins/common/images/icons/fileicon-deb.png [deleted file]
skins/common/images/icons/fileicon-djvu.png [deleted file]
skins/common/images/icons/fileicon-djvu.xcf [deleted file]
skins/common/images/icons/fileicon-dvi.png [deleted file]
skins/common/images/icons/fileicon-exe.png [deleted file]
skins/common/images/icons/fileicon-h.png [deleted file]
skins/common/images/icons/fileicon-html.png [deleted file]
skins/common/images/icons/fileicon-iso.png [deleted file]
skins/common/images/icons/fileicon-java.png [deleted file]
skins/common/images/icons/fileicon-mid.png [deleted file]
skins/common/images/icons/fileicon-mov.png [deleted file]
skins/common/images/icons/fileicon-o.png [deleted file]
skins/common/images/icons/fileicon-ogg.png [deleted file]
skins/common/images/icons/fileicon-ogg.xcf [deleted file]
skins/common/images/icons/fileicon-pdf.png [deleted file]
skins/common/images/icons/fileicon-ps.png [deleted file]
skins/common/images/icons/fileicon-psd.png [deleted file]
skins/common/images/icons/fileicon-rm.png [deleted file]
skins/common/images/icons/fileicon-rpm.png [deleted file]
skins/common/images/icons/fileicon-svg.png [deleted file]
skins/common/images/icons/fileicon-tar.png [deleted file]
skins/common/images/icons/fileicon-tex.png [deleted file]
skins/common/images/icons/fileicon-ttf.png [deleted file]
skins/common/images/icons/fileicon-txt.png [deleted file]
skins/common/images/icons/fileicon-xcf.png [deleted file]
skins/common/images/icons/fileicon.png [deleted file]
skins/common/images/info-32.png [deleted file]
skins/common/images/ksh/LICENSE [deleted file]
skins/common/images/ksh/button_S_italic.png [deleted file]
skins/common/images/link_icon.gif [deleted file]
skins/common/images/mediawiki.png [deleted file]
skins/common/images/nextredirectltr.png [deleted file]
skins/common/images/nextredirectrtl.png [deleted file]
skins/common/images/poweredby_mediawiki_88x31.png [deleted file]
skins/common/images/public-domain.png [deleted file]
skins/common/images/question-small.png [deleted file]
skins/common/images/question.svg [deleted file]
skins/common/images/remove.png [deleted file]
skins/common/images/spinner.gif [deleted file]
skins/common/images/tick-32.png [deleted file]
skins/common/images/tipsy-arrow.gif [deleted file]
skins/common/images/tooltip_icon.png [deleted file]
skins/common/images/warning-32.png [deleted file]
skins/common/oldshared.css [deleted file]
skins/common/protect.js [deleted file]
skins/common/shared.css [deleted file]
skins/common/upload.js [deleted file]
skins/common/wikibits.js [changed from file to symlink]
tests/TestsAutoLoader.php
tests/browser/Gemfile.lock
tests/browser/README.mediawiki
tests/browser/features/support/pages/preferences_appearance_page.rb
tests/frontend/Gruntfile.js
tests/frontend/package.json
tests/parser/parserTest.inc
tests/parser/parserTests.txt
tests/parserTests.php
tests/phpunit/LessFileCompilationTest.php
tests/phpunit/MediaWikiPHPUnitCommand.php [deleted file]
tests/phpunit/MediaWikiPHPUnitTestListener.php
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/ResourceLoaderTestCase.php
tests/phpunit/data/css/expected.css [new file with mode: 0644]
tests/phpunit/data/css/simple-ltr.gif [new file with mode: 0644]
tests/phpunit/data/css/simple-rtl.gif [new file with mode: 0644]
tests/phpunit/data/css/test.css [new file with mode: 0644]
tests/phpunit/data/less/module/styles.css
tests/phpunit/data/localisationcache/en.json [new file with mode: 0644]
tests/phpunit/data/localisationcache/ru.json [new file with mode: 0644]
tests/phpunit/data/localisationcache/uk.json [new file with mode: 0644]
tests/phpunit/includes/ArrayUtilsTest.php
tests/phpunit/includes/ArticleTablesTest.php
tests/phpunit/includes/EditPageTest.php
tests/phpunit/includes/GlobalFunctions/GlobalTest.php
tests/phpunit/includes/GlobalFunctions/GlobalWithDBTest.php
tests/phpunit/includes/GlobalFunctions/wfAssembleUrlTest.php
tests/phpunit/includes/GlobalFunctions/wfBCP47Test.php
tests/phpunit/includes/GlobalFunctions/wfBaseConvertTest.php
tests/phpunit/includes/GlobalFunctions/wfBaseNameTest.php
tests/phpunit/includes/GlobalFunctions/wfExpandUrlTest.php
tests/phpunit/includes/GlobalFunctions/wfGetCallerTest.php
tests/phpunit/includes/GlobalFunctions/wfParseUrlTest.php
tests/phpunit/includes/GlobalFunctions/wfRemoveDotSegmentsTest.php
tests/phpunit/includes/GlobalFunctions/wfShellExecTest.php [new file with mode: 0644]
tests/phpunit/includes/GlobalFunctions/wfShorthandToIntegerTest.php
tests/phpunit/includes/GlobalFunctions/wfTimestampTest.php
tests/phpunit/includes/GlobalFunctions/wfUrlencodeTest.php
tests/phpunit/includes/HtmlFormatterTest.php
tests/phpunit/includes/HtmlTest.php
tests/phpunit/includes/ImagePage404Test.php
tests/phpunit/includes/ImagePageTest.php
tests/phpunit/includes/ImportTest.php
tests/phpunit/includes/LinksUpdateTest.php
tests/phpunit/includes/LocalisationCacheTest.php [deleted file]
tests/phpunit/includes/MWNamespaceTest.php
tests/phpunit/includes/MessageTest.php
tests/phpunit/includes/MimeMagicTest.php
tests/phpunit/includes/OutputPageTest.php
tests/phpunit/includes/PasswordTest.php [new file with mode: 0644]
tests/phpunit/includes/SampleTest.php
tests/phpunit/includes/SanitizerValidateEmailTest.php
tests/phpunit/includes/SkinTemplateTest.php [deleted file]
tests/phpunit/includes/SpecialPageTest.php
tests/phpunit/includes/StatusTest.php
tests/phpunit/includes/TimeAdjustTest.php
tests/phpunit/includes/TitleMethodsTest.php
tests/phpunit/includes/TitlePermissionTest.php
tests/phpunit/includes/TitleTest.php
tests/phpunit/includes/UserMailerTest.php [deleted file]
tests/phpunit/includes/UserTest.php
tests/phpunit/includes/WebRequestTest.php
tests/phpunit/includes/XmlTest.php
tests/phpunit/includes/actions/ActionTest.php [new file with mode: 0644]
tests/phpunit/includes/api/ApiEditPageTest.php
tests/phpunit/includes/api/ApiMainTest.php
tests/phpunit/includes/api/ApiModuleManagerTest.php [new file with mode: 0644]
tests/phpunit/includes/api/ApiRevisionDeleteTest.php [new file with mode: 0644]
tests/phpunit/includes/api/ApiTestCase.php
tests/phpunit/includes/api/ApiTestCaseUpload.php
tests/phpunit/includes/api/PrefixUniquenessTest.php
tests/phpunit/includes/api/RandomImageGenerator.php
tests/phpunit/includes/api/format/ApiFormatJsonTest.php
tests/phpunit/includes/api/format/ApiFormatNoneTest.php [new file with mode: 0644]
tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php
tests/phpunit/includes/api/query/ApiQueryTest.php
tests/phpunit/includes/api/query/ApiQueryTestBase.php
tests/phpunit/includes/cache/LocalisationCacheTest.php [new file with mode: 0644]
tests/phpunit/includes/cache/MessageCacheTest.php
tests/phpunit/includes/cache/RedisBloomCacheTest.php [new file with mode: 0644]
tests/phpunit/includes/changes/EnhancedChangesListTest.php [new file with mode: 0644]
tests/phpunit/includes/changes/OldChangesListTest.php [new file with mode: 0644]
tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php
tests/phpunit/includes/changes/TestRecentChangesHelper.php [new file with mode: 0644]
tests/phpunit/includes/config/ConfigFactoryTest.php
tests/phpunit/includes/config/GlobalVarConfigTest.php
tests/phpunit/includes/content/ContentHandlerTest.php
tests/phpunit/includes/content/JsonContentTest.php [new file with mode: 0644]
tests/phpunit/includes/db/DatabaseSqliteTest.php
tests/phpunit/includes/db/DatabaseTestHelper.php
tests/phpunit/includes/db/ORMRowTest.php
tests/phpunit/includes/debug/MWDebugTest.php
tests/phpunit/includes/deferred/DeferredUpdatesTest.php [new file with mode: 0644]
tests/phpunit/includes/diff/ArrayDiffFormatterTest.php
tests/phpunit/includes/diff/DifferenceEngineTest.php
tests/phpunit/includes/exception/MWExceptionHandlerTest.php
tests/phpunit/includes/filebackend/FileBackendTest.php
tests/phpunit/includes/filerepo/RepoGroupTest.php
tests/phpunit/includes/filerepo/StoreBatchTest.php
tests/phpunit/includes/filerepo/file/FileTest.php
tests/phpunit/includes/filerepo/files/FileTest.php [deleted file]
tests/phpunit/includes/htmlform/HTMLAutoCompleteSelectFieldTest.php [new file with mode: 0644]
tests/phpunit/includes/jobqueue/JobQueueTest.php
tests/phpunit/includes/libs/CSSJanusTest.php
tests/phpunit/includes/libs/MWMessagePackTest.php
tests/phpunit/includes/mail/MailAddressTest.php [new file with mode: 0644]
tests/phpunit/includes/mail/UserMailerTest.php [new file with mode: 0644]
tests/phpunit/includes/media/BitmapMetadataHandlerTest.php
tests/phpunit/includes/media/BitmapScalingTest.php
tests/phpunit/includes/media/DjVuTest.php
tests/phpunit/includes/media/ExifBitmapTest.php
tests/phpunit/includes/media/ExifRotationTest.php
tests/phpunit/includes/media/ExifTest.php
tests/phpunit/includes/media/FakeDimensionFile.php
tests/phpunit/includes/media/FormatMetadataTest.php
tests/phpunit/includes/media/GIFMetadataExtractorTest.php
tests/phpunit/includes/media/GIFTest.php
tests/phpunit/includes/media/IPTCTest.php
tests/phpunit/includes/media/JpegMetadataExtractorTest.php
tests/phpunit/includes/media/JpegTest.php
tests/phpunit/includes/media/MediaHandlerTest.php
tests/phpunit/includes/media/MediaWikiMediaTestCase.php
tests/phpunit/includes/media/PNGMetadataExtractorTest.php
tests/phpunit/includes/media/PNGTest.php
tests/phpunit/includes/media/SVGMetadataExtractorTest.php
tests/phpunit/includes/media/SVGTest.php
tests/phpunit/includes/media/TiffTest.php
tests/phpunit/includes/media/XCFTest.php
tests/phpunit/includes/media/XMPTest.php
tests/phpunit/includes/media/XMPValidateTest.php
tests/phpunit/includes/objectcache/BagOStuffTest.php
tests/phpunit/includes/parser/MagicVariableTest.php
tests/phpunit/includes/parser/MediaWikiParserTest.php
tests/phpunit/includes/parser/NewParserTest.php
tests/phpunit/includes/parser/ParserMethodsTest.php
tests/phpunit/includes/parser/TidyTest.php
tests/phpunit/includes/password/BcryptPasswordTest.php [new file with mode: 0644]
tests/phpunit/includes/password/LayeredParameterizedPasswordTest.php [new file with mode: 0644]
tests/phpunit/includes/password/PasswordTestCase.php [new file with mode: 0644]
tests/phpunit/includes/password/Pbkdf2PasswordTest.php [new file with mode: 0644]
tests/phpunit/includes/poolcounter/PoolCounterTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderLESSTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderModuleTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderStartupModuleTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderWikiModuleTest.php [new file with mode: 0644]
tests/phpunit/includes/site/TestSites.php
tests/phpunit/includes/skins/SkinFactoryTest.php [new file with mode: 0644]
tests/phpunit/includes/skins/SkinTemplateTest.php [new file with mode: 0644]
tests/phpunit/includes/specials/ImageListPagerTest.php [new file with mode: 0644]
tests/phpunit/includes/specials/SpecialListFilesTest.php [deleted file]
tests/phpunit/includes/specials/SpecialMIMESearchTest.php
tests/phpunit/includes/specials/SpecialMyLanguageTest.php [new file with mode: 0644]
tests/phpunit/includes/specials/SpecialSearchTest.php
tests/phpunit/includes/title/MediaWikiPageLinkRendererTest.php
tests/phpunit/includes/title/MediaWikiTitleCodecTest.php
tests/phpunit/includes/upload/UploadFromUrlTest.php
tests/phpunit/includes/utils/StringUtilsTest.php
tests/phpunit/languages/LanguageArqTest.php [new file with mode: 0644]
tests/phpunit/languages/LanguageTest.php
tests/phpunit/maintenance/DumpTestCase.php
tests/phpunit/maintenance/MaintenanceTest.php
tests/phpunit/maintenance/backupPrefetchTest.php
tests/phpunit/maintenance/backupTextPassTest.php
tests/phpunit/maintenance/fetchTextTest.php
tests/phpunit/maintenance/getSlaveServerTest.php [deleted file]
tests/phpunit/mocks/media/MockImageHandler.php
tests/phpunit/phpunit.php
tests/phpunit/structure/AutoLoaderTest.php
tests/phpunit/structure/ResourcesTest.php
tests/phpunit/structure/StructureTest.php
tests/phpunit/suites/UploadFromUrlTestSuite.php
tests/qunit/QUnitTestResources.php
tests/qunit/data/generateJqueryMsgData.php
tests/qunit/data/testrunner.js
tests/qunit/suites/resources/jquery/jquery.autoEllipsis.test.js
tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
tests/qunit/suites/resources/jquery/jquery.textSelection.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.test.js
tests/qunit/suites/resources/startup.test.js
tests/testHelpers.inc
thumb.php

index 0351cf5..93c429f 100644 (file)
@@ -41,6 +41,7 @@ sftp-config.json
 
 # Building & testing
 node_modules/
+/tests/phpunit/phpunit.phar
 
 # Composer
 /vendor
diff --git a/.jscsrc b/.jscsrc
index 0da9aa5..b9139b2 100644 (file)
--- a/.jscsrc
+++ b/.jscsrc
@@ -1,94 +1,10 @@
 {
-    "requireCurlyBraces": [
-        "if",
-        "else",
-        "for",
-        "while",
-        "do",
-        "try",
-        "catch"
-    ],
-    "requireSpaceAfterKeywords": [
-        "if",
-        "else",
-        "for",
-        "while",
-        "do",
-        "switch",
-        "return",
-        "try",
-        "catch",
-        "function"
-    ],
-    "requireSpaceBeforeBlockStatements": true,
-    "requireParenthesesAroundIIFE": true,
-    "requireSpacesInConditionalExpression": true,
-    "disallowSpacesInNamedFunctionExpression": {
-        "beforeOpeningRoundBrace": true
-    },
-    "disallowSpacesInFunctionDeclaration": {
-        "beforeOpeningRoundBrace": true
-    },
-    "requireMultipleVarDecl": "onevar",
-    "requireBlocksOnNewline": 1,
-    "disallowEmptyBlocks": true,
-    "requireSpacesInsideObjectBrackets": "all",
-    "disallowSpaceAfterObjectKeys": true,
-    "requireCommaBeforeLineBreak": true,
-    "disallowSpaceAfterPrefixUnaryOperators": [
-        "++",
-        "--",
-        "+",
-        "-",
-        "~",
-        "!"
-    ],
-    "disallowSpaceBeforePostfixUnaryOperators": [
-        "++",
-        "--"
-    ],
-    "disallowSpaceBeforeBinaryOperators": [
-        ","
-    ],
-    "requireSpaceBeforeBinaryOperators": [
-        "=",
-        "+",
-        "-",
-        "/",
-        "*",
-        "==",
-        "===",
-        "!=",
-        "!==",
-        ">",
-        ">=",
-        "<",
-        "<="
-    ],
-    "requireSpaceAfterBinaryOperators": [
-        "=",
-        "+",
-        "-",
-        "/",
-        "*",
-        "==",
-        "===",
-        "!=",
-        "!==",
-        ">",
-        ">=",
-        "<",
-        "<="
-    ],
-    "disallowKeywords": [ "with" ],
-    "disallowMultipleLineBreaks": true,
-    "validateLineBreaks": "LF",
-    "validateQuoteMarks": "'",
-    "disallowMixedSpacesAndTabs": true,
-    "disallowTrailingWhitespace": true,
-    "disallowTrailingComma": true,
-    "requireLineFeedAtFileEnd": true,
-    "requireCapitalizedConstructors": true,
-    "requireDotNotation": true,
-    "disallowYodaConditions": true
+       "preset": "wikimedia",
+
+       "disallowDanglingUnderscores": null,
+       "disallowKeywordsOnNewLine": null,
+       "disallowQuotedKeysInObjects": null,
+       "requireCamelCaseOrUpperCaseIdentifiers": null,
+       "requireSpacesInsideArrayBrackets": null,
+       "validateIndentation": null
 }
index dedb4e1..6e07653 100644 (file)
@@ -10,6 +10,7 @@ language: php
 
 php:
   - hhvm-nightly
+  - 5.3
 
 services:
   - mysql
@@ -42,6 +43,7 @@ notifications:
   irc:
     channels:
       - "chat.freenode.net#mediawiki-core"
+      - "chat.freenode.net#mediawiki-feed"
     on_success: change
     on_failure: change
     skip_join: true
diff --git a/CREDITS b/CREDITS
index cf222a0..776e51b 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -131,6 +131,7 @@ following names for their contribution to the product.
 * Elvis Stansvik
 * Eranroz
 * Erwin Dokter
+* Étienne Beaulé
 * Federico Leva
 * FunPika
 * fomafix
@@ -157,6 +158,7 @@ following names for their contribution to the product.
 * Kim Hyun-Joon
 * Lee Worden
 * Lejonel
+* Leon Liesener
 * liangent
 * Louperivois
 * Lucas Garczewski
index f23e13a..20aaad6 100644 (file)
@@ -12,6 +12,11 @@ production.
 * MediaWiki will no longer run if register_globals is enabled. It has been
   deprecated for 5 years now, and was removed in PHP 5.4. For more information
   about why, see <https://www.mediawiki.org/wiki/register_globals>.
+* MediaWiki now requires PHP's iconv extension. openSUSE users may need to
+  install the php5-iconv package. Users of other systems may need to add
+  extension=iconv.so to php.ini or recompile PHP without --without-iconv.
+* MediaWiki will no longer function if magic quotes are enabled. It has
+  been deprecated for 5 years now, and was removed in PHP 5.4.
 * The server's canonical hostname is available as $wgServerName, which is
   exposed in both mw.config and ApiQuerySiteInfo.
 * Introduced $wgPagePropsHaveSortkey as a backwards-compatibility switch,
@@ -32,8 +37,43 @@ production.
 * $wgCountTotalSearchHits has been removed. If you're concerned about efficiency
   of search, you should use something like CirrusSearch instead of built in
   search.
+* Users in the 'sysop' group have access to Special:MergeHistory by default.
+* $wgFileStore was removed after having been deprecated in 1.17. Alternative
+  configurations are $wgDeletedDirectory and $wgHashedUploadDirectory.
+* The deprecated $wgUseCommaCount variable has been removed.
+* $wgEnableSorbs and $wgSorbsUrl have been removed.
+* The UserCryptPassword and UserComparePassword hooks are no longer called.
+  Any extensions using them must be updated to use the Password Hashing API.
+* $wgCompiledFiles has been removed.
+* $wgSortSpecialPages was removed, the listing on Special:SpecialPages is
+  now always sorted.
+* $wgHTCPMulticastAddress, $wgHTCPMulticastRouting and $wgHTCPPort were removed.
+* $wgRC2UDPAddress, $wgRC2UDPInterwikiPrefix, $wgRC2UDPOmitBots, $wgRC2UDPPort
+  and $wgRC2UDPPrefix have been removed.
+* The default password type for MediaWiki has been changed from MD5 to PBKDF2.
+  Password hashes will automatically be updated as users log in. If necessary, the
+  old MD5 hashing can be restored by changing $wgPasswordDefault to 'B'. In addition,
+  there is a maintenance script wrapOldPassword.php that can wrap all passwords in
+  PBKDF2 (or the hashing algorithm of your choice) if you don't want to wait for your
+  users to log in.
+* $wgImportSources can now either be a regular array, or an associative map
+  specifying subprojects on the interwiki map of the target wiki, or a mix of
+  the two. Existing configurations will still work.
+* Users must be able to edit through a page's protection to be able to delete it.
+* The default thumb size ($wgDefaultUserOptions['thumbsize']) is now 300px, up from
+  180px. If you have altered the number of entries in $wgThumbLimits for your wiki, you
+  may need to adjust your default user settings to compensate for the index change.
+* $wgDeferredUpdateList is now deprecated, you should use DeferredUpdates::addUpdate()
+  instead.
+* $wgCanonicalLanguageLinks has been removed. Per Google recommendations, we
+  will not send a rel=canonical pointing to a variant-neutral page, however
+  we will send rel=alternate.
 
 === New features in 1.24 ===
+* Added new hook WatchlistEditorBeforeFormRender, allowing subscribers to
+  manipulate the list of pages and/or preload lots of data at once.
+* Added new argument &$link in hook WatchlistEditorBuildRemoveLine, allowing the
+  link to the title to be changed.
 * Added a new hook, "WhatLinksHereProps", to allow extensions to annotate
   WhatLinksHere entries.
 * Added a new hook, "ContentGetParserOutput", to customize parser output for
@@ -106,10 +146,46 @@ production.
   Special:PageLanguage. All pages are set to wiki language by default.
   The feature needs to be enabled with $wgPageLanguageUseDB=true and
   permission needs to be set for 'pagelang'.
-* Upgrade Moment.js to v2.7.0.
+* Upgrade Moment.js to v2.8.3.
 * (bug 67042) Added support for the HTML5 <rtc> tag for East Asian typography.
+* Upgrade Sinon.JS to 1.10.3.
+* Added the es5-shim polyfill for older or non-compliant javascript engines.
+* Upgrade jQuery Cookie to v1.3.1.
+* (bug 20476) Add a "viewsuppressed" user right to be able to view
+  suppressed content but not suppress it ("suppressrevision" right).
+* (bug 66440) The MediaWiki web installer will now allow you to choose the skins
+  to enable (from the ones included in download tarball) and decide which one
+  should be the default.
+* (bug 68085, 68802) Links like [[localInterwikiPrefix:languageCode:pageTitle]],
+  where localInterwikiPrefix is a member of the $wgLocalInterwikis array, will
+  no longer be displayed in the sidebar when $wgInterwikiMagic is true. In a
+  similar way, links like [[localInterwikiPrefix:File:Image.png]] and
+  [[localInterwikiPrefix:Category:Hello]] will now render as regular links, and
+  will not include the file or add the page to the category.
+* New special page, MyLanguages, to redirect users to subpages with localised
+  versions of a page. (Integrated from Extension:Translate)
+* MediaWiki now supports multiple password types, including bcrypt and PBKDF2.
+  The default type can be changed with $wgPasswordDefault and the type
+  configurations can be changed with $wgPasswordConfig.
+* Skins can now define custom styles for default ResourceLoader modules using
+  the $wgResourceModuleSkinStyles global. See the Vector skin for examples.
+* (bug 4488) There is now a preference to watch pages where the user has
+  rollbacked an edit by default.
+* (bug 15484) Users will now be redirected to the login page when they need to
+  log in, rather than being shown a page asking them to log in and having to click
+  another link to actually get to the login page.
+* A JsonContent and JsonContentHandler were added for extensions to extend.
+* (bug 35045) Redirects to sections will now update the URL in browser's address
+  bar using the HTML5 History API. When [[Dog]] redirects to [[Animals#Dog]],
+  the user will now see "Animals#Dog" in their browser instead of "Dog#Dog".
+* API token handling has been rewritten. Any API module using tokens will need
+  to be updated. See the entry below under "Action API internal changes".
+* Added HTMLAutoCompleteSelectField.
+* Added a new hook, "SkinPreloadExistence", to allow extensions to add titles to
+  link existence cache before the page is rendered.
 
 === Bug fixes in 1.24 ===
+* (bug 50572) MediaWiki:Blockip should support gender
 * (bug 49116) Footer copyright notice is now always displayed in user language
   rather than content language (same as copyright notice for editing interface).
 * (bug 62258) A bug was fixed in File::getUnscaledThumb when a height
@@ -134,21 +210,27 @@ production.
 * (bug 65757) MSSQL: Update script drops unnamed constraints to be prepared
   for future updates. Because it's doing so heuristically, it may fail or drop
   wrong constraints.
-
-=== Web API changes in 1.24 ===
+* (bug 67870) wfShellExec() cuts off stdout at multiples of 8192 bytes.
+* $wgRunJobsAsync now works with private wikis (e.g. read requires login).
+* (bugs 57238, 65206) Blank pages can now be directly created.
+* (bug 69789) Title::getContentModel() now loads from the database when
+  necessary instead of incorrectly returning the default content model.
+* (bug 69249) wfBaseConvert() now works around PHP Bug #50175 when using GMP.
+
+=== Action API changes in 1.24 ===
 * action=parse API now supports prop=modules, which provides the list of
   ResourceLoader modules that should be used to enhance the parsed content.
 * action=query&meta=siteinfo&siprop=interwikimap returns a new "protorel"
-  field which is true iff protocol-relative urls can be used to access
+  field which is true if protocol-relative urls can be used to access
   a particular interwiki map entry.
-* ApiQueryLogEvents now provides logpage, which is the page ID from the
+* list=logevents now provides logpage, which is the page ID from the
   logging table, if ids are requested and the user has the permissions.
 * action=edit now requires that appendtext, prependtext, or section=new be used
   when using the 'redirect' parameter, to prevent clients accidentally
   overwriting the target page with the content of the redirect.
-* action=logevents will now return an error if both letitle and leprefix are
+* list=logevents will now return an error if both letitle and leprefix are
   specified.
-* action=logevents has a new parameter, lenamespace, to allow filtering by
+* list=logevents has a new parameter, lenamespace, to allow filtering by
   namespace.
 * action=expandtemplates has a new parameter, prop, and a new output format.
   The old format is still used if prop isn't provided, but this is deprecated.
@@ -160,6 +242,94 @@ production.
 * (bug 60734) Actions that use ApiPageSet (e.g. purge, watch,
   setnotificationtimestamp) will now include continuation information when
   using a generator.
+* Removed 'props' and 'errors' from action=paraminfo, as they have extremely
+  limited use and are generally inaccurate, unmaintained, and impossible to
+  properly maintain.
+* Formats dbg, dump, txt, wddx, and yaml are now deprecated.
+* action=paraminfo now indicates when a parameter is specifying a submodule.
+* The iwurl parameter to prop=iwlinks is deprecated in favor of iwprop=url, for
+  parallelism with prop=langlinks.
+* All tokens should be fetched from action=query&meta=tokens; all other methods
+  of fetching tokens are deprecated. The value needed for meta=tokens's 'type'
+  parameter for each module is documented in the action=help output and is
+  returned from action=paraminfo.
+* New action ClearHasMsg that can be used to clear HasMsg flag.
+* The cmstartsortkey and cmendsortkey parameters to list=categorymembers are
+  deprecated in favor of cmstarthexsortkey and cmendhexsortkey.
+* (bug 63326) Add blockedtimestamp field to output of blockinfo property for
+  the list=allusers and list=users modules.
+
+=== Action API internal changes in 1.24 ===
+* Methods for handling continuation are added to ApiResult, so actions other
+  than query that use generators can easily support continuation.
+* $wgAPIModules (and the related $wgAPIFormatModules, $wgAPIMetaModules,
+  $wgAPIPropModules, and $wgAPIListModules settings) now allow API modules
+  to be specified using a "module spec" array instead of a plain class name.
+  A "module spec" is an associative array containing at least the 'class' key
+  for the module's class, and optionally a 'factory' key for the factory function
+  to use for the module. This is intended for extensions that want control over
+  the instantiation of their API modules, to allow for proper dependency
+  injection.
+* A new param type 'submodule' is available. Parameters of this type will take
+  the list of valid values from the module's ApiModuleManager for the group
+  corresponding to the parameter name.
+* The 'APIGetPossibleErrors' and 'APIGetResultProperties' hooks are no longer used.
+* API token handling has been rewritten. Any API module using tokens will need
+  to be updated:
+  * ApiBase::needsToken now returns a token type instead of boolean true when a
+    token is needed. Returning true will throw an exception. See documentation
+    of that method for details.
+  * Information for the 'token' parameter is automatically set by ApiBase
+    getFinalParams and getFinalParamDescription.
+  * ApiBase::getTokenSalt has been removed.
+  * The hooks APIQueryInfoTokens, APIQueryRevisionsTokens,
+    APIQueryRecentChangesTokens, APIQueryUsersTokens, and
+    ApiTokensGetTokenTypes are deprecated, but are still called to support
+    backwards-compatible token access.
+* ApiBase::validateLimit and ApiBase::validateTimestamp are now protected.
+* The following methods have been deprecated and may be removed in a future
+  release:
+  * ApiBase::getResultProperties
+  * ApiBase::getFinalResultProperties
+  * ApiBase::addTokenProperties
+  * ApiBase::getRequireOnlyOneParameterErrorMessages
+  * ApiBase::getRequireMaxOneParameterErrorMessages
+  * ApiBase::getRequireAtLeastOneParameterErrorMessages
+  * ApiBase::getTitleOrPageIdErrorMessage
+  * ApiBase::getPossibleErrors
+  * ApiBase::getFinalPossibleErrors
+  * ApiBase::parseErrors
+  * ApiQuery::setGeneratorContinue
+  * ApiQueryBase::checkRowCount
+  * ApiQueryBase::titleToKey
+  * ApiQueryBase::keyToTitle
+  * ApiQueryBase::keyPartToTitle
+  * ApiQueryInfo::getTokenFunctions
+  * ApiQueryInfo::resetTokenCache
+  * ApiQueryInfo::getEditToken
+  * ApiQueryInfo::getDeleteToken
+  * ApiQueryInfo::getProtectToken
+  * ApiQueryInfo::getMoveToken
+  * ApiQueryInfo::getBlockToken
+  * ApiQueryInfo::getUnblockToken
+  * ApiQueryInfo::getEmailToken
+  * ApiQueryInfo::getImportToken
+  * ApiQueryInfo::getWatchToken
+  * ApiQueryInfo::getOptionsToken
+  * ApiQueryRecentChanges::getTokenFunctions
+  * ApiQueryRecentChanges::getPatrolToken
+  * ApiQueryRevisions::getTokenFunctions
+  * ApiQueryRevisions::getRollbackToken
+  * ApiQueryUsers::getTokenFunctions
+  * ApiQueryUsers::getUserrightsToken
+* The following classes have been deprecated and may be removed in a future
+  release:
+  * ApiFormatDbg
+  * ApiFormatDump
+  * ApiFormatTxt
+  * ApiFormatWddx
+  * ApiFormatYaml
+  * ApiTokens
 
 === Languages updated in 1.24 ===
 
@@ -180,14 +350,23 @@ changes to languages because of Bugzilla reports.
 * Added pp_sortkey column to page_props table, so pages can be efficiently
   queried and sorted by property value (bug 58032).
   See $wgPagePropsHaveSortkey if you want to postpone the schema change.
-* BREAKING CHANGE: The Modern and Cologne Blue skins were moved out of MediaWiki
-  core to their own respective repositories. See also
-  https://www.mediawiki.org/wiki/Skin:Modern and
-  https://www.mediawiki.org/wiki/Skin:CologneBlue.
+* BREAKING CHANGE: All four built-in MediaWiki skins (Vector, MonoBook, Modern
+  and Cologne Blue) were moved out of MediaWiki core to their own respective
+  repositories. They will be installed with the release tarball, but you must
+  install them separately if installing MediaWiki from source code. A warning
+  message displayed until you do it should guide you through the process. See
+  also <https://www.mediawiki.org/wiki/Manual:Skin_configuration>.
 * BREAKING CHANGE: Skins built for MediaWiki 1.15 and earlier that do not use
   the "headelement" template key are no longer supported. Setting
   $useHeadElement = false; is no longer supported and will not cause old keys
   like "headlinks", "skinnameclass", etc. to be defined.
+* BREAKING CHANGE: The files commonElements.css, commonContent.css and
+  commonInterface.css (in skins/common/) have been removed. Skins may no longer
+  rely on their presence and include them in their style modules. ResourceLoader
+  modules introduced in MediaWiki 1.23 should be loaded instead:
+  - skins/common/commonElements.css  → 'mediawiki.skinning.elements' module
+  - skins/common/commonContent.css   → 'mediawiki.skinning.content' module
+  - skins/common/commonInterface.css → 'mediawiki.skinning.interface' module
 * The deprecated 'SpecialVersionExtensionTypes' hook was removed.
 * (bug 63891) Add 'X-Robots-Tag: noindex' header in action=render pages.
 * SpecialPage no longer supports the syntax for invoking wfSpecial*() functions.
@@ -217,12 +396,74 @@ changes to languages because of Bugzilla reports.
   set of hooks has been removed and replaced by a single new hook
   SpecialPageBeforeFormDisplay.
 * (bug 65781) Removed block warning on included {{Special:Contributions}}
-* Removed Skin::makeGlobalVariablesScript. (deprecated since 1.19)
+* Removed Skin::makeGlobalVariablesScript(). (deprecated since 1.19)
 * Removed MWNamespace::isMain(). (deprecated since 1.19)
 * Removed Preferences::loadOldSearchNs(). (deprecated since 1.19)
 * Removed OutputPage::getStatusMessage(). (deprecated since 1.18)
 * Removed OutputPage::isUserJsAllowed(). (deprecated since 1.18)
 * Removed Title::updateTitleProtection(). (deprecated since 1.19)
+* Removed ParserOptions::setSkin(). (deprecated since 1.19)
+* Removed Title::escapeCanonicalURL(). (deprecated since 1.19)
+* Removed Title::escapeLocalURL(). (deprecated since 1.19)
+* Removed Title::escapeFullURL(). (deprecated since 1.19)
+* Removed User::isValidEmailAddr(). (deprecated since 1.18)
+* Removed Title::getEscapedText(). (deprecated since 1.19)
+* Removed Language::getFallbackLanguageCode(). (deprecated since 1.19)
+* Removed WikiPage::isBigDeletion(). (deprecated since 1.19)
+* Removed MWInit class which contained functions related to a now discontinued
+  PHP compiler called hphpc. (deprecated since 1.22)
+* ApiResult::enableSizeCheck() and disableSizeCheck() are now obsolete.
+* Removed ResourceLoaderGetStartupModules hook. (deprecated since 1.23)
+* Removed getFormFields(), onSubmit() and onSuccess() from FormlessAction, as
+  these were meant specifically for FormAction instead.
+* Removed Action::execute().
+* Removed AjaxAddScript which has been obsolete since ResourceLoader and
+  is unused by any modern extension.
+* Removed maintenance/nextJobDB.php; no longer in use.
+* Removed global function wfViewPrevNext(). (deprecated since 1.19)
+* Removed global function xmlsafe() from Export.php. (moved to OAIRepo extension)
+* Removed Title::userCanRead(). (deprecated since 1.19)
+* Removed maintenance script importTextFile.php. Use edit.php script instead.
+* A _from_namespace field has been added to the templatelinks, pagelinks,
+  and filelinks tables. Run update.php to apply this change to the schema.
+* Removed File::sha1Base36(). (deprecated since 1.19)
+* Removed File::getPropsFromPath(). (deprecated since 1.19)
+* Removed functions blockedPage(), noCreatePermission(), readOnlyPage() and
+  userNotLoggedInPage() from EditPage.php. (deprecated since 1.19)
+* Removed functions getContent(), getPreloadedText(), mergeChangesInto() and
+  setPreloadedText() from EditPage.php. (deprecated since 1.21)
+* Removed global functions wfArrayLookup(), wfArrayMerge(), wfDebugDieBacktrace()
+  and wfTime(). (deprecated since 1.22)
+* Browser support for Internet Explorer 6 and 7 lowered from Grade A to Grade C,
+  meaning that JavaScript is no longer executed in these browser versions.
+* Browser support for Opera 11 lowered from Grade A to Grade C.
+* Removed IEFixes module which existed purely to provide support for MSIE versions
+  below 7 (conditionally loaded only for those browsers).
+* Action::checkCanExecute() no longer has a return value.
+* Removed cleanupForIRC(), loadFromCurRow(), newFromCurRow(), notifyRC2UDP()
+  and sendToUDP() from RecentChange.php. (deprecated since 1.22)
+* Removed EnhancedChangesList::arrow(), sideArrow(), downArrow(), spacerArrow().
+* Removed Xml::namespaceSelector(). (deprecated since 1.19)
+* Removed WikiPage::estimateRevisionCount(). (deprecated since 1.19)
+* MYSQL: Enum item added to "major MIME type" columns.
+  Running update.php on MySQL < v5.1 may result in heavy processing.
+* RSS and Atom feeds generated by MediaWiki no longer include a fallback
+  stylesheet. It was ignored by most browsers these days anyway.
+* SpecialSearchNoResults hook has been removed. SpecialSearchResults is now
+  called unconditionally.
+* TablePager::getBody() is now 'final' and can't be overridden in subclasses.
+* TablePager::getBody() is deprecated, use getBodyOutput() or getFullOutput().
+* Added $outputPage parameter to the SkinTemplateGetLanguageLink hook.
+* log_page for move log entries store the original page ID, rather than that
+  of the new redirect page. This is not retroactive.
+* LCStoreAccel was removed. $wgLocalisationCacheConf can no longer be set to
+  use this store class.
+* Html::infoBox() no longer accepts paths relative to skins/common/images/.
+* Deprecated defunct Skin::getCommonStylePath().
+* Some extensions had their ResourceLoader modules depend on the "mediawiki"
+  and "jquery" modules. In the past, this behavior was undefined, now it will
+  throw an error.
+* Removed BagOStuff::replace(). (deprecated since 1.23)
 
 ==== Renamed classes ====
 * CLDRPluralRuleConverter_Expression to CLDRPluralRuleConverterExpression
@@ -266,6 +507,11 @@ changes to languages because of Bugzilla reports.
 * IPBlockForm - Use SpecialBlock directly
 * WatchlistEditor - Use SpecialEditWatchlist directly
 * FormatExif - Use FormatMetadata directly
+* RevertFileAction - Use RevertAction directly
+* HistoryPage - Use HistoryAction directly
+* RawPage - Use RawAction directly
+* StubContLang - Use Language::factory() instead
+* XMLReader2 - Use XMLReader directly
 
 == Compatibility ==
 
diff --git a/api.php b/api.php
index e55ec75..2a6a095 100644 (file)
--- a/api.php
+++ b/api.php
@@ -34,7 +34,7 @@
 define( 'MW_API', true );
 
 // Bail if PHP is too low
-if ( !function_exists( 'version_compare' ) || version_compare( phpversion(), '5.3.2' ) < 0 ) {
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
        // We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
        require dirname( __FILE__ ) . '/includes/PHPVersionError.php';
        wfPHPVersionError( 'api.php' );
@@ -104,12 +104,17 @@ if ( $wgAPIRequestLog ) {
                wfTimestamp( TS_MW ),
                $endtime - $starttime,
                $wgRequest->getIP(),
-               $_SERVER['HTTP_USER_AGENT']
+               $wgRequest->getHeader( 'User-agent' )
        );
        $items[] = $wgRequest->wasPosted() ? 'POST' : 'GET';
        if ( $processor ) {
-               $module = $processor->getModule();
-               if ( $module->mustBePosted() ) {
+               try {
+                       $manager = $processor->getModuleManager();
+                       $module = $manager->getModule( $wgRequest->getVal( 'action' ), 'action' );
+               } catch ( Exception $ex ) {
+                       $module = null;
+               }
+               if ( !$module || $module->mustBePosted() ) {
                        $items[] = "action=" . $wgRequest->getVal( 'action' );
                } else {
                        $items[] = wfArrayToCgi( $wgRequest->getValues() );
diff --git a/assets/file-type-icons/COPYING b/assets/file-type-icons/COPYING
new file mode 100644 (file)
index 0000000..136530a
--- /dev/null
@@ -0,0 +1,43 @@
+The icons used here are derived from the crystalsvg icons in the the
+pics/crystalsvg/ directory of kdelibs-3.4.0 they were modified on 2005-05-15
+by Ævar Arnfjörð Bjarmason for use in MediaWiki.
+
+What follows is the contents of the LICENSE.crystalsvg file found in the pics/
+subdirectory of kdelibs-3.4.0:
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+This copyright and license notice covers all CrystalSVG images.
+Note the license notice contains an add-on.
+********************************************************************************
+KDE Crystal theme icons.
+Copyright (C) 2002 and following years KDE Artists
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation,
+version 2.1 of the License.
+This library 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
+Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+    **** NOTE THIS ADD-ON ****
+The GNU Lesser General Public License or LGPL is written for software libraries
+in the first place. We expressly want the LGPL to be valid for this artwork
+library too.
+KDE Crystal theme icons is a special kind of software library, it is an
+artwork library, it's elements can be used in a Graphical User Interface, or
+GUI.
+Source code, for this library means:
+ - for vectors svg;
+ - for pixels, if applicable, the multi-layered formats xcf or psd, or
+otherwise png.
+The LGPL in some sections obliges you to make the files carry
+notices. With images this is in some cases impossible or hardly useful.
+With this library a notice is placed at a prominent place in the directory
+containing the elements. You may follow this practice.
+The exception in section 6 of the GNU Lesser General Public License covers
+the use of elements of this art library in a GUI.
+kde-artists [at] kde.org
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/assets/file-type-icons/fileicon-c.png b/assets/file-type-icons/fileicon-c.png
new file mode 100644 (file)
index 0000000..0d603b7
Binary files /dev/null and b/assets/file-type-icons/fileicon-c.png differ
diff --git a/assets/file-type-icons/fileicon-cpp.png b/assets/file-type-icons/fileicon-cpp.png
new file mode 100644 (file)
index 0000000..123688f
Binary files /dev/null and b/assets/file-type-icons/fileicon-cpp.png differ
diff --git a/assets/file-type-icons/fileicon-deb.png b/assets/file-type-icons/fileicon-deb.png
new file mode 100644 (file)
index 0000000..87ca3fa
Binary files /dev/null and b/assets/file-type-icons/fileicon-deb.png differ
diff --git a/assets/file-type-icons/fileicon-djvu.png b/assets/file-type-icons/fileicon-djvu.png
new file mode 100644 (file)
index 0000000..1da2276
Binary files /dev/null and b/assets/file-type-icons/fileicon-djvu.png differ
diff --git a/assets/file-type-icons/fileicon-djvu.xcf b/assets/file-type-icons/fileicon-djvu.xcf
new file mode 100644 (file)
index 0000000..8043dcd
Binary files /dev/null and b/assets/file-type-icons/fileicon-djvu.xcf differ
diff --git a/assets/file-type-icons/fileicon-dvi.png b/assets/file-type-icons/fileicon-dvi.png
new file mode 100644 (file)
index 0000000..f37878d
Binary files /dev/null and b/assets/file-type-icons/fileicon-dvi.png differ
diff --git a/assets/file-type-icons/fileicon-exe.png b/assets/file-type-icons/fileicon-exe.png
new file mode 100644 (file)
index 0000000..dc020eb
Binary files /dev/null and b/assets/file-type-icons/fileicon-exe.png differ
diff --git a/assets/file-type-icons/fileicon-h.png b/assets/file-type-icons/fileicon-h.png
new file mode 100644 (file)
index 0000000..339bf02
Binary files /dev/null and b/assets/file-type-icons/fileicon-h.png differ
diff --git a/assets/file-type-icons/fileicon-html.png b/assets/file-type-icons/fileicon-html.png
new file mode 100644 (file)
index 0000000..f28f8a2
Binary files /dev/null and b/assets/file-type-icons/fileicon-html.png differ
diff --git a/assets/file-type-icons/fileicon-iso.png b/assets/file-type-icons/fileicon-iso.png
new file mode 100644 (file)
index 0000000..c73d229
Binary files /dev/null and b/assets/file-type-icons/fileicon-iso.png differ
diff --git a/assets/file-type-icons/fileicon-java.png b/assets/file-type-icons/fileicon-java.png
new file mode 100644 (file)
index 0000000..a1b4f22
Binary files /dev/null and b/assets/file-type-icons/fileicon-java.png differ
diff --git a/assets/file-type-icons/fileicon-mid.png b/assets/file-type-icons/fileicon-mid.png
new file mode 100644 (file)
index 0000000..ce2bebb
Binary files /dev/null and b/assets/file-type-icons/fileicon-mid.png differ
diff --git a/assets/file-type-icons/fileicon-mov.png b/assets/file-type-icons/fileicon-mov.png
new file mode 100644 (file)
index 0000000..952de1f
Binary files /dev/null and b/assets/file-type-icons/fileicon-mov.png differ
diff --git a/assets/file-type-icons/fileicon-o.png b/assets/file-type-icons/fileicon-o.png
new file mode 100644 (file)
index 0000000..f3523d9
Binary files /dev/null and b/assets/file-type-icons/fileicon-o.png differ
diff --git a/assets/file-type-icons/fileicon-ogg.png b/assets/file-type-icons/fileicon-ogg.png
new file mode 100644 (file)
index 0000000..ef4d801
Binary files /dev/null and b/assets/file-type-icons/fileicon-ogg.png differ
diff --git a/assets/file-type-icons/fileicon-ogg.xcf b/assets/file-type-icons/fileicon-ogg.xcf
new file mode 100644 (file)
index 0000000..a91024b
Binary files /dev/null and b/assets/file-type-icons/fileicon-ogg.xcf differ
diff --git a/assets/file-type-icons/fileicon-pdf.png b/assets/file-type-icons/fileicon-pdf.png
new file mode 100644 (file)
index 0000000..8c8da92
Binary files /dev/null and b/assets/file-type-icons/fileicon-pdf.png differ
diff --git a/assets/file-type-icons/fileicon-ps.png b/assets/file-type-icons/fileicon-ps.png
new file mode 100644 (file)
index 0000000..e872833
Binary files /dev/null and b/assets/file-type-icons/fileicon-ps.png differ
diff --git a/assets/file-type-icons/fileicon-psd.png b/assets/file-type-icons/fileicon-psd.png
new file mode 100644 (file)
index 0000000..598f190
Binary files /dev/null and b/assets/file-type-icons/fileicon-psd.png differ
diff --git a/assets/file-type-icons/fileicon-rm.png b/assets/file-type-icons/fileicon-rm.png
new file mode 100644 (file)
index 0000000..81dbe0b
Binary files /dev/null and b/assets/file-type-icons/fileicon-rm.png differ
diff --git a/assets/file-type-icons/fileicon-rpm.png b/assets/file-type-icons/fileicon-rpm.png
new file mode 100644 (file)
index 0000000..1903aac
Binary files /dev/null and b/assets/file-type-icons/fileicon-rpm.png differ
diff --git a/assets/file-type-icons/fileicon-svg.png b/assets/file-type-icons/fileicon-svg.png
new file mode 100644 (file)
index 0000000..b782113
Binary files /dev/null and b/assets/file-type-icons/fileicon-svg.png differ
diff --git a/assets/file-type-icons/fileicon-tar.png b/assets/file-type-icons/fileicon-tar.png
new file mode 100644 (file)
index 0000000..e5fd1b7
Binary files /dev/null and b/assets/file-type-icons/fileicon-tar.png differ
diff --git a/assets/file-type-icons/fileicon-tex.png b/assets/file-type-icons/fileicon-tex.png
new file mode 100644 (file)
index 0000000..a437284
Binary files /dev/null and b/assets/file-type-icons/fileicon-tex.png differ
diff --git a/assets/file-type-icons/fileicon-ttf.png b/assets/file-type-icons/fileicon-ttf.png
new file mode 100644 (file)
index 0000000..1ed4e74
Binary files /dev/null and b/assets/file-type-icons/fileicon-ttf.png differ
diff --git a/assets/file-type-icons/fileicon-txt.png b/assets/file-type-icons/fileicon-txt.png
new file mode 100644 (file)
index 0000000..9e988e7
Binary files /dev/null and b/assets/file-type-icons/fileicon-txt.png differ
diff --git a/assets/file-type-icons/fileicon-xcf.png b/assets/file-type-icons/fileicon-xcf.png
new file mode 100644 (file)
index 0000000..1037b50
Binary files /dev/null and b/assets/file-type-icons/fileicon-xcf.png differ
diff --git a/assets/file-type-icons/fileicon.png b/assets/file-type-icons/fileicon.png
new file mode 100644 (file)
index 0000000..59696a3
Binary files /dev/null and b/assets/file-type-icons/fileicon.png differ
diff --git a/assets/licenses/cc-0.png b/assets/licenses/cc-0.png
new file mode 100644 (file)
index 0000000..9d3fe5f
Binary files /dev/null and b/assets/licenses/cc-0.png differ
diff --git a/assets/licenses/cc-by-nc-sa.png b/assets/licenses/cc-by-nc-sa.png
new file mode 100644 (file)
index 0000000..0d24a71
Binary files /dev/null and b/assets/licenses/cc-by-nc-sa.png differ
diff --git a/assets/licenses/cc-by-sa.png b/assets/licenses/cc-by-sa.png
new file mode 100644 (file)
index 0000000..518fb64
Binary files /dev/null and b/assets/licenses/cc-by-sa.png differ
diff --git a/assets/licenses/cc-by.png b/assets/licenses/cc-by.png
new file mode 100644 (file)
index 0000000..9cca2f9
Binary files /dev/null and b/assets/licenses/cc-by.png differ
diff --git a/assets/licenses/gnu-fdl.png b/assets/licenses/gnu-fdl.png
new file mode 100644 (file)
index 0000000..3feaf57
Binary files /dev/null and b/assets/licenses/gnu-fdl.png differ
diff --git a/assets/licenses/public-domain.png b/assets/licenses/public-domain.png
new file mode 100644 (file)
index 0000000..ebf0107
Binary files /dev/null and b/assets/licenses/public-domain.png differ
diff --git a/assets/mediawiki.png b/assets/mediawiki.png
new file mode 100644 (file)
index 0000000..8c42118
Binary files /dev/null and b/assets/mediawiki.png differ
diff --git a/assets/poweredby_mediawiki_88x31.png b/assets/poweredby_mediawiki_88x31.png
new file mode 100644 (file)
index 0000000..30e1d2e
Binary files /dev/null and b/assets/poweredby_mediawiki_88x31.png differ
diff --git a/docs/export-0.9.xsd b/docs/export-0.9.xsd
new file mode 100644 (file)
index 0000000..d5e7b99
--- /dev/null
@@ -0,0 +1,292 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+       This is an XML Schema description of the format
+       output by MediaWiki's Special:Export system.
+
+       Version 0.2 adds optional basic file upload info support,
+       which is used by our OAI export/import submodule.
+
+       Version 0.3 adds some site configuration information such
+       as a list of defined namespaces.
+
+       Version 0.4 adds per-revision delete flags, log exports,
+       discussion threading data, a per-page redirect flag, and
+       per-namespace capitalization.
+
+       Version 0.5 adds byte count per revision.
+
+       Version 0.6 adds a separate namespace tag, and resolves the
+       redirect target and adds a separate sha1 tag for each revision.
+
+       Version 0.7 adds a unique identity constraint for both page and
+       revision identifiers. See also bug 4220.
+       Fix type for <ns> from "positiveInteger" to "nonNegativeInteger" to allow 0
+       Moves <logitem> to its right location.
+       Add parentid to revision.
+       Fix type for <id> within <contributor> to "nonNegativeInteger"
+
+       Version 0.8 adds support for a <model> and a <format> tag for
+       each revision. See contenthandler.txt.
+
+       Version 0.9 adds the database name to the site information.
+
+       The canonical URL to the schema document is:
+       http://www.mediawiki.org/xml/export-0.9.xsd
+
+       Use the namespace:
+       http://www.mediawiki.org/xml/export-0.9/
+-->
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+               xmlns:mw="http://www.mediawiki.org/xml/export-0.9/"
+               targetNamespace="http://www.mediawiki.org/xml/export-0.9/"
+               elementFormDefault="qualified">
+
+       <annotation>
+               <documentation xml:lang="en">
+                       MediaWiki's page export format
+               </documentation>
+       </annotation>
+
+       <!-- Need this to reference xml:lang -->
+       <import namespace="http://www.w3.org/XML/1998/namespace"
+                       schemaLocation="http://www.w3.org/2001/xml.xsd" />
+
+       <!-- Our root element -->
+       <element name="mediawiki" type="mw:MediaWikiType">
+               <!-- Page ID contraint, see bug 4220 -->
+               <unique name="PageIDConstraint">
+                       <selector xpath="mw:page" />
+                       <field xpath="mw:id" />
+               </unique>
+               <!-- Revision ID contraint, see bug 4220 -->
+               <unique name="RevIDConstraint">
+                       <selector xpath="mw:page/mw:revision" />
+                       <field xpath="mw:id" />
+               </unique>
+       </element>
+
+       <complexType name="MediaWikiType">
+               <sequence>
+                       <element name="siteinfo" type="mw:SiteInfoType"
+                                        minOccurs="0" maxOccurs="1" />
+                       <element name="page" type="mw:PageType"
+                                        minOccurs="0" maxOccurs="unbounded" />
+                       <element name="logitem" type="mw:LogItemType"
+                                        minOccurs="0" maxOccurs="unbounded" />
+               </sequence>
+               <attribute name="version" type="string" use="required" />
+               <attribute ref="xml:lang" use="required" />
+       </complexType>
+
+       <complexType name="SiteInfoType">
+               <sequence>
+                       <element name="sitename" type="string" minOccurs="0" />
+            <element name="dbname" type="string" minOccurs="0" />
+                       <element name="base" type="anyURI" minOccurs="0" />
+                       <element name="generator" type="string" minOccurs="0" />
+                       <element name="case" type="mw:CaseType" minOccurs="0" />
+                       <element name="namespaces" type="mw:NamespacesType" minOccurs="0" />
+               </sequence>
+       </complexType>
+
+       <simpleType name="CaseType">
+               <restriction base="NMTOKEN">
+                       <!-- Cannot have two titles differing only by case of first letter. -->
+                       <!-- Default behavior through 1.5, $wgCapitalLinks = true -->
+                       <enumeration value="first-letter" />
+
+                       <!-- Complete title is case-sensitive -->
+                       <!-- Behavior when $wgCapitalLinks = false -->
+                       <enumeration value="case-sensitive" />
+
+                       <!-- Cannot have non-case senstitive titles eg [[FOO]] == [[Foo]] -->
+                       <!-- Not yet implemented as of MediaWiki 1.18 -->
+                       <enumeration value="case-insensitive" />
+               </restriction>
+       </simpleType>
+
+       <simpleType name="DeletedFlagType">
+               <restriction base="NMTOKEN">
+                       <enumeration value="deleted" />
+               </restriction>
+       </simpleType>
+
+       <complexType name="NamespacesType">
+               <sequence>
+                       <element name="namespace" type="mw:NamespaceType"
+                                        minOccurs="0" maxOccurs="unbounded" />
+               </sequence>
+       </complexType>
+
+       <complexType name="NamespaceType">
+               <simpleContent>
+                       <extension base="string">
+                               <attribute name="key" type="integer" />
+                               <attribute name="case" type="mw:CaseType" />
+                       </extension>
+               </simpleContent>
+       </complexType>
+
+       <complexType name="RedirectType">
+               <simpleContent>
+                       <extension base="string">
+                               <attribute name="title" type="string" />
+                       </extension>
+               </simpleContent>
+       </complexType>
+
+       <simpleType name="ContentModelType">
+               <restriction base="string">
+                       <pattern value="[a-zA-Z][-+./a-zA-Z0-9]*" />
+               </restriction>
+       </simpleType>
+
+       <simpleType name="ContentFormatType">
+               <restriction base="string">
+                       <pattern value="[a-zA-Z][-+.a-zA-Z0-9]*/[a-zA-Z][-+.a-zA-Z0-9]*" />
+               </restriction>
+       </simpleType>
+
+       <complexType name="PageType">
+               <sequence>
+                       <!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
+                       <element name="title" type="string" />
+
+                       <!-- Namespace in canonical form -->
+                       <element name="ns" type="nonNegativeInteger" />
+
+                       <!-- optional page ID number -->
+                       <element name="id" type="positiveInteger" />
+
+                       <!-- flag if the current revision is a redirect -->
+                       <element name="redirect" type="mw:RedirectType" minOccurs="0" maxOccurs="1" />
+
+                       <!-- comma-separated list of string tokens, if present -->
+                       <element name="restrictions" type="string" minOccurs="0" />
+
+                       <!-- Zero or more sets of revision or upload data -->
+                       <choice minOccurs="0" maxOccurs="unbounded">
+                               <element name="revision" type="mw:RevisionType" />
+                               <element name="upload" type="mw:UploadType" />
+                       </choice>
+
+                       <!-- Zero or One sets of discussion threading data -->
+                       <element name="discussionthreadinginfo" minOccurs="0" maxOccurs="1" type="mw:DiscussionThreadingInfo" />
+               </sequence>
+       </complexType>
+
+       <complexType name="RevisionType">
+               <sequence>
+                       <element name="id" type="positiveInteger" />
+                       <element name="parentid" type="positiveInteger" minOccurs="0" />
+                       <element name="timestamp" type="dateTime" />
+                       <element name="contributor" type="mw:ContributorType" />
+                       <element name="minor" minOccurs="0" maxOccurs="1" />
+                       <element name="comment" type="mw:CommentType" minOccurs="0" maxOccurs="1" />
+                       <element name="text" type="mw:TextType" />
+                       <element name="sha1" type="string" />
+                       <element name="model" type="mw:ContentModelType" />
+                       <element name="format" type="mw:ContentFormatType" />
+               </sequence>
+       </complexType>
+
+       <complexType name="LogItemType">
+               <sequence>
+                       <element name="id" type="positiveInteger" />
+                       <element name="timestamp" type="dateTime" />
+                       <element name="contributor" type="mw:ContributorType" />
+                       <element name="comment" type="mw:CommentType" minOccurs="0" />
+                       <element name="type" type="string" />
+                       <element name="action" type="string" />
+                       <element name="text" type="mw:LogTextType" minOccurs="0" maxOccurs="1" />
+                       <element name="logtitle" type="string" minOccurs="0" maxOccurs="1" />
+                       <element name="params" type="mw:LogParamsType" minOccurs="0" maxOccurs="1" />
+               </sequence>
+       </complexType>
+
+       <complexType name="CommentType">
+               <simpleContent>
+                       <extension base="string">
+                               <!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
+                               <attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
+                       </extension>
+               </simpleContent>
+       </complexType>
+
+       <complexType name="TextType">
+               <simpleContent>
+                       <extension base="string">
+                               <attribute ref="xml:space" use="optional" default="preserve" />
+                               <!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
+                               <attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
+                               <!-- This isn't a good idea; we should be using "ID" instead of "NMTOKEN" -->
+                               <!-- However, "NMTOKEN" is strictest definition that is both compatible with existing -->
+                               <!-- usage ([0-9]+) and with the "ID" type. -->
+                               <attribute name="id" type="NMTOKEN" />
+                               <attribute name="bytes" use="optional" type="nonNegativeInteger" />
+                       </extension>
+               </simpleContent>
+       </complexType>
+
+       <complexType name="LogTextType">
+               <simpleContent>
+                       <extension base="string">
+                               <!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
+                               <attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
+                       </extension>
+               </simpleContent>
+       </complexType>
+
+       <complexType name="LogParamsType">
+               <simpleContent>
+                       <extension base="string">
+                               <attribute ref="xml:space" use="optional" default="preserve" />
+                       </extension>
+               </simpleContent>
+       </complexType>
+
+       <complexType name="ContributorType">
+               <sequence>
+                       <element name="username" type="string" minOccurs="0" />
+                       <element name="id" type="nonNegativeInteger" minOccurs="0" />
+
+                       <element name="ip" type="string" minOccurs="0" />
+               </sequence>
+               <!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
+               <attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
+       </complexType>
+
+       <complexType name="UploadType">
+               <sequence>
+                       <!-- Revision-style data... -->
+                       <element name="timestamp" type="dateTime" />
+                       <element name="contributor" type="mw:ContributorType" />
+                       <element name="comment" type="string" minOccurs="0" />
+
+                       <!-- Filename. (Using underscores, not spaces. No 'File:' namespace marker.) -->
+                       <element name="filename" type="string" />
+
+                       <!-- URI at which this resource can be obtained -->
+                       <element name="src" type="anyURI" />
+
+                       <element name="size" type="positiveInteger" />
+
+                       <!-- TODO: add other metadata fields -->
+               </sequence>
+       </complexType>
+
+       <!-- Discussion threading data for LiquidThreads -->
+       <complexType name="DiscussionThreadingInfo">
+               <sequence>
+                       <element name="ThreadSubject" type="string" />
+                       <element name="ThreadParent" type="positiveInteger" />
+                       <element name="ThreadAncestor" type="positiveInteger" />
+                       <element name="ThreadPage" type="string" />
+                       <element name="ThreadID" type="positiveInteger" />
+                       <element name="ThreadAuthor" type="string" />
+                       <element name="ThreadEditStatus" type="string" />
+                       <element name="ThreadType" type="string" />
+               </sequence>
+       </complexType>
+
+</schema>
index 591f675..fd47d13 100644 (file)
@@ -1,15 +1,18 @@
-<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.8/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.8/ http://www.mediawiki.org/xml/export-0.8.xsd" version="0.8" xml:lang="en">
+<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">
   
   <!-- Optional global configuration info -->
   <siteinfo>
     <!-- Site name, as set in $wgSitename -->
     <sitename>DemoWiki</sitename>
+
+    <!-- Database name, as set in $wgDBname -->
+    <dbname>demowiki</dbname>
     
     <!-- Forgot where you got this set? -->
     <base>http://example.com/wiki/Main_Page</base>
     
     <!-- Source software version -->
-    <generator>MediaWiki 1.20</generator>
+    <generator>MediaWiki 1.24</generator>
     
     <!-- Title case sensitivity options of the wiki this data came from -->
     <!-- May be 'first-letter', 'case-sensitive', or 'case-insensitive' -->
index f2260cf..d5fb2af 100644 (file)
@@ -333,11 +333,6 @@ $ig: Gallery, an object of one of the gallery classes (inheriting from
 ImageGalleryBase)
 $html: HTML generated by the gallery
 
-'AjaxAddScript': Called in output page just before the initialisation
-of the javascript ajax engine. The hook is only called when ajax
-is enabled ( $wgUseAjax = true; ).
-&$output: OutputPage object
-
 'AlternateEdit': Before checking if a user can edit a page and before showing
 the edit form ( EditPage::edit() ). This is triggered on &action=edit.
 $editPage: the EditPage object
@@ -398,16 +393,6 @@ descriptions.
 &$module: ApiBase Module object
 &$desc: Array of parameter descriptions
 
-'APIGetResultProperties': Use this hook to modify the properties in a module's
-result.
-&$module: ApiBase Module object
-&$properties: Array of properties
-
-'APIGetPossibleErrors': Use this hook to modify the module's list of possible
-errors.
-$module: ApiBase Module object
-&$possibleErrors: Array of possible errors
-
 'APIQueryAfterExecute': After calling the execute() method of an
 action=query submodule. Use this to extend core API modules.
 &$module: Module object
@@ -417,36 +402,39 @@ an action=query submodule. Use this to extend core API modules.
 &$module: Module object
 &$resultPageSet: ApiPageSet object
 
-'APIQueryInfoTokens': Use this hook to add custom tokens to prop=info. Every
-token has an action, which will be used in the intoken parameter and in the
-output (actiontoken="..."), and a callback function which should return the
-token, or false if the user isn't allowed to obtain it. The prototype of the
-callback function is func($pageid, $title), where $pageid is the page ID of the
-page the token is requested for and $title is the associated Title object. In
-the hook, just add your callback to the $tokenFunctions array and return true
-(returning false makes no sense).
+'APIQueryInfoTokens': DEPRECATED! Use ApiQueryTokensRegisterTypes instead.
+Use this hook to add custom tokens to prop=info. Every token has an action,
+which will be used in the intoken parameter and in the output
+(actiontoken="..."), and a callback function which should return the token, or
+false if the user isn't allowed to obtain it. The prototype of the callback
+function is func($pageid, $title), where $pageid is the page ID of the page the
+token is requested for and $title is the associated Title object. In the hook,
+just add your callback to the $tokenFunctions array and return true (returning
+false makes no sense).
 $tokenFunctions: array(action => callback)
 
-'APIQueryRevisionsTokens': Use this hook to add custom tokens to prop=revisions.
-Every token has an action, which will be used in the rvtoken parameter and in
-the output (actiontoken="..."), and a callback function which should return the
-token, or false if the user isn't allowed to obtain it. The prototype of the
-callback function is func($pageid, $title, $rev), where $pageid is the page ID
-of the page associated to the revision the token is requested for, $title the
+'APIQueryRevisionsTokens': DEPRECATED! Use ApiQueryTokensRegisterTypes instead.
+Use this hook to add custom tokens to prop=revisions. Every token has an
+action, which will be used in the rvtoken parameter and in the output
+(actiontoken="..."), and a callback function which should return the token, or
+false if the user isn't allowed to obtain it. The prototype of the callback
+function is func($pageid, $title, $rev), where $pageid is the page ID of the
+page associated to the revision the token is requested for, $title the
 associated Title object and $rev the associated Revision object. In the hook,
 just add your callback to the $tokenFunctions array and return true (returning
 false makes no sense).
 $tokenFunctions: array(action => callback)
 
-'APIQueryRecentChangesTokens': Use this hook to add custom tokens to
-list=recentchanges. Every token has an action, which will be used in the rctoken
-parameter and in the output (actiontoken="..."), and a callback function which
-should return the token, or false if the user isn't allowed to obtain it. The
-prototype of the callback function is func($pageid, $title, $rc), where $pageid
-is the page ID of the page associated to the revision the token is requested
-for, $title the associated Title object and $rc the associated RecentChange
-object. In the hook, just add your callback to the $tokenFunctions array and
-return true (returning false makes no sense).
+'APIQueryRecentChangesTokens': DEPRECATED! Use ApiQueryTokensRegisterTypes instead.
+Use this hook to add custom tokens to list=recentchanges. Every token has an
+action, which will be used in the rctoken parameter and in the output
+(actiontoken="..."), and a callback function which should return the token, or
+false if the user isn't allowed to obtain it. The prototype of the callback
+function is func($pageid, $title, $rc), where $pageid is the page ID of the
+page associated to the revision the token is requested for, $title the
+associated Title object and $rc the associated RecentChange object. In the
+hook, just add your callback to the $tokenFunctions array and return true
+(returning false makes no sense).
 $tokenFunctions: array(action => callback)
 
 'APIQuerySiteInfoGeneralInfo': Use this hook to add extra information to the
@@ -458,13 +446,19 @@ $module: the current ApiQuerySiteInfo module
 sites statistics information.
 &$results: array of results, add things here
 
-'APIQueryUsersTokens': Use this hook to add custom token to list=users. Every
-token has an action, which will be used in the ustoken parameter and in the
-output (actiontoken="..."), and a callback function which should return the
-token, or false if the user isn't allowed to obtain it. The prototype of the
-callback function is func($user) where $user is the User object. In the hook,
-just add your callback to the $tokenFunctions array and return true (returning
-false makes no sense).
+'ApiQueryTokensRegisterTypes': Use this hook to add additional token types to
+action=query&meta=tokens. Note that most modules will probably be able to use
+the 'csrf' token instead of creating their own token types.
+&$salts: array( type => salt to pass to User::getEditToken() )
+
+'APIQueryUsersTokens': DEPRECATED! Use ApiQueryTokensRegisterTypes instead.
+Use this hook to add custom token to list=users. Every token has an action,
+which will be used in the ustoken parameter and in the output
+(actiontoken="..."), and a callback function which should return the token, or
+false if the user isn't allowed to obtain it. The prototype of the callback
+function is func($user) where $user is the User object. In the hook, just add
+your callback to the $tokenFunctions array and return true (returning false
+makes no sense).
 $tokenFunctions: array(action => callback)
 
 'ApiMain::onException': Called by ApiMain::executeActionWithErrorHandling() when
@@ -478,8 +472,8 @@ key for the array that represents the service data. In this data array, the
 key-value-pair identified by the apiLink key is required.
 &$apis: array of services
 
-'ApiTokensGetTokenTypes': Use this hook to extend action=tokens with new token
-types.
+'ApiTokensGetTokenTypes': DEPRECATED! Use ApiQueryTokensRegisterTypes instead.
+Use this hook to extend action=tokens with new token types.
 &$tokenTypes: supported token types in format 'type' => callback function
 used to retrieve this type of tokens.
 
@@ -869,6 +863,14 @@ $name: name of the special page, e.g. 'Watchlist'
 &$join_conds: join conditions for the tables
 $opts: FormOptions for this request
 
+'LoginUserMigrated': Called during login to allow extensions the opportunity to
+inform a user that their username doesn't exist for a specific reason, instead
+of letting the login form give the generic error message that the account does
+not exist. For example, when the account has been renamed or deleted.
+$user: the User object being authenticated against.
+&$msg: the message identifier for abort reason, or an array to pass a message
+  key and parameters.
+
 'Collation::factory': Called if $wgCategoryCollation is an unknown collation.
 $collationName: Name of the collation in question
 &$collationObject: Null. Replace with a subclass of the Collation class that
@@ -1645,6 +1647,13 @@ $code: language code
 &$alldata: The localisation data from core and extensions
 &purgeBlobs: whether to purge/update the message blobs via MessageBlobStore::clear()
 
+'LocalisationCacheRecacheFallback': Called for each language when merging
+fallback data into the cache.
+$cache: The LocalisationCache object
+$code: language code
+&$alldata: The localisation data from core and extensions. Note some keys may
+  be omitted if they won't be merged into the final result.
+
 'LocalisationChecksBlacklist': When fetching the blacklist of
 localisation checks.
 &$blacklist: array of checks to blacklist. See the bottom of
@@ -1761,6 +1770,30 @@ caches.
 $title: name of the page changed.
 $text: new contents of the page.
 
+'MimeMagicInit': Before processing the list mapping MIME types to media types
+and the list mapping MIME types to file extensions.
+As an extension author, you are encouraged to submit patches to MediaWiki's
+core to add new MIME types to mime.types.
+$mimeMagic: Instance of MimeMagic.
+  Use $mimeMagic->addExtraInfo( $stringOfInfo );
+  for adding new MIME info to the list.
+  Use $mimeMagic->addExtraTypes( $stringOfTypes );
+  for adding new MIME types to the list.
+
+'MimeMagicImproveFromExtension': Allows MW extensions to further improve the
+MIME type detected by considering the file extension.
+$mimeMagic: Instance of MimeMagic.
+$ext: File extension.
+&$mime: MIME type (in/out).
+
+'MimeMagicGuessFromContent': Allows MW extensions guess the MIME by content.
+$mimeMagic: Instance of MimeMagic.
+&$head: First 1024 bytes of the file in a string (in - Do not alter!).
+&$tail: More or equal than last 65558 bytes of the file in a string
+  (in - Do not alter!).
+$file: File path.
+&$mime: MIME type (out).
+
 'ModifyExportQuery': Modify the query used by the exporter.
 $db: The database object to be queried.
 &$tables: Tables in the query.
@@ -1768,13 +1801,6 @@ $db: The database object to be queried.
 &$opts: Options for the query.
 &$join_conds: Join conditions for the query.
 
-'MonoBookTemplateToolboxEnd': DEPRECATED. Called by Monobook skin after toolbox
-links have been rendered (useful for adding more). Note: this is only run for
-the Monobook skin. To add items to the toolbox you should use the
-SkinTemplateToolboxEnd hook instead, which works for all "SkinTemplate"-type
-skins.
-$tools: array of tools
-
 'BaseTemplateToolbox': Called by BaseTemplate when building the $toolbox array
 and returning it for the skin to output. You can add items to the toolbox while
 still letting the skin make final decisions on skin-specific markup conventions
@@ -2133,17 +2159,11 @@ $oldSessionID: old session id
 $newSessionID: new session id
 
 'ResourceLoaderGetConfigVars': Called at the end of
-ResourceLoaderStartUpModule::getConfig(). Use this to export static
+ResourceLoaderStartUpModule::getConfigSettings(). Use this to export static
 configuration variables to JavaScript. Things that depend on the current page
 or request state must be added through MakeGlobalVariablesScript instead.
 &$vars: array( variable name => value )
 
-'ResourceLoaderGetStartupModules': DEPRECATED. Run once the startup module is being
-generated. This allows you to add modules to the startup module. This hook
-should be used sparingly since any module added here will be loaded on all
-pages. This hook is useful if you want to make code available to module loader
-scripts.
-
 'ResourceLoaderRegisterModules': Right before modules information is required,
 such as when responding to a resource
 loader request or generating HTML output.
@@ -2291,6 +2311,11 @@ $type: 'normal' or 'history' for old/diff views
 the MediaWiki icon but plain text instead.
 $skin: Skin object
 
+'SkinPreloadExistence': Supply titles that should be added to link existence
+cache before the page is rendered.
+&$titles: Array of Title objects
+$skin: Skin object
+
 'SkinSubPageSubtitle': At the beginning of Skin::subPageSubtitle().
 &$subpages: Subpage links HTML
 $skin: Skin object
@@ -2309,8 +2334,9 @@ $nav_urls: array of tabs
 which the actual html is constructed.
 &$languageLink: array containing data about the link. The following keys can be
   modified: href, text, title, class, lang, hreflang. Each of them is a string.
-$languageLinkTitle: Title object belonging to the external language link
-$title: Title object of the page the link belongs to
+$languageLinkTitle: Title object belonging to the external language link.
+$title: Title object of the page the link belongs to.
+$outputPage: The OutputPage object the links are built from.
 
 To alter the structured navigation links in SkinTemplates, there are three
 hooks called in different spots:
@@ -2355,11 +2381,6 @@ $dummy: Called when SkinTemplateToolboxEnd is used from a BaseTemplate skin,
   dummy parameter with "$dummy=false" in their code and return without echoing
   any HTML to avoid creating duplicate toolbox items.
 
-'SkinVectorStyleModules': Called when defining the list of module styles to be
-loaded by the Vector skin.
-$skin: SkinVector object
-&$styles: Array of module names whose style will be loaded for the skin
-
 'SoftwareInfo': Called by Special:Version for returning information about the
 software.
 $software: The array of software in format 'name' => 'version'. See
@@ -2374,7 +2395,7 @@ $sp: SpecialPage object, for context
 &$fields: Current HTMLForm fields
 
 'SpecialContributionsBeforeMainOutput': Before the form on Special:Contributions
-$id: User id number, only provided for backwards-compatability
+$id: User id number, only provided for backwards-compatibility
 $user: User object representing user contributions are being fetched for
 $sp: SpecialPage instance, providing context
 
@@ -2517,16 +2538,11 @@ $specialSearch: SpecialSearch object ($this)
 $output: $wgOut
 $term: Search term specified by the user
 
-'SpecialSearchResults': Called before search result display when there are
-matches.
+'SpecialSearchResults': Called before search result display
 $term: string of search term
 &$titleMatches: empty or SearchResultSet object
 &$textMatches: empty or SearchResultSet object
 
-'SpecialSearchNoResults': Called before search result display when there are no
-matches.
-$term: string of search term
-
 'SpecialStatsAddExtra': Add extra statistic at the end of Special:Statistics.
 &$extraStats: Array to save the new stats
   ( $extraStats['<name of statistic>'] => <value>; )
@@ -2725,11 +2741,11 @@ string &$error: output: message key for message to show if upload canceled by
   returning false. May also be an array, where the first element is the message
   key and the remaining elements are used as parameters to the message.
 
-'UploadVerifyFile': extra file verification, based on mime type, etc. Preferred
+'UploadVerifyFile': extra file verification, based on MIME type, etc. Preferred
 in most cases over UploadVerification.
 object $upload: an instance of UploadBase, with all info about the upload
-string $mime: The uploaded file's mime type, as detected by MediaWiki. Handlers
-  will typically only apply for specific mime types.
+string $mime: The uploaded file's MIME type, as detected by MediaWiki. Handlers
+  will typically only apply for specific MIME types.
 object &$error: output: true if the file is valid. Otherwise, an indexed array
   representing the problem with the file, where the first element is the message
   key and the remaining elements are used as parameters to the message.
@@ -2771,26 +2787,9 @@ messages!" message, return false to not delete it.
 $user: User (object) that will clear the message
 $oldid: ID of the talk page revision being viewed (0 means the most recent one)
 
-'UserComparePasswords': Called when checking passwords, return false to
-override the default password checks.
-&$hash: String of the password hash (from the database)
-&$password: String of the plaintext password the user entered
-&$userId: Integer of the user's ID or Boolean false if the user ID was not
-  supplied
-&$result: If the hook returns false, this Boolean value will be checked to
-  determine if the password was valid
-
 'UserCreateForm': change to manipulate the login form
 $template: SimpleTemplate instance for the form
 
-'UserCryptPassword': Called when hashing a password, return false to implement
-your own hashing method.
-&$password: String of the plaintext password to encrypt
-&$salt: String of the password salt or Boolean false if no salt is provided
-&$wgPasswordSalt: Boolean of whether the salt is used in the default hashing
-  method
-&$hash: If the hook returns false, this String will be used as the hash
-
 'UserEffectiveGroups': Called in User::getEffectiveGroups().
 $user: User to get groups for
 &$groups: Current effective groups
@@ -2900,6 +2899,15 @@ to be switched to HTTPS.
 $user: User in question.
 &$https: Boolean whether $user should be switched to HTTPS.
 
+'UserResetAllOptions': Called in User::resetOptions() when user preferences
+have been requested to be reset. This hook can be used to exclude certain
+options from being reset even when the user has requested all prefs to be reset,
+because certain options might be stored in the user_properties database table
+despite not being visible and editable via Special:Preferences.
+$user: the User (object) whose preferences are being reset
+&$newOptions: array of new (site default) preferences
+$options: array of the user's old preferences
+$resetKinds: array containing the kinds of preferences to reset
 
 'UserRetrieveNewTalks': Called when retrieving "You have new messages!"
 message(s).
@@ -2940,6 +2948,11 @@ invalidated and GetExtendedMetadata hook called again).
 $timestamp: The timestamp metadata was generated
 $file: The file the metadata is for
 
+'UserMailerChangeReturnPath': Called to generate a VERP return address
+when UserMailer sends an email, with a bounce handling extension.
+$to: Array of MailAddress objects for the recipients
+&$returnPath: The return address string
+
 'WantedPages::getQueryInfo': Called in WantedPagesPage::getQueryInfo(), can be
 used to alter the SQL query which gets the list of wanted pages.
 &$wantedPages: WantedPagesPage object
@@ -2954,12 +2967,18 @@ $page: WikiPage object to be watched
 $user: user that watched
 $page: WikiPage object watched
 
+'WatchlistEditorBeforeFormRender': Before building the Special:EditWatchlist
+form, used to manipulate the list of pages or preload data based on that list.
+&$watchlistInfo: array of watchlisted pages in
+  [namespaceId => ['title1' => 1, 'title2' => 1]] format
+
 'WatchlistEditorBuildRemoveLine': when building remove lines in
 Special:Watchlist/edit.
 &$tools: array of extra links
 $title: Title object
 $redirect: whether the page is a redirect
 $skin: Skin object
+&$link: HTML link to title
 
 'WebRequestPathInfoRouter': While building the PathRouter to parse the
 REQUEST_URI.
index 374bab2..a7b0c47 100644 (file)
@@ -1,12 +1,12 @@
 MEDIAWIKI_LOAD_URL ?= http://localhost/w/load.php
 
-kss: nodecheck
-# FIXME: Use more up-to-date Ruby version
-
+kss: kssnodecheck
 # Generates CSS of mediawiki.ui and mediawiki.ui.button using ResourceLoader, then applies it to the
 # KSS style guide
        $(eval KSS_RL_TMP := $(shell mktemp /tmp/tmp.XXXXXXXXXX))
-       @curl -sG "${MEDIAWIKI_LOAD_URL}?modules=mediawiki.legacy.shared|mediawiki.legacy.commonPrint|mediawiki.ui|mediawiki.ui.button&only=styles" > $(KSS_RL_TMP)
+# Keep module names in strict alphabetical order, so CSS loads in the same order as ResourceLoader's addModuleStyles does; this can affect rendering.
+# See OutputPage::makeResourceLoaderLink.
+       @curl -sG "${MEDIAWIKI_LOAD_URL}?modules=mediawiki.legacy.commonPrint|mediawiki.legacy.shared|mediawiki.ui|mediawiki.ui.anchor|mediawiki.ui.button|mediawiki.ui.checkbox|mediawiki.ui.input&only=styles" > $(KSS_RL_TMP)
        @node_modules/.bin/kss-node ../../resources/src/mediawiki.ui static/ --css $(KSS_RL_TMP) -t styleguide-template
        @rm $(KSS_RL_TMP)
 
@@ -15,5 +15,5 @@ kssopen: kss
        @command -v xdg-open >/dev/null 2>&1 || { open ${PWD}/static/index.html; exit 0; }
        @xdg-open ${PWD}/static/index.html
 
-nodecheck:
-       @scripts/nodecheck.sh
+kssnodecheck:
+       @scripts/kss-node-check.sh
diff --git a/docs/kss/scripts/kss-node-check.sh b/docs/kss/scripts/kss-node-check.sh
new file mode 100755 (executable)
index 0000000..84ee1c4
--- /dev/null
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+if command -v npm > /dev/null ; then
+  npm install
+else
+  # If npm isn't installed, but kss-node is, exit normally.
+  # This allows setting it up on one machine, and running it on
+  # another (e.g. Tools Labs execution nodes) that doesn't have npm
+  # installed.  However, "npm install" still needs to be run
+  # occasionally to keep kss updated.
+
+  KSS_NODE="${BASH_SOURCE%/*}/../node_modules/.bin/kss-node"
+  if ! [ -x "$KSS_NODE" ] ; then
+    echo "Neither kss-node nor npm are installed."
+    echo "To install npm, see http://nodejs.org/"
+    echo "When npm is installed, the Makefile can automatically"
+    echo "install kss-node."
+    exit 1
+  fi
+fi
diff --git a/docs/kss/scripts/nodecheck.sh b/docs/kss/scripts/nodecheck.sh
deleted file mode 100755 (executable)
index 3ee0f83..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-if command -v npm > /dev/null ; then
-  npm install
-else
-  echo "You need to install Node.JS!"
-  echo "See http://nodejs.org/"
-  exit 1
-fi
index cb95197..933260e 100644 (file)
@@ -2,61 +2,85 @@
 <html class="no-js" lang="en">
 <head>
        <meta charset="utf-8">
-       <title>MediaWiki Living Styleguide</title>
+       <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="description" content="">
        <meta name="generator" content="kss-node" />
-       <meta name="viewport" content="width=device-width">
+
+       <title>MediaWiki Living Styleguide</title>
+
        <link rel="stylesheet" href="public/kss.css">
        <link rel="stylesheet" href="public/style.css">
 </head>
 <body><div id="kss-wrapper">
        <header id="kss-header">
-               <hgroup><h1>MediaWiki Living Styleguide</h1></hgroup>
+               <div class="container">
+                       <hgroup><h1>Mediawiki.UI</h1></hgroup>
+               </div>
        </header>
-       <nav class="content">
-               <ul>
-               <li><a href="index.html">0.0: Overview</a></li>
-               {{#eachRoot}}
-               <li>
-                       <a href="section-{{reference}}.html">{{reference}}.0: {{header}}</a>
-               </li>
-               {{/eachRoot}}
-               </ul>
-       </nav>
-       <article>
-               {{#if overview}}
-                       {{html overview}}
-               {{else}}
-                       {{#eachSection rootNumber}}
-                       <section>
-                               {{#whenDepth 1}}
-                                       <h1>{{ reference }}.0 - {{ header }}</h1>
-                               {{else}}
-                                       {{#whenDepth 2}}
-                                       <h2>{{ reference }} - {{ header }}</h2>
-                                       {{/whenDepth}}
-                                       {{#whenDepth 3}}
-                                       <h3>{{ reference }} - {{ header }}</h3>
+
+       <div class="container">
+               <nav>
+                       <ul>
+                               <li><a href="index.html"><span>0.0</span> Overview</a></li>
+                               {{#eachRoot}}
+                                       <li>
+                                               <a href="section-{{ reference }}.html">
+                                                       <span>{{ reference }}.0</span> {{ header }}
+                                               </a>
+                                               <ul>
+                                               {{#eachSection reference}}
+                                                       {{#whenDepth  2}}
+                                                               <li>
+                                                                       <a href="section-{{../../reference}}.html#section-{{ reference }}">
+                                                                               <span>{{ reference }}</span>
+                                                                               {{ header }}
+                                                                       </a>
+                                                               </li>
+                                                       {{/whenDepth}}
+                                               {{/eachSection}}
+                                               </ul>
+                                       </li>
+                               {{/eachRoot}}
+                       </ul>
+               </nav>
+
+               <div class="content">
+                       {{#if overview}}
+                               {{html overview}}
+                       {{else}}
+                               {{#eachSection rootNumber}}
+                               <div>
+                                       {{#whenDepth 1}}
+                                               <h1>{{ reference }}.0 {{ header }}</h1>
+                                       {{else}}
+                                               {{#whenDepth 2}}
+                                               <a name="section-{{ reference }}"></a>
+                                               <h2>{{ reference }} {{ header }}</h2>
+                                               {{/whenDepth}}
+                                               {{#whenDepth 3}}
+                                               <h3>{{ reference }} {{ header }}</h3>
+                                               {{/whenDepth}}
                                        {{/whenDepth}}
-                               {{/whenDepth}}
-                               {{#ifAny markup modifiers}}
-                                               <div>{{html description}}</div>
-                                               <h4>Default styling</h4>
-                                               <blockquote>{{modifierMarkup}}</blockquote>
-                                               {{#eachModifier}}
-                                                       <h4>{{name}}</h4>
-                                                       {{html description}}
-                                                       <blockquote>{{modifierMarkup}}</blockquote>
-                                               {{/eachModifier}}
-                                               <pre class="prettyprint lang-html">{{markup}}</pre>
-                               {{else}}
-                                               {{#if description}}
-                                                       {{html description}}
-                                               {{/if}}
-                               {{/ifAny}}
-                       </section>
-                       {{/eachSection}}
-               {{/if}}
-       </article>
+                                       {{#ifAny markup modifiers}}
+                                                       <div>{{html description}}</div>
+                                                       <div class="example">
+                                                               <pre class="prettyprint lang-html">{{markup}}</pre>
+                                                               <blockquote>{{modifierMarkup}}</blockquote>
+                                                       </div>
+                                                       {{#eachModifier}}
+                                                               <h4>{{name}}</h4>
+                                                               {{html description}}
+                                                               <blockquote>{{modifierMarkup}}</blockquote>
+                                                       {{/eachModifier}}
+                                       {{else}}
+                                                       {{#if description}}
+                                                               {{html description}}
+                                                       {{/if}}
+                                       {{/ifAny}}
+                               </div>
+                               {{/eachSection}}
+                       {{/if}}
+               </div>
+       </div>
 </div></body>
 </html>
index 431303d..c30322e 100644 (file)
-header {
-       padding: .8em 16px 0;
+.container {
+       width: 100%;
 }
 
 nav {
-       float: left;
-       width: 200px;
+       display: none;
 }
 
-article {
-       margin-left: 250px;
+.content {
+       .example {
+               blockquote {
+                       margin-top: 20px;
+               }
+       }
 }
 
-.content.kss-no-margin {
+body {
        margin: 0;
-}
+       padding: 0;
+       padding-top: 3px;
+       padding-bottom: 40px;
 
-// FIXME: Remove when typography module in mediawiki-ui
-body {
+       // FIXME: Remove when typography module in mediawiki-ui
        font-family: "Nimbus Sans L", "Liberation Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
 }
-h1,h2,h3,h4,h5 {
-       font-family: "DejaVu Serif", Georgia, serif;
+
+.kss-no-margin {
+       // FIXME: Is this being used anywhere? Remove if not.
+       margin: 0;
+}
+
+.container {
+       margin: 0 auto;
+       display: -webkit-flex;
+       display: flex;
+
+}
+
+header {
+       padding: 0;
+       margin: 0;
+       border-bottom: 1px solid #eee;
+
+       hgroup {
+               min-width: 149px;
+
+               h1 {
+                       padding: 16px 28px;
+                       font-size: 15px;
+                       text-transform: uppercase;
+                       margin: 0;
+                       width: 92px;
+                       border-right: 1px solid #eee;
+               }
+       }
+}
+
+nav {
+       -webkit-flex: initial;
+       flex: initial;
+       min-width: 139px;
+       margin-top: 25px;
+
+       ul {
+               list-style: none;
+               padding: 0;
+
+               li {
+                       margin-left: 10px;
+                       margin-bottom: 20px;
+
+                       a {
+                               text-transform: uppercase;
+                               color: #aaa;
+                               font-size: 12px;
+                               font-weight: bold;
+                               text-decoration: none;
+
+                               &:hover {
+                                       color: #538DF8;
+                               }
+
+                               span {
+                                       display: inline-block;
+                                       width: 35px;
+                               }
+                       }
+
+                       ul {
+                               li {
+                                       margin: 0;
+                               }
+
+                               li a {
+                                       text-transform: none;
+                                       font-weight: normal;
+                               }
+                       }
+               }
+       }
+}
+
+.content {
+       -webkit-flex: 1;
+       flex: 1;
+
+       h1, h2, h3, h4, h5, h6, p {
+               margin-left: 20px;
+       }
+
+       p {
+               width: 338px;
+       }
+
+       h1 {
+               margin-bottom: 0;
+       }
+
+       .example {
+               display: -webkit-flex;
+               display: flex;
+               flex-wrap: wrap;
+
+               pre {
+                       -webkit-flex: initial;
+                       flex: initial;
+                       background: #f8f8f8;
+                       padding: 20px;
+                       color: #999;
+                       word-wrap: break-word;
+                       // word-wrap in pre not affecting Firefox, so add white-space.
+                       white-space: pre-wrap;
+                       float: left;
+                       margin: 0;
+                       margin-right: 22px;
+               }
+
+               blockquote {
+                       -webkit-flex: 1;
+                       flex: 1;
+                       display: block;
+                       margin: 0;
+                       margin-left: 20px;
+               }
+       }
+}
+
+@media (min-width: 768px) {
+       nav {
+               display: block;
+               width: 100px;
+       }
+
+       @columnWidth: (768px - 100px ) / 2;
+       .example {
+               pre,
+               blockquote {
+                       width: @columnWidth;
+               }
+       }
+}
+
+@media (min-width: 980px) {
+       nav {
+               width: auto;
+       }
+
+       .content {
+               margin-left: 30px;
+       }
+
+       .container {
+               width: 980px;
+       }
+
+       .example {
+               pre {
+                       width: 338px;
+               }
+               blockquote {
+                       width: auto;
+               }
+       }
 }
diff --git a/docs/uidesign/confirmable.html b/docs/uidesign/confirmable.html
new file mode 100644 (file)
index 0000000..d035821
--- /dev/null
@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<html lang="en" dir="ltr">
+<head>
+       <meta charset="utf-8">
+       <!--
+       The jquery.confirmable module uses some additional modules and files
+       for internationalization support. These are omitted here for simplicity.
+       -->
+       <script type="text/javascript" src="../../resources/lib/jquery/jquery.js"></script>
+       <link rel="stylesheet" href="../../resources/src/jquery/jquery.confirmable.css">
+       <script type="text/javascript" src="../../resources/src/jquery/jquery.confirmable.js"></script>
+       <style>
+       body {
+               font: small sans-serif;
+       }
+       .mw-rollback-link a,
+       .mw-unwatch-link a,
+       .mw-thanks-thank-link a {
+               background: #ccf;
+       }
+       </style>
+</head>
+<body>
+       <h2>Introduction</h2>
+
+       <p>The jquery.confirmable module provides a simple inline confirmation script for potentially destructive or uncancellable actions.</p>
+
+       <p>Possible uses include confirmable "rollback" links in histories, confirmable "unwatch" links on watchlists, or confirmable "thanks" links (provided by the Echo extension).</p>
+
+       <p>Shown below is a demo of how each of those could work on history and watchlist entries, in an LTR and RTL language. The enhanced links are highlighted in blue.</p>
+
+       <h2>Examples</h2>
+
+       <h3>LTR (English)</h3>
+
+       <p>Watchlist:</p>
+
+       <ul lang="en" dir="ltr">
+               <li class="mw-line-even mw-changeslist-line-not-watched">
+                       (<a href="#">diff</a> | <a href="#">hist</a>)
+                       <span class="mw-changeslist-separator">. .</span>
+                       <span class="mw-title"><a href="#" class="mw-changeslist-title">Example page</a></span>; <span class="mw-changeslist-date">13:38</span>
+                       <span class="mw-changeslist-separator">. .</span>
+                       <span class="mw-plusminus-neg">(-130)</span>
+                       <span class="mw-changeslist-separator">. .</span>
+                       <a href="#" class="mw-userlink">Example user</a>
+                       <span class="mw-usertoollinks">(<a href="#">Talk</a> | <a href="#">contribs</a> | <a href="#">block</a>)</span>
+                       <span class="comment">(example edit)</span>
+                       <span class="mw-rollback-link">[<a href="https://www.mediawiki.org/wiki/Random_ideas_for_rollback_to_be_shelved_and_forgotten_about">rollback</a>]</span>
+                       (<span class="mw-unwatch-link"><a href="#">unwatch</a></span>)
+               </li>
+       </ul>
+
+       <p>History:</p>
+
+       <ul lang="en" dir="ltr">
+               <li>
+                       <span class="mw-history-histlinks">(cur | <a href="#">prev</a>)</span>
+                       <input type="radio" style="visibility: hidden;" /><input type="radio" checked />
+                       <a href="#" class="mw-changeslist-date">13:38, 28 October 2013</a>
+                       <span class='history-user'>
+                               <a href="#" class="mw-userlink">Example user</a>
+                               <span class="mw-usertoollinks">(<a href="#">Talk</a> | <a href="#">contribs</a> | <a href="#">block</a>)</span>
+                       </span>
+                       <span class="mw-changeslist-separator">. .</span>
+                       <span class="history-size">(1,654 bytes)</span>
+                       <span class="mw-plusminus-neg">(-130)</span>
+                       <span class="mw-changeslist-separator">. .</span>
+                       <span class="comment">(example edit)</span>
+                       (<span class="mw-rollback-link"><a href="https://www.mediawiki.org/wiki/Random_ideas_for_rollback_to_be_shelved_and_forgotten_about">rollback 1 edit</a></span> | <span class="mw-history-undo"><a href="#">undo</a></span> | <span class="mw-thanks-thank-link"><a href="#">thank</a></span>)
+               </li>
+       </ul>
+
+       <script type="text/javascript">
+               $( 'ul[lang="en"] .mw-rollback-link a' )
+                       .confirmable({ i18n: { confirm: 'Are you sure you want to rollback?' } });
+               $( 'ul[lang="en"] .mw-unwatch-link a' )
+                       .confirmable({ handler: function(){ alert('Unwatched!') } });
+               $( 'ul[lang="en"] .mw-thanks-thank-link a' )
+                       .confirmable({ handler: function(){ alert('Thanked!') } });
+       </script>
+
+       <h3>RTL (Hebrew)</h3>
+       <!-- All of the Hebrew text below has been basically pulled out of my hat. -->
+
+       <p>Watchlist:</p>
+
+       <ul lang="he" dir="rtl">
+               <li class="mw-line-even mw-changeslist-line-not-watched">
+                       (<a href="#">הבדל</a> | <a href="#">היסטוריה</a>)
+                       <span class="mw-changeslist-separator">. .</span>
+                       <span class="mw-title"><a href="#" class="mw-changeslist-title">דף דוגמה</a></span>; <span class="mw-changeslist-date">13:38</span>
+                       <span class="mw-changeslist-separator">. .</span>
+                       <span class="mw-plusminus-neg">(-57)</span>
+                       <span class="mw-changeslist-separator">. .</span>
+                       <a href="#" class="mw-userlink">דוגמא אדם</a>
+                       <span class="mw-usertoollinks">(<a href="#">שיחה</a> | <a href="#">תרומות</a> | <a href="#">חסימה</a>)</span>
+                       <span class="comment">(עריכה לדוגמה)</span>
+                       <span class="mw-rollback-link">[<a href="https://www.mediawiki.org/wiki/Random_ideas_for_rollback_to_be_shelved_and_forgotten_about">שחזור</a>]</span>
+                       (<span class="mw-unwatch-link"><a href="#">הפסקת מעקב</a></span>)
+               </li>
+       </ul>
+
+       <p>History:</p>
+
+       <ul lang="he" dir="rtl">
+               <li>
+                       <span class="mw-history-histlinks">(נוכחית | <a href="#">קודמת</a>)</span>
+                       <input type="radio" style="visibility: hidden;" /><input type="radio" checked />
+                       <a href="#" class="mw-changeslist-date">23:41, 12 במאי 2012</a>
+                       <span class='history-user'>
+                               <a href="#" class="mw-userlink">דוגמא אדם</a>
+                               <span class="mw-usertoollinks">(<a href="#">שיחה</a> | <a href="#">תרומות</a> | <a href="#">חסימה</a>)</span>
+                       </span>
+                       <span class="mw-changeslist-separator">. .</span>
+                       <span class="history-size">(1,762 בתים)</span>
+                       <span class="mw-plusminus-neg">(-57)</span>
+                       <span class="mw-changeslist-separator">. .</span>
+                       <span class="comment">(עריכה לדוגמה)</span>
+                       (<span class="mw-rollback-link"><a href="https://www.mediawiki.org/wiki/Random_ideas_for_rollback_to_be_shelved_and_forgotten_about">שחזור עריכה אחת</a></span> | <span class="mw-history-undo"><a href="#">ביטול</a></span> | <span class="mw-thanks-thank-link"><a href="#">תודה</a></span>)
+               </li>
+       </ul>
+
+       <script type="text/javascript">
+               var hebrewI18n = {
+                       confirm: 'האם ברצונך להמשיך?',
+                       yes: 'כן',
+                       no: 'לא',
+               }
+
+               $( 'ul[lang="he"] .mw-rollback-link a' )
+                       .confirmable({ i18n: $.extend( {}, hebrewI18n, { confirm: 'האם ברצונך לשחזר?' } ) });
+               $( 'ul[lang="he"] .mw-unwatch-link a' )
+                       .confirmable({ i18n: hebrewI18n, handler: function(){ alert('Unwatched!') } });
+               $( 'ul[lang="he"] .mw-thanks-thank-link a' )
+                       .confirmable({ i18n: hebrewI18n, handler: function(){ alert('Thanked!') } });
+       </script>
+       <style type="text/css">
+               /* This is normally handled by CSSJanus. */
+               ul[dir=rtl] .jquery-confirmable-button {
+                       margin-left: 0;
+                       margin-right: 1ex;
+               }
+       </style>
+</body>
+</html>
+
index a285a5b..51c1b55 100644 (file)
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en" dir="ltr">
 <head>
-       <link rel="stylesheet" href="../../skins/common/shared.css">
+       <link rel="stylesheet" href="../../resources/src/mediawiki.legacy/shared.css">
 </head>
 <body style="font-size: small;">
 
index b665001..bad230e 100644 (file)
@@ -1,23 +1,19 @@
-Extensions (such as the hieroglyphic module WikiHiero) are distributed
-separately. Drop them into this extensions directory and enable as
-per the extension's directions.
+Extensions are distributed separately. Drop them into this directory and enable
+as per the extension's installation instructions.
 
-You can find a list of extensions and documentation on the MediaWiki website:
-    https://www.mediawiki.org/wiki/Category:Extensions
+You can find a list of extensions and documentation at
+<https://www.mediawiki.org/wiki/Category:Extensions>.
 
 
-If you are a developer, you want to fetch the extension tree in another
+If you are a developer, you might want to fetch the extension tree in another
 directory and make a symbolic link:
 
- mediawiki/extensions$ ln -s ../../extensions-trunk/FooBarExt
+ mediawiki/extensions$ ln -s ../../extensions-trunk/FooBar
 
 Most extensions are available through Git:
-    https://gerrit.wikimedia.org/r/#/admin/projects/
+    https://gerrit.wikimedia.org/r/#/admin/projects/?filter=mediawiki%252Fextensions%252F
     https://git.wikimedia.org/project/mediawiki
 
-Old extensions are on Subversion:
-    https://svn.wikimedia.org/svnroot/mediawiki/trunk/extensions/
-
 
 Please note that under POSIX systems (Linux...), parent of a symbolic path
 refers to the link source, NOT to the target! You should check the env
index ca30bbc..e6d6c11 100644 (file)
@@ -1,5 +1,2 @@
 If uploads are enabled in the wiki, files will be put in subdirectories
 under here.
-
-Note to upgraders: as of MediaWiki 1.5, the images used in the user
-interface have been moved to skins/common/images.
index 6f449c6..dcd171f 100644 (file)
@@ -47,6 +47,7 @@ $wgArticlePath = false; # Don't let a "/*" article path clober our action path
 $wgActionPaths = array( "$wgUploadPath/" );
 
 wfImageAuthMain();
+wfProfileOut( 'img_auth.php' );
 wfLogProfilingData();
 // Commit and close up!
 $factory = wfGetLBFactory();
@@ -114,7 +115,7 @@ function wfImageAuthMain() {
        // be under a folder that has the source file name.
        if ( $zone === 'thumb' || $zone === 'transcoded' ) {
                $name = wfBaseName( dirname( $path ) );
-               $filename = $repo->getZonePath( $zone ) . substr( $path, strlen( "/".$zone ) );
+               $filename = $repo->getZonePath( $zone ) . substr( $path, strlen( "/" . $zone ) );
                // Check to see if the file exists
                if ( !$repo->fileExists( $filename ) ) {
                        wfForbidden( 'img-auth-accessdenied', 'img-auth-nofile', $filename );
index c9ca128..9bc92be 100644 (file)
@@ -47,15 +47,22 @@ class AjaxDispatcher {
         */
        private $args;
 
+       /**
+        * @var Config
+        */
+       private $config;
+
        /**
         * Load up our object with user supplied data
         */
-       function __construct() {
+       function __construct( Config $config ) {
                wfProfileIn( __METHOD__ );
 
+               $this->config = $config;
+
                $this->mode = "";
 
-               if ( ! empty( $_GET["rs"] ) ) {
+               if ( !empty( $_GET["rs"] ) ) {
                        $this->mode = "get";
                }
 
@@ -66,7 +73,7 @@ class AjaxDispatcher {
                switch ( $this->mode ) {
                        case 'get':
                                $this->func_name = isset( $_GET["rs"] ) ? $_GET["rs"] : '';
-                               if ( ! empty( $_GET["rsargs"] ) ) {
+                               if ( !empty( $_GET["rsargs"] ) ) {
                                        $this->args = $_GET["rsargs"];
                                } else {
                                        $this->args = array();
@@ -74,7 +81,7 @@ class AjaxDispatcher {
                                break;
                        case 'post':
                                $this->func_name = isset( $_POST["rs"] ) ? $_POST["rs"] : '';
-                               if ( ! empty( $_POST["rsargs"] ) ) {
+                               if ( !empty( $_POST["rsargs"] ) ) {
                                        $this->args = $_POST["rsargs"];
                                } else {
                                        $this->args = array();
@@ -95,17 +102,17 @@ class AjaxDispatcher {
         * BEWARE! Data are passed as they have been supplied by the user,
         * they should be carefully handled in the function processing the
         * request.
+        *
+        * @param User $user
         */
-       function performAction() {
-               global $wgAjaxExportList, $wgUser;
-
+       function performAction( User $user ) {
                if ( empty( $this->mode ) ) {
                        return;
                }
 
                wfProfileIn( __METHOD__ );
 
-               if ( ! in_array( $this->func_name, $wgAjaxExportList ) ) {
+               if ( !in_array( $this->func_name, $this->config->get( 'AjaxExportList' ) ) ) {
                        wfDebug( __METHOD__ . ' Bad Request for unknown function ' . $this->func_name . "\n" );
 
                        wfHttpError(
@@ -113,7 +120,7 @@ class AjaxDispatcher {
                                'Bad Request',
                                "unknown function " . $this->func_name
                        );
-               } elseif ( !User::isEveryoneAllowed( 'read' ) && !$wgUser->isAllowed( 'read' ) ) {
+               } elseif ( !User::isEveryoneAllowed( 'read' ) && !$user->isAllowed( 'read' ) ) {
                        wfHttpError(
                                403,
                                'Forbidden',
index a3808a5..8e9f490 100644 (file)
@@ -70,12 +70,19 @@ class AjaxResponse {
         */
        private $mText;
 
+       /**
+        * @var Config
+        */
+       private $mConfig;
+
        /**
         * @param string|null $text
+        * @param Config|null $config
         */
-       function __construct( $text = null ) {
+       function __construct( $text = null, Config $config = null ) {
                $this->mCacheDuration = null;
                $this->mVary = null;
+               $this->mConfig = $config ?: ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
 
                $this->mDisabled = false;
                $this->mText = '';
@@ -132,7 +139,7 @@ class AjaxResponse {
         * @param string $text
         */
        function addText( $text ) {
-               if ( ! $this->mDisabled && $text ) {
+               if ( !$this->mDisabled && $text ) {
                        $this->mText .= $text;
                }
        }
@@ -141,7 +148,7 @@ class AjaxResponse {
         * Output text
         */
        function printText() {
-               if ( ! $this->mDisabled ) {
+               if ( !$this->mDisabled ) {
                        print $this->mText;
                }
        }
@@ -150,8 +157,6 @@ class AjaxResponse {
         * Construct the header and output it
         */
        function sendHeaders() {
-               global $wgUseSquid, $wgUseESI;
-
                if ( $this->mResponseCode ) {
                        $n = preg_replace( '/^ *(\d+)/', '\1', $this->mResponseCode );
                        header( "Status: " . $this->mResponseCode, true, (int)$n );
@@ -170,12 +175,12 @@ class AjaxResponse {
                        # and tell the client to always check with the squid. Otherwise,
                        # tell the client to use a cached copy, without a way to purge it.
 
-                       if ( $wgUseSquid ) {
+                       if ( $this->mConfig->get( 'UseSquid' ) ) {
                                # Expect explicit purge of the proxy cache, but require end user agents
                                # to revalidate against the proxy on each visit.
                                # Surrogate-Control controls our Squid, Cache-Control downstream caches
 
-                               if ( $wgUseESI ) {
+                               if ( $this->mConfig->get( 'UseESI' ) ) {
                                        header( 'Surrogate-Control: max-age=' . $this->mCacheDuration . ', content="ESI/1.0"' );
                                        header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
                                } else {
index 67f9a1c..d79b2b1 100644 (file)
@@ -31,22 +31,23 @@ $wgAutoloadLocalClasses = array(
        # Includes
        'AjaxDispatcher' => 'includes/AjaxDispatcher.php',
        'AjaxResponse' => 'includes/AjaxResponse.php',
-       'AlphabeticPager' => 'includes/Pager.php',
        'AtomFeed' => 'includes/Feed.php',
        'AuthPlugin' => 'includes/AuthPlugin.php',
        'AuthPluginUser' => 'includes/AuthPlugin.php',
        'Autopromote' => 'includes/Autopromote.php',
-       'BaseTemplate' => 'includes/SkinTemplate.php',
        'Block' => 'includes/Block.php',
+       'BloomCache' => 'includes/cache/bloom/BloomCache.php',
+       'BloomCacheRedis' => 'includes/cache/bloom/BloomCacheRedis.php',
+       'BloomFilterTitleHasLogs' => 'includes/cache/bloom/BloomFilters.php',
        'CacheHelper' => 'includes/CacheHelper.php',
        'Category' => 'includes/Category.php',
-       'Categoryfinder' => 'includes/Categoryfinder.php',
+       'CategoryFinder' => 'includes/CategoryFinder.php',
        'CategoryViewer' => 'includes/CategoryViewer.php',
-       'ChangesFeed' => 'includes/ChangesFeed.php',
        'ChangeTags' => 'includes/ChangeTags.php',
        'ChannelFeed' => 'includes/Feed.php',
        'Collation' => 'includes/Collation.php',
        'CollationCkb' => 'includes/Collation.php',
+       'CollationEt' => 'includes/Collation.php',
        'ConcatenatedGzipHistoryBlob' => 'includes/HistoryBlob.php',
        'Cookie' => 'includes/Cookie.php',
        'CookieJar' => 'includes/Cookie.php',
@@ -67,7 +68,7 @@ $wgAutoloadLocalClasses = array(
        'DumpOutput' => 'includes/Export.php',
        'DumpPipeOutput' => 'includes/Export.php',
        'EditPage' => 'includes/EditPage.php',
-       'EmailNotification' => 'includes/UserMailer.php',
+       'EmptyBloomCache' => 'includes/cache/bloom/BloomCache.php',
        'Fallback' => 'includes/Fallback.php',
        'FauxRequest' => 'includes/WebRequest.php',
        'FauxResponse' => 'includes/WebResponse.php',
@@ -84,6 +85,7 @@ $wgAutoloadLocalClasses = array(
        'Html' => 'includes/Html.php',
        'HtmlFormatter' => 'includes/HtmlFormatter.php',
        'HTMLApiField' => 'includes/htmlform/HTMLApiField.php',
+       'HTMLAutoCompleteSelectField' => 'includes/htmlform/HTMLAutoCompleteSelectField.php',
        'HTMLButtonField' => 'includes/htmlform/HTMLButtonField.php',
        'HTMLCheckField' => 'includes/htmlform/HTMLCheckField.php',
        'HTMLCheckMatrix' => 'includes/htmlform/HTMLCheckMatrix.php',
@@ -102,45 +104,32 @@ $wgAutoloadLocalClasses = array(
        'HTMLRadioField' => 'includes/htmlform/HTMLRadioField.php',
        'HTMLSelectAndOtherField' => 'includes/htmlform/HTMLSelectAndOtherField.php',
        'HTMLSelectField' => 'includes/htmlform/HTMLSelectField.php',
+       'HTMLSelectLimitField' => 'includes/htmlform/HTMLSelectLimitField.php',
        'HTMLSelectOrOtherField' => 'includes/htmlform/HTMLSelectOrOtherField.php',
        'HTMLSubmitField' => 'includes/htmlform/HTMLSubmitField.php',
        'HTMLTextAreaField' => 'includes/htmlform/HTMLTextAreaField.php',
        'HTMLTextField' => 'includes/htmlform/HTMLTextField.php',
        'Http' => 'includes/HttpFunctions.php',
-       'ICacheHelper' => 'includes/CacheHelper.php',
        'IcuCollation' => 'includes/Collation.php',
        'IdentityCollation' => 'includes/Collation.php',
        'ImportStreamSource' => 'includes/Import.php',
        'ImportStringSource' => 'includes/Import.php',
-       'IndexPager' => 'includes/Pager.php',
        'Interwiki' => 'includes/interwiki/Interwiki.php',
-       'LCStore' => 'includes/cache/LocalisationCache.php',
-       'LCStoreAccel' => 'includes/cache/LocalisationCache.php',
-       'LCStoreCDB' => 'includes/cache/LocalisationCache.php',
-       'LCStoreDB' => 'includes/cache/LocalisationCache.php',
-       'LCStoreNull' => 'includes/cache/LocalisationCache.php',
        'License' => 'includes/Licenses.php',
        'Licenses' => 'includes/Licenses.php',
        'Linker' => 'includes/Linker.php',
        'LinkFilter' => 'includes/LinkFilter.php',
-       'LocalisationCache' => 'includes/cache/LocalisationCache.php',
-       'LocalisationCacheBulkLoad' => 'includes/cache/LocalisationCache.php',
        'MagicWord' => 'includes/MagicWord.php',
        'MagicWordArray' => 'includes/MagicWord.php',
-       'MailAddress' => 'includes/UserMailer.php',
-       'MediaWiki' => 'includes/Wiki.php',
-       'MediaWikiI18N' => 'includes/SkinTemplate.php',
+       'MediaWiki' => 'includes/MediaWiki.php',
        'MediaWikiVersionFetcher' => 'includes/MediaWikiVersionFetcher.php',
        'Message' => 'includes/Message.php',
        'MessageBlobStore' => 'includes/MessageBlobStore.php',
        'MimeMagic' => 'includes/MimeMagic.php',
        'MWHookException' => 'includes/Hooks.php',
        'MWHttpRequest' => 'includes/HttpFunctions.php',
-       'MWInit' => 'includes/Init.php',
-       'MWNamespace' => 'includes/Namespace.php',
+       'MWNamespace' => 'includes/MWNamespace.php',
        'OutputPage' => 'includes/OutputPage.php',
-       'Pager' => 'includes/Pager.php',
-       'PasswordError' => 'includes/User.php',
        'PathRouter' => 'includes/PathRouter.php',
        'PathRouterPatternReplacer' => 'includes/PathRouter.php',
        'PhpHttpRequest' => 'includes/HttpFunctions.php',
@@ -148,15 +137,13 @@ $wgAutoloadLocalClasses = array(
        'PoolCounter_Stub' => 'includes/poolcounter/PoolCounter.php',
        'PoolCounterRedis' => 'includes/poolcounter/PoolCounterRedis.php',
        'PoolCounterWork' => 'includes/poolcounter/PoolCounterWork.php',
-       'PoolCounterWorkViaCallback' => 'includes/poolcounter/PoolCounterWork.php',
+       'PoolCounterWorkViaCallback' => 'includes/poolcounter/PoolCounterWorkViaCallback.php',
        'PoolWorkArticleView' => 'includes/poolcounter/PoolWorkArticleView.php',
        'Preferences' => 'includes/Preferences.php',
        'PreferencesForm' => 'includes/Preferences.php',
        'PrefixSearch' => 'includes/PrefixSearch.php',
        'ProtectionForm' => 'includes/ProtectionForm.php',
-       'QuickTemplate' => 'includes/SkinTemplate.php',
        'RawMessage' => 'includes/Message.php',
-       'ReverseChronologicalPager' => 'includes/Pager.php',
        'RevisionItem' => 'includes/RevisionList.php',
        'RevisionItemBase' => 'includes/RevisionList.php',
        'RevisionListBase' => 'includes/RevisionList.php',
@@ -167,18 +154,14 @@ $wgAutoloadLocalClasses = array(
        'SiteConfiguration' => 'includes/SiteConfiguration.php',
        'SiteStats' => 'includes/SiteStats.php',
        'SiteStatsInit' => 'includes/SiteStats.php',
-       'Skin' => 'includes/Skin.php',
-       'SkinTemplate' => 'includes/SkinTemplate.php',
        'SquidPurgeClient' => 'includes/SquidPurgeClient.php',
        'SquidPurgeClientPool' => 'includes/SquidPurgeClient.php',
        'StatCounter' => 'includes/StatCounter.php',
        'Status' => 'includes/Status.php',
        'StreamFile' => 'includes/StreamFile.php',
        'StringPrefixSearch' => 'includes/PrefixSearch.php',
-       'StubContLang' => 'includes/StubObject.php',
        'StubObject' => 'includes/StubObject.php',
        'StubUserLang' => 'includes/StubObject.php',
-       'TablePager' => 'includes/Pager.php',
        'MWTimestamp' => 'includes/MWTimestamp.php',
        'TimestampException' => 'includes/TimestampException.php',
        'Title' => 'includes/Title.php',
@@ -190,8 +173,6 @@ $wgAutoloadLocalClasses = array(
        'User' => 'includes/User.php',
        'UserArray' => 'includes/UserArray.php',
        'UserArrayFromResult' => 'includes/UserArrayFromResult.php',
-       'UserCache' => 'includes/cache/UserCache.php',
-       'UserMailer' => 'includes/UserMailer.php',
        'UserRightsProxy' => 'includes/UserRightsProxy.php',
        'WatchedItem' => 'includes/WatchedItem.php',
        'WebRequest' => 'includes/WebRequest.php',
@@ -205,7 +186,6 @@ $wgAutoloadLocalClasses = array(
        'Xml' => 'includes/Xml.php',
        'XmlDumpWriter' => 'includes/Export.php',
        'XmlJsCode' => 'includes/Xml.php',
-       'XMLReader2' => 'includes/Import.php',
        'XmlSelect' => 'includes/Xml.php',
 
        # includes/actions
@@ -217,28 +197,26 @@ $wgAutoloadLocalClasses = array(
        'FormlessAction' => 'includes/actions/FormlessAction.php',
        'FormAction' => 'includes/actions/FormAction.php',
        'HistoryAction' => 'includes/actions/HistoryAction.php',
-       'HistoryPage' => 'includes/actions/HistoryAction.php',
        'HistoryPager' => 'includes/actions/HistoryAction.php',
        'InfoAction' => 'includes/actions/InfoAction.php',
        'MarkpatrolledAction' => 'includes/actions/MarkpatrolledAction.php',
        'ProtectAction' => 'includes/actions/ProtectAction.php',
        'PurgeAction' => 'includes/actions/PurgeAction.php',
        'RawAction' => 'includes/actions/RawAction.php',
-       'RawPage' => 'includes/actions/RawAction.php',
        'RenderAction' => 'includes/actions/RenderAction.php',
        'RevertAction' => 'includes/actions/RevertAction.php',
-       'RevertFileAction' => 'includes/actions/RevertAction.php',
        'RevisiondeleteAction' => 'includes/actions/RevisiondeleteAction.php',
        'RollbackAction' => 'includes/actions/RollbackAction.php',
-       'SubmitAction' => 'includes/actions/EditAction.php',
-       'UnprotectAction' => 'includes/actions/ProtectAction.php',
-       'UnwatchAction' => 'includes/actions/WatchAction.php',
+       'SubmitAction' => 'includes/actions/SubmitAction.php',
+       'UnprotectAction' => 'includes/actions/UnprotectAction.php',
+       'UnwatchAction' => 'includes/actions/UnwatchAction.php',
        'ViewAction' => 'includes/actions/ViewAction.php',
        'WatchAction' => 'includes/actions/WatchAction.php',
 
        # includes/api
        'ApiBase' => 'includes/api/ApiBase.php',
        'ApiBlock' => 'includes/api/ApiBlock.php',
+       'ApiClearHasMsg' => 'includes/api/ApiClearHasMsg.php',
        'ApiComparePages' => 'includes/api/ApiComparePages.php',
        'ApiCreateAccount' => 'includes/api/ApiCreateAccount.php',
        'ApiDelete' => 'includes/api/ApiDelete.php',
@@ -253,7 +231,7 @@ $wgAutoloadLocalClasses = array(
        'ApiFormatBase' => 'includes/api/ApiFormatBase.php',
        'ApiFormatDbg' => 'includes/api/ApiFormatDbg.php',
        'ApiFormatDump' => 'includes/api/ApiFormatDump.php',
-       'ApiFormatFeedWrapper' => 'includes/api/ApiFormatBase.php',
+       'ApiFormatFeedWrapper' => 'includes/api/ApiFormatFeedWrapper.php',
        'ApiFormatJson' => 'includes/api/ApiFormatJson.php',
        'ApiFormatNone' => 'includes/api/ApiFormatNone.php',
        'ApiFormatPhp' => 'includes/api/ApiFormatPhp.php',
@@ -327,6 +305,7 @@ $wgAutoloadLocalClasses = array(
        'ApiQuerySiteinfo' => 'includes/api/ApiQuerySiteinfo.php',
        'ApiQueryStashImageInfo' => 'includes/api/ApiQueryStashImageInfo.php',
        'ApiQueryTags' => 'includes/api/ApiQueryTags.php',
+       'ApiQueryTokens' => 'includes/api/ApiQueryTokens.php',
        'ApiQueryUserInfo' => 'includes/api/ApiQueryUserInfo.php',
        'ApiQueryUsers' => 'includes/api/ApiQueryUsers.php',
        'ApiQueryWatchlist' => 'includes/api/ApiQueryWatchlist.php',
@@ -347,6 +326,7 @@ $wgAutoloadLocalClasses = array(
        # includes/cache
        'BacklinkCache' => 'includes/cache/BacklinkCache.php',
        'CacheDependency' => 'includes/cache/CacheDependency.php',
+       'CacheHelper' => 'includes/cache/CacheHelper.php',
        'ConstantDependency' => 'includes/cache/CacheDependency.php',
        'DependencyWrapper' => 'includes/cache/CacheDependency.php',
        'FileCacheBase' => 'includes/cache/FileCacheBase.php',
@@ -354,14 +334,23 @@ $wgAutoloadLocalClasses = array(
        'GenderCache' => 'includes/cache/GenderCache.php',
        'GlobalDependency' => 'includes/cache/CacheDependency.php',
        'HTMLFileCache' => 'includes/cache/HTMLFileCache.php',
+       'ICacheHelper' => 'includes/cache/CacheHelper.php',
+       'LCStore' => 'includes/cache/LocalisationCache.php',
+       'LCStoreCDB' => 'includes/cache/LocalisationCache.php',
+       'LCStoreDB' => 'includes/cache/LocalisationCache.php',
+       'LCStoreNull' => 'includes/cache/LocalisationCache.php',
        'LinkBatch' => 'includes/cache/LinkBatch.php',
        'LinkCache' => 'includes/cache/LinkCache.php',
+       'LocalisationCache' => 'includes/cache/LocalisationCache.php',
+       'LocalisationCacheBulkLoad' => 'includes/cache/LocalisationCache.php',
        'MapCacheLRU' => 'includes/cache/MapCacheLRU.php',
        'MessageCache' => 'includes/cache/MessageCache.php',
        'ObjectFileCache' => 'includes/cache/ObjectFileCache.php',
        'ResourceFileCache' => 'includes/cache/ResourceFileCache.php',
+       'UserCache' => 'includes/cache/UserCache.php',
 
        # includes/changes
+       'ChangesFeed' => 'includes/changes/ChangesFeed.php',
        'ChangesList' => 'includes/changes/ChangesList.php',
        'EnhancedChangesList' => 'includes/changes/EnhancedChangesList.php',
        'OldChangesList' => 'includes/changes/OldChangesList.php',
@@ -382,21 +371,25 @@ $wgAutoloadLocalClasses = array(
        'ConfigException' => 'includes/config/ConfigException.php',
        'ConfigFactory' => 'includes/config/ConfigFactory.php',
        'GlobalVarConfig' => 'includes/config/GlobalVarConfig.php',
+       'MutableConfig' => 'includes/config/MutableConfig.php',
 
        # includes/content
        'AbstractContent' => 'includes/content/AbstractContent.php',
-       'ContentHandler' => 'includes/content/ContentHandler.php',
+       'CodeContentHandler' => 'includes/content/CodeContentHandler.php',
        'Content' => 'includes/content/Content.php',
-       'CssContentHandler' => 'includes/content/CssContentHandler.php',
+       'ContentHandler' => 'includes/content/ContentHandler.php',
        'CssContent' => 'includes/content/CssContent.php',
-       'JavaScriptContentHandler' => 'includes/content/JavaScriptContentHandler.php',
+       'CssContentHandler' => 'includes/content/CssContentHandler.php',
        'JavaScriptContent' => 'includes/content/JavaScriptContent.php',
+       'JavaScriptContentHandler' => 'includes/content/JavaScriptContentHandler.php',
+       'JsonContent' => 'includes/content/JsonContent.php',
+       'JsonContentHandler' => 'includes/content/JsonContentHandler.php',
        'MessageContent' => 'includes/content/MessageContent.php',
        'MWContentSerializationException' => 'includes/content/ContentHandler.php',
-       'TextContentHandler' => 'includes/content/TextContentHandler.php',
        'TextContent' => 'includes/content/TextContent.php',
-       'WikitextContentHandler' => 'includes/content/WikitextContentHandler.php',
+       'TextContentHandler' => 'includes/content/TextContentHandler.php',
        'WikitextContent' => 'includes/content/WikitextContent.php',
+       'WikitextContentHandler' => 'includes/content/WikitextContentHandler.php',
 
        # includes/context
        'ContextSource' => 'includes/context/ContextSource.php',
@@ -465,7 +458,7 @@ $wgAutoloadLocalClasses = array(
        'SQLiteField' => 'includes/db/DatabaseSqlite.php',
 
        # includes/debug
-       'MWDebug' => 'includes/debug/Debug.php',
+       'MWDebug' => 'includes/debug/MWDebug.php',
 
        # includes/deferred
        'DataUpdate' => 'includes/deferred/DataUpdate.php',
@@ -643,6 +636,7 @@ $wgAutoloadLocalClasses = array(
        'JobQueueGroup' => 'includes/jobqueue/JobQueueGroup.php',
        'JobQueueFederated' => 'includes/jobqueue/JobQueueFederated.php',
        'JobQueueRedis' => 'includes/jobqueue/JobQueueRedis.php',
+       'JobRunner' => 'includes/jobqueue/JobRunner.php',
        'JobSpecification' => 'includes/jobqueue/JobSpecification.php',
 
        # includes/jobqueue/jobs
@@ -729,6 +723,11 @@ $wgAutoloadLocalClasses = array(
        'PackedHoverImageGallery' => 'includes/gallery/PackedOverlayImageGallery.php',
        'PackedOverlayImageGallery' => 'includes/gallery/PackedOverlayImageGallery.php',
 
+       # includes/mail
+       'EmailNotification' => 'includes/mail/EmailNotification.php',
+       'MailAddress' => 'includes/mail/MailAddress.php',
+       'UserMailer' => 'includes/mail/UserMailer.php',
+
        # includes/media
        'BitmapHandler' => 'includes/media/Bitmap.php',
        'BitmapHandler_ClientOnly' => 'includes/media/Bitmap_ClientOnly.php',
@@ -755,6 +754,7 @@ $wgAutoloadLocalClasses = array(
        'SVGReader' => 'includes/media/SVGMetadataExtractor.php',
        'ThumbnailImage' => 'includes/media/MediaTransformOutput.php',
        'TiffHandler' => 'includes/media/Tiff.php',
+       'TransformationalImageHandler' => 'includes/media/TransformationalImageHandler.php',
        'TransformParameterError' => 'includes/media/MediaTransformOutput.php',
        'XCFHandler' => 'includes/media/XCF.php',
        'XMPInfo' => 'includes/media/XMPInfo.php',
@@ -794,14 +794,21 @@ $wgAutoloadLocalClasses = array(
        'WikiFilePage' => 'includes/page/WikiFilePage.php',
        'WikiPage' => 'includes/page/WikiPage.php',
 
+       # includes/pager
+       'AlphabeticPager' => 'includes/pager/AlphabeticPager.php',
+       'IndexPager' => 'includes/pager/IndexPager.php',
+       'Pager' => 'includes/pager/Pager.php',
+       'ReverseChronologicalPager' => 'includes/pager/ReverseChronologicalPager.php',
+       'TablePager' => 'includes/pager/TablePager.php',
+
        # includes/parser
        'CacheTime' => 'includes/parser/CacheTime.php',
        'CoreParserFunctions' => 'includes/parser/CoreParserFunctions.php',
        'CoreTagHooks' => 'includes/parser/CoreTagHooks.php',
        'DateFormatter' => 'includes/parser/DateFormatter.php',
        'LinkHolderArray' => 'includes/parser/LinkHolderArray.php',
-       'MWTidy' => 'includes/parser/Tidy.php',
-       'MWTidyWrapper' => 'includes/parser/Tidy.php',
+       'MWTidy' => 'includes/parser/MWTidy.php',
+       'MWTidyWrapper' => 'includes/parser/MWTidy.php',
        'PPCustomFrame_DOM' => 'includes/parser/Preprocessor_DOM.php',
        'PPCustomFrame_Hash' => 'includes/parser/Preprocessor_Hash.php',
        'PPDAccum_Hash' => 'includes/parser/Preprocessor_Hash.php',
@@ -832,6 +839,19 @@ $wgAutoloadLocalClasses = array(
        'Preprocessor_Hash' => 'includes/parser/Preprocessor_Hash.php',
        'StripState' => 'includes/parser/StripState.php',
 
+       # includes/password
+       'BcryptPassword' => 'includes/password/BcryptPassword.php',
+       'InvalidPassword' => 'includes/password/InvalidPassword.php',
+       'LayeredParameterizedPassword' => 'includes/password/LayeredParameterizedPassword.php',
+       'MWSaltedPassword' => 'includes/password/MWSaltedPassword.php',
+       'MWOldPassword' => 'includes/password/MWOldPassword.php',
+       'ParameterizedPassword' => 'includes/password/ParameterizedPassword.php',
+       'Password' => 'includes/password/Password.php',
+       'PasswordError' => 'includes/password/PasswordError.php',
+       'PasswordFactory' => 'includes/password/PasswordFactory.php',
+       'Pbkdf2Password' => 'includes/password/Pbkdf2Password.php',
+       'EncryptedPassword' => 'includes/password/EncryptedPassword.php',
+
        # includes/profiler
        'Profiler' => 'includes/profiler/Profiler.php',
        'ProfilerMwprof' => 'includes/profiler/ProfilerMwprof.php',
@@ -855,10 +875,14 @@ $wgAutoloadLocalClasses = array(
        'MachineReadableRCFeedFormatter' => 'includes/rcfeed/MachineReadableRCFeedFormatter.php',
 
        # includes/resourceloader
+       'DerivativeResourceLoaderContext' =>
+               'includes/resourceloader/DerivativeResourceLoaderContext.php',
        'ResourceLoader' => 'includes/resourceloader/ResourceLoader.php',
        'ResourceLoaderContext' => 'includes/resourceloader/ResourceLoaderContext.php',
+       'ResourceLoaderEditToolbarModule' => 'includes/resourceloader/ResourceLoaderEditToolbarModule.php',
        'ResourceLoaderFileModule' => 'includes/resourceloader/ResourceLoaderFileModule.php',
        'ResourceLoaderFilePageModule' => 'includes/resourceloader/ResourceLoaderFilePageModule.php',
+       'ResourceLoaderFilePath' => 'includes/resourceloader/ResourceLoaderFilePath.php',
        'ResourceLoaderLESSFunctions' => 'includes/resourceloader/ResourceLoaderLESSFunctions.php',
        'ResourceLoaderModule' => 'includes/resourceloader/ResourceLoaderModule.php',
        'ResourceLoaderNoscriptModule' => 'includes/resourceloader/ResourceLoaderNoscriptModule.php',
@@ -877,25 +901,23 @@ $wgAutoloadLocalClasses = array(
        'ResourceLoaderWikiModule' => 'includes/resourceloader/ResourceLoaderWikiModule.php',
 
        # includes/revisiondelete
-       'RevDelArchivedFileItem' => 'includes/revisiondelete/RevisionDelete.php',
-       'RevDelArchivedFileList' => 'includes/revisiondelete/RevisionDelete.php',
-       'RevDelArchivedRevisionItem' => 'includes/revisiondelete/RevisionDelete.php',
-       'RevDelArchiveItem' => 'includes/revisiondelete/RevisionDelete.php',
-       'RevDelArchiveList' => 'includes/revisiondelete/RevisionDelete.php',
-       'RevDelFileItem' => 'includes/revisiondelete/RevisionDelete.php',
-       'RevDelFileList' => 'includes/revisiondelete/RevisionDelete.php',
-       'RevDelItem' => 'includes/revisiondelete/RevisionDeleteAbstracts.php',
-       'RevDelList' => 'includes/revisiondelete/RevisionDeleteAbstracts.php',
-       'RevDelLogItem' => 'includes/revisiondelete/RevisionDelete.php',
-       'RevDelLogList' => 'includes/revisiondelete/RevisionDelete.php',
-       'RevDelRevisionItem' => 'includes/revisiondelete/RevisionDelete.php',
-       'RevDelRevisionList' => 'includes/revisiondelete/RevisionDelete.php',
+       'RevDelArchivedFileItem' => 'includes/revisiondelete/RevDelArchivedFileItem.php',
+       'RevDelArchivedFileList' => 'includes/revisiondelete/RevDelArchivedFileList.php',
+       'RevDelArchivedRevisionItem' => 'includes/revisiondelete/RevDelArchivedRevisionItem.php',
+       'RevDelArchiveItem' => 'includes/revisiondelete/RevDelArchiveItem.php',
+       'RevDelArchiveList' => 'includes/revisiondelete/RevDelArchiveList.php',
+       'RevDelFileItem' => 'includes/revisiondelete/RevDelFileItem.php',
+       'RevDelFileList' => 'includes/revisiondelete/RevDelFileList.php',
+       'RevDelItem' => 'includes/revisiondelete/RevDelItem.php',
+       'RevDelList' => 'includes/revisiondelete/RevDelList.php',
+       'RevDelLogItem' => 'includes/revisiondelete/RevDelLogItem.php',
+       'RevDelLogList' => 'includes/revisiondelete/RevDelLogList.php',
+       'RevDelRevisionItem' => 'includes/revisiondelete/RevDelRevisionItem.php',
+       'RevDelRevisionList' => 'includes/revisiondelete/RevDelRevisionList.php',
        'RevisionDeleter' => 'includes/revisiondelete/RevisionDeleter.php',
        'RevisionDeleteUser' => 'includes/revisiondelete/RevisionDeleteUser.php',
 
        # includes/search
-       'PostgresSearchResult' => 'includes/search/SearchPostgres.php',
-       'PostgresSearchResultSet' => 'includes/search/SearchPostgres.php',
        'SearchDatabase' => 'includes/search/SearchDatabase.php',
        'SearchEngine' => 'includes/search/SearchEngine.php',
        'SearchEngineDummy' => 'includes/search/SearchEngine.php',
@@ -920,6 +942,17 @@ $wgAutoloadLocalClasses = array(
        'Sites' => 'includes/site/SiteSQLStore.php',
        'SiteStore' => 'includes/site/SiteStore.php',
 
+       # includes/skins
+       'BaseTemplate' => 'includes/skins/SkinTemplate.php',
+       'MediaWikiI18N' => 'includes/skins/SkinTemplate.php',
+       'QuickTemplate' => 'includes/skins/SkinTemplate.php',
+       'Skin' => 'includes/skins/Skin.php',
+       'SkinException' => 'includes/skins/SkinException.php',
+       'SkinFactory' => 'includes/skins/SkinFactory.php',
+       'SkinFallback' => 'includes/skins/SkinFallback.php',
+       'SkinFallbackTemplate' => 'includes/skins/SkinFallbackTemplate.php',
+       'SkinTemplate' => 'includes/skins/SkinTemplate.php',
+
        # includes/specialpage
        'ChangesListSpecialPage' => 'includes/specialpage/ChangesListSpecialPage.php',
        'FormSpecialPage' => 'includes/specialpage/FormSpecialPage.php',
@@ -953,7 +986,6 @@ $wgAutoloadLocalClasses = array(
        'EmailInvalidation' => 'includes/specials/SpecialConfirmemail.php',
        'FewestrevisionsPage' => 'includes/specials/SpecialFewestrevisions.php',
        'FileDuplicateSearchPage' => 'includes/specials/SpecialFileDuplicateSearch.php',
-       'HTMLBlockedUsersItemSelect' => 'includes/specials/SpecialBlockList.php',
        'ImageListPager' => 'includes/specials/SpecialListfiles.php',
        'ImportReporter' => 'includes/specials/SpecialImport.php',
        'LinkSearchPage' => 'includes/specials/SpecialLinkSearch.php',
@@ -1012,6 +1044,7 @@ $wgAutoloadLocalClasses = array(
        'SpecialLog' => 'includes/specials/SpecialLog.php',
        'SpecialMergeHistory' => 'includes/specials/SpecialMergeHistory.php',
        'SpecialMycontributions' => 'includes/specials/SpecialMyRedirectPages.php',
+       'SpecialMyLanguage' => 'includes/specials/SpecialMyLanguage.php',
        'SpecialMypage' => 'includes/specials/SpecialMyRedirectPages.php',
        'SpecialMytalk' => 'includes/specials/SpecialMyRedirectPages.php',
        'SpecialMyuploads' => 'includes/specials/SpecialMyRedirectPages.php',
@@ -1150,6 +1183,7 @@ $wgAutoloadLocalClasses = array(
        'FixExtLinksProtocolRelative' => 'maintenance/fixExtLinksProtocolRelative.php',
        'LoggedUpdateMaintenance' => 'maintenance/Maintenance.php',
        'Maintenance' => 'maintenance/Maintenance.php',
+       'PopulateBacklinkNamespace' => 'maintenance/populateBacklinkNamespace.php',
        'PopulateCategory' => 'maintenance/populateCategory.php',
        'PopulateImageSha1' => 'maintenance/populateImageSha1.php',
        'PopulateFilearchiveSha1' => 'maintenance/populateFilearchiveSha1.php',
@@ -1188,7 +1222,7 @@ class AutoLoader {
        /**
         * autoload - take a class name and attempt to load it
         *
-        * @param string $className name of class we're looking for.
+        * @param string $className Name of class we're looking for.
         */
        static function autoload( $className ) {
                global $wgAutoloadClasses, $wgAutoloadLocalClasses,
index 3896369..6a29a05 100644 (file)
@@ -80,6 +80,20 @@ class Block {
        /**
         * @todo FIXME: Don't know what the best format to have for this constructor
         *   is, but fourteen optional parameters certainly isn't it.
+        * @param string $address
+        * @param int $user
+        * @param int $by
+        * @param string $reason
+        * @param mixed $timestamp
+        * @param int $auto
+        * @param string $expiry
+        * @param int $anonOnly
+        * @param int $createAccount
+        * @param int $enableAutoblock
+        * @param int $hideName
+        * @param int $blockEmail
+        * @param int $allowUsertalk
+        * @param string $byText
         */
        function __construct( $address = '', $user = 0, $by = 0, $reason = '',
                $timestamp = 0, $auto = 0, $expiry = '', $anonOnly = 0, $createAccount = 0, $enableAutoblock = 0,
@@ -347,7 +361,7 @@ class Block {
        /**
         * Given a database row from the ipblocks table, initialize
         * member variables
-        * @param ResultWrapper $row A row from the ipblocks table
+        * @param stdClass $row A row from the ipblocks table
         */
        protected function initFromRow( $row ) {
                $this->setTarget( $row->ipb_address );
@@ -382,7 +396,7 @@ class Block {
 
        /**
         * Create a new Block object from a database row
-        * @param ResultWrapper $row Row from the ipblocks table
+        * @param stdClass $row Row from the ipblocks table
         * @return Block
         */
        public static function newFromRow( $row ) {
@@ -582,7 +596,6 @@ class Block {
         *
         * @param Block $block
         * @param array &$blockIds
-        * @return array Block IDs of retroactive autoblocks made
         */
        protected static function defaultRetroactiveAutoblock( Block $block, array &$blockIds ) {
                global $wgPutIPinRC;
@@ -967,7 +980,7 @@ class Block {
 
                $method = __METHOD__;
                $dbw = wfGetDB( DB_MASTER );
-               $dbw->onTransactionIdle( function() use ( $dbw, $method ) {
+               $dbw->onTransactionIdle( function () use ( $dbw, $method ) {
                        $dbw->delete( 'ipblocks',
                                array( 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ), $method );
                } );
@@ -1104,13 +1117,13 @@ class Block {
         *  - Other softblocks are chosen over autoblocks
         *  - If there are multiple exact or range blocks at the same level, the one chosen
         *    is random
-
+        *
+        * @param array $blocks Array of blocks
         * @param array $ipChain List of IPs (strings). This is used to determine how "close"
         *        a block is to the server, and if a block matches exactly, or is in a range.
         *        The order is furthest from the server to nearest e.g., (Browser, proxy1, proxy2,
         *        local-squid, ...)
-        * @param array $block Array of blocks
-        * @return Block|null the "best" block from the list
+        * @return Block|null The "best" block from the list
         */
        public static function chooseBlock( array $blocks, array $ipChain ) {
                if ( !count( $blocks ) ) {
@@ -1123,7 +1136,7 @@ class Block {
 
                // Sort hard blocks before soft ones and secondarily sort blocks
                // that disable account creation before those that don't.
-               usort( $blocks, function( Block $a, Block $b ) {
+               usort( $blocks, function ( Block $a, Block $b ) {
                        $aWeight = (int)$a->isHardblock() . (int)$a->prevents( 'createaccount' );
                        $bWeight = (int)$b->isHardblock() . (int)$b->prevents( 'createaccount' );
                        return strcmp( $bWeight, $aWeight ); // highest weight first
@@ -1368,7 +1381,7 @@ class Block {
                        $this->getId(),
                        $lang->formatExpiry( $this->mExpiry ),
                        (string)$intended,
-                       $lang->timeanddate( wfTimestamp( TS_MW, $this->mTimestamp ), true ),
+                       $lang->userTimeAndDate( $this->mTimestamp, $context->getUser() ),
                );
        }
 }
diff --git a/includes/CacheHelper.php b/includes/CacheHelper.php
deleted file mode 100644 (file)
index 695eac3..0000000
+++ /dev/null
@@ -1,386 +0,0 @@
-<?php
-/**
- * Cache of various elements in a single cache entry.
- *
- * 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
- * @license GNU GPL v2 or later
- * @author Jeroen De Dauw < jeroendedauw@gmail.com >
- */
-
-/**
- * Interface for all classes implementing CacheHelper functionality.
- *
- * @since 1.20
- */
-interface ICacheHelper {
-       /**
-        * Sets if the cache should be enabled or not.
-        *
-        * @since 1.20
-        * @param bool $cacheEnabled
-        */
-       function setCacheEnabled( $cacheEnabled );
-
-       /**
-        * Initializes the caching.
-        * Should be called before the first time anything is added via addCachedHTML.
-        *
-        * @since 1.20
-        *
-        * @param int|null $cacheExpiry Sets the cache expiry, either ttl in seconds or unix timestamp.
-        * @param bool|null $cacheEnabled Sets if the cache should be enabled or not.
-        */
-       function startCache( $cacheExpiry = null, $cacheEnabled = null );
-
-       /**
-        * Get a cached value if available or compute it if not and then cache it if possible.
-        * The provided $computeFunction is only called when the computation needs to happen
-        * and should return a result value. $args are arguments that will be passed to the
-        * compute function when called.
-        *
-        * @since 1.20
-        *
-        * @param {function} $computeFunction
-        * @param array|mixed $args
-        * @param string|null $key
-        *
-        * @return mixed
-        */
-       function getCachedValue( $computeFunction, $args = array(), $key = null );
-
-       /**
-        * Saves the HTML to the cache in case it got recomputed.
-        * Should be called after the last time anything is added via addCachedHTML.
-        *
-        * @since 1.20
-        */
-       function saveCache();
-
-       /**
-        * Sets the time to live for the cache, in seconds or a unix timestamp
-        * indicating the point of expiry...
-        *
-        * @since 1.20
-        *
-        * @param int $cacheExpiry
-        */
-       function setExpiry( $cacheExpiry );
-}
-
-/**
- * Helper class for caching various elements in a single cache entry.
- *
- * To get a cached value or compute it, use getCachedValue like this:
- * $this->getCachedValue( $callback );
- *
- * To add HTML that should be cached, use addCachedHTML like this:
- * $this->addCachedHTML( $callback );
- *
- * The callback function is only called when needed, so do all your expensive
- * computations here. This function should returns the HTML to be cached.
- * It should not add anything to the PageOutput object!
- *
- * Before the first addCachedHTML call, you should call $this->startCache();
- * After adding the last HTML that should be cached, call $this->saveCache();
- *
- * @since 1.20
- */
-class CacheHelper implements ICacheHelper {
-       /**
-        * The time to live for the cache, in seconds or a unix timestamp indicating the point of expiry.
-        *
-        * @since 1.20
-        * @var int
-        */
-       protected $cacheExpiry = 3600;
-
-       /**
-        * List of HTML chunks to be cached (if !hasCached) or that where cached (of hasCached).
-        * If not cached already, then the newly computed chunks are added here,
-        * if it as cached already, chunks are removed from this list as they are needed.
-        *
-        * @since 1.20
-        * @var array
-        */
-       protected $cachedChunks;
-
-       /**
-        * Indicates if the to be cached content was already cached.
-        * Null if this information is not available yet.
-        *
-        * @since 1.20
-        * @var bool|null
-        */
-       protected $hasCached = null;
-
-       /**
-        * If the cache is enabled or not.
-        *
-        * @since 1.20
-        * @var bool
-        */
-       protected $cacheEnabled = true;
-
-       /**
-        * Function that gets called when initialization is done.
-        *
-        * @since 1.20
-        * @var callable
-        */
-       protected $onInitHandler = false;
-
-       /**
-        * Elements to build a cache key with.
-        *
-        * @since 1.20
-        * @var array
-        */
-       protected $cacheKey = array();
-
-       /**
-        * Sets if the cache should be enabled or not.
-        *
-        * @since 1.20
-        * @param bool $cacheEnabled
-        */
-       public function setCacheEnabled( $cacheEnabled ) {
-               $this->cacheEnabled = $cacheEnabled;
-       }
-
-       /**
-        * Initializes the caching.
-        * Should be called before the first time anything is added via addCachedHTML.
-        *
-        * @since 1.20
-        *
-        * @param int|null $cacheExpiry Sets the cache expiry, either ttl in seconds or unix timestamp.
-        * @param bool|null $cacheEnabled Sets if the cache should be enabled or not.
-        */
-       public function startCache( $cacheExpiry = null, $cacheEnabled = null ) {
-               if ( is_null( $this->hasCached ) ) {
-                       if ( !is_null( $cacheExpiry ) ) {
-                               $this->cacheExpiry = $cacheExpiry;
-                       }
-
-                       if ( !is_null( $cacheEnabled ) ) {
-                               $this->setCacheEnabled( $cacheEnabled );
-                       }
-
-                       $this->initCaching();
-               }
-       }
-
-       /**
-        * Returns a message that notifies the user he/she is looking at
-        * a cached version of the page, including a refresh link.
-        *
-        * @since 1.20
-        *
-        * @param IContextSource $context
-        * @param bool $includePurgeLink
-        *
-        * @return string
-        */
-       public function getCachedNotice( IContextSource $context, $includePurgeLink = true ) {
-               if ( $this->cacheExpiry < 86400 * 3650 ) {
-                       $message = $context->msg(
-                               'cachedspecial-viewing-cached-ttl',
-                               $context->getLanguage()->formatDuration( $this->cacheExpiry )
-                       )->escaped();
-               } else {
-                       $message = $context->msg(
-                               'cachedspecial-viewing-cached-ts'
-                       )->escaped();
-               }
-
-               if ( $includePurgeLink ) {
-                       $refreshArgs = $context->getRequest()->getQueryValues();
-                       unset( $refreshArgs['title'] );
-                       $refreshArgs['action'] = 'purge';
-
-                       $subPage = $context->getTitle()->getFullText();
-                       $subPage = explode( '/', $subPage, 2 );
-                       $subPage = count( $subPage ) > 1 ? $subPage[1] : false;
-
-                       $message .= ' ' . Linker::link(
-                               $context->getTitle( $subPage ),
-                               $context->msg( 'cachedspecial-refresh-now' )->escaped(),
-                               array(),
-                               $refreshArgs
-                       );
-               }
-
-               return $message;
-       }
-
-       /**
-        * Initializes the caching if not already done so.
-        * Should be called before any of the caching functionality is used.
-        *
-        * @since 1.20
-        */
-       protected function initCaching() {
-               if ( $this->cacheEnabled && is_null( $this->hasCached ) ) {
-                       $cachedChunks = wfGetCache( CACHE_ANYTHING )->get( $this->getCacheKeyString() );
-
-                       $this->hasCached = is_array( $cachedChunks );
-                       $this->cachedChunks = $this->hasCached ? $cachedChunks : array();
-
-                       if ( $this->onInitHandler !== false ) {
-                               call_user_func( $this->onInitHandler, $this->hasCached );
-                       }
-               }
-       }
-
-       /**
-        * Get a cached value if available or compute it if not and then cache it if possible.
-        * The provided $computeFunction is only called when the computation needs to happen
-        * and should return a result value. $args are arguments that will be passed to the
-        * compute function when called.
-        *
-        * @since 1.20
-        *
-        * @param {function} $computeFunction
-        * @param array|mixed $args
-        * @param string|null $key
-        *
-        * @return mixed
-        */
-       public function getCachedValue( $computeFunction, $args = array(), $key = null ) {
-               $this->initCaching();
-
-               if ( $this->cacheEnabled && $this->hasCached ) {
-                       $value = null;
-
-                       if ( is_null( $key ) ) {
-                               $itemKey = array_keys( array_slice( $this->cachedChunks, 0, 1 ) );
-                               $itemKey = array_shift( $itemKey );
-
-                               if ( !is_integer( $itemKey ) ) {
-                                       wfWarn( "Attempted to get item with non-numeric key while " .
-                                               "the next item in the queue has a key ($itemKey) in " . __METHOD__ );
-                               } elseif ( is_null( $itemKey ) ) {
-                                       wfWarn( "Attempted to get an item while the queue is empty in " . __METHOD__ );
-                               } else {
-                                       $value = array_shift( $this->cachedChunks );
-                               }
-                       } else {
-                               if ( array_key_exists( $key, $this->cachedChunks ) ) {
-                                       $value = $this->cachedChunks[$key];
-                                       unset( $this->cachedChunks[$key] );
-                               } else {
-                                       wfWarn( "There is no item with key '$key' in this->cachedChunks in " . __METHOD__ );
-                               }
-                       }
-               } else {
-                       if ( !is_array( $args ) ) {
-                               $args = array( $args );
-                       }
-
-                       $value = call_user_func_array( $computeFunction, $args );
-
-                       if ( $this->cacheEnabled ) {
-                               if ( is_null( $key ) ) {
-                                       $this->cachedChunks[] = $value;
-                               } else {
-                                       $this->cachedChunks[$key] = $value;
-                               }
-                       }
-               }
-
-               return $value;
-       }
-
-       /**
-        * Saves the HTML to the cache in case it got recomputed.
-        * Should be called after the last time anything is added via addCachedHTML.
-        *
-        * @since 1.20
-        */
-       public function saveCache() {
-               if ( $this->cacheEnabled && $this->hasCached === false && !empty( $this->cachedChunks ) ) {
-                       wfGetCache( CACHE_ANYTHING )->set(
-                               $this->getCacheKeyString(),
-                               $this->cachedChunks,
-                               $this->cacheExpiry
-                       );
-               }
-       }
-
-       /**
-        * Sets the time to live for the cache, in seconds or a unix timestamp
-        * indicating the point of expiry...
-        *
-        * @since 1.20
-        *
-        * @param int $cacheExpiry
-        */
-       public function setExpiry( $cacheExpiry ) {
-               $this->cacheExpiry = $cacheExpiry;
-       }
-
-       /**
-        * Returns the cache key to use to cache this page's HTML output.
-        * Is constructed from the special page name and language code.
-        *
-        * @since 1.20
-        *
-        * @return string
-        * @throws MWException
-        */
-       protected function getCacheKeyString() {
-               if ( $this->cacheKey === array() ) {
-                       throw new MWException( 'No cache key set, so cannot obtain or save the CacheHelper values.' );
-               }
-
-               return call_user_func_array( 'wfMemcKey', $this->cacheKey );
-       }
-
-       /**
-        * Sets the cache key that should be used.
-        *
-        * @since 1.20
-        *
-        * @param array $cacheKey
-        */
-       public function setCacheKey( array $cacheKey ) {
-               $this->cacheKey = $cacheKey;
-       }
-
-       /**
-        * Rebuild the content, even if it's already cached.
-        * This effectively has the same effect as purging the cache,
-        * since it will be overridden with the new value on the next request.
-        *
-        * @since 1.20
-        */
-       public function rebuildOnDemand() {
-               $this->hasCached = false;
-       }
-
-       /**
-        * Sets a function that gets called when initialization of the cache is done.
-        *
-        * @since 1.20
-        *
-        * @param callable $handlerFunction
-        */
-       public function setOnInitializedHandler( $handlerFunction ) {
-               $this->onInitHandler = $handlerFunction;
-       }
-}
index 7bab464..322b053 100644 (file)
@@ -291,6 +291,7 @@ class Category {
 
        /**
         * Generic accessor
+        * @param string $key
         * @return bool
         */
        private function getX( $key ) {
diff --git a/includes/CategoryFinder.php b/includes/CategoryFinder.php
new file mode 100644 (file)
index 0000000..cf537e1
--- /dev/null
@@ -0,0 +1,244 @@
+<?php
+/**
+ * Recent changes filtering by category.
+ *
+ * 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
+ */
+
+/**
+ * The "CategoryFinder" class takes a list of articles, creates an internal
+ * representation of all their parent categories (as well as parents of
+ * parents etc.). From this representation, it determines which of these
+ * articles are in one or all of a given subset of categories.
+ *
+ * Example use :
+ * <code>
+ *     # Determines whether the article with the page_id 12345 is in both
+ *     # "Category 1" and "Category 2" or their subcategories, respectively
+ *
+ *     $cf = new CategoryFinder;
+ *     $cf->seed(
+ *         array( 12345 ),
+ *         array( 'Category 1', 'Category 2' ),
+ *         'AND'
+ *     );
+ *     $a = $cf->run();
+ *     print implode( ',' , $a );
+ * </code>
+ *
+ */
+class CategoryFinder {
+       /** @var int[] The original article IDs passed to the seed function */
+       protected $articles = array();
+
+       /** @var array Array of DBKEY category names for categories that don't have a page */
+       protected $deadend = array();
+
+       /** @var array Array of [ID => array()] */
+       protected $parents = array();
+
+       /** @var array Array of article/category IDs */
+       protected $next = array();
+
+       /** @var array Array of DBKEY category names */
+       protected $targets = array();
+
+       /** @var array */
+       protected $name2id = array();
+
+       /** @var string "AND" or "OR" */
+       protected $mode;
+
+       /** @var DatabaseBase Read-DB slave */
+       protected $dbr;
+
+       /**
+        * Initializes the instance. Do this prior to calling run().
+        * @param array $articleIds Array of article IDs
+        * @param array $categories FIXME
+        * @param string $mode FIXME, default 'AND'.
+        * @todo FIXME: $categories/$mode
+        */
+       public function seed( $articleIds, $categories, $mode = 'AND' ) {
+               $this->articles = $articleIds;
+               $this->next = $articleIds;
+               $this->mode = $mode;
+
+               # Set the list of target categories; convert them to DBKEY form first
+               $this->targets = array();
+               foreach ( $categories as $c ) {
+                       $ct = Title::makeTitleSafe( NS_CATEGORY, $c );
+                       if ( $ct ) {
+                               $c = $ct->getDBkey();
+                               $this->targets[$c] = $c;
+                       }
+               }
+       }
+
+       /**
+        * Iterates through the parent tree starting with the seed values,
+        * then checks the articles if they match the conditions
+        * @return array Array of page_ids (those given to seed() that match the conditions)
+        */
+       public function run() {
+               $this->dbr = wfGetDB( DB_SLAVE );
+               while ( count( $this->next ) > 0 ) {
+                       $this->scanNextLayer();
+               }
+
+               # Now check if this applies to the individual articles
+               $ret = array();
+
+               foreach ( $this->articles as $article ) {
+                       $conds = $this->targets;
+                       if ( $this->check( $article, $conds ) ) {
+                               # Matches the conditions
+                               $ret[] = $article;
+                       }
+               }
+               return $ret;
+       }
+
+       /**
+        * Get the parents. Only really useful if run() has been called already
+        * @return array
+        */
+       public function getParents() {
+               return $this->parents;
+       }
+
+       /**
+        * This functions recurses through the parent representation, trying to match the conditions
+        * @param int $id The article/category to check
+        * @param array $conds The array of categories to match
+        * @param array $path Used to check for recursion loops
+        * @return bool Does this match the conditions?
+        */
+       private function check( $id, &$conds, $path = array() ) {
+               // Check for loops and stop!
+               if ( in_array( $id, $path ) ) {
+                       return false;
+               }
+
+               $path[] = $id;
+
+               # Shortcut (runtime paranoia): No conditions=all matched
+               if ( count( $conds ) == 0 ) {
+                       return true;
+               }
+
+               if ( !isset( $this->parents[$id] ) ) {
+                       return false;
+               }
+
+               # iterate through the parents
+               foreach ( $this->parents[$id] as $p ) {
+                       $pname = $p->cl_to;
+
+                       # Is this a condition?
+                       if ( isset( $conds[$pname] ) ) {
+                               # This key is in the category list!
+                               if ( $this->mode == 'OR' ) {
+                                       # One found, that's enough!
+                                       $conds = array();
+                                       return true;
+                               } else {
+                                       # Assuming "AND" as default
+                                       unset( $conds[$pname] );
+                                       if ( count( $conds ) == 0 ) {
+                                               # All conditions met, done
+                                               return true;
+                                       }
+                               }
+                       }
+
+                       # Not done yet, try sub-parents
+                       if ( !isset( $this->name2id[$pname] ) ) {
+                               # No sub-parent
+                               continue;
+                       }
+                       $done = $this->check( $this->name2id[$pname], $conds, $path );
+                       if ( $done || count( $conds ) == 0 ) {
+                               # Subparents have done it!
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * Scans a "parent layer" of the articles/categories in $this->next
+        */
+       private function scanNextLayer() {
+               $profiler = new ProfileSection( __METHOD__ );
+
+               # Find all parents of the article currently in $this->next
+               $layer = array();
+               $res = $this->dbr->select(
+                       /* FROM   */ 'categorylinks',
+                       /* SELECT */ '*',
+                       /* WHERE  */ array( 'cl_from' => $this->next ),
+                       __METHOD__ . '-1'
+               );
+               foreach ( $res as $o ) {
+                       $k = $o->cl_to;
+
+                       # Update parent tree
+                       if ( !isset( $this->parents[$o->cl_from] ) ) {
+                               $this->parents[$o->cl_from] = array();
+                       }
+                       $this->parents[$o->cl_from][$k] = $o;
+
+                       # Ignore those we already have
+                       if ( in_array( $k, $this->deadend ) ) {
+                               continue;
+                       }
+
+                       if ( isset( $this->name2id[$k] ) ) {
+                               continue;
+                       }
+
+                       # Hey, new category!
+                       $layer[$k] = $k;
+               }
+
+               $this->next = array();
+
+               # Find the IDs of all category pages in $layer, if they exist
+               if ( count( $layer ) > 0 ) {
+                       $res = $this->dbr->select(
+                               /* FROM   */ 'page',
+                               /* SELECT */ array( 'page_id', 'page_title' ),
+                               /* WHERE  */ array( 'page_namespace' => NS_CATEGORY, 'page_title' => $layer ),
+                               __METHOD__ . '-2'
+                       );
+                       foreach ( $res as $o ) {
+                               $id = $o->page_id;
+                               $name = $o->page_title;
+                               $this->name2id[$name] = $id;
+                               $this->next[] = $id;
+                               unset( $layer[$name] );
+                       }
+               }
+
+               # Mark dead ends
+               foreach ( $layer as $v ) {
+                       $this->deadend[$v] = $v;
+               }
+       }
+}
index cd9eaa9..7581ae4 100644 (file)
@@ -25,10 +25,10 @@ class CategoryViewer extends ContextSource {
        public $limit;
 
        /** @var array */
-       protected $from;
+       public $from;
 
        /** @var array */
-       protected $until;
+       public $until;
 
        /** @var string[] */
        public $articles;
@@ -37,34 +37,37 @@ class CategoryViewer extends ContextSource {
        public $articles_start_char;
 
        /** @var array */
-       protected $children;
+       public $children;
 
        /** @var array */
-       protected $children_start_char;
+       public $children_start_char;
 
        /** @var bool */
-       protected $showGallery;
+       public $showGallery;
 
        /** @var array */
-       protected $imgsNoGallery_start_char;
+       public $imgsNoGallery_start_char;
 
        /** @var array */
-       protected $imgsNoGallery;
+       public $imgsNoGallery;
 
        /** @var array */
-       protected $nextPage;
+       public $nextPage;
 
        /** @var array */
-       protected $flip;
+       protected $prevPage;
+
+       /** @var array */
+       public $flip;
 
        /** @var Title */
-       protected $title;
+       public $title;
 
        /** @var Collation */
-       protected $collation;
+       public $collation;
 
        /** @var ImageGallery */
-       protected $gallery;
+       public $gallery;
 
        /** @var Category Category object for this page. */
        private $cat;
@@ -84,12 +87,11 @@ class CategoryViewer extends ContextSource {
        function __construct( $title, IContextSource $context, $from = array(),
                $until = array(), $query = array()
        ) {
-               global $wgCategoryPagingLimit;
                $this->title = $title;
                $this->setContext( $context );
                $this->from = $from;
                $this->until = $until;
-               $this->limit = $wgCategoryPagingLimit;
+               $this->limit = $context->getConfig()->get( 'CategoryPagingLimit' );
                $this->cat = Category::newFromTitle( $title );
                $this->query = $query;
                $this->collation = Collation::singleton();
@@ -102,10 +104,10 @@ class CategoryViewer extends ContextSource {
         * @return string HTML output
         */
        public function getHTML() {
-               global $wgCategoryMagicGallery;
                wfProfileIn( __METHOD__ );
 
-               $this->showGallery = $wgCategoryMagicGallery && !$this->getOutput()->mNoGallery;
+               $this->showGallery = $this->getConfig()->get( 'CategoryMagicGallery' )
+                       && !$this->getOutput()->mNoGallery;
 
                $this->clearCategoryState();
                $this->doCategoryQuery();
@@ -151,14 +153,13 @@ class CategoryViewer extends ContextSource {
                        // Note that null for mode is taken to mean use default.
                        $mode = $this->getRequest()->getVal( 'gallerymode', null );
                        try {
-                               $this->gallery = ImageGalleryBase::factory( $mode );
+                               $this->gallery = ImageGalleryBase::factory( $mode, $this->getContext() );
                        } catch ( MWException $e ) {
                                // User specified something invalid, fallback to default.
-                               $this->gallery = ImageGalleryBase::factory();
+                               $this->gallery = ImageGalleryBase::factory( false, $this->getContext() );
                        }
 
                        $this->gallery->setHideBadImages();
-                       $this->gallery->setContext( $this->getContext() );
                } else {
                        $this->imgsNoGallery = array();
                        $this->imgsNoGallery_start_char = array();
@@ -288,6 +289,12 @@ class CategoryViewer extends ContextSource {
                        'subcat' => null,
                        'file' => null,
                );
+               $this->prevPage = array(
+                       'page' => null,
+                       'subcat' => null,
+                       'file' => null,
+               );
+
                $this->flip = array( 'page' => false, 'subcat' => false, 'file' => false );
 
                foreach ( array( 'page', 'subcat', 'file' ) as $type ) {
@@ -344,6 +351,9 @@ class CategoryViewer extends ContextSource {
                                        $this->nextPage[$type] = $humanSortkey;
                                        break;
                                }
+                               if ( $count == $this->limit ) {
+                                       $this->prevPage[$type] = $humanSortkey;
+                               }
 
                                if ( $title->getNamespace() == NS_CATEGORY ) {
                                        $cat = Category::newFromRow( $row, $title );
@@ -458,7 +468,17 @@ class CategoryViewer extends ContextSource {
         */
        private function getSectionPagingLinks( $type ) {
                if ( isset( $this->until[$type] ) && $this->until[$type] !== null ) {
-                       return $this->pagingLinks( $this->nextPage[$type], $this->until[$type], $type );
+                       // The new value for the until parameter should be pointing to the first
+                       // result displayed on the page which is the second last result retrieved
+                       // from the database.The next link should have a from parameter pointing
+                       // to the until parameter of the current page.
+                       if ( $this->nextPage[$type] !== null ) {
+                               return $this->pagingLinks( $this->prevPage[$type], $this->until[$type], $type );
+                       } else {
+                               // If the nextPage variable is null, it means that we have reached the first page
+                               // and therefore the previous link should be disabled.
+                               return $this->pagingLinks( null, $this->until[$type], $type );
+                       }
                } elseif ( $this->nextPage[$type] !== null
                        || ( isset( $this->from[$type] ) && $this->from[$type] !== null )
                ) {
@@ -708,7 +728,7 @@ class CategoryViewer extends ContextSource {
                        // quick due to the small number of entries.
                        $totalcnt = $rescnt;
                        $category = $this->cat;
-                       wfGetDB( DB_MASTER )->onTransactionIdle( function() use ( $category ) {
+                       wfGetDB( DB_MASTER )->onTransactionIdle( function () use ( $category ) {
                                $category->refreshCounts();
                        } );
                } else {
diff --git a/includes/Categoryfinder.php b/includes/Categoryfinder.php
deleted file mode 100644 (file)
index b9cbc9a..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-<?php
-/**
- * Recent changes filtering by category.
- *
- * 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
- */
-
-/**
- * The "Categoryfinder" class takes a list of articles, creates an internal
- * representation of all their parent categories (as well as parents of
- * parents etc.). From this representation, it determines which of these
- * articles are in one or all of a given subset of categories.
- *
- * Example use :
- * <code>
- *     # Determines whether the article with the page_id 12345 is in both
- *     # "Category 1" and "Category 2" or their subcategories, respectively
- *
- *     $cf = new Categoryfinder;
- *     $cf->seed(
- *         array( 12345 ),
- *         array( 'Category 1', 'Category 2' ),
- *         'AND'
- *     );
- *     $a = $cf->run();
- *     print implode( ',' , $a );
- * </code>
- *
- */
-class Categoryfinder {
-       /** @var int[] The original article IDs passed to the seed function */
-       protected $articles = array();
-
-       /** @var array Array of DBKEY category names for categories that don't have a page */
-       protected $deadend = array();
-
-       /** @var array Array of [ID => array()] */
-       protected $parents = array();
-
-       /** @var array Array of article/category IDs */
-       protected $next = array();
-
-       /** @var array Array of DBKEY category names */
-       protected $targets = array();
-
-       /** @var array */
-       protected $name2id = array();
-
-       /** @var  "AND" or "OR" */
-       protected $mode;
-
-       /** @var DatabaseBase Read-DB slave */
-       protected $dbr;
-
-       function __construct() {
-       }
-
-       /**
-        * Initializes the instance. Do this prior to calling run().
-        * @param array $article_ids Array of article IDs
-        * @param array $categories FIXME
-        * @param string $mode FIXME, default 'AND'.
-        * @todo FIXME: $categories/$mode
-        */
-       function seed( $article_ids, $categories, $mode = 'AND' ) {
-               $this->articles = $article_ids;
-               $this->next = $article_ids;
-               $this->mode = $mode;
-
-               # Set the list of target categories; convert them to DBKEY form first
-               $this->targets = array();
-               foreach ( $categories as $c ) {
-                       $ct = Title::makeTitleSafe( NS_CATEGORY, $c );
-                       if ( $ct ) {
-                               $c = $ct->getDBkey();
-                               $this->targets[$c] = $c;
-                       }
-               }
-       }
-
-       /**
-        * Iterates through the parent tree starting with the seed values,
-        * then checks the articles if they match the conditions
-        * @return array of page_ids (those given to seed() that match the conditions)
-        */
-       function run() {
-               $this->dbr = wfGetDB( DB_SLAVE );
-               while ( count( $this->next ) > 0 ) {
-                       $this->scan_next_layer();
-               }
-
-               # Now check if this applies to the individual articles
-               $ret = array();
-
-               foreach ( $this->articles as $article ) {
-                       $conds = $this->targets;
-                       if ( $this->check( $article, $conds ) ) {
-                               # Matches the conditions
-                               $ret[] = $article;
-                       }
-               }
-               return $ret;
-       }
-
-       /**
-        * This functions recurses through the parent representation, trying to match the conditions
-        * @param int $id The article/category to check
-        * @param array $conds The array of categories to match
-        * @param array $path Used to check for recursion loops
-        * @return bool Does this match the conditions?
-        */
-       function check( $id, &$conds, $path = array() ) {
-               // Check for loops and stop!
-               if ( in_array( $id, $path ) ) {
-                       return false;
-               }
-
-               $path[] = $id;
-
-               # Shortcut (runtime paranoia): No conditions=all matched
-               if ( count( $conds ) == 0 ) {
-                       return true;
-               }
-
-               if ( !isset( $this->parents[$id] ) ) {
-                       return false;
-               }
-
-               # iterate through the parents
-               foreach ( $this->parents[$id] as $p ) {
-                       $pname = $p->cl_to;
-
-                       # Is this a condition?
-                       if ( isset( $conds[$pname] ) ) {
-                               # This key is in the category list!
-                               if ( $this->mode == 'OR' ) {
-                                       # One found, that's enough!
-                                       $conds = array();
-                                       return true;
-                               } else {
-                                       # Assuming "AND" as default
-                                       unset( $conds[$pname] );
-                                       if ( count( $conds ) == 0 ) {
-                                               # All conditions met, done
-                                               return true;
-                                       }
-                               }
-                       }
-
-                       # Not done yet, try sub-parents
-                       if ( !isset( $this->name2id[$pname] ) ) {
-                               # No sub-parent
-                               continue;
-                       }
-                       $done = $this->check( $this->name2id[$pname], $conds, $path );
-                       if ( $done || count( $conds ) == 0 ) {
-                               # Subparents have done it!
-                               return true;
-                       }
-               }
-               return false;
-       }
-
-       /**
-        * Scans a "parent layer" of the articles/categories in $this->next
-        */
-       function scan_next_layer() {
-               wfProfileIn( __METHOD__ );
-
-               # Find all parents of the article currently in $this->next
-               $layer = array();
-               $res = $this->dbr->select(
-                       /* FROM   */ 'categorylinks',
-                       /* SELECT */ '*',
-                       /* WHERE  */ array( 'cl_from' => $this->next ),
-                       __METHOD__ . '-1'
-               );
-               foreach ( $res as $o ) {
-                       $k = $o->cl_to;
-
-                       # Update parent tree
-                       if ( !isset( $this->parents[$o->cl_from] ) ) {
-                               $this->parents[$o->cl_from] = array();
-                       }
-                       $this->parents[$o->cl_from][$k] = $o;
-
-                       # Ignore those we already have
-                       if ( in_array( $k, $this->deadend ) ) {
-                               continue;
-                       }
-
-                       if ( isset( $this->name2id[$k] ) ) {
-                               continue;
-                       }
-
-                       # Hey, new category!
-                       $layer[$k] = $k;
-               }
-
-               $this->next = array();
-
-               # Find the IDs of all category pages in $layer, if they exist
-               if ( count( $layer ) > 0 ) {
-                       $res = $this->dbr->select(
-                               /* FROM   */ 'page',
-                               /* SELECT */ array( 'page_id', 'page_title' ),
-                               /* WHERE  */ array( 'page_namespace' => NS_CATEGORY, 'page_title' => $layer ),
-                               __METHOD__ . '-2'
-                       );
-                       foreach ( $res as $o ) {
-                               $id = $o->page_id;
-                               $name = $o->page_title;
-                               $this->name2id[$name] = $id;
-                               $this->next[] = $id;
-                               unset( $layer[$name] );
-                       }
-               }
-
-               # Mark dead ends
-               foreach ( $layer as $v ) {
-                       $this->deadend[$v] = $v;
-               }
-
-               wfProfileOut( __METHOD__ );
-       }
-}
index f51a5a8..94b7b7a 100644 (file)
@@ -63,7 +63,7 @@ class ChangeTags {
        /**
         * Get a short description for a tag
         *
-        * @param string $tag tag
+        * @param string $tag Tag
         *
         * @return string Short description of the tag from "mediawiki:tag-$tag" if this message exists,
         *   html-escaped version of $tag otherwise
@@ -77,15 +77,15 @@ class ChangeTags {
         * Add tags to a change given its rc_id, rev_id and/or log_id
         *
         * @param string|array $tags Tags to add to the change
-        * @param int|null $rc_id rc_id of the change to add the tags to
-        * @param int|null $rev_id rev_id of the change to add the tags to
-        * @param int|null $log_id Log_id of the change to add the tags to
-        * @param string $params params to put in the ct_params field of table 'change_tag'
+        * @param int|null $rc_id The rc_id of the change to add the tags to
+        * @param int|null $rev_id The rev_id of the change to add the tags to
+        * @param int|null $log_id The log_id of the change to add the tags to
+        * @param string $params Params to put in the ct_params field of table 'change_tag'
         *
         * @throws MWException
-        * @return bool false if no changes are made, otherwise true
+        * @return bool False if no changes are made, otherwise true
         *
-        * @exception MWException when $rc_id, $rev_id and $log_id are all null
+        * @exception MWException When $rc_id, $rev_id and $log_id are all null
         */
        public static function addTags( $tags, $rc_id = null, $rev_id = null,
                $log_id = null, $params = null
@@ -236,7 +236,7 @@ class ChangeTags {
        /**
         * Build a text box to select a change tag
         *
-        * @param string $selected tag to select by default
+        * @param string $selected Tag to select by default
         * @param bool $fullForm
         *        - if false, then it returns an array of (label, form).
         *        - if true, it returns an entire form around the selector.
diff --git a/includes/ChangesFeed.php b/includes/ChangesFeed.php
deleted file mode 100644 (file)
index fb491e5..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-<?php
-/**
- * Feed for list of changes.
- *
- * 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
- */
-
-/**
- * Feed to Special:RecentChanges and Special:RecentChangesLiked
- *
- * @ingroup Feed
- */
-class ChangesFeed {
-       public $format, $type, $titleMsg, $descMsg;
-
-       /**
-        * Constructor
-        *
-        * @param string $format Feed's format (either 'rss' or 'atom')
-        * @param string $type Type of feed (for cache keys)
-        */
-       public function __construct( $format, $type ) {
-               $this->format = $format;
-               $this->type = $type;
-       }
-
-       /**
-        * Get a ChannelFeed subclass object to use
-        *
-        * @param string $title Feed's title
-        * @param string $description Feed's description
-        * @param string $url Url of origin page
-        * @return ChannelFeed|bool ChannelFeed subclass or false on failure
-        */
-       public function getFeedObject( $title, $description, $url ) {
-               global $wgSitename, $wgLanguageCode, $wgFeedClasses;
-
-               if ( !isset( $wgFeedClasses[$this->format] ) ) {
-                       return false;
-               }
-
-               if ( !array_key_exists( $this->format, $wgFeedClasses ) ) {
-                       // falling back to atom
-                       $this->format = 'atom';
-               }
-
-               $feedTitle = "$wgSitename  - {$title} [$wgLanguageCode]";
-               return new $wgFeedClasses[$this->format](
-                       $feedTitle, htmlspecialchars( $description ), $url );
-       }
-
-       /**
-        * Generates feed's content
-        *
-        * @param ChannelFeed $feed ChannelFeed subclass object (generally the one returned
-        *   by getFeedObject())
-        * @param ResultWrapper $rows ResultWrapper object with rows in recentchanges table
-        * @param int $lastmod Timestamp of the last item in the recentchanges table (only
-        *   used for the cache key)
-        * @param FormOptions $opts As in SpecialRecentChanges::getDefaultOptions()
-        * @return null|bool True or null
-        */
-       public function execute( $feed, $rows, $lastmod, $opts ) {
-               global $wgLang, $wgRenderHashAppend;
-
-               if ( !FeedUtils::checkFeedOutput( $this->format ) ) {
-                       return null;
-               }
-
-               $optionsHash = md5( serialize( $opts->getAllValues() ) ) . $wgRenderHashAppend;
-               $timekey = wfMemcKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash, 'timestamp' );
-               $key = wfMemcKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash );
-
-               FeedUtils::checkPurge( $timekey, $key );
-
-               /**
-                * Bumping around loading up diffs can be pretty slow, so where
-                * possible we want to cache the feed output so the next visitor
-                * gets it quick too.
-                */
-               $cachedFeed = $this->loadFromCache( $lastmod, $timekey, $key );
-               if ( is_string( $cachedFeed ) ) {
-                       wfDebug( "RC: Outputting cached feed\n" );
-                       $feed->httpHeaders();
-                       echo $cachedFeed;
-               } else {
-                       wfDebug( "RC: rendering new feed and caching it\n" );
-                       ob_start();
-                       self::generateFeed( $rows, $feed );
-                       $cachedFeed = ob_get_contents();
-                       ob_end_flush();
-                       $this->saveToCache( $cachedFeed, $timekey, $key );
-               }
-               return true;
-       }
-
-       /**
-        * Save to feed result to $messageMemc
-        *
-        * @param string $feed Feed's content
-        * @param string $timekey Memcached key of the last modification
-        * @param string $key Memcached key of the content
-        */
-       public function saveToCache( $feed, $timekey, $key ) {
-               global $messageMemc;
-               $expire = 3600 * 24; # One day
-               $messageMemc->set( $key, $feed, $expire );
-               $messageMemc->set( $timekey, wfTimestamp( TS_MW ), $expire );
-       }
-
-       /**
-        * Try to load the feed result from $messageMemc
-        *
-        * @param int $lastmod Timestamp of the last item in the recentchanges table
-        * @param string $timekey Memcached key of the last modification
-        * @param string $key Memcached key of the content
-        * @return string|bool Feed's content on cache hit or false on cache miss
-        */
-       public function loadFromCache( $lastmod, $timekey, $key ) {
-               global $wgFeedCacheTimeout, $wgOut, $messageMemc;
-
-               $feedLastmod = $messageMemc->get( $timekey );
-
-               if ( ( $wgFeedCacheTimeout > 0 ) && $feedLastmod ) {
-                       /**
-                        * If the cached feed was rendered very recently, we may
-                        * go ahead and use it even if there have been edits made
-                        * since it was rendered. This keeps a swarm of requests
-                        * from being too bad on a super-frequently edited wiki.
-                        */
-
-                       $feedAge = time() - wfTimestamp( TS_UNIX, $feedLastmod );
-                       $feedLastmodUnix = wfTimestamp( TS_UNIX, $feedLastmod );
-                       $lastmodUnix = wfTimestamp( TS_UNIX, $lastmod );
-
-                       if ( $feedAge < $wgFeedCacheTimeout || $feedLastmodUnix > $lastmodUnix ) {
-                               wfDebug( "RC: loading feed from cache ($key; $feedLastmod; $lastmod)...\n" );
-                               if ( $feedLastmodUnix < $lastmodUnix ) {
-                                       $wgOut->setLastModified( $feedLastmod ); // bug 21916
-                               }
-                               return $messageMemc->get( $key );
-                       } else {
-                               wfDebug( "RC: cached feed timestamp check failed ($feedLastmod; $lastmod)\n" );
-                       }
-               }
-               return false;
-       }
-
-       /**
-        * Generate the feed items given a row from the database, printing the feed.
-        * @param object $rows DatabaseBase resource with recentchanges rows
-        * @param Feed $feed
-        */
-       public static function generateFeed( $rows, &$feed ) {
-               wfProfileIn( __METHOD__ );
-               $items = self::buildItems( $rows );
-               $feed->outHeader();
-               foreach ( $items as $item ) {
-                       $feed->outItem( $item );
-               }
-               $feed->outFooter();
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * Generate the feed items given a row from the database.
-        * @param object $rows DatabaseBase resource with recentchanges rows
-        */
-       public static function buildItems( $rows ) {
-               wfProfileIn( __METHOD__ );
-               $items = array();
-
-               # Merge adjacent edits by one user
-               $sorted = array();
-               $n = 0;
-               foreach ( $rows as $obj ) {
-                       if ( $n > 0 &&
-                               $obj->rc_type == RC_EDIT &&
-                               $obj->rc_namespace >= 0 &&
-                               $obj->rc_cur_id == $sorted[$n - 1]->rc_cur_id &&
-                               $obj->rc_user_text == $sorted[$n - 1]->rc_user_text ) {
-                               $sorted[$n - 1]->rc_last_oldid = $obj->rc_last_oldid;
-                       } else {
-                               $sorted[$n] = $obj;
-                               $n++;
-                       }
-               }
-
-               foreach ( $sorted as $obj ) {
-                       $title = Title::makeTitle( $obj->rc_namespace, $obj->rc_title );
-                       $talkpage = MWNamespace::canTalk( $obj->rc_namespace )
-                               ? $title->getTalkPage()->getFullURL()
-                               : '';
-
-                       // Skip items with deleted content (avoids partially complete/inconsistent output)
-                       if ( $obj->rc_deleted ) {
-                               continue;
-                       }
-
-                       if ( $obj->rc_this_oldid ) {
-                               $url = $title->getFullURL( array(
-                                       'diff' => $obj->rc_this_oldid,
-                                       'oldid' => $obj->rc_last_oldid,
-                               ) );
-                       } else {
-                               // log entry or something like that.
-                               $url = $title->getFullURL();
-                       }
-
-                       $items[] = new FeedItem(
-                               $title->getPrefixedText(),
-                               FeedUtils::formatDiff( $obj ),
-                               $url,
-                               $obj->rc_timestamp,
-                               ( $obj->rc_deleted & Revision::DELETED_USER )
-                                       ? wfMessage( 'rev-deleted-user' )->escaped() : $obj->rc_user_text,
-                               $talkpage
-                       );
-               }
-
-               wfProfileOut( __METHOD__ );
-               return $items;
-       }
-}
index 71adb09..1c2c2db 100644 (file)
@@ -49,6 +49,8 @@ abstract class Collation {
                                return new IcuCollation( 'root' );
                        case 'xx-uca-ckb':
                                return new CollationCkb;
+                       case 'xx-uca-et':
+                               return new CollationEt;
                        default:
                                $match = array();
                                if ( preg_match( '/^uca-([a-z@=-]+)$/', $collationName, $match ) ) {
@@ -160,7 +162,7 @@ class IcuCollation extends Collation {
        /** @var Collator */
        private $mainCollator;
 
-       /** @var  */
+       /** @var string */
        private $locale;
 
        /** @var Language */
@@ -253,7 +255,7 @@ class IcuCollation extends Collation {
                'el' => array(),
                'eo' => array( "Ĉ", "Ĝ", "Ĥ", "Ĵ", "Ŝ", "Ŭ" ),
                'es' => array( "Ñ" ),
-               'et' => array( "Š", "Ž", "Õ", "Ä", "Ö", "Ü" ),
+               'et' => array( "Š", "Ž", "Õ", "Ä", "Ö", "Ü", "W" ), // added W for CollationEt (xx-uca-et)
                'eu' => array( "Ñ" ),
                'fo' => array( "Á", "Ð", "Í", "Ó", "Ú", "Ý", "Æ", "Ø", "Å" ),
                'fur' => array( "À", "Á", "Â", "È", "Ì", "Ò", "Ù" ),
@@ -365,7 +367,12 @@ class IcuCollation extends Collation {
                }
 
                $cache = wfGetCache( CACHE_ANYTHING );
-               $cacheKey = wfMemcKey( 'first-letters', $this->locale, $this->digitTransformLanguage->getCode() );
+               $cacheKey = wfMemcKey(
+                       'first-letters',
+                       $this->locale,
+                       $this->digitTransformLanguage->getCode(),
+                       self::getICUVersion()
+               );
                $cacheEntry = $cache->get( $cacheKey );
 
                if ( $cacheEntry && isset( $cacheEntry['version'] )
@@ -597,3 +604,42 @@ class CollationCkb extends IcuCollation {
                $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(
+                       array( '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 b8d34e2..cb04190 100644 (file)
@@ -90,13 +90,16 @@ class Cookie {
         * @return bool
         */
        public static function validateCookieDomain( $domain, $originDomain = null ) {
-               // Don't allow a trailing dot
-               if ( substr( $domain, -1 ) == '.' ) {
+               $dc = explode( ".", $domain );
+
+               // Don't allow a trailing dot or addresses without a or just a leading dot
+               if ( substr( $domain, -1 ) == '.' ||
+                       count( $dc ) <= 1 ||
+                       count( $dc ) == 2 && $dc[0] === ''
+               ) {
                        return false;
                }
 
-               $dc = explode( ".", $domain );
-
                // Only allow full, valid IP addresses
                if ( preg_match( '/^[0-9.]+$/', $domain ) ) {
                        if ( count( $dc ) != 4 ) {
index 05c7696..8b29733 100644 (file)
@@ -355,11 +355,6 @@ $wgEnableAsyncUploads = false;
  */
 $wgIllegalFileChars = ":";
 
-/**
- * @deprecated since 1.17 use $wgDeletedDirectory
- */
-$wgFileStore = array();
-
 /**
  * What directory to place deleted uploads in.
  * Defaults to "{$wgUploadDirectory}/deleted".
@@ -763,7 +758,7 @@ $wgFileBlacklist = array(
        'exe', 'scr', 'dll', 'msi', 'vbs', 'bat', 'com', 'pif', 'cmd', 'vxd', 'cpl' );
 
 /**
- * Files with these mime types will never be allowed as uploads
+ * Files with these MIME types will never be allowed as uploads
  * if $wgVerifyMimeType is enabled.
  */
 $wgMimeTypeBlacklist = array(
@@ -815,7 +810,7 @@ $wgDisableUploadScriptChecks = false;
 $wgUploadSizeWarning = false;
 
 /**
- * list of trusted media-types and mime types.
+ * list of trusted media-types and MIME types.
  * Use the MEDIATYPE_xxx constants to represent media types.
  * This list is used by File::isSafeFile
  *
@@ -863,9 +858,11 @@ $wgContentHandlers = array(
        CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler',
        // dumb version, no syntax highlighting
        CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler',
+       // simple implementation, for use by extensions, etc.
+       CONTENT_MODEL_JSON => 'JsonContentHandler',
        // dumb version, no syntax highlighting
        CONTENT_MODEL_CSS => 'CssContentHandler',
-       // plain text, for use by extensions etc
+       // plain text, for use by extensions, etc.
        CONTENT_MODEL_TEXT => 'TextContentHandler',
 );
 
@@ -1138,45 +1135,45 @@ $wgAntivirusSetup = array(
 $wgAntivirusRequired = true;
 
 /**
- * Determines if the mime type of uploaded files should be checked
+ * Determines if the MIME type of uploaded files should be checked
  */
 $wgVerifyMimeType = true;
 
 /**
- * Sets the mime type definition file to use by MimeMagic.php.
+ * Sets the MIME type definition file to use by MimeMagic.php.
  * Set to null, to use built-in defaults only.
  * example: $wgMimeTypeFile = '/etc/mime.types';
  */
 $wgMimeTypeFile = 'includes/mime.types';
 
 /**
- * Sets the mime type info file to use by MimeMagic.php.
+ * Sets the MIME type info file to use by MimeMagic.php.
  * Set to null, to use built-in defaults only.
  */
 $wgMimeInfoFile = 'includes/mime.info';
 
 /**
- * Sets an external mime detector program. The command must print only
- * the mime type to standard output.
+ * Sets an external MIME detector program. The command must print only
+ * the MIME type to standard output.
  * The name of the file to process will be appended to the command given here.
- * If not set or NULL, mime_content_type will be used if available.
+ * If not set or NULL, PHP's fileinfo extension will be used if available.
  *
  * @par Example:
  * @code
- * #$wgMimeDetectorCommand = "file -bi"; # use external mime detector (Linux)
+ * #$wgMimeDetectorCommand = "file -bi"; # use external MIME detector (Linux)
  * @endcode
  */
 $wgMimeDetectorCommand = null;
 
 /**
- * Switch for trivial mime detection. Used by thumb.php to disable all fancy
+ * Switch for trivial MIME detection. Used by thumb.php to disable all fancy
  * things, because only a few types of images are needed and file extensions
  * can be trusted.
  */
 $wgTrivialMimeDetection = false;
 
 /**
- * Additional XML types we can allow via mime-detection.
+ * Additional XML types we can allow via MIME-detection.
  * array = ( 'rootElement' => 'associatedMimeType' )
  */
 $wgXMLMimeTypes = array(
@@ -1229,9 +1226,10 @@ $wgThumbLimits = array(
 $wgThumbnailBuckets = null;
 
 /**
- * When using thumbnail buckets as defined above, this sets the minimum distance with the bucket
- * above the requested size. The distance represents how pany extra pixels of width the bucket needs
- * in order to be used as the reference for a given thumbnail. For example, with the following buckets:
+ * When using thumbnail buckets as defined above, this sets the minimum distance to the bucket
+ * above the requested size. The distance represents how many extra pixels of width the bucket
+ * needs in order to be used as the reference for a given thumbnail. For example, with the
+ * following buckets:
  *
  * $wgThumbnailBuckets = array ( 128, 256, 512 );
  *
@@ -1242,7 +1240,7 @@ $wgThumbnailBuckets = null;
  * If we want to render a thumbnail of width 220px, the 512px bucket will be used,
  * because 220 + 50 = 270 and the closest bucket bigger than 270px is 512.
  */
-$wgThumbnailMinimumBucketDistance = 0;
+$wgThumbnailMinimumBucketDistance = 50;
 
 /**
  * Default parameters for the "<gallery>" tag
@@ -2077,6 +2075,28 @@ $wgObjectCaches = array(
        'hash' => array( 'class' => 'HashBagOStuff' ),
 );
 
+/**
+ * Map of bloom filter store names to configuration arrays.
+ *
+ * Example:
+ * $wgBloomFilterStores['main'] = array(
+ *  'cacheId'      => 'main-v1',
+ *  'class'        => 'BloomCacheRedis',
+ *  'redisServers' => array( '127.0.0.1:6379' ),
+ *  'redisConfig'  => array( 'connectTimeout' => 2 )
+ * );
+ *
+ * A primary bloom filter must be created manually.
+ * Example in eval.php:
+ * <code>
+ *     BloomCache::get( 'main' )->init( 'shared', 1000000000, .001 );
+ * </code>
+ * The size should be as large as practical given wiki size and resources.
+ *
+ * @since 1.24
+ */
+$wgBloomFilterStores = array();
+
 /**
  * The expiry time for the parser cache, in seconds.
  * The default is 86400 (one day).
@@ -2449,42 +2469,6 @@ $wgSquidPurgeUseHostHeader = true;
  */
 $wgHTCPRouting = array();
 
-/**
- * @deprecated since 1.22, please use $wgHTCPRouting instead.
- *
- * Whenever this is set and $wgHTCPRouting evaluates to false, $wgHTCPRouting
- * will be set to this value.
- * This is merely for back compatibility.
- *
- * @since 1.20
- */
-$wgHTCPMulticastRouting = null;
-
-/**
- * HTCP multicast address. Set this to a multicast IP address to enable HTCP.
- *
- * Note that MediaWiki uses the old non-RFC compliant HTCP format, which was
- * present in the earliest Squid implementations of the protocol.
- *
- * This setting is DEPRECATED in favor of $wgHTCPRouting , and kept for
- * backwards compatibility only. If $wgHTCPRouting is set, this setting is
- * ignored. If $wgHTCPRouting is not set and this setting is, it is used to
- * populate $wgHTCPRouting.
- *
- * @deprecated since 1.20 in favor of $wgHTCPMulticastRouting and since 1.22 in
- * favor of $wgHTCPRouting.
- */
-$wgHTCPMulticastAddress = false;
-
-/**
- * HTCP multicast port.
- * @deprecated since 1.20 in favor of $wgHTCPMulticastRouting and since 1.22 in
- * favor of $wgHTCPRouting.
- *
- * @see $wgHTCPMulticastAddress
- */
-$wgHTCPPort = 4827;
-
 /**
  * HTCP multicast TTL.
  * @see $wgHTCPRouting
@@ -2737,11 +2721,6 @@ $wgDisableLangConversion = false;
  */
 $wgDisableTitleConversion = false;
 
-/**
- * Whether to enable canonical language links in meta data.
- */
-$wgCanonicalLanguageLinks = true;
-
 /**
  * Default variant code, if false, the default will be the language code
  */
@@ -2889,6 +2868,23 @@ $wgHtml5 = true;
  */
 $wgHtml5Version = null;
 
+/**
+ * Temporary variable that allows HTMLForms to be rendered as tables.
+ * Table based layouts cause various issues when designing for mobile.
+ * This global allows skins or extensions a means to force non-table based rendering.
+ * Setting to false forces form components to always render as div elements.
+ * @since 1.24
+ */
+$wgHTMLFormAllowTableFormat = true;
+
+/**
+ * Temporary variable that applies MediaWiki UI wherever it can be supported.
+ * Temporary variable that should be removed when mediawiki ui is more
+ * stable and change has been communicated.
+ * @since 1.24
+ */
+$wgUseMediaWikiUIEverywhere = false;
+
 /**
  * Enabled RDFa attributes for use in wikitext.
  * NOTE: Interaction with HTML5 is somewhat underspecified.
@@ -2930,7 +2926,7 @@ $wgWellFormedXml = true;
  * Normally we wouldn't have to define this in the root "<html>"
  * element, but IE needs it there in some circumstances.
  *
- * This is ignored if $wgMimeType is set to a non-XML mimetype.
+ * This is ignored if $wgMimeType is set to a non-XML MIME type.
  */
 $wgXhtmlNamespaces = array();
 
@@ -2964,25 +2960,28 @@ $wgValidateAllHtml = false;
 /**
  * Default skin, for new users and anonymous visitors. Registered users may
  * change this to any one of the other available skins in their preferences.
- * This has to be completely lowercase; see the "skins" directory for the list
- * of available skins.
  */
 $wgDefaultSkin = 'vector';
 
 /**
- * Specify the name of a skin that should not be presented in the list of
- * available skins.  Use for blacklisting a skin which you do not want to
- * remove from the .../skins/ directory
+ * Fallback skin used when the skin defined by $wgDefaultSkin can't be found.
  *
- * @deprecated since 1.23; use $wgSkipSkins instead
+ * @since 1.24
  */
-$wgSkipSkin = '';
+$wgFallbackSkin = 'fallback';
 
 /**
- * Array for more like $wgSkipSkin.
+ * Specify the names of skins that should not be presented in the list of
+ * available skins in user preferences. If you want to remove a skin entirely,
+ * remove it from the skins/ directory and its entry from LocalSettings.php.
  */
 $wgSkipSkins = array();
 
+/**
+ * @deprecated since 1.23; use $wgSkipSkins instead
+ */
+$wgSkipSkin = '';
+
 /**
  * Allow user Javascript page?
  * This enables a lot of neat customizations, but may
@@ -3103,7 +3102,7 @@ $wgFooterIcons = array(
        ),
        "poweredby" => array(
                "mediawiki" => array(
-                       "src" => null, // Defaults to "$wgStylePath/common/images/poweredby_mediawiki_88x31.png"
+                       "src" => null, // Defaults to "$wgScriptPath/assets/poweredby_mediawiki_88x31.png"
                        "url" => "//www.mediawiki.org/",
                        "alt" => "Powered by MediaWiki",
                )
@@ -3118,20 +3117,6 @@ $wgFooterIcons = array(
  */
 $wgUseCombinedLoginLink = false;
 
-/**
- * Search form look for Vector skin only.
- *  - true = use an icon search button
- *  - false = use Go & Search buttons
- */
-$wgVectorUseSimpleSearch = true;
-
-/**
- * Watch and unwatch as an icon rather than a link for Vector skin only.
- *  - true = use an icon watch/unwatch button
- *  - false = use watch/unwatch text link
- */
-$wgVectorUseIconWatch = true;
-
 /**
  * Display user edit counts in various prominent places.
  */
@@ -3194,6 +3179,111 @@ $wgEnableCanonicalServerLink = false;
  */
 $wgResourceModules = array();
 
+/**
+ * Skin-specific styles for resource modules.
+ *
+ * These are later added to the 'skinStyles' list of the existing module. The 'styles' list can
+ * not be modified or disabled.
+ *
+ * For example, here is a module "bar" and how skin Foo would provide additional styles for it.
+ *
+ * @par Example:
+ * @code
+ *   $wgResourceModules['bar'] = array(
+ *     'scripts' => 'resources/bar/bar.js',
+ *     'styles' => 'resources/bar/main.css',
+ *   );
+ *
+ *   $wgResourceModuleSkinStyles['foo'] = array(
+ *     'bar' => 'skins/Foo/bar.css',
+ *   );
+ * @endcode
+ *
+ * This is mostly equivalent to:
+ *
+ * @par Equivalent:
+ * @code
+ *   $wgResourceModules['bar'] = array(
+ *     'scripts' => 'resources/bar/bar.js',
+ *     'styles' => 'resources/bar/main.css',
+ *     'skinStyles' => array(
+ *       'foo' => skins/Foo/bar.css',
+ *     ),
+ *   );
+ * @endcode
+ *
+ * If the module already defines its own entry in `skinStyles` for a given skin, then
+ * $wgResourceModuleSkinStyles is ignored.
+ *
+ * If a module defines a `skinStyles['default']` the skin may want to extend that instead
+ * of replacing them. This can be done using the `+` prefix.
+ *
+ * @par Example:
+ * @code
+ *   $wgResourceModules['bar'] = array(
+ *     'scripts' => 'resources/bar/bar.js',
+ *     'styles' => 'resources/bar/basic.css',
+ *     'skinStyles' => array(
+ *       'default' => 'resources/bar/additional.css',
+ *     ),
+ *   );
+ *   // Note the '+' character:
+ *   $wgResourceModuleSkinStyles['+foo'] = array(
+ *     'bar' => 'skins/Foo/bar.css',
+ *   );
+ * @endcode
+ *
+ * This is mostly equivalent to:
+ *
+ * @par Equivalent:
+ * @code
+ *   $wgResourceModules['bar'] = array(
+ *     'scripts' => 'resources/bar/bar.js',
+ *     'styles' => 'resources/bar/basic.css',
+ *     'skinStyles' => array(
+ *       'default' => 'resources/bar/additional.css',
+ *       'foo' => array(
+ *         'resources/bar/additional.css',
+ *         'skins/Foo/bar.css',
+ *       ),
+ *     ),
+ *   );
+ * @endcode
+ *
+ * In other words, as a module author, use the `styles` list for stylesheets that may not be
+ * disabled by a skin. To provide default styles that may be extended or replaced,
+ * use `skinStyles['default']`.
+ *
+ * As with $wgResourceModules, paths default to being relative to the MediaWiki root.
+ * You should always provide a localBasePath and remoteBasePath (or remoteExtPath/remoteSkinPath).
+ * Either for all skin styles at once (first example below) or for each module separately (second
+ * example).
+ *
+ * @par Example:
+ * @code
+ *   $wgResourceModuleSkinStyles['foo'] = array(
+ *     'bar' => 'bar.css',
+ *     'quux' => 'quux.css',
+ *     'remoteSkinPath' => 'Foo',
+ *     'localBasePath' => __DIR__,
+ *   );
+ *
+ *   $wgResourceModuleSkinStyles['foo'] = array(
+ *     'bar' => array(
+ *       'bar.css',
+ *       'remoteSkinPath' => 'Foo',
+ *       'localBasePath' => __DIR__,
+ *     ),
+ *     'quux' => array(
+ *       'quux.css',
+ *       'remoteSkinPath' => 'Foo',
+ *       'localBasePath' => __DIR__,
+ *     ),
+ *   );
+ * @endcode
+ */
+$wgResourceModuleSkinStyles = array();
+
 /**
  * Extensions should register foreign module sources here. 'local' is a
  * built-in source that is not in this array, but defined by
@@ -3201,10 +3291,7 @@ $wgResourceModules = array();
  *
  * @par Example:
  * @code
- *   $wgResourceLoaderSources['foo'] = array(
- *       'loadScript' => 'http://example.org/w/load.php',
- *       'apiScript' => 'http://example.org/w/api.php'
- *   );
+ *   $wgResourceLoaderSources['foo'] = 'http://example.org/w/load.php';
  * @endcode
  */
 $wgResourceLoaderSources = array();
@@ -3373,12 +3460,14 @@ $wgResourceLoaderValidateStaticJS = false;
 $wgResourceLoaderExperimentalAsyncLoading = false;
 
 /**
- * Global LESS variables. An associative array binding variable names to CSS
- * string values.
+ * Global LESS variables. An associative array binding variable names to
+ * LESS code snippets representing their values.
+ *
+ * Adding an item here is equivalent to writing `@variable: value;`
+ * at the beginning of all your .less files, with all the consequences.
+ * In particular, string values must be escaped and quoted.
  *
- * Because the hashed contents of this array are used to construct the cache key
- * that ResourceLoader uses to look up LESS compilation results, updating this
- * array can be used to deliberately invalidate the set of cached results.
+ * Changes to LESS variables do not trigger cache invalidation.
  *
  * @par Example:
  * @code
@@ -3396,10 +3485,7 @@ $wgResourceLoaderLESSVars = array();
  * Custom LESS functions. An associative array mapping function name to PHP
  * callable.
  *
- * Changes to LESS functions do not trigger cache invalidation. If you update
- * the behavior of a LESS function and need to invalidate stale compilation
- * results, you can touch one of values in $wgResourceLoaderLESSVars, as
- * documented above.
+ * Changes to LESS functions do not trigger cache invalidation.
  *
  * @since 1.22
  */
@@ -3788,6 +3874,12 @@ $wgMaxPPExpandDepth = 40;
 
 /**
  * URL schemes that should be recognized as valid by wfParseUrl().
+ *
+ * WARNING: Do not add 'file:' to this or internal file links will be broken.
+ * Instead, if you want to support file links, add 'file://'. The same applies
+ * to any other protocols with the same name as a namespace. See bug #44011 for
+ * more information.
+ *
  * @see wfParseUrl
  */
 $wgUrlProtocols = array(
@@ -3984,9 +4076,6 @@ $wgTranscludeCacheExpiry = 3600;
  * - 'any': all pages as considered as valid articles
  * - 'comma': the page must contain a comma to be considered valid
  * - 'link': the page must contain a [[wiki link]] to be considered valid
- * - null: the value will be set at run time depending on $wgUseCommaCount:
- *         if $wgUseCommaCount is false, it will be 'link', if it is true
- *         it will be 'comma'
  *
  * See also See https://www.mediawiki.org/wiki/Manual:Article_count
  *
@@ -3994,13 +4083,7 @@ $wgTranscludeCacheExpiry = 3600;
  * to update it, you will need to run the maintenance/updateArticleCount.php
  * script.
  */
-$wgArticleCountMethod = null;
-
-/**
- * Backward compatibility setting, will set $wgArticleCountMethod if it is null.
- * @deprecated since 1.18; use $wgArticleCountMethod instead
- */
-$wgUseCommaCount = false;
+$wgArticleCountMethod = 'link';
 
 /**
  * wgHitcounterUpdateFreq sets how often page counters should be updated, higher
@@ -4029,6 +4112,7 @@ $wgActiveUserDays = 30;
 
 /**
  * For compatibility with old installations set to false
+ * @deprecated since 1.24 will be removed in future
  */
 $wgPasswordSalt = true;
 
@@ -4045,6 +4129,65 @@ $wgMinimalPasswordLength = 1;
  */
 $wgInvalidPasswordReset = true;
 
+/**
+ * Default password type to use when hashing user passwords
+ *
+ * @since 1.24
+ */
+$wgPasswordDefault = 'pbkdf2';
+
+/**
+ * Configuration for built-in password types. Maps the password type
+ * to an array of options. The 'class' option is the Password class to
+ * use. All other options are class-dependent.
+ *
+ * An advanced example:
+ * @code
+ * $wgPasswordConfig['bcrypt-peppered'] = array(
+ *     'class' => 'EncryptedPassword',
+ *     'underlying' => 'bcrypt',
+ *     'secrets' => array(),
+ *     'cipher' => MCRYPT_RIJNDAEL_256,
+ *     'mode' => MCRYPT_MODE_CBC,
+ *     'cost' => 5,
+ * );
+ * @endcode
+ *
+ * @since 1.24
+ */
+$wgPasswordConfig = array(
+       'A' => array(
+               'class' => 'MWOldPassword',
+       ),
+       'B' => array(
+               'class' => 'MWSaltedPassword',
+       ),
+       'pbkdf2-legacyA' => array(
+               'class' => 'LayeredParameterizedPassword',
+               'types' => array(
+                       'A',
+                       'pbkdf2',
+               ),
+       ),
+       'pbkdf2-legacyB' => array(
+               'class' => 'LayeredParameterizedPassword',
+               'types' => array(
+                       'B',
+                       'pbkdf2',
+               ),
+       ),
+       'bcrypt' => array(
+               'class' => 'BcryptPassword',
+               'cost' => 9,
+       ),
+       'pbkdf2' => array(
+               'class' => 'Pbkdf2Password',
+               'algo' => 'sha256',
+               'cost' => '10000',
+               'length' => '128',
+       ),
+);
+
 /**
  * Whether to allow password resets ("enter some identifying data, and we'll send an email
  * with a temporary password you can use to get back into the account") identified by
@@ -4124,7 +4267,7 @@ $wgDefaultUserOptions = array(
        'showtoolbar' => 1,
        'skin' => false,
        'stubthreshold' => 0,
-       'thumbsize' => 2,
+       'thumbsize' => 5,
        'underline' => 2,
        'uselivepreview' => 0,
        'usenewrc' => 0,
@@ -4139,6 +4282,7 @@ $wgDefaultUserOptions = array(
        'watchlisthideown' => 0,
        'watchlisthidepatrolled' => 0,
        'watchmoves' => 0,
+       'watchrollback' => 0,
        'wllimit' => 250,
        'useeditwarning' => 1,
        'prefershttps' => 1,
@@ -4397,7 +4541,7 @@ $wgGroupPermissions['sysop']['unblockself'] = true;
 $wgGroupPermissions['sysop']['suppressredirect'] = true;
 #$wgGroupPermissions['sysop']['pagelang'] = true;
 #$wgGroupPermissions['sysop']['upload_by_url'] = true;
-#$wgGroupPermissions['sysop']['mergehistory'] = true;
+$wgGroupPermissions['sysop']['mergehistory'] = true;
 
 // Permission to change users' group assignments
 $wgGroupPermissions['bureaucrat']['userrights'] = true;
@@ -4413,6 +4557,8 @@ $wgGroupPermissions['bureaucrat']['noratelimit'] = true;
 #$wgGroupPermissions['suppress']['hideuser'] = true;
 // To hide revisions/log items from users and Sysops
 #$wgGroupPermissions['suppress']['suppressrevision'] = true;
+// To view revisions/log items hidden from users and Sysops
+#$wgGroupPermissions['suppress']['viewsuppressed'] = true;
 // For private suppression log access
 #$wgGroupPermissions['suppress']['suppressionlog'] = true;
 
@@ -4712,12 +4858,6 @@ $wgSummarySpamRegex = array();
  */
 $wgEnableDnsBlacklist = false;
 
-/**
- * @deprecated since 1.17 Use $wgEnableDnsBlacklist instead, only kept for
- * backward compatibility.
- */
-$wgEnableSorbs = false;
-
 /**
  * List of DNS blacklists to use, if $wgEnableDnsBlacklist is true.
  *
@@ -4743,12 +4883,6 @@ $wgEnableSorbs = false;
  */
 $wgDnsBlacklistUrls = array( 'http.dnsbl.sorbs.net.' );
 
-/**
- * @deprecated since 1.17 Use $wgDnsBlacklistUrls instead, only kept for
- * backward compatibility.
- */
-$wgSorbsUrl = array();
-
 /**
  * Proxy whitelist, list of addresses that are assumed to be non-proxy despite
  * what the other methods might say.
@@ -5023,6 +5157,13 @@ $wgDebugDBTransactions = false;
  */
 $wgDebugDumpSql = false;
 
+/**
+ * Trim logged SQL queries to this many bytes. Set 0/false/null to do no
+ * trimming.
+ * @since 1.24
+ */
+$wgDebugDumpSqlLength = 500;
+
 /**
  * Map of string log group names to log destinations.
  *
@@ -5170,9 +5311,9 @@ $wgUDPProfilerPort = '3811';
 
 /**
  * Format string for the UDP profiler. The UDP profiler invokes sprintf() with
- * (profile id, count, cpu, cpu_sq, real, real_sq, entry name) as arguments.
- * You can use sprintf's argument numbering/swapping capability to repeat,
- * re-order or omit fields.
+ * (profile id, count, cpu, cpu_sq, real, real_sq, entry name, memory) as
+ * arguments. You can use sprintf's argument numbering/swapping capability to
+ * repeat, re-order or omit fields.
  *
  * @see $wgStatsFormatString
  * @since 1.22
@@ -5536,9 +5677,9 @@ $wgGitBin = '/usr/bin/git';
  */
 $wgGitRepositoryViewers = array(
        'https://(?:[a-z0-9_]+@)?gerrit.wikimedia.org/r/(?:p/)?(.*)' =>
-               'https://git.wikimedia.org/commit/%r/%H',
+               'https://git.wikimedia.org/tree/%r/%H',
        'ssh://(?:[a-z0-9_]+@)?gerrit.wikimedia.org:29418/(.*)' =>
-               'https://git.wikimedia.org/commit/%r/%H',
+               'https://git.wikimedia.org/tree/%r/%H',
 );
 
 /** @} */ # End of maintenance }
@@ -5576,48 +5717,6 @@ $wgRCLinkLimits = array( 50, 100, 250, 500 );
  */
 $wgRCLinkDays = array( 1, 3, 7, 14, 30 );
 
-/**
- * Send recent changes updates via UDP. The updates will be formatted for IRC.
- * Set this to the IP address of the receiver.
- *
- * @deprecated since 1.22, use $wgRCFeeds
- */
-$wgRC2UDPAddress = false;
-
-/**
- * Port number for RC updates
- *
- * @deprecated since 1.22, use $wgRCFeeds
- */
-$wgRC2UDPPort = false;
-
-/**
- * Prefix to prepend to each UDP packet.
- * This can be used to identify the wiki. A script is available called
- * mxircecho.py which listens on a UDP port, and uses a prefix ending in a
- * tab to identify the IRC channel to send the log line to.
- *
- * @deprecated since 1.22, use $wgRCFeeds
- */
-$wgRC2UDPPrefix = '';
-
-/**
- * If this is set to true, the first entry in the $wgLocalInterwikis array (or
- * the value of $wgLocalInterwiki, if set) will be prepended to links in the IRC
- * feed. If this is set to a string, that string will be used as the prefix.
- *
- * @deprecated since 1.22, use $wgRCFeeds
- */
-$wgRC2UDPInterwikiPrefix = false;
-
-/**
- * Set to true to omit "bot" edits (by users with the bot permission) from the
- * UDP feed.
- *
- * @deprecated since 1.22, use $wgRCFeeds
- */
-$wgRC2UDPOmitBots = false;
-
 /**
  * Destinations to which notifications about recent changes
  * should be sent.
@@ -5645,9 +5744,6 @@ $wgRC2UDPOmitBots = false;
  *  The JSON-specific options are:
  *   * 'channel' -- if set, the 'channel' parameter is also set in JSON values.
  *
- *  To ensure backwards-compatibility, whenever $wgRC2UDPAddress is set, a
- *  'default' feed will be created reusing the deprecated $wgRC2UDP* variables.
- *
  * @example $wgRCFeeds['example'] = array(
  *             'formatter' => 'JSONRCFeedFormatter',
  *             'uri' => "udp://localhost:1336",
@@ -5918,6 +6014,17 @@ $wgShowCreditsIfMax = true;
  * Special:Import (for sysops). Since complete page history can be imported,
  * these should be 'trusted'.
  *
+ * This can either be a regular array, or an associative map specifying
+ * subprojects on the interwiki map of the target wiki, or a mix of the two,
+ * e.g.
+ * @code
+ *     $wgImportSources = array(
+ *         'wikipedia' => array( 'cs', 'en', 'fr', 'zh' ),
+ *         'wikispecies',
+ *         'wikia' => array( 'animanga', 'brickipedia', 'desserts' ),
+ *     );
+ * @endcode
+ *
  * If a user has the 'import' permission but not the 'importupload' permission,
  * they will only be able to run imports through this transwiki interface.
  */
@@ -6072,13 +6179,12 @@ $wgParserOutputHooks = array();
 $wgEnableParserLimitReporting = true;
 
 /**
- * List of valid skin names.
+ * List of valid skin names
+ *
  * The key should be the name in all lower case, the value should be a properly
- * cased name for the skin. This value will be prefixed with "Skin" to create the
- * class name of the skin to load, and if the skin's class cannot be found through
- * the autoloader it will be used to load a .php file by that name in the skins directory.
- * The default skins will be added later, by Skin::getSkinNames(). Use
- * Skin::getSkinNames() as an accessor if you wish to have access to the full list.
+ * cased name for the skin. This value will be prefixed with "Skin" to create
+ * the class name of the skin to load. Use Skin::getSkinNames() as an accessor
+ * if you wish to have access to the full list.
  */
 $wgValidSkinNames = array();
 
@@ -6458,9 +6564,6 @@ $wgLogActions = array(
        'protect/modify' => 'modifiedarticleprotection',
        'protect/unprotect' => 'unprotectedarticle',
        'protect/move_prot' => 'movedarticleprotection',
-       'upload/upload' => 'uploadedimage',
-       'upload/overwrite' => 'overwroteimage',
-       'upload/revert' => 'uploadedimage',
        'import/upload' => 'import-logentry-upload',
        'import/interwiki' => 'import-logentry-interwiki',
        'merge/merge' => 'pagemerge-logentry',
@@ -6487,6 +6590,9 @@ $wgLogActionsHandlers = array(
        'patrol/patrol' => 'PatrolLogFormatter',
        'rights/rights' => 'RightsLogFormatter',
        'rights/autopromote' => 'RightsLogFormatter',
+       'upload/upload' => 'LogFormatter',
+       'upload/overwrite' => 'LogFormatter',
+       'upload/revert' => 'LogFormatter',
 );
 
 /**
@@ -6520,11 +6626,6 @@ $wgDisableQueryPageUpdate = false;
  */
 $wgSpecialPageGroups = array();
 
-/**
- * Whether or not to sort special pages in Special:Specialpages
- */
-$wgSortSpecialPages = true;
-
 /**
  * On Special:Unusedimages, consider images "used", if they are put
  * into a category. Default (false) is not to count those as used.
@@ -6689,16 +6790,45 @@ $wgDebugAPI = false;
 
 /**
  * API module extensions.
- * Associative array mapping module name to class name.
- * Extension modules may override the core modules.
  *
+ * Associative array mapping module name to modules specs;
+ * Each module spec is an associative array containing at least
+ * the 'class' key for the module's class, and optionally a
+ * 'factory' key for the factory function to use for the module.
+ *
+ * That factory function will be called with two parameters,
+ * the parent module (an instance of ApiBase, usually ApiMain)
+ * and the name the module was registered under. The return
+ * value must be an instance of the class given in the 'class'
+ * field.
+ *
+ * For backward compatibility, the module spec may also be a
+ * simple string containing the module's class name. In that
+ * case, the class' constructor will be called with the parent
+ * module and module name as parameters, as described above.
+ *
+ * Examples for registering API modules:
+ *
+ * @code
+ *  $wgAPIModules['foo'] = 'ApiFoo';
+ *  $wgAPIModules['bar'] = array(
+ *    'class' => 'ApiBar',
+ *    'factory' => function( $main, $name ) { ... }
+ *  );
+ *  $wgAPIModules['xyzzy'] = array(
+ *    'class' => 'ApiXyzzy',
+ *    'factory' => array( 'XyzzyFactory', 'newApiModule' )
+ *  );
+ * @endcode
+ *
+ * Extension modules may override the core modules.
  * See ApiMain::$Modules for a list of the core modules.
  */
 $wgAPIModules = array();
 
 /**
  * API format module extensions.
- * Associative array mapping format module name to class name.
+ * Associative array mapping format module name to module specs (see $wgAPIModules).
  * Extension modules may override the core modules.
  *
  * See ApiMain::$Formats for a list of the core format modules.
@@ -6707,7 +6837,7 @@ $wgAPIFormatModules = array();
 
 /**
  * API Query meta module extensions.
- * Associative array mapping meta module name to class name.
+ * Associative array mapping meta module name to module specs (see $wgAPIModules).
  * Extension modules may override the core modules.
  *
  * See ApiQuery::$QueryMetaModules for a list of the core meta modules.
@@ -6716,7 +6846,7 @@ $wgAPIMetaModules = array();
 
 /**
  * API Query prop module extensions.
- * Associative array mapping properties module name to class name.
+ * Associative array mapping prop module name to module specs (see $wgAPIModules).
  * Extension modules may override the core modules.
  *
  * See ApiQuery::$QueryPropModules for a list of the core prop modules.
@@ -6725,7 +6855,7 @@ $wgAPIPropModules = array();
 
 /**
  * API Query list module extensions.
- * Associative array mapping list module name to class name.
+ * Associative array mapping list module name to module specs (see $wgAPIModules).
  * Extension modules may override the core modules.
  *
  * See ApiQuery::$QueryListModules for a list of the core list modules.
@@ -6907,12 +7037,12 @@ $wgShellLocale = 'en_US.utf8';
  */
 
 /**
- * Timeout for HTTP requests done internally
+ * Timeout for HTTP requests done internally, in seconds.
  */
 $wgHTTPTimeout = 25;
 
 /**
- * Timeout for Asynchronous (background) HTTP requests
+ * Timeout for Asynchronous (background) HTTP requests, in seconds.
  */
 $wgAsyncHTTPTimeout = 25;
 
@@ -7108,12 +7238,6 @@ $wgSiteTypes = array(
        'mediawiki' => 'MediaWikiSite',
 );
 
-/**
- * Formerly a list of files for HipHop compilation
- * @deprecated since 1.22
- */
-$wgCompiledFiles = array();
-
 /**
  * Whether the page_props table has a pp_sortkey column. Set to false in case
  * the respective database schema change was not applied.
@@ -7147,6 +7271,14 @@ $wgHKDFAlgorithm = 'sha256';
  */
 $wgPageLanguageUseDB = false;
 
+/**
+ * Enable use of the *_namespace fields of the pagelinks, redirect, and templatelinks tables.
+ * Set this only if the fields are fully populated. This may be removed in 1.25.
+ * @var bool
+ * @since 1.24
+ */
+$wgUseLinkNamespaceDBFields = true;
+
 /**
  * For really cool vim folding this needs to be at the end:
  * vim: foldmarker=@{,@} foldmethod=marker
index e0579cb..017e9ea 100644 (file)
@@ -281,6 +281,7 @@ define( 'CONTENT_MODEL_WIKITEXT', 'wikitext' );
 define( 'CONTENT_MODEL_JAVASCRIPT', 'javascript' );
 define( 'CONTENT_MODEL_CSS', 'css' );
 define( 'CONTENT_MODEL_TEXT', 'text' );
+define( 'CONTENT_MODEL_JSON', 'json' );
 /**@}*/
 
 /**@{
index 3d57e95..b71384f 100644 (file)
@@ -66,11 +66,6 @@ class EditPage {
         */
        const AS_CONTENT_TOO_BIG = 216;
 
-       /**
-        * Status: User cannot edit? (not used)
-        */
-       const AS_USER_CANNOT_EDIT = 217;
-
        /**
         * Status: this anonymous user is not allowed to edit this page
         */
@@ -104,7 +99,7 @@ class EditPage {
        const AS_NO_CREATE_PERMISSION = 223;
 
        /**
-        * Status: user tried to create a blank page
+        * Status: user tried to create a blank page and wpIgnoreBlankArticle == false
         */
        const AS_BLANK_ARTICLE = 224;
 
@@ -129,11 +124,6 @@ class EditPage {
         */
        const AS_MAX_ARTICLE_SIZE_EXCEEDED = 229;
 
-       /**
-        * not used
-        */
-       const AS_OK = 230;
-
        /**
         * Status: WikiPage::doEdit() was unsuccessful
         */
@@ -195,7 +185,7 @@ class EditPage {
        private $mContextTitle = null;
 
        /** @var string */
-       protected $action = 'submit';
+       public $action = 'submit';
 
        /** @var bool */
        public $isConflict = false;
@@ -210,13 +200,13 @@ class EditPage {
        public $isJsSubpage = false;
 
        /** @var bool */
-       protected $isWrongCaseCssJsPage = false;
+       public $isWrongCaseCssJsPage = false;
 
        /** @var bool New page or new section */
-       protected $isNew = false;
+       public $isNew = false;
 
        /** @var bool */
-       protected $deletedSinceEdit;
+       public $deletedSinceEdit;
 
        /** @var string */
        public $formtype;
@@ -225,49 +215,55 @@ class EditPage {
        public $firsttime;
 
        /** @var bool|stdClass */
-       protected $lastDelete;
+       public $lastDelete;
+
+       /** @var bool */
+       public $mTokenOk = false;
 
        /** @var bool */
-       protected $mTokenOk = false;
+       public $mTokenOkExceptSuffix = false;
 
        /** @var bool */
-       protected $mTokenOkExceptSuffix = false;
+       public $mTriedSave = false;
 
        /** @var bool */
-       protected $mTriedSave = false;
+       public $incompleteForm = false;
 
        /** @var bool */
-       protected $incompleteForm = false;
+       public $tooBig = false;
 
        /** @var bool */
-       protected $tooBig = false;
+       public $kblength = false;
 
        /** @var bool */
-       protected $kblength = false;
+       public $missingComment = false;
 
        /** @var bool */
-       protected $missingComment = false;
+       public $missingSummary = false;
 
        /** @var bool */
-       protected $missingSummary = false;
+       public $allowBlankSummary = false;
 
        /** @var bool */
-       protected $allowBlankSummary = false;
+       protected $blankArticle = false;
+
+       /** @var bool */
+       protected $allowBlankArticle = false;
 
        /** @var string */
-       protected $autoSumm = '';
+       public $autoSumm = '';
 
        /** @var string */
        public $hookError = '';
 
        /** @var ParserOutput */
-       protected $mParserOutput;
+       public $mParserOutput;
 
        /** @var bool Has a summary been preset using GET parameter &summary= ? */
-       protected $hasPresetSummary = false;
+       public $hasPresetSummary = false;
 
        /** @var bool */
-       protected $mBaseRevision = false;
+       public $mBaseRevision = false;
 
        /** @var bool */
        public $mShowSummaryField = true;
@@ -281,16 +277,16 @@ class EditPage {
        public $preview = false;
 
        /** @var bool */
-       protected $diff = false;
+       public $diff = false;
 
        /** @var bool */
        public $minoredit = false;
 
        /** @var bool */
-       protected $watchthis = false;
+       public $watchthis = false;
 
        /** @var bool */
-       protected $recreate = false;
+       public $recreate = false;
 
        /** @var string */
        public $textbox1 = '';
@@ -302,7 +298,7 @@ class EditPage {
        public $summary = '';
 
        /** @var bool */
-       protected $nosummary = false;
+       public $nosummary = false;
 
        /** @var string */
        public $edittime = '';
@@ -314,13 +310,13 @@ class EditPage {
        public $sectiontitle = '';
 
        /** @var string */
-       protected $starttime = '';
+       public $starttime = '';
 
        /** @var int */
        public $oldid = 0;
 
        /** @var string */
-       protected $editintro = '';
+       public $editintro = '';
 
        /** @var null */
        public $scrolltop = null;
@@ -421,7 +417,7 @@ class EditPage {
         *
         * @param string $modelId The ID of the content model to test. Use CONTENT_MODEL_XXX constants.
         * @return bool
-        * @throws MWException if $modelId has no known handler
+        * @throws MWException If $modelId has no known handler
         */
        public function isSupportedContentModel( $modelId ) {
                return $this->allowNonTextContent ||
@@ -643,26 +639,6 @@ class EditPage {
                }
        }
 
-       /**
-        * Show a read-only error
-        * Parameters are the same as OutputPage:readOnlyPage()
-        * Redirect to the article page if redlink=1
-        * @deprecated since 1.19; use displayPermissionsError() instead
-        */
-       function readOnlyPage( $source = null, $protected = false, $reasons = array(), $action = null ) {
-               wfDeprecated( __METHOD__, '1.19' );
-
-               global $wgRequest, $wgOut;
-               if ( $wgRequest->getBool( 'redlink' ) ) {
-                       // The edit page was reached via a red link.
-                       // Redirect to the article page and let them click the edit tab if
-                       // they really want a permission error.
-                       $wgOut->redirect( $this->mTitle->getFullURL() );
-               } else {
-                       $wgOut->readOnlyPage( $source, $protected, $reasons, $action );
-               }
-       }
-
        /**
         * Should we show a preview when the edit form is first shown?
         *
@@ -720,7 +696,7 @@ class EditPage {
         * Subclasses may override this to replace the default behavior, which is
         * to check ContentHandler::supportsSections.
         *
-        * @return bool true if this edit page supports sections, false otherwise.
+        * @return bool True if this edit page supports sections, false otherwise.
         */
        protected function isSectionEditSupported() {
                $contentHandler = ContentHandler::getForTitle( $this->mTitle );
@@ -860,6 +836,8 @@ class EditPage {
                        }
 
                        $this->autoSumm = $request->getText( 'wpAutoSummary' );
+
+                       $this->allowBlankArticle = $request->getBool( 'wpIgnoreBlankArticle' );
                } else {
                        # Not a posted form? Start with nothing.
                        wfDebug( __METHOD__ . ": Not a posted form.\n" );
@@ -980,29 +958,6 @@ class EditPage {
                return true;
        }
 
-       /**
-        * Fetch initial editing page content.
-        *
-        * @param string|bool $def_text
-        * @return string|bool string on success, $def_text for invalid sections
-        * @private
-        * @deprecated since 1.21, get WikiPage::getContent() instead.
-        */
-       function getContent( $def_text = false ) {
-               ContentHandler::deprecated( __METHOD__, '1.21' );
-
-               if ( $def_text !== null && $def_text !== false && $def_text !== '' ) {
-                       $def_content = $this->toEditContent( $def_text );
-               } else {
-                       $def_content = false;
-               }
-
-               $content = $this->getContentObject( $def_content );
-
-               // Note: EditPage should only be used with text based content anyway.
-               return $this->toEditText( $content );
-       }
-
        /**
         * @param Content|null $def_content The default value to return
         *
@@ -1190,20 +1145,6 @@ class EditPage {
                }
        }
 
-       /**
-        * Use this method before edit() to preload some text into the edit box
-        *
-        * @param string $text
-        * @deprecated since 1.21, use setPreloadedContent() instead.
-        */
-       public function setPreloadedText( $text ) {
-               ContentHandler::deprecated( __METHOD__, "1.21" );
-
-               $content = $this->toEditContent( $text );
-
-               $this->setPreloadedContent( $content );
-       }
-
        /**
         * Use this method before edit() to preload some content into the edit box
         *
@@ -1215,25 +1156,6 @@ class EditPage {
                $this->mPreloadContent = $content;
        }
 
-       /**
-        * Get the contents to be preloaded into the box, either set by
-        * an earlier setPreloadText() or by loading the given page.
-        *
-        * @param string $preload representing the title to preload from.
-        *
-        * @return string
-        *
-        * @deprecated since 1.21, use getPreloadedContent() instead
-        */
-       protected function getPreloadedText( $preload ) {
-               ContentHandler::deprecated( __METHOD__, "1.21" );
-
-               $content = $this->getPreloadedContent( $preload );
-               $text = $this->toEditText( $content );
-
-               return $text;
-       }
-
        /**
         * Get the contents to be preloaded into the box, either set by
         * an earlier setPreloadText() or by loading the given page.
@@ -1331,7 +1253,7 @@ class EditPage {
         * If the variable were set on the server, it would be cached, which is unwanted
         * since the post-edit state should only apply to the load right after the save.
         *
-        * @param $statusValue int The status value (to check for new article status)
+        * @param int $statusValue The status value (to check for new article status)
         */
        protected function setPostEditCookie( $statusValue ) {
                $revisionId = $this->mArticle->getLatest();
@@ -1353,7 +1275,7 @@ class EditPage {
        /**
         * Attempt submission
         * @throws UserBlockedError|ReadOnlyError|ThrottledError|PermissionsError
-        * @return bool false if output is done, true if the rest of the form should be displayed
+        * @return bool False if output is done, true if the rest of the form should be displayed
         */
        public function attemptSave() {
                global $wgUser;
@@ -1373,7 +1295,7 @@ class EditPage {
         * @param array|bool $resultDetails
         *
         * @throws ErrorPageError
-        * @return bool false, if output is done, true if rest of the form should be displayed
+        * @return bool False, if output is done, true if rest of the form should be displayed
         */
        private function handleStatus( Status $status, $resultDetails ) {
                global $wgUser, $wgOut;
@@ -1400,6 +1322,7 @@ class EditPage {
                        case self::AS_TEXTBOX_EMPTY:
                        case self::AS_MAX_ARTICLE_SIZE_EXCEEDED:
                        case self::AS_END:
+                       case self::AS_BLANK_ARTICLE:
                                return true;
 
                        case self::AS_HOOK_ERROR:
@@ -1435,10 +1358,6 @@ class EditPage {
                                $wgOut->redirect( $this->mTitle->getFullURL( $extraQuery ) . $sectionanchor );
                                return false;
 
-                       case self::AS_BLANK_ARTICLE:
-                               $wgOut->redirect( $this->getContextTitle()->getFullURL() );
-                               return false;
-
                        case self::AS_SPAM_ERROR:
                                $this->spamPageWithContent( $resultDetails['spam'] );
                                return false;
@@ -1523,6 +1442,36 @@ class EditPage {
                return true;
        }
 
+       /**
+        * Return the summary to be used for a new section.
+        *
+        * @param string $sectionanchor Set to the section anchor text
+        * @return string
+        */
+       private function newSectionSummary( &$sectionanchor = null ) {
+               global $wgParser;
+
+               if ( $this->sectiontitle !== '' ) {
+                       $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle );
+                       // If no edit summary was specified, create one automatically from the section
+                       // title and have it link to the new section. Otherwise, respect the summary as
+                       // passed.
+                       if ( $this->summary === '' ) {
+                               $cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
+                               return wfMessage( 'newsectionsummary' )
+                                       ->rawParams( $cleanSectionTitle )->inContentLanguage()->text();
+                       }
+               } elseif ( $this->summary !== '' ) {
+                       $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
+                       # This is a new section, so create a link to the new section
+                       # in the revision summary.
+                       $cleanSummary = $wgParser->stripSectionName( $this->summary );
+                       return wfMessage( 'newsectionsummary' )
+                               ->rawParams( $cleanSummary )->inContentLanguage()->text();
+               }
+               return $this->summary;
+       }
+
        /**
         * Attempt submission (no UI)
         *
@@ -1746,7 +1695,9 @@ class EditPage {
                                $defaultText = '';
                        }
 
-                       if ( $this->textbox1 === $defaultText ) {
+                       if ( !$this->allowBlankArticle && $this->textbox1 === $defaultText ) {
+                               $this->blankArticle = true;
+                               $status->fatal( 'blankarticle' );
                                $status->setResult( false, self::AS_BLANK_ARTICLE );
                                wfProfileOut( __METHOD__ );
                                return $status;
@@ -1764,31 +1715,11 @@ class EditPage {
                                if ( $this->sectiontitle !== '' ) {
                                        // Insert the section title above the content.
                                        $content = $content->addSectionHeader( $this->sectiontitle );
-
-                                       // Jump to the new section
-                                       $result['sectionanchor'] =
-                                               $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle );
-
-                                       // If no edit summary was specified, create one automatically from the section
-                                       // title and have it link to the new section. Otherwise, respect the summary as
-                                       // passed.
-                                       if ( $this->summary === '' ) {
-                                               $cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
-                                               $this->summary = wfMessage( 'newsectionsummary' )
-                                                       ->rawParams( $cleanSectionTitle )->inContentLanguage()->text();
-                                       }
                                } elseif ( $this->summary !== '' ) {
                                        // Insert the section title above the content.
                                        $content = $content->addSectionHeader( $this->summary );
-
-                                       // Jump to the new section
-                                       $result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
-
-                                       // Create a link to the new section from the edit summary.
-                                       $cleanSummary = $wgParser->stripSectionName( $this->summary );
-                                       $this->summary = wfMessage( 'newsectionsummary' )
-                                               ->rawParams( $cleanSummary )->inContentLanguage()->text();
                                }
+                               $this->summary = $this->newSectionSummary( $result['sectionanchor'] );
                        }
 
                        $status->value = self::AS_SUCCESS_NEW_ARTICLE;
@@ -1806,7 +1737,8 @@ class EditPage {
                                $this->isConflict = true;
                                if ( $this->section == 'new' ) {
                                        if ( $this->mArticle->getUserText() == $wgUser->getName() &&
-                                               $this->mArticle->getComment() == $this->summary ) {
+                                               $this->mArticle->getComment() == $this->newSectionSummary()
+                                       ) {
                                                // Probably a duplicate submission of a new comment.
                                                // This can happen when squid resends a request after
                                                // a timeout but the first one actually went through.
@@ -1920,24 +1852,7 @@ class EditPage {
                        wfProfileIn( __METHOD__ . '-sectionanchor' );
                        $sectionanchor = '';
                        if ( $this->section == 'new' ) {
-                               if ( $this->sectiontitle !== '' ) {
-                                       $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle );
-                                       // If no edit summary was specified, create one automatically from the section
-                                       // title and have it link to the new section. Otherwise, respect the summary as
-                                       // passed.
-                                       if ( $this->summary === '' ) {
-                                               $cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
-                                               $this->summary = wfMessage( 'newsectionsummary' )
-                                                       ->rawParams( $cleanSectionTitle )->inContentLanguage()->text();
-                                       }
-                               } elseif ( $this->summary !== '' ) {
-                                       $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
-                                       # This is a new section, so create a link to the new section
-                                       # in the revision summary.
-                                       $cleanSummary = $wgParser->stripSectionName( $this->summary );
-                                       $this->summary = wfMessage( 'newsectionsummary' )
-                                               ->rawParams( $cleanSummary )->inContentLanguage()->text();
-                               }
+                               $this->summary = $this->newSectionSummary( $sectionanchor );
                        } elseif ( $this->section != '' ) {
                                # Try to get a section anchor from the section source, redirect
                                # to edited section if header found.
@@ -2022,7 +1937,7 @@ class EditPage {
 
                        // Do this in its own transaction to reduce contention...
                        $dbw = wfGetDB( DB_MASTER );
-                       $dbw->onTransactionIdle( function() use ( $dbw, $title, $watch, $wgUser, $fname ) {
+                       $dbw->onTransactionIdle( function () use ( $dbw, $title, $watch, $wgUser, $fname ) {
                                $dbw->begin( $fname );
                                WatchAction::doWatchOrUnwatch( $watch, $title, $wgUser );
                                $dbw->commit( $fname );
@@ -2030,28 +1945,6 @@ class EditPage {
                }
        }
 
-       /**
-        * Attempts to merge text content with base and current revisions
-        *
-        * @param string $editText
-        *
-        * @return bool
-        * @deprecated since 1.21, use mergeChangesIntoContent() instead
-        */
-       function mergeChangesInto( &$editText ) {
-               ContentHandler::deprecated( __METHOD__, "1.21" );
-
-               $editContent = $this->toEditContent( $editText );
-
-               $ok = $this->mergeChangesIntoContent( $editContent );
-
-               if ( $ok ) {
-                       $editText = $this->toEditText( $editContent );
-                       return true;
-               }
-               return false;
-       }
-
        /**
         * Attempts to do 3-way merge of edit content with a base revision
         * and current content, in case of edit conflict, in whichever way appropriate
@@ -2329,7 +2222,7 @@ class EditPage {
         * @param Content|null|bool|string $content
         * @return string The editable text form of the content.
         *
-        * @throws MWException if $content is not an instance of TextContent and
+        * @throws MWException If $content is not an instance of TextContent and
         *   $this->allowNonTextContent is not true.
         */
        protected function toEditText( $content ) {
@@ -2361,7 +2254,7 @@ class EditPage {
         * @return Content The content object created from $text. If $text was false
         *   or null, false resp. null will be  returned instead.
         *
-        * @throws MWException if unserializing the text results in a Content
+        * @throws MWException If unserializing the text results in a Content
         *   object that is not an instance of TextContent and
         *   $this->allowNonTextContent is not true.
         */
@@ -2536,6 +2429,10 @@ class EditPage {
                        $wgOut->addHTML( EditPage::getEditToolbar() );
                }
 
+               if ( $this->blankArticle ) {
+                       $wgOut->addHTML( Html::hidden( 'wpIgnoreBlankArticle', true ) );
+               }
+
                if ( $this->isConflict ) {
                        // In an edit conflict bypass the overridable content form method
                        // and fallback to the raw wpTextbox1 since editconflicts can't be
@@ -2605,7 +2502,7 @@ class EditPage {
         * Extract the section title from current section text, if any.
         *
         * @param string $text
-        * @return string|bool string or false
+        * @return string|bool String or false
         */
        public static function extractSectionTitle( $text ) {
                preg_match( "/^(=+)(.+)\\1\\s*(\n|$)/i", $text, $matches );
@@ -2664,6 +2561,10 @@ class EditPage {
                                $wgOut->wrapWikiMsg( "<div id='mw-missingcommentheader'>\n$1\n</div>", 'missingcommentheader' );
                        }
 
+                       if ( $this->blankArticle ) {
+                               $wgOut->wrapWikiMsg( "<div id='mw-blankarticle'>\n$1\n</div>", 'blankarticle' );
+                       }
+
                        if ( $this->hookError !== '' ) {
                                $wgOut->addWikiText( $this->hookError );
                        }
@@ -2709,9 +2610,18 @@ class EditPage {
                        );
                } elseif ( $wgUser->isAnon() ) {
                        if ( $this->formtype != 'preview' ) {
-                               $wgOut->wrapWikiMsg( "<div id=\"mw-anon-edit-warning\">\n$1</div>", 'anoneditwarning' );
+                               $wgOut->wrapWikiMsg(
+                                       "<div id='mw-anon-edit-warning'>\n$1\n</div>",
+                                       array( 'anoneditwarning',
+                                               // Log-in link
+                                               '{{fullurl:Special:UserLogin|returnto={{FULLPAGENAMEE}}}}',
+                                               // Sign-up link
+                                               '{{fullurl:Special:UserLogin/signup|returnto={{FULLPAGENAMEE}}}}' )
+                               );
                        } else {
-                               $wgOut->wrapWikiMsg( "<div id=\"mw-anon-preview-warning\">\n$1</div>", 'anonpreviewwarning' );
+                               $wgOut->wrapWikiMsg( "<div id=\"mw-anon-preview-warning\">\n$1</div>",
+                                       'anonpreviewwarning'
+                               );
                        }
                } else {
                        if ( $this->isCssJsSubpage ) {
@@ -2851,11 +2761,10 @@ class EditPage {
        }
 
        /**
-        * @param bool $isSubjectPreview true if this is the section subject/title
+        * @param bool $isSubjectPreview True if this is the section subject/title
         *   up top, or false if this is the comment summary
         *   down below the textarea
         * @param string $summary The text of the summary to display
-        * @return string
         */
        protected function showSummaryInput( $isSubjectPreview, $summary = "" ) {
                global $wgOut, $wgContLang;
@@ -2882,7 +2791,7 @@ class EditPage {
        }
 
        /**
-        * @param bool $isSubjectPreview true if this is the section subject/title
+        * @param bool $isSubjectPreview True if this is the section subject/title
         *   up top, or false if this is the comment summary
         *   down below the textarea
         * @param string $summary The text of the summary to display
@@ -3197,6 +3106,7 @@ HTML
         * Get the copyright warning
         *
         * Renamed to getCopyrightWarning(), old name kept around for backwards compatibility
+        * @return string
         */
        protected function getCopywarn() {
                return self::getCopyrightWarning( $this->mTitle );
@@ -3280,7 +3190,7 @@ HTML
        }
 
        protected function showStandardInputs( &$tabindex = 2 ) {
-               global $wgOut;
+               global $wgOut, $wgUseMediaWikiUIEverywhere;
                $wgOut->addHTML( "<div class='editOptions'>\n" );
 
                if ( $this->section != 'new' ) {
@@ -3308,8 +3218,15 @@ HTML
 
                $message = wfMessage( 'edithelppage' )->inContentLanguage()->text();
                $edithelpurl = Skin::makeInternalOrExternalUrl( $message );
-               $edithelp = '<a target="helpwindow" href="' . $edithelpurl . '">' .
-                       wfMessage( 'edithelp' )->escaped() . '</a> ' .
+               $attrs = array(
+                       'target' => 'helpwindow',
+                       'href' => $edithelpurl,
+               );
+               if ( $wgUseMediaWikiUIEverywhere ) {
+                       $attrs['class'] = 'mw-ui-button mw-ui-quiet';
+               }
+               $edithelp = Html::element( 'a', $attrs, wfMessage( 'edithelp' )->text() ) .
+                       wfMessage( 'word-separator' )->escaped() .
                        wfMessage( 'newwindow' )->parse();
 
                $wgOut->addHTML( "      <span class='cancelLink'>{$cancel}</span>\n" );
@@ -3351,15 +3268,20 @@ HTML
         * @return string
         */
        public function getCancelLink() {
+               global $wgUseMediaWikiUIEverywhere;
                $cancelParams = array();
                if ( !$this->isConflict && $this->oldid > 0 ) {
                        $cancelParams['oldid'] = $this->oldid;
                }
+               $attrs = array( 'id' => 'mw-editform-cancel' );
+               if ( $wgUseMediaWikiUIEverywhere ) {
+                       $attrs['class'] = 'mw-ui-button mw-ui-quiet';
+               }
 
                return Linker::linkKnown(
                        $this->getContextTitle(),
                        wfMessage( 'cancel' )->parse(),
-                       array( 'id' => 'mw-editform-cancel' ),
+                       $attrs,
                        $cancelParams
                );
        }
@@ -3623,119 +3545,94 @@ HTML
        /**
         * Shows a bulletin board style toolbar for common editing functions.
         * It can be disabled in the user preferences.
-        * The necessary JavaScript code can be found in skins/common/edit.js.
         *
         * @return string
         */
        static function getEditToolbar() {
-               global $wgStylePath, $wgContLang, $wgLang, $wgOut;
+               global $wgContLang, $wgOut;
                global $wgEnableUploads, $wgForeignFileRepos;
 
                $imagesAvailable = $wgEnableUploads || count( $wgForeignFileRepos );
 
                /**
                 * $toolarray is an array of arrays each of which includes the
-                * filename of the button image (without path), the opening
-                * tag, the closing tag, optionally a sample text that is
+                * opening tag, the closing tag, optionally a sample text that is
                 * inserted between the two when no selection is highlighted
                 * and.  The tip text is shown when the user moves the mouse
                 * over the button.
                 *
-                * Also here: accesskeys (key), which are not used yet until
-                * someone can figure out a way to make them work in
-                * IE. However, we should make sure these keys are not defined
-                * on the edit page.
+                * Images are defined in ResourceLoaderEditToolbarModule.
                 */
                $toolarray = array(
                        array(
-                               'image'  => $wgLang->getImageFile( 'button-bold' ),
                                'id'     => 'mw-editbutton-bold',
                                'open'   => '\'\'\'',
                                'close'  => '\'\'\'',
                                'sample' => wfMessage( 'bold_sample' )->text(),
                                'tip'    => wfMessage( 'bold_tip' )->text(),
-                               'key'    => 'B'
                        ),
                        array(
-                               'image'  => $wgLang->getImageFile( 'button-italic' ),
                                'id'     => 'mw-editbutton-italic',
                                'open'   => '\'\'',
                                'close'  => '\'\'',
                                'sample' => wfMessage( 'italic_sample' )->text(),
                                'tip'    => wfMessage( 'italic_tip' )->text(),
-                               'key'    => 'I'
                        ),
                        array(
-                               'image'  => $wgLang->getImageFile( 'button-link' ),
                                'id'     => 'mw-editbutton-link',
                                'open'   => '[[',
                                'close'  => ']]',
                                'sample' => wfMessage( 'link_sample' )->text(),
                                'tip'    => wfMessage( 'link_tip' )->text(),
-                               'key'    => 'L'
                        ),
                        array(
-                               'image'  => $wgLang->getImageFile( 'button-extlink' ),
                                'id'     => 'mw-editbutton-extlink',
                                'open'   => '[',
                                'close'  => ']',
                                'sample' => wfMessage( 'extlink_sample' )->text(),
                                'tip'    => wfMessage( 'extlink_tip' )->text(),
-                               'key'    => 'X'
                        ),
                        array(
-                               'image'  => $wgLang->getImageFile( 'button-headline' ),
                                'id'     => 'mw-editbutton-headline',
                                'open'   => "\n== ",
                                'close'  => " ==\n",
                                'sample' => wfMessage( 'headline_sample' )->text(),
                                'tip'    => wfMessage( 'headline_tip' )->text(),
-                               'key'    => 'H'
                        ),
                        $imagesAvailable ? array(
-                               'image'  => $wgLang->getImageFile( 'button-image' ),
                                'id'     => 'mw-editbutton-image',
                                'open'   => '[[' . $wgContLang->getNsText( NS_FILE ) . ':',
                                'close'  => ']]',
                                'sample' => wfMessage( 'image_sample' )->text(),
                                'tip'    => wfMessage( 'image_tip' )->text(),
-                               'key'    => 'D',
                        ) : false,
                        $imagesAvailable ? array(
-                               'image'  => $wgLang->getImageFile( 'button-media' ),
                                'id'     => 'mw-editbutton-media',
                                'open'   => '[[' . $wgContLang->getNsText( NS_MEDIA ) . ':',
                                'close'  => ']]',
                                'sample' => wfMessage( 'media_sample' )->text(),
                                'tip'    => wfMessage( 'media_tip' )->text(),
-                               'key'    => 'M'
                        ) : false,
                        array(
-                               'image'  => $wgLang->getImageFile( 'button-nowiki' ),
                                'id'     => 'mw-editbutton-nowiki',
                                'open'   => "<nowiki>",
                                'close'  => "</nowiki>",
                                'sample' => wfMessage( 'nowiki_sample' )->text(),
                                'tip'    => wfMessage( 'nowiki_tip' )->text(),
-                               'key'    => 'N'
                        ),
                        array(
-                               'image'  => $wgLang->getImageFile( 'button-sig' ),
                                'id'     => 'mw-editbutton-signature',
                                'open'   => '--~~~~',
                                'close'  => '',
                                'sample' => '',
                                'tip'    => wfMessage( 'sig_tip' )->text(),
-                               'key'    => 'Y'
                        ),
                        array(
-                               'image'  => $wgLang->getImageFile( 'button-hr' ),
                                'id'     => 'mw-editbutton-hr',
                                'open'   => "\n----\n",
                                'close'  => '',
                                'sample' => '',
                                'tip'    => wfMessage( 'hr_tip' )->text(),
-                               'key'    => 'R'
                        )
                );
 
@@ -3746,7 +3643,8 @@ HTML
                        }
 
                        $params = array(
-                               $wgStylePath . '/common/images/' . $tool['image'],
+                               // Images are defined in ResourceLoaderEditToolbarModule
+                               false,
                                // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
                                // Older browsers show a "speedtip" type message only for ALT.
                                // Ideally these should be different, realistically they
@@ -3788,7 +3686,7 @@ HTML
         * @return array
         */
        public function getCheckboxes( &$tabindex, $checked ) {
-               global $wgUser;
+               global $wgUser, $wgUseMediaWikiUIEverywhere;
 
                $checkboxes = array();
 
@@ -3802,11 +3700,19 @@ HTML
                                        'accesskey' => wfMessage( 'accesskey-minoredit' )->text(),
                                        'id' => 'wpMinoredit',
                                );
-                               $checkboxes['minor'] =
+                               $minorEditHtml =
                                        Xml::check( 'wpMinoredit', $checked['minor'], $attribs ) .
                                        "&#160;<label for='wpMinoredit' id='mw-editpage-minoredit'" .
                                        Xml::expandAttributes( array( 'title' => Linker::titleAttrib( 'minoredit', 'withaccess' ) ) ) .
                                        ">{$minorLabel}</label>";
+
+                               if ( $wgUseMediaWikiUIEverywhere ) {
+                                       $checkboxes['minor'] = Html::openElement( 'div', array( 'class' => 'mw-ui-checkbox' ) ) .
+                                               $minorEditHtml .
+                                       Html::closeElement( 'div' );
+                               } else {
+                                       $checkboxes['minor'] = $minorEditHtml;
+                               }
                        }
                }
 
@@ -3818,11 +3724,18 @@ HTML
                                'accesskey' => wfMessage( 'accesskey-watch' )->text(),
                                'id' => 'wpWatchthis',
                        );
-                       $checkboxes['watch'] =
+                       $watchThisHtml =
                                Xml::check( 'wpWatchthis', $checked['watch'], $attribs ) .
                                "&#160;<label for='wpWatchthis' id='mw-editpage-watch'" .
                                Xml::expandAttributes( array( 'title' => Linker::titleAttrib( 'watch', 'withaccess' ) ) ) .
                                ">{$watchLabel}</label>";
+                       if ( $wgUseMediaWikiUIEverywhere ) {
+                               $checkboxes['watch'] = Html::openElement( 'div', array( 'class' => 'mw-ui-checkbox' ) ) .
+                                       $watchThisHtml .
+                                       Html::closeElement( 'div' );
+                       } else {
+                               $checkboxes['watch'] = $watchThisHtml;
+                       }
                }
                wfRunHooks( 'EditPageBeforeEditChecks', array( &$this, &$checkboxes, &$tabindex ) );
                return $checkboxes;
@@ -3837,6 +3750,8 @@ HTML
         * @return array
         */
        public function getEditButtons( &$tabindex ) {
+               global $wgUseMediaWikiUIEverywhere;
+
                $buttons = array();
 
                $attribs = array(
@@ -3846,6 +3761,9 @@ HTML
                        'tabindex' => ++$tabindex,
                        'value' => wfMessage( 'savearticle' )->text(),
                ) + Linker::tooltipAndAccesskeyAttribs( 'save' );
+               if ( $wgUseMediaWikiUIEverywhere ) {
+                       $attribs['class'] = 'mw-ui-button mw-ui-constructive';
+               }
                $buttons['save'] = Xml::element( 'input', $attribs, '' );
 
                ++$tabindex; // use the same for preview and live preview
@@ -3856,6 +3774,9 @@ HTML
                        'tabindex' => $tabindex,
                        'value' => wfMessage( 'showpreview' )->text(),
                ) + Linker::tooltipAndAccesskeyAttribs( 'preview' );
+               if ( $wgUseMediaWikiUIEverywhere ) {
+                       $attribs['class'] = 'mw-ui-button mw-ui-progressive';
+               }
                $buttons['preview'] = Xml::element( 'input', $attribs, '' );
                $buttons['live'] = '';
 
@@ -3866,6 +3787,9 @@ HTML
                        'tabindex' => ++$tabindex,
                        'value' => wfMessage( 'showdiff' )->text(),
                ) + Linker::tooltipAndAccesskeyAttribs( 'diff' );
+               if ( $wgUseMediaWikiUIEverywhere ) {
+                       $attribs['class'] = 'mw-ui-button mw-ui-progressive';
+               }
                $buttons['diff'] = Xml::element( 'input', $attribs, '' );
 
                wfRunHooks( 'EditPageBeforeEditButtons', array( &$this, &$buttons, &$tabindex ) );
@@ -3902,40 +3826,6 @@ HTML
                echo $s;
        }
 
-       /**
-        * Call the stock "user is blocked" page
-        *
-        * @deprecated since 1.19; throw an exception directly instead
-        */
-       function blockedPage() {
-               wfDeprecated( __METHOD__, '1.19' );
-               global $wgUser;
-
-               throw new UserBlockedError( $wgUser->getBlock() );
-       }
-
-       /**
-        * Produce the stock "please login to edit pages" page
-        *
-        * @deprecated since 1.19; throw an exception directly instead
-        */
-       function userNotLoggedInPage() {
-               wfDeprecated( __METHOD__, '1.19' );
-               throw new PermissionsError( 'edit' );
-       }
-
-       /**
-        * Show an error page saying to the user that he has insufficient permissions
-        * to create a new page
-        *
-        * @deprecated since 1.19; throw an exception directly instead
-        */
-       function noCreatePermission() {
-               wfDeprecated( __METHOD__, '1.19' );
-               $permission = $this->mTitle->isTalkPage() ? 'createtalk' : 'createpage';
-               throw new PermissionsError( $permission );
-       }
-
        /**
         * Creates a basic error page which informs the user that
         * they have attempted to edit a nonexistent section.
index 21fcd5a..48a814d 100644 (file)
@@ -41,7 +41,7 @@ class WikiExporter {
        public $dumpUploadFileContents = false;
 
        /** @var string */
-       protected $author_list = "";
+       public $author_list = "";
 
        const FULL = 1;
        const CURRENT = 2;
@@ -56,20 +56,20 @@ class WikiExporter {
        const STUB = 1;
 
        /** @var int */
-       protected $buffer;
+       public $buffer;
 
        /** @var int */
-       protected $text;
+       public $text;
 
        /** @var DumpOutput */
-       protected $sink;
+       public $sink;
 
        /**
         * Returns the export schema version.
         * @return string
         */
        public static function schemaVersion() {
-               return "0.8";
+               return "0.9";
        }
 
        /**
@@ -507,8 +507,17 @@ class XmlDumpWriter {
                return Xml::element( 'mediawiki', array(
                        'xmlns'              => "http://www.mediawiki.org/xml/export-$ver/",
                        'xmlns:xsi'          => "http://www.w3.org/2001/XMLSchema-instance",
+                       /*
+                        * When a new version of the schema is created, it needs staging on mediawiki.org.
+                        * This requires a change in the operations/mediawiki-config git repo.
+                        *
+                        * Create a changeset like https://gerrit.wikimedia.org/r/#/c/149643/ in which
+                        * you copy in the new xsd file.
+                        *
+                        * After it is reviewed, merged and deployed (sync-docroot), the index.html needs purging.
+                        * echo "http://www.mediawiki.org/xml/index.html" | mwscript purgeList.php --wiki=aawiki
+                        */
                        'xsi:schemaLocation' => "http://www.mediawiki.org/xml/export-$ver/ " .
-                               #TODO: how do we get a new version up there?
                                "http://www.mediawiki.org/xml/export-$ver.xsd",
                        'version'            => $ver,
                        'xml:lang'           => $wgLanguageCode ),
@@ -523,6 +532,7 @@ class XmlDumpWriter {
        function siteInfo() {
                $info = array(
                        $this->sitename(),
+                       $this->dbname(),
                        $this->homelink(),
                        $this->generator(),
                        $this->caseSetting(),
@@ -540,6 +550,14 @@ class XmlDumpWriter {
                return Xml::element( 'sitename', array(), $wgSitename );
        }
 
+       /**
+        * @return string
+        */
+       function dbname() {
+               global $wgDBname;
+               return Xml::element( 'dbname', array(), $wgDBname );
+       }
+
        /**
         * @return string
         */
@@ -1352,10 +1370,10 @@ class DumpNotalkFilter extends DumpFilter {
  */
 class DumpNamespaceFilter extends DumpFilter {
        /** @var bool */
-       protected $invert = false;
+       public $invert = false;
 
        /** @var array */
-       protected $namespaces = array();
+       public $namespaces = array();
 
        /**
         * @param DumpOutput $sink
@@ -1419,13 +1437,13 @@ class DumpNamespaceFilter extends DumpFilter {
  * @ingroup Dump
  */
 class DumpLatestFilter extends DumpFilter {
-       protected $page;
+       public $page;
 
-       protected $pageString;
+       public $pageString;
 
-       protected $rev;
+       public $rev;
 
-       protected $revString;
+       public $revString;
 
        /**
         * @param object $page
@@ -1552,23 +1570,3 @@ class DumpMultiWriter {
                return $filenames;
        }
 }
-
-/**
- * @param string $string
- * @return string
- * @todo FIXME: Only used in OAI extension. Move over there.
- */
-function xmlsafe( $string ) {
-       wfProfileIn( __FUNCTION__ );
-
-       /**
-        * The page may contain old data which has not been properly normalized.
-        * Invalid UTF-8 sequences or forbidden control characters will make our
-        * XML output invalid, so be sure to strip them out.
-        */
-       $string = UtfNormal::cleanUp( $string );
-
-       $string = htmlspecialchars( $string );
-       wfProfileOut( __FUNCTION__ );
-       return $string;
-}
index e38bdf1..8e7f4b7 100644 (file)
  */
 class Fallback {
 
-       /**
-        * @param string $from
-        * @param string $to
-        * @param string $string
-        * @return string
-        */
-       public static function iconv( $from, $to, $string ) {
-               if ( substr( $to, -8 ) == '//IGNORE' ) {
-                       $to = substr( $to, 0, strlen( $to ) - 8 );
-               }
-               if ( strcasecmp( $from, $to ) == 0 ) {
-                       return $string;
-               }
-               if ( strcasecmp( $from, 'utf-8' ) == 0 ) {
-                       return utf8_decode( $string );
-               }
-               if ( strcasecmp( $to, 'utf-8' ) == 0 ) {
-                       return utf8_encode( $string );
-               }
-               return $string;
-       }
-
        /**
         * Fallback implementation for mb_substr, hardcoded to UTF-8.
         * Attempts to be at least _moderately_ efficient; best optimized
@@ -174,8 +152,8 @@ class Fallback {
         * 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
+        * @param string $offset Optional start position
+        * @param string $encoding Optional encoding; ignored
         * @return int
         */
        public static function mb_strrpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
index 1674b13..2fdfa42 100644 (file)
  */
 class FeedItem {
        /** @var Title */
-       protected $title;
+       public $title;
 
-       protected $description;
+       public $description;
 
-       protected $url;
+       public $url;
 
-       protected $date;
+       public $date;
 
-       protected $author;
+       public $author;
 
-       protected $uniqueId;
+       public $uniqueId;
 
-       protected $comments;
+       public $comments;
 
        public $rssIsPermalink = false;
 
@@ -174,7 +174,7 @@ class FeedItem {
        /**
         * Quickie hack... strip out wikilinks to more legible form from the comment.
         *
-        * @param string $text wikitext
+        * @param string $text Wikitext
         * @return string
         */
        public static function stripComment( $text ) {
@@ -258,20 +258,11 @@ abstract class ChannelFeed extends FeedItem {
        }
 
        /**
-        * Output the initial XML headers with a stylesheet for legibility
-        * if someone finds it in a browser.
+        * Output the initial XML headers.
         */
        protected function outXmlHeader() {
-               global $wgStylePath, $wgStyleVersion;
-
                $this->httpHeaders();
                echo '<?xml version="1.0"?>' . "\n";
-               echo '<?xml-stylesheet type="text/css" href="' .
-                       htmlspecialchars( wfExpandUrl(
-                               "$wgStylePath/common/feed.css?$wgStyleVersion",
-                               PROTO_CURRENT
-                       ) ) .
-                       '"?' . ">\n";
        }
 }
 
@@ -348,6 +339,7 @@ class RSSFeed extends ChannelFeed {
 class AtomFeed extends ChannelFeed {
        /**
         * @todo document
+        * @param string|int $ts
         * @return string
         */
        function formatTime( $ts ) {
index 83ce755..6937c32 100644 (file)
@@ -48,7 +48,7 @@ class FeedUtils {
        /**
         * Check whether feeds can be used and that $type is a valid feed type
         *
-        * @param string $type feed type, as requested by the user
+        * @param string $type Feed type, as requested by the user
         * @return bool
         */
        public static function checkFeedOutput( $type ) {
index 0582230..c1765e2 100644 (file)
@@ -160,6 +160,7 @@ class ForkController {
        /**
         * Fork a number of worker processes.
         *
+        * @param int $numProcs
         * @return string
         */
        protected function forkWorkers( $numProcs ) {
index 079267a..c91c336 100644 (file)
@@ -375,6 +375,7 @@ class FormOptions implements ArrayAccess {
        /* @{ */
        /**
         * Whether the option exists.
+        * @param string $name
         * @return bool
         */
        public function offsetExists( $name ) {
@@ -383,6 +384,7 @@ class FormOptions implements ArrayAccess {
 
        /**
         * Retrieve an option value.
+        * @param string $name
         * @return mixed
         */
        public function offsetGet( $name ) {
@@ -391,6 +393,8 @@ class FormOptions implements ArrayAccess {
 
        /**
         * Set an option to given value.
+        * @param string $name
+        * @param mixed $value
         */
        public function offsetSet( $name, $value ) {
                $this->setValue( $name, $value );
@@ -398,6 +402,7 @@ class FormOptions implements ArrayAccess {
 
        /**
         * Delete the option.
+        * @param string $name
         */
        public function offsetUnset( $name ) {
                $this->delete( $name );
index acf1bf6..7052820 100644 (file)
@@ -274,7 +274,7 @@ class GitInfo {
 
        /**
         * Get the URL of the remote origin.
-        * @return string|bool string if a URL is available or false otherwise.
+        * @return string|bool String if a URL is available or false otherwise.
         */
        protected function getRemoteUrl() {
                if ( !isset( $this->cache['remoteURL'] ) ) {
index c1908af..20398a5 100644 (file)
@@ -35,19 +35,10 @@ if ( !defined( 'MEDIAWIKI' ) ) {
  * PHP extensions may be included here.
  */
 
-if ( !function_exists( 'iconv' ) ) {
-       /**
-        * @codeCoverageIgnore
-        * @return string
-        */
-       function iconv( $from, $to, $string ) {
-               return Fallback::iconv( $from, $to, $string );
-       }
-}
-
 if ( !function_exists( 'mb_substr' ) ) {
        /**
         * @codeCoverageIgnore
+        * @see Fallback::mb_substr
         * @return string
         */
        function mb_substr( $str, $start, $count = 'end' ) {
@@ -56,6 +47,7 @@ if ( !function_exists( 'mb_substr' ) ) {
 
        /**
         * @codeCoverageIgnore
+        * @see Fallback::mb_substr_split_unicode
         * @return int
         */
        function mb_substr_split_unicode( $str, $splitPos ) {
@@ -66,6 +58,7 @@ if ( !function_exists( 'mb_substr' ) ) {
 if ( !function_exists( 'mb_strlen' ) ) {
        /**
         * @codeCoverageIgnore
+        * @see Fallback::mb_strlen
         * @return int
         */
        function mb_strlen( $str, $enc = '' ) {
@@ -76,6 +69,7 @@ if ( !function_exists( 'mb_strlen' ) ) {
 if ( !function_exists( 'mb_strpos' ) ) {
        /**
         * @codeCoverageIgnore
+        * @see Fallback::mb_strpos
         * @return int
         */
        function mb_strpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
@@ -86,6 +80,7 @@ if ( !function_exists( 'mb_strpos' ) ) {
 if ( !function_exists( 'mb_strrpos' ) ) {
        /**
         * @codeCoverageIgnore
+        * @see Fallback::mb_strrpos
         * @return int
         */
        function mb_strrpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
@@ -98,6 +93,7 @@ if ( !function_exists( 'mb_strrpos' ) ) {
 if ( !function_exists( 'gzdecode' ) ) {
        /**
         * @codeCoverageIgnore
+        * @param string $data
         * @return string
         */
        function gzdecode( $data ) {
@@ -186,21 +182,6 @@ function wfArrayDiff2_cmp( $a, $b ) {
        }
 }
 
-/**
- * Array lookup
- * Returns an array where the values in array $b are replaced by the
- * values in array $a with the corresponding keys
- *
- * @deprecated since 1.22; use array_intersect_key()
- * @param array $a
- * @param array $b
- * @return array
- */
-function wfArrayLookup( $a, $b ) {
-       wfDeprecated( __FUNCTION__, '1.22' );
-       return array_flip( array_intersect( array_flip( $a ), array_keys( $b ) ) );
-}
-
 /**
  * Appends to second array if $value differs from that in $default
  *
@@ -219,27 +200,6 @@ function wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed ) {
        }
 }
 
-/**
- * Backwards array plus for people who haven't bothered to read the PHP manual
- * XXX: will not darn your socks for you.
- *
- * @deprecated since 1.22; use array_replace()
- *
- * @param array $array1 Initial array to merge.
- * @param array [$array2,...] Variable list of arrays to merge.
- * @return array
- */
-function wfArrayMerge( $array1 /*...*/ ) {
-       wfDeprecated( __FUNCTION__, '1.22' );
-       $args = func_get_args();
-       $args = array_reverse( $args, true );
-       $out = array();
-       foreach ( $args as $arg ) {
-               $out += $arg;
-       }
-       return $out;
-}
-
 /**
  * Merge arrays in the style of getUserPermissionsErrors, with duplicate removal
  * e.g.
@@ -256,7 +216,7 @@ function wfArrayMerge( $array1 /*...*/ ) {
  *             array( 'y' )
  *     )
  *
- * @param array [$array1,...]
+ * @param array $array1,...
  * @return array
  */
 function wfMergeErrorArrays( /*...*/ ) {
@@ -1189,7 +1149,7 @@ function wfDeprecated( $function, $version = false, $component = false, $callerO
  * Send a warning either to the debug log or in a PHP error depending on
  * $wgDevelopmentWarnings. To log warnings in production, use wfLogWarning() instead.
  *
- * @param string $msg message to send
+ * @param string $msg Message to send
  * @param int $callerOffset Number of items to go back in the backtrace to
  *        find the correct caller (1 = function calling wfWarn, ...)
  * @param int $level PHP error level; defaults to E_USER_NOTICE;
@@ -1448,7 +1408,7 @@ function wfGetLangObj( $langcode = false ) {
  * This function replaces all old wfMsg* functions.
  *
  * @param string $key Message key
- * @param mixed [$params,...] Normal message parameters
+ * @param mixed $params,... Normal message parameters
  * @return Message
  *
  * @since 1.17
@@ -1469,7 +1429,7 @@ function wfMessage( $key /*...*/ ) {
  * for the first message which is non-empty. If all messages are empty then an
  * instance of the first message key is returned.
  *
- * @param string|string[] [$keys,...] Message keys
+ * @param string|string[] $keys,... Message keys
  * @return Message
  *
  * @since 1.18
@@ -1489,7 +1449,7 @@ function wfMessageFallback( /*...*/ ) {
  *
  * @deprecated since 1.18
  *
- * @param string $key lookup key for the message, usually
+ * @param string $key Lookup key for the message, usually
  *    defined in languages/Language.php
  *
  * Parameters to the message, which can be used to insert variable text into
@@ -1674,7 +1634,7 @@ function wfMsgReplaceArgs( $message, $args ) {
  * @deprecated since 1.18
  *
  * @param string $key
- * @param string [$args,...] Parameters
+ * @param string $args,... Parameters
  * @return string
  */
 function wfMsgHtml( $key ) {
@@ -1695,7 +1655,7 @@ function wfMsgHtml( $key ) {
  * @deprecated since 1.18
  *
  * @param string $key
- * @param string [$args,...] Parameters
+ * @param string $args,... Parameters
  * @return string
  */
 function wfMsgWikiHtml( $key ) {
@@ -1817,19 +1777,6 @@ function wfEmptyMsg( $key ) {
        return MessageCache::singleton()->get( $key, /*useDB*/true, /*content*/false ) === false;
 }
 
-/**
- * Throw a debugging exception. This function previously once exited the process,
- * but now throws an exception instead, with similar results.
- *
- * @deprecated since 1.22; just throw an MWException yourself
- * @param string $msg Message shown when dying.
- * @throws MWException
- */
-function wfDebugDieBacktrace( $msg = '' ) {
-       wfDeprecated( __FUNCTION__, '1.22' );
-       throw new MWException( $msg );
-}
-
 /**
  * Fetch server name for use in error reporting etc.
  * Use real server name if available, so we know which machine
@@ -1883,7 +1830,7 @@ function wfReportTime() {
        $responseTime = round( ( microtime( true ) - $wgRequestTime ) * 1000 );
        $reportVars = array( 'wgBackendResponseTime' => $responseTime );
        if ( $wgShowHostnames ) {
-               $reportVars[ 'wgHostname' ] = wfHostname();
+               $reportVars['wgHostname'] = wfHostname();
        }
        return Skin::makeVariablesScript( $reportVars );
 }
@@ -2028,36 +1975,6 @@ function wfShowingResults( $offset, $limit ) {
        return wfMessage( 'showingresults' )->numParams( $limit, $offset + 1 )->parse();
 }
 
-/**
- * Generate (prev x| next x) (20|50|100...) type links for paging
- *
- * @param string $offset
- * @param int $limit
- * @param string $link
- * @param string $query Optional URL query parameter string
- * @param bool $atend Optional param for specified if this is the last page
- * @return string
- * @deprecated since 1.19; use Language::viewPrevNext() instead
- */
-function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) {
-       wfDeprecated( __METHOD__, '1.19' );
-
-       global $wgLang;
-
-       $query = wfCgiToArray( $query );
-
-       if ( is_object( $link ) ) {
-               $title = $link;
-       } else {
-               $title = Title::newFromText( $link );
-               if ( is_null( $title ) ) {
-                       return false;
-               }
-       }
-
-       return $wgLang->viewPrevNext( $title, $offset, $limit, $query, $atend );
-}
-
 /**
  * @todo document
  * @todo FIXME: We may want to blacklist some broken browsers
@@ -2156,16 +2073,6 @@ function wfEscapeWikiText( $text ) {
        return $text;
 }
 
-/**
- * Get the current unix timestamp with microseconds.  Useful for profiling
- * @deprecated since 1.22; call microtime() directly
- * @return float
- */
-function wfTime() {
-       wfDeprecated( __FUNCTION__, '1.22' );
-       return microtime( true );
-}
-
 /**
  * Sets dest to source and returns the original value of dest
  * If source is NULL, it just returns the value, it doesn't set the variable
@@ -2316,7 +2223,7 @@ function wfClearOutputBuffers() {
  * factors
  *
  * @param string $accept
- * @param string $def default
+ * @param string $def Default
  * @return float[] Associative array of string => float pairs
  */
 function wfAcceptToPrefs( $accept, $def = '*/*' ) {
@@ -2580,10 +2487,12 @@ function wfIsHHVM() {
 /**
  * Swap two variables
  *
+ * @deprecated since 1.24
  * @param mixed $x
  * @param mixed $y
  */
 function swap( &$x, &$y ) {
+       wfDeprecated( __FUNCTION__, '1.24' );
        $z = $x;
        $x = $y;
        $y = $z;
@@ -2739,7 +2648,7 @@ function wfIniGetBool( $setting ) {
  * Also fixes the locale problems on Linux in PHP 5.2.6+ (bug backported to
  * earlier distro releases of PHP)
  *
- * @param string [$args,...]
+ * @param string $args,...
  * @return string
  */
 function wfEscapeShellArg( /*...*/ ) {
@@ -2823,7 +2732,9 @@ function wfShellExecDisabled() {
  * Execute a shell command, with time and memory limits mirrored from the PHP
  * configuration if supported.
  *
- * @param string $cmd Command line, properly escaped for shell.
+ * @param string|string[] $cmd If string, a properly shell-escaped command line,
+ *   or an array of unescaped arguments, in which case each value will be escaped
+ *   Example:   [ 'convert', '-font', 'font name' ] would produce "'convert' '-font' 'font name'"
  * @param null|mixed &$retval Optional, will receive the program's exit code.
  *   (non-zero is usually failure). If there is an error from
  *   read, select, or proc_open(), this will be set to -1.
@@ -2872,6 +2783,15 @@ function wfShellExec( $cmd, &$retval = null, $environ = array(),
                        $envcmd .= "$k=" . escapeshellarg( $v ) . ' ';
                }
        }
+       if ( is_array( $cmd ) ) {
+               // Command line may be given as an array, escape each value and glue them together with a space
+               $cmdVals = array();
+               foreach ( $cmd as $val ) {
+                       $cmdVals[] = wfEscapeShellArg( $val );
+               }
+               $cmd = implode( ' ', $cmdVals );
+       }
+
        $cmd = $envcmd . $cmd;
 
        $useLogPipe = false;
@@ -2948,19 +2868,28 @@ function wfShellExec( $cmd, &$retval = null, $environ = array(),
                $fds[(int)$pipe] = $fd;
        }
 
-       while ( true ) {
-               $status = proc_get_status( $proc );
-               if ( !$status['running'] ) {
-                       break;
+       $running = true;
+       $timeout = null;
+       $numReadyPipes = 0;
+
+       while ( $running === true || $numReadyPipes !== 0 ) {
+               if ( $running ) {
+                       $status = proc_get_status( $proc );
+                       // If the process has terminated, switch to nonblocking selects
+                       // for getting any data still waiting to be read.
+                       if ( !$status['running'] ) {
+                               $running = false;
+                               $timeout = 0;
+                       }
                }
-               $status = false;
 
                $readyPipes = $pipes;
 
                // Clear last error
                // @codingStandardsIgnoreStart Generic.PHP.NoSilencedErrors.Discouraged
                @trigger_error( '' );
-               if ( @stream_select( $readyPipes, $emptyArray, $emptyArray, null ) === false ) {
+               $numReadyPipes = @stream_select( $readyPipes, $emptyArray, $emptyArray, $timeout );
+               if ( $numReadyPipes === false ) {
                        // @codingStandardsIgnoreEnd
                        $error = error_get_last();
                        if ( strncmp( $error['message'], $eintrMessage, strlen( $eintrMessage ) ) == 0 ) {
@@ -3008,7 +2937,7 @@ function wfShellExec( $cmd, &$retval = null, $environ = array(),
 
        // Use the status previously collected if possible, since proc_get_status()
        // just calls waitpid() which will not return anything useful the second time.
-       if ( $status === false ) {
+       if ( $running ) {
                $status = proc_get_status( $proc );
        }
 
@@ -3049,7 +2978,7 @@ function wfShellExec( $cmd, &$retval = null, $environ = array(),
  * @param string $cmd Command line, properly escaped for shell.
  * @param null|mixed &$retval Optional, will receive the program's exit code.
  *   (non-zero is usually failure)
- * @param array $environ optional environment variables which should be
+ * @param array $environ Optional environment variables which should be
  *   added to the executed command environment.
  * @param array $limits Optional array with limits(filesize, memory, time, walltime)
  *   this overwrites the global wgMaxShell* limits.
@@ -3250,10 +3179,10 @@ function wfDiff( $before, $after, $params = '-u' ) {
 
        // Kill the --- and +++ lines. They're not useful.
        $diff_lines = explode( "\n", $diff );
-       if ( strpos( $diff_lines[0], '---' ) === 0 ) {
+       if ( isset( $diff_lines[0] ) && strpos( $diff_lines[0], '---' ) === 0 ) {
                unset( $diff_lines[0] );
        }
-       if ( strpos( $diff_lines[1], '+++' ) === 0 ) {
+       if ( isset( $diff_lines[1] ) && strpos( $diff_lines[1], '+++' ) === 0 ) {
                unset( $diff_lines[1] );
        }
 
@@ -3437,7 +3366,10 @@ function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1,
        );
 
        if ( extension_loaded( 'gmp' ) && ( $engine == 'auto' || $engine == 'gmp' ) ) {
-               $result = gmp_strval( gmp_init( $input, $sourceBase ), $destBase );
+               // Removing leading zeros works around broken base detection code in
+               // some PHP versions (see <https://bugs.php.net/bug.php?id=50175> and
+               // <https://bugs.php.net/bug.php?id=55398>).
+               $result = gmp_strval( gmp_init( ltrim( $input, '0' ), $sourceBase ), $destBase );
        } elseif ( extension_loaded( 'bcmath' ) && ( $engine == 'auto' || $engine == 'bcmath' ) ) {
                $decimal = '0';
                foreach ( str_split( strtolower( $input ) ) as $char ) {
@@ -3497,7 +3429,7 @@ function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1,
 /**
  * Check if there is sufficient entropy in php's built-in session generation
  *
- * @return bool true = there is sufficient entropy
+ * @return bool True = there is sufficient entropy
  */
 function wfCheckEntropy() {
        return (
@@ -3603,7 +3535,7 @@ function wfGetPrecompiledData( $name ) {
 /**
  * Get a cache key
  *
- * @param string [$args,...]
+ * @param string $args,...
  * @return string
  */
 function wfMemcKey( /*...*/ ) {
@@ -3620,7 +3552,7 @@ function wfMemcKey( /*...*/ ) {
  *
  * @param string $db
  * @param string $prefix
- * @param string [$args,...]
+ * @param string $args,...
  * @return string
  */
 function wfForeignMemcKey( $db, $prefix /*...*/ ) {
@@ -3692,7 +3624,7 @@ function &wfGetDB( $db, $groups = array(), $wiki = false ) {
 /**
  * Get a load balancer object.
  *
- * @param string|bool $wiki wiki ID, or false for the current wiki
+ * @param string|bool $wiki Wiki ID, or false for the current wiki
  * @return LoadBalancer
  */
 function wfGetLB( $wiki = false ) {
@@ -3712,7 +3644,7 @@ function &wfGetLBFactory() {
  * Find a file.
  * Shortcut for RepoGroup::singleton()->findFile()
  *
- * @param string $title or Title object
+ * @param string $title String or Title object
  * @param array $options Associative array of options:
  *     time:           requested time for an archived image, or false for the
  *                     current version. An image object will be returned which was
@@ -3779,7 +3711,7 @@ function wfScript( $script = 'index' ) {
 /**
  * Get the script URL.
  *
- * @return string script URL
+ * @return string Script URL
  */
 function wfGetScriptUrl() {
        if ( isset( $_SERVER['SCRIPT_NAME'] ) ) {
@@ -3826,11 +3758,15 @@ function wfGetNull() {
  * in maintenance scripts, to avoid causing too much lag.  Of course, this is
  * a no-op if there are no slaves.
  *
- * @param int|bool $maxLag (deprecated)
+ * @param float|null $ifWritesSince Only wait if writes were done since this UNIX timestamp
  * @param string|bool $wiki Wiki identifier accepted by wfGetLB
  * @param string|bool $cluster Cluster name accepted by LBFactory. Default: false.
+ * @return bool Success (able to connect and no timeouts reached)
  */
-function wfWaitForSlaves( $maxLag = false, $wiki = false, $cluster = false ) {
+function wfWaitForSlaves( $ifWritesSince = false, $wiki = false, $cluster = false ) {
+       // B/C: first argument used to be "max seconds of lag"; ignore such values
+       $ifWritesSince = ( $ifWritesSince > 1e9 ) ? $ifWritesSince : false;
+
        if ( $cluster !== false ) {
                $lb = wfGetLBFactory()->getExternalLB( $cluster );
        } else {
@@ -3840,14 +3776,22 @@ function wfWaitForSlaves( $maxLag = false, $wiki = false, $cluster = false ) {
        // bug 27975 - Don't try to wait for slaves if there are none
        // Prevents permission error when getting master position
        if ( $lb->getServerCount() > 1 ) {
+               if ( $ifWritesSince && !$lb->hasMasterConnection() ) {
+                       return true; // assume no writes done
+               }
                $dbw = $lb->getConnection( DB_MASTER, array(), $wiki );
+               if ( $ifWritesSince && $dbw->lastDoneWrites() < $ifWritesSince ) {
+                       return true; // no writes since the last wait
+               }
                $pos = $dbw->getMasterPos();
                // The DBMS may not support getMasterPos() or the whole
                // load balancer might be fake (e.g. $wgAllDBsAreLocalhost).
                if ( $pos !== false ) {
-                       $lb->waitForAll( $pos );
+                       return $lb->waitForAll( $pos, PHP_SAPI === 'cli' ? 86400 : null );
                }
        }
+
+       return true;
 }
 
 /**
@@ -4051,7 +3995,7 @@ function wfRunHooks( $event, array $args = array(), $deprecatedVersion = null )
  * Also be careful when using this function to read unsigned 32 bit integer
  * because php might make it negative.
  *
- * @throws MWException if $data not long enough, or if unpack fails
+ * @throws MWException If $data not long enough, or if unpack fails
  * @return array Associative array of the extracted data
  */
 function wfUnpack( $format, $data, $length = false ) {
index d0cae36..69f1120 100644 (file)
@@ -202,7 +202,7 @@ class HistoryBlobStub {
        /** @var string */
        public $mHash;
 
-       /** @var  */
+       /** @var string */
        public $mRef;
 
        /**
@@ -351,10 +351,10 @@ class HistoryBlobCurStub {
  */
 class DiffHistoryBlob implements HistoryBlob {
        /** @var array Uncompressed item cache */
-       protected $mItems = array();
+       public $mItems = array();
 
        /** @var int Total uncompressed size */
-       protected $mSize = 0;
+       public $mSize = 0;
 
        /**
         * @var array Array of diffs. If a diff D from A to B is notated D = B - A,
@@ -364,20 +364,20 @@ class DiffHistoryBlob implements HistoryBlob {
         *    diff[i] = {
         *              { item[map[i]] - Z                where i = 0
         */
-       protected $mDiffs;
+       public $mDiffs;
 
        /** @var array The diff map, see above */
-       protected $mDiffMap;
+       public $mDiffMap;
 
        /** @var int The key for getText()
         */
-       protected $mDefaultKey;
+       public $mDefaultKey;
 
        /** @var string Compressed storage */
        public $mCompressed;
 
        /** @var bool True if the object is locked against further writes */
-       protected $mFrozen = false;
+       public $mFrozen = false;
 
        /**
         * @var int The maximum uncompressed size before the object becomes sad
@@ -593,7 +593,7 @@ class DiffHistoryBlob implements HistoryBlob {
         * the bytes backwards and initialised with 0 instead of 1. See bug 34428.
         *
         * @param string $s
-        * @return string|bool false if the hash extension is not available
+        * @return string|bool False if the hash extension is not available
         */
        function xdiffAdler32( $s ) {
                if ( !function_exists( 'hash' ) ) {
index 77486b2..2928748 100644 (file)
@@ -64,10 +64,10 @@ class Hooks {
         * Clears hooks registered via Hooks::register(). Does not touch $wgHooks.
         * This is intended for use while testing and will fail if MW_PHPUNIT_TEST is not defined.
         *
-        * @param string $name the name of the hook to clear.
+        * @param string $name The name of the hook to clear.
         *
         * @since 1.21
-        * @throws MWException if not in testing mode.
+        * @throws MWException If not in testing mode.
         */
        public static function clear( $name ) {
                if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
@@ -123,7 +123,7 @@ class Hooks {
         * Finally, process the return value and return/throw accordingly.
         *
         * @param string $event Event name
-        * @param array $args  Array of parameters passed to hook functions
+        * @param array $args Array of parameters passed to hook functions
         * @param string|null $deprecatedVersion Optionally, mark hook as deprecated with version number
         * @return bool True if no handler aborted the hook
         *
index 5262ffe..1e16e39 100644 (file)
@@ -36,7 +36,7 @@
  *
  * There are two important configuration options this class uses:
  *
- * $wgMimeType: If this is set to an xml mimetype then output should be
+ * $wgMimeType: If this is set to an xml MIME type then output should be
  *     valid XHTML5.
  * $wgWellFormedXml: If this is set to true, then all output should be
  *     well-formed XML (quotes on attributes, self-closing tags, etc.).
@@ -101,6 +101,35 @@ class Html {
                'itemscope',
        );
 
+       /**
+        * Modifies a set of attributes meant for text input elements
+        * and apply a set of default attributes.
+        * Removes size attribute when $wgUseMediaWikiUIEverywhere enabled.
+        * @param array $attrs An attribute array.
+        * @return array $attrs A modified attribute array
+        */
+       public static function getTextInputAttributes( $attrs ) {
+               global $wgUseMediaWikiUIEverywhere;
+               if ( !$attrs ) {
+                       $attrs = array();
+               }
+               if ( isset( $attrs['class'] ) ) {
+                       if ( is_array( $attrs['class'] ) ) {
+                               $attrs['class'][] = 'mw-ui-input';
+                       } else {
+                               $attrs['class'] .= ' mw-ui-input';
+                       }
+               } else {
+                       $attrs['class'] = 'mw-ui-input';
+               }
+               if ( $wgUseMediaWikiUIEverywhere ) {
+                       // Note that size can effect the desired width rendering of mw-ui-input elements
+                       // so it is removed. Left intact when mediawiki ui not enabled.
+                       unset( $attrs['size'] );
+               }
+               return $attrs;
+       }
+
        /**
         * Returns an HTML element in a string.  The major advantage here over
         * manually typing out the HTML is that it will escape all attribute
@@ -114,7 +143,7 @@ class Html {
         * shaved off the HTML output as well.
         *
         * @param string $element The element's name, e.g., 'a'
-        * @param array $attribs  Associative array of attributes, e.g., array(
+        * @param array $attribs Associative array of attributes, e.g., array(
         *   'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for
         *   further documentation.
         * @param string $contents The raw HTML contents of the element: *not*
@@ -225,33 +254,15 @@ class Html {
        }
 
        /**
-        * Returns "</$element>", except if $wgWellFormedXml is off, in which case
-        * it returns the empty string when that's guaranteed to be safe.
+        * Returns "</$element>"
         *
         * @since 1.17
         * @param string $element Name of the element, e.g., 'a'
-        * @return string A closing tag, if required
+        * @return string A closing tag
         */
        public static function closeElement( $element ) {
-               global $wgWellFormedXml;
-
                $element = strtolower( $element );
 
-               // Reference:
-               // http://www.whatwg.org/html/syntax.html#optional-tags
-               if ( !$wgWellFormedXml && in_array( $element, array(
-                       'html',
-                       'head',
-                       'body',
-                       'li',
-                       'dt',
-                       'dd',
-                       'tr',
-                       'td',
-                       'th',
-               ) ) ) {
-                       return '';
-               }
                return "</$element>";
        }
 
@@ -386,7 +397,7 @@ class Html {
         * For instance, it will omit quotation marks if $wgWellFormedXml is false,
         * and will treat boolean attributes specially.
         *
-        * Attributes that should contain space-separated lists (such as 'class') array
+        * Attributes that can contain space-separated lists ('class', 'accesskey' and 'rel') array
         * values are allowed as well, which will automagically be normalized
         * and converted to a space-separated string. In addition to a numerical
         * array, the attribute value may also be an associative array. See the
@@ -413,6 +424,8 @@ class Html {
         *   A value of false means to omit the attribute.  For boolean attributes,
         *   you can omit the key, e.g., array( 'checked' ) instead of
         *   array( 'checked' => 'checked' ) or such.
+        *
+        * @throws MWException If an attribute that doesn't allow lists is set to an array
         * @return string HTML fragment that goes between element name and '>'
         *   (starting with a space if at least one attribute is output)
         */
@@ -500,6 +513,8 @@ class Html {
 
                                // Remove duplicates and create the string
                                $value = implode( ' ', array_unique( $value ) );
+                       } elseif ( is_array( $value ) ) {
+                               throw new MWException( "HTML attribute $key can not contain a list of values" );
                        }
 
                        // See the "Attributes" section in the HTML syntax part of HTML5,
@@ -646,10 +661,73 @@ class Html {
                $attribs['type'] = $type;
                $attribs['value'] = $value;
                $attribs['name'] = $name;
-
+               if ( in_array( $type, array( 'text', 'search', 'email', 'password', 'number' ) ) ) {
+                       $attribs = Html::getTextInputAttributes( $attribs );
+               }
                return self::element( 'input', $attribs );
        }
 
+       /**
+        * Convenience function to produce a checkbox (input element with type=checkbox)
+        *
+        * @param string $name Name attribute
+        * @param bool $checked Whether the checkbox is checked or not
+        * @param array $attribs Array of additional attributes
+        * @return string
+        */
+       public static function check( $name, $checked = false, array $attribs = array() ) {
+               if ( isset( $attribs['value'] ) ) {
+                       $value = $attribs['value'];
+                       unset( $attribs['value'] );
+               } else {
+                       $value = 1;
+               }
+
+               if ( $checked ) {
+                       $attribs[] = 'checked';
+               }
+
+               return self::input( $name, $value, 'checkbox', $attribs );
+       }
+
+       /**
+        * Convenience function to produce a checkbox (input element with type=checkbox)
+        *
+        * @param string $name Name attribute
+        * @param bool $checked Whether the checkbox is checked or not
+        * @param array $attribs Array of additional attributes
+        * @return string
+        */
+       public static function radio( $name, $checked = false, array $attribs = array() ) {
+               if ( isset( $attribs['value'] ) ) {
+                       $value = $attribs['value'];
+                       unset( $attribs['value'] );
+               } else {
+                       $value = 1;
+               }
+
+               if ( $checked ) {
+                       $attribs[] = 'checked';
+               }
+
+               return self::input( $name, $value, 'radio', $attribs );
+       }
+
+       /**
+        * Convenience function for generating a label for inputs.
+        *
+        * @param string $label Contents of the label
+        * @param string $id ID of the element being labeled
+        * @param array $attribs Additional attributes
+        * @return string
+        */
+       public static function label( $label, $id, array $attribs = array() ) {
+               $attribs += array(
+                       'for' => $id
+               );
+               return self::element( 'label', $attribs, $label );
+       }
+
        /**
         * Convenience function to produce an input element with type=hidden
         *
@@ -687,7 +765,7 @@ class Html {
                } else {
                        $spacedValue = $value;
                }
-               return self::element( 'textarea', $attribs, $spacedValue );
+               return self::element( 'textarea', Html::getTextInputAttributes( $attribs ), $spacedValue );
        }
 
        /**
@@ -810,7 +888,7 @@ class Html {
                $isXHTML = self::isXmlMimeType( $wgMimeType );
 
                if ( $isXHTML ) { // XHTML5
-                       // XML mimetyped markup should have an xml header.
+                       // XML MIME-typed markup should have an xml header.
                        // However a DOCTYPE is not needed.
                        $ret .= "<?xml version=\"1.0\" encoding=\"UTF-8\" ?" . ">\n";
 
@@ -842,16 +920,16 @@ class Html {
        }
 
        /**
-        * Determines if the given mime type is xml.
+        * Determines if the given MIME type is xml.
         *
-        * @param string $mimetype MimeType
+        * @param string $mimetype MIME type
         * @return bool
         */
        public static function isXmlMimeType( $mimetype ) {
                # http://www.whatwg.org/html/infrastructure.html#xml-mime-type
                # * text/xml
                # * application/xml
-               # * Any mimetype with a subtype ending in +xml (this implicitly includes application/xhtml+xml)
+               # * Any MIME type with a subtype ending in +xml (this implicitly includes application/xhtml+xml)
                return (bool)preg_match( '!^(text|application)/xml$|^.+/.+\+xml$!', $mimetype );
        }
 
@@ -859,20 +937,13 @@ class Html {
         * Get HTML for an info box with an icon.
         *
         * @param string $text Wikitext, get this with wfMessage()->plain()
-        * @param string $icon Icon name, file in skins/common/images
+        * @param string $icon Path to icon file (used as 'src' attribute)
         * @param string $alt Alternate text for the icon
         * @param string $class Additional class name to add to the wrapper div
-        * @param bool $useStylePath
         *
         * @return string
         */
-       static function infoBox( $text, $icon, $alt, $class = false, $useStylePath = true ) {
-               global $wgStylePath;
-
-               if ( $useStylePath ) {
-                       $icon = $wgStylePath . '/common/images/' . $icon;
-               }
-
+       static function infoBox( $text, $icon, $alt, $class = false ) {
                $s = Html::openElement( 'div', array( 'class' => "mw-infobox $class" ) );
 
                $s .= Html::openElement( 'div', array( 'class' => 'mw-infobox-left' ) ) .
index 38aa392..ccbfba8 100644 (file)
@@ -130,7 +130,7 @@ class HtmlFormatter {
        /**
         * Removes content we've chosen to remove.  The text of the removed elements can be
         * extracted with the getText method.
-        * @return array of removed DOMElements
+        * @return array Array of removed DOMElements
         */
        public function filterContent() {
                wfProfileIn( __METHOD__ );
@@ -138,7 +138,7 @@ class HtmlFormatter {
 
                // Bail out early if nothing to do
                if ( array_reduce( $removals,
-                       function( $carry, $item ) {
+                       function ( $carry, $item ) {
                                return $carry && !$item;
                        },
                        true
@@ -209,7 +209,7 @@ class HtmlFormatter {
        /**
         * Removes a list of elelments from DOMDocument
         * @param array|DOMNodeList $elements
-        * @return array of removed elements
+        * @return array Array of removed elements
         */
        private function removeElements( $elements ) {
                $list = $elements;
@@ -237,7 +237,7 @@ class HtmlFormatter {
        private function fixLibXML( $html ) {
                wfProfileIn( __METHOD__ );
                static $replacements;
-               if ( ! $replacements ) {
+               if ( !$replacements ) {
                        // We don't include rules like '&#34;' => '&amp;quot;' because entities had already been
                        // normalized by libxml. Using this function with input not sanitized by libxml is UNSAFE!
                        $replacements = new ReplacementArray( array(
index c9dd0c0..8302124 100644 (file)
@@ -36,8 +36,8 @@ class Http {
         * Perform an HTTP request
         *
         * @param string $method HTTP method. Usually GET/POST
-        * @param string $url full URL to act on. If protocol-relative, will be expanded to an http:// URL
-        * @param array $options options to pass to MWHttpRequest object.
+        * @param string $url Full URL to act on. If protocol-relative, will be expanded to an http:// URL
+        * @param array $options Options to pass to MWHttpRequest object.
         *      Possible keys for the array:
         *    - timeout             Timeout length in seconds
         *    - connectTimeout      Timeout for connection, in seconds (curl only)
@@ -772,7 +772,7 @@ class CurlHttpRequest extends MWHttpRequest {
 
                if ( $this->followRedirects && $this->canFollowRedirects() ) {
                        wfSuppressWarnings();
-                       if ( ! curl_setopt( $curlHandle, CURLOPT_FOLLOWLOCATION, true ) ) {
+                       if ( !curl_setopt( $curlHandle, CURLOPT_FOLLOWLOCATION, true ) ) {
                                wfDebug( __METHOD__ . ": Couldn't set CURLOPT_FOLLOWLOCATION. " .
                                        "Probably safe_mode or open_basedir is set.\n" );
                                // Continue the processing. If it were in curl_setopt_array,
@@ -809,7 +809,8 @@ class CurlHttpRequest extends MWHttpRequest {
                        return false;
                }
 
-               if ( !defined( 'CURLOPT_REDIR_PROTOCOLS' ) ) {
+               $curlVersionInfo = curl_version();
+               if ( $curlVersionInfo['version_number'] < 0x071304 ) {
                        wfDebug( "Cannot follow redirects with libcurl < 7.19.4 due to CVE-2009-0037\n" );
                        return false;
                }
index 177d023..5319076 100644 (file)
@@ -45,7 +45,7 @@ class WikiImporter {
        function __construct( ImportStreamSource $source ) {
                $this->reader = new XMLReader();
 
-               if ( !in_array(  'uploadsource', stream_get_wrappers() ) ) {
+               if ( !in_array( 'uploadsource', stream_get_wrappers() ) ) {
                        stream_wrapper_register( 'uploadsource', 'UploadSourceAdapter' );
                }
                $id = UploadSourceAdapter::registerSource( $source );
@@ -395,8 +395,8 @@ class WikiImporter {
 
        /**
         * Retrieves the contents of the named attribute of the current element.
-        * @param string $attr the name of the attribute
-        * @return string the value of the attribute or an empty string if it is not set in the current element.
+        * @param string $attr The name of the attribute
+        * @return string The value of the attribute or an empty string if it is not set in the current element.
         */
        public function nodeAttribute( $attr ) {
                return $this->reader->getAttribute( $attr );
@@ -429,53 +429,12 @@ class WikiImporter {
                return '';
        }
 
-       # --------------
-
-       /** Left in for debugging */
-       private function dumpElement() {
-               static $lookup = null;
-               if ( !$lookup ) {
-                       $xmlReaderConstants = array(
-                               "NONE",
-                               "ELEMENT",
-                               "ATTRIBUTE",
-                               "TEXT",
-                               "CDATA",
-                               "ENTITY_REF",
-                               "ENTITY",
-                               "PI",
-                               "COMMENT",
-                               "DOC",
-                               "DOC_TYPE",
-                               "DOC_FRAGMENT",
-                               "NOTATION",
-                               "WHITESPACE",
-                               "SIGNIFICANT_WHITESPACE",
-                               "END_ELEMENT",
-                               "END_ENTITY",
-                               "XML_DECLARATION",
-                       );
-                       $lookup = array();
-
-                       foreach ( $xmlReaderConstants as $name ) {
-                               $lookup[constant( "XmlReader::$name" )] = $name;
-                       }
-               }
-
-               print var_dump(
-                       $lookup[$this->reader->nodeType],
-                       $this->reader->name,
-                       $this->reader->value
-               ) . "\n\n";
-       }
-
        /**
         * Primary entry point
         * @throws MWException
         * @return bool
         */
        public function doImport() {
-
                // Calls to reader->read need to be wrapped in calls to
                // libxml_disable_entity_loader() to avoid local file
                // inclusion attacks (bug 46932).
@@ -533,7 +492,7 @@ class WikiImporter {
        private function handleSiteInfo() {
                // Site info is useful, but not actually used for dump imports.
                // Includes a quick short-circuit to save performance.
-               if ( ! $this->mSiteInfoCallback ) {
+               if ( !$this->mSiteInfoCallback ) {
                        $this->reader->next();
                        return true;
                }
@@ -932,7 +891,7 @@ class WikiImporter {
 /** This is a horrible hack used to keep source compatibility */
 class UploadSourceAdapter {
        /** @var array */
-       private static $sourceRegistrations = array();
+       public static $sourceRegistrations = array();
 
        /** @var string */
        private $mSource;
@@ -1050,43 +1009,19 @@ class UploadSourceAdapter {
        }
 }
 
-class XMLReader2 extends XMLReader {
-
-       /**
-        * @return bool|string
-        */
-       function nodeContents() {
-               if ( $this->isEmptyElement ) {
-                       return "";
-               }
-               $buffer = "";
-               while ( $this->read() ) {
-                       switch ( $this->nodeType ) {
-                       case XmlReader::TEXT:
-                       case XmlReader::SIGNIFICANT_WHITESPACE:
-                               $buffer .= $this->value;
-                               break;
-                       case XmlReader::END_ELEMENT:
-                               return $buffer;
-                       }
-               }
-               return $this->close();
-       }
-}
-
 /**
  * @todo document (e.g. one-sentence class description).
  * @ingroup SpecialPage
  */
 class WikiRevision {
        /** @todo Unused? */
-       private $importer = null;
+       public $importer = null;
 
        /** @var Title */
        public $title = null;
 
        /** @var int */
-       private $id = 0;
+       public $id = 0;
 
        /** @var string */
        public $timestamp = "20010115000000";
@@ -1100,10 +1035,10 @@ class WikiRevision {
        public $user_text = "";
 
        /** @var string */
-       protected $model = null;
+       public $model = null;
 
        /** @var string */
-       protected $format = null;
+       public $format = null;
 
        /** @var string */
        public $text = "";
@@ -1112,7 +1047,7 @@ class WikiRevision {
        protected $size;
 
        /** @var Content */
-       protected $content = null;
+       public $content = null;
 
        /** @var ContentHandler */
        protected $contentHandler = null;
@@ -1121,31 +1056,31 @@ class WikiRevision {
        public $comment = "";
 
        /** @var bool */
-       protected $minor = false;
+       public $minor = false;
 
        /** @var string */
-       protected $type = "";
+       public $type = "";
 
        /** @var string */
-       protected $action = "";
+       public $action = "";
 
        /** @var string */
-       protected $params = "";
+       public $params = "";
 
        /** @var string */
-       protected $fileSrc = '';
+       public $fileSrc = '';
 
        /** @var bool|string */
-       protected $sha1base36 = false;
+       public $sha1base36 = false;
 
        /**
         * @var bool
         * @todo Unused?
         */
-       private $isTemp = false;
+       public $isTemp = false;
 
        /** @var string */
-       protected $archiveName = '';
+       public $archiveName = '';
 
        protected $filename;
 
@@ -1153,7 +1088,7 @@ class WikiRevision {
        protected $src;
 
        /** @todo Unused? */
-       private $fileIsTemp;
+       public $fileIsTemp;
 
        /** @var bool */
        private $mNoUpdates = false;
@@ -1503,6 +1438,7 @@ class WikiRevision {
                $linkCache->clear();
 
                $page = WikiPage::factory( $this->title );
+               $page->loadPageData( 'fromdbmaster' );
                if ( !$page->exists() ) {
                        # must create the page...
                        $pageId = $page->insertOn( $dbw );
@@ -1558,9 +1494,6 @@ class WikiRevision {
                return true;
        }
 
-       /**
-        * @return mixed
-        */
        function importLogItem() {
                $dbw = wfGetDB( DB_MASTER );
                # @todo FIXME: This will not record autoblocks
diff --git a/includes/Init.php b/includes/Init.php
deleted file mode 100644 (file)
index d9aeb7b..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-<?php
-/**
- * Some functions that are useful during startup.
- *
- * This class previously contained some functionality related to a PHP compiler
- * called hphpc. That compiler has now been discontinued.
- *
- * 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
- */
-
-/**
- * Some functions that are useful during startup.
- *
- * This class previously contained some functionality related to a PHP compiler
- * called hphpc. That compiler has now been discontinued. All methods are now
- * deprecated.
- */
-class MWInit {
-       private static $compilerVersion;
-
-       /**
-        * @deprecated since 1.22
-        */
-       static function getCompilerVersion() {
-               return false;
-       }
-
-       /**
-        * Returns true if we are running under HipHop, whether in compiled or
-        * interpreted mode.
-        *
-        * @deprecated since 1.22
-        * @return bool
-        */
-       static function isHipHop() {
-               return wfIsHHVM();
-       }
-
-       /**
-        * Get a fully-qualified path for a source file relative to $IP.
-        * @deprecated since 1.22
-        *
-        * @param string $file
-        *
-        * @return string
-        */
-       static function interpretedPath( $file ) {
-               global $IP;
-               return "$IP/$file";
-       }
-
-       /**
-        * @deprecated since 1.22
-        * @param string $file
-        * @return string
-        */
-       static function compiledPath( $file ) {
-               global $IP;
-               return "$IP/$file";
-       }
-
-       /**
-        * @deprecated since 1.22
-        * @param string $file
-        * @return string
-        */
-       static function extCompiledPath( $file ) {
-               return false;
-       }
-
-       /**
-        * Deprecated wrapper for class_exists()
-        * @deprecated since 1.22
-        *
-        * @param string $class
-        *
-        * @return bool
-        */
-       static function classExists( $class ) {
-               return class_exists( $class );
-       }
-
-       /**
-        * Deprecated wrapper for method_exists()
-        * @deprecated since 1.22
-        *
-        * @param string $class
-        * @param string $method
-        *
-        * @return bool
-        */
-       static function methodExists( $class, $method ) {
-               return method_exists( $class, $method );
-       }
-
-       /**
-        * Deprecated wrapper for function_exists()
-        * @deprecated since 1.22
-        *
-        * @param string $function
-        *
-        * @return bool
-        */
-       static function functionExists( $function ) {
-               return function_exists( $function );
-       }
-
-       /**
-        * Deprecated wrapper for call_user_func_array()
-        * @deprecated since 1.22
-        *
-        * @param string $className
-        * @param string $methodName
-        * @param array $args
-        *
-        * @return mixed
-        */
-       static function callStaticMethod( $className, $methodName, $args ) {
-               return call_user_func_array( array( $className, $methodName ), $args );
-       }
-}
index 54b779e..0bcbc91 100644 (file)
@@ -199,7 +199,7 @@ class License {
        public $text;
 
        /**
-        * @param string $str license name??
+        * @param string $str License name??
         */
        function __construct( $str ) {
                list( $text, $template ) = explode( '|', strrev( $str ), 2 );
index 7d88f25..012bc1b 100644 (file)
@@ -25,7 +25,7 @@
  * for primarily page content: links, embedded images, table of contents. Links
  * are also used in the skin.
  *
- * @todo: turn this into a legacy interface for HtmlPageLinkRenderer and similar services.
+ * @todo turn this into a legacy interface for HtmlPageLinkRenderer and similar services.
  *
  * @ingroup Skins
  */
@@ -259,6 +259,7 @@ class Linker {
 
        /**
         * Identical to link(), except $options defaults to 'known'.
+        * @see Linker::link
         * @return string
         */
        public static function linkKnown(
@@ -272,7 +273,7 @@ class Linker {
         * Returns the Url used to link to a Title
         *
         * @param Title $target
-        * @param array $query query parameters
+        * @param array $query Query parameters
         * @param array $options
         * @return string
         */
@@ -702,6 +703,7 @@ class Linker {
         * frame parameters supplied by the Parser.
         * @param array $frameParams The frame parameters
         * @param string $query An optional query string to add to description page links
+        * @param Parser|null $parser
         * @return array
         */
        private static function getImageLinkMTOParams( $frameParams, $query = '', $parser = null ) {
@@ -770,7 +772,6 @@ class Linker {
        public static function makeThumbLink2( Title $title, $file, $frameParams = array(),
                $handlerParams = array(), $time = false, $query = ""
        ) {
-               global $wgStylePath, $wgContLang;
                $exists = $file && $file->exists();
 
                # Shortcuts
@@ -879,12 +880,7 @@ class Linker {
                                                'href' => $url,
                                                'class' => 'internal',
                                                'title' => wfMessage( 'thumbnail-more' )->text() ),
-                                               Html::element( 'img', array(
-                                                       'src' => $wgStylePath . '/common/images/magnify-clip'
-                                                               . ( $wgContLang->isRTL() ? '-rtl' : '' ) . '.png',
-                                                       'width' => 15,
-                                                       'height' => 11,
-                                                       'alt' => "" ) ) ) );
+                                               "" ) );
                        }
                }
                $s .= '  <div class="thumbcaption">' . $zoomIcon . $fp['caption'] . "</div></div></div>";
@@ -901,7 +897,7 @@ class Linker {
         */
        public static function processResponsiveImages( $file, $thumb, $hp ) {
                global $wgResponsiveImages;
-               if ( $wgResponsiveImages ) {
+               if ( $wgResponsiveImages && $thumb && !$thumb->isError() ) {
                        $hp15 = $hp;
                        $hp15['width'] = round( $hp['width'] * 1.5 );
                        $hp20 = $hp;
@@ -913,10 +909,10 @@ class Linker {
 
                        $thumb15 = $file->transform( $hp15 );
                        $thumb20 = $file->transform( $hp20 );
-                       if ( $thumb15 && $thumb15->getUrl() !== $thumb->getUrl() ) {
+                       if ( $thumb15 && !$thumb15->isError() && $thumb15->getUrl() !== $thumb->getUrl() ) {
                                $thumb->responsiveUrls['1.5'] = $thumb15->getUrl();
                        }
-                       if ( $thumb20 && $thumb20->getUrl() !== $thumb->getUrl() ) {
+                       if ( $thumb20 && !$thumb20->isError() && $thumb20->getUrl() !== $thumb->getUrl() ) {
                                $thumb->responsiveUrls['2'] = $thumb20->getUrl();
                        }
                }
@@ -937,7 +933,7 @@ class Linker {
                $query = '', $unused1 = '', $unused2 = '', $time = false
        ) {
                global $wgEnableUploads, $wgUploadMissingFileUrl, $wgUploadNavigationUrl;
-               if ( ! $title instanceof Title ) {
+               if ( !$title instanceof Title ) {
                        return "<!-- ERROR -->" . htmlspecialchars( $label );
                }
                wfProfileIn( __METHOD__ );
@@ -1379,7 +1375,7 @@ class Linker {
                                                . '<span dir="auto">' . $auto . $post . '</span>';
                                }
                                return $comment;
-               },
+                       },
                        $comment
                );
        }
@@ -1418,7 +1414,11 @@ class Linker {
 
                                # fix up urlencoded title texts (copied from Parser::replaceInternalLinks)
                                if ( strpos( $match[1], '%' ) !== false ) {
-                                       $match[1] = str_replace( array( '<', '>' ), array( '&lt;', '&gt;' ), rawurldecode( $match[1] ) );
+                                       $match[1] = str_replace(
+                                               array( '<', '>' ),
+                                               array( '&lt;', '&gt;' ),
+                                               rawurldecode( $match[1] )
+                                       );
                                }
 
                                # Handle link renaming [[foo|text]] will show link as "text"
@@ -2151,7 +2151,7 @@ class Linker {
                return $tooltip;
        }
 
-       private static $accesskeycache;
+       public static $accesskeycache;
 
        /**
         * Given the id of an interface element, constructs the appropriate
@@ -2198,7 +2198,7 @@ class Linker {
         *
         * @param User $user
         * @param Revision $rev
-        * @param Revision $title
+        * @param Title $title
         * @return string HTML fragment
         */
        public static function getRevDeleteLink( User $user, Revision $rev, Title $title ) {
diff --git a/includes/MWNamespace.php b/includes/MWNamespace.php
new file mode 100644 (file)
index 0000000..392f558
--- /dev/null
@@ -0,0 +1,496 @@
+<?php
+/**
+ * Provide things related to namespaces.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * This is a utility class with only static functions
+ * for dealing with namespaces that encodes all the
+ * "magic" behaviors of them based on index.  The textual
+ * names of the namespaces are handled by Language.php.
+ *
+ * These are synonyms for the names given in the language file
+ * Users and translators should not change them
+ *
+ */
+class MWNamespace {
+
+       /**
+        * These namespaces should always be first-letter capitalized, now and
+        * forevermore. Historically, they could've probably been lowercased too,
+        * but some things are just too ingrained now. :)
+        */
+       private static $alwaysCapitalizedNamespaces = array( NS_SPECIAL, NS_USER, NS_MEDIAWIKI );
+
+       /**
+        * Throw an exception when trying to get the subject or talk page
+        * for a given namespace where it does not make sense.
+        * Special namespaces are defined in includes/Defines.php and have
+        * a value below 0 (ex: NS_SPECIAL = -1 , NS_MEDIA = -2)
+        *
+        * @param int $index
+        * @param string $method
+        *
+        * @throws MWException
+        * @return bool
+        */
+       private static function isMethodValidFor( $index, $method ) {
+               if ( $index < NS_MAIN ) {
+                       throw new MWException( "$method does not make any sense for given namespace $index" );
+               }
+               return true;
+       }
+
+       /**
+        * Can pages in the given namespace be moved?
+        *
+        * @param int $index Namespace index
+        * @return bool
+        */
+       public static function isMovable( $index ) {
+               global $wgAllowImageMoving;
+
+               $result = !( $index < NS_MAIN || ( $index == NS_FILE && !$wgAllowImageMoving ) );
+
+               /**
+                * @since 1.20
+                */
+               wfRunHooks( 'NamespaceIsMovable', array( $index, &$result ) );
+
+               return $result;
+       }
+
+       /**
+        * Is the given namespace is a subject (non-talk) namespace?
+        *
+        * @param int $index Namespace index
+        * @return bool
+        * @since 1.19
+        */
+       public static function isSubject( $index ) {
+               return !self::isTalk( $index );
+       }
+
+       /**
+        * Is the given namespace a talk namespace?
+        *
+        * @param int $index Namespace index
+        * @return bool
+        */
+       public static function isTalk( $index ) {
+               return $index > NS_MAIN
+                       && $index % 2;
+       }
+
+       /**
+        * Get the talk namespace index for a given namespace
+        *
+        * @param int $index Namespace index
+        * @return int
+        */
+       public static function getTalk( $index ) {
+               self::isMethodValidFor( $index, __METHOD__ );
+               return self::isTalk( $index )
+                       ? $index
+                       : $index + 1;
+       }
+
+       /**
+        * Get the subject namespace index for a given namespace
+        * Special namespaces (NS_MEDIA, NS_SPECIAL) are always the subject.
+        *
+        * @param int $index Namespace index
+        * @return int
+        */
+       public static function getSubject( $index ) {
+               # Handle special namespaces
+               if ( $index < NS_MAIN ) {
+                       return $index;
+               }
+
+               return self::isTalk( $index )
+                       ? $index - 1
+                       : $index;
+       }
+
+       /**
+        * Get the associated namespace.
+        * For talk namespaces, returns the subject (non-talk) namespace
+        * For subject (non-talk) namespaces, returns the talk namespace
+        *
+        * @param int $index Namespace index
+        * @return int|null If no associated namespace could be found
+        */
+       public static function getAssociated( $index ) {
+               self::isMethodValidFor( $index, __METHOD__ );
+
+               if ( self::isSubject( $index ) ) {
+                       return self::getTalk( $index );
+               } elseif ( self::isTalk( $index ) ) {
+                       return self::getSubject( $index );
+               } else {
+                       return null;
+               }
+       }
+
+       /**
+        * Returns whether the specified namespace exists
+        *
+        * @param int $index
+        *
+        * @return bool
+        * @since 1.19
+        */
+       public static function exists( $index ) {
+               $nslist = self::getCanonicalNamespaces();
+               return isset( $nslist[$index] );
+       }
+
+       /**
+        * Returns whether the specified namespaces are the same namespace
+        *
+        * @note It's possible that in the future we may start using something
+        * other than just namespace indexes. Under that circumstance making use
+        * of this function rather than directly doing comparison will make
+        * sure that code will not potentially break.
+        *
+        * @param int $ns1 The first namespace index
+        * @param int $ns2 The second namespace index
+        *
+        * @return bool
+        * @since 1.19
+        */
+       public static function equals( $ns1, $ns2 ) {
+               return $ns1 == $ns2;
+       }
+
+       /**
+        * Returns whether the specified namespaces share the same subject.
+        * eg: NS_USER and NS_USER wil return true, as well
+        *     NS_USER and NS_USER_TALK will return true.
+        *
+        * @param int $ns1 The first namespace index
+        * @param int $ns2 The second namespace index
+        *
+        * @return bool
+        * @since 1.19
+        */
+       public static function subjectEquals( $ns1, $ns2 ) {
+               return self::getSubject( $ns1 ) == self::getSubject( $ns2 );
+       }
+
+       /**
+        * Returns array of all defined namespaces with their canonical
+        * (English) names.
+        *
+        * @param bool $rebuild Rebuild namespace list (default = false). Used for testing.
+        *
+        * @return array
+        * @since 1.17
+        */
+       public static function getCanonicalNamespaces( $rebuild = false ) {
+               static $namespaces = null;
+               if ( $namespaces === null || $rebuild ) {
+                       global $wgExtraNamespaces, $wgCanonicalNamespaceNames;
+                       $namespaces = array( NS_MAIN => '' ) + $wgCanonicalNamespaceNames;
+                       if ( is_array( $wgExtraNamespaces ) ) {
+                               $namespaces += $wgExtraNamespaces;
+                       }
+                       wfRunHooks( 'CanonicalNamespaces', array( &$namespaces ) );
+               }
+               return $namespaces;
+       }
+
+       /**
+        * Returns the canonical (English) name for a given index
+        *
+        * @param int $index Namespace index
+        * @return string|bool If no canonical definition.
+        */
+       public static function getCanonicalName( $index ) {
+               $nslist = self::getCanonicalNamespaces();
+               if ( isset( $nslist[$index] ) ) {
+                       return $nslist[$index];
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * Returns the index for a given canonical name, or NULL
+        * The input *must* be converted to lower case first
+        *
+        * @param string $name Namespace name
+        * @return int
+        */
+       public static function getCanonicalIndex( $name ) {
+               static $xNamespaces = false;
+               if ( $xNamespaces === false ) {
+                       $xNamespaces = array();
+                       foreach ( self::getCanonicalNamespaces() as $i => $text ) {
+                               $xNamespaces[strtolower( $text )] = $i;
+                       }
+               }
+               if ( array_key_exists( $name, $xNamespaces ) ) {
+                       return $xNamespaces[$name];
+               } else {
+                       return null;
+               }
+       }
+
+       /**
+        * Returns an array of the namespaces (by integer id) that exist on the
+        * wiki. Used primarily by the api in help documentation.
+        * @return array
+        */
+       public static function getValidNamespaces() {
+               static $mValidNamespaces = null;
+
+               if ( is_null( $mValidNamespaces ) ) {
+                       foreach ( array_keys( self::getCanonicalNamespaces() ) as $ns ) {
+                               if ( $ns >= 0 ) {
+                                       $mValidNamespaces[] = $ns;
+                               }
+                       }
+               }
+
+               return $mValidNamespaces;
+       }
+
+       /**
+        * Can this namespace ever have a talk namespace?
+        *
+        * @param int $index Namespace index
+        * @return bool
+        */
+       public static function canTalk( $index ) {
+               return $index >= NS_MAIN;
+       }
+
+       /**
+        * Does this namespace contain content, for the purposes of calculating
+        * statistics, etc?
+        *
+        * @param int $index Index to check
+        * @return bool
+        */
+       public static function isContent( $index ) {
+               global $wgContentNamespaces;
+               return $index == NS_MAIN || in_array( $index, $wgContentNamespaces );
+       }
+
+       /**
+        * Can pages in a namespace be watched?
+        *
+        * @param int $index
+        * @return bool
+        */
+       public static function isWatchable( $index ) {
+               return $index >= NS_MAIN;
+       }
+
+       /**
+        * Does the namespace allow subpages?
+        *
+        * @param int $index Index to check
+        * @return bool
+        */
+       public static function hasSubpages( $index ) {
+               global $wgNamespacesWithSubpages;
+               return !empty( $wgNamespacesWithSubpages[$index] );
+       }
+
+       /**
+        * Get a list of all namespace indices which are considered to contain content
+        * @return array Array of namespace indices
+        */
+       public static function getContentNamespaces() {
+               global $wgContentNamespaces;
+               if ( !is_array( $wgContentNamespaces ) || $wgContentNamespaces === array() ) {
+                       return array( NS_MAIN );
+               } elseif ( !in_array( NS_MAIN, $wgContentNamespaces ) ) {
+                       // always force NS_MAIN to be part of array (to match the algorithm used by isContent)
+                       return array_merge( array( NS_MAIN ), $wgContentNamespaces );
+               } else {
+                       return $wgContentNamespaces;
+               }
+       }
+
+       /**
+        * List all namespace indices which are considered subject, aka not a talk
+        * or special namespace. See also MWNamespace::isSubject
+        *
+        * @return array Array of namespace indices
+        */
+       public static function getSubjectNamespaces() {
+               return array_filter(
+                       MWNamespace::getValidNamespaces(),
+                       'MWNamespace::isSubject'
+               );
+       }
+
+       /**
+        * List all namespace indices which are considered talks, aka not a subject
+        * or special namespace. See also MWNamespace::isTalk
+        *
+        * @return array Array of namespace indices
+        */
+       public static function getTalkNamespaces() {
+               return array_filter(
+                       MWNamespace::getValidNamespaces(),
+                       'MWNamespace::isTalk'
+               );
+       }
+
+       /**
+        * Is the namespace first-letter capitalized?
+        *
+        * @param int $index Index to check
+        * @return bool
+        */
+       public static function isCapitalized( $index ) {
+               global $wgCapitalLinks, $wgCapitalLinkOverrides;
+               // Turn NS_MEDIA into NS_FILE
+               $index = $index === NS_MEDIA ? NS_FILE : $index;
+
+               // Make sure to get the subject of our namespace
+               $index = self::getSubject( $index );
+
+               // Some namespaces are special and should always be upper case
+               if ( in_array( $index, self::$alwaysCapitalizedNamespaces ) ) {
+                       return true;
+               }
+               if ( isset( $wgCapitalLinkOverrides[$index] ) ) {
+                       // $wgCapitalLinkOverrides is explicitly set
+                       return $wgCapitalLinkOverrides[$index];
+               }
+               // Default to the global setting
+               return $wgCapitalLinks;
+       }
+
+       /**
+        * Does the namespace (potentially) have different aliases for different
+        * genders. Not all languages make a distinction here.
+        *
+        * @since 1.18
+        * @param int $index Index to check
+        * @return bool
+        */
+       public static function hasGenderDistinction( $index ) {
+               return $index == NS_USER || $index == NS_USER_TALK;
+       }
+
+       /**
+        * It is not possible to use pages from this namespace as template?
+        *
+        * @since 1.20
+        * @param int $index Index to check
+        * @return bool
+        */
+       public static function isNonincludable( $index ) {
+               global $wgNonincludableNamespaces;
+               return $wgNonincludableNamespaces && in_array( $index, $wgNonincludableNamespaces );
+       }
+
+       /**
+        * Get the default content model for a namespace
+        * This does not mean that all pages in that namespace have the model
+        *
+        * @since 1.21
+        * @param int $index Index to check
+        * @return null|string Default model name for the given namespace, if set
+        */
+       public static function getNamespaceContentModel( $index ) {
+               global $wgNamespaceContentModels;
+               return isset( $wgNamespaceContentModels[$index] )
+                       ? $wgNamespaceContentModels[$index]
+                       : null;
+       }
+
+       /**
+        * Determine which restriction levels it makes sense to use in a namespace,
+        * optionally filtered by a user's rights.
+        *
+        * @since 1.23
+        * @param int $index Index to check
+        * @param User $user User to check
+        * @return array
+        */
+       public static function getRestrictionLevels( $index, User $user = null ) {
+               global $wgNamespaceProtection, $wgRestrictionLevels;
+
+               if ( !isset( $wgNamespaceProtection[$index] ) ) {
+                       // All levels are valid if there's no namespace restriction.
+                       // But still filter by user, if necessary
+                       $levels = $wgRestrictionLevels;
+                       if ( $user ) {
+                               $levels = array_values( array_filter( $levels, function ( $level ) use ( $user ) {
+                                       $right = $level;
+                                       if ( $right == 'sysop' ) {
+                                               $right = 'editprotected'; // BC
+                                       }
+                                       if ( $right == 'autoconfirmed' ) {
+                                               $right = 'editsemiprotected'; // BC
+                                       }
+                                       return ( $right == '' || $user->isAllowed( $right ) );
+                               } ) );
+                       }
+                       return $levels;
+               }
+
+               // First, get the list of groups that can edit this namespace.
+               $namespaceGroups = array();
+               $combine = 'array_merge';
+               foreach ( (array)$wgNamespaceProtection[$index] as $right ) {
+                       if ( $right == 'sysop' ) {
+                               $right = 'editprotected'; // BC
+                       }
+                       if ( $right == 'autoconfirmed' ) {
+                               $right = 'editsemiprotected'; // BC
+                       }
+                       if ( $right != '' ) {
+                               $namespaceGroups = call_user_func( $combine, $namespaceGroups,
+                                       User::getGroupsWithPermission( $right ) );
+                               $combine = 'array_intersect';
+                       }
+               }
+
+               // Now, keep only those restriction levels where there is at least one
+               // group that can edit the namespace but would be blocked by the
+               // restriction.
+               $usableLevels = array( '' );
+               foreach ( $wgRestrictionLevels as $level ) {
+                       $right = $level;
+                       if ( $right == 'sysop' ) {
+                               $right = 'editprotected'; // BC
+                       }
+                       if ( $right == 'autoconfirmed' ) {
+                               $right = 'editsemiprotected'; // BC
+                       }
+                       if ( $right != '' && ( !$user || $user->isAllowed( $right ) ) &&
+                               array_diff( $namespaceGroups, User::getGroupsWithPermission( $right ) )
+                       ) {
+                               $usableLevels[] = $level;
+                       }
+               }
+
+               return $usableLevels;
+       }
+}
index ad3228d..26f5e54 100644 (file)
@@ -238,7 +238,6 @@ class MWTimestamp {
         * @since 1.22
         *
         * @param User $user User to take preferences from
-        * @param[out] MWTimestamp $ts Timestamp to adjust
         * @return DateInterval Offset that was applied to the timestamp
         */
        public function offsetForUser( User $user ) {
@@ -401,7 +400,7 @@ class MWTimestamp {
         *
         * @since 1.22
         * @param bool|string $ts Timestamp to set, or false for current time
-        * @return MWTimestamp the local instance
+        * @return MWTimestamp The local instance
         */
        public static function getLocalInstance( $ts = false ) {
                global $wgLocaltimezone;
@@ -415,7 +414,7 @@ class MWTimestamp {
         *
         * @since 1.22
         * @param bool|string $ts Timestamp to set, or false for current time
-        * @return MWTimestamp the instance
+        * @return MWTimestamp The instance
         */
        public static function getInstance( $ts = false ) {
                return new self( $ts );
index 7decbee..4d17298 100644 (file)
@@ -754,6 +754,7 @@ class MagicWordArray {
 
        /**
         * Get a 2-d hashtable for this array
+        * @return array
         */
        function getHash() {
                if ( is_null( $this->hash ) ) {
@@ -775,6 +776,7 @@ class MagicWordArray {
 
        /**
         * Get the base regex
+        * @return array
         */
        function getBaseRegex() {
                if ( is_null( $this->baseRegex ) ) {
@@ -799,6 +801,7 @@ class MagicWordArray {
 
        /**
         * Get an unanchored regex that does not match parameters
+        * @return array
         */
        function getRegex() {
                if ( is_null( $this->regex ) ) {
diff --git a/includes/MediaWiki.php b/includes/MediaWiki.php
new file mode 100644 (file)
index 0000000..9213c02
--- /dev/null
@@ -0,0 +1,704 @@
+<?php
+/**
+ * Helper class for the index.php entry point.
+ *
+ * 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
+ */
+
+/**
+ * The MediaWiki class is the helper class for the index.php entry point.
+ *
+ * @internal documentation reviewed 15 Mar 2010
+ */
+class MediaWiki {
+       /**
+        * @var IContextSource
+        */
+       private $context;
+
+       /**
+        * @var Config
+        */
+       private $config;
+
+       /**
+        * @param IContextSource|null $context
+        */
+       public function __construct( IContextSource $context = null ) {
+               if ( !$context ) {
+                       $context = RequestContext::getMain();
+               }
+
+               $this->context = $context;
+               $this->config = $context->getConfig();
+       }
+
+       /**
+        * Parse the request to get the Title object
+        *
+        * @return Title Title object to be $wgTitle
+        */
+       private function parseTitle() {
+               global $wgContLang;
+
+               $request = $this->context->getRequest();
+               $curid = $request->getInt( 'curid' );
+               $title = $request->getVal( 'title' );
+               $action = $request->getVal( 'action', 'view' );
+
+               if ( $request->getCheck( 'search' ) ) {
+                       // Compatibility with old search URLs which didn't use Special:Search
+                       // Just check for presence here, so blank requests still
+                       // show the search page when using ugly URLs (bug 8054).
+                       $ret = SpecialPage::getTitleFor( 'Search' );
+               } elseif ( $curid ) {
+                       // URLs like this are generated by RC, because rc_title isn't always accurate
+                       $ret = Title::newFromID( $curid );
+               } else {
+                       $ret = Title::newFromURL( $title );
+                       // Alias NS_MEDIA page URLs to NS_FILE...we only use NS_MEDIA
+                       // in wikitext links to tell Parser to make a direct file link
+                       if ( !is_null( $ret ) && $ret->getNamespace() == NS_MEDIA ) {
+                               $ret = Title::makeTitle( NS_FILE, $ret->getDBkey() );
+                       }
+                       // Check variant links so that interwiki links don't have to worry
+                       // about the possible different language variants
+                       if ( count( $wgContLang->getVariants() ) > 1
+                               && !is_null( $ret ) && $ret->getArticleID() == 0
+                       ) {
+                               $wgContLang->findVariantLink( $title, $ret );
+                       }
+               }
+
+               // If title is not provided, always allow oldid and diff to set the title.
+               // If title is provided, allow oldid and diff to override the title, unless
+               // we are talking about a special page which might use these parameters for
+               // other purposes.
+               if ( $ret === null || !$ret->isSpecialPage() ) {
+                       // We can have urls with just ?diff=,?oldid= or even just ?diff=
+                       $oldid = $request->getInt( 'oldid' );
+                       $oldid = $oldid ? $oldid : $request->getInt( 'diff' );
+                       // Allow oldid to override a changed or missing title
+                       if ( $oldid ) {
+                               $rev = Revision::newFromId( $oldid );
+                               $ret = $rev ? $rev->getTitle() : $ret;
+                       }
+               }
+
+               // Use the main page as default title if nothing else has been provided
+               if ( $ret === null
+                       && strval( $title ) === ''
+                       && !$request->getCheck( 'curid' )
+                       && $action !== 'delete'
+               ) {
+                       $ret = Title::newMainPage();
+               }
+
+               if ( $ret === null || ( $ret->getDBkey() == '' && !$ret->isExternal() ) ) {
+                       $ret = SpecialPage::getTitleFor( 'Badtitle' );
+               }
+
+               return $ret;
+       }
+
+       /**
+        * Get the Title object that we'll be acting on, as specified in the WebRequest
+        * @return Title
+        */
+       public function getTitle() {
+               if ( $this->context->getTitle() === null ) {
+                       $this->context->setTitle( $this->parseTitle() );
+               }
+               return $this->context->getTitle();
+       }
+
+       /**
+        * Returns the name of the action that will be executed.
+        *
+        * @return string Action
+        */
+       public function getAction() {
+               static $action = null;
+
+               if ( $action === null ) {
+                       $action = Action::getActionName( $this->context );
+               }
+
+               return $action;
+       }
+
+       /**
+        * Performs the request.
+        * - bad titles
+        * - read restriction
+        * - local interwiki redirects
+        * - redirect loop
+        * - special pages
+        * - normal pages
+        *
+        * @throws MWException|PermissionsError|BadTitleError|HttpError
+        * @return void
+        */
+       private function performRequest() {
+               global $wgTitle;
+
+               wfProfileIn( __METHOD__ );
+
+               $request = $this->context->getRequest();
+               $requestTitle = $title = $this->context->getTitle();
+               $output = $this->context->getOutput();
+               $user = $this->context->getUser();
+
+               if ( $request->getVal( 'printable' ) === 'yes' ) {
+                       $output->setPrintable();
+               }
+
+               $unused = null; // To pass it by reference
+               wfRunHooks( 'BeforeInitialize', array( &$title, &$unused, &$output, &$user, $request, $this ) );
+
+               // Invalid titles. Bug 21776: The interwikis must redirect even if the page name is empty.
+               if ( is_null( $title ) || ( $title->getDBkey() == '' && !$title->isExternal() )
+                       || $title->isSpecial( 'Badtitle' )
+               ) {
+                       $this->context->setTitle( SpecialPage::getTitleFor( 'Badtitle' ) );
+                       wfProfileOut( __METHOD__ );
+                       throw new BadTitleError();
+               }
+
+               // Check user's permissions to read this page.
+               // We have to check here to catch special pages etc.
+               // We will check again in Article::view().
+               $permErrors = $title->isSpecial( 'RunJobs' )
+                       ? array() // relies on HMAC key signature alone
+                       : $title->getUserPermissionsErrors( 'read', $user );
+               if ( count( $permErrors ) ) {
+                       // Bug 32276: allowing the skin to generate output with $wgTitle or
+                       // $this->context->title set to the input title would allow anonymous users to
+                       // determine whether a page exists, potentially leaking private data. In fact, the
+                       // curid and oldid request  parameters would allow page titles to be enumerated even
+                       // when they are not guessable. So we reset the title to Special:Badtitle before the
+                       // permissions error is displayed.
+                       //
+                       // The skin mostly uses $this->context->getTitle() these days, but some extensions
+                       // still use $wgTitle.
+
+                       $badTitle = SpecialPage::getTitleFor( 'Badtitle' );
+                       $this->context->setTitle( $badTitle );
+                       $wgTitle = $badTitle;
+
+                       wfProfileOut( __METHOD__ );
+                       throw new PermissionsError( 'read', $permErrors );
+               }
+
+               $pageView = false; // was an article or special page viewed?
+
+               // Interwiki redirects
+               if ( $title->isExternal() ) {
+                       $rdfrom = $request->getVal( 'rdfrom' );
+                       if ( $rdfrom ) {
+                               $url = $title->getFullURL( array( 'rdfrom' => $rdfrom ) );
+                       } else {
+                               $query = $request->getValues();
+                               unset( $query['title'] );
+                               $url = $title->getFullURL( $query );
+                       }
+                       // Check for a redirect loop
+                       if ( !preg_match( '/^' . preg_quote( $this->config->get( 'Server' ), '/' ) . '/', $url )
+                               && $title->isLocal()
+                       ) {
+                               // 301 so google et al report the target as the actual url.
+                               $output->redirect( $url, 301 );
+                       } else {
+                               $this->context->setTitle( SpecialPage::getTitleFor( 'Badtitle' ) );
+                               wfProfileOut( __METHOD__ );
+                               throw new BadTitleError();
+                       }
+               // Redirect loops, no title in URL, $wgUsePathInfo URLs, and URLs with a variant
+               } elseif ( $request->getVal( 'action', 'view' ) == 'view' && !$request->wasPosted()
+                       && ( $request->getVal( 'title' ) === null
+                               || $title->getPrefixedDBkey() != $request->getVal( 'title' ) )
+                       && !count( $request->getValueNames( array( 'action', 'title' ) ) )
+                       && wfRunHooks( 'TestCanonicalRedirect', array( $request, $title, $output ) )
+               ) {
+                       if ( $title->isSpecialPage() ) {
+                               list( $name, $subpage ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
+                               if ( $name ) {
+                                       $title = SpecialPage::getTitleFor( $name, $subpage );
+                               }
+                       }
+                       $targetUrl = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
+                       // Redirect to canonical url, make it a 301 to allow caching
+                       if ( $targetUrl == $request->getFullRequestURL() ) {
+                               $message = "Redirect loop detected!\n\n" .
+                                       "This means the wiki got confused about what page was " .
+                                       "requested; this sometimes happens when moving a wiki " .
+                                       "to a new server or changing the server configuration.\n\n";
+
+                               if ( $this->config->get( 'UsePathInfo' ) ) {
+                                       $message .= "The wiki is trying to interpret the page " .
+                                               "title from the URL path portion (PATH_INFO), which " .
+                                               "sometimes fails depending on the web server. Try " .
+                                               "setting \"\$wgUsePathInfo = false;\" in your " .
+                                               "LocalSettings.php, or check that \$wgArticlePath " .
+                                               "is correct.";
+                               } else {
+                                       $message .= "Your web server was detected as possibly not " .
+                                               "supporting URL path components (PATH_INFO) correctly; " .
+                                               "check your LocalSettings.php for a customized " .
+                                               "\$wgArticlePath setting and/or toggle \$wgUsePathInfo " .
+                                               "to true.";
+                               }
+                               throw new HttpError( 500, $message );
+                       } else {
+                               $output->setSquidMaxage( 1200 );
+                               $output->redirect( $targetUrl, '301' );
+                       }
+               // Special pages
+               } elseif ( NS_SPECIAL == $title->getNamespace() ) {
+                       $pageView = true;
+                       // Actions that need to be made when we have a special pages
+                       SpecialPageFactory::executePath( $title, $this->context );
+               } else {
+                       // ...otherwise treat it as an article view. The article
+                       // may be a redirect to another article or URL.
+                       $article = $this->initializeArticle();
+                       if ( is_object( $article ) ) {
+                               $pageView = true;
+                               $this->performAction( $article, $requestTitle );
+                       } elseif ( is_string( $article ) ) {
+                               $output->redirect( $article );
+                       } else {
+                               wfProfileOut( __METHOD__ );
+                               throw new MWException( "Shouldn't happen: MediaWiki::initializeArticle()"
+                                       . " returned neither an object nor a URL" );
+                       }
+               }
+
+               if ( $pageView ) {
+                       // Promote user to any groups they meet the criteria for
+                       $user->addAutopromoteOnceGroups( 'onView' );
+               }
+
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Initialize the main Article object for "standard" actions (view, etc)
+        * Create an Article object for the page, following redirects if needed.
+        *
+        * @return mixed An Article, or a string to redirect to another URL
+        */
+       private function initializeArticle() {
+               wfProfileIn( __METHOD__ );
+
+               $title = $this->context->getTitle();
+               if ( $this->context->canUseWikiPage() ) {
+                       // Try to use request context wiki page, as there
+                       // is already data from db saved in per process
+                       // cache there from this->getAction() call.
+                       $page = $this->context->getWikiPage();
+                       $article = Article::newFromWikiPage( $page, $this->context );
+               } else {
+                       // This case should not happen, but just in case.
+                       $article = Article::newFromTitle( $title, $this->context );
+                       $this->context->setWikiPage( $article->getPage() );
+               }
+
+               // NS_MEDIAWIKI has no redirects.
+               // It is also used for CSS/JS, so performance matters here...
+               if ( $title->getNamespace() == NS_MEDIAWIKI ) {
+                       wfProfileOut( __METHOD__ );
+                       return $article;
+               }
+
+               $request = $this->context->getRequest();
+
+               // Namespace might change when using redirects
+               // Check for redirects ...
+               $action = $request->getVal( 'action', 'view' );
+               $file = ( $title->getNamespace() == NS_FILE ) ? $article->getFile() : null;
+               if ( ( $action == 'view' || $action == 'render' ) // ... for actions that show content
+                       && !$request->getVal( 'oldid' ) // ... and are not old revisions
+                       && !$request->getVal( 'diff' ) // ... and not when showing diff
+                       && $request->getVal( 'redirect' ) != 'no' // ... unless explicitly told not to
+                       // ... and the article is not a non-redirect image page with associated file
+                       && !( is_object( $file ) && $file->exists() && !$file->getRedirected() )
+               ) {
+                       // Give extensions a change to ignore/handle redirects as needed
+                       $ignoreRedirect = $target = false;
+
+                       wfRunHooks( 'InitializeArticleMaybeRedirect',
+                               array( &$title, &$request, &$ignoreRedirect, &$target, &$article ) );
+
+                       // Follow redirects only for... redirects.
+                       // If $target is set, then a hook wanted to redirect.
+                       if ( !$ignoreRedirect && ( $target || $article->isRedirect() ) ) {
+                               // Is the target already set by an extension?
+                               $target = $target ? $target : $article->followRedirect();
+                               if ( is_string( $target ) ) {
+                                       if ( !$this->config->get( 'DisableHardRedirects' ) ) {
+                                               // we'll need to redirect
+                                               wfProfileOut( __METHOD__ );
+                                               return $target;
+                                       }
+                               }
+                               if ( is_object( $target ) ) {
+                                       // Rewrite environment to redirected article
+                                       $rarticle = Article::newFromTitle( $target, $this->context );
+                                       $rarticle->loadPageData();
+                                       if ( $rarticle->exists() || ( is_object( $file ) && !$file->isLocal() ) ) {
+                                               $rarticle->setRedirectedFrom( $title );
+                                               $article = $rarticle;
+                                               $this->context->setTitle( $target );
+                                               $this->context->setWikiPage( $article->getPage() );
+                                       }
+                               }
+                       } else {
+                               $this->context->setTitle( $article->getTitle() );
+                               $this->context->setWikiPage( $article->getPage() );
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $article;
+       }
+
+       /**
+        * Perform one of the "standard" actions
+        *
+        * @param Page $page
+        * @param Title $requestTitle The original title, before any redirects were applied
+        */
+       private function performAction( Page $page, Title $requestTitle ) {
+               wfProfileIn( __METHOD__ );
+
+               $request = $this->context->getRequest();
+               $output = $this->context->getOutput();
+               $title = $this->context->getTitle();
+               $user = $this->context->getUser();
+
+               if ( !wfRunHooks( 'MediaWikiPerformAction',
+                               array( $output, $page, $title, $user, $request, $this ) )
+               ) {
+                       wfProfileOut( __METHOD__ );
+                       return;
+               }
+
+               $act = $this->getAction();
+
+               $action = Action::factory( $act, $page, $this->context );
+
+               if ( $action instanceof Action ) {
+                       # Let Squid cache things if we can purge them.
+                       if ( $this->config->get( 'UseSquid' ) &&
+                               in_array( $request->getFullRequestURL(), $requestTitle->getSquidURLs() )
+                       ) {
+                               $output->setSquidMaxage( $this->config->get( 'SquidMaxage' ) );
+                       }
+
+                       $action->show();
+                       wfProfileOut( __METHOD__ );
+                       return;
+               }
+
+               if ( wfRunHooks( 'UnknownAction', array( $request->getVal( 'action', 'view' ), $page ) ) ) {
+                       $output->setStatusCode( 404 );
+                       $output->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
+               }
+
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Run the current MediaWiki instance
+        * index.php just calls this
+        */
+       public function run() {
+               try {
+                       $this->checkMaxLag();
+                       try {
+                               $this->main();
+                       } catch ( ErrorPageError $e ) {
+                               // Bug 62091: while exceptions are convenient to bubble up GUI errors,
+                               // they are not internal application faults. As with normal requests, this
+                               // should commit, print the output, do deferred updates, jobs, and profiling.
+                               wfGetLBFactory()->commitMasterChanges();
+                               $e->report(); // display the GUI error
+                       }
+                       if ( function_exists( 'fastcgi_finish_request' ) ) {
+                               fastcgi_finish_request();
+                       }
+                       $this->triggerJobs();
+                       $this->restInPeace();
+               } catch ( Exception $e ) {
+                       MWExceptionHandler::handle( $e );
+               }
+       }
+
+       /**
+        * Checks if the request should abort due to a lagged server,
+        * for given maxlag parameter.
+        * @return bool
+        */
+       private function checkMaxLag() {
+               wfProfileIn( __METHOD__ );
+               $maxLag = $this->context->getRequest()->getVal( 'maxlag' );
+               if ( !is_null( $maxLag ) ) {
+                       list( $host, $lag ) = wfGetLB()->getMaxLag();
+                       if ( $lag > $maxLag ) {
+                               $resp = $this->context->getRequest()->response();
+                               $resp->header( 'HTTP/1.1 503 Service Unavailable' );
+                               $resp->header( 'Retry-After: ' . max( intval( $maxLag ), 5 ) );
+                               $resp->header( 'X-Database-Lag: ' . intval( $lag ) );
+                               $resp->header( 'Content-Type: text/plain' );
+                               if ( $this->config->get( 'ShowHostnames' ) ) {
+                                       echo "Waiting for $host: $lag seconds lagged\n";
+                               } else {
+                                       echo "Waiting for a database server: $lag seconds lagged\n";
+                               }
+
+                               wfProfileOut( __METHOD__ );
+
+                               exit;
+                       }
+               }
+               wfProfileOut( __METHOD__ );
+               return true;
+       }
+
+       private function main() {
+               global $wgTitle;
+
+               wfProfileIn( __METHOD__ );
+
+               $request = $this->context->getRequest();
+
+               // Send Ajax requests to the Ajax dispatcher.
+               if ( $this->config->get( 'UseAjax' ) && $request->getVal( 'action', 'view' ) == 'ajax' ) {
+
+                       // Set a dummy title, because $wgTitle == null might break things
+                       $title = Title::makeTitle( NS_MAIN, 'AJAX' );
+                       $this->context->setTitle( $title );
+                       $wgTitle = $title;
+
+                       $dispatcher = new AjaxDispatcher( $this->config );
+                       $dispatcher->performAction( $this->context->getUser() );
+                       wfProfileOut( __METHOD__ );
+                       return;
+               }
+
+               // Get title from request parameters,
+               // is set on the fly by parseTitle the first time.
+               $title = $this->getTitle();
+               $action = $this->getAction();
+               $wgTitle = $title;
+
+               // If the user has forceHTTPS set to true, or if the user
+               // is in a group requiring HTTPS, or if they have the HTTPS
+               // preference set, redirect them to HTTPS.
+               // Note: Do this after $wgTitle is setup, otherwise the hooks run from
+               // isLoggedIn() will do all sorts of weird stuff.
+               if (
+                       $request->getProtocol() == 'http' &&
+                       (
+                               $request->getCookie( 'forceHTTPS', '' ) ||
+                               // check for prefixed version for currently logged in users
+                               $request->getCookie( 'forceHTTPS' ) ||
+                               // Avoid checking the user and groups unless it's enabled.
+                               (
+                                       $this->context->getUser()->isLoggedIn()
+                                       && $this->context->getUser()->requiresHTTPS()
+                               )
+                       )
+               ) {
+                       $oldUrl = $request->getFullRequestURL();
+                       $redirUrl = preg_replace( '#^http://#', 'https://', $oldUrl );
+
+                       // ATTENTION: This hook is likely to be removed soon due to overall design of the system.
+                       if ( wfRunHooks( 'BeforeHttpsRedirect', array( $this->context, &$redirUrl ) ) ) {
+
+                               if ( $request->wasPosted() ) {
+                                       // This is weird and we'd hope it almost never happens. This
+                                       // means that a POST came in via HTTP and policy requires us
+                                       // redirecting to HTTPS. It's likely such a request is going
+                                       // to fail due to post data being lost, but let's try anyway
+                                       // and just log the instance.
+                                       //
+                                       // @todo FIXME: See if we could issue a 307 or 308 here, need
+                                       // to see how clients (automated & browser) behave when we do
+                                       wfDebugLog( 'RedirectedPosts', "Redirected from HTTP to HTTPS: $oldUrl" );
+                               }
+                               // Setup dummy Title, otherwise OutputPage::redirect will fail
+                               $title = Title::newFromText( NS_MAIN, 'REDIR' );
+                               $this->context->setTitle( $title );
+                               $output = $this->context->getOutput();
+                               // Since we only do this redir to change proto, always send a vary header
+                               $output->addVaryHeader( 'X-Forwarded-Proto' );
+                               $output->redirect( $redirUrl );
+                               $output->output();
+                               wfProfileOut( __METHOD__ );
+                               return;
+                       }
+               }
+
+               if ( $this->config->get( 'UseFileCache' ) && $title->getNamespace() >= 0 ) {
+                       wfProfileIn( 'main-try-filecache' );
+                       if ( HTMLFileCache::useFileCache( $this->context ) ) {
+                               // Try low-level file cache hit
+                               $cache = HTMLFileCache::newFromTitle( $title, $action );
+                               if ( $cache->isCacheGood( /* Assume up to date */ ) ) {
+                                       // Check incoming headers to see if client has this cached
+                                       $timestamp = $cache->cacheTimestamp();
+                                       if ( !$this->context->getOutput()->checkLastModified( $timestamp ) ) {
+                                               $cache->loadFromFileCache( $this->context );
+                                       }
+                                       // Do any stats increment/watchlist stuff
+                                       // Assume we're viewing the latest revision (this should always be the case with file cache)
+                                       $this->context->getWikiPage()->doViewUpdates( $this->context->getUser() );
+                                       // Tell OutputPage that output is taken care of
+                                       $this->context->getOutput()->disable();
+                                       wfProfileOut( 'main-try-filecache' );
+                                       wfProfileOut( __METHOD__ );
+                                       return;
+                               }
+                       }
+                       wfProfileOut( 'main-try-filecache' );
+               }
+
+               // Actually do the work of the request and build up any output
+               $this->performRequest();
+
+               // Either all DB and deferred updates should happen or none.
+               // The later should not be cancelled due to client disconnect.
+               ignore_user_abort( true );
+               // Now commit any transactions, so that unreported errors after
+               // output() don't roll back the whole DB transaction
+               wfGetLBFactory()->commitMasterChanges();
+
+               // Output everything!
+               $this->context->getOutput()->output();
+
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Ends this task peacefully
+        */
+       public function restInPeace() {
+               // Do any deferred jobs
+               DeferredUpdates::doUpdates( 'commit' );
+
+               // Log profiling data, e.g. in the database or UDP
+               wfLogProfilingData();
+
+               // Commit and close up!
+               $factory = wfGetLBFactory();
+               $factory->commitMasterChanges();
+               $factory->shutdown();
+
+               wfDebug( "Request ended normally\n" );
+       }
+
+       /**
+        * Potentially open a socket and sent an HTTP request back to the server
+        * to run a specified number of jobs. This registers a callback to cleanup
+        * the socket once it's done.
+        */
+       protected function triggerJobs() {
+               $jobRunRate = $this->config->get( 'JobRunRate' );
+               if ( $jobRunRate <= 0 || wfReadOnly() ) {
+                       return;
+               } elseif ( $this->getTitle()->isSpecial( 'RunJobs' ) ) {
+                       return; // recursion guard
+               }
+
+               $section = new ProfileSection( __METHOD__ );
+
+               if ( $jobRunRate < 1 ) {
+                       $max = mt_getrandmax();
+                       if ( mt_rand( 0, $max ) > $max * $jobRunRate ) {
+                               return; // the higher the job run rate, the less likely we return here
+                       }
+                       $n = 1;
+               } else {
+                       $n = intval( $jobRunRate );
+               }
+
+               if ( !$this->config->get( 'RunJobsAsync' ) ) {
+                       // Fall back to running the job here while the user waits
+                       $runner = new JobRunner();
+                       $runner->run( array( 'maxJobs'  => $n ) );
+                       return;
+               }
+
+               try {
+                       if ( !JobQueueGroup::singleton()->queuesHaveJobs( JobQueueGroup::TYPE_DEFAULT ) ) {
+                               return; // do not send request if there are probably no jobs
+                       }
+               } catch ( JobQueueError $e ) {
+                       MWExceptionHandler::logException( $e );
+                       return; // do not make the site unavailable
+               }
+
+               $query = array( 'title' => 'Special:RunJobs',
+                       'tasks' => 'jobs', 'maxjobs' => $n, 'sigexpiry' => time() + 5 );
+               $query['signature'] = SpecialRunJobs::getQuerySignature(
+                       $query, $this->config->get( 'SecretKey' ) );
+
+               $errno = $errstr = null;
+               $info = wfParseUrl( $this->config->get( 'Server' ) );
+               wfSuppressWarnings();
+               $sock = fsockopen(
+                       $info['host'],
+                       isset( $info['port'] ) ? $info['port'] : 80,
+                       $errno,
+                       $errstr,
+                       // If it takes more than 100ms to connect to ourselves there
+                       // is a problem elsewhere.
+                       0.1
+               );
+               wfRestoreWarnings();
+               if ( !$sock ) {
+                       wfDebugLog( 'runJobs', "Failed to start cron API (socket error $errno): $errstr\n" );
+                       // Fall back to running the job here while the user waits
+                       $runner = new JobRunner();
+                       $runner->run( array( 'maxJobs'  => $n ) );
+                       return;
+               }
+
+               $url = wfAppendQuery( wfScript( 'index' ), $query );
+               $req = "POST $url HTTP/1.1\r\nHost: {$info['host']}\r\nConnection: Close\r\n\r\n";
+
+               wfDebugLog( 'runJobs', "Running $n job(s) via '$url'\n" );
+               // Send a cron API request to be performed in the background.
+               // Give up if this takes too long to send (which should be rare).
+               stream_set_timeout( $sock, 1 );
+               $bytes = fwrite( $sock, $req );
+               if ( $bytes !== strlen( $req ) ) {
+                       wfDebugLog( 'runJobs', "Failed to start cron API (socket write error)\n" );
+               } else {
+                       // Do not wait for the response (the script should handle client aborts).
+                       // Make sure that we don't close before that script reaches ignore_user_abort().
+                       $status = fgets( $sock );
+                       if ( !preg_match( '#^HTTP/\d\.\d 202 #', $status ) ) {
+                               wfDebugLog( 'runJobs', "Failed to start cron API: received '$status'\n" );
+                       }
+               }
+               fclose( $sock );
+       }
+}
index 950bcd5..4df0d80 100644 (file)
@@ -175,10 +175,16 @@ class Message {
        protected $language = null;
 
        /**
-        * @var string|string[] The message key or array of keys.
+        * @var string The message key. If $keysToTry has more than one element,
+        * this may change to one of the keys to try when fetching the message text.
         */
        protected $key;
 
+       /**
+        * @var string[] List of keys to try when fetching the message.
+        */
+       protected $keysToTry;
+
        /**
         * @var array List of parameters which will be substituted into the message.
         */
@@ -224,30 +230,61 @@ class Message {
         * non-empty message for.
         * @param array $params Message parameters.
         * @param Language $language Optional language of the message, defaults to $wgLang.
+        *
+        * @throws InvalidArgumentException
         */
        public function __construct( $key, $params = array(), Language $language = null ) {
                global $wgLang;
 
-               $this->key = $key;
+               if ( !is_string( $key ) && !is_array( $key ) ) {
+                       throw new InvalidArgumentException( '$key must be a string or an array' );
+               }
+
+               $this->keysToTry = (array)$key;
+
+               if ( empty( $this->keysToTry ) ) {
+                       throw new InvalidArgumentException( '$key must not be an empty list' );
+               }
+
+               $this->key = reset( $this->keysToTry );
+
                $this->parameters = array_values( $params );
                $this->language = $language ? $language : $wgLang;
        }
 
        /**
-        * Returns the message key or the first from an array of message keys.
+        * @since 1.24
+        *
+        * @return bool True if this is a multi-key message, that is, if the key provided to the
+        * constructor was a fallback list of keys to try.
+        */
+       public function isMultiKey() {
+               return count( $this->keysToTry ) > 1;
+       }
+
+       /**
+        * @since 1.24
+        *
+        * @return string[] The list of keys to try when fetching the message text,
+        * in order of preference.
+        */
+       public function getKeysToTry() {
+               return $this->keysToTry;
+       }
+
+       /**
+        * Returns the message key.
+        *
+        * If a list of multiple possible keys was supplied to the constructor, this method may
+        * return any of these keys. After the message ahs been fetched, this method will return
+        * the key that was actually used to fetch the message.
         *
         * @since 1.21
         *
         * @return string
         */
        public function getKey() {
-               if ( is_array( $this->key ) ) {
-                       // May happen if some kind of fallback is applied.
-                       // For now, just use the first key. We really need a better solution.
-                       return $this->key[0];
-               } else {
-                       return $this->key;
-               }
+               return $this->key;
        }
 
        /**
@@ -291,7 +328,7 @@ class Message {
         * @since 1.17
         *
         * @param string|string[] $key Message key or array of keys.
-        * @param mixed [$param,...] Parameters as strings.
+        * @param mixed $param,... Parameters as strings.
         *
         * @return Message
         */
@@ -308,7 +345,7 @@ class Message {
         *
         * @since 1.18
         *
-        * @param string|string[] [$keys,...] Message keys, or first argument as an array of all the
+        * @param string|string[] $keys,... Message keys, or first argument as an array of all the
         * message keys.
         *
         * @return Message
@@ -332,7 +369,7 @@ class Message {
         *
         * @since 1.17
         *
-        * @param mixed [$params,...] Parameters as strings, or a single argument that is
+        * @param mixed $params,... Parameters as strings, or a single argument that is
         * an array of strings.
         *
         * @return Message $this
@@ -355,7 +392,7 @@ class Message {
         *
         * @since 1.17
         *
-        * @param mixed [$params,...] Raw parameters as strings, or a single argument that is
+        * @param mixed $params,... Raw parameters as strings, or a single argument that is
         * an array of raw parameters.
         *
         * @return Message $this
@@ -377,7 +414,7 @@ class Message {
         *
         * @since 1.18
         *
-        * @param mixed [$param,...] Numeric parameters, or a single argument that is
+        * @param mixed $param,... Numeric parameters, or a single argument that is
         * an array of numeric parameters.
         *
         * @return Message $this
@@ -399,7 +436,7 @@ class Message {
         *
         * @since 1.22
         *
-        * @param int|int[] [$param,...] Duration parameters, or a single argument that is
+        * @param int|int[] $param,... Duration parameters, or a single argument that is
         * an array of duration parameters.
         *
         * @return Message $this
@@ -421,7 +458,7 @@ class Message {
         *
         * @since 1.22
         *
-        * @param string|string[] [$param,...] Expiry parameters, or a single argument that is
+        * @param string|string[] $param,... Expiry parameters, or a single argument that is
         * an array of expiry parameters.
         *
         * @return Message $this
@@ -443,7 +480,7 @@ class Message {
         *
         * @since 1.22
         *
-        * @param int|int[] [$param,...] Time period parameters, or a single argument that is
+        * @param int|int[] $param,... Time period parameters, or a single argument that is
         * an array of time period parameters.
         *
         * @return Message $this
@@ -465,7 +502,7 @@ class Message {
         *
         * @since 1.22
         *
-        * @param int|int[] [$param,...] Size parameters, or a single argument that is
+        * @param int|int[] $param,... Size parameters, or a single argument that is
         * an array of size parameters.
         *
         * @return Message $this
@@ -487,7 +524,7 @@ class Message {
         *
         * @since 1.22
         *
-        * @param int|int[] [$param,...] Bit rate parameters, or a single argument that is
+        * @param int|int[] $param,... Bit rate parameters, or a single argument that is
         * an array of bit rate parameters.
         *
         * @return Message $this
@@ -637,7 +674,7 @@ class Message {
                $string = $this->fetchMessage();
 
                if ( $string === false ) {
-                       $key = htmlspecialchars( is_array( $this->key ) ? $this->key[0] : $this->key );
+                       $key = htmlspecialchars( $this->key );
                        if ( $this->format === 'plain' ) {
                                return '<' . $key . '>';
                        }
@@ -997,20 +1034,18 @@ class Message {
        protected function fetchMessage() {
                if ( $this->message === null ) {
                        $cache = MessageCache::singleton();
-                       if ( is_array( $this->key ) ) {
-                               if ( !count( $this->key ) ) {
-                                       throw new MWException( "Given empty message key array." );
-                               }
-                               foreach ( $this->key as $key ) {
-                                       $message = $cache->get( $key, $this->useDatabase, $this->language );
-                                       if ( $message !== false && $message !== '' ) {
-                                               break;
-                                       }
+
+                       foreach ( $this->keysToTry as $key ) {
+                               $message = $cache->get( $key, $this->useDatabase, $this->language );
+                               if ( $message !== false && $message !== '' ) {
+                                       break;
                                }
-                               $this->message = $message;
-                       } else {
-                               $this->message = $cache->get( $this->key, $this->useDatabase, $this->language );
                        }
+
+                       // NOTE: The constructor makes sure keysToTry isn't empty,
+                       //       so we know that $key and $message are initialized.
+                       $this->key = $key;
+                       $this->message = $message;
                }
                return $this->message;
        }
@@ -1038,13 +1073,20 @@ class RawMessage extends Message {
         *
         * @see Message::__construct
         *
-        * @param string|string[] $key Message to use.
+        * @param string $text Message to use.
         * @param array $params Parameters for the message.
+        *
+        * @throws InvalidArgumentException
         */
-       public function __construct( $key, $params = array() ) {
-               parent::__construct( $key, $params );
+       public function __construct( $text, $params = array() ) {
+               if ( !is_string( $text ) ) {
+                       throw new InvalidArgumentException( '$text must be a string' );
+               }
+
+               parent::__construct( $text, $params );
+
                // The key is the message.
-               $this->message = $key;
+               $this->message = $text;
        }
 
        /**
@@ -1057,6 +1099,7 @@ class RawMessage extends Message {
                if ( $this->message === null ) {
                        $this->message = $this->key;
                }
+
                return $this->message;
        }
 
index 5725898..e3b4dbe 100644 (file)
  * constituent messages or the resource itself is changed.
  */
 class MessageBlobStore {
+       /**
+        * Get the singleton instance
+        *
+        * @since 1.24
+        * @return MessageBlobStore
+        */
+       public static function getInstance() {
+               static $instance = null;
+               if ( $instance === null ) {
+                       $instance = new self;
+               }
+
+               return $instance;
+       }
+
        /**
         * Get the message blobs for a set of modules
         *
@@ -40,19 +55,19 @@ class MessageBlobStore {
         * @param string $lang Language code
         * @return array An array mapping module names to message blobs
         */
-       public static function get( ResourceLoader $resourceLoader, $modules, $lang ) {
+       public function get( ResourceLoader $resourceLoader, $modules, $lang ) {
                wfProfileIn( __METHOD__ );
                if ( !count( $modules ) ) {
                        wfProfileOut( __METHOD__ );
                        return array();
                }
                // Try getting from the DB first
-               $blobs = self::getFromDB( $resourceLoader, array_keys( $modules ), $lang );
+               $blobs = $this->getFromDB( $resourceLoader, array_keys( $modules ), $lang );
 
                // Generate blobs for any missing modules and store them in the DB
                $missing = array_diff( array_keys( $modules ), array_keys( $blobs ) );
                foreach ( $missing as $name ) {
-                       $blob = self::insertMessageBlob( $name, $modules[$name], $lang );
+                       $blob = $this->insertMessageBlob( $name, $modules[$name], $lang );
                        if ( $blob ) {
                                $blobs[$name] = $blob;
                        }
@@ -72,8 +87,8 @@ class MessageBlobStore {
         * @param string $lang Language code
         * @return mixed Message blob or false if the module has no messages
         */
-       public static function insertMessageBlob( $name, ResourceLoaderModule $module, $lang ) {
-               $blob = self::generateMessageBlob( $module, $lang );
+       public function insertMessageBlob( $name, ResourceLoaderModule $module, $lang ) {
+               $blob = $this->generateMessageBlob( $module, $lang );
 
                if ( !$blob ) {
                        return false;
@@ -130,7 +145,7 @@ class MessageBlobStore {
         * @return string Regenerated message blob, or null if there was no blob for
         *   the given module/language pair.
         */
-       public static function updateModule( $name, ResourceLoaderModule $module, $lang ) {
+       public function updateModule( $name, ResourceLoaderModule $module, $lang ) {
                $dbw = wfGetDB( DB_MASTER );
                $row = $dbw->selectRow( 'msg_resource', 'mr_blob',
                        array( 'mr_resource' => $name, 'mr_lang' => $lang ),
@@ -142,7 +157,7 @@ class MessageBlobStore {
 
                // Save the old and new blobs for later
                $oldBlob = $row->mr_blob;
-               $newBlob = self::generateMessageBlob( $module, $lang );
+               $newBlob = $this->generateMessageBlob( $module, $lang );
 
                try {
                        $newRow = array(
@@ -197,7 +212,7 @@ class MessageBlobStore {
         *
         * @param string $key Message key
         */
-       public static function updateMessage( $key ) {
+       public function updateMessage( $key ) {
                try {
                        $dbw = wfGetDB( DB_MASTER );
 
@@ -206,7 +221,7 @@ class MessageBlobStore {
                        // in one iteration.
                        $updates = null;
                        do {
-                               $updates = self::getUpdatesForMessage( $key, $updates );
+                               $updates = $this->getUpdatesForMessage( $key, $updates );
 
                                foreach ( $updates as $k => $update ) {
                                        // Update the row on the condition that it
@@ -240,7 +255,7 @@ class MessageBlobStore {
                }
        }
 
-       public static function clear() {
+       public function clear() {
                // TODO: Give this some more thought
                try {
                        // Not using TRUNCATE, because that needs extra permissions,
@@ -260,7 +275,7 @@ class MessageBlobStore {
         * @param array $prevUpdates Updates queue to refresh or null to build a fresh update queue
         * @return array Updates queue
         */
-       private static function getUpdatesForMessage( $key, $prevUpdates = null ) {
+       private function getUpdatesForMessage( $key, $prevUpdates = null ) {
                $dbw = wfGetDB( DB_MASTER );
 
                if ( is_null( $prevUpdates ) ) {
@@ -297,7 +312,7 @@ class MessageBlobStore {
                                'resource' => $row->mr_resource,
                                'lang' => $row->mr_lang,
                                'timestamp' => $row->mr_timestamp,
-                               'newBlob' => self::reencodeBlob( $row->mr_blob, $key, $row->mr_lang )
+                               'newBlob' => $this->reencodeBlob( $row->mr_blob, $key, $row->mr_lang )
                        );
                }
 
@@ -312,7 +327,7 @@ class MessageBlobStore {
         * @param string $lang Language code
         * @return string Message blob with $key replaced with its new value
         */
-       private static function reencodeBlob( $blob, $key, $lang ) {
+       private function reencodeBlob( $blob, $key, $lang ) {
                $decoded = FormatJson::decode( $blob, true );
                $decoded[$key] = wfMessage( $key )->inLanguage( $lang )->plain();
 
@@ -329,9 +344,8 @@ class MessageBlobStore {
         * @throws MWException
         * @return array Array mapping module names to blobs
         */
-       private static function getFromDB( ResourceLoader $resourceLoader, $modules, $lang ) {
-               global $wgCacheEpoch;
-
+       private function getFromDB( ResourceLoader $resourceLoader, $modules, $lang ) {
+               $config = $resourceLoader->getConfig();
                $retval = array();
                $dbr = wfGetDB( DB_SLAVE );
                $res = $dbr->select( 'msg_resource',
@@ -348,13 +362,13 @@ class MessageBlobStore {
                        }
 
                        // Update the module's blobs if the set of messages changed or if the blob is
-                       // older than $wgCacheEpoch
+                       // older than the CacheEpoch setting
                        $keys = array_keys( FormatJson::decode( $row->mr_blob, true ) );
                        $values = array_values( array_unique( $module->getMessages() ) );
                        if ( $keys !== $values
-                               || wfTimestamp( TS_MW, $row->mr_timestamp ) <= $wgCacheEpoch
+                               || wfTimestamp( TS_MW, $row->mr_timestamp ) <= $config->get( 'CacheEpoch' )
                        ) {
-                               $retval[$row->mr_resource] = self::updateModule( $row->mr_resource, $module, $lang );
+                               $retval[$row->mr_resource] = $this->updateModule( $row->mr_resource, $module, $lang );
                        } else {
                                $retval[$row->mr_resource] = $row->mr_blob;
                        }
@@ -370,7 +384,7 @@ class MessageBlobStore {
         * @param string $lang Language code
         * @return string JSON object
         */
-       private static function generateMessageBlob( ResourceLoaderModule $module, $lang ) {
+       private function generateMessageBlob( ResourceLoaderModule $module, $lang ) {
                $messages = array();
 
                foreach ( $module->getMessages() as $key ) {
index 59f850c..bfd6011 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Module defining helper functions for detecting and dealing with mime types.
+ * Module defining helper functions for detecting and dealing with MIME types.
  *
  * 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
  */
 
 /**
- * Defines a set of well known mime types
+ * Defines a set of well known MIME types
  * This is used as a fallback to mime.types files.
- * An extensive list of well known mime types is provided by
+ * An extensive list of well known MIME types is provided by
  * the file mime.types in the includes directory.
  *
- * This list concatenated with mime.types is used to create a mime <-> ext
- * map. Each line contains a mime type followed by a space separated list of
- * extensions. If multiple extensions for a single mime type exist or if
- * multiple mime types exist for a single extension then in most cases
- * MediaWiki assumes that the first extension following the mime type is the
- * canonical extension, and the first time a mime type appears for a certain
- * extension is considered the canonical mime type.
+ * This list concatenated with mime.types is used to create a MIME <-> ext
+ * map. Each line contains a MIME type followed by a space separated list of
+ * extensions. If multiple extensions for a single MIME type exist or if
+ * multiple MIME types exist for a single extension then in most cases
+ * MediaWiki assumes that the first extension following the MIME type is the
+ * canonical extension, and the first time a MIME type appears for a certain
+ * extension is considered the canonical MIME type.
  *
  * (Note that appending $wgMimeTypeFile to the end of MM_WELL_KNOWN_MIME_TYPES
  * sucks because you can't redefine canonical types. This could be fixed by
@@ -86,9 +86,9 @@ END_STRING
 );
 
 /**
- * Defines a set of well known mime info entries
+ * Defines a set of well known MIME info entries
  * This is used as a fallback to mime.info files.
- * An extensive list of well known mime types is provided by
+ * An extensive list of well known MIME types is provided by
  * the file mime.info in the includes directory.
  */
 define( 'MM_WELL_KNOWN_MIME_INFO', <<<END_STRING
@@ -135,7 +135,7 @@ END_STRING
 );
 
 /**
- * Implements functions related to mime types such as detection and mapping to
+ * Implements functions related to MIME types such as detection and mapping to
  * file extension.
  *
  * Instances of this class are stateless, there only needs to be one global instance
@@ -143,20 +143,20 @@ END_STRING
  */
 class MimeMagic {
        /**
-        * @var array Mapping of media types to arrays of mime types.
+        * @var array Mapping of media types to arrays of MIME types.
         * This is used by findMediaType and getMediaType, respectively
         */
        protected $mMediaTypes = null;
 
-       /** @var array Map of mime type aliases
+       /** @var array Map of MIME type aliases
         */
        protected $mMimeTypeAliases = null;
 
-       /** @var array Map of mime types to file extensions (as a space separated list)
+       /** @var array Map of MIME types to file extensions (as a space separated list)
         */
        protected $mMimeToExt = null;
 
-       /** @var array Map of file extensions types to mime types (as a space separated list)
+       /** @var array Map of file extensions types to MIME types (as a space separated list)
         */
        public $mExtToMime = null;
 
@@ -164,6 +164,17 @@ class MimeMagic {
         */
        protected $mIEAnalyzer;
 
+       /** @var string Extra MIME types, set for example by media handling extensions
+        */
+       private $mExtraTypes = '';
+
+       /** @var string Extra MIME info, set for example by media handling extensions
+        */
+       private $mExtraInfo = '';
+
+       /** @var Config */
+       private $mConfig;
+
        /** @var MimeMagic The singleton instance
         */
        private static $instance = null;
@@ -171,37 +182,52 @@ class MimeMagic {
        /** Initializes the MimeMagic object. This is called by MimeMagic::singleton().
         *
         * This constructor parses the mime.types and mime.info files and build internal mappings.
+        *
+        * @todo Make this constructor private once everything uses the singleton instance
+        * @param Config $config
         */
-       function __construct() {
+       function __construct( Config $config = null ) {
+               if ( !$config ) {
+                       wfDebug( __METHOD__ . ' called with no Config instance passed to it' );
+                       $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               }
+               $this->mConfig = $config;
+
                /**
                 *   --- load mime.types ---
                 */
 
-               global $wgMimeTypeFile, $IP;
+               global $IP;
+
+               # Allow media handling extensions adding MIME-types and MIME-info
+               wfRunHooks( 'MimeMagicInit', array( $this ) );
 
                $types = MM_WELL_KNOWN_MIME_TYPES;
 
-               if ( $wgMimeTypeFile == 'includes/mime.types' ) {
-                       $wgMimeTypeFile = "$IP/$wgMimeTypeFile";
+               $mimeTypeFile = $this->mConfig->get( 'MimeTypeFile' );
+               if ( $mimeTypeFile == 'includes/mime.types' ) {
+                       $mimeTypeFile = "$IP/$mimeTypeFile";
                }
 
-               if ( $wgMimeTypeFile ) {
-                       if ( is_file( $wgMimeTypeFile ) and is_readable( $wgMimeTypeFile ) ) {
-                               wfDebug( __METHOD__ . ": loading mime types from $wgMimeTypeFile\n" );
+               if ( $mimeTypeFile ) {
+                       if ( is_file( $mimeTypeFile ) and is_readable( $mimeTypeFile ) ) {
+                               wfDebug( __METHOD__ . ": loading mime types from $mimeTypeFile\n" );
                                $types .= "\n";
-                               $types .= file_get_contents( $wgMimeTypeFile );
+                               $types .= file_get_contents( $mimeTypeFile );
                        } else {
-                               wfDebug( __METHOD__ . ": can't load mime types from $wgMimeTypeFile\n" );
+                               wfDebug( __METHOD__ . ": can't load mime types from $mimeTypeFile\n" );
                        }
                } else {
                        wfDebug( __METHOD__ . ": no mime types file defined, using build-ins only.\n" );
                }
 
+               $types .= "\n" . $this->mExtraTypes;
+
                $types = str_replace( array( "\r\n", "\n\r", "\n\n", "\r\r", "\r" ), "\n", $types );
                $types = str_replace( "\t", " ", $types );
 
                $this->mMimeToExt = array();
-               $this->mToMime = array();
+               $this->mExtToMime = array();
 
                $lines = explode( "\n", $types );
                foreach ( $lines as $s ) {
@@ -253,25 +279,27 @@ class MimeMagic {
                 *   --- load mime.info ---
                 */
 
-               global $wgMimeInfoFile;
-               if ( $wgMimeInfoFile == 'includes/mime.info' ) {
-                       $wgMimeInfoFile = "$IP/$wgMimeInfoFile";
+               $mimeInfoFile = $this->mConfig->get( 'MimeInfoFile' );
+               if ( $mimeInfoFile == 'includes/mime.info' ) {
+                       $mimeInfoFile = "$IP/$mimeInfoFile";
                }
 
                $info = MM_WELL_KNOWN_MIME_INFO;
 
-               if ( $wgMimeInfoFile ) {
-                       if ( is_file( $wgMimeInfoFile ) and is_readable( $wgMimeInfoFile ) ) {
-                               wfDebug( __METHOD__ . ": loading mime info from $wgMimeInfoFile\n" );
+               if ( $mimeInfoFile ) {
+                       if ( is_file( $mimeInfoFile ) and is_readable( $mimeInfoFile ) ) {
+                               wfDebug( __METHOD__ . ": loading mime info from $mimeInfoFile\n" );
                                $info .= "\n";
-                               $info .= file_get_contents( $wgMimeInfoFile );
+                               $info .= file_get_contents( $mimeInfoFile );
                        } else {
-                               wfDebug( __METHOD__ . ": can't load mime info from $wgMimeInfoFile\n" );
+                               wfDebug( __METHOD__ . ": can't load mime info from $mimeInfoFile\n" );
                        }
                } else {
                        wfDebug( __METHOD__ . ": no mime info file defined, using build-ins only.\n" );
                }
 
+               $info .= "\n" . $this->mExtraInfo;
+
                $info = str_replace( array( "\r\n", "\n\r", "\n\n", "\r\r", "\r" ), "\n", $info );
                $info = str_replace( "\t", " ", $info );
 
@@ -337,15 +365,37 @@ class MimeMagic {
         */
        public static function singleton() {
                if ( self::$instance === null ) {
-                       self::$instance = new MimeMagic;
+                       self::$instance = new MimeMagic(
+                               ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                       );
                }
                return self::$instance;
        }
 
        /**
-        * Returns a list of file extensions for a given mime type as a space
-        * separated string or null if the mime type was unrecognized. Resolves
-        * mime type aliases.
+        * Adds to the list mapping MIME to file extensions.
+        * As an extension author, you are encouraged to submit patches to
+        * MediaWiki's core to add new MIME types to mime.types.
+        * @param string $types
+        */
+       public function addExtraTypes( $types ) {
+               $this->mExtraTypes .= "\n" . $types;
+       }
+
+       /**
+        * Adds to the list mapping MIME to media type.
+        * As an extension author, you are encouraged to submit patches to
+        * MediaWiki's core to add new MIME info to mime.info.
+        * @param string $info
+        */
+       public function addExtraInfo( $info ) {
+               $this->mExtraInfo .= "\n" . $info;
+       }
+
+       /**
+        * Returns a list of file extensions for a given MIME type as a space
+        * separated string or null if the MIME type was unrecognized. Resolves
+        * MIME type aliases.
         *
         * @param string $mime
         * @return string|null
@@ -358,7 +408,7 @@ class MimeMagic {
                        return $this->mMimeToExt[$mime];
                }
 
-               // Resolve the mime type to the canonical type
+               // Resolve the MIME type to the canonical type
                if ( isset( $this->mMimeTypeAliases[$mime] ) ) {
                        $mime = $this->mMimeTypeAliases[$mime];
                        if ( isset( $this->mMimeToExt[$mime] ) ) {
@@ -370,7 +420,7 @@ class MimeMagic {
        }
 
        /**
-        * Returns a list of mime types for a given file extension as a space
+        * Returns a list of MIME types for a given file extension as a space
         * separated string or null if the extension was unrecognized.
         *
         * @param string $ext
@@ -384,7 +434,7 @@ class MimeMagic {
        }
 
        /**
-        * Returns a single mime type for a given file extension or null if unknown.
+        * Returns a single MIME type for a given file extension or null if unknown.
         * This is always the first type from the list returned by getTypesForExtension($ext).
         *
         * @param string $ext
@@ -404,9 +454,9 @@ class MimeMagic {
        }
 
        /**
-        * Tests if the extension matches the given mime type. Returns true if a
-        * match was found, null if the mime type is unknown, and false if the
-        * mime type is known but no matches where found.
+        * Tests if the extension matches the given MIME type. Returns true if a
+        * match was found, null if the MIME type is unknown, and false if the
+        * MIME type is known but no matches where found.
         *
         * @param string $extension
         * @param string $mime
@@ -416,7 +466,7 @@ class MimeMagic {
                $ext = $this->getExtensionsForType( $mime );
 
                if ( !$ext ) {
-                       return null; // Unknown mime type
+                       return null; // Unknown MIME type
                }
 
                $ext = explode( ' ', $ext );
@@ -426,7 +476,7 @@ class MimeMagic {
        }
 
        /**
-        * Returns true if the mime type is known to represent an image format
+        * Returns true if the MIME type is known to represent an image format
         * supported by the PHP GD library.
         *
         * @param string $mime
@@ -455,7 +505,7 @@ class MimeMagic {
         * invalid uploads; if we can't identify the type we won't
         * be able to say if it's invalid.
         *
-        * @todo Be more accurate when using fancy mime detector plugins;
+        * @todo Be more accurate when using fancy MIME detector plugins;
         *       right now this is the bare minimum getimagesize() list.
         * @param string $extension
         * @return bool
@@ -480,15 +530,15 @@ class MimeMagic {
        }
 
        /**
-        * Improves a mime type using the file extension. Some file formats are very generic,
-        * so their mime type is not very meaningful. A more useful mime type can be derived
+        * Improves a MIME type using the file extension. Some file formats are very generic,
+        * so their MIME type is not very meaningful. A more useful MIME type can be derived
         * by looking at the file extension. Typically, this method would be called on the
         * result of guessMimeType().
         *
-        * @param string $mime The mime type, typically guessed from a file's content.
+        * @param string $mime The MIME type, typically guessed from a file's content.
         * @param string $ext The file extension, as taken from the file name
         *
-        * @return string The mime type
+        * @return string The MIME type
         */
        public function improveTypeFromExtension( $mime, $ext ) {
                if ( $mime === 'unknown/unknown' ) {
@@ -503,7 +553,7 @@ class MimeMagic {
                } elseif ( $mime === 'application/x-opc+zip' ) {
                        if ( $this->isMatchingExtension( $ext, $mime ) ) {
                                // A known file extension for an OPC file,
-                               // find the proper mime type for that file extension
+                               // find the proper MIME type for that file extension
                                $mime = $this->guessTypesForExtension( $ext );
                        } else {
                                wfDebug( __METHOD__ . ": refusing to guess better type for $mime file, " .
@@ -518,6 +568,9 @@ class MimeMagic {
                        $mime = $this->guessTypesForExtension( $ext );
                }
 
+               # Media handling extensions can improve the MIME detected
+               wfRunHooks( 'MimeMagicImproveFromExtension', array( $this, $ext, &$mime ) );
+
                if ( isset( $this->mMimeTypeAliases[$mime] ) ) {
                        $mime = $this->mMimeTypeAliases[$mime];
                }
@@ -527,18 +580,18 @@ class MimeMagic {
        }
 
        /**
-        * Mime type detection. This uses detectMimeType to detect the mime type
+        * MIME type detection. This uses detectMimeType to detect the MIME type
         * of the file, but applies additional checks to determine some well known
-        * file formats that may be missed or misinterpreted by the default mime
+        * file formats that may be missed or misinterpreted by the default MIME
         * detection (namely XML based formats like XHTML or SVG, as well as ZIP
         * based formats like OPC/ODF files).
         *
         * @param string $file The file to check
         * @param string|bool $ext The file extension, or true (default) to extract it from the filename.
         *   Set it to false to ignore the extension. DEPRECATED! Set to false, use
-        *   improveTypeFromExtension($mime, $ext) later to improve mime type.
+        *   improveTypeFromExtension($mime, $ext) later to improve MIME type.
         *
-        * @return string The mime type of $file
+        * @return string The MIME type of $file
         */
        public function guessMimeType( $file, $ext = true ) {
                if ( $ext ) { // TODO: make $ext default to false. Or better, remove it.
@@ -562,7 +615,7 @@ class MimeMagic {
        }
 
        /**
-        * Guess the mime type from the file contents.
+        * Guess the MIME type from the file contents.
         *
         * @param string $file
         * @param mixed $ext
@@ -673,9 +726,9 @@ class MimeMagic {
                 */
                $xml = new XmlTypeCheck( $file );
                if ( $xml->wellFormed ) {
-                       global $wgXMLMimeTypes;
-                       if ( isset( $wgXMLMimeTypes[$xml->getRootElement()] ) ) {
-                               return $wgXMLMimeTypes[$xml->getRootElement()];
+                       $xmlMimeTypes = $this->mConfig->get( 'XMLMimeTypes' );
+                       if ( isset( $xmlMimeTypes[$xml->getRootElement()] ) ) {
+                               return $xmlMimeTypes[$xml->getRootElement()];
                        } else {
                                return 'application/xml';
                        }
@@ -744,7 +797,17 @@ class MimeMagic {
                        return 'image/vnd.djvu';
                }
 
-               return false;
+               # Media handling extensions can guess the MIME by content
+               # It's intentionally here so that if core is wrong about a type (false positive),
+               # people will hopefully nag and submit patches :)
+               $mime = false;
+               # Some strings by reference for performance - assuming well-behaved hooks
+               wfRunHooks(
+                       'MimeMagicGuessFromContent',
+                       array( $this, &$head, &$tail, $file, &$mime )
+               );
+
+               return $mime;
        }
 
        /**
@@ -756,7 +819,7 @@ class MimeMagic {
         * @param string|null $tail The tail of the file
         * @param string|bool $ext The file extension, or true to extract it from the filename.
         *   Set it to false (default) to ignore the extension. DEPRECATED! Set to false,
-        *   use improveTypeFromExtension($mime, $ext) later to improve mime type.
+        *   use improveTypeFromExtension($mime, $ext) later to improve MIME type.
         *
         * @return string
         */
@@ -799,7 +862,7 @@ class MimeMagic {
                        # TODO: remove the block below, as soon as improveTypeFromExtension is used everywhere
                        if ( $ext !== true && $ext !== false ) {
                                /** This is the mode used by getPropsFromPath
-                                * These mime's are stored in the database, where we don't really want
+                                * These MIME's are stored in the database, where we don't really want
                                 * x-opc+zip, because we use it only for internal purposes
                                 */
                                if ( $this->isMatchingExtension( $ext, $mime ) ) {
@@ -848,49 +911,37 @@ class MimeMagic {
        }
 
        /**
-        * Internal mime type detection. Detection is done using an external
+        * Internal MIME type detection. Detection is done using an external
         * program, if $wgMimeDetectorCommand is set. Otherwise, the fileinfo
-        * extension and mime_content_type are tried (in this order), if they
-        * are available. If the detections fails and $ext is not false, the mime
-        * type is guessed from the file extension, using guessTypesForExtension.
+        * extension is tried if it is available. If detection fails and $ext
+        * is not false, the MIME type is guessed from the file extension,
+        * using guessTypesForExtension.
         *
-        * If the mime type is still unknown, getimagesize is used to detect the
-        * mime type if the file is an image. If no mime type can be determined,
+        * If the MIME type is still unknown, getimagesize is used to detect the
+        * MIME type if the file is an image. If no MIME type can be determined,
         * this function returns 'unknown/unknown'.
         *
         * @param string $file The file to check
         * @param string|bool $ext The file extension, or true (default) to extract it from the filename.
         *   Set it to false to ignore the extension. DEPRECATED! Set to false, use
-        *   improveTypeFromExtension($mime, $ext) later to improve mime type.
+        *   improveTypeFromExtension($mime, $ext) later to improve MIME type.
         *
-        * @return string The mime type of $file
+        * @return string The MIME type of $file
         */
        private function detectMimeType( $file, $ext = true ) {
-               global $wgMimeDetectorCommand;
-
                /** @todo Make $ext default to false. Or better, remove it. */
                if ( $ext ) {
                        wfDebug( __METHOD__ . ": WARNING: use of the \$ext parameter is deprecated. "
                                . "Use improveTypeFromExtension(\$mime, \$ext) instead.\n" );
                }
 
+               $mimeDetectorCommand = $this->mConfig->get( 'MimeDetectorCommand' );
                $m = null;
-               if ( $wgMimeDetectorCommand ) {
+               if ( $mimeDetectorCommand ) {
                        $args = wfEscapeShellArg( $file );
-                       $m = wfShellExec( "$wgMimeDetectorCommand $args" );
+                       $m = wfShellExec( "$mimeDetectorCommand $args" );
                } elseif ( function_exists( "finfo_open" ) && function_exists( "finfo_file" ) ) {
-
-                       # This required the fileinfo extension by PECL,
-                       # see http://pecl.php.net/package/fileinfo
-                       # This must be compiled into PHP
-                       #
-                       # finfo is the official replacement for the deprecated
-                       # mime_content_type function, see below.
-                       #
-                       # If you may need to load the fileinfo extension at runtime, set
-                       # $wgLoadFileinfoExtension in LocalSettings.php
-
-                       $mime_magic_resource = finfo_open( FILEINFO_MIME ); /* return mime type ala mimetype extension */
+                       $mime_magic_resource = finfo_open( FILEINFO_MIME );
 
                        if ( $mime_magic_resource ) {
                                $m = finfo_file( $mime_magic_resource, $file );
@@ -898,21 +949,6 @@ class MimeMagic {
                        } else {
                                wfDebug( __METHOD__ . ": finfo_open failed on " . FILEINFO_MIME . "!\n" );
                        }
-               } elseif ( function_exists( "mime_content_type" ) ) {
-
-                       # NOTE: this function is available since PHP 4.3.0, but only if
-                       # PHP was compiled with --with-mime-magic or, before 4.3.2, with
-                       # --enable-mime-magic.
-                       #
-                       # On Windows, you must set mime_magic.magicfile in php.ini to point
-                       # to the mime.magic file bundled with PHP; sometimes, this may even
-                       # be needed under *nix.
-                       #
-                       # Also note that this has been DEPRECATED in favor of the fileinfo
-                       # extension by PECL, see above.
-                       # See http://www.php.net/manual/en/ref.mime-magic.php for details.
-
-                       $m = mime_content_type( $file );
                } else {
                        wfDebug( __METHOD__ . ": no magic mime detector found!\n" );
                }
@@ -955,18 +991,18 @@ class MimeMagic {
        }
 
        /**
-        * Determine the media type code for a file, using its mime type, name and
+        * Determine the media type code for a file, using its MIME type, name and
         * possibly its contents.
         *
-        * This function relies on the findMediaType(), mapping extensions and mime
+        * This function relies on the findMediaType(), mapping extensions and MIME
         * types to media types.
         *
         * @todo analyse file if need be
         * @todo look at multiple extension, separately and together.
         *
         * @param string $path Full path to the image file, in case we have to look at the contents
-        *        (if null, only the mime type is used to determine the media type code).
-        * @param string $mime Mime type. If null it will be guessed using guessMimeType.
+        *        (if null, only the MIME type is used to determine the media type code).
+        * @param string $mime MIME type. If null it will be guessed using guessMimeType.
         *
         * @return string A value to be used with the MEDIATYPE_xxx constants.
         */
@@ -975,7 +1011,7 @@ class MimeMagic {
                        return MEDIATYPE_UNKNOWN;
                }
 
-               // If mime type is unknown, guess it
+               // If MIME type is unknown, guess it
                if ( !$mime ) {
                        $mime = $this->guessMimeType( $path, false );
                }
@@ -1008,7 +1044,7 @@ class MimeMagic {
                        }
                }
 
-               // Check for entry for full mime type
+               // Check for entry for full MIME type
                if ( $mime ) {
                        $type = $this->findMediaType( $mime );
                        if ( $type !== MEDIATYPE_UNKNOWN ) {
@@ -1028,7 +1064,7 @@ class MimeMagic {
                        }
                }
 
-               // Check major mime type
+               // Check major MIME type
                if ( $mime ) {
                        $i = strpos( $mime, '/' );
                        if ( $i !== false ) {
@@ -1048,9 +1084,9 @@ class MimeMagic {
        }
 
        /**
-        * Returns a media code matching the given mime type or file extension.
+        * Returns a media code matching the given MIME type or file extension.
         * File extensions are represented by a string starting with a dot (.) to
-        * distinguish them from mime types.
+        * distinguish them from MIME types.
         *
         * This function relies on the mapping defined by $this->mMediaTypes
         * @access private
@@ -1059,7 +1095,7 @@ class MimeMagic {
         */
        function findMediaType( $extMime ) {
                if ( strpos( $extMime, '.' ) === 0 ) {
-                       // If it's an extension, look up the mime types
+                       // If it's an extension, look up the MIME types
                        $m = $this->getTypesForExtension( substr( $extMime, 1 ) );
                        if ( !$m ) {
                                return MEDIATYPE_UNKNOWN;
@@ -1067,7 +1103,7 @@ class MimeMagic {
 
                        $m = explode( ' ', $m );
                } else {
-                       // Normalize mime type
+                       // Normalize MIME type
                        if ( isset( $this->mMimeTypeAliases[$extMime] ) ) {
                                $extMime = $this->mMimeTypeAliases[$extMime];
                        }
diff --git a/includes/Namespace.php b/includes/Namespace.php
deleted file mode 100644 (file)
index 392f558..0000000
+++ /dev/null
@@ -1,496 +0,0 @@
-<?php
-/**
- * Provide things related to namespaces.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * This is a utility class with only static functions
- * for dealing with namespaces that encodes all the
- * "magic" behaviors of them based on index.  The textual
- * names of the namespaces are handled by Language.php.
- *
- * These are synonyms for the names given in the language file
- * Users and translators should not change them
- *
- */
-class MWNamespace {
-
-       /**
-        * These namespaces should always be first-letter capitalized, now and
-        * forevermore. Historically, they could've probably been lowercased too,
-        * but some things are just too ingrained now. :)
-        */
-       private static $alwaysCapitalizedNamespaces = array( NS_SPECIAL, NS_USER, NS_MEDIAWIKI );
-
-       /**
-        * Throw an exception when trying to get the subject or talk page
-        * for a given namespace where it does not make sense.
-        * Special namespaces are defined in includes/Defines.php and have
-        * a value below 0 (ex: NS_SPECIAL = -1 , NS_MEDIA = -2)
-        *
-        * @param int $index
-        * @param string $method
-        *
-        * @throws MWException
-        * @return bool
-        */
-       private static function isMethodValidFor( $index, $method ) {
-               if ( $index < NS_MAIN ) {
-                       throw new MWException( "$method does not make any sense for given namespace $index" );
-               }
-               return true;
-       }
-
-       /**
-        * Can pages in the given namespace be moved?
-        *
-        * @param int $index Namespace index
-        * @return bool
-        */
-       public static function isMovable( $index ) {
-               global $wgAllowImageMoving;
-
-               $result = !( $index < NS_MAIN || ( $index == NS_FILE && !$wgAllowImageMoving ) );
-
-               /**
-                * @since 1.20
-                */
-               wfRunHooks( 'NamespaceIsMovable', array( $index, &$result ) );
-
-               return $result;
-       }
-
-       /**
-        * Is the given namespace is a subject (non-talk) namespace?
-        *
-        * @param int $index Namespace index
-        * @return bool
-        * @since 1.19
-        */
-       public static function isSubject( $index ) {
-               return !self::isTalk( $index );
-       }
-
-       /**
-        * Is the given namespace a talk namespace?
-        *
-        * @param int $index Namespace index
-        * @return bool
-        */
-       public static function isTalk( $index ) {
-               return $index > NS_MAIN
-                       && $index % 2;
-       }
-
-       /**
-        * Get the talk namespace index for a given namespace
-        *
-        * @param int $index Namespace index
-        * @return int
-        */
-       public static function getTalk( $index ) {
-               self::isMethodValidFor( $index, __METHOD__ );
-               return self::isTalk( $index )
-                       ? $index
-                       : $index + 1;
-       }
-
-       /**
-        * Get the subject namespace index for a given namespace
-        * Special namespaces (NS_MEDIA, NS_SPECIAL) are always the subject.
-        *
-        * @param int $index Namespace index
-        * @return int
-        */
-       public static function getSubject( $index ) {
-               # Handle special namespaces
-               if ( $index < NS_MAIN ) {
-                       return $index;
-               }
-
-               return self::isTalk( $index )
-                       ? $index - 1
-                       : $index;
-       }
-
-       /**
-        * Get the associated namespace.
-        * For talk namespaces, returns the subject (non-talk) namespace
-        * For subject (non-talk) namespaces, returns the talk namespace
-        *
-        * @param int $index Namespace index
-        * @return int|null If no associated namespace could be found
-        */
-       public static function getAssociated( $index ) {
-               self::isMethodValidFor( $index, __METHOD__ );
-
-               if ( self::isSubject( $index ) ) {
-                       return self::getTalk( $index );
-               } elseif ( self::isTalk( $index ) ) {
-                       return self::getSubject( $index );
-               } else {
-                       return null;
-               }
-       }
-
-       /**
-        * Returns whether the specified namespace exists
-        *
-        * @param int $index
-        *
-        * @return bool
-        * @since 1.19
-        */
-       public static function exists( $index ) {
-               $nslist = self::getCanonicalNamespaces();
-               return isset( $nslist[$index] );
-       }
-
-       /**
-        * Returns whether the specified namespaces are the same namespace
-        *
-        * @note It's possible that in the future we may start using something
-        * other than just namespace indexes. Under that circumstance making use
-        * of this function rather than directly doing comparison will make
-        * sure that code will not potentially break.
-        *
-        * @param int $ns1 The first namespace index
-        * @param int $ns2 The second namespace index
-        *
-        * @return bool
-        * @since 1.19
-        */
-       public static function equals( $ns1, $ns2 ) {
-               return $ns1 == $ns2;
-       }
-
-       /**
-        * Returns whether the specified namespaces share the same subject.
-        * eg: NS_USER and NS_USER wil return true, as well
-        *     NS_USER and NS_USER_TALK will return true.
-        *
-        * @param int $ns1 The first namespace index
-        * @param int $ns2 The second namespace index
-        *
-        * @return bool
-        * @since 1.19
-        */
-       public static function subjectEquals( $ns1, $ns2 ) {
-               return self::getSubject( $ns1 ) == self::getSubject( $ns2 );
-       }
-
-       /**
-        * Returns array of all defined namespaces with their canonical
-        * (English) names.
-        *
-        * @param bool $rebuild Rebuild namespace list (default = false). Used for testing.
-        *
-        * @return array
-        * @since 1.17
-        */
-       public static function getCanonicalNamespaces( $rebuild = false ) {
-               static $namespaces = null;
-               if ( $namespaces === null || $rebuild ) {
-                       global $wgExtraNamespaces, $wgCanonicalNamespaceNames;
-                       $namespaces = array( NS_MAIN => '' ) + $wgCanonicalNamespaceNames;
-                       if ( is_array( $wgExtraNamespaces ) ) {
-                               $namespaces += $wgExtraNamespaces;
-                       }
-                       wfRunHooks( 'CanonicalNamespaces', array( &$namespaces ) );
-               }
-               return $namespaces;
-       }
-
-       /**
-        * Returns the canonical (English) name for a given index
-        *
-        * @param int $index Namespace index
-        * @return string|bool If no canonical definition.
-        */
-       public static function getCanonicalName( $index ) {
-               $nslist = self::getCanonicalNamespaces();
-               if ( isset( $nslist[$index] ) ) {
-                       return $nslist[$index];
-               } else {
-                       return false;
-               }
-       }
-
-       /**
-        * Returns the index for a given canonical name, or NULL
-        * The input *must* be converted to lower case first
-        *
-        * @param string $name Namespace name
-        * @return int
-        */
-       public static function getCanonicalIndex( $name ) {
-               static $xNamespaces = false;
-               if ( $xNamespaces === false ) {
-                       $xNamespaces = array();
-                       foreach ( self::getCanonicalNamespaces() as $i => $text ) {
-                               $xNamespaces[strtolower( $text )] = $i;
-                       }
-               }
-               if ( array_key_exists( $name, $xNamespaces ) ) {
-                       return $xNamespaces[$name];
-               } else {
-                       return null;
-               }
-       }
-
-       /**
-        * Returns an array of the namespaces (by integer id) that exist on the
-        * wiki. Used primarily by the api in help documentation.
-        * @return array
-        */
-       public static function getValidNamespaces() {
-               static $mValidNamespaces = null;
-
-               if ( is_null( $mValidNamespaces ) ) {
-                       foreach ( array_keys( self::getCanonicalNamespaces() ) as $ns ) {
-                               if ( $ns >= 0 ) {
-                                       $mValidNamespaces[] = $ns;
-                               }
-                       }
-               }
-
-               return $mValidNamespaces;
-       }
-
-       /**
-        * Can this namespace ever have a talk namespace?
-        *
-        * @param int $index Namespace index
-        * @return bool
-        */
-       public static function canTalk( $index ) {
-               return $index >= NS_MAIN;
-       }
-
-       /**
-        * Does this namespace contain content, for the purposes of calculating
-        * statistics, etc?
-        *
-        * @param int $index Index to check
-        * @return bool
-        */
-       public static function isContent( $index ) {
-               global $wgContentNamespaces;
-               return $index == NS_MAIN || in_array( $index, $wgContentNamespaces );
-       }
-
-       /**
-        * Can pages in a namespace be watched?
-        *
-        * @param int $index
-        * @return bool
-        */
-       public static function isWatchable( $index ) {
-               return $index >= NS_MAIN;
-       }
-
-       /**
-        * Does the namespace allow subpages?
-        *
-        * @param int $index Index to check
-        * @return bool
-        */
-       public static function hasSubpages( $index ) {
-               global $wgNamespacesWithSubpages;
-               return !empty( $wgNamespacesWithSubpages[$index] );
-       }
-
-       /**
-        * Get a list of all namespace indices which are considered to contain content
-        * @return array Array of namespace indices
-        */
-       public static function getContentNamespaces() {
-               global $wgContentNamespaces;
-               if ( !is_array( $wgContentNamespaces ) || $wgContentNamespaces === array() ) {
-                       return array( NS_MAIN );
-               } elseif ( !in_array( NS_MAIN, $wgContentNamespaces ) ) {
-                       // always force NS_MAIN to be part of array (to match the algorithm used by isContent)
-                       return array_merge( array( NS_MAIN ), $wgContentNamespaces );
-               } else {
-                       return $wgContentNamespaces;
-               }
-       }
-
-       /**
-        * List all namespace indices which are considered subject, aka not a talk
-        * or special namespace. See also MWNamespace::isSubject
-        *
-        * @return array Array of namespace indices
-        */
-       public static function getSubjectNamespaces() {
-               return array_filter(
-                       MWNamespace::getValidNamespaces(),
-                       'MWNamespace::isSubject'
-               );
-       }
-
-       /**
-        * List all namespace indices which are considered talks, aka not a subject
-        * or special namespace. See also MWNamespace::isTalk
-        *
-        * @return array Array of namespace indices
-        */
-       public static function getTalkNamespaces() {
-               return array_filter(
-                       MWNamespace::getValidNamespaces(),
-                       'MWNamespace::isTalk'
-               );
-       }
-
-       /**
-        * Is the namespace first-letter capitalized?
-        *
-        * @param int $index Index to check
-        * @return bool
-        */
-       public static function isCapitalized( $index ) {
-               global $wgCapitalLinks, $wgCapitalLinkOverrides;
-               // Turn NS_MEDIA into NS_FILE
-               $index = $index === NS_MEDIA ? NS_FILE : $index;
-
-               // Make sure to get the subject of our namespace
-               $index = self::getSubject( $index );
-
-               // Some namespaces are special and should always be upper case
-               if ( in_array( $index, self::$alwaysCapitalizedNamespaces ) ) {
-                       return true;
-               }
-               if ( isset( $wgCapitalLinkOverrides[$index] ) ) {
-                       // $wgCapitalLinkOverrides is explicitly set
-                       return $wgCapitalLinkOverrides[$index];
-               }
-               // Default to the global setting
-               return $wgCapitalLinks;
-       }
-
-       /**
-        * Does the namespace (potentially) have different aliases for different
-        * genders. Not all languages make a distinction here.
-        *
-        * @since 1.18
-        * @param int $index Index to check
-        * @return bool
-        */
-       public static function hasGenderDistinction( $index ) {
-               return $index == NS_USER || $index == NS_USER_TALK;
-       }
-
-       /**
-        * It is not possible to use pages from this namespace as template?
-        *
-        * @since 1.20
-        * @param int $index Index to check
-        * @return bool
-        */
-       public static function isNonincludable( $index ) {
-               global $wgNonincludableNamespaces;
-               return $wgNonincludableNamespaces && in_array( $index, $wgNonincludableNamespaces );
-       }
-
-       /**
-        * Get the default content model for a namespace
-        * This does not mean that all pages in that namespace have the model
-        *
-        * @since 1.21
-        * @param int $index Index to check
-        * @return null|string Default model name for the given namespace, if set
-        */
-       public static function getNamespaceContentModel( $index ) {
-               global $wgNamespaceContentModels;
-               return isset( $wgNamespaceContentModels[$index] )
-                       ? $wgNamespaceContentModels[$index]
-                       : null;
-       }
-
-       /**
-        * Determine which restriction levels it makes sense to use in a namespace,
-        * optionally filtered by a user's rights.
-        *
-        * @since 1.23
-        * @param int $index Index to check
-        * @param User $user User to check
-        * @return array
-        */
-       public static function getRestrictionLevels( $index, User $user = null ) {
-               global $wgNamespaceProtection, $wgRestrictionLevels;
-
-               if ( !isset( $wgNamespaceProtection[$index] ) ) {
-                       // All levels are valid if there's no namespace restriction.
-                       // But still filter by user, if necessary
-                       $levels = $wgRestrictionLevels;
-                       if ( $user ) {
-                               $levels = array_values( array_filter( $levels, function ( $level ) use ( $user ) {
-                                       $right = $level;
-                                       if ( $right == 'sysop' ) {
-                                               $right = 'editprotected'; // BC
-                                       }
-                                       if ( $right == 'autoconfirmed' ) {
-                                               $right = 'editsemiprotected'; // BC
-                                       }
-                                       return ( $right == '' || $user->isAllowed( $right ) );
-                               } ) );
-                       }
-                       return $levels;
-               }
-
-               // First, get the list of groups that can edit this namespace.
-               $namespaceGroups = array();
-               $combine = 'array_merge';
-               foreach ( (array)$wgNamespaceProtection[$index] as $right ) {
-                       if ( $right == 'sysop' ) {
-                               $right = 'editprotected'; // BC
-                       }
-                       if ( $right == 'autoconfirmed' ) {
-                               $right = 'editsemiprotected'; // BC
-                       }
-                       if ( $right != '' ) {
-                               $namespaceGroups = call_user_func( $combine, $namespaceGroups,
-                                       User::getGroupsWithPermission( $right ) );
-                               $combine = 'array_intersect';
-                       }
-               }
-
-               // Now, keep only those restriction levels where there is at least one
-               // group that can edit the namespace but would be blocked by the
-               // restriction.
-               $usableLevels = array( '' );
-               foreach ( $wgRestrictionLevels as $level ) {
-                       $right = $level;
-                       if ( $right == 'sysop' ) {
-                               $right = 'editprotected'; // BC
-                       }
-                       if ( $right == 'autoconfirmed' ) {
-                               $right = 'editsemiprotected'; // BC
-                       }
-                       if ( $right != '' && ( !$user || $user->isAllowed( $right ) ) &&
-                               array_diff( $namespaceGroups, User::getGroupsWithPermission( $right ) )
-                       ) {
-                               $usableLevels[] = $level;
-                       }
-               }
-
-               return $usableLevels;
-       }
-}
index 8967938..22a6012 100644 (file)
@@ -100,7 +100,7 @@ class OutputPage extends ContextSource {
        protected $mStatusCode;
 
        /**
-        * @ var string mLastModified and mEtag are used for sending cache control.
+        * @var string Variable mLastModified and mEtag are used for sending cache control.
         *   The whole caching system should probably be moved into its own class.
         */
        protected $mLastModified = '';
@@ -311,6 +311,7 @@ class OutputPage extends ContextSource {
         * Constructor for OutputPage. This should not be called directly.
         * Instead a new RequestContext should be created and it will implicitly create
         * a OutputPage tied to that context.
+        * @param IContextSource|null $context
         */
        function __construct( IContextSource $context = null ) {
                if ( $context === null ) {
@@ -355,8 +356,8 @@ class OutputPage extends ContextSource {
         * Add a new "<meta>" tag
         * To add an http-equiv meta tag, precede the name with "http:"
         *
-        * @param string $name tag name
-        * @param string $val tag value
+        * @param string $name Tag name
+        * @param string $val Tag value
         */
        function addMeta( $name, $val ) {
                array_push( $this->mMetatags, array( $name, $val ) );
@@ -367,20 +368,20 @@ class OutputPage extends ContextSource {
         *
         * Note: use setCanonicalUrl() for rel=canonical.
         *
-        * @param array $linkarr associative array of attributes.
+        * @param array $linkarr Associative array of attributes.
         */
-       function addLink( $linkarr ) {
+       function addLink( array $linkarr ) {
                array_push( $this->mLinktags, $linkarr );
        }
 
        /**
         * Add a new \<link\> with "rel" attribute set to "meta"
         *
-        * @param array $linkarr associative array mapping attribute names to their
+        * @param array $linkarr Associative array mapping attribute names to their
         *                 values, both keys and values will be escaped, and the
         *                 "rel" attribute will be automatically added
         */
-       function addMetadataLink( $linkarr ) {
+       function addMetadataLink( array $linkarr ) {
                $linkarr['rel'] = $this->getMetadataAttribute();
                $this->addLink( $linkarr );
        }
@@ -388,6 +389,7 @@ class OutputPage extends ContextSource {
        /**
         * Set the URL to be used for the <link rel=canonical>. This should be used
         * in preference to addLink(), to avoid duplicate link tags.
+        * @param string $url
         */
        function setCanonicalUrl( $url ) {
                $this->mCanonicalUrl = $url;
@@ -412,7 +414,7 @@ class OutputPage extends ContextSource {
        /**
         * Add raw HTML to the list of scripts (including \<script\> tag, etc.)
         *
-        * @param string $script raw HTML
+        * @param string $script Raw HTML
         */
        function addScript( $script ) {
                $this->mScripts .= $script . "\n";
@@ -421,7 +423,7 @@ class OutputPage extends ContextSource {
        /**
         * Register and add a stylesheet from an extension directory.
         *
-        * @param string $url path to sheet.  Provide either a full url (beginning
+        * @param string $url Path to sheet.  Provide either a full url (beginning
         *             with 'http', etc) or a relative path from the document root
         *             (beginning with '/').  Otherwise it behaves identically to
         *             addStyle() and draws from the /skins folder.
@@ -442,20 +444,19 @@ class OutputPage extends ContextSource {
        /**
         * Add a JavaScript file out of skins/common, or a given relative path.
         *
-        * @param string $file filename in skins/common or complete on-server path
+        * @param string $file Filename in skins/common or complete on-server path
         *              (/foo/bar.js)
-        * @param string $version style version of the file. Defaults to $wgStyleVersion
+        * @param string $version Style version of the file. Defaults to $wgStyleVersion
         */
        public function addScriptFile( $file, $version = null ) {
-               global $wgStylePath, $wgStyleVersion;
                // See if $file parameter is an absolute URL or begins with a slash
                if ( substr( $file, 0, 1 ) == '/' || preg_match( '#^[a-z]*://#i', $file ) ) {
                        $path = $file;
                } else {
-                       $path = "{$wgStylePath}/common/{$file}";
+                       $path = $this->getConfig()->get( 'StylePath' ) . "/common/{$file}";
                }
                if ( is_null( $version ) ) {
-                       $version = $wgStyleVersion;
+                       $version = $this->getConfig()->get( 'StyleVersion' );
                }
                $this->addScript( Html::linkedScript( wfAppendQuery( $path, $version ) ) );
        }
@@ -484,11 +485,11 @@ class OutputPage extends ContextSource {
         * Filter an array of modules to remove insufficiently trustworthy members, and modules
         * which are no longer registered (eg a page is cached before an extension is disabled)
         * @param array $modules
-        * @param string|null $position if not null, only return modules with this position
+        * @param string|null $position If not null, only return modules with this position
         * @param string $type
         * @return array
         */
-       protected function filterModules( $modules, $position = null,
+       protected function filterModules( array $modules, $position = null,
                $type = ResourceLoaderModule::TYPE_COMBINED
        ) {
                $resourceLoader = $this->getResourceLoader();
@@ -647,8 +648,8 @@ class OutputPage extends ContextSource {
        /**
         * Add or replace an header item to the output
         *
-        * @param string $name item name
-        * @param string $value raw HTML
+        * @param string $name Item name
+        * @param string $value Raw HTML
         */
        public function addHeadItem( $name, $value ) {
                $this->mHeadItems[$name] = $value;
@@ -667,7 +668,7 @@ class OutputPage extends ContextSource {
        /**
         * Set the value of the ETag HTTP header, only used if $wgUseETag is true
         *
-        * @param string $tag value of "ETag" header
+        * @param string $tag Value of "ETag" header
         */
        function setETag( $tag ) {
                $this->mETag = $tag;
@@ -731,13 +732,12 @@ class OutputPage extends ContextSource {
         * @return bool True if cache-ok headers was sent.
         */
        public function checkLastModified( $timestamp ) {
-               global $wgCachePages, $wgCacheEpoch, $wgUseSquid, $wgSquidMaxage;
-
                if ( !$timestamp || $timestamp == '19700101000000' ) {
                        wfDebug( __METHOD__ . ": CACHE DISABLED, NO TIMESTAMP\n" );
                        return false;
                }
-               if ( !$wgCachePages ) {
+               $config = $this->getConfig();
+               if ( !$config->get( 'CachePages' ) ) {
                        wfDebug( __METHOD__ . ": CACHE DISABLED\n" );
                        return false;
                }
@@ -746,11 +746,11 @@ class OutputPage extends ContextSource {
                $modifiedTimes = array(
                        'page' => $timestamp,
                        'user' => $this->getUser()->getTouched(),
-                       'epoch' => $wgCacheEpoch
+                       'epoch' => $config->get( 'CacheEpoch' )
                );
-               if ( $wgUseSquid ) {
+               if ( $config->get( 'UseSquid' ) ) {
                        // bug 44570: the core page itself may not change, but resources might
-                       $modifiedTimes['sepoch'] = wfTimestamp( TS_MW, time() - $wgSquidMaxage );
+                       $modifiedTimes['sepoch'] = wfTimestamp( TS_MW, time() - $config->get( 'SquidMaxage' ) );
                }
                wfRunHooks( 'OutputPageCheckLastModified', array( &$modifiedTimes ) );
 
@@ -815,7 +815,7 @@ class OutputPage extends ContextSource {
        /**
         * Override the last modified timestamp
         *
-        * @param string $timestamp new timestamp, in a format readable by
+        * @param string $timestamp New timestamp, in a format readable by
         *        wfTimestamp()
         */
        public function setLastModified( $timestamp ) {
@@ -825,7 +825,7 @@ class OutputPage extends ContextSource {
        /**
         * Set the robot policy for the page: <http://www.robotstxt.org/meta.html>
         *
-        * @param string $policy the literal string to output as the contents of
+        * @param string $policy The literal string to output as the contents of
         *   the meta tag.  Will be parsed according to the spec and output in
         *   standardized form.
         * @return null
@@ -859,7 +859,7 @@ class OutputPage extends ContextSource {
         * Set the follow policy for the page, but leave the index policy un-
         * touched.
         *
-        * @param string $policy either 'follow' or 'nofollow'.
+        * @param string $policy Either 'follow' or 'nofollow'.
         * @return null
         */
        public function setFollowPolicy( $policy ) {
@@ -873,7 +873,7 @@ class OutputPage extends ContextSource {
         * Set the new value of the "action text", this will be added to the
         * "HTML title", separated from it with " - ".
         *
-        * @param string $text new value of the "action text"
+        * @param string $text New value of the "action text"
         */
        public function setPageTitleActionText( $text ) {
                $this->mPageTitleActionText = $text;
@@ -892,7 +892,7 @@ class OutputPage extends ContextSource {
         * "HTML title" means the contents of "<title>".
         * It is stored as plain, unescaped text and will be run through htmlspecialchars in the skin file.
         *
-        * @param string $name
+        * @param string|Message $name
         */
        public function setHTMLTitle( $name ) {
                if ( $name instanceof Message ) {
@@ -968,7 +968,7 @@ class OutputPage extends ContextSource {
        /**
         * Replace the subtitle with $str
         *
-        * @param string|Message $str new value of the subtitle. String should be safe HTML.
+        * @param string|Message $str New value of the subtitle. String should be safe HTML.
         */
        public function setSubtitle( $str ) {
                $this->clearSubtitle();
@@ -979,7 +979,7 @@ class OutputPage extends ContextSource {
         * Add $str to the subtitle
         *
         * @deprecated since 1.19; use addSubtitle() instead
-        * @param string|Message $str to add to the subtitle
+        * @param string|Message $str String or Message to add to the subtitle
         */
        public function appendSubtitle( $str ) {
                $this->addSubtitle( $str );
@@ -988,7 +988,7 @@ class OutputPage extends ContextSource {
        /**
         * Add $str to the subtitle
         *
-        * @param string|Message $str to add to the subtitle. String should be safe HTML.
+        * @param string|Message $str String or Message to add to the subtitle. String should be safe HTML.
         */
        public function addSubtitle( $str ) {
                if ( $str instanceof Message ) {
@@ -1002,9 +1002,9 @@ class OutputPage extends ContextSource {
         * Add a subtitle containing a backlink to a page
         *
         * @param Title $title Title to link to
+        * @param array $query Array of additional parameters to include in the link
         */
-       public function addBacklinkSubtitle( Title $title ) {
-               $query = array();
+       public function addBacklinkSubtitle( Title $title, $query = array() ) {
                if ( $title->isRedirect() ) {
                        $query['redirect'] = 'no';
                }
@@ -1085,7 +1085,7 @@ class OutputPage extends ContextSource {
         * for the new version
         * @see addFeedLink()
         *
-        * @param bool $show true: add default feeds, false: remove all feeds
+        * @param bool $show True: add default feeds, false: remove all feeds
         */
        public function setSyndicated( $show = true ) {
                if ( $show ) {
@@ -1101,15 +1101,13 @@ class OutputPage extends ContextSource {
         * for the new version
         * @see addFeedLink()
         *
-        * @param string $val query to append to feed links or false to output
+        * @param string $val Query to append to feed links or false to output
         *        default links
         */
        public function setFeedAppendQuery( $val ) {
-               global $wgAdvertisedFeedTypes;
-
                $this->mFeedLinks = array();
 
-               foreach ( $wgAdvertisedFeedTypes as $type ) {
+               foreach ( $this->getConfig()->get( 'AdvertisedFeedTypes' ) as $type ) {
                        $query = "feed=$type";
                        if ( is_string( $val ) ) {
                                $query .= '&' . $val;
@@ -1121,13 +1119,11 @@ class OutputPage extends ContextSource {
        /**
         * Add a feed link to the page header
         *
-        * @param string $format feed type, should be a key of $wgFeedClasses
+        * @param string $format Feed type, should be a key of $wgFeedClasses
         * @param string $href URL
         */
        public function addFeedLink( $format, $href ) {
-               global $wgAdvertisedFeedTypes;
-
-               if ( in_array( $format, $wgAdvertisedFeedTypes ) ) {
+               if ( in_array( $format, $this->getConfig()->get( 'AdvertisedFeedTypes' ) ) ) {
                        $this->mFeedLinks[$format] = $href;
                }
        }
@@ -1142,7 +1138,7 @@ class OutputPage extends ContextSource {
 
        /**
         * Return URLs for each supported syndication format for this page.
-        * @return array associating format keys with URLs
+        * @return array Associating format keys with URLs
         */
        public function getSyndicationLinks() {
                return $this->mFeedLinks;
@@ -1209,7 +1205,7 @@ class OutputPage extends ContextSource {
         * @param array $newLinkArray Associative array mapping language code to the page
         *                      name
         */
-       public function addLanguageLinks( $newLinkArray ) {
+       public function addLanguageLinks( array $newLinkArray ) {
                $this->mLanguageLinks += $newLinkArray;
        }
 
@@ -1219,7 +1215,7 @@ class OutputPage extends ContextSource {
         * @param array $newLinkArray Associative array mapping language code to the page
         *                      name
         */
-       public function setLanguageLinks( $newLinkArray ) {
+       public function setLanguageLinks( array $newLinkArray ) {
                $this->mLanguageLinks = $newLinkArray;
        }
 
@@ -1235,9 +1231,9 @@ class OutputPage extends ContextSource {
        /**
         * Add an array of categories, with names in the keys
         *
-        * @param array $categories mapping category name => sort key
+        * @param array $categories Mapping category name => sort key
         */
-       public function addCategoryLinks( $categories ) {
+       public function addCategoryLinks( array $categories ) {
                global $wgContLang;
 
                if ( !is_array( $categories ) || count( $categories ) == 0 ) {
@@ -1251,9 +1247,15 @@ class OutputPage extends ContextSource {
 
                # Fetch existence plus the hiddencat property
                $dbr = wfGetDB( DB_SLAVE );
+               $fields = array( 'page_id', 'page_namespace', 'page_title', 'page_len',
+                       'page_is_redirect', 'page_latest', 'pp_value' );
+
+               if ( $this->getConfig()->get( 'ContentHandlerUseDB' ) ) {
+                       $fields[] = 'page_content_model';
+               }
+
                $res = $dbr->select( array( 'page', 'page_props' ),
-                       array( 'page_id', 'page_namespace', 'page_title', 'page_len',
-                               'page_is_redirect', 'page_latest', 'pp_value' ),
+                       $fields,
                        $lb->constructSet( 'page', $dbr ),
                        __METHOD__,
                        array(),
@@ -1266,11 +1268,8 @@ class OutputPage extends ContextSource {
                # Add the results to the link cache
                $lb->addResultToCache( LinkCache::singleton(), $res );
 
-               # Set all the values to 'normal'. This can be done with array_fill_keys in PHP 5.2.0+
-               $categories = array_combine(
-                       array_keys( $categories ),
-                       array_fill( 0, count( $categories ), 'normal' )
-               );
+               # Set all the values to 'normal'.
+               $categories = array_fill_keys( array_keys( $categories ), 'normal' );
 
                # Mark hidden categories
                foreach ( $res as $row ) {
@@ -1287,11 +1286,12 @@ class OutputPage extends ContextSource {
                        foreach ( $categories as $category => $type ) {
                                $origcategory = $category;
                                $title = Title::makeTitleSafe( NS_CATEGORY, $category );
+                               if ( !$title ) {
+                                       continue;
+                               }
                                $wgContLang->findVariantLink( $category, $title, true );
-                               if ( $category != $origcategory ) {
-                                       if ( array_key_exists( $category, $categories ) ) {
-                                               continue;
-                                       }
+                               if ( $category != $origcategory && array_key_exists( $category, $categories ) ) {
+                                       continue;
                                }
                                $text = $wgContLang->convertHtml( $title->getText() );
                                $this->mCategories[] = $title->getText();
@@ -1303,9 +1303,9 @@ class OutputPage extends ContextSource {
        /**
         * Reset the category links (but not the category list) and add $categories
         *
-        * @param array $categories mapping category name => sort key
+        * @param array $categories Mapping category name => sort key
         */
-       public function setCategoryLinks( $categories ) {
+       public function setCategoryLinks( array $categories ) {
                $this->mCategoryLinks = array();
                $this->addCategoryLinks( $categories );
        }
@@ -1403,7 +1403,7 @@ class OutputPage extends ContextSource {
         * @param array $attribs
         * @param string $contents
         */
-       public function addElement( $element, $attribs = array(), $contents = '' ) {
+       public function addElement( $element, array $attribs = array(), $contents = '' ) {
                $this->addHTML( Html::element( $element, $attribs, $contents ) );
        }
 
@@ -1611,7 +1611,7 @@ class OutputPage extends ContextSource {
         * @deprecated since 1.24, use addParserOutputMetadata() instead.
         * @param ParserOutput $parserOutput
         */
-       public function addParserOutputNoText( &$parserOutput ) {
+       public function addParserOutputNoText( $parserOutput ) {
                $this->addParserOutputMetadata( $parserOutput );
        }
 
@@ -1623,7 +1623,7 @@ class OutputPage extends ContextSource {
         * @since 1.24
         * @param ParserOutput $parserOutput
         */
-       public function addParserOutputMetadata( &$parserOutput ) {
+       public function addParserOutputMetadata( $parserOutput ) {
                $this->mLanguageLinks += $parserOutput->getLanguageLinks();
                $this->addCategoryLinks( $parserOutput->getCategories() );
                $this->mNewSectionLink = $parserOutput->getNewSection();
@@ -1640,6 +1640,8 @@ class OutputPage extends ContextSource {
                $this->addModuleStyles( $parserOutput->getModuleStyles() );
                $this->addModuleMessages( $parserOutput->getModuleMessages() );
                $this->addJsConfigVars( $parserOutput->getJsConfigVars() );
+               $this->mPreventClickjacking = $this->mPreventClickjacking
+                       || $parserOutput->preventClickjacking();
 
                // Template versioning...
                foreach ( (array)$parserOutput->getTemplateIds() as $ns => $dbks ) {
@@ -1655,11 +1657,11 @@ class OutputPage extends ContextSource {
                }
 
                // Hooks registered in the object
-               global $wgParserOutputHooks;
+               $parserOutputHooks = $this->getConfig()->get( 'ParserOutputHooks' );
                foreach ( $parserOutput->getOutputHooks() as $hookInfo ) {
                        list( $hookName, $data ) = $hookInfo;
-                       if ( isset( $wgParserOutputHooks[$hookName] ) ) {
-                               call_user_func( $wgParserOutputHooks[$hookName], $this, $parserOutput, $data );
+                       if ( isset( $parserOutputHooks[$hookName] ) ) {
+                               call_user_func( $parserOutputHooks[$hookName], $this, $parserOutput, $data );
                        }
                }
 
@@ -1677,7 +1679,7 @@ class OutputPage extends ContextSource {
         * @since 1.24
         * @param ParserOutput $parserOutput
         */
-       public function addParserOutputContent( &$parserOutput ) {
+       public function addParserOutputContent( $parserOutput ) {
                $this->addParserOutputText( $parserOutput );
 
                $this->addModules( $parserOutput->getModules() );
@@ -1694,7 +1696,7 @@ class OutputPage extends ContextSource {
         * @since 1.24
         * @param ParserOutput $parserOutput
         */
-       public function addParserOutputText( &$parserOutput ) {
+       public function addParserOutputText( $parserOutput ) {
                $text = $parserOutput->getText();
                wfRunHooks( 'OutputPageBeforeHTML', array( &$this, &$text ) );
                $this->addHTML( $text );
@@ -1705,7 +1707,7 @@ class OutputPage extends ContextSource {
         *
         * @param ParserOutput $parserOutput
         */
-       function addParserOutput( &$parserOutput ) {
+       function addParserOutput( $parserOutput ) {
                $this->addParserOutputMetadata( $parserOutput );
                $parserOutput->setTOCEnabled( $this->mEnableTOC );
 
@@ -1809,17 +1811,17 @@ class OutputPage extends ContextSource {
         * @return array
         */
        function getCacheVaryCookies() {
-               global $wgCookiePrefix, $wgCacheVaryCookies;
                static $cookies;
                if ( $cookies === null ) {
+                       $config = $this->getConfig();
                        $cookies = array_merge(
                                array(
-                                       "{$wgCookiePrefix}Token",
-                                       "{$wgCookiePrefix}LoggedOut",
+                                       $config->get( 'CookiePrefix' ) . 'Token',
+                                       $config->get( 'CookiePrefix' ) . 'LoggedOut',
                                        "forceHTTPS",
                                        session_name()
                                ),
-                               $wgCacheVaryCookies
+                               $config->get( 'CacheVaryCookies' )
                        );
                        wfRunHooks( 'GetCacheVaryCookies', array( $this, &$cookies ) );
                }
@@ -1852,7 +1854,7 @@ class OutputPage extends ContextSource {
        /**
         * Add an HTTP header that will influence on the cache
         *
-        * @param string $header header name
+        * @param string $header Header name
         * @param array|null $option
         * @todo FIXME: Document the $option parameter; it appears to be for
         *        X-Vary-Options but what format is acceptable?
@@ -1967,6 +1969,16 @@ class OutputPage extends ContextSource {
                $this->mPreventClickjacking = false;
        }
 
+       /**
+        * Get the prevent-clickjacking flag
+        *
+        * @since 1.24
+        * @return bool
+        */
+       public function getPreventClickjacking() {
+               return $this->mPreventClickjacking;
+       }
+
        /**
         * Get the X-Frame-Options header value (without the name part), or false
         * if there isn't one. This is used by Skin to determine whether to enable
@@ -1975,11 +1987,11 @@ class OutputPage extends ContextSource {
         * @return string
         */
        public function getFrameOptions() {
-               global $wgBreakFrames, $wgEditPageFrameOptions;
-               if ( $wgBreakFrames ) {
+               $config = $this->getConfig();
+               if ( $config->get( 'BreakFrames' ) ) {
                        return 'DENY';
-               } elseif ( $this->mPreventClickjacking && $wgEditPageFrameOptions ) {
-                       return $wgEditPageFrameOptions;
+               } elseif ( $this->mPreventClickjacking && $config->get( 'EditPageFrameOptions' ) ) {
+                       return $config->get( 'EditPageFrameOptions' );
                }
                return false;
        }
@@ -1988,10 +2000,9 @@ class OutputPage extends ContextSource {
         * Send cache control HTTP headers
         */
        public function sendCacheControl() {
-               global $wgUseSquid, $wgUseESI, $wgUseETag, $wgSquidMaxage, $wgUseXVO;
-
                $response = $this->getRequest()->response();
-               if ( $wgUseETag && $this->mETag ) {
+               $config = $this->getConfig();
+               if ( $config->get( 'UseETag' ) && $this->mETag ) {
                        $response->header( "ETag: $this->mETag" );
                }
 
@@ -2002,24 +2013,24 @@ class OutputPage extends ContextSource {
                # maintain different caches for logged-in users and non-logged in ones
                $response->header( $this->getVaryHeader() );
 
-               if ( $wgUseXVO ) {
+               if ( $config->get( 'UseXVO' ) ) {
                        # Add an X-Vary-Options header for Squid with Wikimedia patches
                        $response->header( $this->getXVO() );
                }
 
                if ( $this->mEnableClientCache ) {
                        if (
-                               $wgUseSquid && session_id() == '' && !$this->isPrintable() &&
+                               $config->get( 'UseSquid' ) && session_id() == '' && !$this->isPrintable() &&
                                $this->mSquidMaxage != 0 && !$this->haveCacheVaryCookies()
                        ) {
-                               if ( $wgUseESI ) {
+                               if ( $config->get( 'UseESI' ) ) {
                                        # We'll purge the proxy cache explicitly, but require end user agents
                                        # to revalidate against the proxy on each visit.
                                        # Surrogate-Control controls our Squid, Cache-Control downstream caches
                                        wfDebug( __METHOD__ . ": proxy caching with ESI; {$this->mLastModified} **\n", 'log' );
                                        # start with a shorter timeout for initial testing
                                        # header( 'Surrogate-Control: max-age=2678400+2678400, content="ESI/1.0"');
-                                       $response->header( 'Surrogate-Control: max-age=' . $wgSquidMaxage
+                                       $response->header( 'Surrogate-Control: max-age=' . $config->get( 'SquidMaxage' )
                                                . '+' . $this->mSquidMaxage . ', content="ESI/1.0"' );
                                        $response->header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
                                } else {
@@ -2059,8 +2070,7 @@ class OutputPage extends ContextSource {
         * the object, let's actually output it:
         */
        public function output() {
-               global $wgLanguageCode, $wgDebugRedirects, $wgMimeType, $wgVaryOnXFP,
-                       $wgUseAjax, $wgResponsiveImages;
+               global $wgLanguageCode;
 
                if ( $this->mDoNothing ) {
                        return;
@@ -2069,6 +2079,7 @@ class OutputPage extends ContextSource {
                wfProfileIn( __METHOD__ );
 
                $response = $this->getRequest()->response();
+               $config = $this->getConfig();
 
                if ( $this->mRedirect != '' ) {
                        # Standards require redirect URLs to be absolute
@@ -2079,19 +2090,19 @@ class OutputPage extends ContextSource {
 
                        if ( wfRunHooks( "BeforePageRedirect", array( $this, &$redirect, &$code ) ) ) {
                                if ( $code == '301' || $code == '303' ) {
-                                       if ( !$wgDebugRedirects ) {
+                                       if ( !$config->get( 'DebugRedirects' ) ) {
                                                $message = HttpStatus::getMessage( $code );
                                                $response->header( "HTTP/1.1 $code $message" );
                                        }
                                        $this->mLastModified = wfTimestamp( TS_RFC2822 );
                                }
-                               if ( $wgVaryOnXFP ) {
+                               if ( $config->get( 'VaryOnXFP' ) ) {
                                        $this->addVaryHeader( 'X-Forwarded-Proto' );
                                }
                                $this->sendCacheControl();
 
                                $response->header( "Content-Type: text/html; charset=utf-8" );
-                               if ( $wgDebugRedirects ) {
+                               if ( $config->get( 'DebugRedirects' ) ) {
                                        $url = htmlspecialchars( $redirect );
                                        print "<html>\n<head>\n<title>Redirect</title>\n</head>\n<body>\n";
                                        print "<p>Location: <a href=\"$url\">$url</a></p>\n";
@@ -2113,7 +2124,7 @@ class OutputPage extends ContextSource {
                # Buffer output; final headers may depend on later processing
                ob_start();
 
-               $response->header( "Content-type: $wgMimeType; charset=UTF-8" );
+               $response->header( 'Content-type: ' . $config->get( 'MimeType' ) . '; charset=UTF-8' );
                $response->header( 'Content-language: ' . $wgLanguageCode );
 
                // Avoid Internet Explorer "compatibility view" in IE 8-10, so that
@@ -2142,7 +2153,7 @@ class OutputPage extends ContextSource {
                        );
 
                        // Support for high-density display images if enabled
-                       if ( $wgResponsiveImages ) {
+                       if ( $config->get( 'ResponsiveImages' ) ) {
                                $coreModules[] = 'mediawiki.hidpi';
                        }
 
@@ -2151,10 +2162,6 @@ class OutputPage extends ContextSource {
                                $this->addModules( $group );
                        }
                        MWDebug::addModules( $this );
-                       if ( $wgUseAjax ) {
-                               // FIXME: deprecate? - not clear why this is useful
-                               wfRunHooks( 'AjaxAddScript', array( &$this ) );
-                       }
 
                        // Hook that allows last minute changes to the output page, e.g.
                        // adding of CSS or Javascript by extensions.
@@ -2178,7 +2185,7 @@ class OutputPage extends ContextSource {
        /**
         * Actually output something with print.
         *
-        * @param string $ins the string to output
+        * @param string $ins The string to output
         * @deprecated since 1.22 Use echo yourself.
         */
        public function out( $ins ) {
@@ -2199,8 +2206,8 @@ class OutputPage extends ContextSource {
         * indexing, clear the current text and redirect, set the page's title
         * and optionally an custom HTML title (content of the "<title>" tag).
         *
-        * @param string|Message $pageTitle will be passed directly to setPageTitle()
-        * @param string|Message $htmlTitle will be passed directly to setHTMLTitle();
+        * @param string|Message $pageTitle Will be passed directly to setPageTitle()
+        * @param string|Message $htmlTitle Will be passed directly to setHTMLTitle();
         *                   optional, if not passed the "<title>" attribute will be
         *                   based on $pageTitle
         */
@@ -2253,10 +2260,10 @@ class OutputPage extends ContextSource {
        /**
         * Output a standard permission error page
         *
-        * @param array $errors error message keys
-        * @param string $action action that was denied or null if unknown
+        * @param array $errors Error message keys
+        * @param string $action Action that was denied or null if unknown
         */
-       public function showPermissionsErrorPage( $errors, $action = null ) {
+       public function showPermissionsErrorPage( array $errors, $action = null ) {
                // For some action (read, edit, create and upload), display a "login to do this action"
                // error if all of the following conditions are met:
                // 1. the user is not logged in
@@ -2338,7 +2345,7 @@ class OutputPage extends ContextSource {
        /**
         * Display an error page noting that a given permission bit is required.
         * @deprecated since 1.18, just throw the exception directly
-        * @param string $permission key required
+        * @param string $permission Key required
         * @throws PermissionsError
         */
        public function permissionRequired( $permission ) {
@@ -2361,7 +2368,7 @@ class OutputPage extends ContextSource {
         * @param string $action Action that was denied or null if unknown
         * @return string The wikitext error-messages, formatted into a list.
         */
-       public function formatPermissionsErrorMessage( $errors, $action = null ) {
+       public function formatPermissionsErrorMessage( array $errors, $action = null ) {
                if ( $action == null ) {
                        $text = $this->msg( 'permissionserrorstext', count( $errors ) )->plain() . "\n\n";
                } else {
@@ -2414,7 +2421,7 @@ class OutputPage extends ContextSource {
         * @throws ReadOnlyError
         */
        public function readOnlyPage( $source = null, $protected = false,
-               $reasons = array(), $action = null
+               array $reasons = array(), $action = null
        ) {
                $this->setRobotPolicy( 'noindex,nofollow' );
                $this->setArticleRelated( false );
@@ -2489,9 +2496,9 @@ $templates
         * @param int $lag Slave lag
         */
        public function showLagWarning( $lag ) {
-               global $wgSlaveLagWarning, $wgSlaveLagCritical;
-               if ( $lag >= $wgSlaveLagWarning ) {
-                       $message = $lag < $wgSlaveLagCritical
+               $config = $this->getConfig();
+               if ( $lag >= $config->get( 'SlaveLagWarning' ) ) {
+                       $message = $lag < $config->get( 'SlaveLagCritical' )
                                ? 'lag-warn-normal'
                                : 'lag-warn-high';
                        $wrap = Html::rawElement( 'div', array( 'class' => "mw-{$message}" ), "\n$1\n" );
@@ -2533,7 +2540,7 @@ $templates
         * @param string $text Text of the link (input is not escaped)
         * @param array $options Options array to pass to Linker
         */
-       public function addReturnTo( $title, $query = array(), $text = null, $options = array() ) {
+       public function addReturnTo( $title, array $query = array(), $text = null, $options = array() ) {
                $link = $this->msg( 'returnto' )->rawParams(
                        Linker::link( $title, $text, array(), $query, $options ) )->escaped();
                $this->addHTML( "<p id=\"mw-returnto\">{$link}</p>\n" );
@@ -2578,7 +2585,7 @@ $templates
         * @return string The doctype, opening "<html>", and head element.
         */
        public function headElement( Skin $sk, $includeStyle = true ) {
-               global $wgContLang, $wgMimeType;
+               global $wgContLang;
 
                $userdir = $this->getLanguage()->getDir();
                $sitedir = $wgContLang->getDir();
@@ -2595,7 +2602,7 @@ $templates
                        $ret .= "$openHead\n";
                }
 
-               if ( !Html::isXmlMimeType( $wgMimeType ) ) {
+               if ( !Html::isXmlMimeType( $this->getConfig()->get( 'MimeType' ) ) ) {
                        // Add <meta charset="UTF-8">
                        // This should be before <title> since it defines the charset used by
                        // text including the text inside <title>.
@@ -2665,7 +2672,7 @@ $templates
         */
        public function getResourceLoader() {
                if ( is_null( $this->mResourceLoader ) ) {
-                       $this->mResourceLoader = new ResourceLoader();
+                       $this->mResourceLoader = new ResourceLoader( $this->getConfig() );
                }
                return $this->mResourceLoader;
        }
@@ -2684,8 +2691,6 @@ $templates
        protected function makeResourceLoaderLink( $modules, $only, $useESI = false,
                array $extraQuery = array(), $loadCall = false
        ) {
-               global $wgResourceLoaderUseESI;
-
                $modules = (array)$modules;
 
                $links = array(
@@ -2718,9 +2723,10 @@ $templates
                        $extraQuery['target'] = $this->mTarget;
                }
 
-               // Create keyed-by-group list of module objects from modules list
-               $groups = array();
+               // Create keyed-by-source and then keyed-by-group list of module objects from modules list
+               $sortedModules = array();
                $resourceLoader = $this->getResourceLoader();
+               $resourceLoaderUseESI = $this->getConfig()->get( 'ResourceLoaderUseESI' );
                foreach ( $modules as $name ) {
                        $module = $resourceLoader->getModule( $name );
                        # Check that we're allowed to include this module on this page
@@ -2729,141 +2735,149 @@ $templates
                                        && $only == ResourceLoaderModule::TYPE_SCRIPTS )
                                || ( $module->getOrigin() > $this->getAllowedModules( ResourceLoaderModule::TYPE_STYLES )
                                        && $only == ResourceLoaderModule::TYPE_STYLES )
+                               || ( $module->getOrigin() > $this->getAllowedModules( ResourceLoaderModule::TYPE_COMBINED )
+                                       && $only == ResourceLoaderModule::TYPE_COMBINED )
                                || ( $this->mTarget && !in_array( $this->mTarget, $module->getTargets() ) )
                        ) {
                                continue;
                        }
 
-                       $group = $module->getGroup();
-                       if ( !isset( $groups[$group] ) ) {
-                               $groups[$group] = array();
-                       }
-                       $groups[$group][$name] = $module;
+                       $sortedModules[$module->getSource()][$module->getGroup()][$name] = $module;
                }
 
-               foreach ( $groups as $group => $grpModules ) {
-                       // Special handling for user-specific groups
-                       $user = null;
-                       if ( ( $group === 'user' || $group === 'private' ) && $this->getUser()->isLoggedIn() ) {
-                               $user = $this->getUser()->getName();
-                       }
+               foreach ( $sortedModules as $source => $groups ) {
+                       foreach ( $groups as $group => $grpModules ) {
+                               // Special handling for user-specific groups
+                               $user = null;
+                               if ( ( $group === 'user' || $group === 'private' ) && $this->getUser()->isLoggedIn() ) {
+                                       $user = $this->getUser()->getName();
+                               }
 
-                       // Create a fake request based on the one we are about to make so modules return
-                       // correct timestamp and emptiness data
-                       $query = ResourceLoader::makeLoaderQuery(
-                               array(), // modules; not determined yet
-                               $this->getLanguage()->getCode(),
-                               $this->getSkin()->getSkinName(),
-                               $user,
-                               null, // version; not determined yet
-                               ResourceLoader::inDebugMode(),
-                               $only === ResourceLoaderModule::TYPE_COMBINED ? null : $only,
-                               $this->isPrintable(),
-                               $this->getRequest()->getBool( 'handheld' ),
-                               $extraQuery
-                       );
-                       $context = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
-
-                       // Extract modules that know they're empty
-                       foreach ( $grpModules as $key => $module ) {
-                               // Inline empty modules: since they're empty, just mark them as 'ready' (bug 46857)
-                               // If we're only getting the styles, we don't need to do anything for empty modules.
-                               if ( $module->isKnownEmpty( $context ) ) {
-                                       unset( $grpModules[$key] );
-                                       if ( $only !== ResourceLoaderModule::TYPE_STYLES ) {
-                                               $links['states'][$key] = 'ready';
+                               // Create a fake request based on the one we are about to make so modules return
+                               // correct timestamp and emptiness data
+                               $query = ResourceLoader::makeLoaderQuery(
+                                       array(), // modules; not determined yet
+                                       $this->getLanguage()->getCode(),
+                                       $this->getSkin()->getSkinName(),
+                                       $user,
+                                       null, // version; not determined yet
+                                       ResourceLoader::inDebugMode(),
+                                       $only === ResourceLoaderModule::TYPE_COMBINED ? null : $only,
+                                       $this->isPrintable(),
+                                       $this->getRequest()->getBool( 'handheld' ),
+                                       $extraQuery
+                               );
+                               $context = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
+
+
+                               // Extract modules that know they're empty and see if we have one or more
+                               // raw modules
+                               $isRaw = false;
+                               foreach ( $grpModules as $key => $module ) {
+                                       // Inline empty modules: since they're empty, just mark them as 'ready' (bug 46857)
+                                       // If we're only getting the styles, we don't need to do anything for empty modules.
+                                       if ( $module->isKnownEmpty( $context ) ) {
+                                               unset( $grpModules[$key] );
+                                               if ( $only !== ResourceLoaderModule::TYPE_STYLES ) {
+                                                       $links['states'][$key] = 'ready';
+                                               }
                                        }
+
+                                       $isRaw |= $module->isRaw();
                                }
-                       }
 
-                       // If there are no non-empty modules, skip this group
-                       if ( count( $grpModules ) === 0 ) {
-                               continue;
-                       }
+                               // If there are no non-empty modules, skip this group
+                               if ( count( $grpModules ) === 0 ) {
+                                       continue;
+                               }
 
-                       // Inline private modules. These can't be loaded through load.php for security
-                       // reasons, see bug 34907. Note that these modules should be loaded from
-                       // getHeadScripts() before the first loader call. Otherwise other modules can't
-                       // properly use them as dependencies (bug 30914)
-                       if ( $group === 'private' ) {
-                               if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
-                                       $links['html'] .= Html::inlineStyle(
-                                               $resourceLoader->makeModuleResponse( $context, $grpModules )
-                                       );
-                               } else {
-                                       $links['html'] .= Html::inlineScript(
-                                               ResourceLoader::makeLoaderConditionalScript(
+                               // Inline private modules. These can't be loaded through load.php for security
+                               // reasons, see bug 34907. Note that these modules should be loaded from
+                               // getHeadScripts() before the first loader call. Otherwise other modules can't
+                               // properly use them as dependencies (bug 30914)
+                               if ( $group === 'private' ) {
+                                       if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
+                                               $links['html'] .= Html::inlineStyle(
                                                        $resourceLoader->makeModuleResponse( $context, $grpModules )
-                                               )
-                                       );
+                                               );
+                                       } else {
+                                               $links['html'] .= Html::inlineScript(
+                                                       ResourceLoader::makeLoaderConditionalScript(
+                                                               $resourceLoader->makeModuleResponse( $context, $grpModules )
+                                                       )
+                                               );
+                                       }
+                                       $links['html'] .= "\n";
+                                       continue;
                                }
-                               $links['html'] .= "\n";
-                               continue;
-                       }
 
-                       // Special handling for the user group; because users might change their stuff
-                       // on-wiki like user pages, or user preferences; we need to find the highest
-                       // timestamp of these user-changeable modules so we can ensure cache misses on change
-                       // This should NOT be done for the site group (bug 27564) because anons get that too
-                       // and we shouldn't be putting timestamps in Squid-cached HTML
-                       $version = null;
-                       if ( $group === 'user' ) {
-                               // Get the maximum timestamp
-                               $timestamp = 1;
-                               foreach ( $grpModules as $module ) {
-                                       $timestamp = max( $timestamp, $module->getModifiedTime( $context ) );
+                               // Special handling for the user group; because users might change their stuff
+                               // on-wiki like user pages, or user preferences; we need to find the highest
+                               // timestamp of these user-changeable modules so we can ensure cache misses on change
+                               // This should NOT be done for the site group (bug 27564) because anons get that too
+                               // and we shouldn't be putting timestamps in Squid-cached HTML
+                               $version = null;
+                               if ( $group === 'user' ) {
+                                       // Get the maximum timestamp
+                                       $timestamp = 1;
+                                       foreach ( $grpModules as $module ) {
+                                               $timestamp = max( $timestamp, $module->getModifiedTime( $context ) );
+                                       }
+                                       // Add a version parameter so cache will break when things change
+                                       $query['version'] = wfTimestamp( TS_ISO_8601_BASIC, $timestamp );
                                }
-                               // Add a version parameter so cache will break when things change
-                               $version = wfTimestamp( TS_ISO_8601_BASIC, $timestamp );
-                       }
 
-                       $url = ResourceLoader::makeLoaderURL(
-                               array_keys( $grpModules ),
-                               $this->getLanguage()->getCode(),
-                               $this->getSkin()->getSkinName(),
-                               $user,
-                               $version,
-                               ResourceLoader::inDebugMode(),
-                               $only === ResourceLoaderModule::TYPE_COMBINED ? null : $only,
-                               $this->isPrintable(),
-                               $this->getRequest()->getBool( 'handheld' ),
-                               $extraQuery
-                       );
-                       if ( $useESI && $wgResourceLoaderUseESI ) {
-                               $esi = Xml::element( 'esi:include', array( 'src' => $url ) );
-                               if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
-                                       $link = Html::inlineStyle( $esi );
-                               } else {
-                                       $link = Html::inlineScript( $esi );
-                               }
-                       } else {
-                               // Automatically select style/script elements
-                               if ( $only === ResourceLoaderModule::TYPE_STYLES ) {
-                                       $link = Html::linkedStyle( $url );
-                               } elseif ( $loadCall ) {
-                                       $link = Html::inlineScript(
-                                               ResourceLoader::makeLoaderConditionalScript(
-                                                       Xml::encodeJsCall( 'mw.loader.load', array( $url, 'text/javascript', true ) )
-                                               )
-                                       );
+                               $query['modules'] = ResourceLoader::makePackedModulesString( array_keys( $grpModules ) );
+                               $moduleContext = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
+                               $url = $resourceLoader->createLoaderURL( $source, $moduleContext, $extraQuery );
+
+                               if ( $useESI && $resourceLoaderUseESI ) {
+                                       $esi = Xml::element( 'esi:include', array( 'src' => $url ) );
+                                       if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
+                                               $link = Html::inlineStyle( $esi );
+                                       } else {
+                                               $link = Html::inlineScript( $esi );
+                                       }
                                } else {
-                                       $link = Html::linkedScript( $url );
-
-                                       // For modules requested directly in the html via <link> or <script>,
-                                       // tell mw.loader they are being loading to prevent duplicate requests.
-                                       foreach ( $grpModules as $key => $module ) {
-                                               // Don't output state=loading for the startup module..
-                                               if ( $key !== 'startup' ) {
-                                                       $links['states'][$key] = 'loading';
+                                       // Automatically select style/script elements
+                                       if ( $only === ResourceLoaderModule::TYPE_STYLES ) {
+                                               $link = Html::linkedStyle( $url );
+                                       } elseif ( $loadCall ) {
+                                               $link = Html::inlineScript(
+                                                       ResourceLoader::makeLoaderConditionalScript(
+                                                               Xml::encodeJsCall( 'mw.loader.load', array( $url, 'text/javascript', true ) )
+                                                       )
+                                               );
+                                       } else {
+                                               $link = Html::linkedScript( $url );
+                                               if ( $context->getOnly() === 'scripts' && !$context->getRaw() && !$isRaw ) {
+                                                       // Wrap only=script requests in a conditional as browsers not supported
+                                                       // by the startup module would unconditionally execute this module.
+                                                       // Otherwise users will get "ReferenceError: mw is undefined" or
+                                                       // "jQuery is undefined" from e.g. a "site" module.
+                                                       $link = Html::inlineScript(
+                                                               ResourceLoader::makeLoaderConditionalScript(
+                                                                       Xml::encodeJsCall( 'document.write', array( $link ) )
+                                                               )
+                                                       );
+                                               }
+
+                                               // For modules requested directly in the html via <link> or <script>,
+                                               // tell mw.loader they are being loading to prevent duplicate requests.
+                                               foreach ( $grpModules as $key => $module ) {
+                                                       // Don't output state=loading for the startup module..
+                                                       if ( $key !== 'startup' ) {
+                                                               $links['states'][$key] = 'loading';
+                                                       }
                                                }
                                        }
                                }
-                       }
 
-                       if ( $group == 'noscript' ) {
-                               $links['html'] .= Html::rawElement( 'noscript', array(), $link ) . "\n";
-                       } else {
-                               $links['html'] .= $link . "\n";
+                               if ( $group == 'noscript' ) {
+                                       $links['html'] .= Html::rawElement( 'noscript', array(), $link ) . "\n";
+                               } else {
+                                       $links['html'] .= $link . "\n";
+                               }
                        }
                }
 
@@ -2875,7 +2889,7 @@ $templates
         * @param array $links
         * @return string HTML
         */
-       protected static function getHtmlFromLoaderLinks( Array $links ) {
+       protected static function getHtmlFromLoaderLinks( array $links ) {
                $html = '';
                $states = array();
                foreach ( $links as $link ) {
@@ -2905,8 +2919,6 @@ $templates
         * @return string HTML fragment
         */
        function getHeadScripts() {
-               global $wgResourceLoaderExperimentalAsyncLoading;
-
                // Startup - this will immediately load jquery and mediawiki modules
                $links = array();
                $links[] = $this->makeResourceLoaderLink( 'startup', ResourceLoaderModule::TYPE_SCRIPTS, true );
@@ -2946,7 +2958,7 @@ $templates
                        );
                }
 
-               if ( $wgResourceLoaderExperimentalAsyncLoading ) {
+               if ( $this->getConfig()->get( 'ResourceLoaderExperimentalAsyncLoading' ) ) {
                        $links[] = $this->getScriptsForBottomQueue( true );
                }
 
@@ -2965,8 +2977,6 @@ $templates
         * @return string
         */
        function getScriptsForBottomQueue( $inHead ) {
-               global $wgUseSiteJs, $wgAllowUserJs;
-
                // Scripts and messages "only" requests marked for bottom inclusion
                // If we're in the <head>, use load() calls rather than <script src="..."> tags
                // Messages should go first
@@ -3000,7 +3010,7 @@ $templates
                );
 
                // Add user JS if enabled
-               if ( $wgAllowUserJs
+               if ( $this->getConfig()->get( 'AllowUserJs' )
                        && $this->getUser()->isLoggedIn()
                        && $this->getTitle()
                        && $this->getTitle()->isJsSubpage()
@@ -3039,15 +3049,13 @@ $templates
         * @return string
         */
        function getBottomScripts() {
-               global $wgResourceLoaderExperimentalAsyncLoading;
-
                // Optimise jQuery ready event cross-browser.
                // This also enforces $.isReady to be true at </body> which fixes the
                // mw.loader bug in Firefox with using document.write between </body>
                // and the DOMContentReady event (bug 47457).
                $html = Html::inlineScript( 'window.jQuery && jQuery.ready();' );
 
-               if ( !$wgResourceLoaderExperimentalAsyncLoading ) {
+               if ( !$this->getConfig()->get( 'ResourceLoaderExperimentalAsyncLoading' ) ) {
                        $html .= $this->getScriptsForBottomQueue( false );
                }
 
@@ -3231,16 +3239,13 @@ $templates
        }
 
        /**
-        * @return array in format "link name or number => 'link html'".
+        * @return array Array in format "link name or number => 'link html'".
         */
        public function getHeadLinksArray() {
-               global $wgUniversalEditButton, $wgFavicon, $wgAppleTouchIcon, $wgEnableAPI,
-                       $wgSitename, $wgVersion,
-                       $wgFeed, $wgOverrideSiteFeed, $wgAdvertisedFeedTypes,
-                       $wgDisableLangConversion, $wgCanonicalLanguageLinks,
-                       $wgRightsPage, $wgRightsUrl;
+               global $wgVersion;
 
                $tags = array();
+               $config = $this->getConfig();
 
                $canonicalUrl = $this->mCanonicalUrl;
 
@@ -3283,7 +3288,7 @@ $templates
                }
 
                # Universal edit button
-               if ( $wgUniversalEditButton && $this->isArticleRelated() ) {
+               if ( $config->get( 'UniversalEditButton' ) && $this->isArticleRelated() ) {
                        $user = $this->getUser();
                        if ( $this->getTitle()->quickUserCan( 'edit', $user )
                                && ( $this->getTitle()->exists() || $this->getTitle()->quickUserCan( 'create', $user ) ) ) {
@@ -3308,17 +3313,17 @@ $templates
                # should not matter, but Konqueror (3.5.9 at least) incorrectly
                # uses whichever one appears later in the HTML source. Make sure
                # apple-touch-icon is specified first to avoid this.
-               if ( $wgAppleTouchIcon !== false ) {
+               if ( $config->get( 'AppleTouchIcon' ) !== false ) {
                        $tags['apple-touch-icon'] = Html::element( 'link', array(
                                'rel' => 'apple-touch-icon',
-                               'href' => $wgAppleTouchIcon
+                               'href' => $config->get( 'AppleTouchIcon' )
                        ) );
                }
 
-               if ( $wgFavicon !== false ) {
+               if ( $config->get( 'Favicon' ) !== false ) {
                        $tags['favicon'] = Html::element( 'link', array(
                                'rel' => 'shortcut icon',
-                               'href' => $wgFavicon
+                               'href' => $config->get( 'Favicon' )
                        ) );
                }
 
@@ -3330,7 +3335,7 @@ $templates
                        'title' => $this->msg( 'opensearch-desc' )->inContentLanguage()->text(),
                ) );
 
-               if ( $wgEnableAPI ) {
+               if ( $config->get( 'EnableAPI' ) ) {
                        # Real Simple Discovery link, provides auto-discovery information
                        # for the MediaWiki API (and potentially additional custom API
                        # support such as WordPress or Twitter-compatible APIs for a
@@ -3349,39 +3354,37 @@ $templates
                }
 
                # Language variants
-               if ( !$wgDisableLangConversion && $wgCanonicalLanguageLinks ) {
+               if ( !$config->get( 'DisableLangConversion' ) ) {
                        $lang = $this->getTitle()->getPageLanguage();
                        if ( $lang->hasVariants() ) {
-
-                               $urlvar = $lang->getURLVariant();
-
-                               if ( !$urlvar ) {
-                                       $variants = $lang->getVariants();
-                                       foreach ( $variants as $_v ) {
-                                               $tags["variant-$_v"] = Html::element( 'link', array(
-                                                       'rel' => 'alternate',
-                                                       'hreflang' => wfBCP47( $_v ),
-                                                       'href' => $this->getTitle()->getLocalURL( array( 'variant' => $_v ) ) )
-                                               );
-                                       }
-                               } else {
-                                       $canonicalUrl = $this->getTitle()->getLocalURL();
+                               $variants = $lang->getVariants();
+                               foreach ( $variants as $_v ) {
+                                       $tags["variant-$_v"] = Html::element( 'link', array(
+                                               'rel' => 'alternate',
+                                               'hreflang' => wfBCP47( $_v ),
+                                               'href' => $this->getTitle()->getLocalURL( array( 'variant' => $_v ) ) )
+                                       );
                                }
                        }
+                       # x-default link per https://support.google.com/webmasters/answer/189077?hl=en
+                       $tags["variant-x-default"] = Html::element( 'link', array(
+                               'rel' => 'alternate',
+                               'hreflang' => 'x-default',
+                               'href' => $this->getTitle()->getLocalURL() ) );
                }
 
                # Copyright
                $copyright = '';
-               if ( $wgRightsPage ) {
-                       $copy = Title::newFromText( $wgRightsPage );
+               if ( $config->get( 'RightsPage' ) ) {
+                       $copy = Title::newFromText( $config->get( 'RightsPage' ) );
 
                        if ( $copy ) {
                                $copyright = $copy->getLocalURL();
                        }
                }
 
-               if ( !$copyright && $wgRightsUrl ) {
-                       $copyright = $wgRightsUrl;
+               if ( !$copyright && $config->get( 'RightsUrl' ) ) {
+                       $copyright = $config->get( 'RightsUrl' );
                }
 
                if ( $copyright ) {
@@ -3392,7 +3395,7 @@ $templates
                }
 
                # Feeds
-               if ( $wgFeed ) {
+               if ( $config->get( 'Feed' ) ) {
                        foreach ( $this->getSyndicationLinks() as $format => $link ) {
                                # Use the page name for the title.  In principle, this could
                                # lead to issues with having the same name for different feeds
@@ -3414,31 +3417,31 @@ $templates
                        # like to promote instead of the RC feed (maybe like a "Recent New Articles"
                        # or "Breaking news" one). For this, we see if $wgOverrideSiteFeed is defined.
                        # If so, use it instead.
-                       if ( $wgOverrideSiteFeed ) {
-                               foreach ( $wgOverrideSiteFeed as $type => $feedUrl ) {
+                       $sitename = $config->get( 'Sitename' );
+                       if ( $config->get( 'OverrideSiteFeed' ) ) {
+                               foreach ( $config->get( 'OverrideSiteFeed' ) as $type => $feedUrl ) {
                                        // Note, this->feedLink escapes the url.
                                        $tags[] = $this->feedLink(
                                                $type,
                                                $feedUrl,
-                                               $this->msg( "site-{$type}-feed", $wgSitename )->text()
+                                               $this->msg( "site-{$type}-feed", $sitename )->text()
                                        );
                                }
                        } elseif ( !$this->getTitle()->isSpecial( 'Recentchanges' ) ) {
                                $rctitle = SpecialPage::getTitleFor( 'Recentchanges' );
-                               foreach ( $wgAdvertisedFeedTypes as $format ) {
+                               foreach ( $config->get( 'AdvertisedFeedTypes' ) as $format ) {
                                        $tags[] = $this->feedLink(
                                                $format,
                                                $rctitle->getLocalURL( array( 'feed' => $format ) ),
                                                # For grep: 'site-rss-feed', 'site-atom-feed'
-                                               $this->msg( "site-{$format}-feed", $wgSitename )->text()
+                                               $this->msg( "site-{$format}-feed", $sitename )->text()
                                        );
                                }
                        }
                }
 
                # Canonical URL
-               global $wgEnableCanonicalServerLink;
-               if ( $wgEnableCanonicalServerLink ) {
+               if ( $config->get( 'EnableCanonicalServerLink' ) ) {
                        if ( $canonicalUrl !== false ) {
                                $canonicalUrl = wfExpandUrl( $canonicalUrl, PROTO_CANONICAL );
                        } else {
@@ -3488,9 +3491,9 @@ $templates
         * Meant primarily for internal use...
         *
         * @param string $style URL to the file
-        * @param string $media to specify a media type, 'screen', 'printable', 'handheld' or any.
-        * @param string $condition for IE conditional comments, specifying an IE version
-        * @param string $dir set to 'rtl' or 'ltr' for direction-specific sheets
+        * @param string $media To specify a media type, 'screen', 'printable', 'handheld' or any.
+        * @param string $condition For IE conditional comments, specifying an IE version
+        * @param string $dir Set to 'rtl' or 'ltr' for direction-specific sheets
         */
        public function addStyle( $style, $media = '', $condition = '', $dir = '' ) {
                $options = array();
@@ -3517,6 +3520,8 @@ $templates
                if ( $flip === 'flip' && $this->getLanguage()->isRTL() ) {
                        # If wanted, and the interface is right-to-left, flip the CSS
                        $style_css = CSSJanus::transform( $style_css, true, false );
+               } else {
+                       $style_css = CSSJanus::nullTransform( $style_css );
                }
                $this->mInlineStyles .= Html::inlineStyle( $style_css ) . "\n";
        }
@@ -3528,7 +3533,7 @@ $templates
         * @return string
         */
        public function buildCssLinks() {
-               global $wgUseSiteCss, $wgAllowUserCss, $wgAllowUserCssPrefs, $wgContLang;
+               global $wgContLang;
 
                $this->getSkin()->setupSkinUserCss( $this );
 
@@ -3553,7 +3558,7 @@ $templates
                $moduleStyles[] = 'user.groups';
 
                // Per-user custom styles
-               if ( $wgAllowUserCss && $this->getTitle()->isCssSubpage() && $this->userCanPreview() ) {
+               if ( $this->getConfig()->get( 'AllowUserCss' ) && $this->getTitle()->isCssSubpage() && $this->userCanPreview() ) {
                        // We're on a preview of a CSS subpage
                        // Exclude this page from the user module in case it's in there (bug 26283)
                        $link = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_STYLES, false,
@@ -3567,6 +3572,8 @@ $templates
                        $previewedCSS = $this->getRequest()->getText( 'wpTextbox1' );
                        if ( $this->getLanguage()->getDir() !== $wgContLang->getDir() ) {
                                $previewedCSS = CSSJanus::transform( $previewedCSS, true, false );
+                       } else {
+                               $previewedCSS = CSSJanus::nullTransform( $previewedCSS );
                        }
                        $otherTags .= Html::inlineStyle( $previewedCSS ) . "\n";
                } else {
@@ -3585,7 +3592,7 @@ $templates
                        $group = $module->getGroup();
                        // Modules in groups different than the ones listed on top (see $styles assignment)
                        // will be placed in the "other" group
-                       $styles[ isset( $styles[$group] ) ? $group : 'other' ][] = $name;
+                       $styles[isset( $styles[$group] ) ? $group : 'other'][] = $name;
                }
 
                // We want site, private and user styles to override dynamically added
@@ -3644,7 +3651,7 @@ $templates
         * @param array $options Option, can contain 'condition', 'dir', 'media' keys
         * @return string HTML fragment
         */
-       protected function styleLink( $style, $options ) {
+       protected function styleLink( $style, array $options ) {
                if ( isset( $options['dir'] ) ) {
                        if ( $this->getLanguage()->getDir() != $options['dir'] ) {
                                return '';
@@ -3665,8 +3672,8 @@ $templates
                        substr( $style, 0, 6 ) == 'https:' ) {
                        $url = $style;
                } else {
-                       global $wgStylePath, $wgStyleVersion;
-                       $url = $wgStylePath . '/' . $style . '?' . $wgStyleVersion;
+                       $config = $this->getConfig();
+                       $url = $config->get( 'StylePath' ) . '/' . $style . '?' . $config->get( 'StyleVersion' );
                }
 
                $link = Html::linkedStyle( $url, $media );
@@ -3805,7 +3812,7 @@ $templates
         * @since 1.16
         * @deprecated since 1.17
         */
-       public function includeJQuery( $modules = array() ) {
+       public function includeJQuery( array $modules = array() ) {
                return array();
        }
 
index 0fb3952..44038a5 100644 (file)
@@ -32,6 +32,7 @@
  *   - index.php
  *   - load.php
  *   - api.php
+ *   - mw-config/index.php
  *   - cli
  *
  * @note Since we can't rely on anything, the minimum PHP versions and MW current
@@ -41,7 +42,7 @@ function wfPHPVersionError( $type ) {
        $mwVersion = '1.24';
        $minimumVersionPHP = '5.3.2';
 
-       $phpVersion = phpversion();
+       $phpVersion = PHP_VERSION;
        $protocol = isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
        $message = "MediaWiki $mwVersion requires at least "
                . "PHP version $minimumVersionPHP, you are using PHP $phpVersion.";
@@ -50,11 +51,16 @@ function wfPHPVersionError( $type ) {
                $finalOutput = "You are using PHP version $phpVersion "
                        . "but MediaWiki $mwVersion needs PHP $minimumVersionPHP or higher. ABORTING.\n"
                        . "Check if you have a newer php executable with a different name, such as php5.\n";
-       } elseif ( $type == 'index.php' ) {
+       } elseif ( $type == 'index.php' || $type == 'mw-config/index.php' ) {
                $pathinfo = pathinfo( $_SERVER['SCRIPT_NAME'] );
+               if ( $type == 'mw-config/index.php' ) {
+                       $dirname = dirname( $pathinfo['dirname'] );
+               } else {
+                       $dirname = $pathinfo['dirname'];
+               }
                $encLogo = htmlspecialchars(
-                       str_replace( '//', '/', $pathinfo['dirname'] . '/' ) .
-                       'skins/common/images/mediawiki.png'
+                       str_replace( '//', '/', $dirname . '/' ) .
+                       'assets/mediawiki.png'
                );
 
                header( "$protocol 500 MediaWiki configuration Error" );
diff --git a/includes/Pager.php b/includes/Pager.php
deleted file mode 100644 (file)
index 5f05460..0000000
+++ /dev/null
@@ -1,1331 +0,0 @@
-<?php
-/**
- * Efficient paging for SQL queries.
- *
- * 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
- */
-
-/**
- * @defgroup Pager Pager
- */
-
-/**
- * Basic pager interface.
- * @ingroup Pager
- */
-interface Pager {
-       function getNavigationBar();
-       function getBody();
-}
-
-/**
- * IndexPager is an efficient pager which uses a (roughly unique) index in the
- * data set to implement paging, rather than a "LIMIT offset,limit" clause.
- * In MySQL, such a limit/offset clause requires counting through the
- * specified number of offset rows to find the desired data, which can be
- * expensive for large offsets.
- *
- * ReverseChronologicalPager is a child class of the abstract IndexPager, and
- * contains  some formatting and display code which is specific to the use of
- * timestamps as  indexes. Here is a synopsis of its operation:
- *
- *    * The query is specified by the offset, limit and direction (dir)
- *      parameters, in addition to any subclass-specific parameters.
- *    * The offset is the non-inclusive start of the DB query. A row with an
- *      index value equal to the offset will never be shown.
- *    * The query may either be done backwards, where the rows are returned by
- *      the database in the opposite order to which they are displayed to the
- *      user, or forwards. This is specified by the "dir" parameter, dir=prev
- *      means backwards, anything else means forwards. The offset value
- *      specifies the start of the database result set, which may be either
- *      the start or end of the displayed data set. This allows "previous"
- *      links to be implemented without knowledge of the index value at the
- *      start of the previous page.
- *    * An additional row beyond the user-specified limit is always requested.
- *      This allows us to tell whether we should display a "next" link in the
- *      case of forwards mode, or a "previous" link in the case of backwards
- *      mode. Determining whether to display the other link (the one for the
- *      page before the start of the database result set) can be done
- *      heuristically by examining the offset.
- *
- *    * An empty offset indicates that the offset condition should be omitted
- *      from the query. This naturally produces either the first page or the
- *      last page depending on the dir parameter.
- *
- *  Subclassing the pager to implement concrete functionality should be fairly
- *  simple, please see the examples in HistoryPage.php and
- *  SpecialBlockList.php. You just need to override formatRow(),
- *  getQueryInfo() and getIndexField(). Don't forget to call the parent
- *  constructor if you override it.
- *
- * @ingroup Pager
- */
-abstract class IndexPager extends ContextSource implements Pager {
-       public $mRequest;
-       public $mLimitsShown = array( 20, 50, 100, 250, 500 );
-       public $mDefaultLimit = 50;
-       public $mOffset, $mLimit;
-       public $mQueryDone = false;
-       public $mDb;
-       public $mPastTheEndRow;
-
-       /**
-        * The index to actually be used for ordering. This is a single column,
-        * for one ordering, even if multiple orderings are supported.
-        */
-       protected $mIndexField;
-       /**
-        * An array of secondary columns to order by. These fields are not part of the offset.
-        * This is a column list for one ordering, even if multiple orderings are supported.
-        */
-       protected $mExtraSortFields;
-       /** For pages that support multiple types of ordering, which one to use.
-        */
-       protected $mOrderType;
-       /**
-        * $mDefaultDirection gives the direction to use when sorting results:
-        * false for ascending, true for descending.  If $mIsBackwards is set, we
-        * start from the opposite end, but we still sort the page itself according
-        * to $mDefaultDirection.  E.g., if $mDefaultDirection is false but we're
-        * going backwards, we'll display the last page of results, but the last
-        * result will be at the bottom, not the top.
-        *
-        * Like $mIndexField, $mDefaultDirection will be a single value even if the
-        * class supports multiple default directions for different order types.
-        */
-       public $mDefaultDirection;
-       public $mIsBackwards;
-
-       /** True if the current result set is the first one */
-       public $mIsFirst;
-       public $mIsLast;
-
-       protected $mLastShown, $mFirstShown, $mPastTheEndIndex, $mDefaultQuery, $mNavigationBar;
-
-       /**
-        * Whether to include the offset in the query
-        */
-       protected $mIncludeOffset = false;
-
-       /**
-        * Result object for the query. Warning: seek before use.
-        *
-        * @var ResultWrapper
-        */
-       public $mResult;
-
-       public function __construct( IContextSource $context = null ) {
-               if ( $context ) {
-                       $this->setContext( $context );
-               }
-
-               $this->mRequest = $this->getRequest();
-
-               # NB: the offset is quoted, not validated. It is treated as an
-               # arbitrary string to support the widest variety of index types. Be
-               # careful outputting it into HTML!
-               $this->mOffset = $this->mRequest->getText( 'offset' );
-
-               # Use consistent behavior for the limit options
-               $this->mDefaultLimit = $this->getUser()->getIntOption( 'rclimit' );
-               if ( !$this->mLimit ) {
-                       // Don't override if a subclass calls $this->setLimit() in its constructor.
-                       list( $this->mLimit, /* $offset */ ) = $this->mRequest->getLimitOffset();
-               }
-
-               $this->mIsBackwards = ( $this->mRequest->getVal( 'dir' ) == 'prev' );
-               # Let the subclass set the DB here; otherwise use a slave DB for the current wiki
-               $this->mDb = $this->mDb ?: wfGetDB( DB_SLAVE );
-
-               $index = $this->getIndexField(); // column to sort on
-               $extraSort = $this->getExtraSortFields(); // extra columns to sort on for query planning
-               $order = $this->mRequest->getVal( 'order' );
-               if ( is_array( $index ) && isset( $index[$order] ) ) {
-                       $this->mOrderType = $order;
-                       $this->mIndexField = $index[$order];
-                       $this->mExtraSortFields = isset( $extraSort[$order] )
-                               ? (array)$extraSort[$order]
-                               : array();
-               } elseif ( is_array( $index ) ) {
-                       # First element is the default
-                       reset( $index );
-                       list( $this->mOrderType, $this->mIndexField ) = each( $index );
-                       $this->mExtraSortFields = isset( $extraSort[$this->mOrderType] )
-                               ? (array)$extraSort[$this->mOrderType]
-                               : array();
-               } else {
-                       # $index is not an array
-                       $this->mOrderType = null;
-                       $this->mIndexField = $index;
-                       $this->mExtraSortFields = (array)$extraSort;
-               }
-
-               if ( !isset( $this->mDefaultDirection ) ) {
-                       $dir = $this->getDefaultDirections();
-                       $this->mDefaultDirection = is_array( $dir )
-                               ? $dir[$this->mOrderType]
-                               : $dir;
-               }
-       }
-
-       /**
-        * Get the Database object in use
-        *
-        * @return DatabaseBase
-        */
-       public function getDatabase() {
-               return $this->mDb;
-       }
-
-       /**
-        * Do the query, using information from the object context. This function
-        * has been kept minimal to make it overridable if necessary, to allow for
-        * result sets formed from multiple DB queries.
-        */
-       public function doQuery() {
-               # Use the child class name for profiling
-               $fname = __METHOD__ . ' (' . get_class( $this ) . ')';
-               wfProfileIn( $fname );
-
-               $descending = ( $this->mIsBackwards == $this->mDefaultDirection );
-               # Plus an extra row so that we can tell the "next" link should be shown
-               $queryLimit = $this->mLimit + 1;
-
-               if ( $this->mOffset == '' ) {
-                       $isFirst = true;
-               } else {
-                       // If there's an offset, we may or may not be at the first entry.
-                       // The only way to tell is to run the query in the opposite
-                       // direction see if we get a row.
-                       $oldIncludeOffset = $this->mIncludeOffset;
-                       $this->mIncludeOffset = !$this->mIncludeOffset;
-                       $isFirst = !$this->reallyDoQuery( $this->mOffset, 1, !$descending )->numRows();
-                       $this->mIncludeOffset = $oldIncludeOffset;
-               }
-
-               $this->mResult = $this->reallyDoQuery(
-                       $this->mOffset,
-                       $queryLimit,
-                       $descending
-               );
-
-               $this->extractResultInfo( $isFirst, $queryLimit, $this->mResult );
-               $this->mQueryDone = true;
-
-               $this->preprocessResults( $this->mResult );
-               $this->mResult->rewind(); // Paranoia
-
-               wfProfileOut( $fname );
-       }
-
-       /**
-        * @return ResultWrapper The result wrapper.
-        */
-       function getResult() {
-               return $this->mResult;
-       }
-
-       /**
-        * Set the offset from an other source than the request
-        *
-        * @param int|string $offset
-        */
-       function setOffset( $offset ) {
-               $this->mOffset = $offset;
-       }
-
-       /**
-        * Set the limit from an other source than the request
-        *
-        * Verifies limit is between 1 and 5000
-        *
-        * @param int|string $limit
-        */
-       function setLimit( $limit ) {
-               $limit = (int)$limit;
-               // WebRequest::getLimitOffset() puts a cap of 5000, so do same here.
-               if ( $limit > 5000 ) {
-                       $limit = 5000;
-               }
-               if ( $limit > 0 ) {
-                       $this->mLimit = $limit;
-               }
-       }
-
-       /**
-        * Get the current limit
-        *
-        * @return int
-        */
-       function getLimit() {
-               return $this->mLimit;
-       }
-
-       /**
-        * Set whether a row matching exactly the offset should be also included
-        * in the result or not. By default this is not the case, but when the
-        * offset is user-supplied this might be wanted.
-        *
-        * @param bool $include
-        */
-       public function setIncludeOffset( $include ) {
-               $this->mIncludeOffset = $include;
-       }
-
-       /**
-        * Extract some useful data from the result object for use by
-        * the navigation bar, put it into $this
-        *
-        * @param bool $isFirst False if there are rows before those fetched (i.e.
-        *     if a "previous" link would make sense)
-        * @param int $limit Exact query limit
-        * @param ResultWrapper $res
-        */
-       function extractResultInfo( $isFirst, $limit, ResultWrapper $res ) {
-               $numRows = $res->numRows();
-               if ( $numRows ) {
-                       # Remove any table prefix from index field
-                       $parts = explode( '.', $this->mIndexField );
-                       $indexColumn = end( $parts );
-
-                       $row = $res->fetchRow();
-                       $firstIndex = $row[$indexColumn];
-
-                       # Discard the extra result row if there is one
-                       if ( $numRows > $this->mLimit && $numRows > 1 ) {
-                               $res->seek( $numRows - 1 );
-                               $this->mPastTheEndRow = $res->fetchObject();
-                               $this->mPastTheEndIndex = $this->mPastTheEndRow->$indexColumn;
-                               $res->seek( $numRows - 2 );
-                               $row = $res->fetchRow();
-                               $lastIndex = $row[$indexColumn];
-                       } else {
-                               $this->mPastTheEndRow = null;
-                               # Setting indexes to an empty string means that they will be
-                               # omitted if they would otherwise appear in URLs. It just so
-                               # happens that this  is the right thing to do in the standard
-                               # UI, in all the relevant cases.
-                               $this->mPastTheEndIndex = '';
-                               $res->seek( $numRows - 1 );
-                               $row = $res->fetchRow();
-                               $lastIndex = $row[$indexColumn];
-                       }
-               } else {
-                       $firstIndex = '';
-                       $lastIndex = '';
-                       $this->mPastTheEndRow = null;
-                       $this->mPastTheEndIndex = '';
-               }
-
-               if ( $this->mIsBackwards ) {
-                       $this->mIsFirst = ( $numRows < $limit );
-                       $this->mIsLast = $isFirst;
-                       $this->mLastShown = $firstIndex;
-                       $this->mFirstShown = $lastIndex;
-               } else {
-                       $this->mIsFirst = $isFirst;
-                       $this->mIsLast = ( $numRows < $limit );
-                       $this->mLastShown = $lastIndex;
-                       $this->mFirstShown = $firstIndex;
-               }
-       }
-
-       /**
-        * Get some text to go in brackets in the "function name" part of the SQL comment
-        *
-        * @return string
-        */
-       function getSqlComment() {
-               return get_class( $this );
-       }
-
-       /**
-        * Do a query with specified parameters, rather than using the object
-        * context
-        *
-        * @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
-        */
-       public function reallyDoQuery( $offset, $limit, $descending ) {
-               list( $tables, $fields, $conds, $fname, $options, $join_conds ) =
-                       $this->buildQueryInfo( $offset, $limit, $descending );
-
-               return $this->mDb->select( $tables, $fields, $conds, $fname, $options, $join_conds );
-       }
-
-       /**
-        * Build variables to use by the database wrapper.
-        *
-        * @param string $offset Index offset, inclusive
-        * @param int $limit Exact query limit
-        * @param bool $descending Query direction, false for ascending, true for descending
-        * @return array
-        */
-       protected function buildQueryInfo( $offset, $limit, $descending ) {
-               $fname = __METHOD__ . ' (' . $this->getSqlComment() . ')';
-               $info = $this->getQueryInfo();
-               $tables = $info['tables'];
-               $fields = $info['fields'];
-               $conds = isset( $info['conds'] ) ? $info['conds'] : array();
-               $options = isset( $info['options'] ) ? $info['options'] : array();
-               $join_conds = isset( $info['join_conds'] ) ? $info['join_conds'] : array();
-               $sortColumns = array_merge( array( $this->mIndexField ), $this->mExtraSortFields );
-               if ( $descending ) {
-                       $options['ORDER BY'] = $sortColumns;
-                       $operator = $this->mIncludeOffset ? '>=' : '>';
-               } else {
-                       $orderBy = array();
-                       foreach ( $sortColumns as $col ) {
-                               $orderBy[] = $col . ' DESC';
-                       }
-                       $options['ORDER BY'] = $orderBy;
-                       $operator = $this->mIncludeOffset ? '<=' : '<';
-               }
-               if ( $offset != '' ) {
-                       $conds[] = $this->mIndexField . $operator . $this->mDb->addQuotes( $offset );
-               }
-               $options['LIMIT'] = intval( $limit );
-               return array( $tables, $fields, $conds, $fname, $options, $join_conds );
-       }
-
-       /**
-        * Pre-process results; useful for performing batch existence checks, etc.
-        *
-        * @param ResultWrapper $result
-        */
-       protected function preprocessResults( $result ) {
-       }
-
-       /**
-        * Get the formatted result list. Calls getStartBody(), formatRow() and
-        * getEndBody(), concatenates the results and returns them.
-        *
-        * @return string
-        */
-       public function getBody() {
-               if ( !$this->mQueryDone ) {
-                       $this->doQuery();
-               }
-
-               if ( $this->mResult->numRows() ) {
-                       # Do any special query batches before display
-                       $this->doBatchLookups();
-               }
-
-               # Don't use any extra rows returned by the query
-               $numRows = min( $this->mResult->numRows(), $this->mLimit );
-
-               $s = $this->getStartBody();
-               if ( $numRows ) {
-                       if ( $this->mIsBackwards ) {
-                               for ( $i = $numRows - 1; $i >= 0; $i-- ) {
-                                       $this->mResult->seek( $i );
-                                       $row = $this->mResult->fetchObject();
-                                       $s .= $this->formatRow( $row );
-                               }
-                       } else {
-                               $this->mResult->seek( 0 );
-                               for ( $i = 0; $i < $numRows; $i++ ) {
-                                       $row = $this->mResult->fetchObject();
-                                       $s .= $this->formatRow( $row );
-                               }
-                       }
-               } else {
-                       $s .= $this->getEmptyBody();
-               }
-               $s .= $this->getEndBody();
-               return $s;
-       }
-
-       /**
-        * Make a self-link
-        *
-        * @param string $text Text displayed on the link
-        * @param array $query Associative array of parameter to be in the query string
-        * @param string $type Value of the "rel" attribute
-        *
-        * @return string HTML fragment
-        */
-       function makeLink( $text, array $query = null, $type = null ) {
-               if ( $query === null ) {
-                       return $text;
-               }
-
-               $attrs = array();
-               if ( in_array( $type, array( 'first', 'prev', 'next', 'last' ) ) ) {
-                       # HTML5 rel attributes
-                       $attrs['rel'] = $type;
-               }
-
-               if ( $type ) {
-                       $attrs['class'] = "mw-{$type}link";
-               }
-
-               return Linker::linkKnown(
-                       $this->getTitle(),
-                       $text,
-                       $attrs,
-                       $query + $this->getDefaultQuery()
-               );
-       }
-
-       /**
-        * Called from getBody(), before getStartBody() is called and
-        * after doQuery() was called. This will be called only if there
-        * are rows in the result set.
-        *
-        * @return void
-        */
-       protected function doBatchLookups() {
-       }
-
-       /**
-        * Hook into getBody(), allows text to be inserted at the start. This
-        * will be called even if there are no rows in the result set.
-        *
-        * @return string
-        */
-       protected function getStartBody() {
-               return '';
-       }
-
-       /**
-        * Hook into getBody() for the end of the list
-        *
-        * @return string
-        */
-       protected function getEndBody() {
-               return '';
-       }
-
-       /**
-        * Hook into getBody(), for the bit between the start and the
-        * end when there are no rows
-        *
-        * @return string
-        */
-       protected function getEmptyBody() {
-               return '';
-       }
-
-       /**
-        * Get an array of query parameters that should be put into self-links.
-        * By default, all parameters passed in the URL are used, except for a
-        * short blacklist.
-        *
-        * @return array Associative array
-        */
-       function getDefaultQuery() {
-               if ( !isset( $this->mDefaultQuery ) ) {
-                       $this->mDefaultQuery = $this->getRequest()->getQueryValues();
-                       unset( $this->mDefaultQuery['title'] );
-                       unset( $this->mDefaultQuery['dir'] );
-                       unset( $this->mDefaultQuery['offset'] );
-                       unset( $this->mDefaultQuery['limit'] );
-                       unset( $this->mDefaultQuery['order'] );
-                       unset( $this->mDefaultQuery['month'] );
-                       unset( $this->mDefaultQuery['year'] );
-               }
-               return $this->mDefaultQuery;
-       }
-
-       /**
-        * Get the number of rows in the result set
-        *
-        * @return int
-        */
-       function getNumRows() {
-               if ( !$this->mQueryDone ) {
-                       $this->doQuery();
-               }
-               return $this->mResult->numRows();
-       }
-
-       /**
-        * Get a URL query array for the prev, next, first and last links.
-        *
-        * @return array
-        */
-       function getPagingQueries() {
-               if ( !$this->mQueryDone ) {
-                       $this->doQuery();
-               }
-
-               # Don't announce the limit everywhere if it's the default
-               $urlLimit = $this->mLimit == $this->mDefaultLimit ? null : $this->mLimit;
-
-               if ( $this->mIsFirst ) {
-                       $prev = false;
-                       $first = false;
-               } else {
-                       $prev = array(
-                               'dir' => 'prev',
-                               'offset' => $this->mFirstShown,
-                               'limit' => $urlLimit
-                       );
-                       $first = array( 'limit' => $urlLimit );
-               }
-               if ( $this->mIsLast ) {
-                       $next = false;
-                       $last = false;
-               } else {
-                       $next = array( 'offset' => $this->mLastShown, 'limit' => $urlLimit );
-                       $last = array( 'dir' => 'prev', 'limit' => $urlLimit );
-               }
-               return array(
-                       'prev' => $prev,
-                       'next' => $next,
-                       'first' => $first,
-                       'last' => $last
-               );
-       }
-
-       /**
-        * Returns whether to show the "navigation bar"
-        *
-        * @return bool
-        */
-       function isNavigationBarShown() {
-               if ( !$this->mQueryDone ) {
-                       $this->doQuery();
-               }
-               // Hide navigation by default if there is nothing to page
-               return !( $this->mIsFirst && $this->mIsLast );
-       }
-
-       /**
-        * Get paging links. If a link is disabled, the item from $disabledTexts
-        * will be used. If there is no such item, the unlinked text from
-        * $linkTexts will be used. Both $linkTexts and $disabledTexts are arrays
-        * of HTML.
-        *
-        * @param array $linkTexts
-        * @param array $disabledTexts
-        * @return array
-        */
-       function getPagingLinks( $linkTexts, $disabledTexts = array() ) {
-               $queries = $this->getPagingQueries();
-               $links = array();
-
-               foreach ( $queries as $type => $query ) {
-                       if ( $query !== false ) {
-                               $links[$type] = $this->makeLink(
-                                       $linkTexts[$type],
-                                       $queries[$type],
-                                       $type
-                               );
-                       } elseif ( isset( $disabledTexts[$type] ) ) {
-                               $links[$type] = $disabledTexts[$type];
-                       } else {
-                               $links[$type] = $linkTexts[$type];
-                       }
-               }
-
-               return $links;
-       }
-
-       function getLimitLinks() {
-               $links = array();
-               if ( $this->mIsBackwards ) {
-                       $offset = $this->mPastTheEndIndex;
-               } else {
-                       $offset = $this->mOffset;
-               }
-               foreach ( $this->mLimitsShown as $limit ) {
-                       $links[] = $this->makeLink(
-                               $this->getLanguage()->formatNum( $limit ),
-                               array( 'offset' => $offset, 'limit' => $limit ),
-                               'num'
-                       );
-               }
-               return $links;
-       }
-
-       /**
-        * Abstract formatting function. This should return an HTML string
-        * representing the result row $row. Rows will be concatenated and
-        * returned by getBody()
-        *
-        * @param array|stdClass $row Database row
-        * @return string
-        */
-       abstract function formatRow( $row );
-
-       /**
-        * This function should be overridden to provide all parameters
-        * needed for the main paged query. It returns an associative
-        * array with the following elements:
-        *    tables => Table(s) for passing to Database::select()
-        *    fields => Field(s) for passing to Database::select(), may be *
-        *    conds => WHERE conditions
-        *    options => option array
-        *    join_conds => JOIN conditions
-        *
-        * @return array
-        */
-       abstract function getQueryInfo();
-
-       /**
-        * This function should be overridden to return the name of the index fi-
-        * eld.  If the pager supports multiple orders, it may return an array of
-        * 'querykey' => 'indexfield' pairs, so that a request with &count=querykey
-        * will use indexfield to sort.  In this case, the first returned key is
-        * the default.
-        *
-        * Needless to say, it's really not a good idea to use a non-unique index
-        * for this!  That won't page right.
-        *
-        * @return string|array
-        */
-       abstract function getIndexField();
-
-       /**
-        * This function should be overridden to return the names of secondary columns
-        * to order by in addition to the column in getIndexField(). These fields will
-        * not be used in the pager offset or in any links for users.
-        *
-        * If getIndexField() returns an array of 'querykey' => 'indexfield' pairs then
-        * this must return a corresponding array of 'querykey' => array( fields...) pairs
-        * in order for a request with &count=querykey to use array( fields...) to sort.
-        *
-        * This is useful for pagers that GROUP BY a unique column (say page_id)
-        * and ORDER BY another (say page_len). Using GROUP BY and ORDER BY both on
-        * page_len,page_id avoids temp tables (given a page_len index). This would
-        * also work if page_id was non-unique but we had a page_len,page_id index.
-        *
-        * @return array
-        */
-       protected function getExtraSortFields() {
-               return array();
-       }
-
-       /**
-        * Return the default sorting direction: false for ascending, true for
-        * descending.  You can also have an associative array of ordertype => dir,
-        * if multiple order types are supported.  In this case getIndexField()
-        * must return an array, and the keys of that must exactly match the keys
-        * of this.
-        *
-        * For backward compatibility, this method's return value will be ignored
-        * if $this->mDefaultDirection is already set when the constructor is
-        * called, for instance if it's statically initialized.  In that case the
-        * value of that variable (which must be a boolean) will be used.
-        *
-        * Note that despite its name, this does not return the value of the
-        * $this->mDefaultDirection member variable.  That's the default for this
-        * particular instantiation, which is a single value.  This is the set of
-        * all defaults for the class.
-        *
-        * @return bool
-        */
-       protected function getDefaultDirections() {
-               return false;
-       }
-}
-
-/**
- * IndexPager with an alphabetic list and a formatted navigation bar
- * @ingroup Pager
- */
-abstract class AlphabeticPager extends IndexPager {
-
-       /**
-        * Shamelessly stolen bits from ReverseChronologicalPager,
-        * didn't want to do class magic as may be still revamped
-        *
-        * @return string HTML
-        */
-       function getNavigationBar() {
-               if ( !$this->isNavigationBarShown() ) {
-                       return '';
-               }
-
-               if ( isset( $this->mNavigationBar ) ) {
-                       return $this->mNavigationBar;
-               }
-
-               $linkTexts = array(
-                       'prev' => $this->msg( 'prevn' )->numParams( $this->mLimit )->escaped(),
-                       'next' => $this->msg( 'nextn' )->numParams( $this->mLimit )->escaped(),
-                       'first' => $this->msg( 'page_first' )->escaped(),
-                       'last' => $this->msg( 'page_last' )->escaped()
-               );
-
-               $lang = $this->getLanguage();
-
-               $pagingLinks = $this->getPagingLinks( $linkTexts );
-               $limitLinks = $this->getLimitLinks();
-               $limits = $lang->pipeList( $limitLinks );
-
-               $this->mNavigationBar = $this->msg( 'parentheses' )->rawParams(
-                       $lang->pipeList( array( $pagingLinks['first'],
-                       $pagingLinks['last'] ) ) )->escaped() . " " .
-                       $this->msg( 'viewprevnext' )->rawParams( $pagingLinks['prev'],
-                               $pagingLinks['next'], $limits )->escaped();
-
-               if ( !is_array( $this->getIndexField() ) ) {
-                       # Early return to avoid undue nesting
-                       return $this->mNavigationBar;
-               }
-
-               $extra = '';
-               $first = true;
-               $msgs = $this->getOrderTypeMessages();
-               foreach ( array_keys( $msgs ) as $order ) {
-                       if ( $first ) {
-                               $first = false;
-                       } else {
-                               $extra .= $this->msg( 'pipe-separator' )->escaped();
-                       }
-
-                       if ( $order == $this->mOrderType ) {
-                               $extra .= $this->msg( $msgs[$order] )->escaped();
-                       } else {
-                               $extra .= $this->makeLink(
-                                       $this->msg( $msgs[$order] )->escaped(),
-                                       array( 'order' => $order )
-                               );
-                       }
-               }
-
-               if ( $extra !== '' ) {
-                       $extra = ' ' . $this->msg( 'parentheses' )->rawParams( $extra )->escaped();
-                       $this->mNavigationBar .= $extra;
-               }
-
-               return $this->mNavigationBar;
-       }
-
-       /**
-        * If this supports multiple order type messages, give the message key for
-        * enabling each one in getNavigationBar.  The return type is an associative
-        * array whose keys must exactly match the keys of the array returned
-        * by getIndexField(), and whose values are message keys.
-        *
-        * @return array
-        */
-       protected function getOrderTypeMessages() {
-               return null;
-       }
-}
-
-/**
- * IndexPager with a formatted navigation bar
- * @ingroup Pager
- */
-abstract class ReverseChronologicalPager extends IndexPager {
-       public $mDefaultDirection = true;
-       public $mYear;
-       public $mMonth;
-
-       function getNavigationBar() {
-               if ( !$this->isNavigationBarShown() ) {
-                       return '';
-               }
-
-               if ( isset( $this->mNavigationBar ) ) {
-                       return $this->mNavigationBar;
-               }
-
-               $linkTexts = array(
-                       '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();
-               $limits = $this->getLanguage()->pipeList( $limitLinks );
-               $firstLastLinks = $this->msg( 'parentheses' )->rawParams( "{$pagingLinks['first']}" .
-                       $this->msg( 'pipe-separator' )->escaped() .
-                       "{$pagingLinks['last']}" )->escaped();
-
-               $this->mNavigationBar = $firstLastLinks . ' ' .
-                       $this->msg( 'viewprevnext' )->rawParams(
-                               $pagingLinks['prev'], $pagingLinks['next'], $limits )->escaped();
-
-               return $this->mNavigationBar;
-       }
-
-       function getDateCond( $year, $month ) {
-               $year = intval( $year );
-               $month = intval( $month );
-
-               // Basic validity checks
-               $this->mYear = $year > 0 ? $year : false;
-               $this->mMonth = ( $month > 0 && $month < 13 ) ? $month : false;
-
-               // Given an optional year and month, we need to generate a timestamp
-               // to use as "WHERE rev_timestamp <= result"
-               // Examples: year = 2006 equals < 20070101 (+000000)
-               // year=2005, month=1    equals < 20050201
-               // year=2005, month=12   equals < 20060101
-               if ( !$this->mYear && !$this->mMonth ) {
-                       return;
-               }
-
-               if ( $this->mYear ) {
-                       $year = $this->mYear;
-               } else {
-                       // If no year given, assume the current one
-                       $timestamp = MWTimestamp::getInstance();
-                       $year = $timestamp->format( 'Y' );
-                       // If this month hasn't happened yet this year, go back to last year's month
-                       if ( $this->mMonth > $timestamp->format( 'n' ) ) {
-                               $year--;
-                       }
-               }
-
-               if ( $this->mMonth ) {
-                       $month = $this->mMonth + 1;
-                       // For December, we want January 1 of the next year
-                       if ( $month > 12 ) {
-                               $month = 1;
-                               $year++;
-                       }
-               } else {
-                       // No month implies we want up to the end of the year in question
-                       $month = 1;
-                       $year++;
-               }
-
-               // Y2K38 bug
-               if ( $year > 2032 ) {
-                       $year = 2032;
-               }
-
-               $ymd = (int)sprintf( "%04d%02d01", $year, $month );
-
-               if ( $ymd > 20320101 ) {
-                       $ymd = 20320101;
-               }
-
-               $this->mOffset = $this->mDb->timestamp( "${ymd}000000" );
-       }
-}
-
-/**
- * Table-based display with a user-selectable sort order
- * @ingroup Pager
- */
-abstract class TablePager extends IndexPager {
-       protected $mSort;
-
-       protected $mCurrentRow;
-
-       public function __construct( IContextSource $context = null ) {
-               if ( $context ) {
-                       $this->setContext( $context );
-               }
-
-               $this->mSort = $this->getRequest()->getText( 'sort' );
-               if ( !array_key_exists( $this->mSort, $this->getFieldNames() )
-                       || !$this->isFieldSortable( $this->mSort )
-               ) {
-                       $this->mSort = $this->getDefaultSort();
-               }
-               if ( $this->getRequest()->getBool( 'asc' ) ) {
-                       $this->mDefaultDirection = false;
-               } elseif ( $this->getRequest()->getBool( 'desc' ) ) {
-                       $this->mDefaultDirection = true;
-               } /* Else leave it at whatever the class default is */
-
-               parent::__construct();
-       }
-
-       /**
-        * @protected
-        * @return string
-        */
-       function getStartBody() {
-               global $wgStylePath;
-               $sortClass = $this->getSortHeaderClass();
-
-               $s = '';
-               $fields = $this->getFieldNames();
-
-               # Make table header
-               foreach ( $fields as $field => $name ) {
-                       if ( strval( $name ) == '' ) {
-                               $s .= Html::rawElement( 'th', array(), '&#160;' ) . "\n";
-                       } elseif ( $this->isFieldSortable( $field ) ) {
-                               $query = array( 'sort' => $field, 'limit' => $this->mLimit );
-                               if ( $field == $this->mSort ) {
-                                       # This is the sorted column
-                                       # Prepare a link that goes in the other sort order
-                                       if ( $this->mDefaultDirection ) {
-                                               # Descending
-                                               $image = 'Arr_d.png';
-                                               $query['asc'] = '1';
-                                               $query['desc'] = '';
-                                               $alt = $this->msg( 'descending_abbrev' )->escaped();
-                                       } else {
-                                               # Ascending
-                                               $image = 'Arr_u.png';
-                                               $query['asc'] = '';
-                                               $query['desc'] = '1';
-                                               $alt = $this->msg( 'ascending_abbrev' )->escaped();
-                                       }
-                                       $image = "$wgStylePath/common/images/$image";
-                                       $link = $this->makeLink(
-                                               Html::element( 'img', array( 'width' => 12, 'height' => 12,
-                                                       'alt' => $alt, 'src' => $image ) ) . htmlspecialchars( $name ), $query );
-                                       $s .= Html::rawElement( 'th', array( 'class' => $sortClass ), $link ) . "\n";
-                               } else {
-                                       $s .= Html::rawElement( 'th', array(),
-                                               $this->makeLink( htmlspecialchars( $name ), $query ) ) . "\n";
-                               }
-                       } else {
-                               $s .= Html::element( 'th', array(), $name ) . "\n";
-                       }
-               }
-
-               $tableClass = $this->getTableClass();
-               $ret = Html::openElement( 'table', array(
-                       'style' => 'border:1px;',
-                       'class' => "mw-datatable $tableClass" )
-               );
-               $ret .= Html::rawElement( 'thead', array(), Html::rawElement( 'tr', array(), "\n" . $s . "\n" ) );
-               $ret .= Html::openElement( 'tbody' ) . "\n";
-
-               return $ret;
-       }
-
-       /**
-        * @protected
-        * @return string
-        */
-       function getEndBody() {
-               return "</tbody></table>\n";
-       }
-
-       /**
-        * @protected
-        * @return string
-        */
-       function getEmptyBody() {
-               $colspan = count( $this->getFieldNames() );
-               $msgEmpty = $this->msg( 'table_pager_empty' )->text();
-               return Html::rawElement( 'tr', array(),
-                       Html::element( 'td', array( 'colspan' => $colspan ), $msgEmpty ) );
-       }
-
-       /**
-        * @protected
-        * @param stdClass $row
-        * @return string HTML
-        */
-       function formatRow( $row ) {
-               $this->mCurrentRow = $row; // In case formatValue etc need to know
-               $s = Html::openElement( 'tr', $this->getRowAttrs( $row ) ) . "\n";
-               $fieldNames = $this->getFieldNames();
-
-               foreach ( $fieldNames as $field => $name ) {
-                       $value = isset( $row->$field ) ? $row->$field : null;
-                       $formatted = strval( $this->formatValue( $field, $value ) );
-
-                       if ( $formatted == '' ) {
-                               $formatted = '&#160;';
-                       }
-
-                       $s .= Html::rawElement( 'td', $this->getCellAttrs( $field, $value ), $formatted ) . "\n";
-               }
-
-               $s .= Html::closeElement( 'tr' ) . "\n";
-
-               return $s;
-       }
-
-       /**
-        * Get a class name to be applied to the given row.
-        *
-        * @protected
-        *
-        * @param object $row The database result row
-        * @return string
-        */
-       function getRowClass( $row ) {
-               return '';
-       }
-
-       /**
-        * Get attributes to be applied to the given row.
-        *
-        * @protected
-        *
-        * @param object $row The database result row
-        * @return array Array of attribute => value
-        */
-       function getRowAttrs( $row ) {
-               $class = $this->getRowClass( $row );
-               if ( $class === '' ) {
-                       // Return an empty array to avoid clutter in HTML like class=""
-                       return array();
-               } else {
-                       return array( 'class' => $this->getRowClass( $row ) );
-               }
-       }
-
-       /**
-        * Get any extra attributes to be applied to the given cell. Don't
-        * take this as an excuse to hardcode styles; use classes and
-        * CSS instead.  Row context is available in $this->mCurrentRow
-        *
-        * @protected
-        *
-        * @param string $field The column
-        * @param string $value The cell contents
-        * @return array Array of attr => value
-        */
-       function getCellAttrs( $field, $value ) {
-               return array( 'class' => 'TablePager_col_' . $field );
-       }
-
-       /**
-        * @protected
-        * @return string
-        */
-       function getIndexField() {
-               return $this->mSort;
-       }
-
-       /**
-        * @protected
-        * @return string
-        */
-       function getTableClass() {
-               return 'TablePager';
-       }
-
-       /**
-        * @protected
-        * @return string
-        */
-       function getNavClass() {
-               return 'TablePager_nav';
-       }
-
-       /**
-        * @protected
-        * @return string
-        */
-       function getSortHeaderClass() {
-               return 'TablePager_sort';
-       }
-
-       /**
-        * A navigation bar with images
-        * @return string HTML
-        */
-       public function getNavigationBar() {
-               global $wgStylePath;
-
-               if ( !$this->isNavigationBarShown() ) {
-                       return '';
-               }
-
-               $path = "$wgStylePath/common/images";
-               $labels = array(
-                       'first' => 'table_pager_first',
-                       'prev' => 'table_pager_prev',
-                       'next' => 'table_pager_next',
-                       'last' => 'table_pager_last',
-               );
-               $images = array(
-                       'first' => 'arrow_first_25.png',
-                       'prev' => 'arrow_left_25.png',
-                       'next' => 'arrow_right_25.png',
-                       'last' => 'arrow_last_25.png',
-               );
-               $disabledImages = array(
-                       'first' => 'arrow_disabled_first_25.png',
-                       'prev' => 'arrow_disabled_left_25.png',
-                       'next' => 'arrow_disabled_right_25.png',
-                       'last' => 'arrow_disabled_last_25.png',
-               );
-               if ( $this->getLanguage()->isRTL() ) {
-                       $keys = array_keys( $labels );
-                       $images = array_combine( $keys, array_reverse( $images ) );
-                       $disabledImages = array_combine( $keys, array_reverse( $disabledImages ) );
-               }
-
-               $linkTexts = array();
-               $disabledTexts = array();
-               foreach ( $labels as $type => $label ) {
-                       $msgLabel = $this->msg( $label )->escaped();
-                       $linkTexts[$type] = Html::element( 'img', array( 'src' => "$path/{$images[$type]}",
-                               'alt' => $msgLabel ) ) . "<br />$msgLabel";
-                       $disabledTexts[$type] = Html::element( 'img', array( 'src' => "$path/{$disabledImages[$type]}",
-                               'alt' => $msgLabel ) ) . "<br />$msgLabel";
-               }
-               $links = $this->getPagingLinks( $linkTexts, $disabledTexts );
-
-               $s = Html::openElement( 'table', array( 'class' => $this->getNavClass() ) );
-               $s .= Html::openElement( 'tr' ) . "\n";
-               $width = 100 / count( $links ) . '%';
-               foreach ( $labels as $type => $label ) {
-                       $s .= Html::rawElement( 'td', array( 'style' => "width:$width;" ), $links[$type] ) . "\n";
-               }
-               $s .= Html::closeElement( 'tr' ) . Html::closeElement( 'table' ) . "\n";
-               return $s;
-       }
-
-       /**
-        * Get a "<select>" element which has options for each of the allowed limits
-        *
-        * @param string $attribs Extra attributes to set
-        * @return string HTML fragment
-        */
-       public function getLimitSelect( $attribs = array() ) {
-               $select = new XmlSelect( 'limit', false, $this->mLimit );
-               $select->addOptions( $this->getLimitSelectList() );
-               foreach ( $attribs as $name => $value ) {
-                       $select->setAttribute( $name, $value );
-               }
-               return $select->getHTML();
-       }
-
-       /**
-        * Get a list of items to show in a "<select>" element of limits.
-        * This can be passed directly to XmlSelect::addOptions().
-        *
-        * @since 1.22
-        * @return array
-        */
-       public function getLimitSelectList() {
-               # Add the current limit from the query string
-               # to avoid that the limit is lost after clicking Go next time
-               if ( !in_array( $this->mLimit, $this->mLimitsShown ) ) {
-                       $this->mLimitsShown[] = $this->mLimit;
-                       sort( $this->mLimitsShown );
-               }
-               $ret = array();
-               foreach ( $this->mLimitsShown as $key => $value ) {
-                       # The pair is either $index => $limit, in which case the $value
-                       # will be numeric, or $limit => $text, in which case the $value
-                       # will be a string.
-                       if ( is_int( $value ) ) {
-                               $limit = $value;
-                               $text = $this->getLanguage()->formatNum( $limit );
-                       } else {
-                               $limit = $key;
-                               $text = $value;
-                       }
-                       $ret[$text] = $limit;
-               }
-               return $ret;
-       }
-
-       /**
-        * Get \<input type="hidden"\> elements for use in a method="get" form.
-        * Resubmits all defined elements of the query string, except for a
-        * blacklist, passed in the $blacklist parameter.
-        *
-        * @param array $blacklist Parameters from the request query which should not be resubmitted
-        * @return string HTML fragment
-        */
-       function getHiddenFields( $blacklist = array() ) {
-               $blacklist = (array)$blacklist;
-               $query = $this->getRequest()->getQueryValues();
-               foreach ( $blacklist as $name ) {
-                       unset( $query[$name] );
-               }
-               $s = '';
-               foreach ( $query as $name => $value ) {
-                       $s .= Html::hidden( $name, $value ) . "\n";
-               }
-               return $s;
-       }
-
-       /**
-        * Get a form containing a limit selection dropdown
-        *
-        * @return string HTML fragment
-        */
-       function getLimitForm() {
-               global $wgScript;
-
-               return Html::rawElement(
-                       'form',
-                       array(
-                               'method' => 'get',
-                               'action' => $wgScript
-                       ),
-                       "\n" . $this->getLimitDropdown()
-               ) . "\n";
-       }
-
-       /**
-        * Gets a limit selection dropdown
-        *
-        * @return string
-        */
-       function getLimitDropdown() {
-               # Make the select with some explanatory text
-               $msgSubmit = $this->msg( 'table_pager_limit_submit' )->escaped();
-
-               return $this->msg( 'table_pager_limit' )
-                       ->rawParams( $this->getLimitSelect() )->escaped() .
-                       "\n<input type=\"submit\" value=\"$msgSubmit\"/>\n" .
-                       $this->getHiddenFields( array( 'limit' ) );
-       }
-
-       /**
-        * Return true if the named field should be sortable by the UI, false
-        * otherwise
-        *
-        * @param string $field
-        */
-       abstract function isFieldSortable( $field );
-
-       /**
-        * Format a table cell. The return value should be HTML, but use an empty
-        * string not &#160; for empty cells. Do not include the <td> and </td>.
-        *
-        * The current result row is available as $this->mCurrentRow, in case you
-        * need more context.
-        *
-        * @protected
-        *
-        * @param string $name The database field name
-        * @param string $value The value retrieved from the database
-        */
-       abstract function formatValue( $name, $value );
-
-       /**
-        * The database field name used as a default sort order.
-        *
-        * @protected
-        *
-        * @return string
-        */
-       abstract function getDefaultSort();
-
-       /**
-        * An array mapping database field names to a textual description of the
-        * field name, for use in the table header. The description should be plain
-        * text, it will be HTML-escaped later.
-        *
-        * @return array
-        */
-       abstract function getFieldNames();
-}
index f884ec3..e0d5ed7 100644 (file)
@@ -98,9 +98,22 @@ class Preferences {
 
                wfRunHooks( 'GetPreferences', array( $user, &$defaultPreferences ) );
 
+               self::loadPreferenceValues( $user, $context, $defaultPreferences );
+               self::$defaultPreferences = $defaultPreferences;
+               return $defaultPreferences;
+       }
+
+       /**
+        * Loads existing values for a given array of preferences
+        * @throws MWException
+        * @param User $user
+        * @param IContextSource $context
+        * @param array $defaultPreferences Array to load values for
+        * @return array|null
+        */
+       static function loadPreferenceValues( $user, $context, &$defaultPreferences ) {
                ## Remove preferences that wikis don't want to use
-               global $wgHiddenPrefs;
-               foreach ( $wgHiddenPrefs as $pref ) {
+               foreach ( $context->getConfig()->get( 'HiddenPrefs' ) as $pref ) {
                        if ( isset( $defaultPreferences[$pref] ) ) {
                                unset( $defaultPreferences[$pref] );
                        }
@@ -138,8 +151,6 @@ class Preferences {
                        }
                }
 
-               self::$defaultPreferences = $defaultPreferences;
-
                return $defaultPreferences;
        }
 
@@ -195,12 +206,9 @@ class Preferences {
         * @return void
         */
        static function profilePreferences( $user, IContextSource $context, &$defaultPreferences ) {
-               global $wgAuth, $wgContLang, $wgParser, $wgCookieExpiration, $wgLanguageCode,
-                       $wgDisableLangConversion, $wgMaxSigChars,
-                       $wgEnableEmail, $wgEmailConfirmToEdit, $wgEnableUserEmail, $wgEmailAuthentication,
-                       $wgEnotifWatchlist, $wgEnotifUserTalk, $wgEnotifRevealEditorAddress,
-                       $wgSecureLogin;
+               global $wgAuth, $wgContLang, $wgParser;
 
+               $config = $context->getConfig();
                // retrieving user name for GENDER and misc.
                $userName = $user->getName();
 
@@ -298,7 +306,7 @@ class Preferences {
                        );
                }
                // Only show prefershttps if secure login is turned on
-               if ( $wgSecureLogin && wfCanIPUseHTTPS( $context->getRequest()->getIP() ) ) {
+               if ( $config->get( 'SecureLogin' ) && wfCanIPUseHTTPS( $context->getRequest()->getIP() ) ) {
                        $defaultPreferences['prefershttps'] = array(
                                'type' => 'toggle',
                                'label-message' => 'tog-prefershttps',
@@ -309,8 +317,9 @@ class Preferences {
 
                // Language
                $languages = Language::fetchLanguageNames( null, 'mw' );
-               if ( !array_key_exists( $wgLanguageCode, $languages ) ) {
-                       $languages[$wgLanguageCode] = $wgLanguageCode;
+               $languageCode = $config->get( 'LanguageCode' );
+               if ( !array_key_exists( $languageCode, $languages ) ) {
+                       $languages[$languageCode] = $languageCode;
                }
                ksort( $languages );
 
@@ -341,7 +350,7 @@ class Preferences {
                );
 
                // see if there are multiple language variants to choose from
-               if ( !$wgDisableLangConversion ) {
+               if ( !$config->get( 'DisableLangConversion' ) ) {
                        foreach ( LanguageConverter::$languagesWithVariants as $langCode ) {
                                if ( $langCode == $wgContLang->getCode() ) {
                                        $variants = $wgContLang->getVariants();
@@ -406,7 +415,7 @@ class Preferences {
                );
                $defaultPreferences['nickname'] = array(
                        'type' => $wgAuth->allowPropChange( 'nickname' ) ? 'text' : 'info',
-                       'maxlength' => $wgMaxSigChars,
+                       'maxlength' => $config->get( 'MaxSigChars' ),
                        'label-message' => 'yournick',
                        'validation-callback' => array( 'Preferences', 'validateSignature' ),
                        'section' => 'personal/signature',
@@ -422,13 +431,13 @@ class Preferences {
 
                ## Email stuff
 
-               if ( $wgEnableEmail ) {
+               if ( $config->get( 'EnableEmail' ) ) {
                        if ( $canViewPrivateInfo ) {
-                               $helpMessages[] = $wgEmailConfirmToEdit
+                               $helpMessages[] = $config->get( 'EmailConfirmToEdit' )
                                                ? 'prefs-help-email-required'
                                                : 'prefs-help-email';
 
-                               if ( $wgEnableUserEmail ) {
+                               if ( $config->get( 'EnableUserEmail' ) ) {
                                        // additional messages when users can send email to each other
                                        $helpMessages[] = 'prefs-help-email-others';
                                }
@@ -460,7 +469,7 @@ class Preferences {
 
                        $disableEmailPrefs = false;
 
-                       if ( $wgEmailAuthentication ) {
+                       if ( $config->get( 'EmailAuthentication' ) ) {
                                $emailauthenticationclass = 'mw-email-not-authenticated';
                                if ( $user->getEmail() ) {
                                        if ( $user->getEmailAuthenticationTimestamp() ) {
@@ -505,7 +514,7 @@ class Preferences {
                                }
                        }
 
-                       if ( $wgEnableUserEmail && $user->isAllowed( 'sendemail' ) ) {
+                       if ( $config->get( 'EnableUserEmail' ) && $user->isAllowed( 'sendemail' ) ) {
                                $defaultPreferences['disablemail'] = array(
                                        'type' => 'toggle',
                                        'invert' => true,
@@ -521,7 +530,7 @@ class Preferences {
                                );
                        }
 
-                       if ( $wgEnotifWatchlist ) {
+                       if ( $config->get( 'EnotifWatchlist' ) ) {
                                $defaultPreferences['enotifwatchlistpages'] = array(
                                        'type' => 'toggle',
                                        'section' => 'personal/email',
@@ -529,7 +538,7 @@ class Preferences {
                                        'disabled' => $disableEmailPrefs,
                                );
                        }
-                       if ( $wgEnotifUserTalk ) {
+                       if ( $config->get( 'EnotifUserTalk' ) ) {
                                $defaultPreferences['enotifusertalkpages'] = array(
                                        'type' => 'toggle',
                                        'section' => 'personal/email',
@@ -537,7 +546,7 @@ class Preferences {
                                        'disabled' => $disableEmailPrefs,
                                );
                        }
-                       if ( $wgEnotifUserTalk || $wgEnotifWatchlist ) {
+                       if ( $config->get( 'EnotifUserTalk' ) || $config->get( 'EnotifWatchlist' ) ) {
                                $defaultPreferences['enotifminoredits'] = array(
                                        'type' => 'toggle',
                                        'section' => 'personal/email',
@@ -545,7 +554,7 @@ class Preferences {
                                        'disabled' => $disableEmailPrefs,
                                );
 
-                               if ( $wgEnotifRevealEditorAddress ) {
+                               if ( $config->get( 'EnotifRevealEditorAddress' ) ) {
                                        $defaultPreferences['enotifrevealaddr'] = array(
                                                'type' => 'toggle',
                                                'section' => 'personal/email',
@@ -565,28 +574,34 @@ class Preferences {
         */
        static function skinPreferences( $user, IContextSource $context, &$defaultPreferences ) {
                ## Skin #####################################
-               global $wgAllowUserCss, $wgAllowUserJs;
 
-               $defaultPreferences['skin'] = array(
-                       'type' => 'radio',
-                       'options' => self::generateSkinOptions( $user, $context ),
-                       'label' => '&#160;',
-                       'section' => 'rendering/skin',
-               );
+               // Skin selector, if there is at least one valid skin
+               $skinOptions = self::generateSkinOptions( $user, $context );
+               if ( $skinOptions ) {
+                       $defaultPreferences['skin'] = array(
+                               'type' => 'radio',
+                               'options' => $skinOptions,
+                               'label' => '&#160;',
+                               'section' => 'rendering/skin',
+                       );
+               }
 
+               $config = $context->getConfig();
+               $allowUserCss = $config->get( 'AllowUserCss' );
+               $allowUserJs = $config->get( 'AllowUserJs' );
                # Create links to user CSS/JS pages for all skins
                # This code is basically copied from generateSkinOptions().  It'd
                # be nice to somehow merge this back in there to avoid redundancy.
-               if ( $wgAllowUserCss || $wgAllowUserJs ) {
+               if ( $allowUserCss || $allowUserJs ) {
                        $linkTools = array();
                        $userName = $user->getName();
 
-                       if ( $wgAllowUserCss ) {
+                       if ( $allowUserCss ) {
                                $cssPage = Title::makeTitleSafe( NS_USER, $userName . '/common.css' );
                                $linkTools[] = Linker::link( $cssPage, $context->msg( 'prefs-custom-css' )->escaped() );
                        }
 
-                       if ( $wgAllowUserJs ) {
+                       if ( $allowUserJs ) {
                                $jsPage = Title::makeTitleSafe( NS_USER, $userName . '/common.js' );
                                $linkTools[] = Linker::link( $jsPage, $context->msg( 'prefs-custom-js' )->escaped() );
                        }
@@ -714,8 +729,7 @@ class Preferences {
                );
 
                ## Page Rendering ##############################
-               global $wgAllowUserCssPrefs;
-               if ( $wgAllowUserCssPrefs ) {
+               if ( $context->getConfig()->get( 'AllowUserCssPrefs' ) ) {
                        $defaultPreferences['underline'] = array(
                                'type' => 'select',
                                'options' => array(
@@ -738,7 +752,6 @@ class Preferences {
                        'type' => 'select',
                        'section' => 'rendering/advancedrendering',
                        'options' => $stubThresholdOptions,
-                       'size' => 20,
                        'label-raw' => $context->msg( 'stub-threshold' )->text(), // Raw HTML message. Yay?
                );
 
@@ -761,8 +774,6 @@ class Preferences {
         * @param array $defaultPreferences
         */
        static function editingPreferences( $user, IContextSource $context, &$defaultPreferences ) {
-               global $wgAllowUserCssPrefs;
-
                ## Editing #####################################
                $defaultPreferences['editsectiononrightclick'] = array(
                        'type' => 'toggle',
@@ -775,7 +786,7 @@ class Preferences {
                        'label-message' => 'tog-editondblclick',
                );
 
-               if ( $wgAllowUserCssPrefs ) {
+               if ( $context->getConfig()->get( 'AllowUserCssPrefs' ) ) {
                        $defaultPreferences['editfont'] = array(
                                'type' => 'select',
                                'section' => 'editing/editor',
@@ -849,17 +860,17 @@ class Preferences {
         * @param array $defaultPreferences
         */
        static function rcPreferences( $user, IContextSource $context, &$defaultPreferences ) {
-               global $wgRCMaxAge, $wgRCShowWatchingUsers;
-
+               $config = $context->getConfig();
+               $rcMaxAge = $config->get( 'RCMaxAge' );
                ## RecentChanges #####################################
                $defaultPreferences['rcdays'] = array(
                        'type' => 'float',
                        'label-message' => 'recentchangesdays',
                        'section' => 'rc/displayrc',
                        'min' => 1,
-                       'max' => ceil( $wgRCMaxAge / ( 3600 * 24 ) ),
+                       'max' => ceil( $rcMaxAge / ( 3600 * 24 ) ),
                        'help' => $context->msg( 'recentchangesdays-max' )->numParams(
-                               ceil( $wgRCMaxAge / ( 3600 * 24 ) ) )->text()
+                               ceil( $rcMaxAge / ( 3600 * 24 ) ) )->text()
                );
                $defaultPreferences['rclimit'] = array(
                        'type' => 'int',
@@ -891,7 +902,7 @@ class Preferences {
                        );
                }
 
-               if ( $wgRCShowWatchingUsers ) {
+               if ( $config->get( 'RCShowWatchingUsers' ) ) {
                        $defaultPreferences['shownumberswatching'] = array(
                                'type' => 'toggle',
                                'section' => 'rc/advancedrc',
@@ -906,9 +917,8 @@ class Preferences {
         * @param array $defaultPreferences
         */
        static function watchlistPreferences( $user, IContextSource $context, &$defaultPreferences ) {
-               global $wgUseRCPatrol, $wgEnableAPI, $wgRCMaxAge;
-
-               $watchlistdaysMax = ceil( $wgRCMaxAge / ( 3600 * 24 ) );
+               $config = $context->getConfig();
+               $watchlistdaysMax = ceil( $config->get( 'RCMaxAge' ) / ( 3600 * 24 ) );
 
                ## Watchlist #####################################
                $defaultPreferences['watchlistdays'] = array(
@@ -959,7 +969,7 @@ class Preferences {
                        'label-message' => 'tog-watchlisthideliu',
                );
 
-               if ( $wgUseRCPatrol ) {
+               if ( $context->getConfig()->get( 'UseRCPatrol' ) ) {
                        $defaultPreferences['watchlisthidepatrolled'] = array(
                                'type' => 'toggle',
                                'section' => 'watchlist/advancedwatchlist',
@@ -978,10 +988,15 @@ class Preferences {
                        $watchTypes['read'] = 'watchcreations';
                }
 
+               if ( $user->isAllowed( 'rollback' ) ) {
+                       $watchTypes['rollback'] = 'watchrollback';
+               }
+
                foreach ( $watchTypes as $action => $pref ) {
                        if ( $user->isAllowed( $action ) ) {
                                // Messages:
                                // tog-watchdefault, tog-watchmoves, tog-watchdeletion, tog-watchcreations
+                               // tog-watchrollback
                                $defaultPreferences[$pref] = array(
                                        'type' => 'toggle',
                                        'section' => 'watchlist/advancedwatchlist',
@@ -990,7 +1005,7 @@ class Preferences {
                        }
                }
 
-               if ( $wgEnableAPI ) {
+               if ( $config->get( 'EnableAPI' ) ) {
                        $defaultPreferences['watchlisttoken'] = array(
                                'type' => 'api',
                        );
@@ -1011,7 +1026,7 @@ class Preferences {
         */
        static function searchPreferences( $user, IContextSource $context, &$defaultPreferences ) {
                foreach ( MWNamespace::getValidNamespaces() as $n ) {
-                       $defaultPreferences[ 'searchNs' . $n ] = array(
+                       $defaultPreferences['searchNs' . $n] = array(
                                'type' => 'api',
                        );
                }
@@ -1029,7 +1044,6 @@ class Preferences {
         * @return array Text/links to display as key; $skinkey as value
         */
        static function generateSkinOptions( $user, IContextSource $context ) {
-               global $wgDefaultSkin, $wgAllowUserCss, $wgAllowUserJs;
                $ret = array();
 
                $mptitle = Title::newMainPage();
@@ -1048,12 +1062,19 @@ class Preferences {
                }
                asort( $validSkinNames );
 
+               $config = $context->getConfig();
+               $defaultSkin = $config->get( 'DefaultSkin' );
+               $allowUserCss = $config->get( 'AllowUserCss' );
+               $allowUserJs = $config->get( 'AllowUserJs' );
+
+               $foundDefault = false;
                foreach ( $validSkinNames as $skinkey => $sn ) {
                        $linkTools = array();
 
                        # Mark the default skin
-                       if ( $skinkey == $wgDefaultSkin ) {
+                       if ( $skinkey == $defaultSkin ) {
                                $linkTools[] = $context->msg( 'default' )->escaped();
+                               $foundDefault = true;
                        }
 
                        # Create preview link
@@ -1061,12 +1082,12 @@ class Preferences {
                        $linkTools[] = "<a target='_blank' href=\"$mplink\">$previewtext</a>";
 
                        # Create links to user CSS/JS pages
-                       if ( $wgAllowUserCss ) {
+                       if ( $allowUserCss ) {
                                $cssPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/' . $skinkey . '.css' );
                                $linkTools[] = Linker::link( $cssPage, $context->msg( 'prefs-custom-css' )->escaped() );
                        }
 
-                       if ( $wgAllowUserJs ) {
+                       if ( $allowUserJs ) {
                                $jsPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/' . $skinkey . '.js' );
                                $linkTools[] = Linker::link( $jsPage, $context->msg( 'prefs-custom-js' )->escaped() );
                        }
@@ -1078,6 +1099,12 @@ class Preferences {
                        $ret[$display] = $skinkey;
                }
 
+               if ( !$foundDefault ) {
+                       // If the default skin is not available, things are going to break horribly because the
+                       // default value for skin selector will not be a valid value. Let's just not show it then.
+                       return array();
+               }
+
                return $ret;
        }
 
@@ -1097,7 +1124,7 @@ class Preferences {
                                                                                // Bug 19237
                        }
 
-                       // KLUGE: site default might not be valid for user language
+                       // FIXME KLUGE: site default might not be valid for user language
                        global $wgDefaultUserOptions;
                        if ( !in_array( $wgDefaultUserOptions['date'], $dateopts ) ) {
                                $wgDefaultUserOptions['date'] = 'default';
@@ -1121,12 +1148,10 @@ class Preferences {
         * @return array
         */
        static function getImageSizes( IContextSource $context ) {
-               global $wgImageLimits;
-
                $ret = array();
                $pixels = $context->msg( 'unit-pixel' )->text();
 
-               foreach ( $wgImageLimits as $index => $limits ) {
+               foreach ( $context->getConfig()->get( 'ImageLimits' ) as $index => $limits ) {
                        $display = "{$limits[0]}×{$limits[1]}" . $pixels;
                        $ret[$display] = $index;
                }
@@ -1139,12 +1164,10 @@ class Preferences {
         * @return array
         */
        static function getThumbSizes( IContextSource $context ) {
-               global $wgThumbLimits;
-
                $ret = array();
                $pixels = $context->msg( 'unit-pixel' )->text();
 
-               foreach ( $wgThumbLimits as $index => $size ) {
+               foreach ( $context->getConfig()->get( 'ThumbLimits' ) as $index => $size ) {
                        $display = $size . $pixels;
                        $ret[$display] = $index;
                }
@@ -1159,10 +1182,11 @@ class Preferences {
         * @return bool|string
         */
        static function validateSignature( $signature, $alldata, $form ) {
-               global $wgParser, $wgMaxSigChars;
-               if ( mb_strlen( $signature ) > $wgMaxSigChars ) {
+               global $wgParser;
+               $maxSigChars = $form->getConfig()->get( 'MaxSigChars' );
+               if ( mb_strlen( $signature ) > $maxSigChars ) {
                        return Xml::element( 'span', array( 'class' => 'error' ),
-                               $form->msg( 'badsiglength' )->numParams( $wgMaxSigChars )->text() );
+                               $form->msg( 'badsiglength' )->numParams( $maxSigChars )->text() );
                } elseif ( isset( $alldata['fancysig'] ) &&
                                $alldata['fancysig'] &&
                                $wgParser->validateSig( $signature ) === false
@@ -1244,10 +1268,10 @@ class Preferences {
        static function getTimezoneOptions( IContextSource $context ) {
                $opt = array();
 
-               global $wgLocalTZoffset;
+               $localTZoffset = $context->getConfig()->get( 'LocalTZoffset' );
                $timestamp = MWTimestamp::getLocalInstance();
-               // Check that $wgLocalTZoffset is the same as the local time zone offset
-               if ( $wgLocalTZoffset == $timestamp->format( 'Z' ) / 60 ) {
+               // Check that the LocalTZoffset is the same as the local time zone offset
+               if ( $localTZoffset == $timestamp->format( 'Z' ) / 60 ) {
                        $server_tz_msg = $context->msg(
                                'timezoneuseserverdefault',
                                $timestamp->getTimezone()->getName()
@@ -1255,12 +1279,12 @@ class Preferences {
                } else {
                        $tzstring = sprintf(
                                '%+03d:%02d',
-                               floor( $wgLocalTZoffset / 60 ),
-                               abs( $wgLocalTZoffset ) % 60
+                               floor( $localTZoffset / 60 ),
+                               abs( $localTZoffset ) % 60
                        );
                        $server_tz_msg = $context->msg( 'timezoneuseserverdefault', $tzstring )->text();
                }
-               $opt[$server_tz_msg] = "System|$wgLocalTZoffset";
+               $opt[$server_tz_msg] = "System|$localTZoffset";
                $opt[$context->msg( 'timezoneuseoffset' )->text()] = 'other';
                $opt[$context->msg( 'guesstimezone' )->text()] = 'guess';
 
@@ -1360,9 +1384,10 @@ class Preferences {
         * @return bool|Status|string
         */
        static function tryFormSubmit( $formData, $form ) {
-               global $wgHiddenPrefs, $wgAuth;
+               global $wgAuth;
 
                $user = $form->getModifiedUser();
+               $hiddenPrefs = $form->getConfig()->get( 'HiddenPrefs' );
                $result = true;
 
                if ( !$user->isAllowedAny( 'editmyprivateinfo', 'editmyoptions' ) ) {
@@ -1379,7 +1404,7 @@ class Preferences {
 
                // Fortunately, the realname field is MUCH simpler
                // (not really "private", but still shouldn't be edited without permission)
-               if ( !in_array( 'realname', $wgHiddenPrefs )
+               if ( !in_array( 'realname', $hiddenPrefs )
                        && $user->isAllowed( 'editmyprivateinfo' )
                        && array_key_exists( 'realname', $formData )
                ) {
@@ -1395,7 +1420,7 @@ class Preferences {
                        # If users have saved a value for a preference which has subsequently been disabled
                        # via $wgHiddenPrefs, we don't want to destroy that setting in case the preference
                        # is subsequently re-enabled
-                       foreach ( $wgHiddenPrefs as $pref ) {
+                       foreach ( $hiddenPrefs as $pref ) {
                                # If the user has not set a non-default value here, the default will be returned
                                # and subsequently discarded
                                $formData[$pref] = $user->getOption( $pref, null, true );
index 13696ad..295183c 100644 (file)
@@ -29,7 +29,7 @@
 abstract class PrefixSearch {
        /**
         * Do a prefix search of titles and return a list of matching page names.
-        * @deprecated: Since 1.23, use TitlePrefixSearch or StringPrefixSearch classes
+        * @deprecated Since 1.23, use TitlePrefixSearch or StringPrefixSearch classes
         *
         * @param string $search
         * @param int $limit
@@ -166,12 +166,17 @@ abstract class PrefixSearch {
        protected function specialSearch( $search, $limit ) {
                global $wgContLang;
 
-               list( $searchKey, $subpageSearch ) = explode( '/', $search, 2 );
+               $searchParts = explode( '/', $search, 2 );
+               $searchKey = $searchParts[0];
+               $subpageSearch = isset( $searchParts[1] ) ? $searchParts[1] : null;
 
                // Handle subpage search separately.
                if ( $subpageSearch !== null ) {
                        // Try matching the full search string as a page name
                        $specialTitle = Title::makeTitleSafe( NS_SPECIAL, $searchKey );
+                       if ( !$specialTitle ) {
+                               return array();
+                       }
                        $special = SpecialPageFactory::getPage( $specialTitle->getText() );
                        if ( $special ) {
                                $subpages = $special->prefixSearchSubpages( $subpageSearch, $limit );
index 456e4e6..35352d6 100644 (file)
@@ -57,16 +57,21 @@ class ProtectionForm {
        /** @var array Map of action to the expiry time of the existing protection */
        protected $mExistingExpiry = array();
 
-       function __construct( Page $article ) {
-               global $wgUser;
+       /** @var IContextSource */
+       private $mContext;
+
+       function __construct( Article $article ) {
                // Set instance variables.
                $this->mArticle = $article;
                $this->mTitle = $article->getTitle();
                $this->mApplicableTypes = $this->mTitle->getRestrictionTypes();
+               $this->mContext = $article->getContext();
 
                // Check if the form should be disabled.
                // If it is, the form will be available in read-only to show levels.
-               $this->mPermErrors = $this->mTitle->getUserPermissionsErrors( 'protect', $wgUser );
+               $this->mPermErrors = $this->mTitle->getUserPermissionsErrors(
+                       'protect', $this->mContext->getUser()
+               );
                if ( wfReadOnly() ) {
                        $this->mPermErrors[] = array( 'readonlytext', wfReadOnlyReason() );
                }
@@ -82,14 +87,15 @@ class ProtectionForm {
         * Loads the current state of protection into the object.
         */
        function loadData() {
-               global $wgRequest, $wgUser;
-
-               $levels = MWNamespace::getRestrictionLevels( $this->mTitle->getNamespace(), $wgUser );
+               $levels = MWNamespace::getRestrictionLevels(
+                       $this->mTitle->getNamespace(), $this->mContext->getUser()
+               );
                $this->mCascade = $this->mTitle->areRestrictionsCascading();
 
-               $this->mReason = $wgRequest->getText( 'mwProtect-reason' );
-               $this->mReasonSelection = $wgRequest->getText( 'wpProtectReasonSelection' );
-               $this->mCascade = $wgRequest->getBool( 'mwProtect-cascade', $this->mCascade );
+               $request = $this->mContext->getRequest();
+               $this->mReason = $request->getText( 'mwProtect-reason' );
+               $this->mReasonSelection = $request->getText( 'wpProtectReasonSelection' );
+               $this->mCascade = $request->getBool( 'mwProtect-cascade', $this->mCascade );
 
                foreach ( $this->mApplicableTypes as $action ) {
                        // @todo FIXME: This form currently requires individual selections,
@@ -106,8 +112,8 @@ class ProtectionForm {
                        }
                        $this->mExistingExpiry[$action] = $existingExpiry;
 
-                       $requestExpiry = $wgRequest->getText( "mwProtect-expiry-$action" );
-                       $requestExpirySelection = $wgRequest->getVal( "wpProtectExpirySelection-$action" );
+                       $requestExpiry = $request->getText( "mwProtect-expiry-$action" );
+                       $requestExpirySelection = $request->getVal( "wpProtectExpirySelection-$action" );
 
                        if ( $requestExpiry ) {
                                // Custom expiry takes precedence
@@ -128,7 +134,7 @@ class ProtectionForm {
                                $this->mExpirySelection[$action] = 'infinite';
                        }
 
-                       $val = $wgRequest->getVal( "mwProtect-level-$action" );
+                       $val = $request->getVal( "mwProtect-level-$action" );
                        if ( isset( $val ) && in_array( $val, $levels ) ) {
                                $this->mRestrictions[$action] = $val;
                        }
@@ -170,16 +176,14 @@ class ProtectionForm {
         * Main entry point for action=protect and action=unprotect
         */
        function execute() {
-               global $wgRequest, $wgOut;
-
                if ( MWNamespace::getRestrictionLevels( $this->mTitle->getNamespace() ) === array( '' ) ) {
                        throw new ErrorPageError( 'protect-badnamespace-title', 'protect-badnamespace-text' );
                }
 
-               if ( $wgRequest->wasPosted() ) {
+               if ( $this->mContext->getRequest()->wasPosted() ) {
                        if ( $this->save() ) {
                                $q = $this->mArticle->isRedirect() ? 'redirect=no' : '';
-                               $wgOut->redirect( $this->mTitle->getFullURL( $q ) );
+                               $this->mContext->getOutput()->redirect( $this->mTitle->getFullURL( $q ) );
                        }
                } else {
                        $this->show();
@@ -192,28 +196,27 @@ class ProtectionForm {
         * @param string $err Error message or null if there's no error
         */
        function show( $err = null ) {
-               global $wgOut;
-
-               $wgOut->setRobotPolicy( 'noindex,nofollow' );
-               $wgOut->addBacklinkSubtitle( $this->mTitle );
+               $out = $this->mContext->getOutput();
+               $out->setRobotPolicy( 'noindex,nofollow' );
+               $out->addBacklinkSubtitle( $this->mTitle );
 
                if ( is_array( $err ) ) {
-                       $wgOut->wrapWikiMsg( "<p class='error'>\n$1\n</p>\n", $err );
+                       $out->wrapWikiMsg( "<p class='error'>\n$1\n</p>\n", $err );
                } elseif ( is_string( $err ) ) {
-                       $wgOut->addHTML( "<p class='error'>{$err}</p>\n" );
+                       $out->addHTML( "<p class='error'>{$err}</p>\n" );
                }
 
                if ( $this->mTitle->getRestrictionTypes() === array() ) {
                        // No restriction types available for the current title
                        // this might happen if an extension alters the available types
-                       $wgOut->setPageTitle( wfMessage(
+                       $out->setPageTitle( wfMessage(
                                'protect-norestrictiontypes-title',
                                $this->mTitle->getPrefixedText()
                        ) );
-                       $wgOut->addWikiText( wfMessage( 'protect-norestrictiontypes-text' )->text() );
+                       $out->addWikiText( wfMessage( 'protect-norestrictiontypes-text' )->text() );
 
                        // Show the log in case protection was possible once
-                       $this->showLogExtract( $wgOut );
+                       $this->showLogExtract( $out );
                        // return as there isn't anything else we can do
                        return;
                }
@@ -227,7 +230,7 @@ class ProtectionForm {
                        }
 
                        /** @todo FIXME: i18n issue, should use formatted number. */
-                       $wgOut->wrapWikiMsg(
+                       $out->wrapWikiMsg(
                                "<div id=\"mw-protect-cascadeon\">\n$1\n" . $titles . "</div>",
                                array( 'protect-cascadeon', count( $cascadeSources ) )
                        );
@@ -236,19 +239,19 @@ class ProtectionForm {
                # Show an appropriate message if the user isn't allowed or able to change
                # the protection settings at this time
                if ( $this->disabled ) {
-                       $wgOut->setPageTitle(
+                       $out->setPageTitle(
                                wfMessage( 'protect-title-notallowed',
                                        $this->mTitle->getPrefixedText() )
                        );
-                       $wgOut->addWikiText( $wgOut->formatPermissionsErrorMessage( $this->mPermErrors, 'protect' ) );
+                       $out->addWikiText( $out->formatPermissionsErrorMessage( $this->mPermErrors, 'protect' ) );
                } else {
-                       $wgOut->setPageTitle( wfMessage( 'protect-title', $this->mTitle->getPrefixedText() ) );
-                       $wgOut->addWikiMsg( 'protect-text',
+                       $out->setPageTitle( wfMessage( 'protect-title', $this->mTitle->getPrefixedText() ) );
+                       $out->addWikiMsg( 'protect-text',
                                wfEscapeWikiText( $this->mTitle->getPrefixedText() ) );
                }
 
-               $wgOut->addHTML( $this->buildForm() );
-               $this->showLogExtract( $wgOut );
+               $out->addHTML( $this->buildForm() );
+               $this->showLogExtract( $out );
        }
 
        /**
@@ -257,16 +260,17 @@ class ProtectionForm {
         * @return bool Success
         */
        function save() {
-               global $wgRequest, $wgUser, $wgOut;
-
                # Permission check!
                if ( $this->disabled ) {
                        $this->show();
                        return false;
                }
 
-               $token = $wgRequest->getVal( 'wpEditToken' );
-               if ( !$wgUser->matchEditToken( $token, array( 'protect', $this->mTitle->getPrefixedDBkey() ) ) ) {
+               $request = $this->mContext->getRequest();
+               $user = $this->mContext->getUser();
+               $out = $this->mContext->getOutput();
+               $token = $request->getVal( 'wpEditToken' );
+               if ( !$user->matchEditToken( $token, array( 'protect', $this->mTitle->getPrefixedDBkey() ) ) ) {
                        $this->show( array( 'sessionfailure' ) );
                        return false;
                }
@@ -295,18 +299,18 @@ class ProtectionForm {
                        }
                }
 
-               $this->mCascade = $wgRequest->getBool( 'mwProtect-cascade' );
+               $this->mCascade = $request->getBool( 'mwProtect-cascade' );
 
                $status = $this->mArticle->doUpdateRestrictions(
                        $this->mRestrictions,
                        $expiry,
                        $this->mCascade,
                        $reasonstr,
-                       $wgUser
+                       $user
                );
 
                if ( !$status->isOK() ) {
-                       $this->show( $wgOut->parseInline( $status->getWikiText() ) );
+                       $this->show( $out->parseInline( $status->getWikiText() ) );
                        return false;
                }
 
@@ -327,7 +331,7 @@ class ProtectionForm {
                        return false;
                }
 
-               WatchAction::doWatchOrUnwatch( $wgRequest->getCheck( 'mwProtectWatch' ), $this->mTitle, $wgUser );
+               WatchAction::doWatchOrUnwatch( $request->getCheck( 'mwProtectWatch' ), $this->mTitle, $user );
 
                return true;
        }
@@ -338,23 +342,17 @@ class ProtectionForm {
         * @return string HTML form
         */
        function buildForm() {
-               global $wgUser, $wgLang, $wgOut;
-
-               $mProtectreasonother = Xml::label(
-                       wfMessage( 'protectcomment' )->text(),
-                       'wpProtectReasonSelection'
-               );
-               $mProtectreason = Xml::label(
-                       wfMessage( 'protect-otherreason' )->text(),
-                       'mwProtect-reason'
-               );
-
+               $user = $this->mContext->getUser();
+               $output = $this->mContext->getOutput();
+               $lang = $this->mContext->getLanguage();
+               $cascadingRestrictionLevels = $this->mContext->getConfig()->get( 'CascadingRestrictionLevels' );
                $out = '';
                if ( !$this->disabled ) {
-                       $wgOut->addModules( 'mediawiki.legacy.protect' );
+                       $output->addModules( 'mediawiki.legacy.protect' );
+                       $output->addJsConfigVars( 'wgCascadeableLevels', $cascadingRestrictionLevels );
                        $out .= Xml::openElement( 'form', array( 'method' => 'post',
                                'action' => $this->mTitle->getLocalURL( 'action=protect' ),
-                               'id' => 'mw-Protect-Form', 'onsubmit' => 'ProtectionForm.enableUnchainedInputs(true)' ) );
+                               'id' => 'mw-Protect-Form' ) );
                }
 
                $out .= Xml::openElement( 'fieldset' ) .
@@ -362,6 +360,9 @@ class ProtectionForm {
                        Xml::openElement( 'table', array( 'id' => 'mwProtectSet' ) ) .
                        Xml::openElement( 'tbody' );
 
+               $scExpiryOptions = wfMessage( 'protect-expiry-options' )->inContentLanguage()->text();
+               $showProtectOptions = $scExpiryOptions !== '-' && !$this->disabled;
+
                // Not all languages have V_x <-> N_x relation
                foreach ( $this->mRestrictions as $action => $selected ) {
                        // Messages:
@@ -373,15 +374,6 @@ class ProtectionForm {
                        Xml::openElement( 'table', array( 'id' => "mw-protect-table-$action" ) ) .
                                "<tr><td>" . $this->buildSelector( $action, $selected ) . "</td></tr><tr><td>";
 
-                       $reasonDropDown = Xml::listDropDown( 'wpProtectReasonSelection',
-                               wfMessage( 'protect-dropdown' )->inContentLanguage()->text(),
-                               wfMessage( 'protect-otherreason-op' )->inContentLanguage()->text(),
-                               $this->mReasonSelection,
-                               'mwProtect-reason', 4 );
-                       $scExpiryOptions = wfMessage( 'protect-expiry-options' )->inContentLanguage()->text();
-
-                       $showProtectOptions = $scExpiryOptions !== '-' && !$this->disabled;
-
                        $mProtectexpiry = Xml::label(
                                wfMessage( 'protectexpiry' )->text(),
                                "mwProtectExpirySelection-$action"
@@ -393,9 +385,9 @@ class ProtectionForm {
 
                        $expiryFormOptions = '';
                        if ( $this->mExistingExpiry[$action] && $this->mExistingExpiry[$action] != 'infinity' ) {
-                               $timestamp = $wgLang->timeanddate( $this->mExistingExpiry[$action], true );
-                               $d = $wgLang->date( $this->mExistingExpiry[$action], true );
-                               $t = $wgLang->time( $this->mExistingExpiry[$action], true );
+                               $timestamp = $lang->timeanddate( $this->mExistingExpiry[$action], true );
+                               $d = $lang->date( $this->mExistingExpiry[$action], true );
+                               $t = $lang->time( $this->mExistingExpiry[$action], true );
                                $expiryFormOptions .=
                                        Xml::option(
                                                wfMessage( 'protect-existing-expiry', $timestamp, $d, $t )->text(),
@@ -434,16 +426,13 @@ class ProtectionForm {
                                                                array(
                                                                        'id' => "mwProtectExpirySelection-$action",
                                                                        'name' => "wpProtectExpirySelection-$action",
-                                                                       'onchange' => "ProtectionForm.updateExpiryList(this)",
                                                                        'tabindex' => '2' ) + $this->disabledAttrib,
                                                                $expiryFormOptions ) .
                                                "</td>
                                        </tr></table>";
                        }
                        # Add custom expiry field
-                       $attribs = array( 'id' => "mwProtect-$action-expires",
-                               'onkeyup' => 'ProtectionForm.updateExpiry(this)',
-                               'onchange' => 'ProtectionForm.updateExpiry(this)' ) + $this->disabledAttrib;
+                       $attribs = array( 'id' => "mwProtect-$action-expires" ) + $this->disabledAttrib;
                        $out .= "<table><tr>
                                        <td class='mw-label'>" .
                                                $mProtectother .
@@ -482,6 +471,22 @@ class ProtectionForm {
 
                # Add manual and custom reason field/selects as well as submit
                if ( !$this->disabled ) {
+                       $mProtectreasonother = Xml::label(
+                               wfMessage( 'protectcomment' )->text(),
+                               'wpProtectReasonSelection'
+                       );
+
+                       $mProtectreason = Xml::label(
+                               wfMessage( 'protect-otherreason' )->text(),
+                               'mwProtect-reason'
+                       );
+
+                       $reasonDropDown = Xml::listDropDown( 'wpProtectReasonSelection',
+                               wfMessage( 'protect-dropdown' )->inContentLanguage()->text(),
+                               wfMessage( 'protect-otherreason-op' )->inContentLanguage()->text(),
+                               $this->mReasonSelection,
+                               'mwProtect-reason', 4 );
+
                        $out .= Xml::openElement( 'table', array( 'id' => 'mw-protect-table3' ) ) .
                                Xml::openElement( 'tbody' );
                        $out .= "
@@ -506,14 +511,14 @@ class ProtectionForm {
                                        "</td>
                                </tr>";
                        # Disallow watching is user is not logged in
-                       if ( $wgUser->isLoggedIn() ) {
+                       if ( $user->isLoggedIn() ) {
                                $out .= "
                                <tr>
                                        <td></td>
                                        <td class='mw-input'>" .
                                                Xml::checkLabel( wfMessage( 'watchthis' )->text(),
                                                        'mwProtectWatch', 'mwProtectWatch',
-                                                       $wgUser->isWatched( $this->mTitle ) || $wgUser->getOption( 'watchdefault' ) ) .
+                                                       $user->isWatched( $this->mTitle ) || $user->getOption( 'watchdefault' ) ) .
                                        "</td>
                                </tr>";
                        }
@@ -531,7 +536,7 @@ class ProtectionForm {
                }
                $out .= Xml::closeElement( 'fieldset' );
 
-               if ( $wgUser->isAllowed( 'editinterface' ) ) {
+               if ( $user->isAllowed( 'editinterface' ) ) {
                        $title = Title::makeTitle( NS_MEDIAWIKI, 'Protect-dropdown' );
                        $link = Linker::link(
                                $title,
@@ -545,10 +550,9 @@ class ProtectionForm {
                if ( !$this->disabled ) {
                        $out .= Html::hidden(
                                'wpEditToken',
-                               $wgUser->getEditToken( array( 'protect', $this->mTitle->getPrefixedDBkey() ) )
+                               $user->getEditToken( array( 'protect', $this->mTitle->getPrefixedDBkey() ) )
                        );
                        $out .= Xml::closeElement( 'form' );
-                       $wgOut->addScript( $this->buildCleanupScript() );
                }
 
                return $out;
@@ -562,12 +566,10 @@ class ProtectionForm {
         * @return string HTML fragment
         */
        function buildSelector( $action, $selected ) {
-               global $wgUser;
-
                // If the form is disabled, display all relevant levels. Otherwise,
                // just show the ones this user can use.
                $levels = MWNamespace::getRestrictionLevels( $this->mTitle->getNamespace(),
-                       $this->disabled ? null : $wgUser
+                       $this->disabled ? null : $this->mContext->getUser()
                );
 
                $id = 'mwProtect-level-' . $action;
@@ -575,8 +577,7 @@ class ProtectionForm {
                        'id' => $id,
                        'name' => $id,
                        'size' => count( $levels ),
-                       'onchange' => 'ProtectionForm.updateLevels(this)',
-                       ) + $this->disabledAttrib;
+               ) + $this->disabledAttrib;
 
                $out = Xml::openElement( 'select', $attribs );
                foreach ( $levels as $key ) {
@@ -605,22 +606,6 @@ class ProtectionForm {
                }
        }
 
-       function buildCleanupScript() {
-               global $wgCascadingRestrictionLevels, $wgOut;
-
-               $cascadeableLevels = $wgCascadingRestrictionLevels;
-               $options = array(
-                       'tableId' => 'mwProtectSet',
-                       'labelText' => wfMessage( 'protect-unchain-permissions' )->plain(),
-                       'numTypes' => count( $this->mApplicableTypes ),
-                       'existingMatch' => count( array_unique( $this->mExistingExpiry ) ) === 1,
-               );
-
-               $wgOut->addJsConfigVars( 'wgCascadeableLevels', $cascadeableLevels );
-               $script = Xml::encodeJsCall( 'ProtectionForm.init', array( $options ) );
-               return Html::inlineScript( ResourceLoader::makeLoaderConditionalScript( $script ) );
-       }
-
        /**
         * Show protection long extracts for this page
         *
index de69827..28a825d 100644 (file)
@@ -952,7 +952,7 @@ class Revision implements IDBAccessObject {
        }
 
        /**
-        * @param int $field one of DELETED_* bitfield constants
+        * @param int $field One of DELETED_* bitfield constants
         *
         * @return bool
         */
@@ -1569,7 +1569,7 @@ class Revision implements IDBAccessObject {
         * operations and other such meta-modifications.
         *
         * @param DatabaseBase $dbw
-        * @param int $pageId: ID number of the page to read from
+        * @param int $pageId ID number of the page to read from
         * @param string $summary Revision's summary
         * @param bool $minor Whether the revision should be considered as minor
         * @param User|null $user User object to use or null for $wgUser
@@ -1654,23 +1654,39 @@ class Revision implements IDBAccessObject {
         *                               self::DELETED_COMMENT = File::DELETED_COMMENT,
         *                               self::DELETED_USER = File::DELETED_USER
         * @param User|null $user User object to check, or null to use $wgUser
+        * @param Title|null $title A Title object to check for per-page restrictions on,
+        *                          instead of just plain userrights
         * @return bool
         */
-       public static function userCanBitfield( $bitfield, $field, User $user = null ) {
+       public static function userCanBitfield( $bitfield, $field, User $user = null,
+               Title $title = null
+       ) {
                if ( $bitfield & $field ) { // aspect is deleted
+                       if ( $user === null ) {
+                               global $wgUser;
+                               $user = $wgUser;
+                       }
                        if ( $bitfield & self::DELETED_RESTRICTED ) {
-                               $permission = 'suppressrevision';
+                               $permissions = array( 'suppressrevision', 'viewsuppressed' );
                        } elseif ( $field & self::DELETED_TEXT ) {
-                               $permission = 'deletedtext';
+                               $permissions = array( 'deletedtext' );
                        } else {
-                               $permission = 'deletedhistory';
+                               $permissions = array( 'deletedhistory' );
                        }
-                       wfDebug( "Checking for $permission due to $field match on $bitfield\n" );
-                       if ( $user === null ) {
-                               global $wgUser;
-                               $user = $wgUser;
+                       $permissionlist = implode( ', ', $permissions );
+                       if ( $title === null ) {
+                               wfDebug( "Checking for $permissionlist due to $field match on $bitfield\n" );
+                               return call_user_func_array( array( $user, 'isAllowedAny' ), $permissions );
+                       } else {
+                               $text = $title->getPrefixedText();
+                               wfDebug( "Checking for $permissionlist on $text due to $field match on $bitfield\n" );
+                               foreach ( $permissions as $perm ) {
+                                       if ( $title->userCan( $perm, $user ) ) {
+                                               return true;
+                                       }
+                               }
+                               return false;
                        }
-                       return $user->isAllowed( $permission );
                } else {
                        return true;
                }
index ec17a08..ce70047 100644 (file)
@@ -328,6 +328,7 @@ class Sanitizer {
         * Regular expression to match HTML/XML attribute pairs within a tag.
         * Allows some... latitude.
         * Used in Sanitizer::fixTagAttributes and Sanitizer::decodeTagAttributes
+        * @return string
         */
        static function getAttribsRegex() {
                if ( self::$attribsRegex === null ) {
@@ -715,7 +716,7 @@ class Sanitizer {
         * - Invalid id attributes are re-encoded
         *
         * @param array $attribs
-        * @param array $whitelist list of allowed attribute names
+        * @param array $whitelist List of allowed attribute names
         * @return array
         *
         * @todo Check for legal values where the DTD limits things.
@@ -1081,7 +1082,7 @@ class Sanitizer {
         * @see http://www.whatwg.org/html/elements.html#the-id-attribute
         *   HTML5 definition of id attribute
         *
-        * @param string $id id to escape
+        * @param string $id Id to escape
         * @param string|array $options String or array of strings (default is array()):
         *   'noninitial': This is a non-initial fragment of an id, not a full id,
         *       so don't pay attention if the first character isn't valid at the
@@ -1096,8 +1097,9 @@ class Sanitizer {
                global $wgExperimentalHtmlIds;
                $options = (array)$options;
 
+               $id = Sanitizer::decodeCharReferences( $id );
+
                if ( $wgExperimentalHtmlIds && !in_array( 'legacy', $options ) ) {
-                       $id = Sanitizer::decodeCharReferences( $id );
                        $id = preg_replace( '/[ \t\n\r\f_\'"&#%]+/', '_', $id );
                        $id = trim( $id, '_' );
                        if ( $id === '' ) {
@@ -1114,7 +1116,7 @@ class Sanitizer {
                        '%' => '.'
                );
 
-               $id = urlencode( Sanitizer::decodeCharReferences( strtr( $id, ' ', '_' ) ) );
+               $id = urlencode( strtr( $id, ' ', '_' ) );
                $id = str_replace( array_keys( $replace ), array_values( $replace ), $id );
 
                if ( !preg_match( '/^[a-zA-Z]/', $id )
@@ -1228,7 +1230,7 @@ class Sanitizer {
         * attribs regex matches.
         *
         * @param array $set
-        * @throws MWException when tag conditions are not met.
+        * @throws MWException When tag conditions are not met.
         * @return string
         */
        private static function getTagAttributeCallback( $set ) {
index 78655a4..78a41d5 100644 (file)
@@ -78,14 +78,6 @@ if ( $wgExtensionAssetsPath === false ) {
        $wgExtensionAssetsPath = "$wgScriptPath/extensions";
 }
 
-// Enable default skins. Temporary, to be removed before 1.24 release.
-// This is hacky and bad, the require_once calls should eventually be generated by the installer
-// and placed in LocalSettings.php.
-// While this is in Setup.php, it needs to be done as soon as possible, as some of the setup code
-// depends on all extensions and skins being already required (bug 67318).
-require_once "$wgStyleDirectory/MonoBook/MonoBook.php";
-require_once "$wgStyleDirectory/Vector/Vector.php";
-
 if ( $wgLogo === false ) {
        $wgLogo = "$wgStylePath/common/images/wiki.png";
 }
@@ -110,8 +102,13 @@ if ( $wgGitInfoCacheDirectory === false && $wgCacheDirectory !== false ) {
        $wgGitInfoCacheDirectory = "{$wgCacheDirectory}/gitinfo";
 }
 
-if ( isset( $wgFileStore['deleted']['directory'] ) ) {
-       $wgDeletedDirectory = $wgFileStore['deleted']['directory'];
+// Fix path to icon images after they were moved in 1.24
+if ( $wgRightsIcon ) {
+       $wgRightsIcon = str_replace(
+               "{$wgStylePath}/common/images/",
+               "{$wgScriptPath}/assets/licenses/",
+               $wgRightsIcon
+       );
 }
 
 if ( isset( $wgFooterIcons['copyright'] )
@@ -136,7 +133,7 @@ if ( isset( $wgFooterIcons['poweredby'] )
        && $wgFooterIcons['poweredby']['mediawiki']['src'] === null
 ) {
        $wgFooterIcons['poweredby']['mediawiki']['src'] =
-               "$wgStylePath/common/images/poweredby_mediawiki_88x31.png";
+               "$wgScriptPath/assets/poweredby_mediawiki_88x31.png";
 }
 
 /**
@@ -173,11 +170,6 @@ $wgLockManagers[] = array(
  * Initialise $wgLocalFileRepo from backwards-compatible settings
  */
 if ( !$wgLocalFileRepo ) {
-       if ( isset( $wgFileStore['deleted']['hash'] ) ) {
-               $deletedHashLevel = $wgFileStore['deleted']['hash'];
-       } else {
-               $deletedHashLevel = $wgHashedUploadDirectory ? 3 : 0;
-       }
        $wgLocalFileRepo = array(
                'class' => 'LocalRepo',
                'name' => 'local',
@@ -189,7 +181,7 @@ if ( !$wgLocalFileRepo ) {
                'thumbScriptUrl' => $wgThumbnailScriptPath,
                'transformVia404' => !$wgGenerateThumbnailOnParse,
                'deletedDir' => $wgDeletedDirectory,
-               'deletedHashLevels' => $deletedHashLevel
+               'deletedHashLevels' => $wgHashedUploadDirectory ? 3 : 0
        );
 }
 /**
@@ -280,6 +272,23 @@ if ( $wgSkipSkin ) {
        $wgSkipSkins[] = $wgSkipSkin;
 }
 
+// Register skins
+// Use a closure to avoid leaking into global state
+call_user_func( function () use ( $wgValidSkinNames ) {
+       $factory = SkinFactory::getDefaultInstance();
+       foreach ( $wgValidSkinNames as $name => $skin ) {
+               $factory->register( $name, $skin, function () use ( $name, $skin ) {
+                       $class = "Skin$skin";
+                       return new $class( $name );
+               } );
+       }
+       // Register a hidden "fallback" skin
+       $factory->register( 'fallback', 'Fallback', function () {
+               return new SkinFallback;
+       } );
+} );
+$wgSkipSkins[] = 'fallback';
+
 if ( $wgLocalInterwiki ) {
        array_unshift( $wgLocalInterwikis, $wgLocalInterwiki );
 }
@@ -302,7 +311,33 @@ if ( !$wgCookiePrefix ) {
 }
 $wgCookiePrefix = strtr( $wgCookiePrefix, '=,; +."\'\\[', '__________' );
 
-$wgUseEnotif = $wgEnotifUserTalk || $wgEnotifWatchlist;
+if ( $wgEnableEmail ) {
+       $wgUseEnotif = $wgEnotifUserTalk || $wgEnotifWatchlist;
+} else {
+       // Disable all other email settings automatically if $wgEnableEmail
+       // is set to false. - bug 63678
+       $wgAllowHTMLEmail = false;
+       $wgEmailAuthentication = false; // do not require auth if you're not sending email anyway
+       $wgEnableUserEmail = false;
+       $wgEnotifFromEditor = false;
+       $wgEnotifImpersonal = false;
+       $wgEnotifMaxRecips = 0;
+       $wgEnotifMinorEdits = false;
+       $wgEnotifRevealEditorAddress = false;
+       $wgEnotifUseJobQ = false;
+       $wgEnotifUseRealName = false;
+       $wgEnotifUserTalk = false;
+       $wgEnotifWatchlist = false;
+       unset( $wgGroupPermissions['user']['sendemail'] );
+       $wgUseEnotif = false;
+       $wgUserEmailUseReplyTo = false;
+       $wgUsersNotifiedOnAllChanges = array();
+}
+
+// Doesn't make sense to have if disabled.
+if ( !$wgEnotifMinorEdits ) {
+       $wgHiddenPrefs[] = 'enotifminoredits';
+}
 
 if ( $wgMetaNamespace === false ) {
        $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
@@ -355,11 +390,6 @@ if ( $wgUseFileCache || $wgUseSquid ) {
        $wgDebugToolbar = false;
 }
 
-// Doesn't make sense to have if disabled.
-if ( !$wgEnotifMinorEdits ) {
-       $wgHiddenPrefs[] = 'enotifminoredits';
-}
-
 // We always output HTML5 since 1.22, overriding these is no longer supported
 // we set them here for extensions that depend on its value.
 $wgHtml5 = true;
@@ -378,10 +408,6 @@ if ( !$wgHtml5Version && $wgAllowRdfaAttributes ) {
 // Blacklisted file extensions shouldn't appear on the "allowed" list
 $wgFileExtensions = array_values( array_diff ( $wgFileExtensions, $wgFileBlacklist ) );
 
-if ( $wgArticleCountMethod === null ) {
-       $wgArticleCountMethod = $wgUseCommaCount ? 'comma' : 'link';
-}
-
 if ( $wgInvalidateCacheOnLocalSettingsChange ) {
        // @codingStandardsIgnoreStart Generic.PHP.NoSilencedErrors.Discouraged - No GlobalFunction here yet.
        $wgCacheEpoch = max( $wgCacheEpoch, gmdate( 'YmdHis', @filemtime( "$IP/LocalSettings.php" ) ) );
@@ -409,13 +435,14 @@ if ( $wgCookieSecure === 'detect' ) {
        $wgCookieSecure = ( WebRequest::detectProtocol() === 'https' );
 }
 
-if ( $wgRC2UDPAddress ) {
-       $wgRCFeeds['default'] = array(
-               'formatter' => 'IRCColourfulRCFeedFormatter',
-               'uri' => "udp://$wgRC2UDPAddress:$wgRC2UDPPort/$wgRC2UDPPrefix",
-               'add_interwiki_prefix' => &$wgRC2UDPInterwikiPrefix,
-               'omit_bots' => &$wgRC2UDPOmitBots,
-       );
+// Back compatibility for $wgRateLimitLog deprecated with 1.23
+if ( $wgRateLimitLog && !array_key_exists( 'ratelimit', $wgDebugLogGroups ) ) {
+       $wgDebugLogGroups['ratelimit'] = $wgRateLimitLog;
+}
+
+if ( $wgProfileOnly ) {
+       $wgDebugLogGroups['profileoutput'] = $wgDebugLogFile;
+       $wgDebugLogFile = '';
 }
 
 wfProfileOut( $fname . '-defaults' );
@@ -482,33 +509,6 @@ if ( $wgTmpDirectory === false ) {
        wfProfileOut( $fname . '-tempDir' );
 }
 
-// $wgHTCPMulticastRouting got renamed to $wgHTCPRouting in MediaWiki 1.22
-// ensure back compatibility.
-if ( !$wgHTCPRouting && $wgHTCPMulticastRouting ) {
-       $wgHTCPRouting = $wgHTCPMulticastRouting;
-}
-
-// Initialize $wgHTCPRouting from backwards-compatible settings that
-// comes from pre 1.20 version.
-if ( !$wgHTCPRouting && $wgHTCPMulticastAddress ) {
-       $wgHTCPRouting = array(
-               '' => array(
-                       'host' => $wgHTCPMulticastAddress,
-                       'port' => $wgHTCPPort,
-               )
-       );
-}
-
-// Back compatibility for $wgRateLimitLog deprecated with 1.23
-if ( $wgRateLimitLog && ! array_key_exists( 'ratelimit', $wgDebugLogGroups ) ) {
-       $wgDebugLogGroups['ratelimit'] = $wgRateLimitLog;
-}
-
-if ( $wgProfileOnly ) {
-       $wgDebugLogGroups['profileoutput'] = $wgDebugLogFile;
-       $wgDebugLogFile = '';
-}
-
 wfProfileOut( $fname . '-defaults2' );
 wfProfileIn( $fname . '-misc1' );
 
@@ -571,15 +571,15 @@ wfRunHooks( 'SetupAfterCache' );
 
 wfProfileIn( $fname . '-session' );
 
-// If session.auto_start is there, we can't touch session name
-if ( !wfIniGetBool( 'session.auto_start' ) ) {
-       session_name( $wgSessionName ? $wgSessionName : $wgCookiePrefix . '_session' );
-}
+if ( !defined( 'MW_NO_SESSION' ) && !$wgCommandLineMode ) {
+       // If session.auto_start is there, we can't touch session name
+       if ( !wfIniGetBool( 'session.auto_start' ) ) {
+               session_name( $wgSessionName ? $wgSessionName : $wgCookiePrefix . '_session' );
+       }
 
-if ( !defined( 'MW_NO_SESSION' ) && !$wgCommandLineMode &&
-       ( $wgRequest->checkSessionCookie() || isset( $_COOKIE[$wgCookiePrefix . 'Token'] ) )
-) {
-       wfSetupSession();
+       if ( $wgRequest->checkSessionCookie() || isset( $_COOKIE[$wgCookiePrefix . 'Token'] ) ) {
+               wfSetupSession();
+       }
 }
 
 wfProfileOut( $fname . '-session' );
@@ -625,6 +625,10 @@ if ( !is_object( $wgAuth ) ) {
  */
 $wgTitle = null;
 
+/**
+ * @deprecated since 1.24 Use DeferredUpdates::addUpdate instead
+ * @var array
+ */
 $wgDeferredUpdateList = array();
 
 wfProfileOut( $fname . '-globals' );
index b877544..8c1f26b 100644 (file)
@@ -532,7 +532,7 @@ class SiteConfiguration {
                        if ( isset( $this->cfgCache[$wiki] ) ) {
                                $res = array_intersect_key( $this->cfgCache[$wiki], array_flip( $settings ) );
                                if ( count( $res ) == count( $settings ) ) {
-                                       return $res; // cache hit
+                                       return $multi ? $res : current( $res ); // cache hit
                                }
                        } elseif ( !in_array( $wiki, $this->wikis ) ) {
                                throw new MWException( "No such wiki '$wiki'." );
index e5c1e17..3dc1793 100644 (file)
@@ -170,7 +170,7 @@ class SiteStats {
 
        /**
         * Find the number of users in a given user group.
-        * @param string $group name of group
+        * @param string $group Name of group
         * @return int
         */
        static function numberingroup( $group ) {
@@ -373,7 +373,7 @@ class SiteStatsInit {
         * @param DatabaseBase|bool $database
         * - Boolean: whether to use the master DB
         * - DatabaseBase: database connection to use
-        * @param array $options of options, may contain the following values
+        * @param array $options Array of options, may contain the following values
         * - views Boolean: when true, do not update the number of page views (default: true)
         * - activeUsers Boolean: whether to update the number of active users (default: false)
         */
diff --git a/includes/Skin.php b/includes/Skin.php
deleted file mode 100644 (file)
index bc30eff..0000000
+++ /dev/null
@@ -1,1676 +0,0 @@
-<?php
-/**
- * Base class for all skins.
- *
- * 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
- */
-
-/**
- * @defgroup Skins Skins
- */
-
-/**
- * The main skin class which provides methods and properties for all other skins.
- *
- * See docs/skin.txt for more information.
- *
- * @ingroup Skins
- */
-abstract class Skin extends ContextSource {
-       protected $skinname = null;
-       protected $mRelevantTitle = null;
-       protected $mRelevantUser = null;
-
-       /**
-        * @var string Stylesheets set to use. Subdirectory in skins/ where various stylesheets are
-        *   located. Only needs to be set if you intend to use the getSkinStylePath() method.
-        */
-       public $stylename = null;
-
-       /**
-        * Fetch the set of available skins.
-        * @return array Associative array of strings
-        */
-       static function getSkinNames() {
-               global $wgValidSkinNames;
-               static $skinsInitialised = false;
-
-               if ( !$skinsInitialised || !count( $wgValidSkinNames ) ) {
-                       # Get a list of available skins
-                       # Build using the regular expression '^(.*).php$'
-                       # Array keys are all lower case, array value keep the case used by filename
-                       #
-                       wfProfileIn( __METHOD__ . '-init' );
-
-                       global $wgStyleDirectory;
-
-                       $skinDir = dir( $wgStyleDirectory );
-
-                       if ( $skinDir !== false && $skinDir !== null ) {
-                               # while code from www.php.net
-                               while ( false !== ( $file = $skinDir->read() ) ) {
-                                       // Skip non-PHP files, hidden files, and '.dep' includes
-                                       $matches = array();
-
-                                       if ( preg_match( '/^([^.]*)\.php$/', $file, $matches ) ) {
-                                               $aSkin = $matches[1];
-
-                                               // Explicitly disallow loading core skins via the autodiscovery mechanism.
-                                               //
-                                               // They should be loaded already (in a non-autodicovery way), but old files might still
-                                               // exist on the server because our MW version upgrade process is widely documented as
-                                               // requiring just copying over all files, without removing old ones.
-                                               //
-                                               // This is one of the reasons we should have never used autodiscovery in the first
-                                               // place. This hack can be safely removed when autodiscovery is gone.
-                                               if ( in_array( $aSkin, array( 'CologneBlue', 'Modern', 'MonoBook', 'Vector' ) ) ) {
-                                                       wfLogWarning(
-                                                               "An old copy of the $aSkin skin was found in your skins/ directory. " .
-                                                               "You should remove it to avoid problems in the future." .
-                                                               "See https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery for details."
-                                                       );
-                                                       continue;
-                                               }
-
-                                               wfLogWarning(
-                                                       "A skin using autodiscovery mechanism, $aSkin, was found in your skins/ directory. " .
-                                                       "The mechanism will be removed in MediaWiki 1.25 and the skin will no longer be recognized. " .
-                                                       "See https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery for information how to fix this."
-                                               );
-                                               $wgValidSkinNames[strtolower( $aSkin )] = $aSkin;
-                                       }
-                               }
-                               $skinDir->close();
-                       }
-                       $skinsInitialised = true;
-                       wfProfileOut( __METHOD__ . '-init' );
-               }
-               return $wgValidSkinNames;
-       }
-
-       /**
-        * Fetch the skinname messages for available skins.
-        * @return string[]
-        */
-       static function getSkinNameMessages() {
-               $messages = array();
-               foreach ( self::getSkinNames() as $skinKey => $skinName ) {
-                       $messages[] = "skinname-$skinKey";
-               }
-               return $messages;
-       }
-
-       /**
-        * Fetch the list of user-selectable skins in regards to $wgSkipSkins.
-        * Useful for Special:Preferences and other places where you
-        * only want to show skins users _can_ use.
-        * @return string[]
-        * @since 1.23
-        */
-       public static function getAllowedSkins() {
-               global $wgSkipSkins;
-
-               $allowedSkins = self::getSkinNames();
-
-               foreach ( $wgSkipSkins as $skip ) {
-                       unset( $allowedSkins[$skip] );
-               }
-
-               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.
-        * If a skin can't be found, it will fall back to the configured
-        * default, or the hardcoded default if that's broken.
-        * @param string $key 'monobook', 'vector', etc.
-        * @return string
-        */
-       static function normalizeKey( $key ) {
-               global $wgDefaultSkin;
-
-               $skinNames = Skin::getSkinNames();
-
-               if ( $key == '' || $key == 'default' ) {
-                       // Don't return the default immediately;
-                       // in a misconfiguration we need to fall back.
-                       $key = $wgDefaultSkin;
-               }
-
-               if ( isset( $skinNames[$key] ) ) {
-                       return $key;
-               }
-
-               // Older versions of the software used a numeric setting
-               // in the user preferences.
-               $fallback = array(
-                       0 => $wgDefaultSkin,
-                       2 => 'cologneblue'
-               );
-
-               if ( isset( $fallback[$key] ) ) {
-                       $key = $fallback[$key];
-               }
-
-               if ( isset( $skinNames[$key] ) ) {
-                       return $key;
-               } elseif ( isset( $skinNames[$wgDefaultSkin] ) ) {
-                       return $wgDefaultSkin;
-               } else {
-                       return 'vector';
-               }
-       }
-
-       /**
-        * Factory method for loading a skin of a given type
-        * @param string $key 'monobook', 'vector', etc.
-        * @return Skin
-        */
-       static function &newFromKey( $key ) {
-               global $wgStyleDirectory;
-
-               $key = Skin::normalizeKey( $key );
-
-               $skinNames = Skin::getSkinNames();
-               $skinName = $skinNames[$key];
-               $className = "Skin{$skinName}";
-
-               # Grab the skin class and initialise it.
-               if ( !class_exists( $className ) ) {
-
-                       require_once "{$wgStyleDirectory}/{$skinName}.php";
-
-                       # Check if we got if not fallback to default skin
-                       if ( !class_exists( $className ) ) {
-                               # DO NOT die if the class isn't found. This breaks maintenance
-                               # scripts and can cause a user account to be unrecoverable
-                               # except by SQL manipulation if a previously valid skin name
-                               # is no longer valid.
-                               wfDebug( "Skin class does not exist: $className\n" );
-                               $className = 'SkinVector';
-                       }
-               }
-               $skin = new $className( $key );
-               return $skin;
-       }
-
-       /**
-        * @return string Skin name
-        */
-       public function getSkinName() {
-               return $this->skinname;
-       }
-
-       /**
-        * @param OutputPage $out
-        */
-       function initPage( OutputPage $out ) {
-               wfProfileIn( __METHOD__ );
-
-               $this->preloadExistence();
-
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * Defines the ResourceLoader modules that should be added to the skin
-        * It is recommended that skins wishing to override call parent::getDefaultModules()
-        * and substitute out any modules they wish to change by using a key to look them up
-        * @return array Array of modules with helper keys for easy overriding
-        */
-       public function getDefaultModules() {
-               global $wgIncludeLegacyJavaScript, $wgPreloadJavaScriptMwUtil, $wgUseAjax,
-                       $wgAjaxWatch, $wgEnableAPI, $wgEnableWriteAPI;
-
-               $out = $this->getOutput();
-               $user = $out->getUser();
-               $modules = array(
-                       // modules that enhance the page content in some way
-                       'content' => array(
-                               'mediawiki.page.ready',
-                       ),
-                       // modules that exist for legacy reasons
-                       'legacy' => array(),
-                       // modules relating to search functionality
-                       'search' => array(),
-                       // modules relating to functionality relating to watching an article
-                       'watch' => array(),
-                       // modules which relate to the current users preferences
-                       'user' => array(),
-               );
-               if ( $wgIncludeLegacyJavaScript ) {
-                       $modules['legacy'][] = 'mediawiki.legacy.wikibits';
-               }
-
-               if ( $wgPreloadJavaScriptMwUtil ) {
-                       $modules['legacy'][] = 'mediawiki.util';
-               }
-
-               // Add various resources if required
-               if ( $wgUseAjax ) {
-                       $modules['legacy'][] = 'mediawiki.legacy.ajax';
-
-                       if ( $wgEnableAPI ) {
-                               if ( $wgEnableWriteAPI && $wgAjaxWatch && $user->isLoggedIn()
-                                       && $user->isAllowed( 'writeapi' )
-                               ) {
-                                       $modules['watch'][] = 'mediawiki.page.watch.ajax';
-                               }
-
-                               $modules['search'][] = 'mediawiki.searchSuggest';
-                       }
-               }
-
-               if ( $user->getBoolOption( 'editsectiononrightclick' ) ) {
-                       $modules['user'][] = 'mediawiki.action.view.rightClickEdit';
-               }
-
-               // Crazy edit-on-double-click stuff
-               if ( $out->isArticle() && $user->getOption( 'editondblclick' ) ) {
-                       $modules['user'][] = 'mediawiki.action.view.dblClickEdit';
-               }
-               return $modules;
-       }
-
-       /**
-        * Preload the existence of three commonly-requested pages in a single query
-        */
-       function preloadExistence() {
-               $user = $this->getUser();
-
-               // User/talk link
-               $titles = array( $user->getUserPage(), $user->getTalkPage() );
-
-               // Other tab link
-               if ( $this->getTitle()->isSpecialPage() ) {
-                       // nothing
-               } elseif ( $this->getTitle()->isTalkPage() ) {
-                       $titles[] = $this->getTitle()->getSubjectPage();
-               } else {
-                       $titles[] = $this->getTitle()->getTalkPage();
-               }
-
-               $lb = new LinkBatch( $titles );
-               $lb->setCaller( __METHOD__ );
-               $lb->execute();
-       }
-
-       /**
-        * Get the current revision ID
-        *
-        * @return int
-        */
-       public function getRevisionId() {
-               return $this->getOutput()->getRevisionId();
-       }
-
-       /**
-        * Whether the revision displayed is the latest revision of the page
-        *
-        * @return bool
-        */
-       public function isRevisionCurrent() {
-               $revID = $this->getRevisionId();
-               return $revID == 0 || $revID == $this->getTitle()->getLatestRevID();
-       }
-
-       /**
-        * Set the "relevant" title
-        * @see self::getRelevantTitle()
-        * @param Title $t
-        */
-       public function setRelevantTitle( $t ) {
-               $this->mRelevantTitle = $t;
-       }
-
-       /**
-        * Return the "relevant" title.
-        * A "relevant" title is not necessarily the actual title of the page.
-        * Special pages like Special:MovePage use set the page they are acting on
-        * as their "relevant" title, this allows the skin system to display things
-        * such as content tabs which belong to to that page instead of displaying
-        * a basic special page tab which has almost no meaning.
-        *
-        * @return Title
-        */
-       public function getRelevantTitle() {
-               if ( isset( $this->mRelevantTitle ) ) {
-                       return $this->mRelevantTitle;
-               }
-               return $this->getTitle();
-       }
-
-       /**
-        * Set the "relevant" user
-        * @see self::getRelevantUser()
-        * @param User $u
-        */
-       public function setRelevantUser( $u ) {
-               $this->mRelevantUser = $u;
-       }
-
-       /**
-        * Return the "relevant" user.
-        * A "relevant" user is similar to a relevant title. Special pages like
-        * Special:Contributions mark the user which they are relevant to so that
-        * things like the toolbox can display the information they usually are only
-        * able to display on a user's userpage and talkpage.
-        * @return User
-        */
-       public function getRelevantUser() {
-               if ( isset( $this->mRelevantUser ) ) {
-                       return $this->mRelevantUser;
-               }
-               $title = $this->getRelevantTitle();
-               if ( $title->hasSubjectNamespace( NS_USER ) ) {
-                       $rootUser = $title->getRootText();
-                       if ( User::isIP( $rootUser ) ) {
-                               $this->mRelevantUser = User::newFromName( $rootUser, false );
-                       } else {
-                               $user = User::newFromName( $rootUser, false );
-                               if ( $user && $user->isLoggedIn() ) {
-                                       $this->mRelevantUser = $user;
-                               }
-                       }
-                       return $this->mRelevantUser;
-               }
-               return null;
-       }
-
-       /**
-        * Outputs the HTML generated by other functions.
-        * @param OutputPage $out
-        */
-       abstract function outputPage( OutputPage $out = null );
-
-       /**
-        * @param array $data
-        * @return string
-        */
-       static function makeVariablesScript( $data ) {
-               if ( $data ) {
-                       return Html::inlineScript(
-                               ResourceLoader::makeLoaderConditionalScript( ResourceLoader::makeConfigSetScript( $data ) )
-                       );
-               } else {
-                       return '';
-               }
-       }
-
-       /**
-        * Get the query to generate a dynamic stylesheet
-        *
-        * @return array
-        */
-       public static function getDynamicStylesheetQuery() {
-               global $wgSquidMaxage;
-
-               return array(
-                               'action' => 'raw',
-                               'maxage' => $wgSquidMaxage,
-                               'usemsgcache' => 'yes',
-                               'ctype' => 'text/css',
-                               'smaxage' => $wgSquidMaxage,
-                       );
-       }
-
-       /**
-        * Add skin specific stylesheets
-        * Calling this method with an $out of anything but the same OutputPage
-        * inside ->getOutput() is deprecated. The $out arg is kept
-        * for compatibility purposes with skins.
-        * @param OutputPage $out
-        * @todo delete
-        */
-       abstract function setupSkinUserCss( OutputPage $out );
-
-       /**
-        * TODO: document
-        * @param Title $title
-        * @return string
-        */
-       function getPageClasses( $title ) {
-               $numeric = 'ns-' . $title->getNamespace();
-
-               if ( $title->isSpecialPage() ) {
-                       $type = 'ns-special';
-                       // bug 23315: provide a class based on the canonical special page name without subpages
-                       list( $canonicalName ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
-                       if ( $canonicalName ) {
-                               $type .= ' ' . Sanitizer::escapeClass( "mw-special-$canonicalName" );
-                       } else {
-                               $type .= ' mw-invalidspecialpage';
-                       }
-               } elseif ( $title->isTalkPage() ) {
-                       $type = 'ns-talk';
-               } else {
-                       $type = 'ns-subject';
-               }
-
-               $name = Sanitizer::escapeClass( 'page-' . $title->getPrefixedText() );
-
-               return "$numeric $type $name";
-       }
-
-       /*
-        * Return values for <html> element
-        * @return array of associative name-to-value elements for <html> element
-        */
-       public function getHtmlElementAttributes() {
-               $lang = $this->getLanguage();
-               return array(
-                       'lang' => $lang->getHtmlCode(),
-                       'dir' => $lang->getDir(),
-                       'class' => 'client-nojs',
-               );
-       }
-
-       /**
-        * This will be called by OutputPage::headElement when it is creating the
-        * "<body>" tag, skins can override it if they have a need to add in any
-        * body attributes or classes of their own.
-        * @param OutputPage $out
-        * @param array $bodyAttrs
-        */
-       function addToBodyAttributes( $out, &$bodyAttrs ) {
-               // does nothing by default
-       }
-
-       /**
-        * URL to the logo
-        * @return string
-        */
-       function getLogo() {
-               global $wgLogo;
-               return $wgLogo;
-       }
-
-       /**
-        * @return string
-        */
-       function getCategoryLinks() {
-               global $wgUseCategoryBrowser;
-
-               $out = $this->getOutput();
-               $allCats = $out->getCategoryLinks();
-
-               if ( !count( $allCats ) ) {
-                       return '';
-               }
-
-               $embed = "<li>";
-               $pop = "</li>";
-
-               $s = '';
-               $colon = $this->msg( 'colon-separator' )->escaped();
-
-               if ( !empty( $allCats['normal'] ) ) {
-                       $t = $embed . implode( "{$pop}{$embed}", $allCats['normal'] ) . $pop;
-
-                       $msg = $this->msg( 'pagecategories' )->numParams( count( $allCats['normal'] ) )->escaped();
-                       $linkPage = wfMessage( 'pagecategorieslink' )->inContentLanguage()->text();
-                       $s .= '<div id="mw-normal-catlinks" class="mw-normal-catlinks">' .
-                               Linker::link( Title::newFromText( $linkPage ), $msg )
-                               . $colon . '<ul>' . $t . '</ul>' . '</div>';
-               }
-
-               # Hidden categories
-               if ( isset( $allCats['hidden'] ) ) {
-                       if ( $this->getUser()->getBoolOption( 'showhiddencats' ) ) {
-                               $class = ' mw-hidden-cats-user-shown';
-                       } elseif ( $this->getTitle()->getNamespace() == NS_CATEGORY ) {
-                               $class = ' mw-hidden-cats-ns-shown';
-                       } else {
-                               $class = ' mw-hidden-cats-hidden';
-                       }
-
-                       $s .= "<div id=\"mw-hidden-catlinks\" class=\"mw-hidden-catlinks$class\">" .
-                               $this->msg( 'hidden-categories' )->numParams( count( $allCats['hidden'] ) )->escaped() .
-                               $colon . '<ul>' . $embed . implode( "{$pop}{$embed}", $allCats['hidden'] ) . $pop . '</ul>' .
-                               '</div>';
-               }
-
-               # optional 'dmoz-like' category browser. Will be shown under the list
-               # of categories an article belong to
-               if ( $wgUseCategoryBrowser ) {
-                       $s .= '<br /><hr />';
-
-                       # get a big array of the parents tree
-                       $parenttree = $this->getTitle()->getParentCategoryTree();
-                       # Skin object passed by reference cause it can not be
-                       # accessed under the method subfunction drawCategoryBrowser
-                       $tempout = explode( "\n", $this->drawCategoryBrowser( $parenttree ) );
-                       # Clean out bogus first entry and sort them
-                       unset( $tempout[0] );
-                       asort( $tempout );
-                       # Output one per line
-                       $s .= implode( "<br />\n", $tempout );
-               }
-
-               return $s;
-       }
-
-       /**
-        * Render the array as a series of links.
-        * @param array $tree Categories tree returned by Title::getParentCategoryTree
-        * @return string Separated by &gt;, terminate with "\n"
-        */
-       function drawCategoryBrowser( $tree ) {
-               $return = '';
-
-               foreach ( $tree as $element => $parent ) {
-                       if ( empty( $parent ) ) {
-                               # element start a new list
-                               $return .= "\n";
-                       } else {
-                               # grab the others elements
-                               $return .= $this->drawCategoryBrowser( $parent ) . ' &gt; ';
-                       }
-
-                       # add our current element to the list
-                       $eltitle = Title::newFromText( $element );
-                       $return .= Linker::link( $eltitle, htmlspecialchars( $eltitle->getText() ) );
-               }
-
-               return $return;
-       }
-
-       /**
-        * @return string
-        */
-       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;
-
-               if ( empty( $allCats['normal'] ) && !( !empty( $allCats['hidden'] ) && $showHidden ) ) {
-                       $classes .= ' catlinks-allhidden';
-               }
-
-               return "<div id='catlinks' class='$classes'>{$catlinks}</div>";
-       }
-
-       /**
-        * This runs a hook to allow extensions placing their stuff after content
-        * and article metadata (e.g. categories).
-        * Note: This function has nothing to do with afterContent().
-        *
-        * This hook is placed here in order to allow using the same hook for all
-        * skins, both the SkinTemplate based ones and the older ones, which directly
-        * use this class to get their data.
-        *
-        * The output of this function gets processed in SkinTemplate::outputPage() for
-        * the SkinTemplate based skins, all other skins should directly echo it.
-        *
-        * @return string Empty by default, if not changed by any hook function.
-        */
-       protected function afterContentHook() {
-               $data = '';
-
-               if ( wfRunHooks( 'SkinAfterContent', array( &$data, $this ) ) ) {
-                       // adding just some spaces shouldn't toggle the output
-                       // of the whole <div/>, so we use trim() here
-                       if ( trim( $data ) != '' ) {
-                               // Doing this here instead of in the skins to
-                               // ensure that the div has the same ID in all
-                               // skins
-                               $data = "<div id='mw-data-after-content'>\n" .
-                                       "\t$data\n" .
-                                       "</div>\n";
-                       }
-               } else {
-                       wfDebug( "Hook SkinAfterContent changed output processing.\n" );
-               }
-
-               return $data;
-       }
-
-       /**
-        * Generate debug data HTML for displaying at the bottom of the main content
-        * area.
-        * @return string HTML containing debug data, if enabled (otherwise empty).
-        */
-       protected function generateDebugHTML() {
-               return MWDebug::getHTMLDebugLog();
-       }
-
-       /**
-        * This gets called shortly before the "</body>" tag.
-        *
-        * @return string HTML-wrapped JS code to be put before "</body>"
-        */
-       function bottomScripts() {
-               // TODO and the suckage continues. This function is really just a wrapper around
-               // OutputPage::getBottomScripts() which takes a Skin param. This should be cleaned
-               // up at some point
-               $bottomScriptText = $this->getOutput()->getBottomScripts();
-               wfRunHooks( 'SkinAfterBottomScripts', array( $this, &$bottomScriptText ) );
-
-               return $bottomScriptText;
-       }
-
-       /**
-        * Text with the permalink to the source page,
-        * usually shown on the footer of a printed page
-        *
-        * @return string HTML text with an URL
-        */
-       function printSource() {
-               $oldid = $this->getRevisionId();
-               if ( $oldid ) {
-                       $canonicalUrl = $this->getTitle()->getCanonicalURL( 'oldid=' . $oldid );
-                       $url = htmlspecialchars( wfExpandIRI( $canonicalUrl ) );
-               } else {
-                       // oldid not available for non existing pages
-                       $url = htmlspecialchars( wfExpandIRI( $this->getTitle()->getCanonicalURL() ) );
-               }
-
-               return $this->msg( 'retrievedfrom', '<a dir="ltr" href="' . $url
-                       . '">' . $url . '</a>' )->text();
-       }
-
-       /**
-        * @return string
-        */
-       function getUndeleteLink() {
-               $action = $this->getRequest()->getVal( 'action', 'view' );
-
-               if ( $this->getUser()->isAllowed( 'deletedhistory' ) &&
-                       ( $this->getTitle()->getArticleID() == 0 || $action == 'history' ) ) {
-                       $n = $this->getTitle()->isDeleted();
-
-                       if ( $n ) {
-                               if ( $this->getUser()->isAllowed( 'undelete' ) ) {
-                                       $msg = 'thisisdeleted';
-                               } else {
-                                       $msg = 'viewdeleted';
-                               }
-
-                               return $this->msg( $msg )->rawParams(
-                                       Linker::linkKnown(
-                                               SpecialPage::getTitleFor( 'Undelete', $this->getTitle()->getPrefixedDBkey() ),
-                                               $this->msg( 'restorelink' )->numParams( $n )->escaped() )
-                                       )->text();
-                       }
-               }
-
-               return '';
-       }
-
-       /**
-        * @return string
-        */
-       function subPageSubtitle() {
-               $out = $this->getOutput();
-               $subpages = '';
-
-               if ( !wfRunHooks( 'SkinSubPageSubtitle', array( &$subpages, $this, $out ) ) ) {
-                       return $subpages;
-               }
-
-               if ( $out->isArticle() && MWNamespace::hasSubpages( $out->getTitle()->getNamespace() ) ) {
-                       $ptext = $this->getTitle()->getPrefixedText();
-                       if ( preg_match( '/\//', $ptext ) ) {
-                               $links = explode( '/', $ptext );
-                               array_pop( $links );
-                               $c = 0;
-                               $growinglink = '';
-                               $display = '';
-                               $lang = $this->getLanguage();
-
-                               foreach ( $links as $link ) {
-                                       $growinglink .= $link;
-                                       $display .= $link;
-                                       $linkObj = Title::newFromText( $growinglink );
-
-                                       if ( is_object( $linkObj ) && $linkObj->isKnown() ) {
-                                               $getlink = Linker::linkKnown(
-                                                       $linkObj,
-                                                       htmlspecialchars( $display )
-                                               );
-
-                                               $c++;
-
-                                               if ( $c > 1 ) {
-                                                       $subpages .= $lang->getDirMarkEntity() . $this->msg( 'pipe-separator' )->escaped();
-                                               } else {
-                                                       $subpages .= '&lt; ';
-                                               }
-
-                                               $subpages .= $getlink;
-                                               $display = '';
-                                       } else {
-                                               $display .= '/';
-                                       }
-                                       $growinglink .= '/';
-                               }
-                       }
-               }
-
-               return $subpages;
-       }
-
-       /**
-        * Returns true if the IP should be shown in the header
-        * @return bool
-        */
-       function showIPinHeader() {
-               global $wgShowIPinHeader;
-               return $wgShowIPinHeader && session_id() != '';
-       }
-
-       /**
-        * @return string
-        */
-       function getSearchLink() {
-               $searchPage = SpecialPage::getTitleFor( 'Search' );
-               return $searchPage->getLocalURL();
-       }
-
-       /**
-        * @return string
-        */
-       function escapeSearchLink() {
-               return htmlspecialchars( $this->getSearchLink() );
-       }
-
-       /**
-        * @param string $type
-        * @return string
-        */
-       function getCopyright( $type = 'detect' ) {
-               global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgContLang;
-
-               if ( $type == 'detect' ) {
-                       if ( !$this->isRevisionCurrent()
-                               && !$this->msg( 'history_copyright' )->inContentLanguage()->isDisabled()
-                       ) {
-                               $type = 'history';
-                       } else {
-                               $type = 'normal';
-                       }
-               }
-
-               if ( $type == 'history' ) {
-                       $msg = 'history_copyright';
-               } else {
-                       $msg = 'copyright';
-               }
-
-               if ( $wgRightsPage ) {
-                       $title = Title::newFromText( $wgRightsPage );
-                       $link = Linker::linkKnown( $title, $wgRightsText );
-               } elseif ( $wgRightsUrl ) {
-                       $link = Linker::makeExternalLink( $wgRightsUrl, $wgRightsText );
-               } elseif ( $wgRightsText ) {
-                       $link = $wgRightsText;
-               } else {
-                       # Give up now
-                       return '';
-               }
-
-               // Allow for site and per-namespace customization of copyright notice.
-               // @todo Remove deprecated $forContent param from hook handlers and then remove here.
-               $forContent = true;
-
-               wfRunHooks(
-                       'SkinCopyrightFooter',
-                       array( $this->getTitle(), $type, &$msg, &$link, &$forContent )
-               );
-
-               return $this->msg( $msg )->rawParams( $link )->text();
-       }
-
-       /**
-        * @return null|string
-        */
-       function getCopyrightIcon() {
-               global $wgRightsUrl, $wgRightsText, $wgRightsIcon, $wgCopyrightIcon;
-
-               $out = '';
-
-               if ( $wgCopyrightIcon ) {
-                       $out = $wgCopyrightIcon;
-               } elseif ( $wgRightsIcon ) {
-                       $icon = htmlspecialchars( $wgRightsIcon );
-
-                       if ( $wgRightsUrl ) {
-                               $url = htmlspecialchars( $wgRightsUrl );
-                               $out .= '<a href="' . $url . '">';
-                       }
-
-                       $text = htmlspecialchars( $wgRightsText );
-                       $out .= "<img src=\"$icon\" alt=\"$text\" width=\"88\" height=\"31\" />";
-
-                       if ( $wgRightsUrl ) {
-                               $out .= '</a>';
-                       }
-               }
-
-               return $out;
-       }
-
-       /**
-        * Gets the powered by MediaWiki icon.
-        * @return string
-        */
-       function getPoweredBy() {
-               global $wgStylePath;
-
-               $url = htmlspecialchars( "$wgStylePath/common/images/poweredby_mediawiki_88x31.png" );
-               $text = '<a href="//www.mediawiki.org/"><img src="' . $url
-                       . '" height="31" width="88" alt="Powered by MediaWiki" /></a>';
-               wfRunHooks( 'SkinGetPoweredBy', array( &$text, $this ) );
-               return $text;
-       }
-
-       /**
-        * Get the timestamp of the latest revision, formatted in user language
-        *
-        * @return string
-        */
-       protected function lastModified() {
-               $timestamp = $this->getOutput()->getRevisionTimestamp();
-
-               # No cached timestamp, load it from the database
-               if ( $timestamp === null ) {
-                       $timestamp = Revision::getTimestampFromId( $this->getTitle(), $this->getRevisionId() );
-               }
-
-               if ( $timestamp ) {
-                       $d = $this->getLanguage()->userDate( $timestamp, $this->getUser() );
-                       $t = $this->getLanguage()->userTime( $timestamp, $this->getUser() );
-                       $s = ' ' . $this->msg( 'lastmodifiedat', $d, $t )->text();
-               } else {
-                       $s = '';
-               }
-
-               if ( wfGetLB()->getLaggedSlaveMode() ) {
-                       $s .= ' <strong>' . $this->msg( 'laggedslavemode' )->text() . '</strong>';
-               }
-
-               return $s;
-       }
-
-       /**
-        * @param string $align
-        * @return string
-        */
-       function logoText( $align = '' ) {
-               if ( $align != '' ) {
-                       $a = " style='float: {$align};'";
-               } else {
-                       $a = '';
-               }
-
-               $mp = $this->msg( 'mainpage' )->escaped();
-               $mptitle = Title::newMainPage();
-               $url = ( is_object( $mptitle ) ? htmlspecialchars( $mptitle->getLocalURL() ) : '' );
-
-               $logourl = $this->getLogo();
-               $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
-
-               return $s;
-       }
-
-       /**
-        * Renders a $wgFooterIcons icon according to the method's arguments
-        * @param array $icon The icon to build the html for, see $wgFooterIcons
-        *   for the format of this array.
-        * @param bool|string $withImage Whether to use the icon's image or output
-        *   a text-only footericon.
-        * @return string HTML
-        */
-       function makeFooterIcon( $icon, $withImage = 'withImage' ) {
-               if ( is_string( $icon ) ) {
-                       $html = $icon;
-               } else { // Assuming array
-                       $url = isset( $icon["url"] ) ? $icon["url"] : null;
-                       unset( $icon["url"] );
-                       if ( isset( $icon["src"] ) && $withImage === 'withImage' ) {
-                               // do this the lazy way, just pass icon data as an attribute array
-                               $html = Html::element( 'img', $icon );
-                       } else {
-                               $html = htmlspecialchars( $icon["alt"] );
-                       }
-                       if ( $url ) {
-                               $html = Html::rawElement( 'a', array( "href" => $url ), $html );
-                       }
-               }
-               return $html;
-       }
-
-       /**
-        * Gets the link to the wiki's main page.
-        * @return string
-        */
-       function mainPageLink() {
-               $s = Linker::linkKnown(
-                       Title::newMainPage(),
-                       $this->msg( 'mainpage' )->escaped()
-               );
-
-               return $s;
-       }
-
-       /**
-        * Returns an HTML link for use in the footer
-        * @param string $desc i18n message key for the link text
-        * @param string $page i18n message key for the page to link to
-        * @return string HTML anchor
-        */
-       public function footerLink( $desc, $page ) {
-               // if the link description has been set to "-" in the default language,
-               if ( $this->msg( $desc )->inContentLanguage()->isDisabled() ) {
-                       // then it is disabled, for all languages.
-                       return '';
-               } else {
-                       // Otherwise, we display the link for the user, described in their
-                       // language (which may or may not be the same as the default language),
-                       // but we make the link target be the one site-wide page.
-                       $title = Title::newFromText( $this->msg( $page )->inContentLanguage()->text() );
-
-                       return Linker::linkKnown(
-                               $title,
-                               $this->msg( $desc )->escaped()
-                       );
-               }
-       }
-
-       /**
-        * Gets the link to the wiki's privacy policy page.
-        * @return string HTML
-        */
-       function privacyLink() {
-               return $this->footerLink( 'privacy', 'privacypage' );
-       }
-
-       /**
-        * Gets the link to the wiki's about page.
-        * @return string HTML
-        */
-       function aboutLink() {
-               return $this->footerLink( 'aboutsite', 'aboutpage' );
-       }
-
-       /**
-        * Gets the link to the wiki's general disclaimers page.
-        * @return string HTML
-        */
-       function disclaimerLink() {
-               return $this->footerLink( 'disclaimers', 'disclaimerpage' );
-       }
-
-       /**
-        * Return URL options for the 'edit page' link.
-        * This may include an 'oldid' specifier, if the current page view is such.
-        *
-        * @return array
-        * @private
-        */
-       function editUrlOptions() {
-               $options = array( 'action' => 'edit' );
-
-               if ( !$this->isRevisionCurrent() ) {
-                       $options['oldid'] = intval( $this->getRevisionId() );
-               }
-
-               return $options;
-       }
-
-       /**
-        * @param User|int $id
-        * @return bool
-        */
-       function showEmailUser( $id ) {
-               if ( $id instanceof User ) {
-                       $targetUser = $id;
-               } else {
-                       $targetUser = User::newFromId( $id );
-               }
-
-               # The sending user must have a confirmed email address and the target
-               # user must have a confirmed email address and allow emails from users.
-               return $this->getUser()->canSendEmail() &&
-                       $targetUser->canReceiveEmail();
-       }
-
-       /**
-        * Return a fully resolved style path url to images or styles stored in the common folder.
-        * This method returns a url resolved using the configured skin style path
-        * and includes the style version inside of the url.
-        * @param string $name The name or path of a skin resource file
-        * @return string The fully resolved style path url including styleversion
-        */
-       function getCommonStylePath( $name ) {
-               global $wgStylePath, $wgStyleVersion;
-               return "$wgStylePath/common/$name?$wgStyleVersion";
-       }
-
-       /**
-        * 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
-        * and includes the style version inside of the url.
-        *
-        * Requires $stylename to be set, otherwise throws MWException.
-        *
-        * @param string $name The name or path of a skin resource file
-        * @return string The fully resolved style path url including styleversion
-        */
-       function getSkinStylePath( $name ) {
-               global $wgStylePath, $wgStyleVersion;
-
-               if ( $this->stylename === null ) {
-                       $class = get_class( $this );
-                       throw new MWException( "$class::\$stylename must be set to use getSkinStylePath()" );
-               }
-
-               return "$wgStylePath/{$this->stylename}/$name?$wgStyleVersion";
-       }
-
-       /* these are used extensively in SkinTemplate, but also some other places */
-
-       /**
-        * @param string $urlaction
-        * @return string
-        */
-       static function makeMainPageUrl( $urlaction = '' ) {
-               $title = Title::newMainPage();
-               self::checkTitle( $title, '' );
-
-               return $title->getLocalURL( $urlaction );
-       }
-
-       /**
-        * Make a URL for a Special Page using the given query and protocol.
-        *
-        * If $proto is set to null, make a local URL. Otherwise, make a full
-        * URL with the protocol specified.
-        *
-        * @param string $name Name of the Special page
-        * @param string $urlaction Query to append
-        * @param string|null $proto Protocol to use or null for a local URL
-        * @return string
-        */
-       static function makeSpecialUrl( $name, $urlaction = '', $proto = null ) {
-               $title = SpecialPage::getSafeTitleFor( $name );
-               if ( is_null( $proto ) ) {
-                       return $title->getLocalURL( $urlaction );
-               } else {
-                       return $title->getFullURL( $urlaction, false, $proto );
-               }
-       }
-
-       /**
-        * @param string $name
-        * @param string $subpage
-        * @param string $urlaction
-        * @return string
-        */
-       static function makeSpecialUrlSubpage( $name, $subpage, $urlaction = '' ) {
-               $title = SpecialPage::getSafeTitleFor( $name, $subpage );
-               return $title->getLocalURL( $urlaction );
-       }
-
-       /**
-        * @param string $name
-        * @param string $urlaction
-        * @return string
-        */
-       static function makeI18nUrl( $name, $urlaction = '' ) {
-               $title = Title::newFromText( wfMessage( $name )->inContentLanguage()->text() );
-               self::checkTitle( $title, $name );
-               return $title->getLocalURL( $urlaction );
-       }
-
-       /**
-        * @param string $name
-        * @param string $urlaction
-        * @return string
-        */
-       static function makeUrl( $name, $urlaction = '' ) {
-               $title = Title::newFromText( $name );
-               self::checkTitle( $title, $name );
-
-               return $title->getLocalURL( $urlaction );
-       }
-
-       /**
-        * If url string starts with http, consider as external URL, else
-        * internal
-        * @param string $name
-        * @return string URL
-        */
-       static function makeInternalOrExternalUrl( $name ) {
-               if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $name ) ) {
-                       return $name;
-               } else {
-                       return self::makeUrl( $name );
-               }
-       }
-
-       /**
-        * this can be passed the NS number as defined in Language.php
-        * @param string $name
-        * @param string $urlaction
-        * @param int $namespace
-        * @return string
-        */
-       static function makeNSUrl( $name, $urlaction = '', $namespace = NS_MAIN ) {
-               $title = Title::makeTitleSafe( $namespace, $name );
-               self::checkTitle( $title, $name );
-
-               return $title->getLocalURL( $urlaction );
-       }
-
-       /**
-        * these return an array with the 'href' and boolean 'exists'
-        * @param string $name
-        * @param string $urlaction
-        * @return array
-        */
-       static function makeUrlDetails( $name, $urlaction = '' ) {
-               $title = Title::newFromText( $name );
-               self::checkTitle( $title, $name );
-
-               return array(
-                       'href' => $title->getLocalURL( $urlaction ),
-                       'exists' => $title->getArticleID() != 0,
-               );
-       }
-
-       /**
-        * Make URL details where the article exists (or at least it's convenient to think so)
-        * @param string $name Article name
-        * @param string $urlaction
-        * @return array
-        */
-       static function makeKnownUrlDetails( $name, $urlaction = '' ) {
-               $title = Title::newFromText( $name );
-               self::checkTitle( $title, $name );
-
-               return array(
-                       'href' => $title->getLocalURL( $urlaction ),
-                       'exists' => true
-               );
-       }
-
-       /**
-        * make sure we have some title to operate on
-        *
-        * @param Title $title
-        * @param string $name
-        */
-       static function checkTitle( &$title, $name ) {
-               if ( !is_object( $title ) ) {
-                       $title = Title::newFromText( $name );
-                       if ( !is_object( $title ) ) {
-                               $title = Title::newFromText( '--error: link target missing--' );
-                       }
-               }
-       }
-
-       /**
-        * Build an array that represents the sidebar(s), the navigation bar among them.
-        *
-        * BaseTemplate::getSidebar can be used to simplify the format and id generation in new skins.
-        *
-        * The format of the returned array is array( heading => content, ... ), where:
-        * - heading is the heading of a navigation portlet. It is either:
-        *   - magic string to be handled by the skins ('SEARCH' / 'LANGUAGES' / 'TOOLBOX' / ...)
-        *   - a message name (e.g. 'navigation'), the message should be HTML-escaped by the skin
-        *   - plain text, which should be HTML-escaped by the skin
-        * - content is the contents of the portlet. It is either:
-        *   - HTML text (<ul><li>...</li>...</ul>)
-        *   - array of link data in a format accepted by BaseTemplate::makeListItem()
-        *   - (for a magic string as a key, any value)
-        *
-        * Note that extensions can control the sidebar contents using the SkinBuildSidebar hook
-        * and can technically insert anything in here; skin creators are expected to handle
-        * values described above.
-        *
-        * @return array
-        */
-       function buildSidebar() {
-               global $wgMemc, $wgEnableSidebarCache, $wgSidebarCacheExpiry;
-               wfProfileIn( __METHOD__ );
-
-               $key = wfMemcKey( 'sidebar', $this->getLanguage()->getCode() );
-
-               if ( $wgEnableSidebarCache ) {
-                       $cachedsidebar = $wgMemc->get( $key );
-                       if ( $cachedsidebar ) {
-                               wfRunHooks( 'SidebarBeforeOutput', array( $this, &$cachedsidebar ) );
-
-                               wfProfileOut( __METHOD__ );
-                               return $cachedsidebar;
-                       }
-               }
-
-               $bar = array();
-               $this->addToSidebar( $bar, 'sidebar' );
-
-               wfRunHooks( 'SkinBuildSidebar', array( $this, &$bar ) );
-               if ( $wgEnableSidebarCache ) {
-                       $wgMemc->set( $key, $bar, $wgSidebarCacheExpiry );
-               }
-
-               wfRunHooks( 'SidebarBeforeOutput', array( $this, &$bar ) );
-
-               wfProfileOut( __METHOD__ );
-               return $bar;
-       }
-
-       /**
-        * Add content from a sidebar system message
-        * Currently only used for MediaWiki:Sidebar (but may be used by Extensions)
-        *
-        * This is just a wrapper around addToSidebarPlain() for backwards compatibility
-        *
-        * @param array $bar
-        * @param string $message
-        */
-       function addToSidebar( &$bar, $message ) {
-               $this->addToSidebarPlain( $bar, wfMessage( $message )->inContentLanguage()->plain() );
-       }
-
-       /**
-        * Add content from plain text
-        * @since 1.17
-        * @param array $bar
-        * @param string $text
-        * @return array
-        */
-       function addToSidebarPlain( &$bar, $text ) {
-               $lines = explode( "\n", $text );
-
-               $heading = '';
-
-               foreach ( $lines as $line ) {
-                       if ( strpos( $line, '*' ) !== 0 ) {
-                               continue;
-                       }
-                       $line = rtrim( $line, "\r" ); // for Windows compat
-
-                       if ( strpos( $line, '**' ) !== 0 ) {
-                               $heading = trim( $line, '* ' );
-                               if ( !array_key_exists( $heading, $bar ) ) {
-                                       $bar[$heading] = array();
-                               }
-                       } else {
-                               $line = trim( $line, '* ' );
-
-                               if ( strpos( $line, '|' ) !== false ) { // sanity check
-                                       $line = MessageCache::singleton()->transform( $line, false, null, $this->getTitle() );
-                                       $line = array_map( 'trim', explode( '|', $line, 2 ) );
-                                       if ( count( $line ) !== 2 ) {
-                                               // Second sanity check, could be hit by people doing
-                                               // funky stuff with parserfuncs... (bug 33321)
-                                               continue;
-                                       }
-
-                                       $extraAttribs = array();
-
-                                       $msgLink = $this->msg( $line[0] )->inContentLanguage();
-                                       if ( $msgLink->exists() ) {
-                                               $link = $msgLink->text();
-                                               if ( $link == '-' ) {
-                                                       continue;
-                                               }
-                                       } else {
-                                               $link = $line[0];
-                                       }
-                                       $msgText = $this->msg( $line[1] );
-                                       if ( $msgText->exists() ) {
-                                               $text = $msgText->text();
-                                       } else {
-                                               $text = $line[1];
-                                       }
-
-                                       if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $link ) ) {
-                                               $href = $link;
-
-                                               // Parser::getExternalLinkAttribs won't work here because of the Namespace things
-                                               global $wgNoFollowLinks, $wgNoFollowDomainExceptions;
-                                               if ( $wgNoFollowLinks && !wfMatchesDomainList( $href, $wgNoFollowDomainExceptions ) ) {
-                                                       $extraAttribs['rel'] = 'nofollow';
-                                               }
-
-                                               global $wgExternalLinkTarget;
-                                               if ( $wgExternalLinkTarget ) {
-                                                       $extraAttribs['target'] = $wgExternalLinkTarget;
-                                               }
-                                       } else {
-                                               $title = Title::newFromText( $link );
-
-                                               if ( $title ) {
-                                                       $title = $title->fixSpecialName();
-                                                       $href = $title->getLinkURL();
-                                               } else {
-                                                       $href = 'INVALID-TITLE';
-                                               }
-                                       }
-
-                                       $bar[$heading][] = array_merge( array(
-                                               'text' => $text,
-                                               'href' => $href,
-                                               'id' => 'n-' . Sanitizer::escapeId( strtr( $line[1], ' ', '-' ), 'noninitial' ),
-                                               'active' => false
-                                       ), $extraAttribs );
-                               } else {
-                                       continue;
-                               }
-                       }
-               }
-
-               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)
-        * @return string
-        */
-       function getNewtalks() {
-
-               $newMessagesAlert = '';
-               $user = $this->getUser();
-               $newtalks = $user->getNewMessageLinks();
-               $out = $this->getOutput();
-
-               // Allow extensions to disable or modify the new messages alert
-               if ( !wfRunHooks( 'GetNewMessagesAlert', array( &$newMessagesAlert, $newtalks, $user, $out ) ) ) {
-                       return '';
-               }
-               if ( $newMessagesAlert ) {
-                       return $newMessagesAlert;
-               }
-
-               if ( count( $newtalks ) == 1 && $newtalks[0]['wiki'] === wfWikiID() ) {
-                       $uTalkTitle = $user->getTalkPage();
-                       $lastSeenRev = isset( $newtalks[0]['rev'] ) ? $newtalks[0]['rev'] : null;
-                       $nofAuthors = 0;
-                       if ( $lastSeenRev !== null ) {
-                               $plural = true; // Default if we have a last seen revision: if unknown, use plural
-                               $latestRev = Revision::newFromTitle( $uTalkTitle, false, Revision::READ_NORMAL );
-                               if ( $latestRev !== null ) {
-                                       // Singular if only 1 unseen revision, plural if several unseen revisions.
-                                       $plural = $latestRev->getParentId() !== $lastSeenRev->getId();
-                                       $nofAuthors = $uTalkTitle->countAuthorsBetween(
-                                               $lastSeenRev, $latestRev, 10, 'include_new' );
-                               }
-                       } else {
-                               // Singular if no revision -> diff link will show latest change only in any case
-                               $plural = false;
-                       }
-                       $plural = $plural ? 999 : 1;
-                       // 999 signifies "more than one revision". We don't know how many, and even if we did,
-                       // the number of revisions or authors is not necessarily the same as the number of
-                       // "messages".
-                       $newMessagesLink = Linker::linkKnown(
-                               $uTalkTitle,
-                               $this->msg( 'newmessageslinkplural' )->params( $plural )->escaped(),
-                               array(),
-                               array( 'redirect' => 'no' )
-                       );
-
-                       $newMessagesDiffLink = Linker::linkKnown(
-                               $uTalkTitle,
-                               $this->msg( 'newmessagesdifflinkplural' )->params( $plural )->escaped(),
-                               array(),
-                               $lastSeenRev !== null
-                                       ? array( 'oldid' => $lastSeenRev->getId(), 'diff' => 'cur' )
-                                       : array( 'diff' => 'cur' )
-                       );
-
-                       if ( $nofAuthors >= 1 && $nofAuthors <= 10 ) {
-                               $newMessagesAlert = $this->msg(
-                                       'youhavenewmessagesfromusers',
-                                       $newMessagesLink,
-                                       $newMessagesDiffLink
-                               )->numParams( $nofAuthors, $plural );
-                       } else {
-                               // $nofAuthors === 11 signifies "11 or more" ("more than 10")
-                               $newMessagesAlert = $this->msg(
-                                       $nofAuthors > 10 ? 'youhavenewmessagesmanyusers' : 'youhavenewmessages',
-                                       $newMessagesLink,
-                                       $newMessagesDiffLink
-                               )->numParams( $plural );
-                       }
-                       $newMessagesAlert = $newMessagesAlert->text();
-                       # Disable Squid cache
-                       $out->setSquidMaxage( 0 );
-               } elseif ( count( $newtalks ) ) {
-                       $sep = $this->msg( 'newtalkseparator' )->escaped();
-                       $msgs = array();
-
-                       foreach ( $newtalks as $newtalk ) {
-                               $msgs[] = Xml::element(
-                                       'a',
-                                       array( 'href' => $newtalk['link'] ), $newtalk['wiki']
-                               );
-                       }
-                       $parts = implode( $sep, $msgs );
-                       $newMessagesAlert = $this->msg( 'youhavenewmessagesmulti' )->rawParams( $parts )->escaped();
-                       $out->setSquidMaxage( 0 );
-               }
-
-               return $newMessagesAlert;
-       }
-
-       /**
-        * Get a cached notice
-        *
-        * @param string $name Message name, or 'default' for $wgSiteNotice
-        * @return string HTML fragment
-        */
-       private function getCachedNotice( $name ) {
-               global $wgRenderHashAppend, $parserMemc, $wgContLang;
-
-               wfProfileIn( __METHOD__ );
-
-               $needParse = false;
-
-               if ( $name === 'default' ) {
-                       // special case
-                       global $wgSiteNotice;
-                       $notice = $wgSiteNotice;
-                       if ( empty( $notice ) ) {
-                               wfProfileOut( __METHOD__ );
-                               return false;
-                       }
-               } else {
-                       $msg = $this->msg( $name )->inContentLanguage();
-                       if ( $msg->isDisabled() ) {
-                               wfProfileOut( __METHOD__ );
-                               return false;
-                       }
-                       $notice = $msg->plain();
-               }
-
-               // Use the extra hash appender to let eg SSL variants separately cache.
-               $key = wfMemcKey( $name . $wgRenderHashAppend );
-               $cachedNotice = $parserMemc->get( $key );
-               if ( is_array( $cachedNotice ) ) {
-                       if ( md5( $notice ) == $cachedNotice['hash'] ) {
-                               $notice = $cachedNotice['html'];
-                       } else {
-                               $needParse = true;
-                       }
-               } else {
-                       $needParse = true;
-               }
-
-               if ( $needParse ) {
-                       $parsed = $this->getOutput()->parse( $notice );
-                       $parserMemc->set( $key, array( 'html' => $parsed, 'hash' => md5( $notice ) ), 600 );
-                       $notice = $parsed;
-               }
-
-               $notice = Html::rawElement( 'div', array( 'id' => 'localNotice',
-                       'lang' => $wgContLang->getHtmlCode(), 'dir' => $wgContLang->getDir() ), $notice );
-               wfProfileOut( __METHOD__ );
-               return $notice;
-       }
-
-       /**
-        * Get a notice based on page's namespace
-        *
-        * @return string HTML fragment
-        */
-       function getNamespaceNotice() {
-               wfProfileIn( __METHOD__ );
-
-               $key = 'namespacenotice-' . $this->getTitle()->getNsText();
-               $namespaceNotice = $this->getCachedNotice( $key );
-               if ( $namespaceNotice && substr( $namespaceNotice, 0, 7 ) != '<p>&lt;' ) {
-                       $namespaceNotice = '<div id="namespacebanner">' . $namespaceNotice . '</div>';
-               } else {
-                       $namespaceNotice = '';
-               }
-
-               wfProfileOut( __METHOD__ );
-               return $namespaceNotice;
-       }
-
-       /**
-        * Get the site notice
-        *
-        * @return string HTML fragment
-        */
-       function getSiteNotice() {
-               wfProfileIn( __METHOD__ );
-               $siteNotice = '';
-
-               if ( wfRunHooks( 'SiteNoticeBefore', array( &$siteNotice, $this ) ) ) {
-                       if ( is_object( $this->getUser() ) && $this->getUser()->isLoggedIn() ) {
-                               $siteNotice = $this->getCachedNotice( 'sitenotice' );
-                       } else {
-                               $anonNotice = $this->getCachedNotice( 'anonnotice' );
-                               if ( !$anonNotice ) {
-                                       $siteNotice = $this->getCachedNotice( 'sitenotice' );
-                               } else {
-                                       $siteNotice = $anonNotice;
-                               }
-                       }
-                       if ( !$siteNotice ) {
-                               $siteNotice = $this->getCachedNotice( 'default' );
-                       }
-               }
-
-               wfRunHooks( 'SiteNoticeAfter', array( &$siteNotice, $this ) );
-               wfProfileOut( __METHOD__ );
-               return $siteNotice;
-       }
-
-       /**
-        * Create a section edit link.  This supersedes editSectionLink() and
-        * editSectionLinkForOther().
-        *
-        * @param Title $nt The title being linked to (may not be the same as
-        *   the current page, if the section is included from a template)
-        * @param string $section The designation of the section being pointed to,
-        *   to be included in the link, like "&section=$section"
-        * @param string $tooltip The tooltip to use for the link: will be escaped
-        *   and wrapped in the 'editsectionhint' message
-        * @param string $lang Language code
-        * @return string HTML to use for edit link
-        */
-       public function doEditSectionLink( Title $nt, $section, $tooltip = null, $lang = false ) {
-               // HTML generated here should probably have userlangattributes
-               // added to it for LTR text on RTL pages
-
-               $lang = wfGetLangObj( $lang );
-
-               $attribs = array();
-               if ( !is_null( $tooltip ) ) {
-                       # Bug 25462: undo double-escaping.
-                       $tooltip = Sanitizer::decodeCharReferences( $tooltip );
-                       $attribs['title'] = wfMessage( 'editsectionhint' )->rawParams( $tooltip )
-                               ->inLanguage( $lang )->text();
-               }
-               $link = Linker::link( $nt, wfMessage( 'editsection' )->inLanguage( $lang )->text(),
-                       $attribs,
-                       array( 'action' => 'edit', 'section' => $section ),
-                       array( 'noclasses', 'known' )
-               );
-
-               # Add the brackets and the span and run the hook.
-               $result = '<span class="mw-editsection">'
-                       . '<span class="mw-editsection-bracket">[</span>'
-                       . $link
-                       . '<span class="mw-editsection-bracket">]</span>'
-                       . '</span>';
-
-               wfRunHooks( 'DoEditSectionLink', array( $this, $nt, $section, $tooltip, &$result, $lang ) );
-               return $result;
-       }
-
-       /**
-        * Use PHP's magic __call handler to intercept legacy calls to the linker
-        * for backwards compatibility.
-        *
-        * @param string $fname Name of called method
-        * @param array $args Arguments to the method
-        * @throws MWException
-        * @return mixed
-        */
-       function __call( $fname, $args ) {
-               $realFunction = array( 'Linker', $fname );
-               if ( is_callable( $realFunction ) ) {
-                       wfDeprecated( get_class( $this ) . '::' . $fname, '1.21' );
-                       return call_user_func_array( $realFunction, $args );
-               } else {
-                       $className = get_class( $this );
-                       throw new MWException( "Call to undefined method $className::$fname" );
-               }
-       }
-
-}
diff --git a/includes/SkinTemplate.php b/includes/SkinTemplate.php
deleted file mode 100644 (file)
index 97c0ec4..0000000
+++ /dev/null
@@ -1,2121 +0,0 @@
-<?php
-/**
- * Base class for template-based skins.
- *
- * 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
- */
-
-/**
- * Wrapper object for MediaWiki's localization functions,
- * to be passed to the template engine.
- *
- * @private
- * @ingroup Skins
- */
-class MediaWikiI18N {
-       private $context = array();
-
-       function set( $varName, $value ) {
-               $this->context[$varName] = $value;
-       }
-
-       function translate( $value ) {
-               wfProfileIn( __METHOD__ );
-
-               // Hack for i18n:attributes in PHPTAL 1.0.0 dev version as of 2004-10-23
-               $value = preg_replace( '/^string:/', '', $value );
-
-               $value = wfMessage( $value )->text();
-               // interpolate variables
-               $m = array();
-               while ( preg_match( '/\$([0-9]*?)/sm', $value, $m ) ) {
-                       list( $src, $var ) = $m;
-                       wfSuppressWarnings();
-                       $varValue = $this->context[$var];
-                       wfRestoreWarnings();
-                       $value = str_replace( $src, $varValue, $value );
-               }
-               wfProfileOut( __METHOD__ );
-               return $value;
-       }
-}
-
-/**
- * Template-filler skin base class
- * Formerly generic PHPTal (http://phptal.sourceforge.net/) skin
- * Based on Brion's smarty skin
- * @copyright Copyright © Gabriel Wicke -- http://www.aulinx.de/
- *
- * @todo Needs some serious refactoring into functions that correspond
- * to the computations individual esi snippets need. Most importantly no body
- * parsing for most of those of course.
- *
- * @ingroup Skins
- */
-class SkinTemplate extends Skin {
-       /**
-        * @var string Name of our skin, it probably needs to be all lower case.
-        *   Child classes should override the default.
-        */
-       public $skinname = 'monobook';
-
-       /**
-        * @var string For QuickTemplate, the name of the subclass which will
-        *   actually fill the template.  Child classes should override the default.
-        */
-       public $template = 'QuickTemplate';
-
-       /**
-        * Add specific styles for this skin
-        *
-        * @param OutputPage $out
-        */
-       function setupSkinUserCss( OutputPage $out ) {
-               $out->addModuleStyles( array(
-                       'mediawiki.legacy.shared',
-                       'mediawiki.legacy.commonPrint',
-                       'mediawiki.ui.button'
-               ) );
-       }
-
-       /**
-        * Create the template engine object; we feed it a bunch of data
-        * and eventually it spits out some HTML. Should have interface
-        * roughly equivalent to PHPTAL 0.7.
-        *
-        * @param string $classname
-        * @param bool|string $repository Subdirectory where we keep template files
-        * @param bool|string $cache_dir
-        * @return QuickTemplate
-        * @private
-        */
-       function setupTemplate( $classname, $repository = false, $cache_dir = false ) {
-               return new $classname();
-       }
-
-       /**
-        * Generates array of language links for the current page
-        *
-        * @return array
-        */
-       public function getLanguages() {
-               global $wgHideInterlanguageLinks;
-               if ( $wgHideInterlanguageLinks ) {
-                       return array();
-               }
-
-               $userLang = $this->getLanguage();
-               $languageLinks = array();
-
-               foreach ( $this->getOutput()->getLanguageLinks() as $languageLinkText ) {
-                       $languageLinkParts = explode( ':', $languageLinkText, 2 );
-                       $class = 'interlanguage-link interwiki-' . $languageLinkParts[0];
-                       unset( $languageLinkParts );
-
-                       $languageLinkTitle = Title::newFromText( $languageLinkText );
-                       if ( $languageLinkTitle ) {
-                               $ilInterwikiCode = $languageLinkTitle->getInterwiki();
-                               $ilLangName = Language::fetchLanguageName( $ilInterwikiCode );
-
-                               if ( strval( $ilLangName ) === '' ) {
-                                       $ilDisplayTextMsg = wfMessage( "interlanguage-link-$ilInterwikiCode" );
-                                       if ( !$ilDisplayTextMsg->isDisabled() ) {
-                                               // Use custom MW message for the display text
-                                               $ilLangName = $ilDisplayTextMsg->text();
-                                       } else {
-                                               // Last resort: fallback to the language link target
-                                               $ilLangName = $languageLinkText;
-                                       }
-                               } else {
-                                       // Use the language autonym as display text
-                                       $ilLangName = $this->formatLanguageName( $ilLangName );
-                               }
-
-                               // CLDR extension or similar is required to localize the language name;
-                               // otherwise we'll end up with the autonym again.
-                               $ilLangLocalName = Language::fetchLanguageName(
-                                       $ilInterwikiCode,
-                                       $userLang->getCode()
-                               );
-
-                               $languageLinkTitleText = $languageLinkTitle->getText();
-                               if ( $ilLangLocalName === '' ) {
-                                       $ilFriendlySiteName = wfMessage( "interlanguage-link-sitename-$ilInterwikiCode" );
-                                       if ( !$ilFriendlySiteName->isDisabled() ) {
-                                               if ( $languageLinkTitleText === '' ) {
-                                                       $ilTitle = wfMessage(
-                                                               'interlanguage-link-title-nonlangonly',
-                                                               $ilFriendlySiteName->text()
-                                                       )->text();
-                                               } else {
-                                                       $ilTitle = wfMessage(
-                                                               'interlanguage-link-title-nonlang',
-                                                               $languageLinkTitleText,
-                                                               $ilFriendlySiteName->text()
-                                                       )->text();
-                                               }
-                                       } else {
-                                               // we have nothing friendly to put in the title, so fall back to
-                                               // displaying the interlanguage link itself in the title text
-                                               // (similar to what is done in page content)
-                                               $ilTitle = $languageLinkTitle->getInterwiki() .
-                                                       ":$languageLinkTitleText";
-                                       }
-                               } elseif ( $languageLinkTitleText === '' ) {
-                                       $ilTitle = wfMessage(
-                                               'interlanguage-link-title-langonly',
-                                               $ilLangLocalName
-                                       )->text();
-                               } else {
-                                       $ilTitle = wfMessage(
-                                               'interlanguage-link-title',
-                                               $languageLinkTitleText,
-                                               $ilLangLocalName
-                                       )->text();
-                               }
-
-                               $ilInterwikiCodeBCP47 = wfBCP47( $ilInterwikiCode );
-                               $languageLink = array(
-                                       'href' => $languageLinkTitle->getFullURL(),
-                                       'text' => $ilLangName,
-                                       'title' => $ilTitle,
-                                       'class' => $class,
-                                       'lang' => $ilInterwikiCodeBCP47,
-                                       'hreflang' => $ilInterwikiCodeBCP47,
-                               );
-                               wfRunHooks(
-                                       'SkinTemplateGetLanguageLink',
-                                       array( &$languageLink, $languageLinkTitle, $this->getTitle() )
-                               );
-                               $languageLinks[] = $languageLink;
-                       }
-               }
-
-               return $languageLinks;
-       }
-
-       protected function setupTemplateForOutput() {
-               wfProfileIn( __METHOD__ );
-
-               $request = $this->getRequest();
-               $user = $this->getUser();
-               $title = $this->getTitle();
-
-               wfProfileIn( __METHOD__ . '-init' );
-               $tpl = $this->setupTemplate( $this->template, 'skins' );
-               wfProfileOut( __METHOD__ . '-init' );
-
-               wfProfileIn( __METHOD__ . '-stuff' );
-               $this->thispage = $title->getPrefixedDBkey();
-               $this->titletxt = $title->getPrefixedText();
-               $this->userpage = $user->getUserPage()->getPrefixedText();
-               $query = array();
-               if ( !$request->wasPosted() ) {
-                       $query = $request->getValues();
-                       unset( $query['title'] );
-                       unset( $query['returnto'] );
-                       unset( $query['returntoquery'] );
-               }
-               $this->thisquery = wfArrayToCgi( $query );
-               $this->loggedin = $user->isLoggedIn();
-               $this->username = $user->getName();
-
-               if ( $this->loggedin || $this->showIPinHeader() ) {
-                       $this->userpageUrlDetails = self::makeUrlDetails( $this->userpage );
-               } else {
-                       # This won't be used in the standard skins, but we define it to preserve the interface
-                       # To save time, we check for existence
-                       $this->userpageUrlDetails = self::makeKnownUrlDetails( $this->userpage );
-               }
-
-               wfProfileOut( __METHOD__ . '-stuff' );
-
-               wfProfileOut( __METHOD__ );
-
-               return $tpl;
-       }
-
-       /**
-        * initialize various variables and generate the template
-        *
-        * @param OutputPage $out
-        */
-       function outputPage( OutputPage $out = null ) {
-               wfProfileIn( __METHOD__ );
-               Profiler::instance()->setTemplated( true );
-
-               $oldContext = null;
-               if ( $out !== null ) {
-                       // @todo Add wfDeprecated in 1.20
-                       $oldContext = $this->getContext();
-                       $this->setContext( $out->getContext() );
-               }
-
-               $out = $this->getOutput();
-
-               wfProfileIn( __METHOD__ . '-init' );
-               $this->initPage( $out );
-               wfProfileOut( __METHOD__ . '-init' );
-               $tpl = $this->prepareQuickTemplate( $out );
-               // execute template
-               wfProfileIn( __METHOD__ . '-execute' );
-               $res = $tpl->execute();
-               wfProfileOut( __METHOD__ . '-execute' );
-
-               // result may be an error
-               $this->printOrError( $res );
-
-               if ( $oldContext ) {
-                       $this->setContext( $oldContext );
-               }
-
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * initialize various variables and generate the template
-        *
-        * @since 1.23
-        * @return QuickTemplate The template to be executed by outputPage
-        */
-       protected function prepareQuickTemplate() {
-               global $wgContLang, $wgScript, $wgStylePath,
-                       $wgMimeType, $wgJsMimeType, $wgXhtmlNamespaces, $wgHtml5Version,
-                       $wgDisableCounters, $wgSitename, $wgLogo, $wgMaxCredits,
-                       $wgShowCreditsIfMax, $wgPageShowWatchingUsers, $wgArticlePath,
-                       $wgScriptPath, $wgServer;
-
-               wfProfileIn( __METHOD__ );
-
-               $title = $this->getTitle();
-               $request = $this->getRequest();
-               $out = $this->getOutput();
-               $tpl = $this->setupTemplateForOutput();
-
-               wfProfileIn( __METHOD__ . '-stuff2' );
-               $tpl->set( 'title', $out->getPageTitle() );
-               $tpl->set( 'pagetitle', $out->getHTMLTitle() );
-               $tpl->set( 'displaytitle', $out->mPageLinkTitle );
-
-               $tpl->setRef( 'thispage', $this->thispage );
-               $tpl->setRef( 'titleprefixeddbkey', $this->thispage );
-               $tpl->set( 'titletext', $title->getText() );
-               $tpl->set( 'articleid', $title->getArticleID() );
-
-               $tpl->set( 'isarticle', $out->isArticle() );
-
-               $subpagestr = $this->subPageSubtitle();
-               if ( $subpagestr !== '' ) {
-                       $subpagestr = '<span class="subpages">' . $subpagestr . '</span>';
-               }
-               $tpl->set( 'subtitle', $subpagestr . $out->getSubtitle() );
-
-               $undelete = $this->getUndeleteLink();
-               if ( $undelete === '' ) {
-                       $tpl->set( 'undelete', '' );
-               } else {
-                       $tpl->set( 'undelete', '<span class="subpages">' . $undelete . '</span>' );
-               }
-
-               $tpl->set( 'catlinks', $this->getCategories() );
-               if ( $out->isSyndicated() ) {
-                       $feeds = array();
-                       foreach ( $out->getSyndicationLinks() as $format => $link ) {
-                               $feeds[$format] = array(
-                                       // Messages: feed-atom, feed-rss
-                                       'text' => $this->msg( "feed-$format" )->text(),
-                                       'href' => $link
-                               );
-                       }
-                       $tpl->setRef( 'feeds', $feeds );
-               } else {
-                       $tpl->set( 'feeds', false );
-               }
-
-               $tpl->setRef( 'mimetype', $wgMimeType );
-               $tpl->setRef( 'jsmimetype', $wgJsMimeType );
-               $tpl->set( 'charset', 'UTF-8' );
-               $tpl->setRef( 'wgScript', $wgScript );
-               $tpl->setRef( 'skinname', $this->skinname );
-               $tpl->set( 'skinclass', get_class( $this ) );
-               $tpl->setRef( 'skin', $this );
-               $tpl->setRef( 'stylename', $this->stylename );
-               $tpl->set( 'printable', $out->isPrintable() );
-               $tpl->set( 'handheld', $request->getBool( 'handheld' ) );
-               $tpl->setRef( 'loggedin', $this->loggedin );
-               $tpl->set( 'notspecialpage', !$title->isSpecialPage() );
-               /* XXX currently unused, might get useful later
-               $tpl->set( 'editable', ( !$title->isSpecialPage() ) );
-               $tpl->set( 'exists', $title->getArticleID() != 0 );
-               $tpl->set( 'watch', $user->isWatched( $title ) ? 'unwatch' : 'watch' );
-               $tpl->set( 'protect', count( $title->isProtected() ) ? 'unprotect' : 'protect' );
-               $tpl->set( 'helppage', $this->msg( 'helppage' )->text() );
-               */
-               $tpl->set( 'searchaction', $this->escapeSearchLink() );
-               $tpl->set( 'searchtitle', SpecialPage::getTitleFor( 'Search' )->getPrefixedDBkey() );
-               $tpl->set( 'search', trim( $request->getVal( 'search' ) ) );
-               $tpl->setRef( 'stylepath', $wgStylePath );
-               $tpl->setRef( 'articlepath', $wgArticlePath );
-               $tpl->setRef( 'scriptpath', $wgScriptPath );
-               $tpl->setRef( 'serverurl', $wgServer );
-               $tpl->setRef( 'logopath', $wgLogo );
-               $tpl->setRef( 'sitename', $wgSitename );
-
-               $userLang = $this->getLanguage();
-               $userLangCode = $userLang->getHtmlCode();
-               $userLangDir = $userLang->getDir();
-
-               $tpl->set( 'lang', $userLangCode );
-               $tpl->set( 'dir', $userLangDir );
-               $tpl->set( 'rtl', $userLang->isRTL() );
-
-               $tpl->set( 'capitalizeallnouns', $userLang->capitalizeAllNouns() ? ' capitalize-all-nouns' : '' );
-               $tpl->set( 'showjumplinks', true ); // showjumplinks preference has been removed
-               $tpl->set( 'username', $this->loggedin ? $this->username : null );
-               $tpl->setRef( 'userpage', $this->userpage );
-               $tpl->setRef( 'userpageurl', $this->userpageUrlDetails['href'] );
-               $tpl->set( 'userlang', $userLangCode );
-
-               // Users can have their language set differently than the
-               // content of the wiki. For these users, tell the web browser
-               // that interface elements are in a different language.
-               $tpl->set( 'userlangattributes', '' );
-               $tpl->set( 'specialpageattributes', '' ); # obsolete
-               // Used by VectorBeta to insert HTML before content but after the
-               // heading for the page title. Defaults to empty string.
-               $tpl->set( 'prebodyhtml', '' );
-
-               if ( $userLangCode !== $wgContLang->getHtmlCode() || $userLangDir !== $wgContLang->getDir() ) {
-                       $escUserlang = htmlspecialchars( $userLangCode );
-                       $escUserdir = htmlspecialchars( $userLangDir );
-                       // Attributes must be in double quotes because htmlspecialchars() doesn't
-                       // escape single quotes
-                       $attrs = " lang=\"$escUserlang\" dir=\"$escUserdir\"";
-                       $tpl->set( 'userlangattributes', $attrs );
-               }
-
-               wfProfileOut( __METHOD__ . '-stuff2' );
-
-               wfProfileIn( __METHOD__ . '-stuff3' );
-               $tpl->set( 'newtalk', $this->getNewtalks() );
-               $tpl->set( 'logo', $this->logoText() );
-
-               $tpl->set( 'copyright', false );
-               $tpl->set( 'viewcount', false );
-               $tpl->set( 'lastmod', false );
-               $tpl->set( 'credits', false );
-               $tpl->set( 'numberofwatchingusers', false );
-               if ( $out->isArticle() && $title->exists() ) {
-                       if ( $this->isRevisionCurrent() ) {
-                               if ( !$wgDisableCounters ) {
-                                       $viewcount = $this->getWikiPage()->getCount();
-                                       if ( $viewcount ) {
-                                               $tpl->set( 'viewcount', $this->msg( 'viewcount' )->numParams( $viewcount )->parse() );
-                                       }
-                               }
-
-                               if ( $wgPageShowWatchingUsers ) {
-                                       $dbr = wfGetDB( DB_SLAVE );
-                                       $num = $dbr->selectField( 'watchlist', 'COUNT(*)',
-                                               array( 'wl_title' => $title->getDBkey(), 'wl_namespace' => $title->getNamespace() ),
-                                               __METHOD__
-                                       );
-                                       if ( $num > 0 ) {
-                                               $tpl->set( 'numberofwatchingusers',
-                                                       $this->msg( 'number_of_watching_users_pageview' )->numParams( $num )->parse()
-                                               );
-                                       }
-                               }
-
-                               if ( $wgMaxCredits != 0 ) {
-                                       $tpl->set( 'credits', Action::factory( 'credits', $this->getWikiPage(),
-                                               $this->getContext() )->getCredits( $wgMaxCredits, $wgShowCreditsIfMax ) );
-                               } else {
-                                       $tpl->set( 'lastmod', $this->lastModified() );
-                               }
-                       }
-                       $tpl->set( 'copyright', $this->getCopyright() );
-               }
-               wfProfileOut( __METHOD__ . '-stuff3' );
-
-               wfProfileIn( __METHOD__ . '-stuff4' );
-               $tpl->set( 'copyrightico', $this->getCopyrightIcon() );
-               $tpl->set( 'poweredbyico', $this->getPoweredBy() );
-               $tpl->set( 'disclaimer', $this->disclaimerLink() );
-               $tpl->set( 'privacy', $this->privacyLink() );
-               $tpl->set( 'about', $this->aboutLink() );
-
-               $tpl->set( 'footerlinks', array(
-                       'info' => array(
-                               'lastmod',
-                               'viewcount',
-                               'numberofwatchingusers',
-                               'credits',
-                               'copyright',
-                       ),
-                       'places' => array(
-                               'privacy',
-                               'about',
-                               'disclaimer',
-                       ),
-               ) );
-
-               global $wgFooterIcons;
-               $tpl->set( 'footericons', $wgFooterIcons );
-               foreach ( $tpl->data['footericons'] as $footerIconsKey => &$footerIconsBlock ) {
-                       if ( count( $footerIconsBlock ) > 0 ) {
-                               foreach ( $footerIconsBlock as &$footerIcon ) {
-                                       if ( isset( $footerIcon['src'] ) ) {
-                                               if ( !isset( $footerIcon['width'] ) ) {
-                                                       $footerIcon['width'] = 88;
-                                               }
-                                               if ( !isset( $footerIcon['height'] ) ) {
-                                                       $footerIcon['height'] = 31;
-                                               }
-                                       }
-                               }
-                       } else {
-                               unset( $tpl->data['footericons'][$footerIconsKey] );
-                       }
-               }
-
-               $tpl->set( 'sitenotice', $this->getSiteNotice() );
-               $tpl->set( 'bottomscripts', $this->bottomScripts() );
-               $tpl->set( 'printfooter', $this->printSource() );
-
-               # An ID that includes the actual body text; without categories, contentSub, ...
-               $realBodyAttribs = array( 'id' => 'mw-content-text' );
-
-               # Add a mw-content-ltr/rtl class to be able to style based on text direction
-               # when the content is different from the UI language, i.e.:
-               # not for special pages or file pages AND only when viewing AND if the page exists
-               # (or is in MW namespace, because that has default content)
-               if ( !in_array( $title->getNamespace(), array( NS_SPECIAL, NS_FILE ) ) &&
-                       Action::getActionName( $this ) === 'view' &&
-                       ( $title->exists() || $title->getNamespace() == NS_MEDIAWIKI ) ) {
-                       $pageLang = $title->getPageViewLanguage();
-                       $realBodyAttribs['lang'] = $pageLang->getHtmlCode();
-                       $realBodyAttribs['dir'] = $pageLang->getDir();
-                       $realBodyAttribs['class'] = 'mw-content-' . $pageLang->getDir();
-               }
-
-               $out->mBodytext = Html::rawElement( 'div', $realBodyAttribs, $out->mBodytext );
-               $tpl->setRef( 'bodytext', $out->mBodytext );
-
-               $language_urls = $this->getLanguages();
-               if ( count( $language_urls ) ) {
-                       $tpl->setRef( 'language_urls', $language_urls );
-               } else {
-                       $tpl->set( 'language_urls', false );
-               }
-               wfProfileOut( __METHOD__ . '-stuff4' );
-
-               wfProfileIn( __METHOD__ . '-stuff5' );
-               # Personal toolbar
-               $tpl->set( 'personal_urls', $this->buildPersonalUrls() );
-               $content_navigation = $this->buildContentNavigationUrls();
-               $content_actions = $this->buildContentActionUrls( $content_navigation );
-               $tpl->setRef( 'content_navigation', $content_navigation );
-               $tpl->setRef( 'content_actions', $content_actions );
-
-               $tpl->set( 'sidebar', $this->buildSidebar() );
-               $tpl->set( 'nav_urls', $this->buildNavUrls() );
-
-               // Set the head scripts near the end, in case the above actions resulted in added scripts
-               $tpl->set( 'headelement', $out->headElement( $this ) );
-
-               $tpl->set( 'debug', '' );
-               $tpl->set( 'debughtml', $this->generateDebugHTML() );
-               $tpl->set( 'reporttime', wfReportTime() );
-
-               // original version by hansm
-               if ( !wfRunHooks( 'SkinTemplateOutputPageBeforeExec', array( &$this, &$tpl ) ) ) {
-                       wfDebug( __METHOD__ . ": Hook SkinTemplateOutputPageBeforeExec broke outputPage execution!\n" );
-               }
-
-               // Set the bodytext to another key so that skins can just output it on it's own
-               // and output printfooter and debughtml separately
-               $tpl->set( 'bodycontent', $tpl->data['bodytext'] );
-
-               // Append printfooter and debughtml onto bodytext so that skins that
-               // were already using bodytext before they were split out don't suddenly
-               // start not outputting information.
-               $tpl->data['bodytext'] .= Html::rawElement(
-                       'div',
-                       array( 'class' => 'printfooter' ),
-                       "\n{$tpl->data['printfooter']}"
-               ) . "\n";
-               $tpl->data['bodytext'] .= $tpl->data['debughtml'];
-
-               // allow extensions adding stuff after the page content.
-               // See Skin::afterContentHook() for further documentation.
-               $tpl->set( 'dataAfterContent', $this->afterContentHook() );
-               wfProfileOut( __METHOD__ . '-stuff5' );
-
-               wfProfileOut( __METHOD__ );
-               return $tpl;
-       }
-
-       /**
-        * Get the HTML for the p-personal list
-        * @return string
-        */
-       public function getPersonalToolsList() {
-               $tpl = $this->setupTemplateForOutput();
-               $tpl->set( 'personal_urls', $this->buildPersonalUrls() );
-               $html = '';
-               foreach ( $tpl->getPersonalTools() as $key => $item ) {
-                       $html .= $tpl->makeListItem( $key, $item );
-               }
-               return $html;
-       }
-
-       /**
-        * Format language name for use in sidebar interlanguage links list.
-        * By default it is capitalized.
-        *
-        * @param string $name Language name, e.g. "English" or "español"
-        * @return string
-        * @private
-        */
-       function formatLanguageName( $name ) {
-               return $this->getLanguage()->ucfirst( $name );
-       }
-
-       /**
-        * Output the string, or print error message if it's
-        * an error object of the appropriate type.
-        * For the base class, assume strings all around.
-        *
-        * @param string $str
-        * @private
-        */
-       function printOrError( $str ) {
-               echo $str;
-       }
-
-       /**
-        * Output a boolean indicating if buildPersonalUrls should output separate
-        * login and create account links or output a combined link
-        * By default we simply return a global config setting that affects most skins
-        * This is setup as a method so that like with $wgLogo and getLogo() a skin
-        * can override this setting and always output one or the other if it has
-        * a reason it can't output one of the two modes.
-        * @return bool
-        */
-       function useCombinedLoginLink() {
-               global $wgUseCombinedLoginLink;
-               return $wgUseCombinedLoginLink;
-       }
-
-       /**
-        * build array of urls for personal toolbar
-        * @return array
-        */
-       protected function buildPersonalUrls() {
-               $title = $this->getTitle();
-               $request = $this->getRequest();
-               $pageurl = $title->getLocalURL();
-               wfProfileIn( __METHOD__ );
-
-               /* set up the default links for the personal toolbar */
-               $personal_urls = array();
-
-               # Due to bug 32276, if a user does not have read permissions,
-               # $this->getTitle() will just give Special:Badtitle, which is
-               # not especially useful as a returnto parameter. Use the title
-               # from the request instead, if there was one.
-               if ( $this->getUser()->isAllowed( 'read' ) ) {
-                       $page = $this->getTitle();
-               } else {
-                       $page = Title::newFromText( $request->getVal( 'title', '' ) );
-               }
-               $page = $request->getVal( 'returnto', $page );
-               $a = array();
-               if ( strval( $page ) !== '' ) {
-                       $a['returnto'] = $page;
-                       $query = $request->getVal( 'returntoquery', $this->thisquery );
-                       if ( $query != '' ) {
-                               $a['returntoquery'] = $query;
-                       }
-               }
-
-               $returnto = wfArrayToCgi( $a );
-               if ( $this->loggedin ) {
-                       $personal_urls['userpage'] = array(
-                               'text' => $this->username,
-                               'href' => &$this->userpageUrlDetails['href'],
-                               'class' => $this->userpageUrlDetails['exists'] ? false : 'new',
-                               'active' => ( $this->userpageUrlDetails['href'] == $pageurl ),
-                               'dir' => 'auto'
-                       );
-                       $usertalkUrlDetails = $this->makeTalkUrlDetails( $this->userpage );
-                       $personal_urls['mytalk'] = array(
-                               'text' => $this->msg( 'mytalk' )->text(),
-                               'href' => &$usertalkUrlDetails['href'],
-                               'class' => $usertalkUrlDetails['exists'] ? false : 'new',
-                               'active' => ( $usertalkUrlDetails['href'] == $pageurl )
-                       );
-                       $href = self::makeSpecialUrl( 'Preferences' );
-                       $personal_urls['preferences'] = array(
-                               'text' => $this->msg( 'mypreferences' )->text(),
-                               'href' => $href,
-                               'active' => ( $href == $pageurl )
-                       );
-
-                       if ( $this->getUser()->isAllowed( 'viewmywatchlist' ) ) {
-                               $href = self::makeSpecialUrl( 'Watchlist' );
-                               $personal_urls['watchlist'] = array(
-                                       'text' => $this->msg( 'mywatchlist' )->text(),
-                                       'href' => $href,
-                                       'active' => ( $href == $pageurl )
-                               );
-                       }
-
-                       # We need to do an explicit check for Special:Contributions, as we
-                       # have to match both the title, and the target, which could come
-                       # from request values (Special:Contributions?target=Jimbo_Wales)
-                       # or be specified in "sub page" form
-                       # (Special:Contributions/Jimbo_Wales). The plot
-                       # thickens, because the Title object is altered for special pages,
-                       # so it doesn't contain the original alias-with-subpage.
-                       $origTitle = Title::newFromText( $request->getText( 'title' ) );
-                       if ( $origTitle instanceof Title && $origTitle->isSpecialPage() ) {
-                               list( $spName, $spPar ) = SpecialPageFactory::resolveAlias( $origTitle->getText() );
-                               $active = $spName == 'Contributions'
-                                       && ( ( $spPar && $spPar == $this->username )
-                                               || $request->getText( 'target' ) == $this->username );
-                       } else {
-                               $active = false;
-                       }
-
-                       $href = self::makeSpecialUrlSubpage( 'Contributions', $this->username );
-                       $personal_urls['mycontris'] = array(
-                               'text' => $this->msg( 'mycontris' )->text(),
-                               'href' => $href,
-                               'active' => $active
-                       );
-                       $personal_urls['logout'] = array(
-                               'text' => $this->msg( 'pt-userlogout' )->text(),
-                               'href' => self::makeSpecialUrl( 'Userlogout',
-                                       // userlogout link must always contain an & character, otherwise we might not be able
-                                       // to detect a buggy precaching proxy (bug 17790)
-                                       $title->isSpecial( 'Preferences' ) ? 'noreturnto' : $returnto
-                               ),
-                               'active' => false
-                       );
-               } else {
-                       $useCombinedLoginLink = $this->useCombinedLoginLink();
-                       $loginlink = $this->getUser()->isAllowed( 'createaccount' ) && $useCombinedLoginLink
-                               ? 'nav-login-createaccount'
-                               : 'pt-login';
-                       $is_signup = $request->getText( 'type' ) == 'signup';
-
-                       $login_url = array(
-                               'text' => $this->msg( $loginlink )->text(),
-                               'href' => self::makeSpecialUrl( 'Userlogin', $returnto ),
-                               'active' => $title->isSpecial( 'Userlogin' )
-                                       && ( $loginlink == 'nav-login-createaccount' || !$is_signup ),
-                       );
-                       $createaccount_url = array(
-                               'text' => $this->msg( 'pt-createaccount' )->text(),
-                               'href' => self::makeSpecialUrl( 'Userlogin', "$returnto&type=signup" ),
-                               'active' => $title->isSpecial( 'Userlogin' ) && $is_signup,
-                       );
-
-                       if ( $this->showIPinHeader() ) {
-                               $href = &$this->userpageUrlDetails['href'];
-                               $personal_urls['anonuserpage'] = array(
-                                       'text' => $this->username,
-                                       'href' => $href,
-                                       'class' => $this->userpageUrlDetails['exists'] ? false : 'new',
-                                       'active' => ( $pageurl == $href )
-                               );
-                               $usertalkUrlDetails = $this->makeTalkUrlDetails( $this->userpage );
-                               $href = &$usertalkUrlDetails['href'];
-                               $personal_urls['anontalk'] = array(
-                                       'text' => $this->msg( 'anontalk' )->text(),
-                                       'href' => $href,
-                                       'class' => $usertalkUrlDetails['exists'] ? false : 'new',
-                                       'active' => ( $pageurl == $href )
-                               );
-                       }
-
-                       if ( $this->getUser()->isAllowed( 'createaccount' ) && !$useCombinedLoginLink ) {
-                               $personal_urls['createaccount'] = $createaccount_url;
-                       }
-
-                       $personal_urls['login'] = $login_url;
-               }
-
-               wfRunHooks( 'PersonalUrls', array( &$personal_urls, &$title, $this ) );
-               wfProfileOut( __METHOD__ );
-               return $personal_urls;
-       }
-
-       /**
-        * Builds an array with tab definition
-        *
-        * @param Title $title page Where the tab links to
-        * @param string|array $message Message key or an array of message keys (will fall back)
-        * @param bool $selected Display the tab as selected
-        * @param string $query Query string attached to tab URL
-        * @param bool $checkEdit Check if $title exists and mark with .new if one doesn't
-        *
-        * @return array
-        */
-       function tabAction( $title, $message, $selected, $query = '', $checkEdit = false ) {
-               $classes = array();
-               if ( $selected ) {
-                       $classes[] = 'selected';
-               }
-               if ( $checkEdit && !$title->isKnown() ) {
-                       $classes[] = 'new';
-                       if ( $query !== '' ) {
-                               $query = 'action=edit&redlink=1&' . $query;
-                       } else {
-                               $query = 'action=edit&redlink=1';
-                       }
-               }
-
-               // wfMessageFallback will nicely accept $message as an array of fallbacks
-               // or just a single key
-               $msg = wfMessageFallback( $message )->setContext( $this->getContext() );
-               if ( is_array( $message ) ) {
-                       // for hook compatibility just keep the last message name
-                       $message = end( $message );
-               }
-               if ( $msg->exists() ) {
-                       $text = $msg->text();
-               } else {
-                       global $wgContLang;
-                       $text = $wgContLang->getFormattedNsText(
-                               MWNamespace::getSubject( $title->getNamespace() ) );
-               }
-
-               $result = array();
-               if ( !wfRunHooks( 'SkinTemplateTabAction', array( &$this,
-                               $title, $message, $selected, $checkEdit,
-                               &$classes, &$query, &$text, &$result ) ) ) {
-                       return $result;
-               }
-
-               return array(
-                       'class' => implode( ' ', $classes ),
-                       'text' => $text,
-                       'href' => $title->getLocalURL( $query ),
-                       'primary' => true );
-       }
-
-       function makeTalkUrlDetails( $name, $urlaction = '' ) {
-               $title = Title::newFromText( $name );
-               if ( !is_object( $title ) ) {
-                       throw new MWException( __METHOD__ . " given invalid pagename $name" );
-               }
-               $title = $title->getTalkPage();
-               self::checkTitle( $title, $name );
-               return array(
-                       'href' => $title->getLocalURL( $urlaction ),
-                       'exists' => $title->getArticleID() != 0,
-               );
-       }
-
-       function makeArticleUrlDetails( $name, $urlaction = '' ) {
-               $title = Title::newFromText( $name );
-               $title = $title->getSubjectPage();
-               self::checkTitle( $title, $name );
-               return array(
-                       'href' => $title->getLocalURL( $urlaction ),
-                       'exists' => $title->getArticleID() != 0,
-               );
-       }
-
-       /**
-        * a structured array of links usually used for the tabs in a skin
-        *
-        * There are 4 standard sections
-        * namespaces: Used for namespace tabs like special, page, and talk namespaces
-        * views: Used for primary page views like read, edit, history
-        * actions: Used for most extra page actions like deletion, protection, etc...
-        * variants: Used to list the language variants for the page
-        *
-        * Each section's value is a key/value array of links for that section.
-        * The links themselves have these common keys:
-        * - class: The css classes to apply to the tab
-        * - text: The text to display on the tab
-        * - href: The href for the tab to point to
-        * - rel: An optional rel= for the tab's link
-        * - redundant: If true the tab will be dropped in skins using content_actions
-        *   this is useful for tabs like "Read" which only have meaning in skins that
-        *   take special meaning from the grouped structure of content_navigation
-        *
-        * Views also have an extra key which can be used:
-        * - primary: If this is not true skins like vector may try to hide the tab
-        *            when the user has limited space in their browser window
-        *
-        * content_navigation using code also expects these ids to be present on the
-        * links, however these are usually automatically generated by SkinTemplate
-        * itself and are not necessary when using a hook. The only things these may
-        * matter to are people modifying content_navigation after it's initial creation:
-        * - id: A "preferred" id, most skins are best off outputting this preferred
-        *   id for best compatibility.
-        * - tooltiponly: This is set to true for some tabs in cases where the system
-        *   believes that the accesskey should not be added to the tab.
-        *
-        * @return array
-        */
-       protected function buildContentNavigationUrls() {
-               global $wgDisableLangConversion;
-
-               wfProfileIn( __METHOD__ );
-
-               // Display tabs for the relevant title rather than always the title itself
-               $title = $this->getRelevantTitle();
-               $onPage = $title->equals( $this->getTitle() );
-
-               $out = $this->getOutput();
-               $request = $this->getRequest();
-               $user = $this->getUser();
-
-               $content_navigation = array(
-                       'namespaces' => array(),
-                       'views' => array(),
-                       'actions' => array(),
-                       'variants' => array()
-               );
-
-               // parameters
-               $action = $request->getVal( 'action', 'view' );
-
-               $userCanRead = $title->quickUserCan( 'read', $user );
-
-               $preventActiveTabs = false;
-               wfRunHooks( 'SkinTemplatePreventOtherActiveTabs', array( &$this, &$preventActiveTabs ) );
-
-               // Checks if page is some kind of content
-               if ( $title->canExist() ) {
-                       // Gets page objects for the related namespaces
-                       $subjectPage = $title->getSubjectPage();
-                       $talkPage = $title->getTalkPage();
-
-                       // Determines if this is a talk page
-                       $isTalk = $title->isTalkPage();
-
-                       // Generates XML IDs from namespace names
-                       $subjectId = $title->getNamespaceKey( '' );
-
-                       if ( $subjectId == 'main' ) {
-                               $talkId = 'talk';
-                       } else {
-                               $talkId = "{$subjectId}_talk";
-                       }
-
-                       $skname = $this->skinname;
-
-                       // Adds namespace links
-                       $subjectMsg = array( "nstab-$subjectId" );
-                       if ( $subjectPage->isMainPage() ) {
-                               array_unshift( $subjectMsg, 'mainpage-nstab' );
-                       }
-                       $content_navigation['namespaces'][$subjectId] = $this->tabAction(
-                               $subjectPage, $subjectMsg, !$isTalk && !$preventActiveTabs, '', $userCanRead
-                       );
-                       $content_navigation['namespaces'][$subjectId]['context'] = 'subject';
-                       $content_navigation['namespaces'][$talkId] = $this->tabAction(
-                               $talkPage, array( "nstab-$talkId", 'talk' ), $isTalk && !$preventActiveTabs, '', $userCanRead
-                       );
-                       $content_navigation['namespaces'][$talkId]['context'] = 'talk';
-
-                       if ( $userCanRead ) {
-                               $isForeignFile = $title->inNamespace( NS_FILE ) && $this->canUseWikiPage() &&
-                                       $this->getWikiPage() instanceof WikiFilePage && !$this->getWikiPage()->isLocal();
-
-                               // Adds view view link
-                               if ( $title->exists() || $isForeignFile ) {
-                                       $content_navigation['views']['view'] = $this->tabAction(
-                                               $isTalk ? $talkPage : $subjectPage,
-                                               array( "$skname-view-view", 'view' ),
-                                               ( $onPage && ( $action == 'view' || $action == 'purge' ) ), '', true
-                                       );
-                                       // signal to hide this from simple content_actions
-                                       $content_navigation['views']['view']['redundant'] = true;
-                               }
-
-                               // If it is a non-local file, show a link to the file in its own repository
-                               if ( $isForeignFile ) {
-                                       $file = $this->getWikiPage()->getFile();
-                                       $content_navigation['views']['view-foreign'] = array(
-                                               'class' => '',
-                                               'text' => wfMessageFallback( "$skname-view-foreign", 'view-foreign' )->
-                                                       setContext( $this->getContext() )->
-                                                       params( $file->getRepo()->getDisplayName() )->text(),
-                                               'href' => $file->getDescriptionUrl(),
-                                               'primary' => false,
-                                       );
-                               }
-
-                               wfProfileIn( __METHOD__ . '-edit' );
-
-                               // Checks if user can edit the current page if it exists or create it otherwise
-                               if ( $title->quickUserCan( 'edit', $user )
-                                       && ( $title->exists() || $title->quickUserCan( 'create', $user ) )
-                               ) {
-                                       // Builds CSS class for talk page links
-                                       $isTalkClass = $isTalk ? ' istalk' : '';
-                                       // Whether the user is editing the page
-                                       $isEditing = $onPage && ( $action == 'edit' || $action == 'submit' );
-                                       // Whether to show the "Add a new section" tab
-                                       // Checks if this is a current rev of talk page and is not forced to be hidden
-                                       $showNewSection = !$out->forceHideNewSectionLink()
-                                               && ( ( $isTalk && $this->isRevisionCurrent() ) || $out->showNewSectionLink() );
-                                       $section = $request->getVal( 'section' );
-
-                                       if ( $title->exists()
-                                               || ( $title->getNamespace() == NS_MEDIAWIKI
-                                                       && $title->getDefaultMessageText() !== false
-                                               )
-                                       ) {
-                                               $msgKey = $isForeignFile ? 'edit-local' : 'edit';
-                                       } else {
-                                               $msgKey = $isForeignFile ? 'create-local' : 'create';
-                                       }
-                                       $content_navigation['views']['edit'] = array(
-                                               'class' => ( $isEditing && ( $section !== 'new' || !$showNewSection )
-                                                       ? 'selected'
-                                                       : ''
-                                               ) . $isTalkClass,
-                                               'text' => wfMessageFallback( "$skname-view-$msgKey", $msgKey )
-                                                       ->setContext( $this->getContext() )->text(),
-                                               'href' => $title->getLocalURL( $this->editUrlOptions() ),
-                                               'primary' => !$isForeignFile, // don't collapse this in vector
-                                       );
-
-                                       // section link
-                                       if ( $showNewSection ) {
-                                               // Adds new section link
-                                               //$content_navigation['actions']['addsection']
-                                               $content_navigation['views']['addsection'] = array(
-                                                       'class' => ( $isEditing && $section == 'new' ) ? 'selected' : false,
-                                                       'text' => wfMessageFallback( "$skname-action-addsection", 'addsection' )
-                                                               ->setContext( $this->getContext() )->text(),
-                                                       'href' => $title->getLocalURL( 'action=edit&section=new' )
-                                               );
-                                       }
-                               // Checks if the page has some kind of viewable content
-                               } elseif ( $title->hasSourceText() ) {
-                                       // Adds view source view link
-                                       $content_navigation['views']['viewsource'] = array(
-                                               'class' => ( $onPage && $action == 'edit' ) ? 'selected' : false,
-                                               'text' => wfMessageFallback( "$skname-action-viewsource", 'viewsource' )
-                                                       ->setContext( $this->getContext() )->text(),
-                                               'href' => $title->getLocalURL( $this->editUrlOptions() ),
-                                               'primary' => true, // don't collapse this in vector
-                                       );
-                               }
-                               wfProfileOut( __METHOD__ . '-edit' );
-
-                               wfProfileIn( __METHOD__ . '-live' );
-                               // Checks if the page exists
-                               if ( $title->exists() ) {
-                                       // Adds history view link
-                                       $content_navigation['views']['history'] = array(
-                                               'class' => ( $onPage && $action == 'history' ) ? 'selected' : false,
-                                               'text' => wfMessageFallback( "$skname-view-history", 'history_short' )
-                                                       ->setContext( $this->getContext() )->text(),
-                                               'href' => $title->getLocalURL( 'action=history' ),
-                                               'rel' => 'archives',
-                                       );
-
-                                       if ( $title->quickUserCan( 'delete', $user ) ) {
-                                               $content_navigation['actions']['delete'] = array(
-                                                       'class' => ( $onPage && $action == 'delete' ) ? 'selected' : false,
-                                                       'text' => wfMessageFallback( "$skname-action-delete", 'delete' )
-                                                               ->setContext( $this->getContext() )->text(),
-                                                       'href' => $title->getLocalURL( 'action=delete' )
-                                               );
-                                       }
-
-                                       if ( $title->quickUserCan( 'move', $user ) ) {
-                                               $moveTitle = SpecialPage::getTitleFor( 'Movepage', $title->getPrefixedDBkey() );
-                                               $content_navigation['actions']['move'] = array(
-                                                       'class' => $this->getTitle()->isSpecial( 'Movepage' ) ? 'selected' : false,
-                                                       'text' => wfMessageFallback( "$skname-action-move", 'move' )
-                                                               ->setContext( $this->getContext() )->text(),
-                                                       'href' => $moveTitle->getLocalURL()
-                                               );
-                                       }
-                               } else {
-                                       // article doesn't exist or is deleted
-                                       if ( $user->isAllowed( 'deletedhistory' ) ) {
-                                               $n = $title->isDeleted();
-                                               if ( $n ) {
-                                                       $undelTitle = SpecialPage::getTitleFor( 'Undelete' );
-                                                       // If the user can't undelete but can view deleted
-                                                       // history show them a "View .. deleted" tab instead.
-                                                       $msgKey = $user->isAllowed( 'undelete' ) ? 'undelete' : 'viewdeleted';
-                                                       $content_navigation['actions']['undelete'] = array(
-                                                               'class' => $this->getTitle()->isSpecial( 'Undelete' ) ? 'selected' : false,
-                                                               'text' => wfMessageFallback( "$skname-action-$msgKey", "{$msgKey}_short" )
-                                                                       ->setContext( $this->getContext() )->numParams( $n )->text(),
-                                                               'href' => $undelTitle->getLocalURL( array( 'target' => $title->getPrefixedDBkey() ) )
-                                                       );
-                                               }
-                                       }
-                               }
-
-                               if ( $title->quickUserCan( 'protect', $user ) && $title->getRestrictionTypes() &&
-                                       MWNamespace::getRestrictionLevels( $title->getNamespace(), $user ) !== array( '' )
-                               ) {
-                                       $mode = $title->isProtected() ? 'unprotect' : 'protect';
-                                       $content_navigation['actions'][$mode] = array(
-                                               'class' => ( $onPage && $action == $mode ) ? 'selected' : false,
-                                               'text' => wfMessageFallback( "$skname-action-$mode", $mode )
-                                                       ->setContext( $this->getContext() )->text(),
-                                               'href' => $title->getLocalURL( "action=$mode" )
-                                       );
-                               }
-
-                               wfProfileOut( __METHOD__ . '-live' );
-
-                               // Checks if the user is logged in
-                               if ( $this->loggedin && $user->isAllowedAll( 'viewmywatchlist', 'editmywatchlist' ) ) {
-                                       /**
-                                        * The following actions use messages which, if made particular to
-                                        * the any specific skins, would break the Ajax code which makes this
-                                        * action happen entirely inline. OutputPage::getJSVars
-                                        * defines a set of messages in a javascript object - and these
-                                        * messages are assumed to be global for all skins. Without making
-                                        * a change to that procedure these messages will have to remain as
-                                        * the global versions.
-                                        */
-                                       $mode = $user->isWatched( $title ) ? 'unwatch' : 'watch';
-                                       $token = WatchAction::getWatchToken( $title, $user, $mode );
-                                       $content_navigation['actions'][$mode] = array(
-                                               'class' => $onPage && ( $action == 'watch' || $action == 'unwatch' ) ? 'selected' : false,
-                                               // uses 'watch' or 'unwatch' message
-                                               'text' => $this->msg( $mode )->text(),
-                                               'href' => $title->getLocalURL( array( 'action' => $mode, 'token' => $token ) )
-                                       );
-                               }
-                       }
-
-                       wfRunHooks( 'SkinTemplateNavigation', array( &$this, &$content_navigation ) );
-
-                       if ( $userCanRead && !$wgDisableLangConversion ) {
-                               $pageLang = $title->getPageLanguage();
-                               // Gets list of language variants
-                               $variants = $pageLang->getVariants();
-                               // Checks that language conversion is enabled and variants exist
-                               // And if it is not in the special namespace
-                               if ( count( $variants ) > 1 ) {
-                                       // Gets preferred variant (note that user preference is
-                                       // only possible for wiki content language variant)
-                                       $preferred = $pageLang->getPreferredVariant();
-                                       if ( Action::getActionName( $this ) === 'view' ) {
-                                               $params = $request->getQueryValues();
-                                               unset( $params['title'] );
-                                       } else {
-                                               $params = array();
-                                       }
-                                       // Loops over each variant
-                                       foreach ( $variants as $code ) {
-                                               // Gets variant name from language code
-                                               $varname = $pageLang->getVariantname( $code );
-                                               // Appends variant link
-                                               $content_navigation['variants'][] = array(
-                                                       'class' => ( $code == $preferred ) ? 'selected' : false,
-                                                       'text' => $varname,
-                                                       'href' => $title->getLocalURL( array( 'variant' => $code ) + $params ),
-                                                       'lang' => wfBCP47( $code ),
-                                                       'hreflang' => wfBCP47( $code ),
-                                               );
-                                       }
-                               }
-                       }
-               } else {
-                       // If it's not content, it's got to be a special page
-                       $content_navigation['namespaces']['special'] = array(
-                               'class' => 'selected',
-                               'text' => $this->msg( 'nstab-special' )->text(),
-                               'href' => $request->getRequestURL(), // @see: bug 2457, bug 2510
-                               'context' => 'subject'
-                       );
-
-                       wfRunHooks( 'SkinTemplateNavigation::SpecialPage',
-                               array( &$this, &$content_navigation ) );
-               }
-
-               // Equiv to SkinTemplateContentActions
-               wfRunHooks( 'SkinTemplateNavigation::Universal', array( &$this, &$content_navigation ) );
-
-               // Setup xml ids and tooltip info
-               foreach ( $content_navigation as $section => &$links ) {
-                       foreach ( $links as $key => &$link ) {
-                               $xmlID = $key;
-                               if ( isset( $link['context'] ) && $link['context'] == 'subject' ) {
-                                       $xmlID = 'ca-nstab-' . $xmlID;
-                               } elseif ( isset( $link['context'] ) && $link['context'] == 'talk' ) {
-                                       $xmlID = 'ca-talk';
-                               } elseif ( $section == 'variants' ) {
-                                       $xmlID = 'ca-varlang-' . $xmlID;
-                               } else {
-                                       $xmlID = 'ca-' . $xmlID;
-                               }
-                               $link['id'] = $xmlID;
-                       }
-               }
-
-               # We don't want to give the watch tab an accesskey if the
-               # page is being edited, because that conflicts with the
-               # accesskey on the watch checkbox.  We also don't want to
-               # give the edit tab an accesskey, because that's fairly
-               # superfluous and conflicts with an accesskey (Ctrl-E) often
-               # used for editing in Safari.
-               if ( in_array( $action, array( 'edit', 'submit' ) ) ) {
-                       if ( isset( $content_navigation['views']['edit'] ) ) {
-                               $content_navigation['views']['edit']['tooltiponly'] = true;
-                       }
-                       if ( isset( $content_navigation['actions']['watch'] ) ) {
-                               $content_navigation['actions']['watch']['tooltiponly'] = true;
-                       }
-                       if ( isset( $content_navigation['actions']['unwatch'] ) ) {
-                               $content_navigation['actions']['unwatch']['tooltiponly'] = true;
-                       }
-               }
-
-               wfProfileOut( __METHOD__ );
-
-               return $content_navigation;
-       }
-
-       /**
-        * an array of edit links by default used for the tabs
-        * @param $content_navigation
-        * @return array
-        */
-       private function buildContentActionUrls( $content_navigation ) {
-
-               wfProfileIn( __METHOD__ );
-
-               // content_actions has been replaced with content_navigation for backwards
-               // compatibility and also for skins that just want simple tabs content_actions
-               // is now built by flattening the content_navigation arrays into one
-
-               $content_actions = array();
-
-               foreach ( $content_navigation as $links ) {
-                       foreach ( $links as $key => $value ) {
-                               if ( isset( $value['redundant'] ) && $value['redundant'] ) {
-                                       // Redundant tabs are dropped from content_actions
-                                       continue;
-                               }
-
-                               // content_actions used to have ids built using the "ca-$key" pattern
-                               // so the xmlID based id is much closer to the actual $key that we want
-                               // for that reason we'll just strip out the ca- if present and use
-                               // the latter potion of the "id" as the $key
-                               if ( isset( $value['id'] ) && substr( $value['id'], 0, 3 ) == 'ca-' ) {
-                                       $key = substr( $value['id'], 3 );
-                               }
-
-                               if ( isset( $content_actions[$key] ) ) {
-                                       wfDebug( __METHOD__ . ": Found a duplicate key for $key while flattening " .
-                                               "content_navigation into content_actions.\n" );
-                                       continue;
-                               }
-
-                               $content_actions[$key] = $value;
-                       }
-               }
-
-               wfProfileOut( __METHOD__ );
-
-               return $content_actions;
-       }
-
-       /**
-        * build array of common navigation links
-        * @return array
-        */
-       protected function buildNavUrls() {
-               global $wgUploadNavigationUrl;
-
-               wfProfileIn( __METHOD__ );
-
-               $out = $this->getOutput();
-               $request = $this->getRequest();
-
-               $nav_urls = array();
-               $nav_urls['mainpage'] = array( 'href' => self::makeMainPageUrl() );
-               if ( $wgUploadNavigationUrl ) {
-                       $nav_urls['upload'] = array( 'href' => $wgUploadNavigationUrl );
-               } elseif ( UploadBase::isEnabled() && UploadBase::isAllowed( $this->getUser() ) === true ) {
-                       $nav_urls['upload'] = array( 'href' => self::makeSpecialUrl( 'Upload' ) );
-               } else {
-                       $nav_urls['upload'] = false;
-               }
-               $nav_urls['specialpages'] = array( 'href' => self::makeSpecialUrl( 'Specialpages' ) );
-
-               $nav_urls['print'] = false;
-               $nav_urls['permalink'] = false;
-               $nav_urls['info'] = false;
-               $nav_urls['whatlinkshere'] = false;
-               $nav_urls['recentchangeslinked'] = false;
-               $nav_urls['contributions'] = false;
-               $nav_urls['log'] = false;
-               $nav_urls['blockip'] = false;
-               $nav_urls['emailuser'] = false;
-               $nav_urls['userrights'] = false;
-
-               // A print stylesheet is attached to all pages, but nobody ever
-               // figures that out. :)  Add a link...
-               if ( !$out->isPrintable() && ( $out->isArticle() || $this->getTitle()->isSpecialPage() ) ) {
-                       $nav_urls['print'] = array(
-                               'text' => $this->msg( 'printableversion' )->text(),
-                               'href' => $this->getTitle()->getLocalURL(
-                                       $request->appendQueryValue( 'printable', 'yes', true ) )
-                       );
-               }
-
-               if ( $out->isArticle() ) {
-                       // Also add a "permalink" while we're at it
-                       $revid = $this->getRevisionId();
-                       if ( $revid ) {
-                               $nav_urls['permalink'] = array(
-                                       'text' => $this->msg( 'permalink' )->text(),
-                                       'href' => $this->getTitle()->getLocalURL( "oldid=$revid" )
-                               );
-                       }
-
-                       // Use the copy of revision ID in case this undocumented, shady hook tries to mess with internals
-                       wfRunHooks( 'SkinTemplateBuildNavUrlsNav_urlsAfterPermalink',
-                               array( &$this, &$nav_urls, &$revid, &$revid ) );
-               }
-
-               if ( $out->isArticleRelated() ) {
-                       $nav_urls['whatlinkshere'] = array(
-                               'href' => SpecialPage::getTitleFor( 'Whatlinkshere', $this->thispage )->getLocalURL()
-                       );
-
-                       $nav_urls['info'] = array(
-                               'text' => $this->msg( 'pageinfo-toolboxlink' )->text(),
-                               'href' => $this->getTitle()->getLocalURL( "action=info" )
-                       );
-
-                       if ( $this->getTitle()->getArticleID() ) {
-                               $nav_urls['recentchangeslinked'] = array(
-                                       'href' => SpecialPage::getTitleFor( 'Recentchangeslinked', $this->thispage )->getLocalURL()
-                               );
-                       }
-               }
-
-               $user = $this->getRelevantUser();
-               if ( $user ) {
-                       $rootUser = $user->getName();
-
-                       $nav_urls['contributions'] = array(
-                               'text' => $this->msg( 'contributions', $rootUser )->text(),
-                               'href' => self::makeSpecialUrlSubpage( 'Contributions', $rootUser )
-                       );
-
-                       $nav_urls['log'] = array(
-                               'href' => self::makeSpecialUrlSubpage( 'Log', $rootUser )
-                       );
-
-                       if ( $this->getUser()->isAllowed( 'block' ) ) {
-                               $nav_urls['blockip'] = array(
-                                       'href' => self::makeSpecialUrlSubpage( 'Block', $rootUser )
-                               );
-                       }
-
-                       if ( $this->showEmailUser( $user ) ) {
-                               $nav_urls['emailuser'] = array(
-                                       'href' => self::makeSpecialUrlSubpage( 'Emailuser', $rootUser )
-                               );
-                       }
-
-                       if ( !$user->isAnon() ) {
-                               $sur = new UserrightsPage;
-                               $sur->setContext( $this->getContext() );
-                               if ( $sur->userCanExecute( $this->getUser() ) ) {
-                                       $nav_urls['userrights'] = array(
-                                               'href' => self::makeSpecialUrlSubpage( 'Userrights', $rootUser )
-                                       );
-                               }
-                       }
-               }
-
-               wfProfileOut( __METHOD__ );
-               return $nav_urls;
-       }
-
-       /**
-        * Generate strings used for xml 'id' names
-        * @return string
-        */
-       protected function getNameSpaceKey() {
-               return $this->getTitle()->getNamespaceKey();
-       }
-}
-
-/**
- * Generic wrapper for template functions, with interface
- * compatible with what we use of PHPTAL 0.7.
- * @ingroup Skins
- */
-abstract class QuickTemplate {
-       /**
-        * Constructor
-        */
-       function __construct() {
-               $this->data = array();
-               $this->translator = new MediaWikiI18N();
-       }
-
-       /**
-        * Sets the value $value to $name
-        * @param string $name
-        * @param mixed $value
-        */
-       public function set( $name, $value ) {
-               $this->data[$name] = $value;
-       }
-
-       /**
-        * Gets the template data requested
-        * @since 1.22
-        * @param string $name Key for the data
-        * @param mixed $default Optional default (or null)
-        * @return mixed The value of the data requested or the deafult
-        */
-       public function get( $name, $default = null ) {
-               if ( isset( $this->data[$name] ) ) {
-                       return $this->data[$name];
-               } else {
-                       return $default;
-               }
-       }
-
-       /**
-        * @param string $name
-        * @param mixed $value
-        */
-       public function setRef( $name, &$value ) {
-               $this->data[$name] =& $value;
-       }
-
-       /**
-        * @param MediaWikiI18N $t
-        */
-       public function setTranslator( &$t ) {
-               $this->translator = &$t;
-       }
-
-       /**
-        * Main function, used by classes that subclass QuickTemplate
-        * to show the actual HTML output
-        */
-       abstract public function execute();
-
-       /**
-        * @private
-        * @param string $str
-        * @return string
-        */
-       function text( $str ) {
-               echo htmlspecialchars( $this->data[$str] );
-       }
-
-       /**
-        * @private
-        * @param string $str
-        * @return string
-        */
-       function html( $str ) {
-               echo $this->data[$str];
-       }
-
-       /**
-        * @private
-        * @param string $str
-        * @return string
-        */
-       function msg( $str ) {
-               echo htmlspecialchars( $this->translator->translate( $str ) );
-       }
-
-       /**
-        * @private
-        * @param string $str
-        * @return string
-        */
-       function msgHtml( $str ) {
-               echo $this->translator->translate( $str );
-       }
-
-       /**
-        * An ugly, ugly hack.
-        * @private
-        * @param string $str
-        * @return string
-        */
-       function msgWiki( $str ) {
-               global $wgOut;
-
-               $text = $this->translator->translate( $str );
-               echo $wgOut->parse( $text );
-       }
-
-       /**
-        * @private
-        * @param string $str
-        * @return bool
-        */
-       function haveData( $str ) {
-               return isset( $this->data[$str] );
-       }
-
-       /**
-        * @private
-        *
-        * @param string $str
-        * @return bool
-        */
-       function haveMsg( $str ) {
-               $msg = $this->translator->translate( $str );
-               return ( $msg != '-' ) && ( $msg != '' ); # ????
-       }
-
-       /**
-        * Get the Skin object related to this object
-        *
-        * @return Skin
-        */
-       public function getSkin() {
-               return $this->data['skin'];
-       }
-
-       /**
-        * Fetch the output of a QuickTemplate and return it
-        *
-        * @since 1.23
-        * @return string
-        */
-       public function getHTML() {
-               ob_start();
-               $this->execute();
-               $html = ob_get_contents();
-               ob_end_clean();
-               return $html;
-       }
-}
-
-/**
- * New base template for a skin's template extended from QuickTemplate
- * this class features helper methods that provide common ways of interacting
- * with the data stored in the QuickTemplate
- */
-abstract class BaseTemplate extends QuickTemplate {
-
-       /**
-        * Get a Message object with its context set
-        *
-        * @param string $name Message name
-        * @return Message
-        */
-       public function getMsg( $name ) {
-               return $this->getSkin()->msg( $name );
-       }
-
-       function msg( $str ) {
-               echo $this->getMsg( $str )->escaped();
-       }
-
-       function msgHtml( $str ) {
-               echo $this->getMsg( $str )->text();
-       }
-
-       function msgWiki( $str ) {
-               echo $this->getMsg( $str )->parseAsBlock();
-       }
-
-       /**
-        * Create an array of common toolbox items from the data in the quicktemplate
-        * stored by SkinTemplate.
-        * The resulting array is built according to a format intended to be passed
-        * through makeListItem to generate the html.
-        * @return array
-        */
-       function getToolbox() {
-               wfProfileIn( __METHOD__ );
-
-               $toolbox = array();
-               if ( isset( $this->data['nav_urls']['whatlinkshere'] )
-                       && $this->data['nav_urls']['whatlinkshere']
-               ) {
-                       $toolbox['whatlinkshere'] = $this->data['nav_urls']['whatlinkshere'];
-                       $toolbox['whatlinkshere']['id'] = 't-whatlinkshere';
-               }
-               if ( isset( $this->data['nav_urls']['recentchangeslinked'] )
-                       && $this->data['nav_urls']['recentchangeslinked']
-               ) {
-                       $toolbox['recentchangeslinked'] = $this->data['nav_urls']['recentchangeslinked'];
-                       $toolbox['recentchangeslinked']['msg'] = 'recentchangeslinked-toolbox';
-                       $toolbox['recentchangeslinked']['id'] = 't-recentchangeslinked';
-               }
-               if ( isset( $this->data['feeds'] ) && $this->data['feeds'] ) {
-                       $toolbox['feeds']['id'] = 'feedlinks';
-                       $toolbox['feeds']['links'] = array();
-                       foreach ( $this->data['feeds'] as $key => $feed ) {
-                               $toolbox['feeds']['links'][$key] = $feed;
-                               $toolbox['feeds']['links'][$key]['id'] = "feed-$key";
-                               $toolbox['feeds']['links'][$key]['rel'] = 'alternate';
-                               $toolbox['feeds']['links'][$key]['type'] = "application/{$key}+xml";
-                               $toolbox['feeds']['links'][$key]['class'] = 'feedlink';
-                       }
-               }
-               foreach ( array( 'contributions', 'log', 'blockip', 'emailuser',
-                       'userrights', 'upload', 'specialpages' ) as $special
-               ) {
-                       if ( isset( $this->data['nav_urls'][$special] ) && $this->data['nav_urls'][$special] ) {
-                               $toolbox[$special] = $this->data['nav_urls'][$special];
-                               $toolbox[$special]['id'] = "t-$special";
-                       }
-               }
-               if ( isset( $this->data['nav_urls']['print'] ) && $this->data['nav_urls']['print'] ) {
-                       $toolbox['print'] = $this->data['nav_urls']['print'];
-                       $toolbox['print']['id'] = 't-print';
-                       $toolbox['print']['rel'] = 'alternate';
-                       $toolbox['print']['msg'] = 'printableversion';
-               }
-               if ( isset( $this->data['nav_urls']['permalink'] ) && $this->data['nav_urls']['permalink'] ) {
-                       $toolbox['permalink'] = $this->data['nav_urls']['permalink'];
-                       if ( $toolbox['permalink']['href'] === '' ) {
-                               unset( $toolbox['permalink']['href'] );
-                               $toolbox['ispermalink']['tooltiponly'] = true;
-                               $toolbox['ispermalink']['id'] = 't-ispermalink';
-                               $toolbox['ispermalink']['msg'] = 'permalink';
-                       } else {
-                               $toolbox['permalink']['id'] = 't-permalink';
-                       }
-               }
-               if ( isset( $this->data['nav_urls']['info'] ) && $this->data['nav_urls']['info'] ) {
-                       $toolbox['info'] = $this->data['nav_urls']['info'];
-                       $toolbox['info']['id'] = 't-info';
-               }
-
-               wfRunHooks( 'BaseTemplateToolbox', array( &$this, &$toolbox ) );
-               wfProfileOut( __METHOD__ );
-               return $toolbox;
-       }
-
-       /**
-        * Create an array of personal tools items from the data in the quicktemplate
-        * stored by SkinTemplate.
-        * The resulting array is built according to a format intended to be passed
-        * through makeListItem to generate the html.
-        * This is in reality the same list as already stored in personal_urls
-        * however it is reformatted so that you can just pass the individual items
-        * to makeListItem instead of hardcoding the element creation boilerplate.
-        * @return array
-        */
-       function getPersonalTools() {
-               $personal_tools = array();
-               foreach ( $this->get( 'personal_urls' ) as $key => $plink ) {
-                       # The class on a personal_urls item is meant to go on the <a> instead
-                       # of the <li> so we have to use a single item "links" array instead
-                       # of using most of the personal_url's keys directly.
-                       $ptool = array(
-                               'links' => array(
-                                       array( 'single-id' => "pt-$key" ),
-                               ),
-                               'id' => "pt-$key",
-                       );
-                       if ( isset( $plink['active'] ) ) {
-                               $ptool['active'] = $plink['active'];
-                       }
-                       foreach ( array( 'href', 'class', 'text', 'dir' ) as $k ) {
-                               if ( isset( $plink[$k] ) ) {
-                                       $ptool['links'][0][$k] = $plink[$k];
-                               }
-                       }
-                       $personal_tools[$key] = $ptool;
-               }
-               return $personal_tools;
-       }
-
-       function getSidebar( $options = array() ) {
-               // Force the rendering of the following portals
-               $sidebar = $this->data['sidebar'];
-               if ( !isset( $sidebar['SEARCH'] ) ) {
-                       $sidebar['SEARCH'] = true;
-               }
-               if ( !isset( $sidebar['TOOLBOX'] ) ) {
-                       $sidebar['TOOLBOX'] = true;
-               }
-               if ( !isset( $sidebar['LANGUAGES'] ) ) {
-                       $sidebar['LANGUAGES'] = true;
-               }
-
-               if ( !isset( $options['search'] ) || $options['search'] !== true ) {
-                       unset( $sidebar['SEARCH'] );
-               }
-               if ( isset( $options['toolbox'] ) && $options['toolbox'] === false ) {
-                       unset( $sidebar['TOOLBOX'] );
-               }
-               if ( isset( $options['languages'] ) && $options['languages'] === false ) {
-                       unset( $sidebar['LANGUAGES'] );
-               }
-
-               $boxes = array();
-               foreach ( $sidebar as $boxName => $content ) {
-                       if ( $content === false ) {
-                               continue;
-                       }
-                       switch ( $boxName ) {
-                       case 'SEARCH':
-                               // Search is a special case, skins should custom implement this
-                               $boxes[$boxName] = array(
-                                       'id' => 'p-search',
-                                       'header' => $this->getMsg( 'search' )->text(),
-                                       'generated' => false,
-                                       'content' => true,
-                               );
-                               break;
-                       case 'TOOLBOX':
-                               $msgObj = $this->getMsg( 'toolbox' );
-                               $boxes[$boxName] = array(
-                                       'id' => 'p-tb',
-                                       'header' => $msgObj->exists() ? $msgObj->text() : 'toolbox',
-                                       'generated' => false,
-                                       'content' => $this->getToolbox(),
-                               );
-                               break;
-                       case 'LANGUAGES':
-                               if ( $this->data['language_urls'] ) {
-                                       $msgObj = $this->getMsg( 'otherlanguages' );
-                                       $boxes[$boxName] = array(
-                                               'id' => 'p-lang',
-                                               'header' => $msgObj->exists() ? $msgObj->text() : 'otherlanguages',
-                                               'generated' => false,
-                                               'content' => $this->data['language_urls'],
-                                       );
-                               }
-                               break;
-                       default:
-                               $msgObj = $this->getMsg( $boxName );
-                               $boxes[$boxName] = array(
-                                       'id' => "p-$boxName",
-                                       'header' => $msgObj->exists() ? $msgObj->text() : $boxName,
-                                       'generated' => true,
-                                       'content' => $content,
-                               );
-                               break;
-                       }
-               }
-
-               // HACK: Compatibility with extensions still using SkinTemplateToolboxEnd
-               $hookContents = null;
-               if ( isset( $boxes['TOOLBOX'] ) ) {
-                       ob_start();
-                       // We pass an extra 'true' at the end so extensions using BaseTemplateToolbox
-                       // can abort and avoid outputting double toolbox links
-                       wfRunHooks( 'SkinTemplateToolboxEnd', array( &$this, true ) );
-                       $hookContents = ob_get_contents();
-                       ob_end_clean();
-                       if ( !trim( $hookContents ) ) {
-                               $hookContents = null;
-                       }
-               }
-               // END hack
-
-               if ( isset( $options['htmlOnly'] ) && $options['htmlOnly'] === true ) {
-                       foreach ( $boxes as $boxName => $box ) {
-                               if ( is_array( $box['content'] ) ) {
-                                       $content = '<ul>';
-                                       foreach ( $box['content'] as $key => $val ) {
-                                               $content .= "\n " . $this->makeListItem( $key, $val );
-                                       }
-                                       // HACK, shove the toolbox end onto the toolbox if we're rendering itself
-                                       if ( $hookContents ) {
-                                               $content .= "\n $hookContents";
-                                       }
-                                       // END hack
-                                       $content .= "\n</ul>\n";
-                                       $boxes[$boxName]['content'] = $content;
-                               }
-                       }
-               } else {
-                       if ( $hookContents ) {
-                               $boxes['TOOLBOXEND'] = array(
-                                       'id' => 'p-toolboxend',
-                                       'header' => $boxes['TOOLBOX']['header'],
-                                       'generated' => false,
-                                       'content' => "<ul>{$hookContents}</ul>",
-                               );
-                               // HACK: Make sure that TOOLBOXEND is sorted next to TOOLBOX
-                               $boxes2 = array();
-                               foreach ( $boxes as $key => $box ) {
-                                       if ( $key === 'TOOLBOXEND' ) {
-                                               continue;
-                                       }
-                                       $boxes2[$key] = $box;
-                                       if ( $key === 'TOOLBOX' ) {
-                                               $boxes2['TOOLBOXEND'] = $boxes['TOOLBOXEND'];
-                                       }
-                               }
-                               $boxes = $boxes2;
-                               // END hack
-                       }
-               }
-
-               return $boxes;
-       }
-
-       /**
-        * @param string $name
-        */
-       protected function renderAfterPortlet( $name ) {
-               $content = '';
-               wfRunHooks( 'BaseTemplateAfterPortlet', array( $this, $name, &$content ) );
-
-               if ( $content !== '' ) {
-                       echo "<div class='after-portlet after-portlet-$name'>$content</div>";
-               }
-
-       }
-
-       /**
-        * Makes a link, usually used by makeListItem to generate a link for an item
-        * in a list used in navigation lists, portlets, portals, sidebars, etc...
-        *
-        * @param string $key usually a key from the list you are generating this
-        * link from.
-        * @param array $item contains some of a specific set of keys.
-        *
-        * The text of the link will be generated either from the contents of the
-        * "text" key in the $item array, if a "msg" key is present a message by
-        * that name will be used, and if neither of those are set the $key will be
-        * used as a message name.
-        *
-        * If a "href" key is not present makeLink will just output htmlescaped text.
-        * The "href", "id", "class", "rel", and "type" keys are used as attributes
-        * for the link if present.
-        *
-        * If an "id" or "single-id" (if you don't want the actual id to be output
-        * on the link) is present it will be used to generate a tooltip and
-        * accesskey for the link.
-        *
-        * The keys "context" and "primary" are ignored; these keys are used
-        * internally by skins and are not supposed to be included in the HTML
-        * output.
-        *
-        * If you don't want an accesskey, set $item['tooltiponly'] = true;
-        *
-        * @param array $options can be used to affect the output of a link.
-        * Possible options are:
-        *   - 'text-wrapper' key to specify a list of elements to wrap the text of
-        *   a link in. This should be an array of arrays containing a 'tag' and
-        *   optionally an 'attributes' key. If you only have one element you don't
-        *   need to wrap it in another array. eg: To use <a><span>...</span></a>
-        *   in all links use array( 'text-wrapper' => array( 'tag' => 'span' ) )
-        *   for your options.
-        *   - 'link-class' key can be used to specify additional classes to apply
-        *   to all links.
-        *   - 'link-fallback' can be used to specify a tag to use instead of "<a>"
-        *   if there is no link. eg: If you specify 'link-fallback' => 'span' than
-        *   any non-link will output a "<span>" instead of just text.
-        *
-        * @return string
-        */
-       function makeLink( $key, $item, $options = array() ) {
-               if ( isset( $item['text'] ) ) {
-                       $text = $item['text'];
-               } else {
-                       $text = $this->translator->translate( isset( $item['msg'] ) ? $item['msg'] : $key );
-               }
-
-               $html = htmlspecialchars( $text );
-
-               if ( isset( $options['text-wrapper'] ) ) {
-                       $wrapper = $options['text-wrapper'];
-                       if ( isset( $wrapper['tag'] ) ) {
-                               $wrapper = array( $wrapper );
-                       }
-                       while ( count( $wrapper ) > 0 ) {
-                               $element = array_pop( $wrapper );
-                               $html = Html::rawElement( $element['tag'], isset( $element['attributes'] )
-                                       ? $element['attributes']
-                                       : null, $html );
-                       }
-               }
-
-               if ( isset( $item['href'] ) || isset( $options['link-fallback'] ) ) {
-                       $attrs = $item;
-                       foreach ( array( 'single-id', 'text', 'msg', 'tooltiponly', 'context', 'primary' ) as $k ) {
-                               unset( $attrs[$k] );
-                       }
-
-                       if ( isset( $item['id'] ) && !isset( $item['single-id'] ) ) {
-                               $item['single-id'] = $item['id'];
-                       }
-                       if ( isset( $item['single-id'] ) ) {
-                               if ( isset( $item['tooltiponly'] ) && $item['tooltiponly'] ) {
-                                       $title = Linker::titleAttrib( $item['single-id'] );
-                                       if ( $title !== false ) {
-                                               $attrs['title'] = $title;
-                                       }
-                               } else {
-                                       $tip = Linker::tooltipAndAccesskeyAttribs( $item['single-id'] );
-                                       if ( isset( $tip['title'] ) && $tip['title'] !== false ) {
-                                               $attrs['title'] = $tip['title'];
-                                       }
-                                       if ( isset( $tip['accesskey'] ) && $tip['accesskey'] !== false ) {
-                                               $attrs['accesskey'] = $tip['accesskey'];
-                                       }
-                               }
-                       }
-                       if ( isset( $options['link-class'] ) ) {
-                               if ( isset( $attrs['class'] ) ) {
-                                       $attrs['class'] .= " {$options['link-class']}";
-                               } else {
-                                       $attrs['class'] = $options['link-class'];
-                               }
-                       }
-                       $html = Html::rawElement( isset( $attrs['href'] )
-                               ? 'a'
-                               : $options['link-fallback'], $attrs, $html );
-               }
-
-               return $html;
-       }
-
-       /**
-        * Generates a list item for a navigation, portlet, portal, sidebar... list
-        *
-        * @param string $key Usually a key from the list you are generating this link from.
-        * @param array $item Array of list item data containing some of a specific set of keys.
-        * The "id", "class" and "itemtitle" keys will be used as attributes for the list item,
-        * if "active" contains a value of true a "active" class will also be appended to class.
-        *
-        * @param array $options
-        *
-        * If you want something other than a "<li>" you can pass a tag name such as
-        * "tag" => "span" in the $options array to change the tag used.
-        * link/content data for the list item may come in one of two forms
-        * A "links" key may be used, in which case it should contain an array with
-        * a list of links to include inside the list item, see makeLink for the
-        * format of individual links array items.
-        *
-        * Otherwise the relevant keys from the list item $item array will be passed
-        * to makeLink instead. Note however that "id" and "class" are used by the
-        * list item directly so they will not be passed to makeLink
-        * (however the link will still support a tooltip and accesskey from it)
-        * If you need an id or class on a single link you should include a "links"
-        * array with just one link item inside of it. If you want to add a title
-        * to the list item itself, you can set "itemtitle" to the value.
-        * $options is also passed on to makeLink calls
-        *
-        * @return string
-        */
-       function makeListItem( $key, $item, $options = array() ) {
-               if ( isset( $item['links'] ) ) {
-                       $links = array();
-                       foreach ( $item['links'] as $linkKey => $link ) {
-                               $links[] = $this->makeLink( $linkKey, $link, $options );
-                       }
-                       $html = implode( ' ', $links );
-               } else {
-                       $link = $item;
-                       // These keys are used by makeListItem and shouldn't be passed on to the link
-                       foreach ( array( 'id', 'class', 'active', 'tag', 'itemtitle' ) as $k ) {
-                               unset( $link[$k] );
-                       }
-                       if ( isset( $item['id'] ) && !isset( $item['single-id'] ) ) {
-                               // The id goes on the <li> not on the <a> for single links
-                               // but makeSidebarLink still needs to know what id to use when
-                               // generating tooltips and accesskeys.
-                               $link['single-id'] = $item['id'];
-                       }
-                       $html = $this->makeLink( $key, $link, $options );
-               }
-
-               $attrs = array();
-               foreach ( array( 'id', 'class' ) as $attr ) {
-                       if ( isset( $item[$attr] ) ) {
-                               $attrs[$attr] = $item[$attr];
-                       }
-               }
-               if ( isset( $item['active'] ) && $item['active'] ) {
-                       if ( !isset( $attrs['class'] ) ) {
-                               $attrs['class'] = '';
-                       }
-                       $attrs['class'] .= ' active';
-                       $attrs['class'] = trim( $attrs['class'] );
-               }
-               if ( isset( $item['itemtitle'] ) ) {
-                       $attrs['title'] = $item['itemtitle'];
-               }
-               return Html::rawElement( isset( $options['tag'] ) ? $options['tag'] : 'li', $attrs, $html );
-       }
-
-       function makeSearchInput( $attrs = array() ) {
-               $realAttrs = array(
-                       'type' => 'search',
-                       'name' => 'search',
-                       'placeholder' => wfMessage( 'searchsuggest-search' )->text(),
-                       'value' => $this->get( 'search', '' ),
-               );
-               $realAttrs = array_merge( $realAttrs, Linker::tooltipAndAccesskeyAttribs( 'search' ), $attrs );
-               return Html::element( 'input', $realAttrs );
-       }
-
-       function makeSearchButton( $mode, $attrs = array() ) {
-               switch ( $mode ) {
-                       case 'go':
-                       case 'fulltext':
-                               $realAttrs = array(
-                                       'type' => 'submit',
-                                       'name' => $mode,
-                                       'value' => $this->translator->translate(
-                                               $mode == 'go' ? 'searcharticle' : 'searchbutton' ),
-                               );
-                               $realAttrs = array_merge(
-                                       $realAttrs,
-                                       Linker::tooltipAndAccesskeyAttribs( "search-$mode" ),
-                                       $attrs
-                               );
-                               return Html::element( 'input', $realAttrs );
-                       case 'image':
-                               $buttonAttrs = array(
-                                       'type' => 'submit',
-                                       'name' => 'button',
-                               );
-                               $buttonAttrs = array_merge(
-                                       $buttonAttrs,
-                                       Linker::tooltipAndAccesskeyAttribs( 'search-fulltext' ),
-                                       $attrs
-                               );
-                               unset( $buttonAttrs['src'] );
-                               unset( $buttonAttrs['alt'] );
-                               unset( $buttonAttrs['width'] );
-                               unset( $buttonAttrs['height'] );
-                               $imgAttrs = array(
-                                       'src' => $attrs['src'],
-                                       'alt' => isset( $attrs['alt'] )
-                                               ? $attrs['alt']
-                                               : $this->translator->translate( 'searchbutton' ),
-                                       'width' => isset( $attrs['width'] ) ? $attrs['width'] : null,
-                                       'height' => isset( $attrs['height'] ) ? $attrs['height'] : null,
-                               );
-                               return Html::rawElement( 'button', $buttonAttrs, Html::element( 'img', $imgAttrs ) );
-                       default:
-                               throw new MWException( 'Unknown mode passed to BaseTemplate::makeSearchButton' );
-               }
-       }
-
-       /**
-        * Returns an array of footerlinks trimmed down to only those footer links that
-        * are valid.
-        * If you pass "flat" as an option then the returned array will be a flat array
-        * of footer icons instead of a key/value array of footerlinks arrays broken
-        * up into categories.
-        * @param string $option
-        * @return array|mixed
-        */
-       function getFooterLinks( $option = null ) {
-               $footerlinks = $this->get( 'footerlinks' );
-
-               // Reduce footer links down to only those which are being used
-               $validFooterLinks = array();
-               foreach ( $footerlinks as $category => $links ) {
-                       $validFooterLinks[$category] = array();
-                       foreach ( $links as $link ) {
-                               if ( isset( $this->data[$link] ) && $this->data[$link] ) {
-                                       $validFooterLinks[$category][] = $link;
-                               }
-                       }
-                       if ( count( $validFooterLinks[$category] ) <= 0 ) {
-                               unset( $validFooterLinks[$category] );
-                       }
-               }
-
-               if ( $option == 'flat' ) {
-                       // fold footerlinks into a single array using a bit of trickery
-                       $validFooterLinks = call_user_func_array(
-                               'array_merge',
-                               array_values( $validFooterLinks )
-                       );
-               }
-
-               return $validFooterLinks;
-       }
-
-       /**
-        * Returns an array of footer icons filtered down by options relevant to how
-        * the skin wishes to display them.
-        * If you pass "icononly" as the option all footer icons which do not have an
-        * image icon set will be filtered out.
-        * If you pass "nocopyright" then MediaWiki's copyright icon will not be included
-        * in the list of footer icons. This is mostly useful for skins which only
-        * display the text from footericons instead of the images and don't want a
-        * duplicate copyright statement because footerlinks already rendered one.
-        * @param string $option
-        * @return string
-        */
-       function getFooterIcons( $option = null ) {
-               // Generate additional footer icons
-               $footericons = $this->get( 'footericons' );
-
-               if ( $option == 'icononly' ) {
-                       // Unset any icons which don't have an image
-                       foreach ( $footericons as &$footerIconsBlock ) {
-                               foreach ( $footerIconsBlock as $footerIconKey => $footerIcon ) {
-                                       if ( !is_string( $footerIcon ) && !isset( $footerIcon['src'] ) ) {
-                                               unset( $footerIconsBlock[$footerIconKey] );
-                                       }
-                               }
-                       }
-                       // Redo removal of any empty blocks
-                       foreach ( $footericons as $footerIconsKey => &$footerIconsBlock ) {
-                               if ( count( $footerIconsBlock ) <= 0 ) {
-                                       unset( $footericons[$footerIconsKey] );
-                               }
-                       }
-               } elseif ( $option == 'nocopyright' ) {
-                       unset( $footericons['copyright']['copyright'] );
-                       if ( count( $footericons['copyright'] ) <= 0 ) {
-                               unset( $footericons['copyright'] );
-                       }
-               }
-
-               return $footericons;
-       }
-
-       /**
-        * Output the basic end-page trail including bottomscripts, reporttime, and
-        * debug stuff. This should be called right before outputting the closing
-        * body and html tags.
-        */
-       function printTrail() { ?>
-<?php echo MWDebug::getDebugHTML( $this->getSkin()->getContext() ); ?>
-<?php $this->html( 'bottomscripts' ); /* JS call to runBodyOnloadHook */ ?>
-<?php $this->html( 'reporttime' ) ?>
-<?php
-       }
-}
index c790bb7..824dd06 100644 (file)
@@ -343,7 +343,6 @@ class SquidPurgeClient {
 
        /**
         * @param string $line
-        * @return
         */
        protected function processStatusLine( $line ) {
                if ( !preg_match( '!^HTTP/(\d+)\.(\d+) (\d{3}) (.*)$!', $line, $m ) ) {
@@ -397,7 +396,7 @@ class SquidPurgeClient {
 }
 
 class SquidPurgeClientPool {
-       /** @var array of SquidPurgeClient */
+       /** @var array Array of SquidPurgeClient */
        protected $clients = array();
 
        /** @var int */
index 102fffd..5fc8f2f 100644 (file)
@@ -39,7 +39,11 @@ class StatCounter {
        /** @var array */
        protected $deltas = array(); // (key => count)
 
-       protected function __construct() {
+       /** @var Config */
+       protected $config;
+
+       protected function __construct( Config $config ) {
+               $this->config = $config;
        }
 
        /**
@@ -48,7 +52,9 @@ class StatCounter {
        public static function singleton() {
                static $instance = null;
                if ( !$instance ) {
-                       $instance = new self();
+                       $instance = new self(
+                               ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                       );
                }
                return $instance;
        }
@@ -74,12 +80,11 @@ class StatCounter {
         * @return void
         */
        public function flush() {
-               global $wgStatsMethod;
-
+               $statsMethod = $this->config->get( 'StatsMethod' );
                $deltas = array_filter( $this->deltas ); // remove 0 valued entries
-               if ( $wgStatsMethod === 'udp' ) {
+               if ( $statsMethod === 'udp' ) {
                        $this->sendDeltasUDP( $deltas );
-               } elseif ( $wgStatsMethod === 'cache' ) {
+               } elseif ( $statsMethod === 'cache' ) {
                        $this->sendDeltasMemc( $deltas );
                } else {
                        // disabled
@@ -92,14 +97,12 @@ class StatCounter {
         * @return void
         */
        protected function sendDeltasUDP( array $deltas ) {
-               global $wgUDPProfilerHost, $wgUDPProfilerPort, $wgAggregateStatsID,
-                       $wgStatsFormatString;
-
-               $id = strlen( $wgAggregateStatsID ) ? $wgAggregateStatsID : wfWikiID();
+               $aggregateStatsID = $this->config->get( 'AggregateStatsID' );
+               $id = strlen( $aggregateStatsID ) ? $aggregateStatsID : wfWikiID();
 
                $lines = array();
                foreach ( $deltas as $key => $count ) {
-                       $lines[] = sprintf( $wgStatsFormatString, $id, $count, $key );
+                       $lines[] = sprintf( $this->config->get( 'StatsFormatString' ), $id, $count, $key );
                }
 
                if ( count( $lines ) ) {
@@ -126,8 +129,8 @@ class StatCounter {
                                        $packet,
                                        strlen( $packet ),
                                        0,
-                                       $wgUDPProfilerHost,
-                                       $wgUDPProfilerPort
+                                       $this->config->get( 'UDPProfilerHost' ),
+                                       $this->config->get( 'UDPProfilerPort' )
                                );
                                wfRestoreWarnings();
                        }
index 77bf4a8..1a72968 100644 (file)
@@ -64,7 +64,7 @@ class Status {
        /**
         * Factory function for fatal errors
         *
-        * @param string|Message $message message name or object
+        * @param string|Message $message Message name or object
         * @return Status
         */
        static function newFatal( $message /*, parameters...*/ ) {
index fb9b3e4..8878660 100644 (file)
@@ -58,7 +58,7 @@ class StubObject {
         * @param string $class Name of the class of the real object.
         * @param array $params Parameters to pass to constructor of the real object.
         */
-       function __construct( $global = null, $class = null, $params = array() ) {
+       public function __construct( $global = null, $class = null, $params = array() ) {
                $this->global = $global;
                $this->class = $class;
                $this->params = $params;
@@ -71,7 +71,7 @@ class StubObject {
         * @param object $obj Object to check.
         * @return bool True if $obj is not an instance of StubObject class.
         */
-       static function isRealObject( $obj ) {
+       public static function isRealObject( $obj ) {
                return is_object( $obj ) && !$obj instanceof StubObject;
        }
 
@@ -83,7 +83,7 @@ class StubObject {
         * @param object $obj Object to check.
         * @return void
         */
-       static function unstub( &$obj ) {
+       public static function unstub( &$obj ) {
                if ( $obj instanceof StubObject ) {
                        $obj = $obj->_unstub( 'unstub', 3 );
                }
@@ -100,7 +100,7 @@ class StubObject {
         * @param array $args Arguments
         * @return mixed
         */
-       function _call( $name, $args ) {
+       public function _call( $name, $args ) {
                $this->_unstub( $name, 5 );
                return call_user_func_array( array( $GLOBALS[$this->global], $name ), $args );
        }
@@ -109,7 +109,7 @@ class StubObject {
         * Create a new object to replace this stub object.
         * @return object
         */
-       function _newObject() {
+       public function _newObject() {
                return MWFunction::newObj( $this->class, $this->params );
        }
 
@@ -121,7 +121,7 @@ class StubObject {
         * @param array $args Arguments
         * @return mixed
         */
-       function __call( $name, $args ) {
+       public function __call( $name, $args ) {
                return $this->_call( $name, $args );
        }
 
@@ -134,10 +134,10 @@ class StubObject {
         * @param string $name Name of the method called in this object.
         * @param int $level Level to go in the stack trace to get the function
         *   who called this function.
-        * @return The unstubbed version of itself
+        * @return object The unstubbed version of itself
         * @throws MWException
         */
-       function _unstub( $name = '_unstub', $level = 2 ) {
+       public function _unstub( $name = '_unstub', $level = 2 ) {
                static $recursionLevel = 0;
 
                if ( !$GLOBALS[$this->global] instanceof StubObject ) {
@@ -163,35 +163,6 @@ class StubObject {
        }
 }
 
-/**
- * Stub object for the content language of this wiki. This object have to be in
- * $wgContLang global.
- *
- * @deprecated since 1.18
- */
-class StubContLang extends StubObject {
-
-       function __construct() {
-               wfDeprecated( __CLASS__, '1.18' );
-               parent::__construct( 'wgContLang' );
-       }
-
-       function __call( $name, $args ) {
-               return $this->_call( $name, $args );
-       }
-
-       /**
-        * @return Language
-        */
-       function _newObject() {
-               global $wgLanguageCode;
-               $obj = Language::factory( $wgLanguageCode );
-               $obj->initEncoding();
-               $obj->initContLang();
-               return $obj;
-       }
-}
-
 /**
  * Stub object for the user language. It depends of the user preferences and
  * "uselang" parameter that can be passed to index.php. This object have to be
@@ -199,18 +170,18 @@ class StubContLang extends StubObject {
  */
 class StubUserLang extends StubObject {
 
-       function __construct() {
+       public function __construct() {
                parent::__construct( 'wgLang' );
        }
 
-       function __call( $name, $args ) {
+       public function __call( $name, $args ) {
                return $this->_call( $name, $args );
        }
 
        /**
         * @return Language
         */
-       function _newObject() {
+       public function _newObject() {
                return RequestContext::getMain()->getLanguage();
        }
 }
index 3c5b80f..7959860 100644 (file)
@@ -74,6 +74,9 @@ class Title {
        /** @var string Interwiki prefix */
        public $mInterwiki = '';
 
+       /** @var bool Was this Title created from a string with a local interwiki prefix? */
+       private $mLocalInterwiki = false;
+
        /** @var string Title fragment (i.e. the bit after the #) */
        public $mFragment = '';
 
@@ -95,7 +98,7 @@ class Title {
        /** @var array Array of groups allowed to edit this article */
        public $mRestrictions = array();
 
-       /** @var bool  */
+       /** @var bool */
        protected $mOldRestrictions = false;
 
        /** @var bool Cascade restrictions on this page to included templates and images? */
@@ -155,6 +158,9 @@ class Title {
 
        /** @var TitleValue A corresponding TitleValue object */
        private $mTitleValue = null;
+
+       /** @var bool Would deleting this page be a big deletion? */
+       private $mIsBigDeletion = null;
        // @}
 
        /**
@@ -608,7 +614,7 @@ class Title {
         * Note that this doesn't pick up many things that could be wrong with titles, but that
         * replacing this regex with something valid will make many titles valid.
         *
-        * @todo: move this into MediaWikiTitleCodec
+        * @todo move this into MediaWikiTitleCodec
         *
         * @return string Regex string
         */
@@ -823,6 +829,15 @@ class Title {
                return $this->mInterwiki;
        }
 
+       /**
+        * Was this a local interwiki link?
+        *
+        * @return bool
+        */
+       public function wasLocalInterwiki() {
+               return $this->mLocalInterwiki;
+       }
+
        /**
         * Determine whether the object refers to a page within
         * this project and is transcludable.
@@ -853,7 +868,7 @@ class Title {
        /**
         * Get a TitleValue object representing this Title.
         *
-        * @note: Not all valid Titles have a corresponding valid TitleValue
+        * @note Not all valid Titles have a corresponding valid TitleValue
         * (e.g. TitleValues cannot represent page-local links that have a
         * fragment but no title text).
         *
@@ -929,10 +944,12 @@ class Title {
         * Get the page's content model id, see the CONTENT_MODEL_XXX constants.
         *
         * @throws MWException
+        * @param int $flags A bit field; may be Title::GAID_FOR_UPDATE to select for update
         * @return string Content model id
         */
-       public function getContentModel() {
-               if ( !$this->mContentModel ) {
+       public function getContentModel( $flags = 0 ) {
+               # Calling getArticleID() loads the field from cache as needed
+               if ( !$this->mContentModel && $this->getArticleID( $flags ) ) {
                        $linkCache = LinkCache::singleton();
                        $this->mContentModel = $linkCache->getGoodLinkFieldObj( $this, 'model' );
                }
@@ -977,9 +994,9 @@ class Title {
                }
 
                try {
-                       $formatter = $this->getTitleFormatter();
+                       $formatter = self::getTitleFormatter();
                        return $formatter->getNamespaceName( $this->mNamespace, $this->mDbkeyform );
-               } catch ( InvalidArgumentException $ex )  {
+               } catch ( InvalidArgumentException $ex ) {
                        wfDebug( __METHOD__ . ': ' . $ex->getMessage() . "\n" );
                        return false;
                }
@@ -1094,7 +1111,7 @@ class Title {
        /**
         * Returns true if the title is inside one of the specified namespaces.
         *
-        * @param ...$namespaces The namespaces to check for
+        * @param int $namespaces,... The namespaces to check for
         * @return bool
         * @since 1.19
         */
@@ -1546,18 +1563,6 @@ class Title {
                return Title::makeTitleSafe( $this->getNamespace(), $this->getText() . '/' . $text );
        }
 
-       /**
-        * Get the HTML-escaped displayable text form.
-        * Used for the title field in <a> tags.
-        *
-        * @return string The text, including any prefixes
-        * @deprecated since 1.19
-        */
-       public function getEscapedText() {
-               wfDeprecated( __METHOD__, '1.19' );
-               return htmlspecialchars( $this->getPrefixedText() );
-       }
-
        /**
         * Get a URL-encoded form of the subpage text
         *
@@ -1655,9 +1660,11 @@ class Title {
         * $wgServer is prepended to make an absolute URL.
         *
         * @see self::getFullURL to always get an absolute URL.
+        * @see self::getLinkURL to always get a URL that's the simplest URL that will be
+        *  valid to link, locally, to the current Title.
         * @see self::newFromText to produce a Title object.
         *
-        * @param string|array $query an optional query string,
+        * @param string|array $query An optional query string,
         *   not used for interwiki links. Can be specified as an associative array as well,
         *   e.g., array( 'action' => 'edit' ) (keys and values will be URL-escaped).
         *   Some query patterns will trigger various shorturl path replacements.
@@ -1775,34 +1782,6 @@ class Title {
                return $ret;
        }
 
-       /**
-        * Get an HTML-escaped version of the URL form, suitable for
-        * using in a link, without a server name or fragment
-        *
-        * @see self::getLocalURL for the arguments.
-        * @param string $query
-        * @param bool|string $query2
-        * @return string The URL
-        * @deprecated since 1.19
-        */
-       public function escapeLocalURL( $query = '', $query2 = false ) {
-               wfDeprecated( __METHOD__, '1.19' );
-               return htmlspecialchars( $this->getLocalURL( $query, $query2 ) );
-       }
-
-       /**
-        * Get an HTML-escaped version of the URL form, suitable for
-        * using in a link, including the server name and fragment
-        *
-        * @see self::getLocalURL for the arguments.
-        * @return string The URL
-        * @deprecated since 1.19
-        */
-       public function escapeFullURL( $query = '', $query2 = false ) {
-               wfDeprecated( __METHOD__, '1.19' );
-               return htmlspecialchars( $this->getFullURL( $query, $query2 ) );
-       }
-
        /**
         * Get the URL form for an internal link.
         * - Used in various Squid-related code, in case we have a different
@@ -1842,19 +1821,6 @@ class Title {
                return $url;
        }
 
-       /**
-        * HTML-escaped version of getCanonicalURL()
-        *
-        * @see self::getLocalURL for the arguments.
-        * @since 1.18
-        * @return string
-        * @deprecated since 1.19
-        */
-       public function escapeCanonicalURL( $query = '', $query2 = false ) {
-               wfDeprecated( __METHOD__, '1.19' );
-               return htmlspecialchars( $this->getCanonicalURL( $query, $query2 ) );
-       }
-
        /**
         * Get the edit URL for this Title
         *
@@ -1888,17 +1854,6 @@ class Title {
                return $this->mWatched;
        }
 
-       /**
-        * Can $wgUser read this page?
-        *
-        * @deprecated since 1.19; use userCan(), quickUserCan() or getUserPermissionsErrors() instead
-        * @return bool
-        */
-       public function userCanRead() {
-               wfDeprecated( __METHOD__, '1.19' );
-               return $this->userCan( 'read' );
-       }
-
        /**
         * Can $user perform $action on this page?
         * This skips potentially expensive cascading permission checks
@@ -1942,11 +1897,11 @@ class Title {
         *
         * @todo FIXME: This *does not* check throttles (User::pingLimiter()).
         *
-        * @param string $action action that permission needs to be checked for
+        * @param string $action Action that permission needs to be checked for
         * @param User $user User to check
         * @param bool $doExpensiveQueries Set this to false to avoid doing unnecessary
         *   queries by skipping checks for cascading protections and user blocks.
-        * @param array $ignoreErrors of Strings Set this to a list of message keys
+        * @param array $ignoreErrors Array of Strings Set this to a list of message keys
         *   whose corresponding errors may be ignored.
         * @return array Array of arguments to wfMessage to explain permissions problems.
         */
@@ -1970,7 +1925,7 @@ class Title {
        /**
         * Permissions checks that fail most often, and which are easiest to test.
         *
-        * @param string $action the action to check
+        * @param string $action The action to check
         * @param User $user User to check
         * @param array $errors List of current errors
         * @param bool $doExpensiveQueries Whether or not to perform expensive queries
@@ -2125,7 +2080,7 @@ class Title {
                        $ns = $this->mNamespace == NS_MAIN ?
                                wfMessage( 'nstab-main' )->text() : $this->getNsText();
                        $errors[] = $this->mNamespace == NS_MEDIAWIKI ?
-                               array( 'protectedinterface' ) : array( 'namespaceprotected', $ns );
+                               array( 'protectedinterface', $action ) : array( 'namespaceprotected', $ns, $action );
                }
 
                return $errors;
@@ -2149,15 +2104,15 @@ class Title {
                if ( $action != 'patrol' && !$user->isAllowed( 'editusercssjs' ) ) {
                        if ( preg_match( '/^' . preg_quote( $user->getName(), '/' ) . '\//', $this->mTextform ) ) {
                                if ( $this->isCssSubpage() && !$user->isAllowedAny( 'editmyusercss', 'editusercss' ) ) {
-                                       $errors[] = array( 'mycustomcssprotected' );
+                                       $errors[] = array( 'mycustomcssprotected', $action );
                                } elseif ( $this->isJsSubpage() && !$user->isAllowedAny( 'editmyuserjs', 'edituserjs' ) ) {
-                                       $errors[] = array( 'mycustomjsprotected' );
+                                       $errors[] = array( 'mycustomjsprotected', $action );
                                }
                        } else {
                                if ( $this->isCssSubpage() && !$user->isAllowed( 'editusercss' ) ) {
-                                       $errors[] = array( 'customcssprotected' );
+                                       $errors[] = array( 'customcssprotected', $action );
                                } elseif ( $this->isJsSubpage() && !$user->isAllowed( 'edituserjs' ) ) {
-                                       $errors[] = array( 'customjsprotected' );
+                                       $errors[] = array( 'customjsprotected', $action );
                                }
                        }
                }
@@ -2192,9 +2147,9 @@ class Title {
                                continue;
                        }
                        if ( !$user->isAllowed( $right ) ) {
-                               $errors[] = array( 'protectedpagetext', $right );
+                               $errors[] = array( 'protectedpagetext', $right, $action );
                        } elseif ( $this->mCascadeRestriction && !$user->isAllowed( 'protect' ) ) {
-                               $errors[] = array( 'protectedpagetext', 'protect' );
+                               $errors[] = array( 'protectedpagetext', 'protect', $action );
                        }
                }
 
@@ -2241,7 +2196,7 @@ class Title {
                                                foreach ( $cascadingSources as $page ) {
                                                        $pages .= '* [[:' . $page->getPrefixedText() . "]]\n";
                                                }
-                                               $errors[] = array( 'cascadeprotected', count( $cascadingSources ), $pages );
+                                               $errors[] = array( 'cascadeprotected', count( $cascadingSources ), $pages, $action );
                                        }
                                }
                        }
@@ -2308,6 +2263,16 @@ class Title {
                                $errors[] = array( 'immobile-target-page' );
                        }
                } elseif ( $action == 'delete' ) {
+                       $tempErrors = $this->checkPageRestrictions( 'edit',
+                               $user, array(), $doExpensiveQueries, true );
+                       if ( !$tempErrors ) {
+                               $tempErrors = $this->checkCascadingSourcesRestrictions( 'edit',
+                                       $user, $tempErrors, $doExpensiveQueries, true );
+                       }
+                       if ( $tempErrors ) {
+                               // If protection keeps them from editing, they shouldn't be able to delete.
+                               $errors[] = array( 'deleteprotected' );
+                       }
                        if ( $doExpensiveQueries && $wgDeleteRevisionsLimit
                                && !$this->userCan( 'bigdelete', $user ) && $this->isBigDeletion()
                        ) {
@@ -2481,6 +2446,19 @@ class Title {
                                'checkPermissionHooks',
                                'checkReadPermissions',
                        );
+               # Don't call checkSpecialsAndNSPermissions or checkCSSandJSPermissions
+               # here as it will lead to duplicate error messages. This is okay to do
+               # since anywhere that checks for create will also check for edit, and
+               # those checks are called for edit.
+               } elseif ( $action == 'create' ) {
+                       $checks = array(
+                               'checkQuickPermissions',
+                               'checkPermissionHooks',
+                               'checkPageRestrictions',
+                               'checkCascadingSourcesRestrictions',
+                               'checkActionPermissions',
+                               'checkUserBlock'
+                       );
                } else {
                        $checks = array(
                                'checkQuickPermissions',
@@ -2628,7 +2606,7 @@ class Title {
        /**
         * Does the title correspond to a protected article?
         *
-        * @param string $action the action the page is protected from,
+        * @param string $action The action the page is protected from,
         * by default checks all actions.
         * @return bool
         */
@@ -3036,7 +3014,7 @@ class Title {
 
                $method = __METHOD__;
                $dbw = wfGetDB( DB_MASTER );
-               $dbw->onTransactionIdle( function() use ( $dbw, $method ) {
+               $dbw->onTransactionIdle( function () use ( $dbw, $method ) {
                        $dbw->delete(
                                'page_restrictions',
                                array( 'pr_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ),
@@ -3302,6 +3280,7 @@ class Title {
                $this->mEstimateRevisions = null;
                $this->mPageLanguage = false;
                $this->mDbPageLanguage = null;
+               $this->mIsBigDeletion = null;
        }
 
        /**
@@ -3344,8 +3323,8 @@ class Title {
                        // @note: splitTitleString() is a temporary hack to allow MediaWikiTitleCodec to share
                        //        the parsing code with Title, while avoiding massive refactoring.
                        // @todo: get rid of secureAndSplit, refactor parsing code.
-                       $parser = $this->getTitleParser();
-                       $parts = $parser->splitTitleString( $dbkey, $this->getDefaultNamespace() );
+                       $titleParser = self::getTitleParser();
+                       $parts = $titleParser->splitTitleString( $dbkey, $this->getDefaultNamespace() );
                } catch ( MalformedTitleException $ex ) {
                        return false;
                }
@@ -3353,6 +3332,7 @@ class Title {
                # Fill fields
                $this->setFragment( '#' . $parts['fragment'] );
                $this->mInterwiki = $parts['interwiki'];
+               $this->mLocalInterwiki = $parts['local_interwiki'];
                $this->mNamespace = $parts['namespace'];
                $this->mUserCaseDBKey = $parts['user_case_dbkey'];
 
@@ -3768,7 +3748,7 @@ class Title {
         * @return array|bool True on success, getUserPermissionsErrors()-like array on failure
         */
        public function moveTo( &$nt, $auth = true, $reason = '', $createRedirect = true ) {
-               global $wgUser;
+               global $wgUser, $wgCategoryCollation;
                $err = $this->isValidMoveOperation( $nt, $auth, $reason );
                if ( is_array( $err ) ) {
                        // Auto-block user's IP if the account was "hard" blocked
@@ -3807,12 +3787,21 @@ class Title {
 
                // Refresh the sortkey for this row.  Be careful to avoid resetting
                // cl_timestamp, which may disturb time-based lists on some sites.
+               // @todo This block should be killed, it's duplicating code
+               // from LinksUpdate::getCategoryInsertions() and friends.
                $prefixes = $dbw->select(
                        'categorylinks',
                        array( 'cl_sortkey_prefix', 'cl_to' ),
                        array( 'cl_from' => $pageid ),
                        __METHOD__
                );
+               if ( $nt->getNamespace() == NS_CATEGORY ) {
+                       $type = 'subcat';
+               } elseif ( $nt->getNamespace() == NS_FILE ) {
+                       $type = 'file';
+               } else {
+                       $type = 'page';
+               }
                foreach ( $prefixes as $prefixRow ) {
                        $prefix = $prefixRow->cl_sortkey_prefix;
                        $catTo = $prefixRow->cl_to;
@@ -3820,6 +3809,8 @@ class Title {
                                array(
                                        'cl_sortkey' => Collation::singleton()->getSortKey(
                                                $nt->getCategorySortkey( $prefix ) ),
+                                       'cl_collation' => $wgCategoryCollation,
+                                       'cl_type' => $type,
                                        'cl_timestamp=cl_timestamp' ),
                                array(
                                        'cl_from' => $pageid,
@@ -3878,13 +3869,31 @@ class Title {
                        $log->addRelations( 'pr_id', $logRelationsValues, $logId );
                }
 
+               // Update *_from_namespace fields as needed
+               if ( $this->getNamespace() != $nt->getNamespace() ) {
+                       $dbw->update( 'pagelinks',
+                               array( 'pl_from_namespace' => $nt->getNamespace() ),
+                               array( 'pl_from' => $pageid ),
+                               __METHOD__
+                       );
+                       $dbw->update( 'templatelinks',
+                               array( 'tl_from_namespace' => $nt->getNamespace() ),
+                               array( 'tl_from' => $pageid ),
+                               __METHOD__
+                       );
+                       $dbw->update( 'imagelinks',
+                               array( 'il_from_namespace' => $nt->getNamespace() ),
+                               array( 'il_from' => $pageid ),
+                               __METHOD__
+                       );
+               }
+
                # Update watchlists
-               $oldnamespace = MWNamespace::getSubject( $this->getNamespace() );
-               $newnamespace = MWNamespace::getSubject( $nt->getNamespace() );
                $oldtitle = $this->getDBkey();
                $newtitle = $nt->getDBkey();
-
-               if ( $oldnamespace != $newnamespace || $oldtitle != $newtitle ) {
+               $oldsnamespace = MWNamespace::getSubject( $this->getNamespace() );
+               $newsnamespace = MWNamespace::getSubject( $nt->getNamespace() );
+               if ( $oldsnamespace != $newsnamespace || $oldtitle != $newtitle ) {
                        WatchedItem::duplicateEntries( $this, $nt );
                }
 
@@ -3933,9 +3942,13 @@ class Title {
                        $redirectContent = null;
                }
 
+               // bug 57084: log_page should be the ID of the *moved* page
+               $oldid = $this->getArticleID();
+               $logTitle = clone $this;
+
                $logEntry = new ManualLogEntry( 'move', $logType );
                $logEntry->setPerformer( $wgUser );
-               $logEntry->setTarget( $this );
+               $logEntry->setTarget( $logTitle );
                $logEntry->setComment( $reason );
                $logEntry->setParameters( array(
                        '4::target' => $nt->getPrefixedText(),
@@ -3951,8 +3964,6 @@ class Title {
                # Truncate for whole multibyte characters.
                $comment = $wgContLang->truncate( $comment, 255 );
 
-               $oldid = $this->getArticleID();
-
                $dbw = wfGetDB( DB_MASTER );
 
                $newpage = WikiPage::factory( $nt );
@@ -4389,12 +4400,32 @@ class Title {
                        return false;
                }
 
-               $revCount = $this->estimateRevisionCount();
-               return $revCount > $wgDeleteRevisionsLimit;
+               if ( $this->mIsBigDeletion === null ) {
+                       $dbr = wfGetDB( DB_SLAVE );
+
+                       $innerQuery = $dbr->selectSQLText(
+                               'revision',
+                               '1',
+                               array( 'rev_page' => $this->getArticleID() ),
+                               __METHOD__,
+                               array( 'LIMIT' => $wgDeleteRevisionsLimit + 1 )
+                       );
+
+                       $revCount = $dbr->query(
+                               'SELECT COUNT(*) FROM (' . $innerQuery . ') AS innerQuery',
+                               __METHOD__
+                       );
+                       $revCount = $revCount->fetchRow();
+                       $revCount = $revCount['COUNT(*)'];
+
+                       $this->mIsBigDeletion = $revCount > $wgDeleteRevisionsLimit;
+               }
+
+               return $this->mIsBigDeletion;
        }
 
        /**
-        * Get the  approximate revision count of this page.
+        * Get the approximate revision count of this page.
         *
         * @return int
         */
@@ -4720,7 +4751,7 @@ class Title {
                $method = __METHOD__;
                $dbw = wfGetDB( DB_MASTER );
                $conds = $this->pageCond();
-               $dbw->onTransactionIdle( function() use ( $dbw, $conds, $method ) {
+               $dbw->onTransactionIdle( function () use ( $dbw, $conds, $method ) {
                        $dbw->update(
                                'page',
                                array( 'page_touched' => $dbw->timestamp() ),
index 5a117bd..635b1e9 100644 (file)
  * @file
  */
 
-/**
- * Int Number of characters in user_token field.
- * @ingroup Constants
- */
-define( 'USER_TOKEN_LENGTH', 32 );
-
-/**
- * Int Serialized record version.
- * @ingroup Constants
- */
-define( 'MW_USER_VERSION', 9 );
-
 /**
  * String Some punctuation to prevent editing from broken text-mangling proxies.
  * @ingroup Constants
  */
 define( 'EDIT_TOKEN_SUFFIX', '+\\' );
 
-/**
- * Thrown by User::setPassword() on error.
- * @ingroup Exception
- */
-class PasswordError extends MWException {
-       // NOP
-}
-
 /**
  * The User object encapsulates all of the user-specific settings (user_id,
  * name, rights, password, email address, options, last login time). Client
@@ -58,18 +38,31 @@ class PasswordError extends MWException {
  */
 class User implements IDBAccessObject {
        /**
-        * Global constants made accessible as class constants so that autoloader
+        * @const int Number of characters in user_token field.
+        */
+       const TOKEN_LENGTH = 32;
+
+       /**
+        * Global constant made accessible as class constants so that autoloader
         * magic can be used.
         */
-       const USER_TOKEN_LENGTH = USER_TOKEN_LENGTH;
-       const MW_USER_VERSION = MW_USER_VERSION;
        const EDIT_TOKEN_SUFFIX = EDIT_TOKEN_SUFFIX;
 
+       /**
+        * @const int Serialized record version.
+        */
+       const VERSION = 10;
+
        /**
         * Maximum items in $mWatchedItems
         */
        const MAX_WATCHED_ITEMS_CACHE = 100;
 
+       /**
+        * @var PasswordFactory Lazily loaded factory object for passwords
+        */
+       private static $mPasswordFactory = null;
+
        /**
         * Array of Strings List of member variables which are saved to the
         * shared cache (memcached). Any operation which changes the
@@ -81,16 +74,12 @@ class User implements IDBAccessObject {
                'mId',
                'mName',
                'mRealName',
-               'mPassword',
-               'mNewpassword',
-               'mNewpassTime',
                'mEmail',
                'mTouched',
                'mToken',
                'mEmailAuthenticated',
                'mEmailToken',
                'mEmailTokenExpires',
-               'mPasswordExpires',
                'mRegistration',
                'mEditCount',
                // user_groups table
@@ -175,6 +164,7 @@ class User implements IDBAccessObject {
                'userrights-interwiki',
                'viewmyprivateinfo',
                'viewmywatchlist',
+               'viewsuppressed',
                'writeapi',
        );
 
@@ -191,8 +181,16 @@ class User implements IDBAccessObject {
 
        public $mRealName;
 
+       /**
+        * @todo Make this actually private
+        * @private
+        */
        public $mPassword;
 
+       /**
+        * @todo Make this actually private
+        * @private
+        */
        public $mNewpassword;
 
        public $mNewpassTime;
@@ -356,7 +354,7 @@ class User implements IDBAccessObject {
 
        /**
         * Load user table data, given mId has already been set.
-        * @return bool false if the ID does not exist, true otherwise
+        * @return bool False if the ID does not exist, true otherwise
         */
        public function loadFromId() {
                global $wgMemc;
@@ -368,7 +366,7 @@ class User implements IDBAccessObject {
                // Try cache
                $key = wfMemcKey( 'user', 'id', $this->mId );
                $data = $wgMemc->get( $key );
-               if ( !is_array( $data ) || $data['mVersion'] < MW_USER_VERSION ) {
+               if ( !is_array( $data ) || $data['mVersion'] != self::VERSION ) {
                        // Object is expired, load from DB
                        $data = false;
                }
@@ -409,7 +407,7 @@ class User implements IDBAccessObject {
                foreach ( self::$mCacheVars as $name ) {
                        $data[$name] = $this->$name;
                }
-               $data['mVersion'] = MW_USER_VERSION;
+               $data['mVersion'] = self::VERSION;
                $key = wfMemcKey( 'user', 'id', $this->mId );
                global $wgMemc;
                $wgMemc->set( $key, $data );
@@ -752,7 +750,7 @@ class User implements IDBAccessObject {
         * Given unvalidated password input, return error message on failure.
         *
         * @param string $password Desired password
-        * @return bool|string|array true on success, string or array of error message on failure
+        * @return bool|string|array True on success, string or array of error message on failure
         */
        public function getPasswordValidity( $password ) {
                $result = $this->checkPasswordValidity( $password );
@@ -831,7 +829,7 @@ class User implements IDBAccessObject {
         * @param int $ts Optional timestamp to convert, default 0 for the current time
         */
        public function expirePassword( $ts = 0 ) {
-               $this->load();
+               $this->loadPasswords();
                $timestamp = wfTimestamp( TS_MW, $ts );
                $this->mPasswordExpires = $timestamp;
                $this->saveSettings();
@@ -892,38 +890,6 @@ class User implements IDBAccessObject {
                return $this->mPasswordExpires;
        }
 
-       /**
-        * Does a string look like an e-mail address?
-        *
-        * This validates an email address using an HTML5 specification found at:
-        * http://www.whatwg.org/html/states-of-the-type-attribute.html#valid-e-mail-address
-        * Which as of 2011-01-24 says:
-        *
-        *     A valid e-mail address is a string that matches the ABNF production
-        *   1*( atext / "." ) "@" ldh-str *( "." ldh-str ) where atext is defined
-        *   in RFC 5322 section 3.2.3, and ldh-str is defined in RFC 1034 section
-        *   3.5.
-        *
-        * This function is an implementation of the specification as requested in
-        * bug 22449.
-        *
-        * Client-side forms will use the same standard validation rules via JS or
-        * HTML 5 validation; additional restrictions can be enforced server-side
-        * by extensions via the 'isValidEmailAddr' hook.
-        *
-        * Note that this validation doesn't 100% match RFC 2822, but is believed
-        * to be liberal enough for wide use. Some invalid addresses will still
-        * pass validation here.
-        *
-        * @param string $addr E-mail address
-        * @return bool
-        * @deprecated since 1.18 call Sanitizer::isValidEmail() directly
-        */
-       public static function isValidEmailAddr( $addr ) {
-               wfDeprecated( __METHOD__, '1.18' );
-               return Sanitizer::validateEmail( $addr );
-       }
-
        /**
         * Given unvalidated user input, return a canonical username, or false if
         * the username is invalid.
@@ -949,8 +915,9 @@ class User implements IDBAccessObject {
                        return false;
                }
 
-               // Clean up name according to title rules
-               $t = ( $validate === 'valid' ) ?
+               // Clean up name according to title rules,
+               // but only when validation is requested (bug 12654)
+               $t = ( $validate !== false ) ?
                        Title::newFromText( $name ) : Title::makeTitle( NS_USER, $name );
                // Check for invalid titles
                if ( is_null( $t ) ) {
@@ -1028,10 +995,13 @@ class User implements IDBAccessObject {
        public function loadDefaults( $name = false ) {
                wfProfileIn( __METHOD__ );
 
+               $passwordFactory = self::getPasswordFactory();
+
                $this->mId = 0;
                $this->mName = $name;
                $this->mRealName = '';
-               $this->mPassword = $this->mNewpassword = '';
+               $this->mPassword = $passwordFactory->newFromCiphertext( null );
+               $this->mNewpassword = $passwordFactory->newFromCiphertext( null );
                $this->mNewpassTime = null;
                $this->mEmail = '';
                $this->mOptionOverrides = null;
@@ -1170,7 +1140,7 @@ class User implements IDBAccessObject {
         * Load user and user_group data from the database.
         * $this->mId must be set, this is how the user is identified.
         *
-        * @param integer $flags Supports User::READ_LOCKING
+        * @param int $flags Supports User::READ_LOCKING
         * @return bool True if the user exists, false if the user is anonymous
         */
        public function loadFromDatabase( $flags = 0 ) {
@@ -1221,6 +1191,7 @@ class User implements IDBAccessObject {
         */
        public function loadFromRow( $row, $data = null ) {
                $all = true;
+               $passwordFactory = self::getPasswordFactory();
 
                $this->mGroups = null; // deferred
 
@@ -1254,9 +1225,31 @@ class User implements IDBAccessObject {
                }
 
                if ( isset( $row->user_password ) ) {
-                       $this->mPassword = $row->user_password;
-                       $this->mNewpassword = $row->user_newpassword;
+                       // Check for *really* old password hashes that don't even have a type
+                       // The old hash format was just an md5 hex hash, with no type information
+                       if ( preg_match( '/^[0-9a-f]{32}$/', $row->user_password ) ) {
+                               $row->user_password = ":A:{$this->mId}:{$row->user_password}";
+                       }
+
+                       try {
+                               $this->mPassword = $passwordFactory->newFromCiphertext( $row->user_password );
+                       } catch ( PasswordError $e ) {
+                               wfDebug( 'Invalid password hash found in database.' );
+                               $this->mPassword = $passwordFactory->newFromCiphertext( null );
+                       }
+
+                       try {
+                               $this->mNewpassword = $passwordFactory->newFromCiphertext( $row->user_newpassword );
+                       } catch ( PasswordError $e ) {
+                               wfDebug( 'Invalid password hash found in database.' );
+                               $this->mNewpassword = $passwordFactory->newFromCiphertext( null );
+                       }
+
                        $this->mNewpassTime = wfTimestampOrNull( TS_MW, $row->user_newpass_time );
+                       $this->mPasswordExpires = wfTimestampOrNull( TS_MW, $row->user_password_expires );
+               }
+
+               if ( isset( $row->user_email ) ) {
                        $this->mEmail = $row->user_email;
                        $this->mTouched = wfTimestamp( TS_MW, $row->user_touched );
                        $this->mToken = $row->user_token;
@@ -1266,7 +1259,6 @@ class User implements IDBAccessObject {
                        $this->mEmailAuthenticated = wfTimestampOrNull( TS_MW, $row->user_email_authenticated );
                        $this->mEmailToken = $row->user_email_token;
                        $this->mEmailTokenExpires = wfTimestampOrNull( TS_MW, $row->user_email_token_expires );
-                       $this->mPasswordExpires = wfTimestampOrNull( TS_MW, $row->user_password_expires );
                        $this->mRegistration = wfTimestampOrNull( TS_MW, $row->user_registration );
                } else {
                        $all = false;
@@ -1317,6 +1309,26 @@ class User implements IDBAccessObject {
                }
        }
 
+       /**
+        * Load the user's password hashes from the database
+        *
+        * This is usually called in a scenario where the actual User object was
+        * loaded from the cache, and then password comparison needs to be performed.
+        * Password hashes are not stored in memcached.
+        *
+        * @since 1.24
+        */
+       private function loadPasswords() {
+               if ( $this->getId() !== 0 && ( $this->mPassword === null || $this->mNewpassword === null ) ) {
+                       $this->loadFromRow( wfGetDB( DB_MASTER )->selectRow(
+                                       'user',
+                                       array( 'user_password', 'user_newpassword', 'user_newpass_time', 'user_password_expires' ),
+                                       array( 'user_id' => $this->getId() ),
+                                       __METHOD__
+                               ) );
+               }
+       }
+
        /**
         * Add the user to the group if he/she meets given criteria.
         *
@@ -1416,7 +1428,7 @@ class User implements IDBAccessObject {
                foreach ( SearchEngine::searchableNamespaces() as $nsnum => $nsname ) {
                        $defOpt['searchNs' . $nsnum] = !empty( $wgNamespacesToBeSearchedDefault[$nsnum] );
                }
-               $defOpt['skin'] = $wgDefaultSkin;
+               $defOpt['skin'] = Skin::normalizeKey( $wgDefaultSkin );
 
                wfRunHooks( 'UserGetDefaultOptions', array( &$defOpt ) );
 
@@ -1537,10 +1549,9 @@ class User implements IDBAccessObject {
         * @return bool True if blacklisted.
         */
        public function isDnsBlacklisted( $ip, $checkWhitelist = false ) {
-               global $wgEnableSorbs, $wgEnableDnsBlacklist,
-                       $wgSorbsUrl, $wgDnsBlacklistUrls, $wgProxyWhitelist;
+               global $wgEnableDnsBlacklist, $wgDnsBlacklistUrls, $wgProxyWhitelist;
 
-               if ( !$wgEnableDnsBlacklist && !$wgEnableSorbs ) {
+               if ( !$wgEnableDnsBlacklist ) {
                        return false;
                }
 
@@ -1548,8 +1559,7 @@ class User implements IDBAccessObject {
                        return false;
                }
 
-               $urls = array_merge( $wgDnsBlacklistUrls, (array)$wgSorbsUrl );
-               return $this->inDnsBlacklist( $ip, $urls );
+               return $this->inDnsBlacklist( $ip, $wgDnsBlacklistUrls );
        }
 
        /**
@@ -1875,7 +1885,6 @@ class User implements IDBAccessObject {
                        return $this->mLocked;
                }
                global $wgAuth;
-               StubObject::unstub( $wgAuth );
                $authUser = $wgAuth->getUserInstance( $this );
                $this->mLocked = (bool)$authUser->isLocked();
                return $this->mLocked;
@@ -1893,7 +1902,6 @@ class User implements IDBAccessObject {
                $this->getBlockedStatus();
                if ( !$this->mHideName ) {
                        global $wgAuth;
-                       StubObject::unstub( $wgAuth );
                        $authUser = $wgAuth->getUserInstance( $this );
                        $this->mHideName = (bool)$authUser->isHidden();
                }
@@ -2067,7 +2075,7 @@ class User implements IDBAccessObject {
         * @see getNewtalk()
         * @param string $field 'user_ip' for anonymous users, 'user_id' otherwise
         * @param string|int $id User's IP address for anonymous users, User ID otherwise
-        * @param bool $fromMaster true to fetch from the master, false for a slave
+        * @param bool $fromMaster True to fetch from the master, false for a slave
         * @return bool True if the user has new messages
         */
        protected function checkNewtalk( $field, $id, $fromMaster = false ) {
@@ -2184,7 +2192,7 @@ class User implements IDBAccessObject {
         *
         * Called implicitly from invalidateCache() and saveSettings().
         */
-       private function clearSharedCache() {
+       public function clearSharedCache() {
                $this->load();
                if ( $this->mId ) {
                        global $wgMemc;
@@ -2209,7 +2217,7 @@ class User implements IDBAccessObject {
                        $userid = $this->mId;
                        $touched = $this->mTouched;
                        $method = __METHOD__;
-                       $dbw->onTransactionIdle( function() use ( $dbw, $userid, $touched, $method ) {
+                       $dbw->onTransactionIdle( function () use ( $dbw, $userid, $touched, $method ) {
                                // Prevent contention slams by checking user_touched first
                                $encTouched = $dbw->addQuotes( $dbw->timestamp( $touched ) );
                                $needsPurge = $dbw->selectField( 'user', '1',
@@ -2245,6 +2253,26 @@ class User implements IDBAccessObject {
                return $this->mTouched;
        }
 
+       /**
+        * @return Password
+        * @since 1.24
+        */
+       public function getPassword() {
+               $this->loadPasswords();
+
+               return $this->mPassword;
+       }
+
+       /**
+        * @return Password
+        * @since 1.24
+        */
+       public function getTemporaryPassword() {
+               $this->loadPasswords();
+
+               return $this->mNewpassword;
+       }
+
        /**
         * Set the password and reset the random token.
         * Calls through to authentication plugin if necessary;
@@ -2257,13 +2285,15 @@ class User implements IDBAccessObject {
         * a new password is set, for instance via e-mail.
         *
         * @param string $str New password to set
-        * @throws PasswordError on failure
+        * @throws PasswordError On failure
         *
         * @return bool
         */
        public function setPassword( $str ) {
                global $wgAuth;
 
+               $this->loadPasswords();
+
                if ( $str !== null ) {
                        if ( !$wgAuth->allowPasswordChange() ) {
                                throw new PasswordError( wfMessage( 'password-change-forbidden' )->text() );
@@ -2300,16 +2330,16 @@ class User implements IDBAccessObject {
         *  through the web interface.
         */
        public function setInternalPassword( $str ) {
-               $this->load();
                $this->setToken();
 
+               $passwordFactory = self::getPasswordFactory();
                if ( $str === null ) {
-                       // Save an invalid hash...
-                       $this->mPassword = '';
+                       $this->mPassword = $passwordFactory->newFromCiphertext( null );
                } else {
-                       $this->mPassword = self::crypt( $str );
+                       $this->mPassword = $passwordFactory->newFromPlaintext( $str );
                }
-               $this->mNewpassword = '';
+
+               $this->mNewpassword = $passwordFactory->newFromCiphertext( null );
                $this->mNewpassTime = null;
        }
 
@@ -2336,7 +2366,7 @@ class User implements IDBAccessObject {
        public function setToken( $token = false ) {
                $this->load();
                if ( !$token ) {
-                       $this->mToken = MWCryptRand::generateHex( USER_TOKEN_LENGTH );
+                       $this->mToken = MWCryptRand::generateHex( self::TOKEN_LENGTH );
                } else {
                        $this->mToken = $token;
                }
@@ -2350,13 +2380,13 @@ class User implements IDBAccessObject {
         * @param bool $throttle If true, reset the throttle timestamp to the present
         */
        public function setNewpassword( $str, $throttle = true ) {
-               $this->load();
+               $this->loadPasswords();
 
                if ( $str === null ) {
                        $this->mNewpassword = '';
                        $this->mNewpassTime = null;
                } else {
-                       $this->mNewpassword = self::crypt( $str );
+                       $this->mNewpassword = self::getPasswordFactory()->newFromPlaintext( $str );
                        if ( $throttle ) {
                                $this->mNewpassTime = wfTimestampNow();
                        }
@@ -2407,8 +2437,8 @@ class User implements IDBAccessObject {
                if ( $str == $this->mEmail ) {
                        return;
                }
-               $this->mEmail = $str;
                $this->invalidateEmail();
+               $this->mEmail = $str;
                wfRunHooks( 'UserSetEmail', array( $this, &$this->mEmail ) );
        }
 
@@ -2657,7 +2687,7 @@ class User implements IDBAccessObject {
         * @param IContextSource $context
         * @param array $options Assoc. array with options keys to check as keys.
         *   Defaults to $this->mOptions.
-        * @return array the key => kind mapping data
+        * @return array The key => kind mapping data
         */
        public function getOptionKinds( IContextSource $context, $options = null ) {
                $this->loadOptions();
@@ -2701,7 +2731,7 @@ class User implements IDBAccessObject {
 
                                foreach ( $columns as $column ) {
                                        foreach ( $rows as $row ) {
-                                               $checkmatrixOptions["$prefix-$column-$row"] = true;
+                                               $checkmatrixOptions["$prefix$column-$row"] = true;
                                        }
                                }
 
@@ -2778,6 +2808,8 @@ class User implements IDBAccessObject {
                        }
                }
 
+               wfRunHooks( 'UserResetAllOptions', array( $this, &$newOptions, $this->mOptions, $resetKinds ) );
+
                $this->mOptions = $newOptions;
                $this->mOptionsLoaded = true;
        }
@@ -2939,7 +2971,7 @@ class User implements IDBAccessObject {
 
        /**
         * Get the user's edit count.
-        * @return int|null null for anonymous users
+        * @return int|null Null for anonymous users
         */
        public function getEditCount() {
                if ( !$this->getId() ) {
@@ -3052,10 +3084,8 @@ class User implements IDBAccessObject {
        /**
         * Check if user is allowed to access a feature / make an action
         *
-        * @internal param \String $varargs permissions to test
+        * @param string $permissions,... Permissions to test
         * @return bool True if user is allowed to perform *any* of the given actions
-        *
-        * @return bool
         */
        public function isAllowedAny( /*...*/ ) {
                $permissions = func_get_args();
@@ -3069,7 +3099,7 @@ class User implements IDBAccessObject {
 
        /**
         *
-        * @internal param $varargs string
+        * @param string $permissions,... Permissions to test
         * @return bool True if the user is allowed to perform *all* of the given actions
         */
        public function isAllowedAll( /*...*/ ) {
@@ -3442,6 +3472,7 @@ class User implements IDBAccessObject {
                global $wgAuth;
 
                $this->load();
+               $this->loadPasswords();
                if ( wfReadOnly() ) {
                        return;
                }
@@ -3451,15 +3482,15 @@ class User implements IDBAccessObject {
 
                $this->mTouched = self::newTouchedTimestamp();
                if ( !$wgAuth->allowSetLocalPassword() ) {
-                       $this->mPassword = '';
+                       $this->mPassword = self::getPasswordFactory()->newFromCiphertext( null );
                }
 
                $dbw = wfGetDB( DB_MASTER );
                $dbw->update( 'user',
                        array( /* SET */
                                'user_name' => $this->mName,
-                               'user_password' => $this->mPassword,
-                               'user_newpassword' => $this->mNewpassword,
+                               'user_password' => $this->mPassword->toString(),
+                               'user_newpassword' => $this->mNewpassword->toString(),
                                'user_newpass_time' => $dbw->timestampOrNull( $this->mNewpassTime ),
                                'user_real_name' => $this->mRealName,
                                'user_email' => $this->mEmail,
@@ -3521,6 +3552,7 @@ class User implements IDBAccessObject {
        public static function createNew( $name, $params = array() ) {
                $user = new User;
                $user->load();
+               $user->loadPasswords();
                $user->setToken(); // init token
                if ( isset( $params['options'] ) ) {
                        $user->mOptions = $params['options'] + (array)$user->mOptions;
@@ -3532,8 +3564,8 @@ class User implements IDBAccessObject {
                $fields = array(
                        'user_id' => $seqVal,
                        'user_name' => $name,
-                       'user_password' => $user->mPassword,
-                       'user_newpassword' => $user->mNewpassword,
+                       'user_password' => $user->mPassword->toString(),
+                       'user_newpassword' => $user->mNewpassword->toString(),
                        'user_newpass_time' => $dbw->timestampOrNull( $user->mNewpassTime ),
                        'user_email' => $user->mEmail,
                        'user_email_authenticated' => $dbw->timestampOrNull( $user->mEmailAuthenticated ),
@@ -3583,6 +3615,7 @@ class User implements IDBAccessObject {
         */
        public function addToDatabase() {
                $this->load();
+               $this->loadPasswords();
                if ( !$this->mToken ) {
                        $this->setToken(); // init token
                }
@@ -3596,8 +3629,8 @@ class User implements IDBAccessObject {
                        array(
                                'user_id' => $seqVal,
                                'user_name' => $this->mName,
-                               'user_password' => $this->mPassword,
-                               'user_newpassword' => $this->mNewpassword,
+                               'user_password' => $this->mPassword->toString(),
+                               'user_newpassword' => $this->mNewpassword->toString(),
                                'user_newpass_time' => $dbw->timestampOrNull( $this->mNewpassTime ),
                                'user_email' => $this->mEmail,
                                'user_email_authenticated' => $dbw->timestampOrNull( $this->mEmailAuthenticated ),
@@ -3748,17 +3781,19 @@ class User implements IDBAccessObject {
 
        /**
         * Check to see if the given clear-text password is one of the accepted passwords
-        * @param string $password user password.
-        * @return bool True if the given password is correct, otherwise False.
+        * @param string $password User password
+        * @return bool True if the given password is correct, otherwise False
         */
        public function checkPassword( $password ) {
                global $wgAuth, $wgLegacyEncoding;
-               $this->load();
+
+               $section = new ProfileSection( __METHOD__ );
+
+               $this->loadPasswords();
 
                // Certain authentication plugins do NOT want to save
                // domain passwords in a mysql database, so we should
                // check this (in case $wgAuth->strict() is false).
-
                if ( $wgAuth->authenticate( $this->getName(), $password ) ) {
                        return true;
                } elseif ( $wgAuth->strict() ) {
@@ -3768,19 +3803,27 @@ class User implements IDBAccessObject {
                        // Auth plugin doesn't allow local authentication for this user name
                        return false;
                }
-               if ( self::comparePasswords( $this->mPassword, $password, $this->mId ) ) {
-                       return true;
-               } elseif ( $wgLegacyEncoding ) {
-                       // Some wikis were converted from ISO 8859-1 to UTF-8, the passwords can't be converted
-                       // Check for this with iconv
-                       $cp1252Password = iconv( 'UTF-8', 'WINDOWS-1252//TRANSLIT', $password );
-                       if ( $cp1252Password != $password
-                               && self::comparePasswords( $this->mPassword, $cp1252Password, $this->mId )
-                       ) {
-                               return true;
+
+               $passwordFactory = self::getPasswordFactory();
+               if ( !$this->mPassword->equals( $password ) ) {
+                       if ( $wgLegacyEncoding ) {
+                               // Some wikis were converted from ISO 8859-1 to UTF-8, the passwords can't be converted
+                               // Check for this with iconv
+                               $cp1252Password = iconv( 'UTF-8', 'WINDOWS-1252//TRANSLIT', $password );
+                               if ( $cp1252Password === $password || !$this->mPassword->equals( $cp1252Password ) ) {
+                                       return false;
+                               }
+                       } else {
+                               return false;
                        }
                }
-               return false;
+
+               if ( $passwordFactory->needsUpdate( $this->mPassword ) ) {
+                       $this->mPassword = $passwordFactory->newFromPlaintext( $password );
+                       $this->saveSettings();
+               }
+
+               return true;
        }
 
        /**
@@ -3795,7 +3838,8 @@ class User implements IDBAccessObject {
                global $wgNewPasswordExpiry;
 
                $this->load();
-               if ( self::comparePasswords( $this->mNewpassword, $plaintext, $this->getId() ) ) {
+               $this->loadPasswords();
+               if ( $this->mNewpassword->equals( $plaintext ) ) {
                        if ( is_null( $this->mNewpassTime ) ) {
                                return true;
                        }
@@ -3810,7 +3854,7 @@ class User implements IDBAccessObject {
         * Alias for getEditToken.
         * @deprecated since 1.19, use getEditToken instead.
         *
-        * @param string|array $salt of Strings Optional function-specific data for hashing
+        * @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 string The new edit token
         */
@@ -3827,7 +3871,7 @@ class User implements IDBAccessObject {
         *
         * @since 1.19
         *
-        * @param string|array $salt of Strings Optional function-specific data for hashing
+        * @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 string The new edit token
         */
@@ -3837,7 +3881,7 @@ class User implements IDBAccessObject {
                }
 
                if ( $this->isAnon() ) {
-                       return EDIT_TOKEN_SUFFIX;
+                       return self::EDIT_TOKEN_SUFFIX;
                } else {
                        $token = $request->getSessionData( 'wsEditToken' );
                        if ( $token === null ) {
@@ -3847,7 +3891,7 @@ class User implements IDBAccessObject {
                        if ( is_array( $salt ) ) {
                                $salt = implode( '|', $salt );
                        }
-                       return md5( $token . $salt ) . EDIT_TOKEN_SUFFIX;
+                       return md5( $token . $salt ) . self::EDIT_TOKEN_SUFFIX;
                }
        }
 
@@ -3888,7 +3932,7 @@ class User implements IDBAccessObject {
         *
         * @param string $val Input value to compare
         * @param string $salt Optional function-specific data for hashing
-        * @param WebRequest|null $request object to use or null to use $wgRequest
+        * @param WebRequest|null $request Object to use or null to use $wgRequest
         * @return bool Whether the token matches
         */
        public function matchEditTokenNoSuffix( $val, $salt = '', $request = null ) {
@@ -3948,10 +3992,10 @@ class User implements IDBAccessObject {
                        $sender = new MailAddress( $wgPasswordSender,
                                wfMessage( 'emailsender' )->inContentLanguage()->text() );
                } else {
-                       $sender = new MailAddress( $from );
+                       $sender = MailAddress::newFromUser( $from );
                }
 
-               $to = new MailAddress( $this );
+               $to = MailAddress::newFromUser( $this );
                return UserMailer::send( $to, $sender, $subject, $body, $replyto );
        }
 
@@ -4045,6 +4089,7 @@ class User implements IDBAccessObject {
                $this->mEmailToken = null;
                $this->mEmailTokenExpires = null;
                $this->setEmailAuthenticationTimestamp( null );
+               $this->mEmail = '';
                wfRunHooks( 'InvalidateEmailComplete', array( $this ) );
                return true;
        }
@@ -4394,7 +4439,7 @@ class User implements IDBAccessObject {
         * Returns an array of the groups that a particular group can add/remove.
         *
         * @param string $group The group to check for whether it can add/remove
-        * @return array array( 'add' => array( addablegroups ),
+        * @return array Array( 'add' => array( addablegroups ),
         *     'remove' => array( removablegroups ),
         *     'add-self' => array( addablegroups to self),
         *     'remove-self' => array( removable groups from self) )
@@ -4464,7 +4509,7 @@ class User implements IDBAccessObject {
 
        /**
         * Returns an array of groups that this user can add and remove
-        * @return array array( 'add' => array( addablegroups ),
+        * @return array Array( 'add' => array( addablegroups ),
         *  'remove' => array( removablegroups ),
         *  'add-self' => array( addablegroups to self),
         *  'remove-self' => array( removable groups from self) )
@@ -4581,22 +4626,6 @@ class User implements IDBAccessObject {
                return $msg->isBlank() ? $right : $msg->text();
        }
 
-       /**
-        * Make an old-style password hash
-        *
-        * @param string $password Plain-text password
-        * @param string $userId User ID
-        * @return string Password hash
-        */
-       public static function oldCrypt( $password, $userId ) {
-               global $wgPasswordSalt;
-               if ( $wgPasswordSalt ) {
-                       return md5( $userId . '-' . md5( $password ) );
-               } else {
-                       return md5( $password );
-               }
-       }
-
        /**
         * Make a new-style password hash
         *
@@ -4604,23 +4633,12 @@ class User implements IDBAccessObject {
         * @param bool|string $salt Optional salt, may be random or the user ID.
         *  If unspecified or false, will generate one automatically
         * @return string Password hash
+        * @deprecated since 1.24, use Password class
         */
        public static function crypt( $password, $salt = false ) {
-               global $wgPasswordSalt;
-
-               $hash = '';
-               if ( !wfRunHooks( 'UserCryptPassword', array( &$password, &$salt, &$wgPasswordSalt, &$hash ) ) ) {
-                       return $hash;
-               }
-
-               if ( $wgPasswordSalt ) {
-                       if ( $salt === false ) {
-                               $salt = MWCryptRand::generateHex( 8 );
-                       }
-                       return ':B:' . $salt . ':' . md5( $salt . '-' . md5( $password ) );
-               } else {
-                       return ':A:' . md5( $password );
-               }
+               wfDeprecated( __METHOD__, '1.24' );
+               $hash = self::getPasswordFactory()->newFromPlaintext( $password );
+               return $hash->toString();
        }
 
        /**
@@ -4632,26 +4650,24 @@ class User implements IDBAccessObject {
         * @param string|bool $userId User ID for old-style password salt
         *
         * @return bool
+        * @deprecated since 1.24, use Password class
         */
        public static function comparePasswords( $hash, $password, $userId = false ) {
-               $type = substr( $hash, 0, 3 );
-
-               $result = false;
-               if ( !wfRunHooks( 'UserComparePasswords', array( &$hash, &$password, &$userId, &$result ) ) ) {
-                       return $result;
+               wfDeprecated( __METHOD__, '1.24' );
+
+               // Check for *really* old password hashes that don't even have a type
+               // The old hash format was just an md5 hex hash, with no type information
+               if ( preg_match( '/^[0-9a-f]{32}$/', $hash ) ) {
+                       global $wgPasswordSalt;
+                       if ( $wgPasswordSalt ) {
+                               $password = ":B:{$userId}:{$hash}";
+                       } else {
+                               $password = ":A:{$hash}";
+                       }
                }
 
-               if ( $type == ':A:' ) {
-                       // Unsalted
-                       return md5( $password ) === substr( $hash, 3 );
-               } elseif ( $type == ':B:' ) {
-                       // Salted
-                       list( $salt, $realHash ) = explode( ':', substr( $hash, 3 ), 2 );
-                       return md5( $salt . '-' . md5( $password ) ) === $realHash;
-               } else {
-                       // Old-style
-                       return self::oldCrypt( $password, $userId ) === $hash;
-               }
+               $hash = self::getPasswordFactory()->newFromCiphertext( $hash );
+               return $hash->equals( $password );
        }
 
        /**
@@ -4855,6 +4871,20 @@ class User implements IDBAccessObject {
                $dbw->insert( 'user_properties', $insert_rows, __METHOD__, array( 'IGNORE' ) );
        }
 
+       /**
+        * Lazily instantiate and return a factory object for making passwords
+        *
+        * @return PasswordFactory
+        */
+       public static function getPasswordFactory() {
+               if ( self::$mPasswordFactory === null ) {
+                       self::$mPasswordFactory = new PasswordFactory();
+                       self::$mPasswordFactory->init( RequestContext::getMain()->getConfig() );
+               }
+
+               return self::$mPasswordFactory;
+       }
+
        /**
         * Provide an array of HTML5 attributes to put on an input element
         * intended for the user to enter a new password.  This may include
@@ -4923,16 +4953,12 @@ class User implements IDBAccessObject {
                        'user_id',
                        'user_name',
                        'user_real_name',
-                       'user_password',
-                       'user_newpassword',
-                       'user_newpass_time',
                        'user_email',
                        'user_touched',
                        'user_token',
                        'user_email_authenticated',
                        'user_email_token',
                        'user_email_token_expires',
-                       'user_password_expires',
                        'user_registration',
                        'user_editcount',
                );
index dd67acd..fb533d0 100644 (file)
@@ -27,7 +27,7 @@ class UserArrayFromResult extends UserArray implements Countable {
        /** @var int */
        public $key;
 
-       /** @var  */
+       /** @var bool|stdClass */
        public $current;
 
        /**
diff --git a/includes/UserMailer.php b/includes/UserMailer.php
deleted file mode 100644 (file)
index d73f6b4..0000000
+++ /dev/null
@@ -1,936 +0,0 @@
-<?php
-/**
- * Classes used to send e-mails
- *
- * 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 <brion@pobox.com>
- * @author <mail@tgries.de>
- * @author Tim Starling
- * @author Luke Welling lwelling@wikimedia.org
- */
-
-/**
- * Stores a single person's name and email address.
- * These are passed in via the constructor, and will be returned in SMTP
- * header format when requested.
- */
-class MailAddress {
-       /**
-        * @param string|User $address String with an email address, or a User object
-        * @param string $name Human-readable name if a string address is given
-        * @param string $realName Human-readable real name if a string address is given
-        */
-       function __construct( $address, $name = null, $realName = null ) {
-               if ( is_object( $address ) && $address instanceof User ) {
-                       $this->address = $address->getEmail();
-                       $this->name = $address->getName();
-                       $this->realName = $address->getRealName();
-               } else {
-                       $this->address = strval( $address );
-                       $this->name = strval( $name );
-                       $this->realName = strval( $realName );
-               }
-       }
-
-       /**
-        * Return formatted and quoted address to insert into SMTP headers
-        * @return string
-        */
-       function toString() {
-               # PHP's mail() implementation under Windows is somewhat shite, and
-               # can't handle "Joe Bloggs <joe@bloggs.com>" format email addresses,
-               # so don't bother generating them
-               if ( $this->address ) {
-                       if ( $this->name != '' && !wfIsWindows() ) {
-                               global $wgEnotifUseRealName;
-                               $name = ( $wgEnotifUseRealName && $this->realName !== '' ) ? $this->realName : $this->name;
-                               $quoted = UserMailer::quotedPrintable( $name );
-                               if ( strpos( $quoted, '.' ) !== false || strpos( $quoted, ',' ) !== false ) {
-                                       $quoted = '"' . $quoted . '"';
-                               }
-                               return "$quoted <{$this->address}>";
-                       } else {
-                               return $this->address;
-                       }
-               } else {
-                       return "";
-               }
-       }
-
-       function __toString() {
-               return $this->toString();
-       }
-}
-
-/**
- * Collection of static functions for sending mail
- */
-class UserMailer {
-       private static $mErrorString;
-
-       /**
-        * Send mail using a PEAR mailer
-        *
-        * @param UserMailer $mailer
-        * @param string $dest
-        * @param string $headers
-        * @param string $body
-        *
-        * @return Status
-        */
-       protected static function sendWithPear( $mailer, $dest, $headers, $body ) {
-               $mailResult = $mailer->send( $dest, $headers, $body );
-
-               # Based on the result return an error string,
-               if ( PEAR::isError( $mailResult ) ) {
-                       wfDebug( "PEAR::Mail failed: " . $mailResult->getMessage() . "\n" );
-                       return Status::newFatal( 'pear-mail-error', $mailResult->getMessage() );
-               } else {
-                       return Status::newGood();
-               }
-       }
-
-       /**
-        * Creates a single string from an associative array
-        *
-        * @param array $headers Associative Array: keys are header field names,
-        *                 values are ... values.
-        * @param string $endl The end of line character.  Defaults to "\n"
-        *
-        * Note RFC2822 says newlines must be CRLF (\r\n)
-        * but php mail naively "corrects" it and requires \n for the "correction" to work
-        *
-        * @return string
-        */
-       static function arrayToHeaderString( $headers, $endl = "\n" ) {
-               $strings = array();
-               foreach ( $headers as $name => $value ) {
-                       // Prevent header injection by stripping newlines from value
-                       $value = self::sanitizeHeaderValue( $value );
-                       $strings[] = "$name: $value";
-               }
-               return implode( $endl, $strings );
-       }
-
-       /**
-        * Create a value suitable for the MessageId Header
-        *
-        * @return string
-        */
-       static function makeMsgId() {
-               global $wgSMTP, $wgServer;
-
-               $msgid = uniqid( wfWikiID() . ".", true ); /* true required for cygwin */
-               if ( is_array( $wgSMTP ) && isset( $wgSMTP['IDHost'] ) && $wgSMTP['IDHost'] ) {
-                       $domain = $wgSMTP['IDHost'];
-               } else {
-                       $url = wfParseUrl( $wgServer );
-                       $domain = $url['host'];
-               }
-               return "<$msgid@$domain>";
-       }
-
-       /**
-        * This function will perform a direct (authenticated) login to
-        * a SMTP Server to use for mail relaying if 'wgSMTP' specifies an
-        * array of parameters. It requires PEAR:Mail to do that.
-        * Otherwise it just uses the standard PHP 'mail' function.
-        *
-        * @param MailAddress $to Recipient's email (or an array of them)
-        * @param MailAddress $from Sender's email
-        * @param string $subject Email's subject.
-        * @param string $body Email's text or Array of two strings to be the text and html bodies
-        * @param MailAddress $replyto Optional reply-to email (default: null).
-        * @param string $contentType Optional custom Content-Type (default: text/plain; charset=UTF-8)
-        * @throws MWException
-        * @return Status
-        */
-       public static function send( $to, $from, $subject, $body, $replyto = null,
-               $contentType = 'text/plain; charset=UTF-8'
-       ) {
-               global $wgSMTP, $wgEnotifMaxRecips, $wgAdditionalMailParams, $wgAllowHTMLEmail;
-               $mime = null;
-               if ( !is_array( $to ) ) {
-                       $to = array( $to );
-               }
-
-               // mail body must have some content
-               $minBodyLen = 10;
-               // arbitrary but longer than Array or Object to detect casting error
-
-               // body must either be a string or an array with text and body
-               if (
-                       !(
-                               !is_array( $body ) &&
-                               strlen( $body ) >= $minBodyLen
-                       )
-                       &&
-                       !(
-                               is_array( $body ) &&
-                               isset( $body['text'] ) &&
-                               isset( $body['html'] ) &&
-                               strlen( $body['text'] ) >= $minBodyLen &&
-                               strlen( $body['html'] ) >= $minBodyLen
-                       )
-               ) {
-                       // if it is neither we have a problem
-                       return Status::newFatal( 'user-mail-no-body' );
-               }
-
-               if ( !$wgAllowHTMLEmail && is_array( $body ) ) {
-                       // HTML not wanted.  Dump it.
-                       $body = $body['text'];
-               }
-
-               wfDebug( __METHOD__ . ': sending mail to ' . implode( ', ', $to ) . "\n" );
-
-               # Make sure we have at least one address
-               $has_address = false;
-               foreach ( $to as $u ) {
-                       if ( $u->address ) {
-                               $has_address = true;
-                               break;
-                       }
-               }
-               if ( !$has_address ) {
-                       return Status::newFatal( 'user-mail-no-addy' );
-               }
-
-               # Forge email headers
-               # -------------------
-               #
-               # WARNING
-               #
-               # DO NOT add To: or Subject: headers at this step. They need to be
-               # handled differently depending upon the mailer we are going to use.
-               #
-               # To:
-               #  PHP mail() first argument is the mail receiver. The argument is
-               #  used as a recipient destination and as a To header.
-               #
-               #  PEAR mailer has a recipient argument which is only used to
-               #  send the mail. If no To header is given, PEAR will set it to
-               #  to 'undisclosed-recipients:'.
-               #
-               #  NOTE: To: is for presentation, the actual recipient is specified
-               #  by the mailer using the Rcpt-To: header.
-               #
-               # Subject:
-               #  PHP mail() second argument to pass the subject, passing a Subject
-               #  as an additional header will result in a duplicate header.
-               #
-               #  PEAR mailer should be passed a Subject header.
-               #
-               # -- hashar 20120218
-
-               $headers['From'] = $from->toString();
-               $headers['Return-Path'] = $from->address;
-
-               if ( $replyto ) {
-                       $headers['Reply-To'] = $replyto->toString();
-               }
-
-               $headers['Date'] = MWTimestamp::getLocalInstance()->format( 'r' );
-               $headers['Message-ID'] = self::makeMsgId();
-               $headers['X-Mailer'] = 'MediaWiki mailer';
-
-               # Line endings need to be different on Unix and Windows due to
-               # the bug described at http://trac.wordpress.org/ticket/2603
-               if ( wfIsWindows() ) {
-                       $endl = "\r\n";
-               } else {
-                       $endl = "\n";
-               }
-
-               if ( is_array( $body ) ) {
-                       // we are sending a multipart message
-                       wfDebug( "Assembling multipart mime email\n" );
-                       if ( !stream_resolve_include_path( 'Mail/mime.php' ) ) {
-                               wfDebug( "PEAR Mail_Mime package is not installed. Falling back to text email.\n" );
-                               // remove the html body for text email fall back
-                               $body = $body['text'];
-                       } else {
-                               require_once 'Mail/mime.php';
-                               if ( wfIsWindows() ) {
-                                       $body['text'] = str_replace( "\n", "\r\n", $body['text'] );
-                                       $body['html'] = str_replace( "\n", "\r\n", $body['html'] );
-                               }
-                               $mime = new Mail_mime( array(
-                                       'eol' => $endl,
-                                       'text_charset' => 'UTF-8',
-                                       'html_charset' => 'UTF-8'
-                               ) );
-                               $mime->setTXTBody( $body['text'] );
-                               $mime->setHTMLBody( $body['html'] );
-                               $body = $mime->get(); // must call get() before headers()
-                               $headers = $mime->headers( $headers );
-                       }
-               }
-               if ( $mime === null ) {
-                       // sending text only, either deliberately or as a fallback
-                       if ( wfIsWindows() ) {
-                               $body = str_replace( "\n", "\r\n", $body );
-                       }
-                       $headers['MIME-Version'] = '1.0';
-                       $headers['Content-type'] = ( is_null( $contentType ) ?
-                               'text/plain; charset=UTF-8' : $contentType );
-                       $headers['Content-transfer-encoding'] = '8bit';
-               }
-
-               $ret = wfRunHooks( 'AlternateUserMailer', array( $headers, $to, $from, $subject, $body ) );
-               if ( $ret === false ) {
-                       // the hook implementation will return false to skip regular mail sending
-                       return Status::newGood();
-               } elseif ( $ret !== true ) {
-                       // the hook implementation will return a string to pass an error message
-                       return Status::newFatal( 'php-mail-error', $ret );
-               }
-
-               if ( is_array( $wgSMTP ) ) {
-                       #
-                       # PEAR MAILER
-                       #
-
-                       if ( !stream_resolve_include_path( 'Mail.php' ) ) {
-                               throw new MWException( 'PEAR mail package is not installed' );
-                       }
-                       require_once 'Mail.php';
-
-                       wfSuppressWarnings();
-
-                       // Create the mail object using the Mail::factory method
-                       $mail_object =& Mail::factory( 'smtp', $wgSMTP );
-                       if ( PEAR::isError( $mail_object ) ) {
-                               wfDebug( "PEAR::Mail factory failed: " . $mail_object->getMessage() . "\n" );
-                               wfRestoreWarnings();
-                               return Status::newFatal( 'pear-mail-error', $mail_object->getMessage() );
-                       }
-
-                       wfDebug( "Sending mail via PEAR::Mail\n" );
-
-                       $headers['Subject'] = self::quotedPrintable( $subject );
-
-                       # When sending only to one recipient, shows it its email using To:
-                       if ( count( $to ) == 1 ) {
-                               $headers['To'] = $to[0]->toString();
-                       }
-
-                       # Split jobs since SMTP servers tends to limit the maximum
-                       # number of possible recipients.
-                       $chunks = array_chunk( $to, $wgEnotifMaxRecips );
-                       foreach ( $chunks as $chunk ) {
-                               $status = self::sendWithPear( $mail_object, $chunk, $headers, $body );
-                               # FIXME : some chunks might be sent while others are not!
-                               if ( !$status->isOK() ) {
-                                       wfRestoreWarnings();
-                                       return $status;
-                               }
-                       }
-                       wfRestoreWarnings();
-                       return Status::newGood();
-               } else {
-                       #
-                       # PHP mail()
-                       #
-                       if ( count( $to ) > 1 ) {
-                               $headers['To'] = 'undisclosed-recipients:;';
-                       }
-                       $headers = self::arrayToHeaderString( $headers, $endl );
-
-                       wfDebug( "Sending mail via internal mail() function\n" );
-
-                       self::$mErrorString = '';
-                       $html_errors = ini_get( 'html_errors' );
-                       ini_set( 'html_errors', '0' );
-                       set_error_handler( 'UserMailer::errorHandler' );
-
-                       try {
-                               $safeMode = wfIniGetBool( 'safe_mode' );
-
-                               foreach ( $to as $recip ) {
-                                       if ( $safeMode ) {
-                                               $sent = mail( $recip, self::quotedPrintable( $subject ), $body, $headers );
-                                       } else {
-                                               $sent = mail(
-                                                       $recip,
-                                                       self::quotedPrintable( $subject ),
-                                                       $body,
-                                                       $headers,
-                                                       $wgAdditionalMailParams
-                                               );
-                                       }
-                               }
-                       } catch ( Exception $e ) {
-                               restore_error_handler();
-                               throw $e;
-                       }
-
-                       restore_error_handler();
-                       ini_set( 'html_errors', $html_errors );
-
-                       if ( self::$mErrorString ) {
-                               wfDebug( "Error sending mail: " . self::$mErrorString . "\n" );
-                               return Status::newFatal( 'php-mail-error', self::$mErrorString );
-                       } elseif ( ! $sent ) {
-                               // mail function only tells if there's an error
-                               wfDebug( "Unknown error sending mail\n" );
-                               return Status::newFatal( 'php-mail-error-unknown' );
-                       } else {
-                               return Status::newGood();
-                       }
-               }
-       }
-
-       /**
-        * Set the mail error message in self::$mErrorString
-        *
-        * @param int $code Error number
-        * @param string $string Error message
-        */
-       static function errorHandler( $code, $string ) {
-               self::$mErrorString = preg_replace( '/^mail\(\)(\s*\[.*?\])?: /', '', $string );
-       }
-
-       /**
-        * Strips bad characters from a header value to prevent PHP mail header injection attacks
-        * @param string $val String to be santizied
-        * @return string
-        */
-       public static function sanitizeHeaderValue( $val ) {
-               return strtr( $val, array( "\r" => '', "\n" => '' ) );
-       }
-
-       /**
-        * Converts a string into a valid RFC 822 "phrase", such as is used for the sender name
-        * @param string $phrase
-        * @return string
-        */
-       public static function rfc822Phrase( $phrase ) {
-               // Remove line breaks
-               $phrase = self::sanitizeHeaderValue( $phrase );
-               // Remove quotes
-               $phrase = str_replace( '"', '', $phrase );
-               return '"' . $phrase . '"';
-       }
-
-       /**
-        * Converts a string into quoted-printable format
-        * @since 1.17
-        *
-        * From PHP5.3 there is a built in function quoted_printable_encode()
-        * This method does not duplicate that.
-        * This method is doing Q encoding inside encoded-words as defined by RFC 2047
-        * This is for email headers.
-        * The built in quoted_printable_encode() is for email bodies
-        * @return string
-        */
-       public static function quotedPrintable( $string, $charset = '' ) {
-               # Probably incomplete; see RFC 2045
-               if ( empty( $charset ) ) {
-                       $charset = 'UTF-8';
-               }
-               $charset = strtoupper( $charset );
-               $charset = str_replace( 'ISO-8859', 'ISO8859', $charset ); // ?
-
-               $illegal = '\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\xff=';
-               $replace = $illegal . '\t ?_';
-               if ( !preg_match( "/[$illegal]/", $string ) ) {
-                       return $string;
-               }
-               $out = "=?$charset?Q?";
-               $out .= preg_replace_callback( "/([$replace])/",
-                       array( __CLASS__, 'quotedPrintableCallback' ), $string );
-               $out .= '?=';
-               return $out;
-       }
-
-       protected static function quotedPrintableCallback( $matches ) {
-               return sprintf( "=%02X", ord( $matches[1] ) );
-       }
-}
-
-/**
- * This module processes the email notifications when the current page is
- * changed. It looks up the table watchlist to find out which users are watching
- * that page.
- *
- * The current implementation sends independent emails to each watching user for
- * the following reason:
- *
- * - Each watching user will be notified about the page edit time expressed in
- * his/her local time (UTC is shown additionally). To achieve this, we need to
- * find the individual timeoffset of each watching user from the preferences..
- *
- * Suggested improvement to slack down the number of sent emails: We could think
- * of sending out bulk mails (bcc:user1,user2...) for all these users having the
- * same timeoffset in their preferences.
- *
- * Visit the documentation pages under http://meta.wikipedia.com/Enotif
- *
- *
- */
-class EmailNotification {
-       protected $subject, $body, $replyto, $from;
-       protected $timestamp, $summary, $minorEdit, $oldid, $composed_common, $pageStatus;
-       protected $mailTargets = array();
-
-       /**
-        * @var Title
-        */
-       protected $title;
-
-       /**
-        * @var User
-        */
-       protected $editor;
-
-       /**
-        * Send emails corresponding to the user $editor editing the page $title.
-        * Also updates wl_notificationtimestamp.
-        *
-        * May be deferred via the job queue.
-        *
-        * @param User $editor
-        * @param Title $title
-        * @param string $timestamp
-        * @param string $summary
-        * @param bool $minorEdit
-        * @param bool $oldid (default: false)
-        * @param string $pageStatus (default: 'changed')
-        */
-       public function notifyOnPageChange( $editor, $title, $timestamp, $summary,
-               $minorEdit, $oldid = false, $pageStatus = 'changed'
-       ) {
-               global $wgEnotifUseJobQ, $wgEnotifWatchlist, $wgShowUpdatedMarker, $wgEnotifMinorEdits,
-                       $wgUsersNotifiedOnAllChanges, $wgEnotifUserTalk;
-
-               if ( $title->getNamespace() < 0 ) {
-                       return;
-               }
-
-               // Build a list of users to notify
-               $watchers = array();
-               if ( $wgEnotifWatchlist || $wgShowUpdatedMarker ) {
-                       $dbw = wfGetDB( DB_MASTER );
-                       $res = $dbw->select( array( 'watchlist' ),
-                               array( 'wl_user' ),
-                               array(
-                                       'wl_user != ' . intval( $editor->getID() ),
-                                       'wl_namespace' => $title->getNamespace(),
-                                       'wl_title' => $title->getDBkey(),
-                                       'wl_notificationtimestamp IS NULL',
-                               ), __METHOD__
-                       );
-                       foreach ( $res as $row ) {
-                               $watchers[] = intval( $row->wl_user );
-                       }
-                       if ( $watchers ) {
-                               // Update wl_notificationtimestamp for all watching users except the editor
-                               $fname = __METHOD__;
-                               $dbw->onTransactionIdle(
-                                       function() use ( $dbw, $timestamp, $watchers, $title, $fname ) {
-                                               $dbw->update( 'watchlist',
-                                                       array( /* SET */
-                                                               'wl_notificationtimestamp' => $dbw->timestamp( $timestamp )
-                                                       ), array( /* WHERE */
-                                                               'wl_user' => $watchers,
-                                                               'wl_namespace' => $title->getNamespace(),
-                                                               'wl_title' => $title->getDBkey(),
-                                                       ), $fname
-                                               );
-                                       }
-                               );
-                       }
-               }
-
-               $sendEmail = true;
-               // If nobody is watching the page, and there are no users notified on all changes
-               // don't bother creating a job/trying to send emails
-               // $watchers deals with $wgEnotifWatchlist
-               if ( !count( $watchers ) && !count( $wgUsersNotifiedOnAllChanges ) ) {
-                       $sendEmail = false;
-                       // Only send notification for non minor edits, unless $wgEnotifMinorEdits
-                       if ( !$minorEdit || ( $wgEnotifMinorEdits && !$editor->isAllowed( 'nominornewtalk' ) ) ) {
-                               $isUserTalkPage = ( $title->getNamespace() == NS_USER_TALK );
-                               if ( $wgEnotifUserTalk
-                                       && $isUserTalkPage
-                                       && $this->canSendUserTalkEmail( $editor, $title, $minorEdit )
-                               ) {
-                                       $sendEmail = true;
-                               }
-                       }
-               }
-
-               if ( !$sendEmail ) {
-                       return;
-               }
-
-               if ( $wgEnotifUseJobQ ) {
-                       $params = array(
-                               'editor' => $editor->getName(),
-                               'editorID' => $editor->getID(),
-                               'timestamp' => $timestamp,
-                               'summary' => $summary,
-                               'minorEdit' => $minorEdit,
-                               'oldid' => $oldid,
-                               'watchers' => $watchers,
-                               'pageStatus' => $pageStatus
-                       );
-                       $job = new EnotifNotifyJob( $title, $params );
-                       JobQueueGroup::singleton()->push( $job );
-               } else {
-                       $this->actuallyNotifyOnPageChange(
-                               $editor,
-                               $title,
-                               $timestamp,
-                               $summary,
-                               $minorEdit,
-                               $oldid,
-                               $watchers,
-                               $pageStatus
-                       );
-               }
-       }
-
-       /**
-        * Immediate version of notifyOnPageChange().
-        *
-        * Send emails corresponding to the user $editor editing the page $title.
-        * Also updates wl_notificationtimestamp.
-        *
-        * @param User $editor
-        * @param Title $title
-        * @param string $timestamp Edit timestamp
-        * @param string $summary Edit summary
-        * @param bool $minorEdit
-        * @param int $oldid Revision ID
-        * @param array $watchers Array of user IDs
-        * @param string $pageStatus
-        * @throws MWException
-        */
-       public function actuallyNotifyOnPageChange( $editor, $title, $timestamp, $summary, $minorEdit,
-               $oldid, $watchers, $pageStatus = 'changed' ) {
-               # we use $wgPasswordSender as sender's address
-               global $wgEnotifWatchlist;
-               global $wgEnotifMinorEdits, $wgEnotifUserTalk;
-
-               wfProfileIn( __METHOD__ );
-
-               # The following code is only run, if several conditions are met:
-               # 1. EmailNotification for pages (other than user_talk pages) must be enabled
-               # 2. minor edits (changes) are only regarded if the global flag indicates so
-
-               $isUserTalkPage = ( $title->getNamespace() == NS_USER_TALK );
-
-               $this->title = $title;
-               $this->timestamp = $timestamp;
-               $this->summary = $summary;
-               $this->minorEdit = $minorEdit;
-               $this->oldid = $oldid;
-               $this->editor = $editor;
-               $this->composed_common = false;
-               $this->pageStatus = $pageStatus;
-
-               $formattedPageStatus = array( 'deleted', 'created', 'moved', 'restored', 'changed' );
-
-               wfRunHooks( 'UpdateUserMailerFormattedPageStatus', array( &$formattedPageStatus ) );
-               if ( !in_array( $this->pageStatus, $formattedPageStatus ) ) {
-                       wfProfileOut( __METHOD__ );
-                       throw new MWException( 'Not a valid page status!' );
-               }
-
-               $userTalkId = false;
-
-               if ( !$minorEdit || ( $wgEnotifMinorEdits && !$editor->isAllowed( 'nominornewtalk' ) ) ) {
-                       if ( $wgEnotifUserTalk
-                               && $isUserTalkPage
-                               && $this->canSendUserTalkEmail( $editor, $title, $minorEdit )
-                       ) {
-                               $targetUser = User::newFromName( $title->getText() );
-                               $this->compose( $targetUser );
-                               $userTalkId = $targetUser->getId();
-                       }
-
-                       if ( $wgEnotifWatchlist ) {
-                               // Send updates to watchers other than the current editor
-                               $userArray = UserArray::newFromIDs( $watchers );
-                               foreach ( $userArray as $watchingUser ) {
-                                       if ( $watchingUser->getOption( 'enotifwatchlistpages' )
-                                               && ( !$minorEdit || $watchingUser->getOption( 'enotifminoredits' ) )
-                                               && $watchingUser->isEmailConfirmed()
-                                               && $watchingUser->getID() != $userTalkId
-                                       ) {
-                                               if ( wfRunHooks( 'SendWatchlistEmailNotification', array( $watchingUser, $title, $this ) ) ) {
-                                                       $this->compose( $watchingUser );
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               global $wgUsersNotifiedOnAllChanges;
-               foreach ( $wgUsersNotifiedOnAllChanges as $name ) {
-                       if ( $editor->getName() == $name ) {
-                               // No point notifying the user that actually made the change!
-                               continue;
-                       }
-                       $user = User::newFromName( $name );
-                       $this->compose( $user );
-               }
-
-               $this->sendMails();
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * @param User $editor
-        * @param Title $title
-        * @param bool $minorEdit
-        * @return bool
-        */
-       private function canSendUserTalkEmail( $editor, $title, $minorEdit ) {
-               global $wgEnotifUserTalk;
-               $isUserTalkPage = ( $title->getNamespace() == NS_USER_TALK );
-
-               if ( $wgEnotifUserTalk && $isUserTalkPage ) {
-                       $targetUser = User::newFromName( $title->getText() );
-
-                       if ( !$targetUser || $targetUser->isAnon() ) {
-                               wfDebug( __METHOD__ . ": user talk page edited, but user does not exist\n" );
-                       } elseif ( $targetUser->getId() == $editor->getId() ) {
-                               wfDebug( __METHOD__ . ": user edited their own talk page, no notification sent\n" );
-                       } elseif ( $targetUser->getOption( 'enotifusertalkpages' )
-                               && ( !$minorEdit || $targetUser->getOption( 'enotifminoredits' ) )
-                       ) {
-                               if ( !$targetUser->isEmailConfirmed() ) {
-                                       wfDebug( __METHOD__ . ": talk page owner doesn't have validated email\n" );
-                               } elseif ( !wfRunHooks( 'AbortTalkPageEmailNotification', array( $targetUser, $title ) ) ) {
-                                       wfDebug( __METHOD__ . ": talk page update notification is aborted for this user\n" );
-                               } else {
-                                       wfDebug( __METHOD__ . ": sending talk page update notification\n" );
-                                       return true;
-                               }
-                       } else {
-                               wfDebug( __METHOD__ . ": talk page owner doesn't want notifications\n" );
-                       }
-               }
-               return false;
-       }
-
-       /**
-        * Generate the generic "this page has been changed" e-mail text.
-        */
-       private function composeCommonMailtext() {
-               global $wgPasswordSender, $wgNoReplyAddress;
-               global $wgEnotifFromEditor, $wgEnotifRevealEditorAddress;
-               global $wgEnotifImpersonal, $wgEnotifUseRealName;
-
-               $this->composed_common = true;
-
-               # You as the WikiAdmin and Sysops can make use of plenty of
-               # named variables when composing your notification emails while
-               # simply editing the Meta pages
-
-               $keys = array();
-               $postTransformKeys = array();
-               $pageTitleUrl = $this->title->getCanonicalURL();
-               $pageTitle = $this->title->getPrefixedText();
-
-               if ( $this->oldid ) {
-                       // Always show a link to the diff which triggered the mail. See bug 32210.
-                       $keys['$NEWPAGE'] = "\n\n" . wfMessage( 'enotif_lastdiff',
-                               $this->title->getCanonicalURL( array( 'diff' => 'next', 'oldid' => $this->oldid ) ) )
-                               ->inContentLanguage()->text();
-
-                       if ( !$wgEnotifImpersonal ) {
-                               // For personal mail, also show a link to the diff of all changes
-                               // since last visited.
-                               $keys['$NEWPAGE'] .= "\n\n" . wfMessage( 'enotif_lastvisited',
-                                       $this->title->getCanonicalURL( array( 'diff' => '0', 'oldid' => $this->oldid ) ) )
-                                       ->inContentLanguage()->text();
-                       }
-                       $keys['$OLDID'] = $this->oldid;
-                       // Deprecated since MediaWiki 1.21, not used by default. Kept for backwards-compatibility.
-                       $keys['$CHANGEDORCREATED'] = wfMessage( 'changed' )->inContentLanguage()->text();
-               } else {
-                       # clear $OLDID placeholder in the message template
-                       $keys['$OLDID'] = '';
-                       $keys['$NEWPAGE'] = '';
-                       // Deprecated since MediaWiki 1.21, not used by default. Kept for backwards-compatibility.
-                       $keys['$CHANGEDORCREATED'] = wfMessage( 'created' )->inContentLanguage()->text();
-               }
-
-               $keys['$PAGETITLE'] = $this->title->getPrefixedText();
-               $keys['$PAGETITLE_URL'] = $this->title->getCanonicalURL();
-               $keys['$PAGEMINOREDIT'] = $this->minorEdit ?
-                       wfMessage( 'minoredit' )->inContentLanguage()->text() : '';
-               $keys['$UNWATCHURL'] = $this->title->getCanonicalURL( 'action=unwatch' );
-
-               if ( $this->editor->isAnon() ) {
-                       # real anon (user:xxx.xxx.xxx.xxx)
-                       $keys['$PAGEEDITOR'] = wfMessage( 'enotif_anon_editor', $this->editor->getName() )
-                               ->inContentLanguage()->text();
-                       $keys['$PAGEEDITOR_EMAIL'] = wfMessage( 'noemailtitle' )->inContentLanguage()->text();
-
-               } else {
-                       $keys['$PAGEEDITOR'] = $wgEnotifUseRealName && $this->editor->getRealName() !== ''
-                               ? $this->editor->getRealName() : $this->editor->getName();
-                       $emailPage = SpecialPage::getSafeTitleFor( 'Emailuser', $this->editor->getName() );
-                       $keys['$PAGEEDITOR_EMAIL'] = $emailPage->getCanonicalURL();
-               }
-
-               $keys['$PAGEEDITOR_WIKI'] = $this->editor->getUserPage()->getCanonicalURL();
-               $keys['$HELPPAGE'] = wfExpandUrl(
-                       Skin::makeInternalOrExternalUrl( wfMessage( 'helppage' )->inContentLanguage()->text() )
-               );
-
-               # Replace this after transforming the message, bug 35019
-               $postTransformKeys['$PAGESUMMARY'] = $this->summary == '' ? ' - ' : $this->summary;
-
-               // Now build message's subject and body
-
-               // Messages:
-               // enotif_subject_deleted, enotif_subject_created, enotif_subject_moved,
-               // enotif_subject_restored, enotif_subject_changed
-               $this->subject = wfMessage( 'enotif_subject_' . $this->pageStatus )->inContentLanguage()
-                       ->params( $pageTitle, $keys['$PAGEEDITOR'] )->text();
-
-               // Messages:
-               // enotif_body_intro_deleted, enotif_body_intro_created, enotif_body_intro_moved,
-               // enotif_body_intro_restored, enotif_body_intro_changed
-               $keys['$PAGEINTRO'] = wfMessage( 'enotif_body_intro_' . $this->pageStatus )
-                       ->inContentLanguage()->params( $pageTitle, $keys['$PAGEEDITOR'], $pageTitleUrl )
-                       ->text();
-
-               $body = wfMessage( 'enotif_body' )->inContentLanguage()->plain();
-               $body = strtr( $body, $keys );
-               $body = MessageCache::singleton()->transform( $body, false, null, $this->title );
-               $this->body = wordwrap( strtr( $body, $postTransformKeys ), 72 );
-
-               # Reveal the page editor's address as REPLY-TO address only if
-               # the user has not opted-out and the option is enabled at the
-               # global configuration level.
-               $adminAddress = new MailAddress( $wgPasswordSender,
-                       wfMessage( 'emailsender' )->inContentLanguage()->text() );
-               if ( $wgEnotifRevealEditorAddress
-                       && ( $this->editor->getEmail() != '' )
-                       && $this->editor->getOption( 'enotifrevealaddr' )
-               ) {
-                       $editorAddress = new MailAddress( $this->editor );
-                       if ( $wgEnotifFromEditor ) {
-                               $this->from = $editorAddress;
-                       } else {
-                               $this->from = $adminAddress;
-                               $this->replyto = $editorAddress;
-                       }
-               } else {
-                       $this->from = $adminAddress;
-                       $this->replyto = new MailAddress( $wgNoReplyAddress );
-               }
-       }
-
-       /**
-        * Compose a mail to a given user and either queue it for sending, or send it now,
-        * depending on settings.
-        *
-        * Call sendMails() to send any mails that were queued.
-        * @param User $user
-        */
-       function compose( $user ) {
-               global $wgEnotifImpersonal;
-
-               if ( !$this->composed_common ) {
-                       $this->composeCommonMailtext();
-               }
-
-               if ( $wgEnotifImpersonal ) {
-                       $this->mailTargets[] = new MailAddress( $user );
-               } else {
-                       $this->sendPersonalised( $user );
-               }
-       }
-
-       /**
-        * Send any queued mails
-        */
-       function sendMails() {
-               global $wgEnotifImpersonal;
-               if ( $wgEnotifImpersonal ) {
-                       $this->sendImpersonal( $this->mailTargets );
-               }
-       }
-
-       /**
-        * Does the per-user customizations to a notification e-mail (name,
-        * timestamp in proper timezone, etc) and sends it out.
-        * Returns true if the mail was sent successfully.
-        *
-        * @param User $watchingUser
-        * @return bool
-        * @private
-        */
-       function sendPersonalised( $watchingUser ) {
-               global $wgContLang, $wgEnotifUseRealName;
-               // From the PHP manual:
-               //   Note: The to parameter cannot be an address in the form of
-               //   "Something <someone@example.com>". The mail command will not parse
-               //   this properly while talking with the MTA.
-               $to = new MailAddress( $watchingUser );
-
-               # $PAGEEDITDATE is the time and date of the page change
-               # expressed in terms of individual local time of the notification
-               # recipient, i.e. watching user
-               $body = str_replace(
-                       array( '$WATCHINGUSERNAME',
-                               '$PAGEEDITDATE',
-                               '$PAGEEDITTIME' ),
-                       array( $wgEnotifUseRealName && $watchingUser->getRealName() !== ''
-                                       ? $watchingUser->getRealName() : $watchingUser->getName(),
-                               $wgContLang->userDate( $this->timestamp, $watchingUser ),
-                               $wgContLang->userTime( $this->timestamp, $watchingUser ) ),
-                       $this->body );
-
-               return UserMailer::send( $to, $this->from, $this->subject, $body, $this->replyto );
-       }
-
-       /**
-        * Same as sendPersonalised but does impersonal mail suitable for bulk
-        * mailing.  Takes an array of MailAddress objects.
-        * @param MailAddress[] $addresses
-        * @return Status|null
-        */
-       function sendImpersonal( $addresses ) {
-               global $wgContLang;
-
-               if ( empty( $addresses ) ) {
-                       return null;
-               }
-
-               $body = str_replace(
-                               array( '$WATCHINGUSERNAME',
-                                       '$PAGEEDITDATE',
-                                       '$PAGEEDITTIME' ),
-                               array( wfMessage( 'enotif_impersonal_salutation' )->inContentLanguage()->text(),
-                                       $wgContLang->date( $this->timestamp, false, false ),
-                                       $wgContLang->time( $this->timestamp, false, false ) ),
-                               $this->body );
-
-               return UserMailer::send( $addresses, $this->from, $this->subject, $body, $this->replyto );
-       }
-
-} # end of class EmailNotification
index e3655ce..53c69d8 100644 (file)
@@ -113,12 +113,23 @@ class UserRightsProxy {
         * @return null|UserRightsProxy
         */
        private static function newFromLookup( $database, $field, $value, $ignoreInvalidDB = false ) {
+               global $wgSharedDB, $wgSharedTables;
+               // If the user table is shared, perform the user query on it, but don't pass it to the UserRightsProxy,
+               // as user rights are normally not shared.
+               if ( $wgSharedDB && in_array( 'user', $wgSharedTables ) ) {
+                       $userdb = self::getDB( $wgSharedDB, $ignoreInvalidDB );
+               } else {
+                       $userdb = self::getDB( $database, $ignoreInvalidDB );
+               }
+
                $db = self::getDB( $database, $ignoreInvalidDB );
-               if ( $db ) {
-                       $row = $db->selectRow( 'user',
+
+               if ( $db && $userdb ) {
+                       $row = $userdb->selectRow( 'user',
                                array( 'user_id', 'user_name' ),
                                array( $field => $value ),
                                __METHOD__ );
+
                        if ( $row !== false ) {
                                return new UserRightsProxy( $db, $database,
                                        $row->user_name,
index f69fe63..ab136b8 100644 (file)
@@ -164,6 +164,7 @@ class WatchedItem {
        /**
         * Check permissions
         * @param string $what 'viewmywatchlist' or 'editmywatchlist'
+        * @return bool
         */
        private function isAllowed( $what ) {
                return !$this->mCheckRights || $this->mUser->isAllowed( $what );
@@ -270,45 +271,61 @@ class WatchedItem {
        }
 
        /**
-        * Given a title and user (assumes the object is setup), add the watch to the database.
+        * @param WatchedItem[] $items
         * @return bool
         */
-       public function addWatch() {
-               wfProfileIn( __METHOD__ );
+       public static function batchAddWatch( array $items ) {
+               $section = new ProfileSection( __METHOD__ );
 
-               // Only loggedin user can have a watchlist
-               if ( wfReadOnly() || $this->mUser->isAnon() || !$this->isAllowed( 'editmywatchlist' ) ) {
-                       wfProfileOut( __METHOD__ );
+               if ( wfReadOnly() ) {
                        return false;
                }
 
-               // Use INSERT IGNORE to avoid overwriting the notification timestamp
-               // if there's already an entry for this page
-               $dbw = wfGetDB( DB_MASTER );
-               $dbw->insert( 'watchlist',
-                       array(
-                               'wl_user' => $this->getUserId(),
-                               'wl_namespace' => MWNamespace::getSubject( $this->getTitleNs() ),
-                               'wl_title' => $this->getTitleDBkey(),
+               $rows = array();
+               foreach ( $items as $item ) {
+                       // Only loggedin user can have a watchlist
+                       if ( $item->mUser->isAnon() || !$item->isAllowed( 'editmywatchlist' ) ) {
+                               continue;
+                       }
+                       $rows[] = array(
+                               'wl_user' => $item->getUserId(),
+                               'wl_namespace' => MWNamespace::getSubject( $item->getTitleNs() ),
+                               'wl_title' => $item->getTitleDBkey(),
+                               'wl_notificationtimestamp' => null,
+                       );
+                       // Every single watched page needs now to be listed in watchlist;
+                       // namespace:page and namespace_talk:page need separate entries:
+                       $rows[] = array(
+                               'wl_user' => $item->getUserId(),
+                               'wl_namespace' => MWNamespace::getTalk( $item->getTitleNs() ),
+                               'wl_title' => $item->getTitleDBkey(),
                                'wl_notificationtimestamp' => null
-                       ), __METHOD__, 'IGNORE' );
+                       );
+                       $item->watched = true;
+               }
 
-               // Every single watched page needs now to be listed in watchlist;
-               // namespace:page and namespace_talk:page need separate entries:
-               $dbw->insert( 'watchlist',
-                       array(
-                               'wl_user' => $this->getUserId(),
-                               'wl_namespace' => MWNamespace::getTalk( $this->getTitleNs() ),
-                               'wl_title' => $this->getTitleDBkey(),
-                               'wl_notificationtimestamp' => null
-                       ), __METHOD__, 'IGNORE' );
+               if ( !$rows ) {
+                       return false;
+               }
 
-               $this->watched = true;
+               $dbw = wfGetDB( 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' );
+               }
 
-               wfProfileOut( __METHOD__ );
                return true;
        }
 
+       /**
+        * Given a title and user (assumes the object is setup), add the watch to the database.
+        * @return bool
+        */
+       public function addWatch() {
+               return self::batchAddWatch( array( $this ) );
+       }
+
        /**
         * Same as addWatch, only the opposite.
         * @return bool
index ce9fecd..b187c4a 100644 (file)
@@ -25,8 +25,8 @@
 
 /**
  * The WebRequest class encapsulates getting at data passed in the
- * URL or via a POSTed form, handling remove of "magic quotes" slashes,
- * stripping illegal input characters and normalizing Unicode sequences.
+ * URL or via a POSTed form stripping illegal input characters and
+ * normalizing Unicode sequences.
  *
  * Usually this is used via a global singleton, $wgRequest. You should
  * not create a second WebRequest object; make a FauxRequest object if
@@ -57,10 +57,9 @@ class WebRequest {
        protected $protocol;
 
        public function __construct() {
-               /// @todo FIXME: This preemptive de-quoting can interfere with other web libraries
-               ///        and increases our memory footprint. It would be cleaner to do on
-               ///        demand; but currently we have no wrapper for $_SERVER etc.
-               $this->checkMagicQuotes();
+               if ( function_exists( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc() ) {
+                       throw new MWException( "MediaWiki does not function when magic quotes are enabled." );
+               }
 
                // POST overrides GET data
                // We don't use $_REQUEST here to avoid interference from cookies...
@@ -182,7 +181,12 @@ class WebRequest {
                                continue;
                        }
                        $host = $parts[0];
-                       if ( $parts[1] === false ) {
+                       if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) ) {
+                               // Bug 70021: Assume that upstream proxy is running on the default
+                               // port based on the protocol. We have no reliable way to determine
+                               // the actual port in use upstream.
+                               $port = $stdPort;
+                       } elseif ( $parts[1] === false ) {
                                if ( isset( $_SERVER['SERVER_PORT'] ) ) {
                                        $port = $_SERVER['SERVER_PORT'];
                                } // else leave it as $stdPort
@@ -271,51 +275,6 @@ class WebRequest {
                return array();
        }
 
-       /**
-        * Recursively strips slashes from the given array;
-        * used for undoing the evil that is magic_quotes_gpc.
-        *
-        * @param array $arr will be modified
-        * @param bool $topLevel Specifies if the array passed is from the top
-        * level of the source. In PHP5 magic_quotes only escapes the first level
-        * of keys that belong to an array.
-        * @return array The original array
-        * @see http://www.php.net/manual/en/function.get-magic-quotes-gpc.php#49612
-        */
-       private function &fix_magic_quotes( &$arr, $topLevel = true ) {
-               $clean = array();
-               foreach ( $arr as $key => $val ) {
-                       if ( is_array( $val ) ) {
-                               $cleanKey = $topLevel ? stripslashes( $key ) : $key;
-                               $clean[$cleanKey] = $this->fix_magic_quotes( $arr[$key], false );
-                       } else {
-                               $cleanKey = stripslashes( $key );
-                               $clean[$cleanKey] = stripslashes( $val );
-                       }
-               }
-               $arr = $clean;
-               return $arr;
-       }
-
-       /**
-        * If magic_quotes_gpc option is on, run the global arrays
-        * through fix_magic_quotes to strip out the stupid slashes.
-        * WARNING: This should only be done once! Running a second
-        * time could damage the values.
-        */
-       private function checkMagicQuotes() {
-               $mustFixQuotes = function_exists( 'get_magic_quotes_gpc' )
-                       && get_magic_quotes_gpc();
-               if ( $mustFixQuotes ) {
-                       $this->fix_magic_quotes( $_COOKIE );
-                       $this->fix_magic_quotes( $_ENV );
-                       $this->fix_magic_quotes( $_GET );
-                       $this->fix_magic_quotes( $_POST );
-                       $this->fix_magic_quotes( $_REQUEST );
-                       $this->fix_magic_quotes( $_SERVER );
-               }
-       }
-
        /**
         * Recursively normalizes UTF-8 strings in the given array.
         *
@@ -746,7 +705,7 @@ class WebRequest {
 
        /**
         * Take an arbitrary query and rewrite the present URL to include it
-        * @param string $query query string fragment; do not include initial '?'
+        * @param string $query Query string fragment; do not include initial '?'
         *
         * @return string
         */
@@ -818,7 +777,7 @@ class WebRequest {
         * Return the path to the temporary file where PHP has stored the upload.
         *
         * @param string $key
-        * @return string|null string or null if no such file.
+        * @return string|null String or null if no such file.
         */
        public function getFileTempname( $key ) {
                $file = new WebRequestUpload( $this, $key );
@@ -845,7 +804,7 @@ class WebRequest {
         * Other than this the name is not verified for being a safe filename.
         *
         * @param string $key
-        * @return string|null string or null if no such file.
+        * @return string|null String or null if no such file.
         */
        public function getFileName( $key ) {
                $file = new WebRequestUpload( $this, $key );
@@ -914,7 +873,7 @@ class WebRequest {
 
        /**
         * Get a request header, or false if it isn't set
-        * @param string $name case-insensitive header name
+        * @param string $name Case-insensitive header name
         *
         * @return string|bool False on failure
         */
@@ -1015,7 +974,7 @@ HTML;
        /**
         * Parse the Accept-Language header sent by the client into an array
         *
-        * @return array array( languageCode => q-value ) sorted by q-value in
+        * @return array Array( languageCode => q-value ) sorted by q-value in
         *   descending order then appearing time in the header in ascending order.
         * May contain the "language" '*', which applies to languages other than those explicitly listed.
         * This is aligned with rfc2616 section 14.4
@@ -1298,7 +1257,7 @@ class FauxRequest extends WebRequest {
        private $session = array();
 
        /**
-        * @param array $data of *non*-urlencoded key => value pairs, the
+        * @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 array|null $session Session array or null
index 75efce5..ad9f4e6 100644 (file)
@@ -29,8 +29,8 @@ class WebResponse {
 
        /**
         * Output a HTTP header, wrapper for PHP's header()
-        * @param string $string header to output
-        * @param bool $replace replace current similar header
+        * @param string $string Header to output
+        * @param bool $replace Replace current similar header
         * @param null|int $http_response_code Forces the HTTP response code to the specified value.
         */
        public function header( $string, $replace = true, $http_response_code = null ) {
@@ -39,8 +39,8 @@ class WebResponse {
 
        /**
         * Set the browser cookie
-        * @param string $name name of cookie
-        * @param string $value value to give cookie
+        * @param string $name Name of cookie
+        * @param string $value Value to give cookie
         * @param int|null $expire Unix timestamp (in seconds) when the cookie should expire.
         *        0 (the default) causes it to expire $wgCookieExpiration seconds from now.
         *        null causes it to be a session cookie.
@@ -51,7 +51,7 @@ class WebResponse {
         *     secure: bool, secure attribute ($wgCookieSecure)
         *     httpOnly: bool, httpOnly attribute ($wgCookieHttpOnly)
         *     raw: bool, if true uses PHP's setrawcookie() instead of setcookie()
-        *   For backwards compatability, if $options is not an array then it and
+        *   For backwards compatibility, if $options is not an array then it and
         *   the following two parameters will be interpreted as values for
         *   'prefix', 'domain', and 'secure'
         * @since 1.22 Replaced $prefix, $domain, and $forceSecure with $options
@@ -61,7 +61,7 @@ class WebResponse {
                global $wgCookieSecure, $wgCookieExpiration, $wgCookieHttpOnly;
 
                if ( !is_array( $options ) ) {
-                       // Backwards compatability
+                       // Backwards compatibility
                        $options = array( 'prefix' => $options );
                        if ( func_num_args() >= 5 ) {
                                $options['domain'] = func_get_arg( 4 );
@@ -123,8 +123,8 @@ class FauxResponse extends WebResponse {
 
        /**
         * Stores a HTTP header
-        * @param string $string header to output
-        * @param bool $replace replace current similar header
+        * @param string $string Header to output
+        * @param bool $replace Replace current similar header
         * @param null|int $http_response_code Forces the HTTP response code to the specified value.
         */
        public function header( $string, $replace = true, $http_response_code = null ) {
@@ -171,10 +171,10 @@ class FauxResponse extends WebResponse {
        /**
         * @todo document. It just ignore optional parameters.
         *
-        * @param string $name name of cookie
-        * @param string $value value to give cookie
-        * @param int $expire number of seconds til cookie expires (Default: 0)
-        * @param array $options ignored
+        * @param string $name Name of cookie
+        * @param string $value Value to give cookie
+        * @param int $expire Number of seconds til cookie expires (Default: 0)
+        * @param array $options Ignored
         */
        public function setcookie( $name, $value, $expire = 0, $options = null ) {
                $this->cookies[$name] = $value;
index 71454f0..2ae72dc 100644 (file)
@@ -40,12 +40,6 @@ if ( ini_get( 'register_globals' ) ) {
 header( 'X-Content-Type-Options: nosniff' );
 
 $wgRequestTime = microtime( true );
-# getrusage() does not exist on the Microsoft Windows platforms, catching this
-if ( function_exists ( 'getrusage' ) ) {
-       $wgRUstart = getrusage();
-} else {
-       $wgRUstart = array();
-}
 unset( $IP );
 
 # Valid web server entry point, enable includes.
@@ -61,18 +55,15 @@ define( 'MEDIAWIKI', true );
 # if we don't have permissions on parent directories.
 $IP = getenv( 'MW_INSTALL_PATH' );
 if ( $IP === false ) {
-       if ( realpath( '.' ) ) {
-               $IP = realpath( '.' );
-       } else {
-               $IP = dirname( __DIR__ );
-       }
+       $IP = realpath( '.' ) ?: dirname( __DIR__ );
 }
 
-# Start the autoloader, so that extensions can derive classes from core files
-require_once "$IP/includes/AutoLoader.php";
-
 # Load the profiler
 require_once "$IP/includes/profiler/Profiler.php";
+$wgRUstart = wfGetRusage() ?: array();
+
+# Start the autoloader, so that extensions can derive classes from core files
+require_once "$IP/includes/AutoLoader.php";
 
 # Load up some global defines.
 require_once "$IP/includes/Defines.php";
diff --git a/includes/Wiki.php b/includes/Wiki.php
deleted file mode 100644 (file)
index a8bafa3..0000000
+++ /dev/null
@@ -1,722 +0,0 @@
-<?php
-/**
- * Helper class for the index.php entry point.
- *
- * 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
- */
-
-/**
- * The MediaWiki class is the helper class for the index.php entry point.
- *
- * @internal documentation reviewed 15 Mar 2010
- */
-class MediaWiki {
-       /**
-        * @todo Fold $output, etc, into this
-        * @var IContextSource
-        */
-       private $context;
-
-       /**
-        * @param null|WebRequest $x
-        * @return WebRequest
-        */
-       public function request( WebRequest $x = null ) {
-               $old = $this->context->getRequest();
-               $this->context->setRequest( $x );
-               return $old;
-       }
-
-       /**
-        * @param null|OutputPage $x
-        * @return OutputPage
-        */
-       public function output( OutputPage $x = null ) {
-               $old = $this->context->getOutput();
-               $this->context->setOutput( $x );
-               return $old;
-       }
-
-       /**
-        * @param IContextSource|null $context
-        */
-       public function __construct( IContextSource $context = null ) {
-               if ( !$context ) {
-                       $context = RequestContext::getMain();
-               }
-
-               $this->context = $context;
-       }
-
-       /**
-        * Parse the request to get the Title object
-        *
-        * @return Title Title object to be $wgTitle
-        */
-       private function parseTitle() {
-               global $wgContLang;
-
-               $request = $this->context->getRequest();
-               $curid = $request->getInt( 'curid' );
-               $title = $request->getVal( 'title' );
-               $action = $request->getVal( 'action', 'view' );
-
-               if ( $request->getCheck( 'search' ) ) {
-                       // Compatibility with old search URLs which didn't use Special:Search
-                       // Just check for presence here, so blank requests still
-                       // show the search page when using ugly URLs (bug 8054).
-                       $ret = SpecialPage::getTitleFor( 'Search' );
-               } elseif ( $curid ) {
-                       // URLs like this are generated by RC, because rc_title isn't always accurate
-                       $ret = Title::newFromID( $curid );
-               } else {
-                       $ret = Title::newFromURL( $title );
-                       // Alias NS_MEDIA page URLs to NS_FILE...we only use NS_MEDIA
-                       // in wikitext links to tell Parser to make a direct file link
-                       if ( !is_null( $ret ) && $ret->getNamespace() == NS_MEDIA ) {
-                               $ret = Title::makeTitle( NS_FILE, $ret->getDBkey() );
-                       }
-                       // Check variant links so that interwiki links don't have to worry
-                       // about the possible different language variants
-                       if ( count( $wgContLang->getVariants() ) > 1
-                               && !is_null( $ret ) && $ret->getArticleID() == 0
-                       ) {
-                               $wgContLang->findVariantLink( $title, $ret );
-                       }
-               }
-
-               // If title is not provided, always allow oldid and diff to set the title.
-               // If title is provided, allow oldid and diff to override the title, unless
-               // we are talking about a special page which might use these parameters for
-               // other purposes.
-               if ( $ret === null || !$ret->isSpecialPage() ) {
-                       // We can have urls with just ?diff=,?oldid= or even just ?diff=
-                       $oldid = $request->getInt( 'oldid' );
-                       $oldid = $oldid ? $oldid : $request->getInt( 'diff' );
-                       // Allow oldid to override a changed or missing title
-                       if ( $oldid ) {
-                               $rev = Revision::newFromId( $oldid );
-                               $ret = $rev ? $rev->getTitle() : $ret;
-                       }
-               }
-
-               // Use the main page as default title if nothing else has been provided
-               if ( $ret === null
-                       && strval( $title ) === ''
-                       && !$request->getCheck( 'curid' )
-                       && $action !== 'delete'
-               ) {
-                       $ret = Title::newMainPage();
-               }
-
-               if ( $ret === null || ( $ret->getDBkey() == '' && !$ret->isExternal() ) ) {
-                       $ret = SpecialPage::getTitleFor( 'Badtitle' );
-               }
-
-               return $ret;
-       }
-
-       /**
-        * Get the Title object that we'll be acting on, as specified in the WebRequest
-        * @return Title
-        */
-       public function getTitle() {
-               if ( $this->context->getTitle() === null ) {
-                       $this->context->setTitle( $this->parseTitle() );
-               }
-               return $this->context->getTitle();
-       }
-
-       /**
-        * Returns the name of the action that will be executed.
-        *
-        * @return string Action
-        */
-       public function getAction() {
-               static $action = null;
-
-               if ( $action === null ) {
-                       $action = Action::getActionName( $this->context );
-               }
-
-               return $action;
-       }
-
-       /**
-        * Performs the request.
-        * - bad titles
-        * - read restriction
-        * - local interwiki redirects
-        * - redirect loop
-        * - special pages
-        * - normal pages
-        *
-        * @throws MWException|PermissionsError|BadTitleError|HttpError
-        * @return void
-        */
-       private function performRequest() {
-               global $wgServer, $wgUsePathInfo, $wgTitle;
-
-               wfProfileIn( __METHOD__ );
-
-               $request = $this->context->getRequest();
-               $requestTitle = $title = $this->context->getTitle();
-               $output = $this->context->getOutput();
-               $user = $this->context->getUser();
-
-               if ( $request->getVal( 'printable' ) === 'yes' ) {
-                       $output->setPrintable();
-               }
-
-               $unused = null; // To pass it by reference
-               wfRunHooks( 'BeforeInitialize', array( &$title, &$unused, &$output, &$user, $request, $this ) );
-
-               // Invalid titles. Bug 21776: The interwikis must redirect even if the page name is empty.
-               if ( is_null( $title ) || ( $title->getDBkey() == '' && !$title->isExternal() )
-                       || $title->isSpecial( 'Badtitle' )
-               ) {
-                       $this->context->setTitle( SpecialPage::getTitleFor( 'Badtitle' ) );
-                       wfProfileOut( __METHOD__ );
-                       throw new BadTitleError();
-               }
-
-               // Check user's permissions to read this page.
-               // We have to check here to catch special pages etc.
-               // We will check again in Article::view().
-               $permErrors = $title->getUserPermissionsErrors( 'read', $user );
-               if ( count( $permErrors ) ) {
-                       // Bug 32276: allowing the skin to generate output with $wgTitle or
-                       // $this->context->title set to the input title would allow anonymous users to
-                       // determine whether a page exists, potentially leaking private data. In fact, the
-                       // curid and oldid request  parameters would allow page titles to be enumerated even
-                       // when they are not guessable. So we reset the title to Special:Badtitle before the
-                       // permissions error is displayed.
-                       //
-                       // The skin mostly uses $this->context->getTitle() these days, but some extensions
-                       // still use $wgTitle.
-
-                       $badTitle = SpecialPage::getTitleFor( 'Badtitle' );
-                       $this->context->setTitle( $badTitle );
-                       $wgTitle = $badTitle;
-
-                       wfProfileOut( __METHOD__ );
-                       throw new PermissionsError( 'read', $permErrors );
-               }
-
-               $pageView = false; // was an article or special page viewed?
-
-               // Interwiki redirects
-               if ( $title->isExternal() ) {
-                       $rdfrom = $request->getVal( 'rdfrom' );
-                       if ( $rdfrom ) {
-                               $url = $title->getFullURL( array( 'rdfrom' => $rdfrom ) );
-                       } else {
-                               $query = $request->getValues();
-                               unset( $query['title'] );
-                               $url = $title->getFullURL( $query );
-                       }
-                       // Check for a redirect loop
-                       if ( !preg_match( '/^' . preg_quote( $wgServer, '/' ) . '/', $url )
-                               && $title->isLocal()
-                       ) {
-                               // 301 so google et al report the target as the actual url.
-                               $output->redirect( $url, 301 );
-                       } else {
-                               $this->context->setTitle( SpecialPage::getTitleFor( 'Badtitle' ) );
-                               wfProfileOut( __METHOD__ );
-                               throw new BadTitleError();
-                       }
-               // Redirect loops, no title in URL, $wgUsePathInfo URLs, and URLs with a variant
-               } elseif ( $request->getVal( 'action', 'view' ) == 'view' && !$request->wasPosted()
-                       && ( $request->getVal( 'title' ) === null
-                               || $title->getPrefixedDBkey() != $request->getVal( 'title' ) )
-                       && !count( $request->getValueNames( array( 'action', 'title' ) ) )
-                       && wfRunHooks( 'TestCanonicalRedirect', array( $request, $title, $output ) )
-               ) {
-                       if ( $title->isSpecialPage() ) {
-                               list( $name, $subpage ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
-                               if ( $name ) {
-                                       $title = SpecialPage::getTitleFor( $name, $subpage );
-                               }
-                       }
-                       $targetUrl = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
-                       // Redirect to canonical url, make it a 301 to allow caching
-                       if ( $targetUrl == $request->getFullRequestURL() ) {
-                               $message = "Redirect loop detected!\n\n" .
-                                       "This means the wiki got confused about what page was " .
-                                       "requested; this sometimes happens when moving a wiki " .
-                                       "to a new server or changing the server configuration.\n\n";
-
-                               if ( $wgUsePathInfo ) {
-                                       $message .= "The wiki is trying to interpret the page " .
-                                               "title from the URL path portion (PATH_INFO), which " .
-                                               "sometimes fails depending on the web server. Try " .
-                                               "setting \"\$wgUsePathInfo = false;\" in your " .
-                                               "LocalSettings.php, or check that \$wgArticlePath " .
-                                               "is correct.";
-                               } else {
-                                       $message .= "Your web server was detected as possibly not " .
-                                               "supporting URL path components (PATH_INFO) correctly; " .
-                                               "check your LocalSettings.php for a customized " .
-                                               "\$wgArticlePath setting and/or toggle \$wgUsePathInfo " .
-                                               "to true.";
-                               }
-                               throw new HttpError( 500, $message );
-                       } else {
-                               $output->setSquidMaxage( 1200 );
-                               $output->redirect( $targetUrl, '301' );
-                       }
-               // Special pages
-               } elseif ( NS_SPECIAL == $title->getNamespace() ) {
-                       $pageView = true;
-                       // Actions that need to be made when we have a special pages
-                       SpecialPageFactory::executePath( $title, $this->context );
-               } else {
-                       // ...otherwise treat it as an article view. The article
-                       // may be a redirect to another article or URL.
-                       $article = $this->initializeArticle();
-                       if ( is_object( $article ) ) {
-                               $pageView = true;
-                               $this->performAction( $article, $requestTitle );
-                       } elseif ( is_string( $article ) ) {
-                               $output->redirect( $article );
-                       } else {
-                               wfProfileOut( __METHOD__ );
-                               throw new MWException( "Shouldn't happen: MediaWiki::initializeArticle()"
-                                       . " returned neither an object nor a URL" );
-                       }
-               }
-
-               if ( $pageView ) {
-                       // Promote user to any groups they meet the criteria for
-                       $user->addAutopromoteOnceGroups( 'onView' );
-               }
-
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * Initialize the main Article object for "standard" actions (view, etc)
-        * Create an Article object for the page, following redirects if needed.
-        *
-        * @return mixed An Article, or a string to redirect to another URL
-        */
-       private function initializeArticle() {
-               global $wgDisableHardRedirects;
-
-               wfProfileIn( __METHOD__ );
-
-               $title = $this->context->getTitle();
-               if ( $this->context->canUseWikiPage() ) {
-                       // Try to use request context wiki page, as there
-                       // is already data from db saved in per process
-                       // cache there from this->getAction() call.
-                       $page = $this->context->getWikiPage();
-                       $article = Article::newFromWikiPage( $page, $this->context );
-               } else {
-                       // This case should not happen, but just in case.
-                       $article = Article::newFromTitle( $title, $this->context );
-                       $this->context->setWikiPage( $article->getPage() );
-               }
-
-               // NS_MEDIAWIKI has no redirects.
-               // It is also used for CSS/JS, so performance matters here...
-               if ( $title->getNamespace() == NS_MEDIAWIKI ) {
-                       wfProfileOut( __METHOD__ );
-                       return $article;
-               }
-
-               $request = $this->context->getRequest();
-
-               // Namespace might change when using redirects
-               // Check for redirects ...
-               $action = $request->getVal( 'action', 'view' );
-               $file = ( $title->getNamespace() == NS_FILE ) ? $article->getFile() : null;
-               if ( ( $action == 'view' || $action == 'render' ) // ... for actions that show content
-                       && !$request->getVal( 'oldid' ) // ... and are not old revisions
-                       && !$request->getVal( 'diff' ) // ... and not when showing diff
-                       && $request->getVal( 'redirect' ) != 'no' // ... unless explicitly told not to
-                       // ... and the article is not a non-redirect image page with associated file
-                       && !( is_object( $file ) && $file->exists() && !$file->getRedirected() )
-               ) {
-                       // Give extensions a change to ignore/handle redirects as needed
-                       $ignoreRedirect = $target = false;
-
-                       wfRunHooks( 'InitializeArticleMaybeRedirect',
-                               array( &$title, &$request, &$ignoreRedirect, &$target, &$article ) );
-
-                       // Follow redirects only for... redirects.
-                       // If $target is set, then a hook wanted to redirect.
-                       if ( !$ignoreRedirect && ( $target || $article->isRedirect() ) ) {
-                               // Is the target already set by an extension?
-                               $target = $target ? $target : $article->followRedirect();
-                               if ( is_string( $target ) ) {
-                                       if ( !$wgDisableHardRedirects ) {
-                                               // we'll need to redirect
-                                               wfProfileOut( __METHOD__ );
-                                               return $target;
-                                       }
-                               }
-                               if ( is_object( $target ) ) {
-                                       // Rewrite environment to redirected article
-                                       $rarticle = Article::newFromTitle( $target, $this->context );
-                                       $rarticle->loadPageData();
-                                       if ( $rarticle->exists() || ( is_object( $file ) && !$file->isLocal() ) ) {
-                                               $rarticle->setRedirectedFrom( $title );
-                                               $article = $rarticle;
-                                               $this->context->setTitle( $target );
-                                               $this->context->setWikiPage( $article->getPage() );
-                                       }
-                               }
-                       } else {
-                               $this->context->setTitle( $article->getTitle() );
-                               $this->context->setWikiPage( $article->getPage() );
-                       }
-               }
-
-               wfProfileOut( __METHOD__ );
-               return $article;
-       }
-
-       /**
-        * Perform one of the "standard" actions
-        *
-        * @param Page $page
-        * @param Title $requestTitle The original title, before any redirects were applied
-        */
-       private function performAction( Page $page, Title $requestTitle ) {
-               global $wgUseSquid, $wgSquidMaxage;
-
-               wfProfileIn( __METHOD__ );
-
-               $request = $this->context->getRequest();
-               $output = $this->context->getOutput();
-               $title = $this->context->getTitle();
-               $user = $this->context->getUser();
-
-               if ( !wfRunHooks( 'MediaWikiPerformAction',
-                               array( $output, $page, $title, $user, $request, $this ) )
-               ) {
-                       wfProfileOut( __METHOD__ );
-                       return;
-               }
-
-               $act = $this->getAction();
-
-               $action = Action::factory( $act, $page, $this->context );
-
-               if ( $action instanceof Action ) {
-                       # Let Squid cache things if we can purge them.
-                       if ( $wgUseSquid &&
-                               in_array( $request->getFullRequestURL(), $requestTitle->getSquidURLs() )
-                       ) {
-                               $output->setSquidMaxage( $wgSquidMaxage );
-                       }
-
-                       $action->show();
-                       wfProfileOut( __METHOD__ );
-                       return;
-               }
-
-               if ( wfRunHooks( 'UnknownAction', array( $request->getVal( 'action', 'view' ), $page ) ) ) {
-                       $output->setStatusCode( 404 );
-                       $output->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
-               }
-
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * Run the current MediaWiki instance
-        * index.php just calls this
-        */
-       public function run() {
-               try {
-                       $this->checkMaxLag();
-                       try {
-                               $this->main();
-                       } catch ( ErrorPageError $e ) {
-                               // Bug 62091: while exceptions are convenient to bubble up GUI errors,
-                               // they are not internal application faults. As with normal requests, this
-                               // should commit, print the output, do deferred updates, jobs, and profiling.
-                               wfGetLBFactory()->commitMasterChanges();
-                               $e->report(); // display the GUI error
-                       }
-                       if ( function_exists( 'fastcgi_finish_request' ) ) {
-                               fastcgi_finish_request();
-                       }
-                       $this->triggerJobs();
-                       $this->restInPeace();
-               } catch ( Exception $e ) {
-                       MWExceptionHandler::handle( $e );
-               }
-       }
-
-       /**
-        * Checks if the request should abort due to a lagged server,
-        * for given maxlag parameter.
-        * @return bool
-        */
-       private function checkMaxLag() {
-               global $wgShowHostnames;
-
-               wfProfileIn( __METHOD__ );
-               $maxLag = $this->context->getRequest()->getVal( 'maxlag' );
-               if ( !is_null( $maxLag ) ) {
-                       list( $host, $lag ) = wfGetLB()->getMaxLag();
-                       if ( $lag > $maxLag ) {
-                               $resp = $this->context->getRequest()->response();
-                               $resp->header( 'HTTP/1.1 503 Service Unavailable' );
-                               $resp->header( 'Retry-After: ' . max( intval( $maxLag ), 5 ) );
-                               $resp->header( 'X-Database-Lag: ' . intval( $lag ) );
-                               $resp->header( 'Content-Type: text/plain' );
-                               if ( $wgShowHostnames ) {
-                                       echo "Waiting for $host: $lag seconds lagged\n";
-                               } else {
-                                       echo "Waiting for a database server: $lag seconds lagged\n";
-                               }
-
-                               wfProfileOut( __METHOD__ );
-
-                               exit;
-                       }
-               }
-               wfProfileOut( __METHOD__ );
-               return true;
-       }
-
-       private function main() {
-               global $wgUseFileCache, $wgTitle, $wgUseAjax;
-
-               wfProfileIn( __METHOD__ );
-
-               $request = $this->context->getRequest();
-
-               // Send Ajax requests to the Ajax dispatcher.
-               if ( $wgUseAjax && $request->getVal( 'action', 'view' ) == 'ajax' ) {
-
-                       // Set a dummy title, because $wgTitle == null might break things
-                       $title = Title::makeTitle( NS_MAIN, 'AJAX' );
-                       $this->context->setTitle( $title );
-                       $wgTitle = $title;
-
-                       $dispatcher = new AjaxDispatcher();
-                       $dispatcher->performAction();
-                       wfProfileOut( __METHOD__ );
-                       return;
-               }
-
-               // Get title from request parameters,
-               // is set on the fly by parseTitle the first time.
-               $title = $this->getTitle();
-               $action = $this->getAction();
-               $wgTitle = $title;
-
-               // If the user has forceHTTPS set to true, or if the user
-               // is in a group requiring HTTPS, or if they have the HTTPS
-               // preference set, redirect them to HTTPS.
-               // Note: Do this after $wgTitle is setup, otherwise the hooks run from
-               // isLoggedIn() will do all sorts of weird stuff.
-               if (
-                       $request->getProtocol() == 'http' &&
-                       (
-                               $request->getCookie( 'forceHTTPS', '' ) ||
-                               // check for prefixed version for currently logged in users
-                               $request->getCookie( 'forceHTTPS' ) ||
-                               // Avoid checking the user and groups unless it's enabled.
-                               (
-                                       $this->context->getUser()->isLoggedIn()
-                                       && $this->context->getUser()->requiresHTTPS()
-                               )
-                       )
-               ) {
-                       $oldUrl = $request->getFullRequestURL();
-                       $redirUrl = preg_replace( '#^http://#', 'https://', $oldUrl );
-
-                       // ATTENTION: This hook is likely to be removed soon due to overall design of the system.
-                       if ( wfRunHooks( 'BeforeHttpsRedirect', array( $this->context, &$redirUrl ) ) ) {
-
-                               if ( $request->wasPosted() ) {
-                                       // This is weird and we'd hope it almost never happens. This
-                                       // means that a POST came in via HTTP and policy requires us
-                                       // redirecting to HTTPS. It's likely such a request is going
-                                       // to fail due to post data being lost, but let's try anyway
-                                       // and just log the instance.
-                                       //
-                                       // @todo @fixme See if we could issue a 307 or 308 here, need
-                                       // to see how clients (automated & browser) behave when we do
-                                       wfDebugLog( 'RedirectedPosts', "Redirected from HTTP to HTTPS: $oldUrl" );
-                               }
-                               // Setup dummy Title, otherwise OutputPage::redirect will fail
-                               $title = Title::newFromText( NS_MAIN, 'REDIR' );
-                               $this->context->setTitle( $title );
-                               $output = $this->context->getOutput();
-                               // Since we only do this redir to change proto, always send a vary header
-                               $output->addVaryHeader( 'X-Forwarded-Proto' );
-                               $output->redirect( $redirUrl );
-                               $output->output();
-                               wfProfileOut( __METHOD__ );
-                               return;
-                       }
-               }
-
-               if ( $wgUseFileCache && $title->getNamespace() >= 0 ) {
-                       wfProfileIn( 'main-try-filecache' );
-                       if ( HTMLFileCache::useFileCache( $this->context ) ) {
-                               // Try low-level file cache hit
-                               $cache = HTMLFileCache::newFromTitle( $title, $action );
-                               if ( $cache->isCacheGood( /* Assume up to date */ ) ) {
-                                       // Check incoming headers to see if client has this cached
-                                       $timestamp = $cache->cacheTimestamp();
-                                       if ( !$this->context->getOutput()->checkLastModified( $timestamp ) ) {
-                                               $cache->loadFromFileCache( $this->context );
-                                       }
-                                       // Do any stats increment/watchlist stuff
-                                       // Assume we're viewing the latest revision (this should always be the case with file cache)
-                                       $this->context->getWikiPage()->doViewUpdates( $this->context->getUser() );
-                                       // Tell OutputPage that output is taken care of
-                                       $this->context->getOutput()->disable();
-                                       wfProfileOut( 'main-try-filecache' );
-                                       wfProfileOut( __METHOD__ );
-                                       return;
-                               }
-                       }
-                       wfProfileOut( 'main-try-filecache' );
-               }
-
-               // Actually do the work of the request and build up any output
-               $this->performRequest();
-
-               // Either all DB and deferred updates should happen or none.
-               // The later should not be cancelled due to client disconnect.
-               ignore_user_abort( true );
-               // Now commit any transactions, so that unreported errors after
-               // output() don't roll back the whole DB transaction
-               wfGetLBFactory()->commitMasterChanges();
-
-               // Output everything!
-               $this->context->getOutput()->output();
-
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * Ends this task peacefully
-        */
-       public function restInPeace() {
-               // Do any deferred jobs
-               DeferredUpdates::doUpdates( 'commit' );
-
-               // Log profiling data, e.g. in the database or UDP
-               wfLogProfilingData();
-
-               // Commit and close up!
-               $factory = wfGetLBFactory();
-               $factory->commitMasterChanges();
-               $factory->shutdown();
-
-               wfDebug( "Request ended normally\n" );
-       }
-
-       /**
-        * Potentially open a socket and sent an HTTP request back to the server
-        * to run a specified number of jobs. This registers a callback to cleanup
-        * the socket once it's done.
-        */
-       protected function triggerJobs() {
-               global $wgJobRunRate, $wgServer, $wgRunJobsAsync;
-
-               if ( $wgJobRunRate <= 0 || wfReadOnly() ) {
-                       return;
-               } elseif ( $this->getTitle()->isSpecial( 'RunJobs' ) ) {
-                       return; // recursion guard
-               }
-
-               $section = new ProfileSection( __METHOD__ );
-
-               if ( $wgJobRunRate < 1 ) {
-                       $max = mt_getrandmax();
-                       if ( mt_rand( 0, $max ) > $max * $wgJobRunRate ) {
-                               return; // the higher $wgJobRunRate, the less likely we return here
-                       }
-                       $n = 1;
-               } else {
-                       $n = intval( $wgJobRunRate );
-               }
-
-               if ( !$wgRunJobsAsync ) {
-                       // If running jobs asynchronously has been disabled, run the job here
-                       // while the user waits
-                       SpecialRunJobs::executeJobs( $n );
-                       return;
-               }
-
-               try {
-                       if ( !JobQueueGroup::singleton()->queuesHaveJobs( JobQueueGroup::TYPE_DEFAULT ) ) {
-                               return; // do not send request if there are probably no jobs
-                       }
-               } catch ( JobQueueError $e ) {
-                       MWExceptionHandler::logException( $e );
-                       return; // do not make the site unavailable
-               }
-
-               $query = array( 'title' => 'Special:RunJobs',
-                       'tasks' => 'jobs', 'maxjobs' => $n, 'sigexpiry' => time() + 5 );
-               $query['signature'] = SpecialRunJobs::getQuerySignature( $query );
-
-               $errno = $errstr = null;
-               $info = wfParseUrl( $wgServer );
-               wfSuppressWarnings();
-               $sock = fsockopen(
-                       $info['host'],
-                       isset( $info['port'] ) ? $info['port'] : 80,
-                       $errno,
-                       $errstr,
-                       // If it takes more than 100ms to connect to ourselves there
-                       // is a problem elsewhere.
-                       0.1
-               );
-               wfRestoreWarnings();
-               if ( !$sock ) {
-                       wfDebugLog( 'runJobs', "Failed to start cron API (socket error $errno): $errstr\n" );
-                       // Fall back to running the job here while the user waits
-                       SpecialRunJobs::executeJobs( $n );
-                       return;
-               }
-
-               $url = wfAppendQuery( wfScript( 'index' ), $query );
-               $req = "POST $url HTTP/1.1\r\nHost: {$info['host']}\r\nConnection: Close\r\n\r\n";
-
-               wfDebugLog( 'runJobs', "Running $n job(s) via '$url'\n" );
-               // Send a cron API request to be performed in the background.
-               // Give up if this takes too long to send (which should be rare).
-               stream_set_timeout( $sock, 1 );
-               $bytes = fwrite( $sock, $req );
-               if ( $bytes !== strlen( $req ) ) {
-                       wfDebugLog( 'runJobs', "Failed to start cron API (socket write error)\n" );
-               } else {
-                       // Do not wait for the response (the script should handle client aborts).
-                       // Make sure that we don't close before that script reaches ignore_user_abort().
-                       $status = fgets( $sock );
-                       if ( !preg_match( '#^HTTP/\d\.\d 202 #', $status ) ) {
-                               wfDebugLog( 'runJobs', "Failed to start cron API: received '$status'\n" );
-                       }
-               }
-               fclose( $sock );
-       }
-}
index 6fb5380..159f711 100644 (file)
@@ -134,31 +134,6 @@ class Xml {
                return self::openElement( $element, $attribs ) . $contents . "</$element>";
        }
 
-       /**
-        * Build a drop-down box for selecting a namespace
-        *
-        * @param string $selected Namespace which should be pre-selected
-        * @param string|null $all Value of an item denoting all namespaces, or null to omit
-        * @param string $element_name Value of the "name" attribute of the select tag
-        * @param string $label Optional label to add to the field
-        * @return string
-        * @deprecated since 1.19
-        */
-       public static function namespaceSelector( $selected = '', $all = null,
-               $element_name = 'namespace', $label = null
-       ) {
-               wfDeprecated( __METHOD__, '1.19' );
-               return Html::namespaceSelector( array(
-                       'selected' => $selected,
-                       'all' => $all,
-                       'label' => $label,
-               ), array(
-                       'name' => $element_name,
-                       'id' => 'namespace',
-                       'class' => 'namespaceselector',
-               ) );
-       }
-
        /**
         * Create a date selector
         *
@@ -233,7 +208,7 @@ class Xml {
         * @param string $inLanguage The ISO code of the language to display the select list in (optional)
         * @param array $overrideAttrs Override the attributes of the select tag (since 1.20)
         * @param Message|null $msg Label message key (since 1.20)
-        * @return array containing 2 items: label HTML and select list HTML
+        * @return array Array containing 2 items: label HTML and select list HTML
         */
        public static function languageSelector( $selected, $customisedOnly = true,
                $inLanguage = null, $overrideAttrs = array(), Message $msg = null
@@ -317,7 +292,8 @@ class Xml {
                        $attributes['value'] = $value;
                }
 
-               return self::element( 'input', $attributes + $attribs );
+               return self::element( 'input',
+                       Html::getTextInputAttributes( $attributes + $attribs ) );
        }
 
        /**
@@ -453,9 +429,16 @@ class Xml {
         * @return string HTML
         */
        public static function checkLabel( $label, $name, $id, $checked = false, $attribs = array() ) {
-               return self::check( $name, $checked, array( 'id' => $id ) + $attribs ) .
+               global $wgUseMediaWikiUIEverywhere;
+               $chkLabel = self::check( $name, $checked, array( 'id' => $id ) + $attribs ) .
                        '&#160;' .
                        self::label( $label, $id, $attribs );
+
+               if ( $wgUseMediaWikiUIEverywhere ) {
+                       $chkLabel = self::openElement( 'div', array( 'class' => 'mw-ui-checkbox' ) ) .
+                               $chkLabel . self::closeElement( 'div' );
+               }
+               return $chkLabel;
        }
 
        /**
@@ -480,12 +463,26 @@ class Xml {
 
        /**
         * Convenience function to build an HTML submit button
+        * When $wgUseMediaWikiUIEverywhere is true it will default to a constructive button
         * @param string $value Label text for the button
         * @param array $attribs Optional custom attributes
         * @return string HTML
         */
        public static function submitButton( $value, $attribs = array() ) {
-               return Html::element( 'input', array( 'type' => 'submit', 'value' => $value ) + $attribs );
+               global $wgUseMediaWikiUIEverywhere;
+               $baseAttrs = array(
+                       'type' => 'submit',
+                       'value' => $value,
+               );
+               // Done conditionally for time being as it is possible
+               // some submit forms
+               // might need to be mw-ui-destructive (e.g. delete a page)
+               if ( $wgUseMediaWikiUIEverywhere ) {
+                       $baseAttrs['class'] = 'mw-ui-button mw-ui-constructive';
+               }
+               // Any custom attributes will take precendence of anything in baseAttrs e.g. override the class
+               $attribs = $attribs + $baseAttrs;
+               return Html::element( 'input', $attribs );
        }
 
        /**
@@ -617,12 +614,14 @@ class Xml {
         */
        public static function textarea( $name, $content, $cols = 40, $rows = 5, $attribs = array() ) {
                return self::element( 'textarea',
-                                       array(
-                                               'name' => $name,
-                                               'id' => $name,
-                                               'cols' => $cols,
-                                               'rows' => $rows
-                                       ) + $attribs,
+                                       Html::getTextInputAttributes(
+                                               array(
+                                                       'name' => $name,
+                                                       'id' => $name,
+                                                       'cols' => $cols,
+                                                       'rows' => $rows
+                                               ) + $attribs
+                                       ),
                                        $content, false );
        }
 
index d4b08b2..8d11d90 100644 (file)
@@ -38,18 +38,21 @@ abstract class Action {
 
        /**
         * Page on which we're performing the action
+        * @since 1.17
         * @var WikiPage|Article|ImagePage|CategoryPage|Page $page
         */
        protected $page;
 
        /**
         * IContextSource if specified; otherwise we'll use the Context from the Page
+        * @since 1.17
         * @var IContextSource $context
         */
        protected $context;
 
        /**
         * The fields used to create the HTMLForm
+        * @since 1.17
         * @var array $fields
         */
        protected $fields;
@@ -82,6 +85,7 @@ abstract class Action {
 
        /**
         * Get an appropriate Action subclass for the given action
+        * @since 1.17
         * @param string $action
         * @param Page $page
         * @param IContextSource $context
@@ -152,6 +156,7 @@ abstract class Action {
 
        /**
         * Check if a given action is recognised, even if it's disabled
+        * @since 1.17
         *
         * @param string $name Name of an action
         * @return bool
@@ -162,6 +167,7 @@ abstract class Action {
 
        /**
         * Get the IContextSource in use here
+        * @since 1.17
         * @return IContextSource
         */
        final public function getContext() {
@@ -179,6 +185,7 @@ abstract class Action {
 
        /**
         * Get the WebRequest being used for this instance
+        * @since 1.17
         *
         * @return WebRequest
         */
@@ -188,6 +195,7 @@ abstract class Action {
 
        /**
         * Get the OutputPage being used for this instance
+        * @since 1.17
         *
         * @return OutputPage
         */
@@ -197,6 +205,7 @@ abstract class Action {
 
        /**
         * Shortcut to get the User being used for this instance
+        * @since 1.17
         *
         * @return User
         */
@@ -206,6 +215,7 @@ abstract class Action {
 
        /**
         * Shortcut to get the Skin being used for this instance
+        * @since 1.17
         *
         * @return Skin
         */
@@ -224,6 +234,8 @@ abstract class Action {
 
        /**
         * Shortcut to get the Title object from the page
+        * @since 1.17
+        *
         * @return Title
         */
        final public function getTitle() {
@@ -262,6 +274,8 @@ abstract class Action {
 
        /**
         * Return the name of the action this object responds to
+        * @since 1.17
+        *
         * @return string Lowercase name
         */
        abstract public function getName();
@@ -269,6 +283,8 @@ abstract class Action {
        /**
         * Get the permission required to perform this action.  Often, but not always,
         * the same as the action name
+        * @since 1.17
+        *
         * @return string|null
         */
        public function getRestriction() {
@@ -279,10 +295,10 @@ abstract class Action {
         * Checks if the given user (identified by an object) can perform this action.  Can be
         * overridden by sub-classes with more complicated permissions schemes.  Failures here
         * must throw subclasses of ErrorPageError
+        * @since 1.17
         *
         * @param User $user The user to check, or null to use the context user
         * @throws UserBlockedError|ReadOnlyError|PermissionsError
-        * @return bool True on success
         */
        protected function checkCanExecute( User $user ) {
                $right = $this->getRestriction();
@@ -304,11 +320,12 @@ abstract class Action {
                if ( $this->requiresWrite() && wfReadOnly() ) {
                        throw new ReadOnlyError();
                }
-               return true;
        }
 
        /**
         * Whether this action requires the wiki not to be locked
+        * @since 1.17
+        *
         * @return bool
         */
        public function requiresWrite() {
@@ -317,6 +334,8 @@ abstract class Action {
 
        /**
         * Whether this action can still be executed by a blocked user
+        * @since 1.17
+        *
         * @return bool
         */
        public function requiresUnblock() {
@@ -326,12 +345,13 @@ abstract class Action {
        /**
         * Set output headers for noindexing etc.  This function will not be called through
         * the execute() entry point, so only put UI-related stuff in here.
+        * @since 1.17
         */
        protected function setHeaders() {
                $out = $this->getOutput();
                $out->setRobotPolicy( "noindex,nofollow" );
                $out->setPageTitle( $this->getPageTitle() );
-               $this->getOutput()->setSubtitle( $this->getDescription() );
+               $out->setSubtitle( $this->getDescription() );
                $out->setArticleRelated( true );
        }
 
@@ -346,6 +366,7 @@ abstract class Action {
 
        /**
         * Returns the description that goes below the \<h1\> tag
+        * @since 1.17
         *
         * @return string
         */
@@ -357,13 +378,9 @@ abstract class Action {
         * The main action entry point.  Do all output for display and send it to the context
         * output.  Do not use globals $wgOut, $wgRequest, etc, in implementations; use
         * $this->getOutput(), etc.
+        * @since 1.17
+        *
         * @throws ErrorPageError
         */
        abstract public function show();
-
-       /**
-        * Execute the action in a silent fashion: do not display anything or release any errors.
-        * @return bool whether execution was successful
-        */
-       abstract public function execute();
 }
index 32efc68..bc4df34 100644 (file)
@@ -110,7 +110,7 @@ abstract class CachedAction extends FormlessAction implements ICacheHelper {
         *
         * @since 1.20
         *
-        * @param {function} $computeFunction
+        * @param callable $computeFunction
         * @param array|mixed $args
         * @param string|null $key
         *
@@ -128,7 +128,7 @@ abstract class CachedAction extends FormlessAction implements ICacheHelper {
         *
         * @since 1.20
         *
-        * @param {function} $computeFunction
+        * @param callable $computeFunction
         * @param array $args
         * @param string|null $key
         */
index 2bb1be4..e064aab 100644 (file)
@@ -60,7 +60,7 @@ class CreditsAction extends FormlessAction {
         *
         * @param int $cnt Maximum list of contributors to show
         * @param bool $showIfMax Whether to contributors if there more than $cnt
-        * @return string html
+        * @return string Html
         */
        public function getCredits( $cnt, $showIfMax = true ) {
                wfProfileIn( __METHOD__ );
@@ -100,15 +100,24 @@ class CreditsAction extends FormlessAction {
                        $this->userLink( $user ) )->params( $user->getName() )->escaped();
        }
 
+       /**
+        * Whether we can display the user's real name (not a hidden pref)
+        *
+        * @since 1.24
+        * @return bool
+        */
+       protected function canShowRealUserName() {
+               $hiddenPrefs = $this->context->getConfig()->get( 'HiddenPrefs' );
+               return !in_array( 'realname', $hiddenPrefs );
+       }
+
        /**
         * Get a list of contributors of $article
         * @param int $cnt Maximum list of contributors to show
         * @param bool $showIfMax Whether to contributors if there more than $cnt
-        * @return string html
+        * @return string Html
         */
        protected function getContributors( $cnt, $showIfMax ) {
-               global $wgHiddenPrefs;
-
                $contributors = $this->page->getContributors();
 
                $others_link = false;
@@ -132,7 +141,7 @@ class CreditsAction extends FormlessAction {
                        $cnt--;
                        if ( $user->isLoggedIn() ) {
                                $link = $this->link( $user );
-                               if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) {
+                               if ( $this->canShowRealUserName() && $user->getRealName() ) {
                                        $real_names[] = $link;
                                } else {
                                        $user_names[] = $link;
@@ -192,8 +201,7 @@ class CreditsAction extends FormlessAction {
         * @return string Html
         */
        protected function link( User $user ) {
-               global $wgHiddenPrefs;
-               if ( !in_array( 'realname', $wgHiddenPrefs ) && !$user->isAnon() ) {
+               if ( $this->canShowRealUserName() && !$user->isAnon() ) {
                        $real = $user->getRealName();
                } else {
                        $real = false;
@@ -216,8 +224,7 @@ class CreditsAction extends FormlessAction {
                if ( $user->isAnon() ) {
                        return $this->msg( 'anonuser' )->rawParams( $link )->parse();
                } else {
-                       global $wgHiddenPrefs;
-                       if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) {
+                       if ( $this->canShowRealUserName() && $user->getRealName() ) {
                                return $link;
                        } else {
                                return $this->msg( 'siteuser' )->rawParams( $link )->params( $user->getName() )->escaped();
index 069d570..12f0dff 100644 (file)
@@ -41,7 +41,13 @@ class DeleteAction extends FormlessAction {
        }
 
        public function show() {
-
+               if ( $this->getContext()->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
+                       $out = $this->getOutput();
+                       $out->addModuleStyles( array(
+                               'mediawiki.ui.input',
+                               'mediawiki.ui.checkbox',
+                       ) );
+               }
                $this->page->delete();
        }
 }
index 31f58b8..8876724 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * action=edit / action=submit handler
+ * action=edit handler
  *
  * Copyright © 2012 Timo Tijhof
  *
@@ -41,6 +41,13 @@ class EditAction extends FormlessAction {
        }
 
        public function show() {
+               if ( $this->getContext()->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
+                       $out = $this->getOutput();
+                       $out->addModuleStyles( array(
+                               'mediawiki.ui.input',
+                               'mediawiki.ui.checkbox',
+                       ) );
+               }
                $page = $this->page;
                $user = $this->getUser();
 
@@ -50,26 +57,3 @@ class EditAction extends FormlessAction {
                }
        }
 }
-
-/**
- * Edit submission handler
- *
- * This is the same as EditAction; except that it sets the session cookie.
- *
- * @ingroup Actions
- */
-class SubmitAction extends EditAction {
-
-       public function getName() {
-               return 'submit';
-       }
-
-       public function show() {
-               if ( session_id() == '' ) {
-                       // Send a cookie so anons get talk message notifications
-                       wfSetupSession();
-               }
-
-               parent::show();
-       }
-}
index 7477d11..4c9e85d 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * @file
- */
-
-/**
- * @defgroup Actions Action done on pages
+ * @ingroup Actions
  */
 
 /**
  * An action which shows a form and does something based on the input from the form
+ *
+ * @ingroup Actions
  */
 abstract class FormAction extends Action {
 
@@ -121,48 +120,4 @@ abstract class FormAction extends Action {
                        $this->onSuccess();
                }
        }
-
-       /**
-        * @see Action::execute()
-        *
-        * @param array|null $data
-        * @param bool $captureErrors
-        * @throws ErrorPageError|Exception
-        * @return bool
-        */
-       public function execute( array $data = null, $captureErrors = true ) {
-               try {
-                       // Set a new context so output doesn't leak.
-                       $this->context = clone $this->getContext();
-
-                       // This will throw exceptions if there's a problem
-                       $this->checkCanExecute( $this->getUser() );
-
-                       $fields = array();
-                       foreach ( $this->fields as $key => $params ) {
-                               if ( isset( $data[$key] ) ) {
-                                       $fields[$key] = $data[$key];
-                               } elseif ( isset( $params['default'] ) ) {
-                                       $fields[$key] = $params['default'];
-                               } else {
-                                       $fields[$key] = null;
-                               }
-                       }
-                       $status = $this->onSubmit( $fields );
-                       if ( $status === true ) {
-                               // This might do permanent stuff
-                               $this->onSuccess();
-                               return true;
-                       } else {
-                               return false;
-                       }
-               }
-               catch ( ErrorPageError $e ) {
-                       if ( $captureErrors ) {
-                               return false;
-                       } else {
-                               throw $e;
-                       }
-               }
-       }
 }
index 0039838..a6f1e29 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * @file
- */
-
-/**
- * @defgroup Actions Action done on pages
+ * @ingroup Actions
  */
 
 /**
  * An action which just does something, without showing a form first.
+ *
+ * @ingroup Actions
  */
 abstract class FormlessAction extends Action {
 
@@ -35,29 +34,6 @@ abstract class FormlessAction extends Action {
         */
        abstract public function onView();
 
-       /**
-        * We don't want an HTMLForm
-        * @return bool
-        */
-       protected function getFormFields() {
-               return false;
-       }
-
-       /**
-        * @param array $data
-        * @return bool
-        */
-       public function onSubmit( $data ) {
-               return false;
-       }
-
-       /**
-        * @return bool
-        */
-       public function onSuccess() {
-               return false;
-       }
-
        public function show() {
                $this->setHeaders();
 
@@ -66,35 +42,4 @@ abstract class FormlessAction extends Action {
 
                $this->getOutput()->addHTML( $this->onView() );
        }
-
-       /**
-        * Execute the action silently, not giving any output.  Since these actions don't have
-        * forms, they probably won't have any data, but some (eg rollback) may do
-        * @param array $data Values that would normally be in the GET request
-        * @param bool $captureErrors Whether to catch exceptions and just return false
-        * @throws ErrorPageError|Exception
-        * @return bool Whether execution was successful
-        */
-       public function execute( array $data = null, $captureErrors = true ) {
-               try {
-                       // Set a new context so output doesn't leak.
-                       $this->context = clone $this->getContext();
-                       if ( is_array( $data ) ) {
-                               $this->context->setRequest( new FauxRequest( $data, false ) );
-                       }
-
-                       // This will throw exceptions if there's a problem
-                       $this->checkCanExecute( $this->getUser() );
-
-                       $this->onView();
-                       return true;
-               }
-               catch ( ErrorPageError $e ) {
-                       if ( $captureErrors ) {
-                               return false;
-                       } else {
-                               throw $e;
-                       }
-               }
-       }
 }
index c946184..523da68 100644 (file)
@@ -92,8 +92,6 @@ class HistoryAction extends FormlessAction {
         * Print the history page for an article.
         */
        function onView() {
-               global $wgScript, $wgUseFileCache;
-
                $out = $this->getOutput();
                $request = $this->getRequest();
 
@@ -107,9 +105,11 @@ class HistoryAction extends FormlessAction {
                wfProfileIn( __METHOD__ );
 
                $this->preCacheMessages();
+               $config = $this->context->getConfig();
 
                # Fill in the file cache if not set already
-               if ( $wgUseFileCache && HTMLFileCache::useFileCache( $this->getContext() ) ) {
+               $useFileCache = $config->get( 'UseFileCache' );
+               if ( $useFileCache && HTMLFileCache::useFileCache( $this->getContext() ) ) {
                        $cache = HTMLFileCache::newFromTitle( $this->getTitle(), 'history' );
                        if ( !$cache->isCacheGood( /* Assume up to date */ ) ) {
                                ob_start( array( &$cache, 'saveToFileCache' ) );
@@ -119,6 +119,13 @@ class HistoryAction extends FormlessAction {
                // Setup page variables.
                $out->setFeedAppendQuery( 'action=history' );
                $out->addModules( 'mediawiki.action.history' );
+               if ( $config->get( 'UseMediaWikiUIEverywhere' ) ) {
+                       $out = $this->getOutput();
+                       $out->addModuleStyles( array(
+                               'mediawiki.ui.input',
+                               'mediawiki.ui.checkbox',
+                       ) );
+               }
 
                // Handle atom/RSS feeds.
                $feedType = $request->getVal( 'feed' );
@@ -173,7 +180,7 @@ class HistoryAction extends FormlessAction {
                }
 
                // Add the general form
-               $action = htmlspecialchars( $wgScript );
+               $action = htmlspecialchars( wfScript() );
                $out->addHTML(
                        "<form action=\"$action\" method=\"get\" id=\"mw-history-searchform\">" .
                        Xml::fieldset(
@@ -214,7 +221,7 @@ class HistoryAction extends FormlessAction {
         *
         * @param int $limit The limit number of revisions to get
         * @param int $offset
-        * @param int $direction Either HistoryPage::DIR_PREV or HistoryPage::DIR_NEXT
+        * @param int $direction Either self::DIR_PREV or self::DIR_NEXT
         * @return ResultWrapper
         */
        function fetchRevisions( $limit, $offset, $direction ) {
@@ -225,9 +232,9 @@ class HistoryAction extends FormlessAction {
 
                $dbr = wfGetDB( DB_SLAVE );
 
-               if ( $direction == HistoryPage::DIR_PREV ) {
+               if ( $direction === self::DIR_PREV ) {
                        list( $dirs, $oper ) = array( "ASC", ">=" );
-               } else { /* $direction == HistoryPage::DIR_NEXT */
+               } else { /* $direction === self::DIR_NEXT */
                        list( $dirs, $oper ) = array( "DESC", "<=" );
                }
 
@@ -251,17 +258,17 @@ class HistoryAction extends FormlessAction {
        /**
         * Output a subscription feed listing recent edits to this page.
         *
-        * @param string $type feed type
+        * @param string $type Feed type
         */
        function feed( $type ) {
-               global $wgFeedClasses, $wgFeedLimit;
                if ( !FeedUtils::checkFeedOutput( $type ) ) {
                        return;
                }
                $request = $this->getRequest();
 
+               $feedClasses = $this->context->getConfig()->get( 'FeedClasses' );
                /** @var RSSFeed|AtomFeed $feed */
-               $feed = new $wgFeedClasses[$type](
+               $feed = new $feedClasses[$type](
                        $this->getTitle()->getPrefixedText() . ' - ' .
                        $this->msg( 'history-feed-title' )->inContentLanguage()->text(),
                        $this->msg( 'history-feed-description' )->inContentLanguage()->text(),
@@ -271,9 +278,12 @@ class HistoryAction extends FormlessAction {
                // Get a limit on number of feed entries. Provide a sane default
                // of 10 if none is defined (but limit to $wgFeedLimit max)
                $limit = $request->getInt( 'limit', 10 );
-               $limit = min( max( $limit, 1 ), $wgFeedLimit );
+               $limit = min(
+                       max( $limit, 1 ),
+                       $this->context->getConfig()->get( 'FeedLimit' )
+               );
 
-               $items = $this->fetchRevisions( $limit, 0, HistoryPage::DIR_NEXT );
+               $items = $this->fetchRevisions( $limit, 0, self::DIR_NEXT );
 
                // Generate feed elements enclosed between header and footer.
                $feed->outHeader();
@@ -303,7 +313,7 @@ class HistoryAction extends FormlessAction {
         * Borrows Recent Changes' feed generation functions for formatting;
         * includes a diff to the previous revision (if any).
         *
-        * @param stdClass|array $row database row
+        * @param stdClass|array $row Database row
         * @return FeedItem
         */
        function feedItem( $row ) {
@@ -462,21 +472,24 @@ class HistoryPager extends ReverseChronologicalPager {
         * @return string HTML output
         */
        function getStartBody() {
-               global $wgScript;
                $this->lastRow = false;
                $this->counter = 1;
                $this->oldIdChecked = 0;
 
                $this->getOutput()->wrapWikiMsg( "<div class='mw-history-legend'>\n$1\n</div>", 'histlegend' );
-               $s = Html::openElement( 'form', array( 'action' => $wgScript,
+               $s = Html::openElement( 'form', array( 'action' => wfScript(),
                        'id' => 'mw-history-compare' ) ) . "\n";
                $s .= Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) . "\n";
                $s .= Html::hidden( 'action', 'historysubmit' ) . "\n";
 
                // Button container stored in $this->buttons for re-use in getEndBody()
                $this->buttons = '<div>';
+               $className = 'historysubmit mw-history-compareselectedversions-button';
+               if ( $this->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
+                       $className .= ' mw-ui-button mw-ui-constructive';
+               }
                $this->buttons .= $this->submitButton( $this->msg( 'compareselectedversions' )->text(),
-                       array( 'class' => 'historysubmit mw-history-compareselectedversions-button' )
+                       array( 'class' => $className )
                                + Linker::tooltipAndAccesskeyAttribs( 'compareselectedversions' )
                ) . "\n";
 
@@ -776,18 +789,21 @@ class HistoryPager extends ReverseChronologicalPager {
        /**
         * Create a diff-to-previous link for this revision for this page.
         *
-        * @param Revision $prevRev The previous revision
-        * @param mixed $next The newer revision
+        * @param Revision $prevRev The revision being displayed
+        * @param stdClass|string|null $next The next revision in list (that is
+        *        the previous one in chronological order).
+        *        May either be a row, "unknown" or null.
         * @return string
         */
        function lastLink( $prevRev, $next ) {
                $last = $this->historyPage->message['last'];
-               # $next may either be a Row, null, or "unknown"
-               $nextRev = is_object( $next ) ? new Revision( $next ) : $next;
-               if ( is_null( $next ) ) {
+
+               if ( $next === null ) {
                        # Probably no next row
                        return $last;
-               } elseif ( $next === 'unknown' ) {
+               }
+
+               if ( $next === 'unknown' ) {
                        # Next row probably exists but is unknown, use an oldid=prev link
                        return Linker::linkKnown(
                                $this->getTitle(),
@@ -798,21 +814,25 @@ class HistoryPager extends ReverseChronologicalPager {
                                        'oldid' => 'prev'
                                )
                        );
-               } elseif ( !$prevRev->userCan( Revision::DELETED_TEXT, $this->getUser() )
+               }
+
+               $nextRev = new Revision( $next );
+
+               if ( !$prevRev->userCan( Revision::DELETED_TEXT, $this->getUser() )
                        || !$nextRev->userCan( Revision::DELETED_TEXT, $this->getUser() )
                ) {
                        return $last;
-               } else {
-                       return Linker::linkKnown(
-                               $this->getTitle(),
-                               $last,
-                               array(),
-                               array(
-                                       'diff' => $prevRev->getId(),
-                                       'oldid' => $next->rev_id
-                               )
-                       );
                }
+
+               return Linker::linkKnown(
+                       $this->getTitle(),
+                       $last,
+                       array(),
+                       array(
+                               'diff' => $prevRev->getId(),
+                               'oldid' => $next->rev_id
+                       )
+               );
        }
 
        /**
@@ -866,6 +886,7 @@ class HistoryPager extends ReverseChronologicalPager {
 
        /**
         * This is called if a write operation is possible from the generated HTML
+        * @param bool $enable
         */
        function preventClickjacking( $enable = true ) {
                $this->preventClickjacking = $enable;
@@ -879,18 +900,3 @@ class HistoryPager extends ReverseChronologicalPager {
                return $this->preventClickjacking;
        }
 }
-
-/**
- * Backwards-compatibility alias
- */
-class HistoryPage extends HistoryAction {
-       // @codingStandardsIgnoreStart Needed "useless" override to make it public.
-       public function __construct( Page $article ) {
-               parent::__construct( $article );
-       }
-       // @codingStandardsIgnoreEnd
-
-       public function history() {
-               $this->onView();
-       }
-}
index c2c1ff5..f932a40 100644 (file)
@@ -193,13 +193,13 @@ class InfoAction extends FormlessAction {
         * @return array
         */
        protected function pageInfo() {
-               global $wgContLang, $wgRCMaxAge, $wgMemc, $wgMiserMode,
-                       $wgUnwatchedPageThreshold, $wgPageInfoTransclusionLimit, $wgPageLanguageUseDB;
+               global $wgContLang, $wgMemc;
 
                $user = $this->getUser();
                $lang = $this->getLanguage();
                $title = $this->getTitle();
                $id = $title->getArticleID();
+               $config = $this->context->getConfig();
 
                $memcKey = wfMemcKey( 'infoaction',
                        sha1( $title->getPrefixedText() ), $this->page->getLatest() );
@@ -207,7 +207,7 @@ class InfoAction extends FormlessAction {
                $version = isset( $pageCounts['cacheversion'] ) ? $pageCounts['cacheversion'] : false;
                if ( $pageCounts === false || $version !== self::CACHE_VERSION ) {
                        // Get page information that would be too "expensive" to retrieve by normal means
-                       $pageCounts = self::pageCounts( $title );
+                       $pageCounts = $this->pageCounts( $title );
                        $pageCounts['cacheversion'] = self::CACHE_VERSION;
 
                        $wgMemc->set( $memcKey, $pageCounts );
@@ -276,7 +276,7 @@ class InfoAction extends FormlessAction {
                // Language in which the page content is (supposed to be) written
                $pageLang = $title->getPageLanguage()->getCode();
 
-               if ( $wgPageLanguageUseDB && $this->getTitle()->userCan( 'pagelang' ) ) {
+               if ( $config->get( 'PageLanguageUseDB' ) && $this->getTitle()->userCan( 'pagelang' ) ) {
                        // Link to Special:PageLanguage with pre-filled page title if user has permissions
                        $titleObj = SpecialPage::getTitleFor( 'PageLanguage', $title->getPrefixedText() );
                        $langDisp = Linker::link(
@@ -321,19 +321,20 @@ class InfoAction extends FormlessAction {
                        );
                }
 
+               $unwatchedPageThreshold = $config->get( 'UnwatchedPageThreshold' );
                if (
                        $user->isAllowed( 'unwatchedpages' ) ||
-                       ( $wgUnwatchedPageThreshold !== false &&
-                               $pageCounts['watchers'] >= $wgUnwatchedPageThreshold )
+                       ( $unwatchedPageThreshold !== false &&
+                               $pageCounts['watchers'] >= $unwatchedPageThreshold )
                ) {
                        // Number of page watchers
                        $pageInfo['header-basic'][] = array(
                                $this->msg( 'pageinfo-watchers' ), $lang->formatNum( $pageCounts['watchers'] )
                        );
-               } elseif ( $wgUnwatchedPageThreshold !== false ) {
+               } elseif ( $unwatchedPageThreshold !== false ) {
                        $pageInfo['header-basic'][] = array(
                                $this->msg( 'pageinfo-watchers' ),
-                               $this->msg( 'pageinfo-few-watchers' )->numParams( $wgUnwatchedPageThreshold )
+                               $this->msg( 'pageinfo-few-watchers' )->numParams( $unwatchedPageThreshold )
                        );
                }
 
@@ -521,7 +522,7 @@ class InfoAction extends FormlessAction {
 
                // Recent number of edits (within past 30 days)
                $pageInfo['header-edits'][] = array(
-                       $this->msg( 'pageinfo-recent-edits', $lang->formatDuration( $wgRCMaxAge ) ),
+                       $this->msg( 'pageinfo-recent-edits', $lang->formatDuration( $config->get( 'RCMaxAge' ) ) ),
                        $lang->formatNum( $pageCounts['recent_edits'] )
                );
 
@@ -555,9 +556,9 @@ class InfoAction extends FormlessAction {
                        $pageCounts['transclusion']['from'] > 0 ||
                        $pageCounts['transclusion']['to'] > 0
                ) {
-                       $options = array( 'LIMIT' => $wgPageInfoTransclusionLimit );
+                       $options = array( 'LIMIT' => $config->get( 'PageInfoTransclusionLimit' ) );
                        $transcludedTemplates = $title->getTemplateLinksFrom( $options );
-                       if ( $wgMiserMode ) {
+                       if ( $config->get( 'MiserMode' ) ) {
                                $transcludedTargets = array();
                        } else {
                                $transcludedTargets = $title->getTemplateLinksTo( $options );
@@ -602,7 +603,7 @@ class InfoAction extends FormlessAction {
                                );
                        }
 
-                       if ( !$wgMiserMode && $pageCounts['transclusion']['to'] > 0 ) {
+                       if ( !$config->get( 'MiserMode' ) && $pageCounts['transclusion']['to'] > 0 ) {
                                if ( $pageCounts['transclusion']['to'] > count( $transcludedTargets ) ) {
                                        $more = Linker::link(
                                                $whatLinksHere,
@@ -635,16 +636,15 @@ class InfoAction extends FormlessAction {
         * @param Title $title Title to get counts for
         * @return array
         */
-       protected static function pageCounts( Title $title ) {
-               global $wgRCMaxAge, $wgDisableCounters, $wgMiserMode;
-
+       protected function pageCounts( Title $title ) {
                wfProfileIn( __METHOD__ );
                $id = $title->getArticleID();
+               $config = $this->context->getConfig();
 
                $dbr = wfGetDB( DB_SLAVE );
                $result = array();
 
-               if ( !$wgDisableCounters ) {
+               if ( !$config->get( 'DisableCounters' ) ) {
                        // Number of views
                        $views = (int)$dbr->selectField(
                                'page',
@@ -685,8 +685,8 @@ class InfoAction extends FormlessAction {
                );
                $result['authors'] = $authors;
 
-               // "Recent" threshold defined by $wgRCMaxAge
-               $threshold = $dbr->timestamp( time() - $wgRCMaxAge );
+               // "Recent" threshold defined by RCMaxAge setting
+               $threshold = $dbr->timestamp( time() - $config->get( 'RCMaxAge' ) );
 
                // Recent number of edits
                $edits = (int)$dbr->selectField(
@@ -740,7 +740,7 @@ class InfoAction extends FormlessAction {
                }
 
                // Counts for the number of transclusion links (to/from)
-               if ( $wgMiserMode ) {
+               if ( $config->get( 'MiserMode' ) ) {
                        $result['transclusion']['to'] = 0;
                } else {
                        $result['transclusion']['to'] = (int)$dbr->selectField(
@@ -780,8 +780,6 @@ class InfoAction extends FormlessAction {
         * @return string Html
         */
        protected function getContributors() {
-               global $wgHiddenPrefs;
-
                $contributors = $this->page->getContributors();
                $real_names = array();
                $user_names = array();
@@ -794,9 +792,10 @@ class InfoAction extends FormlessAction {
                                ? SpecialPage::getTitleFor( 'Contributions', $user->getName() )
                                : $user->getUserPage();
 
+                       $hiddenPrefs = $this->context->getConfig()->get( 'HiddenPrefs' );
                        if ( $user->getID() == 0 ) {
                                $anon_ips[] = Linker::link( $page, htmlspecialchars( $user->getName() ) );
-                       } elseif ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) {
+                       } elseif ( !in_array( 'realname', $hiddenPrefs ) && $user->getRealName() ) {
                                $real_names[] = Linker::link( $page, htmlspecialchars( $user->getRealName() ) );
                        } else {
                                $user_names[] = Linker::link( $page, htmlspecialchars( $user->getName() ) );
index 8b2bfaa..a7f1ac3 100644 (file)
@@ -41,26 +41,15 @@ class ProtectAction extends FormlessAction {
        }
 
        public function show() {
+               if ( $this->getContext()->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
+                       $out = $this->getOutput();
+                       $out->addModuleStyles( array(
+                               'mediawiki.ui.input',
+                               'mediawiki.ui.checkbox',
+                       ) );
+               }
 
                $this->page->protect();
        }
 }
 
-/**
- * Handle page unprotection
- *
- * This is a wrapper that will call Article::unprotect().
- *
- * @ingroup Actions
- */
-class UnprotectAction extends ProtectAction {
-
-       public function getName() {
-               return 'unprotect';
-       }
-
-       public function show() {
-
-               $this->page->unprotect();
-       }
-}
index a212915..d0d956e 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright © 2004 Gabriel Wicke <wicke@wikidev.net>
  * http://wikidev.net/
  *
- * Based on HistoryPage and SpecialExport
+ * Based on HistoryAction and SpecialExport
  *
  * 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 Actions
  */
 class RawAction extends FormlessAction {
-       private $mGen;
+       /**
+        * @var bool Does the request include a gen=css|javascript parameter
+        * @deprecated This used to be a string for "css" or "javascript" but
+        * it is no longer used. Setting this parameter results in empty content
+        * being served
+        */
+       private $gen = false;
 
        public function getName() {
                return 'raw';
@@ -48,10 +54,9 @@ class RawAction extends FormlessAction {
        }
 
        function onView() {
-               global $wgSquidMaxage, $wgForcedRawSMaxage;
-
                $this->getOutput()->disable();
                $request = $this->getRequest();
+               $config = $this->context->getConfig();
 
                if ( !$request->checkUrlExtension() ) {
                        return;
@@ -67,12 +72,10 @@ class RawAction extends FormlessAction {
                $smaxage = $request->getIntOrNull( 'smaxage' );
 
                if ( $gen == 'css' || $gen == 'js' ) {
-                       $this->mGen = $gen;
+                       $this->gen = true;
                        if ( $smaxage === null ) {
-                               $smaxage = $wgSquidMaxage;
+                               $smaxage = $config->get( 'SquidMaxage' );
                        }
-               } else {
-                       $this->mGen = false;
                }
 
                $contentType = $this->getContentType();
@@ -81,13 +84,13 @@ class RawAction extends FormlessAction {
                # Note: If using a canonical url for userpage css/js, we send an HTCP purge.
                if ( $smaxage === null ) {
                        if ( $contentType == 'text/css' || $contentType == 'text/javascript' ) {
-                               $smaxage = intval( $wgForcedRawSMaxage );
+                               $smaxage = intval( $config->get( 'ForcedRawSMaxage' ) );
                        } else {
                                $smaxage = 0;
                        }
                }
 
-               $maxage = $request->getInt( 'maxage', $wgSquidMaxage );
+               $maxage = $request->getInt( 'maxage', $config->get( 'SquidMaxage' ) );
 
                $response = $request->response();
 
@@ -131,7 +134,7 @@ class RawAction extends FormlessAction {
                global $wgParser;
 
                # No longer used
-               if ( $this->mGen ) {
+               if ( $this->gen ) {
                        return '';
                }
 
@@ -205,10 +208,11 @@ class RawAction extends FormlessAction {
                switch ( $this->getRequest()->getText( 'direction' ) ) {
                        case 'next':
                                # output next revision, or nothing if there isn't one
+                               $nextid = 0;
                                if ( $oldid ) {
-                                       $oldid = $this->getTitle()->getNextRevisionID( $oldid );
+                                       $nextid = $this->getTitle()->getNextRevisionID( $oldid );
                                }
-                               $oldid = $oldid ? $oldid : -1;
+                               $oldid = $nextid ?: -1;
                                break;
                        case 'prev':
                                # output previous revision, or nothing if there isn't one
@@ -216,8 +220,8 @@ class RawAction extends FormlessAction {
                                        # get the current revision so we can get the penultimate one
                                        $oldid = $this->page->getLatest();
                                }
-                               $prev = $this->getTitle()->getPreviousRevisionID( $oldid );
-                               $oldid = $prev ? $prev : -1;
+                               $previd = $this->getTitle()->getPreviousRevisionID( $oldid );
+                               $oldid = $previd ?: -1;
                                break;
                        case 'cur':
                                $oldid = 0;
@@ -252,40 +256,3 @@ class RawAction extends FormlessAction {
                return $ctype;
        }
 }
-
-/**
- * Backward compatibility for extensions
- *
- * @deprecated since 1.19
- */
-class RawPage extends RawAction {
-       public $mOldId;
-
-       /**
-        * @param Page $page
-        * @param WebRequest|bool $request The WebRequest (default: false).
-        */
-       function __construct( Page $page, $request = false ) {
-               wfDeprecated( __CLASS__, '1.19' );
-               parent::__construct( $page );
-
-               if ( $request !== false ) {
-                       $context = new DerivativeContext( $this->getContext() );
-                       $context->setRequest( $request );
-                       $this->context = $context;
-               }
-       }
-
-       public function view() {
-               $this->onView();
-       }
-
-       public function getOldId() {
-               # Some extensions like to set $mOldId
-               if ( $this->mOldId !== null ) {
-                       return $this->mOldId;
-               }
-
-               return parent::getOldId();
-       }
-}
index 92428cf..6481630 100644 (file)
  */
 
 /**
- * Dummy class for pages not in NS_FILE
- *
- * @ingroup Actions
- */
-class RevertAction extends Action {
-
-       public function getName() {
-               return 'revert';
-       }
-
-       public function show() {
-               $this->getOutput()->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
-       }
-
-       public function execute() {
-       }
-}
-
-/**
- * Class for pages in NS_FILE
+ * File reversion user interface
  *
  * @ingroup Actions
  */
-class RevertFileAction extends FormAction {
+class RevertAction extends FormAction {
        /**
         * @var OldLocalFile
         */
@@ -62,6 +43,9 @@ class RevertFileAction extends FormAction {
        }
 
        protected function checkCanExecute( User $user ) {
+               if ( $this->getTitle()->getNamespace() !== NS_FILE ) {
+                       throw new ErrorPageError( $this->msg( 'nosuchaction' ), $this->msg( 'nosuchactiontext' ) );
+               }
                parent::checkCanExecute( $user );
 
                $oldimage = $this->getRequest()->getText( 'oldimage' );
index 617f1c9..76d70d7 100644 (file)
@@ -39,6 +39,7 @@ class RollbackAction extends FormlessAction {
                $details = null;
 
                $request = $this->getRequest();
+               $user = $this->getUser();
 
                $result = $this->page->doRollback(
                        $request->getVal( 'from' ),
@@ -97,6 +98,11 @@ class RollbackAction extends FormlessAction {
                $new = Linker::revUserTools( $target );
                $this->getOutput()->addHTML( $this->msg( 'rollback-success' )->rawParams( $old, $new )
                        ->parseAsBlock() );
+
+               if ( $user->getBoolOption( 'watchrollback' ) ) {
+                       $user->addWatch( $this->page->getTitle(), WatchedItem::IGNORE_USER_RIGHTS );
+               }
+
                $this->getOutput()->returnToMain( false, $this->getTitle() );
 
                if ( !$request->getBool( 'hidediff', false ) &&
diff --git a/includes/actions/SubmitAction.php b/includes/actions/SubmitAction.php
new file mode 100644 (file)
index 0000000..fae49f6
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Wrapper for EditAction; sets the session cookie.
+ *
+ * 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
+ *
+ * @file
+ * @ingroup Actions
+ */
+
+/**
+ * This is the same as EditAction; except that it sets the session cookie.
+ *
+ * @ingroup Actions
+ */
+class SubmitAction extends EditAction {
+
+       public function getName() {
+               return 'submit';
+       }
+
+       public function show() {
+               if ( session_id() === '' ) {
+                       // Send a cookie so anons get talk message notifications
+                       wfSetupSession();
+               }
+
+               parent::show();
+       }
+}
diff --git a/includes/actions/UnprotectAction.php b/includes/actions/UnprotectAction.php
new file mode 100644 (file)
index 0000000..bc28c8e
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * action=unprotect handler
+ *
+ * Copyright © 2012 Timo Tijhof
+ *
+ * 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
+ *
+ * @file
+ * @ingroup Actions
+ * @author Timo Tijhof
+ */
+
+/**
+ * Handle page unprotection
+ *
+ * This is a wrapper that will call Article::unprotect().
+ *
+ * @ingroup Actions
+ */
+class UnprotectAction extends ProtectAction {
+
+       public function getName() {
+               return 'unprotect';
+       }
+
+       public function show() {
+
+               $this->page->unprotect();
+       }
+}
diff --git a/includes/actions/UnwatchAction.php b/includes/actions/UnwatchAction.php
new file mode 100644 (file)
index 0000000..e2e5a1d
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Performs the unwatch actions on a page
+ *
+ * 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
+ *
+ * @file
+ * @ingroup Actions
+ */
+
+/**
+ * Page removal from a user's watchlist
+ *
+ * @ingroup Actions
+ */
+class UnwatchAction extends WatchAction {
+
+       public function getName() {
+               return 'unwatch';
+       }
+
+       protected function getDescription() {
+               return $this->msg( 'removewatch' )->escaped();
+       }
+
+       public function onSubmit( $data ) {
+               wfProfileIn( __METHOD__ );
+               self::doUnwatch( $this->getTitle(), $this->getUser() );
+               wfProfileOut( __METHOD__ );
+
+               return true;
+       }
+
+       protected function alterForm( HTMLForm $form ) {
+               $form->setSubmitTextMsg( 'confirm-unwatch-button' );
+       }
+
+       protected function preText() {
+               return $this->msg( 'confirm-unwatch-top' )->parse();
+       }
+
+       public function onSuccess() {
+               $this->getOutput()->addWikiMsg( 'removedwatchtext', $this->getTitle()->getPrefixedText() );
+       }
+}
index 2c7502e..8c9a46a 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Performs the watch and unwatch actions on a page
+ * Performs the watch actions on a page
  *
  * 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
@@ -82,17 +82,10 @@ class WatchAction extends FormAction {
        protected function checkCanExecute( User $user ) {
                // Must be logged in
                if ( $user->isAnon() ) {
-                       $loginreqlink = Linker::linkKnown(
-                               SpecialPage::getTitleFor( 'Userlogin' ),
-                               $this->msg( 'loginreqlink' )->escaped(),
-                               array(),
-                               array( 'returnto' => $this->getPageTitle(), 'returntoquery' => 'action=' . $this->getName() )
-                       );
-                       $reasonMsg = $this->msg( 'watchlistanontext' )->rawParams( $loginreqlink );
-                       throw new UserNotLoggedIn( $reasonMsg, 'watchnologin' );
+                       throw new UserNotLoggedIn( 'watchlistanontext', 'watchnologin' );
                }
 
-               return parent::checkCanExecute( $user );
+               parent::checkCanExecute( $user );
        }
 
        /**
@@ -185,7 +178,7 @@ class WatchAction extends FormAction {
                if ( $action != 'unwatch' ) {
                        $action = 'watch';
                }
-               $salt = array( $action, $title->getDBkey() );
+               $salt = array( $action, $title->getPrefixedDBkey() );
 
                // This token stronger salted and not compatible with ApiWatch
                // It's title/action specific because index.php is GET and API is POST
@@ -217,39 +210,3 @@ class WatchAction extends FormAction {
                $this->getOutput()->addWikiMsg( 'addedwatchtext', $this->getTitle()->getPrefixedText() );
        }
 }
-
-/**
- * Page removal from a user's watchlist
- *
- * @ingroup Actions
- */
-class UnwatchAction extends WatchAction {
-
-       public function getName() {
-               return 'unwatch';
-       }
-
-       protected function getDescription() {
-               return $this->msg( 'removewatch' )->escaped();
-       }
-
-       public function onSubmit( $data ) {
-               wfProfileIn( __METHOD__ );
-               self::doUnwatch( $this->getTitle(), $this->getUser() );
-               wfProfileOut( __METHOD__ );
-
-               return true;
-       }
-
-       protected function alterForm( HTMLForm $form ) {
-               $form->setSubmitTextMsg( 'confirm-unwatch-button' );
-       }
-
-       protected function preText() {
-               return $this->msg( 'confirm-unwatch-top' )->parse();
-       }
-
-       public function onSuccess() {
-               $this->getOutput()->addWikiMsg( 'removedwatchtext', $this->getTitle()->getPrefixedText() );
-       }
-}
index d221799..eafa9cc 100644 (file)
@@ -109,9 +109,11 @@ abstract class ApiBase extends ContextSource {
                }
        }
 
-       /*****************************************************************************
-        * ABSTRACT METHODS                                                          *
-        *****************************************************************************/
+
+       /************************************************************************//**
+        * @name   Methods to implement
+        * @{
+        */
 
        /**
         * Evaluates the parameters, performs the requested query, and sets up
@@ -132,438 +134,232 @@ abstract class ApiBase extends ContextSource {
        abstract public function execute();
 
        /**
-        * Returns a string that identifies the version of the extending class.
-        * Typically includes the class name, the svn revision, timestamp, and
-        * last author. Usually done with SVN's Id keyword
-        * @return string
-        * @deprecated since 1.21, version string is no longer supported
+        * Get the module manager, or null if this module has no sub-modules
+        * @since 1.21
+        * @return ApiModuleManager
         */
-       public function getVersion() {
-               wfDeprecated( __METHOD__, '1.21' );
+       public function getModuleManager() {
+               return null;
+       }
 
-               return '';
+       /**
+        * If the module may only be used with a certain format module,
+        * it should override this method to return an instance of that formatter.
+        * A value of null means the default format will be used.
+        * @return mixed Instance of a derived class of ApiFormatBase, or null
+        */
+       public function getCustomPrinter() {
+               return null;
        }
 
        /**
-        * Get the name of the module being executed by this instance
-        * @return string
+        * Returns the description string for this module
+        * @return string|array
         */
-       public function getModuleName() {
-               return $this->mModuleName;
+       protected function getDescription() {
+               return false;
        }
 
        /**
-        * Get the module manager, or null if this module has no sub-modules
-        * @since 1.21
-        * @return ApiModuleManager
+        * Returns usage examples for this module. Return false if no examples are available.
+        * @return bool|string|array
         */
-       public function getModuleManager() {
-               return null;
+       protected function getExamples() {
+               return false;
        }
 
        /**
-        * Get parameter prefix (usually two letters or an empty string).
-        * @return string
+        * @return bool|string|array Returns a false if the module has no help URL,
+        *   else returns a (array of) string
         */
-       public function getModulePrefix() {
-               return $this->mModulePrefix;
+       public function getHelpUrls() {
+               return false;
        }
 
        /**
-        * Get the name of the module as shown in the profiler log
+        * Returns an array of allowed parameters (parameter name) => (default
+        * value) or (parameter name) => (array with PARAM_* constants as keys)
+        * Don't call this function directly: use getFinalParams() to allow
+        * hooks to modify parameters as needed.
         *
-        * @param DatabaseBase|bool $db
+        * Some derived classes may choose to handle an integer $flags parameter
+        * in the overriding methods. Callers of this method can pass zero or
+        * more OR-ed flags like GET_VALUES_FOR_HELP.
         *
-        * @return string
+        * @return array|bool
         */
-       public function getModuleProfileName( $db = false ) {
-               if ( $db ) {
-                       return 'API:' . $this->mModuleName . '-DB';
-               }
-
-               return 'API:' . $this->mModuleName;
+       protected function getAllowedParams( /* $flags = 0 */ ) {
+               // int $flags is not declared because it causes "Strict standards"
+               // warning. Most derived classes do not implement it.
+               return false;
        }
 
        /**
-        * Get the main module
-        * @return ApiMain
+        * Returns an array of parameter descriptions.
+        * Don't call this function directly: use getFinalParamDescription() to
+        * allow hooks to modify descriptions as needed.
+        * @return array|bool False on no parameter descriptions
         */
-       public function getMain() {
-               return $this->mMainModule;
+       protected function getParamDescription() {
+               return false;
        }
 
        /**
-        * Returns true if this module is the main module ($this === $this->mMainModule),
-        * false otherwise.
+        * Indicates if this module needs maxlag to be checked
         * @return bool
         */
-       public function isMain() {
-               return $this === $this->mMainModule;
+       public function shouldCheckMaxlag() {
+               return true;
        }
 
        /**
-        * Get the result object
-        * @return ApiResult
+        * Indicates whether this module requires read rights
+        * @return bool
         */
-       public function getResult() {
-               // Main module has getResult() method overridden
-               // Safety - avoid infinite loop:
-               if ( $this->isMain() ) {
-                       ApiBase::dieDebug( __METHOD__, 'base method was called on main module. ' );
-               }
-
-               return $this->getMain()->getResult();
+       public function isReadMode() {
+               return true;
        }
 
        /**
-        * Get the result data array (read-only)
-        * @return array
+        * Indicates whether this module requires write mode
+        * @return bool
         */
-       public function getResultData() {
-               return $this->getResult()->getData();
+       public function isWriteMode() {
+               return false;
        }
 
        /**
-        * Set warning section for this module. Users should monitor this
-        * section to notice any changes in API. Multiple calls to this
-        * function will result in the warning messages being separated by
-        * newlines
-        * @param string $warning Warning message
+        * Indicates whether this module must be called with a POST request
+        * @return bool
         */
-       public function setWarning( $warning ) {
-               $result = $this->getResult();
-               $data = $result->getData();
-               $moduleName = $this->getModuleName();
-               if ( isset( $data['warnings'][$moduleName] ) ) {
-                       // Don't add duplicate warnings
-                       $oldWarning = $data['warnings'][$moduleName]['*'];
-                       $warnPos = strpos( $oldWarning, $warning );
-                       // If $warning was found in $oldWarning, check if it starts at 0 or after "\n"
-                       if ( $warnPos !== false && ( $warnPos === 0 || $oldWarning[$warnPos - 1] === "\n" ) ) {
-                               // Check if $warning is followed by "\n" or the end of the $oldWarning
-                               $warnPos += strlen( $warning );
-                               if ( strlen( $oldWarning ) <= $warnPos || $oldWarning[$warnPos] === "\n" ) {
-                                       return;
-                               }
-                       }
-                       // If there is a warning already, append it to the existing one
-                       $warning = "$oldWarning\n$warning";
-               }
-               $msg = array();
-               ApiResult::setContent( $msg, $warning );
-               $result->disableSizeCheck();
-               $result->addValue( 'warnings', $moduleName,
-                       $msg, ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP );
-               $result->enableSizeCheck();
+       public function mustBePosted() {
+               return $this->needsToken() !== false;
        }
 
        /**
-        * If the module may only be used with a certain format module,
-        * it should override this method to return an instance of that formatter.
-        * A value of null means the default format will be used.
-        * @return mixed Instance of a derived class of ApiFormatBase, or null
+        * Returns the token type this module requires in order to execute.
+        *
+        * Modules are strongly encouraged to use the core 'csrf' type unless they
+        * have specialized security needs. If the token type is not one of the
+        * core types, you must use the ApiQueryTokensRegisterTypes hook to
+        * register it.
+        *
+        * Returning a non-falsey value here will cause self::getFinalParams() to
+        * return a required string 'token' parameter and
+        * self::getFinalParamDescription() to ensure there is standardized
+        * documentation for it. Also, self::mustBePosted() must return true when
+        * tokens are used.
+        *
+        * In previous versions of MediaWiki, true was a valid return value.
+        * Returning true will generate errors indicating that the API module needs
+        * updating.
+        *
+        * @return string|false
         */
-       public function getCustomPrinter() {
-               return null;
+       public function needsToken() {
+               return false;
        }
 
        /**
-        * Generates help message for this module, or false if there is no description
-        * @return string|bool
+        * Fetch the salt used in the Web UI corresponding to this module.
+        *
+        * Only override this if the Web UI uses a token with a non-constant salt.
+        *
+        * @since 1.24
+        * @param array $params All supplied parameters for the module
+        * @return string|array|null
         */
-       public function makeHelpMsg() {
-               static $lnPrfx = "\n  ";
-
-               $msg = $this->getFinalDescription();
-
-               if ( $msg !== false ) {
-
-                       if ( !is_array( $msg ) ) {
-                               $msg = array(
-                                       $msg
-                               );
-                       }
-                       $msg = $lnPrfx . implode( $lnPrfx, $msg ) . "\n";
-
-                       $msg .= $this->makeHelpArrayToString( $lnPrfx, false, $this->getHelpUrls() );
-
-                       if ( $this->isReadMode() ) {
-                               $msg .= "\nThis module requires read rights";
-                       }
-                       if ( $this->isWriteMode() ) {
-                               $msg .= "\nThis module requires write rights";
-                       }
-                       if ( $this->mustBePosted() ) {
-                               $msg .= "\nThis module only accepts POST requests";
-                       }
-                       if ( $this->isReadMode() || $this->isWriteMode() ||
-                               $this->mustBePosted()
-                       ) {
-                               $msg .= "\n";
-                       }
+       protected function getWebUITokenSalt( array $params ) {
+               return null;
+       }
 
-                       // Parameters
-                       $paramsMsg = $this->makeHelpMsgParameters();
-                       if ( $paramsMsg !== false ) {
-                               $msg .= "Parameters:\n$paramsMsg";
-                       }
+       /**@}*/
 
-                       $examples = $this->getExamples();
-                       if ( $examples ) {
-                               if ( !is_array( $examples ) ) {
-                                       $examples = array(
-                                               $examples
-                                       );
-                               }
-                               $msg .= "Example" . ( count( $examples ) > 1 ? 's' : '' ) . ":\n";
-                               foreach ( $examples as $k => $v ) {
-                                       if ( is_numeric( $k ) ) {
-                                               $msg .= "  $v\n";
-                                       } else {
-                                               if ( is_array( $v ) ) {
-                                                       $msgExample = implode( "\n", array_map( array( $this, 'indentExampleText' ), $v ) );
-                                               } else {
-                                                       $msgExample = "  $v";
-                                               }
-                                               $msgExample .= ":";
-                                               $msg .= wordwrap( $msgExample, 100, "\n" ) . "\n    $k\n";
-                                       }
-                               }
-                       }
-               }
-
-               return $msg;
-       }
+       /************************************************************************//**
+        * @name   Data access methods
+        * @{
+        */
 
        /**
-        * @param string $item
+        * Get the name of the module being executed by this instance
         * @return string
         */
-       private function indentExampleText( $item ) {
-               return "  " . $item;
+       public function getModuleName() {
+               return $this->mModuleName;
        }
 
        /**
-        * @param string $prefix Text to split output items
-        * @param string $title What is being output
-        * @param string|array $input
+        * Get parameter prefix (usually two letters or an empty string).
         * @return string
         */
-       protected function makeHelpArrayToString( $prefix, $title, $input ) {
-               if ( $input === false ) {
-                       return '';
-               }
-               if ( !is_array( $input ) ) {
-                       $input = array( $input );
-               }
-
-               if ( count( $input ) > 0 ) {
-                       if ( $title ) {
-                               $msg = $title . ( count( $input ) > 1 ? 's' : '' ) . ":\n  ";
-                       } else {
-                               $msg = '  ';
-                       }
-                       $msg .= implode( $prefix, $input ) . "\n";
-
-                       return $msg;
-               }
-
-               return '';
+       public function getModulePrefix() {
+               return $this->mModulePrefix;
        }
 
        /**
-        * Generates the parameter descriptions for this module, to be displayed in the
-        * module's help.
-        * @return string|bool
+        * Get the main module
+        * @return ApiMain
         */
-       public function makeHelpMsgParameters() {
-               $params = $this->getFinalParams( ApiBase::GET_VALUES_FOR_HELP );
-               if ( $params ) {
-
-                       $paramsDescription = $this->getFinalParamDescription();
-                       $msg = '';
-                       $paramPrefix = "\n" . str_repeat( ' ', 24 );
-                       $descWordwrap = "\n" . str_repeat( ' ', 28 );
-                       foreach ( $params as $paramName => $paramSettings ) {
-                               $desc = isset( $paramsDescription[$paramName] ) ? $paramsDescription[$paramName] : '';
-                               if ( is_array( $desc ) ) {
-                                       $desc = implode( $paramPrefix, $desc );
-                               }
-
-                               //handle shorthand
-                               if ( !is_array( $paramSettings ) ) {
-                                       $paramSettings = array(
-                                               self::PARAM_DFLT => $paramSettings,
-                                       );
-                               }
-
-                               //handle missing type
-                               if ( !isset( $paramSettings[ApiBase::PARAM_TYPE] ) ) {
-                                       $dflt = isset( $paramSettings[ApiBase::PARAM_DFLT] )
-                                               ? $paramSettings[ApiBase::PARAM_DFLT]
-                                               : null;
-                                       if ( is_bool( $dflt ) ) {
-                                               $paramSettings[ApiBase::PARAM_TYPE] = 'boolean';
-                                       } elseif ( is_string( $dflt ) || is_null( $dflt ) ) {
-                                               $paramSettings[ApiBase::PARAM_TYPE] = 'string';
-                                       } elseif ( is_int( $dflt ) ) {
-                                               $paramSettings[ApiBase::PARAM_TYPE] = 'integer';
-                                       }
-                               }
-
-                               if ( isset( $paramSettings[self::PARAM_DEPRECATED] )
-                                       && $paramSettings[self::PARAM_DEPRECATED]
-                               ) {
-                                       $desc = "DEPRECATED! $desc";
-                               }
-
-                               if ( isset( $paramSettings[self::PARAM_REQUIRED] )
-                                       && $paramSettings[self::PARAM_REQUIRED]
-                               ) {
-                                       $desc .= $paramPrefix . "This parameter is required";
-                               }
-
-                               $type = isset( $paramSettings[self::PARAM_TYPE] )
-                                       ? $paramSettings[self::PARAM_TYPE]
-                                       : null;
-                               if ( isset( $type ) ) {
-                                       $hintPipeSeparated = true;
-                                       $multi = isset( $paramSettings[self::PARAM_ISMULTI] )
-                                               ? $paramSettings[self::PARAM_ISMULTI]
-                                               : false;
-                                       if ( $multi ) {
-                                               $prompt = 'Values (separate with \'|\'): ';
-                                       } else {
-                                               $prompt = 'One value: ';
-                                       }
-
-                                       if ( is_array( $type ) ) {
-                                               $choices = array();
-                                               $nothingPrompt = '';
-                                               foreach ( $type as $t ) {
-                                                       if ( $t === '' ) {
-                                                               $nothingPrompt = 'Can be empty, or ';
-                                                       } else {
-                                                               $choices[] = $t;
-                                                       }
-                                               }
-                                               $desc .= $paramPrefix . $nothingPrompt . $prompt;
-                                               $choicesstring = implode( ', ', $choices );
-                                               $desc .= wordwrap( $choicesstring, 100, $descWordwrap );
-                                               $hintPipeSeparated = false;
-                                       } else {
-                                               switch ( $type ) {
-                                                       case 'namespace':
-                                                               // Special handling because namespaces are
-                                                               // type-limited, yet they are not given
-                                                               $desc .= $paramPrefix . $prompt;
-                                                               $desc .= wordwrap( implode( ', ', MWNamespace::getValidNamespaces() ),
-                                                                       100, $descWordwrap );
-                                                               $hintPipeSeparated = false;
-                                                               break;
-                                                       case 'limit':
-                                                               $desc .= $paramPrefix . "No more than {$paramSettings[self::PARAM_MAX]}";
-                                                               if ( isset( $paramSettings[self::PARAM_MAX2] ) ) {
-                                                                       $desc .= " ({$paramSettings[self::PARAM_MAX2]} for bots)";
-                                                               }
-                                                               $desc .= ' allowed';
-                                                               break;
-                                                       case 'integer':
-                                                               $s = $multi ? 's' : '';
-                                                               $hasMin = isset( $paramSettings[self::PARAM_MIN] );
-                                                               $hasMax = isset( $paramSettings[self::PARAM_MAX] );
-                                                               if ( $hasMin || $hasMax ) {
-                                                                       if ( !$hasMax ) {
-                                                                               $intRangeStr = "The value$s must be no less than " .
-                                                                                       "{$paramSettings[self::PARAM_MIN]}";
-                                                                       } elseif ( !$hasMin ) {
-                                                                               $intRangeStr = "The value$s must be no more than " .
-                                                                                       "{$paramSettings[self::PARAM_MAX]}";
-                                                                       } else {
-                                                                               $intRangeStr = "The value$s must be between " .
-                                                                                       "{$paramSettings[self::PARAM_MIN]} and {$paramSettings[self::PARAM_MAX]}";
-                                                                       }
-
-                                                                       $desc .= $paramPrefix . $intRangeStr;
-                                                               }
-                                                               break;
-                                                       case 'upload':
-                                                               $desc .= $paramPrefix . "Must be posted as a file upload using multipart/form-data";
-                                                               break;
-                                               }
-                                       }
-
-                                       if ( $multi ) {
-                                               if ( $hintPipeSeparated ) {
-                                                       $desc .= $paramPrefix . "Separate values with '|'";
-                                               }
-
-                                               $isArray = is_array( $type );
-                                               if ( !$isArray
-                                                       || $isArray && count( $type ) > self::LIMIT_SML1
-                                               ) {
-                                                       $desc .= $paramPrefix . "Maximum number of values " .
-                                                               self::LIMIT_SML1 . " (" . self::LIMIT_SML2 . " for bots)";
-                                               }
-                                       }
-                               }
-
-                               $default = isset( $paramSettings[self::PARAM_DFLT] ) ? $paramSettings[self::PARAM_DFLT] : null;
-                               if ( !is_null( $default ) && $default !== false ) {
-                                       $desc .= $paramPrefix . "Default: $default";
-                               }
-
-                               $msg .= sprintf( "  %-19s - %s\n", $this->encodeParamName( $paramName ), $desc );
-                       }
-
-                       return $msg;
-               }
+       public function getMain() {
+               return $this->mMainModule;
+       }
 
-               return false;
+       /**
+        * Returns true if this module is the main module ($this === $this->mMainModule),
+        * false otherwise.
+        * @return bool
+        */
+       public function isMain() {
+               return $this === $this->mMainModule;
        }
 
        /**
-        * Returns the description string for this module
-        * @return string|array
+        * Get the result object
+        * @return ApiResult
         */
-       protected function getDescription() {
-               return false;
+       public function getResult() {
+               // Main module has getResult() method overridden
+               // Safety - avoid infinite loop:
+               if ( $this->isMain() ) {
+                       ApiBase::dieDebug( __METHOD__, 'base method was called on main module. ' );
+               }
+
+               return $this->getMain()->getResult();
        }
 
        /**
-        * Returns usage examples for this module. Return false if no examples are available.
-        * @return bool|string|array
+        * Get the result data array (read-only)
+        * @return array
         */
-       protected function getExamples() {
-               return false;
+       public function getResultData() {
+               return $this->getResult()->getData();
        }
 
        /**
-        * Returns an array of allowed parameters (parameter name) => (default
-        * value) or (parameter name) => (array with PARAM_* constants as keys)
-        * Don't call this function directly: use getFinalParams() to allow
-        * hooks to modify parameters as needed.
-        *
-        * Some derived classes may choose to handle an integer $flags parameter
-        * in the overriding methods. Callers of this method can pass zero or
-        * more OR-ed flags like GET_VALUES_FOR_HELP.
-        *
-        * @return array|bool
+        * Gets a default slave database connection object
+        * @return DatabaseBase
         */
-       protected function getAllowedParams( /* $flags = 0 */ ) {
-               // int $flags is not declared because it causes "Strict standards"
-               // warning. Most derived classes do not implement it.
-               return false;
+       protected function getDB() {
+               if ( !isset( $this->mSlaveDB ) ) {
+                       $this->profileDBIn();
+                       $this->mSlaveDB = wfGetDB( DB_SLAVE, 'api' );
+                       $this->profileDBOut();
+               }
+
+               return $this->mSlaveDB;
        }
 
        /**
-        * Returns an array of parameter descriptions.
-        * Don't call this function directly: use getFinalParamDescription() to
-        * allow hooks to modify descriptions as needed.
-        * @return array|bool False on no parameter descriptions
+        * Get final module description, after hooks have had a chance to tweak it as
+        * needed.
+        *
+        * @return array|bool False on no parameters
         */
-       protected function getParamDescription() {
-               return false;
+       public function getFinalDescription() {
+               $desc = $this->getDescription();
+               wfRunHooks( 'APIGetDescription', array( &$this, &$desc ) );
+
+               return $desc;
        }
 
        /**
@@ -576,6 +372,14 @@ abstract class ApiBase extends ContextSource {
         */
        public function getFinalParams( $flags = 0 ) {
                $params = $this->getAllowedParams( $flags );
+
+               if ( $this->needsToken() ) {
+                       $params['token'] = array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => true,
+                       );
+               }
+
                wfRunHooks( 'APIGetAllowedParams', array( &$this, &$params, $flags ) );
 
                return $params;
@@ -589,72 +393,33 @@ abstract class ApiBase extends ContextSource {
         */
        public function getFinalParamDescription() {
                $desc = $this->getParamDescription();
-               wfRunHooks( 'APIGetParamDescription', array( &$this, &$desc ) );
-
-               return $desc;
-       }
-
-       /**
-        * Returns possible properties in the result, grouped by the value of the prop parameter
-        * that shows them.
-        *
-        * Properties that are shown always are in a group with empty string as a key.
-        * Properties that can be shown by several values of prop are included multiple times.
-        * If some properties are part of a list and some are on the root object (see ApiQueryQueryPage),
-        * those on the root object are under the key PROP_ROOT.
-        * The array can also contain a boolean under the key PROP_LIST,
-        * indicating whether the result is a list.
-        *
-        * Don't call this function directly: use getFinalResultProperties() to
-        * allow hooks to modify descriptions as needed.
-        *
-        * @return array|bool False on no properties
-        */
-       protected function getResultProperties() {
-               return false;
-       }
-
-       /**
-        * Get final possible result properties, after hooks have had a chance to tweak it as
-        * needed.
-        *
-        * @return array
-        */
-       public function getFinalResultProperties() {
-               $properties = $this->getResultProperties();
-               wfRunHooks( 'APIGetResultProperties', array( $this, &$properties ) );
-
-               return $properties;
-       }
 
-       /**
-        * Add token properties to the array used by getResultProperties,
-        * based on a token functions mapping.
-        * @param array $props
-        * @param array $tokenFunctions
-        */
-       protected static function addTokenProperties( &$props, $tokenFunctions ) {
-               foreach ( array_keys( $tokenFunctions ) as $token ) {
-                       $props[''][$token . 'token'] = array(
-                               ApiBase::PROP_TYPE => 'string',
-                               ApiBase::PROP_NULLABLE => true
+               $tokenType = $this->needsToken();
+               if ( $tokenType ) {
+                       if ( !isset( $desc['token'] ) ) {
+                               $desc['token'] = array();
+                       } elseif ( !is_array( $desc['token'] ) ) {
+                               // We ignore a plain-string token, because it's probably an
+                               // extension that is supplying the string for BC.
+                               $desc['token'] = array();
+                       }
+                       array_unshift( $desc['token'],
+                               "A '$tokenType' token retrieved from action=query&meta=tokens"
                        );
                }
-       }
 
-       /**
-        * Get final module description, after hooks have had a chance to tweak it as
-        * needed.
-        *
-        * @return array|bool False on no parameters
-        */
-       public function getFinalDescription() {
-               $desc = $this->getDescription();
-               wfRunHooks( 'APIGetDescription', array( &$this, &$desc ) );
+               wfRunHooks( 'APIGetParamDescription', array( &$this, &$desc ) );
 
                return $desc;
        }
 
+       /**@}*/
+
+       /************************************************************************//**
+        * @name   Parameter handling
+        * @{
+        */
+
        /**
         * This method mangles parameter name based on the prefix supplied to the constructor.
         * Override this method to change parameter name during runtime
@@ -708,8 +473,6 @@ abstract class ApiBase extends ContextSource {
        /**
         * Die if none or more than one of a certain set of parameters is set and not false.
         *
-        * Call getRequireOnlyOneParameterErrorMessages() to get a list of possible errors.
-        *
         * @param array $params User provided set of parameters, as from $this->extractRequestParams()
         * @param string $required,... Names of parameters of which exactly one must be set
         */
@@ -733,33 +496,9 @@ abstract class ApiBase extends ContextSource {
                }
        }
 
-       /**
-        * Generates the possible errors requireOnlyOneParameter() can die with
-        *
-        * @param array $params
-        * @return array
-        */
-       public function getRequireOnlyOneParameterErrorMessages( $params ) {
-               $p = $this->getModulePrefix();
-               $params = implode( ", {$p}", $params );
-
-               return array(
-                       array(
-                               'code' => "{$p}missingparam",
-                               'info' => "One of the parameters {$p}{$params} is required"
-                       ),
-                       array(
-                               'code' => "{$p}invalidparammix",
-                               'info' => "The parameters {$p}{$params} can not be used together"
-                       )
-               );
-       }
-
        /**
         * Die if more than one of a certain set of parameters is set and not false.
         *
-        * Call getRequireMaxOneParameterErrorMessages() to get a list of possible errors.
-        *
         * @param array $params User provided set of parameters, as from $this->extractRequestParams()
         * @param string $required,... Names of parameters of which at most one must be set
         */
@@ -779,29 +518,9 @@ abstract class ApiBase extends ContextSource {
                }
        }
 
-       /**
-        * Generates the possible error requireMaxOneParameter() can die with
-        *
-        * @param array $params
-        * @return array
-        */
-       public function getRequireMaxOneParameterErrorMessages( $params ) {
-               $p = $this->getModulePrefix();
-               $params = implode( ", {$p}", $params );
-
-               return array(
-                       array(
-                               'code' => "{$p}invalidparammix",
-                               'info' => "The parameters {$p}{$params} can not be used together"
-                       )
-               );
-       }
-
        /**
         * Die if none of a certain set of parameters is set and not false.
         *
-        * Call getRequireAtLeastOneParameterErrorMessages() to get a list of possible errors.
-        *
         * @since 1.23
         * @param array $params User provided set of parameters, as from $this->extractRequestParams()
         * @param string $required,... Names of parameters of which at least one must be set
@@ -823,30 +542,19 @@ abstract class ApiBase extends ContextSource {
        }
 
        /**
-        * Generates the possible errors requireAtLeastOneParameter() can die with
+        * Callback function used in requireOnlyOneParameter to check whether required parameters are set
         *
-        * @since 1.23
-        * @param array $params Array of parameter key names
-        * @return array
+        * @param object $x Parameter to check is not null/false
+        * @return bool
         */
-       public function getRequireAtLeastOneParameterErrorMessages( $params ) {
-               $p = $this->getModulePrefix();
-               $params = implode( ", {$p}", $params );
-
-               return array(
-                       array(
-                               'code' => "{$p}missingparam",
-                               'info' => "At least one of the parameters {$p}{$params} is required",
-                       ),
-               );
+       private function parameterNotEmpty( $x ) {
+               return !is_null( $x ) && $x !== false;
        }
 
        /**
         * Get a WikiPage object from a title or pageid param, if possible.
         * Can die, if no param is set or if the title or page id is not valid.
         *
-        * Call getTitleOrPageIdErrorMessage() to get a list of possible errors.
-        *
         * @param array $params
         * @param bool|string $load Whether load the object's state from the database:
         *        - false: don't load (if the pageid is given, it will still be loaded)
@@ -883,32 +591,6 @@ abstract class ApiBase extends ContextSource {
                return $pageObj;
        }
 
-       /**
-        * Generates the possible error getTitleOrPageId() can die with
-        *
-        * @return array
-        */
-       public function getTitleOrPageIdErrorMessage() {
-               return array_merge(
-                       $this->getRequireOnlyOneParameterErrorMessages( array( 'title', 'pageid' ) ),
-                       array(
-                               array( 'invalidtitle', 'title' ),
-                               array( 'nosuchpageid', 'pageid' ),
-                               array( 'code' => 'pagecannotexist', 'info' => "Namespace doesn't allow actual pages" ),
-                       )
-               );
-       }
-
-       /**
-        * Callback function used in requireOnlyOneParameter to check whether required parameters are set
-        *
-        * @param object $x Parameter to check is not null/false
-        * @return bool
-        */
-       private function parameterNotEmpty( $x ) {
-               return !is_null( $x ) && $x !== false;
-       }
-
        /**
         * Return true if we're to watch the page, false if not, null if no change.
         * @param string $watchlist Valid values: 'watch', 'unwatch', 'preferences', 'nochange'
@@ -950,21 +632,6 @@ abstract class ApiBase extends ContextSource {
                }
        }
 
-       /**
-        * Set a watch (or unwatch) based the based on a watchlist parameter.
-        * @param string $watch Valid values: 'watch', 'unwatch', 'preferences', 'nochange'
-        * @param Title $titleObj The article's title to change
-        * @param string $userOption The user option to consider when $watch=preferences
-        */
-       protected function setWatch( $watch, $titleObj, $userOption = null ) {
-               $value = $this->getWatchlistValue( $watch, $titleObj, $userOption );
-               if ( $value === null ) {
-                       return;
-               }
-
-               WatchAction::doWatchOrUnwatch( $value, $titleObj, $this->getUser() );
-       }
-
        /**
         * Using the settings determine the value for the given parameter
         *
@@ -1058,6 +725,9 @@ abstract class ApiBase extends ContextSource {
                        if ( isset( $value ) && $type == 'namespace' ) {
                                $type = MWNamespace::getValidNamespaces();
                        }
+                       if ( isset( $value ) && $type == 'submodule' ) {
+                               $type = $this->getModuleManager()->getNames( $paramName );
+                       }
                }
 
                if ( isset( $value ) && ( $multi || is_array( $type ) ) ) {
@@ -1189,9 +859,9 @@ abstract class ApiBase extends ContextSource {
         * @param mixed $value The value being parsed
         * @param bool $allowMultiple Can $value contain more than one value
         *  separated by '|'?
-        * @param mixed $allowedValues An array of values to check against. If
+        * @param string[]|null $allowedValues An array of values to check against. If
         *  null, all values are accepted.
-        * @return mixed (allowMultiple ? an_array_of_values : a_single_value)
+        * @return string|string[] (allowMultiple ? an_array_of_values : a_single_value)
         */
        protected function parseMultiValue( $valueName, $value, $allowMultiple, $allowedValues ) {
                if ( trim( $value ) === '' && $allowMultiple ) {
@@ -1257,7 +927,7 @@ abstract class ApiBase extends ContextSource {
         * @param int $botMax Maximum value for sysops/bots
         * @param bool $enforceLimits Whether to enforce (die) if value is outside limits
         */
-       function validateLimit( $paramName, &$value, $min, $max, $botMax = null, $enforceLimits = false ) {
+       protected function validateLimit( $paramName, &$value, $min, $max, $botMax = null, $enforceLimits = false ) {
                if ( !is_null( $min ) && $value < $min ) {
 
                        $msg = $this->encodeParamName( $paramName ) . " may not be less than $min (set to $value)";
@@ -1295,7 +965,7 @@ abstract class ApiBase extends ContextSource {
         * @param string $encParamName Parameter name
         * @return string Validated and normalized parameter
         */
-       function validateTimestamp( $value, $encParamName ) {
+       protected function validateTimestamp( $value, $encParamName ) {
                $unixTimestamp = wfTimestamp( TS_UNIX, $value );
                if ( $unixTimestamp === false ) {
                        $this->dieUsage(
@@ -1307,6 +977,44 @@ abstract class ApiBase extends ContextSource {
                return wfTimestamp( TS_MW, $unixTimestamp );
        }
 
+       /**
+        * Validate the supplied token.
+        *
+        * @since 1.24
+        * @param string $token Supplied token
+        * @param array $params All supplied parameters for the module
+        * @return bool
+        */
+       public final function validateToken( $token, array $params ) {
+               $tokenType = $this->needsToken();
+               $salts = ApiQueryTokens::getTokenTypeSalts();
+               if ( !isset( $salts[$tokenType] ) ) {
+                       throw new MWException(
+                               "Module '{$this->getModuleName()}' tried to use token type '$tokenType' " .
+                                       'without registering it'
+                       );
+               }
+
+               if ( $this->getUser()->matchEditToken(
+                       $token,
+                       $salts[$tokenType],
+                       $this->getRequest()
+               ) ) {
+                       return true;
+               }
+
+               $webUiSalt = $this->getWebUITokenSalt( $params );
+               if ( $webUiSalt !== null && $this->getUser()->matchEditToken(
+                       $token,
+                       $webUiSalt,
+                       $this->getRequest()
+               ) ) {
+                       return true;
+               }
+
+               return false;
+       }
+
        /**
         * Validate and normalize of parameters of type 'user'
         * @param string $value Parameter value
@@ -1321,8 +1029,117 @@ abstract class ApiBase extends ContextSource {
                                "baduser_{$encParamName}"
                        );
                }
-
-               return $title->getText();
+
+               return $title->getText();
+       }
+
+       /**@}*/
+
+       /************************************************************************//**
+        * @name   Utility methods
+        * @{
+        */
+
+       /**
+        * Set a watch (or unwatch) based the based on a watchlist parameter.
+        * @param string $watch Valid values: 'watch', 'unwatch', 'preferences', 'nochange'
+        * @param Title $titleObj The article's title to change
+        * @param string $userOption The user option to consider when $watch=preferences
+        */
+       protected function setWatch( $watch, $titleObj, $userOption = null ) {
+               $value = $this->getWatchlistValue( $watch, $titleObj, $userOption );
+               if ( $value === null ) {
+                       return;
+               }
+
+               WatchAction::doWatchOrUnwatch( $value, $titleObj, $this->getUser() );
+       }
+
+       /**
+        * Truncate an array to a certain length.
+        * @param array $arr Array to truncate
+        * @param int $limit Maximum length
+        * @return bool True if the array was truncated, false otherwise
+        */
+       public static function truncateArray( &$arr, $limit ) {
+               $modified = false;
+               while ( count( $arr ) > $limit ) {
+                       array_pop( $arr );
+                       $modified = true;
+               }
+
+               return $modified;
+       }
+
+       /**
+        * Gets the user for whom to get the watchlist
+        *
+        * @param array $params
+        * @return User
+        */
+       public function getWatchlistUser( $params ) {
+               if ( !is_null( $params['owner'] ) && !is_null( $params['token'] ) ) {
+                       $user = User::newFromName( $params['owner'], false );
+                       if ( !( $user && $user->getId() ) ) {
+                               $this->dieUsage( 'Specified user does not exist', 'bad_wlowner' );
+                       }
+                       $token = $user->getOption( 'watchlisttoken' );
+                       if ( $token == '' || $token != $params['token'] ) {
+                               $this->dieUsage(
+                                       'Incorrect watchlist token provided -- please set a correct token in Special:Preferences',
+                                       'bad_wltoken'
+                               );
+                       }
+               } else {
+                       if ( !$this->getUser()->isLoggedIn() ) {
+                               $this->dieUsage( 'You must be logged-in to have a watchlist', 'notloggedin' );
+                       }
+                       if ( !$this->getUser()->isAllowed( 'viewmywatchlist' ) ) {
+                               $this->dieUsage( 'You don\'t have permission to view your watchlist', 'permissiondenied' );
+                       }
+                       $user = $this->getUser();
+               }
+
+               return $user;
+       }
+
+       /**@}*/
+
+       /************************************************************************//**
+        * @name   Warning and error reporting
+        * @{
+        */
+
+       /**
+        * Set warning section for this module. Users should monitor this
+        * section to notice any changes in API. Multiple calls to this
+        * function will result in the warning messages being separated by
+        * newlines
+        * @param string $warning Warning message
+        */
+       public function setWarning( $warning ) {
+               $result = $this->getResult();
+               $data = $result->getData();
+               $moduleName = $this->getModuleName();
+               if ( isset( $data['warnings'][$moduleName] ) ) {
+                       // Don't add duplicate warnings
+                       $oldWarning = $data['warnings'][$moduleName]['*'];
+                       $warnPos = strpos( $oldWarning, $warning );
+                       // If $warning was found in $oldWarning, check if it starts at 0 or after "\n"
+                       if ( $warnPos !== false && ( $warnPos === 0 || $oldWarning[$warnPos - 1] === "\n" ) ) {
+                               // Check if $warning is followed by "\n" or the end of the $oldWarning
+                               $warnPos += strlen( $warning );
+                               if ( strlen( $oldWarning ) <= $warnPos || $oldWarning[$warnPos] === "\n" ) {
+                                       return;
+                               }
+                       }
+                       // If there is a warning already, append it to the existing one
+                       $warning = "$oldWarning\n$warning";
+               }
+               $msg = array();
+               ApiResult::setContent( $msg, $warning );
+               $result->addValue( 'warnings', $moduleName,
+                       $msg, ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
        }
 
        /**
@@ -1339,22 +1156,6 @@ abstract class ApiBase extends ContextSource {
                $this->setWarning( $msg );
        }
 
-       /**
-        * Truncate an array to a certain length.
-        * @param array $arr Array to truncate
-        * @param int $limit Maximum length
-        * @return bool True if the array was truncated, false otherwise
-        */
-       public static function truncateArray( &$arr, $limit ) {
-               $modified = false;
-               while ( count( $arr ) > $limit ) {
-                       array_pop( $arr );
-                       $modified = true;
-               }
-
-               return $modified;
-       }
-
        /**
         * Throw a UsageException, which will (if uncaught) call the main module's
         * error handler and die with an error message.
@@ -1409,7 +1210,7 @@ abstract class ApiBase extends ContextSource {
                        $msg = wfMessage( $code, $errors[0] );
                }
                if ( isset( ApiBase::$messageMap[$code] ) ) {
-                       // Translate message to code, for backwards compatability
+                       // Translate message to code, for backwards compatibility
                        $code = ApiBase::$messageMap[$code]['code'];
                }
 
@@ -1471,6 +1272,10 @@ abstract class ApiBase extends ContextSource {
                        'code' => 'cantedit',
                        'info' => "You can't protect this page because you can't edit it"
                ),
+               'deleteprotected' => array(
+                       'code' => 'cantedit',
+                       'info' => "You can't delete this page because it has been protected"
+               ),
                'badaccess-group0' => array(
                        'code' => 'permissiondenied',
                        'info' => "Permission denied"
@@ -1866,6 +1671,10 @@ abstract class ApiBase extends ContextSource {
                        'code' => 'undofailure',
                        'info' => 'Undo failed due to conflicting intermediate edits'
                ),
+               'content-not-allowed-here' => array(
+                       'code' => 'contentnotallowedhere',
+                       'info' => 'Content model "$1" is not allowed at title "$2"'
+               ),
 
                // Messages from WikiPage::doEit()
                'edit-hook-aborted' => array(
@@ -1998,209 +1807,313 @@ abstract class ApiBase extends ContextSource {
                        );
                }
 
-               // If the key isn't present, throw an "unknown error"
-               return $this->parseMsg( array( 'unknownerror', $key ) );
-       }
+               // If the key isn't present, throw an "unknown error"
+               return $this->parseMsg( array( 'unknownerror', $key ) );
+       }
+
+       /**
+        * Internal code errors should be reported with this method
+        * @param string $method Method or function name
+        * @param string $message Error message
+        * @throws MWException
+        */
+       protected static function dieDebug( $method, $message ) {
+               throw new MWException( "Internal error in $method: $message" );
+       }
+
+       /**@}*/
+
+       /************************************************************************//**
+        * @name   Help message generation
+        * @{
+        */
+
+       /**
+        * Generates help message for this module, or false if there is no description
+        * @return string|bool
+        */
+       public function makeHelpMsg() {
+               static $lnPrfx = "\n  ";
+
+               $msg = $this->getFinalDescription();
+
+               if ( $msg !== false ) {
+
+                       if ( !is_array( $msg ) ) {
+                               $msg = array(
+                                       $msg
+                               );
+                       }
+                       $msg = $lnPrfx . implode( $lnPrfx, $msg ) . "\n";
+
+                       $msg .= $this->makeHelpArrayToString( $lnPrfx, false, $this->getHelpUrls() );
+
+                       if ( $this->isReadMode() ) {
+                               $msg .= "\nThis module requires read rights";
+                       }
+                       if ( $this->isWriteMode() ) {
+                               $msg .= "\nThis module requires write rights";
+                       }
+                       if ( $this->mustBePosted() ) {
+                               $msg .= "\nThis module only accepts POST requests";
+                       }
+                       if ( $this->isReadMode() || $this->isWriteMode() ||
+                               $this->mustBePosted()
+                       ) {
+                               $msg .= "\n";
+                       }
+
+                       // Parameters
+                       $paramsMsg = $this->makeHelpMsgParameters();
+                       if ( $paramsMsg !== false ) {
+                               $msg .= "Parameters:\n$paramsMsg";
+                       }
+
+                       $examples = $this->getExamples();
+                       if ( $examples ) {
+                               if ( !is_array( $examples ) ) {
+                                       $examples = array(
+                                               $examples
+                                       );
+                               }
+                               $msg .= "Example" . ( count( $examples ) > 1 ? 's' : '' ) . ":\n";
+                               foreach ( $examples as $k => $v ) {
+                                       if ( is_numeric( $k ) ) {
+                                               $msg .= "  $v\n";
+                                       } else {
+                                               if ( is_array( $v ) ) {
+                                                       $msgExample = implode( "\n", array_map( array( $this, 'indentExampleText' ), $v ) );
+                                               } else {
+                                                       $msgExample = "  $v";
+                                               }
+                                               $msgExample .= ":";
+                                               $msg .= wordwrap( $msgExample, 100, "\n" ) . "\n    $k\n";
+                                       }
+                               }
+                       }
+               }
+
+               return $msg;
+       }
+
+       /**
+        * @param string $item
+        * @return string
+        */
+       private function indentExampleText( $item ) {
+               return "  " . $item;
+       }
+
+       /**
+        * @param string $prefix Text to split output items
+        * @param string $title What is being output
+        * @param string|array $input
+        * @return string
+        */
+       protected function makeHelpArrayToString( $prefix, $title, $input ) {
+               if ( $input === false ) {
+                       return '';
+               }
+               if ( !is_array( $input ) ) {
+                       $input = array( $input );
+               }
+
+               if ( count( $input ) > 0 ) {
+                       if ( $title ) {
+                               $msg = $title . ( count( $input ) > 1 ? 's' : '' ) . ":\n  ";
+                       } else {
+                               $msg = '  ';
+                       }
+                       $msg .= implode( $prefix, $input ) . "\n";
+
+                       return $msg;
+               }
+
+               return '';
+       }
+
+       /**
+        * Generates the parameter descriptions for this module, to be displayed in the
+        * module's help.
+        * @return string|bool
+        */
+       public function makeHelpMsgParameters() {
+               $params = $this->getFinalParams( ApiBase::GET_VALUES_FOR_HELP );
+               if ( $params ) {
+
+                       $paramsDescription = $this->getFinalParamDescription();
+                       $msg = '';
+                       $paramPrefix = "\n" . str_repeat( ' ', 24 );
+                       $descWordwrap = "\n" . str_repeat( ' ', 28 );
+                       foreach ( $params as $paramName => $paramSettings ) {
+                               $desc = isset( $paramsDescription[$paramName] ) ? $paramsDescription[$paramName] : '';
+                               if ( is_array( $desc ) ) {
+                                       $desc = implode( $paramPrefix, $desc );
+                               }
+
+                               //handle shorthand
+                               if ( !is_array( $paramSettings ) ) {
+                                       $paramSettings = array(
+                                               self::PARAM_DFLT => $paramSettings,
+                                       );
+                               }
+
+                               //handle missing type
+                               if ( !isset( $paramSettings[ApiBase::PARAM_TYPE] ) ) {
+                                       $dflt = isset( $paramSettings[ApiBase::PARAM_DFLT] )
+                                               ? $paramSettings[ApiBase::PARAM_DFLT]
+                                               : null;
+                                       if ( is_bool( $dflt ) ) {
+                                               $paramSettings[ApiBase::PARAM_TYPE] = 'boolean';
+                                       } elseif ( is_string( $dflt ) || is_null( $dflt ) ) {
+                                               $paramSettings[ApiBase::PARAM_TYPE] = 'string';
+                                       } elseif ( is_int( $dflt ) ) {
+                                               $paramSettings[ApiBase::PARAM_TYPE] = 'integer';
+                                       }
+                               }
+
+                               if ( isset( $paramSettings[self::PARAM_DEPRECATED] )
+                                       && $paramSettings[self::PARAM_DEPRECATED]
+                               ) {
+                                       $desc = "DEPRECATED! $desc";
+                               }
+
+                               if ( isset( $paramSettings[self::PARAM_REQUIRED] )
+                                       && $paramSettings[self::PARAM_REQUIRED]
+                               ) {
+                                       $desc .= $paramPrefix . "This parameter is required";
+                               }
+
+                               $type = isset( $paramSettings[self::PARAM_TYPE] )
+                                       ? $paramSettings[self::PARAM_TYPE]
+                                       : null;
+                               if ( isset( $type ) ) {
+                                       $hintPipeSeparated = true;
+                                       $multi = isset( $paramSettings[self::PARAM_ISMULTI] )
+                                               ? $paramSettings[self::PARAM_ISMULTI]
+                                               : false;
+                                       if ( $multi ) {
+                                               $prompt = 'Values (separate with \'|\'): ';
+                                       } else {
+                                               $prompt = 'One value: ';
+                                       }
+
+                                       if ( $type === 'submodule' ) {
+                                               $type = $this->getModuleManager()->getNames( $paramName );
+                                               sort( $type );
+                                       }
+                                       if ( is_array( $type ) ) {
+                                               $choices = array();
+                                               $nothingPrompt = '';
+                                               foreach ( $type as $t ) {
+                                                       if ( $t === '' ) {
+                                                               $nothingPrompt = 'Can be empty, or ';
+                                                       } else {
+                                                               $choices[] = $t;
+                                                       }
+                                               }
+                                               $desc .= $paramPrefix . $nothingPrompt . $prompt;
+                                               $choicesstring = implode( ', ', $choices );
+                                               $desc .= wordwrap( $choicesstring, 100, $descWordwrap );
+                                               $hintPipeSeparated = false;
+                                       } else {
+                                               switch ( $type ) {
+                                                       case 'namespace':
+                                                               // Special handling because namespaces are
+                                                               // type-limited, yet they are not given
+                                                               $desc .= $paramPrefix . $prompt;
+                                                               $desc .= wordwrap( implode( ', ', MWNamespace::getValidNamespaces() ),
+                                                                       100, $descWordwrap );
+                                                               $hintPipeSeparated = false;
+                                                               break;
+                                                       case 'limit':
+                                                               $desc .= $paramPrefix . "No more than {$paramSettings[self::PARAM_MAX]}";
+                                                               if ( isset( $paramSettings[self::PARAM_MAX2] ) ) {
+                                                                       $desc .= " ({$paramSettings[self::PARAM_MAX2]} for bots)";
+                                                               }
+                                                               $desc .= ' allowed';
+                                                               break;
+                                                       case 'integer':
+                                                               $s = $multi ? 's' : '';
+                                                               $hasMin = isset( $paramSettings[self::PARAM_MIN] );
+                                                               $hasMax = isset( $paramSettings[self::PARAM_MAX] );
+                                                               if ( $hasMin || $hasMax ) {
+                                                                       if ( !$hasMax ) {
+                                                                               $intRangeStr = "The value$s must be no less than " .
+                                                                                       "{$paramSettings[self::PARAM_MIN]}";
+                                                                       } elseif ( !$hasMin ) {
+                                                                               $intRangeStr = "The value$s must be no more than " .
+                                                                                       "{$paramSettings[self::PARAM_MAX]}";
+                                                                       } else {
+                                                                               $intRangeStr = "The value$s must be between " .
+                                                                                       "{$paramSettings[self::PARAM_MIN]} and {$paramSettings[self::PARAM_MAX]}";
+                                                                       }
+
+                                                                       $desc .= $paramPrefix . $intRangeStr;
+                                                               }
+                                                               break;
+                                                       case 'upload':
+                                                               $desc .= $paramPrefix . "Must be posted as a file upload using multipart/form-data";
+                                                               break;
+                                               }
+                                       }
 
-       /**
-        * Internal code errors should be reported with this method
-        * @param string $method Method or function name
-        * @param string $message Error message
-        * @throws MWException
-        */
-       protected static function dieDebug( $method, $message ) {
-               throw new MWException( "Internal error in $method: $message" );
-       }
+                                       if ( $multi ) {
+                                               if ( $hintPipeSeparated ) {
+                                                       $desc .= $paramPrefix . "Separate values with '|'";
+                                               }
 
-       /**
-        * Indicates if this module needs maxlag to be checked
-        * @return bool
-        */
-       public function shouldCheckMaxlag() {
-               return true;
-       }
+                                               $isArray = is_array( $type );
+                                               if ( !$isArray
+                                                       || $isArray && count( $type ) > self::LIMIT_SML1
+                                               ) {
+                                                       $desc .= $paramPrefix . "Maximum number of values " .
+                                                               self::LIMIT_SML1 . " (" . self::LIMIT_SML2 . " for bots)";
+                                               }
+                                       }
+                               }
 
-       /**
-        * Indicates whether this module requires read rights
-        * @return bool
-        */
-       public function isReadMode() {
-               return true;
-       }
+                               $default = isset( $paramSettings[self::PARAM_DFLT] ) ? $paramSettings[self::PARAM_DFLT] : null;
+                               if ( !is_null( $default ) && $default !== false ) {
+                                       $desc .= $paramPrefix . "Default: $default";
+                               }
 
-       /**
-        * Indicates whether this module requires write mode
-        * @return bool
-        */
-       public function isWriteMode() {
-               return false;
-       }
+                               $msg .= sprintf( "  %-19s - %s\n", $this->encodeParamName( $paramName ), $desc );
+                       }
 
-       /**
-        * Indicates whether this module must be called with a POST request
-        * @return bool
-        */
-       public function mustBePosted() {
-               return false;
-       }
+                       return $msg;
+               }
 
-       /**
-        * Returns whether this module requires a token to execute
-        * It is used to show possible errors in action=paraminfo
-        * see bug 25248
-        * @return bool
-        */
-       public function needsToken() {
                return false;
        }
 
-       /**
-        * Returns the token salt if there is one,
-        * '' if the module doesn't require a salt,
-        * else false if the module doesn't need a token
-        * You have also to override needsToken()
-        * Value is passed to User::getEditToken
-        * @return bool|string|array
-        */
-       public function getTokenSalt() {
-               return false;
-       }
+       /**@}*/
 
-       /**
-        * Gets the user for whom to get the watchlist
-        *
-        * @param array $params
-        * @return User
+       /************************************************************************//**
+        * @name   Profiling
+        * @{
         */
-       public function getWatchlistUser( $params ) {
-               if ( !is_null( $params['owner'] ) && !is_null( $params['token'] ) ) {
-                       $user = User::newFromName( $params['owner'], false );
-                       if ( !( $user && $user->getId() ) ) {
-                               $this->dieUsage( 'Specified user does not exist', 'bad_wlowner' );
-                       }
-                       $token = $user->getOption( 'watchlisttoken' );
-                       if ( $token == '' || $token != $params['token'] ) {
-                               $this->dieUsage(
-                                       'Incorrect watchlist token provided -- please set a correct token in Special:Preferences',
-                                       'bad_wltoken'
-                               );
-                       }
-               } else {
-                       if ( !$this->getUser()->isLoggedIn() ) {
-                               $this->dieUsage( 'You must be logged-in to have a watchlist', 'notloggedin' );
-                       }
-                       if ( !$this->getUser()->isAllowed( 'viewmywatchlist' ) ) {
-                               $this->dieUsage( 'You don\'t have permission to view your watchlist', 'permissiondenied' );
-                       }
-                       $user = $this->getUser();
-               }
-
-               return $user;
-       }
 
        /**
-        * @return bool|string|array Returns a false if the module has no help URL,
-        *   else returns a (array of) string
+        * Profiling: total module execution time
         */
-       public function getHelpUrls() {
-               return false;
-       }
+       private $mTimeIn = 0, $mModuleTime = 0;
 
        /**
-        * Returns a list of all possible errors returned by the module
-        *
-        * Don't call this function directly: use getFinalPossibleErrors() to allow
-        * hooks to modify parameters as needed.
+        * Get the name of the module as shown in the profiler log
         *
-        * @return array Array in the format of array( key, param1, param2, ... )
-        *   or array( 'code' => ..., 'info' => ... )
-        */
-       public function getPossibleErrors() {
-               $ret = array();
-
-               $params = $this->getFinalParams();
-               if ( $params ) {
-                       foreach ( $params as $paramName => $paramSettings ) {
-                               if ( isset( $paramSettings[ApiBase::PARAM_REQUIRED] )
-                                       && $paramSettings[ApiBase::PARAM_REQUIRED]
-                               ) {
-                                       $ret[] = array( 'missingparam', $paramName );
-                               }
-                       }
-                       if ( array_key_exists( 'continue', $params ) ) {
-                               $ret[] = array(
-                                       'code' => 'badcontinue',
-                                       'info' => 'Invalid continue param. You should pass the ' .
-                                               'original value returned by the previous query'
-                               );
-                       }
-               }
-
-               if ( $this->mustBePosted() ) {
-                       $ret[] = array( 'mustbeposted', $this->getModuleName() );
-               }
-
-               if ( $this->isReadMode() ) {
-                       $ret[] = array( 'readrequired' );
-               }
-
-               if ( $this->isWriteMode() ) {
-                       $ret[] = array( 'writerequired' );
-                       $ret[] = array( 'writedisabled' );
-               }
-
-               if ( $this->needsToken() ) {
-                       if ( !isset( $params['token'][ApiBase::PARAM_REQUIRED] )
-                               || !$params['token'][ApiBase::PARAM_REQUIRED]
-                       ) {
-                               // Add token as possible missing parameter, if not already done
-                               $ret[] = array( 'missingparam', 'token' );
-                       }
-                       $ret[] = array( 'sessionfailure' );
-               }
-
-               return $ret;
-       }
-
-       /**
-        * Get final list of possible errors, after hooks have had a chance to
-        * tweak it as needed.
+        * @param DatabaseBase|bool $db
         *
-        * @return array
-        * @since 1.22
-        */
-       public function getFinalPossibleErrors() {
-               $possibleErrors = $this->getPossibleErrors();
-               wfRunHooks( 'APIGetPossibleErrors', array( $this, &$possibleErrors ) );
-
-               return $possibleErrors;
-       }
-
-       /**
-        * Parses a list of errors into a standardised format
-        * @param array $errors List of errors. Items can be in the for
-        *   array( key, param1, param2, ... ) or array( 'code' => ..., 'info' => ... )
-        * @return array Parsed list of errors with items in the form array( 'code' => ..., 'info' => ... )
+        * @return string
         */
-       public function parseErrors( $errors ) {
-               $ret = array();
-
-               foreach ( $errors as $row ) {
-                       if ( isset( $row['code'] ) && isset( $row['info'] ) ) {
-                               $ret[] = $row;
-                       } else {
-                               $ret[] = $this->parseMsg( $row );
-                       }
+       public function getModuleProfileName( $db = false ) {
+               if ( $db ) {
+                       return 'API:' . $this->mModuleName . '-DB';
                }
 
-               return $ret;
+               return 'API:' . $this->mModuleName;
        }
 
-       /**
-        * Profiling: total module execution time
-        */
-       private $mTimeIn = 0, $mModuleTime = 0;
-
        /**
         * Start module profiling
         */
@@ -2311,31 +2224,152 @@ abstract class ApiBase extends ContextSource {
        }
 
        /**
-        * Gets a default slave database connection object
-        * @return DatabaseBase
+        * Write logging information for API features to a debug log, for usage
+        * analysis.
+        * @param string $feature Feature being used.
         */
-       protected function getDB() {
-               if ( !isset( $this->mSlaveDB ) ) {
-                       $this->profileDBIn();
-                       $this->mSlaveDB = wfGetDB( DB_SLAVE, 'api' );
-                       $this->profileDBOut();
-               }
+       protected function logFeatureUsage( $feature ) {
+               $request = $this->getRequest();
+               $s = '"' . addslashes( $feature ) . '"' .
+                       ' "' . wfUrlencode( str_replace( ' ', '_', $this->getUser()->getName() ) ) . '"' .
+                       ' "' . $request->getIP() . '"' .
+                       ' "' . addslashes( $request->getHeader( 'Referer' ) ) . '"' .
+                       ' "' . addslashes( $request->getHeader( 'User-agent' ) ) . '"';
+               wfDebugLog( 'api-feature-usage', $s, 'private' );
+       }
 
-               return $this->mSlaveDB;
+       /**@}*/
+
+       /************************************************************************//**
+        * @name   Deprecated
+        * @{
+        */
+
+       /**
+        * Formerly returned a string that identifies the version of the extending
+        * class. Typically included the class name, the svn revision, timestamp,
+        * and last author. Usually done with SVN's Id keyword
+        *
+        * @deprecated since 1.21, version string is no longer supported
+        * @return string
+        */
+       public function getVersion() {
+               wfDeprecated( __METHOD__, '1.21' );
+               return '';
        }
 
        /**
-        * Debugging function that prints a value and an optional backtrace
-        * @param mixed $value Value to print
-        * @param string $name Description of the printed value
-        * @param bool $backtrace If true, print a backtrace
+        * 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
         */
-       public static function debugPrint( $value, $name = 'unknown', $backtrace = false ) {
-               print "\n\n<pre><b>Debugging value '$name':</b>\n\n";
-               var_export( $value );
-               if ( $backtrace ) {
-                       print "\n" . wfBacktrace();
-               }
-               print "\n</pre>\n";
+       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 array();
+       }
+
+       /**
+        * @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 array();
+       }
+
+       /**
+        * @see self::getPossibleErrors()
+        * @deprecated since 1.24
+        * @return array
+        */
+       public function getRequireMaxOneParameterErrorMessages( $params ) {
+               wfDeprecated( __METHOD__, '1.24' );
+               return array();
+       }
+
+       /**
+        * @see self::getPossibleErrors()
+        * @deprecated since 1.24
+        * @return array
+        */
+       public function getRequireAtLeastOneParameterErrorMessages( $params ) {
+               wfDeprecated( __METHOD__, '1.24' );
+               return array();
+       }
+
+       /**
+        * @see self::getPossibleErrors()
+        * @deprecated since 1.24
+        * @return array
+        */
+       public function getTitleOrPageIdErrorMessage() {
+               wfDeprecated( __METHOD__, '1.24' );
+               return array();
+       }
+
+       /**
+        * 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 array();
        }
+
+       /**
+        * @see self::getPossibleErrors()
+        * @deprecated since 1.24
+        * @return array
+        */
+       public function getFinalPossibleErrors() {
+               wfDeprecated( __METHOD__, '1.24' );
+               return array();
+       }
+
+       /**
+        * @see self::getPossibleErrors()
+        * @deprecated since 1.24
+        * @return array
+        */
+       public function parseErrors( $errors ) {
+               wfDeprecated( __METHOD__, '1.24' );
+               return array();
+       }
+
+       /**@}*/
 }
+
+/**
+ * For really cool vim folding this needs to be at the end:
+ * vim: foldmarker=@{,@} foldmethod=marker
+ */
index 364300e..07f62c6 100644 (file)
@@ -152,7 +152,6 @@ class ApiBlock extends ApiBase {
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => true
                        ),
-                       'token' => null,
                        'expiry' => 'never',
                        'reason' => '',
                        'anononly' => false,
@@ -169,7 +168,6 @@ class ApiBlock extends ApiBase {
        public function getParamDescription() {
                return array(
                        'user' => 'Username, IP address or IP range you want to block',
-                       'token' => 'A block token previously obtained through prop=info',
                        'expiry' => 'Relative expiry time, e.g. \'5 months\' or \'2 weeks\'. ' .
                                'If set to \'infinite\', \'indefinite\' or \'never\', the block will never expire.',
                        'reason' => 'Reason for block',
@@ -187,66 +185,18 @@ class ApiBlock extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'user' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'userID' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'expiry' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'id' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'reason' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'anononly' => 'boolean',
-                               'nocreate' => 'boolean',
-                               'autoblock' => 'boolean',
-                               'noemail' => 'boolean',
-                               'hidename' => 'boolean',
-                               'allowusertalk' => 'boolean',
-                               'watchuser' => 'boolean'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Block a user.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'cantblock' ),
-                       array( 'canthide' ),
-                       array( 'cantblock-email' ),
-                       array( 'ipbblocked' ),
-                       array( 'ipbnounblockself' ),
-               ) );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getExamples() {
                return array(
-                       'api.php?action=block&user=123.5.5.12&expiry=3%20days&reason=First%20strike',
-                       'api.php?action=block&user=Vandal&expiry=never&reason=Vandalism&nocreate=&autoblock=&noemail='
+                       'api.php?action=block&user=123.5.5.12&expiry=3%20days&reason=First%20strike&token=123ABC',
+                       'api.php?action=block&user=Vandal&expiry=never&reason=Vandalism&nocreate=&autoblock=&noemail=&token=123ABC'
                );
        }
 
diff --git a/includes/api/ApiClearHasMsg.php b/includes/api/ApiClearHasMsg.php
new file mode 100644 (file)
index 0000000..32e20e8
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * Created on August 26, 2014
+ *
+ * Copyright © 2014 Petr Bena (benapetr@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
+ */
+
+/**
+ * API module that clears the hasmsg flag for current user
+ * @ingroup API
+ */
+class ApiClearHasMsg extends ApiBase {
+       public function execute() {
+               $user = $this->getUser();
+               $user->setNewtalk( false );
+               $this->getResult()->addValue( null, $this->getModuleName(), 'success' );
+       }
+
+       public function isWriteMode() {
+               return true;
+       }
+
+       public function mustBePosted() {
+               return false;
+       }
+
+       public function getDescription() {
+               return array( 'Clears the hasmsg flag for current user.' );
+       }
+
+       public function getExamples() {
+               return array(
+                       'api.php?action=clearhasmsg' => 'Clears the hasmsg flag for current user',
+               );
+       }
+
+       public function getHelpUrls() {
+               return 'https://www.mediawiki.org/wiki/API:ClearHasMsg';
+       }
+}
index 6b12a7d..4855926 100644 (file)
@@ -137,24 +137,6 @@ class ApiComparePages extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'fromtitle' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'fromrevid' => 'integer',
-                               'totitle' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'torevid' => 'integer',
-                               '*' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return array(
                        'Get the difference between 2 pages.',
@@ -162,19 +144,6 @@ class ApiComparePages extends ApiBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'inputneeded', 'info' => 'A title or a revision is needed' ),
-                       array( 'invalidtitle', 'title' ),
-                       array( 'nosuchpageid', 'pageid' ),
-                       array(
-                               'code' => 'baddiff',
-                               'info' => 'The diff cannot be retrieved. Maybe one or both ' .
-                                       'revisions do not exist or you do not have permission to view them.'
-                       ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=compare&fromrev=1&torev=2' => 'Create a diff between revision 1 and 2',
index 35bba17..2ce532b 100644 (file)
@@ -221,84 +221,6 @@ class ApiCreateAccount extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       'createaccount' => array(
-                               'result' => array(
-                                       ApiBase::PROP_TYPE => array(
-                                               'Success',
-                                               'Warning',
-                                               'NeedToken'
-                                       )
-                               ),
-                               'username' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'userid' => array(
-                                       ApiBase::PROP_TYPE => 'int',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'token' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                       )
-               );
-       }
-
-       public function getPossibleErrors() {
-               // Note the following errors aren't possible and don't need to be listed:
-               // sessionfailure, nocookiesfornew, badretype
-               $localErrors = array(
-                       'wrongpassword', // Actually caused by wrong domain field. Riddle me that...
-                       'sorbs_create_account_reason',
-                       'noname',
-                       'userexists',
-                       'password-name-match', // from User::getPasswordValidity
-                       'password-login-forbidden', // from User::getPasswordValidity
-                       'noemailtitle',
-                       'invalidemailaddress',
-                       'externaldberror',
-                       'acct_creation_throttle_hit',
-               );
-
-               $errors = parent::getPossibleErrors();
-               // All local errors are from LoginForm, which means they're actually message keys.
-               foreach ( $localErrors as $error ) {
-                       $errors[] = array(
-                               'code' => $error,
-                               'info' => wfMessage( $error )->inLanguage( 'en' )->useDatabase( false )->parse()
-                       );
-               }
-
-               $errors[] = array(
-                       'code' => 'permdenied-createaccount',
-                       'info' => 'You do not have the right to create a new account'
-               );
-               $errors[] = array(
-                       'code' => 'blocked',
-                       'info' => 'You cannot create a new account because you are blocked'
-               );
-               $errors[] = array(
-                       'code' => 'aborted',
-                       'info' => 'Account creation aborted by hook (info may vary)'
-               );
-               $errors[] = array(
-                       'code' => 'langinvalid',
-                       'info' => 'Invalid language parameter'
-               );
-
-               // 'passwordtooshort' has parameters. :(
-               $errors[] = array(
-                       'code' => 'passwordtooshort',
-                       'info' => wfMessage( 'passwordtooshort', $this->getConfig()->get( 'MinimalPasswordLength' ) )
-                               ->inLanguage( 'en' )->useDatabase( false )->parse()
-               );
-
-               return $errors;
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=createaccount&name=testuser&password=test123',
index 2fa4518..abca824 100644 (file)
@@ -72,8 +72,10 @@ class ApiDelete extends ApiBase {
 
                // Deprecated parameters
                if ( $params['watch'] ) {
+                       $this->logFeatureUsage( 'action=delete&watch' );
                        $watch = 'watch';
                } elseif ( $params['unwatch'] ) {
+                       $this->logFeatureUsage( 'action=delete&unwatch' );
                        $watch = 'unwatch';
                } else {
                        $watch = $params['watchlist'];
@@ -104,8 +106,8 @@ class ApiDelete extends ApiBase {
         *
         * @param Page|WikiPage $page Page or WikiPage object to work on
         * @param User $user User doing the action
-        * @param string $token delete token (same as edit token)
-        * @param string|null $reason reason for the deletion. Autogenerated if null
+        * @param string $token Delete token (same as edit token)
+        * @param string|null $reason Reason for the deletion. Autogenerated if null
         * @return Status|array
         */
        public static function delete( Page $page, User $user, $token, &$reason = null ) {
@@ -186,10 +188,6 @@ class ApiDelete extends ApiBase {
                        'pageid' => array(
                                ApiBase::PARAM_TYPE => 'integer'
                        ),
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'reason' => null,
                        'watch' => array(
                                ApiBase::PARAM_DFLT => false,
@@ -218,7 +216,6 @@ class ApiDelete extends ApiBase {
                return array(
                        'title' => "Title of the page you want to delete. Cannot be used together with {$p}pageid",
                        'pageid' => "Page ID of the page you want to delete. Cannot be used together with {$p}title",
-                       'token' => 'A delete token previously retrieved through prop=info',
                        'reason'
                                => 'Reason for the deletion. If not set, an automatically generated reason will be used',
                        'watch' => 'Add the page to your watchlist',
@@ -229,40 +226,12 @@ class ApiDelete extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'title' => 'string',
-                               'reason' => 'string',
-                               'logid' => 'integer'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Delete a page.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(),
-                       $this->getTitleOrPageIdErrorMessage(),
-                       array(
-                               array( 'notanarticle' ),
-                               array( 'hookaborted', 'error' ),
-                               array( 'delete-toobig', 'limit' ),
-                               array( 'cannotdelete', 'title' ),
-                               array( 'invalidoldimage' ),
-                               array( 'nodeleteablefile' ),
-                       )
-               );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getExamples() {
index 884306a..8a76271 100644 (file)
@@ -252,7 +252,8 @@ class ApiEditPage extends ApiBase {
                        'format' => $contentFormat,
                        'model' => $contentHandler->getModelID(),
                        'wpEditToken' => $params['token'],
-                       'wpIgnoreBlankSummary' => ''
+                       'wpIgnoreBlankSummary' => '',
+                       'wpIgnoreBlankArticle' => true
                );
 
                if ( !is_null( $params['summary'] ) ) {
@@ -308,8 +309,10 @@ class ApiEditPage extends ApiBase {
 
                // Deprecated parameters
                if ( $params['watch'] ) {
+                       $this->logFeatureUsage( 'action=edit&watch' );
                        $watch = true;
                } elseif ( $params['unwatch'] ) {
+                       $this->logFeatureUsage( 'action=edit&unwatch' );
                        $watch = false;
                }
 
@@ -497,65 +500,6 @@ class ApiEditPage extends ApiBase {
                return 'Create and edit pages.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(),
-                       $this->getTitleOrPageIdErrorMessage(),
-                       array(
-                               array( 'missingtext' ),
-                               array( 'createonly-exists' ),
-                               array( 'nocreate-missing' ),
-                               array( 'nosuchrevid', 'undo' ),
-                               array( 'nosuchrevid', 'undoafter' ),
-                               array( 'revwrongpage', 'id', 'text' ),
-                               array( 'undo-failure' ),
-                               array( 'hashcheckfailed' ),
-                               array( 'hookaborted' ),
-                               array( 'code' => 'parseerror', 'info' => 'Failed to parse the given text.' ),
-                               array( 'noimageredirect-anon' ),
-                               array( 'noimageredirect-logged' ),
-                               array( 'spamdetected', 'spam' ),
-                               array( 'summaryrequired' ),
-                               array( 'blockedtext' ),
-                               array( 'contenttoobig', $this->getConfig()->get( 'MaxArticleSize' ) ),
-                               array( 'noedit-anon' ),
-                               array( 'noedit' ),
-                               array( 'actionthrottledtext' ),
-                               array( 'wasdeleted' ),
-                               array( 'nocreate-loggedin' ),
-                               array( 'blankpage' ),
-                               array( 'editconflict' ),
-                               array( 'emptynewsection' ),
-                               array( 'unknownerror', 'retval' ),
-                               array( 'code' => 'nosuchsection', 'info' => 'There is no such section.' ),
-                               array(
-                                       'code' => 'invalidsection',
-                                       'info' => 'The section parameter must be a valid section id or \'new\''
-                               ),
-                               array(
-                                       'code' => 'sectionsnotsupported',
-                                       'info' => 'Sections are not supported for this type of page.'
-                               ),
-                               array(
-                                       'code' => 'editnotsupported',
-                                       'info' => 'Editing of this type of page is not supported using the text based edit API.'
-                               ),
-                               array(
-                                       'code' => 'appendnotsupported',
-                                       'info' => 'This type of page can not be edited by appending or prepending text.' ),
-                               array(
-                                       'code' => 'redirect-appendonly',
-                                       'info' => 'You have attempted to edit using the "redirect"-following mode, which must be used in conjuction with section=new, prependtext, or appendtext.',
-                               ),
-                               array(
-                                       'code' => 'badformat',
-                                       'info' => 'The requested serialization format can not be applied to the page\'s content model'
-                               ),
-                               array( 'customcssprotected' ),
-                               array( 'customjsprotected' ),
-                       )
-               );
-       }
-
        public function getAllowedParams() {
                return array(
                        'title' => array(
@@ -569,10 +513,6 @@ class ApiEditPage extends ApiBase {
                                ApiBase::PARAM_TYPE => 'string',
                        ),
                        'text' => null,
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'summary' => null,
                        'minor' => false,
                        'notminor' => false,
@@ -631,8 +571,8 @@ class ApiEditPage extends ApiBase {
                        'sectiontitle' => 'The title for a new section',
                        'text' => 'Page content',
                        'token' => array(
-                               'Edit token. You can get one of these through prop=info.',
-                               "The token should always be sent as the last parameter, or at " .
+                               /* Standard description is automatically prepended */
+                               'The token should always be sent as the last parameter, or at ' .
                                        "least, after the {$p}text parameter"
                        ),
                        'summary'
@@ -645,7 +585,8 @@ class ApiEditPage extends ApiBase {
                                'Used to detect edit conflicts; leave unset to ignore conflicts'
                        ),
                        'starttimestamp' => array(
-                               'Timestamp when you obtained the edit token.',
+                               'Timestamp when you began the editing process, e.g. when the current page content ' .
+                                       'was loaded for editing.',
                                'Used to detect edit conflicts; leave unset to ignore conflicts'
                        ),
                        'recreate' => 'Override any errors about the article having been deleted in the meantime',
@@ -671,47 +612,8 @@ class ApiEditPage extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'new' => 'boolean',
-                               'result' => array(
-                                       ApiBase::PROP_TYPE => array(
-                                               'Success',
-                                               'Failure'
-                                       ),
-                               ),
-                               'pageid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'title' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'nochange' => 'boolean',
-                               'oldrevid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'newrevid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'newtimestamp' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getExamples() {
index 29f7e05..9870b2d 100644 (file)
@@ -40,7 +40,11 @@ class ApiEmailUser extends ApiBase {
                }
 
                // Check permissions and errors
-               $error = SpecialEmailUser::getPermissionsError( $this->getUser(), $params['token'] );
+               $error = SpecialEmailUser::getPermissionsError(
+                       $this->getUser(),
+                       $params['token'],
+                       $this->getConfig()
+               );
                if ( $error ) {
                        $this->dieUsageMsg( array( $error ) );
                }
@@ -94,10 +98,6 @@ class ApiEmailUser extends ApiBase {
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => true
                        ),
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'ccme' => false,
                );
        }
@@ -107,49 +107,21 @@ class ApiEmailUser extends ApiBase {
                        'target' => 'User to send email to',
                        'subject' => 'Subject header',
                        'text' => 'Mail body',
-                       'token' => 'A token previously acquired via prop=info',
                        'ccme' => 'Send a copy of this mail to me',
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'result' => array(
-                                       ApiBase::PROP_TYPE => array(
-                                               'Success',
-                                               'Failure'
-                                       ),
-                               ),
-                               'message' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Email a user.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'usermaildisabled' ),
-               ) );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getExamples() {
                return array(
-                       'api.php?action=emailuser&target=WikiSysop&text=Content'
+                       'api.php?action=emailuser&target=WikiSysop&text=Content&token=123ABC'
                                => 'Send an email to the User "WikiSysop" with the text "Content"',
                );
        }
index 82d303f..8a3b534 100644 (file)
@@ -42,8 +42,11 @@ class ApiExpandTemplates extends ApiBase {
                $this->requireMaxOneParameter( $params, 'prop', 'generatexml' );
 
                if ( $params['prop'] === null ) {
-                       $this->setWarning( 'Because no values have been specified for the prop parameter, a legacy format has been used for the output.'
-                                . ' This format is deprecated, and in the future, a default value will be set for the prop parameter, causing the new format to always be used.' );
+                       $this->logFeatureUsage( 'action=expandtemplates&!prop' );
+                       $this->setWarning( 'Because no values have been specified for the prop parameter, a ' .
+                               'legacy format has been used for the output. This format is deprecated, and in ' .
+                               'the future, a default value will be set for the prop parameter, causing the new' .
+                               'format to always be used.' );
                        $prop = array();
                } else {
                        $prop = array_flip( $params['prop'] );
@@ -68,6 +71,10 @@ class ApiExpandTemplates extends ApiBase {
                $retval = array();
 
                if ( isset( $prop['parsetree'] ) || $params['generatexml'] ) {
+                       if ( !isset( $prop['parsetree'] ) ) {
+                               $this->logFeatureUsage( 'action=expandtemplates&generatexml' );
+                       }
+
                        $wgParser->startExternalParse( $title_obj, $options, OT_PREPROCESS );
                        $dom = $wgParser->preprocessToDom( $params['text'] );
                        if ( is_callable( array( $dom, 'saveXML' ) ) ) {
@@ -159,9 +166,12 @@ class ApiExpandTemplates extends ApiBase {
                        'prop' => array(
                                'Which pieces of information to get',
                                ' wikitext   - The expanded wikitext',
-                               ' categories - Any categories present in the input that are not represented in the wikitext output',
-                               ' volatile   - Whether the output is volatile and should not be reused elsewhere within the page',
-                               ' ttl        - The maximum time after which caches of the result should be invalidated',
+                               ' categories - Any categories present in the input that are not represented in ' .
+                                       'the wikitext output',
+                               ' volatile   - Whether the output is volatile and should not be reused ' .
+                                       'elsewhere within the page',
+                               ' ttl        - The maximum time after which caches of the result should be ' .
+                                       'invalidated',
                                ' parsetree  - The XML parse tree of the input',
                                'Note that if no values are selected, the result will contain the wikitext,',
                                'but the output will be in a deprecated format.',
@@ -171,45 +181,10 @@ class ApiExpandTemplates extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       'wikitext' => array(
-                               'wikitext' => 'string',
-                       ),
-                       'categories' => array(
-                               'categories' => array(
-                                       ApiBase::PROP_TYPE => 'array',
-                                       ApiBase::PROP_NULLABLE => true,
-                               ),
-                       ),
-                       'volatile' => array(
-                               'volatile' => array(
-                                       ApiBase::PROP_TYPE => 'boolean',
-                                       ApiBase::PROP_NULLABLE => true,
-                               ),
-                       ),
-                       'ttl' => array(
-                               'ttl' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true,
-                               ),
-                       ),
-                       'parsetree' => array(
-                               'parsetree' => 'string',
-                       ),
-               );
-       }
-
        public function getDescription() {
                return 'Expands all templates in wikitext.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'invalidtitle', 'title' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=expandtemplates&text={{Project:Sandbox}}'
index 3392a5c..374203e 100644 (file)
@@ -210,14 +210,6 @@ class ApiFeedContributions extends ApiBase {
                return 'Returns a user contributions feed.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'feed-unavailable', 'info' => 'Syndication feeds are not available' ),
-                       array( 'code' => 'feed-invalid', 'info' => 'Invalid subscription feed type' ),
-                       array( 'code' => 'sizediffdisabled', 'info' => 'Size difference is disabled in Miser Mode' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=feedcontributions&user=Reedy',
index bb68d5a..7239a29 100644 (file)
@@ -198,13 +198,6 @@ class ApiFeedRecentChanges extends ApiBase {
                return 'Returns a recent changes feed';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'feed-unavailable', 'info' => 'Syndication feeds are not available' ),
-                       array( 'code' => 'feed-invalid', 'info' => 'Invalid subscription feed type' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=feedrecentchanges',
index 983b6a8..6aef8fc 100644 (file)
@@ -259,13 +259,6 @@ class ApiFeedWatchlist extends ApiBase {
                return 'Returns a watchlist feed.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'feed-unavailable', 'info' => 'Syndication feeds are not available' ),
-                       array( 'code' => 'feed-invalid', 'info' => 'Invalid subscription feed type' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=feedwatchlist',
index fab8b5a..f518e17 100644 (file)
@@ -132,63 +132,25 @@ class ApiFileRevert extends ApiBase {
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => true,
                        ),
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                );
        }
 
        public function getParamDescription() {
                return array(
                        'filename' => 'Target filename without the File: prefix',
-                       'token' => 'Edit token. You can get one of these through prop=info',
                        'comment' => 'Upload comment',
                        'archivename' => 'Archive name of the revision to revert to',
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'result' => array(
-                                       ApiBase::PROP_TYPE => array(
-                                               'Success',
-                                               'Failure'
-                                       )
-                               ),
-                               'errors' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return array(
                        'Revert a file to an old version.'
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(),
-                       array(
-                               array( 'mustbeloggedin', 'upload' ),
-                               array( 'badaccess-groups' ),
-                               array( 'invalidtitle', 'title' ),
-                               array( 'notanarticle' ),
-                               array( 'filerevert-badversion' ),
-                       )
-               );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getExamples() {
index 03a6843..9165ce8 100644 (file)
@@ -52,7 +52,7 @@ abstract class ApiFormatBase extends ApiBase {
        }
 
        /**
-        * Overriding class returns the mime type that should be sent to the client.
+        * Overriding class returns the MIME type that should be sent to the client.
         * This method is not called if getIsHtml() returns true.
         * @return string
         */
@@ -247,6 +247,7 @@ See the <a href='https://www.mediawiki.org/wiki/API'>complete documentation</a>,
 
        /**
         * Get the contents of the buffer.
+        * @return string
         */
        public function getBuffer() {
                return $this->mBuffer;
@@ -338,82 +339,16 @@ See the <a href='https://www.mediawiki.org/wiki/API'>complete documentation</a>,
        public function getDescription() {
                return $this->getIsHtml() ? ' (pretty-print in HTML)' : '';
        }
-}
-
-/**
- * This printer is used to wrap an instance of the Feed class
- * @ingroup API
- */
-class ApiFormatFeedWrapper extends ApiFormatBase {
-
-       public function __construct( ApiMain $main ) {
-               parent::__construct( $main, 'feed' );
-       }
-
-       /**
-        * Call this method to initialize output data. See execute()
-        * @param ApiResult $result
-        * @param object $feed An instance of one of the $wgFeedClasses classes
-        * @param array $feedItems of FeedItem objects
-        */
-       public static function setResult( $result, $feed, $feedItems ) {
-               // Store output in the Result data.
-               // This way we can check during execution if any error has occurred
-               // Disable size checking for this because we can't continue
-               // cleanly; size checking would cause more problems than it'd
-               // solve
-               $result->disableSizeCheck();
-               $result->addValue( null, '_feed', $feed );
-               $result->addValue( null, '_feeditems', $feedItems );
-               $result->enableSizeCheck();
-       }
 
        /**
-        * Feed does its own headers
-        *
-        * @return null
+        * To avoid code duplication with the deprecation of dbg, dump, txt, wddx,
+        * and yaml, this method is added to do the necessary work. It should be
+        * removed when those deprecated formats are removed.
         */
-       public function getMimeType() {
-               return null;
-       }
-
-       /**
-        * Optimization - no need to sanitize data that will not be needed
-        *
-        * @return bool
-        */
-       public function getNeedsRawData() {
-               return true;
-       }
-
-       /**
-        * ChannelFeed doesn't give us a method to print errors in a friendly
-        * manner, so just punt errors to the default printer.
-        * @return bool
-        */
-       public function canPrintErrors() {
-               return false;
-       }
-
-       /**
-        * This class expects the result data to be in a custom format set by self::setResult()
-        * $result['_feed'] - an instance of one of the $wgFeedClasses classes
-        * $result['_feeditems'] - an array of FeedItem instances
-        */
-       public function execute() {
-               $data = $this->getResultData();
-               if ( isset( $data['_feed'] ) && isset( $data['_feeditems'] ) ) {
-                       $feed = $data['_feed'];
-                       $items = $data['_feeditems'];
-
-                       $feed->outHeader();
-                       foreach ( $items as & $item ) {
-                               $feed->outItem( $item );
-                       }
-                       $feed->outFooter();
-               } else {
-                       // Error has occurred, print something useful
-                       ApiBase::dieDebug( __METHOD__, 'Invalid feed class/item' );
-               }
+       protected function markDeprecated() {
+               $fm = $this->getIsHtml() ? 'fm' : '';
+               $name = $this->getModuleName();
+               $this->logFeatureUsage( "format=$name" );
+               $this->setWarning( "format=$name has been deprecated. Please use format=json$fm instead." );
        }
 }
index 1b2e02c..5ec518b 100644 (file)
@@ -26,6 +26,7 @@
 
 /**
  * API PHP's var_export() output formatter
+ * @deprecated since 1.24
  * @ingroup API
  */
 class ApiFormatDbg extends ApiFormatBase {
@@ -38,10 +39,11 @@ class ApiFormatDbg extends ApiFormatBase {
        }
 
        public function execute() {
+               $this->markDeprecated();
                $this->printText( var_export( $this->getResultData(), true ) );
        }
 
        public function getDescription() {
-               return 'Output data in PHP\'s var_export() format' . parent::getDescription();
+               return 'DEPRECATED! Output data in PHP\'s var_export() format' . parent::getDescription();
        }
 }
index 62253e1..d4c7cab 100644 (file)
@@ -26,6 +26,7 @@
 
 /**
  * API PHP's var_dump() output formatter
+ * @deprecated since 1.24
  * @ingroup API
  */
 class ApiFormatDump extends ApiFormatBase {
@@ -38,6 +39,7 @@ class ApiFormatDump extends ApiFormatBase {
        }
 
        public function execute() {
+               $this->markDeprecated();
                ob_start();
                var_dump( $this->getResultData() );
                $result = ob_get_contents();
@@ -46,6 +48,6 @@ class ApiFormatDump extends ApiFormatBase {
        }
 
        public function getDescription() {
-               return 'Output data in PHP\'s var_dump() format' . parent::getDescription();
+               return 'DEPRECATED! Output data in PHP\'s var_dump() format' . parent::getDescription();
        }
 }
diff --git a/includes/api/ApiFormatFeedWrapper.php b/includes/api/ApiFormatFeedWrapper.php
new file mode 100644 (file)
index 0000000..9260006
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+/**
+ *
+ *
+ * Created on Sep 19, 2006
+ *
+ * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@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
+ */
+
+/**
+ * This printer is used to wrap an instance of the Feed class
+ * @ingroup API
+ */
+class ApiFormatFeedWrapper extends ApiFormatBase {
+
+       public function __construct( ApiMain $main ) {
+               parent::__construct( $main, 'feed' );
+       }
+
+       /**
+        * Call this method to initialize output data. See execute()
+        * @param ApiResult $result
+        * @param object $feed An instance of one of the $wgFeedClasses classes
+        * @param array $feedItems Array of FeedItem objects
+        */
+       public static function setResult( $result, $feed, $feedItems ) {
+               // Store output in the Result data.
+               // This way we can check during execution if any error has occurred
+               // Disable size checking for this because we can't continue
+               // cleanly; size checking would cause more problems than it'd
+               // solve
+               $result->addValue( null, '_feed', $feed, ApiResult::NO_SIZE_CHECK );
+               $result->addValue( null, '_feeditems', $feedItems, ApiResult::NO_SIZE_CHECK );
+       }
+
+       /**
+        * Feed does its own headers
+        *
+        * @return null
+        */
+       public function getMimeType() {
+               return null;
+       }
+
+       /**
+        * Optimization - no need to sanitize data that will not be needed
+        *
+        * @return bool
+        */
+       public function getNeedsRawData() {
+               return true;
+       }
+
+       /**
+        * ChannelFeed doesn't give us a method to print errors in a friendly
+        * manner, so just punt errors to the default printer.
+        * @return bool
+        */
+       public function canPrintErrors() {
+               return false;
+       }
+
+       /**
+        * This class expects the result data to be in a custom format set by self::setResult()
+        * $result['_feed'] - an instance of one of the $wgFeedClasses classes
+        * $result['_feeditems'] - an array of FeedItem instances
+        */
+       public function execute() {
+               $data = $this->getResultData();
+               if ( isset( $data['_feed'] ) && isset( $data['_feeditems'] ) ) {
+                       $feed = $data['_feed'];
+                       $items = $data['_feeditems'];
+
+                       $feed->outHeader();
+                       foreach ( $items as & $item ) {
+                               $feed->outItem( $item );
+                       }
+                       $feed->outFooter();
+               } else {
+                       // Error has occurred, print something useful
+                       ApiBase::dieDebug( __METHOD__, 'Invalid feed class/item' );
+               }
+       }
+}
index e2c6b9a..6c5ad38 100644 (file)
@@ -66,7 +66,9 @@ class ApiFormatJson extends ApiFormatBase {
                $callback = $params['callback'];
                if ( $callback !== null ) {
                        $callback = preg_replace( "/[^][.\\'\\\"_A-Za-z0-9]/", '', $callback );
-                       $this->printText( "$callback($json)" );
+                       # Prepend a comment to try to avoid attacks against content
+                       # sniffers, such as bug 68187.
+                       $this->printText( "/**/$callback($json)" );
                } else {
                        $this->printText( $json );
                }
index 4130e70..c451ed7 100644 (file)
@@ -26,6 +26,7 @@
 
 /**
  * API Text output formatter
+ * @deprecated since 1.24
  * @ingroup API
  */
 class ApiFormatTxt extends ApiFormatBase {
@@ -38,10 +39,11 @@ class ApiFormatTxt extends ApiFormatBase {
        }
 
        public function execute() {
+               $this->markDeprecated();
                $this->printText( print_r( $this->getResultData(), true ) );
        }
 
        public function getDescription() {
-               return 'Output data in PHP\'s print_r() format' . parent::getDescription();
+               return 'DEPRECATED! Output data in PHP\'s print_r() format' . parent::getDescription();
        }
 }
index 2e58c72..ba90c26 100644 (file)
@@ -26,6 +26,7 @@
 
 /**
  * API WDDX output formatter
+ * @deprecated since 1.24
  * @ingroup API
  */
 class ApiFormatWddx extends ApiFormatBase {
@@ -35,6 +36,8 @@ class ApiFormatWddx extends ApiFormatBase {
        }
 
        public function execute() {
+               $this->markDeprecated();
+
                // Some versions of PHP have a broken wddx_serialize_value, see
                // PHP bug 45314. Test encoding an affected character (U+00A0)
                // to avoid this.
@@ -107,6 +110,6 @@ class ApiFormatWddx extends ApiFormatBase {
        }
 
        public function getDescription() {
-               return 'Output data in WDDX format' . parent::getDescription();
+               return 'DEPRECATED! Output data in WDDX format' . parent::getDescription();
        }
 }
index 700d4a5..3798f89 100644 (file)
@@ -26,6 +26,7 @@
 
 /**
  * API YAML output formatter
+ * @deprecated since 1.24
  * @ingroup API
  */
 class ApiFormatYaml extends ApiFormatJson {
@@ -34,7 +35,12 @@ class ApiFormatYaml extends ApiFormatJson {
                return 'application/yaml';
        }
 
+       public function execute() {
+               $this->markDeprecated();
+               parent::execute();
+       }
+
        public function getDescription() {
-               return 'Output data in YAML format' . ApiFormatBase::getDescription();
+               return 'DEPRECATED! Output data in YAML format' . ApiFormatBase::getDescription();
        }
 }
index b0b8328..bcd6c12 100644 (file)
@@ -51,6 +51,7 @@ class ApiHelp extends ApiBase {
                }
 
                if ( is_array( $params['querymodules'] ) ) {
+                       $this->logFeatureUsage( 'action=help&querymodules' );
                        $queryModules = $params['querymodules'];
                        foreach ( $queryModules as $m ) {
                                $modules[] = 'query+' . $m;
index c932a74..20396dd 100644 (file)
@@ -26,10 +26,10 @@ class ApiImageRotate extends ApiBase {
 
        /**
         * Add all items from $values into the result
-        * @param array $result output
-        * @param array $values values to add
-        * @param string $flag the name of the boolean flag to mark this element
-        * @param string $name if given, name of the value
+        * @param array $result Output
+        * @param array $values Values to add
+        * @param string $flag The name of the boolean flag to mark this element
+        * @param string $name If given, name of the value
         */
        private static function addValues( array &$result, $values, $flag = null, $name = null ) {
                foreach ( $values as $val ) {
@@ -184,10 +184,6 @@ class ApiImageRotate extends ApiBase {
                                ApiBase::PARAM_TYPE => array( '90', '180', '270' ),
                                ApiBase::PARAM_REQUIRED => true
                        ),
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'continue' => '',
                );
                if ( $flags ) {
@@ -202,7 +198,6 @@ class ApiImageRotate extends ApiBase {
 
                return $pageSet->getFinalParamDescription() + array(
                        'rotation' => 'Degrees to rotate image clockwise',
-                       'token' => 'Edit token. You can get one of these through action=tokens',
                        'continue' => 'When more results are available, use this to continue',
                );
        }
@@ -212,20 +207,7 @@ class ApiImageRotate extends ApiBase {
        }
 
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
-       }
-
-       public function getPossibleErrors() {
-               $pageSet = $this->getPageSet();
-
-               return array_merge(
-                       parent::getPossibleErrors(),
-                       $pageSet->getFinalPossibleErrors()
-               );
+               return 'csrf';
        }
 
        public function getExamples() {
index 3144fc1..b11348e 100644 (file)
@@ -99,10 +99,6 @@ class ApiImport extends ApiBase {
 
        public function getAllowedParams() {
                return array(
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'summary' => null,
                        'xml' => array(
                                ApiBase::PARAM_TYPE => 'upload',
@@ -122,7 +118,6 @@ class ApiImport extends ApiBase {
 
        public function getParamDescription() {
                return array(
-                       'token' => 'Import token obtained through prop=info',
                        'summary' => 'Import summary',
                        'xml' => 'Uploaded XML file',
                        'interwikisource' => 'For interwiki imports: wiki to import from',
@@ -134,17 +129,6 @@ class ApiImport extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       ApiBase::PROP_LIST => true,
-                       '' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string',
-                               'revisions' => 'integer'
-                       )
-               );
-       }
-
        public function getDescription() {
                return array(
                        'Import a page from another wiki, or an XML file.',
@@ -153,24 +137,8 @@ class ApiImport extends ApiBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'cantimport' ),
-                       array( 'missingparam', 'interwikipage' ),
-                       array( 'cantimport-upload' ),
-                       array( 'import-unknownerror', 'source' ),
-                       array( 'import-unknownerror', 'result' ),
-                       array( 'import-rootpage-nosubpage', 'namespace' ),
-                       array( 'import-rootpage-invalid' ),
-               ) );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getExamples() {
index f818c5f..976f4c1 100644 (file)
@@ -193,66 +193,6 @@ class ApiLogin extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'result' => array(
-                                       ApiBase::PROP_TYPE => array(
-                                               'Success',
-                                               'NeedToken',
-                                               'WrongToken',
-                                               'NoName',
-                                               'Illegal',
-                                               'WrongPluginPass',
-                                               'NotExists',
-                                               'WrongPass',
-                                               'EmptyPass',
-                                               'CreateBlocked',
-                                               'Throttled',
-                                               'Blocked',
-                                               'Aborted'
-                                       )
-                               ),
-                               'lguserid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'lgusername' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'lgtoken' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'cookieprefix' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'sessionid' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'token' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'details' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'wait' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'reason' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return array(
                        'Log in and get the authentication tokens.',
@@ -263,37 +203,6 @@ class ApiLogin extends ApiBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array(
-                               'code' => 'NeedToken', 'info' => 'You need to resubmit your ' .
-                               'login with the specified token. See ' .
-                                       'https://bugzilla.wikimedia.org/show_bug.cgi?id=23076'
-                       ),
-                       array( 'code' => 'WrongToken', 'info' => 'You specified an invalid token' ),
-                       array( 'code' => 'NoName', 'info' => 'You didn\'t set the lgname parameter' ),
-                       array( 'code' => 'Illegal', 'info' => 'You provided an illegal username' ),
-                       array( 'code' => 'NotExists', 'info' => 'The username you provided doesn\'t exist' ),
-                       array(
-                               'code' => 'EmptyPass',
-                               'info' => 'You didn\'t set the lgpassword parameter or you left it empty'
-                       ),
-                       array( 'code' => 'WrongPass', 'info' => 'The password you provided is incorrect' ),
-                       array(
-                               'code' => 'WrongPluginPass',
-                               'info' => 'Same as "WrongPass", returned when an authentication ' .
-                                       'plugin rather than MediaWiki itself rejected the password'
-                       ),
-                       array(
-                               'code' => 'CreateBlocked',
-                               'info' => 'The wiki tried to automatically create a new account ' .
-                                       'for you, but your IP address has been blocked from account creation'
-                       ),
-                       array( 'code' => 'Throttled', 'info' => 'You\'ve logged in too many times in a short time' ),
-                       array( 'code' => 'Blocked', 'info' => 'User is blocked' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=login&lgname=user&lgpassword=password'
index c8b3882..324f4b2 100644 (file)
@@ -50,10 +50,6 @@ class ApiLogout extends ApiBase {
                return array();
        }
 
-       public function getResultProperties() {
-               return array();
-       }
-
        public function getParamDescription() {
                return array();
        }
index 84db9ed..0d677b1 100644 (file)
@@ -81,6 +81,7 @@ class ApiMain extends ApiBase {
                'watch' => 'ApiWatch',
                'patrol' => 'ApiPatrol',
                'import' => 'ApiImport',
+               'clearhasmsg' => 'ApiClearHasMsg',
                'userrights' => 'ApiUserrights',
                'options' => 'ApiOptions',
                'imagerotate' => 'ApiImageRotate',
@@ -699,21 +700,20 @@ class ApiMain extends ApiBase {
                $warnings = isset( $oldResult['warnings'] ) ? $oldResult['warnings'] : null;
 
                $result->reset();
-               $result->disableSizeCheck();
                // Re-add the id
                $requestid = $this->getParameter( 'requestid' );
                if ( !is_null( $requestid ) ) {
-                       $result->addValue( null, 'requestid', $requestid );
+                       $result->addValue( null, 'requestid', $requestid, ApiResult::NO_SIZE_CHECK );
                }
                if ( $config->get( 'ShowHostnames' ) ) {
                        // servedby is especially useful when debugging errors
-                       $result->addValue( null, 'servedby', wfHostName() );
+                       $result->addValue( null, 'servedby', wfHostName(), ApiResult::NO_SIZE_CHECK );
                }
                if ( $warnings !== null ) {
-                       $result->addValue( null, 'warnings', $warnings );
+                       $result->addValue( null, 'warnings', $warnings, ApiResult::NO_SIZE_CHECK );
                }
 
-               $result->addValue( null, 'error', $errMessage );
+               $result->addValue( null, 'error', $errMessage, ApiResult::NO_SIZE_CHECK );
 
                return $errMessage['code'];
        }
@@ -737,6 +737,11 @@ class ApiMain extends ApiBase {
                        }
                }
 
+               if ( $this->getParameter( 'curtimestamp' ) ) {
+                       $result->addValue( null, 'curtimestamp', wfTimestamp( TS_ISO_8601, time() ),
+                               ApiResult::NO_SIZE_CHECK );
+               }
+
                $params = $this->extractRequestParams();
 
                $this->mAction = $params['action'];
@@ -760,18 +765,35 @@ class ApiMain extends ApiBase {
                }
                $moduleParams = $module->extractRequestParams();
 
-               // Die if token required, but not provided
-               $salt = $module->getTokenSalt();
-               if ( $salt !== false ) {
+               // Check token, if necessary
+               if ( $module->needsToken() === true ) {
+                       throw new MWException(
+                               "Module '{$module->getModuleName()}' must be updated for the new token handling. " .
+                               "See documentation for ApiBase::needsToken for details."
+                       );
+               }
+               if ( $module->needsToken() ) {
+                       if ( !$module->mustBePosted() ) {
+                               throw new MWException(
+                                       "Module '{$module->getModuleName()}' must require POST to use tokens."
+                               );
+                       }
+
                        if ( !isset( $moduleParams['token'] ) ) {
                                $this->dieUsageMsg( array( 'missingparam', 'token' ) );
                        }
 
-                       if ( !$this->getUser()->matchEditToken(
-                               $moduleParams['token'],
-                               $salt,
-                               $this->getContext()->getRequest() )
-                       ) {
+                       if ( array_key_exists(
+                               $module->encodeParamName( 'token' ),
+                               $this->getRequest()->getQueryValues()
+                       ) ) {
+                               $this->dieUsage(
+                                       "The '{$module->encodeParamName( 'token' )}' parameter was found in the query string, but must be in the POST body",
+                                       'mustposttoken'
+                               );
+                       }
+
+                       if ( !$module->validateToken( $moduleParams['token'], $moduleParams ) ) {
                                $this->dieUsageMsg( 'sessionfailure' );
                        }
                }
@@ -862,7 +884,7 @@ class ApiMain extends ApiBase {
        /**
         * Check POST for external response and setup result printer
         * @param ApiBase $module An Api module
-        * @param array $params an array with the request parameters
+        * @param array $params An array with the request parameters
         */
        protected function setupExternalResponse( $module, $params ) {
                if ( !$this->getRequest()->wasPosted() && $module->mustBePosted() ) {
@@ -1091,11 +1113,11 @@ class ApiMain extends ApiBase {
                return array(
                        'format' => array(
                                ApiBase::PARAM_DFLT => ApiMain::API_DEFAULT_FORMAT,
-                               ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'format' )
+                               ApiBase::PARAM_TYPE => 'submodule',
                        ),
                        'action' => array(
                                ApiBase::PARAM_DFLT => 'help',
-                               ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'action' )
+                               ApiBase::PARAM_TYPE => 'submodule',
                        ),
                        'maxlag' => array(
                                ApiBase::PARAM_TYPE => 'integer'
@@ -1113,6 +1135,7 @@ class ApiMain extends ApiBase {
                        ),
                        'requestid' => null,
                        'servedby' => false,
+                       'curtimestamp' => false,
                        'origin' => null,
                );
        }
@@ -1140,6 +1163,7 @@ class ApiMain extends ApiBase {
                        'requestid' => 'Request ID to distinguish requests. This will just be output back to you',
                        'servedby' => 'Include the hostname that served the request in the ' .
                                'results. Unconditionally shown on error',
+                       'curtimestamp' => 'Include the current timestamp in the result.',
                        'origin' => array(
                                'When accessing the API using a cross-domain AJAX request (CORS), set this to the',
                                'originating domain. This must be included in any pre-flight request, and',
@@ -1199,24 +1223,6 @@ class ApiMain extends ApiBase {
                );
        }
 
-       /**
-        * @return array
-        */
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'readonlytext' ),
-                       array( 'code' => 'unknown_format', 'info' => 'Unrecognized format: format' ),
-                       array( 'code' => 'unknown_action', 'info' => 'The API requires a valid action parameter' ),
-                       array( 'code' => 'maxlag', 'info' => 'Waiting for host: x seconds lagged' ),
-                       array( 'code' => 'maxlag', 'info' => 'Waiting for a database server: x seconds lagged' ),
-                       array( 'code' => 'assertuserfailed', 'info' => 'Assertion that the user is logged in failed' ),
-                       array(
-                               'code' => 'assertbotfailed',
-                               'info' => 'Assertion that the user has the bot right failed'
-                       ),
-               ) );
-       }
-
        /**
         * Returns an array of strings with credits for the API
         * @return array
index 8226529..a0300ab 100644 (file)
@@ -59,13 +59,55 @@ class ApiModuleManager extends ContextSource {
        }
 
        /**
-        * Add a list of modules to the manager
-        * @param array $modules A map of ModuleName => ModuleClass
+        * Add a list of modules to the manager. Each module is described
+        * by a module spec.
+        *
+        * Each module spec is an associative array containing at least
+        * the 'class' key for the module's class, and optionally a
+        * 'factory' key for the factory function to use for the module.
+        *
+        * That factory function will be called with two parameters,
+        * the parent module (an instance of ApiBase, usually ApiMain)
+        * and the name the module was registered under. The return
+        * value must be an instance of the class given in the 'class'
+        * field.
+        *
+        * For backward compatibility, the module spec may also be a
+        * simple string containing the module's class name. In that
+        * case, the class' constructor will be called with the parent
+        * module and module name as parameters, as described above.
+        *
+        * Examples for defining module specs:
+        *
+        * @code
+        *  $modules['foo'] = 'ApiFoo';
+        *  $modules['bar'] = array(
+        *      'class' => 'ApiBar',
+        *      'factory' => function( $main, $name ) { ... }
+        *  );
+        *  $modules['xyzzy'] = array(
+        *      'class' => 'ApiXyzzy',
+        *      'factory' => array( 'XyzzyFactory', 'newApiModule' )
+        *  );
+        * @endcode
+        *
+        * @param array $modules A map of ModuleName => ModuleSpec; The ModuleSpec
+        *        is either a string containing the module's class name, or an associative
+        *        array (see above for details).
         * @param string $group Which group modules belong to (action,format,...)
         */
        public function addModules( array $modules, $group ) {
-               foreach ( $modules as $name => $class ) {
-                       $this->addModule( $name, $group, $class );
+
+               foreach ( $modules as $name => $moduleSpec ) {
+                       if ( is_array( $moduleSpec ) ) {
+                               $class = $moduleSpec['class'];
+                               $factory = ( isset( $moduleSpec['factory'] ) ? $moduleSpec['factory'] : null );
+                       } else {
+                               $class = $moduleSpec;
+                               $factory = null;
+                       }
+
+                       $this->addModule( $name, $group, $class, $factory );
                }
        }
 
@@ -74,37 +116,61 @@ class ApiModuleManager extends ContextSource {
         * classes who wish to add their own modules to their lexicon or override the
         * behavior of inherent ones.
         *
-        * @param string $group Name of the module group
         * @param string $name The identifier for this module.
+        * @param string $group Name of the module group
         * @param string $class The class where this module is implemented.
+        * @param callable|null $factory Callback for instantiating the module.
+        *
+        * @throws InvalidArgumentException
         */
-       public function addModule( $name, $group, $class ) {
+       public function addModule( $name, $group, $class, $factory = null ) {
+               if ( !is_string( $name ) ) {
+                       throw new InvalidArgumentException( '$name must be a string' );
+               }
+
+               if ( !is_string( $group ) ) {
+                       throw new InvalidArgumentException( '$group must be a string' );
+               }
+
+               if ( !is_string( $class ) ) {
+                       throw new InvalidArgumentException( '$class must be a string' );
+               }
+
+               if ( $factory !== null && !is_callable( $factory ) ) {
+                       throw new InvalidArgumentException( '$factory must be a callable (or null)' );
+               }
+
                $this->mGroups[$group] = null;
-               $this->mModules[$name] = array( $group, $class );
+               $this->mModules[$name] = array( $group, $class, $factory );
        }
 
        /**
         * Get module instance by name, or instantiate it if it does not exist
+        *
         * @param string $moduleName Module name
         * @param string $group Optionally validate that the module is in a specific group
         * @param bool $ignoreCache If true, force-creates a new instance and does not cache it
-        * @return mixed The new module instance, or null if failed
+        *
+        * @return ApiBase|null The new module instance, or null if failed
         */
        public function getModule( $moduleName, $group = null, $ignoreCache = false ) {
                if ( !isset( $this->mModules[$moduleName] ) ) {
                        return null;
                }
-               $grpCls = $this->mModules[$moduleName];
-               if ( $group !== null && $grpCls[0] !== $group ) {
+
+               list( $moduleGroup, $moduleClass, $moduleFactory ) = $this->mModules[$moduleName];
+
+               if ( $group !== null && $moduleGroup !== $group ) {
                        return null;
                }
+
                if ( !$ignoreCache && isset( $this->mInstances[$moduleName] ) ) {
                        // already exists
                        return $this->mInstances[$moduleName];
                } else {
                        // new instance
-                       $class = $grpCls[1];
-                       $instance = new $class ( $this->mParent, $moduleName );
+                       $instance = $this->instantiateModule( $moduleName, $moduleClass, $moduleFactory );
+
                        if ( !$ignoreCache ) {
                                // cache this instance in case it is needed later
                                $this->mInstances[$moduleName] = $instance;
@@ -114,6 +180,32 @@ class ApiModuleManager extends ContextSource {
                }
        }
 
+       /**
+        * Instantiate the module using the given class or factory function.
+        *
+        * @param string $name The identifier for this module.
+        * @param string $class The class where this module is implemented.
+        * @param callable|null $factory Callback for instantiating the module.
+        *
+        * @throws MWException
+        * @return ApiBase
+        */
+       private function instantiateModule( $name, $class, $factory = null ) {
+               if ( $factory !== null ) {
+                       // create instance from factory
+                       $instance = call_user_func( $factory, $this->mParent, $name );
+
+                       if ( !$instance instanceof $class ) {
+                               throw new MWException( "The factory function for module $name did not return an instance of $class!" );
+                       }
+               } else {
+                       // create instance from class name
+                       $instance = new $class( $this->mParent, $name );
+               }
+
+               return $instance;
+       }
+
        /**
         * Get an array of modules in a specific group or all if no group is set.
         * @param string $group Optional group filter
@@ -149,6 +241,21 @@ class ApiModuleManager extends ContextSource {
                return $result;
        }
 
+       /**
+        * Returns the class name of the given module
+        *
+        * @param string $module Module name
+        * @return string|bool class name or false if the module does not exist
+        * @since 1.24
+        */
+       public function getClassName( $module ) {
+               if ( isset( $this->mModules[$module] ) ) {
+                       return $this->mModules[$module][1];
+               }
+
+               return false;
+       }
+
        /**
         * Returns true if the specific module is defined at all or in a specific group.
         * @param string $moduleName Module name
index 2cfc251..04e931d 100644 (file)
@@ -134,8 +134,10 @@ class ApiMove extends ApiBase {
                        $watch = $params['watchlist'];
                } elseif ( $params['watch'] ) {
                        $watch = 'watch';
+                       $this->logFeatureUsage( 'action=move&watch' );
                } elseif ( $params['unwatch'] ) {
                        $watch = 'unwatch';
+                       $this->logFeatureUsage( 'action=move&unwatch' );
                }
 
                // Watch pages
@@ -193,10 +195,6 @@ class ApiMove extends ApiBase {
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => true
                        ),
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'reason' => '',
                        'movetalk' => false,
                        'movesubpages' => false,
@@ -229,7 +227,6 @@ class ApiMove extends ApiBase {
                        'from' => "Title of the page you want to move. Cannot be used together with {$p}fromid",
                        'fromid' => "Page ID of the page you want to move. Cannot be used together with {$p}from",
                        'to' => 'Title you want to rename the page to',
-                       'token' => 'A move token previously retrieved through prop=info',
                        'reason' => 'Reason for the move',
                        'movetalk' => 'Move the talk page, if it exists',
                        'movesubpages' => 'Move subpages, if applicable',
@@ -242,58 +239,12 @@ class ApiMove extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'from' => 'string',
-                               'to' => 'string',
-                               'reason' => 'string',
-                               'redirectcreated' => 'boolean',
-                               'moveoverredirect' => 'boolean',
-                               'talkfrom' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'talkto' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'talkmoveoverredirect' => 'boolean',
-                               'talkmove-error-code' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'talkmove-error-info' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Move a page.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(),
-                       $this->getRequireOnlyOneParameterErrorMessages( array( 'from', 'fromid' ) ),
-                       array(
-                               array( 'invalidtitle', 'from' ),
-                               array( 'nosuchpageid', 'fromid' ),
-                               array( 'notanarticle' ),
-                               array( 'invalidtitle', 'to' ),
-                               array( 'sharedfile-exists' ),
-                       )
-               );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getExamples() {
index 86d051a..b01dc3e 100644 (file)
@@ -135,10 +135,6 @@ class ApiOptions extends ApiBase {
                $optionKinds[] = 'all';
 
                return array(
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'reset' => false,
                        'resetkinds' => array(
                                ApiBase::PARAM_TYPE => $optionKinds,
@@ -157,21 +153,8 @@ class ApiOptions extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               '*' => array(
-                                       ApiBase::PROP_TYPE => array(
-                                               'success'
-                                       )
-                               )
-                       )
-               );
-       }
-
        public function getParamDescription() {
                return array(
-                       'token' => 'An options token previously obtained through the action=tokens',
                        'reset' => 'Resets preferences to the site defaults',
                        'resetkinds' => 'List of types of options to reset when the "reset" option is set',
                        'change' => array( 'List of changes, formatted name=value (e.g. skin=vector), ' .
@@ -194,19 +177,8 @@ class ApiOptions extends ApiBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'notloggedin', 'info' => 'Anonymous users cannot change preferences' ),
-                       array( 'code' => 'nochanges', 'info' => 'No changes were requested' ),
-               ) );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getHelpUrls() {
index 20444d0..0f26467 100644 (file)
@@ -61,6 +61,7 @@ class ApiPageSet extends ApiBase {
        private $mSpecialTitles = array();
        private $mNormalizedTitles = array();
        private $mInterwikiTitles = array();
+       /** @var Title[] */
        private $mPendingRedirectIDs = array();
        private $mConvertedTitles = array();
        private $mGoodRevIDs = array();
@@ -68,9 +69,7 @@ class ApiPageSet extends ApiBase {
        private $mFakePageId = -1;
        private $mCacheMode = 'public';
        private $mRequestedPageFields = array();
-       /**
-        * @var int
-        */
+       /** @var int */
        private $mDefaultNamespace = NS_MAIN;
 
        /**
@@ -389,7 +388,7 @@ class ApiPageSet extends ApiBase {
        /**
         * Get a list of redirect resolutions - maps a title to its redirect
         * target, as an array of output-ready arrays
-        * @return array
+        * @return Title[]
         */
        public function getRedirectTitles() {
                return $this->mRedirectTitles;
@@ -598,7 +597,7 @@ class ApiPageSet extends ApiBase {
 
        /**
         * Get the list of titles with negative namespace
-        * @return array Title
+        * @return Title[]
         */
        public function getSpecialTitles() {
                return $this->mSpecialTitles;
@@ -1168,21 +1167,4 @@ class ApiPageSet extends ApiBase {
                        ),
                );
        }
-
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array(
-                               'code' => 'multisource',
-                               'info' => "Cannot use 'pageids' at the same time as 'dataSource'"
-                       ),
-                       array(
-                               'code' => 'multisource',
-                               'info' => "Cannot use 'revids' at the same time as 'dataSource'"
-                       ),
-                       array(
-                               'code' => 'badgenerator',
-                               'info' => 'Module $generatorName cannot be used as a generator'
-                       ),
-               ) );
-       }
 }
index 622e3a6..067b2f5 100644 (file)
@@ -198,6 +198,10 @@ class ApiParamInfo extends ApiBase {
                                $a['required'] = '';
                        }
 
+                       if ( $n === 'token' && $obj->needsToken() ) {
+                               $a['tokentype'] = $obj->needsToken();
+                       }
+
                        if ( isset( $p[ApiBase::PARAM_DFLT] ) ) {
                                $type = $p[ApiBase::PARAM_TYPE];
                                if ( $type === 'boolean' ) {
@@ -224,7 +228,13 @@ class ApiParamInfo extends ApiBase {
                        }
 
                        if ( isset( $p[ApiBase::PARAM_TYPE] ) ) {
-                               $a['type'] = $p[ApiBase::PARAM_TYPE];
+                               if ( $p[ApiBase::PARAM_TYPE] === 'submodule' ) {
+                                       $a['type'] = $obj->getModuleManager()->getNames( $n );
+                                       sort( $a['type'] );
+                                       $a['submodules'] = '';
+                               } else {
+                                       $a['type'] = $p[ApiBase::PARAM_TYPE];
+                               }
                                if ( is_array( $a['type'] ) ) {
                                        // To prevent sparse arrays from being serialized to JSON as objects
                                        $a['type'] = array_values( $a['type'] );
@@ -244,66 +254,6 @@ class ApiParamInfo extends ApiBase {
                }
                $result->setIndexedTagName( $retval['parameters'], 'param' );
 
-               $props = $obj->getFinalResultProperties();
-               $listResult = null;
-               if ( $props !== false ) {
-                       $retval['props'] = array();
-
-                       foreach ( $props as $prop => $properties ) {
-                               $propResult = array();
-                               if ( $prop == ApiBase::PROP_LIST ) {
-                                       $listResult = $properties;
-                                       continue;
-                               }
-                               if ( $prop != ApiBase::PROP_ROOT ) {
-                                       $propResult['name'] = $prop;
-                               }
-                               $propResult['properties'] = array();
-
-                               foreach ( $properties as $name => $p ) {
-                                       $propertyResult = array();
-
-                                       $propertyResult['name'] = $name;
-
-                                       if ( !is_array( $p ) ) {
-                                               $p = array( ApiBase::PROP_TYPE => $p );
-                                       }
-
-                                       $propertyResult['type'] = $p[ApiBase::PROP_TYPE];
-
-                                       if ( is_array( $propertyResult['type'] ) ) {
-                                               $propertyResult['type'] = array_values( $propertyResult['type'] );
-                                               $result->setIndexedTagName( $propertyResult['type'], 't' );
-                                       }
-
-                                       $nullable = null;
-                                       if ( isset( $p[ApiBase::PROP_NULLABLE] ) ) {
-                                               $nullable = $p[ApiBase::PROP_NULLABLE];
-                                       }
-
-                                       if ( $nullable === true ) {
-                                               $propertyResult['nullable'] = '';
-                                       }
-
-                                       $propResult['properties'][] = $propertyResult;
-                               }
-
-                               $result->setIndexedTagName( $propResult['properties'], 'property' );
-                               $retval['props'][] = $propResult;
-                       }
-
-                       // default is true for query modules, false for other modules, overridden by ApiBase::PROP_LIST
-                       if ( $listResult === true || ( $listResult !== false && $obj instanceof ApiQueryBase ) ) {
-                               $retval['listresult'] = '';
-                       }
-
-                       $result->setIndexedTagName( $retval['props'], 'prop' );
-               }
-
-               // Errors
-               $retval['errors'] = $this->parseErrors( $obj->getFinalPossibleErrors() );
-               $result->setIndexedTagName( $retval['errors'], 'error' );
-
                return $retval;
        }
 
index b906b59..06fdf85 100644 (file)
@@ -213,7 +213,7 @@ class ApiParse extends ApiBase {
                        }
 
                        if ( $this->section !== false ) {
-                               $this->content = $this->getSectionContent( $this->content, $titleObj->getText() );
+                               $this->content = $this->getSectionContent( $this->content, $titleObj->getPrefixedText() );
                        }
 
                        if ( $params['pst'] || $params['onlypst'] ) {
@@ -450,7 +450,7 @@ class ApiParse extends ApiBase {
                if ( $this->section !== false && $this->content !== null ) {
                        $this->content = $this->getSectionContent(
                                $this->content,
-                               !is_null( $pageId ) ? 'page id ' . $pageId : $page->getTitle()->getText()
+                               !is_null( $pageId ) ? 'page id ' . $pageId : $page->getTitle()->getPrefixedText()
                        );
 
                        // Not cached (save or load)
@@ -470,6 +470,11 @@ class ApiParse extends ApiBase {
                return $pout;
        }
 
+       /**
+        * @param Content $content
+        * @param string $what Identifies the content in error messages, e.g. page title.
+        * @return Content|bool
+        */
        private function getSectionContent( Content $content, $what ) {
                // Not cached (save or load)
                $section = $content->getSection( $this->section );
@@ -800,29 +805,6 @@ class ApiParse extends ApiBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array(
-                               'code' => 'params',
-                               'info' => 'The page parameter cannot be used together with the text and title parameters'
-                       ),
-                       array( 'code' => 'missingrev', 'info' => 'There is no revision ID oldid' ),
-                       array(
-                               'code' => 'permissiondenied',
-                               'info' => 'You don\'t have permission to view deleted revisions'
-                       ),
-                       array( 'code' => 'missingtitle', 'info' => 'The page you specified doesn\'t exist' ),
-                       array( 'code' => 'nosuchsection', 'info' => 'There is no section sectionnumber in page' ),
-                       array( 'nosuchpageid' ),
-                       array( 'invalidtitle', 'title' ),
-                       array( 'code' => 'parseerror', 'info' => 'Failed to parse the given text.' ),
-                       array(
-                               'code' => 'notwikitext',
-                               'info' => 'The requested operation is only supported on wikitext content.'
-                       ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=parse&page=Project:Sandbox' => 'Parse a page',
index 00297ec..8b66781 100644 (file)
@@ -77,10 +77,6 @@ class ApiPatrol extends ApiBase {
 
        public function getAllowedParams() {
                return array(
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'rcid' => array(
                                ApiBase::PARAM_TYPE => 'integer'
                        ),
@@ -92,53 +88,23 @@ class ApiPatrol extends ApiBase {
 
        public function getParamDescription() {
                return array(
-                       'token' => 'Patrol token obtained from list=recentchanges',
                        'rcid' => 'Recentchanges ID to patrol',
                        'revid' => 'Revision ID to patrol',
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'rcid' => 'integer',
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Patrol a page or revision.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge(
-                       parent::getPossibleErrors(),
-                       parent::getRequireOnlyOneParameterErrorMessages( array( 'rcid', 'revid' ) ),
-                       array(
-                               array( 'nosuchrcid', 'rcid' ),
-                               array( 'nosuchrevid', 'revid' ),
-                               array(
-                                       'code' => 'notpatrollable',
-                                       'info' => "The revision can't be patrolled as it's too old"
-                               )
-                       )
-               );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
                return 'patrol';
        }
 
        public function getExamples() {
                return array(
-                       'api.php?action=patrol&token=123abc&rcid=230672766',
-                       'api.php?action=patrol&token=123abc&revid=230672766'
+                       'api.php?action=patrol&token=123ABC&rcid=230672766',
+                       'api.php?action=patrol&token=123ABC&revid=230672766'
                );
        }
 
index b9f97e3..a3d12b7 100644 (file)
@@ -102,6 +102,9 @@ class ApiProtect extends ApiBase {
 
                $cascade = $params['cascade'];
 
+               if ( $params['watch'] ) {
+                       $this->logFeatureUsage( 'action=protect&watch' );
+               }
                $watch = $params['watch'] ? 'watch' : $params['watchlist'];
                $this->setWatch( $watch, $titleObj, 'watchdefault' );
 
@@ -145,10 +148,6 @@ class ApiProtect extends ApiBase {
                        'pageid' => array(
                                ApiBase::PARAM_TYPE => 'integer',
                        ),
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'protections' => array(
                                ApiBase::PARAM_ISMULTI => true,
                                ApiBase::PARAM_REQUIRED => true,
@@ -182,7 +181,6 @@ class ApiProtect extends ApiBase {
                return array(
                        'title' => "Title of the page you want to (un)protect. Cannot be used together with {$p}pageid",
                        'pageid' => "ID of the page you want to (un)protect. Cannot be used together with {$p}title",
-                       'token' => 'A protect token previously retrieved through prop=info',
                        'protections' => 'List of protection levels, formatted action=group (e.g. edit=sysop)',
                        'expiry' => array(
                                'Expiry timestamps. If only one timestamp is ' .
@@ -200,41 +198,12 @@ class ApiProtect extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'title' => 'string',
-                               'reason' => 'string',
-                               'cascade' => 'boolean'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Change the protection level of a page.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(),
-                       $this->getTitleOrPageIdErrorMessage(),
-                       array(
-                               array( 'toofewexpiries', 'noofexpiries', 'noofprotections' ),
-                               array( 'create-titleexists' ),
-                               array( 'missingtitle-createonly' ),
-                               array( 'protect-invalidaction', 'action' ),
-                               array( 'protect-invalidlevel', 'level' ),
-                               array( 'invalidexpiry', 'expiry' ),
-                               array( 'pastexpiry', 'expiry' ),
-                       )
-               );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getExamples() {
index 3399843..7667b23 100644 (file)
@@ -152,52 +152,12 @@ class ApiPurge extends ApiBase {
                        );
        }
 
-       public function getResultProperties() {
-               return array(
-                       ApiBase::PROP_LIST => true,
-                       '' => array(
-                               'ns' => array(
-                                       ApiBase::PROP_TYPE => 'namespace',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'title' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'pageid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'revid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'invalid' => 'boolean',
-                               'special' => 'boolean',
-                               'missing' => 'boolean',
-                               'purged' => 'boolean',
-                               'linkupdate' => 'boolean',
-                               'iw' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                       )
-               );
-       }
-
        public function getDescription() {
                return array( 'Purge the cache for the given titles.',
                        'Requires a POST request if the user is not logged in.'
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge(
-                       parent::getPossibleErrors(),
-                       $this->getPageSet()->getFinalPossibleErrors()
-               );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=purge&titles=Main_Page|API' => 'Purge the "Main Page" and the "API" page',
index cd6a840..8407fad 100644 (file)
@@ -108,6 +108,7 @@ class ApiQuery extends ApiBase {
                'siteinfo' => 'ApiQuerySiteinfo',
                'userinfo' => 'ApiQueryUserInfo',
                'filerepoinfo' => 'ApiQueryFileRepoInfo',
+               'tokens' => 'ApiQueryTokens',
        );
 
        /**
@@ -180,7 +181,7 @@ class ApiQuery extends ApiBase {
        /**
         * Get the array mapping module names to class names
         * @deprecated since 1.21, use getModuleManager()'s methods instead
-        * @return array array(modulename => classname)
+        * @return array Array(modulename => classname)
         */
        public function getModules() {
                wfDeprecated( __METHOD__, '1.21' );
@@ -191,7 +192,7 @@ class ApiQuery extends ApiBase {
        /**
         * Get the generators array mapping module names to class names
         * @deprecated since 1.21, list of generators is maintained by ApiPageSet
-        * @return array array(modulename => classname)
+        * @return array Array(modulename => classname)
         */
        public function getGenerators() {
                wfDeprecated( __METHOD__, '1.21' );
@@ -348,29 +349,29 @@ class ApiQuery extends ApiBase {
                $pageSet = $this->getPageSet();
                $result = $this->getResult();
 
-               // We don't check for a full result set here because we can't be adding
-               // more than 380K. The maximum revision size is in the megabyte range,
-               // and the maximum result size must be even higher than that.
+               // We can't really handle max-result-size failure here, but we need to
+               // check anyway in case someone set the limit stupidly low.
+               $fit = true;
 
                $values = $pageSet->getNormalizedTitlesAsResult( $result );
                if ( $values ) {
-                       $result->addValue( 'query', 'normalized', $values );
+                       $fit = $fit && $result->addValue( 'query', 'normalized', $values );
                }
                $values = $pageSet->getConvertedTitlesAsResult( $result );
                if ( $values ) {
-                       $result->addValue( 'query', 'converted', $values );
+                       $fit = $fit && $result->addValue( 'query', 'converted', $values );
                }
                $values = $pageSet->getInterwikiTitlesAsResult( $result, $this->mParams['iwurl'] );
                if ( $values ) {
-                       $result->addValue( 'query', 'interwiki', $values );
+                       $fit = $fit && $result->addValue( 'query', 'interwiki', $values );
                }
                $values = $pageSet->getRedirectTitlesAsResult( $result );
                if ( $values ) {
-                       $result->addValue( 'query', 'redirects', $values );
+                       $fit = $fit && $result->addValue( 'query', 'redirects', $values );
                }
                $values = $pageSet->getMissingRevisionIDsAsResult( $result );
                if ( $values ) {
-                       $result->addValue( 'query', 'badrevids', $values );
+                       $fit = $fit && $result->addValue( 'query', 'badrevids', $values );
                }
 
                // Page elements
@@ -426,12 +427,21 @@ class ApiQuery extends ApiBase {
                                // json treats all map keys as strings - converting to match
                                $pageIDs = array_map( 'strval', $pageIDs );
                                $result->setIndexedTagName( $pageIDs, 'id' );
-                               $result->addValue( 'query', 'pageids', $pageIDs );
+                               $fit = $fit && $result->addValue( 'query', 'pageids', $pageIDs );
                        }
 
                        $result->setIndexedTagName( $pages, 'page' );
-                       $result->addValue( 'query', 'pages', $pages );
+                       $fit = $fit && $result->addValue( 'query', 'pages', $pages );
                }
+
+               if ( !$fit ) {
+                       $this->dieUsage(
+                               'The value of $wgAPIMaxResultSize on this wiki is ' .
+                                       'too small to hold basic result information',
+                               'badconfig'
+                       );
+               }
+
                if ( $this->mParams['export'] ) {
                        $this->doExport( $pageSet, $result );
                }
@@ -441,7 +451,7 @@ class ApiQuery extends ApiBase {
         * This method is called by the generator base when generator in the smart-continue
         * mode tries to set 'query-continue' value. ApiQuery stores those values separately
         * until the post-processing when it is known if the generation should continue or repeat.
-        * @deprecated @since 1.24
+        * @deprecated since 1.24
         * @param ApiQueryGeneratorBase $module Generator module
         * @param string $paramName
         * @param mixed $paramValue
@@ -485,39 +495,38 @@ class ApiQuery extends ApiBase {
                // Don't check the size of exported stuff
                // It's not continuable, so it would cause more
                // problems than it'd solve
-               $result->disableSizeCheck();
                if ( $this->mParams['exportnowrap'] ) {
                        $result->reset();
                        // Raw formatter will handle this
-                       $result->addValue( null, 'text', $exportxml );
-                       $result->addValue( null, 'mime', 'text/xml' );
+                       $result->addValue( null, 'text', $exportxml, ApiResult::NO_SIZE_CHECK );
+                       $result->addValue( null, 'mime', 'text/xml', ApiResult::NO_SIZE_CHECK );
                } else {
                        $r = array();
                        ApiResult::setContent( $r, $exportxml );
-                       $result->addValue( 'query', 'export', $r );
+                       $result->addValue( 'query', 'export', $r, ApiResult::NO_SIZE_CHECK );
                }
-               $result->enableSizeCheck();
        }
 
        public function getAllowedParams( $flags = 0 ) {
                $result = array(
                        'prop' => array(
                                ApiBase::PARAM_ISMULTI => true,
-                               ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'prop' )
+                               ApiBase::PARAM_TYPE => 'submodule',
                        ),
                        'list' => array(
                                ApiBase::PARAM_ISMULTI => true,
-                               ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'list' )
+                               ApiBase::PARAM_TYPE => 'submodule',
                        ),
                        'meta' => array(
                                ApiBase::PARAM_ISMULTI => true,
-                               ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'meta' )
+                               ApiBase::PARAM_TYPE => 'submodule',
                        ),
                        'indexpageids' => false,
                        'export' => false,
                        'exportnowrap' => false,
                        'iwurl' => false,
                        'continue' => null,
+                       'rawcontinue' => false,
                );
                if ( $flags ) {
                        $result += $this->getPageSet()->getFinalParams( $flags );
@@ -600,6 +609,8 @@ class ApiQuery extends ApiBase {
                                'This parameter is recommended for all new development, and ' .
                                        'will be made default in the next API version.'
                        ),
+                       'rawcontinue' => 'Currently ignored. In the future, \'continue=\' will become the ' .
+                               'default and this will be needed to receive the raw query-continue data.',
                );
        }
 
@@ -613,13 +624,6 @@ class ApiQuery extends ApiBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge(
-                       parent::getPossibleErrors(),
-                       $this->getPageSet()->getFinalPossibleErrors()
-               );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&prop=revisions&meta=siteinfo&' .
index 1b65097..79fab72 100644 (file)
@@ -207,23 +207,6 @@ class ApiQueryAllCategories extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               '*' => 'string'
-                       ),
-                       'size' => array(
-                               'size' => 'integer',
-                               'pages' => 'integer',
-                               'files' => 'integer',
-                               'subcats' => 'integer'
-                       ),
-                       'hidden' => array(
-                               'hidden' => 'boolean'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Enumerate all categories.';
        }
index 68d968f..9dc5f69 100644 (file)
@@ -393,76 +393,10 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
 
        private $propertyFilter = array( 'archivename', 'thumbmime', 'uploadwarning' );
 
-       public function getResultProperties() {
-               return array_merge(
-                       array(
-                               '' => array(
-                                       'name' => 'string',
-                                       'ns' => 'namespace',
-                                       'title' => 'string'
-                               )
-                       ),
-                       ApiQueryImageInfo::getResultPropertiesFiltered( $this->propertyFilter )
-               );
-       }
-
        public function getDescription() {
                return 'Enumerate all images sequentially.';
        }
 
-       public function getPossibleErrors() {
-               $p = $this->getModulePrefix();
-
-               return array_merge( parent::getPossibleErrors(), array(
-                       array(
-                               'code' => 'params',
-                               'info' => 'Use "gaifilterredir=nonredirects" option instead ' .
-                                       'of "redirects" when using allimages as a generator'
-                       ),
-                       array(
-                               'code' => 'badparams',
-                               'info' => "Parameter'{$p}start' can only be used with {$p}sort=timestamp"
-                       ),
-                       array(
-                               'code' => 'badparams',
-                               'info' => "Parameter'{$p}end' can only be used with {$p}sort=timestamp"
-                       ),
-                       array(
-                               'code' => 'badparams',
-                               'info' => "Parameter'{$p}user' can only be used with {$p}sort=timestamp"
-                       ),
-                       array(
-                               'code' => 'badparams',
-                               'info' => "Parameter'{$p}filterbots' can only be used with {$p}sort=timestamp"
-                       ),
-                       array(
-                               'code' => 'badparams',
-                               'info' => "Parameter'{$p}from' can only be used with {$p}sort=name"
-                       ),
-                       array(
-                               'code' => 'badparams',
-                               'info' => "Parameter'{$p}to' can only be used with {$p}sort=name"
-                       ),
-                       array(
-                               'code' => 'badparams',
-                               'info' => "Parameter'{$p}prefix' can only be used with {$p}sort=name"
-                       ),
-                       array(
-                               'code' => 'badparams',
-                               'info' => "Parameters '{$p}user' and '{$p}filterbots' cannot be used together"
-                       ),
-                       array(
-                               'code' => 'unsupportedrepo',
-                               'info' => 'Local file repository does not support querying all images' ),
-                       array( 'code' => 'mimesearchdisabled', 'info' => 'MIME search disabled in Miser Mode' ),
-                       array( 'code' => 'invalidsha1hash', 'info' => 'The SHA1 hash provided is not valid' ),
-                       array(
-                               'code' => 'invalidsha1base36hash',
-                               'info' => 'The SHA1Base36 hash provided is not valid'
-                       ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=allimages&aifrom=B' => array(
index 61bc90e..903dee4 100644 (file)
@@ -334,34 +334,10 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
                return $paramDescription;
        }
 
-       public function getResultProperties() {
-               return array(
-                       'ids' => array(
-                               'fromid' => 'integer'
-                       ),
-                       'title' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return $this->description;
        }
 
-       public function getPossibleErrors() {
-               $m = $this->getModuleName();
-               $what = $this->descriptionWhat;
-
-               return array_merge( parent::getPossibleErrors(), array(
-                       array(
-                               'code' => 'params',
-                               'info' => "{$m} cannot return corresponding page ids in unique {$what}s mode"
-                       ),
-               ) );
-       }
-
        public function getExamples() {
                $p = $this->getModulePrefix();
                $name = $this->getModuleName();
index c6171e9..a75a16f 100644 (file)
@@ -256,33 +256,6 @@ class ApiQueryAllMessages extends ApiQueryBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'invalidlang', 'info' => 'Invalid language code for parameter lang' ),
-               ) );
-       }
-
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'name' => 'string',
-                               'customised' => 'boolean',
-                               'missing' => 'boolean',
-                               '*' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'default' => array(
-                               'defaultmissing' => 'boolean',
-                               'default' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Return messages from this site.';
        }
index a3ba5ab..b7bd65a 100644 (file)
@@ -328,31 +328,10 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'pageid' => 'integer',
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Enumerate all pages sequentially in a given namespace.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array(
-                               'code' => 'params',
-                               'info' => 'Use "gapfilterredir=nonredirects" option instead of ' .
-                                       '"redirects" when using allpages as a generator'
-                       ),
-                       array( 'code' => 'params', 'info' => 'prlevel may not be used without prtype' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=allpages&apfrom=B' => array(
index d0980e6..d241311 100644 (file)
@@ -46,10 +46,11 @@ class ApiQueryAllUsers extends ApiQueryBase {
 
        public function execute() {
                $params = $this->extractRequestParams();
+               $activeUserDays = $this->getConfig()->get( 'ActiveUserDays' );
 
                if ( $params['activeusers'] ) {
                        // Update active user cache
-                       SpecialActiveUsers::mergeActiveUsers( 600 );
+                       SpecialActiveUsers::mergeActiveUsers( 600, $activeUserDays );
                }
 
                $db = $this->getDB();
@@ -110,35 +111,18 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        }
                }
 
-               if ( !is_null( $params['group'] ) && !is_null( $params['excludegroup'] ) ) {
-                       $this->dieUsage( 'group and excludegroup cannot be used together', 'group-excludegroup' );
-               }
-
                if ( !is_null( $params['group'] ) && count( $params['group'] ) ) {
-                       $useIndex = false;
                        // Filter only users that belong to a given group
-                       $this->addTables( 'user_groups', 'ug1' );
-                       $this->addJoinConds( array( 'ug1' => array( 'INNER JOIN', array( 'ug1.ug_user=user_id',
-                               'ug1.ug_group' => $params['group'] ) ) ) );
+                       $this->addWhere( 'EXISTS (' . $db->selectSQLText(
+                               'user_groups', '1', array( 'ug_user=user_id', 'ug_group' => $params['group'] )
+                       ) . ')' );
                }
 
                if ( !is_null( $params['excludegroup'] ) && count( $params['excludegroup'] ) ) {
-                       $useIndex = false;
                        // Filter only users don't belong to a given group
-                       $this->addTables( 'user_groups', 'ug1' );
-
-                       if ( count( $params['excludegroup'] ) == 1 ) {
-                               $exclude = array( 'ug1.ug_group' => $params['excludegroup'][0] );
-                       } else {
-                               $exclude = array( $db->makeList(
-                                       array( 'ug1.ug_group' => $params['excludegroup'] ),
-                                       LIST_OR
-                               ) );
-                       }
-                       $this->addJoinConds( array( 'ug1' => array( 'LEFT OUTER JOIN',
-                               array_merge( array( 'ug1.ug_user=user_id' ), $exclude )
-                       ) ) );
-                       $this->addWhere( 'ug1.ug_user IS NULL' );
+                       $this->addWhere( 'NOT EXISTS (' . $db->selectSQLText(
+                               'user_groups', '1', array( 'ug_user=user_id', 'ug_group' => $params['excludegroup'] )
+                       ) . ')' );
                }
 
                if ( $params['witheditsonly'] ) {
@@ -155,13 +139,13 @@ class ApiQueryAllUsers extends ApiQueryBase {
 
                        $this->addTables( 'user_groups', 'ug2' );
                        $this->addJoinConds( array( 'ug2' => array( 'LEFT JOIN', 'ug2.ug_user=user_id' ) ) );
-                       $this->addFields( 'ug2.ug_group ug_group2' );
+                       $this->addFields( array( 'ug_group2' => 'ug2.ug_group' ) );
                } else {
                        $sqlLimit = $limit + 1;
                }
 
                if ( $params['activeusers'] ) {
-                       $activeUserSeconds = $this->getConfig()->get( 'ActiveUserDays' ) * 86400;
+                       $activeUserSeconds = $activeUserDays * 86400;
 
                        // Filter query to only include users in the active users cache
                        $this->addTables( 'querycachetwo' );
@@ -255,6 +239,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
                                        $lastUserData['blockid'] = $row->ipb_id;
                                        $lastUserData['blockedby'] = $row->ipb_by_text;
                                        $lastUserData['blockedbyid'] = $row->ipb_by;
+                                       $lastUserData['blockedtimestamp'] = wfTimestamp( TS_ISO_8601, $row->ipb_timestamp );
                                        $lastUserData['blockreason'] = $row->ipb_reason;
                                        $lastUserData['blockexpiry'] = $row->ipb_expiry;
                                }
@@ -420,61 +405,10 @@ class ApiQueryAllUsers extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'userid' => 'integer',
-                               'name' => 'string',
-                               'recentactions' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'blockinfo' => array(
-                               'blockid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedby' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedbyid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedreason' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedexpiry' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'hidden' => 'boolean'
-                       ),
-                       'editcount' => array(
-                               'editcount' => 'integer'
-                       ),
-                       'registration' => array(
-                               'registration' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Enumerate all registered users.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array(
-                               'code' => 'group-excludegroup',
-                               'info' => 'group and excludegroup cannot be used together'
-                       ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=allusers&aufrom=Y',
index 8dc2a65..c141246 100644 (file)
@@ -520,17 +520,6 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                ) );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'pageid' => 'integer',
-                               'ns' => 'namespace',
-                               'title' => 'string',
-                               'redirect' => 'boolean'
-                       )
-               );
-       }
-
        public function getDescription() {
                switch ( $this->getModuleName() ) {
                        case 'backlinks':
@@ -544,18 +533,6 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                }
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(),
-                       $this->getTitleOrPageIdErrorMessage(),
-                       array(
-                               array(
-                                       'code' => 'bad_image_title',
-                                       'info' => "The title for {$this->getModuleName()} query must be an image"
-                               ),
-                       )
-               );
-       }
-
        public function getExamples() {
                static $examples = array(
                        'backlinks' => array(
index 2fd8597..65e10ab 100644 (file)
@@ -47,6 +47,11 @@ abstract class ApiQueryBase extends ApiBase {
                $this->resetQueryParams();
        }
 
+       /************************************************************************//**
+        * @name   Methods to implement
+        * @{
+        */
+
        /**
         * Get the cache mode for the data generated by this module. Override
         * this in the module subclass. For possible return values and other
@@ -62,6 +67,68 @@ abstract class ApiQueryBase extends ApiBase {
                return 'private';
        }
 
+       /**
+        * Override this method to request extra fields from the pageSet
+        * using $pageSet->requestField('fieldName')
+        * @param ApiPageSet $pageSet
+        */
+       public function requestExtraData( $pageSet ) {
+       }
+
+       /**@}*/
+
+       /************************************************************************//**
+        * @name   Data access
+        * @{
+        */
+
+       /**
+        * Get the main Query module
+        * @return ApiQuery
+        */
+       public function getQuery() {
+               return $this->mQueryModule;
+       }
+
+       /**
+        * Get the Query database connection (read-only)
+        * @return DatabaseBase
+        */
+       protected function getDB() {
+               if ( is_null( $this->mDb ) ) {
+                       $this->mDb = $this->getQuery()->getDB();
+               }
+
+               return $this->mDb;
+       }
+
+       /**
+        * Selects the query database connection with the given name.
+        * See ApiQuery::getNamedDB() for more information
+        * @param string $name Name to assign to the database connection
+        * @param int $db One of the DB_* constants
+        * @param array $groups Query groups
+        * @return DatabaseBase
+        */
+       public function selectNamedDB( $name, $db, $groups ) {
+               $this->mDb = $this->getQuery()->getNamedDB( $name, $db, $groups );
+       }
+
+       /**
+        * Get the PageSet object to work on
+        * @return ApiPageSet
+        */
+       protected function getPageSet() {
+               return $this->getQuery()->getPageSet();
+       }
+
+       /**@}*/
+
+       /************************************************************************//**
+        * @name   Querying
+        * @{
+        */
+
        /**
         * Blank the internal arrays with query parameters
         */
@@ -75,8 +142,8 @@ abstract class ApiQueryBase extends ApiBase {
 
        /**
         * Add a set of tables to the internal array
-        * @param mixed $tables Table name or array of table names
-        * @param mixed $alias Table alias, or null for no alias. Cannot be
+        * @param string|string[] $tables Table name or array of table names
+        * @param string|null $alias Table alias, or null for no alias. Cannot be
         *  used with multiple tables
         */
        protected function addTables( $tables, $alias = null ) {
@@ -305,29 +372,64 @@ abstract class ApiQueryBase extends ApiBase {
        }
 
        /**
-        * Estimate the row count for the SELECT query that would be run if we
-        * called select() right now, and check if it's acceptable.
-        * @return bool True if acceptable, false otherwise
+        * @param string $query
+        * @param string $protocol
+        * @return null|string
         */
-       protected function checkRowCount() {
-               $db = $this->getDB();
-               $this->profileDBIn();
-               $rowcount = $db->estimateRowCount(
-                       $this->tables,
-                       $this->fields,
-                       $this->where,
-                       __METHOD__,
-                       $this->options
-               );
-               $this->profileDBOut();
+       public function prepareUrlQuerySearchString( $query = null, $protocol = null ) {
+               $db = $this->getDb();
+               if ( !is_null( $query ) || $query != '' ) {
+                       if ( is_null( $protocol ) ) {
+                               $protocol = 'http://';
+                       }
 
-               if ( $rowcount > $this->getConfig()->get( 'APIMaxDBRows' ) ) {
-                       return false;
+                       $likeQuery = LinkFilter::makeLikeArray( $query, $protocol );
+                       if ( !$likeQuery ) {
+                               $this->dieUsage( 'Invalid query', 'bad_query' );
+                       }
+
+                       $likeQuery = LinkFilter::keepOneWildcard( $likeQuery );
+
+                       return 'el_index ' . $db->buildLike( $likeQuery );
+               } elseif ( !is_null( $protocol ) ) {
+                       return 'el_index ' . $db->buildLike( "$protocol", $db->anyString() );
                }
 
-               return true;
+               return null;
+       }
+
+       /**
+        * Filters hidden users (where the user doesn't have the right to view them)
+        * Also adds relevant block information
+        *
+        * @param bool $showBlockInfo
+        * @return void
+        */
+       public function showHiddenUsersAddBlockInfo( $showBlockInfo ) {
+               $this->addTables( 'ipblocks' );
+               $this->addJoinConds( array(
+                       'ipblocks' => array( 'LEFT JOIN', 'ipb_user=user_id' ),
+               ) );
+
+               $this->addFields( 'ipb_deleted' );
+
+               if ( $showBlockInfo ) {
+                       $this->addFields( array( 'ipb_id', 'ipb_by', 'ipb_by_text', 'ipb_reason', 'ipb_expiry', 'ipb_timestamp' ) );
+               }
+
+               // Don't show hidden names
+               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
+                       $this->addWhere( 'ipb_deleted = 0 OR ipb_deleted IS NULL' );
+               }
        }
 
+       /**@}*/
+
+       /************************************************************************//**
+        * @name   Utility methods
+        * @{
+        */
+
        /**
         * Add information (title and namespace) about a Title object to a
         * result array
@@ -340,22 +442,6 @@ abstract class ApiQueryBase extends ApiBase {
                $arr[$prefix . 'title'] = $title->getPrefixedText();
        }
 
-       /**
-        * Override this method to request extra fields from the pageSet
-        * using $pageSet->requestField('fieldName')
-        * @param ApiPageSet $pageSet
-        */
-       public function requestExtraData( $pageSet ) {
-       }
-
-       /**
-        * Get the main Query module
-        * @return ApiQuery
-        */
-       public function getQuery() {
-               return $this->mQueryModule;
-       }
-
        /**
         * Add a sub-element under the page element with the given page ID
         * @param int $pageId Page ID
@@ -405,89 +491,21 @@ abstract class ApiQueryBase extends ApiBase {
        }
 
        /**
-        * Get the Query database connection (read-only)
-        * @return DatabaseBase
-        */
-       protected function getDB() {
-               if ( is_null( $this->mDb ) ) {
-                       $this->mDb = $this->getQuery()->getDB();
-               }
-
-               return $this->mDb;
-       }
-
-       /**
-        * Selects the query database connection with the given name.
-        * See ApiQuery::getNamedDB() for more information
-        * @param string $name Name to assign to the database connection
-        * @param int $db One of the DB_* constants
-        * @param array $groups Query groups
-        * @return DatabaseBase
-        */
-       public function selectNamedDB( $name, $db, $groups ) {
-               $this->mDb = $this->getQuery()->getNamedDB( $name, $db, $groups );
-       }
-
-       /**
-        * Get the PageSet object to work on
-        * @return ApiPageSet
-        */
-       protected function getPageSet() {
-               return $this->getQuery()->getPageSet();
-       }
-
-       /**
-        * Convert a title to a DB key
-        * @param string $title Page title with spaces
-        * @return string Page title with underscores
-        */
-       public function titleToKey( $title ) {
-               // Don't throw an error if we got an empty string
-               if ( trim( $title ) == '' ) {
-                       return '';
-               }
-               $t = Title::newFromText( $title );
-               if ( !$t ) {
-                       $this->dieUsageMsg( array( 'invalidtitle', $title ) );
-               }
-
-               return $t->getPrefixedDBkey();
-       }
-
-       /**
-        * The inverse of titleToKey()
-        * @param string $key Page title with underscores
-        * @return string Page title with spaces
-        */
-       public function keyToTitle( $key ) {
-               // Don't throw an error if we got an empty string
-               if ( trim( $key ) == '' ) {
-                       return '';
-               }
-               $t = Title::newFromDBkey( $key );
-               // This really shouldn't happen but we gotta check anyway
-               if ( !$t ) {
-                       $this->dieUsageMsg( array( 'invalidtitle', $key ) );
-               }
-
-               return $t->getPrefixedText();
-       }
-
-       /**
-        * An alternative to titleToKey() that doesn't trim trailing spaces, and
-        * does not mangle the input if starts with something that looks like a
-        * namespace. It is advisable to pass the namespace parameter in order to
-        * handle per-namespace capitalization settings.
-        * @param string $titlePart Title part with spaces
-        * @param int $defaultNamespace Namespace to assume
-        * @return string Title part with underscores
+        * Convert an input title or title prefix into a dbkey.
+        *
+        * $namespace should always be specified in order to handle per-namespace
+        * capitalization settings.
+        *
+        * @param string $titlePart Title part
+        * @param int $defaultNamespace Namespace of the title
+        * @return string DBkey (no namespace prefix)
         */
-       public function titlePartToKey( $titlePart, $defaultNamespace = NS_MAIN ) {
-               $t = Title::makeTitleSafe( $defaultNamespace, $titlePart . 'x' );
+       public function titlePartToKey( $titlePart, $namespace = NS_MAIN ) {
+               $t = Title::makeTitleSafe( $namespace, $titlePart . 'x' );
                if ( !$t ) {
                        $this->dieUsageMsg( array( 'invalidtitle', $titlePart ) );
                }
-               if ( $defaultNamespace != $t->getNamespace() || $t->isExternal() ) {
+               if ( $namespace != $t->getNamespace() || $t->isExternal() ) {
                        // This can happen in two cases. First, if you call titlePartToKey with a title part
                        // that looks like a namespace, but with $defaultNamespace = NS_MAIN. It would be very
                        // difficult to handle such a case. Such cases cannot exist and are therefore treated
@@ -499,15 +517,6 @@ abstract class ApiQueryBase extends ApiBase {
                return substr( $t->getDbKey(), 0, -1 );
        }
 
-       /**
-        * An alternative to keyToTitle() that doesn't trim trailing spaces
-        * @param string $keyPart Key part with spaces
-        * @return string Key part with underscores
-        */
-       public function keyPartToTitle( $keyPart ) {
-               return substr( $this->keyToTitle( $keyPart . 'x' ), 0, -1 );
-       }
-
        /**
         * Gets the personalised direction parameter description
         *
@@ -524,94 +533,122 @@ abstract class ApiQueryBase extends ApiBase {
        }
 
        /**
-        * @param string $query
-        * @param string $protocol
-        * @return null|string
+        * @param string $hash
+        * @return bool
         */
-       public function prepareUrlQuerySearchString( $query = null, $protocol = null ) {
-               $db = $this->getDb();
-               if ( !is_null( $query ) || $query != '' ) {
-                       if ( is_null( $protocol ) ) {
-                               $protocol = 'http://';
-                       }
+       public function validateSha1Hash( $hash ) {
+               return preg_match( '/^[a-f0-9]{40}$/', $hash );
+       }
 
-                       $likeQuery = LinkFilter::makeLikeArray( $query, $protocol );
-                       if ( !$likeQuery ) {
-                               $this->dieUsage( 'Invalid query', 'bad_query' );
-                       }
+       /**
+        * @param string $hash
+        * @return bool
+        */
+       public function validateSha1Base36Hash( $hash ) {
+               return preg_match( '/^[a-z0-9]{31}$/', $hash );
+       }
 
-                       $likeQuery = LinkFilter::keepOneWildcard( $likeQuery );
+       /**
+        * Check whether the current user has permission to view revision-deleted
+        * fields.
+        * @return bool
+        */
+       public function userCanSeeRevDel() {
+               return $this->getUser()->isAllowedAny(
+                       'deletedhistory',
+                       'deletedtext',
+                       'suppressrevision',
+                       'viewsuppressed'
+               );
+       }
 
-                       return 'el_index ' . $db->buildLike( $likeQuery );
-               } elseif ( !is_null( $protocol ) ) {
-                       return 'el_index ' . $db->buildLike( "$protocol", $db->anyString() );
-               }
+       /**@}*/
 
-               return null;
-       }
+       /************************************************************************//**
+        * @name   Deprecated
+        * @{
+        */
 
        /**
-        * Filters hidden users (where the user doesn't have the right to view them)
-        * Also adds relevant block information
-        *
-        * @param bool $showBlockInfo
-        * @return void
+        * Estimate the row count for the SELECT query that would be run if we
+        * called select() right now, and check if it's acceptable.
+        * @deprecated since 1.24
+        * @return bool True if acceptable, false otherwise
         */
-       public function showHiddenUsersAddBlockInfo( $showBlockInfo ) {
-               $this->addTables( 'ipblocks' );
-               $this->addJoinConds( array(
-                       'ipblocks' => array( 'LEFT JOIN', 'ipb_user=user_id' ),
-               ) );
-
-               $this->addFields( 'ipb_deleted' );
+       protected function checkRowCount() {
+               wfDeprecated( __METHOD__, '1.24' );
+               $db = $this->getDB();
+               $this->profileDBIn();
+               $rowcount = $db->estimateRowCount(
+                       $this->tables,
+                       $this->fields,
+                       $this->where,
+                       __METHOD__,
+                       $this->options
+               );
+               $this->profileDBOut();
 
-               if ( $showBlockInfo ) {
-                       $this->addFields( array( 'ipb_id', 'ipb_by', 'ipb_by_text', 'ipb_reason', 'ipb_expiry' ) );
+               if ( $rowcount > $this->getConfig()->get( 'APIMaxDBRows' ) ) {
+                       return false;
                }
 
-               // Don't show hidden names
-               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
-                       $this->addWhere( 'ipb_deleted = 0 OR ipb_deleted IS NULL' );
-               }
+               return true;
        }
 
        /**
-        * @param string $hash
-        * @return bool
+        * Convert a title to a DB key
+        * @deprecated since 1.24, past uses of this were always incorrect and should
+        *   have used self::titlePartToKey() instead
+        * @param string $title Page title with spaces
+        * @return string Page title with underscores
         */
-       public function validateSha1Hash( $hash ) {
-               return preg_match( '/^[a-f0-9]{40}$/', $hash );
-       }
+       public function titleToKey( $title ) {
+               wfDeprecated( __METHOD__, '1.24' );
+               // Don't throw an error if we got an empty string
+               if ( trim( $title ) == '' ) {
+                       return '';
+               }
+               $t = Title::newFromText( $title );
+               if ( !$t ) {
+                       $this->dieUsageMsg( array( 'invalidtitle', $title ) );
+               }
 
-       /**
-        * @param string $hash
-        * @return bool
-        */
-       public function validateSha1Base36Hash( $hash ) {
-               return preg_match( '/^[a-z0-9]{31}$/', $hash );
+               return $t->getPrefixedDBkey();
        }
 
        /**
-        * @return array
+        * The inverse of titleToKey()
+        * @deprecated since 1.24, unused and probably never needed
+        * @param string $key Page title with underscores
+        * @return string Page title with spaces
         */
-       public function getPossibleErrors() {
-               $errors = parent::getPossibleErrors();
-               $errors = array_merge( $errors, array(
-                       array( 'invalidtitle', 'title' ),
-                       array( 'invalidtitle', 'key' ),
-               ) );
+       public function keyToTitle( $key ) {
+               wfDeprecated( __METHOD__, '1.24' );
+               // Don't throw an error if we got an empty string
+               if ( trim( $key ) == '' ) {
+                       return '';
+               }
+               $t = Title::newFromDBkey( $key );
+               // This really shouldn't happen but we gotta check anyway
+               if ( !$t ) {
+                       $this->dieUsageMsg( array( 'invalidtitle', $key ) );
+               }
 
-               return $errors;
+               return $t->getPrefixedText();
        }
 
        /**
-        * Check whether the current user has permission to view revision-deleted
-        * fields.
-        * @return bool
+        * Inverse of titlePartToKey()
+        * @deprecated since 1.24, unused and probably never needed
+        * @param string $keyPart DBkey, with prefix
+        * @return string Key part with underscores
         */
-       public function userCanSeeRevDel() {
-               return $this->getUser()->isAllowedAny( 'deletedhistory', 'deletedtext', 'suppressrevision' );
+       public function keyPartToTitle( $keyPart ) {
+               wfDeprecated( __METHOD__, '1.24' );
+               return substr( $this->keyToTitle( $keyPart . 'x' ), 0, -1 );
        }
+
+       /**@}*/
 }
 
 /**
@@ -649,7 +686,7 @@ abstract class ApiQueryGeneratorBase extends ApiQueryBase {
        }
 
        /**
-        * Overrides base class to prepend 'g' to every generator parameter
+        * Overrides ApiBase to prepend 'g' to every generator parameter
         * @param string $paramName Parameter name
         * @return string Prefixed parameter name
         */
index d62e87d..33b25fd 100644 (file)
@@ -368,86 +368,10 @@ class ApiQueryBlocks extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       'id' => array(
-                               'id' => 'integer'
-                       ),
-                       'user' => array(
-                               'user' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'userid' => array(
-                               'userid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'by' => array(
-                               'by' => 'string'
-                       ),
-                       'byid' => array(
-                               'byid' => 'integer'
-                       ),
-                       'timestamp' => array(
-                               'timestamp' => 'timestamp'
-                       ),
-                       'expiry' => array(
-                               'expiry' => 'timestamp'
-                       ),
-                       'reason' => array(
-                               'reason' => 'string'
-                       ),
-                       'range' => array(
-                               'rangestart' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'rangeend' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'flags' => array(
-                               'automatic' => 'boolean',
-                               'anononly' => 'boolean',
-                               'nocreate' => 'boolean',
-                               'autoblock' => 'boolean',
-                               'noemail' => 'boolean',
-                               'hidden' => 'boolean',
-                               'allowusertalk' => 'boolean'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'List all blocked users and IP addresses.';
        }
 
-       public function getPossibleErrors() {
-               $blockCIDRLimit = $this->getConfig()->get( 'BlockCIDRLimit' );
-
-               return array_merge( parent::getPossibleErrors(),
-                       $this->getRequireMaxOneParameterErrorMessages( array( 'users', 'ip' ) ),
-                       array(
-                               array(
-                                       'code' => 'cidrtoobroad',
-                                       'info' => "IPv4 CIDR ranges broader than /{$blockCIDRLimit['IPv4']} are not accepted"
-                               ),
-                               array(
-                                       'code' => 'cidrtoobroad',
-                                       'info' => "IPv6 CIDR ranges broader than /{$blockCIDRLimit['IPv6']} are not accepted"
-                               ),
-                               array( 'code' => 'param_ip', 'info' => 'IP parameter is not valid' ),
-                               array( 'code' => 'param_user', 'info' => 'User parameter may not be empty' ),
-                               array( 'code' => 'param_user', 'info' => 'User name user is not valid' ),
-                               array( 'show' ),
-                       )
-               );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=blocks',
index cfc76e6..1926dd0 100644 (file)
@@ -234,35 +234,10 @@ class ApiQueryCategories extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       ),
-                       'sortkey' => array(
-                               'sortkey' => 'string',
-                               'sortkeyprefix' => 'string'
-                       ),
-                       'timestamp' => array(
-                               'timestamp' => 'timestamp'
-                       ),
-                       'hidden' => array(
-                               'hidden' => 'boolean'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'List all categories the page(s) belong to.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'show' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&prop=categories&titles=Albert%20Einstein'
index 8097b7b..6e9f33c 100644 (file)
@@ -114,34 +114,6 @@ class ApiQueryCategoryInfo extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       ApiBase::PROP_LIST => false,
-                       '' => array(
-                               'size' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => false
-                               ),
-                               'pages' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => false
-                               ),
-                               'files' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => false
-                               ),
-                               'subcats' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => false
-                               ),
-                               'hidden' => array(
-                                       ApiBase::PROP_TYPE => 'boolean',
-                                       ApiBase::PROP_NULLABLE => false
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Returns information about the given categories.';
        }
index dc11071..a88a9cb 100644 (file)
@@ -140,12 +140,22 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
                                $this->addWhereRange( 'cl_sortkey', $dir, null, null );
                                $this->addWhereRange( 'cl_from', $dir, null, null );
                        } else {
-                               $startsortkey = $params['startsortkeyprefix'] !== null ?
-                                       Collation::singleton()->getSortkey( $params['startsortkeyprefix'] ) :
-                                       $params['startsortkey'];
-                               $endsortkey = $params['endsortkeyprefix'] !== null ?
-                                       Collation::singleton()->getSortkey( $params['endsortkeyprefix'] ) :
-                                       $params['endsortkey'];
+                               if ( $params['startsortkeyprefix'] !== null ) {
+                                       $startsortkey = Collation::singleton()->getSortkey( $params['startsortkeyprefix'] );
+                               } elseif ( $params['starthexsortkey'] !== null ) {
+                                       $startsortkey = pack( 'H*', $params['starthexsortkey'] );
+                               } else {
+                                       $this->logFeatureUsage( 'list=categorymembers&cmstartsortkey' );
+                                       $startsortkey = $params['startsortkey'];
+                               }
+                               if ( $params['endsortkeyprefix'] !== null ) {
+                                       $endsortkey = Collation::singleton()->getSortkey( $params['endsortkeyprefix'] );
+                               } elseif ( $params['endhexsortkey'] !== null ) {
+                                       $endsortkey = pack( 'H*', $params['endhexsortkey'] );
+                               } else {
+                                       $this->logFeatureUsage( 'list=categorymembers&cmendsortkey' );
+                                       $endsortkey = $params['endsortkey'];
+                               }
 
                                // The below produces ORDER BY cl_sortkey, cl_from, possibly with DESC added to each of them
                                $this->addWhereRange( 'cl_sortkey',
@@ -330,10 +340,16 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
                        'end' => array(
                                ApiBase::PARAM_TYPE => 'timestamp'
                        ),
-                       'startsortkey' => null,
-                       'endsortkey' => null,
+                       'starthexsortkey' => null,
+                       'endhexsortkey' => null,
                        'startsortkeyprefix' => null,
                        'endsortkeyprefix' => null,
+                       'startsortkey' => array(
+                               ApiBase::PARAM_DEPRECATED => true,
+                       ),
+                       'endsortkey' => array(
+                               ApiBase::PARAM_DEPRECATED => true,
+                       ),
                );
        }
 
@@ -359,15 +375,17 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
                        'dir' => 'In which direction to sort',
                        'start' => "Timestamp to start listing from. Can only be used with {$p}sort=timestamp",
                        'end' => "Timestamp to end listing at. Can only be used with {$p}sort=timestamp",
-                       'startsortkey' => "Sortkey to start listing from. Must be given in " .
-                               "binary format. Can only be used with {$p}sort=sortkey",
-                       'endsortkey' => "Sortkey to end listing at. Must be given in binary " .
-                               "format. Can only be used with {$p}sort=sortkey",
+                       'starthexsortkey' => "Sortkey to start listing from, as returned by prop=sortkey. " .
+                               "Can only be used with {$p}sort=sortkey",
+                       'endhexsortkey' => "Sortkey to end listing from, as returned by prop=sortkey. " .
+                               "Can only be used with {$p}sort=sortkey",
                        'startsortkeyprefix' => "Sortkey prefix to start listing from. Can " .
-                               "only be used with {$p}sort=sortkey. Overrides {$p}startsortkey",
+                               "only be used with {$p}sort=sortkey. Overrides {$p}starthexsortkey",
                        'endsortkeyprefix' => "Sortkey prefix to end listing BEFORE (not at, " .
                                "if this value occurs it will not be included!). Can only be used with " .
-                               "{$p}sort=sortkey. Overrides {$p}endsortkey",
+                               "{$p}sort=sortkey. Overrides {$p}endhexsortkey",
+                       'startsortkey' => "Use starthexsortkey instead",
+                       'endsortkey' => "Use endhexsortkey instead",
                        'continue' => 'For large categories, give the value returned from previous query',
                        'limit' => 'The maximum number of pages to return.',
                );
@@ -384,49 +402,10 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
                return $desc;
        }
 
-       public function getResultProperties() {
-               return array(
-                       'ids' => array(
-                               'pageid' => 'integer'
-                       ),
-                       'title' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       ),
-                       'sortkey' => array(
-                               'sortkey' => 'string'
-                       ),
-                       'sortkeyprefix' => array(
-                               'sortkeyprefix' => 'string'
-                       ),
-                       'type' => array(
-                               'type' => array(
-                                       ApiBase::PROP_TYPE => array(
-                                               'page',
-                                               'subcat',
-                                               'file'
-                                       )
-                               )
-                       ),
-                       'timestamp' => array(
-                               'timestamp' => 'timestamp'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'List all pages in a given category.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(),
-                       $this->getTitleOrPageIdErrorMessage(),
-                       array(
-                               array( 'code' => 'invalidcategory', 'info' => 'The category name you entered is not valid' ),
-                       )
-               );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=categorymembers&cmtitle=Category:Physics'
index b90283f..55ea470 100644 (file)
@@ -265,14 +265,6 @@ class ApiQueryContributors extends ApiQueryBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(),
-                       $this->getRequireMaxOneParameterErrorMessages(
-                               array( 'group', 'excludegroup', 'rights', 'excluderights' )
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Get the list of logged-in contributors and ' .
                        'the count of anonymous contributors to a page.';
index af0d938..9042696 100644 (file)
@@ -61,6 +61,13 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                $fld_token = isset( $prop['token'] );
                $fld_tags = isset( $prop['tags'] );
 
+               if ( isset( $prop['token'] ) ) {
+                       $p = $this->getModulePrefix();
+                       $this->setWarning(
+                               "{$p}prop=token has been deprecated. Please use action=query&meta=tokens instead."
+                       );
+               }
+
                // If we're in JSON callback mode, no tokens can be obtained
                if ( !is_null( $this->getMain()->getRequest()->getVal( 'callback' ) ) ) {
                        $fld_token = false;
@@ -134,11 +141,17 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                }
 
                if ( $fld_content ) {
+                       // Modern MediaWiki has the content for deleted revs in the 'text'
+                       // table using fields old_text and old_flags. But revisions deleted
+                       // pre-1.5 store the content in the 'archive' table directly using
+                       // fields ar_text and ar_flags, and no corresponding 'text' row. So
+                       // we have to LEFT JOIN and fetch all four fields, plus ar_text_id
+                       // to be able to tell the difference.
                        $this->addTables( 'text' );
                        $this->addJoinConds(
-                               array( 'text' => array( 'INNER JOIN', array( 'ar_text_id=old_id' ) ) )
+                               array( 'text' => array( 'LEFT JOIN', array( 'ar_text_id=old_id' ) ) )
                        );
-                       $this->addFields( array( 'ar_text', 'ar_text_id', 'old_text', 'old_flags' ) );
+                       $this->addFields( array( 'ar_text', 'ar_flags', 'ar_text_id', 'old_text', 'old_flags' ) );
 
                        // This also means stricter restrictions
                        if ( !$user->isAllowedAny( 'undelete', 'deletedtext' ) ) {
@@ -204,7 +217,7 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                        // check it again just in case)
                        if ( !$user->isAllowed( 'deletedhistory' ) ) {
                                $bitmask = Revision::DELETED_USER;
-                       } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+                       } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                                $bitmask = Revision::DELETED_USER | Revision::DELETED_RESTRICTED;
                        } else {
                                $bitmask = 0;
@@ -353,7 +366,12 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                                        $anyHidden = true;
                                }
                                if ( Revision::userCanBitfield( $row->ar_deleted, Revision::DELETED_TEXT, $user ) ) {
-                                       ApiResult::setContent( $rev, Revision::getRevisionText( $row ) );
+                                       if ( isset( $row->ar_text ) && !$row->ar_text_id ) {
+                                               // Pre-1.5 ar_text row (if condition from Revision::newFromArchiveRow)
+                                               ApiResult::setContent( $rev, Revision::getRevisionText( $row, 'ar_' ) );
+                                       } else {
+                                               ApiResult::setContent( $rev, Revision::getRevisionText( $row ) );
+                                       }
                                }
                        }
 
@@ -482,7 +500,7 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                                ' len            - Adds the length (bytes) of the revision',
                                ' sha1           - Adds the SHA-1 (base 16) of the revision',
                                ' content        - Adds the content of the revision',
-                               ' token          - Gives the edit token',
+                               ' token          - DEPRECATED! Gives the edit token',
                                ' tags           - Tags for the revision',
                        ),
                        'namespace' => 'Only list pages in this namespace (3)',
@@ -494,18 +512,6 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       ),
-                       'token' => array(
-                               'token' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                $p = $this->getModulePrefix();
 
@@ -521,29 +527,6 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array(
-                               'code' => 'permissiondenied',
-                               'info' => 'You don\'t have permission to view deleted revision information'
-                       ),
-                       array( 'code' => 'badparams', 'info' => 'user and excludeuser cannot be used together'
-                       ),
-                       array(
-                               'code' => 'permissiondenied',
-                               'info' => 'You don\'t have permission to view deleted revision content'
-                       ),
-                       array( 'code' => 'badparams', 'info' => "The 'from' parameter cannot be used in modes 1 or 2" ),
-                       array( 'code' => 'badparams', 'info' => "The 'to' parameter cannot be used in modes 1 or 2" ),
-                       array(
-                               'code' => 'badparams',
-                               'info' => "The 'prefix' parameter cannot be used in modes 1 or 2"
-                       ),
-                       array( 'code' => 'badparams', 'info' => "The 'start' parameter cannot be used in mode 3" ),
-                       array( 'code' => 'badparams', 'info' => "The 'end' parameter cannot be used in mode 3" ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=deletedrevs&titles=Main%20Page|Talk:Main%20Page&' .
index 4645402..6d836cd 100644 (file)
@@ -188,17 +188,6 @@ class ApiQueryDuplicateFiles extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'name' => 'string',
-                               'user' => 'string',
-                               'timestamp' => 'timestamp',
-                               'shared' => 'boolean',
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'List all files that are duplicates of the given file(s) based on hash values.';
        }
index 33e8739..faabb92 100644 (file)
@@ -239,31 +239,10 @@ class ApiQueryExtLinksUsage extends ApiQueryGeneratorBase {
                return $desc;
        }
 
-       public function getResultProperties() {
-               return array(
-                       'ids' => array(
-                               'pageid' => 'integer'
-                       ),
-                       'title' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       ),
-                       'url' => array(
-                               'url' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Enumerate pages that contain a given URL.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'bad_query', 'info' => 'Invalid query' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=exturlusage&euquery=www.mediawiki.org'
index e3a7be3..9566635 100644 (file)
@@ -141,24 +141,10 @@ class ApiQueryExternalLinks extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               '*' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Returns all external URLs (not interwikis) from the given page(s).';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'bad_query', 'info' => 'Invalid query' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&prop=extlinks&titles=Main%20Page'
index 97918e3..f047d8d 100644 (file)
@@ -67,9 +67,8 @@ class ApiQueryFilearchive extends ApiQueryBase {
                $this->addTables( 'filearchive' );
 
                $this->addFields( ArchivedFile::selectFields() );
-               $this->addFields( array( 'fa_name', 'fa_deleted' ) );
+               $this->addFields( array( 'fa_id', 'fa_name', 'fa_timestamp', 'fa_deleted' ) );
                $this->addFieldsIf( 'fa_sha1', $fld_sha1 );
-               $this->addFieldsIf( 'fa_timestamp', $fld_timestamp );
                $this->addFieldsIf( array( 'fa_user', 'fa_user_text' ), $fld_user );
                $this->addFieldsIf( array( 'fa_height', 'fa_width', 'fa_size' ), $fld_dimensions || $fld_size );
                $this->addFieldsIf( 'fa_description', $fld_description );
@@ -81,18 +80,23 @@ class ApiQueryFilearchive extends ApiQueryBase {
 
                if ( !is_null( $params['continue'] ) ) {
                        $cont = explode( '|', $params['continue'] );
-                       $this->dieContinueUsageIf( count( $cont ) != 1 );
+                       $this->dieContinueUsageIf( count( $cont ) != 3 );
                        $op = $params['dir'] == 'descending' ? '<' : '>';
                        $cont_from = $db->addQuotes( $cont[0] );
-                       $this->addWhere( "fa_name $op= $cont_from" );
+                       $cont_timestamp = $db->addQuotes( $db->timestamp( $cont[1] ) );
+                       $cont_id = (int)$cont[2];
+                       $this->dieContinueUsageIf( $cont[2] !== (string)$cont_id );
+                       $this->addWhere( "fa_name $op $cont_from OR " .
+                               "(fa_name = $cont_from AND " .
+                               "(fa_timestamp $op $cont_timestamp OR " .
+                               "(fa_timestamp = $cont_timestamp AND " .
+                               "fa_id $op= $cont_id )))"
+                       );
                }
 
                // Image filters
                $dir = ( $params['dir'] == 'descending' ? 'older' : 'newer' );
                $from = ( $params['from'] === null ? null : $this->titlePartToKey( $params['from'], NS_FILE ) );
-               if ( !is_null( $params['continue'] ) ) {
-                       $from = $params['continue'];
-               }
                $to = ( $params['to'] === null ? null : $this->titlePartToKey( $params['to'], NS_FILE ) );
                $this->addWhereRange( 'fa_name', $dir, $from, $to );
                if ( isset( $params['prefix'] ) ) {
@@ -125,7 +129,7 @@ class ApiQueryFilearchive extends ApiQueryBase {
                // Exclude files this user can't view.
                if ( !$user->isAllowed( 'deletedtext' ) ) {
                        $bitmask = File::DELETED_FILE;
-               } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                        $bitmask = File::DELETED_FILE | File::DELETED_RESTRICTED;
                } else {
                        $bitmask = 0;
@@ -137,7 +141,11 @@ class ApiQueryFilearchive extends ApiQueryBase {
                $limit = $params['limit'];
                $this->addOption( 'LIMIT', $limit + 1 );
                $sort = ( $params['dir'] == 'descending' ? ' DESC' : '' );
-               $this->addOption( 'ORDER BY', 'fa_name' . $sort );
+               $this->addOption( 'ORDER BY', array(
+                       'fa_name' . $sort,
+                       'fa_timestamp' . $sort,
+                       'fa_id' . $sort,
+               ) );
 
                $res = $this->select( __METHOD__ );
 
@@ -147,11 +155,14 @@ class ApiQueryFilearchive extends ApiQueryBase {
                        if ( ++$count > $limit ) {
                                // We've reached the one extra which shows that there are
                                // additional pages to be had. Stop here...
-                               $this->setContinueEnumParameter( 'continue', $row->fa_name );
+                               $this->setContinueEnumParameter(
+                                       'continue', "$row->fa_name|$row->fa_timestamp|$row->fa_id"
+                               );
                                break;
                        }
 
                        $file = array();
+                       $file['id'] = $row->fa_id;
                        $file['name'] = $row->fa_name;
                        $title = Title::makeTitle( NS_FILE, $row->fa_name );
                        self::addTitleInfo( $file, $title );
@@ -222,7 +233,9 @@ class ApiQueryFilearchive extends ApiQueryBase {
 
                        $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $file );
                        if ( !$fit ) {
-                               $this->setContinueEnumParameter( 'continue', $row->fa_name );
+                               $this->setContinueEnumParameter(
+                                       'continue', "$row->fa_name|$row->fa_timestamp|$row->fa_id"
+                               );
                                break;
                        }
                }
@@ -302,89 +315,10 @@ class ApiQueryFilearchive extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'name' => 'string',
-                               'ns' => 'namespace',
-                               'title' => 'string',
-                               'filehidden' => 'boolean',
-                               'commenthidden' => 'boolean',
-                               'userhidden' => 'boolean',
-                               'suppressed' => 'boolean'
-                       ),
-                       'sha1' => array(
-                               'sha1' => 'string'
-                       ),
-                       'timestamp' => array(
-                               'timestamp' => 'timestamp'
-                       ),
-                       'user' => array(
-                               'userid' => 'integer',
-                               'user' => 'string'
-                       ),
-                       'size' => array(
-                               'size' => 'integer',
-                               'pagecount' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'height' => 'integer',
-                               'width' => 'integer'
-                       ),
-                       'dimensions' => array(
-                               'size' => 'integer',
-                               'pagecount' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'height' => 'integer',
-                               'width' => 'integer'
-                       ),
-                       'description' => array(
-                               'description' => 'string'
-                       ),
-                       'parseddescription' => array(
-                               'description' => 'string',
-                               'parseddescription' => 'string'
-                       ),
-                       'metadata' => array(
-                               'metadata' => 'string'
-                       ),
-                       'bitdepth' => array(
-                               'bitdepth' => 'integer'
-                       ),
-                       'mime' => array(
-                               'mime' => 'string'
-                       ),
-                       'mediatype' => array(
-                               'mediatype' => 'string'
-                       ),
-                       'archivename' => array(
-                               'archivename' => 'string'
-                       ),
-               );
-       }
-
        public function getDescription() {
                return 'Enumerate all deleted files sequentially.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array(
-                               'code' => 'permissiondenied',
-                               'info' => 'You don\'t have permission to view deleted file information'
-                       ),
-                       array( 'code' => 'hashsearchdisabled', 'info' => 'Search by hash disabled in Miser Mode' ),
-                       array( 'code' => 'invalidsha1hash', 'info' => 'The SHA-1 hash provided is not valid' ),
-                       array(
-                               'code' => 'invalidsha1base36hash',
-                               'info' => 'The SHA1Base36 hash provided is not valid'
-                       ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=filearchive' => array(
index 35b2b40..b5aa45b 100644 (file)
@@ -210,23 +210,6 @@ class ApiQueryIWBacklinks extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'pageid' => 'integer',
-                               'ns' => 'namespace',
-                               'title' => 'string',
-                               'redirect' => 'boolean'
-                       ),
-                       'iwprefix' => array(
-                               'iwprefix' => 'string'
-                       ),
-                       'iwtitle' => array(
-                               'iwtitle' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return array( 'Find all pages that link to the given interwiki link.',
                        'Can be used to find all links with a prefix, or',
@@ -235,12 +218,6 @@ class ApiQueryIWBacklinks extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'missingparam', 'prefix' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=iwbacklinks&iwbltitle=Test&iwblprefix=wikibooks',
index f38a7b1..a185ee2 100644 (file)
@@ -42,11 +42,19 @@ class ApiQueryIWLinks extends ApiQueryBase {
                }
 
                $params = $this->extractRequestParams();
+               $prop = array_flip( (array)$params['prop'] );
 
                if ( isset( $params['title'] ) && !isset( $params['prefix'] ) ) {
                        $this->dieUsageMsg( array( 'missingparam', 'prefix' ) );
                }
 
+               // Handle deprecated param
+               $this->requireMaxOneParameter( $params, 'url', 'prop' );
+               if ( $params['url'] ) {
+                       $this->logFeatureUsage( 'prop=iwlinks&iwurl' );
+                       $prop = array( 'url' => 1 );
+               }
+
                $this->addFields( array(
                        'iwl_from',
                        'iwl_prefix',
@@ -114,7 +122,7 @@ class ApiQueryIWLinks extends ApiQueryBase {
                        }
                        $entry = array( 'prefix' => $row->iwl_prefix );
 
-                       if ( $params['url'] ) {
+                       if ( isset( $prop['url'] ) ) {
                                $title = Title::newFromText( "{$row->iwl_prefix}:{$row->iwl_title}" );
                                if ( $title ) {
                                        $entry['url'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
@@ -139,7 +147,16 @@ class ApiQueryIWLinks extends ApiQueryBase {
 
        public function getAllowedParams() {
                return array(
-                       'url' => false,
+                       'url' => array(
+                               ApiBase::PARAM_DFLT => false,
+                               ApiBase::PARAM_DEPRECATED => true,
+                       ),
+                       'prop' => array(
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TYPE => array(
+                                       'url',
+                               )
+                       ),
                        'limit' => array(
                                ApiBase::PARAM_DFLT => 10,
                                ApiBase::PARAM_TYPE => 'limit',
@@ -162,7 +179,11 @@ class ApiQueryIWLinks extends ApiQueryBase {
 
        public function getParamDescription() {
                return array(
-                       'url' => 'Whether to get the full URL',
+                       'prop' => array(
+                               'Which additional properties to get for each interlanguage link',
+                               ' url      - Adds the full URL',
+                       ),
+                       'url' => "Whether to get the full URL (Cannot be used with {$this->getModulePrefix()}prop)",
                        'limit' => 'How many interwiki links to return',
                        'continue' => 'When more results are available, use this to continue',
                        'prefix' => 'Prefix for the interwiki',
@@ -171,29 +192,10 @@ class ApiQueryIWLinks extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'prefix' => 'string',
-                               'url' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               '*' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Returns all interwiki links from the given page(s).';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'missingparam', 'prefix' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&prop=iwlinks&titles=Main%20Page'
index 4b49a80..5cc1454 100644 (file)
@@ -534,7 +534,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
         *
         * If this is >= TRANSFORM_LIMIT, you should probably stop processing images.
         *
-        * @return int count
+        * @return int Count
         */
        static function getTransformCount() {
                return self::$transformCount;
@@ -739,151 +739,10 @@ class ApiQueryImageInfo extends ApiQueryBase {
                );
        }
 
-       public static function getResultPropertiesFiltered( $filter = array() ) {
-               $props = array(
-                       'timestamp' => array(
-                               'timestamp' => 'timestamp'
-                       ),
-                       'user' => array(
-                               'userhidden' => 'boolean',
-                               'user' => 'string',
-                               'anon' => 'boolean'
-                       ),
-                       'userid' => array(
-                               'userhidden' => 'boolean',
-                               'userid' => 'integer',
-                               'anon' => 'boolean'
-                       ),
-                       'size' => array(
-                               'size' => 'integer',
-                               'width' => 'integer',
-                               'height' => 'integer',
-                               'pagecount' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'dimensions' => array(
-                               'size' => 'integer',
-                               'width' => 'integer',
-                               'height' => 'integer',
-                               'pagecount' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'comment' => array(
-                               'commenthidden' => 'boolean',
-                               'comment' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'parsedcomment' => array(
-                               'commenthidden' => 'boolean',
-                               'parsedcomment' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'canonicaltitle' => array(
-                               'canonicaltitle' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'url' => array(
-                               'filehidden' => 'boolean',
-                               'thumburl' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'thumbwidth' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'thumbheight' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'thumberror' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'url' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'descriptionurl' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'sha1' => array(
-                               'filehidden' => 'boolean',
-                               'sha1' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'mime' => array(
-                               'filehidden' => 'boolean',
-                               'mime' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'thumbmime' => array(
-                               'filehidden' => 'boolean',
-                               'thumbmime' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'mediatype' => array(
-                               'filehidden' => 'boolean',
-                               'mediatype' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'archivename' => array(
-                               'filehidden' => 'boolean',
-                               'archivename' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'bitdepth' => array(
-                               'filehidden' => 'boolean',
-                               'bitdepth' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-               );
-
-               return array_diff_key( $props, array_flip( $filter ) );
-       }
-
-       public function getResultProperties() {
-               return self::getResultPropertiesFiltered();
-       }
-
        public function getDescription() {
                return 'Returns image information and upload history.';
        }
 
-       public function getPossibleErrors() {
-               $p = $this->getModulePrefix();
-
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => "{$p}urlwidth", 'info' => "{$p}urlheight cannot be used without {$p}urlwidth" ),
-                       array( 'code' => 'urlparam', 'info' => "Invalid value for {$p}urlparam" ),
-                       array( 'code' => 'urlparam_no_width', 'info' => "{$p}urlparam requires {$p}urlwidth" ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&titles=File:Albert%20Einstein%20Head.jpg&prop=imageinfo',
index 87b0778..9bc3abe 100644 (file)
@@ -170,15 +170,6 @@ class ApiQueryImages extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Returns all images contained on the given page(s).';
        }
index 8b6886d..d7037e3 100644 (file)
@@ -79,6 +79,7 @@ class ApiQueryInfo extends ApiQueryBase {
         * Get an array mapping token names to their handler functions.
         * The prototype for a token function is func($pageid, $title)
         * it should return a token or false (permission denied)
+        * @deprecated since 1.24
         * @return array Array(tokenname => function)
         */
        protected function getTokenFunctions() {
@@ -110,10 +111,16 @@ class ApiQueryInfo extends ApiQueryBase {
 
        static protected $cachedTokens = array();
 
+       /**
+        * @deprecated since 1.24
+        */
        public static function resetTokenCache() {
                ApiQueryInfo::$cachedTokens = array();
        }
 
+       /**
+        * @deprecated since 1.24
+        */
        public static function getEditToken( $pageid, $title ) {
                // We could check for $title->userCan('edit') here,
                // but that's too expensive for this purpose
@@ -131,6 +138,9 @@ class ApiQueryInfo extends ApiQueryBase {
                return ApiQueryInfo::$cachedTokens['edit'];
        }
 
+       /**
+        * @deprecated since 1.24
+        */
        public static function getDeleteToken( $pageid, $title ) {
                global $wgUser;
                if ( !$wgUser->isAllowed( 'delete' ) ) {
@@ -145,6 +155,9 @@ class ApiQueryInfo extends ApiQueryBase {
                return ApiQueryInfo::$cachedTokens['delete'];
        }
 
+       /**
+        * @deprecated since 1.24
+        */
        public static function getProtectToken( $pageid, $title ) {
                global $wgUser;
                if ( !$wgUser->isAllowed( 'protect' ) ) {
@@ -159,6 +172,9 @@ class ApiQueryInfo extends ApiQueryBase {
                return ApiQueryInfo::$cachedTokens['protect'];
        }
 
+       /**
+        * @deprecated since 1.24
+        */
        public static function getMoveToken( $pageid, $title ) {
                global $wgUser;
                if ( !$wgUser->isAllowed( 'move' ) ) {
@@ -173,6 +189,9 @@ class ApiQueryInfo extends ApiQueryBase {
                return ApiQueryInfo::$cachedTokens['move'];
        }
 
+       /**
+        * @deprecated since 1.24
+        */
        public static function getBlockToken( $pageid, $title ) {
                global $wgUser;
                if ( !$wgUser->isAllowed( 'block' ) ) {
@@ -187,11 +206,17 @@ class ApiQueryInfo extends ApiQueryBase {
                return ApiQueryInfo::$cachedTokens['block'];
        }
 
+       /**
+        * @deprecated since 1.24
+        */
        public static function getUnblockToken( $pageid, $title ) {
                // Currently, this is exactly the same as the block token
                return self::getBlockToken( $pageid, $title );
        }
 
+       /**
+        * @deprecated since 1.24
+        */
        public static function getEmailToken( $pageid, $title ) {
                global $wgUser;
                if ( !$wgUser->canSendEmail() || $wgUser->isBlockedFromEmailUser() ) {
@@ -206,6 +231,9 @@ class ApiQueryInfo extends ApiQueryBase {
                return ApiQueryInfo::$cachedTokens['email'];
        }
 
+       /**
+        * @deprecated since 1.24
+        */
        public static function getImportToken( $pageid, $title ) {
                global $wgUser;
                if ( !$wgUser->isAllowedAny( 'import', 'importupload' ) ) {
@@ -220,6 +248,9 @@ class ApiQueryInfo extends ApiQueryBase {
                return ApiQueryInfo::$cachedTokens['import'];
        }
 
+       /**
+        * @deprecated since 1.24
+        */
        public static function getWatchToken( $pageid, $title ) {
                global $wgUser;
                if ( !$wgUser->isLoggedIn() ) {
@@ -234,6 +265,9 @@ class ApiQueryInfo extends ApiQueryBase {
                return ApiQueryInfo::$cachedTokens['watch'];
        }
 
+       /**
+        * @deprecated since 1.24
+        */
        public static function getOptionsToken( $pageid, $title ) {
                global $wgUser;
                if ( !$wgUser->isLoggedIn() ) {
@@ -424,6 +458,7 @@ class ApiQueryInfo extends ApiQueryBase {
                if ( $this->fld_url ) {
                        $pageInfo['fullurl'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
                        $pageInfo['editurl'] = wfExpandUrl( $title->getFullURL( 'action=edit' ), PROTO_CURRENT );
+                       $pageInfo['canonicalurl'] = wfExpandUrl( $title->getFullURL(), PROTO_CANONICAL );
                }
                if ( $this->fld_readable && $title->userCan( 'read', $this->getUser() ) ) {
                        $pageInfo['readable'] = '';
@@ -784,6 +819,7 @@ class ApiQueryInfo extends ApiQueryBase {
                                        // need to be added to getCacheMode()
                                ) ),
                        'token' => array(
+                               ApiBase::PARAM_DEPRECATED => true,
                                ApiBase::PARAM_DFLT => null,
                                ApiBase::PARAM_ISMULTI => true,
                                ApiBase::PARAM_TYPE => array_keys( $this->getTokenFunctions() )
@@ -802,7 +838,7 @@ class ApiQueryInfo extends ApiQueryBase {
                                ' watchers              - The number of watchers, if allowed',
                                ' notificationtimestamp - The watchlist notification timestamp of each page',
                                ' subjectid             - The page ID of the parent page for each talk page',
-                               ' url                   - Gives a full URL to the page, and also an edit URL',
+                               ' url                   - Gives a full URL, an edit URL, and the canonical URL for each page',
                                ' readable              - Whether the user can read this page',
                                ' preload               - Gives the text returned by EditFormPreloadText',
                                ' displaytitle          - Gives the way the page title is actually displayed',
@@ -812,72 +848,6 @@ class ApiQueryInfo extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               $props = array(
-                       ApiBase::PROP_LIST => false,
-                       '' => array(
-                               'touched' => 'timestamp',
-                               'lastrevid' => 'integer',
-                               'counter' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'length' => 'integer',
-                               'redirect' => 'boolean',
-                               'new' => 'boolean',
-                               'starttimestamp' => array(
-                                       ApiBase::PROP_TYPE => 'timestamp',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'contentmodel' => 'string',
-                       ),
-                       'watched' => array(
-                               'watched' => 'boolean'
-                       ),
-                       'watchers' => array(
-                               'watchers' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'notificationtimestamp' => array(
-                               'notificationtimestamp' => array(
-                                       ApiBase::PROP_TYPE => 'timestamp',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'talkid' => array(
-                               'talkid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'subjectid' => array(
-                               'subjectid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'url' => array(
-                               'fullurl' => 'string',
-                               'editurl' => 'string'
-                       ),
-                       'readable' => array(
-                               'readable' => 'boolean'
-                       ),
-                       'preload' => array(
-                               'preload' => 'string'
-                       ),
-                       'displaytitle' => array(
-                               'displaytitle' => 'string'
-                       )
-               );
-
-               self::addTokenProperties( $props, $this->getTokenFunctions() );
-
-               return $props;
-       }
-
        public function getDescription() {
                return 'Get basic page information such as namespace, title, last touched date, ...';
        }
index 13711e6..34842c6 100644 (file)
@@ -209,23 +209,6 @@ class ApiQueryLangBacklinks extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'pageid' => 'integer',
-                               'ns' => 'namespace',
-                               'title' => 'string',
-                               'redirect' => 'boolean'
-                       ),
-                       'lllang' => array(
-                               'lllang' => 'string'
-                       ),
-                       'lltitle' => array(
-                               'lltitle' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return array( 'Find all pages that link to the given language link.',
                        'Can be used to find all links with a language code, or',
@@ -235,12 +218,6 @@ class ApiQueryLangBacklinks extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'missingparam', 'lang' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=langbacklinks&lbltitle=Test&lbllang=fr',
index 53cfba1..da05f27 100644 (file)
@@ -50,6 +50,7 @@ class ApiQueryLangLinks extends ApiQueryBase {
                // Handle deprecated param
                $this->requireMaxOneParameter( $params, 'url', 'prop' );
                if ( $params['url'] ) {
+                       $this->logFeatureUsage( 'prop=langlinks&llurl' );
                        $prop = array( 'url' => 1 );
                }
 
@@ -191,42 +192,10 @@ class ApiQueryLangLinks extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'lang' => 'string',
-                               'url' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'langname' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'autonym' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               '*' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Returns all interlanguage links from the given page(s).';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(),
-                       $this->getRequireMaxOneParameterErrorMessages(
-                               array( 'url', 'prop' )
-                       ),
-                       array(
-                               array( 'missingparam', 'lang' ),
-                       )
-               );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&prop=langlinks&titles=Main%20Page&redirects='
index 7c17938..71329c4 100644 (file)
@@ -223,15 +223,6 @@ class ApiQueryLinks extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return "Returns all {$this->description}s from the given page(s).";
        }
index 3aad785..d3607e1 100644 (file)
@@ -204,7 +204,7 @@ class ApiQueryLogEvents extends ApiQueryBase {
                        if ( !$this->getUser()->isAllowed( 'deletedhistory' ) ) {
                                $titleBits = LogPage::DELETED_ACTION;
                                $userBits = LogPage::DELETED_USER;
-                       } elseif ( !$this->getUser()->isAllowed( 'suppressrevision' ) ) {
+                       } elseif ( !$this->getUser()->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                                $titleBits = LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED;
                                $userBits = LogPage::DELETED_USER | LogPage::DELETED_RESTRICTED;
                        } else {
@@ -403,7 +403,7 @@ class ApiQueryLogEvents extends ApiQueryBase {
                                        $vals['user'] = $row->user_name === null ? $row->log_user_text : $row->user_name;
                                }
                                if ( $this->fld_userid ) {
-                                       $vals['userid'] = $row->log_user;
+                                       $vals['userid'] = intval( $row->log_user );
                                }
 
                                if ( !$row->log_user ) {
@@ -566,80 +566,10 @@ class ApiQueryLogEvents extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       'ids' => array(
-                               'logid' => 'integer',
-                               'pageid' => 'integer'
-                       ),
-                       'title' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       ),
-                       'type' => array(
-                               'type' => array(
-                                       ApiBase::PROP_TYPE => $this->getConfig()->get( 'LogTypes' )
-                               ),
-                               'action' => 'string'
-                       ),
-                       'details' => array(
-                               'actionhidden' => 'boolean'
-                       ),
-                       'user' => array(
-                               'userhidden' => 'boolean',
-                               'user' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'anon' => 'boolean'
-                       ),
-                       'userid' => array(
-                               'userhidden' => 'boolean',
-                               'userid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'anon' => 'boolean'
-                       ),
-                       'timestamp' => array(
-                               'timestamp' => 'timestamp'
-                       ),
-                       'comment' => array(
-                               'commenthidden' => 'boolean',
-                               'comment' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'parsedcomment' => array(
-                               'commenthidden' => 'boolean',
-                               'parsedcomment' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Get events from logs.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge(
-                       parent::getPossibleErrors(),
-                       $this->getRequireMaxOneParameterErrorMessages(
-                               array( 'title', 'prefix', 'namespace' ) ),
-                       array(
-                               array( 'code' => 'param_user', 'info' => 'User name $user not found' ),
-                               array( 'code' => 'param_title', 'info' => 'Bad title value \'title\'' ),
-                               array( 'code' => 'param_prefix', 'info' => 'Bad title value \'prefix\'' ),
-                               array( 'code' => 'prefixsearchdisabled',
-                                       'info' => 'Prefix search disabled in Miser Mode' ),
-                       )
-               );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=logevents'
index 2cc18c5..4c88be7 100644 (file)
@@ -243,42 +243,6 @@ class ApiQueryProtectedTitles extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       ),
-                       'timestamp' => array(
-                               'timestamp' => 'timestamp'
-                       ),
-                       'user' => array(
-                               'user' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'userid' => 'integer'
-                       ),
-                       'userid' => array(
-                               'userid' => 'integer'
-                       ),
-                       'comment' => array(
-                               'comment' => 'string'
-                       ),
-                       'parsedcomment' => array(
-                               'parsedcomment' => 'string'
-                       ),
-                       'expiry' => array(
-                               'expiry' => 'timestamp'
-                       ),
-                       'level' => array(
-                               'level' => array(
-                                       ApiBase::PROP_TYPE => array_diff( $this->getConfig()->get( 'RestrictionLevels' ), array( '' ) )
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'List all titles protected from creation.';
        }
index 1a7f826..5ddd945 100644 (file)
@@ -163,48 +163,10 @@ class ApiQueryQueryPage extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       ApiBase::PROP_ROOT => array(
-                               'name' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => false
-                               ),
-                               'disabled' => array(
-                                       ApiBase::PROP_TYPE => 'boolean',
-                                       ApiBase::PROP_NULLABLE => false
-                               ),
-                               'cached' => array(
-                                       ApiBase::PROP_TYPE => 'boolean',
-                                       ApiBase::PROP_NULLABLE => false
-                               ),
-                               'cachedtimestamp' => array(
-                                       ApiBase::PROP_TYPE => 'timestamp',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       '' => array(
-                               'value' => 'string',
-                               'timestamp' => array(
-                                       ApiBase::PROP_TYPE => 'timestamp',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Get a list provided by a QueryPage-based special page.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'specialpage-cantexecute' )
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=querypage&qppage=Ancientpages'
index 07f8a0e..530557e 100644 (file)
@@ -173,16 +173,6 @@ class ApiQueryRandom extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'id' => 'integer',
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return array(
                        'Get a set of random pages.',
index e4078d5..6f0c5d3 100644 (file)
@@ -47,7 +47,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
         * Get an array mapping token names to their handler functions.
         * The prototype for a token function is func($pageid, $title, $rc)
         * it should return a token or false (permission denied)
-        * @return array array(tokenname => function)
+        * @deprecated since 1.24
+        * @return array Array(tokenname => function)
         */
        protected function getTokenFunctions() {
                // Don't call the hooks twice
@@ -69,6 +70,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
        }
 
        /**
+        * @deprecated since 1.24
         * @param int $pageid
         * @param Title $title
         * @param RecentChange|null $rc
@@ -105,7 +107,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
 
        /**
         * Sets internal state to include the desired properties in the output.
-        * @param array $prop associative array of properties, only keys are used here
+        * @param array $prop Associative array of properties, only keys are used here
         */
        public function initProperties( $prop ) {
                $this->fld_comment = isset( $prop['comment'] );
@@ -329,7 +331,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                if ( !is_null( $params['user'] ) || !is_null( $params['excludeuser'] ) ) {
                        if ( !$user->isAllowed( 'deletedhistory' ) ) {
                                $bitmask = Revision::DELETED_USER;
-                       } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+                       } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                                $bitmask = Revision::DELETED_USER | Revision::DELETED_RESTRICTED;
                        } else {
                                $bitmask = 0;
@@ -342,7 +344,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        // LogPage::DELETED_ACTION hides the affected page, too.
                        if ( !$user->isAllowed( 'deletedhistory' ) ) {
                                $bitmask = LogPage::DELETED_ACTION;
-                       } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+                       } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                                $bitmask = LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED;
                        } else {
                                $bitmask = 0;
@@ -405,7 +407,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
        /**
         * Extracts from a single sql row the data needed to describe one recent change.
         *
-        * @param mixed $row The row from which to extract the data.
+        * @param stdClass $row The row from which to extract the data.
         * @return array An array mapping strings (descriptors) to their respective string values.
         * @access public
         */
@@ -657,6 +659,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                )
                        ),
                        'token' => array(
+                               ApiBase::PARAM_DEPRECATED => true,
                                ApiBase::PARAM_TYPE => array_keys( $this->getTokenFunctions() ),
                                ApiBase::PARAM_ISMULTI => true
                        ),
@@ -737,122 +740,10 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               $props = array(
-                       '' => array(
-                               'type' => array(
-                                       ApiBase::PROP_TYPE => array(
-                                               'edit',
-                                               'new',
-                                               'move',
-                                               'log',
-                                               'move over redirect'
-                                       )
-                               )
-                       ),
-                       'title' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string',
-                               'new_ns' => array(
-                                       ApiBase::PROP_TYPE => 'namespace',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'new_title' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'ids' => array(
-                               'rcid' => 'integer',
-                               'pageid' => 'integer',
-                               'revid' => 'integer',
-                               'old_revid' => 'integer'
-                       ),
-                       'user' => array(
-                               'user' => 'string',
-                               'anon' => 'boolean'
-                       ),
-                       'userid' => array(
-                               'userid' => 'integer',
-                               'anon' => 'boolean'
-                       ),
-                       'flags' => array(
-                               'bot' => 'boolean',
-                               'new' => 'boolean',
-                               'minor' => 'boolean'
-                       ),
-                       'sizes' => array(
-                               'oldlen' => 'integer',
-                               'newlen' => 'integer'
-                       ),
-                       'timestamp' => array(
-                               'timestamp' => 'timestamp'
-                       ),
-                       'comment' => array(
-                               'comment' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'parsedcomment' => array(
-                               'parsedcomment' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'redirect' => array(
-                               'redirect' => 'boolean'
-                       ),
-                       'patrolled' => array(
-                               'patrolled' => 'boolean',
-                               'unpatrolled' => 'boolean'
-                       ),
-                       'loginfo' => array(
-                               'logid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'logtype' => array(
-                                       ApiBase::PROP_TYPE => $this->getConfig()->get( 'LogTypes' ),
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'logaction' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'sha1' => array(
-                               'sha1' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'sha1hidden' => array(
-                                       ApiBase::PROP_TYPE => 'boolean',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                       ),
-               );
-
-               self::addTokenProperties( $props, $this->getTokenFunctions() );
-
-               return $props;
-       }
-
        public function getDescription() {
                return 'Enumerate recent changes.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'show' ),
-                       array(
-                               'code' => 'permissiondenied',
-                               'info' => 'You need the patrol right to request the patrolled flag'
-                       ),
-                       array( 'code' => 'user-excludeuser', 'info' => 'user and excludeuser cannot be used together' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=recentchanges'
index 3ff6805..da4ec19 100644 (file)
@@ -48,6 +48,7 @@ class ApiQueryRevisions extends ApiQueryBase {
 
        private $tokenFunctions;
 
+       /** @deprecated since 1.24 */
        protected function getTokenFunctions() {
                // tokenname => function
                // function prototype is func($pageid, $title, $rev)
@@ -72,6 +73,7 @@ class ApiQueryRevisions extends ApiQueryBase {
        }
 
        /**
+        * @deprecated since 1.24
         * @param int $pageid
         * @param Title $title
         * @param Revision $rev
@@ -318,7 +320,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                                // Paranoia: avoid brute force searches (bug 17342)
                                if ( !$this->getUser()->isAllowed( 'deletedhistory' ) ) {
                                        $bitmask = Revision::DELETED_USER;
-                               } elseif ( !$this->getUser()->isAllowed( 'suppressrevision' ) ) {
+                               } elseif ( !$this->getUser()->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                                        $bitmask = Revision::DELETED_USER | Revision::DELETED_RESTRICTED;
                                } else {
                                        $bitmask = 0;
@@ -748,6 +750,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                        'parse' => false,
                        'section' => null,
                        'token' => array(
+                               ApiBase::PARAM_DEPRECATED => true,
                                ApiBase::PARAM_TYPE => array_keys( $this->getTokenFunctions() ),
                                ApiBase::PARAM_ISMULTI => true
                        ),
@@ -807,70 +810,6 @@ class ApiQueryRevisions extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               $props = array(
-                       '' => array(),
-                       'ids' => array(
-                               'revid' => 'integer',
-                               'parentid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'flags' => array(
-                               'minor' => 'boolean'
-                       ),
-                       'user' => array(
-                               'userhidden' => 'boolean',
-                               'user' => 'string',
-                               'anon' => 'boolean'
-                       ),
-                       'userid' => array(
-                               'userhidden' => 'boolean',
-                               'userid' => 'integer',
-                               'anon' => 'boolean'
-                       ),
-                       'timestamp' => array(
-                               'timestamp' => 'timestamp'
-                       ),
-                       'size' => array(
-                               'size' => 'integer'
-                       ),
-                       'sha1' => array(
-                               'sha1' => 'string'
-                       ),
-                       'comment' => array(
-                               'commenthidden' => 'boolean',
-                               'comment' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'parsedcomment' => array(
-                               'commenthidden' => 'boolean',
-                               'parsedcomment' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'content' => array(
-                               '*' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'texthidden' => 'boolean',
-                               'textmissing' => 'boolean',
-                       ),
-                       'contentmodel' => array(
-                               'contentmodel' => 'string'
-                       ),
-               );
-
-               self::addTokenProperties( $props, $this->getTokenFunctions() );
-
-               return $props;
-       }
-
        public function getDescription() {
                return array(
                        'Get revision information.',
@@ -882,33 +821,6 @@ class ApiQueryRevisions extends ApiQueryBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'nosuchrevid', 'diffto' ),
-                       array(
-                               'code' => 'revids',
-                               'info' => 'The revids= parameter may not be used with the list options '
-                                       . '(limit, startid, endid, dirNewer, start, end).'
-                       ),
-                       array(
-                               'code' => 'multpages',
-                               'info' => 'titles, pageids or a generator was used to supply multiple pages, '
-                                       . ' but the limit, startid, endid, dirNewer, user, excludeuser, '
-                                       . 'start and end parameters may only be used on a single page.'
-                       ),
-                       array(
-                               'code' => 'diffto',
-                               'info' => 'rvdiffto must be set to a non-negative number, "prev", "next" or "cur"'
-                       ),
-                       array( 'code' => 'badparams', 'info' => 'start and startid cannot be used together' ),
-                       array( 'code' => 'badparams', 'info' => 'end and endid cannot be used together' ),
-                       array( 'code' => 'badparams', 'info' => 'user and excludeuser cannot be used together' ),
-                       array( 'code' => 'nosuchsection', 'info' => 'There is no section section in rID' ),
-                       array( 'code' => 'badformat', 'info' => 'The requested serialization format can not be applied '
-                               . ' to the page\'s content model' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'Get data with content for the last revision of titles "API" and "Main Page"',
index 1c41113..b7dcd0e 100644 (file)
@@ -67,6 +67,16 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                $searchInfo = array_flip( $params['info'] );
                $prop = array_flip( $params['prop'] );
 
+               // Deprecated parameters
+               if ( isset( $prop['hasrelated'] ) ) {
+                       $this->logFeatureUsage( 'action=search&srprop=hasrelated' );
+                       $this->setWarning( 'srprop=hasrelated has been deprecated' );
+               }
+               if ( isset( $prop['score'] ) ) {
+                       $this->logFeatureUsage( 'action=search&srprop=score' );
+                       $this->setWarning( 'srprop=score has been deprecated' );
+               }
+
                // Create search engine instance and set options
                $search = isset( $params['backend'] ) && $params['backend'] != self::BACKEND_NULL_PARAM ?
                        SearchEngine::create( $params['backend'] ) : SearchEngine::create();
@@ -157,9 +167,6 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                                if ( isset( $prop['timestamp'] ) ) {
                                        $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $result->getTimestamp() );
                                }
-                               if ( !is_null( $result->getScore() ) && isset( $prop['score'] ) ) {
-                                       $vals['score'] = $result->getScore();
-                               }
                                if ( isset( $prop['titlesnippet'] ) ) {
                                        $vals['titlesnippet'] = $result->getTitleSnippet( $terms );
                                }
@@ -179,9 +186,6 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                                                $vals['sectionsnippet'] = $result->getSectionSnippet();
                                        }
                                }
-                               if ( isset( $prop['hasrelated'] ) && $result->hasRelated() ) {
-                                       $vals['hasrelated'] = '';
-                               }
 
                                // Add item to results and see whether it fits
                                $fit = $apiResult->addValue( array( 'query', $this->getModuleName() ),
@@ -200,7 +204,6 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                $hasInterwikiResults = false;
                if ( $interwiki && $resultPageSet === null && $matches->hasInterwikiResults() ) {
                        $matches = $matches->getInterwikiResults();
-                       $iwprefixes = array();
                        $hasInterwikiResults = true;
 
                        // Include number of results if requested
@@ -336,14 +339,14 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                                ' size             - Adds the size of the page in bytes',
                                ' wordcount        - Adds the word count of the page',
                                ' timestamp        - Adds the timestamp of when the page was last edited',
-                               ' score            - Adds the score (if any) from the search engine',
+                               ' score            - DEPRECATED and IGNORED',
                                ' snippet          - Adds a parsed snippet of the page',
                                ' titlesnippet     - Adds a parsed snippet of the page title',
                                ' redirectsnippet  - Adds a parsed snippet of the redirect title',
                                ' redirecttitle    - Adds the title of the matching redirect',
                                ' sectionsnippet   - Adds a parsed snippet of the matching section title',
                                ' sectiontitle     - Adds the title of the matching section',
-                               ' hasrelated       - Indicates whether a related search is available',
+                               ' hasrelated       - DEPRECATED and IGNORED',
                        ),
                        'offset' => 'Use this value to continue paging (return by query)',
                        'limit' => 'How many total pages to return',
@@ -357,75 +360,10 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                return $descriptions;
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       ),
-                       'snippet' => array(
-                               'snippet' => 'string'
-                       ),
-                       'size' => array(
-                               'size' => 'integer'
-                       ),
-                       'wordcount' => array(
-                               'wordcount' => 'integer'
-                       ),
-                       'timestamp' => array(
-                               'timestamp' => 'timestamp'
-                       ),
-                       'score' => array(
-                               'score' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'titlesnippet' => array(
-                               'titlesnippet' => 'string'
-                       ),
-                       'redirecttitle' => array(
-                               'redirecttitle' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'redirectsnippet' => array(
-                               'redirectsnippet' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'sectiontitle' => array(
-                               'sectiontitle' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'sectionsnippet' => array(
-                               'sectionsnippet' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'hasrelated' => array(
-                               'hasrelated' => 'boolean'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Perform a full text search.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'search-text-disabled', 'info' => 'text search is disabled' ),
-                       array( 'code' => 'search-title-disabled', 'info' => 'title search is disabled' ),
-                       array( 'code' => 'search-error', 'info' => 'search error has occurred' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=search&srsearch=meaning',
index aacf091..fd0c429 100644 (file)
@@ -136,8 +136,11 @@ class ApiQuerySiteinfo extends ApiQueryBase {
 
                $data['generator'] = "MediaWiki {$config->get( 'Version' )}";
 
-               $data['phpversion'] = phpversion();
+               $data['phpversion'] = PHP_VERSION;
                $data['phpsapi'] = PHP_SAPI;
+               if ( defined( 'HHVM_VERSION' ) ) {
+                       $data['hhvmversion'] = HHVM_VERSION;
+               }
                $data['dbtype'] = $config->get( 'DBtype' );
                $data['dbversion'] = $this->getDB()->getServerVersion();
 
@@ -166,7 +169,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                if ( $wgContLang->linkPrefixExtension() ) {
                        $linkPrefixCharset = $wgContLang->linkPrefixCharset();
                        $data['linkprefixcharset'] = $linkPrefixCharset;
-                       // For backwards compatability
+                       // For backwards compatibility
                        $data['linkprefix'] = "/^((?>.*[^$linkPrefixCharset]|))(.+)$/sDu";
                } else {
                        $data['linkprefixcharset'] = '';
@@ -242,7 +245,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                $data['articlepath'] = $config->get( 'ArticlePath' );
                $data['scriptpath'] = $config->get( 'ScriptPath' );
                $data['script'] = $config->get( 'Script' );
-               $data['variantarticlepath'] = $config->get( 'VariantArticlePath'  );
+               $data['variantarticlepath'] = $config->get( 'VariantArticlePath' );
                $data['server'] = $config->get( 'Server' );
                $data['servername'] = $config->get( 'ServerName' );
                $data['wikiid'] = wfWikiID();
@@ -262,8 +265,8 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        $data['imagelimits'][$k] = array( 'width' => $limit[0], 'height' => $limit[1] );
                }
 
-                $favicon = $config->get( 'Favicon' );
-                if ( !empty( $favicon ) ) {
+               $favicon = $config->get( 'Favicon' );
+               if ( !empty( $favicon ) ) {
                        // wgFavicon can either be a relative or an absolute path
                        // make sure we always return an absolute path
                        $data['favicon'] = wfExpandUrl( $favicon, PROTO_RELATIVE );
@@ -314,7 +317,8 @@ class ApiQuerySiteinfo extends ApiQueryBase {
 
        protected function appendNamespaceAliases( $property ) {
                global $wgContLang;
-               $aliases = array_merge( $this->getConfig()->get( 'NamespaceAliases' ), $wgContLang->getNamespaceAliases() );
+               $aliases = array_merge( $this->getConfig()->get( 'NamespaceAliases' ),
+                       $wgContLang->getNamespaceAliases() );
                $namespaces = $wgContLang->getNamespaces();
                $data = array();
                foreach ( $aliases as $title => $ns ) {
@@ -392,10 +396,10 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        $prefix = $row['iw_prefix'];
                        $val = array();
                        $val['prefix'] = $prefix;
-                       if ( $row['iw_local'] == '1' ) {
+                       if ( isset( $row['iw_local'] ) && $row['iw_local'] == '1' ) {
                                $val['local'] = '';
                        }
-                       if ( $row['iw_trans'] == '1' ) {
+                       if ( isset( $row['iw_trans'] ) && $row['iw_trans'] == '1' ) {
                                $val['trans'] = '';
                        }
 
@@ -420,7 +424,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        }
 
                        $val['url'] = wfExpandUrl( $row['iw_url'], PROTO_CURRENT );
-                       if (substr( $row['iw_url'], 0, 2) == '//') {
+                       if ( substr( $row['iw_url'], 0, 2 ) == '//' ) {
                                $val['protorel'] = '';
                        }
                        if ( isset( $row['iw_wikiid'] ) ) {
@@ -497,6 +501,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
 
                $data = array();
                $result = $this->getResult();
+               $allGroups = User::getAllGroups();
                foreach ( $config->get( 'GroupPermissions' ) as $group => $permissions ) {
                        $arr = array(
                                'name' => $group,
@@ -523,8 +528,11 @@ class ApiQuerySiteinfo extends ApiQueryBase {
 
                        foreach ( $groupArr as $type => $rights ) {
                                if ( isset( $rights[$group] ) ) {
-                                       $arr[$type] = $rights[$group];
-                                       $result->setIndexedTagName( $arr[$type], 'group' );
+                                       $groups = array_intersect( $rights[$group], $allGroups );
+                                       if ( $groups ) {
+                                               $arr[$type] = $groups;
+                                               $result->setIndexedTagName( $arr[$type], 'group' );
+                                       }
                                }
                        }
 
@@ -688,6 +696,16 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                $allowed = Skin::getAllowedSkins();
                $default = Skin::normalizeKey( 'default' );
                foreach ( Skin::getSkinNames() as $name => $displayName ) {
+                       $msg = $this->msg( "skinname-{$name}" );
+                       $code = $this->getParameter( 'inlanguagecode' );
+                       if ( $code && Language::isValidCode( $code ) ) {
+                               $msg->inLanguage( $code );
+                       } else {
+                               $msg->inContentLanguage();
+                       }
+                       if ( $msg->exists() ) {
+                               $displayName = $msg->text();
+                       }
                        $skin = array( 'code' => $name );
                        ApiResult::setContent( $skin, $displayName );
                        if ( !isset( $allowed[$name] ) ) {
@@ -839,9 +857,10 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                                ' fileextensions        - Returns list of file extensions allowed to be uploaded',
                                ' rightsinfo            - Returns wiki rights (license) information if available',
                                ' restrictions          - Returns information on available restriction (protection) types',
-                               ' languages             - Returns a list of languages MediaWiki supports' .
+                               ' languages             - Returns a list of languages MediaWiki supports ' .
                                        "(optionally localised by using {$p}inlanguagecode)",
-                               ' skins                 - Returns a list of all enabled skins',
+                               ' skins                 - Returns a list of all enabled skins ' .
+                                       "(optionally localised by using {$p}inlanguagecode, otherwise in content language)",
                                ' extensiontags         - Returns a list of parser extension tags',
                                ' functionhooks         - Returns a list of parser function hooks',
                                ' showhooks             - Returns a list of all subscribed hooks (contents of $wgHooks)',
@@ -853,7 +872,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        'showalldb' => 'List all database servers, not just the one lagging the most',
                        'numberingroup' => 'Lists the number of users in user groups',
                        'inlanguagecode' => 'Language code for localised language names ' .
-                               '(best effort, use CLDR extension)',
+                               '(best effort, use CLDR extension) and skin names',
                );
        }
 
@@ -861,13 +880,6 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                return 'Return general information about the site.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array( array(
-                       'code' => 'includeAllDenied',
-                       'info' => 'Cannot view all servers info unless $wgShowHostnames is true'
-               ), ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics',
index d9409ec..db92856 100644 (file)
@@ -47,6 +47,7 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
 
                // Alias sessionkey to filekey, but give an existing filekey precedence.
                if ( !$params['filekey'] && $params['sessionkey'] ) {
+                       $this->logFeatureUsage( 'prop=stashimageinfo&siisessionkey' );
                        $params['filekey'] = $params['sessionkey'];
                }
 
@@ -124,10 +125,6 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
                );
        }
 
-       public function getResultProperties() {
-               return ApiQueryImageInfo::getResultPropertiesFiltered( $this->propertyFilter );
-       }
-
        public function getDescription() {
                return 'Returns image information for stashed images.';
        }
index 77c105a..3184564 100644 (file)
@@ -170,23 +170,6 @@ class ApiQueryTags extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'name' => 'string'
-                       ),
-                       'displayname' => array(
-                               'displayname' => 'string'
-                       ),
-                       'description' => array(
-                               'description' => 'string'
-                       ),
-                       'hitcount' => array(
-                               'hitcount' => 'integer'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'List change tags.';
        }
diff --git a/includes/api/ApiQueryTokens.php b/includes/api/ApiQueryTokens.php
new file mode 100644 (file)
index 0000000..ba9c937
--- /dev/null
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Module to fetch tokens via action=query&meta=tokens
+ *
+ * Created on August 8, 2014
+ *
+ * Copyright © 2014 Brad Jorsch bjorsch@wikimedia.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
+ * @since 1.24
+ */
+
+/**
+ * Module to fetch tokens via action=query&meta=tokens
+ *
+ * @ingroup API
+ * @since 1.24
+ */
+class ApiQueryTokens extends ApiQueryBase {
+
+       public function execute() {
+               $params = $this->extractRequestParams();
+               $res = array();
+
+               if ( $this->getMain()->getRequest()->getVal( 'callback' ) !== null ) {
+                       $this->setWarning( 'Tokens may not be obtained when using a callback' );
+                       return;
+               }
+
+               $salts = self::getTokenTypeSalts();
+               foreach ( $params['type'] as $type ) {
+                       $salt = $salts[$type];
+                       $val = $this->getUser()->getEditToken( $salt, $this->getRequest() );
+                       $res[$type . 'token'] = $val;
+               }
+
+               $this->getResult()->addValue( 'query', $this->getModuleName(), $res );
+       }
+
+       public static function getTokenTypeSalts() {
+               static $salts = null;
+               if ( !$salts ) {
+                       wfProfileIn( __METHOD__ );
+                       $salts = array(
+                               'csrf' => '',
+                               'watch' => 'watch',
+                               'patrol' => 'patrol',
+                               'rollback' => 'rollback',
+                               'userrights' => 'userrights',
+                       );
+                       wfRunHooks( 'ApiQueryTokensRegisterTypes', array( &$salts ) );
+                       ksort( $salts );
+                       wfProfileOut( __METHOD__ );
+               }
+
+               return $salts;
+       }
+
+       public function getAllowedParams() {
+               return array(
+                       'type' => array(
+                               ApiBase::PARAM_DFLT => 'csrf',
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TYPE => array_keys( self::getTokenTypeSalts() ),
+                       ),
+               );
+       }
+
+       public function getParamDescription() {
+               return array(
+                       'type' => 'Type of token(s) to request'
+               );
+       }
+
+       public function getDescription() {
+               return 'Gets tokens for data-modifying actions.';
+       }
+
+       protected function getExamples() {
+               return array(
+                       'api.php?action=query&meta=tokens' => 'Retrieve a csrf token (the default)',
+                       'api.php?action=query&meta=tokens&type=watch|patrol' => 'Retrieve a watch token and a patrol token'
+               );
+       }
+
+       public function getCacheMode( $params ) {
+               return 'private';
+       }
+}
index 24c4c20..4b167b8 100644 (file)
@@ -193,7 +193,7 @@ class ApiQueryContributions extends ApiQueryBase {
                // see the username.
                if ( !$user->isAllowed( 'deletedhistory' ) ) {
                        $bitmask = Revision::DELETED_USER;
-               } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                        $bitmask = Revision::DELETED_USER | Revision::DELETED_RESTRICTED;
                } else {
                        $bitmask = 0;
@@ -224,6 +224,7 @@ class ApiQueryContributions extends ApiQueryBase {
 
                $show = $this->params['show'];
                if ( $this->params['toponly'] ) { // deprecated/old param
+                       $this->logFeatureUsage( 'list=usercontribs&uctoponly' );
                        $show[] = 'top';
                }
                if ( !is_null( $show ) ) {
@@ -326,7 +327,7 @@ class ApiQueryContributions extends ApiQueryBase {
        /**
         * Extract fields from the database row and append them to a result array
         *
-        * @param mixed $row
+        * @param stdClass $row
         * @return array
         */
        private function extractRowInfo( $row ) {
@@ -555,81 +556,10 @@ class ApiQueryContributions extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'userid' => 'integer',
-                               'user' => 'string',
-                               'userhidden' => 'boolean'
-                       ),
-                       'ids' => array(
-                               'pageid' => 'integer',
-                               'revid' => 'integer',
-                               'parentid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'title' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       ),
-                       'timestamp' => array(
-                               'timestamp' => 'timestamp'
-                       ),
-                       'flags' => array(
-                               'new' => 'boolean',
-                               'minor' => 'boolean',
-                               'top' => 'boolean'
-                       ),
-                       'comment' => array(
-                               'commenthidden' => 'boolean',
-                               'comment' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'parsedcomment' => array(
-                               'commenthidden' => 'boolean',
-                               'parsedcomment' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'patrolled' => array(
-                               'patrolled' => 'boolean'
-                       ),
-                       'size' => array(
-                               'size' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'sizediff' => array(
-                               'sizediff' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Get all edits by a user.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'param_user', 'info' => 'User parameter may not be empty.' ),
-                       array( 'code' => 'param_user', 'info' => 'User name user is not valid' ),
-                       array( 'show' ),
-                       array(
-                               'code' => 'permissiondenied',
-                               'info' => 'You need the patrol right to request the patrolled flag'
-                       ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=usercontribs&ucuser=YurikBot',
index 140f35a..fd5f47b 100644 (file)
@@ -69,6 +69,10 @@ class ApiQueryUserInfo extends ApiQueryBase {
                                $vals['blockedby'] = $block->getByName();
                                $vals['blockedbyid'] = $block->getBy();
                                $vals['blockreason'] = $user->blockedFor();
+                               $vals['blockedtimestamp'] = wfTimestamp( TS_ISO_8601, $block->mTimestamp );
+                               $vals['blockexpiry'] = $block->getExpiry() === 'infinity'
+                                       ? 'infinite'
+                                       : wfTimestamp( TS_ISO_8601, $block->getExpiry() );
                        }
                }
 
@@ -104,6 +108,12 @@ class ApiQueryUserInfo extends ApiQueryBase {
                        $vals['options'] = $user->getOptions();
                }
 
+               if ( isset( $this->prop['preferencestoken'] ) ) {
+                       $p = $this->getModulePrefix();
+                       $this->setWarning(
+                               "{$p}prop=preferencestoken has been deprecated. Please use action=query&meta=tokens instead."
+                       );
+               }
                if ( isset( $this->prop['preferencestoken'] ) &&
                        is_null( $this->getMain()->getRequest()->getVal( 'callback' ) ) &&
                        $user->isAllowed( 'editmyoptions' )
@@ -252,7 +262,7 @@ class ApiQueryUserInfo extends ApiQueryBase {
                                '  rights           - Lists all the rights the current user has',
                                '  changeablegroups - Lists the groups the current user can add to and remove from',
                                '  options          - Lists all preferences the current user has set',
-                               '  preferencestoken - Get a token to change current user\'s preferences',
+                               '  preferencestoken - DEPRECATED! Get a token to change current user\'s preferences',
                                '  editcount        - Adds the current user\'s edit count',
                                '  ratelimits       - Lists all rate limits applying to the current user',
                                '  realname         - Adds the user\'s real name',
@@ -267,63 +277,6 @@ class ApiQueryUserInfo extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       ApiBase::PROP_LIST => false,
-                       '' => array(
-                               'id' => 'integer',
-                               'name' => 'string',
-                               'anon' => 'boolean'
-                       ),
-                       'blockinfo' => array(
-                               'blockid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedby' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedbyid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedreason' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'hasmsg' => array(
-                               'messages' => 'boolean'
-                       ),
-                       'preferencestoken' => array(
-                               'preferencestoken' => 'string'
-                       ),
-                       'editcount' => array(
-                               'editcount' => 'integer'
-                       ),
-                       'realname' => array(
-                               'realname' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'email' => array(
-                               'email' => 'string',
-                               'emailauthenticated' => array(
-                                       ApiBase::PROP_TYPE => 'timestamp',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'registrationdate' => array(
-                               'registrationdate' => array(
-                                       ApiBase::PROP_TYPE => 'timestamp',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Get information about the current user.';
        }
index d0d0f08..2f5e4b4 100644 (file)
@@ -58,6 +58,7 @@ class ApiQueryUsers extends ApiQueryBase {
         * Get an array mapping token names to their handler functions.
         * The prototype for a token function is func($user)
         * it should return a token or false (permission denied)
+        * @deprecated since 1.24
         * @return array Array of tokenname => function
         */
        protected function getTokenFunctions() {
@@ -80,6 +81,7 @@ class ApiQueryUsers extends ApiQueryBase {
        }
 
        /**
+        * @deprecated since 1.24
         * @param User $user
         * @return string
         */
@@ -193,6 +195,7 @@ class ApiQueryUsers extends ApiQueryBase {
                                        $data[$name]['blockid'] = $row->ipb_id;
                                        $data[$name]['blockedby'] = $row->ipb_by_text;
                                        $data[$name]['blockedbyid'] = $row->ipb_by;
+                                       $data[$name]['blockedtimestamp'] = wfTimestamp( TS_ISO_8601, $row->ipb_timestamp );
                                        $data[$name]['blockreason'] = $row->ipb_reason;
                                        $data[$name]['blockexpiry'] = $row->ipb_expiry;
                                }
@@ -317,6 +320,7 @@ class ApiQueryUsers extends ApiQueryBase {
                                ApiBase::PARAM_ISMULTI => true
                        ),
                        'token' => array(
+                               ApiBase::PARAM_DEPRECATED => true,
                                ApiBase::PARAM_TYPE => array_keys( $this->getTokenFunctions() ),
                                ApiBase::PARAM_ISMULTI => true
                        ),
@@ -342,73 +346,6 @@ class ApiQueryUsers extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               $props = array(
-                       '' => array(
-                               'userid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'name' => 'string',
-                               'invalid' => 'boolean',
-                               'hidden' => 'boolean',
-                               'interwiki' => 'boolean',
-                               'missing' => 'boolean'
-                       ),
-                       'editcount' => array(
-                               'editcount' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'registration' => array(
-                               'registration' => array(
-                                       ApiBase::PROP_TYPE => 'timestamp',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'blockinfo' => array(
-                               'blockid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedby' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedbyid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedreason' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedexpiry' => array(
-                                       ApiBase::PROP_TYPE => 'timestamp',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'emailable' => array(
-                               'emailable' => 'boolean'
-                       ),
-                       'gender' => array(
-                               'gender' => array(
-                                       ApiBase::PROP_TYPE => array(
-                                               'male',
-                                               'female',
-                                               'unknown'
-                                       ),
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-
-               self::addTokenProperties( $props, $this->getTokenFunctions() );
-
-               return $props;
-       }
-
        public function getDescription() {
                return 'Get information about a list of users.';
        }
index 506fb59..efbe05e 100644 (file)
@@ -224,7 +224,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                if ( !is_null( $params['user'] ) || !is_null( $params['excludeuser'] ) ) {
                        if ( !$user->isAllowed( 'deletedhistory' ) ) {
                                $bitmask = Revision::DELETED_USER;
-                       } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+                       } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                                $bitmask = Revision::DELETED_USER | Revision::DELETED_RESTRICTED;
                        } else {
                                $bitmask = 0;
@@ -238,7 +238,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                // entirely from the watchlist, or someone could guess the title.
                if ( !$user->isAllowed( 'deletedhistory' ) ) {
                        $bitmask = LogPage::DELETED_ACTION;
-               } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                        $bitmask = LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED;
                } else {
                        $bitmask = 0;
@@ -561,109 +561,10 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'type' => array(
-                                       ApiBase::PROP_TYPE => array(
-                                               'edit',
-                                               'new',
-                                               'move',
-                                               'log',
-                                               'move over redirect'
-                                       )
-                               )
-                       ),
-                       'ids' => array(
-                               'pageid' => 'integer',
-                               'revid' => 'integer',
-                               'old_revid' => 'integer'
-                       ),
-                       'title' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       ),
-                       'user' => array(
-                               'user' => 'string',
-                               'anon' => 'boolean'
-                       ),
-                       'userid' => array(
-                               'userid' => 'integer',
-                               'anon' => 'boolean'
-                       ),
-                       'flags' => array(
-                               'new' => 'boolean',
-                               'minor' => 'boolean',
-                               'bot' => 'boolean'
-                       ),
-                       'patrol' => array(
-                               'patrolled' => 'boolean'
-                       ),
-                       'timestamp' => array(
-                               'timestamp' => 'timestamp'
-                       ),
-                       'sizes' => array(
-                               'oldlen' => 'integer',
-                               'newlen' => 'integer'
-                       ),
-                       'notificationtimestamp' => array(
-                               'notificationtimestamp' => array(
-                                       ApiBase::PROP_TYPE => 'timestamp',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'comment' => array(
-                               'comment' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'parsedcomment' => array(
-                               'parsedcomment' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'loginfo' => array(
-                               'logid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'logtype' => array(
-                                       ApiBase::PROP_TYPE => $this->getConfig()->get( 'LogTypes' ),
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'logaction' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return "Get all recent changes to pages in the logged in user's watchlist.";
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'bad_wlowner', 'info' => 'Specified user does not exist' ),
-                       array(
-                               'code' => 'bad_wltoken',
-                               'info' => 'Incorrect watchlist token provided -- ' .
-                                       'please set a correct token in Special:Preferences'
-                       ),
-                       array( 'code' => 'notloggedin', 'info' => 'You must be logged-in to have a watchlist' ),
-                       array( 'code' => 'patrol', 'info' => 'patrol property is not available' ),
-                       array( 'show' ),
-                       array(
-                               'code' => 'permissiondenied',
-                               'info' => 'You need the patrol right to request the patrolled flag'
-                       ),
-                       array( 'code' => 'user-excludeuser', 'info' => 'user and excludeuser cannot be used together' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=watchlist',
index 6aae6dc..6b2223a 100644 (file)
@@ -189,38 +189,10 @@ class ApiQueryWatchlistRaw extends ApiQueryGeneratorBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'ns' => 'namespace',
-                               'title' => 'string'
-                       ),
-                       'changed' => array(
-                               'changed' => array(
-                                       ApiBase::PROP_TYPE => 'timestamp',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return "Get all pages on the logged in user's watchlist.";
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'notloggedin', 'info' => 'You must be logged-in to have a watchlist' ),
-                       array( 'show' ),
-                       array( 'code' => 'bad_wlowner', 'info' => 'Specified user does not exist' ),
-                       array(
-                               'code' => 'bad_wltoken',
-                               'info' => 'Incorrect watchlist token provided -- ' .
-                                       'please set a correct token in Special:Preferences'
-                       ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=watchlistraw',
index b30d9dd..2e80447 100644 (file)
@@ -58,6 +58,14 @@ class ApiResult extends ApiBase {
         */
        const ADD_ON_TOP = 2;
 
+       /**
+        * For addValue() and setElement(), do not check size while adding a value
+        * Don't use this unless you REALLY know what you're doing.
+        * Values added while the size checking was disabled will never be counted
+        * @since 1.24
+        */
+       const NO_SIZE_CHECK = 4;
+
        private $mData, $mIsRawMode, $mSize, $mCheckingSize;
 
        private $continueAllModules = array();
@@ -143,6 +151,7 @@ class ApiResult extends ApiBase {
         * Disable size checking in addValue(). Don't use this unless you
         * REALLY know what you're doing. Values added while size checking
         * was disabled will not be counted (ever)
+        * @deprecated since 1.24, use ApiResult::NO_SIZE_CHECK
         */
        public function disableSizeCheck() {
                $this->mCheckingSize = false;
@@ -150,6 +159,7 @@ class ApiResult extends ApiBase {
 
        /**
         * Re-enable size checking in addValue()
+        * @deprecated since 1.24, use ApiResult::NO_SIZE_CHECK
         */
        public function enableSizeCheck() {
                $this->mCheckingSize = true;
@@ -312,17 +322,16 @@ class ApiResult extends ApiBase {
         * @param array|string|null $path
         * @param string $name
         * @param mixed $value
-        * @param int $flags Zero or more OR-ed flags like OVERRIDE | ADD_ON_TOP. This
-        *    parameter used to be boolean, and the value of OVERRIDE=1 was specifically
-        *    chosen so that it would be backwards compatible with the new method
-        *    signature.
+        * @param int $flags Zero or more OR-ed flags like OVERRIDE | ADD_ON_TOP.
+        *   This parameter used to be boolean, and the value of OVERRIDE=1 was specifically
+        *   chosen so that it would be backwards compatible with the new method signature.
         * @return bool True if $value fits in the result, false if not
         *
         * @since 1.21 int $flags replaced boolean $override
         */
        public function addValue( $path, $name, $value, $flags = 0 ) {
                $data = &$this->mData;
-               if ( $this->mCheckingSize ) {
+               if ( $this->mCheckingSize && !( $flags & ApiResult::NO_SIZE_CHECK ) ) {
                        $newsize = $this->mSize + self::size( $value );
                        $maxResultSize = $this->getConfig()->get( 'APIMaxResultSize' );
                        if ( $newsize > $maxResultSize ) {
@@ -452,7 +461,7 @@ class ApiResult extends ApiBase {
         *
         * @since 1.24
         * @param string|null $continue The "continue" parameter, if any
-        * @param array $allModules Contains ApiBase instances that will be executed
+        * @param ApiBase[] $allModules Contains ApiBase instances that will be executed
         * @param array $generatedModules Names of modules that depend on the generator
         * @return array Two elements: a boolean indicating if the generator is done,
         *   and an array of modules to actually execute.
@@ -588,7 +597,7 @@ class ApiResult extends ApiBase {
                                        $this->getMain()->getRequest()->getValues(),
                                        array_flip( $this->generatorParams )
                                );
-                       } else if ( $this->generatorContinuationData ) {
+                       } elseif ( $this->generatorContinuationData ) {
                                // All the generator-using modules are complete, but the
                                // generator isn't. Continue the generator and restart the
                                // generator-using modules
@@ -616,9 +625,7 @@ class ApiResult extends ApiBase {
                        }
                }
                if ( $data ) {
-                       $this->disableSizeCheck();
-                       $this->addValue( null, $key, $data, ApiResult::ADD_ON_TOP );
-                       $this->enableSizeCheck();
+                       $this->addValue( null, $key, $data, ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
                }
        }
 }
index 2c76f37..cbc3070 100644 (file)
@@ -195,10 +195,6 @@ class ApiRevisionDelete extends ApiBase {
                                ApiBase::PARAM_TYPE => array( 'yes', 'no', 'nochange' ),
                                ApiBase::PARAM_DFLT => 'nochange',
                        ),
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'reason' => null,
                );
        }
@@ -211,7 +207,6 @@ class ApiRevisionDelete extends ApiBase {
                        'hide' => 'What to hide for each revision',
                        'show' => 'What to unhide for each revision',
                        'suppress' => 'Whether to suppress data from administrators as well as others',
-                       'token' => 'A delete token previously retrieved through action=tokens',
                        'reason' => 'Reason for the deletion/undeletion',
                );
        }
@@ -220,22 +215,8 @@ class ApiRevisionDelete extends ApiBase {
                return 'Delete/undelete revisions.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(),
-                       array(
-                               array( 'code' => 'needtarget',
-                                       'info' => 'A target title is required for this RevDel type' ),
-                               array( 'code' => 'badparams', 'info' => 'Bad value for some parameter' ),
-                       )
-               );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getExamples() {
index 80e09b6..f4d3c54 100644 (file)
@@ -40,9 +40,19 @@ class ApiRollback extends ApiBase {
        private $mUser = null;
 
        public function execute() {
+               $user = $this->getUser();
                $params = $this->extractRequestParams();
 
-               // User and title already validated in call to getTokenSalt from Main
+               // WikiPage::doRollback needs a Web UI token, so get one of those if we
+               // validated based on an API rollback token.
+               $token = $params['token'];
+               if ( $user->matchEditToken( $token, 'rollback', $this->getRequest() ) ) {
+                       $token = $this->getUser()->getEditToken(
+                               $this->getWebUITokenSalt( $params ),
+                               $this->getRequest()
+                       );
+               }
+
                $titleObj = $this->getRbTitle( $params );
                $pageObj = WikiPage::factory( $titleObj );
                $summary = $params['summary'];
@@ -50,10 +60,10 @@ class ApiRollback extends ApiBase {
                $retval = $pageObj->doRollback(
                        $this->getRbUser( $params ),
                        $summary,
-                       $params['token'],
+                       $token,
                        $params['markbot'],
                        $details,
-                       $this->getUser()
+                       $user
                );
 
                if ( $retval ) {
@@ -61,7 +71,13 @@ class ApiRollback extends ApiBase {
                        $this->dieUsageMsg( reset( $retval ) );
                }
 
-               $this->setWatch( $params['watchlist'], $titleObj );
+               $watch = 'preferences';
+               if ( isset( $params['watchlist'] ) ) {
+                       $watch = $params['watchlist'];
+               }
+
+               // Watch pages
+               $this->setWatch( $watch, $titleObj, 'watchrollback' );
 
                $info = array(
                        'title' => $titleObj->getPrefixedText(),
@@ -93,10 +109,6 @@ class ApiRollback extends ApiBase {
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => true
                        ),
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'summary' => '',
                        'markbot' => false,
                        'watchlist' => array(
@@ -117,10 +129,11 @@ class ApiRollback extends ApiBase {
                return array(
                        'title' => "Title of the page you want to roll back. Cannot be used together with {$p}pageid",
                        'pageid' => "Page ID of the page you want to roll back. Cannot be used together with {$p}title",
-                       'user' => 'Name of the user whose edits are to be rolled back. If ' .
-                               'set incorrectly, you\'ll get a badtoken error.',
-                       'token' => 'A rollback token previously retrieved through ' .
-                               "{$this->getModulePrefix()}prop=revisions",
+                       'user' => 'Name of the user whose edits are to be rolled back.',
+                       'token' => array(
+                               /* Standard description automatically prepended */
+                               'For compatibility, the token used in the web UI is also accepted.'
+                       ),
                        'summary' => 'Custom edit summary. If empty, default summary will be used',
                        'markbot' => 'Mark the reverted edits and the revert as bot edits',
                        'watchlist' => 'Unconditionally add or remove the page from your watchlist, ' .
@@ -128,19 +141,6 @@ class ApiRollback extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'title' => 'string',
-                               'pageid' => 'integer',
-                               'summary' => 'string',
-                               'revid' => 'integer',
-                               'old_revid' => 'integer',
-                               'last_revid' => 'integer'
-                       )
-               );
-       }
-
        public function getDescription() {
                return array(
                        'Undo the last edit to the page. If the last user who edited the page made',
@@ -148,26 +148,11 @@ class ApiRollback extends ApiBase {
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge(
-                       parent::getPossibleErrors(),
-                       $this->getRequireOnlyOneParameterErrorMessages( array( 'title', 'pageid' ) ),
-                       array(
-                               array( 'invalidtitle', 'title' ),
-                               array( 'notanarticle' ),
-                               array( 'nosuchpageid', 'pageid' ),
-                               array( 'invaliduser', 'user' ),
-                       )
-               );
-       }
-
        public function needsToken() {
-               return true;
+               return 'rollback';
        }
 
-       public function getTokenSalt() {
-               $params = $this->extractRequestParams();
-
+       protected function getWebUITokenSalt( array $params ) {
                return array(
                        $this->getRbTitle( $params )->getPrefixedText(),
                        $this->getRbUser( $params )
index 04be450..5d527fc 100644 (file)
@@ -202,11 +202,7 @@ class ApiSetNotificationTimestamp extends ApiBase {
        }
 
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getAllowedParams( $flags = 0 ) {
@@ -214,7 +210,6 @@ class ApiSetNotificationTimestamp extends ApiBase {
                        'entirewatchlist' => array(
                                ApiBase::PARAM_TYPE => 'boolean'
                        ),
-                       'token' => null,
                        'timestamp' => array(
                                ApiBase::PARAM_TYPE => 'timestamp'
                        ),
@@ -239,48 +234,10 @@ class ApiSetNotificationTimestamp extends ApiBase {
                        'timestamp' => 'Timestamp to which to set the notification timestamp',
                        'torevid' => 'Revision to set the notification timestamp to (one page only)',
                        'newerthanrevid' => 'Revision to set the notification timestamp newer than (one page only)',
-                       'token' => 'A token previously acquired via prop=info',
                        'continue' => 'When more results are available, use this to continue',
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       ApiBase::PROP_LIST => true,
-                       ApiBase::PROP_ROOT => array(
-                               'notificationtimestamp' => array(
-                                       ApiBase::PROP_TYPE => 'timestamp',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       '' => array(
-                               'ns' => array(
-                                       ApiBase::PROP_TYPE => 'namespace',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'title' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'pageid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'revid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'invalid' => 'boolean',
-                               'missing' => 'boolean',
-                               'notwatched' => 'boolean',
-                               'notificationtimestamp' => array(
-                                       ApiBase::PROP_TYPE => 'timestamp',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return array( 'Update the notification timestamp for watched pages.',
                        'This affects the highlighting of changed pages in the watchlist and history,',
@@ -289,25 +246,6 @@ class ApiSetNotificationTimestamp extends ApiBase {
                );
        }
 
-       public function getPossibleErrors() {
-               $ps = $this->getPageSet();
-
-               return array_merge(
-                       parent::getPossibleErrors(),
-                       $ps->getFinalPossibleErrors(),
-                       $this->getRequireMaxOneParameterErrorMessages(
-                               array( 'timestamp', 'torevid', 'newerthanrevid' ) ),
-                       $this->getRequireOnlyOneParameterErrorMessages(
-                               array_merge( array( 'entirewatchlist' ), array_keys( $ps->getFinalParams() ) ) ),
-                       array(
-                               array( 'code' => 'notloggedin', 'info'
-                               => 'Anonymous users cannot use watchlist change notifications' ),
-                               array( 'code' => 'multpages', 'info' => 'torevid may only be used with a single page' ),
-                               array( 'code' => 'multpages', 'info' => 'newerthanrevid may only be used with a single page' ),
-                       )
-               );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=setnotificationtimestamp&entirewatchlist=&token=123ABC'
index 5e197db..9287fe6 100644 (file)
  */
 
 /**
+ * @deprecated since 1.24
  * @ingroup API
  */
 class ApiTokens extends ApiBase {
 
        public function execute() {
+               $this->setWarning(
+                       "action=tokens has been deprecated. Please use action=query&meta=tokens instead."
+               );
+
                $params = $this->extractRequestParams();
                $res = array();
 
@@ -81,16 +86,6 @@ class ApiTokens extends ApiBase {
                );
        }
 
-       public function getResultProperties() {
-               $props = array(
-                       '' => array(),
-               );
-
-               self::addTokenProperties( $props, $this->getTokenTypes() );
-
-               return $props;
-       }
-
        public function getParamDescription() {
                return array(
                        'type' => 'Type of token(s) to request'
@@ -98,7 +93,10 @@ class ApiTokens extends ApiBase {
        }
 
        public function getDescription() {
-               return 'Gets tokens for data-modifying actions.';
+               return array(
+                       'This module is deprecated in favor of action=query&meta=tokens.',
+                       'Gets tokens for data-modifying actions.'
+               );
        }
 
        protected function getExamples() {
index f34d4df..2854a82 100644 (file)
@@ -89,7 +89,6 @@ class ApiUnblock extends ApiBase {
                                ApiBase::PARAM_TYPE => 'integer',
                        ),
                        'user' => null,
-                       'token' => null,
                        'reason' => '',
                );
        }
@@ -102,54 +101,16 @@ class ApiUnblock extends ApiBase {
                                "Cannot be used together with {$p}user",
                        'user' => "Username, IP address or IP range you want to unblock. " .
                                "Cannot be used together with {$p}id",
-                       'token' => "An unblock token previously obtained through prop=info",
                        'reason' => 'Reason for unblock',
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'id' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'user' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'userid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'reason' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Unblock a user.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'unblock-notarget' ),
-                       array( 'unblock-idanduser' ),
-                       array( 'cantunblock' ),
-                       array( 'ipbblocked' ),
-                       array( 'ipbnounblockself' ),
-               ) );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getExamples() {
index 332ed51..07aad9f 100644 (file)
@@ -56,11 +56,11 @@ class ApiUndelete extends ApiBase {
                        $params['timestamps'][$i] = wfTimestamp( TS_MW, $ts );
                }
 
-               $pa = new PageArchive( $titleObj );
+               $pa = new PageArchive( $titleObj, $this->getConfig() );
                $retval = $pa->undelete(
                        ( isset( $params['timestamps'] ) ? $params['timestamps'] : array() ),
                        $params['reason'],
-                       array(),
+                       $params['fileids'],
                        false,
                        $this->getUser()
                );
@@ -70,7 +70,7 @@ class ApiUndelete extends ApiBase {
 
                if ( $retval[1] ) {
                        wfRunHooks( 'FileUndeleteComplete',
-                               array( $titleObj, array(), $this->getUser(), $params['reason'] ) );
+                               array( $titleObj, $params['fileids'], $this->getUser(), $params['reason'] ) );
                }
 
                $this->setWatch( $params['watchlist'], $titleObj );
@@ -96,15 +96,15 @@ class ApiUndelete extends ApiBase {
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => true
                        ),
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'reason' => '',
                        'timestamps' => array(
                                ApiBase::PARAM_TYPE => 'timestamp',
                                ApiBase::PARAM_ISMULTI => true,
                        ),
+                       'fileids' => array(
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_ISMULTI => true,
+                       ),
                        'watchlist' => array(
                                ApiBase::PARAM_DFLT => 'preferences',
                                ApiBase::PARAM_TYPE => array(
@@ -120,48 +120,30 @@ class ApiUndelete extends ApiBase {
        public function getParamDescription() {
                return array(
                        'title' => 'Title of the page you want to restore',
-                       'token' => 'An undelete token previously retrieved through list=deletedrevs',
                        'reason' => 'Reason for restoring',
-                       'timestamps' => 'Timestamps of the revisions to restore. If not set, all ' .
-                               'revisions will be restored.',
+                       'timestamps' => array(
+                               'Timestamps of the revisions to restore.',
+                               'If both timestamps and fileids are empty, all will be restored.',
+                       ),
+                       'fileids' => array(
+                               'IDs of the file revisions to restore.',
+                               'If both timestamps and fileids are empty, all will be restored.',
+                       ),
                        'watchlist' => 'Unconditionally add or remove the page from your ' .
                                'watchlist, use preferences or do not change watch',
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'title' => 'string',
-                               'revisions' => 'integer',
-                               'filerevisions' => 'integer',
-                               'reason' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return array(
                        'Restore certain revisions of a deleted page. A list of deleted revisions ',
-                       '(including timestamps) can be retrieved through list=deletedrevs.'
+                       '(including timestamps) can be retrieved through list=deletedrevs, and a list',
+                       'of deleted file ids can be retrieved through list=filearchive.'
                );
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'permdenied-undelete' ),
-                       array( 'blockedtext' ),
-                       array( 'invalidtitle', 'title' ),
-                       array( 'cannotundelete' ),
-               ) );
-       }
-
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getExamples() {
index 5e6c962..657181b 100644 (file)
@@ -28,7 +28,7 @@
  * @ingroup API
  */
 class ApiUpload extends ApiBase {
-       /** @var UploadBase */
+       /** @var UploadBase|UploadFromChunks */
        protected $mUpload = null;
 
        protected $mParams;
@@ -52,6 +52,7 @@ class ApiUpload extends ApiBase {
 
                // Copy the session key to the file key, for backward compatibility.
                if ( !$this->mParams['filekey'] && $this->mParams['sessionkey'] ) {
+                       $this->logFeatureUsage( 'action=upload&sessionkey' );
                        $this->mParams['filekey'] = $this->mParams['sessionkey'];
                }
 
@@ -210,7 +211,6 @@ class ApiUpload extends ApiBase {
                        }
                } else {
                        $filekey = $this->mParams['filekey'];
-                       /** @var $status Status */
                        $status = $this->mUpload->addChunk(
                                $chunkPath, $chunkSize, $this->mParams['offset'] );
                        if ( !$status->isGood() ) {
@@ -241,6 +241,7 @@ class ApiUpload extends ApiBase {
                                        )
                                ) );
                                $result['result'] = 'Poll';
+                               $result['stage'] = 'queued';
                        } else {
                                $status = $this->mUpload->concatenateChunks();
                                if ( !$status->isGood() ) {
@@ -467,6 +468,7 @@ class ApiUpload extends ApiBase {
 
        /**
         * Performs file verification, dies on error.
+        * @param array $verification
         */
        protected function checkVerification( array $verification ) {
                // @todo Move them to ApiBase's message map
@@ -551,6 +553,7 @@ class ApiUpload extends ApiBase {
 
                        if ( isset( $warnings['duplicate'] ) ) {
                                $dupes = array();
+                               /** @var File $dupe */
                                foreach ( $warnings['duplicate'] as $dupe ) {
                                        $dupes[] = $dupe->getName();
                                }
@@ -561,6 +564,7 @@ class ApiUpload extends ApiBase {
                        if ( isset( $warnings['exists'] ) ) {
                                $warning = $warnings['exists'];
                                unset( $warnings['exists'] );
+                               /** @var LocalFile $localFile */
                                $localFile = isset( $warning['normalizedFile'] )
                                        ? $warning['normalizedFile']
                                        : $warning['file'];
@@ -602,6 +606,7 @@ class ApiUpload extends ApiBase {
 
                // Deprecated parameters
                if ( $this->mParams['watch'] ) {
+                       $this->logFeatureUsage( 'action=upload&watch' );
                        $watch = true;
                }
 
@@ -627,6 +632,7 @@ class ApiUpload extends ApiBase {
                                )
                        ) );
                        $result['result'] = 'Poll';
+                       $result['stage'] = 'queued';
                } else {
                        /** @var $status Status */
                        $status = $this->mUpload->performUpload( $this->mParams['comment'],
@@ -684,10 +690,6 @@ class ApiUpload extends ApiBase {
                                ApiBase::PARAM_DFLT => ''
                        ),
                        'text' => null,
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'watch' => array(
                                ApiBase::PARAM_DFLT => false,
                                ApiBase::PARAM_DEPRECATED => true,
@@ -731,7 +733,6 @@ class ApiUpload extends ApiBase {
        public function getParamDescription() {
                $params = array(
                        'filename' => 'Target filename',
-                       'token' => 'Edit token. You can get one of these through prop=info',
                        'comment' => 'Upload comment. Also used as the initial page text for new ' .
                                'files if "text" is not specified',
                        'text' => 'Initial page text for new files',
@@ -760,41 +761,6 @@ class ApiUpload extends ApiBase {
                return $params;
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'result' => array(
-                                       ApiBase::PROP_TYPE => array(
-                                               'Success',
-                                               'Warning',
-                                               'Continue',
-                                               'Queued'
-                                       ),
-                               ),
-                               'filekey' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'sessionkey' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'offset' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'statuskey' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'filename' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       )
-               );
-       }
-
        public function getDescription() {
                return array(
                        'Upload a file, or get the status of pending uploads. Several methods are available:',
@@ -802,50 +768,20 @@ class ApiUpload extends ApiBase {
                        ' * Have the MediaWiki server fetch a file from a URL, using the "url" parameter',
                        ' * Complete an earlier upload that failed due to warnings, using the "filekey" parameter',
                        'Note that the HTTP POST must be done as a file upload (i.e. using multipart/form-data) when',
-                       'sending the "file". Also you must get and send an edit token before doing any upload stuff.'
-               );
-       }
-
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(),
-                       $this->getRequireOnlyOneParameterErrorMessages( array( 'filekey', 'file', 'url', 'statuskey' ) ),
-                       array(
-                               array( 'uploaddisabled' ),
-                               array( 'invalid-file-key' ),
-                               array( 'uploaddisabled' ),
-                               array( 'mustbeloggedin', 'upload' ),
-                               array( 'badaccess-groups' ),
-                               array( 'code' => 'fetchfileerror', 'info' => '' ),
-                               array( 'code' => 'nomodule', 'info' => 'No upload module set' ),
-                               array( 'code' => 'empty-file', 'info' => 'The file you submitted was empty' ),
-                               array( 'code' => 'filetype-missing', 'info' => 'The file is missing an extension' ),
-                               array( 'code' => 'filename-tooshort', 'info' => 'The filename is too short' ),
-                               array( 'code' => 'overwrite', 'info' => 'Overwriting an existing file is not allowed' ),
-                               array( 'code' => 'stashfailed', 'info' => 'Stashing temporary file failed' ),
-                               array( 'code' => 'publishfailed', 'info' => 'Publishing of stashed file failed' ),
-                               array( 'code' => 'internal-error', 'info' => 'An internal error occurred' ),
-                               array( 'code' => 'asynccopyuploaddisabled', 'info' => 'Asynchronous copy uploads disabled' ),
-                               array( 'code' => 'stasherror', 'info' => 'An upload stash error occurred' ),
-                               array( 'fileexists-forbidden' ),
-                               array( 'fileexists-shared-forbidden' ),
-                       )
+                       'sending the "file".',
                );
        }
 
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
-               return '';
+               return 'csrf';
        }
 
        public function getExamples() {
                return array(
                        'api.php?action=upload&filename=Wiki.png' .
-                       '&url=http%3A//upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png'
+                       '&url=http%3A//upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png&token=123ABC'
                                => 'Upload from a URL',
-                       'api.php?action=upload&filename=Wiki.png&filekey=filekey&ignorewarnings=1'
+                       'api.php?action=upload&filename=Wiki.png&filekey=filekey&ignorewarnings=1&token=123ABC'
                                => 'Complete an upload that failed due to warnings',
                );
        }
index 0bed859..c3ceb34 100644 (file)
@@ -35,7 +35,7 @@ class ApiUserrights extends ApiBase {
        public function execute() {
                $params = $this->extractRequestParams();
 
-               $user = $this->getUrUser();
+               $user = $this->getUrUser( $params );
 
                $form = new UserrightsPage;
                $form->setContext( $this->getContext() );
@@ -53,14 +53,14 @@ class ApiUserrights extends ApiBase {
        }
 
        /**
+        * @param array $params
         * @return User
         */
-       private function getUrUser() {
+       private function getUrUser( array $params ) {
                if ( $this->mUser !== null ) {
                        return $this->mUser;
                }
 
-               $params = $this->extractRequestParams();
                $this->requireOnlyOneParameter( $params, 'user', 'userid' );
 
                $user = isset( $params['user'] ) ? $params['user'] : '#' . $params['userid'];
@@ -101,10 +101,6 @@ class ApiUserrights extends ApiBase {
                                ApiBase::PARAM_TYPE => User::getAllGroups(),
                                ApiBase::PARAM_ISMULTI => true
                        ),
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'reason' => array(
                                ApiBase::PARAM_DFLT => ''
                        )
@@ -117,7 +113,10 @@ class ApiUserrights extends ApiBase {
                        'userid' => 'User id',
                        'add' => 'Add the user to these groups',
                        'remove' => 'Remove the user from these groups',
-                       'token' => 'A userrights token previously retrieved through list=users',
+                       'token' => array(
+                               /* Standard description automatically prepended */
+                               'For compatibility, the token used in the web UI is also accepted.'
+                       ),
                        'reason' => 'Reason for the change',
                );
        }
@@ -127,11 +126,11 @@ class ApiUserrights extends ApiBase {
        }
 
        public function needsToken() {
-               return true;
+               return 'userrights';
        }
 
-       public function getTokenSalt() {
-               return $this->getUrUser()->getName();
+       protected function getWebUITokenSalt( array $params ) {
+               return $this->getUrUser( $params )->getName();
        }
 
        public function getExamples() {
index c5aa90e..e6a660b 100644 (file)
@@ -84,6 +84,7 @@ class ApiWatch extends ApiBase {
                                );
                        }
 
+                       $this->logFeatureUsage( 'action=watch&title' );
                        $title = Title::newFromText( $params['title'] );
                        if ( !$title || !$title->isWatchable() ) {
                                $this->dieUsageMsg( array( 'invalidtitle', $params['title'] ) );
@@ -165,10 +166,6 @@ class ApiWatch extends ApiBase {
        }
 
        public function needsToken() {
-               return true;
-       }
-
-       public function getTokenSalt() {
                return 'watch';
        }
 
@@ -180,10 +177,6 @@ class ApiWatch extends ApiBase {
                        ),
                        'unwatch' => false,
                        'uselang' => null,
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
-                       ),
                        'continue' => '',
                );
                if ( $flags ) {
@@ -200,34 +193,14 @@ class ApiWatch extends ApiBase {
                        'title' => 'The page to (un)watch. use titles instead',
                        'unwatch' => 'If set the page will be unwatched rather than watched',
                        'uselang' => 'Language to show the message in',
-                       'token' => 'A token previously acquired via prop=info',
                        'continue' => 'When more results are available, use this to continue',
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'title' => 'string',
-                               'unwatched' => 'boolean',
-                               'watched' => 'boolean',
-                               'message' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Add or remove pages from/to the current user\'s watchlist.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'notloggedin', 'info' => 'You must be logged-in to have a watchlist' ),
-                       array( 'invalidtitle', 'title' ),
-                       array( 'hookaborted' ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=watch&titles=Main_Page' => 'Watch the page "Main Page"',
index 15d7c89..9b48ecb 100644 (file)
@@ -156,7 +156,7 @@ class FileDependency extends CacheDependency {
        /**
         * Create a file dependency
         *
-        * @param string $filename the name of the file, preferably fully qualified
+        * @param string $filename The name of the file, preferably fully qualified
         * @param null|bool|int $timestamp The unix last modified timestamp, or false if the
         *        file does not exist. If omitted, the timestamp will be loaded from
         *        the file.
diff --git a/includes/cache/CacheHelper.php b/includes/cache/CacheHelper.php
new file mode 100644 (file)
index 0000000..401c2b9
--- /dev/null
@@ -0,0 +1,386 @@
+<?php
+/**
+ * Cache of various elements in a single cache entry.
+ *
+ * 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
+ * @license GNU GPL v2 or later
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+
+/**
+ * Interface for all classes implementing CacheHelper functionality.
+ *
+ * @since 1.20
+ */
+interface ICacheHelper {
+       /**
+        * Sets if the cache should be enabled or not.
+        *
+        * @since 1.20
+        * @param bool $cacheEnabled
+        */
+       function setCacheEnabled( $cacheEnabled );
+
+       /**
+        * Initializes the caching.
+        * Should be called before the first time anything is added via addCachedHTML.
+        *
+        * @since 1.20
+        *
+        * @param int|null $cacheExpiry Sets the cache expiry, either ttl in seconds or unix timestamp.
+        * @param bool|null $cacheEnabled Sets if the cache should be enabled or not.
+        */
+       function startCache( $cacheExpiry = null, $cacheEnabled = null );
+
+       /**
+        * Get a cached value if available or compute it if not and then cache it if possible.
+        * The provided $computeFunction is only called when the computation needs to happen
+        * and should return a result value. $args are arguments that will be passed to the
+        * compute function when called.
+        *
+        * @since 1.20
+        *
+        * @param callable $computeFunction
+        * @param array|mixed $args
+        * @param string|null $key
+        *
+        * @return mixed
+        */
+       function getCachedValue( $computeFunction, $args = array(), $key = null );
+
+       /**
+        * Saves the HTML to the cache in case it got recomputed.
+        * Should be called after the last time anything is added via addCachedHTML.
+        *
+        * @since 1.20
+        */
+       function saveCache();
+
+       /**
+        * Sets the time to live for the cache, in seconds or a unix timestamp
+        * indicating the point of expiry...
+        *
+        * @since 1.20
+        *
+        * @param int $cacheExpiry
+        */
+       function setExpiry( $cacheExpiry );
+}
+
+/**
+ * Helper class for caching various elements in a single cache entry.
+ *
+ * To get a cached value or compute it, use getCachedValue like this:
+ * $this->getCachedValue( $callback );
+ *
+ * To add HTML that should be cached, use addCachedHTML like this:
+ * $this->addCachedHTML( $callback );
+ *
+ * The callback function is only called when needed, so do all your expensive
+ * computations here. This function should returns the HTML to be cached.
+ * It should not add anything to the PageOutput object!
+ *
+ * Before the first addCachedHTML call, you should call $this->startCache();
+ * After adding the last HTML that should be cached, call $this->saveCache();
+ *
+ * @since 1.20
+ */
+class CacheHelper implements ICacheHelper {
+       /**
+        * The time to live for the cache, in seconds or a unix timestamp indicating the point of expiry.
+        *
+        * @since 1.20
+        * @var int
+        */
+       protected $cacheExpiry = 3600;
+
+       /**
+        * List of HTML chunks to be cached (if !hasCached) or that where cached (of hasCached).
+        * If not cached already, then the newly computed chunks are added here,
+        * if it as cached already, chunks are removed from this list as they are needed.
+        *
+        * @since 1.20
+        * @var array
+        */
+       protected $cachedChunks;
+
+       /**
+        * Indicates if the to be cached content was already cached.
+        * Null if this information is not available yet.
+        *
+        * @since 1.20
+        * @var bool|null
+        */
+       protected $hasCached = null;
+
+       /**
+        * If the cache is enabled or not.
+        *
+        * @since 1.20
+        * @var bool
+        */
+       protected $cacheEnabled = true;
+
+       /**
+        * Function that gets called when initialization is done.
+        *
+        * @since 1.20
+        * @var callable
+        */
+       protected $onInitHandler = false;
+
+       /**
+        * Elements to build a cache key with.
+        *
+        * @since 1.20
+        * @var array
+        */
+       protected $cacheKey = array();
+
+       /**
+        * Sets if the cache should be enabled or not.
+        *
+        * @since 1.20
+        * @param bool $cacheEnabled
+        */
+       public function setCacheEnabled( $cacheEnabled ) {
+               $this->cacheEnabled = $cacheEnabled;
+       }
+
+       /**
+        * Initializes the caching.
+        * Should be called before the first time anything is added via addCachedHTML.
+        *
+        * @since 1.20
+        *
+        * @param int|null $cacheExpiry Sets the cache expiry, either ttl in seconds or unix timestamp.
+        * @param bool|null $cacheEnabled Sets if the cache should be enabled or not.
+        */
+       public function startCache( $cacheExpiry = null, $cacheEnabled = null ) {
+               if ( is_null( $this->hasCached ) ) {
+                       if ( !is_null( $cacheExpiry ) ) {
+                               $this->cacheExpiry = $cacheExpiry;
+                       }
+
+                       if ( !is_null( $cacheEnabled ) ) {
+                               $this->setCacheEnabled( $cacheEnabled );
+                       }
+
+                       $this->initCaching();
+               }
+       }
+
+       /**
+        * Returns a message that notifies the user he/she is looking at
+        * a cached version of the page, including a refresh link.
+        *
+        * @since 1.20
+        *
+        * @param IContextSource $context
+        * @param bool $includePurgeLink
+        *
+        * @return string
+        */
+       public function getCachedNotice( IContextSource $context, $includePurgeLink = true ) {
+               if ( $this->cacheExpiry < 86400 * 3650 ) {
+                       $message = $context->msg(
+                               'cachedspecial-viewing-cached-ttl',
+                               $context->getLanguage()->formatDuration( $this->cacheExpiry )
+                       )->escaped();
+               } else {
+                       $message = $context->msg(
+                               'cachedspecial-viewing-cached-ts'
+                       )->escaped();
+               }
+
+               if ( $includePurgeLink ) {
+                       $refreshArgs = $context->getRequest()->getQueryValues();
+                       unset( $refreshArgs['title'] );
+                       $refreshArgs['action'] = 'purge';
+
+                       $subPage = $context->getTitle()->getFullText();
+                       $subPage = explode( '/', $subPage, 2 );
+                       $subPage = count( $subPage ) > 1 ? $subPage[1] : false;
+
+                       $message .= ' ' . Linker::link(
+                               $context->getTitle( $subPage ),
+                               $context->msg( 'cachedspecial-refresh-now' )->escaped(),
+                               array(),
+                               $refreshArgs
+                       );
+               }
+
+               return $message;
+       }
+
+       /**
+        * Initializes the caching if not already done so.
+        * Should be called before any of the caching functionality is used.
+        *
+        * @since 1.20
+        */
+       protected function initCaching() {
+               if ( $this->cacheEnabled && is_null( $this->hasCached ) ) {
+                       $cachedChunks = wfGetCache( CACHE_ANYTHING )->get( $this->getCacheKeyString() );
+
+                       $this->hasCached = is_array( $cachedChunks );
+                       $this->cachedChunks = $this->hasCached ? $cachedChunks : array();
+
+                       if ( $this->onInitHandler !== false ) {
+                               call_user_func( $this->onInitHandler, $this->hasCached );
+                       }
+               }
+       }
+
+       /**
+        * Get a cached value if available or compute it if not and then cache it if possible.
+        * The provided $computeFunction is only called when the computation needs to happen
+        * and should return a result value. $args are arguments that will be passed to the
+        * compute function when called.
+        *
+        * @since 1.20
+        *
+        * @param callable $computeFunction
+        * @param array|mixed $args
+        * @param string|null $key
+        *
+        * @return mixed
+        */
+       public function getCachedValue( $computeFunction, $args = array(), $key = null ) {
+               $this->initCaching();
+
+               if ( $this->cacheEnabled && $this->hasCached ) {
+                       $value = null;
+
+                       if ( is_null( $key ) ) {
+                               $itemKey = array_keys( array_slice( $this->cachedChunks, 0, 1 ) );
+                               $itemKey = array_shift( $itemKey );
+
+                               if ( !is_integer( $itemKey ) ) {
+                                       wfWarn( "Attempted to get item with non-numeric key while " .
+                                               "the next item in the queue has a key ($itemKey) in " . __METHOD__ );
+                               } elseif ( is_null( $itemKey ) ) {
+                                       wfWarn( "Attempted to get an item while the queue is empty in " . __METHOD__ );
+                               } else {
+                                       $value = array_shift( $this->cachedChunks );
+                               }
+                       } else {
+                               if ( array_key_exists( $key, $this->cachedChunks ) ) {
+                                       $value = $this->cachedChunks[$key];
+                                       unset( $this->cachedChunks[$key] );
+                               } else {
+                                       wfWarn( "There is no item with key '$key' in this->cachedChunks in " . __METHOD__ );
+                               }
+                       }
+               } else {
+                       if ( !is_array( $args ) ) {
+                               $args = array( $args );
+                       }
+
+                       $value = call_user_func_array( $computeFunction, $args );
+
+                       if ( $this->cacheEnabled ) {
+                               if ( is_null( $key ) ) {
+                                       $this->cachedChunks[] = $value;
+                               } else {
+                                       $this->cachedChunks[$key] = $value;
+                               }
+                       }
+               }
+
+               return $value;
+       }
+
+       /**
+        * Saves the HTML to the cache in case it got recomputed.
+        * Should be called after the last time anything is added via addCachedHTML.
+        *
+        * @since 1.20
+        */
+       public function saveCache() {
+               if ( $this->cacheEnabled && $this->hasCached === false && !empty( $this->cachedChunks ) ) {
+                       wfGetCache( CACHE_ANYTHING )->set(
+                               $this->getCacheKeyString(),
+                               $this->cachedChunks,
+                               $this->cacheExpiry
+                       );
+               }
+       }
+
+       /**
+        * Sets the time to live for the cache, in seconds or a unix timestamp
+        * indicating the point of expiry...
+        *
+        * @since 1.20
+        *
+        * @param int $cacheExpiry
+        */
+       public function setExpiry( $cacheExpiry ) {
+               $this->cacheExpiry = $cacheExpiry;
+       }
+
+       /**
+        * Returns the cache key to use to cache this page's HTML output.
+        * Is constructed from the special page name and language code.
+        *
+        * @since 1.20
+        *
+        * @return string
+        * @throws MWException
+        */
+       protected function getCacheKeyString() {
+               if ( $this->cacheKey === array() ) {
+                       throw new MWException( 'No cache key set, so cannot obtain or save the CacheHelper values.' );
+               }
+
+               return call_user_func_array( 'wfMemcKey', $this->cacheKey );
+       }
+
+       /**
+        * Sets the cache key that should be used.
+        *
+        * @since 1.20
+        *
+        * @param array $cacheKey
+        */
+       public function setCacheKey( array $cacheKey ) {
+               $this->cacheKey = $cacheKey;
+       }
+
+       /**
+        * Rebuild the content, even if it's already cached.
+        * This effectively has the same effect as purging the cache,
+        * since it will be overridden with the new value on the next request.
+        *
+        * @since 1.20
+        */
+       public function rebuildOnDemand() {
+               $this->hasCached = false;
+       }
+
+       /**
+        * Sets a function that gets called when initialization of the cache is done.
+        *
+        * @since 1.20
+        *
+        * @param callable $handlerFunction
+        */
+       public function setOnInitializedHandler( $handlerFunction ) {
+               $this->onInitHandler = $handlerFunction;
+       }
+}
index 76cc583..48c063f 100644 (file)
@@ -180,6 +180,8 @@ class LinkBatch {
         * @return bool|ResultWrapper
         */
        public function doQuery() {
+               global $wgContentHandlerUseDB;
+
                if ( $this->isEmpty() ) {
                        return false;
                }
@@ -190,6 +192,11 @@ class LinkBatch {
                $table = 'page';
                $fields = array( 'page_id', 'page_namespace', 'page_title', 'page_len',
                        'page_is_redirect', 'page_latest' );
+
+               if ( $wgContentHandlerUseDB ) {
+                       $fields[] = 'page_content_model';
+               }
+
                $conds = $this->constructSet( 'page', $dbr );
 
                // Do query
index e80dfb3..6925df9 100644 (file)
@@ -129,10 +129,10 @@ class LinkCache {
         * @param int $len Text's length
         * @param int $redir Whether the page is a redirect
         * @param int $revision Latest revision's ID
-        * @param int $model Latest revision's content model ID
+        * @param string|null $model Latest revision's content model ID
         */
        public function addGoodLinkObj( $id, $title, $len = -1, $redir = null,
-               $revision = 0, $model = 0
+               $revision = 0, $model = null
        ) {
                $dbkey = $title->getPrefixedDBkey();
                $this->mGoodLinks[$dbkey] = (int)$id;
@@ -140,7 +140,7 @@ class LinkCache {
                        'length' => (int)$len,
                        'redirect' => (int)$redir,
                        'revision' => (int)$revision,
-                       'model' => (int)$model
+                       'model' => $model ? (string)$model : null,
                );
        }
 
index ec36cfb..ae27fba 100644 (file)
@@ -20,8 +20,6 @@
  * @file
  */
 
-define( 'MW_LC_VERSION', 2 );
-
 /**
  * Class for caching the contents of localisation files, Messages*.php
  * and *.i18n.php.
@@ -35,6 +33,8 @@ define( 'MW_LC_VERSION', 2 );
  * as grammatical transformation, is done by the caller.
  */
 class LocalisationCache {
+       const VERSION = 2;
+
        /** Configuration associative array */
        private $conf;
 
@@ -200,9 +200,6 @@ class LocalisationCache {
                                case 'db':
                                        $storeClass = 'LCStoreDB';
                                        break;
-                               case 'accel':
-                                       $storeClass = 'LCStoreAccel';
-                                       break;
                                case 'detect':
                                        $storeClass = $wgCacheDirectory ? 'LCStoreCDB' : 'LCStoreDB';
                                        break;
@@ -404,7 +401,7 @@ class LocalisationCache {
                $deps = $this->store->get( $code, 'deps' );
                $keys = $this->store->get( $code, 'list' );
                $preload = $this->store->get( $code, 'preload' );
-               // Different keys may expire separately, at least in LCStoreAccel
+               // 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" );
 
@@ -536,7 +533,7 @@ class LocalisationCache {
        /**
         * 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
+        * @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 ) {
@@ -686,6 +683,7 @@ class LocalisationCache {
         *
         * @param string $code
         * @param array $deps
+        * @return array
         */
        protected function readSourceFilesAndRegisterDeps( $code, &$deps ) {
                global $IP;
@@ -773,7 +771,7 @@ class LocalisationCache {
         *
         * Returns true if any data from the extension array was used, false
         * otherwise.
-        * @param string $codeSequence
+        * @param array $codeSequence
         * @param string $key
         * @param mixed $value
         * @param mixed $fallbackValue
@@ -842,78 +840,114 @@ class LocalisationCache {
                        if ( $coreData['fallbackSequence'][$len - 1] !== 'en' ) {
                                $coreData['fallbackSequence'][] = 'en';
                        }
+               }
 
-                       # Load the fallback localisation item by item and merge it
-                       foreach ( $coreData['fallbackSequence'] as $fbCode ) {
-                               # Load the secondary localisation from the source file to
-                               # avoid infinite cycles on cyclic fallbacks
-                               $fbData = $this->readSourceFilesAndRegisterDeps( $fbCode, $deps );
-                               if ( $fbData === false ) {
-                                       continue;
-                               }
+               $codeSequence = array_merge( array( $code ), $coreData['fallbackSequence'] );
 
-                               foreach ( self::$allKeys as $key ) {
-                                       if ( !isset( $fbData[$key] ) ) {
-                                               continue;
-                                       }
+               wfProfileIn( __METHOD__ . '-fallbacks' );
+
+               # Load non-JSON localisation data for extensions
+               $extensionData = array_combine(
+                       $codeSequence,
+                       array_fill( 0, count( $codeSequence ), $initialData ) );
+               foreach ( $wgExtensionMessagesFiles as $extension => $fileName ) {
+                       if ( isset( $wgMessagesDirs[$extension] ) ) {
+                               # This extension has JSON message data; skip the PHP shim
+                               continue;
+                       }
+
+                       $data = $this->readPHPFile( $fileName, 'extension' );
+                       $used = false;
 
-                                       if ( is_null( $coreData[$key] ) || $this->isMergeableKey( $key ) ) {
-                                               $this->mergeItem( $key, $coreData[$key], $fbData[$key] );
+                       foreach ( $data as $key => $item ) {
+                               foreach ( $codeSequence as $csCode ) {
+                                       if ( isset( $item[$csCode] ) ) {
+                                               $this->mergeItem( $key, $extensionData[$csCode][$key], $item[$csCode] );
+                                               $used = true;
                                        }
                                }
                        }
-               }
 
-               $codeSequence = array_merge( array( $code ), $coreData['fallbackSequence'] );
+                       if ( $used ) {
+                               $deps[] = new FileDependency( $fileName );
+                       }
+               }
 
-               # Load core messages and the extension localisations.
-               wfProfileIn( __METHOD__ . '-extensions' );
+               # Load the localisation data for each fallback, then merge it into the full array
                $allData = $initialData;
-               foreach ( $wgMessagesDirs as $dirs ) {
-                       foreach ( (array)$dirs as $dir ) {
-                               foreach ( $codeSequence as $csCode ) {
+               foreach ( $codeSequence as $csCode ) {
+                       $csData = $initialData;
+
+                       # Load core messages and the extension localisations.
+                       foreach ( $wgMessagesDirs as $dirs ) {
+                               foreach ( (array)$dirs as $dir ) {
                                        $fileName = "$dir/$csCode.json";
                                        $data = $this->readJSONFile( $fileName );
 
                                        foreach ( $data as $key => $item ) {
-                                               $this->mergeItem( $key, $allData[$key], $item );
+                                               $this->mergeItem( $key, $csData[$key], $item );
                                        }
 
                                        $deps[] = new FileDependency( $fileName );
                                }
                        }
-               }
 
-               foreach ( $wgExtensionMessagesFiles as $extension => $fileName ) {
-                       if ( isset( $wgMessagesDirs[$extension] ) ) {
-                               # Already loaded the JSON files for this extension; skip the PHP shim
-                               continue;
+                       # Merge non-JSON extension data
+                       if ( isset( $extensionData[$csCode] ) ) {
+                               foreach ( $extensionData[$csCode] as $key => $item ) {
+                                       $this->mergeItem( $key, $csData[$key], $item );
+                               }
                        }
 
-                       $data = $this->readPHPFile( $fileName, 'extension' );
-                       $used = false;
-
-                       foreach ( $data as $key => $item ) {
-                               if ( $this->mergeExtensionItem( $codeSequence, $key, $allData[$key], $item ) ) {
-                                       $used = true;
+                       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] );
+                                               }
+                                       }
                                }
                        }
 
-                       if ( $used ) {
-                               $deps[] = new FileDependency( $fileName );
+                       # Allow extensions an opportunity to adjust the data for this
+                       # fallback
+                       wfRunHooks( 'LocalisationCacheRecacheFallback', array( $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] );
+                                       }
+                               }
                        }
                }
 
-               # Merge core data into extension data
-               foreach ( $coreData as $key => $item ) {
-                       $this->mergeItem( $key, $allData[$key], $item );
-               }
-               wfProfileOut( __METHOD__ . '-extensions' );
+               wfProfileOut( __METHOD__ . '-fallbacks' );
 
                # Add cache dependencies for any referenced globals
                $deps['wgExtensionMessagesFiles'] = new GlobalDependency( 'wgExtensionMessagesFiles' );
                $deps['wgMessagesDirs'] = new GlobalDependency( 'wgMessagesDirs' );
-               $deps['version'] = new ConstantDependency( 'MW_LC_VERSION' );
+               $deps['version'] = new ConstantDependency( 'LocalisationCache::VERSION' );
 
                # Add dependencies to the cache entry
                $allData['deps'] = $deps;
@@ -983,7 +1017,7 @@ class LocalisationCache {
                # HACK: If using a null (i.e. disabled) storage backend, we
                # can't write to the MessageBlobStore either
                if ( $purgeBlobs && !$this->store instanceof LCStoreNull ) {
-                       MessageBlobStore::clear();
+                       MessageBlobStore::getInstance()->clear();
                }
 
                wfProfileOut( __METHOD__ );
@@ -1097,56 +1131,6 @@ interface LCStore {
        function set( $key, $value );
 }
 
-/**
- * LCStore implementation which uses PHP accelerator to store data.
- * This will work if one of XCache, WinCache or APC cacher is configured.
- * (See ObjectCache.php)
- */
-class LCStoreAccel implements LCStore {
-       private $currentLang;
-       private $keys;
-
-       public function __construct() {
-               $this->cache = wfGetCache( CACHE_ACCEL );
-       }
-
-       public function get( $code, $key ) {
-               $k = wfMemcKey( 'l10n', $code, 'k', $key );
-               $r = $this->cache->get( $k );
-
-               return $r === false ? null : $r;
-       }
-
-       public function startWrite( $code ) {
-               $k = wfMemcKey( 'l10n', $code, 'l' );
-               $keys = $this->cache->get( $k );
-               if ( $keys ) {
-                       foreach ( $keys as $k ) {
-                               $this->cache->delete( $k );
-                       }
-               }
-               $this->currentLang = $code;
-               $this->keys = array();
-       }
-
-       public function finishWrite() {
-               if ( $this->currentLang ) {
-                       $k = wfMemcKey( 'l10n', $this->currentLang, 'l' );
-                       $this->cache->set( $k, array_keys( $this->keys ) );
-               }
-               $this->currentLang = null;
-               $this->keys = array();
-       }
-
-       public function set( $key, $value ) {
-               if ( $this->currentLang ) {
-                       $k = wfMemcKey( 'l10n', $this->currentLang, 'k', $key );
-                       $this->keys[$k] = true;
-                       $this->cache->set( $k, $value );
-               }
-       }
-}
-
 /**
  * LCStore implementation which uses the standard DB functions to store data.
  * This will work on any MediaWiki installation.
@@ -1157,7 +1141,7 @@ class LCStoreDB implements LCStore {
 
        /** @var DatabaseBase */
        private $dbw;
-       /** @var Array */
+       /** @var array */
        private $batch = array();
 
        private $readOnly = false;
index a22d802..95e3af7 100644 (file)
@@ -57,7 +57,7 @@ class MapCacheLRU {
         * @return void
         */
        public function set( $key, $value ) {
-               if ( isset( $this->cache[$key] ) ) {
+               if ( array_key_exists( $key, $this->cache ) ) {
                        $this->ping( $key ); // push to top
                } elseif ( count( $this->cache ) >= $this->maxCacheKeys ) {
                        reset( $this->cache );
@@ -74,7 +74,7 @@ class MapCacheLRU {
         * @return bool
         */
        public function has( $key ) {
-               return isset( $this->cache[$key] );
+               return array_key_exists( $key, $this->cache );
        }
 
        /**
@@ -86,7 +86,7 @@ class MapCacheLRU {
         * @return mixed
         */
        public function get( $key ) {
-               if ( isset( $this->cache[$key] ) ) {
+               if ( array_key_exists( $key, $this->cache ) ) {
                        $this->ping( $key ); // push to top
                        return $this->cache[$key];
                } else {
index e5afd21..1ef7cc5 100644 (file)
@@ -573,7 +573,7 @@ class MessageCache {
 
                // Update the message in the message blob store
                global $wgContLang;
-               MessageBlobStore::updateMessage( $wgContLang->lcfirst( $msg ) );
+               MessageBlobStore::getInstance()->updateMessage( $wgContLang->lcfirst( $msg ) );
 
                wfRunHooks( 'MessageCacheReplace', array( $title, $text ) );
 
@@ -699,9 +699,9 @@ class MessageCache {
         *   - If boolean and false, create object from the current users language
         *   - If boolean and true, create object from the wikis content language
         *   - If language object, use it as given
-        * @param bool $isFullKey specifies whether $key is a two part key "msg/lang".
+        * @param bool $isFullKey Specifies whether $key is a two part key "msg/lang".
         *
-        * @throws MWException when given an invalid key
+        * @throws MWException When given an invalid key
         * @return string|bool False if the message doesn't exist, otherwise the
         *   message (which can be empty)
         */
diff --git a/includes/cache/bloom/BloomCache.php b/includes/cache/bloom/BloomCache.php
new file mode 100644 (file)
index 0000000..236db95
--- /dev/null
@@ -0,0 +1,323 @@
+<?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
+ */
+
+/**
+ * Persistent bloom filter used to avoid expensive lookups
+ *
+ * @since 1.24
+ */
+abstract class BloomCache {
+       /** @var string Unique ID for key namespacing */
+       protected $cacheID;
+
+       /** @var array Map of (id => BloomCache) */
+       protected static $instances = array();
+
+       /**
+        * @param string $id
+        * @return BloomCache
+        */
+       final public static function get( $id ) {
+               global $wgBloomFilterStores;
+
+               if ( !isset( self::$instances[$id] ) ) {
+                       if ( isset( $wgBloomFilterStores[$id] ) ) {
+                               $class = $wgBloomFilterStores[$id]['class'];
+                               self::$instances[$id] = new $class( $wgBloomFilterStores[$id] );
+                       } else {
+                               wfDebug( "No bloom filter store '$id'; using EmptyBloomCache." );
+                               return new EmptyBloomCache( array() );
+                       }
+               }
+
+               return self::$instances[$id];
+       }
+
+       /**
+        * Create a new bloom cache instance from configuration.
+        * This should only be called from within BloomCache.
+        *
+        * @param array $config Parameters include:
+        *   - cacheID : Prefix to all bloom filter names that is unique to this cache.
+        *               It should only consist of alphanumberic, '-', and '_' characters.
+        *               This ID is what avoids collisions if multiple logical caches
+        *               use the same storage system, so this should be set carefully.
+        */
+       public function __construct( array $config ) {
+               $this->cacheID = $config['cacheId'];
+               if ( !preg_match( '!^[a-zA-Z0-9-_]{1,32}$!', $this->cacheID ) ) {
+                       throw new MWException( "Cache ID '{$this->cacheID}' is invalid." );
+               }
+       }
+
+       /**
+        * Check if a member is set in the bloom filter
+        *
+        * A member being set means that it *might* have been added.
+        * A member not being set means it *could not* have been added.
+        *
+        * This abstracts over isHit() to deal with filter updates and readiness.
+        * A class must exist with the name BloomFilter<type> and a static public
+        * mergeAndCheck() method. The later takes the following arguments:
+        *              (BloomCache $bcache, $domain, $virtualKey, array $status)
+        * The method should return a bool indicating whether to use the filter.
+        *
+        * The 'shared' bloom key must be used for any updates and will be used
+        * for the membership check if the method returns true. Since the key is shared,
+        * the method should never use delete(). The filter cannot be used in cases where
+        * membership in the filter needs to be taken away. In such cases, code *cannot*
+        * use this method - instead, it can directly use the other BloomCache methods
+        * to manage custom filters with their own keys (e.g. not 'shared').
+        *
+        * @param string $domain
+        * @param string $type
+        * @param string $member
+        * @return bool True if set, false if not (also returns true on error)
+        */
+       final public function check( $domain, $type, $member ) {
+               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+
+               if ( method_exists( "BloomFilter{$type}", 'mergeAndCheck' ) ) {
+                       try {
+                               $virtualKey = "$domain:$type";
+
+                               $status = $this->getStatus( $virtualKey );
+                               if ( $status == false ) {
+                                       wfDebug( "Could not query virtual bloom filter '$virtualKey'." );
+                                       return null;
+                               }
+
+                               $useFilter = call_user_func_array(
+                                       array( "BloomFilter{$type}", 'mergeAndCheck' ),
+                                       array( $this, $domain, $virtualKey, $status )
+                               );
+
+                               if ( $useFilter ) {
+                                       return ( $this->isHit( 'shared', "$virtualKey:$member" ) !== false );
+                               }
+                       } catch ( MWException $e ) {
+                               MWExceptionHandler::logException( $e );
+                               return true;
+                       }
+               }
+
+               return true;
+       }
+
+       /**
+        * Inform the bloom filter of a new member in order to keep it up to date
+        *
+        * @param string $domain
+        * @param string $type
+        * @param string|array $members
+        * @return bool Success
+        */
+       final public function insert( $domain, $type, $members ) {
+               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+
+               if ( method_exists( "BloomFilter{$type}", 'mergeAndCheck' ) ) {
+                       try {
+                               $virtualKey = "$domain:$type";
+                               $prefixedMembers = array();
+                               foreach ( (array)$members as $member ) {
+                                       $prefixedMembers[] = "$virtualKey:$member";
+                               }
+
+                               return $this->add( 'shared', $prefixedMembers );
+                       } catch ( MWException $e ) {
+                               MWExceptionHandler::logException( $e );
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+
+       /**
+        * Create a new bloom filter at $key (if one does not exist yet)
+        *
+        * @param string $key
+        * @param integer $size Bit length [default: 1000000]
+        * @param float $precision [default: .001]
+        * @return bool Success
+        */
+       final public function init( $key, $size = 1000000, $precision = .001 ) {
+               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+
+               return $this->doInit( "{$this->cacheID}:$key", $size, min( .1, $precision ) );
+       }
+
+       /**
+        * Add a member to the bloom filter at $key
+        *
+        * @param string $key
+        * @param string|array $members
+        * @return bool Success
+        */
+       final public function add( $key, $members ) {
+               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+
+               return $this->doAdd( "{$this->cacheID}:$key", (array)$members );
+       }
+
+       /**
+        * Check if a member is set in the bloom filter.
+        *
+        * A member being set means that it *might* have been added.
+        * A member not being set means it *could not* have been added.
+        *
+        * If this returns true, then the caller usually should do the
+        * expensive check (whatever that may be). It can be avoided otherwise.
+        *
+        * @param string $key
+        * @param string $member
+        * @return bool|null True if set, false if not, null on error
+        */
+       final public function isHit( $key, $member ) {
+               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+
+               return $this->doIsHit( "{$this->cacheID}:$key", $member );
+       }
+
+       /**
+        * Destroy a bloom filter at $key
+        *
+        * @param string $key
+        * @return bool Success
+        */
+       final public function delete( $key ) {
+               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+
+               return $this->doDelete( "{$this->cacheID}:$key" );
+       }
+
+       /**
+        * Set the status map of the virtual bloom filter at $key
+        *
+        * @param string $virtualKey
+        * @param array $values Map including some of (lastID, asOfTime, epoch)
+        * @return bool Success
+        */
+       final public function setStatus( $virtualKey, array $values ) {
+               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+
+               return $this->doSetStatus( "{$this->cacheID}:$virtualKey", $values );
+       }
+
+       /**
+        * Get the status map of the virtual bloom filter at $key
+        *
+        * The map includes:
+        *   - lastID    : the highest ID of the items merged in
+        *   - asOfTime  : UNIX timestamp that the filter is up-to-date as of
+        *   - epoch     : UNIX timestamp that filter started being populated
+        * Unset fields will have a null value.
+        *
+        * @param string $virtualKey
+        * @return array|bool False on failure
+        */
+       final public function getStatus( $virtualKey ) {
+               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+
+               return $this->doGetStatus( "{$this->cacheID}:$virtualKey" );
+       }
+
+       /**
+        * Get an exclusive lock on a filter for updates
+        *
+        * @param string $virtualKey
+        * @return ScopedCallback|ScopedLock|null Returns null if acquisition failed
+        */
+       public function getScopedLock( $virtualKey ) {
+               return null;
+       }
+
+       /**
+        * @param string $key
+        * @param integer $size Bit length
+        * @param float $precision
+        * @return bool Success
+        */
+       abstract protected function doInit( $key, $size, $precision );
+
+       /**
+        * @param string $key
+        * @param array $members
+        * @return bool Success
+        */
+       abstract protected function doAdd( $key, array $members );
+
+       /**
+        * @param string $key
+        * @param string $member
+        * @return bool|null
+        */
+       abstract protected function doIsHit( $key, $member );
+
+       /**
+        * @param string $key
+        * @return bool Success
+        */
+       abstract protected function doDelete( $key );
+
+       /**
+        * @param string $virtualKey
+        * @param array $values
+        * @return bool Success
+        */
+       abstract protected function doSetStatus( $virtualKey, array $values );
+
+       /**
+        * @param string $key
+        * @return array|bool
+        */
+       abstract protected function doGetStatus( $key );
+}
+
+class EmptyBloomCache extends BloomCache {
+       public function __construct( array $config ) {
+               parent::__construct( array( 'cacheId' => 'none' ) );
+       }
+
+       protected function doInit( $key, $size, $precision ) {
+               return true;
+       }
+
+       protected function doAdd( $key, array $members ) {
+               return true;
+       }
+
+       protected function doIsHit( $key, $member ) {
+               return true;
+       }
+
+       protected function doDelete( $key ) {
+               return true;
+       }
+
+       protected function doSetStatus( $virtualKey, array $values ) {
+               return true;
+       }
+
+       protected function doGetStatus( $virtualKey ) {
+               return array( 'lastID' => null, 'asOfTime' => null, 'epoch' => null ) ;
+       }
+}
diff --git a/includes/cache/bloom/BloomCacheRedis.php b/includes/cache/bloom/BloomCacheRedis.php
new file mode 100644 (file)
index 0000000..7bafc99
--- /dev/null
@@ -0,0 +1,370 @@
+<?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
+ */
+
+/**
+ * Bloom filter implented using Redis
+ *
+ * The Redis server must be >= 2.6 and should have volatile-lru or volatile-ttl
+ * if there is any eviction policy. It should not be allkeys-* in any case. Also,
+ * this can be used in a simple master/slave setup or with Redis Sentinal preferably.
+ *
+ * Some bits are based on https://github.com/ErikDubbelboer/redis-lua-scaling-bloom-filter
+ * but are simplified to use a single filter instead of up to 32 filters.
+ *
+ * @since 1.24
+ */
+class BloomCacheRedis extends BloomCache {
+       /** @var RedisConnectionPool */
+       protected $redisPool;
+       /** @var RedisLockManager */
+       protected $lockMgr;
+       /** @var array */
+       protected $servers;
+       /** @var integer Federate each filter into this many redis bitfield objects */
+       protected $segments = 128;
+
+       /**
+        * @params include:
+        *   - redisServers : list of servers (address:<port>) (the first is the master)
+        *   - redisConf    : additional redis configuration
+        *
+        * @param array $config
+        */
+       public function __construct( array $config ) {
+               parent::__construct( $config );
+
+               $redisConf = $config['redisConfig'];
+               $redisConf['serializer'] = 'none'; // manage that in this class
+               $this->redisPool = RedisConnectionPool::singleton( $redisConf );
+               $this->servers = $config['redisServers'];
+               $this->lockMgr = new RedisLockManager( array(
+                       'lockServers'  => array( 'srv1' => $this->servers[0] ),
+                       'srvsByBucket' => array( 0 => array( 'srv1' ) ),
+                       'redisConfig'  => $config['redisConfig']
+               ) );
+       }
+
+       protected function doInit( $key, $size, $precision ) {
+               $conn = $this->getConnection( 'master' );
+               if ( !$conn ) {
+                       return false;
+               }
+
+               // 80000000 items at p = .001 take up 500MB and fit into one value.
+               // Do not hit the 512MB redis value limit by reducing the demands.
+               $size = min( $size, 80000000 * $this->segments );
+               $precision = max( round( $precision, 3 ), .001 );
+               $epoch = microtime( true );
+
+               static $script =
+<<<LUA
+               local kMetadata, kData = unpack(KEYS)
+               local aEntries, aPrec, aEpoch = unpack(ARGV)
+               if redis.call('EXISTS',kMetadata) == 0 or redis.call('EXISTS',kData) == 0 then
+                       redis.call('DEL',kMetadata)
+                       redis.call('HSET',kMetadata,'entries',aEntries)
+                       redis.call('HSET',kMetadata,'precision',aPrec)
+                       redis.call('HSET',kMetadata,'epoch',aEpoch)
+                       redis.call('SET',kData,'')
+                       return 1
+               end
+               return 0
+LUA;
+
+               $res = false;
+               try {
+                       $conn->script( 'load', $script );
+                       $conn->multi( Redis::MULTI );
+                       for ( $i = 0; $i < $this->segments; ++$i ) {
+                               $res = $conn->luaEval( $script,
+                                       array(
+                                               "$key:$i:bloom-metadata", # KEYS[1]
+                                               "$key:$i:bloom-data", # KEYS[2]
+                                               ceil( $size / $this->segments ), # ARGV[1]
+                                               $precision, # ARGV[2]
+                                               $epoch # ARGV[3]
+                                       ),
+                                       2 # number of first argument(s) that are keys
+                               );
+                       }
+                       $results = $conn->exec();
+                       $res = $results && !in_array( false, $results, true );
+               } catch ( RedisException $e ) {
+                       $this->handleException( $conn, $e );
+               }
+
+               return ( $res !== false );
+       }
+
+       protected function doAdd( $key, array $members ) {
+               $conn = $this->getConnection( 'master' );
+               if ( !$conn ) {
+                       return false;
+               }
+
+               static $script =
+<<<LUA
+               local kMetadata, kData = unpack(KEYS)
+               local aMember = unpack(ARGV)
+
+               -- Check if the filter was initialized
+               if redis.call('EXISTS',kMetadata) == 0 or redis.call('EXISTS',kData) == 0 then
+                       return false
+               end
+
+               -- Initial expected entries and desired precision
+               local entries = 1*redis.call('HGET',kMetadata,'entries')
+               local precision = 1*redis.call('HGET',kMetadata,'precision')
+               local hash = redis.sha1hex(aMember)
+
+               -- Based on the math from: http://en.wikipedia.org/wiki/Bloom_filter#Probability_of_false_positives
+               -- 0.480453013 = ln(2)^2
+               local bits = math.ceil((entries * math.log(precision)) / -0.480453013)
+
+               -- 0.693147180 = ln(2)
+               local k = math.floor(0.693147180 * bits / entries)
+
+               -- This uses a variation on:
+               -- 'Less Hashing, Same Performance: Building a Better Bloom Filter'
+               -- http://www.eecs.harvard.edu/~kirsch/pubs/bbbf/esa06.pdf
+               local h = { }
+               h[0] = tonumber(string.sub(hash, 1, 8 ), 16)
+               h[1] = tonumber(string.sub(hash, 9, 16), 16)
+               h[2] = tonumber(string.sub(hash, 17, 24), 16)
+               h[3] = tonumber(string.sub(hash, 25, 32), 16)
+
+               for i=1, k do
+                       local pos = (h[i % 2] + i * h[2 + (((i + (i % 2)) % 4) / 2)]) % bits
+                       redis.call('SETBIT', kData, pos, 1)
+               end
+
+               return 1
+LUA;
+
+               $res = false;
+               try {
+                       $conn->script( 'load', $script );
+                       $conn->multi( Redis::PIPELINE );
+                       foreach ( $members as $member ) {
+                               $i = $this->getSegment( $member );
+                               $conn->luaEval( $script,
+                                       array(
+                                               "$key:$i:bloom-metadata", # KEYS[1],
+                                               "$key:$i:bloom-data", # KEYS[2]
+                                               $member # ARGV[1]
+                                       ),
+                                       2 # number of first argument(s) that are keys
+                               );
+                       }
+                       $results = $conn->exec();
+                       $res = $results && !in_array( false, $results, true );
+               } catch ( RedisException $e ) {
+                       $this->handleException( $conn, $e );
+               }
+
+               if ( $res === false ) {
+                       wfDebug( "Could not add to the '$key' bloom filter; it may be missing." );
+               }
+
+               return ( $res !== false );
+       }
+
+       protected function doSetStatus( $virtualKey, array $values ) {
+               $conn = $this->getConnection( 'master' );
+               if ( !$conn ) {
+                       return null;
+               }
+
+               $res = false;
+               try {
+                       $res = $conn->hMSet( "$virtualKey:filter-metadata", $values );
+               } catch ( RedisException $e ) {
+                       $this->handleException( $conn, $e );
+               }
+
+               return ( $res !== false );
+       }
+
+       protected function doGetStatus( $virtualKey ) {
+               $conn = $this->getConnection( 'slave' );
+               if ( !$conn ) {
+                       return false;
+               }
+
+               $res = false;
+               try {
+                       $res = $conn->hGetAll( "$virtualKey:filter-metadata" );
+               } catch ( RedisException $e ) {
+                       $this->handleException( $conn, $e );
+               }
+
+               if ( is_array( $res ) ) {
+                       $res['lastID'] = isset( $res['lastID'] ) ? $res['lastID'] : null;
+                       $res['asOfTime'] = isset( $res['asOfTime'] ) ? $res['asOfTime'] : null;
+                       $res['epoch'] = isset( $res['epoch'] ) ? $res['epoch'] : null;
+               }
+
+               return $res;
+       }
+
+       protected function doIsHit( $key, $member ) {
+               $conn = $this->getConnection( 'slave' );
+               if ( !$conn ) {
+                       return null;
+               }
+
+               static $script =
+<<<LUA
+               local kMetadata, kData = unpack(KEYS)
+               local aMember = unpack(ARGV)
+
+               -- Check if the filter was initialized
+               if redis.call('EXISTS',kMetadata) == 0 or redis.call('EXISTS',kData) == 0 then
+                       return false
+               end
+
+               -- Initial expected entries and desired precision.
+               -- This determines the size of the first and subsequent filters.
+               local entries = redis.call('HGET',kMetadata,'entries')
+               local precision = redis.call('HGET',kMetadata,'precision')
+               local hash = redis.sha1hex(aMember)
+
+               -- This uses a variation on:
+               -- 'Less Hashing, Same Performance: Building a Better Bloom Filter'
+               -- http://www.eecs.harvard.edu/~kirsch/pubs/bbbf/esa06.pdf
+               local h = { }
+               h[0] = tonumber(string.sub(hash, 1, 8 ), 16)
+               h[1] = tonumber(string.sub(hash, 9, 16), 16)
+               h[2] = tonumber(string.sub(hash, 17, 24), 16)
+               h[3] = tonumber(string.sub(hash, 25, 32), 16)
+
+               -- 0.480453013 = ln(2)^2
+               local bits = math.ceil((entries * math.log(precision)) / -0.480453013)
+
+               -- 0.693147180 = ln(2)
+               local k = math.floor(0.693147180 * bits / entries)
+
+               local found = 1
+               for i=1, k do
+                       local pos = (h[i % 2] + i * h[2 + (((i + (i % 2)) % 4) / 2)]) % bits
+                       if redis.call('GETBIT', kData, pos) == 0 then
+                               found = 0
+                               break
+                       end
+               end
+
+               return found
+LUA;
+
+               $res = null;
+               try {
+                       $i = $this->getSegment( $member );
+                       $res = $conn->luaEval( $script,
+                               array(
+                                       "$key:$i:bloom-metadata", # KEYS[1],
+                                       "$key:$i:bloom-data", # KEYS[2]
+                                       $member # ARGV[1]
+                               ),
+                               2 # number of first argument(s) that are keys
+                       );
+               } catch ( RedisException $e ) {
+                       $this->handleException( $conn, $e );
+               }
+
+               return is_int( $res ) ? (bool)$res : null;
+       }
+
+       protected function doDelete( $key ) {
+               $conn = $this->getConnection( 'master' );
+               if ( !$conn ) {
+                       return false;
+               }
+
+               $res = false;
+               try {
+                       $keys = array();
+                       for ( $i = 0; $i < $this->segments; ++$i ) {
+                               $keys[] = "$key:$i:bloom-metadata";
+                               $keys[] = "$key:$i:bloom-data";
+                       }
+                       $res = $conn->delete( $keys );
+               } catch ( RedisException $e ) {
+                       $this->handleException( $conn, $e );
+               }
+
+               return ( $res !== false );
+       }
+
+       public function getScopedLock( $virtualKey ) {
+               $status = Status::newGood();
+               return ScopedLock::factory( $this->lockMgr,
+                       array( $virtualKey ), LockManager::LOCK_EX, $status );
+       }
+
+       /**
+        * @param string $member
+        * @return integer
+        */
+       protected function getSegment( $member ) {
+               return hexdec( substr( md5( $member ), 0, 2 ) ) % $this->segments;
+       }
+
+       /**
+        * $param string $to (master/slave)
+        * @return RedisConnRef|bool Returns false on failure
+        */
+       protected function getConnection( $to ) {
+               if ( $to === 'master' ) {
+                       $conn = $this->redisPool->getConnection( $this->servers[0] );
+               } else {
+                       static $lastServer = null;
+
+                       $conn = false;
+                       if ( $lastServer ) {
+                               $conn = $this->redisPool->getConnection( $lastServer );
+                               if ( $conn ) {
+                                       return $conn; // reuse connection
+                               }
+                       }
+                       $servers = $this->servers;
+                       $attempts = min( 3, count( $servers ) );
+                       for ( $i = 1; $i <= $attempts; ++$i ) {
+                               $index = mt_rand( 0, count( $servers ) - 1 );
+                               $conn = $this->redisPool->getConnection( $servers[$index] );
+                               if ( $conn ) {
+                                       $lastServer = $servers[$index];
+                                       return $conn;
+                               }
+                               unset( $servers[$index] ); // skip next time
+                       }
+               }
+
+               return $conn;
+       }
+
+       /**
+        * @param RedisConnRef $conn
+        * @param Exception $e
+        */
+       protected function handleException( RedisConnRef $conn, $e ) {
+               $this->redisPool->handleError( $conn, $e );
+       }
+}
diff --git a/includes/cache/bloom/BloomFilters.php b/includes/cache/bloom/BloomFilters.php
new file mode 100644 (file)
index 0000000..9b710d7
--- /dev/null
@@ -0,0 +1,79 @@
+<?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
+ */
+
+/**
+ * @since 1.24
+ */
+class BloomFilterTitleHasLogs {
+       public static function mergeAndCheck(
+               BloomCache $bcache, $domain, $virtualKey, array $status
+       ) {
+               $age = microtime( true ) - $status['asOfTime']; // seconds
+               $scopedLock = ( mt_rand( 1, (int)pow( 3, max( 0, 5 - $age ) ) ) == 1 )
+                       ? $bcache->getScopedLock( $virtualKey )
+                       : false;
+
+               if ( $scopedLock ) {
+                       $updates = self::merge( $bcache, $domain, $virtualKey, $status );
+                       if ( isset( $updates['asOfTime'] ) ) {
+                               $age = ( microtime( true ) - $updates['asOfTime'] );
+                       }
+               }
+
+               return ( $age < 30 );
+       }
+
+       public static function merge(
+               BloomCache $bcache, $domain, $virtualKey, array $status
+       ) {
+               $limit = 1000;
+               $dbr = wfGetDB( DB_SLAVE, array(), $domain );
+               $res = $dbr->select( 'logging',
+                       array( 'log_namespace', 'log_title', 'log_id', 'log_timestamp' ),
+                       array( 'log_id > ' . $dbr->addQuotes( (int)$status['lastID'] ) ),
+                       __METHOD__,
+                       array( 'ORDER BY' => 'log_id', 'LIMIT' => $limit )
+               );
+
+               $updates = array();
+               if ( $res->numRows() > 0 ) {
+                       $members = array();
+                       foreach ( $res as $row ) {
+                               $members[] = "$virtualKey:{$row->log_namespace}:{$row->log_title}";
+                       }
+                       $lastID = $row->log_id;
+                       $lastTime = $row->log_timestamp;
+                       if ( !$bcache->add( 'shared', $members ) ) {
+                               return false;
+                       }
+                       $updates['lastID'] = $lastID;
+                       $updates['asOfTime'] = wfTimestamp( TS_UNIX, $lastTime );
+               } else {
+                       $updates['asOfTime'] = microtime( true );
+               }
+
+               $updates['epoch'] = $status['epoch'] ?: microtime( true );
+
+               $bcache->setStatus( $virtualKey, $updates );
+
+               return $updates;
+       }
+}
diff --git a/includes/changes/ChangesFeed.php b/includes/changes/ChangesFeed.php
new file mode 100644 (file)
index 0000000..2d3b919
--- /dev/null
@@ -0,0 +1,240 @@
+<?php
+/**
+ * Feed for list of changes.
+ *
+ * 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
+ */
+
+/**
+ * Feed to Special:RecentChanges and Special:RecentChangesLiked
+ *
+ * @ingroup Feed
+ */
+class ChangesFeed {
+       public $format, $type, $titleMsg, $descMsg;
+
+       /**
+        * Constructor
+        *
+        * @param string $format Feed's format (either 'rss' or 'atom')
+        * @param string $type Type of feed (for cache keys)
+        */
+       public function __construct( $format, $type ) {
+               $this->format = $format;
+               $this->type = $type;
+       }
+
+       /**
+        * Get a ChannelFeed subclass object to use
+        *
+        * @param string $title Feed's title
+        * @param string $description Feed's description
+        * @param string $url Url of origin page
+        * @return ChannelFeed|bool ChannelFeed subclass or false on failure
+        */
+       public function getFeedObject( $title, $description, $url ) {
+               global $wgSitename, $wgLanguageCode, $wgFeedClasses;
+
+               if ( !isset( $wgFeedClasses[$this->format] ) ) {
+                       return false;
+               }
+
+               if ( !array_key_exists( $this->format, $wgFeedClasses ) ) {
+                       // falling back to atom
+                       $this->format = 'atom';
+               }
+
+               $feedTitle = "$wgSitename  - {$title} [$wgLanguageCode]";
+               return new $wgFeedClasses[$this->format](
+                       $feedTitle, htmlspecialchars( $description ), $url );
+       }
+
+       /**
+        * Generates feed's content
+        *
+        * @param ChannelFeed $feed ChannelFeed subclass object (generally the one returned
+        *   by getFeedObject())
+        * @param ResultWrapper $rows ResultWrapper object with rows in recentchanges table
+        * @param int $lastmod Timestamp of the last item in the recentchanges table (only
+        *   used for the cache key)
+        * @param FormOptions $opts As in SpecialRecentChanges::getDefaultOptions()
+        * @return null|bool True or null
+        */
+       public function execute( $feed, $rows, $lastmod, $opts ) {
+               global $wgLang, $wgRenderHashAppend;
+
+               if ( !FeedUtils::checkFeedOutput( $this->format ) ) {
+                       return null;
+               }
+
+               $optionsHash = md5( serialize( $opts->getAllValues() ) ) . $wgRenderHashAppend;
+               $timekey = wfMemcKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash, 'timestamp' );
+               $key = wfMemcKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash );
+
+               FeedUtils::checkPurge( $timekey, $key );
+
+               /**
+                * Bumping around loading up diffs can be pretty slow, so where
+                * possible we want to cache the feed output so the next visitor
+                * gets it quick too.
+                */
+               $cachedFeed = $this->loadFromCache( $lastmod, $timekey, $key );
+               if ( is_string( $cachedFeed ) ) {
+                       wfDebug( "RC: Outputting cached feed\n" );
+                       $feed->httpHeaders();
+                       echo $cachedFeed;
+               } else {
+                       wfDebug( "RC: rendering new feed and caching it\n" );
+                       ob_start();
+                       self::generateFeed( $rows, $feed );
+                       $cachedFeed = ob_get_contents();
+                       ob_end_flush();
+                       $this->saveToCache( $cachedFeed, $timekey, $key );
+               }
+               return true;
+       }
+
+       /**
+        * Save to feed result to $messageMemc
+        *
+        * @param string $feed Feed's content
+        * @param string $timekey Memcached key of the last modification
+        * @param string $key Memcached key of the content
+        */
+       public function saveToCache( $feed, $timekey, $key ) {
+               global $messageMemc;
+               $expire = 3600 * 24; # One day
+               $messageMemc->set( $key, $feed, $expire );
+               $messageMemc->set( $timekey, wfTimestamp( TS_MW ), $expire );
+       }
+
+       /**
+        * Try to load the feed result from $messageMemc
+        *
+        * @param int $lastmod Timestamp of the last item in the recentchanges table
+        * @param string $timekey Memcached key of the last modification
+        * @param string $key Memcached key of the content
+        * @return string|bool Feed's content on cache hit or false on cache miss
+        */
+       public function loadFromCache( $lastmod, $timekey, $key ) {
+               global $wgFeedCacheTimeout, $wgOut, $messageMemc;
+
+               $feedLastmod = $messageMemc->get( $timekey );
+
+               if ( ( $wgFeedCacheTimeout > 0 ) && $feedLastmod ) {
+                       /**
+                        * If the cached feed was rendered very recently, we may
+                        * go ahead and use it even if there have been edits made
+                        * since it was rendered. This keeps a swarm of requests
+                        * from being too bad on a super-frequently edited wiki.
+                        */
+
+                       $feedAge = time() - wfTimestamp( TS_UNIX, $feedLastmod );
+                       $feedLastmodUnix = wfTimestamp( TS_UNIX, $feedLastmod );
+                       $lastmodUnix = wfTimestamp( TS_UNIX, $lastmod );
+
+                       if ( $feedAge < $wgFeedCacheTimeout || $feedLastmodUnix > $lastmodUnix ) {
+                               wfDebug( "RC: loading feed from cache ($key; $feedLastmod; $lastmod)...\n" );
+                               if ( $feedLastmodUnix < $lastmodUnix ) {
+                                       $wgOut->setLastModified( $feedLastmod ); // bug 21916
+                               }
+                               return $messageMemc->get( $key );
+                       } else {
+                               wfDebug( "RC: cached feed timestamp check failed ($feedLastmod; $lastmod)\n" );
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * Generate the feed items given a row from the database, printing the feed.
+        * @param object $rows DatabaseBase resource with recentchanges rows
+        * @param Feed $feed
+        */
+       public static function generateFeed( $rows, &$feed ) {
+               wfProfileIn( __METHOD__ );
+               $items = self::buildItems( $rows );
+               $feed->outHeader();
+               foreach ( $items as $item ) {
+                       $feed->outItem( $item );
+               }
+               $feed->outFooter();
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Generate the feed items given a row from the database.
+        * @param object $rows DatabaseBase resource with recentchanges rows
+        * @return array
+        */
+       public static function buildItems( $rows ) {
+               wfProfileIn( __METHOD__ );
+               $items = array();
+
+               # Merge adjacent edits by one user
+               $sorted = array();
+               $n = 0;
+               foreach ( $rows as $obj ) {
+                       if ( $n > 0 &&
+                               $obj->rc_type == RC_EDIT &&
+                               $obj->rc_namespace >= 0 &&
+                               $obj->rc_cur_id == $sorted[$n - 1]->rc_cur_id &&
+                               $obj->rc_user_text == $sorted[$n - 1]->rc_user_text ) {
+                               $sorted[$n - 1]->rc_last_oldid = $obj->rc_last_oldid;
+                       } else {
+                               $sorted[$n] = $obj;
+                               $n++;
+                       }
+               }
+
+               foreach ( $sorted as $obj ) {
+                       $title = Title::makeTitle( $obj->rc_namespace, $obj->rc_title );
+                       $talkpage = MWNamespace::canTalk( $obj->rc_namespace )
+                               ? $title->getTalkPage()->getFullURL()
+                               : '';
+
+                       // Skip items with deleted content (avoids partially complete/inconsistent output)
+                       if ( $obj->rc_deleted ) {
+                               continue;
+                       }
+
+                       if ( $obj->rc_this_oldid ) {
+                               $url = $title->getFullURL( array(
+                                       'diff' => $obj->rc_this_oldid,
+                                       'oldid' => $obj->rc_last_oldid,
+                               ) );
+                       } else {
+                               // log entry or something like that.
+                               $url = $title->getFullURL();
+                       }
+
+                       $items[] = new FeedItem(
+                               $title->getPrefixedText(),
+                               FeedUtils::formatDiff( $obj ),
+                               $url,
+                               $obj->rc_timestamp,
+                               ( $obj->rc_deleted & Revision::DELETED_USER )
+                                       ? wfMessage( 'rev-deleted-user' )->escaped() : $obj->rc_user_text,
+                               $talkpage
+                       );
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $items;
+       }
+}
index cd43f82..03d1289 100644 (file)
@@ -36,6 +36,9 @@ class ChangesList extends ContextSource {
        protected $rclistOpen;
        protected $rcMoveIndex;
 
+       /** @var MapCacheLRU */
+       protected $watchingCache;
+
        /**
         * Changeslist constructor
         *
@@ -50,6 +53,7 @@ class ChangesList extends ContextSource {
                        $this->skin = $obj;
                }
                $this->preCacheMessages();
+               $this->watchingCache = new MapCacheLRU( 50 );
        }
 
        /**
@@ -110,9 +114,8 @@ class ChangesList extends ContextSource {
         * @return string
         */
        public function recentChangesFlags( $flags, $nothing = '&#160;' ) {
-               global $wgRecentChangesFlags;
                $f = '';
-               foreach ( array_keys( $wgRecentChangesFlags ) as $flag ) {
+               foreach ( array_keys( $this->getConfig()->get( 'RecentChangesFlags' ) ) as $flag ) {
                        $f .= isset( $flags[$flag] ) && $flags[$flag]
                                ? self::flag( $flag )
                                : $nothing;
@@ -188,8 +191,6 @@ class ChangesList extends ContextSource {
         * @return string
         */
        public static function showCharacterDifference( $old, $new, IContextSource $context = null ) {
-               global $wgRCChangedSizeThreshold, $wgMiserMode;
-
                if ( !$context ) {
                        $context = RequestContext::getMain();
                }
@@ -199,10 +200,11 @@ class ChangesList extends ContextSource {
                $szdiff = $new - $old;
 
                $lang = $context->getLanguage();
+               $config = $context->getConfig();
                $code = $lang->getCode();
                static $fastCharDiff = array();
                if ( !isset( $fastCharDiff[$code] ) ) {
-                       $fastCharDiff[$code] = $wgMiserMode || $context->msg( 'rc-change-size' )->plain() === '$1';
+                       $fastCharDiff[$code] = $config->get( 'MiserMode' ) || $context->msg( 'rc-change-size' )->plain() === '$1';
                }
 
                $formattedSize = $lang->formatNum( $szdiff );
@@ -211,7 +213,7 @@ class ChangesList extends ContextSource {
                        $formattedSize = $context->msg( 'rc-change-size', $formattedSize )->text();
                }
 
-               if ( abs( $szdiff ) > abs( $wgRCChangedSizeThreshold ) ) {
+               if ( abs( $szdiff ) > abs( $config->get( 'RCChangedSizeThreshold' ) ) ) {
                        $tag = 'strong';
                } else {
                        $tag = 'span';
@@ -438,8 +440,6 @@ class ChangesList extends ContextSource {
                } else {
                        return Linker::commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() );
                }
-
-               return '';
        }
 
        /**
@@ -462,14 +462,14 @@ class ChangesList extends ContextSource {
         * @return string
         */
        protected function numberofWatchingusers( $count ) {
-               static $cache = array();
+               $cache = $this->watchingCache;
                if ( $count > 0 ) {
-                       if ( !isset( $cache[$count] ) ) {
-                               $cache[$count] = $this->msg( 'number_of_watching_users_RCview' )
-                                       ->numParams( $count )->escaped();
+                       if ( !$cache->has( $count ) ) {
+                               $cache->set( $count, $this->msg( 'number_of_watching_users_RCview' )
+                                       ->numParams( $count )->escaped() );
                        }
 
-                       return $cache[$count];
+                       return $cache->get( $count );
                } else {
                        return '';
                }
index 0c073c6..4ab7729 100644 (file)
@@ -40,7 +40,7 @@ class EnhancedChangesList extends ChangesList {
                        // @todo: deprecate constructing with Skin
                        $context = $obj->getContext();
                } else {
-                       if ( ! $obj instanceof IContextSource ) {
+                       if ( !$obj instanceof IContextSource ) {
                                throw new MWException( 'EnhancedChangesList must be constructed with a '
                                        . 'context source or skin.' );
                        }
@@ -160,8 +160,6 @@ class EnhancedChangesList extends ChangesList {
         * @return string
         */
        protected function recentChangesBlockGroup( $block ) {
-               global $wgRCShowChangedSize;
-
                wfProfileIn( __METHOD__ );
 
                # Add the namespace and title of the block as part of the class
@@ -191,6 +189,7 @@ class EnhancedChangesList extends ChangesList {
                $namehidden = true;
                $allLogs = true;
                $oldid = '';
+               $RCShowChangedSize = $this->getConfig()->get( 'RCShowChangedSize' );
                foreach ( $block as $rcObj ) {
                        $oldid = $rcObj->mAttribs['rc_last_oldid'];
                        if ( $rcObj->mAttribs['rc_type'] == RC_NEW ) {
@@ -364,7 +363,7 @@ class EnhancedChangesList extends ChangesList {
                $r .= ' <span class="mw-changeslist-separator">. .</span> ';
 
                # Character difference (does not apply if only log items)
-               if ( $wgRCShowChangedSize && !$allLogs ) {
+               if ( $RCShowChangedSize && !$allLogs ) {
                        $last = 0;
                        $first = count( $block ) - 1;
                        # Some events (like logs) have an "empty" size, so we need to skip those...
@@ -442,7 +441,7 @@ class EnhancedChangesList extends ChangesList {
                        $r .= ' <span class="mw-changeslist-separator">. .</span> ';
 
                        # Character diff
-                       if ( $wgRCShowChangedSize ) {
+                       if ( $RCShowChangedSize ) {
                                $cd = $this->formatCharacterDifference( $rcObj );
                                if ( $cd !== '' ) {
                                        $r .= $cd . ' <span class="mw-changeslist-separator">. .</span> ';
@@ -474,50 +473,6 @@ class EnhancedChangesList extends ChangesList {
                return $r;
        }
 
-       /**
-        * Generate HTML for an arrow or placeholder graphic
-        * @param string $dir One of '', 'd', 'l', 'r'
-        * @param string $alt
-        * @param string $title
-        * @return string HTML "<img>" tag
-        */
-       protected function arrow( $dir, $alt = '', $title = '' ) {
-               global $wgStylePath;
-               $encUrl = htmlspecialchars( $wgStylePath . '/common/images/Arr_' . $dir . '.png' );
-               $encAlt = htmlspecialchars( $alt );
-               $encTitle = htmlspecialchars( $title );
-
-               return "<img src=\"$encUrl\" width=\"12\" height=\"12\" alt=\"$encAlt\" title=\"$encTitle\" />";
-       }
-
-       /**
-        * Generate HTML for a right- or left-facing arrow,
-        * depending on language direction.
-        * @return string HTML "<img>" tag
-        */
-       protected function sideArrow() {
-               $dir = $this->getLanguage()->isRTL() ? 'l' : 'r';
-
-               return $this->arrow( $dir, '+', $this->msg( 'rc-enhanced-expand' )->text() );
-       }
-
-       /**
-        * Generate HTML for a down-facing arrow
-        * depending on language direction.
-        * @return string HTML "<img>" tag
-        */
-       protected function downArrow() {
-               return $this->arrow( 'd', '-', $this->msg( 'rc-enhanced-hide' )->text() );
-       }
-
-       /**
-        * Generate HTML for a spacer image
-        * @return string HTML "<img>" tag
-        */
-       protected function spacerArrow() {
-               return $this->arrow( '', codepointToUtf8( 0xa0 ) ); // non-breaking space
-       }
-
        /**
         * Enhanced RC ungrouped line.
         *
@@ -525,8 +480,6 @@ class EnhancedChangesList extends ChangesList {
         * @return string A HTML formatted line (generated using $r)
         */
        protected function recentChangesBlockLine( $rcObj ) {
-               global $wgRCShowChangedSize;
-
                wfProfileIn( __METHOD__ );
                $query['curid'] = $rcObj->mAttribs['rc_cur_id'];
 
@@ -577,7 +530,7 @@ class EnhancedChangesList extends ChangesList {
                }
                $r .= ' <span class="mw-changeslist-separator">. .</span> ';
                # Character diff
-               if ( $wgRCShowChangedSize ) {
+               if ( $this->getConfig()->get( 'RCShowChangedSize' ) ) {
                        $cd = $this->formatCharacterDifference( $rcObj );
                        if ( $cd !== '' ) {
                                $r .= $cd . ' <span class="mw-changeslist-separator">. .</span> ';
index d590ff6..4eed926 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 class OldChangesList extends ChangesList {
+
        /**
         * Format a line using the old system (aka without any javascript).
         *
@@ -31,13 +32,8 @@ class OldChangesList extends ChangesList {
         * @return string|bool
         */
        public function recentChangesLine( &$rc, $watched = false, $linenumber = null ) {
-               global $wgRCShowChangedSize;
                wfProfileIn( __METHOD__ );
 
-               # Should patrol-related stuff be shown?
-               $unpatrolled = $this->showAsUnpatrolled( $rc );
-
-               $s = '';
                $classes = array();
                // use mw-line-even/mw-line-odd class only if linenumber is given (feature from bug 14468)
                if ( $linenumber ) {
@@ -53,20 +49,53 @@ class OldChangesList extends ChangesList {
                $classes[] = $watched && $rc->mAttribs['rc_timestamp'] >= $watched
                        ? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched';
 
+               $html = $this->formatChangeLine( $rc, $classes, $watched );
+
+               if ( $this->watchlist ) {
+                       $classes[] = Sanitizer::escapeClass( 'watchlist-' .
+                               $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title'] );
+               }
+
+               if ( !wfRunHooks( 'OldChangesListRecentChangesLine', array( &$this, &$html, $rc, &$classes ) ) ) {
+                       wfProfileOut( __METHOD__ );
+
+                       return false;
+               }
+
+               wfProfileOut( __METHOD__ );
+
+               $dateheader = ''; // $html now contains only <li>...</li>, for hooks' convenience.
+               $this->insertDateHeader( $dateheader, $rc->mAttribs['rc_timestamp'] );
+
+               return "$dateheader<li class=\"" . implode( ' ', $classes ) . "\">" . $html . "</li>\n";
+       }
+
+       /**
+        * @param RecentChange $rc
+        * @param string[] &$classes
+        * @param boolean $watched
+        *
+        * @return string
+        */
+       private function formatChangeLine( RecentChange $rc, array &$classes, $watched ) {
+               $html = '';
+
                if ( $rc->mAttribs['rc_log_type'] ) {
                        $logtitle = SpecialPage::getTitleFor( 'Log', $rc->mAttribs['rc_log_type'] );
-                       $this->insertLog( $s, $logtitle, $rc->mAttribs['rc_log_type'] );
+                       $this->insertLog( $html, $logtitle, $rc->mAttribs['rc_log_type'] );
                // Log entries (old format) or log targets, and special pages
                } elseif ( $rc->mAttribs['rc_namespace'] == NS_SPECIAL ) {
-                       list( $name, $subpage ) = SpecialPageFactory::resolveAlias( $rc->mAttribs['rc_title'] );
+                       list( $name, $htmlubpage ) = SpecialPageFactory::resolveAlias( $rc->mAttribs['rc_title'] );
                        if ( $name == 'Log' ) {
-                               $this->insertLog( $s, $rc->getTitle(), $subpage );
+                               $this->insertLog( $html, $rc->getTitle(), $htmlubpage );
                        }
                // Regular entries
                } else {
-                       $this->insertDiffHist( $s, $rc, $unpatrolled );
+                       $unpatrolled = $this->showAsUnpatrolled( $rc );
+
+                       $this->insertDiffHist( $html, $rc, $unpatrolled );
                        # M, N, b and ! (minor, new, bot and unpatrolled)
-                       $s .= $this->recentChangesFlags(
+                       $html .= $this->recentChangesFlags(
                                array(
                                        'newpage' => $rc->mAttribs['rc_type'] == RC_NEW,
                                        'minor' => $rc->mAttribs['rc_minor'],
@@ -75,56 +104,40 @@ class OldChangesList extends ChangesList {
                                ),
                                ''
                        );
-                       $this->insertArticleLink( $s, $rc, $unpatrolled, $watched );
+                       $this->insertArticleLink( $html, $rc, $unpatrolled, $watched );
                }
                # Edit/log timestamp
-               $this->insertTimestamp( $s, $rc );
+               $this->insertTimestamp( $html, $rc );
                # Bytes added or removed
-               if ( $wgRCShowChangedSize ) {
+               if ( $this->getConfig()->get( 'RCShowChangedSize' ) ) {
                        $cd = $this->formatCharacterDifference( $rc );
                        if ( $cd !== '' ) {
-                               $s .= $cd . '  <span class="mw-changeslist-separator">. .</span> ';
+                               $html .= $cd . '  <span class="mw-changeslist-separator">. .</span> ';
                        }
                }
 
                if ( $rc->mAttribs['rc_type'] == RC_LOG ) {
-                       $s .= $this->insertLogEntry( $rc );
+                       $html .= $this->insertLogEntry( $rc );
                } else {
                        # User tool links
-                       $this->insertUserRelatedLinks( $s, $rc );
+                       $this->insertUserRelatedLinks( $html, $rc );
                        # LTR/RTL direction mark
-                       $s .= $this->getLanguage()->getDirMark();
-                       $s .= $this->insertComment( $rc );
+                       $html .= $this->getLanguage()->getDirMark();
+                       $html .= $this->insertComment( $rc );
                }
 
                # Tags
-               $this->insertTags( $s, $rc, $classes );
+               $this->insertTags( $html, $rc, $classes );
                # Rollback
-               $this->insertRollback( $s, $rc );
+               $this->insertRollback( $html, $rc );
                # For subclasses
-               $this->insertExtra( $s, $rc, $classes );
+               $this->insertExtra( $html, $rc, $classes );
 
                # How many users watch this page
                if ( $rc->numberofWatchingusers > 0 ) {
-                       $s .= ' ' . $this->numberofWatchingusers( $rc->numberofWatchingusers );
-               }
-
-               if ( $this->watchlist ) {
-                       $classes[] = Sanitizer::escapeClass( 'watchlist-' .
-                               $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title'] );
+                       $html .= ' ' . $this->numberofWatchingusers( $rc->numberofWatchingusers );
                }
 
-               if ( !wfRunHooks( 'OldChangesListRecentChangesLine', array( &$this, &$s, $rc, &$classes ) ) ) {
-                       wfProfileOut( __METHOD__ );
-
-                       return false;
-               }
-
-               wfProfileOut( __METHOD__ );
-
-               $dateheader = ''; // $s now contains only <li>...</li>, for hooks' convenience.
-               $this->insertDateHeader( $dateheader, $rc->mAttribs['rc_timestamp'] );
-
-               return "$dateheader<li class=\"" . implode( ' ', $classes ) . "\">" . $s . "</li>\n";
+               return $html;
        }
 }
index 8fa6ed9..e33274e 100644 (file)
@@ -136,7 +136,7 @@ class RecentChange {
        /**
         * Parsing RC_* constants to human-readable test
         * @since 1.24
-        * @param int $rc_type
+        * @param int $rcType
         * @return string $type
         */
        public static function parseFromRCType( $rcType ) {
@@ -160,26 +160,10 @@ class RecentChange {
                return $type;
        }
 
-       /**
-        * No uses left in Gerrit on 2013-11-19.
-        * @deprecated since 1.22
-        * @param mixed $row
-        * @return RecentChange
-        */
-       public static function newFromCurRow( $row ) {
-               wfDeprecated( __METHOD__, '1.22' );
-               $rc = new RecentChange;
-               $rc->loadFromCurRow( $row );
-               $rc->notificationtimestamp = false;
-               $rc->numberofWatchingusers = false;
-
-               return $rc;
-       }
-
        /**
         * Obtain the recent change with a given rc_id value
         *
-        * @param int $rcid rc_id value to retrieve
+        * @param int $rcid The rc_id value to retrieve
         * @return RecentChange
         */
        public static function newFromId( $rcid ) {
@@ -350,38 +334,6 @@ class RecentChange {
                }
        }
 
-       /**
-        * @deprecated since 1.22, use notifyRCFeeds instead.
-        */
-       public function notifyRC2UDP() {
-               wfDeprecated( __METHOD__, '1.22' );
-               $this->notifyRCFeeds();
-       }
-
-       /**
-        * Send some text to UDP.
-        * @deprecated since 1.22
-        */
-       public static function sendToUDP( $line, $address = '', $prefix = '', $port = '' ) {
-               global $wgRC2UDPAddress, $wgRC2UDPInterwikiPrefix, $wgRC2UDPPort, $wgRC2UDPPrefix;
-
-               wfDeprecated( __METHOD__, '1.22' );
-
-               # Assume default for standard RC case
-               $address = $address ? $address : $wgRC2UDPAddress;
-               $prefix = $prefix ? $prefix : $wgRC2UDPPrefix;
-               $port = $port ? $port : $wgRC2UDPPort;
-
-               $engine = new UDPRCFeedEngine();
-               $feed = array(
-                       'uri' => "udp://$address:$port/$prefix",
-                       'formatter' => 'IRCColourfulRCFeedFormatter',
-                       'add_interwiki_prefix' => $wgRC2UDPInterwikiPrefix,
-               );
-
-               $engine->send( $feed, $line );
-       }
-
        /**
         * Notify all the feeds about the change.
         * @param array $feeds Optional feeds to send to, defaults to $wgRCFeeds
@@ -452,15 +404,6 @@ class RecentChange {
                return new $wgRCEngines[$scheme];
        }
 
-       /**
-        * @deprecated since 1.22, moved to IRCColourfulRCFeedFormatter
-        */
-       public static function cleanupForIRC( $text ) {
-               wfDeprecated( __METHOD__, '1.22' );
-
-               return IRCColourfulRCFeedFormatter::cleanupForIRC( $text );
-       }
-
        /**
         * Mark a given change as patrolled
         *
@@ -793,42 +736,6 @@ class RecentChange {
                $this->mAttribs['rc_deleted'] = $row->rc_deleted; // MUST be set
        }
 
-       /**
-        * Makes a pseudo-RC entry from a cur row
-        *
-        * @deprecated since 1.22
-        * @param mixed $row
-        */
-       public function loadFromCurRow( $row ) {
-               wfDeprecated( __METHOD__, '1.22' );
-               $this->mAttribs = array(
-                       'rc_timestamp' => wfTimestamp( TS_MW, $row->rev_timestamp ),
-                       'rc_user' => $row->rev_user,
-                       'rc_user_text' => $row->rev_user_text,
-                       'rc_namespace' => $row->page_namespace,
-                       'rc_title' => $row->page_title,
-                       'rc_comment' => $row->rev_comment,
-                       'rc_minor' => $row->rev_minor_edit ? 1 : 0,
-                       'rc_type' => $row->page_is_new ? RC_NEW : RC_EDIT,
-                       'rc_source' => $row->page_is_new ? self::SRC_NEW : self::SRC_EDIT,
-                       'rc_cur_id' => $row->page_id,
-                       'rc_this_oldid' => $row->rev_id,
-                       'rc_last_oldid' => isset( $row->rc_last_oldid ) ? $row->rc_last_oldid : 0,
-                       'rc_bot' => 0,
-                       'rc_ip' => '',
-                       'rc_id' => $row->rc_id,
-                       'rc_patrolled' => $row->rc_patrolled,
-                       'rc_new' => $row->page_is_new, # obsolete
-                       'rc_old_len' => $row->rc_old_len,
-                       'rc_new_len' => $row->rc_new_len,
-                       'rc_params' => isset( $row->rc_params ) ? $row->rc_params : '',
-                       'rc_log_type' => isset( $row->rc_log_type ) ? $row->rc_log_type : null,
-                       'rc_log_action' => isset( $row->rc_log_action ) ? $row->rc_log_action : null,
-                       'rc_logid' => isset( $row->rc_logid ) ? $row->rc_logid : 0,
-                       'rc_deleted' => $row->rc_deleted // MUST be set
-               );
-       }
-
        /**
         * Get an attribute value
         *
index d2c504a..dc95727 100644 (file)
@@ -346,7 +346,7 @@ class RedisConnectionPool {
         * Adjust or reset the connection handle read timeout value
         *
         * @param Redis $conn
-        * @param integer $timeout Optional
+        * @param int $timeout Optional
         */
        public function resetTimeout( Redis $conn, $timeout = null ) {
                $conn->setOption( Redis::OPT_READ_TIMEOUT, $timeout ?: $this->readTimeout );
index 68e90b4..03d2cb9 100644 (file)
@@ -35,13 +35,4 @@ interface Config {
         * @throws ConfigException
         */
        public function get( $name );
-
-       /**
-        * Set a configuration variable such a "Sitename" to something like "My Wiki"
-        *
-        * @param string $name Name of configuration option
-        * @param mixed $value Value to set
-        * @throws ConfigException
-        */
-       public function set( $name, $value );
 }
index 368ca5a..75cd5ee 100644 (file)
@@ -25,4 +25,5 @@
  *
  * @since 1.23
  */
-class ConfigException extends MWException {}
+class ConfigException extends MWException {
+}
index b09316b..12b0c39 100644 (file)
@@ -41,24 +41,42 @@ class ConfigFactory {
         */
        protected $configs = array();
 
+       /**
+        * @var ConfigFactory
+        */
+       private static $self;
+
        public static function getDefaultInstance() {
-               static $self = null;
-               if ( !$self ) {
-                       $self = new self;
+               if ( !self::$self ) {
+                       self::$self = new self;
                        global $wgConfigRegistry;
                        foreach ( $wgConfigRegistry as $name => $callback ) {
-                               $self->register( $name, $callback );
+                               self::$self->register( $name, $callback );
                        }
                }
-               return $self;
+               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;
        }
 
        /**
         * Register a new config factory function
         * Will override if it's already registered
         * @param string $name
-        * @param callable $callback that takes this ConfigFactory as an argument
-        * @throws InvalidArgumentException if an invalid callback is provided
+        * @param callable $callback That takes this ConfigFactory as an argument
+        * @throws InvalidArgumentException If an invalid callback is provided
         */
        public function register( $name, $callback ) {
                if ( !is_callable( $callback ) ) {
@@ -70,10 +88,10 @@ class ConfigFactory {
        /**
         * Create a given Config using the registered callback for $name.
         * If an object was already created, the same Config object is returned.
-        * @param string $name of the extension/component you want a Config object for
+        * @param string $name Name of the extension/component you want a Config object for
         *                     'main' is used for core
-        * @throws ConfigException if a factory function isn't registered for $name
-        * @throws UnexpectedValueException if the factory function returns a non-Config object
+        * @throws ConfigException If a factory function isn't registered for $name
+        * @throws UnexpectedValueException If the factory function returns a non-Config object
         * @return Config
         */
        public function makeConfig( $name ) {
index 0d7f3f0..1144384 100644 (file)
@@ -53,9 +53,11 @@ class GlobalVarConfig implements Config {
        }
 
        /**
-        * @see Config::set
+        * @see MutableConfig::set
+        * @deprecated since 1.24
         */
        public function set( $name, $value ) {
+               wfDeprecated( __METHOD__, '1.24' );
                $this->setWithPrefix( $this->prefix, $name, $value );
        }
 
@@ -72,7 +74,7 @@ class GlobalVarConfig implements Config {
                if ( !array_key_exists( $var, $GLOBALS ) ) {
                        throw new ConfigException( __METHOD__ . ": undefined variable: '$var'" );
                }
-               return $GLOBALS[ $var ];
+               return $GLOBALS[$var];
        }
 
        /**
@@ -80,9 +82,10 @@ class GlobalVarConfig implements Config {
         *
         * @param string $prefix Prefix to use on the variable
         * @param string $name Variable name without prefix
-        * @param mixed $value value to set
+        * @param mixed $value Value to set
+        * @deprecated since 1.24
         */
        protected function setWithPrefix( $prefix, $name, $value ) {
-               $GLOBALS[ $prefix . $name ] = $value;
+               $GLOBALS[$prefix . $name] = $value;
        }
 }
diff --git a/includes/config/MutableConfig.php b/includes/config/MutableConfig.php
new file mode 100644 (file)
index 0000000..e765e3b
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Copyright 2014
+ *
+ * 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 mutable configuration instances
+ *
+ * @since 1.24
+ */
+interface MutableConfig {
+
+       /**
+        * Set a configuration variable such a "Sitename" to something like "My Wiki"
+        *
+        * @param string $name Name of configuration option
+        * @param mixed $value Value to set
+        * @throws ConfigException
+        */
+       public function set( $name, $value );
+}
index e09be56..683c959 100644 (file)
@@ -503,7 +503,7 @@ abstract class AbstractContent implements Content {
         *
         * @param Title $title Context title for parsing
         * @param int|null $revId Revision ID (for {{REVISIONID}})
-        * @param ParserOptions|null $options Parser options
+        * @param ParserOptions $options Parser options
         * @param bool $generateHtml Whether or not to generate HTML
         * @param ParserOutput &$output The output object to fill (reference).
         *
diff --git a/includes/content/CodeContentHandler.php b/includes/content/CodeContentHandler.php
new file mode 100644 (file)
index 0000000..447a2a7
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+/**
+ * Content handler for the pages with code, such as CSS, JavaScript, JSON.
+ *
+ * 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 Content
+ */
+
+/**
+ * Content handler for code content such as CSS, JavaScript, JSON, etc
+ * @since 1.24
+ * @ingroup Content
+ */
+abstract class CodeContentHandler extends TextContentHandler {
+
+       /**
+        * Returns the english language, because code is english, and should be handled as such.
+        *
+        * @param Title $title
+        * @param Content $content
+        *
+        * @return Language Return of wfGetLangObj( 'en' )
+        *
+        * @see ContentHandler::getPageLanguage()
+        */
+       public function getPageLanguage( Title $title, Content $content = null ) {
+               return wfGetLangObj( 'en' );
+       }
+
+       /**
+        * Returns the english language, because code is english, and should be handled as such.
+        *
+        * @param Title $title
+        * @param Content $content
+        *
+        * @return Language Return of wfGetLangObj( 'en' )
+        *
+        * @see ContentHandler::getPageViewLanguage()
+        */
+       public function getPageViewLanguage( Title $title, Content $content = null ) {
+               return wfGetLangObj( 'en' );
+       }
+
+       /**
+        * @return string
+        */
+       protected function getContentClass() {
+               throw new MWException( 'Subclass must override' );
+       }
+}
index e077c77..ac41722 100644 (file)
@@ -709,7 +709,7 @@ abstract class ContentHandler {
         * typically based on the namespace or some other aspect of the title, such as a special suffix
         * (e.g. ".svg" for SVG content).
         *
-        * @note: this calls the ContentHandlerCanBeUsedOn hook which may be used to override which
+        * @note this calls the ContentHandlerCanBeUsedOn hook which may be used to override which
         * content model can be used where.
         *
         * @param Title $title The page's title.
@@ -743,9 +743,9 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param Content|string $oldContent The page's previous content.
-        * @param Content|string $myContent One of the page's conflicting contents.
-        * @param Content|string $yourContent One of the page's conflicting contents.
+        * @param Content $oldContent The page's previous content.
+        * @param Content $myContent One of the page's conflicting contents.
+        * @param Content $yourContent One of the page's conflicting contents.
         *
         * @return Content|bool Always false.
         */
@@ -821,6 +821,11 @@ abstract class ContentHandler {
                                ->inContentLanguage()->text();
                }
 
+               // New blank article auto-summary
+               if ( $flags & EDIT_NEW && $newContent->isEmpty() ) {
+                       return wfMessage( 'autosumm-newblank' )->inContentLanguage()->text();
+               }
+
                // If we reach this point, there's no applicable auto-summary for our
                // case, so our auto-summary is empty.
                return '';
@@ -837,7 +842,7 @@ abstract class ContentHandler {
         * @return mixed String containing deletion reason or empty string, or
         *    boolean false if no revision occurred
         *
-        * @XXX &$hasHistory is extremely ugly, it's here because
+        * @todo &$hasHistory is extremely ugly, it's here because
         * WikiPage::getAutoDeleteReason() and Article::generateReason()
         * have it / want it.
         */
index 2673084..8290603 100644 (file)
@@ -34,9 +34,10 @@ class CssContent extends TextContent {
 
        /**
         * @param string $text CSS code.
+        * @param string $modelId the content content model
         */
-       public function __construct( $text ) {
-               parent::__construct( $text, CONTENT_MODEL_CSS );
+       public function __construct( $text, $modelId = CONTENT_MODEL_CSS ) {
+               parent::__construct( $text, $modelId );
        }
 
        /**
@@ -58,7 +59,7 @@ class CssContent extends TextContent {
                $text = $this->getNativeData();
                $pst = $wgParser->preSaveTransform( $text, $title, $user, $popts );
 
-               return new CssContent( $pst );
+               return new static( $pst );
        }
 
        /**
index 85059a8..b2a8676 100644 (file)
@@ -27,7 +27,7 @@
  * @since 1.21
  * @ingroup Content
  */
-class CssContentHandler extends TextContentHandler {
+class CssContentHandler extends CodeContentHandler {
 
        /**
         * @param string $modelId
@@ -36,55 +36,7 @@ class CssContentHandler extends TextContentHandler {
                parent::__construct( $modelId, array( CONTENT_FORMAT_CSS ) );
        }
 
-       /**
-        * @param string $text
-        * @param string $format
-        *
-        * @return CssContent
-        *
-        * @see ContentHandler::unserializeContent()
-        */
-       public function unserializeContent( $text, $format = null ) {
-               $this->checkFormat( $format );
-
-               return new CssContent( $text );
-       }
-
-       /**
-        * @return CssContent A new CssContent object with empty text.
-        *
-        * @see ContentHandler::makeEmptyContent()
-        */
-       public function makeEmptyContent() {
-               return new CssContent( '' );
-       }
-
-       /**
-        * Returns the english language, because CSS is english, and should be handled as such.
-        *
-        * @param Title $title
-        * @param Content $content
-        *
-        * @return Language wfGetLangObj( 'en' )
-        *
-        * @see ContentHandler::getPageLanguage()
-        */
-       public function getPageLanguage( Title $title, Content $content = null ) {
-               return wfGetLangObj( 'en' );
-       }
-
-       /**
-        * Returns the english language, because CSS is english, and should be handled as such.
-        *
-        * @param Title $title
-        * @param Content $content
-        *
-        * @return Language wfGetLangObj( 'en' )
-        *
-        * @see ContentHandler::getPageViewLanguage()
-        */
-       public function getPageViewLanguage( Title $title, Content $content = null ) {
-               return wfGetLangObj( 'en' );
+       protected function getContentClass() {
+               return 'CssContent';
        }
-
 }
index 442b705..c0194c2 100644 (file)
@@ -34,9 +34,10 @@ class JavaScriptContent extends TextContent {
 
        /**
         * @param string $text JavaScript code.
+        * @param string $modelId the content model name
         */
-       public function __construct( $text ) {
-               parent::__construct( $text, CONTENT_MODEL_JAVASCRIPT );
+       public function __construct( $text, $modelId = CONTENT_MODEL_JAVASCRIPT ) {
+               parent::__construct( $text, $modelId );
        }
 
        /**
@@ -57,7 +58,7 @@ class JavaScriptContent extends TextContent {
                $text = $this->getNativeData();
                $pst = $wgParser->preSaveTransform( $text, $title, $user, $popts );
 
-               return new JavaScriptContent( $pst );
+               return new static( $pst );
        }
 
        /**
index 2e98976..457b83d 100644 (file)
@@ -27,7 +27,7 @@
  * @ingroup Content
  * @todo make ScriptContentHandler base class, do highlighting stuff there?
  */
-class JavaScriptContentHandler extends TextContentHandler {
+class JavaScriptContentHandler extends CodeContentHandler {
 
        /**
         * @param string $modelId
@@ -36,55 +36,7 @@ class JavaScriptContentHandler extends TextContentHandler {
                parent::__construct( $modelId, array( CONTENT_FORMAT_JAVASCRIPT ) );
        }
 
-       /**
-        * @param string $text
-        * @param string $format
-        *
-        * @return JavaScriptContent
-        *
-        * @see ContentHandler::unserializeContent()
-        */
-       public function unserializeContent( $text, $format = null ) {
-               $this->checkFormat( $format );
-
-               return new JavaScriptContent( $text );
-       }
-
-       /**
-        * @return JavaScriptContent A new JavaScriptContent object with empty text.
-        *
-        * @see ContentHandler::makeEmptyContent()
-        */
-       public function makeEmptyContent() {
-               return new JavaScriptContent( '' );
-       }
-
-       /**
-        * Returns the english language, because JS is english, and should be handled as such.
-        *
-        * @param Title $title
-        * @param Content $content
-        *
-        * @return Language wfGetLangObj( 'en' )
-        *
-        * @see ContentHandler::getPageLanguage()
-        */
-       public function getPageLanguage( Title $title, Content $content = null ) {
-               return wfGetLangObj( 'en' );
-       }
-
-       /**
-        * Returns the english language, because JS is english, and should be handled as such.
-        *
-        * @param Title $title
-        * @param Content $content
-        *
-        * @return Language wfGetLangObj( 'en' )
-        *
-        * @see ContentHandler::getPageViewLanguage()
-        */
-       public function getPageViewLanguage( Title $title, Content $content = null ) {
-               return wfGetLangObj( 'en' );
+       protected function getContentClass() {
+               return 'JavaScriptContent';
        }
-
 }
diff --git a/includes/content/JsonContent.php b/includes/content/JsonContent.php
new file mode 100644 (file)
index 0000000..b36827c
--- /dev/null
@@ -0,0 +1,120 @@
+<?php
+/**
+ * JSON Content Model
+ *
+ * @file
+ *
+ * @author Ori Livneh <ori@wikimedia.org>
+ * @author Kunal Mehta <legoktm@gmail.com>
+ */
+
+/**
+ * Represents the content of a JSON content.
+ * @since 1.24
+ */
+class JsonContent extends TextContent {
+
+       public function __construct( $text, $modelId = CONTENT_MODEL_JSON ) {
+               parent::__construct( $text, $modelId );
+       }
+
+       /**
+        * Decodes the JSON into a PHP associative array.
+        * @return array
+        */
+       public function getJsonData() {
+               return FormatJson::decode( $this->getNativeData(), true );
+       }
+
+       /**
+        * @return bool Whether content is valid JSON.
+        */
+       public function isValid() {
+               return $this->getJsonData() !== null;
+       }
+
+       /**
+        * Pretty-print JSON
+        *
+        * @return bool|null|string
+        */
+       public function beautifyJSON() {
+               $decoded = FormatJson::decode( $this->getNativeData(), true );
+               if ( !is_array( $decoded ) ) {
+                       return null;
+               }
+               return FormatJson::encode( $decoded, true );
+
+       }
+
+       /**
+        * Beautifies JSON prior to save.
+        * @param Title $title Title
+        * @param User $user User
+        * @param ParserOptions $popts
+        * @return JsonContent
+        */
+       public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
+               return new static( $this->beautifyJSON() );
+       }
+
+       /**
+        * Set the HTML and add the appropriate styles
+        *
+        *
+        * @param Title $title
+        * @param int $revId
+        * @param ParserOptions $options
+        * @param bool $generateHtml
+        * @param ParserOutput $output
+        */
+       protected function fillParserOutput( Title $title, $revId,
+               ParserOptions $options, $generateHtml, ParserOutput &$output
+       ) {
+               if ( $generateHtml ) {
+                       $output->setText( $this->objectTable( $this->getJsonData() ) );
+                       $output->addModuleStyles( 'mediawiki.content.json' );
+               } else {
+                       $output->setText( '' );
+               }
+       }
+       /**
+        * Constructs an HTML representation of a JSON object.
+        * @param array $mapping
+        * @return string HTML
+        */
+       protected function objectTable( $mapping ) {
+               $rows = array();
+
+               foreach ( $mapping as $key => $val ) {
+                       $rows[] = $this->objectRow( $key, $val );
+               }
+               return Xml::tags( 'table', array( 'class' => 'mw-json' ),
+                       Xml::tags( 'tbody', array(), join( "\n", $rows ) )
+               );
+       }
+
+       /**
+        * Constructs HTML representation of a single key-value pair.
+        * @param string $key
+        * @param mixed $val
+        * @return string HTML.
+        */
+       protected function objectRow( $key, $val ) {
+               $th = Xml::elementClean( 'th', array(), $key );
+               if ( is_array( $val ) ) {
+                       $td = Xml::tags( 'td', array(), self::objectTable( $val ) );
+               } else {
+                       if ( is_string( $val ) ) {
+                               $val = '"' . $val . '"';
+                       } else {
+                               $val = FormatJson::encode( $val );
+                       }
+
+                       $td = Xml::elementClean( 'td', array( 'class' => 'value' ), $val );
+               }
+
+               return Xml::tags( 'tr', array(), $th . $td );
+       }
+
+}
diff --git a/includes/content/JsonContentHandler.php b/includes/content/JsonContentHandler.php
new file mode 100644 (file)
index 0000000..392ce37
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+/**
+ * JSON Schema Content Handler
+ *
+ * @file
+ *
+ * @author Ori Livneh <ori@wikimedia.org>
+ * @author Kunal Mehta <legoktm@gmail.com>
+ */
+
+/**
+ * @since 1.24
+ */
+class JsonContentHandler extends CodeContentHandler {
+
+       public function __construct( $modelId = CONTENT_MODEL_JSON ) {
+               parent::__construct( $modelId, array( CONTENT_FORMAT_JSON ) );
+       }
+
+       /**
+        * @return string
+        */
+       protected function getContentClass() {
+               return 'JsonContent';
+       }
+}
index b601344..5b84657 100644 (file)
@@ -29,7 +29,7 @@
  * Wrapper allowing us to handle a system message as a Content object.
  * Note that this is generally *not* used to represent content from the
  * MediaWiki namespace, and that there is no MessageContentHandler.
- * MessageContent is just intended as glue for wrapping a message programatically.
+ * MessageContent is just intended as glue for wrapping a message programmatically.
  *
  * @ingroup Content
  */
@@ -106,7 +106,7 @@ class MessageContent extends AbstractContent {
        }
 
        /**
-        * @param int $maxLength Maximum length of the summary text, defaults to 250.
+        * @param int $maxlength Maximum length of the summary text, defaults to 250.
         *
         * @return string The summary text.
         *
@@ -126,7 +126,7 @@ class MessageContent extends AbstractContent {
        }
 
        /**
-        * @return Content. A copy of this object
+        * @return Content A copy of this object
         *
         * @see Content::copy
         */
@@ -165,6 +165,8 @@ class MessageContent extends AbstractContent {
                }
 
                $po = new ParserOutput( $html );
+               // Message objects are in the user language.
+               $po->recordOption( 'userlang' );
 
                return $po;
        }
index c3daf83..d292880 100644 (file)
@@ -132,7 +132,7 @@ class TextContent extends AbstractContent {
         * Returns attempts to convert this content object to wikitext,
         * and then returns the text string. The conversion may be lossy.
         *
-        * @note: this allows any text-based content to be transcluded as if it was wikitext.
+        * @note this allows any text-based content to be transcluded as if it was wikitext.
         *
         * @return string|bool The raw text, or false if the conversion failed.
         */
@@ -257,7 +257,7 @@ class TextContent extends AbstractContent {
         * This default implementation returns an HTML-escaped version
         * of the raw text content.
         *
-        * @note: The functionality of this method should really be implemented
+        * @note The functionality of this method should really be implemented
         * in getHtml(), and subclasses should override getHtml() if needed.
         * getHighlightHtml() is kept around for backward compatibility with
         * extensions that already override it.
index b728d31..ffe1acb 100644 (file)
@@ -60,9 +60,9 @@ class TextContentHandler extends ContentHandler {
         *
         * This text-based implementation uses wfMerge().
         *
-        * @param Content|string $oldContent The page's previous content.
-        * @param Content|string $myContent One of the page's conflicting contents.
-        * @param Content|string $yourContent One of the page's conflicting contents.
+        * @param Content $oldContent The page's previous content.
+        * @param Content $myContent One of the page's conflicting contents.
+        * @param Content $yourContent One of the page's conflicting contents.
         *
         * @return Content|bool
         */
@@ -92,6 +92,19 @@ class TextContentHandler extends ContentHandler {
                return $mergedContent;
        }
 
+       /**
+        * Returns the name of the associated Content class, to
+        * be used when creating new objects. Override expected
+        * by subclasses.
+        *
+        * @since 1.24
+        *
+        * @return string
+        */
+       protected function getContentClass() {
+               return 'TextContent';
+       }
+
        /**
         * Unserializes a Content object of the type supported by this ContentHandler.
         *
@@ -105,7 +118,8 @@ class TextContentHandler extends ContentHandler {
        public function unserializeContent( $text, $format = null ) {
                $this->checkFormat( $format );
 
-               return new TextContent( $text );
+               $class = $this->getContentClass();
+               return new $class( $text );
        }
 
        /**
@@ -116,7 +130,8 @@ class TextContentHandler extends ContentHandler {
         * @return Content A new TextContent object with empty text.
         */
        public function makeEmptyContent() {
-               return new TextContent( '' );
+               $class = $this->getContentClass();
+               return new $class( '' );
        }
 
 }
index cdf5962..3ab6a6d 100644 (file)
@@ -52,7 +52,7 @@ class WikitextContent extends TextContent {
                if ( $sect === false ) {
                        return false;
                } else {
-                       return new WikitextContent( $sect );
+                       return new static( $sect );
                }
        }
 
@@ -104,7 +104,7 @@ class WikitextContent extends TextContent {
                        $text = $wgParser->replaceSection( $oldtext, $sectionId, $text );
                }
 
-               $newContent = new WikitextContent( $text );
+               $newContent = new static( $text );
 
                wfProfileOut( __METHOD__ );
 
@@ -125,7 +125,7 @@ class WikitextContent extends TextContent {
                $text .= "\n\n";
                $text .= $this->getNativeData();
 
-               return new WikitextContent( $text );
+               return new static( $text );
        }
 
        /**
@@ -145,7 +145,7 @@ class WikitextContent extends TextContent {
                $pst = $wgParser->preSaveTransform( $text, $title, $user, $popts );
                rtrim( $pst );
 
-               return ( $text === $pst ) ? $this : new WikitextContent( $pst );
+               return ( $text === $pst ) ? $this : new static( $pst );
        }
 
        /**
@@ -164,13 +164,13 @@ class WikitextContent extends TextContent {
                $text = $this->getNativeData();
                $plt = $wgParser->getPreloadText( $text, $title, $popts, $params );
 
-               return new WikitextContent( $plt );
+               return new static( $plt );
        }
 
        /**
         * Extract the redirect target and the remaining text on the page.
         *
-        * @note: migrated here from Title::newFromRedirectInternal()
+        * @note migrated here from Title::newFromRedirectInternal()
         *
         * @since 1.23
         *
@@ -246,7 +246,7 @@ class WikitextContent extends TextContent {
                        '[[' . $target->getFullText() . ']]',
                        $this->getNativeData(), 1 );
 
-               return new WikitextContent( $newText );
+               return new static( $newText );
        }
 
        /**
@@ -315,7 +315,7 @@ class WikitextContent extends TextContent {
         * @param int $revId Revision to pass to the parser (default: null)
         * @param ParserOptions $options (default: null)
         * @param bool $generateHtml (default: true)
-        * @param &$output ParserOutput representing the HTML form of the text,
+        * @param ParserOutput &$output ParserOutput representing the HTML form of the text,
         *           may be manipulated or replaced.
         */
        protected function fillParserOutput( Title $title, $revId,
@@ -336,6 +336,7 @@ class WikitextContent extends TextContent {
                                        Article::getRedirectHeaderHtml( $title->getPageLanguage(), $chain, false ) .
                                        $output->getText()
                                );
+                               $output->addModuleStyles( 'mediawiki.action.view.redirectPage' );
                        }
                }
        }
index 5ae3e25..c1db1de 100644 (file)
@@ -34,19 +34,8 @@ class WikitextContentHandler extends TextContentHandler {
                parent::__construct( $modelId, array( CONTENT_FORMAT_WIKITEXT ) );
        }
 
-       public function unserializeContent( $text, $format = null ) {
-               $this->checkFormat( $format );
-
-               return new WikitextContent( $text );
-       }
-
-       /**
-        * @return Content A new WikitextContent object with empty text.
-        *
-        * @see ContentHandler::makeEmptyContent
-        */
-       public function makeEmptyContent() {
-               return new WikitextContent( '' );
+       protected function getContentClass() {
+               return 'WikitextContent';
        }
 
        /**
@@ -79,7 +68,8 @@ class WikitextContentHandler extends TextContentHandler {
                        $redirectText .= "\n" . $text;
                }
 
-               return new WikitextContent( $redirectText );
+               $class = $this->getContentClass();
+               return new $class( $redirectText );
        }
 
        /**
index d0c0bdc..076504e 100644 (file)
@@ -34,9 +34,9 @@ abstract class ContextSource implements IContextSource {
        private $context;
 
        /**
-        * Get the RequestContext object
+        * Get the base IContextSource object
         * @since 1.18
-        * @return RequestContext
+        * @return IContextSource
         */
        public function getContext() {
                if ( $this->context === null ) {
index f550e9e..b8966f0 100644 (file)
@@ -126,12 +126,8 @@ class DerivativeContext extends ContextSource {
         * Set the Title object
         *
         * @param Title $t
-        * @throws MWException
         */
-       public function setTitle( $t ) {
-               if ( $t !== null && !$t instanceof Title ) {
-                       throw new MWException( __METHOD__ . " expects an instance of Title" );
-               }
+       public function setTitle( Title $t ) {
                $this->title = $t;
        }
 
@@ -300,8 +296,7 @@ class DerivativeContext extends ContextSource {
         * it would set only the original context, and not take
         * into account any changes.
         *
-        * @param String Message name
-        * @param Variable number of message arguments
+        * @param mixed $args,... Arguments to wfMessage
         * @return Message
         */
        public function msg() {
index d4bf0b4..ede10fe 100644 (file)
@@ -123,14 +123,10 @@ class RequestContext implements IContextSource {
        /**
         * Set the Title object
         *
-        * @param Title $t
-        * @throws MWException
+        * @param Title $title
         */
-       public function setTitle( $t ) {
-               if ( $t !== null && !$t instanceof Title ) {
-                       throw new MWException( __METHOD__ . " expects an instance of Title" );
-               }
-               $this->title = $t;
+       public function setTitle( Title $title ) {
+               $this->title = $title;
                // Erase the WikiPage so a new one with the new title gets created.
                $this->wikipage = null;
        }
@@ -158,18 +154,14 @@ class RequestContext implements IContextSource {
         * @return bool
         */
        public function canUseWikiPage() {
-               if ( $this->wikipage !== null ) {
-                       # If there's a WikiPage object set, we can for sure get it
+               if ( $this->wikipage ) {
+                       // If there's a WikiPage object set, we can for sure get it
                        return true;
                }
+               // Only pages with legitimate titles can have WikiPages.
+               // That usually means pages in non-virtual namespaces.
                $title = $this->getTitle();
-               if ( $title === null ) {
-                       # No Title, no WikiPage
-                       return false;
-               } else {
-                       # Only namespaces whose pages are stored in the database can have WikiPage
-                       return $title->canExist();
-               }
+               return $title ? $title->canExist() : false;
        }
 
        /**
@@ -265,7 +257,7 @@ class RequestContext implements IContextSource {
                $code = strtolower( $code );
 
                # Validate $code
-               if ( empty( $code ) || !Language::isValidCode( $code ) || ( $code === 'qqq' ) ) {
+               if ( !$code || !Language::isValidCode( $code ) || $code === 'qqq' ) {
                        wfDebug( "Invalid user language code\n" );
                        $code = $wgLanguageCode;
                }
@@ -305,13 +297,12 @@ class RequestContext implements IContextSource {
                        $e = new Exception;
                        wfDebugLog( 'recursion-guard', "Recursion detected:\n" . $e->getTraceAsString() );
 
-                       global $wgLanguageCode;
-                       $code = ( $wgLanguageCode ) ? $wgLanguageCode : 'en';
+                       $code = $this->getConfig()->get( 'LanguageCode' ) ?: 'en';
                        $this->lang = Language::factory( $code );
                } elseif ( $this->lang === null ) {
                        $this->recursion = true;
 
-                       global $wgLanguageCode, $wgContLang;
+                       global $wgContLang;
 
                        try {
                                $request = $this->getRequest();
@@ -322,7 +313,7 @@ class RequestContext implements IContextSource {
 
                                wfRunHooks( 'UserGetLanguageObject', array( $user, &$code, $this ) );
 
-                               if ( $code === $wgLanguageCode ) {
+                               if ( $code === $this->getConfig()->get( 'LanguageCode' ) ) {
                                        $this->lang = $wgContLang;
                                } else {
                                        $obj = Language::factory( $code );
@@ -361,29 +352,36 @@ class RequestContext implements IContextSource {
 
                        $skin = null;
                        wfRunHooks( 'RequestContextCreateSkin', array( $this, &$skin ) );
+                       $factory = SkinFactory::getDefaultInstance();
 
                        // If the hook worked try to set a skin from it
                        if ( $skin instanceof Skin ) {
                                $this->skin = $skin;
                        } elseif ( is_string( $skin ) ) {
-                               $this->skin = Skin::newFromKey( $skin );
+                               // Normalize the key, just in case the hook did something weird.
+                               $normalized = Skin::normalizeKey( $skin );
+                               $this->skin = $factory->makeSkin( $normalized );
                        }
 
                        // If this is still null (the hook didn't run or didn't work)
                        // then go through the normal processing to load a skin
                        if ( $this->skin === null ) {
-                               global $wgHiddenPrefs;
-                               if ( !in_array( 'skin', $wgHiddenPrefs ) ) {
+                               if ( !in_array( 'skin', $this->getConfig()->get( 'HiddenPrefs' ) ) ) {
                                        # get the user skin
                                        $userSkin = $this->getUser()->getOption( 'skin' );
                                        $userSkin = $this->getRequest()->getVal( 'useskin', $userSkin );
                                } else {
                                        # if we're not allowing users to override, then use the default
-                                       global $wgDefaultSkin;
-                                       $userSkin = $wgDefaultSkin;
+                                       $userSkin = $this->getConfig()->get( 'DefaultSkin' );
                                }
 
-                               $this->skin = Skin::newFromKey( $userSkin );
+                               // Normalize the key in case the user is passing gibberish
+                               // or has old preferences (bug 69566).
+                               $normalized = Skin::normalizeKey( $userSkin );
+
+                               // Skin::normalizeKey will also validate it, so
+                               // this won't throw an exception
+                               $this->skin = $factory->makeSkin( $normalized );
                        }
 
                        // After all that set a context on whatever skin got created
@@ -423,6 +421,21 @@ class RequestContext implements IContextSource {
                return self::$instance;
        }
 
+       /**
+        * Get the RequestContext object associated with the main request
+        * and gives a warning to the log, to find places, where a context maybe is missing.
+        *
+        * @param string $func
+        * @return RequestContext
+        * @since 1.24
+        */
+       public static function getMainAndWarn( $func = __METHOD__ ) {
+               wfDebug( $func . ' called without context. ' .
+                       "Using RequestContext::getMain() for sanity\n" );
+
+               return self::getMain();
+       }
+
        /**
         * Resets singleton returned by getMain(). Should be called only from unit tests.
         */
@@ -475,7 +488,8 @@ class RequestContext implements IContextSource {
 
                if ( $params['userId'] ) { // logged-in user
                        $user = User::newFromId( $params['userId'] );
-                       if ( !$user ) {
+                       $user->load();
+                       if ( !$user->getId() ) {
                                throw new MWException( "No user with ID '{$params['userId']}'." );
                        }
                } elseif ( !IP::isValid( $params['ip'] ) ) {
index 7d8fbe9..9b783a9 100644 (file)
@@ -600,7 +600,18 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * @return bool
         */
        public function doneWrites() {
-               return $this->mDoneWrites;
+               return (bool)$this->mDoneWrites;
+       }
+
+       /**
+        * Returns the last time the connection may have been used for write queries.
+        * Should return a timestamp if unsure.
+        *
+        * @return int|float UNIX timestamp or false
+        * @since 1.24
+        */
+       public function lastDoneWrites() {
+               return $this->mDoneWrites ?: false;
        }
 
        /**
@@ -668,8 +679,6 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         *   - DBO_DEBUG: output some debug info (same as debug())
         *   - DBO_NOBUFFER: don't buffer results (inverse of bufferResults())
         *   - DBO_TRX: automatically start transactions
-        *   - DBO_DEFAULT: automatically sets DBO_TRX if not in command line mode
-        *       and removes it in command line mode
         *   - DBO_PERSISTENT: use persistant database connection
         * @return bool
         */
@@ -699,19 +708,42 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
        }
 
        /**
-        * Return a path to the DBMS-specific schema file, otherwise default to tables.sql
+        * Return a path to the DBMS-specific SQL file if it exists,
+        * otherwise default SQL file
         *
+        * @param string $filename
         * @return string
         */
-       public function getSchemaPath() {
+       private function getSqlFilePath( $filename ) {
                global $IP;
-               if ( file_exists( "$IP/maintenance/" . $this->getType() . "/tables.sql" ) ) {
-                       return "$IP/maintenance/" . $this->getType() . "/tables.sql";
+               $dbmsSpecificFilePath = "$IP/maintenance/" . $this->getType() . "/$filename";
+               if ( file_exists( $dbmsSpecificFilePath ) ) {
+                       return $dbmsSpecificFilePath;
                } else {
-                       return "$IP/maintenance/tables.sql";
+                       return "$IP/maintenance/$filename";
                }
        }
 
+       /**
+        * Return a path to the DBMS-specific schema file,
+        * otherwise default to tables.sql
+        *
+        * @return string
+        */
+       public function getSchemaPath() {
+               return $this->getSqlFilePath( 'tables.sql' );
+       }
+
+       /**
+        * Return a path to the DBMS-specific update key file,
+        * otherwise default to update-keys.sql
+        *
+        * @return string
+        */
+       public function getUpdateKeysPath() {
+               return $this->getSqlFilePath( 'update-keys.sql' );
+       }
+
 # ------------------------------------------------------------------------------
 # Other functions
 # ------------------------------------------------------------------------------
@@ -1017,13 +1049,13 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         *     for a successful read query, or false on failure if $tempIgnore set
         */
        public function query( $sql, $fname = __METHOD__, $tempIgnore = false ) {
-               global $wgUser, $wgDebugDBTransactions;
+               global $wgUser, $wgDebugDBTransactions, $wgDebugDumpSqlLength;
 
                $this->mLastQuery = $sql;
-               if ( !$this->mDoneWrites && $this->isWriteQuery( $sql ) ) {
+               if ( $this->isWriteQuery( $sql ) ) {
                        # Set a flag indicating that writes have been done
                        wfDebug( __METHOD__ . ': Writes done: ' . DatabaseBase::generalizeSQL( $sql ) . "\n" );
-                       $this->mDoneWrites = true;
+                       $this->mDoneWrites = microtime( true );
                }
 
                # Add a comment for easy SHOW PROCESSLIST interpretation
@@ -1091,7 +1123,8 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                        static $cnt = 0;
 
                        $cnt++;
-                       $sqlx = substr( $commentedSql, 0, 500 );
+                       $sqlx = $wgDebugDumpSqlLength ? substr( $commentedSql, 0, $wgDebugDumpSqlLength )
+                               : $commentedSql;
                        $sqlx = strtr( $sqlx, "\t\n", '  ' );
 
                        $master = $isMaster ? 'master' : 'slave';
@@ -1118,11 +1151,14 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                        $this->mTrxIdleCallbacks = array(); // bug 65263
                        $this->mTrxPreCommitCallbacks = array(); // bug 65263
                        wfDebug( "Connection lost, reconnecting...\n" );
-
+                       # Stash the last error values since ping() might clear them
+                       $lastError = $this->lastError();
+                       $lastErrno = $this->lastErrno();
                        if ( $this->ping() ) {
                                global $wgRequestTime;
                                wfDebug( "Reconnected\n" );
-                               $sqlx = substr( $commentedSql, 0, 500 );
+                               $sqlx = $wgDebugDumpSqlLength ? substr( $commentedSql, 0, $wgDebugDumpSqlLength )
+                                       : $commentedSql;
                                $sqlx = strtr( $sqlx, "\t\n", '  ' );
                                $elapsed = round( microtime( true ) - $wgRequestTime, 3 );
                                if ( $elapsed < 300 ) {
@@ -1132,6 +1168,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                                if ( $hadTrx ) {
                                        # Leave $ret as false and let an error be reported.
                                        # Callers may catch the exception and continue to use the DB.
+                                       $this->reportQueryError( $lastError, $lastErrno, $sql, $fname, $tempIgnore );
                                } else {
                                        # Should be safe to silently retry (no trx and thus no callbacks)
                                        $ret = $this->doQuery( $commentedSql );
@@ -1477,6 +1514,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * @param array $options Query options
         * @param array $join_conds Join conditions
         *
+        *
         * @param string|array $table
         *
         * May be either an array of table names, or a single string holding a table
@@ -1714,7 +1752,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
        }
 
        /**
-        * Estimate rows in dataset.
+        * Estimate the number of rows in dataset
         *
         * MySQL allows you to estimate the number of rows that would be returned
         * by a SELECT query, using EXPLAIN SELECT. The estimate is provided using
@@ -1733,8 +1771,8 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * @param array $options Options for select
         * @return int Row count
         */
-       public function estimateRowCount( $table, $vars = '*', $conds = '',
-               $fname = __METHOD__, $options = array()
+       public function estimateRowCount(
+               $table, $vars = '*', $conds = '', $fname = __METHOD__, $options = array()
        ) {
                $rows = 0;
                $res = $this->select( $table, array( 'rowcount' => 'COUNT(*)' ), $conds, $fname, $options );
@@ -1747,6 +1785,36 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                return $rows;
        }
 
+       /**
+        * Get the number of rows in dataset
+        *
+        * This is useful when trying to do COUNT(*) but with a LIMIT for performance.
+        *
+        * Takes the same arguments as DatabaseBase::select().
+        *
+        * @param string $table Table name
+        * @param string $vars Unused
+        * @param array|string $conds Filters on the table
+        * @param string $fname Function name for profiling
+        * @param array $options Options for select
+        * @return int Row count
+        * @since 1.24
+        */
+       public function selectRowCount(
+               $table, $vars = '*', $conds = '', $fname = __METHOD__, $options = array()
+       ) {
+               $rows = 0;
+               $sql = $this->selectSQLText( $table, '1', $conds, $fname, $options );
+               $res = $this->query( "SELECT COUNT(*) AS rowcount FROM ($sql) tmp_count" );
+
+               if ( $res ) {
+                       $row = $this->fetchRow( $res );
+                       $rows = ( isset( $row['rowcount'] ) ) ? $row['rowcount'] : 0;
+               }
+
+               return $rows;
+       }
+
        /**
         * Removes most variables from an SQL query and replaces them with X or N for numbers.
         * It's only slightly flawed. Don't use for anything important.
@@ -1769,9 +1837,10 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                # All newlines, tabs, etc replaced by single space
                $sql = preg_replace( '/\s+/', ' ', $sql );
 
-               # All numbers => N
+               # All numbers => N,
+               # except the ones surrounded by characters, e.g. l10n
                $sql = preg_replace( '/-?\d+(,-?\d+)+/s', 'N,...,N', $sql );
-               $sql = preg_replace( '/-?\d+/s', 'N', $sql );
+               $sql = preg_replace( '/(?<![a-zA-Z])-?\d+(?![a-zA-Z])/s', 'N', $sql );
 
                return $sql;
        }
@@ -1886,7 +1955,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         *   DatabaseBase::tableName().
         * @param array $a Array of rows to insert
         * @param string $fname Calling function name (use __METHOD__) for logs/profiling
-        * @param array $options of options
+        * @param array $options Array of options
         *
         * @return bool
         */
@@ -2081,11 +2150,11 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * Build a partial where clause from a 2-d array such as used for LinkBatch.
         * The keys on each level may be either integers or strings.
         *
-        * @param array $data organized as 2-d
+        * @param array $data Organized as 2-d
         *    array(baseKeyVal => array(subKeyVal => [ignored], ...), ...)
         * @param string $baseKey Field name to match the base-level keys to (eg 'pl_namespace')
         * @param string $subKey Field name to match the sub-level keys to (eg 'pl_title')
-        * @return string|bool string SQL fragment, or false if no items in array.
+        * @return string|bool SQL fragment, or false if no items in array
         */
        public function makeWhereFrom2d( $data, $baseKey, $subKey ) {
                $conds = array();
@@ -2371,7 +2440,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
        /**
         * Gets an array of aliased table names
         *
-        * @param array $tables array( [alias] => table )
+        * @param array $tables Array( [alias] => table )
         * @return string[] See tableNameWithAlias()
         */
        public function tableNamesWithAlias( $tables ) {
@@ -2405,7 +2474,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
        /**
         * Gets an array of aliased field names
         *
-        * @param array $fields array( [alias] => field )
+        * @param array $fields Array( [alias] => field )
         * @return string[] See fieldNameWithAlias()
         */
        public function fieldNamesWithAlias( $fields ) {
@@ -2906,9 +2975,9 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * DELETE query wrapper.
         *
         * @param array $table Table name
-        * @param string|array $conds of conditions. See $conds in DatabaseBase::select()
+        * @param string|array $conds Array of conditions. See $conds in DatabaseBase::select()
         *   for the format. Use $conds == "*" to delete all rows
-        * @param string $fname name of the calling function
+        * @param string $fname Name of the calling function
         * @throws DBUnexpectedError
         * @return bool|ResultWrapper
         */
@@ -3197,7 +3266,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * @param DBMasterPos $pos
         * @param int $timeout The maximum number of seconds to wait for
         *   synchronisation
-        * @return int Zzero if the slave was past that position already,
+        * @return int Zero if the slave was past that position already,
         *   greater than zero if we waited for some period of time, less than
         *   zero if we timed out.
         */
@@ -3274,7 +3343,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
        protected function runOnTransactionIdleCallbacks() {
                $autoTrx = $this->getFlag( DBO_TRX ); // automatic begin() enabled?
 
-               $e = null; // last exception
+               $e = $ePrior = null; // last exception
                do { // callbacks may add callbacks :)
                        $callbacks = $this->mTrxIdleCallbacks;
                        $this->mTrxIdleCallbacks = array(); // recursion guard
@@ -3285,6 +3354,10 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                                        call_user_func( $phpCallback );
                                        $this->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore automatic begin()
                                } catch ( Exception $e ) {
+                                       if ( $ePrior ) {
+                                               MWExceptionHandler::logException( $ePrior );
+                                       }
+                                       $ePrior = $e;
                                }
                        }
                } while ( count( $this->mTrxIdleCallbacks ) );
@@ -3300,7 +3373,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * @since 1.22
         */
        protected function runOnTransactionPreCommitCallbacks() {
-               $e = null; // last exception
+               $e = $ePrior = null; // last exception
                do { // callbacks may add callbacks :)
                        $callbacks = $this->mTrxPreCommitCallbacks;
                        $this->mTrxPreCommitCallbacks = array(); // recursion guard
@@ -3309,6 +3382,10 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                                        list( $phpCallback ) = $callback;
                                        call_user_func( $phpCallback );
                                } catch ( Exception $e ) {
+                                       if ( $ePrior ) {
+                                               MWExceptionHandler::logException( $ePrior );
+                                       }
+                                       $ePrior = $e;
                                }
                        }
                } while ( count( $this->mTrxPreCommitCallbacks ) );
@@ -4138,7 +4215,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
        /**
         * Encode an expiry time into the DBMS dependent format
         *
-        * @param string $expiry timestamp for expiry, or the 'infinity' string
+        * @param string $expiry Timestamp for expiry, or the 'infinity' string
         * @return string
         */
        public function encodeExpiry( $expiry ) {
@@ -4175,6 +4252,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
 
        /**
         * @since 1.19
+        * @return string
         */
        public function __toString() {
                return (string)$this->mConn;
index be01f1a..3a4bb27 100644 (file)
@@ -340,6 +340,7 @@ class DatabaseMssql extends DatabaseBase {
        }
 
        /**
+        * @param array $err
         * @return string
         */
        private function formatError( $err ) {
@@ -743,7 +744,7 @@ class DatabaseMssql extends DatabaseBase {
        /**
         * UPDATE wrapper. Takes a condition array and a SET array.
         *
-        * @param string $table name of the table to UPDATE. This will be passed through
+        * @param string $table Name of the table to UPDATE. This will be passed through
         *                DatabaseBase::tableName().
         *
         * @param array $values An array of values to SET. For each array element,
@@ -787,7 +788,7 @@ class DatabaseMssql extends DatabaseBase {
 
        /**
         * Makes an encoded list of strings from an array
-        * @param array $a containing the data
+        * @param array $a Containing the data
         * @param int $mode Constant
         *      - LIST_COMMA:          comma separated, no field names
         *      - LIST_AND:            ANDed WHERE clause (without the WHERE). See
@@ -1068,6 +1069,7 @@ class DatabaseMssql extends DatabaseBase {
 
        /**
         * Begin a transaction, committing any previously open transaction
+        * @param string $fname
         */
        protected function doBegin( $fname = __METHOD__ ) {
                sqlsrv_begin_transaction( $this->mConn );
@@ -1076,6 +1078,7 @@ class DatabaseMssql extends DatabaseBase {
 
        /**
         * End a transaction
+        * @param string $fname
         */
        protected function doCommit( $fname = __METHOD__ ) {
                sqlsrv_commit( $this->mConn );
@@ -1085,6 +1088,7 @@ class DatabaseMssql extends DatabaseBase {
        /**
         * Rollback a transaction.
         * No-op on non-transactional databases.
+        * @param string $fname
         */
        protected function doRollback( $fname = __METHOD__ ) {
                sqlsrv_rollback( $this->mConn );
@@ -1177,7 +1181,7 @@ class DatabaseMssql extends DatabaseBase {
        }
 
        /**
-        * @param array $options an associative array of options to be turned into
+        * @param array $options An associative array of options to be turned into
         *   an SQL query, valid keys are listed in the function.
         * @return array
         */
index cf37736..ba0f39f 100644 (file)
@@ -806,8 +806,8 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
        /**
         * Check to see if a named lock is available. This is non-blocking.
         *
-        * @param string $lockName name of lock to poll
-        * @param string $method name of method calling us
+        * @param string $lockName Name of lock to poll
+        * @param string $method Name of method calling us
         * @return bool
         * @since 1.20
         */
@@ -901,7 +901,6 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
 
        /**
         * @param bool $value
-        * @return mixed null|bool|ResultWrapper
         */
        public function setBigSelects( $value = true ) {
                if ( $value === 'default' ) {
@@ -1241,7 +1240,7 @@ class MySQLMasterPos implements DBMasterPos {
        /** @var string */
        public $file;
 
-       /** @var int timestamp */
+       /** @var int Timestamp */
        public $pos;
 
        function __construct( $file, $pos ) {
index b8d5d79..a03c9aa 100644 (file)
@@ -58,14 +58,22 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                }
 
                // Other than mysql_connect, mysqli_real_connect expects an explicit port
-               // parameter. So we need to parse the port out of $realServer
+               // and socket parameters. So we need to parse the port and socket out of
+               // $realServer
                $port = null;
+               $socket = null;
                $hostAndPort = IP::splitHostAndPort( $realServer );
                if ( $hostAndPort ) {
                        $realServer = $hostAndPort[0];
                        if ( $hostAndPort[1] ) {
                                $port = $hostAndPort[1];
                        }
+               } elseif ( substr_count( $realServer, ':' ) == 1 ) {
+                       // If we have a colon and something that's not a port number
+                       // inside the hostname, assume it's the socket location
+                       $hostAndSocket = explode( ':', $realServer );
+                       $realServer = $hostAndSocket[0];
+                       $socket = $hostAndSocket[1];
                }
 
                $connFlags = 0;
@@ -90,7 +98,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                $mysqli->options( MYSQLI_OPT_CONNECT_TIMEOUT, 3 );
 
                if ( $mysqli->real_connect( $realServer, $this->mUser,
-                       $this->mPassword, $this->mDBname, $port, null, $connFlags )
+                       $this->mPassword, $this->mDBname, $port, $socket, $connFlags )
                ) {
                        return $mysqli;
                }
@@ -292,6 +300,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
         * Give an id for the connection
         *
         * mysql driver used resource id, but mysqli objects cannot be cast to string.
+        * @return string
         */
        public function __toString() {
                if ( $this->mConn instanceof Mysqli ) {
index 7686010..f031f78 100644 (file)
@@ -1000,7 +1000,7 @@ class DatabaseOracle extends DatabaseBase {
        }
 
        /**
-        * @return string wikitext of a link to the server software's web site
+        * @return string Wikitext of a link to the server software's web site
         */
        public function getSoftwareLink() {
                return '[{{int:version-db-oracle-url}} Oracle]';
index fe5fa1f..ce14d7a 100644 (file)
@@ -117,6 +117,7 @@ SQL;
 
        /**
         * @since 1.19
+        * @return bool|mixed
         */
        function defaultValue() {
                if ( $this->has_default ) {
@@ -827,8 +828,9 @@ __INDEXATTR__;
         * In Postgres when using FOR UPDATE, only the main table and tables that are inner joined
         * can be locked. That means tables in an outer join cannot be FOR UPDATE locked. Trying to do
         * so causes a DB error. This wrapper checks which tables can be locked and adjusts it accordingly.
-        * 
+        *
         * MySQL uses "ORDER BY NULL" as an optimization hint, but that syntax is illegal in PostgreSQL.
+        * @see DatabaseBase::selectSQLText
         */
        function selectSQLText( $table, $vars, $conds = '', $fname = __METHOD__,
                $options = array(), $join_conds = array()
@@ -1154,7 +1156,7 @@ __INDEXATTR__;
                return wfTimestamp( TS_POSTGRES, $ts );
        }
 
-       /*
+       /**
         * Posted by cc[plus]php[at]c2se[dot]com on 25-Mar-2009 09:12
         * to http://www.php.net/manual/en/ref.pgsql.php
         *
@@ -1201,6 +1203,9 @@ __INDEXATTR__;
 
        /**
         * Return aggregated value function call
+        * @param array $valuedata
+        * @param string $valuename
+        * @return array
         */
        public function aggregateValue( $valuedata, $valuename = 'value' ) {
                return $valuedata;
@@ -1235,7 +1240,7 @@ __INDEXATTR__;
         * @see getSearchPath()
         * @see setSearchPath()
         * @since 1.19
-        * @return array list of actual schemas for the current sesson
+        * @return array List of actual schemas for the current sesson
         */
        function getSchemas() {
                $res = $this->query( "SELECT current_schemas(false)", __METHOD__ );
@@ -1322,7 +1327,7 @@ __INDEXATTR__;
         * Return schema name fore core MediaWiki tables
         *
         * @since 1.19
-        * @return string core schema name
+        * @return string Core schema name
         */
        function getCoreSchema() {
                return $this->mCoreSchema;
@@ -1546,7 +1551,7 @@ SQL;
        /**
         * Various select options
         *
-        * @param array $options an associative array of options to be turned into
+        * @param array $options An associative array of options to be turned into
         *   an SQL query, valid keys are listed in the function.
         * @return array
         */
index 3e063c6..dd2e813 100644 (file)
@@ -342,9 +342,9 @@ class DatabaseSqlite extends DatabaseBase {
         */
        function numFields( $res ) {
                $r = $res instanceof ResultWrapper ? $res->result : $res;
-               if ( is_array($r) && count( $r ) > 0 ){
+               if ( is_array( $r ) && count( $r ) > 0 ) {
                        // The size of the result array is twice the number of fields. (Bug: 65578)
-                       return count( $r[0] ) / 2 ;
+                       return count( $r[0] ) / 2;
                } else {
                        // If the result is empty return 0
                        return 0;
@@ -666,7 +666,7 @@ class DatabaseSqlite extends DatabaseBase {
        }
 
        /**
-        * @return string wikitext of a link to the server software's web site
+        * @return string Wikitext of a link to the server software's web site
         */
        public function getSoftwareLink() {
                return "[{{int:version-db-sqlite-url}} SQLite]";
@@ -873,6 +873,9 @@ class DatabaseSqlite extends DatabaseBase {
                } elseif ( preg_match( '/^\s*DROP INDEX/i', $s ) ) {
                        // DROP INDEX is database-wide, not table-specific, so no ON <table> clause.
                        $s = preg_replace( '/\sON\s+[^\s]*/i', '', $s );
+               } elseif ( preg_match( '/^\s*INSERT IGNORE\b/i', $s ) ) {
+                       // INSERT IGNORE --> INSERT OR IGNORE
+                       $s = preg_replace( '/^\s*INSERT IGNORE\b/i', 'INSERT OR IGNORE', $s );
                }
 
                return $s;
index 36d218a..c1e80d3 100644 (file)
@@ -107,7 +107,7 @@ class ResultWrapper implements Iterator {
        /** @var int */
        protected $pos = 0;
 
-       /** @var */
+       /** @var object|null */
        protected $currentRow = null;
 
        /**
@@ -140,7 +140,7 @@ class ResultWrapper implements Iterator {
         * Fields can be retrieved with $row->fieldname, with fields acting like
         * member variables.
         *
-        * @return object
+        * @return stdClass
         * @throws DBUnexpectedError Thrown if the database returns an error
         */
        function fetchObject() {
@@ -177,8 +177,8 @@ class ResultWrapper implements Iterator {
                $this->db->dataSeek( $this, $row );
        }
 
-       /*********************
-        * Iterator functions
+       /*
+        * ======= Iterator functions =======
         * Note that using these in combination with the non-iterator functions
         * above may cause rows to be skipped or repeated.
         */
@@ -192,7 +192,7 @@ class ResultWrapper implements Iterator {
        }
 
        /**
-        * @return int
+        * @return stdClass|array|bool
         */
        function current() {
                if ( is_null( $this->currentRow ) ) {
@@ -210,7 +210,7 @@ class ResultWrapper implements Iterator {
        }
 
        /**
-        * @return int
+        * @return stdClass
         */
        function next() {
                $this->pos++;
@@ -255,6 +255,9 @@ class FakeResultWrapper extends ResultWrapper {
                return count( $this->result );
        }
 
+       /**
+        * @return array|bool
+        */
        function fetchRow() {
                if ( $this->pos < count( $this->result ) ) {
                        $this->currentRow = $this->result[$this->pos];
@@ -276,7 +279,10 @@ class FakeResultWrapper extends ResultWrapper {
        function free() {
        }
 
-       // Callers want to be able to access fields with $this->fieldName
+       /**
+        * Callers want to be able to access fields with $this->fieldName
+        * @return bool|stdClass
+        */
        function fetchObject() {
                $this->fetchRow();
                if ( $this->currentRow ) {
@@ -291,6 +297,9 @@ class FakeResultWrapper extends ResultWrapper {
                $this->currentRow = null;
        }
 
+       /**
+        * @return bool|stdClass
+        */
        function next() {
                return $this->fetchObject();
        }
index ab1ab79..4dc693a 100644 (file)
@@ -107,7 +107,7 @@ interface IORMTable {
         * @param string|null $functionName
         *
         * @return ORMResult The result set
-        * @throws DBQueryError if the query failed (even if the database was in ignoreErrors mode)
+        * @throws DBQueryError If the query failed (even if the database was in ignoreErrors mode)
         */
        public function select( $fields = null, array $conditions = array(),
                array $options = array(), $functionName = null );
@@ -123,7 +123,7 @@ interface IORMTable {
         * @param array $options
         * @param string|null $functionName
         *
-        * @return array of self
+        * @return array Array of self
         */
        public function selectObjects( $fields = null, array $conditions = array(),
                array $options = array(), $functionName = null );
@@ -139,7 +139,7 @@ interface IORMTable {
         * @param null|string $functionName
         *
         * @return ResultWrapper
-        * @throws DBQueryError if the query failed (even if the database was in ignoreErrors mode)
+        * @throws DBQueryError If the query failed (even if the database was in ignoreErrors mode)
         */
        public function rawSelect( $fields = null, array $conditions = array(),
                array $options = array(), $functionName = null );
@@ -164,7 +164,7 @@ interface IORMTable {
         * @param bool $collapse Set to false to always return each result row as associative array.
         * @param string|null $functionName
         *
-        * @return array of array
+        * @return array Array of array
         */
        public function selectFields( $fields = null, array $conditions = array(),
                array $options = array(), $collapse = true, $functionName = null );
@@ -421,7 +421,7 @@ interface IORMTable {
         *
         * @since 1.20
         *
-        * @param array|string $fields
+        * @param array $fields
         *
         * @return array
         */
index 168d846..73456e2 100644 (file)
@@ -59,7 +59,7 @@ abstract class LBFactory {
         * Returns the LBFactory class to use and the load balancer configuration.
         *
         * @param array $config (e.g. $wgLBFactoryConf)
-        * @return string class name
+        * @return string Class name
         */
        public static function getLBFactoryClass( array $config ) {
                // For configuration backward compatibility after removing
@@ -142,7 +142,7 @@ abstract class LBFactory {
        /**
         * Get a cached (tracked) load balancer for external storage
         *
-        * @param string $cluster external storage cluster, or false for core
+        * @param string $cluster External storage cluster, or false for core
         * @param bool|string $wiki Wiki ID, or false for the current wiki
         * @return LoadBalancer
         */
index bda3dd6..bac9652 100644 (file)
@@ -263,7 +263,7 @@ class LBFactoryMulti extends LBFactory {
        }
 
        /**
-        * @param string $cluster external storage cluster, or false for core
+        * @param string $cluster External storage cluster, or false for core
         * @param bool|string $wiki Wiki ID, or false for the current wiki
         * @return LoadBalancer
         */
index b3f9210..e517a02 100644 (file)
  * @ingroup Database
  */
 class LoadBalancer {
-       private $mServers, $mConns, $mLoads, $mGroupLoads;
+       /** @var array Map of (server index => server config array) */
+       private $mServers;
+       /** @var array Map of (local/foreignUsed/foreignFree => server index => DatabaseBase array) */
+       private $mConns;
+       /** @var array Map of (server index => weight) */
+       private $mLoads;
+       /** @var array Map of (group => server index => weight) */
+       private $mGroupLoads;
+       /** @var bool Whether to disregard slave lag as a factor in slave selection */
+       private $mAllowLagged;
+       /** @var integer Seconds to spend waiting on slave lag to resolve */
+       private $mWaitTimeout;
+
+       /** @var array LBFactory information */
+       private $mParentInfo;
+       /** @var string The LoadMonitor subclass name */
+       private $mLoadMonitorClass;
+       /** @var LoadMonitor */
+       private $mLoadMonitor;
 
        /** @var bool|DatabaseBase Database connection that caused a problem */
        private $mErrorConnection;
-       private $mReadIndex, $mAllowLagged;
-
+       /** @var integer The generic (not query grouped) slave index (of $mServers) */
+       private $mReadIndex;
        /** @var bool|DBMasterPos False if not set */
        private $mWaitForPos;
-
-       private $mWaitTimeout;
-       private $mLaggedSlaveMode, $mLastError = 'Unknown error';
-       private $mParentInfo, $mLagTimes;
-       private $mLoadMonitorClass, $mLoadMonitor;
+       /** @var bool Whether the generic reader fell back to a lagged slave */
+       private $mLaggedSlaveMode;
+       /** @var string The last DB selection or connection error */
+       private $mLastError = 'Unknown error';
+       /** @var array Process cache of LoadMonitor::getLagTimes() */
+       private $mLagTimes;
 
        /**
-        * @param array $params with keys:
+        * @param array $params Array with keys:
         *   servers           Required. Array of server info structures.
         *   loadMonitor       Name of a class used to fetch server lag and load.
         * @throws MWException
@@ -331,17 +350,23 @@ class LoadBalancer {
        /**
         * Set the master wait position and wait for ALL slaves to catch up to it
         * @param DBMasterPos $pos
+        * @param int $timeout Max seconds to wait; default is mWaitTimeout
+        * @return bool Success (able to connect and no timeouts reached)
         */
-       public function waitForAll( $pos ) {
+       public function waitForAll( $pos, $timeout = null ) {
                wfProfileIn( __METHOD__ );
                $this->mWaitForPos = $pos;
                $serverCount = count( $this->mServers );
+
+               $ok = true;
                for ( $i = 1; $i < $serverCount; $i++ ) {
                        if ( $this->mLoads[$i] > 0 ) {
-                               $this->doWait( $i, true );
+                               $ok = $this->doWait( $i, true, $timeout ) && $ok;
                        }
                }
                wfProfileOut( __METHOD__ );
+
+               return $ok;
        }
 
        /**
@@ -363,11 +388,12 @@ class LoadBalancer {
 
        /**
         * Wait for a given slave to catch up to the master pos stored in $this
-        * @param int $index
-        * @param bool $open
+        * @param int $index Server index
+        * @param bool $open Check the server even if a new connection has to be made
+        * @param int $timeout Max seconds to wait; default is mWaitTimeout
         * @return bool
         */
-       protected function doWait( $index, $open = false ) {
+       protected function doWait( $index, $open = false, $timeout = null ) {
                # Find a connection to wait on
                $conn = $this->getAnyOpenConnection( $index );
                if ( !$conn ) {
@@ -386,7 +412,8 @@ class LoadBalancer {
                }
 
                wfDebug( __METHOD__ . ": Waiting for slave #$index to catch up...\n" );
-               $result = $conn->masterPosWait( $this->mWaitForPos, $this->mWaitTimeout );
+               $timeout = $timeout ?: $this->mWaitTimeout;
+               $result = $conn->masterPosWait( $this->mWaitForPos, $timeout );
 
                if ( $result == -1 || is_null( $result ) ) {
                        # Timed out waiting for slave, use master instead
@@ -948,6 +975,14 @@ class LoadBalancer {
                }
        }
 
+       /**
+        * @return bool Whether a master connection is already open
+        * @since 1.24
+        */
+       function hasMasterConnection() {
+               return $this->isOpen( $this->getWriterIndex() );
+       }
+
        /**
         * Determine if there are any pending changes that need to be rolled back
         * or committed.
@@ -1048,8 +1083,22 @@ class LoadBalancer {
                $maxLag = -1;
                $host = '';
                $maxIndex = 0;
-               if ( $this->getServerCount() > 1 ) { // no replication = no lag
+
+               if ( $this->getServerCount() <= 1 ) { // no replication = no lag
+                       return array( $host, $maxLag, $maxIndex );
+               }
+
+               // Try to get the max lag info from the server cache
+               $key = 'loadbalancer:maxlag:cluster:' . $this->mServers[0]['host'];
+               $cache = ObjectCache::newAccelerator( array(), 'hash' );
+               $maxLagInfo = $cache->get( $key ); // (host, lag, index)
+
+               // Fallback to connecting to each slave and getting the lag
+               if ( !$maxLagInfo ) {
                        foreach ( $this->mServers as $i => $conn ) {
+                               if ( $i == $this->getWriterIndex() ) {
+                                       continue; // nothing to check
+                               }
                                $conn = false;
                                if ( $wiki === false ) {
                                        $conn = $this->getAnyOpenConnection( $i );
@@ -1067,9 +1116,11 @@ class LoadBalancer {
                                        $maxIndex = $i;
                                }
                        }
+                       $maxLagInfo = array( $host, $maxLag, $maxIndex );
+                       $cache->set( $key, $maxLagInfo, 5 );
                }
 
-               return array( $host, $maxLag, $maxIndex );
+               return $maxLagInfo;
        }
 
        /**
index fa2dd99..7281485 100644 (file)
@@ -74,9 +74,14 @@ class LoadMonitorNull implements LoadMonitor {
 class LoadMonitorMySQL implements LoadMonitor {
        /** @var LoadBalancer */
        public $parent;
+       /** @var BagOStuff */
+       protected $cache;
 
        public function __construct( $parent ) {
+               global $wgMemc;
+
                $this->parent = $parent;
+               $this->cache = $wgMemc ?: wfGetMainCache();
        }
 
        public function scaleLoads( &$loads, $group = false, $wiki = false ) {
@@ -93,14 +98,10 @@ class LoadMonitorMySQL implements LoadMonitor {
                $expiry = 5;
                $requestRate = 10;
 
-               global $wgMemc;
-               if ( empty( $wgMemc ) ) {
-                       $wgMemc = wfGetMainCache();
-               }
-
+               $cache = $this->cache;
                $masterName = $this->parent->getServerName( 0 );
                $memcKey = wfMemcKey( 'lag_times', $masterName );
-               $times = $wgMemc->get( $memcKey );
+               $times = $cache->get( $memcKey );
                if ( is_array( $times ) ) {
                        # Randomly recache with probability rising over $expiry
                        $elapsed = time() - $times['timestamp'];
@@ -116,10 +117,10 @@ class LoadMonitorMySQL implements LoadMonitor {
                }
 
                # Cache key missing or expired
-               if ( $wgMemc->add( "$memcKey:lock", 1, 10 ) ) {
+               if ( $cache->add( "$memcKey:lock", 1, 10 ) ) {
                        # Let this process alone update the cache value
-                       $unlocker = new ScopedCallback( function () use ( $wgMemc, $memcKey ) {
-                               $wgMemc->delete( $memcKey );
+                       $unlocker = new ScopedCallback( function () use ( $cache, $memcKey ) {
+                               $cache->delete( $memcKey );
                        } );
                } elseif ( is_array( $times ) ) {
                        # Could not acquire lock but an old cache exists, so use it
@@ -136,12 +137,17 @@ class LoadMonitorMySQL implements LoadMonitor {
                                $times[$i] = $conn->getLag();
                        } elseif ( false !== ( $conn = $this->parent->openConnection( $i, $wiki ) ) ) {
                                $times[$i] = $conn->getLag();
+                               // Close the connection to avoid sleeper connections piling up.
+                               // Note that the caller will pick one of these DBs and reconnect,
+                               // which is slightly inefficient, but this only matters for the lag
+                               // time cache miss cache, which is far less common that cache hits.
+                               $this->parent->closeConnection( $conn );
                        }
                }
 
                # Add a timestamp key so we know when it was cached
                $times['timestamp'] = time();
-               $wgMemc->set( $memcKey, $times, $expiry + 10 );
+               $cache->set( $memcKey, $times, $expiry + 10 );
                unset( $times['timestamp'] ); // hide from caller
 
                return $times;
index 51b81da..2f898b7 100644 (file)
@@ -220,8 +220,8 @@ class ORMTable extends DBAccessBase implements IORMTable {
         * @param array $options
         * @param string|null $functionName
         *
-        * @return array of row objects
-        * @throws DBQueryError if the query failed (even if the database was in ignoreErrors mode).
+        * @return array Array of row objects
+        * @throws DBQueryError If the query failed (even if the database was in ignoreErrors mode).
         */
        public function selectObjects( $fields = null, array $conditions = array(),
                array $options = array(), $functionName = null
@@ -247,7 +247,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
         * @param array $options
         * @param null|string $functionName
         * @return ResultWrapper
-        * @throws DBQueryError if the query failed (even if the database was in
+        * @throws DBQueryError If the query failed (even if the database was in
         *   ignoreErrors mode).
         */
        public function rawSelect( $fields = null, array $conditions = array(),
@@ -314,7 +314,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
         * @param bool $collapse Set to false to always return each result row as associative array.
         * @param string|null $functionName
         *
-        * @return array of array
+        * @return array Array of array
         */
        public function selectFields( $fields = null, array $conditions = array(),
                array $options = array(), $collapse = true, $functionName = null
@@ -648,7 +648,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
         *
         * @see LoadBalancer::reuseConnection
         *
-        * @param DatabaseBase $db the database
+        * @param DatabaseBase $db
         *
         * @since 1.20
         */
@@ -748,7 +748,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
         *
         * @since 1.20
         *
-        * @param array|string $fields
+        * @param array $fields
         *
         * @return array
         */
diff --git a/includes/debug/Debug.php b/includes/debug/Debug.php
deleted file mode 100644 (file)
index 0cea658..0000000
+++ /dev/null
@@ -1,562 +0,0 @@
-<?php
-/**
- * Debug toolbar related code.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * New debugger system that outputs a toolbar on page view.
- *
- * By default, most methods do nothing ( self::$enabled = false ). You have
- * to explicitly call MWDebug::init() to enabled them.
- *
- * @todo Profiler support
- *
- * @since 1.19
- */
-class MWDebug {
-       /**
-        * Log lines
-        *
-        * @var array $log
-        */
-       protected static $log = array();
-
-       /**
-        * Debug messages from wfDebug().
-        *
-        * @var array $debug
-        */
-       protected static $debug = array();
-
-       /**
-        * SQL statements of the databses queries.
-        *
-        * @var array $query
-        */
-       protected static $query = array();
-
-       /**
-        * Is the debugger enabled?
-        *
-        * @var bool $enabled
-        */
-       protected static $enabled = false;
-
-       /**
-        * Array of functions that have already been warned, formatted
-        * function-caller to prevent a buttload of warnings
-        *
-        * @var array $deprecationWarnings
-        */
-       protected static $deprecationWarnings = array();
-
-       /**
-        * Enabled the debugger and load resource module.
-        * This is called by Setup.php when $wgDebugToolbar is true.
-        *
-        * @since 1.19
-        */
-       public static function init() {
-               self::$enabled = true;
-       }
-
-       /**
-        * Add ResourceLoader modules to the OutputPage object if debugging is
-        * enabled.
-        *
-        * @since 1.19
-        * @param OutputPage $out
-        */
-       public static function addModules( OutputPage $out ) {
-               if ( self::$enabled ) {
-                       $out->addModules( 'mediawiki.debug.init' );
-               }
-       }
-
-       /**
-        * Adds a line to the log
-        *
-        * @todo Add support for passing objects
-        *
-        * @since 1.19
-        * @param string $str
-        */
-       public static function log( $str ) {
-               if ( !self::$enabled ) {
-                       return;
-               }
-
-               self::$log[] = array(
-                       'msg' => htmlspecialchars( $str ),
-                       'type' => 'log',
-                       'caller' => wfGetCaller(),
-               );
-       }
-
-       /**
-        * Returns internal log array
-        * @since 1.19
-        * @return array
-        */
-       public static function getLog() {
-               return self::$log;
-       }
-
-       /**
-        * Clears internal log array and deprecation tracking
-        * @since 1.19
-        */
-       public static function clearLog() {
-               self::$log = array();
-               self::$deprecationWarnings = array();
-       }
-
-       /**
-        * Adds a warning entry to the log
-        *
-        * @since 1.19
-        * @param string $msg
-        * @param int $callerOffset
-        * @param int $level A PHP error level. See sendMessage()
-        * @param string $log 'production' will always trigger a php error, 'auto'
-        *    will trigger an error if $wgDevelopmentWarnings is true, and 'debug'
-        *    will only write to the debug log(s).
-        *
-        * @return mixed
-        */
-       public static function warning( $msg, $callerOffset = 1, $level = E_USER_NOTICE, $log = 'auto' ) {
-               global $wgDevelopmentWarnings;
-
-               if ( $log === 'auto' && !$wgDevelopmentWarnings ) {
-                       $log = 'debug';
-               }
-
-               if ( $log === 'debug' ) {
-                       $level = false;
-               }
-
-               $callerDescription = self::getCallerDescription( $callerOffset );
-
-               self::sendMessage( $msg, $callerDescription, 'warning', $level );
-
-               if ( self::$enabled ) {
-                       self::$log[] = array(
-                               'msg' => htmlspecialchars( $msg ),
-                               'type' => 'warn',
-                               'caller' => $callerDescription['func'],
-                       );
-               }
-       }
-
-       /**
-        * Show a warning that $function is deprecated.
-        * This will send it to the following locations:
-        * - Debug toolbar, with one item per function and caller, if $wgDebugToolbar
-        *   is set to true.
-        * - PHP's error log, with level E_USER_DEPRECATED, if $wgDevelopmentWarnings
-        *   is set to true.
-        * - MediaWiki's debug log, if $wgDevelopmentWarnings is set to false.
-        *
-        * @since 1.19
-        * @param string $function Function that is deprecated.
-        * @param string|bool $version Version in which the function was deprecated.
-        * @param string|bool $component Component to which the function belongs.
-        *    If false, it is assumbed the function is in MediaWiki core.
-        * @param int $callerOffset How far up the callstack is the original
-        *    caller. 2 = function that called the function that called
-        *    MWDebug::deprecated() (Added in 1.20).
-        * @return mixed
-        */
-       public static function deprecated( $function, $version = false,
-               $component = false, $callerOffset = 2
-       ) {
-               $callerDescription = self::getCallerDescription( $callerOffset );
-               $callerFunc = $callerDescription['func'];
-
-               $sendToLog = true;
-
-               // Check to see if there already was a warning about this function
-               if ( isset( self::$deprecationWarnings[$function][$callerFunc] ) ) {
-                       return;
-               } elseif ( isset( self::$deprecationWarnings[$function] ) ) {
-                       if ( self::$enabled ) {
-                               $sendToLog = false;
-                       } else {
-                               return;
-                       }
-               }
-
-               self::$deprecationWarnings[$function][$callerFunc] = true;
-
-               if ( $version ) {
-                       global $wgDeprecationReleaseLimit;
-                       if ( $wgDeprecationReleaseLimit && $component === false ) {
-                               # Strip -* off the end of $version so that branches can use the
-                               # format #.##-branchname to avoid issues if the branch is merged into
-                               # a version of MediaWiki later than what it was branched from
-                               $comparableVersion = preg_replace( '/-.*$/', '', $version );
-
-                               # If the comparableVersion is larger than our release limit then
-                               # skip the warning message for the deprecation
-                               if ( version_compare( $wgDeprecationReleaseLimit, $comparableVersion, '<' ) ) {
-                                       $sendToLog = false;
-                               }
-                       }
-
-                       $component = $component === false ? 'MediaWiki' : $component;
-                       $msg = "Use of $function was deprecated in $component $version.";
-               } else {
-                       $msg = "Use of $function is deprecated.";
-               }
-
-               if ( $sendToLog ) {
-                       global $wgDevelopmentWarnings; // we could have a more specific $wgDeprecationWarnings setting.
-                       self::sendMessage(
-                               $msg,
-                               $callerDescription,
-                               'deprecated',
-                               $wgDevelopmentWarnings ? E_USER_DEPRECATED : false
-                       );
-               }
-
-               if ( self::$enabled ) {
-                       $logMsg = htmlspecialchars( $msg ) .
-                               Html::rawElement( 'div', array( 'class' => 'mw-debug-backtrace' ),
-                                       Html::element( 'span', array(), 'Backtrace:' ) . wfBacktrace()
-                               );
-
-                       self::$log[] = array(
-                               'msg' => $logMsg,
-                               'type' => 'deprecated',
-                               'caller' => $callerFunc,
-                       );
-               }
-       }
-
-       /**
-        * Get an array describing the calling function at a specified offset.
-        *
-        * @param int $callerOffset How far up the callstack is the original
-        *    caller. 0 = function that called getCallerDescription()
-        * @return array Array with two keys: 'file' and 'func'
-        */
-       private static function getCallerDescription( $callerOffset ) {
-               $callers = wfDebugBacktrace();
-
-               if ( isset( $callers[$callerOffset] ) ) {
-                       $callerfile = $callers[$callerOffset];
-                       if ( isset( $callerfile['file'] ) && isset( $callerfile['line'] ) ) {
-                               $file = $callerfile['file'] . ' at line ' . $callerfile['line'];
-                       } else {
-                               $file = '(internal function)';
-                       }
-               } else {
-                       $file = '(unknown location)';
-               }
-
-               if ( isset( $callers[$callerOffset + 1] ) ) {
-                       $callerfunc = $callers[$callerOffset + 1];
-                       $func = '';
-                       if ( isset( $callerfunc['class'] ) ) {
-                               $func .= $callerfunc['class'] . '::';
-                       }
-                       if ( isset( $callerfunc['function'] ) ) {
-                               $func .= $callerfunc['function'];
-                       }
-               } else {
-                       $func = 'unknown';
-               }
-
-               return array( 'file' => $file, 'func' => $func );
-       }
-
-       /**
-        * Send a message to the debug log and optionally also trigger a PHP
-        * error, depending on the $level argument.
-        *
-        * @param string $msg Message to send
-        * @param array $caller Caller description get from getCallerDescription()
-        * @param string $group Log group on which to send the message
-        * @param int|bool $level Error level to use; set to false to not trigger an error
-        */
-       private static function sendMessage( $msg, $caller, $group, $level ) {
-               $msg .= ' [Called from ' . $caller['func'] . ' in ' . $caller['file'] . ']';
-
-               if ( $level !== false ) {
-                       trigger_error( $msg, $level );
-               }
-
-               wfDebugLog( $group, $msg, 'log' );
-       }
-
-       /**
-        * This is a method to pass messages from wfDebug to the pretty debugger.
-        * Do NOT use this method, use MWDebug::log or wfDebug()
-        *
-        * @since 1.19
-        * @param string $str
-        */
-       public static function debugMsg( $str ) {
-               global $wgDebugComments, $wgShowDebug;
-
-               if ( self::$enabled || $wgDebugComments || $wgShowDebug ) {
-                       self::$debug[] = rtrim( UtfNormal::cleanUp( $str ) );
-               }
-       }
-
-       /**
-        * Begins profiling on a database query
-        *
-        * @since 1.19
-        * @param string $sql
-        * @param string $function
-        * @param bool $isMaster
-        * @return int ID number of the query to pass to queryTime or -1 if the
-        *  debugger is disabled
-        */
-       public static function query( $sql, $function, $isMaster ) {
-               if ( !self::$enabled ) {
-                       return -1;
-               }
-
-               self::$query[] = array(
-                       'sql' => $sql,
-                       'function' => $function,
-                       'master' => (bool)$isMaster,
-                       'time' => 0.0,
-                       '_start' => microtime( true ),
-               );
-
-               return count( self::$query ) - 1;
-       }
-
-       /**
-        * Calculates how long a query took.
-        *
-        * @since 1.19
-        * @param int $id
-        */
-       public static function queryTime( $id ) {
-               if ( $id === -1 || !self::$enabled ) {
-                       return;
-               }
-
-               self::$query[$id]['time'] = microtime( true ) - self::$query[$id]['_start'];
-               unset( self::$query[$id]['_start'] );
-       }
-
-       /**
-        * Returns a list of files included, along with their size
-        *
-        * @param IContextSource $context
-        * @return array
-        */
-       protected static function getFilesIncluded( IContextSource $context ) {
-               $files = get_included_files();
-               $fileList = array();
-               foreach ( $files as $file ) {
-                       $size = filesize( $file );
-                       $fileList[] = array(
-                               'name' => $file,
-                               'size' => $context->getLanguage()->formatSize( $size ),
-                       );
-               }
-
-               return $fileList;
-       }
-
-       /**
-        * Returns the HTML to add to the page for the toolbar
-        *
-        * @since 1.19
-        * @param IContextSource $context
-        * @return string
-        */
-       public static function getDebugHTML( IContextSource $context ) {
-               global $wgDebugComments;
-
-               $html = '';
-
-               if ( self::$enabled ) {
-                       MWDebug::log( 'MWDebug output complete' );
-                       $debugInfo = self::getDebugInfo( $context );
-
-                       // Cannot use OutputPage::addJsConfigVars because those are already outputted
-                       // by the time this method is called.
-                       $html = Html::inlineScript(
-                               ResourceLoader::makeLoaderConditionalScript(
-                                       ResourceLoader::makeConfigSetScript( array( 'debugInfo' => $debugInfo ) )
-                               )
-                       );
-               }
-
-               if ( $wgDebugComments ) {
-                       $html .= "<!-- Debug output:\n" .
-                               htmlspecialchars( implode( "\n", self::$debug ) ) .
-                               "\n\n-->";
-               }
-
-               return $html;
-       }
-
-       /**
-        * Generate debug log in HTML for displaying at the bottom of the main
-        * content area.
-        * If $wgShowDebug is false, an empty string is always returned.
-        *
-        * @since 1.20
-        * @return string HTML fragment
-        */
-       public static function getHTMLDebugLog() {
-               global $wgDebugTimestamps, $wgShowDebug;
-
-               if ( !$wgShowDebug ) {
-                       return '';
-               }
-
-               $curIdent = 0;
-               $ret = "\n<hr />\n<strong>Debug data:</strong><ul id=\"mw-debug-html\">\n<li>";
-
-               foreach ( self::$debug as $line ) {
-                       $pre = '';
-                       if ( $wgDebugTimestamps ) {
-                               $matches = array();
-                               if ( preg_match( '/^(\d+\.\d+ {1,3}\d+.\dM\s{2})/', $line, $matches ) ) {
-                                       $pre = $matches[1];
-                                       $line = substr( $line, strlen( $pre ) );
-                               }
-                       }
-                       $display = ltrim( $line );
-                       $ident = strlen( $line ) - strlen( $display );
-                       $diff = $ident - $curIdent;
-
-                       $display = $pre . $display;
-                       if ( $display == '' ) {
-                               $display = "\xc2\xa0";
-                       }
-
-                       if ( !$ident
-                               && $diff < 0
-                               && substr( $display, 0, 9 ) != 'Entering '
-                               && substr( $display, 0, 8 ) != 'Exiting '
-                       ) {
-                               $ident = $curIdent;
-                               $diff = 0;
-                               $display = '<span style="background:yellow;">' .
-                                       nl2br( htmlspecialchars( $display ) ) . '</span>';
-                       } else {
-                               $display = nl2br( htmlspecialchars( $display ) );
-                       }
-
-                       if ( $diff < 0 ) {
-                               $ret .= str_repeat( "</li></ul>\n", -$diff ) . "</li><li>\n";
-                       } elseif ( $diff == 0 ) {
-                               $ret .= "</li><li>\n";
-                       } else {
-                               $ret .= str_repeat( "<ul><li>\n", $diff );
-                       }
-                       $ret .= "<code>$display</code>\n";
-
-                       $curIdent = $ident;
-               }
-
-               $ret .= str_repeat( '</li></ul>', $curIdent ) . "</li>\n</ul>\n";
-
-               return $ret;
-       }
-
-       /**
-        * Append the debug info to given ApiResult
-        *
-        * @param IContextSource $context
-        * @param ApiResult $result
-        */
-       public static function appendDebugInfoToApiResult( IContextSource $context, ApiResult $result ) {
-               if ( !self::$enabled ) {
-                       return;
-               }
-
-               // output errors as debug info, when display_errors is on
-               // this is necessary for all non html output of the api, because that clears all errors first
-               $obContents = ob_get_contents();
-               if ( $obContents ) {
-                       $obContentArray = explode( '<br />', $obContents );
-                       foreach ( $obContentArray as $obContent ) {
-                               if ( trim( $obContent ) ) {
-                                       self::debugMsg( Sanitizer::stripAllTags( $obContent ) );
-                               }
-                       }
-               }
-
-               MWDebug::log( 'MWDebug output complete' );
-               $debugInfo = self::getDebugInfo( $context );
-
-               $result->setIndexedTagName( $debugInfo, 'debuginfo' );
-               $result->setIndexedTagName( $debugInfo['log'], 'line' );
-               $result->setIndexedTagName( $debugInfo['debugLog'], 'msg' );
-               $result->setIndexedTagName( $debugInfo['queries'], 'query' );
-               $result->setIndexedTagName( $debugInfo['includes'], 'queries' );
-               $result->setIndexedTagName( $debugInfo['profile'], 'function' );
-               $result->addValue( null, 'debuginfo', $debugInfo );
-       }
-
-       /**
-        * Returns the HTML to add to the page for the toolbar
-        *
-        * @param IContextSource $context
-        * @return array
-        */
-       public static function getDebugInfo( IContextSource $context ) {
-               if ( !self::$enabled ) {
-                       return array();
-               }
-
-               global $wgVersion, $wgRequestTime;
-               $request = $context->getRequest();
-
-               // HHVM's reported memory usage from memory_get_peak_usage()
-               // is not useful when passing false, but we continue passing
-               // false for consistency of historical data in zend.
-               // see: https://github.com/facebook/hhvm/issues/2257#issuecomment-39362246
-               $realMemoryUsage = wfIsHHVM();
-
-               return array(
-                       'mwVersion' => $wgVersion,
-                       'phpVersion' => PHP_VERSION,
-                       'gitRevision' => GitInfo::headSHA1(),
-                       'gitBranch' => GitInfo::currentBranch(),
-                       'gitViewUrl' => GitInfo::headViewUrl(),
-                       'time' => microtime( true ) - $wgRequestTime,
-                       'log' => self::$log,
-                       'debugLog' => self::$debug,
-                       'queries' => self::$query,
-                       'request' => array(
-                               'method' => $request->getMethod(),
-                               'url' => $request->getRequestURL(),
-                               'headers' => $request->getAllHeaders(),
-                               'params' => $request->getValues(),
-                       ),
-                       'memory' => $context->getLanguage()->formatSize( memory_get_usage( $realMemoryUsage ) ),
-                       'memoryPeak' => $context->getLanguage()->formatSize( memory_get_peak_usage( $realMemoryUsage ) ),
-                       'includes' => self::getFilesIncluded( $context ),
-                       'profile' => Profiler::instance()->getRawData(),
-               );
-       }
-}
diff --git a/includes/debug/MWDebug.php b/includes/debug/MWDebug.php
new file mode 100644 (file)
index 0000000..c2f2223
--- /dev/null
@@ -0,0 +1,584 @@
+<?php
+/**
+ * Debug toolbar related code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * New debugger system that outputs a toolbar on page view.
+ *
+ * By default, most methods do nothing ( self::$enabled = false ). You have
+ * to explicitly call MWDebug::init() to enabled them.
+ *
+ * @todo Profiler support
+ *
+ * @since 1.19
+ */
+class MWDebug {
+       /**
+        * Log lines
+        *
+        * @var array $log
+        */
+       protected static $log = array();
+
+       /**
+        * Debug messages from wfDebug().
+        *
+        * @var array $debug
+        */
+       protected static $debug = array();
+
+       /**
+        * SQL statements of the databses queries.
+        *
+        * @var array $query
+        */
+       protected static $query = array();
+
+       /**
+        * Is the debugger enabled?
+        *
+        * @var bool $enabled
+        */
+       protected static $enabled = false;
+
+       /**
+        * Array of functions that have already been warned, formatted
+        * function-caller to prevent a buttload of warnings
+        *
+        * @var array $deprecationWarnings
+        */
+       protected static $deprecationWarnings = array();
+
+       /**
+        * Enabled the debugger and load resource module.
+        * This is called by Setup.php when $wgDebugToolbar is true.
+        *
+        * @since 1.19
+        */
+       public static function init() {
+               self::$enabled = true;
+       }
+
+       /**
+        * Add ResourceLoader modules to the OutputPage object if debugging is
+        * enabled.
+        *
+        * @since 1.19
+        * @param OutputPage $out
+        */
+       public static function addModules( OutputPage $out ) {
+               if ( self::$enabled ) {
+                       $out->addModules( 'mediawiki.debug.init' );
+               }
+       }
+
+       /**
+        * Adds a line to the log
+        *
+        * @todo Add support for passing objects
+        *
+        * @since 1.19
+        * @param string $str
+        */
+       public static function log( $str ) {
+               if ( !self::$enabled ) {
+                       return;
+               }
+
+               self::$log[] = array(
+                       'msg' => htmlspecialchars( $str ),
+                       'type' => 'log',
+                       'caller' => wfGetCaller(),
+               );
+       }
+
+       /**
+        * Returns internal log array
+        * @since 1.19
+        * @return array
+        */
+       public static function getLog() {
+               return self::$log;
+       }
+
+       /**
+        * Clears internal log array and deprecation tracking
+        * @since 1.19
+        */
+       public static function clearLog() {
+               self::$log = array();
+               self::$deprecationWarnings = array();
+       }
+
+       /**
+        * Adds a warning entry to the log
+        *
+        * @since 1.19
+        * @param string $msg
+        * @param int $callerOffset
+        * @param int $level A PHP error level. See sendMessage()
+        * @param string $log 'production' will always trigger a php error, 'auto'
+        *    will trigger an error if $wgDevelopmentWarnings is true, and 'debug'
+        *    will only write to the debug log(s).
+        *
+        * @return mixed
+        */
+       public static function warning( $msg, $callerOffset = 1, $level = E_USER_NOTICE, $log = 'auto' ) {
+               global $wgDevelopmentWarnings;
+
+               if ( $log === 'auto' && !$wgDevelopmentWarnings ) {
+                       $log = 'debug';
+               }
+
+               if ( $log === 'debug' ) {
+                       $level = false;
+               }
+
+               $callerDescription = self::getCallerDescription( $callerOffset );
+
+               self::sendMessage( $msg, $callerDescription, 'warning', $level );
+
+               if ( self::$enabled ) {
+                       self::$log[] = array(
+                               'msg' => htmlspecialchars( $msg ),
+                               'type' => 'warn',
+                               'caller' => $callerDescription['func'],
+                       );
+               }
+       }
+
+       /**
+        * Show a warning that $function is deprecated.
+        * This will send it to the following locations:
+        * - Debug toolbar, with one item per function and caller, if $wgDebugToolbar
+        *   is set to true.
+        * - PHP's error log, with level E_USER_DEPRECATED, if $wgDevelopmentWarnings
+        *   is set to true.
+        * - MediaWiki's debug log, if $wgDevelopmentWarnings is set to false.
+        *
+        * @since 1.19
+        * @param string $function Function that is deprecated.
+        * @param string|bool $version Version in which the function was deprecated.
+        * @param string|bool $component Component to which the function belongs.
+        *    If false, it is assumbed the function is in MediaWiki core.
+        * @param int $callerOffset How far up the callstack is the original
+        *    caller. 2 = function that called the function that called
+        *    MWDebug::deprecated() (Added in 1.20).
+        */
+       public static function deprecated( $function, $version = false,
+               $component = false, $callerOffset = 2
+       ) {
+               $callerDescription = self::getCallerDescription( $callerOffset );
+               $callerFunc = $callerDescription['func'];
+
+               $sendToLog = true;
+
+               // Check to see if there already was a warning about this function
+               if ( isset( self::$deprecationWarnings[$function][$callerFunc] ) ) {
+                       return;
+               } elseif ( isset( self::$deprecationWarnings[$function] ) ) {
+                       if ( self::$enabled ) {
+                               $sendToLog = false;
+                       } else {
+                               return;
+                       }
+               }
+
+               self::$deprecationWarnings[$function][$callerFunc] = true;
+
+               if ( $version ) {
+                       global $wgDeprecationReleaseLimit;
+                       if ( $wgDeprecationReleaseLimit && $component === false ) {
+                               # Strip -* off the end of $version so that branches can use the
+                               # format #.##-branchname to avoid issues if the branch is merged into
+                               # a version of MediaWiki later than what it was branched from
+                               $comparableVersion = preg_replace( '/-.*$/', '', $version );
+
+                               # If the comparableVersion is larger than our release limit then
+                               # skip the warning message for the deprecation
+                               if ( version_compare( $wgDeprecationReleaseLimit, $comparableVersion, '<' ) ) {
+                                       $sendToLog = false;
+                               }
+                       }
+
+                       $component = $component === false ? 'MediaWiki' : $component;
+                       $msg = "Use of $function was deprecated in $component $version.";
+               } else {
+                       $msg = "Use of $function is deprecated.";
+               }
+
+               if ( $sendToLog ) {
+                       global $wgDevelopmentWarnings; // we could have a more specific $wgDeprecationWarnings setting.
+                       self::sendMessage(
+                               $msg,
+                               $callerDescription,
+                               'deprecated',
+                               $wgDevelopmentWarnings ? E_USER_DEPRECATED : false
+                       );
+               }
+
+               if ( self::$enabled ) {
+                       $logMsg = htmlspecialchars( $msg ) .
+                               Html::rawElement( 'div', array( 'class' => 'mw-debug-backtrace' ),
+                                       Html::element( 'span', array(), 'Backtrace:' ) . wfBacktrace()
+                               );
+
+                       self::$log[] = array(
+                               'msg' => $logMsg,
+                               'type' => 'deprecated',
+                               'caller' => $callerFunc,
+                       );
+               }
+       }
+
+       /**
+        * Get an array describing the calling function at a specified offset.
+        *
+        * @param int $callerOffset How far up the callstack is the original
+        *    caller. 0 = function that called getCallerDescription()
+        * @return array Array with two keys: 'file' and 'func'
+        */
+       private static function getCallerDescription( $callerOffset ) {
+               $callers = wfDebugBacktrace();
+
+               if ( isset( $callers[$callerOffset] ) ) {
+                       $callerfile = $callers[$callerOffset];
+                       if ( isset( $callerfile['file'] ) && isset( $callerfile['line'] ) ) {
+                               $file = $callerfile['file'] . ' at line ' . $callerfile['line'];
+                       } else {
+                               $file = '(internal function)';
+                       }
+               } else {
+                       $file = '(unknown location)';
+               }
+
+               if ( isset( $callers[$callerOffset + 1] ) ) {
+                       $callerfunc = $callers[$callerOffset + 1];
+                       $func = '';
+                       if ( isset( $callerfunc['class'] ) ) {
+                               $func .= $callerfunc['class'] . '::';
+                       }
+                       if ( isset( $callerfunc['function'] ) ) {
+                               $func .= $callerfunc['function'];
+                       }
+               } else {
+                       $func = 'unknown';
+               }
+
+               return array( 'file' => $file, 'func' => $func );
+       }
+
+       /**
+        * Send a message to the debug log and optionally also trigger a PHP
+        * error, depending on the $level argument.
+        *
+        * @param string $msg Message to send
+        * @param array $caller Caller description get from getCallerDescription()
+        * @param string $group Log group on which to send the message
+        * @param int|bool $level Error level to use; set to false to not trigger an error
+        */
+       private static function sendMessage( $msg, $caller, $group, $level ) {
+               $msg .= ' [Called from ' . $caller['func'] . ' in ' . $caller['file'] . ']';
+
+               if ( $level !== false ) {
+                       trigger_error( $msg, $level );
+               }
+
+               wfDebugLog( $group, $msg, 'log' );
+       }
+
+       /**
+        * This is a method to pass messages from wfDebug to the pretty debugger.
+        * Do NOT use this method, use MWDebug::log or wfDebug()
+        *
+        * @since 1.19
+        * @param string $str
+        */
+       public static function debugMsg( $str ) {
+               global $wgDebugComments, $wgShowDebug;
+
+               if ( self::$enabled || $wgDebugComments || $wgShowDebug ) {
+                       self::$debug[] = rtrim( UtfNormal::cleanUp( $str ) );
+               }
+       }
+
+       /**
+        * Begins profiling on a database query
+        *
+        * @since 1.19
+        * @param string $sql
+        * @param string $function
+        * @param bool $isMaster
+        * @return int ID number of the query to pass to queryTime or -1 if the
+        *  debugger is disabled
+        */
+       public static function query( $sql, $function, $isMaster ) {
+               if ( !self::$enabled ) {
+                       return -1;
+               }
+
+               // Replace invalid UTF-8 chars with a square UTF-8 character
+               // This prevents json_encode from erroring out due to binary SQL data
+               $sql = preg_replace(
+                       '/(
+                               [\xC0-\xC1] # Invalid UTF-8 Bytes
+                               | [\xF5-\xFF] # Invalid UTF-8 Bytes
+                               | \xE0[\x80-\x9F] # Overlong encoding of prior code point
+                               | \xF0[\x80-\x8F] # Overlong encoding of prior code point
+                               | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
+                               | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
+                               | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
+                               | (?<=[\x0-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
+                               | (?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]
+                                  |[\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence
+                               | (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence
+                               | (?<=[\xF0-\xF4])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence
+                               | (?<=[\xF0-\xF4][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2)
+                       )/x',
+                       '■',
+                       $sql
+               );
+
+               self::$query[] = array(
+                       'sql' => $sql,
+                       'function' => $function,
+                       'master' => (bool)$isMaster,
+                       'time' => 0.0,
+                       '_start' => microtime( true ),
+               );
+
+               return count( self::$query ) - 1;
+       }
+
+       /**
+        * Calculates how long a query took.
+        *
+        * @since 1.19
+        * @param int $id
+        */
+       public static function queryTime( $id ) {
+               if ( $id === -1 || !self::$enabled ) {
+                       return;
+               }
+
+               self::$query[$id]['time'] = microtime( true ) - self::$query[$id]['_start'];
+               unset( self::$query[$id]['_start'] );
+       }
+
+       /**
+        * Returns a list of files included, along with their size
+        *
+        * @param IContextSource $context
+        * @return array
+        */
+       protected static function getFilesIncluded( IContextSource $context ) {
+               $files = get_included_files();
+               $fileList = array();
+               foreach ( $files as $file ) {
+                       $size = filesize( $file );
+                       $fileList[] = array(
+                               'name' => $file,
+                               'size' => $context->getLanguage()->formatSize( $size ),
+                       );
+               }
+
+               return $fileList;
+       }
+
+       /**
+        * Returns the HTML to add to the page for the toolbar
+        *
+        * @since 1.19
+        * @param IContextSource $context
+        * @return string
+        */
+       public static function getDebugHTML( IContextSource $context ) {
+               global $wgDebugComments;
+
+               $html = '';
+
+               if ( self::$enabled ) {
+                       MWDebug::log( 'MWDebug output complete' );
+                       $debugInfo = self::getDebugInfo( $context );
+
+                       // Cannot use OutputPage::addJsConfigVars because those are already outputted
+                       // by the time this method is called.
+                       $html = Html::inlineScript(
+                               ResourceLoader::makeLoaderConditionalScript(
+                                       ResourceLoader::makeConfigSetScript( array( 'debugInfo' => $debugInfo ) )
+                               )
+                       );
+               }
+
+               if ( $wgDebugComments ) {
+                       $html .= "<!-- Debug output:\n" .
+                               htmlspecialchars( implode( "\n", self::$debug ) ) .
+                               "\n\n-->";
+               }
+
+               return $html;
+       }
+
+       /**
+        * Generate debug log in HTML for displaying at the bottom of the main
+        * content area.
+        * If $wgShowDebug is false, an empty string is always returned.
+        *
+        * @since 1.20
+        * @return string HTML fragment
+        */
+       public static function getHTMLDebugLog() {
+               global $wgDebugTimestamps, $wgShowDebug;
+
+               if ( !$wgShowDebug ) {
+                       return '';
+               }
+
+               $curIdent = 0;
+               $ret = "\n<hr />\n<strong>Debug data:</strong><ul id=\"mw-debug-html\">\n<li>";
+
+               foreach ( self::$debug as $line ) {
+                       $pre = '';
+                       if ( $wgDebugTimestamps ) {
+                               $matches = array();
+                               if ( preg_match( '/^(\d+\.\d+ {1,3}\d+.\dM\s{2})/', $line, $matches ) ) {
+                                       $pre = $matches[1];
+                                       $line = substr( $line, strlen( $pre ) );
+                               }
+                       }
+                       $display = ltrim( $line );
+                       $ident = strlen( $line ) - strlen( $display );
+                       $diff = $ident - $curIdent;
+
+                       $display = $pre . $display;
+                       if ( $display == '' ) {
+                               $display = "\xc2\xa0";
+                       }
+
+                       if ( !$ident
+                               && $diff < 0
+                               && substr( $display, 0, 9 ) != 'Entering '
+                               && substr( $display, 0, 8 ) != 'Exiting '
+                       ) {
+                               $ident = $curIdent;
+                               $diff = 0;
+                               $display = '<span style="background:yellow;">' .
+                                       nl2br( htmlspecialchars( $display ) ) . '</span>';
+                       } else {
+                               $display = nl2br( htmlspecialchars( $display ) );
+                       }
+
+                       if ( $diff < 0 ) {
+                               $ret .= str_repeat( "</li></ul>\n", -$diff ) . "</li><li>\n";
+                       } elseif ( $diff == 0 ) {
+                               $ret .= "</li><li>\n";
+                       } else {
+                               $ret .= str_repeat( "<ul><li>\n", $diff );
+                       }
+                       $ret .= "<code>$display</code>\n";
+
+                       $curIdent = $ident;
+               }
+
+               $ret .= str_repeat( '</li></ul>', $curIdent ) . "</li>\n</ul>\n";
+
+               return $ret;
+       }
+
+       /**
+        * Append the debug info to given ApiResult
+        *
+        * @param IContextSource $context
+        * @param ApiResult $result
+        */
+       public static function appendDebugInfoToApiResult( IContextSource $context, ApiResult $result ) {
+               if ( !self::$enabled ) {
+                       return;
+               }
+
+               // output errors as debug info, when display_errors is on
+               // this is necessary for all non html output of the api, because that clears all errors first
+               $obContents = ob_get_contents();
+               if ( $obContents ) {
+                       $obContentArray = explode( '<br />', $obContents );
+                       foreach ( $obContentArray as $obContent ) {
+                               if ( trim( $obContent ) ) {
+                                       self::debugMsg( Sanitizer::stripAllTags( $obContent ) );
+                               }
+                       }
+               }
+
+               MWDebug::log( 'MWDebug output complete' );
+               $debugInfo = self::getDebugInfo( $context );
+
+               $result->setIndexedTagName( $debugInfo, 'debuginfo' );
+               $result->setIndexedTagName( $debugInfo['log'], 'line' );
+               $result->setIndexedTagName( $debugInfo['debugLog'], 'msg' );
+               $result->setIndexedTagName( $debugInfo['queries'], 'query' );
+               $result->setIndexedTagName( $debugInfo['includes'], 'queries' );
+               $result->setIndexedTagName( $debugInfo['profile'], 'function' );
+               $result->addValue( null, 'debuginfo', $debugInfo );
+       }
+
+       /**
+        * Returns the HTML to add to the page for the toolbar
+        *
+        * @param IContextSource $context
+        * @return array
+        */
+       public static function getDebugInfo( IContextSource $context ) {
+               if ( !self::$enabled ) {
+                       return array();
+               }
+
+               global $wgVersion, $wgRequestTime;
+               $request = $context->getRequest();
+
+               // HHVM's reported memory usage from memory_get_peak_usage()
+               // is not useful when passing false, but we continue passing
+               // false for consistency of historical data in zend.
+               // see: https://github.com/facebook/hhvm/issues/2257#issuecomment-39362246
+               $realMemoryUsage = wfIsHHVM();
+
+               return array(
+                       'mwVersion' => $wgVersion,
+                       'phpEngine' => wfIsHHVM() ? 'HHVM' : 'PHP',
+                       'phpVersion' => wfIsHHVM() ? HHVM_VERSION : PHP_VERSION,
+                       'gitRevision' => GitInfo::headSHA1(),
+                       'gitBranch' => GitInfo::currentBranch(),
+                       'gitViewUrl' => GitInfo::headViewUrl(),
+                       'time' => microtime( true ) - $wgRequestTime,
+                       'log' => self::$log,
+                       'debugLog' => self::$debug,
+                       'queries' => self::$query,
+                       'request' => array(
+                               'method' => $request->getMethod(),
+                               'url' => $request->getRequestURL(),
+                               'headers' => $request->getAllHeaders(),
+                               'params' => $request->getValues(),
+                       ),
+                       'memory' => $context->getLanguage()->formatSize( memory_get_usage( $realMemoryUsage ) ),
+                       'memoryPeak' => $context->getLanguage()->formatSize( memory_get_peak_usage( $realMemoryUsage ) ),
+                       'includes' => self::getFilesIncluded( $context ),
+                       'profile' => Profiler::instance()->getRawData(),
+               );
+       }
+}
index 53990bf..ed12c60 100644 (file)
@@ -25,9 +25,9 @@
  * Abstract base class for update jobs that do something with some secondary
  * data extracted from article.
  *
- * @note: subclasses should NOT start or commit transactions in their doUpdate() method,
- *        a transaction will automatically be wrapped around the update. If need be,
- *        subclasses can override the beginTransaction() and commitTransaction() methods.
+ * @note subclasses should NOT start or commit transactions in their doUpdate() method,
+ *       a transaction will automatically be wrapped around the update. If need be,
+ *       subclasses can override the beginTransaction() and commitTransaction() methods.
  */
 abstract class DataUpdate implements DeferrableUpdate {
        /**
@@ -73,7 +73,7 @@ abstract class DataUpdate implements DeferrableUpdate {
         * This allows for limited transactional logic across multiple backends for storing
         * secondary data.
         *
-        * @param array $updates a list of DataUpdate instances
+        * @param array $updates A list of DataUpdate instances
         * @throws Exception|null
         */
        public static function runUpdates( $updates ) {
index 5cf0d2b..b0c1899 100644 (file)
@@ -76,7 +76,7 @@ class DeferredUpdates {
        /**
         * Do any deferred updates and clear the list
         *
-        * @param string $commit set to 'commit' to commit after every update to
+        * @param string $commit Set to 'commit' to commit after every update to
         *   prevent lock contention
         */
        public static function doUpdates( $commit = '' ) {
@@ -99,25 +99,29 @@ class DeferredUpdates {
                        $dbw = wfGetDB( DB_MASTER );
                }
 
-               /** @var DeferrableUpdate $update */
-               foreach ( $updates as $update ) {
-                       try {
-                               $update->doUpdate();
+               while ( $updates ) {
+                       self::clearPendingUpdates();
 
-                               if ( $doCommit && $dbw->trxLevel() ) {
-                                       $dbw->commit( __METHOD__, 'flush' );
-                               }
-                       } catch ( MWException $e ) {
-                               // We don't want exceptions thrown during deferred updates to
-                               // be reported to the user since the output is already sent.
-                               // Instead we just log them.
-                               if ( !$e instanceof ErrorPageError ) {
-                                       MWExceptionHandler::logException( $e );
+                       /** @var DeferrableUpdate $update */
+                       foreach ( $updates as $update ) {
+                               try {
+                                       $update->doUpdate();
+
+                                       if ( $doCommit && $dbw->trxLevel() ) {
+                                               $dbw->commit( __METHOD__, 'flush' );
+                                       }
+                               } catch ( MWException $e ) {
+                                       // We don't want exceptions thrown during deferred updates to
+                                       // be reported to the user since the output is already sent.
+                                       // Instead we just log them.
+                                       if ( !$e instanceof ErrorPageError ) {
+                                               MWExceptionHandler::logException( $e );
+                                       }
                                }
                        }
+                       $updates = array_merge( $wgDeferredUpdateList, self::$updates );
                }
 
-               self::clearPendingUpdates();
                wfProfileOut( __METHOD__ );
        }
 
index 0789b21..45d2664 100644 (file)
@@ -31,7 +31,7 @@ class LinksUpdate extends SqlDataUpdate {
        /** @var int Page ID of the article linked from */
        public $mId;
 
-       /** @var Title object of the article linked from */
+       /** @var Title Title object of the article linked from */
        public $mTitle;
 
        /** @var ParserOutput */
@@ -52,7 +52,7 @@ class LinksUpdate extends SqlDataUpdate {
        /** @var array Map of category names to sort keys */
        public $mCategories;
 
-       /** @var array ap of language codes to titles */
+       /** @var array Map of language codes to titles */
        public $mInterlangs;
 
        /** @var array Map of arbitrary name to value */
@@ -358,6 +358,7 @@ class LinksUpdate extends SqlDataUpdate {
                        foreach ( $diffs as $dbk => $id ) {
                                $arr[] = array(
                                        'pl_from' => $this->mId,
+                                       'pl_from_namespace' => $this->mTitle->getNamespace(),
                                        'pl_namespace' => $ns,
                                        'pl_title' => $dbk
                                );
@@ -379,6 +380,7 @@ class LinksUpdate extends SqlDataUpdate {
                        foreach ( $diffs as $dbk => $id ) {
                                $arr[] = array(
                                        'tl_from' => $this->mId,
+                                       'tl_from_namespace' => $this->mTitle->getNamespace(),
                                        'tl_namespace' => $ns,
                                        'tl_title' => $dbk
                                );
@@ -400,6 +402,7 @@ class LinksUpdate extends SqlDataUpdate {
                foreach ( $diffs as $iname => $dummy ) {
                        $arr[] = array(
                                'il_from' => $this->mId,
+                               'il_from_namespace' => $this->mTitle->getNamespace(),
                                'il_to' => $iname
                        );
                }
@@ -521,7 +524,7 @@ class LinksUpdate extends SqlDataUpdate {
         * is present in the database (as indicated by $wgPagePropsHaveSortkey).
         * The sortkey value is currently determined by getPropertySortKeyValue().
         *
-        * @note: this assumes that $this->mProperties[$prop] is defined.
+        * @note this assumes that $this->mProperties[$prop] is defined.
         *
         * @param string $prop The name of the property.
         *
@@ -550,8 +553,8 @@ class LinksUpdate extends SqlDataUpdate {
         * This will return $value if it is a float or int,
         * 1 or resp. 0 if it is a bool, and null otherwise.
         *
-        * @note: In the future, we may allow the sortkey to be specified explicitly
-        *        in ParserOutput::setProperty.
+        * @note In the future, we may allow the sortkey to be specified explicitly
+        *       in ParserOutput::setProperty.
         *
         * @param mixed $value
         *
index 20f348a..5d084af 100644 (file)
@@ -115,6 +115,8 @@ class SearchUpdate implements DeferrableUpdate {
         * Clean text for indexing. Only really suitable for indexing in databases.
         * If you're using a real search engine, you'll probably want to override
         * this behavior and do something nicer with the original wikitext.
+        * @param string $text
+        * @return string
         */
        public static function updateText( $text ) {
                global $wgContLang;
@@ -179,6 +181,7 @@ class SearchUpdate implements DeferrableUpdate {
         * Get a string representation of a title suitable for
         * including in a search index
         *
+        * @param SearchEngine $search
         * @return string A stripped-down title string ready for the search index
         */
        private function indexTitle( SearchEngine $search ) {
index 121af04..9c58503 100644 (file)
  * Abstract base class for update jobs that put some secondary data extracted
  * from article content into the database.
  *
- * @note: subclasses should NOT start or commit transactions in their doUpdate() method,
- *        a transaction will automatically be wrapped around the update. Starting another
- *        one would break the outer transaction bracket. If need be, subclasses can override
- *        the beginTransaction() and commitTransaction() methods.
+ * @note subclasses should NOT start or commit transactions in their doUpdate() method,
+ *       a transaction will automatically be wrapped around the update. Starting another
+ *       one would break the outer transaction bracket. If need be, subclasses can override
+ *       the beginTransaction() and commitTransaction() methods.
  */
 abstract class SqlDataUpdate extends DataUpdate {
        /** @var DatabaseBase Database connection reference */
@@ -46,7 +46,7 @@ abstract class SqlDataUpdate extends DataUpdate {
        /**
         * Constructor
         *
-        * @param bool $withTransaction whether this update should be wrapped in a
+        * @param bool $withTransaction Whether this update should be wrapped in a
         *   transaction (default: true). A transaction is only started if no
         *   transaction is already in progress, see beginTransaction() for details.
         */
index ddd2e09..8282295 100644 (file)
@@ -49,23 +49,32 @@ class ViewCountUpdate implements DeferrableUpdate {
                $dbw = wfGetDB( DB_MASTER );
 
                if ( $wgHitcounterUpdateFreq <= 1 || $dbw->getType() == 'sqlite' ) {
-                       $dbw->update(
-                               'page', array( 'page_counter = page_counter + 1' ),
-                               array( 'page_id' => $this->id ),
-                               __METHOD__
-                       );
-
+                       $id = $this->id;
+                       $method = __METHOD__;
+                       $dbw->onTransactionIdle( function () use ( $dbw, $id, $method ) {
+                               try {
+                                       $dbw->update( 'page',
+                                               array( 'page_counter = page_counter + 1' ),
+                                               array( 'page_id' => $id ),
+                                               $method
+                                       );
+                               } catch ( DBError $e ) {
+                                       MWExceptionHandler::logException( $e );
+                               }
+                       } );
                        return;
                }
 
                # Not important enough to warrant an error page in case of failure
                try {
+                       // Since `hitcounter` is non-transactional, the contention is minimal
                        $dbw->insert( 'hitcounter', array( 'hc_id' => $this->id ), __METHOD__ );
                        $checkfreq = intval( $wgHitcounterUpdateFreq / 25 + 1 );
                        if ( rand() % $checkfreq == 0 && $dbw->lastErrno() == 0 ) {
                                $this->collect();
                        }
                } catch ( DBError $e ) {
+                       MWExceptionHandler::logException( $e );
                }
        }
 
@@ -75,7 +84,6 @@ class ViewCountUpdate implements DeferrableUpdate {
                $dbw = wfGetDB( DB_MASTER );
 
                $rown = $dbw->selectField( 'hitcounter', 'COUNT(*)', array(), __METHOD__ );
-
                if ( $rown < $wgHitcounterUpdateFreq ) {
                        return;
                }
@@ -83,14 +91,13 @@ class ViewCountUpdate implements DeferrableUpdate {
                wfProfileIn( __METHOD__ . '-collect' );
                $old_user_abort = ignore_user_abort( true );
 
-               $dbw->lockTables( array(), array( 'hitcounter' ), __METHOD__, false );
-
                $dbType = $dbw->getType();
                $tabletype = $dbType == 'mysql' ? "ENGINE=HEAP " : '';
                $hitcounterTable = $dbw->tableName( 'hitcounter' );
                $acchitsTable = $dbw->tableName( 'acchits' );
                $pageTable = $dbw->tableName( 'page' );
 
+               $dbw->lockTables( array(), array( 'hitcounter' ), __METHOD__, false );
                $dbw->query( "CREATE TEMPORARY TABLE $acchitsTable $tabletype AS " .
                        "SELECT hc_id,COUNT(*) AS hc_n FROM $hitcounterTable " .
                        'GROUP BY hc_id', __METHOD__ );
index 3aad389..50e08ca 100644 (file)
@@ -98,9 +98,9 @@ class DifferenceEngine extends ContextSource {
 
        /**
         * Constructor
-        * @param IContextSource $context context to use, anything else will be ignored
-        * @param int $old old ID we want to show and diff with.
-        * @param string|int $new either revision ID or 'prev' or 'next'. Default: 0.
+        * @param IContextSource $context Context to use, anything else will be ignored
+        * @param int $old Old ID we want to show and diff with.
+        * @param string|int $new Either revision ID or 'prev' or 'next'. Default: 0.
         * @param int $rcid Deprecated, no longer used!
         * @param bool $refreshCache If set, refreshes the diff cache
         * @param bool $unhide If set, allow viewing deleted revs
@@ -310,11 +310,11 @@ class DifferenceEngine extends ContextSource {
                                                                'undoafter' => $this->mOldid,
                                                                'undo' => $this->mNewid
                                                        ) ),
-                                                       'title' => Linker::titleAttrib( 'undo' )
+                                                       'title' => Linker::titleAttrib( 'undo' ),
                                                ),
                                                $this->msg( 'editundo' )->text()
                                        );
-                                       $revisionTools[] = $undoLink;
+                                       $revisionTools['mw-diff-undo'] = $undoLink;
                                }
                        }
 
@@ -387,8 +387,14 @@ class DifferenceEngine extends ContextSource {
                wfRunHooks( 'DiffRevisionTools', array( $this->mNewRev, &$revisionTools, $this->mOldRev ) );
                $formattedRevisionTools = array();
                // Put each one in parentheses (poor man's button)
-               foreach ( $revisionTools as $tool ) {
-                       $formattedRevisionTools[] = $this->msg( 'parentheses' )->rawParams( $tool )->escaped();
+               foreach ( $revisionTools as $key => $tool ) {
+                       $toolClass = is_string( $key ) ? $key : 'mw-diff-tool';
+                       $element = Html::rawElement(
+                               'span',
+                               array( 'class' => $toolClass ),
+                               $this->msg( 'parentheses' )->rawParams( $tool )->escaped()
+                       );
+                       $formattedRevisionTools[] = $element;
                }
                $newRevisionHeader = $this->getRevisionHeader( $this->mNewRev, 'complete' ) .
                        ' ' . implode( ' ', $formattedRevisionTools );
@@ -823,8 +829,8 @@ class DifferenceEngine extends ContextSource {
         *
         * @todo move this to TextDifferenceEngine, make DifferenceEngine abstract. At some point.
         *
-        * @param string $otext old text, must be already segmented
-        * @param string $ntext new text, must be already segmented
+        * @param string $otext Old text, must be already segmented
+        * @param string $ntext New text, must be already segmented
         *
         * @return bool|string
         */
@@ -972,7 +978,7 @@ class DifferenceEngine extends ContextSource {
                }
 
                // Sanity: don't show the notice if too many rows must be scanned
-               // @TODO: show some special message for that case
+               // @todo show some special message for that case
                $nEdits = $this->mNewPage->countRevisionsBetween( $oldRev, $newRev, 1000 );
                if ( $nEdits > 0 && $nEdits <= 1000 ) {
                        $limit = 100; // use diff-multi-manyusers if too many users
@@ -1052,8 +1058,13 @@ class DifferenceEngine extends ContextSource {
 
                        $key = $title->quickUserCan( 'edit', $user ) ? 'editold' : 'viewsourceold';
                        $msg = $this->msg( $key )->escaped();
-                       $header .= ' ' . $this->msg( 'parentheses' )->rawParams(
-                               Linker::linkKnown( $title, $msg, array(), $editQuery ) )->plain();
+                       $editLink = $this->msg( 'parentheses' )->rawParams(
+                               Linker::linkKnown( $title, $msg, array( ), $editQuery ) )->plain();
+                       $header .= ' ' . Html::rawElement(
+                               'span',
+                               array( 'class' => 'mw-diff-edit' ),
+                               $editLink
+                       );
                        if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
                                $header = Html::rawElement(
                                        'span',
@@ -1140,6 +1151,8 @@ class DifferenceEngine extends ContextSource {
 
        /**
         * Use specified text instead of loading from the database
+        * @param Content $oldContent
+        * @param Content $newContent
         * @since 1.21
         */
        public function setContent( Content $oldContent, Content $newContent ) {
@@ -1153,6 +1166,7 @@ class DifferenceEngine extends ContextSource {
        /**
         * Set the language in which the diff text is written
         * (Defaults to page content language).
+        * @param Language|string $lang
         * @since 1.19
         */
        public function setTextLanguage( $lang ) {
index 2da3775..e62f8bd 100644 (file)
@@ -29,7 +29,7 @@
 class BadTitleError extends ErrorPageError {
        /**
         * @param string|Message $msg A message key (default: 'badtitletext')
-        * @param array $params parameter to wfMessage()
+        * @param array $params Parameter to wfMessage()
         */
        public function __construct( $msg = 'badtitletext', $params = array() ) {
                parent::__construct( 'badtitle', $msg, $params );
index 7cd198b..3631a34 100644 (file)
@@ -32,7 +32,7 @@ class ErrorPageError extends MWException {
         *
         * @param string|Message $title Message key (string) for page title, or a Message object
         * @param string|Message $msg Message key (string) for error text, or a Message object
-        * @param array $params with parameters to wfMessage()
+        * @param array $params Array with parameters to wfMessage()
         */
        public function __construct( $title, $msg, $params = array() ) {
                $this->title = $title;
index 58b07f5..074128f 100644 (file)
@@ -252,6 +252,7 @@ class MWException extends Exception {
        /**
         * Send a header, if we haven't already sent them. We shouldn't,
         * but sometimes we might in a weird case like Export
+        * @param string $header
         */
        private static function header( $header ) {
                if ( !headers_sent() ) {
index 9d89009..03ba0b2 100644 (file)
  */
 
 /**
- * Shows a generic "user is not logged in" error page.
+ * Redirect a user to the login page
  *
  * This is essentially an ErrorPageError exception which by default uses the
  * 'exception-nologin' as a title and 'exception-nologin-text' for the message.
- * @see bug 37627
- * @since 1.20
+ *
+ * @note In order for this exception to redirect, the error message passed to the
+ * constructor has to be explicitly added to LoginForm::validErrorMessages. Otherwise,
+ * the user will just be shown the message rather than redirected.
  *
  * @par Example:
  * @code
  * }
  * @endcode
  *
+ * @see bug 37627
+ * @since 1.20
  * @ingroup Exception
  */
 class UserNotLoggedIn extends ErrorPageError {
 
        /**
+        * @note The value of the $reasonMsg parameter must be put into LoginForm::validErrorMessages
+        * if you want the user to be automatically redirected to the login form.
+        *
         * @param string $reasonMsg A message key containing the reason for the error.
         *        Optional, default: 'exception-nologin-text'
         * @param string $titleMsg A message key to set the page title.
@@ -62,4 +69,34 @@ class UserNotLoggedIn extends ErrorPageError {
        ) {
                parent::__construct( $titleMsg, $reasonMsg, $params );
        }
+
+       /**
+        * Redirect to Special:Userlogin if the specified message is compatible. Otherwise,
+        * show an error page as usual.
+        */
+       public function report() {
+               // If an unsupported message is used, don't try redirecting to Special:Userlogin,
+               // since the message may not be compatible.
+               if ( !in_array( $this->msg, LoginForm::$validErrorMessages ) ) {
+                       parent::report();
+               }
+
+               // Message is valid. Redirec to Special:Userlogin
+
+               $context = RequestContext::getMain();
+
+               $output = $context->getOutput();
+               $query = $context->getRequest()->getValues();
+               // Title will be overridden by returnto
+               unset( $query['title'] );
+               // Redirect to Special:Userlogin
+               $output->redirect( SpecialPage::getTitleFor( 'Userlogin' )->getFullURL( array(
+                       // Return to this page when the user logs in
+                       'returnto' => $context->getTitle()->getFullText(),
+                       'returntoquery' => wfArrayToCgi( $query ),
+                       'warning' => $this->msg,
+               ) ) );
+
+               $output->output();
+       }
 }
index 9e09b22..688130e 100644 (file)
@@ -178,7 +178,7 @@ class ExternalStore {
         * itself. It also fails-over to the next possible clusters
         * as provided in the first parameter.
         *
-        * @param array $tryStores refer to $wgDefaultExternalStore
+        * @param array $tryStores Refer to $wgDefaultExternalStore
         * @param string $data
         * @param array $params Associative array of ExternalStoreMedium parameters
         * @return string|bool The URL of the stored data item, or false on error
index 5774a24..952bf63 100644 (file)
@@ -96,9 +96,6 @@ class ExternalStoreDB extends ExternalStoreMedium {
                if ( !$id ) {
                        throw new MWException( __METHOD__ . ': no insert ID' );
                }
-               if ( $dbw->getFlag( DBO_TRX ) ) {
-                       $dbw->commit( __METHOD__ );
-               }
 
                return "DB://$cluster/$id";
        }
@@ -134,7 +131,10 @@ class ExternalStoreDB extends ExternalStoreMedium {
                        wfDebug( "writable external store\n" );
                }
 
-               return $lb->getConnection( DB_SLAVE, array(), $wiki );
+               $db = $lb->getConnection( DB_SLAVE, array(), $wiki );
+               $db->clearFlag( DBO_TRX ); // sanity
+
+               return $db;
        }
 
        /**
@@ -147,7 +147,10 @@ class ExternalStoreDB extends ExternalStoreMedium {
                $wiki = isset( $this->params['wiki'] ) ? $this->params['wiki'] : false;
                $lb = $this->getLoadBalancer( $cluster );
 
-               return $lb->getConnection( DB_MASTER, array(), $wiki );
+               $db = $lb->getConnection( DB_MASTER, array(), $wiki );
+               $db->clearFlag( DBO_TRX ); // sanity
+
+               return $db;
        }
 
        /**
@@ -282,6 +285,10 @@ class ExternalStoreDB extends ExternalStoreMedium {
                }
        }
 
+       /**
+        * @param string $url
+        * @return array
+        */
        protected function parseURL( $url ) {
                $path = explode( '/', $url );
 
index 4575e7c..1659c62 100644 (file)
@@ -98,7 +98,7 @@ class FSFile {
         * Get an associative array containing information about
         * a file with the given storage path.
         *
-        * @param mixed $ext The file extension, or true to extract it from the filename.
+        * @param string|bool $ext The file extension, or true to extract it from the filename.
         *             Set it to false to ignore the extension.
         *
         * @return array
@@ -118,9 +118,9 @@ class FSFile {
                                $ext = self::extensionFromPath( $this->path );
                        }
 
-                       # mime type according to file contents
+                       # MIME type according to file contents
                        $info['file-mime'] = $this->getMimeType();
-                       # logical mime type
+                       # logical MIME type
                        $info['mime'] = $magic->improveTypeFromExtension( $info['file-mime'], $ext );
 
                        list( $info['major_mime'], $info['minor_mime'] ) = File::splitMime( $info['mime'] );
@@ -237,8 +237,8 @@ class FSFile {
        /**
         * Get an associative array containing information about a file in the local filesystem.
         *
-        * @param string $path absolute local filesystem path
-        * @param mixed $ext The file extension, or true to extract it from the filename.
+        * @param string $path Absolute local filesystem path
+        * @param string|bool $ext The file extension, or true to extract it from the filename.
         *   Set it to false to ignore the extension.
         * @return array
         */
index e7c1f6f..b99ffb6 100644 (file)
@@ -213,7 +213,7 @@ class FSFileBackend extends FileBackendStore {
                                wfEscapeShellArg( $this->cleanPathSlashes( $tempFile->getPath() ) ),
                                wfEscapeShellArg( $this->cleanPathSlashes( $dest ) )
                        ) );
-                       $handler = function( $errors, Status $status, array $params, $cmd ) {
+                       $handler = function ( $errors, Status $status, array $params, $cmd ) {
                                if ( $errors !== '' && !( wfIsWindows() && $errors[0] === " " ) ) {
                                        $status->fatal( 'backend-fail-create', $params['dst'] );
                                        trigger_error( "$cmd\n$errors", E_USER_WARNING ); // command output
@@ -252,7 +252,7 @@ class FSFileBackend extends FileBackendStore {
                                wfEscapeShellArg( $this->cleanPathSlashes( $params['src'] ) ),
                                wfEscapeShellArg( $this->cleanPathSlashes( $dest ) )
                        ) );
-                       $handler = function( $errors, Status $status, array $params, $cmd ) {
+                       $handler = function ( $errors, Status $status, array $params, $cmd ) {
                                if ( $errors !== '' && !( wfIsWindows() && $errors[0] === " " ) ) {
                                        $status->fatal( 'backend-fail-store', $params['src'], $params['dst'] );
                                        trigger_error( "$cmd\n$errors", E_USER_WARNING ); // command output
@@ -310,7 +310,7 @@ class FSFileBackend extends FileBackendStore {
                                wfEscapeShellArg( $this->cleanPathSlashes( $source ) ),
                                wfEscapeShellArg( $this->cleanPathSlashes( $dest ) )
                        ) );
-                       $handler = function( $errors, Status $status, array $params, $cmd ) {
+                       $handler = function ( $errors, Status $status, array $params, $cmd ) {
                                if ( $errors !== '' && !( wfIsWindows() && $errors[0] === " " ) ) {
                                        $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
                                        trigger_error( "$cmd\n$errors", E_USER_WARNING ); // command output
@@ -370,7 +370,7 @@ class FSFileBackend extends FileBackendStore {
                                wfEscapeShellArg( $this->cleanPathSlashes( $source ) ),
                                wfEscapeShellArg( $this->cleanPathSlashes( $dest ) )
                        ) );
-                       $handler = function( $errors, Status $status, array $params, $cmd ) {
+                       $handler = function ( $errors, Status $status, array $params, $cmd ) {
                                if ( $errors !== '' && !( wfIsWindows() && $errors[0] === " " ) ) {
                                        $status->fatal( 'backend-fail-move', $params['src'], $params['dst'] );
                                        trigger_error( "$cmd\n$errors", E_USER_WARNING ); // command output
@@ -415,7 +415,7 @@ class FSFileBackend extends FileBackendStore {
                                wfIsWindows() ? 'DEL' : 'unlink',
                                wfEscapeShellArg( $this->cleanPathSlashes( $source ) )
                        ) );
-                       $handler = function( $errors, Status $status, array $params, $cmd ) {
+                       $handler = function ( $errors, Status $status, array $params, $cmd ) {
                                if ( $errors !== '' && !( wfIsWindows() && $errors[0] === " " ) ) {
                                        $status->fatal( 'backend-fail-delete', $params['src'] );
                                        trigger_error( "$cmd\n$errors", E_USER_WARNING ); // command output
@@ -828,7 +828,7 @@ abstract class FSFileBackendList implements Iterator {
        protected $params = array();
 
        /**
-        * @param string $dir file system directory
+        * @param string $dir File system directory
         * @param array $params
         */
        public function __construct( $dir, array $params ) {
@@ -849,7 +849,7 @@ abstract class FSFileBackendList implements Iterator {
        /**
         * Return an appropriate iterator object to wrap
         *
-        * @param string $dir file system directory
+        * @param string $dir File system directory
         * @return Iterator
         */
        protected function initIterator( $dir ) {
index 2820be2..8c0a61a 100644 (file)
@@ -135,19 +135,12 @@ abstract class FileBackend {
         */
        public function __construct( array $config ) {
                $this->name = $config['name'];
+               $this->wikiId = $config['wikiId']; // e.g. "my_wiki-en_"
                if ( !preg_match( '!^[a-zA-Z0-9-_]{1,255}$!', $this->name ) ) {
-                       throw new FileBackendException( "Backend name `{$this->name}` is invalid." );
-               }
-               if ( !isset( $config['wikiId'] ) ) {
-                       $config['wikiId'] = wfWikiID();
-                       wfDeprecated( __METHOD__ . ' called without "wikiID".', '1.23' );
-               }
-               if ( isset( $config['lockManager'] ) && !is_object( $config['lockManager'] ) ) {
-                       $config['lockManager'] =
-                               LockManagerGroup::singleton( $config['wikiId'] )->get( $config['lockManager'] );
-                       wfDeprecated( __METHOD__ . ' called with non-object "lockManager".', '1.23' );
+                       throw new FileBackendException( "Backend name '{$this->name}' is invalid." );
+               } elseif ( !is_string( $this->wikiId ) ) {
+                       throw new FileBackendException( "Backend wiki ID not provided for '{$this->name}'." );
                }
-               $this->wikiId = $config['wikiId']; // e.g. "my_wiki-en_"
                $this->lockManager = isset( $config['lockManager'] )
                        ? $config['lockManager']
                        : new NullLockManager( array() );
@@ -218,7 +211,7 @@ abstract class FileBackend {
        /**
         * Check if the backend medium supports a field of extra features
         *
-        * @return int Bitfield of FileBackend::ATTR_* flags
+        * @param int $bitfield Bitfield of FileBackend::ATTR_* flags
         * @return bool
         * @since 1.23
         */
index ee9a49d..495ac3c 100644 (file)
@@ -69,7 +69,7 @@ abstract class FileBackendStore extends FileBackend {
                $this->mimeCallback = isset( $config['mimeCallback'] )
                        ? $config['mimeCallback']
                        : function ( $storagePath, $content, $fsPath ) {
-                               // @TODO: handle the case of extension-less files using the contents
+                               // @todo handle the case of extension-less files using the contents
                                return StreamFile::contentTypeFromPath( $storagePath ) ?: 'unknown/unknown';
                        };
                $this->memCache = new EmptyBagOStuff(); // disabled by default
@@ -1696,7 +1696,7 @@ abstract class FileBackendStore extends FileBackend {
                if ( !$this->memCache->add( $key, $val, $ttl ) && !empty( $val['latest'] ) ) {
                        $this->memCache->merge(
                                $key,
-                               function( BagOStuff $cache, $key, $cValue ) use ( $val ) {
+                               function ( BagOStuff $cache, $key, $cValue ) use ( $val ) {
                                        return ( is_array( $cValue ) && empty( $cValue['latest'] ) )
                                                ? $val // update the stat cache with the lastest info
                                                : false; // do nothing (cache is salted or some error happened)
@@ -1819,7 +1819,7 @@ abstract class FileBackendStore extends FileBackend {
         * @param string $storagePath
         * @param string|null $content File data
         * @param string|null $fsPath File system path
-        * @return MIME type
+        * @return string MIME type
         */
        protected function getContentType( $storagePath, $content, $fsPath ) {
                return call_user_func_array( $this->mimeCallback, func_get_args() );
index 569f337..c06f6fc 100644 (file)
@@ -51,7 +51,7 @@ On files:
 * read a file into a string or  several files into a map of path names to strings
 * download a file or set of files to a temporary file (on a mounted file system)
 * get the SHA1 hash of a file
-* get various properties of a file (stat information, content time, mime information, ...)
+* get various properties of a file (stat information, content time, MIME information, ...)
 
 On directories:
 * get a list of files directly under a directory
index 9ef23f8..f40ec46 100644 (file)
@@ -173,7 +173,7 @@ class SwiftFileBackend extends FileBackendStore {
         * Sanitize and filter the custom headers from a $params array.
         * We only allow certain Content- and X-Content- headers.
         *
-        * @param array $headers
+        * @param array $params
         * @return array Sanitized value of 'headers' field in $params
         */
        protected function sanitizeHdrs( array $params ) {
@@ -1521,7 +1521,7 @@ class SwiftFileBackend extends FileBackendStore {
                                        'mtime' => $this->convertSwiftDate( $rhdrs['last-modified'], TS_MW ),
                                        // Empty objects actually return no content-length header in Ceph
                                        'size'  => isset( $rhdrs['content-length'] ) ? (int)$rhdrs['content-length'] : 0,
-                                       'sha1'  => $rhdrs[ 'x-object-meta-sha1base36'],
+                                       'sha1'  => $rhdrs['x-object-meta-sha1base36'],
                                        // Note: manifiest ETags are not an MD5 of the file
                                        'md5'   => ctype_xdigit( $rhdrs['etag'] ) ? $rhdrs['etag'] : null,
                                        'xattr' => array( 'metadata' => $metadata, 'headers' => $headers )
@@ -1791,7 +1791,7 @@ abstract class SwiftFileBackendList implements Iterator {
         *
         * @param string $container Resolved container name
         * @param string $dir Resolved path relative to container
-        * @param string $after null
+        * @param string $after
         * @param int $limit
         * @param array $params
         * @return Traversable|array
index 20c7c35..c065148 100644 (file)
@@ -132,7 +132,7 @@ abstract class FileJournal {
        /**
         * Get the position ID of the latest journal entry at some point in time
         *
-        * @param int|string $time timestamp
+        * @param int|string $time Timestamp
         * @return int|bool
         */
        final public function getPositionAtTime( $time ) {
@@ -224,7 +224,7 @@ class NullFileJournal extends FileJournal {
 
        /**
         * @see FileJournal::doGetPositionAtTime()
-        * @param int|string $time timestamp
+        * @param int|string $time Timestamp
         * @return int|bool
         */
        protected function doGetPositionAtTime( $time ) {
index b58e901..450ccc8 100644 (file)
@@ -108,7 +108,7 @@ abstract class DBLockManager extends QuorumLockManager {
                $this->session = wfRandomString( 31 );
        }
 
-       // @TODO: change this code to work in one batch
+       // @todo change this code to work in one batch
        protected function getLocksOnServer( $lockSrv, array $pathsByType ) {
                $status = Status::newGood();
                foreach ( $pathsByType as $type => $paths ) {
index ecf396a..19fc4fe 100644 (file)
@@ -34,7 +34,7 @@ class LockManagerGroup {
 
        protected $domain; // string; domain (usually wiki ID)
 
-       /** @var array of (name => ('class' => ..., 'config' => ..., 'instance' => ...)) */
+       /** @var array Array of (name => ('class' => ..., 'config' => ..., 'instance' => ...)) */
        protected $managers = array();
 
        /**
index f7ffb2d..9bb01c2 100644 (file)
@@ -49,7 +49,7 @@ class MemcLockManager extends QuorumLockManager {
        /** @var array (server name => bool) */
        protected $serversUp = array();
 
-       /** @var string random UUID */
+       /** @var string Random UUID */
        protected $session = '';
 
        /**
index ff4cba5..90e0581 100644 (file)
@@ -51,7 +51,7 @@ class RedisLockManager extends QuorumLockManager {
        /** @var array Map server names to hostname/IP and port numbers */
        protected $lockServers = array();
 
-       /** @var string random UUID */
+       /** @var string Random UUID */
        protected $session = '';
 
        /**
index 8598005..5929525 100644 (file)
@@ -546,7 +546,7 @@ class FileRepo {
         *
         * STUB
         * @param string $hash SHA-1 hash
-        * @return array
+        * @return File[]
         */
        public function findBySha1( $hash ) {
                return array();
@@ -1014,6 +1014,7 @@ class FileRepo {
                        } elseif ( is_array( $triple[2] ) && isset( $triple[2]['headers'] ) ) {
                                $headers = $triple[2]['headers'];
                        }
+                       // @fixme: $headers might not be defined
                        $operations[] = array(
                                'op' => FileBackend::isStoragePath( $src ) ? 'copy' : 'store',
                                'src' => $src,
@@ -1055,7 +1056,7 @@ class FileRepo {
         * Returns a FileRepoStatus object with the file Virtual URL in the value,
         * file can later be disposed using FileRepo::freeTemp().
         *
-        * @param string $originalName the base name of the file as specified
+        * @param string $originalName The base name of the file as specified
         *   by the user. The file extension will be maintained.
         * @param string $srcPath The current location of the file.
         * @return FileRepoStatus Object with the URL in the value.
@@ -1345,13 +1346,16 @@ class FileRepo {
         * Checks existence of an array of files.
         *
         * @param array $files Virtual URLs (or storage paths) of files to check
-        * @return array|bool Either array of files and existence flags, or false
+        * @return array Map of files and existence flags, or false
         */
        public function fileExistsBatch( array $files ) {
+               $paths = array_map( array( $this, 'resolveToStoragePath' ), $files );
+               $this->backend->preloadFileStat( array( 'srcs' => $paths ) );
+
                $result = array();
                foreach ( $files as $key => $file ) {
-                       $file = $this->resolveToStoragePath( $file );
-                       $result[$key] = $this->backend->fileExists( array( 'src' => $file ) );
+                       $path = $this->resolveToStoragePath( $file );
+                       $result[$key] = $this->backend->fileExists( array( 'src' => $path ) );
                }
 
                return $result;
@@ -1447,6 +1451,7 @@ class FileRepo {
         * Delete files in the deleted directory if they are not referenced in the filearchive table
         *
         * STUB
+        * @param array $storageKeys
         */
        public function cleanupDeletedBatch( array $storageKeys ) {
                $this->assertWritableRepo();
index 3f7adb0..926fd0b 100644 (file)
@@ -49,7 +49,7 @@ class LocalRepo extends FileRepo {
 
        /**
         * @throws MWException
-        * @param array $row
+        * @param stdClass $row
         * @return LocalFile
         */
        function newFileFromRow( $row ) {
@@ -91,7 +91,7 @@ class LocalRepo extends FileRepo {
                        $hashPath = $this->getDeletedHashPath( $key );
                        $path = "$root/$hashPath$key";
                        $dbw->begin( __METHOD__ );
-                       // Check for usage in deleted/hidden files and pre-emptively
+                       // Check for usage in deleted/hidden files and preemptively
                        // lock the key to avoid any future use until we are finished.
                        $deleted = $this->deletedFileHasKey( $key, 'lock' );
                        $hidden = $this->hiddenFileHasKey( $key, 'lock' );
@@ -167,7 +167,7 @@ class LocalRepo extends FileRepo {
         * Checks if there is a redirect named as $title
         *
         * @param Title $title Title of file
-        * @return bool
+        * @return bool|Title
         */
        function checkRedirect( Title $title ) {
                global $wgMemc;
@@ -369,8 +369,8 @@ class LocalRepo extends FileRepo {
         * Get an array or iterator of file objects for files that have a given
         * SHA-1 content hash.
         *
-        * @param string $hash a sha1 hash to look for
-        * @return array
+        * @param string $hash A sha1 hash to look for
+        * @return File[]
         */
        function findBySha1( $hash ) {
                $dbr = $this->getSlaveDB();
index 65637df..fab4216 100644 (file)
@@ -170,7 +170,7 @@ class RepoGroup {
        /**
         * Search repositories for many files at once.
         *
-        * @param array $items An array of titles, or an array of findFile() options with
+        * @param array $inputItems An array of titles, or an array of findFile() options with
         *    the "title" option giving the title. Example:
         *
         *     $findItem = array( 'title' => $title, 'private' => true );
@@ -183,10 +183,6 @@ class RepoGroup {
         *       The search title uses the input titles; the other is the final post-redirect title.
         *       All titles are returned as string DB keys and the inner array is associative.
         * @return array Map of (file name => File objects) for matches
-        *
-        * @param array $inputItems
-        * @param int $flags
-        * @return array
         */
        function findFiles( array $inputItems, $flags = 0 ) {
                if ( !$this->reposInitialised ) {
@@ -221,7 +217,7 @@ class RepoGroup {
        /**
         * Interface for FileRepo::checkRedirect()
         * @param Title $title
-        * @return bool
+        * @return bool|Title
         */
        function checkRedirect( Title $title ) {
                if ( !$this->reposInitialised ) {
@@ -272,8 +268,8 @@ class RepoGroup {
        /**
         * Find all instances of files with this key
         *
-        * @param string $hash base 36 SHA-1 hash
-        * @return array Array of File objects
+        * @param string $hash Base 36 SHA-1 hash
+        * @return File[]
         */
        function findBySha1( $hash ) {
                if ( !$this->reposInitialised ) {
@@ -292,7 +288,7 @@ class RepoGroup {
        /**
         * Find all instances of files with this keys
         *
-        * @param array $hashes base 36 SHA-1 hashes
+        * @param array $hashes Base 36 SHA-1 hashes
         * @return array Array of array of File objects
         */
        function findBySha1s( array $hashes ) {
@@ -409,6 +405,8 @@ class RepoGroup {
 
        /**
         * Create a repo class based on an info structure
+        * @param array $info
+        * @return FileRepo
         */
        protected function newRepo( $info ) {
                $class = $info['class'];
@@ -420,7 +418,7 @@ class RepoGroup {
         * Split a virtual URL into repo, zone and rel parts
         * @param string $url
         * @throws MWException
-        * @return array containing repo, zone and rel
+        * @return array Containing repo, zone and rel
         */
        function splitVirtualUrl( $url ) {
                if ( substr( $url, 0, 9 ) != 'mwrepo://' ) {
index 1eee6a2..8bf9040 100644 (file)
@@ -27,7 +27,7 @@
  * @ingroup FileAbstraction
  */
 class ArchivedFile {
-       /** @var int filearchive row ID */
+       /** @var int Filearchive row ID */
        private $id;
 
        /** @var string File name */
@@ -42,7 +42,7 @@ class ArchivedFile {
        /** @var int File size in bytes */
        private $size;
 
-       /** @var int size in bytes */
+       /** @var int Size in bytes */
        private $bits;
 
        /** @var int Width */
@@ -383,7 +383,7 @@ class ArchivedFile {
        }
 
        /**
-        * Returns the mime type of the file.
+        * Returns the MIME type of the file.
         * @return string
         */
        public function getMimeType() {
@@ -407,6 +407,7 @@ class ArchivedFile {
        /**
         * Returns the number of pages of a multipage document, or false for
         * documents which aren't multipage documents
+        * @return bool|int
         */
        function pageCount() {
                if ( !isset( $this->pageCount ) ) {
index e970e38..f9e0a2d 100644 (file)
@@ -127,7 +127,7 @@ abstract class File {
        /** @var string Relative path including trailing slash */
        protected $hashPath;
 
-       /** @var string number of pages of a multipage document, or false for
+       /** @var string Number of pages of a multipage document, or false for
         *    documents which aren't multipage documents
         */
        protected $pageCount;
@@ -583,7 +583,7 @@ abstract class File {
         *
         * Currently used to add a warning to the image description page
         *
-        * @return bool false if the main image is both animated
+        * @return bool False if the main image is both animated
         *   and the thumbnail is not. In all other cases must return
         *   true. If image is not renderable whatsoever, should
         *   return true.
@@ -679,7 +679,7 @@ abstract class File {
        }
 
        /**
-        * Returns the mime type of the file.
+        * Returns the MIME type of the file.
         * Overridden by LocalFile, UnregisteredLocalFile
         * STUB
         *
@@ -714,7 +714,7 @@ abstract class File {
         */
        function canRender() {
                if ( !isset( $this->canRender ) ) {
-                       $this->canRender = $this->getHandler() && $this->handler->canRender( $this );
+                       $this->canRender = $this->getHandler() && $this->handler->canRender( $this ) && $this->exists();
                }
 
                return $this->canRender;
@@ -1178,7 +1178,7 @@ abstract class File {
                        return false;
                }
 
-               $this->tmpBucketedThumbCache[ $bucket ] = $tmpFile->getPath();
+               $this->tmpBucketedThumbCache[$bucket] = $tmpFile->getPath();
                // For the caching to work, we need to make the tmp file survive as long as
                // this object exists
                $tmpFile->bind( $this );
@@ -1189,7 +1189,7 @@ abstract class File {
        /**
         * Returns the most appropriate source image for the thumbnail, given a target thumbnail size
         * @param array $params
-        * @return array source path and width/height of the source
+        * @return array Source path and width/height of the source
         */
        public function getThumbnailSource( $params ) {
                if ( $this->repo
@@ -1204,8 +1204,8 @@ abstract class File {
                        }
 
                        // Try to avoid reading from storage if the file was generated by this script
-                       if ( isset( $this->tmpBucketedThumbCache[ $bucket ] ) ) {
-                               $tmpPath = $this->tmpBucketedThumbCache[ $bucket ];
+                       if ( isset( $this->tmpBucketedThumbCache[$bucket] ) ) {
+                               $tmpPath = $this->tmpBucketedThumbCache[$bucket];
 
                                if ( file_exists( $tmpPath ) ) {
                                        return array(
@@ -1261,7 +1261,7 @@ abstract class File {
        /**
         * Creates a temp FS file with the same extension and the thumbnail
         * @param string $thumbPath Thumbnail path
-        * @returns TempFSFile
+        * @return TempFSFile
         */
        protected function makeTransformTmpFile( $thumbPath ) {
                $thumbExt = FileBackend::extensionFromPath( $thumbPath );
@@ -1287,6 +1287,7 @@ abstract class File {
         * Hook into transform() to allow migration of thumbnail files
         * STUB
         * Overridden by LocalFile
+        * @param string $thumbName
         */
        function migrateThumbFile( $thumbName ) {
        }
@@ -1311,16 +1312,16 @@ abstract class File {
         * @return ThumbnailImage
         */
        function iconThumb() {
-               global $wgStylePath, $wgStyleDirectory;
+               global $wgScriptPath, $IP;
+               $assetsPath = "$wgScriptPath/assets/file-type-icons/";
+               $assetsDirectory = "$IP/assets/file-type-icons/";
 
                $try = array( 'fileicon-' . $this->getExtension() . '.png', 'fileicon.png' );
                foreach ( $try as $icon ) {
-                       $path = '/common/images/icons/' . $icon;
-                       $filepath = $wgStyleDirectory . $path;
-                       if ( file_exists( $filepath ) ) { // always FS
+                       if ( file_exists( $assetsDirectory . $icon ) ) { // always FS
                                $params = array( 'width' => 120, 'height' => 120 );
 
-                               return new ThumbnailImage( $this, $wgStylePath . $path, false, $params );
+                               return new ThumbnailImage( $this, $assetsPath . $icon, false, $params );
                        }
                }
 
@@ -1330,6 +1331,7 @@ abstract class File {
        /**
         * Get last thumbnailing error.
         * Largely obsolete.
+        * @return string
         */
        function getLastError() {
                return $this->lastError;
@@ -1606,7 +1608,7 @@ abstract class File {
         *
         * @param string $zone Name of requested zone
         * @param bool|string $suffix If not false, the name of a file in zone
-        * @return string path
+        * @return string Path
         */
        function getZoneUrl( $zone, $suffix = false ) {
                $this->assertRepoDefined();
@@ -1623,7 +1625,7 @@ abstract class File {
         * Get the URL of the thumbnail directory, or a particular file if $suffix is specified
         *
         * @param bool|string $suffix If not false, the name of a thumbnail file
-        * @return string path
+        * @return string Path
         */
        function getThumbUrl( $suffix = false ) {
                return $this->getZoneUrl( 'thumb', $suffix );
@@ -1633,7 +1635,7 @@ abstract class File {
         * Get the URL of the transcoded directory, or a particular file if $suffix is specified
         *
         * @param bool|string $suffix If not false, the name of a media file
-        * @return string path
+        * @return string Path
         */
        function getTranscodedUrl( $suffix = false ) {
                return $this->getZoneUrl( 'transcoded', $suffix );
@@ -1741,7 +1743,7 @@ abstract class File {
         * @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 object. On success, the value member contains the
+        * @return FileRepoStatus On success, the value member contains the
         *   archive name, or an empty string if it was a new file.
         *
         * STUB
@@ -1937,7 +1939,7 @@ abstract class File {
         * @note Use getWidth()/getHeight() instead of this method unless you have a
         *  a good reason. This method skips all caches.
         *
-        * @param string $fileName The path to the file (e.g. From getLocalPathRef() )
+        * @param string $filePath The path to the file (e.g. From getLocalPathRef() )
         * @return array The width, followed by height, with optionally more things after
         */
        function getImageSize( $filePath ) {
@@ -2072,44 +2074,6 @@ abstract class File {
                return true;
        }
 
-       /**
-        * Get an associative array containing information about a file in the local filesystem.
-        *
-        * @param string $path Absolute local filesystem path
-        * @param string|bool $ext The file extension, or true to extract it from
-        *   the filename. Set it to false to ignore the extension.
-        *
-        * @return array
-        * @deprecated since 1.19
-        */
-       static function getPropsFromPath( $path, $ext = true ) {
-               wfDebug( __METHOD__ . ": Getting file info for $path\n" );
-               wfDeprecated( __METHOD__, '1.19' );
-
-               $fsFile = new FSFile( $path );
-
-               return $fsFile->getProps();
-       }
-
-       /**
-        * Get a SHA-1 hash of a file in the local filesystem, in base-36 lower case
-        * encoding, zero padded to 31 digits.
-        *
-        * 160 log 2 / log 36 = 30.95, so the 160-bit hash fills 31 digits in base 36
-        * fairly neatly.
-        *
-        * @param string $path
-        * @return bool|string False on failure
-        * @deprecated since 1.19
-        */
-       static function sha1Base36( $path ) {
-               wfDeprecated( __METHOD__, '1.19' );
-
-               $fsFile = new FSFile( $path );
-
-               return $fsFile->getSha1Base36();
-       }
-
        /**
         * @return array HTTP header name/value map to use for HEAD/GET request responses
         */
index 300e68e..8824b66 100644 (file)
@@ -49,10 +49,10 @@ class LocalFile extends File {
        /** @var bool Does the file exist on disk? (loadFromXxx) */
        protected $fileExists;
 
-       /** @var int image width */
+       /** @var int Image width */
        protected $width;
 
-       /** @var int image height */
+       /** @var int Image height */
        protected $height;
 
        /** @var int Returned by getimagesize (loadFromXxx) */
@@ -91,10 +91,10 @@ class LocalFile extends File {
        /** @var int Result of the query for the file's history (nextHistoryLine) */
        private $historyRes;
 
-       /** @var string Major mime type */
+       /** @var string Major MIME type */
        private $major_mime;
 
-       /** @var string Minor mime type */
+       /** @var string Minor MIME type */
        private $minor_mime;
 
        /** @var string Upload timestamp */
@@ -166,7 +166,7 @@ class LocalFile extends File {
         * Create a LocalFile from a SHA-1 key
         * Do not call this except from inside a repo class.
         *
-        * @param string $sha1 base-36 SHA-1
+        * @param string $sha1 Base-36 SHA-1
         * @param LocalRepo $repo
         * @param string|bool $timestamp MW_timestamp (optional)
         * @return bool|LocalFile
@@ -379,6 +379,7 @@ class LocalFile extends File {
 
        /**
         * Load file metadata from the DB
+        * @param int $flags
         */
        function loadFromDB( $flags = 0 ) {
                # Polymorphic function name to distinguish foreign and local fetches
@@ -437,7 +438,7 @@ class LocalFile extends File {
        /**
         * @param DatabaseBase $dbr
         * @param string $fname
-        * @return array|false
+        * @return array|bool
         */
        private function loadFieldsWithTimestamp( $dbr, $fname ) {
                $fieldMap = false;
@@ -594,6 +595,7 @@ class LocalFile extends File {
 
                # Don't destroy file info of missing files
                if ( !$this->fileExists ) {
+                       $this->unlock();
                        wfDebug( __METHOD__ . ": file does not exist, aborting\n" );
                        wfProfileOut( __METHOD__ );
 
@@ -604,6 +606,7 @@ class LocalFile extends File {
                list( $major, $minor ) = self::splitMime( $this->mime );
 
                if ( wfReadOnly() ) {
+                       $this->unlock();
                        wfProfileOut( __METHOD__ );
 
                        return;
@@ -782,7 +785,7 @@ class LocalFile extends File {
        }
 
        /**
-        * Returns the mime type of the file.
+        * Returns the MIME type of the file.
         * @return string
         */
        function getMimeType() {
@@ -831,7 +834,7 @@ class LocalFile extends File {
        /**
         * Get all thumbnail names previously generated for this file
         * @param string|bool $archiveName Name of an archive file, default false
-        * @return array first element is the base dir, then files in that base dir.
+        * @return array First element is the base dir, then files in that base dir.
         */
        function getThumbnails( $archiveName = false ) {
                if ( $archiveName ) {
@@ -929,6 +932,7 @@ class LocalFile extends File {
 
        /**
         * Delete cached transformed files for the current version only.
+        * @param array $options
         */
        function purgeThumbnails( $options = array() ) {
                global $wgUseSquid;
@@ -1266,6 +1270,7 @@ class LocalFile extends File {
                # Fail now if the file isn't there
                if ( !$this->fileExists ) {
                        wfDebug( __METHOD__ . ": File " . $this->getRel() . " went missing!\n" );
+                       $dbw->rollback( __METHOD__ );
                        wfProfileOut( __METHOD__ );
 
                        return false;
@@ -1845,7 +1850,7 @@ class LocalFile extends File {
         * Start a transaction and lock the image for update
         * Increments a reference counter if the lock is already held
         * @throws MWException Throws an error if the lock was not acquired
-        * @return bool success
+        * @return bool Success
         */
        function lock() {
                $dbw = $this->repo->getMasterDB();
@@ -2279,7 +2284,12 @@ class LocalFileDeleteBatch {
                $this->doDBInserts();
 
                // Removes non-existent file from the batch, so we don't get errors.
-               $this->deletionBatch = $this->removeNonexistentFiles( $this->deletionBatch );
+               $checkStatus = $this->removeNonexistentFiles( $this->deletionBatch );
+               if ( !$checkStatus->isGood() ) {
+                       $this->status->merge( $checkStatus );
+                       return $this->status;
+               }
+               $this->deletionBatch = $checkStatus->value;
 
                // Execute the file deletion batch
                $status = $this->file->repo->deleteBatch( $this->deletionBatch );
@@ -2311,7 +2321,7 @@ class LocalFileDeleteBatch {
        /**
         * Removes non-existent files from a deletion batch.
         * @param array $batch
-        * @return array
+        * @return Status
         */
        function removeNonexistentFiles( $batch ) {
                $files = $newBatch = array();
@@ -2322,6 +2332,10 @@ class LocalFileDeleteBatch {
                }
 
                $result = $this->file->repo->fileExistsBatch( $files );
+               if ( in_array( null, $result, true ) ) {
+                       return Status::newFatal( 'backend-fail-internal',
+                               $this->file->repo->getBackend()->getName() );
+               }
 
                foreach ( $batch as $batchItem ) {
                        if ( $result[$batchItem[0]] ) {
@@ -2329,7 +2343,7 @@ class LocalFileDeleteBatch {
                        }
                }
 
-               return $newBatch;
+               return Status::newGood( $newBatch );
        }
 }
 
@@ -2368,6 +2382,7 @@ class LocalFileRestoreBatch {
 
        /**
         * Add a file by ID
+        * @param int $fa_id
         */
        function addId( $fa_id ) {
                $this->ids[] = $fa_id;
@@ -2375,6 +2390,7 @@ class LocalFileRestoreBatch {
 
        /**
         * Add a whole lot of files by ID
+        * @param int[] $ids
         */
        function addIds( $ids ) {
                $this->ids = array_merge( $this->ids, $ids );
@@ -2568,7 +2584,12 @@ class LocalFileRestoreBatch {
                }
 
                // Remove missing files from batch, so we don't get errors when undeleting them
-               $storeBatch = $this->removeNonexistentFiles( $storeBatch );
+               $checkStatus = $this->removeNonexistentFiles( $storeBatch );
+               if ( !$checkStatus->isGood() ) {
+                       $status->merge( $checkStatus );
+                       return $status;
+               }
+               $storeBatch = $checkStatus->value;
 
                // Run the store batch
                // Use the OVERWRITE_SAME flag to smooth over a common error
@@ -2628,7 +2649,7 @@ class LocalFileRestoreBatch {
        /**
         * Removes non-existent files from a store batch.
         * @param array $triplets
-        * @return array
+        * @return Status
         */
        function removeNonexistentFiles( $triplets ) {
                $files = $filteredTriplets = array();
@@ -2637,6 +2658,10 @@ class LocalFileRestoreBatch {
                }
 
                $result = $this->file->repo->fileExistsBatch( $files );
+               if ( in_array( null, $result, true ) ) {
+                       return Status::newFatal( 'backend-fail-internal',
+                               $this->file->repo->getBackend()->getName() );
+               }
 
                foreach ( $triplets as $file ) {
                        if ( $result[$file[0]] ) {
@@ -2644,7 +2669,7 @@ class LocalFileRestoreBatch {
                        }
                }
 
-               return $filteredTriplets;
+               return Status::newGood( $filteredTriplets );
        }
 
        /**
@@ -2817,7 +2842,12 @@ class LocalFileMoveBatch {
                $status = $repo->newGood();
 
                $triplets = $this->getMoveTriplets();
-               $triplets = $this->removeNonexistentFiles( $triplets );
+               $checkStatus = $this->removeNonexistentFiles( $triplets );
+               if ( !$checkStatus->isGood() ) {
+                       $status->merge( $checkStatus );
+                       return $status;
+               }
+               $triplets = $checkStatus->value;
                $destFile = wfLocalFile( $this->target );
 
                $this->file->lock(); // begin
@@ -2829,6 +2859,7 @@ class LocalFileMoveBatch {
                // cleanupTarget() to trigger. It would delete the C files and cause data loss.
                $statusDb = $this->doDBUpdates();
                if ( !$statusDb->isGood() ) {
+                       $destFile->unlock();
                        $this->file->unlockAndRollback();
                        $statusDb->ok = false;
 
@@ -2846,6 +2877,7 @@ class LocalFileMoveBatch {
                if ( !$statusMove->isGood() ) {
                        // Delete any files copied over (while the destination is still locked)
                        $this->cleanupTarget( $triplets );
+                       $destFile->unlock();
                        $this->file->unlockAndRollback(); // unlocks the destination
                        wfDebugLog( 'imagemove', "Error in moving files: " . $statusMove->getWikiText() );
                        $statusMove->ok = false;
@@ -2942,7 +2974,7 @@ class LocalFileMoveBatch {
        /**
         * Removes non-existent files from move batch.
         * @param array $triplets
-        * @return array
+        * @return Status
         */
        function removeNonexistentFiles( $triplets ) {
                $files = array();
@@ -2952,8 +2984,12 @@ class LocalFileMoveBatch {
                }
 
                $result = $this->file->repo->fileExistsBatch( $files );
-               $filteredTriplets = array();
+               if ( in_array( null, $result, true ) ) {
+                       return Status::newFatal( 'backend-fail-internal',
+                               $this->file->repo->getBackend()->getName() );
+               }
 
+               $filteredTriplets = array();
                foreach ( $triplets as $file ) {
                        if ( $result[$file[0]] ) {
                                $filteredTriplets[] = $file;
@@ -2962,12 +2998,13 @@ class LocalFileMoveBatch {
                        }
                }
 
-               return $filteredTriplets;
+               return Status::newGood( $filteredTriplets );
        }
 
        /**
         * Cleanup a partially moved array of triplets by deleting the target
         * files. Called if something went wrong half way.
+        * @param array $triplets
         */
        function cleanupTarget( $triplets ) {
                // Create dest pairs from the triplets
@@ -2983,6 +3020,7 @@ class LocalFileMoveBatch {
        /**
         * Cleanup a fully moved array of triplets by deleting the source files.
         * Called at the end of the move process if everything else went ok.
+        * @param array $triplets
         */
        function cleanupSource( $triplets ) {
                // Create source file names from the triplets
index ca92496..710058f 100644 (file)
@@ -79,7 +79,7 @@ class OldLocalFile extends LocalFile {
         * Create a OldLocalFile from a SHA-1 key
         * Do not call this except from inside a repo class.
         *
-        * @param string $sha1 base-36 SHA-1
+        * @param string $sha1 Base-36 SHA-1
         * @param LocalRepo $repo
         * @param string|bool $timestamp MW_timestamp (optional)
         *
@@ -130,7 +130,7 @@ class OldLocalFile extends LocalFile {
         * @param Title $title
         * @param FileRepo $repo
         * @param string $time Timestamp or null to load by archive name
-        * @param string $archiveName archive name or null to load by timestamp
+        * @param string $archiveName Archive name or null to load by timestamp
         * @throws MWException
         */
        function __construct( $title, $repo, $time, $archiveName ) {
@@ -404,4 +404,18 @@ class OldLocalFile extends LocalFile {
 
                return true;
        }
+
+       /**
+        * If archive name is an empty string, then file does not "exist"
+        *
+        * This is the case for a couple files on Wikimedia servers where
+        * the old version is "lost".
+        */
+       public function exists() {
+               $archiveName = $this->getArchiveName();
+               if ( $archiveName === '' || !is_string( $archiveName ) ) {
+                       return false;
+               }
+               return parent::exists();
+       }
 }
index 837a731..b0a593d 100644 (file)
 abstract class ImageGalleryBase extends ContextSource {
        /**
         * @var array Gallery images
-        * @deprecated in 1.23 (was declared "var") and will be removed in 1.24
+        * @deprecated since 1.23 (was declared "var") and will be removed in 1.24
         */
        public $mImages;
 
        /**
         * @var bool Whether to show the filesize in bytes in categories
-        * @deprecated in 1.23 (was declared "var") and will be removed in 1.24
+        * @deprecated since 1.23 (was declared "var") and will be removed in 1.24
         */
        public $mShowBytes;
 
        /**
         * @var bool Whether to show the filename. Default: true
-        * @deprecated in 1.23 (was declared "var") and will be removed in 1.24
+        * @deprecated since 1.23 (was declared "var") and will be removed in 1.24
         */
        public $mShowFilename;
 
        /**
         * @var string Gallery mode. Default: traditional
-        * @deprecated in 1.23 (was declared "var") and will be removed in 1.24
+        * @deprecated since 1.23 (was declared "var") and will be removed in 1.24
         */
        public $mMode;
 
        /**
         * @var bool|string Gallery caption. Default: false
-        * @deprecated in 1.23 (was declared "var") and will be removed in 1.24
+        * @deprecated since 1.23 (was declared "var") and will be removed in 1.24
         */
        public $mCaption = false;
 
        /**
         * @var bool Hide blacklisted images?
-        * @deprecated in 1.23 (was declared "var") and will be removed in 1.24
+        * @deprecated since 1.23 (was declared "var") and will be removed in 1.24
         */
        public $mHideBadImages;
 
@@ -86,19 +86,25 @@ abstract class ImageGalleryBase extends ContextSource {
         * should use to get a gallery.
         *
         * @param string|bool $mode Mode to use. False to use the default
+        * @param IContextSource|null $context
+        * @return ImageGalleryBase
         * @throws MWException
         */
-       static function factory( $mode = false ) {
-               global $wgGalleryOptions, $wgContLang;
+       static function factory( $mode = false, IContextSource $context = null ) {
+               global $wgContLang;
                self::loadModes();
+               if ( !$context ) {
+                       $context = RequestContext::getMainAndWarn( __METHOD__ );
+               }
                if ( !$mode ) {
-                       $mode = $wgGalleryOptions['mode'];
+                       $galleryOpions = $context->getConfig()->get( 'GalleryOptions' );
+                       $mode = $galleryOpions['mode'];
                }
 
                $mode = $wgContLang->lc( $mode );
 
                if ( isset( self::$modeMapping[$mode] ) ) {
-                       return new self::$modeMapping[$mode]( $mode );
+                       return new self::$modeMapping[$mode]( $mode, $context );
                } else {
                        throw new MWException( "No gallery class registered for mode $mode" );
                }
@@ -123,18 +129,24 @@ abstract class ImageGalleryBase extends ContextSource {
         *
         * You should not call this directly, but instead use
         * ImageGalleryBase::factory().
+        * @param string $mode
+        * @param IContextSource|null $context
         */
-       function __construct( $mode = 'traditional' ) {
-               global $wgGalleryOptions;
+       function __construct( $mode = 'traditional', IContextSource $context = null ) {
+               if ( $context ) {
+                       $this->setContext( $context );
+               }
+
+               $galleryOptions = $this->getConfig()->get( 'GalleryOptions' );
                $this->mImages = array();
-               $this->mShowBytes = $wgGalleryOptions['showBytes'];
+               $this->mShowBytes = $galleryOptions['showBytes'];
                $this->mShowFilename = true;
                $this->mParser = false;
                $this->mHideBadImages = false;
-               $this->mPerRow = $wgGalleryOptions['imagesPerRow'];
-               $this->mWidths = $wgGalleryOptions['imageWidth'];
-               $this->mHeights = $wgGalleryOptions['imageHeight'];
-               $this->mCaptionLength = $wgGalleryOptions['captionLength'];
+               $this->mPerRow = $galleryOptions['imagesPerRow'];
+               $this->mWidths = $galleryOptions['imageWidth'];
+               $this->mHeights = $galleryOptions['imageHeight'];
+               $this->mCaptionLength = $galleryOptions['captionLength'];
                $this->mMode = $mode;
        }
 
@@ -154,6 +166,7 @@ abstract class ImageGalleryBase extends ContextSource {
 
        /**
         * Set bad image flag
+        * @param bool $flag
         */
        function setHideBadImages( $flag = true ) {
                $this->mHideBadImages = $flag;
index bb55c89..52a49dd 100644 (file)
@@ -76,7 +76,7 @@ class PackedImageGallery extends TraditionalImageGallery {
        }
 
        /**
-        * @param MediaTransformOutput|bool $thumb the thumbnail, or false if no
+        * @param MediaTransformOutput|bool $thumb The thumbnail, or false if no
         *   thumb (which can happen)
         * @return float
         */
@@ -95,6 +95,7 @@ class PackedImageGallery extends TraditionalImageGallery {
        /**
         * Add javascript which auto-justifies the rows by manipulating the image sizes.
         * Also ensures that the hover version of this degrades gracefully.
+        * @return array
         */
        protected function getModules() {
                return array( 'mediawiki.page.gallery' );
@@ -103,6 +104,7 @@ class PackedImageGallery extends TraditionalImageGallery {
        /**
         * Do not support per-row on packed. It really doesn't work
         * since the images have varying widths.
+        * @param int $num
         */
        public function setPerRow( $num ) {
                return;
diff --git a/includes/htmlform/HTMLAutoCompleteSelectField.php b/includes/htmlform/HTMLAutoCompleteSelectField.php
new file mode 100644 (file)
index 0000000..4905362
--- /dev/null
@@ -0,0 +1,165 @@
+<?php
+
+/**
+ * Text field for selecting a value from a large list of possible values, with
+ * auto-completion and optionally with a select dropdown for selecting common
+ * options.
+ *
+ * If one of 'options-messages', 'options', or 'options-message' is provided
+ * and non-empty, the select dropdown will be shown. An 'other' key will be
+ * appended using message 'htmlform-selectorother-other' if not already
+ * present.
+ *
+ * Besides the parameters recognized by HTMLTextField, the following are
+ * recognized:
+ *   options-messages - As for HTMLSelectField
+ *   options - As for HTMLSelectField
+ *   options-message - As for HTMLSelectField
+ *   autocomplete - Associative array mapping display text to values.
+ *   autocomplete-messages - Like autocomplete, but keys are message names.
+ *   require-match - Boolean, if true the value must be in the options or the
+ *     autocomplete.
+ *   other-message - Message to use instead of htmlform-selectorother-other for
+ *      the 'other' message.
+ *   other - Raw text to use for the 'other' message
+ *
+ */
+class HTMLAutoCompleteSelectField extends HTMLTextField {
+       protected $autocomplete = array();
+
+       function __construct( $params ) {
+               $params += array(
+                       'require-match' => false,
+               );
+
+               parent::__construct( $params );
+
+               if ( array_key_exists( 'autocomplete-messages', $this->mParams ) ) {
+                       foreach ( $this->mParams['autocomplete-messages'] as $key => $value ) {
+                               $key = $this->msg( $key )->plain();
+                               $this->autocomplete[$key] = strval( $value );
+                       }
+               } elseif ( array_key_exists( 'autocomplete', $this->mParams ) ) {
+                       foreach ( $this->mParams['autocomplete'] as $key => $value ) {
+                               $this->autocomplete[$key] = strval( $value );
+                       }
+               }
+               if ( !is_array( $this->autocomplete ) || !$this->autocomplete ) {
+                       throw new MWException( 'HTMLAutoCompleteSelectField called without any autocompletions' );
+               }
+
+               $this->getOptions();
+               if ( $this->mOptions && !in_array( 'other', $this->mOptions, true ) ) {
+                       if ( isset( $params['other-message'] ) ) {
+                               $msg = wfMessage( $params['other-message'] )->text();
+                       } elseif ( isset( $params['other'] ) ) {
+                               $msg = $params['other'];
+                       } else {
+                               $msg = wfMessage( 'htmlform-selectorother-other' )->text();
+                       }
+                       $this->mOptions[$msg] = 'other';
+               }
+       }
+
+       function loadDataFromRequest( $request ) {
+               if ( $request->getCheck( $this->mName ) ) {
+                       $val = $request->getText( $this->mName . '-select', 'other' );
+
+                       if ( $val === 'other' ) {
+                               $val = $request->getText( $this->mName );
+                               if ( isset( $this->autocomplete[$val] ) ) {
+                                       $val = $this->autocomplete[$val];
+                               }
+                       }
+
+                       return $val;
+               } else {
+                       return $this->getDefault();
+               }
+       }
+
+       function validate( $value, $alldata ) {
+               $p = parent::validate( $value, $alldata );
+
+               if ( $p !== true ) {
+                       return $p;
+               }
+
+               $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
+
+               if ( in_array( strval( $value ), $validOptions, true ) ) {
+                       return true;
+               } elseif ( in_array( strval( $value ), $this->autocomplete, true ) ) {
+                       return true;
+               } elseif ( $this->mParams['require-match'] ) {
+                       return $this->msg( 'htmlform-select-badoption' )->parse();
+               }
+
+               return true;
+       }
+
+       function getAttributes( array $list ) {
+               $attribs = array(
+                       'type' => 'text',
+                       'data-autocomplete' => FormatJson::encode( array_keys( $this->autocomplete ) ),
+               ) + parent::getAttributes( $list );
+
+               if ( $this->getOptions() ) {
+                       $attribs['data-hide-if'] = FormatJson::encode(
+                               array( '!==', $this->mName . '-select', 'other' )
+                       );
+               }
+
+               return $attribs;
+       }
+
+       function getInputHTML( $value ) {
+               $oldClass = $this->mClass;
+               $this->mClass = (array)$this->mClass;
+
+               $valInSelect = false;
+               $ret = '';
+
+               if ( $this->getOptions() ) {
+                       if ( $value !== false ) {
+                               $value = strval( $value );
+                               $valInSelect = in_array(
+                                       $value, HTMLFormField::flattenOptions( $this->getOptions() ), true
+                               );
+                       }
+
+                       $selected = $valInSelect ? $value : 'other';
+                       $select = new XmlSelect( $this->mName . '-select', $this->mID . '-select', $selected );
+                       $select->addOptions( $this->getOptions() );
+                       $select->setAttribute( 'class', 'mw-htmlform-select-or-other' );
+
+                       if ( !empty( $this->mParams['disabled'] ) ) {
+                               $select->setAttribute( 'disabled', 'disabled' );
+                       }
+
+                       if ( isset( $this->mParams['tabindex'] ) ) {
+                               $select->setAttribute( 'tabindex', $this->mParams['tabindex'] );
+                       }
+
+                       $ret = $select->getHTML() . "<br />\n";
+
+                       $this->mClass[] = 'mw-htmlform-hide-if';
+               }
+
+               if ( $valInSelect ) {
+                       $value = '';
+               } else {
+                       $key = array_search( strval( $value ), $this->autocomplete, true );
+                       if ( $key !== false ) {
+                               $value = $key;
+                       }
+               }
+
+               $this->mClass[] = 'mw-htmlform-autocomplete';
+               $ret .= parent::getInputHTML( $valInSelect ? '' : $value );
+               $this->mClass = $oldClass;
+
+               return $ret;
+       }
+
+}
index a0dd370..5f70362 100644 (file)
@@ -5,6 +5,8 @@
  */
 class HTMLCheckField extends HTMLFormField {
        function getInputHTML( $value ) {
+               global $wgUseMediaWikiUIEverywhere;
+
                if ( !empty( $this->mParams['invert'] ) ) {
                        $value = !$value;
                }
@@ -26,9 +28,19 @@ class HTMLCheckField extends HTMLFormField {
                                ),
                                Xml::check( $this->mName, $value, $attr ) . $this->mLabel );
                } else {
-                       return Xml::check( $this->mName, $value, $attr )
+                       $chkLabel = Xml::check( $this->mName, $value, $attr )
                        . '&#160;'
                        . Html::rawElement( 'label', array( 'for' => $this->mID ), $this->mLabel );
+
+                       if ( $wgUseMediaWikiUIEverywhere ) {
+                               $chkLabel = Html::rawElement(
+                                       'div',
+                                       array( 'class' => 'mw-ui-checkbox' ),
+                                       $chkLabel
+                               );
+                       }
+
+                       return $chkLabel;
                }
        }
 
index 606523b..6c538fd 100644 (file)
@@ -113,8 +113,9 @@ class HTMLCheckMatrix extends HTMLFormField implements HTMLNestedFilterable {
                        foreach ( $columns as $columnTag ) {
                                $thisTag = "$columnTag-$rowTag";
                                // Construct the checkbox
+                               $thisId = "{$this->mID}-$thisTag";
                                $thisAttribs = array(
-                                       'id' => "{$this->mID}-$thisTag",
+                                       'id' => $thisId,
                                        'value' => $thisTag,
                                );
                                $checked = in_array( $thisTag, (array)$value, true );
@@ -125,10 +126,17 @@ class HTMLCheckMatrix extends HTMLFormField implements HTMLNestedFilterable {
                                        $checked = true;
                                        $thisAttribs['disabled'] = 1;
                                }
+                               $chkBox = Xml::check( "{$this->mName}[]", $checked, $attribs + $thisAttribs );
+                               if ( $this->mParent->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
+                                       $chkBox = Html::openElement( 'div', array( 'class' => 'mw-ui-checkbox' ) ) .
+                                               $chkBox .
+                                               Html::element( 'label', array( 'for' => $thisId ) ) .
+                                               Html::closeElement( 'div' );
+                               }
                                $rowContents .= Html::rawElement(
                                        'td',
                                        array(),
-                                       Xml::check( "{$this->mName}[]", $checked, $attribs + $thisAttribs )
+                                       $chkBox
                                );
                        }
                        $tableContents .= Html::rawElement( 'tr', array(), "\n$rowContents\n" );
index 4f1b530..77924ef 100644 (file)
@@ -16,6 +16,8 @@ class HTMLEditTools extends HTMLFormField {
        }
 
        /**
+        * @param string $value
+        * @return string
         * @since 1.20
         */
        public function getDiv( $value ) {
@@ -25,6 +27,8 @@ class HTMLEditTools extends HTMLFormField {
        }
 
        /**
+        * @param string $value
+        * @return string
         * @since 1.20
         */
        public function getRaw( $value ) {
index 3334694..5fda7bd 100644 (file)
@@ -50,6 +50,7 @@
  *    'default'             -- default value when the form is displayed
  *    'id'                  -- HTML id attribute
  *    'cssclass'            -- CSS class
+ *    'csshelpclass'        -- CSS class used to style help text
  *    'options'             -- associative array mapping labels to values.
  *                             Some field types support multi-level arrays.
  *    'options-messages'    -- associative array mapping message keys to values.
@@ -106,6 +107,7 @@ class HTMLForm extends ContextSource {
                'select' => 'HTMLSelectField',
                'radio' => 'HTMLRadioField',
                'multiselect' => 'HTMLMultiSelectField',
+               'limitselect' => 'HTMLSelectLimitField',
                'check' => 'HTMLCheckField',
                'toggle' => 'HTMLCheckField',
                'int' => 'HTMLIntField',
@@ -118,6 +120,7 @@ class HTMLForm extends ContextSource {
                'edittools' => 'HTMLEditTools',
                'checkmatrix' => 'HTMLCheckMatrix',
                'cloner' => 'HTMLFormFieldCloner',
+               'autocompleteselect' => 'HTMLAutoCompleteSelectField',
                // HTMLTextField will output the correct type="" attribute automagically.
                // There are about four zillion other HTML5 input types, like range, but
                // we don't use those at the moment, so no point in adding all of them.
@@ -298,7 +301,11 @@ class HTMLForm extends ContextSource {
         * @return string
         */
        public function getDisplayFormat() {
-               return $this->displayFormat;
+               $format = $this->displayFormat;
+               if ( !$this->getConfig()->get( 'HTMLFormAllowTableFormat' ) && $format === 'table' ) {
+                       $format = 'div';
+               }
+               return $format;
        }
 
        /**
@@ -351,7 +358,7 @@ class HTMLForm extends ContextSource {
         * @param array $descriptor Input Descriptor, as described above
         *
         * @throws MWException
-        * @return HTMLFormField subclass
+        * @return HTMLFormField Instance of a subclass of HTMLFormField
         */
        public static function loadInputFromParameters( $fieldname, $descriptor ) {
                $class = self::getClassFromDescriptor( $fieldname, $descriptor );
@@ -466,6 +473,9 @@ class HTMLForm extends ContextSource {
                        if ( !empty( $field->mParams['nodata'] ) ) {
                                continue;
                        }
+                       if ( $field->isHidden( $this->mFieldData ) ) {
+                               continue;
+                       }
                        if ( $field->validate(
                                        $this->mFieldData[$fieldname],
                                        $this->mFieldData )
@@ -621,7 +631,7 @@ class HTMLForm extends ContextSource {
        /**
         * Add footer text, inside the form.
         *
-        * @param string $msg complete text of message to display
+        * @param string $msg Complete text of message to display
         * @param string|null $section The section to add the footer text to
         *
         * @return HTMLForm $this for chaining calls (since 1.20)
@@ -740,8 +750,8 @@ class HTMLForm extends ContextSource {
         * Only useful when the method is "post".
         *
         * @since 1.24
-        * @param string|array Salt to use
-        * @return HTMLForm $this for chaining calls
+        * @param string|array $salt Salt to use
+        * @return HTMLForm $this For chaining calls
         */
        public function setTokenSalt( $salt ) {
                $this->mTokenSalt = $salt;
@@ -759,7 +769,7 @@ class HTMLForm extends ContextSource {
         *
         * @param bool|string|array|Status $submitResult Output from HTMLForm::trySubmit()
         *
-        * @return Nothing, should be last call
+        * @return void Nothing, should be last call
         */
        function displayForm( $submitResult ) {
                $this->getOutput()->addHTML( $this->getHTML( $submitResult ) );
@@ -838,8 +848,6 @@ class HTMLForm extends ContextSource {
         * @return string HTML.
         */
        function getHiddenFields() {
-               global $wgArticlePath;
-
                $html = '';
                if ( $this->getMethod() == 'post' ) {
                        $html .= Html::hidden(
@@ -850,7 +858,8 @@ class HTMLForm extends ContextSource {
                        $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n";
                }
 
-               if ( strpos( $wgArticlePath, '?' ) !== false && $this->getMethod() == 'get' ) {
+               $articlePath = $this->getConfig()->get( 'ArticlePath' );
+               if ( strpos( $articlePath, '?' ) !== false && $this->getMethod() == 'get' ) {
                        $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n";
                }
 
@@ -868,6 +877,7 @@ class HTMLForm extends ContextSource {
         */
        function getButtons() {
                $buttons = '';
+               $useMediaWikiUIEverywhere = $this->getConfig()->get( 'UseMediaWikiUIEverywhere' );
 
                if ( $this->mShowSubmit ) {
                        $attribs = array();
@@ -886,15 +896,17 @@ class HTMLForm extends ContextSource {
 
                        $attribs['class'] = array( 'mw-htmlform-submit' );
 
+                       if ( $this->isVForm() || $useMediaWikiUIEverywhere ) {
+                               array_push( $attribs['class'], 'mw-ui-button', 'mw-ui-constructive' );
+                       }
+
                        if ( $this->isVForm() ) {
                                // mw-ui-block is necessary because the buttons aren't necessarily in an
                                // immediate child div of the vform.
                                // @todo Let client specify if the primary submit button is progressive or destructive
                                array_push(
                                        $attribs['class'],
-                                       'mw-ui-button',
                                        'mw-ui-big',
-                                       'mw-ui-constructive',
                                        'mw-ui-block'
                                );
                        }
@@ -927,6 +939,17 @@ class HTMLForm extends ContextSource {
                                $attrs['id'] = $button['id'];
                        }
 
+                       if ( $this->isVForm() || $useMediaWikiUIEverywhere ) {
+                               if ( isset( $attrs['class'] ) ) {
+                                       $attrs['class'] .= ' mw-ui-button';
+                               } else {
+                                       $attrs['class'] = 'mw-ui-button';
+                               }
+                               if ( $this->isVForm() ) {
+                                       $attrs['class'] .= ' mw-ui-big mw-ui-block';
+                               }
+                       }
+
                        $buttons .= Html::element( 'input', $attrs ) . "\n";
                }
 
@@ -979,7 +1002,7 @@ class HTMLForm extends ContextSource {
        /**
         * Format a stack of error messages into a single HTML string
         *
-        * @param array $errors of message keys/values
+        * @param array $errors Array of message keys/values
         *
         * @return string HTML, a "<ul>" list of errors
         */
@@ -1009,7 +1032,7 @@ class HTMLForm extends ContextSource {
        /**
         * Set the text for the submit button
         *
-        * @param string $t plaintext.
+        * @param string $t Plaintext
         *
         * @return HTMLForm $this for chaining calls (since 1.20)
         */
@@ -1023,12 +1046,15 @@ class HTMLForm extends ContextSource {
         * Set the text for the submit button to a message
         * @since 1.19
         *
-        * @param string $msg Message key
+        * @param string|Message $msg Message key or Message object
         *
         * @return HTMLForm $this for chaining calls (since 1.20)
         */
        public function setSubmitTextMsg( $msg ) {
-               $this->setSubmitText( $this->msg( $msg )->text() );
+               if ( !$msg instanceof Message ) {
+                       $msg = $this->msg( $msg );
+               }
+               $this->setSubmitText( $msg->text() );
 
                return $this;
        }
@@ -1142,12 +1168,15 @@ class HTMLForm extends ContextSource {
         * this message as its "<legend>" element.
         * @since 1.19
         *
-        * @param string $msg Message key
+        * @param string|Message $msg Message key or Message object
         *
         * @return HTMLForm $this for chaining calls (since 1.20)
         */
        public function setWrapperLegendMsg( $msg ) {
-               $this->setWrapperLegend( $this->msg( $msg )->text() );
+               if ( !$msg instanceof Message ) {
+                       $msg = $this->msg( $msg );
+               }
+               $this->setWrapperLegend( $msg->text() );
 
                return $this;
        }
@@ -1238,6 +1267,9 @@ class HTMLForm extends ContextSource {
                                // Close enough to a div.
                                $getFieldHtmlMethod = 'getDiv';
                                break;
+                       case 'div':
+                               $getFieldHtmlMethod = 'getDiv';
+                               break;
                        default:
                                $getFieldHtmlMethod = 'get' . ucfirst( $displayFormat );
                }
@@ -1369,7 +1401,7 @@ class HTMLForm extends ContextSource {
         *
         * @param array $data
         *
-        * @return
+        * @return array
         */
        function filterDataForSubmit( $data ) {
                return $data;
@@ -1411,20 +1443,19 @@ class HTMLForm extends ContextSource {
         * @return string
         */
        public function getAction() {
-               global $wgScript, $wgArticlePath;
-
                // If an action is alredy provided, return it
                if ( $this->mAction !== false ) {
                        return $this->mAction;
                }
 
-               // Check whether we are in GET mode and $wgArticlePath contains a "?"
+               $articlePath = $this->getConfig()->get( 'ArticlePath' );
+               // Check whether we are in GET mode and the ArticlePath contains a "?"
                // meaning that getLocalURL() would return something like "index.php?title=...".
                // As browser remove the query string before submitting GET forms,
-               // it means that the title would be lost. In such case use $wgScript instead
+               // it means that the title would be lost. In such case use wfScript() instead
                // and put title in an hidden field (see getHiddenFields()).
-               if ( strpos( $wgArticlePath, '?' ) !== false && $this->getMethod() === 'get' ) {
-                       return $wgScript;
+               if ( strpos( $articlePath, '?' ) !== false && $this->getMethod() === 'get' ) {
+                       return wfScript();
                }
 
                return $this->getTitle()->getLocalURL();
index 8076e8a..4cf2394 100644 (file)
@@ -13,6 +13,7 @@ abstract class HTMLFormField {
        protected $mLabel; # String label.  Set on construction
        protected $mID;
        protected $mClass = '';
+       protected $mHelpClass = false;
        protected $mDefault;
        protected $mOptions = false;
        protected $mOptionsLabelsNotFromMessage = false;
@@ -34,7 +35,7 @@ abstract class HTMLFormField {
         * the input object itself.  It should not implement the surrounding
         * table cells/rows, or labels/help messages.
         *
-        * @param string $value the value to set the input to; eg a default
+        * @param string $value The value to set the input to; eg a default
         *     text for a text input.
         *
         * @return string Valid HTML.
@@ -112,7 +113,7 @@ abstract class HTMLFormField {
                                }
                                $data = $data[$key];
                        }
-                       $testValue = $data;
+                       $testValue = (string)$data;
                        break;
                }
 
@@ -124,7 +125,7 @@ abstract class HTMLFormField {
         *
         * @param array $alldata
         * @param array $params
-        * @return boolean
+        * @return bool
         */
        protected function isHiddenRecurse( array $alldata, array $params ) {
                $origParams = $params;
@@ -249,7 +250,7 @@ abstract class HTMLFormField {
         * @param string|array $value The value the field was submitted with
         * @param array $alldata The data collected from the form
         *
-        * @return bool true to cancel the submission
+        * @return bool True to cancel the submission
         */
        function cancelSubmit( $value, $alldata ) {
                return false;
@@ -263,7 +264,7 @@ abstract class HTMLFormField {
         * @param string|array $value The value the field was submitted with
         * @param array $alldata The data collected from the form
         *
-        * @return bool|string true on success, or String error to display, or
+        * @return bool|string True on success, or String error to display, or
         *   false to fail validation without displaying an error.
         */
        function validate( $value, $alldata ) {
@@ -397,6 +398,10 @@ abstract class HTMLFormField {
                        $this->mClass = $params['cssclass'];
                }
 
+               if ( isset( $params['csshelpclass'] ) ) {
+                       $this->mHelpClass = $params['csshelpclass'];
+               }
+
                if ( isset( $params['validation-callback'] ) ) {
                        $this->mValidationCallback = $params['validation-callback'];
                }
@@ -562,7 +567,11 @@ abstract class HTMLFormField {
                        $rowAttributes['class'] = 'mw-htmlform-hide-if';
                }
 
-               $row = Html::rawElement( 'td', array( 'colspan' => 2, 'class' => 'htmlform-tip' ), $helptext );
+               $tdClasses = array( 'htmlform-tip' );
+               if ( $this->mHelpClass !== false ) {
+                       $tdClasses[] = $this->mHelpClass;
+               }
+               $row = Html::rawElement( 'td', array( 'colspan' => 2, 'class' => $tdClasses ), $helptext );
                $row = Html::rawElement( 'tr', $rowAttributes, $row );
 
                return $row;
@@ -584,6 +593,9 @@ abstract class HTMLFormField {
                $wrapperAttributes = array(
                        'class' => 'htmlform-tip',
                );
+               if ( $this->mHelpClass !== false ) {
+                       $wrapperAttributes['class'] .= " {$this->mHelpClass}";
+               }
                if ( $this->mHideIf ) {
                        $wrapperAttributes['data-hide-if'] = FormatJson::encode( $this->mHideIf );
                        $wrapperAttributes['class'] .= ' mw-htmlform-hide-if';
index 597a03f..029911c 100644 (file)
@@ -80,7 +80,7 @@ class HTMLFormFieldCloner extends HTMLFormField {
         * specified key.
         *
         * @param string $key Array key under which these fields should be named
-        * @return HTMLFormFields[]
+        * @return HTMLFormField[]
         */
        protected function createFieldsForKey( $key ) {
                $fields = array();
@@ -303,6 +303,7 @@ class HTMLFormFieldCloner extends HTMLFormField {
                                'cssclass' => 'mw-htmlform-cloner-delete-button',
                                'default' => $this->msg( $label )->text(),
                        ) );
+                       $field->mParent = $this->mParent;
                        $v = $field->getDefault();
 
                        if ( $displayFormat === 'table' ) {
@@ -373,6 +374,7 @@ class HTMLFormFieldCloner extends HTMLFormField {
                        'cssclass' => 'mw-htmlform-cloner-create-button',
                        'default' => $this->msg( $label )->text(),
                ) );
+               $field->mParent = $this->mParent;
                $html .= $field->getInputHTML( $field->getDefault() );
 
                return $html;
index 6ea95ed..e32c0bb 100644 (file)
@@ -21,6 +21,8 @@ class HTMLHiddenField extends HTMLFormField {
        }
 
        /**
+        * @param string $value
+        * @return string
         * @since 1.20
         */
        public function getDiv( $value ) {
@@ -28,6 +30,8 @@ class HTMLHiddenField extends HTMLFormField {
        }
 
        /**
+        * @param string $value
+        * @return string
         * @since 1.20
         */
        public function getRaw( $value ) {
index cff8202..a422047 100644 (file)
@@ -23,6 +23,8 @@ class HTMLInfoField extends HTMLFormField {
        }
 
        /**
+        * @param string $value
+        * @return string
         * @since 1.20
         */
        public function getDiv( $value ) {
@@ -34,6 +36,8 @@ class HTMLInfoField extends HTMLFormField {
        }
 
        /**
+        * @param string $value
+        * @return string
         * @since 1.20
         */
        public function getRaw( $value ) {
index 576f5cd..1b71ab9 100644 (file)
@@ -47,6 +47,7 @@ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable
                        } else {
                                $thisAttribs = array( 'id' => "{$this->mID}-$info", 'value' => $info );
 
+                               // @todo: Make this use checkLabel for consistency purposes
                                $checkbox = Xml::check(
                                        $this->mName . '[]',
                                        in_array( $info, $value, true ),
index 2bf9f8b..a198037 100644 (file)
@@ -29,7 +29,7 @@ class HTMLSelectField extends HTMLFormField {
 
                $allowedParams = array( 'tabindex', 'size' );
                $customParams = $this->getAttributes( $allowedParams );
-               foreach( $customParams as $name => $value ) {
+               foreach ( $customParams as $name => $value ) {
                        $select->setAttribute( $name, $value );
                }
 
diff --git a/includes/htmlform/HTMLSelectLimitField.php b/includes/htmlform/HTMLSelectLimitField.php
new file mode 100644 (file)
index 0000000..e7f1c04
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * A limit dropdown, which accepts any valid number
+ */
+class HTMLSelectLimitField extends HTMLSelectField {
+       /**
+        * Basically don't do any validation. If it's a number that's fine. Also,
+        * add it to the list if it's not there already
+        *
+        * @param string $value
+        * @param array $alldata
+        * @return bool
+        */
+       function validate( $value, $alldata ) {
+               if ( $value == '' ) {
+                       return true;
+               }
+
+               // Let folks pick an explicit limit not from our list, as long as it's a real numbr.
+               if ( !in_array( $value, $this->mParams['options'] )
+                       && $value == intval( $value )
+                       && $value > 0
+               ) {
+                       // This adds the explicitly requested limit value to the drop-down,
+                       // then makes sure it's sorted correctly so when we output the list
+                       // later, the custom option doesn't just show up last.
+                       $this->mParams['options'][$this->mParent->getLanguage()->formatNum( $value )] =
+                               intval( $value );
+                       asort( $this->mParams['options'] );
+               }
+
+               return true;
+       }
+}
index 4fd1989..21173d2 100644 (file)
@@ -15,7 +15,6 @@ class HTMLTextAreaField extends HTMLFormField {
        function getInputHTML( $value ) {
                $attribs = array(
                                'id' => $this->mID,
-                               'name' => $this->mName,
                                'cols' => $this->getCols(),
                                'rows' => $this->getRows(),
                        ) + $this->getTooltipAndAccessKey();
@@ -34,7 +33,6 @@ class HTMLTextAreaField extends HTMLFormField {
                );
 
                $attribs += $this->getAttributes( $allowedParams );
-
-               return Html::element( 'textarea', $attribs, $value );
+               return Html::textarea( $this->mName, $value, $attribs );
        }
 }
index e584d88..10bc67f 100644 (file)
@@ -41,13 +41,14 @@ class HTMLTextField extends HTMLFormField {
                # Implement tiny differences between some field variants
                # here, rather than creating a new class for each one which
                # is essentially just a clone of this one.
+               $type = 'text';
                if ( isset( $this->mParams['type'] ) ) {
                        switch ( $this->mParams['type'] ) {
                                case 'int':
-                                       $attribs['type'] = 'number';
+                                       $type = 'number';
                                        break;
                                case 'float':
-                                       $attribs['type'] = 'number';
+                                       $type = 'number';
                                        $attribs['step'] = 'any';
                                        break;
                                # Pass through
@@ -55,11 +56,10 @@ class HTMLTextField extends HTMLFormField {
                                case 'password':
                                case 'file':
                                case 'url':
-                                       $attribs['type'] = $this->mParams['type'];
+                                       $type = $this->mParams['type'];
                                        break;
                        }
                }
-
-               return Html::element( 'input', $attribs );
+               return Html::input( $this->mName, $value, $type, $attribs );
        }
 }
index 8a01b32..31b93c8 100644 (file)
@@ -163,19 +163,26 @@ abstract class DatabaseInstaller {
        }
 
        /**
-        * Create database tables from scratch.
+        * Apply a SQL source file to the database as part of running an installation step.
         *
+        * @param string $sourceFileMethod
+        * @param string $stepName
+        * @param string $archiveTableMustNotExist
         * @return Status
         */
-       public function createTables() {
+       private function stepApplySourceFile(
+               $sourceFileMethod,
+               $stepName,
+               $archiveTableMustNotExist = false
+       ) {
                $status = $this->getConnection();
                if ( !$status->isOK() ) {
                        return $status;
                }
                $this->db->selectDB( $this->getVar( 'wgDBname' ) );
 
-               if ( $this->db->tableExists( 'archive', __METHOD__ ) ) {
-                       $status->warning( 'config-install-tables-exist' );
+               if ( $archiveTableMustNotExist && $this->db->tableExists( 'archive', __METHOD__ ) ) {
+                       $status->warning( "config-$stepName-tables-exist" );
                        $this->enableLB();
 
                        return $status;
@@ -184,11 +191,13 @@ abstract class DatabaseInstaller {
                $this->db->setFlag( DBO_DDLMODE ); // For Oracle's handling of schema files
                $this->db->begin( __METHOD__ );
 
-               $error = $this->db->sourceFile( $this->db->getSchemaPath() );
+               $error = $this->db->sourceFile(
+                       call_user_func( array( $this->db, $sourceFileMethod ) )
+               );
                if ( $error !== true ) {
                        $this->db->reportQueryError( $error, 0, '', __METHOD__ );
                        $this->db->rollback( __METHOD__ );
-                       $status->fatal( 'config-install-tables-failed', $error );
+                       $status->fatal( "config-$stepName-tables-failed", $error );
                } else {
                        $this->db->commit( __METHOD__ );
                }
@@ -200,6 +209,24 @@ abstract class DatabaseInstaller {
                return $status;
        }
 
+       /**
+        * Create database tables from scratch.
+        *
+        * @return Status
+        */
+       public function createTables() {
+               return $this->stepApplySourceFile( 'getSchemaPath', 'install', true );
+       }
+
+       /**
+        * Insert update keys into table to prevent running unneded updates.
+        *
+        * @return Status
+        */
+       public function insertUpdateKeys() {
+               return $this->stepApplySourceFile( 'getUpdateKeysPath', 'updates', false );
+       }
+
        /**
         * Create the tables for each extension the user enabled
         * @return Status
index 28dac46..193d592 100644 (file)
@@ -72,6 +72,7 @@ abstract class DatabaseUpdater {
                'PopulateImageSha1',
                'FixExtLinksProtocolRelative',
                'PopulateFilearchiveSha1',
+               'PopulateBacklinkNamespace'
        );
 
        /**
@@ -296,9 +297,9 @@ abstract class DatabaseUpdater {
         * @param string $tableName The table name
         * @param string $oldIndexName The old index name
         * @param string $newIndexName The new index name
+        * @param string $sqlPath The path to the SQL change path
         * @param bool $skipBothIndexExistWarning Whether to warn if both the old
         * and the new indexes exist. [facultative; by default, false]
-        * @param string $sqlPath The path to the SQL change path
         */
        public function renameExtensionIndex( $tableName, $oldIndexName, $newIndexName,
                $sqlPath, $skipBothIndexExistWarning = false
@@ -906,7 +907,7 @@ abstract class DatabaseUpdater {
                if ( $wgLocalisationCacheConf['manualRecache'] ) {
                        $this->rebuildLocalisationCache();
                }
-               MessageBlobStore::clear();
+               MessageBlobStore::getInstance()->clear();
                $this->output( "done.\n" );
        }
 
@@ -983,6 +984,7 @@ abstract class DatabaseUpdater {
 
        /**
         * Updates the timestamps in the transcache table
+        * @return bool
         */
        protected function doUpdateTranscacheField() {
                if ( $this->updateRowExists( 'convert transcache field' ) ) {
index f014032..544efb6 100644 (file)
@@ -38,9 +38,6 @@
  */
 abstract class Installer {
 
-       // This is the absolute minimum PHP version we can support
-       const MINIMUM_PHP_VERSION = '5.3.2';
-
        /**
         * The oldest version of PCRE we can support.
         *
@@ -111,6 +108,10 @@ abstract class Installer {
         * These may output warnings using showMessage(), and/or abort the
         * installation process by returning false.
         *
+        * For the WebInstaller these are only called on the Welcome page,
+        * if these methods have side-effects that should affect later page loads
+        * (as well as the generated stylesheet), use envPreps instead.
+        *
         * @var array
         */
        protected $envChecks = array(
@@ -118,7 +119,6 @@ abstract class Installer {
                'envCheckRegisterGlobals',
                'envCheckBrokenXML',
                'envCheckMagicQuotes',
-               'envCheckMagicSybase',
                'envCheckMbstring',
                'envCheckSafeMode',
                'envCheckXML',
@@ -131,15 +131,26 @@ abstract class Installer {
                'envCheckGit',
                'envCheckServer',
                'envCheckPath',
-               'envCheckExtension',
                'envCheckShellLocale',
                'envCheckUploadsDirectory',
                'envCheckLibicu',
                'envCheckSuhosinMaxValueLength',
                'envCheckCtype',
+               'envCheckIconv',
                'envCheckJSON',
        );
 
+       /**
+        * A list of environment preparation methods called by doEnvironmentPreps().
+        *
+        * @var array
+        */
+       protected $envPreps = array(
+               'envPrepExtension',
+               'envPrepServer',
+               'envPrepPath',
+       );
+
        /**
         * MediaWiki configuration globals that will eventually be passed through
         * to LocalSettings.php. The names only are given here, the defaults
@@ -207,6 +218,7 @@ abstract class Installer {
                '_LicenseCode' => 'none',
                '_CCDone' => false,
                '_Extensions' => array(),
+               '_Skins' => array(),
                '_MemCachedServers' => '',
                '_UpgradeKeySupplied' => false,
                '_ExistingDBSettings' => false,
@@ -274,27 +286,27 @@ abstract class Installer {
        public $licenses = array(
                'cc-by' => array(
                        'url' => 'http://creativecommons.org/licenses/by/3.0/',
-                       'icon' => '{$wgStylePath}/common/images/cc-by.png',
+                       'icon' => '{$wgScriptPath}/assets/licenses/cc-by.png',
                ),
                'cc-by-sa' => array(
                        'url' => 'http://creativecommons.org/licenses/by-sa/3.0/',
-                       'icon' => '{$wgStylePath}/common/images/cc-by-sa.png',
+                       'icon' => '{$wgScriptPath}/assets/licenses/cc-by-sa.png',
                ),
                'cc-by-nc-sa' => array(
                        'url' => 'http://creativecommons.org/licenses/by-nc-sa/3.0/',
-                       'icon' => '{$wgStylePath}/common/images/cc-by-nc-sa.png',
+                       'icon' => '{$wgScriptPath}/assets/licenses/cc-by-nc-sa.png',
                ),
                'cc-0' => array(
                        'url' => 'https://creativecommons.org/publicdomain/zero/1.0/',
-                       'icon' => '{$wgStylePath}/common/images/cc-0.png',
+                       'icon' => '{$wgScriptPath}/assets/licenses/cc-0.png',
                ),
                'pd' => array(
                        'url' => '',
-                       'icon' => '{$wgStylePath}/common/images/public-domain.png',
+                       'icon' => '{$wgScriptPath}/assets/licenses/public-domain.png',
                ),
                'gfdl' => array(
                        'url' => 'http://www.gnu.org/copyleft/fdl.html',
-                       'icon' => '{$wgStylePath}/common/images/gnu-fdl.png',
+                       'icon' => '{$wgScriptPath}/assets/licenses/gnu-fdl.png',
                ),
                'none' => array(
                        'url' => '',
@@ -380,6 +392,8 @@ abstract class Installer {
                        $this->settings[$var] = $GLOBALS[$var];
                }
 
+               $this->doEnvironmentPreps();
+
                $this->compiledDBs = array();
                foreach ( self::getDBTypes() as $type ) {
                        $installer = $this->getDBInstaller( $type );
@@ -418,25 +432,21 @@ abstract class Installer {
         * @return Status
         */
        public function doEnvironmentChecks() {
-               $phpVersion = phpversion();
-               if ( version_compare( $phpVersion, self::MINIMUM_PHP_VERSION, '>=' ) ) {
-                       $this->showMessage( 'config-env-php', $phpVersion );
-                       $good = true;
+               // Php version has already been checked by entry scripts
+               // Show message here for information purposes
+               if ( wfIsHHVM() ) {
+                       $this->showMessage( 'config-env-hhvm', HHVM_VERSION );
                } else {
-                       $this->showMessage( 'config-env-php-toolow', $phpVersion, self::MINIMUM_PHP_VERSION );
-                       $good = false;
+                       $this->showMessage( 'config-env-php', PHP_VERSION );
                }
 
+               $good = true;
                // Must go here because an old version of PCRE can prevent other checks from completing
-               if ( $good ) {
-                       list( $pcreVersion ) = explode( ' ', PCRE_VERSION, 2 );
-                       if ( version_compare( $pcreVersion, self::MINIMUM_PCRE_VERSION, '<' ) ) {
-                               $this->showError( 'config-pcre-old', self::MINIMUM_PCRE_VERSION, $pcreVersion );
-                               $good = false;
-                       }
-               }
-
-               if ( $good ) {
+               list( $pcreVersion ) = explode( ' ', PCRE_VERSION, 2 );
+               if ( version_compare( $pcreVersion, self::MINIMUM_PCRE_VERSION, '<' ) ) {
+                       $this->showError( 'config-pcre-old', self::MINIMUM_PCRE_VERSION, $pcreVersion );
+                       $good = false;
+               } else {
                        foreach ( $this->envChecks as $check ) {
                                $status = $this->$check();
                                if ( $status === false ) {
@@ -450,6 +460,12 @@ abstract class Installer {
                return $good ? Status::newGood() : Status::newFatal( 'config-env-bad' );
        }
 
+       public function doEnvironmentPreps() {
+               foreach ( $this->envPreps as $prep ) {
+                       $this->$prep();
+               }
+       }
+
        /**
         * Set a MW configuration variable, or internal installer configuration variable.
         *
@@ -517,6 +533,14 @@ abstract class Installer {
        public static function getExistingLocalSettings() {
                global $IP;
 
+               // You might be wondering why this is here. Well if you don't do this
+               // then some poorly-formed extensions try to call their own classes
+               // after immediately registering them. We really need to get extension
+               // registration out of the global scope and into a real format.
+               // @see https://bugzilla.wikimedia.org/67440
+               global $wgAutoloadClasses;
+               $wgAutoloadClasses = array();
+
                wfSuppressWarnings();
                $_lsExists = file_exists( "$IP/LocalSettings.php" );
                wfRestoreWarnings();
@@ -716,6 +740,7 @@ abstract class Installer {
        /**
         * Environment check for register_globals.
         * Prevent installation if enabled
+        * @return bool
         */
        protected function envCheckRegisterGlobals() {
                if ( wfIniGetBool( 'register_globals' ) ) {
@@ -742,31 +767,19 @@ abstract class Installer {
        }
 
        /**
-        * Environment check for magic_quotes_runtime.
+        * Environment check for magic_quotes_(gpc|runtime|sybase).
         * @return bool
         */
        protected function envCheckMagicQuotes() {
-               if ( wfIniGetBool( "magic_quotes_runtime" ) ) {
-                       $this->showError( 'config-magic-quotes-runtime' );
-
-                       return false;
-               }
-
-               return true;
-       }
-
-       /**
-        * Environment check for magic_quotes_sybase.
-        * @return bool
-        */
-       protected function envCheckMagicSybase() {
-               if ( wfIniGetBool( 'magic_quotes_sybase' ) ) {
-                       $this->showError( 'config-magic-quotes-sybase' );
-
-                       return false;
+               $status = true;
+               foreach ( array( 'gpc', 'runtime', 'sybase' ) as $magicJunk ) {
+                       if ( wfIniGetBool( "magic_quotes_$magicJunk" ) ) {
+                               $this->showError( "config-magic-quotes-$magicJunk" );
+                               $status = false;
+                       }
                }
 
-               return true;
+               return $status;
        }
 
        /**
@@ -964,55 +977,29 @@ abstract class Installer {
        }
 
        /**
-        * Environment check for the server hostname.
+        * Environment check to inform user which server we've assumed.
+        *
+        * @return bool
         */
        protected function envCheckServer() {
                $server = $this->envGetDefaultServer();
                if ( $server !== null ) {
                        $this->showMessage( 'config-using-server', $server );
-                       $this->setVar( 'wgServer', $server );
                }
-
                return true;
        }
 
        /**
-        * Helper function to be called from envCheckServer()
-        * @return string
-        */
-       abstract protected function envGetDefaultServer();
-
-       /**
-        * Environment check for setting $IP and $wgScriptPath.
+        * Environment check to inform user which paths we've assumed.
+        *
         * @return bool
         */
        protected function envCheckPath() {
-               global $IP;
-               $IP = dirname( dirname( __DIR__ ) );
-               $this->setVar( 'IP', $IP );
-
                $this->showMessage(
                        'config-using-uri',
                        $this->getVar( 'wgServer' ),
                        $this->getVar( 'wgScriptPath' )
                );
-
-               return true;
-       }
-
-       /**
-        * Environment check for setting the preferred PHP file extension.
-        * @return bool
-        */
-       protected function envCheckExtension() {
-               // @todo FIXME: Detect this properly
-               if ( defined( 'MW_INSTALL_PHP5_EXT' ) ) {
-                       $ext = 'php5';
-               } else {
-                       $ext = 'php';
-               }
-               $this->setVar( 'wgScriptExtension', ".$ext" );
-
                return true;
        }
 
@@ -1214,6 +1201,19 @@ abstract class Installer {
                return true;
        }
 
+       /**
+        * @return bool
+        */
+       protected function envCheckIconv() {
+               if ( !function_exists( 'iconv' ) ) {
+                       $this->showError( 'config-iconv' );
+
+                       return false;
+               }
+
+               return true;
+       }
+
        /**
         * @return bool
         */
@@ -1227,6 +1227,44 @@ abstract class Installer {
                return true;
        }
 
+       /**
+        * Environment prep for the server hostname.
+        */
+       protected function envPrepServer() {
+               $server = $this->envGetDefaultServer();
+               if ( $server !== null ) {
+                       $this->setVar( 'wgServer', $server );
+               }
+       }
+
+       /**
+        * Helper function to be called from envPrepServer()
+        * @return string
+        */
+       abstract protected function envGetDefaultServer();
+
+       /**
+        * Environment prep for setting the preferred PHP file extension.
+        */
+       protected function envPrepExtension() {
+               // @todo FIXME: Detect this properly
+               if ( defined( 'MW_INSTALL_PHP5_EXT' ) ) {
+                       $ext = '.php5';
+               } else {
+                       $ext = '.php';
+               }
+               $this->setVar( 'wgScriptExtension', $ext );
+       }
+
+       /**
+        * Environment prep for setting $IP and $wgScriptPath.
+        */
+       protected function envPrepPath() {
+               global $IP;
+               $IP = dirname( dirname( __DIR__ ) );
+               $this->setVar( 'IP', $IP );
+       }
+
        /**
         * Get an array of likely places we can find executables. Check a bunch
         * of known Unix-like defaults, as well as the PATH environment variable
@@ -1249,8 +1287,8 @@ abstract class Installer {
         *
         * Used only by environment checks.
         *
-        * @param string $path path to search
-        * @param array $names of executable names
+        * @param string $path Path to search
+        * @param array $names Array of executable names
         * @param array|bool $versionInfo False or array with two members:
         *   0 => Command to run for version check, with $1 for the full executable name
         *   1 => String to compare the output with
@@ -1396,17 +1434,20 @@ abstract class Installer {
        }
 
        /**
-        * Finds extensions that follow the format /extensions/Name/Name.php,
+        * Finds extensions that follow the format /$directory/Name/Name.php,
         * and returns an array containing the value for 'Name' for each found extension.
         *
+        * Reasonable values for $directory include 'extensions' (the default) and 'skins'.
+        *
+        * @param string $directory Directory to search in
         * @return array
         */
-       public function findExtensions() {
+       public function findExtensions( $directory = 'extensions' ) {
                if ( $this->getVar( 'IP' ) === null ) {
                        return array();
                }
 
-               $extDir = $this->getVar( 'IP' ) . '/extensions';
+               $extDir = $this->getVar( 'IP' ) . '/' . $directory;
                if ( !is_readable( $extDir ) || !is_dir( $extDir ) ) {
                        return array();
                }
@@ -1483,6 +1524,7 @@ abstract class Installer {
                        array( 'name' => 'interwiki', 'callback' => array( $installer, 'populateInterwikiTable' ) ),
                        array( 'name' => 'stats', 'callback' => array( $this, 'populateSiteStats' ) ),
                        array( 'name' => 'keys', 'callback' => array( $this, 'generateKeys' ) ),
+                       array( 'name' => 'updates', 'callback' => array( $installer, 'insertUpdateKeys' ) ),
                        array( 'name' => 'sysop', 'callback' => array( $this, 'createSysop' ) ),
                        array( 'name' => 'mainpage', 'callback' => array( $this, 'createMainpage' ) ),
                );
index 3c8a5b1..c0ba300 100644 (file)
@@ -49,6 +49,7 @@ class LocalSettingsGenerator {
                $this->installer = $installer;
 
                $this->extensions = $installer->getVar( '_Extensions' );
+               $this->skins = $installer->getVar( '_Skins' );
 
                $db = $installer->getDBInstaller( $installer->getVar( 'wgDBtype' ) );
 
@@ -129,13 +130,26 @@ class LocalSettingsGenerator {
 
        /**
         * Return the full text of the generated LocalSettings.php file,
-        * including the extensions
+        * including the extensions and skins.
         *
         * @return string
         */
        public function getText() {
                $localSettings = $this->getDefaultText();
 
+               if ( count( $this->skins ) ) {
+                       $localSettings .= "
+# Enabled skins.
+# The following skins were automatically enabled:\n";
+
+                       foreach ( $this->skins as $skinName ) {
+                               $encSkinName = self::escapePhpString( $skinName );
+                               $localSettings .= "require_once \"\$IP/skins/$encSkinName/$encSkinName.php\";\n";
+                       }
+
+                       $localSettings .= "\n";
+               }
+
                if ( count( $this->extensions ) ) {
                        $localSettings .= "
 # Enabled Extensions. Most extensions are enabled by including the base extension file here
@@ -146,9 +160,12 @@ class LocalSettingsGenerator {
                                $encExtName = self::escapePhpString( $extName );
                                $localSettings .= "require_once \"\$IP/extensions/$encExtName/$encExtName.php\";\n";
                        }
+
+                       $localSettings .= "\n";
                }
 
-               $localSettings .= "\n\n# End of automatically generated settings.
+               $localSettings .= "
+# End of automatically generated settings.
 # Add more configuration options below.\n\n";
 
                return $localSettings;
@@ -202,7 +219,6 @@ class LocalSettingsGenerator {
                        $locale = '';
                }
 
-               //$rightsUrl = $this->values['wgRightsUrl'] ? '' : '#'; // @todo FIXME: I'm unused!
                $hashedUploads = $this->safeMode ? '' : '#';
                $metaNamespace = '';
                if ( $this->values['wgMetaNamespace'] !== $this->values['wgSitename'] ) {
@@ -221,6 +237,8 @@ class LocalSettingsGenerator {
                                                wfBoolToStr( $perm ) . ";\n";
                                }
                        }
+                       $groupRights .= "\n";
+
                        if ( ( isset( $this->groupPermissions['*']['edit'] ) &&
                                        $this->groupPermissions['*']['edit'] === false )
                                && ( isset( $this->groupPermissions['*']['createaccount'] ) &&
@@ -228,12 +246,12 @@ class LocalSettingsGenerator {
                                && ( isset( $this->groupPermissions['*']['read'] ) &&
                                        $this->groupPermissions['*']['read'] !== false )
                        ) {
-                               $noFollow = "\n# Set \$wgNoFollowLinks to true if you open up your wiki to editing by\n"
+                               $noFollow = "# Set \$wgNoFollowLinks to true if you open up your wiki to editing by\n"
                                        . "# the general public and wish to apply nofollow to external links as a\n"
                                        . "# deterrent to spammers. Nofollow is not a comprehensive anti-spam solution\n"
                                        . "# and open wikis will generally require other anti-spam measures; for more\n"
                                        . "# information, see https://www.mediawiki.org/wiki/Manual:Combating_spam\n"
-                                       . "\$wgNoFollowLinks = false;";
+                                       . "\$wgNoFollowLinks = false;\n\n";
                        }
                }
 
@@ -353,10 +371,6 @@ ${serverSetting}
 # web installer while LocalSettings.php is in place
 \$wgUpgradeKey = \"{$this->values['wgUpgradeKey']}\";
 
-## Default skin: you can change the default skin. Use the internal symbolic
-## names, ie 'vector', 'monobook':
-\$wgDefaultSkin = \"{$this->values['wgDefaultSkin']}\";
-
 ## For attaching licensing metadata to pages, and displaying an
 ## appropriate copyright notice / icon. GNU Free Documentation
 ## License and Creative Commons licenses are supported so far.
@@ -368,6 +382,9 @@ ${serverSetting}
 # Path to the GNU diff3 utility. Used for conflict resolution.
 \$wgDiff3 = \"{$this->values['wgDiff3']}\";
 
-{$groupRights}{$noFollow}";
+{$groupRights}{$noFollow}## Default skin: you can change the default skin. Use the internal symbolic
+## names, ie 'vector', 'monobook':
+\$wgDefaultSkin = \"{$this->values['wgDefaultSkin']}\";
+";
        }
 }
index 83681b6..46bb86c 100644 (file)
@@ -702,7 +702,7 @@ class MssqlInstaller extends DatabaseInstaller {
        /**
         * Try to see if a given fulltext catalog exists
         * We assume we already have the appropriate database selected
-        * @param string $schemaName Catalog name to check
+        * @param string $catalogName Catalog name to check
         * @return bool
         */
        private function catalogExists( $catalogName ) {
index d590a70..ed11f8b 100644 (file)
@@ -52,6 +52,13 @@ class MssqlUpdater extends DatabaseUpdater {
                        array( 'updateConstraints', 'media_type', 'image', 'img_media_type' ),
                        array( 'updateConstraints', 'media_type', 'uploadstash', 'us_media_type' ),
                        // END: Constraint updates
+
+                       array( 'modifyField', 'image', 'img_major_mime',
+                               'patch-img_major_mime-chemical.sql' ),
+                       array( 'modifyField', 'oldimage', 'oi_major_mime',
+                               'patch-oi_major_mime-chemical.sql' ),
+                       array( 'modifyField', 'filearchive', 'fa_major_mime',
+                               'patch-fa_major_mime-chemical.sql' ),
                );
        }
 
@@ -65,6 +72,8 @@ class MssqlUpdater extends DatabaseUpdater {
         * @return bool False if patch is skipped.
         */
        protected function updateConstraints( $constraintType, $table, $field ) {
+               global $wgDBname, $wgDBmwschema;
+
                if ( !$this->doTable( $table ) ) {
                        return true;
                }
index 10f6692..b82e611 100644 (file)
@@ -120,7 +120,7 @@ class MysqlInstaller extends DatabaseInstaller {
                if ( !strlen( $newValues['_InstallUser'] ) ) {
                        $status->fatal( 'config-db-username-empty' );
                }
-               if (!strlen( $newValues['_InstallPassword'] ) ) {
+               if ( !strlen( $newValues['_InstallPassword'] ) ) {
                        $status->fatal( 'config-db-password-empty', $newValues['_InstallUser'] );
                }
                if ( !$status->isOK() ) {
index 853ee0b..990b5b0 100644 (file)
@@ -254,8 +254,18 @@ class MysqlUpdater extends DatabaseUpdater {
                        // 1.24
                        array( 'addField', 'page_props', 'pp_sortkey', 'patch-pp_sortkey.sql' ),
                        array( 'dropField', 'recentchanges', 'rc_cur_time', 'patch-drop-rc_cur_time.sql' ),
-                       array( 'addIndex', 'watchlist', 'wl_user_notificationtimestamp', 'patch-watchlist-user-notificationtimestamp-index.sql' ),
+                       array( 'addIndex', 'watchlist', 'wl_user_notificationtimestamp',
+                               'patch-watchlist-user-notificationtimestamp-index.sql' ),
                        array( 'addField', 'page', 'page_lang', 'patch-page_lang.sql' ),
+                       array( 'addField', 'pagelinks', 'pl_from_namespace', 'patch-pl_from_namespace.sql' ),
+                       array( 'addField', 'templatelinks', 'tl_from_namespace', 'patch-tl_from_namespace.sql' ),
+                       array( 'addField', 'imagelinks', 'il_from_namespace', 'patch-il_from_namespace.sql' ),
+                       array( 'modifyField', 'image', 'img_major_mime',
+                               'patch-img_major_mime-chemical.sql' ),
+                       array( 'modifyField', 'oldimage', 'oi_major_mime',
+                               'patch-oi_major_mime-chemical.sql' ),
+                       array( 'modifyField', 'filearchive', 'fa_major_mime',
+                               'patch-fa_major_mime-chemical.sql' ),
                );
        }
 
index 89a6978..6dcce23 100644 (file)
@@ -84,7 +84,7 @@ class PostgresInstaller extends DatabaseInstaller {
        function submitConnectForm() {
                // Get variables from the request
                $newValues = $this->setVarsFromRequest( array(
-                       'wgDBserver', 'wgDBport','wgDBname', 'wgDBmwschema',
+                       'wgDBserver', 'wgDBport', 'wgDBname', 'wgDBmwschema',
                        '_InstallUser', '_InstallPassword'
                ) );
 
@@ -158,7 +158,7 @@ class PostgresInstaller extends DatabaseInstaller {
        protected function openConnectionWithParams( $user, $password, $dbName, $schema ) {
                $status = Status::newGood();
                try {
-                       $db = Database::factory( 'postgres', array(
+                       $db = DatabaseBase::factory( 'postgres', array(
                                'host' => $this->getVar( 'wgDBserver' ),
                                'user' => $user,
                                'password' => $password,
index 8404c2d..9e8ee94 100644 (file)
@@ -415,6 +415,9 @@ class PostgresUpdater extends DatabaseUpdater {
                        array( 'addPgIndex', 'page_props', 'pp_propname_sortkey_page',
                                        '( pp_propname, pp_sortkey, pp_page ) WHERE ( pp_sortkey IS NOT NULL )' ),
                        array( 'addPgField', 'page', 'page_lang', 'TEXT default NULL' ),
+                       array( 'addPgField', 'pagelinks', 'pl_from_namespace', 'INTEGER NOT NULL DEFAULT 0' ),
+                       array( 'addPgField', 'templatelinks', 'tl_from_namespace', 'INTEGER NOT NULL DEFAULT 0' ),
+                       array( 'addPgField', 'imagelinks', 'il_from_namespace', 'INTEGER NOT NULL DEFAULT 0' ),
                );
        }
 
@@ -694,7 +697,7 @@ END;
                        $this->output( "...column '$table.$field' is already of type '$newtype'\n" );
                } else {
                        $this->output( "Purging data from cache table '$table'\n" );
-                       $this->db->query("DELETE from $table" );
+                       $this->db->query( "DELETE from $table" );
                        $this->output( "Changing column type of '$table.$field' from '{$fi->type()}' to '$newtype'\n" );
                        $sql = "ALTER TABLE $table ALTER $field TYPE $newtype";
                        if ( strlen( $default ) ) {
index cf3f065..ab5ab7d 100644 (file)
@@ -134,6 +134,9 @@ class SqliteUpdater extends DatabaseUpdater {
                        array( 'dropField', 'recentchanges', 'rc_cur_time', 'patch-drop-rc_cur_time.sql' ),
                        array( 'addIndex', 'watchlist', 'wl_user_notificationtimestamp', 'patch-watchlist-user-notificationtimestamp-index.sql' ),
                        array( 'addField', 'page', 'page_lang', 'patch-page-page_lang.sql' ),
+                       array( 'addField', 'pagelinks', 'pl_from_namespace', 'patch-pl_from_namespace.sql' ),
+                       array( 'addField', 'templatelinks', 'tl_from_namespace', 'patch-tl_from_namespace.sql' ),
+                       array( 'addField', 'imagelinks', 'il_from_namespace', 'patch-il_from_namespace.sql' ),
                );
        }
 
index 46348f9..f3dba3a 100644 (file)
@@ -148,7 +148,7 @@ class WebInstaller extends Installer {
        /**
         * Main entry point.
         *
-        * @param array[] $session initial session array
+        * @param array[] $session Initial session array
         *
         * @return array[] New session array
         */
@@ -667,7 +667,7 @@ class WebInstaller extends Installer {
         * Get HTML for an info box with an icon.
         *
         * @param string $text Wikitext, get this with wfMessage()->plain()
-        * @param string|bool $icon Icon name, file in skins/common/images. Default: false
+        * @param string|bool $icon Icon name, file in mw-config/images. Default: false
         * @param string|bool $class Additional class name to add to the wrapper div. Default: false.
         *
         * @return string
@@ -675,11 +675,11 @@ class WebInstaller extends Installer {
        public function getInfoBox( $text, $icon = false, $class = false ) {
                $text = $this->parse( $text, true );
                $icon = ( $icon == false ) ?
-                       '../skins/common/images/info-32.png' :
-                       '../skins/common/images/' . $icon;
+                       'images/info-32.png' :
+                       'images/' . $icon;
                $alt = wfMessage( 'config-information' )->text();
 
-               return Html::infoBox( $text, $icon, $alt, $class, false );
+               return Html::infoBox( $text, $icon, $alt, $class );
        }
 
        /**
@@ -960,6 +960,7 @@ class WebInstaller extends Installer {
         *      var:             The variable to be configured (required)
         *      label:           The message name for the label (required)
         *      itemLabelPrefix: The message name prefix for the item labels (required)
+        *      itemLabels:      List of message names to use for the item labels instead of itemLabelPrefix, keyed by values
         *      values:          List of allowed values (required)
         *      itemAttribs:     Array of attribute arrays, outer key is the value name (optional)
         *      commonAttribs:   Attribute array applied to all items
@@ -970,23 +971,49 @@ class WebInstaller extends Installer {
         * @return string
         */
        public function getRadioSet( $params ) {
-               if ( !isset( $params['controlName'] ) ) {
-                       $params['controlName'] = 'config_' . $params['var'];
-               }
-
-               if ( !isset( $params['value'] ) ) {
-                       $params['value'] = $this->getVar( $params['var'] );
-               }
+               $items = $this->getRadioElements( $params );
 
                if ( !isset( $params['label'] ) ) {
                        $label = '';
                } else {
                        $label = $params['label'];
                }
+
+               if ( !isset( $params['controlName'] ) ) {
+                       $params['controlName'] = 'config_' . $params['var'];
+               }
+
                if ( !isset( $params['help'] ) ) {
                        $params['help'] = "";
                }
+
                $s = "<ul>\n";
+               foreach ( $items as $value => $item ) {
+                       $s .= "<li>$item</li>\n";
+               }
+               $s .= "</ul>\n";
+
+               return $this->label( $label, $params['controlName'], $s, $params['help'] );
+       }
+
+       /**
+        * Get a set of labelled radio buttons. You probably want to use getRadioSet(), not this.
+        *
+        * @see getRadioSet
+        *
+        * @return array
+        */
+       public function getRadioElements( $params ) {
+               if ( !isset( $params['controlName'] ) ) {
+                       $params['controlName'] = 'config_' . $params['var'];
+               }
+
+               if ( !isset( $params['value'] ) ) {
+                       $params['value'] = $this->getVar( $params['var'] );
+               }
+
+               $items = array();
+
                foreach ( $params['values'] as $value ) {
                        $itemAttribs = array();
 
@@ -1003,19 +1030,17 @@ class WebInstaller extends Installer {
                        $itemAttribs['id'] = $id;
                        $itemAttribs['tabindex'] = $this->nextTabIndex();
 
-                       $s .=
-                               '<li>' .
+                       $items[$value] =
                                Xml::radio( $params['controlName'], $value, $checked, $itemAttribs ) .
                                '&#160;' .
                                Xml::tags( 'label', array( 'for' => $id ), $this->parse(
-                                       wfMessage( $params['itemLabelPrefix'] . strtolower( $value ) )->plain()
-                               ) ) .
-                               "</li>\n";
+                                       isset( $params['itemLabels'] ) ?
+                                               wfMessage( $params['itemLabels'][$value] )->plain() :
+                                               wfMessage( $params['itemLabelPrefix'] . strtolower( $value ) )->plain()
+                               ) );
                }
 
-               $s .= "</ul>\n";
-
-               return $this->label( $label, $params['controlName'], $s, $params['help'] );
+               return $items;
        }
 
        /**
@@ -1051,7 +1076,11 @@ class WebInstaller extends Installer {
                $newValues = array();
 
                foreach ( $varNames as $name ) {
-                       $value = trim( $this->request->getVal( $prefix . $name ) );
+                       $value = $this->request->getVal( $prefix . $name );
+                       // bug 30524, do not trim passwords
+                       if ( stripos( $name, 'password' ) === false ) {
+                               $value = trim( $value );
+                       }
                        $newValues[$name] = $value;
 
                        if ( $value === null ) {
@@ -1135,8 +1164,18 @@ class WebInstaller extends Installer {
                        $path = $_SERVER['SCRIPT_NAME'];
                }
                if ( $path !== false ) {
-                       $uri = preg_replace( '{^(.*)/(mw-)?config.*$}', '$1', $path );
-                       $this->setVar( 'wgScriptPath', $uri );
+                       $scriptPath = preg_replace( '{^(.*)/(mw-)?config.*$}', '$1', $path );
+                       $scriptExtension = $this->getVar( 'wgScriptExtension' );
+
+                       $this->setVar( 'wgScriptPath', "$scriptPath" );
+                       // Update variables set from Setup.php that are derived from wgScriptPath
+                       $this->setVar( 'wgScript', "$scriptPath/index$scriptExtension" );
+                       $this->setVar( 'wgLoadScript', "$scriptPath/load$scriptExtension" );
+                       $this->setVar( 'wgStylePath', "$scriptPath/skins" );
+                       $this->setVar( 'wgLocalStylePath', "$scriptPath/skins" );
+                       $this->setVar( 'wgExtensionAssetsPath', "$scriptPath/extensions" );
+                       $this->setVar( 'wgUploadPath', "$scriptPath/images" );
+
                } else {
                        $this->showError( 'config-no-uri' );
 
index 97f4830..3094d55 100644 (file)
@@ -124,49 +124,55 @@ class WebInstallerOutput {
         * @return string
         */
        public function getCSS() {
-               // Horrible, horrible hack: the installer is currently hardcoded to use the Vector skin, so load
-               // it here. Include instead of require, as this will work without it, it will just look bad.
-               global $wgResourceModules;
                global $wgStyleDirectory;
-               include_once "$wgStyleDirectory/Vector/Vector.php";
 
                $moduleNames = array(
                        // See SkinTemplate::setupSkinUserCss
                        'mediawiki.legacy.shared',
                        // See Vector::setupSkinUserCss
                        'mediawiki.skinning.interface',
-                       'skins.vector.styles',
-
-                       'mediawiki.legacy.config',
                );
 
-               $css = '';
+               if ( file_exists( "$wgStyleDirectory/Vector/Vector.php" ) ) {
+                       // Force loading Vector skin if available as a fallback skin
+                       // for whatever ResourceLoader wants to have as the default.
+
+                       // Include instead of require, as this will work without it, it will just look bad.
+                       // We need the 'global' statement for $wgResourceModules because the Vector skin adds the
+                       // definitions for its RL modules there that we use implicitly below.
+
+                       // @codingStandardsIgnoreStart
+                       global $wgResourceModules; // This is NOT UNUSED!
+                       // @codingStandardsIgnoreEnd
+
+                       include_once "$wgStyleDirectory/Vector/Vector.php";
+
+                       $moduleNames[] = 'skins.vector.styles';
+               }
+
+               $moduleNames[] = 'mediawiki.legacy.config';
 
                $resourceLoader = new ResourceLoader();
                $rlContext = new ResourceLoaderContext( $resourceLoader, new FauxRequest( array(
                                'debug' => 'true',
                                'lang' => $this->getLanguageCode(),
                                'only' => 'styles',
-                               'skin' => 'vector',
                ) ) );
+
+               $styles = array();
                foreach ( $moduleNames as $moduleName ) {
                        /** @var ResourceLoaderFileModule $module */
                        $module = $resourceLoader->getModule( $moduleName );
-                       // One of the modules will be missing if Vector is unavailable
-                       if ( !$module ) {
-                               continue;
-                       }
 
                        // Based on: ResourceLoaderFileModule::getStyles (without the DB query)
-                       $styles = ResourceLoader::makeCombinedStyles( $module->readStyleFiles(
-                               $module->getStyleFiles( $rlContext ),
-                               $module->getFlip( $rlContext )
-                       ) );
-
-                       $css .= implode( "\n", $styles );
+                       $styles = array_merge( $styles, ResourceLoader::makeCombinedStyles(
+                               $module->readStyleFiles(
+                                       $module->getStyleFiles( $rlContext ),
+                                       $module->getFlip( $rlContext )
+                       ) ) );
                }
 
-               return $css;
+               return implode( "\n", $styles );
        }
 
        /**
@@ -261,14 +267,14 @@ class WebInstallerOutput {
        <title><?php $this->outputTitle(); ?></title>
        <?php echo $this->getCssUrl() . "\n"; ?>
        <?php echo $this->getJQuery() . "\n"; ?>
-       <?php echo Html::linkedScript( '../skins/common/config.js' ) . "\n"; ?>
+       <?php echo Html::linkedScript( 'config.js' ) . "\n"; ?>
 </head>
 
 <?php echo Html::openElement( 'body', array( 'class' => $this->getDir() ) ) . "\n"; ?>
 <div id="mw-page-base"></div>
 <div id="mw-head-base"></div>
-<div id="content">
-<div id="bodyContent">
+<div id="content" class="mw-body">
+<div id="bodyContent" class="mw-body-content">
 
 <h1><?php $this->outputTitle(); ?></h1>
 <?php
@@ -286,7 +292,7 @@ class WebInstallerOutput {
 
 <div id="mw-panel">
        <div class="portal" id="p-logo">
-         <a style="background-image: url(../skins/common/images/mediawiki.png);"
+         <a style="background-image: url(images/installer-logo.png);"
                href="https://www.mediawiki.org/"
                title="Main Page"></a>
        </div>
@@ -310,7 +316,7 @@ class WebInstallerOutput {
        <title><?php $this->outputTitle(); ?></title>
        <?php echo $this->getCssUrl() . "\n"; ?>
        <?php echo $this->getJQuery(); ?>
-       <?php echo Html::linkedScript( '../skins/common/config.js' ); ?>
+       <?php echo Html::linkedScript( 'config.js' ); ?>
 </head>
 
 <body style="background-image: none">
index 677af4f..2a9c54c 100644 (file)
@@ -145,11 +145,12 @@ abstract class WebInstallerPage {
 
        /**
         * @param string $var
+        * @param mixed $default
         *
         * @return mixed
         */
-       public function getVar( $var ) {
-               return $this->parent->getVar( $var );
+       public function getVar( $var, $default = null ) {
+               return $this->parent->getVar( $var, $default );
        }
 
        /**
@@ -163,7 +164,7 @@ abstract class WebInstallerPage {
        /**
         * Get the starting tags of a fieldset.
         *
-        * @param string $legend message name
+        * @param string $legend Message name
         *
         * @return string
         */
@@ -186,7 +187,7 @@ abstract class WebInstallerPage {
        protected function startLiveBox() {
                $this->addHTML(
                        '<div id="config-spinner" style="display:none;">' .
-                       '<img src="../skins/common/images/ajax-loader.gif" /></div>' .
+                       '<img src="images/ajax-loader.gif" /></div>' .
                        '<script>jQuery( "#config-spinner" ).show();</script>' .
                        '<div id="config-live-log">' .
                        '<textarea name="LiveLog" rows="10" cols="30" readonly="readonly">'
@@ -948,6 +949,7 @@ class WebInstallerOptions extends WebInstallerPage {
         */
        public function execute() {
                if ( $this->getVar( '_SkipOptional' ) == 'skip' ) {
+                       $this->submitSkins();
                        return 'skip';
                }
                if ( $this->parent->request->wasPosted() ) {
@@ -1025,6 +1027,38 @@ class WebInstallerOptions extends WebInstallerPage {
                        $this->getFieldSetEnd()
                );
 
+               $skins = $this->parent->findExtensions( 'skins' );
+               $skinHtml = $this->getFieldSetStart( 'config-skins' );
+
+               if ( $skins ) {
+                       $skinNames = array_map( 'strtolower', $skins );
+
+                       $radioButtons = $this->parent->getRadioElements( array(
+                               'var' => 'wgDefaultSkin',
+                               'itemLabels' => array_fill_keys( $skinNames, 'config-skins-use-as-default' ),
+                               'values' => $skinNames,
+                               'value' => $this->getVar( 'wgDefaultSkin', $this->getDefaultSkin( $skinNames ) ),
+                       ) );
+
+                       foreach ( $skins as $skin ) {
+                               $skinHtml .=
+                                       '<div class="config-skins-item">' .
+                                       $this->parent->getCheckBox( array(
+                                               'var' => "skin-$skin",
+                                               'rawtext' => $skin,
+                                               'value' => $this->getVar( "skin-$skin", true ), // all found skins enabled by default
+                                       ) ) .
+                                       '<div class="config-skins-use-as-default">' . $radioButtons[strtolower( $skin )] . '</div>' .
+                                       '</div>';
+                       }
+               } else {
+                       $skinHtml .= $this->parent->getWarningBox( wfMessage( 'config-skins-missing' )->plain() );
+               }
+
+               $skinHtml .= $this->parent->getHelpBox( 'config-skins-help' ) .
+                       $this->getFieldSetEnd();
+               $this->addHTML( $skinHtml );
+
                $extensions = $this->parent->findExtensions();
 
                if ( $extensions ) {
@@ -1142,7 +1176,7 @@ class WebInstallerOptions extends WebInstallerPage {
                        'config_wgRightsIcon' => '[license_button]',
                ) );
                $styleUrl = $server . dirname( dirname( $this->parent->getUrl() ) ) .
-                       '/skins/common/config-cc.css';
+                       '/mw-config/config-cc.css';
                $iframeUrl = 'http://creativecommons.org/license/?' .
                        wfArrayToCgi( array(
                                'partner' => 'MediaWiki',
@@ -1220,6 +1254,40 @@ class WebInstallerOptions extends WebInstallerPage {
                $this->addHTML( $this->getCCDoneBox() );
        }
 
+       /**
+        * Returns a default value to be used for $wgDefaultSkin: the preferred skin, if available among
+        * the installed skins, or any other one otherwise.
+        *
+        * @param string[] $skinNames Names of installed skins.
+        * @return string
+        */
+       public function getDefaultSkin( array $skinNames ) {
+               $defaultSkin = $GLOBALS['wgDefaultSkin'];
+               if ( in_array( $defaultSkin, $skinNames ) ) {
+                       return $defaultSkin;
+               } else {
+                       return $skinNames[0];
+               }
+       }
+
+       /**
+        * If the user skips this installer page, we still need to set up the default skins, but ignore
+        * everything else.
+        *
+        * @return bool
+        */
+       public function submitSkins() {
+               $skins = $this->parent->findExtensions( 'skins' );
+               $this->parent->setVar( '_Skins', $skins );
+
+               if ( $skins ) {
+                       $skinNames = array_map( 'strtolower', $skins );
+                       $this->parent->setVar( 'wgDefaultSkin', $this->getDefaultSkin( $skinNames ) );
+               }
+
+               return true;
+       }
+
        /**
         * @return bool
         */
@@ -1228,7 +1296,7 @@ class WebInstallerOptions extends WebInstallerPage {
                        'wgEnableEmail', 'wgPasswordSender', 'wgEnableUploads', 'wgLogo',
                        'wgEnableUserEmail', 'wgEnotifUserTalk', 'wgEnotifWatchlist',
                        'wgEmailAuthentication', 'wgMainCacheType', '_MemCachedServers',
-                       'wgUseInstantCommons' ) );
+                       'wgUseInstantCommons', 'wgDefaultSkin' ) );
 
                $retVal = true;
 
@@ -1263,6 +1331,27 @@ class WebInstallerOptions extends WebInstallerPage {
                        $this->setVar( 'wgRightsIcon', '' );
                }
 
+               $skinsAvailable = $this->parent->findExtensions( 'skins' );
+               $skinsToInstall = array();
+               foreach ( $skinsAvailable as $skin ) {
+                       $this->parent->setVarsFromRequest( array( "skin-$skin" ) );
+                       if ( $this->getVar( "skin-$skin" ) ) {
+                               $skinsToInstall[] = $skin;
+                       }
+               }
+               $this->parent->setVar( '_Skins', $skinsToInstall );
+
+               if ( !$skinsToInstall && $skinsAvailable ) {
+                       $this->parent->showError( 'config-skins-must-enable-some' );
+                       $retVal = false;
+               }
+               $defaultSkin = $this->getVar( 'wgDefaultSkin' );
+               $skinsToInstallLowercase = array_map( 'strtolower', $skinsToInstall );
+               if ( $skinsToInstall && array_search( $defaultSkin, $skinsToInstallLowercase ) === false ) {
+                       $this->parent->showError( 'config-skins-must-enable-default' );
+                       $retVal = false;
+               }
+
                $extsAvailable = $this->parent->findExtensions();
                $extsToInstall = array();
                foreach ( $extsAvailable as $ext ) {
index 1c0af17..7edb97c 100644 (file)
        "config-help-restart": "هل تريد إزالة البيانات المحفوظة التي قد قمت بإدخالها وإعادة تشغيل عملية التثبيت؟",
        "config-restart": "نعم، إعادة التشغيل",
        "config-env-php": "بي إتش بي $1 مثبت.",
-       "config-env-php-toolow": "بي إتش بي $1 مثبت.\nومع ذلك، يتطلب ميدياويكي بي إتش بي $2 أو أعلى.",
        "config-db-type": "نوع قاعدة البيانات:",
        "config-db-wiki-settings": "حدِّد هذا الويكي",
+       "config-db-name": "اسم قاعدة البيانات",
        "config-db-username": "اسم مستخدم قاعدة البيانات:",
        "config-db-password": "كلمة سر قاعدة البيانات:",
        "config-db-port": "منفذ قاعدة البيانات:",
+       "config-db-schema": "سكيما لميدياويكي",
        "config-type-mysql": "ماي إس كيو إل",
        "config-type-postgres": "بوستجر إس كيو إل",
        "config-type-sqlite": "إس كيو لايت",
        "config-type-oracle": "أوراكل",
+       "config-header-mysql": "إعدادات MySQL",
+       "config-header-postgres": "إعدادات PostgreSQL",
+       "config-header-sqlite": "إعدادات SQLite",
+       "config-header-oracle": "إعدادات أوراكل",
+       "config-invalid-db-type": "نوع قاعدة بيانات غير صحيح",
+       "config-mysql-engine": "محرك التخزين",
+       "config-mysql-innodb": "إنو دي بي",
+       "config-mysql-myisam": "ماي إسام",
+       "config-mysql-binary": "ثنائي",
+       "config-mysql-utf8": "يو تي إف-8",
        "config-site-name": "اسم الويكي:",
+       "config-site-name-blank": "أدخل اسم موقع.",
+       "config-project-namespace": "نطاق المشروع:",
+       "config-ns-generic": "المشروع",
+       "config-ns-site-name": "مثل اسم الويكي: $1",
+       "config-ns-other": "أخرى (حدد)",
+       "config-ns-other-default": "ماي ويكي",
+       "config-admin-box": "حساب إداري",
        "config-admin-name": "اسم المستخدم:",
        "config-admin-password": "كلمة السر:",
        "config-admin-password-confirm": "كلمة المرور مرة أخرى:",
+       "config-admin-name-blank": "أدخل اسم مستخدم لإداري.",
        "config-admin-email": "عنوان البريد الإلكتروني:",
        "config-optional-continue": "اسألني المزيد من الأسئلة",
        "config-optional-skip": "إنني أشعر بالملل بالفعل، فقط قم بتثبيت الويكي",
+       "config-profile": "ملف صلاحيات المستخدم:",
        "config-profile-wiki": "افتح ويكي",
+       "config-profile-no-anon": "إنشاء الحساب مطلوب",
        "config-profile-private": "ويكي خاص",
+       "config-license": "حقوق النسخ والترخيص:",
+       "config-license-none": "لا تذييل ترخيص",
+       "config-license-cc-by-sa": "المشاع الإبداعي النسبة للمؤلف المشاركة بالمثل",
+       "config-license-cc-by": "المشاع الإبداعي النسبة للمؤلف",
+       "config-license-cc-by-nc-sa": "المشاع الإبداعي النسبة للمؤلف غير تجاري المشاركة بالمثل",
        "config-license-pd": "ملكية عامة",
        "config-email-settings": "إعدادات البريد الإلكتروني",
+       "config-email-usertalk": "فعل إخطارات صفحات نقاش المستخدمين",
        "config-email-watchlist": "تمكين إشعارات قائمة المراقبة",
+       "config-email-sender": "يرجع عنوان البريد الإلكتروني:",
+       "config-upload-settings": "الصور وتحميل الملفات",
        "config-upload-enable": "تمكين تحميل الملفات",
+       "config-logo": "مسار الشعار:",
        "config-cc-again": "اختر مجددًا",
+       "config-advanced-settings": "ضبط متقدم",
        "config-extensions": "امتدادات",
+       "config-skins": "الواجهات",
+       "config-skins-use-as-default": "استخدم هذه الواجهة كافتراضية",
        "config-install-step-done": "نفذ",
        "config-install-step-failed": "فشل",
+       "config-install-extensions": "متضمنا الامتدادات",
+       "config-install-database": "إنشاء قاعدة البيانات",
+       "config-install-schema": "إنشاء السكيما",
+       "config-install-user": "إنشاء مستخدم قاعدة البيانات",
+       "config-install-user-alreadyexists": "المستخدم \"$1\" موجود بالفعل",
+       "config-install-user-create-failed": "إنشاء مستخدم \"$1\" فشل:$2",
+       "config-install-tables": "إنشاء الجداول",
+       "config-install-keys": "توليد المفاتيح السرية",
        "config-help": "مساعدة",
        "mainpagetext": "'''تم تثبيت ميدياويكي بنجاح.'''",
        "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 القائمة البريدية الخاصة بإصدار ميدياويكي]"
diff --git a/includes/installer/i18n/av.json b/includes/installer/i18n/av.json
new file mode 100644 (file)
index 0000000..0ce76fa
--- /dev/null
@@ -0,0 +1,8 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Gazimagomedov"
+               ]
+       },
+       "config-page-options": "Рекъезаби"
+}
index 376a227..0aeae7f 100644 (file)
@@ -51,7 +51,7 @@
        "config-env-good": "Асяродзьдзе было праверанае.\nВы можаце ўсталёўваць MediaWiki.",
        "config-env-bad": "Асяродзьдзе было праверанае.\nУсталяваньне MediaWiki немагчымае.",
        "config-env-php": "Усталяваны PHP $1.",
-       "config-env-php-toolow": "Усталяваны PHP $1.\nАле MediaWiki патрабуе PHP вэрсіі $2 ці навейшай.",
+       "config-env-hhvm": "HHVM $1 усталяваная.",
        "config-unicode-using-utf8": "Выкарыстоўваецца бібліятэка Unicode-нармалізацыі Браяна Вібэра",
        "config-unicode-using-intl": "Выкарыстоўваецца [http://pecl.php.net/intl intl пашырэньне з PECL] для Unicode-нармалізацыі",
        "config-unicode-pure-php-warning": "'''Папярэджаньне''': [http://pecl.php.net/intl Пашырэньне intl з PECL] — ня слушнае для Unicode-нармалізацыі, цяпер выкарыстоўваецца марудная PHP-рэалізацыя.\nКалі ў Вас сайт з высокай наведваемасьцю, раім пачытаць пра [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode-нармалізацыю].",
@@ -59,7 +59,8 @@
        "config-no-db": "Немагчыма знайсьці адпаведны драйвэр базы зьвестак. Вам неабходна ўсталяваць драйвэр базы зьвестак для PHP.\nПадтрымліваюцца наступныя тыпы базаў зьвестак: $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": "'''Папярэджаньне: уключаная опцыя PHP <code>[http://php.net/register_globals register_globals]</code>.'''\n'''Адключыце яе, калі можаце.'''\nMediaWiki будзе працаваць, але гэта панізіць узровень бясьпекі сэрвэра.",
+       "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": "'''Фатальная памылка: уключаная опцыя PHP [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime]!'''\nГэтая опцыя псуе ўводны паток зьвестак непрадказальным чынам.\nПрацяг усталяваньня альбо выкарыстаньне MediaWiki без адключэньня гэтай опцыі немагчымыя.",
        "config-magic-quotes-sybase": "'''Фатальная памылка: рэжым [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] уключаны!'''\nГэты рэжым шкодзіць уваходныя зьвесткі непрадказальным чынам.\nПрацяг усталяваньня альбо выкарыстаньне MediaWiki немагчымыя, пакуль рэжым ня будзе выключаны.",
        "config-mbstring": "'''Фатальная памылка: рэжым [http://www.php.net/manual/en/ref.info.php#mbstring.overload mbstring.func_overload] уключаны!'''\nГэты рэжым выклікае памылкі і можа шкодзіць зьвесткі непрадказальным чынам.\nПрацяг усталяваньня альбо выкарыстаньне MediaWiki немагчымыя, пакуль рэжым ня будзе выключаны.",
@@ -70,6 +71,7 @@
        "config-memory-raised": "Абмежаваньне на даступную для PHP памяць <code>memory_limit</code> было падвышанае з $1 да $2.",
        "config-memory-bad": "'''Папярэджаньне:''' памер PHP <code>memory_limit</code> складае $1.\nВерагодна, гэта вельмі мала.\nУсталяваньне можа быць няўдалым!",
        "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-xcache": "[http://xcache.lighttpd.net/ XCache] усталяваны",
        "config-apc": "[http://www.php.net/apc APC] усталяваны",
        "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 вольнай ліцэнзіі].\nГэта дазваляе ствараць эфэкт супольнай уласнасьці і садзейнічае доўгатэрміноваму ўнёску.\nДля прыватных і карпаратыўных вікі гэта не зьяўляецца неабходнасьцю.\n\nКалі Вы жадаеце выкарыстоўваць тэкст зь Вікіпэдыі, і жадаеце, каб Вікіпэдыя магла прымаць тэксты, скапіяваныя з Вашай вікі, Вам неабходна выбраць ліцэнзію '''Creative Commons Attribution Share Alike'''.\n\nРаней Вікіпэдыя выкарыстоўвала ліцэнзію GNU Free Documentation.\nЯна ўсё яшчэ дзейнічае, але яна ўтрымлівае некаторыя моманты,\nякія ўскладняюць паўторнае выкарыстоўваньне і інтэрпрэтацыю матэрыялаў.",
+       "config-license-help": "Шматлікія адкрытыя вікі публікуюць увесь унёсак у праект на ўмовах [http://freedomdefined.org/Definition вольнай ліцэнзіі].\nГэта дазваляе ствараць эфэкт супольнай уласнасьці і садзейнічае доўгатэрміноваму ўнёску.\nДля прыватных і карпаратыўных вікі гэта не зьяўляецца неабходнасьцю.\n\nКалі Вы жадаеце выкарыстоўваць тэкст зь Вікіпэдыі, і жадаеце, каб Вікіпэдыя магла прымаць тэксты, скапіяваныя з Вашай вікі, Вам неабходна выбраць ліцэнзію <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nРаней Вікіпэдыя выкарыстоўвала ліцэнзію GNU Free Documentation.\nЯна ўсё яшчэ дзейнічае, але яна ўтрымлівае некаторыя моманты, якія ўскладняюць паўторнае выкарыстаньне і інтэрпрэтацыю матэрыялаў.",
        "config-email-settings": "Налады электроннай пошты",
        "config-enable-email": "Дазволіць выходзячыя электронныя лісты",
        "config-enable-email-help": "Калі Вы жадаеце, каб працавала электронная пошта, неабходна сканфігураваць PHP [http://www.php.net/manual/en/mail.configuration.php адпаведным чынам].\nКалі Вы не жадаеце выкарыстоўваць магчымасьці электроннай пошты, Вы можаце яе адключыць.",
        "config-memcache-badport": "Нумар порту Memcached павінен быць паміж $1 і $2",
        "config-extensions": "Пашырэньні",
        "config-extensions-help": "Пашырэньні пададзеныя вышэй, былі знойдзеныя ў Вашай дырэкторыі <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": "Тэма афармленьня, абраная па змоўчаньні, мусіць быць уключаная.",
        "config-install-alreadydone": "'''Папярэджаньне:''' здаецца, што Вы ўжо ўсталёўвалі MediaWiki і спрабуеце зрабіць гэтай зноў.\nКалі ласка, перайдзіце на наступную старонку.",
        "config-install-begin": "Пасьля націску кнопкі «{{int:config-continue}}» пачнецца ўсталяваньне MediaWiki.\nКалі Вы жадаеце што-небудзь зьмяніць, націсьніце кнопку «{{int:config-back}}».",
        "config-install-step-done": "зроблена",
        "config-install-stats": "Ініцыялізацыі статыстыкі",
        "config-install-keys": "Стварэньне сакрэтных ключоў",
        "config-insecure-keys": "<strong>Папярэджаньне:</strong> {{PLURAL:$2|1=Ключ бясьпекі $1 створаны|Ключы бясьпекі $1 створаныя}} падчас усталяваньня, {{PLURAL:$2|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> недаступны.",
index b59a628..32e4c39 100644 (file)
@@ -2,7 +2,8 @@
        "@metadata": {
                "authors": [
                        "DCLXVI",
-                       "아라"
+                       "아라",
+                       "StanProg"
                ]
        },
        "config-desc": "Инсталатор на МедияУики",
@@ -47,7 +48,6 @@
        "config-env-good": "Средата беше проверена.\nИнсталирането на МедияУики е възможно.",
        "config-env-bad": "Средата беше проверена.\nНе е възможна инсталация на МедияУики.",
        "config-env-php": "Инсталирана е версия на PHP $1.",
-       "config-env-php-toolow": "Инсталирана е версия на PHP $1.\nМедияУики изисква версия PHP $2 или по-нова.",
        "config-unicode-using-utf8": "Използване на utf8_normalize.so от Brion Vibber за нормализация на Уникод.",
        "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 нормализацията на Уникод].",
@@ -55,7 +55,6 @@
        "config-no-db": "Не може да бъде открит подходящ драйвер за база от данни! Необходимо е да се инсталира драйвер за база от данни за PHP.\nПоддържат се следните типове базни от данни: $1.\n\nАко използвате споделен хостинг, помолете доставчика на услугата да инсталира подходящ драйвер за база от данни.\nАко сами сте компилирали PHP, преконфигурирайте го с включен клиент за база от данни, например чрез използване на <code>./configure --with-mysql</code>.\nАко сте инсталирали PHP от пакет за Debian или Убунту, необходимо е, също така, да инсталирате и модула php5-mysql.",
        "config-outdated-sqlite": "<strong>Предупреждение:</strong> имате инсталиран SQLite  $1, а минималната допустима версия е $2. SQLite ще бъде недостъпна за ползване.",
        "config-no-fts3": "'''Предупреждение''': SQLite е компилирана без [//sqlite.org/fts3.html модула FTS3], затова възможностите за търсене няма да са достъпни.",
-       "config-register-globals": "'''Предупреждение: Настройката на PHP <code>[http://php.net/register_globals register_globals]</code> е включена.'''\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-memcache-badport": "Портовете за Memcached трябва да бъдат между $1 и $2.",
        "config-extensions": "Разширения",
        "config-extensions-help": "Разширенията от списъка по-горе бяха открити в директорията <code>./extensions</code>.\n\nВъзможно е те да изискват допълнително конфигуриране, но сега могат да бъдат включени.",
+       "config-skins": "Облици",
        "config-install-alreadydone": "'''Предупреждение:''' Изглежда вече сте инсталирали МедияУики и се опитвате да го инсталирате отново.\nПродължете към следващата страница.",
        "config-install-begin": "Инсталацията на МедияУики ще започне след натискане на бутона „{{int:config-continue}}“.\nВ случай, че е необходимо да се направят промени, използва се бутона „{{int:config-back}}“.",
        "config-install-step-done": "готово",
index 1192e2c..212c599 100644 (file)
        "config-help-restart": "আপনি কী সকল সংরক্ষিত উপাত্ত পরিষ্কার করতে যা আপনি প্রবেস করিয়েছিলেন এবং ইন্সটালেসন ব্যবস্থা পুনরায় আরম্ভ করতে চান?",
        "config-restart": "হ্যাঁ, পুনরায় চালু করুন",
        "config-env-php": "পিএইচপি $1 ইন্সটল করা হয়েছে।",
+       "config-env-hhvm": "HHVM $1 ইনস্টল করা হয়েছে।",
+       "config-xcache": "[http://xcache.lighttpd.net/ XCache] ইনস্টল করা হয়েছে",
        "config-apc": "[http://www.php.net/apc এপিসি] ইনস্টল হয়েছে",
+       "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] ইনস্টল করা হয়েছে",
        "config-db-type": "ডেটাবেজের ধরন:",
        "config-db-host": "ডেটাবেজের হোস্ট:",
        "config-db-wiki-settings": "এই উইকি সনাক্ত করুন",
@@ -44,6 +47,9 @@
        "config-db-install-account": "ইন্সটলের জন্য ব্যবহারকারী অ্যাকাউন্ট",
        "config-db-username": "ডেটাবেজের ব্যবহারকারী নাম:",
        "config-db-password": "ডেটাবেজের শব্দচাবি:",
+       "config-db-username-empty": "আপনাকে অবশ্যই \"{{int:config-db-username}}\"-এর জন্য একটি মান প্রবেশ করাতে হবে।",
+       "config-db-wiki-account": "সাধারণ অভিযানের জন্য ব্যবহারকারী একাউন্ট",
+       "config-db-prefix": "উপাত্তশালা ছক প্রিফিক্স:",
        "config-db-charset": "ডেটাবেজের অক্ষর সেট",
        "config-db-port": "ডেটাবেজ পোর্ট:",
        "config-db-schema": "মিডিয়াউইকির স্কিমা",
        "config-sqlite-dir": "এসকিউলাইট ডেটা ডিরেক্টরি:",
        "config-oracle-def-ts": "পূর্বনির্ধারিত টেবিলস্পেস",
        "config-oracle-temp-ts": "সাময়কি টেবিলস্পেস:",
+       "config-type-mssql": "মাইক্রোসফট এসকিউএল সার্ভার",
        "config-header-mysql": "মাইএসকিউএল সেটিংস",
        "config-header-postgres": "পোস্টগ্রেএসকিউএল সেটিংস",
        "config-header-sqlite": "এসকিউলাইট সেটিংস",
        "config-header-oracle": "ওরাকল সেটিংস",
        "config-invalid-db-type": "ডেটাবেজের ধরন অগ্রহযোগ্য",
-       "config-missing-db-name": "আপনাকে অবশ্যই \"ডেটাবেজ নাম\"-এর জন্য একটি মান প্রবেশ করাতে হবে",
-       "config-missing-db-host": "আপনাকে অবশ্যই \"ডেটাবেজ হোস্ট\"-এর জন্য একটি মান প্রবেশ করাতে হবে",
-       "config-missing-db-server-oracle": "আপনাকে অবশ্যই \"ডেটাবেজ টিএনএস\"-এর জন্য একটি মান প্রবেশ করাতে হবে",
+       "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-connection-error": "$1।\n\n\nদয়া করে প্রস্তাবকারী, ব্যবহারকারী নাম ও শব্দচাবি দেখুন এবং পুনরায় চেষ্টা করুন।",
        "config-mysql-engine": "সংরক্ষণ ইঞ্জিন:",
        "config-mysql-innodb": "ইনোডিবি",
@@ -92,6 +99,7 @@
        "config-license": "কপিরাইট ও লাইসেন্স:",
        "config-license-none": "কোনো লাইসেন্স ফুটার নেই",
        "config-license-cc-by-sa": "ক্রিয়েটিভ কমন্স অ্যাট্রিবিউশন শেয়ার অ্যালাইক",
+       "config-license-cc-by": "ক্রিয়েটিভ কমন্স অ্যাট্রিবিউশন",
        "config-license-cc-by-nc-sa": "ক্রিয়েটিভ কমন্স অ্যাট্রিবিউশন নন-কমার্শিয়াল শেয়ার অ্যালাইক",
        "config-license-cc-0": "ক্রিয়েটিভ কমন্স জিরো (পাবলিক ডোমেইন)",
        "config-license-pd": "পাবলিক ডোমেইন",
index f4b75db..78381be 100644 (file)
        "config-env-good": "Gwiriet eo bet an endro.\nGallout a rit staliañ MediaWiki.",
        "config-env-bad": "Gwiriet eo bet an endro.\nNe c'hallit ket staliañ MediaWiki.",
        "config-env-php": "Staliet eo PHP $1.",
-       "config-env-php-toolow": "Staliet eo PHP $1.\nNemet eo rekis PHP $2 pe nevesoc'h evit MediaWiki.",
+       "config-env-hhvm": "HHVM $1 zo staliet.",
        "config-unicode-using-utf8": "Oc'h implijout utf8_normalize.so gant Brion Vibber evit ar reolata Unicode.",
        "config-unicode-using-intl": "Oc'h implijout [http://pecl.php.net/intl an astenn PECL intl] evit ar reolata Unicode.",
        "config-unicode-pure-php-warning": "'''Diwallit''' : N'haller ket kaout an [http://pecl.php.net/intl intl PECL astenn] evit merañ reoladur Unicode, a zistro d'ar stumm gorrek emplementet e-PHP.\nMa lakait da dreiñ ul lec'hienn darempredet-stank e vo mat deoc'h lenn un tammig bihan diwar-benn se war [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode normalization]. (e saozneg)",
        "config-unicode-update-warning": "'''Diwallit''': ober a ra stumm staliet endalc'her skoueriekaat Unicode gant ur stumm kozh eus [http://site.icu-project.org/ levraoueg meziantoù ar raktres ICU].\nDleout a rafec'h [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations hizivaat] ma seblant deoc'h bezañ pouezus ober gant Unicode.",
        "config-no-db": "N'eus ket bet gallet kavout ur sturier diazoù roadennoù a zere ! Ret eo deoc'h staliañ ur sturier diazoù roadennoù evit PHP.\nSkoret eo an diazoù roadennoù da-heul : $1.\n\nMa rit gant un herberc'hiañ kenrannet, goulennit digant ho herberc'hier staliañ ur sturier diaz roadennoù azas.\nMa kempunit PHP c'hwi hoc'h-unan, adkeflugnit-eñ en ur weredekaat un arval diaz roadennoù, da skouer en ur ober gant <code>./configure --mysql</code>.\nM'hoc'h eus staliet PHP adalek ur pakad Debian pe Ubuntu, eo ret deoc'h staliañ ar vodulenn php5-mysql ivez.",
        "config-no-fts3": "'''Diwallit ''': Kempunet eo SQLite hep ar [//sqlite.org/fts3.html vodulenn FTS3]; ne vo ket posupl ober gant an arc'hwelioù klask er staliadur-mañ",
-       "config-register-globals": "'''Diwallit : Gweredekaet eo dibarzh <code>[http://php.net/register_globals register_globals]</code> PHP.'''\n'''Diweredekait anezhañ ma c'hallit.'''\nMont a raio MediaWiki en-dro met fazioù surentez a c'hallo c'hoari war ho servijer",
        "config-magic-quotes-runtime": "'''Fazi groñs : gweredekaet eo [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] !'''\nBreinañ a ra an dibarzh-mañ ar roadennoù en ur mod dic'hortoz.\nN'hallit ket staliañ pe ober gant MediaWiki e-keit ha m'eo gweredekaet an dibarzh-se.",
        "config-magic-quotes-sybase": "'''Fazi groñs : gweredekaet eo [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] !'''\nBreinañ a ra an dibarzh-mañ ar roadennoù en ur mod dic'hortoz.\nN'hallit ket staliañ pe ober gant MediaWiki e-keit ha m'eo gweredekaet an dibarzh-se.",
        "config-mbstring": "'''Fazi groñs : gweredekaet eo [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] !'''\nDegas a ra an dibarzh-mañ fazioù ha gallout a ra breinañ ar roadennoù en ur mod dic'hortoz.\nN'hallit ket staliañ pe ober gant MediaWiki e-keit ha m'eo gweredekaet an dibarzh-se.",
        "config-header-oracle": "Arventennoù Oracle",
        "config-header-mssql": "Arventennoù Microsoft SQL Server",
        "config-invalid-db-type": "Direizh eo ar seurt diaz roadennoù",
-       "config-missing-db-name": "Ret eo deoc'h merkañ un dalvoudenn evit \"Anv an diaz titouroù\"",
-       "config-missing-db-host": "Ret eo deoc'h merkañ un dalvoudenn evit \"Ostiz an diaz titouroù\"",
-       "config-missing-db-server-oracle": "Ret eo deoc'h merkañ un dalvoudenn evit \"Anv TNS an diaz titouroù\"",
+       "config-missing-db-name": "Ret eo deoc'h merkañ un dalvoudenn evit \"{{int:config-db-name}}\".",
+       "config-missing-db-host": "Ret eo deoc'h merkañ un dalvoudenn evit \"{{int:config-db-host}}\"",
+       "config-missing-db-server-oracle": "Ret eo deoc'h merkañ un dalvoudenn evit \"{{int:config-db-host-oracle}}\".",
        "config-invalid-db-server-oracle": "Direizh eo anv TNS an diaz titouroù \"$1\".\nOber hepken gant lizherennoù ASCII (a-z, A-Z), sifroù (0-9), arouezennoù islinennañ (_) ha pikoù (.).",
        "config-invalid-db-name": "Direizh eo anv an diaz titouroù \"$1\".\nOber hepken gant lizherennoù ASCII (a-z, A-Z), sifroù (0-9), arouezennoù islinennañ (_) ha tiredoù (-).",
        "config-invalid-db-prefix": "Direizh eo rakger an diaz titouroù \"$1\".\nOber hepken gant lizherennoù ASCII (a-z, A-Z), sifroù (0-9), arouezennoù islinennañ (_) ha tiredoù (-).",
        "config-db-web-help": "Diuzañ an anv implijer hag ar ger-tremen a vo implijet gant ar servijer web evit kevreañ ouzh ar servijer diaz roadennoù pa vez ar wiki o vont en-dro war ar pemdez.",
        "config-db-web-account-same": "Ober gant an hevelep kont hag an hini implijet evit ar staliañ",
        "config-db-web-create": "Krouiñ ar gont ma n'eus ket anezhi c'hoazh",
+       "config-db-web-no-create-privs": "Ar gont ho peus diferet evit ar staliañ n'he deus ket gwirioù a-walc'h evit krouiñ ur gont.\nRet eo d'ar gont diferet amañ bezañ anezhi dija.",
        "config-mysql-engine": "Lusker stokañ :",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
        "config-memcache-badport": "Niverennoù porzh Memcached a zlefe bezañ etre $1 ha $2.",
        "config-extensions": "Astennoù",
        "config-extensions-help": "N'eo ket bet detektet an astennoù rollet a-us en ho kavlec'h <code>./astennoù</code>.\n\nMarteze e vo ezhomm kefluniañ pelloc'h met gallout a rit o gweredekaat bremañ.",
+       "config-skins": "Gwiskadurioù",
+       "config-skins-use-as-default": "Implijout ar gwiskadur-mañ dre ziouer",
+       "config-skins-must-enable-some": "Ret eo deoc'h dibab da nebautañ ur gwiskadur da weredekaat.",
+       "config-skins-must-enable-default": "Ar gwiskadur dre ziouer dibabet a rank bezañ gweredekaet.",
        "config-install-alreadydone": "'''Diwallit''': Staliet hoc'h eus MediaWiki dija war a seblant hag emaoc'h o klask e staliañ c'hoazh.\nKit d'ar bajenn war-lerc'h, mar plij.",
        "config-install-begin": "Pa vo bet pouezet ganeoc'h war \"{{int:config-continue}}\"  e krogo staliadur MediaWiki.\nPouezit war \"{{int:config-back}}\" mar fell deoc'h cheñch tra pe dra.",
        "config-install-step-done": "graet",
        "config-install-interwiki-list": "Ne c'haller ket kavout ar restr <code>interwiki.list</code>.",
        "config-install-stats": "O sevel ar stadegoù",
        "config-install-keys": "Genel an alc'hwezioù kuzh",
+       "config-install-updates": "Mirout da lakaat hizivadennoù diezhomm da vont en-dro",
        "config-install-sysop": "Krouidigezh kont ar merour",
        "config-install-subscribe-fail": "N'haller ket koumanantiñ da mediawiki-announce : $1",
        "config-install-subscribe-notpossible": "cURL n'eo ket staliet ha ne c'haller ket ober gant <code>allow_url_fopen</code>.",
diff --git a/includes/installer/i18n/bto.json b/includes/installer/i18n/bto.json
new file mode 100644 (file)
index 0000000..468bceb
--- /dev/null
@@ -0,0 +1,65 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Filipinayzd"
+               ]
+       },
+       "config-title": "Pabutang ka MediaWiki $1",
+       "config-information": "Impormasyon",
+       "config-your-language": "A kanimong sarita:",
+       "config-wiki-language": "Sarita ka Wiki:",
+       "config-back": "← Bumalik",
+       "config-continue": "Magpadagos →",
+       "config-page-language": "Sarita",
+       "config-page-welcome": "Dagos sa MediaWiki!",
+       "config-page-name": "Ngaran",
+       "config-page-options": "Mga pipilian",
+       "config-page-install": "Ikabit",
+       "config-page-complete": "Tapos!",
+       "config-page-readme": "Basahon ako",
+       "config-page-copying": "Kinokopya",
+       "config-restart": "Amo, uliton adi",
+       "config-diff3-bad": "Diri nataurakan a GNU diff3.",
+       "config-db-type": "Klase ka database:",
+       "config-db-host": "Host ka database:",
+       "config-db-host-oracle": "Database ka TNS:",
+       "config-db-wiki-settings": "Mibdiron adin wiki",
+       "config-db-name": "Ngaran ka database:",
+       "config-charset-mysql5-binary": "MySQL 4.1/5.0 binary",
+       "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
+       "config-charset-mysql4": "MySQL 4.0 backwards-compatible UTF-8",
+       "config-db-port": "Port ka database:",
+       "config-db-schema": "Skema para sa MediaWiki:",
+       "config-sqlite-dir": "Direktoryo ka data sa SQLite:",
+       "config-oracle-def-ts": "Dating tablescape:",
+       "config-oracle-temp-ts": "Temporaryong tablescape:",
+       "config-type-mysql": "MySQL (o compatible)",
+       "config-type-mssql": "Microsoft SQL Server",
+       "config-header-mysql": "MySQL settings",
+       "config-header-postgres": "PostgreSQL settings",
+       "config-header-sqlite": "SQLite settings",
+       "config-header-oracle": "Oracle settings",
+       "config-header-mssql": "Microsoft SQL Server settings",
+       "config-mysql-innodb": "InnoDB",
+       "config-mysql-myisam": "MyISAM",
+       "config-mysql-binary": "Binary",
+       "config-mysql-utf8": "UTF-8",
+       "config-site-name": "Ngaran ka wiki",
+       "config-site-name-blank": "Ibutang a ngaran ka site.",
+       "config-project-namespace": "Bibutangan ka proyekto:",
+       "config-ns-generic": "Proyekto",
+       "config-ns-other-default": "MyWiki",
+       "config-admin-password": "Password:",
+       "config-admin-password-confirm": "Password ulit:",
+       "config-admin-email": "Email address:",
+       "config-profile-wiki": "Bukas na wiki",
+       "config-profile-private": "Pribadong wiki",
+       "config-license-pd": "Pampublikong Domain",
+       "config-email-sender": "Pabalik na email adres:",
+       "config-logo": "URL ko logo:",
+       "config-cc-again": "Pumili dayday...",
+       "config-install-step-done": "tapus na",
+       "config-install-user-alreadyexists": "Agko na ka user na \"$1\"",
+       "config-install-user-create-failed": "Sala a ginigibong user na \"$1\": $2",
+       "config-help": "tabang"
+}
index 8d678e0..3f1fcfc 100644 (file)
@@ -4,7 +4,8 @@
                        "Pitort",
                        "පසිඳු කාවින්ද",
                        "Kippelboy",
-                       "Toniher"
+                       "Toniher",
+                       "Fitoschido"
                ]
        },
        "config-desc": "L'instal·lador del MediaWiki",
        "config-env-good": "S'ha comprovat l'entorn.\nPodeu instal·lar el MediaWiki.",
        "config-env-bad": "S'ha comprovat l'entorn.\nNo podeu instal·lar el MediaWiki.",
        "config-env-php": "El PHP $1 està instal·lat.",
-       "config-env-php-toolow": "El PHP $1 està instal·lat.\nMalauradament, el MediaWiki necessita el PHP $2 o superior.",
        "config-memory-raised": "El <code>memory_limit</code> del PHP és $1 i s'ha aixecat a $2.",
        "config-memory-bad": "<strong>Avís:</strong> El <code>memory_limit</code> del PHP és $1.\nAixò és probablement massa baix.\nLa instal·lació pot fallar!",
+       "config-apc": "L’[http://www.php.net/apc APC] està instal·lat",
        "config-diff3-bad": "No s'ha trobat el GNU diff3.",
        "config-git": "S'ha trobat el programari de control de versions Git: <code>$1</code>.",
        "config-git-bad": "No s'ha trobat el programari de control de versions Git.",
+       "config-no-scaling": "No s'ha pogut trobar la biblioteca GD o ImageMagick.\nS'inhabilitaran les miniatures de les imatges.",
        "config-no-uri": "'''Error:''' No s'ha pogut determinar l'URI actual. S'ha interromput la instal·lació.",
        "config-no-cli-uri": "'''Avís:''' No s'ha especificat un <code>--scriptpath</code>. S'utilitza el valor per defecte: <code>$1</code>.",
        "config-using-server": "S'utilitza el nom del servidor «<nowiki>$1</nowiki>».",
        "config-using-uri": "S'utilitza l'URL del servidor «<nowiki>$1$2</nowiki>».",
+       "config-uploads-not-safe": "<strong>Avís:</strong> El directori de càrregues per defecte <code>$1</code> és vulnerable a l'execució d'scripts arbitraris.\nEncara que el MediaWiki comprova tots els fitxers que es carreguen davant d'amenaces de seguretat, és molt recomanable [//www.mediawiki.org/ wiki/Special:MyLanguage/Manual:Security#Upload_security tancar aquesta vulnerabilitat de seguretat] abans d'habilitar les càrregues.",
        "config-db-type": "Tipus de base de dades:",
        "config-db-host": "Servidor de la base de dades:",
        "config-db-wiki-settings": "Identifica aquest wiki",
@@ -73,6 +76,7 @@
        "config-db-charset": "Joc de caràcters de la base de dades",
        "config-charset-mysql5-binary": "Binari de MySQL 4.1/5.0",
        "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
+       "config-mysql-old": "Cal el MySQL $1 o posterior. Teniu el $2.",
        "config-db-port": "Port de la base de dades:",
        "config-db-schema": "Esquema per a MediaWiki:",
        "config-db-schema-help": "Aquest esquema normalment ja serveix.\nNomés canvieu-lo si sabeu què us feu.",
        "config-type-mysql": "MySQL (o compatible)",
        "config-type-mssql": "Microsoft SQL Server",
        "config-header-mysql": "Paràmetres de MySQL",
+       "config-header-postgres": "Paràmetres del PostgreSQL",
+       "config-header-sqlite": "Paràmetres de l'SQLite",
+       "config-header-oracle": "Paràmetres de l'Oracle",
+       "config-header-mssql": "Paràmetres del Microsoft SQL Server",
        "config-invalid-db-type": "Tipus de base de dades no vàlid",
-       "config-missing-db-name": "Heu d'introduir un valor per al «nom de la base de dades»",
-       "config-missing-db-host": "Heu d'introduir un valor per al «servidor de la base de dades»",
+       "config-missing-db-name": "Heu d'introduir un valor per a «{{int:config-db-name}}».",
+       "config-missing-db-host": "Heu d'introduir un valor per a «{{int:config-db-host}}».",
+       "config-missing-db-server-oracle": "Heu d’introduir un valor per a «{{int:config-db-host-oracle}}».",
+       "config-db-sys-user-exists-oracle": "El compte d’usuari «$1» ja existeix. SYSDBA només es pot fer servir per crear comptes nous.",
        "config-sqlite-readonly": "El fitxer <code>$1</code> no es pot escriure.",
        "config-sqlite-cant-create-db": "No s'ha pogut crear el fitxer de base de dades <code>$1</code>.",
        "config-upgrade-done-no-regenerate": "S'ha completat l'actualització.\n\nJa podeu [$1 començar a utilitzar el wiki].",
        "config-mysql-engine": "Motor d'emmagatzemament:",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
+       "config-mysql-charset": "Joc de caràcters de la base de dades:",
        "config-mysql-binary": "Binari",
        "config-mysql-utf8": "UTF-8",
        "config-mssql-auth": "Tipus d'autenticació:",
+       "config-mssql-sqlauth": "Autenticació de l’SQL Server",
+       "config-mssql-windowsauth": "Autenticació del Windows",
        "config-site-name": "Nom del wiki:",
        "config-site-name-blank": "Introduïu un nom per al lloc.",
        "config-project-namespace": "Espai de noms del projecte:",
        "config-upload-deleted": "Directori pels arxius suprimits:",
        "config-logo": "URL del logo:",
        "config-instantcommons": "Habilita Instant Commons",
+       "config-cc-error": "El selector de llicència Creative Commons no ha donat cap resultat.\nIntroduïu la llicència manualment.",
        "config-cc-again": "Torneu-ho a triar...",
        "config-cc-not-chosen": "Trieu quina llicència Creative Commons voleu i feu clic a «procedeix».",
        "config-advanced-settings": "Configuració avançada",
        "config-cache-options": "Configuració per a la memòria cau dels objectes:",
+       "config-cache-help": "L'encauament d'objectes s'utilitza per a millorar la rapidesa del MediaWiki afegint a la memòria cau les dades que s'utilitzen de forma freqüent. És recomanable que els llocs web mitjans o grans ho habilitin. També els llocs web petits en veuran els beneficis.",
+       "config-cache-none": "Sense encauament (no se suprimeix cap funcionalitat, però la velocitat pot veure's afectada en els llocs wiki més grans)",
        "config-memcached-servers": "Servidors de Memcache:",
        "config-extensions": "Extensions",
+       "config-skins": "Aparences",
        "config-install-step-done": "fet",
        "config-install-step-failed": "ha fallat",
        "config-install-extensions": "S'estan incloent les extensions",
        "config-install-database": "S'està configurant la base de dades",
        "config-install-schema": "S'està creant l'esquema",
+       "config-install-pg-schema-not-exist": "No existeix un esquema PostgreSQL.",
+       "config-install-pg-schema-failed": "La creació de les taules ha fallat.\nAssegureu-vos que l'usuari «$1» pot escriure a l'esquema «$2».",
        "config-install-pg-commit": "S'estan trametent els canvis",
        "config-install-user": "S'està creant l'usuari de la base de dades",
        "config-install-user-alreadyexists": "L'usuari «$1» ja existeix",
        "config-install-mainpage-failed": "No s'ha pogut inserir la pàgina principal: $1",
        "config-download-localsettings": "Baixa <code>LocalSettings.php</code>",
        "config-help": "ajuda",
+       "config-help-tooltip": "feu clic per ampliar",
        "config-nofile": "No s'ha pogut trobar el fitxer «$1». S'ha suprimit?",
        "mainpagetext": "'''El MediaWiki s'ha instal·lat correctament.'''",
        "mainpagedocfooter": "Consulteu la [//meta.wikimedia.org/wiki/Help:Contents Guia d'Usuari] per a més informació sobre com utilitzar-lo.\n\n== Per a començar ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Llista de característiques configurables]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ PMF del MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Llista de correu (''listserv'') per a anuncis del MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Traduïu MediaWiki en la vostra llengua]"
index 56b2732..0cffa94 100644 (file)
        "config-enable-email": "Латае дӀайохьуьйту e-mail",
        "config-upload-deleted": "ДӀаяхна файлийн директори:",
        "config-cc-again": "Хьаржа кхин цӀа…",
+       "config-skins": "Кечяран тема",
+       "config-skins-use-as-default": "ХӀара тема Ӏад йитарца лелае",
+       "config-skins-must-enable-some": "Ахьа цхьаъ мукъа тема латина йита езаш ю.",
+       "config-skins-must-enable-default": "Ӏад йитарца йолу тема латина хила еза.",
        "config-install-user": "Декъашхочун хаамийн база кхоллар",
        "config-install-user-alreadyexists": "Декъашхо «$1» хӀинцале волуш ву",
        "config-install-user-create-failed": "Декъашхо «$1» кхолла цаделира: $2",
index dbfef20..a783cfe 100644 (file)
@@ -52,7 +52,7 @@
        "config-env-good": "Prostředí bylo zkontrolováno.\nMůžete nainstalovat MediaWiki.",
        "config-env-bad": "Prostředí bylo zkontrolováno.\nMediaWiki nelze nainstalovat.",
        "config-env-php": "Je nainstalováno PHP $1.",
-       "config-env-php-toolow": "Je nainstalováno PHP $1.\nMediaWiki ale vyžaduje PHP $2 nebo vyšší.",
+       "config-env-hhvm": "Je nainstalováno HHVM $1.",
        "config-unicode-using-utf8": "Pro normalizaci Unicode se používá utf8_normalize.so Briona Vibbera.",
        "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].",
@@ -60,7 +60,8 @@
        "config-no-db": "Nepodařilo se nalézt vhodný databázový ovladač! Musíte do PHP nainstalovat databázový ovladač.\nJsou 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 php5-mysql.",
        "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-register-globals": "'''Upozornění: Je zapnuta PHP volba <code>[http://php.net/register_globals register_globals]</code>.'''\n'''Pokud můžete, vypněte ji.'''\nMediaWiki bude fungovat, ale váš server je vystaven potenciálním bezpečnostním hrozbám.",
+       "config-register-globals-error": "<strong>Chyba: PHP nastavení <code>[http://php.net/register_globals register_globals]</code> je zapnuto. Pro pokračování v instalaci musí být vypnuto.</strong>\nRady, jak toho dosáhnout, najdete na [https://www.mediawiki.org/wiki/Register_globals https://www.mediawiki.org/wiki/register_globals].",
+       "config-magic-quotes-gpc": "<strong>Kritická chyba: Je zapnuto [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc]!</strong>\nToto nastavení nepředvídatelně poškozuje vstupní data.\nMediaWiki nelze nainstalovat ani používat, dokud není toto nastavení vypnuto.",
        "config-magic-quotes-runtime": "'''Kritická chyba: Je zapnuto [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime]!'''\nToto nastavení nepředvídatelně poškozuje vstupní data.\nMediaWiki nelze nainstalovat ani používat, dokud není toto nastavení vypnuto.",
        "config-magic-quotes-sybase": "'''Kritická chyba: Je zapnuto [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase]!'''\nToto nastavení nepředvídatelně poškozuje vstupní data.\nMediaWiki nelze nainstalovat ani používat, dokud není toto nastavení vypnuto.",
        "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.",
@@ -71,6 +72,7 @@
        "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-xcache": "Je nainstalována [http://xcache.lighttpd.net/ XCache]",
        "config-apc": "Je nainstalováno [http://www.php.net/apc APC]",
        "config-license-gfdl": "GNU Free Documentation License 1.3 nebo novější",
        "config-license-pd": "Volné dílo",
        "config-license-cc-choose": "Zvolit vlastní licenci Creative Commons",
-       "config-license-help": "Mnoho veřejných wiki všechny příspěvky zveřejňuje pod některou [http://freedomdefined.org/Definition/Cs svobodnou licencí].\nTo pomáhá vytvořit duch komunitního vlastnictví a povzbuzuje dlouhodobé přispívání.\nTo obecně není potřeba u soukromé nebo firemní wiki.\n\nPokud chcete být schopni používat text z Wikipedie a chcete, aby Wikipedie byla schopna přijímat text okopírovaný z vaší wiki, měli byste zvolit '''Creative Commons Uveďte autora-Zachovejte licenci'''.\n\nDříve Wikipedie používala GNU Free Documentation License.\nGFDL je platná licence, ale složité jí porozumět.\nTaké je komplikované používat obsah licencovaný pod GFDL.",
+       "config-license-help": "Mnoho veřejných wiki všechny příspěvky zveřejňuje pod některou [http://freedomdefined.org/Definition/Cs svobodnou licencí].\nTo pomáhá vytvořit duch komunitního vlastnictví a povzbuzuje dlouhodobé přispívání.\nTo obecně není potřeba u soukromé nebo firemní wiki.\n\nPokud chcete být schopni používat text z Wikipedie a chcete, aby Wikipedie byla schopna přijímat text okopírovaný z vaší wiki, měli byste zvolit <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nDříve Wikipedie používala GNU Free Documentation License.\nGFDL je platná licence, ale složité jí porozumět.\nTaké je komplikované používat obsah licencovaný pod GFDL.",
        "config-email-settings": "Nastavení e-mailu",
        "config-enable-email": "Zapnout odchozí e-mail",
        "config-enable-email-help": "Pokud chcete, aby e-mail fungoval, je potřeba správně nakonfigurovat [http://www.php.net/manual/en/mail.configuration.php e-mailová nastavení PHP].\nPokud nechcete žádné e-mailové funkce, můžete je zde vypnout.",
        "config-memcache-badport": "Čísla portů pro Memcached by měla být mezi $1 a $2.",
        "config-extensions": "Rozšíření",
        "config-extensions-help": "Výše uvedená rozšíření byla nalezena ve vašem adresáři <code>./extensions</code>.\n\nMohou vyžadovat dodatečnou konfiguraci, ale teď je můžete povolit.",
+       "config-skins": "Vzhledy",
+       "config-skins-help": "Ve vašem adresáři <code>./skins</code> byly nalezeny výše uvedené vzhledy. Musíte nejméně jeden z nich povolit a některý vybrat jako výchozí.",
+       "config-skins-use-as-default": "Tento vzhled používat jako výchozí",
+       "config-skins-missing": "Nebyly nalezeny žádné vzhledy; MediaWiki bude používat nouzový vzhled, dokud nenainstalujete nějaké plnohodnotné.",
+       "config-skins-must-enable-some": "Musíte povolit alespoň jeden vzhled.",
+       "config-skins-must-enable-default": "Vzhled vybraný jako výchozí musí být povolen.",
        "config-install-alreadydone": "'''Upozornění:''' Vypadá to, že jste MediaWiki již nainstalovali a teď se o to pokoušíte znovu.\nPokračujte na další stránku.",
        "config-install-begin": "Stisknutím „{{int:config-continue}}“ spustíte instalaci MediaWiki.\nPokud ještě chcete udělat nějaké změny, stiskněte „{{int:config-back}}“.",
        "config-install-step-done": "hotovo",
        "config-install-stats": "Inicializují se statistiky",
        "config-install-keys": "Vytvářejí se tajné klíče",
        "config-insecure-keys": "'''Upozornění:''' {{PLURAL:$2|Tajný klíč|Tajné klíče}} ($1) vytvořené v průběhu instalace {{PLURAL:$2|není|nejsou}} zcela {{PLURAL:$2|bezpečný|bezpečné}}. Zvažte {{PLURAL:$2|jeho|jejich}} ruční změnu.",
+       "config-install-updates": "Ruší se spuštění nepotřebných aktualizací",
+       "config-install-updates-failed": "<strong>Chyba:</strong> Vložení aktualizačních klíčů do tabulek selhalo s následující chybou: $1",
        "config-install-sysop": "Zakládá se uživatelský účet správce",
        "config-install-subscribe-fail": "Nelze se přihlásit k odběru mediawiki-announce: $1",
        "config-install-subscribe-notpossible": "Není nainstalován cURL a není dostupné <code>allow_url_fopen</code>.",
index 59eec45..b9de2cf 100644 (file)
@@ -3,7 +3,8 @@
                "authors": [
                        "Peter Alberti",
                        "Christian List",
-                       "Tjernobyl"
+                       "Tjernobyl",
+                       "Thomsen"
                ]
        },
        "config-page-language": "Sprog",
        "config-page-name": "Navn",
        "config-page-options": "Indstillinger",
        "config-page-install": "Installer",
+       "config-page-complete": "Færdig!",
+       "config-page-restart": "Genstarte installation",
+       "config-page-readme": "Læs mig",
+       "config-page-copying": "Kopiering",
+       "config-page-upgradedoc": "Opgraderer",
+       "config-page-existingwiki": "Eksisterende wiki",
+       "config-help-restart": "Vil du rydde alle gemte data, du har indtastet og genstarte installationen?",
+       "config-restart": "Ja, genstart den",
+       "config-env-php": "PHP $1 er installeret.",
+       "config-db-type": "Databasetype:",
+       "config-db-host": "Databasevært:",
+       "config-db-name": "Databasenavn:",
+       "config-mysql-old": "MySQL $1 eller nyere kræves. Du har $2.",
        "config-header-mysql": "MySQL-indstillinger",
        "config-header-postgres": "PostgreSQL-indstillinger",
        "config-header-sqlite": "SQLite-indstillinger",
index cd18c92..f329db9 100644 (file)
@@ -58,7 +58,7 @@
        "config-env-good": "Die Installationsumgebung wurde geprüft.\nMediaWiki kann installiert werden.",
        "config-env-bad": "Die Installationsumgebung wurde geprüft.\nMediaWiki kann nicht installiert werden.",
        "config-env-php": "Die Skriptsprache „PHP“ ($1) ist installiert.",
-       "config-env-php-toolow": "PHP $1 ist installiert.\nAllerdings benötigt MediaWiki PHP $2 oder höher.",
+       "config-env-hhvm": "HHVM $1 ist installiert.",
        "config-unicode-using-utf8": "Zur Unicode-Normalisierung wird Brion Vibbers <code>utf8_normalize.so</code> eingesetzt.",
        "config-unicode-using-intl": "Zur  Unicode-Normalisierung wird die [http://pecl.php.net/intl PECL-Erweiterung intl] eingesetzt.",
        "config-unicode-pure-php-warning": "'''Warnung:''' Die [http://pecl.php.net/intl PECL-Erweiterung intl] ist für die Unicode-Normalisierung nicht verfügbar, so dass stattdessen die langsame pure-PHP-Implementierung genutzt wird.\nSofern eine Website mit großer Benutzeranzahl betrieben wird, sollten weitere Informationen auf der Webseite [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode-Normalisierung (en)] gelesen werden.",
@@ -66,7 +66,8 @@
        "config-no-db": "Es konnte kein adäquater Datenbanktreiber gefunden werden. Es muss daher ein Datenbanktreiber für PHP installiert werden.\nDie folgenden Datenbanksysteme werden unterstützt: $1\n\nWenn du PHP selbst kompiliert hast, konfiguriere es erneut mit einem aktivierten Datenbankclient, zum Beispiel durch Verwendung von <code>./configure --with-mysqli</code>.\nWenn du PHP von einem Debian- oder Ubuntu-Paket installiert hast, dann musst du auch beispielsweise das <code>php5-mysql</code>-Paket installieren.",
        "config-outdated-sqlite": "'''Warnung:''' SQLite $1 ist installiert. Allerdings benötigt MediaWiki SQLite $2 oder höher. SQLite wird daher nicht verfügbar sein.",
        "config-no-fts3": "'''Warnung:''' SQLite wurde ohne das [//sqlite.org/fts3.html FTS3-Modul] kompiliert, sodass keine Suchfunktionen für dieses Datenbanksystem zur Verfügung stehen werden.",
-       "config-register-globals": "'''Warnung: Der Parameter <code>[http://php.net/register_globals register_globals]</code> von PHP ist aktiviert.'''\n'''Sie sollte deaktiviert werden, sofern dies möglich ist.'''\nDie MediaWiki-Installation wird zwar laufen, wobei aber der Server für potentielle Sicherheitsprobleme anfällig ist.",
+       "config-register-globals-error": "<strong>Fehler: Die PHP-Option <code>[http://php.net/register_globals register_globals]</code> ist aktiviert.\nSie muss deaktiviert sein, um mit der Installation fortzufahren.</strong>\nSiehe [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] für Hilfe.",
+       "config-magic-quotes-gpc": "<strong>Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] ist aktiv!</strong>\nDiese Option beschädigt eingegebene Daten unvorhersehbar.\nDu kannst MediaWiki nicht installieren oder verwenden, bis diese Option deaktiviert ist.",
        "config-magic-quotes-runtime": "'''Fataler Fehler: Der Parameter <code>[http://www.php.net/manual/de/function.set-magic-quotes-runtime.php set_magic_quotes_runtime]</code> von PHP ist aktiviert!'''\nDiese Einstellung führt zu unvorhersehbaren Problemen bei der Dateneingabe.\nMediaWiki kann nicht installiert werden, solange dieser Parameter nicht deaktiviert wurde.",
        "config-magic-quotes-sybase": "<strong>Fataler Fehler: Der Parameter <code>[http://www.php.net/manual/de/sybase.configuration.php#ini.magic-quotes-sybase magic_quotes_sybase]</code> von PHP ist aktiviert!</strong>\nDiese Einstellung führt zu unvorhersehbaren Problemen bei der Dateneingabe.\nMediaWiki kann nicht installiert werden, solange dieser Parameter nicht deaktiviert wurde.",
        "config-mbstring": "'''Fataler Fehler: Der Parameter <code>[http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]</code> von PHP ist aktiviert!'''\nDiese Einstellung verursacht Fehler und führt zu unvorhersehbaren Problemen bei der Dateneingabe.\nMediaWiki kann nicht installiert werden, solange dieser Parameter nicht deaktiviert wurde.",
@@ -77,6 +78,7 @@
        "config-memory-raised": "Der PHP-Parameter <code>memory_limit</code> betrug $1 und wurde auf $2 erhöht.",
        "config-memory-bad": "'''Warnung:''' Der PHP-Parameter <code>memory_limit</code> beträgt $1.\nDieser Wert ist wahrscheinlich zu niedrig.\nDer Installationsvorgang könnte eventuell scheitern!",
        "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-xcache": "[http://xcache.lighttpd.net/ XCache] ist installiert",
        "config-apc": "[http://www.php.net/apc APC] ist installiert",
        "config-license-gfdl": "GNU-Lizenz für freie Dokumentation 1.3 oder höher",
        "config-license-pd": "Gemeinfreiheit",
        "config-license-cc-choose": "Eine benutzerdefinierte Creative-Commons-Lizenz auswählen",
-       "config-license-help": "Viele öffentliche Wikis publizieren alle Beiträge unter einer [http://freedomdefined.org/Definition/De freien Lizenz.]\nDies trägt dazu bei, ein Gefühl von Gemeinschaft zu schaffen, und ermutigt zu längerfristiger Mitarbeit.\nHingegen ist im Allgemeinen eine freie Lizenz auf geschlossenen Wikis nicht notwendig.\n\nSofern man Texte aus der Wikipedia verwenden möchte und umgekehrt, sollte die ''Creative-Commons''-Lizenz „Namensnennung – Weitergabe unter gleichen Bedingungen“ gewählt werden.\n\nDie Wikipedia nutzte vormals die GNU-Lizenz für freie Dokumentation (GFDL).\nDie GFDL ist eine gültige Lizenz, die allerdings schwer zu verstehen ist.\nEs ist zudem schwierig, gemäß dieser Lizenz lizenzierte Inhalte wiederzuverwenden.",
+       "config-license-help": "Viele öffentliche Wikis publizieren alle Beiträge unter einer [http://freedomdefined.org/Definition/De freien Lizenz.]\nDies trägt dazu bei, ein Gefühl von Gemeinschaft zu schaffen, und ermutigt zu längerfristiger Mitarbeit.\nHingegen ist im Allgemeinen eine freie Lizenz auf geschlossenen Wikis nicht notwendig.\n\nSofern man Texte aus der Wikipedia verwenden möchte und umgekehrt, sollte die Lizenz {{int:config-license-cc-by-sa}} gewählt werden.\n\nDie Wikipedia nutzte vormals die GNU-Lizenz für freie Dokumentation (GFDL).\nDie GFDL ist eine gültige Lizenz, die allerdings schwer zu verstehen ist.\nEs ist zudem schwierig, gemäß dieser Lizenz lizenzierte Inhalte wiederzuverwenden.",
        "config-email-settings": "E-Mail-Einstellungen",
        "config-enable-email": "Ausgehende E-Mails ermöglichen",
        "config-enable-email-help": "Sofern die E-Mail-Funktionen genutzt werden sollen, müssen die entsprechenden [http://www.php.net/manual/en/mail.configuration.php PHP-E-Mail-Einstellungen] richtig konfiguriert werden.\nFür den Fall, dass die E-Mail-Funktionen nicht benötigt werden, können sie hier deaktiviert werden.",
        "config-advanced-settings": "Erweiterte Konfiguration",
        "config-cache-options": "Einstellungen für die Zwischenspeicherung von Objekten:",
        "config-cache-help": "Das Objektcaching wird dazu genutzt, die Geschwindigkeit von MediaWiki zu verbessern, indem häufig genutzte Daten zwischengespeichert werden.\nEs wird sehr empfohlen, es für mittelgroße bis große Wikis zu nutzen, aber auch für kleine Wikis ergeben sich erkennbare Geschwindigkeitsverbesserungen.",
-       "config-cache-none": "Kein Objektcaching (es wird keine Funktion entfernt, allerdings kann dies die Geschwindigkeit größerer Wikis negativ beeinflussen)",
+       "config-cache-none": "Kein Objektcaching (es wird keine Funktion entfernt, allerdings kann dies die Leistungsfähigkeit größerer Wikis negativ beeinflussen)",
        "config-cache-accel": "Objektcaching von PHP (APC, XCache oder WinCache)",
-       "config-cache-memcached": "Memcached Cacheserver nutzen (erfordert einen zusätzlichen Installationsvorgang mitsamt Konfiguration)",
+       "config-cache-memcached": "Memcached Cacheserver (erfordert einen zusätzlichen Installationsvorgang mitsamt Konfiguration)",
        "config-memcached-servers": "Memcached Cacheserver",
        "config-memcached-help": "Liste der für Memcached nutzbaren IP-Adressen.\nEs sollte eine je Zeile mitsamt des vorgesehenen Ports angegeben werden. Beispiele:\n127.0.0.1:11211 oder\n192.168.1.25:1234 usw.",
        "config-memcache-needservers": "Memcached wurde als Cacheserver ausgewählt. Dabei wurde allerdings kein Server angegeben.",
        "config-memcache-badport": "Der Ports für den Memcached Cacheserver sollten zwischen $1 und $2 liegen",
        "config-extensions": "Erweiterungen",
        "config-extensions-help": "Die obig angegebenen Erweiterungen wurden im Verzeichnis <code>./extensions</code> gefunden.\n\nEs könnten zusätzliche Konfigurierungen zu einzelnen Erweiterungen erforderlich sein, dennoch können sie aber bereits jetzt aktiviert werden.",
+       "config-skins": "Benutzeroberflächen",
+       "config-skins-help": "Die oben aufgeführten Benutzeroberflächen wurden im Verzeichnis <code>./skins</code> gefunden. Du musst mindestens eine aktivieren und als Standard auswählen.",
+       "config-skins-use-as-default": "Diese Benutzeroberfläche als Standard verwenden",
+       "config-skins-missing": "Es wurden keine Benutzeroberflächen gefunden. MediaWiki wird eine Fallback-Benutzeroberfläche verwenden, bis du andere Benutzeroberflächen installierst.",
+       "config-skins-must-enable-some": "Du musst mindestens eine zu aktivierende Benutzeroberfläche auswählen.",
+       "config-skins-must-enable-default": "Die ausgewählte Standard-Benutzeroberfläche muss aktiviert sein.",
        "config-install-alreadydone": "'''Warnung:''' Es wurde eine vorhandene MediaWiki-Installation gefunden.\nEs muss daher mit den nächsten Seite weitergemacht werden.",
        "config-install-begin": "Durch Drücken von „{{int:config-continue}}“ wird die Installation von MediaWiki gestartet.\nSofern Änderungen vorgenommen werden sollen, kann man auf „{{int:config-back}}“ klicken.",
        "config-install-step-done": "erledigt",
        "config-install-stats": "Statistiken werden initialisiert",
        "config-install-keys": "Geheimschlüssel werden erstellt",
        "config-insecure-keys": "'''Warnung:''' {{PLURAL:$2|Der Geheimschlüssel|Die Geheimschlüssel}} $1, {{PLURAL:$2|der|die}} während des Installationsvorgangs generiert {{PLURAL:$2|wurde, ist|wurden, sind}} nicht sehr sicher. {{PLURAL:$2|Er sollte|Sie sollten}} manuell geändert werden.",
+       "config-install-updates": "Unnötige Aktualisierungen nicht ausführen",
+       "config-install-updates-failed": "<strong>Fehler:</strong> Das Einfügen von Aktualisierungsschlüssel in die Tabellen ist mit dem folgenden Fehler fehlgeschlagen: $1",
        "config-install-sysop": "Administratorkonto wird erstellt",
        "config-install-subscribe-fail": "Abonnieren von „mediawiki-announce“ ist gescheitert: $1",
        "config-install-subscribe-notpossible": "cURL ist nicht installiert und <code>allow_url_fopen</code> ist nicht verfügbar.",
index 7d782d5..6b9f590 100644 (file)
@@ -15,7 +15,7 @@
        "config-license-none": "No licence footer",
        "config-license-gfdl": "GNU Free Documentation Licence 1.3 or later",
        "config-license-cc-choose": "Select a custom Creative Commons licence",
-       "config-license-help": "Many public wikis put all contributions under a [http://freedomdefined.org/Definition free licence].\nThis helps to create a sense of community ownership and encourages long-term contribution.\nIt is not generally necessary for a private or corporate wiki.\n\nIf you want to be able to use text from Wikipedia, and you want Wikipedia to be able to accept text copied from your wiki, you should choose '''Creative Commons Attribution Share Alike'''.\n\nWikipedia previously used the GNU Free Documentation Licence.\nThe GFDL is a valid licence, but it is difficult to understand.\nIt is also difficult to reuse content licenced under the GFDL.",
+       "config-license-help": "Many public wikis put all contributions under a [http://freedomdefined.org/Definition free licence].\nThis helps to create a sense of community ownership and encourages long-term contribution.\nIt is not generally necessary for a private or corporate wiki.\n\nIf you want to be able to use text from Wikipedia, and you want Wikipedia to be able to accept text copied from your wiki, you should choose <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nWikipedia previously used the GNU Free Documentation Licence.\nThe GFDL is a valid licence, but it is difficult to understand.\nIt is also difficult to reuse content licenced under the GFDL.",
        "config-cc-error": "The Creative Commons licence chooser gave no result.\nEnter the licence name manually.",
        "config-cc-not-chosen": "Choose which Creative Commons licence you want and click \"proceed\".",
        "config-install-stats": "Initialising statistics"
index 0d1f90e..1e1c2da 100644 (file)
@@ -44,7 +44,7 @@
        "config-env-good": "The environment has been checked.\nYou can install MediaWiki.",
        "config-env-bad": "The environment has been checked.\nYou cannot install MediaWiki.",
        "config-env-php": "PHP $1 is installed.",
-       "config-env-php-toolow": "PHP $1 is installed.\nHowever, MediaWiki requires PHP $2 or higher.",
+       "config-env-hhvm": "HHVM $1 is installed.",
        "config-unicode-using-utf8": "Using Brion Vibber's utf8_normalize.so for Unicode normalization.",
        "config-unicode-using-intl": "Using the [http://pecl.php.net/intl intl PECL extension] for Unicode normalization.",
        "config-unicode-pure-php-warning": "<strong>Warning:</strong> The [http://pecl.php.net/intl intl PECL extension] is not available to handle Unicode normalization, falling back to slow pure-PHP implementation.\nIf you run a high-traffic site, you should read a little on [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode normalization].",
@@ -52,7 +52,8 @@
        "config-no-db": "Could not find a suitable database driver! You need to install a database driver for PHP.\nThe following database types are supported: $1.\n\nIf you compiled PHP yourself, reconfigure it with a database client enabled, for example, using <code>./configure --with-mysqli</code>.\nIf you installed PHP from a Debian or Ubuntu package, then you also need to install, for example, the <code>php5-mysql</code> package.",
        "config-outdated-sqlite": "<strong>Warning:</strong> you have SQLite $1, which is lower than minimum required version $2. SQLite will be unavailable.",
        "config-no-fts3": "<strong>Warning:</strong> SQLite is compiled without the [//sqlite.org/fts3.html FTS3 module], search features will be unavailable on this backend.",
-       "config-register-globals-error": "<strong>Error: PHP's <code>[http://php.net/register_globals register_globals]</code> option is enabled.\nIt must be disabled to continue with installation.</strong>\nSee [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] for help on how to do so.",
+       "config-register-globals-error": "<strong>Error: PHP's <code>[http://php.net/register_globals register_globals]</code> option is enabled.\nIt must be disabled to continue with the installation.</strong>\nSee [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] for help on how to do so.",
+       "config-magic-quotes-gpc": "<strong>Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] is active!</strong>\nThis option corrupts data input unpredictably.\nYou cannot install or use MediaWiki unless this option is disabled.",
        "config-magic-quotes-runtime": "<strong>Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] is active!'</strong>\nThis option corrupts data input unpredictably.\nYou cannot install or use MediaWiki unless this option is disabled.",
        "config-magic-quotes-sybase": "<strong>Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] is active!</strong>\nThis option corrupts data input unpredictably.\nYou cannot install or use MediaWiki unless this option is disabled.",
        "config-mbstring": "<strong>Fatal: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] is active!</strong>\nThis option causes errors and may corrupt data unpredictably.\nYou cannot install or use MediaWiki unless this option is disabled.",
@@ -63,6 +64,7 @@
        "config-memory-raised": "PHP's <code>memory_limit</code> is $1, raised to $2.",
        "config-memory-bad": "<strong>Warning:</strong> PHP's <code>memory_limit</code> is $1.\nThis is probably too low.\nThe installation may fail!",
        "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-xcache": "[http://xcache.lighttpd.net/ XCache] is installed",
        "config-apc": "[http://www.php.net/apc APC] is installed",
        "config-license-gfdl": "GNU Free Documentation License 1.3 or later",
        "config-license-pd": "Public Domain",
        "config-license-cc-choose": "Select a custom Creative Commons license",
-       "config-license-help": "Many public wikis put all contributions under a [http://freedomdefined.org/Definition free license].\nThis helps to create a sense of community ownership and encourages long-term contribution.\nIt is not generally necessary for a private or corporate wiki.\n\nIf you want to be able to use text from Wikipedia, and you want Wikipedia to be able to accept text copied from your wiki, you should choose <strong>Creative Commons Attribution Share Alike</strong>.\n\nWikipedia previously used the GNU Free Documentation License.\nThe GFDL is a valid license, but it is difficult to understand.\nIt is also difficult to reuse content licensed under the GFDL.",
+       "config-license-help": "Many public wikis put all contributions under a [http://freedomdefined.org/Definition free license].\nThis helps to create a sense of community ownership and encourages long-term contribution.\nIt is not generally necessary for a private or corporate wiki.\n\nIf you want to be able to use text from Wikipedia, and you want Wikipedia to be able to accept text copied from your wiki, you should choose <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nWikipedia previously used the GNU Free Documentation License.\nThe GFDL is a valid license, but it is difficult to understand.\nIt is also difficult to reuse content licensed under the GFDL.",
        "config-email-settings": "Email settings",
        "config-enable-email": "Enable outbound email",
        "config-enable-email-help": "If you want email to work, [http://www.php.net/manual/en/mail.configuration.php PHP's mail settings] need to be configured correctly.\nIf you do not want any email features, you can disable them here.",
        "config-memcache-badport": "Memcached port numbers should be between $1 and $2.",
        "config-extensions": "Extensions",
        "config-extensions-help": "The extensions listed above were detected in your <code>./extensions</code> directory.\n\nThey may require additional configuration, but you can enable them now.",
+       "config-skins": "Skins",
+       "config-skins-help": "The skins listed above were detected in your <code>./skins</code> directory. You must enable at least one, and choose the default.",
+       "config-skins-use-as-default": "Use this skin as default",
+       "config-skins-missing": "No skins were found; MediaWiki will use a fallback skin until you install some proper ones.",
+       "config-skins-must-enable-some": "You must choose at least one skin to enable.",
+       "config-skins-must-enable-default": "The skin chosen as default must be enabled.",
        "config-install-alreadydone": "<strong>Warning:</strong> You seem to have already installed MediaWiki and are trying to install it again.\nPlease proceed to the next page.",
        "config-install-begin": "By pressing \"{{int:config-continue}}\", you will begin the installation of MediaWiki.\nIf you still want to make changes, press \"{{int:config-back}}\".",
        "config-install-step-done": "done",
        "config-install-stats": "Initializing statistics",
        "config-install-keys": "Generating secret keys",
        "config-insecure-keys": "<strong>Warning:</strong> {{PLURAL:$2|A secure key|Secure keys}} ($1) generated during installation {{PLURAL:$2|is|are}} not completely safe. Consider changing {{PLURAL:$2|it|them}} manually.",
+       "config-install-updates": "Prevent running unneeded updates",
+       "config-install-updates-failed": "<strong>Error:</strong> Inserting update keys into tables failed with the following error: $1",
        "config-install-sysop": "Creating administrator user account",
        "config-install-subscribe-fail": "Unable to subscribe to mediawiki-announce: $1",
        "config-install-subscribe-notpossible": "cURL is not installed and <code>allow_url_fopen</code> is not available.",
index 71da7f2..250816a 100644 (file)
        "config-env-good": "La medio estis kontrolita.\nVi povas instali MediaWiki.",
        "config-env-bad": "La medio estis kontrolita.\nNe eblas instali MediaWiki.",
        "config-env-php": "PHP $1 estas instalita.",
-       "config-env-php-toolow": "PHP $1 estas instalita.\nTamen, MediaWiki bezonas PHP $2 aŭ pli novan.",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] estas instalita.",
        "config-apc": "[http://www.php.net/apc APC] estas instalita",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] estas instalita",
        "config-diff3-bad": "GNU diff3 ne estis trovita.",
        "config-db-type": "Tipo de datumbazo:",
+       "config-db-wiki-settings": "Identigu ĉi tiun vikion",
+       "config-db-name": "Nomo de datumbazo:",
        "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
        "config-type-mysql": "MySQL (aŭ kongrua)",
+       "config-admin-password": "Pasvorto:",
+       "config-admin-password-confirm": "Retajpu pasvorton:",
+       "config-admin-name-blank": "Enigu salutnomon de administranto.",
+       "config-admin-email": "Retpoŝtadreso:",
        "mainpagetext": "'''MediaWiki estis sukcese instalita.'''",
        "mainpagedocfooter": "Konsultu la [//meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide Gvidilon por uzantoj de MediaWiki] por informoj pri uzado de vikia programaro.\n\n==Kiel komenci==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Listo de konfiguraĵoj] (angle)\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki Oftaj Demandoj] (angle)\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Anonco-dissendolisto pri MediaWiki] (angle)\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Preklad MediaWiki do tvojho jazyka]"
 }
index b37a1b7..ee1a2f4 100644 (file)
                        "Ihojose",
                        "Seb35",
                        "McDutchie",
-                       "Miguel2706"
+                       "Miguel2706",
+                       "Macofe",
+                       "AVIADOR",
+                       "FuzzyDice"
                ]
        },
        "config-desc": "El instalador de MediaWiki",
@@ -39,9 +42,9 @@
        "config-session-expired": "Tus datos de sesión parecen haber expirado.\nLas sesiones están configuradas por una duración de $1.\nPuedes incrementar esto configurando <code>session.gc_maxlifetime</code> en php.ini.\nReiniciar el proceso de instalación.",
        "config-no-session": "Se han perdido los datos de sesión.\nVerifica tu php.ini y comprueba que <code>session.save_path</code> está establecido en un directorio apropiado.",
        "config-your-language": "Tu idioma:",
-       "config-your-language-help": "Seleccionar un idioma a usar durante el proceso de instalación.",
+       "config-your-language-help": "Selecciona un idioma para usar durante el proceso de instalación.",
        "config-wiki-language": "Idioma del wiki:",
-       "config-wiki-language-help": "Seleccionar el idioma en el que el wiki será escrito predominantemente.",
+       "config-wiki-language-help": "Selecciona el idioma en el que se escribirá predominantemente el wiki.",
        "config-back": "← Atrás",
        "config-continue": "Continuar →",
        "config-page-language": "Idioma",
@@ -67,7 +70,7 @@
        "config-env-good": "El entorno ha sido comprobado.\nPuedes instalar MediaWiki.",
        "config-env-bad": "El entorno ha sido comprobado.\nNo puedes instalar MediaWiki.",
        "config-env-php": "PHP $1 está instalado.",
-       "config-env-php-toolow": "PHP $1 está instalado.\nSin embargo, MediaWiki requiere PHP $2 o superior.",
+       "config-env-hhvm": "HHVM $1 está instalado.",
        "config-unicode-using-utf8": "Usando utf8_normalize.so de Brion Vibber para la normalización Unicode.",
        "config-unicode-using-intl": "Usando la [http://pecl.php.net/intl extensión intl PECL] para la normalización Unicode.",
        "config-unicode-pure-php-warning": "'''Advertencia''': La [http://pecl.php.net/intl extensión intl] no está disponible para efectuar la normalización Unicode. Utilizando la implementación más lenta en PHP.\nSi tu web tiene mucho tráfico, te recomendamos leer acerca de la [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations normalización Unicode].",
@@ -75,7 +78,8 @@
        "config-no-db": "¡No fue posible encontrar un controlador adecuado para la base de datos! Necesitas instalar un controlador de base de datos para PHP.\nLos siguientes sistemas gestores de bases de datos están soportados: $1.\n\nSi compilaste PHP tú mismo, debes reconfigurarlo habilitando un cliente de base de datos, por ejemplo, usando <code>./configure --with-mysqli</code>.\nSi instalaste PHP desde un paquete Debian o Ubuntu, entonces también necesitas instalar, por ejemplo, el paquete <code>php5-mysql</code>.",
        "config-outdated-sqlite": "''' Advertencia ''': tiene la versión SQLite $1, que es inferior a la mínima versión requerida: $2 . SQLite no estará disponible.",
        "config-no-fts3": "'''Advertencia''': SQLite está compilado sin el [//sqlite.org/fts3.html módulo FTS3]. Las funcionalidades de búsqueda no estarán disponibles en esta instalación.",
-       "config-register-globals": "'''Advertencia: La opción de <code>[http://php.net/register_globals register_globals]</code> de PHP está habilitada.'''\n'''Desactívela si puede.'''\nMediaWiki funcionará, pero tu servidor quedará expuesto a vulnerabilidades de seguridad potenciales.",
+       "config-register-globals-error": "<strong>Error: la opción de PHP <code>[http://php.net/register_globals register_globals]</code> está activada.\nDebe estar desactivada para continuar con la instalación.</strong>\nVea [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] para obtener ayuda sobre cómo hacerlo.",
+       "config-magic-quotes-gpc": "<strong>Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] está activa!</strong>\nEsta opción corrompe la entrada de datos de forma impredecible.\nUsted no puede instalar o utilizar MediaWiki a menos que esta opción esté deshabilitada.",
        "config-magic-quotes-runtime": "'''Fatal: ¡[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] está activada!'''\nEsta opción causa la imprevisible corrupción de la entrada de datos.\nNo puedes instalar o utilizar MediaWiki a menos que esta opción esté inhabilitada.",
        "config-magic-quotes-sybase": "'''Fatal: ¡[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] está activada!'''\nEsta opción causa la imprevisible corrupción de la entrada de datos.\nNo puedes instalar o utilizar MediaWiki a menos que esta opción esté inhabilitada.",
        "config-mbstring": "'''Fatal: La opción [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] está activada!'''\nEsta opción causa errores y puede corromper los datos de una forma imprevisible.\nNo se puede instalar o usar MediaWiki a menos que esta opción sea desactivada.",
@@ -86,6 +90,7 @@
        "config-memory-raised": "el parámetro <code>memory_limit</code> de PHP es $1, aumentada a $2.",
        "config-memory-bad": "'''Advertencia:''' El parámetro <code>memory_limit</code> de PHP es $1.\nProbablemente este valor es demasiado bajo.\n¡La instalación podrá fallar!",
        "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-xcache": "[http://xcache.lighttpd.net/ XCache] está instalado",
        "config-apc": "[http://www.php.net/apc APC] está instalado",
        "config-no-cache": "'''Advertencia:''' No pudo encontrarse [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache] o [http://www.iis.net/download/WinCacheForPhp WinCache].\nEl caché de objetos no está habilitado.",
        "config-mod-security": "''' Advertencia ''': Su servidor web tiene [http://modsecurity.org/ mod_security] habilitado. Si la configuración es incorrecta, puede causar problemas a MediaWiki u otro software que permita a los usuarios publicar contenido arbitrarios.\nConsulte la [http://modsecurity.org/documentation/ documentación de mod_security] o contacte con el soporte de su servidor (''host'') si encuentra errores aleatorios.",
        "config-diff3-bad": "GNU diff3 no se encuentra.",
-       "config-git": "Se encontró el ''software'' de control de versiones Git: <code>$1</code>.",
+       "config-git": "Se encontró el software de control de versiones Git: <code>$1</code>.",
        "config-git-bad": "No se encontró el software de control de versiones Git.",
        "config-imagemagick": "ImageMagick encontrado: <code>$1</code>.\nLa miniaturización de imágenes se habilitará si habilitas las cargas.",
        "config-gd": "Se ha encontrado una biblioteca de gráficos GD integrada.\nLa miniaturización de imágenes se habilitará si habilitas las subidas.",
        "config-no-scaling": "No se ha encontrado ninguma biblioteca GD o ImageMagik.\nSe inhabilitará la miniaturización de imágenes.",
-       "config-no-uri": "'''Error:''' No se pudo determinar el URI actual.\nSe interrumpió la instalación.",
+       "config-no-uri": "<strong>Error:</strong> no se pudo determinar el URI actual.\nSe interrumpió la instalación.",
        "config-no-cli-uri": "<strong>Aviso:</strong> No se especificó <code>--scriptpath</code>; se usa el valor predeterminado: <code>$1</code>.",
        "config-using-server": "Utilizando el nombre de servidor \"<nowiki>$1</nowiki>\".",
-       "config-using-uri": "Utilizando la dirección URL del servidor \"<nowiki>$1$2</nowiki>\".",
+       "config-using-uri": "Utilizando la URL del servidor \"<nowiki>$1$2</nowiki>\".",
        "config-uploads-not-safe": "'''Atención:''' Su directorio por defecto para las cargas, <code>$1</code>, es vulnerable a la ejecución de scripts arbitrarios.\nAunque MediaWiki comprueba todos los archivos cargados por si hubiese amenazas de seguridad, es altamente recomendable [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security cerrar esta vulnerabilidad de seguridad] antes de activar las cargas.",
        "config-no-cli-uploads-check": "'''Atención:''' Su directorio predeterminado para cargas (<code>$1</code>) no está comprobado para la vulnerabilidad\n de ejecución arbitraria de comandos script durante la instalación de CLI.",
        "config-brokenlibxml": "El sistema tiene una combinación de versiones de PHP y de libxml2 que es poco confiable y puede provocar corrupción oculta en los datos de MediaWiki y otras aplicaciones web.\nActualizar a PHP 5.2.9 o posterior y a libxml2 2.7.3 o posterior ([//bugs.php.net/bug.php?id=45996 bug reportado con PHP]).\nInstalación abortada.",
        "config-suhosin-max-value-length": "Suhosin está instalado y limita el parámetro <code>length</code> GET a $1 bytes.\nEl componente ResourceLoader (gestor de recursos) de MediaWiki trabajará en este límite, pero eso perjudicará el rendimiento.\nSi es posible, deberías establecer <code>suhosin.get.max_value_length</code> en el valor 1024 o superior en <code>php.ini</code> y establecer <code>$wgResourceLoaderMaxQueryLength</code> en el mismo valor en <code>php.ini</code>.",
-       "config-db-type": "Tipo de base de datos",
+       "config-db-type": "Tipo de base de datos:",
        "config-db-host": "Servidor de la base de datos:",
        "config-db-host-help": "Si su servidor de base de datos está en otro servidor, escriba el nombre del host o su dirección IP aquí.\nSi está utilizando alojamiento web compartido, su proveedor de alojamiento debería darle el nombre correcto del servidor de alojamiento (host) en su documentación.\nSi va a instalarlo en un servidor Windows y utiliza MySQL, el uso de \"localhost\" como nombre del servidor puede no funcionar. Si no es así, intente poner \"127.0.0.1\" como dirección IP local.\nSi utiliza PostgreSQL, deje este campo en blanco para conectarse a través de un socket de Unix.",
        "config-db-host-oracle": "TNS de la base de datos:",
        "config-db-host-oracle-help": "Introduzca un [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm nombre de conexión local] válido; un archivo tnsnames.ora debe ser visible para esta instalación.<br />Si está utilizando bibliotecas de cliente 10g o más recientes también puede utilizar el método de asignación de nombres [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm Easy Connect].",
-       "config-db-wiki-settings": "Identifique este wiki",
-       "config-db-name": "Nombre de base de datos:",
+       "config-db-wiki-settings": "Identifica este wiki",
+       "config-db-name": "Nombre de la base de datos:",
        "config-db-name-help": "Elija un nombre que identifique su wiki.\nNo debe contener espacios.\n\nSi está utilizando alojamiento web compartido, su proveedor de alojamiento le dará un nombre específico de base de datos para que lo utilice, o bien le permitirá crear bases de datos a través de un panel de control.",
-       "config-db-name-oracle": "Esquema de base de datos:",
+       "config-db-name-oracle": "Esquema de la base de datos:",
        "config-db-account-oracle-warn": "Hay tres escenarios compatibles para la instalación de Oracle como base de datos back-end:\n\nSi desea crear una cuenta de base de datos como parte del proceso de instalación, por favor suministre una cuenta con función SYSDBA como cuenta de base de datos para la instalación y especifique las credenciales deseadas de la cuenta de acceso al web, de lo contrario puede crear manualmente la cuenta de acceso al web y suministrar sólo esa cuenta (si tiene los permisos necesarios para crear los objetos de esquema) o suministrar dos cuentas diferentes, una con privilegios de creación y otra con acceso restringido a la web\n\nLa secuencia de comandos (script) para crear una cuenta con los privilegios necesarios puede encontrarse en el directorio \"maintenance/oracle/\" de esta instalación. Tenga en cuenta que utilizando una cuenta restringida desactivará todas las capacidades de mantenimiento con la cuenta predeterminada.",
        "config-db-install-account": "Cuenta de usuario para instalación",
-       "config-db-username": "Nombre de usuario de base de datos:",
-       "config-db-password": "contraseña de base de datos:",
+       "config-db-username": "Nombre de usuario de la base de datos:",
+       "config-db-password": "Contraseña de la base de datos:",
        "config-db-password-empty": "Introduzca una contraseña para el nuevo usuario de base de datos:  $1.\nAunque es posible crear usuarios sin contraseña, esto no es seguro.",
        "config-db-username-empty": "Debe introducir un valor para \"{{int:config-db-username}}\"",
        "config-db-install-username": "Introduzca el nombre de usuario que se utilizará para conectarse a la base de datos durante el proceso de instalación.\nEste no es el nombre de usuario de la cuenta de MediaWiki; Este es el nombre de usuario para la base de datos.",
        "config-db-install-password": "Introduzca la contraseña que se utilizará para conectarse a la base de datos durante el proceso de instalación.\nEsta no es la contraseña para la cuenta de MediaWiki; esta es la contraseña para la base de datos.",
        "config-db-install-help": "Ingresar el nombre de usuario y la contraseña que será usada para conectar a la base de datos durante el proceso de instalación.",
        "config-db-account-lock": "Usar el mismo nombre de usuario y contraseña durante operación normal",
-       "config-db-wiki-account": "Usar cuenta para operación normal",
+       "config-db-wiki-account": "Cuenta de usuario para operación normal",
        "config-db-wiki-help": "Introduce el nombre de usuario y la contraseña que serán usados para acceder a la base de datos durante la operación normal del wiki.\nSi esta cuenta no existe y la cuenta de instalación tiene suficientes privilegios, se creará esta cuenta de usuario con los privilegios mínimos necesarios para la operación normal del wiki.",
-       "config-db-prefix": "Prefijo de tablas de base de datos:",
+       "config-db-prefix": "Prefijo de tablas de la base de datos:",
        "config-db-prefix-help": "Si necesita compartir una base de datos entre múltiples wikis, o entre MediaWiki y otra aplicación web, puede optar por agregar un prefijo a todos los nombres de tabla para evitar conflictos.\nNo utilice espacios.\n\nNormalmente se deja este campo vacío.",
        "config-db-charset": "Conjunto de caracteres de la base de datos",
        "config-charset-mysql5-binary": "MySQL 4.1/5.0 binario",
        "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
        "config-charset-mysql4": "MySQL 4.0 retrocompatible UTF-8",
        "config-charset-help": "'''Atención:''' Si emplea '''backwards-compatible UTF-8''' en MySQL 4.1+ y posteriormente hace copia de seguridad de la base de datos con <code>mysqldump</code> , puede destruir todos los caracteres no-ASCII, ¡dañando irreversiblemente sus copias de seguridad!\n\nEn '''modo binario''', MediaWiki almacena texto UTF-8 en la base de datos en campos binarios.\nEsto es más eficiente que el modo UTF-8 de MySQL, y le permite utilizar la gama completa de caracteres Unicode.\nEn ''' modo UTF-8'' ', MySQL sabrá el juego de caracteres de sus datos y puede presentarlos y convertirlos apropiadamente,\npero no le permitirá almacenar caracteres por encima del [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes plano multilingüe básico].",
-       "config-mysql-old": "Se necesita MySQL $1 o una versión más reciente. Tienes la versión $2.",
+       "config-mysql-old": "Se necesita MySQL $1 o posterior. Tienes $2.",
        "config-db-port": "Puerto de la base de datos:",
        "config-db-schema": "Esquema para MediaWiki",
        "config-db-schema-help": "Estos esquemas usualmente estarán bien.\nAltéralos sólo si tienes la seguridad de que necesitas hacerlo.",
        "config-upgrade-done": "Actualización completa.\n\nUsted puede ahora [ $1  empezar a usar su wiki].\n\nSi desea regenerar su archivo <code>LocalSettings.php</code> de archivo, haga clic en el botón de abajo.\nEsto '''no se recomienda''' a menos que esté teniendo problemas con su wiki.",
        "config-upgrade-done-no-regenerate": "Actualización completa.\n\nUsted puede ahora [$1  empezar a usar su wiki].",
        "config-regenerate": "Regenerar LocalSettings.php →",
-       "config-show-table-status": "<code>SHOW TABLE STATUS</code> ha fallado!",
+       "config-show-table-status": "¡Falló la consulta <code>SHOW TABLE STATUS</code>!",
        "config-unknown-collation": "'''Advertencia:''' La base de datos está utilizando una intercalación no reconocida.",
-       "config-db-web-account": "Cuenta de base de datos para acceso Web",
+       "config-db-web-account": "Cuenta de la base de datos para acceso web",
        "config-db-web-help": "Elige el usuario y contraseña que el servidor Web usará para conectarse al servidor de la base de datos durante el fincionamiento normal del wiki.",
        "config-db-web-account-same": "Utilizar la misma cuenta que en la instalación",
        "config-db-web-create": "Crear la cuenta si no existe",
        "config-mysql-binary": "Binario",
        "config-mysql-utf8": "UTF-8",
        "config-mysql-charset-help": "En '''modo binario''', MediaWiki almacena texto UTF-8 para la base de datos en campos binarios.\nEsto es más eficiente que el modo UTF-8 de MySQL y le permite utilizar la gama completa de caracteres Unicode.\n\nEn '''modo UTF-8''', MySQL sabrá qué conjunto de caracteres emplean sus datos y puede presentarlos y convertirlos adecuadamente, pero no le permitirá almacenar caracteres por encima del [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes plano multilingüe básico].",
-       "config-mssql-auth": "Tipo de autentificación:",
+       "config-mssql-auth": "Tipo de autenticación:",
        "config-mssql-install-auth": "Seleccione el tipo de autenticación que se utilizará para conectarse a la base de datos durante el proceso de instalación.\nSi selecciona \"{{int:config-mssql-windowsauth}}\", las credenciales de cualquier usuario de el servidor web que se está ejecutando van a ser utilizadas.",
        "config-mssql-web-auth": "Seleccione 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 selecciona \"{{int:config-mssql-windowsauth}}\", las credenciales del usuario que sea cual sea el servidor Web se ejecuta como será utilizado.",
        "config-mssql-sqlauth": "Autenticación de SQL Server",
        "config-site-name-blank": "Ingresar un nombre de sitio.",
        "config-project-namespace": "Espacio de nombre de proyecto:",
        "config-ns-generic": "Proyecto",
-       "config-ns-site-name": "Igual como el nombre del wiki: $1",
+       "config-ns-site-name": "Igual al nombre del wiki: $1",
        "config-ns-other": "Otro (especificar)",
        "config-ns-other-default": "MiWiki",
        "config-project-namespace-help": "Siguiendo el ejemplo de  Wikipedia, muchos wikis mantienen sus páginas de políticas separadas de sus páginas de contenido, en un \"'''espacio de nombres del proyecto'''\".\n\nTodos los títulos de página en este espacio de nombres comienzan con un determinado prefijo, que usted puede especificar aquí.\nTradicionalmente, este prefijo se deriva del nombre del wiki, pero no puede contener caracteres de puntuación como \"#\" o \":\".",
        "config-admin-box": "Cuenta de administrador",
        "config-admin-name": "Tu nombre de usuario:",
        "config-admin-password": "Contraseña:",
-       "config-admin-password-confirm": "Repita la contraseña:",
+       "config-admin-password-confirm": "Repite la contraseña:",
        "config-admin-help": "Escribe aquí el nombre de usuario que desees, como por ejemplo \"Pedro Bloggs\".\nEste es el nombre que usarás para entrar al wiki.",
        "config-admin-name-blank": "Introduce un nombre de usuario de administrador.",
        "config-admin-name-invalid": "El nombre de usuario especificado \"<nowiki>$1</nowiki>\" no es válido.\nEspecifique un nombre de usuario diferente.",
        "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-license": "Copyright and licencia:",
+       "config-license": "Derechos de autor y licencia:",
        "config-license-none": "Pie sin licencia",
-       "config-license-cc-by-sa": "Creative Commons Reconocimiento Compartir Igual",
-       "config-license-cc-by": "Creative Commons Reconocimiento",
-       "config-license-cc-by-nc-sa": "Creative Commons Reconocimiento Compartir Igual no comercial",
+       "config-license-cc-by-sa": "Creative Commons Atribución-CompartirIgual",
+       "config-license-cc-by": "Creative Commons Atribución",
+       "config-license-cc-by-nc-sa": "Creative Commons Atribución-NoComercial-CompartirIgual",
        "config-license-cc-0": "Creative Commons Zero (dominio público)",
        "config-license-gfdl": "Licencia de documentación libre de GNU 1.3 o posterior",
-       "config-license-pd": "Dominio Público",
+       "config-license-pd": "Dominio público",
        "config-license-cc-choose": "Selecciona una licencia personalizada de Creative Commons",
-       "config-license-help": "Muchos wikis públicos ponen todas las contribuciones bajo una [http://freedomdefined.org/Definition licencia libre].\nEsto ayuda a crear un sentido de propiedad comunitaria y alienta la contribución a largo plazo.\nEsto no es generalmente necesario para un wiki privado o corporativo.\n\nSi desea poder utilizar texto de Wikipedia, y desea que Wikipedia pueda aceptar el texto copiado de tu wiki, debe elegir '''Creative Commons Reconocimiento Compartir Igual'''.\n\nWikipedia utilizaba anteriormente la licencia de documentación libre de GNU (GFDL).\nLa GFDL es una licencia válida, pero es difícil de entender.\nTambién es difícil reutilizar el contenido licenciado bajo la GFDL.",
+       "config-license-help": "Muchos wikis públicos ponen todas las contribuciones bajo una [http://freedomdefined.org/Definition licencia libre].\nEsto ayuda a crear un sentido de propiedad comunitaria y alienta la contribución a largo plazo.\nEsto no es generalmente necesario para un wiki privado o corporativo.\n\nSi deseas poder utilizar texto de Wikipedia, y deseas que Wikipedia pueda aceptar el texto copiado de tu wiki, debes elegir <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nWikipedia utilizaba anteriormente la licencia de documentación libre de GNU (GFDL).\nLa GFDL es una licencia válida, pero es difícil de entender.\nTambién es difícil reutilizar el contenido licenciado bajo la GFDL.",
        "config-email-settings": "Configuración de correo electrónico",
        "config-enable-email": "Activar el envío de correos electrónicos",
        "config-enable-email-help": "Si quieres que el correo electrónico funcione, la [http://www.php.net/manual/en/mail.configuration.php configuración PHP de correo electrónico] debe ser la correcta.\nSi no quieres la funcionalidad de correo electrónico, puedes desactivarla aquí.",
-       "config-email-user": "Habilitar correo electrónico de usuario a usuario",
+       "config-email-user": "Habilitar correo electrónico entre usuarios",
        "config-email-user-help": "Permitir que todos los usuarios intercambien correos electrónicos si lo han activado en sus preferencias.",
        "config-email-usertalk": "Activar notificaciones de páginas de discusión de usuarios",
        "config-email-usertalk-help": "Permitir a los usuarios recibir notificaciones de cambios en la página de discusión de usuario, si lo han activado en sus preferencias.",
        "config-memcache-badport": "Los números de puerto de Memcached deben estar entre  $1  y  $2.",
        "config-extensions": "Extensiones",
        "config-extensions-help": "Se ha detectado en tu directorio <code>./extensions</code>  las extensiones listadas arriba.\n\nPuede que necesiten configuraciones adicionales, pero puedes habilitarlas ahora.",
+       "config-skins": "Apariencias",
+       "config-skins-help": "Las apariencias mencionadas anteriormente fueron detectadas en tu directorio <code>./skins</code>. Debes habilitar al menos una y elegir la predeterminada.",
+       "config-skins-use-as-default": "Utilizar esta apariencia como predeterminada",
+       "config-skins-missing": "No se encontró ninguna apariencia; MediaWiki utilizará una apariencia anterior hasta que instales unas apariencias adecuadas.",
+       "config-skins-must-enable-some": "Debes seleccionar al menos una apariencia para activar.",
+       "config-skins-must-enable-default": "La apariencia elegida como predeterminada debe estar habilitada.",
        "config-install-alreadydone": "'''Aviso:''' Parece que ya habías instalado MediaWiki y estás intentando instalarlo nuevamente.\nPasa a la próxima página, por favor.",
        "config-install-begin": "Al pulsar en «{{int:config-continue}}» comenzará el proceso de instalación de MediaWiki.\nSi quieres realizar algún cambio, pulsa en «{{int:config-back}}».",
        "config-install-step-done": "hecho",
        "config-install-user": "Creando el usuario de la base de datos",
        "config-install-user-alreadyexists": "El usuario \"$1\" ya existe",
        "config-install-user-create-failed": "La creación del usuario \"$1\" falló:  $2",
-       "config-install-user-grant-failed": "La concesión de permisos para el usuario \"$1\" ha fallado: $2",
+       "config-install-user-grant-failed": "La concesión de permisos al usuario \"$1\" falló: $2",
        "config-install-user-missing": "El usuario especificado \"$1\" no existe.",
        "config-install-user-missing-create": "El usuario especificado \"$1\" no existe.\nPor favor, haga clic en la casilla \"Crear cuenta\" que aparece a continuación si desea crearlo.",
        "config-install-tables": "Creando tablas",
        "config-install-interwiki-list": "No se pudo encontrar el archivo <code>interwiki.list</code>.",
        "config-install-interwiki-exists": "'''Advertencia''': La tabla de interwikis parece ya contener entradas.\nSe omitirá la lista predeterminada.",
        "config-install-stats": "Iniciando las estadísticas",
-       "config-install-keys": "Generación de claves secretas",
+       "config-install-keys": "Generando claves secretas",
        "config-insecure-keys": "''' Atención:'' '  {{PLURAL:$2|Una clave de seguridad generada|Las claves de seguridad generadas}} ($1) durante la instalación no  {{PLURAL:$2|es totalmente segura|son totalmente seguras}}. Considere {{PLURAL:$2| cambiarla|cambiarlas}} manualmente.",
-       "config-install-sysop": "Creando cuenta de usuario del administrador",
+       "config-install-updates": "Evitar ejecutar actualizaciones innecesarias",
+       "config-install-updates-failed": "<strong>Error:</strong> falló la inserción de claves de actualización en las tablas con el siguiente error: $1",
+       "config-install-sysop": "Creando la cuenta de usuario del administrador",
        "config-install-subscribe-fail": "No se ha podido suscribir a mediawiki-announce: $1",
        "config-install-subscribe-notpossible": "cURL no está instalado y <code>allow_url_fopen</code> no está disponible.",
        "config-install-mainpage": "Creando página principal con contenido predeterminado",
        "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-download-localsettings": "Descargar archivo <code>LocalSettings.php</code>",
-       "config-help": "Ayuda",
-       "config-help-tooltip": "Haz clic para ampliar",
+       "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": "'''MediaWiki ha sido instalado con éxito.'''",
-       "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== Empezando ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lista de ajustes de configuración]\n* [//www.mediawiki.org/wiki/Manual:FAQ/es FAQ de MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de correo de anuncios de distribución de MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Regionalizar MediaWiki para tu idioma]"
+       "mainpagetext": "<strong>MediaWiki se ha instalado con éxito.<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]"
 }
index 13b61ed..8fae026 100644 (file)
@@ -2,7 +2,8 @@
        "@metadata": {
                "authors": [
                        "Avjoska",
-                       "Pikne"
+                       "Pikne",
+                       "Boxmein"
                ]
        },
        "config-information": "Teave",
@@ -26,6 +27,7 @@
        "config-page-upgradedoc": "Uuendamine",
        "config-page-existingwiki": "Olemasolev viki",
        "config-restart": "Jah, tee taaskäivitus",
+       "config-env-hhvm": "HHVM $1 on installitud.",
        "config-db-name": "Andmebaasi nimi:",
        "config-db-username": "Andmebaasi kasutajanimi:",
        "config-db-password": "Andmebaasi parool:",
index 23fe457..02ffd0d 100644 (file)
@@ -6,7 +6,8 @@
                        "Ebraminio",
                        "Omidh",
                        "Pouyana",
-                       "Reza1615"
+                       "Reza1615",
+                       "Alirezaaa"
                ]
        },
        "config-desc": "نصب کنندهٔ ویکی‌مدیا",
@@ -19,7 +20,7 @@
        "config-upgrade-key-missing": "نصب موجود مدیاویکی شناسایی شده‌است.\nبرای بروزرسانی این نصب، لطفاً خط زیر را در آخر کد \nقرار دادن به نصب ارتقاء داده شده، به خط زیر لطفاً در پایین خود را <code>LocalSettings.php</code> قرار دهید:\n\n$1",
        "config-localsettings-incomplete": "وجود <code>LocalSettings.php</code> به نظر ناقص می‌رسد.\nمتغیر $1 تنظیم نشده‌است.\nبرای اینکه این متغیر تنظیم شود لطفاً <code>LocalSettings.php</code> را تغییر دهید، و \"{{int:Config-continue}}\" را کلیک کنید.",
        "config-localsettings-connection-error": "هنگام اتصال به پایگاه اطلاعاتی که ازتنظیمات مشخص شده در<code>LocalSettings.php</code> استفاده می‌کند، خطایی رخ داد. لطفاً این تنظیمات را نصب کنید و دوباره تلاش کنید.\n$1",
-       "config-session-error": "خطا در شروع جلسه $1",
+       "config-session-error": "خطا در شروع جلسه: $1",
        "config-session-expired": "به نظر می‌رسد اطلاعات جلسهٔ شما منقضی شده‌است.\nجلسات برای مادام العمر $1 پیکربندی شده‌اند.\nشما می‌توانید این پیکربندی را با تنظیم <code>session.gc_maxlifetime</code> در php.ini افزایش دهید.\nروند نصب را دوباره شروع کنید.",
        "config-no-session": "اطلاعات دورهٔ شما از دست رفته‌ است!\nphp.ini خود را بررسی کنید و مطمئن شوید <code>session.save_path</code> برای یک فهرست مناسب تنظیم شده‌است.",
        "config-your-language": "زبان شما:",
        "config-page-language": "زبان",
        "config-page-welcome": "به مدیاویکی خوش آمدید!",
        "config-page-dbconnect": "اتصال به پایگاه داده",
-       "config-page-upgrade": "نصب موجود را ارتقاء دهید.",
-       "config-page-dbsettings": "تÙ\86ظÛ\8cÙ\85ات Ù¾Ø§Û\8cگاÙ\87 Ø§Ø·Ù\84اعاتÛ\8c",
+       "config-page-upgrade": "ارتقای نصب موجود",
+       "config-page-dbsettings": "تÙ\86ظÛ\8cÙ\85ات Ù¾Ø§Û\8cگاÙ\87 Ø¯Ø§Ø¯Ù\87",
        "config-page-name": "نام",
        "config-page-options": "گزینه‌ها",
        "config-page-install": "نصب",
        "config-page-complete": "کامل!",
-       "config-page-restart": "نصب را دوباره شروع کنید",
+       "config-page-restart": "راه‌اندازی دوباره نصب",
        "config-page-readme": "مرا بخوان",
        "config-page-releasenotes": "یادداشت‌های انتشار",
        "config-page-copying": "تکثیر",
-       "config-page-upgradedoc": "ارتقا",
+       "config-page-upgradedoc": "ارتقاء",
        "config-page-existingwiki": "ویکی موجود",
        "config-help-restart": "آیا می‌خواهید همهٔ اطلاعات ذخیره شده‌ای که وارد کرده‌اید را پاک کنید و دوباره روند نصب را شروع کنید؟",
-       "config-restart": "بله ، آن دوباره راه اندازی کن",
+       "config-restart": "بله، دوباره راه‌اندازی کن",
        "config-welcome": "===بررسی‌های محیطی===\nبرای فهمیدن اینکه این محیط برای نصب مدیاویکی مناسب است، اکنون بررسی‌های اساسی انجام خواهد‌شد.\nاگر به دنبال پشتیبانی در چگونگی تکمیل نصب هستید،به یاد داشته باشید این اطلاعات را بگنجانید.",
        "config-copyright": "===حق چاپ و شرایط===\n$1\nاین برنامه،نرم‌افزاری آزاد است;شما می‌توانید این برنامه را دوباره توزیع کنید و/یا تحت شرایط مجوز عمومی کلی جی‌ان‌یو که توسط بنیاد نرم‌افزار آزاد منتشر شده،اصلاح کنید;یا نسخهٔ 2 مجوز، یا (به انتخاب خود) هر نسخهٔ پس از این.\nاین برنامه به امید اینکه مفید واقع‌ شود توزیع شده‌است،اما '''بدون هیچ ضمانتی'''; حتی بدون اشارهٔ ضمانتی از '''قابلیت عرضه''' یا ''' صلاحیت برای یک هدف خاص'''.\nبرای جزئیات بیشتر مجوز عمومی کلی جی‌ان‌یو را مشاهده کنید.\nشما باید <doclink href=Copying> یک چاپ ازمجوز عمومی کلی </doclink> همراه این برنامه دریافت کنید; اگر دریافت نکردید،به بنیاد نرم‌افزار آزاد بنویسید،Inc.،خیابان فرانکلین۵۱،طبقه پنجم،بوستون، MA۰۲۱۱۰-۱۳۰،آمریکا،یا [http://www.gnu.org/copyleft/gpl.html read it online].",
        "config-sidebar": "* [//www.mediawiki.org صفحهٔ اصلی مدیاویکی]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents راهنمای کاربر]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents راهنمای مدیر]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ پرسش‌های رایج]\n----\n* <doclink href=Readme>مرا بخوان</doclink>\n* <doclink href=ReleaseNotes>یادداشت‌های انتشار</doclink>\n* <doclink href=Copying>نسخه برداری</doclink>\n* <doclink href=UpgradeDoc>ارتقا</doclink>",
        "config-env-good": "محیط بررسی شده‌است.\nشما می‌توانید مدیاویکی را نصب کنید.",
        "config-env-bad": "محیط بررسی شده‌است.\nشما نمی‌توانید مدیاویکی را نصب کنید.",
        "config-env-php": "پی‌اچ‌پی $1 نصب شده‌است.",
-       "config-env-php-toolow": "پی‌اچ‌پی $1 نصب شده است.\nدر هر صورت، مدیاویکی نیاز به پی‌اچ‌پی نسخهٔ $2 یا بالاتر دارد.",
+       "config-env-hhvm": "HHVM $1 نصب شده‌است.",
        "config-unicode-using-utf8": "برای یونیکد عادی از Brion Vibber's utf8_normalize.so استفاده کنید.",
        "config-unicode-using-intl": "برای یونیکد عادی از [http://pecl.php.net/intl intl PECL extension] استفاده کنید.",
        "config-unicode-pure-php-warning": "'''هشدار:''' [http://pecl.php.net/intl intl PECL extension] برای کنترل یونیکد عادی در دسترس نیست،اجرای کاملاً آهسته به تعویق می‌افتد.\nاگر شما یک سایت پر‌ ترافیک را اجرا می‌کنید، باید کمی [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode normalization] را بخوانید.",
@@ -59,7 +60,8 @@
        "config-no-db": "درایور پایگاه اطلاعاتی مناسب پیدا نشد! شما لازم دارید یک درایور پایگاه اطلاعاتی  برای پی‌اچ‌پی نصب کنید.انواع پایگاه اطلاعاتی زیر پشتیبانی شده‌اند:$1.\nاگر شما در گروه اشتراک‌گذاری هستید، از تهیه کنندهٔ گروه خود برای نصب یک درایور پایگاه اطلاعاتی مناسب سوأل کنید.\nاگر خود، پی‌اچ‌پی را تهیه کرده‌اید، با یک پردازشگر فعال دوباره پیکربندی کنید، برای مثال از <code>./configure --with-mysql</code> استفاده کنید.\nاگر پی‌اچ‌پی را از یک بستهٔ دبیان یا آبونتو نصب کرده‌اید، بنابراین لازم دارید بخش php5-mysql را نصب کنید.",
        "config-outdated-sqlite": "''' هشدار:''' شما اس‌کیولایت $1 دارید، که پایین‌تر از حداقل نسخهٔ $2 مورد نیاز است.اس‌کیولایت در دسترس نخواهد بود.",
        "config-no-fts3": "'''هشدار:''' اس‌کیولایت بدون [//sqlite.org/fts3.html FTS3 module] تهیه شده‌است ، جستجوی ویژگی‌ها در این بخش پیشین در دسترس نخواهد‌بود.",
-       "config-register-globals": "'''هشدار:''' گزینهٔ  PHP's <code>[http://php.net/register_globals register_globals]</code> فعال شده‌است.'''\n''' اگر می‌توانید غیر فعالش کنید.'''\nمدیاویکی کار خواهد‌کرد، اما سرور شما در معرض آسیب‌پذیری‌های امنیتی ممکن قرار دارد.",
+       "config-register-globals-error": "<strong>خطا:  پی‌اچ‌پی<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شما نمی‌توانید مدیاویکی را نصب یا استفاده کنید مگر اینکه این گزینه غیر‌فعال باشد.",
        "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شما نمی‌توانید مدیاویکی را نصب یا استفاده کنید مگر اینکه این گزینه غیر‌فعال باشد.",
@@ -70,6 +72,7 @@
        "config-memory-raised": "PHP's <code>memory_limit</code>, نسخهٔ $1 است، به نسخهٔ $2 ارتقاء داده شده‌است.",
        "config-memory-bad": "'''هشدار:''' PHP's <code>memory_limit</code> نسخهٔ $1 است.\nاین ممکن است خیلی پایین باشد.\nممکن است نصب با مشکل رو‌به‌رو شود.",
        "config-ctype": "'''مخرب:''' پی‌اچ‌پی باید با پشتیبانی برای [http://www.php.net/manual/en/ctype.installation.php Ctype extension] تهیه شده‌باشد.",
+       "config-iconv": "<strong>خطای اساسی:</strong> پی‌اچ‌پی باید کامپایل‌شده باشد برای پشتیبانی از [http://www.php.net/manual/en/iconv.installation.php افزونهٔ iconv].",
        "config-json": "'''مخرب:''' پی‌اچ‌پی بدون پشتیبانی جِی‌اس‌اُ‌ان تهیه شده‌بود.\nشما باید قبل از نصب مدیاویکی یا بسط  جِی‌اس‌اُ‌ان پی‌اچ‌پی یا بسط [http://pecl.php.net/package/jsonc PECL jsonc] را نصب کنید.\n* بسط پی‌اچ‌پی شامل لینوکس اینترپرایز رد هت (سِنت‌اُاِس) 5 یا 6 است، هرچند باید در <code>/etc/php.ini</code> یا <code>/etc/php.d/json.ini</code> فعال باشد.\n*  به‌جای بسته‌بندی کردن بسط پی‌ایی‌سی‌اِل مانند <code>php5-json</code> یا <code>php-pecl-jsonc</code>، توزیع‌های برخی لینوکس پس از ماه می ۲۰۱۳ با حذف بسط پی‌اچ‌پی افزایش پیدا کرد.",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] نصب شده‌است.",
        "config-apc": "[http://www.php.net/apc APC] نصب شده‌است.",
@@ -77,8 +80,8 @@
        "config-no-cache": "'''هشدار:''' [http://www.php.net/apc APC],[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 documentation] مراجعه کنید یا اگر با خطاهای اتفاقی مواجه شدید با پشتیبانی میزبان خود در تماس باشید.",
        "config-diff3-bad": "جی‌ان‌یو دیف۳ پیدا نشد.",
-       "config-git": "نسخهٔ کنترل نرم‌افزار جیت پیدا شد:<code>$1</code>.",
-       "config-git-bad": "نسخه نرم‌افزار کنترل جیت پیدا نشد.",
+       "config-git": "کنترل نسخهٔ نرم‌افزار گیت پیدا شد: <code>$1</code>.",
+       "config-git-bad": "کنترل نسخهٔ نرم‌افزار گیت پیدا نشد.",
        "config-imagemagick": "ایمیج‌مجیک پیدا شد: <code>$1</code>.\nاگر ارسال‌ها را فعال کنید،تصویر کوچک فعال خواهد‌شد.",
        "config-gd": "گرافیک‌های جی‌دی ساخته‌‌ شده در کتابخانه پیدا شد.\nاگر ارسال‌ها را فعال کنید تصویر کوچک فعال خواهد‌شد.",
        "config-no-scaling": "کتابخانهٔ جی‌دی یا ایمیج‌مجیک نتوانست پیدا شود.\nتصویر کوچک غیر‌فعال خواهد‌شد.",
        "config-db-install-account": "حساب کاربری برای نصب",
        "config-db-username": "نام کاربری پایگاه اطلاعات:",
        "config-db-password": "گذرواژه پایگاه داده‌ها:",
-       "config-db-password-empty": "Ù\84Ø·Ù\81اÙ\8b Û\8cÚ© Ø±Ù\85ز Ø¹Ø¨Ù\88ر Ø¨Ø±Ø§Û\8c Ú©Ø§Ø±Ø¨Ø± Ø¬Ø¯Û\8cد پایگاه اطلا‌عاتی وارد کنید: $1\nدر صورتی که ممکن است کاربران بدون رمز عبور به وجود آیند،امن نیست.",
+       "config-db-password-empty": "Ù\84Ø·Ù\81اÙ\8b Û\8cÚ© Ø±Ù\85ز Ø¹Ø¨Ù\88ر Ø¨Ø±Ø§Û\8c Ú©Ø§Ø±Ø¨Ø± ØªØ§Ø²Ù\87 پایگاه اطلا‌عاتی وارد کنید: $1\nدر صورتی که ممکن است کاربران بدون رمز عبور به وجود آیند،امن نیست.",
        "config-db-username-empty": "شما باید یک مقدار برای \"نام کاربری {{int:config-db-username}}\" وارد کنید",
        "config-db-install-username": "نام کاربری را وارد کنید که برای اتصال به پایگاه اطلاعاتی در طول روند نصب استفاده خواهد‌شد.\nاین نام کاربری حساب مدیاویکی نیست; نام کاربری برای پایگاه اطلاعاتی شما است.",
        "config-db-install-password": "رمز عبوری را وارد کنید که برای اتصال به پایگاه اطلاعاتی در طول روند نصب استفاده خواهد‌شد.\nاین رمز عبور برای حساب مدیاویکی نیست;رمز عبور برای پایگاه اطلاعاتی شما است.",
        "config-license-cc-by-nc-sa": "اشتراک گذاری یکجور استناد رایج سازندهٔ غیر تجاری",
        "config-license-cc-0": "مبداء عوام سازنده (حیطهٔ عمومی)",
        "config-license-gfdl": "مجوز اسنادومدارک آزاد جی‌ان‌یو ۱.۳ یا بالاتر",
-       "config-license-pd": "دامنه عمومی",
+       "config-license-pd": "مالکیت عمومی",
        "config-license-cc-choose": "انتخاب یک مجوز سفارشی عوام خلاق",
-       "config-license-help": "بسیاری از وبگاه‌ها ویرایش‌های ها را با  [http://freedomdefined.org/Definition اجازه‌نامهٔ آزاد] منتشر می‌کنند.\nاین کار به داشتن حس مالکیت جمعی کمک می‌کند و ویرایش‌های طولانی مدت را اشاعه می‌دهد.\nاین برای ویکی‌های خصوصی یا سازمانی الزامی نیست.\n\nاگر شما می‌خواهید از متون ویکی‌پدیا استفاده کنید، یا اینکه به ویکی‌پدیا اجازه دهید از متون شما استفاده کند باید متون خود را با '''Creative Commons Attribution Share Alike''' منتشر کنید.\n\nویکی‌پدیا در گذشته از اجازه‌نامهٔ داده‌های آزاد گنو استفاده می‌کرد.\nاین اجازه‌نامه مورد قبول است، ولی فهم آن آسان نیست.\nهمچنین استفادهٔ دوباره از متون تحت اجازه‌نامهٔ داده‌های آزاد گنو به سختی انجام می‌گیرد.",
+       "config-license-help": "بسیاری از وبگاه‌ها ویرایش‌های ها را با  [http://freedomdefined.org/Definition اجازه‌نامهٔ آزاد] منتشر می‌کنند.\nاین کار به داشتن حس مالکیت جمعی کمک می‌کند و ویرایش‌های طولانی مدت را اشاعه می‌دهد.\nاین برای ویکی‌های خصوصی یا سازمانی الزامی نیست.\n\nاگر شما می‌خواهید از متون ویکی‌پدیا استفاده کنید، یا اینکه به ویکی‌پدیا اجازه دهید از متون شما استفاده کند باید متون خود را با <strong>{{int:config-license-cc-by-sa}}</strong> منتشر کنید.\n\nویکی‌پدیا در گذشته از اجازه‌نامهٔ داده‌های آزاد گنو استفاده می‌کرد.\nاین اجازه‌نامه مورد قبول است، ولی فهم آن آسان نیست.\nهمچنین استفادهٔ دوباره از متون تحت اجازه‌نامهٔ داده‌های آزاد گنو به سختی انجام می‌گیرد.",
        "config-email-settings": "تنظیمات رایانامه",
        "config-enable-email": "فعال‌سازی رایانامهٔ خروجی",
        "config-enable-email-help": "اگر برای کار کردن رایانامه می‌خواهید [http://www.php.net/manual/en/mail.configuration.php PHP's mail settings] نیازمند پیکربندی صحیح است.\nاگر هیچ ویژگی رایانامه را نمی‌خواهید، می‌توانید آنها را اینجا غیر‌فعال کنید.",
        "config-memcache-badport": "اعداد درگاه ممکچد باید بین $1 و $2 باشد.",
        "config-extensions": "افزونه‌ها",
        "config-extensions-help": "لیست وسیع بالا در فهرست <code>./extensions</code> شما یافت شد.\nممکن است نیازمند پیکربندی اضافه باشند، اما اکنون می‌توانید آنها را فعال کنید.",
+       "config-skins": "پوسته‌ها",
+       "config-skins-help": "پوسته های ذکر شده در بالا در <code>./skins</code> پوشهٔ شما شناسایی شده است. شما باید حداقل یکی را فعال و پیش فرض کنید.",
+       "config-skins-use-as-default": "این پوست را به عنوان پیش فرض استفاده کنید",
+       "config-skins-missing": "هیچ پوسته‌ای انتخاب نشده‌است‌‌، تا زمانی که یک پوستهٔ مناسب نصب کنید مدیاویکی از پوسته ذخیره‌شده استفاده می‌کند",
+       "config-skins-must-enable-some": "شما باید حداقل یک پوست برای فعال کردن انتخاب کنید.",
+       "config-skins-must-enable-default": "پوست انتخاب شده به عنوان پیش فرض باید فعال شده باشد.",
        "config-install-alreadydone": "'''هشدار:''' به نظر می‌رسد در حال حاضر شما مدیاویکی را نصب کرده‌اید و دوباره سعی میکنید آن را نصب کنید.\nلطفاً به صفحهٔ بعدی بروید.",
        "config-install-begin": "با فشاردادن \"{{int:config-continue}}\"، نصب مدیاویکی را آغاز خواهید‌کرد.\nاگر هنوز می‌خواهید تغییرات ایجاد کنید، \"{{int:config-back}}\" را فشار دهید.",
        "config-install-step-done": "انجام شد",
        "config-install-stats": "شروع آمار",
        "config-install-keys": "تولید کلیدهای مخفی",
        "config-insecure-keys": "'''هشدار:''' {{PLURAL:$2|کلید امن|کلیدهای امن}} ($1) در طی نصب  کاملاً ایمن {{PLURAL:$2|نیست|نیستند}}. تغییر دستی {{PLURAL:$2|آن|آنها}} را در نظر بگیرید.",
+       "config-install-updates": "جلوگیری از به روز رسانی‌های غیر ضروری در حال اجرا",
+       "config-install-updates-failed": "<strong>خطا:</strong> قراردادن کلیدهای به روز رسانی به داخل جداول با خطای روبرو مواجه شد: $1",
        "config-install-sysop": "ایجاد حساب کاربری مدیر",
        "config-install-subscribe-fail": "قادر تصدیق اعلام مدیاویکی نیست:$1",
        "config-install-subscribe-notpossible": "سی‌یوآر‌ال نصب نشده‌است و <code>allow_url_fopen</code> در دسترس نیست.",
index 3aa0e84..0835f41 100644 (file)
@@ -56,7 +56,6 @@
        "config-env-good": "Asennusympäristö on tarkastettu.\nVoit asentaa MediaWikin.",
        "config-env-bad": "Asennusympäristö on tarkastettu.\nEt voi asentaa MediaWikiä.",
        "config-env-php": "PHP $1 on asennettu.",
-       "config-env-php-toolow": "PHP $1 on asennettu.\nMediaWiki vaatii PHP:n version $2 tai uudemman.",
        "config-no-db": "Sopivaa tietokanta-ajuria ei löytynyt! Sinun täytyy asentaa tietokanta-ajurit PHP:lle.\nSeuraavat tietokantatyypit ovat tuettuja: $1.",
        "config-outdated-sqlite": "<strong>Varoitus:</strong> sinulla on käytössä SQLite $1, joke on vanhempi kuin vähintään vaadittava versio $2. SQLite ei ole saatavilla.",
        "config-safe-mode": "'''Varoitus:''' PHP:n [http://www.php.net/features.safe-mode safe mode] -tila on aktiivinen.\nSe voi aiheuttaa ongelmia erityisesti tiedostojen tallentamisen ja matemaattisten kaavojen kanssa.",
        "config-cc-again": "Valitse uudelleen...",
        "config-extensions": "Laajennukset",
        "config-extensions-help": "Yllä luetellut laajennukset löytyvät <code>./extensions</code> hakemistosta.\n\nNe saattavat vaatia lisäasetuksia, mutta voit ottaa ne käyttöön nyt.",
+       "config-skins": "Ulkoasut",
+       "config-skins-must-enable-some": "Sinut täytyy valita ainakin yksi ulkoasu.",
        "config-install-alreadydone": "<strong>Varoitus:</strong> MediaWiki on jo asennettu ja yrität asentaa sitä uudestaan.\nSiirry seuraavalle sivulle.",
        "config-install-begin": "Painamalla \"{{int:config-continue}}\", aloitetaan MediaWikin asentaminen. \nJos haluat vielä tehdä muutoksia, paina \"{{int:config-back}}\".",
        "config-install-step-done": "valmis",
index d9ef1ef..9fd6726 100644 (file)
@@ -66,7 +66,7 @@
        "config-env-good": "L’environnement a été vérifié.\nVous pouvez installer MediaWiki.",
        "config-env-bad": "L’environnement a été vérifié.\nVous ne pouvez pas installer MediaWiki.",
        "config-env-php": "PHP $1 est installé.",
-       "config-env-php-toolow": "PHP $1 est installé.\nCependant, MediaWiki requiert PHP $2 ou supérieur.",
+       "config-env-hhvm": "HHVM $1 est installé.",
        "config-unicode-using-utf8": "Utilisation de utf8_normalize.so par Brion Vibber pour la normalisation Unicode.",
        "config-unicode-using-intl": "Utilisation de [http://pecl.php.net/intl l'extension PECL intl] pour la normalisation Unicode.",
        "config-unicode-pure-php-warning": "<strong>Attention</strong> : L'[http://pecl.php.net/intl extension PECL intl] n'est pas disponible pour la normalisation d’Unicode, retour à la version lente implémentée en PHP.\nSi votre site web sera très fréquenté, vous devriez lire ceci : [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations ''Unicode normalization''] (en anglais).",
@@ -74,7 +74,8 @@
        "config-no-db": "Impossible de trouver un pilote de base de données approprié ! Vous devez installer un pilote de base de données pour PHP. Les types de bases de données suivants sont reconnus : $1.\n\nSi vous avez compilé PHP vous-même, reconfigurez-le avec un client de base de données activé, par exemple en utilisant <code>./configure --with-mysqli</code>. Si vous avez installé PHP depuis un paquet Debian ou Ubuntu, alors vous devrez aussi installer, par exemple, le paquet <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Attention''': vous avez SQLite $1, qui est inférieur à la version minimale requise $2. SQLite sera indisponible.",
        "config-no-fts3": "'''Attention :''' SQLite est compilé sans le module [//sqlite.org/fts3.html FTS3] ; les fonctions de recherche ne seront pas disponibles sur ce moteur.",
-       "config-register-globals": "'''Attention : l'option <code>[http://php.net/register_globals register_globals]</code> de PHP est activée.'''\n'''Désactivez-la si vous le pouvez.'''\nMediaWiki fonctionnera, mais votre serveur sera exposé à de potentielles failles de sécurité.",
+       "config-register-globals-error": "<strong>Erreur : L’option <code>[http://php.net/register_globals register_globals]</code> de PHP est activée.\nElle doit être désactivée pour poursuivre l’installation.</strong>\nVoyez [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] pour avoir de l’aide sur la manière de faire cela.",
+       "config-magic-quotes-gpc": "<strong>Ereur critique : [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] est actif !</strong>\nCette option corrompt les entrées de donnée de façon imprévisible.\nVous ne pouvez pas installer ou utiliser MédiaWiki tant que cette option n’est pas désactivée.",
        "config-magic-quotes-runtime": "'''Erreur fatale : [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] est activé !'''\nCette option corrompt les données de manière imprévisible.\nVous ne pouvez pas installer ou utiliser MediaWiki tant que cette option est activée.",
        "config-magic-quotes-sybase": "'''Erreur fatale : [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybasee] est activé !'''\nCette option corrompt les données de manière imprévisible.\nVous ne pouvez pas installer ou utiliser MediaWiki tant que cette option est activée.",
        "config-mbstring": "'''Erreur fatale : [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] est activé !'''\nCette option provoque des erreurs et peut corrompre les données de manière imprévisible.\nVous ne pouvez pas installer ou utiliser MediaWiki tant que cette option est activée.",
@@ -85,6 +86,7 @@
        "config-memory-raised": "Le paramètre <code>memory_limit</code> de PHP était à $1, porté à $2.",
        "config-memory-bad": "'''Attention :''' Le paramètre <code>memory_limit</code> de PHP est à $1.\nCette valeur est probablement trop faible.\nIl est possible que l’installation échoue !",
        "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-xcache": "[http://xcache.lighttpd.net/ XCache] est installé",
        "config-apc": "[http://www.php.net/apc APC] est installé",
        "config-license-gfdl": "GNU Free Documentation License 1.3 ou ultérieure",
        "config-license-pd": "Domaine public",
        "config-license-cc-choose": "Sélectionner une licence Creative Commons personnalisée",
-       "config-license-help": "Beaucoup de wikis publics mettent l'ensemble des contributions sous [http://freedomdefined.org/Definition/Fr licence libre].\nCela contribue à créer un sentiment d'appartenance dans leur communauté et encourage les contributions sur le long terme.\nCe n'est généralement pas nécessaire pour un wiki privé ou d'entreprise.\n\nSi vous souhaitez utiliser des textes de Wikipédia, et souhaitez que Wikipédia réutilise des textes de votre wiki, vous devriez choisir la licence ''Creative Commons Attribution Share Alike''].\n\nWikipédia utilisait auparavent la ''GNU Free Documentation License'' (GFDL).\nC'est une licence valide, mais elle est difficile à comprendre. \nDe plus, elle possède des caractéristiques qui rendent difficile la réutilisation.sour GFDL des contenus.",
+       "config-license-help": "Beaucoup de wikis publics mettent l’ensemble des contributions sous une [http://freedomdefined.org/Definition/Fr licence libre].\nCela contribue à créer un sentiment d’appartenance à une communauté et encourage les contributions sur le long terme.\nCe n’est généralement pas nécessaire pour un wiki privé ou d’entreprise.\n\nSi vous souhaitez utiliser des textes de Wikipédia, et souhaitez que Wikipédia puisse réutiliser des textes copiés depuis votre wiki, vous devriez choisir <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nWikipédia utilisait auparavant la Licence de Documentation Libre GNU (GFDL).\nC’est une licence valide, mais difficile à comprendre. \nIl est aussi difficile de réutiliser du contenu sous la licence GFDL.",
        "config-email-settings": "Paramètres de courriel",
        "config-enable-email": "Activer les courriels sortants",
        "config-enable-email-help": "Si vous souhaitez utiliser le courriel, vous devez [http://www.php.net/manual/en/mail.configuration.php configurer des paramètres PHP] (texte en anglais).\nSi vous ne voulez pas du service de courriel, vous pouvez le désactiver ici.",
        "config-memcache-badport": "Les numéros de port de Memcached sont situés entre $1 et $2.",
        "config-extensions": "Extensions",
        "config-extensions-help": "Les extensions énumérées ci-dessus ont été détectées dans votre répertoire <code>./extensions</code>.\n\nElles peuvent nécessiter une configuration supplémentaire, mais vous pouvez les activer maintenant",
+       "config-skins": "Habillages",
+       "config-skins-help": "Les habillages listés ci-dessous ont été détectés dans votre répertoire <code>./skins</code>. Vous devez en activer au moins un, et choisir celui par défaut.",
+       "config-skins-use-as-default": "Utiliser cet habillage par défaut",
+       "config-skins-missing": "Aucun habillage trouvé ; MédiaWiki utilisera un habillage de secours jusqu’à ce que vous en installiez un approprié.",
+       "config-skins-must-enable-some": "Vous devez choisir au moins un habillage à activer.",
+       "config-skins-must-enable-default": "L’habillage choisi par défaut doit être activé.",
        "config-install-alreadydone": "'''Attention''': Vous semblez avoir déjà installé MediaWiki et tentez de l'installer à nouveau.\nS'il vous plaît, allez à la page suivante.",
        "config-install-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-stats": "Initialisation des statistiques",
        "config-install-keys": "Génération de la clé secrète",
        "config-insecure-keys": "'''Avertissement''' : {{PLURAL:$2|Une clé de sécurité générée ($1) pendant l'installation n'est pas complètement sécuritaire. Envisagez de la modifier manuellement.|Des clés de sécurité générées ($1) pendant l'installation ne sont pas complètement sécuritaires. Envisagez de les modifier manuellement.}}",
+       "config-install-updates": "Empêcher l’exécution des mises à jour inutiles",
+       "config-install-updates-failed": "<strong>Erreur :</strong> L’insertion de clés modifiées dans les tables a échoué avec l’erreur suivante : $1",
        "config-install-sysop": "Création du compte administrateur",
        "config-install-subscribe-fail": "Impossible de s'abonner à mediawiki-announce : $1",
        "config-install-subscribe-notpossible": "cURL n’est pas installé et <code>allow_url_fopen</code> n’est pas disponible.",
index 6d5861b..a42cb17 100644 (file)
        "config-help-restart": "Quere eliminar todos os datos gardados e reiniciar o proceso de instalación?",
        "config-restart": "Si, reiniciala",
        "config-welcome": "=== Comprobación da contorna ===\nCómpre realizar agora unhas comprobacións básicas para ver se a contorna é axeitada para a instalación de MediaWiki.\nLembre incluír esta información se necesita axuda para completar a instalación.",
-       "config-copyright": "=== Dereitos de autor e termos de uso ===\n\n$1\n\nEste programa é software libre; pode redistribuílo e/ou modificalo segundo os termos da licenza pública xeral GNU publicada pola Free Software Foundation; versión 2 ou (na súa escolla) calquera outra posterior.\n\nEste programa distribúese coa esperanza de que poida ser útil, pero '''sen garantía ningunha'''; nin sequera a garantía implícita de '''comercialización''' ou '''adecuación a unha finalidade específica'''.\nOlle a licenza pública xeral GNU para obter máis detalles.\n\nDebería recibir <doclink href=Copying>unha copia da licenza pública xeral GNU</doclink> xunto ao programa; se non é así, escriba á Free Software Foundation, Inc., rúa Franklin, número 51, quinto andar, Boston, Massachusetts, 02110-1301, Estados Unidos de América ou [http://www.gnu.org/copyleft/gpl.html lea a licenza en liña].",
+       "config-copyright": "=== Dereitos de autor e termos de uso ===\n\n$1\n\nEste programa é software libre; pode redistribuílo e/ou modificalo segundo os termos da licenza pública xeral GNU publicada pola Free Software Foundation; versión 2 ou (na súa escolla) calquera outra posterior.\n\nEste programa distribúese coa esperanza de que poida ser útil, pero <strong>sen garantía ningunha</strong>; nin sequera a garantía implícita de <strong>comercialización</strong> ou <strong>adecuación a unha finalidade específica</strong>.\nOlle a licenza pública xeral GNU para obter máis detalles.\n\nDebería recibir <doclink href=Copying>unha copia da licenza pública xeral GNU</doclink> xunto ao programa; se non é así, escriba á Free Software Foundation, Inc., rúa Franklin, número 51, quinto andar, Boston, Massachusetts, 02110-1301, Estados Unidos de América ou [http://www.gnu.org/copyleft/gpl.html lea a licenza en liña].",
        "config-sidebar": "* [//www.mediawiki.org/wiki/MediaWiki/gl Páxina principal de MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Guía de usuario]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents Guía de administrador]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Preguntas máis frecuentes]\n----\n* <doclink href=Readme>Léame</doclink>\n* <doclink href=ReleaseNotes>Notas de lanzamento</doclink>\n* <doclink href=Copying>Copia</doclink>\n* <doclink href=UpgradeDoc>Actualizacións</doclink>",
        "config-env-good": "Rematou a comprobación da contorna.\nPode instalar MediaWiki.",
        "config-env-bad": "Rematou a comprobación da contorna.\nNon pode instalar MediaWiki.",
        "config-env-php": "Está instalado o PHP $1.",
-       "config-env-php-toolow": "Está instalado o PHP $1.\nPorén, MediaWiki necesita o PHP $2 ou superior.",
+       "config-env-hhvm": "Está instalado o HHVM $1.",
        "config-unicode-using-utf8": "Usando utf8_normalize.so de Brion Vibber para a normalización Unicode.",
        "config-unicode-using-intl": "Usando a [http://pecl.php.net/intl extensión intl PECL] para a normalización Unicode.",
-       "config-unicode-pure-php-warning": "'''Atención:''' A [http://pecl.php.net/intl extensión intl PECL] non está dispoñible para manexar a normalización Unicode; volvendo á implementación lenta de PHP puro.\nSe o seu sitio posúe un alto tráfico de visitantes, debería ler un chisco sobre a [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations normalización Unicode].",
-       "config-unicode-update-warning": "'''Atención:''' A versión instalada da envoltura de normalización Unicode emprega unha versión vella da biblioteca [http://site.icu-project.org/ do proxecto ICU].\nDebería [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations actualizar] se o uso de Unicode é importante para vostede.",
+       "config-unicode-pure-php-warning": "<strong>Atención:</strong> A [http://pecl.php.net/intl extensión intl PECL] non está dispoñible para manexar a normalización Unicode; volvendo á implementación lenta de PHP puro.\nSe o seu sitio posúe un alto tráfico de visitantes, debería ler un chisco sobre a [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations normalización Unicode].",
+       "config-unicode-update-warning": "<strong>Atención:</strong> A versión instalada da envoltura de normalización Unicode emprega unha versión vella da biblioteca [http://site.icu-project.org/ do proxecto ICU].\nDebería [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations actualizar] se o uso de Unicode é importante para vostede.",
        "config-no-db": "Non se puido atopar un controlador axeitado para a base de datos! Necesita instalar un controlador de base de datos para PHP.\nOs tipos de base de datos admitidos son os seguintes: $1.\n\nSe compilou o PHP vostede mesmo, reconfigúreo activando un cliente de base de datos, por exemplo, usando <code>./configure --with-mysql</code>.\nSe instalou o PHP desde un paquete Debian ou Ubuntu, entón tamén necesita instalar, por exemplo, o módulo <code>php5-mysql</code>.",
-       "config-outdated-sqlite": "'''Atención:''' Ten o SQLite $1, que é inferior á versión mínima necesaria: $2. O SQLite non estará dispoñible.",
-       "config-no-fts3": "'''Atención:''' O SQLite está compilado sen o [//sqlite.org/fts3.html módulo FTS3]; as características de procura non estarán dispoñibles nesta instalación.",
-       "config-register-globals": "'''Atención: A opción PHP <code>[http://php.net/register_globals register_globals]</code> está activada.'''\n'''Desactívea se pode.'''\nMediaWiki funcionará, pero o seu servidor está exposto a potenciais vulnerabilidades de seguridade.",
-       "config-magic-quotes-runtime": "'''Erro fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] está activado!'''\nEsta opción corrompe os datos de entrada de xeito imprevisible.\nNon pode instalar ou empregar MediaWiki a menos que esta opción estea desactivada.",
-       "config-magic-quotes-sybase": "'''Erro fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] está activado!'''\nEsta opción corrompe os datos de entrada de xeito imprevisible.\nNon pode instalar ou empregar MediaWiki a menos que esta opción estea desactivada.",
-       "config-mbstring": "'''Erro fatal: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] está activado!'''\nEsta opción causa erros e pode corromper os datos de xeito imprevisible.\nNon pode instalar ou empregar MediaWiki a menos que esta opción estea desactivada.",
-       "config-safe-mode": "'''Atención:''' O [http://www.php.net/features.safe-mode safe mode] do PHP está activado.\nIsto pode causar problemas, particularmente se emprega cargas de ficheiros e soporte de <code>math</code>.",
+       "config-outdated-sqlite": "<strong>Atención:</strong> Ten o SQLite $1, que é inferior á versión mínima necesaria: $2. O SQLite non estará dispoñible.",
+       "config-no-fts3": "<strong>Atención:</strong> O SQLite está compilado sen o [//sqlite.org/fts3.html módulo FTS3]; as características de procura non estarán dispoñibles nesta instalación.",
+       "config-register-globals-error": "<strong>Erro: A opción <code>[http://php.net/register_globals register_globals]</code> do PHP está activada.\nCómpre desactivala para continuar a instalación.</strong>\nConsulte o enderezo [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] para obter axuda sobre como facelo.",
+       "config-magic-quotes-gpc": "<strong>Erro fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] está activado!</strong>\nEsta opción corrompe os datos de entrada de xeito imprevisible.\nNon pode instalar ou empregar MediaWiki a menos que esta opción estea desactivada.",
+       "config-magic-quotes-runtime": "<strong>Erro fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] está activado!</strong>\nEsta opción corrompe os datos de entrada de xeito imprevisible.\nNon pode instalar ou empregar MediaWiki a menos que esta opción estea desactivada.",
+       "config-magic-quotes-sybase": "<strong>Erro fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] está activado!</strong>\nEsta opción corrompe os datos de entrada de xeito imprevisible.\nNon pode instalar ou empregar MediaWiki a menos que esta opción estea desactivada.",
+       "config-mbstring": "<strong>Erro fatal: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] está activado!</strong>\nEsta opción causa erros e pode corromper os datos de xeito imprevisible.\nNon pode instalar ou empregar MediaWiki a menos que esta opción estea desactivada.",
+       "config-safe-mode": "<strong>Atención:</strong> O [http://www.php.net/features.safe-mode safe mode] do PHP está activado.\nIsto pode causar problemas, particularmente se emprega cargas de ficheiros e soporte de <code>math</code>.",
        "config-xml-bad": "Falta o módulo XML do PHP.\nMediaWiki necesita funcións neste módulo e non funcionará con esta configuración.\nSe está executando o Mandrake, instale o paquete php-xml.",
        "config-pcre-old": "<strong>Erro fatal:</strong> Necesítase PCRE $1 ou posterior.\nO seu PHP binario está ligado con PCRE $2.\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE Máis información].",
-       "config-pcre-no-utf8": "'''Erro fatal:''' Semella que o módulo PCRE do PHP foi compilado sen o soporte PCRE_UTF8.\nMediaWiki necesita soporte UTF-8 para funcionar correctamente.",
+       "config-pcre-no-utf8": "<strong>Erro fatal:</strong> Semella que o módulo PCRE do PHP foi compilado sen o soporte PCRE_UTF8.\nMediaWiki necesita soporte UTF-8 para funcionar correctamente.",
        "config-memory-raised": "O parámetro <code>memory_limit</code> do PHP é $1. Aumentado a $2.",
-       "config-memory-bad": "'''Atención:''' O parámetro <code>memory_limit</code> do PHP é $1.\nProbablemente é un valor baixo de máis.\nA instalación pode fallar!",
-       "config-ctype": "'''Erro fatal:''' O PHP debe compilarse co soporte para a [http://www.php.net/manual/en/ctype.installation.php extensión Ctype].",
-       "config-json": "'''Erro fatal:''' 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-memory-bad": "<strong>Atención:<strong> O parámetro <code>memory_limit</code> do PHP é $1.\nProbablemente é un valor baixo de máis.\nA instalación pode fallar!",
+       "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-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": "'''Atención:''' Non se puido atopar [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache] ou [http://www.iis.net/download/WinCacheForPhp WinCache].\nA caché de obxectos está desactivada.",
-       "config-mod-security": "'''Atención:''' O seu servidor web ten o [http://modsecurity.org/ mod_security] activado. Se estivese mal configurado, pode causar problemas a MediaWiki ou calquera outro software que permita aos usuarios publicar contidos arbitrarios.\nOlle a [http://modsecurity.org/documentation/ documentación do mod_security] ou póñase en contacto co soporte do seu servidor se atopa erros aleatorios.",
+       "config-no-cache": "<strong>Atención:</strong> Non se puido atopar [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache] ou [http://www.iis.net/download/WinCacheForPhp WinCache].\nA caché de obxectos está desactivada.",
+       "config-mod-security": "<strong>Atención:</strong> O seu servidor web ten o [http://modsecurity.org/ mod_security] activado. Se estivese mal configurado, pode causar problemas a MediaWiki ou calquera outro software que permita aos usuarios publicar contidos arbitrarios.\nOlle a [http://modsecurity.org/documentation/ documentación do mod_security] ou póñase en contacto co soporte do seu servidor se atopa erros aleatorios.",
        "config-diff3-bad": "GNU diff3 non se atopou.",
        "config-git": "Atopouse o software de control da versión de Git: <code>$1</code>.",
        "config-git-bad": "Non se atopou o software de control da versión de Git.",
        "config-imagemagick": "ImageMagick atopado: <code>$1</code>.\nAs miniaturas de imaxes estarán dispoñibles se activa as cargas.",
        "config-gd": "Atopouse a biblioteca gráfica GD integrada.\nAs miniaturas de imaxes estarán dispoñibles se activa as cargas.",
        "config-no-scaling": "Non se puido atopar a biblioteca GD ou ImageMagick.\nAs miniaturas de imaxes estarán desactivadas.",
-       "config-no-uri": "'''Erro:''' Non se puido determinar o URI actual.\nInstalación abortada.",
-       "config-no-cli-uri": "'''Aviso:''' Non se especificou ningún <code>--scriptpath</code>; por defecto, usarase: <code>$1</code>.",
+       "config-no-uri": "<strong>Erro:</strong> Non se puido determinar o URI actual.\nInstalación abortada.",
+       "config-no-cli-uri": "<strong>Atención:</strong> Non se especificou ningún <code>--scriptpath</code>; por defecto, usarase: <code>$1</code>.",
        "config-using-server": "Usando o nome do servidor \"<nowiki>$1</nowiki>\".",
        "config-using-uri": "Usando o URL do servidor \"<nowiki>$1$2</nowiki>\".",
-       "config-uploads-not-safe": "'''Atención:''' O seu directorio por defecto para as cargas, <code>$1</code>, é vulnerable a execucións arbitrarias de escrituras.\nAínda que MediaWiki comproba todos os ficheiros cargados por se houbese ameazas de seguridade, é amplamente recomendable [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security pechar esta vulnerabilidade de seguridade] antes de activar as cargas.",
-       "config-no-cli-uploads-check": "'''Atención:''' Durante a instalación CLI, o seu directorio por defecto para as cargas, <code>$1</code>, non se comproba fronte a posibles vulnerabilidades de execucións arbitrarias de escrituras.",
+       "config-uploads-not-safe": "<strong>Atención:</strong> O seu directorio por defecto para as cargas, <code>$1</code>, é vulnerable a execucións arbitrarias de escrituras.\nAínda que MediaWiki comproba todos os ficheiros cargados por se houbese ameazas de seguridade, é amplamente recomendable [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security pechar esta vulnerabilidade de seguridade] antes de activar as cargas.",
+       "config-no-cli-uploads-check": "<strong>Atención:</strong> Durante a instalación CLI, o seu directorio por defecto para as cargas, <code>$1</code>, non se comproba fronte a posibles vulnerabilidades de execucións arbitrarias de escrituras.",
        "config-brokenlibxml": "O seu sistema ten unha combinación de versións de PHP e libxml2 que pode ser problemático e causar corrupción de datos en MediaWiki e outras aplicacións web.\nActualice o sistema á versión 2.7.3 ou posterior de libxml2 ([https://bugs.php.net/bug.php?id=45996 erro presentado co PHP]).\nInstalación abortada.",
        "config-suhosin-max-value-length": "Suhosin está instalado e limita o parámetro GET <code>length</code> a $1 bytes.\nO compoñente ResourceLoader (xestor de recursos) de MediaWiki traballa neste límite, pero este prexudica o rendemento.\nSe é posible, debería establecer <code>suhosin.get.max_value_length</code> no valor 1024 ou superior en <code>php.ini</code> e establecer <code>$wgResourceLoaderMaxQueryLength</code> no mesmo valor en <code>LocalSettings.php</code>.",
        "config-db-type": "Tipo de base de datos:",
        "config-charset-mysql5-binary": "MySQL 4.1/5.0 binario",
        "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
        "config-charset-mysql4": "MySQL 4.0 retrocompatible UTF-8",
-       "config-charset-help": "'''Atención:''' Se emprega '''backwards-compatible UTF-8''' no MySQL 4.1+ e posteriormente realiza unha copia de seguridade da base de datos con <code>mysqldump</code>, pode destruír todos os caracteres que non sexan ASCII, corrompendo de xeito irreversible as súas copias!\n\nNo '''modo binario''', MediaWiki almacena texto UTF-8 na base de datos en campos binarios.\nIsto é máis eficaz ca o modo UTF-8 de MySQL e permítelle usar o rango completo de caracteres Unicode.\nNo '''modo UTF-8''', MySQL saberá o xogo de caracteres dos seus datos e pode presentar e converter os datos de maneira axeitada,\npero non lle deixará gardar caracteres por riba do [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes plan multilingüe básico].",
+       "config-charset-help": "<strong>Atención:</strong> Se emprega <strong>backwards-compatible UTF-8</strong> no MySQL 4.1+ e posteriormente realiza unha copia de seguridade da base de datos con <code>mysqldump</code>, pode destruír todos os caracteres que non sexan ASCII, corrompendo de xeito irreversible as súas copias!\n\nNo <strong>modo binario</strong>, MediaWiki almacena texto UTF-8 na base de datos en campos binarios.\nIsto é máis eficaz ca o modo UTF-8 de MySQL e permítelle usar o rango completo de caracteres Unicode.\nNo <strong>modo UTF-8</strong>, MySQL saberá o xogo de caracteres dos seus datos e pode presentar e converter os datos de maneira axeitada,\npero non lle deixará gardar caracteres por riba do [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes plan multilingüe básico].",
        "config-mysql-old": "Necesítase MySQL $1 ou posterior. Vostede ten a versión $2.",
        "config-db-port": "Porto da base de datos:",
        "config-db-schema": "Esquema para MediaWiki",
        "config-db-schema-help": "O normal é que este esquema sexa correcto.\nCámbieo soamente se sabe que é necesario.",
-       "config-pg-test-error": "Non se pode conectar coa base de datos '''$1''': $2",
+       "config-pg-test-error": "Non se pode conectar coa base de datos <strong>$1</strong>: $2",
        "config-sqlite-dir": "Directorio de datos SQLite:",
-       "config-sqlite-dir-help": "SQLite recolle todos os datos nun ficheiro único.\n\nO servidor web debe ter permisos sobre o directorio para que poida escribir nel durante a instalación.\n\nAdemais, o servidor '''non''' debe ser accesible a través da web, motivo polo que non está no mesmo lugar ca os ficheiros PHP.\n\nAsemade, o programa de instalación escribirá un ficheiro <code>.htaccess</code>, pero se erra alguén pode obter acceso á súa base de datos.\nIsto inclúe datos de usuario (enderezos de correo electrónico, contrasinais codificados), así como revisións borradas e outros datos restrinxidos no wiki.\n\nConsidere poñer a base de datos nun só lugar, por exemplo en <code>/var/lib/mediawiki/oseuwiki</code>.",
+       "config-sqlite-dir-help": "SQLite recolle todos os datos nun ficheiro único.\n\nO servidor web debe ter permisos sobre o directorio para que poida escribir nel durante a instalación.\n\nAdemais, o servidor <strong>non</strong> debe ser accesible a través da web, motivo polo que non está no mesmo lugar ca os ficheiros PHP.\n\nAsemade, o programa de instalación escribirá un ficheiro <code>.htaccess</code>, pero se erra alguén pode obter acceso á súa base de datos.\nIsto inclúe datos de usuario (enderezos de correo electrónico, contrasinais codificados), así como revisións borradas e outros datos restrinxidos no wiki.\n\nConsidere poñer a base de datos nun só lugar, por exemplo en <code>/var/lib/mediawiki/oseuwiki</code>.",
        "config-oracle-def-ts": "Espazo de táboas por defecto:",
        "config-oracle-temp-ts": "Espazo de táboas temporal:",
        "config-type-mysql": "MySQL (ou compatible)",
        "config-sqlite-readonly": "Non se pode escribir no ficheiro <code>$1</code>.",
        "config-sqlite-cant-create-db": "Non se puido crear o ficheiro da base de datos <code>$1</code>.",
        "config-sqlite-fts3-downgrade": "Falta o soporte FTS3 para o PHP; diminuíndo as táboas",
-       "config-can-upgrade": "Existen táboas MediaWiki nesta base de datos.\nPara actualizalas a MediaWiki $1, prema sobre \"'''Continuar'''\".",
-       "config-upgrade-done": "Actualización completada.\n\nAgora pode [$1 comezar a utilizar o seu wiki].\n\nSe quere rexenerar o seu ficheiro <code>LocalSettings.php</code>, prema no botón que aparece a continuación.\nIsto '''non é recomendable''' a menos que estea a ter problemas co seu wiki.",
+       "config-can-upgrade": "Existen táboas MediaWiki nesta base de datos.\nPara actualizalas a MediaWiki $1, prema sobre \"<strong>Continuar</strong>\".",
+       "config-upgrade-done": "Actualización completada.\n\nAgora pode [$1 comezar a utilizar o seu wiki].\n\nSe quere rexenerar o seu ficheiro <code>LocalSettings.php</code>, prema no botón que aparece a continuación.\nIsto <strong>non é recomendable</strong> a menos que estea a ter problemas co seu wiki.",
        "config-upgrade-done-no-regenerate": "Actualización completada.\n\nXa pode [$1 comezar a usar o seu wiki].",
        "config-regenerate": "Rexenerar LocalSettings.php →",
        "config-show-table-status": "A pescuda <code>SHOW TABLE STATUS</code> fallou!",
-       "config-unknown-collation": "'''Atención:''' A base de datos está a empregar unha clasificación alfabética irrecoñecible.",
+       "config-unknown-collation": "<strong>Atención:</strong> A base de datos está a empregar unha clasificación alfabética irrecoñecible.",
        "config-db-web-account": "Conta na base de datos para o acceso á internet",
        "config-db-web-help": "Seleccione o nome de usuario e contrasinal que o servidor web empregará para se conectar ao servidor da base de datos durante o funcionamento normal do wiki.",
        "config-db-web-account-same": "Empregar a mesma conta que para a instalación",
        "config-mysql-engine": "Motor de almacenamento:",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
-       "config-mysql-myisam-dep": "'''Atención:''' Seleccionou MyISAM como o motor de almacenamento para MySQL, unha combinación non recomendada para MediaWiki, porque:\n* practicamente non soporta os accesos simultáneos debido ao bloqueo de táboas\n* é máis propenso a corromperse ca outros motores\n* o código base de MediaWiki non sempre manexa o MyISAM como debera\n\nSe a súa instalación MySQL soporta InnoDB, recoméndase elixilo no canto de MyISAM.\nSe a súa instalación MySQL non soporta InnoDB, quizais sexa boa idea realizar unha actualización.",
-       "config-mysql-only-myisam-dep": "'''Atención:''' MyISAM é o único motor de almacenamento para MySQL nesta máquina, unha combinación non recomendada para MediaWiki, porque:\n* practicamente non soporta os accesos simultáneos debido ao bloqueo de táboas\n* é máis propenso a corromperse ca outros motores\n* o código base de MediaWiki non sempre manexa o MyISAM como debera\n\nA súa instalación MySQL non soporta InnoDB, quizais sexa boa idea realizar unha actualización.",
-       "config-mysql-engine-help": "'''InnoDB''' é case sempre a mellor opción, dado que soporta ben os accesos simultáneos.\n\n'''MyISAM''' é máis rápido en instalacións de usuario único e de só lectura.\nAs bases de datos MyISAM tenden a se corromper máis a miúdo ca as bases de datos InnoDB.",
+       "config-mysql-myisam-dep": "<strong>Atención:</strong> Seleccionou MyISAM como o motor de almacenamento para MySQL, unha combinación non recomendada para MediaWiki, porque:\n* practicamente non soporta os accesos simultáneos debido ao bloqueo de táboas\n* é máis propenso a corromperse ca outros motores\n* o código base de MediaWiki non sempre manexa o MyISAM como debera\n\nSe a súa instalación MySQL soporta InnoDB, recoméndase elixilo no canto de MyISAM.\nSe a súa instalación MySQL non soporta InnoDB, quizais sexa boa idea realizar unha actualización.",
+       "config-mysql-only-myisam-dep": "<strong>Atención:</strong> MyISAM é o único motor de almacenamento para MySQL nesta máquina, unha combinación non recomendada para MediaWiki, porque:\n* practicamente non soporta os accesos simultáneos debido ao bloqueo de táboas\n* é máis propenso a corromperse ca outros motores\n* o código base de MediaWiki non sempre manexa o MyISAM como debera\n\nA súa instalación MySQL non soporta InnoDB, quizais sexa boa idea realizar unha actualización.",
+       "config-mysql-engine-help": "<strong>InnoDB</strong> é case sempre a mellor opción, dado que soporta ben os accesos simultáneos.\n\n<strong>MyISAM</strong> é máis rápido en instalacións de usuario único e de só lectura.\nAs bases de datos MyISAM tenden a se corromper máis a miúdo ca as bases de datos InnoDB.",
        "config-mysql-charset": "Conxunto de caracteres da base de datos:",
        "config-mysql-binary": "Binario",
        "config-mysql-utf8": "UTF-8",
-       "config-mysql-charset-help": "No '''modo binario''', MediaWiki almacena texto UTF-8 na base de datos en campos binarios.\nIsto é máis eficaz ca o modo UTF-8 de MySQL e permítelle usar o rango completo de caracteres Unicode.\n\nNo '''modo UTF-8''', MySQL saberá o xogo de caracteres dos seus datos e pode presentar e converter os datos de maneira axeitada,\npero non lle deixará gardar caracteres por riba do [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes plan multilingüe básico].",
+       "config-mysql-charset-help": "No <strong>modo binario</strong>, MediaWiki almacena texto UTF-8 na base de datos en campos binarios.\nIsto é máis eficaz ca o modo UTF-8 de MySQL e permítelle usar o rango completo de caracteres Unicode.\n\nNo <strong>modo UTF-8</strong>, MySQL saberá o xogo de caracteres dos seus datos e pode presentar e converter os datos de maneira axeitada,\npero non lle deixará gardar caracteres por riba do [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes plan multilingüe básico].",
        "config-mssql-auth": "Tipo de autenticación:",
        "config-mssql-install-auth": "Seleccione o tipo de autenticación que se utilizará para conectarse á base de datos durante o proceso de instalación.\nSe selecciona \"{{int:config-mssql-windowsauth}}\", usaranse as credenciais do usuario co que se está a executar o servidor web.",
        "config-mssql-web-auth": "Seleccione o tipo de autenticación que utilizará o servidor web para conectarse ao servidor da base de datos durante o funcionamiento normal do wiki.\nSe selecciona \"{{int:config-mssql-windowsauth}}\", usaranse as credenciais do usuario co que se está a executar o servidor web.",
        "config-ns-site-name": "O mesmo nome que o wiki: $1",
        "config-ns-other": "Outro (especificar)",
        "config-ns-other-default": "OMeuWiki",
-       "config-project-namespace-help": "Seguindo o exemplo da Wikipedia, moitos wikis manteñen as súas páxinas de políticas separadas das súas páxinas de contido, nun \"'''espazo de nomes do proxecto'''\".\nTodos os títulos presentes neste espazo de nomes comezan cun prefixo determinado, que pode especificar aquí.\nTradicionalmente, este prefixo deriva do nome do wiki, pero non pode conter caracteres de puntuación como \"#\" ou \":\".",
+       "config-project-namespace-help": "Seguindo o exemplo da Wikipedia, moitos wikis manteñen as súas páxinas de políticas separadas das súas páxinas de contido, nun \"'''espazo de nomes do proxecto'''\".\nTodos os títulos presentes neste espazo de nomes comezan cun prefixo determinado, que pode especificar aquí.\nNormalmente, este prefixo deriva do nome do wiki, pero non pode conter caracteres de puntuación como \"#\" ou \":\".",
        "config-ns-invalid": "O espazo de nomes especificado, \"<nowiki>$1</nowiki>\", é incorrecto.\nEspecifique un espazo de nomes do proxecto diferente.",
        "config-ns-conflict": "O espazo de nomes especificado, \"<nowiki>$1</nowiki>\", entra en conflito co espazo de nomes MediaWiki por defecto.\nEspecifique un espazo de nomes do proxecto diferente.",
        "config-admin-box": "Conta de administrador",
        "config-profile-no-anon": "Necesítase a creación dunha conta",
        "config-profile-fishbowl": "Só os editores autorizados",
        "config-profile-private": "Wiki privado",
-       "config-profile-help": "Os wikis funcionan mellor canta máis xente os edite.\nEn MediaWiki, é doado revisar os cambios recentes e reverter calquera dano feito por usuarios novatos ou con malas intencións.\nPorén, moita xente atopa MediaWiki útil nunha ampla variedade de papeis, e ás veces non é fácil convencer a todos dos beneficios que leva consigo o estilo wiki.\nVostede decide.\n\nO modelo '''{{int:config-profile-wiki}}''' permite a edición por parte de calquera, mesmo sen rexistro.\nA opción '''{{int:config-profile-no-anon}}''' proporciona un control maior, pero pode desalentar os colaboradores casuais.\n\nO escenario '''{{int:config-profile-fishbowl}}''' restrinxe a edición aos usuarios aprobados, pero o público pode ollar as páxinas, incluíndo os historiais.\nO tipo '''{{int:config-profile-private}}''' só deixa que os usuarios aprobados vexan e editen as páxinas.\n\nHai dispoñibles configuracións de dereitos de usuario máis complexas despois da instalación; bótelle un ollo a [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights esta entrada no manual].",
+       "config-profile-help": "Os wikis funcionan mellor canta máis xente os edite.\nEn MediaWiki, é doado revisar os cambios recentes e reverter calquera dano feito por usuarios novatos ou con malas intencións.\nPorén, moita xente atopa MediaWiki útil nunha ampla variedade de papeis, e ás veces non é fácil convencer a todos dos beneficios que leva consigo o estilo wiki.\nVostede decide.\n\nO modelo <strong>{{int:config-profile-wiki}}</strong> permite a edición por parte de calquera, mesmo sen rexistro.\nA opción <strong>{{int:config-profile-no-anon}}</strong> proporciona un control maior, pero pode desalentar os colaboradores casuais.\n\nO escenario <strong>{{int:config-profile-fishbowl}}</strong> restrinxe a edición aos usuarios aprobados, pero o público pode ollar as páxinas, incluíndo os historiais.\nO tipo <strong>{{int:config-profile-private}}</strong> só deixa que os usuarios aprobados vexan e editen as páxinas.\n\nHai dispoñibles configuracións de dereitos de usuario máis complexas despois da instalación; bótelle un ollo a [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights esta entrada no manual].",
        "config-license": "Dereitos de autoría e licenza:",
        "config-license-none": "Sen licenza ao pé",
        "config-license-cc-by-sa": "Creative Commons recoñecemento compartir igual",
        "config-license-gfdl": "Licenza de documentación libre de GNU 1.3 ou posterior",
        "config-license-pd": "Dominio público",
        "config-license-cc-choose": "Seleccione unha licenza Creative Commons personalizada",
-       "config-license-help": "Moitos wikis públicos liberan todas as súas contribucións baixo unha [http://freedomdefined.org/Definition/Gl licenza libre].\nIsto axuda a crear un sentido de propiedade comunitaria e anima a seguir contribuíndo durante moito tempo.\nXeralmente, non é necesario nos wikis privados ou de empresas.\n\nSe quere poder empregar textos da Wikipedia, así como que a Wikipedia poida aceptar textos copiados do seu wiki, escolla a licenza '''Creative Commons recoñecemento compartir igual'''.\n\nA licenza de documentación libre de GNU era a licenza anterior da Wikipedia.\nMalia aínda ser unha licenza válida, é difícil de entender.\nTamén é difícil reusar contidos baixo esta licenza.",
+       "config-license-help": "Moitos wikis públicos liberan todas as súas contribucións baixo unha [http://freedomdefined.org/Definition/Gl licenza libre].\nIsto axuda a crear un sentido de propiedade comunitaria e anima a seguir contribuíndo durante moito tempo.\nXeralmente, non é necesario nos wikis privados ou de empresas.\n\nSe quere poder empregar textos da Wikipedia, así como que a Wikipedia poida aceptar textos copiados do seu wiki, escolla a licenza <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nA licenza de documentación libre de GNU era a licenza anterior da Wikipedia.\nMalia aínda ser unha licenza válida, é difícil de entender.\nTamén é difícil reusar contidos baixo esta licenza.",
        "config-email-settings": "Configuración do correo electrónico",
        "config-enable-email": "Activar os correos electrónicos de saída",
        "config-enable-email-help": "Se quere que o correo electrónico funcione, cómpre configurar os [http://www.php.net/manual/en/mail.configuration.php parámetros PHP] correctamente.\nSe non quere ningunha característica no correo, pode desactivalas aquí.",
        "config-email-watchlist": "Activar a notificación da lista de vixilancia",
        "config-email-watchlist-help": "Permitir que os usuarios reciban notificacións sobre modificacións nas páxinas que vixían, se o teñen activado nas súas preferencias.",
        "config-email-auth": "Activar a autenticación do correo electrónico",
-       "config-email-auth-help": "Se esta opción está activada, os usuarios teñen que confirmar o seu correo electrónico mediante unha ligazón enviada ao enderezo cando o definan ou o cambien.\nSó os enderezos autenticados poden recibir correos doutros usuarios ou de notificación.\nÉ '''recomendable''' establecer esta opción nos wikis públicos para evitar abusos potenciais das características do correo.",
+       "config-email-auth-help": "Se esta opción está activada, os usuarios teñen que confirmar o seu correo electrónico mediante unha ligazón enviada ao enderezo cando o definan ou o cambien.\nSó os enderezos autenticados poden recibir correos doutros usuarios ou de notificación.\nÉ <strong>recomendable</strong> establecer esta opción nos wikis públicos para evitar abusos potenciais das características do correo.",
        "config-email-sender": "Enderezo de correo electrónico de retorno:",
        "config-email-sender-help": "Introduza o enderezo de correo electrónico a usar como enderezo de retorno dos correos de saída.\nAquí é onde irán parar os correos rexeitados.\nMoitos servidores de correo electrónico esixen que polo menos a parte do nome de dominio sexa válido.",
        "config-upload-settings": "Imaxes e carga de ficheiros",
        "config-memcache-badport": "Os números de porto Memcached deben estar entre $1 e $2.",
        "config-extensions": "Extensións",
        "config-extensions-help": "As extensións anteriores detectáronse no seu directorio <code>./extensions</code>.\n\nQuizais necesite algunha configuración adicional, pero pode activalas agora",
-       "config-install-alreadydone": "'''Atención:''' Semella que xa instalou MediaWiki e que o está a instalar de novo.\nVaia ata a seguinte páxina.",
+       "config-skins": "Aparencias",
+       "config-skins-help": "As aparencias listadas enriba detectáronse no seu directorio <code>./skins</code>. Debe activar, polo menos, unha e elixir a predeterminada.",
+       "config-skins-use-as-default": "Utilizar esta aparencia por defecto",
+       "config-skins-missing": "Non se atopou aparencia ningunha. MediaWiki ha utilizar unha aparencia de respaldo ata que vostede instale algunha aparencia axeitada.",
+       "config-skins-must-enable-some": "Debe elixir, polo menos, unha aparencia para activala.",
+       "config-skins-must-enable-default": "A aparencia elixida como predeterminada debe estar activada.",
+       "config-install-alreadydone": "<strong>Atención:</strong> Semella que xa instalou MediaWiki e que o está a instalar de novo.\nVaia ata a seguinte páxina.",
        "config-install-begin": "Ao premer en \"{{int:config-continue}}\", comezará a instalación de MediaWiki.\nSe aínda quere facer algún cambio, prema en \"{{int:config-back}}\".",
        "config-install-step-done": "feito",
        "config-install-step-failed": "erro",
        "config-install-user-missing": "O usuario especificado, \"$1\", non existe.",
        "config-install-user-missing-create": "O usuario especificado, \"$1\", non existe.\nPrema na caixa de verificación \"crear unha conta\" que hai a continuación se quere crear unha.",
        "config-install-tables": "Creando as táboas",
-       "config-install-tables-exist": "'''Atención:''' Semella que as táboas de MediaWiki xa existen.\nSaltando a creación.",
-       "config-install-tables-failed": "'''Erro:''' Fallou a creación da táboa. Descrición do erro: $1",
+       "config-install-tables-exist": "<strong>Atención:</strong> Semella que as táboas de MediaWiki xa existen.\nSaltando a creación.",
+       "config-install-tables-failed": "<strong>Erro:</strong> Fallou a creación da táboa. Descrición do erro: $1",
        "config-install-interwiki": "Enchendo a táboa de interwiki por defecto",
        "config-install-interwiki-list": "Non se puido atopar o ficheiro <code>interwiki.list</code>.",
-       "config-install-interwiki-exists": "'''Atención:''' Semella que a táboa de interwiki xa contén entradas.\nSaltando a lista por defecto.",
+       "config-install-interwiki-exists": "<strong>Atención:</strong> Semella que a táboa de interwiki xa contén entradas.\nSaltando a lista por defecto.",
        "config-install-stats": "Iniciando as estatísticas",
        "config-install-keys": "Xerando as claves secretas",
-       "config-insecure-keys": "'''Atención:''' {{PLURAL:$2|A clave de seguridade|As claves de seguridade}} ($1) {{PLURAL:$2|xerada|xeradas}} durante a instalación non {{PLURAL:$2|é|son}} completamente {{PLURAL:$2|segura|seguras}}. Considere a posibilidade de {{PLURAL:$2|cambiala|cambialas}} manualmente.",
+       "config-insecure-keys": "<strong>Atención:</strong> {{PLURAL:$2|A clave de seguridade|As claves de seguridade}} ($1) {{PLURAL:$2|xerada|xeradas}} durante a instalación non {{PLURAL:$2|é|son}} completamente {{PLURAL:$2|segura|seguras}}. Considere a posibilidade de {{PLURAL:$2|cambiala|cambialas}} manualmente.",
+       "config-install-updates": "Evitar executar actualizacións innecesarias",
+       "config-install-updates-failed": "<strong>Error:</strong> a inserción de claves de actualización nas táboas fallou co seguinte erro: $1",
        "config-install-sysop": "Creando a conta de usuario de administrador",
        "config-install-subscribe-fail": "Non se puido subscribir á lista mediawiki-announce: $1",
        "config-install-subscribe-notpossible": "cURL non está instalado e <code>allow_url_fopen</code> non está dispoñible.",
        "config-install-mainpage": "Creando a páxina principal co contido por defecto",
        "config-install-extension-tables": "Creando as táboas para as extensións activadas",
        "config-install-mainpage-failed": "Non se puido inserir a páxina principal: $1",
-       "config-install-done": "'''Parabéns!'''\nInstalou correctamente MediaWiki.\n\nO programa de instalación xerou un ficheiro <code>LocalSettings.php</code>.\nEste ficheiro contén toda a súa configuración.\n\nTerá que descargalo e poñelo na base da instalación do seu wiki (no mesmo directorio ca index.php). A descarga debería comezar automaticamente.\n\nSe non comezou a descarga ou se a cancelou, pode facer que comece de novo premendo na ligazón que aparece a continuación:\n\n$3\n\n'''Nota:''' Se non fai iso agora, este ficheiro de configuración xerado non estará dispoñible máis adiante se sae da instalación sen descargalo.\n\nCando faga todo isto, xa poderá '''[$2 entrar no seu wiki]'''.",
+       "config-install-done": "<strong>Parabéns!</strong>\nInstalou correctamente MediaWiki.\n\nO programa de instalación xerou un ficheiro <code>LocalSettings.php</code>.\nEste ficheiro contén toda a súa configuración.\n\nTerá que descargalo e poñelo na base da instalación do seu wiki (no mesmo directorio ca index.php). A descarga debería comezar automaticamente.\n\nSe non comezou a descarga ou se a cancelou, pode facer que comece de novo premendo na ligazón que aparece a continuación:\n\n$3\n\n<strong>Nota:</strong> Se non fai iso agora, este ficheiro de configuración xerado non estará dispoñible máis adiante se sae da instalación sen descargalo.\n\nCando faga todo isto, xa poderá <strong>[$2 entrar no seu wiki]</strong>.",
        "config-download-localsettings": "Descargar o <code>LocalSettings.php</code>",
        "config-help": "axuda",
        "config-help-tooltip": "prema para expandir",
        "config-nofile": "Non se puido atopar o ficheiro \"$1\". Se cadra, foi borrado.",
        "config-extension-link": "Sabía que o seu wiki soporta [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions extensións]?\n\nPode explorar as [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category extensións por categoría] ou a [//www.mediawiki.org/wiki/Extension_Matrix matriz de extensións] para ollar a lista completa de extensións.",
-       "mainpagetext": "'''MediaWiki instalouse correctamente.'''",
+       "mainpagetext": "<strong>MediaWiki instalouse correctamente.</strong>",
        "mainpagedocfooter": "Consulte a [//meta.wikimedia.org/wiki/Help:Contents guía de usuario] para obter máis información sobre como usar o software wiki.\n\n== Primeiros pasos ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lista das opcións de configuración]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Preguntas máis frecuentes sobre MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de correo dos lanzamentos de MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localice MediaWiki á súa lingua]"
 }
index 5a7d148..afa7d72 100644 (file)
        "config-localsettings-key": "Pihi hoʻopuka hou:",
        "config-localsettings-badkey": "Hewa ka pihi.",
        "config-upgrade-key-missing": "Loaʻa he hoʻonohona mai mua o MīkiaWiki mai mua.\nNo ka hoʻopuka hou ʻana o kēia hoʻonohona, e ʻoluʻolu, e kau i kēia laina lalo ma lalo o kāu <code>LocalSettings.php</code>:\n\n$1",
+       "config-localsettings-incomplete": "ʻAʻole piha pono kēia <code>LocalSettings.php</code> nei.\nʻAʻole hoʻopaʻa ʻia ka hualau $1.\nE hoʻololi iā <code>LocalSettings.php</code> i hiki ke hoʻopaʻa i ka hualau, a laila e kaomi iā \"{{int:Config-continue}}\" ke ʻoluʻolu.",
+       "config-localsettings-connection-error": "Ua loaʻa i ke kuʻia i ka hoʻokuʻi ʻana i ke hōkeo ʻikepili ma muli o ka hana ʻana o ka makemake e kākau ʻia ma <code>LocalSettings.php</code>. E ʻoluʻolu e hoʻoponopono i kēia makemake a hana hou.\n\n$1",
+       "config-session-error": "Kuʻia ka wā hoʻohana hoʻomaka: $1",
+       "config-session-expired": "Ua pau kāu ʻikepili wā hoʻohana.\nOla ka wā hoʻohana no ka manawa o $1.\nHiki iā ʻoe ke hoʻonui i kēia wā ma o ka hoʻololi ʻana o <code>session.gc_maxlifetime</code> ma php.ini.\nE hana hou i ka hana hoʻoukana.",
+       "config-no-session": "Ua nalo kāu ʻikepili wā hoʻohana!\nE hōʻoia i kāu php.ini a me ka hoʻopaʻa ʻana o <code>session.save_path</code> i ke kumu kūpono.",
        "config-your-language": "Kāu ʻōlelo:",
        "config-your-language-help": "E koho i kekahi ʻōlelo no ka hoʻohana ʻana ma loko o ka hana hoʻonohona.",
        "config-wiki-language": "ʻŌlelo Wiki:",
@@ -33,6 +38,7 @@
        "config-page-copying": "Kope",
        "config-page-upgradedoc": "Ka Hoʻopuka ʻana",
        "config-page-existingwiki": "Ka wiki nei",
+       "config-help-restart": "He ʻoiaʻiʻo kāu makemake no ka holoi pono o nā ʻikepili mālamalia a pau āu i kikokiko a hoʻomaka hou i ka hana hoʻouka?",
        "config-restart": "ʻAe, e hōʻano hou",
        "config-db-type": "ʻAno hōkeo ʻikepili:",
        "config-db-name": "Inoa hōkeo ʻikepili",
index 5d4ba21..dd14e63 100644 (file)
@@ -51,7 +51,7 @@
        "config-env-good": "הסביבה שלכם נבדקה.\nאפשר להתקין מדיה־ויקי.",
        "config-env-bad": "הסביבה שלכם נבדקה.\nאי־אפשר להתקין מדיה־ויקי.",
        "config-env-php": "מותקנת <span dir=\"ltr\">PHP $1</span>.",
-       "config-env-php-toolow": "מותקנת <span dir=\"ltr\">PHP $1</span>.\nלמדיה־ויקי נדרשת <span dir=\"ltr\">PHP $2</span> או גרסה גבוהה יותר.",
+       "config-env-hhvm": "מותקנת <span dir=\"ltr\">HHVM $1</span>.",
        "config-unicode-using-utf8": "משתמש ב־utf8_normalize.so של בריון ויבר לנרמול יוניקוד.",
        "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 Unicode normalization].",
@@ -59,7 +59,8 @@
        "config-no-db": "לא נמצא דרייבר מסד נתונים מתאים. יש להתקין דרייבר מסד נתונים ל־PHP.\nנתמכים הסוגים הבאים של מסדי נתונים: $1.\n\nאם קִמפלת את PHP בעצמך, יש להגדיר אותו מחדש ולהפעיל את לקוח מסד נתונים, למשל באמצעות <code dir=\"ltr\">./configure --with-mysqli</code>.\nאם התקנת את PHP מחבילה של דביאן או של אובונטו, יש להתקין, למשל, גם את המודול <code dir=\"ltr\">php5-mysql</code>.",
        "config-outdated-sqlite": "'''אזהרה''': במערכת מתוקן SQLite $1. גרסה זו לא נתמכת ולשימוש ב־SQLite נדרשת גרסה $2 לפחות. SQLlite לא יהיה זמין.",
        "config-no-fts3": "'''אזהרה''': SQLite מקומפל ללא [//sqlite.org/fts3.html מודול FTS]. יכולות חיפוש לא יהיו זמינות בהתקנה הזאת.",
-       "config-register-globals": "'''אזהרה: האפשרות <code>[http://php.net/register_globals register_globals]</code> של PHP מופעלת.'''\n'''כבו אותה אם זה אפשרי.'''\nמדיה־ויקי תעבוד, אבל השרת שלך חשוף לפגיעות אבטחה.",
+       "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": "<strong>שגיאה סופנית: האפשרות [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] פעילה!</strong>\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לא ניתן להתקין את מדיה־ויקי או להשתמש בה אלא אם האפשרות הזאת תכובה.",
@@ -70,6 +71,7 @@
        "config-memory-raised": "ערך האפשרות <code>memory_limit</code> של PHP הוא $1, הועלה ל־$2.",
        "config-memory-bad": "'''אזהרה:''' ערך האפשרות <code>memory_limit</code> של PHP הוא $1.\nזה כנראה נמוך מדי.\nההתקנה עשויה להיכשל!",
        "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 כלולה ב־Red Hat Enterprise Linux (ו־CentOS), אך יש להפעיל אותה ב־<code dir=\"ltr\">/etc/php.ini</code> או ב־<code dir=\"ltr\">/etc/php.d/json.ini</code>.",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] מותקן",
        "config-apc": "[http://www.php.net/apc APC] מותקן",
        "config-license-gfdl": "רישיון חופשי למסמכים של גנו גרסה 1.3 או חדשה יותר",
        "config-license-pd": "נחלת הכלל",
        "config-license-cc-choose": "בחירת רישיון קריאייטיב קומונז מותאם אישית",
-       "config-license-help": "אתרי ויקי ציבוריים רבים מפרסמים את כל התרומות [http://freedomdefined.org/Definition ברישיון חופשי].\nזה עוזר ליצור תחושה של בעלות קהילתית ומעודד תרומה לאורך זמן.\nזה בדרך כלל לא נחוץ לאתר ויקי פרטי או אתר של חברה מסחרית.\n\nאם האפשרות להשתמש בטקסט מוויקיפדיה והאפשרות שוויקיפדיה תוכל תקבל עותקים של טקסטים מהוויקי שלך חשובות לך, כדאי לבחור ב'''רישיון קריאייטיב קומונז ייחוס–שיתוף זהה''' (CC BY-SA).\n\nויקיפדיה השתמשה בעבר ברישיון החופשי למסמכים של גנו (GNU FDL או GFDL).\nהוא עדיין רישיון תקין, אבל קשה להבנה.\nכמו־כן, קשה לעשות שימוש חוזר ביצירות שפורסמו לפי GFDL.",
+       "config-license-help": "אתרי ויקי ציבוריים רבים מפרסמים את כל התרומות [http://freedomdefined.org/Definition ברישיון חופשי].\nזה עוזר ליצור תחושה של בעלות קהילתית ומעודד תרומה לאורך זמן.\nזה בדרך כלל לא נחוץ לאתר ויקי פרטי או אתר של חברה מסחרית.\n\nאם האפשרות להשתמש בטקסט מוויקיפדיה והאפשרות שוויקיפדיה תוכל תקבל עותקים של טקסטים מהוויקי שלך חשובות לך, כדאי לבחור ב<strong>{{int:config-license-cc-by-sa}}</strong>.\n\nויקיפדיה השתמשה בעבר ברישיון החופשי למסמכים של גנו (GNU FDL או GFDL).\nהוא עדיין רישיון תקין, אבל קשה להבנה.\nכמו־כן, קשה לעשות שימוש חוזר ביצירות שפורסמו לפי GFDL.",
        "config-email-settings": "הגדרות דוא״ל",
        "config-enable-email": "להפעיל דוא״ל יוצא",
        "config-enable-email-help": "אם אתם רוצים שדוא״ל יעבוד, [http://www.php.net/manual/en/mail.configuration.php אפשרויות הדוא״ל של PHP] צריכות להיות מוגדרות נכון.\nאם אינכם רוצים להפעיל שום אפשרויות דוא״ל, כבו אותן כאן ועכשיו.",
        "config-memcache-badport": "מספרי פתחה של Memcached צריכים להיות בין $1 ל־$2",
        "config-extensions": "הרחבות",
        "config-extensions-help": "ההרחבות ברשימה לעיל התגלו בתיקיית <span dir=\"ltr\"><code>./extensions</code></span> שלכם.\n\nייתכן שזה ידרוש הגדרות נוספות, אבל תוכלו להפעיל אותן עכשיו.",
+       "config-skins": "עיצובים",
+       "config-skins-help": "העיצובים לעיל נמצאו בתיקיית ה־<code dir=\"ltr\">./skins</code> שלך. חובה להפעיל לפחות אחת ולבחור בררת מחדל.",
+       "config-skins-use-as-default": "להשתמש בזה בתור בררת מחדל",
+       "config-skins-missing": "לא נמצאו עיצובים; מדיה־ויקי תשתמש בעיצוב גיבוי עד התקנת משהו מתאים.",
+       "config-skins-must-enable-some": "חובה לבחור לפחות עיצוב אחד שיופעל.",
+       "config-skins-must-enable-default": "העיצוב שנבחר בתור בררת מחדל חייב להיות מופעל.",
        "config-install-alreadydone": "'''אזהרה:''' נראה שכבר התקנתם את מדיה־ויקי ואתם מנסים להתקין אותה שוב.\nאנה התקדמו לדף הבא.",
        "config-install-begin": "כשתלחצו על \"{{int:config-continue}}\", תתחילו את ההתקנה של מדיה־ויקי.\nאם אתם עדיין רוצים לשנות משהו, לחצו על \"{{int:config-back}}\".",
        "config-install-step-done": "בוצע",
        "config-install-stats": "אתחול סטטיסטיקות",
        "config-install-keys": "יצירת מפתחות סודיים",
        "config-insecure-keys": "'''אזהרה''': {{PLURAL:$2|מפתח|מפתחות}} אבטחה ($1) {{PLURAL:$2|שנוצר|שנוצרו}} במהלך ההתקנה {{PLURAL:$2|אינו בטוח|אינם בטוחים}} מספיק. מומלץ לשקול לשנות {{PLURAL:$2|אותו|אותם}} ידנית.",
+       "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> אינה זמינה.",
index 5c0e9db..62afb44 100644 (file)
@@ -47,7 +47,6 @@
        "config-env-good": "Le ambiente ha essite verificate.\nTu pote installar MediaWiki.",
        "config-env-bad": "Le ambiente ha essite verificate.\nTu non pote installar MediaWiki.",
        "config-env-php": "PHP $1 es installate.",
-       "config-env-php-toolow": "PHP $1 es installate.\nNonobstante, MediaWiki require PHP $2 o plus recente.",
        "config-unicode-using-utf8": "utf8_normalize.so per Brion Vibber es usate pro le normalisation Unicode.",
        "config-unicode-using-intl": "Le [http://pecl.php.net/intl extension PECL intl] es usate pro le normalisation Unicode.",
        "config-unicode-pure-php-warning": "'''Aviso''': Le [http://pecl.php.net/intl extension PECL intl] non es disponibile pro exequer le normalisation Unicode; le systema recurre al implementation lente in PHP pur.\nSi tu sito ha un alte volumine de traffico, tu deberea informar te un poco super le [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations normalisation Unicode].",
@@ -55,7 +54,7 @@
        "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 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 installar equalmente, 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": "'''Attention: le option <code>[http://php.net/register_globals register_globals]</code> de PHP es activate.'''\n'''Disactiva lo si tu pote.'''\nMediaWiki functionara, ma tu servitor es exponite a potential vulnerabilitates de securitate.",
+       "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-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.",
index a37ed89..c2411ef 100644 (file)
@@ -53,7 +53,6 @@
        "config-env-good": "Kondisi telah diperiksa.\nAnda dapat menginstal MediaWiki.",
        "config-env-bad": "Kondisi telah diperiksa.\nAnda tidak dapat menginstal MediaWiki.",
        "config-env-php": "PHP $1 diinstal.",
-       "config-env-php-toolow": "PHP $1 telah terinstal.\nNamun, MediaWiki memerlukan PHP $2 atau lebih tinggi.",
        "config-unicode-using-utf8": "Menggunakan utf8_normalize.so Brion Vibber untuk normalisasi Unicode.",
        "config-unicode-using-intl": "Menggunakan [http://pecl.php.net/intl ekstensi PECL intl] untuk normalisasi Unicode.",
        "config-unicode-pure-php-warning": "'''Peringatan''': [http://pecl.php.net/intl Ekstensi intl PECL] untuk menangani normalisasi Unicode tidak tersedia, kembali menggunakan implementasi murni PHP yang lambat.\nJika Anda menjalankan situs berlalu lintas tinggi, Anda harus sedikit membaca [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations normalisasi Unicode].",
@@ -61,7 +60,7 @@
        "config-no-db": "Pengandar basis data yang sesuai tidak ditemukan! Anda perlu menginstal pengandar basis data untuk PHP.\nJenis basis data yang didukung: $1.\n\nJika Anda mengompilasi sendiri PHP, ubahlah konfigurasinya dengan mengaktifkan klien basis data, misalnya menggunakan <code>./configure --with-mysql</code>.\nJika Anda menginstal PHP dari paket Debian atau Ubuntu, maka Anda juga perlu menginstal modul php5-mysql.",
        "config-outdated-sqlite": "<strong>Peringatan:</strong> Anda menggunakan SQLite $1, yang lebih rendah dari versi minimum yang diperlukan $2. SQLite akan tidak tersedia.",
        "config-no-fts3": "'''Peringatan''': SQLite dikompilasi tanpa [//sqlite.org/fts3.html modul FTS3], fitur pencarian tidak akan tersedia pada konfigurasi ini.",
-       "config-register-globals": "'''Peringatan: Opsi <code>[http://php.net/register_globals register_globals]</code> PHP diaktifkan.'''\n'''Nonaktifkan kalau bisa.'''\nMediaWiki akan bekerja, tetapi server Anda memiliki potensi kerentanan keamanan.",
+       "config-register-globals-error": "<strong>Kesalahan: Pilihan PHP <code>[http://php.net/register_globals register_globals]</code> diaktifkan.\nIni harus dinonaktifkan untuk melanjutkan instalasi.</strong>\nLihat [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] untuk bantuan tentang cara melakukannya.",
        "config-magic-quotes-runtime": "'''Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] aktif!'''\nPilihan ini dapat merusak masukan data secara tidak terduga.\nAnda tidak dapat menginstal atau menggunakan MediaWiki kecuali pilihan ini dinonaktifkan.",
        "config-magic-quotes-sybase": "'''Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic_quotes_sybase magic_quotes_sybase] aktif!'''\nPilihan ini dapat merusak masukan data secara tidak terduga.\nAnda tidak dapat menginstal atau menggunakan MediaWiki kecuali pilihan ini dinonaktifkan.",
        "config-mbstring": "'''Fatal: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] aktif!'' '\nPilihan ini dapat menyebabkan kesalahan dan kerusakan data yang tidak terduga.\nAnda tidak dapat menginstal atau menggunakan MediaWiki kecuali pilihan ini dinonaktifkan.",
@@ -72,6 +71,7 @@
        "config-memory-raised": "<code>memory_limit</code> PHP adalah $1, dinaikkan ke $2.",
        "config-memory-bad": "'''Peringatan:''' <code>memory_limit</code> PHP adalah $1.\nIni terlalu rendah.\nInstalasi terancam gagal!",
        "config-ctype": "<strong>Fatal:</strong> PHP harus disusun dengan dukungan untuk [http://www.php.net/manual/en/ctype.installation.php ekstensi Ctype].",
+       "config-json": "<strong>Fatal:</strong> PHP dikompilasi tanpa dukungan JSON.\nAnda harus menginstal salah satu pengaya PHP JSON atau pengaya [http://pecl.php.net/package/jsonc PECL jsonc] sebelum menginstal MediaWiki.\n* Pengaya PHP termasuk dalam Red Hat Enterprise Linux (CentOS) 5 dan 6, meskipun harus diaktifkan pada <code>/etc/php.ini</code> atau <code>/etc/php.d/json.ini</code>.\n* Beberapa distribusi Linux dirilis setelah Mei 2013 menghilangkan pengaya PHP, bukan kemasan pengaya PECL sebagai <code>php5-json</code> atau <code>php-pecl-jsonc</code>.",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] telah diinstal",
        "config-apc": "[http://www.php.net/apc APC] telah diinstal",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] telah diinstal",
@@ -88,6 +88,7 @@
        "config-using-server": "Menggunakan nama server \"<nowiki>$1</nowiki>\".",
        "config-using-uri": "Menggunakan URL server \"<nowiki>$1$2</nowiki>\".",
        "config-uploads-not-safe": "'''Peringatan:''' Direktori bawaan pengunggahan <code>$1</code> Anda rentan terhadap eksekusi skrip yang sewenang-wenang.\nMeskipun MediaWiki memeriksa semua berkas unggahan untuk ancaman keamanan, sangat dianjurkan untuk [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security menutup kerentanan keamanan ini] sebelum mengaktifkan pengunggahan.",
+       "config-no-cli-uploads-check": "<strong>Peringatan:</strong> Direktori default Anda untuk unggahan (<code>$1</code>) tidak diperiksa untuk kerentanan terhadap\neksekusi script sewenang-wenang selama instalasi CLI.",
        "config-brokenlibxml": "Sistem Anda memiliki kombinasi versi PHP dan libxml2 yang memiliki bug dan dapat menyebabkan kerusakan data tersembunyi pada MediaWiki dan aplikasi web lain.\nMutakhirkan ke PHP 5.2.9 atau yang lebih baru dan libxml2 2.7.3 atau yang lebih baru ([https://bugs.php.net/bug.php?id=45996 arsip bug di PHP]).\nInstalasi dibatalkan.",
        "config-suhosin-max-value-length": "Suhosin terpasang dan membatasi parameter GET <code>length</code> sebesar $1 bita. Komponen ResourceLoader MediaWiki akan berjalan dalam batasan ini, tetapi penanganannya akan menurunkan kinerja. Jika memungkinkan, Anda sebaiknya menetapkan nilai <code>suhosin.get.max_value_length</code> menjadi 1024 atau lebih tinggi dalam <code>php.ini</code> dan menyetel <code>$wgResourceLoaderMaxQueryLength</code> dengan nilai yang sama dalam <code>LocalSettings.php</code>.",
        "config-db-type": "Jenis basis data:",
        "config-missing-db-name": "Anda harus memasukkan nilai untuk \"{{int:config-db-name}}\"",
        "config-missing-db-host": "Anda harus memasukkan nilai untuk \"{{int:config-db-host}}\"",
        "config-missing-db-server-oracle": "Anda harus memasukkan nilai untuk \"{{int:config-db-host-oracle}}\"",
-       "config-invalid-db-server-oracle": "TNS basis data \"$1\" tidak sah.\nGunakan hanya huruf ASCII (a-z, A-Z), angka (0-9), garis bawah (_), dan titik (.).",
+       "config-invalid-db-server-oracle": "TNS basis data \"$1\" tidak sah.\nGunakan baik \"Nama TNS\" atau string \"Easy Connect\" ([http://docs.oracle.com/cd/E11882_01/network.112/e10836/naming.htm Metode Penamaan Oracle]).",
        "config-invalid-db-name": "Nama basis data \"$1\" tidak sah.\nGunakan hanya huruf ASCII (a-z, A-Z), angka (0-9), garis bawah (_), dan tanda hubung (-).",
        "config-invalid-db-prefix": "Prefiks basis data \"$1\" tidak sah.\nGunakan hanya huruf ASCII (a-z, A-Z), angka (0-9), garis bawah (_), dan tanda hubung (-).",
        "config-connection-error": "$1.\n\nPeriksa nama inang, pengguna, dan sandi di bawah ini dan coba lagi.",
index 101c19a..a61fff2 100644 (file)
@@ -55,7 +55,7 @@
        "config-env-good": "L'ambiente è stato controllato.\nÈ possibile installare MediaWiki.",
        "config-env-bad": "L'ambiente è stato controllato.\nNon è possibile installare MediaWiki.",
        "config-env-php": "PHP $1 è installato.",
-       "config-env-php-toolow": "PHP $1 è installato.\nTuttavia, MediaWiki richiede PHP $2 o superiore.",
+       "config-env-hhvm": "HHVM $1 è installato.",
        "config-unicode-using-utf8": "Usa Brion Vibber's utf8_normalize.so per la normalizzazione Unicode.",
        "config-unicode-using-intl": "Usa [http://pecl.php.net/intl l'estensione PECL intl] per la normalizzazione Unicode.",
        "config-unicode-pure-php-warning": "'''Attenzione:''' [http://pecl.php.net/intl l'estensione PECL intl] non è disponibile per gestire la normalizzazione Unicode, così si usa la lenta implementazione in puro PHP.\nSe esegui un sito ad alto traffico, dovresti leggere alcune considerazioni sulla [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations normalizzazione Unicode].",
@@ -63,7 +63,8 @@
        "config-no-db": "Impossibile trovare un driver adatto per il database! È necessario installare un driver per PHP.\nI seguenti formati di database sono supportati: $1.\n\nSe compili PHP autonomamente, riconfiguralo attivando un client database, per esempio utilizzando <code>./configure --with-mysqli</code>.\nQualora avessi installato PHP per mezzo di un pacchetto Debian o Ubuntu, allora devi installare anche il pacchetto <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Attenzione''': è presente SQLite $1 mentre è richiesta la versione $2, SQLite non sarà disponibile.",
        "config-no-fts3": "'''Attenzione''': SQLite è compilato senza il [//sqlite.org/fts3.html modulo FTS3], le funzionalità di ricerca non saranno disponibili su questo backend.",
-       "config-register-globals": "'''Attenzione: le variabili PHP <code>[http://php.net/register_globals register globals]</code> sono attivate.'''\n'''Disattivale se possibile.''' MediaWiki funzionerà, ma il server sarà esposto a potenziali vulnerabilità di sicurezza.",
+       "config-register-globals-error": "<strong>Errore: l'opzione PHP <code>[http://php.net/register_globals register_globals]</code> è abilitata.\nDeve essere disabilitata per continuare con l'installazione.</strong>\nVedi [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] per un aiuto su come farlo.",
+       "config-magic-quotes-gpc": "<strong>Fatale: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] è attivo!</strong>\nQuesta opzione danneggia i dati di input in modo imprevedibile.\nNon puoi installare o utilizzare MediaWiki, a meno che questa opzione sia disabilitata.",
        "config-magic-quotes-runtime": "'''Errore: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] è attivato!''' Questa opzione interferisce in modo imprevedibile con l'inserimento dei dati. Non è possibile installare o utilizzare MediaWiki a meno che questa opzione non sia disabilitata.",
        "config-magic-quotes-sybase": "'''Errore: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] è attivato!''' Questa opzione interferisce in modo imprevedibile con l'inserimento dei dati. Non è possibile installare o utilizzare MediaWiki a meno che questa opzione non sia disabilitata.",
        "config-mbstring": "'''Errore: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] è attivato!''' Questa opzione causa errori e può interferire in modo imprevedibile coi dati. Non è possibile installare o utilizzare MediaWiki a meno che questa opzione non sia disabilitata.",
@@ -74,6 +75,7 @@
        "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-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-xcache": "[http://xcache.lighttpd.net/ XCache] è installato",
        "config-apc": "[http://www.php.net/apc APC] è installato",
        "config-uploads-not-safe": "<strong>Attenzione:</strong> la directory predefinita per i caricamenti <code>$1</code> è vulnerabile all'esecuzione arbitraria di script.\nAnche se MediaWiki controlla tutti i file caricati per rischi alla sicurezza, è fortemente raccomandato di [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security chiudere questa vulnerabilità di sicurezza] prima di abilitare i caricamenti.",
        "config-no-cli-uploads-check": "<strong>Attenzione:</strong> la directory predefinita per i caricamenti (<code>$1</code>) non è stata verificata per la vulnerabilità sull'esecuzione arbitraria di script durante l'installazione da linea di comando.",
        "config-brokenlibxml": "Il tuo sistema ha una combinazione di versioni di PHP e libxml2 che è difettosa e che può provocare un danneggiamento non visibile di dati in MediaWiki ed in altre applicazioni per il web.\nAggiorna a libxml2 2.7.3 o successivo ([https://bugs.php.net/bug.php?id=45996 il bug è studiato dal lato PHP]).\nInstallazione interrotta.",
+       "config-suhosin-max-value-length": "Suhosin è installato e limita il parametro GET <code>length</code> a $1 byte.\nIl componente MediaWiki ResourceLoader funzionerà aggirando questo limite, ma riducendo le prestazioni.\nSe possibile, dovresti impostare <code>suhosin.get.max_value_length</code> a 1024 o superiore in <code>php.ini</code>, ed impostare <code>$wgResourceLoaderMaxQueryLength</code> allo stesso valore in <code>LocalSettings.php</code>.",
        "config-db-type": "Tipo di database:",
        "config-db-host": "Host del database:",
        "config-db-host-help": "Se il server del tuo database è su un server diverso, immetti qui il nome dell'host o il suo indirizzo IP.\n\nSe stai utilizzando un web hosting condiviso, il tuo hosting provider dovrebbe fornirti il nome host corretto nella sua documentazione.\n\nSe stai installando su un server Windows con uso di MySQL, l'uso di \"localhost\" potrebbe non funzionare correttamente come nome del server. In caso di problemi, prova a impostare \"127.0.0.1\" come indirizzo IP locale.\n\nSe usi PostgreSQL, lascia questo campo vuoto per consentire di connettersi tramite un socket Unix.",
        "config-db-host-oracle": "TNS del database:",
+       "config-db-host-oracle-help": "Inserisci un valido [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm Local Connect Name]; un file tnsnames.ora deve essere visibile a questa installazione.<br />Se stai usando la libreria cliente 10g o più recente puoi anche usare il metodo di denominazione [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm Easy Connect].",
        "config-db-wiki-settings": "Identifica questo wiki",
        "config-db-name": "Nome del database:",
        "config-db-name-help": "Scegli un nome che identifica il tuo wiki.\nNon deve contenere spazi.\n\nSe utilizzi un web hosting condiviso, il tuo hosting provider o ti fornisce uno specifico nome di database da utilizzare, oppure ti consentirà di creare il database tramite un pannello di controllo.",
        "config-db-name-oracle": "Schema del database:",
+       "config-db-account-oracle-warn": "Ci sono tre scenari supportati per l'installazione di Oracle come database di backend:\n\nSe vuoi creare un'utenza di database come parte del processo di installazione, fornisci un account con ruolo SYSDBA come utenza di database per l'installazione e specifica le credenziali volute per l'utenza di accesso web, altrimenti è possibile creare manualmente l'utenza di accesso web e fornire solo quell'account (se dispone delle autorizzazioni necessario per creare gli oggetti dello schema) o fornire due diverse utenze, una con i permessi di creazione e una per l'accesso web.\n\nScript per la creazione di un'utenza con le autorizzazioni necessarie può essere trovato nella directory \"maintenance/oracle/\" di questa installazione. Tieni presente che l'uso di un'utenza con restrizioni disabiliterà tutte le funzionalità di manutenzione con l'account predefinito.",
        "config-db-install-account": "Account utente per l'installazione",
        "config-db-username": "Nome utente del database:",
        "config-db-password": "Password del database:",
        "config-charset-mysql5-binary": "MySQL 4.1/5.0 binario",
        "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
        "config-charset-mysql4": "MySQL 4.0 con compatibilità UTF-8",
+       "config-charset-help": "<strong>Attenzione:</strong> se si utilizza <strong>backwards-compatible UTF-8</strong> su MySQL 4.1+, e successivamente si esegue il backup del database con <code>mysqldump</code>, si può distriggere tutti i caratteri non ASCII, danneggiando irreversibilmente i backup!\n\nIn <strong>modalità binaria</strong>, MediaWiki archivia il testo UTF-8 nel database in cambi binari.\nQuesto è più efficiente rispetto alla modalità UTF-8 di MySQL, e consente di utilizzare la gamma completa di caratteri Unicode.\nIn <strong>modalità UTF-8</strong>, MySQL conoscerà in quale set di caratteri sono i tuoi dati, e può presentarli e convertirli in modo appropriato,\nma non ti permetterà di memorizzare i caratteri al di sopra del [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane].",
        "config-mysql-old": "MySQL $1 o una versione successiva è necessaria, rilevata la $2.",
        "config-db-port": "Porta del database:",
        "config-db-schema": "Schema per MediaWiki:",
        "config-type-mssql": "Microsoft SQL Server",
        "config-support-info": "MediaWiki supporta i seguenti sistemi di database:\n\n$1\n\nSe fra quelli elencati qui sotto non vedi il sistema di database che vorresti utilizzare, seguire le istruzioni linkate sopra per abilitare il supporto.",
        "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] è la configurazione preferibile per MediaWiki ed è quella meglio supportata. MediaWiki funziona anche con [{{int:version-db-mariadb-url}} MariaDB] e [{{int:version-db-percona-url}} Percona Server], che sono compatibili con MySQL.([http://www.php.net/manual/en/mysqli.installation.php Come compilare PHP con supporto MySQL])",
+       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] è un popolare sistema di database open source come alternativa a MySQL. Ci possono essere alcuni bug minori in sospeso, e non è raccomandato per l'uso in un ambiente di produzione. ([http://www.php.net/manual/en/pgsql.installation.php Come compilare PHP con supporto PostgreSQL])",
+       "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite]  è un sistema di database leggero, che è supportato molto bene. ([http://www.php.net/manual/en/pdo.installation.php Come compilare PHP con supporto SQLite], utilizza PDO)",
+       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] è un database di un'impresa commerciale. ([http://www.php.net/manual/en/oci8.installation.php Come compilare PHP con supporto OCI8])",
+       "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] è un database di un'impresa commerciale per Windows. ([http://www.php.net/manual/en/sqlsrv.installation.php Come compilare PHP con supporto SQLSRV])",
        "config-header-mysql": "Impostazioni MySQL",
        "config-header-postgres": "Impostazioni PostgreSQL",
        "config-header-sqlite": "Impostazioni SQLite",
        "config-postgres-old": "PostgreSQL $1 o una versione successiva è necessaria, rilevata la $2.",
        "config-mssql-old": "Si richiede Microsoft SQL Server $1 o successivo. Tu hai la versione $2.",
        "config-sqlite-name-help": "Scegli un nome che identifichi il tuo wiki.\nNon utilizzare spazi o trattini.\nQuesto servirà per il nome del file di dati SQLite.",
+       "config-sqlite-parent-unwritable-group": "Non è possibile creare la directory dati <code><nowiki>$1</nowiki></code>, perché la directory superiore <code><nowiki>$2</nowiki></code> non è scrivibile dal webserver.\n\nIl programma di installazione ha determinato l'utente con cui il server web è in esecuzione.\nForniscigli la possibilità di scrivere nella directory <code><nowiki>$3</nowiki></code> per continuare.\nSu un sistema Unix/Linux:\n\n<pre>cd $2\nmkdir $3\nchgrp $4 $3\nchmod g+w $3</pre>",
+       "config-sqlite-parent-unwritable-nogroup": "Non è possibile creare la directory dati <code><nowiki>$1</nowiki></code>, perché la directory superiore <code><nowiki>$2</nowiki></code> non è scrivibile dal webserver.\n\nIl programma di installazione non ha potuto determinare l'utente con cui il server web è in esecuzione.\nFornisci ad esso (ed altri!) la possibilità di scrivere globalmente nella directory <code><nowiki>$3</nowiki></code> per continuare.\nSu un sistema Unix/Linux:\n\n<pre>cd $2\nmkdir $3\nchmod a+w $3</pre>",
        "config-sqlite-mkdir-error": "Errore durante la creazione della directory dati \"$1\".\nControlla la posizione e riprova.",
        "config-sqlite-dir-unwritable": "Impossibile scrivere nella directory \"$1\".\nModifica le autorizzazioni in modo che il webserver possa scrivere in essa e riprova.",
        "config-sqlite-connection-error": "$1.\n\nControlla la directory dati e il nome del database qui sotto, poi riprova.",
        "config-mysql-engine": "Storage engine:",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
+       "config-mysql-myisam-dep": "<strong>Attenzione:</strong> hai selezionato MyISAM come motore di archiviazione per MySQL, che non è raccomandato per l'uso con  MediaWiki, perché:\n* supporta debolmente la concorrenza per il blocco della tabella\n* è più incline alla corruzione di altri motori\n* il codice di base MediaWiki non gestisce sempre MyISAM come dovrebbe\n\nSe la tua installazione MySQL supporta InnoDB, è altamente raccomandato che lo si scelga al suo posto.\nSe la tua installazione MySQL non supporta InnoDB, forse è il momento per un aggiornamento.",
+       "config-mysql-only-myisam-dep": "<strong>Attenzione:</strong> MyISAM è l'unico motore di archiviazione disponibile per MySQL su questa macchina, e questo non è consigliato per l'uso con MediaWiki, perché:\n* supporta debolmente la concorrenza per il blocco della tabella\n* è più incline alla corruzione di altri motori\n* il codice di base MediaWiki non gestisce sempre MyISAM come dovrebbe\n\nSe la tua installazione MySQL non supporta InnoDB, forse è il momento per un aggiornamento.",
+       "config-mysql-engine-help": "<strong>InnoDB</strong> è quasi sempre l'opzione migliore, in quanto ha un buon supporto della concorrenza.\n\n<strong>MyISAM</strong> potrebbe essere più veloce nelle installazioni monoutente o in sola lettura.\nI database MyISAM tendono a danneggiarsi più spesso dei database InnoDB.",
        "config-mysql-charset": "Set di caratteri del database:",
        "config-mysql-binary": "Binario",
        "config-mysql-utf8": "UTF-8",
+       "config-mysql-charset-help": "In <strong>modalità binaria</strong>, MediaWiki archivia il testo UTF-8 nel database in cambi binari.\nQuesto è più efficiente rispetto alla modalità UTF-8 di MySQL, e consente di utilizzare la gamma completa di caratteri Unicode.\n\nIn <strong>modalità UTF-8</strong>, MySQL conoscerà in quale set di caratteri sono i tuoi dati, e può presentarli e convertirli in modo appropriato, ma non ti permetterà di memorizzare i caratteri al di sopra del [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane].",
        "config-mssql-auth": "Tipo di autenticazione:",
+       "config-mssql-install-auth": "Seleziona il tipo di autenticazione che verrà utilizzato per connettersi al database durante il processo di installazione.\nSe si seleziona \"{{int:config-mssql-windowsauth}}\", saranno utilizzate le credenziali dell'utente con cui viene eseguito il server web, qualunque esso sia.",
+       "config-mssql-web-auth": "Seleziona il tipo di autenticazione che il server web utilizzerà per connettersi al database, durante il normale funzionamento del wiki.\nSe si seleziona \"{{int:config-mssql-windowsauth}}\", saranno utilizzate le credenziali dell'utente con cui viene eseguito il server web, qualunque esso sia.",
        "config-mssql-sqlauth": "Autenticazione di SQL Server",
        "config-mssql-windowsauth": "Autenticazione di Windows",
        "config-site-name": "Nome del wiki:",
        "config-ns-site-name": "Stesso nome del wiki: $1",
        "config-ns-other": "Altro (specificare)",
        "config-ns-other-default": "MyWiki",
+       "config-project-namespace-help": "Seguendo l'esempio di Wikipedia, molti wiki tengono le loro pagine con le regole separate dalle pagine di contenuto, in un \"'''namespace di progetto'''\".\nTutti i titoli delle pagine in questo namespace iniziano con un certo prefisso, che puoi indicare qui.\nSolitamente, questo prefisso deriva dal nome del wiki, ma non può contenere caratteri di punteggiatura come \"#\" o \":\".",
+       "config-ns-invalid": "Il namespace indicato \"<nowiki>$1</nowiki>\" non è valido.\nSpecificare un diverso namespace di progetto.",
+       "config-ns-conflict": "Il namespace indicato \"<nowiki>$1</nowiki>\" è in conflitto con un namespace predefinito MediaWiki.\nSpecificare un diverso namespace di progetto.",
        "config-admin-box": "Account amministratore",
        "config-admin-name": "Il tuo nome utente:",
        "config-admin-password": "Password:",
        "config-admin-name-invalid": "Il nome utente specificato \"<nowiki>$1</nowiki>\" non è valido.\nSpecificare un nome utente diverso.",
        "config-admin-password-blank": "Inserisci una password per l'account di amministratore.",
        "config-admin-password-mismatch": "Le password inserite non coincidono tra loro.",
-       "config-admin-email": "Indirizzo e-mail:",
+       "config-admin-email": "Indirizzo email:",
        "config-admin-email-help": "Inserisci qui un indirizzo email per poter ricevere email dagli altri utenti del wiki, reimpostare la tua password, ed essere informato delle modifiche apportate alle pagine tuoi osservati speciali. Se non ti interessa, puoi lasciare vuoto questo campo.",
        "config-admin-error-user": "Errore interno durante la creazione di un amministratore con il nome \"<nowiki>$1</nowiki>\".",
        "config-admin-error-password": "Errore interno durante l'impostazione di una password per amministratore \"<nowiki>$1</nowiki>\": <pre>$2</pre>",
        "config-profile-wiki": "Wiki aperto",
        "config-profile-no-anon": "Creazione utenza obbligatoria",
        "config-profile-fishbowl": "Solo editori autorizzati",
-       "config-profile-private": "Wiki privata",
+       "config-profile-private": "Wiki privato",
+       "config-profile-help": "I wiki funzionano meglio se si lascia che molte persone li possano modificare.\nIn MediaWiki, è semplice rivedere le ultime modifiche, e ripristinare i danni causati da utenti ingenui o malintenzionati.\n\nTuttavia, molti hanno trovato MediaWiki essere utile in un'ampia varietà di ruoli, e a volte non è facile convincere tutti i vantaggi della modalità wiki.\nPerciò, fai la tua scelta.\n\nIl modello <strong>{{int:config-profile-wiki}}</strong> consente a chiunque di modificare, anche senza effettuare l'accesso.\nUn wiki con <strong>{{int:config-profile-no-anon}}</strong> offre una maggiore responsabilità, ma potrebbe scoraggiare i contributori occasionali.\n\nLo scenario <strong>{{int:config-profile-fishbowl}}</strong> consente agli utenti autorizzati di modificare, ma il pubblico può visualizzare le pagine, compresa la cronologia.\nUn <strong>{{int:config-profile-private}}</strong> consente solo agli utenti autorizzati di visualizzare le pagine, lo stesso gruppo può modificarle.\n\nConfigurazioni di diritti utente più complesse sono disponibili dopo l'installazione, vedi la  [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights parte relativa del manuale].",
        "config-license": "Copyright e licenza:",
        "config-license-none": "Nessun piè di pagina per la licenza",
        "config-license-cc-by-sa": "Creative Commons Attribuzione-Condividi allo stesso modo",
        "config-license-gfdl": "GNU Free Documentation License 1.3 o versioni successive",
        "config-license-pd": "Pubblico dominio",
        "config-license-cc-choose": "Seleziona una delle licenze Creative Commons",
-       "config-license-help": "Molti wiki pubblici rilasciano i loro contributi con una [http://freedomdefined.org/Definition licenza libera]. Questo aiuta a creare un senso di proprietà condivisa nella comunità e incoraggia a contribuire a lungo termine. Non è generalmente necessario per un wiki privato o aziendale.\n\nSe vuoi usare testi da Wikipedia, o desideri che Wikipedia possa essere in grado di accettare testi copiati dal tuo wiki, dovresti scegliere '''Creative Commons Attribution Share Alike'''.\n\nIn precedenza Wikipedia ha utilizzato la GNU Free Documentation License. La GFDL è una licenza valida, ma è di difficile comprensione e complica il riutilizzo dei contenuti.",
+       "config-license-help": "Molti wiki pubblici rilasciano i loro contributi con una [http://freedomdefined.org/Definition licenza libera]. Questo aiuta a creare un senso di proprietà condivisa nella comunità e incoraggia a contribuire a lungo termine. Non è generalmente necessario per un wiki privato o aziendale.\n\nSe vuoi usare testi da Wikipedia, o desideri che Wikipedia possa essere in grado di accettare testi copiati dal tuo wiki, dovresti scegliere <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nIn precedenza Wikipedia ha utilizzato la GNU Free Documentation License. La GFDL è una licenza valida, ma è di difficile comprensione e complica il riutilizzo dei contenuti.",
        "config-email-settings": "Impostazioni email",
        "config-enable-email": "Abilita la posta elettronica in uscita",
+       "config-enable-email-help": "Se vuoi che funzionino le email, le [http://www.php.net/manual/en/mail.configuration.php PHP's impostazioni della posta] devono essere configurate correttamente.\nSe non si desidera alcuna funzionalità di posta elettronica, puoi disabilitarla qui.",
        "config-email-user": "Abilita invio email fra utenti",
        "config-email-user-help": "Consente a tutti gli utenti di inviarsi a vicenda email, se lo hanno abilitato nelle loro preferenze.",
        "config-email-usertalk": "Abilita le notifiche per le pagine di discussione utente",
        "config-email-watchlist": "Abilita le notifiche per gli osservati speciali",
        "config-email-watchlist-help": "Consente agli utenti di ricevere notifiche per pagine tra gli osservati speciali, se lo hanno abilitato nelle loro preferenze.",
        "config-email-auth": "Abilita autenticazione via email",
+       "config-email-auth-help": "Se questa opzione è attivata, gli utenti dovranno confermare il loro indirizzo email utilizzando un collegamento che viene inviato ogni volta che lo impostano o lo modificano.\nSolo gli indirizzi di posta elettronica autenticati possono ricevere email da altri utenti o modificare le email di notifica.\nImpostare questa opzione è <strong>raccomandato</strong> per wiki pubblici a causa del potenziale abuso delle funzioni di posta elettronica.",
        "config-email-sender": "Indirizzo email di ritorno:",
+       "config-email-sender-help": "Inserisci l'indirizzo email da utilizzare come indirizzo di ritorno per la posta in uscita.\nQuesto è dove verranno inviati gli eventuali errori.\nMolti server di posta richiedono che almeno la parte del nome di dominio sia valido.",
        "config-upload-settings": "Caricamenti di immagini e file",
        "config-upload-enable": "Consentire il caricamento di file",
+       "config-upload-help": "Il caricamento di file può potenzialmente esporre il tuo server a rischi di sicurezza.\nPer ulteriori informazioni, leggi la  [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security sezione sulla sicurezza] nel manuale.\n\nPer consentire il caricamento di file, modificare la modalità nella sottodirectory <code>images</code> della directory principale di MediaWiki affinché il server web possa scriverci.\nPoi attivare questa opzione.",
        "config-upload-deleted": "Directory per i file cancellati:",
        "config-upload-deleted-help": "Scegli una directory in cui archiviare i file cancellati.\nIdealmente, questa non dovrebbe essere accessibile dal web.",
        "config-logo": "URL del logo:",
        "config-logo-help": "La skin predefinita di MediaWiki include lo spazio per un logo di 135 x 160 pixel sopra il menu laterale.\nCarica un'immagine di dimensioni appropriate e inserisci l'URL qui.\n\nÈ possibile utilizzare <code>$wgStylePath</code> o <code>$wgScriptPath</code> se il logo è relativo a tali percorsi.\n\nSe non si desidera un logo, lascia vuota questa casella.",
        "config-instantcommons": "Abilita Instant Commons",
+       "config-instantcommons-help": "[//www.mediawiki.org/wiki/InstantCommons Instant Commons] è una funzionalità che consente ai wiki di usare immagini, suoni e altri file multimediali che trovate sul sito [//commons.wikimedia.org/ Wikimedia Commons].\nPer fare questo, MediaWiki richiede l'accesso a Internet.\n\nPer ulteriori informazioni su questa funzionalità, incluse le istruzioni su come configurarlo per wiki diversi da Wikimedia Commons, consultare [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgForeignFileRepos il manuale].",
        "config-cc-error": "Il selettore di licenze Creative Commons non ha dato alcun risultato.\nInserisci manualmente il nome della licenza.",
        "config-cc-again": "Seleziona di nuovo...",
        "config-cc-not-chosen": "Scegliere quale licenza Creative Commons si desidera e cliccare su \"procedi\".",
        "config-memcache-badport": "I numeri di porta per memcached dovrebbero essere tra $1 e $2.",
        "config-extensions": "Estensioni",
        "config-extensions-help": "Le estensioni elencate sopra sono state rilevate nella tua directory <code>./extensions</code>.\n\nQueste potrebbero richiedere ulteriore configurazione, ma è possibile attivarle ora",
+       "config-skins": "Skin",
+       "config-skins-help": "Le skin elencate sopra sono state rilevate nella tua directory <code>./skins</code>. Devi attivarne almeno una e scegliere quella predefinita.",
+       "config-skins-use-as-default": "Usa questa skin come predefinita",
+       "config-skins-missing": "Non è stata trovata alcuna skin, MediaWiki userà una soluzione di ripiego finché non ne installerai una appropriata.",
+       "config-skins-must-enable-some": "Devi scegliere almeno una skin da attivare.",
+       "config-skins-must-enable-default": "La skin scelta come predefinita deve essere attivata.",
        "config-install-alreadydone": "'''Attenzione:''' sembra che hai già installato MediaWiki e stai tentando di installarlo nuovamente.\nProcedi alla pagina successiva.",
        "config-install-begin": "Premendo \"{{int:config-continue}}\", si avvierà l'installazione di MediaWiki.\nSe prima desideri apportare altre modifiche, premi \"{{int:config-back}}\".",
        "config-install-step-done": "fatto",
        "config-install-pg-plpgsql": "Controllo il linguaggio PL/pgSQL",
        "config-pg-no-plpgsql": "È necessario installare il linguaggio PL/pgSQL nel database $1",
        "config-pg-no-create-privs": "L'account indicato per l'installazione non dispone dei permessi necessari per creare un'utenza.",
+       "config-pg-not-in-role": "L'account indicato per l'utente web esiste già.\nL'account indicato per l'installazione non è un utente avanzato e non è un membro del ruolo degli utente web, quindi non è in grado di creare oggetti di proprietà dell'utente web.\n\nMediaWiki attualmente richiede che le tabelle siano di proprietà dell'utente web. Indica un altro account web, o fai click su  \"indietro\" e specifica un utente per l'installazione opportunamente privilegiato.",
        "config-install-user": "Creazione di utente del database",
        "config-install-user-alreadyexists": "L'utente \"$1\" è già presente",
        "config-install-user-create-failed": "Creazione dell'utente \"$1\" non riuscita: $2",
        "config-install-stats": "Inizializzazione delle statistiche",
        "config-install-keys": "Generazione delle chiavi segrete",
        "config-insecure-keys": "'''Attenzione:''' {{PLURAL:$2|Una chiave sicura|Delle chiavi sicure}} ($1) {{PLURAL:$2|generata|generate}} durante l'installazione non {{PLURAL:$2|è|sono}} completamente {{PLURAL:$2|sicura|sicure}}. Considera di {{PLURAL:$2|cambiarla|cambiarle}} manualmente.",
+       "config-install-updates": "Impedire l'esecuzione di aggiornamenti non necessari",
+       "config-install-updates-failed": "<strong>Errore:</strong> l'inserimento delle chiavi di aggiornamento nelle tabelle non è riuscito con il seguente errore: $1",
        "config-install-sysop": "Creazione dell'account utente per l'amministratore",
        "config-install-subscribe-fail": "Impossibile sottoscrivere mediawiki-announce: $1",
        "config-install-subscribe-notpossible": "cURL non è installato e <code>allow_url_fopen</code> non è disponibile.",
index 02ff624..21fcb9d 100644 (file)
@@ -11,7 +11,9 @@
                        "Whym",
                        "Yanajin66",
                        "青子守歌",
-                       "아라"
+                       "아라",
+                       "Shield-9",
+                       "Takot"
                ]
        },
        "config-desc": "MediaWiki のインストーラー",
@@ -56,7 +58,7 @@
        "config-env-good": "環境を確認しました。\nMediaWiki をインストールできます。",
        "config-env-bad": "環境を確認しました。\nMediaWiki のインストールはできません。",
        "config-env-php": "PHP $1がインストールされています。",
-       "config-env-php-toolow": "PHP $1 がインストールされています。\nしかし、MediaWikiには PHP $2 以上が必要です。",
+       "config-env-hhvm": "HHVM $1 がインストールされています。",
        "config-unicode-using-utf8": "Unicode正規化に、Brion Vibberのutf8_normalize.soを使用。",
        "config-unicode-using-intl": "Unicode正規化に[http://pecl.php.net/intl intl PECL 拡張機能]を使用。",
        "config-unicode-pure-php-warning": "<strong>警告:</strong> Unicode 正規化の処理に [http://pecl.php.net/intl intl PECL 拡張機能]を利用できないため、処理が遅いピュア PHP の実装を代わりに使用しています。\n高トラフィックのサイトを運営する場合は、[//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode 正規化]をお読みください。",
@@ -64,7 +66,8 @@
        "config-no-db": "適切なデータベース ドライバーが見つかりませんでした! PHP にデータベース ドライバーをインストールする必要があります。\n以下の種類のデータベースに対応しています: $1\n\nPHP を自分でコンパイルした場合は、例えば <code>./configure --with-mysqli</code> を実行して、データベース クライアントを使用できるように再設定してください。\nDebian または 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": "<strong>警告: PHP の <code>[http://php.net/register_globals register_globals]</code> オプションが有効になっています。\n可能なら無効化してください。</strong>\nMediaWiki は動作しますが、サーバーの潜在的なセキュリティ脆弱性が露呈されます。",
+       "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 のインストールや使用はできません。",
@@ -75,6 +78,7 @@
        "config-memory-raised": "PHPの<code>memory_limit</code>は$1で、$2に引き上げられました。",
        "config-memory-bad": "<strong>警告:</strong> PHPの<code>memory_limit</code>に$1に設定されています。\nこの値はおそらく小さすぎます。\nインストールが失敗するおそれがあります!",
        "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-xcache": "[http://xcache.lighttpd.net/ XCache] がインストール済み",
        "config-apc": "[http://www.php.net/apc APC] がインストール済み",
@@ -92,6 +96,7 @@
        "config-using-server": "サーバー名「<nowiki>$1</nowiki>」を使用しています。",
        "config-using-uri": "サーバー URL「<nowiki>$1$2</nowiki>」を使用しています。",
        "config-uploads-not-safe": "<strong>警告:</strong> アップロードの既定ディレクトリ <code>$1</code> に、任意のスクリプト実行に関する脆弱性があります。\nMediaWiki はアップロードされたファイルのセキュリティ上の脅威を確認しますが、アップロードを有効化する前に、[//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security このセキュリティ上の脆弱性を解決する]ことを強く推奨します。",
+       "config-no-cli-uploads-check": "<strong>警告:</strong> アップロード用のデフォルトディレクトリ (<code>$1</code>) が、CLIでのインストール中に任意のスクリプト実行の脆弱性チェックを受けていません。",
        "config-brokenlibxml": "このシステムで使われているPHPとlibxml2のバージョンのこの組み合わせにはバグがあります。具体的には、MediaWikiやその他のウェブアプリケーションでhiddenデータが破損する可能性があります。\nlibxml2を2.7.3以降のバージョンにアップグレードしてください([//bugs.php.net/bug.php?id=45996 PHPでのバグ情報])。\nインストールを終了します。",
        "config-suhosin-max-value-length": "Suhosin がインストールされており、GET パラメーターの <code>length</code> を $1 バイトに制限しています。\nMediaWiki の ResourceLoader コンポーネントはこの制限を回避しますが、パフォーマンスは低下します。\n可能な限り、<code>php.ini</code> で <code>suhosin.get.max_value_length</code> を 1024 以上に設定し、同じ値を <code>LocalSettings.php</code> 内で <code>$wgResourceLoaderMaxQueryLength</code> に設定してください。",
        "config-db-type": "データベースの種類:",
        "config-db-name": "データベース名:",
        "config-db-name-help": "このウィキを識別する名前を入力してください。\n空白を含めることはできません。\n\n共有ウェブホストを利用している場合、ホスティングプロバイダーが特定の使用可能なデータベース名を提供するか、あるいは管理パネルからデータベースを作成できるようにしているでしょう。",
        "config-db-name-oracle": "データベースのスキーマ:",
+       "config-db-account-oracle-warn": "バックエンドのデータベースとして Oracle をインストールする場合、3つのシナリオが考えられます。\n\nデータベース用のアカウントをインストールのプロセス途中で作成したい場合、インストールに使うデータベース用のアカウントしては SYSDBAロール付きのアカウントを指定し、ウェブアクセス用アカウントには必要なログイン情報を指定してください。あるいは、ウェブアクセス用のアカウントを手動で作成して、そのアカウント(スキーマオブジェクトの作成のパーミッションを要求する場合)だけを使うか、二つの異なるアカウントを用意して一つは特権を付与できるもの、もう一つをウェブアクセス用の制限アカウントとしてください。\n\n要求された特権でアカウントを作成するスクリプトは、このインストール環境では、\"maintenance/oracle/\" にあります。制限アカウントを使用することは、デフォルトアカウントでのすべてのメンテナンス特権を無効にすることにご注意ください。",
        "config-db-install-account": "インストールで使用する利用者アカウント",
        "config-db-username": "データベースのユーザー名:",
        "config-db-password": "データベースのパスワード:",
        "config-type-postgres": "PostgreSQL",
        "config-type-sqlite": "SQLite",
        "config-type-oracle": "Oracle",
+       "config-type-mssql": "マイクロソフト 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/ja/mysqli.installation.php PHPをMySQLサポート付きでコンパイルする方法])",
        "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] は、MySQLの代替として人気があるオープンソースのデータベースシステムです。細部の未解消バグがある場合があるため、プロダクション環境での使用は推奨されません。 ([http://www.php.net/manual/en/pgsql.installation.php PHPをPostgreSQLサポート付きでコンパイルする方法])",
        "config-invalid-db-prefix": "「$1」は無効なデータベース接頭辞です。\n半角の英数字 (a-z、A-Z、0-9)、アンダースコア (_)、ハイフン (-) のみを使用してください。",
        "config-connection-error": "$1。\n\n以下のホスト名、ユーザー名、パスワードを確認してから再度試してください。",
        "config-invalid-schema": "「$1」は MediaWiki のスキーマとして無効です。\n半角の英数字 (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": "Microsoft SQL Server $1 以降が必要です。ご使用中の Microsoft SQL Server は $2 です。",
        "config-mysql-engine": "ストレージ エンジン:",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
+       "config-mysql-myisam-dep": "<strong>警告:</strong> MySQLのストレージエンジンとして MyISAM を選択していますが、これをMediaWikiで利用するのは推奨されていません。その理由は: \n* テーブルロックによる並列性をほとんどサポートしていない\n* 他のエンジンに比べて壊れやすい\n* MediaWiki のコードベースは必ずしも MyISAM を本来あるべきほどには扱っていない\n\nあなたがインストールした MySQL が InnoDB をサポートしている場合、代わりにそちらをお使いになることを強くお勧めします。\nあなたがインストールした MySQL が InnoDB をサポートしていない場合、アップグレードした方がいいでしょう。",
+       "config-mysql-only-myisam-dep": "<strong>警告:</strong> MyISAM がこのマシンの MySQL の唯一のストレージエンジンですが、これをMediaWikiで利用するのは推奨されていません。その理由は: \n* テーブルロックによる並列性をほとんどサポートしていない\n* 他のエンジンに比べて壊れやすい\n* MediaWiki のコードベースは必ずしも MyISAM を本来あるべきほどには扱っていない\n\nあなたがインストールした MySQL が InnoDB をサポートしていない場合、アップグレードした方がいいでしょう。",
        "config-mysql-engine-help": "<strong>InnoDB</strong>は、並行処理のサポートに優れているので、ほとんどの場合において最良の選択肢です。\n\n<strong>MyISAM</strong>は、利用者が1人の場合、あるいは読み込み専用でインストールする場合に、より処理が早くなるでしょう。\nただし、MyISAMのデータベースは、InnoDBより高頻度で破損する傾向があります。",
        "config-mysql-charset": "データベースの文字セット:",
        "config-mysql-binary": "バイナリ",
        "config-ns-other-default": "マイウィキ",
        "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-error-bademail": "無効なメールアドレスを入力しました。",
        "config-subscribe": "[https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce リリース告知のメーリングリスト]を購読する。",
        "config-subscribe-help": "これは、リリースの告知 (重要なセキュリティに関する案内を含む) に使用される、流量が少ないメーリングリストです。\nこのメーリングリストを購読して、新しいバージョンが出た場合にMediaWikiを更新してください。",
+       "config-subscribe-noemail": "メールアドレスなしでリリースアナウンスのメーリングリストを購読しようとしています。\nメーリングリストを購読する場合にはメールアドレスを入力してください。",
        "config-almost-done": "これでほぼ終わりました!\n残りの設定を飛ばして、ウィキを今すぐインストールできます。",
        "config-optional-continue": "私にもっと質問してください。",
        "config-optional-skip": "もう飽きてしまったので、とにかくウィキをインストールしてください。",
        "config-license-gfdl": "GNU フリー文書利用許諾契約書 1.3 以降",
        "config-license-pd": "パブリック・ドメイン",
        "config-license-cc-choose": "その他のクリエイティブ・コモンズ・ライセンスを選択する",
-       "config-license-help": "多くの公開ウィキでは、すべての寄稿物が[http://freedomdefined.org/Definition フリーライセンス]のもとに置かれています。\nこうすることにより、コミュニティによる共有の感覚が生まれ、長期的な寄稿が促されます。\n私的ウィキや企業のウィキでは、通常、フリーライセンスにする必要はありません。\n\nウィキペディアにあるテキストをあなたのウィキで利用し、逆にあなたのウィキにあるテキストをウィキペディアに複製することを許可したい場合には、<strong>クリエイティブ・コモンズ 表示-継承</strong>を選択するべきです。\n\nウィキペディアは以前、GNUフリー文書利用許諾契約書(GFDL)を使用していました。\nGFDLは有効なライセンスですが、内容を理解するのは困難です。\nまた、GFDLのもとに置かれているコンテンツの再利用も困難です。",
+       "config-license-help": "多くの公開ウィキでは、すべての寄稿物が[http://freedomdefined.org/Definition フリーライセンス]のもとに置かれています。\nこうすることにより、コミュニティによる共有の感覚が生まれ、長期的な寄稿が促されます。\n私的ウィキや企業のウィキでは、通常、フリーライセンスにする必要はありません。\n\nウィキペディアにあるテキストをあなたのウィキで利用し、逆にあなたのウィキにあるテキストをウィキペディアに複製することを許可したい場合には、<strong>{{int:config-license-cc-by-sa}}</strong>を選択するべきです。\n\nウィキペディアは以前、GNUフリー文書利用許諾契約書(GFDL)を使用していました。\nGFDLは有効なライセンスですが、内容を理解するのは困難です。\nまた、GFDLのもとに置かれているコンテンツの再利用も困難です。",
        "config-email-settings": "メールの設定",
        "config-enable-email": "メール送信を有効にする",
        "config-enable-email-help": "メールを使用したい場合は、[http://www.php.net/manual/en/mail.configuration.php PHP のメール設定]が正しく設定されている必要があります。\nメールの機能を使用しない場合は、ここで無効にすることができます。",
        "config-cache-memcached": "memcached を使用 (追加の設定が必要)",
        "config-memcached-servers": "memcached サーバー:",
        "config-memcached-help": "Memcachedを使用するIPアドレスの一覧。\nカンマ区切りで、利用する特定のポートの指定が必要です。例:\n127.0.0.1:11211\n192.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": "<code>./extensions</code> ディレクトリ内で、上に列挙した拡張機能を検出しました。\n\nこれらの拡張機能には追加の設定が必要な場合がありますが、今すぐ有効化できます。",
+       "config-skins": "外装",
+       "config-skins-help": "以上に挙げたスキンは<code>./skins</code>で検出されたものです。\n少なくともひとつを有効にして、デフォルトを選択してください。",
+       "config-skins-use-as-default": "この外装をデフォルトとして使う",
+       "config-skins-missing": "外装が見つかりませんでした。適切なものをいくつかインストールするまで、MediaWikiはフォールバック外装を使用します。",
+       "config-skins-must-enable-some": "少なくとも1つの有効化する外装を選択する必要があります。",
+       "config-skins-must-enable-default": "デフォルトとして選択された外装は有効である必要があります。",
        "config-install-alreadydone": "<strong>警告:</strong> 既にMediaWikiがインストール済みで、再びインストールし直そうとしています。\n次のページへ進んでください。",
        "config-install-begin": "「{{int:config-continue}}」を押すと、MediaWiki のインストールを開始できます。\n変更したい設定がある場合は、「{{int:config-back}}」を押してください。",
        "config-install-step-done": "実行",
        "config-install-pg-schema-not-exist": "PostgreSQL スキーマがありません。",
        "config-install-pg-schema-failed": "テーブルの作成に失敗しました。\n利用者「$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インストール用に指定したアカウントはスーパーユーザーでなく、またウェブユーザーのロールを持ったものでもありません。そのためウェブユーザーが所有するオブジェクトを作成することができません。\n\nMediaWikiは現状では、ウェブユーザーが所有するテーブルを要求します。別のウェブアカウント名を指定するか、「戻る」をクリックして適切な権限を持つインストール用ユーザーを指定してください。",
        "config-install-user": "データベースユーザーの作成",
        "config-install-user-alreadyexists": "ユーザー「$1」は既に存在します",
        "config-install-user-create-failed": "ユーザー「$1」の作成に失敗しました: $2",
        "config-install-interwiki-exists": "<strong>警告:</strong> ウィキ間テーブルは既に登録されているようです。\n既定のテーブルを無視します。",
        "config-install-stats": "統計情報の初期化",
        "config-install-keys": "秘密鍵の生成",
+       "config-insecure-keys": "<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これをダウンロードして、ウィキをインストールした基準ディレクトリ (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": "<strong>MediaWiki のインストールに成功しました。</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 のあなたの言語へのローカライズ]"
 }
index 0638452..bc828a5 100644 (file)
@@ -50,7 +50,6 @@
        "config-env-good": "환경이 확인되었습니다.\n미디어위키를 설치할 수 있습니다.",
        "config-env-bad": "환경이 확인되었습니다.\n미디어위키를 설치할 수 없습니다.",
        "config-env-php": "PHP $1(이)가 설치되었습니다.",
-       "config-env-php-toolow": "PHP $1(이)가 설치되었습니다.\n하지만 미디어위키는 PHP $2 이상이 필요합니다.",
        "config-unicode-using-utf8": "유니코드 정규화에 Brion Vibber의 utf8_normalize.so를 사용합니다.",
        "config-unicode-using-intl": "유니코드 정규화에 [http://pecl.php.net/intl intl PECL 확장 기능]을 사용합니다.",
        "config-unicode-pure-php-warning": "'''경고''': 유니코드 정규화를 처리할 [http://pecl.php.net/intl intl PECL 확장 기능]을 사용할 수 없기 때문에 느린 pure-PHP 구현을 대신 사용합니다.\n트래픽이 높은 사이트에서 실행하시려면 [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations 유니코드 정규화]를 읽어보시기 바랍니다.",
@@ -58,7 +57,7 @@
        "config-no-db": "적절한 데이터베이스 드라이버를 찾을 수 없습니다! PHP용 데이터베이스 드라이버를 설치해야 합니다.\n다음 데이터베이스 유형을 지원합니다: $1.\n\nPHP를 직접 컴파일했다면, 예를 들어 <code>./configure --with-mysql</code>을 사용하여, 데이터베이스 클라이언트를 활성화하도록 다시 설정하세요.\n데비안이나 우분투 패키지에서 PHP를 설치했다면 <code>php5-mysql</code> 모듈도 설치해야 합니다.",
        "config-outdated-sqlite": "'''경고''': 최소인 $2 버전보다 낮은 SQLite $1(이)가 있습니다. SQLite를 사용할 수 없습니다.",
        "config-no-fts3": "'''경고''': SQLite를 [//sqlite.org/fts3.html FTS3 모듈] 없이 컴파일하며, 검색 기능은 백엔드에 사용할 수 없습니다.",
-       "config-register-globals": "'''경고: PHP의 <code>[http://php.net/register_globals register_globals]</code> 옵션이 활성화되어 있습니다.'''\n'''가능하면 이를 비활성화하십시오.'''\n미디어위키는 작동하지만 서버에 잠재적인 보안 취약점이 노출됩니다.",
+       "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-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-license-gfdl": "GNU 자유 문서 사용 허가서 1.3 이상",
        "config-license-pd": "퍼블릭 도메인",
        "config-license-cc-choose": "다른 크리에이티브 커먼즈 라이선스 선택",
-       "config-license-help": "많은 공개 위키는 모든 기여를 [http://freedomdefined.org/Definition 자유 라이선스]에 따르도록 합니다.\n이렇게 하면 커뮤니티에 대한 소유권을 이해할 수 있도록 하고 장기적인 기여를 장려합니다.\n일반적으로 개인 또는 회사 위키에게는 필요하지 않습니다.\n\n위키백과의 텍스트를 사용할 수 있도록 하고 위키백과가 위키에서 복사한 텍스트를 사용할 수 있도록 원한다면 '''크리에이티브 커먼즈 저작자표시-동일조건변경허락'''으로 선택해야 합니다.\n\n위키백과는 이전에 GNU 자유 문서 사용 허가서(GFDL)를 사용했습니다.\nGFDL은 유효한 라이선스이지만 내용을 이해하기 어렵습니다.\nGFDL에 따라 사용이 허가된 내용을 재사용하는 것도 어렵습니다.",
+       "config-license-help": "많은 공개 위키는 모든 기여를 [http://freedomdefined.org/Definition 자유 라이선스]에 따르도록 합니다.\n이렇게 하면 커뮤니티에 대한 소유권을 이해할 수 있도록 하고 장기적인 기여를 장려합니다.\n일반적으로 개인 또는 회사 위키에게는 필요하지 않습니다.\n\n위키백과의 텍스트를 사용할 수 있도록 하고 위키백과가 위키에서 복사한 텍스트를 사용할 수 있도록 원한다면 <strong>{{int:config-license-cc-by-sa}}</strong>으로 선택해야 합니다.\n\n위키백과는 이전에 GNU 자유 문서 사용 허가서(GFDL)를 사용했습니다.\nGFDL은 유효한 라이선스이지만 내용을 이해하기 어렵습니다.\nGFDL에 따라 사용이 허가된 내용을 재사용하는 것도 어렵습니다.",
        "config-email-settings": "이메일 설정",
        "config-enable-email": "발신 이메일 활성화",
        "config-enable-email-help": "이메일을 작동하려면 [http://www.php.net/manual/en/mail.configuration.php PHP의 메일 설정]을 올바르게 설정해야 합니다.\n이메일 기능을 사용하지 않으려면 이를 비활성화할 수 있습니다.",
        "config-memcache-badport": "Memcached 포트 번호는 $1(와)과 $2 사이여야 합니다.",
        "config-extensions": "확장 기능",
        "config-extensions-help": "위에 나열된 확장 기능이 <code>./extensions</code>에서 발견되었습니다.\n\n추가적인 설정이 필요할 수 있습니다만 지금 활성화시킬 수 있습니다.",
+       "config-skins": "스킨",
+       "config-skins-use-as-default": "이 스킨을 기본값으로 사용",
+       "config-skins-must-enable-some": "적어도 활성화활 스킨 하나를 선택해야 합니다.",
+       "config-skins-must-enable-default": "기본값으로 설정한 스킨은 반드시 활성화해야 합니다.",
        "config-install-alreadydone": "'''경고:''' 이미 미디어위키를 설치했고 다시 설치하려고 합니다.\n다음 페이지로 진행하세요.",
        "config-install-begin": "\"{{int:config-continue}}\"을 누르면 미디어위키의 설치를 시작합니다.\n그래도 바꾸는 것을 원한다면 \"{{int:config-back}}\"를 누르세요.",
        "config-install-step-done": "완료",
index 08526f4..bb1c829 100644 (file)
        "config-env-good": "Den Environement gouf nogekuckt.\nDir kënnt MediaWiki installéieren.",
        "config-env-bad": "Den Environnement gouf iwwerpréift.\nDir kënnt MediWiki net installéieren.",
        "config-env-php": "PHP $1 ass installéiert.",
-       "config-env-php-toolow": "PHP $1 ass installéiert.\nAwer MediaWiki brauch PHP $2 oder méi héich.",
+       "config-env-hhvm": "HHVM $1 ass installéiert.",
        "config-unicode-using-utf8": "Fir d'Unicode-Normalisatioun gëtt dem Brion Vibber säin <code>utf8_normalize.so</code> benotzt.",
        "config-no-db": "Et konnt kee passenden Datebank-Driver fonnt ginn! Dir musst een Datebank-Driver fir PHP installéieren.\nDës Datebank-Type ginn ënnerstëtzt: $1.\n\nWann Dir PHP selwer compiléiert hutt, da rekonfiguréiert en mat dem ageschalten Datebank-Client, zum Beispill an deem Dir <code>./configure --with-mysql</code> benotzt.\nWann Dir PHP vun engem Debian oder Ubuntu Package aus installéiert hutt, da musst Dir och den php5-mysql Modul installéieren.",
        "config-outdated-sqlite": "'''Warnung:''' SQLite $1 ass installéiert. Allerdengs brauch MediaWiki SQLite $2 oder méi nei. SQLite ass dofir net disponibel.",
        "config-memory-bad": "'''Opgepasst:''' De Parameter <code>memory_limit</code> vu PHP ass $1.\nDat ass wahrscheinlech ze niddreg.\nD'Installatioun kéint net funktionéieren.",
+       "config-iconv": "<strong>Fatal:</strong> PHP muss mat Support fir d'[http://www.php.net/manual/en/iconv.installation.php iconv-Erweiderung] kompiléiert ginn.",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] ass installéiert",
        "config-apc": "[http://www.php.net/apc APC] ass installéiert",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] ass installéiert",
        "config-diff3-bad": "GNU diff3 gouf net fonnt.",
        "config-git": "D'Software Git fir d'Kontroll vu Versioune gouf fonnt: <code>$1</code>.",
+       "config-git-bad": "D'Software fir d'Kontroll vun de Versiounen 'Git' gouf net fonnt.",
        "config-no-uri": "'''Feeler:''' Déi aktuell URI konnt net festgestallt ginn.\nInstallatioun ofgebrach.",
        "config-using-server": "De Servernumm \"<nowiki>$1</nowiki>\" gëtt benotzt.",
        "config-using-uri": "D'Server URL  \"<nowiki>$1$2</nowiki>\" gëtt benotzt.",
        "config-missing-db-name": "Dir musst e Wäert fir \"{{int:config-db-name}}\" aginn",
        "config-missing-db-host": "Dir musst e Wäert fir \"{{int:config-db-host}}\" aginn.",
        "config-missing-db-server-oracle": "Dir musst e Wäert fir \"{{int:config-db-host-oracle}}\" aginn",
+       "config-connection-error": "$1.\n\nKuckt den Numm vum Server, de Benotzernumm an d'Passwuert no a probéiert et nach eng Kéier.",
        "config-db-sys-user-exists-oracle": "De Benotzerkont \"$1\" gëtt et schonn. SYSDBA kann nëmme benotzt gi fir en neie Benotzerkont opzemaachen.",
        "config-postgres-old": "PostgreSQL $1 oder eng méi nei Versioun gëtt gebraucht, Dir hutt $2.",
        "config-mssql-old": "Microsoft SQL Server $1 oder eng méi rezent Versioun gëtt gebraucht. Dir hutt d'Versioun $2.",
        "config-cc-again": "Nach eng kéier eraussichen...",
        "config-advanced-settings": "Erweidert Astellungen",
        "config-extensions": "Erweiderungen",
+       "config-skins": "Ausgesinn",
+       "config-skins-help": "D'Ausgesinn déi hei driwwer stinn goufen am Repertoire <code>./skins</code> fonnt. Dir musst mindestens eent aktivéieren an de Standard eraussichen.",
+       "config-skins-use-as-default": "Dëst Ausgesinn als Standard benotzen",
+       "config-skins-missing": "Et goufe keen Ausgesinn (Skin) fonnt; MediaWiki benotzt e Fallback-Ausgesinnbis Dir anerer installéiert.",
+       "config-skins-must-enable-some": "Dir musst mindestens een Ausgesinn fir z'aktivéieren eraussichen.",
+       "config-skins-must-enable-default": "Dat als Standard erausgesichten Ausgesinn muss aktivéiert sinn.",
        "config-install-step-done": "fäerdeg",
        "config-install-step-failed": "huet net funktionéiert",
        "config-install-extensions": "Mat den Ereiderungen",
        "config-install-interwiki-list": "De Fichier <code>interwiki.list</code> gouf net fonnt.",
        "config-install-stats": "Initialisatioun vun de Statistiken",
        "config-install-keys": "Generéiere vum Geheimschlëssel",
+       "config-install-updates": "Net néideg Aktualiséierungen net maachen",
        "config-install-sysop": "Administrateur Benotzerkont gëtt ugeluecht",
        "config-install-mainpage": "Haaptsäit mat Standard-Inhalt gëtt ugeluecht",
        "config-install-extension-tables": "D'Tabelle fir déi aktivéiert Erweiderunge ginn ugeluecht",
index 4b0c692..190ee04 100644 (file)
@@ -1,5 +1,10 @@
 {
-       "@metadata": [],
+       "@metadata": {
+               "authors": [
+                       "Jason924tw"
+               ]
+       },
+       "config-information": "文訊",
        "mainpagetext": "'''共筆臺已立'''",
        "mainpagedocfooter": "欲識維基,見[//meta.wikimedia.org/wiki/Help:Contents User's Guide]\n\n== 始 ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Configuration settings list]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]"
 }
index 7a6787b..8784521 100644 (file)
@@ -47,7 +47,7 @@
        "config-env-good": "Околината е проверена.\nМожете да го воспоставите МедијаВики.",
        "config-env-bad": "Околината е проверена.\nНе можете да го воспоставите МедијаВики.",
        "config-env-php": "PHP $1 е воспоставен.",
-       "config-env-php-toolow": "PHP $1 е воспоставен.\nМеѓутоа, МедијаВики бара PHP $2 или поново.",
+       "config-env-hhvm": "HHVM $1 е воспоставен.",
        "config-unicode-using-utf8": "Со utf8_normalize.so за уникодна нормализација од Брајон Вибер (Brion Vibber).",
        "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\nАко имате високопрометно мрежно место, тогаш ќе треба да прочитате повеќе за [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations уникодната нормализација].",
@@ -55,7 +55,8 @@
        "config-no-db": "Не можев да најдам соодветен двигател за базата на податоци! Ќе треба да воспоставите двигател за PHP-база.\nПоддржани се следниве видови бази: $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": "'''Предупредување: Можноста <code>[http://php.net/register_globals register_globals]</code> за PHP е овозможена.'''\n'''Оневозможете ја ако е можно.'''\nМедијаВики ќе работи, но опслужувачот ви е изложен на безбедносни ризици.",
+       "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Оваа можност мора да е исклучена. Во спротивно нема да можете да го воспоставите и користите МедијаВики.",
@@ -66,6 +67,7 @@
        "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-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-xcache": "[http://xcache.lighttpd.net/ XCache] е воспоставен",
        "config-apc": "[http://www.php.net/apc APC] е воспоставен",
        "config-license-gfdl": "ГНУ-ова лиценца за слободна документација 1.3 или понова",
        "config-license-pd": "Јавна сопственост",
        "config-license-cc-choose": "Одберете друга лиценца на Криејтив комонс по ваш избор",
-       "config-license-help": "Многу јавни викија ги ставаат сите придонеси под [http://freedomdefined.org/Definition слободна лиценца].\nСо ова се создава атмосфера на општа сопственост и поттикнува долгорочно учество.\nОва не е неопходно за викија на поединечни физички или правни лица.\n\nАко сакате да користите текст од Википедија, и сакате Википедија да прифаќа текст прекопиран од вашето вики, тогаш треба да ја одберете лиценцата '''Криејтив комонс НаведиИзвор СподелиПодИстиУслови'''.\n\nГНУ-овата лиценца за слободна документација (ГЛСД) е старата лиценца на Википедија.\nОваа лиценца сè уште важи, но е тешка за разбирање.\nИсто така треба да се има на ум дека пренамената на содржините под ГЛСД не е лесна.",
+       "config-license-help": "Многу јавни викија ги ставаат сите придонеси под [http://freedomdefined.org/Definition слободна лиценца].\nСо ова се создава атмосфера на општа сопственост и поттикнува долгорочно учество.\nОва не е неопходно за викија на поединечни физички или правни лица.\n\nАко сакате да користите текст од Википедија, и сакате Википедија да прифаќа текст прекопиран од вашето вики, тогаш треба да ја одберете лиценцата <strong>{{int:config-license-cc-by-sa}}</strong>..\n\nГНУ-овата лиценца за слободна документација (ГЛСД) е старата лиценца на Википедија.\nОваа лиценца сè уште важи, но е тешка за разбирање.\nИсто така треба да се има на ум дека пренамената на содржините под ГЛСД не е лесна.",
        "config-email-settings": "Нагодувања за е-пошта",
        "config-enable-email": "Овозможи излезна е-пошта",
        "config-enable-email-help": "Ако сакате да работи е-поштата, [http://www.php.net/manual/en/mail.configuration.php поштенските нагодувања на PHP] треба да се правилно наместени.\nАко воопшто не сакате никакви функции за е-пошта, тогаш можете да ги оневозможите тука.",
        "config-memcache-badport": "Бројките за портата на Memcached треба да бидат помеѓу $1 и $2",
        "config-extensions": "Додатоци",
        "config-extensions-help": "Во вашата папка <code>./extensions</code> беа востановени горенаведените додатоци.\n\nЗа ова може да треба дополнително нагодување, но можете да ги овозможите сега",
+       "config-skins": "Рува",
+       "config-skins-help": "Во вашата папка <code>./skins</code> се утврдени горенаведените рува. Ќе мора да овозможите барем едно и да го изберете основното.",
+       "config-skins-use-as-default": "Користи го како основно",
+       "config-skins-missing": "Не пронајдов ниедно руво. МедијаВики ќе користи резервно руво сè додека не воспоставите други.",
+       "config-skins-must-enable-some": "Ќе треба да изберете барем едно руво.",
+       "config-skins-must-enable-default": "Рувото што го избравте како основно мора да се овозможи.",
        "config-install-alreadydone": "'''Предупредување:''' Изгледа дека веќе го имате воспоставено МедијаВики и сега сакате да го воспоставите повторно.\nПродолжете на следната страница.",
        "config-install-begin": "Стискајќи на „{{int:config-continue}}“ ќе ја започнете воспоставката на МедијаВики.\nАко сакате да направите измени во досегашното, стиснете на „{{int:config-back}}“.",
        "config-install-step-done": "готово",
        "config-install-stats": "Ги подготвувам статистиките",
        "config-install-keys": "Создавање на тајни клучеви",
        "config-insecure-keys": "'''Предупредување:''' {{PLURAL:$2|Безбедносниот клуч $1 создаден во текот на воспоставката не е сосем безбеден|Безбедносните клучеви $1 создадени во текот на воспоставката не се сосем безбедни}}. Ви препорачуваме да {{PLURAL:$2|го|ги}} смените рачно.",
+       "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> не е достапно.",
index 26f1cc7..f9bcb91 100644 (file)
@@ -4,11 +4,12 @@
                        "Anakmalaysia",
                        "Pizza1016",
                        "SNN95",
-                       "MaxSem"
+                       "MaxSem",
+                       "Aviator"
                ]
        },
        "config-desc": "Pemasang MediaWiki",
-       "config-title": "Pasangan MediaWiki $1",
+       "config-title": "Pemasangan MediaWiki $1",
        "config-information": "Maklumat",
        "config-localsettings-upgrade": "Fail <code>LocalSettings.php</code> telah dikesan.\nUntuk menaik taraf pemasangan, sila masukkan nilai <code>$wgUpgradeKey</code> dalam kotak di bawah.\nAnda akan menjumpainya di <code>LocalSettings.php</code> .",
        "config-localsettings-cli-upgrade": "Fail <code>LocalSettings.php</code> telah dikesan.\nUntuk menaik taraf pemasangan, sila jalankan <code>update.php</code> sebaliknya",
@@ -16,7 +17,7 @@
        "config-localsettings-badkey": "Kunci yang anda berikan tidak betul.",
        "config-upgrade-key-missing": "Pemasangan yang sedia ada MediaWiki telah dikesan.\nUntuk menaik taraf pemasangan, Sila letakkan baris berikut di bahagian bawah <code>LocalSettings.php</code> anda:\n\n$1",
        "config-localsettings-incomplete": "<code>LocalSettings.php</code> sedia ada nampaknya tidak lengkap.\nPemboleh ubah $1 tidak disetkan.\nSila tukar <code>LocalSettings.php</code> supaya pemboleh ubah ini disetkan, dan klik \"{{int:Config-terus}}\".",
-       "config-localsettings-connection-error": "Ralat berlaku semasa semasa menyambung ke dalam pangkalan data yang menggunakan seting yang dinyatakan dalam <code>LocalSettings.php</code> atau <code>AdminSettings.php</code>. Sila betulkan tetapan ini dan cuba lagi.\n\n$1",
+       "config-localsettings-connection-error": "Ralat berlaku semasa menyambung ke pangkalan data dengan menggunakan tetapan yang dinyatakan dalam <code>LocalSettings.php</code>. Sila betulkan tetapan tersebut dan cuba lagi.\n\n$1",
        "config-session-error": "Ralat ketika memulakan sesi: $1",
        "config-session-expired": "Data sesi anda seolah-olah telah tamat tempoh.\nSesi dikonfigurasi untuk seumur hidup sebanyak $1.\nAnda boleh menambah ini dengan menetapkan <code>session.gc_maxlifetime</code> di php.ini.\nMemulakan semula proses pemasangan.",
        "config-no-session": "Data sesi anda telah hilang!\nSemak php.ini anda dan pastikan <code>session.save_path</code> disetkan kepada satu direktori yang sesuai.",
        "config-restart": "Ya, mula semula",
        "config-welcome": "=== Pemeriksaan persekitaran ===\nPemeriksaan asas kini boleh dilakukan untuk melihat jika persekitaran ini adalah sesuai untuk pemasangan MediaWiki.\nIngat untuk memasukkan maklumat ini jika anda mahukan sokongan tentang bagaimana untuk menyelesaikan pemasangan.",
        "config-copyright": "=== Hakcipta dan Syarat-Syarat ===\n\n$1\n\nProgram ini merupakan perisian bebas; anda boleh mengedarkannya semula dan/atau mengubahsuainya di bawah syarat-syarat Lesen Awam GNU seperti yang diterbitkan oleh Yayasan Perisian Bebas; sama ada versi 2 Lesen ini atau (mengikut pilihan anda) mana-mana versi selepas ini.\n\nProgram ini diedarkan dengan harapan bahawa ia akan menjadi berguna, tetapi '''tanpa sebarang waranti'''; tanpa jaminan yang tersirat '''kebolehdagangan''' atau '''kesesuaian untuk tujuan tertentu'''.\nLihat Lesen Awam GNU untuk maklumat lanjut.\n\nAnda sepatutnya telah menerima <doclink href=Copying> satu salinan Lesen Awam GNU </doclink> bersama-sama dengan program ini, jika tidak, menulis surat kepada Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA, atau [http://www.gnu.org/copyleft/gpl.html membacanya dalam talian].",
-       "config-sidebar": "* [//www.mediawiki.org Laman utama MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Panduan Pengguna]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents Panduan Pentadbir]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Soalan lazim]\n----\n* <doclink href=Readme>Baca saya</doclink>\n* <doclink href=ReleaseNotes>Nota keluaran</doclink>\n* <doclink href=Copying>Menyalin</doclink>\n* <doclink href=UpgradeDoc>Menaik taraf</doclink>",
+       "config-sidebar": "* [//www.mediawiki.org Laman utama MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Panduan Pengguna]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents Panduan Penyelia]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Soalan lazim]\n----\n* <doclink href=Readme>Baca saya</doclink>\n* <doclink href=ReleaseNotes>Nota keluaran</doclink>\n* <doclink href=Copying>Menyalin</doclink>\n* <doclink href=UpgradeDoc>Menaik taraf</doclink>",
        "config-env-good": "Persekitaran telah diperiksa.\nAnda boleh memasang MediaWiki.",
        "config-env-bad": "Persekitaran telah diperiksa. \nAnda tidak boleh memasang MediaWiki.",
        "config-env-php": "PHP $1 dipasang.",
-       "config-env-php-toolow": "PHP $1 dipasang.\nBagaimanapun, MediaWiki memerlukan PHP $2 ke atas.",
        "config-unicode-using-utf8": "utf8_normalize.so oleh Brion Vibber digunakan untuk penormalan Unicode.",
        "config-unicode-using-intl": "[http://pecl.php.net/intl Sambungan intl PECL] digunakan untuk penormalan Unicode.",
        "config-unicode-update-warning": "<strong>Amaran:</strong> Versi pembalut penormalan Unicode yang terpasang menggunakan perpustakaan [http://site.icu-project.org/ projek ICU] dalam versi yang lampau.\nAnda harus [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations menaik taraf] jika Unicode penting bagi anda.",
        "config-no-fts3": "<strong>Amaran:</strong> SQLite disusun tanpa [//sqlite.org/fts3.html modil FTS3], maka ciri-ciri pencarian tidak akan disediakan pada backend ini.",
-       "config-register-globals": "<strong>Amaran: Pilihan <code>[http://php.net/register_globals register_globals]</code> PHP dihidupkan.\nMatikannya jika boleh.</strong>\nMediaWiki boleh digunakan, tetapi pelayan anda akan terdedah kepada kemungkinan kerentanan keselamatan.",
        "config-mbstring": "<strong>Amaran keras: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] sedang aktif!</strong>\nOpsyen ini menyebabkan ralat dan mungkin mencemari data secara tanpa diduga.\nAnda tidak boleh memasang atau menggunakan MediaWiki melainkan opsyen ini dinyahdayakan.",
        "config-pcre-old": "<strong>Amaran keras:</strong> PCRE $1 ke atas diperlukan.\nBinari PHP anda berpaut dengan PCRE $2.\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE Keterangan lanjut].",
        "config-memory-bad": "<strong>Amaran:</strong> <code>memory_limit</code> (Had memori) PHP adalah $1.\nIni mungkin terlalu rendah.\nPemasangan mungkin akan gagal!",
        "config-ctype": "<strong>Amaran keras:</strong> PHP mesti disusun dengan sokongan untuk [http://www.php.net/manual/en/ctype.installation.php sambungan Ctype].",
+       "config-xcache": "[http://xcache.lighttpd.net/ XCache] dipasang",
+       "config-apc": "[http://www.php.net/apc APC] dipasang",
+       "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] dipasang",
+       "config-diff3-bad": "GNU diff3 tidak dijumpai.",
+       "config-git": "Perisian kawalan versi Git dijumpai: <code>$1</code>.",
+       "config-git-bad": "Perisian kawalan versi Git tidak dijumpai.",
        "config-no-cli-uri": "<strong>Amaran:</strong> Tiada <code>--scriptpath</code> dinyatakan, maka digunakannya yang asali: <code>$1</code>.",
+       "config-using-server": "Sedang menggunakan nama pelayan \"<nowiki>$1</nowiki>\".",
+       "config-using-uri": "Sedang menggunakan URL pelayan \"<nowiki>$1$2</nowiki>\".",
        "config-no-cli-uploads-check": "<strong>Amaran:</strong> Direktori asali anda untuk muat naikan (<code>$1</code>) belum diperiksa untuk kerentanan\nkepada pelaksanaan skrip yang menyeleweng sewaktu pemasangan CLI.",
+       "config-db-type": "Jenis pangkalan data:",
+       "config-db-host": "Hos pangkalan data:",
+       "config-db-host-oracle": "TNS pangkalan data:",
+       "config-db-name": "Nama pangkalan data:",
+       "config-db-name-oracle": "Skema pangkalan data:",
+       "config-db-username": "Nama pengguna pangkalan data:",
+       "config-db-password": "Kata laluan pangkalan data:",
+       "config-db-prefix": "Awalan jadual pangkalan data:",
        "config-db-charset": "Peranggu aksara pangkalan data",
+       "config-charset-mysql5-binary": "MySQL 4.1/5.0 dedua",
+       "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
+       "config-db-port": "Port pangkalan data:",
+       "config-db-schema": "Skema untuk MediaWiki:",
        "config-pg-test-error": "Tidak boleh bersambung dengan pangkalan data <strong>$1</strong>: $2",
+       "config-sqlite-dir": "Direktori data SQLite:",
+       "config-oracle-def-ts": "Ruang jadual lalai:",
+       "config-oracle-temp-ts": "Ruang jadual sementara:",
+       "config-type-mysql": "MySQL (atau yang serasi)",
        "config-header-mysql": "Keutamaan MySQL",
        "config-header-postgres": "Keutamaan PostgreSQL",
        "config-header-sqlite": "Keutamaan SQLite",
        "config-header-oracle": "Keutamaan Oracle",
+       "config-header-mssql": "Tetapan Microsoft SQL Server",
        "config-invalid-db-type": "Jenis pangkalan data tidak sah",
        "config-can-upgrade": "Terdapat jadual MediaWiki dalam pangkalan data ini. Untuk menaik tarafnya kepada MediaWiki $1, klik <strong>Teruskan</strong>.",
        "config-unknown-collation": "<strong>Amaran:</strong> Pangkalan data sedang menggunakan kolasi yang tidak dikenali.",
        "config-ns-other": "Lain-lain (nyatakan)",
        "config-ns-other-default": "MyWiki",
        "config-admin-box": "Akaun penyelia",
-       "config-admin-name": "Nama kamu:",
+       "config-admin-name": "Nama pengguna anda:",
        "config-admin-password": "Kata laluan:",
        "config-admin-password-confirm": "Kata laluan lagi:",
+       "config-admin-name-blank": "Masukkan nama pengguna pentadbir.",
        "config-admin-password-mismatch": "Kata-kata laluan yang kamu berikan tidak sepadan.",
        "config-admin-email": "Alamat e-mel:",
        "config-admin-error-bademail": "Kamu telah memberikan alamat e-mel yang tidak betul.",
        "config-optional-skip": "Saya sudah bosan, pasangkanlah wiki sahaja.",
+       "config-profile-wiki": "Wiki terbuka",
+       "config-profile-no-anon": "Pembukaan akaun diwajibkan",
+       "config-profile-private": "Wiki tertutup",
        "config-license": "Hak cipta dan lesen:",
        "config-license-none": "Tiada pengaki lesen",
        "config-license-cc-by-sa": "Creative Commons Attribution Share Alike",
        "config-install-step-done": "siap",
        "config-install-step-failed": "gagal",
        "config-install-user-alreadyexists": "Pengguna \"$1\" sudah wujud",
+       "config-install-tables": "Mencipta jadual",
        "config-install-tables-exist": "<strong>Amaran:</strong> Nampaknya sudah terdapat jadual MediaWiki. Penciptaan dilangkau.",
+       "config-install-interwiki": "Mengisi jadual antara wiki lalai",
+       "config-install-interwiki-list": "Fail <code>interwiki.list</code> tidak dapat dibaca.",
        "config-install-interwiki-exists": "<strong>Amaran:</strong> Jadual antara wiki nampaknya sudah ada entri. Senarai asali dilangkau.",
+       "config-install-keys": "Menjana kunci-kunci rahsia",
        "config-insecure-keys": "<strong>Amaran:</strong> {{PLURAL:$2|Kunci keselamatan|Kunci-kunci keselamatan}} ($1) yang dihasilkan sewaktu pemasangan itu {{PLURAL:$2|adalah}} tidak selamat sepenuhnya. Oleh itu, {{PLURAL:$2|ia}} wajar ditukar secara manual.",
+       "config-install-sysop": "Membuka akaun pengguna pentadbir",
+       "config-install-mainpage": "Mewujudkan laman utama dengan kandungan lalai",
        "config-help": "bantuan",
        "mainpagetext": "'''MediaWiki telah berjaya dipasang.'''",
        "mainpagedocfooter": "Sila rujuk [//meta.wikimedia.org/wiki/Help:Contents Panduan Penggunaan] untuk maklumat mengenai penggunaan perisian wiki ini.\n\n== Permulaan ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Senarai tetapan konfigurasi]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Soalan Lazim MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Senarai surat keluaran MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Terjemahkan MediaWiki ke dalam bahasa anda]"
index 0a84d87..262a837 100644 (file)
@@ -1,7 +1,8 @@
 {
        "@metadata": {
                "authors": [
-                       "Chrisportelli"
+                       "Chrisportelli",
+                       "Leli Forte"
                ]
        },
        "config-title": "Installazzjoni ta' MediaWiki $1",
@@ -30,6 +31,7 @@
        "config-page-existingwiki": "Wiki eżistenti",
        "config-restart": "Iva, erġa' ibda",
        "config-env-php": "PHP $1 huwa installat.",
+       "config-env-hhvm": "HHVM $1 hu installat.",
        "config-db-wiki-settings": "Identifika din il-wiki",
        "config-db-name": "Isem tad-databażi:",
        "config-db-install-account": "Kont tal-utent għall-installazzjoni",
        "config-site-name": "Isem tal-wiki:",
        "config-site-name-help": "Dan se jidher fil-barra tat-titlu tal-browżer u f'diversi postijiet oħra.",
        "config-site-name-blank": "Daħħal isem tas-sit.",
-       "config-project-namespace": "Spazju tal-isem tal-proġett:",
+       "config-project-namespace": "Spazju tal-ismijiet tal-proġett:",
        "config-ns-generic": "Proġett",
        "config-ns-site-name": "L-istess bħall-isem tal-wiki: $1",
        "config-ns-other": "Oħrajn (speċifika)",
        "config-ns-other-default": "MyWiki",
-       "config-ns-invalid": "L-ispazju speċifikat \"<nowiki>$1</nowiki>\" huwa ħażin.\nSpeċifika spazju tal-isem tal-proġett differenti.",
-       "config-ns-conflict": "L-ispazju speċifikat \"<nowiki>$1</nowiki>\" joħloq kunflitt ma' spazju tal-isem ieħor tal-MediaWiki.\nSpeċifika spazju tal-isem tal-proġett differenti.",
+       "config-ns-invalid": "L-ispazju speċifikat \"<nowiki>$1</nowiki>\" huwa ħażin.\nSpeċifika spazju tal-ismijiet ta' proġett differenti.",
+       "config-ns-conflict": "L-ispazju speċifikat \"<nowiki>$1</nowiki>\" joħloq kunflitt ma' spazju tal-ismijiet tal-MediaWiki predeterminat.\nSpeċifika spazju tal-ismijiet ta' proġett differenti.",
        "config-admin-box": "Kont tal-amministratur",
        "config-admin-name": "Ismek:",
        "config-admin-password": "Password:",
index 0bfcbe8..1cbe7d5 100644 (file)
@@ -4,6 +4,13 @@
                        "C.R."
                ]
        },
+       "config-desc": "'O prugramma d'istallazione 'e MediaWiki",
+       "config-title": "Installazione 'e MediaWiki $1",
+       "config-information": "Nfurmaziune",
+       "config-localsettings-upgrade": "È stato rilevato nu file <code>LocalSettings.php</code>.\nP'agghiurnà sta installazione, pe' piacere nzertàte 'o valore 'e <code>$wgUpgradeKey</code> dint' 'a cascia ccà abbascio.\n'O putite truvà dint'a <code>LocalSettings.php</code>.",
+       "config-localsettings-cli-upgrade": "È stato scummigliato nu file <code>LocalSettings.php</code>.\nPe l'agghiurnà sta installazione, secutate <code>update.php</code>",
+       "config-localsettings-key": "Chiave d'agghiurnamiento:",
+       "config-localsettings-badkey": "'A chiave c'avete dato nun è curretta.",
        "config-mssql-install-auth": "Sceglie 'o tipo d'autenticazziona ca s'ausarrà pe cunnettà â database, durante ll'operazziona d'istallazziona. Si piglie \"{{int:config-mssql-windowsauth}}\", 'e credenziale 'e qualunque fosse ll'utenza ca 'o webserver sta pruciessanno sarranno ausate.",
        "config-mssql-web-auth": "Sceglie 'o tipo d'autenticazziona ca 'o web server pigliarrà pe se cunnettà a 'o server 'e bbase 'e dati, durante ll'operazziona nurmale d&#39;'a wiki.\nSi piglie \"{{int:config-mssql-windowsauth}}\", 'e credenziale 'e qualunque fosse ll'utenza ca 'o webserver sta pruciessanno sarranno ausate."
 }
index c95e9df..f3cf645 100644 (file)
@@ -50,7 +50,7 @@
        "config-env-good": "Miljøet har blitt sjekket.\nDu kan installere MediaWiki.",
        "config-env-bad": "Miljøet har blitt sjekket.\nDu kan installere MediaWiki.",
        "config-env-php": "PHP $1 er innstallert.",
-       "config-env-php-toolow": "PHP $1 er installert.\nMediaWiki krever imidlertid PHP $2 eller høyere.",
+       "config-env-hhvm": "HHVM $1 er installert.",
        "config-unicode-using-utf8": "Bruker Brion Vibbers utf8_normalize.so for Unicode-normalisering.",
        "config-unicode-using-intl": "Bruker [http://pecl.php.net/intl intl PECL-utvidelsen] for Unicode-normalisering.",
        "config-unicode-pure-php-warning": "'''Advarsel''': [http://pecl.php.net/intl intl PECL-utvidelsen] er ikke tilgjengelig for å håndtere Unicode-normaliseringen, faller tilbake til en langsommere ren-PHP-implementasjon.\nOm du kjører et nettsted med høy trafikk bør du lese litt om [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode-normalisering].",
@@ -58,7 +58,8 @@
        "config-no-db": "Fant ingen passende databasedriver! Du må installere en databasedriver for PHP.\nFølgende databasetyper støttes: $1\n\nOm du kompilerte PHP selv, rekonfigurer den med en aktivert databaseklient, for eksempel ved å bruke <code>./configure --with-mysql</code>.\nOm du installerte PHP fra en Debian- eller Ubuntu-pakke, må du også installere for eksempel <code>php5-mysql</code>-pakken.",
        "config-outdated-sqlite": "'''Advarsel''': Du har SQLite $1, som er en eldre versjon enn minimumskravet SQLite $2. SQLite vil ikke være tilgjengelig.",
        "config-no-fts3": "'''Advarsel''': SQLite er kompilert uten [//sqlite.org/fts3.html FTS3-modulen], søkefunksjoner vil ikke være tilgjengelig på dette bakstykket.",
-       "config-register-globals": "'''Advarsel: PHPs <code>[http://php.net/register_globals register_globals]</code>-alternativ er aktivert.'''\n'''Deaktiver det om du kan.'''\nMediaWiki vil fungere, men tjeneren din er utsatt for potensielle sikkerhetssårbarheter.",
+       "config-register-globals-error": "<strong>Feil: PHPs <code>[http://php.net/register_globals register_globals]</code>-valg er aktivt.\nDet må deaktiveres for å kunne fortsette med installeringen.</strong>\nSe [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] for å få hjelp til å gjøre dette.",
+       "config-magic-quotes-gpc": "<strong>Fatalt: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] er aktiv!</strong>\nDette valget kan ødelegge inndata på en uforutsigelig måte.\nDu kan ikke installere eller bruke MediaWiki uten at denne valgmuligheten er slått av.",
        "config-magic-quotes-runtime": "'''Kritisk: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] er aktiv!'''\nDette alternativet ødelegger inndata på en uforutsigbar måte.\nDu kan ikke installere eller bruke MediaWiki med mindre dette alternativet deaktiveres.",
        "config-magic-quotes-sybase": "'''Kritisk: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] er aktiv!'''\nDette alternativet ødelegger inndata på en uforutsigbar måte.\nDu kan ikke installere eller bruke MediaWiki med mindre dette alternativet deaktiveres.",
        "config-mbstring": "'''Kritisk: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] er aktiv!'''\nDette alternativet fører til feil og kan ødelegge data på en uforutsigbar måte.\nDu kan ikke installere eller bruke MediaWiki med mindre dette alternativet deaktiveres.",
@@ -69,6 +70,7 @@
        "config-memory-raised": "PHPs <code>memory_limit</code> er $1, økt til $2.",
        "config-memory-bad": "'''Advarsel:''' PHPs <code>memory_limit</code> er $1.\nDette er sannsynligvis for lavt.\nInstallasjonen kan mislykkes!",
        "config-ctype": "'''Fatal feil''': PHP må kompileres med støtte for [http://www.php.net/manual/en/ctype.installation.php Ctype-utvidelsen].",
+       "config-iconv": "<strong>Kritisk:</strong> PHP må kompileres med støtte for [http://www.php.net/manual/en/iconv.installation.php iconv-utvidelsen].",
        "config-json": "'''Alvorlig:''' PHP ble kompilert uten JSON-støtte.\nDu må installere enten PHP JSON-utvidelsen eller [http://pecl.php.net/package/jsonc PECL jsonc]-utvidelsen før du installere MediaWiki.\n* PHP-utvidelsen inngår i Red Hat Enterprise Linux (CentOS) 5 and 6, men må aktiveres i <code>/etc/php.ini</code> eller <code>/etc/php.d/json.ini</code>.\n* Noen Linux-distribusjoner sluppet etter mai 2013 har ikke med PHP-utvidelsen, men har i stedet med PECL-utvidelsen <code>php5-json</code> eller <code>php-pecl-jsonc</code>.",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] er innstallert",
        "config-apc": "[http://www.php.net/apc APC] er innstallert",
index b2d4a04..836e0fc 100644 (file)
@@ -4,9 +4,15 @@
                        "Bhawani Gautam",
                        "RajeshPandey",
                        "सरोज कुमार ढकाल",
-                       "Ganesh Paudel"
+                       "Ganesh Paudel",
+                       "बिप्लब आनन्द"
                ]
        },
+       "config-information": "जानकारी",
+       "config-localsettings-badkey": "तपाइले दिनु भएको कुन्जी गलत छ ।",
+       "config-your-language": "तपाईंको भाषा:",
+       "config-your-language-help": "इन्स्टल गर्दा उपयोग गर्ने भाषा छान्नुहोस् ।",
+       "config-wiki-language": "विकि भाषाहरू",
        "config-page-name": "नाम",
        "config-page-options": "विकल्पहरु",
        "config-page-install": "स्थापना गर्ने",
index 14321ff..5bf1645 100644 (file)
@@ -12,7 +12,8 @@
                        "JurgenNL",
                        "Southparkfan",
                        "Seb35",
-                       "Mar(c)"
+                       "Mar(c)",
+                       "Sjoerddebruin"
                ]
        },
        "config-desc": "Het installatieprogramma voor MediaWiki",
@@ -57,7 +58,6 @@
        "config-env-good": "De omgeving is gecontroleerd.\nU kunt MediaWiki installeren.",
        "config-env-bad": "De omgeving is gecontroleerd.\nU kunt MediaWiki niet installeren.",
        "config-env-php": "PHP $1 is op dit moment geïnstalleerd.",
-       "config-env-php-toolow": "PHP $1 is geïnstalleerd.\nMediaWiki heeft PHP $2 of hoger nodig om correct te kunnen werken.",
        "config-unicode-using-utf8": "Voor Unicode-normalisatie wordt utf8_normalize.so van Brion Vibber gebruikt.",
        "config-unicode-using-intl": "Voor Unicode-normalisatie wordt de [http://pecl.php.net/intl PECL-extensie intl] gebruikt.",
        "config-unicode-pure-php-warning": "'''Waarschuwing''': de [http://pecl.php.net/intl PECL-extensie intl] is niet beschikbaar om de Unicodenormalisatie af te handelen en daarom wordt de langzame PHP-implementatie gebruikt.\nAls u MediaWiki voor een website met veel verkeer installeert, lees u dan in over [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicodenormalisatie].",
@@ -65,7 +65,6 @@
        "config-no-db": "Het was niet mogelijk een geschikte databasedriver te vinden voor PHP. U moet een databasedriver installeren voor PHP.\nDe volgende databases worden ondersteund: $1.\n\nAls u een gedeelde omgeving gebruikt, vraag dan aan uw hostingprovider een geschikte databasedriver te installeren.\nAls u PHP zelf hebt gecompileerd, wijzig dan uw instellingen zodat een databasedriver wordt geactiveerd, bijvoorbeeld via <code>./configure --with-mysql</code>.\nAls u PHP hebt geïnstalleerd via een Debian- of Ubuntu-package, installeer dan ook de module php5-mysql.",
        "config-outdated-sqlite": "''' Waarschuwing:''' u gebruikt SQLite $1. SQLite is niet beschikbaar omdat de minimaal vereiste versie $2 is.",
        "config-no-fts3": "'''Waarschuwing''': SQLite is gecompileerd zonder de module [//sqlite.org/fts3.html FTS3]; zoekfuncties zijn niet beschikbaar.",
-       "config-register-globals": "'''Waarschuwing: de PHP-optie <code>[http://php.net/register_globals register_globals]</code> is ingeschakeld.'''\n'''Schakel deze uit als dat mogelijk is.'''\nMediaWiki kan ermee werken, maar uw server is dan  kwetsbaarder voor eventuele beveiligingslekken.",
        "config-magic-quotes-runtime": "'''Onherstelbare fout: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] is actief!'''\nDeze instelling zorgt voor onvoorspelbare gegevenscorruptie.\nU kunt MediaWiki niet installeren tenzij deze instelling is uitgeschakeld.",
        "config-magic-quotes-sybase": "'''Onherstelbare fout: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_sybase] is actief!'''\nDeze instelling zorgt voor onvoorspelbare gegevenscorruptie.\nU kunt MediaWiki niet installeren tenzij deze instelling is uitgeschakeld.",
        "config-mbstring": "'''Onherstelbare fout: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] is actief!'''\nDeze instelling zorgt voor onvoorspelbare gegevenscorruptie.\nU kunt MediaWiki niet installeren tenzij deze instelling is uitgeschakeld.",
        "config-memcache-badport": "Poortnummers voor Memcached moeten tussen $1 en $2 liggen.",
        "config-extensions": "Uitbreidingen",
        "config-extensions-help": "De bovenstaande uitbreidingen zijn aangetroffen in de map <code>./extensions</code>.\n\nMogelijk moet u aanvullende instellingen maken, maar u kunt deze uitbreidingen nu inschakelen.",
+       "config-skins": "Vormgevingen",
+       "config-skins-use-as-default": "Als standaard vormgeving instellen",
        "config-install-alreadydone": "'''Waarschuwing:''' het lijkt alsof u MediaWiki al hebt geïnstalleerd en probeert het programma opnieuw te installeren.\nGa door naar de volgende pagina.",
        "config-install-begin": "Als u nu op \"{{int:config-continue}}\" klikt, begint de installatie van MediaWiki.\nAls u nog wijzigingen wilt maken, klik dan op \"{{int:config-back}}\".",
        "config-install-step-done": "afgerond",
diff --git a/includes/installer/i18n/no.json b/includes/installer/i18n/no.json
deleted file mode 100644 (file)
index a8c9833..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-    "@metadata": [],
-    "mainpagetext": "'''MediaWiki-programvaren er nå installert.'''"
-}
index e4bcb6e..372058f 100644 (file)
@@ -37,7 +37,7 @@
        "config-env-good": "L’environament es estat verificat.\nPodètz installar MediaWiki.",
        "config-env-bad": "L’environament es estat verificat.\nPodètz pas installar MediaWiki.",
        "config-env-php": "PHP $1 es installat.",
-       "config-env-php-toolow": "PHP $1 es installat.\nPasmens, MediaWiki requerís PHP $2 o superior.",
+       "config-env-hhvm": "HHVM $1 es installat.",
        "config-unicode-using-utf8": "Utilizacion de utf8_normalize.so per Brion Vibber per la normalizacion Unicode.",
        "config-unicode-using-intl": "Utilizacion de [http://pecl.php.net/intl l'extension PECL intl] per la normalizacion Unicode.",
        "config-memory-raised": "Lo paramètre <code>memory_limit</code> de PHP èra a $1, portat a $2.",
        "config-cache-options": "Paramètres per la mesa en escondedor dels objèctes :",
        "config-memcached-servers": "servidors per Memcached :",
        "config-extensions": "Extensions",
+       "config-skins": "Abilhatges",
+       "config-skins-use-as-default": "Utilizar aqueste abilhatge per defaut",
        "config-install-step-done": "fach",
        "config-install-step-failed": "fracàs",
        "config-install-extensions": "Inclusion de las extensions",
        "config-install-database": "Creacion de la banca de donadas",
        "config-install-schema": "Creacion d'esquèma",
+       "config-install-pg-schema-not-exist": "L'esquèma PostgreSQL existís pas",
        "config-install-pg-commit": "Validacion de las modificacions",
        "config-install-pg-plpgsql": "Verificacion del lengatge PL/pgSQL",
        "config-install-user": "Creacion d'un utilizaire de la banca de donadas",
+       "config-install-user-alreadyexists": "L'utilizaire « $1 » existís ja.",
+       "config-install-user-create-failed": "Fracàs al moment de la creacion de l'utilizaire « $1 » : $2",
+       "config-install-user-missing": "L'utilizaire «$1» existís pas.",
        "config-install-tables": "Creacion de las taulas",
        "config-install-stats": "Inicializacion de las estatisticas",
+       "config-install-keys": "Generacion de la clau secreta",
+       "config-install-updates": "Empachar l’execucion de las mesas a jorn inutilas",
        "config-install-sysop": "Creacion del compte administrator",
        "config-install-mainpage-failed": "Impossible d’inserir la pagina principala : $1",
        "config-download-localsettings": "Telecargar <code>LocalSettings.php</code>",
        "config-help": "ajuda",
+       "config-help-tooltip": "clicar per agrandir",
        "mainpagetext": "'''MediaWiki es estat installat amb succès.'''",
        "mainpagedocfooter": "Consultatz lo [//meta.wikimedia.org/wiki/Help:Contents/fr Guida de l'utilizaire] per mai d'entresenhas sus l'utilizacion d'aqueste logicial de wiki.\n\n== Per començar ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lista dels paramètres de configuracion]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/oc FAQ MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de discussions de las distribucions de MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Adaptatz MediaWiki dins vòstra lenga]"
 }
index fb88379..c129ab9 100644 (file)
@@ -1,4 +1,13 @@
 {
-       "@metadata": [],
+       "@metadata": {
+               "authors": [
+                       "Aalam"
+               ]
+       },
+       "config-information": "ਜਾਣਕਾਰੀ",
+       "config-your-language": "ਤੁਹਾਡੀ ਭਾਸ਼ਾ:",
+       "config-back": "← ਪਿੱਛੇ",
+       "config-continue": "ਜਾਰੀ ਰੱਖੋ →",
+       "config-page-language": "ਭਾਸ਼ਾ",
        "mainpagetext": "'''ਮੀਡਿਆਵਿਕਿ ਠੀਕ ਤਰ੍ਹਾਂ ਇੰਸਟਾਲ ਹੋ ਗਿਆ ਹੈ।'''"
 }
index 1a3e7ae..2e7e023 100644 (file)
@@ -16,7 +16,8 @@
                        "Pan Cube",
                        "WTM",
                        "Alan ffm",
-                       "Matik7"
+                       "Matik7",
+                       "Pio387"
                ]
        },
        "config-desc": "Instalator MediaWiki",
@@ -61,7 +62,7 @@
        "config-env-good": "Środowisko oprogramowania zostało sprawdzone.\nMożesz teraz zainstalować MediaWiki.",
        "config-env-bad": "Środowisko oprogramowania zostało sprawdzone.\nNie możesz zainstalować MediaWiki.",
        "config-env-php": "Zainstalowane jest PHP w wersji $1.",
-       "config-env-php-toolow": "Zainstalowane jest PHP $1.\nJednak MediaWiki wymaga PHP $2 lub nowszego.",
+       "config-env-hhvm": "Zainstalowany jest HHVM $1.",
        "config-unicode-using-utf8": "Korzystanie z normalizacji Unicode utf8_normalize.so napisanej przez Brion Vibbera.",
        "config-unicode-using-intl": "Korzystanie z [http://pecl.php.net/intl rozszerzenia intl PECL] do normalizacji Unicode.",
        "config-unicode-pure-php-warning": "'''Uwaga!''' [http://pecl.php.net/intl Rozszerzenie intl PECL] do obsługi normalizacji Unicode nie jest dostępne. Użyta zostanie mało wydajna zwykła implementacja w PHP.\nJeśli prowadzisz stronę o dużym natężeniu ruchu, powinieneś zapoznać się z informacjami o [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations normalizacji Unicode].",
@@ -69,7 +70,8 @@
        "config-no-db": "Nie można odnaleźć właściwego sterownika bazy danych! Musisz zainstalować sterownik bazy danych dla PHP.\nMożna użyć następujących typów baz danych: $1.\n\nJeśli skompilowałeś PHP samodzielnie, skonfiguruj je ponownie z włączonym klientem bazy danych, na przykład za pomocą polecenia <code>./configure --with-mysqli</code>.\nJeśli zainstalowałeś PHP jako pakiet Debiana lub Ubuntu, musisz również zainstalować np. moduł <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Ostrzeżenie''': masz SQLite  $1, która jest niższa od minimalnej wymaganej wersji  $2 . SQLite będzie niedostępne.",
        "config-no-fts3": "'''Uwaga''' – SQLite został skompilowany bez [//sqlite.org/fts3.html modułu FTS3] – funkcje wyszukiwania nie będą dostępne.",
-       "config-register-globals": "'''Uwaga –  w konfiguracji PHP włączona jest opcja <code>[http://php.net/register_globals register_globals]</code>.'''\n'''Jeśli możesz, wyłącz ją.'''\nMediaWiki będzie działać, ale Twój serwer może być narażony potencjalnymi lukami w zabezpieczeniach.",
+       "config-register-globals-error": "<strong>Błąd: dyrektywa PHP <code>[http://php.net/register_globals register_globals]</code> jest włączona.\nAby kontynuować instalację musi zostać wyłączona.</strong>\nPrzeczytaj [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals], aby dowiedzieć się, jak to zrobić.",
+       "config-magic-quotes-gpc": "<strong>Błąd krytyczny – dyrektywa [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] jest włączona!</strong>\nTa opcja powoduje nieprzewidywalne uszkodzenia wprowadzanych danych.\nNie możesz instalować lub korzystać z MediaWiki, dopóki ta opcja nie zostanie wyłączona.",
        "config-magic-quotes-runtime": "'''Błąd krytyczny – włączono [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime]!'''\nTa opcja powoduje nieprzewidywalne uszkodzenia wprowadzanych danych.\nZainstalować lub korzystać z MediaWiki można pod warunkiem, że ta opcja jest wyłączona.",
        "config-magic-quotes-sybase": "'''Błąd krytyczny – włączono [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase]!'''\nTa opcja powoduje nieprzewidywalne uszkodzenia wprowadzanych danych.\nZainstalować lub korzystać z MediaWiki można pod warunkiem, że ta opcja jest wyłączona.",
        "config-mbstring": "'''Błąd krytyczny – włączono [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]!'''\nTa opcja powoduje błędy i może wywołać nieprzewidywalne uszkodzenia wprowadzanych danych.\nZainstalować lub korzystać z MediaWiki można pod warunkiem, że ta opcja jest wyłączona.",
@@ -80,6 +82,7 @@
        "config-memory-raised": "PHP <code>memory_limit</code> było ustawione na $1, zostanie zwiększone do $2.",
        "config-memory-bad": "'''Uwaga:''' PHP <code>memory_limit</code> jest ustawione na $1.\nTo jest prawdopodobnie zbyt mało.\nInstalacja może się nie udać!",
        "config-ctype": "''' Krytyczny ''': PHP musi być skompilowany z obsługą [http://www.php.net/manual/en/ctype.installation.php rozszerzenia Ctype].",
+       "config-iconv": "<strong>Błąd krytyczny:</strong> PHP musi być skompilowane z obsługą [http://www.php.net/manual/en/iconv.installation.php rozszerzenia iconv].",
        "config-json": "'''Błąd krytyczny:''' PHP skompilowano bez obsługa JSON.\nPrzed zainstalowaniem oprogramowania MediaWiki musisz zainstalować rozszerzenie PHP JSON albo rozszerzenie [http://pecl.php.net/package/jsonc PECL jsonc].\n* Rozszerzenie PHP jest zawarte w Red Hat Enterprise Linux (CentOS) 5 i 6, jednak musi zostać włączone w <code>/etc/php.ini</code> or <code>/etc/php.d/json.ini</code>.\n* Niektóre dystrybucje Linuksa, wydane po maju 2013, nie używają rozszerzenia PHP, lecz rozszerzenie PECL, jako <code>php5-json</code> lub <code>php-pecl-jsonc</code>.",
        "config-xcache": "[Http://trac.lighttpd.net/xcache/ XCache] jest zainstalowany",
        "config-apc": "[Http://www.php.net/apc APC] jest zainstalowany",
        "config-sqlite-cant-create-db": "Nie można utworzyć pliku bazy danych <code>$1</code>.",
        "config-sqlite-fts3-downgrade": "Brak wsparcia FTS3 dla PHP. Tabele zostały cofnięte",
        "config-can-upgrade": "W bazie danych są już tabele MediaWiki.\nAby uaktualnić je do MediaWiki $1, kliknij '''Dalej'''.",
-       "config-upgrade-done": "Uaktualnienie kompletne.\n\nMożna teraz [ $1  rozpocząć korzystanie z wiki].\n\nJeśli chcesz ponownie wygenerować plik <code>LocalSettings.php</code>, kliknij przycisk poniżej.\nJest to '''nie zalecane''', chyba że występują problemy z twoją wiki.",
+       "config-upgrade-done": "Uaktualnienie kompletne.\n\nMożna teraz [$1 rozpocząć korzystanie z wiki].\n\nJeśli chcesz ponownie wygenerować plik <code>LocalSettings.php</code>, kliknij przycisk poniżej.\nJest to <strong>niezalecane</strong>, chyba że występują problemy z twoją wiki.",
        "config-upgrade-done-no-regenerate": "Aktualizacja zakończona.\n\nMożesz teraz [$1 zacząć korzystać ze swojej wiki].",
        "config-regenerate": "Ponowne generowanie LocalSettings.php →",
        "config-show-table-status": "Zapytanie „<code>SHOW TABLE STATUS</code>” nie powiodło się!",
        "config-license-gfdl": "GNU licencja wolnej dokumentacji 1.3 lub nowsza",
        "config-license-pd": "Domena publiczna",
        "config-license-cc-choose": "Wybierz własną licencję Creative Commons",
-       "config-license-help": "Wiele publicznych wiki umieszcza wszystkie dopisane treści na [http://freedomdefined.org/Definition wolnej licencji].\nTo pomaga tworzyć poczucie wspólnoty i zachęca do długoterminowego wkładu.\nNie jest to zazwyczaj konieczne w prywatnych lub firmowych wiki.\n\nJeśli chcesz móc użyć tekstu z Wikipedii i chcesz Wikipedia mogła zaakceptować tekst skopiowany z twojej wiki, należy wybrać '''Creative Commons Attribution Share Alike'''.\n\nWikipedia używała poprzednio GNU Free Documentation License.\nGFDL jest poprawną licencję, ale trudno ją zrozumieć.\nTrudno także ponowne użyć zawartości na licencji GFDL.",
+       "config-license-help": "Wiele publicznych wiki umieszcza wszystkie dopisane treści na [http://freedomdefined.org/Definition wolnej licencji].\nPomaga to tworzyć poczucie wspólnoty i zachęca do długoterminowego wkładu.\nNie jest to zazwyczaj konieczne w prywatnych lub firmowych wiki.\n\nJeśli chcesz móc użyć tekstu z Wikipedii i chcesz Wikipedia mogła zaakceptować tekst skopiowany z twojej wiki, należy wybrać <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nWikipedia używała poprzednio GNU Free Documentation License.\nGFDL jest poprawną licencję, ale trudno ją zrozumieć.\nTrudno także ponowne użyć zawartości na licencji GFDL.",
        "config-email-settings": "Ustawienia e-maili",
        "config-enable-email": "Włącz wychodzące wiadomości e–mail",
        "config-enable-email-help": "Jeśli chcesz, aby działał e-mail, [http://www.php.net/manual/en/mail.configuration.php Ustawienia poczty PHP] muszą być poprawnie wprowadzone.\nJeśli nie chcesz jakichś funkcji poczty e-mail, można je wyłączyć tutaj.",
        "config-memcache-badport": "Numery portu Memcached powinny zawierać się pomiędzy $1 i $2.",
        "config-extensions": "Rozszerzenia",
        "config-extensions-help": "Rozszerzenia wyżej wymienione zostały wykryte w katalogu <code>./extensions</code>.\n\nMogą one wymagać dodatkowych czynności konfiguracyjnych, ale można je teraz włączyć",
+       "config-skins": "Skórki",
+       "config-skins-help": "Powyższe skórki zostały wykryte w twoim katalogi <code>./skins</code>. Należy włączyć co najmniej jedną i wybrać domyślną.",
+       "config-skins-use-as-default": "Użyj tej skórki jako domyślnej",
+       "config-skins-missing": "Nie znaleziono skórki; MediaWiki będzie używać rezerwowej skórki do czasu zainstalowania odpowiednich.",
+       "config-skins-must-enable-some": "Musisz wybrać co najmniej jedną skórkę, aby ją włączyć.",
+       "config-skins-must-enable-default": "Skórka wybrana jako domyślna musi być włączona.",
        "config-install-alreadydone": "'''Uwaga''' – wydaje się, że MediaWiki jest już zainstalowane, a obecnie próbujesz zainstalować je ponownie.\nPrzejdź do następnej strony.",
        "config-install-begin": "Po naciśnięciu \"{{int:config-continue}}\", rozpocznie się instalacja MediaWiki.\nJeśli nadal chcesz dokonać zmian, naciśnij \"{{int:config-back}}\".",
        "config-install-step-done": "gotowe",
        "config-install-stats": "Inicjowanie statystyki",
        "config-install-keys": "Generowanie tajnych kluczy",
        "config-insecure-keys": "'''Ostrzeżenie:''' {{PLURAL:$2|Klucz bezpieczeństwa|Klucze bezpieczeństwa|Klucze bezpieczeństwa}} ($1) utworzone podczas instalacji {{PLURAL:$2|utworzony podczas instalacji nie jest|utworzone podczas instalacji nie są|utworzone podczas instalacji nie są}} w pełni bezpieczne. Być może warto wygenerować {{PLURAL:$2|własny klucz|własne klucze|własne klucze}}.",
+       "config-install-updates": "Zapobieganie uruchamianiu niepotrzebnych aktualizacji",
        "config-install-sysop": "Tworzenie konta administratora",
        "config-install-subscribe-fail": "Nie można zapisać na listę „mediawiki-announce“ – $1",
        "config-install-subscribe-notpossible": "cURL nie jest zainstalowany, więc <code>allow_url_fopen</code> nie jest dostępne.",
index 20f0b3e..68a94e8 100644 (file)
@@ -57,7 +57,6 @@
        "config-env-good": "O ambiente foi verificado.\nVocê pode instalar o MediaWiki.",
        "config-env-bad": "O ambiente foi verificado.\nVocê não pode instalar o MediaWiki.",
        "config-env-php": "O PHP $1 está instalado.",
-       "config-env-php-toolow": "PHP $1 está instalado.\nNo entanto, o MediaWiki requer PHP $2 ou superior.",
        "config-unicode-using-utf8": "Usando o utf8_normalize.so, de Brion Vibber, para a normalização Unicode.",
        "config-unicode-using-intl": "Usando a [http://pecl.php.net/intl extensão intl PECL] para a normalização Unicode.",
        "config-unicode-pure-php-warning": "<strong>Aviso</strong>: A [http://pecl.php.net/intl extensão intl PECL] não está disponível para efetuar a normalização Unicode, abortando e passando para a lenta implementação de PHP puro.\nSe o seu site tem um alto volume de tráfego, informe-se sobre a [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations normalização Unicode].",
@@ -65,7 +64,6 @@
        "config-no-db": "Não foi possível encontrar um driver de banco de dados adequado! É necessário instalar um driver de banco de dados para o PHP.\nSão suportados os seguintes tipos de bancos de dados: $1.\n\nSe você mesmo tiver compilado o PHP, reconfigure-o com um cliente de banco de dados ativado usando, por exemplo <code>./configure --with-mysqli</code>.\nSe você instalou o PHP a partir de um pacote do Debian ou do Ubuntu, então será também necessário 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": "<strong>Aviso: A opção <code>[http://php.net/register_globals register_globals]</code> do PHP está ativada.\nDesative-a se puder.</strong>\nO MediaWiki funcionará mesmo assim, mas o seu servidor ficará exposto a potenciais vulnerabilidades de segurança.",
        "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.",
index a547edc..835cf9b 100644 (file)
@@ -59,7 +59,7 @@
        "config-env-good": "O ambiente foi verificado.\nPode instalar o MediaWiki.",
        "config-env-bad": "O ambiente foi verificado.\nNão pode instalar o MediaWiki.",
        "config-env-php": "O PHP $1 está instalado.",
-       "config-env-php-toolow": "O PHP $1 está instalado.\nNo entanto, o MediaWiki requer o PHP $2 ou superior.",
+       "config-env-hhvm": "HHVM $1 está instalado.",
        "config-unicode-using-utf8": "A usar o utf8_normalize.so, por Brion Vibber, para a normalização Unicode.",
        "config-unicode-using-intl": "A usar a [http://pecl.php.net/intl extensão intl PECL] para a normalização Unicode.",
        "config-unicode-pure-php-warning": "'''Aviso''': A [http://pecl.php.net/intl extensão intl PECL] não está disponível para efetuar a normalização Unicode. Irá recorrer-se à implementação em PHP puro, que é mais lenta.\nSe o seu site tem alto volume de tráfego, devia informar-se um pouco sobre a [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations/pt normalização Unicode].",
@@ -67,7 +67,6 @@
        "config-no-db": "Não foi possível encontrar um controlador ''(driver)'' apropriado da base de dados! Precisa de instalar um controlador da base de dados para o PHP. São aceites os seguintes tipos de base de dados: $1.\n\nSe fez a compilação do PHP, reconfigure-o com um cliente de base de dados ativado; por exemplo, usando <code>./configure --with-mysql</code>.\nSe instalou o PHP a partir de um pacote Debian ou Ubuntu, então precisa de instalar também, por exemplo, o pacote <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Aviso''': Tem a versão $1 do SQLite, que é anterior à versão mínima necessária, a $2. O SQLite não estará disponível.",
        "config-no-fts3": "'''Aviso''': O SQLite foi compilado sem o módulo [//sqlite.org/fts3.html FTS3]; as funcionalidades de pesquisa não estarão disponíveis nesta instalação.",
-       "config-register-globals": "'''Aviso: A opção <code>[http://php.net/register_globals register_globals]</code> do PHP está ativada.'''\n'''Desative-a, se puder.'''\nO MediaWiki funciona mesmo assim, mas o seu servidor está exposto a potenciais vulnerabilidades de segurança.",
        "config-magic-quotes-runtime": "'''Erro fatal: A opção [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] está ativa!'''\nEsta opção causa corrupção dos dados de entrada, de uma forma imprevisível.\nNão pode instalar ou usar o MediaWiki a menos que esta opção seja desativada.",
        "config-magic-quotes-sybase": "'''Erro fatal: A opção [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] está ativa!'''\nEsta opção causa corrupção dos dados de entrada, de uma forma imprevisível.\nNão pode instalar ou usar o MediaWiki a menos que esta opção seja desativada.",
        "config-mbstring": "'''Erro fatal: A opção [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] está ativa!'''\nEsta opção causa erros e pode corromper os dados de uma forma imprevisível.\nNão pode instalar ou usar o MediaWiki a menos que esta opção seja desativada.",
        "config-ns-site-name": "O mesmo que o nome da wiki: $1",
        "config-ns-other": "Outro (especifique)",
        "config-ns-other-default": "AMinhaWiki",
-       "config-project-namespace-help": "Seguindo o exemplo da Wikipedia, muitas wikis mantêm as páginas das suas normas e políticas, separadas das páginas de conteúdo, num \"'''espaço nominal do projeto'''\".\nTodos os nomes das páginas neste espaço nominal começam com um determinado prefixo, que pode especificar aqui.\nTradicionalmente, este prefixo deriva do nome da wiki, mas não pode conter caracteres de pontuação, como \"#\" ou \":\".",
+       "config-project-namespace-help": "Seguindo o exemplo da Wikipédia, muitas wikis mantêm as páginas das suas normas e políticas, separadas das páginas de conteúdo, num \"'''domínio do projeto'''\".\nTodos os nomes das páginas neste domínio começam com um determinado prefixo, que pode especificar aqui.\nTradicionalmente, este prefixo deriva do nome da wiki, mas não pode conter caracteres de pontuação, como \"#\" ou \":\".",
        "config-ns-invalid": "O espaço nominal especificado \"<nowiki>$1</nowiki>\" é inválido.\nIntroduza um espaço nominal de projeto diferente.",
        "config-ns-conflict": "O espaço nominal que especificou, \"<nowiki>$1</nowiki>\", cria um conflito com um dos espaços nominais padrão do MediaWiki.\nEspecifique um espaço nominal do projeto diferente.",
        "config-admin-box": "Conta de administrador",
        "config-license-gfdl": "GNU Free Documentation License 1.3 ou posterior",
        "config-license-pd": "Domínio Público",
        "config-license-cc-choose": "Selecionar uma licença personalizada Creative Commons",
-       "config-license-help": "Muitas wikis de acesso público licenciam todas as colaborações com uma [http://freedomdefined.org/Definition licença livre].\nIsto ajuda a criar um sentido de propriedade da comunidade e encoraja as colaborações a longo prazo.\nTal não é geralmente necessário nas wikis privadas ou corporativas.\n\nSe pretende que seja possível usar textos da Wikipédia na sua wiki e que seja possível a Wikipédia aceitar textos copiados da sua wiki, deve escolher a licença Creative Commons - Atribuição - Partilha nos Mesmos Termos.\n\nA licença anterior da Wikipédia era a licença GNU Free Documentation License.\nA GFDL é uma licença válida, mas de difícil compreensão.\nTambém é difícil reutilizar conteúdos licenciados com a GFDL.",
+       "config-license-help": "Muitas wikis de acesso público licenciam todas as colaborações com uma [http://freedomdefined.org/Definition licença livre].\nIsto ajuda a criar um sentido de propriedade da comunidade e encoraja as colaborações a longo prazo.\nTal não é geralmente necessário nas wikis privadas ou corporativas.\n\nSe pretende que seja possível usar textos da Wikipédia na sua wiki e que seja possível a Wikipédia aceitar textos copiados da sua wiki, deve escolher a licença <strong>{{int:config-license-cc-by-sa}}</strong>..\n\nA licença anterior da Wikipédia era a licença GNU Free Documentation License.\nA GFDL é uma licença válida, mas de difícil compreensão.\nTambém é difícil reutilizar conteúdos licenciados com a GFDL.",
        "config-email-settings": "Definições do correio electrónico",
        "config-enable-email": "Ativar mensagens eletrónicas de saída",
        "config-enable-email-help": "Se quer que o correio eletrónico funcione, as [http://www.php.net/manual/en/mail.configuration.php definições de correio eletrónico do PHP] têm de estar configuradas corretamente.\nSe não pretende viabilizar qualquer funcionalidade de correio eletrónico, pode desativá-lo aqui.",
        "config-memcache-badport": "Os números das portas do Memcached devem estar entre $1 e $2.",
        "config-extensions": "Extensões",
        "config-extensions-help": "Foi detectada a existência das extensões listadas acima, no seu diretório <code>./extensions</code>.\n\nEstas talvez necessitem de configurações adicionais, mas pode ativá-las agora",
+       "config-skins": "Temas",
+       "config-skins-help": "Os temas listados abaixo foram detetados no seu diretório <code>./skins</code>. Deverá ativar pelo menos um e escolher qual o escolhido por padrão.",
+       "config-skins-use-as-default": "Usar este tema como padrão",
+       "config-skins-must-enable-some": "Deve escolher pelo menos um tema para ativar.",
+       "config-skins-must-enable-default": "O tema escolhido como padrão deve ser ativado.",
        "config-install-alreadydone": "'''Aviso:''' Parece que já instalou o MediaWiki e está a tentar instalá-lo novamente.\nPasse para a próxima página, por favor.",
        "config-install-begin": "Ao clicar \"{{int:config-continue}}\", vai iniciar a instalação do MediaWiki.\nSe quiser fazer mais alterações, clique \"{{int:config-back}}\".",
        "config-install-step-done": "terminado",
index b57ebf9..772ce96 100644 (file)
@@ -62,7 +62,7 @@
        "config-env-good": "See also:\n* {{msg-mw|Config-env-bad}}",
        "config-env-bad": "See also:\n* {{msg-mw|Config-env-good}}",
        "config-env-php": "Parameters:\n* $1 - the version of PHP that has been installed\nSee also:\n* {{msg-mw|config-env-php-toolow}}",
-       "config-env-php-toolow": "Parameters:\n* $1 - the version of PHP that has been installed\n* $2 - minimum PHP version number\nSee also:\n* {{msg-mw|config-env-php}}",
+       "config-env-hhvm": "Parameters:\n* $1 - the version of HHVM that has been installed",
        "config-unicode-using-utf8": "Status message in the MediaWiki installer environment checks.",
        "config-unicode-using-intl": "Status message in the MediaWiki installer environment checks.",
        "config-unicode-pure-php-warning": "PECL is the name of a group producing standard pieces of software for PHP, and intl is the name of their library handling some aspects of internationalization.",
@@ -71,6 +71,7 @@
        "config-outdated-sqlite": "Used as warning. Parameters:\n* $1 - the version of SQLite that has been installed\n* $2 - minimum version",
        "config-no-fts3": "A \"[[:wikipedia:Front and back ends|backend]]\" is a system or component that ordinary users don't interact with directly and don't need to know about, and that is responsible for a distinct task or service - for example, a storage back-end is a generic system for storing data which other applications can use. Possible alternatives for back-end are \"system\" or \"service\", or (depending on context and language) even leave it untranslated.",
        "config-register-globals-error": "Error message in the MediaWiki installer environment checks.",
+       "config-magic-quotes-gpc": "{{Related|Config-fatal}}",
        "config-magic-quotes-runtime": "{{Related|Config-fatal}}",
        "config-magic-quotes-sybase": "{{Related|Config-fatal}}",
        "config-mbstring": "{{Related|Config-fatal}}",
@@ -81,6 +82,7 @@
        "config-memory-raised": "Parameters:\n* $1 is the configured <code>memory_limit</code>.\n* $2 is the value to which <code>memory_limit</code> was raised.",
        "config-memory-bad": "Parameters:\n* $1 is the configured <code>memory_limit</code>.",
        "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 [[bugzilla:47431]]).\n{{Related|Config-fatal}}",
        "config-xcache": "Message indicates if this program is available",
        "config-apc": "Message indicates if this program is available",
        "config-license-gfdl": "Option for the wiki content license in the MediaWiki installer.",
        "config-license-pd": "{{Identical|Public domain}}",
        "config-license-cc-choose": "Option for the wiki content license in the MediaWiki installer.",
-       "config-license-help": "Help text in MediaWiki installer for license selection.",
+       "config-license-help": "Help text in MediaWiki installer for license selection.\n\nRefers to {{msg-mw|Config-license-cc-by-sa}}.",
        "config-email-settings": "{{Identical|E-mail setting}}",
        "config-enable-email": "Checkbox label in the MediaWiki installer to allow the wiki to send email to its users.",
        "config-enable-email-help": "Help text in the MediaWiki installer to allow the wiki to send email to its users.",
        "config-upload-deleted": "Prompt for the server directory into which deleted files should be moved.",
        "config-upload-deleted-help": "Explanation for {{msg|config-upload-deleted}}.",
        "config-logo": "Prompt for a link to the logo to use for the wiki.",
-       "config-logo-help": "",
+       "config-logo-help": "Help string shown to the user explaining the requirements for the wiki's logo.",
        "config-instantcommons": "Used as label for the checkbox.\n\nThe help message for this checkbox is:\n* {{msg-mw|Config-instantcommons-help}}",
        "config-instantcommons-help": "Used as help message for the checkbox which is labeled {{msg-mw|config-instantcommons}}.",
        "config-cc-error": "Prompt to manually enter a license when the tool fails to match.",
        "config-cache-help": "Explanation for what object caching is, next to {{msg|config-cache-options}}.",
        "config-cache-none": "Label for the object caching disabled option.",
        "config-cache-accel": "Label for the object caching via PHP option.",
-       "config-cache-memcached": "Label for the object caching via memcached option.",
+       "config-cache-memcached": "{{doc-important|Do not translate \"memcached\".}}\nLabel for the object caching via memcached option.",
        "config-memcached-servers": "{{doc-important|Do not translate \"memcached\".}}\n{{Identical|Memcached server}}",
        "config-memcached-help": "Prompt for the object caching via Memcached option for the user to define server(s) to be used.",
-       "config-memcache-needservers": "Error message for the object caching via Memcached option when the user has failed to define servers at the above prompt.",
+       "config-memcache-needservers": "Error message for the object caching via Memcached option when the user has failed to define servers at the above prompt.\n{{doc-important|Do not translate \"memcached\".}}",
        "config-memcache-badip": "Used as error message. Parameters:\n* $1 - IP address for Memcached\nSee also:\n* {{msg-mw|Config-memcache-noport}}\n* {{msg-mw|Config-memcache-badport}}",
-       "config-memcache-noport": "Used as error message. Parameters:\n* $1 - Memcached server name\nSee also:\n* {{msg-mw|Config-memcache-badip}}\n* {{msg-mw|Config-memcache-badport}}",
-       "config-memcache-badport": "Used as error message. Parameters:\n* $1 - 1 (hard-coded)\n* $2 - 65535 (hard-coded)\nSee also:\n* {{msg-mw|Config-memcache-badip}}\n* {{msg-mw|Config-memcache-noport}}",
+       "config-memcache-noport": "Used as error message. Parameters:\n* $1 - Memcached server name\nSee also:\n* {{msg-mw|Config-memcache-badip}}\n* {{msg-mw|Config-memcache-badport}}\n{{doc-important|Do not translate \"memcached\".}}",
+       "config-memcache-badport": "Used as error message. Parameters:\n* $1 - 1 (hard-coded)\n* $2 - 65535 (hard-coded)\nSee also:\n* {{msg-mw|Config-memcache-badip}}\n* {{msg-mw|Config-memcache-noport}}\n{{doc-important|Do not translate \"memcached\".}}",
        "config-extensions": "{{Identical|Extension}}",
        "config-extensions-help": "{{doc-important|Do not translate <code>./extensions</code>.}}\nUsed in help box.",
+       "config-skins": "{{Identical|Skin}}",
+       "config-skins-help": "{{doc-important|Do not translate <code>./skins</code>.}}\nUsed in help box.",
+       "config-skins-use-as-default": "Label shown next to skin names.",
+       "config-skins-missing": "Warning message shown when there are no skins to install.",
+       "config-skins-must-enable-some": "Error message shown when the user does silly things.",
+       "config-skins-must-enable-default": "Error message shown when the user does silly things.",
        "config-install-alreadydone": "Error message shown to users visiting the installer when the wiki appears to already be set up.",
        "config-install-begin": "Prompt at the end of the initial configuration options screen before the wiki software is installed.",
        "config-install-step-done": "{{Identical|Done}}",
        "config-install-step-failed": "{{Identical|Failed}}",
        "config-install-extensions": "Notice shown to the user during the install about progress when extensions are being installed.",
-       "config-install-database": "*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
+       "config-install-database": "Message indicates the database is being set up\n\nSee also:\n*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-updates}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
        "config-install-schema": "*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
        "config-install-pg-schema-not-exist": "Error message shown to users picking PostgreSQL.",
        "config-install-pg-schema-failed": "Parameters:\n* $1 = database user name (usernames in the database are unrelated to wiki user names)\n* $2 =",
        "config-install-user-grant-failed": "Parameters:\n* $1 is the database username for which granting rights failed\n* $2 is the error message",
        "config-install-user-missing": "Used as PostgreSQL error message. Parameters:\n* $1 - database username\nSee also:\n* {{msg-mw|Config-install-user-missing-create}}",
        "config-install-user-missing-create": "Used as PostgreSQL error message. Parameters:\n* $1 - database username\nSee also:\n* {{msg-mw|Config-install-user-missing}}",
-       "config-install-tables": "Message indicates that the tables are being created\n\nSee also:\n*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
+       "config-install-tables": "Message indicates that the tables are being created\n\nSee also:\n*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-updates}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
        "config-install-tables-exist": "Error notice during the installation saying that the database already seems set up for MediaWiki, so it's continuing without taking that step.",
        "config-install-tables-failed": "Used as PostgreSQL error message. Parameters:\n* $1 - detailed error message",
        "config-install-interwiki": "Message indicates that the interwikitables are being populated\n\nSee also:\n*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
        "config-install-stats": "*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
        "config-install-keys": "*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
        "config-insecure-keys": "Parameters:\n* $1 - A list of names of the secret keys that were generated.\n* $2 - the number of items in the list $1, to be used with PLURAL.",
+       "config-install-updates": "Message indicating that the updatelog table is filled with keys of updates that won't be run when running database updates.\n\nSee also:\n*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-updates}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
+       "config-install-updates-failed": "Used as error message. Parameters:\n* $1 - detailed error message",
        "config-install-sysop": "Message indicates that the administrator user account is being created\n\nSee also:\n*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
-       "config-install-subscribe-fail": "{{doc-important|\"mediawiki-announce\" is the name of a mailing list and should not be translated.}}",
+       "config-install-subscribe-fail": "{{doc-important|\"[[m:mail:mediawiki-announce|mediawiki-announce]]\" is the name of a mailing list and should not be translated.}}\nA message displayed if the MediaWiki installer encounters an error making a request to lists.wikimedia.org which hosts the mailing list.\n* $1 - the HTTP error encountered, reproduced as is (English string)",
        "config-install-subscribe-notpossible": "Error shown when automatically subscribing to the MediaWiki announcements mailing list fails.",
        "config-install-mainpage": "*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
        "config-install-extension-tables": "Notice shown to the user during the install about progress.",
index 17f5fbc..b8a36be 100644 (file)
@@ -62,7 +62,7 @@
        "config-env-good": "Проверка внешней среды была успешно проведена.\nВы можете установить MediaWiki.",
        "config-env-bad": "Была проведена проверка внешней среды.\nВы не можете установить MediaWiki.",
        "config-env-php": "Установленная версия PHP: $1.",
-       "config-env-php-toolow": "Найден PHP $1, тогда как MediaWiki требуется PHP версии $2 или выше.",
+       "config-env-hhvm": "HHVM $1 установлена.",
        "config-unicode-using-utf8": "Использовать Brion Vibber utf8_normalize.so для нормализации Юникода.",
        "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 нормализации Юникода].",
@@ -70,7 +70,8 @@
        "config-no-db": "Не удалось найти подходящие драйвера баз данных! Вам необходимо установить драйвера базы данных для PHP.\nПоддерживаются следующие типы баз данных: $1.\nЕсли вы скомпилировали PHP сами, перенастройте его с включением клиента баз данных, например, с помощью <code>./configure --with-mysqli</code>.\nЕсли вы скомпилировали PHP сами, сконфигурируйте его снова с включенным клиентом базы данных, например, с помощью <code>./configure --with-mysql</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": "'''Внимание: PHP-опция <code>[http://php.net/register_globals register_globals]</code> включена.'''\n'''Отключите её, если это возможно.'''\nMediaWiki будет работать, но это снизит безопасность сервера и увеличит риск проникновения извне.",
+       "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 без выключения этой опции невозможно.",
@@ -81,6 +82,7 @@
        "config-memory-raised": "Ограничение на доступную PHP память (<code>memory_limit</code>) поднято с $1 до $2.",
        "config-memory-bad": "'''Внимание:''' размер PHP <code>memory_limit</code> составляет $1.\nВероятно, этого слишком мало.\nУстановка может потерпеть неудачу!",
        "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-xcache": "[http://xcache.lighttpd.net/ XCache] установлен",
        "config-apc": "[http://www.php.net/apc APC] установлен",
        "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Если вы хотите использовать тексты из Википедии или хотите, что в Википедию можно было копировать тексты из вашей вики, вам следует выбрать '''Creative Commons Attribution Share Alike'''.\n\nВикипедия ранее использовала лицензию GNU Free Documentation License.\nGFDL может быть использована, но она сложна для понимания и осложняет повторное использование материалов.",
+       "config-license-help": "Многие общедоступные вики разрешают использовать свои материалы на условиях [http://freedomdefined.org/Definition/Ru свободных лицензий].\nЭто помогает созданию чувства общности, стимулирует долгосрочное участие.\nНо в этом нет необходимости для частных или корпоративных вики.\n\nЕсли вы хотите использовать тексты из Википедии или хотите, что в Википедию можно было копировать тексты из вашей вики, вам следует выбрать <strong>{{int:config-license-cc-by-sa}}</strong>.\n\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-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": "Тема оформления, выбранная по умолчанию, должна быть включена.",
        "config-install-alreadydone": "'''Предупреждение:''' Вы, кажется, уже устанавливали MediaWiki и пытаетесь произвести повторную установку.\nПожалуйста, перейдите на следующую страницу.",
        "config-install-begin": "Нажав «{{int:config-continue}}», вы начнёте установку MediaWiki.\nЕсли вы хотите внести изменения, нажмите «{{int:config-back}}».",
        "config-install-step-done": "выполнено",
        "config-install-stats": "Статистика инициализации",
        "config-install-keys": "Создание секретных ключей",
        "config-insecure-keys": "'''Предупреждение.''' {{PLURAL:$2|1=Ключ безопасности $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>.",
index 681e8ee..100f316 100644 (file)
@@ -2,11 +2,13 @@
        "@metadata": {
                "authors": [
                        "Andria",
-                       "L2212"
+                       "L2212",
+                       "Uharteko",
+                       "Taxandru"
                ]
        },
        "config-page-language": "Limba",
        "config-page-name": "Nùmene",
        "config-page-options": "Preferèntzias",
-       "mainpagetext": "'''MediaWiki est stadu installadu in modu currègidu.'''"
+       "mainpagetext": "'''MediaWiki est stadu installadu in modu currèggidu.'''"
 }
index 40d0876..4d44735 100644 (file)
@@ -48,7 +48,6 @@
        "config-env-good": "The environment haes been checked.\nYe can install MediaWiki.",
        "config-env-bad": "The environment haes been checked.\nYe canna install MediaWiki.",
        "config-env-php": "PHP $1 is instâlled.",
-       "config-env-php-toolow": "PHP $1 is instâlled.\nHoue'er, MediaWiki requires PHP $2 or heier.",
        "config-unicode-using-utf8": "Uising Brion Vibber's utf8_normalize.so fer Unicode normalization.",
        "config-unicode-using-intl": "Uising the [http://pecl.php.net/intl intl PECL extension] fer Unicode normalization.",
        "config-unicode-pure-php-warning": "<strong>Warnishment:</strong> The [http://pecl.php.net/intl intl PECL extension] is no available tae haunle Unicode normalisation, fawin back tae slaw pure-PHP implementation.\nGif ye rin ae hei-traffic steid, ye shid read ae wee bit oan [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode normalization].",
@@ -56,7 +55,7 @@
        "config-no-db": "Coudna fynd ae suitable database driver! Ye need tae instaw ae database driver fer PHP.\nThe follaein database types ar supported: $1.\n\nGif ye compiled PHP yersel, reconfeegure it wi ae database client enabled, fer example, uising <code>./confeegure --wi-mysqli</code>.\nGif ye installed PHP fae ae Debian or Ubuntu package, than ye need tae instaw forby, fer example, the <code>php5-mysql</code> package.",
        "config-outdated-sqlite": "<strong>Warnishment:</strong> ye have SQLite $1, this is lower than minimum required version $2. SQLite will be onavailable.",
        "config-no-fts3": "<strong>Warnishment:</strong> SQLite is compiled wioot the [//sqlite.org/fts3.html FTS3 module], rake features will be onavailable oan this backend.",
-       "config-register-globals": "<strong>Warnishment: PHP's <code>[http://php.net/register_globals register_globals]</code> optie is enabled.\nDisable it gif ye can.</strong>\nMediaWiki will wark, but yer server is exposed til poteential securitie vulnerabeelities.",
+       "config-magic-quotes-gpc": "<strong>Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] is active!</strong>\nThis option corrupts data input unpredictably.\nYe cannae install or uise MediaWiki unless this option is disabled.",
        "config-magic-quotes-runtime": "<strong>Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] is active!'</strong>\nThis optie rots data input onpredictably.\nYe canna install or uise MediaWiki onless this optie is disabled.",
        "config-magic-quotes-sybase": "<strong>Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] is active!</strong>\nThis optie rots data input onpredictably.\nYe canna install or uise MediaWiki onless this optie is disabled.",
        "config-mbstring": "<strong>Fatal: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] is active!</strong>\nThis optie causes mistaks an can rot data onpredictably.\nYe canna install or uise MediaWiki onless this optie is disabled.",
        "config-license-gfdl": "GNU Free Documentâtion License 1.3 or later",
        "config-license-pd": "Public Domain",
        "config-license-cc-choose": "Select ae custym Creative Commyns license",
-       "config-license-help": "Monie publeec wikis pit aw contreebutions unner ae [http://freedomdefined.org/Defineetion free license].\nThis heelps tae cræft ae sense o communitie ainership n encoorages lang-term contreebution.\nIt's naw generallie necessarie fer ae private or corporate wiki.\n\nGif ye wish tae be able tae uise tex fae Wikipedia, n ye want Wikipedia tae be able tae accept tex copied fae yer wiki, ye shid chuise <strong>Creative Commyns Attribution Shair Alike</strong>.\n\nWikipædia preeveeooslie uised the GNU Free Documentation License.\nThe GFDL is ae valid license, but it's difficult tae unnerstaunn.\nIt's difficult tae reuise content licensed unner the GFDL ava.",
+       "config-license-help": "Monie publeec wikis pit aw contreebutions unner ae [http://freedomdefined.org/Defineetion free license].\nThis heelps tae creaut ae sense o communitie ainership n encoorages lang-term contreebution.\nIt's naw generallie necessair fer ae preevate or corporate wiki.\n\nGif ye wish tae be able tae uise tex fae Wikipædia, n ye want Wikipædia tae be able tae accept tex copied fae yer wiki, than ye shid chuise <strong>Creative Commons Attribution Shair Alike</strong>.\n\nWikipædia preeveeooslie uised the GNU Free Documentation License.\nThe GFDL is ae valid license, but it's difficult tae unnerstaunn.\nMairower, it's difficult tae reuise content licensed unner the GFDL.",
        "config-email-settings": "Wab-mail settins",
        "config-enable-email": "Enable ootboond wab-mail",
        "config-enable-email-help": "Gif ye want wab-mail tae wark, [http://www.php.net/manual/en/mail.configuration.php PHP's mail settins] need tae be confeegured jyst richt.\nGif ye dinna want oni wab-mail features, ye can disable theim here.",
index 961264d..b27fcdd 100644 (file)
@@ -2,16 +2,20 @@
        "@metadata": {
                "authors": [
                        "Dbc334",
-                       "Eleassar"
+                       "Eleassar",
+                       "Yerpo"
                ]
        },
        "config-desc": "Namestitveni program za MediaWiki",
        "config-title": "Namestitev MediaWiki $1",
        "config-information": "Informacije",
+       "config-localsettings-upgrade": "Zaznana je bila datoteka <code>LocalSettings.php</code>.\nZa nadgradnjo te inštalacije prosim vnesite vrednost <code>$wgUpgradeKey</code> v polje za vnos spodaj.\nNašli jo boste v <code>LocalSettings.php</code>.",
        "config-localsettings-cli-upgrade": "Zaznana je bila datoteka <code>LocalSettings.php</code>.\nZa nadgradnjo te namestitve zaženite <code>update.php</code>",
        "config-localsettings-key": "Nadgraditveni ključ:",
        "config-localsettings-badkey": "Naveden ključ je napačen.",
        "config-upgrade-key-missing": "Zaznana je bila obstoječa namestitev MediaWiki.\nZa nadgradnjo te namestitve vstavite naslednjo vrstico na dno vaše <code>LocalSettings.php</code>:\n\n$1",
+       "config-localsettings-incomplete": "Kaže, da je obstoječa datoteka <code>LocalSettings.php</code> nepopolna. Vrednost $1 ni nastavljena. Prosimo, nastavite to vrednost v <code>LocalSettings.php</code> in kliknite \"{{int:Config-continue}}\".",
+       "config-localsettings-connection-error": "Prišlo je do napake pri povezovanju s podatkovno zbirko z nastavitvami, določenimi v <code>LocalSettings.php</code>. Prosimo popravite te nastavitve in poskusite znova.\n\n$1",
        "config-session-error": "Napaka pri začenjanju seje: $1",
        "config-session-expired": "Kot kaže, so vaši podatki seje potekli.\nSeje so konfigurirane za dobo $1.\nTo lahko povečate tako, da nastavite <code>session.gc_maxlifetime</code> v php.ini.\nPonovno zaženite postopek namestitve.",
        "config-no-session": "Vaši podatki seje so bili izgubljeni!\nPreverite vaš php.ini in se prepričajte, da je <code>session.save_path</code> nastavljena na ustrezno mapo.",
@@ -43,7 +47,6 @@
        "config-env-good": "Okolje je pregledano.\nLahko namestite MediaWiki.",
        "config-env-bad": "Okolje je pregledano.\nNe morete namestiti MediaWiki.",
        "config-env-php": "Nameščen je PHP $1.",
-       "config-env-php-toolow": "Nameščen je PHP $1.\nVendar pa MediaWiki zahteva PHP $2 ali višji.",
        "config-unicode-using-utf8": "Uporaba utf8_normalize.so Briona Vibberja za normalizacijo unikoda.",
        "config-unicode-using-intl": "Uporaba [http://pecl.php.net/intl razširitve PECL intl] za normalizacijo unikoda.",
        "config-memory-raised": "PHP-jev <code>memory_limit</code> je $1, dvignjen na $2.",
index 53010fb..2bdfb10 100644 (file)
@@ -51,7 +51,7 @@
        "config-env-good": "Miljön har kontrollerats.\nDu kan installera MediaWiki.",
        "config-env-bad": "Miljön har kontrollerats.\nDu kan inte installera MediaWiki.",
        "config-env-php": "PHP $1 är installerat.",
-       "config-env-php-toolow": "PHP $1 är installerat.\nMediaWiki kräver PHP $2 eller högre.",
+       "config-env-hhvm": "HHVM $1 är installerat.",
        "config-unicode-using-utf8": "Använder Brion Vibbers utf8_normalize.so för Unicode-normalisering.",
        "config-unicode-using-intl": "Använder [http://pecl.php.net/intl intl PECL-tillägget] för Unicode-normalisering.",
        "config-unicode-pure-php-warning": "'''Varning:''' [http://pecl.php.net/intl intl PECL-tillägget] är inte tillgängligt för att hantera Unicode-normalisering, faller tillbaka till en långsamt implementering i ren PHP.\nOm du driver en högtrafikerad webbplats bör du läsa lite om [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode-normalisering].",
@@ -59,7 +59,8 @@
        "config-no-db": "Kunde inte hitta en lämplig databasdrivrutin! Du måste installera en databasdrivrutin för PHP.\nFöljande databastyper stöds: $1.\n\nI du själv kompilerat din PHP, konfigurera den med en databasklient aktiverad genom att t.ex. använda <code>./configure --with-mysqli</code>.\nOm du installerade PHP från ett Debian- eller Ubuntupaket måste du även installera, t.ex. <code>php5-mysql</code>-paketet.",
        "config-outdated-sqlite": "'''Varning:''' du har SQLite $1, vilket är lägre än minimikravet version $2. SQLite kommer inte att vara tillgänglig.",
        "config-no-fts3": "'''Varning:''' SQLite kompileras utan [//sqlite.org/fts3.html FTS3-modulen], sökfunktioner kommer att vara otillgängliga på denna backend.",
-       "config-register-globals": "'''Varning: PHP:s <code>[http://php.net/register_globals register_globals]</code>-tillval är aktiverat.'''\n'''Inaktivera den om du kan.'''\nMediaWiki kommer att fungera, men din server exponeras för potentiella säkerhetshål.",
+       "config-register-globals-error": "<strong>Fel: PHP-alternativet <code>[http://php.net/register_globals register_globals]</code> är aktiverad.\nDen måste vara inaktiverad för att fortsätta med installationen.</strong>\nSe [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] för hjälp om hur man gör så.",
+       "config-magic-quotes-gpc": "<strong>Kritiskt: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_gpc är aktiv!</strong>\nDetta alternativ korrumperar inmatad data oförutsägbart.\nDu kan inte installera eller använda MediaWiki om detta alternativ är aktiverat.",
        "config-magic-quotes-runtime": "'''Kritiskt: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] är aktiv!'''\nDetta alternativ korrumperar inmatad data oförutsägbart.\nDu kan inte installera eller använda MediaWiki om detta alternativ är aktiverat.",
        "config-magic-quotes-sybase": "'''Kritiskt: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] är aktiv!'''\nDetta alternativ korrumperar inmatad data oförutsägbart.\nDu kan inte installera eller använda MediaWiki om detta alternativ är aktiverat.",
        "config-mbstring": "'''Kritiskt: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] är aktiv!'''\nDetta alternativ orsakar fel och kan korrumpera data oförutsägbart.\nDu kan inte installera eller använda MediaWiki om detta alternativ är aktiverat.",
@@ -70,6 +71,7 @@
        "config-memory-raised": "PHPs <code>memory_limit</code> är $1, ökad till $2.",
        "config-memory-bad": "''' Varning:''' PHP:s <code>memory_limit</code> är $1.\nDetta är förmodligen för lågt.\nInstallationen kan misslyckas!",
        "config-ctype": "'''Kritiskt:''' PHP måste kompileras med stöd för [http://www.php.net/manual/en/ctype.installation.php Ctype-tillägget].",
+       "config-iconv": "<strong>Kritiskt:</strong> PHP måste kompileras med stöd för [http://www.php.net/manual/en/iconv.installation.php iconv-tillägget].",
        "config-json": "'''Varning:''' PHP kompilerades utan JSON-stöd.\nDu måste antingen installera PHP JSON-tillägget eller [http://pecl.php.net/package/jsonc PECL jsonc]-tillägget före installationen av MediaWiki.\n* PHP-tillägget är inkluderat i Red Hat Enterprise Linux (CentOS) 5 och 6, men måste aktiveras i <code>/etc/php.ini</code> eller <code>/etc/php.d/json.ini</code>.\n* Vissa Linux-distributioner släppta efter maj 2013 har utelämnat PHP-tillägget och har istället inkluderat PECL-tillägget som <code>php5-json</code> eller <code>php-pecl-jsonc</code>.",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] är installerat",
        "config-apc": "[http://www.php.net/apc APC] är installerat",
        "config-license-gfdl": "GNU Free Documentation License 1.3 eller senare",
        "config-license-pd": "Public Domain",
        "config-license-cc-choose": "Välj en anpassad Creative Commons-licens",
-       "config-license-help": "Många publika wikis släpper alla bidrag under en  [http://freedomdefined.org/Definition fri licens].\nDetta bidrar till en känsla av gemensamt ägandeskap och uppmuntrar till långsiktiga bidrag.\nDet är i allmänhet inte nödvändigt för en privat eller företagswiki.\n\nOm du vill kunna använda text från Wikipedia, och du vill att Wikipedia ska kunna acceptera text kopierad ifrån din wiki bör du välja <strong>Creative Commons Erkännande-DelaLika</strong>.\n\nWikipedia använde tidigare  GNU Free Documentation License.\nGFDL är en giltig licens, men svår att förstå.\nDet är även svårt att återanvända innehåll som licensierats under GFDL.",
+       "config-license-help": "Många publika wikis släpper alla bidrag under en  [http://freedomdefined.org/Definition fri licens].\nDetta bidrar till en känsla av gemensamt ägandeskap och uppmuntrar till långsiktiga bidrag.\nDet är i allmänhet inte nödvändigt för en privat eller företagswiki.\n\nOm du vill kunna använda text från Wikipedia, och du vill att Wikipedia ska kunna acceptera text kopierad ifrån din wiki bör du välja <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nWikipedia använde tidigare  GNU Free Documentation License.\nGFDL är en giltig licens, men svår att förstå.\nDet är även svårt att återanvända innehåll som licensierats under GFDL.",
        "config-email-settings": "E-postinställningar",
        "config-enable-email": "Aktivera utgående e-post",
        "config-enable-email-help": "Om du vill att e-post ska fungera behöver,[http://www.php.net/manual/en/mail.configuration.php PHPs e-postinställningar] vara konfigurerad på rätt sätt.\nOm du inte vill ha några e-postfunktioner, kan du inaktivera dem här.",
        "config-memcache-badport": "Memcached-portnummer bör vara mellan $1 och $2.",
        "config-extensions": "Tillägg",
        "config-extensions-help": "Tilläggen ovan upptäcktes i din <code>./extensions</code>-katalog.\n\nDe kan kräva ytterligare konfiguration, men du kan aktivera dem nu.",
+       "config-skins": "Utseenden",
+       "config-skins-help": "Utseenden som listas upp ovan identifierades i din filkatalog <code>./skins</code>. Du måste aktivera minst en och välja ett som standard.",
+       "config-skins-use-as-default": "Använd detta utseende som standard",
+       "config-skins-missing": "Ingen utseenden hittades; MediaWiki använder ett reservutseende tills du installerar några.",
+       "config-skins-must-enable-some": "Du måste välja minst ett utseende att aktivera.",
+       "config-skins-must-enable-default": "Utseendet som valdes som standard måste aktiveras.",
        "config-install-alreadydone": "''' Varning:''' Du verkar redan ha installerat MediaWiki och försöker installera det igen.\nVänligen fortsätt till nästa sida.",
        "config-install-begin": "Genom att trycka på \"{{int:config-continue}}\", påbörjar du installationen av MediaWiki.\nOm du fortfarande vill göra ändringar tryck på \"{{int:config-back}}\".",
        "config-install-step-done": "klar",
        "config-install-stats": "Initierar statistik",
        "config-install-keys": "Genererar hemliga nycklar",
        "config-insecure-keys": "'''Varning:''' {{PLURAL:$2|En säkerhetsnyckel|Säkerhetsnycklar}} ($1) som generades under installationen är inte helt {{PLURAL:$2|säker|säkra}} . Överväg att ändra {{PLURAL:$2|den|dem}} manuellt.",
+       "config-install-updates": "Förhindra att onödiga uppdateringar körs",
+       "config-install-updates-failed": "<strong>Fel:</strong> Infogning av uppdateringsnycklar i tabeller misslyckades med följande fel:$1",
        "config-install-sysop": "Skapar administratörskonto",
        "config-install-subscribe-fail": "Det gick inte att prenumerera på mediawiki-announce: $1",
        "config-install-subscribe-notpossible": "cURL är inte installerad och <code>allow_url_fopen</code> är inte tillgänglig.",
index 6ec8860..83c51ee 100644 (file)
@@ -18,7 +18,7 @@
        "config-localsettings-badkey": "Sağladığınız anahtar doğru değil.",
        "config-upgrade-key-missing": "Mevcut bir MediaWiki kurulumu algılandı.\nBu kurulumu güncelleştirmek için, lütfen aşağıdaki satırı <code>LocalSettings.php</code> dosyanızın en altına koyun:\n\n$1",
        "config-localsettings-incomplete": "Mevcut <code>LocalSettings.php</code> eksik gibi görünüyor.\n $1  değişkeni ayarlanmamış.\nLütfen <code>LocalSettings.php</code> dosyasını değiştirin bu değişkenleri kuracak, ve tıklayın  \"{{int:Config-cuntinue}}\".",
-       "config-localsettings-connection-error": "<code>LocalSettings.php</code> ya da <code>AdminSettings.php</code> dosyasında belirtilen ayarları kullanarak veritabanına bağlanırken bir hatayla karşılaşıldı. Lütfen bu ayarları düzeltin ve yeniden deneyin.\n\n$1",
+       "config-localsettings-connection-error": "<code>LocalSettings.php</code> içinde belirtilen ayarları kullanarak veritabanına bağlanırken bir hatayla karşılaşıldı. Lütfen bu ayarları düzeltin ve yeniden deneyin.\n\n$1",
        "config-session-error": "Oturum başlatılırken hata: $1",
        "config-session-expired": "Oturum bilgilerinizin süresi bitmiş.\nOturumların süresi $1 kadardır.\nBu süreyi php.ini' deki <code>session.gc_maxlifetime</code> ayarla arttırabilirsiniz.\nKurulum işlemini yeniden başlatın.",
        "config-no-session": "Oturum bilgileriniz silinmiş.\nphp.ini dosyanızı kontrol edin ve <code>session.save_path</code> ayarının uygun bir klasöre yönlendiğinden emin olun.",
        "config-restart": "Evet, yeniden başlat",
        "config-welcome": "===Ortam Kontrolleri===\nOrtamın Mediawiki kurulumuna uygun olup olmadığını anlamak için basit kontroller yapılacak.\nKurulumu nasıl tamamlayacağınız konusunda destek isterken bu bilgileri eklemeyi unutmayın.",
        "config-copyright": "=== Telif Hakları ve Koşulları ===\n\n$1\n\nBu program ücretsiz bir yazılımdır; yeniden dağıtabilir veya Özgür Yazılım Kuruluşu tarafından yayınlanan (GNU) Genel Kamu Lisansı koşulları altında değiştirebilirsiniz; isterseniz ikinci lisans sürümünü veya (sizin seçeneğiniz) herhangi bir sonraki lisans sürümünü kullanabilirsiniz.\n\nBu program, faydalı olacağı umuduyla dağıtılmaktadır, ancak ''' herhangi bir garantisi yoktur '''; ''' uygunluk ''' veya ''' belirli bir amaca uygunluk ''' gibi dolaylı garantileri bile yoktur.\nDaha fazla ayrıntı için (GNU) Genel Kamu Lisansına bakınız.\n\nBu program ile birlikte <doclink href=\"Copying\">bir (GNU) Genel Kamu Lisansının bir kopyasını </doclink> almış olmanız gerekir; bu program (GNU) Genel Kamu Lisansı ile dağıtılmadıysa, Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, ABD adresine yazın veya [http://www.gnu.org/copyleft/gpl.html online olarak okuyun].",
+       "config-sidebar": "* [//www.mediawiki.org MediaWiki ana sayfa]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Kullanıcı Rehberi]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents Yetkili Rehberi]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ SSS]\n----\n* <doclink href=Readme>Beni oku</doclink>\n* <doclink href=ReleaseNotes>Sürüm notları</doclink>\n* <doclink href=Copying>Kopyalama</doclink>\n* <doclink href=UpgradeDoc>Yükseltme</doclink>",
        "config-env-good": "Ortam kontrol edildi.\nMediaWiki'yi kurabilirsiniz.",
        "config-env-bad": "Ortam kontrol edildi.\nMediaWiki'yi kuramazsınız.",
        "config-env-php": "PHP $1 kurulu.",
-       "config-env-php-toolow": "PHP $1 kurulu.\nAncak, MediaWiki PHP $2 ya da daha yenisine ihtiyaç duyuyor.",
        "config-unicode-using-utf8": "Unikod normalleştirmesi için Brion Vibber'in utf8_normalize.so kullanılıyor.",
        "config-unicode-using-intl": "Unikod normalleştirmesi için [http://pecl.php.net/intl intl PECL uzantısı] kullanılıyor.",
        "config-xml-bad": "PHP 'nin XML modülü eksik.\nMediaWiki bu modüldeki fonksiyonlara ihtiyaç duyar ve şimdiki kurulumda çalışmayacaktır.\nMandrake kullanıyorsanız php-xml paketini yükleyin.",
        "config-install-mainpage-failed": "Ana sayfa eklenemedi:$1",
        "config-download-localsettings": "İndir <code>LocalSettings.php</code>",
        "config-help": "Yardım",
+       "config-help-tooltip": "genişletmek için tıklayın",
        "config-nofile": "\"$1\" dosyası bulunamadı. Silindi mi?",
        "config-extension-link": "Vikinizin [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions eklentileri] desteklediğini biliyor musunuz?\n\n[//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category Eklentileri kategorilerine göre] inceleyebilir ya da tüm eklentilerin listesini görmek için [//www.mediawiki.org/wiki/Extension_Matrix Eklenti Matrisine] bakabilirsiniz.",
        "mainpagetext": "'''MediaWiki başarı ile kuruldu.'''",
index 2065352..9eee1a7 100644 (file)
@@ -55,7 +55,6 @@
        "config-env-good": "Перевірку середовища успішно завершено.\nВи можете встановити MediaWiki.",
        "config-env-bad": "Було проведено перевірку середовища. Ви не можете встановити MediaWiki.",
        "config-env-php": "Встановлено версію PHP: $1.",
-       "config-env-php-toolow": "Встановлено PHP $1.\nНатомість MediaWiki вимагає PHP $2 і вище.",
        "config-unicode-using-utf8": "Використовувати utf8_normalize.so Брайона Віббера для нормалізації Юнікоду.",
        "config-unicode-using-intl": "Використовувати [http://pecl.php.net/intl міжнародне розширення PECL] для нормалізації Юнікоду.",
        "config-unicode-pure-php-warning": "'''Увага''': [http://pecl.php.net/intl міжнародне розширення PECL] не може провести нормалізацію Юнікоду.\nЯкщо ваш сайт має високий трафік, вам варто почитати про [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations нормалізацію Юнікоду].",
@@ -63,7 +62,8 @@
        "config-no-db": "Не вдалося знайти відповідний драйвер бази даних! Вам необхідно встановити драйвер бази даних для PHP. Підтримуються такі типи баз даних: $1.\n\nЯкщо ви скомпілювали PHP самостійно, переналаштуйте його з включенням клієнта бази даних, наприклад за допомогою <code>./configure --with-mysqli</code>.\n\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": "'''Увага: Опція PHP <code>[http://php.net/register_globals register_globals]</code> увімкнена.'''\n'''Вимкніть її, якщо це можливо.'''\nMediaWiki буде працювати, але Ваш сервер буде більш вразливим до потенційного проникнення зовні.",
+       "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": "'''Фатальна помилка: [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/en/ref.info.php#ini.magic-quotes-runtime 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, поки не буде вимкнено цю опцію.",
@@ -74,6 +74,7 @@
        "config-memory-raised": "Обмеження пам'яті PHP (<code>memory_limit</code>) $1, піднято до $2.",
        "config-memory-bad": "'''Увага:''' Розмір пам'яті PHP (<code>memory_limit</code>) становить $1.\nІмовірно, це замало.\nВстановлення може не вдатись!",
        "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-xcache": "[http://xcache.lighttpd.net/ XCache] встановлено",
        "config-apc": "[http://www.php.net/apc APC] встановлено",
        "config-license-gfdl": "GNU Free Documentation License 1.3 або пізніша",
        "config-license-pd": "Суспільне надбання (Public Domain)",
        "config-license-cc-choose": "Виберіть одну з ліцензій Creative Commons",
-       "config-license-help": "Чимало загальнодоступних вікі публікують увесь свій вміст під [http://freedomdefined.org/Definition вільною ліцензією]. Це розвиває відчуття спільної власності і заохочує довготривалу участь. У загальному випадку для приватної чи корпоративної вікі у цьому немає необхідності.\n\nЯкщо Ви хочете мати змогу використовувати текст з Вікіпедії і дати Вікіпедії змогу використовувати текст, скопійований з Вашої вікі, вам необхідно обрати '''Creative Commons Attribution Share Alike'''.\n\nРаніше Вікіпедія використовувала GNU Free Documentation License.\nGFDL — допустима ліцензія, але у ній важко розібратися, а контент під GFDL важко використовувати повторно.",
+       "config-license-help": "Чимало загальнодоступних вікі публікують увесь свій вміст під [http://freedomdefined.org/Definition вільною ліцензією]. Це розвиває відчуття спільної власності і заохочує довготривалу участь. У загальному випадку для приватної чи корпоративної вікі у цьому немає необхідності.\n\nЯкщо Ви хочете мати змогу використовувати текст з Вікіпедії і дати Вікіпедії змогу використовувати текст, скопійований з Вашої вікі, вам необхідно обрати <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nРаніше Вікіпедія використовувала GNU Free Documentation License.\nGFDL — допустима ліцензія, але у ній важко розібратися, а контент під GFDL важко використовувати повторно.",
        "config-email-settings": "Налаштування електронної пошти",
        "config-enable-email": "Увімкнути вихідну електронну пошту",
        "config-enable-email-help": "Якщо Ви хочете, що електронна пошта працювала, необхідно виставити коректні [http://www.php.net/manual/en/mail.configuration.php налаштування пошти у PHP].\nЯкщо Вам не потрібні жодні можливості електронної пошти у вікі, можете тут їх відключити.",
        "config-memcache-badport": "Номери портів Memcached повинні лежати в межах від $1 до $2.",
        "config-extensions": "Розширення",
        "config-extensions-help": "Розширення, перераховані вище, були знайдені у папці <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": "Тема, обрана за замовчуванням, повинна бути увімкнена.",
        "config-install-alreadydone": "'''Увага:''' Здається, Ви вже встановлювали MediaWiki і зараз намагаєтесь встановити її знову.\nБудь ласка, перейдіть на наступну сторінку.",
        "config-install-begin": "Натискаючи \"{{int:config-continue}}\", Ви розпочинаєте встановлення MediaWiki.\nЯкщо Ви все ще хочете внести зміни, натисніть \"{{int:config-back}}\".",
        "config-install-step-done": "виконано",
        "config-install-stats": "Ініціалізація статистики",
        "config-install-keys": "Генерація секретних ключів",
        "config-insecure-keys": "'''Увага:''' {{PLURAL:$2|1=Секретний ключ|Секретні ключі}} ($1), {{PLURAL:$2|1=згенерований в процесі встановлення, недостатньо надійний|згенеровані в процесі встановлення, недостатньо надійні}}. Розгляньте можливість {{PLURAL:$2|1=його|їх}} заміни вручну.",
+       "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> не доступна.",
index e39477b..f4dbdd7 100644 (file)
@@ -20,7 +20,8 @@
                        "Kuailong",
                        "Zjzengdongyang",
                        "Mywood",
-                       "Impersonator 1"
+                       "Impersonator 1",
+                       "Fengchao"
                ]
        },
        "config-desc": "MediaWiki安装程序",
@@ -65,7 +66,7 @@
        "config-env-good": "环境检查已经完成。您可以安装MediaWiki。",
        "config-env-bad": "环境检查已经完成。您不能安装MediaWiki。",
        "config-env-php": "PHP $1已安装。",
-       "config-env-php-toolow": "已安装PHP $1;但是,MediaWiki需要PHP $2或更高版本。",
+       "config-env-hhvm": "HHVM $1已安装。",
        "config-unicode-using-utf8": "使用Brion Vibber的utf8_normalize.so实现Unicode正常化。",
        "config-unicode-using-intl": "使用[http://pecl.php.net/intl intl PECL扩展程序]标准化Unicode。",
        "config-unicode-pure-php-warning": "<strong>警告:</strong>因为尚未安装 [http://pecl.php.net/intl intl PECL 扩展]以处理 Unicode 正常化,故只能退而采用运行较慢的纯 PHP 实现的方法。\n如果您运行着一个高流量的站点,请参阅 [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode 正常化]一文。",
@@ -73,7 +74,8 @@
        "config-no-db": "找不到合适的数据库驱动!您需要为PHP安装数据库驱动。目前支持以下数据库:$1。如果您是自己编译的PHP,请重新配置他与数据库客户端将其启用,诸如,使用<code>./configure --with-mysqli</code>。如果您从Debian或Ubuntu包安装了PHP,之后您仍需要安装诸如<code>php5-mysql</code>包。",
        "config-outdated-sqlite": "'''警告''':您已安装SQLite $1,但是它的版本低于最低要求版本$2。因此您无法选择SQLite。",
        "config-no-fts3": "'''警告''':已编译的SQLite不包含[//sqlite.org/fts3.html FTS3模块],后台搜索功能将不可用。",
-       "config-register-globals": "'''警告:PHP的<code>[http://php.net/register_globals register_globals]</code>选项被启用。请尽量禁用该功能,'''虽然不会影响MediaWiki的运行,但您的服务器会被暴露给潜在的安全漏洞。",
+       "config-register-globals-error": "<strong>错误:PHP<code>[http://php.net/register_globals register_globals]</code>选项被启用。必须禁用它才能继续安装。</strong>关于如何禁用,参见[https://www.mediawiki.org/wiki/register_globals mediawiki.org此页]。",
+       "config-magic-quotes-gpc": "<strong>致命错误:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc]已启用!</strong>此选项会无法挽回的破坏输入数据。除非此选项被禁用否则您不能安装或使用MediaWiki。",
        "config-magic-quotes-runtime": "'''毁灭性错误:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime]已启用!'''\n此选项会无法预测地破坏输入的数据,请将其禁用,否则您将不能安装或使用MediaWiki。",
        "config-magic-quotes-sybase": "'''毁灭性错误:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_sybase]已启用!'''\n此选项会无法预测地破坏输入的数据,请将其禁用,否则您将不能安装或使用MediaWiki。",
        "config-mbstring": "'''毁灭性错误:[http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]已启用!'''\n此选项会导致错误并不可预测地破坏数据,请将其禁用,否则您将不能安装或使用MediaWiki。",
@@ -84,6 +86,7 @@
        "config-memory-raised": "PHP的内存使用上限<code>memory_limit</code>为$1,自动提升到$2。",
        "config-memory-bad": "'''警告:'''PHP的内存使用上限<code>memory_limit</code>为$1。该设定可能过低,并导致安装失败!",
        "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": "'''致命问题:''' 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-xcache": "[http://xcache.lighttpd.net/ XCache]已安装",
        "config-apc": "[http://www.php.net/apc APC]已安装",
        "config-db-username": "数据库用户名:",
        "config-db-password": "数据库密码:",
        "config-db-password-empty": "请为新数据库用户$1输入密码。尽管您可以创建不使用密码的用户,但这样做并不安全。",
-       "config-db-username-empty": "您必须输入用于“{{int:config-db-username}}”的值",
+       "config-db-username-empty": "您必须输入用于“{{int:config-db-username}}”的值",
        "config-db-install-username": "请输入在安装过程中用于连接数据库的用户名。请勿输入MediaWiki帐号的用户名,请输入您数据库的用户名。",
        "config-db-install-password": "请输入在安装过程中用于连接数据库的密码。请勿输入MediaWiki帐号的密码,请输入您数据库的密码。",
        "config-db-install-help": "请输入在安装过程中用于连接数据库的用户名和密码。",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
        "config-mysql-myisam-dep": "'''警告''':您选择了MyISAM作为MySQL的存储引擎,MediaWiki并不推荐您这么做,因为:\n* 它仅能通过表锁定来勉强支持并发\n* 与其他引擎相比,它更容易被损坏\n* MediaWiki代码库并不总会去处理MyISAM\n\n如果您的MySQL程序支持InnoDB,我们高度推荐您使用该引擎替代MyISAM。\n如果您的MySQL程序不支持InnoDB,请考虑升级。",
-       "config-mysql-only-myisam-dep": "''''警告:'''MyISAM是MySQL在此机器上唯一可用的存储引擎,但它不适合用于MediaWiki,因为:\n*因为表级锁定,它几乎不支持并发。\n*它相比其他引擎更容易损坏。\n*MediaWiki代码不能总是按照预期操作MyISAM。\n\n你的MySQL不支持InnoDB,是时候升级了。",
+       "config-mysql-only-myisam-dep": "<strong>警告:</strong>MyISAM是MySQL在此机器上唯一可用的存储引擎,但它不适合用于MediaWiki,因为:\n*因为表级锁定,它几乎不支持并发。\n*它相比其他引擎更容易损坏。\n*MediaWiki代码不能总是按照预期操作MyISAM。\n\n你的MySQL不支持InnoDB,是时候升级了。",
        "config-mysql-engine-help": "'''InnoDB'''通常是最佳选项,因为它对并发操作有着良好的支持。\n\n'''MyISAM'''在单用户或只读环境下可能会有更快的性能表现。但MyISAM数据库出错的概率一般要大于InnoDB数据库。",
        "config-mysql-charset": "数据库字符集:",
        "config-mysql-binary": "二进制",
        "config-profile-help": "如果您允许尽量多的人编写wiki,网站上的内容会更加丰富。在MediaWiki中,您可以轻松地审查最近更改,并轻易回退掉新手或破坏者造成的损害。\n\n然而,许多人觉得让MediaWiki存在多种角色将更加好用;同时,要说服所有人都愿以wiki的方式作贡献并非一件易事。因此,您可以有以下选择:\n\n'''{{int:config-profile-wiki}}'''允许包括未登录用户在内的所有人编辑。'''{{int:config-profile-no-anon}}'''的wiki需要额外的注册流程,这有可能会阻碍随意贡献者。\n\n'''{{int:config-profile-fishbowl}}'''模式只允许获批准的用户编辑,但对公众开放页面浏览(包括历史记录)。'''{{int:config-profile-private}}'''则只允许获批准的用户浏览、编辑页面。\n\n安装完成后,您还可以对用户权限进行更多、更复杂的配置,参见[//www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights 相关的使用手册]。",
        "config-license": "版权和许可证:",
        "config-license-none": "页脚无许可证",
-       "config-license-cc-by-sa": "ç\9f¥è¯\86å\85±äº«ç½²å\90\8d\9b¸å\90\8cæ\96¹å¼\8få\88\86享",
+       "config-license-cc-by-sa": "ç\9f¥è¯\86å\85±äº«ç½²å\90\8d\9b¸å\90\8cæ\96¹å¼\8få\85±享",
        "config-license-cc-by": "知识共享署名",
        "config-license-cc-by-nc-sa": "知识共享署名-非商业性使用-相同方式共享",
        "config-license-cc-0": "知识共享Zero(公有领域)",
        "config-license-gfdl": "GNU自由文档许可证1.3或更高版本",
        "config-license-pd": "公有领域",
        "config-license-cc-choose": "选择自定义的知识共享许可证",
-       "config-license-help": "许多公共wiki会以[http://freedomdefined.org/Definition 自由许可证]的方式释放出编者的所有贡献。这有助于构建社区的主人翁意识,并能鼓励长期贡献。对于非公共wiki或公司wiki,这并非必要条件。\n\n如果您希望使用来自维基百科的内容,并希望维基百科能接受复制自您的wiki的内容,您应当选择<strong>知识共享-署名-相同方式共享</strong>。\n\nGNU自由文档许可证是维基百科曾经使用过的许可证,并迄今有效。然而,该许可证难以理解,并会增加重用内容的难度。",
+       "config-license-help": "许多公共wiki将所有用户贡献置于[http://freedomdefined.org/Definition 自由许可证]之下。这有助于构建社区的主人翁意识,并鼓励长期贡献。对于非公共wiki或公司wiki,这并非必要条件。\n\n如果您希望使用来自维基百科的内容,并希望维基百科能接受复制自您的wiki的内容,您应当选择<strong>{{int:config-license-cc-by-sa}}</strong>\n\nGNU自由文档许可证是维基百科曾经使用过的许可证,并迄今有效。然而,该许可证难以理解,并会增加重用内容的难度。",
        "config-email-settings": "电子邮件设置",
        "config-enable-email": "启用出站电子邮件",
        "config-enable-email-help": "如果您希望使用电子邮件功能,请正确配置[http://www.php.net/manual/en/mail.configuration.php PHP的邮件设定]。如果您不需要任何电子邮件功能,请在此处禁用它。",
        "config-memcache-badport": "Memcached的端口号应该在$1到$2之间。",
        "config-extensions": "扩展程序",
        "config-extensions-help": "已在您的<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": "默认选择的皮肤必须启用。",
        "config-install-alreadydone": "'''警告:'''您似乎已经安装了MediaWiki,并试图重新安装它。请前往下一个页面。",
        "config-install-begin": "点击“{{int:config-continue}}”后,您将开始安装MediaWiki。如果您还想对配置作一些修改,请点击“{{int:config-back}}”。",
        "config-install-step-done": "完成",
        "config-install-stats": "初始化统计",
        "config-install-keys": "生成密钥中",
        "config-insecure-keys": "'''警告''':在安装过程中生成的{{PLURAL:$2|安全密钥|安全密钥}}($1){{PLURAL:$2|并|并}}不一定安全。请考虑手动更改{{PLURAL:$2|它|它们}}。",
+       "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>也不可用。",
index a6e87cf..b860dc6 100644 (file)
                        "아라",
                        "Liuxinyu970226",
                        "Xiaomingyan",
-                       "Cwlin0416"
+                       "Cwlin0416",
+                       "S8321414",
+                       "LNDDYL",
+                       "NigelSoft"
                ]
        },
        "config-desc": "MediaWiki 安裝程式",
@@ -23,9 +26,9 @@
        "config-upgrade-key-missing": "已偵測到先前安裝的 MediaWiki。\n要升級目前安裝的版本,請將下列文字附加到 <code>LocalSettings.php</code> 的檔案最下方:\n\n$1",
        "config-localsettings-incomplete": "目前的 <code>LocalSettings.php</code> 檔案不完整。\n未設定參數 $1。\n請將此參數設定至 <code>LocalSettings.php</code> 中,並點選 \"{{int:Config-continue}}\"。",
        "config-localsettings-connection-error": "使用 <code>LocalSettings.php</code> 中所指定的資料庫設定連線發生錯誤。 請修復相關設定並再試一次。\n\n$1",
-       "config-session-error": "開始工作階段錯誤:$1",
-       "config-session-expired": "您的工作階段已過期。\n目前設定的工作階段期限為 $1。\n您可以在 php.ini 設定檔中設定 <code>session.gc_maxlifetime</code> 的參數來延長此期限。\n重新開始安裝程序。",
-       "config-no-session": "您的工作階段資料遺失!\n請檢查 php.ini 設定檔並確認 <code>session.save_path</code> 所設定的目錄是否合適。",
+       "config-session-error": "開始連線階段錯誤:$1",
+       "config-session-expired": "您的連線階段已過期。\n目前設定的工作階段期限為 $1。\n您可以在 php.ini 設定檔中設定 <code>session.gc_maxlifetime</code> 的參數來延長此期限。\n重新開始安裝程序。",
+       "config-no-session": "您的連線階段資料遺失!\n請檢查 php.ini 設定檔並確認 <code>session.save_path</code> 所設定的目錄是否合適。",
        "config-your-language": "您的語言:",
        "config-your-language-help": "請選擇接下來安裝程序中要使用的語言。",
        "config-wiki-language": "Wiki 語言:",
        "config-restart": "是的,重新開始",
        "config-welcome": "=== 環境檢查 ===\n現在會做基本的檢查,檢查環境是否符合 MediaWiki 安裝所需。\n若您要尋求如何完成安裝的協助,請記得提供以下訊息。",
        "config-copyright": "=== 版權聲明與授權條款 ===\n\n$1\n\n本程式為自由軟體;您可依據自由軟體基金會所發表的 GNU 通用公共授權條款規定,將本程式重新發佈與/或修改;無論您依據的是本授權條款的第二版或 (您可自行選擇) 之後的任何版本。\n\n本程式發佈的目的是希望可以提供幫助,但 <strong>不負任何擔保責任</strong>;亦無隱含對 <strong>適售性</strong> 或 <strong>特定用途的適用性</strong> 的情形擔保。詳情請參照 GNU 通用公共授權。\n\n您應已隨本程式收到 <doclink href=\"Copying\">GNU 通用公共授權條款的副本</doclink>;如果沒有,請信件通知自由軟體基金會,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA,或 [http://www.gnu.org/copyleft/gpl.html 線上閱讀]。",
-       "config-sidebar": "* [www.mediawiki.org/wiki/MediaWiki/zh-hant MediaWiki 首頁]\n* [www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents/zh 使用者指南]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents/zh 管理者指南]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/zh-hant 常見問題集]\n----\n* <doclink href=Readme>讀我說明</doclink>\n* <doclink href=ReleaseNotes>發行說明</doclink>\n* <doclink href=Copying>版權聲明</doclink>\n* <doclink href=UpgradeDoc>升級</doclink>",
+       "config-sidebar": "* [//www.mediawiki.org/wiki/MediaWiki/zh-hant MediaWiki 首頁]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents/zh 使用者指南]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents/zh 管理員指南]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/zh 常見問題集]\n----\n* <doclink href=Readme>讀我說明</doclink>\n* <doclink href=ReleaseNotes>發行說明</doclink>\n* <doclink href=Copying>版權聲明</doclink>\n* <doclink href=UpgradeDoc>升級</doclink>",
        "config-env-good": "環境檢查已完成。\n您可以安裝 MediaWiki。",
        "config-env-bad": "環境檢查已完成。\n您無法安裝 MediaWiki。",
        "config-env-php": "PHP $1 已安裝。",
-       "config-env-php-toolow": "已安裝 PHP $1。\n但 MediaWiki 需要 PHP $2 或更新的版本。",
+       "config-env-hhvm": "HHVM $1 已安裝。",
        "config-unicode-using-utf8": "使用 Brion Vibber 的 utf8_normalize.so 做 Unicode 正規化。",
        "config-unicode-using-intl": "使用 [http://pecl.php.net/intl intl PECL 擴充套件] 做 Unicode 正規化。",
        "config-unicode-pure-php-warning": "<strong>警告:</strong> 無法使用 [http://pecl.php.net/intl intl PECL 擴充套件] 處理 Unicode 正規化,故回退使用純 PHP 實作的正規化程式,此方式處理速度較緩慢。\n\n如果您的網站瀏覽人次很高,您應先閱讀 [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations/zh Unicode 正規化]。",
@@ -63,7 +66,8 @@
        "config-no-db": "找不到合適的資料庫驅動程式!您需要安裝 PHP 資料庫驅動程式。\n目前支援以下類型的資料庫: $1 。\n\n如果您是自行編譯 PHP,您必須重新設定並開啟資料庫客戶端,例:使用 <code>./configure --with-mysqli</code> 指令參數。\n如果您是使用 Debian 或 Ubuntu 的套件安裝,您則需要額外安裝,例:<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": "<strong>警告:PHP 的<code>[http://php.net/register_globals register_globals]</code>選項已開啟,如果可以請關閉該選項。</strong>\nMediaWiki 仍可正常執行,但您的伺服器將會有潛藏的安全性問題。",
+       "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。",
@@ -74,6 +78,7 @@
        "config-memory-raised": "PHP 的記憶體使用上限 <code>memory_limit</code> 目前為 $1,自動提高到 $2。",
        "config-memory-bad": "<strong>警告:</strong>PHP 的記憶體使用上限 <code>memory_limit</code> 為 $1。\n該設定值可能過低。\n這可能導致後續的安裝失敗!",
        "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 Enterprice 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-xcache": "[http://xcache.lighttpd.net/ XCache] 已安裝",
        "config-apc": "[http://www.php.net/apc APC] 已安裝",
        "config-db-name-help": "請輸入一個可以辨識您的 Wiki 的名稱,\n請勿包含空格。\n\n如果您使用的是共用的網頁主機,您的主機提供商會給您一個指定的資料庫名稱,或者讓您透過管理介面建立資料庫。",
        "config-db-name-oracle": "資料庫 Schema:",
        "config-db-account-oracle-warn": "目前有三種支援 Oracle 做為後端資料庫的方案:\n\n如果您希望在安裝的過程中自動建立新的資料庫,請提供具有 SYSDBA 權限的帳號並且提供未來要給網頁存取使用的資料庫帳號及密碼。或者您可以手動建立給網頁存取使用的資料庫帳號 (請確保該帳號有建立 Schema Object 的權限),再不然您可以提供兩組不同的帳號,一組用來建立權限,而另一組用來做為網頁存取使用。\n\n本次安裝建立的帳號以及權限所需要的 Script,可以在 \"maintenance/oracle/\" 中找到。\n請注意,若您使用有限制的帳號將會預設關閉所有維護性功能。",
-       "config-db-install-account": "å®\89è£\9dç¨\8båº\8f使ç\94¨ç\9a\84使ç\94¨è\80\85帳è\99\9f",
+       "config-db-install-account": "å®\89è£\9dç¨\8bå¼\8f使ç\94¨ç\9a\84使ç\94¨è\80\85帳è\99\9f",
        "config-db-username": "資料庫使用者名稱:",
        "config-db-password": "資料庫密碼:",
        "config-db-password-empty": "請輸入新增資料庫使用者 $1 的密碼。\n雖然您可以不設定任何密碼,但這樣做並不安全。",
        "config-sqlite-cant-create-db": "無法建立資料庫檔案 <code>$1</code>。",
        "config-sqlite-fts3-downgrade": "PHP 不支援 FTS3,正在降級資料表。",
        "config-can-upgrade": "在資料庫中找到 MediaWiki 的資料表。\n要升級至 MediaWiki $1,請點選 <strong>繼續</strong>。",
-       "config-upgrade-done": "升級完成。\n\n現在您可以 [$1 開始使用您的 Wiki] 了。\n\n如果您需要重新產生 <code>LocalSettings.php</code> 檔案,請點下方按鈕。\n除非您的 Wiki 出現了問題,否則我們 <strong>不建議</strong> 您執行此操作。",
+       "config-upgrade-done": "升級完成。\n\n現在您可以 [$1 開始使用您的 Wiki] 了。\n\n如果您需要重新產生 <code>LocalSettings.php</code> 檔案,請點下方按鈕。\n除非您的 Wiki 出現了問題,否則我們 <strong>不建議</strong> 您執行此操作。",
        "config-upgrade-done-no-regenerate": "升級完成。\n\n現在您可以 [$1 開始使用您的 Wiki] 了。",
        "config-regenerate": "重新產生 LocalSettings.php →",
        "config-show-table-status": "<code>SHOW TABLE STATUS</code> 查詢失敗!",
        "config-admin-password-blank": "輸入管理員帳號密碼。",
        "config-admin-password-mismatch": "兩次輸入的密碼並不相同。",
        "config-admin-email": "電子郵件位址:",
-       "config-admin-email-help": "在此輸入的電子郵件信箱可用來接收 Wiki 上其他使用者所發送的訊息、重設您的密碼與通知監視列表中頁面更動。您可將此欄位留空。",
+       "config-admin-email-help": "在此輸入的電子郵件信箱可用來接收 Wiki 上其他使用者所傳送的訊息、重設您的密碼與通知監視清單中頁面更動。您可將此欄位留空。",
        "config-admin-error-user": "建立管理員帳號 \"<nowiki>$1</nowiki>\" 時發送內部錯誤。",
        "config-admin-error-password": "設定管理員 \"<nowiki>$1</nowiki>\" 的密碼時發送內部錯誤:<pre>$2</pre>",
-       "config-admin-error-bademail": "您輸入了不正確的電子郵件址。",
+       "config-admin-error-bademail": "您輸入了不正確的電子郵件址。",
        "config-subscribe": "訂閱 [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce 發佈公告郵寄清單]。",
        "config-subscribe-help": "這是一個用於發佈公告的低郵件量郵寄清單,內容包括重要的安全公告。\n您應該訂閱它並在 MediaWiki 發佈新版的時候更新系統。",
-       "config-subscribe-noemail": "您正嘗試不填寫電子郵件地址訂閱發佈公告郵寄清單。 \n請如果您希望訂閱郵寄清單,請提供一個有效的電子郵件地址。",
+       "config-subscribe-noemail": "您正嘗試不填寫電子郵件位址訂閱發佈公告郵寄清單。 \n請如果您希望訂閱郵寄清單,請提供一個有效的電子郵件位址。",
        "config-almost-done": "您快要完成了!\n您現在可以跳過其餘的設定項目並且立即安裝 Wiki。",
        "config-optional-continue": "多問我一些問題吧。",
        "config-optional-skip": "我已經不耐煩了,請趕緊安裝 Wiki。",
        "config-license-gfdl": "GNU 自由文件授權條款 1.3 或更高版本",
        "config-license-pd": "公共領域",
        "config-license-cc-choose": "請選擇一個自訂的創作共用授權條款",
-       "config-license-help": "許多開放式 Wiki 會以 [http://freedomdefined.org/Definition 自由授權條款] 的方式釋放出編者的所有貢獻,這有助於構建社群的所有權,並且能鼓勵長期貢獻。對於封閉式的 Wiki 或公司 Wiki,則是非必要的。\n\n如果您希望使用來自維基百科(Wikipedia)的內容,並希望維基百科能接受您的 Wiki 內容,請應選擇 <strong>創作共用 Attribution Share Alike</strong> 授權條款。\n\n維基百科̽(Wikipedia)先前是使用 GNU 自由文件授權條款,\n但該授權條款的內容較難理解,因此較難再利用在該條款底下的內容。",
+       "config-license-help": "許多開放式 Wiki 會以 [http://freedomdefined.org/Definition 自由授權條款] 的方式釋放出編者的所有貢獻,這有助於構建社群的所有權,並且能鼓勵長期貢獻。對於封閉式的 Wiki 或公司 Wiki 則是非必要的。\n\n如果您希望使用來自維基百科(Wikipedia)的內容,並希望維基百科能接受您的 Wiki 內容,請應選擇 <strong>{{int:config-license-cc-by-sa}}</strong> 授權條款。\n\n維基百科̽(Wikipedia)先前是使用 GNU 自由文件授權條款,\n但該授權條款的內容較難理解,因此較難再利用在該條款底下的內容。",
        "config-email-settings": "E-mail 設定",
        "config-enable-email": "開啟外寄電子郵件",
        "config-enable-email-help": "如果您要使用電子郵件功能,請正確設定 [http://www.php.net/manual/en/mail.configuration.php PHP 的郵件設定]。\n如果您不需要使用電子郵件功能,請在此處關閉。",
        "config-email-user": "開啟使用者對使用者間的電子郵件互通",
-       "config-email-user-help": "若使用者在個人偏好開啟了此功能,則可允許使用者間相互發送郵件。",
+       "config-email-user-help": "若使用者在個人偏好設定開啟了此功能,則可允許使用者間相互傳送郵件。",
        "config-email-usertalk": "開啟使用者討論頁面通知",
        "config-email-usertalk-help": "若使用者在個人偏好開啟了此功能,則可收到使用者討論頁面被修改的通知。",
-       "config-email-watchlist": "開啟監視列表通知",
-       "config-email-watchlist-help": "若使用者在個人偏好開啟了此功能,允許使用者收到與其監視列表有關的通知。",
+       "config-email-watchlist": "開啟監視清單通知",
+       "config-email-watchlist-help": "若使用者在個人偏好開啟了此功能,允許使用者收到與其監視清單有關的通知。",
        "config-email-auth": "開啟電子郵件身份認證",
        "config-email-auth-help": "若開啟此選項,使用者不論設定或者更改電子郵件地址,都必須透過收信的方式確認沒有問題。\n只有驗證過的電子郵件地址可以收到來自其他使用者或修改通知的信件。\n公開的 Wiki 會 <strong>建議</strong> 設定此選項,以防使用者濫用電子郵件功能。",
-       "config-email-sender": "電子郵件回覆址:",
+       "config-email-sender": "電子郵件回覆址:",
        "config-email-sender-help": "請輸入要用來做為外寄郵件的電子郵件回覆地址。\n該郵件地址會收到被拒收的信件。\n許多郵件伺服器會要求使用有效的網域名稱。",
        "config-upload-settings": "圖片和檔案上傳",
        "config-upload-enable": "開啟檔案上傳",
        "config-memcache-badport": "Memcached 埠號應介於 $1 到 $2 之間。",
        "config-extensions": "擴充套件",
        "config-extensions-help": "已在您的 <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": "必須啟用選為預設的外觀。",
        "config-install-alreadydone": "<strong>警告:</strong>您已經安裝 MediaWiki,並且試圖重新安裝。\n請點繼續前往下一個頁面。",
        "config-install-begin": "請點選 \"{{int:config-continue}}\" 開始安裝 MediaWiki。\n若您還想要修改設定,請點選 \"{{int:config-back}}\"。",
        "config-install-step-done": "完成",
index 09283f2..55b2506 100644 (file)
@@ -45,7 +45,7 @@ class Interwiki {
         */
        protected $mWikiID;
 
-       /** @var bool whether the wiki is in this project */
+       /** @var bool Whether the wiki is in this project */
        protected $mLocal;
 
        /** @var bool Whether interwiki transclusions are allowed */
@@ -118,7 +118,7 @@ class Interwiki {
         * @note More logic is explained in DefaultSettings.
         *
         * @param string $prefix Interwiki prefix
-        * @return Interwiki object
+        * @return Interwiki
         */
        protected static function getInterwikiCached( $prefix ) {
                $value = self::getInterwikiCacheEntry( $prefix );
index 35b4f13..ee3f2c2 100644 (file)
@@ -279,7 +279,7 @@ abstract class Job implements IJobSpecification {
 
        /**
         * Insert a single job into the queue.
-        * @return bool true on success
+        * @return bool True on success
         * @deprecated since 1.21
         */
        public function insert() {
@@ -291,7 +291,7 @@ abstract class Job implements IJobSpecification {
         * @return string
         */
        public function toString() {
-               $truncFunc = function( $value ) {
+               $truncFunc = function ( $value ) {
                        $value = (string)$value;
                        if ( mb_strlen( $value ) > 1024 ) {
                                $value = "string(" . mb_strlen( $value ) . ")";
index d6f9560..c4301ee 100644 (file)
@@ -64,7 +64,7 @@ class JobQueueFederated extends JobQueue {
        const CACHE_TTL_LONG = 300; // integer; seconds to cache info that is kept up to date
 
        /**
-        * @params include:
+        * @param array $params Possible keys:
         *  - sectionsByWiki      : A map of wiki IDs to section names.
         *                          Wikis will default to using the section "default".
         *  - partitionsBySection : Map of section names to maps of (partition name => weight).
@@ -80,7 +80,6 @@ class JobQueueFederated extends JobQueue {
         *                          different partition queues. This improves availability
         *                          during failure, at the cost of added latency and somewhat
         *                          less reliable job de-duplication mechanisms.
-        * @param array $params
         * @throws MWException
         */
        protected function __construct( array $params ) {
@@ -282,7 +281,7 @@ class JobQueueFederated extends JobQueue {
                        }
                        if ( $ok ) {
                                $key = $this->getCacheKey( 'empty' );
-                               $this->cache->set( $key, 'false', JobQueueDB::CACHE_TTL_LONG );
+                               $this->cache->set( $key, 'false', self::CACHE_TTL_LONG );
                        } else {
                                if ( !$partitionRing->ejectFromLiveRing( $partition, 5 ) ) { // blacklist
                                        throw new JobQueueError( "Could not insert job(s), no partitions available." );
@@ -304,7 +303,7 @@ class JobQueueFederated extends JobQueue {
                        }
                        if ( $ok ) {
                                $key = $this->getCacheKey( 'empty' );
-                               $this->cache->set( $key, 'false', JobQueueDB::CACHE_TTL_LONG );
+                               $this->cache->set( $key, 'false', self::CACHE_TTL_LONG );
                        } else {
                                if ( !$partitionRing->ejectFromLiveRing( $partition, 5 ) ) { // blacklist
                                        throw new JobQueueError( "Could not insert job(s), no partitions available." );
@@ -317,13 +316,6 @@ class JobQueueFederated extends JobQueue {
        }
 
        protected function doPop() {
-               $key = $this->getCacheKey( 'empty' );
-
-               $isEmpty = $this->cache->get( $key );
-               if ( $isEmpty === 'true' ) {
-                       return false;
-               }
-
                $partitionsTry = $this->partitionRing->getLiveLocationWeights(); // (partition => weight)
 
                $failed = 0;
@@ -352,7 +344,8 @@ class JobQueueFederated extends JobQueue {
                }
                $this->throwErrorIfAllPartitionsDown( $failed );
 
-               $this->cache->set( $key, 'true', JobQueueDB::CACHE_TTL_LONG );
+               $key = $this->getCacheKey( 'empty' );
+               $this->cache->set( $key, 'true', self::CACHE_TTL_LONG );
 
                return false;
        }
index 088f447..3519eac 100644 (file)
@@ -62,9 +62,10 @@ class JobQueueRedis extends JobQueue {
 
        /** @var string Server address */
        protected $server;
-
        /** @var string Compression method to use */
        protected $compression;
+       /** @var bool */
+       protected $daemonized;
 
        const MAX_AGE_PRUNE = 604800; // integer; seconds a job can live once claimed (7 days)
 
@@ -72,14 +73,16 @@ class JobQueueRedis extends JobQueue {
        protected $key;
 
        /**
-        * @params include:
+        * @param array $params Possible keys:
         *   - redisConfig : An array of parameters to RedisConnectionPool::__construct().
         *                   Note that the serializer option is ignored as "none" is always used.
         *   - redisServer : A hostname/port combination or the absolute path of a UNIX socket.
         *                   If a hostname is specified but no port, the standard port number
         *                   6379 will be used. Required.
         *   - compression : The type of compression to use; one of (none,gzip).
-        * @param array $params
+        *   - daemonized  : Set to true if the redisJobRunnerService runs in the background.
+        *                   This will disable job recycling/undelaying from the MediaWiki side
+        *                   to avoid redundance and out-of-sync configuration.
         */
        public function __construct( array $params ) {
                parent::__construct( $params );
@@ -87,6 +90,7 @@ class JobQueueRedis extends JobQueue {
                $this->server = $params['redisServer'];
                $this->compression = isset( $params['compression'] ) ? $params['compression'] : 'none';
                $this->redisPool = RedisConnectionPool::singleton( $params['redisConfig'] );
+               $this->daemonized = !empty( $params['daemonized'] );
        }
 
        protected function supportedOrders() {
@@ -716,6 +720,9 @@ LUA;
         * @return array
         */
        protected function doGetPeriodicTasks() {
+               if ( $this->daemonized ) {
+                       return array(); // managed in the runner loop
+               }
                $periods = array( 3600 ); // standard cleanup (useful on config change)
                if ( $this->claimTTL > 0 ) {
                        $periods[] = ceil( $this->claimTTL / 2 ); // avoid bad timing
diff --git a/includes/jobqueue/JobRunner.php b/includes/jobqueue/JobRunner.php
new file mode 100644 (file)
index 0000000..8a708f1
--- /dev/null
@@ -0,0 +1,350 @@
+<?php
+/**
+ * Job queue runner utility methods
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup JobQueue
+ */
+
+/**
+ * Job queue runner utility methods
+ *
+ * @ingroup JobQueue
+ * @since 1.24
+ */
+class JobRunner {
+       /** @var callable|null Debug output handler */
+       protected $debug;
+
+       /**
+        * @param callable $debug Optional debug output handler
+        */
+       public function setDebugHandler( $debug ) {
+               $this->debug = $debug;
+       }
+
+       /**
+        * Run jobs of the specified number/type for the specified time
+        *
+        * The response map has a 'job' field that lists status of each job, including:
+        *   - type   : the job type
+        *   - status : ok/failed
+        *   - error  : any error message string
+        *   - time   : the job run time in ms
+        * The response map also has:
+        *   - backoffs : the (job type => seconds) map of backoff times
+        *   - elapsed  : the total time spent running tasks in ms
+        *   - reached  : the reason the script finished, one of (none-ready, job-limit, time-limit)
+        *
+        * This method outputs status information only if a debug handler was set.
+        * Any exceptions are caught and logged, but are not reported as output.
+        *
+        * @param array $options Map of parameters:
+        *    - type     : the job type (or false for the default types)
+        *    - maxJobs  : maximum number of jobs to run
+        *    - maxTime  : maximum time in seconds before stopping
+        *    - throttle : whether to respect job backoff configuration
+        * @return array Summary response that can easily be JSON serialized
+        */
+       public function run( array $options ) {
+               $response = array( 'jobs' => array(), 'reached' => 'none-ready' );
+
+               $type = isset( $options['type'] ) ? $options['type'] : false;
+               $maxJobs = isset( $options['maxJobs'] ) ? $options['maxJobs'] : false;
+               $maxTime = isset( $options['maxTime'] ) ? $options['maxTime'] : false;
+               $noThrottle = isset( $options['throttle'] ) && !$options['throttle'];
+
+               $group = JobQueueGroup::singleton();
+               // Handle any required periodic queue maintenance
+               $count = $group->executeReadyPeriodicTasks();
+               if ( $count > 0 ) {
+                       $this->runJobsLog( "Executed $count periodic queue task(s)." );
+               }
+
+               // Flush any pending DB writes for sanity
+               wfGetLBFactory()->commitMasterChanges();
+
+               // Some jobs types should not run until a certain timestamp
+               $backoffs = array(); // map of (type => UNIX expiry)
+               $backoffDeltas = array(); // map of (type => seconds)
+               $wait = 'wait'; // block to read backoffs the first time
+
+               $jobsRun = 0; // counter
+               $timeMsTotal = 0;
+               $flags = JobQueueGroup::USE_CACHE;
+               $sTime = microtime( true ); // time since jobs started running
+               $lastTime = microtime( true ); // time since last slave check
+               do {
+                       // Sync the persistent backoffs with concurrent runners
+                       $backoffs = $this->syncBackoffDeltas( $backoffs, $backoffDeltas, $wait );
+                       $blacklist = $noThrottle ? array() : array_keys( $backoffs );
+                       $wait = 'nowait'; // less important now
+
+                       if ( $type === false ) {
+                               $job = $group->pop( JobQueueGroup::TYPE_DEFAULT, $flags, $blacklist );
+                       } elseif ( in_array( $type, $blacklist ) ) {
+                               $job = false; // requested queue in backoff state
+                       } else {
+                               $job = $group->pop( $type ); // job from a single queue
+                       }
+
+                       if ( $job ) { // found a job
+                               $jType = $job->getType();
+
+                               // Back off of certain jobs for a while (for throttling and for errors)
+                               $ttw = $this->getBackoffTimeToWait( $job );
+                               if ( $ttw > 0 ) {
+                                       // Always add the delta for other runners in case the time running the
+                                       // job negated the backoff for each individually but not collectively.
+                                       $backoffDeltas[$jType] = isset( $backoffDeltas[$jType] )
+                                               ? $backoffDeltas[$jType] + $ttw
+                                               : $ttw;
+                                       $backoffs = $this->syncBackoffDeltas( $backoffs, $backoffDeltas, $wait );
+                               }
+
+                               $this->runJobsLog( $job->toString() . " STARTING" );
+
+                               // Run the job...
+                               wfProfileIn( __METHOD__ . '-' . get_class( $job ) );
+                               $sTime = microtime( true );
+                               try {
+                                       ++$jobsRun;
+                                       $status = $job->run();
+                                       $error = $job->getLastError();
+                                       wfGetLBFactory()->commitMasterChanges();
+                               } catch ( MWException $e ) {
+                                       MWExceptionHandler::rollbackMasterChangesAndLog( $e );
+                                       $status = false;
+                                       $error = get_class( $e ) . ': ' . $e->getMessage();
+                                       MWExceptionHandler::logException( $e );
+                               }
+                               $timeMs = intval( ( microtime( true ) - $sTime ) * 1000 );
+                               wfProfileOut( __METHOD__ . '-' . get_class( $job ) );
+                               $timeMsTotal += $timeMs;
+
+                               // Mark the job as done on success or when the job cannot be retried
+                               if ( $status !== false || !$job->allowRetries() ) {
+                                       $group->ack( $job ); // done
+                               }
+
+                               // Back off of certain jobs for a while (for throttling and for errors)
+                               if ( $status === false && mt_rand( 0, 49 ) == 0 ) {
+                                       $ttw = max( $ttw, 30 ); // too many errors
+                                       $backoffDeltas[$jType] = isset( $backoffDeltas[$jType] )
+                                               ? $backoffDeltas[$jType] + $ttw
+                                               : $ttw;
+                               }
+
+                               if ( $status === false ) {
+                                       $this->runJobsLog( $job->toString() . " t=$timeMs error={$error}" );
+                               } else {
+                                       $this->runJobsLog( $job->toString() . " t=$timeMs good" );
+                               }
+
+                               $response['jobs'][] = array(
+                                       'type'   => $jType,
+                                       'status' => ( $status === false ) ? 'failed' : 'ok',
+                                       'error'  => $error,
+                                       'time'   => $timeMs
+                               );
+
+                               // Break out if we hit the job count or wall time limits...
+                               if ( $maxJobs && $jobsRun >= $maxJobs ) {
+                                       $response['reached'] = 'job-limit';
+                                       break;
+                               } elseif ( $maxTime && ( microtime( true ) - $sTime ) > $maxTime ) {
+                                       $response['reached'] = 'time-limit';
+                                       break;
+                               }
+
+                               // Don't let any of the main DB slaves get backed up
+                               $timePassed = microtime( true ) - $lastTime;
+                               if ( $timePassed >= 5 || $timePassed < 0 ) {
+                                       wfWaitForSlaves( $lastTime );
+                                       $lastTime = microtime( true );
+                               }
+                               // Don't let any queue slaves/backups fall behind
+                               if ( $jobsRun > 0 && ( $jobsRun % 100 ) == 0 ) {
+                                       $group->waitForBackups();
+                               }
+
+                               // Bail if near-OOM instead of in a job
+                               $this->assertMemoryOK();
+                       }
+               } while ( $job ); // stop when there are no jobs
+
+               // Sync the persistent backoffs for the next runJobs.php pass
+               if ( $backoffDeltas ) {
+                       $this->syncBackoffDeltas( $backoffs, $backoffDeltas, 'wait' );
+               }
+
+               $response['backoffs'] = $backoffs;
+               $response['elapsed'] = $timeMsTotal;
+
+               return $response;
+       }
+
+       /**
+        * @param Job $job
+        * @return int Seconds for this runner to avoid doing more jobs of this type
+        * @see $wgJobBackoffThrottling
+        */
+       private function getBackoffTimeToWait( Job $job ) {
+               global $wgJobBackoffThrottling;
+
+               if ( !isset( $wgJobBackoffThrottling[$job->getType()] ) ||
+                       $job instanceof DuplicateJob // no work was done
+               ) {
+                       return 0; // not throttled
+               }
+
+               $itemsPerSecond = $wgJobBackoffThrottling[$job->getType()];
+               if ( $itemsPerSecond <= 0 ) {
+                       return 0; // not throttled
+               }
+
+               $seconds = 0;
+               if ( $job->workItemCount() > 0 ) {
+                       $exactSeconds = $job->workItemCount() / $itemsPerSecond;
+                       // use randomized rounding
+                       $seconds = floor( $exactSeconds );
+                       $remainder = $exactSeconds - $seconds;
+                       $seconds += ( mt_rand() / mt_getrandmax() < $remainder ) ? 1 : 0;
+               }
+
+               return (int)$seconds;
+       }
+
+       /**
+        * Get the previous backoff expiries from persistent storage
+        * On I/O or lock acquisition failure this returns the original $backoffs.
+        *
+        * @param array $backoffs Map of (job type => UNIX timestamp)
+        * @param string $mode Lock wait mode - "wait" or "nowait"
+        * @return array Map of (job type => backoff expiry timestamp)
+        */
+       private function loadBackoffs( array $backoffs, $mode = 'wait' ) {
+               $section = new ProfileSection( __METHOD__ );
+
+               $file = wfTempDir() . '/mw-runJobs-backoffs.json';
+               if ( is_file( $file ) ) {
+                       $noblock = ( $mode === 'nowait' ) ? LOCK_NB : 0;
+                       $handle = fopen( $file, 'rb' );
+                       if ( !flock( $handle, LOCK_SH | $noblock ) ) {
+                               fclose( $handle );
+                               return $backoffs; // don't wait on lock
+                       }
+                       $content = stream_get_contents( $handle );
+                       flock( $handle, LOCK_UN );
+                       fclose( $handle );
+                       $ctime = microtime( true );
+                       $cBackoffs = json_decode( $content, true ) ?: array();
+                       foreach ( $cBackoffs as $type => $timestamp ) {
+                               if ( $timestamp < $ctime ) {
+                                       unset( $cBackoffs[$type] );
+                               }
+                       }
+               } else {
+                       $cBackoffs = array();
+               }
+
+               return $cBackoffs;
+       }
+
+       /**
+        * Merge the current backoff expiries from persistent storage
+        *
+        * The $deltas map is set to an empty array on success.
+        * On I/O or lock acquisition failure this returns the original $backoffs.
+        *
+        * @param array $backoffs Map of (job type => UNIX timestamp)
+        * @param array $deltas Map of (job type => seconds)
+        * @param string $mode Lock wait mode - "wait" or "nowait"
+        * @return array The new backoffs account for $backoffs and the latest file data
+        */
+       private function syncBackoffDeltas( array $backoffs, array &$deltas, $mode = 'wait' ) {
+               $section = new ProfileSection( __METHOD__ );
+
+               if ( !$deltas ) {
+                       return $this->loadBackoffs( $backoffs, $mode );
+               }
+
+               $noblock = ( $mode === 'nowait' ) ? LOCK_NB : 0;
+               $file = wfTempDir() . '/mw-runJobs-backoffs.json';
+               $handle = fopen( $file, 'wb+' );
+               if ( !flock( $handle, LOCK_EX | $noblock ) ) {
+                       fclose( $handle );
+                       return $backoffs; // don't wait on lock
+               }
+               $ctime = microtime( true );
+               $content = stream_get_contents( $handle );
+               $cBackoffs = json_decode( $content, true ) ?: array();
+               foreach ( $deltas as $type => $seconds ) {
+                       $cBackoffs[$type] = isset( $cBackoffs[$type] ) && $cBackoffs[$type] >= $ctime
+                               ? $cBackoffs[$type] + $seconds
+                               : $ctime + $seconds;
+               }
+               foreach ( $cBackoffs as $type => $timestamp ) {
+                       if ( $timestamp < $ctime ) {
+                               unset( $cBackoffs[$type] );
+                       }
+               }
+               ftruncate( $handle, 0 );
+               fwrite( $handle, json_encode( $cBackoffs ) );
+               flock( $handle, LOCK_UN );
+               fclose( $handle );
+
+               $deltas = array();
+
+               return $cBackoffs;
+       }
+
+       /**
+        * Make sure that this script is not too close to the memory usage limit.
+        * It is better to die in between jobs than OOM right in the middle of one.
+        * @throws MWException
+        */
+       private function assertMemoryOK() {
+               static $maxBytes = null;
+               if ( $maxBytes === null ) {
+                       $m = array();
+                       if ( preg_match( '!^(\d+)(k|m|g|)$!i', ini_get( 'memory_limit' ), $m ) ) {
+                               list( , $num, $unit ) = $m;
+                               $conv = array( 'g' => 1073741824, 'm' => 1048576, 'k' => 1024, '' => 1 );
+                               $maxBytes = $num * $conv[strtolower( $unit )];
+                       } else {
+                               $maxBytes = 0;
+                       }
+               }
+               $usedBytes = memory_get_usage();
+               if ( $maxBytes && $usedBytes >= 0.95 * $maxBytes ) {
+                       throw new MWException( "Detected excessive memory usage ($usedBytes/$maxBytes)." );
+               }
+       }
+
+       /**
+        * Log the job message
+        * @param string $msg The message to log
+        */
+       private function runJobsLog( $msg ) {
+               if ( $this->debug ) {
+                       call_user_func_array( $this->debug, array( wfTimestamp( TS_DB ) . " $msg\n" ) );
+               }
+               wfDebugLog( 'runJobs', $msg );
+       }
+}
index d733a42..ae266ef 100644 (file)
@@ -34,11 +34,10 @@ class JobQueueAggregatorMemc extends JobQueueAggregator {
        protected $cacheTTL; // integer; seconds
 
        /**
-        * @params include:
+        * @param array $params Possible keys:
         *   - objectCache : Name of an object cache registered in $wgObjectCaches.
         *                   This defaults to the one specified by $wgMainCacheType.
         *   - cacheTTL    : Seconds to cache the aggregate data before regenerating.
-        * @param array $params
         */
        protected function __construct( array $params ) {
                parent::__construct( $params );
index df9ae39..db9e764 100644 (file)
@@ -36,20 +36,20 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
        protected $servers;
 
        /**
-        * @params include:
+        * @param array $params Possible keys:
         *   - redisConfig  : An array of parameters to RedisConnectionPool::__construct().
         *   - redisServers : Array of server entries, the first being the primary and the
         *                    others being fallback servers. Each entry is either a hostname/port
         *                    combination or the absolute path of a UNIX socket.
         *                    If a hostname is specified but no port, the standard port number
         *                    6379 will be used. Required.
-        * @param array $params
         */
        protected function __construct( array $params ) {
                parent::__construct( $params );
                $this->servers = isset( $params['redisServers'] )
                        ? $params['redisServers']
                        : array( $params['redisServer'] ); // b/c
+               $params['redisConfig']['serializer'] = 'none';
                $this->redisPool = RedisConnectionPool::singleton( $params['redisConfig'] );
        }
 
@@ -94,18 +94,16 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
                        return array();
                }
                try {
-                       $conn->multi( Redis::PIPELINE );
-                       $conn->exists( $this->getReadyQueueKey() );
-                       $conn->hGetAll( $this->getReadyQueueKey() );
-                       list( $exists, $map ) = $conn->exec();
+                       $map = $conn->hGetAll( $this->getReadyQueueKey() );
 
-                       if ( $exists ) { // cache hit
+                       if ( is_array( $map ) && isset( $map['_epoch'] ) ) {
+                               unset( $map['_epoch'] ); // ignore
                                $pendingDBs = array(); // (type => list of wikis)
                                foreach ( $map as $key => $time ) {
                                        list( $type, $wiki ) = $this->dencQueueName( $key );
                                        $pendingDBs[$type][] = $wiki;
                                }
-                       } else { // cache miss
+                       } else {
                                // Avoid duplicated effort
                                $rand = wfRandomString( 32 );
                                $conn->multi( Redis::MULTI );
@@ -120,7 +118,7 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
 
                                $conn->multi( Redis::PIPELINE );
                                $now = time();
-                               $map = array();
+                               $map = array( '_epoch' => time() ); // dummy key for empty Redis collections
                                foreach ( $pendingDBs as $type => $wikis ) {
                                        $conn->hSetNx( $this->getQueueTypesKey(), $type, 'enabled' );
                                        foreach ( $wikis as $wiki ) {
@@ -189,14 +187,14 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
         * @return string
         */
        private function getReadyQueueKey() {
-               return "jobqueue:aggregator:h-ready-queues:v1"; // global
+               return "jobqueue:aggregator:h-ready-queues:v2"; // global
        }
 
        /**
         * @return string
         */
        private function getQueueTypesKey() {
-               return "jobqueue:aggregator:h-queue-types:v1"; // global
+               return "jobqueue:aggregator:h-queue-types:v2"; // global
        }
 
        /**
index 34c302e..2561f2f 100644 (file)
@@ -84,7 +84,6 @@ class DoubleRedirectJob extends Job {
        /**
         * @param Title $title
         * @param array|bool $params
-        * @param int $id
         */
        function __construct( $title, $params = false ) {
                parent::__construct( 'fixDoubleRedirect', $title, $params );
index b0a6ef7..1fa6cef 100644 (file)
@@ -31,7 +31,7 @@ final class DuplicateJob extends Job {
         * Callers should use DuplicateJob::newFromJob() instead
         *
         * @param Title $title
-        * @param array $params job parameters
+        * @param array $params Job parameters
         */
        function __construct( $title, $params ) {
                parent::__construct( 'duplicate', $title, $params );
index b2d6a9a..66291e9 100644 (file)
@@ -47,7 +47,7 @@
 class NullJob extends Job {
        /**
         * @param Title $title
-        * @param array $params job parameters (lives, usleep)
+        * @param array $params Job parameters (lives, usleep)
         */
        function __construct( $title, $params ) {
                parent::__construct( 'null', $title, $params );
index 480246b..a09db15 100644 (file)
@@ -155,8 +155,8 @@ class UploadFromUrlJob extends Job {
         * Store a result in the session data. Note that the caller is responsible
         * for appropriate session_start and session_write_close calls.
         *
-        * @param string $result the result (Success|Warning|Failure)
-        * @param string $dataKey the key of the extra data
+        * @param string $result The result (Success|Warning|Failure)
+        * @param string $dataKey The key of the extra data
         * @param mixed $dataValue The extra data itself
         */
        protected function storeResultInSession( $result, $dataKey, $dataValue ) {
index 4f0651d..ae28163 100644 (file)
@@ -179,6 +179,22 @@ class CSSJanus {
                $css = $noFlipClass->detokenize( $css );
                $css = $noFlipSingle->detokenize( $css );
 
+               // Remove remaining /* @noflip */ annotations, they won't be needed anymore
+               // and can interfere with other code (bug 69698).
+               $css = self::nullTransform( $css );
+
+               return $css;
+       }
+
+       /**
+        * Remove @noflip annotations, but don't do any other transforms.
+        * @param string $css stylesheet to transform
+        * @return string Transformed stylesheet
+        */
+       public static function nullTransform( $css ) {
+               $patt = self::$patterns['noflip_annotation'];
+               $css = preg_replace( "/($patt)\\s*/i", '', $css );
+
                return $css;
        }
 
@@ -301,7 +317,7 @@ class CSSJanus {
                // (We can't just negate the value with unary minus due to the units.)
                $flipSign = function ( $cssValue ) {
                        // Don't mangle zeroes
-                       if ( intval( $cssValue ) === 0 ) {
+                       if ( floatval( $cssValue ) === 0.0 ) {
                                return $cssValue;
                        } elseif ( $cssValue[0] === '-' ) {
                                return substr( $cssValue, 1 );
index 6b10ae4..dcaa685 100644 (file)
@@ -44,7 +44,7 @@ class CSSMin {
 
        /* Protected Static Members */
 
-       /** @var array List of common image files extensions and mime-types */
+       /** @var array List of common image files extensions and MIME-types */
        protected static $mimeTypes = array(
                'gif' => 'image/gif',
                'jpe' => 'image/jpeg',
@@ -135,27 +135,21 @@ class CSSMin {
         */
        public static function getMimeType( $file ) {
                $realpath = realpath( $file );
-               // Try a couple of different ways to get the mime-type of a file, in order of
-               // preference
                if (
                        $realpath
                        && function_exists( 'finfo_file' )
                        && function_exists( 'finfo_open' )
                        && defined( 'FILEINFO_MIME_TYPE' )
                ) {
-                       // As of PHP 5.3, this is how you get the mime-type of a file; it uses the Fileinfo
-                       // PECL extension
                        return finfo_file( finfo_open( FILEINFO_MIME_TYPE ), $realpath );
-               } elseif ( function_exists( 'mime_content_type' ) ) {
-                       // Before this was deprecated in PHP 5.3, this was how you got the mime-type of a file
-                       return mime_content_type( $file );
-               } else {
-                       // Worst-case scenario has happened, use the file extension to infer the mime-type
-                       $ext = strtolower( pathinfo( $file, PATHINFO_EXTENSION ) );
-                       if ( isset( self::$mimeTypes[$ext] ) ) {
-                               return self::$mimeTypes[$ext];
-                       }
                }
+
+               // Infer the MIME-type from the file extension
+               $ext = strtolower( pathinfo( $file, PATHINFO_EXTENSION ) );
+               if ( isset( self::$mimeTypes[$ext] ) ) {
+                       return self::$mimeTypes[$ext];
+               }
+
                return false;
        }
 
@@ -163,6 +157,8 @@ class CSSMin {
         * Build a CSS 'url()' value for the given URL, quoting parentheses (and other funny characters)
         * and escaping quotes as necessary.
         *
+        * See http://www.w3.org/TR/css-syntax-3/#consume-a-url-token
+        *
         * @param string $url URL to process
         * @return string 'url()' value, usually just `"url($url)"`, quoted/escaped if necessary
         */
index a80f6d9..c31a352 100644 (file)
@@ -333,7 +333,7 @@ class IEContentAnalyzer {
         * @param string $chunk the first 256 bytes of the file
         * @param string $proposed the MIME type proposed by the server
         *
-        * @return Array: map of IE version to detected mime type
+        * @return Array: map of IE version to detected MIME type
         */
        public function getRealMimesFromData( $fileName, $chunk, $proposed ) {
                $types = $this->getMimesFromData( $fileName, $chunk, $proposed );
@@ -371,7 +371,7 @@ class IEContentAnalyzer {
         * @param string $chunk the first 256 bytes of the file
         * @param string $proposed the MIME type proposed by the server
         *
-        * @return Array: map of IE version to detected mime type
+        * @return Array: map of IE version to detected MIME type
         */
        public function getMimesFromData( $fileName, $chunk, $proposed ) {
                $types = array();
index 671e812..8c982c4 100644 (file)
@@ -116,7 +116,7 @@ class MultiHttpClient {
         * This is true for the request headers and the response headers. Integer-indexed
         * method/URL entries will also be changed to use the corresponding string keys.
         *
-        * @param array $req Map of HTTP request arrays
+        * @param array $reqs Map of HTTP request arrays
         * @param array $opts
         *   - connTimeout     : connection timeout per request
         *   - reqTimeout      : post-connection timeout per request
index 37723d5..61ed771 100644 (file)
@@ -1036,7 +1036,7 @@ class lessc {
                                        }
                                }
 
-                               if(!is_null($mime)) // fallback if the mime type is still unknown
+                               if(!is_null($mime)) // fallback if the MIME type is still unknown
                                        $url = sprintf('data:%s;base64,%s', $mime, base64_encode(file_get_contents($fullpath)));
                        }
                }
index bebe3a9..46c5515 100644 (file)
@@ -533,6 +533,10 @@ class ManualLogEntry extends LogEntryBase {
                        $dbw->insert( 'log_search', $rows, __METHOD__, 'IGNORE' );
                }
 
+               // Update any bloom filter cache
+               $member = $this->getTarget()->getNamespace() . ':' . $this->getTarget()->getDBkey();
+               BloomCache::get( 'main' )->insert( wfWikiId(), 'TitleHasLogs', $member );
+
                return $this->id;
        }
 
index 4ce8070..4dc25ef 100644 (file)
@@ -355,9 +355,13 @@ class LogEventsList extends ContextSource {
                // Don't show useless checkbox to people who cannot hide log entries
                if ( $user->isAllowed( 'deletedhistory' ) ) {
                        $canHide = $user->isAllowed( 'deletelogentry' );
+                       $canViewSuppressedOnly = $user->isAllowed( 'viewsuppressed' ) &&
+                               !$user->isAllowed( 'suppressrevision' );
+                       $entryIsSuppressed = self::isDeleted( $row, LogPage::DELETED_RESTRICTED );
+                       $canViewThisSuppressedEntry = $canViewSuppressedOnly && $entryIsSuppressed;
                        if ( $row->log_deleted || $canHide ) {
                                // Show checkboxes instead of links.
-                               if ( $canHide && $this->flags & self::USE_REVDEL_CHECKBOXES ) {
+                               if ( $canHide && $this->flags & self::USE_REVDEL_CHECKBOXES && !$canViewThisSuppressedEntry ) {
                                        // If event was hidden from sysops
                                        if ( !self::userCan( $row, LogPage::DELETED_RESTRICTED, $user ) ) {
                                                $del = Xml::check( 'deleterevisions', false, array( 'disabled' => 'disabled' ) );
@@ -380,8 +384,8 @@ class LogEventsList extends ContextSource {
                                                );
                                                $del = Linker::revDeleteLink(
                                                        $query,
-                                                       self::isDeleted( $row, LogPage::DELETED_RESTRICTED ),
-                                                       $canHide
+                                                       $entryIsSuppressed,
+                                                       $canHide && !$canViewThisSuppressedEntry
                                                );
                                        }
                                }
@@ -437,20 +441,19 @@ class LogEventsList extends ContextSource {
         */
        public static function userCanBitfield( $bitfield, $field, User $user = null ) {
                if ( $bitfield & $field ) {
-                       if ( $bitfield & LogPage::DELETED_RESTRICTED ) {
-                               $permission = 'suppressrevision';
-                       } else {
-                               $permission = 'deletedhistory';
-                       }
-                       wfDebug( "Checking for $permission due to $field match on $bitfield\n" );
                        if ( $user === null ) {
                                global $wgUser;
                                $user = $wgUser;
                        }
-
-                       return $user->isAllowed( $permission );
+                       if ( $bitfield & LogPage::DELETED_RESTRICTED ) {
+                               $permissions = array( 'suppressrevision', 'viewsuppressed' );
+                       } else {
+                               $permissions = array( 'deletedhistory' );
+                       }
+                       $permissionlist = implode( ', ', $permissions );
+                       wfDebug( "Checking for $permissionlist due to $field match on $bitfield\n" );
+                       return call_user_func_array( array( $user, 'isAllowedAny' ), $permissions );
                }
-
                return true;
        }
 
index 0139c4a..48a565f 100644 (file)
@@ -112,7 +112,7 @@ class LogFormatter {
         * Set the visibility restrictions for displaying content.
         * If set to public, and an item is deleted, then it will be replaced
         * with a placeholder even if the context user is allowed to view it.
-        * @param int $audience self::FOR_THIS_USER or self::FOR_PUBLIC
+        * @param int $audience Const self::FOR_THIS_USER or self::FOR_PUBLIC
         */
        public function setAudience( $audience ) {
                $this->audience = ( $audience == self::FOR_THIS_USER )
@@ -163,7 +163,7 @@ class LogFormatter {
         * Even uglier hack to maintain backwards compatibilty with IRC bots
         * (bug 34508).
         * @see getActionText()
-        * @return string text
+        * @return string Text
         */
        public function getIRCActionComment() {
                $actionComment = $this->getIRCActionText();
@@ -184,7 +184,7 @@ class LogFormatter {
         * Even uglier hack to maintain backwards compatibilty with IRC bots
         * (bug 34508).
         * @see getActionText()
-        * @return string text
+        * @return string Text
         */
        public function getIRCActionText() {
                $this->plaintext = true;
@@ -482,8 +482,7 @@ class LogFormatter {
         *     * number: Format value as number
         * @param string $value The parameter value that should
         *                      be formated
-        * @return string|Message::numParam|Message::rawParam
-        *         Formated value
+        * @return string|array Formated value
         * @since 1.21
         */
        protected function formatParameterValue( $type, $value ) {
@@ -652,7 +651,7 @@ class LogFormatter {
        }
 
        /**
-        * @return array of titles that should be preloaded with LinkBatch.
+        * @return array Array of titles that should be preloaded with LinkBatch
         */
        public function getPreloadTitles() {
                return array();
@@ -806,7 +805,8 @@ class LegacyLogFormatter extends LogFormatter {
                                array(
                                        'target' => $params[3],
                                        'dest' => $title->getPrefixedDBkey(),
-                                       'mergepoint' => $params[4]
+                                       'mergepoint' => $params[4],
+                                       'submitted' => 1 // show the revisions immediately
                                )
                        );
 
index 1b7e677..ce5b972 100644 (file)
@@ -87,7 +87,7 @@ class LogPage {
        }
 
        /**
-        * @return int log_id of the inserted log entry
+        * @return int The log_id of the inserted log entry
         */
        protected function saveContent() {
                global $wgLogRestrictions;
@@ -184,6 +184,7 @@ class LogPage {
 
        /**
         * Get the comment from the last addEntry() call
+        * @return string
         */
        public function getComment() {
                return $this->comment;
@@ -192,7 +193,7 @@ class LogPage {
        /**
         * Get the list of valid log types
         *
-        * @return array of strings
+        * @return array Array of strings
         */
        public static function validTypes() {
                global $wgLogTypes;
@@ -234,7 +235,7 @@ class LogPage {
         * Get the log header for the given log type
         *
         * @todo handle missing log types
-        * @param string $type logtype
+        * @param string $type Logtype
         * @return string Header text of this logtype
         * @deprecated since 1.19, warnings in 1.21. Use getDescription()
         */
@@ -250,12 +251,12 @@ class LogPage {
         * Generate text for a log entry.
         * Only LogFormatter should call this function.
         *
-        * @param string $type log type
-        * @param string $action log action
+        * @param string $type Log type
+        * @param string $action Log action
         * @param Title|null $title Title object or null
         * @param Skin|null $skin Skin object or null. If null, we want to use the wiki
         *   content language, since that will go to the IRC feed.
-        * @param array $params parameters
+        * @param array $params Parameters
         * @param bool $filterWikilinks Whether to filter wiki links
         * @return string HTML
         */
@@ -440,14 +441,14 @@ class LogPage {
        /**
         * Add a log entry
         *
-        * @param string $action one of '', 'block', 'protect', 'rights', 'delete',
+        * @param string $action One of '', 'block', 'protect', 'rights', 'delete',
         *   'upload', 'move', 'move_redir'
         * @param Title $target Title object
-        * @param string $comment description associated
-        * @param array $params parameters passed later to wfMessage function
+        * @param string $comment Description associated
+        * @param array $params Parameters passed later to wfMessage function
         * @param null|int|User $doer The user doing the action. null for $wgUser
         *
-        * @return int log_id of the inserted log entry
+        * @return int The log_id of the inserted log entry
         */
        public function addEntry( $action, $target, $comment, $params = array(), $doer = null ) {
                global $wgContLang;
index 399c799..256934e 100644 (file)
@@ -175,7 +175,7 @@ class LogPager extends ReverseChronologicalPager {
                $user = $this->getUser();
                if ( !$user->isAllowed( 'deletedhistory' ) ) {
                        $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::DELETED_USER ) . ' = 0';
-               } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                        $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::SUPPRESSED_USER ) .
                                ' != ' . LogPage::SUPPRESSED_USER;
                }
@@ -207,6 +207,18 @@ class LogPager extends ReverseChronologicalPager {
                $ns = $title->getNamespace();
                $db = $this->mDb;
 
+               $doUserRightsLogLike = false;
+               if ( $this->types == array( 'rights' ) ) {
+                       global $wgUserrightsInterwikiDelimiter;
+                       $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
+                                       $doUserRightsLogLike = true;
+                               }
+                       }
+               }
+
                # Using the (log_namespace, log_title, log_timestamp) index with a
                # range scan (LIKE) on the first two parts, instead of simple equality,
                # makes it unusable for sorting.  Sorted retrieval using another index
@@ -218,12 +230,19 @@ class LogPager extends ReverseChronologicalPager {
                # use the page_time index.  That should have no more than a few hundred
                # log entries for even the busiest pages, so it can be safely scanned
                # in full to satisfy an impossible condition on user or similar.
-               if ( $pattern && !$wgMiserMode ) {
-                       $this->mConds['log_namespace'] = $ns;
-                       $this->mConds[] = 'log_title ' . $db->buildLike( $title->getDBkey(), $db->anyString() );
+               $this->mConds['log_namespace'] = $ns;
+               if ( $doUserRightsLogLike ) {
+                       $params = array( $name . $wgUserrightsInterwikiDelimiter );
+                       foreach ( explode( '*', $database ) as $databasepart ) {
+                               $params[] = $databasepart;
+                               $params[] = $db->anyString();
+                       }
+                       array_pop( $params ); // Get rid of the last % we added.
+                       $this->mConds[] = 'log_title' . $db->buildLike( $params );
+               } elseif ( $pattern && !$wgMiserMode ) {
+                       $this->mConds[] = 'log_title' . $db->buildLike( $title->getDBkey(), $db->anyString() );
                        $this->pattern = $pattern;
                } else {
-                       $this->mConds['log_namespace'] = $ns;
                        $this->mConds['log_title'] = $title->getDBkey();
                }
                // Paranoia: avoid brute force searches (bug 17342)
diff --git a/includes/mail/EmailNotification.php b/includes/mail/EmailNotification.php
new file mode 100644 (file)
index 0000000..9219c3a
--- /dev/null
@@ -0,0 +1,494 @@
+<?php
+/**
+ * Classes used to send e-mails
+ *
+ * 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 <brion@pobox.com>
+ * @author <mail@tgries.de>
+ * @author Tim Starling
+ * @author Luke Welling lwelling@wikimedia.org
+ */
+
+/**
+ * This module processes the email notifications when the current page is
+ * changed. It looks up the table watchlist to find out which users are watching
+ * that page.
+ *
+ * The current implementation sends independent emails to each watching user for
+ * the following reason:
+ *
+ * - Each watching user will be notified about the page edit time expressed in
+ * his/her local time (UTC is shown additionally). To achieve this, we need to
+ * find the individual timeoffset of each watching user from the preferences..
+ *
+ * Suggested improvement to slack down the number of sent emails: We could think
+ * of sending out bulk mails (bcc:user1,user2...) for all these users having the
+ * same timeoffset in their preferences.
+ *
+ * Visit the documentation pages under http://meta.wikipedia.com/Enotif
+ */
+class EmailNotification {
+       protected $subject, $body, $replyto, $from;
+       protected $timestamp, $summary, $minorEdit, $oldid, $composed_common, $pageStatus;
+       protected $mailTargets = array();
+
+       /**
+        * @var Title
+        */
+       protected $title;
+
+       /**
+        * @var User
+        */
+       protected $editor;
+
+       /**
+        * Send emails corresponding to the user $editor editing the page $title.
+        * Also updates wl_notificationtimestamp.
+        *
+        * May be deferred via the job queue.
+        *
+        * @param User $editor
+        * @param Title $title
+        * @param string $timestamp
+        * @param string $summary
+        * @param bool $minorEdit
+        * @param bool $oldid (default: false)
+        * @param string $pageStatus (default: 'changed')
+        */
+       public function notifyOnPageChange( $editor, $title, $timestamp, $summary,
+               $minorEdit, $oldid = false, $pageStatus = 'changed'
+       ) {
+               global $wgEnotifUseJobQ, $wgEnotifWatchlist, $wgShowUpdatedMarker, $wgEnotifMinorEdits,
+                      $wgUsersNotifiedOnAllChanges, $wgEnotifUserTalk;
+
+               if ( $title->getNamespace() < 0 ) {
+                       return;
+               }
+
+               // Build a list of users to notify
+               $watchers = array();
+               if ( $wgEnotifWatchlist || $wgShowUpdatedMarker ) {
+                       $dbw = wfGetDB( DB_MASTER );
+                       $res = $dbw->select( array( 'watchlist' ),
+                               array( 'wl_user' ),
+                               array(
+                                       'wl_user != ' . intval( $editor->getID() ),
+                                       'wl_namespace' => $title->getNamespace(),
+                                       'wl_title' => $title->getDBkey(),
+                                       'wl_notificationtimestamp IS NULL',
+                               ), __METHOD__
+                       );
+                       foreach ( $res as $row ) {
+                               $watchers[] = intval( $row->wl_user );
+                       }
+                       if ( $watchers ) {
+                               // Update wl_notificationtimestamp for all watching users except the editor
+                               $fname = __METHOD__;
+                               $dbw->onTransactionIdle(
+                                       function () use ( $dbw, $timestamp, $watchers, $title, $fname ) {
+                                               $dbw->update( 'watchlist',
+                                                       array( /* SET */
+                                                               'wl_notificationtimestamp' => $dbw->timestamp( $timestamp )
+                                                       ), array( /* WHERE */
+                                                               'wl_user' => $watchers,
+                                                               'wl_namespace' => $title->getNamespace(),
+                                                               'wl_title' => $title->getDBkey(),
+                                                       ), $fname
+                                               );
+                                       }
+                               );
+                       }
+               }
+
+               $sendEmail = true;
+               // If nobody is watching the page, and there are no users notified on all changes
+               // don't bother creating a job/trying to send emails
+               // $watchers deals with $wgEnotifWatchlist
+               if ( !count( $watchers ) && !count( $wgUsersNotifiedOnAllChanges ) ) {
+                       $sendEmail = false;
+                       // Only send notification for non minor edits, unless $wgEnotifMinorEdits
+                       if ( !$minorEdit || ( $wgEnotifMinorEdits && !$editor->isAllowed( 'nominornewtalk' ) ) ) {
+                               $isUserTalkPage = ( $title->getNamespace() == NS_USER_TALK );
+                               if ( $wgEnotifUserTalk
+                                       && $isUserTalkPage
+                                       && $this->canSendUserTalkEmail( $editor, $title, $minorEdit )
+                               ) {
+                                       $sendEmail = true;
+                               }
+                       }
+               }
+
+               if ( !$sendEmail ) {
+                       return;
+               }
+
+               if ( $wgEnotifUseJobQ ) {
+                       $params = array(
+                               'editor' => $editor->getName(),
+                               'editorID' => $editor->getID(),
+                               'timestamp' => $timestamp,
+                               'summary' => $summary,
+                               'minorEdit' => $minorEdit,
+                               'oldid' => $oldid,
+                               'watchers' => $watchers,
+                               'pageStatus' => $pageStatus
+                       );
+                       $job = new EnotifNotifyJob( $title, $params );
+                       JobQueueGroup::singleton()->push( $job );
+               } else {
+                       $this->actuallyNotifyOnPageChange(
+                               $editor,
+                               $title,
+                               $timestamp,
+                               $summary,
+                               $minorEdit,
+                               $oldid,
+                               $watchers,
+                               $pageStatus
+                       );
+               }
+       }
+
+       /**
+        * Immediate version of notifyOnPageChange().
+        *
+        * Send emails corresponding to the user $editor editing the page $title.
+        * Also updates wl_notificationtimestamp.
+        *
+        * @param User $editor
+        * @param Title $title
+        * @param string $timestamp Edit timestamp
+        * @param string $summary Edit summary
+        * @param bool $minorEdit
+        * @param int $oldid Revision ID
+        * @param array $watchers Array of user IDs
+        * @param string $pageStatus
+        * @throws MWException
+        */
+       public function actuallyNotifyOnPageChange( $editor, $title, $timestamp, $summary, $minorEdit,
+               $oldid, $watchers, $pageStatus = 'changed' ) {
+               # we use $wgPasswordSender as sender's address
+               global $wgEnotifWatchlist;
+               global $wgEnotifMinorEdits, $wgEnotifUserTalk;
+
+               wfProfileIn( __METHOD__ );
+
+               # The following code is only run, if several conditions are met:
+               # 1. EmailNotification for pages (other than user_talk pages) must be enabled
+               # 2. minor edits (changes) are only regarded if the global flag indicates so
+
+               $isUserTalkPage = ( $title->getNamespace() == NS_USER_TALK );
+
+               $this->title = $title;
+               $this->timestamp = $timestamp;
+               $this->summary = $summary;
+               $this->minorEdit = $minorEdit;
+               $this->oldid = $oldid;
+               $this->editor = $editor;
+               $this->composed_common = false;
+               $this->pageStatus = $pageStatus;
+
+               $formattedPageStatus = array( 'deleted', 'created', 'moved', 'restored', 'changed' );
+
+               wfRunHooks( 'UpdateUserMailerFormattedPageStatus', array( &$formattedPageStatus ) );
+               if ( !in_array( $this->pageStatus, $formattedPageStatus ) ) {
+                       wfProfileOut( __METHOD__ );
+                       throw new MWException( 'Not a valid page status!' );
+               }
+
+               $userTalkId = false;
+
+               if ( !$minorEdit || ( $wgEnotifMinorEdits && !$editor->isAllowed( 'nominornewtalk' ) ) ) {
+                       if ( $wgEnotifUserTalk
+                               && $isUserTalkPage
+                               && $this->canSendUserTalkEmail( $editor, $title, $minorEdit )
+                       ) {
+                               $targetUser = User::newFromName( $title->getText() );
+                               $this->compose( $targetUser );
+                               $userTalkId = $targetUser->getId();
+                       }
+
+                       if ( $wgEnotifWatchlist ) {
+                               // Send updates to watchers other than the current editor
+                               $userArray = UserArray::newFromIDs( $watchers );
+                               foreach ( $userArray as $watchingUser ) {
+                                       if ( $watchingUser->getOption( 'enotifwatchlistpages' )
+                                               && ( !$minorEdit || $watchingUser->getOption( 'enotifminoredits' ) )
+                                               && $watchingUser->isEmailConfirmed()
+                                               && $watchingUser->getID() != $userTalkId
+                                       ) {
+                                               if ( wfRunHooks( 'SendWatchlistEmailNotification', array( $watchingUser, $title, $this ) ) ) {
+                                                       $this->compose( $watchingUser );
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               global $wgUsersNotifiedOnAllChanges;
+               foreach ( $wgUsersNotifiedOnAllChanges as $name ) {
+                       if ( $editor->getName() == $name ) {
+                               // No point notifying the user that actually made the change!
+                               continue;
+                       }
+                       $user = User::newFromName( $name );
+                       $this->compose( $user );
+               }
+
+               $this->sendMails();
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * @param User $editor
+        * @param Title $title
+        * @param bool $minorEdit
+        * @return bool
+        */
+       private function canSendUserTalkEmail( $editor, $title, $minorEdit ) {
+               global $wgEnotifUserTalk;
+               $isUserTalkPage = ( $title->getNamespace() == NS_USER_TALK );
+
+               if ( $wgEnotifUserTalk && $isUserTalkPage ) {
+                       $targetUser = User::newFromName( $title->getText() );
+
+                       if ( !$targetUser || $targetUser->isAnon() ) {
+                               wfDebug( __METHOD__ . ": user talk page edited, but user does not exist\n" );
+                       } elseif ( $targetUser->getId() == $editor->getId() ) {
+                               wfDebug( __METHOD__ . ": user edited their own talk page, no notification sent\n" );
+                       } elseif ( $targetUser->getOption( 'enotifusertalkpages' )
+                               && ( !$minorEdit || $targetUser->getOption( 'enotifminoredits' ) )
+                       ) {
+                               if ( !$targetUser->isEmailConfirmed() ) {
+                                       wfDebug( __METHOD__ . ": talk page owner doesn't have validated email\n" );
+                               } elseif ( !wfRunHooks( 'AbortTalkPageEmailNotification', array( $targetUser, $title ) ) ) {
+                                       wfDebug( __METHOD__ . ": talk page update notification is aborted for this user\n" );
+                               } else {
+                                       wfDebug( __METHOD__ . ": sending talk page update notification\n" );
+                                       return true;
+                               }
+                       } else {
+                               wfDebug( __METHOD__ . ": talk page owner doesn't want notifications\n" );
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * Generate the generic "this page has been changed" e-mail text.
+        */
+       private function composeCommonMailtext() {
+               global $wgPasswordSender, $wgNoReplyAddress;
+               global $wgEnotifFromEditor, $wgEnotifRevealEditorAddress;
+               global $wgEnotifImpersonal, $wgEnotifUseRealName;
+
+               $this->composed_common = true;
+
+               # You as the WikiAdmin and Sysops can make use of plenty of
+               # named variables when composing your notification emails while
+               # simply editing the Meta pages
+
+               $keys = array();
+               $postTransformKeys = array();
+               $pageTitleUrl = $this->title->getCanonicalURL();
+               $pageTitle = $this->title->getPrefixedText();
+
+               if ( $this->oldid ) {
+                       // Always show a link to the diff which triggered the mail. See bug 32210.
+                       $keys['$NEWPAGE'] = "\n\n" . wfMessage( 'enotif_lastdiff',
+                                       $this->title->getCanonicalURL( array( 'diff' => 'next', 'oldid' => $this->oldid ) ) )
+                                       ->inContentLanguage()->text();
+
+                       if ( !$wgEnotifImpersonal ) {
+                               // For personal mail, also show a link to the diff of all changes
+                               // since last visited.
+                               $keys['$NEWPAGE'] .= "\n\n" . wfMessage( 'enotif_lastvisited',
+                                               $this->title->getCanonicalURL( array( 'diff' => '0', 'oldid' => $this->oldid ) ) )
+                                               ->inContentLanguage()->text();
+                       }
+                       $keys['$OLDID'] = $this->oldid;
+                       // Deprecated since MediaWiki 1.21, not used by default. Kept for backwards-compatibility.
+                       $keys['$CHANGEDORCREATED'] = wfMessage( 'changed' )->inContentLanguage()->text();
+               } else {
+                       # clear $OLDID placeholder in the message template
+                       $keys['$OLDID'] = '';
+                       $keys['$NEWPAGE'] = '';
+                       // Deprecated since MediaWiki 1.21, not used by default. Kept for backwards-compatibility.
+                       $keys['$CHANGEDORCREATED'] = wfMessage( 'created' )->inContentLanguage()->text();
+               }
+
+               $keys['$PAGETITLE'] = $this->title->getPrefixedText();
+               $keys['$PAGETITLE_URL'] = $this->title->getCanonicalURL();
+               $keys['$PAGEMINOREDIT'] = $this->minorEdit ?
+                       wfMessage( 'minoredit' )->inContentLanguage()->text() : '';
+               $keys['$UNWATCHURL'] = $this->title->getCanonicalURL( 'action=unwatch' );
+
+               if ( $this->editor->isAnon() ) {
+                       # real anon (user:xxx.xxx.xxx.xxx)
+                       $keys['$PAGEEDITOR'] = wfMessage( 'enotif_anon_editor', $this->editor->getName() )
+                               ->inContentLanguage()->text();
+                       $keys['$PAGEEDITOR_EMAIL'] = wfMessage( 'noemailtitle' )->inContentLanguage()->text();
+
+               } else {
+                       $keys['$PAGEEDITOR'] = $wgEnotifUseRealName && $this->editor->getRealName() !== ''
+                               ? $this->editor->getRealName() : $this->editor->getName();
+                       $emailPage = SpecialPage::getSafeTitleFor( 'Emailuser', $this->editor->getName() );
+                       $keys['$PAGEEDITOR_EMAIL'] = $emailPage->getCanonicalURL();
+               }
+
+               $keys['$PAGEEDITOR_WIKI'] = $this->editor->getUserPage()->getCanonicalURL();
+               $keys['$HELPPAGE'] = wfExpandUrl(
+                       Skin::makeInternalOrExternalUrl( wfMessage( 'helppage' )->inContentLanguage()->text() )
+               );
+
+               # Replace this after transforming the message, bug 35019
+               $postTransformKeys['$PAGESUMMARY'] = $this->summary == '' ? ' - ' : $this->summary;
+
+               // Now build message's subject and body
+
+               // Messages:
+               // enotif_subject_deleted, enotif_subject_created, enotif_subject_moved,
+               // enotif_subject_restored, enotif_subject_changed
+               $this->subject = wfMessage( 'enotif_subject_' . $this->pageStatus )->inContentLanguage()
+                       ->params( $pageTitle, $keys['$PAGEEDITOR'] )->text();
+
+               // Messages:
+               // enotif_body_intro_deleted, enotif_body_intro_created, enotif_body_intro_moved,
+               // enotif_body_intro_restored, enotif_body_intro_changed
+               $keys['$PAGEINTRO'] = wfMessage( 'enotif_body_intro_' . $this->pageStatus )
+                       ->inContentLanguage()->params( $pageTitle, $keys['$PAGEEDITOR'], $pageTitleUrl )
+                       ->text();
+
+               $body = wfMessage( 'enotif_body' )->inContentLanguage()->plain();
+               $body = strtr( $body, $keys );
+               $body = MessageCache::singleton()->transform( $body, false, null, $this->title );
+               $this->body = wordwrap( strtr( $body, $postTransformKeys ), 72 );
+
+               # Reveal the page editor's address as REPLY-TO address only if
+               # the user has not opted-out and the option is enabled at the
+               # global configuration level.
+               $adminAddress = new MailAddress( $wgPasswordSender,
+                       wfMessage( 'emailsender' )->inContentLanguage()->text() );
+               if ( $wgEnotifRevealEditorAddress
+                       && ( $this->editor->getEmail() != '' )
+                       && $this->editor->getOption( 'enotifrevealaddr' )
+               ) {
+                       $editorAddress = MailAddress::newFromUser( $this->editor );
+                       if ( $wgEnotifFromEditor ) {
+                               $this->from = $editorAddress;
+                       } else {
+                               $this->from = $adminAddress;
+                               $this->replyto = $editorAddress;
+                       }
+               } else {
+                       $this->from = $adminAddress;
+                       $this->replyto = new MailAddress( $wgNoReplyAddress );
+               }
+       }
+
+       /**
+        * Compose a mail to a given user and either queue it for sending, or send it now,
+        * depending on settings.
+        *
+        * Call sendMails() to send any mails that were queued.
+        * @param User $user
+        */
+       function compose( $user ) {
+               global $wgEnotifImpersonal;
+
+               if ( !$this->composed_common ) {
+                       $this->composeCommonMailtext();
+               }
+
+               if ( $wgEnotifImpersonal ) {
+                       $this->mailTargets[] = MailAddress::newFromUser( $user );
+               } else {
+                       $this->sendPersonalised( $user );
+               }
+       }
+
+       /**
+        * Send any queued mails
+        */
+       function sendMails() {
+               global $wgEnotifImpersonal;
+               if ( $wgEnotifImpersonal ) {
+                       $this->sendImpersonal( $this->mailTargets );
+               }
+       }
+
+       /**
+        * Does the per-user customizations to a notification e-mail (name,
+        * timestamp in proper timezone, etc) and sends it out.
+        * Returns true if the mail was sent successfully.
+        *
+        * @param User $watchingUser
+        * @return bool
+        * @private
+        */
+       function sendPersonalised( $watchingUser ) {
+               global $wgContLang, $wgEnotifUseRealName;
+               // From the PHP manual:
+               //   Note: The to parameter cannot be an address in the form of
+               //   "Something <someone@example.com>". The mail command will not parse
+               //   this properly while talking with the MTA.
+               $to = MailAddress::newFromUser( $watchingUser );
+
+               # $PAGEEDITDATE is the time and date of the page change
+               # expressed in terms of individual local time of the notification
+               # recipient, i.e. watching user
+               $body = str_replace(
+                       array( '$WATCHINGUSERNAME',
+                               '$PAGEEDITDATE',
+                               '$PAGEEDITTIME' ),
+                       array( $wgEnotifUseRealName && $watchingUser->getRealName() !== ''
+                               ? $watchingUser->getRealName() : $watchingUser->getName(),
+                               $wgContLang->userDate( $this->timestamp, $watchingUser ),
+                               $wgContLang->userTime( $this->timestamp, $watchingUser ) ),
+                       $this->body );
+
+               return UserMailer::send( $to, $this->from, $this->subject, $body, $this->replyto );
+       }
+
+       /**
+        * Same as sendPersonalised but does impersonal mail suitable for bulk
+        * mailing.  Takes an array of MailAddress objects.
+        * @param MailAddress[] $addresses
+        * @return Status|null
+        */
+       function sendImpersonal( $addresses ) {
+               global $wgContLang;
+
+               if ( empty( $addresses ) ) {
+                       return null;
+               }
+
+               $body = str_replace(
+                       array( '$WATCHINGUSERNAME',
+                               '$PAGEEDITDATE',
+                               '$PAGEEDITTIME' ),
+                       array( wfMessage( 'enotif_impersonal_salutation' )->inContentLanguage()->text(),
+                               $wgContLang->date( $this->timestamp, false, false ),
+                               $wgContLang->time( $this->timestamp, false, false ) ),
+                       $this->body );
+
+               return UserMailer::send( $addresses, $this->from, $this->subject, $body, $this->replyto );
+       }
+
+}
diff --git a/includes/mail/MailAddress.php b/includes/mail/MailAddress.php
new file mode 100644 (file)
index 0000000..6817908
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/**
+ * Classes used to send e-mails
+ *
+ * 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 <brion@pobox.com>
+ * @author <mail@tgries.de>
+ * @author Tim Starling
+ * @author Luke Welling lwelling@wikimedia.org
+ */
+
+/**
+ * Stores a single person's name and email address.
+ * These are passed in via the constructor, and will be returned in SMTP
+ * header format when requested.
+ */
+class MailAddress {
+       /**
+        * @param string $address String with an email address, or a User object
+        * @param string $name Human-readable name if a string address is given
+        * @param string $realName Human-readable real name if a string address is given
+        */
+       function __construct( $address, $name = null, $realName = null ) {
+               if ( is_object( $address ) && $address instanceof User ) {
+                       // Old calling format, now deprecated
+                       wfDeprecated( __METHOD__ . ' with a User object' , '1.24' );
+                       $this->address = $address->getEmail();
+                       $this->name = $address->getName();
+                       $this->realName = $address->getRealName();
+               } else {
+                       $this->address = strval( $address );
+                       $this->name = strval( $name );
+                       $this->realName = strval( $realName );
+               }
+       }
+
+       /**
+        * Create a new MailAddress object for the given user
+        *
+        * @since 1.24
+        * @param User $user
+        * @return MailAddress
+        */
+       public static function newFromUser( User $user ) {
+               return new MailAddress( $user->getEmail(), $user->getName(), $user->getRealName() );
+       }
+
+       /**
+        * Return formatted and quoted address to insert into SMTP headers
+        * @return string
+        */
+       function toString() {
+               # PHP's mail() implementation under Windows is somewhat shite, and
+               # can't handle "Joe Bloggs <joe@bloggs.com>" format email addresses,
+               # so don't bother generating them
+               if ( $this->address ) {
+                       if ( $this->name != '' && !wfIsWindows() ) {
+                               global $wgEnotifUseRealName;
+                               $name = ( $wgEnotifUseRealName && $this->realName !== '' ) ? $this->realName : $this->name;
+                               $quoted = UserMailer::quotedPrintable( $name );
+                               if ( strpos( $quoted, '.' ) !== false || strpos( $quoted, ',' ) !== false ) {
+                                       $quoted = '"' . $quoted . '"';
+                               }
+                               return "$quoted <{$this->address}>";
+                       } else {
+                               return $this->address;
+                       }
+               } else {
+                       return "";
+               }
+       }
+
+       function __toString() {
+               return $this->toString();
+       }
+}
diff --git a/includes/mail/UserMailer.php b/includes/mail/UserMailer.php
new file mode 100644 (file)
index 0000000..b5a57a8
--- /dev/null
@@ -0,0 +1,425 @@
+<?php
+/**
+ * Classes used to send e-mails
+ *
+ * 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 <brion@pobox.com>
+ * @author <mail@tgries.de>
+ * @author Tim Starling
+ * @author Luke Welling lwelling@wikimedia.org
+ */
+
+/**
+ * Collection of static functions for sending mail
+ */
+class UserMailer {
+       private static $mErrorString;
+
+       /**
+        * Send mail using a PEAR mailer
+        *
+        * @param UserMailer $mailer
+        * @param string $dest
+        * @param string $headers
+        * @param string $body
+        *
+        * @return Status
+        */
+       protected static function sendWithPear( $mailer, $dest, $headers, $body ) {
+               $mailResult = $mailer->send( $dest, $headers, $body );
+
+               # Based on the result return an error string,
+               if ( PEAR::isError( $mailResult ) ) {
+                       wfDebug( "PEAR::Mail failed: " . $mailResult->getMessage() . "\n" );
+                       return Status::newFatal( 'pear-mail-error', $mailResult->getMessage() );
+               } else {
+                       return Status::newGood();
+               }
+       }
+
+       /**
+        * Creates a single string from an associative array
+        *
+        * @param array $headers Associative Array: keys are header field names,
+        *                 values are ... values.
+        * @param string $endl The end of line character.  Defaults to "\n"
+        *
+        * Note RFC2822 says newlines must be CRLF (\r\n)
+        * but php mail naively "corrects" it and requires \n for the "correction" to work
+        *
+        * @return string
+        */
+       static function arrayToHeaderString( $headers, $endl = "\n" ) {
+               $strings = array();
+               foreach ( $headers as $name => $value ) {
+                       // Prevent header injection by stripping newlines from value
+                       $value = self::sanitizeHeaderValue( $value );
+                       $strings[] = "$name: $value";
+               }
+               return implode( $endl, $strings );
+       }
+
+       /**
+        * Create a value suitable for the MessageId Header
+        *
+        * @return string
+        */
+       static function makeMsgId() {
+               global $wgSMTP, $wgServer;
+
+               $msgid = uniqid( wfWikiID() . ".", true ); /* true required for cygwin */
+               if ( is_array( $wgSMTP ) && isset( $wgSMTP['IDHost'] ) && $wgSMTP['IDHost'] ) {
+                       $domain = $wgSMTP['IDHost'];
+               } else {
+                       $url = wfParseUrl( $wgServer );
+                       $domain = $url['host'];
+               }
+               return "<$msgid@$domain>";
+       }
+
+       /**
+        * This function will perform a direct (authenticated) login to
+        * a SMTP Server to use for mail relaying if 'wgSMTP' specifies an
+        * array of parameters. It requires PEAR:Mail to do that.
+        * Otherwise it just uses the standard PHP 'mail' function.
+        *
+        * @param MailAddress|MailAddress[] $to Recipient's email (or an array of them)
+        * @param MailAddress $from Sender's email
+        * @param string $subject Email's subject.
+        * @param string $body Email's text or Array of two strings to be the text and html bodies
+        * @param MailAddress $replyto Optional reply-to email (default: null).
+        * @param string $contentType Optional custom Content-Type (default: text/plain; charset=UTF-8)
+        * @throws MWException
+        * @throws Exception
+        * @return Status
+        */
+       public static function send( $to, $from, $subject, $body, $replyto = null,
+               $contentType = 'text/plain; charset=UTF-8'
+       ) {
+               global $wgSMTP, $wgEnotifMaxRecips, $wgAdditionalMailParams, $wgAllowHTMLEmail;
+               $mime = null;
+               if ( !is_array( $to ) ) {
+                       $to = array( $to );
+               }
+
+               // mail body must have some content
+               $minBodyLen = 10;
+               // arbitrary but longer than Array or Object to detect casting error
+
+               // body must either be a string or an array with text and body
+               if (
+                       !(
+                               !is_array( $body ) &&
+                               strlen( $body ) >= $minBodyLen
+                       )
+                       &&
+                       !(
+                               is_array( $body ) &&
+                               isset( $body['text'] ) &&
+                               isset( $body['html'] ) &&
+                               strlen( $body['text'] ) >= $minBodyLen &&
+                               strlen( $body['html'] ) >= $minBodyLen
+                       )
+               ) {
+                       // if it is neither we have a problem
+                       return Status::newFatal( 'user-mail-no-body' );
+               }
+
+               if ( !$wgAllowHTMLEmail && is_array( $body ) ) {
+                       // HTML not wanted.  Dump it.
+                       $body = $body['text'];
+               }
+
+               wfDebug( __METHOD__ . ': sending mail to ' . implode( ', ', $to ) . "\n" );
+
+               # Make sure we have at least one address
+               $has_address = false;
+               foreach ( $to as $u ) {
+                       if ( $u->address ) {
+                               $has_address = true;
+                               break;
+                       }
+               }
+               if ( !$has_address ) {
+                       return Status::newFatal( 'user-mail-no-addy' );
+               }
+
+               # Forge email headers
+               # -------------------
+               #
+               # WARNING
+               #
+               # DO NOT add To: or Subject: headers at this step. They need to be
+               # handled differently depending upon the mailer we are going to use.
+               #
+               # To:
+               #  PHP mail() first argument is the mail receiver. The argument is
+               #  used as a recipient destination and as a To header.
+               #
+               #  PEAR mailer has a recipient argument which is only used to
+               #  send the mail. If no To header is given, PEAR will set it to
+               #  to 'undisclosed-recipients:'.
+               #
+               #  NOTE: To: is for presentation, the actual recipient is specified
+               #  by the mailer using the Rcpt-To: header.
+               #
+               # Subject:
+               #  PHP mail() second argument to pass the subject, passing a Subject
+               #  as an additional header will result in a duplicate header.
+               #
+               #  PEAR mailer should be passed a Subject header.
+               #
+               # -- hashar 20120218
+
+               $headers['From'] = $from->toString();
+               $returnPath = $from->address;
+               $extraParams = $wgAdditionalMailParams;
+
+               // Hook to generate custom VERP address for 'Return-Path'
+               wfRunHooks( 'UserMailerChangeReturnPath', array( $to, &$returnPath ) );
+               # Add the envelope sender address using the -f command line option when PHP mail() is used.
+               # Will default to the $from->address when the UserMailerChangeReturnPath hook fails and the
+               # generated VERP address when the hook runs effectively.
+               $extraParams .= ' -f ' . $returnPath;
+
+               $headers['Return-Path'] = $returnPath;
+
+               if ( $replyto ) {
+                       $headers['Reply-To'] = $replyto->toString();
+               }
+
+               $headers['Date'] = MWTimestamp::getLocalInstance()->format( 'r' );
+               $headers['Message-ID'] = self::makeMsgId();
+               $headers['X-Mailer'] = 'MediaWiki mailer';
+
+               # Line endings need to be different on Unix and Windows due to
+               # the bug described at http://trac.wordpress.org/ticket/2603
+               if ( wfIsWindows() ) {
+                       $endl = "\r\n";
+               } else {
+                       $endl = "\n";
+               }
+
+               if ( is_array( $body ) ) {
+                       // we are sending a multipart message
+                       wfDebug( "Assembling multipart mime email\n" );
+                       if ( !stream_resolve_include_path( 'Mail/mime.php' ) ) {
+                               wfDebug( "PEAR Mail_Mime package is not installed. Falling back to text email.\n" );
+                               // remove the html body for text email fall back
+                               $body = $body['text'];
+                       } else {
+                               require_once 'Mail/mime.php';
+                               if ( wfIsWindows() ) {
+                                       $body['text'] = str_replace( "\n", "\r\n", $body['text'] );
+                                       $body['html'] = str_replace( "\n", "\r\n", $body['html'] );
+                               }
+                               $mime = new Mail_mime( array(
+                                       'eol' => $endl,
+                                       'text_charset' => 'UTF-8',
+                                       'html_charset' => 'UTF-8'
+                               ) );
+                               $mime->setTXTBody( $body['text'] );
+                               $mime->setHTMLBody( $body['html'] );
+                               $body = $mime->get(); // must call get() before headers()
+                               $headers = $mime->headers( $headers );
+                       }
+               }
+               if ( $mime === null ) {
+                       // sending text only, either deliberately or as a fallback
+                       if ( wfIsWindows() ) {
+                               $body = str_replace( "\n", "\r\n", $body );
+                       }
+                       $headers['MIME-Version'] = '1.0';
+                       $headers['Content-type'] = ( is_null( $contentType ) ?
+                               'text/plain; charset=UTF-8' : $contentType );
+                       $headers['Content-transfer-encoding'] = '8bit';
+               }
+
+               $ret = wfRunHooks( 'AlternateUserMailer', array( $headers, $to, $from, $subject, $body ) );
+               if ( $ret === false ) {
+                       // the hook implementation will return false to skip regular mail sending
+                       return Status::newGood();
+               } elseif ( $ret !== true ) {
+                       // the hook implementation will return a string to pass an error message
+                       return Status::newFatal( 'php-mail-error', $ret );
+               }
+
+               if ( is_array( $wgSMTP ) ) {
+                       #
+                       # PEAR MAILER
+                       #
+
+                       if ( !stream_resolve_include_path( 'Mail.php' ) ) {
+                               throw new MWException( 'PEAR mail package is not installed' );
+                       }
+                       require_once 'Mail.php';
+
+                       wfSuppressWarnings();
+
+                       // Create the mail object using the Mail::factory method
+                       $mail_object =& Mail::factory( 'smtp', $wgSMTP );
+                       if ( PEAR::isError( $mail_object ) ) {
+                               wfDebug( "PEAR::Mail factory failed: " . $mail_object->getMessage() . "\n" );
+                               wfRestoreWarnings();
+                               return Status::newFatal( 'pear-mail-error', $mail_object->getMessage() );
+                       }
+
+                       wfDebug( "Sending mail via PEAR::Mail\n" );
+
+                       $headers['Subject'] = self::quotedPrintable( $subject );
+
+                       # When sending only to one recipient, shows it its email using To:
+                       if ( count( $to ) == 1 ) {
+                               $headers['To'] = $to[0]->toString();
+                       }
+
+                       # Split jobs since SMTP servers tends to limit the maximum
+                       # number of possible recipients.
+                       $chunks = array_chunk( $to, $wgEnotifMaxRecips );
+                       foreach ( $chunks as $chunk ) {
+                               $status = self::sendWithPear( $mail_object, $chunk, $headers, $body );
+                               # FIXME : some chunks might be sent while others are not!
+                               if ( !$status->isOK() ) {
+                                       wfRestoreWarnings();
+                                       return $status;
+                               }
+                       }
+                       wfRestoreWarnings();
+                       return Status::newGood();
+               } else {
+                       #
+                       # PHP mail()
+                       #
+                       if ( count( $to ) > 1 ) {
+                               $headers['To'] = 'undisclosed-recipients:;';
+                       }
+                       $headers = self::arrayToHeaderString( $headers, $endl );
+
+                       wfDebug( "Sending mail via internal mail() function\n" );
+
+                       self::$mErrorString = '';
+                       $html_errors = ini_get( 'html_errors' );
+                       ini_set( 'html_errors', '0' );
+                       set_error_handler( 'UserMailer::errorHandler' );
+
+                       try {
+                               $safeMode = wfIniGetBool( 'safe_mode' );
+
+                               foreach ( $to as $recip ) {
+                                       if ( $safeMode ) {
+                                               $sent = mail( $recip, self::quotedPrintable( $subject ), $body, $headers );
+                                       } else {
+                                               $sent = mail(
+                                                       $recip,
+                                                       self::quotedPrintable( $subject ),
+                                                       $body,
+                                                       $headers,
+                                                       $extraParams
+                                               );
+                                       }
+                               }
+                       } catch ( Exception $e ) {
+                               restore_error_handler();
+                               throw $e;
+                       }
+
+                       restore_error_handler();
+                       ini_set( 'html_errors', $html_errors );
+
+                       if ( self::$mErrorString ) {
+                               wfDebug( "Error sending mail: " . self::$mErrorString . "\n" );
+                               return Status::newFatal( 'php-mail-error', self::$mErrorString );
+                       } elseif ( !$sent ) {
+                               // mail function only tells if there's an error
+                               wfDebug( "Unknown error sending mail\n" );
+                               return Status::newFatal( 'php-mail-error-unknown' );
+                       } else {
+                               return Status::newGood();
+                       }
+               }
+       }
+
+       /**
+        * Set the mail error message in self::$mErrorString
+        *
+        * @param int $code Error number
+        * @param string $string Error message
+        */
+       static function errorHandler( $code, $string ) {
+               self::$mErrorString = preg_replace( '/^mail\(\)(\s*\[.*?\])?: /', '', $string );
+       }
+
+       /**
+        * Strips bad characters from a header value to prevent PHP mail header injection attacks
+        * @param string $val String to be santizied
+        * @return string
+        */
+       public static function sanitizeHeaderValue( $val ) {
+               return strtr( $val, array( "\r" => '', "\n" => '' ) );
+       }
+
+       /**
+        * Converts a string into a valid RFC 822 "phrase", such as is used for the sender name
+        * @param string $phrase
+        * @return string
+        */
+       public static function rfc822Phrase( $phrase ) {
+               // Remove line breaks
+               $phrase = self::sanitizeHeaderValue( $phrase );
+               // Remove quotes
+               $phrase = str_replace( '"', '', $phrase );
+               return '"' . $phrase . '"';
+       }
+
+       /**
+        * Converts a string into quoted-printable format
+        * @since 1.17
+        *
+        * From PHP5.3 there is a built in function quoted_printable_encode()
+        * This method does not duplicate that.
+        * This method is doing Q encoding inside encoded-words as defined by RFC 2047
+        * This is for email headers.
+        * The built in quoted_printable_encode() is for email bodies
+        * @param string $string
+        * @param string $charset
+        * @return string
+        */
+       public static function quotedPrintable( $string, $charset = '' ) {
+               # Probably incomplete; see RFC 2045
+               if ( empty( $charset ) ) {
+                       $charset = 'UTF-8';
+               }
+               $charset = strtoupper( $charset );
+               $charset = str_replace( 'ISO-8859', 'ISO8859', $charset ); // ?
+
+               $illegal = '\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\xff=';
+               $replace = $illegal . '\t ?_';
+               if ( !preg_match( "/[$illegal]/", $string ) ) {
+                       return $string;
+               }
+               $out = "=?$charset?Q?";
+               $out .= preg_replace_callback( "/([$replace])/",
+                       array( __CLASS__, 'quotedPrintableCallback' ), $string );
+               $out .= '?=';
+               return $out;
+       }
+
+       protected static function quotedPrintableCallback( $matches ) {
+               return sprintf( "=%02X", ord( $matches[1] ) );
+       }
+}
index 9a3e927..e81b37d 100644 (file)
  *
  * @ingroup Media
  */
-class BitmapHandler extends ImageHandler {
-       /**
-        * @param File $image
-        * @param array $params Transform parameters. Entries with the keys 'width'
-        * and 'height' are the respective screen width and height, while the keys
-        * 'physicalWidth' and 'physicalHeight' indicate the thumbnail dimensions.
-        * @return bool
-        */
-       function normaliseParams( $image, &$params ) {
-               if ( !parent::normaliseParams( $image, $params ) ) {
-                       return false;
-               }
-
-               # Obtain the source, pre-rotation dimensions
-               $srcWidth = $image->getWidth( $params['page'] );
-               $srcHeight = $image->getHeight( $params['page'] );
-
-               # Don't make an image bigger than the source
-               if ( $params['physicalWidth'] >= $srcWidth ) {
-                       $params['physicalWidth'] = $srcWidth;
-                       $params['physicalHeight'] = $srcHeight;
-
-                       # Skip scaling limit checks if no scaling is required
-                       # due to requested size being bigger than source.
-                       if ( !$image->mustRender() ) {
-                               return true;
-                       }
-               }
-
-               # Check if the file is smaller than the maximum image area for thumbnailing
-               $checkImageAreaHookResult = null;
-               wfRunHooks(
-                       'BitmapHandlerCheckImageArea',
-                       array( $image, &$params, &$checkImageAreaHookResult )
-               );
-
-               if ( is_null( $checkImageAreaHookResult ) ) {
-                       global $wgMaxImageArea;
-
-                       if ( $srcWidth * $srcHeight > $wgMaxImageArea
-                               && !( $image->getMimeType() == 'image/jpeg'
-                                       && self::getScalerType( false, false ) == 'im' )
-                       ) {
-                               # Only ImageMagick can efficiently downsize jpg images without loading
-                               # the entire file in memory
-                               return false;
-                       }
-               } else {
-                       return $checkImageAreaHookResult;
-               }
-
-               return true;
-       }
-
-       /**
-        * Extracts the width/height if the image will be scaled before rotating
-        *
-        * This will match the physical size/aspect ratio of the original image
-        * prior to application of the rotation -- so for a portrait image that's
-        * stored as raw landscape with 90-degress rotation, the resulting size
-        * will be wider than it is tall.
-        *
-        * @param array $params Parameters as returned by normaliseParams
-        * @param int $rotation The rotation angle that will be applied
-        * @return array ($width, $height) array
-        */
-       public function extractPreRotationDimensions( $params, $rotation ) {
-               if ( $rotation == 90 || $rotation == 270 ) {
-                       # We'll resize before rotation, so swap the dimensions again
-                       $width = $params['physicalHeight'];
-                       $height = $params['physicalWidth'];
-               } else {
-                       $width = $params['physicalWidth'];
-                       $height = $params['physicalHeight'];
-               }
-
-               return array( $width, $height );
-       }
-
-       /**
-        * @param File $image
-        * @param string $dstPath
-        * @param string $dstUrl
-        * @param array $params
-        * @param int $flags
-        * @return MediaTransformError|ThumbnailImage|TransformParameterError
-        */
-       function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
-               if ( !$this->normaliseParams( $image, $params ) ) {
-                       return new TransformParameterError( $params );
-               }
-
-               # Create a parameter array to pass to the scaler
-               $scalerParams = array(
-                       # The size to which the image will be resized
-                       'physicalWidth' => $params['physicalWidth'],
-                       'physicalHeight' => $params['physicalHeight'],
-                       'physicalDimensions' => "{$params['physicalWidth']}x{$params['physicalHeight']}",
-                       # The size of the image on the page
-                       'clientWidth' => $params['width'],
-                       'clientHeight' => $params['height'],
-                       # Comment as will be added to the Exif of the thumbnail
-                       'comment' => isset( $params['descriptionUrl'] )
-                               ? "File source: {$params['descriptionUrl']}"
-                               : '',
-                       # Properties of the original image
-                       'srcWidth' => $image->getWidth(),
-                       'srcHeight' => $image->getHeight(),
-                       'mimeType' => $image->getMimeType(),
-                       'dstPath' => $dstPath,
-                       'dstUrl' => $dstUrl,
-               );
-
-               if ( isset( $params['quality'] ) && $params['quality'] === 'low' ) {
-                       $scalerParams['quality'] = 30;
-               }
-
-               # Determine scaler type
-               $scaler = self::getScalerType( $dstPath );
-
-               wfDebug( __METHOD__ . ": creating {$scalerParams['physicalDimensions']} " .
-                       "thumbnail at $dstPath using scaler $scaler\n" );
-
-               if ( !$image->mustRender() &&
-                       $scalerParams['physicalWidth'] == $scalerParams['srcWidth']
-                       && $scalerParams['physicalHeight'] == $scalerParams['srcHeight']
-                       && !isset( $scalerParams['quality'] )
-               ) {
-
-                       # normaliseParams (or the user) wants us to return the unscaled image
-                       wfDebug( __METHOD__ . ": returning unscaled image\n" );
-
-                       return $this->getClientScalingThumbnailImage( $image, $scalerParams );
-               }
-
-               if ( $scaler == 'client' ) {
-                       # Client-side image scaling, use the source URL
-                       # Using the destination URL in a TRANSFORM_LATER request would be incorrect
-                       return $this->getClientScalingThumbnailImage( $image, $scalerParams );
-               }
-
-               if ( $flags & self::TRANSFORM_LATER ) {
-                       wfDebug( __METHOD__ . ": Transforming later per flags.\n" );
-                       $newParams = array(
-                               'width' => $scalerParams['clientWidth'],
-                               'height' => $scalerParams['clientHeight']
-                       );
-                       if ( isset( $params['quality'] ) ) {
-                               $newParams['quality'] = $params['quality'];
-                       }
-                       return new ThumbnailImage( $image, $dstUrl, false, $newParams );
-               }
-
-               # Try to make a target path for the thumbnail
-               if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) {
-                       wfDebug( __METHOD__ . ": Unable to create thumbnail destination " .
-                               "directory, falling back to client scaling\n" );
-
-                       return $this->getClientScalingThumbnailImage( $image, $scalerParams );
-               }
-
-               # Transform functions and binaries need a FS source file
-               $thumbnailSource = $image->getThumbnailSource( $params );
-
-               $scalerParams['srcPath'] = $thumbnailSource['path'];
-               $scalerParams['srcWidth'] = $thumbnailSource['width'];
-               $scalerParams['srcHeight'] = $thumbnailSource['height'];
-
-               if ( $scalerParams['srcPath'] === false ) { // Failed to get local copy
-                       wfDebugLog( 'thumbnail',
-                               sprintf( 'Thumbnail failed on %s: could not get local copy of "%s"',
-                                       wfHostname(), $image->getName() ) );
-
-                       return new MediaTransformError( 'thumbnail_error',
-                               $scalerParams['clientWidth'], $scalerParams['clientHeight'],
-                               wfMessage( 'filemissing' )->text()
-                       );
-               }
-
-               # Try a hook
-               $mto = null;
-               wfRunHooks( 'BitmapHandlerTransform', array( $this, $image, &$scalerParams, &$mto ) );
-               if ( !is_null( $mto ) ) {
-                       wfDebug( __METHOD__ . ": Hook to BitmapHandlerTransform created an mto\n" );
-                       $scaler = 'hookaborted';
-               }
-
-               switch ( $scaler ) {
-                       case 'hookaborted':
-                               # Handled by the hook above
-                               /** @var MediaTransformOutput $mto */
-                               $err = $mto->isError() ? $mto : false;
-                               break;
-                       case 'im':
-                               $err = $this->transformImageMagick( $image, $scalerParams );
-                               break;
-                       case 'custom':
-                               $err = $this->transformCustom( $image, $scalerParams );
-                               break;
-                       case 'imext':
-                               $err = $this->transformImageMagickExt( $image, $scalerParams );
-                               break;
-                       case 'gd':
-                       default:
-                               $err = $this->transformGd( $image, $scalerParams );
-                               break;
-               }
-
-               # Remove the file if a zero-byte thumbnail was created, or if there was an error
-               $removed = $this->removeBadFile( $dstPath, (bool)$err );
-               if ( $err ) {
-                       # transform returned MediaTransforError
-                       return $err;
-               } elseif ( $removed ) {
-                       # Thumbnail was zero-byte and had to be removed
-                       return new MediaTransformError( 'thumbnail_error',
-                               $scalerParams['clientWidth'], $scalerParams['clientHeight'],
-                               wfMessage( 'unknown-error' )->text()
-                       );
-               } elseif ( $mto ) {
-                       return $mto;
-               } else {
-                       $newParams = array(
-                               'width' => $scalerParams['clientWidth'],
-                               'height' => $scalerParams['clientHeight']
-                       );
-                       if ( isset( $params['quality'] ) ) {
-                               $newParams['quality'] = $params['quality'];
-                       }
-                       return new ThumbnailImage( $image, $dstUrl, $dstPath, $newParams );
-               }
-       }
+class BitmapHandler extends TransformationalImageHandler {
 
        /**
         * Returns which scaler type should be used. Creates parent directories
@@ -265,9 +34,9 @@ class BitmapHandler extends ImageHandler {
         *
         * @param string $dstPath
         * @param bool $checkDstPath
-        * @return string One of client, im, custom, gd, imext
+        * @return string|Callable One of client, im, custom, gd, imext or an array( object, method )
         */
-       protected static function getScalerType( $dstPath, $checkDstPath = true ) {
+       protected function getScalerType( $dstPath, $checkDstPath = true ) {
                global $wgUseImageResize, $wgUseImageMagick, $wgCustomConvertCommand;
 
                if ( !$dstPath && $checkDstPath ) {
@@ -290,25 +59,6 @@ class BitmapHandler extends ImageHandler {
                return $scaler;
        }
 
-       /**
-        * Get a ThumbnailImage that respresents an image that will be scaled
-        * client side
-        *
-        * @param File $image File associated with this thumbnail
-        * @param array $scalerParams Array with scaler params
-        * @return ThumbnailImage
-        *
-        * @todo FIXME: No rotation support
-        */
-       protected function getClientScalingThumbnailImage( $image, $scalerParams ) {
-               $params = array(
-                       'width' => $scalerParams['clientWidth'],
-                       'height' => $scalerParams['clientHeight']
-               );
-
-               return new ThumbnailImage( $image, $image->getURL(), null, $params );
-       }
-
        /**
         * Transform an image using ImageMagick
         *
@@ -329,7 +79,7 @@ class BitmapHandler extends ImageHandler {
                $animation_post = array();
                $decoderHint = array();
                if ( $params['mimeType'] == 'image/jpeg' ) {
-                       $qualityVal = isset( $params['quality'] ) ? (string) $params['quality'] : null;
+                       $qualityVal = isset( $params['quality'] ) ? (string)$params['quality'] : null;
                        $quality = array( '-quality', $qualityVal ?: '80' ); // 80%
                        # Sharpening, see bug 6193
                        if ( ( $params['physicalWidth'] + $params['physicalHeight'] )
@@ -366,7 +116,7 @@ class BitmapHandler extends ImageHandler {
                        // background colour. After merging we reset the background
                        // to be white for the default background colour setting
                        // in the PNG image (which is used in old IE)
-                       $animation_post = array(
+                       $animation_pre = array(
                                '-background', 'transparent',
                                '-layers', 'merge',
                                '-background', 'white',
@@ -382,7 +132,7 @@ class BitmapHandler extends ImageHandler {
                                // bug 66323 - Greyscale images not rendered properly.
                                // So only take the "red" channel.
                                $channelOnly = array( '-channel', 'R', '-separate' );
-                               $animation_post = array_merge( $animation_post, $channelOnly );
+                               $animation_pre = array_merge( $animation_pre, $channelOnly );
                        }
                }
 
@@ -458,7 +208,7 @@ class BitmapHandler extends ImageHandler {
                                        list( $radius, $sigma ) = explode( 'x', $wgSharpenParameter );
                                        $im->sharpenImage( $radius, $sigma );
                                }
-                               $qualityVal = isset( $params['quality'] ) ? (string) $params['quality'] : null;
+                               $qualityVal = isset( $params['quality'] ) ? (string)$params['quality'] : null;
                                $im->setCompressionQuality( $qualityVal ?: 80 );
                        } elseif ( $params['mimeType'] == 'image/png' ) {
                                $im->setCompressionQuality( 95 );
@@ -544,18 +294,6 @@ class BitmapHandler extends ImageHandler {
                return false; # No error
        }
 
-       /**
-        * Get a MediaTransformError with error 'thumbnail_error'
-        *
-        * @param array $params Parameter array as passed to the transform* functions
-        * @param string $errMsg Error message
-        * @return MediaTransformError
-        */
-       public function getMediaTransformError( $params, $errMsg ) {
-               return new MediaTransformError( 'thumbnail_error', $params['clientWidth'],
-                       $params['clientHeight'], $errMsg );
-       }
-
        /**
         * Transform an image using the built in GD library
         *
@@ -651,131 +389,8 @@ class BitmapHandler extends ImageHandler {
        }
 
        /**
-        * Escape a string for ImageMagick's property input (e.g. -set -comment)
-        * See InterpretImageProperties() in magick/property.c
-        * @param string $s
-        * @return string
-        */
-       function escapeMagickProperty( $s ) {
-               // Double the backslashes
-               $s = str_replace( '\\', '\\\\', $s );
-               // Double the percents
-               $s = str_replace( '%', '%%', $s );
-               // Escape initial - or @
-               if ( strlen( $s ) > 0 && ( $s[0] === '-' || $s[0] === '@' ) ) {
-                       $s = '\\' . $s;
-               }
-
-               return $s;
-       }
-
-       /**
-        * Escape a string for ImageMagick's input filenames. See ExpandFilenames()
-        * and GetPathComponent() in magick/utility.c.
-        *
-        * This won't work with an initial ~ or @, so input files should be prefixed
-        * with the directory name.
-        *
-        * Glob character unescaping is broken in ImageMagick before 6.6.1-5, but
-        * it's broken in a way that doesn't involve trying to convert every file
-        * in a directory, so we're better off escaping and waiting for the bugfix
-        * to filter down to users.
-        *
-        * @param string $path The file path
-        * @param bool|string $scene The scene specification, or false if there is none
-        * @throws MWException
-        * @return string
-        */
-       function escapeMagickInput( $path, $scene = false ) {
-               # Die on initial metacharacters (caller should prepend path)
-               $firstChar = substr( $path, 0, 1 );
-               if ( $firstChar === '~' || $firstChar === '@' ) {
-                       throw new MWException( __METHOD__ . ': cannot escape this path name' );
-               }
-
-               # Escape glob chars
-               $path = preg_replace( '/[*?\[\]{}]/', '\\\\\0', $path );
-
-               return $this->escapeMagickPath( $path, $scene );
-       }
-
-       /**
-        * Escape a string for ImageMagick's output filename. See
-        * InterpretImageFilename() in magick/image.c.
-        * @param string $path The file path
-        * @param bool|string $scene The scene specification, or false if there is none
-        * @return string
-        */
-       function escapeMagickOutput( $path, $scene = false ) {
-               $path = str_replace( '%', '%%', $path );
-
-               return $this->escapeMagickPath( $path, $scene );
-       }
-
-       /**
-        * Armour a string against ImageMagick's GetPathComponent(). This is a
-        * helper function for escapeMagickInput() and escapeMagickOutput().
-        *
-        * @param string $path The file path
-        * @param bool|string $scene The scene specification, or false if there is none
-        * @throws MWException
-        * @return string
-        */
-       protected function escapeMagickPath( $path, $scene = false ) {
-               # Die on format specifiers (other than drive letters). The regex is
-               # meant to match all the formats you get from "convert -list format"
-               if ( preg_match( '/^([a-zA-Z0-9-]+):/', $path, $m ) ) {
-                       if ( wfIsWindows() && is_dir( $m[0] ) ) {
-                               // OK, it's a drive letter
-                               // ImageMagick has a similar exception, see IsMagickConflict()
-                       } else {
-                               throw new MWException( __METHOD__ . ': unexpected colon character in path name' );
-                       }
-               }
-
-               # If there are square brackets, add a do-nothing scene specification
-               # to force a literal interpretation
-               if ( $scene === false ) {
-                       if ( strpos( $path, '[' ) !== false ) {
-                               $path .= '[0--1]';
-                       }
-               } else {
-                       $path .= "[$scene]";
-               }
-
-               return $path;
-       }
-
-       /**
-        * Retrieve the version of the installed ImageMagick
-        * You can use PHPs version_compare() to use this value
-        * Value is cached for one hour.
-        * @return string Representing the IM version.
+        * Callback for transformGd when transforming jpeg images.
         */
-       protected function getMagickVersion() {
-               global $wgMemc;
-
-               $cache = $wgMemc->get( "imagemagick-version" );
-               if ( !$cache ) {
-                       global $wgImageMagickConvertCommand;
-                       $cmd = wfEscapeShellArg( $wgImageMagickConvertCommand ) . ' -version';
-                       wfDebug( __METHOD__ . ": Running convert -version\n" );
-                       $retval = '';
-                       $return = wfShellExec( $cmd, $retval );
-                       $x = preg_match( '/Version: ImageMagick ([0-9]*\.[0-9]*\.[0-9]*)/', $return, $matches );
-                       if ( $x != 1 ) {
-                               wfDebug( __METHOD__ . ": ImageMagick version check failed\n" );
-
-                               return null;
-                       }
-                       $wgMemc->set( "imagemagick-version", $matches[1], 3600 );
-
-                       return $matches[1];
-               }
-
-               return $cache;
-       }
-
        // FIXME: transformImageMagick() & transformImageMagickExt() uses JPEG quality 80, here it's 95?
        static function imageJpegWrapper( $dst_image, $thumbPath, $quality = 95 ) {
                imageinterlace( $dst_image );
@@ -787,8 +402,8 @@ class BitmapHandler extends ImageHandler {
         *
         * @return bool
         */
-       public static function canRotate() {
-               $scaler = self::getScalerType( null, false );
+       public function canRotate() {
+               $scaler = $this->getScalerType( null, false );
                switch ( $scaler ) {
                        case 'im':
                                # ImageMagick supports autorotation
@@ -810,12 +425,12 @@ class BitmapHandler extends ImageHandler {
         * @see $wgEnableAutoRotation
         * @return bool Whether auto rotation is enabled
         */
-       public static function autoRotateEnabled() {
+       public function autoRotateEnabled() {
                global $wgEnableAutoRotation;
 
                if ( $wgEnableAutoRotation === null ) {
-                       // Only enable auto-rotation when the bitmap handler can rotate
-                       $wgEnableAutoRotation = BitmapHandler::canRotate();
+                       // Only enable auto-rotation when we actually can
+                       return $this->canRotate();
                }
 
                return $wgEnableAutoRotation;
@@ -834,7 +449,7 @@ class BitmapHandler extends ImageHandler {
                $rotation = ( $params['rotation'] + $this->getRotation( $file ) ) % 360;
                $scene = false;
 
-               $scaler = self::getScalerType( null, false );
+               $scaler = $this->getScalerType( null, false );
                switch ( $scaler ) {
                        case 'im':
                                $cmd = wfEscapeShellArg( $wgImageMagickConvertCommand ) . " " .
@@ -872,15 +487,4 @@ class BitmapHandler extends ImageHandler {
                                        "$scaler rotation not implemented" );
                }
        }
-
-       /**
-        * Returns whether the file needs to be rendered. Returns true if the
-        * file requires rotation and we are able to rotate it.
-        *
-        * @param File $file
-        * @return bool
-        */
-       public function mustRender( $file ) {
-               return self::canRotate() && $this->getRotation( $file ) != 0;
-       }
 }
index 2a393db..dd41c38 100644 (file)
@@ -97,7 +97,7 @@ class BitmapMetadataHandler {
        /** Add misc metadata. Warning: atm if the metadata category
         * doesn't have a priority, it will be silently discarded.
         *
-        * @param array $metaArray array of metadata values
+        * @param array $metaArray Array of metadata values
         * @param string $type Type. defaults to other. if two things have the same type they're merged
         */
        function addMetadata( $metaArray, $type = 'other' ) {
@@ -149,9 +149,9 @@ class BitmapMetadataHandler {
 
        /** Main entry point for jpeg's.
         *
-        * @param string $filename filename (with full path)
+        * @param string $filename Filename (with full path)
         * @return array Metadata result array.
-        * @throws MWException on invalid file.
+        * @throws MWException On invalid file.
         */
        static function Jpeg( $filename ) {
                $showXMP = function_exists( 'xml_parser_create_ns' );
@@ -224,7 +224,7 @@ class BitmapMetadataHandler {
         * They don't really have native metadata, so just merges together
         * XMP and image comment.
         *
-        * @param string $filename full path to file
+        * @param string $filename Full path to file
         * @return array Metadata array
         */
        public static function GIF( $filename ) {
index 200d526..daeb475 100644 (file)
@@ -73,7 +73,7 @@ class DjVuHandler extends ImageHandler {
         * @return bool
         */
        function validateParam( $name, $value ) {
-               if ( $name === 'page' && trim( $value ) !== (string) intval( $value ) ) {
+               if ( $name === 'page' && trim( $value ) !== (string)intval( $value ) ) {
                        // Extra junk on the end of page, probably actually a caption
                        // e.g. [[File:Foo.djvu|thumb|Page 3 of the document shows foo]]
                        return false;
@@ -188,7 +188,7 @@ class DjVuHandler extends ImageHandler {
                if ( $image->getSize() >= 1e7 ) { // 10MB
                        $work = new PoolCounterWorkViaCallback( 'GetLocalFileCopy', sha1( $image->getName() ),
                                array(
-                                       'doWork' => function() use ( $image ) {
+                                       'doWork' => function () use ( $image ) {
                                                return $image->getLocalRefPath();
                                        }
                                )
index 099375b..6ff19c9 100644 (file)
@@ -88,7 +88,7 @@ class DjVuImage {
                // something that explicitly initializes local variables.
                extract( unpack( 'a4magic/a4chunk/NchunkLength', $header ) );
                /** @var string $chunk
-                *  @var string $chunkLength */
+                * @var string $chunkLength */
                echo "$chunk $chunkLength\n";
                $this->dumpForm( $file, $chunkLength, 1 );
                fclose( $file );
@@ -107,7 +107,7 @@ class DjVuImage {
                        // something that explicitly initializes local variables.
                        extract( unpack( 'a4chunk/NchunkLength', $chunkHeader ) );
                        /** @var string $chunk
-                        *  @var string $chunkLength */
+                        * @var string $chunkLength */
                        echo str_repeat( ' ', $indent * 4 ) . "$chunk $chunkLength\n";
 
                        if ( $chunk == 'FORM' ) {
@@ -143,9 +143,9 @@ class DjVuImage {
                        extract( unpack( 'a4magic/a4form/NformLength/a4subtype', $header ) );
 
                        /** @var string $magic
-                        *  @var string $subtype
-                        *  @var string $formLength
-                        *  @var string $formType */
+                        * @var string $subtype
+                        * @var string $formLength
+                        * @var string $formType */
                        if ( $magic != 'AT&T' ) {
                                wfDebug( __METHOD__ . ": not a DjVu file\n" );
                        } elseif ( $subtype == 'DJVU' ) {
@@ -173,7 +173,7 @@ class DjVuImage {
                        extract( unpack( 'a4chunk/Nlength', $header ) );
 
                        /** @var string $chunk
-                        *  @var string $length */
+                        * @var string $length */
                        return array( $chunk, $length );
                }
        }
@@ -249,12 +249,12 @@ class DjVuImage {
                # Newer files have rotation info in byte 10, but we don't use it yet.
 
                /** @var string $width
-                *  @var string $height
-                *  @var string $major
-                *  @var string $minor
-                *  @var string $resolution
-                *  @var string $length
-                *  @var string $gamma */
+                * @var string $height
+                * @var string $major
+                * @var string $minor
+                * @var string $resolution
+                * @var string $length
+                * @var string $gamma */
                return array(
                        'width' => $width,
                        'height' => $height,
index b39e042..018b58c 100644 (file)
@@ -442,7 +442,7 @@ class Exif {
         * Do userComment tags and similar. See pg. 34 of exif standard.
         * basically first 8 bytes is charset, rest is value.
         * This has not been tested on any shift-JIS strings.
-        * @param string $prop prop name.
+        * @param string $prop Prop name
         */
        private function charCodeString( $prop ) {
                if ( isset( $this->mFilteredExifData[$prop] ) ) {
@@ -470,8 +470,6 @@ class Exif {
                                        $charset = "";
                                        break;
                        }
-                       // This could possibly check to see if iconv is really installed
-                       // or if we're using the compatibility wrapper in globalFunctions.php
                        if ( $charset ) {
                                wfSuppressWarnings();
                                $val = iconv( $charset, 'UTF-8//IGNORE', $val );
@@ -565,6 +563,7 @@ class Exif {
 
        /**
         * Get $this->mFilteredExifData
+        * @return array
         */
        function getFilteredData() {
                return $this->mFilteredExifData;
@@ -588,7 +587,7 @@ class Exif {
                return 2; // We don't need no bloddy constants!
        }
 
-       /**#@+
+       /**
         * Validates if a tag value is of the type it should be according to the Exif spec
         *
         * @param mixed $in The input value to check
@@ -731,8 +730,8 @@ class Exif {
        /**
         * Validates if a tag has a legal value according to the Exif spec
         *
-        * @param string $section section where tag is located.
-        * @param string $tag the tag to check.
+        * @param string $section Section where tag is located.
+        * @param string $tag The tag to check.
         * @param mixed $val The value of the tag.
         * @param bool $recursive True if called recursively for array types.
         * @return bool
@@ -842,7 +841,7 @@ class Exif {
        /**
         * Convenience function for debugging output
         *
-        * @param string $fname the name of the function calling this function
+        * @param string $fname The name of the function calling this function
         * @param bool $io Specify whether we're beginning or ending
         */
        private function debugFile( $fname, $io ) {
index ae1ff9d..b7657cb 100644 (file)
@@ -173,7 +173,7 @@ class ExifBitmapHandler extends BitmapHandler {
 
                // Don't just call $image->getMetadata(); FSFile::getPropsFromPath() calls us with a bogus object.
                // This may mean we read EXIF data twice on initial upload.
-               if ( BitmapHandler::autoRotateEnabled() ) {
+               if ( $this->autoRotateEnabled() ) {
                        $meta = $this->getMetadata( $image, $path );
                        $rotation = $this->getRotationForExif( $meta );
                } else {
@@ -202,7 +202,7 @@ class ExifBitmapHandler extends BitmapHandler {
         * @return int 0, 90, 180 or 270
         */
        public function getRotation( $file ) {
-               if ( !BitmapHandler::autoRotateEnabled() ) {
+               if ( !$this->autoRotateEnabled() ) {
                        return 0;
                }
 
index 4200541..4356953 100644 (file)
@@ -72,7 +72,7 @@ class FormatMetadata extends ContextSource {
         *
         * This is the usual entry point for this class.
         *
-        * @param array $tags the Exif data to format ( as returned by
+        * @param array $tags The Exif data to format ( as returned by
         *   Exif::getFilteredData() or BitmapMetadataHandler )
         * @param bool|IContextSource $context Context to use (optional)
         * @return array
@@ -92,7 +92,7 @@ class FormatMetadata extends ContextSource {
         * value which most of the time are plain integers. This function
         * formats Exif (and other metadata) values into human readable form.
         *
-        * @param array $tags the Exif data to format ( as returned by
+        * @param array $tags The Exif data to format ( as returned by
         *   Exif::getFilteredData() or BitmapMetadataHandler )
         * @return array
         * @since 1.23
@@ -1006,7 +1006,7 @@ class FormatMetadata extends ContextSource {
        /**
         * Flatten an array, using the user language for any messages.
         *
-        * @param array $vals array of values
+        * @param array $vals Array of values
         * @param string $type Type of array (either lang, ul, ol).
         *   lang = language assoc array with keys being the lang code
         *   ul = unordered list, ol = ordered list
@@ -1031,7 +1031,7 @@ class FormatMetadata extends ContextSource {
         *
         * This is public on the basis it might be useful outside of this class.
         *
-        * @param array $vals array of values
+        * @param array $vals Array of values
         * @param string $type Type of array (either lang, ul, ol).
         *     lang = language assoc array with keys being the lang code
         *     ul = unordered list, ol = ordered list
@@ -1706,7 +1706,7 @@ class FormatMetadata extends ContextSource {
         *
         * @param File $file File to use
         * @param array $extendedMetadata
-        * @param int $maxCacheTime hook handlers might use this parameter to override cache time
+        * @param int $maxCacheTime Hook handlers might use this parameter to override cache time
         *
         * @return array [<property name> => ['value' => <value>]], or [] on error
         * @since 1.23
@@ -1741,7 +1741,7 @@ class FormatMetadata extends ContextSource {
         * If the value is not a multilang array, it is returned unchanged.
         * See mediawiki.org/wiki/Manual:File_metadata_handling#Multi-language_array_format
         * @param mixed $value
-        * @return mixed value in best language, null if there were no languages at all
+        * @return mixed Value in best language, null if there were no languages at all
         * @since 1.23
         */
        protected function resolveMultilangValue( $value ) {
index 503b968..478249f 100644 (file)
@@ -34,7 +34,7 @@ class IPTC {
         *
         * @see http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf
         *
-        * @param string $rawData app13 block from jpeg containing iptc/iim data
+        * @param string $rawData The app13 block from jpeg containing iptc/iim data
         * @return array IPTC metadata array
         */
        static function parse( $rawData ) {
@@ -470,7 +470,7 @@ class IPTC {
        /**
         * take the value of 1:90 tag and returns a charset
         * @param string $tag 1:90 tag.
-        * @return string charset name or "?"
+        * @return string Charset name or "?"
         * Warning, this function does not (and is not intended to) detect
         * all iso 2022 escape codes. In practise, the code for utf-8 is the
         * only code that seems to have wide use. It does detect that code.
index 918d4ae..fbdbdfe 100644 (file)
@@ -51,8 +51,8 @@ class JpegHandler extends ExifBitmapHandler {
        }
 
        /** Validate and normalize quality value to be between 1 and 100 (inclusive).
-        * @param int $value quality value, will be converted to integer or 0 if invalid
-        * @return bool true if the value is valid
+        * @param int $value Quality value, will be converted to integer or 0 if invalid
+        * @return bool True if the value is valid
         */
        private static function validateQuality( $value ) {
                return $value === 'low';
index a0f8524..8c5b46b 100644 (file)
@@ -43,9 +43,9 @@ class JpegMetadataExtractor {
         * but gis doesn't support having multiple app1 segments
         * and those can't extract xmp on files containing both exif and xmp data
         *
-        * @param string $filename name of jpeg file
-        * @return array of interesting segments.
-        * @throws MWException if given invalid file.
+        * @param string $filename Name of jpeg file
+        * @return array Array of interesting segments.
+        * @throws MWException If given invalid file.
         */
        static function segmentSplitter( $filename ) {
                $showXMP = function_exists( 'xml_parser_create_ns' );
@@ -193,7 +193,7 @@ class JpegMetadataExtractor {
         *
         * This should generally be called by BitmapMetadataHandler::doApp13()
         *
-        * @param string $app13 photoshop psir app13 block from jpg.
+        * @param string $app13 Photoshop psir app13 block from jpg.
         * @throws MWException (It gets caught next level up though)
         * @return string If the iptc hash is good or not. One of 'iptc-no-hash',
         *   'iptc-good-hash', 'iptc-bad-hash'.
index c4aab7b..64ca011 100644 (file)
@@ -56,6 +56,7 @@ abstract class MediaHandler {
                if ( !isset( self::$handlers[$class] ) ) {
                        self::$handlers[$class] = new $class;
                        if ( !self::$handlers[$class]->isEnabled() ) {
+                               wfDebug( __METHOD__ . ": $class is not enabled\n" );
                                self::$handlers[$class] = false;
                        }
                }
@@ -63,6 +64,13 @@ abstract class MediaHandler {
                return self::$handlers[$class];
        }
 
+       /**
+        * Resets all static caches
+        */
+       public static function resetCache() {
+               self::$handlers = array();
+       }
+
        /**
         * Get an associative array mapping magic word IDs to parameter names.
         * Will be used by the parser to identify parameters.
@@ -116,7 +124,7 @@ abstract class MediaHandler {
         *  first page.
         *
         * @param File $image The image object, or false if there isn't one
-        * @param string $path the filename
+        * @param string $path The filename
         * @return array Follow the format of PHP getimagesize() internal function.
         *   See http://www.php.net/getimagesize. MediaWiki will only ever use the
         *   first two array keys (the width and height), and the 'bits' associative
@@ -300,20 +308,20 @@ abstract class MediaHandler {
         * @param string $ext Extension of original file
         * @param string $mime MIME type of original file
         * @param array $params Handler specific rendering parameters
-        * @return array thumbnail extension and MIME type
+        * @return array Thumbnail extension and MIME type
         */
        function getThumbType( $ext, $mime, $params = null ) {
                $magic = MimeMagic::singleton();
                if ( !$ext || $magic->isMatchingExtension( $ext, $mime ) === false ) {
-                       // The extension is not valid for this mime type and we do
-                       // recognize the mime type
+                       // The extension is not valid for this MIME type and we do
+                       // recognize the MIME type
                        $extensions = $magic->getExtensionsForType( $mime );
                        if ( $extensions ) {
                                return array( strtok( $extensions, ' ' ), $mime );
                        }
                }
 
-               // The extension is correct (true) or the mime type is unknown to
+               // The extension is correct (true) or the MIME type is unknown to
                // MediaWiki (null)
                return array( $ext, $mime );
        }
@@ -681,7 +689,7 @@ abstract class MediaHandler {
         * relevant errors.
         *
         * @param string $fileName The local path to the file.
-        * @return Status object
+        * @return Status
         */
        function verifyUpload( $fileName ) {
                return Status::newGood();
@@ -735,12 +743,12 @@ abstract class MediaHandler {
                // Do nothing
        }
 
-       /*
+       /**
         * True if the handler can rotate the media
-        * @since 1.21
+        * @since 1.24 non-static. From 1.21-1.23 was static
         * @return bool
         */
-       public static function canRotate() {
+       public function canRotate() {
                return false;
        }
 
@@ -835,8 +843,8 @@ abstract class MediaHandler {
        /**
         * Returns whether or not this handler supports the chained generation of thumbnails according
         * to buckets
-        * @return boolean
-        * @since  1.24
+        * @return bool
+        * @since 1.24
         */
        public function supportsBucketing() {
                return false;
index d8d56a4..bc9e917 100644 (file)
@@ -32,7 +32,7 @@ abstract class MediaTransformOutput {
         */
        public $responsiveUrls = array();
 
-       /** @var File object */
+       /** @var File */
        protected $file;
 
        /** @var int Image width */
@@ -71,7 +71,7 @@ abstract class MediaTransformOutput {
        }
 
        /**
-        * @return File file
+        * @return File
         */
        public function getFile() {
                return $this->file;
index d879c12..7b3ddb5 100644 (file)
@@ -100,7 +100,7 @@ class PNGHandler extends BitmapHandler {
        /**
         * We do not support making APNG thumbnails, so always false
         * @param File $image
-        * @return bool false
+        * @return bool False
         */
        function canAnimateThumbnail( $image ) {
                return false;
index 30376f1..bccd36c 100644 (file)
@@ -413,7 +413,7 @@ class PNGMetadataExtractor {
         *
         * @param resource $fh The file handle
         * @param int $size Size in bytes.
-        * @throws Exception if too big.
+        * @throws Exception If too big
         * @return string The chunk.
         */
        private static function read( $fh, $size ) {
index e28b38f..74e5e04 100644 (file)
@@ -107,6 +107,7 @@ class SvgHandler extends ImageHandler {
        /**
         * What language to render file in if none selected.
         *
+        * @param File $file
         * @return string Language code.
         */
        public function getDefaultRenderLanguage( File $file ) {
@@ -115,6 +116,8 @@ class SvgHandler extends ImageHandler {
 
        /**
         * We do not support making animated svg thumbnails
+        * @param File $file
+        * @return bool
         */
        function canAnimateThumbnail( $file ) {
                return false;
@@ -185,7 +188,40 @@ class SvgHandler extends ImageHandler {
                }
 
                $srcPath = $image->getLocalRefPath();
-               $status = $this->rasterize( $srcPath, $dstPath, $physicalWidth, $physicalHeight, $lang );
+               if ( $srcPath === false ) { // Failed to get local copy
+                       wfDebugLog( 'thumbnail',
+                               sprintf( 'Thumbnail failed on %s: could not get local copy of "%s"',
+                                       wfHostname(), $image->getName() ) );
+
+                       return new MediaTransformError( 'thumbnail_error',
+                               $params['width'], $params['height'],
+                               wfMessage( 'filemissing' )->text()
+                       );
+               }
+
+               // Make a temp dir with a symlink to the local copy in it.
+               // This plays well with rsvg-convert policy for external entities.
+               // https://git.gnome.org/browse/librsvg/commit/?id=f01aded72c38f0e18bc7ff67dee800e380251c8e
+               $tmpDir = wfTempDir() . '/svg_' . wfRandomString( 24 );
+               $lnPath = "$tmpDir/" . basename( $srcPath );
+               $ok = mkdir( $tmpDir, 0771 ) && symlink( $srcPath, $lnPath );
+               $cleaner = new ScopedCallback( function () use ( $tmpDir, $lnPath ) {
+                       wfSuppressWarnings();
+                       unlink( $lnPath );
+                       rmdir( $tmpDir );
+                       wfRestoreWarnings();
+               } );
+               if ( !$ok ) {
+                       wfDebugLog( 'thumbnail',
+                               sprintf( 'Thumbnail failed on %s: could not link %s to %s',
+                                       wfHostname(), $lnPath, $srcPath ) );
+                       return new MediaTransformError( 'thumbnail_error',
+                               $params['width'], $params['height'],
+                               wfMessage( 'thumbnail-temp-create' )->text()
+                       );
+               }
+
+               $status = $this->rasterize( $lnPath, $dstPath, $physicalWidth, $physicalHeight, $lang );
                if ( $status === true ) {
                        return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
                } else {
@@ -446,7 +482,7 @@ class SvgHandler extends ImageHandler {
        }
 
        /**
-        * @param array $params name=>value pairs of parameters
+        * @param array $params Name=>value pairs of parameters
         * @return string Filename to use
         */
        function makeParamString( $params ) {
diff --git a/includes/media/TransformationalImageHandler.php b/includes/media/TransformationalImageHandler.php
new file mode 100644 (file)
index 0000000..13fb52b
--- /dev/null
@@ -0,0 +1,587 @@
+<?php
+/**
+ * Base class for handlers which require transforming images in a
+ * similar way as BitmapHandler does.
+ *
+ * This was split from BitmapHandler on the basis that some extensions
+ * might want to work in a similar way to BitmapHandler, but for
+ * different formats.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Media
+ */
+
+/**
+ * Handler for images that need to be transformed
+ *
+ * @since 1.24
+ * @ingroup Media
+ */
+abstract class TransformationalImageHandler extends ImageHandler {
+       /**
+        * @param File $image
+        * @param array $params Transform parameters. Entries with the keys 'width'
+        * and 'height' are the respective screen width and height, while the keys
+        * 'physicalWidth' and 'physicalHeight' indicate the thumbnail dimensions.
+        * @return bool
+        */
+       function normaliseParams( $image, &$params ) {
+               if ( !parent::normaliseParams( $image, $params ) ) {
+                       return false;
+               }
+
+               # Obtain the source, pre-rotation dimensions
+               $srcWidth = $image->getWidth( $params['page'] );
+               $srcHeight = $image->getHeight( $params['page'] );
+
+               # Don't make an image bigger than the source
+               if ( $params['physicalWidth'] >= $srcWidth ) {
+                       $params['physicalWidth'] = $srcWidth;
+                       $params['physicalHeight'] = $srcHeight;
+
+                       # Skip scaling limit checks if no scaling is required
+                       # due to requested size being bigger than source.
+                       if ( !$image->mustRender() ) {
+                               return true;
+                       }
+               }
+
+               # Check if the file is smaller than the maximum image area for thumbnailing
+               # For historical reasons, hook starts with BitmapHandler
+               $checkImageAreaHookResult = null;
+               wfRunHooks(
+                       'BitmapHandlerCheckImageArea',
+                       array( $image, &$params, &$checkImageAreaHookResult )
+               );
+
+               if ( is_null( $checkImageAreaHookResult ) ) {
+                       global $wgMaxImageArea;
+
+                       if ( $srcWidth * $srcHeight > $wgMaxImageArea
+                               && !( $image->getMimeType() == 'image/jpeg'
+                                       && $this->getScalerType( false, false ) == 'im' )
+                       ) {
+                               # Only ImageMagick can efficiently downsize jpg images without loading
+                               # the entire file in memory
+                               return false;
+                       }
+               } else {
+                       return $checkImageAreaHookResult;
+               }
+
+               return true;
+       }
+
+       /**
+        * Extracts the width/height if the image will be scaled before rotating
+        *
+        * This will match the physical size/aspect ratio of the original image
+        * prior to application of the rotation -- so for a portrait image that's
+        * stored as raw landscape with 90-degress rotation, the resulting size
+        * will be wider than it is tall.
+        *
+        * @param array $params Parameters as returned by normaliseParams
+        * @param int $rotation The rotation angle that will be applied
+        * @return array ($width, $height) array
+        */
+       public function extractPreRotationDimensions( $params, $rotation ) {
+               if ( $rotation == 90 || $rotation == 270 ) {
+                       # We'll resize before rotation, so swap the dimensions again
+                       $width = $params['physicalHeight'];
+                       $height = $params['physicalWidth'];
+               } else {
+                       $width = $params['physicalWidth'];
+                       $height = $params['physicalHeight'];
+               }
+
+               return array( $width, $height );
+       }
+
+       /**
+        * Create a thumbnail.
+        *
+        * This sets up various parameters, and then calls a helper method
+        * based on $this->getScalerType in order to scale the image.
+        *
+        * @param File $image
+        * @param string $dstPath
+        * @param string $dstUrl
+        * @param array $params
+        * @param int $flags
+        * @return MediaTransformError|ThumbnailImage|TransformParameterError
+        */
+       function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
+               if ( !$this->normaliseParams( $image, $params ) ) {
+                       return new TransformParameterError( $params );
+               }
+
+               # Create a parameter array to pass to the scaler
+               $scalerParams = array(
+                       # The size to which the image will be resized
+                       'physicalWidth' => $params['physicalWidth'],
+                       'physicalHeight' => $params['physicalHeight'],
+                       'physicalDimensions' => "{$params['physicalWidth']}x{$params['physicalHeight']}",
+                       # The size of the image on the page
+                       'clientWidth' => $params['width'],
+                       'clientHeight' => $params['height'],
+                       # Comment as will be added to the Exif of the thumbnail
+                       'comment' => isset( $params['descriptionUrl'] )
+                               ? "File source: {$params['descriptionUrl']}"
+                               : '',
+                       # Properties of the original image
+                       'srcWidth' => $image->getWidth(),
+                       'srcHeight' => $image->getHeight(),
+                       'mimeType' => $image->getMimeType(),
+                       'dstPath' => $dstPath,
+                       'dstUrl' => $dstUrl,
+               );
+
+               if ( isset( $params['quality'] ) && $params['quality'] === 'low' ) {
+                       $scalerParams['quality'] = 30;
+               }
+
+               // For subclasses that might be paged.
+               if ( $image->isMultipage() && isset( $params['page'] ) ) {
+                       $scalerParams['page'] = intval( $params['page'] );
+               }
+
+               # Determine scaler type
+               $scaler = $this->getScalerType( $dstPath );
+
+               wfDebug( __METHOD__ . ": creating {$scalerParams['physicalDimensions']} " .
+                       "thumbnail at $dstPath using scaler $scaler\n" );
+
+               if ( !$image->mustRender() &&
+                       $scalerParams['physicalWidth'] == $scalerParams['srcWidth']
+                       && $scalerParams['physicalHeight'] == $scalerParams['srcHeight']
+                       && !isset( $scalerParams['quality'] )
+               ) {
+
+                       # normaliseParams (or the user) wants us to return the unscaled image
+                       wfDebug( __METHOD__ . ": returning unscaled image\n" );
+
+                       return $this->getClientScalingThumbnailImage( $image, $scalerParams );
+               }
+
+               if ( $scaler == 'client' ) {
+                       # Client-side image scaling, use the source URL
+                       # Using the destination URL in a TRANSFORM_LATER request would be incorrect
+                       return $this->getClientScalingThumbnailImage( $image, $scalerParams );
+               }
+
+               if ( $flags & self::TRANSFORM_LATER ) {
+                       wfDebug( __METHOD__ . ": Transforming later per flags.\n" );
+                       $newParams = array(
+                               'width' => $scalerParams['clientWidth'],
+                               'height' => $scalerParams['clientHeight']
+                       );
+                       if ( isset( $params['quality'] ) ) {
+                               $newParams['quality'] = $params['quality'];
+                       }
+                       if ( isset( $params['page'] ) && $params['page'] ) {
+                               $newParams['page'] = $params['page'];
+                       }
+                       return new ThumbnailImage( $image, $dstUrl, false, $newParams );
+               }
+
+               # Try to make a target path for the thumbnail
+               if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) {
+                       wfDebug( __METHOD__ . ": Unable to create thumbnail destination " .
+                               "directory, falling back to client scaling\n" );
+
+                       return $this->getClientScalingThumbnailImage( $image, $scalerParams );
+               }
+
+               # Transform functions and binaries need a FS source file
+               $thumbnailSource = $this->getThumbnailSource( $image, $params );
+
+               $scalerParams['srcPath'] = $thumbnailSource['path'];
+               $scalerParams['srcWidth'] = $thumbnailSource['width'];
+               $scalerParams['srcHeight'] = $thumbnailSource['height'];
+
+               if ( $scalerParams['srcPath'] === false ) { // Failed to get local copy
+                       wfDebugLog( 'thumbnail',
+                               sprintf( 'Thumbnail failed on %s: could not get local copy of "%s"',
+                                       wfHostname(), $image->getName() ) );
+
+                       return new MediaTransformError( 'thumbnail_error',
+                               $scalerParams['clientWidth'], $scalerParams['clientHeight'],
+                               wfMessage( 'filemissing' )->text()
+                       );
+               }
+
+               # Try a hook. Called "Bitmap" for historical reasons.
+               /** @var $mto MediaTransformOutput */
+               $mto = null;
+               wfRunHooks( 'BitmapHandlerTransform', array( $this, $image, &$scalerParams, &$mto ) );
+               if ( !is_null( $mto ) ) {
+                       wfDebug( __METHOD__ . ": Hook to BitmapHandlerTransform created an mto\n" );
+                       $scaler = 'hookaborted';
+               }
+
+               // $scaler will return a MediaTransformError on failure, or false on success.
+               // If the scaler is succesful, it will have created a thumbnail at the destination
+               // path.
+               if ( is_array( $scaler ) && is_callable( $scaler ) ) {
+                       // Allow subclasses to specify their own rendering methods.
+                       $err = call_user_func( $scaler, $image, $scalerParams );
+               } else {
+                       switch ( $scaler ) {
+                               case 'hookaborted':
+                                       # Handled by the hook above
+                                       $err = $mto->isError() ? $mto : false;
+                                       break;
+                               case 'im':
+                                       $err = $this->transformImageMagick( $image, $scalerParams );
+                                       break;
+                               case 'custom':
+                                       $err = $this->transformCustom( $image, $scalerParams );
+                                       break;
+                               case 'imext':
+                                       $err = $this->transformImageMagickExt( $image, $scalerParams );
+                                       break;
+                               case 'gd':
+                               default:
+                                       $err = $this->transformGd( $image, $scalerParams );
+                                       break;
+                       }
+               }
+
+               # Remove the file if a zero-byte thumbnail was created, or if there was an error
+               $removed = $this->removeBadFile( $dstPath, (bool)$err );
+               if ( $err ) {
+                       # transform returned MediaTransforError
+                       return $err;
+               } elseif ( $removed ) {
+                       # Thumbnail was zero-byte and had to be removed
+                       return new MediaTransformError( 'thumbnail_error',
+                               $scalerParams['clientWidth'], $scalerParams['clientHeight'],
+                               wfMessage( 'unknown-error' )->text()
+                       );
+               } elseif ( $mto ) {
+                       return $mto;
+               } else {
+                       $newParams = array(
+                               'width' => $scalerParams['clientWidth'],
+                               'height' => $scalerParams['clientHeight']
+                       );
+                       if ( isset( $params['quality'] ) ) {
+                               $newParams['quality'] = $params['quality'];
+                       }
+                       if ( isset( $params['page'] ) && $params['page'] ) {
+                               $newParams['page'] = $params['page'];
+                       }
+                       return new ThumbnailImage( $image, $dstUrl, $dstPath, $newParams );
+               }
+       }
+
+       /**
+        * Get the source file for the transform
+        *
+        * @param $file File
+        * @param $params Array
+        * @return Array Array with keys  width, height and path.
+        */
+       protected function getThumbnailSource( $file, $params ) {
+               return $file->getThumbnailSource( $params );
+       }
+
+       /**
+        * Returns what sort of scaler type should be used.
+        *
+        * Values can be one of client, im, custom, gd, imext, or an array
+        * of object, method-name to call that specific method.
+        *
+        * If specifying a custom scaler command with array( Obj, method ),
+        * the method in question should take 2 parameters, a File object,
+        * and a $scalerParams array with various options (See doTransform
+        * for what is in $scalerParams). On error it should return a
+        * MediaTransformError object. On success it should return false,
+        * and simply make sure the thumbnail file is located at
+        * $scalerParams['dstPath'].
+        *
+        * If there is a problem with the output path, it returns "client"
+        * to do client side scaling.
+        *
+        * @param string $dstPath
+        * @param bool $checkDstPath Check that $dstPath is valid
+        * @return string|Callable One of client, im, custom, gd, imext, or a Callable array.
+        */
+       abstract protected function getScalerType( $dstPath, $checkDstPath = true );
+
+       /**
+        * Get a ThumbnailImage that respresents an image that will be scaled
+        * client side
+        *
+        * @param File $image File associated with this thumbnail
+        * @param array $scalerParams Array with scaler params
+        * @return ThumbnailImage
+        *
+        * @todo FIXME: No rotation support
+        */
+       protected function getClientScalingThumbnailImage( $image, $scalerParams ) {
+               $params = array(
+                       'width' => $scalerParams['clientWidth'],
+                       'height' => $scalerParams['clientHeight']
+               );
+
+               return new ThumbnailImage( $image, $image->getURL(), null, $params );
+       }
+
+       /**
+        * Transform an image using ImageMagick
+        *
+        * This is a stub method. The real method is in BitmapHander.
+        *
+        * @param File $image File associated with this thumbnail
+        * @param array $params Array with scaler params
+        *
+        * @return MediaTransformError Error object if error occurred, false (=no error) otherwise
+        */
+       protected function transformImageMagick( $image, $params ) {
+               return $this->getMediaTransformError( $params, "Unimplemented" );
+       }
+
+       /**
+        * Transform an image using the Imagick PHP extension
+        *
+        * This is a stub method. The real method is in BitmapHander.
+        *
+        * @param File $image File associated with this thumbnail
+        * @param array $params Array with scaler params
+        *
+        * @return MediaTransformError Error object if error occurred, false (=no error) otherwise
+        */
+       protected function transformImageMagickExt( $image, $params ) {
+               return $this->getMediaTransformError( $params, "Unimplemented" );
+       }
+
+       /**
+        * Transform an image using a custom command
+        *
+        * This is a stub method. The real method is in BitmapHander.
+        *
+        * @param File $image File associated with this thumbnail
+        * @param array $params Array with scaler params
+        *
+        * @return MediaTransformError Error object if error occurred, false (=no error) otherwise
+        */
+       protected function transformCustom( $image, $params ) {
+               return $this->getMediaTransformError( $params, "Unimplemented" );
+       }
+
+       /**
+        * Get a MediaTransformError with error 'thumbnail_error'
+        *
+        * @param array $params Parameter array as passed to the transform* functions
+        * @param string $errMsg Error message
+        * @return MediaTransformError
+        */
+       public function getMediaTransformError( $params, $errMsg ) {
+               return new MediaTransformError( 'thumbnail_error', $params['clientWidth'],
+                       $params['clientHeight'], $errMsg );
+       }
+
+       /**
+        * Transform an image using the built in GD library
+        *
+        * This is a stub method. The real method is in BitmapHander.
+        *
+        * @param File $image File associated with this thumbnail
+        * @param array $params Array with scaler params
+        *
+        * @return MediaTransformError Error object if error occurred, false (=no error) otherwise
+        */
+       protected function transformGd( $image, $params ) {
+               return $this->getMediaTransformError( $params, "Unimplemented" );
+       }
+
+       /**
+        * Escape a string for ImageMagick's property input (e.g. -set -comment)
+        * See InterpretImageProperties() in magick/property.c
+        * @param string $s
+        * @return string
+        */
+       function escapeMagickProperty( $s ) {
+               // Double the backslashes
+               $s = str_replace( '\\', '\\\\', $s );
+               // Double the percents
+               $s = str_replace( '%', '%%', $s );
+               // Escape initial - or @
+               if ( strlen( $s ) > 0 && ( $s[0] === '-' || $s[0] === '@' ) ) {
+                       $s = '\\' . $s;
+               }
+
+               return $s;
+       }
+
+       /**
+        * Escape a string for ImageMagick's input filenames. See ExpandFilenames()
+        * and GetPathComponent() in magick/utility.c.
+        *
+        * This won't work with an initial ~ or @, so input files should be prefixed
+        * with the directory name.
+        *
+        * Glob character unescaping is broken in ImageMagick before 6.6.1-5, but
+        * it's broken in a way that doesn't involve trying to convert every file
+        * in a directory, so we're better off escaping and waiting for the bugfix
+        * to filter down to users.
+        *
+        * @param string $path The file path
+        * @param bool|string $scene The scene specification, or false if there is none
+        * @throws MWException
+        * @return string
+        */
+       function escapeMagickInput( $path, $scene = false ) {
+               # Die on initial metacharacters (caller should prepend path)
+               $firstChar = substr( $path, 0, 1 );
+               if ( $firstChar === '~' || $firstChar === '@' ) {
+                       throw new MWException( __METHOD__ . ': cannot escape this path name' );
+               }
+
+               # Escape glob chars
+               $path = preg_replace( '/[*?\[\]{}]/', '\\\\\0', $path );
+
+               return $this->escapeMagickPath( $path, $scene );
+       }
+
+       /**
+        * Escape a string for ImageMagick's output filename. See
+        * InterpretImageFilename() in magick/image.c.
+        * @param string $path The file path
+        * @param bool|string $scene The scene specification, or false if there is none
+        * @return string
+        */
+       function escapeMagickOutput( $path, $scene = false ) {
+               $path = str_replace( '%', '%%', $path );
+
+               return $this->escapeMagickPath( $path, $scene );
+       }
+
+       /**
+        * Armour a string against ImageMagick's GetPathComponent(). This is a
+        * helper function for escapeMagickInput() and escapeMagickOutput().
+        *
+        * @param string $path The file path
+        * @param bool|string $scene The scene specification, or false if there is none
+        * @throws MWException
+        * @return string
+        */
+       protected function escapeMagickPath( $path, $scene = false ) {
+               # Die on format specifiers (other than drive letters). The regex is
+               # meant to match all the formats you get from "convert -list format"
+               if ( preg_match( '/^([a-zA-Z0-9-]+):/', $path, $m ) ) {
+                       if ( wfIsWindows() && is_dir( $m[0] ) ) {
+                               // OK, it's a drive letter
+                               // ImageMagick has a similar exception, see IsMagickConflict()
+                       } else {
+                               throw new MWException( __METHOD__ . ': unexpected colon character in path name' );
+                       }
+               }
+
+               # If there are square brackets, add a do-nothing scene specification
+               # to force a literal interpretation
+               if ( $scene === false ) {
+                       if ( strpos( $path, '[' ) !== false ) {
+                               $path .= '[0--1]';
+                       }
+               } else {
+                       $path .= "[$scene]";
+               }
+
+               return $path;
+       }
+
+       /**
+        * Retrieve the version of the installed ImageMagick
+        * You can use PHPs version_compare() to use this value
+        * Value is cached for one hour.
+        * @return string Representing the IM version.
+        */
+       protected function getMagickVersion() {
+               global $wgMemc;
+
+               $cache = $wgMemc->get( "imagemagick-version" );
+               if ( !$cache ) {
+                       global $wgImageMagickConvertCommand;
+                       $cmd = wfEscapeShellArg( $wgImageMagickConvertCommand ) . ' -version';
+                       wfDebug( __METHOD__ . ": Running convert -version\n" );
+                       $retval = '';
+                       $return = wfShellExec( $cmd, $retval );
+                       $x = preg_match( '/Version: ImageMagick ([0-9]*\.[0-9]*\.[0-9]*)/', $return, $matches );
+                       if ( $x != 1 ) {
+                               wfDebug( __METHOD__ . ": ImageMagick version check failed\n" );
+
+                               return null;
+                       }
+                       $wgMemc->set( "imagemagick-version", $matches[1], 3600 );
+
+                       return $matches[1];
+               }
+
+               return $cache;
+       }
+
+       /**
+        * Returns whether the current scaler supports rotation.
+        *
+        * @since 1.24 No longer static
+        * @return bool
+        */
+       public function canRotate() {
+               return false;
+       }
+
+       /**
+        * Should we automatically rotate an image based on exif
+        *
+        * @since 1.24 No longer static
+        * @see $wgEnableAutoRotation
+        * @return bool Whether auto rotation is enabled
+        */
+       public function autoRotateEnabled() {
+               return false;
+       }
+
+       /**
+        * Rotate a thumbnail.
+        *
+        * This is a stub. See BitmapHandler::rotate.
+        *
+        * @param File $file
+        * @param array $params Rotate parameters.
+        *   'rotation' clockwise rotation in degrees, allowed are multiples of 90
+        * @since 1.24 Is non-static. From 1.21 it was static
+        * @return bool
+        */
+       public function rotate( $file, $params ) {
+               return new MediaTransformError( 'thumbnail_error', 0, 0,
+                       "$scaler rotation not implemented" );
+       }
+
+       /**
+        * Returns whether the file needs to be rendered. Returns true if the
+        * file requires rotation and we are able to rotate it.
+        *
+        * @param File $file
+        * @return bool
+        */
+       public function mustRender( $file ) {
+               return $this->canRotate() && $this->getRotation( $file ) != 0;
+       }
+}
index b303a01..48b7a47 100644 (file)
@@ -93,7 +93,7 @@ class XCFHandler extends BitmapHandler {
         * @author Hashar
         *
         * @param string $filename Full path to a XCF file
-        * @return bool|array metadata array just like PHP getimagesize()
+        * @return bool|array Metadata Array just like PHP getimagesize()
         */
        static function getXCFMetaData( $filename ) {
                # Decode master structure
@@ -155,7 +155,7 @@ class XCFHandler extends BitmapHandler {
         *
         * @param File $file The image object, or false if there isn't one.
         *   Warning, FSFile::getPropsFromPath might pass an (object)array() instead (!)
-        * @param string $path The filename
+        * @param string $filename The filename
         * @return string
         */
        public function getMetadata( $file, $filename ) {
@@ -165,7 +165,7 @@ class XCFHandler extends BitmapHandler {
                        // Try to be consistent with the names used by PNG files.
                        // Unclear from base media type if it has an alpha layer,
                        // so just assume that it does since it "potentially" could.
-                       switch( $header['base_type'] ) {
+                       switch ( $header['base_type'] ) {
                        case 0:
                                $metadata['colorType'] = 'truecolour-alpha';
                                break;
@@ -209,7 +209,7 @@ class XCFHandler extends BitmapHandler {
         * @param bool $checkDstPath
         * @return string
         */
-       protected static function getScalerType( $dstPath, $checkDstPath = true ) {
+       protected function getScalerType( $dstPath, $checkDstPath = true ) {
                return "im";
        }
 
@@ -218,6 +218,8 @@ class XCFHandler extends BitmapHandler {
         *
         * Image magick doesn't support indexed xcf files as of current
         * writing (as of 6.8.9-3)
+        * @param File $file
+        * @return bool
         */
        public function canRender( $file ) {
                wfSuppressWarnings();
index a74b701..cdbd5ab 100644 (file)
@@ -406,7 +406,7 @@ class XMPReader {
         *
         * @param XMLParser $parser XMLParser reference to the xml parser
         * @param string $data Character data
-        * @throws MWException on invalid data
+        * @throws MWException On invalid data
         */
        function char( $parser, $data ) {
 
@@ -726,7 +726,7 @@ class XMPReader {
         * this should always be <rdf:Bag>
         *
         * @param string $elm Namespace . ' ' . tag
-        * @throws MWException if we have an element that's not <rdf:Bag>
+        * @throws MWException If we have an element that's not <rdf:Bag>
         */
        private function startElementModeBag( $elm ) {
                if ( $elm === self::NS_RDF . ' Bag' ) {
@@ -741,7 +741,7 @@ class XMPReader {
         * this should always be <rdf:Seq>
         *
         * @param string $elm Namespace . ' ' . tag
-        * @throws MWException if we have an element that's not <rdf:Seq>
+        * @throws MWException If we have an element that's not <rdf:Seq>
         */
        private function startElementModeSeq( $elm ) {
                if ( $elm === self::NS_RDF . ' Seq' ) {
@@ -768,7 +768,7 @@ class XMPReader {
         * we don't care about.
         *
         * @param string $elm Namespace . ' ' . tag
-        * @throws MWException if we have an element that's not <rdf:Alt>
+        * @throws MWException If we have an element that's not <rdf:Alt>
         */
        private function startElementModeLang( $elm ) {
                if ( $elm === self::NS_RDF . ' Alt' ) {
@@ -963,7 +963,7 @@ class XMPReader {
         *
         * @param string $elm Namespace . ' ' . tagname
         * @param array $attribs Attributes. (needed for BAGSTRUCTS)
-        * @throws MWException if gets a tag other than <rdf:li>
+        * @throws MWException If gets a tag other than <rdf:li>
         */
        private function startElementModeLi( $elm, $attribs ) {
                if ( ( $elm ) !== self::NS_RDF . ' li' ) {
@@ -1122,7 +1122,6 @@ class XMPReader {
                }
        }
 
-       // @codingStandardsIgnoreStart Long line that cannot be broken
        /**
         * Process attributes.
         * Simple values can be stored as either a tag or attribute
@@ -1130,15 +1129,16 @@ class XMPReader {
         * Often the initial "<rdf:Description>" tag just has all the simple
         * properties as attributes.
         *
+        * @codingStandardsIgnoreStart Long line that cannot be broken
         * @par Example:
         * @code
         * <rdf:Description rdf:about="" xmlns:exif="http://ns.adobe.com/exif/1.0/" exif:DigitalZoomRatio="0/10">
         * @endcode
+        * @codingStandardsIgnoreEnd
         *
         * @param array $attribs Array attribute=>value
         * @throws MWException
         */
-       // @codingStandardsIgnoreEnd
        private function doAttribs( $attribs ) {
                // first check for rdf:parseType attribute, as that can change
                // how the attributes are interperted.
index 3700556..7e47ec1 100644 (file)
@@ -726,7 +726,7 @@ class XMPInfo {
                                'mode' => XMPReader::MODE_SEQ,
                                'validate' => 'validateDate',
                        ),
-                       /* Do not extract dc:format, as we've got better ways to determine mimetype */
+                       /* Do not extract dc:format, as we've got better ways to determine MIME type */
                        'identifier' => array(
                                'map_group' => 'deprecated',
                                'map_name' => 'Identifier',
index 7a4de3b..07b2495 100644 (file)
@@ -1,5 +1,5 @@
-# Mime type info file.
-# the first mime type in each line is the "main" mime type,
+# MIME type info file.
+# the first MIME type in each line is the "main" MIME type,
 # the others are aliases for this type
 # the media type is given in upper case and square brackets,
 # like [BITMAP], and must indicate a media type as defined by
@@ -13,7 +13,7 @@ image/jpeg    [BITMAP]
 image/jp2      [BITMAP]
 image/xbm      [BITMAP]
 image/tiff     [BITMAP]
-image/x-icon image/x-ico       [BITMAP]
+image/x-icon image/x-ico image/vnd.microsoft.icon      [BITMAP]
 image/x-rgb    [BITMAP]
 image/x-portable-pixmap                [BITMAP]
 image/x-portable-graymap image/x-portable-greymap      [BITMAP]
index ae6ca4d..75017db 100644 (file)
@@ -91,6 +91,7 @@ image/png png apng
 image/svg+xml svg
 image/tiff tiff tif
 image/vnd.djvu djvu djv
+image/vnd.microsoft.icon ico
 image/vnd.wap.wbmp wbmp
 image/webp webp
 image/x-cmu-raster ras
index bd4cf05..bd2bc4e 100644 (file)
@@ -81,20 +81,14 @@ function benchmarkTest( &$u, $filename, $desc ) {
        }
 }
 
-function benchTime() {
-       $st = explode( ' ', microtime() );
-
-       return (float)$st[0] + (float)$st[1];
-}
-
 function benchmarkForm( &$u, &$data, $form ) {
-       #$start = benchTime();
+       #$start = microtime( true );
        for ( $i = 0; $i < BENCH_CYCLES; $i++ ) {
-               $start = benchTime();
+               $start = microtime( true );
                $out = $u->$form( $data, UtfNormal::$utfCanonicalDecomp );
-               $deltas[] = ( benchTime() - $start );
+               $deltas[] = ( microtime( true ) - $start );
        }
-       #$delta = (benchTime() - $start) / BENCH_CYCLES;
+       #$delta = (microtime( true ) - $start) / BENCH_CYCLES;
        sort( $deltas );
        $delta = $deltas[0]; # Take shortest time
 
index 14abf93..f133e4d 100644 (file)
@@ -83,20 +83,14 @@ function benchmarkTest( &$u, $filename, $desc ) {
        }
 }
 
-function benchTime() {
-       $st = explode( ' ', microtime() );
-
-       return (float)$st[0] + (float)$st[1];
-}
-
 function benchmarkForm( &$u, &$data, $form ) {
-       #$start = benchTime();
+       #$start = microtime( true );
        for ( $i = 0; $i < BENCH_CYCLES; $i++ ) {
-               $start = benchTime();
+               $start = microtime( true );
                $out = $u->$form( $data, UtfNormal::$utfCanonicalDecomp );
-               $deltas[] = ( benchTime() - $start );
+               $deltas[] = ( microtime( true ) - $start );
        }
-       #$delta = (benchTime() - $start) / BENCH_CYCLES;
+       #$delta = (microtime( true ) - $start) / BENCH_CYCLES;
        sort( $deltas );
        $delta = $deltas[0]; # Take shortest time
 
index dca5f32..1978c3e 100644 (file)
@@ -46,10 +46,10 @@ abstract class BagOStuff {
        protected $lastError = self::ERR_NONE;
 
        /** Possible values for getLastError() */
-       const ERR_NONE        = 0; // no error
+       const ERR_NONE = 0; // no error
        const ERR_NO_RESPONSE = 1; // no response
        const ERR_UNREACHABLE = 2; // can't connect
-       const ERR_UNEXPECTED  = 3; // response gave some error
+       const ERR_UNEXPECTED = 3; // response gave some error
 
        /**
         * @param bool $bool
@@ -251,7 +251,7 @@ abstract class BagOStuff {
         * Batch insertion
         * @param array $data $key => $value assoc array
         * @param int $exptime Either an interval in seconds or a unix timestamp for expiry
-        * @return bool success
+        * @return bool Success
         * @since 1.24
         */
        public function setMulti( array $data, $exptime = 0 ) {
@@ -277,21 +277,6 @@ abstract class BagOStuff {
                return false; // key already set
        }
 
-       /**
-        * @param string $key
-        * @param mixed $value
-        * @param int $exptime
-        * @return bool Success
-        * @deprecated since 1.23
-        */
-       public function replace( $key, $value, $exptime = 0 ) {
-               wfDeprecated( __METHOD__, '1.23' );
-               if ( $this->get( $key ) !== false ) {
-                       return $this->set( $key, $value, $exptime );
-               }
-               return false; // key not already set
-       }
-
        /**
         * Increase stored value of $key by $value while preserving its TTL
         * @param string $key Key to increase
@@ -330,9 +315,9 @@ abstract class BagOStuff {
         * This will create the key with value $init and TTL $ttl if not present
         *
         * @param string $key
-        * @param integer $ttl
-        * @param integer $value
-        * @param integer $init
+        * @param int $ttl
+        * @param int $value
+        * @param int $init
         * @return bool
         * @since 1.24
         */
index 79a6841..53edcdd 100644 (file)
@@ -78,8 +78,8 @@ class MemcachedBagOStuff extends BagOStuff {
        }
 
        /**
-        * @param string $key
         * @param mixed $casToken
+        * @param string $key
         * @param mixed $value
         * @param int $exptime
         * @return bool
@@ -154,7 +154,7 @@ class MemcachedBagOStuff extends BagOStuff {
                if ( $expiry > 2592000 && $expiry < 1000000000 ) {
                        $expiry = 2592000;
                }
-               return $expiry;
+               return (int)$expiry;
        }
 
        /**
index 7990053..41eebfb 100644 (file)
@@ -106,7 +106,7 @@ class MWMemcached {
         * @var array
         * @access public
         */
-       var $stats;
+       public $stats;
 
        // }}}
        // {{{ private
@@ -117,7 +117,7 @@ class MWMemcached {
         * @var array
         * @access private
         */
-       var $_cache_sock;
+       public $_cache_sock;
 
        /**
         * Current debug status; 0 - none to 9 - profiling
@@ -125,7 +125,7 @@ class MWMemcached {
         * @var bool
         * @access private
         */
-       var $_debug;
+       public $_debug;
 
        /**
         * Dead hosts, assoc array, 'host'=>'unixtime when ok to check again'
@@ -133,7 +133,7 @@ class MWMemcached {
         * @var array
         * @access private
         */
-       var $_host_dead;
+       public $_host_dead;
 
        /**
         * Is compression available?
@@ -141,7 +141,7 @@ class MWMemcached {
         * @var bool
         * @access private
         */
-       var $_have_zlib;
+       public $_have_zlib;
 
        /**
         * Do we want to use compression?
@@ -149,7 +149,7 @@ class MWMemcached {
         * @var bool
         * @access private
         */
-       var $_compress_enable;
+       public $_compress_enable;
 
        /**
         * At how many bytes should we compress?
@@ -157,7 +157,7 @@ class MWMemcached {
         * @var int
         * @access private
         */
-       var $_compress_threshold;
+       public $_compress_threshold;
 
        /**
         * Are we using persistent links?
@@ -165,7 +165,7 @@ class MWMemcached {
         * @var bool
         * @access private
         */
-       var $_persistent;
+       public $_persistent;
 
        /**
         * If only using one server; contains ip:port to connect to
@@ -173,7 +173,7 @@ class MWMemcached {
         * @var string
         * @access private
         */
-       var $_single_sock;
+       public $_single_sock;
 
        /**
         * Array containing ip:port or array(ip:port, weight)
@@ -181,7 +181,7 @@ class MWMemcached {
         * @var array
         * @access private
         */
-       var $_servers;
+       public $_servers;
 
        /**
         * Our bit buckets
@@ -189,7 +189,7 @@ class MWMemcached {
         * @var array
         * @access private
         */
-       var $_buckets;
+       public $_buckets;
 
        /**
         * Total # of bit buckets we have
@@ -197,7 +197,7 @@ class MWMemcached {
         * @var int
         * @access private
         */
-       var $_bucketcount;
+       public $_bucketcount;
 
        /**
         * # of total servers we have
@@ -205,7 +205,7 @@ class MWMemcached {
         * @var int
         * @access private
         */
-       var $_active;
+       public $_active;
 
        /**
         * Stream timeout in seconds. Applies for example to fread()
@@ -213,7 +213,7 @@ class MWMemcached {
         * @var int
         * @access private
         */
-       var $_timeout_seconds;
+       public $_timeout_seconds;
 
        /**
         * Stream timeout in microseconds
@@ -221,17 +221,17 @@ class MWMemcached {
         * @var int
         * @access private
         */
-       var $_timeout_microseconds;
+       public $_timeout_microseconds;
 
        /**
         * Connect timeout in seconds
         */
-       var $_connect_timeout;
+       public $_connect_timeout;
 
        /**
         * Number of connection attempts for each server
         */
-       var $_connect_attempts;
+       public $_connect_attempts;
 
        // }}}
        // }}}
index f7dfe46..c853bcf 100644 (file)
@@ -247,6 +247,7 @@ class MemcachedPeclBagOStuff extends MemcachedBagOStuff {
                $callback = array( $this, 'encodeKey' );
                $result = $this->client->getMulti( array_map( $callback, $keys ) );
                wfProfileOut( __METHOD__ );
+               $result = $result ?: array(); // must be an array
                return $this->checkResult( false, $result );
        }
 
@@ -269,10 +270,4 @@ class MemcachedPeclBagOStuff extends MemcachedBagOStuff {
                wfProfileOut( __METHOD__ );
                return $this->checkResult( false, $result );
        }
-
-
-       /* NOTE: there is no cas() method here because it is currently not supported
-        * by the BagOStuff interface and other BagOStuff subclasses, such as
-        * SqlBagOStuff.
-        */
 }
index 497f75d..6a69137 100644 (file)
@@ -115,16 +115,6 @@ class MultiWriteBagOStuff extends BagOStuff {
                return $this->doWrite( 'add', $key, $value, $exptime );
        }
 
-       /**
-        * @param string $key
-        * @param mixed $value
-        * @param int $exptime
-        * @return bool
-        */
-       public function replace( $key, $value, $exptime = 0 ) {
-               return $this->doWrite( 'replace', $key, $value, $exptime );
-       }
-
        /**
         * @param string $key
         * @param int $value
index 0009999..633b34a 100644 (file)
@@ -119,11 +119,15 @@ class ObjectCache {
        /**
         * Factory function referenced from DefaultSettings.php for CACHE_ACCEL.
         *
+        * This will look for any APC style server-local cache.
+        * A fallback cache can be specified if none is found.
+        *
         * @param array $params
+        * @param int|string $fallback Fallback cache, e.g. (CACHE_NONE, "hash") (since 1.24)
         * @throws MWException
         * @return BagOStuff
         */
-       static function newAccelerator( $params ) {
+       static function newAccelerator( $params, $fallback = null ) {
                if ( function_exists( 'apc_fetch' ) ) {
                        $id = 'apc';
                } elseif ( function_exists( 'xcache_get' ) && wfIniGetBool( 'xcache.var_size' ) ) {
@@ -131,6 +135,9 @@ class ObjectCache {
                } elseif ( function_exists( 'wincache_ucache_get' ) ) {
                        $id = 'wincache';
                } else {
+                       if ( $fallback ) {
+                               return self::newFromId( $fallback );
+                       }
                        throw new MWException( "CACHE_ACCEL requested but no suitable object " .
                                "cache is present. You may want to install APC." );
                }
index c7d2f13..ae8cc5b 100644 (file)
@@ -342,6 +342,7 @@ class RedisBagOStuff extends BagOStuff {
 
        /**
         * Get a Redis object with a connection suitable for fetching the specified key
+        * @param string $key
         * @return array (server, RedisConnRef) or (false, false)
         */
        protected function getConnection( $key ) {
index 483f8b9..5872079 100644 (file)
@@ -243,7 +243,15 @@ class SqlBagOStuff extends BagOStuff {
                                        $res = $db->select( $tableName,
                                                array( 'keyname', 'value', 'exptime' ),
                                                array( 'keyname' => $tableKeys ),
-                                               __METHOD__ );
+                                               __METHOD__,
+                                               // Approximate write-on-the-fly BagOStuff API via blocking.
+                                               // This approximation fails if a ROLLBACK happens (which is rare).
+                                               // We do not want to flush the TRX as that can break callers.
+                                               $db->trxLevel() ? array( 'LOCK IN SHARE MODE' ) : array()
+                                       );
+                                       if ( $res === false ) {
+                                               continue;
+                                       }
                                        foreach ( $res as $row ) {
                                                $row->serverIndex = $serverIndex;
                                                $row->tableName = $tableName;
@@ -263,13 +271,11 @@ class SqlBagOStuff extends BagOStuff {
                                        $db = $this->getDB( $row->serverIndex );
                                        if ( $this->isExpired( $db, $row->exptime ) ) { // MISS
                                                $this->debug( "get: key has expired, deleting" );
-                                               $db->commit( __METHOD__, 'flush' );
                                                # Put the expiry time in the WHERE condition to avoid deleting a
                                                # newly-inserted value
                                                $db->delete( $row->tableName,
                                                        array( 'keyname' => $key, 'exptime' => $row->exptime ),
                                                        __METHOD__ );
-                                               $db->commit( __METHOD__, 'flush' );
                                        } else { // HIT
                                                $values[$key] = $this->unserialize( $db->decodeBlob( $row->value ) );
                                        }
@@ -332,14 +338,12 @@ class SqlBagOStuff extends BagOStuff {
                                }
 
                                try {
-                                       $db->commit( __METHOD__, 'flush' );
                                        $db->replace(
                                                $tableName,
                                                array( 'keyname' ),
                                                $rows,
                                                __METHOD__
                                        );
-                                       $db->commit( __METHOD__, 'flush' );
                                } catch ( DBError $e ) {
                                        $this->handleWriteError( $e, $serverIndex );
                                        $result = false;
@@ -379,7 +383,6 @@ class SqlBagOStuff extends BagOStuff {
 
                                $encExpiry = $db->timestamp( $exptime );
                        }
-                       $db->commit( __METHOD__, 'flush' );
                        // (bug 24425) use a replace if the db supports it instead of
                        // delete/insert to avoid clashes with conflicting keynames
                        $db->replace(
@@ -390,7 +393,6 @@ class SqlBagOStuff extends BagOStuff {
                                        'value' => $db->encodeBlob( $this->serialize( $value ) ),
                                        'exptime' => $encExpiry
                                ), __METHOD__ );
-                       $db->commit( __METHOD__, 'flush' );
                } catch ( DBError $e ) {
                        $this->handleWriteError( $e, $serverIndex );
                        return false;
@@ -424,7 +426,6 @@ class SqlBagOStuff extends BagOStuff {
                                }
                                $encExpiry = $db->timestamp( $exptime );
                        }
-                       $db->commit( __METHOD__, 'flush' );
                        // (bug 24425) use a replace if the db supports it instead of
                        // delete/insert to avoid clashes with conflicting keynames
                        $db->update(
@@ -440,7 +441,6 @@ class SqlBagOStuff extends BagOStuff {
                                ),
                                __METHOD__
                        );
-                       $db->commit( __METHOD__, 'flush' );
                } catch ( DBQueryError $e ) {
                        $this->handleWriteError( $e, $serverIndex );
 
@@ -459,12 +459,10 @@ class SqlBagOStuff extends BagOStuff {
                list( $serverIndex, $tableName ) = $this->getTableByKey( $key );
                try {
                        $db = $this->getDB( $serverIndex );
-                       $db->commit( __METHOD__, 'flush' );
                        $db->delete(
                                $tableName,
                                array( 'keyname' => $key ),
                                __METHOD__ );
-                       $db->commit( __METHOD__, 'flush' );
                } catch ( DBError $e ) {
                        $this->handleWriteError( $e, $serverIndex );
                        return false;
@@ -483,7 +481,6 @@ class SqlBagOStuff extends BagOStuff {
                try {
                        $db = $this->getDB( $serverIndex );
                        $step = intval( $step );
-                       $db->commit( __METHOD__, 'flush' );
                        $row = $db->selectRow(
                                $tableName,
                                array( 'value', 'exptime' ),
@@ -492,14 +489,12 @@ class SqlBagOStuff extends BagOStuff {
                                array( 'FOR UPDATE' ) );
                        if ( $row === false ) {
                                // Missing
-                               $db->commit( __METHOD__, 'flush' );
 
                                return null;
                        }
                        $db->delete( $tableName, array( 'keyname' => $key ), __METHOD__ );
                        if ( $this->isExpired( $db, $row->exptime ) ) {
                                // Expired, do not reinsert
-                               $db->commit( __METHOD__, 'flush' );
 
                                return null;
                        }
@@ -517,7 +512,6 @@ class SqlBagOStuff extends BagOStuff {
                                // Race condition. See bug 28611
                                $newValue = null;
                        }
-                       $db->commit( __METHOD__, 'flush' );
                } catch ( DBError $e ) {
                        $this->handleWriteError( $e, $serverIndex );
                        return null;
@@ -527,6 +521,7 @@ class SqlBagOStuff extends BagOStuff {
        }
 
        /**
+        * @param DatabaseBase $db
         * @param string $exptime
         * @return bool
         */
@@ -593,7 +588,7 @@ class SqlBagOStuff extends BagOStuff {
                                                        $conds,
                                                        __METHOD__,
                                                        array( 'LIMIT' => 100, 'ORDER BY' => 'exptime' ) );
-                                               if ( !$rows->numRows() ) {
+                                               if ( $rows === false || !$rows->numRows() ) {
                                                        break;
                                                }
                                                $keys = array();
@@ -608,7 +603,6 @@ class SqlBagOStuff extends BagOStuff {
                                                        $maxExpTime = $row->exptime;
                                                }
 
-                                               $db->commit( __METHOD__, 'flush' );
                                                $db->delete(
                                                        $this->getTableNameByShard( $i ),
                                                        array(
@@ -617,7 +611,6 @@ class SqlBagOStuff extends BagOStuff {
                                                                'keyname' => $keys
                                                        ),
                                                        __METHOD__ );
-                                               $db->commit( __METHOD__, 'flush' );
 
                                                if ( $progressCallback ) {
                                                        if ( intval( $totalSeconds ) === 0 ) {
@@ -650,9 +643,7 @@ class SqlBagOStuff extends BagOStuff {
                        try {
                                $db = $this->getDB( $serverIndex );
                                for ( $i = 0; $i < $this->shards; $i++ ) {
-                                       $db->commit( __METHOD__, 'flush' );
                                        $db->delete( $this->getTableNameByShard( $i ), '*', __METHOD__ );
-                                       $db->commit( __METHOD__, 'flush' );
                                }
                        } catch ( DBError $e ) {
                                $this->handleWriteError( $e, $serverIndex );
@@ -780,12 +771,10 @@ class SqlBagOStuff extends BagOStuff {
                        }
 
                        for ( $i = 0; $i < $this->shards; $i++ ) {
-                               $db->commit( __METHOD__, 'flush' );
                                $db->query(
                                        'CREATE TABLE ' . $db->tableName( $this->getTableNameByShard( $i ) ) .
                                        ' LIKE ' . $db->tableName( 'objectcache' ),
                                        __METHOD__ );
-                               $db->commit( __METHOD__, 'flush' );
                        }
                }
        }
index a6c7d9c..78a512c 100644 (file)
@@ -52,7 +52,7 @@ class WinCacheBagOStuff extends BagOStuff {
         * Store a value in the WinCache object cache
         *
         * @param string $key Cache key
-        * @param mixed $valueObject to store
+        * @param mixed $value Value to store
         * @param int $expire Expiration time
         * @return bool
         */
index 0e989d3..9845316 100644 (file)
@@ -53,25 +53,25 @@ class Article implements Page {
         * @var Content Content of the revision we are working on
         * @since 1.21
         */
-       protected $mContentObject;
+       public $mContentObject;
 
        /** @var bool Is the content ($mContent) already loaded? */
-       protected $mContentLoaded = false;
+       public $mContentLoaded = false;
 
        /** @var int|null The oldid of the article that is to be shown, 0 for the current revision */
-       protected $mOldId;
+       public $mOldId;
 
        /** @var Title Title from which we were redirected here */
-       protected $mRedirectedFrom = null;
+       public $mRedirectedFrom = null;
 
        /** @var string|bool URL to redirect to or false if none */
-       protected $mRedirectUrl = false;
+       public $mRedirectUrl = false;
 
        /** @var int Revision ID of revision we are working on */
-       protected $mRevIdFetched = 0;
+       public $mRevIdFetched = 0;
 
        /** @var Revision Revision we are working on */
-       protected $mRevision = null;
+       public $mRevision = null;
 
        /** @var ParserOutput */
        public $mParserOutput;
@@ -480,7 +480,7 @@ class Article implements Page {
         * page of the given title.
         */
        public function view() {
-               global $wgUseFileCache, $wgUseETag, $wgDebugToolbar;
+               global $wgUseFileCache, $wgUseETag, $wgDebugToolbar, $wgMaxRedirects;
 
                wfProfileIn( __METHOD__ );
 
@@ -542,8 +542,31 @@ class Article implements Page {
                                $outputPage->setETag( $parserCache->getETag( $this, $parserOptions ) );
                        }
 
+                       # Use the greatest of the page's timestamp or the timestamp of any
+                       # redirect in the chain (bug 67849)
+                       $timestamp = $this->mPage->getTouched();
+                       if ( isset( $this->mRedirectedFrom ) ) {
+                               $timestamp = max( $timestamp, $this->mRedirectedFrom->getTouched() );
+
+                               # If there can be more than one redirect in the chain, we have
+                               # to go through the whole chain too in case an intermediate
+                               # redirect was changed.
+                               if ( $wgMaxRedirects > 1 ) {
+                                       $titles = Revision::newFromTitle( $this->mRedirectedFrom )
+                                               ->getContent( Revision::FOR_THIS_USER, $user )
+                                               ->getRedirectChain();
+                                       $thisTitle = $this->getTitle();
+                                       foreach ( $titles as $title ) {
+                                               if ( Title::compare( $title, $thisTitle ) === 0 ) {
+                                                       break;
+                                               }
+                                               $timestamp = max( $timestamp, $title->getTouched() );
+                                       }
+                               }
+                       }
+
                        # Is it client cached?
-                       if ( $outputPage->checkLastModified( $this->mPage->getTouched() ) ) {
+                       if ( $outputPage->checkLastModified( $timestamp ) ) {
                                wfDebug( __METHOD__ . ": done 304\n" );
                                wfProfileOut( __METHOD__ );
 
@@ -680,7 +703,9 @@ class Article implements Page {
                                        $this->mParserOutput = $poolArticleView->getParserOutput();
                                        $outputPage->addParserOutput( $this->mParserOutput );
                                        if ( $content->getRedirectTarget() ) {
-                                               $outputPage->addSubtitle( wfMessage( 'redirectpagesub' )->parse() );
+                                               $outputPage->addSubtitle(
+                                                       "<span id=\"redirectsub\">" . wfMessage( 'redirectpagesub' )->parse() . "</span>"
+                                               );
                                        }
 
                                        # Don't cache a dirty ParserOutput object
@@ -835,7 +860,7 @@ class Article implements Page {
         * @param string $action The action= GET parameter
         * @param ParserOutput|null $pOutput
         * @return array The policy that should be set
-        * @todo: actions other than 'view'
+        * @todo actions other than 'view'
         */
        public function getRobotPolicy( $action, $pOutput = null ) {
                global $wgArticleRobotPolicies, $wgNamespaceRobotPolicies, $wgDefaultRobotPolicy;
@@ -950,7 +975,14 @@ class Article implements Page {
                global $wgRedirectSources;
                $outputPage = $this->getContext()->getOutput();
 
-               $rdfrom = $this->getContext()->getRequest()->getVal( 'rdfrom' );
+               $request = $this->getContext()->getRequest();
+               $rdfrom = $request->getVal( 'rdfrom' );
+
+               // Construct a URL for the current page view, but with the target title
+               $query = $request->getValues();
+               unset( $query['rdfrom'] );
+               unset( $query['title'] );
+               $redirectTargetUrl = $this->getTitle()->getLinkURL( $query );
 
                if ( isset( $this->mRedirectedFrom ) ) {
                        // This is an internally redirected page view.
@@ -965,11 +997,12 @@ class Article implements Page {
 
                                $outputPage->addSubtitle( wfMessage( 'redirectedfrom' )->rawParams( $redir ) );
 
-                               // Set the fragment if one was specified in the redirect
-                               if ( $this->getTitle()->hasFragment() ) {
-                                       $outputPage->addJsConfigVars( 'wgRedirectToFragment', $this->getTitle()->getFragmentForURL() );
-                                       $outputPage->addModules( 'mediawiki.action.view.redirectToFragment' );
-                               }
+                               // Add the script to update the displayed URL and
+                               // set the fragment if one was specified in the redirect
+                               $outputPage->addJsConfigVars( array(
+                                       'wgInternalRedirectTargetUrl' => $redirectTargetUrl,
+                               ) );
+                               $outputPage->addModules( 'mediawiki.action.view.redirect' );
 
                                // Add a <link rel="canonical"> tag
                                $outputPage->setCanonicalUrl( $this->getTitle()->getLocalURL() );
@@ -986,6 +1019,12 @@ class Article implements Page {
                                $redir = Linker::makeExternalLink( $rdfrom, $rdfrom );
                                $outputPage->addSubtitle( wfMessage( 'redirectedfrom' )->rawParams( $redir ) );
 
+                               // Add the script to update the displayed URL
+                               $outputPage->addJsConfigVars( array(
+                                       'wgInternalRedirectTargetUrl' => $redirectTargetUrl,
+                               ) );
+                               $outputPage->addModules( 'mediawiki.action.view.redirect' );
+
                                return true;
                        }
                }
@@ -1151,15 +1190,18 @@ class Article implements Page {
         */
        public function showMissingArticle() {
                global $wgSend404Code;
+
                $outputPage = $this->getContext()->getOutput();
                // Whether the page is a root user page of an existing user (but not a subpage)
                $validUserPage = false;
 
+               $title = $this->getTitle();
+
                # Show info in user (talk) namespace. Does the user exist? Is he blocked?
-               if ( $this->getTitle()->getNamespace() == NS_USER
-                       || $this->getTitle()->getNamespace() == NS_USER_TALK
+               if ( $title->getNamespace() == NS_USER
+                       || $title->getNamespace() == NS_USER_TALK
                ) {
-                       $parts = explode( '/', $this->getTitle()->getText() );
+                       $parts = explode( '/', $title->getText() );
                        $rootPart = $parts[0];
                        $user = User::newFromName( $rootPart, false /* allow IP users*/ );
                        $ip = User::isIP( $rootPart );
@@ -1183,9 +1225,9 @@ class Article implements Page {
                                                )
                                        )
                                );
-                               $validUserPage = !$this->getTitle()->isSubpage();
+                               $validUserPage = !$title->isSubpage();
                        } else {
-                               $validUserPage = !$this->getTitle()->isSubpage();
+                               $validUserPage = !$title->isSubpage();
                        }
                }
 
@@ -1197,12 +1239,16 @@ class Article implements Page {
                wfRunHooks( 'Article::MissingArticleConditions', array( &$conds, $logTypes ) );
 
                # Show delete and move logs
-               LogEventsList::showLogExtract( $outputPage, $logTypes, $this->getTitle(), '',
-                       array( 'lim' => 10,
-                               'conds' => $conds,
-                               'showIfEmpty' => false,
-                               'msgKey' => array( 'moveddeleted-notice' ) )
-               );
+               $member = $title->getNamespace() . ':' . $title->getDBkey();
+               // @todo: move optimization to showLogExtract()?
+               if ( BloomCache::get( 'main' )->check( wfWikiId(), 'TitleHasLogs', $member ) ) {
+                       LogEventsList::showLogExtract( $outputPage, $logTypes, $title, '',
+                               array( 'lim' => 10,
+                                       'conds' => $conds,
+                                       'showIfEmpty' => false,
+                                       'msgKey' => array( 'moveddeleted-notice' ) )
+                       );
+               }
 
                if ( !$this->mPage->hasViewableContent() && $wgSend404Code && !$validUserPage ) {
                        // If there's no backing content, send a 404 Not Found
@@ -1217,7 +1263,7 @@ class Article implements Page {
 
                $hookResult = wfRunHooks( 'BeforeDisplayNoArticleText', array( $this ) );
 
-               if ( ! $hookResult ) {
+               if ( !$hookResult ) {
                        return;
                }
 
@@ -1225,11 +1271,11 @@ class Article implements Page {
                $oldid = $this->getOldID();
                if ( $oldid ) {
                        $text = wfMessage( 'missing-revision', $oldid )->plain();
-               } elseif ( $this->getTitle()->getNamespace() === NS_MEDIAWIKI ) {
+               } elseif ( $title->getNamespace() === NS_MEDIAWIKI ) {
                        // Use the default message text
-                       $text = $this->getTitle()->getDefaultMessageText();
-               } elseif ( $this->getTitle()->quickUserCan( 'create', $this->getContext()->getUser() )
-                       && $this->getTitle()->quickUserCan( 'edit', $this->getContext()->getUser() )
+                       $text = $title->getDefaultMessageText();
+               } elseif ( $title->quickUserCan( 'create', $this->getContext()->getUser() )
+                       && $title->quickUserCan( 'edit', $this->getContext()->getUser() )
                ) {
                        $message = $this->getContext()->getUser()->isLoggedIn() ? 'noarticletext' : 'noarticletextanon';
                        $text = wfMessage( $message )->plain();
@@ -1245,7 +1291,7 @@ class Article implements Page {
         * If the revision requested for view is deleted, check permissions.
         * Send either an error message or a warning header to the output.
         *
-        * @return bool true if the view is allowed, false if not.
+        * @return bool True if the view is allowed, false if not.
         */
        public function showDeletedRevisionHeader() {
                if ( !$this->mRevision->isDeleted( Revision::DELETED_TEXT ) ) {
@@ -1416,14 +1462,15 @@ class Article implements Page {
         * @param Title|array $target Destination(s) to redirect
         * @param bool $appendSubtitle [optional]
         * @param bool $forceKnown Should the image be shown as a bluelink regardless of existence?
-        * @return string Containing HMTL with redirect link
+        * @return string Containing HTML with redirect link
         */
        public function viewRedirect( $target, $appendSubtitle = true, $forceKnown = false ) {
                $lang = $this->getTitle()->getPageLanguage();
+               $out = $this->getContext()->getOutput();
                if ( $appendSubtitle ) {
-                       $out = $this->getContext()->getOutput();
                        $out->addSubtitle( wfMessage( 'redirectpagesub' )->parse() );
                }
+               $out->addModuleStyles( 'mediawiki.action.view.redirectPage' );
                return static::getRedirectHeaderHtml( $lang, $target, $forceKnown );
        }
 
@@ -1437,58 +1484,33 @@ class Article implements Page {
         * @param Language $lang
         * @param Title|array $target Destination(s) to redirect
         * @param bool $forceKnown Should the image be shown as a bluelink regardless of existence?
-        * @return string Containing HMTL with redirect link
+        * @return string Containing HTML with redirect link
         */
        public static function getRedirectHeaderHtml( Language $lang, $target, $forceKnown = false ) {
-               global $wgStylePath;
-
                if ( !is_array( $target ) ) {
                        $target = array( $target );
                }
 
-               $imageDir = $lang->getDir();
-
-               // the loop prepends the arrow image before the link, so the first case needs to be outside
-
-               /** @var $title Title */
-               $title = array_shift( $target );
-
-               if ( $forceKnown ) {
-                       $link = Linker::linkKnown( $title, htmlspecialchars( $title->getFullText() ) );
-               } else {
-                       $link = Linker::link( $title, htmlspecialchars( $title->getFullText() ) );
+               $html = '<ul class="redirectText">';
+               /** @var Title $title */
+               foreach ( $target as $title ) {
+                       $html .= '<li>' . Linker::link(
+                               $title,
+                               htmlspecialchars( $title->getFullText() ),
+                               array(),
+                               // Automatically append redirect=no to each link, since most of them are
+                               // redirect pages themselves.
+                               array( 'redirect' => 'no' ),
+                               ( $forceKnown ? array( 'known', 'noclasses' ) : array() )
+                       ) . '</li>';
                }
 
-               $nextRedirect = $wgStylePath . '/common/images/nextredirect' . $imageDir . '.png';
-               $alt = $lang->isRTL() ? '←' : '→';
-
-               // Automatically append redirect=no to each link, since most of them are
-               // redirect pages themselves.
-               /** @var Title $rt */
-               foreach ( $target as $rt ) {
-                       $link .= Html::element( 'img', array( 'src' => $nextRedirect, 'alt' => $alt ) );
-                       if ( $forceKnown ) {
-                               $link .= Linker::linkKnown(
-                                       $rt,
-                                       htmlspecialchars( $rt->getFullText(),
-                                       array(),
-                                       array( 'redirect' => 'no' )
-                               )
-                               );
-                       } else {
-                               $link .= Linker::link(
-                                       $rt,
-                                       htmlspecialchars( $rt->getFullText() ),
-                                       array(),
-                                       array( 'redirect' => 'no' )
-                               );
-                       }
-               }
+               $redirectToText = wfMessage( 'redirectto' )->inLanguage( $lang )->text();
 
-               $imageUrl = $wgStylePath . '/common/images/redirect' . $imageDir . '.png';
                return '<div class="redirectMsg">' .
-                       Html::element( 'img', array( 'src' => $imageUrl, 'alt' => '#REDIRECT' ) ) .
-                       '<span class="redirectText">' . $link . '</span></div>';
+                       '<p>' . $redirectToText . '</p>' .
+                       $html .
+                       '</div>';
        }
 
        /**
@@ -1526,9 +1548,9 @@ class Article implements Page {
                $user = $this->getContext()->getUser();
 
                # Check permissions
-               $permission_errors = $title->getUserPermissionsErrors( 'delete', $user );
-               if ( count( $permission_errors ) ) {
-                       throw new PermissionsError( 'delete', $permission_errors );
+               $permissionErrors = $title->getUserPermissionsErrors( 'delete', $user );
+               if ( count( $permissionErrors ) ) {
+                       throw new PermissionsError( 'delete', $permissionErrors );
                }
 
                # Read-only check...
@@ -1599,7 +1621,20 @@ class Article implements Page {
 
                // If the page has a history, insert a warning
                if ( $hasHistory ) {
-                       $revisions = $this->mTitle->estimateRevisionCount();
+                       $title = $this->getTitle();
+
+                       // The following can use the real revision count as this is only being shown for users that can delete
+                       // this page.
+                       // This, as a side-effect, also makes sure that the following query isn't being run for pages with a
+                       // larger history, unless the user has the 'bigdelete' right (and is about to delete this page).
+                       $dbr = wfGetDB( DB_SLAVE );
+                       $revisions = $edits = (int)$dbr->selectField(
+                               'revision',
+                               'COUNT(rev_page)',
+                               array( 'rev_page' => $title->getArticleID() ),
+                               __METHOD__
+                       );
+
                        // @todo FIXME: i18n issue/patchwork message
                        $this->getContext()->getOutput()->addHTML( '<strong class="mw-delete-warning-revisions">' .
                                wfMessage( 'historywarning' )->numParams( $revisions )->parse() .
@@ -1610,7 +1645,7 @@ class Article implements Page {
                                '</strong>'
                        );
 
-                       if ( $this->mTitle->isBigDeletion() ) {
+                       if ( $title->isBigDeletion() ) {
                                global $wgDeleteRevisionsLimit;
                                $this->getContext()->getOutput()->wrapWikiMsg( "<div class='error'>\n$1\n</div>\n",
                                        array(
@@ -1632,11 +1667,12 @@ class Article implements Page {
        public function confirmDelete( $reason ) {
                wfDebug( "Article::confirmDelete\n" );
 
+               $title = $this->getTitle();
                $outputPage = $this->getContext()->getOutput();
-               $outputPage->setPageTitle( wfMessage( 'delete-confirm', $this->getTitle()->getPrefixedText() ) );
-               $outputPage->addBacklinkSubtitle( $this->getTitle() );
+               $outputPage->setPageTitle( wfMessage( 'delete-confirm', $title->getPrefixedText() ) );
+               $outputPage->addBacklinkSubtitle( $title );
                $outputPage->setRobotPolicy( 'noindex,nofollow' );
-               $backlinkCache = $this->getTitle()->getBacklinkCache();
+               $backlinkCache = $title->getBacklinkCache();
                if ( $backlinkCache->hasLinks( 'pagelinks' ) || $backlinkCache->hasLinks( 'templatelinks' ) ) {
                        $outputPage->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n",
                                'deleting-backlinks-warning' );
@@ -1658,10 +1694,10 @@ class Article implements Page {
                } else {
                        $suppress = '';
                }
-               $checkWatch = $user->getBoolOption( 'watchdeletion' ) || $user->isWatched( $this->getTitle() );
+               $checkWatch = $user->getBoolOption( 'watchdeletion' ) || $user->isWatched( $title );
 
                $form = Xml::openElement( 'form', array( 'method' => 'post',
-                       'action' => $this->getTitle()->getLocalURL( 'action=delete' ), 'id' => 'deleteconfirm' ) ) .
+                       'action' => $title->getLocalURL( 'action=delete' ), 'id' => 'deleteconfirm' ) ) .
                        Xml::openElement( 'fieldset', array( 'id' => 'mw-delete-table' ) ) .
                        Xml::tags( 'legend', null, wfMessage( 'delete-legend' )->escaped() ) .
                        Xml::openElement( 'table', array( 'id' => 'mw-deleteconfirm-table' ) ) .
@@ -1720,14 +1756,14 @@ class Article implements Page {
                        Xml::closeElement( 'fieldset' ) .
                        Html::hidden(
                                'wpEditToken',
-                               $user->getEditToken( array( 'delete', $this->getTitle()->getPrefixedText() ) )
+                               $user->getEditToken( array( 'delete', $title->getPrefixedText() ) )
                        ) .
                        Xml::closeElement( 'form' );
 
                        if ( $user->isAllowed( 'editinterface' ) ) {
-                               $title = Title::makeTitle( NS_MEDIAWIKI, 'Deletereason-dropdown' );
+                               $dropdownTitle = Title::makeTitle( NS_MEDIAWIKI, 'Deletereason-dropdown' );
                                $link = Linker::link(
-                                       $title,
+                                       $dropdownTitle,
                                        wfMessage( 'delete-edit-reasonlist' )->escaped(),
                                        array(),
                                        array( 'action' => 'edit' )
@@ -1739,9 +1775,7 @@ class Article implements Page {
 
                $deleteLogPage = new LogPage( 'delete' );
                $outputPage->addHTML( Xml::element( 'h2', null, $deleteLogPage->getName()->text() ) );
-               LogEventsList::showLogExtract( $outputPage, 'delete',
-                       $this->getTitle()
-               );
+               LogEventsList::showLogExtract( $outputPage, 'delete', $title );
        }
 
        /**
@@ -1795,7 +1829,7 @@ class Article implements Page {
         * output to the client that is necessary for this request.
         * (that is, it has sent a cached version of the page)
         *
-        * @return bool true if cached version send, false otherwise
+        * @return bool True if cached version send, false otherwise
         */
        protected function tryFileCache() {
                static $called = false;
@@ -1871,7 +1905,7 @@ class Article implements Page {
         * Override the ParserOptions used to render the primary article wikitext.
         *
         * @param ParserOptions $options
-        * @throws MWException if the parser options where already initialized.
+        * @throws MWException If the parser options where already initialized.
         */
        public function setParserOptions( ParserOptions $options ) {
                if ( $this->mParserOptions ) {
@@ -1925,6 +1959,7 @@ class Article implements Page {
         * raw WikiPage fields for backwards compatibility.
         *
         * @param string $fname Field name
+        * @return mixed
         */
        public function __get( $fname ) {
                if ( property_exists( $this->mPage, $fname ) ) {
index 89ca241..d06c819 100644 (file)
@@ -267,8 +267,7 @@ class ImagePage extends Article {
                                # @todo FIXME: Why is this using escapeId for a class?!
                                $class = Sanitizer::escapeId( $v['id'] );
                                if ( $type == 'collapsed' ) {
-                                       // Handled by mediawiki.action.view.metadata module
-                                       // and skins/common/shared.css.
+                                       // Handled by mediawiki.action.view.metadata module.
                                        $class .= ' collapsable';
                                }
                                $r .= "<tr class=\"$class\">\n";
@@ -363,7 +362,7 @@ class ImagePage extends Article {
                                                // it can be denoted as the current size being shown.
                                                // Vectorized images are "infinitely" big, so all thumb
                                                // sizes are shown.
-                                               if ( ( ($size[0] <= $width_orig && $size[1] <= $height_orig)
+                                               if ( ( ( $size[0] <= $width_orig && $size[1] <= $height_orig )
                                                                || $this->displayImg->isVectorized() )
                                                        && $size[0] != $width && $size[1] != $height
                                                ) {
@@ -430,6 +429,8 @@ class ImagePage extends Article {
 
                                        if ( $page > 1 ) {
                                                $label = $out->parse( wfMessage( 'imgmultipageprev' )->text(), false );
+                                               // on the client side, this link is generated in ajaxifyPageNavigation()
+                                               // in the mediawiki.page.image.pagination module
                                                $link = Linker::linkKnown(
                                                        $this->getTitle(),
                                                        $label,
@@ -1061,12 +1062,12 @@ EOT
         *  of the dimensions are bigger than the max, or if the
         *  image is vectorized.
         *
-        * @param $maxWidth integer Max width to display at
-        * @param $maxHeight integer Max height to display at
-        * @param $width integer Actual width of the image
-        * @param $height integer Actual height of the image
+        * @param int $maxWidth Max width to display at
+        * @param int $maxHeight Max height to display at
+        * @param int $width Actual width of the image
+        * @param int $height Actual height of the image
         * @throws MWException
-        * @return Array (width, height)
+        * @return array Array (width, height)
         */
        protected function getDisplayWidthHeight( $maxWidth, $maxHeight, $width, $height ) {
                if ( !$maxWidth || !$maxHeight ) {
@@ -1100,9 +1101,9 @@ EOT
         * Get alternative thumbnail sizes.
         *
         * @note This will only list several alternatives if thumbnails are rendered on 404
-        * @param $origWidth Actual width of image
-        * @param $origHeight Actual height of image
-        * @return Array An array of [width, height] pairs.
+        * @param int $origWidth Actual width of image
+        * @param int $origHeight Actual height of image
+        * @return array An array of [width, height] pairs.
         */
        protected function getThumbSizes( $origWidth, $origHeight ) {
                global $wgImageLimits;
@@ -1327,6 +1328,9 @@ class ImageHistoryList extends ContextSource {
                                $url = $lang->userTimeAndDate( $timestamp, $user );
                        }
                        $row .= '<span class="history-deleted">' . $url . '</span>';
+               } elseif ( !$file->exists() ) {
+                       $row .= '<span class="mw-file-missing">'
+                               . $lang->userTimeAndDate( $timestamp, $user ) . '</span>';
                } else {
                        $url = $iscur ? $this->current->getUrl() : $this->current->getArchiveUrl( $img );
                        $row .= Xml::element(
index 34f15c3..bfcd4c3 100644 (file)
@@ -40,12 +40,6 @@ class WikiFilePage extends WikiPage {
                $this->mRepo = null;
        }
 
-       public function getActionOverrides() {
-               $overrides = parent::getActionOverrides();
-               $overrides['revert'] = 'RevertFileAction';
-               return $overrides;
-       }
-
        /**
         * @param File $file
         */
@@ -207,7 +201,7 @@ class WikiFilePage extends WikiPage {
                $title = $this->mTitle;
                $file = $this->mFile;
 
-               if ( ! $file instanceof LocalFile ) {
+               if ( !$file instanceof LocalFile ) {
                        wfDebug( __CLASS__ . '::' . __METHOD__ . " is not supported for this file\n" );
                        return TitleArray::newFromResult( new FakeResultWrapper( array() ) );
                }
index 7c412ea..9ade16e 100644 (file)
@@ -530,7 +530,7 @@ class WikiPage implements Page, IDBAccessObject {
 
        /**
         * Loads page_touched and returns a value indicating if it should be used
-        * @return bool true if not a redirect
+        * @return bool True if not a redirect
         */
        public function checkTouched() {
                if ( !$this->mDataLoaded ) {
@@ -563,7 +563,7 @@ class WikiPage implements Page, IDBAccessObject {
 
        /**
         * Get the page_latest field
-        * @return int rev_id of current revision
+        * @return int The rev_id of current revision
         */
        public function getLatest() {
                if ( !$this->mDataLoaded ) {
@@ -663,7 +663,7 @@ class WikiPage implements Page, IDBAccessObject {
        /**
         * Get the content of the current revision. No side-effects...
         *
-        * @param int $audience int One of:
+        * @param int $audience One of:
         *   Revision::FOR_PUBLIC       to be displayed to all users
         *   Revision::FOR_THIS_USER    to be displayed to $wgUser
         *   Revision::RAW              get the text regardless of permissions
@@ -743,7 +743,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Revision::RAW              get the text regardless of permissions
         * @param User $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
-        * @return int user ID for the user that made the last article revision
+        * @return int User ID for the user that made the last article revision
         */
        public function getUser( $audience = Revision::FOR_PUBLIC, User $user = null ) {
                $this->loadLastEdit();
@@ -781,7 +781,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Revision::RAW              get the text regardless of permissions
         * @param User $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
-        * @return string username of the user that made the last article revision
+        * @return string Username of the user that made the last article revision
         */
        public function getUserText( $audience = Revision::FOR_PUBLIC, User $user = null ) {
                $this->loadLastEdit();
@@ -968,7 +968,7 @@ class WikiPage implements Page, IDBAccessObject {
        /**
         * Get the Title object or URL this page redirects to
         *
-        * @return bool|Title|string false, Title of in-wiki target, or string with URL
+        * @return bool|Title|string False, Title of in-wiki target, or string with URL
         */
        public function followRedirect() {
                return $this->getRedirectURL( $this->getRedirectTarget() );
@@ -979,7 +979,7 @@ class WikiPage implements Page, IDBAccessObject {
         * objects for same-wiki, non-special redirects and URLs for everything
         * else.
         * @param Title $rt Redirect target
-        * @return bool|Title|string false, Title object of local target, or string with URL
+        * @return bool|Title|string False, Title object of local target, or string with URL
         */
        public function getRedirectURL( $rt ) {
                if ( !$rt ) {
@@ -1295,7 +1295,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Giving 0 indicates the new page flag should be set on.
         * @param bool $lastRevIsRedirect If given, will optimize adding and
         *   removing rows in redirect table.
-        * @return bool true on success, false on failure
+        * @return bool True on success, false on failure
         */
        public function updateRevisionOn( $dbw, $revision, $lastRevision = null,
                $lastRevIsRedirect = null
@@ -1357,7 +1357,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   or NULL if this is not a redirect
         * @param null|bool $lastRevIsRedirect If given, will optimize adding and
         *   removing rows in redirect table.
-        * @return bool true on success, false on failure
+        * @return bool True on success, false on failure
         * @private
         */
        public function updateRedirectOn( $dbw, $redirectTitle, $lastRevIsRedirect = null ) {
@@ -1433,7 +1433,7 @@ class WikiPage implements Page, IDBAccessObject {
         * must exist and must not be deleted
         * @param Revision $undo
         * @param Revision $undoafter Must be an earlier revision than $undo
-        * @return mixed string on success, false on failure
+        * @return mixed String on success, false on failure
         * @since 1.21
         * Before we had the Content object, this was done in getUndoText
         */
@@ -1448,7 +1448,7 @@ class WikiPage implements Page, IDBAccessObject {
         * 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
+        * @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 ) {
@@ -1563,7 +1563,7 @@ class WikiPage implements Page, IDBAccessObject {
         * or 'new' for a new section.
         * @param Content $sectionContent New content of the section.
         * @param string $sectionTitle New section's subject, only if $section is "new".
-        * @param string $baseRevId integer|null
+        * @param int|null $baseRevId
         *
         * @throws MWException
         * @return Content New complete article content, or null if error.
@@ -1603,7 +1603,7 @@ class WikiPage implements Page, IDBAccessObject {
                                $oldContent = $rev->getContent();
                        }
 
-                       if ( ! $oldContent ) {
+                       if ( !$oldContent ) {
                                wfDebug( __METHOD__ . ": no page text\n" );
                                wfProfileOut( __METHOD__ );
                                return null;
@@ -1666,7 +1666,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @param User $user The user doing the edit
         *
         * @throws MWException
-        * @return Status object. Possible errors:
+        * @return Status Possible errors:
         *   edit-hook-aborted: The ArticleSave hook aborted the edit but didn't
         *     set the fatal flag of $status
         *   edit-gone-missing: In update mode, but the article didn't exist.
@@ -1728,7 +1728,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   database.
         *
         * @throws MWException
-        * @return Status object. Possible errors:
+        * @return Status Possible errors:
         *     edit-hook-aborted: The ArticleSave hook aborted the edit but didn't
         *       set the fatal flag of $status.
         *     edit-gone-missing: In update mode, but the article didn't exist.
@@ -2047,7 +2047,9 @@ class WikiPage implements Page, IDBAccessObject {
                wfRunHooks( 'PageContentSaveComplete', $hook_args );
 
                // Promote user to any groups they meet the criteria for
-               $user->addAutopromoteOnceGroups( 'onEdit' );
+               $dbw->onTransactionIdle( function () use ( $user ) {
+                       $user->addAutopromoteOnceGroups( 'onEdit' );
+               } );
 
                wfProfileOut( __METHOD__ );
                return $status;
@@ -2311,9 +2313,9 @@ class WikiPage implements Page, IDBAccessObject {
         *
         * @param Content $content Content submitted
         * @param User $user The relevant user
-        * @param string $comment comment submitted
-        * @param string $serialisation_format Format for storing the content in the database
+        * @param string $comment Comment submitted
         * @param bool $minor Whereas it's a minor modification
+        * @param string $serialisation_format Format for storing the content in the database
         */
        public function doQuickEditContent( Content $content, User $user, $comment = '', $minor = false,
                $serialisation_format = null
@@ -2737,7 +2739,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @param bool $commit Defaults to true, triggers transaction end
         * @param array &$error Array of errors to append to
         * @param User $user The deleting user
-        * @return bool true if successful
+        * @return bool True if successful
         */
        public function doDeleteArticle(
                $reason, $suppress = false, $id = 0, $commit = true, &$error = '', User $user = null
@@ -2778,7 +2780,7 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                $user = is_null( $user ) ? $wgUser : $user;
-               if ( ! wfRunHooks( 'ArticleDelete', array( &$this, &$user, &$reason, &$error, &$status ) ) ) {
+               if ( !wfRunHooks( 'ArticleDelete', array( &$this, &$user, &$reason, &$error, &$status ) ) ) {
                        if ( $status->isOK() ) {
                                // Hook aborted but didn't set a fatal status
                                $status->fatal( 'delete-hook-aborted' );
@@ -2874,8 +2876,6 @@ class WikiPage implements Page, IDBAccessObject {
                // Clone the title, so we have the information we need when we log
                $logTitle = clone $this->mTitle;
 
-               $this->doDeleteUpdates( $id, $content );
-
                // Log the deletion, if the page was suppressed, log it at Oversight instead
                $logtype = $suppress ? 'suppress' : 'delete';
 
@@ -2885,7 +2885,7 @@ class WikiPage implements Page, IDBAccessObject {
                $logEntry->setComment( $reason );
                $logid = $logEntry->insert();
 
-               $dbw->onTransactionPreCommitOrIdle( function() use ( $dbw, $logEntry, $logid ) {
+               $dbw->onTransactionPreCommitOrIdle( function () use ( $dbw, $logEntry, $logid ) {
                        // Bug 56776: avoid deadlocks (especially from FileDeleteForm)
                        $logEntry->publish( $logid );
                } );
@@ -2894,6 +2894,8 @@ class WikiPage implements Page, IDBAccessObject {
                        $dbw->commit( __METHOD__ );
                }
 
+               $this->doDeleteUpdates( $id, $content );
+
                wfRunHooks( 'ArticleDeleteComplete', array( &$this, &$user, $reason, $id, $content, $logEntry ) );
                $status->value = $logid;
                return $status;
@@ -2902,7 +2904,7 @@ class WikiPage implements Page, IDBAccessObject {
        /**
         * Do some database updates after deletion
         *
-        * @param int $id page_id value of the page being deleted
+        * @param int $id The page_id value of the page being deleted
         * @param Content $content Optional page content to be used when determining
         *   the required updates. This may be needed because $this->getContent()
         *   may already return null when the page proper was deleted.
@@ -2947,7 +2949,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @param string $token Rollback token.
         * @param bool $bot If true, mark all reverted edits as bot.
         *
-        * @param array $resultDetails contains result-specific array of additional values
+        * @param array $resultDetails Array contains result-specific array of additional values
         *    'alreadyrolled' : 'current' (rev)
         *    success        : 'summary' (str), 'current' (rev), 'target' (rev)
         *
@@ -3345,7 +3347,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                // Do this at the end of the commit to reduce lock wait timeouts
                $dbw->onTransactionPreCommitOrIdle(
-                       function() use ( $dbw, $that, $method, $added, $deleted ) {
+                       function () use ( $dbw, $that, $method, $added, $deleted ) {
                                $ns = $that->getTitle()->getNamespace();
 
                                $addFields = array( 'cat_pages = cat_pages + 1' );
@@ -3503,28 +3505,6 @@ class WikiPage implements Page, IDBAccessObject {
                return $wgParser->preSaveTransform( $text, $this->mTitle, $user, $popts );
        }
 
-       /**
-        * Check whether the number of revisions of this page surpasses $wgDeleteRevisionsLimit
-        *
-        * @deprecated since 1.19; use Title::isBigDeletion() instead.
-        * @return bool
-        */
-       public function isBigDeletion() {
-               wfDeprecated( __METHOD__, '1.19' );
-               return $this->mTitle->isBigDeletion();
-       }
-
-       /**
-        * Get the  approximate revision count of this page.
-        *
-        * @deprecated since 1.19; use Title::estimateRevisionCount() instead.
-        * @return int
-        */
-       public function estimateRevisionCount() {
-               wfDeprecated( __METHOD__, '1.19' );
-               return $this->mTitle->estimateRevisionCount();
-       }
-
        /**
         * Update the article's restriction field, and leave a log entry.
         *
@@ -3534,7 +3514,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @param int &$cascade Set to false if cascading protection isn't allowed.
         * @param array $expiry Per restriction type expiration
         * @param User $user The user updating the restrictions
-        * @return bool true on success
+        * @return bool True on success
         */
        public function updateRestrictions(
                $limit = array(), $reason = '', &$cascade = 0, $expiry = array(), User $user = null
diff --git a/includes/pager/AlphabeticPager.php b/includes/pager/AlphabeticPager.php
new file mode 100644 (file)
index 0000000..34c7897
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Efficient paging for SQL queries.
+ *
+ * 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
+ */
+
+/**
+ * IndexPager with an alphabetic list and a formatted navigation bar
+ * @ingroup Pager
+ */
+abstract class AlphabeticPager extends IndexPager {
+
+       /**
+        * Shamelessly stolen bits from ReverseChronologicalPager,
+        * didn't want to do class magic as may be still revamped
+        *
+        * @return string HTML
+        */
+       function getNavigationBar() {
+               if ( !$this->isNavigationBarShown() ) {
+                       return '';
+               }
+
+               if ( isset( $this->mNavigationBar ) ) {
+                       return $this->mNavigationBar;
+               }
+
+               $linkTexts = array(
+                       'prev' => $this->msg( 'prevn' )->numParams( $this->mLimit )->escaped(),
+                       'next' => $this->msg( 'nextn' )->numParams( $this->mLimit )->escaped(),
+                       'first' => $this->msg( 'page_first' )->escaped(),
+                       'last' => $this->msg( 'page_last' )->escaped()
+               );
+
+               $lang = $this->getLanguage();
+
+               $pagingLinks = $this->getPagingLinks( $linkTexts );
+               $limitLinks = $this->getLimitLinks();
+               $limits = $lang->pipeList( $limitLinks );
+
+               $this->mNavigationBar = $this->msg( 'parentheses' )->rawParams(
+                       $lang->pipeList( array( $pagingLinks['first'],
+                       $pagingLinks['last'] ) ) )->escaped() . " " .
+                       $this->msg( 'viewprevnext' )->rawParams( $pagingLinks['prev'],
+                               $pagingLinks['next'], $limits )->escaped();
+
+               if ( !is_array( $this->getIndexField() ) ) {
+                       # Early return to avoid undue nesting
+                       return $this->mNavigationBar;
+               }
+
+               $extra = '';
+               $first = true;
+               $msgs = $this->getOrderTypeMessages();
+               foreach ( array_keys( $msgs ) as $order ) {
+                       if ( $first ) {
+                               $first = false;
+                       } else {
+                               $extra .= $this->msg( 'pipe-separator' )->escaped();
+                       }
+
+                       if ( $order == $this->mOrderType ) {
+                               $extra .= $this->msg( $msgs[$order] )->escaped();
+                       } else {
+                               $extra .= $this->makeLink(
+                                       $this->msg( $msgs[$order] )->escaped(),
+                                       array( 'order' => $order )
+                               );
+                       }
+               }
+
+               if ( $extra !== '' ) {
+                       $extra = ' ' . $this->msg( 'parentheses' )->rawParams( $extra )->escaped();
+                       $this->mNavigationBar .= $extra;
+               }
+
+               return $this->mNavigationBar;
+       }
+
+       /**
+        * If this supports multiple order type messages, give the message key for
+        * enabling each one in getNavigationBar.  The return type is an associative
+        * array whose keys must exactly match the keys of the array returned
+        * by getIndexField(), and whose values are message keys.
+        *
+        * @return array
+        */
+       protected function getOrderTypeMessages() {
+               return null;
+       }
+}
diff --git a/includes/pager/IndexPager.php b/includes/pager/IndexPager.php
new file mode 100644 (file)
index 0000000..ce6dc50
--- /dev/null
@@ -0,0 +1,742 @@
+<?php
+/**
+ * Efficient paging for SQL queries.
+ *
+ * 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
+ */
+
+/**
+ * IndexPager is an efficient pager which uses a (roughly unique) index in the
+ * data set to implement paging, rather than a "LIMIT offset,limit" clause.
+ * In MySQL, such a limit/offset clause requires counting through the
+ * specified number of offset rows to find the desired data, which can be
+ * expensive for large offsets.
+ *
+ * ReverseChronologicalPager is a child class of the abstract IndexPager, and
+ * contains  some formatting and display code which is specific to the use of
+ * timestamps as  indexes. Here is a synopsis of its operation:
+ *
+ *    * The query is specified by the offset, limit and direction (dir)
+ *      parameters, in addition to any subclass-specific parameters.
+ *    * The offset is the non-inclusive start of the DB query. A row with an
+ *      index value equal to the offset will never be shown.
+ *    * The query may either be done backwards, where the rows are returned by
+ *      the database in the opposite order to which they are displayed to the
+ *      user, or forwards. This is specified by the "dir" parameter, dir=prev
+ *      means backwards, anything else means forwards. The offset value
+ *      specifies the start of the database result set, which may be either
+ *      the start or end of the displayed data set. This allows "previous"
+ *      links to be implemented without knowledge of the index value at the
+ *      start of the previous page.
+ *    * An additional row beyond the user-specified limit is always requested.
+ *      This allows us to tell whether we should display a "next" link in the
+ *      case of forwards mode, or a "previous" link in the case of backwards
+ *      mode. Determining whether to display the other link (the one for the
+ *      page before the start of the database result set) can be done
+ *      heuristically by examining the offset.
+ *
+ *    * An empty offset indicates that the offset condition should be omitted
+ *      from the query. This naturally produces either the first page or the
+ *      last page depending on the dir parameter.
+ *
+ *  Subclassing the pager to implement concrete functionality should be fairly
+ *  simple, please see the examples in HistoryAction.php and
+ *  SpecialBlockList.php. You just need to override formatRow(),
+ *  getQueryInfo() and getIndexField(). Don't forget to call the parent
+ *  constructor if you override it.
+ *
+ * @ingroup Pager
+ */
+abstract class IndexPager extends ContextSource implements Pager {
+       /**
+        * Constants for the $mDefaultDirection field.
+        *
+        * These are boolean for historical reasons and should stay boolean for backwards-compatibility.
+        */
+       const DIR_ASCENDING = false;
+       const DIR_DESCENDING = true;
+
+       public $mRequest;
+       public $mLimitsShown = array( 20, 50, 100, 250, 500 );
+       public $mDefaultLimit = 50;
+       public $mOffset, $mLimit;
+       public $mQueryDone = false;
+       public $mDb;
+       public $mPastTheEndRow;
+
+       /**
+        * The index to actually be used for ordering. This is a single column,
+        * for one ordering, even if multiple orderings are supported.
+        */
+       protected $mIndexField;
+       /**
+        * An array of secondary columns to order by. These fields are not part of the offset.
+        * This is a column list for one ordering, even if multiple orderings are supported.
+        */
+       protected $mExtraSortFields;
+       /** For pages that support multiple types of ordering, which one to use.
+        */
+       protected $mOrderType;
+       /**
+        * $mDefaultDirection gives the direction to use when sorting results:
+        * DIR_ASCENDING or DIR_DESCENDING.  If $mIsBackwards is set, we
+        * start from the opposite end, but we still sort the page itself according
+        * to $mDefaultDirection.  E.g., if $mDefaultDirection is false but we're
+        * going backwards, we'll display the last page of results, but the last
+        * result will be at the bottom, not the top.
+        *
+        * Like $mIndexField, $mDefaultDirection will be a single value even if the
+        * class supports multiple default directions for different order types.
+        */
+       public $mDefaultDirection;
+       public $mIsBackwards;
+
+       /** True if the current result set is the first one */
+       public $mIsFirst;
+       public $mIsLast;
+
+       protected $mLastShown, $mFirstShown, $mPastTheEndIndex, $mDefaultQuery, $mNavigationBar;
+
+       /**
+        * Whether to include the offset in the query
+        */
+       protected $mIncludeOffset = false;
+
+       /**
+        * Result object for the query. Warning: seek before use.
+        *
+        * @var ResultWrapper
+        */
+       public $mResult;
+
+       public function __construct( IContextSource $context = null ) {
+               if ( $context ) {
+                       $this->setContext( $context );
+               }
+
+               $this->mRequest = $this->getRequest();
+
+               # NB: the offset is quoted, not validated. It is treated as an
+               # arbitrary string to support the widest variety of index types. Be
+               # careful outputting it into HTML!
+               $this->mOffset = $this->mRequest->getText( 'offset' );
+
+               # Use consistent behavior for the limit options
+               $this->mDefaultLimit = $this->getUser()->getIntOption( 'rclimit' );
+               if ( !$this->mLimit ) {
+                       // Don't override if a subclass calls $this->setLimit() in its constructor.
+                       list( $this->mLimit, /* $offset */ ) = $this->mRequest->getLimitOffset();
+               }
+
+               $this->mIsBackwards = ( $this->mRequest->getVal( 'dir' ) == 'prev' );
+               # Let the subclass set the DB here; otherwise use a slave DB for the current wiki
+               $this->mDb = $this->mDb ?: wfGetDB( DB_SLAVE );
+
+               $index = $this->getIndexField(); // column to sort on
+               $extraSort = $this->getExtraSortFields(); // extra columns to sort on for query planning
+               $order = $this->mRequest->getVal( 'order' );
+               if ( is_array( $index ) && isset( $index[$order] ) ) {
+                       $this->mOrderType = $order;
+                       $this->mIndexField = $index[$order];
+                       $this->mExtraSortFields = isset( $extraSort[$order] )
+                               ? (array)$extraSort[$order]
+                               : array();
+               } elseif ( is_array( $index ) ) {
+                       # First element is the default
+                       reset( $index );
+                       list( $this->mOrderType, $this->mIndexField ) = each( $index );
+                       $this->mExtraSortFields = isset( $extraSort[$this->mOrderType] )
+                               ? (array)$extraSort[$this->mOrderType]
+                               : array();
+               } else {
+                       # $index is not an array
+                       $this->mOrderType = null;
+                       $this->mIndexField = $index;
+                       $this->mExtraSortFields = (array)$extraSort;
+               }
+
+               if ( !isset( $this->mDefaultDirection ) ) {
+                       $dir = $this->getDefaultDirections();
+                       $this->mDefaultDirection = is_array( $dir )
+                               ? $dir[$this->mOrderType]
+                               : $dir;
+               }
+       }
+
+       /**
+        * Get the Database object in use
+        *
+        * @return DatabaseBase
+        */
+       public function getDatabase() {
+               return $this->mDb;
+       }
+
+       /**
+        * Do the query, using information from the object context. This function
+        * has been kept minimal to make it overridable if necessary, to allow for
+        * result sets formed from multiple DB queries.
+        */
+       public function doQuery() {
+               # Use the child class name for profiling
+               $fname = __METHOD__ . ' (' . get_class( $this ) . ')';
+               wfProfileIn( $fname );
+
+               // @todo This should probably compare to DIR_DESCENDING and DIR_ASCENDING constants
+               $descending = ( $this->mIsBackwards == $this->mDefaultDirection );
+               # Plus an extra row so that we can tell the "next" link should be shown
+               $queryLimit = $this->mLimit + 1;
+
+               if ( $this->mOffset == '' ) {
+                       $isFirst = true;
+               } else {
+                       // If there's an offset, we may or may not be at the first entry.
+                       // The only way to tell is to run the query in the opposite
+                       // direction see if we get a row.
+                       $oldIncludeOffset = $this->mIncludeOffset;
+                       $this->mIncludeOffset = !$this->mIncludeOffset;
+                       $isFirst = !$this->reallyDoQuery( $this->mOffset, 1, !$descending )->numRows();
+                       $this->mIncludeOffset = $oldIncludeOffset;
+               }
+
+               $this->mResult = $this->reallyDoQuery(
+                       $this->mOffset,
+                       $queryLimit,
+                       $descending
+               );
+
+               $this->extractResultInfo( $isFirst, $queryLimit, $this->mResult );
+               $this->mQueryDone = true;
+
+               $this->preprocessResults( $this->mResult );
+               $this->mResult->rewind(); // Paranoia
+
+               wfProfileOut( $fname );
+       }
+
+       /**
+        * @return ResultWrapper The result wrapper.
+        */
+       function getResult() {
+               return $this->mResult;
+       }
+
+       /**
+        * Set the offset from an other source than the request
+        *
+        * @param int|string $offset
+        */
+       function setOffset( $offset ) {
+               $this->mOffset = $offset;
+       }
+
+       /**
+        * Set the limit from an other source than the request
+        *
+        * Verifies limit is between 1 and 5000
+        *
+        * @param int|string $limit
+        */
+       function setLimit( $limit ) {
+               $limit = (int)$limit;
+               // WebRequest::getLimitOffset() puts a cap of 5000, so do same here.
+               if ( $limit > 5000 ) {
+                       $limit = 5000;
+               }
+               if ( $limit > 0 ) {
+                       $this->mLimit = $limit;
+               }
+       }
+
+       /**
+        * Get the current limit
+        *
+        * @return int
+        */
+       function getLimit() {
+               return $this->mLimit;
+       }
+
+       /**
+        * Set whether a row matching exactly the offset should be also included
+        * in the result or not. By default this is not the case, but when the
+        * offset is user-supplied this might be wanted.
+        *
+        * @param bool $include
+        */
+       public function setIncludeOffset( $include ) {
+               $this->mIncludeOffset = $include;
+       }
+
+       /**
+        * Extract some useful data from the result object for use by
+        * the navigation bar, put it into $this
+        *
+        * @param bool $isFirst False if there are rows before those fetched (i.e.
+        *     if a "previous" link would make sense)
+        * @param int $limit Exact query limit
+        * @param ResultWrapper $res
+        */
+       function extractResultInfo( $isFirst, $limit, ResultWrapper $res ) {
+               $numRows = $res->numRows();
+               if ( $numRows ) {
+                       # Remove any table prefix from index field
+                       $parts = explode( '.', $this->mIndexField );
+                       $indexColumn = end( $parts );
+
+                       $row = $res->fetchRow();
+                       $firstIndex = $row[$indexColumn];
+
+                       # Discard the extra result row if there is one
+                       if ( $numRows > $this->mLimit && $numRows > 1 ) {
+                               $res->seek( $numRows - 1 );
+                               $this->mPastTheEndRow = $res->fetchObject();
+                               $this->mPastTheEndIndex = $this->mPastTheEndRow->$indexColumn;
+                               $res->seek( $numRows - 2 );
+                               $row = $res->fetchRow();
+                               $lastIndex = $row[$indexColumn];
+                       } else {
+                               $this->mPastTheEndRow = null;
+                               # Setting indexes to an empty string means that they will be
+                               # omitted if they would otherwise appear in URLs. It just so
+                               # happens that this  is the right thing to do in the standard
+                               # UI, in all the relevant cases.
+                               $this->mPastTheEndIndex = '';
+                               $res->seek( $numRows - 1 );
+                               $row = $res->fetchRow();
+                               $lastIndex = $row[$indexColumn];
+                       }
+               } else {
+                       $firstIndex = '';
+                       $lastIndex = '';
+                       $this->mPastTheEndRow = null;
+                       $this->mPastTheEndIndex = '';
+               }
+
+               if ( $this->mIsBackwards ) {
+                       $this->mIsFirst = ( $numRows < $limit );
+                       $this->mIsLast = $isFirst;
+                       $this->mLastShown = $firstIndex;
+                       $this->mFirstShown = $lastIndex;
+               } else {
+                       $this->mIsFirst = $isFirst;
+                       $this->mIsLast = ( $numRows < $limit );
+                       $this->mLastShown = $lastIndex;
+                       $this->mFirstShown = $firstIndex;
+               }
+       }
+
+       /**
+        * Get some text to go in brackets in the "function name" part of the SQL comment
+        *
+        * @return string
+        */
+       function getSqlComment() {
+               return get_class( $this );
+       }
+
+       /**
+        * Do a query with specified parameters, rather than using the object
+        * context
+        *
+        * @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
+        */
+       public function reallyDoQuery( $offset, $limit, $descending ) {
+               list( $tables, $fields, $conds, $fname, $options, $join_conds ) =
+                       $this->buildQueryInfo( $offset, $limit, $descending );
+
+               return $this->mDb->select( $tables, $fields, $conds, $fname, $options, $join_conds );
+       }
+
+       /**
+        * Build variables to use by the database wrapper.
+        *
+        * @param string $offset Index offset, inclusive
+        * @param int $limit Exact query limit
+        * @param bool $descending Query direction, false for ascending, true for descending
+        * @return array
+        */
+       protected function buildQueryInfo( $offset, $limit, $descending ) {
+               $fname = __METHOD__ . ' (' . $this->getSqlComment() . ')';
+               $info = $this->getQueryInfo();
+               $tables = $info['tables'];
+               $fields = $info['fields'];
+               $conds = isset( $info['conds'] ) ? $info['conds'] : array();
+               $options = isset( $info['options'] ) ? $info['options'] : array();
+               $join_conds = isset( $info['join_conds'] ) ? $info['join_conds'] : array();
+               $sortColumns = array_merge( array( $this->mIndexField ), $this->mExtraSortFields );
+               if ( $descending ) {
+                       $options['ORDER BY'] = $sortColumns;
+                       $operator = $this->mIncludeOffset ? '>=' : '>';
+               } else {
+                       $orderBy = array();
+                       foreach ( $sortColumns as $col ) {
+                               $orderBy[] = $col . ' DESC';
+                       }
+                       $options['ORDER BY'] = $orderBy;
+                       $operator = $this->mIncludeOffset ? '<=' : '<';
+               }
+               if ( $offset != '' ) {
+                       $conds[] = $this->mIndexField . $operator . $this->mDb->addQuotes( $offset );
+               }
+               $options['LIMIT'] = intval( $limit );
+               return array( $tables, $fields, $conds, $fname, $options, $join_conds );
+       }
+
+       /**
+        * Pre-process results; useful for performing batch existence checks, etc.
+        *
+        * @param ResultWrapper $result
+        */
+       protected function preprocessResults( $result ) {
+       }
+
+       /**
+        * Get the formatted result list. Calls getStartBody(), formatRow() and
+        * getEndBody(), concatenates the results and returns them.
+        *
+        * @return string
+        */
+       public function getBody() {
+               if ( !$this->mQueryDone ) {
+                       $this->doQuery();
+               }
+
+               if ( $this->mResult->numRows() ) {
+                       # Do any special query batches before display
+                       $this->doBatchLookups();
+               }
+
+               # Don't use any extra rows returned by the query
+               $numRows = min( $this->mResult->numRows(), $this->mLimit );
+
+               $s = $this->getStartBody();
+               if ( $numRows ) {
+                       if ( $this->mIsBackwards ) {
+                               for ( $i = $numRows - 1; $i >= 0; $i-- ) {
+                                       $this->mResult->seek( $i );
+                                       $row = $this->mResult->fetchObject();
+                                       $s .= $this->formatRow( $row );
+                               }
+                       } else {
+                               $this->mResult->seek( 0 );
+                               for ( $i = 0; $i < $numRows; $i++ ) {
+                                       $row = $this->mResult->fetchObject();
+                                       $s .= $this->formatRow( $row );
+                               }
+                       }
+               } else {
+                       $s .= $this->getEmptyBody();
+               }
+               $s .= $this->getEndBody();
+               return $s;
+       }
+
+       /**
+        * Make a self-link
+        *
+        * @param string $text Text displayed on the link
+        * @param array $query Associative array of parameter to be in the query string
+        * @param string $type Link type used to create additional attributes, like "rel", "class" or
+        *  "title". Valid values (non-exhaustive list): 'first', 'last', 'prev', 'next', 'asc', 'desc'.
+        * @return string HTML fragment
+        */
+       function makeLink( $text, array $query = null, $type = null ) {
+               if ( $query === null ) {
+                       return $text;
+               }
+
+               $attrs = array();
+               if ( in_array( $type, array( 'prev', 'next' ) ) ) {
+                       $attrs['rel'] = $type;
+               }
+
+               if ( in_array( $type, array( 'asc', 'desc' ) ) ) {
+                       $attrs['title'] = wfMessage( $type == 'asc' ? 'sort-ascending' : 'sort-descending' )->text();
+               }
+
+               if ( $type ) {
+                       $attrs['class'] = "mw-{$type}link";
+               }
+
+
+               return Linker::linkKnown(
+                       $this->getTitle(),
+                       $text,
+                       $attrs,
+                       $query + $this->getDefaultQuery()
+               );
+       }
+
+       /**
+        * Called from getBody(), before getStartBody() is called and
+        * after doQuery() was called. This will be called only if there
+        * are rows in the result set.
+        *
+        * @return void
+        */
+       protected function doBatchLookups() {
+       }
+
+       /**
+        * Hook into getBody(), allows text to be inserted at the start. This
+        * will be called even if there are no rows in the result set.
+        *
+        * @return string
+        */
+       protected function getStartBody() {
+               return '';
+       }
+
+       /**
+        * Hook into getBody() for the end of the list
+        *
+        * @return string
+        */
+       protected function getEndBody() {
+               return '';
+       }
+
+       /**
+        * Hook into getBody(), for the bit between the start and the
+        * end when there are no rows
+        *
+        * @return string
+        */
+       protected function getEmptyBody() {
+               return '';
+       }
+
+       /**
+        * Get an array of query parameters that should be put into self-links.
+        * By default, all parameters passed in the URL are used, except for a
+        * short blacklist.
+        *
+        * @return array Associative array
+        */
+       function getDefaultQuery() {
+               if ( !isset( $this->mDefaultQuery ) ) {
+                       $this->mDefaultQuery = $this->getRequest()->getQueryValues();
+                       unset( $this->mDefaultQuery['title'] );
+                       unset( $this->mDefaultQuery['dir'] );
+                       unset( $this->mDefaultQuery['offset'] );
+                       unset( $this->mDefaultQuery['limit'] );
+                       unset( $this->mDefaultQuery['order'] );
+                       unset( $this->mDefaultQuery['month'] );
+                       unset( $this->mDefaultQuery['year'] );
+               }
+               return $this->mDefaultQuery;
+       }
+
+       /**
+        * Get the number of rows in the result set
+        *
+        * @return int
+        */
+       function getNumRows() {
+               if ( !$this->mQueryDone ) {
+                       $this->doQuery();
+               }
+               return $this->mResult->numRows();
+       }
+
+       /**
+        * Get a URL query array for the prev, next, first and last links.
+        *
+        * @return array
+        */
+       function getPagingQueries() {
+               if ( !$this->mQueryDone ) {
+                       $this->doQuery();
+               }
+
+               # Don't announce the limit everywhere if it's the default
+               $urlLimit = $this->mLimit == $this->mDefaultLimit ? null : $this->mLimit;
+
+               if ( $this->mIsFirst ) {
+                       $prev = false;
+                       $first = false;
+               } else {
+                       $prev = array(
+                               'dir' => 'prev',
+                               'offset' => $this->mFirstShown,
+                               'limit' => $urlLimit
+                       );
+                       $first = array( 'limit' => $urlLimit );
+               }
+               if ( $this->mIsLast ) {
+                       $next = false;
+                       $last = false;
+               } else {
+                       $next = array( 'offset' => $this->mLastShown, 'limit' => $urlLimit );
+                       $last = array( 'dir' => 'prev', 'limit' => $urlLimit );
+               }
+               return array(
+                       'prev' => $prev,
+                       'next' => $next,
+                       'first' => $first,
+                       'last' => $last
+               );
+       }
+
+       /**
+        * Returns whether to show the "navigation bar"
+        *
+        * @return bool
+        */
+       function isNavigationBarShown() {
+               if ( !$this->mQueryDone ) {
+                       $this->doQuery();
+               }
+               // Hide navigation by default if there is nothing to page
+               return !( $this->mIsFirst && $this->mIsLast );
+       }
+
+       /**
+        * Get paging links. If a link is disabled, the item from $disabledTexts
+        * will be used. If there is no such item, the unlinked text from
+        * $linkTexts will be used. Both $linkTexts and $disabledTexts are arrays
+        * of HTML.
+        *
+        * @param array $linkTexts
+        * @param array $disabledTexts
+        * @return array
+        */
+       function getPagingLinks( $linkTexts, $disabledTexts = array() ) {
+               $queries = $this->getPagingQueries();
+               $links = array();
+
+               foreach ( $queries as $type => $query ) {
+                       if ( $query !== false ) {
+                               $links[$type] = $this->makeLink(
+                                       $linkTexts[$type],
+                                       $queries[$type],
+                                       $type
+                               );
+                       } elseif ( isset( $disabledTexts[$type] ) ) {
+                               $links[$type] = $disabledTexts[$type];
+                       } else {
+                               $links[$type] = $linkTexts[$type];
+                       }
+               }
+
+               return $links;
+       }
+
+       function getLimitLinks() {
+               $links = array();
+               if ( $this->mIsBackwards ) {
+                       $offset = $this->mPastTheEndIndex;
+               } else {
+                       $offset = $this->mOffset;
+               }
+               foreach ( $this->mLimitsShown as $limit ) {
+                       $links[] = $this->makeLink(
+                               $this->getLanguage()->formatNum( $limit ),
+                               array( 'offset' => $offset, 'limit' => $limit ),
+                               'num'
+                       );
+               }
+               return $links;
+       }
+
+       /**
+        * Abstract formatting function. This should return an HTML string
+        * representing the result row $row. Rows will be concatenated and
+        * returned by getBody()
+        *
+        * @param array|stdClass $row Database row
+        * @return string
+        */
+       abstract function formatRow( $row );
+
+       /**
+        * This function should be overridden to provide all parameters
+        * needed for the main paged query. It returns an associative
+        * array with the following elements:
+        *    tables => Table(s) for passing to Database::select()
+        *    fields => Field(s) for passing to Database::select(), may be *
+        *    conds => WHERE conditions
+        *    options => option array
+        *    join_conds => JOIN conditions
+        *
+        * @return array
+        */
+       abstract function getQueryInfo();
+
+       /**
+        * This function should be overridden to return the name of the index fi-
+        * eld.  If the pager supports multiple orders, it may return an array of
+        * 'querykey' => 'indexfield' pairs, so that a request with &count=querykey
+        * will use indexfield to sort.  In this case, the first returned key is
+        * the default.
+        *
+        * Needless to say, it's really not a good idea to use a non-unique index
+        * for this!  That won't page right.
+        *
+        * @return string|array
+        */
+       abstract function getIndexField();
+
+       /**
+        * This function should be overridden to return the names of secondary columns
+        * to order by in addition to the column in getIndexField(). These fields will
+        * not be used in the pager offset or in any links for users.
+        *
+        * If getIndexField() returns an array of 'querykey' => 'indexfield' pairs then
+        * this must return a corresponding array of 'querykey' => array( fields...) pairs
+        * in order for a request with &count=querykey to use array( fields...) to sort.
+        *
+        * This is useful for pagers that GROUP BY a unique column (say page_id)
+        * and ORDER BY another (say page_len). Using GROUP BY and ORDER BY both on
+        * page_len,page_id avoids temp tables (given a page_len index). This would
+        * also work if page_id was non-unique but we had a page_len,page_id index.
+        *
+        * @return array
+        */
+       protected function getExtraSortFields() {
+               return array();
+       }
+
+       /**
+        * Return the default sorting direction: DIR_ASCENDING or DIR_DESCENDING.
+        * You can also have an associative array of ordertype => dir,
+        * if multiple order types are supported.  In this case getIndexField()
+        * must return an array, and the keys of that must exactly match the keys
+        * of this.
+        *
+        * For backward compatibility, this method's return value will be ignored
+        * if $this->mDefaultDirection is already set when the constructor is
+        * called, for instance if it's statically initialized.  In that case the
+        * value of that variable (which must be a boolean) will be used.
+        *
+        * Note that despite its name, this does not return the value of the
+        * $this->mDefaultDirection member variable.  That's the default for this
+        * particular instantiation, which is a single value.  This is the set of
+        * all defaults for the class.
+        *
+        * @return bool
+        */
+       protected function getDefaultDirections() {
+               return IndexPager::DIR_ASCENDING;
+       }
+}
diff --git a/includes/pager/Pager.php b/includes/pager/Pager.php
new file mode 100644 (file)
index 0000000..edec490
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Efficient paging for SQL queries.
+ *
+ * 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
+ */
+
+/**
+ * @defgroup Pager Pager
+ */
+
+/**
+ * Basic pager interface.
+ * @ingroup Pager
+ */
+interface Pager {
+       function getNavigationBar();
+       function getBody();
+}
diff --git a/includes/pager/ReverseChronologicalPager.php b/includes/pager/ReverseChronologicalPager.php
new file mode 100644 (file)
index 0000000..4f8c438
--- /dev/null
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Efficient paging for SQL queries.
+ *
+ * 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
+ */
+
+/**
+ * IndexPager with a formatted navigation bar
+ * @ingroup Pager
+ */
+abstract class ReverseChronologicalPager extends IndexPager {
+       public $mDefaultDirection = IndexPager::DIR_DESCENDING;
+       public $mYear;
+       public $mMonth;
+
+       function getNavigationBar() {
+               if ( !$this->isNavigationBarShown() ) {
+                       return '';
+               }
+
+               if ( isset( $this->mNavigationBar ) ) {
+                       return $this->mNavigationBar;
+               }
+
+               $linkTexts = array(
+                       '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();
+               $limits = $this->getLanguage()->pipeList( $limitLinks );
+               $firstLastLinks = $this->msg( 'parentheses' )->rawParams( "{$pagingLinks['first']}" .
+                       $this->msg( 'pipe-separator' )->escaped() .
+                       "{$pagingLinks['last']}" )->escaped();
+
+               $this->mNavigationBar = $firstLastLinks . ' ' .
+                       $this->msg( 'viewprevnext' )->rawParams(
+                               $pagingLinks['prev'], $pagingLinks['next'], $limits )->escaped();
+
+               return $this->mNavigationBar;
+       }
+
+       function getDateCond( $year, $month ) {
+               $year = intval( $year );
+               $month = intval( $month );
+
+               // Basic validity checks
+               $this->mYear = $year > 0 ? $year : false;
+               $this->mMonth = ( $month > 0 && $month < 13 ) ? $month : false;
+
+               // Given an optional year and month, we need to generate a timestamp
+               // to use as "WHERE rev_timestamp <= result"
+               // Examples: year = 2006 equals < 20070101 (+000000)
+               // year=2005, month=1    equals < 20050201
+               // year=2005, month=12   equals < 20060101
+               if ( !$this->mYear && !$this->mMonth ) {
+                       return;
+               }
+
+               if ( $this->mYear ) {
+                       $year = $this->mYear;
+               } else {
+                       // If no year given, assume the current one
+                       $timestamp = MWTimestamp::getInstance();
+                       $year = $timestamp->format( 'Y' );
+                       // If this month hasn't happened yet this year, go back to last year's month
+                       if ( $this->mMonth > $timestamp->format( 'n' ) ) {
+                               $year--;
+                       }
+               }
+
+               if ( $this->mMonth ) {
+                       $month = $this->mMonth + 1;
+                       // For December, we want January 1 of the next year
+                       if ( $month > 12 ) {
+                               $month = 1;
+                               $year++;
+                       }
+               } else {
+                       // No month implies we want up to the end of the year in question
+                       $month = 1;
+                       $year++;
+               }
+
+               // Y2K38 bug
+               if ( $year > 2032 ) {
+                       $year = 2032;
+               }
+
+               $ymd = (int)sprintf( "%04d%02d01", $year, $month );
+
+               if ( $ymd > 20320101 ) {
+                       $ymd = 20320101;
+               }
+
+               $this->mOffset = $this->mDb->timestamp( "${ymd}000000" );
+       }
+}
diff --git a/includes/pager/TablePager.php b/includes/pager/TablePager.php
new file mode 100644 (file)
index 0000000..8095539
--- /dev/null
@@ -0,0 +1,469 @@
+<?php
+/**
+ * Efficient paging for SQL queries.
+ *
+ * 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
+ */
+
+/**
+ * Table-based display with a user-selectable sort order
+ * @ingroup Pager
+ */
+abstract class TablePager extends IndexPager {
+       protected $mSort;
+
+       protected $mCurrentRow;
+
+       public function __construct( IContextSource $context = null ) {
+               if ( $context ) {
+                       $this->setContext( $context );
+               }
+
+               $this->mSort = $this->getRequest()->getText( 'sort' );
+               if ( !array_key_exists( $this->mSort, $this->getFieldNames() )
+                       || !$this->isFieldSortable( $this->mSort )
+               ) {
+                       $this->mSort = $this->getDefaultSort();
+               }
+               if ( $this->getRequest()->getBool( 'asc' ) ) {
+                       $this->mDefaultDirection = IndexPager::DIR_ASCENDING;
+               } elseif ( $this->getRequest()->getBool( 'desc' ) ) {
+                       $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
+               } /* Else leave it at whatever the class default is */
+
+               parent::__construct();
+       }
+
+       /**
+        * Get the formatted result list. Calls getStartBody(), formatRow() and getEndBody(), concatenates
+        * the results and returns them.
+        *
+        * Also adds the required styles to our OutputPage object (this means that if context wasn't
+        * passed to constructor or otherwise set up, you will get a pager with missing styles).
+        *
+        * This method has been made 'final' in 1.24. There's no reason to override it, and if there exist
+        * any subclasses that do, the style loading hack is probably broken in them. Let's fail fast
+        * rather than mysteriously render things wrong.
+        *
+        * @deprecated since 1.24, use getBodyOutput() or getFullOutput() instead
+        * @return string
+        */
+       final public function getBody() {
+               $this->getOutput()->addModuleStyles( $this->getModuleStyles() );
+               return parent::getBody();
+       }
+
+       /**
+        * Get the formatted result list.
+        *
+        * Calls getBody() and getModuleStyles() and builds a ParserOutput object. (This is a bit hacky
+        * but works well.)
+        *
+        * @since 1.24
+        * @return ParserOutput
+        */
+       public function getBodyOutput() {
+               $body = parent::getBody();
+
+               $pout = new ParserOutput;
+               $pout->setText( $body );
+               $pout->addModuleStyles( $this->getModuleStyles() );
+               return $pout;
+       }
+
+       /**
+        * Get the formatted result list, with navigation bars.
+        *
+        * Calls getBody(), getNavigationBar() and getModuleStyles() and
+        * builds a ParserOutput object. (This is a bit hacky but works well.)
+        *
+        * @since 1.24
+        * @return ParserOutput
+        */
+       public function getFullOutput() {
+               $navigation = $this->getNavigationBar();
+               $body = parent::getBody();
+
+               $pout = new ParserOutput;
+               $pout->setText( $navigation . $body . $navigation );
+               $pout->addModuleStyles( $this->getModuleStyles() );
+               return $pout;
+       }
+
+       /**
+        * @protected
+        * @return string
+        */
+       function getStartBody() {
+               $sortClass = $this->getSortHeaderClass();
+
+               $s = '';
+               $fields = $this->getFieldNames();
+
+               // Make table header
+               foreach ( $fields as $field => $name ) {
+                       if ( strval( $name ) == '' ) {
+                               $s .= Html::rawElement( 'th', array(), '&#160;' ) . "\n";
+                       } elseif ( $this->isFieldSortable( $field ) ) {
+                               $query = array( 'sort' => $field, 'limit' => $this->mLimit );
+                               $linkType = null;
+                               $class = null;
+
+                               if ( $this->mSort == $field ) {
+                                       // The table is sorted by this field already, make a link to sort in the other direction
+                                       // We don't actually know in which direction other fields will be sorted by default…
+                                       if ( $this->mDefaultDirection == IndexPager::DIR_DESCENDING ) {
+                                               $linkType = 'asc';
+                                               $class = "$sortClass TablePager_sort-descending";
+                                               $query['asc'] = '1';
+                                               $query['desc'] = '';
+                                       } else {
+                                               $linkType = 'desc';
+                                               $class = "$sortClass TablePager_sort-ascending";
+                                               $query['asc'] = '';
+                                               $query['desc'] = '1';
+                                       }
+                               }
+
+                               $link = $this->makeLink( htmlspecialchars( $name ), $query, $linkType );
+                               $s .= Html::rawElement( 'th', array( 'class' => $class ), $link ) . "\n";
+                       } else {
+                               $s .= Html::element( 'th', array(), $name ) . "\n";
+                       }
+               }
+
+               $tableClass = $this->getTableClass();
+               $ret = Html::openElement( 'table', array(
+                       'class' => "mw-datatable $tableClass" )
+               );
+               $ret .= Html::rawElement( 'thead', array(), Html::rawElement( 'tr', array(), "\n" . $s . "\n" ) );
+               $ret .= Html::openElement( 'tbody' ) . "\n";
+
+               return $ret;
+       }
+
+       /**
+        * @protected
+        * @return string
+        */
+       function getEndBody() {
+               return "</tbody></table>\n";
+       }
+
+       /**
+        * @protected
+        * @return string
+        */
+       function getEmptyBody() {
+               $colspan = count( $this->getFieldNames() );
+               $msgEmpty = $this->msg( 'table_pager_empty' )->text();
+               return Html::rawElement( 'tr', array(),
+                       Html::element( 'td', array( 'colspan' => $colspan ), $msgEmpty ) );
+       }
+
+       /**
+        * @protected
+        * @param stdClass $row
+        * @return string HTML
+        */
+       function formatRow( $row ) {
+               $this->mCurrentRow = $row; // In case formatValue etc need to know
+               $s = Html::openElement( 'tr', $this->getRowAttrs( $row ) ) . "\n";
+               $fieldNames = $this->getFieldNames();
+
+               foreach ( $fieldNames as $field => $name ) {
+                       $value = isset( $row->$field ) ? $row->$field : null;
+                       $formatted = strval( $this->formatValue( $field, $value ) );
+
+                       if ( $formatted == '' ) {
+                               $formatted = '&#160;';
+                       }
+
+                       $s .= Html::rawElement( 'td', $this->getCellAttrs( $field, $value ), $formatted ) . "\n";
+               }
+
+               $s .= Html::closeElement( 'tr' ) . "\n";
+
+               return $s;
+       }
+
+       /**
+        * Get a class name to be applied to the given row.
+        *
+        * @protected
+        *
+        * @param object $row The database result row
+        * @return string
+        */
+       function getRowClass( $row ) {
+               return '';
+       }
+
+       /**
+        * Get attributes to be applied to the given row.
+        *
+        * @protected
+        *
+        * @param object $row The database result row
+        * @return array Array of attribute => value
+        */
+       function getRowAttrs( $row ) {
+               $class = $this->getRowClass( $row );
+               if ( $class === '' ) {
+                       // Return an empty array to avoid clutter in HTML like class=""
+                       return array();
+               } else {
+                       return array( 'class' => $this->getRowClass( $row ) );
+               }
+       }
+
+       /**
+        * Get any extra attributes to be applied to the given cell. Don't
+        * take this as an excuse to hardcode styles; use classes and
+        * CSS instead.  Row context is available in $this->mCurrentRow
+        *
+        * @protected
+        *
+        * @param string $field The column
+        * @param string $value The cell contents
+        * @return array Array of attr => value
+        */
+       function getCellAttrs( $field, $value ) {
+               return array( 'class' => 'TablePager_col_' . $field );
+       }
+
+       /**
+        * @protected
+        * @return string
+        */
+       function getIndexField() {
+               return $this->mSort;
+       }
+
+       /**
+        * @protected
+        * @return string
+        */
+       function getTableClass() {
+               return 'TablePager';
+       }
+
+       /**
+        * @protected
+        * @return string
+        */
+       function getNavClass() {
+               return 'TablePager_nav';
+       }
+
+       /**
+        * @protected
+        * @return string
+        */
+       function getSortHeaderClass() {
+               return 'TablePager_sort';
+       }
+
+       /**
+        * A navigation bar with images
+        * @return string HTML
+        */
+       public function getNavigationBar() {
+               if ( !$this->isNavigationBarShown() ) {
+                       return '';
+               }
+
+               $labels = array(
+                       'first' => 'table_pager_first',
+                       'prev' => 'table_pager_prev',
+                       'next' => 'table_pager_next',
+                       'last' => 'table_pager_last',
+               );
+
+               $linkTexts = array();
+               $disabledTexts = array();
+               foreach ( $labels as $type => $label ) {
+                       $msgLabel = $this->msg( $label )->escaped();
+                       $linkTexts[$type] = "<div class='TablePager_nav-enabled'>$msgLabel</div>";
+                       $disabledTexts[$type] = "<div class='TablePager_nav-disabled'>$msgLabel</div>";
+               }
+               $links = $this->getPagingLinks( $linkTexts, $disabledTexts );
+
+               $s = Html::openElement( 'table', array( 'class' => $this->getNavClass() ) );
+               $s .= Html::openElement( 'tr' ) . "\n";
+               $width = 100 / count( $links ) . '%';
+               foreach ( $labels as $type => $label ) {
+                       // We want every cell to have the same width. We could use table-layout: fixed; in CSS,
+                       // but it only works if we specify the width of a cell or the table and we don't want to.
+                       // There is no better way. <http://www.w3.org/TR/CSS2/tables.html#fixed-table-layout>
+                       $s .= Html::rawElement( 'td',
+                               array( 'style' => "width: $width;", 'class' => "TablePager_nav-$type" ),
+                               $links[$type] ) . "\n";
+               }
+               $s .= Html::closeElement( 'tr' ) . Html::closeElement( 'table' ) . "\n";
+               return $s;
+       }
+
+       /**
+        * ResourceLoader modules that must be loaded to provide correct styling for this pager
+        * @since 1.24
+        * @return string[]
+        */
+       public function getModuleStyles() {
+               return array( 'mediawiki.pager.tablePager' );
+       }
+
+       /**
+        * Get a "<select>" element which has options for each of the allowed limits
+        *
+        * @param string $attribs Extra attributes to set
+        * @return string HTML fragment
+        */
+       public function getLimitSelect( $attribs = array() ) {
+               $select = new XmlSelect( 'limit', false, $this->mLimit );
+               $select->addOptions( $this->getLimitSelectList() );
+               foreach ( $attribs as $name => $value ) {
+                       $select->setAttribute( $name, $value );
+               }
+               return $select->getHTML();
+       }
+
+       /**
+        * Get a list of items to show in a "<select>" element of limits.
+        * This can be passed directly to XmlSelect::addOptions().
+        *
+        * @since 1.22
+        * @return array
+        */
+       public function getLimitSelectList() {
+               # Add the current limit from the query string
+               # to avoid that the limit is lost after clicking Go next time
+               if ( !in_array( $this->mLimit, $this->mLimitsShown ) ) {
+                       $this->mLimitsShown[] = $this->mLimit;
+                       sort( $this->mLimitsShown );
+               }
+               $ret = array();
+               foreach ( $this->mLimitsShown as $key => $value ) {
+                       # The pair is either $index => $limit, in which case the $value
+                       # will be numeric, or $limit => $text, in which case the $value
+                       # will be a string.
+                       if ( is_int( $value ) ) {
+                               $limit = $value;
+                               $text = $this->getLanguage()->formatNum( $limit );
+                       } else {
+                               $limit = $key;
+                               $text = $value;
+                       }
+                       $ret[$text] = $limit;
+               }
+               return $ret;
+       }
+
+       /**
+        * Get \<input type="hidden"\> elements for use in a method="get" form.
+        * Resubmits all defined elements of the query string, except for a
+        * blacklist, passed in the $blacklist parameter.
+        *
+        * @param array $blacklist Parameters from the request query which should not be resubmitted
+        * @return string HTML fragment
+        */
+       function getHiddenFields( $blacklist = array() ) {
+               $blacklist = (array)$blacklist;
+               $query = $this->getRequest()->getQueryValues();
+               foreach ( $blacklist as $name ) {
+                       unset( $query[$name] );
+               }
+               $s = '';
+               foreach ( $query as $name => $value ) {
+                       $s .= Html::hidden( $name, $value ) . "\n";
+               }
+               return $s;
+       }
+
+       /**
+        * Get a form containing a limit selection dropdown
+        *
+        * @return string HTML fragment
+        */
+       function getLimitForm() {
+               return Html::rawElement(
+                       'form',
+                       array(
+                               'method' => 'get',
+                               'action' => wfScript(),
+                       ),
+                       "\n" . $this->getLimitDropdown()
+               ) . "\n";
+       }
+
+       /**
+        * Gets a limit selection dropdown
+        *
+        * @return string
+        */
+       function getLimitDropdown() {
+               # Make the select with some explanatory text
+               $msgSubmit = $this->msg( 'table_pager_limit_submit' )->escaped();
+
+               return $this->msg( 'table_pager_limit' )
+                       ->rawParams( $this->getLimitSelect() )->escaped() .
+                       "\n<input type=\"submit\" value=\"$msgSubmit\"/>\n" .
+                       $this->getHiddenFields( array( 'limit' ) );
+       }
+
+       /**
+        * Return true if the named field should be sortable by the UI, false
+        * otherwise
+        *
+        * @param string $field
+        */
+       abstract function isFieldSortable( $field );
+
+       /**
+        * Format a table cell. The return value should be HTML, but use an empty
+        * string not &#160; for empty cells. Do not include the <td> and </td>.
+        *
+        * The current result row is available as $this->mCurrentRow, in case you
+        * need more context.
+        *
+        * @protected
+        *
+        * @param string $name The database field name
+        * @param string $value The value retrieved from the database
+        */
+       abstract function formatValue( $name, $value );
+
+       /**
+        * The database field name used as a default sort order.
+        *
+        * @protected
+        *
+        * @return string
+        */
+       abstract function getDefaultSort();
+
+       /**
+        * An array mapping database field names to a textual description of the
+        * field name, for use in the table header. The description should be plain
+        * text, it will be HTML-escaped later.
+        *
+        * @return array
+        */
+       abstract function getFieldNames();
+}
index 6fb3e0a..94abc26 100644 (file)
@@ -32,7 +32,7 @@ class CacheTime {
         */
        public $mUsedOptions;
 
-       var     $mVersion = Parser::VERSION,  # Compatibility check
+       public $mVersion = Parser::VERSION,  # Compatibility check
                $mCacheTime = '',             # Time when this object was generated, or -1 for uncacheable. Used in ParserCache.
                $mCacheExpiry = null,         # Seconds after which the object should expire, use 0 for uncachable. Used in ParserCache.
                $mContainsOldMagic,           # Boolean variable indicating if the input contained variables like {{CURRENTDAY}}
@@ -41,14 +41,14 @@ class CacheTime {
        /**
         * @return string TS_MW timestamp
         */
-       function getCacheTime() {
+       public function getCacheTime() {
                return wfTimestamp( TS_MW, $this->mCacheTime );
        }
 
        /**
         * @return bool
         */
-       function containsOldMagic() {
+       public function containsOldMagic() {
                return $this->mContainsOldMagic;
        }
 
@@ -56,7 +56,7 @@ class CacheTime {
         * @param bool $com
         * @return bool
         */
-       function setContainsOldMagic( $com ) {
+       public function setContainsOldMagic( $com ) {
                return wfSetVar( $this->mContainsOldMagic, $com );
        }
 
@@ -66,7 +66,7 @@ class CacheTime {
         * @param string $t
         * @return string
         */
-       function setCacheTime( $t ) {
+       public function setCacheTime( $t ) {
                return wfSetVar( $this->mCacheTime, $t );
        }
 
@@ -74,7 +74,7 @@ class CacheTime {
         * @since 1.23
         * @return int|null Revision id, if any was set
         */
-       function getCacheRevisionId() {
+       public function getCacheRevisionId() {
                return $this->mCacheRevisionId;
        }
 
@@ -82,7 +82,7 @@ class CacheTime {
         * @since 1.23
         * @param int $id Revision id
         */
-       function setCacheRevisionId( $id ) {
+       public function setCacheRevisionId( $id ) {
                $this->mCacheRevisionId = $id;
        }
 
@@ -96,7 +96,7 @@ class CacheTime {
         *
         * @param int $seconds
         */
-       function updateCacheExpiry( $seconds ) {
+       public function updateCacheExpiry( $seconds ) {
                $seconds = (int)$seconds;
 
                if ( $this->mCacheExpiry === null || $this->mCacheExpiry > $seconds ) {
@@ -118,7 +118,7 @@ class CacheTime {
         * value of $wgParserCacheExpireTime.
         * @return int|mixed|null
         */
-       function getCacheExpiry() {
+       public function getCacheExpiry() {
                global $wgParserCacheExpireTime;
 
                if ( $this->mCacheTime < 0 ) {
@@ -147,7 +147,7 @@ class CacheTime {
        /**
         * @return bool
         */
-       function isCacheable() {
+       public function isCacheable() {
                return $this->getCacheExpiry() > 0;
        }
 
index 79c8ade..eacbecd 100644 (file)
@@ -30,10 +30,10 @@ class CoreParserFunctions {
         * @param Parser $parser
         * @return void
         */
-       static function register( $parser ) {
+       public static function register( $parser ) {
                global $wgAllowDisplayTitle, $wgAllowSlowParserFunctions;
 
-               # Syntax for arguments (see self::setFunctionHook):
+               # Syntax for arguments (see Parser::setFunctionHook):
                #  "name for lookup in localized magic words array",
                #  function callback,
                #  optional SFH_NO_HASH to omit the hash from calls (e.g. {{int:...}}
@@ -84,7 +84,7 @@ class CoreParserFunctions {
         * @param string $part1
         * @return array
         */
-       static function intFunction( $parser, $part1 = '' /*, ... */ ) {
+       public static function intFunction( $parser, $part1 = '' /*, ... */ ) {
                if ( strval( $part1 ) !== '' ) {
                        $args = array_slice( func_get_args(), 2 );
                        $message = wfMessage( $part1, $args )
@@ -103,7 +103,7 @@ class CoreParserFunctions {
         *
         * @return string
         */
-       static function formatDate( $parser, $date, $defaultPref = null ) {
+       public static function formatDate( $parser, $date, $defaultPref = null ) {
                $lang = $parser->getFunctionLang();
                $df = DateFormatter::getInstance( $lang );
 
@@ -121,7 +121,7 @@ class CoreParserFunctions {
                return $date;
        }
 
-       static function ns( $parser, $part1 = '' ) {
+       public static function ns( $parser, $part1 = '' ) {
                global $wgContLang;
                if ( intval( $part1 ) || $part1 == "0" ) {
                        $index = intval( $part1 );
@@ -135,7 +135,7 @@ class CoreParserFunctions {
                }
        }
 
-       static function nse( $parser, $part1 = '' ) {
+       public static function nse( $parser, $part1 = '' ) {
                $ret = self::ns( $parser, $part1 );
                if ( is_string( $ret ) ) {
                        $ret = wfUrlencode( str_replace( ' ', '_', $ret ) );
@@ -155,7 +155,7 @@ class CoreParserFunctions {
         * @param string $arg (optional): The type of encoding.
         * @return string
         */
-       static function urlencode( $parser, $s = '', $arg = null ) {
+       public static function urlencode( $parser, $s = '', $arg = null ) {
                static $magicWords = null;
                if ( is_null( $magicWords ) ) {
                        $magicWords = new MagicWordArray( array( 'url_path', 'url_query', 'url_wiki' ) );
@@ -181,12 +181,12 @@ class CoreParserFunctions {
                return $parser->markerSkipCallback( $s, $func );
        }
 
-       static function lcfirst( $parser, $s = '' ) {
+       public static function lcfirst( $parser, $s = '' ) {
                global $wgContLang;
                return $wgContLang->lcfirst( $s );
        }
 
-       static function ucfirst( $parser, $s = '' ) {
+       public static function ucfirst( $parser, $s = '' ) {
                global $wgContLang;
                return $wgContLang->ucfirst( $s );
        }
@@ -196,7 +196,7 @@ class CoreParserFunctions {
         * @param string $s
         * @return string
         */
-       static function lc( $parser, $s = '' ) {
+       public static function lc( $parser, $s = '' ) {
                global $wgContLang;
                return $parser->markerSkipCallback( $s, array( $wgContLang, 'lc' ) );
        }
@@ -206,16 +206,16 @@ class CoreParserFunctions {
         * @param string $s
         * @return string
         */
-       static function uc( $parser, $s = '' ) {
+       public static function uc( $parser, $s = '' ) {
                global $wgContLang;
                return $parser->markerSkipCallback( $s, array( $wgContLang, 'uc' ) );
        }
 
-       static function localurl( $parser, $s = '', $arg = null ) {
+       public static function localurl( $parser, $s = '', $arg = null ) {
                return self::urlFunction( 'getLocalURL', $s, $arg );
        }
 
-       static function localurle( $parser, $s = '', $arg = null ) {
+       public static function localurle( $parser, $s = '', $arg = null ) {
                $temp = self::urlFunction( 'getLocalURL', $s, $arg );
                if ( !is_string( $temp ) ) {
                        return $temp;
@@ -224,11 +224,11 @@ class CoreParserFunctions {
                }
        }
 
-       static function fullurl( $parser, $s = '', $arg = null ) {
+       public static function fullurl( $parser, $s = '', $arg = null ) {
                return self::urlFunction( 'getFullURL', $s, $arg );
        }
 
-       static function fullurle( $parser, $s = '', $arg = null ) {
+       public static function fullurle( $parser, $s = '', $arg = null ) {
                $temp = self::urlFunction( 'getFullURL', $s, $arg );
                if ( !is_string( $temp ) ) {
                        return $temp;
@@ -237,11 +237,11 @@ class CoreParserFunctions {
                }
        }
 
-       static function canonicalurl( $parser, $s = '', $arg = null ) {
+       public static function canonicalurl( $parser, $s = '', $arg = null ) {
                return self::urlFunction( 'getCanonicalURL', $s, $arg );
        }
 
-       static function canonicalurle( $parser, $s = '', $arg = null ) {
+       public static function canonicalurle( $parser, $s = '', $arg = null ) {
                $temp = self::urlFunction( 'getCanonicalURL', $s, $arg );
                if ( !is_string( $temp ) ) {
                        return $temp;
@@ -250,7 +250,7 @@ class CoreParserFunctions {
                }
        }
 
-       static function urlFunction( $func, $s = '', $arg = null ) {
+       public static function urlFunction( $func, $s = '', $arg = null ) {
                $title = Title::newFromText( $s );
                # Due to order of execution of a lot of bits, the values might be encoded
                # before arriving here; if that's true, then the title can't be created
@@ -281,7 +281,7 @@ class CoreParserFunctions {
         * @param string $arg
         * @return string
         */
-       static function formatnum( $parser, $num = '', $arg = null ) {
+       public static function formatnum( $parser, $num = '', $arg = null ) {
                if ( self::matchAgainstMagicword( 'rawsuffix', $arg ) ) {
                        $func = array( $parser->getFunctionLang(), 'parseFormattedNumber' );
                } elseif ( self::matchAgainstMagicword( 'nocommafysuffix', $arg ) ) {
@@ -298,7 +298,7 @@ class CoreParserFunctions {
         * @param string $word
         * @return string
         */
-       static function grammar( $parser, $case = '', $word = '' ) {
+       public static function grammar( $parser, $case = '', $word = '' ) {
                $word = $parser->killMarkers( $word );
                return $parser->getFunctionLang()->convertGrammar( $word, $case );
        }
@@ -308,7 +308,7 @@ class CoreParserFunctions {
         * @param string $username
         * @return string
         */
-       static function gender( $parser, $username ) {
+       public static function gender( $parser, $username ) {
                wfProfileIn( __METHOD__ );
                $forms = array_slice( func_get_args(), 2 );
 
@@ -350,7 +350,7 @@ class CoreParserFunctions {
         * @param string $text
         * @return string
         */
-       static function plural( $parser, $text = '' ) {
+       public static function plural( $parser, $text = '' ) {
                $forms = array_slice( func_get_args(), 2 );
                $text = $parser->getFunctionLang()->parseFormattedNumber( $text );
                settype( $text, ctype_digit( $text ) ? 'int' : 'float' );
@@ -363,11 +363,18 @@ class CoreParserFunctions {
         *
         * @param Parser $parser Parent parser
         * @param string $text Desired title text
+        * @param string $uarg
         * @return string
         */
-       static function displaytitle( $parser, $text = '' ) {
+       public static function displaytitle( $parser, $text = '', $uarg = '' ) {
                global $wgRestrictDisplayTitle;
 
+               static $magicWords = null;
+               if ( is_null( $magicWords ) ) {
+                       $magicWords = new MagicWordArray( array( 'displaytitle_noerror', 'displaytitle_noreplace' ) );
+               }
+               $arg = $magicWords->matchStartToEnd( $uarg );
+
                // parse a limited subset of wiki markup (just the single quote items)
                $text = $parser->doQuotes( $text );
 
@@ -413,13 +420,25 @@ class CoreParserFunctions {
                ) );
                $title = Title::newFromText( Sanitizer::stripAllTags( $text ) );
 
-               if ( !$wgRestrictDisplayTitle ) {
-                       $parser->mOutput->setDisplayTitle( $text );
-               } elseif ( $title instanceof Title
+               if ( !$wgRestrictDisplayTitle ||
+                       ( $title instanceof Title
                        && !$title->hasFragment()
-                       && $title->equals( $parser->mTitle )
+                       && $title->equals( $parser->mTitle ) )
                ) {
-                       $parser->mOutput->setDisplayTitle( $text );
+                       $old = $parser->mOutput->getProperty( 'displaytitle' );
+                       if ( $old === false || $arg !== 'displaytitle_noreplace' ) {
+                               $parser->mOutput->setDisplayTitle( $text );
+                       }
+                       if ( $old !== false && $old !== $text && !$arg ) {
+                               $converter = $parser->getConverterLanguage()->getConverter();
+                               return '<span class="error">' .
+                                       wfMessage( 'duplicate-displaytitle',
+                                               // Message should be parsed, but these params should only be escaped.
+                                               $converter->markNoConversion( wfEscapeWikiText( $old ) ),
+                                               $converter->markNoConversion( wfEscapeWikiText( $text ) )
+                                       )->inContentLanguage()->text() .
+                                       '</span>';
+                       }
                }
 
                return '';
@@ -441,7 +460,7 @@ class CoreParserFunctions {
                return $mwObject->matchStartToEnd( $value );
        }
 
-       static function formatRaw( $num, $raw ) {
+       public static function formatRaw( $num, $raw ) {
                if ( self::matchAgainstMagicword( 'rawsuffix', $raw ) ) {
                        return $num;
                } else {
@@ -449,35 +468,35 @@ class CoreParserFunctions {
                        return $wgContLang->formatNum( $num );
                }
        }
-       static function numberofpages( $parser, $raw = null ) {
+       public static function numberofpages( $parser, $raw = null ) {
                return self::formatRaw( SiteStats::pages(), $raw );
        }
-       static function numberofusers( $parser, $raw = null ) {
+       public static function numberofusers( $parser, $raw = null ) {
                return self::formatRaw( SiteStats::users(), $raw );
        }
-       static function numberofactiveusers( $parser, $raw = null ) {
+       public static function numberofactiveusers( $parser, $raw = null ) {
                return self::formatRaw( SiteStats::activeUsers(), $raw );
        }
-       static function numberofarticles( $parser, $raw = null ) {
+       public static function numberofarticles( $parser, $raw = null ) {
                return self::formatRaw( SiteStats::articles(), $raw );
        }
-       static function numberoffiles( $parser, $raw = null ) {
+       public static function numberoffiles( $parser, $raw = null ) {
                return self::formatRaw( SiteStats::images(), $raw );
        }
-       static function numberofadmins( $parser, $raw = null ) {
+       public static function numberofadmins( $parser, $raw = null ) {
                return self::formatRaw( SiteStats::numberingroup( 'sysop' ), $raw );
        }
-       static function numberofedits( $parser, $raw = null ) {
+       public static function numberofedits( $parser, $raw = null ) {
                return self::formatRaw( SiteStats::edits(), $raw );
        }
-       static function numberofviews( $parser, $raw = null ) {
+       public static function numberofviews( $parser, $raw = null ) {
                global $wgDisableCounters;
                return !$wgDisableCounters ? self::formatRaw( SiteStats::views(), $raw ) : '';
        }
-       static function pagesinnamespace( $parser, $namespace = 0, $raw = null ) {
+       public static function pagesinnamespace( $parser, $namespace = 0, $raw = null ) {
                return self::formatRaw( SiteStats::pagesInNs( intval( $namespace ) ), $raw );
        }
-       static function numberingroup( $parser, $name = '', $raw = null ) {
+       public static function numberingroup( $parser, $name = '', $raw = null ) {
                return self::formatRaw( SiteStats::numberingroup( strtolower( $name ) ), $raw );
        }
 
@@ -490,49 +509,49 @@ class CoreParserFunctions {
         * @param string $title
         * @return mixed|string
         */
-       static function mwnamespace( $parser, $title = null ) {
+       public static function mwnamespace( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return str_replace( '_', ' ', $t->getNsText() );
        }
-       static function namespacee( $parser, $title = null ) {
+       public static function namespacee( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return wfUrlencode( $t->getNsText() );
        }
-       static function namespacenumber( $parser, $title = null ) {
+       public static function namespacenumber( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return $t->getNamespace();
        }
-       static function talkspace( $parser, $title = null ) {
+       public static function talkspace( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) || !$t->canTalk() ) {
                        return '';
                }
                return str_replace( '_', ' ', $t->getTalkNsText() );
        }
-       static function talkspacee( $parser, $title = null ) {
+       public static function talkspacee( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) || !$t->canTalk() ) {
                        return '';
                }
                return wfUrlencode( $t->getTalkNsText() );
        }
-       static function subjectspace( $parser, $title = null ) {
+       public static function subjectspace( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return str_replace( '_', ' ', $t->getSubjectNsText() );
        }
-       static function subjectspacee( $parser, $title = null ) {
+       public static function subjectspacee( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
@@ -547,98 +566,98 @@ class CoreParserFunctions {
         * @param string $title
         * @return string
         */
-       static function pagename( $parser, $title = null ) {
+       public static function pagename( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return wfEscapeWikiText( $t->getText() );
        }
-       static function pagenamee( $parser, $title = null ) {
+       public static function pagenamee( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return wfEscapeWikiText( $t->getPartialURL() );
        }
-       static function fullpagename( $parser, $title = null ) {
+       public static function fullpagename( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) || !$t->canTalk() ) {
                        return '';
                }
                return wfEscapeWikiText( $t->getPrefixedText() );
        }
-       static function fullpagenamee( $parser, $title = null ) {
+       public static function fullpagenamee( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) || !$t->canTalk() ) {
                        return '';
                }
                return wfEscapeWikiText( $t->getPrefixedURL() );
        }
-       static function subpagename( $parser, $title = null ) {
+       public static function subpagename( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return wfEscapeWikiText( $t->getSubpageText() );
        }
-       static function subpagenamee( $parser, $title = null ) {
+       public static function subpagenamee( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return wfEscapeWikiText( $t->getSubpageUrlForm() );
        }
-       static function rootpagename( $parser, $title = null ) {
+       public static function rootpagename( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return wfEscapeWikiText( $t->getRootText() );
        }
-       static function rootpagenamee( $parser, $title = null ) {
+       public static function rootpagenamee( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return wfEscapeWikiText( wfUrlEncode( str_replace( ' ', '_', $t->getRootText() ) ) );
        }
-       static function basepagename( $parser, $title = null ) {
+       public static function basepagename( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return wfEscapeWikiText( $t->getBaseText() );
        }
-       static function basepagenamee( $parser, $title = null ) {
+       public static function basepagenamee( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return wfEscapeWikiText( wfUrlEncode( str_replace( ' ', '_', $t->getBaseText() ) ) );
        }
-       static function talkpagename( $parser, $title = null ) {
+       public static function talkpagename( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) || !$t->canTalk() ) {
                        return '';
                }
                return wfEscapeWikiText( $t->getTalkPage()->getPrefixedText() );
        }
-       static function talkpagenamee( $parser, $title = null ) {
+       public static function talkpagenamee( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) || !$t->canTalk() ) {
                        return '';
                }
                return wfEscapeWikiText( $t->getTalkPage()->getPrefixedURL() );
        }
-       static function subjectpagename( $parser, $title = null ) {
+       public static function subjectpagename( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
                }
                return wfEscapeWikiText( $t->getSubjectPage()->getPrefixedText() );
        }
-       static function subjectpagenamee( $parser, $title = null ) {
+       public static function subjectpagenamee( $parser, $title = null ) {
                $t = Title::newFromText( $title );
                if ( is_null( $t ) ) {
                        return '';
@@ -656,7 +675,7 @@ class CoreParserFunctions {
         * @param string $arg2
         * @return string
         */
-       static function pagesincategory( $parser, $name = '', $arg1 = null, $arg2 = null ) {
+       public static function pagesincategory( $parser, $name = '', $arg1 = null, $arg2 = null ) {
                global $wgContLang;
                static $magicWords = null;
                if ( is_null( $magicWords ) ) {
@@ -723,7 +742,7 @@ class CoreParserFunctions {
         * @param string $raw Should number be human readable with commas or just number
         * @return string
         */
-       static function pagesize( $parser, $page = '', $raw = null ) {
+       public static function pagesize( $parser, $page = '', $raw = null ) {
                $title = Title::newFromText( $page );
 
                if ( !is_object( $title ) ) {
@@ -748,7 +767,7 @@ class CoreParserFunctions {
         *
         * @return string
         */
-       static function protectionlevel( $parser, $type = '', $title = '' ) {
+       public static function protectionlevel( $parser, $type = '', $title = '' ) {
                $titleObject = Title::newFromText( $title );
                if ( !( $titleObject instanceof Title ) ) {
                        $titleObject = $parser->mTitle;
@@ -769,7 +788,7 @@ class CoreParserFunctions {
         * @param string $inLanguage Language code (in which to get name)
         * @return string
         */
-       static function language( $parser, $code = '', $inLanguage = '' ) {
+       public static function language( $parser, $code = '', $inLanguage = '' ) {
                $code = strtolower( $code );
                $inLanguage = strtolower( $inLanguage );
                $lang = Language::fetchLanguageName( $code, $inLanguage );
@@ -785,7 +804,7 @@ class CoreParserFunctions {
         * @param int $direction
         * @return string
         */
-       static function pad( $parser, $string, $length, $padding = '0', $direction = STR_PAD_RIGHT ) {
+       public static function pad( $parser, $string, $length, $padding = '0', $direction = STR_PAD_RIGHT ) {
                $padding = $parser->killMarkers( $padding );
                $lengthOfPadding = mb_strlen( $padding );
                if ( $lengthOfPadding == 0 ) {
@@ -811,11 +830,11 @@ class CoreParserFunctions {
                }
        }
 
-       static function padleft( $parser, $string = '', $length = 0, $padding = '0' ) {
+       public static function padleft( $parser, $string = '', $length = 0, $padding = '0' ) {
                return self::pad( $parser, $string, $length, $padding, STR_PAD_LEFT );
        }
 
-       static function padright( $parser, $string = '', $length = 0, $padding = '0' ) {
+       public static function padright( $parser, $string = '', $length = 0, $padding = '0' ) {
                return self::pad( $parser, $string, $length, $padding );
        }
 
@@ -824,12 +843,12 @@ class CoreParserFunctions {
         * @param string $text
         * @return string
         */
-       static function anchorencode( $parser, $text ) {
+       public static function anchorencode( $parser, $text ) {
                $text = $parser->killMarkers( $text );
                return (string)substr( $parser->guessSectionNameFromWikiText( $text ), 1 );
        }
 
-       static function special( $parser, $text ) {
+       public static function special( $parser, $text ) {
                list( $page, $subpage ) = SpecialPageFactory::resolveAlias( $text );
                if ( $page ) {
                        $title = SpecialPage::getTitleFor( $page, $subpage );
@@ -841,7 +860,7 @@ class CoreParserFunctions {
                }
        }
 
-       static function speciale( $parser, $text ) {
+       public static function speciale( $parser, $text ) {
                return wfUrlencode( str_replace( ' ', '_', self::special( $parser, $text ) ) );
        }
 
@@ -981,7 +1000,10 @@ class CoreParserFunctions {
         * @since 1.23
         */
        private static function getCachedRevisionObject( $parser, $title = null ) {
-               static $cache = array();
+               static $cache = null;
+               if ( $cache == null ) {
+                       $cache = new MapCacheLRU( 50 );
+               }
 
                if ( is_null( $title ) ) {
                        return null;
@@ -1002,21 +1024,21 @@ class CoreParserFunctions {
                // Normalize name for cache
                $page = $title->getPrefixedDBkey();
 
-               if ( array_key_exists( $page, $cache ) ) { // cache contains null values
-                       return $cache[$page];
+               if ( $cache->has( $page ) ) { // cache contains null values
+                       return $cache->get( $page );
                }
                if ( $parser->incrementExpensiveFunctionCount() ) {
                        $rev = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
                        $pageID = $rev ? $rev->getPage() : 0;
                        $revID = $rev ? $rev->getId() : 0;
-                       $cache[$page] = $rev; // maybe null
+                       $cache->set( $page, $rev ); // maybe null
 
                        // Register dependency in templatelinks
                        $parser->getOutput()->addTemplate( $title, $pageID, $revID );
 
                        return $rev;
                }
-               $cache[$page] = null;
+               $cache->set( $page, null );
                return null;
        }
 
index 01ad97c..85920cc 100644 (file)
@@ -30,7 +30,7 @@ class CoreTagHooks {
         * @param Parser $parser
         * @return void
         */
-       static function register( $parser ) {
+       public static function register( $parser ) {
                global $wgRawHtml;
                $parser->setHook( 'pre', array( __CLASS__, 'pre' ) );
                $parser->setHook( 'nowiki', array( __CLASS__, 'nowiki' ) );
@@ -50,7 +50,7 @@ class CoreTagHooks {
         * @param Parser $parser
         * @return string HTML
         */
-       static function pre( $text, $attribs, $parser ) {
+       public static function pre( $text, $attribs, $parser ) {
                // Backwards-compatibility hack
                $content = StringUtils::delimiterReplace( '<nowiki>', '</nowiki>', '$1', $text, 'i' );
 
@@ -75,7 +75,7 @@ class CoreTagHooks {
         * @throws MWException
         * @return array
         */
-       static function html( $content, $attributes, $parser ) {
+       public static function html( $content, $attributes, $parser ) {
                global $wgRawHtml;
                if ( $wgRawHtml ) {
                        return array( $content, 'markerType' => 'nowiki' );
@@ -96,7 +96,7 @@ class CoreTagHooks {
         * @param Parser $parser
         * @return array
         */
-       static function nowiki( $content, $attributes, $parser ) {
+       public static function nowiki( $content, $attributes, $parser ) {
                $content = strtr( $content, array( '-{' => '-&#123;', '}-' => '&#125;-' ) );
                return array( Xml::escapeTagsOnly( $content ), 'markerType' => 'nowiki' );
        }
@@ -116,7 +116,7 @@ class CoreTagHooks {
         * @param Parser $parser
         * @return string HTML
         */
-       static function gallery( $content, $attributes, $parser ) {
+       public static function gallery( $content, $attributes, $parser ) {
                return $parser->renderImageGallery( $content, $attributes );
        }
 }
index cfd5370..82f0e9d 100644 (file)
  * @ingroup Parser
  */
 class DateFormatter {
-       var $mSource, $mTarget;
-       var $monthNames = '', $rxDM, $rxMD, $rxDMY, $rxYDM, $rxMDY, $rxYMD;
+       public $mSource, $mTarget;
+       public $monthNames = '', $rxDM, $rxMD, $rxDMY, $rxYDM, $rxMDY, $rxYMD;
 
-       var $regexes, $pDays, $pMonths, $pYears;
-       var $rules, $xMonths, $preferences;
+       public $regexes, $pDays, $pMonths, $pYears;
+       public $rules, $xMonths, $preferences;
 
        protected $lang;
 
@@ -51,7 +51,7 @@ class DateFormatter {
        /**
         * @param Language $lang In which language to format the date
         */
-       function __construct( Language $lang ) {
+       public function __construct( Language $lang ) {
                $this->lang = $lang;
 
                $this->monthNames = $this->getMonthRegex();
@@ -122,7 +122,7 @@ class DateFormatter {
         *
         * @param Language|string|null $lang In which language to format the date
         *              Defaults to the site content language
-        * @return DateFormatter object
+        * @return DateFormatter
         */
        public static function &getInstance( $lang = null ) {
                global $wgMemc, $wgContLang;
@@ -146,7 +146,7 @@ class DateFormatter {
         *
         * @return string
         */
-       function reformat( $preference, $text, $options = array( 'linked' ) ) {
+       public function reformat( $preference, $text, $options = array( 'linked' ) ) {
                $linked = in_array( 'linked', $options );
                $match_whole = in_array( 'match-whole', $options );
 
@@ -196,7 +196,7 @@ class DateFormatter {
         * @param array $matches
         * @return string
         */
-       function replace( $matches ) {
+       public function replace( $matches ) {
                # Extract information from $matches
                $linked = true;
                if ( isset( $this->mLinked ) ) {
@@ -220,7 +220,7 @@ class DateFormatter {
         * @param bool $link
         * @return string
         */
-       function formatDate( $bits, $link = true ) {
+       public function formatDate( $bits, $link = true ) {
                $format = $this->targets[$this->mTarget];
 
                if ( !$link ) {
@@ -318,7 +318,7 @@ class DateFormatter {
         * @todo document
         * @return string
         */
-       function getMonthRegex() {
+       public function getMonthRegex() {
                $names = array();
                for ( $i = 1; $i <= 12; $i++ ) {
                        $names[] = $this->lang->getMonthName( $i );
@@ -332,7 +332,7 @@ class DateFormatter {
         * @param string $monthName Month name
         * @return string ISO month name
         */
-       function makeIsoMonth( $monthName ) {
+       public function makeIsoMonth( $monthName ) {
                $n = $this->xMonths[$this->lang->lc( $monthName )];
                return sprintf( '%02d', $n );
        }
@@ -342,7 +342,7 @@ class DateFormatter {
         * @param string $year Year name
         * @return string ISO year name
         */
-       function makeIsoYear( $year ) {
+       public function makeIsoYear( $year ) {
                # Assumes the year is in a nice format, as enforced by the regex
                if ( substr( $year, -2 ) == 'BC' ) {
                        $num = intval( substr( $year, 0, -3 ) ) - 1;
@@ -360,7 +360,7 @@ class DateFormatter {
         * @param string $iso
         * @return int|string
         */
-       function makeNormalYear( $iso ) {
+       public function makeNormalYear( $iso ) {
                if ( $iso[0] == '-' ) {
                        $text = ( intval( substr( $iso, 1 ) ) + 1 ) . ' BC';
                } else {
index 648667b..7794fae 100644 (file)
  * @ingroup Parser
  */
 class LinkHolderArray {
-       var $internals = array(), $interwikis = array();
-       var $size = 0;
+       public $internals = array();
+       public $interwikis = array();
+       public $size = 0;
 
        /**
         * @var Parser
         */
-       var $parent;
+       public $parent;
        protected $tempIdOffset;
 
        /**
         * @param Parser $parent
         */
-       function __construct( $parent ) {
+       public function __construct( $parent ) {
                $this->parent = $parent;
        }
 
        /**
         * Reduce memory usage to reduce the impact of circular references
         */
-       function __destruct() {
+       public function __destruct() {
                foreach ( $this as $name => $value ) {
                        unset( $this->$name );
                }
@@ -58,7 +59,7 @@ class LinkHolderArray {
         * Compact the titles, only serialize the text form.
         * @return array
         */
-       function __sleep() {
+       public function __sleep() {
                foreach ( $this->internals as &$nsLinks ) {
                        foreach ( $nsLinks as &$entry ) {
                                unset( $entry['title'] );
@@ -78,7 +79,7 @@ class LinkHolderArray {
        /**
         * Recreate the Title objects
         */
-       function __wakeup() {
+       public function __wakeup() {
                foreach ( $this->internals as &$nsLinks ) {
                        foreach ( $nsLinks as &$entry ) {
                                $entry['title'] = Title::newFromText( $entry['pdbk'] );
@@ -97,7 +98,7 @@ class LinkHolderArray {
         * Merge another LinkHolderArray into this one
         * @param LinkHolderArray $other
         */
-       function merge( $other ) {
+       public function merge( $other ) {
                foreach ( $other->internals as $ns => $entries ) {
                        $this->size += count( $entries );
                        if ( !isset( $this->internals[$ns] ) ) {
@@ -121,7 +122,7 @@ class LinkHolderArray {
         * @param array $texts Array of strings
         * @return array
         */
-       function mergeForeign( $other, $texts ) {
+       public function mergeForeign( $other, $texts ) {
                $this->tempIdOffset = $idOffset = $this->parent->nextLinkID();
                $maxId = 0;
 
@@ -165,7 +166,7 @@ class LinkHolderArray {
         * @param string $text
         * @return LinkHolderArray
         */
-       function getSubArray( $text ) {
+       public function getSubArray( $text ) {
                $sub = new LinkHolderArray( $this->parent );
 
                # Internal links
@@ -199,7 +200,7 @@ class LinkHolderArray {
         * Returns true if the memory requirements of this object are getting large
         * @return bool
         */
-       function isBig() {
+       public function isBig() {
                global $wgLinkHolderBatchSize;
                return $this->size > $wgLinkHolderBatchSize;
        }
@@ -208,7 +209,7 @@ class LinkHolderArray {
         * Clear all stored link holders.
         * Make sure you don't have any text left using these link holders, before you call this
         */
-       function clear() {
+       public function clear() {
                $this->internals = array();
                $this->interwikis = array();
                $this->size = 0;
@@ -227,7 +228,7 @@ class LinkHolderArray {
         * @param string $prefix [optional]
         * @return string
         */
-       function makeHolder( $nt, $text = '', $query = array(), $trail = '', $prefix = '' ) {
+       public function makeHolder( $nt, $text = '', $query = array(), $trail = '', $prefix = '' ) {
                wfProfileIn( __METHOD__ );
                if ( !is_object( $nt ) ) {
                        # Fail gracefully
@@ -265,10 +266,10 @@ class LinkHolderArray {
        /**
         * Replace <!--LINK--> link placeholders with actual links, in the buffer
         *
-        * @param $text
+        * @param string $text
         * @return array Array of link CSS classes, indexed by PDBK.
         */
-       function replace( &$text ) {
+       public function replace( &$text ) {
                wfProfileIn( __METHOD__ );
 
                /** @todo FIXME: replaceInternal doesn't return a value */
@@ -289,7 +290,7 @@ class LinkHolderArray {
                }
 
                wfProfileIn( __METHOD__ );
-               global $wgContLang;
+               global $wgContLang, $wgContentHandlerUseDB;
 
                $colours = array();
                $linkCache = LinkCache::singleton();
@@ -347,10 +348,16 @@ class LinkHolderArray {
                                );
                        }
 
+                       $fields = array( 'page_id', 'page_namespace', 'page_title',
+                               'page_is_redirect', 'page_len', 'page_latest' );
+
+                       if ( $wgContentHandlerUseDB ) {
+                               $fields[] = 'page_content_model';
+                       }
+
                        $res = $dbr->select(
                                'page',
-                               array( 'page_id', 'page_namespace', 'page_title',
-                                       'page_is_redirect', 'page_len', 'page_latest' ),
+                               $fields,
                                $dbr->makeList( $where, LIST_OR ),
                                __METHOD__
                        );
@@ -464,7 +471,7 @@ class LinkHolderArray {
         * @param array $colours
         */
        protected function doVariants( &$colours ) {
-               global $wgContLang;
+               global $wgContLang, $wgContentHandlerUseDB;
                $linkBatch = new LinkBatch();
                $variantMap = array(); // maps $pdbkey_Variant => $keys (of link holders)
                $output = $this->parent->getOutput();
@@ -553,9 +560,15 @@ class LinkHolderArray {
                if ( !$linkBatch->isEmpty() ) {
                        // construct query
                        $dbr = wfGetDB( DB_SLAVE );
+                       $fields = array( 'page_id', 'page_namespace', 'page_title',
+                               'page_is_redirect', 'page_len', 'page_latest' );
+
+                       if ( $wgContentHandlerUseDB ) {
+                               $fields[] = 'page_content_model';
+                       }
+
                        $varRes = $dbr->select( 'page',
-                               array( 'page_id', 'page_namespace', 'page_title',
-                                       'page_is_redirect', 'page_len', 'page_latest' ),
+                               $fields,
                                $linkBatch->constructSet( 'page', $dbr ),
                                __METHOD__
                        );
@@ -630,7 +643,7 @@ class LinkHolderArray {
         * @param string $text
         * @return string
         */
-       function replaceText( $text ) {
+       public function replaceText( $text ) {
                wfProfileIn( __METHOD__ );
 
                $text = preg_replace_callback(
@@ -649,7 +662,7 @@ class LinkHolderArray {
         * @return string
         * @private
         */
-       function replaceTextCallback( $matches ) {
+       public function replaceTextCallback( $matches ) {
                $type = $matches[1];
                $key = $matches[2];
                if ( $type == 'LINK' ) {
diff --git a/includes/parser/MWTidy.php b/includes/parser/MWTidy.php
new file mode 100644 (file)
index 0000000..b310862
--- /dev/null
@@ -0,0 +1,291 @@
+<?php
+/**
+ * HTML validation and correction
+ *
+ * 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 Parser
+ */
+
+/**
+ * Class used to hide mw:editsection tokens from Tidy so that it doesn't break them
+ * or break on them. This is a bit of a hack for now, but hopefully in the future
+ * we may create a real postprocessor or something that will replace this.
+ * It's called wrapper because for now it basically takes over MWTidy::tidy's task
+ * of wrapping the text in a xhtml block
+ *
+ * This re-uses some of the parser's UNIQ tricks, though some of it is private so it's
+ * duplicated. Perhaps we should create an abstract marker hiding class.
+ *
+ * @ingroup Parser
+ */
+class MWTidyWrapper {
+
+       /**
+        * @var ReplacementArray
+        */
+       protected $mTokens;
+
+       protected $mUniqPrefix;
+
+       protected $mMarkerIndex;
+
+       public function __construct() {
+               $this->mTokens = null;
+               $this->mUniqPrefix = null;
+       }
+
+       /**
+        * @param string $text
+        * @return string
+        */
+       public function getWrapped( $text ) {
+               $this->mTokens = new ReplacementArray;
+               $this->mUniqPrefix = "\x7fUNIQ" .
+                       dechex( mt_rand( 0, 0x7fffffff ) ) . dechex( mt_rand( 0, 0x7fffffff ) );
+               $this->mMarkerIndex = 0;
+
+               // Replace <mw:editsection> elements with placeholders
+               $wrappedtext = preg_replace_callback( ParserOutput::EDITSECTION_REGEX,
+                       array( &$this, 'replaceCallback' ), $text );
+               // ...and <mw:toc> markers
+               $wrappedtext = preg_replace_callback( '/\<\\/?mw:toc\>/',
+                       array( &$this, 'replaceCallback' ), $wrappedtext );
+               // ... and <math> tags
+               $wrappedtext = preg_replace_callback( '/\<math(.*?)\<\\/math\>/s',
+                       array( &$this, 'replaceCallback' ), $wrappedtext );
+               // Modify inline Microdata <link> and <meta> elements so they say <html-link> and <html-meta> so
+               // we can trick Tidy into not stripping them out by including them in tidy's new-empty-tags config
+               $wrappedtext = preg_replace( '!<(link|meta)([^>]*?)(/{0,1}>)!', '<html-$1$2$3', $wrappedtext );
+
+               // Wrap the whole thing in a doctype and body for Tidy.
+               $wrappedtext = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' .
+                       ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html>' .
+                       '<head><title>test</title></head><body>' . $wrappedtext . '</body></html>';
+
+               return $wrappedtext;
+       }
+
+       /**
+        * @param array $m
+        *
+        * @return string
+        */
+       public function replaceCallback( $m ) {
+               $marker = "{$this->mUniqPrefix}-item-{$this->mMarkerIndex}" . Parser::MARKER_SUFFIX;
+               $this->mMarkerIndex++;
+               $this->mTokens->setPair( $marker, $m[0] );
+               return $marker;
+       }
+
+       /**
+        * @param string $text
+        * @return string
+        */
+       public function postprocess( $text ) {
+               // Revert <html-{link,meta}> back to <{link,meta}>
+               $text = preg_replace( '!<html-(link|meta)([^>]*?)(/{0,1}>)!', '<$1$2$3', $text );
+
+               // Restore the contents of placeholder tokens
+               $text = $this->mTokens->replace( $text );
+
+               return $text;
+       }
+
+}
+
+/**
+ * Class to interact with HTML tidy
+ *
+ * Either the external tidy program or the in-process tidy extension
+ * will be used depending on availability. Override the default
+ * $wgTidyInternal setting to disable the internal if it's not working.
+ *
+ * @ingroup Parser
+ */
+class MWTidy {
+       /**
+        * Interface with html tidy, used if $wgUseTidy = true.
+        * If tidy isn't able to correct the markup, the original will be
+        * returned in all its glory with a warning comment appended.
+        *
+        * @param string $text Hideous HTML input
+        * @return string Corrected HTML output
+        */
+       public static function tidy( $text ) {
+               global $wgTidyInternal;
+
+               $wrapper = new MWTidyWrapper;
+               $wrappedtext = $wrapper->getWrapped( $text );
+
+               $retVal = null;
+               if ( $wgTidyInternal ) {
+                       $correctedtext = self::execInternalTidy( $wrappedtext, false, $retVal );
+               } else {
+                       $correctedtext = self::execExternalTidy( $wrappedtext, false, $retVal );
+               }
+
+               if ( $retVal < 0 ) {
+                       wfDebug( "Possible tidy configuration error!\n" );
+                       return $text . "\n<!-- Tidy was unable to run -->\n";
+               } elseif ( is_null( $correctedtext ) ) {
+                       wfDebug( "Tidy error detected!\n" );
+                       return $text . "\n<!-- Tidy found serious XHTML errors -->\n";
+               }
+
+               $correctedtext = $wrapper->postprocess( $correctedtext ); // restore any hidden tokens
+
+               return $correctedtext;
+       }
+
+       /**
+        * Check HTML for errors, used if $wgValidateAllHtml = true.
+        *
+        * @param string $text
+        * @param string &$errorStr Return the error string
+        * @return bool Whether the HTML is valid
+        */
+       public static function checkErrors( $text, &$errorStr = null ) {
+               global $wgTidyInternal;
+
+               $retval = 0;
+               if ( $wgTidyInternal ) {
+                       $errorStr = self::execInternalTidy( $text, true, $retval );
+               } else {
+                       $errorStr = self::execExternalTidy( $text, true, $retval );
+               }
+
+               return ( $retval < 0 && $errorStr == '' ) || $retval == 0;
+       }
+
+       /**
+        * Spawn an external HTML tidy process and get corrected markup back from it.
+        * Also called in OutputHandler.php for full page validation
+        *
+        * @param string $text HTML to check
+        * @param bool $stderr Whether to read result from STDERR rather than STDOUT
+        * @param int &$retval Exit code (-1 on internal error)
+        * @return string|null
+        */
+       private static function execExternalTidy( $text, $stderr = false, &$retval = null ) {
+               global $wgTidyConf, $wgTidyBin, $wgTidyOpts;
+               wfProfileIn( __METHOD__ );
+
+               $cleansource = '';
+               $opts = ' -utf8';
+
+               if ( $stderr ) {
+                       $descriptorspec = array(
+                               0 => array( 'pipe', 'r' ),
+                               1 => array( 'file', wfGetNull(), 'a' ),
+                               2 => array( 'pipe', 'w' )
+                       );
+               } else {
+                       $descriptorspec = array(
+                               0 => array( 'pipe', 'r' ),
+                               1 => array( 'pipe', 'w' ),
+                               2 => array( 'file', wfGetNull(), 'a' )
+                       );
+               }
+
+               $readpipe = $stderr ? 2 : 1;
+               $pipes = array();
+
+               $process = proc_open(
+                       "$wgTidyBin -config $wgTidyConf $wgTidyOpts$opts", $descriptorspec, $pipes );
+
+               //NOTE: At least on linux, the process will be created even if tidy is not installed.
+               //      This means that missing tidy will be treated as a validation failure.
+
+               if ( is_resource( $process ) ) {
+                       // Theoretically, this style of communication could cause a deadlock
+                       // here. If the stdout buffer fills up, then writes to stdin could
+                       // block. This doesn't appear to happen with tidy, because tidy only
+                       // writes to stdout after it's finished reading from stdin. Search
+                       // for tidyParseStdin and tidySaveStdout in console/tidy.c
+                       fwrite( $pipes[0], $text );
+                       fclose( $pipes[0] );
+                       while ( !feof( $pipes[$readpipe] ) ) {
+                               $cleansource .= fgets( $pipes[$readpipe], 1024 );
+                       }
+                       fclose( $pipes[$readpipe] );
+                       $retval = proc_close( $process );
+               } else {
+                       wfWarn( "Unable to start external tidy process" );
+                       $retval = -1;
+               }
+
+               if ( !$stderr && $cleansource == '' && $text != '' ) {
+                       // Some kind of error happened, so we couldn't get the corrected text.
+                       // Just give up; we'll use the source text and append a warning.
+                       $cleansource = null;
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $cleansource;
+       }
+
+       /**
+        * Use the HTML tidy extension to use the tidy library in-process,
+        * saving the overhead of spawning a new process.
+        *
+        * @param string $text HTML to check
+        * @param bool $stderr Whether to read result from error status instead of output
+        * @param int &$retval Exit code (-1 on internal error)
+        * @return string|null
+        */
+       private static function execInternalTidy( $text, $stderr = false, &$retval = null ) {
+               global $wgTidyConf, $wgDebugTidy;
+               wfProfileIn( __METHOD__ );
+
+               if ( !class_exists( 'tidy' ) ) {
+                       wfWarn( "Unable to load internal tidy class." );
+                       $retval = -1;
+
+                       wfProfileOut( __METHOD__ );
+                       return null;
+               }
+
+               $tidy = new tidy;
+               $tidy->parseString( $text, $wgTidyConf, 'utf8' );
+
+               if ( $stderr ) {
+                       $retval = $tidy->getStatus();
+
+                       wfProfileOut( __METHOD__ );
+                       return $tidy->errorBuffer;
+               }
+
+               $tidy->cleanRepair();
+               $retval = $tidy->getStatus();
+               if ( $retval == 2 ) {
+                       // 2 is magic number for fatal error
+                       // http://www.php.net/manual/en/function.tidy-get-status.php
+                       $cleansource = null;
+               } else {
+                       $cleansource = tidy_get_output( $tidy );
+                       if ( $wgDebugTidy && $retval > 0 ) {
+                               $cleansource .= "<!--\nTidy reports:\n" .
+                                       str_replace( '-->', '--&gt;', $tidy->errorBuffer ) .
+                                       "\n-->";
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $cleansource;
+       }
+}
index e5917b8..8bf400a 100644 (file)
@@ -120,61 +120,61 @@ class Parser {
        const TOC_END = '</mw:toc>';
 
        # Persistent:
-       var $mTagHooks = array();
-       var $mTransparentTagHooks = array();
-       var $mFunctionHooks = array();
-       var $mFunctionSynonyms = array( 0 => array(), 1 => array() );
-       var $mFunctionTagHooks = array();
-       var $mStripList = array();
-       var $mDefaultStripList = array();
-       var $mVarCache = array();
-       var $mImageParams = array();
-       var $mImageParamsMagicArray = array();
-       var $mMarkerIndex = 0;
-       var $mFirstCall = true;
+       public $mTagHooks = array();
+       public $mTransparentTagHooks = array();
+       public $mFunctionHooks = array();
+       public $mFunctionSynonyms = array( 0 => array(), 1 => array() );
+       public $mFunctionTagHooks = array();
+       public $mStripList = array();
+       public $mDefaultStripList = array();
+       public $mVarCache = array();
+       public $mImageParams = array();
+       public $mImageParamsMagicArray = array();
+       public $mMarkerIndex = 0;
+       public $mFirstCall = true;
 
        # Initialised by initialiseVariables()
 
        /**
         * @var MagicWordArray
         */
-       var $mVariables;
+       public $mVariables;
 
        /**
         * @var MagicWordArray
         */
-       var $mSubstWords;
-       var $mConf, $mPreprocessor, $mExtLinkBracketedRegex, $mUrlProtocols; # Initialised in constructor
+       public $mSubstWords;
+       public $mConf, $mPreprocessor, $mExtLinkBracketedRegex, $mUrlProtocols; # Initialised in constructor
 
        # Cleared with clearState():
        /**
         * @var ParserOutput
         */
-       var $mOutput;
-       var $mAutonumber, $mDTopen;
+       public $mOutput;
+       public $mAutonumber, $mDTopen;
 
        /**
         * @var StripState
         */
-       var $mStripState;
+       public $mStripState;
 
-       var $mIncludeCount, $mArgStack, $mLastSection, $mInPre;
+       public $mIncludeCount, $mArgStack, $mLastSection, $mInPre;
        /**
         * @var LinkHolderArray
         */
-       var $mLinkHolders;
+       public $mLinkHolders;
 
-       var $mLinkID;
-       var $mIncludeSizes, $mPPNodeCount, $mGeneratedPPNodeCount, $mHighestExpansionDepth;
-       var $mDefaultSort;
-       var $mTplRedirCache, $mTplDomCache, $mHeadings, $mDoubleUnderscores;
-       var $mExpensiveFunctionCount; # number of expensive parser function calls
-       var $mShowToc, $mForceTocPosition;
+       public $mLinkID;
+       public $mIncludeSizes, $mPPNodeCount, $mGeneratedPPNodeCount, $mHighestExpansionDepth;
+       public $mDefaultSort;
+       public $mTplRedirCache, $mTplDomCache, $mHeadings, $mDoubleUnderscores;
+       public $mExpensiveFunctionCount; # number of expensive parser function calls
+       public $mShowToc, $mForceTocPosition;
 
        /**
         * @var User
         */
-       var $mUser; # User object; only used when doing pre-save transform
+       public $mUser; # User object; only used when doing pre-save transform
 
        # Temporary
        # These are variables reset at least once per parse regardless of $clearState
@@ -182,36 +182,36 @@ class Parser {
        /**
         * @var ParserOptions
         */
-       var $mOptions;
+       public $mOptions;
 
        /**
         * @var Title
         */
-       var $mTitle;        # Title context, used for self-link rendering and similar things
-       var $mOutputType;   # Output type, one of the OT_xxx constants
-       var $ot;            # Shortcut alias, see setOutputType()
-       var $mRevisionObject; # The revision object of the specified revision ID
-       var $mRevisionId;   # ID to display in {{REVISIONID}} tags
-       var $mRevisionTimestamp; # The timestamp of the specified revision ID
-       var $mRevisionUser; # User to display in {{REVISIONUSER}} tag
-       var $mRevisionSize; # Size to display in {{REVISIONSIZE}} variable
-       var $mRevIdForTs;   # The revision ID which was used to fetch the timestamp
-       var $mInputSize = false; # For {{PAGESIZE}} on current page.
+       public $mTitle;        # Title context, used for self-link rendering and similar things
+       public $mOutputType;   # Output type, one of the OT_xxx constants
+       public $ot;            # Shortcut alias, see setOutputType()
+       public $mRevisionObject; # The revision object of the specified revision ID
+       public $mRevisionId;   # ID to display in {{REVISIONID}} tags
+       public $mRevisionTimestamp; # The timestamp of the specified revision ID
+       public $mRevisionUser; # User to display in {{REVISIONUSER}} tag
+       public $mRevisionSize; # Size to display in {{REVISIONSIZE}} variable
+       public $mRevIdForTs;   # The revision ID which was used to fetch the timestamp
+       public $mInputSize = false; # For {{PAGESIZE}} on current page.
 
        /**
         * @var string
         */
-       var $mUniqPrefix;
+       public $mUniqPrefix;
 
        /**
         * @var array Array with the language name of each language link (i.e. the
         * interwiki prefix) in the key, value arbitrary. Used to avoid sending
         * duplicate language links to the ParserOutput.
         */
-       var $mLangLinkLanguages;
+       public $mLangLinkLanguages;
 
        /**
-        * @var boolean Recursive call protection.
+        * @var bool Recursive call protection.
         * This variable should be treated as if it were private.
         */
        public $mInParse = false;
@@ -244,7 +244,7 @@ class Parser {
        /**
         * Reduce memory usage to reduce the impact of circular references
         */
-       function __destruct() {
+       public function __destruct() {
                if ( isset( $this->mLinkHolders ) ) {
                        unset( $this->mLinkHolders );
                }
@@ -256,7 +256,7 @@ class Parser {
        /**
         * Allow extensions to clean up when the parser is cloned
         */
-       function __clone() {
+       public function __clone() {
                $this->mInParse = false;
                wfRunHooks( 'ParserCloned', array( $this ) );
        }
@@ -264,7 +264,7 @@ class Parser {
        /**
         * Do various kinds of initialisation on the first call of the parser
         */
-       function firstCallInit() {
+       public function firstCallInit() {
                if ( !$this->mFirstCall ) {
                        return;
                }
@@ -285,7 +285,7 @@ class Parser {
         *
         * @private
         */
-       function clearState() {
+       public function clearState() {
                wfProfileIn( __METHOD__ );
                if ( $this->mFirstCall ) {
                        $this->firstCallInit();
@@ -349,7 +349,7 @@ class Parser {
         * Convert wikitext to HTML
         * Do not call this function recursively.
         *
-        * @param string $text text we want to parse
+        * @param string $text Text we want to parse
         * @param Title $title
         * @param ParserOptions $options
         * @param bool $linestart
@@ -605,7 +605,7 @@ class Parser {
         *
         * @return string
         */
-       function recursiveTagParse( $text, $frame = false ) {
+       public function recursiveTagParse( $text, $frame = false ) {
                wfProfileIn( __METHOD__ );
                wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
                wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
@@ -625,7 +625,7 @@ class Parser {
         * @param bool|PPFrame $frame
         * @return mixed|string
         */
-       function preprocess( $text, Title $title = null, ParserOptions $options, $revid = null, $frame = false ) {
+       public function preprocess( $text, Title $title = null, ParserOptions $options, $revid = null, $frame = false ) {
                wfProfileIn( __METHOD__ );
                $magicScopeVariable = $this->lock();
                $this->startParse( $title, $options, self::OT_PREPROCESS, true );
@@ -700,7 +700,7 @@ class Parser {
         *
         * @param User|null $user User object or null (to reset)
         */
-       function setUser( $user ) {
+       public function setUser( $user ) {
                $this->mUser = $user;
        }
 
@@ -727,7 +727,7 @@ class Parser {
         *
         * @param Title $t
         */
-       function setTitle( $t ) {
+       public function setTitle( $t ) {
                if ( !$t ) {
                        $t = Title::newFromText( 'NO TITLE' );
                }
@@ -746,7 +746,7 @@ class Parser {
         *
         * @return Title
         */
-       function getTitle() {
+       public function getTitle() {
                return $this->mTitle;
        }
 
@@ -756,7 +756,7 @@ class Parser {
         * @param Title $x Title object or null to just get the current one
         * @return Title
         */
-       function Title( $x = null ) {
+       public function Title( $x = null ) {
                return wfSetVar( $this->mTitle, $x );
        }
 
@@ -765,7 +765,7 @@ class Parser {
         *
         * @param int $ot New value
         */
-       function setOutputType( $ot ) {
+       public function setOutputType( $ot ) {
                $this->mOutputType = $ot;
                # Shortcut alias
                $this->ot = array(
@@ -782,7 +782,7 @@ class Parser {
         * @param int|null $x New value or null to just get the current one
         * @return int
         */
-       function OutputType( $x = null ) {
+       public function OutputType( $x = null ) {
                return wfSetVar( $this->mOutputType, $x );
        }
 
@@ -791,16 +791,16 @@ class Parser {
         *
         * @return ParserOutput
         */
-       function getOutput() {
+       public function getOutput() {
                return $this->mOutput;
        }
 
        /**
         * Get the ParserOptions object
         *
-        * @return ParserOptions object
+        * @return ParserOptions
         */
-       function getOptions() {
+       public function getOptions() {
                return $this->mOptions;
        }
 
@@ -810,21 +810,21 @@ class Parser {
         * @param ParserOptions $x New value or null to just get the current one
         * @return ParserOptions Current ParserOptions object
         */
-       function Options( $x = null ) {
+       public function Options( $x = null ) {
                return wfSetVar( $this->mOptions, $x );
        }
 
        /**
         * @return int
         */
-       function nextLinkID() {
+       public function nextLinkID() {
                return $this->mLinkID++;
        }
 
        /**
         * @param int $id
         */
-       function setLinkID( $id ) {
+       public function setLinkID( $id ) {
                $this->mLinkID = $id;
        }
 
@@ -832,7 +832,7 @@ class Parser {
         * Get a language object for use in parser functions such as {{FORMATNUM:}}
         * @return Language
         */
-       function getFunctionLang() {
+       public function getFunctionLang() {
                return $this->getTargetLanguage();
        }
 
@@ -843,7 +843,7 @@ class Parser {
         * @since 1.19
         *
         * @throws MWException
-        * @return Language|null
+        * @return Language
         */
        public function getTargetLanguage() {
                $target = $this->mOptions->getTargetLanguage();
@@ -863,7 +863,7 @@ class Parser {
         * Get the language object for language conversion
         * @return Language|null
         */
-       function getConverterLanguage() {
+       public function getConverterLanguage() {
                return $this->getTargetLanguage();
        }
 
@@ -873,7 +873,7 @@ class Parser {
         *
         * @return User
         */
-       function getUser() {
+       public function getUser() {
                if ( !is_null( $this->mUser ) ) {
                        return $this->mUser;
                }
@@ -885,7 +885,7 @@ class Parser {
         *
         * @return Preprocessor
         */
-       function getPreprocessor() {
+       public function getPreprocessor() {
                if ( !isset( $this->mPreprocessor ) ) {
                        $class = $this->mPreprocessorClass;
                        $this->mPreprocessor = new $class( $this );
@@ -980,7 +980,7 @@ class Parser {
         *
         * @return array
         */
-       function getStripList() {
+       public function getStripList() {
                return $this->mStripList;
        }
 
@@ -993,7 +993,7 @@ class Parser {
         *
         * @return string
         */
-       function insertStripItem( $text ) {
+       public function insertStripItem( $text ) {
                $rnd = "{$this->mUniqPrefix}-item-{$this->mMarkerIndex}-" . self::MARKER_SUFFIX;
                $this->mMarkerIndex++;
                $this->mStripState->addGeneral( $rnd, $text );
@@ -1007,7 +1007,7 @@ class Parser {
         * @param string $text
         * @return string
         */
-       function doTableStuff( $text ) {
+       public function doTableStuff( $text ) {
                wfProfileIn( __METHOD__ );
 
                $lines = StringUtils::explode( "\n", $text );
@@ -1212,7 +1212,7 @@ class Parser {
         *
         * @return string
         */
-       function internalParse( $text, $isMain = true, $frame = false ) {
+       public function internalParse( $text, $isMain = true, $frame = false ) {
                wfProfileIn( __METHOD__ );
 
                $origText = $text;
@@ -1285,7 +1285,7 @@ class Parser {
         *
         * @return string
         */
-       function doMagicLinks( $text ) {
+       public function doMagicLinks( $text ) {
                wfProfileIn( __METHOD__ );
                $prots = wfUrlProtocolsWithoutProtRel();
                $urlChar = self::EXT_LINK_URL_CLASS;
@@ -1310,7 +1310,7 @@ class Parser {
         * @param array $m
         * @return HTML|string
         */
-       function magicLinkCallback( $m ) {
+       public function magicLinkCallback( $m ) {
                if ( isset( $m[1] ) && $m[1] !== '' ) {
                        # Skip anchor
                        return $m[0];
@@ -1363,7 +1363,7 @@ class Parser {
         * @return string HTML
         * @private
         */
-       function makeFreeExternalLink( $url ) {
+       public function makeFreeExternalLink( $url ) {
                wfProfileIn( __METHOD__ );
 
                $trail = '';
@@ -1418,7 +1418,7 @@ class Parser {
         *
         * @return string
         */
-       function doHeadings( $text ) {
+       public function doHeadings( $text ) {
                wfProfileIn( __METHOD__ );
                for ( $i = 6; $i >= 1; --$i ) {
                        $h = str_repeat( '=', $i );
@@ -1434,9 +1434,9 @@ class Parser {
         *
         * @param string $text
         *
-        * @return string the altered text
+        * @return string The altered text
         */
-       function doAllQuotes( $text ) {
+       public function doAllQuotes( $text ) {
                wfProfileIn( __METHOD__ );
                $outtext = '';
                $lines = StringUtils::explode( "\n", $text );
@@ -1645,7 +1645,7 @@ class Parser {
         * @throws MWException
         * @return string
         */
-       function replaceExternalLinks( $text ) {
+       public function replaceExternalLinks( $text ) {
                wfProfileIn( __METHOD__ );
 
                $bits = preg_split( $this->mExtLinkBracketedRegex, $text, -1, PREG_SPLIT_DELIM_CAPTURE );
@@ -1748,7 +1748,7 @@ class Parser {
         *   nofollow if appropriate
         * @return array Associative array of HTML attributes
         */
-       function getExternalLinkAttribs( $url = false ) {
+       public function getExternalLinkAttribs( $url = false ) {
                $attribs = array();
                $attribs['rel'] = self::getExternalLinkRel( $url, $this->mTitle );
 
@@ -1769,7 +1769,7 @@ class Parser {
         *       the URL differently; as a workaround, just use the output for
         *       statistical records, not for actual linking/output.
         */
-       static function replaceUnusualEscapes( $url ) {
+       public static function replaceUnusualEscapes( $url ) {
                return preg_replace_callback( '/%[0-9A-Fa-f]{2}/',
                        array( __CLASS__, 'replaceUnusualEscapesCallback' ), $url );
        }
@@ -1862,7 +1862,7 @@ class Parser {
         *
         * @private
         */
-       function replaceInternalLinks( $s ) {
+       public function replaceInternalLinks( $s ) {
                $this->mLinkHolders->merge( $this->replaceInternalLinks2( $s ) );
                return $s;
        }
@@ -1875,7 +1875,7 @@ class Parser {
         *
         * @private
         */
-       function replaceInternalLinks2( &$s ) {
+       public function replaceInternalLinks2( &$s ) {
                global $wgExtraInterlanguageLinkPrefixes;
                wfProfileIn( __METHOD__ );
 
@@ -2002,10 +2002,12 @@ class Parser {
                        wfProfileOut( __METHOD__ . "-e1" );
                        wfProfileIn( __METHOD__ . "-misc" );
 
+                       $origLink = $m[1];
+
                        # Don't allow internal links to pages containing
                        # PROTO: where PROTO is a valid URL protocol; these
                        # should be external links.
-                       if ( preg_match( '/^(?i:' . $this->mUrlProtocols . ')/', $m[1] ) ) {
+                       if ( preg_match( '/^(?i:' . $this->mUrlProtocols . ')/', $origLink ) ) {
                                $s .= $prefix . '[[' . $line;
                                wfProfileOut( __METHOD__ . "-misc" );
                                continue;
@@ -2013,12 +2015,12 @@ class Parser {
 
                        # Make subpage if necessary
                        if ( $useSubpages ) {
-                               $link = $this->maybeDoSubpageLink( $m[1], $text );
+                               $link = $this->maybeDoSubpageLink( $origLink, $text );
                        } else {
-                               $link = $m[1];
+                               $link = $origLink;
                        }
 
-                       $noforce = ( substr( $m[1], 0, 1 ) !== ':' );
+                       $noforce = ( substr( $origLink, 0, 1 ) !== ':' );
                        if ( !$noforce ) {
                                # Strip off leading ':'
                                $link = substr( $link, 1 );
@@ -2094,7 +2096,7 @@ class Parser {
                        }
 
                        # Link not escaped by : , create the various objects
-                       if ( $noforce ) {
+                       if ( $noforce && !$nt->wasLocalInterwiki() ) {
                                # Interwikis
                                wfProfileIn( __METHOD__ . "-interwiki" );
                                if (
@@ -2225,7 +2227,7 @@ class Parser {
         * @param string $prefix
         * @return string HTML-wikitext mix oh yuck
         */
-       function makeKnownLinkHolder( $nt, $text = '', $query = array(), $trail = '', $prefix = '' ) {
+       public function makeKnownLinkHolder( $nt, $text = '', $query = array(), $trail = '', $prefix = '' ) {
                list( $inside, $trail ) = Linker::splitTrail( $trail );
 
                if ( is_string( $query ) ) {
@@ -2250,7 +2252,7 @@ class Parser {
         * @param string $text More-or-less HTML
         * @return string Less-or-more HTML with NOPARSE bits
         */
-       function armorLinks( $text ) {
+       public function armorLinks( $text ) {
                return preg_replace( '/\b((?i)' . $this->mUrlProtocols . ')/',
                        "{$this->mUniqPrefix}NOPARSE$1", $text );
        }
@@ -2259,7 +2261,7 @@ class Parser {
         * Return true if subpage links should be expanded on this page.
         * @return bool
         */
-       function areSubpagesAllowed() {
+       public function areSubpagesAllowed() {
                # Some namespaces don't allow subpages
                return MWNamespace::hasSubpages( $this->mTitle->getNamespace() );
        }
@@ -2272,7 +2274,7 @@ class Parser {
         * @return string The full name of the link
         * @private
         */
-       function maybeDoSubpageLink( $target, &$text ) {
+       public function maybeDoSubpageLink( $target, &$text ) {
                return Linker::normalizeSubpageLink( $this->mTitle, $target, $text );
        }
 
@@ -2282,7 +2284,7 @@ class Parser {
         *
         * @return string
         */
-       function closeParagraph() {
+       public function closeParagraph() {
                $result = '';
                if ( $this->mLastSection != '' ) {
                        $result = '</' . $this->mLastSection . ">\n";
@@ -2302,7 +2304,7 @@ class Parser {
         *
         * @return int
         */
-       function getCommon( $st1, $st2 ) {
+       public function getCommon( $st1, $st2 ) {
                $fl = strlen( $st1 );
                $shorter = strlen( $st2 );
                if ( $fl < $shorter ) {
@@ -2326,7 +2328,7 @@ class Parser {
         *
         * @return string
         */
-       function openList( $char ) {
+       public function openList( $char ) {
                $result = $this->closeParagraph();
 
                if ( '*' === $char ) {
@@ -2352,7 +2354,7 @@ class Parser {
         *
         * @return string
         */
-       function nextItem( $char ) {
+       public function nextItem( $char ) {
                if ( '*' === $char || '#' === $char ) {
                        return "</li>\n<li>";
                } elseif ( ':' === $char || ';' === $char ) {
@@ -2378,7 +2380,7 @@ class Parser {
         *
         * @return string
         */
-       function closeList( $char ) {
+       public function closeList( $char ) {
                if ( '*' === $char ) {
                        $text = "</li></ul>";
                } elseif ( '#' === $char ) {
@@ -2405,7 +2407,7 @@ class Parser {
         * @private
         * @return string The lists rendered as HTML
         */
-       function doBlockLevels( $text, $linestart ) {
+       public function doBlockLevels( $text, $linestart ) {
                wfProfileIn( __METHOD__ );
 
                # Parsing through the text line by line.  The main thing
@@ -2623,7 +2625,7 @@ class Parser {
         * @throws MWException
         * @return string The position of the ':', or false if none found
         */
-       function findColonNoLinks( $str, &$before, &$after ) {
+       public function findColonNoLinks( $str, &$before, &$after ) {
                wfProfileIn( __METHOD__ );
 
                $pos = strpos( $str, ':' );
@@ -2791,7 +2793,7 @@ class Parser {
         * @throws MWException
         * @return string
         */
-       function getVariableValue( $index, $frame = false ) {
+       public function getVariableValue( $index, $frame = false ) {
                global $wgContLang, $wgSitename, $wgServer, $wgServerName;
                global $wgArticlePath, $wgScriptPath, $wgStylePath;
 
@@ -3147,7 +3149,7 @@ class Parser {
         *
         * @private
         */
-       function initialiseVariables() {
+       public function initialiseVariables() {
                wfProfileIn( __METHOD__ );
                $variableIDs = MagicWord::getVariableIDs();
                $substIDs = MagicWord::getSubstIDs();
@@ -3179,7 +3181,7 @@ class Parser {
         *
         * @return PPNode
         */
-       function preprocessToDom( $text, $flags = 0 ) {
+       public function preprocessToDom( $text, $flags = 0 ) {
                $dom = $this->getPreprocessor()->preprocessToObj( $text, $flags );
                return $dom;
        }
@@ -3254,7 +3256,7 @@ class Parser {
         *
         * @return array
         */
-       static function createAssocArgs( $args ) {
+       public static function createAssocArgs( $args ) {
                $assocArgs = array();
                $index = 1;
                foreach ( $args as $arg ) {
@@ -3300,7 +3302,7 @@ class Parser {
         * @param string|int|null $max Maximum allowed, when an explicit limit has been
         *       exceeded, provide the values (optional)
         */
-       function limitationWarn( $limitationType, $current = '', $max = '' ) {
+       public function limitationWarn( $limitationType, $current = '', $max = '' ) {
                # does no harm if $current and $max are present but are unnecessary for the message
                $warning = wfMessage( "$limitationType-warning" )->numParams( $current, $max )
                        ->inLanguage( $this->mOptions->getUserLangObj() )->text();
@@ -3760,7 +3762,7 @@ class Parser {
         *
         * @return array
         */
-       function getTemplateDom( $title ) {
+       public function getTemplateDom( $title ) {
                $cacheTitle = $title;
                $titleText = $title->getPrefixedDBkey();
 
@@ -3797,7 +3799,7 @@ class Parser {
         * @param Title $title
         * @return array ( string or false, Title )
         */
-       function fetchTemplateAndTitle( $title ) {
+       public function fetchTemplateAndTitle( $title ) {
                // Defaults to Parser::statelessFetchTemplate()
                $templateCb = $this->mOptions->getTemplateCallback();
                $stuff = call_user_func( $templateCb, $title, $this );
@@ -3821,7 +3823,7 @@ class Parser {
         * @param Title $title
         * @return string|bool
         */
-       function fetchTemplate( $title ) {
+       public function fetchTemplate( $title ) {
                $rv = $this->fetchTemplateAndTitle( $title );
                return $rv[0];
        }
@@ -3835,7 +3837,7 @@ class Parser {
         *
         * @return array
         */
-       static function statelessFetchTemplate( $title, $parser = false ) {
+       public static function statelessFetchTemplate( $title, $parser = false ) {
                $text = $skip = false;
                $finalTitle = $title;
                $deps = array();
@@ -3919,7 +3921,7 @@ class Parser {
         * @param array $options Array of options to RepoGroup::findFile
         * @return File|bool
         */
-       function fetchFile( $title, $options = array() ) {
+       public function fetchFile( $title, $options = array() ) {
                $res = $this->fetchFileAndTitle( $title, $options );
                return $res[0];
        }
@@ -3931,7 +3933,7 @@ class Parser {
         * @param array $options Array of options to RepoGroup::findFile
         * @return array ( File or false, Title of file )
         */
-       function fetchFileAndTitle( $title, $options = array() ) {
+       public function fetchFileAndTitle( $title, $options = array() ) {
                $file = $this->fetchFileNoRegister( $title, $options );
 
                $time = $file ? $file->getTimestamp() : false;
@@ -3975,7 +3977,7 @@ class Parser {
         *
         * @return string
         */
-       function interwikiTransclude( $title, $action ) {
+       public function interwikiTransclude( $title, $action ) {
                global $wgEnableScaryTranscluding;
 
                if ( !$wgEnableScaryTranscluding ) {
@@ -3994,7 +3996,7 @@ class Parser {
         * @param string $url
         * @return mixed|string
         */
-       function fetchScaryTemplateMaybeFromCache( $url ) {
+       public function fetchScaryTemplateMaybeFromCache( $url ) {
                global $wgTranscludeCacheExpiry;
                $dbr = wfGetDB( DB_SLAVE );
                $tsCond = $dbr->timestamp( time() - $wgTranscludeCacheExpiry );
@@ -4034,7 +4036,7 @@ class Parser {
         *
         * @return array
         */
-       function argSubstitution( $piece, $frame ) {
+       public function argSubstitution( $piece, $frame ) {
                wfProfileIn( __METHOD__ );
 
                $error = false;
@@ -4089,7 +4091,7 @@ class Parser {
         * @throws MWException
         * @return string
         */
-       function extensionSubstitution( $params, $frame ) {
+       public function extensionSubstitution( $params, $frame ) {
                $name = $frame->expand( $params['name'] );
                $attrText = !isset( $params['attr'] ) ? null : $frame->expand( $params['attr'] );
                $content = !isset( $params['inner'] ) ? null : $frame->expand( $params['inner'] );
@@ -4173,7 +4175,7 @@ class Parser {
         * @param int $size The size of the text
         * @return bool False if this inclusion would take it over the maximum, true otherwise
         */
-       function incrementIncludeSize( $type, $size ) {
+       public function incrementIncludeSize( $type, $size ) {
                if ( $this->mIncludeSizes[$type] + $size > $this->mOptions->getMaxIncludeSize() ) {
                        return false;
                } else {
@@ -4187,7 +4189,7 @@ class Parser {
         *
         * @return bool False if the limit has been exceeded
         */
-       function incrementExpensiveFunctionCount() {
+       public function incrementExpensiveFunctionCount() {
                $this->mExpensiveFunctionCount++;
                return $this->mExpensiveFunctionCount <= $this->mOptions->getExpensiveParserFunctionLimit();
        }
@@ -4200,7 +4202,7 @@ class Parser {
         *
         * @return string
         */
-       function doDoubleUnderscore( $text ) {
+       public function doDoubleUnderscore( $text ) {
                wfProfileIn( __METHOD__ );
 
                # The position of __TOC__ needs to be recorded
@@ -4306,7 +4308,7 @@ class Parser {
         * @return mixed|string
         * @private
         */
-       function formatHeadings( $text, $origText, $isMain = true ) {
+       public function formatHeadings( $text, $origText, $isMain = true ) {
                global $wgMaxTocLevel, $wgExperimentalHtmlIds;
 
                # Inhibit editsection links if requested in the page
@@ -4595,13 +4597,13 @@ class Parser {
                                if ( $isTemplate ) {
                                        # Put a T flag in the section identifier, to indicate to extractSections()
                                        # that sections inside <includeonly> should be counted.
-                                       $editlinkArgs = array( $titleText, "T-$sectionIndex"/*, null */ );
+                                       $editsectionPage = $titleText;
+                                       $editsectionSection = "T-$sectionIndex";
+                                       $editsectionContent = null;
                                } else {
-                                       $editlinkArgs = array(
-                                               $this->mTitle->getPrefixedText(),
-                                               $sectionIndex,
-                                               $headlineHint
-                                       );
+                                       $editsectionPage = $this->mTitle->getPrefixedText();
+                                       $editsectionSection = $sectionIndex;
+                                       $editsectionContent = $headlineHint;
                                }
                                // We use a bit of pesudo-xml for editsection markers. The
                                // language converter is run later on. Using a UNIQ style marker
@@ -4614,10 +4616,11 @@ class Parser {
                                // important bits of data, but put the headline hint inside a
                                // content block because the language converter is supposed to
                                // be able to convert that piece of data.
-                               $editlink = '<mw:editsection page="' . htmlspecialchars( $editlinkArgs[0] );
-                               $editlink .= '" section="' . htmlspecialchars( $editlinkArgs[1] ) . '"';
-                               if ( isset( $editlinkArgs[2] ) ) {
-                                       $editlink .= '>' . $editlinkArgs[2] . '</mw:editsection>';
+                               // Gets replaced with html in ParserOutput::getText
+                               $editlink = '<mw:editsection page="' . htmlspecialchars( $editsectionPage );
+                               $editlink .= '" section="' . htmlspecialchars( $editsectionSection ) . '"';
+                               if ( $editsectionContent !== null ) {
+                                       $editlink .= '>' . $editsectionContent . '</mw:editsection>';
                                } else {
                                        $editlink .= '/>';
                                }
@@ -4826,7 +4829,7 @@ class Parser {
         *    or null to use default value
         * @return string
         */
-       function getUserSig( &$user, $nickname = false, $fancySig = null ) {
+       public function getUserSig( &$user, $nickname = false, $fancySig = null ) {
                global $wgMaxSigChars;
 
                $username = $user->getName();
@@ -4875,7 +4878,7 @@ class Parser {
         * @param string $text
         * @return string|bool An expanded string, or false if invalid.
         */
-       function validateSig( $text ) {
+       public function validateSig( $text ) {
                return Xml::isWellFormedXmlFragment( $text ) ? $text : false;
        }
 
@@ -5048,7 +5051,7 @@ class Parser {
         * @throws MWException
         * @return callable|null The old value of the mTagHooks array associated with the hook
         */
-       function setTransparentTagHook( $tag, $callback ) {
+       public function setTransparentTagHook( $tag, $callback ) {
                $tag = strtolower( $tag );
                if ( preg_match( '/[<>\r\n]/', $tag, $m ) ) {
                        throw new MWException( "Invalid character {$m[0]} in setTransparentHook('$tag', ...) call" );
@@ -5062,7 +5065,7 @@ class Parser {
        /**
         * Remove all tag hooks
         */
-       function clearTagHooks() {
+       public function clearTagHooks() {
                $this->mTagHooks = array();
                $this->mFunctionTagHooks = array();
                $this->mStripList = $this->mDefaultStripList;
@@ -5149,7 +5152,7 @@ class Parser {
         *
         * @return array
         */
-       function getFunctionHooks() {
+       public function getFunctionHooks() {
                return array_keys( $this->mFunctionHooks );
        }
 
@@ -5163,7 +5166,7 @@ class Parser {
         * @throws MWException
         * @return null
         */
-       function setFunctionTagHook( $tag, $callback, $flags ) {
+       public function setFunctionTagHook( $tag, $callback, $flags ) {
                $tag = strtolower( $tag );
                if ( preg_match( '/[<>\r\n]/', $tag, $m ) ) {
                        throw new MWException( "Invalid character {$m[0]} in setFunctionTagHook('$tag', ...) call" );
@@ -5189,7 +5192,7 @@ class Parser {
         *
         * @return array Array of link CSS classes, indexed by PDBK.
         */
-       function replaceLinkHolders( &$text, $options = 0 ) {
+       public function replaceLinkHolders( &$text, $options = 0 ) {
                return $this->mLinkHolders->replace( $text );
        }
 
@@ -5200,7 +5203,7 @@ class Parser {
         * @param string $text
         * @return string
         */
-       function replaceLinkHoldersText( $text ) {
+       public function replaceLinkHoldersText( $text ) {
                return $this->mLinkHolders->replaceText( $text );
        }
 
@@ -5217,7 +5220,7 @@ class Parser {
         * @param array $params
         * @return string HTML
         */
-       function renderImageGallery( $text, $params ) {
+       public function renderImageGallery( $text, $params ) {
                wfProfileIn( __METHOD__ );
 
                $mode = false;
@@ -5378,7 +5381,7 @@ class Parser {
         * @param string $handler
         * @return array
         */
-       function getImageParams( $handler ) {
+       public function getImageParams( $handler ) {
                if ( $handler ) {
                        $handlerClass = get_class( $handler );
                } else {
@@ -5426,7 +5429,7 @@ class Parser {
         * @param LinkHolderArray|bool $holders
         * @return string HTML
         */
-       function makeImage( $title, $options, $holders = false ) {
+       public function makeImage( $title, $options, $holders = false ) {
                # Check if the options text is of the form "options|alt text"
                # Options are:
                #  * thumbnail  make a thumbnail with enlarge-icon and caption, alignment depends on lang
@@ -5525,7 +5528,7 @@ class Parser {
                                                                $paramName = 'no-link';
                                                                $value = true;
                                                                $validated = true;
-                                                       } elseif ( preg_match( "/^(?i)$prots/", $value ) ) {
+                                                       } elseif ( preg_match( "/^((?i)$prots)/", $value ) ) {
                                                                if ( preg_match( "/^((?i)$prots)$chars+$/u", $value, $m ) ) {
                                                                        $paramName = 'link-url';
                                                                        $this->mOutput->addExternalLink( $value );
@@ -5665,7 +5668,7 @@ class Parser {
         * Set a flag in the output object indicating that the content is dynamic and
         * shouldn't be cached.
         */
-       function disableCache() {
+       public function disableCache() {
                wfDebug( "Parser output marked as uncacheable.\n" );
                if ( !$this->mOutput ) {
                        throw new MWException( __METHOD__ .
@@ -5683,7 +5686,7 @@ class Parser {
         * @param bool|PPFrame $frame
         * @return string
         */
-       function attributeStripCallback( &$text, $frame = false ) {
+       public function attributeStripCallback( &$text, $frame = false ) {
                $text = $this->replaceVariables( $text, $frame );
                $text = $this->mStripState->unstripBoth( $text );
                return $text;
@@ -5694,7 +5697,7 @@ class Parser {
         *
         * @return array
         */
-       function getTags() {
+       public function getTags() {
                return array_merge(
                        array_keys( $this->mTransparentTagHooks ),
                        array_keys( $this->mTagHooks ),
@@ -5712,7 +5715,7 @@ class Parser {
         *
         * @return string
         */
-       function replaceTransparentTags( $text ) {
+       public function replaceTransparentTags( $text ) {
                $matches = array();
                $elements = array_keys( $this->mTransparentTagHooks );
                $text = self::extractTagsAndParams( $elements, $text, $matches, $this->mUniqPrefix );
@@ -5913,7 +5916,7 @@ class Parser {
         *
         * @return int|null
         */
-       function getRevisionId() {
+       public function getRevisionId() {
                return $this->mRevisionId;
        }
 
@@ -5940,7 +5943,7 @@ class Parser {
         * the default server-local timestamp
         * @return string
         */
-       function getRevisionTimestamp() {
+       public function getRevisionTimestamp() {
                if ( is_null( $this->mRevisionTimestamp ) ) {
                        wfProfileIn( __METHOD__ );
 
@@ -5967,7 +5970,7 @@ class Parser {
         *
         * @return string User name
         */
-       function getRevisionUser() {
+       public function getRevisionUser() {
                if ( is_null( $this->mRevisionUser ) ) {
                        $revObject = $this->getRevisionObject();
 
@@ -5987,7 +5990,7 @@ class Parser {
         *
         * @return int|null Revision size
         */
-       function getRevisionSize() {
+       public function getRevisionSize() {
                if ( is_null( $this->mRevisionSize ) ) {
                        $revObject = $this->getRevisionObject();
 
@@ -6115,7 +6118,7 @@ class Parser {
         *
         * @return string
         */
-       function testSrvus( $text, Title $title, ParserOptions $options, $outputType = self::OT_HTML ) {
+       public function testSrvus( $text, Title $title, ParserOptions $options, $outputType = self::OT_HTML ) {
                $magicScopeVariable = $this->lock();
                $this->startParse( $title, $options, $outputType, true );
 
@@ -6131,7 +6134,7 @@ class Parser {
         * @param ParserOptions $options
         * @return string
         */
-       function testPst( $text, Title $title, ParserOptions $options ) {
+       public function testPst( $text, Title $title, ParserOptions $options ) {
                return $this->preSaveTransform( $text, $title, $options->getUser(), $options );
        }
 
@@ -6141,7 +6144,7 @@ class Parser {
         * @param ParserOptions $options
         * @return string
         */
-       function testPreprocess( $text, Title $title, ParserOptions $options ) {
+       public function testPreprocess( $text, Title $title, ParserOptions $options ) {
                return $this->testSrvus( $text, $title, $options, self::OT_PREPROCESS );
        }
 
@@ -6161,7 +6164,7 @@ class Parser {
         *
         * @return string
         */
-       function markerSkipCallback( $s, $callback ) {
+       public function markerSkipCallback( $s, $callback ) {
                $i = 0;
                $out = '';
                while ( $i < strlen( $s ) ) {
@@ -6191,7 +6194,7 @@ class Parser {
         * @param string $text Input string
         * @return string
         */
-       function killMarkers( $text ) {
+       public function killMarkers( $text ) {
                return $this->mStripState->killMarkers( $text );
        }
 
@@ -6211,7 +6214,7 @@ class Parser {
         *
         * @return array
         */
-       function serializeHalfParsedText( $text ) {
+       public function serializeHalfParsedText( $text ) {
                wfProfileIn( __METHOD__ );
                $data = array(
                        'text' => $text,
@@ -6238,7 +6241,7 @@ class Parser {
         * @throws MWException
         * @return string
         */
-       function unserializeHalfParsedText( $data ) {
+       public function unserializeHalfParsedText( $data ) {
                if ( !isset( $data['version'] ) || $data['version'] != self::HALF_PARSED_VERSION ) {
                        throw new MWException( __METHOD__ . ': invalid version' );
                }
@@ -6263,7 +6266,7 @@ class Parser {
         *
         * @return bool
         */
-       function isValidHalfParsedText( $data ) {
+       public function isValidHalfParsedText( $data ) {
                return isset( $data['version'] ) && $data['version'] == self::HALF_PARSED_VERSION;
        }
 
index 33f0f96..7952300 100644 (file)
@@ -26,7 +26,7 @@
  * @todo document
  */
 class ParserCache {
-       /** @var MWMemcached  */
+       /** @var MWMemcached */
        private $mMemc;
        /**
         * Get an instance of this object
@@ -95,7 +95,7 @@ class ParserCache {
         * @param ParserOptions $popts
         * @return string
         */
-       function getETag( $article, $popts ) {
+       public function getETag( $article, $popts ) {
                return 'W/"' . $this->getParserOutputKey( $article,
                        $popts->optionsHash( ParserOptions::legacyOptions(), $article->getTitle() ) ) .
                                "--" . $article->getTouched() . '"';
index 2db0597..174c1d6 100644 (file)
  */
 class ParserDiffTest
 {
-       var $parsers, $conf;
-       var $shortOutput = false;
+       public $parsers;
+       public $conf;
+       public $shortOutput = false;
+       public $dtUniqPrefix;
 
-       var $dtUniqPrefix;
-
-       function __construct( $conf ) {
+       public function __construct( $conf ) {
                if ( !isset( $conf['parsers'] ) ) {
                        throw new MWException( __METHOD__ . ': no parsers specified' );
                }
                $this->conf = $conf;
        }
 
-       function init() {
+       public function init() {
                if ( !is_null( $this->parsers ) ) {
                        return;
                }
@@ -64,7 +64,7 @@ class ParserDiffTest
                }
        }
 
-       function __call( $name, $args ) {
+       public function __call( $name, $args ) {
                $this->init();
                $results = array();
                $mismatch = false;
@@ -109,7 +109,7 @@ class ParserDiffTest
                return $lastResult;
        }
 
-       function formatArray( $array ) {
+       public function formatArray( $array ) {
                if ( $this->shortOutput ) {
                        foreach ( $array as $key => $value ) {
                                if ( $value instanceof ParserOutput ) {
@@ -120,7 +120,7 @@ class ParserDiffTest
                return var_export( $array, true );
        }
 
-       function setFunctionHook( $id, $callback, $flags = 0 ) {
+       public function setFunctionHook( $id, $callback, $flags = 0 ) {
                $this->init();
                foreach ( $this->parsers as $parser ) {
                        $parser->setFunctionHook( $id, $callback, $flags );
@@ -131,7 +131,7 @@ class ParserDiffTest
         * @param Parser $parser
         * @return bool
         */
-       function onClearState( &$parser ) {
+       public function onClearState( &$parser ) {
                // hack marker prefixes to get identical output
                if ( !isset( $this->dtUniqPrefix ) ) {
                        $this->dtUniqPrefix = $parser->uniqPrefix();
index 90617b3..2ca9d50 100644 (file)
@@ -22,7 +22,7 @@
  */
 
 /**
- * \brief Set options of the Parser
+ * @brief Set options of the Parser
  *
  * All member variables are supposed to be private in theory, although in
  * practise this is not the case.
@@ -34,108 +34,108 @@ class ParserOptions {
        /**
         * Interlanguage links are removed and returned in an array
         */
-       var $mInterwikiMagic;
+       public $mInterwikiMagic;
 
        /**
         * Allow external images inline?
         */
-       var $mAllowExternalImages;
+       public $mAllowExternalImages;
 
        /**
         * If not, any exception?
         */
-       var $mAllowExternalImagesFrom;
+       public $mAllowExternalImagesFrom;
 
        /**
         * If not or it doesn't match, should we check an on-wiki whitelist?
         */
-       var $mEnableImageWhitelist;
+       public $mEnableImageWhitelist;
 
        /**
         * Date format index
         */
-       var $mDateFormat = null;
+       public $mDateFormat = null;
 
        /**
         * Create "edit section" links?
         */
-       var $mEditSection = true;
+       public $mEditSection = true;
 
        /**
         * Allow inclusion of special pages?
         */
-       var $mAllowSpecialInclusion;
+       public $mAllowSpecialInclusion;
 
        /**
         * Use tidy to cleanup output HTML?
         */
-       var $mTidy = false;
+       public $mTidy = false;
 
        /**
         * Which lang to call for PLURAL and GRAMMAR
         */
-       var $mInterfaceMessage = false;
+       public $mInterfaceMessage = false;
 
        /**
         * Overrides $mInterfaceMessage with arbitrary language
         */
-       var $mTargetLanguage = null;
+       public $mTargetLanguage = null;
 
        /**
         * Maximum size of template expansions, in bytes
         */
-       var $mMaxIncludeSize;
+       public $mMaxIncludeSize;
 
        /**
         * Maximum number of nodes touched by PPFrame::expand()
         */
-       var $mMaxPPNodeCount;
+       public $mMaxPPNodeCount;
 
        /**
         * Maximum number of nodes generated by Preprocessor::preprocessToObj()
         */
-       var $mMaxGeneratedPPNodeCount;
+       public $mMaxGeneratedPPNodeCount;
 
        /**
         * Maximum recursion depth in PPFrame::expand()
         */
-       var $mMaxPPExpandDepth;
+       public $mMaxPPExpandDepth;
 
        /**
         * Maximum recursion depth for templates within templates
         */
-       var $mMaxTemplateDepth;
+       public $mMaxTemplateDepth;
 
        /**
         * Maximum number of calls per parse to expensive parser functions
         */
-       var $mExpensiveParserFunctionLimit;
+       public $mExpensiveParserFunctionLimit;
 
        /**
         * Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS
         */
-       var $mRemoveComments = true;
+       public $mRemoveComments = true;
 
        /**
         * Callback for template fetching. Used as first argument to call_user_func().
         */
-       var $mTemplateCallback =
+       public $mTemplateCallback =
                array( 'Parser', 'statelessFetchTemplate' );
 
        /**
         * Enable limit report in an HTML comment on output
         */
-       var $mEnableLimitReport = false;
+       public $mEnableLimitReport = false;
 
        /**
         * Timestamp used for {{CURRENTDAY}} etc.
         */
-       var $mTimestamp;
+       public $mTimestamp;
 
        /**
         * Target attribute for external links
         */
-       var $mExternalLinkTarget;
+       public $mExternalLinkTarget;
 
        /**
         * Clean up signature texts?
@@ -143,32 +143,32 @@ class ParserOptions {
         * 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures
         * 2) Substitute all transclusions
         */
-       var $mCleanSignatures;
+       public $mCleanSignatures;
 
        /**
         * Transform wiki markup when saving the page?
         */
-       var $mPreSaveTransform = true;
+       public $mPreSaveTransform = true;
 
        /**
         * Whether content conversion should be disabled
         */
-       var $mDisableContentConversion;
+       public $mDisableContentConversion;
 
        /**
         * Whether title conversion should be disabled
         */
-       var $mDisableTitleConversion;
+       public $mDisableTitleConversion;
 
        /**
         * Automatically number headings?
         */
-       var $mNumberHeadings;
+       public $mNumberHeadings;
 
        /**
         * Thumb size preferred by the user.
         */
-       var $mThumbSize;
+       public $mThumbSize;
 
        /**
         * Maximum article size of an article to be marked as "stub"
@@ -178,169 +178,169 @@ class ParserOptions {
        /**
         * Language object of the User language.
         */
-       var $mUserLang;
+       public $mUserLang;
 
        /**
         * @var User
         * Stored user object
         */
-       var $mUser;
+       public $mUser;
 
        /**
         * Parsing the page for a "preview" operation?
         */
-       var $mIsPreview = false;
+       public $mIsPreview = false;
 
        /**
         * Parsing the page for a "preview" operation on a single section?
         */
-       var $mIsSectionPreview = false;
+       public $mIsSectionPreview = false;
 
        /**
         * Parsing the printable version of the page?
         */
-       var $mIsPrintable = false;
+       public $mIsPrintable = false;
 
        /**
         * Extra key that should be present in the caching key.
         */
-       var $mExtraKey = '';
+       public $mExtraKey = '';
 
        /**
         * Function to be called when an option is accessed.
         */
        protected $onAccessCallback = null;
 
-       function getInterwikiMagic() {
+       public function getInterwikiMagic() {
                return $this->mInterwikiMagic;
        }
 
-       function getAllowExternalImages() {
+       public function getAllowExternalImages() {
                return $this->mAllowExternalImages;
        }
 
-       function getAllowExternalImagesFrom() {
+       public function getAllowExternalImagesFrom() {
                return $this->mAllowExternalImagesFrom;
        }
 
-       function getEnableImageWhitelist() {
+       public function getEnableImageWhitelist() {
                return $this->mEnableImageWhitelist;
        }
 
-       function getEditSection() {
+       public function getEditSection() {
                return $this->mEditSection;
        }
 
-       function getNumberHeadings() {
+       public function getNumberHeadings() {
                $this->optionUsed( 'numberheadings' );
 
                return $this->mNumberHeadings;
        }
 
-       function getAllowSpecialInclusion() {
+       public function getAllowSpecialInclusion() {
                return $this->mAllowSpecialInclusion;
        }
 
-       function getTidy() {
+       public function getTidy() {
                return $this->mTidy;
        }
 
-       function getInterfaceMessage() {
+       public function getInterfaceMessage() {
                return $this->mInterfaceMessage;
        }
 
-       function getTargetLanguage() {
+       public function getTargetLanguage() {
                return $this->mTargetLanguage;
        }
 
-       function getMaxIncludeSize() {
+       public function getMaxIncludeSize() {
                return $this->mMaxIncludeSize;
        }
 
-       function getMaxPPNodeCount() {
+       public function getMaxPPNodeCount() {
                return $this->mMaxPPNodeCount;
        }
 
-       function getMaxGeneratedPPNodeCount() {
+       public function getMaxGeneratedPPNodeCount() {
                return $this->mMaxGeneratedPPNodeCount;
        }
 
-       function getMaxPPExpandDepth() {
+       public function getMaxPPExpandDepth() {
                return $this->mMaxPPExpandDepth;
        }
 
-       function getMaxTemplateDepth() {
+       public function getMaxTemplateDepth() {
                return $this->mMaxTemplateDepth;
        }
 
        /* @since 1.20 */
-       function getExpensiveParserFunctionLimit() {
+       public function getExpensiveParserFunctionLimit() {
                return $this->mExpensiveParserFunctionLimit;
        }
 
-       function getRemoveComments() {
+       public function getRemoveComments() {
                return $this->mRemoveComments;
        }
 
-       function getTemplateCallback() {
+       public function getTemplateCallback() {
                return $this->mTemplateCallback;
        }
 
-       function getEnableLimitReport() {
+       public function getEnableLimitReport() {
                return $this->mEnableLimitReport;
        }
 
-       function getCleanSignatures() {
+       public function getCleanSignatures() {
                return $this->mCleanSignatures;
        }
 
-       function getExternalLinkTarget() {
+       public function getExternalLinkTarget() {
                return $this->mExternalLinkTarget;
        }
 
-       function getDisableContentConversion() {
+       public function getDisableContentConversion() {
                return $this->mDisableContentConversion;
        }
 
-       function getDisableTitleConversion() {
+       public function getDisableTitleConversion() {
                return $this->mDisableTitleConversion;
        }
 
-       function getThumbSize() {
+       public function getThumbSize() {
                $this->optionUsed( 'thumbsize' );
 
                return $this->mThumbSize;
        }
 
-       function getStubThreshold() {
+       public function getStubThreshold() {
                $this->optionUsed( 'stubthreshold' );
 
                return $this->mStubThreshold;
        }
 
-       function getIsPreview() {
+       public function getIsPreview() {
                return $this->mIsPreview;
        }
 
-       function getIsSectionPreview() {
+       public function getIsSectionPreview() {
                return $this->mIsSectionPreview;
        }
 
-       function getIsPrintable() {
+       public function getIsPrintable() {
                $this->optionUsed( 'printable' );
 
                return $this->mIsPrintable;
        }
 
-       function getUser() {
+       public function getUser() {
                return $this->mUser;
        }
 
-       function getPreSaveTransform() {
+       public function getPreSaveTransform() {
                return $this->mPreSaveTransform;
        }
 
-       function getDateFormat() {
+       public function getDateFormat() {
                $this->optionUsed( 'dateformat' );
                if ( !isset( $this->mDateFormat ) ) {
                        $this->mDateFormat = $this->mUser->getDatePreference();
@@ -348,7 +348,7 @@ class ParserOptions {
                return $this->mDateFormat;
        }
 
-       function getTimestamp() {
+       public function getTimestamp() {
                if ( !isset( $this->mTimestamp ) ) {
                        $this->mTimestamp = wfTimestampNow();
                }
@@ -371,7 +371,7 @@ class ParserOptions {
         * @return Language
         * @since 1.19
         */
-       function getUserLangObj() {
+       public function getUserLangObj() {
                $this->optionUsed( 'userlang' );
                return $this->mUserLang;
        }
@@ -382,113 +382,108 @@ class ParserOptions {
         * @return string Language code
         * @since 1.17
         */
-       function getUserLang() {
+       public function getUserLang() {
                return $this->getUserLangObj()->getCode();
        }
 
-       function setInterwikiMagic( $x ) {
+       public function setInterwikiMagic( $x ) {
                return wfSetVar( $this->mInterwikiMagic, $x );
        }
 
-       function setAllowExternalImages( $x ) {
+       public function setAllowExternalImages( $x ) {
                return wfSetVar( $this->mAllowExternalImages, $x );
        }
 
-       function setAllowExternalImagesFrom( $x ) {
+       public function setAllowExternalImagesFrom( $x ) {
                return wfSetVar( $this->mAllowExternalImagesFrom, $x );
        }
 
-       function setEnableImageWhitelist( $x ) {
+       public function setEnableImageWhitelist( $x ) {
                return wfSetVar( $this->mEnableImageWhitelist, $x );
        }
 
-       function setDateFormat( $x ) {
+       public function setDateFormat( $x ) {
                return wfSetVar( $this->mDateFormat, $x );
        }
 
-       function setEditSection( $x ) {
+       public function setEditSection( $x ) {
                return wfSetVar( $this->mEditSection, $x );
        }
 
-       function setNumberHeadings( $x ) {
+       public function setNumberHeadings( $x ) {
                return wfSetVar( $this->mNumberHeadings, $x );
        }
 
-       function setAllowSpecialInclusion( $x ) {
+       public function setAllowSpecialInclusion( $x ) {
                return wfSetVar( $this->mAllowSpecialInclusion, $x );
        }
 
-       function setTidy( $x ) {
+       public function setTidy( $x ) {
                return wfSetVar( $this->mTidy, $x );
        }
 
-       /** @deprecated since 1.19 */
-       function setSkin( $x ) {
-               wfDeprecated( __METHOD__, '1.19' );
-       }
-
-       function setInterfaceMessage( $x ) {
+       public function setInterfaceMessage( $x ) {
                return wfSetVar( $this->mInterfaceMessage, $x );
        }
 
-       function setTargetLanguage( $x ) {
+       public function setTargetLanguage( $x ) {
                return wfSetVar( $this->mTargetLanguage, $x, true );
        }
 
-       function setMaxIncludeSize( $x ) {
+       public function setMaxIncludeSize( $x ) {
                return wfSetVar( $this->mMaxIncludeSize, $x );
        }
 
-       function setMaxPPNodeCount( $x ) {
+       public function setMaxPPNodeCount( $x ) {
                return wfSetVar( $this->mMaxPPNodeCount, $x );
        }
 
-       function setMaxGeneratedPPNodeCount( $x ) {
+       public function setMaxGeneratedPPNodeCount( $x ) {
                return wfSetVar( $this->mMaxGeneratedPPNodeCount, $x );
        }
 
-       function setMaxTemplateDepth( $x ) {
+       public function setMaxTemplateDepth( $x ) {
                return wfSetVar( $this->mMaxTemplateDepth, $x );
        }
 
        /* @since 1.20 */
-       function setExpensiveParserFunctionLimit( $x ) {
+       public function setExpensiveParserFunctionLimit( $x ) {
                return wfSetVar( $this->mExpensiveParserFunctionLimit, $x );
        }
 
-       function setRemoveComments( $x ) {
+       public function setRemoveComments( $x ) {
                return wfSetVar( $this->mRemoveComments, $x );
        }
 
-       function setTemplateCallback( $x ) {
+       public function setTemplateCallback( $x ) {
                return wfSetVar( $this->mTemplateCallback, $x );
        }
 
-       function enableLimitReport( $x = true ) {
+       public function enableLimitReport( $x = true ) {
                return wfSetVar( $this->mEnableLimitReport, $x );
        }
 
-       function setTimestamp( $x ) {
+       public function setTimestamp( $x ) {
                return wfSetVar( $this->mTimestamp, $x );
        }
 
-       function setCleanSignatures( $x ) {
+       public function setCleanSignatures( $x ) {
                return wfSetVar( $this->mCleanSignatures, $x );
        }
 
-       function setExternalLinkTarget( $x ) {
+       public function setExternalLinkTarget( $x ) {
                return wfSetVar( $this->mExternalLinkTarget, $x );
        }
 
-       function disableContentConversion( $x = true ) {
+       public function disableContentConversion( $x = true ) {
                return wfSetVar( $this->mDisableContentConversion, $x );
        }
 
-       function disableTitleConversion( $x = true ) {
+       public function disableTitleConversion( $x = true ) {
                return wfSetVar( $this->mDisableTitleConversion, $x );
        }
 
-       function setUserLang( $x ) {
+       public function setUserLang( $x ) {
                if ( is_string( $x ) ) {
                        $x = Language::factory( $x );
                }
@@ -496,34 +491,35 @@ class ParserOptions {
                return wfSetVar( $this->mUserLang, $x );
        }
 
-       function setThumbSize( $x ) {
+       public function setThumbSize( $x ) {
                return wfSetVar( $this->mThumbSize, $x );
        }
 
-       function setStubThreshold( $x ) {
+       public function setStubThreshold( $x ) {
                return wfSetVar( $this->mStubThreshold, $x );
        }
 
-       function setPreSaveTransform( $x ) {
+       public function setPreSaveTransform( $x ) {
                return wfSetVar( $this->mPreSaveTransform, $x );
        }
 
-       function setIsPreview( $x ) {
+       public function setIsPreview( $x ) {
                return wfSetVar( $this->mIsPreview, $x );
        }
 
-       function setIsSectionPreview( $x ) {
+       public function setIsSectionPreview( $x ) {
                return wfSetVar( $this->mIsSectionPreview, $x );
        }
 
-       function setIsPrintable( $x ) {
+       public function setIsPrintable( $x ) {
                return wfSetVar( $this->mIsPrintable, $x );
        }
 
        /**
         * Extra key that should be present in the parser cache key.
+        * @param string $key
         */
-       function addExtraKey( $key ) {
+       public function addExtraKey( $key ) {
                $this->mExtraKey .= '!' . $key;
        }
 
@@ -532,7 +528,7 @@ class ParserOptions {
         * @param User $user
         * @param Language $lang
         */
-       function __construct( $user = null, $lang = null ) {
+       public function __construct( $user = null, $lang = null ) {
                if ( $user === null ) {
                        global $wgUser;
                        if ( $wgUser === null ) {
@@ -628,7 +624,7 @@ class ParserOptions {
         * This is a private API with the parser.
         * @param callable $callback
         */
-       function registerWatcher( $callback ) {
+       public function registerWatcher( $callback ) {
                $this->onAccessCallback = $callback;
        }
 
index 09f714f..5037ce1 100644 (file)
@@ -22,7 +22,7 @@
  * @ingroup Parser
  */
 class ParserOutput extends CacheTime {
-       var $mText,                       # The output text
+       public $mText,                       # The output text
                $mLanguageLinks,              # List of the full text of language links, in the order they appear
                $mCategories,                 # Map of category names to sort keys
                $mTitleText,                  # title text of the chosen language variant
@@ -50,17 +50,18 @@ class ParserOutput extends CacheTime {
                $mTOCHTML = '',               # HTML of the TOC
                $mTimestamp,                  # Timestamp of the revision
                $mTOCEnabled = true;          # Whether TOC should be shown, can't override __NOTOC__
-               private $mIndexPolicy = '';       # 'index' or 'noindex'?  Any other value will result in no change.
-               private $mAccessedOptions = array(); # List of ParserOptions (stored in the keys)
-               private $mSecondaryDataUpdates = array(); # List of DataUpdate, used to save info from the page somewhere else.
-               private $mExtensionData = array(); # extra data used by extensions
-               private $mLimitReportData = array(); # Parser limit report data
-               private $mParseStartTime = array(); # Timestamps for getTimeSinceStart()
+       private $mIndexPolicy = '';       # 'index' or 'noindex'?  Any other value will result in no change.
+       private $mAccessedOptions = array(); # List of ParserOptions (stored in the keys)
+       private $mSecondaryDataUpdates = array(); # List of DataUpdate, used to save info from the page somewhere else.
+       private $mExtensionData = array(); # extra data used by extensions
+       private $mLimitReportData = array(); # Parser limit report data
+       private $mParseStartTime = array(); # Timestamps for getTimeSinceStart()
+       private $mPreventClickjacking = false; # Whether to emit X-Frame-Options: DENY
 
        const EDITSECTION_REGEX =
                '#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)(</(?:mw:)?editsection>))#';
 
-       function __construct( $text = '', $languageLinks = array(), $categoryLinks = array(),
+       public function __construct( $text = '', $languageLinks = array(), $categoryLinks = array(),
                $containsOldMagic = false, $titletext = ''
        ) {
                $this->mText = $text;
@@ -70,12 +71,31 @@ class ParserOutput extends CacheTime {
                $this->mTitleText = $titletext;
        }
 
-       function getText() {
+       public function getText() {
                wfProfileIn( __METHOD__ );
                $text = $this->mText;
                if ( $this->mEditSectionTokens ) {
-                       $text = preg_replace_callback( ParserOutput::EDITSECTION_REGEX,
-                               array( &$this, 'replaceEditSectionLinksCallback' ), $text );
+                       $text = preg_replace_callback(
+                               ParserOutput::EDITSECTION_REGEX,
+                               function ( $m ) {
+                                       global $wgOut, $wgLang;
+                                       $editsectionPage = Title::newFromText( htmlspecialchars_decode( $m[1] ) );
+                                       $editsectionSection = htmlspecialchars_decode( $m[2] );
+                                       $editsectionContent = isset( $m[4] ) ? $m[3] : null;
+
+                                       if ( !is_object( $editsectionPage ) ) {
+                                               throw new MWException( "Bad parser output text." );
+                                       }
+
+                                       $skin = $wgOut->getSkin();
+                                       return call_user_func_array(
+                                               array( $skin, 'doEditSectionLink' ),
+                                               array( $editsectionPage, $editsectionSection,
+                                                       $editsectionContent, $wgLang->getCode() )
+                                       );
+                               },
+                               $text
+                       );
                } else {
                        $text = preg_replace( ParserOutput::EDITSECTION_REGEX, '', $text );
                }
@@ -94,204 +114,181 @@ class ParserOutput extends CacheTime {
                return $text;
        }
 
-       /**
-        * callback used by getText to replace editsection tokens
-        * @private
-        * @param array $m
-        * @throws MWException
-        * @return mixed
-        */
-       function replaceEditSectionLinksCallback( $m ) {
-               global $wgOut, $wgLang;
-               $args = array(
-                       htmlspecialchars_decode( $m[1] ),
-                       htmlspecialchars_decode( $m[2] ),
-                       isset( $m[4] ) ? $m[3] : null,
-               );
-               $args[0] = Title::newFromText( $args[0] );
-               if ( !is_object( $args[0] ) ) {
-                       throw new MWException( "Bad parser output text." );
-               }
-               $args[] = $wgLang->getCode();
-               $skin = $wgOut->getSkin();
-               return call_user_func_array( array( $skin, 'doEditSectionLink' ), $args );
-       }
-
-       function &getLanguageLinks() {
+       public function &getLanguageLinks() {
                return $this->mLanguageLinks;
        }
 
-       function getInterwikiLinks() {
+       public function getInterwikiLinks() {
                return $this->mInterwikiLinks;
        }
 
-       function getCategoryLinks() {
+       public function getCategoryLinks() {
                return array_keys( $this->mCategories );
        }
 
-       function &getCategories() {
+       public function &getCategories() {
                return $this->mCategories;
        }
 
-       function getTitleText() {
+       public function getTitleText() {
                return $this->mTitleText;
        }
 
-       function getSections() {
+       public function getSections() {
                return $this->mSections;
        }
 
-       function getEditSectionTokens() {
+       public function getEditSectionTokens() {
                return $this->mEditSectionTokens;
        }
 
-       function &getLinks() {
+       public function &getLinks() {
                return $this->mLinks;
        }
 
-       function &getTemplates() {
+       public function &getTemplates() {
                return $this->mTemplates;
        }
 
-       function &getTemplateIds() {
+       public function &getTemplateIds() {
                return $this->mTemplateIds;
        }
 
-       function &getImages() {
+       public function &getImages() {
                return $this->mImages;
        }
 
-       function &getFileSearchOptions() {
+       public function &getFileSearchOptions() {
                return $this->mFileSearchOptions;
        }
 
-       function &getExternalLinks() {
+       public function &getExternalLinks() {
                return $this->mExternalLinks;
        }
 
-       function getNoGallery() {
+       public function getNoGallery() {
                return $this->mNoGallery;
        }
 
-       function getHeadItems() {
+       public function getHeadItems() {
                return $this->mHeadItems;
        }
 
-       function getModules() {
+       public function getModules() {
                return $this->mModules;
        }
 
-       function getModuleScripts() {
+       public function getModuleScripts() {
                return $this->mModuleScripts;
        }
 
-       function getModuleStyles() {
+       public function getModuleStyles() {
                return $this->mModuleStyles;
        }
 
-       function getModuleMessages() {
+       public function getModuleMessages() {
                return $this->mModuleMessages;
        }
 
        /** @since 1.23 */
-       function getJsConfigVars() {
+       public function getJsConfigVars() {
                return $this->mJsConfigVars;
        }
 
-       function getOutputHooks() {
+       public function getOutputHooks() {
                return (array)$this->mOutputHooks;
        }
 
-       function getWarnings() {
+       public function getWarnings() {
                return array_keys( $this->mWarnings );
        }
 
-       function getIndexPolicy() {
+       public function getIndexPolicy() {
                return $this->mIndexPolicy;
        }
 
-       function getTOCHTML() {
+       public function getTOCHTML() {
                return $this->mTOCHTML;
        }
 
-       function getTimestamp() {
+       public function getTimestamp() {
                return $this->mTimestamp;
        }
 
-       function getLimitReportData() {
+       public function getLimitReportData() {
                return $this->mLimitReportData;
        }
 
-       function getTOCEnabled() {
+       public function getTOCEnabled() {
                return $this->mTOCEnabled;
        }
 
-       function setText( $text ) {
+       public function setText( $text ) {
                return wfSetVar( $this->mText, $text );
        }
 
-       function setLanguageLinks( $ll ) {
+       public function setLanguageLinks( $ll ) {
                return wfSetVar( $this->mLanguageLinks, $ll );
        }
 
-       function setCategoryLinks( $cl ) {
+       public function setCategoryLinks( $cl ) {
                return wfSetVar( $this->mCategories, $cl );
        }
 
-       function setTitleText( $t ) {
+       public function setTitleText( $t ) {
                return wfSetVar( $this->mTitleText, $t );
        }
 
-       function setSections( $toc ) {
+       public function setSections( $toc ) {
                return wfSetVar( $this->mSections, $toc );
        }
 
-       function setEditSectionTokens( $t ) {
+       public function setEditSectionTokens( $t ) {
                return wfSetVar( $this->mEditSectionTokens, $t );
        }
 
-       function setIndexPolicy( $policy ) {
+       public function setIndexPolicy( $policy ) {
                return wfSetVar( $this->mIndexPolicy, $policy );
        }
 
-       function setTOCHTML( $tochtml ) {
+       public function setTOCHTML( $tochtml ) {
                return wfSetVar( $this->mTOCHTML, $tochtml );
        }
 
-       function setTimestamp( $timestamp ) {
+       public function setTimestamp( $timestamp ) {
                return wfSetVar( $this->mTimestamp, $timestamp );
        }
 
-       function setTOCEnabled( $flag ) {
+       public function setTOCEnabled( $flag ) {
                return wfSetVar( $this->mTOCEnabled, $flag );
        }
 
-       function addCategory( $c, $sort ) {
+       public function addCategory( $c, $sort ) {
                $this->mCategories[$c] = $sort;
        }
 
-       function addLanguageLink( $t ) {
+       public function addLanguageLink( $t ) {
                $this->mLanguageLinks[] = $t;
        }
 
-       function addWarning( $s ) {
+       public function addWarning( $s ) {
                $this->mWarnings[$s] = 1;
        }
 
-       function addOutputHook( $hook, $data = false ) {
+       public function addOutputHook( $hook, $data = false ) {
                $this->mOutputHooks[] = array( $hook, $data );
        }
 
-       function setNewSection( $value ) {
+       public function setNewSection( $value ) {
                $this->mNewSection = (bool)$value;
        }
-       function hideNewSection( $value ) {
+       public function hideNewSection( $value ) {
                $this->mHideNewSection = (bool)$value;
        }
-       function getHideNewSection() {
+       public function getHideNewSection() {
                return (bool)$this->mHideNewSection;
        }
-       function getNewSection() {
+       public function getNewSection() {
                return (bool)$this->mNewSection;
        }
 
@@ -302,7 +299,7 @@ class ParserOutput extends CacheTime {
         * @param string $url The url to check
         * @return bool
         */
-       static function isLinkInternal( $internal, $url ) {
+       public static function isLinkInternal( $internal, $url ) {
                return (bool)preg_match( '/^' .
                        # If server is proto relative, check also for http/https links
                        ( substr( $internal, 0, 2 ) === '//' ? '(?:https?:)?' : '' ) .
@@ -313,7 +310,7 @@ class ParserOutput extends CacheTime {
                );
        }
 
-       function addExternalLink( $url ) {
+       public function addExternalLink( $url ) {
                # We don't register links pointing to our own server, unless... :-)
                global $wgServer, $wgRegisterInternalExternals;
 
@@ -332,7 +329,7 @@ class ParserOutput extends CacheTime {
         * @param Title $title
         * @param int|null $id Optional known page_id so we can skip the lookup
         */
-       function addLink( Title $title, $id = null ) {
+       public function addLink( Title $title, $id = null ) {
                if ( $title->isExternal() ) {
                        // Don't record interwikis in pagelinks
                        $this->addInterwikiLink( $title );
@@ -367,7 +364,7 @@ class ParserOutput extends CacheTime {
         * @param string $sha1 Base 36 SHA-1 of file (or false if non-existing)
         * @return void
         */
-       function addImage( $name, $timestamp = null, $sha1 = null ) {
+       public function addImage( $name, $timestamp = null, $sha1 = null ) {
                $this->mImages[$name] = 1;
                if ( $timestamp !== null && $sha1 !== null ) {
                        $this->mFileSearchOptions[$name] = array( 'time' => $timestamp, 'sha1' => $sha1 );
@@ -381,7 +378,7 @@ class ParserOutput extends CacheTime {
         * @param int $rev_id
         * @return void
         */
-       function addTemplate( $title, $page_id, $rev_id ) {
+       public function addTemplate( $title, $page_id, $rev_id ) {
                $ns = $title->getNamespace();
                $dbk = $title->getDBkey();
                if ( !isset( $this->mTemplates[$ns] ) ) {
@@ -396,9 +393,9 @@ class ParserOutput extends CacheTime {
 
        /**
         * @param Title $title Title object, must be an interwiki link
-        * @throws MWException if given invalid input
+        * @throws MWException If given invalid input
         */
-       function addInterwikiLink( $title ) {
+       public function addInterwikiLink( $title ) {
                if ( !$title->isExternal() ) {
                        throw new MWException( 'Non-interwiki link passed, internal parser error.' );
                }
@@ -416,7 +413,7 @@ class ParserOutput extends CacheTime {
         * @param string $section
         * @param string|bool $tag
         */
-       function addHeadItem( $section, $tag = false ) {
+       public function addHeadItem( $section, $tag = false ) {
                if ( $tag !== false ) {
                        $this->mHeadItems[$tag] = $section;
                } else {
@@ -471,6 +468,7 @@ class ParserOutput extends CacheTime {
                $this->addJsConfigVars( $out->getJsConfigVars() );
 
                $this->mHeadItems = array_merge( $this->mHeadItems, $out->getHeadItemsArray() );
+               $this->mPreventClickjacking = $this->mPreventClickjacking || $out->getPreventClickjacking();
        }
 
        /**
@@ -478,7 +476,7 @@ class ParserOutput extends CacheTime {
         * -- this is assumed to have been validated
         * (check equal normalisation, etc.)
         *
-        * @param string $text desired title text
+        * @param string $text Desired title text
         */
        public function setDisplayTitle( $text ) {
                $this->setTitleText( $text );
@@ -500,6 +498,7 @@ class ParserOutput extends CacheTime {
 
        /**
         * Fairly generic flag setter thingy.
+        * @param string $flag
         */
        public function setFlag( $flag ) {
                $this->mFlags[$flag] = true;
@@ -537,7 +536,7 @@ class ParserOutput extends CacheTime {
         *     Wikimedia Commons.
         *     This is not actually implemented, yet but would be pretty cool.
         *
-        * @note: Do not use setProperty() to set a property which is only used
+        * @note Do not use setProperty() to set a property which is only used
         * in a context where the ParserOutput object itself is already available,
         * for example a normal page view. There is no need to save such a property
         * in the database since the text is already parsed. You can just hook
@@ -576,7 +575,7 @@ class ParserOutput extends CacheTime {
        /**
         * @param string $name The property name to look up.
         *
-        * @return mixed|false The value previously set using setProperty(). False if null or no value
+        * @return mixed|bool The value previously set using setProperty(). False if null or no value
         * was set for the given property name.
         *
         * @note You need to use getProperties() to check for boolean and null properties.
@@ -734,10 +733,12 @@ class ParserOutput extends CacheTime {
                if ( !$clock || $clock === 'wall' ) {
                        $ret['wall'] = microtime( true );
                }
-               if ( ( !$clock || $clock === 'cpu' ) && function_exists( 'getrusage' ) ) {
-                       $ru = getrusage();
-                       $ret['cpu'] = $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1e6;
-                       $ret['cpu'] += $ru['ru_stime.tv_sec'] + $ru['ru_stime.tv_usec'] / 1e6;
+               if ( !$clock || $clock === 'cpu' ) {
+                       $ru = wfGetRusage();
+                       if ( $ru ) {
+                               $ret['cpu'] = $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1e6;
+                               $ret['cpu'] += $ru['ru_stime.tv_sec'] + $ru['ru_stime.tv_usec'] / 1e6;
+                       }
                }
                return $ret;
        }
@@ -746,7 +747,7 @@ class ParserOutput extends CacheTime {
         * Resets the parse start timestamps for future calls to getTimeSinceStart()
         * @since 1.22
         */
-       function resetParseStartTime() {
+       public function resetParseStartTime() {
                $this->mParseStartTime = self::getTimes();
        }
 
@@ -761,7 +762,7 @@ class ParserOutput extends CacheTime {
         * @param string $clock
         * @return float|null
         */
-       function getTimeSinceStart( $clock ) {
+       public function getTimeSinceStart( $clock ) {
                if ( !isset( $this->mParseStartTime[$clock] ) ) {
                        return null;
                }
@@ -789,14 +790,26 @@ class ParserOutput extends CacheTime {
         * @param string $key Message key
         * @param mixed $value Appropriate for Message::params()
         */
-       function setLimitReportData( $key, $value ) {
+       public function setLimitReportData( $key, $value ) {
                $this->mLimitReportData[$key] = $value;
        }
 
+       /**
+        * Get or set the prevent-clickjacking flag
+        *
+        * @since 1.24
+        * @param bool|null $flag New flag value, or null to leave it unchanged
+        * @return bool Old flag value
+        */
+       public function preventClickjacking( $flag = null ) {
+               return wfSetVar( $this->mPreventClickjacking, $flag );
+       }
+
        /**
         * Save space for for serialization by removing useless values
+        * @return array
         */
-       function __sleep() {
+       public function __sleep() {
                return array_diff(
                        array_keys( get_object_vars( $this ) ),
                        array( 'mSecondaryDataUpdates', 'mParseStartTime' )
index 335bd61..b32593c 100644 (file)
@@ -30,14 +30,14 @@ interface Preprocessor {
         *
         * @param Parser $parser
         */
-       function __construct( $parser );
+       public function __construct( $parser );
 
        /**
         * Create a new top-level frame for expansion of a page
         *
         * @return PPFrame
         */
-       function newFrame();
+       public function newFrame();
 
        /**
         * Create a new custom frame for programmatic use of parameter replacement
@@ -47,7 +47,7 @@ interface Preprocessor {
         *
         * @return PPFrame
         */
-       function newCustomFrame( $args );
+       public function newCustomFrame( $args );
 
        /**
         * Create a new custom node for programmatic use of parameter replacement
@@ -55,7 +55,7 @@ interface Preprocessor {
         *
         * @param array $values
         */
-       function newPartNodeArray( $values );
+       public function newPartNodeArray( $values );
 
        /**
         * Preprocess text to a PPNode
@@ -65,7 +65,7 @@ interface Preprocessor {
         *
         * @return PPNode
         */
-       function preprocessToObj( $text, $flags = 0 );
+       public function preprocessToObj( $text, $flags = 0 );
 }
 
 /**
@@ -93,65 +93,92 @@ interface PPFrame {
         *
         * @return PPFrame
         */
-       function newChild( $args = false, $title = false, $indexOffset = 0 );
+       public function newChild( $args = false, $title = false, $indexOffset = 0 );
 
        /**
         * Expand a document tree node, caching the result on its parent with the given key
+        * @param string|int $key
+        * @param string|PPNode $root
+        * @param int $flags
+        * @return string
         */
-       function cachedExpand( $key, $root, $flags = 0 );
+       public function cachedExpand( $key, $root, $flags = 0 );
 
        /**
         * Expand a document tree node
+        * @param string|PPNode $root
+        * @param int $flags
+        * @return string
         */
-       function expand( $root, $flags = 0 );
+       public function expand( $root, $flags = 0 );
 
        /**
         * Implode with flags for expand()
+        * @param string $sep
+        * @param int $flags
+        * @param string|PPNode $args,...
+        * @return string
         */
-       function implodeWithFlags( $sep, $flags /*, ... */ );
+       public function implodeWithFlags( $sep, $flags /*, ... */ );
 
        /**
         * Implode with no flags specified
+        * @param string $sep
+        * @param string|PPNode $args,...
+        * @return string
         */
-       function implode( $sep /*, ... */ );
+       public function implode( $sep /*, ... */ );
 
        /**
         * Makes an object that, when expand()ed, will be the same as one obtained
         * with implode()
+        * @param string $sep
+        * @param string|PPNode $args,...
+        * @return PPNode
         */
-       function virtualImplode( $sep /*, ... */ );
+       public function virtualImplode( $sep /*, ... */ );
 
        /**
         * Virtual implode with brackets
+        * @param string $start
+        * @param string $sep
+        * @param string $end
+        * @param string|PPNode $args,...
+        * @return PPNode
         */
-       function virtualBracketedImplode( $start, $sep, $end /*, ... */ );
+       public function virtualBracketedImplode( $start, $sep, $end /*, ... */ );
 
        /**
         * Returns true if there are no arguments in this frame
         *
         * @return bool
         */
-       function isEmpty();
+       public function isEmpty();
 
        /**
         * Returns all arguments of this frame
+        * @return array
         */
-       function getArguments();
+       public function getArguments();
 
        /**
         * Returns all numbered arguments of this frame
+        * @return array
         */
-       function getNumberedArguments();
+       public function getNumberedArguments();
 
        /**
         * Returns all named arguments of this frame
+        * @return array
         */
-       function getNamedArguments();
+       public function getNamedArguments();
 
        /**
         * Get an argument to this frame by name
+        * @param string $name
+        * @return bool
         */
-       function getArgument( $name );
+       public function getArgument( $name );
 
        /**
         * Returns true if the infinite loop check is OK, false if a loop is detected
@@ -159,12 +186,13 @@ interface PPFrame {
         * @param Title $title
         * @return bool
         */
-       function loopCheck( $title );
+       public function loopCheck( $title );
 
        /**
         * Return true if the frame is a template frame
+        * @return bool
         */
-       function isTemplate();
+       public function isTemplate();
 
        /**
         * Set the "volatile" flag.
@@ -177,7 +205,7 @@ interface PPFrame {
         *
         * @param bool $flag
         */
-       function setVolatile( $flag = true );
+       public function setVolatile( $flag = true );
 
        /**
         * Get the "volatile" flag.
@@ -188,7 +216,7 @@ interface PPFrame {
         * @see self::setVolatile()
         * @return bool
         */
-       function isVolatile();
+       public function isVolatile();
 
        /**
         * Get the TTL of the frame's output.
@@ -202,7 +230,7 @@ interface PPFrame {
         *
         * @return int|null
         */
-       function getTTL();
+       public function getTTL();
 
        /**
         * Set the TTL of the output of this frame and all of its ancestors.
@@ -213,14 +241,14 @@ interface PPFrame {
         * @see self::getTTL()
         * @param int $ttl
         */
-       function setTTL( $ttl );
+       public function setTTL( $ttl );
 
        /**
         * Get a title of frame
         *
         * @return Title
         */
-       function getTitle();
+       public function getTitle();
 }
 
 /**
@@ -240,36 +268,42 @@ interface PPNode {
        /**
         * Get an array-type node containing the children of this node.
         * Returns false if this is not a tree node.
+        * @return PPNode
         */
-       function getChildren();
+       public function getChildren();
 
        /**
         * Get the first child of a tree node. False if there isn't one.
         *
         * @return PPNode
         */
-       function getFirstChild();
+       public function getFirstChild();
 
        /**
         * Get the next sibling of any node. False if there isn't one
+        * @return PPNode
         */
-       function getNextSibling();
+       public function getNextSibling();
 
        /**
         * Get all children of this tree node which have a given name.
         * Returns an array-type node, or false if this is not a tree node.
+        * @param string $type
+        * @return bool|PPNode
         */
-       function getChildrenOfType( $type );
+       public function getChildrenOfType( $type );
 
        /**
         * Returns the length of the array, or false if this is not an array-type node
         */
-       function getLength();
+       public function getLength();
 
        /**
         * Returns an item of an array-type node
+        * @param int $i
+        * @return bool|PPNode
         */
-       function item( $i );
+       public function item( $i );
 
        /**
         * Get the name of this node. The following names are defined here:
@@ -282,25 +316,29 @@ interface PPNode {
         *    #nodelist     An array-type node
         *
         * The subclass may define various other names for tree and leaf nodes.
+        * @return string
         */
-       function getName();
+       public function getName();
 
        /**
         * Split a "<part>" node into an associative array containing:
         *    name          PPNode name
         *    index         String index
         *    value         PPNode value
+        * @return array
         */
-       function splitArg();
+       public function splitArg();
 
        /**
         * Split an "<ext>" node into an associative array containing name, attr, inner and close
         * All values in the resulting array are PPNodes. Inner and close are optional.
+        * @return array
         */
-       function splitExt();
+       public function splitExt();
 
        /**
         * Split an "<h>" node
+        * @return array
         */
-       function splitHeading();
+       public function splitHeading();
 }
index f5fc3ec..2edb79a 100644 (file)
 
 /**
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class Preprocessor_DOM implements Preprocessor {
+       // @codingStandardsIgnoreEnd
 
        /**
         * @var Parser
         */
-       var $parser;
+       public $parser;
 
-       var $memoryLimit;
+       public $memoryLimit;
 
        const CACHE_VERSION = 1;
 
-       function __construct( $parser ) {
+       public function __construct( $parser ) {
                $this->parser = $parser;
                $mem = ini_get( 'memory_limit' );
                $this->memoryLimit = false;
@@ -51,7 +53,7 @@ class Preprocessor_DOM implements Preprocessor {
        /**
         * @return PPFrame_DOM
         */
-       function newFrame() {
+       public function newFrame() {
                return new PPFrame_DOM( $this );
        }
 
@@ -59,7 +61,7 @@ class Preprocessor_DOM implements Preprocessor {
         * @param array $args
         * @return PPCustomFrame_DOM
         */
-       function newCustomFrame( $args ) {
+       public function newCustomFrame( $args ) {
                return new PPCustomFrame_DOM( $this, $args );
        }
 
@@ -67,7 +69,7 @@ class Preprocessor_DOM implements Preprocessor {
         * @param array $values
         * @return PPNode_DOM
         */
-       function newPartNodeArray( $values ) {
+       public function newPartNodeArray( $values ) {
                //NOTE: DOM manipulation is slower than building & parsing XML! (or so Tim sais)
                $xml = "<list>";
 
@@ -110,7 +112,7 @@ class Preprocessor_DOM implements Preprocessor {
         * @throws MWException
         * @return bool
         */
-       function memCheck() {
+       public function memCheck() {
                if ( $this->memoryLimit === false ) {
                        return true;
                }
@@ -146,7 +148,7 @@ class Preprocessor_DOM implements Preprocessor {
         * @throws MWException
         * @return PPNode_DOM
         */
-       function preprocessToObj( $text, $flags = 0 ) {
+       public function preprocessToObj( $text, $flags = 0 ) {
                wfProfileIn( __METHOD__ );
                global $wgMemc, $wgPreprocessorCacheThreshold;
 
@@ -224,7 +226,7 @@ class Preprocessor_DOM implements Preprocessor {
         * @param int $flags
         * @return string
         */
-       function preprocessToXml( $text, $flags = 0 ) {
+       public function preprocessToXml( $text, $flags = 0 ) {
                wfProfileIn( __METHOD__ );
                $rules = array(
                        '{' => array(
@@ -773,18 +775,18 @@ class Preprocessor_DOM implements Preprocessor {
  * @ingroup Parser
  */
 class PPDStack {
-       var $stack, $rootAccum;
+       public $stack, $rootAccum;
 
        /**
         * @var PPDStack
         */
-       var $top;
-       var $out;
-       var $elementClass = 'PPDStackElement';
+       public $top;
+       public $out;
+       public $elementClass = 'PPDStackElement';
 
-       static $false = false;
+       public static $false = false;
 
-       function __construct() {
+       public function __construct() {
                $this->stack = array();
                $this->top = false;
                $this->rootAccum = '';
@@ -794,15 +796,15 @@ class PPDStack {
        /**
         * @return int
         */
-       function count() {
+       public function count() {
                return count( $this->stack );
        }
 
-       function &getAccum() {
+       public function &getAccum() {
                return $this->accum;
        }
 
-       function getCurrentPart() {
+       public function getCurrentPart() {
                if ( $this->top === false ) {
                        return false;
                } else {
@@ -810,7 +812,7 @@ class PPDStack {
                }
        }
 
-       function push( $data ) {
+       public function push( $data ) {
                if ( $data instanceof $this->elementClass ) {
                        $this->stack[] = $data;
                } else {
@@ -821,7 +823,7 @@ class PPDStack {
                $this->accum =& $this->top->getAccum();
        }
 
-       function pop() {
+       public function pop() {
                if ( !count( $this->stack ) ) {
                        throw new MWException( __METHOD__ . ': no elements remaining' );
                }
@@ -837,7 +839,7 @@ class PPDStack {
                return $temp;
        }
 
-       function addPart( $s = '' ) {
+       public function addPart( $s = '' ) {
                $this->top->addPart( $s );
                $this->accum =& $this->top->getAccum();
        }
@@ -845,7 +847,7 @@ class PPDStack {
        /**
         * @return array
         */
-       function getFlags() {
+       public function getFlags() {
                if ( !count( $this->stack ) ) {
                        return array(
                                'findEquals' => false,
@@ -862,15 +864,15 @@ class PPDStack {
  * @ingroup Parser
  */
 class PPDStackElement {
-       var     $open,              // Opening character (\n for heading)
+       public $open,              // Opening character (\n for heading)
                $close,             // Matching closing character
                $count,             // Number of opening characters found (number of "=" for heading)
                $parts,             // Array of PPDPart objects describing pipe-separated parts.
                $lineStart;         // True if the open char appeared at the start of the input line. Not set for headings.
 
-       var $partClass = 'PPDPart';
+       public $partClass = 'PPDPart';
 
-       function __construct( $data = array() ) {
+       public function __construct( $data = array() ) {
                $class = $this->partClass;
                $this->parts = array( new $class );
 
@@ -879,23 +881,23 @@ class PPDStackElement {
                }
        }
 
-       function &getAccum() {
+       public function &getAccum() {
                return $this->parts[count( $this->parts ) - 1]->out;
        }
 
-       function addPart( $s = '' ) {
+       public function addPart( $s = '' ) {
                $class = $this->partClass;
                $this->parts[] = new $class( $s );
        }
 
-       function getCurrentPart() {
+       public function getCurrentPart() {
                return $this->parts[count( $this->parts ) - 1];
        }
 
        /**
         * @return array
         */
-       function getFlags() {
+       public function getFlags() {
                $partCount = count( $this->parts );
                $findPipe = $this->open != "\n" && $this->open != '[';
                return array(
@@ -911,7 +913,7 @@ class PPDStackElement {
         * @param bool|int $openingCount
         * @return string
         */
-       function breakSyntax( $openingCount = false ) {
+       public function breakSyntax( $openingCount = false ) {
                if ( $this->open == "\n" ) {
                        $s = $this->parts[0]->out;
                } else {
@@ -937,14 +939,14 @@ class PPDStackElement {
  * @ingroup Parser
  */
 class PPDPart {
-       var $out; // Output accumulator string
+       public $out; // Output accumulator string
 
        // Optional member variables:
        //   eqpos        Position of equals sign in output accumulator
        //   commentEnd   Past-the-end input pointer for the last comment encountered
        //   visualEnd    Past-the-end input pointer for the end of the accumulator minus comments
 
-       function __construct( $out = '' ) {
+       public function __construct( $out = '' ) {
                $this->out = $out;
        }
 }
@@ -952,36 +954,38 @@ class PPDPart {
 /**
  * An expansion frame, used as a context to expand the result of preprocessToObj()
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPFrame_DOM implements PPFrame {
+       // @codingStandardsIgnoreEnd
 
        /**
         * @var Preprocessor
         */
-       var $preprocessor;
+       public $preprocessor;
 
        /**
         * @var Parser
         */
-       var $parser;
+       public $parser;
 
        /**
         * @var Title
         */
-       var $title;
-       var $titleCache;
+       public $title;
+       public $titleCache;
 
        /**
         * Hashtable listing templates which are disallowed for expansion in this frame,
         * having been encountered previously in parent frames.
         */
-       var $loopCheckHash;
+       public $loopCheckHash;
 
        /**
         * Recursion depth of this frame, top = 0
         * Note that this is NOT the same as expansion depth in expand()
         */
-       var $depth;
+       public $depth;
 
        private $volatile = false;
        private $ttl = null;
@@ -995,7 +999,7 @@ class PPFrame_DOM implements PPFrame {
         * Construct a new preprocessor frame.
         * @param Preprocessor $preprocessor The parent preprocessor
         */
-       function __construct( $preprocessor ) {
+       public function __construct( $preprocessor ) {
                $this->preprocessor = $preprocessor;
                $this->parser = $preprocessor->parser;
                $this->title = $this->parser->mTitle;
@@ -1014,7 +1018,7 @@ class PPFrame_DOM implements PPFrame {
         * @param int $indexOffset
         * @return PPTemplateFrame_DOM
         */
-       function newChild( $args = false, $title = false, $indexOffset = 0 ) {
+       public function newChild( $args = false, $title = false, $indexOffset = 0 ) {
                $namedArgs = array();
                $numberedArgs = array();
                if ( $title === false ) {
@@ -1029,7 +1033,7 @@ class PPFrame_DOM implements PPFrame {
                                if ( $arg instanceof PPNode ) {
                                        $arg = $arg->node;
                                }
-                               if ( !$xpath ) {
+                               if ( !$xpath || $xpath->document !== $arg->ownerDocument ) {
                                        $xpath = new DOMXPath( $arg->ownerDocument );
                                }
 
@@ -1059,7 +1063,7 @@ class PPFrame_DOM implements PPFrame {
         * @param int $flags
         * @return string
         */
-       function cachedExpand( $key, $root, $flags = 0 ) {
+       public function cachedExpand( $key, $root, $flags = 0 ) {
                // we don't have a parent, so we don't have a cache
                return $this->expand( $root, $flags );
        }
@@ -1070,7 +1074,7 @@ class PPFrame_DOM implements PPFrame {
         * @param int $flags
         * @return string
         */
-       function expand( $root, $flags = 0 ) {
+       public function expand( $root, $flags = 0 ) {
                static $expansionDepth = 0;
                if ( is_string( $root ) ) {
                        return $root;
@@ -1311,9 +1315,10 @@ class PPFrame_DOM implements PPFrame {
        /**
         * @param string $sep
         * @param int $flags
+        * @param string|PPNode_DOM|DOMDocument $args,...
         * @return string
         */
-       function implodeWithFlags( $sep, $flags /*, ... */ ) {
+       public function implodeWithFlags( $sep, $flags /*, ... */ ) {
                $args = array_slice( func_get_args(), 2 );
 
                $first = true;
@@ -1342,9 +1347,10 @@ class PPFrame_DOM implements PPFrame {
         * This previously called implodeWithFlags but has now been inlined to reduce stack depth
         *
         * @param string $sep
+        * @param string|PPNode_DOM|DOMDocument $args,...
         * @return string
         */
-       function implode( $sep /*, ... */ ) {
+       public function implode( $sep /*, ... */ ) {
                $args = array_slice( func_get_args(), 1 );
 
                $first = true;
@@ -1373,9 +1379,10 @@ class PPFrame_DOM implements PPFrame {
         * with implode()
         *
         * @param string $sep
+        * @param string|PPNode_DOM|DOMDocument $args,...
         * @return array
         */
-       function virtualImplode( $sep /*, ... */ ) {
+       public function virtualImplode( $sep /*, ... */ ) {
                $args = array_slice( func_get_args(), 1 );
                $out = array();
                $first = true;
@@ -1404,9 +1411,10 @@ class PPFrame_DOM implements PPFrame {
         * @param string $start
         * @param string $sep
         * @param string $end
+        * @param string|PPNode_DOM|DOMDocument $args,...
         * @return array
         */
-       function virtualBracketedImplode( $start, $sep, $end /*, ... */ ) {
+       public function virtualBracketedImplode( $start, $sep, $end /*, ... */ ) {
                $args = array_slice( func_get_args(), 3 );
                $out = array( $start );
                $first = true;
@@ -1431,11 +1439,11 @@ class PPFrame_DOM implements PPFrame {
                return $out;
        }
 
-       function __toString() {
+       public function __toString() {
                return 'frame{}';
        }
 
-       function getPDBK( $level = false ) {
+       public function getPDBK( $level = false ) {
                if ( $level === false ) {
                        return $this->title->getPrefixedDBkey();
                } else {
@@ -1446,21 +1454,21 @@ class PPFrame_DOM implements PPFrame {
        /**
         * @return array
         */
-       function getArguments() {
+       public function getArguments() {
                return array();
        }
 
        /**
         * @return array
         */
-       function getNumberedArguments() {
+       public function getNumberedArguments() {
                return array();
        }
 
        /**
         * @return array
         */
-       function getNamedArguments() {
+       public function getNamedArguments() {
                return array();
        }
 
@@ -1469,11 +1477,11 @@ class PPFrame_DOM implements PPFrame {
         *
         * @return bool
         */
-       function isEmpty() {
+       public function isEmpty() {
                return true;
        }
 
-       function getArgument( $name ) {
+       public function getArgument( $name ) {
                return false;
        }
 
@@ -1483,7 +1491,7 @@ class PPFrame_DOM implements PPFrame {
         * @param Title $title
         * @return bool
         */
-       function loopCheck( $title ) {
+       public function loopCheck( $title ) {
                return !isset( $this->loopCheckHash[$title->getPrefixedDBkey()] );
        }
 
@@ -1492,7 +1500,7 @@ class PPFrame_DOM implements PPFrame {
         *
         * @return bool
         */
-       function isTemplate() {
+       public function isTemplate() {
                return false;
        }
 
@@ -1501,7 +1509,7 @@ class PPFrame_DOM implements PPFrame {
         *
         * @return Title
         */
-       function getTitle() {
+       public function getTitle() {
                return $this->title;
        }
 
@@ -1510,7 +1518,7 @@ class PPFrame_DOM implements PPFrame {
         *
         * @param bool $flag
         */
-       function setVolatile( $flag = true ) {
+       public function setVolatile( $flag = true ) {
                $this->volatile = $flag;
        }
 
@@ -1519,7 +1527,7 @@ class PPFrame_DOM implements PPFrame {
         *
         * @return bool
         */
-       function isVolatile() {
+       public function isVolatile() {
                return $this->volatile;
        }
 
@@ -1528,7 +1536,7 @@ class PPFrame_DOM implements PPFrame {
         *
         * @param int $ttl
         */
-       function setTTL( $ttl ) {
+       public function setTTL( $ttl ) {
                if ( $ttl !== null && ( $this->ttl === null || $ttl < $this->ttl ) ) {
                        $this->ttl = $ttl;
                }
@@ -1539,7 +1547,7 @@ class PPFrame_DOM implements PPFrame {
         *
         * @return int|null
         */
-       function getTTL() {
+       public function getTTL() {
                return $this->ttl;
        }
 }
@@ -1547,15 +1555,18 @@ class PPFrame_DOM implements PPFrame {
 /**
  * Expansion frame with template arguments
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPTemplateFrame_DOM extends PPFrame_DOM {
-       var $numberedArgs, $namedArgs;
+       // @codingStandardsIgnoreEnd
+
+       public $numberedArgs, $namedArgs;
 
        /**
         * @var PPFrame_DOM
         */
-       var $parent;
-       var $numberedExpansionCache, $namedExpansionCache;
+       public $parent;
+       public $numberedExpansionCache, $namedExpansionCache;
 
        /**
         * @param Preprocessor $preprocessor
@@ -1564,7 +1575,7 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
         * @param array $namedArgs
         * @param bool|Title $title
         */
-       function __construct( $preprocessor, $parent = false, $numberedArgs = array(),
+       public function __construct( $preprocessor, $parent = false, $numberedArgs = array(),
                $namedArgs = array(), $title = false
        ) {
                parent::__construct( $preprocessor );
@@ -1584,7 +1595,7 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
                $this->numberedExpansionCache = $this->namedExpansionCache = array();
        }
 
-       function __toString() {
+       public function __toString() {
                $s = 'tplframe{';
                $first = true;
                $args = $this->numberedArgs + $this->namedArgs;
@@ -1608,7 +1619,7 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
         * @param int $flags
         * @return string
         */
-       function cachedExpand( $key, $root, $flags = 0 ) {
+       public function cachedExpand( $key, $root, $flags = 0 ) {
                if ( isset( $this->parent->childExpansionCache[$key] ) ) {
                        return $this->parent->childExpansionCache[$key];
                }
@@ -1624,11 +1635,11 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
         *
         * @return bool
         */
-       function isEmpty() {
+       public function isEmpty() {
                return !count( $this->numberedArgs ) && !count( $this->namedArgs );
        }
 
-       function getArguments() {
+       public function getArguments() {
                $arguments = array();
                foreach ( array_merge(
                                array_keys( $this->numberedArgs ),
@@ -1638,7 +1649,7 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
                return $arguments;
        }
 
-       function getNumberedArguments() {
+       public function getNumberedArguments() {
                $arguments = array();
                foreach ( array_keys( $this->numberedArgs ) as $key ) {
                        $arguments[$key] = $this->getArgument( $key );
@@ -1646,7 +1657,7 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
                return $arguments;
        }
 
-       function getNamedArguments() {
+       public function getNamedArguments() {
                $arguments = array();
                foreach ( array_keys( $this->namedArgs ) as $key ) {
                        $arguments[$key] = $this->getArgument( $key );
@@ -1654,7 +1665,7 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
                return $arguments;
        }
 
-       function getNumberedArgument( $index ) {
+       public function getNumberedArgument( $index ) {
                if ( !isset( $this->numberedArgs[$index] ) ) {
                        return false;
                }
@@ -1668,7 +1679,7 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
                return $this->numberedExpansionCache[$index];
        }
 
-       function getNamedArgument( $name ) {
+       public function getNamedArgument( $name ) {
                if ( !isset( $this->namedArgs[$name] ) ) {
                        return false;
                }
@@ -1680,7 +1691,7 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
                return $this->namedExpansionCache[$name];
        }
 
-       function getArgument( $name ) {
+       public function getArgument( $name ) {
                $text = $this->getNumberedArgument( $name );
                if ( $text === false ) {
                        $text = $this->getNamedArgument( $name );
@@ -1693,16 +1704,16 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
         *
         * @return bool
         */
-       function isTemplate() {
+       public function isTemplate() {
                return true;
        }
 
-       function setVolatile( $flag = true ) {
+       public function setVolatile( $flag = true ) {
                parent::setVolatile( $flag );
                $this->parent->setVolatile( $flag );
        }
 
-       function setTTL( $ttl ) {
+       public function setTTL( $ttl ) {
                parent::setTTL( $ttl );
                $this->parent->setTTL( $ttl );
        }
@@ -1711,16 +1722,19 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
 /**
  * Expansion frame with custom arguments
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPCustomFrame_DOM extends PPFrame_DOM {
-       var $args;
+       // @codingStandardsIgnoreEnd
+
+       public $args;
 
-       function __construct( $preprocessor, $args ) {
+       public function __construct( $preprocessor, $args ) {
                parent::__construct( $preprocessor );
                $this->args = $args;
        }
 
-       function __toString() {
+       public function __toString() {
                $s = 'cstmframe{';
                $first = true;
                foreach ( $this->args as $name => $value ) {
@@ -1739,48 +1753,50 @@ class PPCustomFrame_DOM extends PPFrame_DOM {
        /**
         * @return bool
         */
-       function isEmpty() {
+       public function isEmpty() {
                return !count( $this->args );
        }
 
-       function getArgument( $index ) {
+       public function getArgument( $index ) {
                if ( !isset( $this->args[$index] ) ) {
                        return false;
                }
                return $this->args[$index];
        }
 
-       function getArguments() {
+       public function getArguments() {
                return $this->args;
        }
 }
 
 /**
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPNode_DOM implements PPNode {
+       // @codingStandardsIgnoreEnd
 
        /**
         * @var DOMElement
         */
-       var $node;
-       var $xpath;
+       public $node;
+       public $xpath;
 
-       function __construct( $node, $xpath = false ) {
+       public function __construct( $node, $xpath = false ) {
                $this->node = $node;
        }
 
        /**
         * @return DOMXPath
         */
-       function getXPath() {
+       public function getXPath() {
                if ( $this->xpath === null ) {
                        $this->xpath = new DOMXPath( $this->node->ownerDocument );
                }
                return $this->xpath;
        }
 
-       function __toString() {
+       public function __toString() {
                if ( $this->node instanceof DOMNodeList ) {
                        $s = '';
                        foreach ( $this->node as $node ) {
@@ -1795,21 +1811,21 @@ class PPNode_DOM implements PPNode {
        /**
         * @return bool|PPNode_DOM
         */
-       function getChildren() {
+       public function getChildren() {
                return $this->node->childNodes ? new self( $this->node->childNodes ) : false;
        }
 
        /**
         * @return bool|PPNode_DOM
         */
-       function getFirstChild() {
+       public function getFirstChild() {
                return $this->node->firstChild ? new self( $this->node->firstChild ) : false;
        }
 
        /**
         * @return bool|PPNode_DOM
         */
-       function getNextSibling() {
+       public function getNextSibling() {
                return $this->node->nextSibling ? new self( $this->node->nextSibling ) : false;
        }
 
@@ -1818,14 +1834,14 @@ class PPNode_DOM implements PPNode {
         *
         * @return bool|PPNode_DOM
         */
-       function getChildrenOfType( $type ) {
+       public function getChildrenOfType( $type ) {
                return new self( $this->getXPath()->query( $type, $this->node ) );
        }
 
        /**
         * @return int
         */
-       function getLength() {
+       public function getLength() {
                if ( $this->node instanceof DOMNodeList ) {
                        return $this->node->length;
                } else {
@@ -1837,7 +1853,7 @@ class PPNode_DOM implements PPNode {
         * @param int $i
         * @return bool|PPNode_DOM
         */
-       function item( $i ) {
+       public function item( $i ) {
                $item = $this->node->item( $i );
                return $item ? new self( $item ) : false;
        }
@@ -1845,7 +1861,7 @@ class PPNode_DOM implements PPNode {
        /**
         * @return string
         */
-       function getName() {
+       public function getName() {
                if ( $this->node instanceof DOMNodeList ) {
                        return '#nodelist';
                } else {
@@ -1862,7 +1878,7 @@ class PPNode_DOM implements PPNode {
         * @throws MWException
         * @return array
         */
-       function splitArg() {
+       public function splitArg() {
                $xpath = $this->getXPath();
                $names = $xpath->query( 'name', $this->node );
                $values = $xpath->query( 'value', $this->node );
@@ -1884,7 +1900,7 @@ class PPNode_DOM implements PPNode {
         * @throws MWException
         * @return array
         */
-       function splitExt() {
+       public function splitExt() {
                $xpath = $this->getXPath();
                $names = $xpath->query( 'name', $this->node );
                $attrs = $xpath->query( 'attr', $this->node );
@@ -1910,7 +1926,7 @@ class PPNode_DOM implements PPNode {
         * @throws MWException
         * @return array
         */
-       function splitHeading() {
+       public function splitHeading() {
                if ( $this->getName() !== 'h' ) {
                        throw new MWException( 'Invalid h node passed to ' . __METHOD__ );
                }
index bf2bf61..6376396 100644 (file)
  *   * attribute nodes are children
  *   * "<h>" nodes that aren't at the top are replaced with <possible-h>
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class Preprocessor_Hash implements Preprocessor {
+       // @codingStandardsIgnoreEnd
+
        /**
         * @var Parser
         */
-       var $parser;
+       public $parser;
 
        const CACHE_VERSION = 1;
 
-       function __construct( $parser ) {
+       public function __construct( $parser ) {
                $this->parser = $parser;
        }
 
        /**
         * @return PPFrame_Hash
         */
-       function newFrame() {
+       public function newFrame() {
                return new PPFrame_Hash( $this );
        }
 
@@ -50,7 +53,7 @@ class Preprocessor_Hash implements Preprocessor {
         * @param array $args
         * @return PPCustomFrame_Hash
         */
-       function newCustomFrame( $args ) {
+       public function newCustomFrame( $args ) {
                return new PPCustomFrame_Hash( $this, $args );
        }
 
@@ -58,7 +61,7 @@ class Preprocessor_Hash implements Preprocessor {
         * @param array $values
         * @return PPNode_Hash_Array
         */
-       function newPartNodeArray( $values ) {
+       public function newPartNodeArray( $values ) {
                $list = array();
 
                foreach ( $values as $k => $val ) {
@@ -108,7 +111,7 @@ class Preprocessor_Hash implements Preprocessor {
         * @throws MWException
         * @return PPNode_Hash_Tree
         */
-       function preprocessToObj( $text, $flags = 0 ) {
+       public function preprocessToObj( $text, $flags = 0 ) {
                wfProfileIn( __METHOD__ );
 
                // Check cache.
@@ -758,9 +761,12 @@ class Preprocessor_Hash implements Preprocessor {
 /**
  * Stack class to help Preprocessor::preprocessToObj()
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPDStack_Hash extends PPDStack {
-       function __construct() {
+       // @codingStandardsIgnoreEnd
+
+       public function __construct() {
                $this->elementClass = 'PPDStackElement_Hash';
                parent::__construct();
                $this->rootAccum = new PPDAccum_Hash;
@@ -769,9 +775,12 @@ class PPDStack_Hash extends PPDStack {
 
 /**
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPDStackElement_Hash extends PPDStackElement {
-       function __construct( $data = array() ) {
+       // @codingStandardsIgnoreENd
+
+       public function __construct( $data = array() ) {
                $this->partClass = 'PPDPart_Hash';
                parent::__construct( $data );
        }
@@ -782,7 +791,7 @@ class PPDStackElement_Hash extends PPDStackElement {
         * @param int|bool $openingCount
         * @return PPDAccum_Hash
         */
-       function breakSyntax( $openingCount = false ) {
+       public function breakSyntax( $openingCount = false ) {
                if ( $this->open == "\n" ) {
                        $accum = $this->parts[0]->out;
                } else {
@@ -807,9 +816,12 @@ class PPDStackElement_Hash extends PPDStackElement {
 
 /**
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPDPart_Hash extends PPDPart {
-       function __construct( $out = '' ) {
+       // @codingStandardsIgnoreEnd
+
+       public function __construct( $out = '' ) {
                $accum = new PPDAccum_Hash;
                if ( $out !== '' ) {
                        $accum->addLiteral( $out );
@@ -820,11 +832,14 @@ class PPDPart_Hash extends PPDPart {
 
 /**
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPDAccum_Hash {
-       var $firstNode, $lastNode;
+       // @codingStandardsIgnoreEnd
+
+       public $firstNode, $lastNode;
 
-       function __construct() {
+       public function __construct() {
                $this->firstNode = $this->lastNode = false;
        }
 
@@ -832,7 +847,7 @@ class PPDAccum_Hash {
         * Append a string literal
         * @param string $s
         */
-       function addLiteral( $s ) {
+       public function addLiteral( $s ) {
                if ( $this->lastNode === false ) {
                        $this->firstNode = $this->lastNode = new PPNode_Hash_Text( $s );
                } elseif ( $this->lastNode instanceof PPNode_Hash_Text ) {
@@ -847,7 +862,7 @@ class PPDAccum_Hash {
         * Append a PPNode
         * @param PPNode $node
         */
-       function addNode( PPNode $node ) {
+       public function addNode( PPNode $node ) {
                if ( $this->lastNode === false ) {
                        $this->firstNode = $this->lastNode = $node;
                } else {
@@ -861,7 +876,7 @@ class PPDAccum_Hash {
         * @param string $name
         * @param string $value
         */
-       function addNodeWithText( $name, $value ) {
+       public function addNodeWithText( $name, $value ) {
                $node = PPNode_Hash_Tree::newWithText( $name, $value );
                $this->addNode( $node );
        }
@@ -872,7 +887,7 @@ class PPDAccum_Hash {
         * subsequently be modified, especially nextSibling.
         * @param PPDAccum_Hash $accum
         */
-       function addAccum( $accum ) {
+       public function addAccum( $accum ) {
                if ( $accum->lastNode === false ) {
                        // nothing to add
                } elseif ( $this->lastNode === false ) {
@@ -888,36 +903,38 @@ class PPDAccum_Hash {
 /**
  * An expansion frame, used as a context to expand the result of preprocessToObj()
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPFrame_Hash implements PPFrame {
+       // @codingStandardsIgnoreEnd
 
        /**
         * @var Parser
         */
-       var $parser;
+       public $parser;
 
        /**
         * @var Preprocessor
         */
-       var $preprocessor;
+       public $preprocessor;
 
        /**
         * @var Title
         */
-       var $title;
-       var $titleCache;
+       public $title;
+       public $titleCache;
 
        /**
         * Hashtable listing templates which are disallowed for expansion in this frame,
         * having been encountered previously in parent frames.
         */
-       var $loopCheckHash;
+       public $loopCheckHash;
 
        /**
         * Recursion depth of this frame, top = 0
         * Note that this is NOT the same as expansion depth in expand()
         */
-       var $depth;
+       public $depth;
 
        private $volatile = false;
        private $ttl = null;
@@ -931,7 +948,7 @@ class PPFrame_Hash implements PPFrame {
         * Construct a new preprocessor frame.
         * @param Preprocessor $preprocessor The parent preprocessor
         */
-       function __construct( $preprocessor ) {
+       public function __construct( $preprocessor ) {
                $this->preprocessor = $preprocessor;
                $this->parser = $preprocessor->parser;
                $this->title = $this->parser->mTitle;
@@ -951,7 +968,7 @@ class PPFrame_Hash implements PPFrame {
         * @throws MWException
         * @return PPTemplateFrame_Hash
         */
-       function newChild( $args = false, $title = false, $indexOffset = 0 ) {
+       public function newChild( $args = false, $title = false, $indexOffset = 0 ) {
                $namedArgs = array();
                $numberedArgs = array();
                if ( $title === false ) {
@@ -984,22 +1001,22 @@ class PPFrame_Hash implements PPFrame {
        /**
         * @throws MWException
         * @param string|int $key
-        * @param string|PPNode_Hash|DOMDocument $root
+        * @param string|PPNode $root
         * @param int $flags
         * @return string
         */
-       function cachedExpand( $key, $root, $flags = 0 ) {
+       public function cachedExpand( $key, $root, $flags = 0 ) {
                // we don't have a parent, so we don't have a cache
                return $this->expand( $root, $flags );
        }
 
        /**
         * @throws MWException
-        * @param string|PPNode$root
+        * @param string|PPNode $root
         * @param int $flags
         * @return string
         */
-       function expand( $root, $flags = 0 ) {
+       public function expand( $root, $flags = 0 ) {
                static $expansionDepth = 0;
                if ( is_string( $root ) ) {
                        return $root;
@@ -1207,9 +1224,10 @@ class PPFrame_Hash implements PPFrame {
        /**
         * @param string $sep
         * @param int $flags
+        * @param string|PPNode $args,...
         * @return string
         */
-       function implodeWithFlags( $sep, $flags /*, ... */ ) {
+       public function implodeWithFlags( $sep, $flags /*, ... */ ) {
                $args = array_slice( func_get_args(), 2 );
 
                $first = true;
@@ -1237,9 +1255,10 @@ class PPFrame_Hash implements PPFrame {
         * Implode with no flags specified
         * This previously called implodeWithFlags but has now been inlined to reduce stack depth
         * @param string $sep
+        * @param string|PPNode $args,...
         * @return string
         */
-       function implode( $sep /*, ... */ ) {
+       public function implode( $sep /*, ... */ ) {
                $args = array_slice( func_get_args(), 1 );
 
                $first = true;
@@ -1268,9 +1287,10 @@ class PPFrame_Hash implements PPFrame {
         * with implode()
         *
         * @param string $sep
+        * @param string|PPNode $args,...
         * @return PPNode_Hash_Array
         */
-       function virtualImplode( $sep /*, ... */ ) {
+       public function virtualImplode( $sep /*, ... */ ) {
                $args = array_slice( func_get_args(), 1 );
                $out = array();
                $first = true;
@@ -1300,9 +1320,10 @@ class PPFrame_Hash implements PPFrame {
         * @param string $start
         * @param string $sep
         * @param string $end
+        * @param string|PPNode $args,...
         * @return PPNode_Hash_Array
         */
-       function virtualBracketedImplode( $start, $sep, $end /*, ... */ ) {
+       public function virtualBracketedImplode( $start, $sep, $end /*, ... */ ) {
                $args = array_slice( func_get_args(), 3 );
                $out = array( $start );
                $first = true;
@@ -1327,7 +1348,7 @@ class PPFrame_Hash implements PPFrame {
                return new PPNode_Hash_Array( $out );
        }
 
-       function __toString() {
+       public function __toString() {
                return 'frame{}';
        }
 
@@ -1335,7 +1356,7 @@ class PPFrame_Hash implements PPFrame {
         * @param bool $level
         * @return array|bool|string
         */
-       function getPDBK( $level = false ) {
+       public function getPDBK( $level = false ) {
                if ( $level === false ) {
                        return $this->title->getPrefixedDBkey();
                } else {
@@ -1346,21 +1367,21 @@ class PPFrame_Hash implements PPFrame {
        /**
         * @return array
         */
-       function getArguments() {
+       public function getArguments() {
                return array();
        }
 
        /**
         * @return array
         */
-       function getNumberedArguments() {
+       public function getNumberedArguments() {
                return array();
        }
 
        /**
         * @return array
         */
-       function getNamedArguments() {
+       public function getNamedArguments() {
                return array();
        }
 
@@ -1369,7 +1390,7 @@ class PPFrame_Hash implements PPFrame {
         *
         * @return bool
         */
-       function isEmpty() {
+       public function isEmpty() {
                return true;
        }
 
@@ -1377,7 +1398,7 @@ class PPFrame_Hash implements PPFrame {
         * @param string $name
         * @return bool
         */
-       function getArgument( $name ) {
+       public function getArgument( $name ) {
                return false;
        }
 
@@ -1388,7 +1409,7 @@ class PPFrame_Hash implements PPFrame {
         *
         * @return bool
         */
-       function loopCheck( $title ) {
+       public function loopCheck( $title ) {
                return !isset( $this->loopCheckHash[$title->getPrefixedDBkey()] );
        }
 
@@ -1397,7 +1418,7 @@ class PPFrame_Hash implements PPFrame {
         *
         * @return bool
         */
-       function isTemplate() {
+       public function isTemplate() {
                return false;
        }
 
@@ -1406,7 +1427,7 @@ class PPFrame_Hash implements PPFrame {
         *
         * @return Title
         */
-       function getTitle() {
+       public function getTitle() {
                return $this->title;
        }
 
@@ -1415,7 +1436,7 @@ class PPFrame_Hash implements PPFrame {
         *
         * @param bool $flag
         */
-       function setVolatile( $flag = true ) {
+       public function setVolatile( $flag = true ) {
                $this->volatile = $flag;
        }
 
@@ -1424,7 +1445,7 @@ class PPFrame_Hash implements PPFrame {
         *
         * @return bool
         */
-       function isVolatile() {
+       public function isVolatile() {
                return $this->volatile;
        }
 
@@ -1433,7 +1454,7 @@ class PPFrame_Hash implements PPFrame {
         *
         * @param int $ttl
         */
-       function setTTL( $ttl ) {
+       public function setTTL( $ttl ) {
                if ( $ttl !== null && ( $this->ttl === null || $ttl < $this->ttl ) ) {
                        $this->ttl = $ttl;
                }
@@ -1444,7 +1465,7 @@ class PPFrame_Hash implements PPFrame {
         *
         * @return int|null
         */
-       function getTTL() {
+       public function getTTL() {
                return $this->ttl;
        }
 }
@@ -1452,10 +1473,13 @@ class PPFrame_Hash implements PPFrame {
 /**
  * Expansion frame with template arguments
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPTemplateFrame_Hash extends PPFrame_Hash {
-       var $numberedArgs, $namedArgs, $parent;
-       var $numberedExpansionCache, $namedExpansionCache;
+       // @codingStandardsIgnoreEnd
+
+       public $numberedArgs, $namedArgs, $parent;
+       public $numberedExpansionCache, $namedExpansionCache;
 
        /**
         * @param Preprocessor $preprocessor
@@ -1464,7 +1488,7 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
         * @param array $namedArgs
         * @param bool|Title $title
         */
-       function __construct( $preprocessor, $parent = false, $numberedArgs = array(),
+       public function __construct( $preprocessor, $parent = false, $numberedArgs = array(),
                $namedArgs = array(), $title = false
        ) {
                parent::__construct( $preprocessor );
@@ -1484,7 +1508,7 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
                $this->numberedExpansionCache = $this->namedExpansionCache = array();
        }
 
-       function __toString() {
+       public function __toString() {
                $s = 'tplframe{';
                $first = true;
                $args = $this->numberedArgs + $this->namedArgs;
@@ -1504,11 +1528,11 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
        /**
         * @throws MWException
         * @param string|int $key
-        * @param string|PPNode_Hash|DOMDocument $root
+        * @param string|PPNode $root
         * @param int $flags
         * @return string
         */
-       function cachedExpand( $key, $root, $flags = 0 ) {
+       public function cachedExpand( $key, $root, $flags = 0 ) {
                if ( isset( $this->parent->childExpansionCache[$key] ) ) {
                        return $this->parent->childExpansionCache[$key];
                }
@@ -1524,14 +1548,14 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
         *
         * @return bool
         */
-       function isEmpty() {
+       public function isEmpty() {
                return !count( $this->numberedArgs ) && !count( $this->namedArgs );
        }
 
        /**
         * @return array
         */
-       function getArguments() {
+       public function getArguments() {
                $arguments = array();
                foreach ( array_merge(
                                array_keys( $this->numberedArgs ),
@@ -1544,7 +1568,7 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
        /**
         * @return array
         */
-       function getNumberedArguments() {
+       public function getNumberedArguments() {
                $arguments = array();
                foreach ( array_keys( $this->numberedArgs ) as $key ) {
                        $arguments[$key] = $this->getArgument( $key );
@@ -1555,7 +1579,7 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
        /**
         * @return array
         */
-       function getNamedArguments() {
+       public function getNamedArguments() {
                $arguments = array();
                foreach ( array_keys( $this->namedArgs ) as $key ) {
                        $arguments[$key] = $this->getArgument( $key );
@@ -1567,7 +1591,7 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
         * @param int $index
         * @return array|bool
         */
-       function getNumberedArgument( $index ) {
+       public function getNumberedArgument( $index ) {
                if ( !isset( $this->numberedArgs[$index] ) ) {
                        return false;
                }
@@ -1585,7 +1609,7 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
         * @param string $name
         * @return bool
         */
-       function getNamedArgument( $name ) {
+       public function getNamedArgument( $name ) {
                if ( !isset( $this->namedArgs[$name] ) ) {
                        return false;
                }
@@ -1601,7 +1625,7 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
         * @param string $name
         * @return array|bool
         */
-       function getArgument( $name ) {
+       public function getArgument( $name ) {
                $text = $this->getNumberedArgument( $name );
                if ( $text === false ) {
                        $text = $this->getNamedArgument( $name );
@@ -1614,16 +1638,16 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
         *
         * @return bool
         */
-       function isTemplate() {
+       public function isTemplate() {
                return true;
        }
 
-       function setVolatile( $flag = true ) {
+       public function setVolatile( $flag = true ) {
                parent::setVolatile( $flag );
                $this->parent->setVolatile( $flag );
        }
 
-       function setTTL( $ttl ) {
+       public function setTTL( $ttl ) {
                parent::setTTL( $ttl );
                $this->parent->setTTL( $ttl );
        }
@@ -1632,16 +1656,19 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
 /**
  * Expansion frame with custom arguments
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPCustomFrame_Hash extends PPFrame_Hash {
-       var $args;
+       // @codingStandardsIgnoreEnd
 
-       function __construct( $preprocessor, $args ) {
+       public $args;
+
+       public function __construct( $preprocessor, $args ) {
                parent::__construct( $preprocessor );
                $this->args = $args;
        }
 
-       function __toString() {
+       public function __toString() {
                $s = 'cstmframe{';
                $first = true;
                foreach ( $this->args as $name => $value ) {
@@ -1660,7 +1687,7 @@ class PPCustomFrame_Hash extends PPFrame_Hash {
        /**
         * @return bool
         */
-       function isEmpty() {
+       public function isEmpty() {
                return !count( $this->args );
        }
 
@@ -1668,30 +1695,33 @@ class PPCustomFrame_Hash extends PPFrame_Hash {
         * @param int $index
         * @return bool
         */
-       function getArgument( $index ) {
+       public function getArgument( $index ) {
                if ( !isset( $this->args[$index] ) ) {
                        return false;
                }
                return $this->args[$index];
        }
 
-       function getArguments() {
+       public function getArguments() {
                return $this->args;
        }
 }
 
 /**
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPNode_Hash_Tree implements PPNode {
-       var $name, $firstChild, $lastChild, $nextSibling;
+       // @codingStandardsIgnoreEnd
+
+       public $name, $firstChild, $lastChild, $nextSibling;
 
-       function __construct( $name ) {
+       public function __construct( $name ) {
                $this->name = $name;
                $this->firstChild = $this->lastChild = $this->nextSibling = false;
        }
 
-       function __toString() {
+       public function __toString() {
                $inner = '';
                $attribs = '';
                for ( $node = $this->firstChild; $node; $node = $node->nextSibling ) {
@@ -1713,13 +1743,13 @@ class PPNode_Hash_Tree implements PPNode {
         * @param string $text
         * @return PPNode_Hash_Tree
         */
-       static function newWithText( $name, $text ) {
+       public static function newWithText( $name, $text ) {
                $obj = new self( $name );
                $obj->addChild( new PPNode_Hash_Text( $text ) );
                return $obj;
        }
 
-       function addChild( $node ) {
+       public function addChild( $node ) {
                if ( $this->lastChild === false ) {
                        $this->firstChild = $this->lastChild = $node;
                } else {
@@ -1731,7 +1761,7 @@ class PPNode_Hash_Tree implements PPNode {
        /**
         * @return PPNode_Hash_Array
         */
-       function getChildren() {
+       public function getChildren() {
                $children = array();
                for ( $child = $this->firstChild; $child; $child = $child->nextSibling ) {
                        $children[] = $child;
@@ -1739,15 +1769,15 @@ class PPNode_Hash_Tree implements PPNode {
                return new PPNode_Hash_Array( $children );
        }
 
-       function getFirstChild() {
+       public function getFirstChild() {
                return $this->firstChild;
        }
 
-       function getNextSibling() {
+       public function getNextSibling() {
                return $this->nextSibling;
        }
 
-       function getChildrenOfType( $name ) {
+       public function getChildrenOfType( $name ) {
                $children = array();
                for ( $child = $this->firstChild; $child; $child = $child->nextSibling ) {
                        if ( isset( $child->name ) && $child->name === $name ) {
@@ -1760,7 +1790,7 @@ class PPNode_Hash_Tree implements PPNode {
        /**
         * @return bool
         */
-       function getLength() {
+       public function getLength() {
                return false;
        }
 
@@ -1768,14 +1798,14 @@ class PPNode_Hash_Tree implements PPNode {
         * @param int $i
         * @return bool
         */
-       function item( $i ) {
+       public function item( $i ) {
                return false;
        }
 
        /**
         * @return string
         */
-       function getName() {
+       public function getName() {
                return $this->name;
        }
 
@@ -1788,7 +1818,7 @@ class PPNode_Hash_Tree implements PPNode {
         * @throws MWException
         * @return array
         */
-       function splitArg() {
+       public function splitArg() {
                $bits = array();
                for ( $child = $this->firstChild; $child; $child = $child->nextSibling ) {
                        if ( !isset( $child->name ) ) {
@@ -1822,7 +1852,7 @@ class PPNode_Hash_Tree implements PPNode {
         * @throws MWException
         * @return array
         */
-       function splitExt() {
+       public function splitExt() {
                $bits = array();
                for ( $child = $this->firstChild; $child; $child = $child->nextSibling ) {
                        if ( !isset( $child->name ) ) {
@@ -1850,7 +1880,7 @@ class PPNode_Hash_Tree implements PPNode {
         * @throws MWException
         * @return array
         */
-       function splitHeading() {
+       public function splitHeading() {
                if ( $this->name !== 'h' ) {
                        throw new MWException( 'Invalid h node passed to ' . __METHOD__ );
                }
@@ -1877,7 +1907,7 @@ class PPNode_Hash_Tree implements PPNode {
         * @throws MWException
         * @return array
         */
-       function splitTemplate() {
+       public function splitTemplate() {
                $parts = array();
                $bits = array( 'lineStart' => '' );
                for ( $child = $this->firstChild; $child; $child = $child->nextSibling ) {
@@ -1904,169 +1934,178 @@ class PPNode_Hash_Tree implements PPNode {
 
 /**
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPNode_Hash_Text implements PPNode {
-       var $value, $nextSibling;
+       // @codingStandardsIgnoreEnd
+
+       public $value, $nextSibling;
 
-       function __construct( $value ) {
+       public function __construct( $value ) {
                if ( is_object( $value ) ) {
                        throw new MWException( __CLASS__ . ' given object instead of string' );
                }
                $this->value = $value;
        }
 
-       function __toString() {
+       public function __toString() {
                return htmlspecialchars( $this->value );
        }
 
-       function getNextSibling() {
+       public function getNextSibling() {
                return $this->nextSibling;
        }
 
-       function getChildren() {
+       public function getChildren() {
                return false;
        }
 
-       function getFirstChild() {
+       public function getFirstChild() {
                return false;
        }
 
-       function getChildrenOfType( $name ) {
+       public function getChildrenOfType( $name ) {
                return false;
        }
 
-       function getLength() {
+       public function getLength() {
                return false;
        }
 
-       function item( $i ) {
+       public function item( $i ) {
                return false;
        }
 
-       function getName() {
+       public function getName() {
                return '#text';
        }
 
-       function splitArg() {
+       public function splitArg() {
                throw new MWException( __METHOD__ . ': not supported' );
        }
 
-       function splitExt() {
+       public function splitExt() {
                throw new MWException( __METHOD__ . ': not supported' );
        }
 
-       function splitHeading() {
+       public function splitHeading() {
                throw new MWException( __METHOD__ . ': not supported' );
        }
 }
 
 /**
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPNode_Hash_Array implements PPNode {
-       var $value, $nextSibling;
+       // @codingStandardsIgnoreEnd
 
-       function __construct( $value ) {
+       public $value, $nextSibling;
+
+       public function __construct( $value ) {
                $this->value = $value;
        }
 
-       function __toString() {
+       public function __toString() {
                return var_export( $this, true );
        }
 
-       function getLength() {
+       public function getLength() {
                return count( $this->value );
        }
 
-       function item( $i ) {
+       public function item( $i ) {
                return $this->value[$i];
        }
 
-       function getName() {
+       public function getName() {
                return '#nodelist';
        }
 
-       function getNextSibling() {
+       public function getNextSibling() {
                return $this->nextSibling;
        }
 
-       function getChildren() {
+       public function getChildren() {
                return false;
        }
 
-       function getFirstChild() {
+       public function getFirstChild() {
                return false;
        }
 
-       function getChildrenOfType( $name ) {
+       public function getChildrenOfType( $name ) {
                return false;
        }
 
-       function splitArg() {
+       public function splitArg() {
                throw new MWException( __METHOD__ . ': not supported' );
        }
 
-       function splitExt() {
+       public function splitExt() {
                throw new MWException( __METHOD__ . ': not supported' );
        }
 
-       function splitHeading() {
+       public function splitHeading() {
                throw new MWException( __METHOD__ . ': not supported' );
        }
 }
 
 /**
  * @ingroup Parser
+ * @codingStandardsIgnoreStart
  */
 class PPNode_Hash_Attr implements PPNode {
-       var $name, $value, $nextSibling;
+       // @codingStandardsIgnoreEnd
+
+       public $name, $value, $nextSibling;
 
-       function __construct( $name, $value ) {
+       public function __construct( $name, $value ) {
                $this->name = $name;
                $this->value = $value;
        }
 
-       function __toString() {
+       public function __toString() {
                return "<@{$this->name}>" . htmlspecialchars( $this->value ) . "</@{$this->name}>";
        }
 
-       function getName() {
+       public function getName() {
                return $this->name;
        }
 
-       function getNextSibling() {
+       public function getNextSibling() {
                return $this->nextSibling;
        }
 
-       function getChildren() {
+       public function getChildren() {
                return false;
        }
 
-       function getFirstChild() {
+       public function getFirstChild() {
                return false;
        }
 
-       function getChildrenOfType( $name ) {
+       public function getChildrenOfType( $name ) {
                return false;
        }
 
-       function getLength() {
+       public function getLength() {
                return false;
        }
 
-       function item( $i ) {
+       public function item( $i ) {
                return false;
        }
 
-       function splitArg() {
+       public function splitArg() {
                throw new MWException( __METHOD__ . ': not supported' );
        }
 
-       function splitExt() {
+       public function splitExt() {
                throw new MWException( __METHOD__ . ': not supported' );
        }
 
-       function splitHeading() {
+       public function splitHeading() {
                throw new MWException( __METHOD__ . ': not supported' );
        }
 }
index d4f4559..5d1743e 100644 (file)
@@ -39,7 +39,7 @@ class StripState {
        /**
         * @param string $prefix
         */
-       function __construct( $prefix ) {
+       public function __construct( $prefix ) {
                $this->prefix = $prefix;
                $this->data = array(
                        'nowiki' => array(),
@@ -54,7 +54,7 @@ class StripState {
         * @param string $marker
         * @param string $value
         */
-       function addNoWiki( $marker, $value ) {
+       public function addNoWiki( $marker, $value ) {
                $this->addItem( 'nowiki', $marker, $value );
        }
 
@@ -62,7 +62,7 @@ class StripState {
         * @param string $marker
         * @param string $value
         */
-       function addGeneral( $marker, $value ) {
+       public function addGeneral( $marker, $value ) {
                $this->addItem( 'general', $marker, $value );
        }
 
@@ -84,7 +84,7 @@ class StripState {
         * @param string $text
         * @return mixed
         */
-       function unstripGeneral( $text ) {
+       public function unstripGeneral( $text ) {
                return $this->unstripType( 'general', $text );
        }
 
@@ -92,7 +92,7 @@ class StripState {
         * @param string $text
         * @return mixed
         */
-       function unstripNoWiki( $text ) {
+       public function unstripNoWiki( $text ) {
                return $this->unstripType( 'nowiki', $text );
        }
 
@@ -100,7 +100,7 @@ class StripState {
         * @param string $text
         * @return mixed
         */
-       function unstripBoth( $text ) {
+       public function unstripBoth( $text ) {
                $text = $this->unstripType( 'general', $text );
                $text = $this->unstripType( 'nowiki', $text );
                return $text;
@@ -163,7 +163,7 @@ class StripState {
         *
         * @return StripState
         */
-       function getSubState( $text ) {
+       public function getSubState( $text ) {
                $subState = new StripState( $this->prefix );
                $pos = 0;
                while ( true ) {
@@ -199,7 +199,7 @@ class StripState {
         * @param array $texts
         * @return array
         */
-       function merge( $otherState, $texts ) {
+       public function merge( $otherState, $texts ) {
                $mergePrefix = Parser::getRandomString();
 
                foreach ( $otherState->data as $type => $items ) {
@@ -229,7 +229,7 @@ class StripState {
         * @param string $text Input string
         * @return string
         */
-       function killMarkers( $text ) {
+       public function killMarkers( $text ) {
                return preg_replace( $this->regex, '', $text );
        }
 }
diff --git a/includes/parser/Tidy.php b/includes/parser/Tidy.php
deleted file mode 100644 (file)
index f7fe5a8..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-<?php
-/**
- * HTML validation and correction
- *
- * 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 Parser
- */
-
-/**
- * Class used to hide mw:editsection tokens from Tidy so that it doesn't break them
- * or break on them. This is a bit of a hack for now, but hopefully in the future
- * we may create a real postprocessor or something that will replace this.
- * It's called wrapper because for now it basically takes over MWTidy::tidy's task
- * of wrapping the text in a xhtml block
- *
- * This re-uses some of the parser's UNIQ tricks, though some of it is private so it's
- * duplicated. Perhaps we should create an abstract marker hiding class.
- *
- * @ingroup Parser
- */
-class MWTidyWrapper {
-
-       /**
-        * @var ReplacementArray
-        */
-       protected $mTokens;
-
-       protected $mUniqPrefix;
-
-       protected $mMarkerIndex;
-
-       public function __construct() {
-               $this->mTokens = null;
-               $this->mUniqPrefix = null;
-       }
-
-       /**
-        * @param string $text
-        * @return string
-        */
-       public function getWrapped( $text ) {
-               $this->mTokens = new ReplacementArray;
-               $this->mUniqPrefix = "\x7fUNIQ" .
-                       dechex( mt_rand( 0, 0x7fffffff ) ) . dechex( mt_rand( 0, 0x7fffffff ) );
-               $this->mMarkerIndex = 0;
-
-               // Replace <mw:editsection> elements with placeholders
-               $wrappedtext = preg_replace_callback( ParserOutput::EDITSECTION_REGEX,
-                       array( &$this, 'replaceCallback' ), $text );
-               // ...and <mw:toc> markers
-               $wrappedtext = preg_replace_callback( '/\<\\/?mw:toc\>/',
-                       array( &$this, 'replaceCallback' ), $wrappedtext );
-
-               // Modify inline Microdata <link> and <meta> elements so they say <html-link> and <html-meta> so
-               // we can trick Tidy into not stripping them out by including them in tidy's new-empty-tags config
-               $wrappedtext = preg_replace( '!<(link|meta)([^>]*?)(/{0,1}>)!', '<html-$1$2$3', $wrappedtext );
-
-               // Wrap the whole thing in a doctype and body for Tidy.
-               $wrappedtext = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' .
-                       ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html>' .
-                       '<head><title>test</title></head><body>' . $wrappedtext . '</body></html>';
-
-               return $wrappedtext;
-       }
-
-       /**
-        * @param array $m
-        *
-        * @return string
-        */
-       function replaceCallback( $m ) {
-               $marker = "{$this->mUniqPrefix}-item-{$this->mMarkerIndex}" . Parser::MARKER_SUFFIX;
-               $this->mMarkerIndex++;
-               $this->mTokens->setPair( $marker, $m[0] );
-               return $marker;
-       }
-
-       /**
-        * @param string $text
-        * @return string
-        */
-       public function postprocess( $text ) {
-               // Revert <html-{link,meta}> back to <{link,meta}>
-               $text = preg_replace( '!<html-(link|meta)([^>]*?)(/{0,1}>)!', '<$1$2$3', $text );
-
-               // Restore the contents of placeholder tokens
-               $text = $this->mTokens->replace( $text );
-
-               return $text;
-       }
-
-}
-
-/**
- * Class to interact with HTML tidy
- *
- * Either the external tidy program or the in-process tidy extension
- * will be used depending on availability. Override the default
- * $wgTidyInternal setting to disable the internal if it's not working.
- *
- * @ingroup Parser
- */
-class MWTidy {
-       /**
-        * Interface with html tidy, used if $wgUseTidy = true.
-        * If tidy isn't able to correct the markup, the original will be
-        * returned in all its glory with a warning comment appended.
-        *
-        * @param string $text Hideous HTML input
-        * @return string Corrected HTML output
-        */
-       public static function tidy( $text ) {
-               global $wgTidyInternal;
-
-               $wrapper = new MWTidyWrapper;
-               $wrappedtext = $wrapper->getWrapped( $text );
-
-               $retVal = null;
-               if ( $wgTidyInternal ) {
-                       $correctedtext = self::execInternalTidy( $wrappedtext, false, $retVal );
-               } else {
-                       $correctedtext = self::execExternalTidy( $wrappedtext, false, $retVal );
-               }
-
-               if ( $retVal < 0 ) {
-                       wfDebug( "Possible tidy configuration error!\n" );
-                       return $text . "\n<!-- Tidy was unable to run -->\n";
-               } elseif ( is_null( $correctedtext ) ) {
-                       wfDebug( "Tidy error detected!\n" );
-                       return $text . "\n<!-- Tidy found serious XHTML errors -->\n";
-               }
-
-               $correctedtext = $wrapper->postprocess( $correctedtext ); // restore any hidden tokens
-
-               return $correctedtext;
-       }
-
-       /**
-        * Check HTML for errors, used if $wgValidateAllHtml = true.
-        *
-        * @param string $text
-        * @param string &$errorStr Return the error string
-        * @return bool Whether the HTML is valid
-        */
-       public static function checkErrors( $text, &$errorStr = null ) {
-               global $wgTidyInternal;
-
-               $retval = 0;
-               if ( $wgTidyInternal ) {
-                       $errorStr = self::execInternalTidy( $text, true, $retval );
-               } else {
-                       $errorStr = self::execExternalTidy( $text, true, $retval );
-               }
-
-               return ( $retval < 0 && $errorStr == '' ) || $retval == 0;
-       }
-
-       /**
-        * Spawn an external HTML tidy process and get corrected markup back from it.
-        * Also called in OutputHandler.php for full page validation
-        *
-        * @param string $text HTML to check
-        * @param bool $stderr Whether to read result from STDERR rather than STDOUT
-        * @param int &$retval Exit code (-1 on internal error)
-        * @return string|null
-        */
-       private static function execExternalTidy( $text, $stderr = false, &$retval = null ) {
-               global $wgTidyConf, $wgTidyBin, $wgTidyOpts;
-               wfProfileIn( __METHOD__ );
-
-               $cleansource = '';
-               $opts = ' -utf8';
-
-               if ( $stderr ) {
-                       $descriptorspec = array(
-                               0 => array( 'pipe', 'r' ),
-                               1 => array( 'file', wfGetNull(), 'a' ),
-                               2 => array( 'pipe', 'w' )
-                       );
-               } else {
-                       $descriptorspec = array(
-                               0 => array( 'pipe', 'r' ),
-                               1 => array( 'pipe', 'w' ),
-                               2 => array( 'file', wfGetNull(), 'a' )
-                       );
-               }
-
-               $readpipe = $stderr ? 2 : 1;
-               $pipes = array();
-
-               $process = proc_open(
-                       "$wgTidyBin -config $wgTidyConf $wgTidyOpts$opts", $descriptorspec, $pipes );
-
-               //NOTE: At least on linux, the process will be created even if tidy is not installed.
-               //      This means that missing tidy will be treated as a validation failure.
-
-               if ( is_resource( $process ) ) {
-                       // Theoretically, this style of communication could cause a deadlock
-                       // here. If the stdout buffer fills up, then writes to stdin could
-                       // block. This doesn't appear to happen with tidy, because tidy only
-                       // writes to stdout after it's finished reading from stdin. Search
-                       // for tidyParseStdin and tidySaveStdout in console/tidy.c
-                       fwrite( $pipes[0], $text );
-                       fclose( $pipes[0] );
-                       while ( !feof( $pipes[$readpipe] ) ) {
-                               $cleansource .= fgets( $pipes[$readpipe], 1024 );
-                       }
-                       fclose( $pipes[$readpipe] );
-                       $retval = proc_close( $process );
-               } else {
-                       wfWarn( "Unable to start external tidy process" );
-                       $retval = -1;
-               }
-
-               if ( !$stderr && $cleansource == '' && $text != '' ) {
-                       // Some kind of error happened, so we couldn't get the corrected text.
-                       // Just give up; we'll use the source text and append a warning.
-                       $cleansource = null;
-               }
-
-               wfProfileOut( __METHOD__ );
-               return $cleansource;
-       }
-
-       /**
-        * Use the HTML tidy extension to use the tidy library in-process,
-        * saving the overhead of spawning a new process.
-        *
-        * @param string $text HTML to check
-        * @param bool $stderr Whether to read result from error status instead of output
-        * @param int &$retval Exit code (-1 on internal error)
-        * @return string|null
-        */
-       private static function execInternalTidy( $text, $stderr = false, &$retval = null ) {
-               global $wgTidyConf, $wgDebugTidy;
-               wfProfileIn( __METHOD__ );
-
-               if ( !class_exists( 'tidy' ) ) {
-                       wfWarn( "Unable to load internal tidy class." );
-                       $retval = -1;
-
-                       wfProfileOut( __METHOD__ );
-                       return null;
-               }
-
-               $tidy = new tidy;
-               $tidy->parseString( $text, $wgTidyConf, 'utf8' );
-
-               if ( $stderr ) {
-                       $retval = $tidy->getStatus();
-
-                       wfProfileOut( __METHOD__ );
-                       return $tidy->errorBuffer;
-               }
-
-               $tidy->cleanRepair();
-               $retval = $tidy->getStatus();
-               if ( $retval == 2 ) {
-                       // 2 is magic number for fatal error
-                       // http://www.php.net/manual/en/function.tidy-get-status.php
-                       $cleansource = null;
-               } else {
-                       $cleansource = tidy_get_output( $tidy );
-                       if ( $wgDebugTidy && $retval > 0 ) {
-                               $cleansource .= "<!--\nTidy reports:\n" .
-                                       str_replace( '-->', '--&gt;', $tidy->errorBuffer ) .
-                                       "\n-->";
-                       }
-               }
-
-               wfProfileOut( __METHOD__ );
-               return $cleansource;
-       }
-}
diff --git a/includes/password/BcryptPassword.php b/includes/password/BcryptPassword.php
new file mode 100644 (file)
index 0000000..dd806e2
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Implements the BcryptPassword class for the MediaWiki software.
+ *
+ * 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 Bcrypt-hashed password
+ *
+ * This is a computationally complex password hash for use in modern applications.
+ * The number of rounds can be configured by $wgPasswordConfig['bcrypt']['cost'].
+ *
+ * @since 1.24
+ */
+class BcryptPassword extends ParameterizedPassword {
+       protected function getDefaultParams() {
+               return array(
+                       'rounds' => $this->config['cost'],
+               );
+       }
+
+       protected function getDelimiter() {
+               return '$';
+       }
+
+       protected function parseHash( $hash ) {
+               parent::parseHash( $hash );
+
+               $this->params['rounds'] = (int)$this->params['rounds'];
+       }
+
+       /**
+        * @param string $password Password to encrypt
+        *
+        * @throws PasswordError If bcrypt has an unknown error
+        * @throws MWException If bcrypt is not supported by PHP
+        */
+       public function crypt( $password ) {
+               if ( !defined( 'CRYPT_BLOWFISH' ) ) {
+                       throw new MWException( 'Bcrypt is not supported.' );
+               }
+
+               // Either use existing hash or make a new salt
+               // Bcrypt expects 22 characters of base64-encoded salt
+               // Note: bcrypt does not use MIME base64. It uses its own base64 without any '=' padding.
+               //       It expects a 128 bit salt, so it will ignore anything after the first 128 bits
+               if ( !isset( $this->args[0] ) ) {
+                       $this->args[] = substr(
+                               // Replace + with ., because bcrypt uses a non-MIME base64 format
+                               strtr(
+                                       // Random base64 encoded string
+                                       base64_encode( MWCryptRand::generate( 16, true ) ),
+                                       '+', '.'
+                               ),
+                               0, 22
+                       );
+               }
+
+               $hash = crypt( $password,
+                       sprintf( '$2y$%02d$%s', (int)$this->params['rounds'], $this->args[0] ) );
+
+               if ( !is_string( $hash ) || strlen( $hash ) <= 13 ) {
+                       throw new PasswordError( 'Error when hashing password.' );
+               }
+
+               // Strip the $2y$
+               $parts = explode( $this->getDelimiter(), substr( $hash, 4 ) );
+               $this->params['rounds'] = (int)$parts[0];
+               $this->args[0] = substr( $parts[1], 0, 22 );
+               $this->hash = substr( $parts[1], 22 );
+       }
+}
diff --git a/includes/password/EncryptedPassword.php b/includes/password/EncryptedPassword.php
new file mode 100644 (file)
index 0000000..39da32d
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Implements the EncryptedPassword class for the MediaWiki software.
+ *
+ * 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
+ */
+
+/**
+ * Helper class for passwords that use another password hash underneath it
+ * and encrypts that hash with a configured secret.
+ *
+ * @since 1.24
+ */
+class EncryptedPassword extends ParameterizedPassword {
+       protected function getDelimiter() {
+               return ':';
+       }
+
+       protected function getDefaultParams() {
+               return array(
+                       'cipher' => $this->config['cipher'],
+                       'secret' => count( $this->config['secrets'] ) - 1
+               );
+       }
+
+       public function crypt( $password ) {
+               $secret = $this->config['secrets'][$this->params['secret']];
+
+               if ( $this->hash ) {
+                       $underlyingPassword = $this->factory->newFromCiphertext( openssl_decrypt(
+                                       base64_decode( $this->hash ), $this->params['cipher'],
+                                       $secret, 0, base64_decode( $this->args[0] )
+                               ) );
+               } else {
+                       $underlyingPassword = $this->factory->newFromType( $this->config['underlying'], $this->config );
+               }
+
+               $underlyingPassword->crypt( $password );
+               $iv = MWCryptRand::generate( openssl_cipher_iv_length( $this->params['cipher'] ), true );
+
+               $this->hash = openssl_encrypt(
+                       $underlyingPassword->toString(), $this->params['cipher'], $secret, 0, $iv );
+               $this->args = array( base64_encode( $iv ) );
+       }
+
+       /**
+        * Updates the underlying hash by encrypting it with the newest secret.
+        *
+        * @throws MWException If the configuration is not valid
+        * @return bool True if the password was updated
+        */
+       public function update() {
+               if ( count( $this->args ) != 2 || $this->params == $this->getDefaultParams() ) {
+                       // Hash does not need updating
+                       return false;
+               }
+
+               // Decrypt the underlying hash
+               $underlyingHash = openssl_decrypt(
+                       base64_decode( $this->args[1] ),
+                       $this->params['cipher'],
+                       $this->config['secrets'][$this->params['secret']],
+                       0,
+                       base64_decode( $this->args[0] )
+               );
+
+               // Reset the params
+               $this->params = $this->getDefaultParams();
+
+               // Check the key size with the new params
+               $iv = MWCryptRand::generate( openssl_cipher_iv_length( $this->params['cipher'] ), true );
+               $this->hash = base64_encode( openssl_encrypt(
+                               $underlyingHash,
+                               $this->params['cipher'],
+                               $this->config['secrets'][$this->params['secret']],
+                               0,
+                               $iv
+                       ) );
+               $this->args = array( base64_encode( $iv ) );
+
+               return true;
+       }
+}
diff --git a/includes/password/InvalidPassword.php b/includes/password/InvalidPassword.php
new file mode 100644 (file)
index 0000000..e45b774
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Implements the InvalidPassword class for the MediaWiki software.
+ *
+ * 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
+ */
+
+/**
+ * Represents an invalid password hash. It is represented as the empty string (i.e.,
+ * a password hash with no type).
+ *
+ * No two invalid passwords are equal. Comparing anything to an invalid password will
+ * return false.
+ *
+ * @since 1.24
+ */
+class InvalidPassword extends Password {
+       public function crypt( $plaintext ) {
+       }
+
+       public function toString() {
+               return '';
+       }
+
+       public function equals( $other ) {
+               return false;
+       }
+
+       public function needsUpdate() {
+               return false;
+       }
+}
diff --git a/includes/password/LayeredParameterizedPassword.php b/includes/password/LayeredParameterizedPassword.php
new file mode 100644 (file)
index 0000000..5735e28
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+/**
+ * Implements the LayeredParameterizedPassword class for the MediaWiki software.
+ *
+ * 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 password hash type layers one or more parameterized password types
+ * on top of each other.
+ *
+ * The underlying types must be parameterized. This wrapping type accumulates
+ * all the parameters and arguments from each hash and then passes the hash of
+ * the last layer as the password for the next layer.
+ *
+ * @since 1.24
+ */
+class LayeredParameterizedPassword extends ParameterizedPassword {
+       protected function getDelimiter() {
+               return '!';
+       }
+
+       protected function getDefaultParams() {
+               $params = array();
+
+               foreach ( $this->config['types'] as $type ) {
+                       $passObj = $this->factory->newFromType( $type );
+
+                       if ( !$passObj instanceof ParameterizedPassword ) {
+                               throw new MWException( 'Underlying type must be a parameterized password.' );
+                       } elseif ( $passObj->getDelimiter() === $this->getDelimiter() ) {
+                               throw new MWException( 'Underlying type cannot use same delimiter as encapsulating type.' );
+                       }
+
+                       $params[] = implode( $passObj->getDelimiter(), $passObj->getDefaultParams() );
+               }
+
+               return $params;
+       }
+
+       public function crypt( $password ) {
+               $lastHash = $password;
+               foreach ( $this->config['types'] as $i => $type ) {
+                       // Construct pseudo-hash based on params and arguments
+                       /** @var ParameterizedPassword $passObj */
+                       $passObj = $this->factory->newFromType( $type );
+
+                       $params = '';
+                       $args = '';
+                       if ( $this->params[$i] !== '' ) {
+                               $params = $this->params[$i] . $passObj->getDelimiter();
+                       }
+                       if ( isset( $this->args[$i] ) && $this->args[$i] !== '' ) {
+                               $args = $this->args[$i] . $passObj->getDelimiter();
+                       }
+                       $existingHash = ":$type:" . $params . $args . $this->hash;
+
+                       // Hash the last hash with the next type in the layer
+                       $passObj = $this->factory->newFromCiphertext( $existingHash );
+                       $passObj->crypt( $lastHash );
+
+                       // Move over the params and args
+                       $this->params[$i] = implode( $passObj->getDelimiter(), $passObj->params );
+                       $this->args[$i] = implode( $passObj->getDelimiter(), $passObj->args );
+                       $lastHash = $passObj->hash;
+               }
+
+               $this->hash = $lastHash;
+       }
+
+       /**
+        * Finish the hashing of a partially hashed layered hash
+        *
+        * Given a password hash that is hashed using the first layer of this object's
+        * configuration, perform the remaining layers of password hashing in order to
+        * get an updated hash with all the layers.
+        *
+        * @param ParameterizedPassword $passObj Password hash of the first layer
+        *
+        * @throws MWException If the first parameter is not of the correct type
+        */
+       public function partialCrypt( ParameterizedPassword $passObj ) {
+               $type = $passObj->config['type'];
+               if ( $type !== $this->config['types'][0] ) {
+                       throw new MWException( 'Only a hash in the first layer can be finished.' );
+               }
+
+               // Gather info from the existing hash
+               $this->params[0] = implode( $passObj->getDelimiter(), $passObj->params );
+               $this->args[0] = implode( $passObj->getDelimiter(), $passObj->args );
+               $lastHash = $passObj->hash;
+
+               // Layer the remaining types
+               foreach ( $this->config['types'] as $i => $type ) {
+                       if ( $i == 0 ) {
+                               continue;
+                       };
+
+                       // Construct pseudo-hash based on params and arguments
+                       /** @var ParameterizedPassword $passObj */
+                       $passObj = $this->factory->newFromType( $type );
+
+                       $params = '';
+                       $args = '';
+                       if ( $this->params[$i] !== '' ) {
+                               $params = $this->params[$i] . $passObj->getDelimiter();
+                       }
+                       if ( isset( $this->args[$i] ) && $this->args[$i] !== '' ) {
+                               $args = $this->args[$i] . $passObj->getDelimiter();
+                       }
+                       $existingHash = ":$type:" . $params . $args . $this->hash;
+
+                       // Hash the last hash with the next type in the layer
+                       $passObj = $this->factory->newFromCiphertext( $existingHash );
+                       $passObj->crypt( $lastHash );
+
+                       // Move over the params and args
+                       $this->params[$i] = implode( $passObj->getDelimiter(), $passObj->params );
+                       $this->args[$i] = implode( $passObj->getDelimiter(), $passObj->args );
+                       $lastHash = $passObj->hash;
+               }
+
+               $this->hash = $lastHash;
+       }
+}
diff --git a/includes/password/MWOldPassword.php b/includes/password/MWOldPassword.php
new file mode 100644 (file)
index 0000000..0ba407f
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Implements the MWOldPassword class for the MediaWiki software.
+ *
+ * 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
+ */
+
+/**
+ * The old style of MediaWiki password hashing. It involves
+ * running MD5 on the password.
+ *
+ * @since 1.24
+ */
+class MWOldPassword extends ParameterizedPassword {
+       protected function getDefaultParams() {
+               return array();
+       }
+
+       protected function getDelimiter() {
+               return ':';
+       }
+
+       public function crypt( $plaintext ) {
+               global $wgPasswordSalt;
+
+               if ( $wgPasswordSalt && count( $this->args ) == 1 ) {
+                       $this->hash = md5( $this->args[0] . '-' . md5( $plaintext ) );
+               } else {
+                       $this->args = array();
+                       $this->hash = md5( $plaintext );
+               }
+       }
+}
diff --git a/includes/password/MWSaltedPassword.php b/includes/password/MWSaltedPassword.php
new file mode 100644 (file)
index 0000000..6c6895a
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Implements the BcryptPassword class for the MediaWiki software.
+ *
+ * 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
+ */
+
+/**
+ * The old style of MediaWiki password hashing, with a salt. It involves
+ * running MD5 on the password, and then running MD5 on the salt concatenated
+ * with the first hash.
+ *
+ * @since 1.24
+ */
+class MWSaltedPassword extends ParameterizedPassword {
+       protected function getDefaultParams() {
+               return array();
+       }
+
+       protected function getDelimiter() {
+               return ':';
+       }
+
+       public function crypt( $plaintext ) {
+               if ( count( $this->args ) == 0 ) {
+                       $this->args[] = MWCryptRand::generateHex( 8 );
+               }
+
+               $this->hash = md5( $this->args[0] . '-' . md5( $plaintext ) );
+       }
+}
diff --git a/includes/password/ParameterizedPassword.php b/includes/password/ParameterizedPassword.php
new file mode 100644 (file)
index 0000000..4d6e415
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+/**
+ * Implements the ParameterizedPassword class for the MediaWiki software.
+ *
+ * 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
+ */
+
+/**
+ * Helper class for password hash types that have a delimited set of parameters
+ * inside of the hash.
+ *
+ * All passwords are in the form of :<TYPE>:... as explained in the main Password
+ * class. This class is for hashes in the form of :<TYPE>:<PARAM1>:<PARAM2>:... where
+ * <PARAM1>, <PARAM2>, etc. are parameters that determine how the password was hashed.
+ * Of course, the internal delimiter (which is : by convention and default), can be
+ * changed by overriding the ParameterizedPassword::getDelimiter() function.
+ *
+ * This class requires overriding an additional function: ParameterizedPassword::getDefaultParams().
+ * See the function description for more details on the implementation.
+ *
+ * @since 1.24
+ */
+abstract class ParameterizedPassword extends Password {
+       /**
+        * Named parameters that have default values for this password type
+        * @var array
+        */
+       protected $params = array();
+
+       /**
+        * Extra arguments that were found in the hash. This may or may not make
+        * the hash invalid.
+        * @var array
+        */
+       protected $args = array();
+
+       protected function parseHash( $hash ) {
+               parent::parseHash( $hash );
+
+               if ( $hash === null ) {
+                       $this->params = $this->getDefaultParams();
+                       return;
+               }
+
+               $parts = explode( $this->getDelimiter(), $hash );
+               $paramKeys = array_keys( $this->getDefaultParams() );
+
+               if ( count( $parts ) < count( $paramKeys ) ) {
+                       throw new PasswordError( 'Hash is missing required parameters.' );
+               }
+
+               if ( $paramKeys ) {
+                       $this->args = array_splice( $parts, count( $paramKeys ) );
+                       $this->params = array_combine( $paramKeys, $parts );
+               } else {
+                       $this->args = $parts;
+               }
+
+               if ( $this->args ) {
+                       $this->hash = array_pop( $this->args );
+               } else {
+                       $this->hash = null;
+               }
+       }
+
+       public function needsUpdate() {
+               return parent::needsUpdate() || $this->params !== $this->getDefaultParams();
+       }
+
+       public function toString() {
+               return
+                       ':' . $this->config['type'] . ':' .
+                       implode( $this->getDelimiter(), array_merge( $this->params, $this->args ) ) .
+                       $this->getDelimiter() . $this->hash;
+       }
+
+       /**
+        * Returns the delimiter for the parameters inside the hash
+        *
+        * @return string
+        */
+       abstract protected function getDelimiter();
+
+       /**
+        * Return an ordered array of default parameters for this password hash
+        *
+        * The keys should be the parameter names and the values should be the default
+        * values. Additionally, the order of the array should be the order in which they
+        * appear in the hash.
+        *
+        * When parsing a password hash, the constructor will split the hash based on
+        * the delimiter, and consume as many parts as it can, matching each to a parameter
+        * in this list. Once all the parameters have been filled, all remaining parts will
+        * be considered extra arguments, except, of course, for the very last part, which
+        * is the hash itself.
+        *
+        * @return array
+        */
+       abstract protected function getDefaultParams();
+}
diff --git a/includes/password/Password.php b/includes/password/Password.php
new file mode 100644 (file)
index 0000000..4e395b5
--- /dev/null
@@ -0,0 +1,186 @@
+<?php
+/**
+ * Implements the Password class for the MediaWiki software.
+ *
+ * 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
+ */
+
+/**
+ * Represents a password hash for use in authentication
+ *
+ * Note: All password types are transparently prefixed with :<TYPE>:, where <TYPE>
+ * is the registered type of the hash. This prefix is stripped in the constructor
+ * and is added back in the toString() function.
+ *
+ * When inheriting this class, there are a couple of expectations
+ * to be fulfilled:
+ *  * If Password::toString() is called on an object, and the result is passed back in
+ *    to PasswordFactory::newFromCiphertext(), the result will be identical to the original.
+ *  * The string representations of two Password objects are equal only if
+ *    the original plaintext passwords match. In other words, if the toString() result of
+ *    two objects match, the passwords are the same, and the user will be logged in.
+ *    Since the string representation of a hash includes its type name (@see Password::toString),
+ *    this property is preserved across all classes that inherit Password.
+ *    If a hashing scheme does not fulfill this expectation, it must make sure to override the
+ *    Password::equals() function and use custom comparison logic. However, this is not
+ *    recommended unless absolutely required by the hashing mechanism.
+ * With these two points in mind, when creating a new Password sub-class, there are some functions
+ * you have to override (because they are abstract) and others that you may want to override.
+ *
+ * The abstract functions that must be overridden are:
+ *  * Password::crypt(), which takes a plaintext password and hashes it into a string hash suitable
+ *    for being passed to the constructor of that class, and then stores that hash (and whatever
+ *     other data) into the internal state of the object.
+ * The functions that can optionally be overridden are:
+ *  * Password::parseHash(), which can be useful to override if you need to extract values from or
+ *    otherwise parse a password hash when it's passed to the constructor.
+ *  * Password::needsUpdate(), which can be useful if a specific password hash has different
+ *    logic for when the hash needs to be updated.
+ *  * Password::toString(), which can be useful if the hash was changed in the constructor and
+ *    needs to be re-assembled before being returned as a string. This function is expected to add
+ *    the type back on to the hash, so make sure to do that if you override the function.
+ *  * Password::equals() - This function compares two Password objects to see if they are equal.
+ *    The default is to just do a timing-safe string comparison on the $this->hash values.
+ *
+ * After creating a new password hash type, it can be registered using the static
+ * Password::register() method. The default type is set using the Password::setDefaultType() type.
+ * Types must be registered before they can be set as the default.
+ *
+ * @since 1.24
+ */
+abstract class Password {
+       /**
+        * @var PasswordFactory Factory that created the object
+        */
+       protected $factory;
+
+       /**
+        * String representation of the hash without the type
+        * @var string
+        */
+       protected $hash;
+
+       /**
+        * Array of configuration variables injected from the constructor
+        * @var array
+        */
+       protected $config;
+
+       /**
+        * Construct the Password object using a string hash
+        *
+        * It is strongly recommended not to call this function directly unless you
+        * have a reason to. Use the PasswordFactory class instead.
+        *
+        * @throws MWException If $config does not contain required parameters
+        *
+        * @param PasswordFactory $factory Factory object that created the password
+        * @param array $config Array of engine configuration options for hashing
+        * @param string|null $hash The raw hash, including the type
+        */
+       final public function __construct( PasswordFactory $factory, array $config, $hash = null ) {
+               if ( !isset( $config['type'] ) ) {
+                       throw new MWException( 'Password configuration must contain a type name.' );
+               }
+               $this->config = $config;
+               $this->factory = $factory;
+
+               if ( $hash !== null && strlen( $hash ) >= 3 ) {
+                       // Strip the type from the hash for parsing
+                       $hash = substr( $hash, strpos( $hash, ':', 1 ) + 1 );
+               }
+
+               $this->hash = $hash;
+               $this->parseHash( $hash );
+       }
+
+       /**
+        * Get the type name of the password
+        *
+        * @return string Password type
+        */
+       final public function getType() {
+               return $this->config['type'];
+       }
+
+       /**
+        * Perform any parsing necessary on the hash to see if the hash is valid
+        * and/or to perform logic for seeing if the hash needs updating.
+        *
+        * @param string $hash The hash, with the :<TYPE>: prefix stripped
+        * @throws PasswordError If there is an error in parsing the hash
+        */
+       protected function parseHash( $hash ) {
+       }
+
+       /**
+        * Determine if the hash needs to be updated
+        *
+        * @return bool True if needs update, false otherwise
+        */
+       public function needsUpdate() {
+       }
+
+       /**
+        * Compare one Password object to this object
+        *
+        * By default, do a timing-safe string comparison on the result of
+        * Password::toString() for each object. This can be overridden to do
+        * custom comparison, but it is not recommended unless necessary.
+        *
+        * @param Password|string $other The other password
+        * @return bool True if equal, false otherwise
+        */
+       public function equals( $other ) {
+               if ( !$other instanceof self ) {
+                       // No need to use the factory because we're definitely making
+                       // an object of the same type.
+                       $obj = clone $this;
+                       $obj->crypt( $other );
+                       $other = $obj;
+               }
+
+               return hash_equals( $this->toString(), $other->toString() );
+       }
+
+       /**
+        * Convert this hash to a string that can be stored in the database
+        *
+        * The resulting string should be considered the seralized representation
+        * of this hash, i.e., if the return value were recycled back into
+        * PasswordFactory::newFromCiphertext, the returned object would be equivalent to
+        * this; also, if two objects return the same value from this function, they
+        * are considered equivalent.
+        *
+        * @return string
+        */
+       public function toString() {
+               return ':' . $this->config['type'] . ':' . $this->hash;
+       }
+
+       /**
+        * Hash a password and store the result in this object
+        *
+        * The result of the password hash should be put into the internal
+        * state of the hash object.
+        *
+        * @param string $password Password to hash
+        * @throws PasswordError If an internal error occurs in hashing
+        */
+       abstract public function crypt( $password );
+}
diff --git a/includes/password/PasswordError.php b/includes/password/PasswordError.php
new file mode 100644 (file)
index 0000000..c9707ad
--- /dev/null
@@ -0,0 +1,28 @@
+<?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
+ */
+
+/**
+ * Show an error when any operation involving passwords fails to run.
+ *
+ * @ingroup Exception
+ */
+class PasswordError extends MWException {
+       // NOP
+}
diff --git a/includes/password/PasswordFactory.php b/includes/password/PasswordFactory.php
new file mode 100644 (file)
index 0000000..3b4ebb1
--- /dev/null
@@ -0,0 +1,178 @@
+<?php
+/**
+ * Implements the Password class for the MediaWiki software.
+ *
+ * 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
+ */
+
+/**
+ * Factory class for creating and checking Password objects
+ *
+ * @since 1.24
+ */
+final class PasswordFactory {
+       /**
+        * The default PasswordHash type
+        *
+        * @var string
+        * @see PasswordFactory::setDefaultType
+        */
+       private $default = '';
+
+       /**
+        * Mapping of password types to classes
+        * @var array
+        * @see PasswordFactory::register
+        * @see Setup.php
+        */
+       private $types = array(
+               '' => array( 'type' => '', 'class' => 'InvalidPassword' ),
+       );
+
+       /**
+        * Register a new type of password hash
+        *
+        * @param string $type Unique type name for the hash
+        * @param array $config Array of configuration options
+        */
+       public function register( $type, array $config ) {
+               $config['type'] = $type;
+               $this->types[$type] = $config;
+       }
+
+       /**
+        * Set the default password type
+        *
+        * @throws InvalidArgumentException If the type is not registered
+        * @param string $type Password hash type
+        */
+       public function setDefaultType( $type ) {
+               if ( !isset( $this->types[$type] ) ) {
+                       throw new InvalidArgumentException( "Invalid password type $type." );
+               }
+               $this->default = $type;
+       }
+
+       /**
+        * Initialize the internal static variables using the global variables
+        *
+        * @param Config $config Configuration object to load data from
+        */
+       public function init( Config $config ) {
+               foreach ( $config->get( 'PasswordConfig' ) as $type => $options ) {
+                       $this->register( $type, $options );
+               }
+
+               $this->setDefaultType( $config->get( 'PasswordDefault' ) );
+       }
+
+       /**
+        * Get the list of types of passwords
+        *
+        * @return array
+        */
+       public function getTypes() {
+               return $this->types;
+       }
+
+       /**
+        * Create a new Hash object from an existing string hash
+        *
+        * Parse the type of a hash and create a new hash object based on the parsed type.
+        * Pass the raw hash to the constructor of the new object. Use InvalidPassword type
+        * if a null hash is given.
+        *
+        * @param string|null $hash Existing hash or null for an invalid password
+        * @return Password
+        * @throws PasswordError If hash is invalid or type is not recognized
+        */
+       public function newFromCiphertext( $hash ) {
+               if ( $hash === null || $hash === false || $hash === '' ) {
+                       return new InvalidPassword( $this, array( 'type' => '' ), null );
+               } elseif ( $hash[0] !== ':' ) {
+                       throw new PasswordError( 'Invalid hash given' );
+               }
+
+               $type = substr( $hash, 1, strpos( $hash, ':', 1 ) - 1 );
+               if ( !isset( $this->types[$type] ) ) {
+                       throw new PasswordError( "Unrecognized password hash type $type." );
+               }
+
+               $config = $this->types[$type];
+
+               return new $config['class']( $this, $config, $hash );
+       }
+
+       /**
+        * Make a new default password of the given type.
+        *
+        * @param string $type Existing type
+        * @return Password
+        * @throws PasswordError If hash is invalid or type is not recognized
+        */
+       public function newFromType( $type ) {
+               if ( !isset( $this->types[$type] ) ) {
+                       throw new PasswordError( "Unrecognized password hash type $type." );
+               }
+
+               $config = $this->types[$type];
+
+               return new $config['class']( $this, $config );
+       }
+
+       /**
+        * Create a new Hash object from a plaintext password
+        *
+        * If no existing object is given, make a new default object. If one is given, clone that
+        * object. Then pass the plaintext to Password::crypt().
+        *
+        * @param string $password Plaintext password
+        * @param Password|null $existing Optional existing hash to get options from
+        * @return Password
+        */
+       public function newFromPlaintext( $password, Password $existing = null ) {
+               if ( $existing === null ) {
+                       $config = $this->types[$this->default];
+                       $obj = new $config['class']( $this, $config );
+               } else {
+                       $obj = clone $existing;
+               }
+
+               $obj->crypt( $password );
+
+               return $obj;
+       }
+
+       /**
+        * Determine whether a password object needs updating
+        *
+        * Check whether the given password is of the default type. If it is,
+        * pass off further needsUpdate checks to Password::needsUpdate.
+        *
+        * @param Password $password
+        *
+        * @return bool True if needs update, false otherwise
+        */
+       public function needsUpdate( Password $password ) {
+               if ( $password->getType() !== $this->default ) {
+                       return true;
+               } else {
+                       return $password->needsUpdate();
+               }
+       }
+}
diff --git a/includes/password/Pbkdf2Password.php b/includes/password/Pbkdf2Password.php
new file mode 100644 (file)
index 0000000..080e3b0
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/**
+ * Implements the Pbkdf2Password class for the MediaWiki software.
+ *
+ * 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 PBKDF2-hashed password
+ *
+ * This is a computationally complex password hash for use in modern applications.
+ * The number of rounds can be configured by $wgPasswordConfig['pbkdf2']['cost'].
+ *
+ * @since 1.24
+ */
+class Pbkdf2Password extends ParameterizedPassword {
+       protected function getDefaultParams() {
+               return array(
+                       'algo' => $this->config['algo'],
+                       'rounds' => $this->config['cost'],
+                       'length' => $this->config['length']
+               );
+       }
+
+       protected function getDelimiter() {
+               return ':';
+       }
+
+       public function crypt( $password ) {
+               if ( count( $this->args ) == 0 ) {
+                       $this->args[] = base64_encode( MWCryptRand::generate( 16, true ) );
+               }
+
+               if ( function_exists( 'hash_pbkdf2' ) ) {
+                       $hash = hash_pbkdf2(
+                               $this->params['algo'],
+                               $password,
+                               base64_decode( $this->args[0] ),
+                               (int)$this->params['rounds'],
+                               (int)$this->params['length'],
+                               true
+                       );
+               } else {
+                       $hashLen = strlen( hash( $this->params['algo'], '', true ) );
+                       $blockCount = ceil( $this->params['length'] / $hashLen );
+
+                       $hash = '';
+                       $salt = base64_decode( $this->args[0] );
+                       for ( $i = 1; $i <= $blockCount; ++$i ) {
+                               $roundTotal = $lastRound = hash_hmac(
+                                       $this->params['algo'],
+                                       $salt . pack( 'N', $i ),
+                                       $password,
+                                       true
+                               );
+
+                               for ( $j = 1; $j < $this->params['rounds']; ++$j ) {
+                                       $lastRound = hash_hmac( $this->params['algo'], $lastRound, $password, true );
+                                       $roundTotal ^= $lastRound;
+                               }
+
+                               $hash .= $roundTotal;
+                       }
+
+                       $hash = substr( $hash, 0, $this->params['length'] );
+               }
+
+               $this->hash = base64_encode( $hash );
+       }
+}
index f8d48cc..e77ffd7 100644 (file)
@@ -132,7 +132,7 @@ abstract class PoolCounter {
         * Lets another one grab the lock, and returns the workers
         * waiting on acquireForAnyone()
         *
-        * @return Status value is one of Released/NotLocked/Error
+        * @return Status Value is one of Released/NotLocked/Error
         */
        abstract public function release();
 
@@ -143,7 +143,7 @@ abstract class PoolCounter {
         * the same key can acquire a lock.
         *
         * @param string $key PoolCounter instance key (any string)
-        * @param int $slots the number of slots (max allowed value is 65536)
+        * @param int $slots The number of slots (max allowed value is 65536)
         * @return int
         */
        protected function hashKeyIntoSlots( $key, $slots ) {
index 2b37b0b..d609f61 100644 (file)
@@ -90,7 +90,7 @@ class PoolCounterRedis extends PoolCounter {
 
                $this->keySha1 = sha1( $this->key );
                $met = ini_get( 'max_execution_time' ); // usually 0 in CLI mode
-               $this->lockTTL = $met ? 2*$met : 3600;
+               $this->lockTTL = $met ? 2 * $met : 3600;
 
                if ( self::$active === null ) {
                        self::$active = array();
index 1bc1a8b..c0be7a1 100644 (file)
@@ -64,6 +64,9 @@ abstract class PoolCounterWork {
 
        /**
         * Do something with the error, like showing it to the user.
+        *
+        * @param Status $status
+        *
         * @return bool
         */
        public function error( $status ) {
@@ -155,73 +158,3 @@ abstract class PoolCounterWork {
                }
        }
 }
-
-/**
- * Convenience class for dealing with PoolCounters using callbacks
- * @since 1.22
- */
-class PoolCounterWorkViaCallback extends PoolCounterWork {
-       /** @var callable */
-       protected $doWork;
-       /** @var callable|null */
-       protected $doCachedWork;
-       /** @var callable|null */
-       protected $fallback;
-       /** @var callable|null */
-       protected $error;
-
-       /**
-        * Build a PoolCounterWork class from a type, key, and callback map.
-        *
-        * The callback map must at least have a callback for the 'doWork' method.
-        * Additionally, callbacks can be provided for the 'doCachedWork', 'fallback',
-        * and 'error' methods. Methods without callbacks will be no-ops that return false.
-        * If a 'doCachedWork' callback is provided, then execute() may wait for any prior
-        * process in the pool to finish and reuse its cached result.
-        *
-        * @param string $type
-        * @param string $key
-        * @param array $callbacks Map of callbacks
-        * @throws MWException
-        */
-       public function __construct( $type, $key, array $callbacks ) {
-               parent::__construct( $type, $key );
-               foreach ( array( 'doWork', 'doCachedWork', 'fallback', 'error' ) as $name ) {
-                       if ( isset( $callbacks[$name] ) ) {
-                               if ( !is_callable( $callbacks[$name] ) ) {
-                                       throw new MWException( "Invalid callback provided for '$name' function." );
-                               }
-                               $this->$name = $callbacks[$name];
-                       }
-               }
-               if ( !isset( $this->doWork ) ) {
-                       throw new MWException( "No callback provided for 'doWork' function." );
-               }
-               $this->cacheable = isset( $this->doCachedWork );
-       }
-
-       public function doWork() {
-               return call_user_func_array( $this->doWork, array() );
-       }
-
-       public function getCachedWork() {
-               if ( $this->doCachedWork ) {
-                       return call_user_func_array( $this->doCachedWork, array() );
-               }
-               return false;
-       }
-
-       public function fallback() {
-               if ( $this->fallback ) {
-                       return call_user_func_array( $this->fallback, array() );
-               }
-               return false;
-       }
-
-       public function error( $status ) {
-               if ( $this->error ) {
-                       return call_user_func_array( $this->error, array( $status ) );
-               }
-               return false;
-       }
-}
diff --git a/includes/poolcounter/PoolCounterWorkViaCallback.php b/includes/poolcounter/PoolCounterWorkViaCallback.php
new file mode 100644 (file)
index 0000000..af83d2e
--- /dev/null
@@ -0,0 +1,92 @@
+<?php
+/**
+ * Provides of semaphore semantics for restricting the number
+ * of workers that may be concurrently performing the same task.
+ *
+ * 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
+ */
+
+/**
+ * Convenience class for dealing with PoolCounters using callbacks
+ * @since 1.22
+ */
+class PoolCounterWorkViaCallback extends PoolCounterWork {
+       /** @var callable */
+       protected $doWork;
+       /** @var callable|null */
+       protected $doCachedWork;
+       /** @var callable|null */
+       protected $fallback;
+       /** @var callable|null */
+       protected $error;
+
+       /**
+        * Build a PoolCounterWork class from a type, key, and callback map.
+        *
+        * The callback map must at least have a callback for the 'doWork' method.
+        * Additionally, callbacks can be provided for the 'doCachedWork', 'fallback',
+        * and 'error' methods. Methods without callbacks will be no-ops that return false.
+        * If a 'doCachedWork' callback is provided, then execute() may wait for any prior
+        * process in the pool to finish and reuse its cached result.
+        *
+        * @param string $type
+        * @param string $key
+        * @param array $callbacks Map of callbacks
+        * @throws MWException
+        */
+       public function __construct( $type, $key, array $callbacks ) {
+               parent::__construct( $type, $key );
+               foreach ( array( 'doWork', 'doCachedWork', 'fallback', 'error' ) as $name ) {
+                       if ( isset( $callbacks[$name] ) ) {
+                               if ( !is_callable( $callbacks[$name] ) ) {
+                                       throw new MWException( "Invalid callback provided for '$name' function." );
+                               }
+                               $this->$name = $callbacks[$name];
+                       }
+               }
+               if ( !isset( $this->doWork ) ) {
+                       throw new MWException( "No callback provided for 'doWork' function." );
+               }
+               $this->cacheable = isset( $this->doCachedWork );
+       }
+
+       public function doWork() {
+               return call_user_func_array( $this->doWork, array() );
+       }
+
+       public function getCachedWork() {
+               if ( $this->doCachedWork ) {
+                       return call_user_func_array( $this->doCachedWork, array() );
+               }
+               return false;
+       }
+
+       public function fallback() {
+               if ( $this->fallback ) {
+                       return call_user_func_array( $this->fallback, array() );
+               }
+               return false;
+       }
+
+       public function error( $status ) {
+               if ( $this->error ) {
+                       return call_user_func_array( $this->error, array( $status ) );
+               }
+               return false;
+       }
+}
index 4cdb0ff..5e7e391 100644 (file)
@@ -45,9 +45,9 @@ class PoolWorkArticleView extends PoolCounterWork {
 
        /**
         * @param Page $page
+        * @param ParserOptions $parserOptions ParserOptions to use for the parse
         * @param int $revid ID of the revision being parsed.
         * @param bool $useParserCache Whether to use the parser cache.
-        * @param ParserOptions $parserOptions ParserOptions to use for the parse
         *   operation.
         * @param Content|string $content Content to parse or null to load it; may
         *   also be given as a wikitext string, for BC.
index 75f6966..418b5d4 100644 (file)
  * @file
  * @ingroup Profiler
  * @defgroup Profiler Profiler
- * This file is only included if profiling is enabled
  */
 
+/**
+ * Get system resource usage of current request context.
+ * Invokes the getrusage(2) system call, requesting RUSAGE_SELF if on PHP5
+ * or RUSAGE_THREAD if on HHVM. Returns false if getrusage is not available.
+ *
+ * @since 1.24
+ * @return array|bool Resource usage data or false if no data available.
+ */
+function wfGetRusage() {
+       if ( !function_exists( 'getrusage' ) ) {
+               return false;
+       } elseif ( defined ( 'HHVM_VERSION' ) ) {
+               return getrusage( 2 /* RUSAGE_THREAD */ );
+       } else {
+               return getrusage( 0 /* RUSAGE_SELF */ );
+       }
+}
+
 /**
  * Begin profiling of a function
- * @param string $functionname name of the function we will profile
+ * @param string $functionname Name of the function we will profile
  */
 function wfProfileIn( $functionname ) {
        if ( Profiler::$__instance === null ) { // use this directly to reduce overhead
@@ -38,7 +55,7 @@ function wfProfileIn( $functionname ) {
 
 /**
  * Stop profiling of a function
- * @param string $functionname name of the function we have profiled
+ * @param string $functionname Name of the function we have profiled
  */
 function wfProfileOut( $functionname = 'missing' ) {
        if ( Profiler::$__instance === null ) { // use this directly to reduce overhead
@@ -126,7 +143,7 @@ abstract class Profiler {
                        if ( is_array( $wgProfiler ) ) {
                                if ( !isset( $wgProfiler['class'] ) ) {
                                        $class = 'ProfilerStub';
-                               } elseif ( $wgProfiler['class'] === 'Profiler'  ) {
+                               } elseif ( $wgProfiler['class'] === 'Profiler' ) {
                                        $class = 'ProfilerStub'; // b/c; don't explode
                                } else {
                                        $class = $wgProfiler['class'];
@@ -196,7 +213,7 @@ abstract class Profiler {
        /**
         * Called by wfProfieOut()
         *
-        * @param  string $functionname
+        * @param string $functionname
         */
        abstract public function profileOut( $functionname );
 
@@ -272,10 +289,10 @@ abstract class Profiler {
         */
        protected function getTime( $metric = 'wall' ) {
                if ( $metric === 'cpu' || $metric === 'user' ) {
-                       if ( !function_exists( 'getrusage' ) ) {
+                       $ru = wfGetRusage();
+                       if ( !$ru ) {
                                return 0;
                        }
-                       $ru = getrusage();
                        $time = $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1e6;
                        if ( $metric === 'cpu' ) {
                                # This is the time of system calls, added to the user time
@@ -326,7 +343,7 @@ abstract class Profiler {
        /**
         * Add an entry in the debug log file
         *
-        * @param string $s to output
+        * @param string $s String to output
         */
        protected function debug( $s ) {
                if ( function_exists( 'wfDebug' ) ) {
@@ -338,7 +355,7 @@ abstract class Profiler {
         * Add an entry in the debug log group
         *
         * @param string $group Group to send the message to
-        * @param string $s to output
+        * @param string $s String to output
         */
        protected function debugGroup( $group, $s ) {
                if ( function_exists( 'wfDebugLog' ) ) {
@@ -356,7 +373,7 @@ abstract class Profiler {
  * @since 1.24
  */
 class TransactionProfiler {
-       /** @var float seconds */
+       /** @var float Seconds */
        protected $mDBLockThreshold = 3.0;
        /** @var array DB/server name => (active trx count, time, DBs involved) */
        protected $mDBTrxHoldingLocks = array();
@@ -397,7 +414,7 @@ class TransactionProfiler {
        public function recordFunctionCompletion( $method, $realtime ) {
                if ( !$this->mDBTrxHoldingLocks ) {
                        return; // short-circuit
-               // @TODO: hardcoded check is a tad janky (what about FOR UPDATE?)
+               // @todo hardcoded check is a tad janky (what about FOR UPDATE?)
                } elseif ( !preg_match( '/^query-m: (?!SELECT)/', $method )
                        && $realtime < $this->mDBLockThreshold
                ) {
index abcd23c..af3c774 100644 (file)
@@ -94,8 +94,8 @@ class ProfilerMwprof extends Profiler {
         * Update an entry with timing data.
         *
         * @param string $name Section name
-        * @param float $elapsedCpu elapsed CPU time
-        * @param float $elapsedWall elapsed wall-clock time
+        * @param float $elapsedCpu Elapsed CPU time
+        * @param float $elapsedWall Elapsed wall-clock time
         */
        public function updateRunningEntry( $name, $elapsedCpu, $elapsedWall ) {
                // If this is the first measurement for this entry, store plain values.
index 22d5cd4..627b4de 100644 (file)
@@ -58,7 +58,8 @@ class ProfilerSimpleUDP extends ProfilerStandard {
                                continue;
                        }
                        $pfline = sprintf( $wgUDPProfilerFormatString, $this->getProfileID(), $pfdata['count'],
-                               $pfdata['cpu'], $pfdata['cpu_sq'], $pfdata['real'], $pfdata['real_sq'], $entry );
+                               $pfdata['cpu'], $pfdata['cpu_sq'], $pfdata['real'], $pfdata['real_sq'], $entry,
+                               $pfdata['memory'] );
                        $length = strlen( $pfline );
                        /* printf("<!-- $pfline -->"); */
                        if ( $length + $plength > 1400 ) {
index 5de9982..cc13416 100644 (file)
@@ -299,7 +299,7 @@ class ProfilerStandard extends Profiler {
        /**
         * Recursive function the format the current profiling array into a tree
         *
-        * @param array $stack profiling array
+        * @param array $stack Profiling array
         * @return array
         */
        protected function remapCallTree( array $stack ) {
@@ -339,6 +339,7 @@ class ProfilerStandard extends Profiler {
 
        /**
         * Callback to get a formatted line for the call tree
+        * @param array $entry
         * @return string
         */
        protected function getCallTreeLine( $entry ) {
@@ -514,6 +515,7 @@ class ProfilerStandard extends Profiler {
 
        /**
         * Dummy calls to wfProfileIn/wfProfileOut to calculate its overhead
+        * @param int $profileCount
         */
        protected static function calculateOverhead( $profileCount ) {
                wfProfileIn( '-overhead-total' );
index 18e6003..519606c 100644 (file)
@@ -39,64 +39,63 @@ abstract class MachineReadableRCFeedFormatter implements RCFeedFormatter {
         */
        public function getLine( array $feed, RecentChange $rc, $actionComment ) {
                global $wgCanonicalServer, $wgServerName, $wgScriptPath;
-               $attrib = $rc->getAttributes();
 
                $packet = array(
                        // Usually, RC ID is exposed only for patrolling purposes,
                        // but there is no real reason not to expose it in other cases,
                        // and I can see how this may be potentially useful for clients.
-                       'id' => $attrib['rc_id'],
-                       'type' => RecentChange::parseFromRCType( $attrib['rc_type'] ),
+                       'id' => $rc->getAttribute( 'rc_id' ),
+                       'type' => RecentChange::parseFromRCType( $rc->getAttribute( 'rc_type' ) ),
                        'namespace' => $rc->getTitle()->getNamespace(),
                        'title' => $rc->getTitle()->getPrefixedText(),
-                       'comment' => $attrib['rc_comment'],
-                       'timestamp' => (int)wfTimestamp( TS_UNIX, $attrib['rc_timestamp'] ),
-                       'user' => $attrib['rc_user_text'],
-                       'bot' => (bool)$attrib['rc_bot'],
+                       'comment' => $rc->getAttribute( 'rc_comment' ),
+                       'timestamp' => (int)wfTimestamp( TS_UNIX, $rc->getAttribute( 'rc_timestamp' ) ),
+                       'user' => $rc->getAttribute( 'rc_user_text' ),
+                       'bot' => (bool)$rc->getAttribute( 'rc_bot' ),
                );
 
                if ( isset( $feed['channel'] ) ) {
                        $packet['channel'] = $feed['channel'];
                }
 
-               $type = $attrib['rc_type'];
+               $type = $rc->getAttribute( 'rc_type' );
                if ( $type == RC_EDIT || $type == RC_NEW ) {
                        global $wgUseRCPatrol, $wgUseNPPatrol;
 
-                       $packet['minor'] = (bool)$attrib['rc_minor'];
+                       $packet['minor'] = (bool)$rc->getAttribute( 'rc_minor' );
                        if ( $wgUseRCPatrol || ( $type == RC_NEW && $wgUseNPPatrol ) ) {
-                               $packet['patrolled'] = (bool)$attrib['rc_patrolled'];
+                               $packet['patrolled'] = (bool)$rc->getAttribute( 'rc_patrolled' );
                        }
                }
 
                switch ( $type ) {
                        case RC_EDIT:
                                $packet['length'] = array(
-                                       'old' => $attrib['rc_old_len'],
-                                       'new' => $attrib['rc_new_len']
+                                       'old' => $rc->getAttribute( 'rc_old_len' ),
+                                       'new' => $rc->getAttribute( 'rc_new_len' )
                                );
                                $packet['revision'] = array(
-                                       'old' => $attrib['rc_last_oldid'],
-                                       'new' => $attrib['rc_this_oldid']
+                                       'old' => $rc->getAttribute( 'rc_last_oldid' ),
+                                       'new' => $rc->getAttribute( 'rc_this_oldid' )
                                );
                                break;
 
                        case RC_NEW:
-                               $packet['length'] = array( 'old' => null, 'new' => $attrib['rc_new_len'] );
-                               $packet['revision'] = array( 'old' => null, 'new' => $attrib['rc_this_oldid'] );
+                               $packet['length'] = array( 'old' => null, 'new' => $rc->getAttribute( 'rc_new_len' ) );
+                               $packet['revision'] = array( 'old' => null, 'new' => $rc->getAttribute( 'rc_this_oldid' ) );
                                break;
 
                        case RC_LOG:
-                               $packet['log_id'] = $attrib['rc_logid'];
-                               $packet['log_type'] = $attrib['rc_log_type'];
-                               $packet['log_action'] = $attrib['rc_log_action'];
-                               if ( $attrib['rc_params'] ) {
+                               $packet['log_id'] = $rc->getAttribute( 'rc_logid' );
+                               $packet['log_type'] = $rc->getAttribute( 'rc_log_type' );
+                               $packet['log_action'] = $rc->getAttribute( 'rc_log_action' );
+                               if ( $rc->getAttribute( 'rc_params' ) ) {
                                        wfSuppressWarnings();
-                                       $params = unserialize( $attrib['rc_params'] );
+                                       $params = unserialize( $rc->getAttribute( 'rc_params' ) );
                                        wfRestoreWarnings();
                                        if (
                                                // If it's an actual serialised false...
-                                               $attrib['rc_params'] == serialize( false ) ||
+                                               $rc->getAttribute( 'rc_params' ) == serialize( false ) ||
                                                // Or if we did not get false back when trying to unserialise
                                                $params !== false
                                        ) {
@@ -113,7 +112,7 @@ abstract class MachineReadableRCFeedFormatter implements RCFeedFormatter {
                                                }
                                                $packet['log_params'] = $logParams;
                                        } else {
-                                               $packet['log_params'] = explode( "\n", $attrib['rc_params'] );
+                                               $packet['log_params'] = explode( "\n", $rc->getAttribute( 'rc_params' ) );
                                        }
                                }
                                $packet['log_action_comment'] = $actionComment;
index 066ecbe..0b0cd86 100644 (file)
@@ -28,10 +28,10 @@ interface RCFeedEngine {
        /**
         * Sends some text to the specified live feed.
         *
-        * @see RecentChange::cleanupForIRC
+        * @see IRCColourfulRCFeedFormatter::cleanupForIRC
         * @param array $feed The feed, as configured in an associative array
         * @param string $line The text to send
-        * @return bool success
+        * @return bool Success
         */
        public function send( array $feed, $line );
 }
diff --git a/includes/resourceloader/DerivativeResourceLoaderContext.php b/includes/resourceloader/DerivativeResourceLoaderContext.php
new file mode 100644 (file)
index 0000000..d114d7e
--- /dev/null
@@ -0,0 +1,202 @@
+<?php
+/**
+ * Derivative context for resource loader modules.
+ *
+ * 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 Kunal Mehta
+ */
+
+/**
+ * Allows changing specific properties of a context object,
+ * without changing the main one. Inspired by DerivativeContext.
+ *
+ * @since 1.24
+ */
+class DerivativeResourceLoaderContext extends ResourceLoaderContext {
+
+       /**
+        * @var ResourceLoaderContext
+        */
+       private $context;
+       protected $modules;
+       protected $language;
+       protected $direction;
+       protected $skin;
+       protected $user;
+       protected $debug;
+       protected $only;
+       protected $version;
+       protected $hash;
+       protected $raw;
+
+       public function __construct( ResourceLoaderContext $context ) {
+               $this->context = $context;
+       }
+
+       public function getModules() {
+               if ( !is_null( $this->modules ) ) {
+                       return $this->modules;
+               } else {
+                       return $this->context->getModules();
+               }
+       }
+
+       /**
+        * @param string[] $modules
+        */
+       public function setModules( array $modules ) {
+               $this->modules = $modules;
+       }
+
+       public function getLanguage() {
+               if ( !is_null( $this->language ) ) {
+                       return $this->language;
+               } else {
+                       return $this->context->getLanguage();
+               }
+       }
+
+       /**
+        * @param string $language
+        */
+       public function setLanguage( $language ) {
+               $this->language = $language;
+               $this->direction = null; // Invalidate direction since it might be based on language
+               $this->hash = null;
+       }
+
+       public function getDirection() {
+               if ( !is_null( $this->direction ) ) {
+                       return $this->direction;
+               } else {
+                       return $this->context->getDirection();
+               }
+       }
+
+       /**
+        * @param string $direction
+        */
+       public function setDirection( $direction ) {
+               $this->direction = $direction;
+               $this->hash = null;
+       }
+
+       public function getSkin() {
+               if ( !is_null( $this->skin ) ) {
+                       return $this->skin;
+               } else {
+                       return $this->context->getSkin();
+               }
+       }
+
+       /**
+        * @param string $skin
+        */
+       public function setSkin( $skin ) {
+               $this->skin = $skin;
+               $this->hash = null;
+       }
+
+       public function getUser() {
+               if ( !is_null( $this->user ) ) {
+                       return $this->user;
+               } else {
+                       return $this->context->getUser();
+               }
+       }
+
+       /**
+        * @param string $user
+        */
+       public function setUser( $user ) {
+               $this->user = $user;
+               $this->hash = null;
+       }
+
+       public function getDebug() {
+               if ( !is_null( $this->debug ) ) {
+                       return $this->debug;
+               } else {
+                       return $this->context->getDebug();
+               }
+       }
+
+       /**
+        * @param bool $debug
+        */
+       public function setDebug( $debug ) {
+               $this->debug = $debug;
+               $this->hash = null;
+       }
+
+       public function getOnly() {
+               if ( !is_null( $this->only ) ) {
+                       return $this->only;
+               } else {
+                       return $this->context->getOnly();
+               }
+       }
+
+       /**
+        * @param string $only
+        */
+       public function setOnly( $only ) {
+               $this->only = $only;
+               $this->hash = null;
+       }
+
+       public function getVersion() {
+               if ( !is_null( $this->version ) ) {
+                       return $this->version;
+               } else {
+                       return $this->context->getVersion();
+               }
+       }
+
+       /**
+        * @param string $version
+        */
+       public function setVersion( $version ) {
+               $this->version = $version;
+               $this->hash = null;
+       }
+
+       public function getRaw() {
+               if ( !is_null( $this->raw ) ) {
+                       return $this->raw;
+               } else {
+                       return $this->context->getRaw();
+               }
+       }
+
+       /**
+        * @param bool $raw
+        */
+       public function setRaw( $raw ) {
+               $this->raw = $raw;
+       }
+
+       public function getRequest() {
+               return $this->context->getRequest();
+       }
+
+       public function getResourceLoader() {
+               return $this->context->getResourceLoader();
+       }
+
+}
index 5ac874d..4f1414b 100644 (file)
@@ -32,9 +32,6 @@ class ResourceLoader {
        /** @var int */
        protected static $filterCacheVersion = 7;
 
-       /** @var array */
-       protected static $requiredSourceProperties = array( 'loadScript' );
-
        /** @var bool */
        protected static $debugMode = null;
 
@@ -44,13 +41,16 @@ class ResourceLoader {
        /** @var array Associative array mapping module name to info associative array */
        protected $moduleInfos = array();
 
+       /** @var Config $config */
+       private $config;
+
        /**
         * @var array Associative array mapping framework ids to a list of names of test suite modules
         *      like array( 'qunit' => array( 'mediawiki.tests.qunit.suites', 'ext.foo.tests', .. ), .. )
         */
        protected $testModuleNames = array();
 
-       /** @var array e.g. array( 'source-id' => array( 'loadScript' => 'http://.../load.php' ) ) */
+       /** @var array E.g. array( 'source-id' => 'http://.../load.php' ) */
        protected $sources = array();
 
        /** @var bool */
@@ -152,7 +152,6 @@ class ResourceLoader {
         * @return string Filtered data, or a comment containing an error message
         */
        public function filter( $filter, $data, $cacheReport = true ) {
-               global $wgResourceLoaderMinifierStatementsOnOwnLine, $wgResourceLoaderMinifierMaxLineLength;
                wfProfileIn( __METHOD__ );
 
                // For empty/whitespace-only data or for unknown filters, don't perform
@@ -180,8 +179,8 @@ class ResourceLoader {
                        switch ( $filter ) {
                                case 'minify-js':
                                        $result = JavaScriptMinifier::minify( $data,
-                                               $wgResourceLoaderMinifierStatementsOnOwnLine,
-                                               $wgResourceLoaderMinifierMaxLineLength
+                                               $this->config->get( 'ResourceLoaderMinifierStatementsOnOwnLine' ),
+                                               $this->config->get( 'ResourceLoaderMinifierMaxLineLength' )
                                        );
                                        if ( $cacheReport ) {
                                                $result .= "\n/* cache key: $key */";
@@ -214,34 +213,46 @@ class ResourceLoader {
 
        /**
         * Register core modules and runs registration hooks.
+        * @param Config|null $config
         */
-       public function __construct() {
-               global $IP, $wgResourceModules, $wgResourceLoaderSources, $wgLoadScript, $wgEnableJavaScriptTest;
+       public function __construct( Config $config = null ) {
+               global $IP;
 
                wfProfileIn( __METHOD__ );
 
+               if ( $config === null ) {
+                       wfDebug( __METHOD__ . ' was called without providing a Config instance' );
+                       $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               }
+
+               $this->config = $config;
+
                // Add 'local' source first
-               $this->addSource(
-                       'local',
-                       array( 'loadScript' => $wgLoadScript, 'apiScript' => wfScript( 'api' ) )
-               );
+               $this->addSource( 'local', wfScript( 'load' ) );
 
                // Add other sources
-               $this->addSource( $wgResourceLoaderSources );
+               $this->addSource( $config->get( 'ResourceLoaderSources' ) );
 
                // Register core modules
                $this->register( include "$IP/resources/Resources.php" );
                // Register extension modules
                wfRunHooks( 'ResourceLoaderRegisterModules', array( &$this ) );
-               $this->register( $wgResourceModules );
+               $this->register( $config->get( 'ResourceModules' ) );
 
-               if ( $wgEnableJavaScriptTest === true ) {
+               if ( $config->get( 'EnableJavaScriptTest' ) === true ) {
                        $this->registerTestModules();
                }
 
                wfProfileOut( __METHOD__ );
        }
 
+       /**
+        * @return Config
+        */
+       public function getConfig() {
+               return $this->config;
+       }
+
        /**
         * Register a module with the ResourceLoader system.
         *
@@ -293,6 +304,46 @@ class ResourceLoader {
                                        '\': expected ResourceLoaderModule or array (got: ' . gettype( $info ) . ')'
                                );
                        }
+
+                       // Last-minute changes
+
+                       // Apply custom skin-defined styles to existing modules.
+                       if ( $this->isFileModule( $name ) ) {
+                               foreach ( $this->config->get( 'ResourceModuleSkinStyles' ) as $skinName => $skinStyles ) {
+                                       // If this module already defines skinStyles for this skin, ignore $wgResourceModuleSkinStyles.
+                                       if ( isset( $this->moduleInfos[$name]['skinStyles'][$skinName] ) ) {
+                                               continue;
+                                       }
+
+                                       // If $name is preceded with a '+', the defined style files will be added to 'default'
+                                       // skinStyles, otherwise 'default' will be ignored as it normally would be.
+                                       if ( isset( $skinStyles[$name] ) ) {
+                                               $paths = (array)$skinStyles[$name];
+                                               $styleFiles = array();
+                                       } elseif ( isset( $skinStyles['+' . $name] ) ) {
+                                               $paths = (array)$skinStyles['+' . $name];
+                                               $styleFiles = isset( $this->moduleInfos[$name]['skinStyles']['default'] ) ?
+                                                       $this->moduleInfos[$name]['skinStyles']['default'] :
+                                                       array();
+                                       } else {
+                                               continue;
+                                       }
+
+                                       // Add new file paths, remapping them to refer to our directories and not use settings
+                                       // from the module we're modifying. These can come from the base definition or be defined
+                                       // for each module.
+                                       list( $localBasePath, $remoteBasePath ) =
+                                               ResourceLoaderFileModule::extractBasePaths( $skinStyles );
+                                       list( $localBasePath, $remoteBasePath ) =
+                                               ResourceLoaderFileModule::extractBasePaths( $paths, $localBasePath, $remoteBasePath );
+
+                                       foreach ( $paths as $path ) {
+                                               $styleFiles[] = new ResourceLoaderFilePath( $path, $localBasePath, $remoteBasePath );
+                                       }
+
+                                       $this->moduleInfos[$name]['skinStyles'][$skinName] = $styleFiles;
+                               }
+                       }
                }
 
                wfProfileOut( __METHOD__ );
@@ -301,9 +352,9 @@ class ResourceLoader {
        /**
         */
        public function registerTestModules() {
-               global $IP, $wgEnableJavaScriptTest;
+               global $IP;
 
-               if ( $wgEnableJavaScriptTest !== true ) {
+               if ( $this->config->get( 'EnableJavaScriptTest' ) !== true ) {
                        throw new MWException( 'Attempt to register JavaScript test modules '
                                . 'but <code>$wgEnableJavaScriptTest</code> is false. '
                                . 'Edit your <code>LocalSettings.php</code> to enable it.' );
@@ -344,14 +395,12 @@ class ResourceLoader {
        /**
         * Add a foreign source of modules.
         *
-        * Source properties:
-        * 'loadScript': URL (either fully-qualified or protocol-relative) of load.php for this source
-        *
-        * @param mixed $id Source ID (string), or array( id1 => props1, id2 => props2, ... )
-        * @param array $properties Source properties
+        * @param array|string $id Source ID (string), or array( id1 => loadUrl, id2 => loadUrl, ... )
+        * @param string|array $loadUrl load.php url (string), or array with loadUrl key for
+        *  backwards-compatibility.
         * @throws MWException
         */
-       public function addSource( $id, $properties = null ) {
+       public function addSource( $id, $loadUrl = null ) {
                // Allow multiple sources to be registered in one call
                if ( is_array( $id ) ) {
                        foreach ( $id as $key => $value ) {
@@ -368,14 +417,18 @@ class ResourceLoader {
                        );
                }
 
-               // Validate properties
-               foreach ( self::$requiredSourceProperties as $prop ) {
-                       if ( !isset( $properties[$prop] ) ) {
-                               throw new MWException( "Required property $prop missing from source ID $id" );
+               // Pre 1.24 backwards-compatibility
+               if ( is_array( $loadUrl ) ) {
+                       if ( !isset( $loadUrl['loadScript'] ) ) {
+                               throw new MWException(
+                                       __METHOD__ . ' was passed an array with no "loadScript" key.'
+                               );
                        }
+
+                       $loadUrl = $loadUrl['loadScript'];
                }
 
-               $this->sources[$id] = $properties;
+               $this->sources[$id] = $loadUrl;
        }
 
        /**
@@ -439,7 +492,9 @@ class ResourceLoader {
                                } else {
                                        $class = $info['class'];
                                }
+                               /** @var ResourceLoaderModule $object */
                                $object = new $class( $info );
+                               $object->setConfig( $this->getConfig() );
                        }
                        $object->setName( $name );
                        $this->modules[$name] = $object;
@@ -448,25 +503,56 @@ class ResourceLoader {
                return $this->modules[$name];
        }
 
+       /**
+        * Return whether the definition of a module corresponds to a simple ResourceLoaderFileModule.
+        *
+        * @param string $name Module name
+        * @return bool
+        */
+       protected function isFileModule( $name ) {
+               if ( !isset( $this->moduleInfos[$name] ) ) {
+                       return false;
+               }
+               $info = $this->moduleInfos[$name];
+               if ( isset( $info['object'] ) || isset( $info['class'] ) ) {
+                       return false;
+               }
+               return true;
+       }
+
        /**
         * Get the list of sources.
         *
-        * @return array Like array( id => array of properties, .. )
+        * @return array Like array( id => load.php url, .. )
         */
        public function getSources() {
                return $this->sources;
        }
 
+       /**
+        * Get the URL to the load.php endpoint for the given
+        * ResourceLoader source
+        *
+        * @since 1.24
+        * @param string $source
+        * @throws MWException On an invalid $source name
+        * @return string
+        */
+       public function getLoadScript( $source ) {
+               if ( !isset( $this->sources[$source] ) ) {
+                       throw new MWException( "The $source source was never registered in ResourceLoader." );
+               }
+               return $this->sources[$source];
+       }
+
        /**
         * Output a response to a load request, including the content-type header.
         *
         * @param ResourceLoaderContext $context Context in which a response should be formed
         */
        public function respond( ResourceLoaderContext $context ) {
-               global $wgCacheEpoch, $wgUseFileCache;
-
                // Use file cache if enabled and available...
-               if ( $wgUseFileCache ) {
+               if ( $this->config->get( 'UseFileCache' ) ) {
                        $fileCache = ResourceFileCache::newFromContext( $context );
                        if ( $this->tryRespondFromFileCache( $fileCache, $context ) ) {
                                return; // output handled
@@ -522,7 +608,7 @@ class ResourceLoader {
 
                // To send Last-Modified and support If-Modified-Since, we need to detect
                // the last modified time
-               $mtime = wfTimestamp( TS_UNIX, $wgCacheEpoch );
+               $mtime = wfTimestamp( TS_UNIX, $this->config->get( 'CacheEpoch' ) );
                foreach ( $modules as $module ) {
                        /**
                         * @var $module ResourceLoaderModule
@@ -590,18 +676,18 @@ class ResourceLoader {
         * @return void
         */
        protected function sendResponseHeaders( ResourceLoaderContext $context, $mtime, $errors ) {
-               global $wgResourceLoaderMaxage;
+               $rlMaxage = $this->config->get( 'ResourceLoaderMaxage' );
                // If a version wasn't specified we need a shorter expiry time for updates
                // to propagate to clients quickly
                // If there were errors, we also need a shorter expiry time so we can recover quickly
                if ( is_null( $context->getVersion() ) || $errors ) {
-                       $maxage = $wgResourceLoaderMaxage['unversioned']['client'];
-                       $smaxage = $wgResourceLoaderMaxage['unversioned']['server'];
+                       $maxage = $rlMaxage['unversioned']['client'];
+                       $smaxage = $rlMaxage['unversioned']['server'];
                // If a version was specified we can use a longer expiry time since changing
                // version numbers causes cache misses
                } else {
-                       $maxage = $wgResourceLoaderMaxage['versioned']['client'];
-                       $smaxage = $wgResourceLoaderMaxage['versioned']['server'];
+                       $maxage = $rlMaxage['versioned']['client'];
+                       $smaxage = $rlMaxage['versioned']['server'];
                }
                if ( $context->getOnly() === 'styles' ) {
                        header( 'Content-Type: text/css; charset=utf-8' );
@@ -669,13 +755,13 @@ class ResourceLoader {
        protected function tryRespondFromFileCache(
                ResourceFileCache $fileCache, ResourceLoaderContext $context
        ) {
-               global $wgResourceLoaderMaxage;
+               $rlMaxage = $this->config->get( 'ResourceLoaderMaxage' );
                // Buffer output to catch warnings.
                ob_start();
                // Get the maximum age the cache can be
                $maxage = is_null( $context->getVersion() )
-                       ? $wgResourceLoaderMaxage['unversioned']['server']
-                       : $wgResourceLoaderMaxage['versioned']['server'];
+                       ? $rlMaxage['unversioned']['server']
+                       : $rlMaxage['versioned']['server'];
                // Minimum timestamp the cache file must have
                $good = $fileCache->isCacheGood( wfTimestamp( TS_MW, time() - $maxage ) );
                if ( !$good ) {
@@ -765,7 +851,7 @@ class ResourceLoader {
                // Pre-fetch blobs
                if ( $context->shouldIncludeMessages() ) {
                        try {
-                               $blobs = MessageBlobStore::get( $this, $modules, $context->getLanguage() );
+                               $blobs = MessageBlobStore::getInstance()->get( $this, $modules, $context->getLanguage() );
                        } catch ( Exception $e ) {
                                MWExceptionHandler::logException( $e );
                                wfDebugLog(
@@ -1082,11 +1168,13 @@ class ResourceLoader {
         * Returns JS code which calls mw.loader.register with the given
         * parameters. Has three calling conventions:
         *
-        *   - ResourceLoader::makeLoaderRegisterScript( $name, $version, $dependencies, $group, $source, $skip ):
-        *       Register a single module.
+        *   - ResourceLoader::makeLoaderRegisterScript( $name, $version,
+        *        $dependencies, $group, $source, $skip
+        *     ):
+        *        Register a single module.
         *
         *   - ResourceLoader::makeLoaderRegisterScript( array( $name1, $name2 ) ):
-        *       Register modules with the given names.
+        *        Register modules with the given names.
         *
         *   - ResourceLoader::makeLoaderRegisterScript( array(
         *        array( $name1, $version1, $dependencies1, $group1, $source1, $skip1 ),
@@ -1129,7 +1217,7 @@ class ResourceLoader {
         *   - ResourceLoader::makeLoaderSourcesScript( $id, $properties ):
         *       Register a single source
         *
-        *   - ResourceLoader::makeLoaderSourcesScript( array( $id1 => $props1, $id2 => $props2, ... ) );
+        *   - ResourceLoader::makeLoaderSourcesScript( array( $id1 => $loadUrl, $id2 => $loadUrl, ... ) );
         *       Register sources with the given IDs and properties.
         *
         * @param string $id Source ID
@@ -1232,6 +1320,27 @@ class ResourceLoader {
 
        /**
         * Build a load.php URL
+        *
+        * @since 1.24
+        * @param string $source Name of the ResourceLoader source
+        * @param ResourceLoaderContext $context
+        * @param array $extraQuery
+        * @return string URL to load.php. May be protocol-relative (if $wgLoadScript is procol-relative)
+        */
+       public function createLoaderURL( $source, ResourceLoaderContext $context,
+               $extraQuery = array()
+       ) {
+               $query = self::createLoaderQuery( $context, $extraQuery );
+               $script = $this->getLoadScript( $source );
+
+               // Prevent the IE6 extension check from being triggered (bug 28840)
+               // by appending a character that's invalid in Windows extensions ('*')
+               return wfExpandUrl( wfAppendQuery( $script, $query ) . '&*', PROTO_RELATIVE );
+       }
+
+       /**
+        * Build a load.php URL
+        * @deprecated since 1.24, use createLoaderURL instead
         * @param array $modules Array of module names (strings)
         * @param string $lang Language code
         * @param string $skin Skin name
@@ -1259,6 +1368,30 @@ class ResourceLoader {
                return wfExpandUrl( wfAppendQuery( $wgLoadScript, $query ) . '&*', PROTO_RELATIVE );
        }
 
+       /**
+        * Helper for createLoaderURL()
+        *
+        * @since 1.24
+        * @see makeLoaderQuery
+        * @param ResourceLoaderContext $context
+        * @param array $extraQuery
+        * @return array
+        */
+       public static function createLoaderQuery( ResourceLoaderContext $context, $extraQuery = array() ) {
+               return self::makeLoaderQuery(
+                       $context->getModules(),
+                       $context->getLanguage(),
+                       $context->getSkin(),
+                       $context->getUser(),
+                       $context->getVersion(),
+                       $context->getDebug(),
+                       $context->getOnly(),
+                       $context->getRequest()->getBool( 'printable' ),
+                       $context->getRequest()->getBool( 'handheld' ),
+                       $extraQuery
+               );
+       }
+
        /**
         * Build a query array (array representation of query string) for load.php. Helper
         * function for makeLoaderURL().
@@ -1324,12 +1457,12 @@ class ResourceLoader {
        /**
         * Returns LESS compiler set up for use with MediaWiki
         *
+        * @param Config $config
+        * @throws MWException
         * @since 1.22
         * @return lessc
         */
-       public static function getLessCompiler() {
-               global $wgResourceLoaderLESSFunctions, $wgResourceLoaderLESSImportPaths;
-
+       public static function getLessCompiler( Config $config ) {
                // When called from the installer, it is possible that a required PHP extension
                // is missing (at least for now; see bug 47564). If this is the case, throw an
                // exception (caught by the installer) to prevent a fatal error later on.
@@ -1339,9 +1472,9 @@ class ResourceLoader {
 
                $less = new lessc();
                $less->setPreserveComments( true );
-               $less->setVariables( self::getLESSVars() );
-               $less->setImportDir( $wgResourceLoaderLESSImportPaths );
-               foreach ( $wgResourceLoaderLESSFunctions as $name => $func ) {
+               $less->setVariables( self::getLessVars( $config ) );
+               $less->setImportDir( $config->get( 'ResourceLoaderLESSImportPaths' ) );
+               foreach ( $config->get( 'ResourceLoaderLESSFunctions' ) as $name => $func ) {
                        $less->registerFunction( $name, $func );
                }
                return $less;
@@ -1350,13 +1483,12 @@ class ResourceLoader {
        /**
         * Get global LESS variables.
         *
-        * $since 1.22
+        * @param Config $config
+        * @since 1.22
         * @return array Map of variable names to string CSS values.
         */
-       public static function getLESSVars() {
-               global $wgResourceLoaderLESSVars;
-
-               $lessVars = $wgResourceLoaderLESSVars;
+       public static function getLessVars( Config $config ) {
+               $lessVars = $config->get( 'ResourceLoaderLESSVars' );
                // Sort by key to ensure consistent hashing for cache lookups.
                ksort( $lessVars );
                return $lessVars;
index 9013e2b..7af7b89 100644 (file)
@@ -48,9 +48,7 @@ class ResourceLoaderContext {
         * @param ResourceLoader $resourceLoader
         * @param WebRequest $request
         */
-       public function __construct( $resourceLoader, WebRequest $request ) {
-               global $wgDefaultSkin, $wgResourceLoaderDebug;
-
+       public function __construct( ResourceLoader $resourceLoader, WebRequest $request ) {
                $this->resourceLoader = $resourceLoader;
                $this->request = $request;
 
@@ -61,7 +59,9 @@ class ResourceLoaderContext {
                // Various parameters
                $this->skin = $request->getVal( 'skin' );
                $this->user = $request->getVal( 'user' );
-               $this->debug = $request->getFuzzyBool( 'debug', $wgResourceLoaderDebug );
+               $this->debug = $request->getFuzzyBool(
+                       'debug', $resourceLoader->getConfig()->get( 'ResourceLoaderDebug' )
+               );
                $this->only = $request->getVal( 'only' );
                $this->version = $request->getVal( 'version' );
                $this->raw = $request->getFuzzyBool( 'raw' );
@@ -69,7 +69,7 @@ class ResourceLoaderContext {
                $skinnames = Skin::getSkinNames();
                // If no skin is specified, or we don't recognize the skin, use the default skin
                if ( !$this->skin || !isset( $skinnames[$this->skin] ) ) {
-                       $this->skin = $wgDefaultSkin;
+                       $this->skin = $resourceLoader->getConfig()->get( 'DefaultSkin' );
                }
        }
 
@@ -113,7 +113,9 @@ class ResourceLoaderContext {
         * @return ResourceLoaderContext
         */
        public static function newDummyContext() {
-               return new self( null, new FauxRequest( array() ) );
+               return new self( new ResourceLoader(
+                       ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+               ), new FauxRequest( array() ) );
        }
 
        /**
@@ -208,21 +210,21 @@ class ResourceLoaderContext {
         * @return bool
         */
        public function shouldIncludeScripts() {
-               return is_null( $this->only ) || $this->only === 'scripts';
+               return is_null( $this->getOnly() ) || $this->getOnly() === 'scripts';
        }
 
        /**
         * @return bool
         */
        public function shouldIncludeStyles() {
-               return is_null( $this->only ) || $this->only === 'styles';
+               return is_null( $this->getOnly() ) || $this->getOnly() === 'styles';
        }
 
        /**
         * @return bool
         */
        public function shouldIncludeMessages() {
-               return is_null( $this->only ) || $this->only === 'messages';
+               return is_null( $this->getOnly() ) || $this->getOnly() === 'messages';
        }
 
        /**
@@ -231,8 +233,8 @@ class ResourceLoaderContext {
        public function getHash() {
                if ( !isset( $this->hash ) ) {
                        $this->hash = implode( '|', array(
-                               $this->getLanguage(), $this->getDirection(), $this->skin, $this->user,
-                               $this->debug, $this->only, $this->version
+                               $this->getLanguage(), $this->getDirection(), $this->getSkin(), $this->getUser(),
+                               $this->getDebug(), $this->getOnly(), $this->getVersion()
                        ) );
                }
                return $this->hash;
diff --git a/includes/resourceloader/ResourceLoaderEditToolbarModule.php b/includes/resourceloader/ResourceLoaderEditToolbarModule.php
new file mode 100644 (file)
index 0000000..0049421
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Resource loader module for the edit toolbar.
+ *
+ * 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
+ */
+
+/**
+ * ResourceLoader module for the edit toolbar.
+ *
+ * @since 1.24
+ */
+class ResourceLoaderEditToolbarModule extends ResourceLoaderFileModule {
+       /**
+        * Serialize a string (escape and quote) for use as a CSS string value.
+        * http://www.w3.org/TR/2013/WD-cssom-20131205/#serialize-a-string
+        *
+        * @param string $value
+        * @return string
+        */
+       private static function cssSerializeString( $value ) {
+               if ( strstr( $value, "\0" ) ) {
+                       throw new Exception( "Invalid character in CSS string" );
+               }
+               $value = strtr( $value, array( '\\' => '\\\\', '"' => '\\"' ) );
+               $value = preg_replace_callback( '/[\x01-\x1f\x7f-\x9f]/', function ( $match ) {
+                       return '\\' . base_convert( ord( $match[0] ), 10, 16 ) . ' ';
+               }, $value );
+               return '"' . $value . '"';
+       }
+
+       /**
+        * Get language-specific LESS variables for this module.
+        *
+        * @return array
+        */
+       private function getLessVars( ResourceLoaderContext $context ) {
+               $language = Language::factory( $context->getLanguage() );
+
+               // This is very conveniently formatted and we can pass it right through
+               $vars = $language->getImageFiles();
+
+               // lessc tries to be helpful and parse our variables as LESS source code
+               foreach ( $vars as $key => &$value ) {
+                       $value = self::cssSerializeString( $value );
+               }
+
+               return $vars;
+       }
+
+       /**
+        * @param ResourceLoaderContext $context
+        * @return int UNIX timestamp
+        */
+       public function getModifiedTime( ResourceLoaderContext $context ) {
+               return max(
+                       parent::getModifiedTime( $context ),
+                       $this->getHashMtime( $context )
+               );
+       }
+
+       /**
+        * @param ResourceLoaderContext $context
+        * @return string Hash
+        */
+       public function getModifiedHash( ResourceLoaderContext $context ) {
+               return md5(
+                       parent::getModifiedHash( $context ) .
+                       serialize( $this->getLessVars( $context ) )
+               );
+       }
+
+       /**
+        * Get a LESS compiler instance for this module.
+        *
+        * Set our variables in it.
+        *
+        * @throws MWException
+        * @param ResourceLoaderContext $context
+        * @return lessc
+        */
+       protected function getLessCompiler( ResourceLoaderContext $context ) {
+               $compiler = parent::getLessCompiler();
+               $compiler->setVariables( $this->getLessVars( $context ) );
+               return $compiler;
+       }
+}
index 3a6d5d2..fee78d1 100644 (file)
@@ -218,27 +218,17 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         *     )
         * @endcode
         */
-       public function __construct( $options = array(), $localBasePath = null,
+       public function __construct(
+               $options = array(),
+               $localBasePath = null,
                $remoteBasePath = null
        ) {
-               global $IP, $wgScriptPath, $wgResourceBasePath;
-               $this->localBasePath = $localBasePath === null ? $IP : $localBasePath;
-               if ( $remoteBasePath !== null ) {
-                       $this->remoteBasePath = $remoteBasePath;
-               } else {
-                       $this->remoteBasePath = $wgResourceBasePath === null ? $wgScriptPath : $wgResourceBasePath;
-               }
-
-               if ( isset( $options['remoteExtPath'] ) ) {
-                       global $wgExtensionAssetsPath;
-                       $this->remoteBasePath = $wgExtensionAssetsPath . '/' . $options['remoteExtPath'];
-               }
-
-               if ( isset( $options['remoteSkinPath'] ) ) {
-                       global $wgStylePath;
-                       $this->remoteBasePath = $wgStylePath . '/' . $options['remoteSkinPath'];
-               }
+               // localBasePath and remoteBasePath both have unbelievably long fallback chains
+               // and need to be handled separately.
+               list( $this->localBasePath, $this->remoteBasePath ) =
+                       self::extractBasePaths( $options, $localBasePath, $remoteBasePath );
 
+               // Extract, validate and normalise remaining options
                foreach ( $options as $member => $option ) {
                        switch ( $member ) {
                                // Lists of file paths
@@ -281,8 +271,6 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                                // Single strings
                                case 'group':
                                case 'position':
-                               case 'localBasePath':
-                               case 'remoteBasePath':
                                case 'skipFunction':
                                        $this->{$member} = (string)$option;
                                        break;
@@ -293,9 +281,57 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                                        break;
                        }
                }
+       }
+
+       /**
+        * Extract a pair of local and remote base paths from module definition information.
+        * Implementation note: the amount of global state used in this function is staggering.
+        *
+        * @param array $options Module definition
+        * @param string $localBasePath Path to use if not provided in module definition. Defaults
+        *     to $IP
+        * @param string $remoteBasePath Path to use if not provided in module definition. Defaults
+        *     to $wgScriptPath
+        * @return array Array( localBasePath, remoteBasePath )
+        */
+       public static function extractBasePaths(
+               $options = array(),
+               $localBasePath = null,
+               $remoteBasePath = null
+       ) {
+               global $IP, $wgScriptPath, $wgResourceBasePath;
+
+               // The different ways these checks are done, and their ordering, look very silly,
+               // but were preserved for backwards-compatibility just in case. Tread lightly.
+
+               $localBasePath = $localBasePath === null ? $IP : $localBasePath;
+               if ( $remoteBasePath === null ) {
+                       $remoteBasePath = $wgResourceBasePath === null ? $wgScriptPath : $wgResourceBasePath;
+               }
+
+               if ( isset( $options['remoteExtPath'] ) ) {
+                       global $wgExtensionAssetsPath;
+                       $remoteBasePath = $wgExtensionAssetsPath . '/' . $options['remoteExtPath'];
+               }
+
+               if ( isset( $options['remoteSkinPath'] ) ) {
+                       global $wgStylePath;
+                       $remoteBasePath = $wgStylePath . '/' . $options['remoteSkinPath'];
+               }
+
+               if ( array_key_exists( 'localBasePath', $options ) ) {
+                       $localBasePath = (string)$options['localBasePath'];
+               }
+
+               if ( array_key_exists( 'remoteBasePath', $options ) ) {
+                       $remoteBasePath = (string)$options['remoteBasePath'];
+               }
+
                // Make sure the remote base path is a complete valid URL,
                // but possibly protocol-relative to avoid cache pollution
-               $this->remoteBasePath = wfExpandUrl( $this->remoteBasePath, PROTO_RELATIVE );
+               $remoteBasePath = wfExpandUrl( $remoteBasePath, PROTO_RELATIVE );
+
+               return array( $localBasePath, $remoteBasePath );
        }
 
        /**
@@ -331,7 +367,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        /**
         * Get loader script.
         *
-        * @return string|false JavaScript code to be added to startup module
+        * @return string|bool JavaScript code to be added to startup module
         */
        public function getLoaderScript() {
                if ( count( $this->loaderScripts ) === 0 ) {
@@ -349,7 +385,8 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        public function getStyles( ResourceLoaderContext $context ) {
                $styles = $this->readStyleFiles(
                        $this->getStyleFiles( $context ),
-                       $this->getFlip( $context )
+                       $this->getFlip( $context ),
+                       $context
                );
                // Collect referenced files
                $this->localFileRefs = array_unique( $this->localFileRefs );
@@ -437,14 +474,13 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        return null;
                }
 
-               global $wgResourceLoaderValidateStaticJS;
                $localPath = $this->getLocalPath( $this->skipFunction );
                if ( !file_exists( $localPath ) ) {
                        throw new MWException( __METHOD__ . ": skip function file not found: \"$localPath\"" );
                }
                $contents = file_get_contents( $localPath );
-               if ( $wgResourceLoaderValidateStaticJS ) {
-                       $contents = $this->validateScriptFile( $fileName, $contents );
+               if ( $this->getConfig()->get( 'ResourceLoaderValidateStaticJS' ) ) {
+                       $contents = $this->validateScriptFile( $localPath, $contents );
                }
                return $contents;
        }
@@ -534,6 +570,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        /**
         * Get the definition summary for this module.
         *
+        * @param ResourceLoaderContext $context
         * @return array
         */
        public function getDefinitionSummary( ResourceLoaderContext $context ) {
@@ -567,18 +604,26 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        /* Protected Methods */
 
        /**
-        * @param string $path
+        * @param string|ResourceLoaderFilePath $path
         * @return string
         */
        protected function getLocalPath( $path ) {
+               if ( $path instanceof ResourceLoaderFilePath ) {
+                       return $path->getLocalPath();
+               }
+
                return "{$this->localBasePath}/$path";
        }
 
        /**
-        * @param string $path
+        * @param string|ResourceLoaderFilePath $path
         * @return string
         */
        protected function getRemotePath( $path ) {
+               if ( $path instanceof ResourceLoaderFilePath ) {
+                       return $path->getRemotePath();
+               }
+
                return "{$this->remoteBasePath}/$path";
        }
 
@@ -660,7 +705,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        $files = array_merge( $files, $this->debugScripts );
                }
 
-               return array_unique( $files );
+               return array_unique( $files, SORT_REGULAR );
        }
 
        /**
@@ -746,18 +791,17 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * @return string Concatenated and remapped JavaScript data from $scripts
         */
        protected function readScriptFiles( array $scripts ) {
-               global $wgResourceLoaderValidateStaticJS;
                if ( empty( $scripts ) ) {
                        return '';
                }
                $js = '';
-               foreach ( array_unique( $scripts ) as $fileName ) {
+               foreach ( array_unique( $scripts, SORT_REGULAR ) as $fileName ) {
                        $localPath = $this->getLocalPath( $fileName );
                        if ( !file_exists( $localPath ) ) {
                                throw new MWException( __METHOD__ . ": script file not found: \"$localPath\"" );
                        }
                        $contents = file_get_contents( $localPath );
-                       if ( $wgResourceLoaderValidateStaticJS ) {
+                       if ( $this->getConfig()->get( 'ResourceLoaderValidateStaticJS' ) ) {
                                // Static files don't really need to be checked as often; unlike
                                // on-wiki module they shouldn't change unexpectedly without
                                // admin interference.
@@ -773,22 +817,22 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         *
         * @param array $styles List of media type/list of file paths pairs, to read, remap and
         * concetenate
-        *
         * @param bool $flip
+        * @param ResourceLoaderContext $context (optional)
         *
         * @throws MWException
         * @return array List of concatenated and remapped CSS data from $styles,
         *     keyed by media type
         */
-       public function readStyleFiles( array $styles, $flip ) {
+       public function readStyleFiles( array $styles, $flip, $context = null ) {
                if ( empty( $styles ) ) {
                        return array();
                }
                foreach ( $styles as $media => $files ) {
-                       $uniqueFiles = array_unique( $files );
+                       $uniqueFiles = array_unique( $files, SORT_REGULAR );
                        $styleFiles = array();
                        foreach ( $uniqueFiles as $file ) {
-                               $styleFiles[] = $this->readStyleFile( $file, $flip );
+                               $styleFiles[] = $this->readStyleFile( $file, $flip, $context );
                        }
                        $styles[$media] = implode( "\n", $styleFiles );
                }
@@ -802,20 +846,23 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         *
         * @param string $path File path of style file to read
         * @param bool $flip
+        * @param ResourceLoaderContext $context (optional)
         *
         * @return string CSS data in script file
-        * @throws MWException if the file doesn't exist
+        * @throws MWException If the file doesn't exist
         */
-       protected function readStyleFile( $path, $flip ) {
+       protected function readStyleFile( $path, $flip, $context = null ) {
                $localPath = $this->getLocalPath( $path );
+               $remotePath = $this->getRemotePath( $path );
                if ( !file_exists( $localPath ) ) {
                        $msg = __METHOD__ . ": style file not found: \"$localPath\"";
                        wfDebugLog( 'resourceloader', $msg );
                        throw new MWException( $msg );
                }
 
-               if ( $this->getStyleSheetLang( $path ) === 'less' ) {
-                       $style = $this->compileLESSFile( $localPath );
+               if ( $this->getStyleSheetLang( $localPath ) === 'less' ) {
+                       $compiler = $this->getLessCompiler( $context );
+                       $style = $this->compileLessFile( $localPath, $compiler );
                        $this->hasGeneratedStyles = true;
                } else {
                        $style = file_get_contents( $localPath );
@@ -823,21 +870,18 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
 
                if ( $flip ) {
                        $style = CSSJanus::transform( $style, true, false );
+               } else {
+                       $style = CSSJanus::nullTransform( $style );
                }
-               $dirname = dirname( $path );
-               if ( $dirname == '.' ) {
-                       // If $path doesn't have a directory component, don't prepend a dot
-                       $dirname = '';
-               }
-               $dir = $this->getLocalPath( $dirname );
-               $remoteDir = $this->getRemotePath( $dirname );
+               $localDir = dirname( $localPath );
+               $remoteDir = dirname( $remotePath );
                // Get and register local file references
                $this->localFileRefs = array_merge(
                        $this->localFileRefs,
-                       CSSMin::getLocalFileReferences( $style, $dir )
+                       CSSMin::getLocalFileReferences( $style, $localDir )
                );
                return CSSMin::remap(
-                       $style, $dir, $remoteDir, true
+                       $style, $localDir, $remoteDir, true
                );
        }
 
@@ -860,60 +904,36 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        }
 
        /**
-        * Generate a cache key for a LESS file.
+        * Compile a LESS file into CSS.
         *
-        * The cache key varies on the file name and the names and values of global
-        * LESS variables.
+        * Keeps track of all used files and adds them to localFileRefs.
         *
         * @since 1.22
-        * @param string $fileName File name of root LESS file.
-        * @return string Cache key
+        * @throws Exception If lessc encounters a parse error
+        * @param string $fileName File path of LESS source
+        * @param lessc $compiler Compiler to use, if not default
+        * @return string CSS source
         */
-       protected static function getLESSCacheKey( $fileName ) {
-               $vars = json_encode( ResourceLoader::getLESSVars() );
-               $hash = md5( $fileName . $vars );
-               return wfMemcKey( 'resourceloader', 'less', $hash );
+       protected function compileLessFile( $fileName, $compiler = null ) {
+               if ( !$compiler ) {
+                       $compiler = $this->getLessCompiler();
+               }
+               $result = $compiler->compileFile( $fileName );
+               $this->localFileRefs += array_keys( $compiler->allParsedFiles() );
+               return $result;
        }
 
        /**
-        * Compile a LESS file into CSS.
+        * Get a LESS compiler instance for this module in given context.
         *
-        * If invalid, returns replacement CSS source consisting of the compilation
-        * error message encoded as a comment. To save work, we cache a result object
-        * which comprises the compiled CSS and the names & mtimes of the files
-        * that were processed. lessphp compares the cached & current mtimes and
-        * recompiles as necessary.
+        * Just calls ResourceLoader::getLessCompiler() by default to get a global compiler.
         *
-        * @since 1.22
-        * @throws Exception If Less encounters a parse error
-        * @throws MWException If Less compilation returns unexpection result
-        * @param string $fileName File path of LESS source
-        * @return string CSS source
+        * @param ResourceLoaderContext $context
+        * @throws MWException
+        * @since 1.24
+        * @return lessc
         */
-       protected function compileLESSFile( $fileName ) {
-               $key = self::getLESSCacheKey( $fileName );
-               $cache = wfGetCache( CACHE_ANYTHING );
-
-               // The input to lessc. Either an associative array representing the
-               // cached results of a previous compilation, or the string file name if
-               // no cache result exists.
-               $source = $cache->get( $key );
-               if ( !is_array( $source ) || !isset( $source['root'] ) ) {
-                       $source = $fileName;
-               }
-
-               $compiler = ResourceLoader::getLessCompiler();
-               $result = null;
-
-               $result = $compiler->cachedCompile( $source );
-
-               if ( !is_array( $result ) ) {
-                       throw new MWException( 'LESS compiler result has type '
-                               . gettype( $result ) . '; array expected.' );
-               }
-
-               $this->localFileRefs += array_keys( $result['files'] );
-               $cache->set( $key, $result );
-               return $result['compiled'];
+       protected function getLessCompiler( ResourceLoaderContext $context = null ) {
+               return ResourceLoader::getLessCompiler( $this->getConfig() );
        }
 }
diff --git a/includes/resourceloader/ResourceLoaderFilePath.php b/includes/resourceloader/ResourceLoaderFilePath.php
new file mode 100644 (file)
index 0000000..dd239d0
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/**
+ * An object to represent a path to a JavaScript/CSS file, along with a remote
+ * and local base path, for use with ResourceLoaderFileModule.
+ *
+ * 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
+ */
+
+/**
+ * An object to represent a path to a JavaScript/CSS file, along with a remote
+ * and local base path, for use with ResourceLoaderFileModule.
+ */
+class ResourceLoaderFilePath {
+       /* Protected Members */
+
+       /** @var string Local base path */
+       protected $localBasePath;
+
+       /** @var string Remote base path */
+       protected $remoteBasePath;
+
+       /**
+        * @var string Path to the file */
+       protected $path;
+
+       /* Methods */
+
+       /**
+        * @param string $path Path to the file.
+        * @param string $localBasePath Base path to prepend when generating a local path.
+        * @param string $remoteBasePath Base path to prepend when generating a remote path.
+        */
+       public function __construct( $path, $localBasePath, $remoteBasePath ) {
+               $this->path = $path;
+               $this->localBasePath = $localBasePath;
+               $this->remoteBasePath = $remoteBasePath;
+       }
+
+       /**
+        * @return string
+        */
+       public function getLocalPath() {
+               return "{$this->localBasePath}/{$this->path}";
+       }
+
+       /**
+        * @return string
+        */
+       public function getRemotePath() {
+               return "{$this->remoteBasePath}/{$this->path}";
+       }
+
+       /**
+        * @return string
+        */
+       public function getPath() {
+               return $this->path;
+       }
+}
index eb1461f..987b902 100644 (file)
@@ -34,6 +34,8 @@ class ResourceLoaderLESSFunctions {
         *       background-image: url(@url) !ie;
         *   }
         * @endcode
+        * @param array $frame
+        * @param lessc $less
         */
        public static function embeddable( $frame, $less ) {
                $base = pathinfo( $less->parser->sourceName, PATHINFO_DIRNAME );
@@ -54,6 +56,9 @@ class ResourceLoaderLESSFunctions {
         *       background-image: embed('../images/button-bg.png');
         *   }
         * @endcode
+        * @param array $frame
+        * @param lessc $less
+        * @return string
         */
        public static function embed( $frame, $less ) {
                $base = pathinfo( $less->parser->sourceName, PATHINFO_DIRNAME );
index a1c8ac9..09d90d6 100644 (file)
@@ -43,6 +43,7 @@ class ResourceLoaderLanguageDataModule extends ResourceLoaderModule {
                        'grammarForms' => $language->getGrammarForms(),
                        'pluralRules' => $language->getPluralRules(),
                        'digitGroupingPattern' => $language->digitGroupingPattern(),
+                       'fallbackLanguages' => $language->getFallbackLanguages(),
                );
        }
 
index 73b6ea7..fe0c845 100644 (file)
@@ -34,7 +34,7 @@ class ResourceLoaderLanguageNamesModule extends ResourceLoaderModule {
 
 
        /**
-        * @param $context ResourceLoaderContext
+        * @param ResourceLoaderContext $context
         * @return array
         */
        protected function getData( ResourceLoaderContext $context ) {
@@ -45,7 +45,7 @@ class ResourceLoaderLanguageNamesModule extends ResourceLoaderModule {
        }
 
        /**
-        * @param $context ResourceLoaderContext
+        * @param ResourceLoaderContext $context
         * @return string JavaScript code
         */
        public function getScript( ResourceLoaderContext $context ) {
index f636105..45eb70f 100644 (file)
@@ -64,6 +64,11 @@ abstract class ResourceLoaderModule {
        // In-object cache for message blob mtime
        protected $msgBlobMtime = array();
 
+       /**
+        * @var Config
+        */
+       protected $config;
+
        /* Methods */
 
        /**
@@ -129,6 +134,27 @@ abstract class ResourceLoaderModule {
                return '';
        }
 
+       /**
+        * @return Config
+        * @since 1.24
+        */
+       public function getConfig() {
+               if ( $this->config === null ) {
+                       // Ugh, fall back to default
+                       $this->config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               }
+
+               return $this->config;
+       }
+
+       /**
+        * @param Config $config
+        * @since 1.24
+        */
+       public function setConfig( Config $config ) {
+               $this->config = $config;
+       }
+
        /**
         * Get the URL or URLs to load for this module's JS in debug mode.
         * The default behavior is to return a load.php?only=scripts URL for
@@ -144,17 +170,17 @@ abstract class ResourceLoaderModule {
         * @return array Array of URLs
         */
        public function getScriptURLsForDebug( ResourceLoaderContext $context ) {
-               $url = ResourceLoader::makeLoaderURL(
-                       array( $this->getName() ),
-                       $context->getLanguage(),
-                       $context->getSkin(),
-                       $context->getUser(),
-                       $context->getVersion(),
-                       true, // debug
-                       'scripts', // only
-                       $context->getRequest()->getBool( 'printable' ),
-                       $context->getRequest()->getBool( 'handheld' )
+               $resourceLoader = $context->getResourceLoader();
+               $derivative = new DerivativeResourceLoaderContext( $context );
+               $derivative->setModules( array( $this->getName() ) );
+               $derivative->setOnly( 'scripts' );
+               $derivative->setDebug( true );
+
+               $url = $resourceLoader->createLoaderURL(
+                       $this->getSource(),
+                       $derivative
                );
+
                return array( $url );
        }
 
@@ -188,20 +214,20 @@ abstract class ResourceLoaderModule {
         * load the files directly. See also getScriptURLsForDebug()
         *
         * @param ResourceLoaderContext $context
-        * @return array array( mediaType => array( URL1, URL2, ... ), ... )
+        * @return array Array( mediaType => array( URL1, URL2, ... ), ... )
         */
        public function getStyleURLsForDebug( ResourceLoaderContext $context ) {
-               $url = ResourceLoader::makeLoaderURL(
-                       array( $this->getName() ),
-                       $context->getLanguage(),
-                       $context->getSkin(),
-                       $context->getUser(),
-                       $context->getVersion(),
-                       true, // debug
-                       'styles', // only
-                       $context->getRequest()->getBool( 'printable' ),
-                       $context->getRequest()->getBool( 'handheld' )
+               $resourceLoader = $context->getResourceLoader();
+               $derivative = new DerivativeResourceLoaderContext( $context );
+               $derivative->setModules( array( $this->getName() ) );
+               $derivative->setOnly( 'styles' );
+               $derivative->setDebug( true );
+
+               $url = $resourceLoader->createLoaderURL(
+                       $this->getSource(),
+                       $derivative
                );
+
                return array( 'all' => array( $url ) );
        }
 
@@ -460,6 +486,7 @@ abstract class ResourceLoaderModule {
         *
         * @since 1.23
         *
+        * @param ResourceLoaderContext $context
         * @return int UNIX timestamp or 0 if no definition summary was provided
         *  by getDefinitionSummary()
         */
@@ -527,6 +554,7 @@ abstract class ResourceLoaderModule {
         *
         * @since 1.23
         *
+        * @param ResourceLoaderContext $context
         * @return array|null
         */
        public function getDefinitionSummary( ResourceLoaderContext $context ) {
@@ -548,7 +576,7 @@ abstract class ResourceLoaderModule {
                return false;
        }
 
-       /** @var JSParser lazy-initialized; use self::javaScriptParser() */
+       /** @var JSParser Lazy-initialized; use self::javaScriptParser() */
        private static $jsParser;
        private static $parseCacheVersion = 1;
 
@@ -561,8 +589,7 @@ abstract class ResourceLoaderModule {
         * @return string JS with the original, or a replacement error
         */
        protected function validateScriptFile( $fileName, $contents ) {
-               global $wgResourceLoaderValidateJS;
-               if ( $wgResourceLoaderValidateJS ) {
+               if ( $this->getConfig()->get( 'ResourceLoaderValidateJS' ) ) {
                        // Try for cache hit
                        // Use CACHE_ANYTHING since filtering is very slow compared to DB queries
                        $key = wfMemcKey( 'resourceloader', 'jsparse', self::$parseCacheVersion, md5( $contents ) );
index d28f40f..1d9721a 100644 (file)
@@ -37,14 +37,12 @@ class ResourceLoaderSiteModule extends ResourceLoaderWikiModule {
         * @return array List of pages
         */
        protected function getPages( ResourceLoaderContext $context ) {
-               global $wgUseSiteJs, $wgUseSiteCss;
-
                $pages = array();
-               if ( $wgUseSiteJs ) {
+               if ( $this->getConfig()->get( 'UseSiteJs' ) ) {
                        $pages['MediaWiki:Common.js'] = array( 'type' => 'script' );
                        $pages['MediaWiki:' . ucfirst( $context->getSkin() ) . '.js'] = array( 'type' => 'script' );
                }
-               if ( $wgUseSiteCss ) {
+               if ( $this->getConfig()->get( 'UseSiteCss' ) ) {
                        $pages['MediaWiki:Common.css'] = array( 'type' => 'style' );
                        $pages['MediaWiki:' . ucfirst( $context->getSkin() ) . '.css'] = array( 'type' => 'style' );
 
index 8a936c6..78fe8e0 100644 (file)
@@ -36,22 +36,14 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         * @param ResourceLoaderContext $context
         * @return array
         */
-       protected function getConfig( $context ) {
+       protected function getConfigSettings( $context ) {
 
                $hash = $context->getHash();
                if ( isset( $this->configVars[$hash] ) ) {
                        return $this->configVars[$hash];
                }
 
-               global $wgLoadScript, $wgScript, $wgStylePath, $wgScriptExtension,
-                       $wgArticlePath, $wgScriptPath, $wgServer, $wgServerName,
-                       $wgContLang, $wgVariantArticlePath, $wgActionPaths, $wgVersion,
-                       $wgEnableAPI, $wgEnableWriteAPI, $wgDBname,
-                       $wgSitename, $wgFileExtensions, $wgExtensionAssetsPath,
-                       $wgCookiePrefix, $wgCookieDomain, $wgCookiePath,
-                       $wgCookieExpiration, $wgResourceLoaderMaxQueryLength,
-                       $wgResourceLoaderStorageEnabled, $wgResourceLoaderStorageVersion,
-                       $wgSearchType;
+               global $wgContLang;
 
                $mainPage = Title::newMainPage();
 
@@ -69,51 +61,52 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        }
                }
 
+               $conf = $this->getConfig();
                // Build list of variables
                $vars = array(
-                       'wgLoadScript' => $wgLoadScript,
+                       'wgLoadScript' => wfScript( 'load' ),
                        'debug' => $context->getDebug(),
                        'skin' => $context->getSkin(),
-                       'stylepath' => $wgStylePath,
+                       'stylepath' => $conf->get( 'StylePath' ),
                        'wgUrlProtocols' => wfUrlProtocols(),
-                       'wgArticlePath' => $wgArticlePath,
-                       'wgScriptPath' => $wgScriptPath,
-                       'wgScriptExtension' => $wgScriptExtension,
-                       'wgScript' => $wgScript,
-                       'wgSearchType' => $wgSearchType,
-                       'wgVariantArticlePath' => $wgVariantArticlePath,
+                       'wgArticlePath' => $conf->get( 'ArticlePath' ),
+                       'wgScriptPath' => $conf->get( 'ScriptPath' ),
+                       'wgScriptExtension' => $conf->get( 'ScriptExtension' ),
+                       'wgScript' => wfScript(),
+                       'wgSearchType' => $conf->get( 'SearchType' ),
+                       'wgVariantArticlePath' => $conf->get( 'VariantArticlePath' ),
                        // Force object to avoid "empty" associative array from
                        // becoming [] instead of {} in JS (bug 34604)
-                       'wgActionPaths' => (object)$wgActionPaths,
-                       'wgServer' => $wgServer,
-                       'wgServerName' => $wgServerName,
+                       'wgActionPaths' => (object)$conf->get( 'ActionPaths' ),
+                       'wgServer' => $conf->get( 'Server' ),
+                       'wgServerName' => $conf->get( 'ServerName' ),
                        'wgUserLanguage' => $context->getLanguage(),
                        'wgContentLanguage' => $wgContLang->getCode(),
-                       'wgVersion' => $wgVersion,
-                       'wgEnableAPI' => $wgEnableAPI,
-                       'wgEnableWriteAPI' => $wgEnableWriteAPI,
+                       'wgVersion' => $conf->get( 'Version' ),
+                       'wgEnableAPI' => $conf->get( 'EnableAPI' ),
+                       'wgEnableWriteAPI' => $conf->get( 'EnableWriteAPI' ),
                        'wgMainPageTitle' => $mainPage->getPrefixedText(),
                        'wgFormattedNamespaces' => $wgContLang->getFormattedNamespaces(),
                        'wgNamespaceIds' => $namespaceIds,
                        'wgContentNamespaces' => MWNamespace::getContentNamespaces(),
-                       'wgSiteName' => $wgSitename,
-                       'wgFileExtensions' => array_values( array_unique( $wgFileExtensions ) ),
-                       'wgDBname' => $wgDBname,
+                       'wgSiteName' => $conf->get( 'Sitename' ),
+                       'wgFileExtensions' => array_values( array_unique( $conf->get( 'FileExtensions' ) ) ),
+                       'wgDBname' => $conf->get( 'DBname' ),
                        // This sucks, it is only needed on Special:Upload, but I could
                        // not find a way to add vars only for a certain module
-                       'wgFileCanRotate' => BitmapHandler::canRotate(),
+                       'wgFileCanRotate' => SpecialUpload::rotationEnabled(),
                        'wgAvailableSkins' => Skin::getSkinNames(),
-                       'wgExtensionAssetsPath' => $wgExtensionAssetsPath,
+                       'wgExtensionAssetsPath' => $conf->get( 'ExtensionAssetsPath' ),
                        // MediaWiki sets cookies to have this prefix by default
-                       'wgCookiePrefix' => $wgCookiePrefix,
-                       'wgCookieDomain' => $wgCookieDomain,
-                       'wgCookiePath' => $wgCookiePath,
-                       'wgCookieExpiration' => $wgCookieExpiration,
-                       'wgResourceLoaderMaxQueryLength' => $wgResourceLoaderMaxQueryLength,
+                       'wgCookiePrefix' => $conf->get( 'CookiePrefix' ),
+                       'wgCookieDomain' => $conf->get( 'CookieDomain' ),
+                       'wgCookiePath' => $conf->get( 'CookiePath' ),
+                       'wgCookieExpiration' => $conf->get( 'CookieExpiration' ),
+                       'wgResourceLoaderMaxQueryLength' => $conf->get( 'ResourceLoaderMaxQueryLength' ),
                        'wgCaseSensitiveNamespaces' => $caseSensitiveNamespaces,
                        'wgLegalTitleChars' => Title::convertByteClassToUnicodeClass( Title::legalChars() ),
-                       'wgResourceLoaderStorageVersion' => $wgResourceLoaderStorageVersion,
-                       'wgResourceLoaderStorageEnabled' => $wgResourceLoaderStorageEnabled,
+                       'wgResourceLoaderStorageVersion' => $conf->get( 'ResourceLoaderStorageVersion' ),
+                       'wgResourceLoaderStorageEnabled' => $conf->get( 'ResourceLoaderStorageEnabled' ),
                );
 
                wfRunHooks( 'ResourceLoaderGetConfigVars', array( &$vars ) );
@@ -129,7 +122,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         * @param string $moduleName
         * @return array
         */
-       protected static function getImplicitDependencies( Array $registryData, $moduleName ) {
+       protected static function getImplicitDependencies( array $registryData, $moduleName ) {
                static $dependencyCache = array();
 
                // The list of implicit dependencies won't be altered, so we can
@@ -168,14 +161,14 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         * This way we can reasonably reduce the amout of module registration
         * data send to the client.
         *
-        * @param Array &$registryData Modules keyed by name with properties:
+        * @param array &$registryData Modules keyed by name with properties:
         *  - string 'version'
         *  - array 'dependencies'
         *  - string|null 'group'
         *  - string 'source'
         *  - string|false 'loader'
         */
-       public static function compileUnresolvedDependencies( Array &$registryData ) {
+       public static function compileUnresolvedDependencies( array &$registryData ) {
                foreach ( $registryData as $name => &$data ) {
                        if ( $data['loader'] !== false ) {
                                continue;
@@ -197,8 +190,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         * @param ResourceLoaderContext $context
         * @return string JavaScript code for registering all modules with the client loader
         */
-       public static function getModuleRegistrations( ResourceLoaderContext $context ) {
-               global $wgCacheEpoch;
+       public function getModuleRegistrations( ResourceLoaderContext $context ) {
                wfProfileIn( __METHOD__ );
 
                $resourceLoader = $context->getResourceLoader();
@@ -215,10 +207,17 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                                continue;
                        }
 
+                       if ( $module->isRaw() ) {
+                               // Don't register "raw" modules (like 'jquery' and 'mediawiki') client-side because
+                               // depending on them is illegal anyway and would only lead to them being reloaded
+                               // causing any state to be lost (like jQuery plugins, mw.config etc.)
+                               continue;
+                       }
+
                        // getModifiedTime() is supposed to return a UNIX timestamp, but it doesn't always
                        // seem to do that, and custom implementations might forget. Coerce it to TS_UNIX
                        $moduleMtime = wfTimestamp( TS_UNIX, $module->getModifiedTime( $context ) );
-                       $mtime = max( $moduleMtime, wfTimestamp( TS_UNIX, $wgCacheEpoch ) );
+                       $mtime = max( $moduleMtime, wfTimestamp( TS_UNIX, $this->getConfig()->get( 'CacheEpoch' ) ) );
 
                        // FIXME: Convert to numbers, wfTimestamp always gives us stings, even for TS_UNIX
 
@@ -233,7 +232,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                                );
                        }
 
-                       $registryData[ $name ] = array(
+                       $registryData[$name] = array(
                                'version' => $mtime,
                                'dependencies' => $module->getDependencies(),
                                'group' => $module->getGroup(),
@@ -333,6 +332,15 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                return true;
        }
 
+       /**
+        * Base modules required for the the base environment of ResourceLoader
+        *
+        * @return array
+        */
+       public static function getStartupModules() {
+               return array( 'jquery', 'mediawiki' );
+       }
+
        /**
         * Get the load URL of the startup modules.
         *
@@ -343,9 +351,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         * @return string
         */
        public static function getStartupModulesUrl( ResourceLoaderContext $context ) {
-               // The core modules:
-               $moduleNames = array( 'jquery', 'mediawiki' );
-               wfRunHooks( 'ResourceLoaderGetStartupModules', array( &$moduleNames ), '1.23' );
+               $moduleNames = self::getStartupModules();
 
                // Get the latest version
                $loader = $context->getResourceLoader();
@@ -374,19 +380,19 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         * @return string
         */
        public function getScript( ResourceLoaderContext $context ) {
-               global $IP, $wgLegacyJavaScriptGlobals;
+               global $IP;
 
                $out = file_get_contents( "$IP/resources/src/startup.js" );
                if ( $context->getOnly() === 'scripts' ) {
 
                        // Startup function
-                       $configuration = $this->getConfig( $context );
-                       $registrations = self::getModuleRegistrations( $context );
+                       $configuration = $this->getConfigSettings( $context );
+                       $registrations = $this->getModuleRegistrations( $context );
                        // Fix indentation
                        $registrations = str_replace( "\n", "\n\t", trim( $registrations ) );
                        $out .= "var startUp = function () {\n" .
                                "\tmw.config = new " .
-                               Xml::encodeJsCall( 'mw.Map', array( $wgLegacyJavaScriptGlobals ) ) . "\n" .
+                               Xml::encodeJsCall( 'mw.Map', array( $this->getConfig()->get( 'LegacyJavaScriptGlobals' ) ) ) . "\n" .
                                "\t$registrations\n" .
                                "\t" . Xml::encodeJsCall( 'mw.config.set', array( $configuration ) ) .
                                "};\n";
@@ -413,7 +419,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         * @return array|mixed
         */
        public function getModifiedTime( ResourceLoaderContext $context ) {
-               global $IP, $wgCacheEpoch;
+               global $IP;
 
                $hash = $context->getHash();
                if ( isset( $this->modifiedTime[$hash] ) ) {
@@ -426,7 +432,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                $loader->preloadModuleInfo( $loader->getModuleNames(), $context );
 
                $time = max(
-                       wfTimestamp( TS_UNIX, $wgCacheEpoch ),
+                       wfTimestamp( TS_UNIX, $this->getConfig()->get( 'CacheEpoch' ) ),
                        filemtime( "$IP/resources/src/startup.js" ),
                        $this->getHashMtime( $context )
                );
@@ -456,11 +462,9 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         * @return string Hash
         */
        public function getModifiedHash( ResourceLoaderContext $context ) {
-               global $wgLegacyJavaScriptGlobals;
-
                $data = array(
-                       'vars' => $this->getConfig( $context ),
-                       'wgLegacyJavaScriptGlobals' => $wgLegacyJavaScriptGlobals,
+                       'vars' => $this->getConfigSettings( $context ),
+                       'wgLegacyJavaScriptGlobals' => $this->getConfig()->get( 'LegacyJavaScriptGlobals' ),
                );
 
                return md5( serialize( $data ) );
index 082a65c..7abecc7 100644 (file)
@@ -54,9 +54,9 @@ class ResourceLoaderUserCSSPrefsModule extends ResourceLoaderModule {
         * @return array
         */
        public function getStyles( ResourceLoaderContext $context ) {
-               global $wgAllowUserCssPrefs, $wgUser;
+               global $wgUser;
 
-               if ( !$wgAllowUserCssPrefs ) {
+               if ( !$this->getConfig()->get( 'AllowUserCssPrefs' ) ) {
                        return array();
                }
 
@@ -83,6 +83,8 @@ class ResourceLoaderUserCSSPrefsModule extends ResourceLoaderModule {
                $style = implode( "\n", $rules );
                if ( $this->getFlip( $context ) ) {
                        $style = CSSJanus::transform( $style, true, false );
+               } else {
+                       $style = CSSJanus::nullTransform( $style );
                }
                return array( 'all' => $style );
        }
index 680c74c..7cf1942 100644 (file)
@@ -37,13 +37,16 @@ class ResourceLoaderUserGroupsModule extends ResourceLoaderWikiModule {
         * @return array
         */
        protected function getPages( ResourceLoaderContext $context ) {
-               global $wgUser, $wgUseSiteJs, $wgUseSiteCss;
+               global $wgUser;
 
                $userName = $context->getUser();
                if ( $userName === null ) {
                        return array();
                }
-               if ( !$wgUseSiteJs && !$wgUseSiteCss ) {
+
+               $useSiteJs = $this->getConfig()->get( 'UseSiteJs' );
+               $useSiteCss = $this->getConfig()->get( 'UseSiteCss' );
+               if ( !$useSiteJs && !$useSiteCss ) {
                        return array();
                }
 
@@ -62,10 +65,10 @@ class ResourceLoaderUserGroupsModule extends ResourceLoaderWikiModule {
                        if ( $group == '*' ) {
                                continue;
                        }
-                       if ( $wgUseSiteJs ) {
+                       if ( $useSiteJs ) {
                                $pages["MediaWiki:Group-$group.js"] = array( 'type' => 'script' );
                        }
-                       if ( $wgUseSiteCss ) {
+                       if ( $useSiteCss ) {
                                $pages["MediaWiki:Group-$group.css"] = array( 'type' => 'style' );
                        }
                }
index 90b4838..1b6d1de 100644 (file)
@@ -38,13 +38,16 @@ class ResourceLoaderUserModule extends ResourceLoaderWikiModule {
         * @return array
         */
        protected function getPages( ResourceLoaderContext $context ) {
-               global $wgAllowUserJs, $wgAllowUserCss;
                $username = $context->getUser();
 
                if ( $username === null ) {
                        return array();
                }
-               if ( !$wgAllowUserJs && !$wgAllowUserCss ) {
+
+               $allowUserJs = $this->getConfig()->get( 'AllowUserJs' );
+               $allowUserCss = $this->getConfig()->get( 'AllowUserCss' );
+
+               if ( !$allowUserJs && !$allowUserCss ) {
                        return array();
                }
 
@@ -58,11 +61,11 @@ class ResourceLoaderUserModule extends ResourceLoaderWikiModule {
                $userpage = $userpageTitle->getPrefixedDBkey(); // Needed so $excludepages works
 
                $pages = array();
-               if ( $wgAllowUserJs ) {
+               if ( $allowUserJs ) {
                        $pages["$userpage/common.js"] = array( 'type' => 'script' );
                        $pages["$userpage/" . $context->getSkin() . '.js'] = array( 'type' => 'script' );
                }
-               if ( $wgAllowUserCss ) {
+               if ( $allowUserCss ) {
                        $pages["$userpage/common.css"] = array( 'type' => 'style' );
                        $pages["$userpage/" . $context->getSkin() . '.css'] = array( 'type' => 'style' );
                }
index e652422..668467c 100644 (file)
@@ -44,8 +44,8 @@ class ResourceLoaderUserTokensModule extends ResourceLoaderModule {
 
                return array(
                        'editToken' => $wgUser->getEditToken(),
-                       'patrolToken' => ApiQueryRecentChanges::getPatrolToken( null, null ),
-                       'watchToken' => ApiQueryInfo::getWatchToken( null, null ),
+                       'patrolToken' => $wgUser->getEditToken( 'patrol' ),
+                       'watchToken' => $wgUser->getEditToken( 'watch' ),
                );
        }
 
index bfb3c42..2eaca67 100644 (file)
@@ -36,8 +36,8 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
        # Origin is user-supplied code
        protected $origin = self::ORIGIN_USER_SITEWIDE;
 
-       // In-object cache for title mtimes
-       protected $titleMtimes = array();
+       // In-object cache for title info
+       protected $titleInfo = array();
 
        /* Abstract Protected Methods */
 
@@ -96,14 +96,14 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
                        return null;
                }
 
-               $model = $content->getModel();
-
-               if ( $model !== CONTENT_MODEL_CSS && $model !== CONTENT_MODEL_JAVASCRIPT ) {
-                       wfDebugLog( 'resourceloader', __METHOD__ . ': bad content model $model for JS/CSS page!' );
+               if ( $content->isSupportedFormat( CONTENT_FORMAT_JAVASCRIPT ) ) {
+                       return $content->serialize( CONTENT_FORMAT_JAVASCRIPT );
+               } elseif ( $content->isSupportedFormat( CONTENT_FORMAT_CSS ) ) {
+                       return $content->serialize( CONTENT_FORMAT_CSS );
+               } else {
+                       wfDebugLog( 'resourceloader', __METHOD__ . ": bad content model {$content->getModel()} for JS/CSS page!" );
                        return null;
                }
-
-               return $content->getNativeData(); //NOTE: this is safe, we know it's JS or CSS
        }
 
        /* Methods */
@@ -136,8 +136,6 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
         * @return array
         */
        public function getStyles( ResourceLoaderContext $context ) {
-               global $wgScriptPath;
-
                $styles = array();
                foreach ( $this->getPages( $context ) as $titleText => $options ) {
                        if ( $options['type'] !== 'style' ) {
@@ -154,8 +152,10 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
                        }
                        if ( $this->getFlip( $context ) ) {
                                $style = CSSJanus::transform( $style, true, false );
+                       } else {
+                               $style = CSSJanus::nullTransform( $style );
                        }
-                       $style = CSSMin::remap( $style, false, $wgScriptPath, true );
+                       $style = CSSMin::remap( $style, false, $this->getConfig()->get( 'ScriptPath' ), true );
                        if ( !isset( $styles[$media] ) ) {
                                $styles[$media] = array();
                        }
@@ -171,8 +171,11 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
         */
        public function getModifiedTime( ResourceLoaderContext $context ) {
                $modifiedTime = 1; // wfTimestamp() interprets 0 as "now"
-               $mtimes = $this->getTitleMtimes( $context );
-               if ( count( $mtimes ) ) {
+               $titleInfo = $this->getTitleInfo( $context );
+               if ( count( $titleInfo ) ) {
+                       $mtimes = array_map( function( $value ) {
+                               return $value['timestamp'];
+                       }, $titleInfo );
                        $modifiedTime = max( $modifiedTime, max( $mtimes ) );
                }
                $modifiedTime = max(
@@ -186,6 +189,7 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
        /**
         * Get the definition summary for this module.
         *
+        * @param ResourceLoaderContext $context
         * @return array
         */
        public function getDefinitionSummary( ResourceLoaderContext $context ) {
@@ -200,16 +204,35 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
         * @return bool
         */
        public function isKnownEmpty( ResourceLoaderContext $context ) {
-               return count( $this->getTitleMtimes( $context ) ) == 0;
+               $titleInfo = $this->getTitleInfo( $context );
+               // Bug 68488: For modules in the "user" group, we should actually
+               // check that the pages are empty (page_len == 0), but for other
+               // groups, just check the pages exist so that we don't end up
+               // caching temporarily-blank pages without the appropriate
+               // <script> or <link> tag.
+               if ( $this->getGroup() !== 'user' ) {
+                       return count( $titleInfo ) === 0;
+               }
+
+               foreach ( $titleInfo as $info ) {
+                       if ( $info['length'] !== 0 ) {
+                               // At least one non-0-lenth page, not empty
+                               return false;
+                       }
+               }
+
+               // All pages are 0-length, so it's empty
+               return true;
        }
 
        /**
         * Get the modification times of all titles that would be loaded for
         * a given context.
         * @param ResourceLoaderContext $context Context object
-        * @return array( prefixed DB key => UNIX timestamp ), nonexistent titles are dropped
+        * @return array keyed by page dbkey, with value is an array with 'length' and 'timestamp'
+        *               keys, where the timestamp is a unix one
         */
-       protected function getTitleMtimes( ResourceLoaderContext $context ) {
+       protected function getTitleInfo( ResourceLoaderContext $context ) {
                $dbr = $this->getDB();
                if ( !$dbr ) {
                        // We're dealing with a subclass that doesn't have a DB
@@ -217,11 +240,11 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
                }
 
                $hash = $context->getHash();
-               if ( isset( $this->titleMtimes[$hash] ) ) {
-                       return $this->titleMtimes[$hash];
+               if ( isset( $this->titleInfo[$hash] ) ) {
+                       return $this->titleInfo[$hash];
                }
 
-               $this->titleMtimes[$hash] = array();
+               $this->titleInfo[$hash] = array();
                $batch = new LinkBatch;
                foreach ( $this->getPages( $context ) as $titleText => $options ) {
                        $batch->addObj( Title::newFromText( $titleText ) );
@@ -229,16 +252,18 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
 
                if ( !$batch->isEmpty() ) {
                        $res = $dbr->select( 'page',
-                               array( 'page_namespace', 'page_title', 'page_touched' ),
+                               array( 'page_namespace', 'page_title', 'page_touched', 'page_len' ),
                                $batch->constructSet( 'page', $dbr ),
                                __METHOD__
                        );
                        foreach ( $res as $row ) {
                                $title = Title::makeTitle( $row->page_namespace, $row->page_title );
-                               $this->titleMtimes[$hash][$title->getPrefixedDBkey()] =
-                                       wfTimestamp( TS_UNIX, $row->page_touched );
+                               $this->titleInfo[$hash][$title->getPrefixedDBkey()] = array(
+                                       'timestamp' => wfTimestamp( TS_UNIX, $row->page_touched ),
+                                       'length' => $row->page_len,
+                               );
                        }
                }
-               return $this->titleMtimes[$hash];
+               return $this->titleInfo[$hash];
        }
 }
diff --git a/includes/revisiondelete/RevDelArchiveItem.php b/includes/revisiondelete/RevDelArchiveItem.php
new file mode 100644 (file)
index 0000000..0f1c7f0
--- /dev/null
@@ -0,0 +1,105 @@
+<?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 RevisionDelete
+ */
+
+/**
+ * Item class for a archive table row
+ */
+class RevDelArchiveItem extends RevDelRevisionItem {
+       public function __construct( $list, $row ) {
+               RevDelItem::__construct( $list, $row );
+               $this->revision = Revision::newFromArchiveRow( $row,
+                       array( 'page' => $this->list->title->getArticleID() ) );
+       }
+
+       public function getIdField() {
+               return 'ar_timestamp';
+       }
+
+       public function getTimestampField() {
+               return 'ar_timestamp';
+       }
+
+       public function getAuthorIdField() {
+               return 'ar_user';
+       }
+
+       public function getAuthorNameField() {
+               return 'ar_user_text';
+       }
+
+       public function getId() {
+               # Convert DB timestamp to MW timestamp
+               return $this->revision->getTimestamp();
+       }
+
+       public function setBits( $bits ) {
+               $dbw = wfGetDB( DB_MASTER );
+               $dbw->update( 'archive',
+                       array( 'ar_deleted' => $bits ),
+                       array(
+                               'ar_namespace' => $this->list->title->getNamespace(),
+                               'ar_title' => $this->list->title->getDBkey(),
+                               // use timestamp for index
+                               'ar_timestamp' => $this->row->ar_timestamp,
+                               'ar_rev_id' => $this->row->ar_rev_id,
+                               'ar_deleted' => $this->getBits()
+                       ),
+                       __METHOD__ );
+
+               return (bool)$dbw->affectedRows();
+       }
+
+       protected function getRevisionLink() {
+               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
+                       $this->revision->getTimestamp(), $this->list->getUser() ) );
+
+               if ( $this->isDeleted() && !$this->canViewContent() ) {
+                       return $date;
+               }
+
+               return Linker::link(
+                       SpecialPage::getTitleFor( 'Undelete' ),
+                       $date,
+                       array(),
+                       array(
+                               'target' => $this->list->title->getPrefixedText(),
+                               'timestamp' => $this->revision->getTimestamp()
+                       )
+               );
+       }
+
+       protected function getDiffLink() {
+               if ( $this->isDeleted() && !$this->canViewContent() ) {
+                       return $this->list->msg( 'diff' )->escaped();
+               }
+
+               return Linker::link(
+                       SpecialPage::getTitleFor( 'Undelete' ),
+                       $this->list->msg( 'diff' )->escaped(),
+                       array(),
+                       array(
+                               'target' => $this->list->title->getPrefixedText(),
+                               'diff' => 'prev',
+                               'timestamp' => $this->revision->getTimestamp()
+                       )
+               );
+       }
+}
diff --git a/includes/revisiondelete/RevDelArchiveList.php b/includes/revisiondelete/RevDelArchiveList.php
new file mode 100644 (file)
index 0000000..e7aed73
--- /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
+ * @ingroup RevisionDelete
+ */
+
+/**
+ * List for archive table items, i.e. revisions deleted via action=delete
+ */
+class RevDelArchiveList extends RevDelRevisionList {
+       public function getType() {
+               return 'archive';
+       }
+
+       public static function getRelationType() {
+               return 'ar_timestamp';
+       }
+
+       /**
+        * @param DatabaseBase $db
+        * @return mixed
+        */
+       public function doQuery( $db ) {
+               $timestamps = array();
+               foreach ( $this->ids as $id ) {
+                       $timestamps[] = $db->timestamp( $id );
+               }
+
+               return $db->select( 'archive', Revision::selectArchiveFields(),
+                               array(
+                                       'ar_namespace' => $this->title->getNamespace(),
+                                       'ar_title' => $this->title->getDBkey(),
+                                       'ar_timestamp' => $timestamps
+                               ),
+                               __METHOD__,
+                               array( 'ORDER BY' => 'ar_timestamp DESC' )
+                       );
+       }
+
+       public function newItem( $row ) {
+               return new RevDelArchiveItem( $this, $row );
+       }
+
+       public function doPreCommitUpdates() {
+               return Status::newGood();
+       }
+
+       public function doPostCommitUpdates() {
+               return Status::newGood();
+       }
+}
diff --git a/includes/revisiondelete/RevDelArchivedFileItem.php b/includes/revisiondelete/RevDelArchivedFileItem.php
new file mode 100644 (file)
index 0000000..7c41c18
--- /dev/null
@@ -0,0 +1,129 @@
+<?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 RevisionDelete
+ */
+
+/**
+ * Item class for a filearchive table row
+ */
+class RevDelArchivedFileItem extends RevDelFileItem {
+       public function __construct( $list, $row ) {
+               RevDelItem::__construct( $list, $row );
+               $this->file = ArchivedFile::newFromRow( $row );
+       }
+
+       public function getIdField() {
+               return 'fa_id';
+       }
+
+       public function getTimestampField() {
+               return 'fa_timestamp';
+       }
+
+       public function getAuthorIdField() {
+               return 'fa_user';
+       }
+
+       public function getAuthorNameField() {
+               return 'fa_user_text';
+       }
+
+       public function getId() {
+               return $this->row->fa_id;
+       }
+
+       public function setBits( $bits ) {
+               $dbw = wfGetDB( DB_MASTER );
+               $dbw->update( 'filearchive',
+                       array( 'fa_deleted' => $bits ),
+                       array(
+                               'fa_id' => $this->row->fa_id,
+                               'fa_deleted' => $this->getBits(),
+                       ),
+                       __METHOD__
+               );
+
+               return (bool)$dbw->affectedRows();
+       }
+
+       protected function getLink() {
+               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
+                       $this->file->getTimestamp(), $this->list->getUser() ) );
+
+               # Hidden files...
+               if ( !$this->canViewContent() ) {
+                       $link = $date;
+               } else {
+                       $undelete = SpecialPage::getTitleFor( 'Undelete' );
+                       $key = $this->file->getKey();
+                       $link = Linker::link( $undelete, $date, array(),
+                               array(
+                                       'target' => $this->list->title->getPrefixedText(),
+                                       'file' => $key,
+                                       'token' => $this->list->getUser()->getEditToken( $key )
+                               )
+                       );
+               }
+               if ( $this->isDeleted() ) {
+                       $link = '<span class="history-deleted">' . $link . '</span>';
+               }
+
+               return $link;
+       }
+
+       public function getApiData( ApiResult $result ) {
+               $file = $this->file;
+               $user = $this->list->getUser();
+               $ret = array(
+                       'title' => $this->list->title->getPrefixedText(),
+                       'timestamp' => wfTimestamp( TS_ISO_8601, $file->getTimestamp() ),
+                       'width' => $file->getWidth(),
+                       'height' => $file->getHeight(),
+                       'size' => $file->getSize(),
+               );
+               $ret += $file->isDeleted( Revision::DELETED_USER ) ? array( 'userhidden' => '' ) : array();
+               $ret += $file->isDeleted( Revision::DELETED_COMMENT ) ? array( 'commenthidden' => '' ) : array();
+               $ret += $this->isDeleted() ? array( 'contenthidden' => '' ) : array();
+               if ( $this->canViewContent() ) {
+                       $ret += array(
+                               'url' => SpecialPage::getTitleFor( 'Revisiondelete' )->getLinkURL(
+                                       array(
+                                               'target' => $this->list->title->getPrefixedText(),
+                                               'file' => $file->getKey(),
+                                               'token' => $user->getEditToken( $file->getKey() )
+                                       ),
+                                       false, PROTO_RELATIVE
+                               ),
+                       );
+               }
+               if ( $file->userCan( Revision::DELETED_USER, $user ) ) {
+                       $ret += array(
+                               'userid' => $file->getUser( 'id' ),
+                               'user' => $file->getUser( 'text' ),
+                       );
+               }
+               if ( $file->userCan( Revision::DELETED_COMMENT, $user ) ) {
+                       $ret += array(
+                               'comment' => $file->getRawDescription(),
+                       );
+               }
+
+               return $ret;
+       }
+}
diff --git a/includes/revisiondelete/RevDelArchivedFileList.php b/includes/revisiondelete/RevDelArchivedFileList.php
new file mode 100644 (file)
index 0000000..aec51b1
--- /dev/null
@@ -0,0 +1,56 @@
+<?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 RevisionDelete
+ */
+
+/**
+ * List for filearchive table items
+ */
+class RevDelArchivedFileList extends RevDelFileList {
+       public function getType() {
+               return 'filearchive';
+       }
+
+       public static function getRelationType() {
+               return 'fa_id';
+       }
+
+       /**
+        * @param DatabaseBase $db
+        * @return mixed
+        */
+       public function doQuery( $db ) {
+               $ids = array_map( 'intval', $this->ids );
+
+               return $db->select(
+                       'filearchive',
+                       ArchivedFile::selectFields(),
+                       array(
+                               'fa_name' => $this->title->getDBkey(),
+                               'fa_id' => $ids
+                       ),
+                       __METHOD__,
+                       array( 'ORDER BY' => 'fa_id DESC' )
+               );
+       }
+
+       public function newItem( $row ) {
+               return new RevDelArchivedFileItem( $this, $row );
+       }
+}
diff --git a/includes/revisiondelete/RevDelArchivedRevisionItem.php b/includes/revisiondelete/RevDelArchivedRevisionItem.php
new file mode 100644 (file)
index 0000000..9ec548f
--- /dev/null
@@ -0,0 +1,53 @@
+<?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 RevisionDelete
+ */
+
+/**
+ * Item class for a archive table row by ar_rev_id -- actually
+ * used via RevDelRevisionList.
+ */
+class RevDelArchivedRevisionItem extends RevDelArchiveItem {
+       public function __construct( $list, $row ) {
+               RevDelItem::__construct( $list, $row );
+
+               $this->revision = Revision::newFromArchiveRow( $row,
+                       array( 'page' => $this->list->title->getArticleID() ) );
+       }
+
+       public function getIdField() {
+               return 'ar_rev_id';
+       }
+
+       public function getId() {
+               return $this->revision->getId();
+       }
+
+       public function setBits( $bits ) {
+               $dbw = wfGetDB( DB_MASTER );
+               $dbw->update( 'archive',
+                       array( 'ar_deleted' => $bits ),
+                       array( 'ar_rev_id' => $this->row->ar_rev_id,
+                               'ar_deleted' => $this->getBits()
+                       ),
+                       __METHOD__ );
+
+               return (bool)$dbw->affectedRows();
+       }
+}
diff --git a/includes/revisiondelete/RevDelFileItem.php b/includes/revisiondelete/RevDelFileItem.php
new file mode 100644 (file)
index 0000000..a6517fe
--- /dev/null
@@ -0,0 +1,237 @@
+<?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 RevisionDelete
+ */
+
+/**
+ * Item class for an oldimage table row
+ */
+class RevDelFileItem extends RevDelItem {
+       /** @var File */
+       public $file;
+
+       public function __construct( $list, $row ) {
+               parent::__construct( $list, $row );
+               $this->file = RepoGroup::singleton()->getLocalRepo()->newFileFromRow( $row );
+       }
+
+       public function getIdField() {
+               return 'oi_archive_name';
+       }
+
+       public function getTimestampField() {
+               return 'oi_timestamp';
+       }
+
+       public function getAuthorIdField() {
+               return 'oi_user';
+       }
+
+       public function getAuthorNameField() {
+               return 'oi_user_text';
+       }
+
+       public function getId() {
+               $parts = explode( '!', $this->row->oi_archive_name );
+
+               return $parts[0];
+       }
+
+       public function canView() {
+               return $this->file->userCan( File::DELETED_RESTRICTED, $this->list->getUser() );
+       }
+
+       public function canViewContent() {
+               return $this->file->userCan( File::DELETED_FILE, $this->list->getUser() );
+       }
+
+       public function getBits() {
+               return $this->file->getVisibility();
+       }
+
+       public function setBits( $bits ) {
+               # Queue the file op
+               # @todo FIXME: Move to LocalFile.php
+               if ( $this->isDeleted() ) {
+                       if ( $bits & File::DELETED_FILE ) {
+                               # Still deleted
+                       } else {
+                               # Newly undeleted
+                               $key = $this->file->getStorageKey();
+                               $srcRel = $this->file->repo->getDeletedHashPath( $key ) . $key;
+                               $this->list->storeBatch[] = array(
+                                       $this->file->repo->getVirtualUrl( 'deleted' ) . '/' . $srcRel,
+                                       'public',
+                                       $this->file->getRel()
+                               );
+                               $this->list->cleanupBatch[] = $key;
+                       }
+               } elseif ( $bits & File::DELETED_FILE ) {
+                       # Newly deleted
+                       $key = $this->file->getStorageKey();
+                       $dstRel = $this->file->repo->getDeletedHashPath( $key ) . $key;
+                       $this->list->deleteBatch[] = array( $this->file->getRel(), $dstRel );
+               }
+
+               # Do the database operations
+               $dbw = wfGetDB( DB_MASTER );
+               $dbw->update( 'oldimage',
+                       array( 'oi_deleted' => $bits ),
+                       array(
+                               'oi_name' => $this->row->oi_name,
+                               'oi_timestamp' => $this->row->oi_timestamp,
+                               'oi_deleted' => $this->getBits()
+                       ),
+                       __METHOD__
+               );
+
+               return (bool)$dbw->affectedRows();
+       }
+
+       public function isDeleted() {
+               return $this->file->isDeleted( File::DELETED_FILE );
+       }
+
+       /**
+        * Get the link to the file.
+        * Overridden by RevDelArchivedFileItem.
+        * @return string
+        */
+       protected function getLink() {
+               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
+                       $this->file->getTimestamp(), $this->list->getUser() ) );
+
+               if ( !$this->isDeleted() ) {
+                       # Regular files...
+                       return Html::rawElement( 'a', array( 'href' => $this->file->getUrl() ), $date );
+               }
+
+               # Hidden files...
+               if ( !$this->canViewContent() ) {
+                       $link = $date;
+               } else {
+                       $link = Linker::link(
+                               SpecialPage::getTitleFor( 'Revisiondelete' ),
+                               $date,
+                               array(),
+                               array(
+                                       'target' => $this->list->title->getPrefixedText(),
+                                       'file' => $this->file->getArchiveName(),
+                                       'token' => $this->list->getUser()->getEditToken(
+                                               $this->file->getArchiveName() )
+                               )
+                       );
+               }
+
+               return '<span class="history-deleted">' . $link . '</span>';
+       }
+
+       /**
+        * Generate a user tool link cluster if the current user is allowed to view it
+        * @return string HTML
+        */
+       protected function getUserTools() {
+               if ( $this->file->userCan( Revision::DELETED_USER, $this->list->getUser() ) ) {
+                       $uid = $this->file->getUser( 'id' );
+                       $name = $this->file->getUser( 'text' );
+                       $link = Linker::userLink( $uid, $name ) . Linker::userToolLinks( $uid, $name );
+               } else {
+                       $link = $this->list->msg( 'rev-deleted-user' )->escaped();
+               }
+               if ( $this->file->isDeleted( Revision::DELETED_USER ) ) {
+                       return '<span class="history-deleted">' . $link . '</span>';
+               }
+
+               return $link;
+       }
+
+       /**
+        * Wrap and format the file's comment block, if the current
+        * user is allowed to view it.
+        *
+        * @return string HTML
+        */
+       protected function getComment() {
+               if ( $this->file->userCan( File::DELETED_COMMENT, $this->list->getUser() ) ) {
+                       $block = Linker::commentBlock( $this->file->getDescription() );
+               } else {
+                       $block = ' ' . $this->list->msg( 'rev-deleted-comment' )->escaped();
+               }
+               if ( $this->file->isDeleted( File::DELETED_COMMENT ) ) {
+                       return "<span class=\"history-deleted\">$block</span>";
+               }
+
+               return $block;
+       }
+
+       public function getHTML() {
+               $data =
+                       $this->list->msg( 'widthheight' )->numParams(
+                               $this->file->getWidth(), $this->file->getHeight() )->text() .
+                       ' (' . $this->list->msg( 'nbytes' )->numParams( $this->file->getSize() )->text() . ')';
+
+               return '<li>' . $this->getLink() . ' ' . $this->getUserTools() . ' ' .
+                       $data . ' ' . $this->getComment() . '</li>';
+       }
+
+       public function getApiData( ApiResult $result ) {
+               $file = $this->file;
+               $user = $this->list->getUser();
+               $ret = array(
+                       'title' => $this->list->title->getPrefixedText(),
+                       'archivename' => $file->getArchiveName(),
+                       'timestamp' => wfTimestamp( TS_ISO_8601, $file->getTimestamp() ),
+                       'width' => $file->getWidth(),
+                       'height' => $file->getHeight(),
+                       'size' => $file->getSize(),
+               );
+               $ret += $file->isDeleted( Revision::DELETED_USER ) ? array( 'userhidden' => '' ) : array();
+               $ret += $file->isDeleted( Revision::DELETED_COMMENT ) ? array( 'commenthidden' => '' ) : array();
+               $ret += $this->isDeleted() ? array( 'contenthidden' => '' ) : array();
+               if ( !$this->isDeleted() ) {
+                       $ret += array(
+                               'url' => $file->getUrl(),
+                       );
+               } elseif ( $this->canViewContent() ) {
+                       $ret += array(
+                               'url' => SpecialPage::getTitleFor( 'Revisiondelete' )->getLinkURL(
+                                       array(
+                                               'target' => $this->list->title->getPrefixedText(),
+                                               'file' => $file->getArchiveName(),
+                                               'token' => $user->getEditToken( $file->getArchiveName() )
+                                       ),
+                                       false, PROTO_RELATIVE
+                               ),
+                       );
+               }
+               if ( $file->userCan( Revision::DELETED_USER, $user ) ) {
+                       $ret += array(
+                               'userid' => $file->user,
+                               'user' => $file->user_text,
+                       );
+               }
+               if ( $file->userCan( Revision::DELETED_COMMENT, $user ) ) {
+                       $ret += array(
+                               'comment' => $file->description,
+                       );
+               }
+
+               return $ret;
+       }
+}
diff --git a/includes/revisiondelete/RevDelFileList.php b/includes/revisiondelete/RevDelFileList.php
new file mode 100644 (file)
index 0000000..57e15d8
--- /dev/null
@@ -0,0 +1,128 @@
+<?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 RevisionDelete
+ */
+
+/**
+ * List for oldimage table items
+ */
+class RevDelFileList extends RevDelList {
+       /** @var array */
+       public $storeBatch;
+
+       /** @var array */
+       public $deleteBatch;
+
+       /** @var array */
+       public $cleanupBatch;
+
+       public function getType() {
+               return 'oldimage';
+       }
+
+       public static function getRelationType() {
+               return 'oi_archive_name';
+       }
+
+       public static function getRestriction() {
+               return 'deleterevision';
+       }
+
+       public static function getRevdelConstant() {
+               return File::DELETED_FILE;
+       }
+
+       /**
+        * @param DatabaseBase $db
+        * @return mixed
+        */
+       public function doQuery( $db ) {
+               $archiveNames = array();
+               foreach ( $this->ids as $timestamp ) {
+                       $archiveNames[] = $timestamp . '!' . $this->title->getDBkey();
+               }
+
+               return $db->select(
+                       'oldimage',
+                       OldLocalFile::selectFields(),
+                       array(
+                               'oi_name' => $this->title->getDBkey(),
+                               'oi_archive_name' => $archiveNames
+                       ),
+                       __METHOD__,
+                       array( 'ORDER BY' => 'oi_timestamp DESC' )
+               );
+       }
+
+       public function newItem( $row ) {
+               return new RevDelFileItem( $this, $row );
+       }
+
+       public function clearFileOps() {
+               $this->deleteBatch = array();
+               $this->storeBatch = array();
+               $this->cleanupBatch = array();
+       }
+
+       public function doPreCommitUpdates() {
+               $status = Status::newGood();
+               $repo = RepoGroup::singleton()->getLocalRepo();
+               if ( $this->storeBatch ) {
+                       $status->merge( $repo->storeBatch( $this->storeBatch, FileRepo::OVERWRITE_SAME ) );
+               }
+               if ( !$status->isOK() ) {
+                       return $status;
+               }
+               if ( $this->deleteBatch ) {
+                       $status->merge( $repo->deleteBatch( $this->deleteBatch ) );
+               }
+               if ( !$status->isOK() ) {
+                       // Running cleanupDeletedBatch() after a failed storeBatch() with the DB already
+                       // modified (but destined for rollback) causes data loss
+                       return $status;
+               }
+               if ( $this->cleanupBatch ) {
+                       $status->merge( $repo->cleanupDeletedBatch( $this->cleanupBatch ) );
+               }
+
+               return $status;
+       }
+
+       public function doPostCommitUpdates() {
+               $file = wfLocalFile( $this->title );
+               $file->purgeCache();
+               $file->purgeDescription();
+               $purgeUrls = array();
+               foreach ( $this->ids as $timestamp ) {
+                       $archiveName = $timestamp . '!' . $this->title->getDBkey();
+                       $file->purgeOldThumbnails( $archiveName );
+                       $purgeUrls[] = $file->getArchiveUrl( $archiveName );
+               }
+               if ( $this->getConfig()->get( 'UseSquid' ) ) {
+                       // purge full images from cache
+                       SquidUpdate::purge( $purgeUrls );
+               }
+
+               return Status::newGood();
+       }
+
+       public function getSuppressBit() {
+               return File::DELETED_RESTRICTED;
+       }
+}
diff --git a/includes/revisiondelete/RevDelItem.php b/includes/revisiondelete/RevDelItem.php
new file mode 100644 (file)
index 0000000..ebdbf3a
--- /dev/null
@@ -0,0 +1,62 @@
+<?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 RevisionDelete
+ */
+
+/**
+ * Abstract base class for deletable items
+ */
+abstract class RevDelItem extends RevisionItemBase {
+       /**
+        * Returns true if the item is "current", and the operation to set the given
+        * bits can't be executed for that reason
+        * STUB
+        * @param int $newBits
+        * @return bool
+        */
+       public function isHideCurrentOp( $newBits ) {
+               return false;
+       }
+
+       /**
+        * Get the current deletion bitfield value
+        */
+       abstract public function getBits();
+
+       /**
+        * Set the visibility of the item. This should do any necessary DB queries.
+        *
+        * The DB update query should have a condition which forces it to only update
+        * if the value in the DB matches the value fetched earlier with the SELECT.
+        * If the update fails because it did not match, the function should return
+        * false. This prevents concurrency problems.
+        *
+        * @param int $newBits
+        * @return bool Success
+        */
+       abstract public function setBits( $newBits );
+
+       /**
+        * Get the return information about the revision for the API
+        * @since 1.23
+        * @param ApiResult $result API result object
+        * @return array Data for the API result
+        */
+       abstract public function getApiData( ApiResult $result );
+}
diff --git a/includes/revisiondelete/RevDelList.php b/includes/revisiondelete/RevDelList.php
new file mode 100644 (file)
index 0000000..a0ff667
--- /dev/null
@@ -0,0 +1,313 @@
+<?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 RevisionDelete
+ */
+
+/**
+ * Abstract base class for a list of deletable items. The list class
+ * needs to be able to make a query from a set of identifiers to pull
+ * relevant rows, to return RevDelItem subclasses wrapping them, and
+ * to wrap bulk update operations.
+ */
+abstract class RevDelList extends RevisionListBase {
+       function __construct( IContextSource $context, Title $title, array $ids ) {
+               parent::__construct( $context, $title );
+               $this->ids = $ids;
+       }
+
+       /**
+        * Get the DB field name associated with the ID list.
+        * This used to populate the log_search table for finding log entries.
+        * Override this function.
+        * @return string|null
+        */
+       public static function getRelationType() {
+               return null;
+       }
+
+       /**
+        * Get the user right required for this list type
+        * Override this function.
+        * @since 1.22
+        * @return string|null
+        */
+       public static function getRestriction() {
+               return null;
+       }
+
+       /**
+        * Get the revision deletion constant for this list type
+        * Override this function.
+        * @since 1.22
+        * @return int|null
+        */
+       public static function getRevdelConstant() {
+               return null;
+       }
+
+       /**
+        * Suggest a target for the revision deletion
+        * Optionally override this function.
+        * @since 1.22
+        * @param Title|null $target User-supplied target
+        * @param array $ids
+        * @return Title|null
+        */
+       public static function suggestTarget( $target, array $ids ) {
+               return $target;
+       }
+
+       /**
+        * Set the visibility for the revisions in this list. Logging and
+        * transactions are done here.
+        *
+        * @param array $params Associative array of parameters. Members are:
+        *     value:         The integer value to set the visibility to
+        *     comment:       The log comment.
+        *     perItemStatus: Set if you want per-item status reports
+        * @return Status
+        * @since 1.23 Added 'perItemStatus' param
+        */
+       public function setVisibility( $params ) {
+               $bitPars = $params['value'];
+               $comment = $params['comment'];
+               $perItemStatus = isset( $params['perItemStatus'] ) ? $params['perItemStatus'] : false;
+
+               $this->res = false;
+               $dbw = wfGetDB( DB_MASTER );
+               $this->doQuery( $dbw );
+               $dbw->begin( __METHOD__ );
+               $status = Status::newGood();
+               $missing = array_flip( $this->ids );
+               $this->clearFileOps();
+               $idsForLog = array();
+               $authorIds = $authorIPs = array();
+
+               if ( $perItemStatus ) {
+                       $status->itemStatuses = array();
+               }
+
+               // @codingStandardsIgnoreStart Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed
+               for ( $this->reset(); $this->current(); $this->next() ) {
+                       // @codingStandardsIgnoreEnd
+                       $item = $this->current();
+                       unset( $missing[$item->getId()] );
+
+                       if ( $perItemStatus ) {
+                               $itemStatus = Status::newGood();
+                               $status->itemStatuses[$item->getId()] = $itemStatus;
+                       } else {
+                               $itemStatus = $status;
+                       }
+
+                       $oldBits = $item->getBits();
+                       // Build the actual new rev_deleted bitfield
+                       $newBits = RevisionDeleter::extractBitfield( $bitPars, $oldBits );
+
+                       if ( $oldBits == $newBits ) {
+                               $itemStatus->warning( 'revdelete-no-change', $item->formatDate(), $item->formatTime() );
+                               $status->failCount++;
+                               continue;
+                       } elseif ( $oldBits == 0 && $newBits != 0 ) {
+                               $opType = 'hide';
+                       } elseif ( $oldBits != 0 && $newBits == 0 ) {
+                               $opType = 'show';
+                       } else {
+                               $opType = 'modify';
+                       }
+
+                       if ( $item->isHideCurrentOp( $newBits ) ) {
+                               // Cannot hide current version text
+                               $itemStatus->error( 'revdelete-hide-current', $item->formatDate(), $item->formatTime() );
+                               $status->failCount++;
+                               continue;
+                       }
+                       if ( !$item->canView() ) {
+                               // Cannot access this revision
+                               $msg = ( $opType == 'show' ) ?
+                                       'revdelete-show-no-access' : 'revdelete-modify-no-access';
+                               $itemStatus->error( $msg, $item->formatDate(), $item->formatTime() );
+                               $status->failCount++;
+                               continue;
+                       }
+                       // Cannot just "hide from Sysops" without hiding any fields
+                       if ( $newBits == Revision::DELETED_RESTRICTED ) {
+                               $itemStatus->warning( 'revdelete-only-restricted', $item->formatDate(), $item->formatTime() );
+                               $status->failCount++;
+                               continue;
+                       }
+
+                       // Update the revision
+                       $ok = $item->setBits( $newBits );
+
+                       if ( $ok ) {
+                               $idsForLog[] = $item->getId();
+                               $status->successCount++;
+                               if ( $item->getAuthorId() > 0 ) {
+                                       $authorIds[] = $item->getAuthorId();
+                               } elseif ( IP::isIPAddress( $item->getAuthorName() ) ) {
+                                       $authorIPs[] = $item->getAuthorName();
+                               }
+                       } else {
+                               $itemStatus->error( 'revdelete-concurrent-change', $item->formatDate(), $item->formatTime() );
+                               $status->failCount++;
+                       }
+               }
+
+               // Handle missing revisions
+               foreach ( $missing as $id => $unused ) {
+                       if ( $perItemStatus ) {
+                               $status->itemStatuses[$id] = Status::newFatal( 'revdelete-modify-missing', $id );
+                       } else {
+                               $status->error( 'revdelete-modify-missing', $id );
+                       }
+                       $status->failCount++;
+               }
+
+               if ( $status->successCount == 0 ) {
+                       $dbw->rollback( __METHOD__ );
+                       return $status;
+               }
+
+               // Save success count
+               $successCount = $status->successCount;
+
+               // Move files, if there are any
+               $status->merge( $this->doPreCommitUpdates() );
+               if ( !$status->isOK() ) {
+                       // Fatal error, such as no configured archive directory
+                       $dbw->rollback( __METHOD__ );
+                       return $status;
+               }
+
+               // Log it
+               $this->updateLog( array(
+                       'title' => $this->title,
+                       'count' => $successCount,
+                       'newBits' => $newBits,
+                       'oldBits' => $oldBits,
+                       'comment' => $comment,
+                       'ids' => $idsForLog,
+                       'authorIds' => $authorIds,
+                       'authorIPs' => $authorIPs
+               ) );
+               $dbw->commit( __METHOD__ );
+
+               // Clear caches
+               $status->merge( $this->doPostCommitUpdates() );
+               return $status;
+       }
+
+       /**
+        * Reload the list data from the master DB. This can be done after setVisibility()
+        * to allow $item->getHTML() to show the new data.
+        */
+       function reloadFromMaster() {
+               $dbw = wfGetDB( DB_MASTER );
+               $this->res = $this->doQuery( $dbw );
+       }
+
+       /**
+        * Record a log entry on the action
+        * @param array $params Associative array of parameters:
+        *     newBits:         The new value of the *_deleted bitfield
+        *     oldBits:         The old value of the *_deleted bitfield.
+        *     title:           The target title
+        *     ids:             The ID list
+        *     comment:         The log comment
+        *     authorsIds:      The array of the user IDs of the offenders
+        *     authorsIPs:      The array of the IP/anon user offenders
+        * @throws MWException
+        */
+       protected function updateLog( $params ) {
+               // Get the URL param's corresponding DB field
+               $field = RevisionDeleter::getRelationType( $this->getType() );
+               if ( !$field ) {
+                       throw new MWException( "Bad log URL param type!" );
+               }
+               // Put things hidden from sysops in the oversight log
+               if ( ( $params['newBits'] | $params['oldBits'] ) & $this->getSuppressBit() ) {
+                       $logType = 'suppress';
+               } else {
+                       $logType = 'delete';
+               }
+               // Add params for effected page and ids
+               $logParams = $this->getLogParams( $params );
+               // Actually add the deletion log entry
+               $log = new LogPage( $logType );
+               $logid = $log->addEntry( $this->getLogAction(), $params['title'],
+                       $params['comment'], $logParams, $this->getUser() );
+               // Allow for easy searching of deletion log items for revision/log items
+               $log->addRelations( $field, $params['ids'], $logid );
+               $log->addRelations( 'target_author_id', $params['authorIds'], $logid );
+               $log->addRelations( 'target_author_ip', $params['authorIPs'], $logid );
+       }
+
+       /**
+        * Get the log action for this list type
+        * @return string
+        */
+       public function getLogAction() {
+               return 'revision';
+       }
+
+       /**
+        * Get log parameter array.
+        * @param array $params Associative array of log parameters, same as updateLog()
+        * @return array
+        */
+       public function getLogParams( $params ) {
+               return array(
+                       $this->getType(),
+                       implode( ',', $params['ids'] ),
+                       "ofield={$params['oldBits']}",
+                       "nfield={$params['newBits']}"
+               );
+       }
+
+       /**
+        * Clear any data structures needed for doPreCommitUpdates() and doPostCommitUpdates()
+        * STUB
+        */
+       public function clearFileOps() {
+       }
+
+       /**
+        * A hook for setVisibility(): do batch updates pre-commit.
+        * STUB
+        * @return Status
+        */
+       public function doPreCommitUpdates() {
+               return Status::newGood();
+       }
+
+       /**
+        * A hook for setVisibility(): do any necessary updates post-commit.
+        * STUB
+        * @return Status
+        */
+       public function doPostCommitUpdates() {
+               return Status::newGood();
+       }
+
+       /**
+        * Get the integer value of the flag used for suppression
+        */
+       abstract public function getSuppressBit();
+}
diff --git a/includes/revisiondelete/RevDelLogItem.php b/includes/revisiondelete/RevDelLogItem.php
new file mode 100644 (file)
index 0000000..5c8b8c9
--- /dev/null
@@ -0,0 +1,151 @@
+<?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 RevisionDelete
+ */
+
+/**
+ * Item class for a logging table row
+ */
+class RevDelLogItem extends RevDelItem {
+       public function getIdField() {
+               return 'log_id';
+       }
+
+       public function getTimestampField() {
+               return 'log_timestamp';
+       }
+
+       public function getAuthorIdField() {
+               return 'log_user';
+       }
+
+       public function getAuthorNameField() {
+               return 'log_user_text';
+       }
+
+       public function canView() {
+               return LogEventsList::userCan( $this->row, Revision::DELETED_RESTRICTED, $this->list->getUser() );
+       }
+
+       public function canViewContent() {
+               return true; // none
+       }
+
+       public function getBits() {
+               return $this->row->log_deleted;
+       }
+
+       public function setBits( $bits ) {
+               $dbw = wfGetDB( DB_MASTER );
+               $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__
+               );
+               $dbw->update( 'logging',
+                       array( 'log_deleted' => $bits ),
+                       array(
+                               'log_id' => $this->row->log_id,
+                               'log_deleted' => $this->getBits()
+                       ),
+                       __METHOD__
+               );
+
+               return (bool)$dbw->affectedRows();
+       }
+
+       public function getHTML() {
+               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
+                       $this->row->log_timestamp, $this->list->getUser() ) );
+               $title = Title::makeTitle( $this->row->log_namespace, $this->row->log_title );
+               $formatter = LogFormatter::newFromRow( $this->row );
+               $formatter->setContext( $this->list->getContext() );
+               $formatter->setAudience( LogFormatter::FOR_THIS_USER );
+
+               // Log link for this page
+               $loglink = Linker::link(
+                       SpecialPage::getTitleFor( 'Log' ),
+                       $this->list->msg( 'log' )->escaped(),
+                       array(),
+                       array( 'page' => $title->getPrefixedText() )
+               );
+               $loglink = $this->list->msg( 'parentheses' )->rawParams( $loglink )->escaped();
+               // User links and action text
+               $action = $formatter->getActionText();
+               // Comment
+               $comment = $this->list->getLanguage()->getDirMark()
+                       . Linker::commentBlock( $this->row->log_comment );
+
+               if ( LogEventsList::isDeleted( $this->row, LogPage::DELETED_COMMENT ) ) {
+                       $comment = '<span class="history-deleted">' . $comment . '</span>';
+               }
+
+               return "<li>$loglink $date $action $comment</li>";
+       }
+
+       public function getApiData( ApiResult $result ) {
+               $logEntry = DatabaseLogEntry::newFromRow( $this->row );
+               $user = $this->list->getUser();
+               $ret = array(
+                       'id' => $logEntry->getId(),
+                       'type' => $logEntry->getType(),
+                       'action' => $logEntry->getSubtype(),
+               );
+               $ret += $logEntry->isDeleted( LogPage::DELETED_USER )
+                       ? array( 'userhidden' => '' )
+                       : array();
+               $ret += $logEntry->isDeleted( LogPage::DELETED_COMMENT )
+                       ? array( 'commenthidden' => '' )
+                       : array();
+               $ret += $logEntry->isDeleted( LogPage::DELETED_ACTION )
+                       ? array( 'actionhidden' => '' )
+                       : array();
+
+               if ( LogEventsList::userCan( $this->row, LogPage::DELETED_ACTION, $user ) ) {
+                       ApiQueryLogEvents::addLogParams(
+                               $result,
+                               $ret,
+                               $logEntry->getParameters(),
+                               $logEntry->getType(),
+                               $logEntry->getSubtype(),
+                               $logEntry->getTimestamp(),
+                               $logEntry->isLegacy()
+                       );
+               }
+               if ( LogEventsList::userCan( $this->row, LogPage::DELETED_USER, $user ) ) {
+                       $ret += array(
+                               'userid' => $this->row->log_user,
+                               'user' => $this->row->log_user_text,
+                       );
+               }
+               if ( LogEventsList::userCan( $this->row, LogPage::DELETED_COMMENT, $user ) ) {
+                       $ret += array(
+                               'comment' => $this->row->log_comment,
+                       );
+               }
+
+               return $ret;
+       }
+}
diff --git a/includes/revisiondelete/RevDelLogList.php b/includes/revisiondelete/RevDelLogList.php
new file mode 100644 (file)
index 0000000..ad04042
--- /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 RevisionDelete
+ */
+
+/**
+ * List for logging table items
+ */
+class RevDelLogList extends RevDelList {
+       public function getType() {
+               return 'logging';
+       }
+
+       public static function getRelationType() {
+               return 'log_id';
+       }
+
+       public static function getRestriction() {
+               return 'deletelogentry';
+       }
+
+       public static function getRevdelConstant() {
+               return LogPage::DELETED_ACTION;
+       }
+
+       public static function suggestTarget( $target, array $ids ) {
+               $result = wfGetDB( DB_SLAVE )->select( 'logging',
+                       'log_type',
+                       array( 'log_id' => $ids ),
+                       __METHOD__,
+                       array( 'DISTINCT' )
+               );
+               if ( $result->numRows() == 1 ) {
+                       // If there's only one type, the target can be set to include it.
+                       return SpecialPage::getTitleFor( 'Log', $result->current()->log_type );
+               }
+
+               return SpecialPage::getTitleFor( 'Log' );
+       }
+
+       /**
+        * @param DatabaseBase $db
+        * @return mixed
+        */
+       public function doQuery( $db ) {
+               $ids = array_map( 'intval', $this->ids );
+
+               return $db->select( 'logging', array(
+                               'log_id',
+                               'log_type',
+                               'log_action',
+                               'log_timestamp',
+                               'log_user',
+                               'log_user_text',
+                               'log_namespace',
+                               'log_title',
+                               'log_page',
+                               'log_comment',
+                               'log_params',
+                               'log_deleted'
+                       ),
+                       array( 'log_id' => $ids ),
+                       __METHOD__,
+                       array( 'ORDER BY' => 'log_id DESC' )
+               );
+       }
+
+       public function newItem( $row ) {
+               return new RevDelLogItem( $this, $row );
+       }
+
+       public function getSuppressBit() {
+               return Revision::DELETED_RESTRICTED;
+       }
+
+       public function getLogAction() {
+               return 'event';
+       }
+
+       public function getLogParams( $params ) {
+               return array(
+                       implode( ',', $params['ids'] ),
+                       "ofield={$params['oldBits']}",
+                       "nfield={$params['newBits']}"
+               );
+       }
+}
diff --git a/includes/revisiondelete/RevDelRevisionItem.php b/includes/revisiondelete/RevDelRevisionItem.php
new file mode 100644 (file)
index 0000000..300ce6a
--- /dev/null
@@ -0,0 +1,187 @@
+<?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 RevisionDelete
+ */
+
+/**
+ * Item class for a live revision table row
+ */
+class RevDelRevisionItem extends RevDelItem {
+       /** @var Revision */
+       public $revision;
+
+       public function __construct( $list, $row ) {
+               parent::__construct( $list, $row );
+               $this->revision = new Revision( $row );
+       }
+
+       public function getIdField() {
+               return 'rev_id';
+       }
+
+       public function getTimestampField() {
+               return 'rev_timestamp';
+       }
+
+       public function getAuthorIdField() {
+               return 'rev_user';
+       }
+
+       public function getAuthorNameField() {
+               return 'rev_user_text';
+       }
+
+       public function canView() {
+               return $this->revision->userCan( Revision::DELETED_RESTRICTED, $this->list->getUser() );
+       }
+
+       public function canViewContent() {
+               return $this->revision->userCan( Revision::DELETED_TEXT, $this->list->getUser() );
+       }
+
+       public function getBits() {
+               return $this->revision->getVisibility();
+       }
+
+       public function setBits( $bits ) {
+               $dbw = wfGetDB( DB_MASTER );
+               // Update revision table
+               $dbw->update( 'revision',
+                       array( 'rev_deleted' => $bits ),
+                       array(
+                               'rev_id' => $this->revision->getId(),
+                               'rev_page' => $this->revision->getPage(),
+                               'rev_deleted' => $this->getBits()
+                       ),
+                       __METHOD__
+               );
+               if ( !$dbw->affectedRows() ) {
+                       // Concurrent fail!
+                       return false;
+               }
+               // Update recentchanges table
+               $dbw->update( 'recentchanges',
+                       array(
+                               'rc_deleted' => $bits,
+                               'rc_patrolled' => 1
+                       ),
+                       array(
+                               'rc_this_oldid' => $this->revision->getId(), // condition
+                               // non-unique timestamp index
+                               'rc_timestamp' => $dbw->timestamp( $this->revision->getTimestamp() ),
+                       ),
+                       __METHOD__
+               );
+
+               return true;
+       }
+
+       public function isDeleted() {
+               return $this->revision->isDeleted( Revision::DELETED_TEXT );
+       }
+
+       public function isHideCurrentOp( $newBits ) {
+               return ( $newBits & Revision::DELETED_TEXT )
+                       && $this->list->getCurrent() == $this->getId();
+       }
+
+       /**
+        * Get the HTML link to the revision text.
+        * Overridden by RevDelArchiveItem.
+        * @return string
+        */
+       protected function getRevisionLink() {
+               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
+                       $this->revision->getTimestamp(), $this->list->getUser() ) );
+
+               if ( $this->isDeleted() && !$this->canViewContent() ) {
+                       return $date;
+               }
+
+               return Linker::linkKnown(
+                       $this->list->title,
+                       $date,
+                       array(),
+                       array(
+                               'oldid' => $this->revision->getId(),
+                               'unhide' => 1
+                       )
+               );
+       }
+
+       /**
+        * Get the HTML link to the diff.
+        * Overridden by RevDelArchiveItem
+        * @return string
+        */
+       protected function getDiffLink() {
+               if ( $this->isDeleted() && !$this->canViewContent() ) {
+                       return $this->list->msg( 'diff' )->escaped();
+               } else {
+                       return Linker::linkKnown(
+                                       $this->list->title,
+                                       $this->list->msg( 'diff' )->escaped(),
+                                       array(),
+                                       array(
+                                               'diff' => $this->revision->getId(),
+                                               'oldid' => 'prev',
+                                               'unhide' => 1
+                                       )
+                               );
+               }
+       }
+
+       public function getHTML() {
+               $difflink = $this->list->msg( 'parentheses' )
+                       ->rawParams( $this->getDiffLink() )->escaped();
+               $revlink = $this->getRevisionLink();
+               $userlink = Linker::revUserLink( $this->revision );
+               $comment = Linker::revComment( $this->revision );
+               if ( $this->isDeleted() ) {
+                       $revlink = "<span class=\"history-deleted\">$revlink</span>";
+               }
+
+               return "<li>$difflink $revlink $userlink $comment</li>";
+       }
+
+       public function getApiData( ApiResult $result ) {
+               $rev = $this->revision;
+               $user = $this->list->getUser();
+               $ret = array(
+                       'id' => $rev->getId(),
+                       'timestamp' => wfTimestamp( TS_ISO_8601, $rev->getTimestamp() ),
+               );
+               $ret += $rev->isDeleted( Revision::DELETED_USER ) ? array( 'userhidden' => '' ) : array();
+               $ret += $rev->isDeleted( Revision::DELETED_COMMENT ) ? array( 'commenthidden' => '' ) : array();
+               $ret += $rev->isDeleted( Revision::DELETED_TEXT ) ? array( 'texthidden' => '' ) : array();
+               if ( $rev->userCan( Revision::DELETED_USER, $user ) ) {
+                       $ret += array(
+                               'userid' => $rev->getUser( Revision::FOR_THIS_USER ),
+                               'user' => $rev->getUserText( Revision::FOR_THIS_USER ),
+                       );
+               }
+               if ( $rev->userCan( Revision::DELETED_COMMENT, $user ) ) {
+                       $ret += array(
+                               'comment' => $rev->getComment( Revision::FOR_THIS_USER ),
+                       );
+               }
+
+               return $ret;
+       }
+}
diff --git a/includes/revisiondelete/RevDelRevisionList.php b/includes/revisiondelete/RevDelRevisionList.php
new file mode 100644 (file)
index 0000000..2545072
--- /dev/null
@@ -0,0 +1,143 @@
+<?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 RevisionDelete
+ */
+
+/**
+ * List for revision table items
+ *
+ * This will check both the 'revision' table for live revisions and the
+ * 'archive' table for traditionally-deleted revisions that have an
+ * ar_rev_id saved.
+ *
+ * See RevDelRevisionItem and RevDelArchivedRevisionItem for items.
+ */
+class RevDelRevisionList extends RevDelList {
+       /** @var int */
+       public $currentRevId;
+
+       public function getType() {
+               return 'revision';
+       }
+
+       public static function getRelationType() {
+               return 'rev_id';
+       }
+
+       public static function getRestriction() {
+               return 'deleterevision';
+       }
+
+       public static function getRevdelConstant() {
+               return Revision::DELETED_TEXT;
+       }
+
+       public static function suggestTarget( $target, array $ids ) {
+               $rev = Revision::newFromId( $ids[0] );
+               return $rev ? $rev->getTitle() : $target;
+       }
+
+       /**
+        * @param DatabaseBase $db
+        * @return mixed
+        */
+       public function doQuery( $db ) {
+               $ids = array_map( 'intval', $this->ids );
+               $live = $db->select(
+                       array( 'revision', 'page', 'user' ),
+                       array_merge( Revision::selectFields(), Revision::selectUserFields() ),
+                       array(
+                               'rev_page' => $this->title->getArticleID(),
+                               'rev_id' => $ids,
+                       ),
+                       __METHOD__,
+                       array( 'ORDER BY' => 'rev_id DESC' ),
+                       array(
+                               'page' => Revision::pageJoinCond(),
+                               'user' => Revision::userJoinCond() )
+               );
+
+               if ( $live->numRows() >= count( $ids ) ) {
+                       // All requested revisions are live, keeps things simple!
+                       return $live;
+               }
+
+               // Check if any requested revisions are available fully deleted.
+               $archived = $db->select( array( 'archive' ), Revision::selectArchiveFields(),
+                       array(
+                               'ar_rev_id' => $ids
+                       ),
+                       __METHOD__,
+                       array( 'ORDER BY' => 'ar_rev_id DESC' )
+               );
+
+               if ( $archived->numRows() == 0 ) {
+                       return $live;
+               } elseif ( $live->numRows() == 0 ) {
+                       return $archived;
+               } else {
+                       // Combine the two! Whee
+                       $rows = array();
+                       foreach ( $live as $row ) {
+                               $rows[$row->rev_id] = $row;
+                       }
+                       foreach ( $archived as $row ) {
+                               $rows[$row->ar_rev_id] = $row;
+                       }
+                       krsort( $rows );
+                       return new FakeResultWrapper( array_values( $rows ) );
+               }
+       }
+
+       public function newItem( $row ) {
+               if ( isset( $row->rev_id ) ) {
+                       return new RevDelRevisionItem( $this, $row );
+               } elseif ( isset( $row->ar_rev_id ) ) {
+                       return new RevDelArchivedRevisionItem( $this, $row );
+               } else {
+                       // This shouldn't happen. :)
+                       throw new MWException( 'Invalid row type in RevDelRevisionList' );
+               }
+       }
+
+       public function getCurrent() {
+               if ( is_null( $this->currentRevId ) ) {
+                       $dbw = wfGetDB( DB_MASTER );
+                       $this->currentRevId = $dbw->selectField(
+                               'page', 'page_latest', $this->title->pageCond(), __METHOD__ );
+               }
+               return $this->currentRevId;
+       }
+
+       public function getSuppressBit() {
+               return Revision::DELETED_RESTRICTED;
+       }
+
+       public function doPreCommitUpdates() {
+               $this->title->invalidateCache();
+               return Status::newGood();
+       }
+
+       public function doPostCommitUpdates() {
+               $this->title->purgeSquid();
+               // Extensions that require referencing previous revisions may need this
+               wfRunHooks( 'ArticleRevisionVisibilitySet', array( &$this->title ) );
+               return Status::newGood();
+       }
+}
diff --git a/includes/revisiondelete/RevisionDelete.php b/includes/revisiondelete/RevisionDelete.php
deleted file mode 100644 (file)
index e7a09d7..0000000
+++ /dev/null
@@ -1,1098 +0,0 @@
-<?php
-/**
- * Base implementations for deletable items.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup RevisionDelete
- */
-
-/**
- * List for revision table items
- *
- * This will check both the 'revision' table for live revisions and the
- * 'archive' table for traditionally-deleted revisions that have an
- * ar_rev_id saved.
- *
- * See RevDelRevisionItem and RevDelArchivedRevisionItem for items.
- */
-class RevDelRevisionList extends RevDelList {
-       /** @var int */
-       var $currentRevId;
-
-       public function getType() {
-               return 'revision';
-       }
-
-       public static function getRelationType() {
-               return 'rev_id';
-       }
-
-       public static function getRestriction() {
-               return 'deleterevision';
-       }
-
-       public static function getRevdelConstant() {
-               return Revision::DELETED_TEXT;
-       }
-
-       public static function suggestTarget( $target, array $ids ) {
-               $rev = Revision::newFromId( $ids[0] );
-               return $rev ? $rev->getTitle() : $target;
-       }
-
-       /**
-        * @param DatabaseBase $db
-        * @return mixed
-        */
-       public function doQuery( $db ) {
-               $ids = array_map( 'intval', $this->ids );
-               $live = $db->select(
-                       array( 'revision', 'page', 'user' ),
-                       array_merge( Revision::selectFields(), Revision::selectUserFields() ),
-                       array(
-                               'rev_page' => $this->title->getArticleID(),
-                               'rev_id' => $ids,
-                       ),
-                       __METHOD__,
-                       array( 'ORDER BY' => 'rev_id DESC' ),
-                       array(
-                               'page' => Revision::pageJoinCond(),
-                               'user' => Revision::userJoinCond() )
-               );
-
-               if ( $live->numRows() >= count( $ids ) ) {
-                       // All requested revisions are live, keeps things simple!
-                       return $live;
-               }
-
-               // Check if any requested revisions are available fully deleted.
-               $archived = $db->select( array( 'archive' ), Revision::selectArchiveFields(),
-                       array(
-                               'ar_rev_id' => $ids
-                       ),
-                       __METHOD__,
-                       array( 'ORDER BY' => 'ar_rev_id DESC' )
-               );
-
-               if ( $archived->numRows() == 0 ) {
-                       return $live;
-               } elseif ( $live->numRows() == 0 ) {
-                       return $archived;
-               } else {
-                       // Combine the two! Whee
-                       $rows = array();
-                       foreach ( $live as $row ) {
-                               $rows[$row->rev_id] = $row;
-                       }
-                       foreach ( $archived as $row ) {
-                               $rows[$row->ar_rev_id] = $row;
-                       }
-                       krsort( $rows );
-                       return new FakeResultWrapper( array_values( $rows ) );
-               }
-       }
-
-       public function newItem( $row ) {
-               if ( isset( $row->rev_id ) ) {
-                       return new RevDelRevisionItem( $this, $row );
-               } elseif ( isset( $row->ar_rev_id ) ) {
-                       return new RevDelArchivedRevisionItem( $this, $row );
-               } else {
-                       // This shouldn't happen. :)
-                       throw new MWException( 'Invalid row type in RevDelRevisionList' );
-               }
-       }
-
-       public function getCurrent() {
-               if ( is_null( $this->currentRevId ) ) {
-                       $dbw = wfGetDB( DB_MASTER );
-                       $this->currentRevId = $dbw->selectField(
-                               'page', 'page_latest', $this->title->pageCond(), __METHOD__ );
-               }
-               return $this->currentRevId;
-       }
-
-       public function getSuppressBit() {
-               return Revision::DELETED_RESTRICTED;
-       }
-
-       public function doPreCommitUpdates() {
-               $this->title->invalidateCache();
-               return Status::newGood();
-       }
-
-       public function doPostCommitUpdates() {
-               $this->title->purgeSquid();
-               // Extensions that require referencing previous revisions may need this
-               wfRunHooks( 'ArticleRevisionVisibilitySet', array( &$this->title ) );
-               return Status::newGood();
-       }
-}
-
-/**
- * Item class for a live revision table row
- */
-class RevDelRevisionItem extends RevDelItem {
-       /** @var Revision */
-       var $revision;
-
-       public function __construct( $list, $row ) {
-               parent::__construct( $list, $row );
-               $this->revision = new Revision( $row );
-       }
-
-       public function getIdField() {
-               return 'rev_id';
-       }
-
-       public function getTimestampField() {
-               return 'rev_timestamp';
-       }
-
-       public function getAuthorIdField() {
-               return 'rev_user';
-       }
-
-       public function getAuthorNameField() {
-               return 'rev_user_text';
-       }
-
-       public function canView() {
-               return $this->revision->userCan( Revision::DELETED_RESTRICTED, $this->list->getUser() );
-       }
-
-       public function canViewContent() {
-               return $this->revision->userCan( Revision::DELETED_TEXT, $this->list->getUser() );
-       }
-
-       public function getBits() {
-               return $this->revision->getVisibility();
-       }
-
-       public function setBits( $bits ) {
-               $dbw = wfGetDB( DB_MASTER );
-               // Update revision table
-               $dbw->update( 'revision',
-                       array( 'rev_deleted' => $bits ),
-                       array(
-                               'rev_id' => $this->revision->getId(),
-                               'rev_page' => $this->revision->getPage(),
-                               'rev_deleted' => $this->getBits()
-                       ),
-                       __METHOD__
-               );
-               if ( !$dbw->affectedRows() ) {
-                       // Concurrent fail!
-                       return false;
-               }
-               // Update recentchanges table
-               $dbw->update( 'recentchanges',
-                       array(
-                               'rc_deleted' => $bits,
-                               'rc_patrolled' => 1
-                       ),
-                       array(
-                               'rc_this_oldid' => $this->revision->getId(), // condition
-                               // non-unique timestamp index
-                               'rc_timestamp' => $dbw->timestamp( $this->revision->getTimestamp() ),
-                       ),
-                       __METHOD__
-               );
-               return true;
-       }
-
-       public function isDeleted() {
-               return $this->revision->isDeleted( Revision::DELETED_TEXT );
-       }
-
-       public function isHideCurrentOp( $newBits ) {
-               return ( $newBits & Revision::DELETED_TEXT )
-                       && $this->list->getCurrent() == $this->getId();
-       }
-
-       /**
-        * Get the HTML link to the revision text.
-        * Overridden by RevDelArchiveItem.
-        * @return string
-        */
-       protected function getRevisionLink() {
-               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
-                       $this->revision->getTimestamp(), $this->list->getUser() ) );
-
-               if ( $this->isDeleted() && !$this->canViewContent() ) {
-                       return $date;
-               }
-               return Linker::linkKnown(
-                       $this->list->title,
-                       $date,
-                       array(),
-                       array(
-                               'oldid' => $this->revision->getId(),
-                               'unhide' => 1
-                       )
-               );
-       }
-
-       /**
-        * Get the HTML link to the diff.
-        * Overridden by RevDelArchiveItem
-        * @return string
-        */
-       protected function getDiffLink() {
-               if ( $this->isDeleted() && !$this->canViewContent() ) {
-                       return $this->list->msg( 'diff' )->escaped();
-               } else {
-                       return Linker::linkKnown(
-                                       $this->list->title,
-                                       $this->list->msg( 'diff' )->escaped(),
-                                       array(),
-                                       array(
-                                               'diff' => $this->revision->getId(),
-                                               'oldid' => 'prev',
-                                               'unhide' => 1
-                                       )
-                               );
-               }
-       }
-
-       public function getHTML() {
-               $difflink = $this->list->msg( 'parentheses' )
-                       ->rawParams( $this->getDiffLink() )->escaped();
-               $revlink = $this->getRevisionLink();
-               $userlink = Linker::revUserLink( $this->revision );
-               $comment = Linker::revComment( $this->revision );
-               if ( $this->isDeleted() ) {
-                       $revlink = "<span class=\"history-deleted\">$revlink</span>";
-               }
-               return "<li>$difflink $revlink $userlink $comment</li>";
-       }
-
-       public function getApiData( ApiResult $result ) {
-               $rev = $this->revision;
-               $user = $this->list->getUser();
-               $ret = array(
-                       'id' => $rev->getId(),
-                       'timestamp' => wfTimestamp( TS_ISO_8601, $rev->getTimestamp() ),
-               );
-               $ret += $rev->isDeleted( Revision::DELETED_USER ) ? array( 'userhidden' => '' ) : array();
-               $ret += $rev->isDeleted( Revision::DELETED_COMMENT ) ? array( 'commenthidden' => '' ) : array();
-               $ret += $rev->isDeleted( Revision::DELETED_TEXT ) ? array( 'texthidden' => '' ) : array();
-               if ( $rev->userCan( Revision::DELETED_USER, $user ) ) {
-                       $ret += array(
-                               'userid' => $rev->getUser( Revision::FOR_THIS_USER ),
-                               'user' => $rev->getUserText( Revision::FOR_THIS_USER ),
-                       );
-               }
-               if ( $rev->userCan( Revision::DELETED_COMMENT, $user ) ) {
-                       $ret += array(
-                               'comment' => $rev->getComment( Revision::FOR_THIS_USER ),
-                       );
-               }
-               return $ret;
-       }
-}
-
-/**
- * List for archive table items, i.e. revisions deleted via action=delete
- */
-class RevDelArchiveList extends RevDelRevisionList {
-       public function getType() {
-               return 'archive';
-       }
-
-       public static function getRelationType() {
-               return 'ar_timestamp';
-       }
-
-       /**
-        * @param DatabaseBase $db
-        * @return mixed
-        */
-       public function doQuery( $db ) {
-               $timestamps = array();
-               foreach ( $this->ids as $id ) {
-                       $timestamps[] = $db->timestamp( $id );
-               }
-               return $db->select( 'archive', Revision::selectArchiveFields(),
-                               array(
-                                       'ar_namespace' => $this->title->getNamespace(),
-                                       'ar_title' => $this->title->getDBkey(),
-                                       'ar_timestamp' => $timestamps
-                               ),
-                               __METHOD__,
-                               array( 'ORDER BY' => 'ar_timestamp DESC' )
-                       );
-       }
-
-       public function newItem( $row ) {
-               return new RevDelArchiveItem( $this, $row );
-       }
-
-       public function doPreCommitUpdates() {
-               return Status::newGood();
-       }
-
-       public function doPostCommitUpdates() {
-               return Status::newGood();
-       }
-}
-
-/**
- * Item class for a archive table row
- */
-class RevDelArchiveItem extends RevDelRevisionItem {
-       public function __construct( $list, $row ) {
-               RevDelItem::__construct( $list, $row );
-               $this->revision = Revision::newFromArchiveRow( $row,
-                       array( 'page' => $this->list->title->getArticleID() ) );
-       }
-
-       public function getIdField() {
-               return 'ar_timestamp';
-       }
-
-       public function getTimestampField() {
-               return 'ar_timestamp';
-       }
-
-       public function getAuthorIdField() {
-               return 'ar_user';
-       }
-
-       public function getAuthorNameField() {
-               return 'ar_user_text';
-       }
-
-       public function getId() {
-               # Convert DB timestamp to MW timestamp
-               return $this->revision->getTimestamp();
-       }
-
-       public function setBits( $bits ) {
-               $dbw = wfGetDB( DB_MASTER );
-               $dbw->update( 'archive',
-                       array( 'ar_deleted' => $bits ),
-                       array(
-                               'ar_namespace' => $this->list->title->getNamespace(),
-                               'ar_title' => $this->list->title->getDBkey(),
-                               // use timestamp for index
-                               'ar_timestamp' => $this->row->ar_timestamp,
-                               'ar_rev_id' => $this->row->ar_rev_id,
-                               'ar_deleted' => $this->getBits()
-                       ),
-                       __METHOD__ );
-               return (bool)$dbw->affectedRows();
-       }
-
-       protected function getRevisionLink() {
-               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
-                       $this->revision->getTimestamp(), $this->list->getUser() ) );
-
-               if ( $this->isDeleted() && !$this->canViewContent() ) {
-                       return $date;
-               }
-
-               return Linker::link(
-                       SpecialPage::getTitleFor( 'Undelete' ),
-                       $date,
-                       array(),
-                       array(
-                               'target' => $this->list->title->getPrefixedText(),
-                               'timestamp' => $this->revision->getTimestamp()
-                       )
-               );
-       }
-
-       protected function getDiffLink() {
-               if ( $this->isDeleted() && !$this->canViewContent() ) {
-                       return $this->list->msg( 'diff' )->escaped();
-               }
-
-               return Linker::link(
-                       SpecialPage::getTitleFor( 'Undelete' ),
-                       $this->list->msg( 'diff' )->escaped(),
-                       array(),
-                       array(
-                               'target' => $this->list->title->getPrefixedText(),
-                               'diff' => 'prev',
-                               'timestamp' => $this->revision->getTimestamp()
-                       )
-               );
-       }
-}
-
-/**
- * Item class for a archive table row by ar_rev_id -- actually
- * used via RevDelRevisionList.
- */
-class RevDelArchivedRevisionItem extends RevDelArchiveItem {
-       public function __construct( $list, $row ) {
-               RevDelItem::__construct( $list, $row );
-
-               $this->revision = Revision::newFromArchiveRow( $row,
-                       array( 'page' => $this->list->title->getArticleID() ) );
-       }
-
-       public function getIdField() {
-               return 'ar_rev_id';
-       }
-
-       public function getId() {
-               return $this->revision->getId();
-       }
-
-       public function setBits( $bits ) {
-               $dbw = wfGetDB( DB_MASTER );
-               $dbw->update( 'archive',
-                       array( 'ar_deleted' => $bits ),
-                       array( 'ar_rev_id' => $this->row->ar_rev_id,
-                               'ar_deleted' => $this->getBits()
-                       ),
-                       __METHOD__ );
-               return (bool)$dbw->affectedRows();
-       }
-}
-
-/**
- * List for oldimage table items
- */
-class RevDelFileList extends RevDelList {
-       /** @var array */
-       var $storeBatch;
-
-       /** @var array */
-       var $deleteBatch;
-
-       /** @var array */
-       var $cleanupBatch;
-
-       public function getType() {
-               return 'oldimage';
-       }
-
-       public static function getRelationType() {
-               return 'oi_archive_name';
-       }
-
-       public static function getRestriction() {
-               return 'deleterevision';
-       }
-
-       public static function getRevdelConstant() {
-               return File::DELETED_FILE;
-       }
-
-       /**
-        * @param DatabaseBase $db
-        * @return mixed
-        */
-       public function doQuery( $db ) {
-               $archiveNames = array();
-               foreach ( $this->ids as $timestamp ) {
-                       $archiveNames[] = $timestamp . '!' . $this->title->getDBkey();
-               }
-               return $db->select(
-                       'oldimage',
-                       OldLocalFile::selectFields(),
-                       array(
-                               'oi_name' => $this->title->getDBkey(),
-                               'oi_archive_name' => $archiveNames
-                       ),
-                       __METHOD__,
-                       array( 'ORDER BY' => 'oi_timestamp DESC' )
-               );
-       }
-
-       public function newItem( $row ) {
-               return new RevDelFileItem( $this, $row );
-       }
-
-       public function clearFileOps() {
-               $this->deleteBatch = array();
-               $this->storeBatch = array();
-               $this->cleanupBatch = array();
-       }
-
-       public function doPreCommitUpdates() {
-               $status = Status::newGood();
-               $repo = RepoGroup::singleton()->getLocalRepo();
-               if ( $this->storeBatch ) {
-                       $status->merge( $repo->storeBatch( $this->storeBatch, FileRepo::OVERWRITE_SAME ) );
-               }
-               if ( !$status->isOK() ) {
-                       return $status;
-               }
-               if ( $this->deleteBatch ) {
-                       $status->merge( $repo->deleteBatch( $this->deleteBatch ) );
-               }
-               if ( !$status->isOK() ) {
-                       // Running cleanupDeletedBatch() after a failed storeBatch() with the DB already
-                       // modified (but destined for rollback) causes data loss
-                       return $status;
-               }
-               if ( $this->cleanupBatch ) {
-                       $status->merge( $repo->cleanupDeletedBatch( $this->cleanupBatch ) );
-               }
-               return $status;
-       }
-
-       public function doPostCommitUpdates() {
-               global $wgUseSquid;
-               $file = wfLocalFile( $this->title );
-               $file->purgeCache();
-               $file->purgeDescription();
-               $purgeUrls = array();
-               foreach ( $this->ids as $timestamp ) {
-                       $archiveName = $timestamp . '!' . $this->title->getDBkey();
-                       $file->purgeOldThumbnails( $archiveName );
-                       $purgeUrls[] = $file->getArchiveUrl( $archiveName );
-               }
-               if ( $wgUseSquid ) {
-                       // purge full images from cache
-                       SquidUpdate::purge( $purgeUrls );
-               }
-               return Status::newGood();
-       }
-
-       public function getSuppressBit() {
-               return File::DELETED_RESTRICTED;
-       }
-}
-
-/**
- * Item class for an oldimage table row
- */
-class RevDelFileItem extends RevDelItem {
-       /** @var File */
-       var $file;
-
-       public function __construct( $list, $row ) {
-               parent::__construct( $list, $row );
-               $this->file = RepoGroup::singleton()->getLocalRepo()->newFileFromRow( $row );
-       }
-
-       public function getIdField() {
-               return 'oi_archive_name';
-       }
-
-       public function getTimestampField() {
-               return 'oi_timestamp';
-       }
-
-       public function getAuthorIdField() {
-               return 'oi_user';
-       }
-
-       public function getAuthorNameField() {
-               return 'oi_user_text';
-       }
-
-       public function getId() {
-               $parts = explode( '!', $this->row->oi_archive_name );
-               return $parts[0];
-       }
-
-       public function canView() {
-               return $this->file->userCan( File::DELETED_RESTRICTED, $this->list->getUser() );
-       }
-
-       public function canViewContent() {
-               return $this->file->userCan( File::DELETED_FILE, $this->list->getUser() );
-       }
-
-       public function getBits() {
-               return $this->file->getVisibility();
-       }
-
-       public function setBits( $bits ) {
-               # Queue the file op
-               # @todo FIXME: Move to LocalFile.php
-               if ( $this->isDeleted() ) {
-                       if ( $bits & File::DELETED_FILE ) {
-                               # Still deleted
-                       } else {
-                               # Newly undeleted
-                               $key = $this->file->getStorageKey();
-                               $srcRel = $this->file->repo->getDeletedHashPath( $key ) . $key;
-                               $this->list->storeBatch[] = array(
-                                       $this->file->repo->getVirtualUrl( 'deleted' ) . '/' . $srcRel,
-                                       'public',
-                                       $this->file->getRel()
-                               );
-                               $this->list->cleanupBatch[] = $key;
-                       }
-               } elseif ( $bits & File::DELETED_FILE ) {
-                       # Newly deleted
-                       $key = $this->file->getStorageKey();
-                       $dstRel = $this->file->repo->getDeletedHashPath( $key ) . $key;
-                       $this->list->deleteBatch[] = array( $this->file->getRel(), $dstRel );
-               }
-
-               # Do the database operations
-               $dbw = wfGetDB( DB_MASTER );
-               $dbw->update( 'oldimage',
-                       array( 'oi_deleted' => $bits ),
-                       array(
-                               'oi_name' => $this->row->oi_name,
-                               'oi_timestamp' => $this->row->oi_timestamp,
-                               'oi_deleted' => $this->getBits()
-                       ),
-                       __METHOD__
-               );
-               return (bool)$dbw->affectedRows();
-       }
-
-       public function isDeleted() {
-               return $this->file->isDeleted( File::DELETED_FILE );
-       }
-
-       /**
-        * Get the link to the file.
-        * Overridden by RevDelArchivedFileItem.
-        * @return string
-        */
-       protected function getLink() {
-               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
-                       $this->file->getTimestamp(), $this->list->getUser() ) );
-
-               if ( !$this->isDeleted() ) {
-                       # Regular files...
-                       return Html::rawElement( 'a', array( 'href' => $this->file->getUrl() ), $date );
-               }
-
-               # Hidden files...
-               if ( !$this->canViewContent() ) {
-                       $link = $date;
-               } else {
-                       $link = Linker::link(
-                               SpecialPage::getTitleFor( 'Revisiondelete' ),
-                               $date,
-                               array(),
-                               array(
-                                       'target' => $this->list->title->getPrefixedText(),
-                                       'file' => $this->file->getArchiveName(),
-                                       'token' => $this->list->getUser()->getEditToken(
-                                               $this->file->getArchiveName() )
-                               )
-                       );
-               }
-               return '<span class="history-deleted">' . $link . '</span>';
-       }
-
-       /**
-        * Generate a user tool link cluster if the current user is allowed to view it
-        * @return string HTML
-        */
-       protected function getUserTools() {
-               if ( $this->file->userCan( Revision::DELETED_USER, $this->list->getUser() ) ) {
-                       $uid = $this->file->getUser( 'id' );
-                       $name = $this->file->getUser( 'text' );
-                       $link = Linker::userLink( $uid, $name ) . Linker::userToolLinks( $uid, $name );
-               } else {
-                       $link = $this->list->msg( 'rev-deleted-user' )->escaped();
-               }
-               if ( $this->file->isDeleted( Revision::DELETED_USER ) ) {
-                       return '<span class="history-deleted">' . $link . '</span>';
-               }
-               return $link;
-       }
-
-       /**
-        * Wrap and format the file's comment block, if the current
-        * user is allowed to view it.
-        *
-        * @return string HTML
-        */
-       protected function getComment() {
-               if ( $this->file->userCan( File::DELETED_COMMENT, $this->list->getUser() ) ) {
-                       $block = Linker::commentBlock( $this->file->getDescription() );
-               } else {
-                       $block = ' ' . $this->list->msg( 'rev-deleted-comment' )->escaped();
-               }
-               if ( $this->file->isDeleted( File::DELETED_COMMENT ) ) {
-                       return "<span class=\"history-deleted\">$block</span>";
-               }
-               return $block;
-       }
-
-       public function getHTML() {
-               $data =
-                       $this->list->msg( 'widthheight' )->numParams(
-                               $this->file->getWidth(), $this->file->getHeight() )->text() .
-                       ' (' . $this->list->msg( 'nbytes' )->numParams( $this->file->getSize() )->text() . ')';
-
-               return '<li>' . $this->getLink() . ' ' . $this->getUserTools() . ' ' .
-                       $data . ' ' . $this->getComment() . '</li>';
-       }
-
-       public function getApiData( ApiResult $result ) {
-               $file = $this->file;
-               $user = $this->list->getUser();
-               $ret = array(
-                       'title' => $this->list->title->getPrefixedText(),
-                       'archivename' => $file->getArchiveName(),
-                       'timestamp' => wfTimestamp( TS_ISO_8601, $file->getTimestamp() ),
-                       'width' => $file->getWidth(),
-                       'height' => $file->getHeight(),
-                       'size' => $file->getSize(),
-               );
-               $ret += $file->isDeleted( Revision::DELETED_USER ) ? array( 'userhidden' => '' ) : array();
-               $ret += $file->isDeleted( Revision::DELETED_COMMENT ) ? array( 'commenthidden' => '' ) : array();
-               $ret += $this->isDeleted() ? array( 'contenthidden' => '' ) : array();
-               if ( !$this->isDeleted() ) {
-                       $ret += array(
-                               'url' => $file->getUrl(),
-                       );
-               } elseif ( $this->canViewContent() ) {
-                       $ret += array(
-                               'url' => SpecialPage::getTitleFor( 'Revisiondelete' )->getLinkURL(
-                                       array(
-                                               'target' => $this->list->title->getPrefixedText(),
-                                               'file' => $file->getArchiveName(),
-                                               'token' => $user->getEditToken( $file->getArchiveName() )
-                                       ),
-                                       false, PROTO_RELATIVE
-                               ),
-                       );
-               }
-               if ( $file->userCan( Revision::DELETED_USER, $user ) ) {
-                       $ret += array(
-                               'userid' => $file->user,
-                               'user' => $file->user_text,
-                       );
-               }
-               if ( $file->userCan( Revision::DELETED_COMMENT, $user ) ) {
-                       $ret += array(
-                               'comment' => $file->description,
-                       );
-               }
-               return $ret;
-       }
-}
-
-/**
- * List for filearchive table items
- */
-class RevDelArchivedFileList extends RevDelFileList {
-       public function getType() {
-               return 'filearchive';
-       }
-
-       public static function getRelationType() {
-               return 'fa_id';
-       }
-
-       /**
-        * @param DatabaseBase $db
-        * @return mixed
-        */
-       public function doQuery( $db ) {
-               $ids = array_map( 'intval', $this->ids );
-               return $db->select(
-                       'filearchive',
-                       ArchivedFile::selectFields(),
-                       array(
-                               'fa_name' => $this->title->getDBkey(),
-                               'fa_id' => $ids
-                       ),
-                       __METHOD__,
-                       array( 'ORDER BY' => 'fa_id DESC' )
-               );
-       }
-
-       public function newItem( $row ) {
-               return new RevDelArchivedFileItem( $this, $row );
-       }
-}
-
-/**
- * Item class for a filearchive table row
- */
-class RevDelArchivedFileItem extends RevDelFileItem {
-       public function __construct( $list, $row ) {
-               RevDelItem::__construct( $list, $row );
-               $this->file = ArchivedFile::newFromRow( $row );
-       }
-
-       public function getIdField() {
-               return 'fa_id';
-       }
-
-       public function getTimestampField() {
-               return 'fa_timestamp';
-       }
-
-       public function getAuthorIdField() {
-               return 'fa_user';
-       }
-
-       public function getAuthorNameField() {
-               return 'fa_user_text';
-       }
-
-       public function getId() {
-               return $this->row->fa_id;
-       }
-
-       public function setBits( $bits ) {
-               $dbw = wfGetDB( DB_MASTER );
-               $dbw->update( 'filearchive',
-                       array( 'fa_deleted' => $bits ),
-                       array(
-                               'fa_id' => $this->row->fa_id,
-                               'fa_deleted' => $this->getBits(),
-                       ),
-                       __METHOD__
-               );
-               return (bool)$dbw->affectedRows();
-       }
-
-       protected function getLink() {
-               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
-                       $this->file->getTimestamp(), $this->list->getUser() ) );
-
-               # Hidden files...
-               if ( !$this->canViewContent() ) {
-                       $link = $date;
-               } else {
-                       $undelete = SpecialPage::getTitleFor( 'Undelete' );
-                       $key = $this->file->getKey();
-                       $link = Linker::link( $undelete, $date, array(),
-                               array(
-                                       'target' => $this->list->title->getPrefixedText(),
-                                       'file' => $key,
-                                       'token' => $this->list->getUser()->getEditToken( $key )
-                               )
-                       );
-               }
-               if ( $this->isDeleted() ) {
-                       $link = '<span class="history-deleted">' . $link . '</span>';
-               }
-               return $link;
-       }
-}
-
-/**
- * List for logging table items
- */
-class RevDelLogList extends RevDelList {
-       public function getType() {
-               return 'logging';
-       }
-
-       public static function getRelationType() {
-               return 'log_id';
-       }
-
-       public static function getRestriction() {
-               return 'deletelogentry';
-       }
-
-       public static function getRevdelConstant() {
-               return LogPage::DELETED_ACTION;
-       }
-
-       public static function suggestTarget( $target, array $ids ) {
-               $result = wfGetDB( DB_SLAVE )->select( 'logging',
-                       'log_type',
-                       array( 'log_id' => $ids ),
-                       __METHOD__,
-                       array( 'DISTINCT' )
-               );
-               if ( $result->numRows() == 1 ) {
-                       // If there's only one type, the target can be set to include it.
-                       return SpecialPage::getTitleFor( 'Log', $result->current()->log_type );
-               }
-               return SpecialPage::getTitleFor( 'Log' );
-       }
-
-       /**
-        * @param DatabaseBase $db
-        * @return mixed
-        */
-       public function doQuery( $db ) {
-               $ids = array_map( 'intval', $this->ids );
-               return $db->select( 'logging', array(
-                               'log_id',
-                               'log_type',
-                               'log_action',
-                               'log_timestamp',
-                               'log_user',
-                               'log_user_text',
-                               'log_namespace',
-                               'log_title',
-                               'log_page',
-                               'log_comment',
-                               'log_params',
-                               'log_deleted'
-                       ),
-                       array( 'log_id' => $ids ),
-                       __METHOD__,
-                       array( 'ORDER BY' => 'log_id DESC' )
-               );
-       }
-
-       public function newItem( $row ) {
-               return new RevDelLogItem( $this, $row );
-       }
-
-       public function getSuppressBit() {
-               return Revision::DELETED_RESTRICTED;
-       }
-
-       public function getLogAction() {
-               return 'event';
-       }
-
-       public function getLogParams( $params ) {
-               return array(
-                       implode( ',', $params['ids'] ),
-                       "ofield={$params['oldBits']}",
-                       "nfield={$params['newBits']}"
-               );
-       }
-}
-
-/**
- * Item class for a logging table row
- */
-class RevDelLogItem extends RevDelItem {
-       public function getIdField() {
-               return 'log_id';
-       }
-
-       public function getTimestampField() {
-               return 'log_timestamp';
-       }
-
-       public function getAuthorIdField() {
-               return 'log_user';
-       }
-
-       public function getAuthorNameField() {
-               return 'log_user_text';
-       }
-
-       public function canView() {
-               return LogEventsList::userCan( $this->row, Revision::DELETED_RESTRICTED, $this->list->getUser() );
-       }
-
-       public function canViewContent() {
-               return true; // none
-       }
-
-       public function getBits() {
-               return $this->row->log_deleted;
-       }
-
-       public function setBits( $bits ) {
-               $dbw = wfGetDB( DB_MASTER );
-               $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__
-               );
-               $dbw->update( 'logging',
-                       array( 'log_deleted' => $bits ),
-                       array(
-                               'log_id' => $this->row->log_id,
-                               'log_deleted' => $this->getBits()
-                       ),
-                       __METHOD__
-               );
-               return (bool)$dbw->affectedRows();
-       }
-
-       public function getHTML() {
-               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
-                       $this->row->log_timestamp, $this->list->getUser() ) );
-               $title = Title::makeTitle( $this->row->log_namespace, $this->row->log_title );
-               $formatter = LogFormatter::newFromRow( $this->row );
-               $formatter->setContext( $this->list->getContext() );
-               $formatter->setAudience( LogFormatter::FOR_THIS_USER );
-
-               // Log link for this page
-               $loglink = Linker::link(
-                       SpecialPage::getTitleFor( 'Log' ),
-                       $this->list->msg( 'log' )->escaped(),
-                       array(),
-                       array( 'page' => $title->getPrefixedText() )
-               );
-               $loglink = $this->list->msg( 'parentheses' )->rawParams( $loglink )->escaped();
-               // User links and action text
-               $action = $formatter->getActionText();
-               // Comment
-               $comment = $this->list->getLanguage()->getDirMark()
-                       . Linker::commentBlock( $this->row->log_comment );
-
-               if ( LogEventsList::isDeleted( $this->row, LogPage::DELETED_COMMENT ) ) {
-                       $comment = '<span class="history-deleted">' . $comment . '</span>';
-               }
-
-               return "<li>$loglink $date $action $comment</li>";
-       }
-
-       public function getApiData( ApiResult $result ) {
-               $logEntry = DatabaseLogEntry::newFromRow( $this->row );
-               $user = $this->list->getUser();
-               $ret = array(
-                       'id' => $logEntry->getId(),
-                       'type' => $logEntry->getType(),
-                       'action' => $logEntry->getSubtype(),
-               );
-               $ret += $logEntry->isDeleted( LogPage::DELETED_USER )
-                       ? array( 'userhidden' => '' )
-                       : array();
-               $ret += $logEntry->isDeleted( LogPage::DELETED_COMMENT )
-                       ? array( 'commenthidden' => '' )
-                       : array();
-               $ret += $logEntry->isDeleted( LogPage::DELETED_ACTION )
-                       ? array( 'actionhidden' => '' )
-                       : array();
-
-               if ( LogEventsList::userCan( $this->row, LogPage::DELETED_ACTION, $user ) ) {
-                       ApiQueryLogEvents::addLogParams(
-                               $result,
-                               $ret,
-                               $logEntry->getParameters(),
-                               $logEntry->getType(),
-                               $logEntry->getSubtype(),
-                               $logEntry->getTimestamp(),
-                               $logEntry->isLegacy()
-                       );
-               }
-               if ( LogEventsList::userCan( $this->row, LogPage::DELETED_USER, $user ) ) {
-                       $ret += array(
-                               'userid' => $this->row->log_user,
-                               'user' => $this->row->log_user_text,
-                       );
-               }
-               if ( LogEventsList::userCan( $this->row, LogPage::DELETED_COMMENT, $user ) ) {
-                       $ret += array(
-                               'comment' => $this->row->log_comment,
-                       );
-               }
-               return $ret;
-       }
-}
diff --git a/includes/revisiondelete/RevisionDeleteAbstracts.php b/includes/revisiondelete/RevisionDeleteAbstracts.php
deleted file mode 100644 (file)
index 086db3a..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-<?php
-/**
- * Interface definition for deletable items.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup RevisionDelete
- */
-
-/**
- * Abstract base class for a list of deletable items. The list class
- * needs to be able to make a query from a set of identifiers to pull
- * relevant rows, to return RevDelItem subclasses wrapping them, and
- * to wrap bulk update operations.
- */
-abstract class RevDelList extends RevisionListBase {
-       function __construct( IContextSource $context, Title $title, array $ids ) {
-               parent::__construct( $context, $title );
-               $this->ids = $ids;
-       }
-
-       /**
-        * Get the DB field name associated with the ID list.
-        * This used to populate the log_search table for finding log entries.
-        * Override this function.
-        * @return string|null
-        */
-       public static function getRelationType() {
-               return null;
-       }
-
-       /**
-        * Get the user right required for this list type
-        * Override this function.
-        * @since 1.22
-        * @return string|null
-        */
-       public static function getRestriction() {
-               return null;
-       }
-
-       /**
-        * Get the revision deletion constant for this list type
-        * Override this function.
-        * @since 1.22
-        * @return int|null
-        */
-       public static function getRevdelConstant() {
-               return null;
-       }
-
-       /**
-        * Suggest a target for the revision deletion
-        * Optionally override this function.
-        * @since 1.22
-        * @param Title|null $target User-supplied target
-        * @param array $ids
-        * @return Title|null
-        */
-       public static function suggestTarget( $target, array $ids ) {
-               return $target;
-       }
-
-       /**
-        * Set the visibility for the revisions in this list. Logging and
-        * transactions are done here.
-        *
-        * @param array $params Associative array of parameters. Members are:
-        *     value:         The integer value to set the visibility to
-        *     comment:       The log comment.
-        *     perItemStatus: Set if you want per-item status reports
-        * @return Status
-        * @since 1.23 Added 'perItemStatus' param
-        */
-       public function setVisibility( $params ) {
-               $bitPars = $params['value'];
-               $comment = $params['comment'];
-               $perItemStatus = isset( $params['perItemStatus'] ) ? $params['perItemStatus'] : false;
-
-               $this->res = false;
-               $dbw = wfGetDB( DB_MASTER );
-               $this->doQuery( $dbw );
-               $dbw->begin( __METHOD__ );
-               $status = Status::newGood();
-               $missing = array_flip( $this->ids );
-               $this->clearFileOps();
-               $idsForLog = array();
-               $authorIds = $authorIPs = array();
-
-               if ( $perItemStatus ) {
-                       $status->itemStatuses = array();
-               }
-
-               // @codingStandardsIgnoreStart Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed
-               for ( $this->reset(); $this->current(); $this->next() ) {
-                       // @codingStandardsIgnoreEnd
-                       $item = $this->current();
-                       unset( $missing[$item->getId()] );
-
-                       if ( $perItemStatus ) {
-                               $itemStatus = Status::newGood();
-                               $status->itemStatuses[$item->getId()] = $itemStatus;
-                       } else {
-                               $itemStatus = $status;
-                       }
-
-                       $oldBits = $item->getBits();
-                       // Build the actual new rev_deleted bitfield
-                       $newBits = RevisionDeleter::extractBitfield( $bitPars, $oldBits );
-
-                       if ( $oldBits == $newBits ) {
-                               $itemStatus->warning( 'revdelete-no-change', $item->formatDate(), $item->formatTime() );
-                               $status->failCount++;
-                               continue;
-                       } elseif ( $oldBits == 0 && $newBits != 0 ) {
-                               $opType = 'hide';
-                       } elseif ( $oldBits != 0 && $newBits == 0 ) {
-                               $opType = 'show';
-                       } else {
-                               $opType = 'modify';
-                       }
-
-                       if ( $item->isHideCurrentOp( $newBits ) ) {
-                               // Cannot hide current version text
-                               $itemStatus->error( 'revdelete-hide-current', $item->formatDate(), $item->formatTime() );
-                               $status->failCount++;
-                               continue;
-                       }
-                       if ( !$item->canView() ) {
-                               // Cannot access this revision
-                               $msg = ( $opType == 'show' ) ?
-                                       'revdelete-show-no-access' : 'revdelete-modify-no-access';
-                               $itemStatus->error( $msg, $item->formatDate(), $item->formatTime() );
-                               $status->failCount++;
-                               continue;
-                       }
-                       // Cannot just "hide from Sysops" without hiding any fields
-                       if ( $newBits == Revision::DELETED_RESTRICTED ) {
-                               $itemStatus->warning( 'revdelete-only-restricted', $item->formatDate(), $item->formatTime() );
-                               $status->failCount++;
-                               continue;
-                       }
-
-                       // Update the revision
-                       $ok = $item->setBits( $newBits );
-
-                       if ( $ok ) {
-                               $idsForLog[] = $item->getId();
-                               $status->successCount++;
-                               if ( $item->getAuthorId() > 0 ) {
-                                       $authorIds[] = $item->getAuthorId();
-                               } elseif ( IP::isIPAddress( $item->getAuthorName() ) ) {
-                                       $authorIPs[] = $item->getAuthorName();
-                               }
-                       } else {
-                               $itemStatus->error( 'revdelete-concurrent-change', $item->formatDate(), $item->formatTime() );
-                               $status->failCount++;
-                       }
-               }
-
-               // Handle missing revisions
-               foreach ( $missing as $id => $unused ) {
-                       if ( $perItemStatus ) {
-                               $status->itemStatuses[$id] = Status::newFatal( 'revdelete-modify-missing', $id );
-                       } else {
-                               $status->error( 'revdelete-modify-missing', $id );
-                       }
-                       $status->failCount++;
-               }
-
-               if ( $status->successCount == 0 ) {
-                       $dbw->rollback( __METHOD__ );
-                       return $status;
-               }
-
-               // Save success count
-               $successCount = $status->successCount;
-
-               // Move files, if there are any
-               $status->merge( $this->doPreCommitUpdates() );
-               if ( !$status->isOK() ) {
-                       // Fatal error, such as no configured archive directory
-                       $dbw->rollback( __METHOD__ );
-                       return $status;
-               }
-
-               // Log it
-               $this->updateLog( array(
-                       'title' => $this->title,
-                       'count' => $successCount,
-                       'newBits' => $newBits,
-                       'oldBits' => $oldBits,
-                       'comment' => $comment,
-                       'ids' => $idsForLog,
-                       'authorIds' => $authorIds,
-                       'authorIPs' => $authorIPs
-               ) );
-               $dbw->commit( __METHOD__ );
-
-               // Clear caches
-               $status->merge( $this->doPostCommitUpdates() );
-               return $status;
-       }
-
-       /**
-        * Reload the list data from the master DB. This can be done after setVisibility()
-        * to allow $item->getHTML() to show the new data.
-        */
-       function reloadFromMaster() {
-               $dbw = wfGetDB( DB_MASTER );
-               $this->res = $this->doQuery( $dbw );
-       }
-
-       /**
-        * Record a log entry on the action
-        * @param array $params Associative array of parameters:
-        *     newBits:         The new value of the *_deleted bitfield
-        *     oldBits:         The old value of the *_deleted bitfield.
-        *     title:           The target title
-        *     ids:             The ID list
-        *     comment:         The log comment
-        *     authorsIds:      The array of the user IDs of the offenders
-        *     authorsIPs:      The array of the IP/anon user offenders
-        * @throws MWException
-        */
-       protected function updateLog( $params ) {
-               // Get the URL param's corresponding DB field
-               $field = RevisionDeleter::getRelationType( $this->getType() );
-               if ( !$field ) {
-                       throw new MWException( "Bad log URL param type!" );
-               }
-               // Put things hidden from sysops in the oversight log
-               if ( ( $params['newBits'] | $params['oldBits'] ) & $this->getSuppressBit() ) {
-                       $logType = 'suppress';
-               } else {
-                       $logType = 'delete';
-               }
-               // Add params for effected page and ids
-               $logParams = $this->getLogParams( $params );
-               // Actually add the deletion log entry
-               $log = new LogPage( $logType );
-               $logid = $log->addEntry( $this->getLogAction(), $params['title'],
-                       $params['comment'], $logParams, $this->getUser() );
-               // Allow for easy searching of deletion log items for revision/log items
-               $log->addRelations( $field, $params['ids'], $logid );
-               $log->addRelations( 'target_author_id', $params['authorIds'], $logid );
-               $log->addRelations( 'target_author_ip', $params['authorIPs'], $logid );
-       }
-
-       /**
-        * Get the log action for this list type
-        * @return string
-        */
-       public function getLogAction() {
-               return 'revision';
-       }
-
-       /**
-        * Get log parameter array.
-        * @param array $params Associative array of log parameters, same as updateLog()
-        * @return array
-        */
-       public function getLogParams( $params ) {
-               return array(
-                       $this->getType(),
-                       implode( ',', $params['ids'] ),
-                       "ofield={$params['oldBits']}",
-                       "nfield={$params['newBits']}"
-               );
-       }
-
-       /**
-        * Clear any data structures needed for doPreCommitUpdates() and doPostCommitUpdates()
-        * STUB
-        */
-       public function clearFileOps() {
-       }
-
-       /**
-        * A hook for setVisibility(): do batch updates pre-commit.
-        * STUB
-        * @return Status
-        */
-       public function doPreCommitUpdates() {
-               return Status::newGood();
-       }
-
-       /**
-        * A hook for setVisibility(): do any necessary updates post-commit.
-        * STUB
-        * @return Status
-        */
-       public function doPostCommitUpdates() {
-               return Status::newGood();
-       }
-
-       /**
-        * Get the integer value of the flag used for suppression
-        */
-       abstract public function getSuppressBit();
-}
-
-/**
- * Abstract base class for deletable items
- */
-abstract class RevDelItem extends RevisionItemBase {
-       /**
-        * Returns true if the item is "current", and the operation to set the given
-        * bits can't be executed for that reason
-        * STUB
-        * @return bool
-        */
-       public function isHideCurrentOp( $newBits ) {
-               return false;
-       }
-
-       /**
-        * Get the current deletion bitfield value
-        */
-       abstract public function getBits();
-
-       /**
-        * Set the visibility of the item. This should do any necessary DB queries.
-        *
-        * The DB update query should have a condition which forces it to only update
-        * if the value in the DB matches the value fetched earlier with the SELECT.
-        * If the update fails because it did not match, the function should return
-        * false. This prevents concurrency problems.
-        *
-        * @return bool Success
-        */
-       abstract public function setBits( $newBits );
-
-       /**
-        * Get the return information about the revision for the API
-        * @since 1.23
-        * @param ApiResult $result API result object
-        * @return array Data for the API result
-        */
-       abstract public function getApiData( ApiResult $result );
-}
index e42301b..d4f8167 100644 (file)
@@ -91,7 +91,7 @@ class RevisionDeleter {
         * Checks for a change in the bitfield for a certain option and updates the
         * provided array accordingly.
         *
-        * @param string $desc description to add to the array if the option was
+        * @param string $desc Description to add to the array if the option was
         * enabled / disabled.
         * @param int $field The bitmask describing the single option.
         * @param int $diff The xor of the old and new bitfields.
@@ -189,7 +189,7 @@ class RevisionDeleter {
         * Suggest a target for the revision deletion
         * @since 1.22
         * @param string $typeName
-        * @param Title|null $title User-supplied target
+        * @param Title|null $target User-supplied target
         * @param array $ids
         * @return Title|null
         */
index 56bb0ac..0eb87e4 100644 (file)
@@ -120,6 +120,8 @@ class SearchEngine {
         * Transform search term in cases when parts of the query came as different
         * GET params (when supported), e.g. for prefix queries:
         * search=test&prefix=Main_Page/Archive -> test prefix:Main Page/Archive
+        * @param string $term
+        * @return string
         */
        function transformSearchTerm( $term ) {
                return $term;
@@ -152,6 +154,7 @@ class SearchEngine {
 
        /**
         * Really find the title match.
+        * @param string $searchterm
         * @return null|Title
         */
        private static function getNearMatchInternal( $searchterm ) {
index b8b2bae..c3c3a8f 100644 (file)
@@ -117,7 +117,7 @@ class SearchHighlighter {
                                                }
                                                $offset = $endMatches[0][1] + strlen( $endMatches[0][0] );
                                        }
-                                       if ( ! $found ) {
+                                       if ( !$found ) {
                                                // couldn't find appropriate closing tag, skip
                                                $this->splitAndAdd( $textExt, $count, substr( $text, $start, strlen( $matches[0][0] ) ) );
                                                $start += strlen( $matches[0][0] );
@@ -184,7 +184,7 @@ class SearchHighlighter {
                        $succ = true;
                        // check if first text contains all terms
                        foreach ( $terms as $term ) {
-                               if ( ! preg_match( "/$patPre" . $term . "$patPost/ui", $firstText ) ) {
+                               if ( !preg_match( "/$patPre" . $term . "$patPost/ui", $firstText ) ) {
                                        $succ = false;
                                        break;
                                }
@@ -194,7 +194,7 @@ class SearchHighlighter {
                                $offsets[$first] = 0;
                        }
                }
-               if ( ! $snippets ) {
+               if ( !$snippets ) {
                        // match whole query on text
                        $this->process( $pat1, $textExt, $left, $contextchars, $snippets, $offsets );
                        // match whole query on templates/tables/images
@@ -279,7 +279,7 @@ class SearchHighlighter {
 
                $processed = array();
                foreach ( $terms as $term ) {
-                       if ( ! isset( $processed[$term] ) ) {
+                       if ( !isset( $processed[$term] ) ) {
                                $pat3 = "/$patPre(" . $term . ")$patPost/ui"; // highlight word
                                $extract = preg_replace( $pat3,
                                        "\\1<span class='searchmatch'>\\2</span>\\3", $extract );
@@ -295,7 +295,7 @@ class SearchHighlighter {
        /**
         * Split text into lines and add it to extracts array
         *
-        * @param array $extracts index -> $line
+        * @param array $extracts Index -> $line
         * @param int $count
         * @param string $text
         */
@@ -447,6 +447,7 @@ class SearchHighlighter {
        /**
         * Basic wikitext removal
         * @protected
+        * @param string $text
         * @return mixed
         */
        function removeWiki( $text ) {
@@ -482,6 +483,7 @@ class SearchHighlighter {
         * the target is category or image, leave it
         *
         * @param array $matches
+        * @return string
         */
        function linkReplace( $matches ) {
                $colon = strpos( $matches[1], ':' );
@@ -528,7 +530,7 @@ class SearchHighlighter {
                        }
                        ++$lineno;
                        $m = array();
-                       if ( ! preg_match( $pat1, $line, $m ) ) {
+                       if ( !preg_match( $pat1, $line, $m ) ) {
                                continue;
                        }
                        --$contextlines;
@@ -553,4 +555,21 @@ class SearchHighlighter {
 
                return $extract;
        }
+
+       /**
+        * Returns the first few lines of the text
+        *
+        * @param string $text
+        * @param int $contextlines Max number of returned lines
+        * @param int $contextchars Average number of characters per line
+        * @return string
+        */
+       public function highlightNone( $text, $contextlines, $contextchars ) {
+               $match = array();
+               $text = ltrim( $text ) . "\n"; // make sure the preg_match may find the last line
+               $text = str_replace( "\n\n", "\n", $text ); // remove empty lines
+               preg_match( "/^(.*\n){0,$contextlines}/", $text, $match );
+               $text = htmlspecialchars( substr( trim( $match[0] ), 0, $contextlines * $contextchars ) ); // trim and limit to max number of chars
+               return str_replace( "\n", '<br>', $text );
+       }
 }
index 0d1663f..de701f7 100644 (file)
@@ -85,6 +85,8 @@ class SearchMssql extends SearchDatabase {
         * Does not do anything for generic search engine
         * subclasses may define this though
         *
+        * @param string $filteredTerm
+        * @param bool $fulltext
         * @return string
         */
        function queryRanking( $filteredTerm, $fulltext ) {
@@ -134,6 +136,8 @@ class SearchMssql extends SearchDatabase {
        }
 
        /** @todo document
+        * @param string $filteredText
+        * @param bool $fulltext
         * @return string
         */
        function parseQuery( $filteredText, $fulltext ) {
index 581d8bc..78eba2d 100644 (file)
@@ -303,6 +303,8 @@ class SearchMySQL extends SearchDatabase {
 
        /**
         * @since 1.18 (changed)
+        * @param string $filteredTerm
+        * @param bool $fulltext
         * @return array
         */
        function getCountQuery( $filteredTerm, $fulltext ) {
@@ -374,6 +376,7 @@ class SearchMySQL extends SearchDatabase {
        /**
         * Converts some characters for MySQL's indexing to grok it correctly,
         * and pads short words to overcome limitations.
+        * @param string $string
         * @return mixed|string
         */
        function normalizeText( $string ) {
@@ -422,6 +425,7 @@ class SearchMySQL extends SearchDatabase {
         * Armor a case-folded UTF-8 string to get through MySQL's
         * fulltext search without being mucked up by funny charset
         * settings or anything else of the sort.
+        * @param array $matches
         * @return string
         */
        protected function stripForSearchCallback( $matches ) {
index 4cfcec3..348da79 100644 (file)
@@ -125,6 +125,8 @@ class SearchOracle extends SearchDatabase {
         * Does not do anything for generic search engine
         * subclasses may define this though
         *
+        * @param string $filteredTerm
+        * @param bool $fulltext
         * @return string
         */
        function queryRanking( $filteredTerm, $fulltext ) {
@@ -172,6 +174,8 @@ class SearchOracle extends SearchDatabase {
        /**
         * Parse a user input search string, and return an SQL fragment to be used
         * as part of a WHERE clause
+        * @param string $filteredText
+        * @param bool $fulltext
         * @return string
         */
        function parseQuery( $filteredText, $fulltext ) {
index 43fb016..c64c845 100644 (file)
@@ -35,14 +35,14 @@ class SearchPostgres extends SearchDatabase {
         * latest revision article text (pagecontent.old_text)
         *
         * @param string $term Raw search term
-        * @return PostgresSearchResultSet
+        * @return SqlSearchResultSet
         */
        function searchTitle( $term ) {
                $q = $this->searchQuery( $term, 'titlevector', 'page_title' );
                $olderror = error_reporting( E_ERROR );
                $resultSet = $this->db->resultObject( $this->db->query( $q, 'SearchPostgres', true ) );
                error_reporting( $olderror );
-               return new PostgresSearchResultSet( $resultSet, $this->searchTerms );
+               return new SqlSearchResultSet( $resultSet, $this->searchTerms );
        }
 
        function searchText( $term ) {
@@ -50,7 +50,7 @@ class SearchPostgres extends SearchDatabase {
                $olderror = error_reporting( E_ERROR );
                $resultSet = $this->db->resultObject( $this->db->query( $q, 'SearchPostgres', true ) );
                error_reporting( $olderror );
-               return new PostgresSearchResultSet( $resultSet, $this->searchTerms );
+               return new SqlSearchResultSet( $resultSet, $this->searchTerms );
        }
 
        /**
@@ -142,6 +142,7 @@ class SearchPostgres extends SearchDatabase {
                $top = $res->fetchRow();
                $top = $top[0];
 
+               $this->searchTerms = array();
                if ( $top === "" ) { ## e.g. if only stopwords are used XXX return something better
                        $query = "SELECT page_id, page_namespace, page_title, 0 AS score " .
                                "FROM page p, revision r, pagecontent c WHERE p.page_latest = r.rev_id " .
@@ -195,32 +196,4 @@ class SearchPostgres extends SearchDatabase {
                return true;
        }
 
-} ## end of the SearchPostgres class
-
-/**
- * @ingroup Search
- */
-class PostgresSearchResult extends SearchResult {
-       function __construct( $row ) {
-               parent::__construct( $row );
-               $this->score = $row->score;
-       }
-
-       function getScore() {
-               return $this->score;
-       }
-}
-
-/**
- * @ingroup Search
- */
-class PostgresSearchResultSet extends SqlSearchResultSet {
-       function next() {
-               $row = $this->resultSet->fetchObject();
-               if ( $row === false ) {
-                       return false;
-               } else {
-                       return new PostgresSearchResult( $row );
-               }
-       }
 }
index 56ae2ff..aeaba8d 100644 (file)
@@ -61,35 +61,6 @@ class SearchResult {
                return $result;
        }
 
-       /**
-        * Return a new SearchResult and initializes it with a row.
-        *
-        * @param object $row
-        * @return SearchResult
-        */
-       public static function newFromRow( $row ) {
-               $result = new self();
-               $result->initFromRow( $row );
-               return $result;
-       }
-
-       public function __construct( $row = null ) {
-               if ( !is_null( $row ) ) {
-                       // Backwards compatibility with pre-1.17 callers
-                       $this->initFromRow( $row );
-               }
-       }
-
-       /**
-        * Initialize from a database row. Makes a Title and passes that to
-        * initFromTitle.
-        *
-        * @param object $row
-        */
-       protected function initFromRow( $row ) {
-               $this->initFromTitle( Title::makeTitle( $row->page_namespace, $row->page_title ) );
-       }
-
        /**
         * Initialize from a Title and if possible initializes a corresponding
         * Revision and File.
@@ -142,13 +113,6 @@ class SearchResult {
                return $this->mImage;
        }
 
-       /**
-        * @return float|null If not supported
-        */
-       function getScore() {
-               return null;
-       }
-
        /**
         * Lazy initialization of article text from DB
         */
@@ -173,11 +137,16 @@ class SearchResult {
 
                // TODO: make highliter take a content object. Make ContentHandler a factory for SearchHighliter.
                list( $contextlines, $contextchars ) = SearchEngine::userHighlightPrefs();
+
                $h = new SearchHighlighter();
-               if ( $wgAdvancedSearchHighlighting ) {
-                       return $h->highlightText( $this->mText, $terms, $contextlines, $contextchars );
+               if ( count( $terms ) > 0 ) {
+                       if ( $wgAdvancedSearchHighlighting ) {
+                               return $h->highlightText( $this->mText, $terms, $contextlines, $contextchars );
+                       } else {
+                               return $h->highlightSimple( $this->mText, $terms, $contextlines, $contextchars );
+                       }
                } else {
-                       return $h->highlightSimple( $this->mText, $terms, $contextlines, $contextchars );
+                       return $h->highlightNone( $this->mText, $contextlines, $contextchars );
                }
        }
 
@@ -217,7 +186,7 @@ class SearchResult {
        }
 
        /**
-        * @return string timestamp
+        * @return string Timestamp
         */
        function getTimestamp() {
                if ( $this->mRevision ) {
@@ -244,13 +213,6 @@ class SearchResult {
                return strlen( $this->mText );
        }
 
-       /**
-        * @return bool If hit has related articles
-        */
-       function hasRelated() {
-               return false;
-       }
-
        /**
         * @return string Interwiki prefix of the title (return iw even if title is broken)
         */
index 698f93c..406d322 100644 (file)
@@ -161,7 +161,9 @@ class SqlSearchResultSet extends SearchResultSet {
                        return false;
                }
 
-               return SearchResult::newFromRow( $row );
+               return SearchResult::newFromTitle(
+                       Title::makeTitle( $row->page_namespace, $row->page_title )
+               );
        }
 
        function free() {
index 05d5ca0..eee6930 100644 (file)
@@ -38,6 +38,8 @@ class SearchSqlite extends SearchDatabase {
         * Parse the user's query and transform it into an SQL fragment which will
         * become part of a WHERE clause
         *
+        * @param string $filteredText
+        * @param bool $fulltext
         * @return string
         */
        function parseQuery( $filteredText, $fulltext ) {
index 4854bcb..9711f04 100644 (file)
@@ -215,7 +215,7 @@ class MediaWikiSite extends Site {
                        // Filter the substructure down to what we actually are using.
                        $collectedHits = array_filter(
                                array_values( $externalData['query'][$listId] ),
-                               function( $a ) use ( $fieldId, $pageTitle ) {
+                               function ( $a ) use ( $fieldId, $pageTitle ) {
                                        return $a[$fieldId] === $pageTitle;
                                }
                        );
index e3559f5..fafb14c 100644 (file)
@@ -700,7 +700,7 @@ class Site implements Serializable {
 }
 
 /**
- * @deprecated
+ * @deprecated since 1.21
  */
 class SiteObject extends Site {
 }
index dfe4ec5..2d9f22d 100644 (file)
@@ -277,7 +277,7 @@ class SiteList extends GenericArrayObject {
                $group = new self();
 
                /**
-                * @var \Site $site
+                * @var Site $site
                 */
                foreach ( $this as $site ) {
                        if ( $site->getGroup() === $groupName ) {
@@ -352,7 +352,7 @@ class SiteList extends GenericArrayObject {
 }
 
 /**
- * @deprecated
+ * @deprecated since 1.21
  */
 class SiteArray extends SiteList {
 }
index f382d98..6659407 100644 (file)
@@ -460,7 +460,7 @@ class SiteSQLStore implements SiteStore {
 }
 
 /**
- * @deprecated
+ * @deprecated since 1.21
  */
 class Sites extends SiteSQLStore {
 
@@ -468,7 +468,7 @@ class Sites extends SiteSQLStore {
         * Factory for creating new site objects.
         *
         * @since 1.21
-        * @deprecated
+        * @deprecated since 1.21
         *
         * @param string|bool $globalId
         *
@@ -485,7 +485,7 @@ class Sites extends SiteSQLStore {
        }
 
        /**
-        * @deprecated
+        * @deprecated since 1.21
         * @return SiteStore
         */
        public static function singleton() {
@@ -499,7 +499,7 @@ class Sites extends SiteSQLStore {
        }
 
        /**
-        * @deprecated
+        * @deprecated since 1.21
         * @param string $group
         * @return SiteList
         */
diff --git a/includes/skins/Skin.php b/includes/skins/Skin.php
new file mode 100644 (file)
index 0000000..7cabf50
--- /dev/null
@@ -0,0 +1,1620 @@
+<?php
+/**
+ * Base class for all skins.
+ *
+ * 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
+ */
+
+/**
+ * @defgroup Skins Skins
+ */
+
+/**
+ * The main skin class which provides methods and properties for all other skins.
+ *
+ * See docs/skin.txt for more information.
+ *
+ * @ingroup Skins
+ */
+abstract class Skin extends ContextSource {
+       protected $skinname = null;
+       protected $mRelevantTitle = null;
+       protected $mRelevantUser = null;
+
+       /**
+        * @var string Stylesheets set to use. Subdirectory in skins/ where various stylesheets are
+        *   located. Only needs to be set if you intend to use the getSkinStylePath() method.
+        */
+       public $stylename = null;
+
+       /**
+        * Fetch the set of available skins.
+        * @return array Associative array of strings
+        */
+       static function getSkinNames() {
+               return SkinFactory::getDefaultInstance()->getSkinNames();
+       }
+
+       /**
+        * Fetch the skinname messages for available skins.
+        * @return string[]
+        */
+       static function getSkinNameMessages() {
+               $messages = array();
+               foreach ( self::getSkinNames() as $skinKey => $skinName ) {
+                       $messages[] = "skinname-$skinKey";
+               }
+               return $messages;
+       }
+
+       /**
+        * Fetch the list of user-selectable skins in regards to $wgSkipSkins.
+        * Useful for Special:Preferences and other places where you
+        * only want to show skins users _can_ use.
+        * @return string[]
+        * @since 1.23
+        */
+       public static function getAllowedSkins() {
+               global $wgSkipSkins;
+
+               $allowedSkins = self::getSkinNames();
+
+               foreach ( $wgSkipSkins as $skip ) {
+                       unset( $allowedSkins[$skip] );
+               }
+
+               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.
+        *
+        * If a skin can't be found, it will fall back to the configured default ($wgDefaultSkin), or the
+        * hardcoded default ($wgFallbackSkin) if the default skin is unavailable too.
+        *
+        * @param string $key 'monobook', 'vector', etc.
+        * @return string
+        */
+       static function normalizeKey( $key ) {
+               global $wgDefaultSkin, $wgFallbackSkin;
+
+               $skinNames = Skin::getSkinNames();
+
+               // Make keys lowercase for case-insensitive matching.
+               $skinNames = array_change_key_case( $skinNames, CASE_LOWER );
+               $key = strtolower( $key );
+               $defaultSkin = strtolower( $wgDefaultSkin );
+               $fallbackSkin = strtolower( $wgFallbackSkin );
+
+               if ( $key == '' || $key == 'default' ) {
+                       // Don't return the default immediately;
+                       // in a misconfiguration we need to fall back.
+                       $key = $defaultSkin;
+               }
+
+               if ( isset( $skinNames[$key] ) ) {
+                       return $key;
+               }
+
+               // Older versions of the software used a numeric setting
+               // in the user preferences.
+               $fallback = array(
+                       0 => $defaultSkin,
+                       2 => 'cologneblue'
+               );
+
+               if ( isset( $fallback[$key] ) ) {
+                       $key = $fallback[$key];
+               }
+
+               if ( isset( $skinNames[$key] ) ) {
+                       return $key;
+               } elseif ( isset( $skinNames[$defaultSkin] ) ) {
+                       return $defaultSkin;
+               } else {
+                       return $fallbackSkin;
+               }
+       }
+
+       /**
+        * 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
+        */
+       public function getSkinName() {
+               return $this->skinname;
+       }
+
+       /**
+        * @param OutputPage $out
+        */
+       function initPage( OutputPage $out ) {
+               wfProfileIn( __METHOD__ );
+
+               $this->preloadExistence();
+
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Defines the ResourceLoader modules that should be added to the skin
+        * It is recommended that skins wishing to override call parent::getDefaultModules()
+        * and substitute out any modules they wish to change by using a key to look them up
+        * @return array Array of modules with helper keys for easy overriding
+        */
+       public function getDefaultModules() {
+               global $wgIncludeLegacyJavaScript, $wgPreloadJavaScriptMwUtil, $wgUseAjax,
+                       $wgAjaxWatch, $wgEnableAPI, $wgEnableWriteAPI;
+
+               $out = $this->getOutput();
+               $user = $out->getUser();
+               $modules = array(
+                       // modules that enhance the page content in some way
+                       'content' => array(
+                               'mediawiki.page.ready',
+                       ),
+                       // modules that exist for legacy reasons
+                       'legacy' => array(),
+                       // modules relating to search functionality
+                       'search' => array(),
+                       // modules relating to functionality relating to watching an article
+                       'watch' => array(),
+                       // modules which relate to the current users preferences
+                       'user' => array(),
+               );
+               if ( $wgIncludeLegacyJavaScript ) {
+                       $modules['legacy'][] = 'mediawiki.legacy.wikibits';
+               }
+
+               if ( $wgPreloadJavaScriptMwUtil ) {
+                       $modules['legacy'][] = 'mediawiki.util';
+               }
+
+               // Add various resources if required
+               if ( $wgUseAjax ) {
+                       $modules['legacy'][] = 'mediawiki.legacy.ajax';
+
+                       if ( $wgEnableAPI ) {
+                               if ( $wgEnableWriteAPI && $wgAjaxWatch && $user->isLoggedIn()
+                                       && $user->isAllowed( 'writeapi' )
+                               ) {
+                                       $modules['watch'][] = 'mediawiki.page.watch.ajax';
+                               }
+
+                               $modules['search'][] = 'mediawiki.searchSuggest';
+                       }
+               }
+
+               if ( $user->getBoolOption( 'editsectiononrightclick' ) ) {
+                       $modules['user'][] = 'mediawiki.action.view.rightClickEdit';
+               }
+
+               // Crazy edit-on-double-click stuff
+               if ( $out->isArticle() && $user->getOption( 'editondblclick' ) ) {
+                       $modules['user'][] = 'mediawiki.action.view.dblClickEdit';
+               }
+               return $modules;
+       }
+
+       /**
+        * Preload the existence of three commonly-requested pages in a single query
+        */
+       function preloadExistence() {
+               $user = $this->getUser();
+
+               // User/talk link
+               $titles = array( $user->getUserPage(), $user->getTalkPage() );
+
+               // Other tab link
+               if ( $this->getTitle()->isSpecialPage() ) {
+                       // nothing
+               } elseif ( $this->getTitle()->isTalkPage() ) {
+                       $titles[] = $this->getTitle()->getSubjectPage();
+               } else {
+                       $titles[] = $this->getTitle()->getTalkPage();
+               }
+
+               wfRunHooks( 'SkinPreloadExistence', array( &$titles, $this ) );
+
+               $lb = new LinkBatch( $titles );
+               $lb->setCaller( __METHOD__ );
+               $lb->execute();
+       }
+
+       /**
+        * Get the current revision ID
+        *
+        * @return int
+        */
+       public function getRevisionId() {
+               return $this->getOutput()->getRevisionId();
+       }
+
+       /**
+        * Whether the revision displayed is the latest revision of the page
+        *
+        * @return bool
+        */
+       public function isRevisionCurrent() {
+               $revID = $this->getRevisionId();
+               return $revID == 0 || $revID == $this->getTitle()->getLatestRevID();
+       }
+
+       /**
+        * Set the "relevant" title
+        * @see self::getRelevantTitle()
+        * @param Title $t
+        */
+       public function setRelevantTitle( $t ) {
+               $this->mRelevantTitle = $t;
+       }
+
+       /**
+        * Return the "relevant" title.
+        * A "relevant" title is not necessarily the actual title of the page.
+        * Special pages like Special:MovePage use set the page they are acting on
+        * as their "relevant" title, this allows the skin system to display things
+        * such as content tabs which belong to to that page instead of displaying
+        * a basic special page tab which has almost no meaning.
+        *
+        * @return Title
+        */
+       public function getRelevantTitle() {
+               if ( isset( $this->mRelevantTitle ) ) {
+                       return $this->mRelevantTitle;
+               }
+               return $this->getTitle();
+       }
+
+       /**
+        * Set the "relevant" user
+        * @see self::getRelevantUser()
+        * @param User $u
+        */
+       public function setRelevantUser( $u ) {
+               $this->mRelevantUser = $u;
+       }
+
+       /**
+        * Return the "relevant" user.
+        * A "relevant" user is similar to a relevant title. Special pages like
+        * Special:Contributions mark the user which they are relevant to so that
+        * things like the toolbox can display the information they usually are only
+        * able to display on a user's userpage and talkpage.
+        * @return User
+        */
+       public function getRelevantUser() {
+               if ( isset( $this->mRelevantUser ) ) {
+                       return $this->mRelevantUser;
+               }
+               $title = $this->getRelevantTitle();
+               if ( $title->hasSubjectNamespace( NS_USER ) ) {
+                       $rootUser = $title->getRootText();
+                       if ( User::isIP( $rootUser ) ) {
+                               $this->mRelevantUser = User::newFromName( $rootUser, false );
+                       } else {
+                               $user = User::newFromName( $rootUser, false );
+                               if ( $user && $user->isLoggedIn() ) {
+                                       $this->mRelevantUser = $user;
+                               }
+                       }
+                       return $this->mRelevantUser;
+               }
+               return null;
+       }
+
+       /**
+        * Outputs the HTML generated by other functions.
+        * @param OutputPage $out
+        */
+       abstract function outputPage( OutputPage $out = null );
+
+       /**
+        * @param array $data
+        * @return string
+        */
+       static function makeVariablesScript( $data ) {
+               if ( $data ) {
+                       return Html::inlineScript(
+                               ResourceLoader::makeLoaderConditionalScript( ResourceLoader::makeConfigSetScript( $data ) )
+                       );
+               } else {
+                       return '';
+               }
+       }
+
+       /**
+        * Get the query to generate a dynamic stylesheet
+        *
+        * @return array
+        */
+       public static function getDynamicStylesheetQuery() {
+               global $wgSquidMaxage;
+
+               return array(
+                               'action' => 'raw',
+                               'maxage' => $wgSquidMaxage,
+                               'usemsgcache' => 'yes',
+                               'ctype' => 'text/css',
+                               'smaxage' => $wgSquidMaxage,
+                       );
+       }
+
+       /**
+        * Add skin specific stylesheets
+        * Calling this method with an $out of anything but the same OutputPage
+        * inside ->getOutput() is deprecated. The $out arg is kept
+        * for compatibility purposes with skins.
+        * @param OutputPage $out
+        * @todo delete
+        */
+       abstract function setupSkinUserCss( OutputPage $out );
+
+       /**
+        * TODO: document
+        * @param Title $title
+        * @return string
+        */
+       function getPageClasses( $title ) {
+               $numeric = 'ns-' . $title->getNamespace();
+
+               if ( $title->isSpecialPage() ) {
+                       $type = 'ns-special';
+                       // bug 23315: provide a class based on the canonical special page name without subpages
+                       list( $canonicalName ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
+                       if ( $canonicalName ) {
+                               $type .= ' ' . Sanitizer::escapeClass( "mw-special-$canonicalName" );
+                       } else {
+                               $type .= ' mw-invalidspecialpage';
+                       }
+               } elseif ( $title->isTalkPage() ) {
+                       $type = 'ns-talk';
+               } else {
+                       $type = 'ns-subject';
+               }
+
+               $name = Sanitizer::escapeClass( 'page-' . $title->getPrefixedText() );
+
+               return "$numeric $type $name";
+       }
+
+       /**
+        * Return values for <html> element
+        * @return array Array of associative name-to-value elements for <html> element
+        */
+       public function getHtmlElementAttributes() {
+               $lang = $this->getLanguage();
+               return array(
+                       'lang' => $lang->getHtmlCode(),
+                       'dir' => $lang->getDir(),
+                       'class' => 'client-nojs',
+               );
+       }
+
+       /**
+        * This will be called by OutputPage::headElement when it is creating the
+        * "<body>" tag, skins can override it if they have a need to add in any
+        * body attributes or classes of their own.
+        * @param OutputPage $out
+        * @param array $bodyAttrs
+        */
+       function addToBodyAttributes( $out, &$bodyAttrs ) {
+               // does nothing by default
+       }
+
+       /**
+        * URL to the logo
+        * @return string
+        */
+       function getLogo() {
+               global $wgLogo;
+               return $wgLogo;
+       }
+
+       /**
+        * @return string
+        */
+       function getCategoryLinks() {
+               global $wgUseCategoryBrowser;
+
+               $out = $this->getOutput();
+               $allCats = $out->getCategoryLinks();
+
+               if ( !count( $allCats ) ) {
+                       return '';
+               }
+
+               $embed = "<li>";
+               $pop = "</li>";
+
+               $s = '';
+               $colon = $this->msg( 'colon-separator' )->escaped();
+
+               if ( !empty( $allCats['normal'] ) ) {
+                       $t = $embed . implode( "{$pop}{$embed}", $allCats['normal'] ) . $pop;
+
+                       $msg = $this->msg( 'pagecategories' )->numParams( count( $allCats['normal'] ) )->escaped();
+                       $linkPage = wfMessage( 'pagecategorieslink' )->inContentLanguage()->text();
+                       $s .= '<div id="mw-normal-catlinks" class="mw-normal-catlinks">' .
+                               Linker::link( Title::newFromText( $linkPage ), $msg )
+                               . $colon . '<ul>' . $t . '</ul>' . '</div>';
+               }
+
+               # Hidden categories
+               if ( isset( $allCats['hidden'] ) ) {
+                       if ( $this->getUser()->getBoolOption( 'showhiddencats' ) ) {
+                               $class = ' mw-hidden-cats-user-shown';
+                       } elseif ( $this->getTitle()->getNamespace() == NS_CATEGORY ) {
+                               $class = ' mw-hidden-cats-ns-shown';
+                       } else {
+                               $class = ' mw-hidden-cats-hidden';
+                       }
+
+                       $s .= "<div id=\"mw-hidden-catlinks\" class=\"mw-hidden-catlinks$class\">" .
+                               $this->msg( 'hidden-categories' )->numParams( count( $allCats['hidden'] ) )->escaped() .
+                               $colon . '<ul>' . $embed . implode( "{$pop}{$embed}", $allCats['hidden'] ) . $pop . '</ul>' .
+                               '</div>';
+               }
+
+               # optional 'dmoz-like' category browser. Will be shown under the list
+               # of categories an article belong to
+               if ( $wgUseCategoryBrowser ) {
+                       $s .= '<br /><hr />';
+
+                       # get a big array of the parents tree
+                       $parenttree = $this->getTitle()->getParentCategoryTree();
+                       # Skin object passed by reference cause it can not be
+                       # accessed under the method subfunction drawCategoryBrowser
+                       $tempout = explode( "\n", $this->drawCategoryBrowser( $parenttree ) );
+                       # Clean out bogus first entry and sort them
+                       unset( $tempout[0] );
+                       asort( $tempout );
+                       # Output one per line
+                       $s .= implode( "<br />\n", $tempout );
+               }
+
+               return $s;
+       }
+
+       /**
+        * Render the array as a series of links.
+        * @param array $tree Categories tree returned by Title::getParentCategoryTree
+        * @return string Separated by &gt;, terminate with "\n"
+        */
+       function drawCategoryBrowser( $tree ) {
+               $return = '';
+
+               foreach ( $tree as $element => $parent ) {
+                       if ( empty( $parent ) ) {
+                               # element start a new list
+                               $return .= "\n";
+                       } else {
+                               # grab the others elements
+                               $return .= $this->drawCategoryBrowser( $parent ) . ' &gt; ';
+                       }
+
+                       # add our current element to the list
+                       $eltitle = Title::newFromText( $element );
+                       $return .= Linker::link( $eltitle, htmlspecialchars( $eltitle->getText() ) );
+               }
+
+               return $return;
+       }
+
+       /**
+        * @return string
+        */
+       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;
+
+               if ( empty( $allCats['normal'] ) && !( !empty( $allCats['hidden'] ) && $showHidden ) ) {
+                       $classes .= ' catlinks-allhidden';
+               }
+
+               return "<div id='catlinks' class='$classes'>{$catlinks}</div>";
+       }
+
+       /**
+        * This runs a hook to allow extensions placing their stuff after content
+        * and article metadata (e.g. categories).
+        * Note: This function has nothing to do with afterContent().
+        *
+        * This hook is placed here in order to allow using the same hook for all
+        * skins, both the SkinTemplate based ones and the older ones, which directly
+        * use this class to get their data.
+        *
+        * The output of this function gets processed in SkinTemplate::outputPage() for
+        * the SkinTemplate based skins, all other skins should directly echo it.
+        *
+        * @return string Empty by default, if not changed by any hook function.
+        */
+       protected function afterContentHook() {
+               $data = '';
+
+               if ( wfRunHooks( 'SkinAfterContent', array( &$data, $this ) ) ) {
+                       // adding just some spaces shouldn't toggle the output
+                       // of the whole <div/>, so we use trim() here
+                       if ( trim( $data ) != '' ) {
+                               // Doing this here instead of in the skins to
+                               // ensure that the div has the same ID in all
+                               // skins
+                               $data = "<div id='mw-data-after-content'>\n" .
+                                       "\t$data\n" .
+                                       "</div>\n";
+                       }
+               } else {
+                       wfDebug( "Hook SkinAfterContent changed output processing.\n" );
+               }
+
+               return $data;
+       }
+
+       /**
+        * Generate debug data HTML for displaying at the bottom of the main content
+        * area.
+        * @return string HTML containing debug data, if enabled (otherwise empty).
+        */
+       protected function generateDebugHTML() {
+               return MWDebug::getHTMLDebugLog();
+       }
+
+       /**
+        * This gets called shortly before the "</body>" tag.
+        *
+        * @return string HTML-wrapped JS code to be put before "</body>"
+        */
+       function bottomScripts() {
+               // TODO and the suckage continues. This function is really just a wrapper around
+               // OutputPage::getBottomScripts() which takes a Skin param. This should be cleaned
+               // up at some point
+               $bottomScriptText = $this->getOutput()->getBottomScripts();
+               wfRunHooks( 'SkinAfterBottomScripts', array( $this, &$bottomScriptText ) );
+
+               return $bottomScriptText;
+       }
+
+       /**
+        * Text with the permalink to the source page,
+        * usually shown on the footer of a printed page
+        *
+        * @return string HTML text with an URL
+        */
+       function printSource() {
+               $oldid = $this->getRevisionId();
+               if ( $oldid ) {
+                       $canonicalUrl = $this->getTitle()->getCanonicalURL( 'oldid=' . $oldid );
+                       $url = htmlspecialchars( wfExpandIRI( $canonicalUrl ) );
+               } else {
+                       // oldid not available for non existing pages
+                       $url = htmlspecialchars( wfExpandIRI( $this->getTitle()->getCanonicalURL() ) );
+               }
+
+               return $this->msg( 'retrievedfrom', '<a dir="ltr" href="' . $url
+                       . '">' . $url . '</a>' )->text();
+       }
+
+       /**
+        * @return string
+        */
+       function getUndeleteLink() {
+               $action = $this->getRequest()->getVal( 'action', 'view' );
+
+               if ( $this->getUser()->isAllowed( 'deletedhistory' ) &&
+                       ( $this->getTitle()->getArticleID() == 0 || $action == 'history' ) ) {
+                       $n = $this->getTitle()->isDeleted();
+
+                       if ( $n ) {
+                               if ( $this->getUser()->isAllowed( 'undelete' ) ) {
+                                       $msg = 'thisisdeleted';
+                               } else {
+                                       $msg = 'viewdeleted';
+                               }
+
+                               return $this->msg( $msg )->rawParams(
+                                       Linker::linkKnown(
+                                               SpecialPage::getTitleFor( 'Undelete', $this->getTitle()->getPrefixedDBkey() ),
+                                               $this->msg( 'restorelink' )->numParams( $n )->escaped() )
+                                       )->text();
+                       }
+               }
+
+               return '';
+       }
+
+       /**
+        * @return string
+        */
+       function subPageSubtitle() {
+               $out = $this->getOutput();
+               $subpages = '';
+
+               if ( !wfRunHooks( 'SkinSubPageSubtitle', array( &$subpages, $this, $out ) ) ) {
+                       return $subpages;
+               }
+
+               if ( $out->isArticle() && MWNamespace::hasSubpages( $out->getTitle()->getNamespace() ) ) {
+                       $ptext = $this->getTitle()->getPrefixedText();
+                       if ( preg_match( '/\//', $ptext ) ) {
+                               $links = explode( '/', $ptext );
+                               array_pop( $links );
+                               $c = 0;
+                               $growinglink = '';
+                               $display = '';
+                               $lang = $this->getLanguage();
+
+                               foreach ( $links as $link ) {
+                                       $growinglink .= $link;
+                                       $display .= $link;
+                                       $linkObj = Title::newFromText( $growinglink );
+
+                                       if ( is_object( $linkObj ) && $linkObj->isKnown() ) {
+                                               $getlink = Linker::linkKnown(
+                                                       $linkObj,
+                                                       htmlspecialchars( $display )
+                                               );
+
+                                               $c++;
+
+                                               if ( $c > 1 ) {
+                                                       $subpages .= $lang->getDirMarkEntity() . $this->msg( 'pipe-separator' )->escaped();
+                                               } else {
+                                                       $subpages .= '&lt; ';
+                                               }
+
+                                               $subpages .= $getlink;
+                                               $display = '';
+                                       } else {
+                                               $display .= '/';
+                                       }
+                                       $growinglink .= '/';
+                               }
+                       }
+               }
+
+               return $subpages;
+       }
+
+       /**
+        * Returns true if the IP should be shown in the header
+        * @return bool
+        */
+       function showIPinHeader() {
+               global $wgShowIPinHeader;
+               return $wgShowIPinHeader && session_id() != '';
+       }
+
+       /**
+        * @return string
+        */
+       function getSearchLink() {
+               $searchPage = SpecialPage::getTitleFor( 'Search' );
+               return $searchPage->getLocalURL();
+       }
+
+       /**
+        * @return string
+        */
+       function escapeSearchLink() {
+               return htmlspecialchars( $this->getSearchLink() );
+       }
+
+       /**
+        * @param string $type
+        * @return string
+        */
+       function getCopyright( $type = 'detect' ) {
+               global $wgRightsPage, $wgRightsUrl, $wgRightsText;
+
+               if ( $type == 'detect' ) {
+                       if ( !$this->isRevisionCurrent()
+                               && !$this->msg( 'history_copyright' )->inContentLanguage()->isDisabled()
+                       ) {
+                               $type = 'history';
+                       } else {
+                               $type = 'normal';
+                       }
+               }
+
+               if ( $type == 'history' ) {
+                       $msg = 'history_copyright';
+               } else {
+                       $msg = 'copyright';
+               }
+
+               if ( $wgRightsPage ) {
+                       $title = Title::newFromText( $wgRightsPage );
+                       $link = Linker::linkKnown( $title, $wgRightsText );
+               } elseif ( $wgRightsUrl ) {
+                       $link = Linker::makeExternalLink( $wgRightsUrl, $wgRightsText );
+               } elseif ( $wgRightsText ) {
+                       $link = $wgRightsText;
+               } else {
+                       # Give up now
+                       return '';
+               }
+
+               // Allow for site and per-namespace customization of copyright notice.
+               // @todo Remove deprecated $forContent param from hook handlers and then remove here.
+               $forContent = true;
+
+               wfRunHooks(
+                       'SkinCopyrightFooter',
+                       array( $this->getTitle(), $type, &$msg, &$link, &$forContent )
+               );
+
+               return $this->msg( $msg )->rawParams( $link )->text();
+       }
+
+       /**
+        * @return null|string
+        */
+       function getCopyrightIcon() {
+               global $wgRightsUrl, $wgRightsText, $wgRightsIcon, $wgCopyrightIcon;
+
+               $out = '';
+
+               if ( $wgCopyrightIcon ) {
+                       $out = $wgCopyrightIcon;
+               } elseif ( $wgRightsIcon ) {
+                       $icon = htmlspecialchars( $wgRightsIcon );
+
+                       if ( $wgRightsUrl ) {
+                               $url = htmlspecialchars( $wgRightsUrl );
+                               $out .= '<a href="' . $url . '">';
+                       }
+
+                       $text = htmlspecialchars( $wgRightsText );
+                       $out .= "<img src=\"$icon\" alt=\"$text\" width=\"88\" height=\"31\" />";
+
+                       if ( $wgRightsUrl ) {
+                               $out .= '</a>';
+                       }
+               }
+
+               return $out;
+       }
+
+       /**
+        * Gets the powered by MediaWiki icon.
+        * @return string
+        */
+       function getPoweredBy() {
+               global $wgScriptPath;
+
+               $url = htmlspecialchars( "$wgScriptPath/assets/poweredby_mediawiki_88x31.png" );
+               $text = '<a href="//www.mediawiki.org/"><img src="' . $url
+                       . '" height="31" width="88" alt="Powered by MediaWiki" /></a>';
+               wfRunHooks( 'SkinGetPoweredBy', array( &$text, $this ) );
+               return $text;
+       }
+
+       /**
+        * Get the timestamp of the latest revision, formatted in user language
+        *
+        * @return string
+        */
+       protected function lastModified() {
+               $timestamp = $this->getOutput()->getRevisionTimestamp();
+
+               # No cached timestamp, load it from the database
+               if ( $timestamp === null ) {
+                       $timestamp = Revision::getTimestampFromId( $this->getTitle(), $this->getRevisionId() );
+               }
+
+               if ( $timestamp ) {
+                       $d = $this->getLanguage()->userDate( $timestamp, $this->getUser() );
+                       $t = $this->getLanguage()->userTime( $timestamp, $this->getUser() );
+                       $s = ' ' . $this->msg( 'lastmodifiedat', $d, $t )->text();
+               } else {
+                       $s = '';
+               }
+
+               if ( wfGetLB()->getLaggedSlaveMode() ) {
+                       $s .= ' <strong>' . $this->msg( 'laggedslavemode' )->text() . '</strong>';
+               }
+
+               return $s;
+       }
+
+       /**
+        * @param string $align
+        * @return string
+        */
+       function logoText( $align = '' ) {
+               if ( $align != '' ) {
+                       $a = " style='float: {$align};'";
+               } else {
+                       $a = '';
+               }
+
+               $mp = $this->msg( 'mainpage' )->escaped();
+               $mptitle = Title::newMainPage();
+               $url = ( is_object( $mptitle ) ? htmlspecialchars( $mptitle->getLocalURL() ) : '' );
+
+               $logourl = $this->getLogo();
+               $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
+
+               return $s;
+       }
+
+       /**
+        * Renders a $wgFooterIcons icon according to the method's arguments
+        * @param array $icon The icon to build the html for, see $wgFooterIcons
+        *   for the format of this array.
+        * @param bool|string $withImage Whether to use the icon's image or output
+        *   a text-only footericon.
+        * @return string HTML
+        */
+       function makeFooterIcon( $icon, $withImage = 'withImage' ) {
+               if ( is_string( $icon ) ) {
+                       $html = $icon;
+               } else { // Assuming array
+                       $url = isset( $icon["url"] ) ? $icon["url"] : null;
+                       unset( $icon["url"] );
+                       if ( isset( $icon["src"] ) && $withImage === 'withImage' ) {
+                               // do this the lazy way, just pass icon data as an attribute array
+                               $html = Html::element( 'img', $icon );
+                       } else {
+                               $html = htmlspecialchars( $icon["alt"] );
+                       }
+                       if ( $url ) {
+                               $html = Html::rawElement( 'a', array( "href" => $url ), $html );
+                       }
+               }
+               return $html;
+       }
+
+       /**
+        * Gets the link to the wiki's main page.
+        * @return string
+        */
+       function mainPageLink() {
+               $s = Linker::linkKnown(
+                       Title::newMainPage(),
+                       $this->msg( 'mainpage' )->escaped()
+               );
+
+               return $s;
+       }
+
+       /**
+        * Returns an HTML link for use in the footer
+        * @param string $desc The i18n message key for the link text
+        * @param string $page The i18n message key for the page to link to
+        * @return string HTML anchor
+        */
+       public function footerLink( $desc, $page ) {
+               // if the link description has been set to "-" in the default language,
+               if ( $this->msg( $desc )->inContentLanguage()->isDisabled() ) {
+                       // then it is disabled, for all languages.
+                       return '';
+               } else {
+                       // Otherwise, we display the link for the user, described in their
+                       // language (which may or may not be the same as the default language),
+                       // but we make the link target be the one site-wide page.
+                       $title = Title::newFromText( $this->msg( $page )->inContentLanguage()->text() );
+
+                       return Linker::linkKnown(
+                               $title,
+                               $this->msg( $desc )->escaped()
+                       );
+               }
+       }
+
+       /**
+        * Gets the link to the wiki's privacy policy page.
+        * @return string HTML
+        */
+       function privacyLink() {
+               return $this->footerLink( 'privacy', 'privacypage' );
+       }
+
+       /**
+        * Gets the link to the wiki's about page.
+        * @return string HTML
+        */
+       function aboutLink() {
+               return $this->footerLink( 'aboutsite', 'aboutpage' );
+       }
+
+       /**
+        * Gets the link to the wiki's general disclaimers page.
+        * @return string HTML
+        */
+       function disclaimerLink() {
+               return $this->footerLink( 'disclaimers', 'disclaimerpage' );
+       }
+
+       /**
+        * Return URL options for the 'edit page' link.
+        * This may include an 'oldid' specifier, if the current page view is such.
+        *
+        * @return array
+        * @private
+        */
+       function editUrlOptions() {
+               $options = array( 'action' => 'edit' );
+
+               if ( !$this->isRevisionCurrent() ) {
+                       $options['oldid'] = intval( $this->getRevisionId() );
+               }
+
+               return $options;
+       }
+
+       /**
+        * @param User|int $id
+        * @return bool
+        */
+       function showEmailUser( $id ) {
+               if ( $id instanceof User ) {
+                       $targetUser = $id;
+               } else {
+                       $targetUser = User::newFromId( $id );
+               }
+
+               # The sending user must have a confirmed email address and the target
+               # user must have a confirmed email address and allow emails from users.
+               return $this->getUser()->canSendEmail() &&
+                       $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
+        * and includes the style version inside of the url.
+        *
+        * Requires $stylename to be set, otherwise throws MWException.
+        *
+        * @param string $name The name or path of a skin resource file
+        * @return string The fully resolved style path url including styleversion
+        */
+       function getSkinStylePath( $name ) {
+               global $wgStylePath, $wgStyleVersion;
+
+               if ( $this->stylename === null ) {
+                       $class = get_class( $this );
+                       throw new MWException( "$class::\$stylename must be set to use getSkinStylePath()" );
+               }
+
+               return "$wgStylePath/{$this->stylename}/$name?$wgStyleVersion";
+       }
+
+       /* these are used extensively in SkinTemplate, but also some other places */
+
+       /**
+        * @param string $urlaction
+        * @return string
+        */
+       static function makeMainPageUrl( $urlaction = '' ) {
+               $title = Title::newMainPage();
+               self::checkTitle( $title, '' );
+
+               return $title->getLocalURL( $urlaction );
+       }
+
+       /**
+        * Make a URL for a Special Page using the given query and protocol.
+        *
+        * If $proto is set to null, make a local URL. Otherwise, make a full
+        * URL with the protocol specified.
+        *
+        * @param string $name Name of the Special page
+        * @param string $urlaction Query to append
+        * @param string|null $proto Protocol to use or null for a local URL
+        * @return string
+        */
+       static function makeSpecialUrl( $name, $urlaction = '', $proto = null ) {
+               $title = SpecialPage::getSafeTitleFor( $name );
+               if ( is_null( $proto ) ) {
+                       return $title->getLocalURL( $urlaction );
+               } else {
+                       return $title->getFullURL( $urlaction, false, $proto );
+               }
+       }
+
+       /**
+        * @param string $name
+        * @param string $subpage
+        * @param string $urlaction
+        * @return string
+        */
+       static function makeSpecialUrlSubpage( $name, $subpage, $urlaction = '' ) {
+               $title = SpecialPage::getSafeTitleFor( $name, $subpage );
+               return $title->getLocalURL( $urlaction );
+       }
+
+       /**
+        * @param string $name
+        * @param string $urlaction
+        * @return string
+        */
+       static function makeI18nUrl( $name, $urlaction = '' ) {
+               $title = Title::newFromText( wfMessage( $name )->inContentLanguage()->text() );
+               self::checkTitle( $title, $name );
+               return $title->getLocalURL( $urlaction );
+       }
+
+       /**
+        * @param string $name
+        * @param string $urlaction
+        * @return string
+        */
+       static function makeUrl( $name, $urlaction = '' ) {
+               $title = Title::newFromText( $name );
+               self::checkTitle( $title, $name );
+
+               return $title->getLocalURL( $urlaction );
+       }
+
+       /**
+        * If url string starts with http, consider as external URL, else
+        * internal
+        * @param string $name
+        * @return string URL
+        */
+       static function makeInternalOrExternalUrl( $name ) {
+               if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $name ) ) {
+                       return $name;
+               } else {
+                       return self::makeUrl( $name );
+               }
+       }
+
+       /**
+        * this can be passed the NS number as defined in Language.php
+        * @param string $name
+        * @param string $urlaction
+        * @param int $namespace
+        * @return string
+        */
+       static function makeNSUrl( $name, $urlaction = '', $namespace = NS_MAIN ) {
+               $title = Title::makeTitleSafe( $namespace, $name );
+               self::checkTitle( $title, $name );
+
+               return $title->getLocalURL( $urlaction );
+       }
+
+       /**
+        * these return an array with the 'href' and boolean 'exists'
+        * @param string $name
+        * @param string $urlaction
+        * @return array
+        */
+       static function makeUrlDetails( $name, $urlaction = '' ) {
+               $title = Title::newFromText( $name );
+               self::checkTitle( $title, $name );
+
+               return array(
+                       'href' => $title->getLocalURL( $urlaction ),
+                       'exists' => $title->getArticleID() != 0,
+               );
+       }
+
+       /**
+        * Make URL details where the article exists (or at least it's convenient to think so)
+        * @param string $name Article name
+        * @param string $urlaction
+        * @return array
+        */
+       static function makeKnownUrlDetails( $name, $urlaction = '' ) {
+               $title = Title::newFromText( $name );
+               self::checkTitle( $title, $name );
+
+               return array(
+                       'href' => $title->getLocalURL( $urlaction ),
+                       'exists' => true
+               );
+       }
+
+       /**
+        * make sure we have some title to operate on
+        *
+        * @param Title $title
+        * @param string $name
+        */
+       static function checkTitle( &$title, $name ) {
+               if ( !is_object( $title ) ) {
+                       $title = Title::newFromText( $name );
+                       if ( !is_object( $title ) ) {
+                               $title = Title::newFromText( '--error: link target missing--' );
+                       }
+               }
+       }
+
+       /**
+        * Build an array that represents the sidebar(s), the navigation bar among them.
+        *
+        * BaseTemplate::getSidebar can be used to simplify the format and id generation in new skins.
+        *
+        * The format of the returned array is array( heading => content, ... ), where:
+        * - heading is the heading of a navigation portlet. It is either:
+        *   - magic string to be handled by the skins ('SEARCH' / 'LANGUAGES' / 'TOOLBOX' / ...)
+        *   - a message name (e.g. 'navigation'), the message should be HTML-escaped by the skin
+        *   - plain text, which should be HTML-escaped by the skin
+        * - content is the contents of the portlet. It is either:
+        *   - HTML text (<ul><li>...</li>...</ul>)
+        *   - array of link data in a format accepted by BaseTemplate::makeListItem()
+        *   - (for a magic string as a key, any value)
+        *
+        * Note that extensions can control the sidebar contents using the SkinBuildSidebar hook
+        * and can technically insert anything in here; skin creators are expected to handle
+        * values described above.
+        *
+        * @return array
+        */
+       function buildSidebar() {
+               global $wgMemc, $wgEnableSidebarCache, $wgSidebarCacheExpiry;
+               wfProfileIn( __METHOD__ );
+
+               $key = wfMemcKey( 'sidebar', $this->getLanguage()->getCode() );
+
+               if ( $wgEnableSidebarCache ) {
+                       $cachedsidebar = $wgMemc->get( $key );
+                       if ( $cachedsidebar ) {
+                               wfRunHooks( 'SidebarBeforeOutput', array( $this, &$cachedsidebar ) );
+
+                               wfProfileOut( __METHOD__ );
+                               return $cachedsidebar;
+                       }
+               }
+
+               $bar = array();
+               $this->addToSidebar( $bar, 'sidebar' );
+
+               wfRunHooks( 'SkinBuildSidebar', array( $this, &$bar ) );
+               if ( $wgEnableSidebarCache ) {
+                       $wgMemc->set( $key, $bar, $wgSidebarCacheExpiry );
+               }
+
+               wfRunHooks( 'SidebarBeforeOutput', array( $this, &$bar ) );
+
+               wfProfileOut( __METHOD__ );
+               return $bar;
+       }
+
+       /**
+        * Add content from a sidebar system message
+        * Currently only used for MediaWiki:Sidebar (but may be used by Extensions)
+        *
+        * This is just a wrapper around addToSidebarPlain() for backwards compatibility
+        *
+        * @param array $bar
+        * @param string $message
+        */
+       function addToSidebar( &$bar, $message ) {
+               $this->addToSidebarPlain( $bar, wfMessage( $message )->inContentLanguage()->plain() );
+       }
+
+       /**
+        * Add content from plain text
+        * @since 1.17
+        * @param array $bar
+        * @param string $text
+        * @return array
+        */
+       function addToSidebarPlain( &$bar, $text ) {
+               $lines = explode( "\n", $text );
+
+               $heading = '';
+
+               foreach ( $lines as $line ) {
+                       if ( strpos( $line, '*' ) !== 0 ) {
+                               continue;
+                       }
+                       $line = rtrim( $line, "\r" ); // for Windows compat
+
+                       if ( strpos( $line, '**' ) !== 0 ) {
+                               $heading = trim( $line, '* ' );
+                               if ( !array_key_exists( $heading, $bar ) ) {
+                                       $bar[$heading] = array();
+                               }
+                       } else {
+                               $line = trim( $line, '* ' );
+
+                               if ( strpos( $line, '|' ) !== false ) { // sanity check
+                                       $line = MessageCache::singleton()->transform( $line, false, null, $this->getTitle() );
+                                       $line = array_map( 'trim', explode( '|', $line, 2 ) );
+                                       if ( count( $line ) !== 2 ) {
+                                               // Second sanity check, could be hit by people doing
+                                               // funky stuff with parserfuncs... (bug 33321)
+                                               continue;
+                                       }
+
+                                       $extraAttribs = array();
+
+                                       $msgLink = $this->msg( $line[0] )->inContentLanguage();
+                                       if ( $msgLink->exists() ) {
+                                               $link = $msgLink->text();
+                                               if ( $link == '-' ) {
+                                                       continue;
+                                               }
+                                       } else {
+                                               $link = $line[0];
+                                       }
+                                       $msgText = $this->msg( $line[1] );
+                                       if ( $msgText->exists() ) {
+                                               $text = $msgText->text();
+                                       } else {
+                                               $text = $line[1];
+                                       }
+
+                                       if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $link ) ) {
+                                               $href = $link;
+
+                                               // Parser::getExternalLinkAttribs won't work here because of the Namespace things
+                                               global $wgNoFollowLinks, $wgNoFollowDomainExceptions;
+                                               if ( $wgNoFollowLinks && !wfMatchesDomainList( $href, $wgNoFollowDomainExceptions ) ) {
+                                                       $extraAttribs['rel'] = 'nofollow';
+                                               }
+
+                                               global $wgExternalLinkTarget;
+                                               if ( $wgExternalLinkTarget ) {
+                                                       $extraAttribs['target'] = $wgExternalLinkTarget;
+                                               }
+                                       } else {
+                                               $title = Title::newFromText( $link );
+
+                                               if ( $title ) {
+                                                       $title = $title->fixSpecialName();
+                                                       $href = $title->getLinkURL();
+                                               } else {
+                                                       $href = 'INVALID-TITLE';
+                                               }
+                                       }
+
+                                       $bar[$heading][] = array_merge( array(
+                                               'text' => $text,
+                                               'href' => $href,
+                                               'id' => 'n-' . Sanitizer::escapeId( strtr( $line[1], ' ', '-' ), 'noninitial' ),
+                                               'active' => false
+                                       ), $extraAttribs );
+                               } else {
+                                       continue;
+                               }
+                       }
+               }
+
+               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)
+        * @return string
+        */
+       function getNewtalks() {
+
+               $newMessagesAlert = '';
+               $user = $this->getUser();
+               $newtalks = $user->getNewMessageLinks();
+               $out = $this->getOutput();
+
+               // Allow extensions to disable or modify the new messages alert
+               if ( !wfRunHooks( 'GetNewMessagesAlert', array( &$newMessagesAlert, $newtalks, $user, $out ) ) ) {
+                       return '';
+               }
+               if ( $newMessagesAlert ) {
+                       return $newMessagesAlert;
+               }
+
+               if ( count( $newtalks ) == 1 && $newtalks[0]['wiki'] === wfWikiID() ) {
+                       $uTalkTitle = $user->getTalkPage();
+                       $lastSeenRev = isset( $newtalks[0]['rev'] ) ? $newtalks[0]['rev'] : null;
+                       $nofAuthors = 0;
+                       if ( $lastSeenRev !== null ) {
+                               $plural = true; // Default if we have a last seen revision: if unknown, use plural
+                               $latestRev = Revision::newFromTitle( $uTalkTitle, false, Revision::READ_NORMAL );
+                               if ( $latestRev !== null ) {
+                                       // Singular if only 1 unseen revision, plural if several unseen revisions.
+                                       $plural = $latestRev->getParentId() !== $lastSeenRev->getId();
+                                       $nofAuthors = $uTalkTitle->countAuthorsBetween(
+                                               $lastSeenRev, $latestRev, 10, 'include_new' );
+                               }
+                       } else {
+                               // Singular if no revision -> diff link will show latest change only in any case
+                               $plural = false;
+                       }
+                       $plural = $plural ? 999 : 1;
+                       // 999 signifies "more than one revision". We don't know how many, and even if we did,
+                       // the number of revisions or authors is not necessarily the same as the number of
+                       // "messages".
+                       $newMessagesLink = Linker::linkKnown(
+                               $uTalkTitle,
+                               $this->msg( 'newmessageslinkplural' )->params( $plural )->escaped(),
+                               array(),
+                               array( 'redirect' => 'no' )
+                       );
+
+                       $newMessagesDiffLink = Linker::linkKnown(
+                               $uTalkTitle,
+                               $this->msg( 'newmessagesdifflinkplural' )->params( $plural )->escaped(),
+                               array(),
+                               $lastSeenRev !== null
+                                       ? array( 'oldid' => $lastSeenRev->getId(), 'diff' => 'cur' )
+                                       : array( 'diff' => 'cur' )
+                       );
+
+                       if ( $nofAuthors >= 1 && $nofAuthors <= 10 ) {
+                               $newMessagesAlert = $this->msg(
+                                       'youhavenewmessagesfromusers',
+                                       $newMessagesLink,
+                                       $newMessagesDiffLink
+                               )->numParams( $nofAuthors, $plural );
+                       } else {
+                               // $nofAuthors === 11 signifies "11 or more" ("more than 10")
+                               $newMessagesAlert = $this->msg(
+                                       $nofAuthors > 10 ? 'youhavenewmessagesmanyusers' : 'youhavenewmessages',
+                                       $newMessagesLink,
+                                       $newMessagesDiffLink
+                               )->numParams( $plural );
+                       }
+                       $newMessagesAlert = $newMessagesAlert->text();
+                       # Disable Squid cache
+                       $out->setSquidMaxage( 0 );
+               } elseif ( count( $newtalks ) ) {
+                       $sep = $this->msg( 'newtalkseparator' )->escaped();
+                       $msgs = array();
+
+                       foreach ( $newtalks as $newtalk ) {
+                               $msgs[] = Xml::element(
+                                       'a',
+                                       array( 'href' => $newtalk['link'] ), $newtalk['wiki']
+                               );
+                       }
+                       $parts = implode( $sep, $msgs );
+                       $newMessagesAlert = $this->msg( 'youhavenewmessagesmulti' )->rawParams( $parts )->escaped();
+                       $out->setSquidMaxage( 0 );
+               }
+
+               return $newMessagesAlert;
+       }
+
+       /**
+        * Get a cached notice
+        *
+        * @param string $name Message name, or 'default' for $wgSiteNotice
+        * @return string HTML fragment
+        */
+       private function getCachedNotice( $name ) {
+               global $wgRenderHashAppend, $parserMemc, $wgContLang;
+
+               wfProfileIn( __METHOD__ );
+
+               $needParse = false;
+
+               if ( $name === 'default' ) {
+                       // special case
+                       global $wgSiteNotice;
+                       $notice = $wgSiteNotice;
+                       if ( empty( $notice ) ) {
+                               wfProfileOut( __METHOD__ );
+                               return false;
+                       }
+               } else {
+                       $msg = $this->msg( $name )->inContentLanguage();
+                       if ( $msg->isDisabled() ) {
+                               wfProfileOut( __METHOD__ );
+                               return false;
+                       }
+                       $notice = $msg->plain();
+               }
+
+               // Use the extra hash appender to let eg SSL variants separately cache.
+               $key = wfMemcKey( $name . $wgRenderHashAppend );
+               $cachedNotice = $parserMemc->get( $key );
+               if ( is_array( $cachedNotice ) ) {
+                       if ( md5( $notice ) == $cachedNotice['hash'] ) {
+                               $notice = $cachedNotice['html'];
+                       } else {
+                               $needParse = true;
+                       }
+               } else {
+                       $needParse = true;
+               }
+
+               if ( $needParse ) {
+                       $parsed = $this->getOutput()->parse( $notice );
+                       $parserMemc->set( $key, array( 'html' => $parsed, 'hash' => md5( $notice ) ), 600 );
+                       $notice = $parsed;
+               }
+
+               $notice = Html::rawElement( 'div', array( 'id' => 'localNotice',
+                       'lang' => $wgContLang->getHtmlCode(), 'dir' => $wgContLang->getDir() ), $notice );
+               wfProfileOut( __METHOD__ );
+               return $notice;
+       }
+
+       /**
+        * Get a notice based on page's namespace
+        *
+        * @return string HTML fragment
+        */
+       function getNamespaceNotice() {
+               wfProfileIn( __METHOD__ );
+
+               $key = 'namespacenotice-' . $this->getTitle()->getNsText();
+               $namespaceNotice = $this->getCachedNotice( $key );
+               if ( $namespaceNotice && substr( $namespaceNotice, 0, 7 ) != '<p>&lt;' ) {
+                       $namespaceNotice = '<div id="namespacebanner">' . $namespaceNotice . '</div>';
+               } else {
+                       $namespaceNotice = '';
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $namespaceNotice;
+       }
+
+       /**
+        * Get the site notice
+        *
+        * @return string HTML fragment
+        */
+       function getSiteNotice() {
+               wfProfileIn( __METHOD__ );
+               $siteNotice = '';
+
+               if ( wfRunHooks( 'SiteNoticeBefore', array( &$siteNotice, $this ) ) ) {
+                       if ( is_object( $this->getUser() ) && $this->getUser()->isLoggedIn() ) {
+                               $siteNotice = $this->getCachedNotice( 'sitenotice' );
+                       } else {
+                               $anonNotice = $this->getCachedNotice( 'anonnotice' );
+                               if ( !$anonNotice ) {
+                                       $siteNotice = $this->getCachedNotice( 'sitenotice' );
+                               } else {
+                                       $siteNotice = $anonNotice;
+                               }
+                       }
+                       if ( !$siteNotice ) {
+                               $siteNotice = $this->getCachedNotice( 'default' );
+                       }
+               }
+
+               wfRunHooks( 'SiteNoticeAfter', array( &$siteNotice, $this ) );
+               wfProfileOut( __METHOD__ );
+               return $siteNotice;
+       }
+
+       /**
+        * Create a section edit link.  This supersedes editSectionLink() and
+        * editSectionLinkForOther().
+        *
+        * @param Title $nt The title being linked to (may not be the same as
+        *   the current page, if the section is included from a template)
+        * @param string $section The designation of the section being pointed to,
+        *   to be included in the link, like "&section=$section"
+        * @param string $tooltip The tooltip to use for the link: will be escaped
+        *   and wrapped in the 'editsectionhint' message
+        * @param string $lang Language code
+        * @return string HTML to use for edit link
+        */
+       public function doEditSectionLink( Title $nt, $section, $tooltip = null, $lang = false ) {
+               // HTML generated here should probably have userlangattributes
+               // added to it for LTR text on RTL pages
+
+               $lang = wfGetLangObj( $lang );
+
+               $attribs = array();
+               if ( !is_null( $tooltip ) ) {
+                       # Bug 25462: undo double-escaping.
+                       $tooltip = Sanitizer::decodeCharReferences( $tooltip );
+                       $attribs['title'] = wfMessage( 'editsectionhint' )->rawParams( $tooltip )
+                               ->inLanguage( $lang )->text();
+               }
+               $link = Linker::link( $nt, wfMessage( 'editsection' )->inLanguage( $lang )->text(),
+                       $attribs,
+                       array( 'action' => 'edit', 'section' => $section ),
+                       array( 'noclasses', 'known' )
+               );
+
+               # Add the brackets and the span and run the hook.
+               $result = '<span class="mw-editsection">'
+                       . '<span class="mw-editsection-bracket">[</span>'
+                       . $link
+                       . '<span class="mw-editsection-bracket">]</span>'
+                       . '</span>';
+
+               wfRunHooks( 'DoEditSectionLink', array( $this, $nt, $section, $tooltip, &$result, $lang ) );
+               return $result;
+       }
+
+       /**
+        * Use PHP's magic __call handler to intercept legacy calls to the linker
+        * for backwards compatibility.
+        *
+        * @param string $fname Name of called method
+        * @param array $args Arguments to the method
+        * @throws MWException
+        * @return mixed
+        */
+       function __call( $fname, $args ) {
+               $realFunction = array( 'Linker', $fname );
+               if ( is_callable( $realFunction ) ) {
+                       wfDeprecated( get_class( $this ) . '::' . $fname, '1.21' );
+                       return call_user_func_array( $realFunction, $args );
+               } else {
+                       $className = get_class( $this );
+                       throw new MWException( "Call to undefined method $className::$fname" );
+               }
+       }
+
+}
diff --git a/includes/skins/SkinException.php b/includes/skins/SkinException.php
new file mode 100644 (file)
index 0000000..31ff143
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Copyright 2014
+ *
+ * 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
+ */
+
+/**
+ * Exceptions for skin-related failures
+ *
+ * @since 1.24
+ */
+class SkinException extends MWException {
+}
diff --git a/includes/skins/SkinFactory.php b/includes/skins/SkinFactory.php
new file mode 100644 (file)
index 0000000..fb40857
--- /dev/null
@@ -0,0 +1,214 @@
+<?php
+
+/**
+ * Copyright 2014
+ *
+ * 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
+ */
+
+/**
+ * Factory class to create Skin objects
+ *
+ * @since 1.24
+ */
+class SkinFactory {
+
+       /**
+        * Map of name => callback
+        * @var array
+        */
+       private $factoryFunctions = array();
+       /**
+        * Map of name => fallback human-readable name, used when the 'skinname-<skin>' message is not
+        * available
+        *
+        * @var array
+        */
+       private $displayNames = array();
+       /**
+        * Map of name => class name without "Skin" prefix, for legacy skins using the autodiscovery
+        * mechanism
+        *
+        * @var array
+        */
+       private $legacySkins = array();
+
+       /**
+        * @var SkinFactory
+        */
+       private static $self;
+
+       public static function getDefaultInstance() {
+               if ( !self::$self ) {
+                       self::$self = new self;
+               }
+
+               return self::$self;
+       }
+
+       /**
+        * Register a new Skin factory function.
+        *
+        * Will override if it's already registered.
+        *
+        * @param string $name Internal skin name. Should be all-lowercase (technically doesn't have
+        *     to be, but doing so would change the case of i18n message keys).
+        * @param string $displayName For backwards-compatibility with old skin loading system. This is
+        *     the text used as skin's human-readable name when the 'skinname-<skin>' message is not
+        *     available. It should be the same as the skin name provided in $wgExtensionCredits.
+        * @param callable $callback Callback that takes the skin name as an argument
+        * @throws InvalidArgumentException If an invalid callback is provided
+        */
+       public function register( $name, $displayName, $callback ) {
+               if ( !is_callable( $callback ) ) {
+                       throw new InvalidArgumentException( 'Invalid callback provided' );
+               }
+               $this->factoryFunctions[$name] = $callback;
+               $this->displayNames[$name] = $displayName;
+       }
+
+       /**
+        * @return array
+        */
+       private function getLegacySkinNames() {
+               static $skinsInitialised = false;
+
+               if ( !$skinsInitialised || !count( $this->legacySkins ) ) {
+                       # Get a list of available skins
+                       # Build using the regular expression '^(.*).php$'
+                       # Array keys are all lower case, array value keep the case used by filename
+                       #
+                       wfProfileIn( __METHOD__ . '-init' );
+
+                       global $wgStyleDirectory;
+
+                       $skinDir = dir( $wgStyleDirectory );
+
+                       if ( $skinDir !== false && $skinDir !== null ) {
+                               # while code from www.php.net
+                               while ( false !== ( $file = $skinDir->read() ) ) {
+                                       // Skip non-PHP files, hidden files, and '.dep' includes
+                                       $matches = array();
+
+                                       if ( preg_match( '/^([^.]*)\.php$/', $file, $matches ) ) {
+                                               $aSkin = $matches[1];
+
+                                               // Explicitly disallow loading core skins via the autodiscovery mechanism.
+                                               //
+                                               // They should be loaded already (in a non-autodicovery way), but old files might still
+                                               // exist on the server because our MW version upgrade process is widely documented as
+                                               // requiring just copying over all files, without removing old ones.
+                                               //
+                                               // This is one of the reasons we should have never used autodiscovery in the first
+                                               // place. This hack can be safely removed when autodiscovery is gone.
+                                               if ( in_array( $aSkin, array( 'CologneBlue', 'Modern', 'MonoBook', 'Vector' ) ) ) {
+                                                       wfLogWarning(
+                                                               "An old copy of the $aSkin skin was found in your skins/ directory. " .
+                                                               "You should remove it to avoid problems in the future." .
+                                                               "See https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery for details."
+                                                       );
+                                                       continue;
+                                               }
+
+                                               wfLogWarning(
+                                                       "A skin using autodiscovery mechanism, $aSkin, was found in your skins/ directory. " .
+                                                       "The mechanism will be removed in MediaWiki 1.25 and the skin will no longer be recognized. " .
+                                                       "See https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery for information how to fix this."
+                                               );
+                                               $this->legacySkins[strtolower( $aSkin )] = $aSkin;
+                                       }
+                               }
+                               $skinDir->close();
+                       }
+                       $skinsInitialised = true;
+                       wfProfileOut( __METHOD__ . '-init' );
+               }
+               return $this->legacySkins;
+
+       }
+
+       /**
+        * Returns an associative array of:
+        *  skin name => human readable name
+        *
+        * @return array
+        */
+       public function getSkinNames() {
+               return array_merge(
+                       $this->getLegacySkinNames(),
+                       $this->displayNames
+               );
+       }
+
+       /**
+        * Get a legacy skin which uses the autodiscovery mechanism.
+        *
+        * @param string $name
+        * @return Skin|bool False if the skin couldn't be constructed
+        */
+       private function getLegacySkin( $name ) {
+               $skinNames = $this->getLegacySkinNames();
+               if ( !isset( $skinNames[$name] ) ) {
+                       return false;
+               }
+               $skinName = $skinNames[$name];
+               $className = "Skin{$skinName}";
+
+               # Grab the skin class and initialise it.
+               if ( !class_exists( $className ) ) {
+                       global $wgStyleDirectory;
+                       require_once "{$wgStyleDirectory}/{$skinName}.php";
+
+                       # Check if we got it
+                       if ( !class_exists( $className ) ) {
+                               # DO NOT die if the class isn't found. This breaks maintenance
+                               # scripts and can cause a user account to be unrecoverable
+                               # except by SQL manipulation if a previously valid skin name
+                               # is no longer valid.
+                               return false;
+                       }
+               }
+               $skin = new $className( $name );
+               return $skin;
+
+       }
+
+       /**
+        * Create a given Skin using the registered callback for $name.
+        * @param string $name Name of the skin you want
+        * @throws SkinException If a factory function isn't registered for $name
+        * @throws UnexpectedValueException If the factory function returns a non-Skin object
+        * @return Skin
+        */
+       public function makeSkin( $name ) {
+               if ( !isset( $this->factoryFunctions[$name] ) ) {
+                       // Check the legacy autodiscovery method of skin loading
+                       $legacy = $this->getLegacySkin( $name );
+                       if ( $legacy ) {
+                               return $legacy;
+                       }
+                       throw new SkinException( "No registered builder available for $name." );
+               }
+               $skin = call_user_func( $this->factoryFunctions[$name], $name );
+               if ( $skin instanceof Skin ) {
+                       return $skin;
+               } else {
+                       throw new UnexpectedValueException( "The builder for $name returned a non-Skin object." );
+               }
+       }
+}
diff --git a/includes/skins/SkinFallback.php b/includes/skins/SkinFallback.php
new file mode 100644 (file)
index 0000000..96ff228
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Skin file for the fallback skin.
+ *
+ * The structure is copied from the example skin (mediawiki/skins/Example).
+ *
+ * @since 1.24
+ * @file
+ */
+
+/**
+ * SkinTemplate class for the fallback skin
+ */
+class SkinFallback extends SkinTemplate {
+
+       public $skinname = 'fallback';
+       public $template = 'SkinFallbackTemplate';
+
+       /**
+        * Add CSS via ResourceLoader
+        *
+        * @param OutputPage $out
+        */
+       public function setupSkinUserCss( OutputPage $out ) {
+               parent::setupSkinUserCss( $out );
+               $out->addModuleStyles( 'mediawiki.skinning.interface' );
+       }
+
+       /**
+        * @param OutputPage $out
+        */
+       public function initPage( OutputPage $out ) {
+               parent::initPage( $out );
+               $out->enableClientCache( false );
+       }
+}
diff --git a/includes/skins/SkinFallbackTemplate.php b/includes/skins/SkinFallbackTemplate.php
new file mode 100644 (file)
index 0000000..603ee5c
--- /dev/null
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * Skin template for the fallback skin.
+ *
+ * The structure is copied from the example skin (mediawiki/skins/Example).
+ *
+ * @since 1.24
+ * @file
+ */
+
+/**
+ * BaseTemplate class for the fallback skin
+ */
+class SkinFallbackTemplate extends BaseTemplate {
+       /**
+        * @return array
+        */
+       private function findInstalledSkins() {
+               $styleDirectory = $this->config->get( 'StyleDirectory' ); // @todo we should inject this directly?
+               // Get all subdirectories which might contains skins
+               $possibleSkins = scandir( $styleDirectory );
+               $possibleSkins = array_filter( $possibleSkins, function ( $maybeDir ) use ( $styleDirectory ) {
+                       return $maybeDir !== '.' && $maybeDir !== '..' && is_dir( "$styleDirectory/$maybeDir" );
+               } );
+
+               // Only keep the ones that contain a .php file with the same name inside
+               $possibleSkins = array_filter( $possibleSkins, function ( $skinDir ) use ( $styleDirectory ) {
+                       return is_file( "$styleDirectory/$skinDir/$skinDir.php" );
+               } );
+
+               return $possibleSkins;
+       }
+
+       /**
+        * Inform the user why they are seeing this skin.
+        *
+        * @return string
+        */
+       private function buildHelpfulInformationMessage() {
+               $defaultSkin = $this->config->get( 'DefaultSkin' );
+               $installedSkins = $this->findInstalledSkins();
+               $enabledSkins = SkinFactory::getDefaultInstance()->getSkinNames();
+               $enabledSkins = array_change_key_case( $enabledSkins, CASE_LOWER );
+
+               if ( $installedSkins ) {
+                       $skinsInstalledText = array();
+                       $skinsInstalledSnippet = array();
+
+                       foreach ( $installedSkins as $skin ) {
+                               $normalizedKey = strtolower( $skin );
+                               $isEnabled = array_key_exists( $normalizedKey, $enabledSkins );
+                               if ( $isEnabled ) {
+                                       $skinsInstalledText[] = $this->getMsg( 'default-skin-not-found-row-enabled' )
+                                               ->params( $normalizedKey, $skin )->plain();
+                               } else {
+                                       $skinsInstalledText[] = $this->getMsg( 'default-skin-not-found-row-disabled' )
+                                               ->params( $normalizedKey, $skin )->plain();
+                                       $skinsInstalledSnippet[] = "require_once \"\$IP/skins/$skin/$skin.php\";";
+                               }
+                       }
+
+                       return $this->getMsg( 'default-skin-not-found' )->params(
+                               $defaultSkin,
+                               implode( "\n", $skinsInstalledText ),
+                               implode( "\n", $skinsInstalledSnippet )
+                       )->parseAsBlock();
+               } else {
+                       return $this->getMsg( 'default-skin-not-found-no-skins' )->params(
+                               $defaultSkin
+                       )->parseAsBlock();
+               }
+       }
+
+       /**
+        * Outputs the entire contents of the page. No navigation (other than search box), just the big
+        * warning message and page content.
+        */
+       public function execute() {
+               $this->html( 'headelement' ) ?>
+
+               <div class="warningbox">
+                       <?php echo $this->buildHelpfulInformationMessage() ?>
+               </div>
+
+               <form action="<?php $this->text( 'wgScript' ) ?>">
+                       <input type="hidden" name="title" value="<?php $this->text( 'searchtitle' ) ?>" />
+                       <h3><label for="searchInput"><?php $this->msg( 'search' ) ?></label></h3>
+                       <?php echo $this->makeSearchInput( array( "id" => "searchInput" ) ) ?>
+                       <?php echo $this->makeSearchButton( 'go' ) ?>
+               </form>
+
+               <div class="mw-body" role="main">
+                       <h1 class="firstHeading">
+                               <span dir="auto"><?php $this->html( 'title' ) ?></span>
+                       </h1>
+
+                       <div class="mw-body-content">
+                               <?php $this->html( 'bodytext' ) ?>
+                               <?php $this->html( 'catlinks' ) ?>
+                       </div>
+               </div>
+
+               <?php $this->printTrail() ?>
+               </body></html>
+
+       <?php
+       }
+}
diff --git a/includes/skins/SkinTemplate.php b/includes/skins/SkinTemplate.php
new file mode 100644 (file)
index 0000000..b66862b
--- /dev/null
@@ -0,0 +1,2123 @@
+<?php
+/**
+ * Base class for template-based skins.
+ *
+ * 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
+ */
+
+/**
+ * Wrapper object for MediaWiki's localization functions,
+ * to be passed to the template engine.
+ *
+ * @private
+ * @ingroup Skins
+ */
+class MediaWikiI18N {
+       private $context = array();
+
+       function set( $varName, $value ) {
+               $this->context[$varName] = $value;
+       }
+
+       function translate( $value ) {
+               wfProfileIn( __METHOD__ );
+
+               // Hack for i18n:attributes in PHPTAL 1.0.0 dev version as of 2004-10-23
+               $value = preg_replace( '/^string:/', '', $value );
+
+               $value = wfMessage( $value )->text();
+               // interpolate variables
+               $m = array();
+               while ( preg_match( '/\$([0-9]*?)/sm', $value, $m ) ) {
+                       list( $src, $var ) = $m;
+                       wfSuppressWarnings();
+                       $varValue = $this->context[$var];
+                       wfRestoreWarnings();
+                       $value = str_replace( $src, $varValue, $value );
+               }
+               wfProfileOut( __METHOD__ );
+               return $value;
+       }
+}
+
+/**
+ * Template-filler skin base class
+ * Formerly generic PHPTal (http://phptal.sourceforge.net/) skin
+ * Based on Brion's smarty skin
+ * @copyright Copyright © Gabriel Wicke -- http://www.aulinx.de/
+ *
+ * @todo Needs some serious refactoring into functions that correspond
+ * to the computations individual esi snippets need. Most importantly no body
+ * parsing for most of those of course.
+ *
+ * @ingroup Skins
+ */
+class SkinTemplate extends Skin {
+       /**
+        * @var string Name of our skin, it probably needs to be all lower case.
+        *   Child classes should override the default.
+        */
+       public $skinname = 'monobook';
+
+       /**
+        * @var string For QuickTemplate, the name of the subclass which will
+        *   actually fill the template.  Child classes should override the default.
+        */
+       public $template = 'QuickTemplate';
+
+       /**
+        * Add specific styles for this skin
+        *
+        * @param OutputPage $out
+        */
+       function setupSkinUserCss( OutputPage $out ) {
+               $out->addModuleStyles( array(
+                       'mediawiki.legacy.shared',
+                       'mediawiki.legacy.commonPrint',
+                       'mediawiki.ui.button'
+               ) );
+       }
+
+       /**
+        * Create the template engine object; we feed it a bunch of data
+        * and eventually it spits out some HTML. Should have interface
+        * roughly equivalent to PHPTAL 0.7.
+        *
+        * @param string $classname
+        * @param bool|string $repository Subdirectory where we keep template files
+        * @param bool|string $cache_dir
+        * @return QuickTemplate
+        * @private
+        */
+       function setupTemplate( $classname, $repository = false, $cache_dir = false ) {
+               return new $classname( $this->getConfig() );
+       }
+
+       /**
+        * Generates array of language links for the current page
+        *
+        * @return array
+        */
+       public function getLanguages() {
+               global $wgHideInterlanguageLinks;
+               if ( $wgHideInterlanguageLinks ) {
+                       return array();
+               }
+
+               $userLang = $this->getLanguage();
+               $languageLinks = array();
+
+               foreach ( $this->getOutput()->getLanguageLinks() as $languageLinkText ) {
+                       $languageLinkParts = explode( ':', $languageLinkText, 2 );
+                       $class = 'interlanguage-link interwiki-' . $languageLinkParts[0];
+                       unset( $languageLinkParts );
+
+                       $languageLinkTitle = Title::newFromText( $languageLinkText );
+                       if ( $languageLinkTitle ) {
+                               $ilInterwikiCode = $languageLinkTitle->getInterwiki();
+                               $ilLangName = Language::fetchLanguageName( $ilInterwikiCode );
+
+                               if ( strval( $ilLangName ) === '' ) {
+                                       $ilDisplayTextMsg = wfMessage( "interlanguage-link-$ilInterwikiCode" );
+                                       if ( !$ilDisplayTextMsg->isDisabled() ) {
+                                               // Use custom MW message for the display text
+                                               $ilLangName = $ilDisplayTextMsg->text();
+                                       } else {
+                                               // Last resort: fallback to the language link target
+                                               $ilLangName = $languageLinkText;
+                                       }
+                               } else {
+                                       // Use the language autonym as display text
+                                       $ilLangName = $this->formatLanguageName( $ilLangName );
+                               }
+
+                               // CLDR extension or similar is required to localize the language name;
+                               // otherwise we'll end up with the autonym again.
+                               $ilLangLocalName = Language::fetchLanguageName(
+                                       $ilInterwikiCode,
+                                       $userLang->getCode()
+                               );
+
+                               $languageLinkTitleText = $languageLinkTitle->getText();
+                               if ( $ilLangLocalName === '' ) {
+                                       $ilFriendlySiteName = wfMessage( "interlanguage-link-sitename-$ilInterwikiCode" );
+                                       if ( !$ilFriendlySiteName->isDisabled() ) {
+                                               if ( $languageLinkTitleText === '' ) {
+                                                       $ilTitle = wfMessage(
+                                                               'interlanguage-link-title-nonlangonly',
+                                                               $ilFriendlySiteName->text()
+                                                       )->text();
+                                               } else {
+                                                       $ilTitle = wfMessage(
+                                                               'interlanguage-link-title-nonlang',
+                                                               $languageLinkTitleText,
+                                                               $ilFriendlySiteName->text()
+                                                       )->text();
+                                               }
+                                       } else {
+                                               // we have nothing friendly to put in the title, so fall back to
+                                               // displaying the interlanguage link itself in the title text
+                                               // (similar to what is done in page content)
+                                               $ilTitle = $languageLinkTitle->getInterwiki() .
+                                                       ":$languageLinkTitleText";
+                                       }
+                               } elseif ( $languageLinkTitleText === '' ) {
+                                       $ilTitle = wfMessage(
+                                               'interlanguage-link-title-langonly',
+                                               $ilLangLocalName
+                                       )->text();
+                               } else {
+                                       $ilTitle = wfMessage(
+                                               'interlanguage-link-title',
+                                               $languageLinkTitleText,
+                                               $ilLangLocalName
+                                       )->text();
+                               }
+
+                               $ilInterwikiCodeBCP47 = wfBCP47( $ilInterwikiCode );
+                               $languageLink = array(
+                                       'href' => $languageLinkTitle->getFullURL(),
+                                       'text' => $ilLangName,
+                                       'title' => $ilTitle,
+                                       'class' => $class,
+                                       'lang' => $ilInterwikiCodeBCP47,
+                                       'hreflang' => $ilInterwikiCodeBCP47,
+                               );
+                               wfRunHooks(
+                                       'SkinTemplateGetLanguageLink',
+                                       array( &$languageLink, $languageLinkTitle, $this->getTitle(), $this->getOutput() )
+                               );
+                               $languageLinks[] = $languageLink;
+                       }
+               }
+
+               return $languageLinks;
+       }
+
+       protected function setupTemplateForOutput() {
+               wfProfileIn( __METHOD__ );
+
+               $request = $this->getRequest();
+               $user = $this->getUser();
+               $title = $this->getTitle();
+
+               wfProfileIn( __METHOD__ . '-init' );
+               $tpl = $this->setupTemplate( $this->template, 'skins' );
+               wfProfileOut( __METHOD__ . '-init' );
+
+               wfProfileIn( __METHOD__ . '-stuff' );
+               $this->thispage = $title->getPrefixedDBkey();
+               $this->titletxt = $title->getPrefixedText();
+               $this->userpage = $user->getUserPage()->getPrefixedText();
+               $query = array();
+               if ( !$request->wasPosted() ) {
+                       $query = $request->getValues();
+                       unset( $query['title'] );
+                       unset( $query['returnto'] );
+                       unset( $query['returntoquery'] );
+               }
+               $this->thisquery = wfArrayToCgi( $query );
+               $this->loggedin = $user->isLoggedIn();
+               $this->username = $user->getName();
+
+               if ( $this->loggedin || $this->showIPinHeader() ) {
+                       $this->userpageUrlDetails = self::makeUrlDetails( $this->userpage );
+               } else {
+                       # This won't be used in the standard skins, but we define it to preserve the interface
+                       # To save time, we check for existence
+                       $this->userpageUrlDetails = self::makeKnownUrlDetails( $this->userpage );
+               }
+
+               wfProfileOut( __METHOD__ . '-stuff' );
+
+               wfProfileOut( __METHOD__ );
+
+               return $tpl;
+       }
+
+       /**
+        * initialize various variables and generate the template
+        *
+        * @param OutputPage $out
+        */
+       function outputPage( OutputPage $out = null ) {
+               wfProfileIn( __METHOD__ );
+               Profiler::instance()->setTemplated( true );
+
+               $oldContext = null;
+               if ( $out !== null ) {
+                       // @todo Add wfDeprecated in 1.20
+                       $oldContext = $this->getContext();
+                       $this->setContext( $out->getContext() );
+               }
+
+               $out = $this->getOutput();
+
+               wfProfileIn( __METHOD__ . '-init' );
+               $this->initPage( $out );
+               wfProfileOut( __METHOD__ . '-init' );
+               $tpl = $this->prepareQuickTemplate( $out );
+               // execute template
+               wfProfileIn( __METHOD__ . '-execute' );
+               $res = $tpl->execute();
+               wfProfileOut( __METHOD__ . '-execute' );
+
+               // result may be an error
+               $this->printOrError( $res );
+
+               if ( $oldContext ) {
+                       $this->setContext( $oldContext );
+               }
+
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * initialize various variables and generate the template
+        *
+        * @since 1.23
+        * @return QuickTemplate The template to be executed by outputPage
+        */
+       protected function prepareQuickTemplate() {
+               global $wgContLang, $wgScript, $wgStylePath, $wgMimeType, $wgJsMimeType,
+                       $wgDisableCounters, $wgSitename, $wgLogo, $wgMaxCredits,
+                       $wgShowCreditsIfMax, $wgPageShowWatchingUsers, $wgArticlePath,
+                       $wgScriptPath, $wgServer;
+
+               wfProfileIn( __METHOD__ );
+
+               $title = $this->getTitle();
+               $request = $this->getRequest();
+               $out = $this->getOutput();
+               $tpl = $this->setupTemplateForOutput();
+
+               wfProfileIn( __METHOD__ . '-stuff2' );
+               $tpl->set( 'title', $out->getPageTitle() );
+               $tpl->set( 'pagetitle', $out->getHTMLTitle() );
+               $tpl->set( 'displaytitle', $out->mPageLinkTitle );
+
+               $tpl->setRef( 'thispage', $this->thispage );
+               $tpl->setRef( 'titleprefixeddbkey', $this->thispage );
+               $tpl->set( 'titletext', $title->getText() );
+               $tpl->set( 'articleid', $title->getArticleID() );
+
+               $tpl->set( 'isarticle', $out->isArticle() );
+
+               $subpagestr = $this->subPageSubtitle();
+               if ( $subpagestr !== '' ) {
+                       $subpagestr = '<span class="subpages">' . $subpagestr . '</span>';
+               }
+               $tpl->set( 'subtitle', $subpagestr . $out->getSubtitle() );
+
+               $undelete = $this->getUndeleteLink();
+               if ( $undelete === '' ) {
+                       $tpl->set( 'undelete', '' );
+               } else {
+                       $tpl->set( 'undelete', '<span class="subpages">' . $undelete . '</span>' );
+               }
+
+               $tpl->set( 'catlinks', $this->getCategories() );
+               if ( $out->isSyndicated() ) {
+                       $feeds = array();
+                       foreach ( $out->getSyndicationLinks() as $format => $link ) {
+                               $feeds[$format] = array(
+                                       // Messages: feed-atom, feed-rss
+                                       'text' => $this->msg( "feed-$format" )->text(),
+                                       'href' => $link
+                               );
+                       }
+                       $tpl->setRef( 'feeds', $feeds );
+               } else {
+                       $tpl->set( 'feeds', false );
+               }
+
+               $tpl->setRef( 'mimetype', $wgMimeType );
+               $tpl->setRef( 'jsmimetype', $wgJsMimeType );
+               $tpl->set( 'charset', 'UTF-8' );
+               $tpl->setRef( 'wgScript', $wgScript );
+               $tpl->setRef( 'skinname', $this->skinname );
+               $tpl->set( 'skinclass', get_class( $this ) );
+               $tpl->setRef( 'skin', $this );
+               $tpl->setRef( 'stylename', $this->stylename );
+               $tpl->set( 'printable', $out->isPrintable() );
+               $tpl->set( 'handheld', $request->getBool( 'handheld' ) );
+               $tpl->setRef( 'loggedin', $this->loggedin );
+               $tpl->set( 'notspecialpage', !$title->isSpecialPage() );
+               $tpl->set( 'searchaction', $this->escapeSearchLink() );
+               $tpl->set( 'searchtitle', SpecialPage::getTitleFor( 'Search' )->getPrefixedDBkey() );
+               $tpl->set( 'search', trim( $request->getVal( 'search' ) ) );
+               $tpl->setRef( 'stylepath', $wgStylePath );
+               $tpl->setRef( 'articlepath', $wgArticlePath );
+               $tpl->setRef( 'scriptpath', $wgScriptPath );
+               $tpl->setRef( 'serverurl', $wgServer );
+               $tpl->setRef( 'logopath', $wgLogo );
+               $tpl->setRef( 'sitename', $wgSitename );
+
+               $userLang = $this->getLanguage();
+               $userLangCode = $userLang->getHtmlCode();
+               $userLangDir = $userLang->getDir();
+
+               $tpl->set( 'lang', $userLangCode );
+               $tpl->set( 'dir', $userLangDir );
+               $tpl->set( 'rtl', $userLang->isRTL() );
+
+               $tpl->set( 'capitalizeallnouns', $userLang->capitalizeAllNouns() ? ' capitalize-all-nouns' : '' );
+               $tpl->set( 'showjumplinks', true ); // showjumplinks preference has been removed
+               $tpl->set( 'username', $this->loggedin ? $this->username : null );
+               $tpl->setRef( 'userpage', $this->userpage );
+               $tpl->setRef( 'userpageurl', $this->userpageUrlDetails['href'] );
+               $tpl->set( 'userlang', $userLangCode );
+
+               // Users can have their language set differently than the
+               // content of the wiki. For these users, tell the web browser
+               // that interface elements are in a different language.
+               $tpl->set( 'userlangattributes', '' );
+               $tpl->set( 'specialpageattributes', '' ); # obsolete
+               // Used by VectorBeta to insert HTML before content but after the
+               // heading for the page title. Defaults to empty string.
+               $tpl->set( 'prebodyhtml', '' );
+
+               if ( $userLangCode !== $wgContLang->getHtmlCode() || $userLangDir !== $wgContLang->getDir() ) {
+                       $escUserlang = htmlspecialchars( $userLangCode );
+                       $escUserdir = htmlspecialchars( $userLangDir );
+                       // Attributes must be in double quotes because htmlspecialchars() doesn't
+                       // escape single quotes
+                       $attrs = " lang=\"$escUserlang\" dir=\"$escUserdir\"";
+                       $tpl->set( 'userlangattributes', $attrs );
+               }
+
+               wfProfileOut( __METHOD__ . '-stuff2' );
+
+               wfProfileIn( __METHOD__ . '-stuff3' );
+               $tpl->set( 'newtalk', $this->getNewtalks() );
+               $tpl->set( 'logo', $this->logoText() );
+
+               $tpl->set( 'copyright', false );
+               $tpl->set( 'viewcount', false );
+               $tpl->set( 'lastmod', false );
+               $tpl->set( 'credits', false );
+               $tpl->set( 'numberofwatchingusers', false );
+               if ( $out->isArticle() && $title->exists() ) {
+                       if ( $this->isRevisionCurrent() ) {
+                               if ( !$wgDisableCounters ) {
+                                       $viewcount = $this->getWikiPage()->getCount();
+                                       if ( $viewcount ) {
+                                               $tpl->set( 'viewcount', $this->msg( 'viewcount' )->numParams( $viewcount )->parse() );
+                                       }
+                               }
+
+                               if ( $wgPageShowWatchingUsers ) {
+                                       $dbr = wfGetDB( DB_SLAVE );
+                                       $num = $dbr->selectField( 'watchlist', 'COUNT(*)',
+                                               array( 'wl_title' => $title->getDBkey(), 'wl_namespace' => $title->getNamespace() ),
+                                               __METHOD__
+                                       );
+                                       if ( $num > 0 ) {
+                                               $tpl->set( 'numberofwatchingusers',
+                                                       $this->msg( 'number_of_watching_users_pageview' )->numParams( $num )->parse()
+                                               );
+                                       }
+                               }
+
+                               if ( $wgMaxCredits != 0 ) {
+                                       $tpl->set( 'credits', Action::factory( 'credits', $this->getWikiPage(),
+                                               $this->getContext() )->getCredits( $wgMaxCredits, $wgShowCreditsIfMax ) );
+                               } else {
+                                       $tpl->set( 'lastmod', $this->lastModified() );
+                               }
+                       }
+                       $tpl->set( 'copyright', $this->getCopyright() );
+               }
+               wfProfileOut( __METHOD__ . '-stuff3' );
+
+               wfProfileIn( __METHOD__ . '-stuff4' );
+               $tpl->set( 'copyrightico', $this->getCopyrightIcon() );
+               $tpl->set( 'poweredbyico', $this->getPoweredBy() );
+               $tpl->set( 'disclaimer', $this->disclaimerLink() );
+               $tpl->set( 'privacy', $this->privacyLink() );
+               $tpl->set( 'about', $this->aboutLink() );
+
+               $tpl->set( 'footerlinks', array(
+                       'info' => array(
+                               'lastmod',
+                               'viewcount',
+                               'numberofwatchingusers',
+                               'credits',
+                               'copyright',
+                       ),
+                       'places' => array(
+                               'privacy',
+                               'about',
+                               'disclaimer',
+                       ),
+               ) );
+
+               global $wgFooterIcons;
+               $tpl->set( 'footericons', $wgFooterIcons );
+               foreach ( $tpl->data['footericons'] as $footerIconsKey => &$footerIconsBlock ) {
+                       if ( count( $footerIconsBlock ) > 0 ) {
+                               foreach ( $footerIconsBlock as &$footerIcon ) {
+                                       if ( isset( $footerIcon['src'] ) ) {
+                                               if ( !isset( $footerIcon['width'] ) ) {
+                                                       $footerIcon['width'] = 88;
+                                               }
+                                               if ( !isset( $footerIcon['height'] ) ) {
+                                                       $footerIcon['height'] = 31;
+                                               }
+                                       }
+                               }
+                       } else {
+                               unset( $tpl->data['footericons'][$footerIconsKey] );
+                       }
+               }
+
+               $tpl->set( 'sitenotice', $this->getSiteNotice() );
+               $tpl->set( 'bottomscripts', $this->bottomScripts() );
+               $tpl->set( 'printfooter', $this->printSource() );
+
+               # An ID that includes the actual body text; without categories, contentSub, ...
+               $realBodyAttribs = array( 'id' => 'mw-content-text' );
+
+               # Add a mw-content-ltr/rtl class to be able to style based on text direction
+               # when the content is different from the UI language, i.e.:
+               # not for special pages or file pages AND only when viewing AND if the page exists
+               # (or is in MW namespace, because that has default content)
+               if ( !in_array( $title->getNamespace(), array( NS_SPECIAL, NS_FILE ) ) &&
+                       Action::getActionName( $this ) === 'view' &&
+                       ( $title->exists() || $title->getNamespace() == NS_MEDIAWIKI ) ) {
+                       $pageLang = $title->getPageViewLanguage();
+                       $realBodyAttribs['lang'] = $pageLang->getHtmlCode();
+                       $realBodyAttribs['dir'] = $pageLang->getDir();
+                       $realBodyAttribs['class'] = 'mw-content-' . $pageLang->getDir();
+               }
+
+               $out->mBodytext = Html::rawElement( 'div', $realBodyAttribs, $out->mBodytext );
+               $tpl->setRef( 'bodytext', $out->mBodytext );
+
+               $language_urls = $this->getLanguages();
+               if ( count( $language_urls ) ) {
+                       $tpl->setRef( 'language_urls', $language_urls );
+               } else {
+                       $tpl->set( 'language_urls', false );
+               }
+               wfProfileOut( __METHOD__ . '-stuff4' );
+
+               wfProfileIn( __METHOD__ . '-stuff5' );
+               # Personal toolbar
+               $tpl->set( 'personal_urls', $this->buildPersonalUrls() );
+               $content_navigation = $this->buildContentNavigationUrls();
+               $content_actions = $this->buildContentActionUrls( $content_navigation );
+               $tpl->setRef( 'content_navigation', $content_navigation );
+               $tpl->setRef( 'content_actions', $content_actions );
+
+               $tpl->set( 'sidebar', $this->buildSidebar() );
+               $tpl->set( 'nav_urls', $this->buildNavUrls() );
+
+               // Set the head scripts near the end, in case the above actions resulted in added scripts
+               $tpl->set( 'headelement', $out->headElement( $this ) );
+
+               $tpl->set( 'debug', '' );
+               $tpl->set( 'debughtml', $this->generateDebugHTML() );
+               $tpl->set( 'reporttime', wfReportTime() );
+
+               // original version by hansm
+               if ( !wfRunHooks( 'SkinTemplateOutputPageBeforeExec', array( &$this, &$tpl ) ) ) {
+                       wfDebug( __METHOD__ . ": Hook SkinTemplateOutputPageBeforeExec broke outputPage execution!\n" );
+               }
+
+               // Set the bodytext to another key so that skins can just output it on it's own
+               // and output printfooter and debughtml separately
+               $tpl->set( 'bodycontent', $tpl->data['bodytext'] );
+
+               // Append printfooter and debughtml onto bodytext so that skins that
+               // were already using bodytext before they were split out don't suddenly
+               // start not outputting information.
+               $tpl->data['bodytext'] .= Html::rawElement(
+                       'div',
+                       array( 'class' => 'printfooter' ),
+                       "\n{$tpl->data['printfooter']}"
+               ) . "\n";
+               $tpl->data['bodytext'] .= $tpl->data['debughtml'];
+
+               // allow extensions adding stuff after the page content.
+               // See Skin::afterContentHook() for further documentation.
+               $tpl->set( 'dataAfterContent', $this->afterContentHook() );
+               wfProfileOut( __METHOD__ . '-stuff5' );
+
+               wfProfileOut( __METHOD__ );
+               return $tpl;
+       }
+
+       /**
+        * Get the HTML for the p-personal list
+        * @return string
+        */
+       public function getPersonalToolsList() {
+               $tpl = $this->setupTemplateForOutput();
+               $tpl->set( 'personal_urls', $this->buildPersonalUrls() );
+               $html = '';
+               foreach ( $tpl->getPersonalTools() as $key => $item ) {
+                       $html .= $tpl->makeListItem( $key, $item );
+               }
+               return $html;
+       }
+
+       /**
+        * Format language name for use in sidebar interlanguage links list.
+        * By default it is capitalized.
+        *
+        * @param string $name Language name, e.g. "English" or "español"
+        * @return string
+        * @private
+        */
+       function formatLanguageName( $name ) {
+               return $this->getLanguage()->ucfirst( $name );
+       }
+
+       /**
+        * Output the string, or print error message if it's
+        * an error object of the appropriate type.
+        * For the base class, assume strings all around.
+        *
+        * @param string $str
+        * @private
+        */
+       function printOrError( $str ) {
+               echo $str;
+       }
+
+       /**
+        * Output a boolean indicating if buildPersonalUrls should output separate
+        * login and create account links or output a combined link
+        * By default we simply return a global config setting that affects most skins
+        * This is setup as a method so that like with $wgLogo and getLogo() a skin
+        * can override this setting and always output one or the other if it has
+        * a reason it can't output one of the two modes.
+        * @return bool
+        */
+       function useCombinedLoginLink() {
+               global $wgUseCombinedLoginLink;
+               return $wgUseCombinedLoginLink;
+       }
+
+       /**
+        * build array of urls for personal toolbar
+        * @return array
+        */
+       protected function buildPersonalUrls() {
+               $title = $this->getTitle();
+               $request = $this->getRequest();
+               $pageurl = $title->getLocalURL();
+               wfProfileIn( __METHOD__ );
+
+               /* set up the default links for the personal toolbar */
+               $personal_urls = array();
+
+               # Due to bug 32276, if a user does not have read permissions,
+               # $this->getTitle() will just give Special:Badtitle, which is
+               # not especially useful as a returnto parameter. Use the title
+               # from the request instead, if there was one.
+               if ( $this->getUser()->isAllowed( 'read' ) ) {
+                       $page = $this->getTitle();
+               } else {
+                       $page = Title::newFromText( $request->getVal( 'title', '' ) );
+               }
+               $page = $request->getVal( 'returnto', $page );
+               $a = array();
+               if ( strval( $page ) !== '' ) {
+                       $a['returnto'] = $page;
+                       $query = $request->getVal( 'returntoquery', $this->thisquery );
+                       if ( $query != '' ) {
+                               $a['returntoquery'] = $query;
+                       }
+               }
+
+               $returnto = wfArrayToCgi( $a );
+               if ( $this->loggedin ) {
+                       $personal_urls['userpage'] = array(
+                               'text' => $this->username,
+                               'href' => &$this->userpageUrlDetails['href'],
+                               'class' => $this->userpageUrlDetails['exists'] ? false : 'new',
+                               'active' => ( $this->userpageUrlDetails['href'] == $pageurl ),
+                               'dir' => 'auto'
+                       );
+                       $usertalkUrlDetails = $this->makeTalkUrlDetails( $this->userpage );
+                       $personal_urls['mytalk'] = array(
+                               'text' => $this->msg( 'mytalk' )->text(),
+                               'href' => &$usertalkUrlDetails['href'],
+                               'class' => $usertalkUrlDetails['exists'] ? false : 'new',
+                               'active' => ( $usertalkUrlDetails['href'] == $pageurl )
+                       );
+                       $href = self::makeSpecialUrl( 'Preferences' );
+                       $personal_urls['preferences'] = array(
+                               'text' => $this->msg( 'mypreferences' )->text(),
+                               'href' => $href,
+                               'active' => ( $href == $pageurl )
+                       );
+
+                       if ( $this->getUser()->isAllowed( 'viewmywatchlist' ) ) {
+                               $href = self::makeSpecialUrl( 'Watchlist' );
+                               $personal_urls['watchlist'] = array(
+                                       'text' => $this->msg( 'mywatchlist' )->text(),
+                                       'href' => $href,
+                                       'active' => ( $href == $pageurl )
+                               );
+                       }
+
+                       # We need to do an explicit check for Special:Contributions, as we
+                       # have to match both the title, and the target, which could come
+                       # from request values (Special:Contributions?target=Jimbo_Wales)
+                       # or be specified in "sub page" form
+                       # (Special:Contributions/Jimbo_Wales). The plot
+                       # thickens, because the Title object is altered for special pages,
+                       # so it doesn't contain the original alias-with-subpage.
+                       $origTitle = Title::newFromText( $request->getText( 'title' ) );
+                       if ( $origTitle instanceof Title && $origTitle->isSpecialPage() ) {
+                               list( $spName, $spPar ) = SpecialPageFactory::resolveAlias( $origTitle->getText() );
+                               $active = $spName == 'Contributions'
+                                       && ( ( $spPar && $spPar == $this->username )
+                                               || $request->getText( 'target' ) == $this->username );
+                       } else {
+                               $active = false;
+                       }
+
+                       $href = self::makeSpecialUrlSubpage( 'Contributions', $this->username );
+                       $personal_urls['mycontris'] = array(
+                               'text' => $this->msg( 'mycontris' )->text(),
+                               'href' => $href,
+                               'active' => $active
+                       );
+                       $personal_urls['logout'] = array(
+                               'text' => $this->msg( 'pt-userlogout' )->text(),
+                               'href' => self::makeSpecialUrl( 'Userlogout',
+                                       // userlogout link must always contain an & character, otherwise we might not be able
+                                       // to detect a buggy precaching proxy (bug 17790)
+                                       $title->isSpecial( 'Preferences' ) ? 'noreturnto' : $returnto
+                               ),
+                               'active' => false
+                       );
+               } else {
+                       $useCombinedLoginLink = $this->useCombinedLoginLink();
+                       $loginlink = $this->getUser()->isAllowed( 'createaccount' ) && $useCombinedLoginLink
+                               ? 'nav-login-createaccount'
+                               : 'pt-login';
+                       $is_signup = $request->getText( 'type' ) == 'signup';
+
+                       $login_url = array(
+                               'text' => $this->msg( $loginlink )->text(),
+                               'href' => self::makeSpecialUrl( 'Userlogin', $returnto ),
+                               'active' => $title->isSpecial( 'Userlogin' )
+                                       && ( $loginlink == 'nav-login-createaccount' || !$is_signup ),
+                       );
+                       $createaccount_url = array(
+                               'text' => $this->msg( 'pt-createaccount' )->text(),
+                               'href' => self::makeSpecialUrl( 'Userlogin', "$returnto&type=signup" ),
+                               'active' => $title->isSpecial( 'Userlogin' ) && $is_signup,
+                       );
+
+                       if ( $this->showIPinHeader() ) {
+                               $href = &$this->userpageUrlDetails['href'];
+                               $personal_urls['anonuserpage'] = array(
+                                       'text' => $this->username,
+                                       'href' => $href,
+                                       'class' => $this->userpageUrlDetails['exists'] ? false : 'new',
+                                       'active' => ( $pageurl == $href )
+                               );
+                               $usertalkUrlDetails = $this->makeTalkUrlDetails( $this->userpage );
+                               $href = &$usertalkUrlDetails['href'];
+                               $personal_urls['anontalk'] = array(
+                                       'text' => $this->msg( 'anontalk' )->text(),
+                                       'href' => $href,
+                                       'class' => $usertalkUrlDetails['exists'] ? false : 'new',
+                                       'active' => ( $pageurl == $href )
+                               );
+                       }
+
+                       if ( $this->getUser()->isAllowed( 'createaccount' ) && !$useCombinedLoginLink ) {
+                               $personal_urls['createaccount'] = $createaccount_url;
+                       }
+
+                       $personal_urls['login'] = $login_url;
+               }
+
+               wfRunHooks( 'PersonalUrls', array( &$personal_urls, &$title, $this ) );
+               wfProfileOut( __METHOD__ );
+               return $personal_urls;
+       }
+
+       /**
+        * Builds an array with tab definition
+        *
+        * @param Title $title Page Where the tab links to
+        * @param string|array $message Message key or an array of message keys (will fall back)
+        * @param bool $selected Display the tab as selected
+        * @param string $query Query string attached to tab URL
+        * @param bool $checkEdit Check if $title exists and mark with .new if one doesn't
+        *
+        * @return array
+        */
+       function tabAction( $title, $message, $selected, $query = '', $checkEdit = false ) {
+               $classes = array();
+               if ( $selected ) {
+                       $classes[] = 'selected';
+               }
+               if ( $checkEdit && !$title->isKnown() ) {
+                       $classes[] = 'new';
+                       if ( $query !== '' ) {
+                               $query = 'action=edit&redlink=1&' . $query;
+                       } else {
+                               $query = 'action=edit&redlink=1';
+                       }
+               }
+
+               // wfMessageFallback will nicely accept $message as an array of fallbacks
+               // or just a single key
+               $msg = wfMessageFallback( $message )->setContext( $this->getContext() );
+               if ( is_array( $message ) ) {
+                       // for hook compatibility just keep the last message name
+                       $message = end( $message );
+               }
+               if ( $msg->exists() ) {
+                       $text = $msg->text();
+               } else {
+                       global $wgContLang;
+                       $text = $wgContLang->getFormattedNsText(
+                               MWNamespace::getSubject( $title->getNamespace() ) );
+               }
+
+               $result = array();
+               if ( !wfRunHooks( 'SkinTemplateTabAction', array( &$this,
+                               $title, $message, $selected, $checkEdit,
+                               &$classes, &$query, &$text, &$result ) ) ) {
+                       return $result;
+               }
+
+               return array(
+                       'class' => implode( ' ', $classes ),
+                       'text' => $text,
+                       'href' => $title->getLocalURL( $query ),
+                       'primary' => true );
+       }
+
+       function makeTalkUrlDetails( $name, $urlaction = '' ) {
+               $title = Title::newFromText( $name );
+               if ( !is_object( $title ) ) {
+                       throw new MWException( __METHOD__ . " given invalid pagename $name" );
+               }
+               $title = $title->getTalkPage();
+               self::checkTitle( $title, $name );
+               return array(
+                       'href' => $title->getLocalURL( $urlaction ),
+                       'exists' => $title->getArticleID() != 0,
+               );
+       }
+
+       function makeArticleUrlDetails( $name, $urlaction = '' ) {
+               $title = Title::newFromText( $name );
+               $title = $title->getSubjectPage();
+               self::checkTitle( $title, $name );
+               return array(
+                       'href' => $title->getLocalURL( $urlaction ),
+                       'exists' => $title->getArticleID() != 0,
+               );
+       }
+
+       /**
+        * a structured array of links usually used for the tabs in a skin
+        *
+        * There are 4 standard sections
+        * namespaces: Used for namespace tabs like special, page, and talk namespaces
+        * views: Used for primary page views like read, edit, history
+        * actions: Used for most extra page actions like deletion, protection, etc...
+        * variants: Used to list the language variants for the page
+        *
+        * Each section's value is a key/value array of links for that section.
+        * The links themselves have these common keys:
+        * - class: The css classes to apply to the tab
+        * - text: The text to display on the tab
+        * - href: The href for the tab to point to
+        * - rel: An optional rel= for the tab's link
+        * - redundant: If true the tab will be dropped in skins using content_actions
+        *   this is useful for tabs like "Read" which only have meaning in skins that
+        *   take special meaning from the grouped structure of content_navigation
+        *
+        * Views also have an extra key which can be used:
+        * - primary: If this is not true skins like vector may try to hide the tab
+        *            when the user has limited space in their browser window
+        *
+        * content_navigation using code also expects these ids to be present on the
+        * links, however these are usually automatically generated by SkinTemplate
+        * itself and are not necessary when using a hook. The only things these may
+        * matter to are people modifying content_navigation after it's initial creation:
+        * - id: A "preferred" id, most skins are best off outputting this preferred
+        *   id for best compatibility.
+        * - tooltiponly: This is set to true for some tabs in cases where the system
+        *   believes that the accesskey should not be added to the tab.
+        *
+        * @return array
+        */
+       protected function buildContentNavigationUrls() {
+               global $wgDisableLangConversion;
+
+               wfProfileIn( __METHOD__ );
+
+               // Display tabs for the relevant title rather than always the title itself
+               $title = $this->getRelevantTitle();
+               $onPage = $title->equals( $this->getTitle() );
+
+               $out = $this->getOutput();
+               $request = $this->getRequest();
+               $user = $this->getUser();
+
+               $content_navigation = array(
+                       'namespaces' => array(),
+                       'views' => array(),
+                       'actions' => array(),
+                       'variants' => array()
+               );
+
+               // parameters
+               $action = $request->getVal( 'action', 'view' );
+
+               $userCanRead = $title->quickUserCan( 'read', $user );
+
+               $preventActiveTabs = false;
+               wfRunHooks( 'SkinTemplatePreventOtherActiveTabs', array( &$this, &$preventActiveTabs ) );
+
+               // Checks if page is some kind of content
+               if ( $title->canExist() ) {
+                       // Gets page objects for the related namespaces
+                       $subjectPage = $title->getSubjectPage();
+                       $talkPage = $title->getTalkPage();
+
+                       // Determines if this is a talk page
+                       $isTalk = $title->isTalkPage();
+
+                       // Generates XML IDs from namespace names
+                       $subjectId = $title->getNamespaceKey( '' );
+
+                       if ( $subjectId == 'main' ) {
+                               $talkId = 'talk';
+                       } else {
+                               $talkId = "{$subjectId}_talk";
+                       }
+
+                       $skname = $this->skinname;
+
+                       // Adds namespace links
+                       $subjectMsg = array( "nstab-$subjectId" );
+                       if ( $subjectPage->isMainPage() ) {
+                               array_unshift( $subjectMsg, 'mainpage-nstab' );
+                       }
+                       $content_navigation['namespaces'][$subjectId] = $this->tabAction(
+                               $subjectPage, $subjectMsg, !$isTalk && !$preventActiveTabs, '', $userCanRead
+                       );
+                       $content_navigation['namespaces'][$subjectId]['context'] = 'subject';
+                       $content_navigation['namespaces'][$talkId] = $this->tabAction(
+                               $talkPage, array( "nstab-$talkId", 'talk' ), $isTalk && !$preventActiveTabs, '', $userCanRead
+                       );
+                       $content_navigation['namespaces'][$talkId]['context'] = 'talk';
+
+                       if ( $userCanRead ) {
+                               $isForeignFile = $title->inNamespace( NS_FILE ) && $this->canUseWikiPage() &&
+                                       $this->getWikiPage() instanceof WikiFilePage && !$this->getWikiPage()->isLocal();
+
+                               // Adds view view link
+                               if ( $title->exists() || $isForeignFile ) {
+                                       $content_navigation['views']['view'] = $this->tabAction(
+                                               $isTalk ? $talkPage : $subjectPage,
+                                               array( "$skname-view-view", 'view' ),
+                                               ( $onPage && ( $action == 'view' || $action == 'purge' ) ), '', true
+                                       );
+                                       // signal to hide this from simple content_actions
+                                       $content_navigation['views']['view']['redundant'] = true;
+                               }
+
+                               // If it is a non-local file, show a link to the file in its own repository
+                               if ( $isForeignFile ) {
+                                       $file = $this->getWikiPage()->getFile();
+                                       $content_navigation['views']['view-foreign'] = array(
+                                               'class' => '',
+                                               'text' => wfMessageFallback( "$skname-view-foreign", 'view-foreign' )->
+                                                       setContext( $this->getContext() )->
+                                                       params( $file->getRepo()->getDisplayName() )->text(),
+                                               'href' => $file->getDescriptionUrl(),
+                                               'primary' => false,
+                                       );
+                               }
+
+                               wfProfileIn( __METHOD__ . '-edit' );
+
+                               // Checks if user can edit the current page if it exists or create it otherwise
+                               if ( $title->quickUserCan( 'edit', $user )
+                                       && ( $title->exists() || $title->quickUserCan( 'create', $user ) )
+                               ) {
+                                       // Builds CSS class for talk page links
+                                       $isTalkClass = $isTalk ? ' istalk' : '';
+                                       // Whether the user is editing the page
+                                       $isEditing = $onPage && ( $action == 'edit' || $action == 'submit' );
+                                       // Whether to show the "Add a new section" tab
+                                       // Checks if this is a current rev of talk page and is not forced to be hidden
+                                       $showNewSection = !$out->forceHideNewSectionLink()
+                                               && ( ( $isTalk && $this->isRevisionCurrent() ) || $out->showNewSectionLink() );
+                                       $section = $request->getVal( 'section' );
+
+                                       if ( $title->exists()
+                                               || ( $title->getNamespace() == NS_MEDIAWIKI
+                                                       && $title->getDefaultMessageText() !== false
+                                               )
+                                       ) {
+                                               $msgKey = $isForeignFile ? 'edit-local' : 'edit';
+                                       } else {
+                                               $msgKey = $isForeignFile ? 'create-local' : 'create';
+                                       }
+                                       $content_navigation['views']['edit'] = array(
+                                               'class' => ( $isEditing && ( $section !== 'new' || !$showNewSection )
+                                                       ? 'selected'
+                                                       : ''
+                                               ) . $isTalkClass,
+                                               'text' => wfMessageFallback( "$skname-view-$msgKey", $msgKey )
+                                                       ->setContext( $this->getContext() )->text(),
+                                               'href' => $title->getLocalURL( $this->editUrlOptions() ),
+                                               'primary' => !$isForeignFile, // don't collapse this in vector
+                                       );
+
+                                       // section link
+                                       if ( $showNewSection ) {
+                                               // Adds new section link
+                                               //$content_navigation['actions']['addsection']
+                                               $content_navigation['views']['addsection'] = array(
+                                                       'class' => ( $isEditing && $section == 'new' ) ? 'selected' : false,
+                                                       'text' => wfMessageFallback( "$skname-action-addsection", 'addsection' )
+                                                               ->setContext( $this->getContext() )->text(),
+                                                       'href' => $title->getLocalURL( 'action=edit&section=new' )
+                                               );
+                                       }
+                               // Checks if the page has some kind of viewable content
+                               } elseif ( $title->hasSourceText() ) {
+                                       // Adds view source view link
+                                       $content_navigation['views']['viewsource'] = array(
+                                               'class' => ( $onPage && $action == 'edit' ) ? 'selected' : false,
+                                               'text' => wfMessageFallback( "$skname-action-viewsource", 'viewsource' )
+                                                       ->setContext( $this->getContext() )->text(),
+                                               'href' => $title->getLocalURL( $this->editUrlOptions() ),
+                                               'primary' => true, // don't collapse this in vector
+                                       );
+                               }
+                               wfProfileOut( __METHOD__ . '-edit' );
+
+                               wfProfileIn( __METHOD__ . '-live' );
+                               // Checks if the page exists
+                               if ( $title->exists() ) {
+                                       // Adds history view link
+                                       $content_navigation['views']['history'] = array(
+                                               'class' => ( $onPage && $action == 'history' ) ? 'selected' : false,
+                                               'text' => wfMessageFallback( "$skname-view-history", 'history_short' )
+                                                       ->setContext( $this->getContext() )->text(),
+                                               'href' => $title->getLocalURL( 'action=history' ),
+                                               'rel' => 'archives',
+                                       );
+
+                                       if ( $title->quickUserCan( 'delete', $user ) ) {
+                                               $content_navigation['actions']['delete'] = array(
+                                                       'class' => ( $onPage && $action == 'delete' ) ? 'selected' : false,
+                                                       'text' => wfMessageFallback( "$skname-action-delete", 'delete' )
+                                                               ->setContext( $this->getContext() )->text(),
+                                                       'href' => $title->getLocalURL( 'action=delete' )
+                                               );
+                                       }
+
+                                       if ( $title->quickUserCan( 'move', $user ) ) {
+                                               $moveTitle = SpecialPage::getTitleFor( 'Movepage', $title->getPrefixedDBkey() );
+                                               $content_navigation['actions']['move'] = array(
+                                                       'class' => $this->getTitle()->isSpecial( 'Movepage' ) ? 'selected' : false,
+                                                       'text' => wfMessageFallback( "$skname-action-move", 'move' )
+                                                               ->setContext( $this->getContext() )->text(),
+                                                       'href' => $moveTitle->getLocalURL()
+                                               );
+                                       }
+                               } else {
+                                       // article doesn't exist or is deleted
+                                       if ( $user->isAllowed( 'deletedhistory' ) ) {
+                                               $n = $title->isDeleted();
+                                               if ( $n ) {
+                                                       $undelTitle = SpecialPage::getTitleFor( 'Undelete' );
+                                                       // If the user can't undelete but can view deleted
+                                                       // history show them a "View .. deleted" tab instead.
+                                                       $msgKey = $user->isAllowed( 'undelete' ) ? 'undelete' : 'viewdeleted';
+                                                       $content_navigation['actions']['undelete'] = array(
+                                                               'class' => $this->getTitle()->isSpecial( 'Undelete' ) ? 'selected' : false,
+                                                               'text' => wfMessageFallback( "$skname-action-$msgKey", "{$msgKey}_short" )
+                                                                       ->setContext( $this->getContext() )->numParams( $n )->text(),
+                                                               'href' => $undelTitle->getLocalURL( array( 'target' => $title->getPrefixedDBkey() ) )
+                                                       );
+                                               }
+                                       }
+                               }
+
+                               if ( $title->quickUserCan( 'protect', $user ) && $title->getRestrictionTypes() &&
+                                       MWNamespace::getRestrictionLevels( $title->getNamespace(), $user ) !== array( '' )
+                               ) {
+                                       $mode = $title->isProtected() ? 'unprotect' : 'protect';
+                                       $content_navigation['actions'][$mode] = array(
+                                               'class' => ( $onPage && $action == $mode ) ? 'selected' : false,
+                                               'text' => wfMessageFallback( "$skname-action-$mode", $mode )
+                                                       ->setContext( $this->getContext() )->text(),
+                                               'href' => $title->getLocalURL( "action=$mode" )
+                                       );
+                               }
+
+                               wfProfileOut( __METHOD__ . '-live' );
+
+                               // Checks if the user is logged in
+                               if ( $this->loggedin && $user->isAllowedAll( 'viewmywatchlist', 'editmywatchlist' ) ) {
+                                       /**
+                                        * The following actions use messages which, if made particular to
+                                        * the any specific skins, would break the Ajax code which makes this
+                                        * action happen entirely inline. OutputPage::getJSVars
+                                        * defines a set of messages in a javascript object - and these
+                                        * messages are assumed to be global for all skins. Without making
+                                        * a change to that procedure these messages will have to remain as
+                                        * the global versions.
+                                        */
+                                       $mode = $user->isWatched( $title ) ? 'unwatch' : 'watch';
+                                       $token = WatchAction::getWatchToken( $title, $user, $mode );
+                                       $content_navigation['actions'][$mode] = array(
+                                               'class' => $onPage && ( $action == 'watch' || $action == 'unwatch' ) ? 'selected' : false,
+                                               // uses 'watch' or 'unwatch' message
+                                               'text' => $this->msg( $mode )->text(),
+                                               'href' => $title->getLocalURL( array( 'action' => $mode, 'token' => $token ) )
+                                       );
+                               }
+                       }
+
+                       wfRunHooks( 'SkinTemplateNavigation', array( &$this, &$content_navigation ) );
+
+                       if ( $userCanRead && !$wgDisableLangConversion ) {
+                               $pageLang = $title->getPageLanguage();
+                               // Gets list of language variants
+                               $variants = $pageLang->getVariants();
+                               // Checks that language conversion is enabled and variants exist
+                               // And if it is not in the special namespace
+                               if ( count( $variants ) > 1 ) {
+                                       // Gets preferred variant (note that user preference is
+                                       // only possible for wiki content language variant)
+                                       $preferred = $pageLang->getPreferredVariant();
+                                       if ( Action::getActionName( $this ) === 'view' ) {
+                                               $params = $request->getQueryValues();
+                                               unset( $params['title'] );
+                                       } else {
+                                               $params = array();
+                                       }
+                                       // Loops over each variant
+                                       foreach ( $variants as $code ) {
+                                               // Gets variant name from language code
+                                               $varname = $pageLang->getVariantname( $code );
+                                               // Appends variant link
+                                               $content_navigation['variants'][] = array(
+                                                       'class' => ( $code == $preferred ) ? 'selected' : false,
+                                                       'text' => $varname,
+                                                       'href' => $title->getLocalURL( array( 'variant' => $code ) + $params ),
+                                                       'lang' => wfBCP47( $code ),
+                                                       'hreflang' => wfBCP47( $code ),
+                                               );
+                                       }
+                               }
+                       }
+               } else {
+                       // If it's not content, it's got to be a special page
+                       $content_navigation['namespaces']['special'] = array(
+                               'class' => 'selected',
+                               'text' => $this->msg( 'nstab-special' )->text(),
+                               'href' => $request->getRequestURL(), // @see: bug 2457, bug 2510
+                               'context' => 'subject'
+                       );
+
+                       wfRunHooks( 'SkinTemplateNavigation::SpecialPage',
+                               array( &$this, &$content_navigation ) );
+               }
+
+               // Equiv to SkinTemplateContentActions
+               wfRunHooks( 'SkinTemplateNavigation::Universal', array( &$this, &$content_navigation ) );
+
+               // Setup xml ids and tooltip info
+               foreach ( $content_navigation as $section => &$links ) {
+                       foreach ( $links as $key => &$link ) {
+                               $xmlID = $key;
+                               if ( isset( $link['context'] ) && $link['context'] == 'subject' ) {
+                                       $xmlID = 'ca-nstab-' . $xmlID;
+                               } elseif ( isset( $link['context'] ) && $link['context'] == 'talk' ) {
+                                       $xmlID = 'ca-talk';
+                               } elseif ( $section == 'variants' ) {
+                                       $xmlID = 'ca-varlang-' . $xmlID;
+                               } else {
+                                       $xmlID = 'ca-' . $xmlID;
+                               }
+                               $link['id'] = $xmlID;
+                       }
+               }
+
+               # We don't want to give the watch tab an accesskey if the
+               # page is being edited, because that conflicts with the
+               # accesskey on the watch checkbox.  We also don't want to
+               # give the edit tab an accesskey, because that's fairly
+               # superfluous and conflicts with an accesskey (Ctrl-E) often
+               # used for editing in Safari.
+               if ( in_array( $action, array( 'edit', 'submit' ) ) ) {
+                       if ( isset( $content_navigation['views']['edit'] ) ) {
+                               $content_navigation['views']['edit']['tooltiponly'] = true;
+                       }
+                       if ( isset( $content_navigation['actions']['watch'] ) ) {
+                               $content_navigation['actions']['watch']['tooltiponly'] = true;
+                       }
+                       if ( isset( $content_navigation['actions']['unwatch'] ) ) {
+                               $content_navigation['actions']['unwatch']['tooltiponly'] = true;
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+
+               return $content_navigation;
+       }
+
+       /**
+        * an array of edit links by default used for the tabs
+        * @param array $content_navigation
+        * @return array
+        */
+       private function buildContentActionUrls( $content_navigation ) {
+
+               wfProfileIn( __METHOD__ );
+
+               // content_actions has been replaced with content_navigation for backwards
+               // compatibility and also for skins that just want simple tabs content_actions
+               // is now built by flattening the content_navigation arrays into one
+
+               $content_actions = array();
+
+               foreach ( $content_navigation as $links ) {
+                       foreach ( $links as $key => $value ) {
+                               if ( isset( $value['redundant'] ) && $value['redundant'] ) {
+                                       // Redundant tabs are dropped from content_actions
+                                       continue;
+                               }
+
+                               // content_actions used to have ids built using the "ca-$key" pattern
+                               // so the xmlID based id is much closer to the actual $key that we want
+                               // for that reason we'll just strip out the ca- if present and use
+                               // the latter potion of the "id" as the $key
+                               if ( isset( $value['id'] ) && substr( $value['id'], 0, 3 ) == 'ca-' ) {
+                                       $key = substr( $value['id'], 3 );
+                               }
+
+                               if ( isset( $content_actions[$key] ) ) {
+                                       wfDebug( __METHOD__ . ": Found a duplicate key for $key while flattening " .
+                                               "content_navigation into content_actions.\n" );
+                                       continue;
+                               }
+
+                               $content_actions[$key] = $value;
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+
+               return $content_actions;
+       }
+
+       /**
+        * build array of common navigation links
+        * @return array
+        */
+       protected function buildNavUrls() {
+               global $wgUploadNavigationUrl;
+
+               wfProfileIn( __METHOD__ );
+
+               $out = $this->getOutput();
+               $request = $this->getRequest();
+
+               $nav_urls = array();
+               $nav_urls['mainpage'] = array( 'href' => self::makeMainPageUrl() );
+               if ( $wgUploadNavigationUrl ) {
+                       $nav_urls['upload'] = array( 'href' => $wgUploadNavigationUrl );
+               } elseif ( UploadBase::isEnabled() && UploadBase::isAllowed( $this->getUser() ) === true ) {
+                       $nav_urls['upload'] = array( 'href' => self::makeSpecialUrl( 'Upload' ) );
+               } else {
+                       $nav_urls['upload'] = false;
+               }
+               $nav_urls['specialpages'] = array( 'href' => self::makeSpecialUrl( 'Specialpages' ) );
+
+               $nav_urls['print'] = false;
+               $nav_urls['permalink'] = false;
+               $nav_urls['info'] = false;
+               $nav_urls['whatlinkshere'] = false;
+               $nav_urls['recentchangeslinked'] = false;
+               $nav_urls['contributions'] = false;
+               $nav_urls['log'] = false;
+               $nav_urls['blockip'] = false;
+               $nav_urls['emailuser'] = false;
+               $nav_urls['userrights'] = false;
+
+               // A print stylesheet is attached to all pages, but nobody ever
+               // figures that out. :)  Add a link...
+               if ( !$out->isPrintable() && ( $out->isArticle() || $this->getTitle()->isSpecialPage() ) ) {
+                       $nav_urls['print'] = array(
+                               'text' => $this->msg( 'printableversion' )->text(),
+                               'href' => $this->getTitle()->getLocalURL(
+                                       $request->appendQueryValue( 'printable', 'yes', true ) )
+                       );
+               }
+
+               if ( $out->isArticle() ) {
+                       // Also add a "permalink" while we're at it
+                       $revid = $this->getRevisionId();
+                       if ( $revid ) {
+                               $nav_urls['permalink'] = array(
+                                       'text' => $this->msg( 'permalink' )->text(),
+                                       'href' => $this->getTitle()->getLocalURL( "oldid=$revid" )
+                               );
+                       }
+
+                       // Use the copy of revision ID in case this undocumented, shady hook tries to mess with internals
+                       wfRunHooks( 'SkinTemplateBuildNavUrlsNav_urlsAfterPermalink',
+                               array( &$this, &$nav_urls, &$revid, &$revid ) );
+               }
+
+               if ( $out->isArticleRelated() ) {
+                       $nav_urls['whatlinkshere'] = array(
+                               'href' => SpecialPage::getTitleFor( 'Whatlinkshere', $this->thispage )->getLocalURL()
+                       );
+
+                       $nav_urls['info'] = array(
+                               'text' => $this->msg( 'pageinfo-toolboxlink' )->text(),
+                               'href' => $this->getTitle()->getLocalURL( "action=info" )
+                       );
+
+                       if ( $this->getTitle()->getArticleID() ) {
+                               $nav_urls['recentchangeslinked'] = array(
+                                       'href' => SpecialPage::getTitleFor( 'Recentchangeslinked', $this->thispage )->getLocalURL()
+                               );
+                       }
+               }
+
+               $user = $this->getRelevantUser();
+               if ( $user ) {
+                       $rootUser = $user->getName();
+
+                       $nav_urls['contributions'] = array(
+                               'text' => $this->msg( 'contributions', $rootUser )->text(),
+                               'href' => self::makeSpecialUrlSubpage( 'Contributions', $rootUser )
+                       );
+
+                       $nav_urls['log'] = array(
+                               'href' => self::makeSpecialUrlSubpage( 'Log', $rootUser )
+                       );
+
+                       if ( $this->getUser()->isAllowed( 'block' ) ) {
+                               $nav_urls['blockip'] = array(
+                                       'text' => $this->msg( 'blockip', $rootUser )->text(),
+                                       'href' => self::makeSpecialUrlSubpage( 'Block', $rootUser )
+                               );
+                       }
+
+                       if ( $this->showEmailUser( $user ) ) {
+                               $nav_urls['emailuser'] = array(
+                                       'href' => self::makeSpecialUrlSubpage( 'Emailuser', $rootUser )
+                               );
+                       }
+
+                       if ( !$user->isAnon() ) {
+                               $sur = new UserrightsPage;
+                               $sur->setContext( $this->getContext() );
+                               if ( $sur->userCanExecute( $this->getUser() ) ) {
+                                       $nav_urls['userrights'] = array(
+                                               'href' => self::makeSpecialUrlSubpage( 'Userrights', $rootUser )
+                                       );
+                               }
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $nav_urls;
+       }
+
+       /**
+        * Generate strings used for xml 'id' names
+        * @return string
+        */
+       protected function getNameSpaceKey() {
+               return $this->getTitle()->getNamespaceKey();
+       }
+}
+
+/**
+ * Generic wrapper for template functions, with interface
+ * compatible with what we use of PHPTAL 0.7.
+ * @ingroup Skins
+ */
+abstract class QuickTemplate {
+
+       /** @var Config $config */
+       protected $config;
+
+       /**
+        * @param Config $config
+        */
+       function __construct( Config $config = null ) {
+               $this->data = array();
+               $this->translator = new MediaWikiI18N();
+               if ( $config === null ) {
+                       wfDebug( __METHOD__ . ' was called with no Config instance passed to it' );
+                       $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               }
+               $this->config = $config;
+       }
+
+       /**
+        * Sets the value $value to $name
+        * @param string $name
+        * @param mixed $value
+        */
+       public function set( $name, $value ) {
+               $this->data[$name] = $value;
+       }
+
+       /**
+        * Gets the template data requested
+        * @since 1.22
+        * @param string $name Key for the data
+        * @param mixed $default Optional default (or null)
+        * @return mixed The value of the data requested or the deafult
+        */
+       public function get( $name, $default = null ) {
+               if ( isset( $this->data[$name] ) ) {
+                       return $this->data[$name];
+               } else {
+                       return $default;
+               }
+       }
+
+       /**
+        * @param string $name
+        * @param mixed $value
+        */
+       public function setRef( $name, &$value ) {
+               $this->data[$name] =& $value;
+       }
+
+       /**
+        * @param MediaWikiI18N $t
+        */
+       public function setTranslator( &$t ) {
+               $this->translator = &$t;
+       }
+
+       /**
+        * Main function, used by classes that subclass QuickTemplate
+        * to show the actual HTML output
+        */
+       abstract public function execute();
+
+       /**
+        * @private
+        * @param string $str
+        * @return string
+        */
+       function text( $str ) {
+               echo htmlspecialchars( $this->data[$str] );
+       }
+
+       /**
+        * @private
+        * @param string $str
+        * @return string
+        */
+       function html( $str ) {
+               echo $this->data[$str];
+       }
+
+       /**
+        * @private
+        * @param string $str
+        * @return string
+        */
+       function msg( $str ) {
+               echo htmlspecialchars( $this->translator->translate( $str ) );
+       }
+
+       /**
+        * @private
+        * @param string $str
+        * @return string
+        */
+       function msgHtml( $str ) {
+               echo $this->translator->translate( $str );
+       }
+
+       /**
+        * An ugly, ugly hack.
+        * @private
+        * @param string $str
+        * @return string
+        */
+       function msgWiki( $str ) {
+               global $wgOut;
+
+               $text = $this->translator->translate( $str );
+               echo $wgOut->parse( $text );
+       }
+
+       /**
+        * @private
+        * @param string $str
+        * @return bool
+        */
+       function haveData( $str ) {
+               return isset( $this->data[$str] );
+       }
+
+       /**
+        * @private
+        *
+        * @param string $str
+        * @return bool
+        */
+       function haveMsg( $str ) {
+               $msg = $this->translator->translate( $str );
+               return ( $msg != '-' ) && ( $msg != '' ); # ????
+       }
+
+       /**
+        * Get the Skin object related to this object
+        *
+        * @return Skin
+        */
+       public function getSkin() {
+               return $this->data['skin'];
+       }
+
+       /**
+        * Fetch the output of a QuickTemplate and return it
+        *
+        * @since 1.23
+        * @return string
+        */
+       public function getHTML() {
+               ob_start();
+               $this->execute();
+               $html = ob_get_contents();
+               ob_end_clean();
+               return $html;
+       }
+}
+
+/**
+ * New base template for a skin's template extended from QuickTemplate
+ * this class features helper methods that provide common ways of interacting
+ * with the data stored in the QuickTemplate
+ */
+abstract class BaseTemplate extends QuickTemplate {
+
+       /**
+        * Get a Message object with its context set
+        *
+        * @param string $name Message name
+        * @return Message
+        */
+       public function getMsg( $name ) {
+               return $this->getSkin()->msg( $name );
+       }
+
+       function msg( $str ) {
+               echo $this->getMsg( $str )->escaped();
+       }
+
+       function msgHtml( $str ) {
+               echo $this->getMsg( $str )->text();
+       }
+
+       function msgWiki( $str ) {
+               echo $this->getMsg( $str )->parseAsBlock();
+       }
+
+       /**
+        * Create an array of common toolbox items from the data in the quicktemplate
+        * stored by SkinTemplate.
+        * The resulting array is built according to a format intended to be passed
+        * through makeListItem to generate the html.
+        * @return array
+        */
+       function getToolbox() {
+               wfProfileIn( __METHOD__ );
+
+               $toolbox = array();
+               if ( isset( $this->data['nav_urls']['whatlinkshere'] )
+                       && $this->data['nav_urls']['whatlinkshere']
+               ) {
+                       $toolbox['whatlinkshere'] = $this->data['nav_urls']['whatlinkshere'];
+                       $toolbox['whatlinkshere']['id'] = 't-whatlinkshere';
+               }
+               if ( isset( $this->data['nav_urls']['recentchangeslinked'] )
+                       && $this->data['nav_urls']['recentchangeslinked']
+               ) {
+                       $toolbox['recentchangeslinked'] = $this->data['nav_urls']['recentchangeslinked'];
+                       $toolbox['recentchangeslinked']['msg'] = 'recentchangeslinked-toolbox';
+                       $toolbox['recentchangeslinked']['id'] = 't-recentchangeslinked';
+               }
+               if ( isset( $this->data['feeds'] ) && $this->data['feeds'] ) {
+                       $toolbox['feeds']['id'] = 'feedlinks';
+                       $toolbox['feeds']['links'] = array();
+                       foreach ( $this->data['feeds'] as $key => $feed ) {
+                               $toolbox['feeds']['links'][$key] = $feed;
+                               $toolbox['feeds']['links'][$key]['id'] = "feed-$key";
+                               $toolbox['feeds']['links'][$key]['rel'] = 'alternate';
+                               $toolbox['feeds']['links'][$key]['type'] = "application/{$key}+xml";
+                               $toolbox['feeds']['links'][$key]['class'] = 'feedlink';
+                       }
+               }
+               foreach ( array( 'contributions', 'log', 'blockip', 'emailuser',
+                       'userrights', 'upload', 'specialpages' ) as $special
+               ) {
+                       if ( isset( $this->data['nav_urls'][$special] ) && $this->data['nav_urls'][$special] ) {
+                               $toolbox[$special] = $this->data['nav_urls'][$special];
+                               $toolbox[$special]['id'] = "t-$special";
+                       }
+               }
+               if ( isset( $this->data['nav_urls']['print'] ) && $this->data['nav_urls']['print'] ) {
+                       $toolbox['print'] = $this->data['nav_urls']['print'];
+                       $toolbox['print']['id'] = 't-print';
+                       $toolbox['print']['rel'] = 'alternate';
+                       $toolbox['print']['msg'] = 'printableversion';
+               }
+               if ( isset( $this->data['nav_urls']['permalink'] ) && $this->data['nav_urls']['permalink'] ) {
+                       $toolbox['permalink'] = $this->data['nav_urls']['permalink'];
+                       if ( $toolbox['permalink']['href'] === '' ) {
+                               unset( $toolbox['permalink']['href'] );
+                               $toolbox['ispermalink']['tooltiponly'] = true;
+                               $toolbox['ispermalink']['id'] = 't-ispermalink';
+                               $toolbox['ispermalink']['msg'] = 'permalink';
+                       } else {
+                               $toolbox['permalink']['id'] = 't-permalink';
+                       }
+               }
+               if ( isset( $this->data['nav_urls']['info'] ) && $this->data['nav_urls']['info'] ) {
+                       $toolbox['info'] = $this->data['nav_urls']['info'];
+                       $toolbox['info']['id'] = 't-info';
+               }
+
+               wfRunHooks( 'BaseTemplateToolbox', array( &$this, &$toolbox ) );
+               wfProfileOut( __METHOD__ );
+               return $toolbox;
+       }
+
+       /**
+        * Create an array of personal tools items from the data in the quicktemplate
+        * stored by SkinTemplate.
+        * The resulting array is built according to a format intended to be passed
+        * through makeListItem to generate the html.
+        * This is in reality the same list as already stored in personal_urls
+        * however it is reformatted so that you can just pass the individual items
+        * to makeListItem instead of hardcoding the element creation boilerplate.
+        * @return array
+        */
+       function getPersonalTools() {
+               $personal_tools = array();
+               foreach ( $this->get( 'personal_urls' ) as $key => $plink ) {
+                       # The class on a personal_urls item is meant to go on the <a> instead
+                       # of the <li> so we have to use a single item "links" array instead
+                       # of using most of the personal_url's keys directly.
+                       $ptool = array(
+                               'links' => array(
+                                       array( 'single-id' => "pt-$key" ),
+                               ),
+                               'id' => "pt-$key",
+                       );
+                       if ( isset( $plink['active'] ) ) {
+                               $ptool['active'] = $plink['active'];
+                       }
+                       foreach ( array( 'href', 'class', 'text', 'dir' ) as $k ) {
+                               if ( isset( $plink[$k] ) ) {
+                                       $ptool['links'][0][$k] = $plink[$k];
+                               }
+                       }
+                       $personal_tools[$key] = $ptool;
+               }
+               return $personal_tools;
+       }
+
+       function getSidebar( $options = array() ) {
+               // Force the rendering of the following portals
+               $sidebar = $this->data['sidebar'];
+               if ( !isset( $sidebar['SEARCH'] ) ) {
+                       $sidebar['SEARCH'] = true;
+               }
+               if ( !isset( $sidebar['TOOLBOX'] ) ) {
+                       $sidebar['TOOLBOX'] = true;
+               }
+               if ( !isset( $sidebar['LANGUAGES'] ) ) {
+                       $sidebar['LANGUAGES'] = true;
+               }
+
+               if ( !isset( $options['search'] ) || $options['search'] !== true ) {
+                       unset( $sidebar['SEARCH'] );
+               }
+               if ( isset( $options['toolbox'] ) && $options['toolbox'] === false ) {
+                       unset( $sidebar['TOOLBOX'] );
+               }
+               if ( isset( $options['languages'] ) && $options['languages'] === false ) {
+                       unset( $sidebar['LANGUAGES'] );
+               }
+
+               $boxes = array();
+               foreach ( $sidebar as $boxName => $content ) {
+                       if ( $content === false ) {
+                               continue;
+                       }
+                       switch ( $boxName ) {
+                       case 'SEARCH':
+                               // Search is a special case, skins should custom implement this
+                               $boxes[$boxName] = array(
+                                       'id' => 'p-search',
+                                       'header' => $this->getMsg( 'search' )->text(),
+                                       'generated' => false,
+                                       'content' => true,
+                               );
+                               break;
+                       case 'TOOLBOX':
+                               $msgObj = $this->getMsg( 'toolbox' );
+                               $boxes[$boxName] = array(
+                                       'id' => 'p-tb',
+                                       'header' => $msgObj->exists() ? $msgObj->text() : 'toolbox',
+                                       'generated' => false,
+                                       'content' => $this->getToolbox(),
+                               );
+                               break;
+                       case 'LANGUAGES':
+                               if ( $this->data['language_urls'] ) {
+                                       $msgObj = $this->getMsg( 'otherlanguages' );
+                                       $boxes[$boxName] = array(
+                                               'id' => 'p-lang',
+                                               'header' => $msgObj->exists() ? $msgObj->text() : 'otherlanguages',
+                                               'generated' => false,
+                                               'content' => $this->data['language_urls'],
+                                       );
+                               }
+                               break;
+                       default:
+                               $msgObj = $this->getMsg( $boxName );
+                               $boxes[$boxName] = array(
+                                       'id' => "p-$boxName",
+                                       'header' => $msgObj->exists() ? $msgObj->text() : $boxName,
+                                       'generated' => true,
+                                       'content' => $content,
+                               );
+                               break;
+                       }
+               }
+
+               // HACK: Compatibility with extensions still using SkinTemplateToolboxEnd
+               $hookContents = null;
+               if ( isset( $boxes['TOOLBOX'] ) ) {
+                       ob_start();
+                       // We pass an extra 'true' at the end so extensions using BaseTemplateToolbox
+                       // can abort and avoid outputting double toolbox links
+                       wfRunHooks( 'SkinTemplateToolboxEnd', array( &$this, true ) );
+                       $hookContents = ob_get_contents();
+                       ob_end_clean();
+                       if ( !trim( $hookContents ) ) {
+                               $hookContents = null;
+                       }
+               }
+               // END hack
+
+               if ( isset( $options['htmlOnly'] ) && $options['htmlOnly'] === true ) {
+                       foreach ( $boxes as $boxName => $box ) {
+                               if ( is_array( $box['content'] ) ) {
+                                       $content = '<ul>';
+                                       foreach ( $box['content'] as $key => $val ) {
+                                               $content .= "\n " . $this->makeListItem( $key, $val );
+                                       }
+                                       // HACK, shove the toolbox end onto the toolbox if we're rendering itself
+                                       if ( $hookContents ) {
+                                               $content .= "\n $hookContents";
+                                       }
+                                       // END hack
+                                       $content .= "\n</ul>\n";
+                                       $boxes[$boxName]['content'] = $content;
+                               }
+                       }
+               } else {
+                       if ( $hookContents ) {
+                               $boxes['TOOLBOXEND'] = array(
+                                       'id' => 'p-toolboxend',
+                                       'header' => $boxes['TOOLBOX']['header'],
+                                       'generated' => false,
+                                       'content' => "<ul>{$hookContents}</ul>",
+                               );
+                               // HACK: Make sure that TOOLBOXEND is sorted next to TOOLBOX
+                               $boxes2 = array();
+                               foreach ( $boxes as $key => $box ) {
+                                       if ( $key === 'TOOLBOXEND' ) {
+                                               continue;
+                                       }
+                                       $boxes2[$key] = $box;
+                                       if ( $key === 'TOOLBOX' ) {
+                                               $boxes2['TOOLBOXEND'] = $boxes['TOOLBOXEND'];
+                                       }
+                               }
+                               $boxes = $boxes2;
+                               // END hack
+                       }
+               }
+
+               return $boxes;
+       }
+
+       /**
+        * @param string $name
+        */
+       protected function renderAfterPortlet( $name ) {
+               $content = '';
+               wfRunHooks( 'BaseTemplateAfterPortlet', array( $this, $name, &$content ) );
+
+               if ( $content !== '' ) {
+                       echo "<div class='after-portlet after-portlet-$name'>$content</div>";
+               }
+
+       }
+
+       /**
+        * Makes a link, usually used by makeListItem to generate a link for an item
+        * in a list used in navigation lists, portlets, portals, sidebars, etc...
+        *
+        * @param string $key Usually a key from the list you are generating this
+        * link from.
+        * @param array $item Contains some of a specific set of keys.
+        *
+        * The text of the link will be generated either from the contents of the
+        * "text" key in the $item array, if a "msg" key is present a message by
+        * that name will be used, and if neither of those are set the $key will be
+        * used as a message name.
+        *
+        * If a "href" key is not present makeLink will just output htmlescaped text.
+        * The "href", "id", "class", "rel", and "type" keys are used as attributes
+        * for the link if present.
+        *
+        * If an "id" or "single-id" (if you don't want the actual id to be output
+        * on the link) is present it will be used to generate a tooltip and
+        * accesskey for the link.
+        *
+        * The keys "context" and "primary" are ignored; these keys are used
+        * internally by skins and are not supposed to be included in the HTML
+        * output.
+        *
+        * If you don't want an accesskey, set $item['tooltiponly'] = true;
+        *
+        * @param array $options Can be used to affect the output of a link.
+        * Possible options are:
+        *   - 'text-wrapper' key to specify a list of elements to wrap the text of
+        *   a link in. This should be an array of arrays containing a 'tag' and
+        *   optionally an 'attributes' key. If you only have one element you don't
+        *   need to wrap it in another array. eg: To use <a><span>...</span></a>
+        *   in all links use array( 'text-wrapper' => array( 'tag' => 'span' ) )
+        *   for your options.
+        *   - 'link-class' key can be used to specify additional classes to apply
+        *   to all links.
+        *   - 'link-fallback' can be used to specify a tag to use instead of "<a>"
+        *   if there is no link. eg: If you specify 'link-fallback' => 'span' than
+        *   any non-link will output a "<span>" instead of just text.
+        *
+        * @return string
+        */
+       function makeLink( $key, $item, $options = array() ) {
+               if ( isset( $item['text'] ) ) {
+                       $text = $item['text'];
+               } else {
+                       $text = $this->translator->translate( isset( $item['msg'] ) ? $item['msg'] : $key );
+               }
+
+               $html = htmlspecialchars( $text );
+
+               if ( isset( $options['text-wrapper'] ) ) {
+                       $wrapper = $options['text-wrapper'];
+                       if ( isset( $wrapper['tag'] ) ) {
+                               $wrapper = array( $wrapper );
+                       }
+                       while ( count( $wrapper ) > 0 ) {
+                               $element = array_pop( $wrapper );
+                               $html = Html::rawElement( $element['tag'], isset( $element['attributes'] )
+                                       ? $element['attributes']
+                                       : null, $html );
+                       }
+               }
+
+               if ( isset( $item['href'] ) || isset( $options['link-fallback'] ) ) {
+                       $attrs = $item;
+                       foreach ( array( 'single-id', 'text', 'msg', 'tooltiponly', 'context', 'primary' ) as $k ) {
+                               unset( $attrs[$k] );
+                       }
+
+                       if ( isset( $item['id'] ) && !isset( $item['single-id'] ) ) {
+                               $item['single-id'] = $item['id'];
+                       }
+                       if ( isset( $item['single-id'] ) ) {
+                               if ( isset( $item['tooltiponly'] ) && $item['tooltiponly'] ) {
+                                       $title = Linker::titleAttrib( $item['single-id'] );
+                                       if ( $title !== false ) {
+                                               $attrs['title'] = $title;
+                                       }
+                               } else {
+                                       $tip = Linker::tooltipAndAccesskeyAttribs( $item['single-id'] );
+                                       if ( isset( $tip['title'] ) && $tip['title'] !== false ) {
+                                               $attrs['title'] = $tip['title'];
+                                       }
+                                       if ( isset( $tip['accesskey'] ) && $tip['accesskey'] !== false ) {
+                                               $attrs['accesskey'] = $tip['accesskey'];
+                                       }
+                               }
+                       }
+                       if ( isset( $options['link-class'] ) ) {
+                               if ( isset( $attrs['class'] ) ) {
+                                       $attrs['class'] .= " {$options['link-class']}";
+                               } else {
+                                       $attrs['class'] = $options['link-class'];
+                               }
+                       }
+                       $html = Html::rawElement( isset( $attrs['href'] )
+                               ? 'a'
+                               : $options['link-fallback'], $attrs, $html );
+               }
+
+               return $html;
+       }
+
+       /**
+        * Generates a list item for a navigation, portlet, portal, sidebar... list
+        *
+        * @param string $key Usually a key from the list you are generating this link from.
+        * @param array $item Array of list item data containing some of a specific set of keys.
+        * The "id", "class" and "itemtitle" keys will be used as attributes for the list item,
+        * if "active" contains a value of true a "active" class will also be appended to class.
+        *
+        * @param array $options
+        *
+        * If you want something other than a "<li>" you can pass a tag name such as
+        * "tag" => "span" in the $options array to change the tag used.
+        * link/content data for the list item may come in one of two forms
+        * A "links" key may be used, in which case it should contain an array with
+        * a list of links to include inside the list item, see makeLink for the
+        * format of individual links array items.
+        *
+        * Otherwise the relevant keys from the list item $item array will be passed
+        * to makeLink instead. Note however that "id" and "class" are used by the
+        * list item directly so they will not be passed to makeLink
+        * (however the link will still support a tooltip and accesskey from it)
+        * If you need an id or class on a single link you should include a "links"
+        * array with just one link item inside of it. If you want to add a title
+        * to the list item itself, you can set "itemtitle" to the value.
+        * $options is also passed on to makeLink calls
+        *
+        * @return string
+        */
+       function makeListItem( $key, $item, $options = array() ) {
+               if ( isset( $item['links'] ) ) {
+                       $links = array();
+                       foreach ( $item['links'] as $linkKey => $link ) {
+                               $links[] = $this->makeLink( $linkKey, $link, $options );
+                       }
+                       $html = implode( ' ', $links );
+               } else {
+                       $link = $item;
+                       // These keys are used by makeListItem and shouldn't be passed on to the link
+                       foreach ( array( 'id', 'class', 'active', 'tag', 'itemtitle' ) as $k ) {
+                               unset( $link[$k] );
+                       }
+                       if ( isset( $item['id'] ) && !isset( $item['single-id'] ) ) {
+                               // The id goes on the <li> not on the <a> for single links
+                               // but makeSidebarLink still needs to know what id to use when
+                               // generating tooltips and accesskeys.
+                               $link['single-id'] = $item['id'];
+                       }
+                       $html = $this->makeLink( $key, $link, $options );
+               }
+
+               $attrs = array();
+               foreach ( array( 'id', 'class' ) as $attr ) {
+                       if ( isset( $item[$attr] ) ) {
+                               $attrs[$attr] = $item[$attr];
+                       }
+               }
+               if ( isset( $item['active'] ) && $item['active'] ) {
+                       if ( !isset( $attrs['class'] ) ) {
+                               $attrs['class'] = '';
+                       }
+                       $attrs['class'] .= ' active';
+                       $attrs['class'] = trim( $attrs['class'] );
+               }
+               if ( isset( $item['itemtitle'] ) ) {
+                       $attrs['title'] = $item['itemtitle'];
+               }
+               return Html::rawElement( isset( $options['tag'] ) ? $options['tag'] : 'li', $attrs, $html );
+       }
+
+       function makeSearchInput( $attrs = array() ) {
+               $realAttrs = array(
+                       'type' => 'search',
+                       'name' => 'search',
+                       'placeholder' => wfMessage( 'searchsuggest-search' )->text(),
+                       'value' => $this->get( 'search', '' ),
+               );
+               $realAttrs = array_merge( $realAttrs, Linker::tooltipAndAccesskeyAttribs( 'search' ), $attrs );
+               return Html::element( 'input', $realAttrs );
+       }
+
+       function makeSearchButton( $mode, $attrs = array() ) {
+               switch ( $mode ) {
+                       case 'go':
+                       case 'fulltext':
+                               $realAttrs = array(
+                                       'type' => 'submit',
+                                       'name' => $mode,
+                                       'value' => $this->translator->translate(
+                                               $mode == 'go' ? 'searcharticle' : 'searchbutton' ),
+                               );
+                               $realAttrs = array_merge(
+                                       $realAttrs,
+                                       Linker::tooltipAndAccesskeyAttribs( "search-$mode" ),
+                                       $attrs
+                               );
+                               return Html::element( 'input', $realAttrs );
+                       case 'image':
+                               $buttonAttrs = array(
+                                       'type' => 'submit',
+                                       'name' => 'button',
+                               );
+                               $buttonAttrs = array_merge(
+                                       $buttonAttrs,
+                                       Linker::tooltipAndAccesskeyAttribs( 'search-fulltext' ),
+                                       $attrs
+                               );
+                               unset( $buttonAttrs['src'] );
+                               unset( $buttonAttrs['alt'] );
+                               unset( $buttonAttrs['width'] );
+                               unset( $buttonAttrs['height'] );
+                               $imgAttrs = array(
+                                       'src' => $attrs['src'],
+                                       'alt' => isset( $attrs['alt'] )
+                                               ? $attrs['alt']
+                                               : $this->translator->translate( 'searchbutton' ),
+                                       'width' => isset( $attrs['width'] ) ? $attrs['width'] : null,
+                                       'height' => isset( $attrs['height'] ) ? $attrs['height'] : null,
+                               );
+                               return Html::rawElement( 'button', $buttonAttrs, Html::element( 'img', $imgAttrs ) );
+                       default:
+                               throw new MWException( 'Unknown mode passed to BaseTemplate::makeSearchButton' );
+               }
+       }
+
+       /**
+        * Returns an array of footerlinks trimmed down to only those footer links that
+        * are valid.
+        * If you pass "flat" as an option then the returned array will be a flat array
+        * of footer icons instead of a key/value array of footerlinks arrays broken
+        * up into categories.
+        * @param string $option
+        * @return array|mixed
+        */
+       function getFooterLinks( $option = null ) {
+               $footerlinks = $this->get( 'footerlinks' );
+
+               // Reduce footer links down to only those which are being used
+               $validFooterLinks = array();
+               foreach ( $footerlinks as $category => $links ) {
+                       $validFooterLinks[$category] = array();
+                       foreach ( $links as $link ) {
+                               if ( isset( $this->data[$link] ) && $this->data[$link] ) {
+                                       $validFooterLinks[$category][] = $link;
+                               }
+                       }
+                       if ( count( $validFooterLinks[$category] ) <= 0 ) {
+                               unset( $validFooterLinks[$category] );
+                       }
+               }
+
+               if ( $option == 'flat' ) {
+                       // fold footerlinks into a single array using a bit of trickery
+                       $validFooterLinks = call_user_func_array(
+                               'array_merge',
+                               array_values( $validFooterLinks )
+                       );
+               }
+
+               return $validFooterLinks;
+       }
+
+       /**
+        * Returns an array of footer icons filtered down by options relevant to how
+        * the skin wishes to display them.
+        * If you pass "icononly" as the option all footer icons which do not have an
+        * image icon set will be filtered out.
+        * If you pass "nocopyright" then MediaWiki's copyright icon will not be included
+        * in the list of footer icons. This is mostly useful for skins which only
+        * display the text from footericons instead of the images and don't want a
+        * duplicate copyright statement because footerlinks already rendered one.
+        * @param string $option
+        * @return string
+        */
+       function getFooterIcons( $option = null ) {
+               // Generate additional footer icons
+               $footericons = $this->get( 'footericons' );
+
+               if ( $option == 'icononly' ) {
+                       // Unset any icons which don't have an image
+                       foreach ( $footericons as &$footerIconsBlock ) {
+                               foreach ( $footerIconsBlock as $footerIconKey => $footerIcon ) {
+                                       if ( !is_string( $footerIcon ) && !isset( $footerIcon['src'] ) ) {
+                                               unset( $footerIconsBlock[$footerIconKey] );
+                                       }
+                               }
+                       }
+                       // Redo removal of any empty blocks
+                       foreach ( $footericons as $footerIconsKey => &$footerIconsBlock ) {
+                               if ( count( $footerIconsBlock ) <= 0 ) {
+                                       unset( $footericons[$footerIconsKey] );
+                               }
+                       }
+               } elseif ( $option == 'nocopyright' ) {
+                       unset( $footericons['copyright']['copyright'] );
+                       if ( count( $footericons['copyright'] ) <= 0 ) {
+                               unset( $footericons['copyright'] );
+                       }
+               }
+
+               return $footericons;
+       }
+
+       /**
+        * Output the basic end-page trail including bottomscripts, reporttime, and
+        * debug stuff. This should be called right before outputting the closing
+        * body and html tags.
+        */
+       function printTrail() { ?>
+<?php echo MWDebug::getDebugHTML( $this->getSkin()->getContext() ); ?>
+<?php $this->html( 'bottomscripts' ); /* JS call to runBodyOnloadHook */ ?>
+<?php $this->html( 'reporttime' ) ?>
+<?php
+       }
+}
index ad1ee36..c28aa86 100644 (file)
@@ -53,7 +53,8 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                $opts = $this->getOptions();
                if ( $rows === false ) {
                        if ( !$this->including() ) {
-                               $this->doHeader( $opts );
+                               $this->doHeader( $opts, 0 );
+                               $this->getOutput()->setStatusCode( 404 );
                        }
 
                        return;
@@ -290,8 +291,8 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                        ''
                );
 
-               if ( !wfRunHooks( 'ChangesListSpecialPageQuery',
-                       array( $this->getName(), &$tables, &$fields, &$conds, &$query_options, &$join_conds, $opts ) )
+               if ( !$this->runMainQueryHook( $tables, $fields, $conds, $query_options, $join_conds,
+                       $opts )
                ) {
                        return false;
                }
@@ -308,6 +309,13 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                );
        }
 
+       protected function runMainQueryHook( &$tables, &$fields, &$conds, &$query_options, &$join_conds, $opts ) {
+               return wfRunHooks(
+                       'ChangesListSpecialPageQuery',
+                       array( $this->getName(), &$tables, &$fields, &$conds, &$query_options, &$join_conds, $opts )
+               );
+       }
+
        /**
         * Return a DatabaseBase object for reading
         *
@@ -326,7 +334,7 @@ abstract class ChangesListSpecialPage extends SpecialPage {
        public function webOutput( $rows, $opts ) {
                if ( !$this->including() ) {
                        $this->outputFeedLinks();
-                       $this->doHeader( $opts );
+                       $this->doHeader( $opts, $rows->numRows() );
                }
 
                $this->outputChangesList( $rows, $opts );
@@ -348,12 +356,12 @@ abstract class ChangesListSpecialPage extends SpecialPage {
        abstract public function outputChangesList( $rows, $opts );
 
        /**
-        * Return the text to be displayed above the changes
+        * Set the text to be displayed above the changes
         *
         * @param FormOptions $opts
-        * @return string XHTML
+        * @param int $numRows Number of rows in the result to show after this header
         */
-       public function doHeader( $opts ) {
+       public function doHeader( $opts, $numRows ) {
                $this->setTopText( $opts );
 
                // @todo Lots of stuff should be done here.
@@ -402,12 +410,11 @@ abstract class ChangesListSpecialPage extends SpecialPage {
         * @return string
         */
        public static function makeLegend( IContextSource $context ) {
-               global $wgRecentChangesFlags;
                $user = $context->getUser();
                # The legend showing what the letters and stuff mean
                $legend = Html::openElement( 'dl' ) . "\n";
                # Iterates through them and gets the messages for both letter and tooltip
-               $legendItems = $wgRecentChangesFlags;
+               $legendItems = $context->getConfig()->get( 'RecentChangesFlags' );
                if ( !( $user->useRCPatrol() || $user->useNPPatrol() ) ) {
                        unset( $legendItems['unpatrolled'] );
                }
index b0266cb..272d533 100644 (file)
@@ -36,14 +36,13 @@ abstract class ImageQueryPage extends QueryPage {
         * @param OutputPage $out OutputPage to print to
         * @param Skin $skin User skin to use [unused]
         * @param DatabaseBase $dbr (read) connection to use
-        * @param int $res Result pointer
+        * @param ResultWrapper $res Result pointer
         * @param int $num Number of available result rows
         * @param int $offset Paging offset
         */
        protected function outputResults( $out, $skin, $dbr, $res, $num, $offset ) {
                if ( $num > 0 ) {
-                       $gallery = ImageGalleryBase::factory();
-                       $gallery->setContext( $this->getContext() );
+                       $gallery = ImageGalleryBase::factory( false, $this->getContext() );
 
                        # $res might contain the whole 1,000 rows, so we read up to
                        # $num [should update this to use a Pager]
index 3a83d2b..ae0003d 100644 (file)
@@ -203,8 +203,7 @@ abstract class QueryPage extends SpecialPage {
         * @return bool
         */
        function isExpensive() {
-               global $wgDisableQueryPages;
-               return $wgDisableQueryPages;
+               return $this->getConfig()->get( 'DisableQueryPages' );
        }
 
        /**
@@ -225,9 +224,7 @@ abstract class QueryPage extends SpecialPage {
         * @return bool
         */
        function isCached() {
-               global $wgMiserMode;
-
-               return $this->isExpensive() && $wgMiserMode;
+               return $this->isExpensive() && $this->getConfig()->get( 'MiserMode' );
        }
 
        /**
@@ -470,11 +467,8 @@ abstract class QueryPage extends SpecialPage {
         * This is the actual workhorse. It does everything needed to make a
         * real, honest-to-gosh query page.
         * @param string $par
-        * @return int
         */
        function execute( $par ) {
-               global $wgQueryCacheLimit, $wgDisableQueryPageUpdate;
-
                $user = $this->getUser();
                if ( !$this->userCanExecute( $user ) ) {
                        $this->displayRestrictionError();
@@ -488,7 +482,7 @@ abstract class QueryPage extends SpecialPage {
 
                if ( $this->isCached() && !$this->isCacheable() ) {
                        $out->addWikiMsg( 'querypage-disabled' );
-                       return 0;
+                       return;
                }
 
                $out->setSyndicated( $this->isSyndicated() );
@@ -509,7 +503,7 @@ abstract class QueryPage extends SpecialPage {
                                # Fetch the timestamp of this update
                                $ts = $this->getCachedTimestamp();
                                $lang = $this->getLanguage();
-                               $maxResults = $lang->formatNum( $wgQueryCacheLimit );
+                               $maxResults = $lang->formatNum( $this->getConfig()->get( 'QueryCacheLimit' ) );
 
                                if ( $ts ) {
                                        $updated = $lang->userTimeAndDate( $ts, $user );
@@ -524,8 +518,8 @@ abstract class QueryPage extends SpecialPage {
 
                                # If updates on this page have been disabled, let the user know
                                # that the data set won't be refreshed for now
-                               if ( is_array( $wgDisableQueryPageUpdate )
-                                       && in_array( $this->getName(), $wgDisableQueryPageUpdate )
+                               if ( is_array( $this->getConfig()->get( 'DisableQueryPageUpdate' ) )
+                                       && in_array( $this->getName(), $this->getConfig()->get( 'DisableQueryPageUpdate' ) )
                                ) {
                                        $out->wrapWikiMsg(
                                                "<div class=\"mw-querypage-no-updates\">\n$1\n</div>",
@@ -578,8 +572,6 @@ abstract class QueryPage extends SpecialPage {
                }
 
                $out->addHTML( Xml::closeElement( 'div' ) );
-
-               return min( $this->numRows, $this->limit ); # do not return the one extra row, if exist
        }
 
        /**
@@ -674,18 +666,17 @@ abstract class QueryPage extends SpecialPage {
         * @return bool
         */
        function doFeed( $class = '', $limit = 50 ) {
-               global $wgFeed, $wgFeedClasses, $wgFeedLimit;
-
-               if ( !$wgFeed ) {
+               if ( !$this->getConfig()->get( 'Feed' ) ) {
                        $this->getOutput()->addWikiMsg( 'feed-unavailable' );
                        return false;
                }
 
-               $limit = min( $limit, $wgFeedLimit );
+               $limit = min( $limit, $this->getConfig()->get( 'FeedLimit' ) );
 
-               if ( isset( $wgFeedClasses[$class] ) ) {
+               $feedClasses = $this->getConfig()->get( 'FeedClasses' );
+               if ( isset( $feedClasses[$class] ) ) {
                        /** @var RSSFeed|AtomFeed $feed */
-                       $feed = new $wgFeedClasses[$class](
+                       $feed = new $feedClasses[$class](
                                $this->feedTitle(),
                                $this->feedDesc(),
                                $this->feedUrl() );
@@ -746,9 +737,10 @@ abstract class QueryPage extends SpecialPage {
        }
 
        function feedTitle() {
-               global $wgLanguageCode, $wgSitename;
                $desc = $this->getDescription();
-               return "$wgSitename - $desc [$wgLanguageCode]";
+               $code = $this->getConfig()->get( 'LanguageCode' );
+               $sitename = $this->getConfig()->get( 'Sitename' );
+               return "$sitename - $desc [$code]";
        }
 
        function feedDesc() {
index cd41a1c..4226ee0 100644 (file)
@@ -71,10 +71,13 @@ abstract class RedirectSpecialPage extends UnlistedSpecialPage {
         */
        public function getRedirectQuery() {
                $params = array();
+               $request = $this->getRequest();
 
                foreach ( $this->mAllowedRedirectParams as $arg ) {
-                       if ( $this->getRequest()->getVal( $arg, null ) !== null ) {
-                               $params[$arg] = $this->getRequest()->getVal( $arg );
+                       if ( $request->getVal( $arg, null ) !== null ) {
+                               $params[$arg] = $request->getVal( $arg );
+                       } elseif ( $request->getArray( $arg, null ) !== null ) {
+                               $params[$arg] = $request->getArray( $arg );
                        }
                }
 
@@ -188,7 +191,7 @@ abstract class RedirectSpecialArticle extends RedirectSpecialPage {
                        'action',
                        'redirect', 'rdfrom',
                        # Options for preloaded edits
-                       'preload', 'editintro', 'preloadtitle', 'summary', 'nosummary',
+                       'preload', 'preloadparams', 'editintro', 'preloadtitle', 'summary', 'nosummary',
                        # Options for overriding user settings
                        'preview', 'minor', 'watchthis',
                        # Options for history/diffs
index f968276..8fc28f8 100644 (file)
@@ -27,7 +27,6 @@
  * Includes some static functions for handling the special page list deprecated
  * in favor of SpecialPageFactory.
  *
- * @todo Turn this into a real ContextSource
  * @ingroup SpecialPage
  */
 class SpecialPage {
@@ -101,8 +100,8 @@ class SpecialPage {
         * @param string $name Name of the special page, as seen in links and URLs
         * @param string $restriction User right required, e.g. "block" or "delete"
         * @param bool $listed Whether the page is listed in Special:Specialpages
-        * @param callable|bool $function unused
-        * @param string $file unused
+        * @param callable|bool $function Unused
+        * @param string $file Unused
         * @param bool $includable Whether the page can be included in normal pages
         */
        public function __construct(
@@ -134,7 +133,7 @@ class SpecialPage {
        // @todo FIXME: Decide which syntax to use for this, and stick to it
        /**
         * Whether this special page is listed in Special:SpecialPages
-        * @since r3583 (v1.3)
+        * @since 1.3 (r3583)
         * @return bool
         */
        function isListed() {
@@ -274,44 +273,20 @@ class SpecialPage {
        }
 
        /**
-        * If the user is not logged in, throws UserNotLoggedIn error.
+        * If the user is not logged in, throws UserNotLoggedIn error
         *
-        * Default error message includes a link to Special:Userlogin with properly set 'returnto' query
-        * parameter.
+        * The user will be redirected to Special:Userlogin with the given message as an error on
+        * the form.
         *
         * @since 1.23
-        * @param string|Message $reasonMsg [optional] Passed on to UserNotLoggedIn constructor. Strings
-        *     will be used as message keys. If a string is given, the message will also receive a
-        *     formatted login link (generated using the 'loginreqlink' message) as first parameter. If a
-        *     Message is given, it will be passed on verbatim.
-        * @param string|Message $titleMsg [optional] Passed on to UserNotLoggedIn constructor. Strings
-        *     will be used as message keys.
+        * @param string $reasonMsg [optional] Message key to be displayed on login page
+        * @param string $titleMsg [optional] Passed on to UserNotLoggedIn constructor
         * @throws UserNotLoggedIn
         */
-       public function requireLogin( $reasonMsg = null, $titleMsg = null ) {
+       public function requireLogin(
+               $reasonMsg = 'exception-nologin-text', $titleMsg = 'exception-nologin'
+       ) {
                if ( $this->getUser()->isAnon() ) {
-                       // Use default messages if not given or explicit null passed
-                       if ( !$reasonMsg ) {
-                               $reasonMsg = 'exception-nologin-text-manual';
-                       }
-                       if ( !$titleMsg ) {
-                               $titleMsg = 'exception-nologin';
-                       }
-
-                       // Convert to Messages with current context
-                       if ( is_string( $reasonMsg ) ) {
-                               $loginreqlink = Linker::linkKnown(
-                                       SpecialPage::getTitleFor( 'Userlogin' ),
-                                       $this->msg( 'loginreqlink' )->escaped(),
-                                       array(),
-                                       array( 'returnto' => $this->getPageTitle()->getPrefixedText() )
-                               );
-                               $reasonMsg = $this->msg( $reasonMsg )->rawParams( $loginreqlink );
-                       }
-                       if ( is_string( $titleMsg ) ) {
-                               $titleMsg = $this->msg( $titleMsg );
-                       }
-
                        throw new UserNotLoggedIn( $reasonMsg, $titleMsg );
                }
        }
@@ -328,7 +303,7 @@ class SpecialPage {
         *   - `prefixSearchSubpages( "" )` should return `array( foo", "bar", "baz" )`
         *
         * @param string $search Prefix to search for
-        * @param integer $limit Maximum number of results to return
+        * @param int $limit Maximum number of results to return
         * @return string[] Matching subpages
         */
        public function prefixSearchSubpages( $search, $limit = 10 ) {
@@ -358,6 +333,12 @@ class SpecialPage {
                $out->setArticleRelated( false );
                $out->setRobotPolicy( $this->getRobotPolicy() );
                $out->setPageTitle( $this->getDescription() );
+               if ( $this->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
+                       $out->addModuleStyles( array(
+                               'mediawiki.ui.input',
+                               'mediawiki.ui.checkbox',
+                       ) );
+               }
        }
 
        /**
@@ -621,11 +602,9 @@ class SpecialPage {
         * @param array $params
         */
        protected function addFeedLinks( $params ) {
-               global $wgFeedClasses;
-
                $feedTemplate = wfScript( 'api' );
 
-               foreach ( $wgFeedClasses as $format => $class ) {
+               foreach ( $this->getConfig()->get( 'FeedClasses' ) as $format => $class ) {
                        $theseParams = $params + array( 'feedformat' => $format );
                        $url = wfAppendQuery( $feedTemplate, $theseParams );
                        $this->getOutput()->addFeedLink( $format, $url );
@@ -641,8 +620,8 @@ class SpecialPage {
         * @since 1.21
         */
        public function getFinalGroupName() {
-               global $wgSpecialPageGroups;
                $name = $this->getName();
+               $specialPageGroups = $this->getConfig()->get( 'SpecialPageGroups' );
 
                // Allow overbidding the group from the wiki side
                $msg = $this->msg( 'specialpages-specialpagegroup-' . strtolower( $name ) )->inContentLanguage();
@@ -655,8 +634,8 @@ class SpecialPage {
                        // Group '-' is used as default to have the chance to determine,
                        // if the special pages overrides this method,
                        // if not overridden, $wgSpecialPageGroups is checked for b/c
-                       if ( $group === '-' && isset( $wgSpecialPageGroups[$name] ) ) {
-                               $group = $wgSpecialPageGroups[$name];
+                       if ( $group === '-' && isset( $specialPageGroups[$name] ) ) {
+                               $group = $specialPageGroups[$name];
                        }
                }
 
index 9ff96ab..0138cf9 100644 (file)
@@ -160,6 +160,7 @@ class SpecialPageFactory {
                'Emailuser' => 'SpecialEmailUser',
                'Movepage' => 'MovePageForm',
                'Mycontributions' => 'SpecialMycontributions',
+               'MyLanguage' => 'SpecialMyLanguage',
                'Mypage' => 'SpecialMypage',
                'Mytalk' => 'SpecialMytalk',
                'Myuploads' => 'SpecialMyuploads',
@@ -222,9 +223,6 @@ class SpecialPageFactory {
                        // This hook can be used to remove undesired built-in special pages
                        wfRunHooks( 'SpecialPage_initList', array( &self::$list ) );
 
-                       // Cast to object: func()[$key] doesn't work, but func()->$key does
-                       settype( self::$list, 'object' );
-
                        wfProfileOut( __METHOD__ );
                }
 
@@ -244,8 +242,7 @@ class SpecialPageFactory {
                        global $wgContLang;
                        $aliases = $wgContLang->getSpecialPageAliases();
 
-                       // Objects are passed by reference by default, need to create a copy
-                       $missingPages = clone self::getList();
+                       $missingPages = self::getList();
 
                        self::$aliases = array();
                        // Check for $aliases being an array since Language::getSpecialPageAliases can return null
@@ -334,7 +331,8 @@ class SpecialPageFactory {
        public static function exists( $name ) {
                list( $title, /*...*/ ) = self::resolveAlias( $name );
 
-               return property_exists( self::getList(), $title );
+               $specialPageList = self::getList();
+               return isset( $specialPageList[$title] );
        }
 
        /**
@@ -345,8 +343,9 @@ class SpecialPageFactory {
         */
        public static function getPage( $name ) {
                list( $realName, /*...*/ ) = self::resolveAlias( $name );
-               if ( property_exists( self::getList(), $realName ) ) {
-                       $rec = self::getList()->$realName;
+               $specialPageList = self::getList();
+               if ( isset( $specialPageList[$realName] ) ) {
+                       $rec = $specialPageList[$realName];
                        if ( is_string( $rec ) ) {
                                $className = $rec;
 
@@ -356,10 +355,10 @@ class SpecialPageFactory {
                                // @deprecated, officially since 1.18, unofficially since forever
                                wfDeprecated( "Array syntax for \$wgSpecialPages is deprecated ($className), " .
                                        "define a subclass of SpecialPage instead.", '1.18' );
-                               self::getList()->$realName = MWFunction::newObj( $className, $rec );
+                               $specialPageList[$realName] = MWFunction::newObj( $className, $rec );
                        }
 
-                       return self::getList()->$realName;
+                       return $specialPageList[$realName];
                } else {
                        return null;
                }
@@ -610,9 +609,9 @@ class SpecialPageFactory {
         * @return Title|null Title or null if there is no such alias
         */
        static function getTitleForAlias( $alias ) {
-               $name = self::resolveAlias( $alias );
-               if ( $name ) {
-                       return SpecialPage::getTitleFor( $name );
+               list( $name, $subpage ) = self::resolveAlias( $alias );
+               if ( $name != null ) {
+                       return SpecialPage::getTitleFor( $name, $subpage );
                } else {
                        return null;
                }
index 678c803..be2f1e8 100644 (file)
@@ -78,15 +78,9 @@ abstract class WantedQueryPage extends QueryPage {
                $title = Title::makeTitleSafe( $result->namespace, $result->title );
                if ( $title instanceof Title ) {
                        if ( $this->isCached() || $this->forceExistenceCheck() ) {
-                               $pageLink = $title->isKnown()
+                               $pageLink = $this->existenceCheck( $title )
                                        ? '<del>' . Linker::link( $title ) . '</del>'
-                                       : Linker::link(
-                                               $title,
-                                               null,
-                                               array(),
-                                               array(),
-                                               array( 'broken' )
-                                       );
+                                       : Linker::link( $title );
                        } else {
                                $pageLink = Linker::link(
                                        $title,
@@ -102,6 +96,25 @@ abstract class WantedQueryPage extends QueryPage {
                }
        }
 
+       /**
+        * Does the Title currently exists
+        *
+        * This method allows a subclass to override this check
+        * (For example, wantedfiles, would want to check if the file exists
+        * not just that a page in the file namespace exists).
+        *
+        * This will only control if the link is crossed out. Whether or not the link
+        * is blue vs red is controlled by if the title exists.
+        *
+        * @note This will only be run if the page is cached (ie $wgMiserMode = true)
+        *   unless forceExistenceCheck() is true.
+        * @since 1.24
+        * @return boolean
+        */
+       protected function existenceCheck( Title $title ) {
+               return $title->isKnown();
+       }
+
        /**
         * Make a "what links here" link for a given title
         *
index 8dc4b3c..ce43652 100644 (file)
@@ -46,17 +46,20 @@ class ActiveUsersPager extends UsersPager {
         */
        protected $hideRights = array();
 
+       /**
+        * @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 ) {
-               global $wgActiveUserDays;
-
                parent::__construct( $context );
 
-               $this->RCMaxAge = $wgActiveUserDays;
+               $this->RCMaxAge = $this->getConfig()->get( 'ActiveUserDays' );
                $un = $this->getRequest()->getText( 'username', $par );
                $this->requestedUser = '';
                if ( $un != '' ) {
@@ -192,13 +195,11 @@ class ActiveUsersPager extends UsersPager {
        }
 
        function getPageHeader() {
-               global $wgScript;
-
                $self = $this->getTitle();
                $limit = $this->mLimit ? Html::hidden( 'limit', $this->mLimit ) : '';
 
                # Form tag
-               $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) );
+               $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => wfScript() ) );
                $out .= Xml::fieldset( $this->msg( 'activeusers' )->text() ) . "\n";
                $out .= Html::hidden( 'title', $self->getPrefixedDBkey() ) . $limit . "\n";
 
@@ -247,17 +248,17 @@ class SpecialActiveUsers extends SpecialPage {
         * @param string $par Parameter passed to the page or null
         */
        public function execute( $par ) {
-               global $wgActiveUserDays;
+               $days = $this->getConfig()->get( 'ActiveUserDays' );
 
                $this->setHeaders();
                $this->outputHeader();
 
                $out = $this->getOutput();
                $out->wrapWikiMsg( "<div class='mw-activeusers-intro'>\n$1\n</div>",
-                       array( 'activeusers-intro', $this->getLanguage()->formatNum( $wgActiveUserDays ) ) );
+                       array( 'activeusers-intro', $this->getLanguage()->formatNum( $days ) ) );
 
                // Occasionally merge in new updates
-               $seconds = min( self::mergeActiveUsers( 600 ), $wgActiveUserDays * 86400 );
+               $seconds = min( self::mergeActiveUsers( 600, $days ), $days * 86400 );
                // Mention the level of staleness
                $out->addWikiMsg( 'cachedspecial-viewing-cached-ttl',
                        $this->getLanguage()->formatDuration( $seconds ) );
@@ -284,31 +285,31 @@ class SpecialActiveUsers extends SpecialPage {
        }
 
        /**
-        * @param intr $period Seconds (do updates no more often than this)
+        * @param int $period Seconds (do updates no more often than this)
+        * @param int $days How many days user must be idle before he is considered inactive
         * @return int How many seconds old the cache is
         */
-       public static function mergeActiveUsers( $period ) {
-               global $wgActiveUserDays;
-
+       public static function mergeActiveUsers( $period, $days ) {
                $dbr = wfGetDB( DB_SLAVE );
                $cTime = $dbr->selectField( 'querycache_info',
                        'qci_timestamp',
                        array( 'qci_type' => 'activeusers' )
                );
+
                if ( !wfReadOnly() ) {
                        if ( !$cTime || ( time() - wfTimestamp( TS_UNIX, $cTime ) ) > $period ) {
                                $dbw = wfGetDB( DB_MASTER );
                                if ( $dbw->estimateRowCount( 'recentchanges' ) <= 10000 ) {
-                                       $window = $wgActiveUserDays * 86400; // small wiki
+                                       $window = $days * 86400; // small wiki
                                } else {
                                        $window = $period * 2;
                                }
-                               self::doQueryCacheUpdate( $dbw, $window );
+                               $cTime = self::doQueryCacheUpdate( $dbw, $days, $window ) ?: $cTime;
                        }
                }
 
                return ( time() -
-                       ( $cTime ? wfTimestamp( TS_UNIX, $cTime ) : $wgActiveUserDays * 86400 ) );
+                       ( $cTime ? wfTimestamp( TS_UNIX, $cTime ) : $days * 86400 ) );
        }
 
        /**
@@ -318,19 +319,18 @@ class SpecialActiveUsers extends SpecialPage {
        public static function cacheUpdate( DatabaseBase $dbw ) {
                global $wgActiveUserDays;
 
-               self::doQueryCacheUpdate( $dbw, $wgActiveUserDays * 86400 );
+               self::doQueryCacheUpdate( $dbw, $wgActiveUserDays, $wgActiveUserDays * 86400 );
        }
 
        /**
         * Update the query cache as needed
         *
         * @param DatabaseBase $dbw
+        * @param int $days How many days user must be idle before he is considered inactive
         * @param int $window Maximum time range of new data to scan (in seconds)
-        * @return bool Success
+        * @return int|bool UNIX timestamp the cache is now up-to-date as of (false on error)
         */
-       protected static function doQueryCacheUpdate( DatabaseBase $dbw, $window ) {
-               global $wgActiveUserDays;
-
+       protected static function doQueryCacheUpdate( DatabaseBase $dbw, $days, $window ) {
                $lockKey = wfWikiID() . '-activeusers';
                if ( !$dbw->lock( $lockKey, __METHOD__, 1 ) ) {
                        return false; // exclusive update (avoids duplicate entries)
@@ -346,7 +346,7 @@ class SpecialActiveUsers extends SpecialPage {
                // Pick the date range to fetch from. This is normally from the last
                // update to till the present time, but has a limited window for sanity.
                // If the window is limited, multiple runs are need to fully populate it.
-               $sTimestamp = max( $cTimeUnix, $now - $wgActiveUserDays * 86400 );
+               $sTimestamp = max( $cTimeUnix, $now - $days * 86400 );
                $eTimestamp = min( $sTimestamp + $window, $now );
 
                // Get all the users active since the last update
@@ -375,7 +375,7 @@ class SpecialActiveUsers extends SpecialPage {
                $dbw->delete( 'querycachetwo',
                        array(
                                'qcc_type' => 'activeusers',
-                               'qcc_value < ' . $dbw->addQuotes( $now - $wgActiveUserDays * 86400 ) // TS_UNIX
+                               'qcc_value < ' . $dbw->addQuotes( $now - $days * 86400 ) // TS_UNIX
                        ),
                        __METHOD__
                );
@@ -410,7 +410,9 @@ class SpecialActiveUsers extends SpecialPage {
                        }
                        foreach ( array_chunk( $newRows, 500 ) as $rowBatch ) {
                                $dbw->insert( 'querycachetwo', $rowBatch, __METHOD__ );
-                               wfWaitForSlaves();
+                               if ( !$dbw->trxLevel() ) {
+                                       wfWaitForSlaves();
+                               }
                        }
                }
 
@@ -424,6 +426,6 @@ class SpecialActiveUsers extends SpecialPage {
 
                $dbw->unlock( $lockKey, __METHOD__ );
 
-               return true;
+               return $eTimestamp;
        }
 }
index 1e4e18b..96be4d0 100644 (file)
@@ -68,10 +68,8 @@ class SpecialAllMessages extends SpecialPage {
 
                $this->langcode = $this->table->lang->getCode();
 
-               $out->addHTML( $this->table->buildForm() .
-                       $this->table->getNavigationBar() .
-                       $this->table->getBody() .
-                       $this->table->getNavigationBar() );
+               $out->addHTML( $this->table->buildForm() );
+               $out->addParserOutputContent( $this->table->getFullOutput() );
        }
 
        protected function getGroupName() {
@@ -103,7 +101,8 @@ class AllMessagesTablePager extends TablePager {
                $this->mIndexField = 'am_title';
                $this->mPage = $page;
                $this->mConds = $conds;
-               $this->mDefaultDirection = true; // always sort ascending
+               // FIXME: Why does this need to be set to DIR_DESCENDING to produce ascending ordering?
+               $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
                $this->mLimitsShown = array( 20, 50, 100, 250, 500, 5000 );
 
                global $wgContLang;
@@ -336,8 +335,9 @@ class AllMessagesTablePager extends TablePager {
        }
 
        function getStartBody() {
+               $tableClass = $this->getTableClass();
                return Xml::openElement( 'table', array(
-                               'class' => 'mw-datatable TablePager',
+                               'class' => "mw-datatable $tableClass",
                                'id' => 'mw-allmessagestable'
                        ) ) .
                        "\n" .
index e4b606d..c8fae68 100644 (file)
@@ -45,7 +45,7 @@ class SpecialAllPages extends IncludableSpecialPage {
        /**
         * Constructor
         *
-        * @param string $name name of the special page, as seen in links and URLs (default: 'Allpages')
+        * @param string $name Name of the special page, as seen in links and URLs (default: 'Allpages')
         */
        function __construct( $name = 'Allpages' ) {
                parent::__construct( $name );
@@ -54,7 +54,7 @@ class SpecialAllPages extends IncludableSpecialPage {
        /**
         * Entry point : initialise variables and call subfunctions.
         *
-        * @param string $par becomes "FOO" when called like Special:Allpages/FOO (default null)
+        * @param string $par Becomes "FOO" when called like Special:Allpages/FOO (default null)
         */
        function execute( $par ) {
                $request = $this->getRequest();
@@ -213,32 +213,20 @@ class SpecialAllPages extends IncludableSpecialPage {
                        );
 
                        if ( $res->numRows() > 0 ) {
-                               $out = Xml::openElement( 'table', array( 'class' => 'mw-allpages-table-chunk' ) );
+                               $out = Xml::openElement( 'ul', array( 'class' => 'mw-allpages-chunk' ) );
                                while ( ( $n < $this->maxPerPage ) && ( $s = $res->fetchObject() ) ) {
                                        $t = Title::newFromRow( $s );
                                        if ( $t ) {
-                                               $link = ( $s->page_is_redirect ? '<div class="allpagesredirect">' : '' ) .
+                                               $out .= '<li' .
+                                                       ( $s->page_is_redirect ? ' class="allpagesredirect"' : '' ) .
+                                                       '>' .
                                                        Linker::link( $t ) .
-                                                       ( $s->page_is_redirect ? '</div>' : '' );
+                                                       "</li>\n";
                                        } else {
-                                               $link = '[[' . htmlspecialchars( $s->page_title ) . ']]';
+                                               $out .= '<li>[[' . htmlspecialchars( $s->page_title ) . "]]</li>\n";
                                        }
-
-                                       if ( $n % 3 == 0 ) {
-                                               $out .= '<tr>';
-                                       }
-
-                                       $out .= "<td style=\"width:33%\">$link</td>";
-                                       $n++;
-                                       if ( $n % 3 == 0 ) {
-                                               $out .= "</tr>\n";
-                                       }
-                               }
-
-                               if ( ( $n % 3 ) != 0 ) {
-                                       $out .= "</tr>\n";
                                }
-                               $out .= Xml::closeElement( 'table' );
+                               $out .= Xml::closeElement( 'ul' );
                        } else {
                                $out = '';
                        }
index 8c46a93..3297c17 100644 (file)
@@ -28,7 +28,7 @@
  * @ingroup SpecialPage
  */
 class SpecialBlock extends FormSpecialPage {
-       /** @var User user to be blocked, as passed either by parameter (url?wpTarget=Foo)
+       /** @var User User to be blocked, as passed either by parameter (url?wpTarget=Foo)
         * or as subpage (Special:Block/Foo) */
        protected $target;
 
@@ -454,7 +454,7 @@ class SpecialBlock extends FormSpecialPage {
        /**
         * Determine the target of the block, and the type of target
         * @todo Should be in Block.php?
-        * @param string $par subpage parameter passed to setup, or data value from
+        * @param string $par Subpage parameter passed to setup, or data value from
         *     the HTMLForm
         * @param WebRequest $request Optionally try and get data from a request too
         * @return array( User|string|null, Block::TYPE_ constant|null )
@@ -600,7 +600,7 @@ class SpecialBlock extends FormSpecialPage {
         * @return bool|string
         */
        public static function processForm( array $data, IContextSource $context ) {
-               global $wgBlockAllowsUTEdit, $wgHideUserContribLimit;
+               global $wgBlockAllowsUTEdit, $wgHideUserContribLimit, $wgContLang;
 
                $performer = $context->getUser();
 
@@ -687,7 +687,8 @@ class SpecialBlock extends FormSpecialPage {
                $block = new Block();
                $block->setTarget( $target );
                $block->setBlocker( $performer );
-               $block->mReason = $data['Reason'][0];
+               # Truncate reason for whole multibyte characters
+               $block->mReason = $wgContLang->truncate( $data['Reason'][0], 255 );
                $block->mExpiry = self::parseExpiryInput( $data['Expiry'] );
                $block->prevents( 'createaccount', $data['CreateAccount'] );
                $block->prevents( 'editownusertalk', ( !$wgBlockAllowsUTEdit || $data['DisableUTEdit'] ) );
index 9170e3e..456f4ec 100644 (file)
@@ -84,7 +84,7 @@ class SpecialBlockList extends SpecialPage {
                                'flatlist' => true,
                        ),
                        'Limit' => array(
-                               'class' => 'HTMLBlockedUsersItemSelect',
+                               'type' => 'limitselect',
                                'label-message' => 'table_pager_limit_label',
                                'options' => array(
                                        $lang->formatNum( 20 ) => 20,
@@ -181,11 +181,7 @@ class SpecialBlockList extends SpecialPage {
 
                $pager = new BlockListPager( $this, $conds );
                if ( $pager->getNumRows() ) {
-                       $out->addHTML(
-                               $pager->getNavigationBar() .
-                                       $pager->getBody() .
-                                       $pager->getNavigationBar()
-                       );
+                       $out->addParserOutputContent( $pager->getFullOutput() );
                } elseif ( $this->target ) {
                        $out->addWikiMsg( 'ipblocklist-no-results' );
                } else {
@@ -228,7 +224,7 @@ class BlockListPager extends TablePager {
        function __construct( $page, $conds ) {
                $this->page = $page;
                $this->conds = $conds;
-               $this->mDefaultDirection = true;
+               $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
                parent::__construct( $page->getContext() );
        }
 
@@ -409,7 +405,7 @@ class BlockListPager extends TablePager {
        }
 
        public function getTableClass() {
-               return 'TablePager mw-blocklist';
+               return parent::getTableClass() . ' mw-blocklist';
        }
 
        function getIndexField() {
@@ -457,37 +453,3 @@ class BlockListPager extends TablePager {
                wfProfileOut( __METHOD__ );
        }
 }
-
-/**
- * Items per page dropdown. Essentially a crap workaround for bug 32603.
- */
-class HTMLBlockedUsersItemSelect extends HTMLSelectField {
-       /**
-        * Basically don't do any validation. If it's a number that's fine. Also,
-        * add it to the list if it's not there already
-        *
-        * @param string $value
-        * @param array $alldata
-        * @return bool
-        */
-       function validate( $value, $alldata ) {
-               if ( $value == '' ) {
-                       return true;
-               }
-
-               // Let folks pick an explicit limit not from our list, as long as it's a real numbr.
-               if ( !in_array( $value, $this->mParams['options'] )
-                       && $value == intval( $value )
-                       && $value > 0
-               ) {
-                       // This adds the explicitly requested limit value to the drop-down,
-                       // then makes sure it's sorted correctly so when we output the list
-                       // later, the custom option doesn't just show up last.
-                       $this->mParams['options'][$this->mParent->getLanguage()->formatNum( $value )] =
-                               intval( $value );
-                       asort( $this->mParams['options'] );
-               }
-
-               return true;
-       }
-}
index 581619f..72f4e46 100644 (file)
@@ -117,15 +117,13 @@ class SpecialBookSources extends SpecialPage {
         * @return string
         */
        private function makeForm() {
-               global $wgScript;
-
                $form = Html::openElement( 'fieldset' ) . "\n";
                $form .= Html::element(
                        'legend',
                        array(),
                        $this->msg( 'booksources-search-legend' )->text()
                ) . "\n";
-               $form .= Html::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) . "\n";
+               $form .= Html::openElement( 'form', array( 'method' => 'get', 'action' => wfScript() ) ) . "\n";
                $form .= Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ) . "\n";
                $form .= '<p>' . Xml::inputLabel(
                        $this->msg( 'booksources-isbn' )->text(),
index 734544d..95f9efd 100644 (file)
@@ -43,7 +43,7 @@ class SpecialCategories extends SpecialPage {
         * Initialize or override the PageLinkRenderer SpecialCategories collaborates with.
         * Useful mainly for testing.
         *
-        * @todo: the pager should also be injected, and de-coupled from the rendering logic.
+        * @todo the pager should also be injected, and de-coupled from the rendering logic.
         *
         * @param PageLinkRenderer $linkRenderer
         */
@@ -180,11 +180,9 @@ class CategoryPager extends AlphabeticPager {
        }
 
        public function getStartForm( $from ) {
-               global $wgScript;
-
                return Xml::tags(
                        'form',
-                       array( 'method' => 'get', 'action' => $wgScript ),
+                       array( 'method' => 'get', 'action' => wfScript() ),
                        Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
                                Xml::fieldset(
                                        $this->msg( 'categories' )->text(),
index c57e33b..a3b02f5 100644 (file)
  *
  * @ingroup SpecialPage
  */
-class SpecialChangeEmail extends UnlistedSpecialPage {
+class SpecialChangeEmail extends FormSpecialPage {
        /**
-        * Users password
-        * @var string
+        * @var Status
         */
-       protected $mPassword;
-
-       /**
-        * Users new email address
-        * @var string
-        */
-       protected $mNewEmail;
+       private $status;
 
        public function __construct() {
                parent::__construct( 'ChangeEmail', 'editmyprivateinfo' );
@@ -57,197 +50,130 @@ class SpecialChangeEmail extends UnlistedSpecialPage {
         * @param string $par
         */
        function execute( $par ) {
-               global $wgAuth;
-
-               $this->setHeaders();
-               $this->outputHeader();
-
                $out = $this->getOutput();
                $out->disallowUserJs();
                $out->addModules( 'mediawiki.special.changeemail' );
 
-               if ( !$wgAuth->allowPropChange( 'emailaddress' ) ) {
-                       $this->error( 'cannotchangeemail' );
-
-                       return;
-               }
-
-               $user = $this->getUser();
-               $request = $this->getRequest();
-
-               $this->requireLogin( 'changeemail-no-info' );
+               return parent::execute( $par );
+       }
 
-               if ( $request->wasPosted() && $request->getBool( 'wpCancel' ) ) {
-                       $this->doReturnTo();
+       protected function checkExecutePermissions( User $user ) {
+               global $wgAuth;
 
-                       return;
+               if ( !$wgAuth->allowPropChange( 'emailaddress' ) ) {
+                       throw new ErrorPageError( 'changeemail', 'cannotchangeemail' );
                }
 
-               $this->checkReadOnly();
-               $this->checkPermissions();
+               $this->requireLogin( 'changeemail-no-info' );
 
                // This could also let someone check the current email address, so
                // require both permissions.
-               if ( !$user->isAllowed( 'viewmyprivateinfo' ) ) {
+               if ( !$this->getUser()->isAllowed( 'viewmyprivateinfo' ) ) {
                        throw new PermissionsError( 'viewmyprivateinfo' );
                }
 
-               $this->mPassword = $request->getVal( 'wpPassword' );
-               $this->mNewEmail = $request->getVal( 'wpNewEmail' );
+               parent::checkExecutePermissions( $user );
+       }
 
-               if ( $request->wasPosted()
-                       && $user->matchEditToken( $request->getVal( 'token' ) )
-               ) {
-                       $info = $this->attemptChange( $user, $this->mPassword, $this->mNewEmail );
-                       if ( $info === true ) {
-                               $this->doReturnTo();
-                       } elseif ( $info === 'eauth' ) {
-                               # Notify user that a confirmation email has been sent...
-                               $out->wrapWikiMsg( "<div class='error' style='clear: both;'>\n$1\n</div>",
-                                       'eauthentsent', $user->getName() );
-                               $this->doReturnTo( 'soft' ); // just show the link to go back
-                               return; // skip form
-                       }
-               }
+       protected function getFormFields() {
+               $user = $this->getUser();
 
-               $this->showForm();
-       }
+               $fields = array(
+                       'Name' => array(
+                               'type' => 'info',
+                               'label-message' => 'username',
+                               'default' => $user->getName(),
+                       ),
+                       'OldEmail' => array(
+                               'type' => 'info',
+                               'label-message' => 'changeemail-oldemail',
+                               'default' => $user->getEmail() ?: $this->msg( 'changeemail-none' )->text(),
+                       ),
+                       'NewEmail' => array(
+                               'type' => 'email',
+                               'label-message' => 'changeemail-newemail',
+                       ),
+               );
 
-       /**
-        * @param string $type
-        */
-       protected function doReturnTo( $type = 'hard' ) {
-               $titleObj = Title::newFromText( $this->getRequest()->getVal( 'returnto' ) );
-               if ( !$titleObj instanceof Title ) {
-                       $titleObj = Title::newMainPage();
+               if ( $this->getConfig()->get( 'RequirePasswordforEmailChange' ) ) {
+                       $fields['Password'] = array(
+                               'type' => 'password',
+                               'label-message' => 'changeemail-password',
+                               'autofocus' => true,
+                       );
                }
-               if ( $type == 'hard' ) {
-                       $this->getOutput()->redirect( $titleObj->getFullURL() );
-               } else {
-                       $this->getOutput()->addReturnTo( $titleObj );
-               }
-       }
 
-       /**
-        * @param string $msg
-        */
-       protected function error( $msg ) {
-               $this->getOutput()->wrapWikiMsg( "<p class='error'>\n$1\n</p>", $msg );
+               return $fields;
        }
 
-       protected function showForm() {
-               global $wgRequirePasswordforEmailChange;
-               $user = $this->getUser();
-
-               $oldEmailText = $user->getEmail()
-                       ? $user->getEmail()
-                       : $this->msg( 'changeemail-none' )->text();
-
-               $this->getOutput()->addHTML(
-                       Xml::fieldset( $this->msg( 'changeemail-header' )->text() ) .
-                               Xml::openElement( 'form',
-                                       array(
-                                               'method' => 'post',
-                                               'action' => $this->getPageTitle()->getLocalURL(),
-                                               'id' => 'mw-changeemail-form' ) ) . "\n" .
-                               Html::hidden( 'token', $user->getEditToken() ) . "\n" .
-                               Html::hidden( 'returnto', $this->getRequest()->getVal( 'returnto' ) ) . "\n" .
-                               $this->msg( 'changeemail-text' )->parseAsBlock() . "\n" .
-                               Xml::openElement( 'table', array( 'id' => 'mw-changeemail-table' ) ) . "\n"
-               );
-               $items = array(
-                       array( 'wpName', 'username', 'text', $user->getName() ),
-                       array( 'wpOldEmail', 'changeemail-oldemail', 'text', $oldEmailText ),
-                       array( 'wpNewEmail', 'changeemail-newemail', 'email', $this->mNewEmail ),
+       protected function alterForm( HTMLForm $form ) {
+               $form->setId( 'mw-changeemail-form' );
+               $form->setTableId( 'mw-changeemail-table' );
+               $form->setWrapperLegendMsg( 'changeemail-header' );
+               $form->setSubmitTextMsg( 'changeemail-submit' );
+               $form->addButton( 'wpCancel', $this->msg( 'changeemail-cancel' )->text(),
+                       null, array( 'formnovalidate')
                );
-               if ( $wgRequirePasswordforEmailChange ) {
-                       $items[] = array( 'wpPassword', 'changeemail-password', 'password', $this->mPassword );
+               $form->addHiddenField( 'returnto', $this->getRequest()->getVal( 'returnto' ) );
+       }
+
+       public function onSubmit( array $data ) {
+               if ( $this->getRequest()->getBool( 'wpCancel' ) ) {
+                       $status = Status::newGood( true );
+               } else {
+                       $password = isset( $data['Password'] ) ? $data['Password'] : null;
+                       $status = $this->attemptChange( $this->getUser(), $password, $data['NewEmail'] );
                }
 
-               $this->getOutput()->addHTML(
-                       $this->pretty( $items ) .
-                               "\n" .
-                               "<tr>\n" .
-                               "<td></td>\n" .
-                               '<td class="mw-input">' .
-                               Xml::submitButton( $this->msg( 'changeemail-submit' )->text() ) .
-                               Xml::submitButton( $this->msg( 'changeemail-cancel' )->text(), array( 'name' => 'wpCancel' ) ) .
-                               "</td>\n" .
-                               "</tr>\n" .
-                               Xml::closeElement( 'table' ) .
-                               Xml::closeElement( 'form' ) .
-                               Xml::closeElement( 'fieldset' ) . "\n"
-               );
+               $this->status = $status;
+
+               return $status;
        }
 
-       /**
-        * @param array $fields
-        * @return string
-        */
-       protected function pretty( $fields ) {
-               $out = '';
-               foreach ( $fields as $list ) {
-                       list( $name, $label, $type, $value ) = $list;
-                       if ( $type == 'text' ) {
-                               $field = htmlspecialchars( $value );
-                       } else {
-                               $attribs = array( 'id' => $name );
-                               if ( $name == 'wpPassword' ) {
-                                       $attribs[] = 'autofocus';
-                               }
-                               $field = Html::input( $name, $value, $type, $attribs );
-                       }
-                       $out .= "<tr>\n";
-                       $out .= "\t<td class='mw-label'>";
-                       if ( $type != 'text' ) {
-                               $out .= Xml::label( $this->msg( $label )->text(), $name );
-                       } else {
-                               $out .= $this->msg( $label )->escaped();
-                       }
-                       $out .= "</td>\n";
-                       $out .= "\t<td class='mw-input'>";
-                       $out .= $field;
-                       $out .= "</td>\n";
-                       $out .= "</tr>";
+       public function onSuccess() {
+               $titleObj = Title::newFromText( $this->getRequest()->getVal( 'returnto' ) );
+               if ( !$titleObj instanceof Title ) {
+                       $titleObj = Title::newMainPage();
                }
 
-               return $out;
+               if ( $this->status->value === true ) {
+                       $this->getOutput()->redirect( $titleObj->getFullURL() );
+               } elseif ( $this->status->value === 'eauth' ) {
+                       # Notify user that a confirmation email has been sent...
+                       $this->getOutput()->wrapWikiMsg( "<div class='error' style='clear: both;'>\n$1\n</div>",
+                               'eauthentsent', $this->getUser()->getName() );
+                       $this->getOutput()->addReturnTo( $titleObj ); // just show the link to go back
+               }
        }
 
        /**
         * @param User $user
         * @param string $pass
         * @param string $newaddr
-        * @return bool|string True or string on success, false on failure
+        * @return Status
         */
        protected function attemptChange( User $user, $pass, $newaddr ) {
-               global $wgAuth, $wgPasswordAttemptThrottle;
+               global $wgAuth;
 
                if ( $newaddr != '' && !Sanitizer::validateEmail( $newaddr ) ) {
-                       $this->error( 'invalidemailaddress' );
-
-                       return false;
+                       return Status::newFatal( 'invalidemailaddress' );
                }
 
                $throttleCount = LoginForm::incLoginThrottle( $user->getName() );
                if ( $throttleCount === true ) {
                        $lang = $this->getLanguage();
-                       $this->error( array(
+                       $throttleInfo = $this->getConfig()->get( 'PasswordAttemptThrottle' );
+                       return Status::newFatal(
                                'changeemail-throttled',
-                               $lang->formatDuration( $wgPasswordAttemptThrottle['seconds'] )
-                       ) );
-
-                       return false;
+                               $lang->formatDuration( $throttleInfo['seconds'] )
+                       );
                }
 
-               global $wgRequirePasswordforEmailChange;
-               if ( $wgRequirePasswordforEmailChange
+               if ( $this->getConfig()->get( 'RequirePasswordforEmailChange' )
                        && !$user->checkTemporaryPassword( $pass )
                        && !$user->checkPassword( $pass )
                ) {
-                       $this->error( 'wrongpassword' );
-
-                       return false;
+                       return Status::newFatal( 'wrongpassword' );
                }
 
                if ( $throttleCount ) {
@@ -257,12 +183,7 @@ class SpecialChangeEmail extends UnlistedSpecialPage {
                $oldaddr = $user->getEmail();
                $status = $user->setEmailWithConfirmation( $newaddr );
                if ( !$status->isGood() ) {
-                       $this->getOutput()->addHTML(
-                               '<p class="error">' .
-                                       $this->getOutput()->parseInline( $status->getWikiText( 'mailerror' ) ) .
-                                       '</p>' );
-
-                       return false;
+                       return $status;
                }
 
                wfRunHooks( 'PrefsEmailAudit', array( $user, $oldaddr, $newaddr ) );
@@ -271,7 +192,11 @@ class SpecialChangeEmail extends UnlistedSpecialPage {
 
                $wgAuth->updateExternalDB( $user );
 
-               return $status->value;
+               return $status;
+       }
+
+       public function requiresUnblock() {
+               return false;
        }
 
        protected function getGroupName() {
index dcd2443..24664ed 100644 (file)
@@ -43,6 +43,7 @@ class SpecialChangePassword extends FormSpecialPage {
 
        /**
         * Main execution point
+        * @param string|null $par
         */
        function execute( $par ) {
                $this->getOutput()->disallowUserJs();
@@ -61,7 +62,7 @@ class SpecialChangePassword extends FormSpecialPage {
        /**
         * Set a message at the top of the Change Password form
         * @since 1.23
-        * @param Message $msg to parse and add to the form header
+        * @param Message $msg Message to parse and add to the form header
         */
        public function setChangeMessage( Message $msg ) {
                $this->mPreTextMessage = $msg;
@@ -77,8 +78,6 @@ class SpecialChangePassword extends FormSpecialPage {
        }
 
        protected function getFormFields() {
-               global $wgCookieExpiration;
-
                $user = $this->getUser();
                $request = $this->getRequest();
 
@@ -134,8 +133,9 @@ class SpecialChangePassword extends FormSpecialPage {
                        $fields['Remember'] = array(
                                'type' => 'check',
                                'label' => $this->msg( 'remembermypassword' )
-                                               ->numParams( ceil( $wgCookieExpiration / ( 3600 * 24 ) ) )
-                                               ->text(),
+                                               ->numParams(
+                                                       ceil( $this->getConfig()->get( 'CookieExpiration' ) / ( 3600 * 24 ) )
+                                               )->text(),
                                'default' => $request->getVal( 'wpRemember' ),
                        );
                }
@@ -230,11 +230,12 @@ class SpecialChangePassword extends FormSpecialPage {
        }
 
        /**
-        * @throws PasswordError when cannot set the new password because requirements not met.
+        * @param string $oldpass
+        * @param string $newpass
+        * @param string $retype
+        * @throws PasswordError When cannot set the new password because requirements not met.
         */
        protected function attemptReset( $oldpass, $newpass, $retype ) {
-               global $wgPasswordAttemptThrottle;
-
                $isSelf = ( $this->mUserName === $this->getUser()->getName() );
                if ( $isSelf ) {
                        $user = $this->getUser();
@@ -254,13 +255,14 @@ class SpecialChangePassword extends FormSpecialPage {
                $throttleCount = LoginForm::incLoginThrottle( $this->mUserName );
                if ( $throttleCount === true ) {
                        $lang = $this->getLanguage();
+                       $throttleInfo = $this->getConfig()->get( 'PasswordAttemptThrottle' );
                        throw new PasswordError( $this->msg( 'changepassword-throttled' )
-                               ->params( $lang->formatDuration( $wgPasswordAttemptThrottle['seconds'] ) )
+                               ->params( $lang->formatDuration( $throttleInfo['seconds'] ) )
                                ->text()
                        );
                }
 
-               // @TODO Make these separate messages, since the message is written for both cases
+               // @todo Make these separate messages, since the message is written for both cases
                if ( !$user->checkTemporaryPassword( $oldpass ) && !$user->checkPassword( $oldpass ) ) {
                        wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'wrongpassword' ) );
                        throw new PasswordError( $this->msg( 'resetpass-wrong-oldpass' )->text() );
index 05bbb5a..32a887c 100644 (file)
@@ -163,7 +163,7 @@ class SpecialContributions extends IncludableSpecialPage {
                }
 
                if ( $feedType ) {
-                       // Maintain some level of backwards compatability
+                       // Maintain some level of backwards compatibility
                        // If people request feeds using the old parameters, redirect to API
                        $feedParams['feedformat'] = $feedType;
                        $url = wfAppendQuery( wfScript( 'api' ), $feedParams );
@@ -206,7 +206,7 @@ class SpecialContributions extends IncludableSpecialPage {
                                $output = $pager->getBody();
                                if ( !$this->including() ) {
                                        $output = '<p>' . $pager->getNavigationBar() . '</p>' .
-                                               $output.
+                                               $output .
                                                '<p>' . $pager->getNavigationBar() . '</p>';
                                }
                                $out->addHTML( $output );
@@ -255,6 +255,9 @@ class SpecialContributions extends IncludableSpecialPage {
                                                wfEscapeWikiText( $userObj->getName() ),
                                        )
                                );
+                               if ( !$this->including() ) {
+                                       $this->getOutput()->setStatusCode( 404 );
+                               }
                        }
                        $user = htmlspecialchars( $userObj->getName() );
                } else {
@@ -393,8 +396,6 @@ class SpecialContributions extends IncludableSpecialPage {
         * @return string HTML fragment
         */
        protected function getForm() {
-               global $wgScript;
-
                $this->opts['title'] = $this->getPageTitle()->getPrefixedText();
                if ( !isset( $this->opts['target'] ) ) {
                        $this->opts['target'] = '';
@@ -446,7 +447,7 @@ class SpecialContributions extends IncludableSpecialPage {
                        'form',
                        array(
                                'method' => 'get',
-                               'action' => $wgScript,
+                               'action' => wfScript(),
                                'class' => 'mw-contributions-form'
                        )
                );
@@ -651,7 +652,7 @@ class SpecialContributions extends IncludableSpecialPage {
  * @ingroup SpecialPage Pager
  */
 class ContribsPager extends ReverseChronologicalPager {
-       public $mDefaultDirection = true;
+       public $mDefaultDirection = IndexPager::DIR_DESCENDING;
        public $messages;
        public $target;
        public $namespace = '';
@@ -790,7 +791,7 @@ class ContribsPager extends ReverseChronologicalPager {
                // Paranoia: avoid brute force searches (bug 17342)
                if ( !$user->isAllowed( 'deletedhistory' ) ) {
                        $conds[] = $this->mDb->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0';
-               } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                        $conds[] = $this->mDb->bitAnd( 'rev_deleted', Revision::SUPPRESSED_USER ) .
                                ' != ' . Revision::SUPPRESSED_USER;
                }
index 4df5b2b..68f2c46 100644 (file)
@@ -26,7 +26,7 @@
  * @ingroup SpecialPage
  */
 class DeletedContribsPager extends IndexPager {
-       public $mDefaultDirection = true;
+       public $mDefaultDirection = IndexPager::DIR_DESCENDING;
        public $messages;
        public $target;
        public $namespace = '';
@@ -62,7 +62,7 @@ class DeletedContribsPager extends IndexPager {
                // Paranoia: avoid brute force searches (bug 17792)
                if ( !$user->isAllowed( 'deletedhistory' ) ) {
                        $conds[] = $this->mDb->bitAnd( 'ar_deleted', Revision::DELETED_USER ) . ' = 0';
-               } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                        $conds[] = $this->mDb->bitAnd( 'ar_deleted', Revision::SUPPRESSED_USER ) .
                                ' != ' . Revision::SUPPRESSED_USER;
                }
@@ -286,8 +286,6 @@ class DeletedContributionsPage extends SpecialPage {
         * @param string $par (optional) user name of the user for which to show the contributions
         */
        function execute( $par ) {
-               global $wgQueryPageDefaultLimit;
-
                $this->setHeaders();
                $this->outputHeader();
 
@@ -317,7 +315,7 @@ class DeletedContributionsPage extends SpecialPage {
                        return;
                }
 
-               $options['limit'] = $request->getInt( 'limit', $wgQueryPageDefaultLimit );
+               $options['limit'] = $request->getInt( 'limit', $this->getConfig()->get( 'QueryPageDefaultLimit' ) );
                $options['target'] = $target;
 
                $userObj = User::newFromName( $target, false );
@@ -507,8 +505,6 @@ class DeletedContributionsPage extends SpecialPage {
         * @return string
         */
        function getForm( $options ) {
-               global $wgScript;
-
                $options['title'] = $this->getPageTitle()->getPrefixedText();
                if ( !isset( $options['target'] ) ) {
                        $options['target'] = '';
@@ -528,7 +524,7 @@ class DeletedContributionsPage extends SpecialPage {
                        $options['target'] = '';
                }
 
-               $f = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) );
+               $f = Xml::openElement( 'form', array( 'method' => 'get', 'action' => wfScript() ) );
 
                foreach ( $options as $name => $value ) {
                        if ( in_array( $name, array( 'namespace', 'target', 'contribs' ) ) ) {
index 369f11f..3656b9c 100644 (file)
@@ -70,9 +70,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                $this->checkReadOnly();
 
                $this->outputHeader();
-
-               $out->addSubtitle( $this->msg( 'watchlistfor2', $this->getUser()->getName() )
-                       ->rawParams( SpecialEditWatchlist::buildTools( null ) ) );
+               $this->outputSubtitle();
 
                # B/C: $mode used to be waaay down the parameter list, and the first parameter
                # was $wgUser
@@ -104,24 +102,42 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
 
                        case self::EDIT_NORMAL:
                        default:
-                               $out->setPageTitle( $this->msg( 'watchlistedit-normal-title' ) );
-                               $form = $this->getNormalForm();
-                               if ( $form->show() ) {
-                                       $out->addHTML( $this->successMessage );
-                                       $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) );
-                               } elseif ( $this->toc !== false ) {
-                                       $out->prependHTML( $this->toc );
-                                       $out->addModules( 'mediawiki.toc' );
-                               }
+                       $this->executeViewEditWatchlist();
                                break;
                }
        }
 
+       /**
+        * Renders a subheader on the watchlist page.
+        */
+       protected function outputSubtitle() {
+               $out = $this->getOutput();
+               $out->addSubtitle( $this->msg( 'watchlistfor2', $this->getUser()->getName() )
+                       ->rawParams( SpecialEditWatchlist::buildTools( null ) ) );
+       }
+
+       /**
+        * Executes an edit mode for the watchlist view, from which you can manage your watchlist
+        *
+        */
+       protected function executeViewEditWatchlist() {
+               $out = $this->getOutput();
+               $out->setPageTitle( $this->msg( 'watchlistedit-normal-title' ) );
+               $form = $this->getNormalForm();
+               if ( $form->show() ) {
+                       $out->addHTML( $this->successMessage );
+                       $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) );
+               } elseif ( $this->toc !== false ) {
+                       $out->prependHTML( $this->toc );
+                       $out->addModules( 'mediawiki.toc' );
+               }
+       }
+
        /**
         * Return an array of subpages beginning with $search that this special page will accept.
         *
         * @param string $search Prefix to search for
-        * @param integer $limit Maximum number of results to return
+        * @param int $limit Maximum number of results to return
         * @return string[] Matching subpages
         */
        public function prefixSearchSubpages( $search, $limit = 10 ) {
@@ -244,7 +260,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                $talk = $this->msg( 'talkpagelinktext' )->escaped();
                // Do a batch existence check
                $batch = new LinkBatch();
-               if (count($titles) >= 100) {
+               if ( count( $titles ) >= 100 ) {
                        $output = wfMessage( 'watchlistedit-too-many' )->parse();
                        return;
                }
@@ -331,7 +347,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
         *
         * @return array
         */
-       private function getWatchlistInfo() {
+       protected function getWatchlistInfo() {
                $titles = array();
                $dbr = wfGetDB( DB_MASTER );
 
@@ -537,24 +553,35 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                $fields = array();
                $count = 0;
 
-               foreach ( $this->getWatchlistInfo() as $namespace => $pages ) {
-                       if ( $namespace >= 0 ) {
-                               $fields['TitlesNs' . $namespace] = array(
-                                       'class' => 'EditWatchlistCheckboxSeriesField',
-                                       'options' => array(),
-                                       'section' => "ns$namespace",
-                               );
-                       }
+               // Allow subscribers to manipulate the list of watched pages (or use it
+               // to preload lots of details at once)
+               $watchlistInfo = $this->getWatchlistInfo();
+               wfRunHooks(
+                       'WatchlistEditorBeforeFormRender',
+                       array( &$watchlistInfo )
+               );
+
+               foreach ( $watchlistInfo as $namespace => $pages ) {
+                       $options = array();
 
                        foreach ( array_keys( $pages ) as $dbkey ) {
                                $title = Title::makeTitleSafe( $namespace, $dbkey );
 
                                if ( $this->checkTitle( $title, $namespace, $dbkey ) ) {
                                        $text = $this->buildRemoveLine( $title );
-                                       $fields['TitlesNs' . $namespace]['options'][$text] = $title->getPrefixedText();
+                                       $options[$text] = $title->getPrefixedText();
                                        $count++;
                                }
                        }
+
+                       // checkTitle can filter some options out, avoid empty sections
+                       if ( count( $options ) > 0 ) {
+                               $fields['TitlesNs' . $namespace] = array(
+                                       'class' => 'EditWatchlistCheckboxSeriesField',
+                                       'options' => $options,
+                                       'section' => "ns$namespace",
+                               );
+                       }
                }
                $this->cleanupWatchlist();
 
@@ -601,15 +628,10 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
        private function buildRemoveLine( $title ) {
                $link = Linker::link( $title );
 
-               if ( $title->isRedirect() ) {
-                       // Linker already makes class mw-redirect, so this is redundant
-                       $link = '<span class="watchlistredir">' . $link . '</span>';
-               }
-
-               $tools[] = Linker::link( $title->getTalkPage(), $this->msg( 'talkpagelinktext' )->escaped() );
+               $tools['talk'] = Linker::link( $title->getTalkPage(), $this->msg( 'talkpagelinktext' )->escaped() );
 
                if ( $title->exists() ) {
-                       $tools[] = Linker::linkKnown(
+                       $tools['history'] = Linker::linkKnown(
                                $title,
                                $this->msg( 'history_short' )->escaped(),
                                array(),
@@ -618,7 +640,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                }
 
                if ( $title->getNamespace() == NS_USER && !$title->isSubpage() ) {
-                       $tools[] = Linker::linkKnown(
+                       $tools['contributions'] = Linker::linkKnown(
                                SpecialPage::getTitleFor( 'Contributions', $title->getText() ),
                                $this->msg( 'contributions' )->escaped()
                        );
@@ -626,9 +648,14 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
 
                wfRunHooks(
                        'WatchlistEditorBuildRemoveLine',
-                       array( &$tools, $title, $title->isRedirect(), $this->getSkin() )
+                       array( &$tools, $title, $title->isRedirect(), $this->getSkin(), &$link )
                );
 
+               if ( $title->isRedirect() ) {
+                       // Linker already makes class mw-redirect, so this is redundant
+                       $link = '<span class="watchlistredir">' . $link . '</span>';
+               }
+
                return $link . " (" . $this->getLanguage()->pipeList( $tools ) . ")";
        }
 
@@ -763,8 +790,8 @@ class EditWatchlistCheckboxSeriesField extends HTMLMultiSelectField {
         * form is open (bug 32126), but we know that invalid items will
         * be harmless so we can override it here.
         *
-        * @param string $value the value the field was submitted with
-        * @param array $alldata the data collected from the form
+        * @param string $value The value the field was submitted with
+        * @param array $alldata The data collected from the form
         * @return bool|string Bool true on success, or String error to display.
         */
        function validate( $value, $alldata ) {
index 0062211..20532a9 100644 (file)
@@ -113,7 +113,8 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                // error out if sending user cannot do this
                $error = self::getPermissionsError(
                        $this->getUser(),
-                       $this->getRequest()->getVal( 'wpEditToken' )
+                       $this->getRequest()->getVal( 'wpEditToken' ),
+                       $this->getConfig()
                );
 
                switch ( $error ) {
@@ -175,7 +176,7 @@ class SpecialEmailUser extends UnlistedSpecialPage {
        /**
         * Validate target User
         *
-        * @param string $target target user name
+        * @param string $target Target user name
         * @return User User object on success or a string on error
         */
        public static function getTarget( $target ) {
@@ -208,12 +209,15 @@ class SpecialEmailUser extends UnlistedSpecialPage {
         *
         * @param User $user
         * @param string $editToken Edit token
+        * @param Config $config optional for backwards compatibility
         * @return string|null Null on success or string on error
         */
-       public static function getPermissionsError( $user, $editToken ) {
-               global $wgEnableEmail, $wgEnableUserEmail;
-
-               if ( !$wgEnableEmail || !$wgEnableUserEmail ) {
+       public static function getPermissionsError( $user, $editToken, Config $config = null ) {
+               if ( $config === null ) {
+                       wfDebug( __METHOD__ . ' called without a Config instance passed to it' );
+                       $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               }
+               if ( !$config->get( 'EnableEmail' ) || !$config->get( 'EnableUserEmail' ) ) {
                        return 'usermaildisabled';
                }
 
@@ -256,10 +260,9 @@ class SpecialEmailUser extends UnlistedSpecialPage {
         * @return string Form asking for user name.
         */
        protected function userForm( $name ) {
-               global $wgScript;
                $string = Xml::openElement(
                        'form',
-                       array( 'method' => 'get', 'action' => $wgScript, 'id' => 'askusername' )
+                       array( 'method' => 'get', 'action' => wfScript(), 'id' => 'askusername' )
                ) .
                        Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ) .
                        Xml::openElement( 'fieldset' ) .
@@ -302,7 +305,7 @@ class SpecialEmailUser extends UnlistedSpecialPage {
         * or maybe even true on success if anything uses the EmailUser hook.
         */
        public static function submit( array $data, IContextSource $context ) {
-               global $wgUserEmailUseReplyTo;
+               $config = $context->getConfig();
 
                $target = self::getTarget( $data['Target'] );
                if ( !$target instanceof User ) {
@@ -310,8 +313,8 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                        return $context->msg( $target . 'text' )->parseAsBlock();
                }
 
-               $to = new MailAddress( $target );
-               $from = new MailAddress( $context->getUser() );
+               $to = MailAddress::newFromUser( $target );
+               $from = MailAddress::newFromUser( $context->getUser() );
                $subject = $data['Subject'];
                $text = $data['Text'];
 
@@ -325,16 +328,14 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                        return $error;
                }
 
-               if ( $wgUserEmailUseReplyTo ) {
+               if ( $config->get( 'UserEmailUseReplyTo' ) ) {
                        // Put the generic wiki autogenerated address in the From:
                        // header and reserve the user for Reply-To.
                        //
                        // This is a bit ugly, but will serve to differentiate
                        // wiki-borne mails from direct mails and protects against
                        // SPF and bounce problems with some mailers (see below).
-                       global $wgPasswordSender;
-
-                       $mailFrom = new MailAddress( $wgPasswordSender,
+                       $mailFrom = new MailAddress( $config->get( 'PasswordSender' ),
                                wfMessage( 'emailsender' )->inContentLanguage()->text() );
                        $replyTo = $from;
                } else {
index 35a3ba1..269dff6 100644 (file)
@@ -41,7 +41,7 @@ class SpecialExpandTemplates extends SpecialPage {
        /** @var bool Whether or not to remove <nowiki> tags in the expanded wikitext */
        protected $removeNowiki;
 
-       /** @var maximum size in bytes to include. 50MB allows fixing those huge pages */
+       /** @var int Maximum size in bytes to include. 50MB allows fixing those huge pages */
        const MAX_INCLUDE_SIZE = 50000000;
 
        function __construct() {
@@ -50,9 +50,10 @@ class SpecialExpandTemplates extends SpecialPage {
 
        /**
         * Show the special page
+        * @param string|null $subpage
         */
        function execute( $subpage ) {
-               global $wgParser, $wgUseTidy, $wgAlwaysUseTidy;
+               global $wgParser;
 
                $this->setHeaders();
 
@@ -112,7 +113,8 @@ class SpecialExpandTemplates extends SpecialPage {
                                );
                        }
 
-                       if ( ( $wgUseTidy && $options->getTidy() ) || $wgAlwaysUseTidy ) {
+                       $config = $this->getConfig();
+                       if ( ( $config->get( 'UseTidy' ) && $options->getTidy() ) || $config->get( 'AlwaysUseTidy' ) ) {
                                $tmp = MWTidy::tidy( $tmp );
                        }
 
index bc8e728..38c52a0 100644 (file)
@@ -37,12 +37,9 @@ class SpecialExport extends SpecialPage {
        }
 
        public function execute( $par ) {
-               global $wgSitename, $wgExportAllowListContributors, $wgExportFromNamespaces;
-               global $wgExportAllowHistory, $wgExportMaxHistory, $wgExportMaxLinkDepth;
-               global $wgExportAllowAll;
-
                $this->setHeaders();
                $this->outputHeader();
+               $config = $this->getConfig();
 
                // Set some variables
                $this->curonly = true;
@@ -74,7 +71,7 @@ class SpecialExport extends SpecialPage {
                                        }
                                }
                        }
-               } elseif ( $request->getCheck( 'addns' ) && $wgExportFromNamespaces ) {
+               } elseif ( $request->getCheck( 'addns' ) && $config->get( 'ExportFromNamespaces' ) ) {
                        $page = $request->getText( 'pages' );
                        $nsindex = $request->getText( 'nsindex', '' );
 
@@ -87,7 +84,7 @@ class SpecialExport extends SpecialPage {
                                        $page .= "\n" . implode( "\n", $nspages );
                                }
                        }
-               } elseif ( $request->getCheck( 'exportall' ) && $wgExportAllowAll ) {
+               } elseif ( $request->getCheck( 'exportall' ) && $config->get( 'ExportAllowAll' ) ) {
                        $this->doExport = true;
                        $exportall = true;
 
@@ -108,19 +105,20 @@ class SpecialExport extends SpecialPage {
                                $offset = null;
                        }
 
+                       $maxHistory = $config->get( 'ExportMaxHistory' );
                        $limit = $request->getInt( 'limit' );
                        $dir = $request->getVal( 'dir' );
                        $history = array(
                                'dir' => 'asc',
                                'offset' => false,
-                               'limit' => $wgExportMaxHistory,
+                               'limit' => $maxHistory,
                        );
                        $historyCheck = $request->getCheck( 'history' );
 
                        if ( $this->curonly ) {
                                $history = WikiExporter::CURRENT;
                        } elseif ( !$historyCheck ) {
-                               if ( $limit > 0 && ( $wgExportMaxHistory == 0 || $limit < $wgExportMaxHistory ) ) {
+                               if ( $limit > 0 && ( $maxHistory == 0 || $limit < $maxHistory ) ) {
                                        $history['limit'] = $limit;
                                }
 
@@ -152,13 +150,13 @@ class SpecialExport extends SpecialPage {
                        }
                }
 
-               if ( !$wgExportAllowHistory ) {
+               if ( !$config->get( 'ExportAllowHistory' ) ) {
                        // Override
                        $history = WikiExporter::CURRENT;
                }
 
                $list_authors = $request->getCheck( 'listauthors' );
-               if ( !$this->curonly || !$wgExportAllowListContributors ) {
+               if ( !$this->curonly || !$config->get( 'ExportAllowListContributors' ) ) {
                        $list_authors = false;
                }
 
@@ -172,7 +170,7 @@ class SpecialExport extends SpecialPage {
 
                        if ( $request->getCheck( 'wpDownload' ) ) {
                                // Provide a sane filename suggestion
-                               $filename = urlencode( $wgSitename . '-' . wfTimestampNow() . '.xml' );
+                               $filename = urlencode( $config->get( 'Sitename' ) . '-' . wfTimestampNow() . '.xml' );
                                $request->response()->header( "Content-disposition: attachment;filename={$filename}" );
                        }
 
@@ -197,7 +195,7 @@ class SpecialExport extends SpecialPage {
                        array( 'name' => 'addcat' )
                ) . '<br />';
 
-               if ( $wgExportFromNamespaces ) {
+               if ( $config->get( 'ExportFromNamespaces' ) ) {
                        $form .= Html::namespaceSelector(
                                array(
                                        'selected' => $nsindex,
@@ -214,7 +212,7 @@ class SpecialExport extends SpecialPage {
                        ) . '<br />';
                }
 
-               if ( $wgExportAllowAll ) {
+               if ( $config->get( 'ExportAllowAll' ) ) {
                        $form .= Xml::checkLabel(
                                $this->msg( 'exportall' )->text(),
                                'exportall',
@@ -231,7 +229,7 @@ class SpecialExport extends SpecialPage {
                );
                $form .= '<br />';
 
-               if ( $wgExportAllowHistory ) {
+               if ( $config->get( 'ExportAllowHistory' ) ) {
                        $form .= Xml::checkLabel(
                                $this->msg( 'exportcuronly' )->text(),
                                'curonly',
@@ -249,7 +247,7 @@ class SpecialExport extends SpecialPage {
                        $request->wasPosted() ? $request->getCheck( 'templates' ) : false
                ) . '<br />';
 
-               if ( $wgExportMaxLinkDepth || $this->userCanOverrideExportDepth() ) {
+               if ( $config->get( 'ExportMaxLinkDepth' ) || $this->userCanOverrideExportDepth() ) {
                        $form .= Xml::inputLabel(
                                $this->msg( 'export-pagelinks' )->text(),
                                'pagelink-depth',
@@ -274,7 +272,7 @@ class SpecialExport extends SpecialPage {
                        $request->wasPosted() ? $request->getCheck( 'wpDownload' ) : true
                ) . '<br />';
 
-               if ( $wgExportAllowListContributors ) {
+               if ( $config->get( 'ExportAllowListContributors' ) ) {
                        $form .= Xml::checkLabel(
                                $this->msg( 'exportlistauthors' )->text(),
                                'listauthors',
@@ -302,7 +300,7 @@ class SpecialExport extends SpecialPage {
        /**
         * Do the actual page exporting
         *
-        * @param string $page user input on what page(s) to export
+        * @param string $page User input on what page(s) to export
         * @param int $history One of the WikiExporter history export constants
         * @param bool $list_authors Whether to add distinct author list (when
         *   not returning full history)
@@ -487,15 +485,14 @@ class SpecialExport extends SpecialPage {
         * @return int
         */
        private function validateLinkDepth( $depth ) {
-               global $wgExportMaxLinkDepth;
-
                if ( $depth < 0 ) {
                        return 0;
                }
 
                if ( !$this->userCanOverrideExportDepth() ) {
-                       if ( $depth > $wgExportMaxLinkDepth ) {
-                               return $wgExportMaxLinkDepth;
+                       $maxLinkDepth = $this->getConfig()->get( 'ExportMaxLinkDepth' );
+                       if ( $depth > $maxLinkDepth ) {
+                               return $maxLinkDepth;
                        }
                }
 
@@ -536,7 +533,7 @@ class SpecialExport extends SpecialPage {
         * @param array $inputPages List of titles to look up
         * @param array $pageSet Associative array indexed by titles for output
         *
-        * @return array associative array index by titles
+        * @return array Associative array index by titles
         */
        private function getImages( $inputPages, $pageSet ) {
                return $this->getLinks(
index b6c9d55..fc26c90 100644 (file)
@@ -59,7 +59,7 @@ class FileDuplicateSearchPage extends QueryPage {
        /**
         * Fetch dupes from all connected file repositories.
         *
-        * @return array of File objects
+        * @return array Array of File objects
         */
        function getDupes() {
                return RepoGroup::singleton()->findBySha1( $this->hash );
@@ -67,7 +67,7 @@ class FileDuplicateSearchPage extends QueryPage {
 
        /**
         *
-        * @param array $dupes of File objects
+        * @param array $dupes Array of File objects
         */
        function showList( $dupes ) {
                $html = array();
@@ -96,8 +96,6 @@ class FileDuplicateSearchPage extends QueryPage {
        }
 
        function execute( $par ) {
-               global $wgScript;
-
                $this->setHeaders();
                $this->outputHeader();
 
@@ -115,7 +113,7 @@ class FileDuplicateSearchPage extends QueryPage {
                $out->addHTML(
                        Html::openElement(
                                'form',
-                               array( 'id' => 'fileduplicatesearch', 'method' => 'get', 'action' => $wgScript )
+                               array( 'id' => 'fileduplicatesearch', 'method' => 'get', 'action' => wfScript() )
                        ) . "\n" .
                                Html::hidden( 'title', $this->getPageTitle()->getPrefixedDBkey() ) . "\n" .
                                Html::openElement( 'fieldset' ) . "\n" .
index eb1c139..5860f63 100644 (file)
@@ -37,7 +37,12 @@ class SpecialFilepath extends RedirectSpecialPage {
        function getRedirect( $par ) {
                $file = $par ?: $this->getRequest()->getText( 'file' );
 
-               return SpecialPage::getSafeTitleFor( 'Redirect', 'file/' . $file );
+               if ( $file ) {
+                       $argument = "file/$file";
+               } else {
+                       $argument = 'file';
+               }
+               return SpecialPage::getSafeTitleFor( 'Redirect', $argument );
        }
 
        protected function getGroupName() {
index 28e6479..eab4784 100644 (file)
@@ -31,6 +31,8 @@
  */
 class SpecialImport extends SpecialPage {
        private $interwiki = false;
+       private $subproject;
+       private $fullInterwikiPrefix;
        private $namespace;
        private $rootpage = '';
        private $frompage = '';
@@ -44,17 +46,19 @@ class SpecialImport extends SpecialPage {
         */
        public function __construct() {
                parent::__construct( 'Import', 'import' );
-               global $wgImportTargetNamespace;
-               $this->namespace = $wgImportTargetNamespace;
+               $this->namespace = $this->getConfig()->get( 'ImportTargetNamespace' );
        }
 
        /**
         * Execute
+        * @param string|null $par
         */
        function execute( $par ) {
                $this->setHeaders();
                $this->outputHeader();
 
+               $this->getOutput()->addModules( 'mediawiki.special.import' );
+
                $user = $this->getUser();
                if ( !$user->isAllowedAny( 'import', 'importupload' ) ) {
                        throw new PermissionsError( 'import' );
@@ -91,15 +95,13 @@ class SpecialImport extends SpecialPage {
         * Do the actual import
         */
        private function doImport() {
-               global $wgImportSources, $wgExportMaxLinkDepth;
-
                $isUpload = false;
                $request = $this->getRequest();
                $this->namespace = $request->getIntOrNull( 'namespace' );
                $sourceName = $request->getVal( "source" );
 
                $this->logcomment = $request->getText( 'log-comment' );
-               $this->pageLinkDepth = $wgExportMaxLinkDepth == 0
+               $this->pageLinkDepth = $this->getConfig()->get( 'ExportMaxLinkDepth' ) == 0
                        ? 0
                        : $request->getIntOrNull( 'pagelink-depth' );
                $this->rootpage = $request->getText( 'rootpage' );
@@ -118,19 +120,30 @@ class SpecialImport extends SpecialPage {
                        if ( !$user->isAllowed( 'import' ) ) {
                                throw new PermissionsError( 'import' );
                        }
-                       $this->interwiki = $request->getVal( 'interwiki' );
-                       if ( !in_array( $this->interwiki, $wgImportSources ) ) {
+                       $this->interwiki = $this->fullInterwikiPrefix = $request->getVal( 'interwiki' );
+                       // does this interwiki have subprojects?
+                       $importSources = $this->getConfig()->get( 'ImportSources' );
+                       $hasSubprojects = array_key_exists( $this->interwiki, $importSources );
+                       if ( !$hasSubprojects && !in_array( $this->interwiki, $importSources ) ) {
                                $source = Status::newFatal( "import-invalid-interwiki" );
                        } else {
-                               $this->history = $request->getCheck( 'interwikiHistory' );
-                               $this->frompage = $request->getText( "frompage" );
-                               $this->includeTemplates = $request->getCheck( 'interwikiTemplates' );
-                               $source = ImportStreamSource::newFromInterwiki(
-                                       $this->interwiki,
-                                       $this->frompage,
-                                       $this->history,
-                                       $this->includeTemplates,
-                                       $this->pageLinkDepth );
+                               if ( $hasSubprojects ) {
+                                       $this->subproject = $request->getVal( 'subproject' );
+                                       $this->fullInterwikiPrefix .= ':' . $request->getVal( 'subproject' );
+                               }
+                               if ( $hasSubprojects && !in_array( $this->subproject, $importSources[$this->interwiki] ) ) {
+                                       $source = Status::newFatal( "import-invalid-interwiki" );
+                               } else {
+                                       $this->history = $request->getCheck( 'interwikiHistory' );
+                                       $this->frompage = $request->getText( "frompage" );
+                                       $this->includeTemplates = $request->getCheck( 'interwikiTemplates' );
+                                       $source = ImportStreamSource::newFromInterwiki(
+                                               $this->fullInterwikiPrefix,
+                                               $this->frompage,
+                                               $this->history,
+                                               $this->includeTemplates,
+                                               $this->pageLinkDepth );
+                               }
                        }
                } else {
                        $source = Status::newFatal( "importunknownsource" );
@@ -168,7 +181,7 @@ class SpecialImport extends SpecialPage {
                        $reporter = new ImportReporter(
                                $importer,
                                $isUpload,
-                               $this->interwiki,
+                               $this->fullInterwikiPrefix,
                                $this->logcomment
                        );
                        $reporter->setContext( $this->getContext() );
@@ -203,11 +216,10 @@ class SpecialImport extends SpecialPage {
        }
 
        private function showForm() {
-               global $wgImportSources, $wgExportMaxLinkDepth;
-
                $action = $this->getPageTitle()->getLocalURL( array( 'action' => 'submit' ) );
                $user = $this->getUser();
                $out = $this->getOutput();
+               $importSources = $this->getConfig()->get( 'ImportSources' );
 
                if ( $user->isAllowed( 'importupload' ) ) {
                        $out->addHTML(
@@ -266,15 +278,15 @@ class SpecialImport extends SpecialPage {
                                        Xml::closeElement( 'fieldset' )
                        );
                } else {
-                       if ( empty( $wgImportSources ) ) {
+                       if ( empty( $importSources ) ) {
                                $out->addWikiMsg( 'importnosources' );
                        }
                }
 
-               if ( $user->isAllowed( 'import' ) && !empty( $wgImportSources ) ) {
+               if ( $user->isAllowed( 'import' ) && !empty( $importSources ) ) {
                        # Show input field for import depth only if $wgExportMaxLinkDepth > 0
                        $importDepth = '';
-                       if ( $wgExportMaxLinkDepth > 0 ) {
+                       if ( $this->getConfig()->get( 'ExportMaxLinkDepth' ) > 0 ) {
                                $importDepth = "<tr>
                                                        <td class='mw-label'>" .
                                        $this->msg( 'export-pagelinks' )->parse() .
@@ -302,7 +314,7 @@ class SpecialImport extends SpecialPage {
                                        Xml::openElement( 'table', array( 'id' => 'mw-import-table-interwiki' ) ) .
                                        "<tr>
                                        <td class='mw-label'>" .
-                                       Xml::label( $this->msg( 'import-interwiki-source' )->text(), 'interwiki' ) .
+                                       Xml::label( $this->msg( 'import-interwiki-sourcewiki' )->text(), 'interwiki' ) .
                                        "</td>
                                        <td class='mw-input'>" .
                                        Xml::openElement(
@@ -311,13 +323,63 @@ class SpecialImport extends SpecialPage {
                                        )
                        );
 
-                       foreach ( $wgImportSources as $prefix ) {
-                               $selected = ( $this->interwiki === $prefix ) ? ' selected="selected"' : '';
-                               $out->addHTML( Xml::option( $prefix, $prefix, $selected ) );
+                       $needSubprojectField = false;
+                       foreach ( $importSources as $key => $value ) {
+                               if ( is_int( $key ) ) {
+                                       $key = $value;
+                               } elseif ( $value !== $key ) {
+                                       $needSubprojectField = true;
+                               }
+
+                               $attribs = array(
+                                       'value' => $key,
+                               );
+                               if ( is_array( $value ) ) {
+                                       $attribs['data-subprojects'] = implode( ' ', $value );
+                               }
+                               if ( $this->interwiki === $key ) {
+                                       $attribs['selected'] = 'selected';
+                               }
+                               $out->addHTML( Html::element( 'option', $attribs, $key ) );
+                       }
+
+                       $out->addHTML(
+                               Xml::closeElement( 'select' )
+                       );
+
+                       if ( $needSubprojectField ) {
+                               $out->addHTML(
+                                       Xml::openElement(
+                                               'select',
+                                               array( 'name' => 'subproject', 'id' => 'subproject' )
+                                       )
+                               );
+
+                               $subprojectsToAdd = array();
+                               foreach ( $importSources as $key => $value ) {
+                                       if ( is_array( $value ) ) {
+                                               $subprojectsToAdd = array_merge( $subprojectsToAdd, $value );
+                                       }
+                               }
+                               $subprojectsToAdd = array_unique( $subprojectsToAdd );
+                               sort( $subprojectsToAdd );
+                               foreach ( $subprojectsToAdd as $subproject ) {
+                                       $out->addHTML( Xml::option( $subproject, $subproject, $this->subproject === $subproject ) );
+                               }
+
+                               $out->addHTML(
+                                       Xml::closeElement( 'select' )
+                               );
                        }
 
                        $out->addHTML(
-                               Xml::closeElement( 'select' ) .
+                                       "</td>
+                               </tr>
+                               <tr>
+                                       <td class='mw-label'>" .
+                                       Xml::label( $this->msg( 'import-interwiki-sourcepage' )->text(), 'frompage' ) .
+                                       "</td>
+                                       <td class='mw-input'>" .
                                        Xml::input( 'frompage', 50, $this->frompage, array( 'id' => 'frompage' ) ) .
                                        "</td>
                                </tr>
index 03b3688..0efebb3 100644 (file)
@@ -134,16 +134,15 @@ class SpecialJavaScriptTest extends SpecialPage {
         * Initialize the page for QUnit.
         */
        private function initQUnitTesting() {
-               global $wgJavaScriptTestConfig;
-
                $out = $this->getOutput();
+               $testConfig = $this->getConfig()->get( 'JavaScriptTestConfig' );
 
                $out->addModules( 'test.mediawiki.qunit.testrunner' );
                $qunitTestModules = $out->getResourceLoader()->getTestModuleNames( 'qunit' );
                $out->addModules( $qunitTestModules );
 
                $summary = $this->msg( 'javascripttest-qunit-intro' )
-                       ->params( $wgJavaScriptTestConfig['qunit']['documentation'] )
+                       ->params( $testConfig['qunit']['documentation'] )
                        ->parseAsBlock();
                $header = $this->msg( 'javascripttest-qunit-heading' )->escaped();
                $userDir = $this->getLanguage()->getDir();
@@ -169,7 +168,7 @@ HTML;
                // $wgJavaScriptTestConfig in DefaultSettings.php
                $out->addJsConfigVars(
                        'QUnitTestSwarmInjectJSPath',
-                       $wgJavaScriptTestConfig['qunit']['testswarm-injectjs']
+                       $testConfig['qunit']['testswarm-injectjs']
                );
        }
 
@@ -177,7 +176,7 @@ HTML;
         * Return an array of subpages beginning with $search that this special page will accept.
         *
         * @param string $search Prefix to search for
-        * @param integer $limit Maximum number of results to return
+        * @param int $limit Maximum number of results to return
         * @return string[] Matching subpages
         */
        public function prefixSearchSubpages( $search, $limit = 10 ) {
index aec1257..371469b 100644 (file)
@@ -51,7 +51,7 @@ class LinkSearchPage extends QueryPage {
         * Initialize or override the PageLinkRenderer LinkSearchPage collaborates with.
         * Useful mainly for testing.
         *
-        * @todo: query logic and rendering logic should be split and also injected
+        * @todo query logic and rendering logic should be split and also injected
         *
         * @param PageLinkRenderer $linkRenderer
         */
@@ -78,8 +78,6 @@ class LinkSearchPage extends QueryPage {
        }
 
        function execute( $par ) {
-               global $wgUrlProtocols, $wgMiserMode, $wgScript;
-
                $this->initServices();
 
                $this->setHeaders();
@@ -93,7 +91,7 @@ class LinkSearchPage extends QueryPage {
                $namespace = $request->getIntorNull( 'namespace', null );
 
                $protocols_list = array();
-               foreach ( $wgUrlProtocols as $prot ) {
+               foreach ( $this->getConfig()->get( 'UrlProtocols' ) as $prot ) {
                        if ( $prot !== '//' ) {
                                $protocols_list[] = $prot;
                        }
@@ -122,7 +120,7 @@ class LinkSearchPage extends QueryPage {
                );
                $s = Html::openElement(
                        'form',
-                       array( 'id' => 'mw-linksearch-form', 'method' => 'get', 'action' => $wgScript )
+                       array( 'id' => 'mw-linksearch-form', 'method' => 'get', 'action' => wfScript() )
                ) . "\n" .
                        Html::hidden( 'title', $this->getPageTitle()->getPrefixedDBkey() ) . "\n" .
                        Html::openElement( 'fieldset' ) . "\n" .
@@ -139,7 +137,7 @@ class LinkSearchPage extends QueryPage {
                                )
                        ) . "\n";
 
-               if ( !$wgMiserMode ) {
+               if ( !$this->getConfig()->get( 'MiserMode' ) ) {
                        $s .= Html::namespaceSelector(
                                array(
                                        'selected' => $namespace,
@@ -210,10 +208,9 @@ class LinkSearchPage extends QueryPage {
        }
 
        function linkParameters() {
-               global $wgMiserMode;
                $params = array();
                $params['target'] = $this->mProt . $this->mQuery;
-               if ( $this->mNs !== null && !$wgMiserMode ) {
+               if ( $this->mNs !== null && !$this->getConfig()->get( 'MiserMode' ) ) {
                        $params['namespace'] = $this->mNs;
                }
 
@@ -221,7 +218,6 @@ class LinkSearchPage extends QueryPage {
        }
 
        function getQueryInfo() {
-               global $wgMiserMode;
                $dbr = wfGetDB( DB_SLAVE );
                // strip everything past first wildcard, so that
                // index-based-only lookup would be done
@@ -248,7 +244,7 @@ class LinkSearchPage extends QueryPage {
                        'options' => array( 'USE INDEX' => $clause )
                );
 
-               if ( $this->mNs !== null && !$wgMiserMode ) {
+               if ( $this->mNs !== null && !$this->getConfig()->get( 'MiserMode' ) ) {
                        $retval['conds']['page_namespace'] = $this->mNs;
                }
 
index c1dc158..2667270 100644 (file)
@@ -51,6 +51,7 @@ class ListDuplicatedFilesPage extends QueryPage {
         * However this version should be no more expensive then
         * Special:MostLinked, which seems to get handled fine
         * with however we are doing cached special pages.
+        * @return array
         */
        function getQueryInfo() {
                return array(
index 1faa013..04a83c8 100644 (file)
@@ -48,15 +48,13 @@ class SpecialListFiles extends IncludableSpecialPage {
                        $showAll
                );
 
+               $out = $this->getOutput();
                if ( $this->including() ) {
-                       $html = $pager->getBody();
+                       $out->addParserOutputContent( $pager->getBodyOutput() );
                } else {
-                       $form = $pager->getForm();
-                       $body = $pager->getBody();
-                       $nav = $pager->getNavigationBar();
-                       $html = "$form<br />\n$body<br />\n$nav";
+                       $out->addHTML( $pager->getForm() );
+                       $out->addParserOutputContent( $pager->getFullOutput() );
                }
-               $this->getOutput()->addHTML( $html );
        }
 
        protected function getGroupName() {
@@ -86,8 +84,6 @@ class ImageListPager extends TablePager {
        function __construct( IContextSource $context, $userName = null, $search = '',
                $including = false, $showAll = false
        ) {
-               global $wgMiserMode;
-
                $this->mIncluding = $including;
                $this->mShowAll = $showAll;
 
@@ -98,7 +94,7 @@ class ImageListPager extends TablePager {
                        }
                }
 
-               if ( $search !== '' && !$wgMiserMode ) {
+               if ( $search !== '' && !$this->getConfig()->get( 'MiserMode' ) ) {
                        $this->mSearch = $search;
                        $nt = Title::newFromURL( $this->mSearch );
 
@@ -112,12 +108,12 @@ class ImageListPager extends TablePager {
 
                if ( !$including ) {
                        if ( $context->getRequest()->getText( 'sort', 'img_date' ) == 'img_date' ) {
-                               $this->mDefaultDirection = true;
+                               $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
                        } else {
-                               $this->mDefaultDirection = false;
+                               $this->mDefaultDirection = IndexPager::DIR_ASCENDING;
                        }
                } else {
-                       $this->mDefaultDirection = true;
+                       $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
                }
 
                parent::__construct( $context );
@@ -164,7 +160,6 @@ class ImageListPager extends TablePager {
         */
        function getFieldNames() {
                if ( !$this->mFieldNames ) {
-                       global $wgMiserMode;
                        $this->mFieldNames = array(
                                'img_timestamp' => $this->msg( 'listfiles_date' )->text(),
                                'img_name' => $this->msg( 'listfiles_name' )->text(),
@@ -178,7 +173,7 @@ class ImageListPager extends TablePager {
                        // img_description down here, in order so that its still after the username field.
                        $this->mFieldNames['img_description'] = $this->msg( 'listfiles_description' )->text();
 
-                       if ( !$wgMiserMode && !$this->mShowAll ) {
+                       if ( !$this->getConfig()->get( 'MiserMode' ) && !$this->mShowAll ) {
                                $this->mFieldNames['count'] = $this->msg( 'listfiles_count' )->text();
                        }
                        if ( $this->mShowAll ) {
@@ -190,7 +185,6 @@ class ImageListPager extends TablePager {
        }
 
        function isFieldSortable( $field ) {
-               global $wgMiserMode;
                if ( $this->mIncluding ) {
                        return false;
                }
@@ -202,14 +196,14 @@ class ImageListPager extends TablePager {
                 * 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 ( $wgMiserMode && !is_null( $this->mUserName ) ) {
+               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 ( $wgMiserMode && $this->mShowAll /* && mUserName === null */ ) {
+               } 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;
@@ -305,6 +299,7 @@ class ImageListPager extends TablePager {
         * @param int $offset
         * @param int $limit
         * @param bool $asc
+        * @return array
         */
        function reallyDoQuery( $offset, $limit, $asc ) {
                $prevTableName = $this->mTableName;
@@ -392,8 +387,7 @@ class ImageListPager extends TablePager {
        }
 
        function getDefaultSort() {
-               global $wgMiserMode;
-               if ( $this->mShowAll && $wgMiserMode && is_null( $this->mUserName ) ) {
+               if ( $this->mShowAll && $this->getConfig()->get( 'MiserMode' ) && is_null( $this->mUserName ) ) {
                        // Unfortunately no index on oi_timestamp.
                        return 'img_name';
                } else {
@@ -504,55 +498,74 @@ class ImageListPager extends TablePager {
        }
 
        function getForm() {
-               global $wgScript, $wgMiserMode;
-               $inputForm = array();
-               $inputForm['table_pager_limit_label'] = $this->getLimitSelect( array( 'tabindex' => 1 ) );
-               if ( !$wgMiserMode ) {
-                       $inputForm['listfiles_search_for'] = Html::input(
-                               'ilsearch',
-                               $this->mSearch,
-                               'text',
-                               array(
-                                       'size' => '40',
-                                       'maxlength' => '255',
-                                       'id' => 'mw-ilsearch',
-                                       'tabindex' => 2,
-                               )
+               $fields = array();
+               $fields['limit'] = array(
+                       'type' => 'select',
+                       'name' => 'limit',
+                       'label-message' => 'table_pager_limit_label',
+                       'options' => $this->getLimitSelectList(),
+                       'default' => $this->mLimit,
+               );
+
+               if ( !$this->getConfig()->get( 'MiserMode' ) ) {
+                       $fields['ilsearch'] = array(
+                               'type' => 'text',
+                               'name' => 'ilsearch',
+                               'id' => 'mw-ilsearch',
+                               'label-message' => 'listfiles_search_for',
+                               'default' => $this->mSearch,
+                               'size' => '40',
+                               'maxlength' => '255',
                        );
                }
-               $inputForm['username'] = Html::input( 'user', $this->mUserName, 'text', array(
+
+               $fields['user'] = array(
+                       'type' => 'text',
+                       'name' => 'user',
+                       'id' => 'mw-listfiles-user',
+                       'label-message' => 'username',
+                       'default' => $this->mUserName,
                        'size' => '40',
                        'maxlength' => '255',
-                       'id' => 'mw-listfiles-user',
-                       'tabindex' => 3,
-               ) );
-
-               $inputForm['listfiles-show-all'] = Html::input( 'ilshowall', 1, 'checkbox', array(
-                       'checked' => $this->mShowAll,
-                       'tabindex' => 4,
-               ) );
-
-               return Html::openElement( 'form',
-                       array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-listfiles-form' )
-               ) .
-                       Xml::fieldset( $this->msg( 'listfiles' )->text() ) .
-                       Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
-                       Xml::buildForm( $inputForm, 'table_pager_limit_submit', array( 'tabindex' => 5 ) ) .
-                       $this->getHiddenFields( array( 'limit', 'ilsearch', 'user', 'title', 'ilshowall' ) ) .
-                       Html::closeElement( 'fieldset' ) .
-                       Html::closeElement( 'form' ) . "\n";
+               );
+
+               $fields['ilshowall'] = array(
+                       '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['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 'listfiles ' . parent::getTableClass();
+               return parent::getTableClass() . ' listfiles';
        }
 
        function getNavClass() {
-               return 'listfiles_nav ' . parent::getNavClass();
+               return parent::getNavClass() . ' listfiles_nav';
        }
 
        function getSortHeaderClass() {
-               return 'listfiles_sort ' . parent::getSortHeaderClass();
+               return parent::getSortHeaderClass() . ' listfiles_sort';
        }
 
        function getPagingQueries() {
@@ -560,7 +573,9 @@ class ImageListPager extends TablePager {
                if ( !is_null( $this->mUserName ) ) {
                        # Append the username to the query string
                        foreach ( $queries as &$query ) {
-                               $query['user'] = $this->mUserName;
+                               if ( $query !== false ) {
+                                       $query['user'] = $this->mUserName;
+                               }
                        }
                }
 
index a77b70c..5bae28f 100644 (file)
@@ -35,12 +35,9 @@ class SpecialListGroupRights extends SpecialPage {
 
        /**
         * Show the special page
+        * @param string|null $par
         */
        public function execute( $par ) {
-               global $wgImplicitGroups;
-               global $wgGroupPermissions, $wgRevokePermissions, $wgAddGroups, $wgRemoveGroups;
-               global $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
-
                $this->setHeaders();
                $this->outputHeader();
 
@@ -57,19 +54,26 @@ class SpecialListGroupRights extends SpecialPage {
                                '</tr>'
                );
 
+               $config = $this->getConfig();
+               $groupPermissions = $config->get( 'GroupPermissions' );
+               $revokePermissions = $config->get( 'RevokePermissions' );
+               $addGroups = $config->get( 'AddGroups' );
+               $removeGroups = $config->get( 'RemoveGroups' );
+               $groupsAddToSelf = $config->get( 'GroupsAddToSelf' );
+               $groupsRemoveFromSelf = $config->get( 'GroupsRemoveFromSelf' );
                $allGroups = array_unique( array_merge(
-                       array_keys( $wgGroupPermissions ),
-                       array_keys( $wgRevokePermissions ),
-                       array_keys( $wgAddGroups ),
-                       array_keys( $wgRemoveGroups ),
-                       array_keys( $wgGroupsAddToSelf ),
-                       array_keys( $wgGroupsRemoveFromSelf )
+                       array_keys( $groupPermissions ),
+                       array_keys( $revokePermissions ),
+                       array_keys( $addGroups ),
+                       array_keys( $removeGroups ),
+                       array_keys( $groupsAddToSelf ),
+                       array_keys( $groupsRemoveFromSelf )
                ) );
                asort( $allGroups );
 
                foreach ( $allGroups as $group ) {
-                       $permissions = isset( $wgGroupPermissions[$group] )
-                               ? $wgGroupPermissions[$group]
+                       $permissions = isset( $groupPermissions[$group] )
+                               ? $groupPermissions[$group]
                                : array();
                        $groupname = ( $group == '*' ) // Replace * with a more descriptive groupname
                                ? 'all'
@@ -99,7 +103,7 @@ class SpecialListGroupRights extends SpecialPage {
                                        SpecialPage::getTitleFor( 'Listusers' ),
                                        $this->msg( 'listgrouprights-members' )->escaped()
                                );
-                       } elseif ( !in_array( $group, $wgImplicitGroups ) ) {
+                       } elseif ( !in_array( $group, $config->get( 'ImplicitGroups' ) ) ) {
                                $grouplink = '<br />' . Linker::linkKnown(
                                        SpecialPage::getTitleFor( 'Listusers' ),
                                        $this->msg( 'listgrouprights-members' )->escaped(),
@@ -111,12 +115,12 @@ class SpecialListGroupRights extends SpecialPage {
                                $grouplink = '';
                        }
 
-                       $revoke = isset( $wgRevokePermissions[$group] ) ? $wgRevokePermissions[$group] : array();
-                       $addgroups = isset( $wgAddGroups[$group] ) ? $wgAddGroups[$group] : array();
-                       $removegroups = isset( $wgRemoveGroups[$group] ) ? $wgRemoveGroups[$group] : array();
-                       $addgroupsSelf = isset( $wgGroupsAddToSelf[$group] ) ? $wgGroupsAddToSelf[$group] : array();
-                       $removegroupsSelf = isset( $wgGroupsRemoveFromSelf[$group] )
-                               ? $wgGroupsRemoveFromSelf[$group]
+                       $revoke = isset( $revokePermissions[$group] ) ? $revokePermissions[$group] : array();
+                       $addgroups = isset( $addGroups[$group] ) ? $addGroups[$group] : array();
+                       $removegroups = isset( $removeGroups[$group] ) ? $removeGroups[$group] : array();
+                       $addgroupsSelf = isset( $groupsAddToSelf[$group] ) ? $groupsAddToSelf[$group] : array();
+                       $removegroupsSelf = isset( $groupsRemoveFromSelf[$group] )
+                               ? $groupsRemoveFromSelf[$group]
                                : array();
 
                        $id = $group == '*' ? false : Sanitizer::escapeId( $group );
@@ -134,10 +138,11 @@ class SpecialListGroupRights extends SpecialPage {
        }
 
        private function outputNamespaceProtectionInfo() {
-               global $wgNamespaceProtection, $wgParser, $wgContLang;
+               global $wgParser, $wgContLang;
                $out = $this->getOutput();
+               $namespaceProtection = $this->getConfig()->get( 'NamespaceProtection' );
 
-               if ( count( $wgNamespaceProtection ) == 0 ) {
+               if ( count( $namespaceProtection ) == 0 ) {
                        return;
                }
 
@@ -160,8 +165,8 @@ class SpecialListGroupRights extends SpecialPage {
                        )
                );
 
-               ksort( $wgNamespaceProtection );
-               foreach ( $wgNamespaceProtection as $namespace => $rights ) {
+               ksort( $namespaceProtection );
+               foreach ( $namespaceProtection as $namespace => $rights ) {
                        if ( !in_array( $namespace, MWNamespace::getValidNamespaces() ) ) {
                                continue;
                        }
@@ -217,12 +222,12 @@ class SpecialListGroupRights extends SpecialPage {
        /**
         * Create a user-readable list of permissions from the given array.
         *
-        * @param array $permissions of permission => bool (from $wgGroupPermissions items)
-        * @param array $revoke of permission => bool (from $wgRevokePermissions items)
-        * @param array $add of groups this group is allowed to add or true
-        * @param array $remove of groups this group is allowed to remove or true
-        * @param array $addSelf of groups this group is allowed to add to self or true
-        * @param array $removeSelf of group this group is allowed to remove from self or true
+        * @param array $permissions Array of permission => bool (from $wgGroupPermissions items)
+        * @param array $revoke Array of permission => bool (from $wgRevokePermissions items)
+        * @param array $add Array of groups this group is allowed to add or true
+        * @param array $remove Array of groups this group is allowed to remove or true
+        * @param array $addSelf Array of groups this group is allowed to add to self or true
+        * @param array $removeSelf Array of group this group is allowed to remove from self or true
         * @return string List of all granted permissions, separated by comma separator
         */
        private function formatPermissions( $permissions, $revoke, $add, $remove, $addSelf, $removeSelf ) {
@@ -250,45 +255,54 @@ class SpecialListGroupRights extends SpecialPage {
                sort( $r );
 
                $lang = $this->getLanguage();
+               $allGroups = User::getAllGroups();
 
                if ( $add === true ) {
                        $r[] = $this->msg( 'listgrouprights-addgroup-all' )->escaped();
-               } elseif ( is_array( $add ) && count( $add ) ) {
-                       $add = array_values( array_unique( $add ) );
-                       $r[] = $this->msg( 'listgrouprights-addgroup',
-                               $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $add ) ),
-                               count( $add )
-                       )->parse();
+               } elseif ( is_array( $add ) ) {
+                       $add = array_intersect( array_values( array_unique( $add ) ), $allGroups );
+                       if ( count( $add ) ) {
+                               $r[] = $this->msg( 'listgrouprights-addgroup',
+                                       $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $add ) ),
+                                       count( $add )
+                               )->parse();
+                       }
                }
 
                if ( $remove === true ) {
                        $r[] = $this->msg( 'listgrouprights-removegroup-all' )->escaped();
-               } elseif ( is_array( $remove ) && count( $remove ) ) {
-                       $remove = array_values( array_unique( $remove ) );
-                       $r[] = $this->msg( 'listgrouprights-removegroup',
-                               $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $remove ) ),
-                               count( $remove )
-                       )->parse();
+               } elseif ( is_array( $remove ) ) {
+                       $remove = array_intersect( array_values( array_unique( $remove ) ), $allGroups );
+                       if ( count( $remove ) ) {
+                               $r[] = $this->msg( 'listgrouprights-removegroup',
+                                       $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $remove ) ),
+                                       count( $remove )
+                               )->parse();
+                       }
                }
 
                if ( $addSelf === true ) {
                        $r[] = $this->msg( 'listgrouprights-addgroup-self-all' )->escaped();
-               } elseif ( is_array( $addSelf ) && count( $addSelf ) ) {
-                       $addSelf = array_values( array_unique( $addSelf ) );
-                       $r[] = $this->msg( 'listgrouprights-addgroup-self',
-                               $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $addSelf ) ),
-                               count( $addSelf )
-                       )->parse();
+               } elseif ( is_array( $addSelf ) ) {
+                       $addSelf = array_intersect( array_values( array_unique( $addSelf ) ), $allGroups );
+                       if ( count( $addSelf ) ) {
+                               $r[] = $this->msg( 'listgrouprights-addgroup-self',
+                                       $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $addSelf ) ),
+                                       count( $addSelf )
+                               )->parse();
+                       }
                }
 
                if ( $removeSelf === true ) {
                        $r[] = $this->msg( 'listgrouprights-removegroup-self-all' )->parse();
-               } elseif ( is_array( $removeSelf ) && count( $removeSelf ) ) {
-                       $removeSelf = array_values( array_unique( $removeSelf ) );
-                       $r[] = $this->msg( 'listgrouprights-removegroup-self',
-                               $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $removeSelf ) ),
-                               count( $removeSelf )
-                       )->parse();
+               } elseif ( is_array( $removeSelf ) ) {
+                       $removeSelf = array_intersect( array_values( array_unique( $removeSelf ) ), $allGroups );
+                       if ( count( $removeSelf ) ) {
+                               $r[] = $this->msg( 'listgrouprights-removegroup-self',
+                                       $lang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $removeSelf ) ),
+                                       count( $removeSelf )
+                               )->parse();
+                       }
                }
 
                if ( empty( $r ) ) {
index 367adef..dad9074 100644 (file)
@@ -69,7 +69,9 @@ class UsersPager extends AlphabeticPager {
                $this->editsOnly = $request->getBool( 'editsOnly' );
                $this->creationSort = $request->getBool( 'creationSort' );
                $this->including = $including;
-               $this->mDefaultDirection = $request->getBool( 'desc' );
+               $this->mDefaultDirection = $request->getBool( 'desc' )
+                       ? IndexPager::DIR_DESCENDING
+                       : IndexPager::DIR_ASCENDING;
 
                $this->requestedUser = '';
 
@@ -191,12 +193,9 @@ class UsersPager extends AlphabeticPager {
                }
 
                $edits = '';
-               global $wgEdititis;
-               if ( !$this->including && $wgEdititis ) {
-                       // @fixme i18n issue: Hardcoded square brackets.
-                       $edits = ' [' .
-                               $this->msg( 'usereditcount' )->numParams( $row->edits )->escaped() .
-                               ']';
+               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 = '';
@@ -232,14 +231,12 @@ class UsersPager extends AlphabeticPager {
         * @return string
         */
        function getPageHeader() {
-               global $wgScript;
-
                list( $self ) = explode( '/', $this->getTitle()->getPrefixedDBkey() );
 
                # Form tag
                $out = Xml::openElement(
                        'form',
-                       array( 'method' => 'get', 'action' => $wgScript, 'id' => 'mw-listusers-form' )
+                       array( 'method' => 'get', 'action' => wfScript(), 'id' => 'mw-listusers-form' )
                ) .
                        Xml::fieldset( $this->msg( 'listusers' )->text() ) .
                        Html::hidden( 'title', $self );
@@ -399,6 +396,18 @@ class SpecialListUsers extends IncludableSpecialPage {
                $this->getOutput()->addHTML( $s );
        }
 
+       /**
+        * Return an array of subpages beginning with $search that this special page will accept.
+        *
+        * @param string $search Prefix to search for
+        * @param int $limit Maximum number of results to return
+        * @return string[] Matching subpages
+        */
+       public function prefixSearchSubpages( $search, $limit = 10 ) {
+               $subpages = User::getAllGroups();
+               return self::prefixSearchArray( $search, $limit, $subpages );
+       }
+
        protected function getGroupName() {
                return 'users';
        }
index 3382405..1c1f125 100644 (file)
@@ -38,11 +38,9 @@ class SpecialLockdb extends FormSpecialPage {
        }
 
        public function checkExecutePermissions( User $user ) {
-               global $wgReadOnlyFile;
-
                parent::checkExecutePermissions( $user );
                # If the lock file isn't writable, we can do sweet bugger all
-               if ( !is_writable( dirname( $wgReadOnlyFile ) ) ) {
+               if ( !is_writable( dirname( $this->getConfig()->get( 'ReadOnlyFile' ) ) ) ) {
                        throw new ErrorPageError( 'lockdb', 'lockfilenotwritable' );
                }
        }
@@ -69,14 +67,14 @@ class SpecialLockdb extends FormSpecialPage {
        }
 
        public function onSubmit( array $data ) {
-               global $wgContLang, $wgReadOnlyFile;
+               global $wgContLang;
 
                if ( !$data['Confirm'] ) {
                        return Status::newFatal( 'locknoconfirm' );
                }
 
                wfSuppressWarnings();
-               $fp = fopen( $wgReadOnlyFile, 'w' );
+               $fp = fopen( $this->getConfig()->get( 'ReadOnlyFile' ), 'w' );
                wfRestoreWarnings();
 
                if ( false === $fp ) {
index ced5d25..dc33801 100644 (file)
@@ -45,8 +45,6 @@ class SpecialLog extends SpecialPage {
        }
 
        public function execute( $par ) {
-               global $wgLogRestrictions;
-
                $this->setHeaders();
                $this->outputHeader();
 
@@ -77,13 +75,14 @@ class SpecialLog extends SpecialPage {
                // If the user doesn't have the right permission to view the specific
                // log type, throw a PermissionsError
                // If the log type is invalid, just show all public logs
+               $logRestrictions = $this->getConfig()->get( 'LogRestrictions' );
                $type = $opts->getValue( 'type' );
                if ( !LogPage::isLogType( $type ) ) {
                        $opts->setValue( 'type', '' );
-               } elseif ( isset( $wgLogRestrictions[$type] )
-                       && !$this->getUser()->isAllowed( $wgLogRestrictions[$type] )
+               } elseif ( isset( $logRestrictions[$type] )
+                       && !$this->getUser()->isAllowed( $logRestrictions[$type] )
                ) {
-                       throw new PermissionsError( $wgLogRestrictions[$type] );
+                       throw new PermissionsError( $logRestrictions[$type] );
                }
 
                # Handle type-specific inputs
@@ -119,25 +118,22 @@ class SpecialLog extends SpecialPage {
         * Return an array of subpages beginning with $search that this special page will accept.
         *
         * @param string $search Prefix to search for
-        * @param integer $limit Maximum number of results to return
+        * @param int $limit Maximum number of results to return
         * @return string[] Matching subpages
         */
        public function prefixSearchSubpages( $search, $limit = 10 ) {
-               global $wgLogTypes;
-               $subpages = $wgLogTypes;
+               $subpages = $this->getConfig()->get( 'LogTypes' );
                $subpages[] = 'all';
                sort( $subpages );
                return self::prefixSearchArray( $search, $limit, $subpages );
        }
 
        private function parseParams( FormOptions $opts, $par ) {
-               global $wgLogTypes;
-
                # Get parameters
                $parms = explode( '/', ( $par = ( $par !== null ) ? $par : '' ) );
                $symsForAll = array( '*', 'all' );
                if ( $parms[0] != '' &&
-                       ( in_array( $par, $wgLogTypes ) || in_array( $par, $symsForAll ) )
+                       ( in_array( $par, $this->getConfig()->get( 'LogTypes' ) ) || in_array( $par, $symsForAll ) )
                ) {
                        $opts->setValue( 'type', $par );
                } elseif ( count( $parms ) == 2 ) {
@@ -211,10 +207,9 @@ class SpecialLog extends SpecialPage {
                }
 
                # Show button to hide log entries
-               global $wgScript;
                $s = Html::openElement(
                        'form',
-                       array( 'action' => $wgScript, 'id' => 'mw-log-deleterevision-submit' )
+                       array( 'action' => wfScript(), 'id' => 'mw-log-deleterevision-submit' )
                ) . "\n";
                $s .= Html::hidden( 'title', SpecialPage::getTitleFor( 'Revisiondelete' ) ) . "\n";
                $s .= Html::hidden( 'target', SpecialPage::getTitleFor( 'Log' ) ) . "\n";
index 4d9e7da..60225ea 100644 (file)
@@ -28,7 +28,7 @@
  * @ingroup SpecialPage
  */
 class MIMEsearchPage extends QueryPage {
-       protected $major, $minor;
+       protected $major, $minor, $mime;
 
        function __construct( $name = 'MIMEsearch' ) {
                parent::__construct( $name );
@@ -99,39 +99,42 @@ class MIMEsearchPage extends QueryPage {
         * that this report gives results in a logical order). As an aditional
         * note, mysql seems to by default order things by img_name ASC, which
         * is what we ideally want, so everything works out fine anyhow.
+        * @return array
         */
        function getOrderFields() {
                return array();
        }
 
-       function execute( $par ) {
-               global $wgScript;
-
-               $mime = $par ? $par : $this->getRequest()->getText( 'mime' );
-               $mime = trim( $mime );
+       /**
+        * Return HTML to put just before the results.
+        */
+       function getPageHeader() {
 
-               $this->setHeaders();
-               $this->outputHeader();
-               $this->getOutput()->addHTML(
-                       Xml::openElement(
+               return Xml::openElement(
                                'form',
-                               array( 'id' => 'specialmimesearch', 'method' => 'get', 'action' => $wgScript )
+                               array( 'id' => 'specialmimesearch', 'method' => 'get', 'action' => wfScript() )
                        ) .
-                               Xml::openElement( 'fieldset' ) .
-                               Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ) .
-                               Xml::element( 'legend', null, $this->msg( 'mimesearch' )->text() ) .
-                               Xml::inputLabel( $this->msg( 'mimetype' )->text(), 'mime', 'mime', 20, $mime ) .
-                               ' ' .
-                               Xml::submitButton( $this->msg( 'ilsubmit' )->text() ) .
-                               Xml::closeElement( 'fieldset' ) .
-                               Xml::closeElement( 'form' )
-               );
+                       Xml::openElement( 'fieldset' ) .
+                       Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ) .
+                       Xml::element( 'legend', null, $this->msg( 'mimesearch' )->text() ) .
+                       Xml::inputLabel( $this->msg( 'mimetype' )->text(), 'mime', 'mime', 20, $this->mime ) .
+                       ' ' .
+                       Xml::submitButton( $this->msg( 'ilsubmit' )->text() ) .
+                                       Xml::closeElement( 'fieldset' ) .
+                                       Xml::closeElement( 'form' );
+       }
 
-               list( $this->major, $this->minor ) = File::splitMime( $mime );
+       function execute( $par ) {
+               $this->mime = $par ? $par : $this->getRequest()->getText( 'mime' );
+               $this->mime = trim( $this->mime );
+               list( $this->major, $this->minor ) = File::splitMime( $this->mime );
 
                if ( $this->major == '' || $this->minor == '' || $this->minor == 'unknown' ||
                        !self::isValidType( $this->major )
                ) {
+                       $this->setHeaders();
+                       $this->outputHeader();
+                       $this->getOutput()->addHTML( $this->getPageHeader() );
                        return;
                }
 
@@ -185,7 +188,8 @@ class MIMEsearchPage extends QueryPage {
                        'video',
                        'message',
                        'model',
-                       'multipart'
+                       'multipart',
+                       'chemical'
                );
 
                return in_array( $type, $types );
index a27cf4c..3c9b515 100644 (file)
@@ -133,7 +133,7 @@ class SpecialMergeHistory extends SpecialPage {
                if ( !$this->mTargetObj instanceof Title ) {
                        $errors[] = $this->msg( 'mergehistory-invalid-source' )->parseAsBlock();
                } elseif ( !$this->mTargetObj->exists() ) {
-                       $errors[] = $this->msg( 'mergehistory-no-source', array( 'parse' ),
+                       $errors[] = $this->msg( 'mergehistory-no-source',
                                wfEscapeWikiText( $this->mTargetObj->getPrefixedText() )
                        )->parseAsBlock();
                }
@@ -141,7 +141,7 @@ class SpecialMergeHistory extends SpecialPage {
                if ( !$this->mDestObj instanceof Title ) {
                        $errors[] = $this->msg( 'mergehistory-invalid-destination' )->parseAsBlock();
                } elseif ( !$this->mDestObj->exists() ) {
-                       $errors[] = $this->msg( 'mergehistory-no-destination', array( 'parse' ),
+                       $errors[] = $this->msg( 'mergehistory-no-destination',
                                wfEscapeWikiText( $this->mDestObj->getPrefixedText() )
                        )->parseAsBlock();
                }
@@ -159,14 +159,12 @@ class SpecialMergeHistory extends SpecialPage {
        }
 
        function showMergeForm() {
-               global $wgScript;
-
                $this->getOutput()->addWikiMsg( 'mergehistory-header' );
 
                $this->getOutput()->addHTML(
                        Xml::openElement( 'form', array(
                                'method' => 'get',
-                               'action' => $wgScript ) ) .
+                               'action' => wfScript() ) ) .
                                '<fieldset>' .
                                Xml::element( 'legend', array(),
                                        $this->msg( 'mergehistory-box' )->text() ) .
@@ -328,14 +326,14 @@ class SpecialMergeHistory extends SpecialPage {
        /**
         * Actually attempt the history move
         *
-        * @todo: if all versions of page A are moved to B and then a user
+        * @todo if all versions of page A are moved to B and then a user
         * tries to do a reverse-merge via the "unmerge" log link, then page
         * A will still be a redirect (as it was after the original merge),
         * though it will have the old revisions back from before (as expected).
         * The user may have to "undo" the redirect manually to finish the "unmerge".
         * Maybe this should delete redirects at the target page of merges?
         *
-        * @return boolean Success
+        * @return bool Success
         */
        function merge() {
                # Get the titles directly from the IDs, in case the target page params
@@ -390,11 +388,11 @@ class SpecialMergeHistory extends SpecialPage {
                }
                # Check that there are not too many revisions to move
                $limit = 5000; // avoid too much slave lag
-               $count = $dbw->select( 'revision', '1',
+               $count = $dbw->selectRowCount( 'revision', '1',
                        array( 'rev_page' => $this->mTargetID, $timewhere ),
                        __METHOD__,
                        array( 'LIMIT' => $limit + 1 )
-               )->numRows();
+               );
                if ( $count > $limit ) {
                        $this->getOutput()->addWikiMsg( 'mergehistory-fail-toobig' );
 
@@ -452,6 +450,7 @@ class SpecialMergeHistory extends SpecialPage {
                                $dbw->insert( 'pagelinks',
                                        array(
                                                'pl_from' => $this->mDestID,
+                                               'pl_from_namespace' => $destTitle->getNamespace(),
                                                'pl_namespace' => $destTitle->getNamespace(),
                                                'pl_title' => $destTitle->getDBkey() ),
                                        __METHOD__
@@ -476,7 +475,7 @@ class SpecialMergeHistory extends SpecialPage {
                        array( $destTitle->getPrefixedText(), $timestampLimit ), $this->getUser()
                );
 
-               # @TODO: message should use redirect=no
+               # @todo message should use redirect=no
                $this->getOutput()->addWikiMsg( 'mergehistory-success',
                        $targetTitle->getPrefixedText(), $destTitle->getPrefixedText(), $count );
 
@@ -497,7 +496,7 @@ class MergeHistoryPager extends ReverseChronologicalPager {
        /** @var array */
        public $mConds;
 
-       function __construct( $form, $conds = array(), $source, $dest ) {
+       function __construct( $form, $conds, $source, $dest ) {
                $this->mForm = $form;
                $this->mConds = $conds;
                $this->title = $source;
@@ -551,7 +550,7 @@ class MergeHistoryPager extends ReverseChronologicalPager {
        function getQueryInfo() {
                $conds = $this->mConds;
                $conds['rev_page'] = $this->articleID;
-               $conds[] = "rev_timestamp < {$this->maxTimestamp}";
+               $conds[] = "rev_timestamp < " . $this->mDb->addQuotes( $this->maxTimestamp );
 
                return array(
                        'tables' => array( 'revision', 'page', 'user' ),
index 7223efd..ec9593f 100644 (file)
@@ -126,12 +126,12 @@ class MovePageForm extends UnlistedSpecialPage {
        /**
         * Show the form
         *
-        * @param array $err error messages. Each item is an error message.
+        * @param array $err Error messages. Each item is an error message.
         *    It may either be a string message name or array message name and
         *    parameters, like the second argument to OutputPage::wrapWikiMsg().
         */
        function showForm( $err ) {
-               global $wgContLang, $wgFixDoubleRedirects, $wgMaximumMovedPages;
+               global $wgContLang;
 
                $this->getSkin()->setRelevantTitle( $this->oldTitle );
 
@@ -190,7 +190,7 @@ class MovePageForm extends UnlistedSpecialPage {
                                );
                        }
 
-                       $out->addWikiMsg( $wgFixDoubleRedirects ?
+                       $out->addWikiMsg( $this->getConfig()->get( 'FixDoubleRedirects' ) ?
                                'movepagetext' :
                                'movepagetext-noredirectfixer'
                        );
@@ -221,7 +221,7 @@ class MovePageForm extends UnlistedSpecialPage {
                                || ( $oldTitleTalkSubpages && $canMoveSubpage ) );
 
                $dbr = wfGetDB( DB_SLAVE );
-               if ( $wgFixDoubleRedirects ) {
+               if ( $this->getConfig()->get( 'FixDoubleRedirects' ) ) {
                        $hasRedirects = $dbr->selectField( 'redirect', '1',
                                array(
                                        'rd_namespace' => $this->oldTitle->getNamespace(),
@@ -419,6 +419,7 @@ class MovePageForm extends UnlistedSpecialPage {
                }
 
                if ( $canMoveSubpage ) {
+                       $maximumMovedPages = $this->getConfig()->get( 'MaximumMovedPages' );
                        $out->addHTML( "
                                <tr>
                                        <td></td>
@@ -435,7 +436,7 @@ class MovePageForm extends UnlistedSpecialPage {
                                                        ( $this->oldTitle->hasSubpages()
                                                                ? 'move-subpages'
                                                                : 'move-talk-subpages' )
-                                               )->numParams( $wgMaximumMovedPages )->params( $wgMaximumMovedPages )->parse()
+                                               )->numParams( $maximumMovedPages )->params( $maximumMovedPages )->parse()
                                        ) .
                                        "</td>
                                </tr>"
@@ -480,8 +481,6 @@ class MovePageForm extends UnlistedSpecialPage {
        }
 
        function doSubmit() {
-               global $wgMaximumMovedPages, $wgFixDoubleRedirects;
-
                $user = $this->getUser();
 
                if ( $user->pingLimiter( 'move' ) ) {
@@ -557,7 +556,7 @@ class MovePageForm extends UnlistedSpecialPage {
                        return;
                }
 
-               if ( $wgFixDoubleRedirects && $this->fixRedirects ) {
+               if ( $this->getConfig()->get( 'FixDoubleRedirects' ) && $this->fixRedirects ) {
                        DoubleRedirectJob::fixRedirects( 'move', $ot, $nt );
                }
 
@@ -713,9 +712,10 @@ class MovePageForm extends UnlistedSpecialPage {
                                                ->rawParams( $oldLink, $newLink )->escaped();
                                        ++$count;
 
-                                       if ( $count >= $wgMaximumMovedPages ) {
+                                       $maximumMovedPages = $this->getConfig()->get( 'MaximumMovedPages' );
+                                       if ( $count >= $maximumMovedPages ) {
                                                $extraOutput[] = $this->msg( 'movepage-max-pages' )
-                                                       ->numParams( $wgMaximumMovedPages )->escaped();
+                                                       ->numParams( $maximumMovedPages )->escaped();
                                                break;
                                        }
                                } else {
diff --git a/includes/specials/SpecialMyLanguage.php b/includes/specials/SpecialMyLanguage.php
new file mode 100644 (file)
index 0000000..71b1893
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Implements Special:MyLanguage
+ *
+ * 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 Niklas Laxström
+ * @author Siebrand Mazeland
+ * @copyright Copyright © 2010-2013 Niklas Laxström, Siebrand Mazeland
+ */
+
+/**
+ * Unlisted special page just to redirect the user to the translated version of
+ * a page, if it exists.
+ *
+ * Usage: [[Special:MyLanguage/Page name|link text]]
+ *
+ * @since 1.24
+ * @ingroup SpecialPage
+ */
+class SpecialMyLanguage extends RedirectSpecialArticle {
+       public function __construct() {
+               parent::__construct( 'MyLanguage' );
+       }
+
+       /**
+        * If the special page is a redirect, then get the Title object it redirects to.
+        * False otherwise.
+        *
+        * @param string $par Subpage string
+        * @return Title|bool
+        */
+       public function getRedirect( $par ) {
+               $title = $this->findTitle( $par );
+               // Go to the main page if given invalid title.
+               if ( !$title ) {
+                       $title = Title::newMainPage();
+               }
+               return $title;
+       }
+
+       /**
+        * Assuming the user's interface language is fi. Given input Page, it
+        * returns Page/fi if it exists, otherwise Page. Given input Page/de,
+        * it returns Page/fi if it exists, otherwise Page/de if it exists,
+        * otherwise Page.
+        *
+        * @param string $par
+        * @return Title|null
+        */
+       public function findTitle( $par ) {
+               // base = title without language code suffix
+               // provided = the title as it was given
+               $base = $provided = Title::newFromText( $par );
+
+               if ( $base && strpos( $par, '/' ) !== false ) {
+                       $pos = strrpos( $par, '/' );
+                       $basepage = substr( $par, 0, $pos );
+                       $code = substr( $par, $pos + 1 );
+                       if ( strlen( $code ) && Language::isKnownLanguageTag( $code ) ) {
+                               $base = Title::newFromText( $basepage );
+                       }
+               }
+
+               if ( !$base ) {
+                       return null;
+               }
+
+               $uiCode = $this->getLanguage()->getCode();
+               $proposed = $base->getSubpage( $uiCode );
+               if ( $uiCode !== $this->getConfig()->get( 'LanguageCode' ) && $proposed && $proposed->exists() ) {
+                       return $proposed;
+               } elseif ( $provided && $provided->exists() ) {
+                       return $provided;
+               } else {
+                       return $base;
+               }
+       }
+}
index 147d176..546c191 100644 (file)
@@ -89,7 +89,6 @@ class NewFilesPager extends ReverseChronologicalPager {
        }
 
        function getQueryInfo() {
-               global $wgMiserMode;
                $conds = $jconds = array();
                $tables = array( 'image' );
 
@@ -109,7 +108,7 @@ class NewFilesPager extends ReverseChronologicalPager {
                        }
                }
 
-               if ( !$wgMiserMode && $this->like !== null ) {
+               if ( !$this->getConfig()->get( 'MiserMode' ) && $this->like !== null ) {
                        $dbr = wfGetDB( DB_SLAVE );
                        $likeObj = Title::newFromURL( $this->like );
                        if ( $likeObj instanceof Title ) {
@@ -141,12 +140,11 @@ class NewFilesPager extends ReverseChronologicalPager {
                        // Note that null for mode is taken to mean use default.
                        $mode = $this->getRequest()->getVal( 'gallerymode', null );
                        try {
-                               $this->gallery = ImageGalleryBase::factory( $mode );
+                               $this->gallery = ImageGalleryBase::factory( $mode, $this->getContext() );
                        } catch ( MWException $e ) {
                                // User specified something invalid, fallback to default.
-                               $this->gallery = ImageGalleryBase::factory();
+                               $this->gallery = ImageGalleryBase::factory( false, $this->getContext() );
                        }
-                       $this->gallery->setContext( $this->getContext() );
                }
 
                return '';
@@ -173,8 +171,6 @@ class NewFilesPager extends ReverseChronologicalPager {
        }
 
        function getForm() {
-               global $wgMiserMode;
-
                $fields = array(
                        'like' => array(
                                'type' => 'text',
@@ -198,7 +194,7 @@ class NewFilesPager extends ReverseChronologicalPager {
                        ),
                );
 
-               if ( $wgMiserMode ) {
+               if ( $this->getConfig()->get( 'MiserMode' ) ) {
                        unset( $fields['like'] );
                }
 
index 1ec7006..0b70bb7 100644 (file)
@@ -117,7 +117,6 @@ class SpecialNewpages extends IncludableSpecialPage {
         * Show a form for filtering namespace and username
         *
         * @param string $par
-        * @return string
         */
        public function execute( $par ) {
                $out = $this->getOutput();
@@ -199,8 +198,6 @@ class SpecialNewpages extends IncludableSpecialPage {
        }
 
        protected function form() {
-               global $wgScript;
-
                // Consume values
                $this->opts->consumeValue( 'offset' ); // don't carry offset, DWIW
                $namespace = $this->opts->consumeValue( 'namespace' );
@@ -224,7 +221,7 @@ class SpecialNewpages extends IncludableSpecialPage {
                        list( $tagFilterLabel, $tagFilterSelector ) = $tagFilter;
                }
 
-               $form = Xml::openElement( 'form', array( 'action' => $wgScript ) ) .
+               $form = Xml::openElement( 'form', array( 'action' => wfScript() ) ) .
                        Html::hidden( 'title', $this->getPageTitle()->getPrefixedDBkey() ) .
                        Xml::fieldset( $this->msg( 'newpages' )->text() ) .
                        Xml::openElement( 'table', array( 'id' => 'mw-newpages-table' ) ) .
@@ -405,21 +402,20 @@ class SpecialNewpages extends IncludableSpecialPage {
         * @param string $type
         */
        protected function feed( $type ) {
-               global $wgFeed, $wgFeedClasses, $wgFeedLimit;
-
-               if ( !$wgFeed ) {
+               if ( !$this->getConfig()->get( 'Feed' ) ) {
                        $this->getOutput()->addWikiMsg( 'feed-unavailable' );
 
                        return;
                }
 
-               if ( !isset( $wgFeedClasses[$type] ) ) {
+               $feedClasses = $this->getConfig()->get( 'FeedClasses' );
+               if ( !isset( $feedClasses[$type] ) ) {
                        $this->getOutput()->addWikiMsg( 'feed-invalid' );
 
                        return;
                }
 
-               $feed = new $wgFeedClasses[$type](
+               $feed = new $feedClasses[$type](
                        $this->feedTitle(),
                        $this->msg( 'tagline' )->text(),
                        $this->getPageTitle()->getFullURL()
@@ -427,7 +423,7 @@ class SpecialNewpages extends IncludableSpecialPage {
 
                $pager = new NewPagesPager( $this, $this->opts );
                $limit = $this->opts->getValue( 'limit' );
-               $pager->mLimit = min( $limit, $wgFeedLimit );
+               $pager->mLimit = min( $limit, $this->getConfig()->get( 'FeedLimit' ) );
 
                $feed->outHeader();
                if ( $pager->getNumRows() > 0 ) {
@@ -439,10 +435,11 @@ class SpecialNewpages extends IncludableSpecialPage {
        }
 
        protected function feedTitle() {
-               global $wgLanguageCode, $wgSitename;
                $desc = $this->getDescription();
+               $code = $this->getConfig()->get( 'LanguageCode' );
+               $sitename = $this->getConfig()->get( 'Sitename' );
 
-               return "$wgSitename - $desc [$wgLanguageCode]";
+               return "$sitename - $desc [$code]";
        }
 
        protected function feedItem( $row ) {
index 6697004..2acf23c 100644 (file)
@@ -30,7 +30,7 @@
  */
 class SpecialPageLanguage extends FormSpecialPage {
        /**
-        * @var $goToUrl URL to go to if language change successful
+        * @var string URL to go to if language change successful
         */
        private $goToUrl;
 
@@ -43,7 +43,6 @@ class SpecialPageLanguage extends FormSpecialPage {
        }
 
        protected function getFormFields() {
-               global $wgLanguageCode;
                // Get default from the subpage of Special page
                $defaultName = $this->par;
 
@@ -81,12 +80,16 @@ class SpecialPageLanguage extends FormSpecialPage {
                        'type' => 'select',
                        'options' => $options,
                        'label-message' => 'pagelang-language',
-                       'default' => $wgLanguageCode
+                       'default' => $this->getConfig()->get( 'LanguageCode' ),
                );
 
                return $page;
        }
 
+       protected function postText() {
+               return $this->showLogFragment( $this->par );
+       }
+
        public function alterForm( HTMLForm $form ) {
                $form->setDisplayFormat( 'vform' );
                $form->setWrapperLegend( false );
@@ -96,6 +99,7 @@ class SpecialPageLanguage extends FormSpecialPage {
        /**
         *
         * @param array $data
+        * @return bool
         */
        public function onSubmit( array $data ) {
                $title = Title::newFromText( $data['pagename'] );
@@ -109,7 +113,7 @@ class SpecialPageLanguage extends FormSpecialPage {
                // Returns the default since the page is not loaded from DB
                $defLang = $title->getPageLanguage()->getCode();
 
-               $pageId =  $title->getArticleID();
+               $pageId = $title->getArticleID();
 
                // Check if article exists
                if ( !$pageId ) {
@@ -180,4 +184,12 @@ class SpecialPageLanguage extends FormSpecialPage {
                // Success causes a redirect
                $this->getOutput()->redirect( $this->goToUrl );
        }
+
+       function showLogFragment( $title ) {
+               $moveLogPage = new LogPage( 'pagelang' );
+               $out1 = Xml::element( 'h2', null, $moveLogPage->getName()->text() );
+               $out2 = '';
+               LogEventsList::showLogExtract( $out2, 'pagelang', $title );
+               return $out1 . $out2;
+       }
 }
index 05f0b2b..f5b19cc 100644 (file)
@@ -82,7 +82,7 @@ class SpecialPagesWithProp extends QueryPage {
         * Return an array of subpages beginning with $search that this special page will accept.
         *
         * @param string $search Prefix to search for
-        * @param integer $limit Maximum number of results to return
+        * @param int $limit Maximum number of results to return
         * @return string[] Matching subpages
         */
        public function prefixSearchSubpages( $search, $limit = 10 ) {
index c60b347..3061c85 100644 (file)
@@ -62,9 +62,10 @@ class SpecialPasswordReset extends FormSpecialPage {
        }
 
        protected function getFormFields() {
-               global $wgPasswordResetRoutes, $wgAuth;
+               global $wgAuth;
+               $resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
                $a = array();
-               if ( isset( $wgPasswordResetRoutes['username'] ) && $wgPasswordResetRoutes['username'] ) {
+               if ( isset( $resetRoutes['username'] ) && $resetRoutes['username'] ) {
                        $a['Username'] = array(
                                'type' => 'text',
                                'label-message' => 'passwordreset-username',
@@ -75,14 +76,14 @@ class SpecialPasswordReset extends FormSpecialPage {
                        }
                }
 
-               if ( isset( $wgPasswordResetRoutes['email'] ) && $wgPasswordResetRoutes['email'] ) {
+               if ( isset( $resetRoutes['email'] ) && $resetRoutes['email'] ) {
                        $a['Email'] = array(
                                'type' => 'email',
                                'label-message' => 'passwordreset-email',
                        );
                }
 
-               if ( isset( $wgPasswordResetRoutes['domain'] ) && $wgPasswordResetRoutes['domain'] ) {
+               if ( isset( $resetRoutes['domain'] ) && $resetRoutes['domain'] ) {
                        $domains = $wgAuth->domainList();
                        $a['Domain'] = array(
                                'type' => 'select',
@@ -103,7 +104,7 @@ class SpecialPasswordReset extends FormSpecialPage {
        }
 
        public function alterForm( HTMLForm $form ) {
-               global $wgPasswordResetRoutes;
+               $resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
 
                $form->setDisplayFormat( 'vform' );
                // Turn the old-school line around the form off.
@@ -115,13 +116,13 @@ class SpecialPasswordReset extends FormSpecialPage {
                $form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
 
                $i = 0;
-               if ( isset( $wgPasswordResetRoutes['username'] ) && $wgPasswordResetRoutes['username'] ) {
+               if ( isset( $resetRoutes['username'] ) && $resetRoutes['username'] ) {
                        $i++;
                }
-               if ( isset( $wgPasswordResetRoutes['email'] ) && $wgPasswordResetRoutes['email'] ) {
+               if ( isset( $resetRoutes['email'] ) && $resetRoutes['email'] ) {
                        $i++;
                }
-               if ( isset( $wgPasswordResetRoutes['domain'] ) && $wgPasswordResetRoutes['domain'] ) {
+               if ( isset( $resetRoutes['domain'] ) && $resetRoutes['domain'] ) {
                        $i++;
                }
 
@@ -222,19 +223,16 @@ class SpecialPasswordReset extends FormSpecialPage {
                // Check against password throttle
                foreach ( $users as $user ) {
                        if ( $user->isPasswordReminderThrottled() ) {
-                               global $wgPasswordReminderResendTime;
 
                                # Round the time in hours to 3 d.p., in case someone is specifying
                                # minutes or seconds.
                                return array( array(
                                        'throttled-mailpassword',
-                                       round( $wgPasswordReminderResendTime, 3 )
+                                       round( $this->getConfig()->get( 'PasswordReminderResendTime' ), 3 )
                                ) );
                        }
                }
 
-               global $wgNewPasswordExpiry;
-
                // All the users will have the same email address
                if ( $firstUser->getEmail() == '' ) {
                        // This won't be reachable from the email route, so safe to expose the username
@@ -273,7 +271,7 @@ class SpecialPasswordReset extends FormSpecialPage {
                        $passwordBlock,
                        count( $passwords ),
                        '<' . Title::newMainPage()->getCanonicalURL() . '>',
-                       round( $wgNewPasswordExpiry / 86400 )
+                       round( $this->getConfig()->get( 'NewPasswordExpiry' ) / 86400 )
                );
 
                $title = $this->msg( 'passwordreset-emailtitle' );
@@ -320,11 +318,12 @@ class SpecialPasswordReset extends FormSpecialPage {
        }
 
        protected function canChangePassword( User $user ) {
-               global $wgPasswordResetRoutes, $wgEnableEmail, $wgAuth;
+               global $wgAuth;
+               $resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
 
                // Maybe password resets are disabled, or there are no allowable routes
-               if ( !is_array( $wgPasswordResetRoutes ) ||
-                       !in_array( true, array_values( $wgPasswordResetRoutes ) )
+               if ( !is_array( $resetRoutes ) ||
+                       !in_array( true, array_values( $resetRoutes ) )
                ) {
                        return 'passwordreset-disabled';
                }
@@ -335,7 +334,7 @@ class SpecialPasswordReset extends FormSpecialPage {
                }
 
                // Maybe email features have been disabled
-               if ( !$wgEnableEmail ) {
+               if ( !$this->getConfig()->get( 'EnableEmail' ) ) {
                        return 'passwordreset-emaildisabled';
                }
 
index 7554e37..0ba7385 100644 (file)
@@ -79,11 +79,7 @@ class SpecialProtectedpages extends SpecialPage {
                ) );
 
                if ( $pager->getNumRows() ) {
-                       $this->getOutput()->addHTML(
-                               $pager->getNavigationBar() .
-                                       $pager->getBody() .
-                                       $pager->getNavigationBar()
-                       );
+                       $this->getOutput()->addParserOutputContent( $pager->getFullOutput() );
                } else {
                        $this->getOutput()->addWikiMsg( 'protectedpagesempty' );
                }
@@ -103,11 +99,9 @@ class SpecialProtectedpages extends SpecialPage {
        protected function showOptions( $namespace, $type = 'edit', $level, $sizetype,
                $size, $indefOnly, $cascadeOnly, $noRedirect
        ) {
-               global $wgScript;
-
                $title = $this->getPageTitle();
 
-               return Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) .
+               return Xml::openElement( 'form', array( 'method' => 'get', 'action' => wfScript() ) ) .
                        Xml::openElement( 'fieldset' ) .
                        Xml::element( 'legend', array(), $this->msg( 'protectedpages' )->text() ) .
                        Html::hidden( 'title', $title->getPrefixedDBkey() ) . "\n" .
@@ -252,14 +246,12 @@ class SpecialProtectedpages extends SpecialPage {
         * @return string Formatted HTML
         */
        protected function getLevelMenu( $pr_level ) {
-               global $wgRestrictionLevels;
-
                // Temporary array
                $m = array( $this->msg( 'restriction-level-all' )->text() => 0 );
                $options = array();
 
                // First pass to load the log names
-               foreach ( $wgRestrictionLevels as $type ) {
+               foreach ( $this->getConfig()->get( 'RestrictionLevels' ) as $type ) {
                        // Messages used can be 'restriction-level-sysop' and 'restriction-level-autoconfirmed'
                        if ( $type != '' && $type != '*' ) {
                                $text = $this->msg( "restriction-level-$type" )->text();
@@ -562,7 +554,7 @@ class ProtectedPagesPager extends TablePager {
        }
 
        public function getTableClass() {
-               return 'TablePager mw-protectedpages';
+               return parent::getTableClass() . ' mw-protectedpages';
        }
 
        function getIndexField() {
index cb6ec3c..a40da87 100644 (file)
@@ -133,8 +133,7 @@ class SpecialProtectedtitles extends SpecialPage {
         * @private
         */
        function showOptions( $namespace, $type = 'edit', $level ) {
-               global $wgScript;
-               $action = htmlspecialchars( $wgScript );
+               $action = htmlspecialchars( wfScript() );
                $title = $this->getPageTitle();
                $special = htmlspecialchars( $title->getPrefixedDBkey() );
 
@@ -175,14 +174,12 @@ class SpecialProtectedtitles extends SpecialPage {
         * @private
         */
        function getLevelMenu( $pr_level ) {
-               global $wgRestrictionLevels;
-
                // Temporary array
                $m = array( $this->msg( 'restriction-level-all' )->text() => 0 );
                $options = array();
 
                // First pass to load the log names
-               foreach ( $wgRestrictionLevels as $type ) {
+               foreach ( $this->getConfig()->get( 'RestrictionLevels' ) as $type ) {
                        if ( $type != '' && $type != '*' ) {
                                // Messages: restriction-level-sysop, restriction-level-autoconfirmed
                                $text = $this->msg( "restriction-level-$type" )->text();
index 2707916..570ab3b 100644 (file)
@@ -46,7 +46,7 @@
  *
  * @ingroup SpecialPage
  */
-class SpecialRandomInCategory extends SpecialPage {
+class SpecialRandomInCategory extends FormSpecialPage {
        protected $extra = array(); // Extra SQL statements
        protected $category = false; // Title object of category
        protected $maxOffset = 30; // Max amount to fudge randomness by.
@@ -67,12 +67,35 @@ class SpecialRandomInCategory extends SpecialPage {
                $this->minTimestamp = null;
        }
 
-       public function execute( $par ) {
-               global $wgScript;
+       protected function getFormFields() {
+               $form = array(
+                       'category' => array(
+                               'type' => 'text',
+                               'label-message' => 'randomincategory-category',
+                               'required' => true,
+                       )
+               );
+
+               return $form;
+       }
+
+       public function requiresWrite() {
+               return false;
+       }
 
+       public function requiresUnblock() {
+               return false;
+       }
+
+       protected function setParameter( $par ) {
+               // if subpage present, fake form submission
+               $this->onSubmit( array( 'category' => $par ) );
+       }
+
+       public function onSubmit( array $data ) {
                $cat = false;
 
-               $categoryStr = $this->getRequest()->getText( 'category', $par );
+               $categoryStr = $data['category'];
 
                if ( $categoryStr ) {
                        $cat = Title::newFromText( $categoryStr, NS_CATEGORY );
@@ -88,41 +111,25 @@ class SpecialRandomInCategory extends SpecialPage {
                }
 
                if ( !$this->category && $categoryStr ) {
-                       $this->setHeaders();
-                       $this->getOutput()->addWikiMsg( 'randomincategory-invalidcategory',
+                       $msg = $this->msg( 'randomincategory-invalidcategory',
                                wfEscapeWikiText( $categoryStr ) );
 
-                       return;
+                       return Status::newFatal( $msg );
+
                } elseif ( !$this->category ) {
-                       $this->setHeaders();
-                       $input = Html::input( 'category' );
-                       $submitText = $this->msg( 'randomincategory-selectcategory-submit' )->text();
-                       $submit = Html::input( '', $submitText, 'submit' );
-
-                       $msg = $this->msg( 'randomincategory-selectcategory' );
-                       $form = Html::rawElement( 'form', array( 'action' => $wgScript ),
-                               Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ) .
-                               $msg->rawParams( $input, $submit )->parse()
-                       );
-                       $this->getOutput()->addHtml( $form );
-
-                       return;
+                       return; // no data sent
                }
 
                $title = $this->getRandomTitle();
 
                if ( is_null( $title ) ) {
-                       $this->setHeaders();
-                       $this->getOutput()->addWikiMsg( 'randomincategory-nopages',
+                       $msg = $this->msg( 'randomincategory-nopages',
                                $this->category->getText() );
 
-                       return;
+                       return Status::newFatal( $msg );
                }
 
-               $query = $this->getRequest()->getValues();
-               unset( $query['title'] );
-               unset( $query['category'] );
-               $this->getOutput()->redirect( $title->getFullURL( $query ) );
+               $this->getOutput()->redirect( $title->getFullURL() );
        }
 
        /**
@@ -239,7 +246,7 @@ class SpecialRandomInCategory extends SpecialPage {
         *
         * @param Title $category
         * @return array The lowest and highest timestamp
-        * @throws MWException if category has no entries.
+        * @throws MWException If category has no entries.
         */
        protected function getMinAndMaxForCat( Title $category ) {
                $dbr = wfGetDB( DB_SLAVE );
index 24b363d..6d8f59b 100644 (file)
@@ -56,7 +56,9 @@ class RandomPage extends SpecialPage {
        public function execute( $par ) {
                global $wgContLang;
 
-               if ( $par ) {
+               if ( is_string( $par ) ) {
+                       // Testing for stringiness since we want to catch
+                       // the empty string to mean main namespace only.
                        $this->setNamespace( $wgContLang->getNsIndex( $par ) );
                }
 
index f770307..17d7664 100644 (file)
@@ -192,8 +192,6 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
         * @return bool|ResultWrapper Result or false (for Recentchangeslinked only)
         */
        public function doMainQuery( $conds, $opts ) {
-               global $wgAllowCategorizedRecentChanges;
-
                $dbr = $this->getDB();
                $user = $this->getUser();
 
@@ -229,9 +227,8 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                        $opts['tagfilter']
                );
 
-               if ( !wfRunHooks( 'SpecialRecentChangesQuery',
-                       array( &$conds, &$tables, &$join_conds, $opts, &$query_options, &$fields ),
-                       '1.23' )
+               if ( !$this->runMainQueryHook( $tables, $fields, $conds, $query_options, $join_conds,
+                       $opts )
                ) {
                        return false;
                }
@@ -248,13 +245,22 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                );
 
                // Build the final data
-               if ( $wgAllowCategorizedRecentChanges ) {
+               if ( $this->getConfig()->get( 'AllowCategorizedRecentChanges' ) ) {
                        $this->filterByCategories( $rows, $opts );
                }
 
                return $rows;
        }
 
+       protected function runMainQueryHook( &$tables, &$fields, &$conds, &$query_options, &$join_conds, $opts ) {
+               return parent::runMainQueryHook( $tables, $fields, $conds, $query_options, $join_conds, $opts )
+                       && wfRunHooks(
+                               'SpecialRecentChangesQuery',
+                               array( &$conds, &$tables, &$join_conds, $opts, &$query_options, &$fields ),
+                               '1.23'
+                       );
+       }
+
        public function outputFeedLinks() {
                $this->addFeedLinks( $this->getFeedQuery() );
        }
@@ -265,14 +271,14 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
         * @return array
         */
        private function getFeedQuery() {
-               global $wgFeedLimit;
                $query = array_filter( $this->getOptions()->getAllValues(), function ( $value ) {
                        // API handles empty parameters in a different way
                        return $value !== '';
                } );
                $query['action'] = 'feedrecentchanges';
-               if ( $query['limit'] > $wgFeedLimit ) {
-                       $query['limit'] = $wgFeedLimit;
+               $feedLimit = $this->getConfig()->get( 'FeedLimit' );
+               if ( $query['limit'] > $feedLimit ) {
+                       $query['limit'] = $feedLimit;
                }
 
                return $query;
@@ -285,11 +291,9 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
         * @param FormOptions $opts
         */
        public function outputChangesList( $rows, $opts ) {
-               global $wgRCShowWatchingUsers, $wgShowUpdatedMarker;
-
                $limit = $opts['limit'];
 
-               $showWatcherCount = $wgRCShowWatchingUsers
+               $showWatcherCount = $this->getConfig()->get( 'RCShowWatchingUsers' )
                        && $this->getUser()->getOption( 'shownumberswatching' );
                $watcherCache = array();
 
@@ -307,7 +311,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                        $rc = RecentChange::newFromRow( $obj );
                        $rc->counter = $counter++;
                        # Check if the page has been updated since the last visit
-                       if ( $wgShowUpdatedMarker && !empty( $obj->wl_notificationtimestamp ) ) {
+                       if ( $this->getConfig()->get( 'ShowUpdatedMarker' ) && !empty( $obj->wl_notificationtimestamp ) ) {
                                $rc->notificationtimestamp = ( $obj->rc_timestamp >= $obj->wl_notificationtimestamp );
                        } else {
                                $rc->notificationtimestamp = false; // Default
@@ -344,20 +348,21 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                                $this->msg( 'recentchanges-noresult' )->parse() .
                                '</div>'
                        );
+                       if ( !$this->including() ) {
+                               $this->getOutput()->setStatusCode( 404 );
+                       }
                } else {
                        $this->getOutput()->addHTML( $rclistOutput );
                }
        }
 
        /**
-        * Return the text to be displayed above the changes
+        * Set the text to be displayed above the changes
         *
         * @param FormOptions $opts
-        * @return string XHTML
+        * @param int $numRows Number of rows in the result to show after this header
         */
-       public function doHeader( $opts ) {
-               global $wgScript;
-
+       public function doHeader( $opts, $numRows ) {
                $this->setTopText( $opts );
 
                $defaults = $opts->getAllValues();
@@ -365,7 +370,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
 
                $panel = array();
                $panel[] = self::makeLegend( $this->getContext() );
-               $panel[] = $this->optionsPanel( $defaults, $nondefaults );
+               $panel[] = $this->optionsPanel( $defaults, $nondefaults, $numRows );
                $panel[] = '<hr />';
 
                $extraOpts = $this->getExtraOptions( $opts );
@@ -409,7 +414,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
 
                $t = $this->getPageTitle();
                $out .= Html::hidden( 'title', $t->getPrefixedText() );
-               $form = Xml::tags( 'form', array( 'action' => $wgScript ), $out );
+               $form = Xml::tags( 'form', array( 'action' => wfScript() ), $out );
                $panel[] = $form;
                $panelString = implode( "\n", $panel );
 
@@ -459,8 +464,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $extraOpts = array();
                $extraOpts['namespace'] = $this->namespaceFilterForm( $opts );
 
-               global $wgAllowCategorizedRecentChanges;
-               if ( $wgAllowCategorizedRecentChanges ) {
+               if ( $this->getConfig()->get( 'AllowCategorizedRecentChanges' ) ) {
                        $extraOpts['category'] = $this->categoryFilterForm( $opts );
                }
 
@@ -591,9 +595,9 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                }
 
                # Look up
-               $c = new Categoryfinder;
-               $c->seed( $articles, $cats, $opts['categories_any'] ? 'OR' : 'AND' );
-               $match = $c->run();
+               $catFind = new CategoryFinder;
+               $catFind->seed( $articles, $cats, $opts['categories_any'] ? 'OR' : 'AND' );
+               $match = $catFind->run();
 
                # Filter
                $newrows = array();
@@ -640,11 +644,10 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
         *
         * @param array $defaults
         * @param array $nondefaults
+        * @param int $numRows Number of rows in the result to show after this header
         * @return string
         */
-       function optionsPanel( $defaults, $nondefaults ) {
-               global $wgRCLinkLimits, $wgRCLinkDays;
-
+       function optionsPanel( $defaults, $nondefaults, $numRows ) {
                $options = $nondefaults + $defaults;
 
                $note = '';
@@ -656,19 +659,24 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $lang = $this->getLanguage();
                $user = $this->getUser();
                if ( $options['from'] ) {
-                       $note .= $this->msg( 'rcnotefrom' )->numParams( $options['limit'] )->params(
-                               $lang->userTimeAndDate( $options['from'], $user ),
-                               $lang->userDate( $options['from'], $user ),
-                               $lang->userTime( $options['from'], $user ) )->parse() . '<br />';
+                       $note .= $this->msg( 'rcnotefrom' )
+                               ->numParams( $options['limit'] )
+                               ->params(
+                                       $lang->userTimeAndDate( $options['from'], $user ),
+                                       $lang->userDate( $options['from'], $user ),
+                                       $lang->userTime( $options['from'], $user )
+                               )
+                               ->numParams( $numRows )
+                               ->parse() . '<br />';
                }
 
                # Sort data for display and make sure it's unique after we've added user data.
-               $linkLimits = $wgRCLinkLimits;
+               $linkLimits = $this->getConfig()->get( 'RCLinkLimits' );
                $linkLimits[] = $options['limit'];
                sort( $linkLimits );
                $linkLimits = array_unique( $linkLimits );
 
-               $linkDays = $wgRCLinkDays;
+               $linkDays = $this->getConfig()->get( 'RCLinkDays' );
                $linkDays[] = $options['days'];
                sort( $linkDays );
                $linkDays = array_unique( $linkDays );
index e73cabc..3ad9f0f 100644 (file)
@@ -109,9 +109,8 @@ class SpecialRecentChangesLinked extends SpecialRecentChanges {
                        $opts['tagfilter']
                );
 
-               if ( !wfRunHooks( 'SpecialRecentChangesQuery',
-                       array( &$conds, &$tables, &$join_conds, $opts, &$query_options, &$select ),
-                       '1.23' )
+               if ( !$this->runMainQueryHook( $tables, $select, $conds, $query_options, $join_conds,
+                       $opts )
                ) {
                        return false;
                }
@@ -225,6 +224,7 @@ class SpecialRecentChangesLinked extends SpecialRecentChanges {
                $target = $this->getTargetTitle();
                if ( $target ) {
                        $this->getOutput()->addBacklinkSubtitle( $target );
+                       $this->getSkin()->setRelevantTitle( $target );
                }
        }
 
index 4926d6d..2022d74 100644 (file)
@@ -55,6 +55,7 @@ class SpecialRedirect extends FormSpecialPage {
 
        /**
         * Set $mType and $mValue based on parsed value of $subpage.
+        * @param string $subpage
         */
        function setParameter( $subpage ) {
                // parse $subpage to pull out the parts
@@ -66,7 +67,7 @@ class SpecialRedirect extends FormSpecialPage {
        /**
         * Handle Special:Redirect/user/xxxx (by redirecting to User:YYYY)
         *
-        * @return string|null url to redirect to, or null if $mValue is invalid.
+        * @return string|null Url to redirect to, or null if $mValue is invalid.
         */
        function dispatchUser() {
                if ( !ctype_digit( $this->mValue ) ) {
@@ -85,7 +86,7 @@ class SpecialRedirect extends FormSpecialPage {
        /**
         * Handle Special:Redirect/file/xxxx
         *
-        * @return string|null url to redirect to, or null if $mValue is not found.
+        * @return string|null Url to redirect to, or null if $mValue is not found.
         */
        function dispatchFile() {
                $title = Title::makeTitleSafe( NS_FILE, $this->mValue );
@@ -121,7 +122,7 @@ class SpecialRedirect extends FormSpecialPage {
         * Handle Special:Redirect/revision/xxx
         * (by redirecting to index.php?oldid=xxx)
         *
-        * @return string|null url to redirect to, or null if $mValue is invalid.
+        * @return string|null Url to redirect to, or null if $mValue is invalid.
         */
        function dispatchRevision() {
                $oldid = $this->mValue;
@@ -141,7 +142,7 @@ class SpecialRedirect extends FormSpecialPage {
        /**
         * Handle Special:Redirect/page/xxx (by redirecting to index.php?curid=xxx)
         *
-        * @return string|null url to redirect to, or null if $mValue is invalid.
+        * @return string|null Url to redirect to, or null if $mValue is invalid.
         */
        function dispatchPage() {
                $curid = $this->mValue;
@@ -164,7 +165,7 @@ class SpecialRedirect extends FormSpecialPage {
         * or do nothing (if $mValue wasn't set) allowing the form to be
         * displayed.
         *
-        * @return bool true if a redirect was successfully handled.
+        * @return bool True if a redirect was successfully handled.
         */
        function dispatch() {
                // the various namespaces supported by Special:Redirect
index 864485c..4add742 100644 (file)
@@ -40,16 +40,15 @@ class SpecialResetTokens extends FormSpecialPage {
         * @return array
         */
        protected function getTokensList() {
-               global $wgHiddenPrefs;
-
                if ( !isset( $this->tokensList ) ) {
                        $tokens = array(
                                array( 'preference' => 'watchlisttoken', 'label-message' => 'resettokens-watchlist-token' ),
                        );
                        wfRunHooks( 'SpecialResetTokensTokens', array( &$tokens ) );
 
-                       $tokens = array_filter( $tokens, function ( $tok ) use ( $wgHiddenPrefs ) {
-                               return !in_array( $tok['preference'], $wgHiddenPrefs );
+                       $hiddenPrefs = $this->getConfig()->get( 'HiddenPrefs' );
+                       $tokens = array_filter( $tokens, function ( $tok ) use ( $hiddenPrefs ) {
+                               return !in_array( $tok['preference'], $hiddenPrefs );
                        } );
 
                        $this->tokensList = $tokens;
@@ -78,6 +77,7 @@ class SpecialResetTokens extends FormSpecialPage {
        /**
         * Display appropriate message if there's nothing to do.
         * The submit button is also suppressed in this case (see alterForm()).
+        * @return array
         */
        protected function getFormFields() {
                $user = $this->getUser();
@@ -113,6 +113,7 @@ class SpecialResetTokens extends FormSpecialPage {
        /**
         * Suppress the submit button if there's nothing to do;
         * provide additional message on it otherwise.
+        * @param HTMLForm $form
         */
        protected function alterForm( HTMLForm $form ) {
                if ( $this->getTokensList() ) {
index b90026a..7eea71d 100644 (file)
@@ -160,8 +160,6 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                if ( !$this->typeName || count( $this->ids ) == 0 ) {
                        throw new ErrorPageError( 'revdelete-nooldid-title', 'revdelete-nooldid-text' );
                }
-               $this->typeLabels = self::$UILabels[$this->typeName];
-               $this->mIsAllowed = $user->isAllowed( RevisionDeleter::getRestriction( $this->typeName ) );
 
                # Allow the list type to adjust the passed target
                $this->targetObj = RevisionDeleter::suggestTarget(
@@ -170,6 +168,16 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                        $this->ids
                );
 
+               $this->typeLabels = self::$UILabels[$this->typeName];
+               $list = $this->getList();
+               $list->reset();
+               $bitfield = $list->current()->getBits();
+               $this->mIsAllowed = $user->isAllowed( RevisionDeleter::getRestriction( $this->typeName ) );
+               $canViewSuppressedOnly = $this->getUser()->isAllowed( 'viewsuppressed' ) &&
+                       !$this->getUser()->isAllowed( 'suppressrevision' );
+               $pageIsSuppressed = $bitfield & Revision::DELETED_RESTRICTED;
+               $this->mIsAllowed = $this->mIsAllowed && !( $canViewSuppressedOnly && $pageIsSuppressed );
+
                $this->otherReason = $request->getVal( 'wpReason' );
                # We need a target page!
                if ( is_null( $this->targetObj ) ) {
@@ -444,12 +452,8 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                                Html::hidden( 'target', $this->targetObj->getPrefixedText() ) .
                                Html::hidden( 'type', $this->typeName ) .
                                Html::hidden( 'ids', implode( ',', $this->ids ) ) .
-                               Xml::closeElement( 'fieldset' ) . "\n";
-               } else {
-                       $out = '';
-               }
-               if ( $this->mIsAllowed ) {
-                       $out .= Xml::closeElement( 'form' ) . "\n";
+                               Xml::closeElement( 'fieldset' ) . "\n" .
+                               Xml::closeElement( 'form' ) . "\n";
                        // Show link to edit the dropdown reasons
                        if ( $this->getUser()->isAllowed( 'editinterface' ) ) {
                                $title = Title::makeTitle( NS_MEDIAWIKI, 'Revdelete-reason-dropdown' );
@@ -461,6 +465,8 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                                );
                                $out .= Xml::tags( 'p', array( 'class' => 'mw-revdel-editreasons' ), $link ) . "\n";
                        }
+               } else {
+                       $out = '';
                }
                $this->getOutput()->addHTML( $out );
        }
@@ -616,6 +622,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
 
        /**
         * Report that the submit operation failed
+        * @param Status $status
         */
        protected function failure( $status ) {
                // Messages: revdelete-failure, logdelete-failure
index 4c8c8f3..d4a06eb 100644 (file)
@@ -47,7 +47,7 @@ class SpecialRunJobs extends UnlistedSpecialPage {
                        return;
                }
 
-               $optional = array( 'maxjobs' => 0 );
+               $optional = array( 'maxjobs' => 0, 'maxtime' => 30, 'type' => false, 'async' => true );
                $required = array_flip( array( 'title', 'tasks', 'signature', 'sigexpiry' ) );
 
                $params = array_intersect_key( $this->getRequest()->getValues(), $required + $optional );
@@ -61,7 +61,7 @@ class SpecialRunJobs extends UnlistedSpecialPage {
 
                $squery = $params;
                unset( $squery['signature'] );
-               $cSig = self::getQuerySignature( $squery ); // correct signature
+               $cSig = self::getQuerySignature( $squery, $this->getConfig()->get( 'SecretKey' ) ); // correct signature
                $rSig = $params['signature']; // provided signature
 
                $verified = is_string( $rSig ) && hash_equals( $cSig, $rSig );
@@ -75,77 +75,38 @@ class SpecialRunJobs extends UnlistedSpecialPage {
                // Apply any default parameter values
                $params += $optional;
 
-               // Client will usually disconnect before checking the response,
-               // but it needs to know when it is safe to disconnect. Until this
-               // reaches ignore_user_abort(), it is not safe as the jobs won't run.
-               ignore_user_abort( true ); // jobs may take a bit of time
-               header( "HTTP/1.0 202 Accepted" );
-               ob_flush();
-               flush();
-               // Once the client receives this response, it can disconnect
+               if ( $params['async'] ) {
+                       // Client will usually disconnect before checking the response,
+                       // but it needs to know when it is safe to disconnect. Until this
+                       // reaches ignore_user_abort(), it is not safe as the jobs won't run.
+                       ignore_user_abort( true ); // jobs may take a bit of time
+                       header( "HTTP/1.0 202 Accepted" );
+                       ob_flush();
+                       flush();
+                       // Once the client receives this response, it can disconnect
+               }
 
                // Do all of the specified tasks...
                if ( in_array( 'jobs', explode( '|', $params['tasks'] ) ) ) {
-                       self::executeJobs( (int)$params['maxjobs'] );
+                       $runner = new JobRunner();
+                       $response = $runner->run( array(
+                               'type'     => $params['type'],
+                               'maxJobs'  => $params['maxjobs'] ? $params['maxjobs'] : 1,
+                               'maxTime'  => $params['maxtime'] ? $params['maxjobs'] : 30
+                       ) );
+                       if ( !$params['async'] ) {
+                               print FormatJson::encode( $response, true );
+                       }
                }
        }
 
        /**
         * @param array $query
+        * @param string $secretKey
         * @return string
         */
-       public static function getQuerySignature( array $query ) {
-               global $wgSecretKey;
-
+       public static function getQuerySignature( array $query, $secretKey ) {
                ksort( $query ); // stable order
-               return hash_hmac( 'sha1', wfArrayToCgi( $query ), $wgSecretKey );
-       }
-
-       /**
-        * Run jobs from the job queue
-        *
-        * @note: also called from Wiki.php
-        *
-        * @param int $maxJobs Maximum number of jobs to run
-        * @return void
-        */
-       public static function executeJobs( $maxJobs ) {
-               $n = $maxJobs; // number of jobs to run
-               if ( $n < 1 ) {
-                       return;
-               }
-               try {
-                       $group = JobQueueGroup::singleton();
-                       $count = $group->executeReadyPeriodicTasks();
-                       if ( $count > 0 ) {
-                               wfDebugLog( 'jobqueue', "Executed $count periodic queue task(s)." );
-                       }
-
-                       do {
-                               $job = $group->pop( JobQueueGroup::TYPE_DEFAULT, JobQueueGroup::USE_CACHE );
-                               if ( $job ) {
-                                       $output = $job->toString() . "\n";
-                                       $t = -microtime( true );
-                                       wfProfileIn( __METHOD__ . '-' . get_class( $job ) );
-                                       $success = $job->run();
-                                       wfProfileOut( __METHOD__ . '-' . get_class( $job ) );
-                                       $group->ack( $job ); // done
-                                       $t += microtime( true );
-                                       $t = round( $t * 1000 );
-                                       if ( $success === false ) {
-                                               $output .= "Error: " . $job->getLastError() . ", Time: $t ms\n";
-                                       } else {
-                                               $output .= "Success, Time: $t ms\n";
-                                       }
-                                       wfDebugLog( 'jobqueue', $output );
-                               }
-                       } while ( --$n && $job );
-               } catch ( MWException $e ) {
-                       MWExceptionHandler::rollbackMasterChangesAndLog( $e );
-                       // We don't want exceptions thrown during job execution to
-                       // be reported to the user since the output is already sent.
-                       // Instead we just log them.
-                       MWExceptionHandler::logException( $e );
-               }
+               return hash_hmac( 'sha1', wfArrayToCgi( $query ), $secretKey );
        }
 }
index 970b617..adc248e 100644 (file)
@@ -82,7 +82,8 @@ class SpecialSearch extends SpecialPage {
                $out = $this->getOutput();
                $out->allowClickjacking();
                $out->addModuleStyles( array(
-                       'mediawiki.special', 'mediawiki.special.search', 'mediawiki.ui', 'mediawiki.ui.button'
+                       'mediawiki.special', 'mediawiki.special.search', 'mediawiki.ui', 'mediawiki.ui.button',
+                       'mediawiki.ui.input',
                ) );
 
                // Strip underscores from title parameter; most of the time we'll want
@@ -95,6 +96,16 @@ class SpecialSearch extends SpecialPage {
                $search = str_replace( "\n", " ", $request->getText( 'search', $titleParam ) );
 
                $this->load();
+               if ( !is_null( $request->getVal( 'nsRemember' ) ) ) {
+                       $this->saveNamespaces();
+                       // Remove the token from the URL to prevent the user from inadvertently
+                       // exposing it (e.g. by pasting it into a public wiki page) or undoing
+                       // later settings changes (e.g. by reloading the page).
+                       $query = $request->getValues();
+                       unset( $query['title'], $query['nsRemember'] );
+                       $out->redirect( $this->getPageTitle()->getFullURL( $query ) );
+                       return;
+               }
 
                $this->searchEngineType = $request->getVal( 'srbackend' );
 
@@ -185,12 +196,11 @@ class SpecialSearch extends SpecialPage {
                # No match, generate an edit URL
                $title = Title::newFromText( $term );
                if ( !is_null( $title ) ) {
-                       global $wgGoToEdit;
                        wfRunHooks( 'SpecialSearchNogomatch', array( &$title ) );
                        wfDebugLog( 'nogomatch', $title->getFullText(), 'private' );
 
                        # If the feature is enabled, go straight to the edit page
-                       if ( $wgGoToEdit ) {
+                       if ( $this->getConfig()->get( 'GoToEdit' ) ) {
                                $this->getOutput()->redirect( $title->getFullURL( array( 'action' => 'edit' ) ) );
 
                                return;
@@ -203,13 +213,12 @@ class SpecialSearch extends SpecialPage {
         * @param string $term
         */
        public function showResults( $term ) {
-               global $wgDisableTextSearch, $wgSearchForwardUrl, $wgContLang, $wgScript;
+               global $wgContLang;
 
                $profile = new ProfileSection( __METHOD__ );
                $search = $this->getSearchEngine();
                $search->setLimitOffset( $this->limit, $this->offset );
                $search->setNamespaces( $this->namespaces );
-               $this->saveNamespaces();
                $search->prefix = $this->mPrefix;
                $term = $search->transformSearchTerm( $term );
 
@@ -219,9 +228,10 @@ class SpecialSearch extends SpecialPage {
 
                $out = $this->getOutput();
 
-               if ( $wgDisableTextSearch ) {
-                       if ( $wgSearchForwardUrl ) {
-                               $url = str_replace( '$1', urlencode( $term ), $wgSearchForwardUrl );
+               if ( $this->getConfig()->get( 'DisableTextSearch' ) ) {
+                       $searchFowardUrl = $this->getConfig()->get( 'SearchForwardUrl' );
+                       if ( $searchFowardUrl ) {
+                               $url = str_replace( '$1', urlencode( $term ), $searchFowardUrl );
                                $out->redirect( $url );
                        } else {
                                $out->addHTML(
@@ -303,7 +313,7 @@ class SpecialSearch extends SpecialPage {
                                array(
                                        'id' => ( $this->profile === 'advanced' ? 'powersearch' : 'search' ),
                                        'method' => 'get',
-                                       'action' => $wgScript
+                                       'action' => wfScript(),
                                )
                        )
                );
@@ -346,6 +356,9 @@ class SpecialSearch extends SpecialPage {
                        // Show the create link ahead
                        $this->showCreateLink( $title, $num, $titleMatches, $textMatches );
                        if ( $totalRes > $this->limit || $this->offset ) {
+                               if ( $this->searchEngineType !== null ) {
+                                       $this->setExtraParam( 'srbackend', $this->searchEngineType );
+                               }
                                $prevnext = $this->getLanguage()->viewPrevNext(
                                        $this->getPageTitle(),
                                        $this->offset,
@@ -354,10 +367,8 @@ class SpecialSearch extends SpecialPage {
                                        $this->limit + $this->offset >= $totalRes
                                );
                        }
-                       wfRunHooks( 'SpecialSearchResults', array( $term, &$titleMatches, &$textMatches ) );
-               } else {
-                       wfRunHooks( 'SpecialSearchNoResults', array( $term ) );
                }
+               wfRunHooks( 'SpecialSearchResults', array( $term, &$titleMatches, &$textMatches ) );
 
                $out->parserOptions()->setEditSection( false );
                if ( $titleMatches ) {
@@ -406,7 +417,7 @@ class SpecialSearch extends SpecialPage {
         * @param Title $title
         * @param int $num The number of search results found
         * @param null|SearchResultSet $titleMatches Results from title search
-        * @param null|SearchResultSet $textMatches  Results from text search
+        * @param null|SearchResultSet $textMatches Results from text search
         */
        protected function showCreateLink( $title, $num, $titleMatches, $textMatches ) {
                // show direct page/create link if applicable
@@ -423,8 +434,10 @@ class SpecialSearch extends SpecialPage {
                        return;
                }
 
+               $linkClass = 'mw-search-createlink';
                if ( $title->isKnown() ) {
                        $messageName = 'searchmenu-exists';
+                       $linkClass = 'mw-search-exists';
                } elseif ( $title->quickUserCan( 'create', $this->getUser() ) ) {
                        $messageName = 'searchmenu-new';
                } else {
@@ -439,7 +452,7 @@ class SpecialSearch extends SpecialPage {
 
                // Extensions using the hook might still return an empty $messageName
                if ( $messageName ) {
-                       $this->getOutput()->wrapWikiMsg( "<p class=\"mw-search-createlink\">\n$1</p>", $params );
+                       $this->getOutput()->wrapWikiMsg( "<p class=\"$linkClass\">\n$1</p>", $params );
                } else {
                        // preserve the paragraph for margins etc...
                        $this->getOutput()->addHtml( '<p></p>' );
@@ -510,9 +523,8 @@ class SpecialSearch extends SpecialPage {
                $request = $this->getRequest();
 
                if ( $user->isLoggedIn() &&
-                       !is_null( $request->getVal( 'nsRemember' ) ) &&
                        $user->matchEditToken(
-                               $request->getVal( 'nsToken' ),
+                               $request->getVal( 'nsRemember' ),
                                'searchnamespace',
                                $request
                        )
@@ -522,7 +534,7 @@ class SpecialSearch extends SpecialPage {
                        foreach ( MWNamespace::getValidNamespaces() as $n ) {
                                $user->setOption( 'searchNs' . $n, false );
                        }
-                       // The request parameters include all the namespaces we just searched.
+                       // The request parameters include all the namespaces to be searched.
                        // Even if they're the same as an existing profile, they're not eaten.
                        foreach ( $this->namespaces as $n ) {
                                $user->setOption( 'searchNs' . $n, true );
@@ -645,16 +657,6 @@ class SpecialSearch extends SpecialPage {
 
                $lang = $this->getLanguage();
 
-               // format score
-               if ( is_null( $result->getScore() ) ) {
-                       // Search engine doesn't report scoring info
-                       $score = '';
-               } else {
-                       $percent = sprintf( '%2.1f', $result->getScore() * 100 );
-                       $score = $this->msg( 'search-result-score' )->numParams( $percent )->text()
-                               . ' - ';
-               }
-
                // format description
                $byteSize = $result->getByteSize();
                $wordCount = $result->getWordCount();
@@ -671,26 +673,6 @@ class SpecialSearch extends SpecialPage {
 
                $date = $lang->userTimeAndDate( $timestamp, $this->getUser() );
 
-               // link to related articles if supported
-               $related = '';
-               if ( $result->hasRelated() ) {
-                       $stParams = array_merge(
-                               $this->powerSearchOptions(),
-                               array(
-                                       'search' => $this->msg( 'searchrelated' )->inContentLanguage()->text() .
-                                               ':' . $title->getPrefixedText(),
-                                       'fulltext' => $this->msg( 'search' )->text()
-                               )
-                       );
-
-                       $related = ' -- ' . Linker::linkKnown(
-                               $this->getPageTitle(),
-                               $this->msg( 'search-relatedarticle' )->text(),
-                               array(),
-                               $stParams
-                       );
-               }
-
                $fileMatch = '';
                // Include a thumbnail for media files...
                if ( $title->getNamespace() == NS_FILE ) {
@@ -716,7 +698,7 @@ class SpecialSearch extends SpecialPage {
                                                '<td style="vertical-align: top;">' .
                                                "{$link} {$redirect} {$section} {$fileMatch}" .
                                                $extract .
-                                               "<div class='mw-search-result-data'>{$score}{$desc} - {$date}{$related}</div>" .
+                                               "<div class='mw-search-result-data'>{$desc} - {$date}</div>" .
                                                '</td>' .
                                                '</tr>' .
                                                '</table>' .
@@ -727,6 +709,7 @@ class SpecialSearch extends SpecialPage {
 
                $html = null;
 
+               $score = '';
                if ( wfRunHooks( 'ShowSearchHit', array(
                        $this, $result, $terms,
                        &$link, &$redirect, &$section, &$extract,
@@ -735,7 +718,7 @@ class SpecialSearch extends SpecialPage {
                ) ) ) {
                        $html = "<li><div class='mw-search-result-heading'>" .
                                "{$link} {$redirect} {$section} {$fileMatch}</div> {$extract}\n" .
-                               "<div class='mw-search-result-data'>{$score}{$size} - {$date}{$related}</div>" .
+                               "<div class='mw-search-result-data'>{$size} - {$date}</div>" .
                                "</li>\n";
                }
 
@@ -798,7 +781,7 @@ class SpecialSearch extends SpecialPage {
         * @param SearchResult $result
         * @param string $lastInterwiki
         * @param string $query
-        * @param array $customCaptions iw prefix -> caption
+        * @param array $customCaptions Interwiki prefix -> caption
         *
         * @return string
         */
@@ -935,18 +918,17 @@ class SpecialSearch extends SpecialPage {
                $remember = '';
                $user = $this->getUser();
                if ( $user->isLoggedIn() ) {
-                       $remember .= Html::hidden(
-                               'nsToken',
-                               $user->getEditToken(
-                                       'searchnamespace',
-                                       $this->getRequest()
-                               )
-                       ) .
-                       Xml::checkLabel(
+                       $remember .= Xml::checkLabel(
                                wfMessage( 'powersearch-remember' )->text(),
                                'nsRemember',
                                'mw-search-powersearch-remember',
-                               false
+                               false,
+                               // The token goes here rather than in a hidden field so it
+                               // is only sent when necessary (not every form submission).
+                               array( 'value' => $user->getEditToken(
+                                       'searchnamespace',
+                                       $this->getRequest()
+                               ) )
                        );
                }
 
@@ -954,7 +936,7 @@ class SpecialSearch extends SpecialPage {
                return Xml::openElement( 'fieldset', array( 'id' => 'mw-searchoptions' ) ) .
                        Xml::element( 'legend', null, $this->msg( 'powersearch-legend' )->text() ) .
                        Xml::tags( 'h4', null, $this->msg( 'powersearch-ns' )->parse() ) .
-                       Html::element( 'div', array( 'id' => 'mw-search-togglebox' ) ) .
+                       Xml::element( 'div', array( 'id' => 'mw-search-togglebox' ), '', false ) .
                        Xml::element( 'div', array( 'class' => 'divider' ), '', false ) .
                        implode( Xml::element( 'div', array( 'class' => 'divider' ), '', false ), $showSections ) .
                        $hidden .
@@ -1071,6 +1053,8 @@ class SpecialSearch extends SpecialPage {
 
        /**
         * @param string $term
+        * @param int $resultsShown
+        * @param int $totalNum
         * @return string
         */
        protected function shortDialog( $term, $resultsShown, $totalNum ) {
@@ -1081,7 +1065,7 @@ class SpecialSearch extends SpecialPage {
                        'id' => $this->profile === 'advanced' ? 'powerSearchText' : 'searchText',
                        'size' => '50',
                        'autofocus',
-                       'class' => 'mw-ui-input',
+                       'class' => 'mw-ui-input mw-ui-input-inline',
                ) ) . "\n";
                $out .= Html::hidden( 'fulltext', 'Search' ) . "\n";
                $out .= Xml::submitButton(
@@ -1090,14 +1074,13 @@ class SpecialSearch extends SpecialPage {
                ) . "\n";
 
                // Results-info
-               if ( $totalNum > 0 ) {
-                       $top = $this->msg( 'showingresultsheader' )
+               if ( $totalNum > 0 && $this->offset < $totalNum ) {
+                       $top = $this->msg( 'search-showingresults' )
                                ->numParams( $this->offset + 1, $this->offset + $resultsShown, $totalNum )
-                               ->params( wfEscapeWikiText( $term ) )
                                ->numParams( $resultsShown )
                                ->parse();
                        $out .= Xml::tags( 'div', array( 'class' => 'results-info' ), $top ) .
-                               Xml::element( 'div', array( 'style' => 'clear:both' ) );
+                               Xml::element( 'div', array( 'style' => 'clear:both' ), '', false );
                }
 
                return $out . $this->didYouMeanHtml;
index 3ba50bb..eff06f4 100644 (file)
@@ -49,8 +49,6 @@ class SpecialSpecialpages extends UnlistedSpecialPage {
        }
 
        private function getPageGroups() {
-               global $wgSortSpecialPages;
-
                $pages = SpecialPageFactory::getUsablePages( $this->getUser() );
 
                if ( !count( $pages ) ) {
@@ -76,10 +74,8 @@ class SpecialSpecialpages extends UnlistedSpecialPage {
                }
 
                /** Sort */
-               if ( $wgSortSpecialPages ) {
-                       foreach ( $groups as $group => $sortedPages ) {
-                               ksort( $groups[$group] );
-                       }
+               foreach ( $groups as $group => $sortedPages ) {
+                       ksort( $groups[$group] );
                }
 
                /** Always move "other" to end */
index 371e5ea..67c96a7 100644 (file)
@@ -36,7 +36,10 @@ class SpecialStatistics extends SpecialPage {
        }
 
        public function execute( $par ) {
-               global $wgMemc, $wgDisableCounters, $wgMiserMode;
+               global $wgMemc;
+
+               $disableCounters = $this->getConfig()->get( 'DisableCounters' );
+               $miserMode = $this->getConfig()->get( 'MiserMode' );
 
                $this->setHeaders();
                $this->getOutput()->addModuleStyles( 'mediawiki.special' );
@@ -52,12 +55,12 @@ class SpecialStatistics extends SpecialPage {
 
                # Staticic - views
                $viewsStats = '';
-               if ( !$wgDisableCounters ) {
+               if ( !$disableCounters ) {
                        $viewsStats = $this->getViewsStats();
                }
 
                # Set active user count
-               if ( !$wgMiserMode ) {
+               if ( !$miserMode ) {
                        $key = wfMemcKey( 'sitestats', 'activeusers-updated' );
                        // Re-calculate the count if the last tally is old...
                        if ( !$wgMemc->get( $key ) ) {
@@ -83,7 +86,7 @@ class SpecialStatistics extends SpecialPage {
                $text .= $viewsStats;
 
                # Statistic - popular pages
-               if ( !$wgDisableCounters && !$wgMiserMode ) {
+               if ( !$disableCounters && !$miserMode ) {
                        $text .= $this->getMostViewedPages();
                }
 
@@ -170,8 +173,6 @@ class SpecialStatistics extends SpecialPage {
        }
 
        private function getUserStats() {
-               global $wgActiveUserDays;
-
                return Xml::openElement( 'tr' ) .
                        Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-users' )->parse() ) .
                        Xml::closeElement( 'tr' ) .
@@ -187,16 +188,15 @@ class SpecialStatistics extends SpecialPage {
                                $this->getLanguage()->formatNum( $this->activeUsers ),
                                array( 'class' => 'mw-statistics-users-active' ),
                                'statistics-users-active-desc',
-                               $this->getLanguage()->formatNum( $wgActiveUserDays )
+                               $this->getLanguage()->formatNum( $this->getConfig()->get( 'ActiveUserDays' ) )
                        );
        }
 
        private function getGroupStats() {
-               global $wgGroupPermissions, $wgImplicitGroups;
                $text = '';
-               foreach ( $wgGroupPermissions as $group => $permissions ) {
+               foreach ( $this->getConfig()->get( 'GroupPermissions' ) as $group => $permissions ) {
                        # Skip generic * and implicit groups
-                       if ( in_array( $group, $wgImplicitGroups ) || $group == '*' ) {
+                       if ( in_array( $group, $this->getConfig()->get( 'ImplicitGroups' ) ) || $group == '*' ) {
                                continue;
                        }
                        $groupname = htmlspecialchars( $group );
index bea65ba..552031f 100644 (file)
@@ -37,14 +37,11 @@ class SpecialTrackingCategories extends SpecialPage {
        }
 
        function execute( $par ) {
-               // Global array containing names of tracking categories
-               global $wgTrackingCategories;
-
                $this->setHeaders();
                $this->outputHeader();
                $this->getOutput()->allowClickjacking();
                $this->getOutput()->addHTML(
-                       Html::openElement( 'table', array( 'class' => 'mw-datatable TablePager',
+                       Html::openElement( 'table', array( 'class' => 'mw-datatable',
                                'id' => 'mw-trackingcategories-table' ) ) . "\n" .
                        "<thead><tr>
                        <th>" .
@@ -59,7 +56,7 @@ class SpecialTrackingCategories extends SpecialPage {
                        </tr></thead>"
                );
 
-               foreach( $wgTrackingCategories as $catMsg ) {
+               foreach ( $this->getConfig()->get( 'TrackingCategories' ) as $catMsg ) {
                        /*
                         * Check if the tracking category varies by namespace
                         * Otherwise only pages in the current namespace will be displayed
index 797543f..244b889 100644 (file)
@@ -63,8 +63,10 @@ class SpecialUnblock extends SpecialPage {
 
                if ( $form->show() ) {
                        switch ( $this->type ) {
-                               case Block::TYPE_USER:
                                case Block::TYPE_IP:
+                                       $out->addWikiMsg( 'unblocked-ip', wfEscapeWikiText( $this->target ) );
+                                       break;
+                               case Block::TYPE_USER:
                                        $out->addWikiMsg( 'unblocked', wfEscapeWikiText( $this->target ) );
                                        break;
                                case Block::TYPE_RANGE:
@@ -83,7 +85,7 @@ class SpecialUnblock extends SpecialPage {
                        'Target' => array(
                                'type' => 'text',
                                'label-message' => 'ipaddressorusername',
-                               'tabindex' => '1',
+                               'autofocus' => true,
                                'size' => '45',
                                'required' => true,
                        ),
@@ -111,8 +113,14 @@ class SpecialUnblock extends SpecialPage {
                                $fields['Target']['default'] = $target;
                                $fields['Target']['type'] = 'hidden';
                                switch ( $type ) {
-                                       case Block::TYPE_USER:
                                        case Block::TYPE_IP:
+                                               $fields['Name']['default'] = Linker::linkKnown(
+                                                       SpecialPage::getTitleFor( 'Contributions', $target->getName() ),
+                                                       $target->getName()
+                                               );
+                                               $fields['Name']['raw'] = true;
+                                               break;
+                                       case Block::TYPE_USER:
                                                $fields['Name']['default'] = Linker::link(
                                                        $target->getUserPage(),
                                                        $target->getName()
@@ -131,6 +139,9 @@ class SpecialUnblock extends SpecialPage {
                                                $fields['Target']['default'] = "#{$this->target}";
                                                break;
                                }
+                               // target is hidden, so the reason is the first element
+                               $fields['Target']['autofocus'] = false;
+                               $fields['Reason']['autofocus'] = true;
                        }
                } else {
                        $fields['Target']['default'] = $this->target;
index 04b36c7..8acf8a2 100644 (file)
@@ -36,11 +36,19 @@ class PageArchive {
        /** @var Status */
        protected $revisionStatus;
 
-       function __construct( $title ) {
+       /** @var Config */
+       protected $config;
+
+       function __construct( $title, Config $config = null ) {
                if ( is_null( $title ) ) {
                        throw new MWException( __METHOD__ . ' given a null title.' );
                }
                $this->title = $title;
+               if ( $config === null ) {
+                       wfDebug( __METHOD__ . ' did not have a Config object passed to it' );
+                       $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               }
+               $this->config = $config;
        }
 
        /**
@@ -115,8 +123,6 @@ class PageArchive {
         * @return ResultWrapper
         */
        function listRevisions() {
-               global $wgContentHandlerUseDB;
-
                $dbr = wfGetDB( DB_SLAVE );
 
                $tables = array( 'archive' );
@@ -126,7 +132,7 @@ class PageArchive {
                        'ar_comment', 'ar_len', 'ar_deleted', 'ar_rev_id', 'ar_sha1',
                );
 
-               if ( $wgContentHandlerUseDB ) {
+               if ( $this->config->get( 'ContentHandlerUseDB' ) ) {
                        $fields[] = 'ar_content_format';
                        $fields[] = 'ar_content_model';
                }
@@ -190,8 +196,6 @@ class PageArchive {
         * @return Revision|null
         */
        function getRevision( $timestamp ) {
-               global $wgContentHandlerUseDB;
-
                $dbr = wfGetDB( DB_SLAVE );
 
                $fields = array(
@@ -209,7 +213,7 @@ class PageArchive {
                        'ar_sha1',
                );
 
-               if ( $wgContentHandlerUseDB ) {
+               if ( $this->config->get( 'ContentHandlerUseDB' ) ) {
                        $fields[] = 'ar_content_format';
                        $fields[] = 'ar_content_model';
                }
@@ -442,8 +446,6 @@ class PageArchive {
         * @return Status Status object containing the number of revisions restored on success
         */
        private function undeleteRevisions( $timestamps, $unsuppress = false, $comment = '' ) {
-               global $wgContentHandlerUseDB;
-
                if ( wfReadOnly() ) {
                        throw new ReadOnlyError();
                }
@@ -516,7 +518,7 @@ class PageArchive {
                        'ar_sha1'
                );
 
-               if ( $wgContentHandlerUseDB ) {
+               if ( $this->config->get( 'ContentHandlerUseDB' ) ) {
                        $fields[] = 'ar_content_format';
                        $fields[] = 'ar_content_model';
                }
@@ -806,12 +808,10 @@ class SpecialUndelete extends SpecialPage {
        }
 
        function showSearchForm() {
-               global $wgScript;
-
                $out = $this->getOutput();
                $out->setPageTitle( $this->msg( 'undelete-search-title' ) );
                $out->addHTML(
-                       Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) .
+                       Xml::openElement( 'form', array( 'method' => 'get', 'action' => wfScript() ) ) .
                                Xml::fieldset( $this->msg( 'undelete-search-box' )->text() ) .
                                Html::hidden( 'title', $this->getPageTitle()->getPrefixedDBkey() ) .
                                Html::rawElement(
@@ -891,7 +891,7 @@ class SpecialUndelete extends SpecialPage {
                        return;
                }
 
-               $archive = new PageArchive( $this->mTargetObj );
+               $archive = new PageArchive( $this->mTargetObj, $this->getConfig() );
                if ( !wfRunHooks( 'UndeleteForm::showRevision', array( &$archive, $this->mTargetObj ) ) ) {
                        return;
                }
@@ -910,7 +910,8 @@ class SpecialUndelete extends SpecialPage {
                        if ( !$rev->userCan( Revision::DELETED_TEXT, $user ) ) {
                                $out->wrapWikiMsg(
                                        "<div class='mw-warning plainlinks'>\n$1\n</div>\n",
-                                       'rev-deleted-text-permission'
+                               $rev->isDeleted( Revision::DELETED_RESTRICTED ) ?
+                                       'rev-suppressed-text-permission' : 'rev-deleted-text-permission'
                                );
 
                                return;
@@ -918,7 +919,8 @@ class SpecialUndelete extends SpecialPage {
 
                        $out->wrapWikiMsg(
                                "<div class='mw-warning plainlinks'>\n$1\n</div>\n",
-                               'rev-deleted-text-view'
+                               $rev->isDeleted( Revision::DELETED_RESTRICTED ) ?
+                                       'rev-suppressed-text-view' : 'rev-deleted-text-view'
                        );
                        $out->addHTML( '<br />' );
                        // and we are allowed to see...
@@ -1196,7 +1198,7 @@ class SpecialUndelete extends SpecialPage {
                        array( 'undeletepagetitle', wfEscapeWikiText( $this->mTargetObj->getPrefixedText() ) )
                );
 
-               $archive = new PageArchive( $this->mTargetObj );
+               $archive = new PageArchive( $this->mTargetObj, $this->getConfig() );
                wfRunHooks( 'UndeleteForm::showHistory', array( &$archive, $this->mTargetObj ) );
                /*
                $text = $archive->getLastRevisionText();
@@ -1608,9 +1610,7 @@ class SpecialUndelete extends SpecialPage {
        }
 
        function undelete() {
-               global $wgUploadMaintenance;
-
-               if ( $wgUploadMaintenance && $this->mTargetObj->getNamespace() == NS_FILE ) {
+               if ( $this->getConfig()->get( 'UploadMaintenance' ) && $this->mTargetObj->getNamespace() == NS_FILE ) {
                        throw new ErrorPageError( 'undelete-error', 'filedelete-maintenance' );
                }
 
@@ -1619,7 +1619,7 @@ class SpecialUndelete extends SpecialPage {
                }
 
                $out = $this->getOutput();
-               $archive = new PageArchive( $this->mTargetObj );
+               $archive = new PageArchive( $this->mTargetObj, $this->getConfig() );
                wfRunHooks( 'UndeleteForm::undelete', array( &$archive, $this->mTargetObj ) );
                $ok = $archive->undelete(
                        $this->mTargetTimestamp,
index 35141d8..a8b97d7 100644 (file)
@@ -37,11 +37,9 @@ class SpecialUnlockdb extends FormSpecialPage {
        }
 
        public function checkExecutePermissions( User $user ) {
-               global $wgReadOnlyFile;
-
                parent::checkExecutePermissions( $user );
                # If the lock file isn't writable, we can do sweet bugger all
-               if ( !file_exists( $wgReadOnlyFile ) ) {
+               if ( !file_exists( $this->getConfig()->get( 'ReadOnlyFile' ) ) ) {
                        throw new ErrorPageError( 'lockdb', 'databasenotlocked' );
                }
        }
@@ -62,20 +60,19 @@ class SpecialUnlockdb extends FormSpecialPage {
        }
 
        public function onSubmit( array $data ) {
-               global $wgReadOnlyFile;
-
                if ( !$data['Confirm'] ) {
                        return Status::newFatal( 'locknoconfirm' );
                }
 
+               $readOnlyFile = $this->getConfig()->get( 'ReadOnlyFile' );
                wfSuppressWarnings();
-               $res = unlink( $wgReadOnlyFile );
+               $res = unlink( $readOnlyFile );
                wfRestoreWarnings();
 
                if ( $res ) {
                        return Status::newGood();
                } else {
-                       return Status::newFatal( 'filedeleteerror', $wgReadOnlyFile );
+                       return Status::newFatal( 'filedeleteerror', $readOnlyFile );
                }
        }
 
index 743c587..36ec09e 100644 (file)
@@ -44,7 +44,6 @@ class UnusedimagesPage extends ImageQueryPage {
        }
 
        function getQueryInfo() {
-               global $wgCountCategorizedImagesAsUsed;
                $retval = array(
                        'tables' => array( 'image', 'imagelinks' ),
                        'fields' => array(
@@ -58,7 +57,7 @@ class UnusedimagesPage extends ImageQueryPage {
                        'join_conds' => array( 'imagelinks' => array( 'LEFT JOIN', 'il_to = img_name' ) )
                );
 
-               if ( $wgCountCategorizedImagesAsUsed ) {
+               if ( $this->getConfig()->get( 'CountCategorizedImagesAsUsed' ) ) {
                        // Order is significant
                        $retval['tables'] = array( 'image', 'page', 'categorylinks',
                                'imagelinks' );
index fe0638e..bb07c19 100644 (file)
@@ -72,6 +72,7 @@ class UnwatchedpagesPage extends QueryPage {
 
        /**
         * Add the JS
+        * @param string|null $par
         */
        public function execute( $par ) {
                parent::execute( $par );
index 976294b..55d09dd 100644 (file)
@@ -485,6 +485,7 @@ class SpecialUpload extends SpecialPage {
         * @param string $copyStatus
         * @param string $source
         * @return string
+        * @todo Use Config obj instead of globals
         */
        public static function getInitialPageText( $comment = '', $license = '',
                $copyStatus = '', $source = ''
@@ -568,8 +569,6 @@ class SpecialUpload extends SpecialPage {
         * @throws MWException
         */
        protected function processVerificationError( $details ) {
-               global $wgFileExtensions;
-
                switch ( $details['status'] ) {
 
                        /** Statuses that only require name changing **/
@@ -604,7 +603,7 @@ class SpecialUpload extends SpecialPage {
                                } else {
                                        $msg->params( $details['finalExt'] );
                                }
-                               $extensions = array_unique( $wgFileExtensions );
+                               $extensions = array_unique( $this->getConfig()->get( 'FileExtensions' ) );
                                $msg->params( $this->getLanguage()->commaList( $extensions ),
                                        count( $extensions ) );
 
@@ -725,8 +724,7 @@ class SpecialUpload extends SpecialPage {
                        return '';
                }
 
-               $gallery = ImageGalleryBase::factory();
-               $gallery->setContext( $this->getContext() );
+               $gallery = ImageGalleryBase::factory( false, $this->getContext() );
                $gallery->setShowBytes( false );
                foreach ( $dupes as $file ) {
                        $gallery->add( $file->getTitle() );
@@ -740,6 +738,18 @@ class SpecialUpload extends SpecialPage {
        protected function getGroupName() {
                return 'media';
        }
+
+       /**
+        * Should we rotate images in the preview on Special:Upload.
+        *
+        * This controls js: mw.config.get( 'wgFileCanRotate' )
+        *
+        * @todo What about non-BitmapHandler handled files?
+        */
+       static public function rotationEnabled() {
+               $bitmapHandler = new BitmapHandler();
+               return $bitmapHandler->autoRotateEnabled();
+       }
 }
 
 /**
@@ -788,6 +798,18 @@ class UploadForm extends HTMLForm {
                wfRunHooks( 'UploadFormInitDescriptor', array( &$descriptor ) );
                parent::__construct( $descriptor, $context, 'upload' );
 
+               # Add a link to edit MediaWik:Licenses
+               if ( $this->getUser()->isAllowed( 'editinterface' ) ) {
+                       $licensesLink = Linker::link(
+                               Title::makeTitle( NS_MEDIAWIKI, 'Licenses' ),
+                               $this->msg( 'licenses-edit' )->escaped(),
+                               array(),
+                               array( 'action' => 'edit' )
+                       );
+                       $editLicenses = '<p class="mw-upload-editlicenses">' . $licensesLink . '</p>';
+                       $this->addFooterText( $editLicenses, 'description' );
+               }
+
                # Set some form properties
                $this->setSubmitText( $this->msg( 'uploadbtn' )->text() );
                $this->setSubmitName( 'wpUpload' );
@@ -811,8 +833,6 @@ class UploadForm extends HTMLForm {
         * @return array Descriptor array
         */
        protected function getSourceSection() {
-               global $wgCopyUploadsFromSpecialUpload;
-
                if ( $this->mSessionKey ) {
                        return array(
                                'SessionKey' => array(
@@ -828,7 +848,7 @@ class UploadForm extends HTMLForm {
 
                $canUploadByUrl = UploadFromUrl::isEnabled()
                        && ( UploadFromUrl::isAllowed( $this->getUser() ) === true )
-                       && $wgCopyUploadsFromSpecialUpload;
+                       && $this->getConfig()->get( 'CopyUploadsFromSpecialUpload' );
                $radio = $canUploadByUrl;
                $selectedSourceType = strtolower( $this->getRequest()->getText( 'wpSourceType', 'File' ) );
 
@@ -907,17 +927,18 @@ class UploadForm extends HTMLForm {
        protected function getExtensionsMessage() {
                # Print a list of allowed file extensions, if so configured.  We ignore
                # MIME type here, it's incomprehensible to most people and too long.
-               global $wgCheckFileExtensions, $wgStrictFileExtensions,
-                       $wgFileExtensions, $wgFileBlacklist;
+               $config = $this->getConfig();
 
-               if ( $wgCheckFileExtensions ) {
-                       if ( $wgStrictFileExtensions ) {
+               if ( $config->get( 'CheckFileExtensions' ) ) {
+                       if ( $config->get( 'StrictFileExtensions' ) ) {
                                # Everything not permitted is banned
                                $extensionsList =
                                        '<div id="mw-upload-permitted">' .
                                        $this->msg(
                                                'upload-permitted',
-                                               $this->getContext()->getLanguage()->commaList( array_unique( $wgFileExtensions ) )
+                                               $this->getContext()->getLanguage()->commaList(
+                                                       array_unique( $config->get( 'FileExtensions' ) )
+                                               )
                                        )->parseAsBlock() .
                                        "</div>\n";
                        } else {
@@ -926,13 +947,17 @@ class UploadForm extends HTMLForm {
                                        '<div id="mw-upload-preferred">' .
                                                $this->msg(
                                                        'upload-preferred',
-                                                       $this->getContext()->getLanguage()->commaList( array_unique( $wgFileExtensions ) )
+                                                       $this->getContext()->getLanguage()->commaList(
+                                                               array_unique( $config->get( 'FileExtensions' ) )
+                                                       )
                                                )->parseAsBlock() .
                                        "</div>\n" .
                                        '<div id="mw-upload-prohibited">' .
                                                $this->msg(
                                                        'upload-prohibited',
-                                                       $this->getContext()->getLanguage()->commaList( array_unique( $wgFileBlacklist ) )
+                                                       $this->getContext()->getLanguage()->commaList(
+                                                               array_unique( $config->get( 'FileBlacklist' ) )
+                                                       )
                                                )->parseAsBlock() .
                                        "</div>\n";
                        }
@@ -951,6 +976,7 @@ class UploadForm extends HTMLForm {
         * @return array Descriptor array
         */
        protected function getDescriptionSection() {
+               $config = $this->getConfig();
                if ( $this->mSessionKey ) {
                        $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash();
                        try {
@@ -1023,8 +1049,7 @@ class UploadForm extends HTMLForm {
                        );
                }
 
-               global $wgUseCopyrightUpload;
-               if ( $wgUseCopyrightUpload ) {
+               if ( $config->get( 'UseCopyrightUpload' ) ) {
                        $descriptor['UploadCopyStatus'] = array(
                                'type' => 'text',
                                'section' => 'description',
@@ -1099,11 +1124,11 @@ class UploadForm extends HTMLForm {
         * Add upload JS to the OutputPage
         */
        protected function addUploadJS() {
-               global $wgUseAjax, $wgAjaxUploadDestCheck, $wgAjaxLicensePreview,
-                       $wgEnableAPI, $wgStrictFileExtensions;
+               $config = $this->getConfig();
 
-               $useAjaxDestCheck = $wgUseAjax && $wgAjaxUploadDestCheck;
-               $useAjaxLicensePreview = $wgUseAjax && $wgAjaxLicensePreview && $wgEnableAPI;
+               $useAjaxDestCheck = $config->get( 'UseAjax' ) && $config->get( 'AjaxUploadDestCheck' );
+               $useAjaxLicensePreview = $config->get( 'UseAjax' ) &&
+                       $config->get( 'AjaxLicensePreview' ) && $config->get( 'EnableAPI' );
                $this->mMaxUploadSize['*'] = UploadBase::getMaxUploadSize();
 
                $scriptVars = array(
@@ -1114,7 +1139,7 @@ class UploadForm extends HTMLForm {
                                // the wpDestFile textbox
                                $this->mDestFile === '',
                        'wgUploadSourceIds' => $this->mSourceIds,
-                       'wgStrictFileExtensions' => $wgStrictFileExtensions,
+                       'wgStrictFileExtensions' => $config->get( 'StrictFileExtensions' ),
                        'wgCapitalizeUploads' => MWNamespace::isCapitalized( NS_FILE ),
                        'wgMaxUploadSize' => $this->mMaxUploadSize,
                );
@@ -1124,15 +1149,14 @@ class UploadForm extends HTMLForm {
 
                $out->addModules( array(
                        'mediawiki.action.edit', // For <charinsert> support
-                       'mediawiki.legacy.upload', // Old form stuff...
-                       'mediawiki.special.upload', // Newer extras for thumbnail preview.
+                       'mediawiki.special.upload', // Extras for thumbnail and license preview.
                ) );
        }
 
        /**
         * Empty function; submission is handled elsewhere.
         *
-        * @return bool false
+        * @return bool False
         */
        function trySubmit() {
                return false;
index 75ab19f..ddb435d 100644 (file)
@@ -57,7 +57,7 @@ class SpecialUploadStash extends UnlistedSpecialPage {
        /**
         * Execute page -- can output a file directly or show a listing of them.
         *
-        * @param string $subPage subpage, e.g. in
+        * @param string $subPage Subpage, e.g. in
         *   http://example.com/wiki/Special:UploadStash/foo.jpg, the "foo.jpg" part
         * @return bool Success
         */
@@ -75,7 +75,7 @@ class SpecialUploadStash extends UnlistedSpecialPage {
         * If file available in stash, cats it out to the client as a simple HTTP response.
         * n.b. Most sanity checking done in UploadStashLocalFile, so this is straightforward.
         *
-        * @param string $key the key of a particular requested file
+        * @param string $key The key of a particular requested file
         * @throws HttpError
         * @return bool
         */
@@ -159,15 +159,13 @@ class SpecialUploadStash extends UnlistedSpecialPage {
         * @return bool Success
         */
        private function outputThumbFromStash( $file, $params ) {
-               // this global, if it exists, points to a "scaler", as you might find in
+               $flags = 0;
+               // this config option, if it exists, points to a "scaler", as you might find in
                // the Wikimedia Foundation cluster. See outputRemoteScaledThumb(). This
                // is part of our horrible NFS-based system, we create a file on a mount
                // point here, but fetch the scaled file from somewhere else that
                // happens to share it over NFS.
-               global $wgUploadStashScalerBaseUrl;
-
-               $flags = 0;
-               if ( $wgUploadStashScalerBaseUrl ) {
+               if ( $this->getConfig()->get( 'UploadStashScalerBaseUrl' ) ) {
                        $this->outputRemoteScaledThumb( $file, $params, $flags );
                } else {
                        $this->outputLocallyScaledThumb( $file, $params, $flags );
@@ -199,8 +197,8 @@ class SpecialUploadStash extends UnlistedSpecialPage {
                        throw new UploadStashFileNotFoundException( "no local path for scaled item" );
                }
 
-               // now we should construct a File, so we can get mime and other such info in a standard way
-               // n.b. mimetype may be different from original (ogx original -> jpeg thumb)
+               // now we should construct a File, so we can get MIME and other such info in a standard way
+               // n.b. MIME type may be different from original (ogx original -> jpeg thumb)
                $thumbFile = new UnregisteredLocalFile( false,
                        $this->stash->repo, $thumbnailImage->getStoragePath(), false );
                if ( !$thumbFile ) {
@@ -227,14 +225,13 @@ class SpecialUploadStash extends UnlistedSpecialPage {
         * @param array $params Scaling parameters ( e.g. array( width => '50' ) );
         * @param int $flags Scaling flags ( see File:: constants )
         * @throws MWException
-        * @return bool success
+        * @return bool Success
         */
        private function outputRemoteScaledThumb( $file, $params, $flags ) {
-               // This global probably looks something like
+               // This option probably looks something like
                // 'http://upload.wikimedia.org/wikipedia/test/thumb/temp'. Do not use
                // trailing slash.
-               global $wgUploadStashScalerBaseUrl;
-               $scalerBaseUrl = $wgUploadStashScalerBaseUrl;
+               $scalerBaseUrl = $this->getConfig()->get( 'UploadStashScalerBaseUrl' );
 
                if ( preg_match( '/^\/\//', $scalerBaseUrl ) ) {
                        // this is apparently a protocol-relative URL, which makes no sense in this context,
@@ -295,7 +292,7 @@ class SpecialUploadStash extends UnlistedSpecialPage {
         * Output HTTP response of raw content
         * Side effect: writes HTTP response to STDOUT.
         * @param string $content Content
-        * @param string $contentType Mime type
+        * @param string $contentType MIME type
         * @throws SpecialUploadStashTooLargeException
         * @return bool
         */
@@ -313,7 +310,7 @@ class SpecialUploadStash extends UnlistedSpecialPage {
        /**
         * Output headers for streaming
         * @todo Unsure about encoding as binary; if we received from HTTP perhaps
-        * we should use that encoding, concatted with semicolon to mimeType as it
+        * we should use that encoding, concatenated with semicolon to `$contentType` as it
         * usually is.
         * Side effect: preps PHP to write headers to STDOUT.
         * @param string $contentType String suitable for content-type header
index 1ef96c3..845413e 100644 (file)
@@ -41,6 +41,29 @@ class LoginForm extends SpecialPage {
        const USER_BLOCKED = 11;
        const NEED_TOKEN = 12;
        const WRONG_TOKEN = 13;
+       const USER_MIGRATED = 14;
+
+       /**
+        * Valid error and warning messages
+        *
+        * Special:Userlogin can show an error or warning message on the form when
+        * coming from another page. This is done via the ?error= or ?warning= GET
+        * parameters.
+        *
+        * This array is the list of valid message keys. All other values will be
+        * ignored.
+        *
+        * @since 1.24
+        * @var string[]
+        */
+       public static $validErrorMessages = array(
+               'exception-nologin-text',
+               'watchlistanontext',
+               'changeemail-no-info',
+               'resetpass-no-info',
+               'confirmemail_needlogin',
+               'prefsnologintext2',
+       );
 
        public $mAbortLoginErrorMsg = null;
 
@@ -65,6 +88,8 @@ class LoginForm extends SpecialPage {
        protected $mType;
        protected $mReason;
        protected $mRealName;
+       protected $mEntryError = '';
+       protected $mEntryErrorType = 'error';
 
        private $mTempPasswordUsed;
        private $mLoaded = false;
@@ -128,6 +153,37 @@ class LoginForm extends SpecialPage {
                $this->mReturnTo = $request->getVal( 'returnto', '' );
                $this->mReturnToQuery = $request->getVal( 'returntoquery', '' );
 
+               // Show an error or warning passed on from a previous page
+               $entryError = $this->msg( $request->getVal( 'error', '' ) );
+               $entryWarning = $this->msg( $request->getVal( 'warning', '' ) );
+               // bc: provide login link as a parameter for messages where the translation
+               // was not updated
+               $loginreqlink = Linker::linkKnown(
+                       $this->getPageTitle(),
+                       $this->msg( 'loginreqlink' )->escaped(),
+                       array(),
+                       array(
+                               'returnto' => $this->mReturnTo,
+                               'returntoquery' => $this->mReturnToQuery,
+                               'uselang' => $this->mLanguage,
+                               'fromhttp' => $this->mFromHTTP ? '1' : '0',
+                       )
+               );
+
+               // Only show valid error or warning messages.
+               if ( $entryError->exists()
+                       && in_array( $entryError->getKey(), self::$validErrorMessages )
+               ) {
+                       $this->mEntryErrorType = 'error';
+                       $this->mEntryError = $entryError->rawParams( $loginreqlink )->escaped();
+
+               } elseif ( $entryWarning->exists()
+                       && in_array( $entryWarning->getKey(), self::$validErrorMessages )
+               ) {
+                       $this->mEntryErrorType = 'warning';
+                       $this->mEntryError = $entryWarning->rawParams( $loginreqlink )->escaped();
+               }
+
                if ( $wgEnableEmail ) {
                        $this->mEmail = $request->getText( 'wpEmail' );
                } else {
@@ -165,7 +221,7 @@ class LoginForm extends SpecialPage {
                }
        }
 
-       /*
+       /**
         * @param string|null $subPage
         */
        public function execute( $subPage ) {
@@ -182,6 +238,14 @@ class LoginForm extends SpecialPage {
                }
                $this->setHeaders();
 
+               // In the case where the user is already logged in, do not show the login page.
+               // The use case scenario for this is when a user opens a large number of tabs, is
+               // redirected to the login page on all of them, and then logs in on one, expecting
+               // all the others to work properly.
+               if ( $this->mType !== 'signup' && !$this->mPosted && $this->getUser()->isLoggedIn() ) {
+                       $this->successfulLogin();
+               }
+
                // If logging in and not on HTTPS, either redirect to it or offer a link.
                global $wgSecureLogin;
                if ( $this->mRequest->getProtocol() !== 'https' ) {
@@ -191,6 +255,7 @@ class LoginForm extends SpecialPage {
                                'returntoquery' => $this->mReturnToQuery !== '' ?
                                        $this->mReturnToQuery : null,
                                'title' => null,
+                               ( $this->mEntryErrorType === 'error' ? 'error' : 'warning' ) => $this->mEntryError,
                        ) + $this->mRequest->getQueryValues();
                        $url = $title->getFullURL( $query, false, PROTO_HTTPS );
                        if ( $wgSecureLogin
@@ -232,7 +297,7 @@ class LoginForm extends SpecialPage {
                                return;
                        }
                }
-               $this->mainLoginForm( '' );
+               $this->mainLoginForm( $this->mEntryError, $this->mEntryErrorType );
        }
 
        /**
@@ -633,6 +698,14 @@ class LoginForm extends SpecialPage {
                }
 
                $u = User::newFromName( $this->mUsername );
+
+               // Give extensions a way to indicate the username has been updated,
+               // rather than telling the user the account doesn't exist.
+               if ( !wfRunHooks( 'LoginUserMigrated', array( $u, &$msg ) ) ) {
+                       $this->mAbortLoginErrorMsg = $msg;
+                       return self::USER_MIGRATED;
+               }
+
                if ( !( $u instanceof User ) || !User::isUsableName( $u->getName() ) ) {
                        return self::ILLEGAL;
                }
@@ -932,6 +1005,15 @@ class LoginForm extends SpecialPage {
                                $this->mainLoginForm( $this->msg( $error,
                                                wfEscapeWikiText( $this->mUsername ) )->text() );
                                break;
+                       case self::USER_MIGRATED:
+                               $error = $this->mAbortLoginErrorMsg ?: 'login-migrated-generic';
+                               $params = array();
+                               if ( is_array( $error ) ) {
+                                       $error = array_shift( $this->mAbortLoginErrorMsg );
+                                       $params = $this->mAbortLoginErrorMsg;
+                               }
+                               $this->mainLoginForm( $this->msg( $error, $params )->text() );
+                               break;
                        default:
                                throw new MWException( 'Unhandled case value' );
                }
@@ -1048,7 +1130,7 @@ class LoginForm extends SpecialPage {
        /**
         * Display a "successful action" page.
         *
-        * @param string $type condition of return to; see `executeReturnTo`
+        * @param string $type Condition of return to; see `executeReturnTo`
         * @param string|Message $title Page's title
         * @param string $msgname
         * @param string $injected_html
@@ -1173,6 +1255,8 @@ class LoginForm extends SpecialPage {
        }
 
        /**
+        * @param string $msg
+        * @param string $msgtype
         * @private
         */
        function mainLoginForm( $msg, $msgtype = 'error' ) {
@@ -1214,6 +1298,8 @@ class LoginForm extends SpecialPage {
                $out->addModuleStyles( array(
                        'mediawiki.ui',
                        'mediawiki.ui.button',
+                       'mediawiki.ui.checkbox',
+                       'mediawiki.ui.input',
                        'mediawiki.special.userlogin.common.styles'
                ) );
                $out->addModules( array(
@@ -1306,7 +1392,6 @@ class LoginForm extends SpecialPage {
                $template->set( 'cansecurelogin', ( $wgSecureLogin === true ) );
                $template->set( 'stickhttps', (int)$this->mStickHTTPS );
                $template->set( 'loggedin', $user->isLoggedIn() );
-               $template->set( 'loggedinuser', $user->getName() );
 
                if ( $this->mType == 'signup' ) {
                        if ( !self::getCreateaccountToken() ) {
@@ -1457,6 +1542,7 @@ class LoginForm extends SpecialPage {
        }
 
        /**
+        * @param string $type
         * @private
         */
        function cookieRedirectCheck( $type ) {
@@ -1472,6 +1558,7 @@ class LoginForm extends SpecialPage {
        }
 
        /**
+        * @param string $type
         * @private
         */
        function onCookieRedirectCheck( $type ) {
index 411970e..cefdad0 100644 (file)
@@ -328,9 +328,7 @@ class UserrightsPage extends SpecialPage {
         * @return Status
         */
        public function fetchUser( $username ) {
-               global $wgUserrightsInterwikiDelimiter;
-
-               $parts = explode( $wgUserrightsInterwikiDelimiter, $username );
+               $parts = explode( $this->getConfig()->get( 'UserrightsInterwikiDelimiter' ), $username );
                if ( count( $parts ) < 2 ) {
                        $name = trim( $username );
                        $database = '';
@@ -417,13 +415,12 @@ class UserrightsPage extends SpecialPage {
         * Output a form to allow searching for a user
         */
        function switchForm() {
-               global $wgScript;
                $this->getOutput()->addHTML(
                        Html::openElement(
                                'form',
                                array(
                                        'method' => 'get',
-                                       'action' => $wgScript,
+                                       'action' => wfScript(),
                                        'name' => 'uluser',
                                        'id' => 'mw-userrights-form1'
                                )
@@ -715,7 +712,7 @@ class UserrightsPage extends SpecialPage {
        /**
         * Returns $this->getUser()->changeableGroups()
         *
-        * @return array array(
+        * @return array Array(
         *   'add' => array( addablegroups ),
         *   'remove' => array( removablegroups ),
         *   'add-self' => array( addablegroups to self ),
index 576b625..cb3fc11 100644 (file)
@@ -50,6 +50,7 @@ class SpecialVersion extends SpecialPage {
 
        /**
         * main()
+        * @param string|null $par
         */
        public function execute( $par ) {
                global $IP, $wgExtensionCredits;
@@ -203,7 +204,7 @@ class SpecialVersion extends SpecialPage {
         *
         * @return string
         */
-       static function softwareInformation() {
+       public static function softwareInformation() {
                $dbr = wfGetDB( DB_SLAVE );
 
                // Put the software in an array of form 'name' => 'version'. All messages should
@@ -211,9 +212,11 @@ class SpecialVersion extends SpecialPage {
                // wikimarkup can be used.
                $software = array();
                $software['[https://www.mediawiki.org/ MediaWiki]'] = self::getVersionLinked();
-               $phpKey = wfIsHHVM() ? '[http://hhvm.com/ HHVM]' :
-                       '[http://www.php.net/ PHP]';
-               $software[$phpKey] = PHP_VERSION . " (" . PHP_SAPI . ")";
+               if ( wfIsHHVM() ) {
+                       $software['[http://hhvm.com/ HHVM]'] = HHVM_VERSION . " (" . PHP_SAPI . ")";
+               } else {
+                       $software['[https://php.net/ PHP]'] = PHP_VERSION . " (" . PHP_SAPI . ")";
+               }
                $software[$dbr->getSoftwareLink()] = $dbr->getServerInfo();
 
                // Allow a hook to add/remove items.
@@ -307,7 +310,7 @@ class SpecialVersion extends SpecialPage {
        }
 
        /**
-        * @return string wgVersion + a link to subversion revision of svn BASE
+        * @return string Global wgVersion + a link to subversion revision of svn BASE
         */
        private static function getVersionLinkedSvn() {
                global $IP;
@@ -349,7 +352,7 @@ class SpecialVersion extends SpecialPage {
 
        /**
         * @since 1.22 Returns the HEAD date in addition to the sha1 and link
-        * @return bool|string wgVersion + HEAD sha1 stripped to the first 7 chars
+        * @return bool|string Global wgVersion + HEAD sha1 stripped to the first 7 chars
         *   with link and date, or false on failure
         */
        private static function getVersionLinkedGit() {
@@ -425,10 +428,14 @@ class SpecialVersion extends SpecialPage {
         *
         * @return string Wikitext
         */
-       function getExtensionCredits() {
+       public function getExtensionCredits() {
                global $wgExtensionCredits;
 
-               if ( !count( $wgExtensionCredits ) ) {
+               if (
+                       count( $wgExtensionCredits ) === 0 ||
+                       // Skins are displayed separately, see getSkinCredits()
+                       ( count( $wgExtensionCredits ) === 1 && isset( $wgExtensionCredits['skin'] ) )
+               ) {
                        return '';
                }
 
@@ -475,7 +482,12 @@ class SpecialVersion extends SpecialPage {
         *
         * @return string Wikitext
         */
-       function getSkinCredits() {
+       public function getSkinCredits() {
+               global $wgExtensionCredits;
+               if ( !isset( $wgExtensionCredits['skin'] ) || count( $wgExtensionCredits['skin'] ) === 0 ) {
+                       return '';
+               }
+
                $out = Xml::element(
                                'h2',
                                array( 'id' => 'mw-version-skin' ),
@@ -513,7 +525,7 @@ class SpecialVersion extends SpecialPage {
                        );
 
                        array_walk( $tags, function ( &$value ) {
-                               $value = '&lt;' . htmlentities( $value ) . '&gt;';
+                               $value = '&lt;' . htmlspecialchars( $value ) . '&gt;';
                        } );
                        $out .= $this->listToText( $tags );
                } else {
@@ -581,7 +593,7 @@ class SpecialVersion extends SpecialPage {
         * @param array $b
         * @return int
         */
-       function compare( $a, $b ) {
+       public function compare( $a, $b ) {
                if ( $a['name'] === $b['name'] ) {
                        return 0;
                } else {
@@ -608,7 +620,7 @@ class SpecialVersion extends SpecialPage {
         *
         * @return string Raw HTML
         */
-       function getCreditsForExtension( array $extension ) {
+       public function getCreditsForExtension( array $extension ) {
                $out = $this->getOutput();
 
                // We must obtain the information for all the bits and pieces!
@@ -650,6 +662,7 @@ class SpecialVersion extends SpecialPage {
 
                if ( isset( $extension['path'] ) ) {
                        global $IP;
+                       $extensionPath = dirname( $extension['path'] );
                        if ( $this->coreId == '' ) {
                                wfDebug( 'Looking up core head id' );
                                $coreHeadSHA1 = self::getGitHeadSha1( $IP );
@@ -668,7 +681,6 @@ class SpecialVersion extends SpecialPage {
 
                        if ( !$vcsVersion ) {
                                wfDebug( "Getting VCS info for extension $extensionName" );
-                               $extensionPath = dirname( $extension['path'] );
                                $gitInfo = new GitInfo( $extensionPath );
                                $vcsVersion = $gitInfo->getHeadSHA1();
                                if ( $vcsVersion !== false ) {
@@ -714,7 +726,7 @@ class SpecialVersion extends SpecialPage {
                        if ( $vcsDate ) {
                                $vcsTimeString = Html::element( 'span',
                                        array( 'class' => 'mw-version-ext-vcs-timestamp' ),
-                                       $this->getLanguage()->timeanddate( $vcsDate )
+                                       $this->getLanguage()->timeanddate( $vcsDate, true )
                                );
                                $versionString .= " {$vcsTimeString}";
                        }
@@ -893,7 +905,7 @@ class SpecialVersion extends SpecialPage {
         *
         * @return string HTML fragment
         */
-       function listAuthors( $authors, $extName, $extDir ) {
+       public function listAuthors( $authors, $extName, $extDir ) {
                $hasOthers = false;
 
                $list = array();
@@ -996,7 +1008,7 @@ class SpecialVersion extends SpecialPage {
         *
         * @return string
         */
-       function listToText( $list, $sort = true ) {
+       public function listToText( $list, $sort = true ) {
                if ( !count( $list ) ) {
                        return '';
                }
index 7d439fa..937a503 100644 (file)
@@ -49,29 +49,62 @@ class WantedFilesPage extends WantedQueryPage {
                        $category = false;
                }
 
+               $noForeign = '';
+               if ( !$this->likelyToHaveFalsePositives() ) {
+                       // Additional messages for grep:
+                       // wantedfiletext-cat-noforeign, wantedfiletext-nocat
+                       $noForeign = '-noforeign';
+               }
+
                if ( $category ) {
                        return $this
-                               ->msg( 'wantedfiletext-cat' )
+                               ->msg( 'wantedfiletext-cat' . $noForeign )
                                ->params( $category->getFullText() )
                                ->parseAsBlock();
                } else {
                        return $this
-                               ->msg( 'wantedfiletext-nocat' )
+                               ->msg( 'wantedfiletext-nocat' . $noForeign )
                                ->parseAsBlock();
                }
        }
 
+       /**
+        * Whether foreign repos are likely to cause false positives
+        *
+        * In its own function to allow subclasses to override.
+        * @see SpecialWantedFilesGUOverride in GlobalUsage extension.
+        * @since 1.24
+        */
+       protected function likelyToHaveFalsePositives() {
+               return RepoGroup::singleton()->hasForeignRepos();
+       }
+
        /**
         * KLUGE: The results may contain false positives for files
         * that exist e.g. in a shared repo.  Setting this at least
         * keeps them from showing up as redlinks in the output, even
         * if it doesn't fix the real problem (bug 6220).
+        *
+        * @note could also have existing links here from broken file
+        * redirects.
         * @return bool
         */
        function forceExistenceCheck() {
                return true;
        }
 
+       /**
+        * Does the file exist?
+        *
+        * Use wfFindFile so we still think file namespace pages without
+        * files are missing, but valid file redirects and foreign files are ok.
+        *
+        * @return boolean
+        */
+       protected function existenceCheck( Title $title ) {
+               return (bool) wfFindFile( $title );
+       }
+
        function getQueryInfo() {
                return array(
                        'tables' => array(
@@ -90,7 +123,7 @@ class WantedFilesPage extends WantedQueryPage {
                                'img1.img_name' => null,
                                // We also need to exclude file redirects
                                'img2.img_name' => null,
-                        ),
+                       ),
                        'options' => array( 'GROUP BY' => 'il_to' ),
                        'join_conds' => array(
                                'img1' => array( 'LEFT JOIN',
index c54d9f4..38f1808 100644 (file)
@@ -54,8 +54,7 @@ class WantedPagesPage extends WantedQueryPage {
        }
 
        function getQueryInfo() {
-               global $wgWantedPagesThreshold;
-               $count = $wgWantedPagesThreshold - 1;
+               $count = $this->getConfig()->get( 'WantedPagesThreshold' ) - 1;
                $query = array(
                        'tables' => array(
                                'pagelinks',
index 21a1f9b..8f2f86b 100644 (file)
@@ -38,8 +38,6 @@ class SpecialWatchlist extends ChangesListSpecialPage {
         * @param string $subpage
         */
        function execute( $subpage ) {
-               global $wgEnotifWatchlist, $wgShowUpdatedMarker;
-
                // Anons don't get a watchlist
                $this->requireLogin( 'watchlistanontext' );
 
@@ -66,7 +64,8 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                $user = $this->getUser();
                $opts = $this->getOptions();
 
-               if ( ( $wgEnotifWatchlist || $wgShowUpdatedMarker )
+               $config = $this->getConfig();
+               if ( ( $config->get( 'EnotifWatchlist' ) || $config->get( 'ShowUpdatedMarker' ) )
                        && $request->getVal( 'reset' )
                        && $request->wasPosted()
                ) {
@@ -83,7 +82,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
         * Return an array of subpages beginning with $search that this special page will accept.
         *
         * @param string $search Prefix to search for
-        * @param integer $limit Maximum number of results to return
+        * @param int $limit Maximum number of results to return
         * @return string[] Matching subpages
         */
        public function prefixSearchSubpages( $search, $limit = 10 ) {
@@ -198,8 +197,6 @@ class SpecialWatchlist extends ChangesListSpecialPage {
         * @return bool|ResultWrapper Result or false (for Recentchangeslinked only)
         */
        public function doMainQuery( $conds, $opts ) {
-               global $wgShowUpdatedMarker;
-
                $dbr = $this->getDB();
                $user = $this->getUser();
 
@@ -238,7 +235,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                        ),
                );
 
-               if ( $wgShowUpdatedMarker ) {
+               if ( $this->getConfig()->get( 'ShowUpdatedMarker' ) ) {
                        $fields[] = 'wl_notificationtimestamp';
                }
                if ( $limitWatchlist ) {
@@ -258,7 +255,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                // the necessary rights.
                if ( !$user->isAllowed( 'deletedhistory' ) ) {
                        $bitmask = LogPage::DELETED_ACTION;
-               } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
                        $bitmask = LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED;
                } else {
                        $bitmask = 0;
@@ -279,9 +276,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                        ''
                );
 
-               wfRunHooks( 'SpecialWatchlistQuery',
-                       array( &$conds, &$tables, &$join_conds, &$fields, $opts ),
-                       '1.23' );
+               $this->runMainQueryHook( $tables, $fields, $conds, $query_options, $join_conds, $opts );
 
                return $dbr->select(
                        $tables,
@@ -293,6 +288,15 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                );
        }
 
+       protected function runMainQueryHook( &$tables, &$fields, &$conds, &$query_options, &$join_conds, $opts ) {
+               return parent::runMainQueryHook( $tables, $fields, $conds, $query_options, $join_conds, $opts )
+                       && wfRunHooks(
+                               'SpecialWatchlistQuery',
+                               array( &$conds, &$tables, &$join_conds, &$fields, $opts ),
+                               '1.23'
+                       );
+       }
+
        /**
         * Return a DatabaseBase object for reading
         *
@@ -325,8 +329,6 @@ class SpecialWatchlist extends ChangesListSpecialPage {
         * @param FormOptions $opts
         */
        public function outputChangesList( $rows, $opts ) {
-               global $wgShowUpdatedMarker, $wgRCShowWatchingUsers;
-
                $dbr = $this->getDB();
                $user = $this->getUser();
                $output = $this->getOutput();
@@ -359,13 +361,13 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                        $rc = RecentChange::newFromRow( $obj );
                        $rc->counter = $counter++;
 
-                       if ( $wgShowUpdatedMarker ) {
+                       if ( $this->getConfig()->get( 'ShowUpdatedMarker' ) ) {
                                $updated = $obj->wl_notificationtimestamp;
                        } else {
                                $updated = false;
                        }
 
-                       if ( $wgRCShowWatchingUsers && $user->getOption( 'shownumberswatching' ) ) {
+                       if ( $this->getConfig()->get( 'RCShowWatchingUsers' ) && $user->getOption( 'shownumberswatching' ) ) {
                                $rc->numberofWatchingusers = $dbr->selectField( 'watchlist',
                                        'COUNT(*)',
                                        array(
@@ -388,12 +390,12 @@ class SpecialWatchlist extends ChangesListSpecialPage {
        }
 
        /**
-        * Return the text to be displayed above the changes
+        * Set the text to be displayed above the changes
         *
         * @param FormOptions $opts
-        * @return string XHTML
+        * @param int $numRows Number of rows in the result to show after this header
         */
-       public function doHeader( $opts ) {
+       public function doHeader( $opts, $numRows ) {
                $user = $this->getUser();
 
                $this->getOutput()->addSubtitle(
@@ -407,7 +409,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                $wlInfo = '';
                if ( $opts['days'] > 0 ) {
                        $timestamp = wfTimestampNow();
-                       $wlInfo = $this->msg( 'wlnote2' )->numParams( round( $opts['days'] * 24 ) )->params(
+                       $wlInfo = $this->msg( 'wlnote' )->numParams( $numRows, round( $opts['days'] * 24 ) )->params(
                                $lang->userDate( $timestamp, $user ), $lang->userTime( $timestamp, $user )
                        )->parse() . "<br />\n";
                }
@@ -487,14 +489,13 @@ class SpecialWatchlist extends ChangesListSpecialPage {
        }
 
        function setTopText( FormOptions $opts ) {
-               global $wgEnotifWatchlist, $wgShowUpdatedMarker;
-
                $nondefaults = $opts->getChangedValues();
                $form = "";
                $user = $this->getUser();
 
                $dbr = $this->getDB();
                $numItems = $this->countItems( $dbr );
+               $showUpdatedMarker = $this->getConfig()->get( 'ShowUpdatedMarker' );
 
                // Show watchlist header
                $form .= "<p>";
@@ -502,16 +503,16 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                        $form .= $this->msg( 'nowatchlist' )->parse() . "\n";
                } else {
                        $form .= $this->msg( 'watchlist-details' )->numParams( $numItems )->parse() . "\n";
-                       if ( $wgEnotifWatchlist && $user->getOption( 'enotifwatchlistpages' ) ) {
+                       if ( $this->getConfig()->get( 'EnotifWatchlist' ) && $user->getOption( 'enotifwatchlistpages' ) ) {
                                $form .= $this->msg( 'wlheader-enotif' )->parse() . "\n";
                        }
-                       if ( $wgShowUpdatedMarker ) {
+                       if ( $showUpdatedMarker ) {
                                $form .= $this->msg( 'wlheader-showupdated' )->parse() . "\n";
                        }
                }
                $form .= "</p>";
 
-               if ( $numItems > 0 && $wgShowUpdatedMarker ) {
+               if ( $numItems > 0 && $showUpdatedMarker ) {
                        $form .= Xml::openElement( 'form', array( 'method' => 'post',
                                'action' => $this->getPageTitle()->getLocalURL(),
                                'id' => 'mw-watchlist-resetbutton' ) ) . "\n" .
index d980f79..7dc6da1 100644 (file)
@@ -42,7 +42,6 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
        }
 
        function execute( $par ) {
-               global $wgQueryPageDefaultLimit;
                $out = $this->getOutput();
 
                $this->setHeaders();
@@ -52,7 +51,7 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
 
                $opts->add( 'target', '' );
                $opts->add( 'namespace', '', FormOptions::INTNULL );
-               $opts->add( 'limit', $wgQueryPageDefaultLimit );
+               $opts->add( 'limit', $this->getConfig()->get( 'QueryPageDefaultLimit' ) );
                $opts->add( 'from', 0 );
                $opts->add( 'back', 0 );
                $opts->add( 'hideredirs', false );
@@ -101,10 +100,8 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
         * @param int $back Display from this article ID at backwards scrolling (default: 0)
         */
        function showIndirectLinks( $level, $target, $limit, $from = 0, $back = 0 ) {
-               global $wgMaxRedirectLinksRetrieved;
                $out = $this->getOutput();
                $dbr = wfGetDB( DB_SLAVE );
-               $options = array();
 
                $hidelinks = $this->opts->getValue( 'hidelinks' );
                $hideredirs = $this->opts->getValue( 'hideredirs' );
@@ -113,77 +110,88 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
 
                $fetchlinks = ( !$hidelinks || !$hideredirs );
 
-               // Make the query
-               $plConds = array(
-                       'page_id=pl_from',
+               // Build query conds in concert for all three tables...
+               $conds['pagelinks'] = array(
                        'pl_namespace' => $target->getNamespace(),
                        'pl_title' => $target->getDBkey(),
                );
-               if ( $hideredirs ) {
-                       $plConds['rd_from'] = null;
-               } elseif ( $hidelinks ) {
-                       $plConds[] = 'rd_from is NOT NULL';
-               }
-
-               $tlConds = array(
-                       'page_id=tl_from',
+               $conds['templatelinks'] = array(
                        'tl_namespace' => $target->getNamespace(),
                        'tl_title' => $target->getDBkey(),
                );
-
-               $ilConds = array(
-                       'page_id=il_from',
+               $conds['imagelinks'] = array(
                        'il_to' => $target->getDBkey(),
                );
 
+               $useLinkNamespaceDBFields = $this->getConfig()->get( 'UseLinkNamespaceDBFields' );
                $namespace = $this->opts->getValue( 'namespace' );
                if ( is_int( $namespace ) ) {
-                       $plConds['page_namespace'] = $namespace;
-                       $tlConds['page_namespace'] = $namespace;
-                       $ilConds['page_namespace'] = $namespace;
+                       if ( $useLinkNamespaceDBFields ) {
+                               $conds['pagelinks']['pl_from_namespace'] = $namespace;
+                               $conds['templatelinks']['tl_from_namespace'] = $namespace;
+                               $conds['imagelinks']['il_from_namespace'] = $namespace;
+                       } else {
+                               $conds['pagelinks']['page_namespace'] = $namespace;
+                               $conds['templatelinks']['page_namespace'] = $namespace;
+                               $conds['imagelinks']['page_namespace'] = $namespace;
+                       }
                }
 
                if ( $from ) {
-                       $tlConds[] = "tl_from >= $from";
-                       $plConds[] = "pl_from >= $from";
-                       $ilConds[] = "il_from >= $from";
+                       $conds['templatelinks'][] = "tl_from >= $from";
+                       $conds['pagelinks'][] = "pl_from >= $from";
+                       $conds['imagelinks'][] = "il_from >= $from";
                }
 
-               // Read an extra row as an at-end check
-               $queryLimit = $limit + 1;
-
-               $options['LIMIT'] = $queryLimit;
-               $fields = array( 'page_id', 'page_namespace', 'page_title', 'rd_from' );
+               if ( $hideredirs ) {
+                       $conds['pagelinks']['rd_from'] = null;
+               } elseif ( $hidelinks ) {
+                       $conds['pagelinks'][] = 'rd_from is NOT NULL';
+               }
 
-               $joinConds = array( 'redirect' => array( 'LEFT JOIN', array(
-                       'rd_from = page_id',
-                       'rd_namespace' => $target->getNamespace(),
-                       'rd_title' => $target->getDBkey(),
-                       'rd_interwiki = ' . $dbr->addQuotes( '' ) . ' OR rd_interwiki IS NULL'
-               ) ) );
+               $queryFunc = function ( $dbr, $table, $fromCol ) use ( $conds, $target, $limit, $useLinkNamespaceDBFields ) {
+                       // Read an extra row as an at-end check
+                       $queryLimit = $limit + 1;
+                       $on = array(
+                               "rd_from = $fromCol",
+                               'rd_title' => $target->getDBkey(),
+                               'rd_interwiki = ' . $dbr->addQuotes( '' ) . ' OR rd_interwiki IS NULL'
+                       );
+                       if ( $useLinkNamespaceDBFields ) { // migration check
+                               $on['rd_namespace'] = $target->getNamespace();
+                       }
+                       // Inner LIMIT is 2X in case of stale backlinks with wrong namespaces
+                       $subQuery = $dbr->selectSqlText(
+                               array( $table, 'page', 'redirect' ),
+                               array( $fromCol, 'rd_from' ),
+                               $conds[$table],
+                               __CLASS__ . '::showIndirectLinks',
+                               array( 'ORDER BY' => $fromCol, 'LIMIT' => 2 * $queryLimit ),
+                               array(
+                                       'page' => array( 'INNER JOIN', "$fromCol = page_id" ),
+                                       'redirect' => array( 'LEFT JOIN', $on )
+                               )
+                       );
+                       return $dbr->select(
+                               array( 'page', 'temp_backlink_range' => "($subQuery)" ),
+                               array( 'page_id', 'page_namespace', 'page_title', 'rd_from' ),
+                               array(),
+                               __CLASS__ . '::showIndirectLinks',
+                               array( 'ORDER BY' => 'page_id', 'LIMIT' => $queryLimit ),
+                               array( 'page' => array( 'INNER JOIN', "$fromCol = page_id" ) )
+                       );
+               };
 
                if ( $fetchlinks ) {
-                       $options['ORDER BY'] = 'pl_from';
-                       $plRes = $dbr->select( array( 'pagelinks', 'page', 'redirect' ), $fields,
-                               $plConds, __METHOD__, $options,
-                               $joinConds
-                       );
+                       $plRes = $queryFunc( $dbr, 'pagelinks', 'pl_from' );
                }
 
                if ( !$hidetrans ) {
-                       $options['ORDER BY'] = 'tl_from';
-                       $tlRes = $dbr->select( array( 'templatelinks', 'page', 'redirect' ), $fields,
-                               $tlConds, __METHOD__, $options,
-                               $joinConds
-                       );
+                       $tlRes = $queryFunc( $dbr, 'templatelinks', 'tl_from' );
                }
 
                if ( !$hideimages ) {
-                       $options['ORDER BY'] = 'il_from';
-                       $ilRes = $dbr->select( array( 'imagelinks', 'page', 'redirect' ), $fields,
-                               $ilConds, __METHOD__, $options,
-                               $joinConds
-                       );
+                       $ilRes = $queryFunc( $dbr, 'imagelinks', 'il_from' );
                }
 
                if ( ( !$fetchlinks || !$plRes->numRows() )
@@ -200,6 +208,7 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
                                        }
                                        $errMsg = is_int( $namespace ) ? 'nolinkshere-ns' : 'nolinkshere';
                                        $out->addWikiMsg( $errMsg, $this->target->getPrefixedText() );
+                                       $out->setStatusCode( 404 );
                                }
                        }
 
@@ -266,7 +275,7 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
 
                        if ( $row->rd_from && $level < 2 ) {
                                $out->addHTML( $this->listItem( $row, $nt, $target, true ) );
-                               $this->showIndirectLinks( $level + 1, $nt, $wgMaxRedirectLinksRetrieved );
+                               $this->showIndirectLinks( $level + 1, $nt, $this->getConfig()->get( 'MaxRedirectLinksRetrieved' ) );
                                $out->addHTML( Xml::closeElement( 'li' ) );
                        } else {
                                $out->addHTML( $this->listItem( $row, $nt, $target ) );
@@ -403,8 +412,6 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
        }
 
        function whatlinkshereForm() {
-               global $wgScript;
-
                // We get nicer value from the title object
                $this->opts->consumeValue( 'target' );
                // Reset these for new requests
@@ -414,7 +421,7 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
                $namespace = $this->opts->consumeValue( 'namespace' );
 
                # Build up the form
-               $f = Xml::openElement( 'form', array( 'action' => $wgScript ) );
+               $f = Xml::openElement( 'form', array( 'action' => wfScript() ) );
 
                # Values that should not be forgotten
                $f .= Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() );
index e05faef..bd01461 100644 (file)
@@ -41,8 +41,6 @@ class WithoutInterwikiPage extends PageQueryPage {
        }
 
        function getPageHeader() {
-               global $wgScript;
-
                # Do not show useless input form if special page is cached
                if ( $this->isCached() ) {
                        return '';
@@ -51,7 +49,7 @@ class WithoutInterwikiPage extends PageQueryPage {
                $prefix = $this->prefix;
                $t = $this->getPageTitle();
 
-               return Html::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) . "\n" .
+               return Html::openElement( 'form', array( 'method' => 'get', 'action' => wfScript() ) ) . "\n" .
                        Html::openElement( 'fieldset' ) . "\n" .
                        Html::element( 'legend', null, $this->msg( 'withoutinterwiki-legend' )->text() ) . "\n" .
                        Html::hidden( 'title', $t->getPrefixedText() ) . "\n" .
index 33b2400..0f9a6ba 100644 (file)
@@ -72,7 +72,7 @@ if ( !function_exists( 'session_name' ) ) {
                </style>
        </head>
        <body>
-               <img src="<?php echo htmlspecialchars( $path ) ?>skins/common/images/mediawiki.png" alt='The MediaWiki logo' />
+               <img src="<?php echo htmlspecialchars( $path ) ?>assets/mediawiki.png" alt='The MediaWiki logo' />
 
                <h1>MediaWiki <?php echo htmlspecialchars( $wgVersion ) ?></h1>
                <div class='error'>
@@ -81,9 +81,9 @@ if ( !function_exists( 'session_name' ) ) {
                        <p>
                        <?php
                        if ( $installerStarted ) {
-                               echo "Please <a href=\"" . htmlspecialchars( $path ) . "mw-config/index." . htmlspecialchars( $ext ) . "\"> complete the installation</a> and download LocalSettings.php.";
+                               echo "Please <a href=\"" . htmlspecialchars( $path ) . "mw-config/index." . htmlspecialchars( $ext ) . "\">complete the installation</a> and download LocalSettings.php.";
                        } else {
-                               echo "Please <a href=\"" . htmlspecialchars( $path ) . "mw-config/index." . htmlspecialchars( $ext ) . "\"> set up the wiki</a> first.";
+                               echo "Please <a href=\"" . htmlspecialchars( $path ) . "mw-config/index." . htmlspecialchars( $ext ) . "\">set up the wiki</a> first.";
                        }
                        ?>
                        </p>
index a4240e2..01da0bd 100644 (file)
@@ -81,7 +81,7 @@ class UsercreateTemplate extends BaseTemplate {
                                </label>
                                <?php
                                echo Html::input( 'wpName', $this->data['name'], 'text', array(
-                                       'class' => 'mw-input loginText',
+                                       'class' => 'mw-ui-input loginText',
                                        'id' => 'wpName2',
                                        'tabindex' => '1',
                                        'size' => '20',
@@ -94,14 +94,15 @@ class UsercreateTemplate extends BaseTemplate {
 
                        <div class="mw-ui-vform-field">
                                <?php if ( $this->data['createemail'] ) { ?>
-                                       <label class="mw-ui-checkbox-label">
+                                       <div class="mw-ui-checkbox">
                                                <input name="wpCreateaccountMail" type="checkbox" value="1" id="wpCreateaccountMail" tabindex="2"
                                                        <?php if ( $this->data['createemailset'] ) {
                                                                echo 'checked="checked"';
                                                        } ?>
-                                               >
-                                               <?php $this->msg( 'createaccountmail' ); ?>
-                                       </label>
+                                               ><label for="wpCreateaccountMail">
+                                                       <?php $this->msg( 'createaccountmail' ); ?>
+                                               </label>
+                                       </div>
                                <?php } ?>
                        </div>
 
@@ -109,7 +110,7 @@ class UsercreateTemplate extends BaseTemplate {
                                <label for='wpPassword2'><?php $this->msg( 'userlogin-yourpassword' ); ?></label>
                                <?php
                                echo Html::input( 'wpPassword', null, 'password', array(
-                                       'class' => 'mw-input loginPassword',
+                                       'class' => 'mw-ui-input loginPassword',
                                        'id' => 'wpPassword2',
                                        'tabindex' => '3',
                                        'size' => '20',
@@ -129,7 +130,7 @@ class UsercreateTemplate extends BaseTemplate {
                        ?>
                                <div class="mw-ui-vform-field" id="mw-user-domain-section">
                                        <label for="wpDomain"><?php $this->msg( 'yourdomainname' ); ?></label>
-                                       <div class="mw-input">
+                                       <div>
                                                <?php echo $select->getHTML(); ?>
                                        </div>
                                </div>
@@ -139,7 +140,7 @@ class UsercreateTemplate extends BaseTemplate {
                                <label for='wpRetype'><?php $this->msg( 'createacct-yourpasswordagain' ); ?></label>
                                <?php
                                echo Html::input( 'wpRetype', null, 'password', array(
-                                       'class' => 'mw-input loginPassword',
+                                       'class' => 'mw-ui-input loginPassword',
                                        'id' => 'wpRetype',
                                        'tabindex' => '5',
                                        'size' => '20',
@@ -161,7 +162,7 @@ class UsercreateTemplate extends BaseTemplate {
                                        </label>
                                        <?php
                                                echo Html::input( 'wpEmail', $this->data['email'], 'email', array(
-                                                       'class' => 'mw-input loginText',
+                                                       'class' => 'mw-ui-input loginText',
                                                        'id' => 'wpEmail',
                                                        'tabindex' => '6',
                                                        'size' => '20',
@@ -176,7 +177,7 @@ class UsercreateTemplate extends BaseTemplate {
                        <?php if ( $this->data['userealname'] ) { ?>
                                <div class="mw-ui-vform-field">
                                        <label for='wpRealName'><?php $this->msg( 'createacct-realname' ); ?></label>
-                                       <input type='text' class='mw-input loginText' name="wpRealName" id="wpRealName"
+                                       <input type='text' class='mw-ui-input loginText' name="wpRealName" id="wpRealName"
                                                tabindex="7"
                                                value="<?php $this->text( 'realname' ); ?>" size='20' />
                                        <div class="prefsectiontip">
@@ -189,7 +190,7 @@ class UsercreateTemplate extends BaseTemplate {
                                <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(
-                                               'class' => 'mw-input loginText',
+                                               'class' => 'mw-ui-input loginText',
                                                'id' => 'wpReason',
                                                'tabindex' => '8',
                                                'size' => '20',
@@ -207,7 +208,7 @@ class UsercreateTemplate extends BaseTemplate {
                                                // If it's a checkbox, output the whole thing (assume it has a msg).
                                                if ( $inputItem['type'] == 'checkbox' ) {
                                                ?>
-                                                       <label class="mw-ui-checkbox-label">
+                                                       <div class="mw-ui-checkbox">
                                                                <input
                                                                        name="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
                                                                        id="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
@@ -216,9 +217,8 @@ class UsercreateTemplate extends BaseTemplate {
                                                                        <?php if ( !empty( $inputItem['value'] ) ) {
                                                                                echo 'checked="checked"';
                                                                        } ?>
-                                                               >
-                                                               <?php $this->msgHtml( $inputItem['msg'] ); ?>
-                                                       </label>
+                                                               ><label for="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"></label>
+                                                       </div><?php $this->msgHtml( $inputItem['msg'] ); ?>
                                                <?php
                                                } else {
                                                        // Not a checkbox.
@@ -231,7 +231,7 @@ class UsercreateTemplate extends BaseTemplate {
                                                        <?php } ?>
                                                        <input
                                                                type="<?php echo htmlspecialchars( $inputItem['type'] ); ?>"
-                                                               class="mw-input"
+                                                               class="mw-ui-input"
                                                                name="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
                                                                tabindex="<?php echo $tabIndex++; ?>"
                                                                value="<?php echo htmlspecialchars( $inputItem['value'] ); ?>"
index 19ea20b..ad01905 100644 (file)
@@ -29,6 +29,7 @@ class UserloginTemplate extends BaseTemplate {
                $expirationDays = ceil( $wgCookieExpiration / ( 3600 * 24 ) );
 ?>
 <div class="mw-ui-container">
+       <div id="userloginprompt"><?php $this->msgWiki('loginprompt') ?></div>
        <?php if ( $this->haveData( 'languages' ) ) { ?>
                <div id="languagelinks">
                        <p><?php $this->html( 'languages' ); ?></p>
@@ -36,11 +37,6 @@ class UserloginTemplate extends BaseTemplate {
        <?php } ?>
        <div id="userloginForm">
                <form name="userlogin" class="mw-ui-vform" method="post" action="<?php $this->text( 'action' ); ?>">
-                       <?php if ( $this->data['loggedin'] ) { ?>
-                               <div class="warningbox">
-                                       <?php echo $this->getMsg( 'userlogin-loggedin' )->params( $this->data['loggedinuser'] )->parse(); ?>
-                               </div>
-                       <?php } ?>
                        <section class="mw-form-header">
                                <?php $this->html( 'header' ); /* extensions such as ConfirmEdit add form HTML here */ ?>
                        </section>
@@ -71,7 +67,7 @@ class UserloginTemplate extends BaseTemplate {
                                <?php
                                $extraAttrs = array();
                                echo Html::input( 'wpName', $this->data['name'], 'text', array(
-                                       'class' => 'loginText',
+                                       'class' => 'loginText mw-ui-input',
                                        'id' => 'wpName1',
                                        'tabindex' => '1',
                                        'size' => '20',
@@ -101,7 +97,7 @@ class UserloginTemplate extends BaseTemplate {
                                </label>
                                <?php
                                echo Html::input( 'wpPassword', null, 'password', array(
-                                       'class' => 'loginPassword',
+                                       'class' => 'loginPassword mw-ui-input',
                                        'id' => 'wpPassword1',
                                        'tabindex' => '2',
                                        'size' => '20',
@@ -134,14 +130,14 @@ class UserloginTemplate extends BaseTemplate {
 
                        <div class="mw-ui-vform-field">
                                <?php if ( $this->data['canremember'] ) { ?>
-                                       <label class="mw-ui-checkbox-label">
+                                       <div class="mw-ui-checkbox">
                                                <input name="wpRemember" type="checkbox" value="1" id="wpRemember" tabindex="4"
                                                        <?php if ( $this->data['remember'] ) {
                                                                echo 'checked="checked"';
                                                        } ?>
-                                               >
-                                               <?php echo $this->getMsg( 'userlogin-remembermypassword' )->numParams( $expirationDays )->escaped(); ?>
-                                       </label>
+                                               ><label for="wpRemember">
+                                                       <?php echo $this->getMsg( 'userlogin-remembermypassword' )->numParams( $expirationDays )->escaped(); ?></label>
+                                       </div>
                                <?php } ?>
                        </div>
 
@@ -170,15 +166,9 @@ class UserloginTemplate extends BaseTemplate {
                        </div>
 
                        <?php if ( $this->haveData( 'createOrLoginHref' ) ) { ?>
-                               <?php if ( $this->data['loggedin'] ) { ?>
-                                       <div id="mw-createaccount-another">
-                                               <a href="<?php $this->text( 'createOrLoginHref' ); ?>" id="mw-createaccount-join" tabindex="7"  class="mw-ui-button"><?php $this->msg( 'userlogin-createanother' ); ?></a>
-                                       </div>
-                               <?php } else { ?>
-                                       <div id="mw-createaccount-cta">
-                                               <?php $this->msg( 'userlogin-noaccount' ); ?><a href="<?php $this->text( 'createOrLoginHref' ); ?>" id="mw-createaccount-join" tabindex="7"  class="mw-ui-button mw-ui-progressive"><?php $this->msg( 'userlogin-joinproject' ); ?></a>
-                                       </div>
-                               <?php } ?>
+                               <div id="mw-createaccount-cta">
+                                       <?php $this->msg( 'userlogin-noaccount' ); ?><a href="<?php $this->text( 'createOrLoginHref' ); ?>" id="mw-createaccount-join" tabindex="7"  class="mw-ui-button mw-ui-progressive"><?php $this->msg( 'userlogin-joinproject' ); ?></a>
+                               </div>
                        <?php } ?>
                        <?php if ( $this->haveData( 'uselang' ) ) { ?><input type="hidden" name="uselang" value="<?php $this->text( 'uselang' ); ?>" /><?php } ?>
                        <?php if ( $this->haveData( 'token' ) ) { ?><input type="hidden" name="wpLoginToken" value="<?php $this->text( 'token' ); ?>" /><?php } ?>
index c593dca..f46cb5e 100644 (file)
@@ -45,7 +45,7 @@ class MediaWikiPageLinkRenderer implements PageLinkRenderer {
         * HtmlPageLinkRenderer, we will be using them, so it seems prudent to
         * already declare the dependency and inject them.
         *
-        * @param TitleFormatter $formatter formatter for generating the target title string
+        * @param TitleFormatter $formatter Formatter for generating the target title string
         * @param string $baseUrl (currently unused, pending refactoring of Linker).
         *        Defaults to $wgArticlePath.
         */
@@ -62,7 +62,7 @@ class MediaWikiPageLinkRenderer implements PageLinkRenderer {
         * Returns the (partial) URL for the given page (including any section identifier).
         *
         * @param TitleValue $page The link's target
-        * @param array $params any additional URL parameters.
+        * @param array $params Any additional URL parameters.
         *
         * @return string
         */
index 8798de5..6ca0799 100644 (file)
@@ -25,7 +25,7 @@
 /**
  * A codec for %MediaWiki page titles.
  *
- * @note: Normalization and validation is applied while parsing, not when formatting.
+ * @note Normalization and validation is applied while parsing, not when formatting.
  * It's possible to construct a TitleValue with an invalid title, and use MediaWikiTitleCodec
  * to generate an (invalid) title string from it. TitleValues should be constructed only
  * via parseTitle() or from a (semi)trusted source, such as the database.
@@ -49,8 +49,8 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
        protected $localInterwikis;
 
        /**
-        * @param Language $language the language object to use for localizing namespace names.
-        * @param GenderCache $genderCache the gender cache for generating gendered namespace names
+        * @param Language $language The language object to use for localizing namespace names.
+        * @param GenderCache $genderCache The gender cache for generating gendered namespace names
         * @param string[]|string $localInterwikis
         */
        public function __construct( Language $language, GenderCache $genderCache,
@@ -67,7 +67,7 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
         * @param int $namespace
         * @param string $text
         *
-        * @throws InvalidArgumentException if the namespace is invalid
+        * @throws InvalidArgumentException If the namespace is invalid
         * @return string
         */
        public function getNamespaceName( $namespace, $text ) {
@@ -97,7 +97,7 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
         *        Underscores will be replaced.
         * @param string $fragment The fragment name (may be empty).
         *
-        * @throws InvalidArgumentException if the namespace is invalid
+        * @throws InvalidArgumentException If the namespace is invalid
         * @return string
         */
        public function formatTitle( $namespace, $text, $fragment = '' ) {
@@ -187,10 +187,10 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
         * namespace prefixes, sets the other forms, and canonicalizes
         * everything.
         *
-        * @todo: this method is only exposed as a temporary measure to ease refactoring.
+        * @todo this method is only exposed as a temporary measure to ease refactoring.
         * It was copied with minimal changes from Title::secureAndSplit().
         *
-        * @todo: This method should be split up and an appropriate interface
+        * @todo This method should be split up and an appropriate interface
         * defined for use by the Title class.
         *
         * @param string $text
@@ -206,6 +206,7 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
                # Initialisation
                $parts = array(
                        'interwiki' => '',
+                       'local_interwiki' => false,
                        'fragment' => '',
                        'namespace' => $defaultNamespace,
                        'dbkey' => $dbkey,
@@ -282,6 +283,7 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
                                                                $mainPage = Title::newMainPage();
                                                                return array(
                                                                        'interwiki' => $mainPage->getInterwiki(),
+                                                                       'local_interwiki' => true,
                                                                        'fragment' => $mainPage->getFragment(),
                                                                        'namespace' => $mainPage->getNamespace(),
                                                                        'dbkey' => $mainPage->getDBkey(),
@@ -289,6 +291,8 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
                                                                );
                                                        }
                                                        $parts['interwiki'] = '';
+                                                       # local interwikis should behave like initial-colon links
+                                                       $parts['local_interwiki'] = true;
 
                                                        # Do another namespace split...
                                                        continue 2;
index a277594..fb1096e 100644 (file)
@@ -37,7 +37,7 @@ interface PageLinkRenderer {
         * @todo expand this to cover the functionality of Linker::linkUrl
         *
         * @param TitleValue $page The link's target
-        * @param array $params any additional URL parameters.
+        * @param array $params Any additional URL parameters.
         *
         * @return string
         */
index ea58b1e..7c71ef5 100644 (file)
@@ -48,9 +48,9 @@ interface TitleFormatter {
        /**
         * Returns the title text formatted for display, without namespace of fragment.
         *
-        * @note: Only minimal normalization is applied. Consider using TitleValue::getText() directly.
+        * @note Only minimal normalization is applied. Consider using TitleValue::getText() directly.
         *
-        * @param TitleValue $title the title to format
+        * @param TitleValue $title The title to format
         *
         * @return string
         */
@@ -59,7 +59,7 @@ interface TitleFormatter {
        /**
         * Returns the title formatted for display, including the namespace name.
         *
-        * @param TitleValue $title the title to format
+        * @param TitleValue $title The title to format
         *
         * @return string
         */
@@ -68,7 +68,7 @@ interface TitleFormatter {
        /**
         * Returns the title formatted for display, with namespace and fragment.
         *
-        * @param TitleValue $title the title to format
+        * @param TitleValue $title The title to format
         *
         * @return string
         */
index d548663..0635ee8 100644 (file)
@@ -37,8 +37,8 @@ interface TitleParser {
         *
         * @note this only parses local page links, interwiki-prefixes etc. are not considered!
         *
-        * @param string $text the text to parse
-        * @param int $defaultNamespace namespace to assume per default (usually NS_MAIN)
+        * @param string $text The text to parse
+        * @param int $defaultNamespace Namespace to assume per default (usually NS_MAIN)
         *
         * @throws MalformedTitleException If the text is not a valid representation of a page title.
         * @return TitleValue
index 73e1dc2..402247c 100644 (file)
@@ -52,7 +52,7 @@ class TitleValue {
        /**
         * Constructs a TitleValue.
         *
-        * @note: TitleValue expects a valid DB key; typically, a TitleValue is constructed either
+        * @note TitleValue expects a valid DB key; typically, a TitleValue is constructed either
         * from a database entry, or by a TitleParser. We could apply "some" normalization here,
         * such as substituting spaces by underscores, but that would encourage the use of
         * un-normalized text when constructing TitleValues. For constructing a TitleValue from
@@ -122,8 +122,8 @@ class TitleValue {
         *
         * This is computed from the DB key by replacing any underscores with spaces.
         *
-        * @note: To get a title string that includes the namespace and/or fragment,
-        *        use a TitleFormatter.
+        * @note To get a title string that includes the namespace and/or fragment,
+        *       use a TitleFormatter.
         *
         * @return string
         */
index 5defd45..5de543e 100644 (file)
@@ -171,6 +171,7 @@ abstract class UploadBase {
                        return null;
                }
 
+               /** @var UploadBase $handler */
                $handler = new $className;
 
                $handler->initializeFromRequest( $request );
@@ -283,7 +284,7 @@ abstract class UploadBase {
 
        /**
         * Verify whether the upload is sane.
-        * @return mixed self::OK or else an array with error information
+        * @return mixed Const self::OK or else an array with error information
         */
        public function verifyUpload() {
                wfProfileIn( __METHOD__ );
@@ -377,18 +378,19 @@ abstract class UploadBase {
        }
 
        /**
-        * Verify the mime type.
+        * Verify the MIME type.
         *
-        * @note Only checks that it is not an evil mime. The does it have
-        *  correct extension given its mime type check is in verifyFile.
-        * @param string $mime Representing the mime
+        * @note Only checks that it is not an evil MIME. The "does it have
+        *  correct extension given its MIME type?" check is in verifyFile.
+        *  in `verifyFile()` that MIME type and file extension correlate.
+        * @param string $mime Representing the MIME
         * @return mixed True if the file is verified, an array otherwise
         */
        protected function verifyMimeType( $mime ) {
                global $wgVerifyMimeType;
                wfProfileIn( __METHOD__ );
                if ( $wgVerifyMimeType ) {
-                       wfDebug( "\n\nmime: <$mime> extension: <{$this->mFinalExtension}>\n\n" );
+                       wfDebug( "mime: <$mime> extension: <{$this->mFinalExtension}>\n" );
                        global $wgMimeTypeBlacklist;
                        if ( $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) {
                                wfProfileOut( __METHOD__ );
@@ -396,7 +398,7 @@ abstract class UploadBase {
                                return array( 'filetype-badmime', $mime );
                        }
 
-                       # Check IE type
+                       # Check what Internet Explorer would detect
                        $fp = fopen( $this->mTempPath, 'rb' );
                        $chunk = fread( $fp, 256 );
                        fclose( $fp );
@@ -487,7 +489,7 @@ abstract class UploadBase {
 
                $this->mFileProps = FSFile::getPropsFromPath( $this->mTempPath, $this->mFinalExtension );
 
-               # check mime type, if desired
+               # check MIME type, if desired
                $mime = $this->mFileProps['file-mime'];
                $status = $this->verifyMimeType( $mime );
                if ( $status !== true ) {
@@ -593,7 +595,7 @@ abstract class UploadBase {
         * isAllowed() should be called as well for generic is-user-blocked or
         * can-user-upload checking.
         *
-        * @param User $user object to verify the permissions against
+        * @param User $user User object to verify the permissions against
         * @return mixed An array as returned by getUserPermissionsErrors or true
         *   in case the user has proper permissions.
         */
@@ -881,7 +883,7 @@ abstract class UploadBase {
        /**
         * Return the local file and initializes if necessary.
         *
-        * @return LocalFile|null
+        * @return LocalFile|UploadStashFile|null
         */
        public function getLocalFile() {
                if ( is_null( $this->mLocalFile ) ) {
@@ -995,9 +997,9 @@ abstract class UploadBase {
        }
 
        /**
-        * Checks if the mime type of the uploaded file matches the file extension.
+        * Checks if the MIME type of the uploaded file matches the file extension.
         *
-        * @param string $mime The mime type of the uploaded file
+        * @param string $mime The MIME type of the uploaded file
         * @param string $extension The filename extension that the file is to be served with
         * @return bool
         */
@@ -1050,7 +1052,7 @@ abstract class UploadBase {
         * positives in some situations.
         *
         * @param string $file Pathname to the temporary upload file
-        * @param string $mime The mime type of the file
+        * @param string $mime The MIME type of the file
         * @param string $extension The extension of the file
         * @return bool True if the file contains something looking like embedded scripts
         */
@@ -1276,8 +1278,8 @@ abstract class UploadBase {
 
        /**
         * Callback to filter SVG Processing Instructions.
-        * @param string $target processing instruction name
-        * @param string $data processing instruction attribute and value
+        * @param string $target Processing instruction name
+        * @param string $data Processing instruction attribute and value
         * @return bool (true if the filter identified something bad)
         */
        public static function checkSvgPICallback( $target, $data ) {
@@ -1497,7 +1499,7 @@ abstract class UploadBase {
 
        /**
         * Divide the element name passed by the xml parser to the callback into URI and prifix.
-        * @param string $name
+        * @param string $element
         * @return array Containing the namespace URI and prefix
         */
        private static function splitXmlNamespace( $element ) {
@@ -1883,7 +1885,7 @@ abstract class UploadBase {
         * Get the current status of a chunked upload (used for polling).
         * The status will be read from the *current* user session.
         * @param string $statusKey
-        * @return array|bool
+        * @return Status[]|bool
         */
        public static function getSessionStatus( $statusKey ) {
                return isset( $_SESSION[self::SESSION_STATUS_KEY][$statusKey] )
index 6f90280..1499302 100644 (file)
@@ -32,6 +32,8 @@ class UploadFromChunks extends UploadFromFile {
        protected $mChunkIndex;
        protected $mFileKey;
        protected $mVirtualTempPath;
+       /** @var LocalRepo */
+       private $repo;
 
        /**
         * Setup local pointers to stash, repo and user (similar to UploadFromStash)
@@ -60,15 +62,13 @@ class UploadFromChunks extends UploadFromFile {
                        }
                        $this->stash = new UploadStash( $this->repo, $this->user );
                }
-
-               return true;
        }
 
        /**
         * Calls the parent stashFile and updates the uploadsession table to handle "chunks"
         *
         * @param User|null $user
-        * @return UploadStashFile stashed file
+        * @return UploadStashFile Stashed file
         */
        public function stashFile( User $user = null ) {
                // Stash file is the called on creating a new chunk session:
@@ -201,9 +201,9 @@ class UploadFromChunks extends UploadFromFile {
        /**
         * Add a chunk to the temporary directory
         *
-        * @param string $chunkPath path to temporary chunk file
-        * @param int $chunkSize size of the current chunk
-        * @param int $offset offset of current chunk ( mutch match database chunk offset )
+        * @param string $chunkPath Path to temporary chunk file
+        * @param int $chunkSize Size of the current chunk
+        * @param int $offset Offset of current chunk ( mutch match database chunk offset )
         * @return Status
         */
        public function addChunk( $chunkPath, $chunkSize, $offset ) {
index a7e7100..7d80b44 100644 (file)
@@ -167,7 +167,7 @@ class UploadStash {
        /**
         * Getter for file metadata.
         *
-        * @param string $key key under which file information is stored
+        * @param string $key Key under which file information is stored
         * @return array
         */
        public function getMetadata( $key ) {
@@ -179,7 +179,7 @@ class UploadStash {
        /**
         * Getter for fileProps
         *
-        * @param string $key key under which file information is stored
+        * @param string $key Key under which file information is stored
         * @return array
         */
        public function getFileProps( $key ) {
@@ -443,7 +443,7 @@ class UploadStash {
        }
 
        /**
-        * Find or guess extension -- ensuring that our extension matches our mime type.
+        * Find or guess extension -- ensuring that our extension matches our MIME type.
         * Since these files are constructed from php tempnames they may not start off
         * with an extension.
         * XXX this is somewhat redundant with the checks that ApiUpload.php does with incoming
@@ -460,7 +460,7 @@ class UploadStash {
                if ( $n !== false ) {
                        $extension = $n ? substr( $path, $n + 1 ) : '';
                } else {
-                       // If not, assume that it should be related to the mime type of the original file.
+                       // If not, assume that it should be related to the MIME type of the original file.
                        $magic = MimeMagic::singleton();
                        $mimeType = $magic->guessMimeType( $path );
                        $extensions = explode( ' ', MimeMagic::singleton()->getExtensionsForType( $mimeType ) );
@@ -523,7 +523,7 @@ class UploadStash {
        /**
         * Helper function: Initialize the UploadStashFile for a given file.
         *
-        * @param string $key key under which to store the object
+        * @param string $key Key under which to store the object
         * @throws UploadStashZeroLengthFileException
         * @return bool
         */
index b6df18b..1e521cb 100644 (file)
@@ -151,8 +151,7 @@ class ArrayUtils {
         * @since 1.23
         *
         * @param array $array1 The array to compare from
-        * @param array $array2 An array to compare against
-        * @param array ... More arrays to compare against
+        * @param array $array2,... More arrays to compare against
         * @return array An array containing all the values from array1
         *               that are not present in any of the other arrays.
         */
index b16d4a4..3ceb620 100644 (file)
@@ -34,7 +34,7 @@ abstract class CdbReader {
        /**
         * Open a file and return a subclass instance
         *
-        * @param $fileName string
+        * @param string $fileName
         *
         * @return CdbReader
         */
@@ -64,7 +64,7 @@ abstract class CdbReader {
        /**
         * Create the object and open the file
         *
-        * @param $fileName string
+        * @param string $fileName
         */
        abstract public function __construct( $fileName );
 
@@ -76,7 +76,7 @@ abstract class CdbReader {
        /**
         * Get a value with a given key. Only string values are supported.
         *
-        * @param $key string
+        * @param string $key
         */
        abstract public function get( $key );
 }
@@ -107,7 +107,7 @@ abstract class CdbWriter {
         * Open a writer and return a subclass instance.
         * The user must have write access to the directory, for temporary file creation.
         *
-        * @param $fileName string
+        * @param string $fileName
         *
         * @return CdbWriterDBA|CdbWriterPHP
         */
@@ -120,14 +120,14 @@ abstract class CdbWriter {
        /**
         * Create the object and open the file
         *
-        * @param $fileName string
+        * @param string $fileName
         */
        abstract public function __construct( $fileName );
 
        /**
         * Set a key to a given value. The value will be converted to string.
-        * @param $key string
-        * @param $value string
+        * @param string $key
+        * @param string $value
         */
        abstract public function set( $key, $value );
 
@@ -148,6 +148,7 @@ abstract class CdbWriter {
 
        /**
         * Are we running on Windows?
+        * @return bool
         */
        protected function isWindows() {
                return substr( php_uname(), 0, 7 ) == 'Windows';
index baba580..19d747a 100644 (file)
@@ -32,8 +32,8 @@ class CdbFunctions {
         * Take a modulo of a signed integer as if it were an unsigned integer.
         * $b must be less than 0x40000000 and greater than 0
         *
-        * @param $a
-        * @param $b
+        * @param int $a
+        * @param int $b
         *
         * @return int
         */
@@ -49,8 +49,8 @@ class CdbFunctions {
 
        /**
         * Shift a signed integer right as if it were unsigned
-        * @param $a
-        * @param $b
+        * @param int $a
+        * @param int $b
         * @return int
         */
        public static function unsignedShiftRight( $a, $b ) {
@@ -67,7 +67,7 @@ class CdbFunctions {
        /**
         * The CDB hash function.
         *
-        * @param $s string
+        * @param string $s
         *
         * @return int
         */
@@ -125,7 +125,7 @@ class CdbReaderPHP extends CdbReader {
        protected $dlen;
 
        /**
-        * @param $fileName string
+        * @param string $fileName
         * @throws CdbException
         */
        public function __construct( $fileName ) {
@@ -145,7 +145,7 @@ class CdbReaderPHP extends CdbReader {
        }
 
        /**
-        * @param $key
+        * @param mixed $key
         * @return bool|string
         */
        public function get( $key ) {
@@ -158,8 +158,8 @@ class CdbReaderPHP extends CdbReader {
        }
 
        /**
-        * @param $key
-        * @param $pos
+        * @param string $key
+        * @param int $pos
         * @return bool
         */
        protected function match( $key, $pos ) {
@@ -174,8 +174,8 @@ class CdbReaderPHP extends CdbReader {
 
        /**
         * @throws CdbException
-        * @param $length
-        * @param $pos
+        * @param int $length
+        * @param int $pos
         * @return string
         */
        protected function read( $length, $pos ) {
@@ -200,7 +200,7 @@ class CdbReaderPHP extends CdbReader {
 
        /**
         * Unpack an unsigned integer and throw an exception if it needs more than 31 bits
-        * @param $s
+        * @param string $s
         * @throws CdbException
         * @return mixed
         */
@@ -216,7 +216,7 @@ class CdbReaderPHP extends CdbReader {
 
        /**
         * Unpack a 32-bit signed integer
-        * @param $s
+        * @param string $s
         * @return int
         */
        protected function unpackSigned( $s ) {
@@ -226,7 +226,7 @@ class CdbReaderPHP extends CdbReader {
        }
 
        /**
-        * @param $key
+        * @param string $key
         * @return bool
         */
        protected function findNext( $key ) {
@@ -274,7 +274,7 @@ class CdbReaderPHP extends CdbReader {
        }
 
        /**
-        * @param $key
+        * @param mixed $key
         * @return bool
         */
        protected function find( $key ) {
@@ -295,7 +295,7 @@ class CdbWriterPHP extends CdbWriter {
        protected $pos;
 
        /**
-        * @param $fileName string
+        * @param string $fileName
         */
        public function __construct( $fileName ) {
                $this->realFileName = $fileName;
@@ -347,7 +347,7 @@ class CdbWriterPHP extends CdbWriter {
 
        /**
         * @throws CdbException
-        * @param $buf
+        * @param string $buf
         */
        protected function write( $buf ) {
                $len = fwrite( $this->handle, $buf );
@@ -358,7 +358,7 @@ class CdbWriterPHP extends CdbWriter {
 
        /**
         * @throws CdbException
-        * @param $len
+        * @param int $len
         */
        protected function posplus( $len ) {
                $newpos = $this->pos + $len;
@@ -370,9 +370,9 @@ class CdbWriterPHP extends CdbWriter {
        }
 
        /**
-        * @param $keylen
-        * @param $datalen
-        * @param $h
+        * @param int $keylen
+        * @param int $datalen
+        * @param int $h
         */
        protected function addend( $keylen, $datalen, $h ) {
                $this->hplist[] = array(
@@ -388,8 +388,8 @@ class CdbWriterPHP extends CdbWriter {
 
        /**
         * @throws CdbException
-        * @param $keylen
-        * @param $datalen
+        * @param int $keylen
+        * @param int $datalen
         */
        protected function addbegin( $keylen, $datalen ) {
                if ( $keylen > 0x7fffffff ) {
@@ -481,7 +481,7 @@ class CdbWriterPHP extends CdbWriter {
        /**
         * Clean up the temp file and throw an exception
         *
-        * @param $msg string
+        * @param string $msg
         * @throws CdbException
         */
        protected function throwException( $msg ) {
index e4e1cfd..0e2db8c 100644 (file)
@@ -73,8 +73,8 @@ class IP {
         * SIIT IPv4-translated addresses are rejected.
         * Note: canonicalize() tries to convert translated addresses to IPv4.
         *
-        * @param string $ip possible IP address
-        * @return Boolean
+        * @param string $ip Possible IP address
+        * @return bool
         */
        public static function isIPAddress( $ip ) {
                return (bool)preg_match( '/^' . IP_ADDRESS_STRING . '$/', $ip );
@@ -84,8 +84,8 @@ class IP {
         * Given a string, determine if it as valid IP in IPv6 only.
         * Note: Unlike isValid(), this looks for networks too.
         *
-        * @param string $ip possible IP address
-        * @return Boolean
+        * @param string $ip Possible IP address
+        * @return bool
         */
        public static function isIPv6( $ip ) {
                return (bool)preg_match( '/^' . RE_IPV6_ADD . '(?:\/' . RE_IPV6_PREFIX . ')?$/', $ip );
@@ -95,8 +95,8 @@ class IP {
         * Given a string, determine if it as valid IP in IPv4 only.
         * Note: Unlike isValid(), this looks for networks too.
         *
-        * @param string $ip possible IP address
-        * @return Boolean
+        * @param string $ip Possible IP address
+        * @return bool
         */
        public static function isIPv4( $ip ) {
                return (bool)preg_match( '/^' . RE_IP_ADD . '(?:\/' . RE_IP_PREFIX . ')?$/', $ip );
@@ -107,8 +107,8 @@ class IP {
         * SIIT IPv4-translated addresses are rejected.
         * Note: canonicalize() tries to convert translated addresses to IPv4.
         *
-        * @param $ip String
-        * @return Boolean: True if it is valid.
+        * @param string $ip
+        * @return bool True if it is valid
         */
        public static function isValid( $ip ) {
                return ( preg_match( '/^' . RE_IP_ADD . '$/', $ip )
@@ -120,8 +120,8 @@ class IP {
         * SIIT IPv4-translated addresses are rejected.
         * Note: canonicalize() tries to convert translated addresses to IPv4.
         *
-        * @param $ipblock String
-        * @return Boolean: True if it is valid.
+        * @param string $ipblock
+        * @return bool True if it is valid
         */
        public static function isValidBlock( $ipblock ) {
                return ( preg_match( '/^' . RE_IPV6_BLOCK . '$/', $ipblock )
@@ -134,7 +134,7 @@ class IP {
         * IPv4 addresses are just trimmed.
         *
         * @param string $ip IP address in quad or octet form (CIDR or not).
-        * @return String
+        * @return string
         */
        public static function sanitizeIP( $ip ) {
                $ip = trim( $ip );
@@ -186,7 +186,7 @@ class IP {
         * Prettify an IP for display to end users.
         * This will make it more compact and lower-case.
         *
-        * @param $ip string
+        * @param string $ip
         * @return string
         */
        public static function prettifyIP( $ip ) {
@@ -286,9 +286,9 @@ class IP {
         * brackets like in RFC 2732. If the port matches the default port, omit
         * the port specification
         *
-        * @param $host string
-        * @param $port int
-        * @param $defaultPort bool|int
+        * @param string $host
+        * @param int $port
+        * @param bool|int $defaultPort
         * @return string
         */
        public static function combineHostAndPort( $host, $port, $defaultPort = false ) {
@@ -305,8 +305,8 @@ class IP {
        /**
         * Convert an IPv4 or IPv6 hexadecimal representation back to readable format
         *
-        * @param string $hex number, with "v6-" prefix if it is IPv6
-        * @return String: quad-dotted (IPv4) or octet notation (IPv6)
+        * @param string $hex Number, with "v6-" prefix if it is IPv6
+        * @return string Quad-dotted (IPv4) or octet notation (IPv6)
         */
        public static function formatHex( $hex ) {
                if ( substr( $hex, 0, 3 ) == 'v6-' ) { // IPv6
@@ -319,8 +319,8 @@ class IP {
        /**
         * Converts a hexadecimal number to an IPv6 address in octet notation
         *
-        * @param $ip_hex String: pure hex (no v6- prefix)
-        * @return String (of format a:b:c:d:e:f:g:h)
+        * @param string $ip_hex Pure hex (no v6- prefix)
+        * @return string (of format a:b:c:d:e:f:g:h)
         */
        public static function hexToOctet( $ip_hex ) {
                // Pad hex to 32 chars (128 bits)
@@ -339,8 +339,8 @@ class IP {
        /**
         * Converts a hexadecimal number to an IPv4 address in quad-dotted notation
         *
-        * @param $ip_hex String: pure hex
-        * @return String (of format a.b.c.d)
+        * @param string $ip_hex Pure hex
+        * @return string (of format a.b.c.d)
         */
        public static function hexToQuad( $ip_hex ) {
                // Pad hex to 8 chars (32 bits)
@@ -361,8 +361,8 @@ class IP {
         * Determine if an IP address really is an IP address, and if it is public,
         * i.e. not RFC 1918 or similar
         *
-        * @param $ip String
-        * @return Boolean
+        * @param string $ip
+        * @return bool
         */
        public static function isPublic( $ip ) {
                static $privateSet = null;
@@ -388,8 +388,8 @@ class IP {
         * function for an IPv6 address will be prefixed with "v6-", a non-
         * hexadecimal string which sorts after the IPv4 addresses.
         *
-        * @param string $ip quad dotted/octet IP address.
-        * @return String|bool false on failure
+        * @param string $ip Quad dotted/octet IP address.
+        * @return string|bool False on failure
         */
        public static function toHex( $ip ) {
                if ( self::isIPv6( $ip ) ) {
@@ -420,8 +420,8 @@ class IP {
        /**
         * Given an IPv6 address in octet notation, returns a pure hex string.
         *
-        * @param string $ip octet ipv6 IP address.
-        * @return String|bool pure hex (uppercase); false on failure
+        * @param string $ip Octet ipv6 IP address.
+        * @return string|bool Pure hex (uppercase); false on failure
         */
        private static function IPv6ToRawHex( $ip ) {
                $ip = self::sanitizeIP( $ip );
@@ -529,7 +529,7 @@ class IP {
         * Convert a network specification in IPv6 CIDR notation to an
         * integer network and a number of bits
         *
-        * @param $range
+        * @param string $range
         *
         * @return array(string, int)
         */
@@ -570,7 +570,7 @@ class IP {
         *     2001:0db8:85a3::7344 - 2001:0db8:85a3::7344   Explicit range
         *     2001:0db8:85a3::7344/96                       Single IP
         *
-        * @param $range
+        * @param string $range
         *
         * @return array(string, string)
         */
@@ -616,9 +616,9 @@ class IP {
        /**
         * Determine if a given IPv4/IPv6 address is in a given CIDR network
         *
-        * @param string $addr the address to check against the given range.
-        * @param string $range the range to check the given address against.
-        * @return Boolean: whether or not the given address is in the given range.
+        * @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.
         */
        public static function isInRange( $addr, $range ) {
                $hexIP = self::toHex( $addr );
@@ -635,8 +635,8 @@ class IP {
         * This currently only checks a few IPV4-to-IPv6 related cases.  More
         * unusual representations may be added later.
         *
-        * @param string $addr something that might be an IP address
-        * @return String: valid dotted quad IPv4 address or null
+        * @param string $addr Something that might be an IP address
+        * @return string Valid dotted quad IPv4 address or null
         */
        public static function canonicalize( $addr ) {
                // remove zone info (bug 35738)
index 6b6655e..cc13679 100644 (file)
@@ -99,9 +99,10 @@ class MWCryptHKDF {
 
 
        /**
-        * @param string $hash Name of hashing algorithm
+        * @param string $secretKeyMaterial
+        * @param string $algorithm Name of hashing algorithm
         * @param BagOStuff $cache
-        * @param string|array $context to mix into HKDF context
+        * @param string|array $context Context to mix into HKDF context
         */
        public function __construct( $secretKeyMaterial, $algorithm, $cache, $context ) {
                if ( strlen( $secretKeyMaterial ) < 16 ) {
@@ -133,7 +134,7 @@ class MWCryptHKDF {
 
        /**
         * MW specific salt, cached from last run
-        * @return string binary string
+        * @return string Binary string
         */
        protected function getSaltUsingCache() {
                if ( $this->salt == '' ) {
@@ -189,9 +190,9 @@ class MWCryptHKDF {
        /**
         * Produce $bytes of secure random data. As a side-effect,
         * $this->lastK is set to the last hashLen block of key material.
-        * @param int $bytes number of bytes of data
-        * @param string $context to mix into CTXinfo
-        * @return string binary string of length $bytes
+        * @param int $bytes Number of bytes of data
+        * @param string $context Context to mix into CTXinfo
+        * @return string Binary string of length $bytes
         */
        protected function realGenerate( $bytes, $context = '' ) {
 
@@ -237,13 +238,13 @@ class MWCryptHKDF {
         * N.B. http://eprint.iacr.org/2010/264.pdf seems to differ from RFC 5869 in that the test
         * vectors from RFC 5869 only work if K(0) = '' and K(1) = HMAC(PRK, K(0) || CTXinfo || 1)
         *
-        * @param string $hash the hashing function to use (e.g., sha256)
-        * @param string $ikm the input keying material
-        * @param string $salt the salt to add to the ikm, to get the prk
-        * @param string $info optional context (change the output without affecting
+        * @param string $hash The hashing function to use (e.g., sha256)
+        * @param string $ikm The input keying material
+        * @param string $salt The salt to add to the ikm, to get the prk
+        * @param string $info Optional context (change the output without affecting
         *      the randomness properties of the output)
-        * @param integer $L number of bytes to return
-        * @return string cryptographically secure pseudorandom binary string
+        * @param int $L Number of bytes to return
+        * @return string Cryptographically secure pseudorandom binary string
         */
        public static function HKDF( $hash, $ikm, $salt, $info, $L ) {
                $prk = self::HKDFExtract( $hash, $salt, $ikm );
@@ -256,10 +257,10 @@ class MWCryptHKDF {
         * Note that the hmac is keyed with XTS (the salt),
         * and the SKM (source key material) is the "data".
         *
-        * @param string $hash the hashing function to use (e.g., sha256)
-        * @param string $ikm the input keying material
-        * @param string $salt the salt to add to the ikm, to get the prk
-        * @return string binary string (pseudorandm key) used as input to HKDFExpand
+        * @param string $hash The hashing function to use (e.g., sha256)
+        * @param string $salt The salt to add to the ikm, to get the prk
+        * @param string $ikm The input keying material
+        * @return string Binary string (pseudorandm key) used as input to HKDFExpand
         */
        private static function HKDFExtract( $hash, $salt, $ikm ) {
                return hash_hmac( $hash, $ikm, $salt, true );
@@ -268,16 +269,16 @@ class MWCryptHKDF {
        /**
         * Expand the key with the given context
         *
-        * @param $hash Hashing Algorithm
-        * @param $prk a pseudorandom key of at least HashLen octets
-         *     (usually, the output from the extract step)
-        * @param $info optional context and application specific information
-         *     (can be a zero-length string)
-        * @param $bytes length of output keying material in bytes
-         *     (<= 255*HashLen)
-        * @param &$lastK set by this function to the last block of the expansion.
+        * @param string $hash Hashing Algorithm
+        * @param string $prk A pseudorandom key of at least HashLen octets
+             (usually, the output from the extract step)
+        * @param string $info Optional context and application specific information
+             (can be a zero-length string)
+        * @param int $bytes Length of output keying material in bytes
+             (<= 255*HashLen)
+        * @param string &$lastK Set by this function to the last block of the expansion.
         *      In MediaWiki, this is used to seed future Extractions.
-        * @return string cryptographically secure random string $bytes long
+        * @return string Cryptographically secure random string $bytes long
         */
        private static function HKDFExpand( $hash, $prk, $info, $bytes, &$lastK = '' ) {
                $hashLen = MWCryptHKDF::$hashLength[$hash];
@@ -293,7 +294,7 @@ class MWCryptHKDF {
                for ( $counter = 1; $counter <= $rounds; ++$counter ) {
                        $lastK = hash_hmac(
                                $hash,
-                               $lastK . $info . chr($counter),
+                               $lastK . $info . chr( $counter ),
                                $prk,
                                true
                        );
@@ -306,9 +307,9 @@ class MWCryptHKDF {
        /**
         * Generate cryptographically random data and return it in raw binary form.
         *
-        * @param int $bytes the number of bytes of random data to generate
-        * @param string $context string to mix into HMAC context
-        * @return string binary string of length $bytes
+        * @param int $bytes The number of bytes of random data to generate
+        * @param string $context String to mix into HMAC context
+        * @return string Binary string of length $bytes
         */
        public static function generate( $bytes, $context ) {
                return self::singleton()->realGenerate( $bytes, $context );
@@ -318,9 +319,9 @@ class MWCryptHKDF {
         * Generate cryptographically random data and return it in hexadecimal string format.
         * See MWCryptRand::realGenerateHex for details of the char-to-byte conversion logic.
         *
-        * @param int $chars the number of hex chars of random data to generate
-        * @param string $context string to mix into HMAC context
-        * @return string random hex characters, $chars long
+        * @param int $chars The number of hex chars of random data to generate
+        * @param string $context String to mix into HMAC context
+        * @return string Random hex characters, $chars long
         */
        public static function generateHex( $chars, $context = '' ) {
                $bytes = ceil( $chars / 2 );
index eb74d12..b602f78 100644 (file)
@@ -61,6 +61,7 @@ class MWCryptRand {
 
        /**
         * Initialize an initial random state based off of whatever we can find
+        * @return string
         */
        protected function initialRandomState() {
                // $_SERVER contains a variety of unstable user and system specific information
@@ -147,7 +148,7 @@ class MWCryptRand {
         * Randomly hash data while mixing in clock drift data for randomness
         *
         * @param string $data The data to randomly hash.
-        * @return String The hashed bytes
+        * @return string The hashed bytes
         * @author Tim Starling
         */
        protected function driftHash( $data ) {
@@ -214,7 +215,7 @@ class MWCryptRand {
        /**
         * Decide on the best acceptable hash algorithm we have available for hash()
         * @throws MWException
-        * @return String A hash algorithm
+        * @return string A hash algorithm
         */
        protected function hashAlgo() {
                if ( !is_null( $this->algo ) ) {
@@ -259,8 +260,8 @@ class MWCryptRand {
         * Generate an acceptably unstable one-way-hash of some text
         * making use of the best hash algorithm that we have available.
         *
-        * @param $data string
-        * @return String A raw hash of the data
+        * @param string $data
+        * @return string A raw hash of the data
         */
        protected function hash( $data ) {
                return hash( $this->hashAlgo(), $data, true );
@@ -270,9 +271,9 @@ class MWCryptRand {
         * Generate an acceptably unstable one-way-hmac of some text
         * making use of the best hash algorithm that we have available.
         *
-        * @param $data string
-        * @param $key string
-        * @return String A raw hash of the data
+        * @param string $data
+        * @param string $key
+        * @return string A raw hash of the data
         */
        protected function hmac( $data, $key ) {
                return hash_hmac( $this->hashAlgo(), $data, $key, true );
@@ -487,11 +488,11 @@ class MWCryptRand {
         * You can use MWCryptRand::wasStrong() if you wish to know if the source used
         * was cryptographically strong.
         *
-        * @param int $bytes the number of bytes of random data to generate
+        * @param int $bytes The number of bytes of random data to generate
         * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
         *                          strong sources of entropy even if reading from them may steal
         *                          more entropy from the system than optimal.
-        * @return String Raw binary random data
+        * @return string Raw binary random data
         */
        public static function generate( $bytes, $forceStrong = false ) {
                return self::singleton()->realGenerate( $bytes, $forceStrong );
@@ -503,11 +504,11 @@ class MWCryptRand {
         * You can use MWCryptRand::wasStrong() if you wish to know if the source used
         * was cryptographically strong.
         *
-        * @param int $chars the number of hex chars of random data to generate
+        * @param int $chars The number of hex chars of random data to generate
         * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
         *                          strong sources of entropy even if reading from them may steal
         *                          more entropy from the system than optimal.
-        * @return String Hexadecimal random data
+        * @return string Hexadecimal random data
         */
        public static function generateHex( $chars, $forceStrong = false ) {
                return self::singleton()->realGenerateHex( $chars, $forceStrong );
index 7105f6c..3a0492d 100644 (file)
@@ -24,7 +24,7 @@ class MWFunction {
 
        /**
         * @deprecated since 1.22; use call_user_func()
-        * @param $callback
+        * @param callable $callback
         * @return mixed
         */
        public static function call( $callback ) {
@@ -36,8 +36,8 @@ class MWFunction {
 
        /**
         * @deprecated since 1.22; use call_user_func_array()
-        * @param $callback
-        * @param $argsarams
+        * @param callable $callback
+        * @param array $argsarams
         * @return mixed
         */
        public static function callArray( $callback, $argsarams ) {
@@ -47,8 +47,8 @@ class MWFunction {
        }
 
        /**
-        * @param $class
-        * @param $args array
+        * @param string $class
+        * @param array $args
         * @return object
         */
        public static function newObj( $class, $args = array() ) {
index 9cd3d3f..86f4512 100644 (file)
@@ -42,11 +42,11 @@ class StringUtils {
         * Beware of this when backporting code to that version of MediaWiki.
         *
         * @param string $value String to check
-        * @param boolean $disableMbstring Whether to use the pure PHP
+        * @param bool $disableMbstring Whether to use the pure PHP
         * implementation instead of trying mb_check_encoding. Intended for unit
         * testing. Default: false
         *
-        * @return boolean Whether the given $value is a valid UTF-8 encoded string
+        * @return bool Whether the given $value is a valid UTF-8 encoded string
         */
        static function isUtf8( $value, $disableMbstring = false ) {
                $value = (string)$value;
@@ -121,10 +121,10 @@ class StringUtils {
         * hungry and inflexible. The memory requirements are such that I don't
         * recommend using it on anything but guaranteed small chunks of text.
         *
-        * @param $startDelim
-        * @param $endDelim
-        * @param $replace
-        * @param $subject
+        * @param string $startDelim
+        * @param string $endDelim
+        * @param string $replace
+        * @param string $subject
         *
         * @return string
         */
@@ -157,11 +157,11 @@ class StringUtils {
         * start, so e.g. /*\/ is not considered to be both the start and end of a
         * comment. /*\/xy/*\/ is considered to be a single comment with contents /xy/.
         *
-        * @param string $startDelim start delimiter
-        * @param string $endDelim end delimiter
-        * @param $callback Callback: function to call on each match
-        * @param $subject String
-        * @param string $flags regular expression flags
+        * @param string $startDelim Start delimiter
+        * @param string $endDelim End delimiter
+        * @param callable $callback Function to call on each match
+        * @param string $subject
+        * @param string $flags Regular expression flags
         * @throws MWException
         * @return string
         */
@@ -245,13 +245,13 @@ class StringUtils {
         *
         *   preg_replace( "!$startDelim(.*)$endDelim!$flags", $replace, $subject )
         *
-        * @param string $startDelim start delimiter regular expression
-        * @param string $endDelim end delimiter regular expression
-        * @param string $replace replacement string. May contain $1, which will be
+        * @param string $startDelim Start delimiter regular expression
+        * @param string $endDelim End delimiter regular expression
+        * @param string $replace Replacement string. May contain $1, which will be
         *                 replaced by the text between the delimiters
-        * @param string $subject to search
-        * @param string $flags regular expression flags
-        * @return String: The string with the matches replaced
+        * @param string $subject String to search
+        * @param string $flags Regular expression flags
+        * @return string The string with the matches replaced
         */
        static function delimiterReplace( $startDelim, $endDelim, $replace, $subject, $flags = '' ) {
                $replacer = new RegexlikeReplacer( $replace );
@@ -361,8 +361,8 @@ class RegexlikeReplacer extends Replacer {
  */
 class DoubleReplacer extends Replacer {
        /**
-        * @param $from
-        * @param $to
+        * @param mixed $from
+        * @param mixed $to
         * @param int $index
         */
        function __construct( $from, $to, $index = 0 ) {
@@ -387,7 +387,7 @@ class HashtableReplacer extends Replacer {
        private $table, $index;
 
        /**
-        * @param $table
+        * @param array $table
         * @param int $index
         */
        function __construct( $table, $index = 0 ) {
index 0ce90c1..5346afa 100644 (file)
@@ -37,7 +37,7 @@ class UIDGenerator {
        protected $lockFile88; // string; local file path
        protected $lockFile128; // string; local file path
 
-       /** @var Array */
+       /** @var array */
        protected $fileHandles = array(); // cache file handles
 
        const QUICK_RAND = 1; // get randomness from fast and insecure sources
@@ -102,7 +102,7 @@ class UIDGenerator {
         *
         * UID generation is serialized on each server (as the node ID is for the whole machine).
         *
-        * @param $base integer Specifies a base other than 10
+        * @param int $base Specifies a base other than 10
         * @return string Number
         * @throws MWException
         */
@@ -117,7 +117,7 @@ class UIDGenerator {
        }
 
        /**
-        * @param array $time (UIDGenerator::millitime(), clock sequence)
+        * @param array $info (UIDGenerator::millitime(), counter, clock sequence)
         * @return string 88 bits
         */
        protected function getTimestampedID88( array $info ) {
@@ -146,7 +146,7 @@ class UIDGenerator {
         *
         * UID generation is serialized on each server (as the node ID is for the whole machine).
         *
-        * @param $base integer Specifies a base other than 10
+        * @param int $base Specifies a base other than 10
         * @return string Number
         * @throws MWException
         */
@@ -185,7 +185,7 @@ class UIDGenerator {
        /**
         * Return an RFC4122 compliant v4 UUID
         *
-        * @param $flags integer Bitfield (supports UIDGenerator::QUICK_RAND)
+        * @param int $flags Bitfield (supports UIDGenerator::QUICK_RAND)
         * @return string
         * @throws MWException
         */
@@ -211,7 +211,7 @@ class UIDGenerator {
        /**
         * Return an RFC4122 compliant v4 UUID
         *
-        * @param $flags integer Bitfield (supports UIDGenerator::QUICK_RAND)
+        * @param int $flags Bitfield (supports UIDGenerator::QUICK_RAND)
         * @return string 32 hex characters with no hyphens
         * @throws MWException
         */
@@ -226,8 +226,8 @@ class UIDGenerator {
         * If UIDGenerator::QUICK_VOLATILE is used the counter might reset on server restart.
         *
         * @param string $bucket Arbitrary bucket name (should be ASCII)
-        * @param integer $bits Bit size (<=48) of resulting numbers before wrap-around
-        * @param integer $flags (supports UIDGenerator::QUICK_VOLATILE)
+        * @param int $bits Bit size (<=48) of resulting numbers before wrap-around
+        * @param int $flags (supports UIDGenerator::QUICK_VOLATILE)
         * @return float Integer value as float
         * @since 1.23
         */
@@ -240,9 +240,9 @@ class UIDGenerator {
         *
         * @see UIDGenerator::newSequentialPerNodeID()
         * @param string $bucket Arbitrary bucket name (should be ASCII)
-        * @param integer $bits Bit size (16 to 48) of resulting numbers before wrap-around
-        * @param integer $count Number of IDs to return (1 to 10000)
-        * @param integer $flags (supports UIDGenerator::QUICK_VOLATILE)
+        * @param int $bits Bit size (16 to 48) of resulting numbers before wrap-around
+        * @param int $count Number of IDs to return (1 to 10000)
+        * @param int $flags (supports UIDGenerator::QUICK_VOLATILE)
         * @return array Ordered list of float integer values
         * @since 1.23
         */
@@ -256,9 +256,9 @@ class UIDGenerator {
         *
         * @see UIDGenerator::newSequentialPerNodeID()
         * @param string $bucket Arbitrary bucket name (should be ASCII)
-        * @param integer $bits Bit size (16 to 48) of resulting numbers before wrap-around
-        * @param integer $count Number of IDs to return (1 to 10000)
-        * @param integer $flags (supports UIDGenerator::QUICK_VOLATILE)
+        * @param int $bits Bit size (16 to 48) of resulting numbers before wrap-around
+        * @param int $count Number of IDs to return (1 to 10000)
+        * @param int $flags (supports UIDGenerator::QUICK_VOLATILE)
         * @return array Ordered list of float integer values
         */
        protected function getSequentialPerNodeIDs( $bucket, $bits, $count, $flags ) {
@@ -337,9 +337,9 @@ class UIDGenerator {
         * This is useful for making UIDs sequential on a per-node bases.
         *
         * @param string $lockFile Name of a local lock file
-        * @param $clockSeqSize integer The number of possible clock sequence values
-        * @param $counterSize integer The number of possible counter values
-        * @return Array (result of UIDGenerator::millitime(), counter, clock sequence)
+        * @param int $clockSeqSize The number of possible clock sequence values
+        * @param int $counterSize The number of possible counter values
+        * @return array (result of UIDGenerator::millitime(), counter, clock sequence)
         * @throws MWException
         */
        protected function getTimestampAndDelay( $lockFile, $clockSeqSize, $counterSize ) {
@@ -420,7 +420,7 @@ class UIDGenerator {
         * timestamp. This returns false if it would have to wait more than 10ms.
         *
         * @param array $time Result of UIDGenerator::millitime()
-        * @return Array|bool UIDGenerator::millitime() result or false
+        * @return array|bool UIDGenerator::millitime() result or false
         */
        protected function timeWaitUntil( array $time ) {
                do {
@@ -449,7 +449,7 @@ class UIDGenerator {
        }
 
        /**
-        * @return Array (current time in seconds, milliseconds since then)
+        * @return array (current time in seconds, milliseconds since then)
         */
        protected static function millitime() {
                list( $msec, $sec ) = explode( ' ', microtime() );
index 6be186f..bc84976 100644 (file)
@@ -64,7 +64,7 @@ class ZipDirectoryReader {
         *        valid ZIP64 file, and working out what non-ZIP64 readers will make
         *        of such a file is not trivial.
         *
-        * @return Status object. The following fatal errors are defined:
+        * @return Status A Status object. The following fatal errors are defined:
         *
         *      - zip-file-open-error: The file could not be opened.
         *
@@ -129,6 +129,9 @@ class ZipDirectoryReader {
 
        /**
         * Private constructor
+        * @param string $fileName
+        * @param callable $callback
+        * @param array $options
         */
        protected function __construct( $fileName, $callback, $options ) {
                $this->fileName = $fileName;
@@ -181,6 +184,8 @@ class ZipDirectoryReader {
 
        /**
         * Throw an error, and log a debug message
+        * @param mixed $code
+        * @param string $debugMessage
         */
        function error( $code, $debugMessage ) {
                wfDebug( __CLASS__ . ": Fatal error: $debugMessage\n" );
@@ -299,7 +304,7 @@ class ZipDirectoryReader {
         * Find the location of the central directory, as would be seen by a
         * non-ZIP64 reader.
         *
-        * @return List containing offset, size and end position.
+        * @return array List containing offset, size and end position.
         */
        function findOldCentralDirectory() {
                $size = $this->eocdr['CD size'];
@@ -357,6 +362,8 @@ class ZipDirectoryReader {
 
        /**
         * Read the central directory at the given location
+        * @param int $offset
+        * @param int $size
         */
        function readCentralDirectory( $offset, $size ) {
                $block = $this->getBlock( $offset, $size );
@@ -430,9 +437,7 @@ class ZipDirectoryReader {
                                $year, $month, $day, $hour, $minute, $second );
 
                        // Convert the character set in the file name
-                       if ( !function_exists( 'iconv' )
-                               || $this->testBit( $data['general bits'], self::GENERAL_UTF8 )
-                       ) {
+                       if ( $this->testBit( $data['general bits'], self::GENERAL_UTF8 ) ) {
                                $name = $data['name'];
                        } else {
                                $name = iconv( 'CP437', 'UTF-8', $data['name'] );
@@ -450,6 +455,7 @@ class ZipDirectoryReader {
 
        /**
         * Interpret ZIP64 "extra field" data and return an associative array.
+        * @param string $extraField
         * @return array|bool
         */
        function unpackZip64Extra( $extraField ) {
@@ -485,6 +491,7 @@ class ZipDirectoryReader {
 
        /**
         * Get the length of the file.
+        * @return int
         */
        function getFileLength() {
                if ( $this->fileLength === null ) {
@@ -574,6 +581,7 @@ class ZipDirectoryReader {
 
        /**
         * Get the size of a structure in bytes. See unpack() for the format of $struct.
+        * @param array $struct
         * @return int
         */
        function getStructSize( $struct ) {
@@ -661,7 +669,7 @@ class ZipDirectoryReader {
         * Returns a bit from a given position in an integer value, converted to
         * boolean.
         *
-        * @param $value integer
+        * @param int $value
         * @param int $bitIndex The index of the bit, where 0 is the LSB.
         * @return bool
         */
@@ -671,6 +679,7 @@ class ZipDirectoryReader {
 
        /**
         * Debugging helper function which dumps a string in hexdump -C format.
+        * @param string $s
         */
        function hexDump( $s ) {
                $n = strlen( $s );
index bc46111..b35967b 100644 (file)
--- a/index.php
+++ b/index.php
@@ -34,7 +34,7 @@
 # has structures (try/catch, foo()->bar(), etc etc) which throw parse errors in
 # PHP 4. Setup.php and ObjectCache.php have structures invalid in PHP 5.0 and
 # 5.1, respectively.
-if ( !function_exists( 'version_compare' ) || version_compare( phpversion(), '5.3.2' ) < 0 ) {
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
        // We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
        require dirname( __FILE__ ) . '/includes/PHPVersionError.php';
        wfPHPVersionError( 'index.php' );
index bf30455..115a918 100644 (file)
@@ -339,13 +339,13 @@ class Language {
                        throw new MWException( __METHOD__ . " must be passed a string, $type given$addmsg" );
                }
 
-               return (bool)preg_match( '/^[a-z0-9-]{2,}$/i', $code );
+               return (bool)preg_match( '/^[a-z0-9-]{2,}$/', $code );
        }
 
        /**
         * Returns true if a language code is an IETF tag known to MediaWiki.
         *
-        * @param string $code
+        * @param string $tag
         *
         * @since 1.21
         * @return bool
@@ -443,17 +443,6 @@ class Language {
        function initContLang() {
        }
 
-       /**
-        * Same as getFallbacksFor for current language.
-        * @return array|bool
-        * @deprecated since 1.19
-        */
-       function getFallbackLanguageCode() {
-               wfDeprecated( __METHOD__, '1.19' );
-
-               return self::getFallbackFor( $this->mCode );
-       }
-
        /**
         * @return array
         * @since 1.19
@@ -795,6 +784,14 @@ class Language {
                return self::$dataCache->getSubitem( $this->mCode, 'imageFiles', $image );
        }
 
+       /**
+        * @return array
+        * @since 1.24
+        */
+       function getImageFiles() {
+               return self::$dataCache->getItem( $this->mCode, 'imageFiles' );
+       }
+
        /**
         * @return array
         */
@@ -857,6 +854,11 @@ class Language {
                        include "$IP/languages/Names.php";
                }
 
+               // If passed an invalid language code to use, fallback to en
+               if ( $inLanguage !== null && !Language::isValidCode( $inLanguage ) ) {
+                       $inLanguage = 'en';
+               }
+
                $names = array();
 
                if ( $inLanguage ) {
@@ -1032,6 +1034,11 @@ class Language {
 
        /**
         * Pass through result from $dateTimeObj->format()
+        * @param DateTime|bool|null &$dateTimeObj
+        * @param string $ts
+        * @param DateTimeZone|bool|null $zone
+        * @param string $code
+        * @return string
         */
        private static function dateTimeObjFormat( &$dateTimeObj, $ts, $zone, $code ) {
                if ( !$dateTimeObj ) {
@@ -2357,7 +2364,7 @@ class Language {
         * Get the formatted date and time for the given timestamp and formatted for
         * the given user.
         *
-        * @param mixed $ts the time format which needs to be turned into a
+        * @param mixed $ts The time format which needs to be turned into a
         *   date('YmdHis') format with wfTimestamp(TS_MW,$ts)
         * @param User $user User object used to get preferences for timezone and format
         * @param array $options Array, can contain the following keys:
@@ -2402,7 +2409,7 @@ class Language {
                        // Timestamps are in different years: use full timestamp
                        // Also do full timestamp for future dates
                        /**
-                        * @FIXME Add better handling of future timestamps.
+                        * @todo FIXME: Add better handling of future timestamps.
                         */
                        $format = $this->getDateFormatString( 'both', $user->getDatePreference() ?: 'default' );
                        $ts = $this->sprintfDate( $format, $ts->getTimestamp( TS_MW ) );
@@ -3131,7 +3138,7 @@ class Language {
         */
        function getMagic( $mw ) {
                // Saves a function call
-               if ( ! $this->mMagicHookDone ) {
+               if ( !$this->mMagicHookDone ) {
                        $this->doMagicHook();
                }
 
@@ -3143,7 +3150,7 @@ class Language {
                }
 
                if ( !is_array( $rawEntry ) ) {
-                       error_log( "\"$rawEntry\" is not a valid magic word for \"$mw->mId\"" );
+                       wfWarn( "\"$rawEntry\" is not a valid magic word for \"$mw->mId\"" );
                } else {
                        $mw->mCaseSensitive = $rawEntry[0];
                        $mw->mSynonyms = array_slice( $rawEntry, 1 );
@@ -3792,8 +3799,8 @@ class Language {
         *
         * @since 1.23
         *
-        * @param int $count non-localized number
-        * @param array $forms different plural forms
+        * @param int $count Non-localized number
+        * @param array $forms Different plural forms
         *
         * @return array|string
         */
@@ -3801,7 +3808,7 @@ class Language {
                foreach ( $forms as $index => $form ) {
                        if ( preg_match( '/\d+=/i', $form ) ) {
                                $pos = strpos( $form, '=' );
-                               if ( substr( $form, 0, $pos ) === (string) $count ) {
+                               if ( substr( $form, 0, $pos ) === (string)$count ) {
                                        return substr( $form, $pos + 1 );
                                }
                                unset( $forms[$index] );
@@ -3814,8 +3821,8 @@ class Language {
         * Checks that convertPlural was given an array and pads it to requested
         * amount of forms by copying the last one.
         *
-        * @param int $count How many forms should there be at least
         * @param array $forms Array of forms given to convertPlural
+        * @param int $count How many forms should there be at least
         * @return array Padded array of forms or an exception if not an array
         */
        protected function preConvertPlural( /* Array */ $forms, $count ) {
@@ -3998,7 +4005,7 @@ class Language {
         * Get the list of variants supported by this language
         * see sample implementation in LanguageZh.php
         *
-        * @return array an array of language codes
+        * @return array An array of language codes
         */
        public function getVariants() {
                return $this->mConverter->getVariants();
@@ -4030,12 +4037,12 @@ class Language {
         * possible that non-existing link in one variant
         * actually exists in another variant. this function
         * tries to find it. See e.g. LanguageZh.php
+        * The input parameters may be modified upon return
         *
-        * @param string $link The name of the link
-        * @param Title $nt The title object of the link
+        * @param string &$link The name of the link
+        * @param Title &$nt The title object of the link
         * @param bool $ignoreOtherCond To disable other conditions when
         *   we need to transclude a template or update a category's link
-        * @return null the input parameters may be modified upon return
         */
        public function findVariantLink( &$link, &$nt, $ignoreOtherCond = false ) {
                $this->mConverter->findVariantLink( $link, $nt, $ignoreOtherCond );
@@ -4290,7 +4297,7 @@ class Language {
         *
         * @since 1.22
         * @param string $code Language code
-        * @return array array( fallbacks, site fallbacks )
+        * @return array Array( fallbacks, site fallbacks )
         */
        public static function getFallbacksIncludingSiteLanguage( $code ) {
                global $wgLanguageCode;
@@ -4345,7 +4352,7 @@ class Language {
         *
         * @since 1.19
         * @param string $code Language code
-        * @return array of message keys (strings)
+        * @return array Array of message keys (strings)
         */
        public static function getMessageKeysFor( $code ) {
                return self::getLocalisationCache()->getSubItemList( $code, 'messages' );
@@ -4449,7 +4456,7 @@ class Language {
                if ( !isset( $format['avoid'] ) ) {
                        $format['avoid'] = false;
                }
-               if ( !isset( $format['noabbrevs' ] ) ) {
+               if ( !isset( $format['noabbrevs'] ) ) {
                        $format['noabbrevs'] = false;
                }
                $secondsMsg = wfMessage(
@@ -4617,7 +4624,7 @@ class Language {
         * @param Title $title Title object to link
         * @param int $offset
         * @param int $limit
-        * @param array|string $query Optional URL query parameter string
+        * @param array $query Optional URL query parameter string
         * @param bool $atend Optional param for specified if this is the last page
         * @return string
         */
@@ -4746,6 +4753,7 @@ class Language {
 
        /**
         * Find the index number of the plural rule appropriate for the given number
+        * @param int $number
         * @return int The index number of the plural rule
         */
        public function getPluralRuleIndexNumber( $number ) {
@@ -4759,6 +4767,7 @@ class Language {
         * For example, if the language is set to Arabic, getPluralType(5) should
         * return 'few'.
         * @since 1.22
+        * @param int $number
         * @return string The name of the plural rule type, e.g. one, two, few, many
         */
        public function getPluralRuleType( $number ) {
index b3a4c1a..eae77fb 100644 (file)
@@ -54,7 +54,7 @@ class LanguageConverter {
        public $mManualLevel;
 
        /**
-        * @var string memcached key name
+        * @var string Memcached key name
         */
        public $mCacheKey;
 
@@ -737,12 +737,12 @@ class LanguageConverter {
         * If a language supports multiple variants, it is possible that
         * non-existing link in one variant actually exists in another variant.
         * This function tries to find it. See e.g. LanguageZh.php
+        * The input parameters may be modified upon return
         *
-        * @param string $link The name of the link
-        * @param mixed $nt The title object of the link
+        * @param string &$link The name of the link
+        * @param Title &$nt The title object of the link
         * @param bool $ignoreOtherCond To disable other conditions when
         *   we need to transclude a template or update a category's link
-        * @return void Null, the input parameters may be modified upon return
         */
        public function findVariantLink( &$link, &$nt, $ignoreOtherCond = false ) {
                # If the article has already existed, there is no need to
@@ -1102,6 +1102,7 @@ class LanguageConverter {
 
        /**
         * Get the cached separator pattern for ConverterRule::parseRules()
+        * @return string
         */
        function getVarSeparatorPattern() {
                if ( is_null( $this->mVarSeparatorPattern ) ) {
index c9e75e0..9004676 100644 (file)
@@ -33,7 +33,7 @@
  * Some writing systems require some line-height fixes. This includes
  * most Indic scripts, like Devanagari.
  * If you are adding support for such a language, add it also to
- * the relevant section in skins/common/shared.css.
+ * the relevant section in shared.css.
  *
  * @ingroup Language
  */
@@ -52,7 +52,7 @@
        'ar' => 'العربية',       # Arabic
        'arc' => 'ܐܪܡܝܐ',  # Aramaic
        'arn' => 'mapudungun',  # Mapuche, Mapudungu, Araucanian (Araucano)
-       'arq' => 'جزائرÙ\8a', # Algerian Spoken Arabic
+       'arq' => 'جازاÙ\8aرÙ\8aØ©', # Algerian Spoken Arabic
        'ary' => 'Maġribi',    # Moroccan Spoken Arabic
        'arz' => 'مصرى',    # Egyptian Spoken Arabic
        'as' => 'অসমীয়া',        # Assamese
        'tw' => 'Twi',                  # Twi, (FIXME!)
        'ty' => 'reo tahiti',   # Tahitian
        'tyv' => 'тыва дыл',     # Tyvan
+       'tzm' => 'ⵜⴰⵎⴰⵣⵉⵖⵜ',    # Tamazight
        'udm' => 'удмурт',        # Udmurt
        'ug' => 'ئۇيغۇرچە / Uyghurche', # Uyghur (multiple scripts - defaults to Arabic)
        'ug-arab' => 'ئۇيغۇرچە', # Uyghur (Arabic script) (default)
index 4c956f0..db3a22c 100644 (file)
@@ -142,8 +142,8 @@ class IuConverter extends LanguageConverter {
         *     names as they were
         *   - do not try to find variants for usernames
         *
-        * @param string $link
-        * @param Title $nt
+        * @param string &$link
+        * @param Title &$nt
         * @param bool $ignoreOtherCond
         */
        function findVariantLink( &$link, &$nt, $ignoreOtherCond = false ) {
@@ -162,26 +162,6 @@ class IuConverter extends LanguageConverter {
                }
        }
 
-       /**
-        * An ugly function wrapper for parsing Image titles
-        * (to prevent image name conversion)
-        *
-        * @param string $text
-        * @param bool $toVariant
-        *
-        * @return string
-        */
-       function autoConvert( $text, $toVariant = false ) {
-               global $wgTitle;
-               if ( is_object( $wgTitle ) && $wgTitle->getNamespace() == NS_FILE ) {
-                       $imagename = $wgTitle->getNsText();
-                       if ( preg_match( "/^$imagename:/", $text ) ) {
-                               return $text;
-                       }
-               }
-               return parent::autoConvert( $text, $toVariant );
-       }
-
        /**
         * It translates text into variant
         *
index 1ab3c51..1a09818 100644 (file)
@@ -250,8 +250,8 @@ class KkConverter extends LanguageConverter {
         *    names as they were
         *  - do not try to find variants for usernames
         *
-        * @param string $link
-        * @param Title $nt
+        * @param string &$link
+        * @param Title &$nt
         * @param bool $ignoreOtherCond
         */
        function findVariantLink( &$link, &$nt, $ignoreOtherCond = false ) {
@@ -270,26 +270,6 @@ class KkConverter extends LanguageConverter {
                }
        }
 
-       /**
-        * An ugly function wrapper for parsing Image titles
-        * (to prevent image name conversion)
-        *
-        * @param string $text
-        * @param bool $toVariant
-        *
-        * @return string
-        */
-       function autoConvert( $text, $toVariant = false ) {
-               global $wgTitle;
-               if ( is_object( $wgTitle ) && $wgTitle->getNamespace() == NS_FILE ) {
-                       $imagename = $wgTitle->getNsText();
-                       if ( preg_match( "/^$imagename:/", $text ) ) {
-                               return $text;
-                       }
-               }
-               return parent::autoConvert( $text, $toVariant );
-       }
-
        /**
         *  It translates text into variant
         *
index 674e717..1fdebc2 100644 (file)
@@ -160,8 +160,8 @@ class KuConverter extends LanguageConverter {
         *     names as they were
         *   - do not try to find variants for usernames
         *
-        * @param string $link
-        * @param Title $nt
+        * @param string &$link
+        * @param Title &$nt
         * @param bool $ignoreOtherCond
         */
        function findVariantLink( &$link, &$nt, $ignoreOtherCond = false ) {
@@ -180,26 +180,6 @@ class KuConverter extends LanguageConverter {
                }
        }
 
-       /**
-        * An ugly function wrapper for parsing Image titles
-        * (to prevent image name conversion)
-        *
-        * @param string $text
-        * @param bool $toVariant
-        *
-        * @return string
-        */
-       function autoConvert( $text, $toVariant = false ) {
-               global $wgTitle;
-               if ( is_object( $wgTitle ) && $wgTitle->getNamespace() == NS_FILE ) {
-                       $imagename = $wgTitle->getNsText();
-                       if ( preg_match( "/^$imagename:/", $text ) ) {
-                               return $text;
-                       }
-               }
-               return parent::autoConvert( $text, $toVariant );
-       }
-
        /**
         *  It translates text into variant, specials:
         *    - ommiting roman numbers
index 68e047c..105a3af 100644 (file)
@@ -118,8 +118,8 @@ class ShiConverter extends LanguageConverter {
         *     names as they were
         *   - do not try to find variants for usernames
         *
-        * @param string $link
-        * @param Title $nt
+        * @param string &$link
+        * @param Title &$nt
         * @param bool $ignoreOtherCond
         */
        function findVariantLink( &$link, &$nt, $ignoreOtherCond = false ) {
@@ -138,26 +138,6 @@ class ShiConverter extends LanguageConverter {
                }
        }
 
-       /**
-        * An ugly function wrapper for parsing Image titles
-        * (to prevent image name conversion)
-        *
-        * @param string $text
-        * @param bool $toVariant
-        *
-        * @return string
-        */
-       function autoConvert( $text, $toVariant = false ) {
-               global $wgTitle;
-               if ( is_object( $wgTitle ) && $wgTitle->getNamespace() == NS_FILE ) {
-                       $imagename = $wgTitle->getNsText();
-                       if ( preg_match( "/^$imagename:/", $text ) ) {
-                               return $text;
-                       }
-               }
-               return parent::autoConvert( $text, $toVariant );
-       }
-
        /**
         * It translates text into variant
         *
index d0c4e06..bdf1ec4 100644 (file)
@@ -108,8 +108,8 @@ class SrConverter extends LanguageConverter {
         *     names as they were
         *   - do not try to find variants for usernames
         *
-        * @param string $link
-        * @param Title $nt
+        * @param string &$link
+        * @param Title &$nt
         * @param bool $ignoreOtherCond
         */
        function findVariantLink( &$link, &$nt, $ignoreOtherCond = false ) {
@@ -128,26 +128,6 @@ class SrConverter extends LanguageConverter {
                }
        }
 
-       /**
-        * An ugly function wrapper for parsing Image titles
-        * (to prevent image name conversion)
-        *
-        * @param string $text
-        * @param bool $toVariant
-        *
-        * @return string
-        */
-       function autoConvert( $text, $toVariant = false ) {
-               global $wgTitle;
-               if ( is_object( $wgTitle ) && $wgTitle->getNamespace() == NS_FILE ) {
-                       $imagename = $wgTitle->getNsText();
-                       if ( preg_match( "/^$imagename:/", $text ) ) {
-                               return $text;
-                       }
-               }
-               return parent::autoConvert( $text, $toVariant );
-       }
-
        /**
         *  It translates text into variant, specials:
         *    - ommiting roman numbers
index dfdc6b1..67f8769 100644 (file)
@@ -166,7 +166,7 @@ class LanguageZh extends LanguageZh_hans {
         * auto convert to zh-hans and normalize special characters.
         *
         * @param string $string
-        * @param string $autoVariant default to 'zh-hans'
+        * @param string $autoVariant Defaults to 'zh-hans'
         * @return string
         */
        function normalizeForSearch( $string, $autoVariant = 'zh-hans' ) {
index 545f19a..f9e54ae 100644 (file)
        "talkpagelinktext": "Marit",
        "specialpage": "Laman kusuih",
        "personaltools": "Peukakaih droë",
-       "postcomment": "Beunagi barô",
        "articlepage": "Eu asoë laman",
        "talk": "Marit",
        "views": "Seuneudeuih",
        "externaldberror": "Na seunalah bak peusahèh basis data luwa atawa droëneuh hana geubri idin keu neupeubarô akun luwa droëneuh",
        "login": "Tamöng",
        "nav-login-createaccount": "Tamöng / dapeuta",
-       "loginprompt": "Droëneuh suwah/payah neupeu’udép ''cookies'' mangat jeuët neutamong u {{SITENAME}}",
        "userlogin": "Tamöng / dapeuta",
        "userloginnocreate": "Tamöng",
        "logout": "Teubiët",
        "filetype-banned": "Jeunèh beureukaih nyoe geutheun.",
        "illegal-filename": "Nan beureukaih han jeut lagèe nyoe.",
        "savefile": "Kubah beureukaih",
-       "uploadedimage": "peutamöng \"[[$1]]\"",
-       "overwroteimage": "peutamöng vèrsi barô \"[[$1]]\"",
        "upload-source": "Asai beureukaih",
        "sourcefilename": "Asai nan beureukaih:",
        "sourceurl": "Asai URL:",
index bae51c9..32b7b8c 100644 (file)
        "talkpagelinktext": "Ħdith",
        "specialpage": "صفحة خاصة",
        "personaltools": "Outils mteεek",
-       "postcomment": "قسم جديد",
        "articlepage": "عرض صفحة المحتوى",
        "talk": "Ħdith",
        "views": "Affichages",
        "externaldberror": "هناك إما خطأ في دخول قاعدة البيانات الخارجية أو أنه غير مسموح لك بتحديث حسابك الخارجي.",
        "login": "ادخل",
        "nav-login-createaccount": "Connecti / aεmel compte",
-       "loginprompt": "يجب أن تكون الكوكيز لديك مفعلة لتسجل الدخول إلى {{SITENAME}}.",
        "userlogin": "ادخل / أنشئ حسابا",
        "userloginnocreate": "دخول",
        "logout": "اخرج",
        "upload": "Abεeth des fichiers l'esserveur",
        "uploadlogpage": "سجل الرفع",
        "filedesc": "ملخص:",
-       "uploadedimage": "رفع \"[[$1]]\"",
        "license": "ترخيص:",
        "license-header": "licence",
        "file-anchor-link": "milaf (Fichier)",
index c3e146a..3db54fb 100644 (file)
        "talkpagelinktext": "Besprekings",
        "specialpage": "Spesiale bladsy",
        "personaltools": "Persoonlike gereedskap",
-       "postcomment": "Nuwe opskrif",
        "articlepage": "Lees artikel",
        "talk": "Bespreking",
        "views": "Weergawes",
        "externaldberror": "'n Databasisfout het tydens aanmelding voorgekom of u het nie toestemming om u eksterne rekening op te dateer nie.",
        "login": "Meld aan",
        "nav-login-createaccount": "Meld aan / registreer",
-       "loginprompt": "U blaaier moet koekies toelaat om op {{SITENAME}} te kan aanmeld.",
        "userlogin": "Meld aan / registreer",
        "userloginnocreate": "Meld aan",
        "logout": "Teken uit",
        "searchprofile-advanced-tooltip": "Soek in spesifieke naamruimtes",
        "search-result-size": "$1 ({{PLURAL:$2|1 woord|$2 woorde}})",
        "search-result-category-size": "{{PLURAL:$1|1 kategorielid|$1 kategorielede}} ({{PLURAL:$2|1 subkategorie|$2 subkategorieë}}, {{PLURAL:$3|1 lêer|$3 lêers}})",
-       "search-result-score": "Relevansie: $1%",
        "search-redirect": "(aanstuur $1)",
        "search-section": "(afdeling $1)",
        "search-suggest": "Het u $1 bedoel?",
        "powersearch-togglelabel": "Kies:",
        "powersearch-toggleall": "Alle",
        "powersearch-togglenone": "Geen",
+       "powersearch-remember": "Onthou keuse vir toekomstige soekopdragte",
        "search-external": "Eksterne soektog",
        "searchdisabled": "{{SITENAME}} se soekfunksie is tans afgeskakel ter wille van werkverrigting. Gebruik gerus intussen Google of Yahoo! Let daarop dat hulle indekse van die {{SITENAME}}-inhoud verouderd mag wees.",
        "search-error": "'n Fout het tydens die soektog voorgekom: $1",
        "preferences": "Voorkeure",
        "mypreferences": "Voorkeure",
        "prefs-edits": "Aantal wysigings:",
+       "prefsnologintext2": "U moet $1 om voorkeure te stel.",
        "prefs-skin": "Omslag",
        "skin-preview": "Voorskou",
        "datedefault": "Geen voorkeur",
        "uploadwarning": "Laaiwaarskuwing",
        "uploadwarning-text": "Verander die onderstaande lêerbeskrywing en probeer dan weer.",
        "savefile": "Stoor lêer",
-       "uploadedimage": "het \"[[$1]]\" gelaai",
-       "overwroteimage": "het 'n nuwe weergawe van \"[[$1]]\" opgelaai",
        "uploaddisabled": "Die oplaai van lêers is afgeskakel.",
        "copyuploaddisabled": "Die oplaai van lêers per URL is afgeskakel.",
        "uploaddisabledtext": "Die oplaai van lêers is afgeskakel.",
        "license-nopreview": "(Voorskou nie beskikbaar)",
        "upload_source_url": " ('n geldige, publiek toeganklike URL)",
        "upload_source_file": " ('n lêer op u rekenaar)",
+       "listfiles-delete": "skrap",
        "listfiles-summary": "Hierdie spesiale bladsy wys al die opgelaaide lêers.\nDie nuutste lêers word heel bo vertoon.\nKliek op die opskrifte om die tabel te hersorteer.",
        "listfiles_search_for": "Soek vir medianaam:",
        "imgfile": "lêer",
        "download": "laai af",
        "unwatchedpages": "Bladsye wat nie dopgehou word nie",
        "listredirects": "Lys aansture",
+       "listduplicatedfiles": "Lys van leërs met duplikate",
+       "listduplicatedfiles-entry": "[[:File:$1|$1]] het [[$3|{{PLURAL:$2|'n duplikaat|$2 duplikate}}]].",
        "unusedtemplates": "Ongebruikte sjablone",
        "unusedtemplatestext": "Hierdie blad lys alle bladsye in die {{ns:template}}-naamruimte wat nêrens in 'n ander blad ingesluit word nie. Onthou om ook ander skakels na die sjablone na te gaan voor verwydering.",
        "unusedtemplateswlh": "ander skakels",
        "watchlist-details": "{{PLURAL:$1|$1 bladsy|$1 bladsye}} in u dophoulys, besprekingsbladsye uitgesluit.",
        "wlheader-enotif": "E-pos kennisgewings is aangeskakel.",
        "wlheader-showupdated": "Bladsye wat verander is sedert u hulle laas besoek het word in '''vetdruk''' uitgewys.",
+       "wlnote": "Hier volg die laaste {{PLURAL:$1|verandering|'''$1''' veranderings}} binne die laaste {{PLURAL:$2|uur|'''$2''' ure}}, soos vanaf $3 om $4.",
        "wlshowlast": "Wys afgelope $1 ure, $2 dae of $3",
        "watchlist-options": "Opsies vir dophoulys",
        "watching": "Plaas op dophoulys...",
        "autosumm-replace": "Vervang bladsyinhoud met '$1'",
        "autoredircomment": "Stuur aan na [[$1]]",
        "autosumm-new": "Nuwe bladsy geskep met '$1'",
+       "autosumm-newblank": "Leë bladsy geskep",
        "size-bytes": "$1 G",
        "size-kilobytes": "$1 KG",
        "size-megabytes": "$1 MG",
        "duplicate-defaultsort": "Waarskuwing: Die standaardsortering \"$2\" kry voorrang voor die sortering \"$1\".",
        "version": "Weergawe",
        "version-extensions": "Uitbreidings geïnstalleer",
+       "version-skins": "Omslae",
        "version-specialpages": "Spesiale bladsye",
        "version-parserhooks": "Ontlederhoeke",
        "version-variables": "Veranderlikes",
        "version-antispam": "Spam-voorkoming",
-       "version-skins": "Omslae",
        "version-other": "Ander",
        "version-mediahandlers": "Mediaverwerkers",
        "version-hooks": "Hoeke",
        "version-hook-name": "Hoek naam",
        "version-hook-subscribedby": "Gebruik deur",
        "version-version": "(Weergawe $1)",
+       "version-no-ext-name": "[geen naam]",
        "version-license": "MediaWiki se lisensie",
        "version-ext-license": "Lisensie",
        "version-ext-colheader-name": "Uitbreiding",
+       "version-skin-colheader-name": "Omslag",
        "version-ext-colheader-version": "Weergawe",
        "version-ext-colheader-license": "Lisensie",
        "version-ext-colheader-description": "Beskrywing",
        "expand_templates_remove_nowiki": "Onderdruk <nowiki> etikette in die resultaat",
        "expand_templates_generate_xml": "Wys XML-ontledingsboom",
        "expand_templates_generate_rawhtml": "Wys rou HTML",
-       "expand_templates_preview": "Voorskou"
+       "expand_templates_preview": "Voorskou",
+       "pagelang-name": "Bladsy",
+       "pagelang-language": "Taal",
+       "pagelang-select-lang": "Kies taal"
 }
index df26585..6399f44 100644 (file)
        "talkpagelinktext": "Bisedo",
        "specialpage": "Faqe speciale",
        "personaltools": "Vegla vetjake",
-       "postcomment": "Sekcion i ri",
        "articlepage": "Shiko artikullin",
        "talk": "Diskutimi",
        "views": "Paraqitje",
        "externaldberror": "Ose pat gabim në databazën e autentifikimit, ose nuk lejoheni me ndryshue llogarinë tuej të jashtme.",
        "login": "Kyçu",
        "nav-login-createaccount": "Kyçu / çel llogari",
-       "loginprompt": "Shfletuesi duhet me pranue keksa (cookies) për me mujtë me u kyçë në {{SITENAME}}.",
        "userlogin": "Kyçu / çel llogari",
        "userloginnocreate": "Kyçu",
        "logout": "Çkyçu",
        "searchprofile-everything-tooltip": "Kërko krejt përmbajtjen (përfshi edhe faqet e diskutimit)",
        "searchprofile-advanced-tooltip": "Kërkimi në hapësina",
        "search-result-size": "$1 ({{PLURAL:$2|1 fjalë|$2 fjalë}})",
-       "search-result-score": "Relevanca: $1%",
        "search-redirect": "(përcjellje $1)",
        "search-section": "(sekcioni $1)",
        "search-suggest": "Mos menduet: $1",
        "recentchangeslinked-to": "Trego ndryshimet në faqet që lidhen në këtë faqe",
        "upload": "Ngarkoni skeda",
        "uploadlogpage": "Regjistri i ngarkimeve",
-       "uploadedimage": "ngarkue \"[[$1]]\"",
        "file-anchor-link": "Figura",
        "filehist": "Historiku i dosjes",
        "filehist-help": "Kliko në datë/orë për me pa skedën si âsht dukë në atë kohë.",
index 20ad098..59808fc 100644 (file)
        "talkpagelinktext": "ውይይት",
        "specialpage": "ልዩ ገጽ",
        "personaltools": "የኔ መሣርያዎች",
-       "postcomment": "አስተያየት ለማቅረብ",
        "articlepage": "መጣጥፉን ለማየት",
        "talk": "ውይይት",
        "views": "ዕይታዎች",
        "externaldberror": "ወይም አፍአዊ የማረጋገጫ መረጃ-ቤት ስኅተት ነበረ፣ ወይም አፍአዊ አባልነትዎን ማሳደስ አልተፈቀዱም።",
        "login": "ለመግባት",
        "nav-login-createaccount": "መግቢያ",
-       "loginprompt": "(ወደ {{SITENAME}} በብዕር ስም ለመግባት በኮምፒዩተሮ ላይ ኩኪስ (cookies) እንዲቀመጡ መፍቀድ ይኖርቦታል።)",
        "userlogin": "ግባ / ተመዝገብ",
        "userloginnocreate": "ለመግባት",
        "logout": "ከብዕር ስምዎ ለመውጣት",
        "searchprofile-everything-tooltip": "ይዞታውን ሁሉ (ከነውይይት ገጾች) ለመፈለግ",
        "searchprofile-advanced-tooltip": "በልዩ ክፍለ-ዊኪዎች ለመፈለግ",
        "search-result-size": "$1 ({{PLURAL:$2|1 ቃል|$2 ቃላት}})",
-       "search-result-score": "ተገቢነት፦ $1%",
        "search-redirect": "(መምሪያ መንገድ $1)",
        "search-section": "(ክፍል $1)",
        "search-suggest": "ምናልባት $1 የፈለጉት ይሆን",
        "recentchanges": "በቅርብ ጊዜ የተለወጡ",
        "recentchanges-legend": "የቅርብ ለውጥ አማራጮች፦",
        "recentchanges-summary": "በዚሁ ገጽ ላይ በቅርብ ጊዜ የወጡ አዳዲስ ለውጦች ለመከታተል ይችላሉ።",
+       "recentchanges-noresult": "ለዚሁ ጥያቄ በተሰጠው ወቅት ውስጥ  አንዳችም ለውጥ አልነበረም።",
        "recentchanges-feed-description": "በዚህ ዊኪ ላይ በቅርብ ግዜ የተለወጠውን በዚሁ feed መከታተል ይችላሉ",
        "recentchanges-label-newpage": "ይኸው ለውጥ አዲስ ገጽ ፈጠረ።",
        "recentchanges-label-minor": "ይህ ለውጥ ጥቃቅን ነው።",
        "uploadwarning": "የመላክ ማስጠንቀቂያ",
        "uploadwarning-text": "እባክዎ፣ እታች ያለውን የፋይልን መግለጫ ቀይርና እንደገና ይሞክሩ።",
        "savefile": "ፋይሉ ለመቆጠብ",
-       "uploadedimage": "«[[$1]]» ላከ",
-       "overwroteimage": "የ«[[$1]]» አዲስ ዕትም ላከ",
        "uploaddisabled": "ፋይል መላክ አይቻልም",
        "uploaddisabledtext": "ፋይል መላክ በዚህ ዊኪ አይቻልም።",
        "uploadvirus": "ፋይሉ ቫይረስ አለበት! ዝርዝር፦ $1",
        "watchlist-details": "አሁን {{PLURAL:$1|$1 ገፅ|$1 ገፆች}} በምትከታተላቸው ገፆች ላይ አሉ (የውይይት ገፅ ሳይጨመር)።",
        "wlheader-enotif": "የ-ኢሜል ማስታወቂያ እንዲሠራ ተደርጓል።",
        "wlheader-showupdated": "መጨረሻ ከጎበኟቸው ጀምሮ የተቀየሩት ገጾች በ'''ጉልህ ፊደላት''' ይታያሉ",
+       "wlnote": "ባለፉት <b>$2</b> ሰዓቶች የተደረጉት $1 መጨረሻ ለውጦች እታች ይገኛሉ።",
        "wlshowlast": "ያለፉት $1 ሰዓት፤ $2 ቀን፤ $3 ይታዩ።",
        "watchlist-options": "የዝርዝሩ ምርጫዎች",
        "watching": "እየተጨመረ ነው...",
        "thumbnail_invalid_params": "ትክክለኛ ያልሆነ የናሙና ግቤት",
        "import": "ገጾች ከሌላ ዊኪ ለማስገባት",
        "importinterwiki": "ከሌላ ዊኪ ማስገባት",
-       "import-interwiki-source": "መነሻ ዊኪ/ገጽ:",
        "import-interwiki-history": "ለዚህ ገጽ የታሪክ ዕትሞች ሁሉ ለመቅዳት",
        "import-interwiki-submit": "ለማስገባት",
        "import-interwiki-namespace": "መድረሻ ክፍለ-ዊኪ:",
index d804ec0..bc94329 100644 (file)
        "talkpagelinktext": "Descutir",
        "specialpage": "Pachina Especial",
        "personaltools": "Ferramientas personals",
-       "postcomment": "Nueva sección",
        "articlepage": "Veyer l'articlo",
        "talk": "Discusión",
        "views": "Visualizacions",
        "externaldberror": "Bi habió una error d'autenticación externa d'a base de datos u bien no tiene premisos ta esviellar a suya cuenta externa.",
        "login": "Encetar sesión",
        "nav-login-createaccount": "Encetar una sesión / creyar cuenta",
-       "loginprompt": "Ta rechistrar-se en {{SITENAME}} ha d'activar as cookies en o navegador.",
        "userlogin": "Encetar una sesión / creyar cuenta",
        "userloginnocreate": "Encetar una sesión",
        "logout": "Salir d'a sesión",
        "searchprofile-advanced-tooltip": "Mirar en os siguients espacios de nombres",
        "search-result-size": "$1 ({{PLURAL:$2|1 parola|$2 parolas}})",
        "search-result-category-size": "{{PLURAL:$1|1 miembro|$1 miembros}} ({{PLURAL:$2|1 subcategoría|$2 subcategorías}}, {{PLURAL:$3|1 fichero|$3 fichers}})",
-       "search-result-score": "Relevancia: $1%",
        "search-redirect": "(endrecera dende $1)",
        "search-section": "(sección $1)",
        "search-suggest": "Quereba dicir $1?",
        "uploadwarning": "Alvertencia de carga de fichero",
        "uploadwarning-text": "Por favor, modifique a descripción d'o fichero d'abaixo y torne a intentar-lo.",
        "savefile": "Alzar fichero",
-       "uploadedimage": "«[[$1]]» cargato.",
-       "overwroteimage": "s'ha cargato una nueva versión de \"[[$1]]\"",
        "uploaddisabled": "A carga de fichers ye desactivata",
        "copyuploaddisabled": "Carga por URL desactivada.",
        "uploaddisabledtext": "A carga de fichers ye desactivata.",
        "watchlist-details": "{{PLURAL:$1|$1 pachina|$1 pachinas}} en a suya lista de seguimiento, sin contar-ie as pachinas de descusión.",
        "wlheader-enotif": "A notificación por correu electronico ye activata",
        "wlheader-showupdated": "Las pachinas cambiadas dende a suya zaguer vesita s'amuestran en '''negreta'''",
+       "wlnote": "Contino se i {{PLURAL:$1|amuestra o solo cambeo|amuestran os zaguers '''$1''' cambeos}} feitos en {{PLURAL:$2|a zaguer hora|as zagueras '''$2''' horas}}, o $3 a las $4.",
        "wlshowlast": "Amostrar as zagueras $1 horas, $2 días u $3",
        "watchlist-options": "Opcions d'a lista de seguimiento",
        "watching": "Cosirando...",
        "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",
+       "version-skins": "Aparencias",
        "version-specialpages": "Pachinas especials",
        "version-parserhooks": "Grifios d'o parser (parser hooks)",
        "version-variables": "Variables",
        "version-antispam": "Prevención de spam",
-       "version-skins": "Aparencias",
        "version-other": "Atros",
        "version-mediahandlers": "Maneyador de fichers multimedia",
        "version-hooks": "Grifios (Hooks)",
index e3ecd7d..c3bcbf6 100644 (file)
        "talkpagelinktext": "Mōtung",
        "specialpage": "Syndrig tramet",
        "personaltools": "Āgne tōlas",
-       "postcomment": "Nīwe dǣl",
        "articlepage": "Sēon innunge tramet",
        "talk": "Mōtung",
        "views": "Sihþa",
        "password-change-forbidden": "Þū ne canst awendan þafungword on þissum wiki.",
        "login": "Inmeldian",
        "nav-login-createaccount": "Inmeldian / wyrcan reccinge",
-       "loginprompt": "Þū scealt þafian cȳþþu grētunga tō inmeldienne in {{SITENAME}}.",
        "userlogin": "Inmeldian / wyrcan reccinge",
        "userloginnocreate": "Inmeldian",
        "logout": "Ūtmeldian",
        "filesource": "Fruma:",
        "badfilename": "Ymelan nama wearþ gewend tō \"$1\".",
        "savefile": "Hordian ymelan",
-       "uploadedimage": "forþhlōd \"[[$1]]\"",
        "sourcefilename": "Fruman ymelan nama:",
        "license": "Lēaf:",
        "license-header": "Lēaf:",
        "unwatch": "Ablinnan behealdunge",
        "unwatchthispage": "Ablinnan behealdunge",
        "watchlist-details": "{{PLURAL:$1|Þǣr is $1 tramet|Þǣr sind $1 trameta}} on þīnum behealdunggetæle, nā sunderlīce arīmedum mōtunga trametum.",
+       "wlnote": "Niðer {{PLURAL:$1|is sēo nīwoste andwendung|sind þā nīwostan '''$1''' andwendunga}} in {{PLURAL:$2|þǣre latostan tīde|þǣm latostan '''$2''' tīda}}, fram: $3, $4.",
        "wlshowlast": "Īwan þā nīwostan $1 tīda $2 daga $3",
        "watchlist-options": "Behealdungtæles cyras",
        "watching": "Behealdende...",
index 5fddefb..66d7617 100644 (file)
@@ -2,7 +2,8 @@
        "@metadata": {
                "authors": [
                        "Angpradesh",
-                       "Vinitutpal"
+                       "Vinitutpal",
+                       "아라"
                ]
        },
        "tog-underline": " कड़ी अधोरेखित करना:",
@@ -15,7 +16,6 @@
        "tog-showtoolbar": "एडिट टूलबार दर्शाबॊ (जावास्क्रीप्ट)",
        "tog-editondblclick": "दू-बार क्लीक करी कॆ पन्ना संपादित करॊ (जावास्क्रीप्ट)",
        "tog-editsectiononrightclick": "विभाग शीर्षक पर दायाँ क्लीक करीकॆ संपादन करै के अनुमती दॆ (जावास्क्रीप्ट)",
-       "tog-rememberpassword": "इ कंप्यूटर पर हमरॊ लॉग-इन सूचना याद रखॊ (अधिकतम $1 {{PLURAL:$1|दिन|दिन}} लेली)",
        "tog-watchcreations": "हमरॊ तैयार करलॊ पन्ना हमरॊ ध्यानसूचीमॆं रखियै",
        "tog-watchdefault": "हमरॊ संपादित करलॊ पन्ना हमरॊ ध्यानसूचीमॆं रखियै",
        "tog-watchmoves": "हमरॊ हटैलॊ पन्ना हमरॊ ध्यानसूचीमॆं रखियै",
        "search-interwiki-more": "(आरू)",
        "powersearch-legend": "उन्नत खोज",
        "powersearch-ns": "नामस्थानॊ मॆ खोजॊ:",
-       "powersearch-redir": "अनुप्रेषितॊ के सूची दर्शाबॊ.",
        "preferences": "वरीयता",
        "mypreferences": "हमरॊ वरीयता",
        "group-sysop": "प्रचालक",
        "recentchanges": "हाल मॆं होलॊ बदलाव",
        "recentchanges-legend": "हाल केरॊ परिवर्तन संबंधी विकल्प",
        "recentchanges-feed-description": "इ फ़ीड मॆ होय वाला विकि पर हाल मॆ होलॊ बदलाव देखियै.",
-       "rclistfrom": "$1 सॆं नया बदलाव देखलाबॊ",
+       "rclistfrom": "$3 $2 सॆं नया बदलाव देखलाबॊ",
        "rcshowhideminor": "छोटॊ बदलाव $1",
        "rcshowhidebots": "बोट सीनी $1",
        "rcshowhideliu": "लॉग्ड इन सदस्यॊ के बदलाव $1",
        "recentchangeslinked-to": "ऐकरॊ बदला मॆं देलॊ पन्ना सीनी सॆं जुडलॊ पन्ना सीनी के बदलाव दिखलाबॊ",
        "upload": "फाईल अपलोड",
        "uploadlogpage": "अपलोड सूची",
-       "uploadedimage": "\"[[$1]]\" कॆ अपलोड करलॊ गेलै",
        "filehist": "फाइल के इतिहास",
        "filehist-help": "संचिका पुरानॊ समय में कैन्हॊ दिखै रहै इ जानै लेली वांछित दिनांक/समय पर चटका लगाबॊ.",
        "filehist-current": "मौजूदा",
        "booksources-go": "जा",
        "log": "लॉग सूची",
        "allpages": "सब्भे पन्ना",
-       "alphaindexline": "$1 सॆ $2 तलक",
        "prevpage": "पिछला पन्ना ($1)",
        "allpagesfrom": "देलॊ गेलॊ अक्षर सॆं आरंभ होयवाला लेख दर्शाबॊ:",
        "allpagesto": "ऐना समाप्त होय वाला पन्ना दिखाबॊ:",
index 627d283..ac102a6 100644 (file)
@@ -62,6 +62,7 @@
        "tog-watchdefault": "أضف الصفحات والملفات التي أعدلها إلى قائمة مراقبتي",
        "tog-watchmoves": "أضف الصفحات والملفات التي أنقلها إلى قائمة مراقبتي",
        "tog-watchdeletion": "أضف الصفحات والملفات التي أحذفها إلى قائمة مراقبتي",
+       "tog-watchrollback": "أضف إلى قائمة مراقبتي الصفحات التي كنت أجريت فيها استرجاعات",
        "tog-minordefault": "أشِّر كل التعديلات على أنها طفيفة مبدئيا",
        "tog-previewontop": "أظهر معاينة النص فوق صندوق التحرير",
        "tog-previewonfirst": "أظهر معاينة مع أول تعديل",
        "returnto": "ارجع إلى $1.",
        "tagline": "من {{SITENAME}}",
        "help": "مساعدة",
-       "search": "ابحث",
+       "search": "بحث",
        "searchbutton": "ابحث",
        "go": "اذهب",
        "searcharticle": "اذهب",
        "talkpagelinktext": "نقاش",
        "specialpage": "صفحة خاصة",
        "personaltools": "أدوات شخصية",
-       "postcomment": "قسم جديد",
        "articlepage": "اعرض صفحة المحتوى",
        "talk": "نقاش",
        "views": "معاينة",
        "jumptonavigation": "تصفح",
        "jumptosearch": "ابحث",
        "view-pool-error": "عذرا، الخواديم منهكة حاليا.\nيحاول مستخدمون كثر الوصول إلى هذه الصفحة.\nمن فضلك تمهّل قليلا قبل محاولة الوصول إلى هذه الصفحة مجددا.\n\n$1",
+       "generic-pool-error": "عذرا، الخوادم مشغولة حاليا لوجود مستخدمون كثر يطلبون عرض هذا المورد. انتظر قليلا وأعد المحاولة.",
        "pool-timeout": "انتهت مهلة القفل",
        "pool-queuefull": "الطابور ملآن",
        "pool-errorunknown": "خطأ غير معروف",
        "hidetoc": "أخف",
        "collapsible-collapse": "أخف",
        "collapsible-expand": "أظهر",
+       "confirmable-confirm": "أأنت متأكد{{GENDER:$1||ة}}؟",
+       "confirmable-yes": "نعم",
+       "confirmable-no": "لا",
        "thisisdeleted": "عرض أو استرجاع $1؟",
        "viewdeleted": "عرض $1؟",
        "restorelink": "{{PLURAL:$1|$1 تعديل محذوف|تعديلا واحدا محذوفا|تعديلين محذوفين|$1 تعديلات محذوفة|$1 تعديلا محذوفا|$1 تعديل محذوف}}",
        "invalidtitle-knownnamespace": "عنوان غير صالح في النطاق «$2» مع نص «$3»",
        "invalidtitle-unknownnamespace": "عنوان غير صالح ذو نطاق غير معروف رقم $1 ونص «$2»",
        "exception-nologin": "غير مسجل الدخول",
-       "exception-nologin-text": "اÙ\84رجاء [[Special:Userlogin|تسجÙ\8aÙ\84 Ø§Ù\84دخÙ\88Ù\84]] Ù\84تتÙ\85Ù\83Ù\86 Ù\85Ù\86 Ø§Ù\84Ù\88صÙ\88Ù\84 Ù\84Ù\87Ø°Ù\87 Ø§Ù\84صÙ\81حة Ø£Ù\88 Ø£Ø¯Ø§Ø¡ Ù\87ذا Ø§Ù\84إجراء.",
+       "exception-nologin-text": "سجÙ\84 Ø§Ù\84دخÙ\88Ù\84 Ù\84Ù\84تÙ\85Ù\83Ù\86 Ù\85Ù\86 Ø¹Ø±Ø¶ Ù\87Ø°Ù\87 Ø§Ù\84صÙ\81حة Ø£Ù\88 Ø¥Ø¬Ø±Ø§Ø¡ Ù\87ذا Ø§Ù\84Ù\81عÙ\84.",
        "exception-nologin-text-manual": "الرجاء $1 لتتمكن من الوصول لهذه الصفحة أو أداء هذا الإجراء.",
        "virus-badscanner": "ضبط سيء: ماسح فيروسات غير معروف: ''$1''",
        "virus-scanfailed": "فشل المسح (كود $1)",
        "virus-unknownscanner": "مضاد فيروسات غير معروف:",
-       "logouttext": "'''أنت الآن غير مسجل الدخول.'''\n\nقد ترى بعض الصفحات كما لو أنك ما زلت مسجل الدخول، وذلك حتى تفرغ التخزين المؤقت في متصفحك.",
+       "logouttext": "<strong>أنت الآن غير مسجل الدخول.</strong> قد ترى بعض الصفحات كما لو أنك ما زلت مسجل الدخول، وذلك حتى تفرغ التخزين المؤقت في متصفحك.",
        "welcomeuser": "أهلاً بك يا $1!",
        "welcomecreation-msg": "تم إنشاء حسابك.\nلا تنس تعديل [[Special:Preferences|تفضيلاتك في {{SITENAME}}]].",
        "yourname": "اسم المستخدم:",
        "externaldberror": "هناك إما خطأ في دخول قاعدة البيانات الخارجية أو أنه غير مسموح لك بتحديث حسابك الخارجي.",
        "login": "تسجيل الدخول",
        "nav-login-createaccount": "دخول / إنشاء حساب",
-       "loginprompt": "يجب أن تكون الكوكيز لديك مفعلة لتسجل الدخول إلى {{SITENAME}}.",
        "userlogin": "دخول / إنشاء حساب",
        "userloginnocreate": "تسجيل الدخول",
        "logout": "تسجيل الخروج",
        "userlogin-resetlink": "نسيت تفاصيل الدخول؟",
        "userlogin-resetpassword-link": "نسيت كلمة مرورك؟",
        "userlogin-helplink2": "المساعدة في الدخول",
-       "userlogin-loggedin": "أنت {{GENDER:$1|مسجل|مسجلة}} الدخول مسبقًا باسم $1. {{GENDER:$1|استخدم|استخدمي}} النموذج بالأسفل لتسجيل الدخول بحساب آخر.",
-       "userlogin-createanother": "إنشاء حساب آخر",
        "createacct-emailrequired": "عنوان البريد الإلكتروني",
        "createacct-emailoptional": "البريد الإلكتروني (اختياري)",
        "createacct-email-ph": "أدخل عنوان بريدك الإلكتروني",
        "preview": "عرض مسبق",
        "showpreview": "أظهر معاينة",
        "showdiff": "عرض التغييرات",
+       "blankarticle": "<strong>تنبيه:</strong> الصفحة التي تريد إنشاءها فارغة. إذا نقرت \"{{int:savearticle}}\" ثانية فستنشأ الصفحة بدون محتوى.",
        "anoneditwarning": "'''تحذير:''' لم تقم بالدخول.\nسيسجل عنوان الآيبي خاصتك في تاريخ هذه الصفحة.",
        "anonpreviewwarning": "''أنت غير مسجل الدخول. الحفظ سيسجل عنوان الأيبي الخاص بك في تاريخ هذه الصفحة.''",
        "missingsummary": "'''تنبيه:''' لم تقم بكتابة ملخص للتعديل.\nإذا قمت بضغط حفظ الصفحة مرة أخرى، فيتم حفظ تعديلك بدون ملخص.",
        "parser-template-recursion-depth-warning": "تم تجاوز حد عمق فرد القوالب ($1)",
        "language-converter-depth-warning": "تم تخطي حد عمق محول اللغة ($1)",
        "node-count-exceeded-category": "تجاوزات تعداد العقد",
-       "node-count-exceeded-warning": "تجاوزت هذه الصفحة تعداد العقد",
+       "node-count-exceeded-category-desc": "الصفحة تتجاوز الحد الأقصى للعقد البرمجية.",
+       "node-count-exceeded-warning": "الصفحة تجاوزت الحد الأقصى للعقد البرمجية.",
        "expansion-depth-exceeded-category": "تجاوزات عمق التوسيع",
-       "expansion-depth-exceeded-category-desc": "هذا تصنيف للصفحات التي تتجاوز عمق التوسيع.",
+       "expansion-depth-exceeded-category-desc": "الصفحة تجاوزت الحد الأقصى لعمق التوسيع.",
        "expansion-depth-exceeded-warning": "الصفحة تجاوزت عمق التوسيع",
        "parser-unstrip-loop-warning": "حلقة معراة تم الكشف عنها",
        "parser-unstrip-recursion-limit": "تعدى حد العودية Unstrip  ($1)",
        "currentrev": "المراجعة الحالية",
        "currentrev-asof": "المراجعة الحالية بتاريخ $1",
        "revisionasof": "مراجعة $1",
-       "revision-info": "Ù\85راجعة $1 Ø¨Ù\88اسطة $2",
+       "revision-info": "Ù\86سخة $1 Ù\84Ù\84Ù\85ستخدÙ\85 {{GENDER:$6|$2}}$7",
        "previousrevision": "→ مراجعة أقدم",
        "nextrevision": "مراجعة أحدث ←",
        "currentrevisionlink": "المراجعة الحالية",
        "rev-deleted-event": "(فعل السجل تمت إزالته)",
        "rev-deleted-user-contribs": "[اسم المستخدم أو عنوان الأيبي تمت إزالته - التعديل مخفي من المساهمات]",
        "rev-deleted-text-permission": "'''حُذِفت''' مراجعة هذه الصفحة.\nيمكنك العثور على التفاصيل في [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سجل الحذف].",
+       "rev-suppressed-text-permission": "هذه النسخة قد <strong>أخفيت</strong> ([{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} تفاصيل].)",
        "rev-deleted-text-unhide": "'''حُذِفت''' مراجعة الصفحة هذه.\nيمكن العثور على تفاصيل في [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سجل الحذف].\nمازال بإمكانك [$1 رؤية هذه المراجعة] إذا أردت المتابعة.",
        "rev-suppressed-text-unhide": "'''أُخفيت''' مراجعة الصفحة هذه.\nيمكنك العثور على التفاصيل في [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} سجل الإخفاء].\nبإمكانك [$1 رؤية هذه المراجعة] إذا أردت المتابعة.",
        "rev-deleted-text-view": "'''حُذِفت''' مراجعة هذه الصفحة.\nيمكنك رؤيتها؛ ويمكنك العثور على التفاصيل في [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سجل الحذف].",
        "revdelete-no-file": "الملف المحدد غير موجود.",
        "revdelete-show-file-confirm": "هل أنت متأكد أنك تريد رؤية مراجعة محذوفة للملف \"<nowiki>$1</nowiki>\" بتاريخ $2 الساعة $3؟",
        "revdelete-show-file-submit": "نعم",
+       "revdelete-selected-text": "{{PLURAL:$1|نسخة مختارة|نسخ مختارة}} ل[[:$2]]:",
        "logdelete-selected": "{{PLURAL:$1|حدث السجل المختار|أحداث السجل المختارة}}:",
        "revdelete-text-others": "سيتمكن الإداريون الآخرون على {{SITENAME}} من الوصول إلى المحتوى المخفي وإلغاء حذفه مجددا من خلال ذات الواجهة ما لم تطبق قيود إضافية.",
        "revdelete-confirm": "الإداريون الآخرون في {{SITENAME}} سيظل بإمكانهم رؤية المحتوى المخفي ويمكنهم استرجاعه مجددا من خلال هذه الواجهة نفسها، مالم يتم وضع قيود إضافية.\nمن فضلك أكد أنك تنوي فعل هذا، وأنك تفهم العواقب، وأنك تفعل هذا بالتوافق مع [[{{MediaWiki:Policy-url}}|السياسة]].",
        "searchprofile-advanced-tooltip": "ابحث في النطاقات المخصصة",
        "search-result-size": "$1 ({{PLURAL:$2|لا كلمات|كلمة واحدة|كلمتان|$2 كلمات|$2 كلمة}})",
        "search-result-category-size": "{{PLURAL:$1|لا أعضاء|عضو واحد|عضوان|$1 أعضاء|$1 عضوًا|$1 عضو}} ({{PLURAL:$2|لا تصانيف فرعية|تصنيف فرعي واحد|تصنيفان فرعيان|$2 تصنيفات فرعية|$2 تصنيفًا فرعيًا|$2 تصنيف فرعي}} و{{PLURAL:$3|لا ملفات|ملف واحد|ملفان|$3 ملفات|$3 ملفًا|$3 ملف}})",
-       "search-result-score": "الارتباط: $1%",
        "search-redirect": "(تحويلة $1)",
        "search-section": "(قسم $1)",
        "search-file-match": "(يطابق محتوى الملف)",
        "searchrelated": "مرتبطة",
        "searchall": "الكل",
        "showingresults": "معروض بالأسفل {{PLURAL:$1|'''1''' نتيجة|'''$1''' نتيجة}} بدءا من رقم '''$2'''.",
-       "showingresultsinrange": "معروض بالأسفل حتى {{PLURAL:$1|<strong>1</strong> نتيجة|<strong>$1</strong> نتائج}} في النطاق #<strong>$2</strong> إلى #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|النتيجة '''$1''' من'''$3'''|النتائج '''$1 - $2''' من'''$3'''}} ل'''$4'''",
+       "showingresultsinrange": "بالأسفل {{PLURAL:$1|نتيجة واحدة|<strong>$1</strong> نتائج|<strong>$1</strong> نتيجة}} في النطاق من <strong>$2</strong> إلى <strong>$3</strong>.",
        "search-nonefound": "لا توجد نتائج تطابق الاستعلام.",
        "powersearch-legend": "بحث متقدم",
        "powersearch-ns": "بحث في النطاقات:",
        "powersearch-togglelabel": "اختر:",
        "powersearch-toggleall": "الكل",
        "powersearch-togglenone": "لا شيء",
-       "powersearch-remember": "تذÙ\83ر Ø§Ù\84اختÙ\8aار Ù\84بحث Ø§Ù\84Ù\85ستÙ\82بÙ\84",
+       "powersearch-remember": "تذÙ\83ر Ø§Ù\84Ø®Ù\8aارات Ù\84Ù\84بحث Ù\85ستÙ\82بÙ\84ا",
        "search-external": "بحث خارجي",
        "searchdisabled": "البحث في {{SITENAME}} معطل.\nيمكنك البحث من خلال جوجل في الوقت الحالي.\nلاحظ أن فهارسه لمحتوى {{SITENAME}} ربما تكون غير محدثة.",
        "search-error": "حدث خطأ ما أثناء البحث: $1",
        "prefs-files": "ملفات",
        "prefs-custom-css": "CSS مخصص",
        "prefs-custom-js": "جافاسكربت مخصص",
-       "prefs-common-css-js": "CSS أو جافاسكربت مشتركة لجميع المظاهر:",
+       "prefs-common-css-js": "سي إس إس وجافاسكربت مشترك لجميع المظاهر:",
        "prefs-reset-intro": "يمكنك استخدام هذه الصفحة لإعادة تفضيلاتك للحالة الافتراضية للموقع.\nلن تستطيع استرجاع الحالة السابقة.",
        "prefs-emailconfirm-label": "تأكيد البريد الإلكتروني:",
        "youremail": "البريد:",
        "userrights-lookup-user": "أدِر مجموعات المستخدم",
        "userrights-user-editname": "أدخل اسم مستخدم:",
        "editusergroup": "عدل مجموعات المستخدم",
-       "editinguser": "تغيير صلاحيات المستخدم '''[[User:$1|$1]]''' $2",
+       "editinguser": "تغيير صلاحيات {{GENDER:$1|المستخدم|المستخدمة}} '''[[User:$1|$1]]''' $2",
        "userrights-editusergroup": "تعديل مجموعات المستخدم",
        "saveusergroups": "احفظ مجموعات المستخدم",
        "userrights-groupsmember": "عضو في:",
        "uploadwarning": "تحذير الرفع",
        "uploadwarning-text": "من فضلك عدل وصف الملف أدناه وحاول مرة أخرى.",
        "savefile": "احفظ الملف",
-       "uploadedimage": "رفع \"[[$1]]\"",
-       "overwroteimage": "رفع نسخة جديدة من \"[[$1]]\"",
        "uploaddisabled": "تم تعطيل الرفع",
        "copyuploaddisabled": "الرفع من مسار معطل.",
        "uploaddisabledtext": "رفع الملفات معطل.",
        "license": "ترخيص:",
        "license-header": "ترخيص",
        "nolicense": "غير محدد",
+       "licenses-edit": "عدل خيارات الترخيص",
        "license-nopreview": "(العرض المسبق غير متوفر)",
        "upload_source_url": "  (مسار صحيح، يمكن الوصول إليه)",
        "upload_source_file": " (ملف على حاسوبك)",
+       "listfiles-delete": "حذف",
        "listfiles-summary": "هذه الصفحة الخاصة تعرض كل الملفات المرفوعة.",
        "listfiles_search_for": "ابحث عن اسم الميديا:",
        "imgfile": "ملف",
        "randomincategory": "صفحة عشوائية في التصنيف",
        "randomincategory-invalidcategory": "\"$1\" ليس اسم تصنيف صالح.",
        "randomincategory-nopages": "لا توجد صفحات في التصنيف [[:Category:$1|$1]].",
-       "randomincategory-selectcategory": "عرض صفحة عشوائية من التصنيف:  $1   $2",
-       "randomincategory-selectcategory-submit": "اذهب",
        "randomredirect": "تحويلة عشوائية",
        "randomredirect-nopages": "لا توجد تحويلات في النطاق \"$1\".",
        "statistics": "إحصاءات",
        "watchlist-details": "{{PLURAL:$1||صفحة واحدة|صفحتان|$1 صفحات|$1 صفحة}} في قائمة مراقبتك، دون اعتبار صفحات النقاش صفحات منفصلة.",
        "wlheader-enotif": "الإخطار بالبريد الإلكتروني مُفعّل.",
        "wlheader-showupdated": "الصفحات التي تم تحريرها بعد مطالعتك إياها آخر مرة عناوينها بالخط '''الغليظ'''",
-       "wlnote2": "فيما يلي تعرض التعديلات التي أجريت في آخر {{PLURAL:$1|ساعة|ساعتين|<strong>$1</strong> ساعات|<strong>$1</strong> ساعة}}، وذلك اعتبارا من $2، $3.",
+       "wlnote": "بالأسفل {{PLURAL:$1|لا توجد تغييرات|التغيير الأخير|آخر تغييرين|آخر '''$1''' تغييرات|آخر '''$1''' تغييرا|آخر '''$1''' تغيير}} في {{PLURAL:$2||'''الساعة''' الماضية|'''الساعتين''' الماضيتين|ال'''$2''' ساعات الماضية|ال'''$2''' ساعة الماضية}} وفقاً ل$3، $4.",
        "wlshowlast": "عرض آخر $1 ساعات $2 أيام $3",
        "watchlist-options": "خيارات قائمة المراقبة",
        "watching": "يراقب...",
        "contribsub2": "ل{{GENDER:$3|$1}} ($2)",
        "contributions-userdoesnotexist": "حساب المستخدم \"$1\" غير مسجل.",
        "nocontribs": "لم يتم العثور على تغييرات تطابق هذه المحددات.",
-       "uctop": "حالي",
+       "uctop": "(حالية)",
        "month": "من شهر (وأقدم):",
        "year": "من سنة (وأقدم):",
        "sp-contributions-newbies": "اعرض مساهمات الحسابات الجديدة فقط",
        "movepagetalktext": "صفحة النقاش المرفقة سيتم نقلها كذلك، '''إلا في حالة''':\n* توجد صفحة نقاش غير فارغة تحت العنوان الجديد، أو\n* قمت بإزالة اختيار الصندوق بالأسفل.\n\nوفي هذه الحالات، يجب عليك نقل أو دمج محتويات الصفحة يدويا، إذا رغب في ذلك.",
        "movearticle": "انقل الصفحة:",
        "moveuserpage-warning": "'''تحذير: أنت على وشك نقل صفحة مستخدم. من فضلك لاحظ أن الصفحة وحدها سوف تنقل وأن المستخدم لن يعاد تسميته.'''",
-       "movecategorypage-warning": "أنت على وشك نقل صفحة التصنيف إلى عنوان جديد؛ لن تنقل الصفحات المندرجة تحت التصنيف إلى العنوان الجديد.",
+       "movecategorypage-warning": "<strong>تحذير:</strong> أنت على وشك نقل صفحة التصنيف إلى عنوان جديد؛ <em>لن</em> تنقل الصفحات المندرجة تحت التصنيف إلى العنوان الجديد.",
        "movenologintext": "يجب أن تكون مستخدماً مسجلاً وأن  [[Special:UserLogin|تسجل دخولك]] لكي تنقل صفحة.",
        "movenotallowed": "أنت لا تمتلك الصلاحية لنقل الصفحات.",
        "movenotallowedfile": "أنت لا تمتلك الصلاحية لنقل الملفات.",
        "import": "استيراد صفحات",
        "importinterwiki": "استيراد ترانسويكي",
        "import-interwiki-text": "اختر ويكي وعنوان الصفحة للاستيراد.\nتواريخ المراجعات وأسماء المحررين سيتم حفظها.\nكل أفعال الاستيراد عبر الويكي يتم تسجيلها في [[Special:Log/import|سجل الاستيراد]].",
-       "import-interwiki-source": "الويكي/الصفحة المصدر:",
        "import-interwiki-history": "انسخ كل نسخ التاريخ لهذه الصفحة",
        "import-interwiki-templates": "ضمن كل القوالب",
        "import-interwiki-submit": "استيراد",
        "version-hook-name": "اسم الخطاف",
        "version-hook-subscribedby": "يستخدم بواسطة",
        "version-version": "(نسخة $1)",
+       "version-no-ext-name": "[لا اسم]",
        "version-svn-revision": "ن$1",
        "version-license": "ترخيص ميدياويكي",
        "version-ext-license": "ترخيص",
        "version-ext-colheader-name": "امتداد",
+       "version-skin-colheader-name": "واجهة",
        "version-ext-colheader-version": "نسخة",
        "version-ext-colheader-license": "ترخيص",
        "version-ext-colheader-description": "وصف",
        "duration-centuries": "{{PLURAL:$1||قرن واحد|قرنان|$1 قرون|$1 قرنًا|$1 قرن}}",
        "duration-millennia": "{{PLURAL:$1||ألفية واحدة|ألفيتان|$1 ألفيات|$1 ألفية}}",
        "rotate-comment": "تدوير الصورة  {{PLURAL:$1||درجة واحدة|درجتان|$1 درجات|$1 درجة}} باتجاه عقارب الساعة",
-       "limitreport-title": "محلل سمات البيانات:",
+       "limitreport-title": "بيانات تحليلية",
        "limitreport-cputime": "زمن المعالجة المستغرق",
        "limitreport-cputime-value": "{{PLURAL:$1|أقل من ثانية|ثانية واحدة|ثانيتان|$1 ثوان|$1 ثانية}}",
        "limitreport-walltime": "الزمن الحقيقي المستغرق",
        "limitreport-walltime-value": "{{PLURAL:$1|أقل من ثانية|ثانية واحدة|ثانيتان|$1 ثوان|$1 ثانية}}",
-       "limitreport-ppvisitednodes": "زار Ø§Ù\84Ù\85عاÙ\84ج Ø¹Ù\82دة Ø¥Ø­ØµØ§Ø¡",
-       "limitreport-ppgeneratednodes": "أحدث Ø§Ù\84Ù\85عاÙ\84ج Ø¹Ù\82دة Ø¥Ø­ØµØ§Ø¡",
-       "limitreport-postexpandincludesize": "بعد ØªÙ\88سÙ\8aع Ø§Ù\84Ù\85ساحة Ø§Ù\84شاÙ\85Ù\84Ø©",
+       "limitreport-ppvisitednodes": "عدد Ø§Ù\84عÙ\82د Ø§Ù\84Ù\85عاÙ\84جة",
+       "limitreport-ppgeneratednodes": "عÙ\82د Ø²Ø§Ø±Ù\87ا Ø§Ù\84Ù\85عاÙ\84ج Ø§Ù\84Ù\85سبÙ\82",
+       "limitreport-postexpandincludesize": "حجÙ\85 ØªØ¶Ù\85Ù\8aÙ\86 Ø§Ù\84تÙ\88سÙ\8aعات",
        "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|بايت}}",
-       "limitreport-templateargumentsize": "حجÙ\85 Ù\86Ù\82اش Ø§Ù\84Ù\82الب",
+       "limitreport-templateargumentsize": "حجÙ\85 Ù\85عطÙ\8aات Ø§Ù\84Ù\82Ù\88الب",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|بايت}}",
-       "limitreport-expansiondepth": "أكثر عمق توسعي",
-       "limitreport-expensivefunctioncount": "تحÙ\84Ù\8aÙ\84 Ø¥Ø­ØµØ§Ø¡ Ù\88ظÙ\8aÙ\81Ø© Ù\85Ù\83Ù\84Ù\81",
-       "expandtemplates": "فرد القوالب",
+       "limitreport-expansiondepth": "أعمق التوسيعات",
+       "limitreport-expensivefunctioncount": "دÙ\88اÙ\84 Ù\85Ø­Ù\84Ù\84Ø© Ù\85Ù\83Ù\84Ù\81Ø©",
+       "expandtemplates": "توسعة قالب",
        "expand_templates_intro": "تتعامل هذه الصفحة الخاصة مع نصوص الويكي وتقوم بفرد كل القوالب الموجودة به.\nوتقوم أيضا بفرد دوال القوالب مثل\n<code><nowiki>{{</nowiki>#language:…}}</code> and variables like <code><nowiki>{{</nowiki>CURRENTDAY}}</code>. حقيقةً، تقوم التعامل مع كل ما بين الأقواس المزدوجة.",
        "expand_templates_title": "عنوان صفحة هذا النص، لأجل معالجة {{FULLPAGENAME}} إلخ.:",
        "expand_templates_input": "النص المدخل:",
        "expand_templates_remove_nowiki": "أخفِ وسوم <nowiki> في الناتج",
        "expand_templates_generate_xml": "اعرض شجرة XML parse",
        "expand_templates_generate_rawhtml": "أظهر خام HTML",
-       "expand_templates_preview": "عرض مسبق"
+       "expand_templates_preview": "عرض مسبق",
+       "pagelanguage": "اختيار لغة الصفحة",
+       "pagelang-name": "صفحة",
+       "pagelang-language": "اللغة",
+       "pagelang-use-default": "استخدام اللغة الافتراضية",
+       "pagelang-select-lang": "اختر اللغة",
+       "right-pagelang": "تغيير لغة الصفحة",
+       "action-pagelang": "تغيير لغة الصفحة",
+       "log-name-pagelang": "تغيير سجل الصفحة"
 }
index 8d6b802..1a86697 100644 (file)
        "talkpagelinktext": "ܡܡܠܠܐ",
        "specialpage": "ܦܐܬܐ ܕܝܠܢܝܬܐ",
        "personaltools": "ܡܐܢ̈ܐ ܦܪ̈ܨܘܦܝܐ",
-       "postcomment": "ܡܢܬܐ ܚܕܬܐ",
        "articlepage": "ܚܘܝܝܐ ܕܦܐܬܐ ܕܚܒܝܫܬ̈ܐ",
        "talk": "ܡܡܠܠܐ",
        "views": "ܚܙܝܬ̈ܐ",
        "userlogin-signwithsecure": "ܐܚܫܚ ܕܒܝܩܘܬܐ ܡܫܝܢܢܬܐ",
        "login": "ܥܘܠ",
        "nav-login-createaccount": "ܥܘܠ / ܒܪܝ ܚܘܫܒܢܐ",
-       "loginprompt": "ܐܠܨܐ ܠܡܦܐܬܢܐ ܕܝܠܟ ܕܣܡܟ ܠܩܘܩܝܙ (cookies) ܠܥܠܠܬܐ ܒ {{SITENAME}}.",
        "userlogin": "ܥܘܠ / ܒܪܝ ܚܘܫܒܢܐ",
        "userloginnocreate": "ܥܘܠ",
        "logout": "ܦܠܘܛ",
        "minlength1": "ܫܡܗ̈ܐ ܕܠܦܦܐ ܘܠܐ ܕܢܗܘܐ ܒܪܝܐ ܡܢ ܐܬܘܬܐ ܚܕܐ ܟܕ ܙܥܘܪ",
        "uploadwarning": "ܐܣܩ ܙܘܗܪܐ",
        "savefile": "ܠܒܘܟ ܠܦܦܐ",
-       "uploadedimage": "ܐܣܩ \"[[$1]]\"",
-       "overwroteimage": "ܐܣܩ ܨܚܚܐ ܚܕܬܐ ܡܢ \"[[$1]]\"",
        "uploadvirus": "ܠܦܦܐ ܐܝܬ ܒܗ ܒܝܪܘܣ!\nܐܪ̈ܝܟܬܐ: $1",
        "upload-source": "ܡܒܘܥܐ ܕܠܦܦܐ",
        "sourcefilename": "ܫܡܐ ܕܠܦܦܐ ܡܒܘܥܐ",
        "unwatchthispage": "ܟܠܝ ܪܗܝܐ",
        "watchlist-details": "{{PLURAL:$1|$1 ܦܐܬܐ|$1 ܦܐܬܬ̈ܐ}} ܒܪ̈ܗܝܬܟ, ܫܒܘܩ ܡܢ ܦܐܬܬ̈ܐ ܕܡܡܠܠܐ.",
        "wlheader-showupdated": "ܦܐܬܬ̈ܐ ܕܐܫܬܚܠܦܢ ܡܢ ܒܬܪ ܣܘܥܪܢܐ ܐܚܪܝܐ ܠܗܝܢ ܡܬܓܠܚܢ ܒܣܪܛܐ '''ܚܠܝܡܐ'''",
+       "wlnote": "ܠܬܚܬ {{PLURAL:$1|ܫܘܚܠܦܐ ܐܚܪܝܐ| '''$1''' ܫܘܚܠܦ̈ܐ ܐܚܪ̈ܝܐ}} {{PLURAL:$2|ܒܫܥܬܐ ܐܚܪܝܬܐ|'''$2''' ܒܫܥܬ̈ܐ ܐܚܪ̈ܝܬܐ}}, ܠܦܘܬ $3, $4.",
        "wlshowlast": "ܚܘܝ $1 ܫܥܬ̈ܐ $2 ܝܘܡܬ̈ܐ ܐܚܪ̈ܝܐ $3",
        "watchlist-options": "ܨܒܝܢܝܘܬ̈ܐ ܕܪ̈ܗܝܬܐ",
        "watching": "ܪܗܝܐ...",
index c8a3bf9..4eb0a96 100644 (file)
        "remembermypassword": "Amulen tañi nülküwküleael tüfa mew (alürumechi $1 {{PLURAL:$1 antü}})",
        "login": "Konkülen",
        "nav-login-createaccount": "konkülen/dewman konün",
-       "loginprompt": "Müley \"Cookies\" ñi püneleael wirintukuwam {{SITENAME}} mew.",
        "userlogin": "Konkülen/dewman konün",
        "userloginnocreate": "Konün",
        "logout": "Tripan",
        "uploadnologin": "Petu konlaymi",
        "uploadlogpage": "Püramülu eltukawün ñi wirintukun",
        "filedesc": "Pichi trokiñündungu",
-       "uploadedimage": "Püramüngey \"[[$1]]\"",
        "watchthisupload": "Llaytun tüfachi eltukawün",
        "license": "Dungunentuwün:",
        "license-header": "Dungunentuwün",
index c1885cf..c5e815b 100644 (file)
@@ -3,34 +3,35 @@
                "authors": [
                        "Bachounda",
                        "Oldstoneage",
-                       "아라"
+                       "아라",
+                       "Amire80"
                ]
        },
        "tog-underline": "تسطار الوصيلات:",
        "tog-hideminor": "خبي الكتيبات الصغيرة في التبديلات التوالا",
        "tog-hidepatrolled": "خبي الكتيبات المعسوسه في التبديلات التوالا",
        "tog-newpageshidepatrolled": "خبي الباجات المعسوسه اللي في ليستت الباجات الجدد",
-       "tog-extendwatchlist": "دÙ\84Ù\8a Ø§Ù\84Ù\84Ù\8aستÙ\87 Ù\86تاع Ø§Ù\84تبÙ\8aعÙ\87 Ø¨Ø§Ø´ ØªØ¹Ø±Ø¶ Ù\83اÙ\85Ù\84 Ø§Ù\84تبدÙ\8aÙ\84ات Ù\88 Ù\85Ø´Ù\8a Ø¨Ø±Ù\83 التوالا",
-       "tog-usenewrc": "اجÙ\85ع Ø§Ù\84Ù\80تبداÙ\84ات Ø¨Ù\84 ØµÙ\81حات Ù\81Ù\84 ØªØ¨Ø¯Ø§Ù\84ات Ø§Ù\84Ù\80تاÙ\84Ù\8aØ© Ù\88 Ø§Ù\84Ù\80Ù\84Ù\8aستة ØªØ§Ø¹ Ø§Ù\84Ù\80Ù\85راÙ\82بة (تستحÙ\82 Ø§Ù\84Ù\80 JavaScript)",
+       "tog-extendwatchlist": "دÙ\84Ù\91Ù\8a Ø§Ù\84Ù\84Ù\8aستة ØªØ§Ø¹ Ø§Ù\84تتباع Ø¨Ø§Ø´ ØªÙ\88رÙ\91Ù\8a Ù\83اÙ\85Ù\84 Ø§Ù\84تبدÙ\8aÙ\84اتØ\8c Ù\85اشÙ\8a Ø¨Ø±Ù\83 ØºÙ\8aر التوالا",
+       "tog-usenewrc": "جÙ\85Ù\91ع Ø§Ù\84Ù\80تبداÙ\84ات Ø¨Ù\84 ØµÙ\81حة Ù\81Ù\84 ØªØ¨Ø¯Ø§Ù\84ات Ø§Ù\84Ù\80جدÙ\8aدة Ù\88 Ø§Ù\84Ù\80Ù\84Ù\8aستة ØªØ§Ø¹ Ø§Ù\84Ù\80عسÙ\91Ø©",
        "tog-numberheadings": "رقم اليا عناوين السكسيو",
-       "tog-showtoolbar": "تبÙ\8aاÙ\86 Ø¨Ø§Ø±Ù\87 Ø§Ù\84Ù\83تÙ\8aبات (Ù\8aÙ\84زÙ\85Ù\87ا Ø¬Ø§Ù\81اسÙ\83رÙ\8aبت)",
-       "tog-editondblclick": "كتيبت الباجات بالزوج دركات (يلزمها جافاسكربت)",
-       "tog-editsectiononrightclick": "اÙ\83تÙ\8aÙ\81Ù\8a Ù\83تÙ\8aبت Ø§Ù\84سÙ\83سÙ\8aÙ\88ات Ø¨Ø§Ù\84درÙ\8aÙ\83 Ø¨Ø§Ù\84Ù\8aÙ\85Ù\8aÙ\86 Ø¹Ù\84Ù\89 Ø§Ù\84عÙ\86اÙ\88Ù\8aÙ\86 Ù\86تاعÙ\87Ù\85\8aتطÙ\84ب Ø¬Ø§Ù\81اسÙ\83رÙ\8aبت)",
+       "tog-showtoolbar": "بÙ\8aÙ\91Ù\86 Ø§Ù\84بارÙ\91Ø© ØªØ§Ø¹ Ø¯Ù\88زاÙ\86â\80\98 Ø§Ù\84Ù\83تبة",
+       "tog-editondblclick": "آكتيفي التبدال تاع الباجات بل زوج ضركات تاع الفارة",
+       "tog-editsectiononrightclick": "Ø¢Ù\83تÙ\8aÙ\81Ù\8a Ø§Ù\84تبداÙ\84 ØªØ§Ø¹ Ø§Ù\84سÙ\83سÙ\8aÙ\88Ù\91ات Ø¨Ù\84 Ø¶Ø±Ù\8aÙ\83 Ø¨Ù\84 Ù\84Ù\8aÙ\85Ù\86Ø© Ø¹Ù\84Ù\89 Ø§Ù\84عÙ\84اÙ\88Ù\8aÙ\86 Ù\86تاعÙ\87Ù\85",
        "tog-watchcreations": "زيد الـصفحات اللي نخلقها و الـفيشيّات فل قايمة تاع التتباع تاعي",
        "tog-watchdefault": "زيد الـصفحات و الـفيشيّات اللي نبدّلها فل قايمة تاع الـتتباع تاعي",
        "tog-watchmoves": "زيد الـصفحات و الـفيشيات اللي نحوّلها فل قايمة تاع الـتباع تاعي",
        "tog-watchdeletion": "زيد الـصفحات اللي نفصيها فل قايمة تاع التتباع تاعي",
        "tog-minordefault": "ماركي كل التبديلات بلي راهي خفيفه",
-       "tog-previewontop": "Ù\88رÙ\8a Ø´Ù\88Ù\81Ù\87\82بÙ\84Ù\8aÙ\87 Ù\84Ù\84Ù\83تبÙ\87 Ù\81Ù\88Ù\82 ØµÙ\86دÙ\88Ù\82 Ø§Ù\84Ù\83تÙ\8aبÙ\87",
+       "tog-previewontop": "Ù\88رÙ\91Ù\8a Ù\86ضرة Ù\82بÙ\84Ù\8aÙ\91Ø© ØªØ§Ø¹ Ù\88اش Ù\8aصراØ\8c Ù\81Ù\88Ù\82 Ø§Ù\84جÙ\8aÙ\87Ø© ØªØ§Ø¹ Ø§Ù\84تبداÙ\84",
        "tog-previewonfirst": "بين شوفه-قبليه مع اول تبديله",
        "tog-enotifwatchlistpages": "ابحت لي إيمال كي تتبدّل صفحة ولا فيشي من الـليستة تاع الـتتباع تاعي",
-       "tog-enotifusertalkpages": "ابعثÙ\84Ù\8a Ø¨Ø±Ù\8aÙ\87 Ù\83Ù\84 Ù\85ا ØªØ¨Ø¯Ù\84ت Ø¨Ø§Ø¬Øª Ù\86Ù\82اش ديالي",
+       "tog-enotifusertalkpages": "ابعثÙ\84Ù\8a Ø¨Ø±Ù\8aÙ\91Ø© Ù\83Ù\84Ù\91 Ù\85ا ØªØ¨Ø¯Ù\91Ù\84ت Ø¨Ø§Ø¬ØªÙ° Ø§Ù\84تÙ\82رعÙ\8aج ديالي",
        "tog-enotifminoredits": "ابعت لي بريه حتا يلا كانت تبدالات صغيرة فلباجات و الـفيشيّات",
        "tog-enotifrevealaddr": "بين لادريستي إلكترونيك في براوات الاعلام",
        "tog-shownumberswatching": "بين شحال كاين من مستعمل يتبع الباجه",
        "tog-oldsig": "خطّ‘لـيدّ اللي كاين",
        "tog-fancysig": "اعتبر التوقيع كي كتيبه ويكي (بلا وصيله توماتيك)",
-       "tog-uselivepreview": "استعمل الـنضرة الـقبلانيّة (تستحق الـ JavaScript) (تجرابيّة)",
+       "tog-uselivepreview": "استعمل الـنضرة الـقبلانيّة الحيّة (عفسة تجرابيّة، تخلّيك تشوف التبدال الّي يصرا فل وقت الّي تكون تكتب)",
        "tog-forceeditsummary": "نبّهني كي تندخل كاش صفحة خاوية",
        "tog-watchlisthideown": "خبّي الـتبدالات تاوعي فل ليستة تاع الـتتباع",
        "tog-watchlisthidebots": "خبّي الـتبدالات تاع الـروبويات فل ليستة تاع التتباع تاعي",
        "newwindow": "(حل في تاقة جديدة)",
        "cancel": "انيلي",
        "moredotdotdot": "كتر...",
-       "morenotlisted": "Ù\83تر Ù\85اشÙ\8a Ù\85Ù\84Ù\8aستÙ\8a...",
+       "morenotlisted": "Ù\87اد Ø§Ù\84Ù\84Ù\8aستة Ù\85ا Ø±Ø§Ù\87Ù\8aØ´ Ù\85Ù\83Ù\85Ù\88Ù\84Ø©",
        "mypage": "باجه",
-       "mytalk": "نقاش",
+       "mytalk": "تقرعيج",
        "anontalk": "تناقش على الـ ip هادي",
        "navigation": "تبحار",
        "and": "&#32;و",
        "qbmyoptions": "الباجات نتاوعى",
        "faq": "المسقسية المتعاوده",
        "faqpage": "Project:سؤالات متكرره",
-       "vector-action-addsection": "زيد موضوع",
-       "vector-action-delete": "امحي",
-       "vector-action-move": "حول",
-       "vector-action-protect": "بروجي",
-       "vector-action-undelete": "ردّ كيما كان",
-       "vector-action-unprotect": "بدّل الـحماية",
-       "vector-view-create": "أصنع",
-       "vector-view-edit": "بدل",
-       "vector-view-history": "روح للتاريخي",
-       "vector-view-view": "أقرى",
-       "vector-view-viewsource": "شوف المصدر",
        "actions": "أفعال",
        "namespaces": "بلاصه تع أسموات",
        "variants": "متغيرات",
        "history": "تاريخ الملف",
        "history_short": "تاريخ",
        "updatedmarker": "مبدّل منلي الزيارة تاعي الـتالية",
-       "printableversion": "نسخه نتاع طبيع",
+       "printableversion": "نسخة تاع طبيع",
        "permalink": "وصيل دايم",
        "print": "امبريمي",
        "view": "اقرا",
+       "view-foreign": "شوف على $1",
        "edit": "بدل",
+       "edit-local": "عدّل التوصاف المبلّد",
        "create": "أصنع",
+       "create-local": "زيد توصاف مبلّد",
        "editthispage": "بدّل هاد الـصفحة",
        "create-this-page": "خلّق صفحة ب هاد الـعلوان",
        "delete": "امحي",
        "deletethispage": "امحي هاد الـصفحة",
        "undeletethispage": "ردّ الصفحة الّي محيتها",
+       "undelete_short": "رجّع {{PLURAL:$1||تعديل واحد|$1 تعديل}}",
+       "viewdeleted_short": "شوف {{PLURAL:$1||تعديل واحد|$1 تعديل}}",
        "protect": "حمايه",
        "protect_change": "بدل",
+       "protectthispage": "بروتيجي هاد الباجة",
+       "unprotect": "بدّل الحضية",
+       "unprotectthispage": "بدّل الحضية تاع هاد الباجة",
        "newpage": "باجه جديده",
+       "talkpage": "قرعَج على هاد الباجة",
        "talkpagelinktext": "ناقش",
+       "specialpage": "باجة خوصوصيّة",
        "personaltools": "ادوالت شخصيه",
+       "articlepage": "شوف الباجة تاع المحتاوا",
        "talk": "مناقشه",
        "views": "شوفات",
-       "toolbox": "صندوق الادوات",
+       "toolbox": "صندوق تاع الدوزان",
+       "userpage": "شوف الباجة تاع المستعملي",
+       "projectpage": "شوف الباجة تاع البروجي",
+       "imagepage": "شوف الباجة تاع الفيشي",
+       "mediawikipage": "شوف الباجة تاع الميساج",
+       "templatepage": "شوف الباجة تاع القالب",
+       "viewhelppage": "شوف الباجة تاع المعاونة",
+       "categorypage": "شوف الباجة تاع الصنيف",
+       "viewtalkpage": "شوف التقرعيج",
        "otherlanguages": "بلوغات وحد اوخره",
        "redirectedfrom": "(محول من $1)",
+       "redirectpagesub": "باجة تاع التحوال",
        "lastmodifiedat": "هاد الباجه راهي تبدّلت نهار الـ $1, على الـساعة $2.",
+       "viewcount": "هاد الباجة نشافت {{PLURAL:$1|خطرة وحدة|$1 خطرة}}.",
+       "protectedpage": "باجة محضيّة",
        "jumpto": "اقفز ل:",
        "jumptonavigation": "تجوال",
        "jumptosearch": "تفتاش",
+       "view-pool-error": "اعدرونا، السربايات راهم مغبّنين ف هاد الوقيتة.\nبزّاف المستعمليّين راهم باغيين يشوفو هاد الباجة.\nاصبرو شي وقيتة قبل ما تحاولو تلحقو لها عاود.\n\n$1",
+       "generic-pool-error": "اعدرونا، السربايات راهم مغبّنين ف هاد الوقيتة.\nبزّاف المستعمليّين راهم باغيين يشوفو هاد الباجة.\nاصبرو شي وقيتة قبل ما تحاولو تلحقو لها عاود.",
+       "pool-timeout": "المهلة تاع المقارعة راهي فاتت",
+       "pool-queuefull": "السنسلة تاع المقارعة راهي عامرة",
+       "pool-errorunknown": "خلطة ماشي معروفة",
+       "pool-servererror": "السربيس تاع العدّان راه حابس ( $1 ).",
        "aboutsite": "على{{SITENAME}}",
        "aboutpage": "Project:على",
+       "copyright": "المحتاوا راه تحت النسخة $1 تاع الليسانس، غير يلا كان مكتوب حاجاخرة.",
        "copyrightpage": "{{ns:project}}:حقوق النسخ",
        "currentevents": "الخبورات",
        "currentevents-url": "Project:خبورات",
        "disclaimers": "تنبيهات",
        "disclaimerpage": "Project:التحذيرات العامه",
        "edithelp": "معونة",
-       "mainpage": "الباجة اللوله",
+       "mainpage": "الباجة اللولانيّة",
        "mainpage-description": "الباجة اللوله",
+       "policy-url": "Project:المقاون",
        "portal": "المجتمع",
        "portal-url": "Project:بورطاي المجتمع",
        "privacy": "السياسة تاع الخصوصيات (الدين الضيّق)",
        "privacypage": "Project:خصوصيه",
+       "badaccess": "مشكل فل مسموحات",
+       "badaccess-group0": "ماشي مقبول ليك تدير الشي الّي راك تسيّي تديرهُ.",
+       "badaccess-groups": "الفعلة الّي راك سيّيت تديرها مسموحة برك لل مستعملّين {{PLURAL:$2||الّي هوما منل جماعة|الّي هوما من وحدة من هاد الجمايع}}: $1.",
+       "versionrequired": "النسخة $1 تاع ميدياويكي ملزومة",
+       "versionrequiredtext": "النسخة $1 تاع ميدياويكي راهي ملزومة باش تنجم تستعمل هاد الباجة.\nشوف [[Special:Version|الباجة تاع النسخات باش تفهم كتَر على هاد الشي]]",
+       "ok": "قابل",
        "retrievedfrom": "جايبينه من \"$1\"",
        "youhavenewmessages": "عندك $1 ($2).",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|عندك}} $1 من عند {PLURAL:$3|مستعملي واحد|زوج تاع المستعمليّين|$3 مستعملي}} ($2).",
+       "youhavenewmessagesmanyusers": "عندك $1 من عند شحال من مستعملي ($2).",
+       "newmessageslinkplural": "{{PLURAL:$1|بريّة جديدة وحدة|999=بريّة جديدة}}",
+       "newmessagesdifflinkplural": "{{PLURAL:$1التبديلة التالية|التبديلات التاليين}}",
+       "youhavenewmessagesmulti": "عندك بريّة جديدة في $1.",
        "editsection": "بدل",
        "editold": "بدل",
        "viewsourceold": "شوف الاصل",
        "viewsourcelink": "شوف العين",
        "editsectionhint": "إيديتي الصنف:$1",
        "toc": "محتويات",
+       "showtoc": "ورّي",
+       "hidetoc": "خبّي",
+       "collapsible-collapse": "خبّي",
+       "collapsible-expand": "ورّي",
+       "thisisdeleted": "راك باغي تشوف ولا ترجّع $1؟",
+       "viewdeleted": "شوف $1؟",
+       "restorelink": "{{PLURAL:$1|تبدال واحد مفاصي|$1 تبدالات مفاصيين|$1 تبدال مفاصي}}",
+       "feedlinks": "السيلان:",
+       "feed-invalid": "النوع تاع التلقيمة ماشي مصلاح.",
+       "feed-unavailable": "التلقيمات ما راهمش موجودين.",
        "site-rss-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": "الباجة",
        "nstab-user": "باجة{{GENDER:{{BASEPAGENAME}}|المستخدم|المستخدمة}}",
+       "nstab-media": "باجة تاع ميديا",
        "nstab-special": "باجه خوصوصيّة",
        "nstab-project": "باجه مشروع",
        "nstab-image": "ملف",
+       "nstab-mediawiki": "بريّة",
        "nstab-template": "مودال",
+       "nstab-help": "باجة تاع معاونة",
        "nstab-category": "تصنيف",
+       "nosuchaction": "الشي الّي طلبتهُ ما كاينش",
+       "nosuchactiontext": "الفعلة الّي مطلوبة فل URL ماشي مقبولة.\nبالاك ما دخّلتوش الـ URL كيما لازم ولا تاني تبّعتو كاش وصيل مغلوط.\nينجم تاني يكون كاين عُلّة فل لوجيسيال الّي مستعمل فـ {{SITENAME}}.",
+       "nosuchspecialpage": "هاد الباجة الخوصوصيّة ما كاينش منها",
+       "nospecialpagetext": "<strong>راك طلبت باجة خوصوصيّة ماشي صحيحة.</strong>\n\nتصيب الليستة تاع الباجات الخوصوصيّة في [[Special:SpecialPages|{{int:specialpages}}]].",
+       "error": "غلطة",
+       "databaseerror": "غلطة فل دخيرة تاع الخبيرات (DB)",
+       "databaseerror-text": "صرات غلطة عند المسقسية تاع الدخيرة تاع الخبيرات. هاد الشي ينجم يكون جاي من غلطة فل برنامج.",
+       "databaseerror-textcl": "صرات غلطة عند المسقسية تاع الدخيرة تاع الخبيرات.",
+       "databaseerror-query": "مسقسية : $1",
+       "databaseerror-function": "دالّة: $1",
+       "databaseerror-error": "غلطة: $1",
+       "laggedslavemode": "<strong>ردّ بالك:</strong> هاد الباجة تنجم تكون ما حاوياش التبدالات التاليين الّي ندارو.",
+       "readonly": "الدخيرة تاع الخبيرات راهي مغلوقة",
+       "enterlockreason": "حطّ السبّة تاع القفيل و المدّة تاعهُ بل ميز.",
+       "readonlytext": "الدخيرة تاع الخبيرات راهي مغلوقة على الدخلات الجديدة ولا التبدالات، بالاك علاجال كاش صيانة عاديّة، مور ماش غادي تعاود ترجع لل طبَع.\n\nالإيداري الّي دار هاد الشي راه يعطي التفسيرات هادي: $1",
        "missing-article": "الداتاباز ما صابتش باجه كان لازم تنصاب، الباجه هي \"$1\" $2.\n\nنورمالمو يصرا هذا مين اتبع فرق بيريمي والا وصيل تأريخ باجة ممحيه.\n\nإذا ما كانش هذا هو الحال همالا راك طحت في علة تاع البرمجية.\nمن فضلك سينياليها لواحد من[[Special:ListUsers/sysop|الإداريين]]، و أعطه مسار هذه الباجه.",
        "missingarticle-rev": "(رقم الفرسيون: $1)",
+       "missingarticle-diff": "(فرق بين: $1، $2)",
+       "readonly_lag": "الدخيرة تاع الخبرات راهي مقفولة بيدما السربايات التوناويّة يلحقو التوخار الّي عندهم معا السرباي اللولاني",
+       "internalerror": "غلطة دخلانيّة",
+       "internalerror_info": "غلطة دخلانيّة: $1",
+       "filecopyerror": "ما قدرش تنساخ الفيشي \"$1\" لل \"$2\"",
+       "filerenameerror": "ما قدرش تبدال السميّة تاع الفيشي \"$1\" لل \"$2\".",
+       "filedeleteerror": "ما قدرش تمحيتٰ الفيشي \"$1\".",
+       "directorycreateerror": "ما قدرش خلقان الدفتار \"$1\".",
+       "filenotfound": "ما قدرش مصيبتٰ الفيشي \"$1\".",
+       "unexpected": "قيمة ما شي مستنية : \"$1\"=\"$2\".",
+       "formerror": "غلطة: ما قدرش ترسال الستيمارة",
+       "badarticleerror": "هاد الفعلة ما تنجمش تندار ف هاد الباجة.",
+       "cannotdelete": "ما تنجّمش تمحيتٰ الباجة ولا الفيشي \"$1\".\nبالاك كان دار المحيان شي واحد من قبَل.",
+       "cannotdelete-title": "ما يمكنش محيان الباجة \"$1\".",
+       "delete-hook-aborted": "المحيان راه منحّي من عند كاش توسيعة.\nما عندنا حتا تفسار على هاد الشي.",
+       "no-null-revision": "ما يمكنش تخلاق مراجعة جديدة خاوية لل باجة \"$1\".",
        "badtitle": "عنوان عيان",
        "badtitletext": "عنوان الباجه المطلوب إما ماشي صحيح والا فارغ، وبالاك الوصيل بين اللغات والا بين البروجيات ماشي صحيح.\nبالاك فيه حروف ما تصلحش  باس يستعملوها فالعناوين.",
+       "perfcached": "الموطايات هادي راهي مخبّية و بالاك تاني يكون فات عليها الوقت. {{PLURAL:$1||ناتج واحد|زوج نواتج|$1 نواتج|$1 ناتج}} على الكتَر {{PLURAL:$1||مخبّي|مخبّيين}}.",
        "viewsource": "شوف الاصل",
        "yourname": "اسم المستخدم:",
        "yourpassword": "كلمة السر:",
        "remembermypassword": "اتفكر الدخول تاعي ب هاذ النافيكاتور (ب مدّة حدها{{PLURAL:$1||يوم واحد|يومين|$1 إيّام|$1 يوم}})",
        "login": "كونكسيون",
        "nav-login-createaccount": "تسجل/ اصنع حساب",
-       "loginprompt": "لازم تكون الكوكيز لديك ماكتيفيه باش تكونيكتي و تدخل ل{{SITENAME}}.",
        "userlogin": "تسجل/ اصنع حساب",
        "userlogout": "سجل خروج",
        "nologin": "ما عندكش حساب مسجل؟ '''$1'''.",
        "link_tip": "وصيلة داخليه",
        "extlink_sample": "http://www.example.com اسم الوصيلة",
        "extlink_tip": "وصيلة برانية (ما تنساش البديةhttp://)",
-       "headline_sample": "كتبة نتاع عنوان كبير",
+       "headline_sample": "كتبة تاع علوان كبير",
        "headline_tip": "عنوان من المستوى الثاني",
        "nowiki_sample": "دخل الكتبة مشي مستفة هنا",
        "nowiki_tip": "اهمل طريقةالويكي",
        "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": "← نسخة اللوله",
        "lineno": "سطر$1:",
        "compareselectedversions": "كومباري بين نسختين مخيرين",
        "editundo": "نحي",
-       "searchresults": "ريزيلته نتاع التفتاش",
+       "searchresults": "نتاج تاع التفتيشة",
        "searchresults-title": "ريزيلته تاع التحواس \"$1\"",
        "prevn": "{{PLURAL:$1|précédente|$1 اللولانيين}}",
        "nextn": "{{PLURAL:$1|suivante|$1 التاليين}}",
        "searchmenu-exists": "'''كاين باجه اسمها « [[:$1]] » في هاذ الويكي'''",
        "searchmenu-new": "'''أصنع الباجه « [[:$1|$1]] » في هذ الويكي !'''",
        "searchprofile-articles": "باجه تع محتوى",
-       "searchprofile-project": "باجه تع المعونه و البروجي",
        "searchprofile-images": "ميلتيميديا",
        "searchprofile-everything": "كلش",
        "searchprofile-advanced": "تفتاش متقدم",
        "searchprofile-articles-tooltip": "فتش في $1",
-       "searchprofile-project-tooltip": "فتش في  $1",
        "searchprofile-images-tooltip": "فتش على ملفات ميلتيميديا",
        "searchprofile-everything-tooltip": "فتش في قاع السيت (حتى في باجات المناقشه)",
        "searchprofile-advanced-tooltip": "خير إسباسات الأسامي للتفتاش",
        "upload": "طلع فيشي",
        "uploadlogpage": "ريجيستر رفع الفيشيات",
        "filedesc": "ملخص",
-       "uploadedimage": "راه طلع \"[[$1]]\"",
        "license": "ترخيص:",
        "license-header": "ترخيص:",
        "file-anchor-link": "ملف",
        "sharedupload-desc-here": "هاذ الملف جاي من $1. يمكن يكون مستعمل من بروجيات وحد أخرين.\nالتوصيف نتاعو في [$2 باجت الصفات] محطوطه هنا لتحت.",
        "randompage": "باجة على الزهر",
        "statistics": "إحصاويّات",
-       "nbytes": "$1 اوكتي{{PLURAL:$1||s}}",
+       "nbytes": "{{PLURAL:$1|بايت 1|$1 بايت}}",
        "nmembers": "$1 اعضاء{{PLURAL:$1||s}}",
        "prefixindex": "كامل الباجات الباديه ب",
        "usercreated": "{{GENDER:$3|صنعه|صنعته}} في $1 الساعة $2",
        "booksources-go": "اذهب",
        "log": "ريجيسترات العمليات",
        "allpages": "قاع الباجات",
-       "alphaindexline": "$1 إلى $2",
        "allarticles": "قاع الباجات",
        "allpagessubmit": "روح",
        "categories": "تصنيفات",
        "linksearch-line": "$1 موصولة من $2",
        "listgrouprights-members": "(ليسته الأعضاء)",
        "emailuser": "ابعث بريه لهاذ المستخدم",
-       "watchlist": "ليستة نتاع التابعه",
-       "mywatchlist": "ليستة نتاع التابعه",
+       "watchlist": "ليستة تاع المتابعة",
+       "mywatchlist": "ليستة تاع المتابعة",
        "watchlistfor2": "ل$1 ($2)",
        "watch": "تبع",
        "unwatch": "ما تزيدش تعس",
        "sp-contributions-blocklog": "ريجيسترالمنع",
        "sp-contributions-uploads": "مرفوعات",
        "sp-contributions-logs": "ريجيسترات",
-       "sp-contributions-talk": "نقاش",
+       "sp-contributions-talk": "تقرعيج",
        "sp-contributions-search": "تفتاش المشاركات",
        "sp-contributions-username": "عنوان أيبي والال اسم مستخدم:",
-       "sp-contributions-toponly": "ما تبين غير المشاركات التوالا نتاع المقالات",
+       "sp-contributions-toponly": "ما تورّي غير المشاركات التوالا تاع المقالات",
        "sp-contributions-submit": "تفتاش",
        "whatlinkshere": "واش يوصل هنا",
        "whatlinkshere-title": "الباجات اللي تقين في \"$1\"",
        "tooltip-pt-mycontris": "ليسته نتع مساهماتك",
        "tooltip-pt-login": "مادابيك تسجل الدخول تاعك، بصّح ماشي ملزوم عليك",
        "tooltip-pt-logout": "سجل خروج",
-       "tooltip-ca-talk": "نقاش على باجت المحتوى",
+       "tooltip-ca-talk": "تقرعيج على باجتٰ المحتاوا",
        "tooltip-ca-edit": "تنجم تحرر هاذ الباجه ،ماذابيك تستعمل قفله المراجعه قبل ما تحفظ",
        "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": "اÙ\82Ù\84ع Ù\87اذ Ø§Ù\84باجÙ\87 Ù\85Ù\86 Ø§Ù\84Ù\84Ù\8aستÙ\87 Ù\86تاع التتباع",
+       "tooltip-ca-watch": "زيد هذ الباجة لل ليستة تاعك تاع التتباع",
+       "tooltip-ca-unwatch": "اÙ\82Ù\84ع Ù\87اد Ø§Ù\84باجة Ù\85Ù\86Ù\84 Ù\84Ù\8aستة ØªØ§Ø¹Ù\83 تاع التتباع",
        "tooltip-search": " فتّش في {{SITENAME}}",
        "tooltip-search-go": "روح الباجه عندها نفس الآسم إذا كانت كاينه",
        "tooltip-search-fulltext": "فتّش على باجه بهاد الكتبة",
        "tooltip-n-mainpage": "زور الباجه اللوله",
        "tooltip-n-mainpage-description": "زور الباجه لوله",
        "tooltip-n-portal": "على الپروجي،واش تنجم تدير، وين تصيب واش تحتاج",
-       "tooltip-n-currentevents": "تحÙ\88اس Ø¹Ù\84Ù\89 Ù\85عÙ\84Ù\88Ù\85ات Ø£Ø³Ø§Ø³Ù\8aØ© Ù\84صÙ\88اÙ\84Ø­ ØµØ±Ø§Ù\88 Ø°Ø±Ù\88Ù\83",
+       "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": "طلّع باجه على الزهر",
        "tooltip-n-help": "بلاصة المعونة",
-       "tooltip-t-whatlinkshere": "ليسته نتاع قاع باجات المحتوى الي توصل هنا",
-       "tooltip-t-recentchangeslinked": "ليسته نتاع التبديلات التواله نتاع الباجات الي عندهم علاقه بهاذي",
-       "tooltip-feed-atom": "سيلان آتوم نتاع الباجه",
+       "tooltip-t-whatlinkshere": "ليستة تاع كاع الباجات تاع المحتاوا الي توصّل لهنا",
+       "tooltip-t-recentchangeslinked": "ليستة تاع التبديلات التوالا تاع الباجات الّي عندهم رباط معا هادي",
+       "tooltip-feed-atom": "سيلان آتوم تاع هاد الباجة",
        "tooltip-t-contributions": "شوفان ليسته مساهمات هاذا المستخدم",
        "tooltip-t-emailuser": "أرسل بريه لهاذ المستخدم",
        "tooltip-t-upload": "أرسل تصويرة و إلا أي ملف ميديا للسرفر",
        "tooltip-t-specialpages": "ليستة تاع كامل الباجات الخصوصيّة",
        "tooltip-t-print": "نسخه لهاذ الباجه قابله للطبيع",
-       "tooltip-t-permalink": "توصيله دايمه رايحه لهاذ النسخة نتاع الباجة",
+       "tooltip-t-permalink": "وصيل دايم رايح ل هاد النسخة تاع الباجة",
        "tooltip-ca-nstab-main": "شوف باجه المحتوى",
        "tooltip-ca-nstab-user": "شوف باجت المستعمل",
        "tooltip-ca-nstab-special": "هذه الباجه خصوصيه،ما تقدرش تبدل فيها",
        "tooltip-minoredit": "ماركي هاذا تبديل صغير",
        "tooltip-save": "سجل تبديلات نتاعك",
        "tooltip-preview": "بين التغييرات نتاعك، من فضلك استخدم هذا قبل ما تنشر!",
-       "tooltip-diff": "تخلي الشوفان نتاع التبديلات اللي ندارو.",
+       "tooltip-diff": "ورّي التبدالات الّي راك درتهم فل نصّ.",
        "tooltip-compareselectedversions": "شوف الفروق بين نسختين مخيرين من هاذ الباجه.",
-       "tooltip-watch": "زÙ\8aد Ù\87Ø° Ø§Ù\84باجÙ\87 Ù\84Ù\84Ù\8aستتÙ\83 Ù\86تاع التتباع",
-       "tooltip-rollback": "يولي : بدركة وحده تآنيلي التبديله و إلا التبديلات نتاع المساهم التالي",
+       "tooltip-watch": "زÙ\8aد Ù\87اد Ø§Ù\84باجة Ù\84Ù\84 Ù\84Ù\8aستة ØªØ§Ø¹Ù\83 تاع التتباع",
+       "tooltip-rollback": "\"نحّي\" : ب ضركة وحدة تآنيلي التبديلة ولا التبديلات تاع المساهم التالي",
        "tooltip-undo": "\"نحّي\" فاصي هاد الـمعاودة و حلّ تاقة تاع تبدال بشوفه قبلانيّه. تخلّي باش ترجع لل معاوده التاليه و تزيد الـسبّة علاش فل قابسه تاع الـحويصله.",
        "tooltip-summary": "دخل تلخيص صغير",
        "previousdiff": "→ التعديل الي قبل",
        "file-nohires": "ما كانش دقه اكثر من هاك",
        "svg-long-desc": "فيشيي SVG، أبعاده $1 × $2 بكسل، تاي الفيشي : $3",
        "show-big-image": "تصويرة دقة عالية",
-       "bad_image_list": "الفورمه كيما التابعة:\nما كاين غير السطور الّي باديين بل *، الّي يكونو معدودين\nالـوصيل الـلوّل نتاع سطر لازم تكون تاع تصويرة ضايعة.\nكامل الوصيلات لخرين الّي فل سطر، يكونو معدودين كلّي تتنيّات، بل كي الباجات وين الـفيشي يكون باين.",
+       "bad_image_list": "الفورمة راهي كيما واش يتبع:\nما كاين غير السطور الّي باديين بل *، الّي يكونو معدودين\nالـوصيل الـلوّل تاع سطر لازم كون تاع تصويرة ضايعة.\nكامل الوصيلات لخرين الّي فل سطر، يكونو معدودين كلّي تتنيّات، بل متال باجات وين الـتصويرة تنجم تبان.",
        "metadata": "بايان ميتا",
-       "metadata-help": "هذا الملف راه فيه معلومات زيادة، بالاك تكون انزادت من عند صواره نيميريك ولا سكانر مين صنع الملف.\nالأصلي، شي تفاصيل بالاك ما تعبرش على الملف المعدل.",
-       "metadata-fields": "غادÙ\8a Ù\8aÙ\86عرض Ø§Ù\84Ø­Ù\82Ù\84 Ù\86تاع Ù\85عطÙ\8aات Ø§Ù\84Ù\85Ù\8aتا Ø§Ù\84Ù\83اÙ\8aÙ\86Ù\87 Ù\81Ù\8a Ù\87اذ Ø§Ù\84برÙ\8aÙ\87 Ù\81Ù\8a Ø¨Ø§Ø¬Ù\87 Ø§Ù\84تصÙ\88Ù\8aرة Ù\85Ù\86Ù\8aÙ\86 Ù\8aÙ\83Ù\88Ù\86 Ø¬Ø¯Ù\88Ù\84 Ù\85عطÙ\8aات Ø§Ù\84Ù\85Ù\8aتا Ù\85Ø·Ù\88Ù\8aاÙ\8b.\nاÙ\84Ø­Ù\82Ù\88Ù\84 Ù\84خرÙ\87 ØªÙ\83Ù\88Ù\86 Ù\85خبÙ\8aØ© Ø¨Ø§Ø± ديفو.\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": "هذا الملف راه فيه خبيرات زايدين، بالاك تكون انزادت من عند صواره نيميريك ولا سكانر مين صنع الملف.\nالأصلي، شي تفاصيل بالاك ما تعبرش على الملف المعدل.",
+       "metadata-fields": "اÙ\84Ø­Ù\82Ù\88Ù\84 ØªØ§Ø¹ Ø§Ù\84Ù\85Ù\8aتا Ù\85عطÙ\8aÙ\91ات ØªØ§Ø¹ ØªØµØ§Ù\88ر Ø§Ù\84Ù\91Ù\8a Ù\8aÙ\83Ù\88Ù\86Ù\88 Ù\81 Ù\87اد Ø§Ù\84برÙ\8aÙ\91Ø© ØºØ§Ø¯Ù\8a Ù\8aÙ\86حطÙ\91Ù\88 Ù\81Ù\84 Ø¨Ø§Ø¬Ø© ØªØ§Ø¹ Ø§Ù\84تÙ\88صاÙ\81 ØªØ§Ø¹ Ø§Ù\84تصÙ\88Ù\8aرة Ù\85Ù\86Ù\8aÙ\86 Ù\8aÙ\83Ù\88Ù\86 Ø§Ù\84جدÙ\88Ù\84 ØªØ§Ø¹  Ø§Ù\84Ù\85Ù\8aتااÙ\84Ù\85عطÙ\8aات Ù\85Ø·Ù\88Ù\8a.\nاÙ\84Ø­Ù\82Ù\88Ù\84 Ù\84خرة Ù\8aÙ\83Ù\88Ù\86Ù\88 Ù\85خبÙ\8aÙ\8aÙ\86 Ø¨Ø§Ø±ديفو.\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",
        "watchlistall2": "لكل",
        "namespacesall": "لكل",
        "monthsall": "لكل",
index b8eaf38..770e261 100644 (file)
        "talkpagelinktext": "Ṫnaqeċ",
        "specialpage": "Ṣefḫa ĥaṣa",
        "personaltools": "Adawaṫ ċeĥṣiya",
-       "postcomment": "Seksyon jdida",
        "articlepage": "Ċof l-li fe ṣ-ṣefḫa",
        "talk": "Modakara",
        "views": "Afiċaj",
        "externaldberror": "kayn imma ċi ĥata' f-doĥol qaĝidaṫ l-bayanaṫ wlla rah ma msmoḫ-likċ baċ ṫḫddṫ l-ḫisab l-ĥariji taĝk.",
        "login": "Dĥel",
        "nav-login-createaccount": "Ṫkonékta / Ĥṫareĝ ċi konṫ",
-       "loginprompt": "ĥask tkon mĥddm l-cookies baċ ṫdĥol l-{{SITENAME}}.",
        "userlogin": "Ṫkonnékta / Ṣayeb ċi ḫsab",
        "userloginnocreate": "Ṫkonékta",
        "logout": "Ṫdékonékta",
        "searchprofile-advanced-tooltip": "qlleb ġi f-ċi nitaqaṫ",
        "search-result-size": "$1 ({{PLURAL:$2|kelma weḫda|$2 kelmaṫ}})",
        "search-result-category-size": "{{PLURAL:$1|ĝoḍw 1|$1 dl-aĝḍa'}} ({{PLURAL:$2|ṫṣnif fṛĝi 1|$2 d-ṫṣnifaṫ l-fṛĝiyya}}, {{PLURAL:$3|milef 1|$3 dl-milffaṫ}})",
-       "search-result-score": "lirtibat: $1%",
        "search-redirect": "(Ṫeḫwil $1)",
        "search-section": "(seksyon $1)",
        "search-suggest": "Waċ konṫi baġi ṫqol : $1",
        "uploadwarning": "tahdir rafaa",
        "uploadwarning-text": "afak bdl description dyal lmilaf ltaht ohawl awtani",
        "savefile": "sjjl had lfichier",
-       "uploadedimage": "øplowda \"[[$1]]\"",
-       "overwroteimage": "sift noskha jdida dyal \"[[$1]]\"",
        "uploaddisabled": "upload maatl",
        "copyuploaddisabled": "sift b URL makhdamch",
        "uploaddisabledtext": "sift dyal lfichier makhdamch",
        "duplicate-defaultsort": "'''ṫḫdir:''' saroṫ ṫrṫib fṫiṛaḍi \"$2\" faṫ saroṫ ṫrṫib fṫiṛaḍi \"$1\".",
        "version": "Noskha",
        "version-extensions": "limtidadat lmotabbata",
+       "version-skins": "skinat",
        "version-specialpages": "Ṣefḫa ĥaṣa",
        "version-parserhooks": "khatatif lmohllil",
        "version-variables": "lmotaghayyirat",
        "version-antispam": "wiqaya mn ṣ-ṣpam",
-       "version-skins": "skinat",
        "version-other": "okhra",
        "version-mediahandlers": "motahakkimat lmedia",
        "version-hooks": "lkhtatif",
index e04983e..6f52b4a 100644 (file)
@@ -8,7 +8,8 @@
                        "Meno25",
                        "Ouda",
                        "Ramsis II",
-                       "아라"
+                       "아라",
+                       "Oldstoneage"
                ]
        },
        "tog-underline": "حط خط تحت اللينكات:",
        "talkpagelinktext": "مناقشه",
        "specialpage": "صفحة مخصوصة",
        "personaltools": "ادوات شخصيه",
-       "postcomment": "قسم جديد",
        "articlepage": "بين صفحة المحتوى",
        "talk": "مناقشه",
        "views": "مناظر",
        "externaldberror": "يا إما فى حاجة غلط فى الدخول على قاعدة البيانات الخارجية أو انت مش مسموح لك تعمل تحديث لحسابك الخارجي.",
        "login": "دخول",
        "nav-login-createaccount": "تسجيل دخول / فتح حساب",
-       "loginprompt": "لازم تكون الكوكيز عندك مفعله علشان تقدر تدخل ل {{SITENAME}}.",
        "userlogin": "دخول / فتح حساب",
        "userloginnocreate": "دخول",
        "logout": "خروج",
        "searchprofile-advanced-tooltip": "دور فى النطاقات المخصصة",
        "search-result-size": "$1 ({{PLURAL:$2|1 كلمه|$2 كلام}})",
        "search-result-category-size": "{{PLURAL:$1|لا أعضاء|عضو واحد|عضوين|$1 أعضاء|$1 عضوًا|$1 عضو}} ({{PLURAL:$2|لا تصانيف فرعية|تصنيف فرعى واحد|تصنيفين فرعيين|$2 تصنيفات فرعية|$2 تصنيف فرعى|$2 تصنيف فرعى}} و{{PLURAL:$3|لا ملفات|ملف واحد|ملفين|$3 ملفات|$3 ملف|$3 ملف}})",
-       "search-result-score": "الارتباط: $1%",
        "search-redirect": "(تحويله $1)",
        "search-section": "(جزء $1)",
        "search-suggest": "قصدك: $1",
        "uploadwarning": "تحذير التحميل",
        "uploadwarning-text": "لو سمحت عدل وصف الملف اللى تحت وحاول تانى.",
        "savefile": "حفظ الملف",
-       "uploadedimage": "اتحمل \"[[$1]]\"",
-       "overwroteimage": "اتحملت  نسخة جديدة من \"[[$1]]\"",
        "uploaddisabled": "التحميل متعطل",
        "uploaddisabledtext": "تحميل الملفات متعطل.",
        "php-uploaddisabledtext": "تحميل ملفات PHP متعطل. لو سمحت اتأكدن من إعدادات تحميل الملفات.",
        "watchlist-details": "{{PLURAL:$1|$1 صفحه|$1 صفحه}} فى قايمه مراقبتك، بدون عد صفحات المناقشه.",
        "wlheader-enotif": "*خاصية الاعلام بالايميل متفعلة",
        "wlheader-showupdated": "الصفحات اللى اتغيرت  بعد زيارتك ليها اخر مرة معروضة بالخط '''العريض'''",
+       "wlnote": "تحت فى {{PLURAL:$1|آخر تغيير|آخر '''$1''' تغيير}} فى آخر {{PLURAL:$2|ساعه|'''$2''' ساعه}}، من الوقت $3، $4.",
        "wlshowlast": "عرض اخر $1 ساعات $2 ايام $3",
        "watchlist-options": "اختيارات قايمة المراقبة",
        "watching": "بيراقب...",
        "timezone-utc": "يو تى سى",
        "unknown_extension_tag": "تاج بتاع امتداد مش معروف \"$1\"",
        "duplicate-defaultsort": "تحزير: زرار الترتيب الاوتوماتيكي\"$2\" بيوقف زرار الترتيب الاوتوماتيكي\"$1\" القديم.",
-       "version": "نسخه",
+       "version": "نسخة",
        "version-extensions": "الامتدادات المتثبتة",
        "version-specialpages": "صفحات مخصوصة",
        "version-parserhooks": "خطاطيف البريزر",
index 1607c1f..208723e 100644 (file)
@@ -29,7 +29,7 @@
        "tog-editsectiononrightclick": "অনুচ্ছেদৰ শিৰোনামাত ৰাইট্‌ ক্লিক টিপি সম্পাদনা কৰাটো সক্ৰিয় কৰক",
        "tog-watchcreations": "মই সৃষ্টি সকলো পৃষ্ঠা মোৰ লক্ষ্য-তালিকাত যোগ কৰক",
        "tog-watchdefault": "মই সম্পাদনা কৰা সকলো পৃষ্ঠা মোৰ লক্ষ্য-তালিকাত যোগ কৰক",
-       "tog-watchmoves": "মই স্থানান্তৰ কৰা সকলো পৃষ্ঠা মোৰ লক্ষ্য-তালিকাত যোগ কৰক",
+       "tog-watchmoves": "মà¦\87 à¦¸à§\8dথানানà§\8dতৰ à¦\95ৰা à¦¸à¦\95লà§\8b à¦ªà§\83ষà§\8dঠা à¦\86ৰà§\81 à¦«à¦¾à¦\87ল à¦®à§\8bৰ à¦²à¦\95à§\8dষà§\8dয-তালিà¦\95াত à¦¯à§\8bà¦\97 à¦\95ৰà¦\95",
        "tog-watchdeletion": "মই বিলোপ কৰা সকলো পৃষ্ঠা মোৰ লক্ষ্য-তালিকাত যোগ কৰক",
        "tog-minordefault": "সকলো সম্পাদনা অগুৰুত্বপূৰ্ণ বুলি নিজে নিজে চিহ্নিত কৰক",
        "tog-previewontop": "সম্পাদনা বাকছৰ ওপৰত খচৰা দেখুৱাওক",
        "talkpagelinktext": "কথা-বতৰা",
        "specialpage": "বিশেষ পৃষ্ঠা",
        "personaltools": "ব্যক্তিগত সৰঞ্জাম",
-       "postcomment": "নতুন অনুচ্ছেদ",
        "articlepage": "সমল পৃষ্ঠা চাওক",
        "talk": "আলোচনা",
        "views": "দৰ্শন",
        "hidetoc": "দেখুৱাব নালাগে",
        "collapsible-collapse": "সংকোচন",
        "collapsible-expand": "বহলাওক",
+       "confirmable-yes": "হয়",
+       "confirmable-no": "নহয়",
        "thisisdeleted": "$1 চাওক বা সলনি কৰক?",
        "viewdeleted": "$1 চাওক?",
        "restorelink": "{{PLURAL:$1| এটা বিলুপ্ত সম্পাদনা|$1 টা বিলুপ্ত সম্পাদনা}}",
        "invalidtitle-knownnamespace": "নামস্থান \"$2\" আৰু পাঠ্য \"$3\" থকা অবৈধ শিৰোনাম",
        "invalidtitle-unknownnamespace": "অজ্ঞাত নামস্থান সংখ্যা $1 আৰু পাঠ্য \"$2\" থকা অবৈধ শিৰোনাম",
        "exception-nologin": "প্ৰৱেশ কৰা নাই",
-       "exception-nologin-text": "এই কামৰ বাবে আপুনি [[Special:Userlogin|লগ্‌ ইন]] কৰাটো বাধ্যতামূলক।",
+       "exception-nologin-text": "এই কামৰ বাবে আপুনি লগ্‌ ইন কৰাটো বাধ্যতামূলক।",
        "exception-nologin-text-manual": "এই কামৰ বাবে অনুগ্ৰহ কৰি $1 কৰক।",
        "virus-badscanner": "ভুল কনফিগাৰেচন: অজ্ঞাত ভাইৰাছ স্কেনাৰ: ''$1''",
        "virus-scanfailed": "স্কেন অসফল (কোড $1)",
        "externaldberror": "কোনো প্ৰামাণ্যকৰণ তথ্যকোষৰ ত্ৰুটি ঘটিছে নতুবা আপোনাৰ বৰ্হি-একাউণ্ট নৱীকৰণ কৰাৰ অনুমতি নাই ।",
        "login": "প্ৰৱেশ",
        "nav-login-createaccount": "প্ৰৱেশ/সদস্যভুক্তি",
-       "loginprompt": "{{SITENAME}}ত প্ৰৱেশ কৰিবলৈ আপুনি কুকিজ্ সক্ৰিয় থাকিব লাগিব।",
        "userlogin": "প্ৰৱেশ/সদস্যভুক্তি",
        "userloginnocreate": "প্ৰৱেশ",
        "logout": "প্ৰস্থান",
        "userlogin-resetlink": "আপোনাৰ প্ৰৱেশ তথ্য পাহৰিছে?",
        "userlogin-resetpassword-link": "আপোনাৰ গুপ্তশব্দ পাহৰিছে?",
        "userlogin-helplink2": "প্ৰৱেশ সংক্ৰান্তীয় সাহায্য",
-       "userlogin-loggedin": "আপুনি ইতিমধ্যে {{GENDER:$1|$1}} হিচাপে প্ৰৱেশ কৰিছে। তলৰ আন সদস্যৰূপে প্ৰৱেশ কৰিবলৈ তলৰ প্ৰপত্ৰ ব্যৱহাৰ কৰক।",
-       "userlogin-createanother": "আন এটা একাউণ্ট সৃষ্টি কৰক",
        "createacct-emailrequired": "ই-মেইল ঠিকনা",
        "createacct-emailoptional": "ই-মেইল ঠিকনা (বৈকল্পিক)",
        "createacct-email-ph": "আপোনাৰ ই-মেইল ঠিকনা লিখক",
        "noemail": "\"$1\" সদস্যজনৰ কোনো ই-মেইল ঠিকনা সঞ্চিত কৰা নাই।",
        "noemailcreate": "আপুনি এটা সঠিক ই-মেইল ঠিকনা দিব লাগিব",
        "passwordsent": "\"$1\" ৰ ই-মেইল ঠিকনাত নতুন গুপ্তশব্দ এটা পঠোৱা হৈছে। অনুগ্ৰহ কৰি সেয়া পোৱাৰ পাছত পুনৰ প্ৰৱেশ কৰক।",
-       "blocked-mailpassword": "à¦\86পà§\8bনাৰ à¦\86à¦\87পি à¦ à¦¿à¦\95নাৰ à¦ªà§°à¦¾ à¦¸à¦®à§\8dপাদনা à¦\95ৰা à¦¬à¦¾à§°à¦£ à¦\95ৰা à¦¹à§\88à¦\9bà§\87, à¦\8fনà§\87 à¦\85ৱসà§\8dথাত à¦¦à§\81ৰà§\8dবà§\8dযৱহাৰ à§°à§\8bধ à¦\95ৰিবলà§\88 à¦\97à§\81পà§\8dতশবà§\8dদ à¦ªà§\81নà¦\83à¦\89দà§\8dধাৰ à¦\95ৰা à¦¸à§\81বিধাতà§\8b বাতিল কৰা হৈছে।",
+       "blocked-mailpassword": "à¦\86পà§\8bনাৰ à¦\86à¦\87পি à¦ à¦¿à¦\95নাৰ à¦ªà§°à¦¾ à¦¸à¦®à§\8dপাদনা à¦\95ৰা à¦¬à¦¾à§°à¦£ à¦\95ৰা à¦¹à§\88à¦\9bà§\87, à¦\8fনà§\87 à¦\85ৱসà§\8dথাত à¦¦à§\81ৰà§\8dবà§\8dযৱহাৰ à§°à§\8bধ à¦\95ৰিবলà§\88 à¦\97à§\81পà§\8dতশবà§\8dদ à¦ªà§\81নà¦\83à¦\89দà§\8dধাৰ à¦\95ৰা à¦¸à§\81বিধাà¦\93 বাতিল কৰা হৈছে।",
        "eauthentsent": "সঞ্চিত ই-মেইল ঠিকনালৈ নিশ্চিতকৰণ ই-মেইল এখন পঠিওৱা হৈছে।\nএকাউণ্টটোলৈ আন ই-মেইল পঠিওৱাৰ আগতে আপোনাৰ সদস্যতা নিশ্চিত কৰিবলৈ সেই ই-মেইলত দিয়া নিৰ্দেশনা আপুনি অনু্সৰণ কৰিব লাগিব।",
        "throttled-mailpassword": "যোৱা {{PLURAL:$1|এঘণ্টাত|$1 ঘণ্টাত}} এখন গুপ্তশব্দ উদ্ধাৰ ইমেইল পঠিওৱা হৈছে।\nঅবৈধ ব্যৱহাৰ ৰোধ কৰিবলৈ প্ৰতি {{PLURAL:$1|এঘণ্টাত|$1 ঘণ্টাত}} এবাৰহে গুপ্তশব্দ উদ্ধাৰ ইমেইল পঠিওৱা হ'ব।",
        "mailerror": "ই-মেইল পঠিওৱাত সমস্যা হৈছে: $1",
        "login-throttled": "আপুনি স‍ম্প্ৰতি অজস্ৰবাৰ লগ্‌-ইনৰ প্ৰয়াস কৰিছে ।\nঅনুগ্ৰহ কৰি $1 সময়ৰ পিছত আকৌ চেষ্টা কৰক ।",
        "login-abort-generic": "আপোনাৰ প্ৰৱেশ অসফল হৈছে- বাতিল কৰা হ’ল",
        "loginlanguagelabel": "ভাষা: $1",
-       "suspicious-userlogout": "আপোনাৰ প্ৰস্থানৰ অনুৰোধ বাতিল কৰা হৈছে কাৰণ হয়তো আপোনাৰ ব্ৰাউজাৰ অসম্পূৰ্ণ নতুবা পূৰ্বৱতী তথ্য পঠাইছে ।",
+       "suspicious-userlogout": "à¦\86পà§\8bনাৰ à¦ªà§\8dৰসà§\8dথানৰ à¦\85নà§\81ৰà§\8bধ à¦¬à¦¾à¦¤à¦¿à¦² à¦\95ৰা à¦¹à§\88à¦\9bà§\87 à¦\95াৰণ à¦¹à¦¯à¦¼à¦¤à§\8b à¦\86পà§\8bনাৰ à¦¬à§\8dৰাà¦\89à¦\9cাৰ à¦\85সমà§\8dপà§\82ৰà§\8dণ à¦¨à¦¤à§\81বা à¦ªà§\82ৰà§\8dবৱতà§\80 à¦¤à¦¥à§\8dয à¦ªà¦ à¦¿à¦¯à¦¼à¦¾à¦\87à¦\9bà§\87 à¥¤",
        "createacct-another-realname-tip": "প্ৰকৃত নাম দিয়াটো বৈকল্পিক।\nআপুনি নামটো দিলে সেইটো আপোনাৰ বৰঙণিসমূহৰ বাবে স্বীকৃতি প্ৰদানত ব্যৱহাৰ কৰা হ'ব।",
        "pt-login": "প্ৰৱেশ",
        "pt-login-button": "প্ৰৱেশ",
        "preview": "খচৰা",
        "showpreview": "খচৰা চাওক",
        "showdiff": "সালসলনিবোৰ দেখুৱাওক",
+       "blankarticle": "<strong>Warning:</strong>আপুনি সৃষ্টি কৰি থকা পৃষ্ঠাটো খালি।\nযদি আপুনি \"{{int:savearticle}}\" বুটামটোত আকৌ ক্লিক কৰে তেন্তে বিষয়বস্তু অবিহনেই পৃষ্ঠাটো সৃষ্টি হ'ব।",
        "anoneditwarning": "<span style=\"color:red;\">'''সাৱধান:''' আপুনি প্ৰৱেশ কৰা নাই ।</span> \nএই পৃষ্ঠাৰ ইতিহাসত আপোনাৰ আই পি ঠিকনা সংৰক্ষিত কৰা হ'ব।",
        "anonpreviewwarning": "''আপুনি প্ৰৱেশ কৰা নাই। আপোনাৰ সম্পাদনা সাঁচিলে আপোনাৰ আই-পি ঠিকনা এই পৃষ্ঠাৰ ইতিহাসত সংৰক্ষিত হ'ব।\"",
        "missingsummary": "'''স্মাৰক:''' আপুনি সম্পাদনা সাৰাংশ দিয়া নাই।\nআপুনি আৰু এবাৰ সংৰক্ষণৰ বাবে ক্লিক কৰিলে সাৰাংশৰ অবিহনে সংৰক্ষিত হব।",
        "summary-preview": "সাৰাংশৰ খচৰা:",
        "subject-preview": "বিষয়/শিৰোনামাৰ খচৰা:",
        "blockedtitle": "সদস্যজনক অৱৰোধ কৰা হৈছে",
-       "blockedtext": "'''আপোনাৰ সদস্যনাম অথবা আই-পি ঠিকনা অৱৰোধ কৰা হৈছে ।'''\n\n$1ৰ দ্বাৰা এই অৱৰোধ কৰা হৈছে ।\nইয়াৰ বাবে দিয়া কাৰণ হৈছে ''$2'' ।\n\n* অৱৰোধ আৰম্ভণি: $8\n* অৱৰোধ সমাপ্তি: $6\n* অৱৰোধ কৰা হৈছে: $7\n\nআপুনি এই অৱৰোধৰ বিষয়ে আলোচনা কৰিবলৈ $1 বা [[{{MediaWiki:Grouppage-sysop}}|প্ৰবন্ধকৰ]] লগত সম্পৰ্ক স্থাপন কৰিব পাৰে ।\nআপুনি যেতিয়ালৈ [[Special:Preferences|সদস্য পছন্দ]] পৃষ্ঠাত আপোনাৰ ই-মেইল ঠিকনা নিদিয়ে তেতিয়ালৈ ’সদস্যক ই-মেইল পঠাওক’ সুবিধাতো ব্যৱহাৰ কৰিব নোৱাৰিব, আৰু আপোনাক এয়া কৰিবলৈ ৰোধ কৰা হোৱা নাই ।\nআপোনাৰ এতিয়াৰ আই-পি ঠিকনা হল $3, আৰু আপোনাৰ অবৰোধ ক্ৰমিক হৈছে #$5 ।\nএই বিষয়ে হোৱা আলোচনাত ইয়াৰ সবিশেষ সদৰী কৰে যেন।",
+       "blockedtext": "'''আপোনাৰ সদস্যনাম অথবা আই-পি ঠিকনা অৱৰোধ কৰা হৈছে।'''\n\n$1ৰ দ্বাৰা এই অৱৰোধ কৰা হৈছে ।\nইয়াৰ বাবে দিয়া কাৰণ হৈছে ''$2'' ।\n\n* অৱৰোধ আৰম্ভণি: $8\n* অৱৰোধ সমাপ্তি: $6\n* অৱৰোধ কৰা হৈছে: $7\n\nআপুনি এই অৱৰোধৰ বিষয়ে আলোচনা কৰিবলৈ $1 বা [[{{MediaWiki:Grouppage-sysop}}|প্ৰশাসকৰ]] লগত সম্পৰ্ক স্থাপন কৰিব পাৰে ।\nআপুনি যেতিয়ালৈ [[Special:Preferences|সদস্য পছন্দ]] পৃষ্ঠাত আপোনাৰ ই-মেইল ঠিকনা নিদিয়ে তেতিয়ালৈ ’সদস্যক ই-মেইল পঠিয়াওক’ সুবিধাতো ব্যৱহাৰ কৰিব নোৱাৰিব, আৰু আপোনাক এয়া কৰিবলৈ ৰোধ কৰা হোৱা নাই ।\nআপোনাৰ এতিয়াৰ আই-পি ঠিকনা হল $3, আৰু আপোনাৰ অৱৰোধ ক্ৰমিক হৈছে #$5 ।\nএই বিষয়ে হোৱা আলোচনাত ইয়াৰ সবিশেষ সদৰী কৰে যেন।",
        "autoblockedtext": "আপোনাৰ আই-পি ঠিকনা নিজে নিজে অৱৰোধিত হৈছে, কাৰণ ইয়াক কোনোবাই ব্যৱহাৰ কৰি থাকোতে $1ৰ দ্বাৰা অৱৰোধ কৰা হৈছে।\nইয়াৰ বাবে দিয়া কাৰণ হৈছে:\n\n:''$2''\n\n* অৱৰোধ আৰম্ভণি:  $8\n* অৱৰোধ সমাপ্তি: $6\n* অৱৰোধ কৰা হৈছে: $7\n\nআপুনি এই অবৰোধৰ বিষয়ে আলোচনা কৰিবলৈ $1 বা [[{{MediaWiki:Grouppage-sysop}}|প্ৰশাসক]]ৰ লগত সম্পৰ্ক স্থাপন কৰিব পাৰে ।\n\nআপুনি যেতিয়ালৈ [[Special:Preferences|সদস্য পছন্দ]] পৃষ্ঠাত আপোনাৰ ই-মেইল ঠিকনা নিদিয়ে তেতিয়ালৈ ’সদস্যক ই-মেইল পঠাওক’ সুবিধাতো ব্যৱহাৰ কৰিব নোৱাৰে। আপোনাক এয়া কৰিবলৈ ৰোধ কৰা হোৱা নাই ।\nআপোনাৰ এতিয়াৰ আই পি ঠিকনা হৈছে $3, আৰু আপোনাৰ অৱৰোধ ক্ৰমিক হৈছে $5 ।\nএই বিষয়ে হোৱা আলোচনাত ইয়াক ব্যৱহাৰ কৰিবলৈ অনুৰোধ কৰা হ’ল।",
        "blockednoreason": "কাৰণ দিয়া নাই",
        "whitelistedittext": "সম্পাদনা কৰিবলৈ $1 কৰক ।",
        "missing-revision": "\"{{FULLPAGENAME}}\" নামৰ পৃষ্ঠাৰ #$1 সংশোধনৰ অস্তিত্ব নাই।\n\nসাধাৰণতে বিলোপ কৰা এখন পৃষ্ঠাৰ পুৰণা ইতিহাস লিংক অনুসৰণ কৰিলে এনে হয়।\n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} বিলোপন ল'গ]ত অধিক তথ্য পাব।",
        "userpage-userdoesnotexist": "\"<nowiki>$1</nowiki>\" নামৰ সদস্য একাউন্ট নিবন্ধিত নহয় ।\nঅনুগ্ৰহ কৰি চাওক আপুনি এই পৃষ্ঠা সৃষ্টি/সম্পাদনা কৰিব বিচাৰিছে নেকি ।",
        "userpage-userdoesnotexist-view": "সদস্য একাউন্ট ''$1'' পঞ্জীভূত নহয়",
-       "blocked-notice-logextract": "বৰ্তমানে এই সদস্যক বাৰণ কৰা হৈছে ।\nপ্ৰসংগক্ৰমে সাম্প্ৰতিক বাৰণ সূচী তলত দিয়া হ'ল ।",
+       "blocked-notice-logextract": "বৰ্তমানে এই সদস্যক বাৰণ কৰা হৈছে।\nআপোনাৰ সুবিধাৰ্থে সাম্প্ৰতিক বাৰণ সূচী তলত দিয়া হ'ল ।",
        "clearyourcache": "'''টোকা:''' সাঁচি ৰখাৰ পিছত পৰিৱৰ্তনখিনি চাবৰ বাবে আপুনি আপোনাৰ ব্ৰাউজাৰৰ কেচ্‌ (cache) অগ্ৰাহ্য কৰিব লগা হ’ব পাৰে।\n* '''Firefox / Safari: ''' ''Shift'' ধৰি ৰাখি ''Reload'' ক্লিক কৰক, নাইবা ''Ctrl-F5'' বা ''Ctrl-R'' টিপক (এপল মেকৰ বাবে ''⌘-R'')\n* '''Google Chrome:''' ''Ctrl-Shift-R'' টিপক (এপল মেকৰ বাবে ''⌘-Shift-R'' )\n* '''Internet Explorer:''' ''Ctrl'' ধৰি ৰাখি ''Refresh'' ক্লিক কৰক, অথবা ''Ctrl-F5'' টিপক\n* '''Opera:''' ''Tools→Preferences'' ত গৈ কেচ্‌ মচি পেলাওক",
        "usercssyoucanpreview": "'''পৰামৰ্শ:''' \"{{int:showpreview}}\" বুটাম ব্যৱহাৰ কৰি সাঁচি ৰখাৰ আগতে আপোনাৰ নতুন CSS পৰীক্ষা কৰক ।",
        "userjsyoucanpreview": "'''পৰামৰ্শ:''' \"{{int:showpreview}}\" বুটাম ব্যৱহাৰ কৰি সাঁচি ৰখাৰ আগতে আপোনাৰ নতুন জাভালিপি পৰীক্ষা কৰক ।",
        "permissionserrorstext": "আপোনাৰ এই কামটো কৰিবলৈ অনুমতি নাই, যাৰ {{PLURAL:$1|কাৰণ|কাৰণসমূহ}} হ'ল:",
        "permissionserrorstext-withaction": "আপোনাৰ $2 কৰিবলৈ অনুমতি নাই, যাৰ {{PLURAL:$1|কাৰণ|কাৰণসমূহ}} হ'ল:",
        "recreate-moveddeleted-warn": "'''সাৱধান: আগতে বিলোপ কৰা পৃষ্ঠা এটা আপুনি পুনঃনিৰ্মাণ কৰি আছে। '''\n\nএই পৃষ্ঠাটো সম্পাদনা কৰা উচিত হব নে নহয় আপুনি বিবেচনা কৰি চাওক।\nএই পৃষ্ঠাটো বিলোপ আৰু স্থানান্তৰ কৰাৰ অভিলেখ আপোনাৰ সুবিধাৰ্থে ইয়াত দিয়া হৈছে।",
-       "moveddeleted-notice": "à¦\8fà¦\87 à¦ªà§\83ষà§\8dঠা à¦¬à¦¾à¦¤à¦¿à¦² à¦\95ৰা à¦¹à§\88à¦\9bà§\87 à¥¤\nপà§\83ষà§\8dঠাà¦\9fিৰ à¦¬à¦¾à¦¤à¦¿à¦² à¦\86ৰà§\81 à¦¸à§\8dথানানà§\8dতৰ à¦\95ৰা à¦\85ভিলà§\87à¦\96 à¦¤à¦²à¦¤ à¦¦à¦¿à¦¯à¦¼à¦¾ à¦¹'ল ।",
+       "moveddeleted-notice": "à¦\8fà¦\87 à¦ªà§\83ষà§\8dঠা à¦¬à¦¿à¦²à§\8bপ à¦\95ৰা à¦¹à§\88à¦\9bà§\87।\nপà§\83ষà§\8dঠাৰ à¦¬à¦¿à¦²à§\8bপ à¦\86ৰà§\81 à¦¸à§\8dথানানà§\8dতৰণ à¦\85ভিলà§\87à¦\96 à¦¤à¦²à¦¤ à¦¦à¦¿à¦¯à¦¼à¦¾ à¦¹'ল।",
        "log-fulllog": "সম্পূৰ্ণ অভিলেখ চাওক",
        "edit-hook-aborted": "হুকৰ দ্বাৰা সম্পাদনা প্ৰত্যাখ্যান কৰা হৈছে।\nইয়াৰ কোনো ব্যাখ্যা নাই।",
-       "edit-gone-missing": "পà§\83ষà§\8dঠাà¦\9fà§\8b à¦¨à¦¬à§\80à¦\95ৰণ à¦\95ৰিব à¦ªà§°à¦¾ à¦¨à¦\97â\80\99ল।\nসমà§\8dভৱতà¦\83 à¦ªà§\83ষà§\8dঠাà¦\96ন বিলোপ কৰা হৈছে।",
+       "edit-gone-missing": "পà§\83ষà§\8dঠাà¦\9fà§\8b à¦¨à¦¬à§\80à¦\95ৰণ à¦\95ৰিব à¦ªà§°à¦¾ à¦¨à¦\97â\80\99ল।\nসমà§\8dভৱতà¦\83 à¦ªà§\83ষà§\8dঠাà¦\9fà§\8b বিলোপ কৰা হৈছে।",
        "edit-conflict": "সম্পাদনা দ্বন্দ্ব।",
        "edit-no-change": "আপোনাৰ সম্পাদনা আওকাণ কৰা হৈছে, কাৰণ লেখাত কোনো তফাৎ নাই।",
        "postedit-confirmation-created": "পৃষ্ঠাটো সৃষ্টি কৰা হৈছে।",
        "parser-template-recursion-depth-warning": "সাঁচৰ পুনৰাবৃত্তি গভীৰতা সীমা ($1) তকৈ অধিক হৈছে",
        "language-converter-depth-warning": "ভাষা পৰিৱৰ্তকৰ গভীৰতা সীমাই ($1) অতিক্ৰম কৰিছে",
        "node-count-exceeded-category": "ন'ড-গণনা বেছি হোৱা পৃষ্ঠাসমূহ",
-       "node-count-exceeded-warning": "পৃষ্ঠাৰ ন'ড-গণনা বেছি হৈছে",
+       "node-count-exceeded-category-desc": "এই পৃষ্ঠাই সৰ্বোচ্চ ন'ড কাউণ্ট সীমা অতিক্ৰম কৰিছে।",
+       "node-count-exceeded-warning": "পৃষ্ঠাৰ ন'ড গণনা বেছি হৈছে",
        "expansion-depth-exceeded-category": "বিস্তৃতি গভীৰতা বেছি হোৱা পৃষ্ঠা",
        "expansion-depth-exceeded-warning": "পৃষ্ঠাটোৰ বিস্তৃতি গভীৰতা বেছি হৈছে",
        "parser-unstrip-loop-warning": "আন্‌ষ্ট্ৰীপ লুপ চিনাক্ত কৰা হৈছে",
        "converter-manual-rule-error": "মেনুৱেল ভাষা পৰিৱৰ্তন নিয়মত ত্ৰুটি পোৱা গৈছে",
        "undo-success": "এই সম্পাদনা পূৰ্ববৎ কৰিব পাৰি ।\nঅনুগ্ৰহ কৰি তলৰ তুলনাটি পৰীক্ষা কৰি ঠাৱৰ কৰক যে আপুনি এনে কৰিব বিচাৰিছে, আৰু তলত সালসলনিসমূহ সাঁচি এই কাৰ্য্য সম্পন্ন কৰক ।",
        "undo-failure": "এই সম্পাদনা মধ্যৱৰ্তী সম্পাদনাসমূহৰ দ্বন্দৰ কাৰণে পূৰ্ববৎ কৰা নহ'ব ।",
-       "undo-norev": "à¦\8fà¦\87 à¦¸à¦®à§\8dপাদনাà¦\9fি à§°à¦¦ à¦\95ৰিব à¦¨à§\8bৱাৰি, à¦\95াৰণ à¦\87 à¦\86ৰà§\81 à¦¨à¦¾à¦\87 à¦¬à¦¾ à¦\87য়াà¦\95 à¦¬à¦¾à¦¤à¦¿à¦² à¦\95ৰা à¦¹'ল ।",
+       "undo-norev": "à¦\8fà¦\87 à¦¸à¦®à§\8dপাদনাà¦\9fà§\8b à§°à¦¦ à¦\95ৰিব à¦¨à§\8bৱাৰি, à¦\95াৰণ à¦\8fà¦\87à¦\9fà§\8b à¦\86ৰà§\81 à¦¨à¦¾à¦\87 à¦¬à¦¾ à¦\87য়াà¦\95 à¦¬à¦¿à¦²à§\8bপ à¦\95ৰা à¦¹'ল।",
        "undo-nochange": "সম্পাদনাটো ইতিমধ্যেই বাতিল কৰা হৈছে।",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|আলোচনা]]) সম্পাদিত $1 সংশোধনটি বাতিল কৰক",
        "undo-summary-username-hidden": "এজন গোপন ব্যৱহাৰকাৰীয়ে কৰা $1 সংশোধন বাতিল কৰক",
        "rev-deleted-user-contribs": "[সদস্যনাম বা আই-পি ঠিকনা আঁতৰোৱা হ'ল - সম্পাদনা বৰঙনিসমূহৰ পৰা আঁৰ কৰা হৈছে]",
        "rev-deleted-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": "পà§\83ষà§\8dঠাà¦\96নৰ এই সংশোধনটো '''নিবাৰণ''' কৰা হৈছে ।\nসবিশেষ পাব [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} নিবাৰণ অভিলেখত]।\nআপুনি মন কৰিলে [$1 এই সংশোধনটো চাব পাৰে]।",
+       "rev-suppressed-text-unhide": "পà§\83ষà§\8dঠাà¦\9fà§\8bৰ এই সংশোধনটো '''নিবাৰণ''' কৰা হৈছে ।\nসবিশেষ পাব [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} নিবাৰণ অভিলেখত]।\nআপুনি মন কৰিলে [$1 এই সংশোধনটো চাব পাৰে]।",
        "rev-deleted-text-view": "পৃষ্ঠাৰ এই সংশোধনটো '''বিলোপ''' কৰা হ'ল ।\nআপুনি এইটো চাব পাৰে; সবিশেষ পাব [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} অবলুপ্তি অভিলেখত]।",
        "rev-suppressed-text-view": "পৃষ্ঠাৰ এই সংশোধনটো '''নিবাৰণ''' কৰা হ’ল।\nআপুনি এইটো চাব পাৰে; সবিশেষ পাব [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} নিবাৰণ অভিলেখত]।",
        "rev-deleted-no-diff": "আপুনি এই পাৰ্থক্য চাব নোৱাৰে কাৰণ এটা সংস্কৰণ '''বিলোপ''' কৰা হৈছে ।\nসবিশেষ পাব [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} অৱলুপ্তি অভিলেখত]।",
        "searchprofile-advanced-tooltip": "স্বনিৰ্ধাৰিত নামস্থানত অনুসন্ধান কৰক",
        "search-result-size": "$1 ({{PLURAL:$2|1 শব্দ|$2 শব্দসমূহ}})",
        "search-result-category-size": "{{PLURAL:$1|১ জন সদস্য|$1 জন সদস্য}} ({{PLURAL:$2|এটা উপশ্ৰেণী|$2 টা উপশ্ৰেণী}}, {{PLURAL:$3|এটা ফাইল|$3 টা ফাইল}})",
-       "search-result-score": "যথাৰ্থতা: $1%",
        "search-redirect": "(পুনৰ্নিৰ্দেশনা $1)",
        "search-section": "(অনুচ্ছেদ $1)",
        "search-file-match": "(ফাইলৰ বিষয়বস্তুৰ লগত মিল পোৱা গৈছে)",
        "searchrelated": "সম্পৰ্কিত",
        "searchall": "সকলো",
        "showingresults": "তলত #'''$2'''ৰ পৰা {{PLURAL:$1|'''1''' ফলাফল|'''$1''' ফলাফল}} দেখুওৱা হৈছে।",
-       "showingresultsheader": "'''$4'''ৰ বাবে {{PLURAL:$5|'''$3''' ৰ '''$1''' ফলাফল| '''$3''' ৰ '''$1 - $2''' ফলাফলসমূহ}}",
        "search-nonefound": "এই অনুসন্ধানৰ কোনো ফলাফল নাই ।",
        "powersearch-legend": "শক্তিশালী সন্ধান",
        "powersearch-ns": "নামস্থানবোৰত সন্ধান:",
        "action-patrol": "আনৰ সম্পাদনা পৰীক্ষিত বুলি চিহ্নিত কৰক",
        "action-autopatrol": "আপোনাৰ সম্পাদনা পৰীক্ষিত বুলি চিহ্নিত কৰক",
        "action-unwatchedpages": "নিৰীক্ষণ নকৰা পৃষ্ঠাসমূহৰ তালিকা চাওক",
-       "action-mergehistory": "à¦\8fà¦\87 à¦ªà§\83ষà§\8dঠাà¦\96নৰ ইতিহাস একত্ৰিত কৰক",
+       "action-mergehistory": "à¦\8fà¦\87 à¦ªà§\83ষà§\8dঠাà¦\9fà§\8bৰ ইতিহাস একত্ৰিত কৰক",
        "action-userrights": "সকলো সদস্য অধিকাৰ সম্পাদনা কৰক",
        "action-userrights-interwiki": "আন ৱিকিৰ সদস্যৰ অধিকাৰসমূহ সম্পাদনা কৰক",
        "action-siteadmin": "তথ্যকোষ বন্ধ কৰক বা খোলক",
        "uploadwarning": "আপল’ড সতৰ্কবাণী",
        "uploadwarning-text": "অনুগ্ৰহ কৰি তলত ফাইলৰ বিৱৰণী পৰিৱৰ্তন কৰক আৰু পুনৰ চেষ্টা কৰক ।",
        "savefile": "সংৰক্ষণ",
-       "uploadedimage": "\"[[$1]]\" আপল’ড কৰা হ’ল",
-       "overwroteimage": "\"[[$1]]\" ৰ এটা নতুন সংস্কৰণ আপল’ড কৰা হৈছে",
        "uploaddisabled": "আপল’ড নিষ্ক্ৰিয় হৈ আছে",
        "copyuploaddisabled": "ইউ.আৰ.এল.ৰ মাধ্যমেৰে আপল’ড নিষ্ক্ৰিয় হৈ আছে ।",
        "uploaddisabledtext": "ফাইল আপল’ড নিষ্ক্ৰিয় হৈ আছে ।",
        "license": "অনুজ্ঞাপত্ৰ:",
        "license-header": "অনুজ্ঞাপত্ৰ",
        "nolicense": "একো বাছনি কৰা নাই",
+       "licenses-edit": "অনুজ্ঞাপত্ৰ বিকল্পসমূহ সম্পাদনা কৰক",
        "license-nopreview": "(প্ৰাকদৰ্শন উপলব্ধ নহয়)",
        "upload_source_url": "(এটা বৈধ, ৰাজহুৱাকৈ উন্মুক্ত URL)",
        "upload_source_file": "(আপোনাৰ কম্পিউটাৰৰ এটা ফাইল)",
        "download": "ডাউনল’ড কৰক",
        "unwatchedpages": "চকু নৰখা পৃষ্ঠাসমূহ",
        "listredirects": "পুননিৰ্দেশনাৰ তালিকা",
+       "listduplicatedfiles": "প্ৰতিলিপি থকা ফাইলসমূহৰ তালিকা",
+       "listduplicatedfiles-summary": "এই তালিকাখনত থকা ফাইলবোৰৰ শেহতীয়া সংস্কৰণ আন কোনো ফাইলৰ শেহতীয়া সংস্কৰণৰ প্ৰতিলিপি। কেৱল স্থানীয় ফাইলবোৰহে গণ্য কৰা হৈছে।",
        "unusedtemplates": "অব্যৱহৃত সাঁচসমূহ",
        "unusedtemplatestext": "অন্য কোনো পৃষ্ঠাত নথকা {{ns:template}} নামস্থানৰ সকলো পৃষ্ঠা ইয়াত পাব ।\nসাঁচসমূহ বিলোপ কৰাৰ আগতে সেইবোৰলৈ থকা সংযোগ পৰীক্ষা কৰক ।",
        "unusedtemplateswlh": "অন্য সংযোগসমূহ",
        "randomincategory": "শ্ৰেণীৰ যিকোনো পৃষ্ঠা",
        "randomincategory-invalidcategory": "\"$1\" বৈধ শ্ৰেণী নাম নহয়।",
        "randomincategory-nopages": "[[:Category:$1|$1]] শ্ৰেণীত কোনো পৃষ্ঠা নাই।",
-       "randomincategory-selectcategory": "এই শ্ৰেণীৰ পৰা যিকোনো পৃষ্ঠা চাওক: $1 $2।",
-       "randomincategory-selectcategory-submit": "যাওক",
        "randomredirect": "অনিৰ্ধাৰিত পুননিৰ্দেশ",
        "randomredirect-nopages": "\"$1\" নামস্থানত কোনো পুননিৰ্দেশ নাই ।",
        "statistics": "পৰিসংখ্যা",
        "watchlist-details": "আলোচনা পৃষ্ঠাসমূহ বেলেগকৈ লেখত নধৰি {{PLURAL:$1|$1 টা পৃষ্ঠা}} আপোনাৰ লক্ষ্য-তালিকাত আছে।",
        "wlheader-enotif": "ইমেইল জাননী সক্ৰিয় কৰা হৈছে।",
        "wlheader-showupdated": "আপোনাৰ শেষ পৰিদৰ্শনৰ পিছত সলনি হোৱা পৃষ্ঠাসমূহ '''গাঢ়''' আখৰত দেখুওৱা হৈছে।",
-       "wlnote2": "$2, $3 অনুসাৰে শেষ {{PLURAL:$1|ঘণ্টাৰ|<strong>$1</strong> ঘণ্টাৰ}} সালসলনি তলত দিয়া হৈছে।",
+       "wlnote": "তলত {{PLURAL:$1| হ'ল সৰ্বশেষ পৰিৱৰ্তন|হ'ল সৰ্বশেষ '''$1''' পৰিৱৰ্তনসমূহ}} সৰ্বশেষ {{PLURAL:$2|ঘন্টা|'''$2''' ঘন্টা}}, $3, $4 -ৰ হিচাপে।",
        "wlshowlast": "যোৱা $1 ঘণ্টা $2 দিন $3 চাওক",
        "watchlist-options": "লক্ষ্য-তালিকা পছন্দসমূহ",
        "watching": "চকু দিয়া হৈছে.....",
        "actioncomplete": "কাৰ্য সম্পূৰ্ণ",
        "actionfailed": "কাৰ্য বিফল হ'ল",
        "deletedtext": "\"$1\" ক বিলোপন কৰা হৈছে।\nসাম্প্ৰতিক বিলোপনসমূহৰ তালিকা চাবলৈ $2 চাওক।",
-       "dellogpage": "বাতিল কৰা সূচী",
+       "dellogpage": "বিলà§\8bপ কৰা সূচী",
        "dellogpagetext": "তলত সাম্প্ৰতিক বিলোপনৰ তালিকা দিয়া হ'ল ।",
-       "deletionlog": "বাতিল কৰা সূচী",
+       "deletionlog": "বিলà§\8bপ কৰা সূচী",
        "reverted": "পূৰ্ববৰ্তী সংস্কৰণলৈ উভতি যোৱা হ'ল",
        "deletecomment": "কাৰণ:",
        "deleteotherreason": "আন/অতিৰিক্ত কাৰণ:",
        "deletereasonotherlist": "আন কাৰণ:",
        "deletereason-dropdown": "* বিলোপনৰ সাধাৰণ কাৰণসমূহ\n** স্পাম\n** অসভ্যালি\n** কপিৰাইট উলঙ্ঘন\n** লেখকৰ অনুৰোধ\n** ভঙা পুনঃনিৰ্দেশনা",
        "delete-edit-reasonlist": "অপসাৰণ কৰা কাৰণ সম্পাদনা কৰক",
-       "delete-toobig": "à¦\8fà¦\87 à¦ªà§\83ষà§\8dঠাà¦\96নৰ সম্পাদনা ইতিহাস অতি দীঘল, $1 {{PLURAL:$1|টা সংশোধনৰো|টা সংশোধনৰো}} বেছি ।\n{{SITENAME}}ৰ আকস্মিক ক্ষতি ৰোধ কৰিবলৈ এনে পৃষ্ঠাৰ ইতিহাস বিলোপ কৰাত সীমাবদ্ধতা আৰোপ কৰা হৈছে ।",
+       "delete-toobig": "à¦\8fà¦\87 à¦ªà§\83ষà§\8dঠাà¦\9fà§\8bৰ সম্পাদনা ইতিহাস অতি দীঘল, $1 {{PLURAL:$1|টা সংশোধনৰো|টা সংশোধনৰো}} বেছি ।\n{{SITENAME}}ৰ আকস্মিক ক্ষতি ৰোধ কৰিবলৈ এনে পৃষ্ঠাৰ ইতিহাস বিলোপ কৰাত সীমাবদ্ধতা আৰোপ কৰা হৈছে ।",
        "delete-warning-toobig": "এই পৃষ্ঠাখনৰ সম্পাদনা ইতিহাস অতি দীঘল, $1 {{PLURAL:$1|টা সংশোধনৰো|টা সংশোধনৰো}} বেছি ।\nইয়াক বিলোপ কৰিলে {{SITENAME}} ৰ তথ্যভঁৰালৰ কাৰ্য্যকাৰীতাত সমস্যা হ’ব পাৰে;\nসাৱধানেৰে আগ বাঢ়ক ।",
        "rollback": "সম্পাদনা পূৰ্ববৎ কৰক",
        "rollback_short": "পূৰ্ববৎ কৰক",
        "movetalk": "সংলগ্ন বাৰ্তা পৃষ্ঠা স্থানান্তৰ কৰক",
        "move-subpages": "উপ-পৃষ্ঠাসমূহ স্থানান্তৰ কৰক ($1লৈ)",
        "move-talk-subpages": "আলোচনা পৃষ্ঠাৰ উপ-পৃষ্ঠাসমূহ স্থানান্তৰ কৰক ($1-লৈ)",
-       "movepage-page-exists": "$1 à¦ªà§\83ষà§\8dঠাà¦\96ন à¦\87তিমধà§\8dযà§\87à¦\87 à¦\86à¦\9bà§\87 à¦\86ৰà§\81 à¦¤à¦¾à§° à¦\93পৰত à¦¸à§\8dবয়à¦\82à¦\95à§\8dৰিয়ভাৱà§\87 à¦²à¦¿à¦\96িব à¦¨à§\8bৱাৰি ।",
+       "movepage-page-exists": "$1 à¦ªà§\83ষà§\8dঠাà¦\9fà§\8b à¦\87তিমধà§\8dযà§\87 à¦\86à¦\9bà§\87à¦\87 à¦\86ৰà§\81 à¦¤à¦¾à§° à¦\93পৰত à¦¸à§\8dবয়à¦\82à¦\95à§\8dৰিয়ভাৱà§\87 à¦²à¦¿à¦\96িব à¦¨à§\8bৱাৰি।",
        "movepage-page-moved": "$1 পৃষ্ঠাটো $2লৈ স্থানান্তৰ কৰা হ'ল।",
        "movepage-page-unmoved": "$1 পৃষ্ঠাটো $2লৈ স্থানান্তৰ কৰা সম্ভৱ নহয়",
        "movepage-max-pages": "সৰ্বোচ্চ $1 {{PLURAL:$1|পৃষ্ঠা|পৃষ্ঠা}} স্থানান্তৰ কৰা হৈছে আৰু ইয়াতকৈ অধিক স্বয়ংক্ৰিয়ভাৱে স্থানান্তৰ নহ’ব ।",
        "movelogpage": "স্থানান্তৰন অভিলেখ",
        "movelogpagetext": "সকলো পৃষ্ঠা স্থানান্তৰৰ এখন তালিকা তলত দিয়া হৈছে ।",
        "movesubpage": "{{PLURAL:$1|টা উপপৃষ্ঠা}}",
-       "movesubpagetext": "à¦\8fà¦\87 à¦ªà§\83ষà§\8dঠাà¦\96নৰ à¦¤à¦²à¦¤ à¦¦à¦¿à¦¯à¦¼à¦¾ {{PLURAL:$1|à¦\9fা à¦\89পপà§\83ষà§\8dঠা}} à¦\86à¦\9bà§\87 ।",
+       "movesubpagetext": "à¦\8fà¦\87 à¦ªà§\83ষà§\8dঠাà¦\9fà§\8bৰ à¦¤à¦²à¦¤ à¦¦à¦¿à¦¯à¦¼à¦¾ {{PLURAL:$1|à¦\9fা à¦\89পপà§\83ষà§\8dঠা}} à¦\86à¦\9bà§\87।",
        "movenosubpage": "এই পৃষ্ঠাৰ কোনো উপপৃষ্ঠা নাই ।",
        "movereason": "কাৰণ:",
        "revertmove": "আগৰ অৱস্থালৈ ঘূৰি যাওক",
        "import": "পৃষ্ঠা আমদানি কৰক",
        "importinterwiki": "আন্তঃৱিকি আমদানি",
        "import-interwiki-text": "আমদানি কৰিবলৈ এটা ৱিকি বা পৃষ্ঠাৰ শিৰোনামা নিৰ্বাচন কৰক ।\nসংশোধনৰ তাৰিখ আৰু সম্পাদকৰ নাম সংৰক্ষণ কৰা হ'ব ।\nসকলো আন্তঃৱিকি আমদানি [[Special:Log/import|আমদানি অভিলেখ]]ত লিপিবদ্ধ আছে ।",
-       "import-interwiki-source": "উৎস ৱিকি/পৃষ্ঠা:",
+       "import-interwiki-sourcewiki": "উৎস ৱিকি:",
+       "import-interwiki-sourcepage": "উৎস পৃষ্ঠা:",
        "import-interwiki-history": "এই পৃষ্ঠাৰ সকলো সংশোধনৰ ইতিহাস প্ৰতিলিপি কৰক",
        "import-interwiki-templates": "সকলো সাঁচ অন্তৰ্ভুক্ত কৰক",
        "import-interwiki-submit": "আমদানি",
        "importbadinterwiki": "আন্ত:ৱিকি সংযোগ বেয়া",
        "importsuccess": "আমদানি সমাপ্ত !",
        "importnosources": "কোনো আন্তঃৱিকি আমদানি উৎসৰ সংজ্ঞা দিয়া হোৱা নাই আৰু প্ৰত্যক্ষ ইতিহাস আপল'ড নিষ্ক্ৰিয় কৰা হৈছে ।",
-       "importnofile": "কোনো আমদানি নথি আপল'ড কৰা হোৱা নাই ।",
+       "importnofile": "কোনো আমদানি নথি আপল'ড কৰা হোৱা নাই।",
        "importuploaderrorsize": "আমদানি নথিৰ আপল'ড অসফল হৈছে ।\nঅনুমোদিত আপল'ড নথিতকৈ এই নথিৰ আকাৰ ডাঙৰ ।",
        "importuploaderrorpartial": "আমদানি নথিৰ আপল'ড অসফল হৈছে ।\nনথিখন কেৱল আংশিকভাৱে আপল'ড কৰা হৈছে ।",
        "importuploaderrortemp": "আমদানি নথিৰ আপল'ড বিফল হৈছে ।\nএটা অস্থায়ী ফ'ল্ডাৰ হেৰাইছে ।",
        "import-error-create": "\"$1\" পৃষ্ঠাটো আমদানি কৰা নহ'ল কাৰণ ইয়াক সৃষ্টি কৰিবলৈ আপোনাৰ অনুমতি নাই।",
        "import-error-interwiki": "\"$1\" পৃষ্ঠাটো আমদানি কৰা নহ'ল কাৰণ ইয়াৰ নামটো বাহিৰা সংযোগৰ (আন্তঃৱিকি) বাবে সংৰক্ষিত।",
        "import-error-special": "\"$1\" পৃষ্ঠাটো আমদানি কৰা নহ'ল কাৰণ ই পৃষ্ঠা অনুমোদন নকৰা এটা বিশেষ নামস্থানৰ অন্তৰ্গত।",
-       "import-error-invalid": "\"$1\" à¦ªà§\83ষà§\8dঠাà¦\96ন à¦\86মদানি à¦\95ৰা à¦¨à¦¹'ল à¦\95াৰণ à¦\87য়াৰ à¦¨à¦¾à¦®à¦\9fà§\8b অবৈধ।",
+       "import-error-invalid": "\"$1\" à¦ªà§\83ষà§\8dঠাà¦\9fà§\8b à¦\86মদানি à¦\95ৰা à¦¨à¦¹'ল à¦\95াৰণ à¦¯à¦¿à¦\9fà§\8b à¦¨à¦¾à¦®à¦²à§\88 à¦\87য়াà¦\95 à¦\86মদানি à¦\95ৰিব à¦¬à¦¿à¦\9aৰা à¦¹à§\88à¦\9bিল à¦¸à§\87à¦\87à¦\9fà§\8b à¦\8fà¦\87 à§±à¦¿à¦\95িত অবৈধ।",
        "import-error-unserialize": " \"$1\" পৃষ্ঠাৰ $2 সংশোধনৰ ক্ৰম আঁতৰ কৰিব পৰা নগ'ল। এই সংশোধনে $4 ক্ৰমৰ সমল মডেল $3 ব্যৱহাৰ কৰা বুলি জনোৱা হৈছিল।",
        "import-options-wrong": "ভুল {{PLURAL:$2|বিকল্প|বিকল্পসমূহ}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "মূল পৃষ্ঠাৰ শিৰোনামা অবৈধ।",
        "tooltip-ca-protect": "এই পৃষ্ঠাটো সুৰক্ষিত কৰক",
        "tooltip-ca-unprotect": "এই পৃষ্ঠাৰ সুৰক্ষা সলনি কৰক",
        "tooltip-ca-delete": "এই পৃষ্ঠাটো বিলোপ কৰক",
-       "tooltip-ca-undelete": "বিলà§\8bপ à¦\95ৰাৰ à¦\86à¦\97à§\87য়à§\87 à¦\95ৰা à¦ªà§\83ষà§\8dঠাà¦\96নৰ à¦¸à¦¾à¦²à¦¸à¦²à¦¨à¦¿à¦¸à¦®à§\82হ à¦ªà§\81নà¦\83সংস্থাপন কৰক",
+       "tooltip-ca-undelete": "বিলà§\8bপ à¦\95ৰাৰ à¦\86à¦\97à§\87য়à§\87 à¦\95ৰা à¦ªà§\83ষà§\8dঠাà¦\9fà§\8bৰ à¦¸à¦¾à¦²à¦¸à¦²à¦¨à¦¿à¦¸à¦®à§\82হ à¦ªà§\81নৰà§\8dসংস্থাপন কৰক",
        "tooltip-ca-move": "এই পৃষ্ঠাটো স্থানান্তৰিত কৰক",
        "tooltip-ca-watch": "এই পৃষ্ঠাটো আপোনাৰ লক্ষ্য-তালিকাত যোগ কৰক",
        "tooltip-ca-unwatch": "এই পৃষ্ঠাটো আপোনাৰ লক্ষ্য-তালিকাৰ পৰা আঁতৰাওক",
        "tooltip-compareselectedversions": "এই পৃষ্ঠাত নিৰ্বাচিত দুটা সংশোধনৰ মাজত পাৰ্থক্য দেখুৱাওক",
        "tooltip-watch": "এই পৃষ্ঠাটো আপোনাৰ লক্ষ্য-তালিকাভুক্ত কৰক",
        "tooltip-watchlistedit-normal-submit": "শিৰোনামা আঁতৰাওক",
-       "tooltip-watchlistedit-raw-submit": "লক্ষ্য-তালিকা আপডেট কৰক",
+       "tooltip-watchlistedit-raw-submit": "লক্ষ্য-তালিকা আপডে'ট কৰক",
        "tooltip-recreate": "বিলোপ কৰা সত্বেও পৃষ্ঠাটো পুনৰ সৃষ্টি কৰক",
        "tooltip-upload": "আপল'ড আৰম্ভ কৰক",
        "tooltip-rollback": "\"পূৰ্ববত\" কৰিলে এটা ক্লিকত এই পৃষ্ঠাৰ শেষ অৱদানকাৰীৰ সম্পাদনা বাতিল কৰি ইয়াক পূৰ্বাৱস্থালৈ ঘূৰাই নিব।",
        "confirmemail_body": "কোনোবাই (সম্ভৱতঃ আপুনি) আই.পি. ঠিকনা $1ৰ পৰা এইটো ই-মেইল ঠিকনা ব্যৱহাৰ কৰি {{SITENAME}}ত\nএটা একাউণ্ট \"$2\" পঞ্জীয়ন কৰিছে ।\n\nএই একাউণ্ট আপোনাৰ হয়নে নহয় নিশ্চিত কৰাৰ বাবে আৰু {{SITENAME}}ত ই-মেইল বৈশিষ্টসমূহ সক্ৰিয় কৰাৰ বাবে\nআপোনাৰ ব্ৰাউজাৰত এই সংযোগটো খোলক:\n\n$3\n\nযদি আপুনি একাউণ্টটো পঞ্জীয়ন কৰা *নাই*, তেন্তে ই-মেইল ঠিকনা নিশ্চিতকৰণ বাতিলৰ বাবে\nএই সংযোগটো চাওক:\n\n$5\n\nএই নিশ্চিতকৰণ সংকেতৰ ম্যাদ $4ত উকলিব ।",
        "confirmemail_body_changed": "কোনোবাই (সম্ভৱতঃ আপুনি) আই.পি. ঠিকনা $1ৰ পৰা {{SITENAME}}ত\nএকাউণ্ট \"$2\"ৰ ই-মেইল ঠিকনা সলনি  কৰিছে ।\n\nএই একাউণ্ট আপোনাৰ হয়নে নহয় নিশ্চিত কৰাৰ বাবে আৰু {{SITENAME}}ত ই-মেইল বৈশিষ্টসমূহ পুনৰ সক্ৰিয় কৰাৰ বাবে\nআপোনাৰ ব্ৰাউজাৰত এই সংযোগটো খুলক:\n\n$3\n\nযদি একাউণ্টটো আপোনাৰ *নহয়*, তেন্তে ই-মেইল ঠিকনা নিশ্চিতকৰণ বাতিলৰ বাবে\nএই সংযোগটো চাওক:\n\n$5\n\nএই নিশ্চিতকৰণ সংকেতৰ ম্যাদ $4ত উকলিব ।",
        "confirmemail_body_set": "কোনোবাই (সম্ভৱতঃ আপুনি) আই.পি. ঠিকনা $1ৰ পৰা {{SITENAME}}ত\nএকাউণ্ট \"$2\"ৰ ইমেইল ঠিকনা এইটো প্ৰদান কৰিছে ।\n\nএই একাউণ্ট আপোনাৰ হয়নে নহয় নিশ্চিত কৰাৰ বাবে আৰু {{SITENAME}}ত ই-মেইল বৈশিষ্টসমূহ সক্ৰিয় কৰাৰ বাবে\nআপোনাৰ ব্ৰাউজাৰত এই সংযোগটো খোলক:\n\n$3\n\nযদি একাউণ্টটো আপোনাৰ *নহয়*, তেন্তে ইমেইল ঠিকনা নিশ্চিতকৰণ বাতিলৰ বাবে\nএই সংযোগটো চাওক:\n\n$5\n\nএই নিশ্চিতকৰণ সংকেতৰ ম্যাদ $4ত উকলিব ।",
-       "confirmemail_invalidated": "ই-মেইল ঠিকনা নিশ্চিতকৰণ বাতিল কৰা হৈছে",
+       "confirmemail_invalidated": "ইমেইল ঠিকনা নিশ্চিতকৰণ বাতিল কৰা হৈছে",
        "invalidateemail": "ই-মেইল নিশ্চিতকৰণ বাতিল কৰক",
        "scarytranscludedisabled": "[আন্তঃৱিকি আন্তঃভুক্তি নিষ্ক্ৰিয় কৰা আছে]",
        "scarytranscludefailed": "[$1ৰ বাবে সাঁচ অনা অসফল হৈছে]",
        "scarytranscludetoolong": "[URL অত্যাধিক দীঘল]",
        "deletedwhileediting": "'''সতৰ্কবাণী''': আপুনি সম্পাদনা আৰম্ভ কৰাৰ পাছত পৃষ্ঠাটো বিলোপ কৰা হৈছে !",
        "confirmrecreate": "আপুনি সম্পাদনা আৰম্ভ কৰাৰ পিছত সদস্য [[User:$1|$1]] ([[User talk:$1|আলোচনা]])য়ে পৃষ্ঠাটো বিলোপ কৰিছে, তাৰ কাৰণ:\n: ''$2''\nআপুনি এই পৃষ্ঠাটো আকৌ সৃষ্টি কৰিব খোজাটো নিশ্চিত কৰক ।",
-       "confirmrecreate-noreason": "à¦\86পà§\81নি à¦¸à¦®à§\8dপাদনা à¦\86ৰমà§\8dভ à¦\95ৰাৰ à¦ªà¦¿à¦\9bত à¦¸à¦¦à¦¸à§\8dয [[User:$1|$1]] ([[User talk:$1|à¦\86লà§\8bà¦\9aনা]])য়à§\87 à¦ªà§\83ষà§\8dঠাà¦\96ন à¦¬à¦¿à¦²à§\8bপ à¦\95ৰিà¦\9bà§\87 à¥¤ à¦\86পà§\81নি à¦\8fà¦\87 à¦ªà§\83ষà§\8dঠাà¦\96ন à¦\86à¦\95à§\8c à¦¸à§\83ষà§\8dà¦\9fি à¦\95ৰিব à¦\96à§\8bà¦\9cাà¦\9fà§\8b à¦\85নà§\81à¦\97à§\8dৰহ à¦\95ৰি à¦¨à¦¿à¦¶à§\8dà¦\9aিত à¦\95ৰà¦\95 ।",
+       "confirmrecreate-noreason": "à¦\86পà§\81নি à¦¸à¦®à§\8dপাদনা à¦\86ৰমà§\8dভ à¦\95ৰাৰ à¦ªà¦¿à¦\9bত à¦¸à¦¦à¦¸à§\8dয [[User:$1|$1]] ([[User talk:$1|à¦\86লà§\8bà¦\9aনা]])য়à§\87 à¦ªà§\83ষà§\8dঠাà¦\9fà§\8b à¦¬à¦¿à¦²à§\8bপ à¦\95ৰিà¦\9bà§\87। à¦\86পà§\81নি à¦\8fà¦\87 à¦ªà§\83ষà§\8dঠাà¦\96ন à¦\86à¦\95à§\8c à¦¸à§\83ষà§\8dà¦\9fি à¦\95ৰিব à¦\96à§\8bà¦\9cাà¦\9fà§\8b à¦\85নà§\81à¦\97à§\8dৰহ à¦\95ৰি à¦¨à¦¿à¦¶à§\8dà¦\9aিত à¦\95ৰà¦\95।",
        "recreate": "পুনৰ সৃষ্টি কৰক",
        "confirm_purge_button": "শুদ্ধ",
        "confirm-purge-top": "এই পৃষ্ঠাৰ কেচ্‌ খালী কৰা হওক ?",
        "confirm-watch-top": "এই পৃষ্ঠাটো আপোনাৰ লক্ষ্য-তালিকাত যোগ কৰিব?",
        "confirm-unwatch-button": "শুদ্ধ",
        "confirm-unwatch-top": "এই পৃষ্ঠাটো আপোনাৰ লক্ষ্য-তালিকাৰ পৰা আঁতৰাব?",
+       "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← পূৰ্বৱৰ্তী পৃষ্ঠা",
        "imgmultipagenext": "পৰৱৰ্তী পৃষ্ঠা →",
        "imgmultigo": "যাওক",
        "watchlistedit-raw-legend": "অশোধিত অনুসৰণ-তালিকা সম্পাদন কৰক",
        "watchlistedit-raw-explain": "আপোনাৰ দৰ্শন তালিকাত থকা শীৰ্ষকসমূহ তলত দেখুওৱা হৈছে, আৰু তালিকালৈ যোগ কৰি অথবা তালিকাৰ পৰা আতৰাই সম্পাদন কৰিব পাৰি;\nপ্ৰতি শাৰী এটা শীৰ্ষক হিচাপে।\nযেতিয়া সম্পূৰ্ণ হব, \"{{int:Watchlistedit-raw-submit}}\"ত ক্লিক কৰিব।\nআপুনি লগতে [[Special:EditWatchlist|প্ৰামাণিক সম্পাদকক ব্যৱহাৰ কৰিব পাৰে]]।",
        "watchlistedit-raw-titles": "শিৰোনামা:",
-       "watchlistedit-raw-submit": "লক্ষ্য-তালিকা আপডেট কৰক",
+       "watchlistedit-raw-submit": "লক্ষ্য-তালিকা আপডে'ট কৰক",
        "watchlistedit-raw-done": "আপোনাৰ লক্ষ্য-তালিকা নবীকৰণ কৰা হ'ল",
        "watchlistedit-raw-added": "{{PLURAL:$1|এটা শিৰোনামা|$1-টা শিৰোনামা}} যোগ কৰা হ'ল:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|এটা শিৰোনামা|$1-টা শিৰোনামা}} আঁতৰোৱা হ'ল:",
        "watchlistedit-clear-titles": "শিৰোনামাসমূহ:",
        "watchlistedit-clear-submit": "লক্ষ্য-তালিকা পৰিষ্কাৰ কৰক (এইটো স্থায়ী!)",
        "watchlistedit-clear-done": "আপোনাৰ লক্ষ্য-তালিকা পৰিষ্কাৰ কৰা হ'ল।",
+       "watchlisttools-clear": "লক্ষ্য-তালিকা পৰিষ্কাৰ কৰক",
        "watchlisttools-view": "সংগতি থকা সাল-সলনিবোৰ চাওক",
        "watchlisttools-edit": "লক্ষ্য-তালিকা চাওক আৰু সম্পাদনা কৰক",
        "watchlisttools-raw": "অশোধিত লক্ষ্য-তালিকা সম্পাদনা কৰক",
        "version-license": "অনুজ্ঞাপত্ৰ",
        "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-poweredby-credits": "এই ৱিকি '''[https://www.mediawiki.org/ মিডিয়াৱিকিৰ]''' দ্বাৰা প্ৰচলিত , কপিৰাইট © ২০০১-$1 $2.",
        "version-poweredby-others": "অন্য",
        "version-poweredby-translators": "translatewiki.net অনুবাদকসকল",
        "compare-submit": "তুলনা কৰক",
        "compare-invalid-title": "আপুনি নিৰ্ধাৰণ কৰা শিৰোনামাটো অবৈধ ।",
        "compare-title-not-exists": "আপুনি নিৰ্ধাৰণ কৰা ফাইলটোৰ অস্বিত্ব নাই ।",
-       "compare-revision-not-exists": "à¦\86পà§\81নি à¦¨à¦¿à§°à§\8dধাৰণ à¦\95ৰা à¦¸à¦\82শà§\8bধনà§\80à¦\9fà§\8bৰ à¦\85সà§\8dবিত্ব নাই ।",
+       "compare-revision-not-exists": "à¦\86পà§\81নি à¦¨à¦¿à§°à§\8dধাৰণ à¦\95ৰা à¦¸à¦\82শà§\8bধনà¦\9fà§\8bৰ à¦\85সà§\8dতিত্ব নাই ।",
        "dberr-problems": "দুঃখিত! চাইটটোত কিছু কাৰিকৰী সমস্যা হৈছে ।",
        "dberr-again": "অলপ সময় অপেক্ষা কৰি পুনৰ আপল'ডৰ চেষ্টা কৰক ।",
        "dberr-info": "(তথ্যকোষৰ চাৰ্ভাৰৰ লগত যোগাযোগ কৰিব নোৱাৰি: $1)",
        "sqlite-has-fts": "$1 সম্পূৰ্ণ-পাঠ অনুসন্ধান সমৰ্থন সহ",
        "sqlite-no-fts": "$1 সম্পূৰ্ণ-পাঠ অনুসন্ধান সমৰ্থন অবিহনে",
        "logentry-delete-delete": "$3 পৃষ্ঠাটো $1ৰদ্বাৰা {{GENDER:$2|বিলোপ কৰা হ'ল}}",
-       "logentry-delete-restore": "$3 পৃষ্ঠাখন $1 ৰদ্বাৰা {{GENDER:$2|পুনৰ্সংৰক্ষণ কৰা হ'ল}}",
+       "logentry-delete-restore": "$1-এ $3 পৃষ্ঠাটো {{GENDER:$2|পুনৰ্সংৰক্ষণ কৰিলে}}",
        "logentry-delete-event": "$3: $4 -ত {{PLURAL:$5|এটা লগ ঘটনা|$5 লগ ঘটনাসমূহ}} -ৰ $1 পৰিৱৰ্তন কৰা দৃশ্যমানতা",
        "logentry-delete-revision": "পৃষ্ঠা $3ত {{PLURAL:$5|এটা সংশোধন|$5 সংশোধনসমূহ}}ৰ দৃশ্যমানতা $1 {{GENDER:$2|য়ে সলালে}}: $4",
        "logentry-delete-event-legacy": "$3ত ল'গ ঘটনাসমূহৰ দৃশ্যমানতা $1 {{GENDER:$2|ৰদ্বাৰা সলোৱা হ'ল}}",
        "expand_templates_output": "ফলাফল",
        "expand_templates_ok": "ওকে",
        "expand_templates_remove_comments": "মন্তব্য গু়চাওক",
-       "expand_templates_preview": "খচৰা"
+       "expand_templates_preview": "খচৰা",
+       "pagelanguage": "পৃষ্ঠাৰ ভাষা নিৰ্বাচক",
+       "pagelang-name": "পৃষ্ঠা",
+       "pagelang-language": "ভাষা",
+       "pagelang-use-default": "ডিফল্ট ভাষা ব্যৱহাৰ কৰক",
+       "pagelang-select-lang": "ভাষা নিৰ্বাচন কৰক",
+       "right-pagelang": "পৃষ্ঠাৰ ভাষা পৰিৱৰ্তন কৰক",
+       "action-pagelang": "পৃষ্ঠাৰ ভাষা পৰিৱৰ্তন কৰক",
+       "log-name-pagelang": "ভাষা পৰিৱৰ্তন ল'গ"
 }
index 53e2e7b..2fe57e0 100644 (file)
@@ -9,7 +9,8 @@
                        "Shirayuki",
                        "Xuacu",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Fitoschido"
                ]
        },
        "tog-underline": "Sorrayar enllaces:",
@@ -26,6 +27,7 @@
        "tog-watchdefault": "Amestar les páxines y ficheros qu'edite a la mio llista de siguimientu",
        "tog-watchmoves": "Amestar les páxines y ficheros que tresllade a la mio llista de siguimientu",
        "tog-watchdeletion": "Amestar les páxines y ficheros que desanicie a la mio llista de siguimientu",
+       "tog-watchrollback": "Amestar les páxines onde fici una reversión a la mio llista de siguimientu",
        "tog-minordefault": "Marcar toles ediciones como menores de mou predetermináu",
        "tog-previewontop": "Amosar previsualización enantes del cuadru d'edición",
        "tog-previewonfirst": "Amosar previsualización na primera edición",
        "tagline": "De {{SITENAME}}",
        "help": "Ayuda",
        "search": "Buscar",
-       "searchbutton": "Buscar",
+       "searchbutton": "Guetar",
        "go": "Dir",
        "searcharticle": "Dir",
        "history": "Historial de la páxina",
        "talkpagelinktext": "Alderique",
        "specialpage": "Páxina especial",
        "personaltools": "Ferramientes personales",
-       "postcomment": "Seición nueva",
        "articlepage": "Ver la páxina de conteníu",
        "talk": "Alderique",
        "views": "Vistes",
        "policy-url": "Project:Polítiques",
        "portal": "Portal de la comunidá",
        "portal-url": "Project:Portal de la comunidá",
-       "privacy": "Política de proteición de datos",
-       "privacypage": "Project:Política de proteición de datos",
+       "privacy": "Política d'intimidá",
+       "privacypage": "Project:Política de privacidá",
        "badaccess": "Fallu de permisos",
        "badaccess-group0": "Nun tienes permisu pa executar l'aición solicitada.",
        "badaccess-groups": "L'aición solicitada ta acutada pa usuarios {{PLURAL:$2|del grupu|d'unu d'estos grupos}}: $1.",
        "hidetoc": "anubrir",
        "collapsible-collapse": "Plegar",
        "collapsible-expand": "Espander",
+       "confirmable-confirm": "¿Tas {{GENDER:$1|seguru|segura}}?",
+       "confirmable-yes": "Sí",
+       "confirmable-no": "Non",
        "thisisdeleted": "¿Ver o restaurar $1?",
        "viewdeleted": "¿Ver $1?",
        "restorelink": "{{PLURAL:$1|una edición desaniciada|$1 ediciones desaniciaes}}",
        "invalidtitle-knownnamespace": "Títulu inválidu col espaciu de nomes «$2» ya'l testu «$3»",
        "invalidtitle-unknownnamespace": "Títulu inválidu col númberu $1 d'espaciu de nomes desconocíu ya'l testu «$2»",
        "exception-nologin": "Nun anició sesión",
-       "exception-nologin-text": "Por favor, [[Special:Userlogin|anicie sesión]] pa tener accesu a esta páxina o aición.",
+       "exception-nologin-text": "Por favor, anicia sesión pa tener accesu a esta páxina o aición.",
        "exception-nologin-text-manual": "Por favor, $1 pa tener accesu a esta páxina o aición.",
        "virus-badscanner": "Fallu de configuración: Escáner de virus desconocíu: ''$1''",
        "virus-scanfailed": "fallu d'escanéu (códigu $1)",
        "externaldberror": "O hebo un fallu d'autenticación de la base de datos o nun tienes permisu p'anovar la to cuenta esterna.",
        "login": "Entrar",
        "nav-login-createaccount": "Entrar / crear cuenta",
-       "loginprompt": "Ha de tener les «cookies» activaes p'aniciar sesión en {{SITENAME}}.",
        "userlogin": "Entrar / crear cuenta",
        "userloginnocreate": "Aniciar sesión",
        "logout": "Salir",
        "userlogin-resetlink": "¿Escaeció los datos d'accesu?",
        "userlogin-resetpassword-link": "¿Escaeció la contraseña?",
        "userlogin-helplink2": "Ayuda del aniciu de sesión",
-       "userlogin-loggedin": "Yá anició sesión como {{GENDER:$1|$1}}.\nUtilice'l formulariu de más abaxo p'aniciar sesión como otru usuariu.",
-       "userlogin-createanother": "Crear otra cuenta",
        "createacct-emailrequired": "Direición de corréu electrónicu",
        "createacct-emailoptional": "Direición de corréu electrónicu (opcional)",
        "createacct-email-ph": "Escriba la so direición de corréu electrónicu",
        "preview": "Vista previa",
        "showpreview": "Amosar previsualización",
        "showdiff": "Amosar cambeos",
+       "blankarticle": "<strong>Atención:</strong> La páxina que tas a piques de crear ta balera.\nSi vuelves a facer click en «{{int:savearticle}}», crearáse la páxina ensin conteníu dengún.",
        "anoneditwarning": "<strong>Avisu:</strong> Nun anició sesión.\nLa direición IP quedará grabada nel historial d'edición d'esta páxina.",
        "anonpreviewwarning": "''Nun aniciasti sesión. Al guardar quedará rexistrada la to direición IP nel historial d'edición d'esta páxina.''",
        "missingsummary": "'''Recordatoriu:''' Nun conseñasti un resume d'edición.\nSi calques nuevamente \"{{int:savearticle}}\", la to edición guardaráse ensin nengún resume.",
        "accmailtext": "Unvióse a $2 una contraseña xenerada al debalu pal usuariu [[User talk:$1|$1]]. Pue camudase na páxina ''[[Special:ChangePassword|camudar contraseña]]'' depués d'aniciar sesión.",
        "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 '''atrás''' 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.''\nPoro, tenemos qu'usar la direición numbérica IP pa identificalu/la.\nEsa IP pue tar compartida por varios usuarios.\nSi ye un usuariu anónimu y cree qu'hai comentarios irrelevantes empobinaos a vusté, por favor, [[Special:UserLogin/signup|cree una cuenta]] o [[Special:UserLogin/signup|anicie sesión]] pa torgar futures confusiones con otros usuarios anónimos.",
-       "noarticletext": "Nestos momentos nun hai testu nesta páxina.\nPue [[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>.",
+       "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-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.",
        "parser-template-recursion-depth-warning": "Se pasó la llende de fondura recursiva de les plantíes ($1)",
        "language-converter-depth-warning": "Se pasó la llende de fondura del convertidor de llingües ($1)",
        "node-count-exceeded-category": "Páxines onde se pasó la cuenta de noyos",
-       "node-count-exceeded-category-desc": "Una categoría pa les páxines onde se supera la cuenta de noyos.",
-       "node-count-exceeded-warning": "La páxina pasó la cuenta de nodios",
+       "node-count-exceeded-category-desc": "La páxina supera la cuenta máxima de noyos.",
+       "node-count-exceeded-warning": "La páxina superó la cuenta de noyos",
        "expansion-depth-exceeded-category": "Páxines onde se pasó la fondura d'espansión",
-       "expansion-depth-exceeded-category-desc": "Esta ye una categoría pa les páxines onde se pasó la fondura d'espansión.",
+       "expansion-depth-exceeded-category-desc": "La páxina superó la fondura máxima d'espansión.",
        "expansion-depth-exceeded-warning": "La páxina pasó la fondura d'espansión",
        "parser-unstrip-loop-warning": "Deteutóse un bucle \"unstrip\"",
        "parser-unstrip-recursion-limit": "Pasóse la llende de recursividá d'unstrip ($1)",
        "currentrev": "Revisión actual",
        "currentrev-asof": "Revisión actual a fecha de $1",
        "revisionasof": "Revisión a fecha de $1",
-       "revision-info": "Revisión a fecha de $1; $2",
+       "revision-info": "La revisión del $4 a les $5 por {{GENDER:$6|$2}}$7",
        "previousrevision": "←Revisión anterior",
        "nextrevision": "Revisión siguiente→",
        "currentrevisionlink": "Revisión actual",
        "rev-deleted-event": "(aición del rexistru desaniciada)",
        "rev-deleted-user-contribs": "[nome d'usuariu o direición IP desaniciáu - ediciones anubríes en contribuciones]",
        "rev-deleted-text-permission": "Esta revisión de la páxina se '''desanició'''.\nLos detalles s'alcuentren nel [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} rexistru de desanicios].",
+       "rev-suppressed-text-permission": "Esta revisión de la páxina <strong>suprimióse</strong>.\nLos detalles s'alcuentren nel [{{fullurl:{{#Special:Log}}/supress|page={{FULLPAGENAMEE}}}} rexistru de supresiones].",
        "rev-deleted-text-unhide": "Esta revisión de la páxina se '''desanició'''.\nLos detalles s'alcuentren nel [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} rexistru de desanicios].\nEntá pues [$1 ver esta revisión] si quies siguir.",
        "rev-suppressed-text-unhide": "Esta revisión de la páxina se '''suprimió'''.\nLos detalles s'alcuentren nel [{{fullurl:{{#Special:Log}}/supress|page={{FULLPAGENAMEE}}}} rexistru de supresiones].\nEntá pues [$1 ver esta revisión] si quies siguir.",
        "rev-deleted-text-view": "Esta revisión de la páxina se '''desanició'''.\nPues vela; los detalles s'alcuentren nel [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} rexistru de desanicios].",
        "revdelete-text-text": "Les revisiones desaniciaes inda apaecerán nel historial de la páxina, pero partes del conteníu nun sedrán accesibles al públicu.",
        "revdelete-text-file": "Les versiones del ficheru desaniciaes inda apaecerán nel historial del ficheru, pero partes del conteníu nun sedrán accesibles al públicu.",
        "logdelete-text": "Los socesos del rexistru desaniciaos inda apaecerán nos rexistros, pero partes del conteníu nun sedrán accesibles al públicu.",
-       "revdelete-text-others": "Otros alministradores de {{SITENAME}} inda tendrán accesu al conteníu anubríu y puen desfacer l'anubrimientu con esta mesma interfaz, mentanto nun se configuren otres torgues más.",
+       "revdelete-text-others": "Otros alministradores inda tendrán accesu al conteníu anubríu y puen desfacer el desaniciu, mentanto nun se configuren otres torgues más.",
        "revdelete-confirm": "Confirma que quies facer esto, qu'entiendes les consecuencies, y que vas facer esto d'alcuerdo [[{{MediaWiki:Policy-url}}|cola política]].",
        "revdelete-suppress-text": "La supresión '''namái''' tendría d'usase nos casos darréu:\n* Información que pudiere ser bilordiosa\n* Información personal inapropiada\n*: ''direiciones de llares y númberos de teléfonu, númberos d'identidá nacional, etc.''",
        "revdelete-legend": "Establecer torgues de visibilidá",
        "mergehistory-empty": "Nun se pue fusionar nenguna revisión.",
        "mergehistory-success": "$3 {{PLURAL:$3|revisión|revisiones}} de [[:$1]] fusionaes correutamente en [[:$2]].",
        "mergehistory-fail": "Nun se pudo facer la fusión d'historiales, por favor verifica la páxina y los parámetros temporales.",
+       "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.",
        "mergehistory-invalid-source": "La páxina d'orixe ha tener un títulu válidu.",
        "searchprofile-advanced-tooltip": "Buscar nos espacios de nomes personalizaos",
        "search-result-size": "$1 ({{PLURAL:$2|1 pallabra|$2 pallabres}})",
        "search-result-category-size": "{{PLURAL:$1|1 miembru|$1 miembros}} ({{PLURAL:$2|1 subcategoría|$2 subcategories}}, {{PLURAL:$3|1 ficheru|$3 ficheros}})",
-       "search-result-score": "Relevancia: $1%",
        "search-redirect": "(redireición de $1)",
        "search-section": "(seición $1)",
        "search-file-match": "(casa col conteníu del ficheru)",
        "powersearch-togglelabel": "Comprobar:",
        "powersearch-toggleall": "Toos",
        "powersearch-togglenone": "Dengún",
+       "powersearch-remember": "Recordar la seleición pa guetes futures",
        "search-external": "Busca esterna",
        "searchdisabled": "La busca en {{SITENAME}} ta desactivada. Mentanto, pues buscar en Google. Has fixate en que'l conteníu de los sos índices de {{SITENAME}} pue tar desfasáu.",
        "search-error": "Hebo un error al buscar: $1",
        "preferences": "Preferencies",
        "mypreferences": "Preferencies",
        "prefs-edits": "Númberu d'ediciones:",
-       "prefsnologintext2": "Por favor, $1 pa configurar les preferencies d'usuariu",
+       "prefsnologintext2": "Por favor, anicia sesión pa cambiar les tos preferencies.",
        "prefs-skin": "Apariencia",
        "skin-preview": "Vista previa",
        "datedefault": "Ensin preferencia",
        "right-deletedtext": "Ver el testu desaniciáu y los cambeos ente versiones desaniciaes",
        "right-browsearchive": "Buscar páxines desaniciaes",
        "right-undelete": "Restaurar una páxina",
-       "right-suppressrevision": "Revisar y restaurar revisiones ocultes a los alministradores",
+       "right-suppressrevision": "Ver, anubrir y amosar revisiones específiques de páxines de cualquier usuariu",
+       "right-viewsuppressed": "Ver revisiones anubríes de cualquier usuariu",
        "right-suppressionlog": "Ver rexistros privaos",
        "right-block": "Bloquiar la edición d'otros usuarios",
        "right-blockemail": "Bloquia-y l'unviu de corréu electrónicu a un usuariu",
        "recentchanges-legend-heading": "'''Lleenda:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (ver tamién la  [[Special:NewPages|llista de páxines nueves]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Abaxo tan los cambeos dende <strong>$2</strong> (s'amuesen fasta <strong>$1</strong>).",
+       "rcnotefrom": "Abaxo {{PLURAL:$5|tá'l cambiu|tan los cambios}} dende'l <strong>$3</strong>, a les <strong>$4</strong> (s'amuesen un máximu de <strong>$1</strong>).",
        "rclistfrom": "Amosar los nuevos cambios dende $3 $2",
        "rcshowhideminor": "$1 ediciones menores",
        "rcshowhideminor-show": "Amosar",
        "largefileserver": "Esti ficheru ye mayor de lo que permite la configuración del sirvidor.",
        "emptyfile": "El ficheru que xubisti paez tar vaciu.\nEsto podría ser pola mor d'un enquivocu nel nome del ficheru.\nPor favor, camienta si daveres quies xubir esti archivu.",
        "windows-nonascii-filename": "Esta wiki nun permite nomes de ficheru con caráuteres especiales.",
-       "fileexists": "Yá esiste un ficheru con esti nome, por favor comprueba <strong>[[:$1]]</strong> si nun tas seguru de querer camudalu.\n[[$1|thumb]]",
+       "fileexists": "Yá esiste un ficheru con esti nome, por favor comprueba <strong>[[:$1]]</strong> si nun tas {{GENDER:|seguru|segura}} de querer camudalu.\n[[$1|thumb]]",
        "filepageexists": "La páxina de descripción d'esti ficheru creóse yá en <strong>[[:$1]]</strong>, pero anguaño nun esiste nengún ficheru con esti nome.\nEl resume que pongas nun va apaecer na páxina de descripción.\nPa facer que'l to resume apaeza, vas tener qu'editalu manualmente.\n[[$1|thumb]]",
-       "fileexists-extension": "Yá esiste un ficheru con un nome asemeyáu: [[$2|thumb]]\n* Nome del ficheru que se quier xubir: <strong>[[:$1]]</strong>\n* Nome del ficheru esistente: <strong>[[:$2]]</strong>\nPor favor escueyi un nome diferente.",
+       "fileexists-extension": "Yá esiste un ficheru con un nome asemeyáu: [[$2|thumb]]\n* Nome del ficheru que se quier xubir: <strong>[[:$1]]</strong>\n* Nome del ficheru esistente: <strong>[[:$2]]</strong>\n¿Quies meyor usar un nome más distinguible?",
        "fileexists-thumbnail-yes": "El ficheru paez ser una imaxe de tamañu menguáu ''(miniatura)''.\n [[$1|thumb]]\nPor favor comprueba el ficheru <strong>[[:$1]]</strong>.\nSi'l ficheru comprobáu tien el mesmu tamañu que la imaxe orixinal, nun ye necesario xubir una miniatura estra.",
        "file-thumbnail-no": "El ficheru entama con <strong>$1</strong>.\nPaez ser una imaxe de tamañu menguáu ''(miniatura)''.\nSi tienes esta imaxe a resolución completa xúbila; si non, por favor camuda'l nome del ficheru.",
        "fileexists-forbidden": "Yá esiste un ficheru con esti nome, y nun se pue renomar.\nSi tovía asina quies xubir el ficheru, por favor vuelvi atrás y usa otru nome.\n[[File:$1|thumb|center|$1]]",
        "uploadwarning": "Avisu de xubíes de ficheros",
        "uploadwarning-text": "Por favor, camuda más abaxo la descripción del ficheru y vuelve a tentalo.",
        "savefile": "Guardar ficheru",
-       "uploadedimage": "xubió \"[[$1]]\"",
-       "overwroteimage": "xubió una versión nueva de \"[[$1]]\"",
        "uploaddisabled": "Deshabilitaes les xubíes",
        "copyuploaddisabled": "Xubir por URL ta desactivao.",
        "uploaddisabledtext": "Les xubíes de ficheros tán desactivaes.",
        "license": "Llicencia:",
        "license-header": "Llicencia",
        "nolicense": "Nenguna seleicionada",
+       "licenses-edit": "Editar les opciones de llicencia",
        "license-nopreview": "(Previsualización non disponible)",
-       "upload_source_url": " (una URL válida y accesible públicamente)",
-       "upload_source_file": " (un archivu del to ordenador)",
+       "upload_source_url": "(el ficheru qu'escoyisti dende una URL válida y accesible públicamente)",
+       "upload_source_file": "(el ficheru qu'escoyisti del to ordenador)",
+       "listfiles-delete": "desaniciar",
        "listfiles-summary": "Esta páxina especial amuesa tolos ficheros xubíos.",
        "listfiles_search_for": "Buscar por nome d'archivu multimedia:",
        "imgfile": "archivu",
        "filedelete-maintenance": "El desaniciu y restauración de ficheros ta desactivao temporalmente mientres ta en mantenimientu.",
        "filedelete-maintenance-title": "Nun se pue desaniciar el ficheru",
        "mimesearch": "Busca MIME",
-       "mimesearch-summary": "Esta páxina activa'l filtráu d'archivos en función de la so triba MIME. Entrada: contenttype/subtype, p.ex. <code>image/jpeg</code>.",
+       "mimesearch-summary": "Esta páxina permite filtriar los ficheros pol so tipu MIME.\nEntrada: contenttype/subtype o contenttype/*, p.ex. <code>image/jpeg</code>.",
        "mimetype": "Triba MIME:",
        "download": "descargar",
        "unwatchedpages": "Páxines ensin vixilar",
        "randomincategory": "Páxina al debalu de la categoría",
        "randomincategory-invalidcategory": "\"$1\" nun ye un nome de categoría válidu.",
        "randomincategory-nopages": "Nun hai páxines en [[:Category:$1]].",
-       "randomincategory-selectcategory": "Ver una páxina al debalu de la categoría: $1. $2",
-       "randomincategory-selectcategory-submit": "Dir",
+       "randomincategory-category": "Categoría:",
+       "randomincategory-legend": "Páxina al debalu de la categoría",
        "randomredirect": "Redireición al debalu",
        "randomredirect-nopages": "Nun hai redireiciones nel espaciu de nomes \"$1\".",
        "statistics": "Estadístiques",
        "wantedpages-badtitle": "Títulu inválidu nel conxuntu de resultaos: $1",
        "wantedfiles": "Archivos buscaos",
        "wantedfiletext-cat": "Los ficheros siguientes tan usándose, pero nun esisten. Ye posible qu'apaezan ficheros de repositorios esternos ensin qu'esistan. Cualesquier falsu positivu tará <del>tacháu</del>. Amás, les páxines qu'inxerten ficheros que nun esisten apaecen na llista de [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Los ficheros siguientes tán usándose, pero nun existen. Amás, hai una llista de páxines qu'incluyen ficheros que non existen en [[:$1]].",
        "wantedfiletext-nocat": "Los ficheros siguientes tan usándose, pero nun esisten. Ye posible qu'apaezan ficheros de repositorios esternos ensin qu'esistan. Cualesquier falsu positivu tará <del>tacháu</del>.",
+       "wantedfiletext-nocat-noforeign": "Los ficheros siguientes tán usándose, pero nun existen.",
        "wantedtemplates": "Plantíes más buscaes",
        "mostlinked": "Páxines más enllaciaes",
        "mostlinkedcategories": "Categoríes más enllaciaes",
-       "mostlinkedtemplates": "Plantíes más enllaciaes",
+       "mostlinkedtemplates": "Páxines más trescluíes",
        "mostcategories": "Páxines con más categoríes",
        "mostimages": "Archivos más enllaciaos",
        "mostinterwikis": "Páxines con más interwikis",
        "trackingcategories-desc": "Criterios d'inclusión de categoría",
        "noindex-category-desc": "La páxina contién una pallabra máxica <code><nowiki>__NOINDEX__</nowiki></code> (y ta nun espaciu de nomes nel que se permite esta marca) y, poro, los robots nun la indexarán.",
        "index-category-desc": "La páxina contién una pallabra máxica <code><nowiki>__INDEX__</nowiki></code> (y ta nun espaciu de nomes nel que se permite esta marca) y, poro, los robots la indexarán anque normalmente nun lo faigan.",
-       "post-expand-template-inclusion-category-desc": "Después de espander toles plantíes, el tamañu de la páxina ye mayor que <code>$wgMaxArticleSize</code>; de mou qu'algunes plantíes nun s'espandieron.",
-       "post-expand-template-argument-category-desc": "Después d'espander l'argumentu d'una plantía (daqué ente llaves triples, como <code>{{{Daqué}}}</code>), la páxina ye mayor que <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Hai demasiaes funciones analítiques costoses (como <code>#ifexist</code>) incluíes nuna páxina. Vea [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Categoría amestada si la páxina contién un enllaz de ficheru frañáu (un enllaz pa incrustar un ficheru cuando'l ficheru nun esiste).",
-       "hidden-category-category-desc": "Esta ye una categoría que contién la pallabra máxica <code><nowiki>__HIDDENCAT__</nowiki></code>, que torga que s'amuese de mou predetermináu nel cuadru d'enllaces de categoría de les páxines.",
+       "post-expand-template-inclusion-category-desc": "El tamañu de la páxina ye mayor que <code>$wgMaxArticleSize</code> después de espander toles plantíes, de mou qu'algunes plantíes nun s'espandieron.",
+       "post-expand-template-argument-category-desc": "La páxina ye mayor que <code>$wgMaxArticleSize</code> después d'espander l'argumentu d'una plantía (daqué ente llaves triples, como <code>{{{Daqué}}}</code>).",
+       "expensive-parserfunction-category-desc": "La páxina usa demasiaes funciones analítiques costoses (como <code>#ifexist</code>). Llei [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "La páxina contién un enllaz frañáu a un ficheru (un enllaz pa incrustar un ficheru cuando'l ficheru nun esiste).",
+       "hidden-category-category-desc": "La categoría contién <code><nowiki>__HIDDENCAT__</nowiki></code> nel conteníu de páxina, que torga de mou predetermináu que s'amuese nel cuadru d'enllaces de categoría de les páxines.",
        "trackingcategories-nodesc": "Nun hai una descripción disponible.",
        "trackingcategories-disabled": "La categoría ta desactivada",
        "mailnologin": "Ensin direición d'unviu",
        "mywatchlist": "Llista de siguimientu",
        "watchlistfor2": "Pa $1 $2",
        "nowatchlist": "La to llista de siguimientu ta vacia.",
-       "watchlistanontext": "Tienes d'$1 pa ver o editar entraes de la to llista de siguimientu.",
+       "watchlistanontext": "Por favor, anicia sesión pa ver o editar entraes de la to llista de siguimientu.",
        "watchnologin": "Non identificáu",
        "addwatch": "Amestar a la llista de siguimientu",
        "addedwatchtext": "La páxina \"[[:$1]]\" s'amestó a la to [[Special:Watchlist|llista de llista de siguimientu]].\nLos cambeos futuros nesta páxina y na so páxina d'alderique asociada apaecerán allí.",
        "watchlist-details": "{{PLURAL:$1|$1 páxina|$1 páxines}} na to llista de siguimientu, ensin cuntar aparte les páxines d'alderique.",
        "wlheader-enotif": "La notificación per corréu electrónicu ta activada.",
        "wlheader-showupdated": "Les páxines que camudaron dende que les visitasti anteriormente amuesense en '''negrina'''",
-       "wlnote2": "Abaxo tan los cambios {{PLURAL:$1|na cabera hora|nes caberes <strong>$1</strong> hores}}, el día $2 a les $3.",
+       "wlnote": "Abaxo {{PLURAL:$1|tá'l caberu cambiu|tan los caberos <strong>$1</strong> cambios}} {{PLURAL:$2|na cabera hora|nes caberes <strong>$2</strong> hores}}, a día $3, a les $4.",
        "wlshowlast": "Amosar les últimes $1 hores $2 díes $3",
        "watchlist-options": "Opciones de la llista de siguimientu",
        "watching": "Vixilando...",
        "exbeforeblank": "el conteníu enantes de dexar en blanco yera: '$1'",
        "delete-confirm": "Desaniciar «$1»",
        "delete-legend": "Desaniciar",
-       "historywarning": "'''Avisu:'''' La páxina que vas desaniciar tien un historial con aproximadamente $1 {{PLURAL:$1|revisión|revisiones}}:",
+       "historywarning": "<strong>Avisu:</strong> La páxina que vas desaniciar tien un historial con $1 {{PLURAL:$1|revisión|revisiones}}:",
        "confirmdeletetext": "Tas a piques d'esborrar una páxina xunto con tol so historial.\nPor favor confirma que ye lo que quies facer, qu'entiendes les consecuencies, y que lo tas faciendo acordies coles [[{{MediaWiki:Policy-url}}|polítiques]].",
        "actioncomplete": "Aición completada",
        "actionfailed": "Falló l'aición",
        "delete-edit-reasonlist": "Editar los motivos d'esborráu",
        "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.",
        "rollback": "Revertir ediciones",
        "rollback_short": "Revertir",
        "protectlogpage": "Rexistru de proteiciones",
        "protectlogtext": "Darréu ta un rexistru de les protecciones de páxines.\nConsulta la [[Special:ProtectedPages|llista de páxines protexíes]] pa ver les proteiciones actives nestos momentos.",
        "protectedarticle": "protexó «[[$1]]»",
-       "modifiedarticleprotection": "camudó'l nivel de proteición de \"[[$1]]\"",
+       "modifiedarticleprotection": "camudó’l nivel de proteición de «[[$1]]»",
        "unprotectedarticle": "quitó-y la protección a \"[[$1]]\"",
-       "movedarticleprotection": "treslladó los parámetros de proteición dende \"[[$2]]\" a \"[[$1]]\"",
+       "movedarticleprotection": "treslladó los parámetros de proteición dende «[[$2]]» a «[[$1]]»",
        "protect-title": "Protexendo \"$1\"",
-       "protect-title-notallowed": "Ver el nivel de proteición de \"$1\"",
+       "protect-title-notallowed": "Ver el nivel de proteición de «$1»",
        "prot_1movedto2": "[[$1]] treslladáu a [[$2]]",
        "protect-badnamespace-title": "Espaciu de nomes non protexible",
        "protect-badnamespace-text": "Les páxines d'esti espaciu de nomes nun se puen protexer.",
        "undelete-search-title": "Buscar páxines desaniciaes",
        "undelete-search-box": "Buscar páxines desaniciaes",
        "undelete-search-prefix": "Amosar páxines qu'empecipien por:",
-       "undelete-search-submit": "Buscar",
+       "undelete-search-submit": "Guetar",
        "undelete-no-results": "Nun s'atoparon páxines afechisques a la busca nel archivu d'esborraos.",
        "undelete-filename-mismatch": "Nun se pue restaurar la revisión del archivu con fecha $1: el nome d'archivu nun concuaya",
        "undelete-bad-store-key": "Nun se pue restaurar la revisión del archivu con fecha $1: yá nun esistía l'archivu nel momentu d'esborralu.",
        "autoblockid": "Autobloquiar #$1",
        "block": "Bloquiar usuariu",
        "unblock": "Desbloquiar usuariu",
-       "blockip": "Bloquiar usuariu",
+       "blockip": "Bloquiar {{GENDER:$1|al usuariu|a la usuaria}}",
        "blockip-legend": "Bloquiar usuariu",
        "blockiptext": "Usa'l siguiente formulariu pa bloquiar el permisu d'escritura a una IP o a un usuariu concretu.\nEsto debería facese sólo pa prevenir vandalismu como indiquen les [[{{MediaWiki:Policy-url}}|polítiques]]. Da un motivu específicu (como por exemplu citar páxines que fueron vandalizaes).",
        "ipaddressorusername": "Direición IP o nome d'usuariu:",
        "ipb-unblock-addr": "Desbloquiar $1",
        "ipb-unblock": "Desbloquiar un nome d'usuariu o direición IP",
        "ipb-blocklist": "Ver los bloqueos esistentes",
-       "ipb-blocklist-contribs": "Contribuciones de $1",
+       "ipb-blocklist-contribs": "Collaboraciones de {{GENDER:$1|$1}}",
        "unblockip": "Desbloquiar usuariu",
        "unblockiptext": "Usa'l formulariu d'abaxo pa restablecer l'accesu d'escritura a una direicion IP o a un nome d'usuariu previamente bloquiáu.",
        "ipusubmit": "Desaniciar esti bloquéu",
        "import": "Importar páxines",
        "importinterwiki": "Importación treswiki",
        "import-interwiki-text": "Seleiciona una wiki y un títulu de páxina pa importar.\nLes feches de revisión y los nomes de los editores caltendránse.\nToles aiciones d'importación treswiki queden rexistraes nel [[Special:Log/import|rexistru d'importaciones]].",
-       "import-interwiki-source": "Códigu wiki/páxina:",
+       "import-interwiki-sourcewiki": "Wiki d'orixe:",
+       "import-interwiki-sourcepage": "Páxina d'orixe:",
        "import-interwiki-history": "Copiar toles versiones d'historial d'esta páxina",
        "import-interwiki-templates": "Incluyir toles plantíes",
        "import-interwiki-submit": "Importar",
        "import-upload": "Xubir datos XML",
        "import-token-mismatch": "Perdiéronse los datos de la sesión. Intentalo otra vuelta.",
        "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.",
+       "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.",
        "import-error-interwiki": "La páxina «$1» nun s'importó porque'l so nome ta acutáu pa enllaces esternos (interwiki).",
        "import-error-special": "La páxina «$1» nun s'importó porque pertenez a un espaciu de nomes especial que nun permite les páxines.",
-       "import-error-invalid": "La páxina «$1» nun s'importó porque tien un nome inválidu.",
+       "import-error-invalid": "La páxina «$1» nun s'importó porque'l nome al que s'importaría ye inválidu nesta wiki.",
        "import-error-unserialize": "Nun se pudo quitar la serialización de la revisión $2 de la páxina \"$1\". Nel informe figura que la revisión usa'l modelu de conteníu $3 serializáu como $4.",
        "import-error-bad-location": "La revisión $2 qu'usa'l modelu de conteníu $3 nun pue guardase na páxina \"$1\" d'esta wiki, porque esi modelu nun tien sofitu na páxina.",
        "import-options-wrong": "{{PLURAL:$2|Opción enquivocada|Opciones enquivocaes}}: <nowiki>$1</nowiki>",
        "importlogpage": "Rexistru d'importaciones",
        "importlogpagetext": "Importaciones alministrativas de páxines con historial d'ediciones d'otres wikis.",
        "import-logentry-upload": "importada [[$1]] per aciu d'una xuba d'archivu",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revisión|revisiones}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revisión importada|revisiones importaes}}",
        "import-logentry-interwiki": "treswikificada $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisión|revisiones}} dende $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisión importada|revisiones importaes}} dende $2",
        "javascripttest": "Prueba de JavaScript",
        "javascripttest-title": "Executando pruebes de $1",
        "javascripttest-pagetext-noframework": "Esta páxina ta acutada pa executar pruebes de javascript.",
        "newimages-label": "Nome d'archivu (o una parte d'él):",
        "newimages-showbots": "Ver les xubíes de los bots",
        "noimages": "Nun hai nada que ver.",
-       "ilsubmit": "Buscar",
+       "ilsubmit": "Guetar",
        "bydate": "por fecha",
        "sp-newimages-showfrom": "Amosar los archivos nuevos emprimando dende'l $1 a les $2",
        "seconds": "{{PLURAL:$1|$1 segundu|$1 segundos}}",
        "autosumm-replace": "Sustituyendo la páxina por '$1'",
        "autoredircomment": "Redirixendo a [[$1]]",
        "autosumm-new": "Páxina creada con «$1»",
+       "autosumm-newblank": "Creóse una páxina balera",
        "size-gigabytes": "$1 XB",
        "lag-warn-normal": "Los cambios más nuevos que $1 {{PLURAL:$1|segundu|segundos}} seique nun s'amuesen nesta llista.",
        "lag-warn-high": "Pola mor d'un importante retrasu nel sirvidor de la base de datos, los cambios más nuevos que $1 {{PLURAL:$1|segundu|segundos}} seique nun s'amuesen nesta llista.",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|alderique]])",
        "unknown_extension_tag": "Etiqueta d'estensión \"$1\" desconocida",
        "duplicate-defaultsort": "Avisu: La clave d'ordenación predeterminada \"$2\" anula la clave d'ordenación anterior \"$1\".",
+       "duplicate-displaytitle": "<strong>Avisu:</strong> El títulu a amosar \"$2\" anula el títulu anterior \"$1\".",
        "version": "Versión",
        "version-extensions": "Estensiones instalaes",
+       "version-skins": "Temes instalaos",
        "version-specialpages": "Páxines especiales",
        "version-parserhooks": "Hooks d'análisis sintáuticu",
        "version-variables": "Variables",
        "version-antispam": "Prevención del corréu puxarra",
-       "version-skins": "Apariencia",
        "version-other": "Otros",
        "version-mediahandlers": "Remanadores d'archivos multimedia",
        "version-hooks": "Hooks",
        "version-hook-name": "Nome del hook",
        "version-hook-subscribedby": "Suscritu por",
        "version-version": "(Versión $1)",
+       "version-no-ext-name": "[ensin nome]",
        "version-license": "Llicencia de MediaWiki",
        "version-ext-license": "Llicencia",
        "version-ext-colheader-name": "Estensión",
+       "version-skin-colheader-name": "Apariencia",
        "version-ext-colheader-version": "Versión",
        "version-ext-colheader-license": "Llicencia",
        "version-ext-colheader-description": "Descripción",
        "logentry-rights-rights": "$1 {{GENDER:$2|camudó}} la pertenencia a grupos de $3 dende $4 a $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|camudó}} la pertenencia a grupos de $3",
        "logentry-rights-autopromote": "$1 {{GENDER:$2|promocionó}} automáticamente de $4 a $5",
+       "logentry-upload-upload": "$1 {{GENDER:$2|xubió}} $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|xubió}} una versión nueva de $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|xubió}} $3",
        "rightsnone": "(nengún)",
        "feedback-bugornote": "Si tas preparáu pa describir un problema técnicu en detalle, [$1 informa del fallu].\nD'otra miente, pues usar el formulariu cenciellu d'abaxo. El to comentariu apaecerá na páxina \"[$3 $2]\" xunto col to nome d'usuariu y el restolador qu'uses.",
        "feedback-subject": "Asuntu:",
        "expand_templates_remove_nowiki": "Quitar les etiquetes <nowiki> nos resultaos",
        "expand_templates_generate_xml": "Amosar l'árbole d'análisis sintáuticu XML",
        "expand_templates_generate_rawhtml": "Ver el HTML en bruto",
-       "expand_templates_preview": "Vista previa"
+       "expand_templates_preview": "Vista previa",
+       "pagelanguage": "Selector de llingua de la páxina",
+       "pagelang-name": "Páxina",
+       "pagelang-language": "Llingua",
+       "pagelang-use-default": "Usar la llingua predeterminada",
+       "pagelang-select-lang": "Escoyer llingua",
+       "right-pagelang": "Cambiar la llingua de la páxina",
+       "action-pagelang": "cambiar la llingua de la páxina",
+       "log-name-pagelang": "Rexistru de cambios de llingua",
+       "log-description-pagelang": "Esti ye un rexistru de los cambios de llingua de les páxines.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|cambió}} la llingua de la páxina $3 del $4 al $5.",
+       "default-skin-not-found": "¡Coime! L'aspeutu predetermináu pa la to wiki (<code>$wgDefaultSkin</code>), <code>$1</code> nun ta disponible.\n\nLa to instalación paez qu'incluye los siguientes aspeutos. Llei [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Skin configuration] pa más información sobro cómo activalos y escoyer el predetermináu.\n\n$2\n\n; Si acabes d'instalar MediaWiki:\n: Probablemente instalasti dende git, o'l códigu fonte direutamente usando algún otru métodu. Esto ye d'esperar. Intenta instalar dellos aspeutos dende'l [https://www.mediawiki.org/wiki/Category:All_skins direutoriu d'aspeutos de mediawiki.org's], asina:\n:* Descargando [https://www.mediawiki.org/wiki/Download l'instalador tarball], que vien con dellos aspeutos y estensiones. Pues copiar y apegar el direutoriu <code>skins/</code> d'ehí.\n:* Clonando unu de los direutorios <code>mediawiki/skins/*</code> via git nel direutoriu <code>skins/</code> de la to instalación de MediaWiki.\n: Facer esto nun tendría d'interferir col to repositoriu git si yes un desendolcador de MediaWiki.\n\n; Si acabes d'anovar MediaWiki:\n: MediaWiki 1.24 y más nuevu yá nun activa automáticamente los aspeutos instalaos (llei [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: Skin autodiscovery]). Pues apegar les llinies siguientes en <code>LocalSettings.php</code> p'activar tolos aspeutos instalaos actualmente:\n\n<pre>$3</pre>\n\n; Si acabes d'editar <code>LocalSettings.php</code>:\n: Vuelvi a comprobar los nomes de los aspeutos por si hai errores d'escritura.",
+       "default-skin-not-found-no-skins": "¡Coime! L'aspeutu predetermináu pa la to wiki (<code>$wgDefaultSkin</code>), <code>$1</code> nun ta disponible.\n\nNun tienes aspeutos instalaos.\n\n; Si acabes d'instalar MediaWiki:\n: Probablemente instalasti dende git, o'l códigu fonte direutamente usando algún otru métodu. Esto ye d'esperar. MediaWiki 1.24 y más nuevu nun incluye nengún aspeutu nel repositoriu principal. Intenta instalar dellos aspeutos dende'l [https://www.mediawiki.org/wiki/Category:All_skins direutoriu d'aspeutos de mediawiki.org], asina:\n:* Descargando [https://www.mediawiki.org/wiki/Download l'instalador tarball], que vien con dellos aspeutos y estensiones. Pues copiar y apegar el direutoriu <code>skins/</code> d'ehí.\n:* Clonando unu de los direutorios <code>mediawiki/skins/*</code> via git nel direutoriu <code>skins/</code> de la to instalación de MediaWiki.\n: Facer esto nun tendría d'interferir col to repositoriu git si yes un desendolcador de MediaWiki. Llei [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Skin configuration] pa más información sobro cómo activar los aspeutos y escoyer el predetermináu.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (activáu)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''desactiváu''')"
 }
index 7956331..a8c72d1 100644 (file)
        "talkpagelinktext": "Keyaksera",
        "specialpage": "Aptafu bu",
        "personaltools": "Weltafa xeka",
-       "postcomment": "Warzaf gabot",
        "articlepage": "Telizwira",
        "talk": "Keyaksera",
        "views": "Wira",
        "externaldberror": "Ont divefa origakrokla va pilkomodara ont va rinafa divefa pata me ronuskel.",
        "login": "Pilkomodá",
        "nav-login-createaccount": "Pataredú oke va int dogluyá",
-       "loginprompt": "Ta dogluyara va {{SITENAME}} va koti \"cookie\" talpeyki gotutegiral.",
        "userlogin": "Va int dogluyá / pataredú",
        "userloginnocreate": "Dogluyara",
        "logout": "Dimgluyá",
        "searchprofile-advanced-tooltip": "Aneyara ko pilkovafo yoltxo",
        "search-result-size": "$1 ({{PLURAL:$2|1 trogarn|$2 trogarn}})",
        "search-result-category-size": "{{PLURAL:$1|1 bewik|$1 bewik}} ({{PLURAL:$2|1 volveyloma|$2 volveyloma}}, {{PLURAL:$3|1 iyeltak|$3 iyeltak}})",
-       "search-result-score": "Vadjereka : $1%",
        "search-redirect": "(graskara va $1)",
        "search-section": "($1 gabot)",
        "search-suggest": "Va $1 sugdalayal ?",
        "file-exists-duplicate": "Bat iyeltak tir jontolaca ke {{PLURAL:$1|iyeltak|iyeltak}}:",
        "uploadwarning": "Obral !",
        "savefile": "Giwara va iyeltak",
-       "uploadedimage": "« [[$1]] » ksudayan mo zanisiko",
-       "overwroteimage": "kalvajayan siatos ke \"[[$1]]\"",
        "uploaddisabled": "Skalev, staksera va iyeltak tir gritegirayan.",
        "uploaddisabledtext": "Iyeltakkalvajara tir gritegirayana.",
        "uploadscripted": "Bat iyeltak va HTML ok Script beksa rotir narujutuna gan web exulesiki ruldar.",
        "watchlist-details": "{{PLURAL:$1|$1 bu|$1 bu}} koe rinafi suzdasiki rade prilarabueem.",
        "wlheader-enotif": "Email walzera tir tegisa.",
        "wlheader-showupdated": "Bu betayanu vielu rin ironokon worayal tir '''sulatcalakorafu'''.",
+       "wlnote": "Vleveon tid tela '''$1''' ironokafa betara mali '''$2''' ironokaf bartiv.",
        "wlshowlast": "Nedira va ironokaf $1 bartiv isu $2 viel isu $3",
        "watchlist-options": "Suzdasikiolkeem",
        "watching": "Nedis...",
index c7d66d8..1a429a7 100644 (file)
@@ -24,7 +24,9 @@
                        "לערי ריינהארט",
                        "아라",
                        "Arystanbek",
-                       "Dağlı95"
+                       "Dağlı95",
+                       "Sayginer",
+                       "Şeyx Şamil"
                ]
        },
        "tog-underline": "Keçidlərin altını xətlə:",
        "talkpagelinktext": "Müzakirə",
        "specialpage": "Xüsusi səhifə",
        "personaltools": "Şəxsi alətlər",
-       "postcomment": "Yeni bölmə",
        "articlepage": "Məqaləni nəzərdən keçir",
        "talk": "Müzakirə",
        "views": "Görünüş",
        "mainpage": "Ana Səhifə",
        "mainpage-description": "Ana Səhifə",
        "policy-url": "Project:Qaydalar",
-       "portal": "Kənd meydanı",
+       "portal": "İctimai portal",
        "portal-url": "Project:Kənd meydanı",
        "privacy": "Məxfilik siyasəti",
        "privacypage": "Project:Gizlilik prinsipi",
        "externaldberror": "Verilənlər bazasının doğruluğunu yoxlamada xəta baş verib və yaxud sizin xarici istifadəçi qeydiyyatını yeniləmək hüququnuz yoxdur.",
        "login": "Daxil ol",
        "nav-login-createaccount": "Daxil ol / hesab yarat",
-       "loginprompt": "{{SITENAME}} saytına daxil olmaq üçün \"veb kökələrinin\" (cookies) istifadəsinə icazə verilməlidir.",
        "userlogin": "Daxil ol və ya istifadəçi yarat",
        "userloginnocreate": "Daxil ol",
        "logout": "Çıxış",
        "noemailcreate": "Düzgün e-poçt ünvanı qeyd etməlisiniz",
        "passwordsent": "Yeni parol \"$1\" üçün qeydiyyata alınan e-poçt ünvanına göndərilmişdir.\nXahiş edirik, e-məktubu aldıqdan sonra yenidən daxil olasınız.",
        "blocked-mailpassword": "İP ünvanınız bloklu olduğuna görə, yeni parol göndərmə mümkün deyil.",
-       "eauthentsent": "Göstərilən bu e-poçt ünvanına məktub göndərildi. \nGələcəkdə e-poçt almaq üçün,bu e-poçtun sizə aid olması haqqındakı qaydalarla tanış olun.",
+       "eauthentsent": "Göstərilən e-poçt ünvanına məktub göndərildi. \nGələcəkdə həmin ünvana e-məktub ala bilmək üçün, ünvanın sizə aid olmasının təsdiq edilməsi ilə bağlı məktubda verilən göstərişlərə riayət etməlisiniz.",
        "throttled-mailpassword": "Bir parol sıfırlama e-poçtu son {{PLURAL:$1|bir saat|$1 saat}} içində zatən göndərildi. Xidməti pis niyyətlə istifadə etməyi önləmək üçün, hər {{PLURAL:$1|bir saatda|$1 saatda}} sadəcə bir parol sıfırlama e-poçtu göndəriləcəkdir.",
        "mailerror": "Məktub göndərmə xətası: $1",
        "acct_creation_throttle_hit": "Sizin IP ünvanınızdan bu viki-də son bir gün ərzində {{PLURAL:$1|1 hesab|$1 hesab}} açılmışdır. Bu bir gün ərzində icazə verilən maksimum say olduğu üçün, indiki anda daha çox hesab aça bilməzsiniz.",
        "updated": "(yeniləndi)",
        "note": "'''Qeyd:'''",
        "previewnote": "<strong>Unutmayın ki, bu yalnız sınaq göstərişidir.</strong> Dəyişiklikləriniz hal-hazırda qeyd edilməmişdir!",
+       "continue-editing": "Redaktə sahəsinə qayıt",
        "previewconflict": "Bu sınaq göstərişidir və yaddaşda saxlayacağınız təqdirdə mətnin redaktə səhifəsinin yuxarı hissəsində nəticənin necə olacağını göstərir.",
        "session_fail_preview": "'''Üzr istəyirik! Sizin redaktəniz saxlanılmadı. Serverdə identifikasiyanızla bağlı problemlər yaranmışdır. Lütfən bir daha təkrar edin. Problem həll olunmazsa hesabınızdan çıxın və yenidən daxil olun.'''",
        "editing": "Redaktə $1",
        "searchprofile-advanced-tooltip": "Ad aralığında axtar",
        "search-result-size": "$1 ({{PLURAL:$2|1 söz|$2 söz}})",
        "search-result-category-size": "{{PLURAL:$1|$1 element|$1 elementlər}} ({{PLURAL:$2|$2 alt kateqoriya|$2 alt kateqoriyalar}}, {{PLURAL:$3|$3 fayl|$3 fayllar}})",
-       "search-result-score": "Uyğunluq: $1%",
        "search-redirect": "(yönləndirmə $1)",
        "search-section": "(bölmə $1)",
        "search-suggest": "Bəlkə, bunu nəzərdə tuturdunuz: $1",
        "right-deletedhistory": "silinmiş mətnə daxil olmadan silinmiş səhifələrin tarixçələrinə baxma",
        "right-browsearchive": "Silinmiş səhifələri axtar",
        "right-undelete": "Silinmiş səhifələrin bərpası",
-       "right-suppressrevision": "İdarəçilərdən gizlənmiş dəyişikliklərə bax və geri yüklə",
+       "right-suppressrevision": "Səhifələrin gizli versiyalarına bax, gizlə və göstər",
        "right-suppressionlog": "Şəxsi qeydlərə bax",
        "right-block": "Digər istifadəçilərin redaktə etməsinə qadağa qoy",
        "right-blockemail": "İstifadəçinin e-poçt göndərməsinə qadağa qoy",
        "fileexists-extension": "Bu adda başqa bir fayl mövcuddur: [[$2|thumb]]\n* Yüklənilən faylın adı: <strong>[[:$1]]</strong>\n* Mövcud faylın adı: <strong>[[:$2]]</strong>\nXahiş edirik, başqa ad seçin.",
        "uploadwarning": "Yükləmə xəbərdarlığı",
        "savefile": "Faylı qeyd et",
-       "uploadedimage": "\"[[$1]]\" yükləndi",
-       "overwroteimage": "\"[[$1]]\"-in yeni versiyası yükləndi",
        "uploaddisabled": "Yükləmə baş tutmadı",
        "copyuploaddisabled": "URL-dən yükləmə baş tutmadı.",
        "uploaddisabledtext": "Fayl yüklənməsi baş tutmadı.",
        "unusedtemplates": "İstifadəsiz şablonlar",
        "unusedtemplateswlh": "digər keçidlər",
        "randompage": "İxtiyari səhifə",
-       "randomincategory-selectcategory-submit": "Keç",
        "randomredirect": "İxtiyari istiqamətləndirmə",
        "randomredirect-nopages": "\"$1\" ad sahəsində heç bir yönləndirmə yoxdur.",
        "statistics": "Statistika",
        "watchlist-details": "İzləmə siyahınızda, müzakirə səhifələrini çıxmaq şərtilə, {{PLURAL:$1|$1 səhifə|$1 səhifə}} var.",
        "wlheader-enotif": " E-məktubla bildiriş aktivdir.",
        "wlheader-showupdated": "Son ziyarətinizdən sonra edilən dəyişikliklər '''qalın şriftlərlə''' göstərilmişdir.",
+       "wlnote": "Aşağıdakı {{PLURAL:$1|'''$1''' dəyişiklik|'''$1''' dəyişiklik}} son {{PLURAL:$2|saatda|'''$2''' saatda}} edilmişdir.",
        "wlshowlast": "Bunları göstər: son $1 saatı $2 günü $3",
        "watchlist-options": "İzləmə siyahısının nizamlamaları",
        "watching": "İzlənilir...",
        "deletereasonotherlist": "Digər səbəb",
        "deletereason-dropdown": "*Əsas silmə səbəbi\n** Müəllif istəyi\n** Müəllif hüququ pozuntusu\n** Vandalizm",
        "delete-edit-reasonlist": "Silmə səbəblərinin redaktəsi",
-       "rollback": "Əvvəlki versiya",
+       "rollback": "əvvəlki halına qaytar",
        "rollback_short": "əvvəlki halına qaytar",
        "rollbacklink": "əvvəlki halına qaytar",
+       "rollbacklinkcount": "$1 {{PLURAL:$1|dəyişikliyi|dəyişikliyi}} geri qaytar",
        "rollbackfailed": "Geri qaytarma uğursuzdur",
        "cantrollback": "Redaktə geri qaytarıla bilməz; axırıncı redaktə səhifədə olan yeganə fəaliyyətdir.",
        "revertpage": "[[Special:Contributions/$2|$2]] ([[User talk:$2|Müzakirə]]) tərəfindən edilmiş dəyişikliklər [[User:$1|$1]] tərəfindən edilmiş dəyişikliklərə qaytarıldı.",
        "sp-contributions-search": "Fəaliyyətləri axtar",
        "sp-contributions-username": "IP-ünvanı və ya istifadəçi adı:",
        "sp-contributions-toponly": "Son redaktə olan dəyişiklikləri göstər",
+       "sp-contributions-newonly": "Yalnız yeni səhifə yaradılan dəyişiklikləri göstər",
        "sp-contributions-submit": "Axtar",
        "whatlinkshere": "Bu səhifəyə bağlantılar",
        "whatlinkshere-title": "\"$1\" məqaləsinə keçid verən səhifələr",
        "thumbnail_image-missing": "Belə görünür ki, $1 faylı yoxdur",
        "import": "Səhifələri idxal et",
        "importinterwiki": "Vikilərarası çıxarma",
-       "import-interwiki-source": "Mənbə viki/səhifə:",
        "import-interwiki-history": "Səhifənin dəyişmə tarixçələrinin hamısını köçür",
        "import-interwiki-templates": "Bütün şablonlarla birlikdə",
        "import-interwiki-submit": "İdxal",
        "revdelete-uname-unhid": "İstifadəçi adı gizli deyil",
        "revdelete-restricted": "məhdudiyyətlər idarəçilərə tətbiq olunur",
        "revdelete-unrestricted": "idarəçilər üçün götürülmüş məhdudiyyətlər",
+       "logentry-move-move": "$1 $3 səhifəsinin adını $4 olaraq {{GENDER:$1|dəyişdi|dəyişdi}}.",
+       "logentry-move-move_redir": "$1 $3 səhifəsinin adını yönləndirmənin əksinə dəyişərək, $4 {{GENDER:$2|adlandırdı}}",
        "logentry-newusers-newusers": "$1istifadəçi hesabını yaratdı",
        "logentry-newusers-create": "$1 istifadəçi hesabı yaratdı",
        "logentry-newusers-create2": "$1 $3 üçün istifadəçi hesabı yaratdı",
index 7361191..e72d941 100644 (file)
        "talkpagelinktext": "دانیشیق",
        "specialpage": "اؤزل صحیفه",
        "personaltools": "شخصی آراجلار",
-       "postcomment": "يئنی بؤلوم",
        "articlepage": "ایچری‌لی صحیفه‌یه باخ",
        "talk": "دانیشیق",
        "views": "گؤرونوشلر",
        "externaldberror": "بیر دیتابیس دوغرولاما خطاسی اولدو، یوخسا سیزین ائشیک حسابینیزی گونجل‌لدمگه ایجازه‌نیز یوخدور.",
        "login": "گیریش",
        "nav-login-createaccount": "گیریش / حساب یاراد",
-       "loginprompt": "{{SITENAME}} سایتینا گیریش اوچون، کوکی‌لره ایجازه وئرمک لازیم‌دیر.",
        "userlogin": "گیریش / حساب یاراد",
        "userloginnocreate": "گیریش",
        "logout": "چیخیش",
        "searchprofile-advanced-tooltip": "تاپشیریلان آدفضالاریندا آختار",
        "search-result-size": "$1 ({{PLURAL:$2|۱ سؤزجوک|$2 سؤزجوک}})",
        "search-result-category-size": "{{PLURAL:$1|بیر|$1}} عوضو ({{PLURAL:$2|بیر|$}} آلت‌بؤلمه، {{PLURAL:$3|بیر|$3}} فایل)",
-       "search-result-score": "اویغونلوق: $1٪",
        "search-redirect": "یول‌لاندیرما $1",
        "search-section": "(بؤلوم $1)",
        "search-suggest": "بونو نظرده توتوردونوزمو: $1",
        "uploadwarning": "يوکله‌مه خبردارلیغی",
        "uploadwarning-text": "خاهیش ائدیریک آشاغی‌داکی فایل شرحینی دییش‌دیرین و یئنی‌دن جهد ائدین.",
        "savefile": "فايلی قئيد ائت",
-       "uploadedimage": "«[[$1]]» یوکلندی",
-       "overwroteimage": "\"[[$1]]\"-این یئنی نوسخه سی یوکلندی",
        "uploaddisabled": "يوکله‌مه باش توتمادی",
        "copyuploaddisabled": "اینترنت آدرسی ایله یوکلمه باش توتمادی.",
        "uploaddisabledtext": "فايل يوکلنمه‌سی باش توتمادی.",
        "watchlist-details": "دانیشیق صفحه‌لرینی سایمایاراق، {{PLURAL:$1|$1 صفحه‌نی}} ایزله‌ییرسینیز.",
        "wlheader-enotif": "ایمیل ایله بیلدیریش آچیلیب‌دیر.",
        "wlheader-showupdated": "سون گؤروشونوزدن سونرا ائدیلن دییشیکلیکلر '''قالین''' گؤستریلیبدیلر.",
+       "wlnote": "آشاغیداکی {{PLURAL:$1|'''$1''' ديَیشیک‌لیک|'''$1'''ديَیشیک‌لیک}}  سون {{PLURAL:$2|ساعتدا|'''$2''' ساعتدا}} ائدیلمیشدیر.$3، $4",
        "wlshowlast": "سون $1 ساعات $2 گون گؤستر $3",
        "watchlist-options": "ایزله‌دیکلر سئچمه‌لری",
        "watching": "ایزله‌نیلیر...",
        "duplicate-defaultsort": "'''دیقت:''' احتیمال ائدیلن «$2» دفالت آچاری، قاباقکی «$1» دفالت آچارینی گئچرسیز ائدیر.",
        "version": "نوسخه‌",
        "version-extensions": "قورولموش گنیشلندیرمه‌لر",
+       "version-skins": "قابیقلار",
        "version-specialpages": "اؤزل صحیفه‌لر",
        "version-parserhooks": "آیریشدیران چنگل‌لری",
        "version-variables": "دَییشینلر",
        "version-antispam": "اِسپم اؤنله‌مه",
-       "version-skins": "قابیقلار",
        "version-other": "آیری",
        "version-mediahandlers": "مئدیا ایشلدنلری",
        "version-hooks": "چنگل‌لر",
index 4f28db5..b92e7b6 100644 (file)
@@ -24,7 +24,7 @@
        "tog-newpageshidepatrolled": "Яңы биттәр исемлегендә тикшерелгән үҙгәртеүҙәрҙе йәшер",
        "tog-extendwatchlist": "Барлыҡ үҙгәртеүҙәрҙе үҙ эсенә алған, киңәйтелгән күҙәтеү исемлеге",
        "tog-usenewrc": "Һуңғы төҙәтеүҙәр һәм күҙәтеү исемлегендәге үҙгәрештәрҙе төркөмдәргә бүлергә",
-       "tog-numberheadings": "Башисемдәрҙе автоматик рәүештә номерлаe",
+       "tog-numberheadings": "Башисемдәрҙе автоматик рәүештә номерланһын",
        "tog-showtoolbar": "Мөхәррирләгән ваҡытта өҫкө ҡоралдар панелен күрһәтергә (JavaScript кәрәк)",
        "tog-editondblclick": "Биттәрҙе ике сиртеү менән мөхәррирләргә",
        "tog-editsectiononrightclick": "Бүлектәрҙе исемдәренә төрткөнөң уң яғына сиртеп үҙгәртергә",
        "october-date": "Октябрь $1",
        "november-date": "Ноябрь $1",
        "december-date": "Сентябрь $1",
-       "pagecategories": "{{PLURAL:$1|1=Категория|Категория}}",
+       "pagecategories": "{{PLURAL:$1|1=Категория|Категориялар}}",
        "category_header": "«$1» категорияһындағы биттәр",
        "subcategories": "Эске категориялар",
        "category-media-header": "«$1» категорияһындағы файлдар",
        "category-empty": "\"Был категория әлегә буш.\"",
-       "hidden-categories": "{{PLURAL:$1|1=Йәшерен категория|Йәшерен категориялар}}",
+       "hidden-categories": "{{PLURAL:$1|Йәшерен категория|Йәшерен категориялар}}",
        "hidden-category-category": "Йәшерен категориялар",
-       "category-subcat-count": "{{PLURAL:$2|1=Был категорияла тик киләһе эске категория ғына бар.|$2 эске категорияның $1 эске категорияһы күрһәтелгән.}}",
-       "category-subcat-count-limited": "Был категорияла {{PLURAL:$1|$1 эске категория}} бар.",
+       "category-subcat-count": "{{PLURAL:$2|Был категорияла тик киләһе эске категория ғына бар.|Барлығы $2 категориянан, был категорияла киләһе  {{PLURAL:$1|эске категория|$1 эске категория}} күрһәтелә.}}",
+       "category-subcat-count-limited": "Был категорияға киләһе {{PLURAL:$1|эске категория|$1 эске категория}} ингән.",
        "category-article-count": "{{PLURAL:$2|1=Был категорияла бер генә бит бар.|Категориялағы $2 биттең $1 бите күрһәтелгән.}}",
        "category-article-count-limited": "Был категорияла {{PLURAL:$1|$1 бит}} бар.",
        "category-file-count": "{{PLURAL:$2|Был категорияла бер генә файл бар.|Категориялағы $2 файлдың {{PLURAL:$1|$1 файлы күрһәтелгән}}.}}",
-       "category-file-count-limited": "Ð\91Ñ\83 категорияла {{PLURAL:$1|$1 файл}} бар.",
+       "category-file-count-limited": "Ð\91Ñ\8bл категорияла {{PLURAL:$1|$1 файл}} бар.",
        "listingcontinuesabbrev": "(дауамы)",
        "index-category": "Индексланған биттәр",
        "noindex-category": "Индексланмаған биттәр",
        "talkpagelinktext": "әңг.",
        "specialpage": "Ярҙамсы бит",
        "personaltools": "Шәхси ҡоралдар",
-       "postcomment": "Яңы бүлек",
        "articlepage": "Мәҡәләне ҡарап сығырға",
        "talk": "Әңгәмә",
        "views": "Ҡарауҙар",
        "invalidtitle-knownnamespace": "\"$2\" исем арауығы һәм \"$3\"  тексты исем өсөн ярамай",
        "invalidtitle-unknownnamespace": "\"$2\" тексты һәм \"$1\" арауыҡ өсөн билдәһеҙ номерлы исем ярамай",
        "exception-nologin": "Танылмағанһығыҙ",
-       "exception-nologin-text": "Ð\91Ñ\8bл Ð±Ð¸Ñ\82Ñ\82е Ò¡Ð°Ñ\80аÑ\80 Ð¹Ó\99ки Ò»Ð¾Ñ\80аÑ\82Ñ\8bлÒ\93ан Ò\93Ó\99мÓ\99лде Ð±Ð°Ñ\88ҡаÑ\80Ñ\8bÑ\80 Ó©Ñ\81өн Ñ\81иÑ\81Ñ\82емала Ñ\82анÑ\8bлÑ\8bÑ\83 кәрәк.",
+       "exception-nologin-text": "Ð\91Ñ\8bл Ð±Ð¸Ñ\82Ñ\82е Ò¡Ð°Ñ\80аÑ\83 Ð¹Ó\99ки Ò»Ð¾Ñ\80аÑ\82Ñ\8bлÒ\93ан Ò\93Ó\99мÓ\99лде Ð±Ð°Ñ\88ҡаÑ\80Ñ\8bÑ\83 Ó©Ñ\81өн Ñ\81иÑ\81Ñ\82емала [[Special:Userlogin|Ñ\82анÑ\8bлÑ\8bÑ\80Ò\93а]] кәрәк.",
        "virus-badscanner": "Көйләү хатаһы: Билдәһеҙ вирустар сканеры: ''$1''",
        "virus-scanfailed": "сканлау хатаһы ($1 коды)",
        "virus-unknownscanner": "беленмәгән антивирус:",
        "externaldberror": "Тышҡы мәғлүмәт базаһы менән танылғанда хата барлыҡҡа килде йәки тышҡы үҙ көйләүҙәрегеҙҙе үҙгәртер өсөн хоҡуҡтарығыҙ етәрле түгел.",
        "login": "Танылыу",
        "nav-login-createaccount": "Танылыу йәки теркәлеү",
-       "loginprompt": "{{SITENAME}} проектына кереү өсөн «cookies» рөхсәт ителгән булырға тейеш.",
        "userlogin": "Танылыу йәки теркәлеү",
        "userloginnocreate": "Танылыу",
        "logout": "Тамамлау",
        "nologinlink": "Иҫәп яҙыуын булдырырға",
        "createaccount": "Яңы ҡатнашыусыны теркәү",
        "gotaccount": "Әгәр Һеҙ теркәлеү үткән булһағыҙ? '''$1'''.",
-       "gotaccountlink": "Үҙегеҙ менән таныштырығыҙ",
+       "gotaccountlink": "Танылыу",
        "userlogin-resetlink": "Танылыу мәғлүмәттәрен оноттоғоҙмо?",
        "userlogin-resetpassword-link": "Серһүҙҙе ҡабул итмәү",
        "userlogin-loggedin": " Һеҙ {{GENDER:$1|$1}} булараҡ индегеҙ инде. Башҡа файҙаланыусы булып инер өсөн аҫтағы ҡалыпты ҡулланығыҙ.",
        "password-login-forbidden": "Был ҡатнашыусы исемен һәм серһүҙҙе ҡулланыу тыйылған",
        "mailmypassword": "Яңы серһүҙ ебәрергә",
        "passwordremindertitle": "{{SITENAME}} өсөн яңы ваҡытлыса серһүҙ",
-       "passwordremindertext": "Кемдер (бәлки, һеҙ, IP-адресы: $1) {{SITENAME}} ($4) өсөн яңы серһүҙ һоратты. $2 ҡатнашыусыһы өсөн ваҡытлыса яңы серһүҙ яһалды: $3. Әгәр был һеҙ булһағыҙ, системага керегеҙ һәм серһүҙ алмаштырығыҙ. Яңы серһүҙ $5 {{PLURAL:$5|көн}} ғәмәлдә буласаҡ.\n\nӘгәр һеҙ серһүҙҙе алмаштырыуҙы һоратмаған йәки онотоп кире иҫләгән булһағыҙ һәм үҙгәртергә теләмәһәгеҙ, был хәбәргә иғтибар итмәгеҙ һәм элекке серһүҙегеҙҙе ҡулланыуығыҙҙы дауам итегеҙ.",
+       "passwordremindertext": "Кемдер (бәлки, һеҙ, IP-адресы: $1) {{SITENAME}} ($4) өсөн яңы серһүҙ һоратты. $2 ҡатнашыусыһы өсөн ваҡытлыса яңы серһүҙ яһалды: $3. Әгәр был һеҙ булһағыҙ, системага керегеҙ һәм серһүҙ алмаштырығыҙ. Яңы серһүҙ $5 {{PLURAL:$5|көн}} ғәмәлдә буласаҡ.\n\nӘгәр һеҙ серһүҙҙе алмаштырыуҙы һоратмаған йәки онотоп кире иҫләгән булһағыҙ һәм үҙгәртергә теләмәһәгеҙ, был хәбәргә иғтибар итмәгеҙ һәм элекке серһүҙҙе ҡулланыуҙы дауам итегеҙ.",
        "noemail": "$1 исемле ҡулланыусы өсөн электрон почта адресы белдерелмәгән.",
        "noemailcreate": "Дөрөҫ электрон почта адресы күрһәтеү кәрәк",
        "passwordsent": "Яңы серһүҙ $1 исемле ҡатнашыусының электрон почта адресына ебәрелде.\n\nЗинһар, серһүҙҙе алғас, системаға яңынан керегеҙ.",
        "loginlanguagelabel": "Тел: $1",
        "suspicious-userlogout": "Һеҙҙең сеансты тамамлау тураһында һорауығыҙ кире ҡағылды, сөнки ул төҙөк булмаған браузер йәки кэшлаусы прокси тарафынан ебәрелгән һорауға оҡшаған.",
        "createacct-another-realname-tip": "Ысын исемегеҙ (мотлаҡ түгел).\nУны яҙып ҡуйһағыҙ, ул биткә кем төҙәтеү индергәнен күрһәтеү өсөн ҡулланыласаҡ.",
+       "pt-login": "Танылыу",
+       "pt-login-button": "Танылыу",
+       "pt-userlogout": "Тамамлау",
        "php-mail-error-unknown": "PHP-ның mail() функцияһында билдәһеҙ хата",
        "user-mail-no-addy": "Электрон почта адресы булмайынса электрон хәбәр ебәреп ҡараны",
        "user-mail-no-body": "Буш йә мәғәнәһеҙ йөкмәткеле ҡыҫҡа электрон хат ебәрергә тырышҡан.",
        "resetpass-wrong-oldpass": "Хаталы ваҡытлыса йәки ағымдағы серһүҙ.\nҺеҙ, бәлки, серһүҙегеҙҙе алмаштырғанһығыҙ йәки яңы серһүҙ һоратҡанһығыҙ.",
        "resetpass-temp-password": "Ваҡытлыса серһүҙ",
        "resetpass-abort-generic": "Серһүҙҙе үҙгәртеү киңәйеү тарафынан өҙөлдө.",
+       "resetpass-expired": "Һеҙҙең серһүҙҙең ғәмәл ваҡыты үткән. Зинһар, системала танылыу өсөн яңы серҙһүҙ ҡуйығыҙ.",
        "passwordreset": "Серһүҙҙе ташлатыу",
        "passwordreset-text-one": "Серһүҙегеҙҙе ташлар өсөн ош ҡалыпты тултырығыҙ.",
        "passwordreset-text-many": "{{PLURAL:$1|Серһүҙҙе ташлар өсөн яландарҙың береһен тултырығыҙ.}}",
        "accmailtext": "[[User talk:$1|$1]] өсөн осраҡлы яһалған серһүҙ $2 адресына ебәрелде.\n\nТанылғандан һуң был иҫәп яҙмаһы өсөн серһүҙҙе ''[[Special:ChangePassword|серһүҙҙе үҙгәртеү өсөн махсус биттә үҙгәртә алаһығыҙ]]''.",
        "newarticle": "(Яңы)",
        "newarticletext": "Һеҙ һылтанма буйынса әлегә яһалмаған биткә күстегеҙ.\nЯңы бит яһар өсөн аҫтағы тәҙрәгә текст керетегеҙ (тулыраҡ мәғлүмәт өсөн [$1 ярҙам битен] ҡарағыҙ).\nӘгәр был биткә яңылыш килеп эләккән булһағыҙ, браузерығыҙҙың '''артҡа''' төймәһенә баҫығыҙ.",
-       "anontalkpagetext": "----''Был фекер алышыу бите, иҫәп яҙыуы булдырмаған йәки уны ҡулланмаған аноним ҡатнашыусының бите.\nШуның өсөн ҡулланыусыны таныу өсөн IP-адресы ҡулланыла.\nӘгәр һеҙ аноним ҡулланыусы булһағыҙ һәм һеҙгә ебәрелмәгән хәбәрҙәр алдым тиһәгеҙ (бер IP-адрес күп ҡулланыусы өсөн булырға мөмкин) һәм башҡа бындай аңлашылмаусанлыҡтар килеп сыҡмаһын өсөн, зинар, [[Special:UserLogin|системаға керегеҙ]] йәки [[Special:UserLogin/signup|теркәлегеҙ]].''",
+       "anontalkpagetext": "----\n<em>Был фекер алышыу бите, иҫәп яҙыуы булдырмаған йәки уны ҡулланмаған аноним ҡатнашыусының бите.</em>\nШуның өсөн ҡулланыусыны таныу өсөн IP-адресы ҡулланыла.\nӘгәр һеҙ аноним ҡулланыусы булһағыҙ һәм һеҙгә ебәрелмәгән хәбәрҙәр алдым тиһәгеҙ (бер IP-адрес күп ҡулланыусы өсөн булырға мөмкин) һәм башҡа бындай аңлашылмаусанлыҡтар килеп сыҡмаһын өсөн, зинар, [[Special:UserLogin|системаға керегеҙ]] йәки [[Special:UserLogin/signup|теркәлегеҙ]].",
        "noarticletext": "Хәҙерге ваҡытта был биттә текст юҡ.\nҺеҙ [[Special:Search/{{PAGENAME}}|был исемде башҡа биттәрҙә эҙләй]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} тап килгән журнал яҙмаларын таба]\nйәки '''[{{fullurl:{{FULLPAGENAME}}|action=edit}} бындай исемле яңы бит яһай]'''</span> алаһығыҙ.",
        "noarticletext-nopermission": "Хәҙерге ваҡытта был биттә текст юҡ.\nҺеҙ башҡа биттәрҙә [[Special:Search/{{PAGENAME}}|был исемде]] йәки\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} журналдағы яҙмаларҙы] эҙләй алаһығыҙ, тик һеҙҙең бит яһау хоҡуғығыҙ юҡ.</span>",
        "missing-revision": "\"{{FULLPAGENAME}}\" исемле биттең $1 номерлы өлгөһө юҡ.\n\nБыл хәл, ғәҙәттә, юйылған биткә яһалған һылтанманын ваҡыты үтеүенән барлыҡҡа килә.\nТулыраҡ мәғлүмәт өсөн ҡарағыҙ: [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} юйыу яҙмалары].",
        "revdelete-hide-text": "Биттең был версияһының текстын йәшерергә",
        "revdelete-hide-image": "Файл эстәлеген йәшерергә",
        "revdelete-hide-name": "Ғәмәлде һәм маҡсатын йәшерергә",
-       "revdelete-hide-comment": "Үҙгәртеү тасуирламаларын йәшерергә",
-       "revdelete-hide-user": "Мөхәррирләүсенең исемен/IP-адресын йәшерергә",
+       "revdelete-hide-comment": "Үҙгәртеүҙәр тасуирламаһы",
+       "revdelete-hide-user": "Мөхәррирләүсенең исеме/IP-адресы",
        "revdelete-hide-restricted": "Мәғлүмәттәрҙе хакимдәрҙән дә йәшерергә",
        "revdelete-radio-same": "(үҙгәртмәҫкә)",
-       "revdelete-radio-set": "Эйе",
-       "revdelete-radio-unset": "Юҡ",
+       "revdelete-radio-set": "Ð\99Ó\99Ñ\88еÑ\80ен",
+       "revdelete-radio-unset": "Ð\9aÒ¯Ñ\80енгÓ\99н",
        "revdelete-suppress": "Мәғлүмәттәрҙе шулай уҡ хакимдәрҙән дә йәшерергә",
        "revdelete-unsuppress": "Тергеҙелгән версияларҙан бар сикләүҙәрҙе алырға",
        "revdelete-log": "Сәбәп:",
-       "revdelete-submit": "Һайланған {{PLURAL:$1|1=версия|версиялар}} өсөн ҡулланырға",
+       "revdelete-submit": "Һайланған {{PLURAL:$1|версия|версиялар}} өсөн ҡулланырға",
        "revdelete-success": "'''Версия күренеүсәнлеге уңышлы үҙгәртелде.'''",
        "revdelete-failure": "'''Версия күренеүсәнлеген үҙгәртеп булмай:'''\n$1",
        "logdelete-success": "'''Яҙма күренеүсәнлеге үҙгәртелде.'''",
        "searchprofile-advanced-tooltip": "Махсус исем арауыҡтарында эҙләргә",
        "search-result-size": "$1 ({{PLURAL:$2|1=$2 һүҙ|$2 һүҙ}})",
        "search-result-category-size": "{{PLURAL:$1|1=$1 ағза}} ({{PLURAL:$2|$2 эске категория}}, {{PLURAL:$3|$3 файл}})",
-       "search-result-score": "Тап килеүсәнлек: $1%",
        "search-redirect": "(йүнәлтеү $1)",
        "search-section": "($1 бүлеге)",
        "search-suggest": "Бәлки, ошоно эҙләйһегеҙҙер: $1",
        "uploadwarning": "Киҫәтеү",
        "uploadwarning-text": "Зинһар, түбәндәге файл тасуирламаһын үҙгәртегеҙ һәм яңынан ҡабатлап ҡарағыҙ.",
        "savefile": "Һөҙгөстө яҙҙырып ҡуйырға",
-       "uploadedimage": "«[[$1]]» тейәлгән",
-       "overwroteimage": "\"[[$1]]\" файлының яңы өлгөһө тейәлде",
        "uploaddisabled": "Тейәү рөхсәт ителмәй",
        "copyuploaddisabled": "URL адрес аша тейәү рөхсәт ителмәй.",
        "uploaddisabledtext": "Файлдар тейәү рөхсәт ителмәй.",
        "watchlist-details": "Һеҙҙең күҙәтеү исемлегегеҙҙә, фекерләшеү биттәрен һанамағанда, {{PLURAL:$1|$1 бит}} бар.",
        "wlheader-enotif": "Электрон почта аша белдереү индерелгән.",
        "wlheader-showupdated": "Һеҙҙең аҙаҡҡы кереүегеҙҙән һуң үҙгәргән биттәр '''ҡалын''' шрифт менән күрһәтелгән.",
+       "wlnote": "Түбәндә $3 $4 ваҡытына тиклем аҙаҡҡы {{PLURAL:$2|1=сәғәт|'''$2''' сәғәт}} эсендә эшләнгән {{PLURAL:$1|1=үҙгәртеү|'''$1''' үҙгәртеү}} күрһәтелгән.",
        "wlshowlast": "Һуңғы $1 сәғәт $2 көн өсөн күрһәт $3",
        "watchlist-options": "Күҙәтеү исемлеге көйләүҙәре",
        "watching": "Күҙәтеү исемлегенә өҫтәү...",
        "duplicate-defaultsort": "'''Иҫкәртеү:''' \"$2\" ғәҙәттәге тәпртипкә килтереү асҡысы элекке \"$1\" ғәҙәттәге тәртипкә килтереү асҡысын үҙгәртә.",
        "version": "MediaWiki өлгөһө",
        "version-extensions": "Ҡуйылған киңәйтеүҙәр",
+       "version-skins": "Күренештәр",
        "version-specialpages": "Махсус биттәр",
        "version-parserhooks": "Уҡыу ҡоралдары",
        "version-variables": "Үҙгәреүсән дәүмәлдәр",
        "version-antispam": "Спамға ҡаршы ҡорал",
-       "version-skins": "Күренештәр",
        "version-other": "Башҡалар",
        "version-mediahandlers": "Медиа эшкәртеүсе ҡоралдар",
        "version-hooks": "Эләктереп алыусылар",
index d2f090e..4ebcf4a 100644 (file)
@@ -24,7 +24,7 @@
        "tog-extendwatchlist": "Daweiterde Beówochtungslisten",
        "tog-usenewrc": "Endarunga vo \"Lezde Endarunga\" und vo \"Mei Beobochtd\" noch Seitn gruppian",
        "tog-numberheadings": "Ywerschriften autómaatisch nummerrirn",
-       "tog-showtoolbar": "Beorweiten-Werkzeigleisten åzoang (JavaScript werd braucht)",
+       "tog-showtoolbar": "Zoag de Edit Toolbar (JavaScript nedig)",
        "tog-editondblclick": "Seiten mid am Dóppedrucker beorweiden (JavaScript werd braucht)",
        "tog-editsectiononrightclick": "Oahzelne Obschnitt mid am Rechtsdrucker beorweiten (JavaScript werd braucht)",
        "tog-watchcreations": "Voh mir söwer eihgstöde Seiten autómaatisch beówochten",
        "talkpagelinktext": "Dischkrian",
        "specialpage": "Speziaalseiten",
        "personaltools": "Mei Weakzeig",
-       "postcomment": "Neicher Obschnit",
        "articlepage": "Seiteninhoid åzoang",
        "talk": "Dischkrian",
        "views": "Osichtn",
        "externaldberror": "Entweder es ligt a Feeler bai da externen Authentifiziarung vur oder du derfst dai externs Benytzerkonto ned aktualisirn.",
        "login": "Eilogga",
        "nav-login-createaccount": "Eilogga / Konto olegn",
-       "loginprompt": "Zua Omejdung miassen Cookies aktiviat sei.",
        "userlogin": "Eilogga / Konto olegn",
        "userloginnocreate": "Åmöden",
        "logout": "Obmöden",
        "emptyfile": "Dé aufféglooderne Daatei is laar. Da Grund kauh a Tippfeeler im Daateinaum seih. Bittscheh kóntróllier, ób du dé Daatei wirklé aufféloon wüst.",
        "uploadwarning": "Ówocht",
        "savefile": "Daatei speichern",
-       "uploadedimage": "hod „[[$1]]“ affeglodn",
        "uploaddisabled": "'s aufféloon is deaktivierd",
        "uploadscripted": "Dé Datei enthoit HTML- óder Scriptcode, der wos irrtymlicherweis voram Webbrowser ausgfyrd wern kunnterd.",
        "uploadvirus": "Dé Daatei do enthoitt a Virus! Details: $1",
        "linkstoimage-more": "Es {{PLURAL:$1|valinkt|valinkn}} mea wia {{PLURAL:$1|oa Seitn |$1 Seitn}} auf de Datei.\nDe foignde Listn zaagt netta {{PLURAL:$1|in easten Link|de easten $1 Links}} auf de Datei.\nA [[Special:WhatLinksHere/$2|voiständige Listn]] gibt's aa.",
        "nolinkstoimage": "De Datei wead vo koana Seitn gnutzt.",
        "morelinkstoimage": "[[Special:WhatLinksHere/$1|Weidare Links]] fia de Datei.",
+       "linkstoimage-redirect": "$1 (Dateiweidaloatung) $2",
        "duplicatesoffile": "{{PLURAL:$1|D'foignde Datei is a Duplikat|De foigndn $1 Datein han Duplikate}} vu dea Datei ([[Special:FileDuplicateSearch/$2|weidare Deteus]]):",
        "sharedupload": "De Datei stãmmt aus $1 und deaf bei ãndare Projekte vawendt wean.",
        "sharedupload-desc-there": "De Datei stãmmt aus $1 und deaf bei ãndera Projekte vawendt wean. Schau auf'd [$2 Dateibeschreibungsseitn] fia weidare Infoamazionen.",
        "filedelete-intro": "Du léschst dé Daatei '''„[[Media:$1|$1]]“'''.",
        "mimesearch-summary": "Auf dieser Spezialseite können die Dateien nach dem MIME-Typ gefiltert werden. Die Eingabe muss immer den Medien- und Subtyp beinhalten: <code>image/jpeg</code> (siehe Bildbeschreibungsseite).",
        "download": "Owerlooden",
+       "listredirects": "Weidaloatunga",
        "unusedtemplates": "Net benutzte Vorlagen",
        "unusedtemplateswlh": "Aundre Links",
        "randompage": "Zuafoisseitn",
+       "randomredirect": "Zuafällige Weidaloatung",
        "statistics": "Statistik",
        "statistics-articles": "Inhoidsseiten",
        "statistics-pages": "Seiten",
        "statistics-edits-average": "Beorweitungen pró Seiten im Durchschnit",
        "statistics-views-total": "Seitenaufruaff gsåmmt",
        "statistics-mostpopular": "Dé am moastbsuachten Seiten",
-       "doubleredirects": "Doppede Weiderloatungen",
+       "doubleredirects": "Doppede Weidaloatunga",
+       "doubleredirectstext": "Af dea Seitn stengan Weidaloatunga, de wo af Weidaloatunga zoang.\n\nA <del>duachgstrichane</del> Eidrog is scho repariad worn.",
+       "double-redirect-fixed-maintenance": "Doppede Weidaloatunga vo [[$1]] af [[$2]] mid oana Aktion reparian.",
+       "brokenredirectstext": "Af dera Spezialseitn stengan Weidaloatunga af Artiken, de wo s ned gibt.",
        "brokenredirects-edit": "werkeln",
        "brokenredirects-delete": "léschen",
        "withoutinterwiki": "Seitn ohne Sprochlinks",
        "wantedcategories": "Bnutzde, ower néd åglégte Kategorien",
        "wantedpages": "Gwynschde Seiten",
        "wantedpages-badtitle": "Ungütiger Titel im Ergeewnis: $1",
-       "wantedfiles": "Fööhernde Daatein",
-       "wantedtemplates": "Fööhernde Vurlong",
+       "wantedfiles": "Datein, wo ma braucha",
+       "wantedtemplates": "Voalong, wo ma braucha",
        "mostlinked": "Haiffig valinkte Seiten",
        "mostlinkedcategories": "Haiffig brauchde Kategorien",
        "mostlinkedtemplates": "Haiffig brauchde Vurlong",
        "allpagesprefix": "Seiten zoang mid Präfix:",
        "allpagesbadtitle": "Da eihgeewerne Seitennaum is néd gütig: Er hod éntwéder a vurauhgstöds Sprooch-, a Interwiki-Kyrzel óder enthoitt oah óder mererne Zeichen, dé in d' Seitennaumen néd vawendt wern derffm.",
        "allpages-bad-ns": "Dén Naumensraum „$1“ gibts in {{SITENAME}} néd.",
+       "allpages-hide-redirects": "Weidaloatunga ausblendn",
        "categories": "Kategorina",
        "special-categories-sort-count": "Sortiarung noch da Auhzoi",
        "special-categories-sort-abc": "Sortiarung noch 'm Alfabet",
        "listgrouprights-addgroup-self-all": "Kauh olle Gruppm zum oagern Kóntó dazuadoah",
        "mailnologin": "Du bist néd auhgmödt",
        "emailuser": "Mail an den Nutza",
-       "emailpage": "E-Mail aun Benutzer",
-       "noemailtitle": "Koah E-Mail-Adress",
+       "emailpage": "E-Mail an Nutza",
+       "noemailtitle": "Koa Mail-Adress",
        "emailfrom": "Voh:",
        "emailto": "Aun:",
        "emailsubject": "Bedreff:",
        "watchlist-details": "Du beoochst {{PLURAL:$1|$1 Seitn}}, Dischkriaseitn ned mitgrechnad",
        "wlheader-enotif": "Da E-Mail-Benoochrichtigungsdeanst is aktivierd.",
        "wlheader-showupdated": "Seiten mid noh néd gseengne Änderrungen wern '''fett''' dorgstöd.",
+       "wlnote": "Es {{PLURAL:$1|fóigt d' létzde Änderrung|fóing d' létzden '''$1''' Änderrungen}} voh da/dé {{PLURAL:$2|Stund| '''$2''' Stunden}}. Staund: $3, $4 Uar.",
        "wlshowlast": "Zoag dé Änderrungen voh dé létzden $1 Stunden, $2 Dog óder $3 (in dé létzden 30 Dog).",
        "watchlist-options": "Mei Beobochta: Optiona",
        "watching": "Beówochten ...",
        "ipbreason-dropdown": "* Oigmoahne Sperrgrynd\n** Eihfyng voh voische Informaziónen\n** Laarn voh Seiten\n** Massenweiss Eihfyng voh externe Links\n** Eihstön voh unsinnige Inhoite auf Seiten\n** néd åbrochts Vahoiden\n** Missbrauch mid mererne Benutzerkontós\n** néd geigneter Benutzernåm",
        "ipb-hardblock": "Auhgmödte Benutzer dodrauh hindern, daas Beorweitungen unter derer IP-Adress vurgnummer wern",
        "ipbcreateaccount": "D' Erstöung voh Benutzerkóntós vahindern",
-       "ipbemailban": "E-Mail-Vasånd sperrn",
+       "ipbemailban": "E-Mail-Vasand spean",
        "ipbenableautoblock": "Sperr dé aktuö voh dém Benutzer gnutzde IP-Adress sówia autómaatisch olle fóiganden, voh dénen aus er Beorweitungen óder 's Auhléng voh Benutzerkóntós vasuacht.",
        "ipbsubmit": "IP-Adress/Benutzer sperrn",
        "ipbother": "Åndre Dauer (auf englisch):",
        "ipusubmit": "Freigem",
        "unblocked": "[[User:$1|$1]] is freigem worn",
        "unblocked-id": "Sperr-ID $1 is fraigeem worn",
+       "blocklist": "Gspeade Nutza",
        "ipblocklist": "Gsperrte Nutza",
        "ipblocklist-legend": "Suach noch am gsperrden Benytzer",
        "createaccountblock": "'s erstön voh Benutzerkóntós is gsperrd",
        "unblocklink": "Freigebm",
        "change-blocklink": "Sperr endan",
        "contribslink": "Beidreg",
-       "emaillink": "E-Póst schicker",
+       "emaillink": "E-Mail vaschicka",
        "autoblocker": "Autómaatische Sperr, wei du a gmoahsaume IP-Adress mim [[User:$1|$1]] bnutzd. Grund voh da Benutzersperrn: „$2“.",
        "blocklogpage": "Sperrlogbuach",
        "blocklog-showlog": "{{GENDER:$1|Der Benutzer|Dé Benutzerrin|Der Benutzer}} do is schoh friarer gsperrd worn. Es fóigt a Eihtrog aus'm Benutzersperrlogbiaché:",
        "block-log-flags-anononly": "netter Anónyme",
        "block-log-flags-nocreate": "Es Olegn vo Nutzakontn is gsperrt",
        "block-log-flags-noautoblock": "Autóblóck deaktivierd",
-       "block-log-flags-noemail": "E-Post vaschicka gspead",
+       "block-log-flags-noemail": "Mail vaschicka gspead",
        "unlockdb": "Daatenbaunk freigeem",
        "unlockconfirm": "Ja, i mecht de Datenbank freigem.",
        "unlockbtn": "Datenbank freigem",
        "movepagebtn": "Seitn vaschiam",
        "pagemovedsub": "s'Vaschiam håd highaud",
        "movepage-moved": "'''D'Seitn „$1“ is nåch „$2“ vaschom woan.'''",
-       "movepage-moved-redirect": "Es is a Weiderloatung erstöd worn.",
+       "movepage-moved-redirect": "A Weidaloatung eigricht worn.",
+       "movepage-moved-noredirect": "De Eirichtung vo oana Weidaloatung is vahindat worn.",
        "articleexists": "Unter dém Naum existierd schoh a Seiten. Bittscheh nimm an aundern Naumen her.",
        "movetalk": "Waunns geet, d' Dischkrierseiten aa midvaschiam",
        "movelogpage": "Vaschiabungs-Logbuach",
        "lastmodifiedatby": "Dé Seiten is zletzt am $1 um $2 voh $3 gänderd worn.",
        "othercontribs": "Basiard auf da Orweid voh $1",
        "creditspage": "Seiteninformaziónen",
+       "pageinfo-redirects-name": "Ozoi vo de Weidaloatunga zua dea Seitn",
+       "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|Weidaloatung|Weidaloatunga}}; $3 {{PLURAL:$3|Untaseitn|Untaseitn}})",
+       "pageinfo-redirectsto": "Weidaloatunga af",
        "markedaspatrollederrortext": "Du muasst a Seitenänderrung auswön",
        "deletedrevision": "Oide Version $1 glöscht.",
        "filedelete-missing": "De Datei „$1“ ko net glöscht wern, weils es net gibt.",
        "htmlform-submit": "Speichern",
        "htmlform-reset": "Änderrungen ryckgängég mochen",
        "htmlform-selectorother-other": "Åndre",
+       "logentry-move-move_redir": "$1 hod de Seitn $3 af $4 {{GENDER:$2|verschom}} und hod dabei a Weidaloatung ibaschriem",
+       "logentry-move-move_redir-noredirect": "$1 hod de Seitn $3 af $4 {{GENDER:$2|verschom}} und dabei a Weidaloatung ibaschriem, ohne a neiche ozlegn",
        "searchsuggest-search": "Suach",
        "searchsuggest-containing": "Voitextsuach noch ..."
 }
index 96ab52c..829e636 100644 (file)
@@ -10,7 +10,8 @@
                        "WBT003Bugari",
                        "WBT004Togu",
                        "WBT006Hendra",
-                       "WBT009Anju"
+                       "WBT009Anju",
+                       "아라"
                ]
        },
        "tog-underline": "Ondolhon panait",
        "qbmyoptions": "Alaman niiba",
        "faq": "FAQ",
        "faqpage": "Project:FAQ",
-       "vector-action-addsection": "Bagian na imbaru",
-       "vector-action-delete": "Sesa",
-       "vector-action-move": "Pahusor",
-       "vector-action-protect": "Ramoti",
-       "vector-action-undelete": "unang sesa",
-       "vector-action-unprotect": "Uba parlindungan",
-       "vector-view-create": "Tompa",
-       "vector-view-edit": "Paubah",
-       "vector-view-history": "Patudu andorang na",
-       "vector-view-view": "Jaha",
-       "vector-view-viewsource": "Ida haroanna",
        "actions": "Pangulahonon",
        "namespaces": "Inganan ni goar",
        "variants": "Angka ragam",
        "talkpage": "Hatahon alaman on",
        "talkpagelinktext": "Pangkataion",
        "personaltools": "Ula-ula ni sasahalak",
-       "postcomment": "Bagian imbaru",
        "talk": "Panghataion",
        "views": "Hataridaan",
        "toolbox": "Poti ulaula",
        "nstab-help": "Alaman pangurupion",
        "nstab-category": "Kategori",
        "error": "Hasesega",
-       "fileappenderror": "Ndang boi pamasuhon \"$1\" tu \"$2\".",
        "badarticleerror": "Ulaon on dang boi i ulahon di alaman on",
        "cannotdelete-title": "Ndang boi manesa alaman \"$1\"",
        "badtitle": "Ulu ni surat na rumar",
        "password-change-forbidden": "Ndang boi ubaonmu hata hincu di wiki on",
        "login": "Bongot tu log",
        "nav-login-createaccount": "Bongot tu log/ bahen akun",
-       "loginprompt": "Ikkon dipangolu do \"cookies\" laho bongot log tu {{SINTENAME}}.",
        "userlogin": "Bongot tu log/ bahen akun",
        "userlogout": "Haruar log",
        "userlogin-noaccount": "Ndang adong akun",
        "searchmenu-exists": "'''Adong sada alaman na digoari \"[[:$1]]\" di wiki on.'''",
        "searchmenu-new": "'''Bahen alaman \"[[:$1]]\" di wiki on!'''",
        "searchprofile-articles": "Alaman isi",
-       "searchprofile-project": "Alaman pangurupion dohot proyek",
        "searchprofile-images": "Akat na godang gunana",
        "searchprofile-everything": "Sasude",
        "searchprofile-advanced": "Timbul",
        "searchprofile-articles-tooltip": "Mandiori di $1",
-       "searchprofile-project-tooltip": "Mandiori di $1",
        "searchprofile-images-tooltip": "Mandiori berkas",
        "searchprofile-everything-tooltip": "Mandiori di sude inganan (dohot di alaman panghataion)",
        "searchprofile-advanced-tooltip": "Mandiori pake inganan ni goar",
        "recentchanges-label-minor": "Sada panotaan na metmet",
        "recentchanges-label-bot": "Panotaan on diulahon bot",
        "recentchanges-label-unpatrolled": "Panotaan on ndang dipamanat dope",
-       "rclistfrom": "Patuduhon parubaan na imbaru mamungka sian $1",
+       "rclistfrom": "Patuduhon parubaan na imbaru mamungka sian $3 $2",
        "rcshowhideminor": "$1 panotaan na metmet",
        "rcshowhidebots": "$1 bot",
        "rcshowhideliu": "$1 pamarhaseang bongot tu log",
        "booksources-go": "Torushon",
        "log": "Angka log",
        "allpages": "Sude alaman",
-       "alphaindexline": "$1 tu $2",
        "allarticles": "Sude alaman",
        "allpagessubmit": "Torushon",
        "categories": "Angka horong",
index dec808c..08c0dde 100644 (file)
@@ -8,7 +8,9 @@
                        "Reedy",
                        "ZxxZxxZ",
                        "아라",
-                       "RigiMahnoor"
+                       "RigiMahnoor",
+                       "Oldstoneage",
+                       "Baloch Afghanistan"
                ]
        },
        "tog-underline": ":لینکانآ خط کش",
        "talkpagelinktext": "گپ کن",
        "specialpage": "حاصین صفحه",
        "personaltools": "شخصی وسایل",
-       "postcomment": "نوکین بخش",
        "articlepage": "محتوا صفحه به گند",
        "talk": "بحث",
        "views": "چارگان",
        "hidetoc": "پناه کن",
        "collapsible-collapse": "چیر داتن",
        "collapsible-expand": "تچک کتن",
+       "confirmable-confirm": "آیا {{GENDER:$1|شما}} مطمعین ویت?",
+       "confirmable-yes": "هان",
+       "confirmable-no": "نه",
        "thisisdeleted": "به گند یا پچ ترین $1?",
        "viewdeleted": "به گند $1?",
        "restorelink": "{{PLURAL:$1|یک حذف اصلاح|$1 حذف اصلاح}}",
        "externaldberror": "یک حطا دیتابیس تصدیق هویت دراییگی هست یا شما را اجازت نیست وتی حساب درایی په روچ کنیت.",
        "login": "ورود",
        "nav-login-createaccount": "ورود/شرکتن حساب",
-       "loginprompt": "شما بایدن په وارد بیگ ته {{SITENAME}} کوکی فعال کنیت",
        "userlogin": "ورود/شرکتن حساب",
        "userloginnocreate": "لاگین",
        "logout": "در بیگ",
        "searchprofile-advanced-tooltip": "گردگ ته نام فضایان دل واه",
        "search-result-size": "$1 ({{PLURAL:$2|1کلمه|$2 کلمات}})",
        "search-result-category-size": "{{PLURAL:$1|یک عضو|$1 عضو}} ({{PLURAL:$2|یک جهلرده|$2 جهلرده}}، {{PLURAL:$3|یک فایل|$3 فایل}})",
-       "search-result-score": "ربط: $1%",
        "search-redirect": "(غیر مستقیم $1 )",
        "search-section": "(بخش $1 )",
        "search-file-match": "(فایلء محتواء همجندی)",
        "file-deleted-duplicate": "یک فایلی په داب ای فایل ([[:$1]]) پیسرتر حذف بوتگت. شما بایدن تاریح حذف آ فایلء دگه بچاریت",
        "uploadwarning": "هوژاری آپلود",
        "savefile": "ذخیره فایل",
-       "uploadedimage": "اپلود بوت \"[[$1]]\"",
-       "overwroteimage": "یک نوکین نسخه چه \"[[$1]]\" آپلود بیتت",
        "uploaddisabled": "آپ.د غبر فعال انت",
        "uploaddisabledtext": "آپلود فایل غیر فعال انت.",
        "php-uploaddisabledtext": "آپلود کتن فایل ته پی‌اچ‌پی فعال نهنت. تنظیم file_uploads کنترل کنیت.",
        "watchlist-details": "{{PLURAL:$1|$1 صفحه|$1 صفحات}} چارتگ بیت صفحات گپ حساب نه بیگن",
        "wlheader-enotif": "اخطار ایمیل فعالنت.",
        "wlheader-showupdated": "صفحات که عوض بوتگنت چه شمی آهری چارتن '''پررنگ''' پیش دراگ بنت.",
+       "wlnote": "جهلء {{PLURAL:$1|آهرین تغییر هست|آهرین هست'''$1''' تغییرات}} ته آهرین {{PLURAL:$2|ساعت|'''$2''' ساعات}}.",
        "wlshowlast": "پیش دار آهرین $1  ساعات $2 روچان $3",
        "watchlist-options": "گزینه یان لیست چارگ",
        "watching": "چارگ بین",
        "import": "وارد کن صفحاتء",
        "importinterwiki": "ورود بین ویکی",
        "import-interwiki-text": "یک ویکی و  عنوان صفحه انتخاب کن په ورود.\nتاریح بازبینی و نامان اصلاح کنوکان دارگ بیت.\nکل کاران ورود بین ویکی وارد بیت نه [[Special:Log/import|ورود آمار]].",
-       "import-interwiki-source": "ویکی بن در/صفحه:",
        "import-interwiki-history": "کپی کن کل بازبینی آن تاریح په ای صفحه",
        "import-interwiki-templates": "کل تمپلت هور بنت",
        "import-interwiki-submit": "ورود",
        "hebrew-calendar-m12-gen": "الول",
        "unknown_extension_tag": "ناشناس برجسب الحاق  \"$1\"",
        "duplicate-defaultsort": "هژاری: ترتیب پیش فرض «$2» ترتیب پیش فرض پیشگین «$1» را باطل کنت.",
-       "version": "نسخه",
+       "version": "نسخة",
        "version-extensions": "نصب بوتگیت الحاق آن",
        "version-specialpages": "حاصین صفحات",
        "version-parserhooks": "تجزیه کنوک گیر کت",
        "expand_templates_ok": "هوبنت",
        "expand_templates_remove_comments": "بزور نظرات",
        "expand_templates_generate_xml": "پیش دار درچک تجزیه XMLء",
-       "expand_templates_preview": "بازبین"
+       "expand_templates_preview": "بازبین",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (پعال)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''غیر پعال''')"
 }
index f5fb077..f489f8f 100644 (file)
@@ -12,9 +12,9 @@
                ]
        },
        "tog-underline": "Linyahan an kilyawan:",
-       "tog-hideminor": "Tagóon an mga saradít na paghirá sa nakakaági pa sanáng pagbabàgo",
+       "tog-hideminor": "Tagoon an saradít na mga pagliwat sa dae pa sana nahaloy na mga pagbabàgo",
        "tog-hidepatrolled": "Tagóa an patrolyadong mga paghirá sa nakakaági pa sanáng pagbabàgo",
-       "tog-newpageshidepatrolled": "Tagóa an patrolyadong mga pahina gikan sa listahan kan bàgong pahina",
+       "tog-newpageshidepatrolled": "Tagoon an patrolyadong mga pahina gikan sa baguhong listahan nin pahina",
        "tog-extendwatchlist": "Palakbanga an bantay-listahan (watchlist) na maipahiling an gabos na pinagbago, bako sana an pinakahurihang binago",
        "tog-usenewrc": "Pangrupong mga kaliwatan sa kada pahina kan mga dae pa sana nahaloy na mga kaliwatan asin bantay-listahan",
        "tog-numberheadings": "Tolos-bilang na mga pamayohán",
@@ -27,7 +27,7 @@
        "tog-watchdeletion": "Idagdag an mga pahina asin mga sagunson na ako an nagpura sa sakong bantay-listahan",
        "tog-minordefault": "Markahán gabos na saradit na pagliwat sa paaging panugmad",
        "tog-previewontop": "Ipahilíng an patànaw bàgo an kahon nin paghirá",
-       "tog-previewonfirst": "Ipahilíng an patànaw sa enot na paghirá",
+       "tog-previewonfirst": "Ipahiling an patànaw sa enot na pagliwat",
        "tog-enotifwatchlistpages": "E-suratan mo ako kunsoarin an sarong pahina o sagunson na yaon sa sakong bantay-listahan pinagliwat",
        "tog-enotifusertalkpages": "E-koreohan ako pag pigribáyan an pahina kan sakóng olay",
        "tog-enotifminoredits": "E-suratan man ako para sa saraditon na mga pagliwat kan mga pahina asin mga sagunson",
@@ -49,8 +49,8 @@
        "tog-norollbackdiff": "Omidohon an diff matapos himoon an pagbalikot",
        "tog-useeditwarning": "Patanidan ako kunsoarin na ako nagbaya sa pahinang pigliliwat na dae naitatagama an mga kaliwatan",
        "tog-prefershttps": "Pirmeng gumamit nin sarong seguradong koneksyon kunsoarin na ika nakalaog na",
-       "underline-always": "Pirmi",
-       "underline-never": "Nungka",
+       "underline-always": "Parati",
+       "underline-never": "Dae pa lamang",
        "underline-default": "Kublit o kilyaw na panugmad",
        "editfont-style": "Baguhon an estilo nin kalwig sa sinasakupan",
        "editfont-default": "Kilyawang tugmad",
        "june-date": "Hunyo $1",
        "july-date": "Hulyo $1",
        "august-date": "Agosto $1",
-       "september-date": "Septiyembre $1",
-       "october-date": "Oktubre $1",
+       "september-date": "Septyembre $1",
+       "october-date": "Oktobre $1",
        "november-date": "Nobyembre $1",
        "december-date": "Disyembre $1",
        "pagecategories": "{{PLURAL:$1|Kategorya|Mga kategorya}}",
        "category_header": "Mga pahina sa kategoryang \"$1\"",
        "subcategories": "Mga sub-kategorya",
        "category-media-header": "Media sa kategoryang \"$1\"",
-       "category-empty": "''Ining kategorya sa presente mayong laog na mga pahina o media.\"",
+       "category-empty": "''Ining kategorya sa ngunyan mayong laog nin mga pahina o midya.''",
        "hidden-categories": "{{PLURAL:$1|Nakatagong kategorya|Mga nakatagong kategorya}}",
        "hidden-category-category": "Mga nakatagong kategorya",
        "category-subcat-count": "{{PLURAL:$2|Ining kategorya igwa sana kan minasunod na sub-kategorya.|Ining kategorya igwa kan minasunod {{PLURAL:$1|subcategory|$1 subcategories}}, out of $2 total.}}",
        "category-article-count-limited": "An minasunod na {{PLURAL:$1|pahina|$1 mga pahina}} yaon sa presenteng kategorya.",
        "category-file-count": "{{PLURAL:$2|Ining kategorya naglalaman sana kan minasunod na sagunson.|An minasunod {{PLURAL:$1|sagunson iyo|$1 na mga sagunson iyo}} sa kategoryang ini, na ginahi sa $2 sa kabilogan.}}",
        "category-file-count-limited": "An minasunod {{PLURAL:$1|na sagunson|$1 na mga sagunson}} yaon sa presenteng kategorya.",
-       "listingcontinuesabbrev": "sunód",
-       "index-category": "Hinukdoang mga pahina",
-       "noindex-category": "Bakong hinukdoang mga pahina",
+       "listingcontinuesabbrev": "kasumpay",
+       "index-category": "Panhinukdong mga pahina",
+       "noindex-category": "Bakong panhinukdong mga pahina",
        "broken-file-category": "Mga pahina na igwang nagkaparasa na sagunsong kilyawan",
        "about": "Manonongod",
        "article": "Laog na pahina",
        "newwindow": "(minabukas sa bàgong bintanà)",
        "cancel": "Kanselaron",
        "moredotdotdot": "Kadagdagan...",
-       "morenotlisted": "Ining listahan bako pang kumpleto.",
-       "mypage": "An Pahina",
-       "mytalk": "Orolayan",
-       "anontalk": "Olay para kaining IP address",
-       "navigation": "Nabigasyon",
+       "morenotlisted": "Ining listahan bakong kumpleto.",
+       "mypage": "Pahina",
+       "mytalk": "Mag-ulay",
+       "anontalk": "Urulay para kaining IP estada",
+       "navigation": "Paglibotlibot",
        "and": "&#32;asin",
        "qbfind": "Maghanap",
-       "qbbrowse": "Halungkáta",
-       "qbedit": "Liwata",
+       "qbbrowse": "Maghalungkat",
+       "qbedit": "Liwaton",
        "qbpageoptions": "Ining pahina",
        "qbmyoptions": "Sakong mga pahina",
-       "faq": "PPK (Pirmihang Pighahapot na mga kahaputan)",
-       "faqpage": "Project:PPK (Pirmihang Pighahapot na mga Kahaputan)",
-       "actions": "Mga aksyon",
+       "faq": "PHK (Pirmehang Hinahapot na mga Kahaputan)",
+       "faqpage": "Proyekto:PHK",
+       "actions": "Mga paghiro",
        "namespaces": "Mga espasyong ngaran",
-       "variants": "Mga pinalaen",
-       "navigation-heading": "Listahan sa Nabigasyon",
+       "variants": "Mga Kinalaenan",
+       "navigation-heading": "Hihilngan sa paglibotlibot",
        "errorpagetitle": "Salâ",
        "returnto": "Magbalik sa $1.",
        "tagline": "Gikan sa {{SITENAME}}",
        "searchbutton": "Maghanap",
        "go": "Dumani",
        "searcharticle": "Lakaw",
-       "history": "Historiya kan pahina",
-       "history_short": "Historiya",
+       "history": "Uusipon kan pahina",
+       "history_short": "Uusipon",
        "updatedmarker": "dinagdagan poon kan sakong huring pagbisita",
-       "printableversion": "Puwede maimprintang bersyon",
+       "printableversion": "Nalilimbag na bersyon",
        "permalink": "Permanenteng kilyawan",
-       "print": "Imprintaron",
-       "view": "Tanawon",
-       "view-foreign": "Hilngon sa $1",
-       "edit": "Liwatón",
+       "print": "Ilimbag",
+       "view": "Tànawon",
+       "view-foreign": "Hilingon sa $1",
+       "edit": "Liwaton",
        "edit-local": "Liwaton an lokal na deskripsyon",
        "create": "Muknaon",
        "create-local": "Idugang an lokal na deskripsyon",
-       "editthispage": "Liwata ining pahina",
+       "editthispage": "Liwaton ining pahina",
        "create-this-page": "Muknaon ining pahina",
        "delete": "Puraon",
        "deletethispage": "Puraon ining pahina",
        "undeletethispage": "Balikon sa pagkapura ining pahina",
-       "undelete_short": "Bawia an pagpurà kan {{PLURAL:$1|sarong pagliwat|$1 mga pagliwat}}",
-       "viewdeleted_short": "Hilngon {{PLURAL:$1|sarong pinara na pagliwat|$1 mga pinara na pagliwat}}",
+       "undelete_short": "Bawion an {{PLURAL:$1|sarong pagliwat|$1 mga pagliwat}}",
+       "viewdeleted_short": "Hilingon {{PLURAL:$1|sarong pinara na pagliwat|$1 mga pinara na pagliwat}}",
        "protect": "Protektari",
        "protect_change": "Ribayan",
        "protectthispage": "Protektaran ining pahina",
-       "unprotect": "Ribayi an proteksyon",
-       "unprotectthispage": "Ribayi an proteksyon kaining pahina",
+       "unprotect": "Ribayan an proteksyon",
+       "unprotectthispage": "Ribayan an proteksyon kaining pahina",
        "newpage": "Bàguhong pahina",
-       "talkpage": "Orolayan ining pahina",
-       "talkpagelinktext": "Olay",
-       "specialpage": "Espesyal na Pahina",
-       "personaltools": "Personal na mga kagamitan",
-       "postcomment": "Baguhong seksyon",
-       "articlepage": "Tanawon an laog kan pahina",
-       "talk": "Orolayan",
+       "talkpage": "Urulayan ining pahina",
+       "talkpagelinktext": "Mag-ulay",
+       "specialpage": "Espesyal na pahina",
+       "personaltools": "Pansadiring mga gamiton",
+       "articlepage": "Tànawon an laog kan pahina",
+       "talk": "Urulayan",
        "views": "Mga Tanawon",
-       "toolbox": "Mga gagamiton:",
-       "userpage": "Tanawon an pahina kan parágamit",
-       "projectpage": "Tanawon an pahina kan proyekto",
-       "imagepage": "Hilngón an pahina nin sagunson (file)",
-       "mediawikipage": "Tanawon an pahina kan mensahe",
-       "templatepage": "Tanawon an pahina kan panguyog",
-       "viewhelppage": "Tanawon an pahina nin katabangan",
-       "categorypage": "Tanawon an pahina nin kategorya",
-       "viewtalkpage": "Tanawon an orolayan",
+       "toolbox": "Mga gamiton:",
+       "userpage": "Tànawon an pahina kan paragamit",
+       "projectpage": "Tànawon an pahina kan proyekto",
+       "imagepage": "Tànawon an pahina nin sagunson (file)",
+       "mediawikipage": "Tànawon an pahina kan mensahe",
+       "templatepage": "Tànawon an pahina kan panguyog",
+       "viewhelppage": "Tànawon an pahina nin pagtabang",
+       "categorypage": "Tànawon an pahina nin kategorya",
+       "viewtalkpage": "Tànawon an urulay",
        "otherlanguages": "Sa ibang mga lengguwahe",
-       "redirectedfrom": "(Redirektado gikan sa $1)",
-       "redirectpagesub": "Redirektang pahina",
+       "redirectedfrom": "(Pinagbalikwat gikan sa $1)",
+       "redirectpagesub": "Balikwaton an pahina",
+       "redirectto": "Balikwaton pasiring sa:",
        "lastmodifiedat": "Ining pahina huring pinagbago kan $1, mga alas $2.",
        "viewcount": "Ining pahina pinaglaog nin {{PLURAL:$1|sarong beses|nin $1 beses}}.",
        "protectedpage": "Protektadong pahina",
-       "jumpto": "Magluksó sa:",
-       "jumptonavigation": "nabigasyon",
+       "jumpto": "Maglukso sa:",
+       "jumptonavigation": "paglibotlibot",
        "jumptosearch": "hanapon",
        "view-pool-error": "Sori tabi, an mga server kargado sa oras na ini.\nGrabe kadakol an mga paragamit na pinagprubaran mahiling an pahinang ini.\nMakihalat tabi nin kadikit na panahon bago ka magprubara na makapaglaog sa pahinang ini.\n\n$1",
        "generic-pool-error": "Sori tabi, an mga serbidor grabe kakargado sa oras na ini. Kadakulon na gayo an mga paragamit na minaprubar na hilngon ining kaggikanan. Tabi pakihalat kadikit bago ka magprubar otro na makapaglaog sa kaggikanang ini.",
        "pool-queuefull": "An grupong panproseso panoon",
        "pool-errorunknown": "Bakong bistadong sala",
        "aboutsite": "Dapít sa {{SITENAME}}",
-       "aboutpage": "Project:Mapanonongód",
+       "aboutpage": "Project:Mapanonongod",
        "copyright": "An kalamnan manunumpungan sa laog kan $1 o baya notado na ining laen.",
        "copyrightpage": "{{ns:project}}:Mga Katanosang pansurat",
        "currentevents": "Sa ngunyan na mga pangyayari",
        "newmessageslinkplural": "{{PLURAL:$1|sarong baguhong mensahe|999=baguhong mga mensahe}}",
        "newmessagesdifflinkplural": "kahurihan na {{PLURAL:$1|kaliwatan|999=mga kaliwatan}}",
        "youhavenewmessagesmulti": "Igwa ka nin mga bàgong mensahe sa $1",
-       "editsection": "liwatón",
-       "editold": "Liwatón",
-       "viewsourceold": "hilingón an ginikánan",
-       "editlink": "liwatón",
-       "viewsourcelink": "tanawon an ginikanan",
-       "editsectionhint": "Liwatón an seksyon: $1",
-       "toc": "Mga laóg",
-       "showtoc": "ipahilíng",
-       "hidetoc": "tagóon",
-       "collapsible-collapse": "Pinahalipot",
-       "collapsible-expand": "Pinahalawig",
-       "thisisdeleted": "Hilingón o isulít an $1?",
-       "viewdeleted": "Hilingón an $1?",
+       "editsection": "liwaton",
+       "editold": "liwaton",
+       "viewsourceold": "hilingon an ginikanan",
+       "editlink": "liwaton",
+       "viewsourcelink": "tànawon an ginikanan",
+       "editsectionhint": "Liwaton an seksyon: $1",
+       "toc": "Mga laog",
+       "showtoc": "ipahiling",
+       "hidetoc": "tagoon",
+       "collapsible-collapse": "Pahalipoton",
+       "collapsible-expand": "Pahiwason",
+       "confirmable-yes": "Iyo",
+       "confirmable-no": "Dae",
+       "thisisdeleted": "Hilingon o isulit an $1?",
+       "viewdeleted": "Hilingon an $1?",
        "restorelink": "{{PLURAL:$1|sarong pinagpurang pagliwat|$1 na pinagpurang mga pagliwat}}",
        "feedlinks": "Hungit:",
        "feed-invalid": "Imbalidong tipo nin hungit sa subkripsyon.",
-       "feed-unavailable": "Mayò an mga sindikasyon na hungit",
+       "feed-unavailable": "Mga sindikasyong hungit dae magagamit",
        "site-rss-feed": "$1 Hungit nin RSS",
        "site-atom-feed": "$1 Hungit Atomo",
        "page-rss-feed": "\"$1\" Hungit na RSS",
        "nosuchspecialpage": "Mayong siring na espesyal na páhina",
        "nospecialpagetext": "<strong>Dai pwede an pahinang espesyal na pinilî mo.</strong>\n\nPwede mong mahiling an lista nin mga marhay na pahina sa [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Salâ",
-       "databaseerror": "Salâ sa base nin datos",
+       "databaseerror": "Kasalaan sa datos-sarayan",
        "databaseerror-text": "Sarong hapot sa datos-sarayan na kasalaan an nangyari.\nIni puwedeng minapasabot nin sarong kudol sa panuklob.",
        "databaseerror-textcl": "Sarong hapot sa datos-sarayan na kasalaan an nangyari.",
        "databaseerror-query": "Hapot: $1",
        "directorycreateerror": "Dai nagibo an direktorya na \"$1\".",
        "filenotfound": "Dai nahanap an file na \"$1\".",
        "unexpected": "Dai pighuhunà na balór: \"$1\"=\"$2\".",
-       "formerror": "Salâ: dai pwedeng isumitir an porma",
-       "badarticleerror": "Dai pwedeng gibohon ini sa ining páhina.",
+       "formerror": "Salâ: Dae maisusumiter an porma.",
+       "badarticleerror": "Ining aksyon dae magigibo sa pahinang ini.",
        "cannotdelete": "An pahina o an sagunson (file) na \"$1\" dae tabi napupura.\nIni puwede nang napura kan iba.",
        "cannotdelete-title": "Dae mapura an pahina na \"$1\"",
        "delete-hook-aborted": "An pagpura pinundo kan pangawit.\nIni dae nagtao nin kapaliwanagan.",
        "badtitletext": "An pinaghagad na titulo kan pahina imbalido, daeng laog, o sarong salaon na sinugpunan na titulo kan inter-lengguwahe o inter-wiki.\nIni gayod may laog nin o dakol na mga karakter na dae pinaggagamit sa mga titulo.",
        "perfcached": "An minasunod na datos pinagtago asin bakong gayo napapanahon. An maximum na {{PLURAL:$1|sarong resulta na|$1 mga resulta na}} yaon sana sa pinagtago.",
        "perfcachedts": "An minasunod na datos pinagtago, asin huring pinagdagdagan kan $1. An maximum na {{PLURAL:$4|sarong result na |$4 mga resulta na }} yaon sana sa pinagtago.",
-       "querypage-no-updates": "Pigpopogol mùna an mga pagbabàgo sa pahinang ini. Dai mùna mababàgo an mga datos digdi.",
+       "querypage-no-updates": "Mga kasugponan para sa pahinang ini sa ngunyan pinagpupugulan. An datos na yaon digde dae sa presente maipagpresko.",
        "viewsource": "Hilingón an ginikanan",
        "viewsource-title": "Hilnga an piggikanan para sa $1",
        "actionthrottled": "An aksyon pinagpugulan",
        "actionthrottledtext": "Bilang sarong pangontra sa spam, ika limitadong sanang himoon ining aksyon sa kadakulon na beses sa halipot sanang panahon, asin ika nakasobra na sa limitasyong ini.\nPaki-otroha giraray sa nagkapirang minuto sana.",
        "protectedpagetext": "Ining pahina protektado tanganing malikayan an pagliliwat o ibang aksyon.",
-       "viewsourcetext": "Pwede mong hilingón asin arógon an ginikanan kan pahinang ini:",
+       "viewsourcetext": "Ika makakatanaw asin makakakopya sa ginikanan kaining pahina:",
        "viewyourtext": "Saimong mahihiling asin makokopya an gikanan kan '''saimong mga pinagriliwat''' sa pahinang ini:",
        "protectedinterface": "An pahinang ini nagtatao nin panlaog-olay para sa software, asin protektado tangaring malikayan an abuso.\nSa pagdagdag or pagliwat nin mga dakit-taramon para sa bilog na wiki, gamita tabi an [//translatewiki.net/translatewiki.net], an MediaWiki sa proyektong lokalisasyon.",
        "editinginterface": "'''Patanid:''' Ika nagliliwat kan pahina na ginagamit sa pagtao nin pantahaw-olay na teksto para sa software.\nAn mga pagbabago kaining pahina makaka-apekto sa hitsura kan pantahaw-olay nin paragamit para sa iba man na paragamit.\nPara sa mga pagdadakit-taramon, pakikonsidera man tabi an paggagamit kan [//translatewiki.net/wiki/Main_Page?setlang=en translatewiki.net], an MediaWiking lokalisasyon kan proyekto.",
-       "cascadeprotected": "Pinoprotehirán ining páhina sa mga paghirá, ta sarô ini sa mga minasunod na {{PLURAL:$1|páhina|mga páhina}} na pinoprotehiran kan opsyón na \"katarata\" na nakabuká:\n$2",
-       "namespaceprotected": "Mayô kang permisong maghirá kan mga páhina sa '''$1''' ngaran-espacio.",
+       "cascadeprotected": "Ining pahina pinagprotehiran gikan sa pagliliwat nin huli ta ini pinagbale sa minasunod na {{PLURAL:$1|pahina, na iyo ngani an|mga pahina, na iyo ngani an mga}} protektado kan pinagbukasang opsyon na \"pasurunod-sunudan\":\n$2",
+       "namespaceprotected": "Ika mayong permiso sa pagliwat nin mga pahina sa <strong>$1</strong> na ngarang-espasyo.",
        "customcssprotected": "Ika mayong permiso sa pagliwat kaining pahinang CSS, nin huli ta ini naglalaman kan personal na panuytoy (settings) kan ibang paragamit.",
        "customjsprotected": "Ika mayong permiso sa pagliwat kaining pahinang JavaScript, nin huli ta ini naglalaman kan personal na panuytoy (settings) kan ibang paragamit.",
        "mycustomcssprotected": "Ika mayo nin permiso sa pagliwat kaining CSS na pahina.",
        "mycustomjsprotected": "Ika mayo nin permiso sa pagliwat kaining JavaScript na pahina.",
        "myprivateinfoprotected": "Ika daeng permiso na magliliwat kan pribado mong impormasyon.",
        "mypreferencesprotected": "Ika daeng permiso na magliliwat kan saimong mga kamuyahan.",
-       "ns-specialprotected": "An mga pahinang nasa {{ns:special}} na liang-liang dai pwedeng hirahón.",
+       "ns-specialprotected": "Mga espesyal na pahina dae makakapagliwat.",
        "titleprotected": "Ining titulo pinagprotektaran poon pagkamukna ni [[User:$1|$1]].\nAn rason na pinagtao iyo na \"''$2''\".",
        "filereadonlyerror": "Dae kinayang baguhon an sagunson (file) \"$1$ nin huli ta an repositoryo kan sagunson \"$2\" yaon sa kamugtakan na basahon sana.\n\nAn administrador na iyo an nagkandado kaini nagpahayag kaining kapaliwanagan: \"$3\".",
        "invalidtitle-knownnamespace": "Imbalidong titulo na igwang espasyadong ngaran na \"$2\" asin teksto na \"$3\"",
        "invalidtitle-unknownnamespace": "Imbalidong titulo na igwang nin bakong bistado na bilang kan espasyadong ngaran na $1 asin teksto na \"$2\"",
-       "exception-nologin": "Dae ka nakalaog",
-       "exception-nologin-text": "Tabi man [[Special:Userlogin|maglaog]]na tanganing makalangkay sa pahinang ini o aksyon.",
+       "exception-nologin": "Dai ka nakapaglaog",
+       "exception-nologin-text": "Pakipalaog tabi tanganing makalangkay sa pahinang ini o aksyon.",
        "exception-nologin-text-manual": "Tabi man $1 na tanganing makalangkay sa pahinang ini o aksyon.",
        "virus-badscanner": "Raot na kasalansanan: Bakong bistadong virus scanner: ''$1''",
        "virus-scanfailed": "An paghingipid (scan) nagpalya (Koda $1)",
        "userlogin-yourname-ph": "Ikaag an saimong paragamit-na-ngaran",
        "createacct-another-username-ph": "Ikaag an paragamit-na-ngaran",
        "yourpassword": "Pasa-taramon:",
-       "userlogin-yourpassword": "Sikretong panlaog",
+       "userlogin-yourpassword": "Pasa-taramon",
        "userlogin-yourpassword-ph": "Ikaag an saimong sekretong panlaog",
        "createacct-yourpassword-ph": "Ikaag an sekretong panlaog",
        "yourpasswordagain": "Pakilaog giraray kan sekretong panlaog:",
        "externaldberror": "Igwa gayod sala sa arinman kan patunay sa datos-sarayan o ika dae pinagtugutan na bâgohon an saimong panluwas na panindog.",
        "login": "Maglaog",
        "nav-login-createaccount": "Maglaog / magmukna nin panindog",
-       "loginprompt": "Ika kaipong paganahon an mga cookies tanganing makalaog sa {{SITENAME}}.",
        "userlogin": "Maglaog / magmukna nin panindog",
        "userloginnocreate": "Maglaog ka",
        "logout": "Magluwas",
-       "userlogout": "Magluwás",
+       "userlogout": "Magluwas",
        "notloggedin": "Dae ka nakalaog",
        "userlogin-noaccount": "Mayo ka nin panindog?",
        "userlogin-joinproject": "Mag-ayon{{SITENAME}}",
        "userlogin-resetlink": "Nakalingaw ka sa panlaog mong detalye?",
        "userlogin-resetpassword-link": "Nalingawan mo an saimong pasa-taramon?",
        "userlogin-helplink2": "Katabangan sa paglalaog",
-       "userlogin-loggedin": "Ika nakalaog na tabi bilang si {{GENDER:$1|$1}}.\nGamita an porma sa ibaba sa paglaog bilang ibang paragamit.",
-       "userlogin-createanother": "Magmukna nin ibang panindog",
        "createacct-emailrequired": "Estada kan e-surat",
        "createacct-emailoptional": "E-surat na estada (opsyonal)",
        "createacct-email-ph": "Pakikaag an saimong e-surat na estada",
        "php-mail-error-unknown": "Bakong bantog na kasalaan sa PHP mail() function.",
        "user-mail-no-addy": "Nagprubar na magpadara nin e-koreo na mayo nin e-koreong address.",
        "user-mail-no-body": "Nagprubar na magpadara nin e-surat na mayong laman o daeng kanultulan na halipot an hawak.",
-       "changepassword": "Ribayan an sekretong panlaog",
+       "changepassword": "Ribayan an pasa-taramon",
        "resetpass_announce": "Sa pagtapos kan paglalaog mo, ika kaipuhanan na magkaag nin sarong baguhong pasa-taramon.",
        "resetpass_text": "<!-- Magdagdag nin teksto digdi -->",
        "resetpass_header": "Ribayan an panindog na sekretong panlaog",
        "resetpass-no-info": "Ika dapat nakalaog na tanganing direktang makagamit kaining pahina.",
        "resetpass-submit-loggedin": "Ribayan an sekretong panlaog",
        "resetpass-submit-cancel": "I-kansela",
-       "resetpass-wrong-oldpass": "Saláng temporaryo o presenteng sekretong panlaog.\nMatriumpo mo nang nailaog an sekretong panlaog o nakua an bàgong temporaryong sekretong panlaog.",
+       "resetpass-wrong-oldpass": "Imbalidong temporaryo o sa ngunyan na pasa-taramon.\nIka matrayumpong nakapagbago na kan saimong pasa-taramon o naghagad nin sarong baguhon na temporaryong pasa-taramon.",
        "resetpass-recycled": "Tabi man pakibaguha an saimong pasa-taramon na magin sarong bagay na ibahon kesa sa ngunyan mong pasa-taramon.",
        "resetpass-temp-emailed": "Ika nakapaglaog na igwa nin sarong temporaryong koda na pinag-esurat saimo. Sa pagtapos kan paglalaog mo, ika kaipuhan na magkaag nin sarong baguhong pasa-taramon digde:",
        "resetpass-temp-password": "Temporaryong sekretong panlaog:",
        "resettokens-resetbutton": "Pakibaguha an pinagpiling mga paduos",
        "bold_sample": "Mahìbog na teksto",
        "bold_tip": "Mahìbog na teksto",
-       "italic_sample": "Itálikong teksto",
-       "italic_tip": "Tekstong Itáliko",
+       "italic_sample": "Italikong teksto",
+       "italic_tip": "Italikong teksto",
        "link_sample": "Titulo nin sugpon",
        "link_tip": "Panlaog na sugpon",
        "extlink_sample": "http://www.example.com títulong sugpon",
        "sig_tip": "An saimong pirma na igwang tatak-oras",
        "hr_tip": "Pabalagbag na linya (gamiton paminsan-minsan)",
        "summary": "Sumaryo:",
-       "subject": "Tema/pamayohan:",
+       "subject": "Subheto/kapamayuhan:",
        "minoredit": "Ini sarong dikiton na pagliwat",
        "watchthis": "Bantayan ining pahina",
        "savearticle": "Itagáma an pahina",
        "showdiff": "Ipahiling an mga kaliwatan",
        "anoneditwarning": "'''Patanid:''' Ika dae nakapaglaog. An saimong estada kan IP maisusurat sa laog kan historiya nin pagliliwat sa pahinang ini.",
        "anonpreviewwarning": "Dae ka tabi nakalaog. An pagtatagama matala kan saimong IP address sa historya nin pagliwat sa pahinang ini.",
-       "missingsummary": "'''Paisi:''' Dai ka nagkaag nin sumád kan paghirâ. Kun pindotón mo giraray an Itagama, maitatagama an hirá mo na mayô kaini.",
-       "missingcommenttext": "Paki lâgan nin komento sa ibabâ.",
+       "missingsummary": "<strong>Pagiromdom:</strong>Ika dae pa nakapagtao nin sumaryo sa pagliwat. Kun i-klik mo an \"{{int:savearticle}}\" giraray, an saimong pagliwat ipagtatagama na mayo kaiyan.",
+       "missingcommenttext": "Pakikaag nin sarong komento sa ibaba.",
        "missingcommentheader": "'''Pagiromdom:''' Ika dae tabi nagtao nin sarong panultol (subject)/Pamayong linya (headline) para kaining sinambit mo.\nKun saimong pinduton an \"{{int:savearticle}}\" giraray, an saimong pigliwat matatagama na mayo kaiyan.",
-       "summary-preview": "Patànaw nin sumada:",
-       "subject-preview": "Patânaw nin tema/pamayohan:",
-       "blockedtitle": "Pigbágat an parágamit",
+       "summary-preview": "Paenot na patanaw nin sumaryo:",
+       "subject-preview": "Paenot na patanaw sa Subheto/kapamayuhan:",
+       "blockedtitle": "An paragamit pinagbagat",
        "blockedtext": "'''An saimong paragamit na ngaran o IP address pinagkubkob.'''\n\nAn pagkubkob hinimo ni $1.\nAn rason na ipinagtao iyo na ''$2''.\n\n* Pagpoon kan pagkubkob: $8\n* Pagpasó kan pagkubkob: $6\n* Katuyuhan kan parakubkob: $7\n\nIka puwedeng magkontak sa $1 or ibang [[{{MediaWiki:Grouppage-sysop}}|administrador]] tanganing pag-orolayan an pagkubkob.\nIka dae makakagamit kan 'e-koreo kaining paragamit' na panuytuyan laen lang na may sarong balidong e-koreo address na ipinahayag sa saimong [[Special:Preferences|panindog na mga kabotan]] asin ika dae pinagkubkob para sa paggamit kaini.\nAn saimong presenteng IP address iyo $3, asin an kubkob ID iyo #$5.\nPakibale na lang tabi an gabos na mga detalye sa itaas sa anuman na mga kahaputan na saimong himoon.",
        "autoblockedtext": "An saimong IP address awtomatikong pinagkubkob nin huli ta ini pinaggamit kan ibang paragamit, na pinagkubkob ni $1.\nAn rason na ipinagtao iyo na:\n\n:''$2''\n\n* Pagpoon kan pagkubkob: $8\n* Pagpasó kan pagkubkob: $6\n* Katuyuhan kan parakubkob: $7\n\nPuwede mong kontakon si $1 o saro sa [[{{MediaWiki:Grouppage-sysop}}|mga administrador]] tanganing pag-orolayan an kubkob.\n\nPatanid tabi dae mo puwedeng gamiton an \"e-koreo kaining paragamit\" estima laen lang kun ika igwa nin sarong balidong e-koreo address na rehistrado sa saimong [[Special:Preferences|paragamit na mga kabotan]] asin ika dae pinagkubkob para sa paggamit kaini.\n\nAn saimong presenteng IP address iyo an $3, asin and Kubkob ID iyo an #$5.\nPakibale tabi an gabos na mga detalye sa itaas sa arinman na mga kahaputan na saimong himoon.",
-       "blockednoreason": "mayong itinaong rason",
-       "whitelistedittext": "Kaipuhan mong $1 tangarig makahirá nin mga páhina.",
-       "confirmedittext": "Kaipuhan mong kompirmaron an saimong ''e''-surat. Ipwesto tabî asin patunayan an saimong ''e''-surat sa [[Special:Preferences|mga kabôtan kan parágamit]].",
+       "blockednoreason": "mayong rason na ipinagtao",
+       "whitelistedittext": "Tabi man $1 tanganing makapagliwat nin mga pahina.",
+       "confirmedittext": "Ika kaipuhan na magkumpirma kan saimong estada sa e-surat bago makapagliwat nin mga pahina. Tabi man pakikaag asin balidaron an saimong estada sa e-surat sa paagi kan saimong [[Special:Mga Kamuyahan|paragamit na mga kamuyahan]].",
        "nosuchsectiontitle": "Dae managboan an seksyon",
        "nosuchsectiontext": "Ika nagprubar na liwaton an sarong seksyon na bakong eksistido.\nIni puwedeng pinagbalyo o pinagpara na habang saimong pinaghihiling an pahina.",
-       "loginreqtitle": "Kaipuhan Maglaog",
+       "loginreqtitle": "An paglaog pinaghahagad",
        "loginreqlink": "maglaog",
-       "loginreqpagetext": "Kaipuhan kang $1 tangarig makahilíng nin ibang pahina.",
-       "accmailtitle": "Napadará na an sekretong panlaog.",
+       "loginreqpagetext": "Tabi man $1 tanganing makapagtanaw kan ibang mga pahina.",
+       "accmailtitle": "Pasa-taramon naipadara na",
        "accmailtext": "An purak na pinagpuyos na pasa-taramon para ki [[User talk:$1|$1]] ipinagpadara na sa $2. Ini mapupuwedeng pagribayan sa ''[[Special:ChangePassword|change password]]'' na pahina matapos na ika nakalaog na.",
        "newarticle": "(Bàgo)",
-       "newarticletext": "Ika nakapagsunod sa sarong sugpon pasiring sa sarong pahina na bako pang eksistido. Tanganing makapagmukna nin pahina, magpoon sa pagpindot sa laog nin kahon sa ibaba (hilngon an [$1 pahina nin katabangan] para sa kadugangan na impormasyon).\nKun ika napasalang nakadigde, i-klik an  '''ibalik''' na pindutan kan saimong kilyaw.",
+       "newarticletext": "Ika nakapagsunod sa sarong sugpon pasiring sa sarong pahina na bako pang eksistido. Tanganing makapagmukna nin pahina, magpoon sa pagpindot sa laog nin kahon sa ibaba (hilngon an [$1 pahina nin katabangan] para sa kadugangan na impormasyon).\nKun ika napasalang nakadigde, i-klik an  '''ibalik''' na pindutan kan saimong kilyawan.",
        "anontalkpagetext": "----''Ini iyo an pahina kan orolayan para an sarong dae bistadong paragamit na dae pa nakapagmukna nin panindog, o dae pa nakapaggamit kaini.\nKaya kami kaipong gumamit nin numerikal na IP address sa pagbisto saiya.\nAn arog kaining IP address puwedeng maikapagheras sa nagkapirang mga paragamit.\nKun ika sarong dae pa bistadong paragamit asin mati mo na igwang irelebanteng sambit na pinanungod saimo, tabi paki [[Special:UserLogin/signup|mukna nin panindog]] or [[Special:UserLogin|maglaog ka]] tanganing malikayan an pagkaribong sa pag-iriba kan iba pang mga paragamit.''",
        "noarticletext": "Mayo tabi sa presente nin teksto sa pahinang ini.\nIka mapuwedeng [[Special:Search/{{PAGENAME}}|maghanap para sa titulo kan pahinang ini]] sa iba pang mga pahina,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} maghanap sa magkasurundong mga talaan],\no [{{fullurl:{{FULLPAGENAME}}|action=edit}} liwaton ining pahina]</span>.",
        "noarticletext-nopermission": "Mayong sa presente nin teksto an pahinang ini.\nIka mapuwedeng [[Special:Search/{{PAGENAME}}|hanapa para kaining titulo kan pahina]] sa iba pang mga pahina,\no <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} maghanap sa magkasurundong mga talaan]</span>.",
        "sitecsspreview": "'''Giromdoma baya na ika nagtatanaw pa sana kaining CSS.'''\n'''Ini dae pa tabi naitatagama!'''",
        "sitejspreview": "'''Giromdoma baya na ika nagtatatanaw pa sana kaining koda sa JavaScript.'''\n'''Ini dae pa tabi naitatagama!'''",
        "userinvalidcssjstitle": "'''Patanid:''' Mayong ''skin'' na \"$1\". Giromdomon tabî na an .css asin .js na mga páhina naggagamit nin titulong nakasurat sa sadit na letras, halimbawa {{ns:user}}:Foo/vector.css bakong {{ns:user}}:Foo/Vector.css.",
-       "updated": "(Binàgo)",
+       "updated": "(Pinagsugpunan na)",
        "note": "'''Paisi:'''",
        "previewnote": "'''Giromdoma na ini sarong patanaw pa sana.'''\nAn saimong mga pinagriliwat dae pa tabi naitatagama!",
        "continue-editing": "Magduman sa lugar nin pagliliwat",
        "editpage-notsupportedcontentformat-text": "An pormat nin kalamnan na $1 bakong suportado kan modelong kalamnan na $2.",
        "content-model-wikitext": "wiki-teksto",
        "content-model-text": "yanong-teksto",
-       "content-model-javascript": "Java-Kurit",
+       "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
        "expensive-parserfunction-warning": "'''Patanid tabi:''' Ining pahina naglalaman nin grabe kadakulon na ekspensibong programang pambaranga sa punksyon nin mga pag-aapod.\n\nIni dapat magkaigwa nin menos sanang $2 {{PLURAL:$2|apod|mga apod}}, igwa na {{PLURAL:$1|ngunyan nin $1 apod|ngunyan nin $1 mga apod}}.",
        "expensive-parserfunction-category": "Mga pahina na igwa nin grabe kadakulon na mga ekspensibong programang pambaranga sa punksyon nin mga pag-aapod",
        "cantcreateaccount-text": "An pagbukas nin account halì sa IP na ('''$1''') binágat ni [[User:$3|$3]].\n\n''$2'' an rason na pigtao ni $3",
        "viewpagelogs": "\nHilingon an mga katalaanan para sa pahinang ini",
        "nohistory": "Mayong paghirá nin uusipón sa pahinang ini.",
-       "currentrev": "Sa ngonyan na pagpakarháy",
-       "currentrev-asof": "Pinakahuring pagbabago kan $1",
-       "revisionasof": "Rebisyon poon kan $1",
+       "currentrev": "Ppagpakarhay sa ngunyan",
+       "currentrev-asof": "Pinakahuring pagpakarhay kan $1",
+       "revisionasof": "Pagpakarhay poon kan $1",
        "revision-info": "Rebisyon poon kan $1 ni $2",
-       "previousrevision": "←Lumàon na rebisyon",
-       "nextrevision": "Mas bàguhon na rebisyon→",
+       "previousrevision": "← Dating pagpakarhay",
+       "nextrevision": "Bagong pagpakarhay →",
        "currentrevisionlink": "Sa ngunyan na rebisyon",
-       "cur": "sa ngunyán",
+       "cur": "sa ngunyan",
        "next": "sunod",
-       "last": "sa nakaagi",
-       "page_first": "enot",
+       "last": "dati",
+       "page_first": "inot",
        "page_last": "huri",
-       "histlegend": "Kalaenan sa pilian: Markahan an mga kahon nin radyo kan mga rebisyon tanganing komapararon asin pinduta an \"enter\" o an pindutan na yaon sa irarom.<br />\nKabalaynan: '''({{int:cur}})''' = kalaenan sa pinakahuring rebisyon, '''({{int:last}})''' = kalaenan sa sinundan na rebisyon, '''{{int:minoreditletter}}''' = dikiton na pagliwat.",
-       "history-fieldset-title": "Historiya nin kinilyawan",
+       "histlegend": "Lain sa pilian: Markahan an mga kahon nin radyo kan mga pagpakarhay tanganing komapararon asin pinduta an \"enter\" o an pindutan na yaon sa irarom.<br />\nKabalaynan: '''({{int:cur}})''' = kalaenan sa pinakahuring rebisyon, '''({{int:last}})''' = kalaenan sa sinundan na rebisyon, '''{{int:minoreditletter}}''' = dikiton na pagliwat.",
+       "history-fieldset-title": "Uusipon nin paghalungkat",
        "history-show-deleted": "Pinagpura sana",
        "histfirst": "pinakalumaon",
        "histlast": "pinakabaguhon",
        "historysize": "({{PLURAL:$1|sarong byte|$1 mga bytes}})",
        "historyempty": "(mayong laog)",
-       "history-feed-title": "Uusipón kan pagpakaraháy",
-       "history-feed-description": "Uusipón kan pagpakaraháy para sa pahinang ini sa wiki",
+       "history-feed-title": "Uusipon kan pagpakarhay",
+       "history-feed-description": "Uusipon kan pagpakarahay para sa pahinang ini sa wiki",
        "history-feed-item-nocomment": "$1 sa $2",
-       "history-feed-empty": "Mayò man an hinágad na pahina.\nPwedeng pigparà na ini sa wiki, o tinàwan nin bàgong pangaran.\nProbaran tabì an [[Special:Search|pighahanap sa wiki]] para sa mga pahinang dapít.",
+       "history-feed-empty": "Mayò man an hinagad na pahina.\nPwedeng pigparà na ini sa wiki, o tinàwan nin bàgong pangaran.\nProbaran tabì an [[Special:Search|pighahanap sa wiki]] para sa mga pahinang dapít.",
        "rev-deleted-comment": "(pagliwat na sumaryo pinaghale)",
        "rev-deleted-user": "(hinalì an parágamit)",
        "rev-deleted-event": "(talaan kan aksyon pinaghale)",
        "searchprofile-advanced-tooltip": "Maghanap nin pankustombreng espasyong-ngaran",
        "search-result-size": "$1 ({{PLURAL:$2|1 tatarámon|$2 mga tatarámon}})",
        "search-result-category-size": "{{PLURAL:$1|1 miyembro|$1 mga miyembro}} ({{PLURAL:$2|1 subkategorya|$2 mga subkategorya}}, {{PLURAL:$3|1 sagunson|$3 mga sagunson}})",
-       "search-result-score": "Relebansiya: $1%",
        "search-redirect": "(Panukdong otro $1)",
        "search-section": "(Seksyon $1)",
        "search-suggest": "Boot mong ipakahulugan: $1",
        "searchrelated": "kauyon",
        "searchall": "gabós",
        "showingresults": "Pigpapahiling sa babâ sagkod sa {{PLURAL:$1|'''1''' resulta|'''$1''' mga resulta}} poon sa #'''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|Resulta '''$1''' kan '''$3'''|Mga Resulta '''$1 - $2''' kan '''$3'''}} para sa '''$4'''",
        "search-nonefound": "Mayo nin mga resulta na panampok sa kahaputan.",
        "powersearch-legend": "Adbansiyadong paghahanap",
        "powersearch-ns": "Maghanap sa mga espasyong-ngaran:",
        "uploadwarning": "Patanid sa pagkarga",
        "uploadwarning-text": "Pakibaguha tabi an deskripsyon kan sagunson sa ibaba asin paki-otroha giraray.",
        "savefile": "Itagama an ''file''",
-       "uploadedimage": "ipinagkarga na \"[[$1]]\"",
-       "overwroteimage": "kinarga an bagong bersión kan \"[[$1]]\"",
        "uploaddisabled": "Pigpopondó an mga pagkargá",
        "copyuploaddisabled": "An pagkarga sa paagi kan kilyawan pinagpondo.",
        "uploaddisabledtext": "An pagkarga kan mga sagunson pinagpondo tabi.",
        "randomincategory": "Purakan na pahina sa kategoriya",
        "randomincategory-invalidcategory": "\"$1\" bako sarong balidong pangaran nin kategoriya.",
        "randomincategory-nopages": "Mayo nin mga pahina sa [[:Category:$1]].",
-       "randomincategory-selectcategory": "Magkua nin purakan na pahina gikan sa kategoriya: $1 $2.",
-       "randomincategory-selectcategory-submit": "Magduman",
+       "randomincategory-legend": "Purakan na pahina sa kategoriya",
        "randomredirect": "Random na pagredirekta",
        "randomredirect-nopages": "Mayo nin panukdo-liwat sa espasyong-ngaran na \"$1\".",
        "statistics": "Mga Estadistiko",
        "mywatchlist": "Bantay-listahan",
        "watchlistfor2": "Para ki $1 $2",
        "nowatchlist": "Mayo ka man na mga bagay saimong lista nin pigbabantayan.",
-       "watchlistanontext": "Mag $1 tabi para mahiling o maghira nin mga bagay saimong lista nin mga pigbabantayan.",
+       "watchlistanontext": "Pakipalaog tabi tanganing makapaghiling o makapagliwat sa mga aytem na yaon sa saimong bantay-listahan.",
        "watchnologin": "Mayô sa laog",
        "addwatch": "Idagdag sa bantay-listahan",
        "addedwatchtext": "Ining pahina \"[[:$1]]\" dinadagdag sa saimong mga [[Special:Watchlist|Bantay-listahan]].\nAn maabot na mga pagbabâgo sa páhinang ini asin sa asosyadong páhina nin olay paglilistahon duman.",
        "watchlist-details": "{{PLURAL:$1|$1 pahina|$1 mga pahina}} sa saimong bantay-listahan, dae binibilang an mga pahina nin orolayan.",
        "wlheader-enotif": "E-surat na paisi pinagpaandar na.",
        "wlheader-showupdated": "Mga pahina na pinagriliwat poon kaidtong huri kang nagbisita sainda ipinapatanaw na '''mahîbog'''",
+       "wlnote": "Sa ibaba an {{PLURAL:$1|huring pagbabago|mga huring '''$1''' pagbabago}} sa nakaaging {{PLURAL:$2|oras|'''$2''' mga oras}}, magpoon pa kan $3, $4.",
        "wlshowlast": "Ipahilíng an nakaaging $1 na mga oras mga $2 na aldaw $3",
        "watchlist-options": "Bantay-listahan na mga pagpipilian",
        "watching": "Pigbabantayan...",
        "exbeforeblank": "Ini an dating laog bagô blinankohán: '$1'",
        "delete-confirm": "Puraon \"$1\"",
        "delete-legend": "Paraon",
-       "historywarning": "'''Patanid tabi:''' An pahina na saimong pagpupuraon may historiya na igwa nin haros $1 {{PLURAL:$1|rebisyon|mga rebisyon}}:",
+       "historywarning": "<strong>Patanid:</strong> An pahina na saimong pagpupuraon may historiya na igwa nin $1 {{PLURAL:$1|rebisyon|mga rebisyon}}:",
        "confirmdeletetext": "Paparaon mo sa base nin datos ining pahina kasabay an gabos na mga uusipón kaini.\nKonpirmaron tabì na talagang boot mong gibohon ini, nasasabotan mo an mga resulta, asin an piggigibo mo ini konporme sa\n[[{{MediaWiki:Policy-url}}]].",
        "actioncomplete": "An aksyon nakumpleto na",
        "actionfailed": "An aksyon nagpalya",
        "autoblockid": "Awtomatikong-kabarahan #$1",
        "block": "Barahon an paragamit",
        "unblock": "Haleon an bara kan paragamit",
-       "blockip": "Bagáton an paragamit",
+       "blockip": "Bagáton {{KASARIAN:$1|paragamit}}",
        "blockip-legend": "Kubkuba an paragamit",
        "blockiptext": "Gamiton an pormularyo sa babâ para bagaton an pagsurat kan sarong espesipikong IP o ngaran nin parágamit.\nDapat gibohon sana ini para maibitaran vandalismo, asin kompirmi sa [[{{MediaWiki:Policy-url}}|palakaw]].\nMagkaag nin espisipikong rason (halimbawa, magtao nin ehemplo kan mga páhinang rinaot).",
        "ipaddressorusername": "direksyon nin IP o gahâ:",
        "ipb-unblock-addr": "Paagihon $1",
        "ipb-unblock": "Bawion an pagbagat nin ngaran nin paragamit o direccion nin IP",
        "ipb-blocklist": "Hilingon an mga presenteng binagat",
-       "ipb-blocklist-contribs": "Mga kontribusyon para sa $1",
+       "ipb-blocklist-contribs": "Mga kontribusyon para sa {{KASARIAN:$1|$1}}",
        "unblockip": "Paagihon an parâgamit",
        "unblockiptext": "Gamiton an pormulario sa baba para puede giraray suratan an dating binagat na direccion nin IP address o ngaran nin paragamit.",
        "ipusubmit": "Haleon ining bara",
        "import": "Ilaog an mga páhina",
        "importinterwiki": "Ipadara an Transwiki",
        "import-interwiki-text": "Pumili nin sarong wiki asin titulo kan pahina na importaron.\nMga petsa nin kaliwatan asin pangaran kan mga paraliwat pagpepreserbaron.\nGabos na aksyon nin importa sa transwiki nakatala sa [[Special:Log/import|talaan nin importa]].",
-       "import-interwiki-source": "Ginikanang wiki/pahina:",
+       "import-interwiki-sourcepage": "Gikanang pahina:",
        "import-interwiki-history": "Kopyahon an gabos na mga bersyón para sa páhinang ini",
        "import-interwiki-templates": "Ibali an gabos na mga panguyog",
        "import-interwiki-submit": "Ipalaog",
index f49c47e..667c5df 100644 (file)
@@ -31,6 +31,7 @@
        "tog-watchdefault": "Дадаваць у мой сьпіс назіраньня старонкі і файлы, якія я {{GENDER:|рэдагаваў|рэдагавала}}",
        "tog-watchmoves": "Дадаваць у мой сьпіс назіраньня перанесеныя мною старонкі і файлы",
        "tog-watchdeletion": "Дадаваць у мой сьпіс назіраньня старонкі і файлы, якія я выдаляю",
+       "tog-watchrollback": "Дадаваць у мой сьпіс назіраньня старонкі, дзе я {{GENDER:|зрабіў|зрабіла}} адкат",
        "tog-minordefault": "Па змоўчаньні пазначаць усе мае праўкі дробнымі",
        "tog-previewontop": "Паказваць папярэдні прагляд старонкі над полем рэдагаваньня",
        "tog-previewonfirst": "Папярэдні прагляд пры першым рэдагаваньні",
        "talkpagelinktext": "гутаркі",
        "specialpage": "Спэцыяльная старонка",
        "personaltools": "Асабістыя прылады",
-       "postcomment": "Новая сэкцыя",
        "articlepage": "Паказаць старонку зьместу",
        "talk": "Абмеркаваньне",
        "views": "Рэжымы",
        "otherlanguages": "На іншых мовах",
        "redirectedfrom": "(Перанакіравана з «$1»)",
        "redirectpagesub": "Старонка-перанакіраваньне",
+       "redirectto": "Перанакіраваньне на:",
        "lastmodifiedat": "Гэтая старонка апошні раз рэдагавалася $1 году ў $2.",
        "viewcount": "Гэтую старонку праглядалі $1 {{PLURAL:$1|раз|разы|разоў}}.",
        "protectedpage": "Абароненая старонка",
        "hidetoc": "схаваць",
        "collapsible-collapse": "Згарнуць",
        "collapsible-expand": "Разгарнуць",
+       "confirmable-confirm": "Вы ўпэўненыя?",
+       "confirmable-yes": "Так",
+       "confirmable-no": "Не",
        "thisisdeleted": "Праглядзець ці аднавіць $1?",
        "viewdeleted": "Паказаць $1?",
        "restorelink": "$1 {{PLURAL:$1|выдаленую зьмену|выдаленыя зьмены|выдаленых зьменаў}}",
        "invalidtitle-knownnamespace": "Няслушная назва ў прасторы «$2»: «$3»",
        "invalidtitle-unknownnamespace": "Няслушная назва ў невядомай прасторы $1: «$2»",
        "exception-nologin": "Вы не ўвайшлі ў сыстэму",
-       "exception-nologin-text": "Неабходна [[Special:Userlogin|ўвайсьці]], каб атрымаць доступ да гэтай старонкі або дзеяньня.",
+       "exception-nologin-text": "Неабходна ўвайсьці, каб атрымаць доступ да гэтай старонкі або дзеяньня.",
        "exception-nologin-text-manual": "Неабходна $1, каб мець доступ да гэтай старонкі або дзеяньня.",
        "virus-badscanner": "Няслушная канфігурацыя: невядомы антывірусны сканэр: ''$1''",
        "virus-scanfailed": "памылка сканаваньня (код $1)",
        "externaldberror": "Адбылася памылка аўтэнтыфікацыі з дапамогай вонкавай базы зьвестак, ці Вам не дазволена абнаўляць свой рахунак.",
        "login": "Увайсьці",
        "nav-login-createaccount": "Уваход / стварэньне рахунку",
-       "loginprompt": "Вы павінны дазволіць cookie для ўваходу ў {{GRAMMAR:вінавальны|{{SITENAME}}}}.",
        "userlogin": "Увайсьці ў сыстэму",
        "userloginnocreate": "Увайсьці",
        "logout": "Выйсьці",
        "userlogin-resetlink": "Забыліся на зьвесткі для ўваходу?",
        "userlogin-resetpassword-link": "Забылі пароль?",
        "userlogin-helplink2": "Дапамога з уваходам у сыстэму",
-       "userlogin-loggedin": "Вы ўжо ўвайшлі як {{GENDER:$1|$1}}.\nДля ўваходу пад іншым удзельнікам скарыстайцеся формай унізе.",
-       "userlogin-createanother": "Стварыць іншы рахунак",
        "createacct-emailrequired": "E-mail адрас",
        "createacct-emailoptional": "E-mail адрас (неабавязкова)",
        "createacct-email-ph": "Увядзіце ваш e-mail адрас",
        "createaccount-text": "Нехта стварыў рахунак «$2» у {{GRAMMAR:месны|{{SITENAME}}}} ($4) для Вашага адрасу электроннай пошты. Пароль для гэтага рахунку — «$3». Вам трэба ўвайсьці і зьмяніць Ваш пароль зараз.\n\nВы можаце праігнараваць гэты ліст, калі гэты рахунак быў створаны памылкова.",
        "login-throttled": "Вы зрабілі надта шмат спробаў уваходу ў сыстэму.\nКалі ласка, пачакайце $1 перад тым як паспрабаваць ізноў.",
        "login-abort-generic": "Не атрымалася ўвайсьці ў сыстэму, скасавана",
+       "login-migrated-generic": "Ваш рахунак быў перанесены і вашае імя ўдзельніка больш не існуе ў гэтай вікі.",
        "loginlanguagelabel": "Мова: $1",
        "suspicious-userlogout": "Ваш запыт на выхад з сыстэмы быў адхілены, таму што выглядае, што ён быў дасланы пашкоджаным браўзэрам альбо кэшаваным проксі-сэрвэрам.",
        "createacct-another-realname-tip": "Сапраўднае імя паведамляць неабавязкова.\nКалі Вы яго пазначыце, яно будзе выкарыстоўвацца для пазначэньня Вашай працы.",
        "preview": "Папярэдні прагляд",
        "showpreview": "Праглядзець",
        "showdiff": "Паказаць зьмены",
-       "anoneditwarning": "'''Папярэджаньне:''' Вы не ўвайшлі ў сыстэму. Ваш IP-адрас будзе запісаны ў гісторыі гэтай старонкі.",
+       "blankarticle": "<strong>Папярэджаньне:</strong> вы ствараеце пустую старонку.\nКалі вы націсьніце «{{int:savearticle}}» яшчэ раз, старонка будзе створаная без аніякага зьместу.",
+       "anoneditwarning": "<strong>Папярэджаньне</strong>: вы не ўвайшлі ў сыстэму. Ваш IP-адрас будзе бачны ўсім, калі вы адрэдагуеце старонку. Калі вы <strong>[$1 ўвойдзеце]</strong> або <strong>[$2 створыце рахунак]</strong>, вашыя рэдагаваньні будуць зьвязаныя з вашым імем карыстальніка, а таксама вам будуць даступныя дадатковыя перавагі.",
        "anonpreviewwarning": "''Вы не ўвайшлі ў сыстэму. Падчас захаваньня Ваш IP-адрас будзе дададзены ў гісторыю рэдагаваньняў старонкі.''",
        "missingsummary": "'''Напамін:''' Вы не пазначылі кароткае апісаньне зьменаў.\nКалі Вы націсьніце кнопку «Запісаць» яшчэ раз, Вашае рэдагаваньне будзе запісанае без апісаньня.",
        "missingcommenttext": "Калі ласка, увядзіце камэнтар ніжэй.",
        "parser-template-recursion-depth-warning": "Перавышана мяжа глыбіні рэкурсіі шаблёнаў ($1)",
        "language-converter-depth-warning": "Перавышанае абмежаваньне глыбіні канвэртару варыянтаў мовы ($1)",
        "node-count-exceeded-category": "Старонкі зь перавышанай колькасьцю вузлоў",
-       "node-count-exceeded-category-desc": "Ð\9aаÑ\82Ñ\8dгоÑ\80Ñ\8bÑ\8f Ð´Ð»Ñ\8f Ñ\81Ñ\82аÑ\80онак, Ð½Ð° Ñ\8fкÑ\96Ñ\85 Ð¿ÐµÑ\80авÑ\8bÑ\88аная колькасьць вузлоў.",
+       "node-count-exceeded-category-desc": "Ð\9dа Ñ\81Ñ\82аÑ\80онÑ\86Ñ\8b Ð¿ÐµÑ\80авÑ\8bÑ\88анаÑ\8f Ð¼Ð°ÐºÑ\81Ñ\8bмалÑ\8cная колькасьць вузлоў.",
        "node-count-exceeded-warning": "Старонка перавысіла дазволеную колькасьць вузлоў",
        "expansion-depth-exceeded-category": "Старонкі зь перавышанай глыбінёй уключэньня",
-       "expansion-depth-exceeded-category-desc": "Ð\93Ñ\8dÑ\82а ÐºÐ°Ñ\82Ñ\8dгоÑ\80Ñ\8bÑ\8f Ð´Ð»Ñ\8f Ñ\81Ñ\82аÑ\80онак, Ð´Ð·Ðµ Ð¿ÐµÑ\80авÑ\8bÑ\88анаÑ\8f Ð³Ð»Ñ\8bбÑ\96нÑ\8f раскрыцьця.",
+       "expansion-depth-exceeded-category-desc": "СÑ\82аÑ\80онка Ð¿ÐµÑ\80авÑ\8bÑ\88ае Ð¼Ð°ÐºÑ\81Ñ\8bмалÑ\8cнÑ\83Ñ\8e Ð³Ð»Ñ\8bбÑ\96нÑ\8e раскрыцьця.",
        "expansion-depth-exceeded-warning": "Старонка перавысіла дазволеную глыбіню ўключэньняў",
        "parser-unstrip-loop-warning": "Вызначаная незачыненая пятля",
        "parser-unstrip-recursion-limit": "Перавышанае абмежаваньне глыбіні рэкурсіі ($1)",
        "rev-deleted-event": "(запіс з журнала падзеяў выдалены)",
        "rev-deleted-user-contribs": "[імя ўдзельніка альбо IP-адрас выдалены — рэдагаваньне схаванае з унёску]",
        "rev-deleted-text-permission": "Гэтая вэрсія старонкі была '''выдаленая'''.\nМагчыма, падрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].",
+       "rev-suppressed-text-permission": "Гэтая вэрсія старонкі была <strong>схаваная</strong>.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале хаваньняў].",
        "rev-deleted-text-unhide": "Гэтая вэрсія старонкі была '''выдаленая'''.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].\nВы можаце [$1 праглядзець гэтую вэрсію], калі жадаеце.",
        "rev-suppressed-text-unhide": "Гэтая вэрсія старонкі была '''схаваная'''.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале хаваньняў].\nВы можаце [$1 праглядзець гэтую вэрсію], калі жадаеце.",
        "rev-deleted-text-view": "Гэтая вэрсія старонкі была '''выдаленая'''.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].",
        "revdelete-text-text": "Выдаленыя вэрсіі будуць па-ранейшаму бачныя ў гісторыі старонкі, але некаторыя часткі іх зьместу будуць недаступныя для ўдзельнікаў.",
        "revdelete-text-file": "Выдаленыя вэрсіі файла будуць па-ранейшаму бачныя ў гісторыі старонкі, але часткі іх зьместу будуць недаступныя для ўдзельнікаў.",
        "logdelete-text": "Выдаленыя падзеі ў журнале будуць па-ранейшаму даступныя ў журналах, але часткі іх зьместу будуць недаступныя ўдзельнікам.",
-       "revdelete-text-others": "Іншыя адмністратары {{GRAMMAR:родны|{{SITENAME}}}} па-ранейшаму будуць мець магчымасьць пабачыць і аднавіць схаваны зьмест праз гэты ж інтэрфэйс, калі ня будуць усталяваныя дадатковыя абмежаваньні.",
+       "revdelete-text-others": "Іншыя адмністратары па-ранейшаму будуць мець магчымасьць пабачыць і аднавіць схаваны зьмест, калі ня будуць усталяваныя дадатковыя абмежаваньні.",
        "revdelete-confirm": "Калі ласка, пацьвердзіце, што Вы сапраўды жадаеце зрабіць гэта, разумееце наступствы і робіце гэта ў адпаведнасьці з [[{{MediaWiki:Policy-url}}|правіламі]].",
        "revdelete-suppress-text": "Скрываньне можа выкарыстоўвацца '''толькі''' ў наступных выпадках:\n* патэнцыйна паклёпніцкая інфармацыя\n* раскрыцьцё асабістых зьвестак\n*: ''хатнія адрасы, тэлефонныя нумары, нумары пашпартоў і г. д.''",
        "revdelete-legend": "Усталяваць абмежаваньні бачнасьці",
        "searchprofile-advanced-tooltip": "Шукаць у дадатковых прасторах назваў",
        "search-result-size": "$1 ($2 {{PLURAL:$2|слова|словы|словаў}})",
        "search-result-category-size": "$1 {{PLURAL:$1|элемэнт|элемэнты|элемэнтаў}} ($2 {{PLURAL:$2|падкатэгорыя|падкатэгорыі|падкатэгорыяў}}, $3 {{PLURAL:|файл|файлы|файлаў}})",
-       "search-result-score": "Адпаведнасьць: $1%",
        "search-redirect": "(перанакіраваньне $1)",
        "search-section": "(сэкцыя $1)",
        "search-file-match": "(супадае зь зьмесьцівам файла)",
        "searchall": "усе",
        "showingresults": "Ніжэй {{PLURAL:$1|паданы|паданыя|паданыя}} да '''$1''' {{PLURAL:$1|выніку|вынікаў|вынікаў}}, пачынаючы з #<b>$2</b>.",
        "showingresultsinrange": "Ніжэй паказаныя да {{PLURAL:$1|<strong>$1</strong> выніку ў|<strong>$1</strong> вынікаў у}} дыяпазоне ад <strong>$2</strong> да <strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|1=Вынік '''$1''' з '''$3'''|Вынікі '''$1—$2''' з '''$3'''}} для '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|1=Вынік <strong>$1</strong> з <strong>$3</strong>|Вынікі <strong>$1—$2</strong> з <strong>$3</strong>}}",
        "search-nonefound": "Супадзеньняў па запыце ня знойдзена.",
        "powersearch-legend": "Удасканалены пошук",
        "powersearch-ns": "Шукаць у прасторах назваў:",
        "preferences": "Налады",
        "mypreferences": "Налады",
        "prefs-edits": "Колькасьць рэдагаваньняў:",
-       "prefsnologintext2": "Ð\9dеабÑ\85одна $1, каб зьмяніць вашыя налады.",
+       "prefsnologintext2": "Ð\9aалÑ\96 Ð»Ð°Ñ\81ка, Ñ\83вайдзÑ\96Ñ\86е Ñ\9e Ñ\81Ñ\8bÑ\81Ñ\82Ñ\8dмÑ\83, каб зьмяніць вашыя налады.",
        "prefs-skin": "Афармленьне",
        "skin-preview": "Папярэдні прагляд",
        "datedefault": "Па змоўчаньні",
        "right-deletedtext": "прагляд выдаленага тэксту і зьменаў паміж выдаленымі вэрсіямі старонак",
        "right-browsearchive": "пошук выдаленых старонак",
        "right-undelete": "аднаўленьне старонак",
-       "right-suppressrevision": "прагляд і аднаўленьне вэрсіяў, схаваных ад адміністратараў",
+       "right-suppressrevision": "праглядаць, хаваць і аднаўляць пэўныя вэрсіі старонак, зробленыя любым удзельнікам",
+       "right-viewsuppressed": "праглядаць вэрсіі старонак, схаваныя ад усіх удзельнікаў",
        "right-suppressionlog": "прагляд прыватных журналаў",
        "right-block": "блякаваньне іншых удзельнікаў ад рэдагаваньняў",
        "right-blockemail": "блякаваньне іншых ўдзельнікаў ад дасылкі электроннай пошты",
        "recentchanges-label-plusminus": "Памер старонкі зьмяніўся на такую колькасьць байтаў",
        "recentchanges-legend-heading": "'''Легенда:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (глядзіце таксама [[Special:NewPages|сьпіс новых старонак]])",
-       "rcnotefrom": "Ніжэй знаходзяцца зьмены з <strong>$2</strong> (да <strong>$1</strong> на старонку).",
+       "rcnotefrom": "Ніжэй {{PLURAL:$5|знаходзіцца зьмена|знаходзяцца зьмены}} з <strong>$4 $3</strong> (да <strong>$1</strong> на старонку).",
        "rclistfrom": "Паказаць зьмены з $2 $3",
        "rcshowhideminor": "$1 дробныя праўкі",
        "rcshowhideminor-show": "Паказаць",
        "uploadwarning": "Папярэджаньне",
        "uploadwarning-text": "Калі ласка, зьмяніце апісаньне файла ніжэй і паспрабуйце ізноў.",
        "savefile": "Захаваць файл",
-       "uploadedimage": "загружаная «[[$1]]»",
-       "overwroteimage": "загружаная новая вэрсія «[[$1]]»",
        "uploaddisabled": "Загрузка файлаў забароненая",
        "copyuploaddisabled": "Загрузка праз URL-адрас адключаная.",
        "uploaddisabledtext": "Загрузка файлаў забароненая.",
        "license": "Ліцэнзія:",
        "license-header": "Ліцэнзія",
        "nolicense": "Ня выбраная",
+       "licenses-edit": "Рэдагаваць парамэтры ліцэнзіі",
        "license-nopreview": "(Прагляд недаступны)",
-       "upload_source_url": " (слушны, агульнадаступны URL-адрас)",
-       "upload_source_file": " (файл на Вашым кампутары)",
+       "upload_source_url": "(выбраны вамі файл з слушнага і агульнадаступнага URL-адрасу)",
+       "upload_source_file": "(выбраны файл на вашым кампутары)",
+       "listfiles-delete": "выдаліць",
        "listfiles-summary": "На гэтай спэцыяльнай старонцы паказаныя ўсе загружаныя файлы.",
        "listfiles_search_for": "Пошук па назьве файла:",
        "imgfile": "файл",
        "randomincategory": "Выпадковая старонка ў катэгорыі",
        "randomincategory-invalidcategory": "«$1» — ня слушная назва катэгорыі.",
        "randomincategory-nopages": "У катэгорыі «[[:Category:$1|$1]]» старонак няма.",
-       "randomincategory-selectcategory": "Узяць адвольную старонку з катэгорыі: $1 $2.",
-       "randomincategory-selectcategory-submit": "Паказаць",
+       "randomincategory-category": "Катэгорыя:",
+       "randomincategory-legend": "Выпадковая старонка ў катэгорыі",
        "randomredirect": "Выпадковае перанакіраваньне",
        "randomredirect-nopages": "У прасторы назваў «$1» няма перанакіраваньняў.",
        "statistics": "Статыстыка",
        "wantedpages-badtitle": "Няслушная назва сярод вынікаў: $1",
        "wantedfiles": "Запатрабаваныя файлы",
        "wantedfiletext-cat": "Наступныя файлы выкарыстоўваюцца, але іх няма. Файлы са зьнешніх сховішчаў могуць знаходзіцца ў сьпісе без уліку іх існаваньня. Любыя такія няслушныя ўваходжаньні будуць <del>выкрасьленыя</del>. Дадаткова, старонкі, якія ўбудоўваюць неіснуючыя файлы прыведзеныя на [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Наступныя файлы ўжваюцца, але не існуюць. Дадаткова, старонкі, у якія ўключаныя няісныя файлы, прыведзеныя ў [[:$1]].",
        "wantedfiletext-nocat": "Наступныя файлы выкарыстоўваюцца, але іх няма. Файлы са зьнешніх сховішчаў могуць знаходзіцца ў сьпісе без уліку іх існаваньня. Любыя такія няслушныя ўваходжаньні будуць <del>выкрасьленыя</del>.",
+       "wantedfiletext-nocat-noforeign": "Наступныя файлы выкарыстоўваюцца, але іх няма.",
        "wantedtemplates": "Запатрабаваныя шаблёны",
        "mostlinked": "Старонкі, на якія найчасьцей спасылаюцца",
        "mostlinkedcategories": "Катэгорыі з найбольшай колькасьцю старонак",
        "trackingcategories-desc": "Крытэр уключэньня ў катэгорыю",
        "noindex-category-desc": "Гэтая старонка не індэксуецца пошукавымі робатамі, таму што на ёй маецца магічнае слова <code><nowiki>__NOINDEX__</nowiki></code>, а старонка знаходзіцца ў прасторы назваў, дзе дазволны гэты сьцяг.",
        "index-category-desc": "На старонцы знаходзіцца магічнае слова <code><nowiki>__INDEX__</nowiki></code> (пры гэтым старонка знаходзіцца ў прасторы назваў, дзе дазволены гэты сьцяг), таму яна індэксуецца пошукавымі робатамі ў тых выпадках, калі звычайна гэтага не адбываецца.",
-       "post-expand-template-inclusion-category-desc": "Пасьля разгортваньня ўсіх шаблёнаў, памер старонкі перавысіў <code>$wgMaxArticleSize</code>, таму некаторыя шаблёны не былі паказаныя цалкам.",
-       "post-expand-template-argument-category-desc": "Ð\9fаÑ\81Ñ\8cлÑ\8f Ñ\80аÑ\81кÑ\80Ñ\8bÑ\86Ñ\8cÑ\86Ñ\8f Ð°Ñ\80гÑ\83мÑ\8dнÑ\82Ñ\83 Ñ\88аблÑ\91нÑ\83 (неÑ\88Ñ\82а Ñ\9e Ñ\82Ñ\80айнÑ\8bÑ\85 Ð´Ñ\83жкаÑ\85, Ð½Ð°Ð¿Ñ\80Ñ\8bклад, <code>{{{Foo}}}</code>), Ñ\81Ñ\82аÑ\80онка Ð¿ÐµÑ\80авÑ\8bÑ\88ае Ð¿Ð°Ð¼ÐµÑ\80 <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "На старонцы ўжываецца зашмат рэсурсаёмістых функцыяў парсэру (такіх, як <code>#ifexist</code>). Глядзіце [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Ð\9aаÑ\82Ñ\8dгоÑ\80Ñ\8bÑ\8f Ð´Ð°Ð´Ð°ÐµÑ\86Ñ\86а, ÐºÐ°Ð»Ñ\96 Ñ\81таронка ўтрымлівае няслушную спасылку на файл (спасылку на файл, які не існуе).",
-       "hidden-category-category-desc": "Ð\93Ñ\8dÑ\82а ÐºÐ°Ñ\82Ñ\8dгоÑ\80Ñ\8bÑ\8f Ð· Ð´Ð°Ð´Ð°Ð´Ð·ÐµÐ½Ð°Ð¹ Ð¼ÐµÑ\82кай <code><nowiki>__HIDDENCAT__</nowiki></code> Ñ\83 Ñ\91й, што па змоўчаньні не адлюстроўвае яе на старонках у сьпісе катэгорыяў.",
+       "post-expand-template-inclusion-category-desc": "Памер старонкі перавысіў <code>$wgMaxArticleSize</code> пасьля разгортваньня ўсіх шаблёнаў, таму некаторыя шаблёны не былі паказаныя цалкам.",
+       "post-expand-template-argument-category-desc": "СÑ\82аÑ\80онка Ð¿ÐµÑ\80авÑ\8bÑ\88ае Ð¿Ð°Ð¼ÐµÑ\80 <code>$wgMaxArticleSize</code> Ð¿Ð°Ñ\81Ñ\8cлÑ\8f Ñ\80аÑ\81кÑ\80Ñ\8bÑ\86Ñ\8cÑ\86Ñ\8f Ð°Ñ\80гÑ\83мÑ\8dнÑ\82Ñ\83 Ñ\88аблÑ\91нÑ\83 (неÑ\88Ñ\82а Ñ\9e Ñ\82Ñ\80айнÑ\8bÑ\85 Ð´Ñ\83жкаÑ\85, Ð½Ð°Ð¿Ñ\80Ñ\8bклад, <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "На старонцы ўжываецца зашмат рэсурсаёмістых функцыяў парсэру (такіх, як <code>#ifexist</code>). Глядзіце [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Інструкцыя:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "Старонка ўтрымлівае няслушную спасылку на файл (спасылку на файл, які не існуе).",
+       "hidden-category-category-desc": "Ð\9aаÑ\82Ñ\8dгоÑ\80Ñ\8bÑ\8f Ñ\9eÑ\82Ñ\80Ñ\8bмлÑ\96вае Ð¼ÐµÑ\82кÑ\83 <code><nowiki>__HIDDENCAT__</nowiki></code> Ñ\83 Ð·Ñ\8cмеÑ\81Ñ\8cÑ\86е Ñ\81Ñ\82аÑ\80онкÑ\96, што па змоўчаньні не адлюстроўвае яе на старонках у сьпісе катэгорыяў.",
        "trackingcategories-nodesc": "Апісаньне адсутнічае.",
        "trackingcategories-disabled": "Катэгорыя адключаная",
        "mailnologin": "Няма адрасу атрымальніка",
        "mywatchlist": "Сьпіс назіраньня",
        "watchlistfor2": "Для $1 $2",
        "nowatchlist": "Ваш сьпіс назіраньня пусты.",
-       "watchlistanontext": "Ð\92ам Ð¿Ð°Ñ\82Ñ\80Ñ\8dбна $1, каб праглядаць альбо рэдагаваць сьпіс назіраньня.",
+       "watchlistanontext": "Ð\9aалÑ\96 Ð»Ð°Ñ\81ка, Ñ\83вайдзÑ\96Ñ\86е Ñ\9e Ñ\81Ñ\8bÑ\81Ñ\82Ñ\8dмÑ\83, каб праглядаць альбо рэдагаваць сьпіс назіраньня.",
        "watchnologin": "Вы не ўвайшлі ў сыстэму",
        "addwatch": "Дадаць ў сьпіс назіраньня",
        "addedwatchtext": "Старонка «[[:$1]]» была дададзеная да Вашага [[Special:Watchlist|сьпісу назіраньня]].\nНаступныя зьмены ў гэтай старонцы і зьвязанай зь ёю старонцы абмеркаваньняў будуць бачныя там.",
        "watchlist-details": "У Вашым сьпісе назіраньня $1 {{PLURAL:$1|старонка|старонкі|старонак}} за выключэньнем старонак абмеркаваньня.",
        "wlheader-enotif": "Апавяшчэньне па e-mail уключанае.",
        "wlheader-showupdated": "Старонкі, зьмененыя з часу вашага апошняга візыту, вылучаныя '''тоўстым''' шрыфтам.",
-       "wlnote2": "Ніжэй паказаныя зьмены за {{PLURAL:$1|<strong>$1</strong> гадзіну|<strong>$1</strong> гадзіны|<strong>$1</strong> гадзінаў}} на $3 $2.",
+       "wlnote": "Ніжэй {{PLURAL:$1|паказаная <strong>$1</strong> апошняя зьмена|паказаныя <strong>$1</strong> апошнія зьмены|паказаныя <strong>$1</strong> апошніх зьменаў}} за <strong>$2</strong> {{PLURAL:$2|гадзіну|гадзіны|гадзінаў}}, па стане на $4 $3.",
        "wlshowlast": "Паказаць: за апошнія $1 гадзінаў, $2 дзён, $3",
        "watchlist-options": "Налады сьпісу назіраньня",
        "watching": "Дадаецца ў сьпіс назіраньня…",
        "exbeforeblank": "зьмест да ачысткі: «$1»",
        "delete-confirm": "Выдаліць «$1»",
        "delete-legend": "Выдаліць",
-       "historywarning": "'''Папярэджаньне''': старонка, якую Вы зьбіраецеся выдаліць, мае гісторыю з прыкладна $1 {{PLURAL:$1|вэрсіі|вэрсіяў|вэрсіяў}}:",
+       "historywarning": "<strong>Папярэджаньне</strong>: старонка, якую Вы зьбіраецеся выдаліць, мае гісторыю з $1 {{PLURAL:$1|вэрсіі|вэрсіяў|вэрсіяў}}:",
        "confirmdeletetext": "Зараз Вы выдаліце старонку разам з усёй гісторыяй зьменаў.\nКалі ласка, пацьвердзіце, што Вы зьбіраецеся гэта зрабіць і што Вы разумееце ўсе наступствы, а таксама робіце гэта ў адпаведнасьці з [[{{MediaWiki:Policy-url}}|правіламі]].",
        "actioncomplete": "Дзеяньне выкананае",
        "actionfailed": "Дзеяньне ня выкананае",
        "delete-edit-reasonlist": "Рэдагаваць прычыны выдаленьня",
        "delete-toobig": "Гэтая старонка мае доўгую гісторыю рэдагаваньняў, болей за $1 {{PLURAL:$1|вэрсію|вэрсіі|вэрсіяў}}.\nВыдаленьне такіх старонак было забароненае, каб пазьбегнуць праблемаў у працы {{GRAMMAR:родны|{{SITENAME}}}}.",
        "delete-warning-toobig": "Гэтая старонка мае доўгую гісторыю рэдагаваньняў, больш за $1 {{PLURAL:$1|вэрсію|вэрсіі|вэрсіяў}}.\nЯе выдаленьне можа выклікаць праблемы ў працы базы зьвестак {{GRAMMAR:родны|{{SITENAME}}}}; будзьце асьцярожны.",
+       "deleteprotected": "Вы ня можаце выдаліць гэтую старонку, таму што яна абароненая.",
        "deleting-backlinks-warning": "'''Увага:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|іншыя старонкі]] ўключаюць або спасылаюцца на старонку, якую вы зьбіраецеся выдаліць.",
        "rollback": "Адкаціць рэдагаваньні",
        "rollback_short": "Адкат",
        "autoblockid": "Аўтаматычнае блякаваньне №$1",
        "block": "Заблякаваць удзельніка",
        "unblock": "Разблякаваць удзельніка",
-       "blockip": "Заблякаваць",
+       "blockip": "Заблякаваць {{GENDER:$1|удзельніка|удзельніцу}}",
        "blockip-legend": "Заблякаваць удзельніка",
        "blockiptext": "Наступная форма дазваляе заблякаваць магчымасьць рэдагаваньня з пэўнага IP-адрасу альбо імя ўдзельніка. Гэта трэба рабіць толькі дзеля прадухіленьня вандалізму і згодна з [[{{MediaWiki:Policy-url}}|правіламі]]. Пазначце ніжэй дакладную прычыну (напрыклад, пералічыце асобныя старонкі, на якіх былі парушэньні).",
        "ipaddressorusername": "IP-адрас альбо імя ўдзельніка/ўдзельніцы:",
        "unblocked": "[[User:$1|$1]] быў разблякаваны.",
        "unblocked-range": "$1 быў разблякаваны",
        "unblocked-id": "Блякаваньне $1 зьнятае",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] быў разблякаваны.",
        "blocklist": "Заблякаваныя ўдзельнікі",
        "ipblocklist": "Заблякаваныя ўдзельнікі",
        "ipblocklist-legend": "Пошук заблякаванага ўдзельніка",
        "import": "Імпартаваць старонкі",
        "importinterwiki": "Імпартаваньне зь іншых вікі",
        "import-interwiki-text": "Абярыце вікі і назву старонкі для імпартаваньня.\nДаты зьменаў і імёны аўтараў будуць захаваныя.\nУсе дзеяньні імпартаваньня паміж вікі запісваюцца ў [[Special:Log/import|журнал імпартаваньняў]].",
-       "import-interwiki-source": "Крынічная вікі/старонка:",
+       "import-interwiki-sourcewiki": "Крынічная вікі:",
+       "import-interwiki-sourcepage": "Крынічная старонка:",
        "import-interwiki-history": "Капіяваць гісторыю старонкі цалкам",
        "import-interwiki-templates": "Уключыць усе шаблёны",
        "import-interwiki-submit": "Імпартаваць",
        "import-upload": "Загрузіць XML-зьвесткі",
        "import-token-mismatch": "Страчаныя зьвесткі сэсіі. Калі ласка, паспрабуйце ізноў.",
        "import-invalid-interwiki": "Немагчыма імпартаваць з вызначанай вікі.",
-       "import-error-edit": "Старонка «$1» не імпартаваная, бо Вы ня маеце правоў на яе рэдагаваньне.",
-       "import-error-create": "Старонка «$1» не імпартаваная, бо Вы ня маеце правоў на яе стварэньне.",
-       "import-error-interwiki": "Старонка «$1» не была імпартаваная, таму што гэтая назва зарэзэрваваная для інтэрвікі.",
+       "import-error-edit": "Старонка «$1» не была імпартаваная, бо Вы ня маеце правоў на яе рэдагаваньне.",
+       "import-error-create": "Старонка «$1» не была імпартаваная, бо Вы ня маеце правоў на яе стварэньне.",
+       "import-error-interwiki": "Старонка «$1» не была імпартаваная, таму што яе назва зарэзэрваваная для вонкавых спасылак (інтэрвікі).",
        "import-error-special": "Старонка «$1» не была імпартаваная, таму што яна належыць да спэцыяльнай прасторы назваў, старонкі ў якой не дазволеныя.",
-       "import-error-invalid": "Старонка «$1» не была імпартаваная з-за няслушнасьці назвы.",
+       "import-error-invalid": "Старонка «$1» не была імпартаваная, таму што назва зь якой яна павінна быць імпартаваная, не дазволеная ў гэтай вікі.",
        "import-error-unserialize": "Не атрымалася дэсэрыялізаваць вэрсію $2 старонкі «$1». Меркавалася, што вэрсія выкарыстоўвала мадэль зьвестак $3 і была сэрыялізавана ў фармаце $4.",
        "import-error-bad-location": "Праўка $2, якая выкарыстоўвае мадэль зьместу $3, ня можа быць захаваная ў «$1» гэтай вікі, таму што такая мадэль не падтрымліваецца на гэтай старонцы.",
        "import-options-wrong": "{{PLURAL:$2|1=Няслушная налада|Няслушныя налады}}: <nowiki>$1</nowiki>",
        "importlogpage": "Журнал імпартаваньняў",
        "importlogpagetext": "Імпартаваньне адміністратарамі старонак з гісторыяй зьменаў зь іншых вікі.",
        "import-logentry-upload": "імпартавана [[$1]] праз загрузку файла",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|вэрсія|вэрсіі|вэрсіяў}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|вэрсія імпартаваная|вэрсіі імпартаваныя|вэрсіяў імпартаваныя}}",
        "import-logentry-interwiki": "імпартавана зь іншай вікі $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|вэрсія|вэрсіі|вэрсіяў}} з $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|вэрсія імпартаваная|вэрсіі імпартаваныя|вэрсіяў імпартаваныя}} з $2",
        "javascripttest": "Тэставаньне JavaScript",
        "javascripttest-title": "Праводзіцца тэставаньне $1",
        "javascripttest-pagetext-noframework": "Гэтая старонка трымаецца для правядзеньня тэстаў JavaScript.",
        "autosumm-replace": "Старонка замененая на '$1'",
        "autoredircomment": "Перанакіроўвае на [[$1]]",
        "autosumm-new": "Створана старонка са зьместам '$1'",
+       "autosumm-newblank": "Створаная пустая старонка",
        "size-bytes": "$1 б",
        "size-kilobytes": "$1 кб",
        "size-megabytes": "$1 Мб",
        "timezone-utc": "UTC",
        "unknown_extension_tag": "Невядомы тэг пашырэньня «$1»",
        "duplicate-defaultsort": "Папярэджаньне: Ключ сартыроўкі па змоўчваньні «$2» замяняе папярэдні ключ сартыроўкі па змоўчваньні «$1».",
+       "duplicate-displaytitle": "<strong>Папярэджаньне:</strong> назва для адлюстраваньня «$2» перапісвае ранейшую назву для адлюстраваньня «$1».",
        "version": "Вэрсія",
        "version-extensions": "Усталяваныя пашырэньні",
        "version-skins": "Усталяваныя тэмы афармленьня",
        "logentry-rights-rights": "$1 {{GENDER:$1|зьмяніў|зьмяніла}} прыналежнасьць $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",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|загрузіў|загрузіла}} новую вэрсію $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|загрузіў|загрузіла}} $3",
        "rightsnone": "(няма)",
        "feedback-bugornote": "Калі Вы гатовы падрабязна апісаць тэхнічную праблему, калі ласка [$1 паведаміце пра памылку]. \nУ адваротным выпадку, Вы можаце выкарыстоўваць простую форму пададзеную ніжэй. Ваш камэнтар будзе дададзены на старонку «[$3 $2]», разам з Вашым іменем удзельніка і выкарыстоўваемым браўзэрам.",
        "feedback-subject": "Тэма:",
        "pagelang-use-default": "Ужываць мову па змоўчаньні",
        "pagelang-select-lang": "Абярыце мову",
        "right-pagelang": "Зьмяніць мову старонкі",
-       "action-pagelang": "зьмену мовы старонкі"
+       "action-pagelang": "зьмену мовы старонкі",
+       "log-name-pagelang": "Журнал зьменаў мовы",
+       "log-description-pagelang": "Гэта журнал зьменаў мовы старонак.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|зьмяніў|зьмяніла}} мову старонкі $3 з $4 на $5.",
+       "default-skin-not-found": "Упс! Тэма афармленьня па змоўчаньні для вашай вікі, вызначаная ў <code dir=\"ltr\">$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's каталёгу тэмаў]:\n:* Спампуйце [https://www.mediawiki.org/wiki/Download tarball-усталёўнік], які ўтрымлівае некалькі тэмаў і пашырэньняў. Вы можаце скапіяваць каталёг <code>skins/</code> зь яго.\n:* Зрабіце клон аднаго з сховішчаў <code>mediawiki/skins/*</code> праз git у каталёг <code dir=\"ltr\">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 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Вы ня маеце ўсталяваных тэмаў афармленьня.\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 dir=\"ltr\">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 ('''адключана''')"
 }
index 1a09be1..fd2d3c4 100644 (file)
@@ -39,6 +39,7 @@
        "tog-watchdefault": "Дабаўляць старонкі і файлы пасля маіх правак у мой спіс назірання",
        "tog-watchmoves": "Дабаўляць перайменаваныя мной старонкі і файлы ў мой спіс назірання",
        "tog-watchdeletion": "Дабаўляць сцёртыя мной старонкі і файлы ў мой спіс назірання",
+       "tog-watchrollback": "Дадаваць старонкі, дзе я {{GENDER:|зрабіў|зрабіла}} адкат, у мой спіс назірання",
        "tog-minordefault": "Пачынаць кожную праўку як дробную",
        "tog-previewontop": "Папярэдні паказ — над рэдактарскім полем",
        "tog-previewonfirst": "Папярэдні паказ пры першай праўцы",
        "thu": "Чц",
        "fri": "Пт",
        "sat": "Сб",
-       "january": "Студзень",
-       "february": "Ð\9bюты",
-       "march": "Сакавік",
-       "april": "Ð\9aрасавік",
-       "may_long": "ТÑ\80авенÑ\8c",
-       "june": "Чэрвень",
-       "july": "Ð\9bіпень",
-       "august": "Ð\96нівень",
-       "september": "Ð\92ерасень",
-       "october": "Ð\9aастрычнік",
-       "november": "Ð\9bістапад",
-       "december": "Снежань",
+       "january": "cтудзень",
+       "february": "люты",
+       "march": "сакавік",
+       "april": "красавік",
+       "may_long": "май",
+       "june": "чэрвень",
+       "july": "ліпень",
+       "august": "Ðнівень",
+       "september": "верасень",
+       "october": "кастрычнік",
+       "november": "лістапад",
+       "december": "снежань",
        "january-gen": "студзеня",
        "february-gen": "лютага",
        "march-gen": "сакавіка",
        "talkpagelinktext": "Размовы",
        "specialpage": "Адмысловая старонка",
        "personaltools": "Асабістыя прылады",
-       "postcomment": "Новы раздзел",
        "articlepage": "Паказаць старонку змесціва",
        "talk": "Размовы",
        "views": "Віды",
        "pool-timeout": "Выйшаў час чакання блакіроўкі",
        "pool-queuefull": "Чарга запытаў перапоўнена",
        "pool-errorunknown": "Невядомая памылка",
+       "pool-servererror": "Служба лічыльніка пулу недаступная ($1).",
        "aboutsite": "Пра {{GRAMMAR:вінавальны|{{SITENAME}}}}",
        "aboutpage": "Project:Пра {{GRAMMAR:вінавальны|{{SITENAME}}}}",
        "copyright": "Матэрыял даступны на ўмовах $1 (калі не пазначана іншае).",
        "hidetoc": "не паказваць",
        "collapsible-collapse": "Схаваць",
        "collapsible-expand": "Паказаць",
+       "confirmable-confirm": "{{GENDER:$1|Вы}} ўпэўнены?",
+       "confirmable-yes": "Так",
+       "confirmable-no": "Не",
        "thisisdeleted": "Паказаць ці аднавіць $1?",
        "viewdeleted": "Ці паказаць $1?",
        "restorelink": "$1 {{PLURAL:$1|сцёртая праўка|сцёртыя праўкі|сцёртых правак}}",
        "invalidtitle-knownnamespace": "Недапушчальны загаловак з прасторай імёнаў \"$2\" і тэкстам \"$3\"",
        "invalidtitle-unknownnamespace": "Недапушчальны загаловак з невядомым лікам прасторы імён $1 і тэкстам \"$2\"",
        "exception-nologin": "Вы не ўвайшлі ў сістэму",
-       "exception-nologin-text": "Належыць [[Special:Userlogin|прадставіцца сістэме]], каб мець доступ да гэтай старонкі ці дзеяння.",
+       "exception-nologin-text": "Належыць прадставіцца сістэме, каб мець доступ да гэтай старонкі ці дзеяння.",
        "exception-nologin-text-manual": "Належыць $1, каб мець доступ да гэтай старонкі ці дзеяння.",
        "virus-badscanner": "Некарэктная канфігурацыя: невядомы антывірусны сканер: ''$1''",
        "virus-scanfailed": "не ўдалося праверыць (код $1)",
        "externaldberror": "Або памылка вонкавай аўтэнтыкацыі ў базе дадзеных, або вам не дазволена абнаўляць свой вонкавы рахунак.",
        "login": "Увайсці ў сістэму",
        "nav-login-createaccount": "Увайсці ў сістэму / стварыць рахунак",
-       "loginprompt": "Каб уваходзіць у сістэму {{SITENAME}}, трэба дазволіць у браўзеры квіткі (кукі).",
        "userlogin": "Увайсці ў сістэму / стварыць рахунак",
        "userloginnocreate": "Увайсці",
        "logout": "Выйсці з сістэмы",
        "userlogin-resetlink": "Забыліся даныя для ўваходу?",
        "userlogin-resetpassword-link": "Забылі пароль?",
        "userlogin-helplink2": "Даведка па прадстаўленні сістэме",
-       "userlogin-loggedin": "Вы ўжо ўвайшлі ў сістэму як {{GENDER:$1|$1}}.\nСкарыстайцеся формай ніжэй, каб прадставіцца сістэме як іншы ўдзельнік.",
-       "userlogin-createanother": "Стварыць яшчэ адзін уліковы запіс",
        "createacct-emailrequired": "Адрас электроннай пошты",
        "createacct-emailoptional": "Адрас электроннай пошты (неабавязкова)",
        "createacct-email-ph": "Увядзіце ваш адрас электроннай пошты",
        "changeemail-submit": "Змяніць адрас электроннай пошты:",
        "changeemail-cancel": "Адмена",
        "changeemail-throttled": "Надта штмат спробаў увайсці пад гэтым рахункам. Пачакайце $1 перад тым, як спрабаваць ізноў.",
+       "resettokens": "Скінуць токены",
+       "resettokens-text": "Вы можаце пераўстанавіць токены, якія дазваляюць атрымліваць доступ да пэўных прыватных звестак, звязаных з вашым уліковым запісам.\n\nВы мусіце скінуць токены, калі выпадкова падзяліліся імі з кім-небудзь, ці ваш уліковы запіс быў скампраметаваны.",
+       "resettokens-no-tokens": "Няма чаго скідваць.",
+       "resettokens-legend": "Скідванне токенаў",
+       "resettokens-tokens": "Токены:",
        "resettokens-token-label": "$1 (актуальнае значэнне: $2)",
+       "resettokens-watchlist-token": "Токен струменя (Atom/RSS) [[Special:Watchlist|зменаў старонак у вашым спісе назірання]]",
+       "resettokens-done": "Токены скінуты.",
+       "resettokens-resetbutton": "Скінуць выбраныя токены",
        "bold_sample": "Цёмны тэкст",
        "bold_tip": "Цёмны тэкст",
        "italic_sample": "Курсіўны тэкст",
        "preview": "Перадпаказ",
        "showpreview": "Як будзе",
        "showdiff": "Розніца",
+       "blankarticle": "<strong>Увага:</strong> Вы ствараеце пустую старонку.\nКалі вы націсніце \"{{int:savearticle}}\" яшчэ раз, будзе створана старонка без аніякага зместу.",
        "anoneditwarning": "Вы не ўвайшлі ў сістэму. Таму, калі вы запішаце старонку, у яе гісторыю трапіць ваш адрас IP.",
        "anonpreviewwarning": "''Вы не прайшлі ідэнтыфікацыю Захаванне будзе запісана з вашым IP адрасам у гісторыі правак гэтай старонкі.''",
-       "missingsummary": "'''Нагадваем''': вы не ўпісалі тлумачэння для сваёй праўкі. Калі націснуць Запісаць яшчэ раз, праўка будзе замацавана без тлумачэння.",
+       "missingsummary": "<strong>Нагадваем:</strong> вы не ўпісалі тлумачэння для сваёй праўкі. Калі націснуць \"{{int:savearticle}}\" яшчэ раз, праўка будзе замацавана без тлумачэння.",
        "missingcommenttext": "Калі ласка, увядзіце ніжэй каментарый.",
        "missingcommentheader": "'''Увага:''' вы нічога не ўпісалі ў тэму/загаловак гэтай заўвагі. Націсканне '{{int:savearticle}}' замацуе вашую праўку з пустой тэмай/загалоўкам.",
        "summary-preview": "Перадпаказ апісання:",
        "accmailtitle": "Быў адасланы пароль",
        "accmailtext": "На адрас $2 быў дасланы згенераваны пароль для [[User talk:$1|$1]]. Ён можа быць зменены на <em>[[Special:ChangePassword|старонцы змены пароля]]</em> пасля ўваходу ў сістэму.",
        "newarticle": "(Новы)",
-       "newarticletext": "Вы перайшлі да старонкі, якой яшчэ няма, і таму трапілі сюды. Каб пачаць новую старонку, пішыце яе тэкст у ніжэйпаказаным акне рэдагавання (падрабязнасці бач у [$1 даведцы]). Калі вы тут выпадкова, проста націсніце \"назад\" у браўзеры.",
+       "newarticletext": "Вы перайшлі да старонкі, якой яшчэ няма, і таму трапілі сюды. \nКаб пачаць новую старонку, пішыце яе тэкст у ніжэйпаказаным акне рэдагавання (падрабязнасці бач у [$1 даведцы]). \nКалі вы тут выпадкова, проста націсніце <strong>назад</strong> у браўзеры.",
        "anontalkpagetext": "----''Гэта старонка размовы з ананімным удзельнікам, які або не мае свайго рахунку, або ім не карыстаўся. Таму дзеля яго ці яе ідэнтыфікацыі мы мусім выкарыстаць лічбавы Адрас IP. Такі адрас IP могуць дзяліць між сабою некалькі асоб. Калі вы ананімны ўдзельнік, і лічыце, што атрымліваеце няслушныя заўвагі,[[Special:UserLogin/signup|стварыце рахунак]] або [[Special:UserLogin|акажыцеся]], каб вас больш не блыталі з іншымі ананімнымі ўдзельнікамі.''",
        "noarticletext": "Старонка не ўтрымлівае тэксту. Вы можаце [[Special:Search/{{PAGENAME}}|пашукаць гэткую назву]] ў іншых старонках ці <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ў журналах],\nабо [{{fullurl:{{FULLPAGENAME}}|action=edit}} папрацаваць з гэтай старонкай]</span>.",
        "noarticletext-nopermission": "Старонка не ўтрымлівае тэксту.\nВы можаце [[Special:Search/{{PAGENAME}}|пашукаць гэткую назву]] ў іншых старонках,\nці <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ў журналах]</span>, але вы не маеце дазволу на стварэнне гэтай старонкі.",
        "parser-template-recursion-depth-warning": "Вычарпаны ліміт глыбіні ўключэння шаблонаў ($1)",
        "language-converter-depth-warning": "Перавышана глыбіня моўнага канвертэра ($1)",
        "node-count-exceeded-category": "Старонкі, якія перасягнулі колькасць вузлоў",
-       "node-count-exceeded-category-desc": "Ð\9aаÑ\82Ñ\8dгоÑ\80Ñ\8bÑ\8f Ð´Ð»Ñ\8f Ñ\81Ñ\82аÑ\80онак, Ñ\83 Ñ\8fкÑ\96Ñ\85 Ð¿ÐµÑ\80авÑ\8bÑ\88ана колькасць вузлоў.",
+       "node-count-exceeded-category-desc": "Ð\9dа Ñ\81Ñ\82аÑ\80онÑ\86Ñ\8b Ð¿ÐµÑ\80авÑ\8bÑ\88ана Ð¼Ð°ÐºÑ\81Ñ\96малÑ\8cнаÑ\8f колькасць вузлоў.",
        "node-count-exceeded-warning": "Старонка перасягнула колькасць вузлоў",
        "expansion-depth-exceeded-category": "Старонкі, якія перасягнулі глыбіню разгортвання",
-       "expansion-depth-exceeded-category-desc": "Ð\93Ñ\8dÑ\82а ÐºÐ°Ñ\82Ñ\8dгоÑ\80Ñ\8bÑ\8f Ð´Ð»Ñ\8f Ñ\81Ñ\82аÑ\80онак, Ñ\83 Ñ\8fкÑ\96Ñ\85 Ð¿ÐµÑ\80аÑ\81Ñ\8fгнÑ\83Ñ\82а глыбіня разгортвання.",
+       "expansion-depth-exceeded-category-desc": "Ð\9dа Ñ\81Ñ\82аÑ\80онÑ\86Ñ\8b Ð¿ÐµÑ\80аÑ\81Ñ\8fгнÑ\83Ñ\82а Ð¼Ð°ÐºÑ\81Ñ\96малÑ\8cнаÑ\8f глыбіня разгортвання.",
        "expansion-depth-exceeded-warning": "Старонка перасягнула глыбіню разгортвання",
        "parser-unstrip-loop-warning": "Выяўлены закальцаваны unstrip",
        "parser-unstrip-recursion-limit": "Перавышаны ліміт рэкурсіі unstrip ($1)",
        "rev-deleted-event": "(сцёртае дзеянне з журналам)",
        "rev-deleted-user-contribs": "[імя ўдзельніка альбо IP-адрас выдалены — рэдагаванне скрытыя ад узносаў]",
        "rev-deleted-text-permission": "Гэтая версія старонкі была '''сцёртая'''.\nПадрабязнасці гл. у [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале сціранняў].",
+       "rev-suppressed-text-permission": "Гэта версія старонкі <strong>схаваная</strong>.\nПадрабязнасці можна пабачыць у [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале ўтойвання].",
        "rev-deleted-text-unhide": "Гэтая версія старонкі была '''выдаленая'''.\nМагчыма, падрабязнасці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} часопісе сціранняў].\nПры жаданні, Вы можаце [$1 праглядзець гэтую вэрсію].",
        "rev-suppressed-text-unhide": "Гэтая вэрсія старонкі была '''схаваная'''.\nМагчыма, падрабязнасці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} часопісе сціранняў].\nПры жаданні, Вы можаце [$1 праглядзець гэтую вэрсію].",
        "rev-deleted-text-view": "Гэтая версія старонкі была '''сцёртая'''.\nВы можаце яе бачыць; падрабязнасці гл. у [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале сціранняў].",
        "revdelete-text-text": "Сцёртыя версіі будуць па-ранейшаму паказвацца ў гісторыі старонкі, але частка іх зместу будзе недаступна для грамадскасці.",
        "revdelete-text-file": "Сцёртыя версіі файла будуць па-ранейшаму паказвацца ў гісторыі файла, але частка іх зместу будзе недаступна для грамадскасці.",
        "logdelete-text": "Сцёртыя запісы журнала будуць па-ранейшаму паказвацца ў журналах, але частка іх зместу будзе недаступна для грамадскасці.",
-       "revdelete-text-others": "Ð\86нÑ\88Ñ\8bÑ\8f Ð°Ð´Ð¼Ñ\96нÑ\96Ñ\81Ñ\82Ñ\80аÑ\82аÑ\80Ñ\8b Ð¿Ð»Ñ\8fÑ\86оÑ\9eкÑ\96 {{SITENAME}} Ð±Ñ\83дÑ\83Ñ\86Ñ\8c Ð¿Ð°-Ñ\80анейÑ\88амÑ\83 Ð¼ÐµÑ\86Ñ\8c Ð´Ð¾Ñ\81Ñ\82Ñ\83п Ð´Ð° Ñ\81Ñ\85аванага Ð·Ð¼ÐµÑ\81Ñ\82Ñ\83 Ñ\96 Ð·Ð¼Ð¾Ð³Ñ\83Ñ\86Ñ\8c Ð°Ð´Ð½Ð°Ð²Ñ\96Ñ\86Ñ\8c Ñ\8fго Ð¿Ñ\80аз Ð³Ñ\8dÑ\82Ñ\8b Ñ\81амÑ\8b Ñ\96нÑ\82Ñ\8dÑ\80Ñ\84ейÑ\81, калі не ўстанавіць дадатковыя абмежаванні.",
+       "revdelete-text-others": "Ð\86нÑ\88Ñ\8bÑ\8f Ð°Ð´Ð¼Ñ\96нÑ\96Ñ\81Ñ\82Ñ\80аÑ\82аÑ\80Ñ\8b Ð±Ñ\83дÑ\83Ñ\86Ñ\8c Ð¿Ð°-Ñ\80анейÑ\88амÑ\83 Ð¼ÐµÑ\86Ñ\8c Ð´Ð¾Ñ\81Ñ\82Ñ\83п Ð´Ð° Ñ\81Ñ\85аванага Ð·Ð¼ÐµÑ\81Ñ\82Ñ\83 Ñ\96 Ð·Ð¼Ð¾Ð³Ñ\83Ñ\86Ñ\8c Ð°Ð´Ð½Ð°Ð²Ñ\96Ñ\86Ñ\8c Ñ\8fго, калі не ўстанавіць дадатковыя абмежаванні.",
        "revdelete-confirm": "Пацвердзіце, што вы жадаеце гэта зрабіць, што вы разумееце наступствы, і што вы робіце гэта ў адпаведнасці з [[{{MediaWiki:Policy-url}}|арганізацыйнымі правіламі]].",
        "revdelete-suppress-text": "Заглушэнне належыць ужываць <strong>выключна</strong> ў наступных выпадках:\n* патэнцыяльна паклёпніцкія звесткі\n* недапушчальная асабістая інфармацыя\n*: <em>хатнія адрасы і тэлефоны, нумары страхавання і г.д.</em>",
        "revdelete-legend": "Настроіць абмежаванні бачнасці",
        "searchprofile-advanced-tooltip": "Шукаць у дадатковых прасторах назваў",
        "search-result-size": "$1 ({{PLURAL:$2|1 слова|$2 словы|$2 словаў}})",
        "search-result-category-size": "{{PLURAL:$1|$1 элемент|$1 элемента|$1 элементаў}} ({{PLURAL:$2|$2 падкатэгорыя|$2 падкатэгорыі|$2 падкатэгорый}}, {{PLURAL:$3|$3 файл|$3 файла|$3 файлаў}})",
-       "search-result-score": "Адпаведнасць: $1%",
        "search-redirect": "(перасылка $1)",
        "search-section": "(падраздзел $1)",
        "search-file-match": "(адпавядае змесціву файла)",
        "preferences": "Настройкі",
        "mypreferences": "Настройкі",
        "prefs-edits": "Колькасць правак:",
-       "prefsnologintext2": "Трэба $1, каб мяняць свае настройкі.",
+       "prefsnologintext2": "Трэба прадставіцца сістэме, каб мяняць свае настройкі.",
        "prefs-skin": "Вокладка",
        "skin-preview": "Перадпаказ",
        "datedefault": "Не вызначана",
        "right-deletedtext": "Адкрыць выдалены тэкст і ўсе змены паміж выдаленымі версіямі",
        "right-browsearchive": "Шукаць у сцёртых старонках",
        "right-undelete": "Аднаўляць старонкі",
-       "right-suppressrevision": "Бачыць і аднаўляць версіі, схаваныя ад адміністратараў",
+       "right-suppressrevision": "Бачыць, хаваць і адкрываць схаваныя асобныя версіі ад усіх удзельнікаў",
+       "right-viewsuppressed": "Бачыць версіі, схаваныя ад усіх удзельнікаў",
        "right-suppressionlog": "Чытаць прыватныя журналы",
        "right-block": "Забараняць праўкі іншым удзельнікам",
        "right-blockemail": "Забараняць удзельніку адсыланне эл.пошты",
        "right-userrights-interwiki": "Правіць дазволы ўдзельнікаў на іншых вікі",
        "right-siteadmin": "Замыкаць і адмыкаць базу даных",
        "right-override-export-depth": "Экспартаваць старонкі, у тым ліку звязаныя, да глыбіні спасылак 5.",
-       "right-sendemail": "Адправіць па электроннай пошце іншым карыстальнікам",
-       "right-passwordreset": "пÑ\80аглÑ\8fд Ñ\8dлекÑ\82Ñ\80оннÑ\8bÑ\85 Ð»Ñ\96Ñ\81Ñ\82оÑ\9e Ñ\81а Ð·Ð¼Ñ\8fненнем пароля",
+       "right-sendemail": "Адпраўляць электронныя лісты іншым удзельнікам",
+       "right-passwordreset": "Ð\91аÑ\87Ñ\8bÑ\86Ñ\8c Ñ\8dлекÑ\82Ñ\80оннÑ\8bÑ\8f Ð»Ñ\96Ñ\81Ñ\82Ñ\8b Ð°Ð± Ð·Ð¼Ñ\8fненнÑ\96 пароля",
        "newuserlogpage": "Журнал рэгістрацыі ўдзельнікаў",
        "newuserlogpagetext": "Гэта журнал рэгістрацыі новых удзельнікаў.",
        "rightslog": "Журнал правоў удзельнікаў",
        "recentchanges-label-plusminus": "Аб'ём старонкі змяніўся на гэтую лічбу байтаў",
        "recentchanges-legend-heading": "'''Легенда:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (гл. асобна [[Special:NewPages|новыя старонкі]])",
-       "rcnotefrom": "Ніжэй знаходзяцца змены з <b>$2</b> (паказана не больш чым <b>$1</b>).",
+       "rcnotefrom": "Ніжэй {{PLURAL:$5|паказана змяненне|паказаны змены}} з <strong>$3, $4</strong> (не больш за <strong>$1</strong>).",
        "rclistfrom": "Паказаць змены з $3 $2",
        "rcshowhideminor": "$1 дробныя праўкі",
        "rcshowhideminor-show": "Паказаць",
        "uploadwarning": "Папярэджанне пра ўкладанне",
        "uploadwarning-text": "Калі ласка, змяніце апісанне файла ніжэй і паўтарыце спробу.",
        "savefile": "Запісаць файл",
-       "uploadedimage": "укладзена \"[[$1]]\"",
-       "overwroteimage": "укладзена новая версія \"[[$1]]\"",
        "uploaddisabled": "Укладанні не дазваляюцца",
        "copyuploaddisabled": "Даданне па URL адключана.",
        "uploaddisabledtext": "Не дазваляюцца ўкладанні файлаў.",
        "license": "Ліцэнзіяванне:",
        "license-header": "Ліцэнзіяванне",
        "nolicense": "Нішто не выбрана",
+       "licenses-edit": "Правіць параметры ліцэнзіі",
        "license-nopreview": "(без перадпаказу)",
-       "upload_source_url": " (сапраўдны, публічна дасягальны URL)",
-       "upload_source_file": " (файл на вашай машыне)",
+       "upload_source_url": "(выбраны файл з сапраўднага, публічна дасяжнага URL)",
+       "upload_source_file": "(выбраны файл з вашага камп'ютара)",
+       "listfiles-delete": "сцерці",
        "listfiles-summary": "Гэтая службовая старонка паказвае ўсе загружаныя файлы.",
        "listfiles_search_for": "Знайсці назву выявы:",
        "imgfile": "файл",
        "listduplicatedfiles-summary": "Гэта пералік файлаў, у якіх найноўшая версія файла ўяўляе сабою копію апошняй версіі якога-небудзь іншага файла. Улічваюцца толькі лакальныя файлы.",
        "listduplicatedfiles-entry": "[[:File:$1|$1]] мае [[$3|{{PLURAL:$2|дублікат|$2 дублікаты|$2 дублікатаў}}]].",
        "unusedtemplates": "Шаблоны, якія не выкарыстаны",
-       "unusedtemplatestext": "Тут пералічаныя ўсе старонкі ў прасторы назваў {{ns:template}}, якія ані разу не ўкладзеныя ў іншыя старонкі. Памятайце, што трэба правяраць спасылкі на шаблоны перад тым, як сціраць іх.",
+       "unusedtemplatestext": "Тут пералічаныя ўсе старонкі ў прасторы назваў {{ns:template}}, якія ані разу не ўкладзеныя ў іншыя старонкі.\nПамятайце, што трэба правяраць спасылкі на шаблоны перад тым, як сціраць іх.",
        "unusedtemplateswlh": "іншыя спасылкі",
        "randompage": "Выпадковая старонка",
        "randompage-nopages": "Няма старонак у наступн{{PLURAL:$2|ай прасторы|ых прасторах}} назваў: $1.",
        "randomincategory": "Выпадковая старонка ў катэгорыі",
        "randomincategory-invalidcategory": "\"$1\" - недапушчальная назва катэгорыі.",
        "randomincategory-nopages": "Няма старонак у катэгорыі [[:Category:$1|$1]].",
-       "randomincategory-selectcategory": "Атрымаць выпадковую старонку з катэгорыі: $1 $2.",
-       "randomincategory-selectcategory-submit": "Перайсці",
+       "randomincategory-category": "Катэгорыя:",
+       "randomincategory-legend": "Выпадковая старонка ў катэгорыі",
        "randomredirect": "Выпадковая перасылка",
        "randomredirect-nopages": "Няма перасылак у прасторы назваў \"$1\".",
        "statistics": "Статыстыка",
        "wantedpages-badtitle": "Недапушчальная назва ў выніках: $1",
        "wantedfiles": "Патрэбныя файлы",
        "wantedfiletext-cat": "Наступныя файлы выкарыстоўваюцца, але іх няма. Файлы са знешніх сховішчаў могуць знаходзіцца ў спісе без уліку іх існавання. Любыя такія няслушныя ўваходжанні будуць <del>выкрасленыя</del>. Дадаткова, старонкі, якія ўбудоўваюць неіснуючыя файлы прыведзеныя на [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Наступныя файлы выкарыстоўваюцца, хаця іх няма. Дадаткова, старонкі, што ўключаюць файлы, каторых няма, пералічаны ў [[:$1]].",
        "wantedfiletext-nocat": "Наступныя файлы выкарыстоўваюцца, але іх няма. Файлы са знешніх сховішчаў могуць знаходзіцца ў спісе без уліку іх існавання. Любыя такія няслушныя ўваходжанні будуць <del>выкрасленыя</del>.",
+       "wantedfiletext-nocat-noforeign": "Наступныя файлы выкарыстоўваюцца, хоць іх няма.",
        "wantedtemplates": "Патрэбныя шаблоны",
        "mostlinked": "Старонкі, на якія найчасцей спасылаюцца",
        "mostlinkedcategories": "Катэгорыі з найбольшай колькасцю складнікаў",
        "mostlinkedtemplates": "Шаблоны ў частым выкарыстанні",
-       "mostcategories": "Артыкулы ў найбольшай кольк. катэгорый",
+       "mostcategories": "Артыкулы ў найбольшай колькасці катэгорый",
        "mostimages": "Выявы ў частым выкарыстанні",
        "mostinterwikis": "Артыкулы з найбольш. кольк. інтэрвікі",
        "mostrevisions": "Артыкулы з найбольшай колькасцю версій",
        "listusers-editsonly": "Толькі ўдзельнікі, якія маюць праўкі",
        "listusers-creationsort": "У парадку датаў стварэння",
        "listusers-desc": "Парадкаваць да памяншэння",
-       "usereditcount": "$1 {{PLURAL:$1|праўка|праўкі}}",
-       "usercreated": "\t{{GENDER:$3|Зарэгістраваўся|Зарэгістравалася}} $1 в $2",
+       "usereditcount": "$1 {{PLURAL:$1|праўка|праўкі|правак}}",
+       "usercreated": "\t{{GENDER:$3|Зарэгістраваўся|Зарэгістравалася}} $1 у $2",
        "newpages": "Новыя старонкі",
        "newpages-username": "Імя ўдзельніка:",
        "ancientpages": "Найстарэйшыя старонкі",
        "index-category-desc": "На старонцы ёсць магічнае слова <code><nowiki>__INDEX__</nowiki></code> (і старонка знаходзіцца ў прасторы назваў, дзе гэты сцяг дазволены), таму яна індэксуецца пошукавымі робатамі у выпадках, калі гэтага звычайна не адбываецца.",
        "post-expand-template-inclusion-category-desc": "Пасля разгортвання ўсіх шаблонаў памер старонкі перавышае <code>$wgMaxArticleSize</code>, таму некаторыя шаблоны пакінуты неразгорнутымі.",
        "post-expand-template-argument-category-desc": "Пасля разгортвання аргумента шаблона (штосьці ў патройных фігурных дужках, напрыклад, <code>{{{Foo}}}</code>), памер старонкі перавышае <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Ð\97анадÑ\82а Ñ\88маÑ\82 Ð¿Ñ\80аÑ\86аÑ\91мкÑ\96Ñ\85 Ð·Ð²Ð°Ñ\80оÑ\82аÑ\9e Ð´Ð° Ñ\84Ñ\83нкÑ\86Ñ\8bй Ð¿Ð°Ñ\80Ñ\81еÑ\80а (напÑ\80Ñ\8bклад, <code>#ifexist</code>) Ñ\83клÑ\8eÑ\87ана Ñ\9e Ñ\81Ñ\82аÑ\80онкÑ\83. Гл. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Ð\9aаÑ\82Ñ\8dгоÑ\80Ñ\8bÑ\8f Ð´Ð°Ð´Ð°ÐµÑ\86Ñ\86а, ÐºÐ°Ð»Ñ\96 Ñ\81таронка ўтрымлівае няспраўную спасылку на файл (спасылку на ўкладзены файл, якога няма).",
-       "hidden-category-category-desc": "Гэта катэгорыя змяшчае <code><nowiki>__HIDDENCAT__</nowiki></code>, што паводле прадвызначэння засцерагае яе ад паказу ў спісе катэгорый на старонках.",
+       "expensive-parserfunction-category-desc": "У Ñ\81Ñ\82аÑ\80онкÑ\83 Ñ\9eклÑ\8eÑ\87ана Ð·Ð°Ð½Ð°Ð´Ñ\82а Ñ\88маÑ\82 Ð¿Ñ\80аÑ\86аÑ\91мкÑ\96Ñ\85 Ð·Ð²Ð°Ñ\80оÑ\82аÑ\9e Ð´Ð° Ñ\84Ñ\83нкÑ\86Ñ\8bй Ð¿Ð°Ñ\80Ñ\81еÑ\80а (напÑ\80Ñ\8bклад, <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": "Няма эл.адрасу",
        "mywatchlist": "Спіс назірання",
        "watchlistfor2": "Для $1 $2",
        "nowatchlist": "Ваш спіс назірання зараз пусты.",
-       "watchlistanontext": "Каб паглядзець ці змяніць спіс назірання, трэба $1.",
+       "watchlistanontext": "Каб паглядзець ці змяніць спіс назірання, трэба прадставіцца сістэме.",
        "watchnologin": "Без прадстаўлення",
        "addwatch": "Дадаць у спіс назірання",
        "addedwatchtext": "Старонка \"[[:$1]]\" была дададзена да [[Special:Watchlist|назіраных]] вамі.\nЗмяненні, якія адбудуцца з гэтай старонкай і з размовамі пра яе, будуць паказвацца ў спісе назірання.",
        "watchlist-details": "Назіраю {{PLURAL:$1|$1 старонку|$1 старонкі|$1 старонак}} без уліку размоўных.",
        "wlheader-enotif": "Працуе апавяшчанне праз эл.пошту.",
        "wlheader-showupdated": "Старонкі, якія былі зменены пасля вашага апошняга наведвання, паказаны <strong>абрысам шрыфту</strong>.",
-       "wlnote2": "Ніжэй паказаны змены за {{PLURAL:$1|апошнюю гадзіну|апошнія <strong>$1</strong> гадзіны|апошнія <strong>$1</strong> гадзін}}, па стане на $2, $3.",
+       "wlnote": "Ніжэй {{PLURAL:$1|паказана апошняя <strong>$1</strong> змена|паказаны апошнія <strong>$1</strong> змены|паказаны апошнія <strong>$1</strong> змен}} за {{PLURAL:$2|апошнюю|апошнія|апошнія}} <strong>$2</strong> {{PLURAL:$2|гадзіну|гадзіны|гадзін}}, на момант часу $3 $4.",
        "wlshowlast": "Паказваць апошнія $1 гадз. $2 дзён $3",
        "watchlist-options": "Магчымасці назірання",
        "watching": "Дапісваецца ў спіс назірання...",
        "exbeforeblank": "змесціва перад ачысткаю было: '$1'",
        "delete-confirm": "Сцерці \"$1\"",
        "delete-legend": "Сцерці",
-       "historywarning": "'''Увага''': Старонка, якую вы хочаце сцерці, мае гісторыю прыблізна $1 {{PLURAL:$1|праўкі|правак}}:",
+       "historywarning": "<strong>Увага:</strong> Старонка, якую вы хочаце сцерці, мае гісторыю з прыблізна $1 {{PLURAL:$1|праўкі|правак}}:",
        "confirmdeletetext": "Вы збіраецеся сцерці старонку разам з цэлай яе гісторыяй правак.\nПацвердзіце свой намер зрабіць гэта, сваё разуменне наступстваў, і што вы робіце гэта ў адпаведнасці з [[{{MediaWiki:Policy-url}}|палітыкай (асноўнымі правіламі)]].",
        "actioncomplete": "Завершана аперацыя",
        "actionfailed": "Памылка дзеяння",
        "delete-edit-reasonlist": "Правіць прычыны сцірання",
        "delete-toobig": "Старонка мае вялікую гісторыю правак, больш за $1 {{PLURAL:$1|версію|версій}}. Сціранне такіх старонак было абмежавана, каб пазбегчы ўтварэння выпадковых перашкод працы {{SITENAME}}.",
        "delete-warning-toobig": "Старонка мае вялікую гісторыю правак, больш за $1 {{PLURAL:$1|версію|версій}}. Сціранне такіх старонак можа перашкодзіць працы базы даных {{SITENAME}}; будзьце асцярожнымі.",
+       "deleteprotected": "Вы не можаце сцерці гэтую старонку, таму што яна ахоўваецца.",
        "deleting-backlinks-warning": "'''Увага:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Іншыя старонкі]] спасылаюцца на ці ўключаюць старонку, якую вы збіраецеся сцерці.",
        "rollback": "Адкаціць праўкі",
        "rollback_short": "Адкат",
        "protect-badnamespace-title": "Прастора імёнаў без аховы",
        "protect-badnamespace-text": "Старонкі ў гэтай прасторы імёнаў не могуць знаходзіцца пад аховай.",
        "protect-norestrictiontypes-text": "Старонка не можа ахоўвацца, таму што недаступны тыпы абмежавання.",
+       "protect-norestrictiontypes-title": "Неахоўвальная старонка",
        "protect-legend": "Пацверджанне пачатку аховы",
        "protectcomment": "Прычына:",
        "protectexpiry": "Канчаецца:",
        "autoblockid": "Аўтаблакіроўка #$1",
        "block": "Заблакаваць удзельніка",
        "unblock": "Разблакаваць удзельніка",
-       "blockip": "Заблакаваць удзельніка",
+       "blockip": "Заблакаваць {{GENDER:$1|удзельніка|удзельніцу}}",
        "blockip-legend": "Заблакаваць удзельніка",
        "blockiptext": "Гэты фармуляр дазваляе заблакаваць магчымасць запісу для пэўнага адрасу IP ці імя ўдзельніка.\nГэта трэба рабіць толькі дзеля засцерагання ад вандалізму і ў адпаведнасці з [[{{MediaWiki:Policy-url}}|правіламі]].\nНіжэй трэба ўпісаць канкрэтную прычыну (напрыклад, пералічваючы канкрэтныя старонкі, якія былі вандалізаваныя).",
        "ipaddressorusername": "IP-адрас ці імя ўдзельніка:",
        "ipb-unblock-addr": "Зняць блок з $1",
        "ipb-unblock": "Зняць блок з імя ўдзельніка або адрасу IP",
        "ipb-blocklist": "Паказаць наяўныя блокі",
-       "ipb-blocklist-contribs": "Уклад $1",
+       "ipb-blocklist-contribs": "Уклад {{GENDER:$1|$1}}",
        "unblockip": "Зняць блок з удзельніка",
        "unblockiptext": "У форме, што ніжэй, можна вярнуць дазвол на запіс для раней заблакаванага адрасу IP або ўдзельніка.",
        "ipusubmit": "Зняць гэты блок",
        "import": "Імпартаваць старонкі",
        "importinterwiki": "Імпарт Transwiki",
        "import-interwiki-text": "Выбар вікі і назвы старонкі дзеля імпарту.\nДаты версій і імёны аўтараў будуць захаваныя.\nУсе транс-вікавыя імпарты запісваюцца ў [[Special:Log/import|журнале імпартаў]].",
-       "import-interwiki-source": "Выточная вікі/старонка:",
+       "import-interwiki-sourcewiki": "Крынічная вікі:",
+       "import-interwiki-sourcepage": "Крынічная старонка:",
        "import-interwiki-history": "Капіраваць усе гістарычныя версіі гэтай старонкі",
        "import-interwiki-templates": "Разам з усімі шаблонамі",
        "import-interwiki-submit": "Імпартаваць",
        "import-invalid-interwiki": "Немагчыма імпартаваць з гэтай вікі.",
        "import-error-edit": "Старонка «$1» не была імпартавана, бо вам не дазволена яе правіць.",
        "import-error-create": "Старонка «$1» не была імпартавана, бо вам не дазволена яе ствараць.",
-       "import-error-interwiki": "Старонка «$1» не была імпартаваная, таму што гэтая назва зарэзерваваная для інтэрвікі.",
+       "import-error-interwiki": "Старонка «$1» не была імпартавана, таму што гэта назва зарэзервавана для інтэрвікі.",
        "import-error-special": "Старонка «$1» не была імпартаваная, таму што яна належыць да спецыяльнай прасторы назваў, старонкі ў якой не дазволеныя.",
-       "import-error-invalid": "Старонка «$1» не была імпартаваная з-за няслушнасці назвы.",
+       "import-error-invalid": "Старонка «$1» не была імпартавана, таму што назва, пад якую яна імпартуецца, недапушчальная на гэтай вікі.",
+       "import-error-unserialize": "Немагчыма дэсерыялізаваць версію $2 старонкі \"$1\". Меркавалася, што версія выкарыстоўвае мадэль змесціва $3, серыялізавана як $4.",
        "import-error-bad-location": "Версія $2, якая выкарыстоўвае мадэль змесціва $3, не можа быць запісана на старонцы \"$1\" гэтай вікі, паколькі такая мадэль не падтрымліваецца на гэтай старонцы.",
+       "import-options-wrong": "{{PLURAL:$2|1=Няправільны параметр|Няправільныя параметры}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "Пазначаная назва каранёвай старонкі недапушчальная.",
        "import-rootpage-nosubpage": "У прастора назваў \"$1\" каранёвай старонкі падстаронкі не дазволены.",
        "importlogpage": "Журнал імпартаванняў",
        "importlogpagetext": "Адміністрацыйныя імпартаванні старонак з іншых вікі, разам з гісторыямі правак.",
        "import-logentry-upload": "імпартавана [[$1]] праз файлавы ўклад",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|версія|версіі|версій}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|версія|версіі|версій}} імпартавана",
        "import-logentry-interwiki": "транс-вікавана $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|версія|версіі|версій}} з $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|версія|версіі|версій}} імпартавана з $2",
        "javascripttest": "JavaScript-тэсты",
        "javascripttest-title": "Праводзіцца тэставанне $1",
        "javascripttest-pagetext-noframework": "Гэта старонка зарэзервавана для запуску тэстаў JavaScript",
        "pageinfo-header-properties": "Уласцівасці старонкі",
        "pageinfo-display-title": "Паказаная назва",
        "pageinfo-default-sort": "Прадвызначаны ключ парадкавання",
-       "pageinfo-length": "Ð\94аÑ\9eжÑ\8bнÑ\8f старонкі (у байтах)",
+       "pageinfo-length": "Ð\90б'Ñ\91м старонкі (у байтах)",
        "pageinfo-article-id": "Ідэнтыфікатар старонкі",
        "pageinfo-language": "Мова змесціва старонкі",
        "pageinfo-content-model": "Мадэль змесціва старонкі",
        "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": "Спіс назірання",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|размовы]])",
        "unknown_extension_tag": "Невядомая метка пашырэння \"$1\"",
        "duplicate-defaultsort": "Увага: прадвызначаная клавіша ўпарадкавання \"$2\" замяніла ранейшую такую клавішу \"$1\".",
+       "duplicate-displaytitle": "<strong>Папярэджанне:</strong> Паказаная назва \"$2\" перасягае ранейшую назву \"$1\".",
        "version": "Версія",
        "version-extensions": "Устаноўленыя прыстаўкі",
        "version-skins": "Устаноўленыя вокладкі",
        "version-license-title": "Ліцэнзія $1",
        "version-license-not-found": "Не знойдзена падрабязнай інфармацыі аб ліцэнзіі для гэтай прыстаўкі.",
        "version-credits-title": "Спіс аўтараў $1",
+       "version-credits-not-found": "Для гэтай прыстаўкі не знойдзена падрабязных звестак пра аўтараў.",
        "version-poweredby-credits": "Пляцоўка працуе на '''[https://www.mediawiki.org/ MediaWiki]''', капірайт © 2001-$1 $2.",
        "version-poweredby-others": "іншыя",
        "version-poweredby-translators": "перакладчыкі translatewiki.net",
+       "version-credits-summary": "Мы хацелі б адзначыць наступных асоб, якія зрабілі ўнёсак у [[Special:Version|MediaWiki]].",
        "version-license-info": "MediaWiki з'яўляецца свабодным праграмным забеспячэннем. Такім чынам, вы можаце паўторна распаўсюджваць прадукт і(або) змяняць яго на ўмовах пагаднення GNU General Public License у тым выглядзе, у якім яно публікуецца фондам Free Software Foundation; сілу мае версія (выпуск) 2 гэтага пагаднення або, на ваш выбар, навейшая версія (выпуск) пагаднення.\n\nMediaWiki распаўсюджваецца, спадзеючыся на прыдатнасць прадукта, але БЕЗ ЯКІХ-НЕБУДЗЬ ГАРАНТЫЙ, у тым ліку, без імплікаваных гарантый СПАЖЫВЕЦКАЙ ВАРТАСЦІ або ПРЫДАТНАСЦІ ДЛЯ ЯКОЙ-НЕБУДЗЬ МЭТЫ. Больш падрабязна гл. пагадненне GNU General Public License.\n\nРазам з гэтым праграмным забеспячэннем вы павінны былі атрымаць [{{SERVER}}{{SCRIPTPATH}}/COPYING копію пагаднення GNU General Public License]. Калі гэта не так, паведамце аб гэтым у фонд Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA або [//www.gnu.org/licenses/old-licenses/gpl-2.0.html атрымайце яе з Інтэрнэту].",
        "version-software": "Устаноўленыя праграмныя прадукты",
        "version-software-product": "Прадукт",
        "version-software-version": "Версія",
+       "version-entrypoints": "Уваходныя адрасы",
        "version-entrypoints-header-entrypoint": "Кропка ўваходу",
        "version-entrypoints-header-url": "URL",
        "redirect": "Перасылка да файла, ID удзельніка, старонкі ці версіі",
        "htmlform-selectorother-other": "Рознае",
        "htmlform-no": "Не",
        "htmlform-yes": "Так",
+       "htmlform-chosen-placeholder": "Выберыце параметр",
        "htmlform-cloner-create": "Дадаць яшчэ",
        "htmlform-cloner-delete": "Сцерці",
        "htmlform-cloner-required": "Неабходна хаця б адно значэнне.",
        "logentry-rights-rights": "$1 {{GENDER:$2|змяніў|змяніла}} прыналежнасць $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",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|уклаў|уклала}} новую версію $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|уклаў|уклала}} $3",
        "rightsnone": "(няма)",
        "feedback-bugornote": "Калі вы гатовыя падрабязна апісаць тэхнічную праблему, калі ласка, [$1 паведаміце пра памылку].\nУ адваротным выпадку вы можаце выкарыстоўваць гэтую простую форму. Ваш каментар будзе дададзены на старонку «[$3 $2]» разам з вашым імем удзельніка і выкарыстоўваемым браўзерам.",
        "feedback-subject": "Тэма:",
        "duration-millennia": "$1 {{PLURAL:$1|тысячагоддзе|тысячагоддзі|тысячагоддзяў}}",
        "rotate-comment": "Выява павернута на $1 {{PLURAL:$1|градус|градусы|градусаў}} па гадзіннікавай стрэлцы",
        "limitreport-title": "Звесткі прафілявання парсера:",
+       "limitreport-cputime": "Выкарыстанне часу ЦП",
        "limitreport-cputime-value": "$1 {{PLURAL:$1|секунда|секунды|секундаў}}",
+       "limitreport-walltime": "Выкарыстанне рэальнага часу",
        "limitreport-walltime-value": "$1 {{PLURAL:$1|секунда|секунды|секундаў}}",
        "limitreport-ppvisitednodes": "Колькасць вузлоў, наведаных прэпрацэсарам",
        "limitreport-ppgeneratednodes": "Колькасць вузлоў, створаных прэпрацэсарам",
        "limitreport-expensivefunctioncount": "Колькасць працаёмкіх зваротаў да функцый парсера",
        "expandtemplates": "Разгортванне шаблонаў",
        "expand_templates_intro": "Гэта адмысловая старонка бярэ тэкст і разгортвае ў ім усе шаблоны рэкурсіўна.\nТаксама разгортвае падтрыманыя функцыі парсера кшталту\n<code><nowiki>{{</nowiki>#language:…}}</code> і зменныя віду\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nФактычна, яна разгортвае ў пэўнай ступені ўсё ў двайных фігурных дужках.",
+       "expand_templates_title": "Загаловак старонкі, для {{FULLPAGENAME}} і г.д.:",
        "expand_templates_input": "Уваходны тэкст:",
        "expand_templates_output": "Вынік",
        "expand_templates_xml_output": "Выніковы XML",
        "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 ('''выключана''')"
 }
index d279705..24333f0 100644 (file)
@@ -20,7 +20,9 @@
                        "Vladimir Penov",
                        "Петър Петров",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Gazimagomedov",
+                       "StanProg"
                ]
        },
        "tog-underline": "Подчертаване на препратките:",
@@ -37,6 +39,7 @@
        "tog-watchdefault": "Добавяне на страниците, които редактирам, в списъка ми за наблюдение",
        "tog-watchmoves": "Добавяне на преместените от мен страници и файлове към списъка ми за наблюдение",
        "tog-watchdeletion": "Добавяне на изтритите от мен страници и файлове към списъка ми за наблюдение",
+       "tog-watchrollback": "Добавяне на страници, в които съм {{GENDER:$1|извършвал|извършвала}} отмяна на редакции в списъка ми за наблюдениe",
        "tog-minordefault": "Отбелязване на всички промени като малки по подразбиране",
        "tog-previewontop": "Показване на предварителния преглед преди текстовата кутия",
        "tog-previewonfirst": "Показване на предварителен преглед при първа редакция",
        "permalink": "Постоянна препратка",
        "print": "Печат",
        "view": "Преглед",
+       "view-foreign": "Преглед на $1",
        "edit": "Редактиране",
        "edit-local": "Редактиране на локалното описание",
        "create": "Създаване",
        "talkpagelinktext": "Беседа",
        "specialpage": "Специална страница",
        "personaltools": "Лични инструменти",
-       "postcomment": "Нов раздел",
        "articlepage": "Преглед на страница",
        "talk": "Беседа",
        "views": "Прегледи",
        "jumptonavigation": "навигация",
        "jumptosearch": "търсене",
        "view-pool-error": "Съжаляваме, но сървърите в момента са претоварени.\nТвърде много потребители се опитват да отворят тази страница.\nМоля, изчакайте малко преди отново да пробвате да отворите страницата.\n\n$1",
+       "generic-pool-error": "Съжаляваме, но сървърите в момента са претоварени.\nТвърде много потребители се опитват да отворят тази страница.\nМоля, изчакайте малко преди отново да пробвате да отворите страницата.",
        "pool-timeout": "Изтичане на времето за заключване на страницата",
        "pool-queuefull": "Опашката за заявки е пълна",
        "pool-errorunknown": "Непозната грешка",
        "hidetoc": "скриване",
        "collapsible-collapse": "Свиване",
        "collapsible-expand": "Разгръщане",
+       "confirmable-confirm": "{{GENDER:$1|Сигурен|Сигурна}} ли сте?",
+       "confirmable-yes": "Да",
+       "confirmable-no": "Не",
        "thisisdeleted": "Преглед или възстановяване на $1?",
        "viewdeleted": "Преглед на $1?",
        "restorelink": "{{PLURAL:$1|една изтрита редакция|$1 изтрити редакции}}",
        "badarticleerror": "Действието не може да се изпълни върху страницата.",
        "cannotdelete": "Указаната страница или файл \"$1\" не можа да бъде изтрит(а). Възможно е вече да е бил(а) изтрит(а) от някой друг.",
        "cannotdelete-title": "Страницата „$1“ не може да бъде изтрита",
+       "delete-hook-aborted": "Изтриването беше прекъснато от кука.\nНе беше посочена причина за това.",
        "no-null-revision": "Не може да бъде създадена празна версия на страницата „$1“",
        "badtitle": "Невалидно заглавие",
        "badtitletext": "Желаното заглавие на страница е невалидно, празно или неправилна препратка към друго уики. Възможно е да съдържа знаци, които не са позволени в заглавия.",
        "ns-specialprotected": "Специалните страници не могат да бъдат редактирани.",
        "titleprotected": "Тази страница е била защитена срещу създаване от [[User:$1|$1]].\nПосочената причина е ''$2''.",
        "filereadonlyerror": "Файлът „$1“ не може да бъде променен, тъй като файловото хранилище „$2“ е в режим само за четене.\n\nАдминистраторът, който го е заключил, е посочил следната причина: „$3“.",
-       "exception-nologin-text": "За досъп до желаната страница или действие уикито изисква [[Special:Userlogin|влизане в системата]].",
+       "invalidtitle-knownnamespace": "Невалидно заглавие с именно пространство $2\" и текст \"$3\"",
+       "invalidtitle-unknownnamespace": "Невалидно заглавие с неразпознато именно пространство номер $1 и текст „$2“",
+       "exception-nologin": "Не сте влезли",
+       "exception-nologin-text": "За достъп до избраното действие или страница е необходимо влизане в системата.",
        "exception-nologin-text-manual": "За достъп до избраното действие или страница е необходимо $1 в системата.",
        "virus-badscanner": "Лоша конфигурация: непознат скенер за вируси: ''$1''",
        "virus-scanfailed": "сканирането не сполучи (код $1)",
        "externaldberror": "Или е станала грешка в базата от данни при външното удостоверяване, или не ви е позволено да обновявате външната си сметка.",
        "login": "Влизане",
        "nav-login-createaccount": "Регистриране или влизане",
-       "loginprompt": "За влизане в {{SITENAME}} е необходимо да въведете потребителското си име и парола и да натиснете бутона '''Влизане''', като, за да бъде това успешно, бисквитките (cookies) трябва да са разрешени в браузъра ви.\n\nАко все още не сте се регистрирали (нямате открита сметка), лесно можете да сторите това, като последвате препратката '''Създаване на сметка'''.",
        "userlogin": "Влизане / създаване на сметка",
        "userloginnocreate": "Влизане",
        "logout": "Излизане",
        "userlogin-resetlink": "Забравени данни за влизане в системата?",
        "userlogin-resetpassword-link": "Забравена парола?",
        "userlogin-helplink2": "Помощ за влизане",
-       "userlogin-loggedin": "Вече сте влезли в системата като {{GENDER:$1|$1}}.\nЧрез формуляра по-долу можете да влезете като друг потребител.",
-       "userlogin-createanother": "Създаване на друга сметка",
        "createacct-emailrequired": "Адрес за електронна поща",
        "createacct-emailoptional": "Адрес за електронна поща (незадължително)",
        "createacct-email-ph": "Въведете Вашия адрес за електронна поща",
        "pt-userlogout": "Излизане",
        "php-mail-error-unknown": "Неизвестна грешка в mail() функцията на PHP",
        "user-mail-no-addy": "Опитвате се да изпратите е-писмо без да е посочен адрес за електронна поща.",
+       "user-mail-no-body": "Опитвате се да изпратите е-писмо с празно или изключително кратко съдържание.",
        "changepassword": "Смяна на парола",
        "resetpass_announce": "За да се завърши процеса на влизане, необходимо е да се избере нова парола.",
        "resetpass_text": "<!-- Тук добавете текст -->",
        "retypenew": "Нова парола повторно:",
        "resetpass_submit": "Избиране на парола и влизане",
        "changepassword-success": "Паролата ви беше променена успешно!",
+       "changepassword-throttled": "Направили сте твърде много опити да въведете паролата за тази сметка.\nНеобходимо е да изчакате $1 преди да опитате отново.",
        "resetpass_forbidden": "Не е разрешена смяна на паролата",
        "resetpass-no-info": "За да достъпвате тази страница директно, необходимо е да влезете в системата.",
        "resetpass-submit-loggedin": "Промяна на паролата",
        "resetpass-submit-cancel": "Отказ",
        "resetpass-wrong-oldpass": "Невалидна временна или текуща парола.\nВъзможно е вече успешно да сте сменили паролата си или да сте поискали нова временна парола.",
+       "resetpass-recycled": "Моля, променете паролата си с такава, различна от текущата.",
        "resetpass-temp-password": "Временна парола:",
        "resetpass-abort-generic": "Промяната на паролата беше прекъсната от използвано разширение.",
        "resetpass-expired": "Срокът на валидност на паролата е изтекъл. Изберете нова парола за влизане.",
        "resettokens-tokens": "Маркери:",
        "resettokens-token-label": "$1 (текуща стойност: $2)",
        "resettokens-watchlist-token": "Маркер за уеб хранилка (Atom/RSS) на [[Special: Watchlist|промени на страници от списъка Ви за наблюдение]]",
+       "resettokens-done": "Маркерите са изчистени.",
        "resettokens-resetbutton": "Изчистване на избраните маркери",
        "bold_sample": "Получер текст",
        "bold_tip": "Получер (удебелен) текст",
        "recreate-moveddeleted-warn": "'''Внимание: Създавате страница, която по-рано вече е била изтрита.'''\n\nОбмислете добре дали е уместно повторното създаване на страницата.\nЗа ваша информация по-долу е посочена причината за предишното изтриване на страницата:",
        "moveddeleted-notice": "Тази страница е била изтрита.\nЗа справка, по-долу са включени извадки от дневниците на изтриванията и преместванията.",
        "log-fulllog": "Преглеждане на пълния дневник",
-       "edit-hook-aborted": "Редакцията беше прекъсната от кука. Не беше посочена причина за това.",
+       "edit-hook-aborted": "Редакцията беше прекъсната от кука.\nНе беше посочена причина за това.",
        "edit-gone-missing": "Страницата не можа да се обнови.\nВероятно междувременно е била изтрита.",
        "edit-conflict": "Редакционен конфликт.",
        "edit-no-change": "Редакцията ви беше пренебрегната, защото не съдържа промени по текста.",
+       "postedit-confirmation-created": "Страницата е създадена.",
+       "postedit-confirmation-restored": "Страницата е възстановена.",
        "postedit-confirmation-saved": "Редакцията ви беше съхранена",
        "edit-already-exists": "Не можа да се създаде нова страница.\nТакава вече съществува.",
        "defaultmessagetext": "Текст на съобщението по подразбиране",
        "invalid-content-data": "Невалидни данни за съдържание",
        "content-not-allowed-here": "\nНа страницата [[$2]] не е позволено използването на $1",
        "editwarning-warning": "Ако излезете от тази страница, може да загубите всички незапазени промени, които сте направили. \nАко сте влезли в системата, можете да изключите това предупреждение през меню \"Редактиране\" във вашите лични настройки.",
+       "editpage-notsupportedcontentformat-title": "Форматът на съдържанието не се поддържа",
        "content-model-wikitext": "уикитекст",
        "content-model-text": "обикновен текст",
        "content-model-javascript": "Джаваскрипт",
        "parser-template-recursion-depth-warning": "Надвишен лимит на дълбочината при шаблонна рекурсия ($1)",
        "language-converter-depth-warning": "Надвишени са възможностите за автоматичен превод ($1)",
        "node-count-exceeded-category": "Страници, където е превишен възел-граф",
-       "node-count-exceeded-warning": "Страница превишава възел-брой",
+       "node-count-exceeded-category-desc": "Страницата превишава максималния възел-граф.",
+       "node-count-exceeded-warning": "Страница превиши броя на възлите",
        "undo-success": "Редакцията може да бъде върната. Прегледайте долното сравнение и се уверете, че наистина искате да го направите. След това съхранете страницата, за да извършите връщането.",
        "undo-failure": "Редакцията не може да бъде върната поради конфликтни междинни редакции.",
        "undo-norev": "Редакцията не може да бъде върната тъй като не съществува или е била изтрита.",
        "currentrev": "Текуща версия",
        "currentrev-asof": "Текуща версия към $1",
        "revisionasof": "Версия от $1",
-       "revision-info": "Версия от $1 на $2",
+       "revision-info": "Версия от $1 на {{GENDER:$6|$2}}$7",
        "previousrevision": "←По-стара версия",
        "nextrevision": "По-нова версия→",
        "currentrevisionlink": "преглед на текущата версия",
        "revdelete-confirm": "Необходимо е да потвърдите, че велаете да извършите действието, разбирате последствията и го правите според [[{{MediaWiki:Policy-url}}|политиката]].",
        "revdelete-suppress-text": "Премахването трябва да се използва '''само''' при следните случаи:\n*Неподходяща или неприемлива лична информация\n*: ''домашни адреси и телефонни номера, номера за социално осигуряване и др.''",
        "revdelete-legend": "Задаване на ограничения:",
-       "revdelete-hide-text": "СкÑ\80иване Ð½Ð° Ñ\82екÑ\81Ñ\82а на версията",
+       "revdelete-hide-text": "ТекÑ\81Ñ\82 на версията",
        "revdelete-hide-image": "Скриване на файловото съдържание",
        "revdelete-hide-name": "Скриване на действието и целта",
        "revdelete-hide-comment": "Скриване на резюмето",
        "searchprofile-advanced-tooltip": "Търсене в избрани именни пространства",
        "search-result-size": "$1 ({{PLURAL:$2|една дума|$2 думи}})",
        "search-result-category-size": "{{PLURAL:$1|1 член|$1 члена}} ({{PLURAL:$2|1 подкатегория|$2 подкатегории}}, {{PLURAL:$3|1 файл|$3 файла}})",
-       "search-result-score": "Релевантност: $1%",
        "search-redirect": "(пренасочване $1)",
        "search-section": "(раздел $1)",
        "search-suggest": "Вероятно имахте предвид: $1",
        "search-interwiki-caption": "Сродни проекти",
-       "search-interwiki-default": "$1 резултата:",
+       "search-interwiki-default": "Резултати от $1:",
        "search-interwiki-more": "(още)",
        "search-relatedarticle": "Свързани",
        "searchrelated": "свързани",
        "searchall": "всички",
        "showingresults": "Показване на до {{PLURAL:$1|'''1''' резултат|'''$1''' резултата}}, като се започва от номер '''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|Резултат '''$1''' от '''$3'''|Резултати '''$1 - $2''' от '''$3'''}} за '''$4'''",
        "search-nonefound": "Няма резултати, които да отговарят на заявката.",
        "powersearch-legend": "Разширено търсене",
        "powersearch-ns": "Търсене в именни пространства:",
        "preferences": "Настройки",
        "mypreferences": "Настройки",
        "prefs-edits": "Брой редакции:",
+       "prefsnologintext2": "За да промените настройките си е необходимо да влезете в систеата.",
        "prefs-skin": "Облик",
        "skin-preview": "предварителен преглед",
        "datedefault": "Без предпочитание",
        "right-move": "преместване на страници",
        "right-move-subpages": "преместване на страници и техните подстраници",
        "right-move-rootuserpages": "Преместване на основни потребителски страници",
+       "right-move-categorypages": "Преместване на категорийни страници",
        "right-movefile": "Преместване на файлове",
        "right-suppressredirect": "без създаване на пренасочване от старото име при преместване на страница",
        "right-upload": "качване на файлове",
        "right-browsearchive": "търсене на изтрити страници",
        "right-undelete": "възстановяване на страници",
        "right-suppressrevision": "преглед и възстановяване на версии, скрити от администраторите",
+       "right-viewsuppressed": "Преглеждане на версии, скрити от който и да е потребител",
        "right-suppressionlog": "преглеждане на тайните дневници",
        "right-block": "спиране на достъпа до редактиране",
        "right-blockemail": "блокиране на потребители да изпращат писма по е-поща",
        "right-editusercssjs": "редактиране на CSS и JS файловете на други потребители",
        "right-editusercss": "редактиране на CSS файловете на други потребители",
        "right-edituserjs": "редактиране на JS файловете на други потребители",
+       "right-editmyusercss": "Редактиране на собствените потребителски CSS файлове",
+       "right-editmyuserjs": "Редактиране на собствените потребителски JavaScript файлове",
+       "right-viewmywatchlist": "Преглеждане на собствения списък за наблюдение",
+       "right-editmywatchlist": "Редактиране на собствения списък за наблюдение. Забележете, че някои действия все пак ще добавят страници, дори и без текущото право.",
+       "right-viewmyprivateinfo": "Преглеждане на собствените лични данни (например: адрес на електронната поща, истинско име)",
+       "right-editmyprivateinfo": "Редактиране на собствените лични данни (например: адрес на електронната поща, истинско име)",
+       "right-editmyoptions": "Редактиране на собствените настройки",
        "right-rollback": "Бърза отмяна на промените, направени от последния потребител, редактирал дадена страница",
        "right-markbotedits": "отбелязване на възвърнатите редакции като редакции на ботове",
        "right-noratelimit": "Пренебрегване на всякакви ограничения",
        "action-createpage": "създаване на страници",
        "action-createtalk": "създаване на дискусионни страници",
        "action-createaccount": "създаване на тази потребителска сметка",
+       "action-history": "преглед на историята на тази страница",
        "action-minoredit": "отбелязване на редакцията като малка",
        "action-move": "преместване на страницата",
        "action-move-subpages": "преместване на страницата и нейните подстраници",
        "action-move-rootuserpages": "преместване на основни потребителски страници",
+       "action-move-categorypages": "преместване на категорийни страници",
        "action-movefile": "преместване на този файл",
        "action-upload": "качване на файла",
        "action-reupload": "съхранение на файл върху вече съществуващ",
        "action-suppressionlog": "преглеждане на този поверителен дневник",
        "action-block": "блокиране на редакциите на този потребител",
        "action-protect": "променяне на нивото на защита на тази страница",
-       "action-import": "внасяне на тази страница от друго уики",
-       "action-importupload": "внасяне на тази страница от качен файл",
+       "action-rollback": "бърза отмяна на промените, направени от последния потребител, редактирал дадена страница",
+       "action-import": "внасяне на страници от други уикита",
+       "action-importupload": "внасяне на страници от качен файл",
        "action-patrol": "отбелязване на чуждите редакции като проверени",
        "action-autopatrol": "отбелязване на собствените редакции като автоматично патрулирани",
        "action-unwatchedpages": "преглеждане на списъка с ненаблюдавани страници",
        "action-userrights-interwiki": "редактиране на потребителските права на потребители от други уикита",
        "action-siteadmin": "заключване и отключване на базата от данни",
        "action-sendemail": "изпращане на е-писма",
+       "action-editmywatchlist": "редактиране на списъка ви за наблюдение",
+       "action-viewmywatchlist": "преглед на списъка ви за наблюдение",
+       "action-viewmyprivateinfo": "преглеждане на личните данни",
+       "action-editmyprivateinfo": "редактиране на личната си информация",
        "nchanges": "$1 {{PLURAL:$1|промяна|промени}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|от последното посещение}}",
        "enhancedrc-history": "история",
        "recentchanges": "Последни промени",
        "recentchanges-legend": "Настройки на списъка с последни промени",
        "recentchanges-summary": "Проследяване на последните промени в {{SITENAME}}.\n\nЛегенда: '''тек''' = разлика на текущата версия,\n'''ист''' = история на версиите",
+       "recentchanges-noresult": "Не бяха намерени промени за дадения период, които отговарят на критериите.",
        "recentchanges-feed-description": "Проследяване на последните промени в {{SITENAME}}.",
        "recentchanges-label-newpage": "Нова страница",
        "recentchanges-label-minor": "Това е малка промяна",
        "uploadwarning": "Предупреждение при качване",
        "uploadwarning-text": "Необходимо е да промените описанието на файла по-долу и да опитате отново.",
        "savefile": "Съхраняване на файл",
-       "uploadedimage": "качи „[[$1]]“",
-       "overwroteimage": "качи нова версия на „[[$1]]“",
        "uploaddisabled": "Качванията са забранени.",
        "copyuploaddisabled": "Спряно е качването на файлове чрез URL.",
        "uploaddisabledtext": "Качването на файлове е забранено.",
        "license-nopreview": "(Не е наличен предварителен преглед)",
        "upload_source_url": " (правилен, публично достъпен интернет-адрес)",
        "upload_source_file": " (файл на вашия компютър)",
+       "listfiles-delete": "изтриване",
        "listfiles-summary": "Тази специална страница показва всички качени файлове.",
        "listfiles_search_for": "Търсене по име на файла:",
        "imgfile": "файл",
        "download": "сваляне",
        "unwatchedpages": "Ненаблюдавани страници",
        "listredirects": "Списък на пренасочванията",
+       "listduplicatedfiles": "Списък на повтарящи се файлове",
        "unusedtemplates": "Неизползвани шаблони",
        "unusedtemplatestext": "Тази страница съдържа списък на страниците в именно пространство {{ns:template}}, които не са включени в друга страница. Проверявайте за препратки към отделните шаблони преди да ги изтриете или предложите за изтриване.",
        "unusedtemplateswlh": "други препратки",
        "randompage": "Случайна страница",
        "randompage-nopages": "В {{PLURAL:$2|следното именно пространство|следните именни пространства}} няма страници: $1.",
-       "randomincategory": "СлÑ\83Ñ\87айна Ñ\81Ñ\82Ñ\80аниÑ\86а Ð² категорията",
+       "randomincategory": "СлÑ\83Ñ\87айна Ñ\81Ñ\82Ñ\80аниÑ\86а Ð¾Ñ\82 категорията",
        "randomincategory-invalidcategory": "„$1“ не е валидно име на категория.",
        "randomincategory-nopages": "В категория [[:Category:$1|$1]] няма страници.",
+       "randomincategory-category": "Категория:",
+       "randomincategory-legend": "Случайна страница от категорията",
        "randomredirect": "Случайно пренасочване",
        "randomredirect-nopages": "В именно пространство „$1“ няма пренасочвания.",
        "statistics": "Статистика",
        "statistics-users-active": "Активни потребители",
        "statistics-users-active-desc": "Потребители, направили редакция през {{PLURAL:$1|последния ден|последните $1 дни}}",
        "statistics-mostpopular": "Най-преглеждани страници",
+       "pageswithprop-prop": "Име на свойството:",
+       "pageswithprop-submit": "Отваряне",
        "doubleredirects": "Двойни пренасочвания",
        "doubleredirectstext": "Тази страница съдържа списък със страници, които пренасочват към друга пренасочваща страница.\nВсеки ред съдържа препратки към първото и второто пренасочване, както и целта на второто пренасочване, която обикновено е „истинската“ целева страница, към която първото пренасочване би трябвало да сочи.\n<del>Задрасканите</del> записи са коригирани.",
        "double-redirect-fixed-move": "Оправяне на двойно пренасочване след преместването на [[$1]] като [[$2]]",
        "protectedpages": "Защитени страници",
        "protectedpages-indef": "Само безсрочни защити",
        "protectedpages-cascade": "Само каскадни защити",
+       "protectedpages-noredirect": "Скриване на пренасочванията",
        "protectedpagesempty": "В момента няма защитени страници с тези параметри.",
+       "protectedpages-timestamp": "Дата и час",
        "protectedpages-page": "Страница",
+       "protectedpages-expiry": "Срок на изтичане",
+       "protectedpages-performer": "Защитаващ потребител",
+       "protectedpages-params": "Параметри на защита",
        "protectedpages-reason": "Причина",
+       "protectedpages-unknown-timestamp": "Неизвестни",
        "protectedpages-unknown-performer": "Неизвестен потребител",
        "protectedtitles": "Защитени заглавия",
        "protectedtitlesempty": "В момента няма заглавия, защитени с тези параметри.",
        "listusers": "Списък на потребителите",
        "listusers-editsonly": "Показване само на потребители с редакции",
        "listusers-creationsort": "Сортиране по дата на създаване",
+       "listusers-desc": "Сортиране в низходящ ред",
        "usereditcount": "$1 {{PLURAL:$1|редакция|редакции}}",
        "usercreated": "{{GENDER:$3|Създаден}} на $1 в $2",
        "newpages": "Нови страници",
        "allpagesbadtitle": "Зададеното име е невалидно. Възможно е да съдържа междуезикова или междупроектна представка или пък знаци, които не могат да се използват в заглавия.",
        "allpages-bad-ns": "В {{SITENAME}} не съществува именно пространство „$1“.",
        "allpages-hide-redirects": "Скриване на пренасочванията",
+       "cachedspecial-refresh-now": "Преглед на текущата.",
        "categories": "Категории",
        "categoriespagetext": "{{PLURAL:$1|Следната категория съдържа|Следните категории съдържат}} страници или медийни файлове.\n[[Special:UnusedCategories|Неизползваните категории]] не са показани тук.\nВижте също списъка с [[Special:WantedCategories|желани категории]].",
        "categoriesfrom": "Показване на категориите, като се започне от:",
        "listgrouprights-addgroup-self-all": "Може да добавя всички групи към своята сметка",
        "listgrouprights-removegroup-self-all": "Може да премахва всички групи от собствената сметка",
        "listgrouprights-namespaceprotection-namespace": "Именно пространство",
+       "trackingcategories": "Категории за проследяване",
+       "trackingcategories-summary": "Тази страница съдържа списък на категории за проследяване, които се попълват автоматично от софтуера на МедияУики. Имената им могат да се променят чрез съответните системни съобщения в именното пространство {{ns:8}}.",
+       "trackingcategories-msg": "Категория за проследяване",
+       "trackingcategories-name": "Име на съобщението",
+       "trackingcategories-desc": "Критерий за включване на категория",
+       "trackingcategories-nodesc": "Няма налично описание.",
+       "trackingcategories-disabled": "Категорията е деактивирана",
        "mailnologin": "Няма електронна поща",
        "mailnologintext": "Необходимо е да [[Special:UserLogin|влезете]] и да посочите валидна електронна поща в [[Special:Preferences|настройките]] си, за да може да пращате писма на други потребители.",
        "emailuser": "Писмо до потребителя",
+       "emailuser-title-target": "Изпращане на е-писмо на този {{GENDER:$1|потребител}}",
+       "emailuser-title-notarget": "Изпращане на е-писмо на потребител",
        "emailpage": "Пращане писмо на потребител",
        "emailpagetext": "Можете да използвате формуляра по-долу, за да изпратите електронно писмо на {{GENDER:$1|този потребител}}.\nАдресът, който се въвели в [[Special:Preferences|настройките си]], ще се появи в полето „От“ на писмото, така че получателят ще е в състояние да ви отговори директно.",
        "defemailsubject": "Писмо от потребител $1 в {{SITENAME}}",
        "watchnologin": "Не сте влезли",
        "addwatch": "Добавяне към списъка за наблюдение",
        "addedwatchtext": "Страницата „'''[[:$1]]'''“ беше добавена към [[Special:Watchlist|списъка ви за наблюдение]].\nНейните бъдещи промени, както и на съответната й дискусионна страница, ще се описват там.",
+       "addedwatchtext-short": "Страницата „$1“ беше добавена към списъка Ви за наблюдение.",
        "removewatch": "Премахване от списъка за наблюдение",
        "removedwatchtext": "Страницата „[[:$1]]“ беше премахната от [[Special:Watchlist|списъка ви за наблюдение]].",
+       "removedwatchtext-short": "Страницата „$1“ беше премахната от списъка Ви за наблюдение.",
        "watch": "Наблюдение",
        "watchthispage": "Наблюдаване на страницата",
        "unwatch": "Спиране на наблюдение",
        "watchlist-details": "{{PLURAL:$1|Една наблюдавана страница|$1 наблюдавани страници}} от списъка ви за наблюдение (без беседи).",
        "wlheader-enotif": "Известяването по е-поща е включено.",
        "wlheader-showupdated": "Страниците, които са били променени след последния път, когато сте ги посетили, са показани в '''получер'''.",
+       "wlnote": "{{PLURAL:$1|Показана е последната промяна|Показани са последните '''$1''' промени}} през {{PLURAL:$2|последния час|последните '''$2''' часа}}.",
        "wlshowlast": "Показване на последните $1 часа $2 дни $3",
        "watchlist-options": "Опции на списъка за наблюдение",
        "watching": "Наблюдение…",
        "contributions-title": "Потребителски приноси за $1",
        "mycontris": "Приноси",
        "contribsub2": "За {{GENDER:$3|$1}} ($2)",
+       "contributions-userdoesnotexist": "Няма регистрирана потребителска сметка за „$1“.",
        "nocontribs": "Не са намерени промени, отговарящи на критерия.",
        "uctop": "(текуща)",
        "month": "Месец:",
        "ipb-unblock-addr": "Отблокиране на $1",
        "ipb-unblock": "Отблокиране на потребителско име IP-адрес",
        "ipb-blocklist": "Преглед на текущите блокирания",
-       "ipb-blocklist-contribs": "Приноси на $1",
+       "ipb-blocklist-contribs": "Приноси на {{GENDER:$1|$1}}",
        "unblockip": "Отблокиране на потребител",
        "unblockiptext": "Използвайте долния формуляр, за да възстановите правото на писане на по-рано блокиран IP-адрес или потребител.",
        "ipusubmit": "Сваляне на блокирането",
        "blocklist-tempblocks": "Скриване на срочните блокирания",
        "blocklist-addressblocks": "Скриване на отделни блокирани IP адреси",
        "blocklist-rangeblocks": "Скриване на блокиранията по IP диапазон",
+       "blocklist-timestamp": "Дата и час",
        "blocklist-target": "Цел",
-       "blocklist-expiry": "Срок на изтичане:",
+       "blocklist-expiry": "Срок на изтичане",
        "blocklist-by": "Блокиращ администратор",
        "blocklist-params": "Параметри на блокирането",
        "blocklist-reason": "Причина",
        "unblocklink": "отблокиране",
        "change-blocklink": "промяна на параметрите на блокирането",
        "contribslink": "приноси",
+       "emaillink": "изпращане на е-писмо",
        "autoblocker": "Бяхте блокиран автоматично, тъй като неотдавна IP-адресът ви е бил ползван от блокирания в момента потребител [[User:$1|$1]]. Причината за неговото блокиране е: „$2“.",
        "blocklogpage": "Дневник на блокиранията",
        "blocklog-showlog": "Потребителят е бил блокиран в миналото.\nЗа справка по-долу е дадено извлечение от дневника на блокиранията:",
        "import": "Внасяне на страници",
        "importinterwiki": "Внасяне чрез Трансуики",
        "import-interwiki-text": "Изберете уики и име на страницата.\nДатите на редакциите и имената на авторите ще бъдат запазени.\nВсички операции при внасянето от друго уики се записват в [[Special:Log/import|дневника на внасянията]].",
-       "import-interwiki-source": "Изходно уики/страница:",
        "import-interwiki-history": "Копиране на всички версии на страницата",
        "import-interwiki-templates": "Включване на всички шаблони",
        "import-interwiki-submit": "Внасяне",
        "import-error-create": "Страницата „$1“ не беше внесена, тъй като нямате права да я създадете.",
        "import-error-interwiki": "Страницата „$1“ не беше внесена, тъй като името ѝ е запазено за външно свързване (междууики).",
        "import-error-special": "Страницата „$1“ не беше внесена, тъй като принадлежи към специално именно пространство, което не позволява страници.",
-       "import-error-invalid": "Страницата „$1“ не беше внесена, тъй като името ѝ е невалидно.",
+       "import-error-invalid": "Страницата „$1“ не беше внесена, тъй като името към което трябваше да бъде внесена е невалидно на това уики.",
        "import-rootpage-invalid": "Посочената основна страница е с невалидно заглавие.",
        "import-rootpage-nosubpage": "Именното пространство „$1“ на основната страница не позволява създаването на подстраници.",
        "importlogpage": "Дневник на внасянията",
        "importlogpagetext": "Административни внасяния на страници с редакционна история от други уикита.",
        "import-logentry-upload": "[[$1]] беше внесена от файл",
-       "import-logentry-upload-detail": "{{PLURAL:$1|една версия|$1 версии}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|версия беше внесена|версии бяха внесени}}",
        "import-logentry-interwiki": "$1 беше внесена от друго уики",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|една версия|$1 версии}} на $2 бяха внесени",
+       "javascripttest": "Тестване на JavaScript",
        "javascripttest-pagetext-noframework": "Тази страница е запазена за изпълнение на Джаваскрипт тестове.",
        "javascripttest-pagetext-skins": "Избор на облик за тестванията:",
        "javascripttest-qunit-intro": "Вижте [$1 тестовата документация] на mediawiki.org.",
        "spam_reverting": "Връщане на последната версия, несъдържаща препратки към $1",
        "spam_blanking": "Всички версии, съдържащи препратки към $1, изчистване",
        "spam_deleting": "Всички версии съдържат препратки към $1, изтриване",
-       "simpleantispam-label": "Проверка за спам.\nНеобходимо е да '''НЕ''' попълвате това поле!",
+       "simpleantispam-label": "Проверка за спам.\nНеобходимо е да <strong>НЕ</strong> попълвате това поле!",
        "pageinfo-title": "Информация за \"$1\"",
        "pageinfo-not-current": "За съжаление тази информация не може да бъде предоставена за стари версии.",
        "pageinfo-header-basic": "Основна информация",
        "pageinfo-length": "Дължина на страницата (в байтове)",
        "pageinfo-article-id": "Номер на страницата",
        "pageinfo-language": "Език на съдържанието на страницата",
-       "pageinfo-robot-policy": "СÑ\82аÑ\82Ñ\83Ñ\82 Ð½Ð° Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а Ð² Ñ\82Ñ\8aÑ\80Ñ\81аÑ\87киÑ\82е",
-       "pageinfo-robot-index": "Ð\98ндекÑ\81иÑ\80Ñ\83ема",
-       "pageinfo-robot-noindex": "Ð\9dеиндекÑ\81иÑ\80Ñ\83ема",
+       "pageinfo-robot-policy": "Ð\98ндекÑ\81иÑ\80ане Ð¾Ñ\82 Ñ\80обоÑ\82и",
+       "pageinfo-robot-index": "Ð\9fозволено",
+       "pageinfo-robot-noindex": "Ð\9dепозволено",
        "pageinfo-views": "Брой прегледи",
        "pageinfo-watchers": "Брой наблюдаващи страницата",
        "pageinfo-few-watchers": "Под $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",
+       "thursday-at": "Четвъртък в $1",
+       "friday-at": "Петък в $1",
+       "saturday-at": "Събота в $1",
+       "sunday-at": "Неделя в $1",
+       "yesterday-at": "Вчера в $1",
        "bad_image_list": "Спазва се следният формат:\n\nОтчитат се само записите в списъчен вид (редове, започващи със *). Първата препратка в реда трябва да сочи към неприемлив файл. Всички последващи препратки на същия ред се считат за изключения, т.е. страници, в които този файл може да се визуализира.",
        "metadata": "Метаданни",
        "metadata-help": "Файлът съдържа допълнителни данни, обикновено добавяни от цифровите апарати или скенери. Ако файлът е редактиран след създаването си, то някои параметри може да не съответстват на текущото изображение.",
        "exif-specialinstructions": "Специални инструкции",
        "exif-headline": "Заглавие",
        "exif-source": "Източник",
+       "exif-urgency": "Спешност",
        "exif-contact": "Информация за контакти",
        "exif-languagecode": "Език",
        "exif-iimversion": "IIM версия",
        "exif-originalimagewidth": "Ширина на изображението преди намаляването",
        "exif-compression-1": "Некомпресиран",
        "exif-copyrighted-true": "С авторски права",
-       "exif-copyrighted-false": "Ð\9eбÑ\89еÑ\81Ñ\82вено Ð´Ð¾Ñ\81Ñ\82оÑ\8fние",
+       "exif-copyrighted-false": "СÑ\82аÑ\82Ñ\83Ñ\82а Ð½Ð° Ð°Ð²Ñ\82оÑ\80Ñ\81киÑ\82е Ð¿Ñ\80ава Ð½Ðµ Ðµ Ñ\83казан",
        "exif-unknowndate": "Неизвестна дата",
        "exif-orientation-1": "Нормално",
        "exif-orientation-2": "Отражение по хоризонталата",
        "exif-objectcycle-p": "Само вечер",
        "exif-gpsdirection-t": "истинска",
        "exif-gpsdirection-m": "магнитна",
+       "exif-dc-contributor": "Сътрудници",
        "exif-dc-date": "Дата(и)",
        "exif-dc-rights": "Права",
        "exif-isospeedratings-overflow": "По-голяма от 65535",
        "imgmultigo": "Отваряне",
        "imgmultigoto": "Отиване на страница $1",
        "img-lang-default": "(език по подразбиране)",
+       "img-lang-go": "Отваряне",
        "ascending_abbrev": "възх",
        "descending_abbrev": "низх",
        "table_pager_next": "Следваща страница",
        "watchlistedit-raw-done": "Списъкът ви за наблюдение беше обновен.",
        "watchlistedit-raw-added": "{{PLURAL:$1|1 страница беше добавена|$1 страници бяха добавени}}:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|Една страница беше премахната|$1 страници бяха премахнати}}:",
+       "watchlistedit-clear-legend": "Изчистване на списъка за наблюдение",
+       "watchlistedit-clear-submit": "Изчистване на списъка за наблюдение (Необратимо!)",
        "watchlisttools-clear": "Изчистване на списъка за наблюдение",
        "watchlisttools-view": "Преглед на списъка за наблюдение",
        "watchlisttools-edit": "Преглед и редактиране на списъка за наблюдение",
        "duplicate-defaultsort": "Внимание: Ключът за сортиране по подразбиране „$2“ отменя по-ранния ключ „$1“.",
        "version": "Версия",
        "version-extensions": "Инсталирани разширения",
+       "version-skins": "Инсталирани облици",
        "version-specialpages": "Специални страници",
        "version-parserhooks": "Куки в парсера",
        "version-variables": "Променливи",
        "version-antispam": "Предотвратяване на спам",
-       "version-skins": "Облици",
        "version-other": "Други",
        "version-mediahandlers": "Обработчици на медия",
        "version-hooks": "Куки",
        "version-hook-name": "Име на куката",
        "version-hook-subscribedby": "Ползвана от",
        "version-version": "(Версия $1)",
+       "version-no-ext-name": "[без име]",
        "version-license": "Лиценз на МедияУики",
        "version-ext-license": "Лиценз",
        "version-ext-colheader-name": "Разширение",
+       "version-skin-colheader-name": "Облик",
        "version-ext-colheader-version": "Версия",
        "version-ext-colheader-license": "Лиценз",
        "version-ext-colheader-description": "Описание",
        "version-entrypoints": "Адреси на входни точки",
        "version-entrypoints-header-entrypoint": "Входна точка",
        "version-entrypoints-header-url": "Адрес",
+       "redirect-submit": "Отваряне",
        "redirect-user": "Потребителски номер",
+       "redirect-page": "Номер на страницата",
+       "redirect-revision": "Версия на страницата",
        "redirect-file": "Име на файл",
+       "redirect-not-exists": "Стойността не е намерена",
        "fileduplicatesearch": "Търсене на повтарящи се файлове",
        "fileduplicatesearch-summary": "Търсене на повтарящи се файлове на база хеш стойности.",
        "fileduplicatesearch-legend": "Търсене на повтарящ се файл",
        "tags-tag": "Име на етикета",
        "tags-display-header": "Изглед в списъците с промени",
        "tags-description-header": "Пълно описание на значението",
+       "tags-active-header": "Активен?",
        "tags-hitcount-header": "Отбелязани промени",
        "tags-active-yes": "Да",
        "tags-active-no": "Не",
        "logentry-delete-delete": "$1 {{GENDER:$2|изтри}} страницата $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|възстанови}} страницата $3",
        "logentry-suppress-revision": "$1 тайно промени видимостта на {{PLURAL:$5|една версия|$5 версии}} на страницата $3: $4",
-       "logentry-suppress-revision-legacy": "$1 тайно промени видимостта на версиите на страница $3",
+       "logentry-suppress-revision-legacy": "$1 тайно {{GENDER:$2|промени}} видимостта на версиите на страница $3",
        "revdelete-content-hid": "скрито съдържание",
        "revdelete-summary-hid": "скрито резюме на редакцията",
        "revdelete-uname-hid": "скрито потребителско име",
        "logentry-move-move": "$1 {{GENDER:$2|премести}} страница „$3“ като „$4“",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|премести}} страницата „$3“ като „$4“ без пренасочване",
        "logentry-move-move_redir": "$1 {{GENDER:$2|премести}} страницата $3 като $4 (върху пренасочване)",
-       "logentry-move-move_redir-noredirect": "$1 премести върху пренасочване „$3“ като „$4“ без пренасочване",
+       "logentry-move-move_redir-noredirect": "$1 {GENDER:$2|премести}} върху пренасочване $3 като $4 без пренасочване",
        "logentry-patrol-patrol": "$1 {{GENDER:$2|отбеляза}} като патрулирана версия $4 на страницата „$3“",
        "logentry-patrol-patrol-auto": "$1 автоматично {{GENDER:$2|отбеляза}} като патрулирана версия $4 на страницата $3",
        "logentry-newusers-newusers": "Потребителската сметка $1 беше {{GENDER:$2|създадена}}",
        "logentry-newusers-autocreate": "Сметката $1 беше {{GENDER:$2|създадена}} автоматично",
        "logentry-rights-rights": "$1 {{GENDER:$2|промени}} потребителската група на $3 от $4 на $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|промени}} потребителската група на $3",
-       "logentry-rights-autopromote": "\n$1 е автоматично повишен от $4 до $5",
+       "logentry-rights-autopromote": "$1 е автоматично {{GENDER:$2|повишен|повишена}} от $4 до $5",
        "rightsnone": "(никакви)",
        "feedback-bugornote": "Ако сте готови подробно да опишете технически проблем, моля [$1 докладвайте го тук].\nВ противен случай, можете да използвате лесния формуляр по-долу. Коментарът ви ще бъде добавен към страницата \"[$3 $2]\", наред с вашето потребителско име.",
        "feedback-subject": "Тема:",
        "expand_templates_remove_nowiki": "Потискане на елементите <nowiki> в резултата",
        "expand_templates_generate_xml": "Показване на дървото от разбора на XML",
        "expand_templates_generate_rawhtml": "Показване на суров HTML",
-       "expand_templates_preview": "Преглед"
+       "expand_templates_preview": "Преглед",
+       "pagelang-name": "Страница",
+       "pagelang-language": "Език",
+       "pagelang-use-default": "Използване на езика по подразбиране",
+       "pagelang-select-lang": "Избиране на език",
+       "right-pagelang": "Промяна езика на страница",
+       "action-pagelang": "промяна езика на страницата",
+       "log-name-pagelang": "Дневник на езиковите промени",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (включено)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''изключено''')"
 }
index bd3d464..7781475 100644 (file)
        "talkpagelinktext": "बात-चीत",
        "specialpage": "ख़ाश पन्ना",
        "personaltools": "ब्यक्तिगत औजार",
-       "postcomment": "नया खण्ड",
        "articlepage": "सामग्री पन्ना देखीं",
        "talk": "बात-चीत",
        "views": "विचारसूची",
        "hidetoc": "छुपाईं",
        "collapsible-collapse": "सेकुड़ीं",
        "collapsible-expand": "फैलाईं",
+       "confirmable-yes": "जी",
+       "confirmable-no": "ना",
        "thisisdeleted": "देखीं या भंडार करीं $1?",
        "viewdeleted": "$1 देखब?",
        "restorelink": "देखीं {{PLURAL:$1|एगो हटावल गईल सम्पादन|$1 हटावल गईल कुल सम्पादन}}",
        "externaldberror": "या त प्रमाणिकरण डाटाबेस में भइल बा या फिर रउआ के आपन बाह्य खाता अपडेट करे के अनुमति नइखे।",
        "login": "खाता में प्रवेश",
        "nav-login-createaccount": "खाता प्रवेश / खाता बनाईं",
-       "loginprompt": "{{SITENAME}} में प्रवेश खातिर राउर कुकिज चालू होवे के चाहीं",
        "userlogin": "खाता प्रवेश / खाता बनाईं",
        "userloginnocreate": "खाता में प्रवेश",
        "logout": "खाता से बाहर",
        "resetpass-temp-password": "अस्थायी गुप्तशब्द:",
        "resetpass-abort-generic": "कउनो एक्सटेंशन द्वारा गुप्तशब्द में बदलाव रोक दिहल गईल बा।",
        "resetpass-expired": "राउर पासवर्ड की वैधता अवधि समाप्त हो चुकल बा। कृपया लॉग इन करे खातिर एगो नया पासवर्ड सेट करीं।",
+       "resetpass-expired-soft": "राउर गुप्तशब्द अमान्य हो चुकल बा इ के पुनः स्थापित करे के पड़ी। कृपया अभी एगो नया गुप्तशब्द चुनीं या \"{{int:resetpass-submit-cancel}}\" पर बाद में पुनः स्थापित कर सकत बानी।",
+       "resetpass-validity-soft": "राउर पासवर्ड मान्य नईखे: $1 \n\nकृपया अब एक नया पासवर्ड चुनीं, या उ के बाद में पुनर्स्थापित करे खातिर \"{{int:resetpass-submit-cancel}}\" पर क्लिक करीं।",
        "passwordreset": "गुप्तशब्द रिसेट करीं",
        "passwordreset-text-one": "आपन गुप्तशब्द के पुनर्स्थापित करे खातिर इ फॉर्म भरीं।",
-       "passwordreset-text-many": "{{PLURAL:$1|à¤\86पन à¤\97à¥\81पà¥\8dतशबà¥\8dद à¤ªà¥\81नरà¥\8dसà¥\8dथापित à¤\95रे खातिर निम्न में से कउनो एगो स्थान भरीं।}}",
+       "passwordreset-text-many": "{{PLURAL:$1|à¤\88मà¥\87ल à¤¦à¥\8dवारा à¤\85सà¥\8dथाà¤\88 à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤ªà¤¾à¤µे खातिर निम्न में से कउनो एगो स्थान भरीं।}}",
        "passwordreset-legend": "गुप्तशब्द रिसेट करीं",
        "passwordreset-disabled": "इ विकी पर पासवर्ड पुनर्स्थापन अक्षम बा।",
        "passwordreset-emaildisabled": "इ विकि पर ई-मेल सुविधा अक्षम कर दिहल गईल बा।",
        "changeemail-password": "राउर {{SITENAME}} गुप्तशब्द:",
        "changeemail-submit": "ई-मेल बदलीं",
        "changeemail-cancel": "रद्द करीं",
+       "changeemail-throttled": "रउआ हाले में कईयन बार खाता में प्रवेश करे के कोशिश कर चुकल बानी।\nकृपया $1 प्रतिक्षा करला के बाद फिर से प्रयास करब।",
+       "resettokens": "टोकन रीसेट करीं",
+       "resettokens-text": "जौन टोकन राउर खाता से सम्बद्ध कुछ विशिष्ट व्यक्तिगत जानकारी प्रदान करेला, आप उ के अहिजा रीसेट कर सकत बानी।\n\nयदि रउआ ई के गलती से केहू के दिखा देले बानी या फिर राउर खाता हैक हो गईल बा त रउआ ई के रीसेट कर देवे के चाहीं।",
        "bold_sample": "मोट पाठ्य",
        "bold_tip": "मोट पाठ्य",
        "italic_sample": "इटालिक पाठ्य",
        "searchprofile-everything-tooltip": "सभन सामग्री में खोजीं (वार्ता पन्ना सहित)",
        "searchprofile-advanced-tooltip": "विशेष नामस्थान में खोजीं",
        "search-result-size": "$1 ({{PLURAL:$2|1 शब्द|$2 शब्द}})",
-       "search-result-score": "प्रासंगिकता: $1%",
        "search-redirect": "(पुन: निर्देशण $1)",
        "search-section": "(खंड $1)",
        "search-suggest": "का राउर मतलब बा: $1",
index 1f18c13..328fcd2 100644 (file)
        "talkpagelinktext": "Pandir",
        "specialpage": "Tungkaran istimiwa",
        "personaltools": "Pakakas surang",
-       "postcomment": "Palih hanyar",
        "articlepage": "Tiringi isi tungkaran",
        "talk": "Pamandiran",
        "views": "Titiringan",
        "externaldberror": "Ada kasalahan apakah kacucukan basis data atawa Pian kada bulih mamutakhirakan akun luar.",
        "login": "Babuat",
        "nav-login-createaccount": "Babuat log / ulah akun",
-       "loginprompt": "Pian harus mangaktipakan ''cookies'' hagan kawa babuat log ka {{SITENAME}}.",
        "userlogin": "Babuat log / ulah akun",
        "userloginnocreate": "Babuat log",
        "logout": "Kaluar",
        "searchprofile-advanced-tooltip": "Panggagaian pada ragam ngaran kakamar",
        "search-result-size": "$1 ({{PLURAL:$2|1 ujar|$2 uujar}})",
        "search-result-category-size": "{{PLURAL:$1|1 angguta|$1 aangguta}} ({{PLURAL:$2|1 subtumbung|$2 subtutumbung}}, {{PLURAL:$3|1 barakas|$3 babarakas}})",
-       "search-result-score": "Kacucukan: $1%",
        "search-redirect": "(Paugahan $1)",
        "search-section": "(hagian $1)",
        "search-suggest": "Nginikah maksud Pian: $1",
        "uploadwarning": "Paringatan hunggah",
        "uploadwarning-text": "Muhun mangganti katarangan barakas di bawah wan cubai pulang.",
        "savefile": "Simpan barakas",
-       "uploadedimage": "mamuat \"[[$1]]\"",
-       "overwroteimage": "mahunggah sabuah pérsi hanyar matan \"[[$1]]\"",
        "uploaddisabled": "Pahunggahan dipajahakan.",
        "copyuploaddisabled": "Hunggah lawan URL pajah.",
        "uploaddisabledtext": "Hunggah barakas kada kawa.",
        "watchlist-details": "{{PLURAL:$1|$1 tungkaran|$1 tungkaran}} dalam daptar itihan Pian, kada mahitung tungkaran pamandiran.",
        "wlheader-enotif": "Suril pamadahan dipajahi.",
        "wlheader-showupdated": "Tutungkaran nang ba-ubah tumatan ilangan tauncit Pian ditampaiakan dalam '''hurup kandal'''",
+       "wlnote": "Di bawah naya adalah {{PLURAL:$1|paubahan|'''$1''' paubahan}} tauncit dalam '''$2''' jam tauncit, par $3, $4.",
        "wlshowlast": "Tampaiakan $1 jam $2 hari pahabisan $3",
        "watchlist-options": "Pilihan daptar itihan",
        "watching": "Maitihi...",
        "duplicate-defaultsort": "Paringatan: Sunduk pangurutan baku \"$2\" mangabaikan sunduk pangurutan baku \"$1\" sabalumnya.",
        "version": "Virsi",
        "version-extensions": "Ekstensi tapasang",
+       "version-skins": "Kukulimbit",
        "version-specialpages": "Tungkaran istimiwa",
        "version-parserhooks": "Kait parser",
        "version-variables": "Pariabal",
        "version-antispam": "Pancagahan spam",
-       "version-skins": "Kukulimbit",
        "version-other": "Lain-lain",
        "version-mediahandlers": "Pananganan madia",
        "version-hooks": "Kait",
index 434cf28..c33d82c 100644 (file)
@@ -38,6 +38,7 @@
        "tog-watchdefault": "আমার সম্পাদিত পাতা এবং ফাইলগুলো আমার নজরতালিকায় যোগ করা হোক",
        "tog-watchmoves": "আমার স্থানান্তরিত পাতা এবং ফাইলগুলো আমার নজরতালিকায় যোগ করা হোক",
        "tog-watchdeletion": "আমার অপসারিত পাতা এবং ফাইলগুলো আমার নজর তালিকায় যোগ করা হোক",
+       "tog-watchrollback": "আমার দ্বারা রোলব্যাক করা পাতা আমার নজরতালিকায় যোগ করা হোক",
        "tog-minordefault": "শুরুতেই সব সম্পাদনাকে অনুল্লেখ্য বলে চিহ্নিত করা হোক",
        "tog-previewontop": "সম্পাদনা বাক্সের আগে প্রাকদর্শন দেখানো হোক",
        "tog-previewonfirst": "প্রথম সম্পাদনার ক্ষেত্রে প্রাকদর্শন দেখানো হোক",
        "talkpagelinktext": "আলোচনা",
        "specialpage": "বিশেষ পাতা",
        "personaltools": "নিজস্ব সরঞ্জামসমূহ",
-       "postcomment": "নতুন অনুচ্ছেদ",
        "articlepage": "নিবন্ধ দেখুন",
        "talk": "আলোচনা",
        "views": "দৃষ্টিকোণ",
        "pool-timeout": "সময় উত্তির্ণ লক-এর জন্য অপেক্ষারত",
        "pool-queuefull": "পুলের লাইন পূর্ণ",
        "pool-errorunknown": "অজানা ত্রুটি",
+       "pool-servererror": "পুল কাউন্টার সার্ভিস নিষ্ক্রিয় ($1)।",
        "aboutsite": "{{SITENAME}} বৃত্তান্ত",
        "aboutpage": "Project:বৃত্তান্ত",
        "copyright": "বিষয়বস্তু $1-এর আওতায় প্রকাশিত যদি না অন্য কিছু নির্ধারিত থাকে।",
        "hidetoc": "আড়ালে রাখো",
        "collapsible-collapse": "সংকোচন",
        "collapsible-expand": "প্রসারণ",
+       "confirmable-confirm": "{{GENDER:$1|আপনি}} কি নিশ্চিত?",
+       "confirmable-yes": "হ্যাঁ",
+       "confirmable-no": "না",
        "thisisdeleted": "$1 দেখানো বা পুনঃসৃষ্টি করা হোক?",
        "viewdeleted": "$1 দেখানো হোক?",
        "restorelink": "{{PLURAL:$1|একটি মুছে ফেলা সম্পাদনা|$1টি মুছে ফেলা সম্পাদনা}}",
        "invalidtitle-knownnamespace": "অবৈধ শিরোনাম, যেখানে নামস্থান \"$2\" এবং লেখা হয়েছে \"$3\"",
        "invalidtitle-unknownnamespace": "অবৈধ শিরোনাম, যেখানে ব্যবহৃত হয়েছে অপরিচিত নামস্থান সংখ্যা $1 এবং লেখা হয়েছে \"$2\"",
        "exception-nologin": "লগইন করা হয়নি",
-       "exception-nologin-text": "এই কাজটি করার জন্য উইকিতে [[Special:Userlogin|লগইন]] করা প্রয়োজন।",
+       "exception-nologin-text": "এই কাজ করা বা পাতাটি দেখার জন্য অনুগ্রহ করে প্রবেশ করুন।",
        "exception-nologin-text-manual": "অনুগ্রহ করে এই পাতা দেখতে অথবা পরিবর্তন করতে $1 করুন।",
        "virus-badscanner": "ভুল কনফিগারেশন: অজ্ঞাত ভাইরাস স্কেনার: ''$1''",
        "virus-scanfailed": "স্ক্যান করা যাচ্ছে না (কোড $1)",
        "welcomecreation-msg": "আপনার অ্যাকাউন্ট তৈরী হয়েছে।\nআপনার [[Special:Preferences|{{SITENAME}} পছন্দসমূহ]]  পরিবর্তন করে নিতে ভুলবেন না।",
        "yourname": "ব্যবহারকারী নাম:",
        "userlogin-yourname": "ব্যবহারকারী নাম",
-       "userlogin-yourname-ph": "à¦\86পনার à¦¬à§\8dযবহাà¦\95ারà§\80 à¦¨à¦¾à¦® à¦ªà§\8dরবà§\87শ à¦\95রান",
+       "userlogin-yourname-ph": "à¦\86পনার à¦¬à§\8dযবহাà¦\95ারà§\80 à¦¨à¦¾à¦® à¦²à¦¿à¦\96à§\81ন",
        "createacct-another-username-ph": "আপনার ব্যবহাকারী নাম প্রবেশ করান",
-       "yourpassword": "শবà§\8dদà¦\9aাবি:",
-       "userlogin-yourpassword": "শবà§\8dদà¦\9aাবি (Password)",
-       "userlogin-yourpassword-ph": "à¦\86পনার à¦¶à¦¬à§\8dদà¦\9aাবি (পাসà¦\93য়ারà§\8dড) লিখুন",
-       "createacct-yourpassword-ph": "শবà§\8dদà¦\9aাবি à¦ªà§\8dরদান à¦\95রুন",
-       "yourpasswordagain": "শবà§\8dদà¦\9aাবিà¦\9fি (password) à¦\86বার à¦²à¦¿à¦\96à§\81ন",
-       "createacct-yourpasswordagain": "শবà§\8dদà¦\9aাবি নিশ্চিত করুন",
-       "createacct-yourpasswordagain-ph": "à¦\86বারà¦\93 à¦¶à¦¬à§\8dদà¦\9aাবি à¦ªà§\8dরদান à¦\95রুন",
-       "remembermypassword": "à¦\8fà¦\95াধিà¦\95 à¦¸à§\87শনà§\87র à¦\9cনà§\8dয à¦¶à¦¬à§\8dদà¦\9aাবি à¦®à¦¨à§\87 à¦°à¦¾à¦\96া à¦¹à§\8bà¦\95 (সরà§\8dবà§\8bà¦\9aà§\8dà¦\9a $1 {{PLURAL:$1|দিনà§\87র|দিনের}} জন্য)",
+       "yourpassword": "পাসà¦\93য়ারà§\8dড:",
+       "userlogin-yourpassword": "পাসà¦\93য়ারà§\8dড",
+       "userlogin-yourpassword-ph": "à¦\86পনার à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড লিখুন",
+       "createacct-yourpassword-ph": "পাসà¦\93য়ারà§\8dড à¦²à¦¿à¦\96ুন",
+       "yourpasswordagain": "পাসà¦\93য়ারà§\8dড à¦\86বার à¦²à¦¿à¦\96à§\81ন:",
+       "createacct-yourpasswordagain": "পাসà¦\93য়ারà§\8dড নিশ্চিত করুন",
+       "createacct-yourpasswordagain-ph": "à¦\86বারà¦\93 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড à¦²à¦¿à¦\96ুন",
+       "remembermypassword": "à¦\8fà¦\87 à¦¬à§\8dরাà¦\89à¦\9cারà§\87 à¦\86মার à¦ªà§\8dরবà§\87শ à¦®à¦¨à§\87 à¦°à¦¾à¦\96া à¦¹à§\8bà¦\95 (সরà§\8dবà§\8bà¦\9aà§\8dà¦\9a $1 {{PLURAL:$1|দিনের}} জন্য)",
        "userlogin-remembermypassword": "আমাকে প্রবেশ অবস্থায় রাখো",
        "userlogin-signwithsecure": "নিরাপদ সংযোগ ব্যবহার করুন",
        "yourdomainname": "আপনার ডোমেইন",
        "externaldberror": "হয় কোন বহিঃস্থ যাচাইকরণ ডাটাবেজ ত্রুটি ঘটেছে অথবা আপনার বহিঃস্থ অ্যাকাউন্ট হালনাগাদ করার অনুমতি নেই।",
        "login": "প্রবেশ",
        "nav-login-createaccount": "প্রবেশ/নতুন অ্যাকাউন্ট",
-       "loginprompt": "{{SITENAME}}-তে প্রবেশ করতে হলে আপনার ব্রাউজারের কুকি অবশ্যই সক্রিয় করতে হবে।",
        "userlogin": "প্রবেশ/নতুন অ্যাকাউন্ট",
        "userloginnocreate": "প্রবেশ",
        "logout": "প্রস্থান করুন",
        "gotaccount": "আপনার কি ইতিমধ্যে একটি অ্যাকাউন্ট তৈরি করা আছে? '''$1''' করুন।",
        "gotaccountlink": "প্রবেশ",
        "userlogin-resetlink": "আপনার লগইনের বিস্তারিত তথ্যাদি ভুলে গেছেন?",
-       "userlogin-resetpassword-link": "শবà§\8dদà¦\9aাবি ভুলে গেছেন?",
+       "userlogin-resetpassword-link": "পাসà¦\93য়ারà§\8dড ভুলে গেছেন?",
        "userlogin-helplink2": "লগইন সংক্রান্ত সাহায্য",
-       "userlogin-loggedin": "আপনি বর্তমানে {{GENDER:$1|$1}} হিসাবে লগইন আছেন।\nঅন্য ব্যবহারকারী নামে লগইন করতে চাইলে নিচের ফর্মটি ব্যবহার করুন।",
-       "userlogin-createanother": "আরেকটি অ্যাকাউন্ট তৈরি করুন",
        "createacct-emailrequired": "ইমেইল ঠিকানা",
        "createacct-emailoptional": "ইমেইল ঠিকানা (ঐচ্ছিক)",
        "createacct-email-ph": "আপনার ইমেইল ঠিকানা যোগ করুন",
        "createacct-benefit-body1": "{{PLURAL:$1|টি সম্পাদনা}}",
        "createacct-benefit-body2": "{{PLURAL:$1|টি পাতা}}",
        "createacct-benefit-body3": "জন সাম্প্রতিক {{PLURAL:$1|অবদানকারী}}",
-       "badretype": "à¦\86পনার à¦ªà§\8dরবà§\87শ à¦\95রানà§\8b à¦¶à¦¬à§\8dদà¦\9aাবি'à¦\9fি à¦®à¦¿à¦²à¦\9bà§\87না।",
+       "badretype": "à¦\86পনার à¦ªà§\8dরবà§\87শ à¦\95রানà§\8b à¦ªà¦¾à¦¸à¦\93য়ারà§\8dডà¦\9fি à¦®à¦¿à¦²à¦\9bà§\87 না।",
        "userexists": "এই ব্যবহারকারী নামটি ইতমধ্যে ব্যবহার করা হয়েছে।\nঅনুগ্রহ করে অন্য নাম বেছে নিন।",
        "loginerror": "প্রবেশ করতে সমস্যা হয়েছে",
        "createacct-error": "অ্যাকাউন্ট তৈরি ত্রুটি",
        "createaccounterror": "অ্যাকাউন্ট তৈরি হয়নি: $1",
-       "nocookiesnew": "বà§\8dযবহারà¦\95ারà§\80র à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà¦\9fি à¦¸à§\83ষà§\8dà¦\9fি à¦\95রা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87, à¦\95িনà§\8dতà§\81 à¦\86পনি à¦\8fà¦\96নà¦\93 à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà§\87 à¦ªà§\8dরবà§\87শ à¦\95রà§\87ননি। {{SITENAME}}-তà§\87 à¦\95à§\81à¦\95ি à¦¬à§\8dযবহার à¦\95রà§\87 à¦¬à§\8dযবহারà¦\95ারà§\80দà§\87র à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà§\87 à¦ªà§\8dরবà§\87শ à¦\95রানà§\8b à¦¹à¦¯à¦¼à¥¤ à¦\86পনার à¦¬à§\8dরাà¦\89à¦\9cারà§\87 à¦\95à§\81à¦\95িà¦\97à§\81লি à¦¨à¦¿à¦·à§\8dà¦\95à§\8dরিয় à¦\95রা à¦\86à¦\9bà§\87। à¦\85নà§\81à¦\97à§\8dরহ à¦\95রà§\87 à¦\95à§\81à¦\95িà¦\97à§\81লি à¦¸à¦\95à§\8dরিয় à¦\95রà§\81ন à¦\8fবà¦\82 à¦\86পনার à¦¨à¦¤à§\81ন à¦¬à§\8dযবহারà¦\95ারà§\80 à¦¨à¦¾à¦® à¦\93 à¦¶à¦¬à§\8dদà¦\9aাবি ব্যবহার করে অ্যাকাউন্টে প্রবেশ করুন।",
+       "nocookiesnew": "বà§\8dযবহারà¦\95ারà§\80র à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà¦\9fি à¦¸à§\83ষà§\8dà¦\9fি à¦\95রা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87, à¦\95িনà§\8dতà§\81 à¦\86পনি à¦\8fà¦\96নà¦\93 à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà§\87 à¦ªà§\8dরবà§\87শ à¦\95রà§\87ননি। {{SITENAME}}-তà§\87 à¦\95à§\81à¦\95ি à¦¬à§\8dযবহার à¦\95রà§\87 à¦¬à§\8dযবহারà¦\95ারà§\80দà§\87র à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà§\87 à¦ªà§\8dরবà§\87শ à¦\95রানà§\8b à¦¹à¦¯à¦¼à¥¤ à¦\86পনার à¦¬à§\8dরাà¦\89à¦\9cারà§\87 à¦\95à§\81à¦\95িà¦\97à§\81লি à¦¨à¦¿à¦·à§\8dà¦\95à§\8dরিয় à¦\95রা à¦\86à¦\9bà§\87। à¦\85নà§\81à¦\97à§\8dরহ à¦\95রà§\87 à¦\95à§\81à¦\95িà¦\97à§\81লি à¦¸à¦\95à§\8dরিয় à¦\95রà§\81ন à¦\8fবà¦\82 à¦\86পনার à¦¨à¦¤à§\81ন à¦¬à§\8dযবহারà¦\95ারà§\80 à¦¨à¦¾à¦® à¦\93 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড ব্যবহার করে অ্যাকাউন্টে প্রবেশ করুন।",
        "nocookieslogin": "{{SITENAME}} এ কুকি (cookies) এর মাধ্যমে ব্যবহারকারীদের লগ-ইন সম্পন্ন করা হয়। আপনার ব্রাঊজারে কুকি বন্ধ করে দেওয়া আছে। কুকি চালু করে আবার চেষ্টা করুন।",
        "nocookiesfornew": "ব্যবহারকারীর অ্যাকাউন্ট তৈরি হয়নি, কারণ এর উৎস সম্পর্কে আমরা নিশ্চিত নই।\nনিশ্চিত করুন আপনার কুকি সক্রিয় রয়েছে, পাতাটি পুনরায় লোড করে আবার চেষ্টা করুন।",
        "noname": "আপনি সঠিক ব্যবহারকারী নাম নির্দিষ্ট করেননি।",
        "nosuchusershort": "\"$1\" নামের কোন ব্যবহারকারী নেই। নামের বানান পরীক্ষা করুন।",
        "nouserspecified": "আপনাকে অবশ্যই ব্যবহারকারী নাম নির্দিষ্ট করতে হবে।",
        "login-userblocked": "এই ব্যবহারকারীকে বাধা দেওয়া হয়েছে। লগ-ইন সম্ভব নয়।",
-       "wrongpassword": "à¦\86পনি à¦­à§\81ল à¦¶à¦¬à§\8dদà¦\9aাবি ব্যবহার করেছেন। অনুগ্রহ করে আবার চেষ্টা করুন।",
-       "wrongpasswordempty": "শবà§\8dদà¦\9aাবি (password) প্রবেশের ঘরটি খালি ছিল। দয়া করে আবার চেষ্টা করুন।",
-       "passwordtooshort": "শবà§\8dদà¦\9aাবি অবশ্যই {{PLURAL:$1|১ অক্ষরের|$1 অক্ষরের}} হতে হবে।",
-       "password-name-match": "à¦\86পনার à¦¶à¦¬à§\8dদà¦\9aাবি আপনার ব্যবহারকারী নাম থেকে আলাদা হতে হবে।",
-       "password-login-forbidden": "à¦\8fà¦\87 à¦¬à§\8dযবহারà¦\95ারà§\80র à¦¨à¦¾à¦® à¦\8fবà¦\82 à¦¶à¦¬à§\8dদà¦\9aাবিটি ব্যবহার নিষিদ্ধ করা হয়েছে।",
-       "mailmypassword": "শবà§\8dদà¦\9aাবি রিসেট",
-       "passwordremindertitle": "{{SITENAME}}-à¦\8fর à¦\9cনà§\8dয à¦¨à¦¤à§\81ন à¦¸à¦¾à¦®à¦¯à¦¼à¦¿à¦\95 à¦¶à¦¬à§\8dদà¦\9aাবি",
-       "passwordremindertext": "à¦\95à§\87à¦\89 à¦\8fà¦\95à¦\9cন ($1 à¦\86à¦\87পি à¦ à¦¿à¦\95ানাà¦\9fি à¦¥à§\87à¦\95à§\87 à¦¸à¦®à§\8dভবত à¦\86পনি) à¦\85নà§\81রà§\8bধ à¦\95রà§\87à¦\9bà§\87ন à¦¯à§\87ন à¦\86মরা à¦\86পনাà¦\95à§\87 {{SITENAME}} ($4) à¦\8fর à¦\9cনà§\8dয à¦\8fà¦\95à¦\9fি à¦¨à¦¤à§\81ন à¦¶à¦¬à§\8dদà¦\9aাবি à¦ªà¦¾à¦ à¦¾à¦\87।\n\"$2\" à¦¨à¦¾à¦®à§\87 à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9f à¦\96à§\8bলা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87 à¦\8fবà¦\82 à¦\8fর à¦¶à¦¬à§\8dদà¦\9aাবি \"$3\"। à¦\86পনি à¦¯à¦¦à¦¿ à¦\8fà¦\9fাà¦\87 à¦\9aà§\87য়à§\87 à¦¥à¦¾à¦\95à§\87ন, à¦¤à¦¾à¦¹à¦²à§\87 à¦\86পনাà¦\95à§\87 à¦\8fà¦\96ন à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà§\87 à¦ªà§\8dরবà§\87শ à¦\95রতà§\87 à¦¹à¦¬à§\87 à¦\93 à¦¨à¦¤à§\81ন à¦\8fà¦\95à¦\9fি à¦¶à¦¬à§\8dদà¦\9aাবি à¦ªà¦\9bনà§\8dদ à¦\95রতà§\87 à¦¹à¦¬à§\87।\n{{PLURAL:$5|à¦\8fà¦\95 à¦¦à¦¿à¦¨|$5 à¦¦à¦¿à¦¨}} à¦ªà¦°à§\87 à¦\86পনার à¦\8fà¦\87 à¦\85সà§\8dথায়à§\80 à¦¶à¦¬à§\8dদà¦\9aাবির à¦®à§\87য়াদ à¦\89তà§\8dতà§\80রà§\8dণ à¦¹à¦¯à¦¼à§\87 à¦¯à¦¾à¦¬à§\87।\n\nযদি à¦\86পনি à¦\9bাড়া à¦\85নà§\8dয à¦\95à§\87à¦\89 à¦\8fà¦\87 à¦\85নà§\81রà§\8bধ à¦\95রà§\87 à¦¥à¦¾à¦\95à§\87, à¦\95িà¦\82বা à¦¯à¦¦à¦¿ à¦\86পনার à¦ªà§\81রনà§\8b à¦¶à¦¬à§\8dদà¦\9aাবিà¦\9fি à¦®à¦¨à§\87 à¦ªà¦¡à¦¼à§\87 à¦\97িয়à§\87 à¦¥à¦¾à¦\95à§\87 à¦\93 à¦¸à§\87à¦\9fি à¦\86র à¦¬à¦¦à¦²à¦¾à¦¬à¦¾à¦° à¦\87à¦\9aà§\8dà¦\9bা à¦¨à¦¾ à¦¥à¦¾à¦\95à§\87, à¦¤à¦¾à¦¹à¦²à§\87 à¦\8fà¦\87 à¦¬à¦¾à¦°à§\8dতাà¦\9fি à¦\89পà§\87à¦\95à§\8dষা à¦\95রতà§\87 à¦ªà¦¾à¦°à§\87ন à¦\8fবà¦\82 à¦ªà§\81রনà§\8b à¦¶à¦¬à§\8dদà¦\9aাবিটিই ব্যবহার করে যেতে পারেন।",
+       "wrongpassword": "à¦\86পনি à¦­à§\81ল à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড ব্যবহার করেছেন। অনুগ্রহ করে আবার চেষ্টা করুন।",
+       "wrongpasswordempty": "পাসà¦\93য়ারà§\8dড প্রবেশের ঘরটি খালি ছিল। দয়া করে আবার চেষ্টা করুন।",
+       "passwordtooshort": "পাসà¦\93য়ারà§\8dড অবশ্যই {{PLURAL:$1|১ অক্ষরের|$1 অক্ষরের}} হতে হবে।",
+       "password-name-match": "à¦\86পনার à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড আপনার ব্যবহারকারী নাম থেকে আলাদা হতে হবে।",
+       "password-login-forbidden": "à¦\8fà¦\87 à¦¬à§\8dযবহারà¦\95ারà§\80র à¦¨à¦¾à¦® à¦\8fবà¦\82 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dডটি ব্যবহার নিষিদ্ধ করা হয়েছে।",
+       "mailmypassword": "পাসà¦\93য়ারà§\8dড রিসেট",
+       "passwordremindertitle": "{{SITENAME}}-à¦\8fর à¦\9cনà§\8dয à¦¨à¦¤à§\81ন à¦¸à¦¾à¦®à¦¯à¦¼à¦¿à¦\95 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড",
+       "passwordremindertext": "à¦\95à§\87à¦\89 à¦\8fà¦\95à¦\9cন ($1 à¦\86à¦\87পি à¦ à¦¿à¦\95ানাà¦\9fি à¦¥à§\87à¦\95à§\87 à¦¸à¦®à§\8dভবত à¦\86পনি) à¦\85নà§\81রà§\8bধ à¦\95রà§\87à¦\9bà§\87ন à¦¯à§\87ন à¦\86মরা à¦\86পনাà¦\95à§\87 {{SITENAME}} ($4) à¦\8fর à¦\9cনà§\8dয à¦\8fà¦\95à¦\9fি à¦¨à¦¤à§\81ন à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড à¦ªà¦¾à¦ à¦¾à¦\87।\n\"$2\" à¦¨à¦¾à¦®à§\87 à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9f à¦\96à§\8bলা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87 à¦\8fবà¦\82 à¦\8fর à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড \"$3\"। à¦\86পনি à¦¯à¦¦à¦¿ à¦\8fà¦\9fাà¦\87 à¦\9aà§\87য়à§\87 à¦¥à¦¾à¦\95à§\87ন, à¦¤à¦¾à¦¹à¦²à§\87 à¦\86পনাà¦\95à§\87 à¦\8fà¦\96ন à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà§\87 à¦ªà§\8dরবà§\87শ à¦\95রতà§\87 à¦¹à¦¬à§\87 à¦\93 à¦¨à¦¤à§\81ন à¦\8fà¦\95à¦\9fি à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড à¦ªà¦\9bনà§\8dদ à¦\95রতà§\87 à¦¹à¦¬à§\87।\n{{PLURAL:$5|à¦\8fà¦\95 à¦¦à¦¿à¦¨|$5 à¦¦à¦¿à¦¨}} à¦ªà¦°à§\87 à¦\86পনার à¦\8fà¦\87 à¦\85সà§\8dথায়à§\80 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dডà§\87র à¦®à§\87য়াদ à¦\89তà§\8dতà§\80রà§\8dণ à¦¹à¦¯à¦¼à§\87 à¦¯à¦¾à¦¬à§\87।\n\nযদি à¦\86পনি à¦\9bাড়া à¦\85নà§\8dয à¦\95à§\87à¦\89 à¦\8fà¦\87 à¦\85নà§\81রà§\8bধ à¦\95রà§\87 à¦¥à¦¾à¦\95à§\87, à¦\95িà¦\82বা à¦¯à¦¦à¦¿ à¦\86পনার à¦ªà§\81রনà§\8b à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড à¦®à¦¨à§\87 à¦ªà¦¡à¦¼à§\87 à¦\97িয়à§\87 à¦¥à¦¾à¦\95à§\87 à¦\93 à¦¸à§\87à¦\9fি à¦\86র à¦¬à¦¦à¦²à¦¾à¦¬à¦¾à¦° à¦\87à¦\9aà§\8dà¦\9bা à¦¨à¦¾ à¦¥à¦¾à¦\95à§\87, à¦¤à¦¾à¦¹à¦²à§\87 à¦\8fà¦\87 à¦¬à¦¾à¦°à§\8dতাà¦\9fি à¦\89পà§\87à¦\95à§\8dষা à¦\95রতà§\87 à¦ªà¦¾à¦°à§\87ন à¦\8fবà¦\82 à¦ªà§\81রনà§\8b à¦ªà¦¾à¦¸à¦\93য়ারà§\8dডটিই ব্যবহার করে যেতে পারেন।",
        "noemail": "\"$1\" ব্যবহারকারীর জন্য কোন ই-মেইল ঠিকানা সংরক্ষিত নেই।",
        "noemailcreate": "আপনাকে অবশ্যই একটি সঠিক ইমেইল ঠিকানা দিতে হবে",
-       "passwordsent": "à¦\8fà¦\95à¦\9fি à¦¨à¦¤à§\81ন à¦¶à¦¬à§\8dদà¦\9aাবি \"$1\" ব্যবহারকারীর ই-মেইল ঠিকানায় পাঠানো হয়েছে। দয়াকরে তা পাওয়ার পর আবার লগ-ইন করুন।",
-       "blocked-mailpassword": "à¦\86পনার à¦\86à¦\87পি à¦ à¦¿à¦\95ানাà¦\9fি à¦¥à§\87à¦\95à§\87 à¦¸à¦®à§\8dপাদনা à¦\95রতà§\87 à¦¬à¦¾à¦§à¦¾ à¦\86à¦\9bà§\87, à¦¤à¦¾à¦\87 à¦\8fà¦\87 à¦ à¦¿à¦\95ানার à¦\85পবà§\8dযবহার à¦\95রà§\87 à¦¶à¦¬à§\8dদà¦\9aাবি ফেরত আনতে দেয়া যাবে না।",
+       "passwordsent": "à¦\8fà¦\95à¦\9fি à¦¨à¦¤à§\81ন à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড \"$1\" ব্যবহারকারীর ই-মেইল ঠিকানায় পাঠানো হয়েছে। দয়াকরে তা পাওয়ার পর আবার লগ-ইন করুন।",
+       "blocked-mailpassword": "à¦\86পনার à¦\86à¦\87পি à¦ à¦¿à¦\95ানাà¦\9fি à¦¥à§\87à¦\95à§\87 à¦¸à¦®à§\8dপাদনা à¦\95রতà§\87 à¦¬à¦¾à¦§à¦¾ à¦\86à¦\9bà§\87, à¦¤à¦¾à¦\87 à¦\8fà¦\87 à¦ à¦¿à¦\95ানার à¦\85পবà§\8dযবহার à¦\95রà§\87 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড ফেরত আনতে দেয়া যাবে না।",
        "eauthentsent": "মনোনীত ই-মেইল ঠিকানায় একটি নিশ্চিতকরণ ই-মেইল পাঠানো হয়েছে।\nঐ অ্যাকাউন্টটে অন্য কোন ই-মেইল পাঠানোর আগে আপনাকে ই-মেইলের নির্দেশগুলি অনুসরণ করতে হবে, যাতে অ্যাকাউন্টটি যে আসলেই আপনার, তা নিশ্চিত হয়।",
-       "throttled-mailpassword": "বিà¦\97ত {{PLURAL:$1|à¦\98ণà§\8dà¦\9fার|$1 à¦\98ণà§\8dà¦\9fার}} à¦®à¦§à§\8dযà§\87 à¦\87তিমধà§\8dযà§\87à¦\87 à¦\8fà¦\95বার à¦¶à¦¬à§\8dদà¦\9aাবি à¦¬à¦¦à¦²à§\87র à¦¤à¦¥à§\8dয à¦ªà¦¾à¦ à¦¾à¦¨à§\8b à¦¹à¦¯à¦¼à§\87à¦\9bà§\87। à¦\85পবà§\8dযবহার à¦°à§\8bধà§\87 à¦ªà§\8dরতি {{PLURAL:$1|à¦\98ণà§\8dà¦\9fায়|$1 à¦\98ণà§\8dà¦\9fায়}} à¦\95à§\87বল à¦\8fà¦\95বার à¦¶à¦¬à§\8dদà¦\9aাবি বদলের তথ্য পাঠানো যাবে।",
+       "throttled-mailpassword": "বিà¦\97ত {{PLURAL:$1|à¦\98ণà§\8dà¦\9fার|$1 à¦\98ণà§\8dà¦\9fার}} à¦®à¦§à§\8dযà§\87 à¦\87তিমধà§\8dযà§\87à¦\87 à¦\8fà¦\95বার à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড à¦¬à¦¦à¦²à§\87র à¦¤à¦¥à§\8dয à¦ªà¦¾à¦ à¦¾à¦¨à§\8b à¦¹à¦¯à¦¼à§\87à¦\9bà§\87। à¦\85পবà§\8dযবহার à¦°à§\8bধà§\87 à¦ªà§\8dরতি {{PLURAL:$1|à¦\98ণà§\8dà¦\9fায়|$1 à¦\98ণà§\8dà¦\9fায়}} à¦\95à§\87বল à¦\8fà¦\95বার à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড বদলের তথ্য পাঠানো যাবে।",
        "mailerror": "ইমেইল পাঠাতে সমস্যা: $1",
        "acct_creation_throttle_hit": "এই উইকির দর্শক আপনার IP থেকে বিগত সময়ে {{PLURAL:$1|1 টি অ্যাকাউন্ট|$1 গুলো অ্যাকাউন্ট}} তৈরি করেছেন, যা এই সময়ের জন্য সর্বোচ্চ অনুমোদনকৃত।\nফলে, এই IP থেকে দর্শক এই সময়ে নতুন অ্যাকাউন্ট তৈরি করতে পারবেন না।",
        "emailauthenticated": "আপনার ইমেইল ঠিকানাটি $2 তারিখের $3 এ নিশ্চিত করা হয়েছে।",
        "accountcreated": "অ্যাকাউন্ট তৈরি করা হয়েছে",
        "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|আলাপ]]) এর জন্য ব্যবহারকারী অ্যাকাউন্ট তৈরি করা হয়েছে।",
        "createaccount-title": "{{SITENAME}}-এর জন্য অ্যাকাউন্ট সৃষ্টি",
-       "createaccount-text": "à¦\95à§\87à¦\89 $2-à¦\8fর à¦\9cনà§\8dয {{SITENAME}}-à¦\8f à¦\8fà¦\95à¦\9fি à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9f à¦¸à§\83ষà§\8dà¦\9fি à¦\95রà§\87à¦\9bà§\87ন ($4)। \"$2\"-à¦\8fর à¦\9cনà§\8dয à¦¶à¦¬à§\8dদà¦\9aাবি à¦¹à¦² \"$3\"। à¦\86পনার à¦\8fà¦\96ন à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà§\87 à¦ªà§\8dরবà§\87শ à¦\95রà§\87 à¦¶à¦¬à§\8dদà¦\9aাবি পরিবর্তন করা উচিত।\n\nযদি ভুল করে অ্যাকাউন্টটি সৃষ্টি হয়ে থাকে, তাহলে এই বার্তাটি উপেক্ষা করুন।",
+       "createaccount-text": "à¦\95à§\87à¦\89 $2-à¦\8fর à¦\9cনà§\8dয {{SITENAME}}-à¦\8f à¦\8fà¦\95à¦\9fি à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9f à¦¸à§\83ষà§\8dà¦\9fি à¦\95রà§\87à¦\9bà§\87ন ($4)। \"$2\"-à¦\8fর à¦\9cনà§\8dয à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড à¦¹à¦² \"$3\"। à¦\86পনার à¦\8fà¦\96ন à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà§\87 à¦ªà§\8dরবà§\87শ à¦\95রà§\87 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড পরিবর্তন করা উচিত।\n\nযদি ভুল করে অ্যাকাউন্টটি সৃষ্টি হয়ে থাকে, তাহলে এই বার্তাটি উপেক্ষা করুন।",
        "login-throttled": "আপনি সাম্প্রতিক সময়ে পরপর বেশ কয়েকবার প্রবেশের চেষ্টা করেছেন।\nপুনরায় চেষ্টা করার পূর্বে অনুগ্রহ করে $1 অপেক্ষা করুন।",
        "login-abort-generic": "আপনার লগইন সফল ছিলো না - বাতিল করা হয়েছে",
        "loginlanguagelabel": "ভাষা: $1",
        "php-mail-error-unknown": "পিএইচপি এর মেইল () কার্যে অজ্ঞাত ভুল",
        "user-mail-no-addy": "কোনো ইমেইল ঠিকানা ছাড়াই ইমেইল করার চেষ্টা করা হয়েছে।",
        "user-mail-no-body": "অত্যান্ত সংক্ষিপ্ত অথবা কোনো তথ্য ছাড়াই ইমেইল পাঠানোর চেষ্টা করা হয়েছিল।",
-       "changepassword": "শবà§\8dদà¦\9aাবি পরিবর্তন",
+       "changepassword": "পাসà¦\93য়ারà§\8dড পরিবর্তন",
        "resetpass_announce": "লগইন করার জন্য আপনাকে অবশ্যই এনটি নতুন পাসওয়ার্ড নির্ধারণ করতে হবে।",
        "resetpass_text": "<!-- এখানে লেখা যোগ করুন -->",
-       "resetpass_header": "শবà§\8dদà¦\9aাবি পরিবর্তন করো",
-       "oldpassword": "পà§\81রনà§\8b à¦¶à¦¬à§\8dদà¦\9aাবি",
-       "newpassword": "নতà§\81ন à¦¶à¦¬à§\8dদà¦\9aাবি:",
-       "retypenew": "নতà§\81ন à¦¶à¦¬à§\8dদà¦\9aাবি আবার লিখুন:",
-       "resetpass_submit": "শবà§\8dদà¦\9aাবি দাও এবং লগ-ইন করো",
-       "changepassword-success": "à¦\86পনার à¦¶à¦¬à§\8dদà¦\9aাবি সাফলভাবে পরিবর্তীত হয়েছে।",
+       "resetpass_header": "পাসà¦\93য়ারà§\8dড পরিবর্তন করো",
+       "oldpassword": "পà§\81রনà§\8b à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড:",
+       "newpassword": "নতà§\81ন à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড:",
+       "retypenew": "নতà§\81ন à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড আবার লিখুন:",
+       "resetpass_submit": "পাসà¦\93য়ারà§\8dড দাও এবং লগ-ইন করো",
+       "changepassword-success": "à¦\86পনার à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড সাফলভাবে পরিবর্তীত হয়েছে।",
        "changepassword-throttled": "আপনি সম্প্রতি পরপর বেশ কয়েকবার প্রবেশের চেষ্টা করেছেন। পুনরায় চেষ্টা করার পূর্বে অনুগ্রহ করে $1 অপেক্ষা করুন।",
-       "resetpass_forbidden": "শবà§\8dদà¦\9aাবি পরিবর্তন করা সম্ভব নয়",
+       "resetpass_forbidden": "পাসà¦\93য়ারà§\8dড পরিবর্তন করা সম্ভব নয়",
        "resetpass-no-info": "এই পাতাটিতে সরাসরি প্রবেশাধিকার পেতে আপনাকে অবশ্যই লগইন করতে হবে।",
-       "resetpass-submit-loggedin": "শবà§\8dদà¦\9aাবি পরিবর্তন",
+       "resetpass-submit-loggedin": "পাসà¦\93য়ারà§\8dড পরিবর্তন",
        "resetpass-submit-cancel": "বাতিল",
-       "resetpass-wrong-oldpass": "ভà§\81ল à¦\85সà§\8dথায়à§\80 à¦\85থবা à¦¬à¦°à§\8dতমান à¦¶à¦¬à§\8dদà¦\9aাবি।\nসমà§\8dভবতà¦\83 à¦\86পনি à¦\87তà§\8bমধà§\8dযà§\87à¦\87 à¦¸à¦«à¦²à¦­à¦¾à¦¬à§\87 à¦\86পনার à¦¶à¦¬à§\8dদà¦\9aাবিà¦\9fি à¦ªà¦°à¦¿à¦¬à¦°à§\8dতন à¦\95রà§\87à¦\9bà§\87ন à¦\85থবা à¦\8fà¦\95à¦\9fি à¦¨à¦¤à§\81ন à¦\85সà§\8dথায়à§\80 à¦¶à¦¬à§\8dদà¦\9aাবির জন্য অনুরোধ করেছেন।",
+       "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র জন্য অনুরোধ করেছেন।",
        "resetpass-recycled": "অনুগ্রহ করে বর্তমানে ব্যবহার করছেন এমন পাসওয়ার্ডের পরিবর্তে নতুন একটি পাসওয়ার্ড নির্ধারণ করুন।",
        "resetpass-temp-emailed": "সাময়িকভাবে ব্যবহার করার কোড দিয়ে আপনি লগইন করেছেন।\nলগইন করার জন্য আপনাকে অবশ্যই একটি নতুন পাসওয়ার্ড নির্ধারন করতে হবে:",
-       "resetpass-temp-password": "à¦\85সà§\8dথায়à§\80 à¦¶à¦¬à§\8dদà¦\9aাবি:",
-       "resetpass-abort-generic": "শবà§\8dদà¦\9aাবি পরিবর্তন একটি এক্সটেনশনের কারণে স্থগিত করা হয়েছে।",
+       "resetpass-temp-password": "à¦\85সà§\8dথায়à§\80 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড:",
+       "resetpass-abort-generic": "পাসà¦\93য়ারà§\8dড পরিবর্তন একটি এক্সটেনশনের কারণে স্থগিত করা হয়েছে।",
        "resetpass-expired": "আপনার পাসওয়ার্ডের মেয়াদ উত্তীর্ণ হয়েছে। অনুগ্রহ করে নতুন পাসওয়ার্ড নির্ধারণ করুন।",
        "resetpass-expired-soft": "আপনার পাসওয়ার্ডের মেয়াদ উত্তীর্ণ হয়েছে এবং আপনাকে একটি নতুন পাসওয়ার্ড নির্ধারণ করতে হবে। অনুগ্রহ করে এখনই একটি নতুন পাসওয়ার্ড নির্ধারণ করুন অথবা পরে পরিবর্তন করতে চাইলে \"{{int:resetpass-submit-cancel}}\" বাটনে ক্লিক করুন।",
-       "resetpass-validity-soft": "দয়া à¦\95রà§\87 à¦\8fà¦\95à¦\9fি à¦¨à¦¤à§\81ন à¦¶à¦¬à§\8dদà¦\9aাবি নির্ধারণ করুন অথবা পরে করার জন্য \"{{int:resetpass-submit-cancel}}\" ক্লিক করুন।",
-       "passwordreset": "শবà§\8dদà¦\9aাবি রিসেট",
+       "resetpass-validity-soft": "দয়া à¦\95রà§\87 à¦\8fà¦\95à¦\9fি à¦¨à¦¤à§\81ন à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড নির্ধারণ করুন অথবা পরে করার জন্য \"{{int:resetpass-submit-cancel}}\" ক্লিক করুন।",
+       "passwordreset": "পাসà¦\93য়ারà§\8dড রিসেট",
        "passwordreset-text-one": "আপনার পাসওয়ার্ড পুনরায় সেট করতে এই ফর্মটি পূরণ করুন।",
-       "passwordreset-text-many": "{{PLURAL:$1|à¦\87মà§\87à¦\87লà§\87র à¦®à¦¾à¦§à§\8dযমà§\87 à¦\8fà¦\95à¦\9fি à¦\85সà§\8dথায়à§\80 à¦¶à¦¬à§\8dদà¦\9aাবি পেতে ঘরগুলির একটি পূরণ করুন।}}",
-       "passwordreset-legend": "শবà§\8dদà¦\9aাবি রিসেট",
-       "passwordreset-disabled": "à¦\8fà¦\87 à¦\89à¦\87à¦\95িতà§\87 à¦¶à¦¬à§\8dদà¦\9aাবি রিসেটের সুবিধা নিষ্ক্রিয় রয়েছে।",
+       "passwordreset-text-many": "{{PLURAL:$1|à¦\87মà§\87à¦\87লà§\87র à¦®à¦¾à¦§à§\8dযমà§\87 à¦\8fà¦\95à¦\9fি à¦\85সà§\8dথায়à§\80 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড পেতে ঘরগুলির একটি পূরণ করুন।}}",
+       "passwordreset-legend": "পাসà¦\93য়ারà§\8dড রিসেট",
+       "passwordreset-disabled": "à¦\8fà¦\87 à¦\89à¦\87à¦\95িতà§\87 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড রিসেটের সুবিধা নিষ্ক্রিয় রয়েছে।",
        "passwordreset-emaildisabled": "এই উইকিতে ইমেইল অপশনটি বন্ধ করা হয়েছে।",
        "passwordreset-username": "ব্যবহারকারী নাম:",
        "passwordreset-domain": "ডোমেইন:",
        "passwordreset-capture": "অনুসন্ধানের ফলাফলের ইমেইল দেখুন?",
-       "passwordreset-capture-help": "à¦\86পনি à¦¯à¦¦à¦¿ à¦\8fà¦\87 à¦ªà¦°à§\80à¦\95à§\8dষা à¦¬à¦\95à§\8dসà§\87 à¦\95à§\8dলিà¦\95 à¦\95রà§\87ন, à¦¤à¦¬à§\87 à¦\85সà§\8dথায়à§\80 à¦¶à¦¬à§\8dদà¦\9aাবিসহ একটি ইমেইল আপনাকে দেখানো হবে ও সেইসাথে ব্যবহারকারীকে তা পাঠানো হবে।",
+       "passwordreset-capture-help": "à¦\86পনি à¦¯à¦¦à¦¿ à¦\8fà¦\87 à¦ªà¦°à§\80à¦\95à§\8dষা à¦¬à¦\95à§\8dসà§\87 à¦\95à§\8dলিà¦\95 à¦\95রà§\87ন, à¦¤à¦¬à§\87 à¦\85সà§\8dথায়à§\80 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dডসহ একটি ইমেইল আপনাকে দেখানো হবে ও সেইসাথে ব্যবহারকারীকে তা পাঠানো হবে।",
        "passwordreset-email": "ইমেইল ঠিকানা:",
        "passwordreset-emailtitle": "{{SITENAME}} সাইটে ব্যবহারকারীর বিস্তারিত তথ্যাদি",
-       "passwordreset-emailtext-ip": "à¦\95à§\87à¦\89 à¦\8fà¦\95à¦\9cন (সমà§\8dভবত à¦\86পনি, $1 à¦\86à¦\87পি à¦ à¦¿à¦\95ানা à¦¥à§\87à¦\95à§\87) {{SITENAME}} ($4) à¦¸à¦¾à¦\87à¦\9fà§\87র à¦\9cনà§\8dয à¦\86পনার\nশবà§\8dদà¦\9aাবি বদলের জন্য অনুরোধ করেছে। নিচের ব্যবহারকারী {{PLURAL:$3|অ্যাকাউন্টটি|অ্যাকাউন্টগুলো}}\nএই ই-মেইল ঠিকানার সাথে সংযুক্ত:\n\n$2\n\n{{PLURAL:$3|এই অস্থায়ী পাসওয়ার্ডটি|এই অস্থায়ী পাসওয়ার্ডগুলো}} আগামী {{PLURAL:$5|এক দিন|$5 দিন}} পর মেয়াদোত্তীর্ণ হয়ে যাবে।\nআপনার অবশ্যই লগ-ইন করে একটি নতুন পাসওয়ার্ড পছন্দ করা উচিত। যদি অন্য কেউ এই অনুরোধ করে থাকে,\nঅথবা আপনি যদি পুরোনো পাসওয়ার্ড মনে করতে পারেন, এবং আপনার সেটি পরিবর্তন করার কোনো ইচ্ছা না থাকে, তবে\nআপনি এই বার্তাটি উপেক্ষা করতে পারে, এবং আপনার পুরোনো পাসওয়ার্ড ব্যবহার করা চালিয়ে যেতে পারেন।",
-       "passwordreset-emailtext-user": "বà§\8dযবহারà¦\95ারà§\80 $1 {{SITENAME}} ($4) à¦¸à¦¾à¦\87à¦\9fà§\87র à¦\9cনà§\8dয à¦\86পনার à¦¶à¦¬à§\8dদà¦\9aাবি বদলের জন্য অনুরোধ করেছে। নিচের ব্যবহারকারী {{PLURAL:$3|অ্যাকাউন্টটি|অ্যাকাউন্টগুলো}}\nএই ই-মেইল ঠিকানার সাথে সংযুক্ত:\n\n$2\n\n{{PLURAL:$3|এই অস্থায়ী পাসওয়ার্ডটি|এই অস্থায়ী পাসওয়ার্ডগুলো}} আগামী {{PLURAL:$5|এক দিন|$5 দিন}} পর মেয়াদোত্তীর্ণ হয়ে যাবে।\nআপনার অবশ্যই লগ-ইন করে একটি নতুন পাসওয়ার্ড পছন্দ করা উচিত। যদি অন্য কেউ এই অনুরোধ করে থাকে,\nঅথবা আপনি যদি পুরোনো পাসওয়ার্ড মনে করতে পারেন, এবং আপনার সেটি পরিবর্তন করার কোনো ইচ্ছা না থাকে, তবে\nআপনি এই বার্তাটি উপেক্ষা করতে পারে, এবং আপনার পুরোনো পাসওয়ার্ড ব্যবহার করা চালিয়ে যেতে পারেন।",
-       "passwordreset-emailelement": "বà§\8dযবহারà¦\95ারà§\80 à¦¨à¦¾à¦®: $1\nà¦\85সà§\8dথায়à§\80 à¦¶à¦¬à§\8dদà¦\9aাবি: $2",
-       "passwordreset-emailsent": "শবà§\8dদà¦\9aাবি বদলের একটি ই-মেইল পাঠানো হয়েছে।",
+       "passwordreset-emailtext-ip": "à¦\95à§\87à¦\89 à¦\8fà¦\95à¦\9cন (সমà§\8dভবত à¦\86পনি, $1 à¦\86à¦\87পি à¦ à¦¿à¦\95ানা à¦¥à§\87à¦\95à§\87) {{SITENAME}} ($4) à¦¸à¦¾à¦\87à¦\9fà§\87র à¦\9cনà§\8dয à¦\86পনার\nপাসà¦\93য়ারà§\8dড বদলের জন্য অনুরোধ করেছে। নিচের ব্যবহারকারী {{PLURAL:$3|অ্যাকাউন্টটি|অ্যাকাউন্টগুলো}}\nএই ই-মেইল ঠিকানার সাথে সংযুক্ত:\n\n$2\n\n{{PLURAL:$3|এই অস্থায়ী পাসওয়ার্ডটি|এই অস্থায়ী পাসওয়ার্ডগুলো}} আগামী {{PLURAL:$5|এক দিন|$5 দিন}} পর মেয়াদোত্তীর্ণ হয়ে যাবে।\nআপনার অবশ্যই লগ-ইন করে একটি নতুন পাসওয়ার্ড পছন্দ করা উচিত। যদি অন্য কেউ এই অনুরোধ করে থাকে,\nঅথবা আপনি যদি পুরোনো পাসওয়ার্ড মনে করতে পারেন, এবং আপনার সেটি পরিবর্তন করার কোনো ইচ্ছা না থাকে, তবে\nআপনি এই বার্তাটি উপেক্ষা করতে পারে, এবং আপনার পুরোনো পাসওয়ার্ড ব্যবহার করা চালিয়ে যেতে পারেন।",
+       "passwordreset-emailtext-user": "বà§\8dযবহারà¦\95ারà§\80 $1 {{SITENAME}} ($4) à¦¸à¦¾à¦\87à¦\9fà§\87র à¦\9cনà§\8dয à¦\86পনার à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড বদলের জন্য অনুরোধ করেছে। নিচের ব্যবহারকারী {{PLURAL:$3|অ্যাকাউন্টটি|অ্যাকাউন্টগুলো}}\nএই ই-মেইল ঠিকানার সাথে সংযুক্ত:\n\n$2\n\n{{PLURAL:$3|এই অস্থায়ী পাসওয়ার্ডটি|এই অস্থায়ী পাসওয়ার্ডগুলো}} আগামী {{PLURAL:$5|এক দিন|$5 দিন}} পর মেয়াদোত্তীর্ণ হয়ে যাবে।\nআপনার অবশ্যই লগ-ইন করে একটি নতুন পাসওয়ার্ড পছন্দ করা উচিত। যদি অন্য কেউ এই অনুরোধ করে থাকে,\nঅথবা আপনি যদি পুরোনো পাসওয়ার্ড মনে করতে পারেন, এবং আপনার সেটি পরিবর্তন করার কোনো ইচ্ছা না থাকে, তবে\nআপনি এই বার্তাটি উপেক্ষা করতে পারে, এবং আপনার পুরোনো পাসওয়ার্ড ব্যবহার করা চালিয়ে যেতে পারেন।",
+       "passwordreset-emailelement": "বà§\8dযবহারà¦\95ারà§\80 à¦¨à¦¾à¦®: $1\nà¦\85সà§\8dথায়à§\80 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড: $2",
+       "passwordreset-emailsent": "পাসà¦\93য়ারà§\8dড বদলের একটি ই-মেইল পাঠানো হয়েছে।",
        "passwordreset-emailsent-capture": "স্মরণ করিয়ে দেয়ার জন্য একটি ইমেইল করা হয়েছে, যা নিচে দেখানো হচ্ছে।",
        "passwordreset-emailerror-capture": "স্মরণ করিয়ে দেয়ার জন্য একটি ইমেইল তৈরী করা হয়েছিল, যা নিচে দেখানো হচ্ছে, তবে $1 {{GENDER:$2|ব্যবহারকারীকে}} এটি পাঠানো যায়নি!",
        "changeemail": "ই-মেইল ঠিকানা পরিবর্তন",
        "changeemail-header": "অ্যাকাউন্ট ই-মেইল ঠিকানা পরিবর্তন",
-       "changeemail-text": "à¦\87-মà§\87à¦\87ল à¦ à¦¿à¦\95ানা à¦ªà¦°à¦¿à¦¬à¦°à§\8dতন à¦\95রতà§\87 à¦\86পনাà¦\95à§\87 à¦\8fà¦\87 à¦«à¦°à¦®à¦\9fি à¦ªà§\82রণ à¦\95রতà§\87 à¦¹à¦¬à§\87। à¦\8fà¦\87 à¦ªà¦°à¦¿à¦¬à¦°à§\8dতনà¦\9fি à¦¨à¦¿à¦¶à§\8dà¦\9aিত à¦\95রতà§\87 à¦\86পনার à¦¶à¦¬à§\8dদà¦\9aাবি (পাসà¦\93য়ারà§\8dড) প্রদানের প্রয়োজন হবে।",
+       "changeemail-text": "à¦\87-মà§\87à¦\87ল à¦ à¦¿à¦\95ানা à¦ªà¦°à¦¿à¦¬à¦°à§\8dতন à¦\95রতà§\87 à¦\86পনাà¦\95à§\87 à¦\8fà¦\87 à¦«à¦°à¦®à¦\9fি à¦ªà§\82রণ à¦\95রতà§\87 à¦¹à¦¬à§\87। à¦\8fà¦\87 à¦ªà¦°à¦¿à¦¬à¦°à§\8dতনà¦\9fি à¦¨à¦¿à¦¶à§\8dà¦\9aিত à¦\95রতà§\87 à¦\86পনার à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড প্রদানের প্রয়োজন হবে।",
        "changeemail-no-info": "এই পাতাটিতে সরাসরি প্রবেশাধিকার পেতে আপনাকে অবশ্যই লগইন করতে হবে।",
        "changeemail-oldemail": "বর্তমান ই-মেইল ঠিকানা:",
        "changeemail-newemail": "নতুন ই-মেইল ঠিকানা:",
        "changeemail-none": "(কিছু নাই)",
-       "changeemail-password": "à¦\86পনার {{SITENAME}} à¦¶à¦¬à§\8dদà¦\9aাবি:",
+       "changeemail-password": "à¦\86পনার {{SITENAME}} à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড:",
        "changeemail-submit": "ই-মেইল পরিবর্তন",
        "changeemail-cancel": "বাতিল",
        "changeemail-throttled": "আপনি পরপর বেশ কয়েকবার প্রবেশের চেষ্টা করেছেন। পুনরায় চেষ্টা করার পূর্বে অনুগ্রহ করে $1 অপেক্ষা করুন।",
        "preview": "প্রাকদর্শন",
        "showpreview": "প্রাকদর্শন",
        "showdiff": "পরিবর্তনসমূহ",
-       "anoneditwarning": "আপনি লগ ইন করেননি। এই পাতার সম্পাদনার ইতিহাসে আপনার আইপি সংখ্যা সংরক্ষিত হবে।",
+       "blankarticle": "<strong>সতর্ক বার্তা:</strong> আপনি একটি খালি পাতা তৈরী করতে যাচ্ছেন।\nআপনি যদি পুনরায় \"{{int:savearticle}}\" বাটন ক্লিক করেন তাহলে, পাতাটি তৈরী হবে যেখানে কোনো তথ্য লেখা নেই।",
+       "anoneditwarning": "<strong>সতর্কতা:</strong> আপনি বর্তমানে প্রবেশ করেননি। যদি আপনি সম্পাদনা করেন এই পাতার সম্পাদনার ইতিহাসে আপনার আইপি ঠিকানা সার্বজনীনভাবে সংরক্ষিত হবে। যদি আপনি  <strong>[$1 প্রবেশ করেন]</strong> বা  <strong>[$2 একটি অ্যাকাউন্ট তৈরি করেন]</strong>, তাহলে আপনি আপনার আইপি ঠিকানা গোপন রাখতে পারবেন ও অন্যান্য অনেক কিছু সুবিধা পাবেন।",
        "anonpreviewwarning": "আপনি লগ ইন করেননি। এই পাতার সম্পাদনার ইতিহাসে আপনার আইপি সংখ্যা সংরক্ষিত হবে।",
        "missingsummary": "'''খেয়াল করুন''':  আপনি কিন্তু সম্পাদনার সারাংশ দেননি। আবার যদি \"সংরক্ষণ\" বোতামে ক্লিক করেন, তাহলে ঐ সারাংশ বাক্যটি ছাড়াই আপনার সম্পাদনা সংরক্ষিত হবে।",
        "missingcommenttext": "দয়া করে নিচে মন্তব্য যোগ করুন।",
        "loginreqtitle": "লগ-ইন প্রয়োজন",
        "loginreqlink": "লগ-ইন",
        "loginreqpagetext": "অন্যান্য পাতা দেখতে হলে আপনাকে অবশ্যই $1 হতে হবে।",
-       "accmailtitle": "শবà§\8dদà¦\9aাবি à¦ªà¦¾à¦ à¦¾à¦¨à§\8b à¦¹à¦¯à¦¼à§\87à¦\9bà§\87৷",
+       "accmailtitle": "পাসà¦\93য়ারà§\8dড à¦ªà¦¾à¦ à¦¾à¦¨à§\8b à¦¹à¦¯à¦¼à§\87à¦\9bà§\87",
        "accmailtext": "[[User talk:$1|$1]] এর জন্য দৈব ভাবে উৎপন্ন শব্দ চাবি $2 এ পাঠানো হয়েছে।\nলগ-ইন করার পর ''[[Special:ChangePassword|পাসওয়ার্ড পরিবর্তন]]'' পাতা থেকে এটি পরিবর্তন করা যাব।",
        "newarticle": "(নতুন)",
        "newarticletext": "আপনি এমন একটি লিংক অনুসরণ করছেন, যা নেই।\nপাতাটি তৈরি করতে, নিচের বাক্সে তা টাইপ করা শুরু করুন (আরও তথ্য জানতে [$1 সহায়িকা পাতা] দেখুন)।\nআপনি যদি ভুল করে এখানে এসে থাকেন, তাহলে আপনার ব্রাউজারের '''back''' বোতাম ক্লিক করুন।",
        "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": "পাতাটি সর্বোচ্চ এক্সপশন সীমানা অতিক্রম করেছে।",
        "expansion-depth-exceeded-warning": "পাতাটি এক্সেপশন সীমানা অতিক্রম করেছে",
        "parser-unstrip-loop-warning": "ত্রুটিপূর্ণ লুপ খুঁজে পাওয়া গিয়েছে",
        "parser-unstrip-recursion-limit": "লুপ রিকারশন সীমানা অতিক্রম করেছে ($1)",
        "rev-deleted-event": "(লগ অ্যাকশন সরানো হয়েছে)",
        "rev-deleted-user-contribs": "ব্যবহারকারীর নাম অথবা আইপি ঠিকানা অপসারিত হয়েছে - অবদান থেকে সম্পাদনা আড়াল করা হয়েছে",
        "rev-deleted-text-permission": "পাতার এই সংস্করণটি '''অপসারিত''' হয়েছে।\nবিস্তারিত কারণ এর [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} অপসারণ লগে] পাওয়া যেতে পারে।",
+       "rev-suppressed-text-permission": "পাতার সংশোধনটি <strong>গোপন</strong> করা হয়েছে।\nবিস্তারিত বিবরণ [{{fullurl:{{#Special:Log}}/suppress|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}}/suppress|page={{FULLPAGENAMEE}}}} অবলুপ্তি লগে] থাকতে পারে।",
        "searchprofile-advanced-tooltip": "স্বনির্ধারিত নামস্থানে অনুসন্ধান করো",
        "search-result-size": "$1 ({{PLURAL:$2|১টি শব্দ|$2টি শব্দ}})",
        "search-result-category-size": "{{PLURAL:$1 |১টি সদস্য |$1টি সদস্য}} ({{PLURAL:$2 |১টি উপবিষয়শ্রেণী|$2টি উপবিষয়শ্রেণী}}, {{PLURAL:$3 |১টি ফাইল |$3টি ফাইল}})",
-       "search-result-score": "মিলেছে: $1%",
        "search-redirect": "(পুনর্নিদেশনা $1)",
        "search-section": "(অনুচ্ছেদ $1)",
        "search-file-match": "(নথির বিষয়বস্তু মিলে যায়)",
        "searchall": "সমস্ত",
        "showingresults": "নিচে '''$2''' নং থেকে শুরু করে {{PLURAL:$1|'''1''' ফলাফল|'''$1''' ফলাফলসমূহ}} দেখানো হল।",
        "showingresultsinrange": "#<strong>$2</strong> থেকে #<strong>$3</strong> পরিসীমার মধ্যে {{PLURAL:$1|<strong>১টি</strong> ফলাফল|<strong>$1টি</strong> ফলাফল}} নিচে দেখানো হচ্ছে।",
-       "showingresultsheader": "'''$4''' এর জন্য {{PLURAL:$5|ফলাফল '''$3''' এর '''$1'''|ফলাফলসমূহ '''$3''' এর মধ্যে '''$1 - $2'''}}",
+       "search-showingresults": "{{PLURAL:$4|<strong>$3</strong>-এর মধ্যে <strong>$1</strong>টি ফলাফল|<strong>$3</strong>-এর মধ্যে <strong>$1 - $2</strong>টি ফলাফল}}",
        "search-nonefound": "খোঁজকৃত পাতার সাথে মিলে যায় এমন কোনো ফলাফল নেই।",
        "powersearch-legend": "উন্নত অনুসন্ধান",
        "powersearch-ns": "নামস্থানে অনুসন্ধান করো:",
        "powersearch-togglelabel": "পরীক্ষা:",
        "powersearch-toggleall": "সকল",
        "powersearch-togglenone": "কিছু নয়",
+       "powersearch-remember": "ভবিষ্যত অনুসন্ধানগুলির জন্য নির্বাচন মনে রাখুন",
        "search-external": "বহিঃস্থ অনুসন্ধান",
        "searchdisabled": "{{SITENAME}} অনুসন্ধান এখন নিষ্ক্রিয় আছে। আপনি গুগলের মাধ্যমে অনুসন্ধান চালাতে পারেন। লক্ষ্য করুন যে {{SITENAME}}-এর বিষয়বস্তুর উপর গুগলের ইন্ডেক্সগুলি হালনাগাদ না-ও করা থাকতে পারে।",
        "search-error": "অনুসন্ধানের সময় একটি ত্রুটি হয়েছে: $1",
        "preferences": "আমার পছন্দ",
        "mypreferences": "পছন্দসমূহ",
        "prefs-edits": "সম্পাদনা সংখ্যা:",
-       "prefsnologintext2": "বà§\8dযবহারà¦\95ারà§\80 à¦ªà¦\9bনà§\8dদসমà§\82হ à¦¨à¦¿à¦°à§\8dধারনà§\87র à¦\9cনà§\8dয $1 করুন।",
+       "prefsnologintext2": "à¦\86পনার à¦ªà¦\9bনà§\8dদসমà§\82হ à¦ªà¦°à¦¿à¦¬à¦°à§\8dতন à¦\95রতà§\87 à¦ªà§\8dরবà§\87শ করুন।",
        "prefs-skin": "আবরণ (Skin)",
        "skin-preview": "প্রাকদর্শন",
        "datedefault": "কোন পছন্দ নেই",
        "prefs-watchlist-edits-max": "সর্বোচ্চ নাম্বার: ১০০০",
        "prefs-watchlist-token": "নজরতালিকা টোকেন:",
        "prefs-misc": "বিবিধ",
-       "prefs-resetpass": "শবà§\8dদà¦\9aাবি পরিবর্তন",
+       "prefs-resetpass": "পাসà¦\93য়ারà§\8dড পরিবর্তন",
        "prefs-changeemail": "ই-মেইল পরিবর্তন",
        "prefs-setemail": "একটি ই-মেইল ঠিকানা নির্ধারণ করুন",
        "prefs-email": "ই-মেইল অপশন",
        "prefs-help-gender": "সেটিংসের এই পরিবর্তন ঐচ্ছিক।\nসফটওয়্যারে মাধ্যমে লিঙ্গ অনুযায়ী সম্বধনের ক্ষেত্রে এটি ব্যবহৃত হয়।\nএই তথ্য সকলের জন্য উন্মুক্ত থাকেবে।",
        "email": "ই-মেইল",
        "prefs-help-realname": "আসল নাম দেওয়া অনাবশ্যক। যদি আসল নাম দেন, তবে আপনার কাজের স্বীকৃতি দানে তা ব্যবহার করা হবে।",
-       "prefs-help-email": "ই-মেইল ঠিকানা ঐচ্ছিক, তবে শব্দচাবি ভুলে গেলে নতুন করে শব্দচাবি নিতে এটির প্রয়োজন হবে।",
+       "prefs-help-email": "ইমেইল ঠিকানা ঐচ্ছিক, তবে পাসওয়ার্ড ভুলে গেলে নতুন করে পাসওয়ার্ড নিতে এটির প্রয়োজন হবে।",
        "prefs-help-email-others": "আপনি আপনার পরিচয় প্রকাশ না করেও আপনার ব্যবহারকারী অথবা আলাপ পাতাটির মাধ্যমে অন্যদেরকে আপনার সাথে যোগাযোগ করতে দিতে পারেন।",
        "prefs-help-email-required": "ই-মেইল ঠিকানা আবশ্যক।",
        "prefs-info": "সাধারণ তথ্য",
        "right-deletedtext": "অপরাসারিত সংশোধনের অপরাসারিত লেখা এবং পরিবর্তনসমূহ দেখাও",
        "right-browsearchive": "অপসারিত পাতা অনুসন্ধান করো",
        "right-undelete": "পাতাটি পুনরুদ্ধার করুন",
-       "right-suppressrevision": "প্রশাসকদের থেকে লুকানো সংস্করণগুলো রিভিউ এবং রিস্টোর করুন",
+       "right-suppressrevision": "যেকোন ব্যবহারকারী থেকে পাতার নির্দিষ্ট সংশোধন দেখুন, আড়াল করুন এবং অ-আড়াল করুন",
+       "right-viewsuppressed": "সকল ব্যবহারকারীর জন্য লুকিয়াত সংশোধন প্রদর্শন কর",
        "right-suppressionlog": "ব্যক্তিগত লগ দেখাও",
        "right-block": "সম্পাদনা করতে কোনো ব্যবহারকারীকে বাঁধা দাও",
        "right-blockemail": "ই-মেইল পাঠাতে কোনো ব্যবহারকারীকে বাঁধা দাও",
        "recentchanges-legend-heading": "'''ব্যাখ্যামূলক বর্ণনা:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (আরও দেখুন [[Special:NewPages|নতুন পাতার তালিকা]])",
        "recentchanges-legend-plusminus": "(''±১২৩'')",
-       "rcnotefrom": "<strong>$2</strong>টা থেকে সংঘটিত পরিবর্তনগুলি (সর্বোচ্চ <strong>$1টি</strong> দেখানো হয়েছে)",
+       "rcnotefrom": "<strong>$2</strong>টা থেকে সংঘটিত পরিবর্তনগুলি (সর্বোচ্চ <strong>$1টি</strong> দেখানো হয়েছে)",
        "rclistfrom": "$2, $3 তারিখের পর সংঘটিত নতুন পরিবর্তনগুলো দেখাও",
        "rcshowhideminor": "অনুল্লেখ্য পরিবর্তনগুলো $1",
        "rcshowhideminor-show": "দেখাও",
        "largefileserver": "সার্ভারে যতখানি অনুমোদিত তার চেয়ে এই ফাইলের আকার বড়।",
        "emptyfile": "আপনি যে ফাইলটি আপলোড করেছেন, তা খালি মনে হচ্ছে। ফাইলের নামে টাইপিং ত্রুটির কারণে এরকম হতে পারে। অনুগ্রহ করে পরীক্ষা করে দেখুন আপনি আসলেই এই ফাইলটি আপলোড করতে চান কি না।",
        "windows-nonascii-filename": "এই উইকি বিশেষ ক্যারেক্টারসমৃদ্ধ ফাইলের নাম সমর্থন করে না।",
-       "fileexists": "এই নামের একটি ফাইল ইতিমধ্যেই বিদ্যমান অনুগ্রহ করে <strong>[[:$1]]</strong> পরীক্ষা করে দেখুন, যদি আপনি এটি পরিবর্তনের ব্যাপারে নিশ্চিত না হন। [[$1|thumb]]",
+       "fileexists": "এই নামের একটি ফাইল ইতিমধ্যেই বিদ্যমান, অনুগ্রহ করে <strong>[[:$1]]</strong> পরীক্ষা করে দেখুন, যদি আপনি এটি পরিবর্তনের ব্যাপারে নিশ্চিত না হন। [[$1|thumb]]",
        "filepageexists": "এই ফাইলের বর্ণনা পাতা এখানে <strong>[[:$1]]</strong> তৈরী করা হয়েছে, কিন্তু এই নামের কোনো ফাইল নেই।\nআপনার লেখা তথ্যগুলো বর্ণনা পাতায় যোগ করা যাচ্ছে না।\nতথ্যটি সংযোজনের জন্য আপনাকে ম্যানুয়ালী এই পাতাটি সম্পাদনা করতে হবে।\n[[$1|thumb]]",
-       "fileexists-extension": "à¦\8fà¦\95à¦\87 à¦¨à¦¾à¦®à§\87র à¦\86রà§\87à¦\95à¦\9fি à¦«à¦¾à¦\87ল à¦\86à¦\9bà§\87: [[$2|thumb]]\n* à¦\86পলà§\8bড à¦\95রা à¦«à¦¾à¦\87লà§\87র à¦¨à¦¾à¦®: <strong>[[:$1]]</strong>\n* à¦\8fà¦\95à¦\87 à¦¨à¦¾à¦®à§\87 à¦¬à¦°à§\8dতমান à¦«à¦¾à¦\87লà§\87র à¦¨à¦¾à¦®: <strong>[[:$2]]</strong>\nà¦\85নà§\81à¦\97à§\8dরহ à¦\95রà§\87 à¦\8fà¦\95à¦\9fি à¦­à¦¿à¦¨à§\8dন à¦¨à¦¾à¦® à¦ªà¦\9bনà§\8dদ à¦\95রà§\81ন।",
+       "fileexists-extension": "à¦\8fà¦\95à¦\87 à¦¨à¦¾à¦®à§\87র à¦\86রà§\87à¦\95à¦\9fি à¦«à¦¾à¦\87ল à¦\86à¦\9bà§\87: [[$2|thumb]]\n* à¦\86পলà§\8bড à¦\95রা à¦«à¦¾à¦\87লà§\87র à¦¨à¦¾à¦®: <strong>[[:$1]]</strong>\n* à¦\8fà¦\95à¦\87 à¦¨à¦¾à¦®à§\87 à¦¬à¦°à§\8dতমান à¦«à¦¾à¦\87লà§\87র à¦¨à¦¾à¦®: <strong>[[:$2]]</strong>\nà¦\86পনি à¦\95ি à¦\86রà§\8b à¦\8fà¦\95à¦\9fি à¦¸à§\8dবতনà§\8dতà§\8dর à¦¨à¦¾à¦® à¦¬à§\8dযবহার à¦\95রতà§\87 à¦\9aান?",
        "fileexists-thumbnail-yes": "ফাইলটি একটি সংক্ষেপিত আকারের ছবি ''(থাম্বনেইল)'' বলে মনে হচ্ছে। [[$1|thumb]]\nঅনুগ্রহ করে <strong>[[:$1]]</strong> ফাইলটি পরীক্ষা করে দেখুন।\nযদি পরীক্ষাকৃত ফাইলটি একই ছবির মূল আকার হয়, তবে একটি অতিরিক্ত থাম্বনেইল আপলোড করার প্রয়োজন নেই।",
        "file-thumbnail-no": "ফাইলের নামটি <strong>$1</strong> দিয়ে শুরু হয়েছে।\nমনে হচ্ছে এটি একটি সংকুচিত আকারের ছবি  ''(থাম্বনেইল)''।\nআপনার কাছে যদি পূর্ণ রেজোলিউশনের ছবিটি থাকে, তবে সেটি আপলোড করুন, নতুবা অনুগ্রহ করে ফাইলের নামটি পরিবর্তন করুন।",
        "fileexists-forbidden": "এই নামের একটি ফাইল ইতিমধ্যেই বিদ্যমান, এবং এটি প্রতিস্থাপনযোগ্য নয়।\nআপনি যদি এখনো ফাইলটি আপলোড করতে চান, তবে অনুগ্রহপূর্বক পেছনে গিয়ে একটি নতুন নামে ফাইলটি আপলোড করুন।\n[[File:$1|thumb|center|$1]]",
        "uploadwarning": "আপলোড সতর্কবাণী",
        "uploadwarning-text": "অনুগ্রহ করে নিচে ফাইলের বর্ণনা পরিবর্তন করে আবার চেষ্টা করুন।",
        "savefile": "সংরক্ষণ",
-       "uploadedimage": "\"[[$1]]\" আপলোড করা হয়েছে।",
-       "overwroteimage": "\"[[$1]]\"-এর একটি নতুন সংস্করণ আপলোড করা হয়েছে",
        "uploaddisabled": "আপলোড নিষ্ক্রিয় আছে",
        "copyuploaddisabled": "ইউআরএল এর মাধ্যমে আপলোড নিস্ক্রিয় রয়েছে।",
        "uploaddisabledtext": "ফাইল আপলোড নিষ্ক্রিয়।",
        "license": "লাইসেন্সকরণ:",
        "license-header": "লাইসেন্স প্রদান",
        "nolicense": "কিছুই নির্বাচন করা হয়নি",
+       "licenses-edit": "লাইসেন্স অপশন সম্পাদনা করুন",
        "license-nopreview": "(প্রাকদর্শন লভ্য নয়)",
-       "upload_source_url": " (একটি বৈধ, উন্মুক্ত URL)",
-       "upload_source_file": " (আপনার কম্পিউটারের একটি ফাইল)",
+       "upload_source_url": " (আপনি একটি বৈধ, উন্মুক্ত URL থেকে ফাইল চয়ন করেছেন)",
+       "upload_source_file": "(আপনার কম্পিউটারের একটি ফাইল)",
+       "listfiles-delete": "অপসারণ",
        "listfiles-summary": "এই বিশেষ পাতাটি আপলোড করা সকল ফাইল প্রদর্শন করে।",
        "listfiles_search_for": "ছবির নাম অনুসন্ধান:",
        "imgfile": "ফাইল",
        "filedelete-maintenance": "রক্ষণাবেক্ষণের সময় ফাইল অপরাসণ এবং পুনরুদ্ধার সাময়িকভাবে নিস্ক্রিয় রয়েছে।",
        "filedelete-maintenance-title": "ফাইলটি অপসারণ করা সম্ভব নয়",
        "mimesearch": "MIME অনুসন্ধান",
-       "mimesearch-summary": "এই পাতার মাধ্যমে MIME-ধরন অনুসারে ফাইলগুলিকে ফিল্টার করা যায়। ইনপুট: contenttype/subtype, যেমন <code>image/jpeg</code>।",
+       "mimesearch-summary": "এই পাতা তাদের MIME-এর ধরণের জন্য ফাইল ফিল্টার করা সক্ষম করে। ইনপুট: contenttype/subtype বা contenttype/*, উদা: <code>image/jpeg</code>।",
        "mimetype": "MIME ধরন:",
        "download": "ডাউনলোড",
        "unwatchedpages": "নজরে না রাখা পাতাগুলি",
        "randomincategory": "বিষয়শ্রেণীর অজানা যেকোনো পাতা",
        "randomincategory-invalidcategory": "\"$1\" একটি ত্রুটিপূর্ণ বিষয়শ্রেণীর নাম।",
        "randomincategory-nopages": "[[:Category:$1]]-এ কোন পাতা নেই।",
-       "randomincategory-selectcategory": "এই বিষয়শ্রেণীর একটি অজানা যেকোনো পাতা: $1 $2।",
-       "randomincategory-selectcategory-submit": "যাও",
+       "randomincategory-category": "বিষয়শ্রেণী:",
+       "randomincategory-legend": "বিষয়শ্রেণীর অজানা যেকোনো পাতা",
        "randomredirect": "অনির্ধারিত পুনর্নির্দেশ",
        "randomredirect-nopages": "\"$1\" এই নামস্থানে কোন পুনর্নির্দেশ নেই।",
        "statistics": "পরিসংখ্যান",
        "wantedtemplates": "আবশ্যিক টেম্পলেটগুলো",
        "mostlinked": "যেসব পাতার প্রতি সবচেয়ে বেশি সংযোগ আছে",
        "mostlinkedcategories": "যেসব বিষয়শ্রেণীর প্রতি সবচেয়ে বেশি সংযোগ আছে",
-       "mostlinkedtemplates": "যà§\87সব à¦\9fà§\87মপà§\8dলà§\87à¦\9fà§\87 à¦¸à¦¬à¦\9aà§\87য়à§\87 à¦¬à§\87শি à¦¸à¦\82যà§\8bà¦\97 à¦\86à¦\9bà§\87",
+       "mostlinkedtemplates": "সবà¦\9aà§\87য়à§\87 à¦¬à§\87শি à¦\85নà§\8dতরà§\8dভà§\81à¦\95à§\8dত à¦ªà¦¾à¦¤à¦¾",
        "mostcategories": "সবচেয়ে বেশী বিষয়শ্রেণী-সমৃদ্ধ নিবন্ধসমূহ",
        "mostimages": "যেসব ফাইলের দিকে সবচেয়ে বেশি সংযোগ আছে",
        "mostinterwikis": "সবচেয়ে বেশী ইন্টারউইকি লিংক-সমৃদ্ধ নিবন্ধসমূহ",
        "trackingcategories": "বিষয়শ্রেণীসমূহ অনুসরণ করা হচ্ছে",
        "trackingcategories-msg": "বিষয়শ্রেণী অনুসরণ করা হচ্ছে",
        "trackingcategories-name": "বার্তা নাম",
+       "broken-file-category-desc": "এই পাতায় একটি ভাঙ্গা ফাইলের লিঙ্ক রয়েছে (একটি ফাইল এম্বেড করার জন্য একটি লিঙ্ক যখন ফাইলটির অস্তিত্ব নেই)",
        "trackingcategories-nodesc": "কোন বর্ণনা নেই।",
        "trackingcategories-disabled": "বিষয়শ্রেণীটি বিকল",
        "mailnologin": "প্রাপকের ঠিকানা নেই",
        "mywatchlist": "নজর তালিকা",
        "watchlistfor2": "$1 ($2)-এর জন্য",
        "nowatchlist": "আপনার নজরতালিকা খালি।",
-       "watchlistanontext": "আপনার নজরতালিকার আইটেমগুলি দেখতে বা সম্পাদনা করতে অনুগ্রহ করে $1।",
+       "watchlistanontext": "আপনার নজরতালিকার আইটেমগুলি দেখতে বা সম্পাদনা করতে অনুগ্রহ করে প্রবেশ করুন।",
        "watchnologin": "আপনি এখনও লগ-ইন করেননি।",
        "addwatch": "নজরতালিকায় যোগ করো",
        "addedwatchtext": "\"[[:$1]]\" পাতাটি আপনার [[Special:Watchlist|নজরতালিকাতে]] যোগ করা হয়েছে।\nভবিষ্যতে এই পাতা ও এই পাতার সাথে সম্পর্কিত আলোচনা পাতায় সংঘটিত যাবতীয় পরিবর্তন এখানে তালিকাভুক্ত হবে।",
        "watchlist-details": "আপনার নজরতালিকাতে {{PLURAL:$1|$1টি পাতা}} আছে (আলাপ পাতাগুলি গণনায় না ধরে)।",
        "wlheader-enotif": "ইমেল বিজ্ঞপ্তি সক্রিয় করা আছে।",
        "wlheader-showupdated": "আপনার শেষ আগমনের পর থেকে যেসব পাতায় পরিবর্তন হয়েছে সেগুলি '''গাঢ়''' করে দেখানো হয়েছে।",
-       "wlnote2": "$3, $2 অনুসারে, সর্বশেষ {{PLURAL:$1|ঘণ্টার|<strong>$1</strong> ঘণ্টার}} পরিবর্তন নিচে দেয়া হয়েছে।",
+       "wlnote": "নিচে $3, $4 তারিখ থেকে বিগত {{PLURAL:$2|১ ঘন্টায়|<strong>$2</strong> ঘন্টায়}} সংঘটিত {{PLURAL:$1|শেষ ১টি পরিবর্তন|শেষ <strong>$1টি</strong> পরিবর্তন}} দেখানো হল।",
        "wlshowlast": "দেখাও সর্বশেষ  $1 ঘণ্টা $2 দিন $3",
        "watchlist-options": "নজর তালিকা পছন্দসমূহ",
        "watching": "নজর রাখা হচ্ছে...",
        "exbeforeblank": "মুছে ফেলার আগে বিষয়বস্তু ছিল: '$1'",
        "delete-confirm": "\"$1\" অপসারণ",
        "delete-legend": "অপসারণ",
-       "historywarning": "'''সতর্কীকরণ:''' যে পাতাটি আপনি মুছে ফেলতে যাচ্ছেন তার ইতিহাসে প্রায় $1টি {{PLURAL:$1|সংশোধন}} রয়েছে:",
+       "historywarning": "<strong>সতর্কীকরণ:</strong> যে পাতাটি আপনি মুছে ফেলতে যাচ্ছেন তার ইতিহাসে প্রায় $1টি {{PLURAL:$1|সংশোধন}} রয়েছে:",
        "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}} সাইটের ডেটাবেজ সমস্যার কারণ হতে পারে;\nসাবধানতার সাথে এগিয়ে যান।",
+       "deleteprotected": "আপনি এই পাতাটি মুছে ফেলতে পারবেন না কারণ এটি সুরক্ষিত করা হয়েছে।",
        "deleting-backlinks-warning": "'''সতর্কীকরণ:''' আপনি যেটি মুছে ফেলতে যাচ্ছেন তা [[Special:WhatLinksHere/{{FULLPAGENAME}}|অন্যান্য পাতাসমূহে]] সংযুক্ত অথবা অন্তর্ভুক্ত রয়েছে।",
        "rollback": "সম্পাদনা ফিরিয়ে নিন",
        "rollback_short": "ফিরিয়ে নিন",
        "autoblockid": "স্বয়ংক্রিয় বাধা #$1",
        "block": "ব্যবহারকারীকে বাধা দাও",
        "unblock": "ব্যবহারকারীর উপর থেকে বাধা অপসারণ",
-       "blockip": "ব্যবহারকারীকে বাধা দাও",
+       "blockip": "{{GENDER:$1|ব্যবহারকারীকে}} বাধা দাও",
        "blockip-legend": "ব্যবহারকারীকে বাধা দেওয়া হোক",
        "blockiptext": "কোন নির্দিষ্ট আইপি ঠিকানা বা ব্যবহারকারীর লেখার অধিকারে বাধা দিতে নিচের ফর্মটি ব্যবহার করুন।\nএটি কেবলমাত্র ধ্বংসপ্রবণতা প্রতিরোধে ও [[{{MediaWiki:Policy-url}}|নীতিমালা]] মেনে সম্পাদন করা উচিত।\nনিচে একটি নির্দিষ্ট কারণ দিন (উদাহরণস্বরূপ, যেসব পাতার ধ্বংসসাধন করা হয়েছে, সেগুলি উল্লেখ করতে পারেন)।",
        "ipaddressorusername": "আইপি ঠিকানা বা ব্যবহারকারীর নাম:",
        "ipb-unblock-addr": "$1-এর উপর থেকে বাধা তুলে নেওয়া হোক",
        "ipb-unblock": "ব্যবহারকারী বা আইপি ঠিকানার উপর থেকে বাধা তুলে নেওয়া হোক",
        "ipb-blocklist": "বিদ্যমান বাধাগুলি দেখুন",
-       "ipb-blocklist-contribs": "$1 এর অবদানসমূহ",
+       "ipb-blocklist-contribs": "{{GENDER:$1|$1}}-এর অবদানসমূহ",
        "unblockip": "ব্যবহারকারীর উপর থেকে বাধা তুলে নেওয়া হোক",
        "unblockiptext": "নিচের ফর্মটি ব্যবহার করে পূর্বে বাধা দেওয়া কোন আইপি ঠিকানা বা ব্যবহারকারীর সাইটে লেখার অধিকার পুনঃপ্রতিষ্ঠা করুন।",
        "ipusubmit": "বাধা তুলে নেওয়া হোক",
        "nonfile-cannot-move-to-file": "কোনো ফাইলনয় এমন কোনো পাতা ফাইল নামস্থানে স্থানান্তর সম্ভব নয়",
        "imagetypemismatch": "নতুন ফাইল এক্সটেনশনটি ফাইলের ধরনের সাথে মিলছে না",
        "imageinvalidfilename": "ফাইল নামটি সঠিক নয়",
-       "fix-double-redirects": "মà§\82ল à¦¶à¦¿à¦°à¦¨à¦¾à¦®à¦\95à§\87 à¦¨à¦¿à¦°à§\8dদà§\87শ à¦\95রà§\87 à¦\8fমন à¦¸à¦\95ল à¦°à¦¿à¦¡à¦¾à¦\87রà§\87à¦\95à§\8dà¦\9f à¦\86পডà§\87à¦\9f করুন",
+       "fix-double-redirects": "মà§\82ল à¦¶à¦¿à¦°à¦¨à¦¾à¦®à¦\95à§\87 à¦¨à¦¿à¦°à§\8dদà§\87শ à¦\95রà§\87 à¦\8fমন à¦¸à¦\95ল à¦ªà§\81নরà§\8dনিরà§\8dদà§\87শ à¦¹à¦¾à¦²à¦¨à¦¾à¦\97াদ করুন",
        "move-leave-redirect": "পুনর্নির্দেশ রেখে দিন",
        "protectedpagemovewarning": "'''সতর্কীকরণ:''' এই পাতাটি বন্ধ করা হয়েছে; কেবলমাত্র প্রশাসক মর্যাদার ব্যবহারকারীরাই এটি স্থানান্তর করতে পারবেন।\nআপনার সুবিধার্থে পাতাটির সাম্প্রতিক সংরক্ষণ লগের বিবরণ নিচে দেওয়া হলো।",
        "semiprotectedpagemovewarning": "'''নোট:''' এই পাতাটির ব্যবহার নিয়ন্ত্রণ করা হয়েছে তাই নিবন্ধনকৃত ব্যবহারকারী এটি স্থানান্তর করতে পারবেন।\nআপনার সুবিধার্থে পাতাটির সাম্প্রতিক সংরক্ষণ লগের বিবরণ নিচে দেওয়া হলো:",
        "import": "পাতা আমদানি",
        "importinterwiki": "আন্তঃউইকি আমদানি",
        "import-interwiki-text": "আমদানির জন্য একটি উইকি ও পাতার শিরোনাম নির্বাচন করুন।\nসংশোধনের তারিখগুলি এবং সম্পাদকদের নামগুলি সংরক্ষণ করা হবে।\nসমস্ত আন্তঃউইকি আমদানিগুলি [[Special:Log/import|আমদানি লগে]] লিপিবদ্ধ আছে।",
-       "import-interwiki-source": "উৎস উইকি/পাতা:",
+       "import-interwiki-sourcewiki": "উত্স উইকি:",
+       "import-interwiki-sourcepage": "উৎস পাতা:",
        "import-interwiki-history": "এই পাতার সমস্ত ইতিহাসের সংস্করণের অনুলিপি করা হোক",
        "import-interwiki-templates": "সকল টেম্পলেট অন্তর্ভুক্ত",
        "import-interwiki-submit": "আমদানি",
        "import-upload": "XML ডাটা আপলোড",
        "import-token-mismatch": "সেশন ডাটা হারিয়ে গিয়েছে।\nঅনুগ্রহ করে পুনরায় চেষ্টা করুন।",
        "import-invalid-interwiki": "নির্ধারিত উইকি থেকে আমদানী করা যাবে না।",
-       "import-error-edit": "\"$1\" à¦ªà¦¾à¦¤à¦¾à¦\9fি à¦\87মà§\8dপà§\8bরà§\8dà¦\9f করা যায়নি কারণ আপনার এটি সম্পাদনা করার অনুমতি নেই।",
+       "import-error-edit": "\"$1\" à¦ªà¦¾à¦¤à¦¾à¦\9fি à¦\86মদানি করা যায়নি কারণ আপনার এটি সম্পাদনা করার অনুমতি নেই।",
        "import-error-create": "\"$1\" পাতাটি ইম্পোর্ট করা যায়নি কারণ আপনার এটি তৈরী করার অনুমতি নেই।",
        "import-error-interwiki": "\"$1\" পাতাটি ইম্পোর্ট করা যায়নি কারণ এই নামটি বহিঃসংযোগর জন্য নির্ধারিত (ইন্টারউইকি)।",
-       "import-error-special": "\"$1\" à¦ªà¦¾à¦¤à¦¾à¦\9fি à¦\87মà§\8dপà§\8bরà§\8dà¦\9f করা যায়নি কারণ এটি একটি বিশেষ নামস্থানকে নির্দেশ করে যেটি সম্পাদনার জন্য অনুমোদিত নয়।",
+       "import-error-special": "\"$1\" à¦ªà¦¾à¦¤à¦¾à¦\9fি à¦\86মদানি করা যায়নি কারণ এটি একটি বিশেষ নামস্থানকে নির্দেশ করে যেটি সম্পাদনার জন্য অনুমোদিত নয়।",
        "import-error-invalid": "\"$1\" পাতাটি ইম্পোর্ট করা যায়নি কারণ নামটি সঠিক নয়।",
        "import-error-unserialize": "$1 পাতার $2 সংস্করণটি সিরিয়ালাইজ করা যাচ্ছে না। এই রিভিশনে $4 হিসাবে $3 কন্টেন্ট মডেলে সিরিয়ালাইজ করা আছে।",
        "import-options-wrong": "ভুল {{PLURAL:$2|অপশন|অপশনসমূহ}}: <nowiki>$1</nowiki>",
        "importlogpage": "আমদানি লগ",
        "importlogpagetext": "প্রশাসক কর্তৃক অন্যান্য উইকি থেকে সম্পাদনা ইতিহাসসহ পাতা আমদানি।",
        "import-logentry-upload": "ফাইল আপলোডের মাধ্যমে [[$1]] আমদানি করা হয়েছে",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|টি সংশোধন|টি সংশোধন}}",
+       "import-logentry-upload-detail": "$1টি {{PLURAL:$1|সংশোধন}} আমদানি করা হয়েছে",
        "import-logentry-interwiki": "$1 উইকি-স্থানান্তরিত",
-       "import-logentry-interwiki-detail": "$2-à¦\8fর à¦\95রা $1 {{PLURAL:$1|সà¦\82শà§\8bধন|à¦\9fি à¦¸à¦\82শà§\8bধন}}",
+       "import-logentry-interwiki-detail": "$2-à¦\8fর à¦¥à§\87à¦\95à§\87 $1à¦\9fি {{PLURAL:$1|সà¦\82শà§\8bধন}} à¦\95রা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87",
        "javascripttest": "জাভাস্ক্রিপ্ট পরীক্ষা",
        "javascripttest-title": "$1 পরীক্ষা চলছে",
        "javascripttest-pagetext-noframework": "এই পাতাটি জাভাস্ক্রিপ্ট পরীক্ষার জন্য সংরক্ষিত।",
        "mediawarning": "'''সতর্কীকরণ''': এই ফাইলের ধরনে ক্ষতিকর কোড থাকতে পারে। এটি চালালে আপনার সিস্টেমে ক্ষতি হতে পারে।",
        "imagemaxsize": "ছবির আকারের সর্বোচ্চ সীমা:<br />''(ছবির বিবরণ পাতার জন্য)''",
        "thumbsize": "থাম্বনেইল আকার:",
-       "widthheightpage": "$1 × $2, $3 {{PLURAL:$1|পাতাট|পাতাগুলো}}",
+       "widthheightpage": "$1 × $2, $3টি {{PLURAL:$1|পাতা}}",
        "file-info": "ফাইলের আকার: $1, MIME ধরণ: $2",
        "file-info-size": "$1 × $2 পিক্সেল, ফাইলের আকার: $3, এমআইএমই ধরণ: $4",
        "file-info-size-pages": "$1 × $2 পিক্সেল, fফাইলের আকার: $3, MIME ধরন: $4, $5 {{PLURAL:$5|পাতা|পাতাসমূহ}}",
        "autosumm-replace": "পাতাকে '$1' দিয়ে প্রতিস্থাপিত করা হল",
        "autoredircomment": "[[$1]]-এ পুনর্নির্দেশ করা হল",
        "autosumm-new": "$1 দিয়ে তৈরি পাতা",
+       "autosumm-newblank": "খালি পাতা তৈরি হয়েছে",
        "size-bytes": "$1 বাইট",
        "size-kilobytes": "$1 কিলোবাইট",
        "size-megabytes": "$1 মেগাবাইট",
        "logentry-rights-rights": "$1 ব্যবহারকারী, $3 এর দলগত সদস্যপদ $4 থেকে $5 এ {{GENDER:$2|পরিবর্তন}} করেছেন",
        "logentry-rights-rights-legacy": "$1 দলের সদস্যপদ পরিবর্তন করেছেন {{GENDER:$2|changed}} এর জন্য $3",
        "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|আপলোড করেছেন}}",
        "rightsnone": "(কিছু নাই)",
        "feedback-bugornote": "কারিগরী ত্রুটির বিস্তারিত বর্ণনা জানতে [$1 বাগ রিপোর্ট করুন]।\nঅথবা নিচের এই সরল ফর্মটি ব্যবহার করতে পারেন। \"[$3 $2]\" পাতায় আপনার ব্যবহারকারী নাম সহ মন্তব্যটি প্রকাশিত হবে।",
        "feedback-subject": "বিষয়:",
        "expand_templates_remove_nowiki": "ফলাফলে <nowiki> ট্যাগগুলো বাতিল করো",
        "expand_templates_generate_xml": "XML পার্স বৃক্ষ দেখাও",
        "expand_templates_generate_rawhtml": "এইচটিএমএল দেখাও",
-       "expand_templates_preview": "প্রাকদর্শন"
+       "expand_templates_preview": "প্রাকদর্শন",
+       "pagelanguage": "পাতার ভাষা নির্বাচক",
+       "pagelang-name": "পাতা",
+       "pagelang-language": "ভাষা",
+       "pagelang-use-default": "ডিফল্ট ভাষা ব্যবহার করুন",
+       "pagelang-select-lang": "ভাষা নির্বাচন করুন",
+       "right-pagelang": "পাতার ভাষা পরিবর্তন করুন",
+       "action-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 (সক্রিয় করা)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''নিষ্ক্রিয় করা''')"
 }
index 7b5d255..434232e 100644 (file)
        "talkpagelinktext": "གཏམ་གླེང།",
        "specialpage": "དམིགས་གསལ་ཤོག་ངོས།",
        "personaltools": "སྒེར་ཀྱི་ལག་ཆ།",
-       "postcomment": "སྡེ་ཚན་གསར་བ།",
        "articlepage": "ནང་དོན་ཤོག་ངོས་ལ་ལྟ་བ།",
        "talk": "གྲོས་བསྡུར།",
        "views": "ལྟ་ཞིབ།",
        "illegal-filename": "ཡིག་ཆའི་མིང་འདི་ལ་ཆོག་མཆན་མི་འདུག",
        "uploadwarning": "ཡར་འཇུག་སྔོན་བརྡ།",
        "savefile": "ཡིག་ཆ་ཉོར་ཅིག",
-       "uploadedimage": "\"[[$1]]\"ཡར་འཇུག་བྱས་ཟིན།",
        "uploaddisabled": "ཡར་འཇུག་ནུས་མེད་བཟོས་འདུག",
        "watchthisupload": "ཡིག་ཆ་འདི་ལ་གཟིགས།",
        "license": "གན་རྒྱ་ནང་ཞུགས་པ།",
index 6358b2d..3da2377 100644 (file)
        "talkpagelinktext": "য়্যারি",
        "specialpage": "বিশেষ পাতাহান",
        "personaltools": "নিজস্ব আতিয়ার",
-       "postcomment": "নুৱা অনুচ্ছেদহান",
        "articlepage": "নিবন্ধ চেইক",
        "talk": "য়্যারী",
        "views": "চা",
        "externaldberror": "ডাটেবেজর মা বেসেপ আহান ইসে নাইলে তরতা বারেদের একাউন্ট বদালানির য়্যাথাং নেই।",
        "login": "হমানি",
        "nav-login-createaccount": "লগইন / একাউন্ট খুল",
-       "loginprompt": "তি যেসাদেউ হমাসি {{SITENAME}} পাতা এহানর কুকিসর য়্যাথাঙ দে।",
        "userlogin": "হমানি / নৱা একাউন্ট খুলানি",
        "userloginnocreate": "লগইন",
        "logout": "নিকুলানি",
        "searchprofile-advanced-tooltip": "নিজর লেপকরা নাঙথাকে বিসারা",
        "search-result-size": "$1 ({{PLURAL:$2|1 ৱাহি|$2 ৱাহিহানি}})",
        "search-result-category-size": "{{PLURAL:$1 | 1 সদস্য | $1 সদস্যগি}} ({{PLURAL:$2 | 1 উপবিষয়থাকহানি | $2 হান}}, {{PLURAL:$3 | 1 ফাইল | $3 ফাইল}})",
-       "search-result-score": "মান্নপা $1%",
        "search-redirect": "(বারোআলথক $1)",
        "search-section": "(অনুচ্ছেদ $1)",
        "search-suggest": "তি হয়ত মাতানি চারতা: $1",
        "illegalfilename": "\"$1\" ফাইলর নাঙহাত থকনেই মেয়েক মিহিসে যেতা  পাতাহার চিঙনাঙে বরানি নাকরব।\nআরাক নুৱা নাঙ আহান দিয়া কাকর।",
        "badfilename": "ফাইলগর নাঙহান পতিয়া $1\" করানি ইল।",
        "savefile": "ফাইল ইতু",
-       "uploadedimage": "আপলোডকরানি অইল \"[[$1]]\"",
        "upload-source": "ফাইলর উৎস",
        "upload-options": "আপলোডর পছনহানি",
        "watchthisupload": "ফাইলগ খিয়ালে থ",
index 4cbfc49..0203515 100644 (file)
@@ -6,18 +6,18 @@
                        "GerardM",
                        "Huji",
                        "Meno25",
-                       "Mogoeilor"
+                       "Mogoeilor",
+                       "아라"
                ]
        },
        "tog-underline": "لینکهای خط به زیر",
        "tog-hideminor": "من ته نبیدن تغییرات کوچیک",
-       "tog-extendwatchlist": "Ú¯Ù¾ Ú©Ø±Ø¯Ù\86 Ù\84Û\8cستÙ\87اÛ\8c Ù\85Ù\86 ØªÙ\87 Ø³Û\8c Ø¯Û\8cدÙ\86 Ù\87Ù\85Ù\87 ØªØºÛ\8cÛ\8cراتÛ\8c Ú©Ù\87 Ø§Ø¨Ù\88Ù\87",
+       "tog-extendwatchlist": "Ú¯Ù¾ Ú©Ø±Ø¯Ù\86 Ù\86Ù\88Ù\85 Ú¯Ù\87 Ø¢ Ù\85Ù\88 Ø³Û\8c Ø¯Û\8cئÙ\86 Ù\87Ù\85Ù\87 Ø¢Ù\84شتا Ù\86Ù\87 Ù\81Ù\82Ø· Ù\87Ù\88Ù\86Ù\88 Ú©Ù\87 Ø¨Û\8cشتر Ø² Ù\87Ù\85Ù\87 Ø§Ù\86جÙ\88Ù\85 Ø§Ø¨Ù\88Ù\86.",
        "tog-usenewrc": "گپ کردن تغییرات آخری - جاوااسکریپت",
        "tog-numberheadings": "شماره وندن خودکار سی سرخط ها",
        "tog-showtoolbar": "نشو دادن تغییرات  تولبار  یا   جای نشودادن ابزارها- جاوااسکریپت",
        "tog-editondblclick": "اصلاح صفحات با دوبار کلیک - جاوااسکریپت",
        "tog-editsectiononrightclick": "امکان اصلاح یه قسمت زه راه راست کلیک کردن رو عنوان  اوقسمت- جاوااسکریپت",
-       "tog-rememberpassword": "به حافظه کامپیوتر دادن نحوه ورودی خوم (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "tog-watchcreations": "اضاف کردن اوصفحاتی که خوم درست کردم به فهرست نمایشی",
        "tog-watchdefault": "اضاف کردن اوصفحاتی که خوم اصلاح کردم به فهرست نمایشی",
        "tog-watchmoves": "اضاف کردن صفحاتی که خوم جابجا کردم به فهرست نمایشی",
        "talkpagelinktext": "صحبت",
        "specialpage": "صفحه مخصوص",
        "personaltools": "ابزارهای شخصی",
-       "postcomment": "ارسال یک توضیح",
        "articlepage": "دیدن صفحه محتوا",
        "talk": "بحث",
        "views": "مشاهدات",
        "remembermypassword": "رمز اویدن به سیستم را دراین رایانه به خاطر بسپار (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "login": "اویدن به سیستم",
        "nav-login-createaccount": "اویدن به سیستم",
-       "loginprompt": "ایسا وا کوکی ها رافعال کنین سی اویدن به  {{SITENAME}}.",
        "userlogin": "اویدن به سیستم / درست کردن حساب کاربری",
        "logout": "رهدن زه سیستم",
        "userlogout": "رهدن زه سیستم",
        "recentchanges": "تغییرات اخیر",
        "recentchanges-feed-description": "ردیابی آخرین تغییرات  ویکی در ای خورد",
        "rcnotefrom": "در زیر تغییرات زه تاریخ <b>$2</b> آمده‌اند (تا <b>$1</b> مورد نشو داده ابوه).",
-       "rclistfrom": "نشودادن تغییرات تازه با شروع زه $1",
+       "rclistfrom": "نشودادن تغییرات تازه با شروع زه $3 $2",
        "rcshowhideminor": "اصلاحات کوچیک $1",
        "rcshowhidebots": "$1 ربات‌ها یا بوتها",
        "rcshowhideliu": "$1 کاربران داخل وابیده",
        "upload": "آپلود فایل",
        "uploadbtn": "آپلود فایل",
        "uploadlogpage": "نمایه آپلود",
-       "uploadedimage": "آپلود وابید \"[[$1]]\"",
        "listfiles": "لیست فایل",
        "file-anchor-link": "فایل",
        "filehist": "گزارش تاریخی فایل",
        "log": "نمایه ها",
        "all-logs-page": "همه نمایه ها",
        "allpages": "همه صفحات",
-       "alphaindexline": "$1 به\n$2",
        "nextpage": "صفحه بعدی ($1)",
        "prevpage": "صفحه قبلی($1)",
        "allpagesfrom": "نمایش دادن صفحات با شروع زه:",
index 0198e96..c528646 100644 (file)
        "hidden-category-category": "Rummadoù kuzhet",
        "category-subcat-count": "{{PLURAL:$2|N'eus er rummad-mañ nemet an isrummad da-heul.|{{PLURAL:$1|isrummad|$1 isrummad}} zo d'ar rummad-mañ diwar un hollad a $2.}}",
        "category-subcat-count-limited": "Er rummad-mañ e kaver an {{PLURAL:$1|isrummad-se|$1 isrummadoù-se}}.",
-       "category-article-count": "{{PLURAL:$2|N'eus er rummad-mañ nemet ar bajenn da-heul.|Emañ ar {{PLURAL:$1|bajenn da-heul|$1 pajenn da-heul}} er rummad-mañ, diwar un hollad a $2.}}",
-       "category-article-count-limited": "{{PLURAL:$1|Emañ ar bajenn|Emañ an $1 pajenn}} da-heul er rummad-mañ.",
+       "category-article-count": "{{PLURAL:$2|N'eus er rummad-mañ nemet ar bajenn da-heul.|Emañ {{PLURAL:$1|ar bajenn da-heul|an/ar $1 pajenn da-heul}} er rummad-mañ, diwar un hollad a $2.}}",
+       "category-article-count-limited": "{{PLURAL:$1|Emañ ar bajenn|Emañ an/ar $1 pajenn}} da-heul er rummad-mañ.",
        "category-file-count": "{{PLURAL:$2|N'eus er rummad-mañ nemet ar restr da-heul.|Emañ ar {{PLURAL:$1|restr|$1 restr}} da-heul er rummad-mañ, diwar un hollad a $2.}}",
        "category-file-count-limited": "{{PLURAL:$1|Emañ ar restr|Emañ an $1 restr}} da-heul er rummad-mañ.",
        "listingcontinuesabbrev": "(war-lerc'h)",
        "talkpagelinktext": "Kaozeal",
        "specialpage": "Pajenn dibar",
        "personaltools": "Ostilhoù personel",
-       "postcomment": "Rann nevez",
        "articlepage": "Sellet ouzh ar pennad",
        "talk": "Kaozeadenn",
        "views": "Gweladennoù",
        "otherlanguages": "Yezhoù all",
        "redirectedfrom": "(Adkaset eus $1)",
        "redirectpagesub": "Pajenn adkas",
-       "lastmodifiedat": "Kemmoù diwezhañ degaset d'ar bajenn-mañ, d'an $1 da $2.",
+       "redirectto": "Adkas da :",
+       "lastmodifiedat": "Kemmoù diwezhañ degaset d'ar bajenn-mañ, d'an/ar $1 da $2.",
        "viewcount": "Sellet ez eus bet {{PLURAL:$1|$1 wezh|$1 gwezh}} ouzh ar bajenn-mañ.",
        "protectedpage": "Pajenn warezet",
        "jumpto": "Mont da :",
        "jumptonavigation": "merdeiñ",
        "jumptosearch": "klask",
        "view-pool-error": "Ho tigarez, soulgarget eo ar servijerioù evit poent.\nRe a implijerien a glask mont war ar bajenn-mañ war un dro.\nGortozit ur pennadig a-raok klask mont war ar bjann-mañ en-dro.\n\n$1",
+       "generic-pool-error": "Ho tigarez, soulgarget eo ar servijerioù evit poent.\nRe a implijerien a glask mont war ar bajenn-mañ war un dro.\nGortozit ur pennadig a-raok klask mont war ar bajenn-mañ en-dro.",
        "pool-timeout": "Aet eur dreist d'an termen gortoz evit ar stankadenn",
        "pool-queuefull": "Soulgarget eo ar servijerioù",
        "pool-errorunknown": "Fazi dianav",
        "hidetoc": "kuzhat",
        "collapsible-collapse": "Pakañ",
        "collapsible-expand": "Dispakañ",
+       "confirmable-confirm": "Ha sur {{GENDER:$1|hoc'h}} ?",
+       "confirmable-yes": "Ya",
+       "confirmable-no": "Ket",
        "thisisdeleted": "Diskouez pe diziverkañ $1 ?",
        "viewdeleted": "Gwelet $1?",
        "restorelink": "{{PLURAL:$1|ur c'hemm diverket|$1 kemm diverket}}",
        "invalidtitle-knownnamespace": "Titl direizh gant an esaouenn anv \"$2\" hag an destenn \"$3\"",
        "invalidtitle-unknownnamespace": "Titl direizh gant an niverenn esaouenn anv $1 hag an destenn \"$2\" dianav",
        "exception-nologin": "N'oc'h ket kevreet",
-       "exception-nologin-text": "Ar bajenn-mañ pe an ober-mañ a c'houlenn e vefec'h kevreet er wiki-mañ.",
+       "exception-nologin-text": "Ar bajenn-mañ pe an ober-mañ a c'houlenn e vefec'h kevreet.",
        "exception-nologin-text-manual": "$1, mar plij, evit gallout mont d'ar bajenn-mañ pe ober an dra-mañ",
        "virus-badscanner": "Kefluniadur fall : skanner viruzoù dianav : ''$1''",
        "virus-scanfailed": "Skannadenn c'hwitet (kod $1)",
        "externaldberror": "Pe ez eus bet ur fazi gwiriekaat diavaez er bank titouroù pe n'oc'h ket aotreet da nevesaat ho kont diavaez.",
        "login": "Kevreañ",
        "nav-login-createaccount": "Krouiñ ur gont pe kevreañ",
-       "loginprompt": "Ret eo deoc'h bezañ gweredekaet an toupinoù a-benn gellout kevreañ ouzh {{SITENAME}}.",
        "userlogin": "Kevreañ / krouiñ ur gont",
        "userloginnocreate": "Kevreañ",
        "logout": "Digevreañ",
        "gotaccount": "Ur gont zo ganeoc'h dija ? '''$1'''.",
        "gotaccountlink": "Kevreañ",
        "userlogin-resetlink": "Ha disoñjet eo bet ho titouroù kevreañ ganeoc'h ?",
-       "userlogin-resetpassword-link": "Ankouaet ho peus ho ker-tremen ?",
+       "userlogin-resetpassword-link": "Ankouaet ho ker-tremen ganeoc'h ?",
        "userlogin-helplink2": "Skoazell evit kevreañ",
-       "userlogin-loggedin": "Kevreet oc'h dija evel {{GENDER:$1|$1}}.\nImplijit ar furmskrid amañ dindan evit kevreañ evel un implijer all.",
-       "userlogin-createanother": "Krouiñ ur gont all",
        "createacct-emailrequired": "Chomlec'h postel",
        "createacct-emailoptional": "Chomlec'h postel (diret)",
        "createacct-email-ph": "Skrivit ho chomlec'h postel",
        "parser-template-recursion-depth-warning": "Tizhet bevenn donder galvoù ar patromoù ($1)",
        "language-converter-depth-warning": "Aet eur en tu all d'ar vevenn amdreiñ yezhoù ($1)",
        "node-count-exceeded-category": "Pajennoù m'eur aet en tu all d'an niver a skoulmoù",
-       "node-count-exceeded-warning": "Pajenn a ya en tu all d'an niver a skoulmoù",
+       "node-count-exceeded-category-desc": "Mont a ra ar bajenn-mañ en tu all da gont uhelañ ar skoulmoù.",
+       "node-count-exceeded-warning": "Pajenn hag a ya en tu all d'an niver a skoulmoù",
        "expansion-depth-exceeded-category": "Pajennoù m'eur aet dreist d'an donder astenn",
        "expansion-depth-exceeded-warning": "Pajenn a ya dreist d'an donder astenn",
        "parser-unstrip-loop-warning": "Detektet ez eus bet ul lagadenn n'haller ket divontañ",
        "currentrev": "Stumm a-vremañ pe stumm red",
        "currentrev-asof": "Stumm red eus an $1",
        "revisionasof": "Stumm eus an $1",
-       "revision-info": "Stumm eus an $1 gant $2",
+       "revision-info": "Stumm eus an $1 gant $2$7",
        "previousrevision": "← Stumm kent",
        "nextrevision": "Stumm war-lerc'h →",
        "currentrevisionlink": "Gwelet ar stumm red",
        "shown-title": "Diskouez $1 {{PLURAL:$1|disoc'h|disoc'h}} dre bajenn",
        "viewprevnext": "Gwelet ($1 {{int:pipe-separator}} $2) ($3).",
        "searchmenu-exists": "'''Ur bajenn anvet\"[[:$1]]\" zo war ar wiki-mañ'''",
-       "searchmenu-new": "'''Krouiñ ar bajenn \"[[:$1]]\" war ar wiki-mañ !'''",
+       "searchmenu-new": "<strong>Krouiñ ar bajenn \"[[:$1]]\" war ar wiki-mañ !</strong> {{PLURAL:$2|0=|Gwelet ivez ar bajenn kavet gant ho klask.|Gwelet ivez disoc'hoù ar c'hlask.}}",
        "searchprofile-articles": "Pajennoù gant boued",
        "searchprofile-images": "Liesmedia",
        "searchprofile-everything": "Pep tra",
        "searchprofile-advanced-tooltip": "Klask en esaouennoù anv personelaet",
        "search-result-size": "$1 ({{PLURAL:$2|1 ger|$2 ger}})",
        "search-result-category-size": "{{PLURAL:$1|1|$1}} ezel ({{PLURAL:$2|1|$2}} is-rummad, {{PLURAL:$3|1|$3}} restr)",
-       "search-result-score": "Klotadusted : $1%",
        "search-redirect": "(adkas $1)",
        "search-section": "(rann $1)",
        "search-file-match": "(klotañ a ra gant endalc'had ar restr)",
        "searchrelated": "disoc'hoù kar",
        "searchall": "An holl",
        "showingresults": "Diskouez betek {{PLURAL:$1|'''1''' disoc'h|'''$1''' disoc'h}} o kregiñ gant #'''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|Disoc'h '''$1''' diwar '''$3'''|Disoc'hoù '''$1 - $2''' diwar '''$3'''}} evit '''$4'''",
        "search-nonefound": "An enklask-mañ ne zisoc'h war netra.",
        "powersearch-legend": "Klask araokaet",
        "powersearch-ns": "Klask en esaouennoù anv :",
        "powersearch-togglelabel": "Dibab :",
        "powersearch-toggleall": "An holl",
        "powersearch-togglenone": "Hini ebet",
+       "powersearch-remember": "Derc'hel soñj eus an diuzadenn evit klaskoù da zont",
        "search-external": "Klask diavaez",
        "searchdisabled": "<p>Diweredekaet eo bet an arc'hwel klask war an destenn a-bezh evit ur frapad rak ur samm re vras e oa evit ar servijer. Emichañs e vo tu d'e adlakaat pa vo ur servijer galloudusoc'h ganeomp. Da c'hortoz e c'hallit klask gant Google:</p>",
        "search-error": "Ur fazi a zo bet e-ser klask : $1",
        "preferences": "Penndibaboù",
        "mypreferences": "Penndibaboù",
        "prefs-edits": "Niver a zegasadennoù :",
-       "prefsnologintext2": "$1, mar plij, evit cheñch ho penndibaboù.",
+       "prefsnologintext2": "Kevreit evit cheñch ho penndibaboù, mar plij.",
        "prefs-skin": "Gwiskadur",
        "skin-preview": "Rakwelet",
        "datedefault": "Dre ziouer",
        "recentchanges-legend-heading": "'''Alc'hwez :'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (gwelet ivez [[Special:NewPages|roll ar pajennoù nevez]])",
        "rcnotefrom": "Setu aze roll ar c'hemmoù c'hoarvezet abaoe an <strong>$2</strong> (<strong>$1</strong> d'ar muiañ).",
-       "rclistfrom": "Diskouez ar c'hemmoù diwezhañ abaoe an $3 $2",
+       "rclistfrom": "Diskouez ar c'hemmoù diwezhañ abaoe an/ar $3 $2",
        "rcshowhideminor": "$1 ar c'hemmoù dister",
        "rcshowhideminor-show": "Diskouez",
        "rcshowhideminor-hide": "Kuzhat",
        "rcshowhidemine": "$1 ma c'hemmoù",
        "rcshowhidemine-show": "Diskouez",
        "rcshowhidemine-hide": "Kuzhat",
-       "rclinks": "Diskouez an $1 kemm diwezhañ c'hoarvezet e-pad an $2 devezh diwezhañ<br />$3",
+       "rclinks": "Diskouez an/ar $1 kemm diwezhañ c'hoarvezet e-pad an/ar $2 devezh diwezhañ.<br />$3",
        "diff": "diforc'h",
        "hist": "ist",
        "hide": "Kuzhat",
        "uploadwarning": "Kemenn diwall en ur ezporzhiañ",
        "uploadwarning-text": "Cheñchit deskrivadur ar restr a-is ha klaskit en-dro.",
        "savefile": "Enrollañ ar restr",
-       "uploadedimage": "\"[[$1]]\" enporzhiet",
-       "overwroteimage": "enporzhiet ur stumm nevez eus \"[[$1]]\"",
        "uploaddisabled": "Ho tigarez, diweredekaet eo bet kas ar restr-mañ.",
        "copyuploaddisabled": "Diweredekaet eo bet ar pellgargañ dre URL.",
        "uploaddisabledtext": "Diweredekaet eo an enporzhiañ restroù.",
        "license": "Aotre-implijout :",
        "license-header": "Aotre implijout",
        "nolicense": "Hini ebet diuzet",
+       "licenses-edit": "Aozañ dibarzhioù an aotre-implijout",
        "license-nopreview": "(Dibosupl rakwelet)",
        "upload_source_url": " (Un URL reizh a c'hall bezañ tizhet gant an holl)",
-       "upload_source_file": " (ur restr war hoc'h urzhiataer)",
+       "upload_source_file": " (ar restr ho peus dibabet en hoc'h urzhiataer)",
+       "listfiles-delete": "dilemel",
        "listfiles-summary": "Diskouez a ra ar bajenn dibar-mañ an holl restroù bet ezporzhiet.",
        "listfiles_search_for": "Klask anv ar skeudenn :",
        "imgfile": "restr",
        "randomincategory": "Ur bajenn dre zegouezh er rummad",
        "randomincategory-invalidcategory": "\"$1\" n'eo ket un anv rummad reizh.",
        "randomincategory-nopages": "N'eus pajenn ebet e [[:Category:$1]].",
-       "randomincategory-selectcategory": "Tapout ur bajenn dre zegouezh eus ar rummad : $1 $2.",
-       "randomincategory-selectcategory-submit": "Mont",
+       "randomincategory-category": "Rummad :",
+       "randomincategory-legend": "Ur bajenn dre zegouezh er rummad",
        "randomredirect": "Ur bajenn adkas dre zegouezh",
        "randomredirect-nopages": "N'eus pajenn adkas ebet en esaouenn anv \"$1\".",
        "statistics": "Stadegoù",
        "doubleredirects": "Adkasoù doubl",
        "doubleredirectstext": "Rollañ a ra ar bajenn-mañ ar pajennoù a adkas da bajennoù adkas all.\nWar bep linenn ez eus liammoù war-du pajennoù an adkas kentañ hag en eil adkas, hag ivez war-du pajenn-dal an eil adkas zo sañset bezañ ar pal \"gwirion\" a zlefe an adkas kentañ kas di.\nDiskoulmet eo bet an enmontoù <del>barrennet</del>.",
        "double-redirect-fixed-move": "Adanvet eo bet [[$1]], adkaset eo war-du [[$2]] bremañ",
-       "double-redirect-fixed-maintenance": "O reizhañ an adkas doubl adalek [[$1]] war-zu [[$2]].",
+       "double-redirect-fixed-maintenance": "O reizhañ ent emgefre an adkas doubl adalek [[$1]] war-zu [[$2]] en un trevell trezalc'h.",
        "double-redirect-fixer": "Reizher adkasoù",
        "brokenredirects": "Adkasoù torret",
        "brokenredirectstext": "Kas a ra an adkasoù-mañ da bajennoù n'eus ket anezho.",
        "wantedpages-badtitle": "Titl direizh er strollad disoc'hoù : $1",
        "wantedfiles": "Restroù a vank",
        "wantedfiletext-cat": "Ober a reer gant ar restroù da-heul koulskoude n'eus ket anezho. Gallout a reer rollañ kavlec'hioù diavaez ha pa vefe anezho. <del>Barrennet</del> e vo an holl falspozitivoù-se. Ouzhpenn-se emañ renablet an holl bajennoù zo enno restroù n'eus ket anezho e [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Implijet eo ar restroù-mañ, met n'eus ket anezho. Ouzhpenn-se, emañ ar pajennoù a enframm ar restroù er roll [[:$1]].",
        "wantedfiletext-nocat": "Ober a reer gant ar restroù da-heul koulskoude n'eus ket anezho. Gallout a reer rollañ kavlec'hioù diavaez ha pa vefe anezho. <del>Barrennet</del> e vo an holl falspozitivoù-se.",
+       "wantedfiletext-nocat-noforeign": "Implijet e vez ar restroù-mañ met n'eus ket anezho.",
        "wantedtemplates": "Patromoù a vank",
        "mostlinked": "Pajennoù dezho al liammoù niverusañ",
        "mostlinkedcategories": "Rummadoù dezho al liammoù niverusañ",
-       "mostlinkedtemplates": "Patromoù implijet ar muiañ",
+       "mostlinkedtemplates": "Pajennoù enframmet ar muiañ",
        "mostcategories": "Pennadoù rummatet ar muiañ",
        "mostimages": "Skeudennoù implijet ar muiañ",
        "mostinterwikis": "Pajennoù gant an niver brasañ a etrewikioù",
        "listgrouprights-addgroup-self-all": "Gallout a ra ouzhpennañ an holl strolladoù da gont an-unan",
        "listgrouprights-removegroup-self-all": "Gallout a ra tennañ kuit an holl strolladoù eus kont an-unan.",
        "listgrouprights-namespaceprotection-namespace": "Esaouenn anv",
+       "listgrouprights-namespaceprotection-restrictedto": "Gwir(ioù) hag a aotre an implijer da aozañ",
+       "trackingcategories": "Rummadoù evezhiañ",
+       "trackingcategories-msg": "Rummad evezhiañ",
        "trackingcategories-name": "Anv ar gemennadenn",
+       "broken-file-category-desc": "Er bajenn-mañ ez eus ul liamm restr torr (ul liamm da enframmañ ur restr pa n'eus ket eus ar restr-se).",
        "trackingcategories-nodesc": "N'eus deskrivadur ebet.",
        "trackingcategories-disabled": "Diweredekaet eo ar rummad",
        "mailnologin": "Chomlec'h ebet",
        "mywatchlist": "Ma roll evezhiañ",
        "watchlistfor2": "Evit $1 $2",
        "nowatchlist": "N'eus pennad ebet en ho roll evezhiañ.",
-       "watchlistanontext": "Ret eo deoc'h $1 evit gwelet pe kemmañ an elfennoù zo en ho roll evezhiañ.",
+       "watchlistanontext": "Ret eo deoc'h kevreañ evit gwelet pe aozañ an elfennoù a zo en ho roll evezhiañ.",
        "watchnologin": "Digevreet",
        "addwatch": "Ouzhpennañ d'ar roll evezhiañ",
        "addedwatchtext": "Ouzh ho [[Special:Watchlist|rollad evezhiañ]] eo bet ouzhpennet ar bajenn \"[[:$1]]\".\nAmañ e vo rollet ar c'hemmoù da zont evit ar bajenn-mañ hag ar bajenn gaozeal stag outi.",
        "unwatchthispage": "Paouez da evezhiañ",
        "notanarticle": "Pennad ebet",
        "notvisiblerev": "Stumm diverket",
-       "watchlist-details": "Lakaet hoc'h eus {{PLURAL:$1|$1 bajenn|$1 pajenn}} dindan evezh, anez kontañ ar pajennoù kaozeal.",
+       "watchlist-details": "Lakaet hoc'h eus {{PLURAL:$1|$1 bajenn|$1 a bajennoù}} war ho roll evezhiañ, anez kontañ ar pajennoù kaozeal.",
        "wlheader-enotif": "Gweredekaet eo ar c'has posteloù.",
        "wlheader-showupdated": "E '''tev''' emañ merket ar pajennoù bet kemmet abaoe ar wezh ziwezhañ hoc'h eus sellet outo",
+       "wlnote": "Setu aze {{PLURAL:$1|ar c'hemm diwezhañ|ar '''$1''' kemm diwezhañ}} c'hoarvezet e-kerzh an {{PLURAL:$2|eurvezh|'''$2''' eurvezh}} diwezhañ, d'an $3 da $4.",
        "wlshowlast": "Diskouez an $1 eurvezh $2 devezh diwezhañ $3",
        "watchlist-options": "Dibarzhioù ar roll evezhiañ",
        "watching": "Heuliet...",
        "exbeforeblank": "A-raok diverkañ e oa an endalc'had : '$1'",
        "delete-confirm": "Diverkañ \"$1\"",
        "delete-legend": "Diverkañ",
-       "historywarning": "'''Diwallit :''' Emaoc'h war-nes diverkañ ur bajenn dezhi un istor gant e-tro {{PLURAL:$1|adweladenn|adweladenn}} :",
+       "historywarning": "<strong>Diwallit :</strong> Emaoc'h war-nes diverkañ ur bajenn dezhi un istor gant {{PLURAL:$1|adweladenn}} :",
        "confirmdeletetext": "War-nes diverkañ da viken ur bajenn pe ur skeudenn eus ar bank roadennoù emaoc'h. Diverket e vo ivez an holl stummoù kozh stag outi.\nKadarnait, mar plij, eo mat an dra-se hoc'h eus c'hoant da ober, e komprenit mat an heuliadoù, hag e rit se diouzh ar [[{{MediaWiki:Policy-url}}]].",
        "actioncomplete": "Diverkadenn kaset da benn",
        "actionfailed": "Ober c'hwitet",
        "delete-edit-reasonlist": "Kemmañ a ra an abegoù diverkañ",
        "delete-toobig": "Bras eo istor ar bajenn-mañ, ouzhpenn $1 {{PLURAL:$1|stumm|stumm}} zo. Bevennet eo bet an diverkañ pajennoù a-seurt-se kuit da zegas reuz war {{SITENAME}} dre fazi .",
        "delete-warning-toobig": "Bras eo istor ar bajenn-mañ, ouzhpenn {{PLURAL:$1|stumm|stumm}} zo.\nDiverkañ anezhi a c'hallo degas reuz war mont en-dro diaz titouroù {{SITENAME}};\ntaolit evezh bras.",
+       "deleteprotected": "Ne c'hallit ket dilemel ar bajenn-mañ rak gwarezet eo bet.",
        "rollback": "disteuler ar c'hemmoù",
        "rollback_short": "Disteuler",
        "rollbacklink": "disteuler",
        "alreadyrolled": "Dibosupl eo disteuler ar c'hemm diwezhañ graet d'ar bajenn [[:$1]] gant [[User:$2|$2]] ([[User talk:$2|Kaozeal]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]);\nkemmet pe distaolet eo bet c'hoazh gant unan bennak all.\n\nAr c'hemm diwezhañ d'ar bajenn-mañ a oa bet graet gant [[User:$3|$3]] ([[User talk:$3|Kaozeal]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Diverradenn ar c'hemm a oa : \"''$1''\".",
        "revertpage": "Kemmoù distaolet gant [[Special:Contributions/$2|$2]] ([[User talk:$2|Kaozeal]]); adlakaet d'ar stumm diwezhañ a-gent gant [[User:$1|$1]]",
-       "revertpage-nouser": "Disteuler kemmoù un implijer kuzhet ha distreiñ d'ar stumm diwezhañ gant [[User:$1|$1]]",
+       "revertpage-nouser": "Disteuler kemmoù un implijer kuzhet ha distreiñ d'ar stumm diwezhañ gant an {{GENDER:$1|[[implijer :$1|$1]]}}",
        "rollback-success": "Disteuler kemmoù $1; distreiñ da stumm diwezhañ $2.",
        "sessionfailure-title": "Fazi dalc'h",
        "sessionfailure": "Evit doare ez eus ur gudenn gant ho talc'h;\nNullet eo bet an ober-mañ a-benn en em wareziñ diouzh an tagadennoù preizhañ.\nKlikit war \"kent\" hag adkargit ar bajenn oc'h deuet drezi; goude klaskit en-dro.",
        "autoblockid": "Emstankañ #$1",
        "block": "Stankañ an implijer",
        "unblock": "Distankañ an implijer",
-       "blockip": "Stankañ ur chomlec'h IP",
+       "blockip": "Stankañ an {{GENDER:$1|implijer|implijerez}}",
        "blockip-legend": "Stankañ an implijer",
        "blockiptext": "Grit gant ar furmskrid a-is evit stankañ ar moned skrivañ ouzh ur chomlec'h IP pe un implijer bennak.\nSeurt diarbennoù n'hallont bezañ kemeret nemet evit mirout ouzh ar vandalerezh hag a-du gant an [[{{MediaWiki:Policy-url}}|erbedadennoù ha reolennoù da heuliañ]].\nRoit a-is an abeg resis (o verkañ, da skouer, roll ar pajennoù bet graet gaou outo).",
        "ipaddressorusername": "Chomlec'h IP pe anv implijer",
        "blockipsuccesstext": "Stanket eo bet [[Special:Contributions/$1|$1]].<br />\nSellit ouzh [[Special:BlockList|roll ar chomlec'hioù IP ha kontoù stanket]] evit gwiriañ ar stankadennoù.",
        "ipb-blockingself": "Emaoc'h war-nes stankañ ac'hanoc'h hoc'h-unan ! Ha sur oc'h eo se a fell deoc'h ober ?",
        "ipb-confirmhideuser": "Emaoc'h war-nes stankañ un implijer ha gweredekaet hoc'h eus \"kuzhat an implijer\". Diverkañ a ra an dra-se anv an implijer en holl rolloù ha monedoù ar marilh.",
+       "ipb-confirmaction": "A'z oc'h sur e fell deoc'h ober an dra-se evit gwir, askit ar vaezienn \"{{int:ipb-confirm}}\" en traoñ.",
        "ipb-edit-dropdown": "Kemmañ an abegoù stankañ",
        "ipb-unblock-addr": "Distankañ $1",
        "ipb-unblock": "Distankañ un implijer pe ur chomlec'h IP",
        "cant-move-user-page": "Noc'h ket aotreet da adenvel pajennoù pennañ an implijerien (er-maez eus o ispajennoù).",
        "cant-move-to-user-page": "Noc'h ket aotreet da adenvel ur bajenn gant anv hini un implijer all (nemet un ispajenn e vefe).",
        "cant-move-category-page": "N'oc'h ket aotreet da zilec'hiañ pajennoù rummad.",
+       "cant-move-to-category-page": "N'oc'h ket aotreet da zilec'hiañ ur bajenn d'ur bajenn rummad.",
        "newtitle": "anv nevez",
        "move-watch": "Evezhiañ ar bajenn-mañ",
        "movepagebtn": "Adenvel ar pennad",
        "import": "Enporzhiañ pajennoù",
        "importinterwiki": "enporzhiadenn etrewiki",
        "import-interwiki-text": "Diuzit ur wiki hag ur bajenn da enporzhiañ.\nMiret e vo deiziadoù ar stummmoù hag anvioù an aozerien.\nMiret eo an holl enporzhiadennoù etrewiki e-barzh [[Special:Log/import|log an enporzhiadennoù]].",
-       "import-interwiki-source": "wiki ha pajennoù tarzh :",
+       "import-interwiki-sourcewiki": "Wiki mammenn :",
+       "import-interwiki-sourcepage": "Pajenn orin :",
        "import-interwiki-history": "Eilañ holl stummoù istor ar bajenn-mañ",
        "import-interwiki-templates": "Lakaat e-barzh an holl batromoù",
        "import-interwiki-submit": "Enporzhiañ",
        "import-error-create": "N'eo ket bet enporzhiet ar bajenn \"$1\" peogwir n'oc'h ket aotreet da grouiñ anezhi.",
        "import-error-interwiki": "Ne vez ket enporzhiet ar bajenn \"$1\" rak miret eo an anv evit liammoù diavaez (etrewiki).",
        "import-error-special": "Ne vez ket enporzhiet ar bajenn \"$1\" rak stag eo ouzh un esaouenn anv dibar na aotre ket pajennoù.",
-       "import-error-invalid": "Ne vez ket enporzhiet ar bajenn \"$1\" rak direizh eo hec'h anv.",
+       "import-error-invalid": "N'eo ket bet enporzhiet ar bajenn \"$1\" rak direizh e vefe hec'h anv er wiki-mañ.",
        "import-options-wrong": "{{PLURAL:$2|Dibab fall|Dibaboù fall}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "Pourchas a ra ar bennbajenn un titl n'eo ket reizh.",
        "import-rootpage-nosubpage": "Esaouenn anvioù \"$1\" eus ar bennpajenn ne aotre ket an ispajennoù.",
        "importlogpage": "Log an enporzhiadennoù",
        "importlogpagetext": "Enporzhiadennoù melestradurel eus pajennoù adal wikioù all gant istor ar c'hemmadennoù degaset enno.",
        "import-logentry-upload": "en/he deus enporzhiet (pellgarget) [[$1]]",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|stumm|stumm}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|adweladenn}} enporzhiet",
        "import-logentry-interwiki": "treuzwikiet $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|c'hemm|kemm}} abaoe $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|adweladenn}} enporzhiet eus $2",
        "javascripttest": "Amprouadenn JavaScript",
        "javascripttest-title": "Emeur o seveniñ $1 amprouadenn",
        "javascripttest-pagetext-noframework": "Miret eo ar bajenn-mañ evit amprouiñ JavaScript.",
        "newimages-summary": "Diskouez a ra ar bajenn dibar-mañ roll ar restroù diwezhañ bet enporzhiet.",
        "newimages-legend": "Sil",
        "newimages-label": "Anv ar restr (pe darn anezhi) :",
+       "newimages-showbots": "Diskouez an ezporzhiadennoù graet gant robotoù",
        "noimages": "Netra da welet.",
        "ilsubmit": "Klask",
        "bydate": "dre an deiziad anezho",
        "autosumm-replace": "Oc'h erlec'hiañ ar bajenn gant '$1'",
        "autoredircomment": "Adkas war-du [[$1]]",
        "autosumm-new": "Pajenn krouet gant : \"$1\"",
+       "autosumm-newblank": "Krouet eo bet ur bajenn c'houllo",
        "size-bytes": "$1 o",
        "size-kilobytes": "$1 Kio",
        "size-megabytes": "$1 Mio",
        "watchlistedit-raw-done": "Nevesaet eo bet ho roll evezhiañ.",
        "watchlistedit-raw-added": "Ouzhpennet ez eus bet {{PLURAL:$1|1 pajenn|$1 pajenn}} :",
        "watchlistedit-raw-removed": "Tennet ez eus bet {{PLURAL:$1|1 pajenn|$1 pajenn}} :",
+       "watchlistedit-clear-title": "Roll evezhiañ goulloet",
        "watchlistedit-clear-legend": "Diverkañ ar roll-evezhiañ",
+       "watchlistedit-clear-explain": "Lamet e vo an holl ditloù eus ho roll evezhiañ",
        "watchlistedit-clear-titles": "Titloù :",
+       "watchlistedit-clear-done": "Goulloet eo bet ho roll evezhiañ.",
+       "watchlistedit-clear-removed": "Dilamet ez eus bet {{PLURAL:$1|1 titl|$1 a ditloù}} :",
+       "watchlistedit-too-many": "Re a bajennoù zo da ziskwel amañ.",
        "watchlisttools-clear": "Diverkañ ar roll-evezhiañ",
        "watchlisttools-view": "Gwelet ar c'hemmoù degaset",
        "watchlisttools-edit": "Gwelet ha kemmañ ar roll evezhiañ",
        "version-hook-name": "Anv ar galv",
        "version-hook-subscribedby": "Termenet gant",
        "version-version": "($1)",
+       "version-no-ext-name": "[anv ebet]",
        "version-license": "Aotre-implijout MediaWiki",
        "version-ext-license": "Aotre-implijout",
        "version-ext-colheader-name": "Astenn",
+       "version-skin-colheader-name": "Gwiskadur",
        "version-ext-colheader-version": "Stumm",
        "version-ext-colheader-license": "Aotre-implijout",
        "version-ext-colheader-description": "Deskrivadur",
        "fileduplicatesearch-noresults": "N'eus bet kavet restr ebet anvet \"$1\".",
        "specialpages": "Pajennoù dibar",
        "specialpages-note-top": "Alc'hwez",
-       "specialpages-note": "* Pajennoù dibar boutin.\n* <span class=\"mw-specialpagerestricted\">Pajennoù dibar miret strizh.</span>\n* <span class=\"mw-specialpagecached\">Pajennoù dibar krubuilhet hepken (a c'hellfe bezañ re gozh).</span>",
+       "specialpages-note": "* Pajennoù dibar ordinal.\n* <span class=\"mw-specialpagerestricted\">Pajennoù dibar miret strizh.</span>",
        "specialpages-group-maintenance": "Rentaoù-kont trezalc'h",
        "specialpages-group-other": "Pajennoù dibar all",
        "specialpages-group-login": "Kevreañ / krouiñ ur gont",
        "logentry-newusers-byemail": "Krouet eo bet ar gont implijer $3 gant $1 ha kaset eo bet ar ger-tremen dre bostel",
        "logentry-newusers-autocreate": "{{GENDER:$2|Krouet}} eo bet kont $1 ent emgefre",
        "logentry-rights-autopromote": "$1 zo bet {{GENDER:$2|anvet}} ent emgefre a $4 da $5",
+       "logentry-upload-upload": "$1 {{GENDER:$2|en deus|he deus}} ezporzhiet $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|en deus|he deus}} ezporzhiet ur stumm nevez eus $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|en deus|he deus}} ezporzhiet $3",
        "rightsnone": "(netra)",
        "feedback-bugornote": "Ma'z oc'h prest da zeskrivañ ur gudenn deknikel dre ar munud e c'hallit [$1 kemenn un draen].\nA-hend-all e c'hallit ober gant ar furmskrid eeunaet dindan. Ouzhpennet e vo hoc'h evezhiadenn d'ar bajenn \"[$3 $2]\", a-gevret gant hoc'h anv implijer hag anv ar merdeer a rit gantañ.",
        "feedback-subject": "Danvez :",
        "expand_templates_generate_xml": "Gwelet ar gwezennadur XML",
        "expand_templates_generate_rawhtml": "Diskouez an HTML kriz",
        "expand_templates_preview": "Rakwelet",
+       "pagelanguage": "Diuzañ yezh ar bajenn",
        "pagelang-name": "Pajenn",
        "pagelang-language": "Yezh",
        "pagelang-use-default": "Implijout ar yezh dre ziouer",
        "pagelang-select-lang": "Dibab ar yezh",
-       "right-pagelang": "Cheñch yezh ar bajenn"
+       "right-pagelang": "Cheñch yezh ar bajenn",
+       "action-pagelang": "cheñch yezh ar bajenn",
+       "log-name-pagelang": "Cheñch yezh",
+       "log-description-pagelang": "Hemañ zo ur marilh eus ar c'hemmoù e pajenn ar yezhoù.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|en deus|he deus}} cheñchet yezh ar bajenn evit $3 eus $4 da $5.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (gweredekaet)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''diweredekaet''')"
 }
index 2795034..d7ada3a 100644 (file)
@@ -2,7 +2,8 @@
        "@metadata": {
                "authors": [
                        "Imdadb",
-                       "Southparkfan"
+                       "Southparkfan",
+                       "아라"
                ]
        },
        "sunday": "Yakşambe",
        "mytalk": "Kaná ítgap",
        "navigation": "Kasarşoní",
        "qbfind": "Paŧŧa",
-       "vector-action-addsection": "Púskun sarhál",
-       "vector-action-delete": "Mesa",
-       "vector-action-move": "Surif",
-       "vector-action-protect": "Rakk",
-       "vector-view-create": "Biná",
-       "vector-view-edit": "Radbadal",
-       "vector-view-history": "Lekav e ur",
-       "vector-view-view": "Xuán",
-       "vector-view-viewsource": "Bumpad e ur",
        "actions": "Amal ák",
        "namespaces": "Pin-jága ģák",
        "variants": "Badaldroşumk",
        "viewprevnext": "($1 {{int:pipe-separator}} $2) ($3) e ur",
        "searchmenu-new": "'''Dá Vikí ŧí \"[[:$1]]\" panna ná biná kar!'''",
        "searchprofile-articles": "Nivişt panna ģák",
-       "searchprofile-project": "Ráhşon o bunkárem panna ģák",
        "searchprofile-images": "Multimedia",
        "searchprofile-everything": "Ar giŕá",
        "searchprofile-advanced": "Xúŕt",
        "searchprofile-articles-tooltip": "$1 ŧí paŧŧa",
-       "searchprofile-project-tooltip": "$1 ŧí paŧŧa",
        "searchprofile-images-tooltip": "Fáil átekin paŧŧpol",
        "searchprofile-everything-tooltip": "Ģuŧŧ nivişt áteŧí paŧŧpol (ítgap ná panna ģáteton avár)",
        "search-result-size": "$1 ({{PLURAL:$2|1 laoz|$2 laoz}})",
        "search-nonefound": "Just aná icc kaŧŧiá allav",
        "powersearch-legend": "Xúŕt paŧŧopol",
        "powersearch-ns": "Pin-jága ģáteŧí paŧŧopol:",
-       "powersearch-redir": "Aŕsoká panna ģátá cirr e nişán et",
        "preferences": "Gicenk",
        "mypreferences": "Kaná gicenk",
        "yourrealname": "Aslí pin",
        "recentchanges-label-minor": "Dá cunko radbadal as e",
        "recentchanges-label-bot": "Dá xudkár asená dú án maroko radbadal as e",
        "rcnotefrom": "Şefko raddobadal ák '''$2''' án maroko ('''$1''' iskán páş o)",
-       "rclistfrom": "$1 án púskuná radbadal áke nişán et",
+       "rclistfrom": "$3 $2 án púskuná radbadal áke nişán et",
        "rcshowhideminor": "Cunká radbadal áte $1",
        "rcshowhidebots": "Boŧ áte $1",
        "rcshowhideliu": "Drustírástí kárband áte $1",
        "upload": "Fáil laggif",
        "uploadlogpage": "Laggifing ná hisáb",
        "filedesc": "Bungapp",
-       "uploadedimage": "\"[[$1]]\" laggifingá",
        "license": "Muxtárnáma",
        "license-header": "Muxtárnáma",
        "file-anchor-link": "Fáil",
        "booksources-go": "Ráím",
        "log": "Lekav",
        "allpages": "Ģuŧŧ panna ģák",
-       "alphaindexline": "$1 án $2 iskán",
        "prevpage": "Mustko panna ($1)",
        "allpagesfrom": "Dáŕaŧ biná maroká panna ģáte nişán et:",
        "allpagesto": "Dáŕaŧ esar maroká panna ģáte nişán et:",
index 0c30961..f84897d 100644 (file)
        "hidden-category-category": "Sakrivene kategorije",
        "category-subcat-count": "{{PLURAL:$2|Ova kategorija ima sljedeću podkategoriju.|Ova kategorija ima {{PLURAL:$1|sljedeću podkategoriju|sljedeće $1 podkategorije|sljedećih $1 podkategorija}}, od $2 ukupno.}}",
        "category-subcat-count-limited": "Ova kategorija sadrži {{PLURAL:$1|slijedeću $1 podkategoriju|slijedeće $1 podkategorije|slijedećih $1 podkategorija}}.",
-       "category-article-count": "{{PLURAL:$2|U ovoj kategoriji se nalazi $1 članak.|{{PLURAL:$1|Prikazan je $1 članak|Prikazana su $1 članka|Prikazano je $1 članaka}} od ukupno $2 u ovoj kategoriji.}}",
+       "category-article-count": "{{PLURAL:$2|U ovoj kategoriji nalazi se $1 članak.|{{PLURAL:$1|Prikazan je $1 članak|Prikazana su $1 članka|Prikazano je $1 članaka}} od ukupno $2 u ovoj kategoriji.}}",
        "category-article-count-limited": "{{PLURAL:$1|Slijedeća $1 stranica je|Slijedeće $1 stranice su|Slijedećih $1 stranica je}} u ovoj kategoriji.",
        "category-file-count": "{{PLURAL:$2|Ova kategorija ima slijedeću $1 datoteku.|{{PLURAL:$1|Prikazana je $1 datoteka|Prikazane su $1 datoteke|Prikazano je $1 datoteka}} u ovoj kategoriji, od ukupno $2.}}",
        "category-file-count-limited": "{{PLURAL:$1|Slijedeća $1 datoteka je|Slijedeće $1 datoteke su|Slijedećih $1 datoteka je}} u ovoj kategoriji.",
        "permalink": "Trajni link",
        "print": "Štampa",
        "view": "Pogled",
+       "view-foreign": "Vidi na $1",
        "edit": "Uredi",
+       "edit-local": "Uredi lokalni opis",
        "create": "Napravi",
+       "create-local": "Dodaj lokalni opis",
        "editthispage": "Uredite ovu stranicu",
        "create-this-page": "Napravi ovu stranicu",
        "delete": "Obriši",
        "talkpagelinktext": "Razgovor",
        "specialpage": "Posebna Stranica",
        "personaltools": "Lični alati",
-       "postcomment": "Nova sekcija",
        "articlepage": "Pogledaj članak",
        "talk": "Razgovor",
        "views": "Pregledi",
        "jumptonavigation": "navigacija",
        "jumptosearch": "traži",
        "view-pool-error": "Žao nam je, serveri su trenutno preopterećeni.\nPreviše korisnika pokušava da pregleda ovu stranicu.\nMolimo pričekajte trenutak prije nego što ponovno pokušate pristupiti ovoj stranici.\n\n$1",
+       "generic-pool-error": "Nažalost, serveri su trenutno preopterećeni.\nPreviše korisnika pokušava da vidi ovaj resurs.\nMolimo pričekajte trenutak prije nego što ponovo pokušate da mu pristupite.",
        "pool-timeout": "Zaustavi čekanje na zaključavanje",
        "pool-queuefull": "Red na pool je prenapunjen",
        "pool-errorunknown": "Nepoznata greška",
        "hidetoc": "sakrij",
        "collapsible-collapse": "sklopi",
        "collapsible-expand": "Proširi",
+       "confirmable-confirm": "Da li {{GENDER:$1|ste}} sigurni?",
+       "confirmable-yes": "Da",
+       "confirmable-no": "Ne",
        "thisisdeleted": "Pogledaj ili vrati $1?",
        "viewdeleted": "Pogledaj $1?",
        "restorelink": "{{PLURAL:$1|$1 izbrisana izmjena|$1 izbrisanih izmjena}}",
        "nospecialpagetext": "<strong>Tražili ste nevaljanu posebnu stranicu.</strong>\n\nSpisak valjanih posebnih stranica se može naći na [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Greška",
        "databaseerror": "Greška u bazi",
+       "databaseerror-text": "Došlo je do greške u upitu baze podataka. \nMožda je u pitanju softverska greška.",
+       "databaseerror-textcl": "Došlo je do greške u upitu baze podataka.",
+       "databaseerror-query": "Upit: $1",
        "databaseerror-function": "Funkcija: $1",
        "databaseerror-error": "Greška: $1",
        "laggedslavemode": "'''Upozorenje''': Stranica, možda, nije ažurirana.",
        "readonly": "Baza je zaključana",
        "enterlockreason": "Unesite razlog za zaključavanje, uključujući procjenu vremena otključavanja",
        "readonlytext": "Baza je trenutno zaključana za nove unose i ostale izmjene, vjerovatno zbog rutinskog održavanja, posle čega će biti vraćena u uobičajeno stanje.\n\nAdministrator koji ju je zaključao je ponudio ovo objašnjenje: $1",
-       "missing-article": "U bazi podataka nije pronađen tekst stranice tražen pod nazivom \"$1\" $2.\n\nDo ovoga dolazi kada se prati pomjeranje ili historija linka za stranicu koja je pobrisana.\n\n\nU slučaju da se ne radi o gore navedenom, moguće je da ste pronašli grešku u programu.\nMolimo Vas da ovo prijavite [[Special:ListUsers/sysop|administratoru]] sa navođenjem tačne adrese stranice",
+       "missing-article": "U bazi podataka nije pronađen tekst stranice tražen pod nazivom \"$1\" $2.\n\nDo ovoga dolazi kad se prati pomjeranje ili historija linka za stranicu koja je pobrisana.\n\n\nU slučaju da se ne radi o gore navedenom moguće je da ste pronašli grešku u programu.\nMolimo Vas da ovo prijavite [[Special:ListUsers/sysop|administratoru]] s navođenjem tačne adrese stranice.",
        "missingarticle-rev": "(revizija#: $1)",
        "missingarticle-diff": "(Razlika: $1, $2)",
        "readonly_lag": "Baza podataka je zaključana dok se sekundarne baze podataka na serveru ne sastave sa glavnom.",
        "unexpected": "Neočekivana vrijednost: \"$1\"=\"$2\".",
        "formerror": "Greška: ne može se poslati upitnik",
        "badarticleerror": "Ova akcija ne može biti izvršena na ovoj stranici.",
-       "cannotdelete": "Ne može se obrisati stranica ili datoteka \"$1\".\nMoguće je da ju je neko drugi već obrisao.",
+       "cannotdelete": "Ne može se obrisati stranica ili datoteka \"$1\".\nMoguće je da ju je neko već obrisao.",
        "cannotdelete-title": "Ne mogu izbrisati stranicu \"$1\"",
        "delete-hook-aborted": "Brisanje je prekinuo softverski priključak.\nNije ponuđeno nikakvo objašnjenje.",
        "badtitle": "Loš naslov",
        "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",
-       "exception-nologin-text": "[[Special:Userlogin|Prijavite se]] da biste pristupili ovoj stranici ili radnji.",
+       "exception-nologin-text": "Prijavite se da biste pristupili ovoj stranici ili radnji.",
+       "exception-nologin-text-manual": "Molimo $1 da biste pristupili ovoj stranici ili radnji.",
        "virus-badscanner": "Loša konfiguracija: nepoznati anti-virus program: ''$1''",
        "virus-scanfailed": "skeniranje nije uspjelo (code $1)",
        "virus-unknownscanner": "nepoznati anti-virus program:",
        "externaldberror": "Došlo je do greške pri vanjskoj autorizaciji baze podataka ili vam nije dopušteno osvježavanje Vašeg vanjskog korisničkog računa.",
        "login": "Prijavi se",
        "nav-login-createaccount": "Prijavi se / Registruj se",
-       "loginprompt": "Morate imati kolačiće ('''cookies''') omogućene da biste se prijavili na {{SITENAME}}.",
        "userlogin": "Prijavi se / Registruj se",
        "userloginnocreate": "Prijavi se",
        "logout": "Odjavi me",
        "userlogin-resetlink": "Zaboravili ste detalje vaše prijave?",
        "userlogin-resetpassword-link": "Zaboravili ste lozinku?",
        "userlogin-helplink2": "Pomoć pri prijavljivanju",
-       "userlogin-loggedin": "Već ste prijavljeni kao {{GENDER:$1|$1}}.\nKoristite donji obrazac da biste se prijavili kao drugi korisnik.",
-       "userlogin-createanother": "Napravi još jedan račun",
        "createacct-emailrequired": "Adresa e-pošte",
        "createacct-emailoptional": "Adresa e-pošte (opcionalno)",
        "createacct-email-ph": "Unesite Vašu adresu e-pоšte",
        "userexists": "Korisničko ime koje ste unijeli je već u upotrebi.\nMolimo Vas da izaberete drugo ime.",
        "loginerror": "Greška pri prijavljivanju",
        "createaccounterror": "Ne može se napraviti račun: $1",
-       "nocookiesnew": "Korisnički nalog je napravljen, ali niste prijavljeni.  {{SITENAME}} koristi kolačiće (''cookies'') da bi se korisnici prijavili.  Vi ste onemogućili kolačiće na Vašem računaru.  Molimo Vas da ih omogućite, a onda se prijavite sa svojim novim korisničkim imenom i šifrom.",
+       "nocookiesnew": "Korisnički nalog je napravljen, ali niste prijavljeni. {{SITENAME}} koristi kolačiće (''cookies'') da bi se korisnici prijavili.  Vi ste onemogućili kolačiće na Vašem računaru. Molimo Vas da ih omogućite, a onda se prijavite sa svojim novim korisničkim imenom i šifrom.",
        "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",
        "loginsuccess": "'''Sad ste prijavljeni na {{SITENAME}} kao \"$1\".'''",
-       "nosuchuser": "Ne postoji korisnik sa imenom \"$1\".\nKorisnička imena razlikuju velika i mala slova.\nProvjerite vaše kucanje ili [[Special:UserLogin/signup|napravite novi korisnički račun]].",
-       "nosuchusershort": "Ne postoji korisnik sa imenom \"$1\".\nProvjerite da li ste dobro ukucali.",
+       "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.",
        "nouserspecified": "Morate izabrati korisničko ime.",
        "login-userblocked": "Ovaj korisnik je blokiran. Prijava nije dopuštena.",
        "wrongpassword": "Unijeli ste neispravnu šifru.\nMolimo Vas da pokušate ponovno.",
        "retypenew": "Unesite ponovo novu šifru:",
        "resetpass_submit": "Odredi šifru i prijavi se",
        "changepassword-success": "Vaša šifra/lozinka je uspiješno promjenjena!",
+       "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-no-info": "Morate biti prijavljeni da bi ste pristupili ovoj stranici direktno.",
        "resetpass-submit-loggedin": "Promijeni šifru",
        "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-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-expired": "Vaša lozinka je istekla. Postavite novu lozinku da biste se prijavili.",
        "passwordreset": "Poništavanje šifre",
        "passwordreset-text-one": "Ispunite ovaj obrazac da biste resetovali Vašu šifru/lozinku.",
        "passwordreset-text-many": "{{PLURAL:$1|Ispunite jedno od polja kako biste dobili privremenu lozinku putem e-pošte.}}",
        "changeemail-password": "Tvoja šifra/lozinka za {{SITENAME}}:",
        "changeemail-submit": "Promijeni e-mail",
        "changeemail-cancel": "Otkaži",
+       "resettokens-token-label": "$1 (trenutna vrijednost: $2)",
        "bold_sample": "Podebljan tekst",
        "bold_tip": "Podebljan tekst",
        "italic_sample": "Kurzivan tekst",
        "userjspreview": "'''Zapamtite ovo je samo izgled vaše JavaScript-e, još uvijek nije sačuvan!'''",
        "sitecsspreview": "'''Zapamtite ovo je samo izgled ovog CSS-a.'''\n'''Još uvijek nije sačuvan!'''",
        "sitejspreview": "'''Zapamtite ovo je samo izgled ovog koda JavaScripte.'''\n'''Još uvijek nije sačuvan!'''",
-       "userinvalidcssjstitle": "'''Upozorenje:''' Ne postoji interfejs pod imenom \"$1\".\nNe zaboravite da imena stranica s .css i .js kodom počinju malim slovom, npr. {{ns:user}}:Foo/vector.css, a ne {{ns:user}}:Foo/Vector.css.",
+       "userinvalidcssjstitle": "'''Upozorenje:''' Ne postoji interfejs pod imenom \"$1\".\nNe zaboravite da imena stranica s .css i .js kodom počinju malim slovom, npr, {{ns:user}}:Foo/vector.css, a ne {{ns:user}}:Foo/Vector.css.",
        "updated": "(Osvježeno)",
        "note": "'''Pažnja:'''",
        "previewnote": "'''Ne zaboravite da je ovo samo pregled'''\nIzmjene stranice nisu još sačuvane!",
        "continue-editing": "Idi na područje uređivanja",
-       "previewconflict": "Ovaj pregled reflektuje tekst u gornjem polju\nkako će izgledati ako pritisnete \"Sačuvaj članak\".",
+       "previewconflict": "Ovaj pregled prikazuje kako će tekst u gornjem polju\nizgledati ako kliknete \"Sačuvaj članak\".",
        "session_fail_preview": "'''Izvinjavamo se! Nismo mogli obraditi vašu izmjenu zbog gubitka podataka o prijavi. Molimo pokušajte ponovno. Ako i dalje ne bude radilo, pokušajte se [[Special:UserLogout|odjaviti]] i ponovno prijaviti.'''",
        "session_fail_preview_html": "'''Žao nam je! Nismo mogli da obradimo vašu izmjenu zbog gubitka podataka.'''\n\n''Zbog toga što {{SITENAME}} ima omogućen izvorni HTML, predpregled je sakriven kao predostrožnost protiv JavaScript napada.''\n\n'''Ako ste pokušali da napravite pravu izmjenu, molimo pokušajte ponovo. Ako i dalje ne radi, pokušajte da se [[Special:UserLogout|odjavite]] i ponovo prijavite.'''",
        "token_suffix_mismatch": "'''Vaša izmjena nije prihvaćena jer je Vaš web preglednik ubacio znakove interpunkcije u token uređivanja.\nIzmjena je odbačena da bi se spriječilo uništavanje teksta stranice.\nTo se događa ponekad kad korisite problematični anonimni proxy koji je baziran na web-u.'''",
        "editingsection": "Uređujete $1 (dio)",
        "editingcomment": "Uređujete $1 (nova sekcija)",
        "editconflict": "Sukobljenje izmjene: $1",
-       "explainconflict": "Neko drugi je promjenio ovu stranicu otkad ste Vi počeli da je mjenjate.\nGornje tekstualno polje sadrži tekst stranice koji trenutno postoji.\nVaše izmjene su prikazane u donjem tekstu.\nMoraćete da unesete svoje promjene u postojeći tekst.\n'''Samo''' tekst u gornjem tekstualnom polju će biti snimljen kad\npritisnete \"{{int:savearticle}}\".",
+       "explainconflict": "Neko drugi je promijenio ovu stranicu otkad ste je Vi počeli mijenjati.\nGornje tekstualno polje sadrži tekst stranice koji trenutno postoji.\nVaše izmjene prikazane su u donjem tekstu.\nMorat ćete unijeti svoje promjene u postojeći tekst.\n'''Samo''' tekst u gornjem tekstualnom polju bit će sačuvan kad\nkliknete \"{{int:savearticle}}\".",
        "yourtext": "Vaš tekst",
        "storedversion": "Uskladištena verzija",
        "nonunicodebrowser": "'''UPOZORENJE: Vaš preglednik ne podržava Unicode zapis znakova.\nMolimo Vas promijenite ga prije sljedećeg uređivanja članaka. Znakovi koji nisu po ASCII standardu će se u prozoru za izmjene pojaviti kao heksadecimalni kodovi.'''",
        "edit-gone-missing": "Stranica se nije mogla osvježiti.\nIzgleda da je obrisana.",
        "edit-conflict": "Sukob izmjena.",
        "edit-no-change": "Vaša izmjena je ignorirana, jer nije bilo promjena teksta stranice.",
+       "postedit-confirmation-created": "Stranica je napravljena.",
        "postedit-confirmation-saved": "Vaša izmjena je sačuvana.",
        "edit-already-exists": "Stranica nije mogla biti kreirana.\nIzgleda da već postoji.",
        "defaultmessagetext": "Uobičajeni tekst poruke",
        "invalid-content-data": "Nevaljani podaci sadržaja",
        "content-not-allowed-here": "Sadržaj napisan u obliku \"$1\" nije dozvoljen na stranici [[$2]]",
-       "editwarning-warning": "Napuštanje ove stranice može dovesti do gubitka svih promjena koje ste načinili.\nAko ste prijavljeni, možete isključiti ovo upozorenje u Sekciji za \"Uređivanje\" vaših opcija.",
+       "editwarning-warning": "Napuštanje ove stranice može dovesti do gubitka svih promjena koje ste načinili.\nAko ste prijavljeni, možete isključiti ovo upozorenje u Sekciji za \"{{int:prefs-editing}}\" vaših opcija.",
+       "editpage-notsupportedcontentformat-title": "Format sadržaja nije podržan",
        "content-model-wikitext": "wikitekst",
        "content-model-text": "obični tekst",
        "content-model-javascript": "JavaScript",
        "searchprofile-advanced-tooltip": "Traži u ostalim imenskim prostorima",
        "search-result-size": "$1 ({{PLURAL:$2|$2 riječ|$2 riječi}})",
        "search-result-category-size": "{{PLURAL:$1|1 član|$1 člana|$1 članova}} ({{PLURAL:$2|1 podkategorija|$2 podkategorije|$2 podkategorija}}, {{PLURAL:$3|1 datoteka|$3 datoteke|$3 datoteka}})",
-       "search-result-score": "Relevantnost: $1%",
        "search-redirect": "(preusmjeravanje $1)",
        "search-section": "(sekcija $1)",
        "search-suggest": "Da li ste mislili: $1",
        "prefs-displayrc": "Postavke izgleda",
        "prefs-displaywatchlist": "Postavke izgleda",
        "prefs-diffs": "Razlike",
+       "prefs-help-prefershttps": "Ova podešavanja će stupiti na snagu pri sljedećoj prijavi.",
        "email-address-validity-valid": "Izgleda valjano",
        "email-address-validity-invalid": "Neophodna valjana adresa!",
        "userrights": "Postavke korisničkih prava",
        "userrights-notallowed": "Vaš račun nema privilegije da dodaje ili oduzima prava korisnika.",
        "userrights-changeable-col": "Grupe koje možete mijenjati",
        "userrights-unchangeable-col": "Grupe koje ne možete mijenjati",
-       "userrights-conflict": "Sukob u korisničkim pravima! Molimo pošaljite Vaše promjene ponovno.",
+       "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.",
        "group": "Grupa:",
        "group-user": "Korisnici",
        "right-createtalk": "Pravljenje stranica za razgovor",
        "right-createaccount": "Pravljenje korisničkog računa",
        "right-minoredit": "Označavanje izmjena kao malih",
-       "right-move": "Pomjeranje stranica",
-       "right-move-subpages": "Pomjeranje stranica sa svim podstranicama",
+       "right-move": "Preusmjeravanje stranica",
+       "right-move-subpages": "Preusmjeravanje stranica sa svim podstranicama",
        "right-move-rootuserpages": "Premještanje stranica osnovnih korisnika",
        "right-movefile": "Premještanje datoteka",
        "right-suppressredirect": "Ne pravi preusmjeravanje sa starog imena pri preusmjeravanju stranica",
        "upload_directory_missing": "Folder za postavljanje ($1) nedostaje i webserver ga ne može napraviti.",
        "upload_directory_read_only": "Folder za postavljanje ($1) na webserveru je postavljen samo za čitanje.",
        "uploaderror": "Greška pri slanju",
-       "upload-recreate-warning": "'''Upozorenje: Datoteka s tim imenom je obrisana ili pomjerena.'''\nZapisnik brisanja i pomjeranja za ovu stranicu je dostupan ovdje na uvid:",
+       "upload-recreate-warning": "'''Upozorenje: Datoteka s tim imenom je obrisana ili preusmjerena.'''\nZapisnik brisanja i preusmjeravanja za ovu stranicu dostupan je ovdje:",
        "uploadtext": "Koristite formu ispod za postavljanje datoteka.\nDa bi ste vidjeli ili pretražili ranije postavljene datoteke, pogledajte [[Special:FileList|spisak postavljenih datoteka]], ponovna postavljanja su također zapisana u [[Special:Log/upload|zapisnik postavljanja]], a brisanja u [[Special:Log/delete|zapisnik brisanja]].\n\nDa bi ste prikazali datoteku na stranici, koristite link na jedan od slijedećih načina:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Datoteka.jpg]]</nowiki></code>''' da upotrijebite potpunu veziju datoteke\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Datoteka.png|200px|thumb|lijevo|opis slike]]</nowiki></code>''' da upotrijebite smanjeni prikaz širine 200 piksela unutar okvira, s lijevim poravnanjem i ''opisom slike''.\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:Datoteka.ogg]]</nowiki></code>''' za direkno povezivanje datoteke bez njenog prikazivanja",
        "upload-permitted": "Podržane vrste datoteka: $1.",
        "upload-preferred": "Preferirane vrste datoteka: $1.",
        "fileexists-extension": "Datoteka sa sličnim nazivom postoji: [[$2|thumb]]\n* Naziv datoteke koja se postavlja: <strong>[[:$1]]</strong>\n* Naziv postojeće datoteke: <strong>[[:$2]]</strong>\nMolimo Vas da izaberete drugačiji naziv.",
        "fileexists-thumbnail-yes": "Izgleda da je datoteka slika smanjene veličine ''(\"thumbnail\")''. [[$1|thumb]]\nMolimo provjerite datoteku <strong>[[:$1]]</strong>.\nAko je provjerena datoteka ista slika originalne veličine, nije potrebno postavljati dodatnu sliku.",
        "file-thumbnail-no": "Naziv datoteke počinje sa <strong>$1</strong>.\nIzgleda da se radi o smanjenoj slici ''(\"thumbnail\")''.\nAko imate ovu sliku u punoj rezoluciji, postavite nju; ili promijenite naslov ove datoteke.",
-       "fileexists-forbidden": "Datoteka sa ovim imenom već postoji i ne može biti prepisana.\nAko i dalje želite da postavite ovu datoteku, molimo Vas da se vratite i pošaljete ovu datoteku pod novim imenom. [[File:$1|thumb|center|$1]]",
-       "fileexists-shared-forbidden": "Datoteka sa ovim imenom već postoji u zajedničkoj ostavi; molimo Vas da se vratite i pošaljete ovu datoteku pod novim imenom. [[File:$1|thumb|center|$1]]",
+       "fileexists-forbidden": "Datoteka s ovim imenom već postoji i ne može biti prepisana.\nAko i dalje želite postaviti ovu datoteku, molimo Vas da se vratite i pošaljete ovu datoteku pod novim imenom. [[File:$1|thumb|center|$1]]",
+       "fileexists-shared-forbidden": "Datoteka s ovim imenom već postoji u zajedničkoj ostavi. Molimo Vas da se vratite i pošaljete ovu datoteku pod novim imenom. [[File:$1|thumb|center|$1]]",
        "file-exists-duplicate": "Ova datoteka je dvojnik {{PLURAL:$1|slijedećoj datoteci|slijedećim datotekama}}:",
        "file-deleted-duplicate": "Datoteka koje je identična ovoj datoteci ([[:$1]]) je ranije bila obrisana. Trebate provjeriti historiju brisanja te datoteke prije nego što nastavite sa njenim ponovnim postavljanjem.",
        "uploadwarning": "Upozorenje pri slanju",
        "uploadwarning-text": "Molimo izmijeniti opis datoteke ispod i pokušajte kasnije.",
        "savefile": "Sačuvaj datoteku",
-       "uploadedimage": "poslato \"[[$1]]\"",
-       "overwroteimage": "postavljena nova verzija datoteke \"[[$1]]\"",
        "uploaddisabled": "Slanje fajlova je isključeno",
        "copyuploaddisabled": "Postavljanje putem URL nije omogućeno.",
        "uploaddisabledtext": "Postavljanje datoteka je onemogućeno.",
        "upload-description": "Opis datoteke",
        "upload-options": "Opcije postavljanja",
        "watchthisupload": "Prati ovu datoteku",
-       "filewasdeleted": "Datoteka s ovim nazivom je ranije postavljana i nakon toga obrisana.\nPrije nego što nastavite da je ponovno postavite trebate provjeriti $1.",
+       "filewasdeleted": "Datoteka s ovim nazivom je ranije postavljana i nakon toga obrisana.\nPrije no što nastavite da je ponovo postavite trebate provjeriti $1.",
        "filename-bad-prefix": "Naziv datoteke koju postavljate počinje sa '''\"$1\"''', što je naziv koji obično automatski dodjeljuju digitalni fotoaparati i kamere.\nMolimo Vas da odaberete naziv datoteke koji opisuje njen sadržaj.",
        "filename-prefix-blacklist": " #<!-- ostavite ovu liniju onakvom kakva jeste --> <pre>\n# Sintaksa je slijedeća:\n#   * Sve od karaktera \"#\" pa do kraja je komentar\n#   * Svaka neprazna linija je prefiks za tipična imena datoteka koja automatski dodjeljuje digitalna kamera\nCIMG # Casio\nDSC_ # Nikon\nDSCF # Fuji\nDSCN # Nikon\nDUW # neki mobilni telefoni\nIMG # generic\nJD # Jenoptik\nMGP # Pentax\nPICT # razni\n #</pre> <!-- ostavite ovu liniju onakvom kakva jeste -->",
        "upload-success-subj": "Uspješno slanje",
        "license-nopreview": "(Pregled nije dostupan)",
        "upload_source_url": " (validni, javno dostupni URL)",
        "upload_source_file": " (datoteka na Vašem računaru)",
+       "listfiles-delete": "obriši",
        "listfiles-summary": "Ova posebna stranica prikazuje sve postavljene datoteke.",
        "listfiles_search_for": "Traži medije po imenu:",
        "imgfile": "datoteka",
        "randompage": "Slučajna stranica",
        "randompage-nopages": "Nema stranica u {{PLURAL:$2|slijedećem imenskom prostoru|slijedećim imenskim prostorima}}: \"$1\".",
        "randomincategory": "Slučajna stranica u kategoriji",
-       "randomincategory-selectcategory-submit": "Idi",
+       "randomincategory-nopages": "Nema stranica u kategoriji [[:Category:$1|$1]].",
+       "randomincategory-category": "Kategorija:",
+       "randomincategory-legend": "Slučajna stranica u kategoriji",
        "randomredirect": "Slučajno preusmjerenje",
        "randomredirect-nopages": "Ne postoje preusmjerenja u imenskom prostoru \"$1\".",
        "statistics": "Statistike",
        "protectedpages-indef": "Samo neograničena zaštićenja",
        "protectedpages-cascade": "Samo prenosive zaštite",
        "protectedpages-noredirect": "Sakrij preusmjerenja",
-       "protectedpagesempty": "Trenutno nijedna stranica nije zaštićena ovim parametrima.",
+       "protectedpagesempty": "Trenutno nijedna stranica nije zaštićena ovim parametrima.",
        "protectedpages-page": "Stranica",
        "protectedpages-expiry": "Istječe",
        "protectedpages-reason": "Razlog",
        "protectedpages-unknown-timestamp": "Nepoznato",
+       "protectedpages-unknown-performer": "Nepoznati korisnik",
        "protectedtitles": "Zaštićeni naslovi",
-       "protectedtitlesempty": "Nema naslova zaštićenih članaka sa ovim parametrima.",
+       "protectedtitlesempty": "Nijedan naslov članka trenutno nije zaštićen ovim parametrima.",
        "listusers": "Spisak korisnika",
        "listusers-editsonly": "Pokaži samo korisnike koji su uređivali",
        "listusers-creationsort": "Sortiraj po datumu pravljenja",
        "move": "Preusmjeri",
        "movethispage": "Premjesti ovu stranicu",
        "unusedimagestext": "Slijedeće datoteke postoje ali nisu uključene ni u jednu stranicu.\nMolimo obratite pažnju da druge web stranice mogu biti povezane s datotekom putem direktnog URLa, tako da i pored toga mogu biti prikazane ovdje pored aktivne upotrebe.",
-       "unusedcategoriestext": "Slijedeće stranice kategorija postoje iako ih ni jedan drugi članak ili kategorija ne koriste.",
+       "unusedcategoriestext": "Sljedeće stranice kategorija postoje iako ih nijedan drugi članak ili kategorija ne koriste.",
        "notargettitle": "Nema cilja",
        "notargettext": "Niste naveli ciljnu stranicu ili korisnika\nna kome bi se izvela ova funkcija.",
        "nopagetitle": "Ne postoji takva stranica",
        "all-logs-page": "Svi javni registri",
        "alllogstext": "Zajednički prikaz svih dostupnih zapisa sa {{SITENAME}}.\nMožete specificirati prikaz izabiranjem specifičnog spiska, korisničkog imena ili promjenjenog članka (razlikovati velika slova).",
        "logempty": "Ne postoji takav zapis.",
-       "log-title-wildcard": "Traži naslove koji počinju ovim tekstom",
+       "log-title-wildcard": "Traži naslove koji počinju ovim tekstom",
        "showhideselectedlogentries": "Pokaži/sakrij izabrane zapise u evidenciji",
        "allpages": "Sve stranice",
        "nextpage": "Sljedeća strana ($1)",
        "listgrouprights-removegroup-self": "Može ukloniti {{PLURAL:$2|grupu|grupe|grupa}} sa svog računa: $1",
        "listgrouprights-addgroup-self-all": "Može dodati sve grupe na svoj račun",
        "listgrouprights-removegroup-self-all": "Može ukloniti sve grupe sa svog računa",
+       "listgrouprights-namespaceprotection-namespace": "Imenski prostor",
+       "trackingcategories-nodesc": "Opis nije dostupan.",
        "mailnologin": "Nema adrese za slanje",
        "mailnologintext": "Morate biti [[Special:UserLogin|prijavljeni]]\ni imati ispravnu adresu e-pošte u vašim [[Special:Preferences|podešavanjima]]\nda biste slali e-poštu drugim korisnicima.",
        "emailuser": "Pošalji e-poštu ovom korisniku",
        "watchlist-details": "{{PLURAL:$1|$1 stranica praćena|$1 stranice praćene|$1 stranica praćeno}} ne računajući stranice za razgovor.",
        "wlheader-enotif": "Obavještavanje e-poštom je omogućeno.",
        "wlheader-showupdated": "Stranice koje su izmijenjene od kad ste ih posljednji put posjetili su prikazane '''podebljanim slovima'''",
+       "wlnote": "Ispod je {{PLURAL:$1|najskorija izmjena|'''$1''' najskorije izmjene|'''$1''' najskorijih izmjena}} načinjenih {{PLURAL:$2|posljednjeg sata|u posljednjih '''$2''' sata|u posljednjih '''$2''' sati}}, od $3, $4.",
        "wlshowlast": "Prikaži posljednjih $1 sati $2 dana $3",
        "watchlist-options": "Opcije spiska praćenja",
        "watching": "Pratim...",
        "confirmdeletetext": "Brisanjem ćete obrisati stranicu ili sliku zajedno sa historijom iz baze podataka, ali će se iste moći vratiti kasnije.\nMolim potvrdite svoju namjeru, da razumijete posljedice i da ovo radite u skladu sa [[{{MediaWiki:Policy-url}}|pravilima]].",
        "actioncomplete": "Akcija završena",
        "actionfailed": "Akcija nije uspjela",
-       "deletedtext": "Članak \"$1\" je obrisan.\nPogledajte $2 za zapis o skorašnjim brisanjima.",
+       "deletedtext": "Članak \"$1\" je obrisan.\nPogledajte $2 za zapisnik nedavnih brisanja.",
        "dellogpage": "Protokol brisanja",
        "dellogpagetext": "Ispod je spisak najskorijih brisanja.",
        "deletionlog": "zapis brisanja",
        "rollbacklinkcount-morethan": "vrati više od $1 {{PLURAL:$1|izmjene|izmjene|izmjena}}",
        "rollbackfailed": "Vraćanje nije uspjelo",
        "cantrollback": "Ne može se vratiti izmjena; posljednji autor je ujedno i jedini.",
-       "alreadyrolled": "Ne može se vratiti posljednja izmjena [[:$1]] od korisnika [[User:$2|$2]] ([[User talk:$2|razgovor]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]); neko drugi je već izmjenio ili vratio članak.\n\nPosljednja izmjena je bila od korisnika [[User:$3|$3]] ([[User talk:$3|razgovor]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
+       "alreadyrolled": "Ne može se vratiti posljednja izmjena [[:$1]] od korisnika [[User:$2|$2]] ([[User talk:$2|razgovor]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]); neko je već izmijenio ili vratio članak na prethodnu provjerenu verziju.\n\nPosljednju izmjenu napravio je korisnik [[User:$3|$3]] ([[User talk:$3|razgovor]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Sažetak izmjene je bio: \"''$1''\".",
        "revertpage": "Vraćene izmjene korisnika [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]]) na posljednju izmjenu koju je napravio [[User:$1|$1]]",
        "revertpage-nouser": "Vraćene izmjene skrivenog korisnika na posljednju reviziju, koju je {{GENDER:$1|napravio|napravila}} [[User:$1|$1]]",
        "autoblockid": "Automatska blokada #$1",
        "block": "Blokiraj korisnika",
        "unblock": "Odblokiraj korisnika",
-       "blockip": "Blokiraj korisnika",
+       "blockip": "Blokiraj {{GENDER:$1|korisnika|korisnicu}}",
        "blockip-legend": "Blokiranje korisnika",
        "blockiptext": "Upotrebite donji upitnik da biste uklonili prava pisanja sa određene IP adrese ili korisničkog imena.  Ovo bi trebalo da bude urađeno samo da bi se spriječio vandalizam, i u skladu sa [[{{MediaWiki:Policy-url}}|smjernicama]]. Unesite konkretan razlog ispod (na primjer, navodeći koje stranice su vandalizovane).",
        "ipaddressorusername": "IP adresa ili korisničko ime:",
        "blockipsuccesssub": "Blokiranje je uspjelo",
        "blockipsuccesstext": "[[Special:Contributions/$1|$1]] je {{GENDER:$1|blokiran|blokirana|blokiran}}.<br />\nPogledajte [[Special:BlockList|spisak blokiranja]] za pregled blokiranja.",
        "ipb-blockingself": "Ovom akcijom ćete blokirati sebe! Da li ste sigurni da to želite?",
-       "ipb-confirmhideuser": "Upravo ćete blokirati korisnika sa uključenom opcijom ''sakrij korisnika''. Ovim će korisničko ime biti sakriveno u svim spiskovima i stavkama zapisnika. Da li ste sigurni da to želite?",
+       "ipb-confirmhideuser": "Upravo ćete blokirati korisnika s uključenom opcijom \"Sakrij korisnika\". Ovim će korisničko ime biti sakriveno u svim spiskovima i stavkama zapisnika. Jeste li sigurni da to želite?",
        "ipb-edit-dropdown": "Uredi razloge blokiranja",
        "ipb-unblock-addr": "Deblokiraj $1",
        "ipb-unblock": "Deblokiraj korisničko ime ili IP adresu",
        "lockfilenotwritable": "Datoteka zaključavanja baze je zaštićena za pisanje.\nAko želite otključati ili zaključati bazu, ova datoteka mora biti omogućena za pisanje od strane web servera.",
        "databasenotlocked": "Baza podataka nije zaključana.",
        "lockedbyandtime": "(od $1 dana $2 u $3)",
-       "move-page": "Pomjeranje $1",
+       "move-page": "Preusmjeravanje $1",
        "move-page-legend": "Premjestite stranicu",
-       "movepagetext": "Korištenjem ovog formulara možete preimenovati stranicu, premještajući cijelu historiju na novo ime.\nČlanak pod starim imenom će postati stranica koja preusmjerava na članak pod novim imenom. \nMožete automatski izmjeniti preusmjerenje do izvornog naslova.\nAko se ne odlučite na to, provjerite [[Special:DoubleRedirects|dvostruka]] ili [[Special:BrokenRedirects|neispravna preusmjeravanja]].\nDužni ste provjeriti da svi linkovi i dalje nastave voditi na prave stranice.\n\nImajte na umu da članak '''neće''' biti preusmjeren ukoliko već postoji članak pod imenom na koje namjeravate da preusmjerite osim u slučaju stranice za preusmjeravanje koja nema nikakvih starih izmjena.\nTo znači da možete vratiti stranicu na prethodno mjesto ako pogriješite, ali ne možete zamijeniti postojeću stranicu.\n\n'''Pažnja!'''\nOvo može biti drastična i neočekivana promjena kad su u pitanju popularne stranice;\nMolimo dobro razmislite prije nego što preimenujete stranicu.",
-       "movepagetext-noredirectfixer": "Koristeći obrazac ispod ćete preimenovati stranicu i premjestiti cijelu njenu historiju na novi naziv.\nStari naziv će postati preusmjerenje na novi naziv.\nMolimo provjerite da li postoje [[Special:DoubleRedirects|dvostruka]] ili [[Special:BrokenRedirects|nedovršena preusmjerenja]].\nVi ste za to odgovorni te morate provjeriti da li su linkovi ispravni i da li vode tamo gdje bi trebali.\n\nImajte na umu da stranica '''neće''' biti premještena ako već postoji stranica s tim imenom, osim ako je prazna ili je preusmjerenje ili nema ranije historije.\nOvo znali da možete preimenovati stranicu nazad gdje je ranije bila preimenovana ako ste pogriješili a ne možete ponovo preimenovati postojeću stranicu.\n\n'''Pažnja!'''\nImajte na umu da preusmjeravanje popularnog članka može biti\ndrastična i neočekivana promjena za korisnike; molimo budite sigurni da ste shvatili posljedice prije nego što nastavite.",
+       "movepagetext": "Korištenjem ovog formulara možete preimenovati stranicu, premještajući cijelu historiju na novo ime.\nČlanak pod starim imenom postat će stranica koja preusmjerava na članak pod novim imenom. \nMožete automatski izmijeniti preusmjerenje do izvornog naslova.\nAko se ne odlučite na to, provjerite [[Special:DoubleRedirects|dvostruka]] ili [[Special:BrokenRedirects|neispravna preusmjeravanja]].\nDužni ste provjeriti da svi linkovi i dalje nastave voditi na prave stranice.\n\nImajte na umu da članak '''neće''' biti preusmjeren ako već postoji članak pod imenom na koje ga namjeravate preusmjeriti osim u slučaju stranice za preusmjeravanje koja nema nikakvih starih izmjena.\nTo znači da možete vratiti stranicu na prethodno mjesto ako pogriješite, ali ne možete zamijeniti postojeću stranicu.\n\n'''Pažnja!'''\nOvo može biti drastična i neočekivana promjena kad su u pitanju popularne stranice.\nMolimo da dobro razmislite prije no što preimenujete stranicu.",
+       "movepagetext-noredirectfixer": "Koristeći donji obrazac, preimenovat ćete stranicu i premjestiti cijelu njenu historiju na novi naziv.\nStari naziv postat će preusmjerenje na novi naziv.\nMolimo da provjerite postoje li [[Special:DoubleRedirects|dvostruka]] ili [[Special:BrokenRedirects|nedovršena preusmjerenja]].\nVi ste za to odgovorni te morate provjeriti jesu li linkovi ispravni i vode li tamo kamo bi trebali voditi.\n\nImajte na umu da stranica '''neće''' biti premještena ako već postoji stranica s tim imenom, osim ako je prazna ili je preusmjerenje ili nema ranije historije.\nOvo znači da možete preimenovati stranicu nazad gdje je ranije bila preimenovana ako ste pogriješili, ali ne možete ponovo preimenovati postojeću stranicu.\n\n'''Pažnja!'''\nImajte na umu da preusmjeravanje popularnog članka može biti\ndrastična i neočekivana promjena za korisnike; molimo da budete sigurni da ste shvatili posljedice prije no što nastavite.",
        "movepagetalktext": "Odgovarajuća stranica za razgovor, ako postoji, će automatski biti premještena istovremeno '''osim:'''\n*Ako premještate stranicu preko imenskih prostora,\n*Neprazna stranica za razgovor već postoji pod novim imenom, ili\n*Odčekirajte donju kutiju.\n\nU tim slučajevima, moraćete ručno da premjestite stranicu ukoliko to želite.",
        "movearticle": "Premjestite stranicu",
        "moveuserpage-warning": "'''Upozorenje:''' Premještate korisničku stranicu. Molimo da zapamtite da će se samo stranica premjestiti a korisnik se ''neće'' preimenovati.",
        "movepagebtn": "pomjerite stranicu",
        "pagemovedsub": "Premještanje uspjelo",
        "movepage-moved": "'''\"$1\" je premještena na \"$2\"'''",
-       "movepage-moved-redirect": "Pomjeranje je napravljeno.",
+       "movepage-moved-redirect": "Preusmjerenje je napravljeno.",
        "movepage-moved-noredirect": "Pravljenje preusmjerenja je onemogućeno.",
-       "articleexists": "Stranica pod tim imenom već postoji, ili je ime koje ste izabrali neispravno.  Molimo Vas da izaberete drugo ime.",
+       "articleexists": "Stranica pod tim imenom već postoji ili je ime koje ste izabrali neispravno. Molimo Vas da izaberete drugo ime.",
        "cantmove-titleprotected": "Ne možete premjestiti stranicu na ovu lokaciju, jer je novi naslov zaštićen od pravljenja",
        "movetalk": "Premjestite \"stranicu za razgovor\" takođe, ako je moguće.",
        "move-subpages": "Premjesti sve podstranice (do $1)",
        "import": "Uvoz stranica",
        "importinterwiki": "Međuwiki uvoz",
        "import-interwiki-text": "Izaberi wiki i naslov stranice za uvoz.\nDatumi revizija i imena autora će biti sačuvani.\nSve akcije pri međuwiki uvozu će biti zapisane u [[Special:Log/import|zapisu uvoza]].",
-       "import-interwiki-source": "Izvorna wiki/stranica:",
        "import-interwiki-history": "Kopiraj sve verzije historije za ovu stranicu",
        "import-interwiki-templates": "Uključi sve šablone",
        "import-interwiki-submit": "Uvoz",
        "tooltip-pt-login": "Predlažemo da se prijavite, ali nije obvezno.",
        "tooltip-pt-logout": "Odjava sa projekta {{SITENAME}}",
        "tooltip-ca-talk": "Razgovor o sadržaju",
-       "tooltip-ca-edit": "Možete da uređujete ovaj članak. Molimo Vas, koristite dugme \"Prikaži izgled",
+       "tooltip-ca-edit": "Možete uređivati ovaj članak. Molimo Vas, koristite dugme \"Prikaži izgled\" prije spašavanja izmjena.",
        "tooltip-ca-addsection": "Započnite novu sekciju.",
        "tooltip-ca-viewsource": "Ovaj članak je zaključan. Možete ga samo vidjeti ili kopirati kod.",
        "tooltip-ca-history": "Prethodne verzije ove stranice.",
        "tooltip-ca-watch": "Dodajte stranicu u listu praćnih članaka",
        "tooltip-ca-unwatch": "Izbrišite stranicu sa liste praćnih članaka",
        "tooltip-search": "Pretraži projekat {{SITENAME}}",
-       "tooltip-search-go": "Idi na stranicu sa tačno ovim imenom ako postoji",
-       "tooltip-search-fulltext": "Pretraga stranica sa ovim tekstom",
+       "tooltip-search-go": "Idi na stranicu s tačno ovim imenom ako postoji",
+       "tooltip-search-fulltext": "Pretražite stranice s ovim tekstom",
        "tooltip-p-logo": "Glavna stranica",
        "tooltip-n-mainpage": "Posjetite početnu stranicu",
        "tooltip-n-mainpage-description": "Posjetite početnu stranicu",
        "tooltip-n-recentchanges": "Spisak nedavnih izmjena na wiki.",
        "tooltip-n-randompage": "Otvorite slučajan članak",
        "tooltip-n-help": "Mjesto gdje možete nešto da naučite.",
-       "tooltip-t-whatlinkshere": "Spisak svih članaka koji su povezani sa ovim",
+       "tooltip-t-whatlinkshere": "Spisak svih članaka koji su povezani s ovim",
        "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",
        "anonymous": "{{PLURAL:$1|Anonimni korisnik|$1 anonimna korisnika|$1 anonimnih korisnika}} projekta {{SITENAME}}",
        "siteuser": "{{SITENAME}} korisnik $1",
        "anonuser": "{{SITENAME}} anonimni korisnik $1",
-       "lastmodifiedatby": "Ovu stranicu je posljednji put promjenio $3, u $2, $1",
+       "lastmodifiedatby": "Ovu stranicu posljednji je put promijenio $3, u $2, $1",
        "othercontribs": "Bazirano na radu od strane korisnika $1.",
        "others": "ostali",
        "siteusers": "{{SITENAME}} {{PLURAL:$2|korisnik|korisnika}} $1",
        "scarytranscludefailed-httpstatus": "[Preuzimanje šablona nije uspjelo za $1: HTTP $2]",
        "scarytranscludetoolong": "[URL je predugačak]",
        "deletedwhileediting": "'''Upozorenje''': Ova stranica je obrisana prije nego što ste počeli uređivati!",
-       "confirmrecreate": "Korisnik [[User:$1|$1]] ([[User talk:$1|razgovor]]) je obrisao ovaj članak pošto ste počeli uređivanje sa razlogom:\n: ''$2''\n\nMolimo Vas da potvrdite da stvarno želite da ponovo napravite ovaj članak.",
-       "confirmrecreate-noreason": "Korisnik [[User:$1|$1]] ([[User talk:$1|razgovor]]) je obrisao ovaj članak pošto ste ga počeli uređivati. Molimo Vas da potvrdite da stvarno želite da ponovo napravite ovaj članak.",
+       "confirmrecreate": "Korisnik [[User:$1|$1]] ([[User talk:$1|razgovor]]) obrisao je ovaj članak pošto ste počeli uređivanje s razlogom:\n: ''$2''\n\nMolimo Vas da potvrdite da stvarno želite ponovo napraviti ovaj članak.",
+       "confirmrecreate-noreason": "Korisnik [[User:$1|$1]] ([[User talk:$1|razgovor]]) obrisao je ovaj članak nakon što ste ga počeli uređivati. Molimo Vas da potvrdite da stvarno želite ponovo napraviti ovaj članak.",
        "recreate": "Ponovno napravi",
        "unit-pixel": "px",
        "confirm_purge_button": "U redu",
        "version-ext-colheader-license": "Licenca",
        "version-ext-colheader-description": "Opis",
        "version-ext-colheader-credits": "Autori",
+       "version-license-title": "Licenca za $1",
        "version-poweredby-credits": "Ova wiki je zasnovana na '''[https://www.mediawiki.org/ MediaWiki]''', autorska prava zadržana © 2001-$1 $2.",
        "version-poweredby-others": "ostali",
        "version-credits-summary": "Željeli bismo se zahvaliti sljedećim ljudima na njihovom doprinosu [[Special:Version|MediaWikiju]].",
-       "version-license-info": "Mediawiki je slobodni softver, možete ga redistribuirati i/ili mijenjati pod uslovima GNU opće javne licence kao što je objavljeno od strane Fondacije Slobodnog Softvera, bilo u verziji 2 licence, ili (po vašoj volji) nekoj od kasniji verzija.\n\nMediawiki se distriburia 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 GNU opću javnu licencu za više detalja.\n\nTrebali biste dobiti [{{SERVER}}{{SCRIPTPATH}}/KOPIJU GNU opće javne licence] zajedno s ovim programom, ako niste, pišite Fondaciji Slobodnog Softvera 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 online].",
+       "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-software": "Instalirani softver",
        "version-software-product": "Proizvod",
        "version-software-version": "Verzija",
        "fileduplicatesearch-info": "$1 × $2 piksel<br />Veličina datoteke: $3<br />MIME vrsta: $4",
        "fileduplicatesearch-result-1": "Datoteka \"$1\" nema identičnih dvojnika.",
        "fileduplicatesearch-result-n": "Datoteka \"$1\" ima {{PLURAL:$2|1 identičnog|$2 identična|$2 identičnih}} dvojnika.",
-       "fileduplicatesearch-noresults": "Nije pronađena datoteka sa imenom \"$1\".",
+       "fileduplicatesearch-noresults": "Nije pronađena datoteka s imenom \"$1\".",
        "specialpages": "Posebne stranice",
        "specialpages-note-top": "Legenda",
        "specialpages-note": "* Normalne posebne stranice.\n* <strong class=\"mw-specialpagerestricted\">Zaštićene posebne stranice.</strong>",
        "htmlform-no": "Ne",
        "htmlform-yes": "Da",
        "htmlform-chosen-placeholder": "Izaberite opciju",
+       "htmlform-cloner-create": "Dodaj još",
        "sqlite-has-fts": "$1 sa podrškom pretrage cijelog teksta",
        "sqlite-no-fts": "$1 bez podrške pretrage cijelog teksta",
        "logentry-delete-delete": "$1 je {{GENDER:$2|obrisao|obrisala}} stranicu $3",
        "logentry-rights-rights-legacy": "$1 je {{GENDER:$2|promijenio|promijenila|promijenio}} članstvo grupe za $3",
        "logentry-rights-autopromote": "$1 {{GENDER:$1|je automatski promijenjeno članstvo|su automatski promijenjena članstva}} iz $4 u $5",
        "rightsnone": "(nema)",
-       "feedback-bugornote": "Ako ste spremni detaljno opisati tehnički problem molimo [$1 prijavite \"bug\" (grešku)].\nInače, možete ispuniti jednostavan obrazac ispod. Vaš komentar biti će dodan na stranicu \"[$3 $2]\", zajedno s vašim korisničkim imenom i internetskog preglednika koji koristite.",
+       "feedback-bugornote": "Ako ste spremni detaljno opisati tehnički problem, molimo [$1 prijavite \"bug\" (grešku)].\nInače, možete ispuniti jednostavan obrazac ispod. Vaš komentar bit će dodan na stranicu \"[$3 $2]\" zajedno s Vašim korisničkim imenom.",
        "feedback-subject": "Tema:",
        "feedback-message": "Poruka:",
        "feedback-cancel": "Odustani",
        "api-error-empty-file": "Datoteka koju ste poslali je bila prazna.",
        "api-error-emptypage": "Stvaranje novih praznih stranica nije dozvoljeno.",
        "api-error-fetchfileerror": "Unutrašnja greška: pojavio se neki problem pri dobijanju podataka o datoteci.",
-       "api-error-fileexists-forbidden": "Datoteka s imenom \"$1\" već postoji, i ne može biti zamijenjena.",
+       "api-error-fileexists-forbidden": "Datoteka s imenom \"$1\" već postoji i ne može biti zamijenjena.",
        "api-error-fileexists-shared-forbidden": "Datoteka s imenom \"$1\" već postoji u zajedničkom spremištu i ne može biti prepisana.",
        "api-error-file-too-large": "Datoteka koju ste poslali je bila prevelika.",
        "api-error-filename-tooshort": "Ime datoteke je prekratko.",
        "expand_templates_remove_comments": "Ukloni komentare",
        "expand_templates_remove_nowiki": "Onemogući oznake <nowiki> u rezultatima",
        "expand_templates_generate_xml": "Prikaži XML stablo parsera",
-       "expand_templates_preview": "Pregled"
+       "expand_templates_preview": "Pregled",
+       "pagelang-name": "Stranica",
+       "pagelang-language": "Jezik",
+       "pagelang-select-lang": "Izaberi jezik"
 }
diff --git a/languages/i18n/bto.json b/languages/i18n/bto.json
new file mode 100644 (file)
index 0000000..f706e7a
--- /dev/null
@@ -0,0 +1,573 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Filipinayzd",
+                       "Rinconada"
+               ]
+       },
+       "tog-hideminor": "Itago a mga gatikot na pagbalyow sa mga bagong pagribay",
+       "tog-hidepatrolled": "Itago a mga binabantayang na pagbalyow sa mga bagong pagribay",
+       "tog-newpageshidepatrolled": "Itago a mga binabantayan na pagbalyow sa lista ka bagong pahina",
+       "tog-extendwatchlist": "Ibuka a lista ka binabantayan para maipabayad a ngamin na pagribay, buku sana a pinakabago",
+       "tog-usenewrc": "Igrupo a mga pagribay por pahina sa mga bagong pagribay anggan binabantayan",
+       "tog-numberheadings": "Automatikong bilangun a mga titulo",
+       "tog-showtoolbar": "Ipabayad a gamit sa pagbalyow",
+       "tog-editondblclick": "Balyowan a mga pahina sa dobleng click",
+       "tog-watchcreations": "Irugang a mga pahinang kanakong ginibo anggan mga file na isinangat sa kanakong binabantayan",
+       "tog-watchdefault": "Irugang a mga pahinang anggan mga file na binabalyowan ko sa kanakong binabantayan",
+       "tog-watchmoves": "Irugang a mga pahinang anggan mga file na inililipat ko sa kanakong binabantayan",
+       "tog-watchdeletion": "Irugang a mga pahinang anggan mga file na pinupura ko sa kanakong binabantayan",
+       "tog-watchlisthideown": "Itago a kanakong mga pagbalyow sa binabantayan ko",
+       "tog-watchlisthidebots": "Itago a mga pagbalyow ka bot sa binabantayan ko",
+       "tog-watchlisthideminor": "Itago a mga gatikot na pagbalyow sa binabantayan ko",
+       "tog-watchlisthideliu": "Itago a mga pagbalyow ka mga nakaloog na user sa binabantayan ko",
+       "tog-watchlisthideanons": "Itago a mga pagbalyow ka mga diri ising user sa binabantayan ko",
+       "tog-watchlisthidepatrolled": "Itago a mga binabantayan na pagbalyow sa binabantayan ko",
+       "tog-ccmeonemails": "Padarhi ko ka mga kopya ka mga email na ipinapadara ko sa obang user",
+       "tog-diffonly": "Diri ipagpabayad a loog ka pahina sa iraraum ka pagkakaiba",
+       "tog-showhiddencats": "Ipabayad a mga nakatagong kategorya",
+       "tog-norollbackdiff": "Galinon an pagkakaiba matapos gibowon a pagbalik",
+       "underline-always": "Pirmi",
+       "underline-never": "Nungka",
+       "editfont-monospace": "font na Monospaced",
+       "editfont-sansserif": "font na Sans-serif",
+       "editfont-serif": "font na Serif",
+       "sunday": "Domingo",
+       "monday": "Lunis",
+       "tuesday": "Martes",
+       "wednesday": "Myirkules",
+       "thursday": "Hwebes",
+       "friday": "Byernis",
+       "saturday": "Sabado",
+       "sun": "Dom",
+       "mon": "Lun",
+       "tue": "Mar",
+       "wed": "Myi",
+       "thu": "Hwe",
+       "fri": "Bye",
+       "sat": "Sab",
+       "january": "Enero",
+       "february": "Pebrero",
+       "march": "Marso",
+       "april": "Abril",
+       "may_long": "Mayo",
+       "june": "Hunyo",
+       "july": "Hulyo",
+       "august": "Agusto",
+       "september": "Sityembre",
+       "october": "Oktubre",
+       "november": "Nubyembre",
+       "december": "Disyembre",
+       "january-gen": "Enero",
+       "february-gen": "Pebrero",
+       "march-gen": "Marso",
+       "april-gen": "Abril",
+       "may-gen": "Mayo",
+       "june-gen": "Hunyo",
+       "july-gen": "Hulyo",
+       "august-gen": "Agusto",
+       "september-gen": "Sityembre",
+       "october-gen": "Oktubre",
+       "november-gen": "Nubyembre",
+       "december-gen": "Disyembre",
+       "jan": "Ene",
+       "feb": "Peb",
+       "mar": "Mar",
+       "apr": "Abr",
+       "may": "May",
+       "jun": "Hun",
+       "jul": "Hul",
+       "aug": "Agu",
+       "sep": "Sit",
+       "oct": "Okt",
+       "nov": "Nub",
+       "dec": "Dis",
+       "january-date": "Enero $1",
+       "february-date": "Pebrero $1",
+       "march-date": "Marso $1",
+       "april-date": "Abril $1",
+       "may-date": "Mayo $1",
+       "june-date": "Hunyo $1",
+       "july-date": "Hulyo $1",
+       "august-date": "Agusto $1",
+       "september-date": "Sityembre $1",
+       "october-date": "Oktubre $1",
+       "november-date": "Nubyembre $1",
+       "december-date": "Disyembre $1",
+       "pagecategories": "{{PLURAL:$1|Kategorya|Mga kategorya}}",
+       "category_header": "Mga pahina sa kategoryang \"$1\"",
+       "subcategories": "Mga subkategorya",
+       "category-media-header": "Mga pahina sa kategoryang \"$1\"",
+       "hidden-categories": "{{PLURAL:$1|Nakatagong kategorya|Mga nakatagong kategorya}}",
+       "hidden-category-category": "Mga nakatagong kategorya",
+       "listingcontinuesabbrev": "sunod",
+       "cancel": "Galinon",
+       "moredotdotdot": "Dakul pa...",
+       "morenotlisted": "Bukung kumpleto ading lista.",
+       "mypage": "Pahina",
+       "mytalk": "Magbisara",
+       "anontalk": "Pagbisara kading IP adres",
+       "navigation": "Nabigasyon",
+       "and": ",&#32;anggan",
+       "qbfind": "Anapun",
+       "qbedit": "Balyowan",
+       "qbpageoptions": "Ading pahina",
+       "qbmyoptions": "Kanakong mga pahina",
+       "faq": "FAQ",
+       "faqpage": "Proyekto:FAQ",
+       "actions": "Mga aksyon",
+       "namespaces": "Bubutangan",
+       "variants": "Iba pa",
+       "navigation-heading": "Menung nabigasyon",
+       "errorpagetitle": "Sala",
+       "returnto": "Bumalik sa $1",
+       "tagline": "Galin {{SITENAME}}",
+       "help": "Tabang",
+       "search": "Pag-anapon",
+       "searchbutton": "Pag-anapon",
+       "go": "Dumuman",
+       "searcharticle": "Dumuman",
+       "history": "Kasaysayan kan pahina",
+       "history_short": "Kasaysayan",
+       "print": "Ilimbag",
+       "view": "Silung",
+       "view-foreign": "Silung sa $1",
+       "edit": "Balyowan",
+       "create": "Gumibo",
+       "create-local": "Dugangan sa lokal na deskripsyon",
+       "editthispage": "Balyowan ading pahina",
+       "create-this-page": "Gumibo kading pahina",
+       "delete": "Puraon",
+       "deletethispage": "Puraon ading pahina",
+       "undeletethispage": "Ibalik ading pahina",
+       "undelete_short": "Ibalik ading {{PLURAL:$1|pagbalyow|$1 mga pagbalyow}}",
+       "viewdeleted_short": "Baydon a {{PLURAL:$1|pagbalyow|$1 mga pagbalyow}}",
+       "protect": "Protektaran",
+       "protect_change": "ribayan",
+       "protectthispage": "Protektaran ading pahina",
+       "unprotect": "Ribayan a proteksyon",
+       "unprotectthispage": "Ribayan a proteksyon kading pahina",
+       "newpage": "Bagong pahina",
+       "talkpage": "Pagbisara kading pahina",
+       "talkpagelinktext": "Magbisara",
+       "specialpage": "Espesyal na pahina",
+       "personaltools": "Mga personal na gamit",
+       "articlepage": "Baydon a loog ka pahina",
+       "talk": "Pagbisara",
+       "views": "Mga silung",
+       "toolbox": "Mga gamit",
+       "userpage": "Baydon a pahina ka paragamit",
+       "projectpage": "Baydon a pahina ka proyekto",
+       "imagepage": "Baydon a pahina ka file",
+       "mediawikipage": "Baydon a pahina ka mensahe",
+       "templatepage": "Baydon a pahina ka template",
+       "viewhelppage": "Baydon a pahina ka tabang",
+       "categorypage": "Baydon a pahina ka kategorya",
+       "viewtalkpage": "Baydon an pagbisara",
+       "otherlanguages": "Sa ibang mga ngangabilon",
+       "redirectedfrom": "(Nilipat galin sa $1)",
+       "redirectpagesub": "Pahina ka paglipat",
+       "lastmodifiedat": "Huring binago ading pahina ku $1, $2.",
+       "viewcount": "Binuksan ading pahina sa {{PLURAL:$1|beses|$1 beses}}.",
+       "protectedpage": "Protektado ading pahina",
+       "jumpto": "Lumukso sa:",
+       "jumptonavigation": "nabigasyon",
+       "jumptosearch": "anapon",
+       "pool-queuefull": "Punu a pool queue",
+       "pool-errorunknown": "Diri isi a sala",
+       "edithelp": "Tabang sa pagbalyow",
+       "mainpage": "Unang Pahina",
+       "mainpage-description": "Unang Pahina",
+       "policy-url": "Proyekto:Polisiya",
+       "portal": "Portal ka kumunidad",
+       "portal-url": "Proyekto:Portal ka kumunidad",
+       "privacy": "Polisiya ka pribasidad",
+       "privacypage": "Proyekto:Polisiya ka pribasidad",
+       "badaccess": "Sala a pagtugot",
+       "badaccess-group0": "Diri ka pwedeng gibowon a aksyon na boot mo.",
+       "ok": "Amo",
+       "retrievedfrom": "Nakuku galin sa \"$1\"",
+       "youhavenewmessages": "{{PLURAL:$3|Agko ka}} $1 ($2).",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|Agko ka}} $1 galin sa {{PLURAL:$3|ibang user|$3 users}} ($2).",
+       "youhavenewmessagesmanyusers": "Agko ka $1 galin dakul na users ($2).",
+       "newmessageslinkplural": "{{PLURAL:$1|bagong mensahe|999=mga bagong mensahe}}",
+       "newmessagesdifflinkplural": "huring {{PLURAL:$1|pagbago|999=mga pagbago}}",
+       "youhavenewmessagesmulti": "Agko ka mga bagong mensahe sa $1.",
+       "editsection": "balyowan",
+       "editold": "balyowan",
+       "viewsourceold": "baydon a ginikanan",
+       "editlink": "balyowan",
+       "viewsourcelink": "baydon a ginikanan",
+       "editsectionhint": "Balyowan a sekyon: $1",
+       "toc": "Mga loog",
+       "showtoc": "ipabayad",
+       "hidetoc": "itago",
+       "collapsible-collapse": "Ibaba",
+       "collapsible-expand": "Ibuka",
+       "confirmable-yes": "Amo",
+       "confirmable-no": "Diri",
+       "thisisdeleted": "Baydon o ibalik a $1?",
+       "viewdeleted": "Baydon a $1?",
+       "restorelink": "{{PLURAL:$1|usad na pinurang pagbalyow|$1 mga pinurang pagbalyow}}",
+       "feedlinks": "Karga:",
+       "site-rss-feed": "Kargang $1 RSS",
+       "site-atom-feed": "Kargang $1",
+       "page-rss-feed": "Kargang \"$1\" RSS",
+       "page-atom-feed": "Kargang \"$1\" Atom",
+       "red-link-title": "$1 (uda ading pahina)",
+       "nstab-main": "Pahina",
+       "nstab-user": "Pahina ka user",
+       "nstab-media": "Pahina ka media",
+       "nstab-special": "Espesyal na pahina",
+       "nstab-project": "Pahina ka proyekto",
+       "nstab-image": "File",
+       "nstab-mediawiki": "Mensahe",
+       "nstab-template": "Padron",
+       "nstab-help": "Pahina ka tabang",
+       "nstab-category": "Kategorya",
+       "nosuchaction": "Uda kan aksyon",
+       "nosuchspecialpage": "Uda ka espesyal na pahinang iyan",
+       "error": "Sala",
+       "databaseerror": "Sala a database",
+       "databaseerror-query": "Unga: $1",
+       "databaseerror-function": "Gibo: $1",
+       "databaseerror-error": "Sala: $1",
+       "missingarticle-rev": "(pagbago#: $1)",
+       "missingarticle-diff": "(Iba: $1, $2)",
+       "internalerror": "Panloog na sala",
+       "internalerror_info": "Panloog na sala: $1",
+       "filecopyerror": "Diri makopya a \"$1\" sa \"$2\".",
+       "filerenameerror": "Diri mabalyowan a ngaran ka file na \"$1\" sa \"$2\".",
+       "filedeleteerror": "Diri mapura a file na \"$1\".",
+       "directorycreateerror": "Diri magibo a direktoryong \"$1\".",
+       "filenotfound": "Diri maturakan a file na \"$1\".",
+       "formerror": "Sala: Diri maisumitir ana porma.",
+       "badarticleerror": "Diri magibo ading aksyon sadi pahina.",
+       "cannotdelete-title": "Diri mapura a pahinang \"$1\"",
+       "badtitle": "Bukung tamang titulo",
+       "viewsource": "Baydon a ginikanan",
+       "viewsource-title": "Baydon a ginikanan para sa $1",
+       "viewsourcetext": "Pwede mong silungon anggan arogon a ginikanan kading pahina:",
+       "viewyourtext": "Pwede mong silungon anggan arogon a ginikanan ku <strong?mga pagbalyow mo</strong> kading pahina:",
+       "namespaceprotected": "Uda kang permiso na balyowan a mga pahina sa <strong>$1</strong> bubutangan.",
+       "customjsprotected": "Uda kang permiso na balyowan ading pahina ka JavaScript ta agko di pansadiring settings ka ibang user.",
+       "mycustomjsprotected": "Uda ikang persmiso na balyowan ading pahinang JavaCript.",
+       "mypreferencesprotected": "Uda ikang persmiso na balyowan a kanimong mga kamuyahan.",
+       "ns-specialprotected": "Diri mababalyowan a mga espesyal na pahina.",
+       "exception-nologin": "Diri nakaloog",
+       "virus-unknownscanner": "diri ising antivirus:",
+       "welcomeuser": "Dagos, $1!",
+       "welcomecreation-msg": "Nagibo na a kanimong account.\nPwede mong ribayan a [[Special:kamuyahan|mga kamuyahan]] ka kanimong {{SITENAME}} kin boot mo.",
+       "yourname": "Pangaran:",
+       "userlogin-yourname": "Pangaran",
+       "userlogin-yourname-ph": "Ibutang a kanimong username",
+       "createacct-another-username-ph": "Ibutang a username",
+       "yourpassword": "Password:",
+       "userlogin-yourpassword": "Password",
+       "userlogin-yourpassword-ph": "Ibutang a password",
+       "createacct-yourpassword-ph": "Ibutang a password",
+       "yourpasswordagain": "Ibutang dayday a password:",
+       "createacct-yourpasswordagain": "Ikumpirmar a password",
+       "createacct-yourpasswordagain-ph": "Ibutang dayday a password",
+       "yourdomainname": "A kanimong domain:",
+       "password-change-forbidden": "Diri mo mariribayan a mga password kading wiki.",
+       "login": "Lumoog",
+       "nav-login-createaccount": "Lumoog/gumibo sa account",
+       "userlogin": "Lumoog / gumibo sa account",
+       "userloginnocreate": "Lumoog",
+       "logout": "Lumuwas",
+       "userlogout": "Lumuwas",
+       "notloggedin": "Di nakaloog",
+       "userlogin-noaccount": "Uda sa account?",
+       "userlogin-joinproject": "Bumali sa {{SITENAME}}",
+       "nologin": "Uda sa account? $1.",
+       "nologinlink": "Gumibo sa account",
+       "createaccount": "Gumibo sa account",
+       "gotaccount": "Agko na sa account? $1.",
+       "gotaccountlink": "Lumoog",
+       "userlogin-resetlink": "Nalingawan mo a detalye ku kanimong pagloog?",
+       "createacct-emailrequired": "Email address",
+       "createacct-email-ph": "Iloog a kanimong email adres",
+       "createacct-another-email-ph": "Iloog a email adres",
+       "createaccountreason": "Rason:",
+       "createacct-reason": "Rason",
+       "createacct-reason-ph": "Tauno ta muya mong gumibo sa ibang account",
+       "createacct-imgcaptcha-ph": "Ibutang a tekstong nababayad mo sa ibabow",
+       "createacct-submit": "Gumibo sa sadiring account",
+       "createacct-another-submit": "Gumibo sa ibang account",
+       "createacct-benefit-heading": "Gibo ka mga tawo pareho mo ading {{SITENAME}}.",
+       "createacct-benefit-body1": "{{PLURAL:$1|pabalyow|mga pagbalyow}}",
+       "createacct-benefit-body2": "{{PLURAL:$1|pahina|mga pahina}}",
+       "badretype": "Diri pareho a mga password na ibinutang mo.",
+       "loginerror": "Sala a pagloog",
+       "createacct-error": "Sala a paggibo sa account",
+       "createaccounterror": "Diri makagibo sa account: $1",
+       "loginsuccesstitle": "Matriyumpong nakaloog",
+       "loginsuccess": "'''Nakaloog ka na sa {{SITENAME}} bilang si \"$1\".'''",
+       "mailmypassword": "Balyowan a password",
+       "passwordremindertitle": "Bagong temporaryong password para sa {{SITENAME}}",
+       "noemailcreate": "Kaipowan mong ibutang a tamang email adres.",
+       "mailerror": "Sala ana pagpadara ka surat: $1",
+       "emaildisabled": "Diri makapadadarang surat ading sityo.",
+       "accountcreated": "Nakagibo na sa account",
+       "login-abort-generic": "A kanimong pagloog diri magibo - Pinundo.",
+       "loginlanguagelabel": "Sarita: $1",
+       "pt-login": "Lumoog",
+       "pt-login-button": "Lumoog",
+       "pt-createaccount": "Gumibo sa account",
+       "pt-userlogout": "Lumuwas",
+       "changepassword": "Balyowan a password",
+       "oldpassword": "Lumang password:",
+       "newpassword": "Bagong password:",
+       "resetpass-submit-cancel": "Kanselaron",
+       "resetpass-temp-password": "Temporaryong password:",
+       "passwordreset": "Balyowan a password",
+       "passwordreset-legend": "Balyowan a password",
+       "passwordreset-domain": "Nasasakupan:",
+       "passwordreset-email": "Email address:",
+       "changeemail": "Ribayan a email adres",
+       "changeemail-none": "(uda)",
+       "extlink_sample": "http://www.example.com titulo kan link",
+       "watchthis": "Silungon ading pahina",
+       "blockednoreason": "udang binutang na rason",
+       "nosuchsectiontitle": "diri maturakan a seksyon",
+       "loginreqlink": "lumoog",
+       "loginreqpagetext": "Paki $1 para masilung a ibang mga pahina.",
+       "newarticle": "(Bago)",
+       "updated": "(Binago)",
+       "note": "strong>Paisi:</strong>",
+       "editing": "Binabalyowan a $1",
+       "creating": "Ginigibo a $1",
+       "editingsection": "Binabalyowan a $1 (seksyon)",
+       "editingcomment": "Binabalyowan a $1 (bagong seksyon)",
+       "yourtext": "A kanimong teksto",
+       "template-protected": "(protektado)",
+       "template-semiprotected": "(medyo protektado)",
+       "defaultmessagetext": "Dating teksto ka mensahe",
+       "content-model-wikitext": "wikiteksto",
+       "content-model-text": "simpleng teksto",
+       "content-model-javascript": "JavaScript",
+       "content-model-css": "CSS",
+       "cantcreateaccounttitle": "Diri makagibo sa account",
+       "next": "sunod",
+       "last": "sinundan",
+       "page_first": "una",
+       "page_last": "huri",
+       "history-show-deleted": "Puraon sana",
+       "histfirst": "pinakaluma",
+       "histlast": "pinakabago",
+       "historysize": "({{PLURAL:$1|1 byte|$1 mga byte}})",
+       "historyempty": "(uda loog)",
+       "history-feed-item-nocomment": "$1 sa $2",
+       "rev-showdeleted": "ipabayad",
+       "revdelete-show-file-submit": "Amo",
+       "revdelete-radio-set": "Nakatago",
+       "revdelete-radio-unset": "Nababayad",
+       "revdelete-log": "Rason:",
+       "pagehist": "Kasaysayan kan pahina",
+       "revdelete-otherreason": "Iba/rugang na rason:",
+       "revdelete-reasonotherlist": "Ibang rason",
+       "mergehistory-reason": "Rason:",
+       "lineno": "Linya $1:",
+       "editundo": "ibalik",
+       "diff-empty": "(Udang pagkakaiba)",
+       "searchresults": "Resulta ka pag-anap",
+       "searchprofile-images": "Multimedia",
+       "searchprofile-everything": "Ngamin",
+       "searchprofile-articles-tooltip": "Anapon sa $1",
+       "searchprofile-everything-tooltip": "Anapon sa ngamin na loog (pati sa mga pahina ka pagbisara)",
+       "searchall": "ngamin",
+       "powersearch-toggleall": "Ngamin",
+       "powersearch-togglenone": "Uda",
+       "prefs-misc": "Misc",
+       "prefs-resetpass": "Balyowan a password",
+       "prefs-changeemail": "Ribayan a email adres",
+       "searchresultshead": "Pag-anapon",
+       "recentchangesdays": "Mga aldow na ipababayad a mga bagong pagribay:",
+       "recentchangescount": "Bilang ka pagbalow na ipababayad:",
+       "timezoneregion-africa": "Aprika",
+       "timezoneregion-america": "Amerika",
+       "timezoneregion-antarctica": "Antartika",
+       "timezoneregion-arctic": "Artiko",
+       "timezoneregion-asia": "Asya",
+       "timezoneregion-atlantic": "Kadagatan Atlantiko",
+       "timezoneregion-australia": "Australya",
+       "timezoneregion-europe": "Europa",
+       "timezoneregion-indian": "Kadagatan Indyano",
+       "timezoneregion-pacific": "Kadagatan Pasipiko",
+       "prefs-searchoptions": "Pag-anapon",
+       "default": "dati",
+       "youremail": "Email:",
+       "yourlanguage": "Sarita:",
+       "email": "Email",
+       "prefs-signature": "Pirma",
+       "prefs-editor": "Editor",
+       "userrights-reason": "Rason:",
+       "group": "Grupo:",
+       "group-bot": "Bots",
+       "group-all": "(ngamin)",
+       "right-delete": "Puraon a mga pahina",
+       "right-browsearchive": "Anapon a mga pinurang pahina",
+       "right-userrights": "Balyowan ngamin na katanusan ka user",
+       "action-edit": "balyowan ading pahina",
+       "action-createpage": "gumibo sa mga pahina",
+       "action-delete": "puraon ading pahina",
+       "action-browsearchive": "anapon a mga pinurang pahina",
+       "action-userrights": "balyowan ngamin na katanusan ka user",
+       "enhancedrc-history": "kasaysayan",
+       "rcshowhideminor-show": "Ipabayad",
+       "rcshowhideminor-hide": "Itago",
+       "rcshowhidebots": "$1 bots",
+       "rcshowhidebots-show": "Ipabayad",
+       "rcshowhidebots-hide": "Itago",
+       "rcshowhideliu-show": "Ipabayad",
+       "rcshowhideliu-hide": "Itago",
+       "rcshowhideanons-show": "Ipabayad",
+       "rcshowhideanons-hide": "Itago",
+       "rcshowhidepatr-show": "Ipabayad",
+       "rcshowhidepatr-hide": "Itago",
+       "rcshowhidemine-show": "Ipabayad",
+       "rcshowhidemine-hide": "Itago",
+       "diff": "iba",
+       "hist": "usip",
+       "hide": "Itago",
+       "show": "Ipabayad",
+       "minoreditletter": "m",
+       "newpageletter": "B",
+       "boteditletter": "b",
+       "rc_categories_any": "Dawa uno",
+       "newsectionsummary": "/* $1 */ bagong seksyon",
+       "rc-enhanced-expand": "Ipabayad a mga detalye",
+       "filename": "Filename",
+       "filesource": "Ginalinan:",
+       "watchthisupload": "Silungon ading file",
+       "backend-fail-read": "Diri mabasa a file na \"$1\".",
+       "backend-fail-create": "Diri masuratan a file na \"$1\".",
+       "nolicense": "Udang napili",
+       "listfiles-delete": "puraon",
+       "imgfile": "file",
+       "listfiles_date": "Petsa",
+       "listfiles_name": "Ngaran",
+       "listfiles-latestversion-yes": "Amo",
+       "listfiles-latestversion-no": "Diri",
+       "file-anchor-link": "File",
+       "filehist-deleteall": "puraon ngamin",
+       "filehist-datetime": "Petsa/Oras",
+       "filedelete": "Puraon a $1",
+       "filedelete-submit": "Puraon",
+       "filedelete-success": "Napura na a <strong>$1</strong>.",
+       "filedelete-otherreason": "Iba/rugang na rason:",
+       "randomincategory-category": "Kategorya:",
+       "statistics": "Estadistika",
+       "statistics-pages": "Mga pahina",
+       "statistics-views-total": "Ngamin na mga silung",
+       "brokenredirects-edit": "balyowan",
+       "brokenredirects-delete": "puraon",
+       "withoutinterwiki-submit": "Ipabayad",
+       "nbytes": "$1 {{PLURAL:$1|byte|mga bytes}}",
+       "ncategories": "{{PLURAL:$1|Kategorya|Mga kategorya}}",
+       "ninterwikis": "$1 {{PLURAL:$1|interwiki|mga interwiki}}",
+       "nlinks": "$1 {{PLURAL:$1|link|mga links}}",
+       "prefixindex": "Ngamin na mga pahina na agko prefix",
+       "protectedpages-page": "Pahina",
+       "protectedpages-reason": "Rason",
+       "protectedpages-unknown-timestamp": "Diri isi",
+       "newpages": "Mga bagong pahina",
+       "all-logs-page": "Ngamin na mga pampublikong pagloog",
+       "allpages": "Ngamin na mga pahina",
+       "nextpage": "Sunod na pahina ($1)",
+       "allarticles": "Ngamin na mga pahina",
+       "allinnamespace": "Ngamin na mga pahina ($1 butangan)",
+       "deletedcontributions": "Napurang mga ambag ka user",
+       "linksearch-ok": "Pag-anapon",
+       "listusers-submit": "Ipabayad",
+       "activeusers-hidebots": "Itago a bots",
+       "listgrouprights-group": "Grupo",
+       "listgrouprights-addgroup": "Mairurugang a {{PLURAL:$2|grupo|mga grupo}}: $1",
+       "listgrouprights-addgroup-all": "Irugang ngamin na mga grupo",
+       "listgrouprights-removegroup-all": "Galinon ngamin na mga grupo",
+       "listgrouprights-addgroup-self": "Mairurugang a {{PLURAL:$2|grupo|mga grupo}} sa sadiring account: $1",
+       "listgrouprights-addgroup-self-all": "Irugang a ngamin na mga grupo sa sadiring account",
+       "trackingcategories-name": "Ngaran ka mensahe",
+       "mailnologin": "Udang adres na mapapadarhan",
+       "noemailtitle": "Udang email adres",
+       "emailfrom": "Galin ki:",
+       "emailto": "Para ki:",
+       "emailmessage": "Mensahe:",
+       "emailccme": "Padarhi ako sa kopya ku kanakong mensahe",
+       "emailsenttext": "A kanimong email naipadara na.",
+       "watchlistfor2": "Para sa $1 $2",
+       "wlshowlast": "Ipabayad a huring $1 mga oras $2 mga aldow $3",
+       "delete-confirm": "Puraon a $1",
+       "deleteotherreason": "Iba/rugang na rason:",
+       "protect-otherreason": "Iba/rugang na rason:",
+       "restriction-edit": "Balyowan",
+       "restriction-move": "Ilipat",
+       "restriction-create": "Gumibo",
+       "restriction-upload": "Magkarga",
+       "restriction-level-all": "dawa unung lebel",
+       "undelete": "Baydon a mga napurang pahina",
+       "undeletepage": "Baydon anggan ibalik a mga napurang pahina",
+       "undeletebtn": "Ibalik",
+       "undeletelink": "baydon/ibalik",
+       "undeleteviewlink": "silungon",
+       "undeletecomment": "Rason:",
+       "undelete-search-title": "Anapon a mga pinurang pahina",
+       "undelete-search-box": "Anapon a mga pinurang pahina",
+       "undelete-search-prefix": "Ipabayad a mga pahinang nagpopoon sa",
+       "undelete-search-submit": "Pag-anapon",
+       "undelete-show-file-submit": "Ano",
+       "namespace": "Butangan:",
+       "blanknamespace": "(Una)",
+       "contributions": "Mga ambag ka {{GENDER:$1|User}}",
+       "mycontris": "Mga ambag",
+       "contribsub2": "Para sa {{GENDER:$3|$1}} ($2)",
+       "uctop": "(nguwan)",
+       "month": "Poon bulan (anggan nauna):",
+       "year": "Poon taon (anggan nauna):",
+       "sp-contributions-newbies-sub": "Para sa mga bagong account",
+       "sp-contributions-deleted": "napurang mga ambag ka user",
+       "sp-contributions-uploads": "mga karga",
+       "sp-contributions-logs": "mga loog",
+       "sp-contributions-talk": "magbisara",
+       "sp-contributions-search": "Mag-anap sa mga ambag",
+       "sp-contributions-submit": "Pag-anapon",
+       "whatlinkshere-page": "Pahina:",
+       "isredirect": "pahina ka paglipat",
+       "whatlinkshere-hideredirs": "$1 mga redirekta",
+       "ipbreason": "Rason:",
+       "ipblocklist-submit": "Pag-anapon",
+       "lockconfirm": "Amo, muya kong ikandado a database.",
+       "delete_and_move": "Puraon anggan ilipat",
+       "delete_and_move_confirm": "Amo, puraon ading pahina",
+       "export-addcattext": "Irugang a mga pahina galin sa kategorya:",
+       "export-addnstext": "Irugang a mga pahina galin sa bubutangan:",
+       "allmessagesname": "Ngaran",
+       "thumbnail_error_remote": "Salang mensahe galin sa $1: $2",
+       "tooltip-ca-delete": "Puraon ading pahina",
+       "tooltip-ca-watch": "Irugang ading pahina sa kanimong binabantayan",
+       "tooltip-search": "Mag-anap sa {{SITENAME}}",
+       "tooltip-ca-nstab-mediawiki": "Silungon a mensahe ka mensahe",
+       "tooltip-watch": "Irugang ading pahina sa kanimong binabantayan",
+       "pageinfo-contentpage-yes": "Amo",
+       "pageinfo-protect-cascading-yes": "Amo",
+       "ilsubmit": "Pag-anapon",
+       "yesterday-at": "Suhapon ku $1",
+       "exif-worldregiondest": "Ipinababayad na rehiyon ka kinaban",
+       "exif-countrycodedest": "Koda para sa ipinababayad na nasyon",
+       "exif-citydest": "Ipinababayad na syudad",
+       "exif-gaincontrol-0": "Uda",
+       "watchlistall2": "ngamin",
+       "monthsall": "ngamin",
+       "confirm-watch-top": "Muya mong irugang ading pahina sa kanimong binabantayan?",
+       "table_pager_limit": "Ipabayad a $1 na items kada pahina",
+       "version-no-ext-name": "[uda ngaran]",
+       "fileduplicatesearch-submit": "Pag-anapon",
+       "tags-active-yes": "Amo",
+       "htmlform-yes": "Amo",
+       "htmlform-cloner-create": "Rugangan pa",
+       "rightsnone": "(uda)",
+       "feedback-message": "Mensahe:",
+       "searchsuggest-search": "Pag-anapon",
+       "expand_templates_remove_nowiki": "Itago a <nowiki> tags sa resulta"
+}
index a01a3c1..ccd9718 100644 (file)
@@ -41,7 +41,8 @@
                        "Àlex",
                        "לערי ריינהארט",
                        "아라",
-                       "Calak"
+                       "Calak",
+                       "F3RaN"
                ]
        },
        "tog-underline": "Subratlla els enllaços:",
@@ -58,6 +59,7 @@
        "tog-watchdefault": "Afegeix les pàgines que vagi editant a la llista de seguiment",
        "tog-watchmoves": "Afegeix les pàgines que reanomeni a la llista de seguiment",
        "tog-watchdeletion": "Afegeix les pàgines que elimini a la llista de seguiment",
+       "tog-watchrollback": "Afegeix les pàgines on he realitzat una reversió a la llista de seguiment",
        "tog-minordefault": "Marca totes les contribucions com a edicions menors per defecte",
        "tog-previewontop": "Mostra una previsualització abans del quadre d'edició",
        "tog-previewonfirst": "Mostra una previsualització en la primera modificació",
        "talkpagelinktext": "Discussió",
        "specialpage": "Pàgina especial",
        "personaltools": "Eines de l'usuari",
-       "postcomment": "Nova secció",
        "articlepage": "Mostra la pàgina",
        "talk": "Discussió",
        "views": "Vistes",
        "otherlanguages": "En altres llengües",
        "redirectedfrom": "(S'ha redirigit des de: $1)",
        "redirectpagesub": "Pàgina de redirecció",
+       "redirectto": "Redirigeix a:",
        "lastmodifiedat": "Darrera modificació de la pàgina: $1 a les $2.",
        "viewcount": "S'ha visitat aquesta pàgina {{PLURAL:$1|una vegada|$1 vegades}}.",
        "protectedpage": "Pàgina protegida",
        "badaccess-groups": "L'acció que heu soŀlicitat es limita als usuaris {{PLURAL:$2|del grup|dels grups}}: $1.",
        "versionrequired": "Cal la versió $1 del MediaWiki",
        "versionrequiredtext": "Cal la versió $1 del MediaWiki per a utilitzar aquesta pàgina. Vegeu [[Special:Version]]",
-       "ok": "OK",
+       "ok": "D’acord",
        "retrievedfrom": "Obtingut de «$1»",
        "youhavenewmessages": "Tens $1 ($2).",
        "youhavenewmessagesfromusers": "Tens $1 {{PLURAL:$3|d'un altre usuari|de $3 usuaris}} ($2).",
        "hidetoc": "amaga",
        "collapsible-collapse": "Tanca",
        "collapsible-expand": "Amplia",
+       "confirmable-confirm": "Esteu {{GENDER:$1|segur|segura}}?",
+       "confirmable-yes": "Sí",
+       "confirmable-no": "No",
        "thisisdeleted": "Voleu mostrar o restaurar $1?",
        "viewdeleted": "Voleu mostrar $1?",
        "restorelink": "{{PLURAL:$1|una versió esborrada|$1 versions esborrades}}",
        "invalidtitle-knownnamespace": "El títol amb l'espai de noms «$2» i text «$3» no és vàlid",
        "invalidtitle-unknownnamespace": "Títol no vàlid amb espai de noms desconegut de número «$1» i text «$2»",
        "exception-nologin": "No has iniciat sessió",
-       "exception-nologin-text": "[[Special:Userlogin|Inicieu sessió]] per poder accedir a aquesta pàgina o acció.",
+       "exception-nologin-text": "Cal que inicieu una sessió per accedir a aquesta pàgina o acció.",
        "exception-nologin-text-manual": "Si us plau, $1 per poder accedir a aquesta pàgina o acció.",
        "virus-badscanner": "Mala configuració: antivirus desconegut: ''$1''",
        "virus-scanfailed": "escaneig fallit (codi $1)",
        "externaldberror": "Hi ha hagut una fallida en el servidor d'autenticació externa de la base de dades i no teniu permís per a actualitzar el vostre compte d'accès extern.",
        "login": "Inici de sessió",
        "nav-login-createaccount": "Inicia una sessió / crea un compte",
-       "loginprompt": "Heu de tenir les galetes habilitades per a poder iniciar una sessió a {{SITENAME}}.",
        "userlogin": "Inicia una sessió / crea un compte",
        "userloginnocreate": "Inici de sessió",
        "logout": "Finalitza la sessió",
        "gotaccount": "Ja teniu un compte? $1.",
        "gotaccountlink": "Inicia una sessió",
        "userlogin-resetlink": "Heu oblidat les vostres dades d'accés?",
-       "userlogin-resetpassword-link": "Has oblidat la teva contrasenya?",
+       "userlogin-resetpassword-link": "Heu oblidat la contrasenya?",
        "userlogin-helplink2": "Ajuda amb el registre",
-       "userlogin-loggedin": "Heu iniciat una sessió com {{GENDER:$1|$1}}.\nFeu servir el formulari de sota per iniciar la sessió com un altre usuari.",
-       "userlogin-createanother": "Crea un altre compte",
        "createacct-emailrequired": "Adreça de correu electrònic",
        "createacct-emailoptional": "Adreça de correu electrònic (opcional)",
        "createacct-email-ph": "Introduïu la vostra adreça de correu electrònic",
        "createaccount-text": "Algú ha creat un compte d'usuari anomenat $2 al 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 quan abans 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 - Abortada",
+       "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 tancar la sessió ja què sembla que va ser enviada per un navegador defectuós o un proxy cau.",
        "createacct-another-realname-tip": "El nom real és opcional.\nSi decidiu proporcionar-lo, s'utilitzarà per a reconèixer a l'usuari el seu treball.",
        "preview": "Previsualització",
        "showpreview": "Mostra una previsualització",
        "showdiff": "Mostra els canvis",
-       "anoneditwarning": "'''Avís:''' No esteu identificats amb un compte d'usuari. Es mostrarà la vostra adreça IP en l'historial d'aquesta pàgina.",
+       "blankarticle": "<strong>Avís:</strong> La pàgina que esteu creant és en blanc.\nSi feu clic a «{{int:savearticle}}» un altre cop, la pàgina es crearà sense cap contingut.",
+       "anoneditwarning": "<strong>Avís</strong>: No heu iniciat cap sessió. Per tant, la vostra adreça IP serà visible públicament si feu qualsevol modificació. Si <strong>[$1 inicieu una sessió]</strong> o <strong>[$2 creeu un compte]</strong>, les vostres edicions s'atribuiran al vostre nom d'usuari, juntament amb altres beneficis.",
        "anonpreviewwarning": "''No us heu identificat amb un compte d'usuari. La vostra adreça IP quedarà registrada a l'historial d'aquesta pàgina.''",
        "missingsummary": "'''Recordatori''': Heu deixat en blanc el resum de l'edició. Si torneu a clicar al botó de desar, l'edició es guardarà sense resum.",
        "missingcommenttext": "Introduïu un comentari a continuació.",
        "parser-template-recursion-depth-warning": "S'ha excedit el límit de recursivitat de plantilles ($1)",
        "language-converter-depth-warning": "El límit de la profunditat del conversor d'idiomes ha excedit ($1)",
        "node-count-exceeded-category": "Pàgines on s'ha excedit el recompte de nodes",
-       "node-count-exceeded-category-desc": "Una categoria de les pàgines on s'ha excedit el recompte de nodes.",
+       "node-count-exceeded-category-desc": "La pàgina ha excedit el compte màxim de nodes.",
        "node-count-exceeded-warning": "La pàgina ha excedit el recompte de nodes",
        "expansion-depth-exceeded-category": "Pàgines on s'ha excedit la profunditat d'expansió",
-       "expansion-depth-exceeded-category-desc": "Aquesta és una categoria de les pàgines on s'ha s'excedit la profunditat d'expansió.",
+       "expansion-depth-exceeded-category-desc": "La pàgina ha excedit la profunditat màxima d'expansió.",
        "expansion-depth-exceeded-warning": "La pàgina ha excedit la profunditat d'expansió",
        "parser-unstrip-loop-warning": "S'ha detectat un bucle no desmuntable",
        "parser-unstrip-recursion-limit": "S'ha excedit el límit ($1) de recursivitat no desmuntable",
        "currentrev": "Revisió actual",
        "currentrev-asof": "Revisió de $1",
        "revisionasof": "Revisió de $1",
-       "revision-info": "Revisió de $1; $2",
+       "revision-info": "La revisió el $1 per {{GENDER:$6|$2}}$7",
        "previousrevision": "←Versió més antiga",
        "nextrevision": "Versió més nova→",
        "currentrevisionlink": "Versió actual",
        "rev-deleted-event": "(s'ha suprimit el registre d'accions)",
        "rev-deleted-user-contribs": "[nom d'usuari o adreça IP esborrada - modificació ocultada de les contribucions]",
        "rev-deleted-text-permission": "S'ha '''suprimit''' aquesta versió de la pàgina.\nVegeu-ne més detalls al [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registre de supressions].",
+       "rev-suppressed-text-permission": "S'ha '''suprimit''' aquesta versió de la pàgina.\nVegeu-ne més detalls al [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registre de supressions].",
        "rev-deleted-text-unhide": "S'ha '''suprimit''' la revisió d'aquesta pàgina.\nHi poden haver més detalls al [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registre d'esborrats].\nEncara podeu [$1 veure aquesta revisió] si així ho desitgeu.",
        "rev-suppressed-text-unhide": "S'ha '''suprimit''' aquesta versió de la pàgina.\nHi poden haver més detalls al [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registre d'esborrats].\nEncara podeu [$1 veure aquesta revisió] si així ho desitgeu.",
        "rev-deleted-text-view": "S'ha '''suprimit''' aquesta versió de la pàgina.\nPodeu veure-la; vegeu-ne més detalls al [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registre d'esborrats].",
        "revdelete-text-text": "Les versions suprimides encara apareixeran en la pàgina d'historial, però part del seu contingut serà inaccessible al públic.",
        "revdelete-text-file": "Les versions suprimides encara apareixeran en l'historial del fitxer, però part del seu contingut serà inaccessible al públic.",
        "logdelete-text": "Els esdeveniments suprimits encara apareixeran en els registres, però part del seu contingut serà inaccessible al públic.",
-       "revdelete-text-others": "Altres administradors del projecte {{SITENAME}} podran accedir al contingut ocult i podran restaurar-lo amb aquesta mateixa interfície, llevat que s'estableixin restriccions addicionals.",
+       "revdelete-text-others": "Altres administradors podran accedir al contingut ocult i restaurar-lo, llevat que s'estableixin restriccions addicionals.",
        "revdelete-confirm": "Si us plau, confirmeu que és això el que desitgeu fer, que enteneu les conseqüències, i que esteu fent-ho d'acord amb [[{{MediaWiki:Policy-url}}|les polítiques acordades]].",
        "revdelete-suppress-text": "Les supressions '''només''' han de ser portades a terme en els següents casos:\n* Informació potencialment difamatòria\n* Informació personal inapropiada\n*: ''adreces personals, números de telèfon, números d'identificació nacional, etc.''",
        "revdelete-legend": "Defineix restriccions en la visibilitat",
        "mergehistory-empty": "No pot fusionar-se cap revisió.",
        "mergehistory-success": "$3 {{PLURAL:$3|revisió|revisions}} de [[:$1]] s'han fusionat amb èxit 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-toobig": "No s'ha pogut realitzar la fusió de l'historial perquè es mourien més del limit 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.",
        "mergehistory-invalid-source": "La pàgina d'origen ha de tenir un títol vàlid.",
        "searchprofile-advanced-tooltip": "Cerca als espais de noms predefinits",
        "search-result-size": "$1 ({{PLURAL:$2|1 paraula|$2 paraules}})",
        "search-result-category-size": "{{PLURAL:$1|1 membre|$1 membres}} ({{PLURAL:$2|1 subcategoria|$2 subcategories}}, {{PLURAL:$3|1 fitxer|$3 fitxers}})",
-       "search-result-score": "Rellevància: $1%",
        "search-redirect": "(redirigit des de $1)",
        "search-section": "(secció $1)",
        "search-file-match": "(coincideix amb el contingut del fitxer)",
        "searchall": "tots",
        "showingresults": "Tot seguit es {{PLURAL:$1|mostra el resultat|mostren els <b>$1</b> resultats començant pel número <b>$2</b>}}.",
        "showingresultsinrange": "Es mostren a continuació fins a {{PLURAL:$1|<strong>1</strong> resultat|<strong>$1</strong> resultats}} de #<strong>$2</strong> a #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Resultat '''$1''' de '''$3'''|Resultats '''$1 - $2''' de '''$3'''}} per '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Resultat <strong>$1</strong> de <strong>$3</strong>|Resultats <strong>$1 - $2</strong> de <strong>$3</strong>}}",
        "search-nonefound": "La cerca no ha donat cap resultat.",
        "powersearch-legend": "Cerca avançada",
        "powersearch-ns": "Cerca als espais de noms:",
        "preferences": "Preferències",
        "mypreferences": "Preferències",
        "prefs-edits": "Nombre d'edicions:",
-       "prefsnologintext2": "Useu $1 per configurar preferències d'usuari.",
+       "prefsnologintext2": "Inicieu una sessió per canviar les vostres preferències.",
        "prefs-skin": "Aparença",
        "skin-preview": "prova",
        "datedefault": "Cap preferència",
        "username": "{{GENDER:$1|Nom d'usuari}}:",
        "prefs-memberingroups": "{{GENDER:$2|Membre}} {{PLURAL:$1|del grup|dels grups}}:",
        "prefs-registration": "Hora de registre:",
-       "yourrealname": "Nom real *",
+       "yourrealname": "Nom real*:",
        "yourlanguage": "Idioma:",
        "yourvariant": "Variant lingüística:",
        "prefs-help-variant": "La variant lingüística o ortogràfica que preferiu a l'hora de mostrar el contingut d'aquest wiki.",
        "gender-female": "Femení",
        "prefs-help-gender": "Opcional: s'usa perquè el programari se us adreci amb missatges amb el gènere adient. Aquesta informació serà pública.",
        "email": "Correu electrònic",
-       "prefs-help-realname": "* Nom real (opcional): si escolliu donar aquesta informació serà utilitzada per a donar-vos l'atribució de la vostra feina.",
+       "prefs-help-realname": "<nowiki>*</nowiki> Nom real (opcional): si escolliu donar aquesta informació es utilitzarà per a donar-vos l’atribució de la vostra feina.",
        "prefs-help-email": "L'adreça electrònica és opcional, però permet l'enviament d'una nova contrasenya en cas que oblideu l'actual.",
        "prefs-help-email-others": "També podeu optar per deixar que els altres contactin amb vós a través de la pàgina personal de discussió, sense necessitat de desvetllar la vostra identitat.",
        "prefs-help-email-required": "Cal una adreça de correu electrònic.",
        "right-deletedtext": "Veure el text esborrat i els canvis entre revisions esborrades",
        "right-browsearchive": "Cercar pàgines esborrades",
        "right-undelete": "Restaurar pàgines esborrades",
-       "right-suppressrevision": "Revisar i restaurar les versions amagades als administradors",
+       "right-suppressrevision": "Mostra, amaga i revela revisions específiques de pàgines d'un usuari",
+       "right-viewsuppressed": "Mostra les revisions amagades de qualsevol usuari",
        "right-suppressionlog": "Veure registres privats",
        "right-block": "Blocar altres usuaris per a impedir-los l'edició",
        "right-blockemail": "Impedir que un usuari envii correu electrònic",
        "recentchanges-legend-heading": "'''Llegenda:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vegeu també la [[Special:NewPages|llista de pàgines noves]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "A sota hi ha els canvis des de <strong>$2</strong> (es mostren fins <strong>$1</strong>).",
+       "rcnotefrom": "A sota hi ha {{PLURAL:$5|el canvi|els canvis}} a partir de <strong>$3, $4</strong> (fins a <strong>$1</strong>).",
        "rclistfrom": "Mostra els canvis nous des de $3 $2",
        "rcshowhideminor": "$1 edicions menors",
        "rcshowhideminor-show": "Mostra",
        "largefileserver": "Aquest fitxer és més gran del que el servidor permet.",
        "emptyfile": "El fitxer que heu carregat sembla estar buit.\nAçò por ser degut a un mal caràcter en el nom del fitxer.\nComproveu si realment voleu carregar aquest fitxer.",
        "windows-nonascii-filename": "Aquest wiki no permet noms de fitxer amb caràcters especials.",
-       "fileexists": "Ja hi existeix un fitxer amb aquest nom, si us plau, verifiqueu <strong>[[:$1]]</strong> si no esteu segurs de voler substituir-lo.\n[[$1|thumb]]",
+       "fileexists": "Ja existeix un fitxer amb aquest nom. Comproveu <strong>[[:$1]]</strong> si no esteu {{GENDER:|segur|segura}} de voler substituir-lo.\n[[$1|thumb]]",
        "filepageexists": "La pàgina de descripció d'aquest fitxer ja ha estat creada (<strong>[[:$1]]</strong>), però de moment no hi ha cap fitxer amb aquest nom. La descripció que heu posat no apareixerà a la pàgina de descripció. Si voleu que hi aparegui haureu d'editar-la manualment.\n[[$1|thumb]]",
        "fileexists-extension": "Ja existeix un fitxer amb un nom semblant: [[$2|thumb]]\n* Nom del fitxer que es puja: <strong>[[:$1]]</strong>\n* Nom del fitxer existent: <strong>[[:$2]]</strong>\nPotser voleu fer servir un nom més fàcil de distingir?",
        "fileexists-thumbnail-yes": "Aquest fitxer sembla ser una imatge en mida reduïda (<em>miniatura</em>). [[$1|thumb]]\nComproveu si us plau el fitxer <strong>[[:$1]]</strong>.\nSi el fitxer és la mateixa imatge a mida original, no cal carregar cap miniatura més.",
        "uploadwarning": "Avís de càrrega",
        "uploadwarning-text": "Modifiqueu la descripció de la imatge i torneu a intentar-ho.",
        "savefile": "Desa el fitxer",
-       "uploadedimage": "ha carregat [[$1]]",
-       "overwroteimage": "ha carregat una nova versió de «[[$1]]»",
        "uploaddisabled": "S'ha inhabilitat la càrrega",
        "copyuploaddisabled": "Càrrega per URL deshabilitada.",
        "uploaddisabledtext": "S'ha inhabilitat la càrrega de fitxers.",
        "license": "Llicència:",
        "license-header": "Llicència",
        "nolicense": "No se n'ha seleccionat cap",
+       "licenses-edit": "Modifica les opcions de llicència",
        "license-nopreview": "(Previsualització no disponible)",
-       "upload_source_url": " (un URL vàlid i accessible públicament)",
-       "upload_source_file": " (un fitxer en el vostre ordinador)",
+       "upload_source_url": " (el fitxer que heu seleccionat des d'un URL vàlid i accessible públicament)",
+       "upload_source_file": " (un fitxer triat del vostre ordinador)",
+       "listfiles-delete": "elimina",
        "listfiles-summary": "Aquesta pàgina especial mostra tots els fitxers carregats.\nSi filtreu per usuari només es mostraran els fitxers la versió més recent dels quals hagi estat carregada per aquell.",
        "listfiles_search_for": "Cerca el nom d'un fitxer de medis:",
        "imgfile": "fitxer",
        "randomincategory": "Pàgina aleatòria en una categoria",
        "randomincategory-invalidcategory": "«$1» no és un nom de categoria vàlid.",
        "randomincategory-nopages": "No hi ha pàgines a la categoria [[:Category:$1|$1]].",
-       "randomincategory-selectcategory": "Obté una pàgina a l'atzar de la categoria: $1 $2.",
-       "randomincategory-selectcategory-submit": "Vés-hi",
+       "randomincategory-category": "Categoria:",
+       "randomincategory-legend": "Pàgina a l’atzar en la categoria",
        "randomredirect": "Redirecció a l'atzar",
        "randomredirect-nopages": "No hi ha cap redirecció a l'espai de noms «$1».",
        "statistics": "Estadístiques",
        "wantedpages": "Pàgines demanades",
        "wantedpages-badtitle": "Títol invàlid al conjunt de resultats: $1",
        "wantedfiles": "Fitxers demanats",
-       "wantedfiletext-cat": "Els fitxers següents s'utilitzen per no existeixen. Els fitxers de repositoris aliens poden ser llistats encara que existeixin. Aquells que siguin fals positius es <del>tatxaran</del>. A més, les pàgines que tinguin fitxers incrustats que no existeixin es llistaran a [[:$1]].",
+       "wantedfiletext-cat": "Els fitxers següents s'utilitzen per no existeixen. Els fitxers de repositoris aliens poden ser llistats encara que existeixin. Aquells que siguin fals positius es <del>ratllaran</del>. A més, les pàgines que tinguin fitxers incrustats que no existeixin es llistaran a [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Els fitxers següents s'utilitzen, però no existeixen. Addicionalment, s'enumeren a [[:$1]] les pàgines que tenen fitxers inserits que no existeixen.",
        "wantedfiletext-nocat": "Els fitxers següents es fan servir però no existeixen. Els fitxers d'un repositori aliè poden ser llistats encara que existeixin. Tots aquells fals positius es <del>tatxaran</del>.",
+       "wantedfiletext-nocat-noforeign": "Els fitxers següents s'utilitzen però no existeixen.",
        "wantedtemplates": "Plantilles demanades",
        "mostlinked": "Pàgines més enllaçades",
        "mostlinkedcategories": "Categories més utilitzades",
        "trackingcategories-desc": "Criteris d'inclusió de categoria",
        "noindex-category-desc": "La pàgina conté una paraula màgica <code><nowiki>__NOINDEX__</nowiki></code> (i és en un espai de noms on està permesa) i per tant no està indexada per robots.",
        "index-category-desc": "La pàgina conté un <code><nowiki>__INDEX__</nowiki></code> (i és en un espai de noms on està permès) i per tant està indexat per robots quan normalment no ho seria.",
-       "post-expand-template-inclusion-category-desc": "Després d'expandir totes les plantilles, la mida de la pàgina és més gran que <code>$wgMaxArticleSize</code>, per tant algunes plantilles no s'han expandit.",
-       "post-expand-template-argument-category-desc": "Després d'expandir un argument de plantilla (alguna cosa entre claus triples, com <code>{{{Això}}}</code>), la pàgina és més gran que <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Massa funcions d'analitzador costoses (com <code>#ifexist</code>) incloses en una pàgina. Vegeu [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Categoria afegida si la pàgina conté un enllaç de fitxer trencat (un enllaç per inserir un fitxer quan aquest fitxer no existeix).",
-       "hidden-category-category-desc": "Aquesta és una categoria que conté <code><nowiki>__HIDDENCAT__</nowiki></code>, que impedeix que aparegui en la caixa d'enllaços de categoria a les pàgines, per defecte.",
+       "post-expand-template-inclusion-category-desc": "La mida de la pàgina és més gran que <code>$wgMaxArticleSize</code> un cop expandides totes les plantilles, per tant algunes plantilles no s'han expandit.",
+       "post-expand-template-argument-category-desc": "La pàgina és més gran que <code>$wgMaxArticleSize</code> després d'expandir un argument de plantilla (quelcom entre claus triples, com ara <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "La pàgina utilitza massa funcions d'analitzador costoses (com <code>#ifexist</code>). Vegeu [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "La pàgina conté un enllaç de fitxer trencat (un enllaç per inserir un fitxer quan aquest fitxer no existeix).",
+       "hidden-category-category-desc": "La categoria conté <code><nowiki>__HIDDENCAT__</nowiki></code> en el contingut de la pàgina, fet que impedeix que aparegui en la caixa d'enllaços de categoria a les pàgines per defecte.",
        "trackingcategories-nodesc": "Sense descripció disponible.",
        "trackingcategories-disabled": "La categoria està inhabilitada",
        "mailnologin": "Cap adreça de remitent",
        "mywatchlist": "Llista de seguiment",
        "watchlistfor2": "Per $1 $2",
        "nowatchlist": "No teniu cap element en la vostra llista de seguiment.",
-       "watchlistanontext": "Premeu $1 per a visualitzar o modificar elements de la vostra llista de seguiment.",
+       "watchlistanontext": "Inicieu una sessió per a visualitzar o modificar elements de la vostra llista de seguiment.",
        "watchnologin": "No heu iniciat la sessió",
        "addwatch": "Afegeix a llista de seguiment",
        "addedwatchtext": "S'ha afegit la pàgina \"[[:$1]]\" a la vostra [[Special:Watchlist|llista de seguiment]].\nS'hi mostraran els canvis futurs que tinguin lloc en aquesta pàgina i la corresponent discussió.",
        "watchlist-details": "Teniu $1 {{PLURAL:$1|pàgina|pàgines}} a la llista de seguiment, sense comptar les pàgines de discussió.",
        "wlheader-enotif": "La notificació per correu electrònic està habilitada.",
        "wlheader-showupdated": "Les pàgines que s'han canviat des de la vostra darrera visita es mostren en '''negreta'''.",
-       "wlnote2": "A continuació es presenten els canvis durant {{PLURAL:$1|l'última hora|les últimes <strong>$1</strong> hores}}, a partir de $2, $3.",
+       "wlnote": "A sota hi ha {{PLURAL:$1|el darrer canvi|els darrers <strong>$1</strong> canvis}} en {{PLURAL:$2|la darrera hora|les <strong>$2</strong> darreres hores}}, a $4 del $3.",
        "wlshowlast": "<small>- Mostra les darreres $1 hores, els darrers $2 dies o $3</small>",
        "watchlist-options": "Opcions de la llista de seguiment",
        "watching": "S'està vigilant...",
        "exbeforeblank": "el contingut abans de buidar era: '$1'",
        "delete-confirm": "Elimina «$1»",
        "delete-legend": "Elimina",
-       "historywarning": "'''Atenció:''' La pàgina que esteu a punt d'eliminar té un historial amb $1 {{PLURAL:$1|versió|versions}}, aproximadament:",
+       "historywarning": "<strong>Avís:</strong> la pàgina que esteu a punt d'eliminar té un historial amb $1 {{PLURAL:$1|revisió|revisions}}:",
        "confirmdeletetext": "Esteu a punt d'esborrar de forma permanent una pàgina o imatge i tot el seu historial de la base de dades.\nConfirmeu que realment ho voleu fer, que enteneu les\nconseqüències, i que el que esteu fent està d'acord amb la [[{{MediaWiki:Policy-url}}|política]] del projecte.",
-       "actioncomplete": "S'ha realitzat l'acció de manera satisfactòria.",
+       "actioncomplete": "Acció realitzada",
        "actionfailed": "L'acció ha fallat",
        "deletedtext": "S'ha suprimit «$1».\nVegeu $2 per a un registre dels esborrats més recents.",
        "dellogpage": "Registre d'eliminació",
        "delete-edit-reasonlist": "Edita els motius d'eliminació",
        "delete-toobig": "Aquesta pàgina té un historial d'edicions molt gran, amb més de $1 {{PLURAL:$1|canvi|canvis}}. L'eliminació d'aquestes pàgines està restringida per a prevenir que hi pugui haver un desajustament seriós de la base de dades de tot el projecte {{SITENAME}} per accident.",
        "delete-warning-toobig": "Aquesta pàgina té un historial d'edicions molt gran, amb més de $1 {{PLURAL:$1|canvi|canvis}}. Eliminar-la podria suposar un seriós desajustament de la base de dades de tot el projecte {{SITENAME}}; aneu en compte abans dur a terme l'acció.",
+       "deleteprotected": "No podeu eliminar la pàgina perquè ha estat protegida.",
        "deleting-backlinks-warning": "'''Avís:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Altres pàgines]] enllacen o transclouen de la pàgina que esteu a punt de suprimir.",
        "rollback": "Reverteix edicions",
        "rollback_short": "Revoca",
        "autoblockid": "Autoblocatge #$1",
        "block": "Blocatge d'usuaris",
        "unblock": "Desblocatge d'usuaris",
-       "blockip": "Bloqueig d'usuaris",
+       "blockip": "Bloca {{GENDER:$1|l'usuari|l'usuària}}",
        "blockip-legend": "Bloca l'usuari",
        "blockiptext": "Empreu el següent formulari per blocar l'accés\nd'escriptura des d'una adreça IP específica o des d'un usuari determinat.\naixò només s'hauria de fer per prevenir el vandalisme, i\nd'acord amb la [[{{MediaWiki:Policy-url}}|política del projecte]].\nEmpleneu el diàleg de sota amb un motiu específic (per exemple, citant\nquines pàgines en concret estan sent vandalitzades).",
        "ipaddressorusername": "Adreça IP o nom de l'usuari",
        "ipb-unblock-addr": "Desbloca $1",
        "ipb-unblock": "Desbloca un usuari o una adreça IP",
        "ipb-blocklist": "Llista els bloquejos existents",
-       "ipb-blocklist-contribs": "Contribucions de $1",
+       "ipb-blocklist-contribs": "Contribucions de {{GENDER:$1|$1}}",
        "unblockip": "Desbloca l'usuari",
        "unblockiptext": "Empreu el següent formulari per restaurar\nl'accés a l'escriptura a una adreça IP o un usuari prèviament bloquejat.",
        "ipusubmit": "Desbloca aquesta adreça",
        "unblocked": "S'ha desbloquejat l'{{GENDER:$1|usuari|usuària}} [[User:$1|$1]]",
        "unblocked-range": "s'ha desblocat $1",
        "unblocked-id": "S'ha eliminat el bloqueig de $1",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] ha estat desbloquejat.",
        "blocklist": "Usuaris blocats",
        "ipblocklist": "Usuaris blocats",
        "ipblocklist-legend": "Cerca un usuari blocat",
        "import": "Importació de pàgines",
        "importinterwiki": "Importa interwiki",
        "import-interwiki-text": "Trieu un web basat en wiki i un títol de pàgina per a importar.\nEs conservaran les dates de les versions i els noms dels editors.\nTotes les accions d'importació interwiki es conserven al [[Special:Log/import|registre d'importacions]].",
-       "import-interwiki-source": "Pàgina/wiki d'origen:",
+       "import-interwiki-sourcewiki": "Wiki d'origen:",
+       "import-interwiki-sourcepage": "Pàgina d'origen:",
        "import-interwiki-history": "Copia totes les versions de l'historial d'aquesta pàgina",
        "import-interwiki-templates": "Inclou totes les plantilles",
        "import-interwiki-submit": "Importa",
        "import-invalid-interwiki": "No es pot importar des del wiki especificat.",
        "import-error-edit": "La pàgina «$1» no s'ha importat perquè no teniu permís per modificar-la.",
        "import-error-create": "La pàgina «$1» no s'ha importat perquè no teniu permís per crear-la.",
-       "import-error-interwiki": "No s'importa la pàgina «$1» perquè el seu nom està reservat a l'enllaçament extern (interwiki).",
+       "import-error-interwiki": "No s'ha importat la pàgina «$1» perquè el seu nom està reservat per a enllaços externs (interwiki).",
        "import-error-special": "No s'importa la pàgina «$1» perquè el seu nom pertany a l'espai de noms especial que no permet pàgines.",
        "import-error-invalid": "No s'importa la pàgina «$1» perquè el seu nom no és vàlid.",
        "import-error-unserialize": "La revisió $2 de la pàgina \"$1\" no pot ser desserialitzada. La revisió indica que utilitza el model de contingut $3 serialitzat com a $4.",
        "importlogpage": "Registre d'importació",
        "importlogpagetext": "Importacions administratives de pàgines amb l'historial des d'altres wikis.",
        "import-logentry-upload": "ha importat [[$1]] per càrrega de fitxers",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revisió|revisions}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revisió|revisions}} importades",
        "import-logentry-interwiki": "s'ha importat $1 via interwiki",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisió|revisions}} de $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisió|revisions}} importades de $2",
        "javascripttest": "Proves de JavaScript",
        "javascripttest-title": "S'estan executant $1 proves",
        "javascripttest-pagetext-noframework": "Es reserva la pàgina per a l'execució de tests amb JavaScript.",
        "autosumm-replace": "Contingut canviat per «$1».",
        "autoredircomment": "Redirecció a [[$1]]",
        "autosumm-new": "Es crea la pàgina amb «$1».",
+       "autosumm-newblank": "S'ha creat una pàgina en blanc",
        "lag-warn-normal": "Els canvis més nous de $1 {{PLURAL:$1|segon|segons}} podrien no mostrar-se a la llista.",
        "lag-warn-high": "A causa de la lenta resposta del servidor de base de dades, els canvis més nous de $1 {{PLURAL:$1|segon|segons}} potser no es mostren aquesta llista.",
        "watchlistedit-normal-title": "Edita la llista de seguiment",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discussió]])",
        "unknown_extension_tag": "Etiqueta d'extensió desconeguda «$1»",
        "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».",
        "version": "Versió",
        "version-extensions": "Extensions instaŀlades",
-       "version-skins": "Aparences",
+       "version-skins": "Temes instal·lats",
        "version-specialpages": "Pàgines especials",
        "version-parserhooks": "Extensions de l'analitzador",
        "version-variables": "Variables",
        "logentry-rights-rights": "$1 {{GENDER:$2|ha canviat}} la pertinença de grup per $3 de $4 a $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|ha canviat}} la pertinença de grup per $3",
        "logentry-rights-autopromote": "$1 ha estat {{GENDER:$2|promogut}} automàticament de $4 a $5",
+       "logentry-upload-upload": "$1 {{GENDER:$2|ha carregat}} $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|ha carregat}} una nova versió de $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|ha carregat}} $3",
        "rightsnone": "(cap)",
        "feedback-bugornote": "Si podeu descriure un problema tècnic en detall, [$1 informeu-ne].\nAltrament, podeu fer servir un senzill formulari a continuació. El vostre comentari s'afegirà a la pàgina «[$3 $2]», juntament amb el vostre nom d'usuari i el navegador que esteu emprant.",
        "feedback-subject": "Assumpte:",
        "expand_templates_output": "Resultat:",
        "expand_templates_xml_output": "Sortida XML",
        "expand_templates_html_output": "Sortida en HTML sense filtrar",
-       "expand_templates_ok": "OK",
+       "expand_templates_ok": "D’acord",
        "expand_templates_remove_comments": "Elimina els comentaris",
        "expand_templates_remove_nowiki": "Suprimeix l'etiqueta <nowiki> en el resultat",
        "expand_templates_generate_xml": "Mostra l'arbre XML",
        "pagelang-use-default": "Utilitza l'idioma per defecte",
        "pagelang-select-lang": "Selecciona un idioma",
        "right-pagelang": "Canvia l'idioma de la pàgina",
-       "action-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-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-row-enabled": "* <code>$1</code> / $2 (habilitat)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''inhabilitat''')"
 }
index f69fec2..2dd4f9d 100644 (file)
@@ -6,14 +6,20 @@
                        "Yejianfei",
                        "Hakka",
                        "아라",
-                       "Mywood"
+                       "Mywood",
+                       "Impersonator 1",
+                       "LNDDYL",
+                       "唐吉訶德的侍從"
                ]
        },
        "tog-underline": "下劃綫鏈接",
        "tog-hideminor": "藏起最近改變其過要修改",
        "tog-hidepatrolled": "藏起最近改變其巡邏修改",
+       "tog-extendwatchlist": "敆擴展監視單單臺中顯示所有其更改,伓啻最近其更改",
        "tog-numberheadings": "自動編號其標題",
+       "tog-showtoolbar": "顯示編輯工具欄",
        "tog-editondblclick": "雙擊就修改頁面",
+       "tog-editsectiononrightclick": "啟用右擊標題編輯段落",
        "tog-watchcreations": "加添我開其頁面共我上傳其文件遘我其監視單",
        "tog-watchdefault": "添加我編輯其頁面共文件遘我其監視單",
        "tog-watchmoves": "添加我移動其頁面共文件遘我其監視單",
        "category-empty": "''茲類別下底現在無文章也無媒體。''",
        "hidden-categories": "{{PLURAL:$1}}乞藏起其類別",
        "hidden-category-category": "已經藏起其類別",
+       "category-subcat-count": "{{PLURAL:$2|茲萆分類僅包括下底蜀萆子分類|茲分類有 {{PLURAL:$1|子分類|$1 萆子分類}},總計 $2 萆。}}",
        "category-subcat-count-limited": "茲蜀萆類別下底有子類別{{PLURAL:$1}}",
        "category-article-count": "{{PLURAL:$2|茲蜀萆類別儷有下底蜀頁。|共總有$2頁,下底其茲$1頁敆茲蜀萆類別𡅏。}}",
        "category-article-count-limited": "下底$1頁敆茲蜀萆類別𡅏{{PLURAL:$1}}",
        "history_short": "歷史",
        "updatedmarker": "趁我最後蜀回訪問開始更新",
        "printableversion": "會拍印其版本",
-       "permalink": "固定链接",
+       "permalink": "永久鏈接",
        "print": "拍印",
        "view": "覷蜀覷",
        "edit": "修改",
        "talkpagelinktext": "討論",
        "specialpage": "特殊頁",
        "personaltools": "個人其家私",
-       "postcomment": "新其蜀段",
        "articlepage": "覷蜀覷內容頁面",
        "talk": "討論",
        "views": "覷蜀覷",
        "otherlanguages": "其它其語言",
        "redirectedfrom": "(由$1重定向過來)",
        "redirectpagesub": "重定向頁",
-       "lastmodifiedat": "茲頁面是著$2, $1時候修改其。",
+       "lastmodifiedat": "茲蜀頁是着$1 $2其辰候最後修改其。",
        "viewcount": "茲蜀頁已經乞訪問$1回了。{{PLURAL:$1}}",
        "protectedpage": "保護頁",
        "jumpto": "跳遘:",
        "badaccess": "權限錯誤",
        "badaccess-group0": "汝𣍐使做汝要求其茲蜀萆動作。",
        "badaccess-groups": "汝要求其動作著$2底裏用戶才會做其:$1{{PLURAL:$1}}",
-       "versionrequired": "需要版本$1其媒體維基",
-       "versionrequiredtext": "需要媒體維基其版本$1來使茲蜀頁。\n覷[[Special:Version|版本頁面]]。",
+       "versionrequired": "需要版本$1其MediaWiki",
+       "versionrequiredtext": "需要MediaWiki其版本$1來使茲蜀頁。\n覷[[Special:Version|版本頁面]]。",
        "ok": "好",
        "retrievedfrom": "趁「$1」退過來",
        "youhavenewmessages": "汝有$1($2)。",
        "toc": "目錄",
        "showtoc": "顯示",
        "hidetoc": "藏起",
-       "collapsible-collapse": "崩潰",
-       "collapsible-expand": "擴展",
+       "collapsible-collapse": "",
+       "collapsible-expand": "",
        "thisisdeleted": "卜看或者恢復$1?",
        "viewdeleted": "看$1?",
        "restorelink": "$1萆乞刪掉其修改{{PLURAL:$1}}",
        "nosuchspecialpage": "無總款其特殊頁",
        "nospecialpagetext": "<strong>汝請求蜀萆𣍐合法其特殊頁面。</strong>\n\n合法其特殊頁面清單會使敆[[Special:SpecialPages|{{int:特殊頁面}}]]頁面討著",
        "error": "鄭咯",
-       "databaseerror": "數據庫有",
+       "databaseerror": "數據庫有",
        "laggedslavemode": "'''警告:'''頁面可能無最近其更新。",
        "readonly": "數據庫乞鎖起咯",
        "readonlytext": "Só-gé̤ṳ-kó cī-buàng ké̤ṳk nè̤ng sō̤ kī lāu, mâ̤-sāi siā sĭng dèu-mĕ̤k hĕ̤k có̤ siŭ-gāi, ô kō̤-nèng sê ôi-lāu nĭk-siòng mì-hô, cĭ-hâiu cêu â̤ ciáng-siòng.\n\nSō̤ kī só-gé̤ṳ-kó gì guāng-lī-uòng cūng-kuāng gāi-sék: $1",
        "badtitle": "獃其標題",
        "perfcached": "下底其數據乞緩存固加可能伓是最新其。{{PLURAL:$1|$1條結果}}會敆緩存臺中討著。",
        "perfcachedts": "下底其數據已經緩存過了,最後更新遘$1。{{PLURAL:$4|$4條結果}}會敆緩存臺中討著。",
-       "querypage-no-updates": "茲蜀頁其更新乞禁止了。\n數據塊現刻時𣍐更新了。",
+       "querypage-no-updates": "茲蜀頁其更新乞禁止了。\n數據塊現刻時𣍐更新了。",
        "viewsource": "看源代碼",
        "viewsource-title": "覷蜀覷$1其源代碼",
        "actionthrottled": "行動乞取消咯",
        "protectedpagetext": "茲頁已經乞保護起咯,𣍐使修改或者其它行動。",
        "viewsourcetext": "汝會使看共複製茲蜀頁其源代碼:",
        "viewyourtext": "汝會使覷蜀覷或者複製茲頁'''汝其修改'''其源代碼:",
-       "editinginterface": "'''警告:'''汝敆𡅏修改其頁面廮𡅏提供茲蜀萆軟件其界面文本。\n茲蜀頁其改變會影響遘其它用戶其用戶界面其顯示。\n如果蔔想修改維基其翻譯,起動遘媒體維基本地化計劃[//translatewiki.net/wiki/Main_Page?setlang=en translatewiki.net]。",
+       "editinginterface": "'''警告:'''汝敆𡅏修改其頁面廮𡅏提供茲蜀萆軟件其界面文本。\n茲蜀頁其改變會影響遘其它用戶其用戶界面其顯示。\n如果卜想修改維基其翻譯,起動遘MediaWiki本地化計劃[//translatewiki.net/wiki/Main_Page?setlang=en translatewiki.net]。",
        "namespaceprotected": "汝𣍐使修改敆'''$1'''命名空間其頁面。",
        "customcssprotected": "汝𣍐使修改茲蜀萆CSS頁面,因為伊有別蜀隻用戶其設定。",
        "customjsprotected": "汝𣍐使修改茲蜀萆JavaScript頁面,因為伊有別蜀隻用戶其設定。",
        "userlogin-signwithsecure": "使安全其連接",
        "yourdomainname": "汝其域名:",
        "password-change-forbidden": "汝𣍐使敆茲蜀萆維基百科𡅏修改密碼。",
-       "externaldberror": "可能是驗證數據庫咯,或者是汝𣍐使升級汝其外部賬戶。",
+       "externaldberror": "可能是驗證數據庫咯,或者是汝𣍐使升級汝其外部賬戶。",
        "login": "躒底",
        "nav-login-createaccount": "躒底/開賬戶",
-       "loginprompt": "汝著清除cookies才會底{{SITENAME}}。",
        "userlogin": "躒底/開賬戶",
        "userloginnocreate": "躒底",
        "logout": "躒出",
        "gotaccountlink": "躒底",
        "userlogin-resetlink": "躒底其資料𣍐記咯?",
        "userlogin-resetpassword-link": "密码𣍐記?",
+       "userlogin-helplink2": "對手汝躒底",
        "createacct-emailrequired": "電子郵件地址",
        "createacct-emailoptional": "電子郵件地址(愛寫就寫)",
        "createacct-email-ph": "輸底汝其電子郵件地址",
        "passwordtooshort": "密碼著設最少{{PLURAL:$1|$1萆字符}}。",
        "password-name-match": "汝其密碼硬著共汝其用戶名𣍐蜀様才會使其。",
        "password-login-forbidden": "茲蜀萆用戶名共密碼應經乞禁止去了。",
-       "mailmypassword": "共新密碼發遘電子郵件",
+       "mailmypassword": "重新設置密碼",
        "passwordremindertitle": "{{SITENAME}}其新其臨時密碼",
        "passwordsent": "新密碼已經寄遘「$1」註冊其電子郵件地址了。\n收遘後,請再躒底蜀頭部。",
        "mailerror": "發電子郵件有賺:$1",
        "resetpass-submit-cancel": "取消",
        "resetpass-temp-password": "臨時密碼:",
        "passwordreset": "重置密碼",
+       "passwordreset-text-one": "完成者隻表單,通過電子郵件發送臨時密碼來重新設定汝其密碼。",
        "passwordreset-legend": "重置密碼",
        "passwordreset-username": "用戶名:",
        "passwordreset-domain": "域名:",
        "prefs-personal": "用戶資料",
        "prefs-rc": "這般其改變",
        "prefs-watchlist": "監視單",
+       "prefs-watchlist-days": "監視單單臺中顯示其天數",
+       "prefs-watchlist-edits": "敆擴展監視其單單臺中顯示其更改其最大數目:",
        "prefs-misc": "其它",
        "saveprefs": "保存",
+       "prefs-editing": "編輯",
+       "rows": "行數:",
        "searchresultshead": "尋討",
        "recentchangescount": "這般改變其條目:",
        "savedprefs": "汝其設定已經乞保存了。",
        "yournick": "新其簽名:",
        "email": "電子郵件",
        "prefs-help-email": "電子郵件地址是愛寫就寫其,但是如果汝𣍐記密碼咯,密碼重置其時候需要茲。",
+       "prefs-help-email-others": "汝也會使選擇讓其他其用戶通過汝其用戶頁面或者討論頁面懸頂其鏈接,使電子郵件來聯繫汝。其他其用戶聯繫汝其辰候,汝其電子郵件地址𣍐顯示出來。",
        "editusergroup": "修改用戶組",
        "group": "組:",
        "group-bot": "機器人",
        "rclinks": "顯示$2日以內產生其$1回改變<br />$3",
        "diff": "差",
        "hist": "史",
-       "hide": "藏起",
-       "show": "顯示",
+       "hide": "",
+       "show": "",
        "minoreditletter": "~",
        "newpageletter": "!",
        "boteditletter": "^",
        "fileexists": "名字蜀樣其文件已經存在去了。如果汝𣍐確定汝是伓是卜想刪掉伊,起動檢查蜀下<strong>[[:$1]]</strong>。\n[[$1|thumb]]",
        "uploadwarning": "上傳警告",
        "savefile": "保存文件",
-       "uploadedimage": "已經上傳其「[[$1]]」",
        "uploadvirus": "茲文件有病毒!\n細底:$1",
        "sourcefilename": "源文件名:",
        "destfilename": "目標文件名:",
        "sp-contributions-search": "尋討貢獻",
        "sp-contributions-username": "IP地址或者用戶名:",
        "sp-contributions-submit": "尋討",
-       "whatlinkshere": "什乇鏈遘嚽塊",
+       "whatlinkshere": "甚乇鏈遘租塊",
        "whatlinkshere-title": "鏈接遘$1其頁面",
        "whatlinkshere-page": "頁面:",
        "linkshere": "下底其頁面鏈接遘'''[[:$1]]''':",
        "block-log-flags-nocreate": "防止開賬戶",
        "ipb_expiry_invalid": "過期時間無效。",
        "ipb_already_blocked": "「$1」已經乞封鎖了",
-       "lockconfirm": "正,我卜想鎖定數據庫。",
+       "lockconfirm": "正,我卜想鎖定數據庫。",
        "lockbtn": "鎖定數據庫",
        "unlockbtn": "開數據庫",
        "lockdbsuccesssub": "數據庫鎖定好了",
        "allmessagesname": "名",
        "allmessagesdefault": "默認其消息文字",
        "allmessagescurrent": "現時其文字",
-       "allmessagestext": "茲是敆媒體維基命名空間底裏系統消息其蜀萆單單。\n如果汝卜想貢獻通用其媒體維基本地化服務,請訪問[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation 媒體維基本地化]共[//translatewiki.net translatewiki.net]。",
+       "allmessagestext": "茲是敆MediaWiki命名空間裏勢系統消息其蜀萆單單。\n如果汝卜想貢獻通用其MediaWiki基本地化服務,起動汝訪問[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki本地化]共[//translatewiki.net translatewiki.net]。",
        "allmessagesnotsupportedDB": "茲蜀頁𣍐使其,因為'''$wgUseDatabaseMessages'''已經乞禁止去了。",
        "thumbnail-more": "放大",
        "tooltip-pt-userpage": "汝其用戶頁",
        "tooltip-pt-mytalk": "汝其討論頁",
        "tooltip-pt-preferences": "汝其設定",
+       "tooltip-pt-watchlist": "汝監視其頁面有改過其單單",
+       "tooltip-pt-mycontris": "汝其貢獻其單單",
        "tooltip-pt-login": "希望汝躒底其;當然,無逼汝總款做。",
        "tooltip-pt-logout": "躒出",
        "tooltip-ca-talk": "茲蜀頁其討論",
        "tooltip-ca-edit": "汝會使修改茲蜀頁。起動敆保存以前使預覽按鈕",
        "tooltip-ca-addsection": "開始蜀萆新其部分",
        "tooltip-ca-viewsource": "茲蜀頁乞保護起去。\n汝會使看伊其源代碼。",
+       "tooltip-ca-history": "覷茲頁舊底其版本",
        "tooltip-ca-protect": "保護茲蜀頁",
        "tooltip-ca-delete": "刪掉茲蜀頁",
        "tooltip-ca-move": "移動茲蜀頁",
        "tooltip-n-mainpage-description": "覷蜀覷頭頁",
        "tooltip-n-recentchanges": "維基百科最近其改變其單單",
        "tooltip-n-randompage": "隨便罔看",
-       "tooltip-t-whatlinkshere": "鏈遘嚽塊其所有維基頁面其單單",
+       "tooltip-t-whatlinkshere": "鏈遘租塊其所有維基頁面其單單",
+       "tooltip-t-recentchangeslinked": "鏈遘茲頁其頁面其最近修改",
        "tooltip-t-contributions": "茲蜀用戶其貢獻單單",
        "tooltip-t-emailuser": "共茲蜀隻用戶發電子郵件",
        "tooltip-t-upload": "上傳文件",
        "tooltip-t-specialpages": "特殊頁其單單",
        "tooltip-t-print": "茲蜀頁其會拍印其版本",
+       "tooltip-t-permalink": "茲頁茲版本其永久鏈接",
        "tooltip-ca-nstab-main": "看蜀看內容頁",
        "tooltip-ca-nstab-user": "覷蜀覷用戶頁",
        "tooltip-ca-nstab-special": "茲是蜀萆特殊頁,汝𣍐使修改茲蜀頁。",
index 3ee38c1..97c7482 100644 (file)
@@ -25,6 +25,7 @@
        "tog-watchdefault": "ТӀетоха ас нисйина агӀонаш тергаме могӀам чу",
        "tog-watchmoves": "ТӀетоха ас цӀераш хийцина агӀонаш тергаме могӀам чу",
        "tog-watchdeletion": "ТӀетоха ас дӀаяьхна агӀонаш тергаме могӀанан чу",
+       "tog-watchrollback": "Аса нисдар юхудаькхина агӀо сан тергаме могӀанан тӀетуху",
        "tog-minordefault": "Къастам бе нисйиначарн хlумцадеш кегийра долушсанна",
        "tog-previewontop": "Чуяккха хьалххьажар тадаран кора хьалха",
        "tog-previewonfirst": "Гайта хьалххьажар тадарш да долийча",
@@ -46,7 +47,7 @@
        "tog-ccmeonemails": "Дlадахьийта суна исанна кехат, аса дохьуьйтуш долу кхечу декъашхошна.",
        "tog-diffonly": "Ма гайта агlон чулацам шина башхонца цхьатерра йолуш",
        "tog-showhiddencats": "Гайта къайлаха йолу категореш",
-       "tog-norollbackdiff": "ЮÑ\85а Ñ\8fккÑ\85инаÑ\87Ñ\83л Ñ\82Ó\80аÑ\8cÑ\85Ñ\8cа Ð¼Ð° Ð³Ð°Ð¹Ñ\82а Ð²ÐµÑ\80Ñ\81еÑ\88ан башхо",
+       "tog-norollbackdiff": "ЮÑ\85а Ñ\8fккÑ\85инаÑ\87Ñ\83л Ñ\82Ó\80аÑ\8cÑ\85Ñ\8cа Ð¼Ð° Ð³Ð°Ð¹Ñ\82а Ð²ÐµÑ\80Ñ\81ийн башхо",
        "tog-useeditwarning": "Хаамбе бина хийцамаш дӀаязцабеш аса болх дӀатосучу хенахь",
        "tog-prefershttps": "Даима лела йе лардина системин чудалар",
        "underline-always": "Даимна",
        "hidden-category-category": "Къайлаха йолу категореш",
        "category-subcat-count": "{{PLURAL:$2|ХӀокху категори чохь ю хӀокхуьнан бухара категори.|ХӀокху категори чохь ю $1 {{PLURAL:$1|бухара категори|бухара категореш}} $2 массо нах.}}",
        "category-subcat-count-limited": "ХӀокх категори чохь {{PLURAL:$1|бухар категори|$1 бухар категореш}} ю.",
-       "category-article-count": "{{PLURAL:$2|ХӀокху категори чохь яц цхьа агӀо бе.|{{PLURAL:$1|Гойту $1 агӀо|Гойту $1 агӀонаш}} хӀокху категорешца кху $2.}}",
+       "category-article-count": "{{PLURAL:$2|ХӀокху категори чохь яц цхьа агӀо бе.|ХӀокху категори чохь ю $2 агӀо, царах агӀонгахь {{PLURAL:$1|гойту $1 агӀо}}}}",
        "category-article-count-limited": "ХӀокху категори чохь {{PLURAL:$1|$1 агӀо|$1 агӀонаш}} цхьа агӀо бен яц.",
        "category-file-count": "{{PLURAL:$2|ХӀокху категори чохь цхьа файл бе яц.|{{PLURAL:$1|Гойту $1 файл|Гойту $1 файлаш}} хӀокху категорешца кху $2.}}",
        "category-file-count-limited": "ХӀокху категори чохь {{PLURAL:$1|$1 файл|$1 файлаш|1=цхьаъ бен файл яц}}.",
        "listingcontinuesabbrev": "(кхин дlа)",
-       "index-category": "Меттигтерахьйо агlонаш",
+       "index-category": "Меттигтерахьйо агӀонаш",
        "noindex-category": "ДӀахьушйоцу агӀонаш",
        "broken-file-category": "{{#switch:{{NAMESPACE}}\n |{{ns:0}}=Болх цабеш файлийн хьажоргаш йолу агӀонаш}}",
        "about": "Цуьнах лаьцна",
        "talkpagelinktext": "Дийцаре",
        "specialpage": "Белха агӀо",
        "personaltools": "Долахь болу гӀирсаш",
-       "postcomment": "Керла дакъа",
        "articlepage": "Хьажа яззаме",
        "talk": "Дийцаре",
        "views": "Хьажарш",
        "otherlanguages": "Кхечу маттахь дерш",
        "redirectedfrom": "(ДӀасахьажийна кху $1)",
        "redirectpagesub": "АгӀо-дӀасахьажайар",
+       "redirectto": "ДӀасахьажор тӀе:",
        "lastmodifiedat": "ХӀокху агӀон тӀаьххьаралера хийцам: $2, $1.",
        "viewcount": "ХӀокху агӀонг хьовсийна $1 {{PLURAL:$1|за}}.",
        "protectedpage": "ГӀароллийца йолу агӀо",
        "aboutpage": "Project:Цуьнах лаьцна",
        "copyright": "Чулацам лело мега $1 лицензица (кхениг билгалйина яцахь).",
        "copyrightpage": "{{ns:project}}:Авторан бакъонаш",
-       "currentevents": "ХӀинцлера хилларш",
-       "currentevents-url": "Project:ХӀинцлера хилларш",
-       "disclaimers": "Бехк тӀе ца эцар",
-       "disclaimerpage": "Project:Бяхк тӀецалацар",
+       "currentevents": "Ð¥Ó\80инÑ\86алеÑ\80а Ñ\85иллаÑ\80Ñ\88",
+       "currentevents-url": "Project:Ð¥Ó\80инÑ\86алеÑ\80а Ñ\85иллаÑ\80Ñ\88",
+       "disclaimers": "Бехк тӀецалацар",
+       "disclaimerpage": "Project:Бехк тӀецалацар",
        "edithelp": "ГӀо оцу тадарна",
        "mainpage": "Коьрта агӀо",
        "mainpage-description": "Коьрта агӀо",
        "hidetoc": "къайлаяккха",
        "collapsible-collapse": "къайлаяккха",
        "collapsible-expand": "схьаяста",
+       "confirmable-confirm": "Лаьий {{GENDER:$1|хьуна}}?",
+       "confirmable-yes": "ХӀаъ",
+       "confirmable-no": "ХӀахӀа",
        "thisisdeleted": "Хьажа я меттахӀоттайé $1?",
        "viewdeleted": "Хьожий $1?",
        "restorelink": "{{PLURAL:$1|1=$1 дӀадаьккхина нийсдар|$1 дӀадяхна нийсдарш}}",
        "databaseerror-error": "ГӀалат: $1",
        "laggedslavemode": "Тергам бе: агӀона чохь керла йаьхинарш ца хила мега.",
        "readonly": "Блоктоьхна дӀайаздар хаамийн бухе",
-       "enterlockreason": "Билгал де блоктохаран бахьна а и чекх йолу хан а.",
+       "enterlockreason": "Билгалде блоктохаран бахьна а и чекх йолу хан а.",
        "readonlytext": "АгӀонаш тӀетохар а кхин хийцамаш барна а блоктоьхна:\nБлокоьхначо биттина хаам: $1.",
        "missing-article": "ХӀокху чохь кароезаш йолу хьан дехарца йозан агӀонаш цакарийна «$1» $2.\n\nИштнарг наггахь хуьлу хьажораг дӀаяьккхина елахь я хийцам бина тиша хьажорагца дехьа гӀо гӀоьртича.\n\nНагахьсан гӀулкх цуьнах доьзна дацахь, хьуна карийна гӀирс латточехь гӀалат.\nДехар до, хаам бе оцуьнах [[Special:ListUsers/sysop|куьйгалхога]], гойтуш URL.",
        "missingarticle-rev": "(верси № $1)",
-       "missingarticle-diff": "(тейп тайпнара: $1, $2)",
+       "missingarticle-diff": "(башхалла: $1, $2)",
        "readonly_lag": "Хаамашан базина цхьана хан блоктоьхна, хаамашан базан сервераш нисялца.",
        "internalerror": "Чоьхьара гӀалат",
        "internalerror_info": "Чоьхьара гӀалат: $1",
        "invalidtitle-knownnamespace": "Магийна боцу коьртамогӀа цӀерийн меттигца «$2» йоза  «$3»",
        "invalidtitle-unknownnamespace": "Магийна боцу коьртамогӀа ца йовза меттигца $1 «$2» йозанца",
        "exception-nologin": "ХӀинца а ахьа системин чохь болх беш бац",
-       "exception-nologin-text": "Ð\98за Ð´Ð°Ð½ [[Special:Userlogin|системин чугӀо]].",
+       "exception-nologin-text": "Ð¥Ó\80окÑ\85Ñ\83 Ð°Ð³Ó\80о Ñ\82Ó\80екÑ\85аÑ\87а Ð»Ñ\83Ñ\88 Ñ\85илийÑ\82а [[Special:Userlogin|системин чугӀо]].",
        "exception-nologin-text-manual": "АгӀо тӀекхача луш хилийта оьшу $1.",
        "virus-badscanner": "Нисяран гӀалат. Ца йовза вирусийн сканер: ''$1''",
        "virus-scanfailed": "сканиран гӀалат (код $1)",
        "userlogin-yourpassword-ph": "Язъе хьай пароль",
        "createacct-yourpassword-ph": "Язъе пароль",
        "yourpasswordagain": "Юха язъе пароль:",
-       "createacct-yourpasswordagain": "Бакъ йе пароль",
+       "createacct-yourpasswordagain": "Бакъе пароль",
        "createacct-yourpasswordagain-ph": "Кхин цкъа язъе пароль",
        "remembermypassword": "Даглаца сан дӀаяздар хӀокху компьютеран тӀехь (цхьан $1 {{PLURAL:$1|дийнахь}})",
        "userlogin-remembermypassword": "Дагахь латт ве/е со",
        "externaldberror": "Арахьара хаамийн базан гӀоьнца аутентификаци ечу хенахь гӀалат даьлла я хьа дӀаяздаран хийцам бан бакъонаш яц.",
        "login": "Системин чугӀо",
        "nav-login-createaccount": "Системин чугӀо / дӀаяздар кхолла",
-       "loginprompt": "Ахьа бакъо яла еза оцу «cookies» хьайна системин чохь болхбан лаахь.",
        "userlogin": "Довзийтар я декъашхочун дӀаяздар кхоллар",
        "userloginnocreate": "Довзийта",
        "logout": "Болх дӀаберзор",
        "userlogin-resetlink": "Чуволу/йолу хаам биц бела?",
        "userlogin-resetpassword-link": "Пароль кхоссар?",
        "userlogin-helplink2": "Системин чудахаран гӀодар",
-       "userlogin-loggedin": "Хьо {{GENDER:$1|$1}} цӀарца чохь ву/ю.\nЛахара форманца кхин цӀарца чугӀо.",
-       "userlogin-createanother": "Кхолла декъашхочун кхин дӀаяздар",
        "createacct-emailrequired": "Электронан почтан адрес",
        "createacct-emailoptional": "Электронан почтан адрес (ца яздича мега)",
        "createacct-email-ph": "ДӀаязде электронан почтан адрес",
        "passwordreset-emailelement": "Декъашхочун цӀе: $1\nХанна йолу пароль: $2",
        "passwordreset-emailsent": "Электронан хаам баийтина кхоьссинчу паролах лаьцна хаам чохь болуш.",
        "passwordreset-emailsent-capture": "Электронан хаам баийтина кхоьссинчу паролах лаьцна хаам чохь болуш. \nцуна йозане хьажа йиш ю лахахь.",
+       "passwordreset-emailerror-capture": "Пароль кхоссаран хаам чохь болуш электронан кехат кхоьллина, цуна йоза хьажа йиш ю лахахь, амма иза {{GENDER:$2|декъашхочунга}} дӀадахьийта тар цаделира бахьнехь: $1",
        "changeemail": "Хийца электронан почта",
        "changeemail-header": "Электронан почтан адрес хийцар",
        "changeemail-text": "Юза хӀара форма хьайн электронан почтан адрес хуьйцуш. Ахьа хийцар бакъдан язъян еза пароль.",
        "changeemail-password": "Хьан пароль «{{SITENAME}}» проектан:",
        "changeemail-submit": "Хийца email",
        "changeemail-cancel": "Цаоьшу",
+       "changeemail-throttled": "Хьо дукха гӀиртира.\nДехар до, собар де $1 юха гӀортале.",
        "resettokens": "Токенаш кхоссар",
        "resettokens-text": "Хьан йиш ю токенаш кхосса, цара йиш хуьлуьйту цхьаболу долара хаамашна тӀекхача, уьш ю хьан дӀаяздар ца вовшахтесна. \n\nХьона иза оьшу, ахьа хьай токенаш цхьам гучу яьхна елахь я хьан аккаунт йохийна елахь.",
        "resettokens-no-tokens": "Кхосса токенаш яц.",
        "preview": "Хьалха муха ю хьажа",
        "showpreview": "Хьалха муха ю хьажар",
        "showdiff": "Хlоттина болу хийцам",
+       "blankarticle": "<strong>ДӀахьедар:</strong> Ахьа кхуллуш йолу агӀо еса ю.\nЮху кнопка «{{int:savearticle}}» тӀетаӀаяхь, агӀо цхьа чулацам боцуш кхуллур ю.",
        "anoneditwarning": "'''Тергам бе''': Ахьа хьай цӀарца тадарш деш дац. Хьан IP-адрес дӀаяздина хира ду хӀокху агӀон истори чу.",
        "anonpreviewwarning": "''Системин чу цагӀахь хьан IP-адрес агӀона истори чу дӀаяз лур ду.''",
+       "missingsummary": "'''Дагадаийтар.''' Ахьа хийцамаш лаьцна доца яздина дац. Кнопка «{{int:savearticle}}» юху тӀетаӀича хийцамах лаьцна хӀума доцуш Ӏалашбира бу.",
        "missingcommenttext": "Дехар до дӀаязбе хайн хаам лахахь.",
+       "missingcommentheader": "'''Дагадаийтар.''' Ахьа хӀокху къамелан дӀахьедар/корта билгал бина бац. Кнопка «{{int:savearticle}}» юху тӀетаӀича хийцамах лаьцна хӀума доцуш Ӏалашбира бу.",
        "summary-preview": "Цуьнах лаьцна хирду:",
        "subject-preview": "Коьрта могӀа хира бу:",
        "blockedtitle": "Декъашхочун блоктоьхана",
+       "blockedtext": "'''Хьан декъашхочун дӀаяздар я IP-адрес блоктоьхна ду.'''\n\nБлоктоьхна куьйгалхочо $1.\nБилгалдина бахьна: «''$2''».\n\n* Блоктохар доладелла: $8\n* Блоктохар чекхдолу: $6\n* Блоктохаран Ӏалашо: $7\n\nХьа йиш ю $1 декъашхочуьнга дехардан я кхечу муьлха [[{{MediaWiki:Grouppage-sysop}}|куьйгалхочуьнга]].\nТергам бе, хьа таро яц «декъашхочунга кехат» олу функци лелаян, хьан [[Special:Preferences|гӀирс нисбар чохь]] нийса электронан почтан адрес яздина дацахь, я кехаташ кхехӀитарна а блоктоьхна елахь.\nХьан IP-адрес — $3, блоктохаран идентификатор — $5.\nДехар до, хьайн хаам чохь билгалде и.",
        "blockednoreason": "бахьана билгалдина дац",
        "whitelistedittext": "Ахьа да деза $1 агӀона хийцамаш бан.",
        "nosuchsectiontitle": "Дакъа каро йиш яц.",
        "missing-revision": "АгӀона «{{FULLPAGENAME}}» верси $1 яц.\n\nИшта хуьйла ширелла дӀаяьккхина агӀонан хьажораган дихьа делча.\nМа-дара хила мега [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} дӀайаьхарш йолу тептар] чохь.",
        "userpage-userdoesnotexist": "Ишта декъашхочун дӀаяздар «<nowiki>$1</nowiki>» хӀинца дац. Хьажа билгал, хьуна бакъалла лаьий кхолла я хийцам ба хӀокху агӀон.",
        "userpage-userdoesnotexist-view": "«$1» ишта декъашхочун дӀаяздар дац.",
-       "blocked-notice-logextract": "ХӀара декъашхочун дӀаяздар блоктоьхна ду.\nЛахахь гойту блоктохаршан тептар чура тӀаьхьарлера дӀаяздар:",
+       "blocked-notice-logextract": "ХӀара декъашхочун дӀаяздар блоктоьхна ду.\nЛахахь гойту блоктохарийн тептар чура тӀаьхьарлера дӀаяздар:",
        "clearyourcache": "'''Билгалдаккхар.''' Ӏалашйинчул тӀехьа хийцамаш га браузеран кэш цӀанъян езаш хила мега.\n* '''Firefox / Safari:''' ''Shift'' цӀе йолу пиллиг лаьцна битна, гӀирсийн панелан тӀера тӀетаӀе ''Карлаяккха'' я ''Ctrl-F5'' я ''Ctrl-R'' (''⌘-R'' Mac тӀехь)\n* '''Google Chrome:''' ТӀетаӀе ''Ctrl-Shift-R'' (''⌘-Shift-R'' Mac тӀехь)\n* '''Internet Explorer:''' ''Ctrl'' лаьцна йитан, тӀетаӀе ''Карлаяккха'' я тӀетаӀе ''Ctrl-F5''\n* '''Opera:''' Кэш цӀанъяр харжа меню ''Инструменты → Настройки'' чохь",
        "usercssyoucanpreview": "'''ДӀаалар.''' ТӀетаӀае кнопка «{{int:showpreview}}», хьажа хьай керла CSS-файл Ӏалаш яле.",
        "userjsyoucanpreview": "'''ДӀаалар.''' ТӀетаӀае кнопка «{{int:showpreview}}», хьажа хьай керла JS-файл Ӏалаш яле.",
        "protectedpagewarning": "'''Дlахьедар. Хlара агlо гlаролла дина ю хийцам цабайта, иза хийца йа нисйа а бакъо йолуш адаманкуьйгалла лелош болу декъашхой бе бац.'''\nЛахахьа гойту хаамаш тlаьхьара бина болу хийцамна тептар чура:",
        "semiprotectedpagewarning": "'''ДӀахьедо.''' ХӀара агӀо гӀаролла йина ю; дӀабазбиначу декъашхошка бе цӀе хийцалуш яц.\nЛахахьа тептаро балийна тӀаьхьаралера дӀаязбина хаам:",
        "cascadeprotectedwarning": "<div id=\"cascadeprotectedwarning\" style=\"border:1px solid #ee0; padding:10px; background:#ffa; margin-bottom:1em\">[[file:Padlock.svg|left|25px|ДовгӀа|link=]]\nХӀара агӀо тада бакъо йолуш [[Project:Куьйгалхой|куьйгалхой]] бу, хӀунда аьлча и агӀо латийна кхечу агӀонашца хӀоттделлачу гӀаролле:</div>",
-       "templatesused": "{{PLURAL:$1|1=Ð\9aеп, Ð»ÐµÐ»Ð¸Ð¹Ð½Ð°|Ð\9aепаÑ\88, Ð»ÐµÐ»Ð¾Ñ\88 Ñ\8e}} Ñ\85Ó\80окÑ\85Ñ\83 Ð°Ð³он башхонца:",
+       "templatesused": "{{PLURAL:$1|1=Ð\9aеп, Ð»ÐµÐ»Ð¾Ñ\88 Ñ\8e\9aепаÑ\88, Ð»ÐµÐ»Ð¾Ñ\88 Ñ\8e}} Ñ\85Ó\80окÑ\85Ñ\83 Ð°Ð³Ó\80он башхонца:",
        "templatesusedpreview": "{{PLURAL:$1|1=Кеп, лелошдолу|Кепаш, лелойлу}} оцу хьалх хьожучу агӀонца:",
        "templatesusedsection": "ХӀокху декъан чохь {{PLURAL:$1|1=лелош йолу кеп|лелош йолу кепаш}}:",
        "template-protected": "(гlароллийца)",
        "last": "хьалх.",
        "page_first": "хьалхара",
        "page_last": "тlаьххьара",
-       "histlegend": "Кхетор: (хlинцлера.) — йолучу башхон къастам; (хьалх.) — хьалхлерачу башхон къастам; '''ж''' — жимо бозалца болу хийцам.",
+       "histlegend": "Кхетор: (хӀинцалера.) — йолучу башхон къастам; (хьалх.) — хьалхлерачу башхон къастам; '''ж''' — жимо бозалца болу хийцам.",
        "history-fieldset-title": "АгӀона хийцамаш",
        "history-show-deleted": "ДӀаяхинарш",
        "histfirst": "ширниш",
        "rev-deleted-event": "(дӀаяздар дӀаяьккхина)",
        "rev-deleted-user-contribs": "[декъашхочун цӀе я IP-адрес дӀаяхина — къинхьегаман агӀонгара нисдар къайлаяьккхина]",
        "rev-deleted-text-permission": "ХӀара агӀона верси '''дӀаяьккхина''' ю.\nБахьна далина [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} дӀаяьхнарш йолу тептар чохь].",
+       "rev-suppressed-text-permission": "ХӀара агӀона верси <strong>къайлаяьккхина ю</strong>.\nБахьна далина [{{fullurl:{{#Special:Log}}/suppress|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}}}} дӀаяьхнарш йолу тептар чохь].",
        "revdelete-nooldid-text": "Ахьа хӀара функци кхочушъян билгалйина яц Ӏалашонан верси (я версеш).",
        "revdelete-no-file": "Иштта файл яц.",
        "revdelete-show-file-confirm": "Бакъалла лаьий хьуна дӀаяьккхина файлан версега хьажа «<nowiki>$1</nowiki>» $2 тӀера, $3?",
-       "revdelete-show-file-submit": "Хlаъ",
+       "revdelete-show-file-submit": "ХӀаъ",
        "revdelete-selected-text": "{{PLURAL:$1|Файлан хаьржина верси|Файлан хаьржина версеш}} [[:$2]]:",
        "revdelete-selected-file": "{{PLURAL:$1|Файлан хаьржина верси|Файлан хаьржина версеш}} [[:$2]]:",
        "logdelete-selected": "Тептар чура {{PLURAL:$1|хаьржина дӀаяздар|хаьржина дӀаяздарш}}:",
        "revdelete-radio-set": "Къайлаяьккхина",
        "revdelete-radio-unset": "Гуш ерг",
        "revdelete-suppress": "Къайлабаха хаамаш куьйгалхойх а",
-       "revdelete-unsuppress": "Ð\9cеÑ\82Ñ\82аÑ\85Ó\80оÑ\8cÑ\82Ñ\82ина Ð²ÐµÑ\80Ñ\81еÑ\88ан дихкар къайладаккха",
+       "revdelete-unsuppress": "Ð\9cеÑ\82Ñ\82аÑ\85Ó\80оÑ\8cÑ\82Ñ\82ина Ð²ÐµÑ\80Ñ\81ийн дихкар къайладаккха",
        "revdelete-log": "Бахьна:",
        "revdelete-submit": "Кхочушде {{PLURAL:$1|1=къастина версин|къастина версийн}}",
        "revdelete-success": "'''Версеш гуш хилар кхиамца хийцина.'''",
        "revertmerge": "Йекъа",
        "mergelogpagetext": "Лахахь гойту тӀеххьара вовшахтоьхна агӀонийн могӀам.",
        "history-title": "$1 — хийцаман истори",
-       "difference-title": "$1 â\80\94 Ð\92еÑ\80Ñ\81еÑ\88ан башхалла",
+       "difference-title": "$1 â\80\94 Ð\92еÑ\80Ñ\81ийн башхалла",
        "difference-title-multipage": "АгӀонийн башхалла «$1» а «$2» а",
        "difference-multipage": "(АгӀонийн башхалла)",
        "lineno": "МогӀа $1:",
        "searchresults-title": "Лаха «$1»",
        "titlematches": "АгӀонийн цӀераш цхьаьнанисялар",
        "textmatches": "АгӀонийн йоза цхьаьнанисдалар",
-       "notextmatches": "Агlонаш чура йозанашца цхьатера йогlуш яц",
+       "notextmatches": "АгӀонаш чура йозанашца цхьатера йогlуш яц",
        "prevn": "хьалхарнаш {{PLURAL:$1|$1}}",
        "nextn": "тӀаьхьйогӀурш {{PLURAL:$1|$1}}",
        "prevn-title": "{{PLURAL:$1|1=Хьалхара $1 дӀаяздар|Хьалхара $1 дӀаяздарш}}",
        "shown-title": "АгӀона чохь $1 {{PLURAL:$1|1=дӀаяздар|дӀаяздарш}} гайта",
        "viewprevnext": "Хьажа ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "'''ХӀокху вики чохь йолуш ю ишта агӀо «[[:$1]]»'''",
-       "searchmenu-new": "'''Кхолла ишта агӀо «[[:$1]]» хӀокху {{PLURAL:$2|0=|вики-проектехь.}}'''",
-       "searchprofile-articles": "Къаьстина агlонаш",
+       "searchmenu-new": "<strong>Кхолла «[[:$1]]» агӀо хӀокху вики-проектехь!</strong>\n{{PLURAL:$2|0=|Хьан лахарца карина.}}",
+       "searchprofile-articles": "Къаьстина агӀонаш",
        "searchprofile-images": "Мультимедиа",
        "searchprofile-everything": "Массанхьа",
        "searchprofile-advanced": "Шуьйра",
        "searchprofile-advanced-tooltip": "Лаха дехарца хlокху ана цlерашкахь",
        "search-result-size": "$1 ({{PLURAL:$2|$2 дош|$2 дешнаш}})",
        "search-result-category-size": "$1 {{PLURAL:$1|юкъаяр}} ($2 {{PLURAL:$2|1=бухара категори|бухара категореш}}, $3 {{PLURAL:$3|1=файл|файлаш}}).",
-       "search-result-score": "Релевант: $1%.",
        "search-redirect": "(дlасахьажийна $1)",
        "search-section": "(дакъа $1)",
        "search-file-match": "(файлан чулацаме тера хилар)",
        "searchall": "массо",
        "showingresults": "Лахахьа {{PLURAL:$1|гойта|гойту|гойту}} <strong>$1</strong> {{PLURAL:$1|хилам|хиламаш|хиламаш}}, дlаболало кху № <strong>$2</strong>.",
        "showingresultsinrange": "Лахахь гайтина {{PLURAL:$1|<strong>1</strong> хилам}} диапазонехь <strong>$2</strong> тӀера <strong>$3</strong> кхаччалц.",
-       "showingresultsheader": "{{PLURAL:$5|1=Хилам '''$1''' кху '''$3'''|Хиламаш '''$1 — $2''' кху '''$3'''}} оцун '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Хилам <strong>$1</strong> <strong>$3</strong> нах}}",
        "search-nonefound": "Дехаре терра цхьа хӀума ца карийна.",
        "powersearch-legend": "Шуьро лахар",
        "powersearch-ns": "ЦӀерийн меттигашкахь лахар:",
        "prefs-watchlist": "Тергаме могӀам",
        "prefs-watchlist-days": "Денойн дукхалла:",
        "prefs-watchlist-days-max": "Къезиг $1 {{PLURAL:$1|дена}}",
-       "prefs-watchlist-edits": "Тергаме могӀам чохь гойтучу нисдаршан максимальни дукхалла:",
+       "prefs-watchlist-edits": "Тергаме могӀам чохь гойтучу нисдарийн максимальни дукхалла:",
        "prefs-watchlist-edits-max": "Уггар дукха: 1000",
        "prefs-watchlist-token": "Тергаме могӀанан токен:",
        "prefs-misc": "Кхин гlирсаш",
        "stub-threshold-disabled": "ДӀадайина",
        "recentchangesdays": "Керла нисдар гайта динахь:",
        "recentchangesdays-max": "Къезиг $1 {{PLURAL:$1|дена}}",
-       "recentchangescount": "Iад йитарца гойтуш долу нисдаршан дукхалла",
+       "recentchangescount": "Iад йитарца гойтуш долу нисдарийн дукхалла",
        "prefs-help-recentchangescount": "Гойту керла нисдарш, агӀонашан истори, тептарш.",
        "prefs-help-watchlist-token2": "Иза хьан тергаме могӀан къайла догӀа ду.\nМуьлха и хуучунна йиш ю хьан тергаме могӀам беша, цундела ма хаийта иза кхечаьрга. [[Special:ResetTokens|ТӀетаӀа йе кхуза и хьайга кхосса лууш делахь]].",
        "savedprefs": "Хьан гӀирс Ӏалашбина.",
        "timezoneuseoffset": "Кхин (билгалде дӀахилар)",
        "servertime": "Сервера хан:",
        "guesstimezone": "Юза браузеран чура",
+       "timezoneregion-africa": "Африка",
+       "timezoneregion-america": "Америка",
+       "timezoneregion-antarctica": "Антарктика",
+       "timezoneregion-arctic": "Арктика",
        "timezoneregion-asia": "Ази",
        "timezoneregion-atlantic": "Атлантикан океан",
        "timezoneregion-australia": "Австрали",
+       "timezoneregion-europe": "Европа",
        "timezoneregion-indian": "Индин океан",
        "timezoneregion-pacific": "Тийна океан",
        "allowemail": "Магийта декъашхошна хьайга электрони почтехула кехат кхехьийта",
        "prefs-files": "Файлаш",
        "prefs-custom-css": "Долахь йолу CSS",
        "prefs-custom-js": "Долахь йолу JS",
-       "prefs-common-css-js": "ЮкÑ\8aаÑ\80а CSS/JS Ð¼Ð°Ñ\81Ñ\81о ÐºÐµÑ\87 Ð´Ð°Ñ\80ан Ñ\82емаÑ\88ан:",
+       "prefs-common-css-js": "ЮкÑ\8aаÑ\80а CSS/JS Ð¼Ð°Ñ\81Ñ\81о ÐºÐµÑ\87 Ð´Ð°Ñ\80ан Ñ\82емийн:",
        "prefs-reset-intro": "ХӀара агӀо лело мега ахьа нисбина гӀирс Ӏад битарца юха бокхуш.\nХӀара дешдерг кхочушъ динчул  тӀехьа хьан йиш хир-яц и юха меттахӀотто.",
        "prefs-emailconfirm-label": "Электронан почта бакъ яр:",
        "youremail": "Электронан почта:",
        "prefs-advancedwatchlist": "Кхин гӀирс нисбар",
        "prefs-displayrc": "Гуш болу гӀирсаш",
        "prefs-displaywatchlist": "Гуш болу гӀирсаш",
+       "prefs-tokenwatchlist": "Токен",
        "prefs-diffs": "Башхон верси",
        "prefs-help-prefershttps": "И хийцам болх байта юхугӀо системин чу.",
        "email-address-validity-valid": "Го нийса",
        "userrights-nologin": "Куьйгалхочунна бакъо йолу [[Special:UserLogin|дӀаяздарца]] ло декъашхочун бакъо.",
        "userrights-notallowed": "Хьан дӀаяздарца магийна дац декъашхошна бакъо яла а дӀаяккха а.",
        "userrights-changeable-col": "Хьона хийца луш йолу бакъонаш",
-       "userrights-unchangeable-col": "Хьона хийца луш йоцу бакъонаш",
+       "userrights-unchangeable-col": "Хьуна хийца луш йоцу бакъонаш",
        "group": "Тоба:",
        "group-user": "Декъашхой",
        "group-autoconfirmed": "Ша тӀелаьцболу декъашхой",
        "right-editmyprivateinfo": "Хьан долара хаамаш нисбар (масала, электронан адрес, бакъ цӀе)",
        "right-editmyoptions": "Тае хьайн гӀоли хетарг",
        "right-rollback": "билгала агӀона тӀехьарчу декъашхочо дина нисдарш сиха юхадахар",
-       "right-markbotedits": "юхудохучу нисдаршан шаболх бечунна нисдарш аьлла билгало ян",
+       "right-markbotedits": "юхудохучу нисдарийн ботан нисдарш санна билгало ян",
        "right-noratelimit": "чехкалин доза дац",
        "right-import": "кхечу википедешкара агӀонаш импорт ян",
        "right-importupload": "файлаш чуяхарца агӀонаш импорт ян",
        "recentchanges-label-bot": "ХӀара нисдар шаболх бечо дина",
        "recentchanges-label-unpatrolled": "ХӀара нисдар хӀинца цхьано патрулировать дина дац",
        "recentchanges-label-plusminus": "байташкахь барам хийцар",
+       "recentchanges-legend-heading": "'''Легенда:&nbsp;'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (хьажа кхин [[Special:NewPages|керла агӀонийн могӀа]])",
        "rcnotefrom": "Лахахь гайтина тӀера <strong>$2</strong> (хийцамаш <strong>$1</strong> кӀезиг).",
-       "rclistfrom": "Гайта хийцам оцу $3 $2",
+       "rclistfrom": "Гайта хийцам $3 $2 хан",
        "rcshowhideminor": "$1 кегийра нисдарш",
        "rcshowhideminor-show": "Гайта",
        "rcshowhideminor-hide": "Къайладаха",
        "rcshowhidemine": "$1 айхьа нисдинарш",
        "rcshowhidemine-show": "Гайта",
        "rcshowhidemine-hide": "Къайладаха",
-       "rclinks": "Гайта тlаьхьара $1 хийцамаш оцу $2 ден<br />$3",
-       "diff": "тейп тайпнара",
+       "rclinks": "Гайта тӀаьхьара $1 хийцамаш $2 ден<br />$3",
+       "diff": "башхалла",
        "hist": "истори",
        "hide": "Къайлаяккха",
        "show": "Гайта",
        "file-deleted-duplicate": "Иштта файл ([[:$1]]) хӀинцале дӀаяьккхина хилла. Дехар до, юху файл чуяккхале файл дӀаяккхаран историга хьажа.",
        "uploadwarning": "Дlахьедар",
        "uploadwarning-text": "Дехар до, лахара файлах лаьцнарг хийца а дай юху а гӀорта файл чуяккха.",
-       "savefile": "ДӀаязе йе файл",
-       "uploadedimage": "чуяьккхина «[[$1]]»",
-       "overwroteimage": "Чуяьккхина файлан керла верси «[[$1]]»",
+       "savefile": "ДӀаязъе файл",
        "uploaddisabled": "Чуяккхар магийна дац",
        "copyuploaddisabled": "URL тӀера чуяккхар дӀадайина ду.",
        "uploaddisabledtext": "Файлаш чуяхар дӀадайина ду.",
        "license": "Бакъойалар:",
        "license-header": "Бакъойалар",
        "nolicense": "Яц",
+       "licenses-edit": "Лицензин параметраш хийца",
        "license-nopreview": "(Хьалха муха ю хьажа цало)",
-       "upload_source_file": " (файл хьан компьютер чохь ю)",
+       "upload_source_url": "(ахьа хаьржина нийса, массо тӀекхочу интернет-адрес)",
+       "upload_source_file": "(файл хьан компьютер чохь ю)",
+       "listfiles-delete": "дӀаяккха",
        "listfiles-summary": "Лахахь гойтуш ю ерриг файлаш.\nДекъашхо къастичи, цун керла файлаш гойту.",
        "listfiles_search_for": "Лаха хIуман цIарца:",
        "imgfile": "файл",
        "mimesearch-summary": "ХӀокху агӀоно йиш хуьлуьйту MIME-тайпан файлаш харжа. Яздеш долу формат: чулацаман тайп/бухара тайп, масала  <code>image/jpeg</code>.",
        "mimetype": "MIME-тайп:",
        "download": "чуяккха",
-       "unwatchedpages": "Цхьамо тергам ца беш йолу агIонаш",
+       "unwatchedpages": "Цхьамо тергам ца беш йолу агӀонаш",
        "listredirects": "ДIасахьажоран могIам",
        "listduplicatedfiles": "Файлийн могӀам дубликатшца",
        "listduplicatedfiles-entry": "Файлан [[:File:$1|$1]] — [[$3|{{PLURAL:$2|дубликат ю}}]].",
        "unusedtemplateswlh": "кхин хьажоргаш",
        "randompage": "Цахууш нисъелла агӀо",
        "randomincategory": "Категори чу цахууш нисъелла  агӀо",
-       "randomincategory-selectcategory": "Категори чу цахууш нийса елла агӀона чу гӀо: $1 $2.",
-       "randomincategory-selectcategory-submit": "Дехьа гӀо",
+       "randomincategory-nopages": "[[:Category:$1]] категори чохь агӀонаш яц.",
+       "randomincategory-category": "Категори:",
+       "randomincategory-legend": "Категори чу цахууш нисъелла  агӀо",
        "randomredirect": "Цахууш нисделла дIасахьажор",
+       "randomredirect-nopages": "«$1» цӀерийн меттиган чохь дӀасахьажораш яц.",
        "statistics": "Статистика",
        "statistics-header-pages": "АгӀонийн жамӀ",
-       "statistics-header-edits": "Ð\9dиÑ\81даÑ\80ан Ð¶Ð°Ð¼Ó\80",
+       "statistics-header-edits": "Ð\9dиÑ\81даÑ\80ийн Ñ\81Ñ\82аÑ\82иÑ\81Ñ\82ика",
        "statistics-header-views": "Хьажаран статистика",
-       "statistics-header-users": "Декъашхойн жамӀа",
+       "statistics-header-users": "Декъашхойн статистика",
        "statistics-header-hooks": "Кхин статистика",
        "statistics-articles": "Яззамаш",
        "statistics-pages": "АгӀонаш",
-       "statistics-pages-desc": "Массо вики агlонаш, дийцаре агlонашцани, дlасахьаждарш а кхин дерш.",
+       "statistics-pages-desc": "Массо вики агӀонаш, дийцаре агӀонашцани, дӀасахьаждарш а кхин дерш.",
        "statistics-files": "Чуяьхна файлаш",
        "statistics-edits": "Нисдаран дукхалла {{grammar:genitive|{{SITENAME}}}} дlа йолайаларца",
-       "statistics-edits-average": "ЮккÑ\8aеÑ\80а Ð°Ð³Ó\80онан Ð½Ð¸Ñ\81даÑ\80ан Ñ\82еÑ\80аÑ\85Ñ\8c",
+       "statistics-edits-average": "Ð\90гÓ\80онан Ð½Ð¸Ñ\81даÑ\80ийн Ñ\8eкÑ\8aаÑ\80а Ð´Ñ\83кÑ\85алла",
        "statistics-views-total": "Массо хьажарш",
        "statistics-views-total-desc": "Ма лара дӀаяьхна а белхан а агӀонашка хьажар",
        "statistics-views-peredit": "Нисдаре хьажарш",
-       "statistics-users": "[[Ð\92Ð\9f\94Ó\80аÑ\8fзвалар|ДӀаязбелларш]] берриге декъашхой чохь болу [[Special:ListUsers|(могӀам)]]",
+       "statistics-users": "[[Ð\92Ð\9f\94Ó\80аÑ\8fзбаллар|ДӀаязбелларш]] берриге декъашхой чохь болу [[Special:ListUsers|(могӀам)]]",
        "statistics-users-active": "Жигара декъашхой",
        "statistics-users-active-desc": "Декъашхой, муьлха цхьа хӀум дина болу, кху {{PLURAL:$1|1=тӀаьххьара $1 динахь|тӀаьххьара $1 дийнахь}}",
        "statistics-mostpopular": "Дукху хьоьжу агӀонаш",
        "pageswithprop-text": "Кхузахь гойтуш ю агӀонаш цхьадолу къастамаш куьйга юху билгал даьхнарш.",
        "pageswithprop-prop": "Къастаман цӀе:",
        "pageswithprop-submit": "Лаха",
+       "pageswithprop-prophidden-long": "деха йозан хӀуман маьӀна хьулйина ($1)",
+       "pageswithprop-prophidden-binary": "шалха маьӀна долу хӀума хьулйина ($1)",
        "doubleredirects": "Шалха дIасахьажийнарш",
        "doubleredirectstext": "ХӀокху агӀонехь ю дӀасахьажорашан тӀе хьажийна йолу дӀасахьажораш.\n<del>ТӀехула сиз хаькхна </del>нисйина чарна.",
        "double-redirect-fixed-move": "АгӀон [[$1]] цӀе хийцина, хӀинца иза дӀахьажийна оцу [[$2]]",
        "withoutinterwiki": "Юкъарвики-хьажоргаш йоцу агӀонаш",
        "withoutinterwiki-summary": "Лахара агӀонийн юкъарвики-хьажоргаш яц:",
        "withoutinterwiki-submit": "Гайта",
-       "fewestrevisions": "ЧIогIа кIезиг башхонаш йолу агIонаш",
+       "fewestrevisions": "ЧӀогӀа кӀезиг версеш йолу агӀонаш",
        "nbytes": "$1 {{PLURAL:$1|байт}}",
        "ncategories": "$1 {{PLURAL:$1|категори|категореш}}",
        "ninterwikis": "$1 {{PLURAL:$1|1=юкъарвики-хьажораг|юкъарвики-хьажоргаш}}",
-       "nlinks": "$1 {{PLURAL:$1|1=хьажораг|хьажоргаш}}",
+       "nlinks": "$1 {{PLURAL:$1|хьажорг}}",
        "nmembers": "$1 {{PLURAL:$1|хӀума|хӀумнаш}}",
        "nmemberschanged": "$1 → $2 {{PLURAL:$2|хӀума|хӀумнаш}}",
        "nrevisions": "$1 {{PLURAL:$1|верси|версеш}}",
        "nimagelinks": "Лелош ю $1 {{PLURAL:$1|агӀонгахь|агӀонашкахь}}",
        "ntransclusions": "лелош ю $1 {{PLURAL:$1|агӀонгахь|агӀонашкахь}}",
        "specialpage-empty": "Дехаро хӀумма ца елла.",
-       "lonelypages": "Байлахь йисина агIонаш",
+       "lonelypages": "Байлахь йисина агӀонаш",
        "lonelypagestext": "Кхузахь ю {{grammar:genitive|{{SITENAME}}}} кхечу агӀонашкахь тӀе хьажийна хьажоргаш йоцу агӀонаш.",
-       "uncategorizedpages": "Категореш йоцу агIонаш",
+       "uncategorizedpages": "Категореш йоцу агӀонаш",
        "uncategorizedcategories": "Категореш йоцу категореш",
        "uncategorizedimages": "Категореш йоцу файлаш",
        "uncategorizedtemplates": "Категореш йоцу кепаш",
        "unusedimages": "Лелош йоцу файлаш",
        "popularpages": "ГӀараяьлла агӀонаш",
        "wantedcategories": "Оьшуш йолу категореш",
-       "wantedpages": "Оьшуш йолу агIонаш",
+       "wantedpages": "Оьшуш йолу агӀонаш",
        "wantedfiles": "Оьшуш йолу файлаш",
        "wantedfiletext-cat": "Лахара йоцу файлаш лело гӀерта. Оцу могӀам юкъа ца хууш файлаш кхета там бу, кхечу проекташ чохь йолу. Ишта ца хууш юкъа нийса елачарна тӀехула <del>сиз</del> хира ду.\nКхин йоцу файлаш гойту [[:$1]] чохь",
        "wantedfiletext-nocat": "Лахара йоцу файлаш лело гӀерта. Оцу могӀам юкъа ца хууш файлаш кхета там бу, кхечу проекташ чохь йолу. Ишта ца хууш юкъа нийса елачарна тӀехула <del>сиз</del> хира ду.",
        "mostcategories": "Дуккха категореш тӀе тоьхна йолу агӀонаш",
        "mostimages": "Массарел дуккха лелайо файлаш",
        "mostinterwikis": "Дуккха юкъарвики хьажоргаш тӀе тоьхна йолу агӀонаш",
-       "mostrevisions": "Сих сиха нисйина йолу агIонаш",
-       "prefixindex": "Ð¥Ñ\8cалÑ\85а Ð°Ð³Ó\80онаÑ\88ан Ñ\86Ó\80еÑ\80аÑ\88 Ñ\85Ó\80оÑ\82Ñ\82о Ð¹еза",
+       "mostrevisions": "Сих сиха нисйина йолу агӀонаш",
+       "prefixindex": "Ð¥Ñ\8cалÑ\85а Ð°Ð³Ó\80онийн Ñ\86Ó\80еÑ\80аÑ\88 Ñ\85Ó\80оÑ\82Ñ\82о еза",
        "prefixindex-namespace": "Хьалха агӀонашан цӀераш хӀотто еза («{{ns:$1}}»)",
        "prefixindex-strip": "Хиламийн могӀам чура префикс къайлаяккха",
        "shortpages": "Боца яззамаш",
        "longpages": "Беха яззамаш",
-       "deadendpages": "Дика йоцу агIонаш",
-       "protectedpages": "ГIаролла дина агIонаш",
+       "deadendpages": "Дика йоцу агӀонаш",
+       "protectedpages": "ГIаролла дина агӀонаш",
        "protectedpages-indef": "Хан йоцуш гӀоралла динарш бен",
        "protectedpages-cascade": "Чахчарин гӀоралла бен",
        "protectedpages-noredirect": "Къайлаяха дӀасахьажийнарш",
        "usercreated": "{{GENDER:$3|дӀавазвелла|дӀаязелла}} $1 $2",
        "newpages": "Керла агӀонаш",
        "newpages-username": "Декъашхо:",
-       "ancientpages": "ЯззамаÑ\88 Ð¾Ñ\86Ñ\83 Ñ\82еÑ\80аÑ\85Ñ\8cÑ\86а Ñ\82Ó\80аÑ\8cÑ\85Ñ\85Ñ\8cаÑ\80а Ñ\82адаÑ\80 Ð´Ð¸Ð½Ð° Ð´Ð¾Ð»Ñ\83",
+       "ancientpages": "ТÓ\80еÑ\85Ñ\8cаÑ\80а Ñ\82еÑ\80аÑ\85Ñ\8cÑ\86а Ñ\82адаÑ\80 Ð´Ð¸Ð½Ð° Ñ\8fззамаÑ\88",
        "move": "ЦӀе хийца",
        "movethispage": "ХӀокху агӀон цӀе хийца",
        "unusedimagestext": "Дехар до, тидаме эца, кхин йолу дуьнана машан-меттигаш а лелош хила мега нийсса йогӀу хьажораг (URL) хӀокху хӀуман, хӀокху могӀаме йогӀуш ялахь яцахь а иза хила мега жигара лелош.",
        "allpagesfrom": "Гучé яха агӀонаш, йолалуш йолу оцу:",
        "allpagesto": "Арайахар сацадé оцу:",
        "allarticles": "Массо агӀонаш",
-       "allinnamespace": "Массо агlонаш оцу цlери анахь «$1»",
+       "allinnamespace": "Массо агӀонаш оцу цӀерийн анахь «$1»",
        "allpagessubmit": "Кхочушдé",
        "allpagesprefix": "Лаха агӀонаш, дӀайолалуш йолу:",
        "allpagesbadtitle": "Цамагош йолу агӀон цӀе. Коьрта могӀан юкъах ю юкъарвики меттанашан юкъе тӀечӀагӀйина йолу хьаьрк йа магийна доцу оцу коьрта моӀанца символаш йа кхин.",
        "allpages-bad-ns": "{{SITENAME}} кху чохь ана цӀераш яц «$1».",
        "allpages-hide-redirects": "Къайлаяха дӀасахьажийнарш",
+       "cachedspecial-viewing-cached-ttl": "Хьо хьоьжу агӀона верси кэш чура ю, иза карлаяьккхина хила мега $1 хьалха.",
        "cachedspecial-refresh-now": "Хьажа тӀехьарчу версега.",
        "categories": "Категореш",
        "categoriespagetext": "{{PLURAL:$1|1=Лахара категореш чохь ю|Лахара категореш чохь ю}} агӀонаш я медиа-файлаш.\nКхузахь гойтуш яц [[Special:UnusedCategories|лелош йоцу категореш]].\nКхин дӀа [[Special:WantedCategories| хийла еза категореш]].",
        "emailsend": "ДӀадахьийта",
        "emailccme": "Соьга а кхосса хааман копи.",
        "emailccsubject": "$1: $2 бохьуьтучу хааман копи",
-       "emailsent": "Ð\9aеÑ\85аÑ\82 Ð´Ó\8fадахьийтина",
+       "emailsent": "Ð\9aеÑ\85аÑ\82 Ð´Ó\80адахьийтина",
        "emailsenttext": "Хьан электроннан хаам дӏабахьийтина.",
        "emailuserfooter": "ХӀара хаам бахийтинера $1 {{GENDER:$1|декъащхочо}} $2 {{GENDER:$2|декъащхочунга}} «декъашхочунга хаам» олучу функцин гӀоьнца {{SITENAME}} проектан.",
        "usermessage-summary": "Битта системан хаам.",
        "watchlist-details": "Хьан тергаме могӀанца $1 {{PLURAL:$1|агӀо}} ю, дийцаре агӀонаш йоцуш.",
        "wlheader-enotif": "Электронан почте хаамаш байтар латина ду.",
        "wlheader-showupdated": "Хийцам бина агӀонаш '''Ӏаьржа''' шрифтцан билгальяха ю.",
-       "wlnote2": "Лахахьа гайтина {{PLURAL:$1|тӀеххьара сахьт}} чохь бина хийцамаш $2 $3.",
+       "wlnote": "Лахахьа {{PLURAL:$1|тlаьхьа богlу $1 хийцам|тlаьхьа богlу $1 хийцамаш|тlаьхьа богlу $1 хийцамаш}} хlокху {{PLURAL:$2|тlаьхьар|тlаьхьара|тlаьхьара}} <strong>$2</strong> {{PLURAL:$2|сохьт|сохьатехь|сохьташкахь}}.",
        "wlshowlast": "Гайта тӀаьххьара $1 сахьт $2 де $3",
        "watchlist-options": "Тергаме могlаман гlирс нисбар",
        "watching": "Тергаме мlогаман юкъаяккха…",
        "unwatching": "Тергаме могӀанан чура дӀаяккхар…",
-       "enotif_reset": "Билгал йаь ерриге агӀонаш хьаьжна санна",
+       "enotif_reset": "Билгалъе ерриге агӀонаш хьаьжна санна",
        "enotif_impersonal_salutation": "Декъашхо {{grammar:genitive|{{SITENAME}}}}",
        "enotif_subject_deleted": "Проектан «{{SITENAME}}» агӀо «$1» {{gender:$2|декъашхочо}} $2 дӀаяьккхина",
        "enotif_subject_created": "Проектан «{{SITENAME}}» агӀо «$1» {{gender:$2|декъашхочо}} $2 кхоьллина",
        "exbeforeblank": "чуьраниг дlацlанйале хьалха: «$1»",
        "delete-confirm": "$1 — дӀаяккхар",
        "delete-legend": "ДӀаяккхар",
-       "historywarning": "'''Тергам:''' хӀокху агӀона герггарчу хьесапехь $1 {{PLURAL:$1|версеш|верси|верси}} ю:",
+       "historywarning": "<strong>Тергам бе:</strong> Хьо дӀаяккха гӀертачу агӀона, нисдарийн истори ю, $1 {{PLURAL:$1|верси}} йолуш:",
        "confirmdeletetext": "Хьо гӀерта агӀо я файл дӀаяккха '''дехар до''', дӀаяккхале хьалха хьажа [[{{MediaWiki:Policy-url}}|кхуза]].",
        "actioncomplete": "Дешдерг кхочушдина",
        "actionfailed": "Кхочушъ дина дац",
        "protect_expiry_old": "Хан чаккхе — хьалхалера.",
        "protect-unchain-permissions": "Схьабелла кхин гӀорралин гӀирс",
        "protect-text": "Кхузéхь хьо хьажало хийцалуш гӀароллин локхалла оцу агӀонашна '''$1'''.",
-       "protect-locked-access": "Хьан дlаязваларéхь тоъал бакъо яц гlароллийн локхаллéхь агlон хийцам бá. Дlадоьлху хlоттийнарш оцу агlонна '''$1''':",
+       "protect-locked-access": "Хьан дӀаяздаран тоъал бакъо яц гӀароллийн локхаллéхь агӀон хийцам бá. ДӀадоьлху хӀоттийнарш агӀонна '''$1''':",
        "protect-cascadeon": "Хlара агlо гlароллийца ю, хlунд аьлча иза латийна {{PLURAL:$1|1=лахахьа гойтучу агlонца, цуьнца хlоттийна|лахахьа гойтучу агlоншца, цаьрца хlоттийна}} чахчарийца гlаролла. Хьога хийцалур ю гlаролли локхалла хlокху агlон, амма оцо хийцам бийра бац чахчарехь йолучу гlароллийна.",
        "protect-default": "Гlаролла йоцуш",
        "protect-fallback": "Бакъо оьшу «$1»",
        "protect-expiring": "чакхйолу $1 (UTC)",
        "protect-expiring-local": "чекхйолу $1",
        "protect-expiry-indefinite": "хан чаккхе йоцуш",
-       "protect-cascade": "Гlаролла йé агlонаш, хlокху агlонца хlоттайелларш (чахчарé гlаролла)",
+       "protect-cascade": "ГӀаролла йé агӀонаш, хӀокху агӀонца хӀоттайелларш (чахчарé гӀаролла)",
        "protect-cantedit": "Хьéга хийцам цабало хӀокху агӀон гlаролли локхалан, хӀуд аьлча хьан бакъо яц оцунна тадар дан.",
        "protect-othertime": "Кхин хан:",
        "protect-othertime-op": "кхин хан",
+       "protect-existing-expiry": "Карара чекхйолу хан: $2, $3",
        "protect-otherreason": "Кхин бахьна/тӀетохар:",
        "protect-otherreason-op": "Кхин бахьна",
-       "protect-dropdown": "* ГӀоралла дарна баьхьаш \n** сих-сиха зулам дар \n** дуккха спам хилар\n** нисдаршан тӀом \n** гӀараялл агӀо",
+       "protect-dropdown": "* ГӀоралла дарна баьхьаш \n** сих-сиха зулам дар \n** дуккха спам хилар\n** нисдарийн тӀом \n** гӀараялл агӀо",
        "protect-edit-reasonlist": "Бахьанин могӀам нисбар",
        "protect-expiry-options": "1 сахьт:1 hour,1 де:1 day,1 кӀиран:1 week,2 кӀиран:2 weeks,1 бутт:1 month,3 бутт:3 months,6 бутт:6 months,1 шо:1 year,цlкъа:infinite",
        "restriction-type": "Бакъонаш:",
        "restriction-level": "ТӀекхочаран локхалла:",
        "minimum-size": "Лаххара бараме",
        "maximum-size": "Лаккхара бараме:",
+       "pagesize": "(байт)",
        "restriction-edit": "Тадар",
        "restriction-move": "ЦӀе хийцар",
        "restriction-create": "Кхоллар",
        "viewdeletedpage": "ДӀаяьхна йолу агӀонашка хьажар",
        "undelete-fieldset-title": "МеттахӀоттае версеш",
        "undeleteextrahelp": "Ерриге агӀонан истори меттахӀоттая массо а билгалонаш еса а йити '''«{{int:undeletebtn}}»''' тӀетаӀае.\nЦхӀайолу агӀонан версеш меттахӀоттая хьалха меттахӀоттош йолу версеш билгалъяьхна тӀетагӀе '''«{{int:undeletebtn}}»'''.",
+       "undeleterevisions": "$1 {{PLURAL:$1|верси}} архив чу {{PLURAL:$1|йиллина}}",
        "undeletehistory": "Агӏо меттахӏотта йича цуьнан хийцаман истори меттахӏотта ло.\nАгӏо дӏаяккхинчул тӏяха юху кхолийна елахь меттахӏоттина йолу версеш гучуер ю керлачу версешна хьалха",
        "undeleterevdel": "Метта хlоттор хира дац, нагахь иза дакъошкахь дlадайина далахь а тlаьххьара кисак башхо йа хlума.\nИштнарг хилча ахьа дlабаккха беза хlоттийна болу къастам йа хьагайта тlаьххьара дlайайина башхо.",
        "undelete-revision": "Декъашхочун $3 дӀаяьккхина верси $1 (цу $4 $5 хан):",
+       "undelete-nodiff": "Хьалхалера версеш цакарий.",
        "undeletebtn": "МеттахӀоттае",
        "undeletelink": "хьажа/меттахӀоттае",
        "undeleteviewlink": "хьажа",
        "undeleteinvert": "Къастае массо",
        "undeletecomment": "Бахьна:",
        "undeletedrevisions": "{{PLURAL:$1|меттахӀоттайина}} $1 {{PLURAL:$1|хийцам}}",
+       "undeletedrevisions-files": "меттахӀоьттина $1 {{PLURAL:$1|верси}} а $2 {{PLURAL:$2|файл}} а",
        "undeletedfiles": "$1 {{PLURAL:$1|файл меттахӀоттайина|файлаш меттахӀоттайина}}",
        "cannotundelete": "ГӀалат меттахӀоттайина:\n$1",
        "undeletedpage": "'''МеттахӀоттайина агӀо «$1».'''\n\nДӀадяхнарш долу могӀане [[Special:Log/delete|тéптаре хьажа]].",
        "undelete-error": "АгӀо меттахӀоттаяран гӀалат",
        "undelete-error-short": "Файл меттахӀоттаяран гӀалат: $1",
        "undelete-error-long": "Файл меттахӀоттош гӀалат даьлла:\n\n$1",
-       "undelete-show-file-submit": "Хlаъ",
+       "undelete-show-file-submit": "ХӀаъ",
        "namespace": "Цlерийн ана:",
-       "invert": "Хаьржинарг хилийта",
+       "invert": "Хаьржинарг къайлаяккха",
        "tooltip-invert": "ХӀоттае хӀара билгало, хаьржинчу цӀерийн меттиган агӀонашан хийцамаш къайлабаха (кхин дихкина цӀерийн меттигаш, гайтина елахь)",
        "namespace_association": "Йихкина меттиг",
        "tooltip-namespace_association": "ХӀоттае хӀара билгало, иштта дийцарийн (я кхин) цӀерийн меттиг юкъахь хилийта",
        "contributions-title": "{{GENDER:$1|Декъашхочун}} къинхьегам $1",
        "mycontris": "Сан къинхьегам",
        "contribsub2": "Къинхьегам $1 ($2)",
-       "contributions-userdoesnotexist": "«$1» Ð´ÐµÐºÑ\8aаÑ\88Ñ\85оÑ\87Ñ\83н Ð´Ó\80аÑ\8fздаÑ\80 Ð´Ó\80аÑ\8fздина Ñ\8fц.",
+       "contributions-userdoesnotexist": "«$1» Ð¸Ñ\88Ñ\82а Ð´ÐµÐºÑ\8aаÑ\88Ñ\85оÑ\87Ñ\83н Ð´Ó\80аÑ\8fздаÑ\80 Ð´Ð°ц.",
        "nocontribs": "Дехарца хийцамаш цакарий.",
        "uctop": "(карара)",
-       "month": "Ð\91аÑ\82Ñ\82аÑ\86а (я хьалхе):",
+       "month": "Ð\91аÑ\82Ñ\82аÑ\87оÑ\85Ñ\8c (я хьалхе):",
        "year": "Шерачохь (я хьалхе):",
        "sp-contributions-newbies": "Гайта бекъ къинхьегам, керла дlабазбиначара бина болу",
        "sp-contributions-newbies-sub": "Керла декъашхойн дӀаяздаршкара",
+       "sp-contributions-newbies-title": "Дукху хан йоцуш кхоьллинчу декъашхойн дӀаяздарийн къинхьегам",
        "sp-contributions-blocklog": "блоктоьхарш",
        "sp-contributions-suppresslog": "Декъашхочун дӀабаьккхина къинхьегам",
        "sp-contributions-deleted": "дӀадяхна нийсдарш",
        "sp-contributions-logs": "тéптарш",
        "sp-contributions-talk": "дийцаре",
        "sp-contributions-userrights": "декъашхочун бакъона урхалладар",
-       "sp-contributions-blocked-notice": "ХӀара декъашхочун дӀаяздар блоктоьхна ду.\nЛахахь гойту блоктохаршан тептар чура тӀаьхьарлера дӀаяздар:",
-       "sp-contributions-blocked-notice-anon": "ХӀара IP-адрес хӀинца блоктоьхна ду.\nЛахахь гойту блоктохаршан тептар чура тӀаьхьарлера дӀаяздар:",
+       "sp-contributions-blocked-notice": "ХӀара декъашхочун дӀаяздар блоктоьхна ду.\nЛахахь гойту блоктохарийн тептар чура тӀаьхьарлера дӀаяздар:",
+       "sp-contributions-blocked-notice-anon": "ХӀара IP-адрес хӀинца блоктоьхна ду.\nЛахахь гойту блоктохарийн тептар чура тӀаьхьарлера дӀаяздар:",
        "sp-contributions-search": "Къинхьегам лахар",
        "sp-contributions-username": "IP-адрес я декъашхочун цӀе:",
        "sp-contributions-toponly": "ТӀаьхьара бина хийцамаш гайта",
        "sp-contributions-newonly": "АгӀонаш кхоллар бен ма гайта",
        "sp-contributions-submit": "Лаха",
        "whatlinkshere": "Хьажоргаш кхузе",
-       "whatlinkshere-title": "ХӀокхунца «$1» йолу агӀонаш",
+       "whatlinkshere-title": "«$1» тӀе хьажоргаш йолу агӀонаш",
        "whatlinkshere-page": "Агlо:",
        "linkshere": "ТӀаьхьайогӀу агӀонаш оцу '''[[:$1]]''': хьажорагца ю",
        "nolinkshere": "ХӀокху '''[[:$1]]''' агӀона тӀе кхечу агӀонашкахь хьажоргаш яц.",
        "whatlinkshere-links": "← хьажоргаш",
        "whatlinkshere-hideredirs": "$1 дӀасахьажорш",
        "whatlinkshere-hidetrans": "$1 латораш",
-       "whatlinkshere-hidelinks": "$1 хьажоргаш",
+       "whatlinkshere-hidelinks": "$1 хьажорг",
        "whatlinkshere-hideimages": "$1 файлийн хьажоргаш",
        "whatlinkshere-filters": "Литтарш",
        "autoblockid": "Ша блоккхетар #$1",
        "block": "Декъашхочун блоктохар",
        "unblock": "ДекъашхонтӀера блокдӀаякхар",
-       "blockip": "Блоктоха",
+       "blockip": "Блоктоха {{GENDER:$1|декъашхочун}}",
        "blockip-legend": "Декъашхочун блоктохар",
        "blockiptext": "Бухахь йолу форманца блоктоха IP-адресна цунтӏера дӏаяздарш ца дайта.\nБлоктоха магийна цо зенаш деш делахь кхин хӏокху [[{{MediaWiki:Policy-url}}|низам ца]].\nЛахахь билгалде блоктохарна бахьна.",
        "ipaddressorusername": "IP-адрес я декъашхочун цӀе:",
        "ipbexpiry": "Хан чекхйолу:",
        "ipbreason": "Бахьна:",
-       "ipbreason-dropdown": "* Белхан некъ дӀакъовлар бахьанаш:\n** Харца хаам бар\n** АгӀонан чураниг дӀаяккхар\n** Спам-хьажоргаш арахьара сайташна\n** МаьӀна доцу текст тӀетохар\n** Декъашхой хьийзабар, кхерамаш тийсар\n** Масийтта лараман яздар зуламан лелаяр\n** Магийтина йоцу декъашхочун цӀе",
+       "ipbreason-dropdown": "* Белхан некъ дӀакъовлар бахьанаш:\n** Харца хаам бар\n** АгӀонан чураниг дӀаяккхар\n** Спам-хьажоргаш арахьара сайташна\n** МаьӀна доцу йоза тӀетохар\n** Декъашхой хьийзабар, кхерамаш тийсар\n** Масийтта лараман яздар зуламан лелаяр\n** Магийтина йоцу декъашхочун цӀе",
        "ipb-hardblock": "Шаш довзийтина болу декъашхошна бехкам бе хӀокху IP-адресца тадарш дан",
        "ipbcreateaccount": "Цамаго керла декъашхочун дӀаяздарш кхолла",
        "ipbemailban": "Цамагдо декъашхошка хааман кехаташ кхехьийта",
        "ipb-unblock-addr": "ДӀаякхаблок $1",
        "ipb-unblock": "дӀаякхаблок декъашхонтӀера я IP-адрес тӀера",
        "ipb-blocklist": "Блоктоьхнарш",
-       "ipb-blocklist-contribs": "Декъашхочун къинхьегам $1",
+       "ipb-blocklist-contribs": "{{GENDER:$1|$1}} къинхьегам",
        "unblockip": "ДӀаякхаблок декъашхонтӀера",
        "unblockiptext": "Лелае лахара форма IP-адрес тӀера я декъашхойн дӀаяздар тӀера блокдӀайокхуш.",
        "ipusubmit": "ДIаяккха хӀара блок",
        "blocklist": "Блоктоьхна декъашхой",
        "ipblocklist": "Блоктоьхна декъашхой",
        "ipblocklist-legend": "Блоктоьхна декъашхо лахар",
-       "blocklist-userblocks": "ДӀахьулян дӀаяздаршан блоктохарш",
+       "blocklist-userblocks": "ДӀахьулян дӀаяздарийн блоктохарш",
        "blocklist-tempblocks": "ДӀахьулян цхьан ханна йолу блоктохарш",
        "blocklist-addressblocks": "ДӀахулдан цхьайолу IP адресан блоктохарш",
        "blocklist-rangeblocks": "ДӀахьулян блоктоьхна йолу диапазонаш",
        "noautoblockblock": "ша блоктухарг дӏаяйина",
        "createaccountblock": "цамагдо керла дӀаяздарш кхоллар",
        "emailblock": "цамаго кехаташ кхехӀита",
-       "blocklist-nousertalk": "шин дийцаре агӀо тая лууш дац",
+       "blocklist-nousertalk": "шин дийцаре агӀо таян луш дац",
        "ipblocklist-empty": "Блоктохаран могӀам баьсса бу.",
        "ipblocklist-no-results": "И адрес блоктоьхна дац.",
        "blocklink": "блоктоха",
        "blocklogentry": "блоктоьхна [[$1]] цхьана ханна $2 $3",
        "reblock-logentry": "Хийцина  блоктоьхна хан [[$1]] $2 $3",
        "blocklogtext": "Блоктохаршна а блокдӀаякхаршна а тептар. Ша блоккхеташ долу IP-адресаш кхузахь гойтуш дац. Кхин. [[Special:BlockList|хӀийнца блоктоьха берш]].",
-       "unblocklogentry": "дӀаякхинаблок $1",
+       "unblocklogentry": "дӀаяькхинаблок $1",
        "block-log-flags-anononly": "Къайлаха берш",
        "block-log-flags-nocreate": "цамагдо керла дӏаяздарш кхоллар",
        "block-log-flags-noautoblock": "ша блоктухарг дӏаяйина",
        "block-log-flags-noemail": "цамаго кехаташ кхехӀита",
-       "block-log-flags-nousertalk": "шин дийцаре агӀо тая лууш дац",
+       "block-log-flags-nousertalk": "шин дийцаре агӀо таян луш дац",
        "block-log-flags-angry-autoblock": "латина шуьйра автоблоктохар",
        "block-log-flags-hiddenname": "декъашхочун цӀе къайлаяьккхина",
        "range_block_disabled": "Куьйгалхошна диапазонашна блоктоха цамага до.",
        "revertmove": "юхаяккха",
        "delete_and_move": "Цle а хуьйцуш дӀаяккха",
        "delete_and_move_text": "== ДӀаяккха хьокъ ю ==\nИ цӀе йолу аг1о «[[:$1]]» йолуш ю. \nЛаьий хьуна и дӀаяккха, цӀе хийца таро хилийта?",
-       "delete_and_move_confirm": "Хlаъ, дӀаяккха хlара агlо",
+       "delete_and_move_confirm": "ХӀаъ, дӀаяккха хӀара агӀо",
        "delete_and_move_reason": "ДӀаяьккхина цӀе хийца я таро хилийта  «[[$1]]»",
        "selfmove": "АгӀона цӏе хийца йиш яц: и цӏе хӏокху агӏона йолуш ю.",
        "immobile-source-page": "ХӀокху агӏона цӏе хийца йиш яц.",
        "thumbnail_image-missing": "$1 файл йоцчух тера ду",
        "import": "АгӀонаш чуяхар",
        "importinterwiki": "Викиюкъахь-импорт",
-       "import-interwiki-source": "Вики-хьост/агlо:",
+       "import-interwiki-sourcewiki": "ДӀайолалун вики-проект:",
+       "import-interwiki-sourcepage": "ДӀайолалун агӀо:",
        "import-interwiki-history": "ХӀокху агӀона ерриг хийцаман истори копи ян",
        "import-interwiki-templates": "Юкъайихка массо кепаш",
        "import-interwiki-submit": "Импорт ян",
        "importnopages": "Импорт ян агӀонаш яц.",
        "imported-log-entries": "{{PLURAL:$1|Тептар чура импорт дина $1 дӀаяздар|Тептар чура импорт дина $1 дӀаяздарш}}.",
        "importfailed": "Импорт ян цаелира: $1",
+       "importunknownsource": "Импорт еш йолу агӀона цадевза тайп",
        "importcantopen": "Цатарло импорт еш йолу файл елла.",
        "importbadinterwiki": "Нийса йоцу юкъаравики-хьажорг",
        "importsuccess": "Импорт яр кхочушдина!",
        "import-upload": "Чуяха XML-хаамаш",
        "import-token-mismatch": "Сеансан хаамаш дӀадайна. Дехар до, юху гӀорта.",
        "import-invalid-interwiki": "Билгалйина вики чура импорт ян йиш яц.",
-       "import-error-special": "«$1» агӀо импорт йина яц, и къастина цӀерийн меттигашан юкъайогӀуш хиларна.",
+       "import-error-edit": "«$1» агӀо хьуна таян цамагор бахьнехь и импорт цайина.",
+       "import-error-create": "«$1» агӀо хьуна кхолла цамагор бахьнехь и импорт цайина.",
+       "import-error-interwiki": "«$1» агӀо импорт ца йина, цуна цӀе арахьара хьажоргашна (юкъаравикешна) кечйина хилар бахьнехь.",
+       "import-error-special": "«$1» агӀо импорт йина яц, и къастина цӀерийн меттигийн юкъайогӀуш хиларна.",
+       "import-error-invalid": "«$1» агӀо импорт цайина, оцунна импорт еш йолу цӀе хӀокху вики чохь ца магийна хилар бахьнехь.",
+       "import-options-wrong": "{{PLURAL:$2|1=Нийса йоцу опци|Нийса йоцу опцеш}}: <nowiki>$1</nowiki>",
+       "import-rootpage-invalid": "Билгалйина коьрта агӀона цӀе нийса яц.",
        "importlogpage": "Импортан тептар",
        "importlogpagetext": "Куьйгалхоша агӀонаш импорт яр царна бина хийцамашца кхечу википедеш чура.",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|верси|версеш}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|верси импорт йина|версеш импорт йина}}",
        "import-logentry-interwiki": "«$1» — викиюкъара импорт",
-       "import-logentry-interwiki-detail": "$2 чура $1 {{PLURAL:$1|верси|версеш}}",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|верси импорт йина|версеш импорт йина}} $2 чура",
        "javascripttest": "JavaScript хьажар",
        "javascripttest-title": "$1 хьожуш бу",
        "tooltip-pt-userpage": "Декъашхочуьна агlо",
        "tooltip-ca-unwatch": "ДӀаяккха хӀара агӀо хьай тергаме могӀанан юкъар",
        "tooltip-search": "Лаха иза дош",
        "tooltip-search-go": "Билгала и санна цӀе йолучу агӀон чу дехьа гӀо",
-       "tooltip-search-fulltext": "Лаха агlонаш ше чулацамехь хlара йоза долуш",
+       "tooltip-search-fulltext": "Лаха агӀонаш ше чулацамехь хӀара йоза долуш",
        "tooltip-p-logo": "Коьрта агӀона дехьа гӀо",
        "tooltip-n-mainpage": "Коьрта агӀона дехьа гӀо",
        "tooltip-n-mainpage-description": "Коьрта агӀона дехьа гӀо",
        "ilsubmit": "Лаха",
        "bydate": "терахьашца",
        "sp-newimages-showfrom": "Гайта керла файлаш $2, $1 тӀера дуьйна",
-       "seconds-abbrev": "$1оцу",
+       "seconds-abbrev": "$1 оцу",
        "minutes-abbrev": "$1 мин",
        "hours-abbrev": "$1 сахь.",
-       "seconds": "{{PLURAL:$1|$1 секунд}}",
-       "minutes": "$1 минут",
-       "hours": "{{PLURAL:$1|сахьат}}",
-       "days": "{{PLURAL:$1|$1 де}}",
+       "seconds": "{{PLURAL:$1|$1 секунд|$1 секунд}}",
+       "minutes": "{{PLURAL:$1|$1 минот|$1 минот}}",
+       "hours": "{{PLURAL:$1|$1 сахьт|$1 сахьт}}",
+       "days": "{{PLURAL:$1|$1 де|$1 де}}",
        "weeks": "{{PLURAL:$1|$1 кӀира}}",
-       "months": "$1 {{PLURAL:$1|бутт}}",
-       "years": "$1 {{PLURAL:$1|шо}}",
+       "months": "{{PLURAL:$1|$1 бутт|$1 бутт}}",
+       "years": "{{PLURAL:$1|$1 шо|$1 шо}}",
        "ago": "$1 хьалха",
        "just-now": "хӀинца",
-       "hours-ago": "$1 сахьт хьалха",
-       "minutes-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",
        "exif-imagewidth": "Шоралла",
        "exif-imagelength": "Локхалла",
        "exif-bitspersample": "Бесан кIоргалла",
+       "exif-compression": "ТӀеӀовдан кеп",
        "exif-photometricinterpretation": "Беснин модель",
        "exif-orientation": "Суьртан хьал",
+       "exif-samplesperpixel": "Беснийн компонентийн дукхалла",
+       "exif-planarconfiguration": "Организацин хаамийн некъ",
+       "exif-ycbcrsubsampling": "Барамийн компонент Y а C а",
        "exif-ycbcrpositioning": "Y а C а компонентин листаран кеп",
        "exif-xresolution": "Шоралла",
        "exif-yresolution": "Локхалла",
+       "exif-stripoffsets": "Суьртийн хаамаш болу меттиг",
+       "exif-rowsperstrip": "Сизан тӀера могӀанийн дукхалла",
+       "exif-stripbytecounts": "ТӀеӀовдан сизан тӀера байт",
+       "exif-jpeginterchangeformat": "Доладаларан кеп preview",
+       "exif-jpeginterchangeformatlength": "Сизан хааман барам preview",
+       "exif-whitepoint": "Къайн тӀадаман бос",
+       "exif-primarychromaticities": "Коьрта беснийн бос",
        "exif-referenceblackwhite": "Ӏаьржа а къай а тӀадамийн меттиг",
        "exif-datetime": "Файл хийцина терахь а хан",
        "exif-imagedescription": "Суьртан цӏе",
        "exif-make": "Камера арахоьцург",
        "exif-model": "Камеран модель",
        "exif-software": "Лелина программа",
+       "exif-artist": "Автор",
        "exif-copyright": "Авторан бакъо ерг",
        "exif-exifversion": "Верси Exif",
        "exif-flashpixversion": "Ловш йолу верси FlashPix",
        "exif-compressedbitsperpixel": "Бесан кIоргалла дацдина чул тӀехьа",
        "exif-pixelydimension": "Суьртан шоралла",
        "exif-pixelxdimension": "Суьртан локхалла",
+       "exif-usercomment": "Кхин тӀе къамел",
        "exif-relatedsoundfile": "Къамелан аьзнийн файл",
        "exif-datetimeoriginal": "Дуьххьарлера терахь а хан",
        "exif-datetimedigitized": "Оцифровк йина терахь а хан а",
        "exif-licenseurl": "Авторийн лицензин URL",
        "exif-morepermissionsurl": "Альтернативан лицензин хаам",
        "exif-pngfilecomment": "PNG-файлан билгалдаккхар",
-       "exif-disclaimer": "Бехк тӀе ца эцар",
+       "exif-disclaimer": "Бехк тӀецалацар",
        "exif-contentwarning": "Чулацамах лаьцна дӀахьедар",
        "exif-giffilecomment": "GIF-файлан билгалдаккхар",
        "exif-intellectualgenre": "ХӀуман тайп",
        "exif-iimcategory-fin": "Экономика а бизнес а",
        "exif-iimcategory-edu": "Дешна хилар",
        "exif-iimcategory-lab": "Къинхьегам",
+       "exif-iimcategory-rel": "Дин а тешар а",
+       "exif-iimcategory-sci": "Ӏилма а техника а",
+       "exif-iimcategory-soi": "Социалан хаттарш",
+       "exif-iimcategory-wea": "Хенан хӀоттам",
        "exif-urgency-normal": "Диканиг ($1)",
        "exif-urgency-low": "Лахара ($1)",
        "exif-urgency-high": "Лакхара ($1)",
+       "exif-urgency-other": "Декъашхочо билгалйина приоритет ($1)",
        "watchlistall2": "массо",
        "namespacesall": "массо",
        "monthsall": "массо",
+       "confirmemail": "Электронан почтан адрес бакъдар",
+       "confirmemail_noemail": "Ахьа нийса электронан почтан адрес яздина дац [[Special:Preferences|гӀирсан чохь]].",
        "confirmrecreate": "Декъашхочо [[User:$1|$1]] ([[User talk:$1|дийцаре]]) хӀара агӀо дӀаяьккхина, ахьа иза тая йолийча, дӀаяккхарна бахьна:\n: ''$2''\nДехар до, тешал де, хьо иза агӀо меттахӀотто лууш ву/ю але.",
        "confirmrecreate-noreason": "Декъашхочо [[User:$1|$1]] ([[User talk:$1|дийцаре]]) хӀара агӀо дӀаяьккхина, ахьа иза тая йолийча. Дехар до, тешал де, хьо иза агӀо меттахӀотто лууш ву/ю але.",
        "recreate": "Юха кхолла",
        "autosumm-replace": "АгӀона чуьраниг хийцина → «$1»",
        "autoredircomment": "[[$1]] тӀе хьажийна",
        "autosumm-new": "Керла агlо: «$1»",
+       "autosumm-newblank": "Кхоьллина еса агӀо",
        "watchlistedit-normal-title": "Тергаме могӀанийн хийцамаш",
        "watchlistedit-normal-legend": "Тергаме могӀам юкъар дӀаяккхар",
        "watchlistedit-normal-explain": "Лахахь гойту хьан тергаме могӀамехь йолу агӀонаш.\nДӀаяздарш дӀадаха билгалде уьш такха тӀетаӀе кнопка «{{int:Watchlistedit-normal-submit}}».\nКхин хьа йиш ю [[Special:EditWatchlist/raw|йозан кепар могӀом нисба ]].",
        "watchlistedit-clear-submit": "Тергаман могӀам дӀацӀанбан (иза сацадан лурдац)",
        "watchlistedit-clear-done": "Хьан тергаман могӀам дӀацӀанбина",
        "watchlistedit-clear-removed": "{{PLURAL:$1|ДӀаяьккхина|ДӀаяьхна}} $1 {{PLURAL:$1|дӀаяздар|дӀаяздарш}}:",
-       "watchlistedit-too-many": "Ð\9aÑ\85Ñ\83ззаÑ\85Ñ\8c Ð³Ð°Ð¹Ñ\82а Ñ\82Ó\80еÑ\85Ñ\8c Ð´Ñ\83кÑ\85а Ð°Ð³Ó\80онаÑ\88 Ñ\8e.",
+       "watchlistedit-too-many": "Кхузахь гайта тӀехь дукха агӀонаш ю.",
        "watchlisttools-clear": "Тергаман могӀам дӀацӀанбан",
-       "watchlisttools-view": "Ð\9cогÓ\80ам Ñ\87Ñ\83Ñ\80а Ð°Ð³Ó\80онаÑ\88ан хийцамаш",
+       "watchlisttools-view": "Ð\9cогÓ\80ам Ñ\87Ñ\83Ñ\80а Ð°Ð³Ó\80онийн хийцамаш",
        "watchlisttools-edit": "Хьажа/нисбé могӀам",
-       "watchlisttools-raw": "Йоза санна нисдé",
+       "watchlisttools-raw": "Йоза санна тае",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|дийцаре]])",
        "version": "Верси MediaWiki",
        "version-extensions": "ДӀахӀоттийна шордарш",
-       "version-skins": "Ð\9aечяран темаш",
+       "version-skins": "Ð\94Ó\80аÑ\85Ó\80оÑ\82Ñ\82ийна Ðºечяран темаш",
        "version-specialpages": "Белхан агӀонаш",
        "version-parserhooks": "Cинтаксисан къастор схьалоцурш",
        "version-variables": "Хийцаме",
        "version-other": "Кхин",
        "version-mediahandlers": "Медиа кеч ерраш",
+       "version-hooks": "Схьалуьцарш",
        "version-parser-extensiontags": "Cинтаксисан къасторан шораллин тегаш",
        "version-parser-function-hooks": "Cинтаксисан къасторан функци схьалоцурш",
+       "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-credits-title": "Авторийн могӀам цу $1",
        "version-poweredby-credits": "ХӀара вики болх беш ю '''[https://www.mediawiki.org/ MediaWiki]''' движок тӀехь, copyright © 2001-$1 $2.",
        "version-poweredby-others": "кхин",
        "version-poweredby-translators": "гочдархой translatewiki.net",
        "version-license-info": "MediaWiki ю маьрша программин латораг, шу йиш ю фондас арахецна йолу GNU General Public License лицензица и яржо я хийца а.\n\nMediaWiki яржош ю и шуна пайдане хир яц те аьлла, амма  ЦХЬА ЮКЪАРАХИЛАР ДОЦУШ. Хь. кхин. лицензи мадарра GNU General Public License .\n\nШоьга кхача езаш яра [{{SERVER}}{{SCRIPTPATH}}/COPYING копи GNU General Public License] хӀокху программица, кхаьчна яцахь язъе Free Software Foundation, Inc., адрес тӀе: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA я [//www.gnu.org/licenses/old-licenses/gpl-2.0.html еша и онлайнехь].",
        "version-software": "ДӀахӀоттийна программин латтор",
+       "version-software-product": "Сурсат",
        "version-software-version": "Верси",
        "version-entrypoints": "ЧугӀо адресин тӀадамаш",
        "version-entrypoints-header-entrypoint": "Яздаран тӀадам",
        "fileduplicatesearch-info": "$1 × $2 пиксель<br />Файлан барам: $3<br />MIME-тайп: $4",
        "fileduplicatesearch-result-1": "«$1» файлах тера хӀума яц.",
        "fileduplicatesearch-noresults": "ЦӀе «$1» йолуш файл цакарий.",
-       "specialpages": "Леррина агlонаш",
+       "specialpages": "Леррина агӀонаш",
        "specialpages-note": "* Гуттарлера белха агlонаш.\n* <strong class=\"mw-specialpagerestricted\">Кlеззиг таронаш йолу леррина агlонаш.</strong>",
        "specialpages-group-maintenance": "Жамlаш гlирса хьашташ кхочушдар",
        "specialpages-group-other": "Кхин белхан агӀонаш",
        "logentry-rights-rights": "$1 {{GENDER:$2|хийцина}} $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",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|чуяьккхина}} керла верси $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|чуяьккхина}} $3",
        "rightsnone": "(яц)",
        "feedback-bugornote": "Хьайн техникин халонах лаьцна яздан хӀума делахь, дехар до, [$1 хаам бе тхоьга].\nДацахь хьан йиш ю хӀокху атта кепаца «[$3 $2]» агӀонг къамел тӀетоха хьан декъашхочун цӀарца, кхин лелош йолу браузер билгал еш.",
        "feedback-subject": "Къамел:",
        "api-error-duplicate": "Иштта чулацам болу {{PLURAL:$1|1=[$2 кхин файл]|[$2 кхин файлаш]}} йолуш ю",
        "api-error-duplicate-popup-title": "{{PLURAL:$1|1=Файлан|Файлийн}} дубликат.",
        "api-error-empty-file": "Ахьа яхьийтина файл еса ю.",
+       "api-error-mustbeposted": "Чоьхьара гӀалат: дехаро хьехам схьабоьху HTTP POST.",
        "api-error-noimageinfo": "Кхиамца чуяьккхина, амма серверо файлахь лаьцна цхьаа хаам битина бац.",
        "api-error-nomodule": "Чоьхьара гӀалат: чуйокху модуль нисйина яц.",
        "api-error-ok-but-empty": "Чоьхьара гӀалат: серверара жоп дац.",
        "api-error-uploaddisabled": "ХӀокху вики чохь файлаш чуяхар дӀадайина ду.",
        "api-error-verification-error": "ХӀара файл йоьхна я хила цаеза тайпан хила мега.",
        "duration-seconds": "$1 {{PLURAL:$1|секунд}}",
-       "duration-minutes": "$1 {{PLURAL:$1|минут}}",
+       "duration-minutes": "$1 {{PLURAL:$1|минот}}",
        "duration-hours": "$1 {{PLURAL:$1|сахьт}}",
        "duration-days": "$1 {{PLURAL:$1|де}}",
        "duration-weeks": "$1 {{PLURAL:$1|кӀира}}",
        "expand_templates_generate_xml": "Гойту дитта цу XML",
        "expand_templates_generate_rawhtml": "Гайта HTML",
        "expand_templates_preview": "Хьалха муха ю хьажа",
+       "pagelanguage": "АгӀона мотт харжар",
        "pagelang-name": "АгӀо",
        "pagelang-language": "Мотт",
        "pagelang-use-default": "Ӏад битарца мотт",
        "right-pagelang": "АгӀона мотт хийца",
        "action-pagelang": "агӀона мотт хийца",
        "log-name-pagelang": "Мотт хийцаран тептар",
-       "log-description-pagelang": "ХӀара агӀонашкахь мотт хийцаран тептар ду."
+       "log-description-pagelang": "ХӀара агӀонашкахь мотт хийцаран тептар ду.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|хийцина}} агӀона мотт $3 $4 → $5.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (латина)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''дӀаяйина''')"
 }
index 803e6f0..84c6ea2 100644 (file)
        "talkpagelinktext": "Hisgot",
        "specialpage": "Espesyal nga panid",
        "personaltools": "Personal nga galamiton",
-       "postcomment": "Pagbilin og komento",
        "articlepage": "Tan-awa ang panid sa sulod",
        "talk": "Panaghisgot-hisgot",
        "views": "Mga pagtan-aw",
        "externaldberror": "May nahitabong authentication database error o kaha wala ka tugoti nga mag-update sa imong eksternal nga akawnt.",
        "login": "Sulod",
        "nav-login-createaccount": "Rehistro / Dayon",
-       "loginprompt": "Kinahanglang naka-enable ang mga koki aron ikaw maka-log-in sa {{SITENAME}}.",
        "userlogin": "Rehistro / Dayon",
        "logout": "Biya",
        "userlogout": "Bıveciye",
        "recentchangeslinked-to": "Ipakita na lang ang mga pag-usab sa mga panid nga nakasumpay sa nahatag nga panid",
        "upload": "Pagsumiter og payl",
        "uploadlogpage": "Log sa upload",
-       "uploadedimage": "na-upload ang \"[[$1]]\"",
        "license": "Paglilisensya:",
        "license-header": "Paglilisensya",
        "file-anchor-link": "Payl",
index 96b48e0..6a2eddc 100644 (file)
        "talkpagelinktext": "Kuentusi",
        "specialpage": "Påhina espesiat",
        "personaltools": "Ramientan petsonat",
-       "postcomment": "Fa'tinas un komentu",
        "articlepage": "Atan i guinaha i påhina",
        "talk": "Diskuti",
        "views": "Mali'e'-ña",
        "yourdomainname": "Lugat-mu:",
        "login": "Log in",
        "nav-login-createaccount": "Hålom / fa'tinas kuenta-mu",
-       "loginprompt": "Un nesita muna'sedi cookies para un log in gi {{SITENAME}}.",
        "userlogin": "Hålom / fa'tinas kuenta-mu",
        "logout": "Log out",
        "userlogout": "Log out",
        "nextn": "{{PLURAL:$1|$1}} ni manmamaila'",
        "viewprevnext": "Atan i ($1 {{int:pipe-separator}} $2) ($3)",
        "search-result-size": "$1 ({{PLURAL:$2|1 na palabra|$2 na palabra siha}})",
-       "search-result-score": "Prinisisu: $1%",
        "search-redirect": "(na'dirihi $1)",
        "search-section": "(påtte $1)",
        "search-suggest": "Kao kumekeilek-mu: $1",
        "upload": "Na'kåtga hulu' i atkibu",
        "uploadbtn": "Na'kåtga hulu' atkibu",
        "uploadlogpage": "Na'kåtga i log",
-       "uploadedimage": "mana'kåtga hulu' \"[[$1]]\"",
        "listfiles": "Listan atkibu",
        "file-anchor-link": "Atkibu",
        "filehist": "Historian atkibu",
index 42f53e3..327d973 100644 (file)
@@ -13,7 +13,8 @@
                        "Muhammed taha",
                        "رزگار",
                        "아라",
-                       "Serwan"
+                       "Serwan",
+                       "Ebraminio"
                ]
        },
        "tog-underline": "ھێڵ ھێنان بەژێر بەستەرەکان:",
        "category-empty": "''ئەم پۆلە ھەنووکە ھیچ پەڕە یان پەڕگەیەک لە خۆ ناگرێت.‌''",
        "hidden-categories": "{{PLURAL:$1|پۆلی شارداوە|پۆلە شارداوەکان}}",
        "hidden-category-category": "پۆلە شاردراوەکان",
-       "category-subcat-count": "{{PLURAL:$2|ئەم پۆلە تەنیا ژێرپۆلی ژێرەوەی تێدایە.| ئەم پۆلە ئەم {{PLURAL:$1|ژێرپۆلەی|$1 ژێرپۆلانەی}} ژێرەوەی تێدایە، لە کۆی سەرجەم $2 دانە.}}",
+       "category-subcat-count": "{{PLURAL:$2|ئەم پۆلە تەنیا ژێرپۆلی ژێرەوەی تێدایە.|ئەم پۆلە {{PLURAL:$1|ژێرپۆل|$1 ژێرپۆل}}ی ژێرەوەی تێدایە، لە سەرجەم $2 ژێرپۆل.}}",
        "category-subcat-count-limited": "ئەم هاوپۆلە {{PLURAL:$1|ژێرهاوپۆلی}} لەخۆ گرتووە.",
-       "category-article-count": "{{PLURAL:$2|ئەم پۆلە تەنھا ئەم پەڕەی لەخۆگرتووە.|{{PLURAL:$1|پەڕە|$1 پەڕە}} لەم پۆلەدا، لە سەرجەم $2 پەڕە.}}",
+       "category-article-count": "{{PLURAL:$2|ئەم پۆلە تەنیا پەڕەی ژێرەوەی تێدایە.|{{PLURAL:$1|پەڕە|$1 پەڕە}}ی ژێرەوە لەم پۆلەدا{{PLURAL:$1|یە|ن}}، لە سەرجەم $2 پەڕە.}}",
        "category-article-count-limited": "ئەم {{PLURAL:$1|لاپەڕە|$1 لاپەڕانە}}، لەم هاوپۆلەدان.",
        "category-file-count": "{{PLURAL:$2|ئەم هاوپۆلە تەنها ئەم پەڕگەی لەخۆ گرتووە.|ئەم‌ {{PLURAL:$1|پەڕگەیە}} کە بەشێکە لە هەموو $2پەڕگەی ئەم هاوپۆلە‌ دەیبینی.}}",
        "category-file-count-limited": "ئەم {{PLURAL:$1|پەڕگە|پەڕگانە}} لەم هاوپۆلەدایە.",
        "morenotlisted": "ئەم لیستەیە تەواو نییە",
        "mypage": "پەڕه‌",
        "mytalk": "لێدوان",
-       "anontalk": "Ù\88تÙ\88Ù\88Û\8eÚ\98 Ø¨Û\86 Ø¦Û\95Ù\85 Ø¦Ø§Û\8câ\80\8cÙ¾Û\8c یە",
+       "anontalk": "Ù\84Û\8eدÙ\88اÙ\86 Ø¨Û\86 Ø¦Û\95Ù\85 Ø¦Ø§Û\8cÙ¾Û\8cیە",
        "navigation": "ڕێدۆزی",
        "and": "&#32;و",
        "qbfind": "بدۆزەرەوە",
        "talkpagelinktext": "لێدوان",
        "specialpage": "په‌ڕه‌ی تایبه‌ت",
        "personaltools": "ئامڕازە تاکەکەسییەکان",
-       "postcomment": "بەشی نوێ",
        "articlepage": "پەڕەی ناوەرۆک ببینە",
        "talk": "وتووێژ",
        "views": "بینینەکان",
        "hidetoc": "بیشارەوە",
        "collapsible-collapse": "کۆی بکەوە",
        "collapsible-expand": "بڵاوی بکەوە",
+       "confirmable-yes": "بەڵێ",
+       "confirmable-no": "نا",
        "thisisdeleted": "$1 نیشان بدە یا بھێنەوە؟",
        "viewdeleted": "$1 نیشان بده‌؟",
        "restorelink": "{{PLURAL:$1|یەک گۆڕانکاریی سڕاو|$1 گۆڕانکاریی سڕاو}}",
        "externaldberror": "یان هەڵەی ڕێگەپێدانی بنکەدراو هەیە یان ڕێگات پێ نادرێت بۆ نوێ کردنی هەژماری دەرەکیت.",
        "login": "بچۆ ژوورەوە",
        "nav-login-createaccount": "بچۆ ژوورەوە / ھەژمار دروست بکە",
-       "loginprompt": "بۆ چوونەژوورەوە بۆ {{SITENAME}} دەبێ کوکییەکان چالاک بکەیت.",
        "userlogin": "بچۆ ژوورەوە / ھەژمار دروست بکە",
        "userloginnocreate": "بچۆ ژوورەوە",
        "logout": "بچۆ دەرەوە",
        "userlogin-resetlink": "وردەکارییەکانی چوونەژوورەوەتت لە بیر کردووە؟",
        "userlogin-resetpassword-link": "تێپەڕوشەکەت بیر کردووە؟",
        "userlogin-helplink2": "یارمەتی بۆ چوونەژوورەوە",
-       "userlogin-loggedin": "تۆ ھەر ئێستا بە ناوی {{GENDER:$1|$1}} چوویتە ژوورەوە.\nفۆرمی ژێرەوە بەکاربھێنە بۆ چوونەژوورەوە وەک بەکارھێنەرێکی تر.",
-       "userlogin-createanother": "ھەژمارێکی تر دروست بکە",
        "createacct-emailrequired": "ناونیشانی ئیمەیل",
        "createacct-emailoptional": "ناونیشانی ئیمەیل (دڵخوازانە)",
        "createacct-email-ph": "ناونیشانی ئیمەیلەکەت بنووسە",
        "undo-success": "دەکرێ دەستکاریەکە پووچەڵبکرێتەوە.\nتکایە چاو لەو هەڵسەنگاندنەی خوارەوە بکە تا دڵنیا بیت ئەمە ئەوەیە کە‌ دەتویست بیکەی و دواتر گۆڕانکارییەکانی خوارەوە پاشەکەوت بکە بۆ تەواوکردنی پووچەڵکردنەوەکە.",
        "undo-failure": "لەبەر کێشەی دەست‌تێ‌وەردان، ناتوانی دەستکاریەکە ئەنجام‌نەدراو بکەیت.",
        "undo-norev": "ناتوانی دەستکاریەکە ئەنجام‌نەدراو بکەی لەبەر ئەوەی بوونی نیە یا سڕدراوەتەوە.",
-       "undo-summary": "Ú¯Û\95Ú\95اÙ\86دÙ\86Û\95Ù\88Û\95Û\8c Ù¾Û\8eداÚ\86Ù\88Ù\88Ù\86Û\95Ù\88Û\95Û\8c $1 Ù\84Û\95 Ù\84اÛ\8cÛ\95Ù\86 [[Special:Contributions/$2|$2]] ([[User talk:$2|Ù\88تÙ\88Ù\88Û\8eÚ\98]])",
+       "undo-summary": "Ú¯Û\95Ú\95اÙ\86دÙ\86Û\95Ù\88Û\95Û\8c Ù¾Û\8eداÚ\86Ù\88Ù\88Ù\86Û\95Ù\88Û\95Û\8c $1 Ù\84Û\95 Ù\84اÛ\8cÛ\95Ù\86 [[Special:Contributions/$2|$2]] ([[User talk:$2|Ù\84Û\8eدÙ\88اÙ\86]])",
        "cantcreateaccounttitle": "ناتوانرێت هەژمار دروست بکرێت",
        "cantcreateaccount-text": "درووست‌کردنی هەژمارە بۆ ناونیشانی ئای‌پی ('''$1''') لە لایەن [[User:$3|$3]] داخراوە.<br /><br />\n$3 هۆکاری \"$2\" خستوەتەڕوو",
        "viewpagelogs": "لۆگەکانی ئەم پەڕەیە ببینە",
        "currentrev": "دوایین پێداچوونەوە",
        "currentrev-asof": "دوایین پێداچوونەوەی $1",
        "revisionasof": "وەک پێداچوونەوەی $1",
-       "revision-info": "پێداچوونەوی $1 لە لایەن $2",
+       "revision-info": "پێداچوونەوی $1 لە لایەن {{GENDER:$6|$2}}$7",
        "previousrevision": "→پیاچوونەوەی کۆنتر",
        "nextrevision": "پێداچوونەوەی نوێتر←",
        "currentrevisionlink": "پێداچوونەوەی ئێستا",
        "searchprofile-advanced-tooltip": "گەڕان لەناو بۆشایی‌ناوە دڵخوازەکان",
        "search-result-size": "$1 ({{PLURAL:$2|یەک وشە|$2 وشە}})",
        "search-result-category-size": "{{PLURAL:$1|١ ئەندام|$1 ئەندام}} ({{PLURAL:$2|١ ژێرپۆل|$2 ژێرپۆل}}, {{PLURAL:$3|١ پەڕگە|$3 پەڕگە}})",
-       "search-result-score": "پەیوەندی: $1%",
        "search-redirect": "(ڕەوانەکەر $1)",
        "search-section": "(بەشی $1)",
        "search-suggest": "ئایا مەبەستت ئەمە بوو: $1",
        "searchrelated": "پەیوەست",
        "searchall": "ھەموو",
        "showingresults": "لە خوارەوە {{PLURAL:$1|'''یەک''' ئەنجام|'''$1''' ئەنجام}} نیشان دراوە، بە دەست پێ کردن لە ژمارەی '''$2'''ەوە.",
-       "showingresultsheader": "{{PLURAL:$5|ئاکامی '''$1''' لە '''$3'''|ئاکامەکانی '''$1 - $2''' لە '''$3'''}} بۆ '''$4'''",
        "search-nonefound": "ھیچ ئاکامێک کە بە داواکارییەکەت بخوا نەدۆزرایەوە.",
        "powersearch-legend": "گەڕانی پێشکەوتوو",
        "powersearch-ns": "گەڕان لە بۆشاییی ناوەکانی:",
        "powersearch-togglelabel": "تاوتوێ بکە:",
        "powersearch-toggleall": "ھەموو",
        "powersearch-togglenone": "ھیچیان",
+       "powersearch-remember": "ھەڵبژاردەکانت بۆ گەڕانەکانی تر لە بیر بێت",
        "search-external": "گەڕانی دەرەکی",
        "searchdisabled": "گەڕانی {{SITENAME}} ئێستە کار ناکات.\nدەتوانی بۆ ئێستا لە گەڕانی گووگڵ کەڵک وەرگری.\nلەیادت بێت لەوانەیە پێرستەکانیان بۆ گەڕانی ناو {{SITENAME}}، کات‌بەسەرچوو بێت.",
        "preferences": "ھەڵبژاردەکان",
        "default": "بنچینەیی",
        "prefs-files": "پەڕگەکان",
        "prefs-custom-css": "CSSی دڵخواز",
-       "prefs-custom-js": "JSی دڵخواز",
+       "prefs-custom-js": "جاڤاسکریپتی دڵخواز",
        "prefs-common-css-js": "سی‌ئێس‌ئێس/جاڤاسکریپتی ھاوبەش بۆ گشت پێستەکان:",
        "prefs-reset-intro": "دەتوانی لەم لاپەڕە بۆ گەڕانەوەی هەڵبژاردەکانت بۆ بنچینەیی ماڵپەر کەڵک وەرگریت.\nگەر ئەوە بکەی ئیتر گۆڕانەکەت ناگەڕێتەوە.",
        "prefs-emailconfirm-label": "پشتڕاستکردنەوەی ئیمەیل:",
        "file-deleted-duplicate": "ئەم پەڕگەیە ڕێک وەک ئەم پەڕگە ([[:$1]]) دەچێت کە لەم دواییانەدا سڕاوەتەوە.\nپێش دەست‌پێ‌کردنی دیسان بارکردنەوەی، تکایە چاو لە مێژووی سڕینەوەی ئەو پەڕگە بکە.",
        "uploadwarning": "ئاگادارییەکانی بارکردن",
        "savefile": "پەڕگە پاشەکەوت بکە",
-       "uploadedimage": "«[[$1]]»ی بارکرد",
-       "overwroteimage": "وەشانێکی نوێی «[[$1]]» بار کرد",
        "uploaddisabled": "بارکردن قەدەخە کراوە",
        "uploaddisabledtext": "بارکردنی پەڕگەکان لە کار خستراوە.",
        "php-uploaddisabledtext": "بارکردنی پەڕگەکان لە PHPدا لە کار خستراوە.\nتکایە چاو لە هەڵبژاردەکانی بارکردنی_پەڕگەکان بکە.",
        "license-nopreview": "(پێشبینین ئامادەی کەڵک وەرگرتن نییە)",
        "upload_source_url": " (URLـی بەکار، بۆ دەست‌پێگەیشتنی  گشتی)",
        "upload_source_file": " (پەڕگەیەک لەسەر کۆمپیوتەرەکەت)",
+       "listfiles-delete": "بیسڕەوە",
        "listfiles-summary": "ئەم پەڕە تایبەتە ھەموو پەڕگە بارکراوەکان نیشان دەدات.",
        "listfiles_search_for": "بگەڕێ بۆ ناوی میدیای:",
        "imgfile": "پەڕگە",
        "unusedtemplates": "داڕێژە بەکارنەھێنراوەکان",
        "unusedtemplatestext": "ئەم پەڕە هەموو پەڕەکانی بۆشاییی ناوی {{ns:template}} بە لیست دەکات کە لە پەڕەی تردا بەکارنەھێنراون.\nلە بیری نەکەی پێش سڕینەوەیان پشکنینی بەستەرەکانی تر بۆ داڕێژەکان بکەی.",
        "unusedtemplateswlh": "بەستەرەکانی تر",
-       "randompage": "پەڕەیەک بە هەڵکەوت",
+       "randompage": "پەڕەی ھەڕەمەکی",
        "randompage-nopages": "هیچ لاپەڕەیەک لەم {{PLURAL:$2|ناوبۆشاییەدا|ناوبۆشاییانەدا}} نیە: $1.",
-       "randomincategory-selectcategory-submit": "بڕۆ",
-       "randomredirect": "ڕەوانەکەری ھەرمەکی",
+       "randomincategory": "پەڕەی پۆلی ھەڕەمەکی",
+       "randomredirect": "ڕەوانەکەری ھەڕەمەکی",
        "randomredirect-nopages": "لە ناوبۆشایی \"$1\" هیچ ڕەوانکەرێک نییە.",
        "statistics": "ئامارەکان",
        "statistics-header-pages": "ئامارەکانی پەڕەکان",
        "pageswithprop-text": "ئەم پەڕەیە ئەو پەڕانەی تایبەتمەندییەکی پەرەیەکی دیاریکراو بەکاردەھێنن پێرست دەکا.",
        "pageswithprop-prop": "ناوی تایبەتمەندی:",
        "pageswithprop-submit": "بڕۆ",
-       "doubleredirects": "دووجار ڕەوانەکراوەکان",
+       "doubleredirects": "ڕەوانەکەرە دووسەرەکان",
        "doubleredirectstext": "ئەم پەڕە لیستی ئەو پەڕانەیە کە ڕەوانەکراون بۆ پەڕەیەکی ڕەوانەکراوی دیکە.\nهەر ڕیزێک، بەستەرەکانی ڕەوانەکردنەوەی یەکەم و دووەم و ھەروەھا ئامانجی ڕەوانەکراوی دووەمی تێدایە کە حاڵەتی ئاساییدا مەبەستی «ڕاستی»ی ڕەوانەکراوی یەکەمیش دەبێ بۆ ئەوێ بێت.\nئەوانەی <del>هێڵیان بەسەردا کێشراوە</del> چارەسەر کراون.",
        "double-redirect-fixed-move": "[[$1]] گوازرایەوە.\nخۆگەڕ نوێ کرایەوە و ئێستا ڕەوانەکەرە بۆ [[$2]].",
        "double-redirect-fixer": "چارەسەرکەری ڕەوانکەر",
        "watchlist-details": "{{PLURAL:$1|$1 پەڕە|$1 پەڕە}} لە لیستی چاودێریەکەتدایە، بێجگە پەڕەکانی لێدوان.",
        "wlheader-enotif": "ئاگاداری بە ئیمەیل چالاکە.",
        "wlheader-showupdated": "‏ئەو پەڕانە کە لە پاش دواین سەردانت دەستکاری کراون بە '''ئەستوور''' نیشان دراون",
+       "wlnote": "خوارەوە {{PLURAL:$1|دوایین گۆڕانکارییە|دوایین '''$1''' گۆڕانکارییە}} لە دوایین {{PLURAL:$2|کاتژمێر|'''$2''' کاتژمێر}}دا ھەتا $4 لە $3.",
        "wlshowlast": "دوایین $1 کاتژمێر $2 ڕۆژی $3 نیشان بدە",
        "watchlist-options": "ھەڵبژاردەکانی لیستی چاودێری",
        "watching": "چاودێری...",
        "rollbacklinkcount-morethan": "گەڕاندنەوەی زۆرتر لە $1 {{PLURAL:$1|دەستکاری}}",
        "rollbackfailed": "گەڕاندنەوە سەرکەوتوو نەبوو",
        "cantrollback": "دەستکاریەکان ناگەڕێندرێتەوە؛\nدوایین هاوبەش تەنها ڕێکخەری ئەم لاپەڕەیە.",
-       "alreadyrolled": "دÙ\88اÛ\8cÛ\8cÙ\86 Ú¯Û\86Ú\95اÙ\86کارÛ\8cÛ\95کاÙ\86Û\8c Ù\84Û\95سÛ\95ر [[:$1]] Ù\84Û\95 Ù\84اÛ\8cÛ\95Ù\86 [[User:$2|$2]] Ù\86اگÛ\95Ú\95Û\8eÙ\86درÛ\8eÙ\86Û\95Ù\88Û\95 ([[User talk:$2|Ù\88تÙ\88Ù\88Û\8eÚ\98]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]])Ø\9b Ú©Û\95سÛ\8eÚ©Û\8c Ø¯Û\8cÚ©Û\95 Ù\84Û\95 Ù¾Û\8eØ´â\80\8cدا Ø¯Û\95ستکارÛ\8c Ú©Ø±Ø¯Ù\88Ù\88Û\95 Û\8cاÙ\86 Ú¯Û\95Ú\95اÙ\86دÙ\88Ù\88Û\8cÛ\95تÛ\95Ù\88Û\95.\n\nدÙ\88اÛ\8cÛ\8cÙ\86 Ø¯Û\95ستکارÛ\8c Ø¦Û\95Ù\85 Ù\84اپÛ\95Ú\95Û\95 [[User:$3|$3]] Ú©Ø±Ø¯Ù\88Ù\88Û\8cÛ\95 ([[User talk:$3|Ù\88تÙ\88Ù\88Û\8eÚ\98]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
+       "alreadyrolled": "دÙ\88اÛ\8cÛ\8cÙ\86 Ú¯Û\86Ú\95اÙ\86کارÛ\8cÛ\8cÛ\95کاÙ\86 Ù\84Û\95سÛ\95ر [[:$1]] Ù\84Û\95 Ù\84اÛ\8cÛ\95Ù\86 [[User:$2|$2]] Ù\86اگÛ\95Ú\95Û\8eÙ\86درÛ\8eÙ\86Û\95Ù\88Û\95 ([[User talk:$2|Ù\84Û\8eدÙ\88اÙ\86]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]])Ø\9b Ú©Û\95سÛ\8eÚ©Û\8c ØªØ± Ù\84Û\95 Ù¾Û\8eشدا Ø¯Û\95ستکارÛ\8cÛ\8c Ú©Ø±Ø¯Ù\88Ù\88Û\95 Û\8cاÙ\86 Ú¯Û\95Ú\95اÙ\86دÙ\88Ù\88Û\8cÛ\95تÛ\95Ù\88Û\95.\n\nدÙ\88اÛ\8cÛ\8cÙ\86 Ø¯Û\95ستکارÛ\8c Ø¦Û\95Ù\85 Ù¾Û\95Ú\95Û\95 [[User:$3|$3]] Ú©Ø±Ø¯Ù\88Ù\88Û\8cÛ\95 ([[User talk:$3|Ù\84Û\8eدÙ\88اÙ\86]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "پوختەی دەستکاری \"''$1''\" بوو.",
        "revertpage": "گەڕاندنەوەی دەستکارییەکانی [[Special:Contributions/$2|$2]] ([[User talk:$2|لێدوان]]) بۆ دوایین پێداچوونەوەی [[User:$1|$1]]",
        "revertpage-nouser": "دەستکارییەکانی بەکارھێنەرێکی شاڕدراوە بۆ دوایین پێداچوونەوەی {{GENDER:$1|[[User:$1|$1]]}} گەڕێنرایەوە.",
        "undeleteviewlink": "دیتن",
        "undeleteinvert": "ھەڵبژاردەکان پێچەوانە بکە",
        "undeletecomment": "هۆکار:",
-       "undeletedrevisions": "{{PLURAL:$1|1 پێداچوونەوە|$1 پێداچوونەوە}} هێنرایەوە",
+       "undeletedrevisions": "{{PLURAL:$1|$1 پێداچوونەوە}} هێنرایەوە",
        "undeletedrevisions-files": "{{PLURAL:$1|1 پێداچوونەوە|$1 پێداچوونەوە}} و {{PLURAL:$2|1 پەڕگە|$2 پەڕگە}} هێنرایەوە",
        "undeletedfiles": "{{PLURAL:$1|1 پەڕگە|$1 پەڕگە}} هێنرایەوه",
        "cannotundelete": "ھێنانەوە سەرکەوتوو نەبوو:\n$1",
        "noautoblockblock": "بەربەستنی خۆگەڕ ناچالاکە",
        "createaccountblock": "دروستکردنی ھەژمار ناچالاکە",
        "emailblock": "ئیمەیل ناچالاکە",
-       "blocklist-nousertalk": "دÛ\95ستکارÛ\8cکردÙ\86Û\8c Ù¾Û\95Ú\95Û\95Û\8c Ù\88تÙ\88Ù\88Û\8eÚ\98ی خۆی ناچالاکە",
+       "blocklist-nousertalk": "دÛ\95ستکارÛ\8cکردÙ\86Û\8c Ù¾Û\95Ú\95Û\95Û\8c Ù\84Û\8eدÙ\88اÙ\86ی خۆی ناچالاکە",
        "ipblocklist-empty": "لیستی بەربەستەکان بەتاڵە",
        "ipblocklist-no-results": "ئای‌پی ئەدرەس یان ناوی‌ بەکارهێنەری داواکراو بەربەست نەکراوە.",
        "blocklink": "بەربەستن",
        "block-log-flags-nocreate": "دروستکردنی ھەژمار ناچالاک کرا",
        "block-log-flags-noautoblock": "بەربەستنی خۆگەڕ ناچالاک کرا",
        "block-log-flags-noemail": "ئیمەیل ناچالاک کرا",
-       "block-log-flags-nousertalk": "دÛ\95ستکارÛ\8cکردÙ\86Û\8c Ù¾Û\95Ú\95Û\95Û\8c Ù\88تÙ\88Ù\88Û\8eÚ\98ی خۆی ناچالاک کرا",
+       "block-log-flags-nousertalk": "دÛ\95ستکارÛ\8cکردÙ\86Û\8c Ù¾Û\95Ú\95Û\95Û\8c Ù\84Û\8eدÙ\88اÙ\86ی خۆی ناچالاک کرا",
        "block-log-flags-angry-autoblock": "بەربەستکردنی خۆگەڕی پێشکەوتوو چالاک کرا",
        "block-log-flags-hiddenname": "ناوی بەکارھێنەری شاراوە",
        "range_block_disabled": "تایبەتمەندی بەڕێوەبەر بۆ بەربەست‌کردنی زنجیرە لە کارخستراوە.",
        "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دڵنیا بە کە [[Special:DoubleRedirects|دووجار ڕەوانەکراوەکان]] یان [[Special:BrokenRedirects|ڕەوانەکراوە شکاوەکان]] تاقی بکەیتەوە.\nتۆ بەرپرسیاری لەوەی کە دڵنیا ببیتەوە بەستەرەکان ھەر پێوەندییان ھەیە بەو شوێنە کە چاوەڕوان دەکرێت.\n\nدەبێت بزانی کە پەڕەکە '''ناگوازرێتەوە''' ئەگەر پێشتر پەڕەیەک بە ناوە نوێکەوە ھەبێت، مەگەر ئەوەی کە پەڕەکە واڵا یان ڕەوانەکراوەیەک بێت و ھیچ مێژووی گۆڕاندنی پێشووی نەبێت.\nئەمە بەو واتایە کە ئەگەر ھەڵەیەک بکەی دەتوانی ناوی پەڕەکە دیسانەوە بگۆڕی بۆ ناوی پێشووی، و ناتوانی بیخەیتە جێگەی پەڕەیەک کە ھەنووکە ھەیە.\n\n'''ھۆشیار بە!'''\nئەمە دەتوانێت گۆڕانێکی زۆر نابەجێ و چاوەڕێنەکراو بێت بۆ پەڕەیەکی بەناوبانگ؛\nتکایە پێش گۆڕینی ناو باش بیر لە ئاکامەکەی بکەوە.",
-       "movepagetalktext": "Ù¾Û\95Ú\95Û\95Û\8c Ù\88تÙ\88Ù\88Û\8eÚ\98Û\8c Ù¾Û\95Û\8cÙ\88Û\95Ù\86دÛ\8cدارÛ\8c Ø¨Û\95 Ø´Û\8eÙ\88Û\95Û\8c Ø®Û\86کار Ù\84Û\95Ú¯Û\95ÚµÛ\8cدا Ø¯Û\95Ú¯Ù\88ازرÛ\8eتÛ\95Ù\88Û\95Ø\8c '''Ù\85Û\95Ú¯Û\95ر:'''\n* Ù¾Û\95Ú\95Û\95Û\8cÛ\95Ú©Û\8c Ù\88تÙ\88Ù\88Û\8eÚ\98Û\8c Ù\86اÙ\88اڵا Ù¾Û\8eشتر Ú¾Û\95بÛ\8eت Ù\84Û\95 Ú\98Û\8eر Ù\86اÙ\88Û\95 Ù\86Ù\88Û\8eÚ©Û\95داØ\8c Û\8cاÙ\86\n* Ø¦Û\95Ù\88 Ú\86Ù\88ارÚ\86Û\8eÙ\88Û\95Û\8c Ø®Ù\88ارÛ\95Ù\88Û\95 Ù\84Û\8eÙ\86Û\95دراÙ\88 Ø¨Ú©Û\95Û\8c.\n\nÙ\84Û\95Ù\88 Ø­Ø§ÚµÛ\95تÛ\95داØ\8c Ø¦Û\95Ú¯Û\95ر Ø¨ØªÛ\95Ù\88Û\8eت Ø¨Û\8cÚ¯Ù\88ازÛ\8cتÛ\95Ù\88Û\95 Ù\86اÚ\86ار Ø¯Û\95بÛ\8cت Ø¨Û\95 Ø´Û\8eÙ\88Û\95Û\8c Ø¯Û\95ستÛ\8c Ø¨Û\8cÚ¯Ù\88ازÛ\8cتÛ\95Ù\88Û\95 Û\8cاÙ\86 ØªÛ\8eÚ©Û\95ÚµÛ\8cاÙ\86 Ø¨Ú©Û\95Û\8c.",
+       "movepagetext-noredirectfixer": "بەکارھێنانی فۆرمەکەی ژێرەوە ناوی پەڕەیەک دەگۆڕێت، بە گواستنەوەی ھەموو مێژووەکەی بۆ ناوی نوێ.\nناوە کۆنەکە دەبێتە پەڕەیەکی ڕەوانەکەر بۆ ناوە نوێکە.\nلە بیرت بێ ڕەوانەکەرە [[Special:DoubleRedirects|دووسەرەکان]] یان [[Special:BrokenRedirects|شکاوەکان]] تاوتوێ بکەیت.\nتۆ بەرپرسی بۆ ئەوەی دڵنیا ببیتەوە بەستەرەکان ھەر پەیوەندییان ھەیە بەو شوێنەوە کە چاوەڕوان دەکرێت.\n\nئەمە بزانە کە پەڕەکە <strong>ناگوازرێتەوە</strong> ئەگەر پێشتر پەڕەیەک بە ناوە نوێکەوە ھەبێت، مەگەر ئەوەی کە ڕەوانەکەرێک بێت و مێژووی دەستکاریی پێشووی نەبێت.\nئەمە یانی ئەگەر ھەڵەیەک بکەیت دەتوانی ناوی پەڕەکە بگۆڕییەوە بۆ ناوی پێشووی، و ناتوانی بیخەیتە جێگەی پەڕەیەک کە ئێستا ھەیە.\n\n<strong>ھۆشدار!</strong>\nئەمە دەتوانێت گۆڕانێکی زۆر نابەجێ و چاوەڕوان‌نەکراو بێت بۆ پەڕەیەکی بەناوبانگ؛\nتکایە پێش گۆڕینی ناو دڵنیا بە بیرت لە ئاکامەکەی کردووەتەوە.",
+       "movepagetalktext": "Ù¾Û\95Ú\95Û\95Û\8c Ù\84Û\8eدÙ\88اÙ\86Û\8c Ù¾Û\95Û\8cÙ\88Û\95Ù\86دÛ\8cدار Ø¨Û\95 Ø´Û\8eÙ\88Û\95Û\8c Ø®Û\86Ú¯Û\95Ú\95 Ù\84Û\95Ú¯Û\95ÚµÛ\8c Ø¯Û\95Ú¯Ù\88ازرÛ\8eتÛ\95Ù\88Û\95Ø\8c <strong>Ù\85Û\95Ú¯Û\95ر:</strong>\n* Ù¾Û\95Ú\95Û\95Û\8cÛ\95Ú©Û\8c Ù\84Û\8eدÙ\88اÙ\86Û\8c Ù\86اÙ\88اڵا Ù¾Û\8eشتر Ù\84Û\95 Ú\98Û\8eر Ù\86اÙ\88Û\95 Ù\86Ù\88Û\8eÚ©Û\95دا Ú¾Û\95بÛ\8eتØ\8c Û\8cاÙ\86\n* Ø¦Û\95Ù\88 Ú\86Ù\88ارÚ\86Û\8eÙ\88Û\95Û\8c Ú\98Û\8eرÛ\95Ù\88Û\95 Ù\84Û\8eÙ\86Û\95دراÙ\88 Ø¨Ú©Û\95Û\8cت.\n\nÙ\84Û\95Ù\88 Ø¯Û\86خاÙ\86Û\95داØ\8c Ø¦Û\95Ú¯Û\95ر Ø¨ØªÛ\95Ù\88Û\8eت Ø¯Û\95بÛ\8e Ø¨Û\95 Ø¯Û\95ستÛ\8c Ù¾Û\95Ú\95Û\95Ú©Û\95 Ø¨Ú¯Ù\88ازÛ\8cتÛ\95Ù\88Û\95 Û\8cاÙ\86 ØªÛ\8eÚ©Û\95ÚµÛ\8cاÙ\86 Ø¨Ú©Û\95Û\8cت.",
        "movearticle": "ئەم پەڕەیە بگوازەوە:",
+       "moveuserpage-warning": "<strong>ھۆشدار:</strong> تۆ خەریکی گواستنەوەی پەڕەیەکی بەکارھێنەری. تکایە ئەمە لەبەرچاو بگرە تەنیا پەڕەکە دەگوازرێتەوە و ناوی بەکارھێنەر <em>ناگۆڕدرێ</em>.",
+       "movecategorypage-warning": "<strong>ھۆشدار:</strong> تۆ خەریکی گواستنەوەی پەڕەی پۆلی. تکایە ئەمە لەبەرچاو بگرە تەنیا پەڕەکە دەگوازرێتەوە و پەڕەکانی ناو پۆلە کۆنەکە <em>ناچێتە</em> ناو پۆلە نوێکەوە.",
        "movenologintext": "بۆ گواستنەوەی پەڕەیەک، ئەشێ ببی بە ئەندام و [[Special:UserLogin|لە ژوورەوە]] بیت.",
        "movenotallowed": "ڕێگەت پێ‌نەدراوە بۆ گواستنەوەی لاپەڕەکان.",
        "movenotallowedfile": "ڕێگەت پێ‌نەدراوە بۆ گواستنەوەی پەڕگەکان.",
        "movepage-moved-noredirect": "لە دانانی ڕەوانەکەر بەرگری کرا.",
        "articleexists": "پەڕەیەک بەم ناوە ھەیە یان ئەو ناوەی تۆ ھەڵتبژاردووە ڕێگەی پێنەدراوە.\nتکایە ناوێکی دیکە ھەڵبژێرە.",
        "cantmove-titleprotected": "ناتوانی لاپەڕەیەک بگوێزیتەوە بۆ ئەم شوێنە، لەبەر ئەوەی سەردێڕی نوێ لە درووست‌کردن پارێزراوە.",
-       "movetalk": "Ù¾Û\95Ú\95Û\95Û\8c Ù\88تÙ\88Ù\88Û\8eÚ\98ی پەیوەندیدار بگوازەوە",
+       "movetalk": "Ù¾Û\95Ú\95Û\95Û\8c Ù\84Û\8eدÙ\88اÙ\86ی پەیوەندیدار بگوازەوە",
        "move-subpages": "ژێرپەڕەکانی بگوازەوە (ھەتا $1 پەڕە)",
-       "move-talk-subpages": "Ú\98Û\8eرپÛ\95Ú\95Û\95کاÙ\86Û\8c Ù¾Û\95Ú\95Û\95Û\8c Ù\88تÙ\88Ù\88Û\8eÚ\98 بگوازەوە (ھەتا $1 پەڕە)",
+       "move-talk-subpages": "Ú\98Û\8eرپÛ\95Ú\95Û\95کاÙ\86Û\8c Ù¾Û\95Ú\95Û\95Û\8c Ù\84Û\8eدÙ\88اÙ\86 بگوازەوە (ھەتا $1 پەڕە)",
        "movepage-page-exists": "پەڕەی $1 هەیە و ناتوانرێت خۆکار بخرێتە جێی.",
        "movepage-page-moved": "پەڕەی $1 گۆزرایەوە بۆ $2.",
        "movepage-page-unmoved": "ناکرێ پەڕەی $1 بگوێزرێتەوە بۆ $2.",
        "import": "ھاوردنی پەڕەکان",
        "importinterwiki": "ھاوردنی ناووویکی",
        "import-interwiki-text": "بۆ ھاوردن، ویکییەک و سەردێڕێکی پەڕە ھەڵبژێرە.\nڕێکەوتەکانی پێداچوونەوە و ناوی دەستکاریکەرەکان دەپارێزرێت.\nهەموو کردەوەکانی ھاوردنی ناوویکی لە [[Special:Log/import|لۆگی ھاوردن]]دا تۆمار دەکرێت.",
-       "import-interwiki-source": "ویکی/پەڕەی سەرچاوە:",
+       "import-interwiki-sourcewiki": "ویکی سەرچاوە:",
+       "import-interwiki-sourcepage": "پەڕەی سەرچاوە:",
        "import-interwiki-history": "هەموو مێژووی پێداچوونەوەکانی ئەم پەڕەیە کۆپی بکە",
        "import-interwiki-templates": "ھەموو داڕێژەکان لەخۆبگرێتەوە",
        "import-interwiki-submit": "هاوردە بکە",
        "version-software-product": "بەرهەم",
        "version-software-version": "وەشان",
        "version-entrypoints-header-url": "ناونیشانی ئینتەرنێتی",
+       "redirect": "ڕەوانەکەر بە پێی پەڕگە، بەکارھێنەر، پەڕە یان پێناسەی پێداچوونەوە",
        "redirect-submit": "بڕۆ",
        "fileduplicatesearch": "گەڕان بۆ پەڕگە دووپات کراوەکان",
        "fileduplicatesearch-summary": "گەڕان بۆ پەڕگە دووبارەکراوەکان لەسەر بنەمای نرخی hash.",
        "specialpages-group-pages": "پێرستەکانی پەڕەکان",
        "specialpages-group-pagetools": "ئامرازەکانی پەڕە",
        "specialpages-group-wiki": "دراوەکان و ئامرازەکان",
-       "specialpages-group-redirects": "پەڕە تایبەتەکانی رەوانکردنەوە",
+       "specialpages-group-redirects": "پەڕە تایبەتەکانی ڕەوانەکردن",
        "specialpages-group-spam": "ئامرازەکانی سپەم",
        "blankpage": "پەڕەی واڵا",
        "intentionallyblankpage": "ئەم پەڕەیە لەقەست واڵا ھێڵراوەتەوە.",
        "tags": "گۆڕانکاری گونجاوی تاگەکان",
        "tag-filter": "پاڵێوی [[Special:Tags|تاگ]]:",
        "tag-filter-submit": "پاڵاوتن",
+       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|تاگ|تاگەکان}}]]: $2)",
        "tags-title": "تاگەکان",
        "tags-intro": "ئەم لاپەڕە ئەو تاگانەی لیست دەکات کە لەوانەیە نەرمامێر دەستکاریەکی بۆ نیشان بکات و مەبەستی نیشان بدات.",
        "tags-tag": "ناوی تاگ",
        "logentry-newusers-byemail": "ھەژماری بەکارھێنەریی $3 لە لایەن $1 {{GENDER:$2|دروست کرا}} و تێپەڕوشە بە ئیمەیل نێردرا",
        "logentry-newusers-autocreate": "ھەژماری بەکارھێنەریی $1 بە شێوەی خۆگەڕ {{GENDER:$2|دروست کرا}}",
        "logentry-rights-rights": "$1 ئەندامێتیی $3ی لە $4 بۆ $5 {{GENDER:$2|گۆڕی}}",
+       "logentry-upload-upload": "$1 $3ی {{GENDER:$2|بار کرد}}",
+       "logentry-upload-overwrite": "$1 وەشانێکی نوێی $3ی {{GENDER:$2|بار کرد}}",
        "rightsnone": "(ھیچ)",
        "feedback-subject": "بابەت:",
        "feedback-message": "پەیام:",
index 1cbf870..01fe0c0 100644 (file)
        "talkpagelinktext": "discussione",
        "specialpage": "Pagina speciale",
        "personaltools": "Strumenti persunali",
-       "postcomment": "Nova sezione",
        "articlepage": "Vede l'articulu",
        "talk": "Discussione",
        "toolbox": "Stuvigli",
index 18ff1d5..a878acd 100644 (file)
        "talkpagelinktext": "Istoryahanay",
        "specialpage": "Pinasahi nga pahina",
        "personaltools": "Mga pangkaugalingon nga galamiton",
-       "postcomment": "Bag-o nga seksyon",
        "articlepage": "Ipakita ang pahina sang ka-undan",
        "talk": "Diskusyon",
        "views": "Mga dagway",
        "yourdomainname": "Imo domain:",
        "login": "Mag sulod",
        "nav-login-createaccount": "Magsulod / mag-ubra sang account",
-       "loginprompt": "Dapat nakabukas ang cookies para makasulod sa {{SITENAME}}.",
        "userlogin": "Mag sulod / mag-ubra account",
        "userloginnocreate": "Magsulod",
        "logout": "Maggwa",
        "upload": "Magkarga sang akta",
        "uploadlogpage": "Lista sang upload",
        "filedesc": "Kasumahan",
-       "uploadedimage": "na-upload ang \"[[$1]]\"",
        "license": "Paglaong:",
        "file-anchor-link": "Akta",
        "filehist": "Kasaysayan sang akta",
index 2a38313..bc24170 100644 (file)
        "talkpagelinktext": "Музакере",
        "specialpage": "Махсус Саифе",
        "personaltools": "Шахсий алетлер",
-       "postcomment": "Янъы болюк",
        "articlepage": "Саифеге бар",
        "talk": "Музакере",
        "views": "Корюнишлер",
        "externaldberror": "Сайткъа киргенде бир хата олды. Бу тыш эсабынъызны денъиштирмек акъкъынъыз олмагъанындан себеп мейдангъа келип ола.",
        "login": "Кириш",
        "nav-login-createaccount": "Кириш / Къайд олув",
-       "loginprompt": "Отурым ачмакъ ичюн «cookies»ге изин бермелисинъиз.",
        "userlogin": "Кириш / Къайд олув",
        "userloginnocreate": "Кириш",
        "logout": "Чыкъыш",
        "searchprofile-everything-tooltip": "Бутюн саифелерде (музакере саифелеринде де) къыдыр",
        "searchprofile-advanced-tooltip": "Бельгиленген исим фезаларында къыдыр",
        "search-result-size": "$1 ({{PLURAL:$2|1=1|$2}} сёз)",
-       "search-result-score": "Уйгъунлыкъ: $1 %",
        "search-redirect": "(ёллама $1)",
        "search-section": "(болюк $1)",
        "search-suggest": "Бунымы демеге истединъиз: $1",
        "file-exists-duplicate": "Бу файл ашагъыдаки {{PLURAL:$1|1=файлнынъ|файлларнынъ}} дубликаты ола:",
        "uploadwarning": "Тенби",
        "savefile": "Файлны сакъла",
-       "uploadedimage": "Юкленген: \"[[$1]]\"",
-       "overwroteimage": "\"[[$1]]\" янъы версиясы юкленди",
        "uploaddisabled": "Юклеме ясакълыдыр.",
        "uploaddisabledtext": "Файл юклеме ясакълыдыр.",
        "uploadscripted": "Бу файлда браузер тарафындан янълышнен ишленип олур HTML коду я да скрипт бар.",
        "watchlist-details": "Музакере саифелерини эсапкъа алмайып, козетюв джедвелинъизде {{PLURAL:$1|1=1|$1}} саифе бар.",
        "wlheader-enotif": "E-mail иле хабер берюв ачылды.",
        "wlheader-showupdated": "Сонъки зияретинъизден сонъ денъиштирильген саифелер '''къалын арифлернен''' косьтерильди.",
+       "wlnote": "Ашагъыда саат $3, $4 ичюн сонъки {{PLURAL:$2|1=саат|'''$2''' саат}} ичинде япылгъан сонъки {{PLURAL:$1|1=денъиштирме|'''$1''' денъиштирме}} косьтериле.",
        "wlshowlast": "Сонъки $1 саат ичюн, $2 кунь ичюн я да $3 косьтер",
        "watchlist-options": "Козетюв джедвели сазламалары",
        "watching": "Козетюв джедвелине кирсетильмекте...",
index 82e3a05..1e10057 100644 (file)
        "talkpagelinktext": "Muzakere",
        "specialpage": "Mahsus Saife",
        "personaltools": "Şahsiy aletler",
-       "postcomment": "Yañı bölük",
        "articlepage": "Saifege bar",
        "talk": "Muzakere",
        "views": "Körünişler",
        "externaldberror": "Saytqa kirgende bir hata oldı. Bu tış esabıñıznı deñiştirmek aqqıñız olmağanından sebep meydanğa kelip ola.",
        "login": "Kiriş",
        "nav-login-createaccount": "Kiriş / Qayd oluv",
-       "loginprompt": "Oturım açmaq içün \"cookies\"ge izin bermelisiñiz.",
        "userlogin": "Kiriş / Qayd oluv",
        "userloginnocreate": "Kiriş",
        "logout": "Çıqış",
        "searchprofile-everything-tooltip": "Bütün saifelerde (muzakere saifelerinde de) qıdır",
        "searchprofile-advanced-tooltip": "Belgilengen isim fezalarında qıdır",
        "search-result-size": "$1 ({{PLURAL:$2|1|$2}} söz)",
-       "search-result-score": "Uyğunlıq: $1%",
        "search-redirect": "(yollama $1)",
        "search-section": "(bölük $1)",
        "search-suggest": "Bunımı demege istediñiz: $1",
        "file-exists-duplicate": "Bu fayl aşağıdaki {{PLURAL:$1|faylnıñ|fayllarnıñ}} dublikatı ola:",
        "uploadwarning": "Tenbi",
        "savefile": "Faylnı saqla",
-       "uploadedimage": "Yüklengen: \"[[$1]]\"",
-       "overwroteimage": "\"[[$1]]\" yañı versiyası yüklendi",
        "uploaddisabled": "Yükleme yasaqlıdır.",
        "uploaddisabledtext": "Fayl yükleme yasaqlıdır.",
        "uploadscripted": "Bu faylda brauzer tarafından yañlışnen işlenip olur HTML kodu ya da skript bar.",
        "watchlist-details": "Muzakere saifelerini esapqa almayıp, közetüv cedveliñizde {{PLURAL:$1|1|$1}} saife bar.",
        "wlheader-enotif": "E-mail ile haber berüv açıldı.",
        "wlheader-showupdated": "Soñki ziyaretiñizden soñ deñiştirilgen saifeler '''qalın ariflernen''' kösterildi.",
+       "wlnote": "Aşağıda saat $3, $4 içün soñki {{PLURAL:$2|saat|'''$2''' saat}} içinde yapılğan soñki {{PLURAL:$1|deñiştirme|'''$1''' deñiştirme}} kösterile.",
        "wlshowlast": "Soñki $1 saat içün, $2 kün içün ya da $3 köster",
        "watchlist-options": "Közetüv cedveli sazlamaları",
        "watching": "Közetüv cedveline kirsetilmekte...",
index 0e298a5..9650e6f 100644 (file)
@@ -42,6 +42,7 @@
        "tog-watchdefault": "Přidávat mnou editované stránky a soubory ke sledovaným",
        "tog-watchmoves": "Přidávat mnou přesouvané stránky a soubory mezi sledované",
        "tog-watchdeletion": "Přidávat stránky a soubory, které smažu, mezi sledované",
+       "tog-watchrollback": "Přidávat stránky, které jsem {{GENDER:|vrátil|vrátila}} zpět, ke sledovaným",
        "tog-minordefault": "Označovat editace implicitně jako malé",
        "tog-previewontop": "Zobrazovat náhled před editačním oknem (ne za ním)",
        "tog-previewonfirst": "Zobrazit při první editaci náhled",
        "talkpagelinktext": "diskuse",
        "specialpage": "Speciální stránka",
        "personaltools": "Osobní nástroje",
-       "postcomment": "Nová sekce",
        "articlepage": "Prohlédnout si stránku",
        "talk": "Diskuse",
        "views": "Zobrazení",
        "otherlanguages": "V jiných jazycích",
        "redirectedfrom": "(Přesměrováno z $1)",
        "redirectpagesub": "Přesměrování",
+       "redirectto": "Přesměrování na:",
        "lastmodifiedat": "Stránka byla naposledy editována $1 v $2.",
        "viewcount": "Stránka byla zobrazena {{PLURAL:$1|jedenkrát|$1krát|$1krát}}.",
        "protectedpage": "Zamčená stránka",
        "hidetoc": "skrýt",
        "collapsible-collapse": "Sbalit",
        "collapsible-expand": "Rozbalit",
+       "confirmable-confirm": "Jste si {{GENDER:$1|jist|jista|jisti}}?",
+       "confirmable-yes": "Ano",
+       "confirmable-no": "Ne",
        "thisisdeleted": "Prohlédnout nebo obnovit $1?",
        "viewdeleted": "Zobrazit $1?",
        "restorelink": "{{PLURAL:$1|smazanou editaci|$1 smazané editace|$1 smazaných editací}}",
        "invalidtitle-knownnamespace": "Neplatný název se jmenným prostorem „$2“ a textem „$3“",
        "invalidtitle-unknownnamespace": "Neplatný název s neznámým číslem jmenného prostoru $1 a textem „$2“",
        "exception-nologin": "Nejste přihlášen(a)",
-       "exception-nologin-text": "Pro přístup na tuto stránku nebo k této akci se prosím [[Special:Userlogin|přihlaste]].",
+       "exception-nologin-text": "Pro přístup na tuto stránku nebo k této akci se musíte přihlásit.",
        "exception-nologin-text-manual": "Pro přístup na tuto stránku nebo k této akci se musíte $1.",
        "virus-badscanner": "Špatná konfigurace: neznámý antivirový program: ''$1''",
        "virus-scanfailed": "prověřování selhalo (kód $1)",
        "externaldberror": "Buď nastala chyba externí autentizační databáze, nebo nemáte dovoleno měnit svůj externí účet.",
        "login": "Přihlaste se",
        "nav-login-createaccount": "Přihlášení / vytvoření účtu",
-       "loginprompt": "K přihlášení do {{grammar:2sg|{{SITENAME}}}} musíte mít povoleny cookies.",
        "userlogin": "Přihlášení / vytvoření účtu",
        "userloginnocreate": "Přihlášení",
        "logout": "Odhlásit se",
        "userlogin-resetlink": "Zapomněli jste přihlašovací údaje?",
        "userlogin-resetpassword-link": "Zapomněli jste heslo?",
        "userlogin-helplink2": "Nápověda k přihlašování",
-       "userlogin-loggedin": "Již jste {{GENDER:$1|přihlášen|přihlášena}} jako $1.\nPomocí formuláře níže se můžete přihlásit jako jiný uživatel.",
-       "userlogin-createanother": "Vytvořit jiný účet",
        "createacct-emailrequired": "E-mailová adresa",
        "createacct-emailoptional": "E-mailová adresa (nepovinné)",
        "createacct-email-ph": "Zadejte svou e-mailovou adresu",
        "loginerror": "Chyba při přihlašování",
        "createacct-error": "Chyba při zakládání účtu",
        "createaccounterror": "Nepodařilo se vytvořit uživatelský účet: $1",
-       "nocookiesnew": "Uživatelský účet byl vytvořen, ale nejste přihlášeni. {{SITENAME}} používá cookies k přihlášení uživatelů. Vy máte cookies vypnuty. Prosím zapněte je a přihlaste se znovu s vaším novým uživatelským jménem a heslem.",
+       "nocookiesnew": "Uživatelský účet byl vytvořen, ale nejste přihlášeni. {{SITENAME}} používá cookies k přihlášení uživatelů. Vy máte cookies vypnuty. Prosím, zapněte je a poté se přihlaste svým novým uživatelským jménem a heslem.",
        "nocookieslogin": "{{SITENAME}} používá cookies k přihlášení uživatelů. Vy máte cookies vypnuty. Prosím zapněte je a zkuste znovu.",
        "nocookiesfornew": "Uživatelský účet nebyl založen, neboť jsme nebyli schopni potvrdit jeho původ.\nUjistěte se, že máte povoleny cookies, obnovte tuto stránku a zkuste to znovu.",
        "noname": "Musíte uvést jméno svého účtu.",
        "createaccount-text": "Někdo na {{grammar:6sg|{{SITENAME}}}} ($4) vytvořil účet s vaší e-mailovou adresou.\nJméno účtu: „$2“\nHeslo: „$3“\nMěli byste se co nejdřív přihlásit a změnit si heslo.\n\nPokud byl účet vytvořen omylem, považujte tuto zprávu za bezpředmětnou.",
        "login-throttled": "Provedli jste příliš mnoho pokusů o přihlášení.\nNež to zkusíte znovu, musíte počkat na vypršení lhůty $1.",
        "login-abort-generic": "Vaše přihlášení se nezdařilo – přerušeno",
+       "login-migrated-generic": "Váš účet byl zmigrován a vaše uživatelské jméno již nadále na této wiki neexistuje.",
        "loginlanguagelabel": "Jazyk: $1",
        "suspicious-userlogout": "Váš požadavek na odhlášení byl odmítnut, neboť to vypadá, že ho poslal rozbitý prohlížeč nebo cachující proxy.",
        "createacct-another-realname-tip": "Skutečné jméno je nepovinné.\nPokud se ho rozhodnete uvést, bude použito pro označení autorství vaší práce.",
        "preview": "Náhled",
        "showpreview": "Ukázat náhled",
        "showdiff": "Ukázat změny",
-       "anoneditwarning": "'''Varování:''' Nejste přihlášen(a). Vaše IP adresa bude zveřejněna v historii této stránky.",
+       "blankarticle": "<strong>Upozornění:</strong> Stránka, kterou se chystáte založit, je prázdná. Pokud ještě jednou kliknete na „{{int:savearticle}}“, bude založena zcela bez obsahu.",
+       "anoneditwarning": "'''Varování:''' Nejste přihlášen(a). Pokud uložíte jakoukoli editaci, bude vaše IP adresa zveřejněna v historii této stránky. Pokud se <strong>[$1 přihlásíte]</strong> nebo si <strong>[$2 vytvoříte účet]</strong>, budou vaše editace připsány vašemu uživatelskému jménu a získáte i další výhody.",
        "anonpreviewwarning": "''Nejste přihlášen(a). Uložením zveřejníte svou IP adresu v historii této stránky.''",
        "missingsummary": "'''Připomenutí:''' Nezadali jste shrnutí editace. Pokud ještě jednou kliknete na Uložit změny, bude vaše editace zapsána bez shrnutí.",
        "missingcommenttext": "Zadejte komentář",
        "parser-template-recursion-depth-warning": "Překročen limit hloubky rekurzivního vkládání šablon ($1)",
        "language-converter-depth-warning": "Překročen limit vnoření u jazykové konverze ($1)",
        "node-count-exceeded-category": "Stránky překračující počet uzlů",
-       "node-count-exceeded-category-desc": "Kategorie pro stránky, kde je překročen počet uzlů.",
+       "node-count-exceeded-category-desc": "Tato stránka překračuje maximální počet uzlů.",
        "node-count-exceeded-warning": "Stránka překročila počet uzlů",
        "expansion-depth-exceeded-category": "Stránky překračující hloubku expanze",
-       "expansion-depth-exceeded-category-desc": "Toto je kategorie pro stránky, ve kterých je překročena hloubka expanze.",
+       "expansion-depth-exceeded-category-desc": "Stránka překročila maximální hloubku expanze.",
        "expansion-depth-exceeded-warning": "Stránka překročila hloubku expanze",
        "parser-unstrip-loop-warning": "Detekováno zacyklení unstrip",
        "parser-unstrip-recursion-limit": "Překročen limit rekurze unstrip ($1)",
        "rev-deleted-event": "(záznam odstraněn)",
        "rev-deleted-user-contribs": "[uživatelské jméno nebo IP adresa odstraněny – editace v příspěvcích skryta]",
        "rev-deleted-text-permission": "Tato revize byla '''smazána'''.\nPodrobnosti mohou být uvedeny v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} knize smazaných stránek].",
+       "rev-suppressed-text-permission": "Tato revize byla <strong>utajena</strong>. Podrobnosti jsou uvedeny v [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} knize utajení].",
        "rev-deleted-text-unhide": "Tato revize byla '''smazána'''.\nPodrobnosti mohou být uvedeny v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} knize smazaných stránek].\nPokud chcete, můžete si přesto [$1 tuto revizi prohlédnout].",
        "rev-suppressed-text-unhide": "Tato revize byla '''utajena'''.\nPodrobnosti mohou být uvedeny v [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} záznamu utajení].\nPokud chcete, můžete si přesto [$1 tuto revizi prohlédnout].",
        "rev-deleted-text-view": "Tato revize byla '''smazána'''.\nMůžete si ji prohlédnout; podrobnosti jsou uvedeny v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} knize smazaných stránek].",
        "revdelete-text-text": "Smazané editace se budou i nadále zobrazovat v historii stránky, ale části jejich obsahu nebudou veřejně přístupné.",
        "revdelete-text-file": "Smazané verze souborů se budou i nadále zobrazovat v historii stránky, ale části jejich obsahu nebudou veřejně přístupné.",
        "logdelete-text": "Smazané protokolovací záznamy se budou i nadále zobrazovat v historii stránky, ale části jejich obsahu nebudou veřejně přístupné.",
-       "revdelete-text-others": "Ostatní správci {{grammar:2sg|{{SITENAME}}}} budou i nadále moci ke skrytému obsahu přistupovat a mohou ho pomocí stejného rozhraní obnovit, pokud nejsou nastavena dodatečná omezení.",
+       "revdelete-text-others": "Ostatní správci budou i nadále moci ke skrytému obsahu přistupovat a mohou ho obnovit, pokud nejsou nastavena dodatečná omezení.",
        "revdelete-confirm": "Prosím potvrďte, že to opravdu chcete učinit, že si uvědomujete důsledky a že je to v souladu s [[{{MediaWiki:Policy-url}}|pravidly]].",
        "revdelete-suppress-text": "Utajování by se mělo používat '''pouze''' v následujících případech:\n* Potenciálně pomlouvačné informace\n* Nevhodné osobní údaje\n*: ''adresy bydliště a telefonní čísla, rodná čísla apod.''",
        "revdelete-legend": "Nastavit omezení viditelnosti",
        "searchprofile-advanced-tooltip": "Nastavit jmenné prostory, ve kterých se má hledat",
        "search-result-size": "$1 ({{PLURAL:$2|1 slovo|$2 slova|$2 slov}})",
        "search-result-category-size": "{{PLURAL:$1|1 položka|$1 položky|$1 položek}} ({{PLURAL:$2|1 podkategorie|$2 podkategorie|$2 podkategorií}}, {{PLURAL:$3|1 soubor|$3 soubory|$3 souborů}})",
-       "search-result-score": "Relevantnost: $1 %",
        "search-redirect": "(přesměrování $1)",
        "search-section": "(část $1)",
        "search-file-match": "(odpovídá obsahu souboru)",
        "searchall": "vše",
        "showingresults": "Níže zobrazuji nejvýše <strong>$1</strong> {{PLURAL:$1|výsledek|výsledky|výsledků}} počínaje od <strong>$2</strong>.",
        "showingresultsinrange": "Níže zobrazuji nejvýše <strong>$1</strong> {{PLURAL:$1|výsledek|výsledky|výsledků}} v rozsahu #<strong>$2</strong>–#<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Výsledek '''$1''' z '''$3'''|Výsledky '''$1–$2''' z '''$3'''}} pro '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Výsledek <strong>$1</strong> z <strong>$3</strong>|Výsledky <strong>$1–$2</strong> z <strong>$3</strong>}}",
        "search-nonefound": "Na váš dotaz nebyly nalezeny žádné výsledky.",
        "powersearch-legend": "Rozšířené vyhledávání",
        "powersearch-ns": "Hledat ve jmenných prostorech:",
        "preferences": "Nastavení",
        "mypreferences": "Nastavení",
        "prefs-edits": "Počet editací:",
-       "prefsnologintext2": "Pro změnu uživatelských nastavení se musíte $1.",
+       "prefsnologintext2": "Pro změnu uživatelských nastavení se musíte přihlásit.",
        "prefs-skin": "Vzhled",
        "skin-preview": "Náhled",
        "datedefault": "Implicitní",
        "prefs-namespaces": "Jmenné prostory",
        "default": "implicitní",
        "prefs-files": "Soubory",
-       "prefs-custom-css": "Vlastní CSS",
-       "prefs-custom-js": "Vlastní JS",
-       "prefs-common-css-js": "Sdílené CSS/JS pro všechny styly:",
+       "prefs-custom-css": "Uživatelské CSS",
+       "prefs-custom-js": "Uživatelský JavaScript",
+       "prefs-common-css-js": "Sdílené CSS/JavaScript pro všechny styly:",
        "prefs-reset-intro": "Pomocí této stránky můžete všechna nastavení vrátit na implicitní hodnoty.\nTuto operaci nelze vrátit zpět.",
        "prefs-emailconfirm-label": "Ověření e-mailu:",
        "youremail": "E-mail:",
        "right-deletedtext": "Prohlížení smazaného textu a rozdílů mezi smazanými verzemi",
        "right-browsearchive": "Vyhledávání ve smazaných stránkách",
        "right-undelete": "Obnovování smazaných stránek",
-       "right-suppressrevision": "Prohlížení a obnovování revizí skrytých před správci",
+       "right-suppressrevision": "Prohlížení, skrývání a odkrývání revizí skrytých před všemi uživateli",
+       "right-viewsuppressed": "Prohlížení revizí skrytých před všemi uživateli",
        "right-suppressionlog": "Prohlížení skrytých protokolovacích záznamů",
        "right-block": "Blokování možnosti editace ostatním uživatelům",
        "right-blockemail": "Blokování možnosti poslat e-mail",
        "recentchanges-legend-heading": "'''Legenda:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vizte též [[Special:NewPages|seznam nových stránek]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Níže jsou změny od <strong>$2</strong> ({{PLURAL:$1|zobrazena|zobrazeny|zobrazeno}} nejvýše <strong>$1</strong>).",
+       "rcnotefrom": "Níže {{PLURAL:$5|je změna|jsou změny}} od <strong>$3, $4</strong> ({{PLURAL:$1|zobrazena|zobrazeny|zobrazeno}} nejvýše <strong>$1</strong>).",
        "rclistfrom": "Ukázat nové změny, počínaje od $2, $3",
        "rcshowhideminor": "$1 malé editace",
        "rcshowhideminor-show": "Zobrazit",
        "uploadwarning": "Upozornění k načítání",
        "uploadwarning-text": "Prosíme, upravte popis souboru níže a zkuste to znovu.",
        "savefile": "Uložit soubor",
-       "uploadedimage": "načítá „[[$1]]“",
-       "overwroteimage": "načtena nová verze \"[[$1]]\"",
        "uploaddisabled": "Načítání souborů vypnuto.",
        "copyuploaddisabled": "Načítání souborů prostřednictvím URL je vypnuto.",
        "uploaddisabledtext": "Načítání souborů je vypnuto.",
        "license": "Licence:",
        "license-header": "Licence",
        "nolicense": "Bez udání licence",
+       "licenses-edit": "Editovat nabídku licencí",
        "license-nopreview": "(Náhled není dostupný)",
-       "upload_source_url": " (platné, veřejně přístupné URL)",
-       "upload_source_file": " (soubor ve vašem počítači)",
+       "upload_source_url": "(vybraný soubor z platného, veřejně přístupného URL)",
+       "upload_source_file": "(vybraný soubor z vašeho počítače)",
+       "listfiles-delete": "smazat",
        "listfiles-summary": "Tato speciální stránka zobrazuje všechny načtené soubory.",
        "listfiles_search_for": "Hledat soubor podle názvu:",
        "imgfile": "soubor",
        "randomincategory": "Náhodná stránka z kategorie",
        "randomincategory-invalidcategory": "„$1“ není platný název kategorie.",
        "randomincategory-nopages": "V [[:Category:$1|kategorii $1]] žádné stránky nejsou.",
-       "randomincategory-selectcategory": "Získat náhodnou stránku z kategorie: $1 $2",
-       "randomincategory-selectcategory-submit": "Přejít",
+       "randomincategory-category": "Kategorie:",
+       "randomincategory-legend": "Náhodná stránka v kategorii",
        "randomredirect": "Náhodné přesměrování",
        "randomredirect-nopages": "Ve jmenném prostoru „$1“ nejsou žádná přesměrování.",
        "statistics": "Statistika",
        "wantedpages-badtitle": "Výsledky obsahují neplatný název: $1",
        "wantedfiles": "Chybějící soubory",
        "wantedfiletext-cat": "Následující soubory se používají, ale neexistují. Soubory ze vzdálených úložišť zde mohou být uvedeny, přestože existují. Taková falešná pozitiva budou zobrazena <del>přeškrtnutě</del>. Stránky, které vkládají neexistující soubory, jsou navíc uvedeny v [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Následující soubory se používají, ale neexistují. Stránky, které používají neexistující soubory, jsou navíc uvedeny v [[:$1]].",
        "wantedfiletext-nocat": "Následující soubory se používají, ale neexistují. Soubory ze vzdálených úložišť zde mohou být uvedeny, přestože existují. Taková falešná pozitiva budou zobrazena <del>přeškrtnutě</del>.",
+       "wantedfiletext-nocat-noforeign": "Následující soubory se používají, ale neexistují.",
        "wantedtemplates": "Chybějící šablony",
        "mostlinked": "Nejodkazovanější stránky",
        "mostlinkedcategories": "Nejpoužívanější kategorie",
        "trackingcategories-desc": "Kritéria pro vložení do kategorie",
        "noindex-category-desc": "Stránka není indexována roboty, protože obsahuje kouzelné slovo <code><nowiki>__NOINDEX__</nowiki></code> a je ve jmenném prostoru, ve kterém je tento příznak dovolen.",
        "index-category-desc": "Stránka obsahuje kouzelné slovo <code><nowiki>__INDEX__</nowiki></code> (a je ve jmenném prostoru, ve kterém je tento příznak dovolen), takže je indexována roboty, přestože by normálně nebyla.",
-       "post-expand-template-inclusion-category-desc": "Po rozbalení všech šablon je stránka větší než <code>$wgMaxArticleSize</code>, takže některé šablony rozbaleny nebyly.",
-       "post-expand-template-argument-category-desc": "Po rozbalení argumentu šablony (něco v trojitých závorkách, např. <code>{{{Foo}}})</code> je stránka větší než <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Na stránce je použito příliš mnoho náročných funkcí syntaktického analyzátoru (jako <code>#ifexist</code>). Vizte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Kategorie přidaná pokud stránka obsahuje nefunkční odkaz na soubor (odkaz pro vložení souboru, který neexistuje).",
-       "hidden-category-category-desc": "Toto je kategorie, která obsahuje <code><nowiki>__HIDDENCAT__</nowiki></code>, což způsobuje, že se na stránkách implicitně nezobrazuje v rámečku odkazů na kategorie.",
+       "post-expand-template-inclusion-category-desc": "Stránka je po rozbalení všech šablon větší než <code>$wgMaxArticleSize</code>, takže některé šablony rozbaleny nebyly.",
+       "post-expand-template-argument-category-desc": "Stránka je po rozbalení argumentu šablony (něco v trojitých závorkách, např. <code>{{{Foo}}})</code> větší než <code>$wgMaxArticleSize</code>.",
+       "expensive-parserfunction-category-desc": "Stránka používá příliš mnoho náročných funkcí syntaktického analyzátoru (jako <code>#ifexist</code>). Vizte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "Stránka obsahuje nefunkční odkaz na soubor (odkaz pro vložení souboru, který neexistuje).",
+       "hidden-category-category-desc": "Kategorie ve svém textu obsahuje <code><nowiki>__HIDDENCAT__</nowiki></code>, což způsobuje, že se na stránkách implicitně nezobrazuje v rámečku odkazů na kategorie.",
        "trackingcategories-nodesc": "Popis není k dispozici.",
        "trackingcategories-disabled": "Kategorie je vypnuta",
        "mailnologin": "Bez odesílací adresy",
        "mywatchlist": "Sledované stránky",
        "watchlistfor2": "{{GENDER:$1|Uživatele|Uživatelky|Uživatele}} $1 $2",
        "nowatchlist": "Na svém seznamu sledovaných stránek nemáte žádné položky.",
-       "watchlistanontext": "Pro prohlížení či úpravu seznamu sledovaných stránek se musíte $1.",
+       "watchlistanontext": "Pro prohlížení či úpravu seznamu sledovaných stránek se musíte přihlásit.",
        "watchnologin": "Nejste přihlášen(a)",
        "addwatch": "Přidat do sledovaných stránek",
        "addedwatchtext": "Stránka „[[:$1]]“ byla přidána mezi stránky, které sledujete.\nVe [[Special:Watchlist|sledovaných stránkách]] se tak budou objevovat budoucí změny této stránky a přidružené diskuse.",
        "watchlist-details": "Na vašem seznamu sledovaných stránek {{PLURAL:$1|je $1 stránka|jsou $1 stránky|je $1 stránek}}, nepočítaje v to diskusní stránky.",
        "wlheader-enotif": "Upozorňování e-mailem je zapnuto.",
        "wlheader-showupdated": "Stránky, které se změnily od vaší poslední návštěvy, jsou zobrazeny '''tučně'''.",
-       "wlnote2": "Níže jsou změny za {{PLURAL:$1|poslední hodinu|poslední <strong>$1</strong> hodiny|posledních <strong>$1</strong> hodin}} do $3, $2.",
+       "wlnote": "Níže {{PLURAL:$1|je poslední změna|jsou poslední <strong>$1</strong> změny|je posledních <strong>$1</strong> změn}} za {{PLURAL:$2|poslední hodinu|poslední <strong>$2</strong> hodiny|posledních <strong>$2</strong> hodin}} do $4, $3.",
        "wlshowlast": "Ukázat posledních $1 hodin $2 dnů $3",
        "watchlist-options": "Možnosti sledovaných stránek",
        "watching": "Přidávám na seznam sledovaných stránek…",
        "exbeforeblank": "obsah před vyprázdněním byl: „$1“",
        "delete-confirm": "Smazání stránky „$1“",
        "delete-legend": "Smazat",
-       "historywarning": "'''Varování:''' Stránka, kterou chcete smazat, má historii se zhruba $1 {{PLURAL:$1|revizí|revizemi}}:",
+       "historywarning": "<strong>Varování:</strong> Stránka, kterou se chystáte smazat, má historii s $1 {{PLURAL:$1|revizí|revizemi}}:",
        "confirmdeletetext": "Chystáte se smazat stránku s celou její historií. Prosím potvrďte, že to opravdu chcete učinit, že si uvědomujete důsledky a že je to v souladu s [[{{MediaWiki:Policy-url}}|pravidly]].",
        "actioncomplete": "Provedeno",
        "actionfailed": "Operace se nezdařila",
        "delete-edit-reasonlist": "Editovat důvody smazání",
        "delete-toobig": "Tato stránka má velkou historii editací, přes $1 {{PLURAL:$1|verzi|verze|verzí}}. Mazání takových stránek je omezeno, aby se předešlo nechtěnému narušení {{grammar:2sg|{{SITENAME}}}}.",
        "delete-warning-toobig": "Tato stránka má velkou historii editací, přes $1 {{PLURAL:$1|verzi|verze|verzí}}. Mazání takových stránek může narušit databázové operace {{grammar:2sg|{{SITENAME}}}}; postupujte opatrně.",
+       "deleteprotected": "Tuto stránku nemůžete smazat, protože je zamčena.",
        "deleting-backlinks-warning": "'''Upozornění:''' Stránka, kterou se chystáte smazat, je [[Special:WhatLinksHere/{{FULLPAGENAME}}|na jiných stránkách]] odkazována nebo je do nich vložena.",
        "rollback": "Vrátit zpět editace",
        "rollback_short": "Vrátit zpět",
        "autoblockid": "Autoblok #$1",
        "block": "Zablokovat uživatele",
        "unblock": "Odblokovat uživatele",
-       "blockip": "Zablokovat uživatele",
+       "blockip": "Zablokovat {{GENDER:$1|uživatele|uživatelku}}",
        "blockip-legend": "Zablokovat uživatele",
        "blockiptext": "Tento formulář slouží k zablokování editací z konkrétní IP adresy nebo uživatelského jména.\nToto by mělo být používáno jen v souladu s [[{{MediaWiki:Policy-url}}|pravidly]].\nUdejte přesný důvod níže (například ocitujte, které stránky byly poškozeny).",
        "ipaddressorusername": "IP adresa nebo uživatelské jméno:",
        "ipb-unblock-addr": "Odblokovat {{GENDER:$1|uživatele|uživatelku|uživatele nebo IP adresu}} $1",
        "ipb-unblock": "Odblokovat uživatele nebo IP adresu",
        "ipb-blocklist": "Zobrazit probíhající bloky",
-       "ipb-blocklist-contribs": "Příspěvky uživatele $1",
+       "ipb-blocklist-contribs": "Příspěvky {{GENDER:$1|uživatele|uživatelky}} $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",
        "unblocked": "{{GENDER:$1|||Uživatel}} [[User:$1|$1]] {{GENDER:$1|byl odblokován|byla odblokována|byl odblokován}}.",
        "unblocked-range": "Rozsah $1 byl odblokován.",
        "unblocked-id": "Blok $1 byl zrušen.",
+       "unblocked-ip": "Adresa [[Special:Contributions/$1|$1]] byla odblokována.",
        "blocklist": "Zablokovaní uživatelé",
        "ipblocklist": "Zablokovaní uživatelé",
        "ipblocklist-legend": "Hledat zablokovaného uživatele",
        "import": "Import stránek",
        "importinterwiki": "Import mezi wiki",
        "import-interwiki-text": "Pro import zvolte zdrojovou wiki a název stránky. Data revizí a jména autorů budou zachována. Všechny importy se zaznamenávají do [[Special:Log/import|knihy importů]].",
-       "import-interwiki-source": "Zdrojová wiki/stránka:",
+       "import-interwiki-sourcewiki": "Zdrojová wiki:",
+       "import-interwiki-sourcepage": "Zdrojová stránka:",
        "import-interwiki-history": "Zkopírovat všechny historické verze této stránky",
        "import-interwiki-templates": "Zahrnout všechny šablony",
        "import-interwiki-submit": "Importovat",
        "import-invalid-interwiki": "Ze zadané wiki nelze importovat.",
        "import-error-edit": "Stránka „$1“ se nenaimportovala, protože nemáte oprávnění ji editovat.",
        "import-error-create": "Stránka „$1“ se nenaimportovala, protože nemáte oprávnění ji založit.",
-       "import-error-interwiki": "Stránka „$1“ se neimportuje, protože její název je vyhrazen pro externí odkazy (interwiki).",
-       "import-error-special": "Stránka „$1“ se neimportuje, protože patří do speciálního jmenného prostoru, do kterého stránky nepatří.",
-       "import-error-invalid": "Stránka „$1“ se neimportuje, protože její název je neplatný.",
+       "import-error-interwiki": "Stránka „$1“ se nenaimportovala, protože její název je vyhrazen pro externí odkazy (interwiki).",
+       "import-error-special": "Stránka „$1“ se nenaimportovala, protože patří do speciálního jmenného prostoru, ve kterém stránky být nemohou.",
+       "import-error-invalid": "Stránka „$1“ se nenaimportovala, protože název, do kterého by se naimportovala, je na této wiki nepoužitelný.",
        "import-error-unserialize": "Nepodařilo se deserializovat revizi $2 stránky „$1“. Revize měla používat model obsahu $3 serializovaný jako $4.",
        "import-error-bad-location": "Revizi $2 používající obsahový model $3 nelze uložit na \"$1\" na této wiki, neboť tento model není na této stránce podporován.",
        "import-options-wrong": "{{PLURAL:$2|Chybná volba|Chybné volby}}: <nowiki>$1</nowiki>",
        "importlogpage": "Kniha importů",
        "importlogpagetext": "Na této stránce se zobrazují správcovské importy stránek včetně historie editací z jiných wiki.",
        "import-logentry-upload": "naimportoval [[$1]] načtením souboru",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revizi|revize|revizí}}",
+       "import-logentry-upload-detail": "{{PLURAL:$1|naimportována $1 revize|naimportovány $1 revize|naimportováno $1 revizí}}",
        "import-logentry-interwiki": "přenesl $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revizi|revize|revizí}} z $2",
+       "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-title": "Spouštějí se testy v $1",
        "javascripttest-pagetext-noframework": "Tato stránka je vyhrazena pro spouštění testů JavaScriptu.",
        "autosumm-replace": "Obsah stránky nahrazen textem „$1“",
        "autoredircomment": "Přesměrování na [[$1]]",
        "autosumm-new": "Založena nová stránka s textem „$1“",
+       "autosumm-newblank": "Založena prázdná stránka",
        "size-kilobytes": "$1 KB",
        "lag-warn-normal": "Změny za {{PLURAL:$1|poslední sekundu|poslední $1 sekundy|posledních $1 sekund}} nemusí být v tomto seznamu zobrazeny.",
        "lag-warn-high": "Protože je databázový server právě mimořádně vytížen, nemusí být změny za {{PLURAL:$1|poslední sekundu|poslední $1 sekundy|posledních $1 sekund}} v tomto seznamu zobrazeny.",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|diskuse]])",
        "unknown_extension_tag": "Neznámá značka rozšíření: „$1“",
        "duplicate-defaultsort": "Upozornění: Implicitní klíč řazení (DEFAULTSORTKEY) „$2“ přepisuje dříve nastavenou hodnotu „$1“.",
+       "duplicate-displaytitle": "<strong>Upozornění:</strong> Předchozí zobrazovaný název „$1“ je nahrazen zobrazovaným názvem „$2“.",
        "version": "Verze",
        "version-extensions": "Nainstalovaná rozšíření",
        "version-skins": "Nainstalované vzhledy",
        "logentry-rights-rights": "$1 {{GENDER:$2|změnil|změnila}} členství $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",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|načetl|načetla}} novou verzi $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|načetl|načetla}} $3",
        "rightsnone": "(žádné)",
        "feedback-bugornote": "Pokud dokážete podrobně popsat technický problém, můžete [$1 nahlásit chybu].\nJinak můžete využít jednoduchý formulář níže. Váš komentář bude přidán na stránku „[$3 $2]“ spolu s vaším uživatelským jménem a informací o tom, jaký prohlížeč používáte.",
        "feedback-subject": "Předmět:",
        "action-pagelang": "měnit jazyk stránky",
        "log-name-pagelang": "Kniha změn jazyků",
        "log-description-pagelang": "Toto je protokol změn jazyků stránek.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|změnil|změnila}} jazyk stránky $3 z $4 na $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|změnil|změnila}} jazyk stránky $3 z $4 na $5.",
+       "default-skin-not-found": "Jejda! Výchozí vzhled vaší wiki, definovaný ve <code dir=\"ltr\">$wgDefaultSkin</code> jako <code>$1</code>, není dostupný.\n\nVaše instalace zřejmě obsahuje následující vzhledy. Informace o tom, jak je povolit a vybrat výchozí, najdete na stránce [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Skin_configuration/cs Manual:Skin configuration].\n\n$2\n\n; Pokud jste právě nainstalovali MediaWiki:\n: Zřejmě jste instalovali z gitu nebo nějakým jiným způsobem přímo ze zdrojového kódu. Tak to má fungovat. Zkuste nainstalovat některé vzhledy ze [https://www.mediawiki.org/wiki/Category:All_skins seznamu vzhledů na mediawiki.org] buď:\n:* Můžete si stáhnout [https://www.mediawiki.org/wiki/Download/cs instalace v tarballu], která zahrnuje několik vzhledů a rozšíření, a vykopírovat si z ní adresář <code dir=\"ltr\">skins/</code>, nebo\n:* Nebo si můžete gitem naklonovat jeden z repozitářů <code>mediawiki/skins/*</code> do adresáře <code>skins/</code> ve vaší instalaci MediaWiki.\n: Pokud jste vývojářem MediaWiki, nemělo by to nijak narušit váš gitový repozitář.\n\n; Pokud jste právě aktualizovali MediaWiki:\n: MediaWiki 1.24 a novější již automaticky nepovolují nainstalované vzhledy (vizte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Skin_autodiscovery/cs Manual:Skin autodiscovery]). Pro povolení všech právě nainstalovaných vzhledů vlepte následující řádky do <code>LocalSettings.php</code>:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Pokud jste právě upravili <code>LocalSettings.php</code>:\n: Překontrolujte případné překlepy v názvech vzhledů.",
+       "default-skin-not-found-no-skins": "Jejda! Výchozí vzhled vaší wiki, definovaný ve <code dir=\"ltr\">$wgDefaultSkin</code> jako <code>$1</code>, není dostupný.\n\nNemáte nainstalovány žádné vzhledy.\n\n; Pokud jste právě nainstalovali nebo aktualizovali MediaWiki:\n: Zřejmě jste instalovali z gitu nebo nějakým jiným způsobem přímo ze zdrojového kódu. Tak to má fungovat. MediaWiki 1.24 a novější již v hlavním repozitáři neobsahují žádné vzhledy. Zkuste nainstalovat některé vzhledy ze [https://www.mediawiki.org/wiki/Category:All_skins seznamu vzhledů na mediawiki.org] buď:\n:* Můžete si stáhnout [https://www.mediawiki.org/wiki/Download/cs instalace v tarballu], která zahrnuje několik vzhledů a rozšíření, a vykopírovat si z ní adresář <code>skins/</code>, nebo\n:* Nebo si můžete gitem naklonovat jeden z repozitářů <code>mediawiki/skins/*</code> do adresáře <code dir=\"ltr\">skins/</code> ve vaší instalaci MediaWiki.\n: Pokud jste vývojářem MediaWiki, nemělo by to nijak narušit váš gitový repozitář. Informace o tom, jak povolit vzhledy a vybrat výchozí, najdete na stránce [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Skin_configuration/cs Manual:Skin configuration].",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (povolený)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''zakázaný''')"
 }
index 6a4cf9c..7049f9a 100644 (file)
        "talkpagelinktext": "Diskùsëjô",
        "specialpage": "Specjalnô starna",
        "personaltools": "Priwatné przërëchtënczi",
-       "postcomment": "Nowi dzél",
        "articlepage": "Starna artikla",
        "talk": "Diskùsëjô",
        "views": "Pòdzérków",
        "yourdomainname": "Twòjô domena",
        "login": "Wlogùjë mie",
        "nav-login-createaccount": "Logòwanié",
-       "loginprompt": "Brëkùjesz miec ''cookies'' (kùszczi) włączoné bë sã wlogòwac do {{SITENAME}}.",
        "userlogin": "Logòwanié",
        "userloginnocreate": "Wlogùjë mie",
        "logout": "Wëlogùjë mie",
        "badfilename": "Miono òbrôzka zmienioné na \"$1\".",
        "uploadwarning": "Òstrzega ò wladënkù",
        "savefile": "Zapiszë lôpk",
-       "uploadedimage": "wladënk: \"$1\"",
        "uploaddisabled": "Przeprôszómë! Mòżlëwòta wladënkù lopków na nen serwer òsta wëłączonô.",
        "upload-success-subj": "Wladënk darzëł sã",
        "listfiles": "Lësta òbrôzków",
        "notanarticle": "To nie je artikel",
        "watchlist-details": "Ùzérôsz {{PLURAL:$1|$1 artikel|$1 artikle/-ów}}, nie rechùjąc diskùsëjów.",
        "wlheader-showupdated": "Artiklë jakczé òsta zmienioné òd Twòji slédny wizytë są wëapratnioné '''pògrëbieniém'''",
+       "wlnote": "Niżi môsz wëskrzënioné {{PLURAL:$1|slédną zmianã|'''$1''' slédnëch zmianów}} zrobioné òb {{PLURAL:$2|gòdzënã|'''$2''' gòdzënë/gòdzënów}}.",
        "wlshowlast": "Wëskrzëni zjinaczi z $1 gòdzënów $2 dni $3",
        "watchlist-options": "Òptacëje ùzérónych",
        "watching": "Ùzéróm...",
index c80e34b..f5e4590 100644 (file)
        "talkpagelinktext": "бєсѣда",
        "specialpage": "нарочьна страница",
        "personaltools": "моꙗ орѫдиꙗ",
-       "postcomment": "нова чѧсть",
        "talk": "бєсѣда",
        "toolbox": "орѫдиꙗ",
        "otherlanguages": "дроугꙑ ѩꙁꙑкꙑ",
        "filedesc": "опьсаниѥ",
        "fileuploadsummary": "опьсаниѥ:",
        "savefile": "дѣла съхранѥниѥ",
-       "uploadedimage": "⁖ [[$1]] ⁖ положєнъ ѥстъ",
-       "overwroteimage": "новъ обраꙁъ ⁖ [[$1]] ⁖ положєнъ ѥстъ",
        "upload-source": "источьно дѣло",
        "sourcefilename": "источьна дѣла имꙗ :",
        "watchthisupload": "си дѣла блюдєниѥ",
index 9c6f083..7ac4c5d 100644 (file)
        "talkpagelinktext": "Сӳтсе явни",
        "specialpage": "Ятарлă страницă",
        "personaltools": "Ман хатĕрсем",
-       "postcomment": "Хуравла",
        "articlepage": "Статьяна пăх",
        "talk": "Сӳтсе явни",
        "views": "Пурĕ пăхнă",
        "yourdomainname": "Сирĕн домен",
        "login": "Сайта кĕр",
        "nav-login-createaccount": "Сайта кĕр / регистрацилен",
-       "loginprompt": "Сайта кĕрес тесен сирĕн «cookies»-па усă курма ирĕк памалла.",
        "userlogin": "Сайта кĕр",
        "logout": "Сайтран тухас",
        "userlogout": "Сайтран тух",
        "largefileserver": "Файл пысăкăшĕ юрăхлинчен пысăкрах (пĕчĕклетĕр).",
        "uploadwarning": "Асăрхаттару",
        "savefile": "Файла çырса хур",
-       "uploadedimage": "«[[$1]]» кĕртрĕмĕр",
        "uploaddisabled": "Каçарăр та сайта халĕ нимĕн те кĕртме юрамаст.",
        "uploaddisabledtext": "Ку вики-сайтра файлсене кĕртме чарнă.",
        "uploadvirus": "Файл ăшĕнче вирус пур! $1 пăхăр.",
index e66b267..3a0a6ab 100644 (file)
        "talkpagelinktext": "Sgwrs",
        "specialpage": "Tudalen Arbennig",
        "personaltools": "Offer personol",
-       "postcomment": "Adran newydd",
        "articlepage": "Dangos tudalen bwnc",
        "talk": "Sgwrs",
        "views": "Golygon",
        "externaldberror": "Naill ai: cafwyd gwall dilysu allanol ar databas neu: ar y llaw arall efallai nad oes hawl gennych chi i ddiwygio'ch cyfrif allanol.",
        "login": "Mewngofnodi",
        "nav-login-createaccount": "Mewngofnodi",
-       "loginprompt": "Mae'n rhaid galluogi cwcis er mwyn mewngofnodi i {{SITENAME}}.",
        "userlogin": "Mewngofnodi / creu cyfrif",
        "userloginnocreate": "Mewngofnodi",
        "logout": "Allgofnoder",
        "searchprofile-advanced-tooltip": "Chwilio drwy parthau dewisol",
        "search-result-size": "$1 ({{PLURAL:$2|dim geiriau|$2 gair|$2 air|$2 gair|$2 gair|$2 gair|}})",
        "search-result-category-size": "{{PLURAL:$1|$1 aelod}} ({{PLURAL:$2|$2 is-gategori}}, {{PLURAL:$3|$3 ffeil}})",
-       "search-result-score": "Perthnasedd: $1%",
        "search-redirect": "(ailgyfeiriad $1)",
        "search-section": "(adran $1)",
        "search-file-match": "(yn cyfateb i gynnwys y ffeil)",
        "uploadwarning": "Rhybudd uwchlwytho",
        "uploadwarning-text": "Newidiwch ddisgrifiad y ffeil isod ac yna ceisiwch ei huwchlwytho eto, os gwelwch yn dda.",
        "savefile": "Cadw'r ffeil",
-       "uploadedimage": "wedi llwytho \"[[$1]]\"",
-       "overwroteimage": "wedi uwchlwytho fersiwn newydd o \"[[$1]]\"",
        "uploaddisabled": "Ymddiheurwn; mae uwchlwytho wedi'i analluogi.",
        "copyuploaddisabled": "Analluogwyd uwchlwytho gan URL.",
        "uploaddisabledtext": "Analluogwyd uwchlwytho ffeiliau ar y wefan hon.",
        "watchlist-details": "{{PLURAL:$1|Nid oes dim tudalennau|Mae $1 dudalen|Mae $1 dudalen|Mae $1 tudalen|Mae $1 thudalen|Mae $1 o dudalennau}} ar eich rhestr wylio, heb gynnwys tudalennau sgwrs ar wahan.",
        "wlheader-enotif": "Galluogwyd hysbysiadau trwy e-bost.",
        "wlheader-showupdated": "Mae tudalennau sydd wedi newid ers i chi eu gweld ddiwethaf wedi'u '''hamlygu'''.",
-       "wlnote2": "Isod, fe welwch y newidiadau yn ystod {{PLURAL:$1|yr awr|yr awr|y ddwyawr ddiwethaf|teirawr diwethaf|<strong>$1</strong> awr diwethaf}}, hyd at $2, $3.",
+       "wlnote": "{{PLURAL:$1|Ni fu unrhyw newid|Isod mae'r '''$1''' newid diweddaraf|Isod mae'r '''$1''' newid diweddaraf|Isod mae'r '''$1''' newid diweddaraf|Isod mae'r '''$1''' newid diweddaraf|Isod mae'r '''$1''' newid diweddaraf}} yn ystod {{PLURAL:$2||yr awr|y ddwyawr|y teirawr|y \"$2\" awr|y(r) \"$2\" awr}} ddiwethaf, fel ag yr oedd am $4, $3.",
        "wlshowlast": "Dangoser newidiadau'r $1 awr ddiwethaf neu'r $2 {{PLURAL:$2|diwrnod|diwrnod|ddiwrnod|diwrnod|diwrnod|diwrnod}} diwethaf neu'r $3 newidiadau.",
        "watchlist-options": "Dewisiadau ar gyfer y rhestr wylio",
        "watching": "Wrthi'n ychwanegu...",
index 797b8b6..7b34475 100644 (file)
@@ -46,7 +46,8 @@
                        "Søren Løvborg",
                        "Tjernobyl",
                        "Urhixidur",
-                       "아라"
+                       "아라",
+                       "Thomsen"
                ]
        },
        "tog-underline": "Understreg henvisninger:",
        "talkpagelinktext": "diskussion",
        "specialpage": "Speciel side",
        "personaltools": "Personlige værktøjer",
-       "postcomment": "Nyt afsnit",
        "articlepage": "Se artiklen",
        "talk": "Diskussion",
        "views": "Visninger",
        "hidetoc": "skjul",
        "collapsible-collapse": "Fold sammen",
        "collapsible-expand": "Fold ud",
+       "confirmable-confirm": "Er {{GENDER:$1|du}} sikker?",
+       "confirmable-yes": "Ja",
+       "confirmable-no": "Nej",
        "thisisdeleted": "Se eller gendan $1?",
        "viewdeleted": "Vis $1?",
        "restorelink": "{{PLURAL:$1|en slettet ændring|$1 slettede ændringer}}",
        "externaldberror": "Der er opstået en fejl i en ekstern adgangsdatabase, eller du har ikke rettigheder til at opdatere denne.",
        "login": "Log på",
        "nav-login-createaccount": "Opret en konto eller log på",
-       "loginprompt": "Du skal have cookies slået til for at kunne logge på {{SITENAME}}.",
        "userlogin": "Opret en konto eller log på",
        "userloginnocreate": "Log på",
        "logout": "Log af",
        "userlogin-resetlink": "Har du glemt dine login oplysninger?",
        "userlogin-resetpassword-link": "Glemt din adgangskode?",
        "userlogin-helplink2": "Hjælp med at logge på",
-       "userlogin-loggedin": "Du er allerede logget på som {{GENDER:$1|$1}}.\nBrug formularen nedenfor til at logge på som en anden bruger.",
-       "userlogin-createanother": "Opret en anden konto",
        "createacct-emailrequired": "E-mailadresse",
        "createacct-emailoptional": "E-mailadresse (valgfri)",
        "createacct-email-ph": "Indtast din e-mailadresse",
        "preview": "Forhåndsvisning",
        "showpreview": "Forhåndsvisning",
        "showdiff": "Vis ændringer",
+       "blankarticle": "<strong>Advarsel:</strong> Siden du opretter er tom.\nHvis du klikker på \"{{int:savearticle}}\" igen, vil siden blive oprettet uden indhold.",
        "anoneditwarning": "'''Advarsel:''' Du er ikke logget på. I stedet for brugernavn vises din IP-adresse i versionshistorikken.",
        "anonpreviewwarning": "''Du er ikke logget på. Hvis du gemmer, registreres din IP-adresse i versionshistorikken.''",
        "missingsummary": "'''Bemærk:''' Du har ikke angivet en redigeringsbeskrivelse. Hvis du igen trykker på \"{{int:savearticle}}\", gemmes ændringerne uden en beskrivelse.",
        "edit-gone-missing": "Kunne ikke opdatere siden.\nDen ser du til at være slettet.",
        "edit-conflict": "Redigeringskonflikt.",
        "edit-no-change": "Din ændring ignoreredes, fordi der ikke var ændring af teksten.",
+       "postedit-confirmation-created": "Siden er blevet oprettet.",
+       "postedit-confirmation-restored": "Siden er blevet genoprettet.",
        "postedit-confirmation-saved": "Din redigering er gemt.",
        "edit-already-exists": "En ny side kunne ikke oprettes, fordi den allerede findes.",
        "defaultmessagetext": "Standardtekst",
        "parser-template-recursion-depth-warning": "En skabelon er rekursivt inkluderet for mange gange ($1)",
        "language-converter-depth-warning": "Dybdegrænse for sprogkonvertering overskredet ($1)",
        "node-count-exceeded-category": "Sider hvor antal noder er overskredet",
-       "node-count-exceeded-warning": "Sider der har overskredet antallet af noder",
+       "node-count-exceeded-category-desc": "Siden overstiger det maksimale antal af noder.",
+       "node-count-exceeded-warning": "Siden har overskredet antallet af noder",
        "expansion-depth-exceeded-category": "Sider, der overskrider ekspansionsdybden",
        "expansion-depth-exceeded-warning": "Siden overskred ekspansionsdybden",
        "parser-unstrip-loop-warning": "Unstrip-loop opdaget",
        "currentrev": "Nuværende version",
        "currentrev-asof": "Nuværende version fra $1",
        "revisionasof": "Versionen fra $1",
-       "revision-info": "Version fra $1 af $2",
+       "revision-info": "Version fra $1 af $2 {{GENDER:$6|$2}}$7",
        "previousrevision": "←Ældre version",
        "nextrevision": "Nyere version→",
        "currentrevisionlink": "se nuværende version",
        "searchprofile-advanced-tooltip": "Søg i bestemte navnerum",
        "search-result-size": "$1 ({{PLURAL:$2|et ord|$2 ord}})",
        "search-result-category-size": "{{PLURAL:$1|1 medlem|$1 medlemmer}} ({{PLURAL:$2|1 underkategori|$2 underkategorier}}, {{PLURAL:$3|1 fil|$3 filer}})",
-       "search-result-score": "Relevans: $1%",
        "search-redirect": "(omdirigering $1)",
        "search-section": "(afsnit $1)",
        "search-suggest": "Mente du: $1",
        "preferences": "Indstillinger",
        "mypreferences": "Indstillinger",
        "prefs-edits": "Antal redigeringer:",
-       "prefsnologintext2": "Du skal $1 for at ændre brugerindstillinger.",
+       "prefsnologintext2": "Du skal logge på for at ændre dine brugerindstillinger.",
        "prefs-skin": "Udseende",
        "skin-preview": "Forhåndsvisning",
        "datedefault": "Standard",
        "right-deletedtext": "Vise slettet tekst og ændringer i slettede revisioner",
        "right-browsearchive": "Søge i slettede sider",
        "right-undelete": "Gendanne en side",
-       "right-suppressrevision": "Skjule og synliggøre sletninger for administratorer",
+       "right-suppressrevision": "Se, skjule og vise specifikke versioner af sider fra enhver bruger",
+       "right-viewsuppressed": "Se versioner skjult fra enhver bruger",
        "right-suppressionlog": "Se skjulte loglister",
        "right-block": "Blokere brugere",
        "right-blockemail": "Blokere en brugers mulighed for at sende mail",
        "action-createpage": "oprette sider",
        "action-createtalk": "oprette diskussionssider",
        "action-createaccount": "Oprette denne brugerkonto",
+       "action-history": "se historik for denne side",
        "action-minoredit": "markere denne redigering som mindre",
        "action-move": "flytte denne side",
        "action-move-subpages": "flytte denne side og dens undersider",
        "recentchanges-legend-heading": "'''Forklaring:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (se også [[Special:NewPages|listen over nye sider]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Nedenfor er op til '''$1''' ændringer siden '''$2''' vist.",
+       "rcnotefrom": "Nedenfor er op til '''$1''' {{PLURAL:$5|ændring|ændringer}} siden '''$2''' vist.",
        "rclistfrom": "Vis nye ændringer startende fra $3 $2",
        "rcshowhideminor": "$1 mindre ændringer",
        "rcshowhideminor-show": "Vis",
        "largefileserver": "Filen er større end den på serveren indstillede maksimale størrelse.",
        "emptyfile": "Filen du lagde op lader til at være tom. Det kan skyldes en slåfejl i filnavnet. Kontroller om du virkelig ønsker at lægge denne fil op.",
        "windows-nonascii-filename": "Denne wiki understøtter ikke filnavne, der indeholder specialtegn.",
-       "fileexists": "En fil med det navn findes allerede, tjek venligst <strong>[[:$1]]</strong> om du er sikker på du vil ændre den.\n[[$1|thumb]]",
+       "fileexists": "En fil med det navn findes allerede, tjek venligst <strong>[[:$1]]</strong> hvis du ikke er sikker på om du vil ændre den.\n[[$1|thumb]]",
        "filepageexists": "Siden med beskrivelse af denne fil er allerede oprettet på <strong>[[:$1]]</strong>, men der eksisterer ikke en fil med dette navn.\nDen beskrivelse du kan angive nedenfor vil derfor ikke blive brugt.\nFor at få din beskrivelse vist, skal du selv redigere beskrivelsessiden.\n[[$1|thumb]]",
-       "fileexists-extension": "En fil med lignende navn findes allerede: [[$2|thumb]]\n* Navnet på den valgte fil: <strong>[[:$1]]</strong>\n* Navnet på den eksisterende fil: <strong>[[:$2]]</strong>\nVælg venligst et andet navn.",
+       "fileexists-extension": "En fil med lignende navn findes allerede: [[$2|thumb]]\n* Navnet på den valgte fil: <strong>[[:$1]]</strong>\n* Navnet på den eksisterende fil: <strong>[[:$2]]</strong>\nVil du måske bruge et mere karakteristisk navn?",
        "fileexists-thumbnail-yes": "Det ser ud som om filen indeholder et billede i reduceret størrelse ''(thumbnail)''. [[$1|thumb]]\nKontroller filen <strong>[[:$1]]</strong>.\nHvis det er billedet i original størrelse, er det ikke nødvendigt at uploade et separat forhåndsvisningsbillede.",
        "file-thumbnail-no": "Filnavnet begynder med <strong>$1</strong>.\nDet tyder på et billede i reduceret format ''(thumbnail)''.\nHvis du har billedet i fuld størrelse, så brug det i stedet. Ellers bedes du venligst ændre filnavnet.",
        "fileexists-forbidden": "En fil med dette navn findes allerede, og den kan ikke overskrives.\nHvis du fortsat vil lægge filen op, bedes du gå tilbage og bruge et nyt navn.\n[[File:$1|thumb|center|$1]]",
        "uploadwarning": "Advarsel",
        "uploadwarning-text": "Vær venlig at ændre filbeskrivelsen nedenfor og prøv igen.",
        "savefile": "Gem fil",
-       "uploadedimage": "lagde \"[[$1]]\" op",
-       "overwroteimage": "lagde en ny version af \"[[$1]]\" op",
        "uploaddisabled": "Desværre er funktionen til at lægge filer op afbrudt på denne server.",
        "copyuploaddisabled": "Upload via URL er slået fra.",
        "uploaddisabledtext": "Oplægning af filer er deaktiveret.",
        "license": "Licens",
        "license-header": "Licensering",
        "nolicense": "intet forvalg",
+       "licenses-edit": "Rediger licensvalg",
        "license-nopreview": "(forhåndsvisning ikke mulig)",
-       "upload_source_url": " (gyldig, offentligt tillgængelig URL)",
-       "upload_source_file": " (en fil på din computer)",
+       "upload_source_url": "(din valgte fil fra en gyldig, offentligt tilgængelige URL)",
+       "upload_source_file": "(din valgte fil fra din computer)",
+       "listfiles-delete": "slet",
        "listfiles-summary": "Denne specialside viser alle oplagte filer.",
        "listfiles_search_for": "Søge efter fil:",
        "imgfile": "Fil",
        "randomincategory": "Tilfældig side i kategori",
        "randomincategory-invalidcategory": "\"$1\" er ikke et gyldigt kategorinavn.",
        "randomincategory-nopages": "Der er ingen sider i [[:Category:$1]].",
-       "randomincategory-selectcategory": "Få tilfældig side fra kategori: $1 $2.",
-       "randomincategory-selectcategory-submit": "Gå til",
+       "randomincategory-category": "Kategori:",
        "randomredirect": "Tilfældige henvisninger",
        "randomredirect-nopages": "Der er ingen omdirigeringer i navnerummet $1.",
        "statistics": "Statistik",
        "pageswithprop-prophidden-binary": "binær værdi for egenskaben skjult ($1)",
        "doubleredirects": "Dobbelte omdirigeringer",
        "doubleredirectstext": "Dette er en liste over sider som omdirigerer til andre omdirigeringssider.\nHver linje indeholder henvisninger til den første og den anden omdirigering, såvel som til målet for den anden omdirigering som sædvanligvis er den \"rigtige\" målside som den første omdirigering burde henvise til.\n<del>Overstregede</del> poster er rettede.",
-       "double-redirect-fixed-move": "[[$1]] blev flyttet og er nu en omdirigering til [[$2]]",
-       "double-redirect-fixed-maintenance": "Rettelse af dobbelt omdirigering fra [[$1]] til [[$2]].",
+       "double-redirect-fixed-move": "[[$1]] blev flyttet.\nDen blev automatisk opdateret og er nu en omdirigering til [[$2]].",
+       "double-redirect-fixed-maintenance": "Automatisk rettelse af dobbelt omdirigering fra [[$1]] til [[$2]] som en del af en vedligeholdelsesopgave.",
        "double-redirect-fixer": "Omdirigerings-retter",
        "brokenredirects": "Defekte omdirigeringer",
        "brokenredirectstext": "Følgende omdirigeringer peger på en side der ikke eksisterer:",
        "listgrouprights-removegroup-self": "Kan fjerne {{PLURAL:$2|gruppe|grupper}} fra egen konto: $1",
        "listgrouprights-addgroup-self-all": "Kan tilføje alle grupper til egen konto",
        "listgrouprights-removegroup-self-all": "Kan fjerne alle grupper fra egen konto",
+       "listgrouprights-namespaceprotection-header": "Navnerumsbegrænsninger",
+       "listgrouprights-namespaceprotection-namespace": "Navnerum",
+       "listgrouprights-namespaceprotection-restrictedto": "Rettighed(er) der giver brugeren mulighed for at redigere",
+       "trackingcategories-desc": "Optagelseskriterier for kategori",
+       "noindex-category-desc": "Siden indekseres ikke af robotter, fordi den indeholder det magiske ord <code><nowiki>__NOINDEX__</nowiki></code> og er i et navnerum, hvor dette flag er tilladt.",
+       "index-category-desc": "Siden indeholder <code><nowiki>__INDEX__</nowiki></code> (og er i et navnerum, hvor dette flag er tilladt), og bliver derfor indekseret af robotter, hvor den normalt ikke ville blive det.",
        "mailnologin": "Du er ikke logget på",
        "mailnologintext": "Du skal være [[Special:UserLogin|logget på]] og have en gyldig e-mailadresse sat i dine [[Special:Preferences|indstillinger]] for at sende e-mail til andre brugere.",
        "emailuser": "E-mail til denne bruger",
        "mywatchlist": "Overvågningsliste",
        "watchlistfor2": "For $1 $2",
        "nowatchlist": "Du har ingenting i din overvågningsliste.",
-       "watchlistanontext": "Du skal $1, for at se din overvågningsliste eller ændre indholdet af den.",
+       "watchlistanontext": "Du skal logge på, for at se din overvågningsliste eller ændre indholdet af den.",
        "watchnologin": "Ikke logget på",
        "addwatch": "Tilføj til overvågningsliste",
        "addedwatchtext": "Siden \"[[:$1]]\" er blevet tilføjet til din [[Special:Watchlist|overvågningsliste]].\nFremtidige ændringer af denne side og dens tilknyttede diskussionsside vil blive vist der.",
+       "addedwatchtext-short": "Siden \"$1\" er blevet tilføjet til din overvågningsliste.",
        "removewatch": "Fjern fra overvågningsliste",
        "removedwatchtext": "Siden \"[[:$1]]\" er blevet fjernet fra [[Special:Watchlist||din overvågningsliste]].",
+       "removedwatchtext-short": "Siden \"$1\" er blevet fjernet fra din overvågningsliste.",
        "watch": "Overvåg",
        "watchthispage": "Overvåg side",
        "unwatch": "Fjern overvågning",
        "watchlist-details": "Du har $1 {{PLURAL:$1|side|sider}} på din overvågningsliste (ekskl. diskussionssider).",
        "wlheader-enotif": "E-mail-underretning er slået til.",
        "wlheader-showupdated": "Sider, der er ændret siden dit sidste besøg, er vist med '''fed skrift'''.",
-       "wlnote2": "Nedenfor ses ændringerne i {{PLURAL:$1|den sidste time|de sidste <strong>$1</strong> timer}} op til den $2 kl. $3.",
+       "wlnote": "Nedenfor ses {{PLURAL:$1|den seneste ændring|de seneste <strong>$1</strong> ændringer}} i {{PLURAL:$2|den sidste time|de sidste <strong>$2</strong> timer}} op til den $3 kl. $4.",
        "wlshowlast": "Vis de seneste $1 timer $2 dage $3",
        "watchlist-options": "Indstillinger for overvågningslisten",
        "watching": "Tilføjer overvågning …",
        "exbeforeblank": "indholdet før siden blev tømt var: '$1'",
        "delete-confirm": "Slet \"$1\"",
        "delete-legend": "Slet",
-       "historywarning": "Advarsel: Siden du er ved at slette har en historie med $1 {{PLURAL:$1|revision|revisioner}}:",
+       "historywarning": "<strong>Advarsel:</strong> Siden du er ved at slette har en historie med $1 {{PLURAL:$1|version|versioner}}:",
        "confirmdeletetext": "Du er ved at slette en side sammen med hele dens tilhørende historik.\nBekræft venligst at du virkelig vil gøre dette, at du forstår konsekvenserne, og at du gør det i overensstemmelse med [[{{MediaWiki:Policy-url}}|retningslinjerne]].",
        "actioncomplete": "Gennemført",
        "actionfailed": "Handlingen mislykkedes",
        "delete-edit-reasonlist": "Rediger sletningsårsager",
        "delete-toobig": "Denne side har en stor historik, over {{PLURAL:$1|en version|$1 versioner}}. Sletning af sådanne sider er begrænset, for at forhindre utilsigtet forstyrrelse af {{SITENAME}}.",
        "delete-warning-toobig": "Denne side har en stor historik, over {{PLURAL:$1|en version|$1 versioner}} versioner, slettes den kan det forstyrre driften af {{SITENAME}}, gå forsigtigt frem.",
+       "deleteprotected": "Du kan ikke slette denne side, fordi den er beskyttet.",
        "deleting-backlinks-warning": "'''Advarsel:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Andre sider]] linker til eller inkluderer den side, du er ved at slette.",
        "rollback": "Fjern redigeringer",
        "rollback_short": "Fjern redigering",
        "contributions-title": "Brugerbidrag for $1",
        "mycontris": "Bidrag",
        "contribsub2": "For {{GENDER:$3|$1}} ($2)",
+       "contributions-userdoesnotexist": "Brugerkontoen \"$1\" er ikke registreret.",
        "nocontribs": "Ingen ændringer er fundet som opfylder disse kriterier.",
        "uctop": "(seneste)",
        "month": "Måned:",
        "autoblockid": "Autoblock #$1",
        "block": "Bloker bruger",
        "unblock": "Ophæv blokering af bruger",
-       "blockip": "Bloker bruger",
+       "blockip": "Bloker {{GENDER:$1|bruger}}",
        "blockip-legend": "Bloker bruger",
        "blockiptext": "Brug formularen herunder til at blokere for skriveadgang fra en bestemt IP-adresse eller et brugernavn.\nDette bør kun gøres for at forhindre vandalisme og skal være i overensstemmelse med [[{{MediaWiki:Policy-url}}|retningslinjerne]].\nAngiv en konkret begrundelse herunder (for eksempel med angivelse af sider der har været udsat for vandalisme).",
        "ipaddressorusername": "IP-adresse eller brugernavn",
        "ipb-unblock-addr": "Ophæv blokeringen af \"$1\"",
        "ipb-unblock": "Frigive IP-adresse/bruger",
        "ipb-blocklist": "Vis alle blokeringer som er i kraft",
-       "ipb-blocklist-contribs": "Bidrag fra $1",
+       "ipb-blocklist-contribs": "Bidrag fra {{GENDER:$1|$1}}",
        "unblockip": "Ophæv blokering af bruger",
        "unblockiptext": "Brug formularen herunder for at gendanne skriveadgangen for en tidligere blokeret IP-adresse eller bruger.",
        "ipusubmit": "Ophæv blokeringen",
        "import": "Importer sider",
        "importinterwiki": "Importer sider fra en anden wiki",
        "import-interwiki-text": "Vælg en Wiki og en side til importen.\nDatoen i den pågældende version og forfatterne ændres ikke.\nAlle Transwiki import-aktioner protokolleres i [[Special:Log/import|import-loggen]].",
-       "import-interwiki-source": "Kildewiki/-side:",
        "import-interwiki-history": "Importer alle versioner af denne side",
        "import-interwiki-templates": "Inkluder alle skabeloner",
        "import-interwiki-submit": "Importer",
        "import-upload": "Upload XML-data",
        "import-token-mismatch": "Sessionsdata er mistet. Prøv venligst igen.",
        "import-invalid-interwiki": "Kan ikke importere fra den angivne wiki.",
-       "import-error-edit": "Siden \"$1\" importeres ikke, da du ikke har rettigheden til at redigere den.",
-       "import-error-create": "Siden \"$1\" importeres ikke, da du ikke har rettigheden til at oprette den.",
-       "import-error-interwiki": "Siden \"$1\" importeres ikke, da dens navn er reserveret for eksterne henvisninger (interwiki).",
-       "import-error-special": "Siden \"$1\" importeres ikke, da den tilhører et særligt navnerum, der ikke tillader sider.",
-       "import-error-invalid": "Siden \"$1\" importeres ikke, da dens navn er ugyldigt.",
+       "import-error-edit": "Siden \"$1\" blev ikke importeret, da du ikke har rettighed til at redigere den.",
+       "import-error-create": "Siden \"$1\" blev ikke importeret, da du ikke har rettighed til at oprette den.",
+       "import-error-interwiki": "Siden \"$1\" blev ikke importeret, da dens navn er reserveret for eksterne henvisninger (interwiki).",
+       "import-error-special": "Siden \"$1\" blev ikke importeret, da den tilhører et særligt navnerum, der ikke tillader sider.",
+       "import-error-invalid": "Siden \"$1\" blev ikke importeret, fordi det navn, som den ville være importeret til er ugyldigt på denne wiki.",
        "import-error-unserialize": "Ændring $2 af siden \"$1\" kunne ikke afserialiseres. Ændringen brugte indholdsmodel $3 serialiseret som $4.",
        "import-error-bad-location": "Version $2 der bruger indholdsmodellen $3 kan ikke gemmes på \"$1\" på denne wiki, da denne model ikke understøttes på denne side.",
        "import-options-wrong": "{{PLURAL:$2|Ugyldig indstilling|Ugyldige indstillinger}}: <nowiki>$1</nowiki>",
        "importlogpage": "Importlog",
        "importlogpagetext": "Administrativ import af sider med versionshistorik fra andre Wikis.",
        "import-logentry-upload": "[[$1]] blev importeret",
-       "import-logentry-upload-detail": "{{PLURAL:$1|1 version|$1 versioner}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|version|versioner}} importeret",
        "import-logentry-interwiki": "$1 blev importeret (Transwiki)",
-       "import-logentry-interwiki-detail": "{{PLURAL:$1|1 version|$1 versioner}} af $2 importeret",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|version|versioner}} importeret fra $2",
        "javascripttest": "Test af JavaScript",
        "javascripttest-title": "Kører $1 test",
        "javascripttest-pagetext-noframework": "Denne side er reserveret til at teste JavaScript.",
        "newimages-summary": "Denne specialside viser de senest oplagte filer.",
        "newimages-legend": "Filter",
        "newimages-label": "Filnavn (eller en del af det):",
+       "newimages-showbots": "Vis oplægninger af robotter",
        "noimages": "Ingen filer fundet.",
        "ilsubmit": "Søg",
        "bydate": "efter dato",
        "confirm-watch-top": "Tilføj denne side til din overvågningsliste?",
        "confirm-unwatch-button": "OK",
        "confirm-unwatch-top": "Fjern denne side fra din overvågningsliste?",
+       "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← forrige side",
        "imgmultipagenext": "næste side →",
        "imgmultigo": "OK",
        "autosumm-replace": "Erstatter sidens indhold med \"$1\"",
        "autoredircomment": "Omdirigering til [[$1]] oprettet",
        "autosumm-new": "Oprettede siden med \"$1\"",
+       "autosumm-newblank": "Oprettede tom side",
        "lag-warn-normal": "Ændringer som er nyere end {{PLURAL:$1|et sekund|$1 sekunder}}, vises muligvis ikke i denne liste.",
        "lag-warn-high": "Grundet stor belastning af databaseserveren vil ændringer der er nyere end {{PLURAL:$1|et sekund|$1 sekunder}} måske ikke blive vist i denne liste.",
        "watchlistedit-normal-title": "Rediger overvågningsliste",
        "watchlistedit-raw-done": "Din overvågningsliste blev opdateret.",
        "watchlistedit-raw-added": "{{PLURAL:$1|1 side|$1 sider}} er tilføjet:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1 side|$1 sider}} er fjernet:",
+       "watchlistedit-clear-title": "Ryddet overvågningsliste",
+       "watchlistedit-clear-legend": "Ryd overvågningsliste",
+       "watchlistedit-clear-explain": "Alle siderne vil blive fjernet fra din overvågningsliste",
+       "watchlistedit-clear-titles": "Sider:",
+       "watchlistedit-clear-submit": "Ryd overvågningslisten (dette er permanent!)",
+       "watchlistedit-clear-done": "Din overvågningsliste er blevet ryddet.",
+       "watchlisttools-clear": "Ryd overvågningsliste",
        "watchlisttools-view": "Se ændrede sider i overvågningslisten",
        "watchlisttools-edit": "Rediger overvågningsliste",
        "watchlisttools-raw": "Rediger rå overvågningsliste",
        "expand_templates_remove_nowiki": "Undertryk <nowiki>-tags i resultatet",
        "expand_templates_generate_xml": "Vis analysetræ som XML",
        "expand_templates_generate_rawhtml": "Vis rå HTML",
-       "expand_templates_preview": "Forhåndsvisning"
+       "expand_templates_preview": "Forhåndsvisning",
+       "pagelanguage": "Valg af sidesprog",
+       "pagelang-name": "Side",
+       "pagelang-language": "Sprog",
+       "pagelang-use-default": "Brug standardsprog",
+       "pagelang-select-lang": "Vælg sprog",
+       "right-pagelang": "Ændre sidesproget"
 }
index f1bd8f8..0c16519 100644 (file)
@@ -74,7 +74,8 @@
                        "Zylbath",
                        "לערי ריינהארט",
                        "✓",
-                       "XenonX3"
+                       "XenonX3",
+                       "Brackenheim"
                ]
        },
        "tog-underline": "Links unterstreichen:",
@@ -91,6 +92,7 @@
        "tog-watchdefault": "Selbst geänderte Seiten und Dateien automatisch beobachten",
        "tog-watchmoves": "Selbst verschobene Seiten und Dateien automatisch beobachten",
        "tog-watchdeletion": "Selbst gelöschte Seiten und Dateien automatisch beobachten",
+       "tog-watchrollback": "Seiten, bei denen ich eine Zurücksetzung durchgeführt habe, der Beobachtungsliste hinzufügen.",
        "tog-minordefault": "Eigene Änderungen standardmäßig als geringfügig markieren",
        "tog-previewontop": "Vorschau oberhalb des Bearbeitungsfensters anzeigen",
        "tog-previewonfirst": "Beim ersten Bearbeiten immer die Vorschau anzeigen",
        "talkpagelinktext": "Diskussion",
        "specialpage": "Spezialseite",
        "personaltools": "Meine Werkzeuge",
-       "postcomment": "Neuer Abschnitt",
        "articlepage": "Inhaltsseite anzeigen",
        "talk": "Diskussion",
        "views": "Ansichten",
        "otherlanguages": "In anderen Sprachen",
        "redirectedfrom": "(Weitergeleitet von $1)",
        "redirectpagesub": "Weiterleitung",
+       "redirectto": "Weiterleitung nach:",
        "lastmodifiedat": "Diese Seite wurde zuletzt am $1 um $2 Uhr geändert.",
        "viewcount": "Diese Seite wurde bisher {{PLURAL:$1|einmal|$1 mal}} abgerufen.",
        "protectedpage": "Geschützte Seite",
        "hidetoc": "Verbergen",
        "collapsible-collapse": "Einklappen",
        "collapsible-expand": "Ausklappen",
+       "confirmable-confirm": "Bist {{GENDER:$1|du}} sicher?",
+       "confirmable-yes": "Ja",
+       "confirmable-no": "Nein",
        "thisisdeleted": "$1 ansehen oder wiederherstellen?",
        "viewdeleted": "$1 anzeigen?",
        "restorelink": "$1 {{PLURAL:$1|gelöschte Version|gelöschte Versionen}}",
        "invalidtitle-knownnamespace": "Ungültiger Titel mit Namensraum „$2“ und Text „$3“",
        "invalidtitle-unknownnamespace": "Ungültiger Titel mit unbekannter Namensraumnummer $1 und Text „$2“",
        "exception-nologin": "Nicht angemeldet",
-       "exception-nologin-text": "Du musst dich [[Special:Userlogin|anmelden]], um auf diese Seite oder Aktion zugreifen zu können.",
+       "exception-nologin-text": "Du musst dich anmelden, um auf diese Seite oder Aktion zugreifen zu können.",
        "exception-nologin-text-manual": "Du musst dich $1, um auf diese Seite oder Aktion zugreifen zu können.",
        "virus-badscanner": "Fehlerhafte Konfiguration: unbekannter Virenscanner: <em>$1</em>",
        "virus-scanfailed": "Scan fehlgeschlagen (code $1)",
        "externaldberror": "Entweder liegt ein Fehler bei der externen Authentifizierung vor oder du darfst dein externes Benutzerkonto nicht aktualisieren.",
        "login": "Anmelden",
        "nav-login-createaccount": "Anmelden / Benutzerkonto erstellen",
-       "loginprompt": "Zur Anmeldung müssen Cookies aktiviert sein.",
        "userlogin": "Anmelden / Benutzerkonto anlegen",
        "userloginnocreate": "Anmelden",
        "logout": "Abmelden",
        "userlogin-resetlink": "Die Anmeldedaten vergessen?",
        "userlogin-resetpassword-link": "Passwort vergessen?",
        "userlogin-helplink2": "Hilfe beim Anmelden",
-       "userlogin-loggedin": "Du bist bereits als {{GENDER:$1|$1}} angemeldet.\nBenutze das unten stehende Formular, um dich unter einem anderen Benutzernamen anzumelden.",
-       "userlogin-createanother": "Ein weiteres Benutzerkonto erstellen",
        "createacct-emailrequired": "E-Mail-Adresse",
        "createacct-emailoptional": "E-Mail-Adresse (optional)",
        "createacct-email-ph": "Gib deine E-Mail-Adresse ein",
        "createaccount-text": "Es wurde für dich ein Benutzerkonto „$2“ auf {{SITENAME}} ($4) erstellt. Das automatisch generierte Passwort für „$2“ ist „$3“. Du solltest dich nun anmelden und das Passwort ändern.\n\nFalls das Benutzerkonto irrtümlich angelegt wurde, kannst du diese Nachricht ignorieren.",
        "login-throttled": "Du hast zu oft versucht, dich anzumelden.\nBitte warte $1, bevor du es erneut probierst.",
        "login-abort-generic": "Deine Anmeldung war nicht erfolgreich – Abgebrochen",
+       "login-migrated-generic": "Dein Benutzerkonto wurde migriert. Dein Benutzername ist auf diesem Wiki nicht mehr vorhanden.",
        "loginlanguagelabel": "Sprache: $1",
        "suspicious-userlogout": "Deine Abmeldeanfrage wurde verweigert, da sie vermutlich von einem defekten Browser oder einem Cache-Proxy gesendet wurde.",
        "createacct-another-realname-tip": "Der bürgerliche Name ist optional.\nWenn du ihn angibst, wird er für die Zuordnung der Beiträge verwendet.",
        "preview": "Vorschau",
        "showpreview": "Vorschau zeigen",
        "showdiff": "Änderungen zeigen",
-       "anoneditwarning": "Du bearbeitest diese Seite unangemeldet. Wenn du sie abspeicherst, wird deine aktuelle IP-Adresse in der Versionsgeschichte aufgezeichnet und ist damit unwiderruflich '''öffentlich''' einsehbar.",
+       "blankarticle": "<strong>Warnung:</strong> Die Seite, die du erstellst, ist leer.\nWenn du erneut auf „{{int:savearticle}}“ klickst, wird die Seite ohne Inhalt erstellt.",
+       "anoneditwarning": "<strong>Warnung:</strong> Du bist nicht angemeldet. Deine IP-Adresse wird öffentlich sichtbar, falls du Bearbeitungen durchführst. Wenn du dich <strong>[$1 anmeldest]</strong> oder <strong>[$2 ein Benutzerkonto erstellst]</strong>, werden deine Bearbeitungen zusammen mit anderen Beiträgen deinem Benutzernamen zugeordnet.",
        "anonpreviewwarning": "''Du bist nicht angemeldet. Beim Speichern wird deine IP-Adresse in der Versionsgeschichte aufgezeichnet.''",
        "missingsummary": "'''Hinweis:''' Du hast keine Zusammenfassung angegeben. Wenn du erneut auf „{{int:savearticle}}“ klickst, wird deine Änderung ohne Zusammenfassung übernommen.",
        "missingcommenttext": "Dein Abschnitt enthält keinen Text.",
        "parser-template-recursion-depth-warning": "Vorlagenrekursionstiefengrenze überschritten ($1)",
        "language-converter-depth-warning": "Sprachkonvertertiefenlimit überschritten ($1)",
        "node-count-exceeded-category": "Seiten, die die Knotenanzahl überschritten haben",
-       "node-count-exceeded-category-desc": "Eine Kategorie für Seiten, bei denen die Knotenzahl überschritten wurde.",
+       "node-count-exceeded-category-desc": "Die Seite überschreitet die maximale Knotenanzahl.",
        "node-count-exceeded-warning": "Die Seite hat die Knotenpunktanzahl überschritten.",
        "expansion-depth-exceeded-category": "Seiten, die die Expansionstiefe überschritten haben",
-       "expansion-depth-exceeded-category-desc": "Dies ist eine Kategorie für Seiten, bei denen die Expandierungstiefe überschritten wurde.",
+       "expansion-depth-exceeded-category-desc": "Die Seite überschreitet die maximale Expandierungstiefe.",
        "expansion-depth-exceeded-warning": "Die Seite hat die Expansionstiefe überschritten.",
        "parser-unstrip-loop-warning": "Zirkelbezug festgestellt",
        "parser-unstrip-recursion-limit": "Rekursionsgrenze beim Auflösen überschritten ($1)",
        "rev-deleted-event": "(Logbuchaktion entfernt)",
        "rev-deleted-user-contribs": "[Benutzername oder IP-Adresse entfernt – Bearbeitung aus Beiträgen versteckt]",
        "rev-deleted-text-permission": "Diese Version wurde '''gelöscht'''.\nNähere Angaben zum Löschvorgang sowie eine Begründung stehen im [{{fullurl:{{#special:Log}}/delete|page={{FULLPAGENAMEE}}}} Lösch-Logbuch].",
+       "rev-suppressed-text-permission": "Diese Seitenversion wurde <strong>unterdrückt</strong>.\nEinzelheiten können im [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Oversight-Logbuch] gefunden werden.",
        "rev-deleted-text-unhide": "Diese Version wurde '''gelöscht'''.\nNähere Angaben stehen im [{{fullurl:{{#special:Log}}/delete|page={{FULLPAGENAMEE}}}} Lösch-Logbuch].\nDu kannst [$1 diese Version einsehen], sofern du möchtest.",
        "rev-suppressed-text-unhide": "Diese Version wurde '''unterdrückt'''.\nNähere Angaben stehen im [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Unterdrückungs-Logbuch].\nDu kannst [$1 diese Version einsehen], sofern du möchtest.",
        "rev-deleted-text-view": "Diese Version wurde '''gelöscht'''.\nDu kannst sie einsehen, sofern du möchtest. Nähere Angaben stehen im [{{fullurl:{{#special:Log}}/delete|page={{FULLPAGENAMEE}}}} Lösch-Logbuch].",
        "revdelete-text-text": "Gelöschte Versionen verbleiben noch in der Versionsgeschichte, jedoch sind Teile ihres Inhalts für die Öffentlichkeit nicht zugänglich.",
        "revdelete-text-file": "Gelöschte Dateiversionen verbleiben noch in der Datei-Versionsgeschichte, jedoch sind Teile ihres Inhalts für die Öffentlichkeit nicht zugänglich.",
        "logdelete-text": "Gelöschte Logbucheinträge verbleiben noch in den Logbüchern, jedoch sind Teile ihres Inhalts für die Öffentlichkeit nicht zugänglich.",
-       "revdelete-text-others": "Andere Administratoren auf {{SITENAME}} haben noch Zugriff auf den versteckten Inhalt und können ihn auch mithilfe dieser Spezialseite wiederherstellen, solange keine zusätzlichen Beschränkungen festgelegt werden.",
+       "revdelete-text-others": "Andere Administratoren haben noch Zugriff auf den versteckten Inhalt und können ihn auch wiederherstellen, solange keine zusätzlichen Beschränkungen festgelegt werden.",
        "revdelete-confirm": "Bitte bestätige, dass du beabsichtigst, dies zu tun, die Konsequenzen verstehst und es in Übereinstimmung mit den [[{{MediaWiki:Policy-url}}|Richtlinien]] tust.",
        "revdelete-suppress-text": "Unterdrückungen sollten '''nur''' in den folgenden Fällen vorgenommen werden:\n* Potentiell beleidigende Informationen\n* Unangebrachte persönliche Informationen\n*: ''Adressen, Telefonnummern, Sozialversicherungsnummern etc.''",
        "revdelete-legend": "Setzen der Sichtbarkeitseinschränkungen",
        "searchprofile-advanced-tooltip": "Suche in weiteren Namensräumen",
        "search-result-size": "$1 ({{PLURAL:$2|1 Wort|$2 Wörter}})",
        "search-result-category-size": "{{PLURAL:$1|1 Seite|$1 Seiten}} ({{PLURAL:$2|1 Unterkategorie|$2 Unterkategorien}}, {{PLURAL:$3|1 Datei|$3 Dateien}})",
-       "search-result-score": "Relevanz: $1 %",
        "search-redirect": "(Weiterleitung von „$1“)",
        "search-section": "(Abschnitt $1)",
        "search-file-match": "(treffende Dateiinhalte)",
        "searchall": "alle",
        "showingresults": "Hier {{PLURAL:$1|ist '''1''' Ergebnis|sind '''$1''' Ergebnisse}}, beginnend mit Nummer '''$2.'''",
        "showingresultsinrange": "Unten {{PLURAL:$1|wird <strong>ein</strong> Ergebnis|werden bis zu <strong>$1</strong> Ergebnisse}} im Bereich <strong>$2</strong> bis <strong>$3</strong> angezeigt.",
-       "showingresultsheader": "{{PLURAL:$5|Ergebnis '''$1''' von '''$3'''|Ergebnisse '''$1–$2''' von '''$3'''}} für '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Ergebnis <strong>$1</strong> von <strong>$3</strong>|Ergebnisse <strong>$1 bis $2</strong> von <strong>$3</strong>}}",
        "search-nonefound": "Zu deiner Suchanfrage wurden keine Ergebnisse gefunden.",
        "powersearch-legend": "Erweiterte Suche",
        "powersearch-ns": "Suche in Namensräumen:",
        "preferences": "Einstellungen",
        "mypreferences": "Einstellungen",
        "prefs-edits": "Anzahl der Bearbeitungen:",
-       "prefsnologintext2": "Du musst dich $1, um Benutzereinstellungen festzulegen.",
+       "prefsnologintext2": "Bitte anmelden, um deine Benutzereinstellungen festzulegen.",
        "prefs-skin": "Benutzeroberfläche",
        "skin-preview": "Vorschau",
        "datedefault": "Standard",
        "grouppage-suppress": "{{ns:project}}:Oversighter",
        "right-read": "Seiten lesen",
        "right-edit": "Seiten bearbeiten",
-       "right-createpage": "Seiten erstellen (außer Diskussionsseiten)",
+       "right-createpage": "Seiten erstellen (die keine Diskussionsseiten sind)",
        "right-createtalk": "Diskussionsseiten erstellen",
        "right-createaccount": "Benutzerkonto erstellen",
        "right-minoredit": "Bearbeitungen als klein markieren",
        "right-deletedtext": "Gelöschte Texte und Versionsunterschiede zwischen gelöschten Versionen ansehen",
        "right-browsearchive": "Nach gelöschten Seiten suchen",
        "right-undelete": "Seiten wiederherstellen",
-       "right-suppressrevision": "Versionen ansehen und wiederherstellen, die auch vor Administratoren verborgen sind",
+       "right-suppressrevision": "Bestimmte Versionen vor jedem Benutzer verstecken, wiederherstellen und anschauen",
+       "right-viewsuppressed": "Vor jedem Benutzer versteckte Versionen ansehen",
        "right-suppressionlog": "Private Logbücher ansehen",
        "right-block": "Benutzer sperren (Schreibrecht)",
        "right-blockemail": "Benutzer am Versenden von E-Mails hindern",
        "recentchanges-legend-heading": "'''Legende:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (siehe auch die [[Special:NewPages|Liste neuer Seiten]])",
        "recentchanges-legend-plusminus": "''(±123)''",
-       "rcnotefrom": "Angezeigt werden die Änderungen seit <strong>$2</strong> (max. <strong>$1</strong> Einträge).",
+       "rcnotefrom": "Angezeigt {{PLURAL:$5|wird die Änderung|werden die Änderungen}} seit <strong>$3, $4</strong> (max. <strong>$1</strong> Einträge).",
        "rclistfrom": "Nur Änderungen seit $3, $2 Uhr zeigen.",
        "rcshowhideminor": "Kleine Änderungen $1",
        "rcshowhideminor-show": "anzeigen",
        "uploadwarning": "Warnung",
        "uploadwarning-text": "Bitte ändere unten die Dateibeschreibung und versuche es erneut.",
        "savefile": "Datei speichern",
-       "uploadedimage": "lud „[[$1]]“ hoch",
-       "overwroteimage": "lud eine neue Version von „[[$1]]“ hoch",
        "uploaddisabled": "Hochladen deaktiviert",
        "copyuploaddisabled": "Das Hochladen von URLs ist deaktiviert",
        "uploaddisabledtext": "Das Hochladen von Dateien ist deaktiviert.",
        "license": "Lizenz:",
        "license-header": "Lizenz",
        "nolicense": "Keine Vorauswahl",
+       "licenses-edit": "Lizenzoptionen bearbeiten",
        "license-nopreview": "(es ist keine Vorschau verfügbar)",
-       "upload_source_url": " (gültige, öffentlich zugängliche URL)",
-       "upload_source_file": " (eine Datei auf deinem Computer)",
+       "upload_source_url": "(deine ausgewählte Datei von einer gültigen, öffentlich zugänglichen URL)",
+       "upload_source_file": "(deine ausgewählte Datei von deinem Computer)",
+       "listfiles-delete": "löschen",
        "listfiles-summary": "Diese Spezialseite listet alle hochgeladenen Dateien auf.",
        "listfiles_search_for": "Suche nach Datei:",
        "imgfile": "Datei",
        "randomincategory": "Zufällige Seite einer Kategorie",
        "randomincategory-invalidcategory": "„$1“ ist kein gültiger Kategorienname.",
        "randomincategory-nopages": "Es gibt keine Seiten in [[:Category:$1]].",
-       "randomincategory-selectcategory": "Zufällige Seite aus der Kategorie: $1 $2",
-       "randomincategory-selectcategory-submit": "Los",
+       "randomincategory-category": "Kategorie:",
+       "randomincategory-legend": "Zufällige Seite in Kategorie",
        "randomredirect": "Zufällige Weiterleitung",
        "randomredirect-nopages": "Im Namensraum „$1“ sind keine Weiterleitungen vorhanden.",
        "statistics": "Statistik",
        "wantedpages-badtitle": "Ungültiger Titel im Ergebnis: $1",
        "wantedfiles": "Gewünschte Dateien",
        "wantedfiletext-cat": "Die folgenden Dateien werden verwendet, sind jedoch nicht vorhanden. Vorhandene Dateien aus fremden Repositorien können dennoch hier aufgelistet sein und werden <del>durchgestrichen</del> dargestellt. Zusätzlich werden Seiten, die nicht vorhandene Dateien enthalten, in die [[:$1]] eingeordnet.",
+       "wantedfiletext-cat-noforeign": "Die folgenden Dateien werden verwendet, sind jedoch nicht vorhanden. Zusätzlich werden Seiten auf [[:$1]] gelistet, die nicht vorhandene Dateien einbetten.",
        "wantedfiletext-nocat": "Die folgenden Dateien werden verwendet, sind jedoch nicht vorhanden. Vorhandene Dateien aus fremden Repositorien können dennoch hier aufgelistet sein und werden <del>durchgestrichen</del> dargestellt.",
+       "wantedfiletext-nocat-noforeign": "Die folgenden Dateien werden verwendet, sind jedoch nicht vorhanden.",
        "wantedtemplates": "Gewünschte Vorlagen",
        "mostlinked": "Seiten mit den meisten Links",
        "mostlinkedcategories": "Meistbenutzte Kategorien",
        "trackingcategories-desc": "Kategorieeinbindungskriterien",
        "noindex-category-desc": "Die Seite wird nicht von Bots indexiert, da sie das magische Wort <code><nowiki>__NOINDEX__</nowiki></code> enthält und sich in einem Namensraum befindet, wo dieses Flag erlaubt ist.",
        "index-category-desc": "Die Seite enthält ein <code><nowiki>__INDEX__</nowiki></code> und befindet sich in einem Namensraum, in dem dieses Flag nicht erlaubt ist und wird daher von Bots ausnahmsweise indexiert.",
-       "post-expand-template-inclusion-category-desc": "Nach dem Expandieren aller Vorlagen ist die Seitengröße größer als <code>$wgMaxArticleSize</code>, sodass einige Vorlagen nicht expandiert werden.",
-       "post-expand-template-argument-category-desc": "Nach dem Expandieren eines Vorlagenargumentes (etwas in dreifach geschweiften Klammern, z.&nbsp;B. <code>{{{Foo}}})</code> ist die Seite größer als <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Zu viele aufwändige Parserfunktionen (wie <code>#ifexist</code>) sind in der Seite eingebunden. Siehe das [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Benutzerhandbuch].",
-       "broken-file-category-desc": "Kategorie, die hinzugefügt wird, falls die Seite einen defekten Dateilink enthält (einen Link zu einer eingebetteten Datei, die nicht vorhanden ist).",
-       "hidden-category-category-desc": "Dies ist eine Kategorie mit <code><nowiki>__HIDDENCAT__</nowiki></code>, die standardmäßig nicht auf Seiten im Kategorienbereich angezeigt wird.",
+       "post-expand-template-inclusion-category-desc": "Die Seitengröße ist nach dem Expandieren aller Vorlagen größer als <code>$wgMaxArticleSize</code>, so dass einige Vorlagen nicht expandiert wurden.",
+       "post-expand-template-argument-category-desc": "Die Seite ist nach dem Expandieren eines Vorlagenargumentes größer als <code>$wgMaxArticleSize</code> (etwas in dreifachen Klammern, wie <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "Die Seite verwendet zu viele aufwändige Parserfunktionen (wie <code>#ifexist</code>). Siehe das [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Benutzerhandbuch].",
+       "broken-file-category-desc": "Die Seite enthält einen defekten Dateilink (einen Link zu einer eingebetteten Datei, die nicht vorhanden ist).",
+       "hidden-category-category-desc": "Die Kategorie enthält <code><nowiki>__HIDDENCAT__</nowiki></code> in ihrem Seiteninhalt, was verhindert, dass sie standardmäßig auf Seiten im Kategorielinkkasten angezeigt wird.",
        "trackingcategories-nodesc": "Keine Beschreibung verfügbar.",
        "trackingcategories-disabled": "Kategorie ist deaktiviert",
        "mailnologin": "Fehler beim E-Mail-Versand",
        "mywatchlist": "Beobachtungsliste",
        "watchlistfor2": "Von $1 $2",
        "nowatchlist": "Es befinden sich keine Einträge auf deiner Beobachtungsliste.",
-       "watchlistanontext": "Du musst dich $1, um deine Beobachtungsliste sehen oder Einträge auf ihr bearbeiten zu können.",
+       "watchlistanontext": "Du musst dich anmelden, um deine Beobachtungsliste sehen oder Einträge auf ihr bearbeiten zu können.",
        "watchnologin": "Du bist nicht angemeldet",
        "addwatch": "Zur Beobachtungsliste hinzufügen",
        "addedwatchtext": "Die Seite „[[:$1]]“ wurde zu deiner [[Special:Watchlist|Beobachtungsliste]] hinzugefügt.\nSpätere Änderungen an dieser Seite und der zugehörigen Diskussionsseite werden dort gelistet.",
        "watchlist-details": "Du beobachtest {{PLURAL:$1|eine Seite|$1 Seiten}}, ohne dass Diskussionsseiten getrennt gezählt werden.",
        "wlheader-enotif": "Der E-Mail-Benachrichtigungsdienst ist aktiviert.",
        "wlheader-showupdated": "Seiten mit noch nicht gesehenen Änderungen werden '''fett''' dargestellt.",
-       "wlnote2": "Es folgen die Änderungen der letzten {{PLURAL:$1|Stunde|<strong>$1</strong> Stunden}}. Stand: $2, $3.",
+       "wlnote": "Es {{PLURAL:$1|folgt die letzte Änderung|folgen die letzten <strong>$1</strong> Änderungen}} der letzten {{PLURAL:$2|Stunde|<strong>$2</strong> Stunden}}. Stand: $3, $4 Uhr.",
        "wlshowlast": "Zeige die Änderungen der letzten $1 Stunden, $2 Tage oder $3.",
        "watchlist-options": "Anzeigeoptionen",
        "watching": "Beobachten …",
        "exbeforeblank": "Inhalt vor dem Leeren der Seite: „$1“",
        "delete-confirm": "Löschen von „$1“",
        "delete-legend": "Löschen",
-       "historywarning": "'''Achtung:''' Die Seite, die du löschen möchtest, hat eine Versionsgeschichte mit ungefähr $1 {{PLURAL:$1|Version|Versionen}}:",
+       "historywarning": "<strong>Achtung:</strong> Die Seite, die du löschen möchtest, hat eine Versionsgeschichte mit {{PLURAL:$1|einer Version|$1 Versionen}}:",
        "confirmdeletetext": "Du bist dabei, eine Seite mit allen zugehörigen älteren Versionen zu löschen. Bitte bestätige dazu, dass du dir der Konsequenzen bewusst bist, und dass du in Übereinstimmung mit den [[{{MediaWiki:Policy-url}}|Richtlinien]] handelst.",
        "actioncomplete": "Aktion beendet",
        "actionfailed": "Aktion fehlgeschlagen",
        "delete-edit-reasonlist": "Löschgründe bearbeiten",
        "delete-toobig": "Diese Seite hat mit mehr als $1 {{PLURAL:$1|Version|Versionen}} eine sehr lange Versionsgeschichte. Das Löschen solcher Seiten wurde eingeschränkt, um eine versehentliche Überlastung der Server zu verhindern.",
        "delete-warning-toobig": "Diese Seite hat mit mehr als $1 {{PLURAL:$1|Version|Versionen}} eine sehr lange Versionsgeschichte. Das Löschen kann zu Störungen im Datenbankbetrieb führen.",
+       "deleteprotected": "Du kannst diese Seite nicht löschen, da sie geschützt wurde.",
        "deleting-backlinks-warning": "'''Warnung:''' Es verweisen noch [[Special:WhatLinksHere/{{FULLPAGENAME}}|andere Seiten]] auf die zu löschende Seite oder diese Seite ist noch woanders eingebunden.",
        "rollback": "Zurücksetzen der Änderungen",
        "rollback_short": "Zurücksetzen",
        "autoblockid": "Automatische Sperrung #$1",
        "block": "Benutzer sperren",
        "unblock": "Benutzer freigeben",
-       "blockip": "IP-Adresse/Benutzer sperren",
+       "blockip": "IP-Adresse/{{GENDER:$1|Benutzer|Benutzerin}} sperren",
        "blockip-legend": "IP-Adresse/Benutzer sperren",
        "blockiptext": "Mit diesem Formular sperrst du eine IP-Adresse oder einen Benutzernamen, so dass von dort keine Änderungen mehr vorgenommen werden können.\nDies sollte nur erfolgen, um Vandalismus zu verhindern und in Übereinstimmung mit den [[{{MediaWiki:Policy-url}}|Richtlinien]].\nBitte gib den Grund für die Sperre an.",
        "ipaddressorusername": "IP-Adresse oder Benutzername:",
        "ipb-unblock-addr": "„$1“ freigeben",
        "ipb-unblock": "IP-Adresse/Benutzer freigeben",
        "ipb-blocklist": "Alle aktuellen Sperren anzeigen",
-       "ipb-blocklist-contribs": "Benutzerbeiträge von „$1“",
+       "ipb-blocklist-contribs": "Benutzerbeiträge von „{{GENDER:$1|$1}}“",
        "unblockip": "Benutzer freigeben",
        "unblockiptext": "Mit diesem Formular kannst du eine IP-Adresse oder einen Benutzer freigeben.",
        "ipusubmit": "Freigeben",
        "unblocked": "[[User:$1|$1]] wurde freigegeben",
        "unblocked-range": "Sperre für $1 wurde aufgehoben",
        "unblocked-id": "Sperr-ID $1 wurde freigegeben",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] wurde freigegeben.",
        "blocklist": "Gesperrte Benutzer",
        "ipblocklist": "Gesperrte Benutzer",
        "ipblocklist-legend": "Suche nach einem gesperrten Benutzer",
        "import": "Seiten importieren",
        "importinterwiki": "Transwiki-Import",
        "import-interwiki-text": "Wähle ein Wiki und eine Seite zum Importieren aus.\nDie Versionsdaten und Benutzernamen bleiben dabei erhalten.\nAlle Transwiki-Import-Aktionen werden im [[Special:Log/import|Import-Logbuch]] protokolliert.",
-       "import-interwiki-source": "Quell-Wiki/-Seite:",
+       "import-interwiki-sourcewiki": "Quellwiki:",
+       "import-interwiki-sourcepage": "Quellseite:",
        "import-interwiki-history": "Alle Versionen dieser Seite importieren",
        "import-interwiki-templates": "Alle Vorlagen einschließen",
        "import-interwiki-submit": "Importieren",
        "import-error-create": "Die Seite „$1“ wurde nicht importiert, da du nicht berechtigt bist, sie zu erstellen.",
        "import-error-interwiki": "Die Seite „$1“ wurde nicht importiert, da deren Name für externe Links (Interwiki) reserviert ist.",
        "import-error-special": "Die Seite „$1“ wurde nicht importiert, da sie zu einem besonderen Namensraum gehört, in dem keine Seiten möglich sind.",
-       "import-error-invalid": "Seite „$1“ wurde nicht importiert, da deren Name ungültig ist.",
+       "import-error-invalid": "Seite „$1“ wurde nicht importiert, da der Name, zu dem sie importiert werden würde, auf diesem Wiki nicht gültig ist.",
        "import-error-unserialize": "Die Version $2 der Seite „$1“ konnte nicht deserialisiert werden. Die Version wurde zur Verwendung des Inhaltsmodells $3 gemeldet, das als $4 serialisiert ist.",
        "import-error-bad-location": "Die Version $2, die das Inhaltsmodell $3 verwendet, kann auf diesem Wiki nicht unter „$1“ gespeichert werden, da dieses Modell auf dieser Seite nicht unterstützt wird.",
        "import-options-wrong": "Falsche {{PLURAL:$2|Option|Optionen}}: <nowiki>$1</nowiki>",
        "importlogpage": "Import-Logbuch",
        "importlogpagetext": "Administrativer Import von Seiten mit Versionsgeschichte von anderen Wikis.",
        "import-logentry-upload": "importierte „[[$1]]“ von einer Datei",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|Version|Versionen}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|Version|Versionen}} importiert",
        "import-logentry-interwiki": "importierte „$1“ (Transwiki)",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|Version|Versionen}} von $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|Version|Versionen}} von $2 importiert",
        "javascripttest": "JavaScript-Test",
        "javascripttest-title": "$1-Tests werden durchgeführt",
        "javascripttest-pagetext-noframework": "Diese Seite ist JavaSkript-Tests vorbehalten.",
        "autosumm-replace": "Der Seiteninhalt wurde durch einen anderen Text ersetzt: „$1“",
        "autoredircomment": "Weiterleitung nach [[$1]] erstellt",
        "autosumm-new": "Die Seite wurde neu angelegt: „$1“",
+       "autosumm-newblank": "Leere Seite erstellt",
        "size-bytes": "$1 Bytes",
        "size-megabytes": "$1 MB",
        "size-gigabytes": "$1 GB",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|Diskussion]])",
        "unknown_extension_tag": "Unbekanntes Parsertag „$1“",
        "duplicate-defaultsort": "Achtung: Der Sortierungsschlüssel „$2“ überschreibt den vorher verwendeten Schlüssel „$1“.",
+       "duplicate-displaytitle": "<strong>Warnung:</strong> Der Anzeigetitel „$2“ überschreibt den früheren Anzeigetitel „$1“.",
        "version": "Version",
        "version-extensions": "Installierte Erweiterungen",
        "version-skins": "Installierte Benutzeroberflächen",
        "logentry-rights-rights": "$1 {{GENDER:$2|änderte}} die Gruppenzugehörigkeit für $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",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|lud}} eine neue Version von $3 hoch",
+       "logentry-upload-revert": "$1 {{GENDER:$2|lud}} $3 hoch",
        "rightsnone": "(–)",
        "feedback-bugornote": "Sofern du detailliert ein technisches Problem beschreiben möchtest, melde bitte [$1 einen Fehler].\nAnderenfalls kannst du auch das untenstehende einfache Formular nutzen. Dein Kommentar wird, zusammen mit deinem Benutzernamen und der Version des von dir verwendeten Webbrowsers sowie Betriebssystems, auf der Seite „[$3 $2]“ hinzugefügt.",
        "feedback-subject": "Betreff:",
        "action-pagelang": "die Seitensprache zu ändern",
        "log-name-pagelang": "Sprachenänderungs-Logbuch",
        "log-description-pagelang": "Dies ist ein Logbuch mit Änderungen an Seitensprachen.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|änderte}} die Seitensprache für $3 von $4 nach $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|änderte}} die Seitensprache für $3 von $4 nach $5.",
+       "default-skin-not-found": "Hoppla! Die in <code dir=\"ltr\">$wgDefaultSkin</code> als <code>$1</code> definierte Standardbenutzeroberfläche für dein Wiki ist nicht verfügbar.\n\nDeine Installation scheint die folgenden Benutzeroberflächen zu enthalten. Siehe [https://www.mediawiki.org/wiki/Manual:Skin_configuration/de das Benutzerhandbuch] zur Aktivierung und Auswahl des Standards.\n\n$2\n\n; Falls du gerade MediaWiki installiert hast:\n: Du hast vermutlich von Git oder direkt vom Quellcode mithilfe einer anderen Methode installiert. Dies wird erwartet. Versuche einige Benutzeroberflächen aus dem  [https://www.mediawiki.org/wiki/Category:All_skins MediaWiki.org-Benutzeroberflächenverzeichnis] zu installieren, indem du:\n:* Den [https://www.mediawiki.org/wiki/Download/de Tarball-Installer] herunterlädst, der mit verschiedenen Benutzeroberflächen und Erweiterungen kommt. Du kannst das Verzeichnis <code>skins/</code> kopieren und einfügen.\n:* Eine der <code>mediawiki/skins/*</code>-Repositorien über Git in das <code dir=\"ltr\">skins/</code>-Verzeichnis deiner MediaWiki-Installation klonst.\n: Dies sollte nicht dein Git-Repositorium beeinträchtigen, falls du ein MediaWiki-Entwickler bist.\n\n; Falls du gerade MediaWiki aktualisiert hast:\n: MediaWiki 1.24 und neuere Versionen aktivieren nicht mehr automatisch installierte Benutzeroberflächen (siehe das [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Benutzerhandbuch]). Du kannst die folgenden Zeilen in die Datei <code>LocalSettings.php</code> einfügen, um alle derzeit installierten Benutzeroberflächen zu aktivieren:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Falls du gerade <code>LocalSettings.php</code> geändert hast:\n: Überprüfe die Namen der Benutzeroberflächen auf Tippfehler.",
+       "default-skin-not-found-no-skins": "Hoppla! Die in <code>$wgDefaultSkin</code> als <code>$1</code> definierte Standardbenutzeroberfläche für dein Wiki ist nicht verfügbar.\n\nDu hast keine installierten Benutzeroberflächen.\n\n; Falls du gerade MediaWiki installiert oder aktualisiert hast:\n: Du hast vermutlich von Git oder direkt vom Quellcode mithilfe einer anderen Methode installiert. Dies wird erwartet. MediaWiki 1.24 und neuere Versionen enthalten keine Benutzeroberflächen im Haupt-Repositorium. Versuche einige Benutzeroberflächen aus dem [https://www.mediawiki.org/wiki/Category:All_skins MediaWiki.org-Benutzeroberflächenverzeichnis] zu installieren, indem du:\n:* Den [https://www.mediawiki.org/wiki/Download/de Tarball-Installer] herunterlädst, der mit verschiedenen Benutzeroberflächen und Erweiterungen kommt. Du kannst das  <code>skins/</code>-Verzeichnis kopieren und einfügen.\n:* Eine der <code>mediawiki/skins/*</code>-Repositorien über Git in das <code dir=\"ltr\">skins/</code>-Verzeichnis deiner MediaWiki-Installation klonst.\n: Dies sollte nicht dein Git-Repositorium beeinträchtigen, falls du ein MediaWiki-Entwickler bist. Siehe das [https://www.mediawiki.org/wiki/Manual:Skin_configuration/de Benutzerhandbuch] zur Aktivierung von Benutzeroberflächen und Auswahl des Standards.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (aktiviert)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''deaktiviert''')"
 }
index 4250606..7b0a6ad 100644 (file)
        "talkpagelinktext": "Vatenayış",
        "specialpage": "Pela xısusiye",
        "personaltools": "Hacetê şexsiy",
-       "postcomment": "Qısımo newe",
        "articlepage": "Pela zerreki bıvêne",
        "talk": "Werênayış",
        "views": "Asayışi",
        "versionrequired": "No $1 MediaWiki lazımo",
        "versionrequiredtext": "Seba gurenayışê na pele versiyonê MediaWiki $1 lazımo. \n[[Special:Version|Versiyonê pele]] bıvêne.",
        "ok": "Temam",
-       "pagetitle": "\"$1\" adres ra gerya.",
+       "pagetitle": "$1 – {{SITENAME}}",
        "pagetitle-view-mainpage": "{{SITENAME}}",
        "backlinksubtitle": "← $1",
        "retrievedfrom": "\"$1\" ra ard",
        "externaldberror": "Ya database de xeta esta ya zi heqê şıma çino şıma no hesab bıvurni.",
        "login": "Cı kewe",
        "nav-login-createaccount": "Dekew de / hesab vıraze",
-       "loginprompt": "{{SITENAME}} dı ronıştış akerdışi rê ''çerezan'' aktiv kerdış icab keno.",
        "userlogin": "Cı kewe / hesab vıraze",
        "userloginnocreate": "Cı kewe",
        "logout": "Bıveciye",
        "editwarning-warning": "Wexto ke şıma na pele ra veciyê, beno ke vurnayışê şıma vindi bê.\nEke şıma kewtê hesabê xo, şıma şenê nê balantışi qısmê \"{{int:prefs-editing}}\"i de tercihanê xo ra bıvındarnê.",
        "editpage-notsupportedcontentformat-title": "Formatê zerreki qebul nêbeno",
        "content-model-wikitext": "wikimetin",
-       "content-model-text": "duz metin",
+       "content-model-text": "metno pan",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
        "expensive-parserfunction-warning": "Hişyari: No pel de fonksiyoni zaf esti.\n\nNo $2 daweti ra gani tay bıbo, na hel {{PLURAL:$1|1 dawet esto|$1 dawet esto}}.",
        "pagemerge-logentry": "[[$1]] u [[$2]] yew kerd (revizyonî heta $3)",
        "revertmerge": "Abırnê",
        "mergelogpagetext": "Cêr de yew liste esta ke mocnena ra, raya tewr peyêne kamci pela tarixi be a bine ra şanawa pê.",
-       "history-title": "Rewizyonê $1:",
+       "history-title": "Tarixê çımraviyarnayışê \"$1\"",
        "difference-title": "Pela \"$1\" ferqê çım ra viyarnayışan",
        "difference-title-multipage": "Ferkê pelan dê \"$1\" u \"$2\"",
        "difference-multipage": "(Ferqê pelan)",
        "searchprofile-advanced-tooltip": "qe cayê nimeyî bigêre",
        "search-result-size": "$1 ({{PLURAL:$2|1 çekuyo|$2 çekuyê}})",
        "search-result-category-size": "{{PLURAL:$1|1 eza|$1 ezayan}} ({{PLURAL:$2|1 kategoriyê bini|$2 kategirayanê binan}}, {{PLURAL:$3|1 dosya|$3 dosyayan}})",
-       "search-result-score": "Eleqa: $1%",
        "search-redirect": "($1 ra ardış)",
        "search-section": "(qısmê $1)",
        "search-file-match": "(zerreyê dosya yewbini gêno)",
        "uploadwarning": "Îkazê bar kerdişî",
        "uploadwarning-text": "Bînê de deskripyonê dosyayî bivurne u reyna qeyd bike.",
        "savefile": "Dosya qeyd ke",
-       "uploadedimage": "\"[[$1]]\" bar bi",
-       "overwroteimage": "yew versiyonê \"$1\" newe bar bi",
        "uploaddisabled": "bar kerdişî iptal biyo",
        "copyuploaddisabled": "URL bar kerdiş kefiliyeyo.",
        "uploaddisabledtext": "Barkerdışê dosya dewre ra veta.",
        "watchlist-details": "{{PLURAL:$1|$1 pele|$1 peleyan}} listeyê seyr-kerdışi şıma dı, peleyanê vurnayışi dahil niyo.",
        "wlheader-enotif": "E-mail xeber dayiş abiyo.",
        "wlheader-showupdated": "ziyaretê şıma ye peyini de vuryayişê peli pê '''nuşteyo qalıni''' mocyayo.",
-       "wlnote2": "Cêr vurnayışê {{PLURAL:$1|saeta|<strong>$1</strong> saetanê}} peyênan estê, $2 ra be hetan $3.",
+       "wlnote": "$3 seate u bahde $4 deqa dıma {{PLURAL:$2|ju seate dı|'''$2''' ju seate dı}} {{PLURAL:$1|vurnayışe peyeni|vurnayışe '''$1''' peyeni}} cêrdeyê",
        "wlshowlast": "Peyni de vurnayışan ra  $1 seata u $2 roca $3 bımocnê",
        "watchlist-options": "Tercihê liste da seyri",
        "watching": "Seyr ke...",
index c34e9b3..2cebf9a 100644 (file)
@@ -16,7 +16,8 @@
                        "Shirayuki",
                        "Tlustulimu",
                        "Tlustulimu Nepl1",
-                       "아라"
+                       "아라",
+                       "TMg"
                ]
        },
        "tog-underline": "Wótkaze pódšmarnuś:",
@@ -85,7 +86,7 @@
        "april": "apryl",
        "may_long": "maj",
        "june": "junij",
-       "july": " julij",
+       "july": "julij",
        "august": "awgust",
        "september": "september",
        "october": "oktober",
        "talkpagelinktext": "diskusija",
        "specialpage": "Specialny bok",
        "personaltools": "Wósobinske pomocne srědki",
-       "postcomment": "Nowy wótrězk",
        "articlepage": "Nastawk",
        "talk": "Diskusija",
        "views": "Naglědy",
        "externaldberror": "Abo jo wustupiła eksterna zmólka awtentifikacije datoweje banki, abo njesmějoš swójo eksterne wužywarske konto aktualizěrowaś.",
        "login": "Pśizjawiś se",
        "nav-login-createaccount": "Pśizjawiś se/Konto załožyś",
-       "loginprompt": "Za pśizjawjenje do boka {{SITENAME}} muse cookije dowólone byś.",
        "userlogin": "Pśizjawiś se/Konto załožyś",
        "userloginnocreate": "Pśizjawiś",
        "logout": "wótzjawiś se",
        "searchprofile-advanced-tooltip": "W swójskich mjenjowych rumach pytaś",
        "search-result-size": "$1 ({{PLURAL:$2|1 słowow|$2 słowje|$2 słowa|$2 słowow}})",
        "search-result-category-size": "{{PLURAL:$1|1 cłonk|$1 cłonka|$1 cłonki|$1 cłonkow}} ({{PLURAL:$2|1 pódkategorija|$2 pódkategoriji|$2 pódkategorije|$2 pódkategorijow}}, {{PLURAL:$3|1 dataja|$3 dataji|$3 dataje|$3 datajow}})",
-       "search-result-score": "Relewanca: $1 %",
        "search-redirect": "(pśesměrowanje $1)",
        "search-section": "(sekcija $1)",
        "search-file-match": "(wótpowědujo datajowemu wopśimjeśeju)",
        "uploadwarning": "Warnowanje",
        "uploadwarning-text": "Pšosym změń slědujuce datajowe wopisanje a wopytaj hyšći raz.",
        "savefile": "Dataju składowaś",
-       "uploadedimage": "jo  \"[[$1]]\" nagrał.",
-       "overwroteimage": "Jo nowu wersiju \"[[$1]]\" nagrał.",
        "uploaddisabled": "Nagrawanje jo se znjemóžniło.",
        "copyuploaddisabled": "Nagraśe pśez URL znjemóžnjone.",
        "uploaddisabledtext": "Nagraśa datajow su znjemóžnjone.",
        "watchlist-details": "Wobglědujoš {{PLURAL:$1|$1 bok|$1 boka|$1 boki|$1 bokow}}, bźez diskusijnych bokow.",
        "wlheader-enotif": "E-mailowa zdźěleńska słužba jo zmóžnjona.",
        "wlheader-showupdated": "Boki, kótarež su wót twójogo slědnego woglěda se změnili, pokazuju se '''tucnje'''.",
-       "wlnote2": "Slěduju změny {{PLURAL:$1|zachadneje góźiny|zachadneju <strong>$1</strong> góźinowu|zachadnych <strong>$1</strong> góźinow}} Staw: $2, $3.",
+       "wlnote": "{{PLURAL:$1|Slědujo slědna změna|slědujotej '''$1''' slědnej změnje|slěduju slědne '''$1''' změny}} {{PLURAL:$2|slědneje góźiny|slědneju '''$2''' góźinowu|slědnych '''$2''' góźinow}}, staw: $3, $4.",
        "wlshowlast": "Pokaž změny slědnych $1 góźinow, $2 dnjow abo $3 (w slědnych 30 dnjach).",
        "watchlist-options": "Opcije wobglědowańki",
        "watching": "Wobglědowaś …",
        "duplicate-defaultsort": "Glědaj: Standardny sortěrowański kluc (DEFAULT SORT KEY) \"$2\" pśepišo pjerwjej wužyty kluc \"$1\".",
        "version": "Wersija",
        "version-extensions": "Instalowane rozšyrjenja",
+       "version-skins": "Suknje",
        "version-specialpages": "Specialne boki",
        "version-parserhooks": "Parserowe kokule",
        "version-variables": "Wariable",
        "version-antispam": "Šćit pśeśiwo spamoju",
-       "version-skins": "Suknje",
        "version-other": "Druge",
        "version-mediahandlers": "Pśeźěłaki medijow",
        "version-hooks": "Kokule",
index 1db8670..53f608f 100644 (file)
        "talkpagelinktext": "Boroson",
        "specialpage": "Bolikon suaikowokon",
        "personaltools": "Kakamot minsosondiri",
-       "postcomment": "Bogian wagu",
        "articlepage": "Intaai suang bolikon",
        "talk": "Pogigibarasan",
        "views": "Pongintangan",
        "externaldberror": "Haro nokosilap pongintutunan bingdata toi awu ko pasagaon monginwagu takaun poinsoliwannu.",
        "login": "Sumuang log",
        "nav-login-createaccount": "Sumuang log / pomonsoi  do takaun",
-       "loginprompt": "Suhuonko do poposikit pongongonsok do sumuang log id {{SITENAME}}.",
        "userlogin": "Sumuang log / pomonsoi  do takaun",
        "userloginnocreate": "Sumuang log",
        "logout": "Lumabus log",
        "uploadnologintext": "Pinatantu ko do [[Special:UserLogin|lumoog sumuang]] do mangaplod tangapail-pail.",
        "uploadlogpage": "Log poposuang",
        "filedesc": "Koinibaan",
-       "uploadedimage": "poposuang \"[[$1]]\"",
        "license": "Pongolisinan:",
        "license-header": "Pongolisinan",
        "listfiles_search_for": "Mogihum ngaran modia:",
index ca2cfa4..703f898 100644 (file)
        "talkpagelinktext": "ޚިޔާލު ސަފްޙާ",
        "specialpage": "ހާއްސަ ޞަފްޙާ",
        "personaltools": "އަމިއްލަ",
-       "postcomment": "އާ ބައެއް",
        "articlepage": "ފިހުރިސްތު ޞަފްޙާ ބައްލަވާ",
        "talk": "ބަހުސް",
        "views": "ހިޔާލުފުޅުތައް",
        "yourpasswordagain": "ސިއްރުބަސް އަލުންލިޔުއްވާ",
        "login": "ވަދެވަޑައިގަންނަވާ",
        "nav-login-createaccount": "ވަންނަވާ / މެންބަރަކަށް ވެވަޑައިގަންނަވާ",
-       "loginprompt": "{{SITENAME}}އަށް ވަންނަވަން ކުކީޒް ބޭނުންވާނެއެވެ.",
        "userlogin": "ވަންނަވާ / މެންބަރަކަށް ވެ ވަޑައިގަންނަވާ",
        "userloginnocreate": "ވަދެވަޑައިގަންނަވާ",
        "logout": "ބޭރަށް ވަޑައިގަންނަވާ",
        "watch": "ނަޒަރުބަހައްޓަވާ",
        "watchthispage": "މި ޞަފްޙާއަށް ނަޒަރުބަހައްޓަވާ",
        "unwatch": "ހާއްސަ ނަޒަރުން އުނިކުރޭ",
+       "wlnote": "ތިރީގައި މިވަނީ އެއީ ފާއިތުވި <b>$2</b> ގަޑި އިރުގެ ތެރޭގައިގެނެވިފައިވާ ފަހު $1 ބަދަލެވެ.",
        "changed": "ބަދަލުކުރެވިއްޖެ",
        "deletepage": "ޞަފްޙާ ފޮހެލައްވާ",
        "confirm": "ޔަގީން",
index 4f6e294..d9370d7 100644 (file)
@@ -22,6 +22,7 @@
        "tog-watchdefault": "Zûnta al pàgini e i file mudifichê int i tgnû 'd ôc specêl.",
        "tog-watchmoves": "Zûnta al pàgini e i file spustê int i tgnû 'd ôc specêl.",
        "tog-watchdeletion": "Zûnta al pàgini e i file scanşlê int i tgnû 'd ôc specêl.",
+       "tog-watchrollback": "Zûta al pàgini in dóv' ó fât al ritōren a la pàgina 'd préma a i tgnû 'd ôc specêl",
        "tog-minordefault": "Sògna ògni mudéfica cme céca (sōl cme pre-stabilî)",
        "tog-previewontop": "Fà vèder còl ch' ò fât sōver la caşèla ed mudéfica e mìa sòta.",
        "tog-previewonfirst": "Fà vèder còl ch' ò fât almēno 'na vôlta préma 'd salvêr",
        "hidden-category-category": "Categoréi lughêdi",
        "category-subcat-count": "{{PLURAL:$2|In cla categoréia ché a gh'é sōl 'n'ónica sòt-categoréia.| In cla categoréia ché a gh'é {{PLURAL:$1|la sòt-categoréia sgnêda|al $1 sòt-categoréi sgnêdi}} ed sègvit, só 'n totêl ed $2.}}",
        "category-subcat-count-limited": "In cla categoréia ché a gh'é{{PLURAL:$1|'na sòt-categoréia, nutêda|$1 sòt-categoréi, nutêdi}}ché 'd sègvit.",
-       "category-article-count": "{{PLURAL:$2|In cla categoréia ché a gh'é sōl 'na pàgina, sgnêda ché.|In cla categoréia ché gh'é{{PLURAL:$1|la pàgina sgnêda| al pàgini $1 sgnêdi}} ed sègvit, in un totêl ed $2.}}",
+       "category-article-count": "{{PLURAL:$2|In cla categoréia ché a gh'é sōl 'na pàgina, sgnêda ché.|Cla categoréia ché la gh'à {{PLURAL:$1|la pàgina sgnêda| al pàgini $1 sgnêdi}} ed sègvit, in un totêl ed $2.}}",
        "category-article-count-limited": "In cla categoréia ché a gh'é {{PLURAL:$1|la pàgina nutêda|al  $1 pàgini nutêdi ch'é 'd sègvit.}}",
        "category-file-count": "{{PLURAL:$2|In cla categoréia ché a gh'é sōl un file, sgnê ché.|In cla categoréia ché gh'é{{PLURAL:$1|un file sgnê ché| i file $1, sgnê}} ed sègvit, in un totêl ed $2.}}",
        "category-file-count-limited": "In cla categoréia ché a gh'é {{PLURAL:$1|al file nutê|i $1 file nutê}} ché 'd sègvit.",
        "talkpagelinktext": "Discusiòun",
        "specialpage": "Pàgina specêla",
        "personaltools": "Strumèint persunêl",
-       "postcomment": "Sesiòun nōva",
        "articlepage": "Guêrda la pàgina",
        "talk": "Discusiòun",
        "views": "Vîşiti",
        "projectpage": "Guêrda la pàgina dal prugèt",
        "imagepage": "Guêrda la pàgina dal 'file'",
        "mediawikipage": "Guêrda al mesâg",
-       "templatepage": "Guêrda al 'template'",
+       "templatepage": "Guêrda 'l mudèl",
        "viewhelppage": "Guêrda la pàgina 'd ajót",
        "categorypage": "Guêrda la categuréia",
        "viewtalkpage": "Guêrda la discusiòun",
        "otherlanguages": "In êtri léngvi",
        "redirectedfrom": "(Tót còst al deşvîn da <b>$1</b>)",
        "redirectpagesub": "Pàgina 'd partèinsa",
+       "redirectto": "Rimânda a:",
        "lastmodifiedat": "Ûltmi mudéfichi 'dla pàgina: $2, $1.",
        "viewcount": "Cla pàgina ché l'é stêda lişûda {{PLURAL:$1|'na vôlta|$1 vôlti}}.",
        "protectedpage": "Pàgina sòta prutesiòun",
        "hidetoc": "Lōga",
        "collapsible-collapse": "Stréca",
        "collapsible-expand": "Şlêrga",
+       "confirmable-confirm": "Ét {{GENDER:$1|sicûr|sicûra}}?",
+       "confirmable-yes": "Sé",
+       "confirmable-no": "No",
        "thisisdeleted": "Guêrda e tōrna a mèter $1?",
        "viewdeleted": "Guêrda $1?",
        "restorelink": "{{PLURAL:$1|'na mudéfica scanşlêda|$1 mudéfichi scanşlêdi}}",
        "nstab-image": "'File'",
        "nstab-mediawiki": "Mesâg",
        "nstab-template": "Mudèl",
-       "nstab-help": "Per quî rivê da pôch",
+       "nstab-help": "Pàgina 'd ajót",
        "nstab-category": "Categoréia",
        "nosuchaction": "Operasiòun mìa arcgnusûda",
        "nosuchactiontext": "Còl che t'é scrét int l' URL an n'é mìa vâlid.\nL'é anca pusébil che la URL la sia stêda scréta şbaliêda o che sia stê fât un colegamèint mìa vâlid.\nCòst al pré ânca dîr che gh'é un bug in {{SITENAME}}.",
        "protectedinterface": "Cla pàgina ché la gh'à 'n elemèint ch' al fa pêrt dal colegamèint tra utèint e al progrâma 'd cól sît ché e l'é prutèta per schivşêr pusébil abûş. Per zuntêr o mudufichêr tradusiòun per tót i sistēma wiki druvêr [//translatewiki.net/ translatewiki.net], al prugèt 'd adatamèint a ògni léngva 'd MediaWiki.",
        "editinginterface": "'''Atèinti:''' Al tèst ed cla pàgina ché 'l fa pêrt dal colegamèint tra utèint e 'l progrâma dal sît.  Tót' al modéfichi fâti a cla pàgina ché a gnîran spustêdi insém a i mesâg vést da tót j utèint ed cól wiki ché. Per zuntêr o mudufichêr tradusiòun vâlidi per tót i wiki, cunsîdra la pusibilitê 'd druvêr [/ / translatewiki.net / translatewiki.net], al prugèt 'd adatamèint a ògni léngva 'd MediaWiki.",
        "cascadeprotected": "Insém a cla pàgina ché an n'é mìa pusébil fêr dal mudéfichi perchè l'é dèinter {{PLURAL:$1|int la pàgina sgnêda ché  'd sègvit, ch' l'é stêda prutèta|int al pàgini sgnêdi ché  'd sègvit, ch' în stêdi prutèti}} cun la prutesiòun ch' la 's arfà in cuntinvasiòun:\n$2",
-       "namespaceprotected": "An 's gh'à mìa i permès necesâri per mudifichêr al pàgini dal spâsi di nòm '''$1'''.",
+       "namespaceprotected": "An 's gh'à mìa i permès necesâri per mudifichêr al pàgini dal spâsi di nòm <strong>$1</strong>.",
        "customcssprotected": "An 's gh'à mìa i permès necesâri per mudifichêr cla pàgina CSS ché, perchè la gh'à dèinter al j impustasiòun personêli 'd n' êter utèint.",
        "customjsprotected": "An 's gh'à mìa i permès necesâri per mudifichêr cla pàgina JavaScript ché, perchè la gh'à dèinter al j impustasiòun personêli 'd n' êter utèint.",
        "mycustomcssprotected": "An 's gh'à mìa i permès necesâri per mudifichêr cla pàgina CSS ché.",
        "invalidtitle-knownnamespace": "Tétol mìa vâlid cme spâsi di nòm \"$2\" e tèst \"$3\"",
        "invalidtitle-unknownnamespace": "Tétol mìa vâlid cun spâsi di nòm mìa cgnusû \"$1\" e tèst \"$2\"",
        "exception-nologin": "An t'é mìa gnû dèinter",
-       "exception-nologin-text": "Per andêr dèinter a cla pàgina ché o fêr còl ch'ét pèins ét gh'ê da [[Special:Userlogin|fêr l'ingrès]].",
+       "exception-nologin-text": "Per andêr dèinter a cla pàgina ché o fêr còl ch'ét pèins ét gh'ê da fêr l'ingrès.",
        "exception-nologin-text-manual": "Per prèir andêr dèinter a cla pàgina ché o fêr còl ch'ét pèins ét gh'ê da \"$1\".",
        "virus-badscanner": "Erōr 'd impustasiòun: antivîrus mìa cgnusû:\"$1\"",
        "virus-scanfailed": "Al cuntròl antivìrus l'é andê mêl (côdis $1)",
        "externaldberror": "È sucès un erōr cun al terminêl ed certificasiòun ed validitê d'ed fōra, opór an 's gh'à mìa al j autorişasiòun necesâri per arnuvêr l' ingrès d'ed fōra.",
        "login": "Và dèinter",
        "nav-login-createaccount": "Và dèinter / Fà la tó inscrisiòun",
-       "loginprompt": "Per andêr dèinter a {{SITENAME}} l'é necesâri permèter i cookie.",
        "userlogin": "Và dèinter / Fà la tó inscrisiòun",
        "userloginnocreate": "Và dèinter",
        "logout": "Và fōra",
        "userlogin-resetlink": "T'ét scurdê j elemèint p'r al tó ingrès?",
        "userlogin-resetpassword-link": "T' ét scurdê la cêva 'd ingrès?",
        "userlogin-helplink2": "Ajót per l'ingrès",
-       "userlogin-loggedin": "T'ét bèle coleghê {{GENDER:$1|$1}}. \nDrōva al mōdul ché sòta cme un êter utèint.",
-       "userlogin-createanother": "Fà 'n' êtra utèinsa.",
        "createacct-emailrequired": "Indirés pôsta eletrônica",
        "createacct-emailoptional": "Indirés pôsta eletrônica (se 's vōl)",
        "createacct-email-ph": "Scrév al tó indirés ed pôsta eletrônica",
        "createaccount-text": "Quelchidûn l'à fât un inscrisiòun a  {{SITENAME}} ($4) a nòm ed $2 coleghê a cl'indirés ed pôsta eletrônica ché. La cêva 'd ingrès per l'utèint \"$2\" l'é  impustêda a \"$3\". \nÉ necesâri fêr un ingrès préma ch' es pôl e cambiêr subét la cêva 'd ingrès. \nSe l'inscrisiòun l'é stêda fâta per şbâli, es pōl scanşlêr sté mesâg.",
        "login-throttled": "În stê fât trôp tentatîv 'd ingrès in pôch tèimp. Spèta $1 e pó tōrna pruvêr.",
        "login-abort-generic": "An t'é mìa stê arcgnusû - Scanşlê",
+       "login-migrated-generic": "La tó utèinsa l'é stêda spustêda, e al tó nòm utèint al gh'é mìa pió in sém a cla wiki ché.",
        "loginlanguagelabel": "Léngva: $1",
        "suspicious-userlogout": "La tó dmânda per destachêret l'é stēda rifiutêda perchè la sèmbra spidîda da un navigadōr ch' al funsiòuna mìa o da un proxy di caching.",
-       "createacct-another-realname-tip": "Druvêr al nòm vèira l'é 'na siēlta personêla; s' es pèinsa 'd ruvêrel al gnirâ uşê per dêr la paternitê di lavōr spidî.",
+       "createacct-another-realname-tip": "Druvêr al nòm vèira l'é 'na siēlta personêla; s' es pèinsa 'd druvêrel al gnirâ uşê per dêr la paternitê di lavōr spidî.",
        "pt-login": "Và dèinter",
        "pt-login-button": "Và dèinter",
        "pt-createaccount": "Fà la tó inscrisiòun",
        "preview": "Guêrda préma",
        "showpreview": "Guêrda préma 'd salvêr",
        "showdiff": "Guêrda i cambiamèint",
-       "anoneditwarning": "'''Atensiòun:''' Ingrès mìa fât. Al tó indirés IP al srà sgnê int la stòria ed cla pàgina chè.",
+       "blankarticle": "<strong>Atèinti:</strong>la pàgina che t'é drē fêr la gh'à gnînto dèinter. S' ét tōren a schisêr in sém a \"{{int:savearticle}}\", la pàgina la srà fât sèinsa gnînto dèinter.",
+       "anoneditwarning": "<strong>Atèinti:</strong> An n'é mìa stê fât l'ingrès. S' ét farê dal mudéfichi al tó indirés IP al srà vést da tót. Se <strong>[$1 và dèinter]</strong> o <strong>[$2 fà 'n' utèinsa]</strong>, al tô mudéfichi a srân sgnêdi al tó nòm utèint, insèm a êter benefési.",
        "anonpreviewwarning": "\"An n'é mìa stê fât l'ingrès. Mèinter es sêlva la pàgina, l'indirés IP al srà sgnê int la stòria 'd la pàgina.\"",
        "missingsummary": "'''Atensiòun:''' an n'é mìa stê precişê al mutîv de sté mudéfica. S'es tōrna a clichêr insém a \"{{int:savearticle}}\" la mudéfica la gnirà salvêda cun al mutîv vōd.",
        "missingcommenttext": "Scréver un cumèint ché sòta.",
        "parser-template-recursion-depth-warning": "A s'é rivê al lémit 'd arciâm int al mudèl ($1)",
        "language-converter-depth-warning": "A s'é pasê 'l lémit ed fònd dal cunvertidōr ed léngua ($1)",
        "node-count-exceeded-category": "Pàgin in dó vîn pasê 'l nómer ed nōd",
-       "node-count-exceeded-category-desc": "'Na categoréia p'r al pàgini in dó a's pâsa al nómer di nōd.",
+       "node-count-exceeded-category-desc": "La pàgina la và d'ed sōver al nómer di nōd.",
        "node-count-exceeded-warning": "Cla pàgina ché l'à pasê 'l nómer di nōd",
        "expansion-depth-exceeded-category": "Pàgini 'n dó vî pasê al fònd de şlargamèint",
-       "expansion-depth-exceeded-category-desc": "Còsta l'é 'na categoréia per pàgini in dó vî pasê al fònd dal şlargamèint.",
+       "expansion-depth-exceeded-category-desc": "La pàgina la và d'ed là dal fònd mâsim de slarghêda.",
        "expansion-depth-exceeded-warning": "Cla pàgina ché la pasê al fònd de şlargamèint",
        "parser-unstrip-loop-warning": "Catê sèria 'd Unistrip",
        "parser-unstrip-recursion-limit": "A s'é pasê i lémit 'd arciâm 'd Unstrip ($1)",
        "rev-deleted-event": "(asiòun dal log armôsa)",
        "rev-deleted-user-contribs": "(nòm utèint o indirés IP armôs - mudéfica lughêda da la stòria)",
        "rev-deleted-text-permission": "Cla versiòun ché 'd la pàgina l'é stêda <strong> scanşlêda </strong>. \nConsultêr al [{{fullurl:{{#Special:Log}}/delete|page={{PAGENAMEE}}}} log dal canşladûri] per nōv particulêr.",
+       "rev-suppressed-text-permission": "Cla versiòun ché 'd la pàgina l'é stêda <strong> scanşlêda </strong>. Consultêr al [{{fullurl:{{#Special:Log}}/ suppress |page={{ FULLPAGENAMEE }}}} log dal canşladûri] per nōv particulêr.",
        "rev-deleted-text-unhide": "Cla versiòun ché 'd la pàgina l'é stêda <strong> scanşlêda </strong>. Consultêr al [{{fullurl:{{#Special:Log}}/delete|page={{PAGENAMEE}}}} log dal canşladûri] per nōv particulêr.\nS' l' é necesâri a j aministradōr a gh'é incòra permés [$1 ed guardêr cla versiòun ché].",
        "rev-suppressed-text-unhide": "Cla versiòun ché 'd la pàgina l'é stêda <strong> scanşlêda </strong>. Consultêr al [{{fullurl:{{#Special:Log}}/delete|page={{PAGENAMEE}}}} log dal canşladûri] per nōv particulêr.\nS' l' é necesâri a j aministradōr a gh'é incòra permés [$1 ed guardêr cla versiòun ché].",
        "rev-deleted-text-view": "Cla versiòun ché 'd la pàgina l'é stêda <strong> scanşlêda </strong>. J aministradōr a pōlen incòra guardêrla; \nconsultêr al [{{fullurl:{{#Special:Log}}/delete|page={{PAGENAMEE}}}} log dal canşladûri] per nōv particulêr.",
        "revdelete-text-text": "Al versiòun scanşlêdi as vèden incòra int la stòria 'd la pàgina, mó pcòun ed còl che gh'é dèinter al srà mìa vést dal póblich.",
        "revdelete-text-file": " Al versiòun di file scanşlê as vèden incòra int la stòria dal file, mó pcòun ed còl che gh'é dèinter al srà mìa vést dal póblich.",
        "logdelete-text": "I fât scanşlê as vèden incòra int la stòria 'd la pàgina, mó pcòun ed còl che gh'é dèinter al srà mìa vést dal póblich.",
-       "revdelete-text-others": "Êter aministradōr ed {{SITENAME}} a srân incòra bòun ed vèder j argomèint lughê e prân a turnêri a mèter incòra ed nōv per mèz ed cól canêl ché, se în mìa stê impustê di nōv lémit.",
+       "revdelete-text-others": "Êter aministradōr ed {{SITENAME}} a srân incòra bòun ed vèder j argomèint lughê e prân a turnêri a mèter incòra ed nōv, se în mìa stê impustê di nōv lémit.",
        "revdelete-confirm": "Per piaşèir cunfèirma che còst l'é còl ch'ét vō fêr, che t'é infurmê dal cunseguèinsi, e che t'é drē fêr còst int al rispèt dal [[{{MediaWiki:Policy-url}}|léni guîda]].",
        "revdelete-suppress-text": "La scanşlêda la duvré èser druvêda <strong>sōl</strong> in chi chêş ché:\n* infurmasiòun che prén èser calónij \n* infurmasiòun personêli cme \n*: <em>indirés, nómer ed telèfon, côdis fischêl, e via acsé.</em>",
        "revdelete-legend": "Impôsta i lémit seguèint al versiòun scanşlêdi:",
        "searchprofile-advanced-tooltip": "Sērca int i spâsi di nòm fât só mzûra.",
        "search-result-size": "$1 ({{PLURAL:$2|'na parôla|$2 parôli}})",
        "search-result-category-size": "{{PLURAL:$1|1 utèint|$1 utèint}} ({{PLURAL:$2|1 sotcategoréia|$2 sotcategoréi}},{{PLURAL:$3|1 file|$3 files}})",
-       "search-result-score": "Impurtânsa: $1%",
        "search-redirect": "(redirect $1)",
        "search-section": "(sesiòun $1)",
        "search-file-match": "(relasiòun dèinter al file)",
        "searchall": "tót",
        "showingresults": "Ed sègvit {{PLURAL:$1|a vîn preşentê al mâsim <strong>1</strong> rişultêt| a vînen preşentê al mâsim <strong>$1</strong> rişultêt}} a partîr dal nómer #<strong>$2</strong>.",
        "showingresultsinrange": "{{PLURAL:$1|A vîn mustrê| a vînen mustrê}} sòta {{PLURAL:$1|<strong>1</strong> rişultêt|<strong>$1</strong> rişultêt}} dal #<strong>$2</strong> al #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Al risultêt '''$1''' ed '''$3'''|I risultêt '''$1 - $2''' ed '''$3'''}} per '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Rişultêt <strong>$1</strong> ed <strong>$3</strong>|Rişultêt <strong>$1 - $2</strong> ed <strong>$3</strong>}}",
        "search-nonefound": "La sērca an n'à mìa dê di rişultê.",
        "powersearch-legend": "Sèirca specêla",
        "powersearch-ns": "Sērca int al spâsi di nòm:",
        "powersearch-togglenone": "Nisûn",
        "powersearch-remember": "Arcôrda la siēlta per êtri sèirchi ch'é vō fêr",
        "search-external": "Sèirca fâta fōra",
+       "searchdisabled": "La sèirca intêrna ed {{SITENAME}} l'a funsiòuna mìa; int al mèinter a s' pōl pruvêr a druvêr un mutōr ed sèirca d'ed fōra cme Google. (A gh' è da nutêr però che còl che gh'é dèinter in {{SITENAME}} che es câten in chi mutōr a prém èser mìa arnuvê.)",
+       "search-error": "É sucès un erōr mèinter a's fêva la sèirca:$1",
        "preferences": "Preferèinsa",
        "mypreferences": "Preferèinsi",
        "prefs-edits": "Mudéfichi fâti:",
+       "prefsnologintext2": "Es prèiga ed l'ingres per impustêr al tō  preferèinsi 'd utèint.",
        "prefs-skin": "Aspèt grâfich (skin)",
        "skin-preview": "Guêrda préma",
        "datedefault": "Nisóna preferèinsa",
+       "prefs-labs": "Funsiòun adâti in sperimèint",
+       "prefs-user-pages": "Pàgini utèint",
+       "prefs-personal": "Prufîl utèint",
+       "prefs-rc": "Ûltmi mudéfichi",
+       "prefs-watchlist": "Tgnîr sòt ôc",
+       "prefs-watchlist-days": "Nómer ed dé da fêr vèder int i tgnû 'd ôc specêl:",
+       "prefs-watchlist-days-max": "Mâsim $1 {{PLURAL:$1|dé}}",
+       "prefs-watchlist-edits": "Nómer 'd mudéfichi da fêr vèder cun al funsiòun pió şvilupêdi:",
+       "prefs-watchlist-edits-max": "Nómer mâsim:1000",
+       "prefs-watchlist-token": "Token tgnî d'ôc specêl:",
+       "prefs-misc": "Divêrs",
+       "prefs-resetpass": "Câmbia la cêva 'd ingrès",
+       "prefs-changeemail": "Câmbia l'indirés ed la pôsta eletrônica",
+       "prefs-setemail": "Impôsta un indirés ed pôsta eletrônica",
+       "prefs-email": "Siēlta pôsta eletrônica",
+       "prefs-rendering": "Aspèt",
        "saveprefs": "Sêlva",
+       "restoreprefs": "Turnêr a mèter al j impustasiòun ed partèinsa (in tót al sesiòun)",
        "prefs-editing": "Caşèla 'd mudéfica",
        "rows": "Rîghi",
+       "columns": "Clòuni:",
        "searchresultshead": "Sērca",
+       "stub-threshold": "Valōr ménim per i <a href=\"#\" class=\"stub\">colegamèint a i stub</a>, in byte:",
+       "stub-threshold-disabled": "Bluchê",
+       "recentchangesdays": "Nómer di dé da fêr vèder int al j ûltmi mudéfichi:",
+       "recentchangesdays-max": "Mâsim $1 {{PLURAL:$1|dé}}",
+       "recentchangescount": "Nómer ed mudéfichi da fêr vèder per default:",
+       "prefs-help-recentchangescount": "A gh'é dèinter al j ûltmi mudéfichi, stôri, e regéster.",
+       "prefs-help-watchlist-token2": "Còsta l'é la cêva secrēta p'r al flós web di tō tgnû 'd ôc specêl. Tót quî che la cgnòsen a sràn bòun ed lēşer i tō tgnû 'd ôc specêl, per còst an spartîrla mìa cun nisûn. [[Special:ResetTokens|Cléca ché s'ét ghê bişògn ed turnêrla impustêr]].",
+       "savedprefs": "Al preferèinsi în stêdi salvêdi.",
+       "timezonelegend": "Fûş urâri:",
+       "localtime": "Ōra lochêla:",
+       "timezoneuseserverdefault": "Drōva l'ōra stabilîda dal wiki ($1)",
+       "timezoneuseoffset": "Êter (spieghêr la diferèinsa)",
+       "servertime": "Ōra dal server:",
+       "guesstimezone": "Drōva l'ōra dal navigadōr",
        "timezoneregion-africa": "Âfrica",
        "timezoneregion-america": "Amèrica",
        "timezoneregion-antarctica": "Antârtide",
        "timezoneregion-europe": "Eurôpa",
        "timezoneregion-indian": "Ocèan Indiân",
        "timezoneregion-pacific": "Ocèan Pacéfich",
+       "allowemail": "Permèt a chiêter utèin ed mandêret ed la pōsta eletrônica",
+       "prefs-searchoptions": "Sērca",
+       "prefs-namespaces": "Spâsi di nòm",
+       "default": "Stabilî préma",
+       "prefs-files": "File",
+       "prefs-custom-css": "Adâta al CSS al tō necesitê",
+       "prefs-custom-js": "Adâta al JavaScript al tō necesitê",
+       "prefs-common-css-js": "CSS/JavaScript in comûn per tóti 'l skin:",
+       "prefs-reset-intro": "Es pōl druvêr cla pàgina ché per turnêr a impustêr al preferèinsi e cambiêr còli dichiarêdi int al sît. \nL'operasiòun l'an pōl mìa èser scanşlêda.",
+       "prefs-emailconfirm-label": "Cunfèirma ed la pôsta eletrônica:",
        "youremail": "E-mail:",
        "username": "{{GENDER:$1|Nòm utèint}}",
        "prefs-memberingroups": "{{GENDER:$2|Elemèint}}{{PLURAL:$1|dal gróp|di gróp}}:",
+       "prefs-registration": "Dâta 'd registrasiòun:",
        "yourrealname": "Nòm vèira:",
        "yourlanguage": "Léngua",
+       "yourvariant": "Câmbi 'd la léngua:",
+       "prefs-help-variant": "La versiòun o l'ortograféia ch' ét preferés vèder al pàgini ed cla wiki ché.",
+       "yournick": "Scutmâj (nikname):",
+       "prefs-help-signature": "I cumèint int al pàgini 'd discusiòun a dēven èser firmê cun \"<nowiki>~~~~</nowiki>\" ch' al gnirà cambiê cun la tó fîrma cun dôp la dâta.",
+       "badsig": "Erōr int la fîrma mìa standard, verifichêr i tag HTML.",
+       "badsiglength": "La fîrma siēlta l'é trôp lònga, l'an dēv mìa andêr d'ed sōver di $1 {{PLURAL:$1|carâter}}.",
+       "yourgender": "Cme arfêres a té?",
+       "gender-unknown": "Indiferèint",
+       "gender-male": "L'é registrê in sém a {{SITENAME}}",
+       "gender-female": "L'é registrêda in sém a {{SITENAME}}",
+       "prefs-help-gender": "L'impustasiòun ed cla preferèinsa ché l'é a siēlta. Al progrâma al drōva cól valōr ché per parlêr cun tè e numinêret cun chiêter cun al druvêr al gèner ed gramâtica gióst. Cl'infurmasiòun ché la srà póblica.",
        "email": "E-mail",
+       "prefs-help-realname": "Druvêr al nòm vèira l'é 'na siēlta personêla; s' es pèinsa 'd druvêrel al gnirâ uşê per dêr la paternitê di lavōr spidî.",
        "prefs-help-email": "Mèter l'indéris ed la tó pôsta eletrônica an n'é mia necesâri, mó al permèt ed ricêver la cêva 'd ingrès se per chêş ét la scurdés.",
        "prefs-help-email-others": "Ét pō ânca sernîr ed lasêr che chiêter a 's mèten in cuntât  tēgh cun la pôsta eletrônica cun al colegamèint da la tó pàgina utèint o da còla 'd discusiòun.  Al tó indirés al vîn mìa fât savèir a quî ch'ét 's mèten in cuntât tēgh.",
+       "prefs-help-email-required": "L'indirés ed pôsta eletrônica l'é ubligatôri.",
+       "prefs-info": "Infurmasiòun necesâri",
+       "prefs-signature": "Fîrma",
+       "prefs-dateformat": "Fōrma 'd la dâta",
+       "prefs-timeoffset": "Ōri 'd diferèinsa",
+       "prefs-advancedediting": "Siēlti generêli",
+       "prefs-editor": "Editōr",
+       "prefs-preview": "Guêrda préma",
+       "prefs-advancedrc": "Siēlti pió şvilupêdi",
+       "prefs-advancedrendering": "Siēlti pió şvilupêdi",
+       "prefs-advancedsearchoptions": "Siēlti pió şvilupêdi",
+       "prefs-advancedwatchlist": "Siēlti pió şvilupêdi",
+       "prefs-displayrc": "Siēlti ed vidûda",
+       "prefs-displaywatchlist": "Siēlti ed vidûda",
+       "prefs-tokenwatchlist": "Token",
+       "prefs-diffs": "Diferèinsi",
+       "prefs-help-prefershttps": "Cla diferèinsa ché la gh'à efèt dal st'êter ingrès.",
+       "prefs-tabs-navigation-hint": "Sugerimèint: è pusébil druvêr i tâst frècia a mansèina e a dréta per spustêres tr'al schēdi int l'elèinch dal schēdi.",
+       "email-address-validity-valid": "L'indirès ed pôste eletrônica a sèmbra vâlid",
+       "email-address-validity-invalid": "Mèt un indirés ed pôsta eletrônica vâlid",
+       "userrights": "Gestiòun di permès relatîv a j utèint",
+       "userrights-lookup-user": "Gestiòun di gróp utèint",
+       "userrights-user-editname": "Mèt dèinter al nòm utèint:",
+       "editusergroup": "Mudéfica gróp utèint",
+       "editinguser": "Mudéfica i dirét utèint ed l' utèint <strong>[[User:$1|$1]]</strong> $2",
+       "userrights-editusergroup": "Mudéfica gróp utèint",
+       "saveusergroups": "Sêlva gróp utèint",
+       "userrights-groupsmember": "Al fà pêrt {{PLURAL:$1|al gróp|ai gróp}}:",
+       "userrights-groupsmember-auto": "Al fà pêrt ed sicûr a:",
+       "userrights-reason": "Mutîv:",
        "group": "Gróp:",
        "group-user": "Utèint",
        "group-autoconfirmed": "Utèint cunvalidê da per ló",
        "recentchanges-label-minor": "Còsta l'é 'na mudéfica céca",
        "recentchanges-label-bot": "Cla mudéfica ché l'é stêda fâta da un bot.",
        "recentchanges-label-unpatrolled": "Cla mudéfica ché an n'é mìa incòra stêda verifichêda.",
-       "rcnotefrom": "Ché sòt a gh'é la lésta dal mudéfichi fâti a partîr da <strong>$2</strong>(fîn a <strong>$1</strong>).",
+       "rcnotefrom": "Ché sòt a {{PLURAL:$5|gh'é la mudéfica fâta|gh'în al mudéfichi fâti}} a partîr da<strong>$3,$4</strong>(fîn a <strong>$1</strong>).",
        "rclistfrom": "Fà vèder al mudéfichi fâti a partîr da $3 $2",
        "rcshowhideminor": "$1 al mudéfichi céchi",
        "rcshowhidebots": "$1 i bot",
        "rcshowhidemine": "$1 al mē mudéfichi",
        "rclinks": "Fà vèder al $1 ûltmi mudéfichi fâti int j ûltem $2 dé<br />$3",
        "diff": "dif",
-       "hist": "stòr",
+       "hist": "stòria",
        "hide": "Lōga",
        "show": "Fà vèder",
        "minoreditletter": "m",
        "upload": "Cârga un 'file'",
        "uploadlogpage": "Fil carghê",
        "filedesc": "Sûnt.",
-       "uploadedimage": "l'à carghê \"[[$1]]\"",
        "license": "Licèinsa:",
        "license-header": "Licèinsa",
        "nolicense": "Nisóna licèinsa sgnêda",
        "actioncomplete": "Asiòun cumpîda",
        "actionfailed": "Asiòun falîda",
        "dellogpage": "Scanşladûri",
-       "rollback_short": "Tōrna préma dal mudéfichi",
-       "rollbacklink": "tōrna préma dal mudéfichi",
+       "rollback_short": "Tōrna préma dal mudéfichi",
+       "rollbacklink": "tōrna préma dal mudéfichi",
        "rollbackfailed": "An t'é mia turnê indrē",
        "protectlogpage": "Al prutesiòun",
        "protectedarticle": "l'à prutèt \"[[$1]]\"",
        "whatlinkshere-filters": "Fîlter",
        "block": "Blôca l'utèint",
        "unblock": "Şblôcä l'utèint",
-       "blockip": "Blôcä l'utèint",
+       "blockip": "Blôcä {{GENDER:$1|utèint}}",
        "blockip-legend": "Blôcä l'utèint",
        "ipboptions": "2 ōri:2 hours,1 dé:1 day,3 dé:3 days,1 stmâna:1 week,2 stâni:2 weeks,1 mèiş:1 month,3 mèiş:3 months,6 mèiş:6 months,1 ân:1 year,infinito:infinite",
        "ipb-unblock-addr": "Şblôcä $1",
        "blocklink": "blôca",
        "unblocklink": "şblôca",
        "change-blocklink": "câmbia blôch",
-       "contribslink": "lavōr",
+       "contribslink": "lavōr fât",
        "blocklogpage": "Blôch",
        "blocklogentry": "t'é bluchê [[$1]] per un peréiod ed $2 $3",
        "unblocklogentry": "l'à şbluchê $1",
        "tooltip-pt-login": "A 's cunsélia 'd fêr la registrasiòun, ânca s' an n'é mia ubligatôri.",
        "tooltip-pt-logout": "Và fōra",
        "tooltip-ca-talk": "Guêrda al discusiòun relatîvi a cla pàgina chè.",
-       "tooltip-ca-edit": "Ét pō mudifiche cla pàgina ché. Per piaşèir drōva al ptòun \"Guêrda préma\" préma 'd salvêr còl che t'é fât.",
+       "tooltip-ca-edit": "Ét pō mudifiche cla pàgina ché. Per piaşèir drōva al ptòun \"Guêrda préma 'd salvêr\" per vèder còl che t'é fât.",
        "tooltip-ca-addsection": "Cumîncia 'na sesiòun nōva.",
        "tooltip-ca-viewsource": "Cla pàgina ché l'é sòta prutesiòun, mó 't pō vèder al só côdis surzéia.",
        "tooltip-ca-history": "Versiòun ed préma fâti a cla pàgina ché.",
        "tooltip-ca-nstab-special": "Còsta ché l'é 'na pàgina specêlal l'an pōl mìa èser mudifichêda",
        "tooltip-ca-nstab-project": "Guêrda la pàgina dal prugèt",
        "tooltip-ca-nstab-image": "Guêrda la pàgina dal 'file'",
-       "tooltip-ca-nstab-template": "Guêrda 'l template",
+       "tooltip-ca-nstab-template": "Guêrda 'l mudèl",
        "tooltip-ca-nstab-help": "Guêrda la pàgina d'ajót",
        "tooltip-ca-nstab-category": "Guêrda la pàgina 'd la categoréia",
        "tooltip-minoredit": "Sègna cme 'na mudéfica céca",
        "fileduplicatesearch-submit": "Sērca",
        "specialpages": "Pàgini specêli",
        "external_image_whitelist": "#Lasêr cla pàgina ché acsé cme l'é<pre>\n#Mèter dèinter i pès dal j espresiòun regolêri (sōl la pêrta cla va fra //) ed sègvit\n#Còsti gnirân més a cunfrûnt cun j indirés URL dal figûri d'ed fōra (hotlinked) \n#Al cunbinasiòun asrân fât vèder cme figûri, se no a gnirà fât vèder sōl al colegamèint\n#Al rîghi che cumîncen cun # în cunsidrêdi di cumèint\n#La diferèinsa tr' al lètri grândi e al lètri céchi an gh'à mìa impurtânsa\n\n#Mèter sōver cla rîga ché tót i pès di regex. Lasêr cla rîga ché acsé cme l'é</pre>",
-       "tag-filter": "Fîlta per  [[Special:Tags|etichèta]]",
+       "tag-filter": "Fîltra per  [[Special:Tags|etichèta]]",
        "tags-edit": "mudéfica",
        "compare-page1": "Pàgina 1",
        "compare-page2": "Pàgina 2",
index c7bd536..da5bf0c 100644 (file)
@@ -38,7 +38,8 @@
                        "Kolega2357",
                        "아라",
                        "Calak",
-                       "Auslaender"
+                       "Auslaender",
+                       "Milicevic01"
                ]
        },
        "tog-underline": "Υπογράμμιση συνδέσμων:",
@@ -55,6 +56,7 @@
        "tog-watchdefault": "Προσθήκη σελίδων που επεξεργάζομαι στη λίστα παρακολούθησης.",
        "tog-watchmoves": "Προσθήκη σελίδων που μετακινώ στη λίστα παρακολούθησής μου",
        "tog-watchdeletion": "Προσθήκη σελίδων και αρχείων που διαγράφω στη λίστα παρακολούθησής μου",
+       "tog-watchrollback": "Προσθήκη σελίδων όπου έχω κάνει μια επαναφορά στη λίστα παρακολούθησής μου",
        "tog-minordefault": "Σήμανση εκ προεπιλογής όλων των αλλαγών ως μικρής κλίμακας",
        "tog-previewontop": "Εμφάνιση προεπισκόπησης πριν από το πλαίσιο επεξεργασίας",
        "tog-previewonfirst": "Εμφάνιση προεπισκόπησης κατά την πρώτη επεξεργασία",
        "view": "Προβολή",
        "view-foreign": "Δείτε στο $1",
        "edit": "Επεξεργασία",
+       "edit-local": "Επεξεργασία τοπικής περιγραφής",
        "create": "Δημιουργία",
        "create-local": "Προσθέστε τοπική περιγραφή",
        "editthispage": "Επεξεργασία αυτής της σελίδας",
        "talkpagelinktext": "Συζήτηση",
        "specialpage": "Ειδική σελίδα",
        "personaltools": "Προσωπικά εργαλεία",
-       "postcomment": "Νέα ενότητα",
        "articlepage": "Εμφάνιση σελίδας περιεχομένου",
        "talk": "Συζήτηση",
        "views": "Προβολές",
        "jumptonavigation": "πλοήγηση",
        "jumptosearch": "αναζήτηση",
        "view-pool-error": "Λυπούμαστε, οι εξυπηρετητές είναι υπερφορτωμένοι αυτή τη στιγμή.\nΠάρα πολλοί χρήστες προσπαθούν να προβάλουν αυτή τη σελίδα.\nΠαρακαλούμε περιμένετε λίγο πριν ξαναπροσπαθήσετε να προσπελάσετε αυτή τη σελίδα.\n\n$1",
+       "generic-pool-error": "Λυπούμαστε, οι εξυπηρετητές είναι υπερφορτωμένοι αυτή τη στιγμή.\nΠάρα πολλοί χρήστες προσπαθούν να προβάλουν αυτό τον πόρο.\nΠαρακαλούμε περιμένετε λίγο πριν ξαναπροσπαθήσετε να προσπελάσετε αυτό τον πόρο ξανά.",
        "pool-timeout": "Χρόνος αναμονής για το κλείδωμα",
        "pool-queuefull": "Η ουρά της δεξαμενής διεργασιών είναι πλήρης",
        "pool-errorunknown": "Άγνωστο σφάλμα",
        "hidetoc": "απόκρυψη",
        "collapsible-collapse": "Σύμπτυξη",
        "collapsible-expand": "Ανάπτυξη",
+       "confirmable-confirm": "Είστε {{GENDER:$1|σίγουρος|σίγουρη}};",
+       "confirmable-yes": "Ναι",
+       "confirmable-no": "Όχι",
        "thisisdeleted": "Προβολή ή αποκατάσταση $1;",
        "viewdeleted": "Προβολή $1;",
        "restorelink": "{{PLURAL:$1|μίας διαγεγραμμένης επεξεργασίας|$1 διαγεγραμμένων επεξεργασιών}}",
        "cannotdelete": "Η σελίδα ή το αρχείο «$1» δεν μπόρεσε να διαγραφεί.\nΕνδεχομένως να έχει ήδη διαγραφεί από κάποιον άλλον.",
        "cannotdelete-title": "Αδύνατη η διαγραφή της σελίδας «$1»",
        "delete-hook-aborted": "Η επεξεργασία ματαιώθηκε από το άγκιστρο του συντακτικού αναλυτή.\nΔεν έδωσε εξήγηση.",
+       "no-null-revision": "Δεν μπορούσε να δημιουργηθεί νέα μηδενική αναθεώρηση για τη σελίδα \"$1\"",
        "badtitle": "Ακατάλληλος τίτλος",
        "badtitletext": "Ο τίτλος της σελίδας που ζητήσατε δεν είναι έγκυρος ή είναι κενός ή πρόκειται για έναν εσφαλμένα συνδεδεμένο διαγλωσσικό τίτλο ή εσφαλμένα συνδεδεμένο τίτλο ανάμεσα σε διαφορετικά wiki.",
        "perfcached": "Τα δεδομένα που ακολουθούν είναι cached και είναι πιθανόν να μην είναι επικαιροποιημένα. Ένα μέγιστο των  {{PLURAL:$1|one result is|$1 results are}} διαθέσιμο στην cache.",
        "invalidtitle-knownnamespace": "Μη έγκυρος τίτλος με χώρο ονομάτων «$2» και κείμενο «$3»",
        "invalidtitle-unknownnamespace": "Μη έγκυρος τίτλος με άγνωστο αριθμό χώρου ονομάτων $1 και κείμενο «$2»",
        "exception-nologin": "Δεν έχετε συνδεθεί.",
-       "exception-nologin-text": "Παρακαλούμε να [[Special:Userlogin|συνδεθείτε]] για να μπορείτε να αποκτήσετε πρόσβαση σε αυτήν τη σελίδα ή την ενέργεια.",
+       "exception-nologin-text": "Παρακαλούμε να συνδεθείτε για να μπορείτε να αποκτήσετε πρόσβαση σε αυτήν τη σελίδα ή την ενέργεια.",
        "exception-nologin-text-manual": "Παρακαλούμε $1 για να μπορείτε να έχετε πρόσβαση σε αυτή τη σελίδα ή ενέργεια.",
        "virus-badscanner": "Λάθος ρύθμιση: άγνωστος ανιχνευτής ιών: ''$1''",
        "virus-scanfailed": "Η σάρωση απέτυχε (κώδικας $1)",
        "externaldberror": "Είτε συνέβη κάποιο σφάλμα εξωτερικής πιστοποίησης της βάσης δεδομένων είτε δεν σας έχει επιτραπεί να ενημερώσετε τον εξωτερικό σας λογαριασμό.",
        "login": "Είσοδος",
        "nav-login-createaccount": "Είσοδος / δημιουργία λογαριασμού",
-       "loginprompt": "Πρέπει να έχετε ενεργοποιήσει τα cookies για να συνδεθείτε στον ιστοχώρο {{SITENAME}}.",
        "userlogin": "Είσοδος / δημιουργία λογαριασμού",
        "userloginnocreate": "Είσοδος",
        "logout": "Έξοδος",
        "gotaccountlink": "Είσοδος",
        "userlogin-resetlink": "Ξεχάσατε τα στοιχεία εισόδου σας;",
        "userlogin-resetpassword-link": "Ξεχάσατε τον κωδικό πρόσβασης;",
-       "userlogin-loggedin": "Είστε ήδη {{GENDER:$1|συνδεδεμένος|συνδεδεμένη}} ως $1.\nΧρησιμοποιήστε την παρακάτω φόρμα για να συνδεθείτε ως άλλος χρήστης.",
-       "userlogin-createanother": "Δημιουργήσετε έναν άλλο λογαριασμό",
+       "userlogin-helplink2": "Βοήθεια για τη σύνδεση",
        "createacct-emailrequired": "Διεύθυνση ηλεκτρονικού ταχυδρομείου",
        "createacct-emailoptional": "Διεύθυνση ηλεκτρονικού ταχυδρομείου (προαιρετικό)",
        "createacct-email-ph": "Εισάγετε το email σας",
        "resetpass-submit-cancel": "Ακύρωση",
        "resetpass-wrong-oldpass": "Λάθος προσωρινός ή κανονικός κωδικός.\nΜπορεί να έχετε ήδη αλλάξει επιτυχώς τον κωδικό σας ή να έχετε ζητήσει έναν νέο προσωρινό κωδικό.",
        "resetpass-recycled": "Παρακαλούμε επαναφέρετε τον κωδικό πρόσβασής σας σε κάτι διαφορετικό από τον τρέχοντα κωδικό πρόσβασης.",
+       "resetpass-temp-emailed": "Έχετε συνδεθεί με ένα προσωρινό κωδικό μέσω ηλεκτρονικού ταχυδρομείου.\nΓια να ολοκληρώσετε τη σύνδεση, πρέπει να ορίσετε ένα νέο κωδικό εδώ:",
        "resetpass-temp-password": "Προσωρινός κωδικός:",
        "resetpass-abort-generic": "Η αλλαγή του κωδικού έχει απορριφθεί από μια προέκταση.",
        "resetpass-expired": "Τον κωδικό πρόσβασής σας έχει λήξει. Ορίστε ένα νέο κωδικό πρόσβασης για να συνδεθείτε.",
+       "resetpass-expired-soft": "Ο κωδικός πρόσβασής σας έχει λήξει και πρέπει να γίνει επαναφορά του. Παρακαλούμε γράψτε ένα νέο κωδικό πρόσβασης ή κάντε κλικ στο \"{{int:resetpass-submit-cancel}}\" για τον επαναφέρετε αργότερα.",
        "resetpass-validity-soft": "Τον κωδικό πρόσβασής σας δεν είναι έγκυρος: $1 \nΠαρακαλώ επιλέξτε ένα νέο κωδικό πρόσβασης τώρα, ή κάντε κλικ στο κουμπί \"{{int:resetpass-submit-cancel}}\" για να το επαναφέρετε αργότερα.",
        "passwordreset": "Κωδικός επαναφοράς",
        "passwordreset-text-one": "Συμπληρώστε την παρακάτω φόρμα για να επαναφέρετε τον κωδικό πρόσβασής σας.",
        "preview": "Προεπισκόπηση",
        "showpreview": "Εμφάνιση προεπισκόπησης",
        "showdiff": "Εμφάνιση αλλαγών",
-       "anoneditwarning": "'''Προειδοποίηση:''' Δεν έχετε συνδεθεί. Η διεύθυνση IP σας θα καταγραφεί στο ιστορικό επεξεργασίας αυτής της σελίδας.",
+       "blankarticle": "<strong>Προειδοποίηση:</strong> Η σελίδα που δημιουργείτε είναι κενή.\nΕάν κάνετε κλικ στο κουμπί \"{{int:savearticle}}\" και πάλι, η σελίδα θα δημιουργηθεί χωρίς κανένα περιεχόμενο.",
+       "anoneditwarning": "<strong>Προειδοποίηση:</strong> Δεν έχετε συνδεθεί. Η διεύθυνση IP σας θα είναι ορατή δημόσια αν κάνετε κάποια επεξεργασία. Αν <strong>[$1 συνδεθείτε]</strong> ή <strong>[$2 δημιουργήσετε λογαριασμό]</strong>, οι επεξεργασίες σας θα αποδοθούν στο όνομά χρήστη σας, μαζί με άλλα οφέλη.",
        "anonpreviewwarning": "''Δεν έχετε συνδεθεί. Η αποθήκευση θα καταγράψει την διεύθυνσή IP σας στο ιστορικό επεξεργασίας αυτής της σελίδας.''",
        "missingsummary": "'''Υπενθύμιση:''' Δεν έχετε συμπληρώσει τη σύνοψη επεξεργασίας. Αν κάνετε κλικ στο κουμπί Αποθήκευση πάλι, η επεξεργασία σας θα αποθηκευτεί χωρίς σύνοψη.",
        "missingcommenttext": "Παρακαλώ εισάγετε ένα σχόλιο παρακάτω.",
        "nonunicodebrowser": "'''ΠΡΟΣΟΧΗ! Ο περιηγητής σας δεν είναι συμβατός με κωδικοποίηση Unicode.'''\nΓια την ασφαλή επεξεργασία των σελίδων έχει βρεθεί ένας εναλλακτικός τρόπος: Όσοι χαρακτήρες δεν είναι ASCII θα φαίνονται στο πλαίσιο επεξεργασίας ως δεκαεξαδικοί κωδικοί.",
        "editingold": "'''Προειδοποίηση: Επεξεργάζεστε μια παλιότερη αναθεώρηση αυτής της σελίδας.'''\nΑν την αποθηκεύσετε, όσες αλλαγές έχουν γίνει μετά από αυτή την αναθεώρηση θα χαθούν.",
        "yourdiff": "Διαφορές",
-       "copyrightwarning": "Î\9fλεÏ\82 Î¿Î¹ Ï\83Ï\85νειÏ\83Ï\86οÏ\81έÏ\82 Ï\83Ï\84ο {{SITENAME}} Î¸ÎµÏ\89Ï\81οÏ\8dνÏ\84αι Ï\8cÏ\84ι Î´Î·Î¼Î¿Ï\83ιεÏ\8dονÏ\84αι Ï\83Ï\8dμÏ\86Ï\89να Î¼Îµ Ï\84ην $2 (Î\92λ. $1 Î³Î¹Î± Î»ÎµÏ\80Ï\84ομέÏ\81ειεÏ\82).\nÎ\91ν Î´ÎµÎ½ ÎµÏ\80ιθÏ\85μείÏ\84ε Ï\84α ÎºÎµÎ¯Î¼ÎµÎ½Î¬ Ï\83αÏ\82 Î½Î± Ï\84α ÎµÏ\80εξεÏ\81γαÏ\83Ï\84οÏ\8dν ÎºÎ±Ï\84ά Ï\84ην ÎºÏ\81ίÏ\83η Ï\84οÏ\85Ï\82 Î¬Î»Î»Î¿Î¹ Ï\87Ï\81ήÏ\83Ï\84εÏ\82 ÎºÎ±Î¹ Î½Î± Ï\84α Î´Î¹Î±Î´Ï\8eÏ\83οÏ\85ν ÎºÎ±Ï\84ά Î²Î¿Ï\8dληÏ\83η, Ï\80αÏ\81ακαλοÏ\8dμε Î½Î± Î¼Î·Î½ Ï\84α Î±Î½Î±Ï\81Ï\84ήÏ\83εÏ\84ε Ï\83ε Î±Ï\85Ï\84Ï\8c Ï\84ο Ï\87Ï\8eÏ\81ο. Î\8c\84ι Ï\83Ï\85νειÏ\83Ï\86έÏ\81εÏ\84ε Ï\83Ï\84ο Ï\87Ï\8eÏ\81ο Î±Ï\85Ï\84Ï\8c Ï\83ε ÎºÎµÎ¯Î¼ÎµÎ½Î±, Î´Î¹Î±Î³Ï\81άμμαÏ\84α, Ï\83Ï\84οιÏ\87εία Î® ÎµÎ¹ÎºÏ\8cνεÏ\82 Ï\80Ï\81έÏ\80ει Î½Î± ÎµÎ¯Î½Î±Î¹ Î´Î¹ÎºÎ¬ Ï\83αÏ\82 Î­Ï\81γα Î® Î½Î± Î±Î½Î®ÎºÎ¿Ï\85ν Ï\83Ï\84ο Î´Î·Î¼Ï\8cÏ\83ιο Ï\84ομέα (public domain) Î® Î½Î± Ï\80Ï\81οέÏ\81Ï\87ονÏ\84αι Î±Ï\80Ï\8c ÎµÎ»ÎµÏ\8dθεÏ\81εÏ\82 Î® Î±Î½Î¿Î¹Ï\87Ï\84έÏ\82 Ï\80ηγέÏ\82 Î¼Îµ Ï\81ηÏ\84ή Î¬Î´ÎµÎ¹Î± Î±Î½Î±Î´Î·Î¼Î¿Ï\83ίεÏ\85Ï\83ηÏ\82.<br />\nΤέλοÏ\82 Î²ÎµÎ²Î±Î¹Ï\8eνεÏ\84ε Ï\80Ï\89Ï\82 Ï\8c\84ι Î³Ï\81άÏ\86εÏ\84ε Ï\83ε Î±Ï\85Ï\84Ï\8c Ï\84ον Ï\87Ï\8eÏ\81ο ÎµÎ¯Î½Î±Î¹ Ï\80Ï\81Ï\89Ï\84Ï\8cÏ\84Ï\85Ï\80ο Î´Î¹ÎºÏ\8c Ï\83αÏ\82 Î­Ï\81γο ÎºÎ±Î¹, Î¬Ï\83Ï\87εÏ\84α Î¼Îµ Ï\84ην Î­ÎºÏ\84αÏ\83ή Ï\84οÏ\85, Î´ÎµÎ½ Î­Ï\87ει ÎµÎºÏ\87Ï\89Ï\81ηθεί Ï\83ε Ï\84Ï\81ίÏ\84οÏ\85Ï\82 Î· Î´Î·Î¼Î¿Ï\83ίεÏ\85Ï\83η ÎºÎ±Î¹ Î· ÎµÎºÎ¼ÎµÏ\84άλλεÏ\85Ï\83ή Ï\84οÏ\85.\n'''ΠÎ\91ΡÎ\91Î\9aÎ\91Î\9bÎ\9fÎ¥Î\9cÎ\95 Î\9dÎ\91 Î\9cÎ\97Î\9d Î\91Î\9dÎ\91ΡΤÎ\97ΣÎ\95ΤÎ\95 Î\9aÎ\95Î\99Î\9cÎ\95Î\9dÎ\91 Î¤Î¡Î\99ΤΩÎ\9d Î\95Î\91Î\9d Î\94Î\95Î\9d Î\95ΧÎ\95ΤÎ\95 Î¤Î\97Î\9d Î\91Î\94Î\95Î\99Î\91 Î¤Î\9fÎ¥ Î\99Î\94Î\99Î\9fÎ\9aΤÎ\97ΤÎ\97 Î¤Î\9fÎ¥ COPYRIGHT!'''",
+       "copyrightwarning": "ΠαÏ\81ακαλοÏ\8dμε Ï\83ημειÏ\8eÏ\83Ï\84ε Ï\8cÏ\84ι Ï\8cλεÏ\82 Î¿Î¹ Ï\83Ï\85νειÏ\83Ï\86οÏ\81έÏ\82 Ï\83Ï\84ον Î¹Ï\83Ï\84Ï\8cÏ\84οÏ\80ο {{SITENAME}} Î¸ÎµÏ\89Ï\81οÏ\8dνÏ\84αι Ï\8cÏ\84ι Î´Î·Î¼Î¿Ï\83ιεÏ\8dονÏ\84αι Ï\83Ï\8dμÏ\86Ï\89να Î¼Îµ Ï\84ην $2 (βλ. $1 Î³Î¹Î± Î»ÎµÏ\80Ï\84ομέÏ\81ειεÏ\82).\nÎ\91ν Î´ÎµÎ½ ÎµÏ\80ιθÏ\85μείÏ\84ε Ï\84α ÎºÎµÎ¯Î¼ÎµÎ½Î¬ Ï\83αÏ\82 Î½Î± Ï\84α ÎµÏ\80εξεÏ\81γάζονÏ\84αι Î±Î½Î·Î»ÎµÏ\8eÏ\82 Î¬Î»Î»Î¿Î¹ Ï\87Ï\81ήÏ\83Ï\84εÏ\82 ÎºÎ±Î¹ Î½Î± Ï\84α Î´Î¹Î±Î´Î¯Î´Î¿Ï\85ν ÎºÎ±Ï\84ά Î²Î¿Ï\8dληÏ\83η, Ï\84Ï\8cÏ\84ε Î½Î± Î¼Î·Î½ Ï\84α Ï\85Ï\80οβάλλεÏ\84ε ÎµÎ´Ï\8e.<br />Î\9cαÏ\82 Ï\85Ï\80Ï\8cÏ\83Ï\87εÏ\83Ï\84ε ÎµÏ\80ίÏ\83ηÏ\82 Ï\8cÏ\84ι Î±Ï\85Ï\84Ï\8c Ï\84ο Î³Ï\81άÏ\88αÏ\84ε Î¼Ï\8cνοι Ï\83αÏ\82 Î® Ï\84ο Î±Î½Ï\84ιγÏ\81άÏ\88αÏ\84ε Î±Ï\80Ï\8c ÎºÎ¬Ï\80οια ÎµÎ»ÎµÏ\8dθεÏ\81η Ï\80ηγή Ï\89Ï\82 ÎºÎ¿Î¹Î½Ï\8c ÎºÏ\84ήμα Î® ÎºÎ¬Ï\84ι Î±Î½Î¬Î»Î¿Î³Î¿.\n<strong>Î\9cην Ï\85Ï\80οβάλλεÏ\84ε Î´Î¿Ï\85λειά Ï\80οÏ\85 Ï\80Ï\81οÏ\83Ï\84αÏ\84εÏ\8dεÏ\84αι Î±Ï\80Ï\8c Ï\80νεÏ\85μαÏ\84ικά Î´Î¹ÎºÎ±Î¹Ï\8eμαÏ\84α Ï\87Ï\89Ï\81ίÏ\82 Î¬Î´ÎµÎ¹Î±!</strong>",
        "copyrightwarning2": "Σημειώστε ότι όλες οι συνεισφορές στον ιστότοπο {{SITENAME}} μπορούν να υποστούν επεξεργασία, να αλλαχθούν, ή να αφαιρεθούν από άλλους συνεισφέροντες. Αν δεν θέλετε τα γραπτά σας να υποστούν επεξεργασία κατά βούληση, τότε μην τα τοποθετήσετε σε αυτό το χώρο.<br />\nΕπίσης μας υπόσχεστε πως ό,τι γράφετε είναι δικό σας, ή αντιγραμμένο από μια πηγή που είναι κοινό κτήμα, ή μια παρόμοια ελεύθερη πηγή (δείτε $1 για λεπτομέρειες).\n'''ΠΑΡΑΚΑΛΟΥΜΕ ΝΑ ΜΗΝ ΤΟΠΟΘΕΤΕΙΤΕ ΠΝΕΥΜΑΤΙΚΑ ΚΑΤΟΧΥΡΩΜΕΝΟ ΕΡΓΟ ΧΩΡΙΣ ΑΔΕΙΑ!'''",
        "longpageerror": "'''Σφάλμα: Το κείμενο που καταχωρήσατε έχει μήκος {{PLURAL:$1|ένα kilobyte|$1 kilobytes}}, το οποίο είναι μεγαλύτερο από το μέγιστο {{PLURAL:$2|του ενός kilobyte|των $2 kilobytes}}.'''\nΔεν μπορεί να αποθηκευτεί.",
        "readonlywarning": "'''Προειδοποίηση: Η βάση δεδομένων έχει κλειδωθεί για συντήρηση, έτσι δεν θα μπορέσετε να αποθηκεύσετε τις επεξεργασίες σας αυτή τη στιγμή.'''\nΜπορείτε αν θέλετε να μεταφέρετε με αντιγραφή-επικόλληση το κείμενό σας σε αρχείο κειμένου και να το αποθηκεύσετε για αργότερα.\n\nΟ διαχειριστής που την κλείδωσε έδωσε την εξής εξήγηση: $1",
        "edit-gone-missing": "Δεν ήταν εφικτό να ενημερωθεί η σελίδα.\nΦαίνεται πως έχει διαγραφεί.",
        "edit-conflict": "Σύγκρουση επεξεργασιών.",
        "edit-no-change": "Η επεξεργασία σας αγνοήθηκε, επειδή δεν έγινε καμία αλλαγή στο κείμενο.",
+       "postedit-confirmation-created": "Η σελίδα έχει δημιουργηθεί.",
+       "postedit-confirmation-restored": "Η σελίδα έχει αποκατασταθεί.",
        "postedit-confirmation-saved": "H επεξεργασία σας αποθηκεύτηκε.",
        "edit-already-exists": "Δεν ήταν εφικτό να δημιουργηθεί η νέα σελίδα.\nΥπάρχει ήδη.",
        "defaultmessagetext": "Προεπιλεγμένο κείμενο μηνύματος",
        "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": "Η σελίδα υπερβαίνει το μέγιστο βάθος επέκτασης.",
        "expansion-depth-exceeded-warning": "Η σελίδα υπερέβη το βάθος επέκτασης",
        "parser-unstrip-loop-warning": "εντοπίστηκε ένας βρόχος unstrip",
        "parser-unstrip-recursion-limit": "Υπέρβαση του ορίου αναδρομής Unstrip ($1)",
        "undo-failure": "Η επεξεργασία δεν μπορούσε να αναστραφεί λόγω αντικρουόμενων ενδιάμεσων επεξεργασιών.",
        "undo-norev": "Η ανάκληση αυτής της επεξεργασίας δεν ηταν δυνατό να πραγματοποιηθεί επειδή δεν υπάρχει ή επειδή έχει διαγραφεί.",
        "undo-nochange": "Η επεξεργασία φαίνεται να έχει ήδη αναιρεθεί.",
-       "undo-summary": "Αναίρεση αναθεώρησης $1 υπό τον/την [[Special:Contributions/$2|$2]] ([[User talk:$2|Συζήτηση]])",
+       "undo-summary": "Αναίρεση αναθεώρησης $1 υπό τον/την [[Special:Contribs/$2|$2]] ([[User talk:$2|Συζήτηση]])",
        "undo-summary-username-hidden": "Αναίρεση αναθεώρησης $1 από ένα κρυμμένο χρήστη",
        "cantcreateaccounttitle": "Ο λογαριασμός δεν μπορεί να δημιουργηθεί",
        "cantcreateaccount-text": "Η δημιουργία λογαριασμού από αυτή τη διεύθυνση IP ('''$1''') έχει αποτραπεί από τον [[User:$3|$3]].\n\nΟ λόγος που δόθηκε από τον $3 είναι ''$2''",
        "currentrev": "Τρέχουσα αναθεώρηση",
        "currentrev-asof": "Τελευταία αναθεώρηση της $1",
        "revisionasof": "Αναθεώρηση της $1",
-       "revision-info": "Î\91ναθεÏ\8eÏ\81ηÏ\83η Ï\84ηÏ\82 $1 Ï\85Ï\80Ï\8c {{GENDER:$6|Ï\84ον|Ï\84ην}} $2",
+       "revision-info": "Î\91ναθεÏ\8eÏ\81ηÏ\83η Ï\89Ï\82 Ï\80Ï\81οÏ\82 $1 Î±Ï\80Ï\8c {{GENDER:$6|Ï\84ον|Ï\84ην}} $2 $7",
        "previousrevision": "&larr;Παλαιότερη αναθεώρηση",
        "nextrevision": "Νεώτερη αναθεώρηση &rarr;",
        "currentrevisionlink": "Τελευταία αναθεώρηση",
        "rev-deleted-event": "(η καταγραφή στο αρχείο αφαιρέθηκε)",
        "rev-deleted-user-contribs": "[όνομα χρήστη ή διεύθυνση ΙΡ έχουν αφαιρεθεί - η επεξεργασία έχει αποκρυφθεί από τις συνεισφορές]",
        "rev-deleted-text-permission": "Αυτή η αναθεώρηση της σελίδας έχει '''διαγραφεί'''.\nΜπορεί να υπάρχουν λεπτομέρειες στο [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} αρχείο καταγραφής διαγραφών].",
+       "rev-suppressed-text-permission": "Αυτή η έκδοση της σελίδας έχει '''κατασταλεί'''.\nΛεπτομέρειες μπορούν να βρεθούν στο [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} αρχείο καταστολής].",
        "rev-deleted-text-unhide": "Αυτή η έκδοση σελίδας '''διεγράφη'''.\nΠερισσότερες λεπτομέρειες μπορούν να βρεθούν στο [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ιστορικό διαγραφών].\nΜπορείτε ακόμη να [$1 δείτε αυτήν την αναθεώρηση] αν επιθυμείτε να συνεχίσετε.",
        "rev-suppressed-text-unhide": "Αυτή η έκδοση της σελίδας έχει '''αποκρυφθεί'''.\nΜπορεί να υπάρχουν λεπτομέρειες στο [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} αρχείο απόκρυψης].\nΜπορείτε ακόμα [$1 να δείτε την έκδοση] αν επιθυμείτε να συνεχίσετε.",
        "rev-deleted-text-view": "Αυτή η αναθεώρηση της σελίδας έχει '''διαγραφεί'''.\nΜπορείτε να την δείτε. Λεπτομέρειες μπορούν να βρεθούν στο [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} αρχείο καταγραφής διαγραφών].",
        "revdelete-no-file": "Το αρχείο που καθορίσατε δεν υπάρχει.",
        "revdelete-show-file-confirm": "Είστε σίγουροι ότι θέλετε να δείτε μία διεγραμμένη αναθεώρηση του αρχείου \"<nowiki>$1</nowiki>\" από τις $2 στις $3;",
        "revdelete-show-file-submit": "Ναι",
-       "revdelete-selected-text": "'''{{PLURAL:$2|Επιλεγμένη έκδοση|Επιλεγμένες εκδόσεις}} της [[:$1]]:'''",
+       "revdelete-selected-text": "{{PLURAL:$1|Επιλεγμένη έκδοση|Επιλεγμένες εκδόσεις}} της [[:$2]]:",
        "logdelete-selected": "{{PLURAL:$1|Επιλεγμένο γεγονός αρχείου καταγραφής|Επιλεγμένα γεγονότα αρχείου καταγραφής}}:",
        "revdelete-confirm": "Παρακαλούμε επιβεβαιώστε ότι σκοπεύετε να το κάνετε αυτό, ότι αντιλαμβάνεσθε τις συνέπειες, και ότι το κάνετε σύμφωνα με την [[{{MediaWiki:Policy-url}}|πολιτική]].",
        "revdelete-suppress-text": "Η καταστολή μπορεί να χρησιμοποιηθεί <strong> μόνο </strong> για τις ακόλουθες περιπτώσεις:\n* Ενδεχόμενη συκοφαντική δυσφήμιση\n* Ακατάλληλες προσωπικές πληροφορίες\n*: <em>διευθύνσεις κατοικίας και αριθμοί τηλεφώνου, αριθμοί ταυτότητας, κλπ. </em>",
        "searchprofile-advanced-tooltip": "Αναζήτηση σε προσαρμοσμένους ονοματοχώρους",
        "search-result-size": "$1 ({{PLURAL:$2|1 λέξη|$2 λέξεις}})",
        "search-result-category-size": "{{PLURAL:$1|1 μέλος|$1 μέλη}} ({{PLURAL:$2|1 υποκατηγορία|$2 υποκατηγορίες}}, {{PLURAL:$3|1 αρχείο|$3 αρχεία}})",
-       "search-result-score": "Σχετικότητα: $1%",
        "search-redirect": "(ανακατεύθυνση $1)",
        "search-section": "(ενότητα $1)",
        "search-file-match": "(ταιριάζει με το περιεχόμενο του αρχείου)",
        "search-relatedarticle": "Σχετικά",
        "searchrelated": "σχετικά",
        "searchall": "όλα",
-       "showingresults": "Î\94είÏ\84ε Ï\80αÏ\81ακάÏ\84Ï\89 Î¼Î­Ï\87Ï\81ι Ï\84α {{PLURAL:$1|'''1'''αÏ\80οÏ\84έλεÏ\83μα|'''$1''' Î±Ï\80οÏ\84ελέÏ\83μαÏ\84α}} Î¾ÎµÎºÎ¹Î½Ï\8eνÏ\84αÏ\82 Î¼Îµ #'''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|Αποτέλεσμα '''$1''' από '''$3'''|Αποτελέσματα '''$1 - $2''' από '''$3'''}} για '''$4'''",
+       "showingresults": "ΠαÏ\81ακάÏ\84Ï\89 {{PLURAL:$1|εμÏ\86ανίζεÏ\84αι Î¼Î­Ï\87Ï\81ι <strong>1</strong> Î±Ï\80οÏ\84έλεÏ\83μα|εμÏ\86ανίζονÏ\84αι Î¼Î­Ï\87Ï\81ι <strong>$1</strong> Î±Ï\80οÏ\84ελέÏ\83μαÏ\84α}} Î¾ÎµÎºÎ¹Î½Ï\8eνÏ\84αÏ\82 Î±Ï\80Ï\8c Ï\84ο Î\9dο <strong>$2</strong>.",
+       "showingresultsinrange": "Παρακάτω {{PLURAL:$1|εμφανίζεται μέχρι <strong>1</strong> αποτέλεσμα|εμφανίζονται μέχρι <strong>$1</strong> αποτελέσματα}} σε εύρος από το Νο <strong>$2</strong> μέχρι το Νο <strong>$3</strong>.",
        "search-nonefound": "Δεν υπάρχουν αποτελέσματα που να ικανοποιούν το ερώτημα.",
        "powersearch-legend": "Αναλυτική αναζήτηση",
        "powersearch-ns": "Αναζήτηση στις περιοχές ονομάτων:",
        "preferences": "Προτιμήσεις",
        "mypreferences": "Προτιμήσεις",
        "prefs-edits": "Αριθμός επεξεργασιών:",
-       "prefsnologintext2": "Παρακαλούμε $1 για να αλλάξετε τις προτιμήσεις σας.",
+       "prefsnologintext2": "Παρακαλώ συνδεθείτε για να αλλάξετε τις προτιμήσεις σας.",
        "prefs-skin": "Οπτική οργάνωση (skin)",
        "skin-preview": "Προεπισκόπηση",
        "datedefault": "Χωρίς προτίμηση",
        "right-move": "Μετακίνηση σελίδων",
        "right-move-subpages": "Μετακίνηση σελίδων μαζί με τις υποσελίδες τους",
        "right-move-rootuserpages": "Μετακίνηση κεντρικών σελίδων χρηστών",
+       "right-move-categorypages": "Μετακίνηση σελίδων κατηγοριών",
        "right-movefile": "Μετακίνηση αρχείων",
        "right-suppressredirect": "Μη δημιουργία ανακατεύθυνσης από το παλιό όνομα κατά τη μετακίνηση μιας σελίδας",
        "right-upload": "Επιφόρτωση αρχείων",
        "right-browsearchive": "Αναζήτηση στις διαγραμμένες σελίδες",
        "right-undelete": "Ανάκληση διαγραφής μίας σελίδας",
        "right-suppressrevision": "Επιθεώρηση και αποκατάσταση αναθεωρήσεων κρυμμένων από τους διαχειριστές",
+       "right-viewsuppressed": "Προβολή αναθεωρήσεων κρυμμένων από κάθε χρήστη",
        "right-suppressionlog": "Προβολή ιδιωτικών καταγραφών",
        "right-block": "Φραγή άλλων χρηστών από την επεξεργασία",
        "right-blockemail": "Φραγή ενός χρήστη από την αποστολή ηλεκτρονικών μηνυμάτων",
        "action-move": "να μετακινήσετε αυτή τη σελίδα",
        "action-move-subpages": "να μετακινήσετε αυτή τη σελίδα, καθώς και τις υποσελίδες της",
        "action-move-rootuserpages": "να μετακινήσετε κεντρικές σελίδες χρηστών",
+       "action-move-categorypages": "μετακίνηση σελίδων κατηγοριών",
        "action-movefile": "να μετακινήσετε αυτό το αρχείο",
        "action-upload": "να επιφορτώσετε αυτό το αρχείο",
        "action-reupload": "να ανεβάσετε νέα έκδοση αυτού του υπάρχοντος αρχείου",
        "recentchanges-legend-heading": "'''Υπόμνημα:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (δείτε [[Special:NewPages|κατάλογος νέων σελίδων]])",
        "rcnotefrom": "Παρακάτω είναι οι αλλαγές από τις <strong>$2</strong>  (εμφανίζονται μέχρι <strong>$1</strong> ).",
-       "rclistfrom": "Εμφάνιση νέων αλλαγών αρχίζοντας από $3 $2",
+       "rclistfrom": "Εμφάνιση νέων αλλαγών αρχίζοντας από τις $3 στις $2",
        "rcshowhideminor": "$1 μικροεπεξεργασιών",
        "rcshowhideminor-show": "Εμφάνιση",
        "rcshowhideminor-hide": "Απόκρυψη",
        "largefileserver": "Το μέγεθος αυτού του αρχείο είναι μεγαλύτερο από το μέγιστο μέγεθος που ο εξυπηρετητής είναι ρυθμισμένος να επιτρέπει.",
        "emptyfile": "Το αρχείο που φορτώσατε φαίνεται να είναι κενό. Αυτό μπορεί να οφείλεται σε λάθος πληκτρολόγησης του ονόματος του αρχείου. Παρακαλούμε ελέγξτε εαν αυτό είναι πραγματικά το αρχείο που θέλετε να φορτώσετε.",
        "windows-nonascii-filename": "Αυτό το wiki δεν υποστηρίζει ονόματα αρχείων με ειδικούς χαρακτήρες.",
-       "fileexists": "Υπάρχει ήδη αρχείο με αυτό το όνομα, παρακαλούμε ελέγξτε το <strong>[[:$1]]</strong> εάν δεν είστε σίγουρος/η αν θέλετε να το αλλάξετε.\n[[$1|thumb]]",
+       "fileexists": "Υπάρχει ήδη αρχείο με αυτό το όνομα, παρακαλούμε ελέγξτε το <strong>[[:$1]]</strong> εάν δεν είστε {{GENDER:|σίγουρος|σίγουρη}} αν θέλετε να το αλλάξετε.\n[[$1|thumb]]",
        "filepageexists": "Η σελίδα περιγραφής για αυτό το αρχείο δημιουργήθηκε ήδη στο <strong>[[:$1]]</strong>, αλλά κανένα αρχείο με αυτό το όνομα δεν υπάρχει αυτή τη στιγμή.\nΗ περιγραφἠ που θα εισάγετε δεν θα εμφανιστεί στη σελίδα περιγραφής.\nΓια να εμφανιστεί η περιγραφή σας εκεί, θα πρέπει να την επεξεργαστείτε χειροκίνητα.\n[[$1|thumb]]",
-       "fileexists-extension": "Î\88να Î±Ï\81Ï\87είο Î¼Îµ Ï\80αÏ\81Ï\8cμοιο Ï\8cνομα Ï\85Ï\80άÏ\81Ï\87ει: [[$2|thumb]]\n* Î\8cνομα Ï\84οÏ\85 Ï\80Ï\81οÏ\82 ÎµÏ\80ιÏ\86Ï\8cÏ\81Ï\84Ï\89Ï\83η Î±Ï\81Ï\87είοÏ\85: <strong>[[:$1]]</strong>\n* Î\8cνομα Ï\85Ï\80άÏ\81Ï\87ονÏ\84οÏ\82 Î±Ï\81Ï\87είοÏ\85: <strong>[[:$2]]</strong>\nΠαÏ\81ακαλÏ\8e Î´Î¹Î±Î»Î­Î¾Ï\84ε Î­Î½Î± Î´Î¹Î±Ï\86οÏ\81εÏ\84ικÏ\8c Ï\8cνομα.",
+       "fileexists-extension": "Î¥Ï\80άÏ\81Ï\87ει Î­Î½Î± Î±Ï\81Ï\87είο Î¼Îµ Ï\80αÏ\81Ï\8cμοιο Ï\8cνομα: [[$2|thumb]]\n* Î\8cνομα Ï\84οÏ\85 Ï\80Ï\81οÏ\82 Î±Î½Î­Î²Î±Ï\83μα Î±Ï\81Ï\87είοÏ\85: <strong>[[:$1]]</strong>\n* Î\8cνομα Ï\85Ï\80άÏ\81Ï\87ονÏ\84οÏ\82 Î±Ï\81Ï\87είοÏ\85: <strong>[[:$2]]</strong>\nÎ\9cήÏ\80Ï\89Ï\82 Î¸Î± Î¸Î­Î»Î±Ï\84ε Î½Î± Ï\87Ï\81ηÏ\83ιμοÏ\80οιήÏ\83εÏ\84ε ÎºÎ¬Ï\80οιο Ï\8cνομα Ï\80οÏ\85 Î½Î± Î¾ÎµÏ\87Ï\89Ï\81ίζει Ï\80εÏ\81ιÏ\83Ï\83Ï\8cÏ\84εÏ\81ο;",
        "fileexists-thumbnail-yes": "Το αρχείο φαίνεται ότι είναι μια εικόνα μειωμένου μεγέθους ''(μικρογραφία)''. [[$1|thumb]]\nΠαρακαλώ ελέγξτε το αρχείο <strong>[[:$1]]</strong>.\nΑν το ελεγμένο αρχείο είναι η ίδια εικόνα στο αρχικό μέγεθος δεν είναι απαραίτητο να επιφορτώσετε μια επιπλέον μικρογραφία.",
        "file-thumbnail-no": "Το όνομα αρχείου αρχίζει με <strong>$1</strong>.\nΦαίνεται πως είναι μια εικόνα μειωμένου μεγέθους ''(μικρογραφία)''.\nΑν έχετε αυτή την εικόνα σε πλήρη ανάλυση, επιφορτώστε τη, αλλιώς αλλάξτε παρακαλώ το όνομα του αρχείου.",
        "fileexists-forbidden": "Ένα αρχείο με αυτό το όνομα υπάρχει ήδη˙ εάν ακόμη θέλετε να επιφορτώσωτε αυτό το αρχείο παρακαλώ πηγαίνετε πίσω και επιφορτώστε το υπό ένα νέο όνομα. [[File:$1|thumb|center|$1]]",
        "uploadwarning": "Προειδοποίηση φόρτωσης",
        "uploadwarning-text": "Παρακαλώ αλλάξτε την περιγραφή του αρχείου παρακάτω και προσπαθήστε ξανά.",
        "savefile": "Αποθήκευση αρχείου",
-       "uploadedimage": "ανέβασε το «[[$1]]»",
-       "overwroteimage": "ανέβασμα νέας έκδοσης του \"[[$1]]\"",
        "uploaddisabled": "Το ανέβασμα αρχείων είναι απενεργοποιημένο.",
        "copyuploaddisabled": "Το ανέβασμα μέσω URL έχει απενεργοποιηθεί.",
        "uploaddisabledtext": "Το ανέβασμα αρχείων είναι απενεργοποιημένο.",
        "license-header": "Αδειοδότηση",
        "nolicense": "Καμία επιλεγμένη",
        "license-nopreview": "(Μη διαθέσιμη προεπισκόπηση)",
-       "upload_source_url": " (ένα έγκυρο, δημόσια προσβάσιμο URL)",
-       "upload_source_file": " (ένα αρχείο στον υπολογιστή σας)",
+       "upload_source_url": "(το επιλεγμένο σας αρχείο από μια έγκυρη, δημόσια προσβάσιμη διεύθυνση URL)",
+       "upload_source_file": "(το επιλεγμένο αρχείο από τον υπολογιστή σας)",
+       "listfiles-delete": "διαγραφή",
        "listfiles-summary": "Αυτή η ειδική σελίδα δείχνει όλα τα επιφορτωμένα αρχεία.",
        "listfiles_search_for": "Αναζήτηση για όνομα πολυμέσου:",
        "imgfile": "αρχείο",
        "listfiles_size": "Μέγεθος",
        "listfiles_description": "Περιγραφή",
        "listfiles_count": "Εκδόσεις",
+       "listfiles-show-all": "Συμπερίληψη παλαιών εκδόσεων των εικόνων",
        "listfiles-latestversion": "Τρέχουσα έκδοση",
        "listfiles-latestversion-yes": "Ναι",
        "listfiles-latestversion-no": "Όχι",
        "unusedtemplates": "Αχρησιμοποίητα πρότυπα",
        "unusedtemplatestext": "Αυτή η σελίδα περιέχει όλες τις σελίδες στην περιοχή ονομάτος των {{ns:template}}, οι οποίες δεν περιλαμβάνονται σε άλλη σελίδα. Θυμηθείτε να ελέγξετε για άλλους συνδέσμους προς τα πρότυπα πριν τα διαγράψετε.",
        "unusedtemplateswlh": "άλλοι σύνδεσμοι",
-       "randompage": "ΤÏ\85Ï\87αίο Î»Î®Î¼Î¼α",
+       "randompage": "ΤÏ\85Ï\87αία Ï\83ελίδα",
        "randompage-nopages": "Δεν υπάρχουν σελίδες {{PLURAL:$2|στον ακόλουθο ονοματοχώρο|στους ακόλουθους ονοματοχώρους}}: $1.",
        "randomincategory": "Τυχαία σελίδα στην κατηγορία",
        "randomincategory-invalidcategory": "Το «$1» δεν είναι έγκυρο όνομα κατηγορίας.",
        "randomincategory-nopages": "Δεν υπάρχουν σελίδες στην κατηγορία [[:Category:$1|$1]].",
-       "randomincategory-selectcategory-submit": "Μετάβαση",
+       "randomincategory-category": "Κατηγορία:",
+       "randomincategory-legend": "Τυχαία σελίδα στην κατηγορία",
        "randomredirect": "Τυχαία ανακατεύθυνση",
        "randomredirect-nopages": "Δεν υπάρχουν ανακατευθύνσεις στον ονοματοχώρο \"$1\".",
        "statistics": "Στατιστικά",
        "statistics-header-pages": "Στατιστικά σελίδων",
        "statistics-header-edits": "Στατιστικά επεξεργασιών",
-       "statistics-header-views": "Î\95μÏ\86άνιÏ\83η στατιστικών",
+       "statistics-header-views": "ΠÏ\81οβολή στατιστικών",
        "statistics-header-users": "Στατιστικά χρηστών",
        "statistics-header-hooks": "Άλλα στατιστικά",
        "statistics-articles": "Σελίδες περιεχομένου",
        "pageswithprop-submit": "Μετάβαση",
        "doubleredirects": "Διπλές ανακατευθύνσεις",
        "doubleredirectstext": "Αυτή η σελίδα συγκαταλέγει σελίδες οι οποίες ανακατευθύνουν σε άλλες σελίδες ανακατεύθυνσης. Κάθε σειρά περιέχει συνδέσμους προς την πρώτη και τη δεύτερη σελίδα ανακατεύθυνσης, όπως επίσης και την πρώτη αράδα του κειμένου στη δεύτερη σελίδα ανακατεύθυνσης η οποία και είναι, κανονικά, ο πραγματικός προορισμός της ανακατεύθυνσης -εκεί δηλαδή όπου θα έπρεπε να είχατε οδηγηθεί από την αρχή. Τα <del>διεγραμμένα</del> λήμματα έχουν επιλυθεί.",
-       "double-redirect-fixed-move": "Η [[$1]] έχει μετακινηθεί, τώρα είναι ανακατεύθυνση στην [[$2]]",
-       "double-redirect-fixed-maintenance": "Î\94ιÏ\8cÏ\81θÏ\89Ï\83η Î´Î¹Ï\80λήÏ\82 Î±Î½Î±ÎºÎ±Ï\84εÏ\8dθÏ\85νÏ\83ηÏ\82 Î±Ï\80Ï\8c Ï\84ο [[$1]] Ï\83Ï\84ο [[$2]].",
+       "double-redirect-fixed-move": "Η [[$1]] έχει μετακινηθεί.\nΕνημερώθηκε αυτόματα και τώρα είναι ανακατεύθυνση στην [[$2]].",
+       "double-redirect-fixed-maintenance": "Î\91Ï\85Ï\84Ï\8cμαÏ\84η Î´Î¹Ï\8cÏ\81θÏ\89Ï\83η Î´Î¹Ï\80λήÏ\82 Î±Î½Î±ÎºÎ±Ï\84εÏ\8dθÏ\85νÏ\83ηÏ\82 Î±Ï\80Ï\8c [[$1]] Ï\83ε [[$2]] Ï\83ε ÎµÏ\81γαÏ\83ία Ï\83Ï\85νÏ\84ήÏ\81ηÏ\83ηÏ\82.",
        "double-redirect-fixer": "Διορθωτής ανακατευθύνσεων",
        "brokenredirects": "Λανθασμένες ανακατευθύνσεις",
        "brokenredirectstext": "Οι παρακάτω ανακατευθύνσεις οδηγούν σε σελίδες που δεν υπάρχουν:",
        "wantedfiletext-cat": "Τα ακόλουθα αρχεία χρησιμοποιούνται αλλά δεν υπάρχουν. Αρχεία από εξωτερικά αποθετήρια ενδέχεται να παρατίθενται παρότι υπάρχουν. Κάθε τέτοιες λανθασμένες αναφορές θα <del>διαγραμμίζονται</del>. Επιπλέον, σελίδες που ενσωματώνουν αρχεία που δεν υπάρχουν παρατίθενται στο [[:$1]].",
        "wantedfiletext-nocat": "Τα ακόλουθα αρχεία χρησιμοποιούνται αλλά δεν υπάρχουν. Πέρα από τα υπάρχοντα ενδέχεται να έχουν καταχωριστεί και αρχεία από εξωτερικές πηγές λογισμικού. Τέτοιες ψευδο-υπαρκτές καταχωρίσεις θα εμφανίζονται <del>διαγραμμισμένες</del>.",
        "wantedtemplates": "Ζητούμενα πρότυπα",
-       "mostlinked": "Î\9fι Ï\83ελίδεÏ\82 Î¼Îµ Ï\84ιÏ\82 Ï\80εÏ\81ιÏ\83Ï\83Ï\8cÏ\84εÏ\81εÏ\82 Î±Î½Î±Ï\86οÏ\81ές",
+       "mostlinked": "ΣελίδεÏ\82 Î¼Îµ Ï\84οÏ\85Ï\82 Ï\80εÏ\81ιÏ\83Ï\83Ï\8cÏ\84εÏ\81οÏ\85Ï\82 Ï\83Ï\85νδέÏ\83μοÏ\85Ï\82 Ï\80Ï\81οÏ\82 Î±Ï\85Ï\84ές",
        "mostlinkedcategories": "Περισσότερο χρησιμοποιούμενες κατηγορίες",
        "mostlinkedtemplates": "Περισσότερο χρησιμοποιούμενα πρότυπα",
-       "mostcategories": "Î\86Ï\81θÏ\81α με τις περισσότερες κατηγορίες",
+       "mostcategories": "ΣελίδεÏ\82 με τις περισσότερες κατηγορίες",
        "mostimages": "Περισσότερο χρησιμοποιούμενα αρχεία",
        "mostinterwikis": "Σελίδες με τους περισσότερους διαγλωσσικούς συνδέσμους",
-       "mostrevisions": "Î\86Ï\81θÏ\81α με τις περισσότερες αναθεωρήσεις",
+       "mostrevisions": "ΣελίδεÏ\82 με τις περισσότερες αναθεωρήσεις",
        "prefixindex": "Όλες οι σελίδες με πρόθεμα",
        "prefixindex-namespace": "Όλες οι σελίδες με πρόθεμα (ονοματοχώρος $1)",
        "prefixindex-strip": "Αφαίρεση του προθέματος στη λίστα",
        "protectedpages-page": "Σελίδα",
        "protectedpages-expiry": "Λήγει",
        "protectedpages-performer": "Προστασία χρήστη",
+       "protectedpages-params": "Παράμετροι προστασίας",
        "protectedpages-reason": "Αιτία",
        "protectedpages-unknown-timestamp": "Άγνωστο",
        "protectedpages-unknown-performer": "Άγνωστος χρήστης",
        "activeusers-noresult": "Δεν βρέθηκε χρήστης.",
        "listgrouprights": "Δικαιώματα ομάδων χρηστών",
        "listgrouprights-summary": "Ακόλουθεί μία λίστα με τις ομάδες χρηστών σε αυτό το wiki καθώς και με τα δικαιώματα πρόσβασης αυτών.\nΕνδέχεται να περιέχει [[{{MediaWiki:Listgrouprights-helppage}}|πρόσθετες πληροφορίες]] σχετικά με ατομικά δικαιώματα.",
-       "listgrouprights-key": "* <span class=\"listgrouprights-granted\">Δόθηκε δικαίωμα</span>\n* <span class=\"listgrouprights-revoked\">Ανακλήθηκε δικαίωμα</span>",
+       "listgrouprights-key": "Υπόμνημα:\n* <span class=\"listgrouprights-granted\">Χορηγηθέν δικαίωμα</span>\n* <span class=\"listgrouprights-revoked\">Ανακληθέν δικαίωμα</span>",
        "listgrouprights-group": "Ομάδα",
        "listgrouprights-rights": "Δικαιώματα",
        "listgrouprights-helppage": "Help:Δικαιώματα ομάδων",
        "listgrouprights-removegroup-self": "Μπορεί να αφαιρέσει {{PLURAL:$2|ομάδα|ομάδες}} από το δικό σας λογαριασμό: $1",
        "listgrouprights-addgroup-self-all": "Μπορεί να προσθέσει όλες τις ομάδες στο δικό σας λογαριασμό",
        "listgrouprights-removegroup-self-all": "Μπορεί να αφαιρέσει όλες τις ομάδες από το δικό σας λογαριασμό",
+       "listgrouprights-namespaceprotection-header": "Περιορισμοί ονοματοχώρων",
+       "listgrouprights-namespaceprotection-namespace": "Ονοματοχώρος",
+       "listgrouprights-namespaceprotection-restrictedto": "Δικαίωμα(τα) που επιτρέπει(ουν) σε χρήστη να επεξεργαστεί",
+       "trackingcategories": "Παρακολούθηση κατηγοριών",
+       "trackingcategories-name": "Όνομα μηνύματος",
+       "trackingcategories-desc": "Κριτήρια συμπερίληψης κατηγορίας",
+       "post-expand-template-inclusion-category-desc": "Το μέγεθος της σελίδας είναι μεγαλύτερο από <code>$wgMaxArticleSize</code> μετά την επέκταση όλων των προτύπων, έτσι ώστε ορισμένα πρότυπα δεν έχουν αναπτυχθεί.",
+       "hidden-category-category-desc": "Η κατηγορία περιέχει <code><nowiki>__HIDDENCAT__</nowiki></code> στο περιεχόμενο της σελίδας της, που την εμποδίζει εκ προεπιλογής να εμφανίζεται στο πλαίσιο συνδέσμων κατηγοριών των σελίδων.",
+       "trackingcategories-nodesc": "Καμία διαθέσιμη περιγραφή.",
+       "trackingcategories-disabled": "Η κατηγορία είναι απενεργοποιημένη",
        "mailnologin": "Δεν υπάρχει διεύθυνση παραλήπτη.",
        "mailnologintext": "Πρέπει να έχετε [[Special:UserLogin|συνδεθεί]] και να έχετε δηλώσει\nμια έγκυρη ηλεκτρονική διεύθυνση στις [[Special:Preferences|Προτιμήσεις]]\nγια να στείλετε e-mail σε άλλους χρήστες.",
        "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-short": "Η σελίδα «$1» έχει αφαιρεθεί από τη λίστα παρακολούθησής σας.",
        "watch": "Παρακολούθηση",
        "watchthispage": "Παρακολούθηση αυτής της σελίδας",
        "unwatch": "Παύση παρακολούθησης",
        "unwatchthispage": "Παύση παρακολούθησης αυτής της σελίδας",
        "notanarticle": "Η σελίδα αυτή δεν είναι σελίδα περιεχομένου.",
        "notvisiblerev": "Η έκδοση έχει διαγραφεί",
-       "watchlist-details": "{{PLURAL:$1|$1 σελίδα|$1 σελίδες}} στη λίστα παρακολούθησης σας, χωρίς να προσμετρούνται οι σελίδες συζήτησης.",
+       "watchlist-details": "{{PLURAL:$1|$1 Ï\83ελίδα|$1 Ï\83ελίδεÏ\82}} Ï\83Ï\84η Î»Î¯Ï\83Ï\84α Ï\80αÏ\81ακολοÏ\8dθηÏ\83ηÏ\82 Ï\83αÏ\82, Ï\87Ï\89Ï\81ίÏ\82 Î½Î± Ï\80Ï\81οÏ\83μεÏ\84Ï\81οÏ\8dνÏ\84αι Î¾ÎµÏ\87Ï\89Ï\81ιÏ\83Ï\84ά Î¿Î¹ Ï\83ελίδεÏ\82 Ï\83Ï\85ζήÏ\84ηÏ\83ηÏ\82.",
        "wlheader-enotif": "Η ειδοποίηση ηλεκτρονικού ταχυδρομείου ενεργοποιήθηκε.",
        "wlheader-showupdated": "Σελίδες που έχουν υποστεί αλλαγές από την τελευταία φορά που τις επισκεφθήκατε εμφανίζονται με '''έντονους χαρακτήρες'''.",
+       "wlnote": "Παρακάτω είναι {{PLURAL:$1|η πιο πρόσφατη αλλαγή|οι <strong>$1</strong> πιο πρόσφατες αλλαγές}} κατά τη διάρκεια {{PLURAL:$2|της τελευταίας ώρας|των <strong>$2</strong> τελευταίων ωρών}} ως προς τις $3 στις $4.",
        "wlshowlast": "Εμφάνιση των τελευταίων $1 ωρών $2 ημερών $3",
        "watchlist-options": "Επιλογές λίστας παρακολούθησης",
        "watching": "Παρακολούθηση...",
        "enotif_lastvisited": "Δείτε το $1 για όλες τις αλλαγές που έγιναν από την τελευταία σας επίσκεψη.",
        "enotif_lastdiff": "Δείτε το $1 για να εμφανίσετε αυτή την αλλαγή.",
        "enotif_anon_editor": "ανώνυμος χρήστης $1",
-       "enotif_body": "{{GENDER:$WATCHINGUSERNAME|Î\91γαÏ\80ηÏ\84έ|Î\91γαÏ\80ηÏ\84ή}} $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nΠεÏ\81ιγÏ\81αÏ\86ή ÎµÏ\80εξεÏ\81γαÏ\83ίαÏ\82: $PAGESUMMARY $PAGEMINOREDIT\n\nÎ\95Ï\80ικοινÏ\89νία Î¼Îµ Ï\84ο Ï\87Ï\81ήÏ\83Ï\84η Ï\80οÏ\85 Î­ÎºÎ±Î½Îµ Ï\84ην ÎµÏ\80εξεÏ\81γαÏ\83ία:\nηλεκÏ\84Ï\81ονική Î´Î¹ÎµÏ\8dθÏ\85νÏ\83η: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nÎ\94εν Î¸Î± Ï\85Ï\80άÏ\81ξοÏ\85ν Î¬Î»Î»ÎµÏ\82 ÎµÎ¹Î´Î¿Ï\80οιήÏ\83ειÏ\82 Ï\83ε Ï\80εÏ\81ίÏ\80Ï\84Ï\89Ï\83η Ï\80εÏ\81αιÏ\84έÏ\81Ï\89 Î´Ï\81αÏ\83Ï\84ηÏ\81ιÏ\8cÏ\84ηÏ\84αÏ\82 Î±Î½ Î´ÎµÎ½ ÎµÏ\80ιÏ\83κεÏ\86θείÏ\84ε Ï\84η Ï\83ελίδα. Î\9cÏ\80οÏ\81είÏ\84ε ÎµÏ\80ίÏ\83ηÏ\82 Î½Î± ÎµÏ\80αναÏ\86έÏ\81εÏ\84ε Ï\84ην ÎµÏ\80ιλογή ÎµÎ¹Î´Î¿Ï\80οίηÏ\83ηÏ\82 Î³Î¹Î± Ï\8cλεÏ\82 Ï\84ιÏ\82 Ï\80αÏ\81ακολοÏ\85θοÏ\8dμενεÏ\82 Ï\83ελίδεÏ\82 Ï\83Ï\84η Î»Î¯Ï\83Ï\84α Ï\80αÏ\81ακολοÏ\8dθηÏ\83ήÏ\82 Ï\83αÏ\82.\n\n                         Î¦Î¹Î»Î¹ÎºÎ¬,\n                         Tο σύστημα ειδοποίησης του ιστοχώρου {{SITENAME}}\n\n--\nΓια να αλλάξετε τις προτιμήσεις των ειδοποιήσεων ηλεκτρονικού ταχυδρομείου, επισκεφτείτε το\n{{canonicalurl:{{#special:Preferences}}}}\n\nΓια να αλλάξετε τις προτιμήσεις της λίστας παρακολούθησής σας, επισκεφτείτε το\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nΓια να διαγράψετε την σελίδα από την λίστα παρακολούθησής σας, επισκεφτείτε το\n$UNWATCHURL\n\nΠαρατηρήσεις και περισσότερη βοήθεια:\n$HELPPAGE",
+       "enotif_body": "{{GENDER:$WATCHINGUSERNAME|Î\91γαÏ\80ηÏ\84έ|Î\91γαÏ\80ηÏ\84ή}} $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nΠεÏ\81ιγÏ\81αÏ\86ή ÎµÏ\80εξεÏ\81γαÏ\83ίαÏ\82: $PAGESUMMARY $PAGEMINOREDIT\n\nÎ\95Ï\80ικοινÏ\89νία Î¼Îµ Ï\84ο Ï\87Ï\81ήÏ\83Ï\84η Ï\80οÏ\85 Î­ÎºÎ±Î½Îµ Ï\84ην ÎµÏ\80εξεÏ\81γαÏ\83ία:\nδιεÏ\8dθÏ\85νÏ\83η Î·Î»ÎµÎºÏ\84Ï\81ονικήÏ\82 Î±Î»Î»Î·Î»Î¿Î³Ï\81αÏ\86ίαÏ\82: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nÎ\94εν Î¸Î± Ï\85Ï\80άÏ\81ξοÏ\85ν Î¬Î»Î»ÎµÏ\82 ÎµÎ¹Î´Î¿Ï\80οιήÏ\83ειÏ\82 Ï\83ε Ï\80εÏ\81ίÏ\80Ï\84Ï\89Ï\83η Ï\80εÏ\81αιÏ\84έÏ\81Ï\89 Î´Ï\81αÏ\83Ï\84ηÏ\81ιÏ\8cÏ\84ηÏ\84αÏ\82 Î±Î½ Î´ÎµÎ½ ÎµÏ\80ιÏ\83κεÏ\86θείÏ\84ε Ï\84η Ï\83ελίδα Î­Ï\87ονÏ\84αÏ\82 ÎºÎ¬Î½ÎµÎ¹ Ï\83Ï\8dνδεÏ\83η. Î\9cÏ\80οÏ\81είÏ\84ε ÎµÏ\80ίÏ\83ηÏ\82 Î½Î± ÎµÏ\80αναÏ\86έÏ\81εÏ\84ε Ï\84ην ÎµÏ\80ιλογή ÎµÎ¹Î´Î¿Ï\80οίηÏ\83ηÏ\82 Î³Î¹Î± Ï\8cλεÏ\82 Ï\84ιÏ\82 Ï\80αÏ\81ακολοÏ\85θοÏ\8dμενεÏ\82 Ï\83ελίδεÏ\82 Ï\83Ï\84η Î»Î¯Ï\83Ï\84α Ï\80αÏ\81ακολοÏ\8dθηÏ\83ήÏ\82 Ï\83αÏ\82.\n\nΦιλικά, \nÏ\84ο σύστημα ειδοποίησης του ιστοχώρου {{SITENAME}}\n\n--\nΓια να αλλάξετε τις προτιμήσεις των ειδοποιήσεων ηλεκτρονικού ταχυδρομείου, επισκεφτείτε το\n{{canonicalurl:{{#special:Preferences}}}}\n\nΓια να αλλάξετε τις προτιμήσεις της λίστας παρακολούθησής σας, επισκεφτείτε το\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nΓια να διαγράψετε την σελίδα από την λίστα παρακολούθησής σας, επισκεφτείτε το\n$UNWATCHURL\n\nΠαρατηρήσεις και περισσότερη βοήθεια:\n$HELPPAGE",
        "created": "δημιουργήθηκε",
        "changed": "έχει αλλάξει",
        "deletepage": "Διαγραφή σελίδας",
        "exbeforeblank": "το περιεχόμενο πριν απο την εκκαθάριση ήταν: '$1'",
        "delete-confirm": "Διαγραφή του \"$1\"",
        "delete-legend": "Διαγραφή",
-       "historywarning": "'''Προσοχή:''' Η σελίδα που πρόκειται να διαγράψετε έχει ιστορικό με περίπου $1 {{PLURAL:$1|επεξεργασία|επεξεργασίες}}:",
+       "historywarning": "<strong>Προσοχή:</strong> Η σελίδα που πρόκειται να διαγράψετε έχει ιστορικό με περίπου $1 {{PLURAL:$1|επεξεργασία|επεξεργασίες}}:",
        "confirmdeletetext": "Πρόκειται να διαγράψετε οριστικά από τη βάση δεδομένων μια σελίδα (ή μια εικόνα) μαζί με το ιστορικό της. Παρακαλούμε επιβεβαιώστε ότι θέλετε πραγματικά να το κάνετε, ότι αντιλαμβάνεσθε τις συνέπειες και ότι το κάνετε σύμφωνα με την [[{{MediaWiki:Policy-url}}|πολιτική]].",
        "actioncomplete": "Η ενέργεια ολοκληρώθηκε.",
        "actionfailed": "Η ενέργεια απέτυχε",
        "deletecomment": "Λόγος:",
        "deleteotherreason": "Άλλος/πρόσθετος λόγος:",
        "deletereasonotherlist": "Άλλος λόγος",
-       "deletereason-dropdown": "*Συνηθισμένοι λόγοι διαγραφής\n** Αίτηση του δημιουργού της\n** Παραβίαση των πνευματικών δικαιωμάτων\n** Βανδαλισμός",
+       "deletereason-dropdown": "* Συνηθισμένοι λόγοι διαγραφής\n** Σπαμ\n** Βανδαλισμός\n** Παραβίαση πνευματικών δικαιωμάτων\n** Αίτηση του δημιουργού της\n** Κατεστραμμένη ανακατεύθυνση",
        "delete-edit-reasonlist": "Επεξεργασία λόγων διαγραφής",
        "delete-toobig": "Αυτή η σελίδα έχει μεγάλο ιστορικό τροποποιήσεων, πάνω από $1 {{PLURAL:$1|τροποποίηση|τροποποιήσεις}}.\nΗ διαγραφή τέτοιων σελίδων έχει περιοριστεί για την αποφυγή τυχαίας αναστάτωσης του {{SITENAME}}.",
        "delete-warning-toobig": "Αυτή η σελίδα έχει μεγάλο ιστορικό τροποποιήσεων, πάνω από $1 {{PLURAL:$1|τροποποίηση|τροποποιήσεις}}.\nΗ διαγραφή της μπορεί να αναστατώσει τη λειτουργία της βάσης δεδομένων του {{SITENAME}}. Συνιστούμε μεγάλη προσοχή.",
+       "deleteprotected": "Δεν μπορείτε να διαγράψετε αυτή τη σελίδα επειδή είναι προστατευόμενη.",
        "rollback": "Επαναφορά επεξεργασιών",
        "rollback_short": "Επαναφορά",
        "rollbacklink": "αναστροφή",
        "protect-locked-blocked": "Δεν μπορείτε να αλλάξετε επίπεδα προστασίας ενώ είστε σε φραγή.\nΕδώ είναι οι τρέχουσες ρυθμίσεις για τη σελίδα '''$1''':",
        "protect-locked-dblock": "Τα επίπεδα προστασίας δεν μπορούν να αλλαχθούν λόγω ενός ενεργού κλεδώματος της βάσης δεδομένων.\nΕδώ είναι οι τρέχουσες ρυθμίσεις για τη σελίδα '''$1''':",
        "protect-locked-access": "Ο λογαριασμός σας δεν έχει δικαίωμα να αλλάξει τα επίπεδα προστασίας σελίδας.\nΕδώ είναι οι τρέχουσες ρυθμίσεις για τη σελίδα '''$1''':",
-       "protect-cascadeon": "Î\91Ï\85Ï\84ή Î· Ï\83ελίδα ÎµÎ¯Î½Î±Î¹ Ï\80Ï\81οÏ\82 Ï\84ο Ï\80αÏ\81Ï\8cν Ï\80Ï\81οÏ\83Ï\84αÏ\84εÏ\85μένη ÎµÏ\80ειδή Ï\80εÏ\81ιλαμβάνεÏ\84αι {{PLURAL:$1|Ï\83Ï\84ην Î±ÎºÏ\8cλοÏ\85θη Ï\83ελίδα, Î· Î¿Ï\80οία Î­Ï\87ει|Ï\83Ï\84ιÏ\82 Î±ÎºÏ\8cλοÏ\85θεÏ\82 Ï\83ελίδεÏ\82, Î¿Î¹ Î¿Ï\80οίεÏ\82 Î­Ï\87οÏ\85ν}} Ï\84η Î´Î¹Î±Î´Î¿Ï\87ική Ï\80Ï\81οÏ\83Ï\84αÏ\83ία ÎµÎ½ÎµÏ\81γοÏ\80οιημένη. Î\9cÏ\80οÏ\81είÏ\84ε Î½Î± Î±Î»Î»Î¬Î¾ÎµÏ\84ε Ï\84ο ÎµÏ\80ίÏ\80εδο Ï\80Ï\81οÏ\83Ï\84αÏ\83ίαÏ\82 Î±Ï\85Ï\84ήÏ\82 Ï\84ηÏ\82 Ï\83ελίδαÏ\82, Î±Î»Î»Î¬ Î´ÎµÎ½ Î¸Î± ÎµÏ\80ηÏ\81εάÏ\83ει τη διαδοχική προστασία.",
+       "protect-cascadeon": "Î\91Ï\85Ï\84ή Î· Ï\83ελίδα ÎµÎ¯Î½Î±Î¹ Ï\80Ï\81οÏ\82 Ï\84ο Ï\80αÏ\81Ï\8cν Ï\80Ï\81οÏ\83Ï\84αÏ\84εÏ\85μένη ÎµÏ\80ειδή Ï\80εÏ\81ιλαμβάνεÏ\84αι {{PLURAL:$1|Ï\83Ï\84ην Î±ÎºÏ\8cλοÏ\85θη Ï\83ελίδα, Î· Î¿Ï\80οία Î­Ï\87ει|Ï\83Ï\84ιÏ\82 Î±ÎºÏ\8cλοÏ\85θεÏ\82 Ï\83ελίδεÏ\82, Î¿Î¹ Î¿Ï\80οίεÏ\82 Î­Ï\87οÏ\85ν}} Ï\84η Î´Î¹Î±Î´Î¿Ï\87ική Ï\80Ï\81οÏ\83Ï\84αÏ\83ία ÎµÎ½ÎµÏ\81γοÏ\80οιημένη. Î\91λλαγέÏ\82 Ï\83Ï\84ο ÎµÏ\80ίÏ\80εδο Ï\80Ï\81οÏ\83Ï\84αÏ\83ίαÏ\82 Î±Ï\85Ï\84ήÏ\82 Ï\84ηÏ\82 Ï\83ελίδαÏ\82 Î´ÎµÎ½ Î¸Î± ÎµÏ\80ηÏ\81εάÏ\83οÏ\85ν τη διαδοχική προστασία.",
        "protect-default": "Να επιτρέπονται όλοι οι χρήστες",
        "protect-fallback": "Να επιτρέπεται μόνο σε χρήστες με δικαιώματα «$1»",
        "protect-level-autoconfirmed": "Να επιτρέπονται μόνο αυτοεπιβεβαιωμένοι χρήστες",
        "contributions-title": "Συνεισφορές χρήστη για {{GENDER:$1|τον|την}} $1",
        "mycontris": "Συνεισφορές",
        "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»",
        "autoblockid": "Autoblock #$1",
        "block": "Φραγή χρήστη",
        "unblock": "Κατάργηση αποκλεισμού χρήστη",
-       "blockip": "Φραγή χρήστη ή διεύθυνσης IP",
+       "blockip": "Φραγή {{GENDER:$1|χρήστη|χρήστριας}}",
        "blockip-legend": "Φραγή του χρήστη",
        "blockiptext": "Χρησιμοποιήστε την παρακάτω φόρμα για να εμποδίσετε παρεμβάσεις στο κείμενο από μια συγκεκριμένη διεύθυνση IP ή όνομα χρήστη.\nΤο μέτρο αυτό πρέπει να λαμβάνεται μόνο σε περιπτώσεις βανδαλισμού σελίδων και πάντα σύμφωνα με την [[{{MediaWiki:Policy-url}}|πολιτική]].\nΠαρακαλούμε να αιτιολογήσετε την ενέργειά σας (παραπέμποντας π.χ. σε συγκεκριμένες σελίδες που υπέστησαν βανδαλισμό).",
        "ipaddressorusername": "Διεύθυνση IP ή όνομα χρήστη",
        "blockipsuccesstext": "{{GENDER:$1|Ο|Η}} [[Special:Contributions/$1|$1]] έχει υποστεί φραγή.<br />\nΔείτε τον [[Special:BlockList|κατάλογο φραγών]] για να εποπτεύσετε τις φραγές.",
        "ipb-blockingself": "Είστε έτοιμος να επιβάλετε φραγή στον ευατό σας! Είστε σίγουροι ότι θέλετε να το κάνετε αυτό;",
        "ipb-confirmhideuser": "Είστε {{GENDER:|έτοιμος|έτοιμη}} να μπλοκάρετε ένα χρήστη με ενεργοποιημένη την \"απόκρυψη χρήστη\" . Αυτό θα καταστείλει το όνομα του χρήστη σε όλες τις λίστες και τις καταχωρήσεις ημερολογίου. Είστε {{GENDER:|σίγουρος|σίγουρη}} ότι θέλετε να το κάνετε αυτό;",
+       "ipb-confirmaction": "Εάν είστε σίγουροι ότι θέλετε πραγματικά να το κάνετε αυτό, παρακαλούμε τσεκάρετε το πεδίο «{{int:ipb-confirm}}» στο κάτω μέρος.",
        "ipb-edit-dropdown": "Επεξεργασία λόγων φραγής",
        "ipb-unblock-addr": "Τερμάτισε τη φραγή του/της $1",
        "ipb-unblock": "Τερμάτισε τη φραγή για ένα όνομα χρήστη ή μια διεύθυνση IP",
        "ipb-blocklist": "Δες τις υπάρχουσες φραγές",
-       "ipb-blocklist-contribs": "Συνεισφορές για τον/την $1",
+       "ipb-blocklist-contribs": "Συνεισφορές {{GENDER:$1|του $1|της $1}}",
        "unblockip": "Άρση φραγής χρήστη",
        "unblockiptext": "Χρησιμοποιήστε την παρακάτω φόρμα για να αποκαταστήσετε την πρόσβαση σε επεξεργασία, σε μια διεύθυνση IP ή σε ένα χρήστη που είχε αποκλειστεί με φραγή.",
        "ipusubmit": "Άρση φραγής",
        "movepagetalktext": "Η σελίδα συζήτησης που αντιστοιχεί, εάν υπάρχει, θα μετακινηθεί αυτόματα μαζί με αυτήν '''έκτός αν:'''\n*Μετακινείτε τη σελίδα σε διαφορετική περιοχή (namespace),\n*Υπάρχει κάτω από το νέο όνομα μια σελίδα συζήτησης που δεν είναι κενή, ή\n*Έχετε αφαιρέσει τη σημείωση (check) από το κουτάκι που υπάρχει παρακάτω.\n\nΣε αυτές τις περιπτώσεις, θα πρέπει να μετακινήσετε (ή να ενσωματώσετε αν το θέλετε) τη σελίδα με αντιγραφή-και-επικόλληση.",
        "movearticle": "Μετακίνηση σελίδας",
        "moveuserpage-warning": "'''Προσοχή:''' Ετοιμάζεστε να μετακινήσετε μια σελίδα χρήστη. Σημειώστε παρακαλώ ότι θα μετακινηθεί μόνο η σελίδα και ο χρήστης '''δεν''' θα μετονομαστεί.",
+       "movecategorypage-warning": "<strong>Προειδοποίηση:</strong>Πάτε να μετακινήσετε μια σελίδα κατηγορίας. Παρακαλούμε να σημειωθεί ότι μόνο η σελίδα θα μετακινηθεί και τυχόν σελίδες στην παλιά κατηγορία <em>δεν</em> θα επανακατηγοριοποιηθούν στη νέα κατηγορία.",
        "movenologintext": "Για να μετακινήσετε μια σελίδα πρέπει να είστε εγγεγραμένος χρήστης και [[Special:UserLogin|να έχετε συνδεθεί]] στο Wiκi.",
        "movenotallowed": "Δεν έχετε άδεια να μετακινείτε σελίδες.",
        "movenotallowedfile": "Δεν έχετε άδεια να μετακινείτε αρχεία.",
        "cant-move-user-page": "Δεν έχετε άδεια για να μετακινήσετε σελίδες χρηστών (παρά μόνο υποσελίδες).",
        "cant-move-to-user-page": "Δεν έχετε άδεια για να μετακινήσετε μια σελίδα σε σελίδα χρήστη (παρά μόνο σε υποσελίδα χρήστη).",
+       "cant-move-category-page": "Δεν έχετε άδεια να μετακινείτε σελίδες κατηγοριών.",
+       "cant-move-to-category-page": "Δεν έχετε άδεια να μετακινήσετε μια σελίδα σε σελίδα της κατηγορίας.",
        "newtitle": "νέος τίτλος",
        "move-watch": "Παρακολούθησε αυτή τη σελίδα",
        "movepagebtn": "Μετακίνηση σελίδας",
        "import": "Εισαγωγή σελίδων",
        "importinterwiki": "Εισαγωγή από άλλο Wiki",
        "import-interwiki-text": "Επιλέξτε ένα wiki και τίτλο σελίδας για την εισαγωγή.\nΟι ημερομηνίες των αναθεωρήσεων και τα ονόματα των συντακτών θα διατηρηθούν.\nΌλες οι ενέργειες εισαγωγής μεταξύ wiki καταγράφονται στο [[Special:Log/import|αρχείο καταγραφής εισαγωγών]].",
-       "import-interwiki-source": "Wiki και σελίδα πηγή:",
+       "import-interwiki-sourcewiki": "Πηγαίο wiki:",
+       "import-interwiki-sourcepage": "Πηγαία σελίδα:",
        "import-interwiki-history": "Αντιγραφή όλων των εκδόσεων του ιστορικού για αυτή τη σελίδα",
        "import-interwiki-templates": "Συμπερίληψη όλων των προτύπων",
        "import-interwiki-submit": "Εισαγωγή",
        "import-upload": "Επιφόρτωση δεδομένων XML",
        "import-token-mismatch": "Απώλεια των στοιχείων της συνόδου. Παρακαλούμε προσπαθήστε ξανά.",
        "import-invalid-interwiki": "Δεν είναι δυνατή η εισαγωγή από το καθορισμένο wiki.",
-       "import-error-edit": "Η σελίδα \"$1\" δεν εισήχθηκε επειδή δεν επιτρέπεται να το επεξεργαστείτε.",
-       "import-error-create": "Η σελίδα \"$1\" δεν εισήχθηκε επειδή δεν επιτρέπεται να τη δημιουργήσετε.",
-       "import-error-interwiki": "Η σελίδα \" $1 \" δεν έχει εισαχθεί, επειδή το όνομα της δεσμευμένο για εξωτερική σύνδεση (interwiki).",
-       "import-error-special": "Η σελίδα \"$1\" δεν εισήχθη επειδή ανήκει σε έναν ειδικό χώρο ονομάτων που δεν επιτρέπει σελίδες.",
-       "import-error-invalid": "Η σελίδα \"$1\" δεν εισήχθη επειδή το όνομά της δεν είναι έγκυρο.",
+       "import-error-edit": "Η σελίδα «$1» δεν εισήχθη επειδή δεν σας επιτρέπεται να την επεξεργαστείτε.",
+       "import-error-create": "Η σελίδα «$1» δεν εισήχθη επειδή δεν σας επιτρέπεται να την δημιουργήσετε.",
+       "import-error-interwiki": "Η σελίδα «$1» δεν εισήχθη επειδή το όνομα της είναι δεσμευμένο για εξωτερική σύνδεση (interwiki).",
+       "import-error-special": "Η σελίδα «$1» δεν εισήχθη επειδή ανήκει σε έναν ειδικό ονοματοχώρο που δεν επιτρέπει σελίδες.",
+       "import-error-invalid": "Η σελίδα «$1» δεν εισήχθη επειδή το όνομά με το οποίο επρόκειτο να εισαχθεί δεν είναι έγκυρο σε αυτό το wiki.",
        "import-options-wrong": "Λάθος {{PLURAL:$2|επιλογή|επιλογές}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "Η δεδομένη ριζική σελίδα είναι μη έγκυρος τίτλος",
        "importlogpage": "Αρχείο καταγραφής εισαγωγών",
        "importlogpagetext": "Διαχειριστικές εισαγωγές σελίδων με ιστορικό επεξεργασίας από άλλα wiki.",
        "import-logentry-upload": "εισάχθηκε η σελίδα [[$1]] με επιφόρτωση αρχείου",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|αναθεώρηση|αναθεωρήσεις}}",
+       "import-logentry-upload-detail": "{{PLURAL:$1|Εισήχθη $1 αναθεώρηση|Εισήχθησαν $1 αναθεωρήσεις}}",
        "import-logentry-interwiki": "η σελίδα $1 εισάχθηκε μεταξύ wiki",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|αναθεώρηση|αναθεωρήσεις}} από $2",
+       "import-logentry-interwiki-detail": "{{PLURAL:$1|Εισήχθη $1 αναθεώρηση|Εισήχθησαν $1 αναθεωρήσεις}} από $2",
        "javascripttest": "Δοκιμή JavaScript",
        "javascripttest-title": "Εκτελούνται  $1  δοκιμές",
        "javascripttest-pagetext-noframework": "Αυτή η σελίδα είναι δεσμευμένη για την εκτέλεση δοκιμών σε JavaScript.",
        "pageinfo-lasttime": "Ημερομηνία τελευταίας επεξεργασίας",
        "pageinfo-edits": "Συνολικός αριθμός επεξεργασιών",
        "pageinfo-authors": "Συνολικός αριθμός διαφορετικών συντακτών",
-       "pageinfo-recent-edits": "ΠÏ\81Ï\8cÏ\83Ï\86αÏ\84οÏ\82 Î±Ï\81ιθμÏ\8cÏ\82 επεξεργασιών (σε διάστημα $1)",
+       "pageinfo-recent-edits": "Î\91Ï\81ιθμÏ\8cÏ\82 Ï\80Ï\81Ï\8cÏ\83Ï\86αÏ\84Ï\89ν επεξεργασιών (σε διάστημα $1)",
        "pageinfo-recent-authors": "Πρόσφατος αριθμός μοναδικών συντακτών",
        "pageinfo-magic-words": "{{PLURAL:$1|Μαγική λέξη|Μαγικές λέξεις}} ($1)",
        "pageinfo-hidden-categories": "{{PLURAL:$1|Κρυφή κατηγορία|Κρυφές κατηγορίες}} ($1)",
        "svg-long-desc": "Αρχείο SVG, ονομαστικό μέγεθος $1 × $2 εικονοστοιχεία, μέγεθος αρχείου: $3",
        "svg-long-desc-animated": "Κινούμενο αρχείο SVG, ονομαστικό μέγεθος σε pixels: $1 × $2, μέγεθος αρχείου: $3",
        "svg-long-error": "Μη έγκυρο αρχείο SVG: $1",
-       "show-big-image": "Î\91Ï\81Ï\87ικÏ\8c αρχείο",
+       "show-big-image": "ΠÏ\81Ï\89Ï\84Ï\8cÏ\84Ï\85Ï\80ο αρχείο",
        "show-big-image-preview": "Μέγεθος αυτής της προεπισκόπησης: $1 .",
        "show-big-image-other": "Άλλες {{PLURAL:$2|ανάλυση|αναλύσεις}}: $1.",
        "show-big-image-size": "$1 × $2 εικονοστοιχεία",
        "newimages-summary": "Αυτή η ειδική σελίδα δείχνει τα πιο πρόσφατα φορτωμένα αρχεία.",
        "newimages-legend": "Φίλτρο",
        "newimages-label": "Όνομα αρχείου (ή μέρος αυτού):",
+       "newimages-showbots": "Εμφάνιση αρχείων ανεβασμένων από ρομπότ",
        "noimages": "Δεν υπάρχουν εικόνες.",
        "ilsubmit": "Αναζήτηση",
        "bydate": "ημερομηνίας",
        "confirm-watch-top": "Προσθήκη αυτής της σελίδας στη λίστα παρακολούθησης σας;",
        "confirm-unwatch-button": "Εντάξει",
        "confirm-unwatch-top": "Κατάργηση αυτής της σελίδας από τη λίστα παρακολούθησης σας;",
+       "quotation-marks": "«$1»",
        "imgmultipageprev": "← προηγούμενη σελίδα",
        "imgmultipagenext": "επόμενη σελίδα →",
        "imgmultigo": "Πήγαινε!",
        "autosumm-replace": "Αντικατάσταση σελίδας με '$1'",
        "autoredircomment": "Ανακατεύθυνση στη σελίδα [[$1]]",
        "autosumm-new": "Νέα σελίδα με '$1'",
+       "autosumm-newblank": "Δημιουργήθηκε κενή σελίδα",
        "lag-warn-normal": "Αλλαγές νεότερες από {{PLURAL:$1|δευτερόλεπτο|δευτερόλεπτα}} μπορεί να μην φαίνονται σε αυτή τη λίστα.",
        "lag-warn-high": "Εξαιτίας υψηλής καθυστέρησης της βάσης δεδομένων του εξυπηρετητή, αλλαγές νεότερες από $1 {{PLURAL:$1|δευτερόλεπτο|δευτερόλεπτα}} μπορεί να μην φαίνονται σε αυτή τη λίστα.",
        "watchlistedit-normal-title": "Επεξεργασία λίστας παρακολούθησης",
        "watchlistedit-raw-done": "Η λίστα παρακολούθησής σας ενημερώθηκε.",
        "watchlistedit-raw-added": "{{PLURAL:$1|1 σελίδα|$1 σελίδες}} προστέθηκαν:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1 σελίδα|$1 σελίδες}} αφαιρέθηκαν:",
+       "watchlistedit-clear-explain": "Όλοι οι τίτλοι θα αφαιρεθούν από τη λίστα παρακολούθησής σας",
        "watchlistedit-clear-titles": "Τίτλοι:",
        "watchlistedit-clear-submit": "Καθαρίστε τη λίστα παρακολούθησης (αυτό είναι μόνιμο!)",
+       "watchlistedit-clear-done": "Η λίστα παρακολούθησής σας έχει καθαριστεί.",
+       "watchlistedit-clear-removed": "{{PLURAL:$1|1 τίτλος αφαιρέθηκε|$1 τίτλοι αφαιρέθηκαν}}:",
        "watchlistedit-too-many": "Υπάρχουν υπερβολικά πολλές σελίδες και δεν μπορούν να εμφανιστούν εδώ.",
        "watchlisttools-view": "Προβολή σχετικών αλλαγών",
        "watchlisttools-edit": "Προβολή και επεξεργασία λίστας παρακολούθησης",
        "specialpages-group-other": "Άλλες ειδικές σελίδες",
        "specialpages-group-login": "Σύνδεση / δημιουργία λογαριασμού",
        "specialpages-group-changes": "Πρόσφατες αλλαγές και καταγραφές γεγονότων",
-       "specialpages-group-media": "Î\91ναÏ\86οÏ\81έÏ\82 Ï\80ολÏ\85μέÏ\83Ï\89ν ÎºÎ±Î¹ ÎµÏ\80ιÏ\86Ï\8cÏ\81Ï\84Ï\89Ï\83η αρχείων",
+       "specialpages-group-media": "Î\91ναÏ\86οÏ\81έÏ\82 Ï\80ολÏ\85μέÏ\83Ï\89ν ÎºÎ±Î¹ Î±Î½Î­Î²Î±Ï\83μα αρχείων",
        "specialpages-group-users": "Χρήστες και δικαιώματα",
        "specialpages-group-highuse": "Πολυσύχναστες σελίδες",
        "specialpages-group-pages": "Κατάλογοι σελίδων",
        "logentry-rights-rights": "{{GENDER:$2|Ο|Η}} $1 άλλαξε την ιδιότητα μέλους ομάδας για {{GENDER:$3|τον|την}} $3 από $4 σε $5",
        "logentry-rights-rights-legacy": "{{GENDER:$2|Ο|Η}} $1 άλλαξε την ιδιότητα μέλους ομάδας {{GENDER:$1|του|της}} $3",
        "logentry-rights-autopromote": "$1 {{GENDER:$2|προωθήθηκε}} αυτόματα από το $4 στο $5",
+       "logentry-upload-upload": "{{GENDER:$2|Ο|Η}} $1 ανέβασε το $3",
+       "logentry-upload-overwrite": "{{GENDER:$2|Ο|Η}} $1 ανέβασε μια νέα έκδοση του $3",
+       "logentry-upload-revert": "{{GENDER:$2|Ο|Η}} $1 ανέβασε το $3",
        "rightsnone": "(κανένα)",
        "feedback-bugornote": "Εάν είστε έτοιμοι να περιγράψετε ένα τεχνικό πρόβλημα λεπτομερώς παρακαλούμε [$1  κάντε μια αναφορά σφάλματος].\nΔιαφορετικά, μπορείτε να χρησιμοποιήσετε την παρακάτω απλή φόρμα. Το σχόλιό σας θα προστεθεί στη σελίδα \"[$3  $2]\", μαζί με το όνομα χρήστη σας.",
        "feedback-subject": "Θέμα:",
        "api-error-overwrite": "Αντικατάσταση ενός υπάρχοντος αρχείου δεν επιτρέπεται.",
        "api-error-stashfailed": "Εσωτερικό σφάλμα: ο διακομιστής απέτυχε να αποθηκεύσει το προσωρινό αρχείο.",
        "api-error-publishfailed": "Εσωτερικό σφάλμα: ο διακομιστής απέτυχε να αποθηκεύσει το προσωρινό αρχείο.",
+       "api-error-stasherror": "Παρουσιάστηκε ένα σφάλμα κατά το ανέβασμα του αρχείου στην κρύπτη.",
        "api-error-timeout": "Ο διακομιστής δεν αποκρίθηκε εντός του αναμενόμενου χρόνου.",
        "api-error-unclassified": "Προέκυψε ένα άγνωστο σφάλμα.",
        "api-error-unknown-code": "Άγνωστο σφάλμα: \"$1\"",
        "limitreport-ppvisitednodes": "Καταμέτρηση κόμβων επισκεφθέντων από τον προεπεξεργαστή",
        "limitreport-ppgeneratednodes": "Καταμέτρηση κόμβων παραχθέντων από τον προεπεξεργαστή",
        "limitreport-postexpandincludesize": "Μέγεθος συμπερίληψης πριν την ανάπτυξη",
+       "limitreport-postexpandincludesize-value": "$1 από $2 {{PLURAL:$2|byte|bytes}}",
        "limitreport-templateargumentsize": "Μέγεθος ορισμάτων προτύπων",
+       "limitreport-templateargumentsize-value": "$1 από $2 {{PLURAL:$2|byte|bytes}}",
        "limitreport-expansiondepth": "Μεγαλύτερο βάθος ανάπτυξης",
        "limitreport-expensivefunctioncount": "Πλήθος ακριβών συναρτήσεων συντακτικού αναλυτή",
        "expandtemplates": "Επέκτεινε τα πρότυπα",
        "expand_templates_remove_nowiki": "Απόκρυψη της ετικέτας <nowiki> στο αποτέλεσμα",
        "expand_templates_generate_xml": "Εμφάνιση δέντρου συντακτικής ανάλυσης XML",
        "expand_templates_generate_rawhtml": "Εμφάνιση ανεπεξέργαστης HTML",
-       "expand_templates_preview": "Προεπισκόπηση"
+       "expand_templates_preview": "Προεπισκόπηση",
+       "pagelanguage": "Επιλογέας γλώσσας σελίδας",
+       "pagelang-name": "Σελίδα",
+       "pagelang-language": "Γλώσσα",
+       "pagelang-use-default": "Χρήση προεπιλεγμένης γλώσσας",
+       "pagelang-select-lang": "Επιλογή γλώσσας",
+       "right-pagelang": "Αλλαγή γλώσσας σελίδας",
+       "action-pagelang": "αλλαγή της γλώσσας σελίδας",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> /$2 (ενεργοποιημένο)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''απενεργοποιημένο''')"
 }
index d0e7ad3..bc1c6a1 100644 (file)
@@ -4,8 +4,8 @@
        },
        "sidebar": "\n* navigation\n** mainpage|mainpage-description\n** recentchanges-url|recentchanges\n** randompage-url|randompage\n** helppage|help\n* SEARCH\n* TOOLBOX\n* LANGUAGES",
        "tog-underline": "Link underlining:",
-       "tog-hideminor": "Hide minor edits in recent changes",
-       "tog-hidepatrolled": "Hide patrolled edits in recent changes",
+       "tog-hideminor": "Hide minor edits from recent changes",
+       "tog-hidepatrolled": "Hide patrolled edits from recent changes",
        "tog-newpageshidepatrolled": "Hide patrolled pages from new page list",
        "tog-extendwatchlist": "Expand watchlist to show all changes, not just the most recent",
        "tog-usenewrc": "Group changes by page in recent changes and watchlist",
@@ -17,6 +17,7 @@
        "tog-watchdefault": "Add pages and files I edit to my watchlist",
        "tog-watchmoves": "Add pages and files I move to my watchlist",
        "tog-watchdeletion": "Add pages and files I delete to my watchlist",
+       "tog-watchrollback": "Add pages where I have performed a rollback to my watchlist",
        "tog-minordefault": "Mark all edits minor by default",
        "tog-previewontop": "Show preview before edit box",
        "tog-previewonfirst": "Show preview on first edit",
        "talkpagelinktext": "Talk",
        "specialpage": "Special page",
        "personaltools": "Personal tools",
-       "postcomment": "New section",
        "addsection": "+",
        "articlepage": "View content page",
        "talk": "Discussion",
        "otherlanguages": "In other languages",
        "redirectedfrom": "(Redirected from $1)",
        "redirectpagesub": "Redirect page",
+       "redirectto": "Redirect to:",
        "talkpageheader": "-",
        "lastmodifiedat": "This page was last modified on $1, at $2.",
        "viewcount": "This page has been accessed {{PLURAL:$1|once|$1 times}}.",
        "hidetoc": "hide",
        "collapsible-collapse": "Collapse",
        "collapsible-expand": "Expand",
+       "confirmable-confirm": "Are {{GENDER:$1|you}} sure?",
+       "confirmable-yes": "Yes",
+       "confirmable-no": "No",
        "thisisdeleted": "View or restore $1?",
        "viewdeleted": "View $1?",
        "restorelink": "{{PLURAL:$1|one deleted edit|$1 deleted edits}}",
        "invalidtitle-knownnamespace": "Invalid title with namespace \"$2\" and text \"$3\"",
        "invalidtitle-unknownnamespace": "Invalid title with unknown namespace number $1 and text \"$2\"",
        "exception-nologin": "Not logged in",
-       "exception-nologin-text": "Please [[Special:Userlogin|log in]] to be able to access this page or action.",
+       "exception-nologin-text": "Please log in to be able to access this page or action.",
        "exception-nologin-text-manual": "Please $1 to be able to access this page or action.",
        "virus-badscanner": "Bad configuration: Unknown virus scanner: <em>$1</em>",
        "virus-scanfailed": "scan failed (code $1)",
        "externaldberror": "There was either an authentication database error or you are not allowed to update your external account.",
        "login": "Log in",
        "nav-login-createaccount": "Log in / create account",
-       "loginprompt": "You must have cookies enabled to log in to {{SITENAME}}.",
+       "loginprompt": "",
        "userlogin": "Log in / create account",
        "userloginnocreate": "Log in",
        "logout": "Log out",
        "userlogin-resetpassword-link": "Forgot your password?",
        "helplogin-url": "https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Logging_in",
        "userlogin-helplink2": "Help with logging in",
-       "userlogin-loggedin": "You are already logged in as {{GENDER:$1|$1}}.\nUse the form below to log in as another user.",
-       "userlogin-createanother": "Create another account",
        "createacct-emailrequired": "Email address",
        "createacct-emailoptional": "Email address (optional)",
        "createacct-email-ph": "Enter your email address",
        "createaccount-text": "Someone created an account for your email address on {{SITENAME}} ($4) named \"$2\", with password \"$3\".\nYou should log in and change your password now.\n\nYou may ignore this message, if this account was created in error.",
        "login-throttled": "You have made too many recent login attempts.\nPlease wait $1 before trying again.",
        "login-abort-generic": "Your login was unsuccessful - Aborted",
+       "login-migrated-generic": "Your account has been migrated, and your username no longer exist on this wiki.",
        "loginlanguagelabel": "Language: $1",
        "loginlanguagelinks": "* {{#language:de}}|de\n* {{#language:en}}|en\n* {{#language:eo}}|eo\n* {{#language:fr}}|fr\n* {{#language:es}}|es\n* {{#language:it}}|it\n* {{#language:nl}}|nl",
        "suspicious-userlogout": "Your request to log out was denied because it looks like it was sent by a broken browser or caching proxy.",
        "preview": "Preview",
        "showpreview": "Show preview",
        "showdiff": "Show changes",
-       "anoneditwarning": "<strong>Warning:</strong> You are not logged in.\nYour IP address will be recorded in this page's edit history.",
+       "blankarticle": "<strong>Warning:</strong> The page you are creating is blank.\nIf you click \"{{int:savearticle}}\" again, the page will be created without any content.",
+       "anoneditwarning": "<strong>Warning:</strong> You are not logged in. Your IP address will be publicly visible if you make any edits. If you <strong>[$1 log in]</strong> or <strong>[$2 create an account]</strong>, your edits will be attributed to your username, along with other benefits.",
        "anonpreviewwarning": "<em>You are not logged in. Saving will record your IP address in this page's edit history.</em>",
        "missingsummary": "<strong>Reminder:</strong> You have not provided an edit summary.\nIf you click \"{{int:savearticle}}\" again, your edit will be saved without one.",
        "missingcommenttext": "Please enter a comment below.",
        "parser-template-loop-warning": "Template loop detected: [[$1]]",
        "parser-template-recursion-depth-warning": "Template recursion depth limit exceeded ($1)",
        "language-converter-depth-warning": "Language converter depth limit exceeded ($1)",
-       "node-count-exceeded-category": "Pages where node-count is exceeded",
-       "node-count-exceeded-category-desc": "A category for pages where the node-count is exceeded.",
-       "node-count-exceeded-warning": "Page exceeded the node-count",
+       "node-count-exceeded-category": "Pages where node count is exceeded",
+       "node-count-exceeded-category-desc": "The page exceeds the maximum node count.",
+       "node-count-exceeded-warning": "Page exceeded the node count",
        "expansion-depth-exceeded-category": "Pages where expansion depth is exceeded",
-       "expansion-depth-exceeded-category-desc": "This is a category for pages where the expansion depth is exceeded.",
+       "expansion-depth-exceeded-category-desc": "The page exceeds the maximum expansion depth.",
        "expansion-depth-exceeded-warning": "Page exceeded the expansion depth",
        "parser-unstrip-loop-warning": "Unstrip loop detected",
        "parser-unstrip-recursion-limit": "Unstrip recursion limit exceeded ($1)",
        "rev-deleted-event": "(log action removed)",
        "rev-deleted-user-contribs": "[username or IP address removed - edit hidden from contributions]",
        "rev-deleted-text-permission": "This page revision has been <strong>deleted</strong>.\nDetails can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
+       "rev-suppressed-text-permission": "This page revision has been <strong>suppressed</strong>.\nDetails can be found in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].",
        "rev-deleted-text-unhide": "This page revision has been <strong>deleted</strong>.\nDetails can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].\nYou can still [$1 view this revision] if you wish to proceed.",
        "rev-suppressed-text-unhide": "This page revision has been <strong>suppressed</strong>.\nDetails can be found in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].\nYou can still [$1 view this revision] if you wish to proceed.",
        "rev-deleted-text-view": "This page revision has been <strong>deleted</strong>.\nYou can view it; details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
        "revdelete-text-text": "Deleted revisions will still appear in the page history, but parts of their content will be inaccessible to the public.",
        "revdelete-text-file": "Deleted file versions will still appear in the file history, but parts of their content will be inaccessible to the public.",
        "logdelete-text": "Deleted log events will still appear in the logs, but parts of their content will be inaccessible to the public.",
-       "revdelete-text-others": "Other administrators on {{SITENAME}} will still be able to access the hidden content and can undelete it again through this same interface, unless additional restrictions are set.",
+       "revdelete-text-others": "Other administrators will still be able to access the hidden content and to undelete it, unless additional restrictions are set.",
        "revdelete-confirm": "Please confirm that you intend to do this, that you understand the consequences, and that you are doing this in accordance with [[{{MediaWiki:Policy-url}}|the policy]].",
        "revdelete-suppress-text": "Suppression should <strong>only</strong> be used for the following cases:\n* potentially libelous information\n* inappropriate personal information\n*: <em>home addresses and telephone numbers, national identification numbers, etc.</em>",
        "revdelete-legend": "Set visibility restrictions",
        "searchprofile-advanced-tooltip": "Search in custom namespaces",
        "search-result-size": "$1 ({{PLURAL:$2|1 word|$2 words}})",
        "search-result-category-size": "{{PLURAL:$1|1 member|$1 members}} ({{PLURAL:$2|1 subcategory|$2 subcategories}}, {{PLURAL:$3|1 file|$3 files}})",
-       "search-result-score": "Relevance: $1%",
        "search-redirect": "(redirect $1)",
        "search-section": "(section $1)",
        "search-file-match": "(matches file content)",
        "searchall": "all",
        "showingresults": "Showing below up to {{PLURAL:$1|<strong>1</strong> result|<strong>$1</strong> results}} starting with #<strong>$2</strong>.",
        "showingresultsinrange": "Showing below up to {{PLURAL:$1|<strong>1</strong> result|<strong>$1</strong> results}} in range #<strong>$2</strong> to #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Result <strong>$1</strong> of <strong>$3</strong>|Results <strong>$1 - $2</strong> of <strong>$3</strong>}} for <strong>$4</strong>",
+       "search-showingresults": "{{PLURAL:$4|Result <strong>$1</strong> of <strong>$3</strong>|Results <strong>$1 - $2</strong> of <strong>$3</strong>}}",
        "search-nonefound": "There were no results matching the query.",
        "powersearch-legend": "Advanced search",
        "powersearch-ns": "Search in namespaces:",
        "preferences-summary": "",
        "mypreferences": "Preferences",
        "prefs-edits": "Number of edits:",
-       "prefsnologintext2": "Please $1 to change your preferences.",
+       "prefsnologintext2": "Please login to change your preferences.",
        "prefs-skin": "Skin",
        "skin-preview": "Preview",
        "datedefault": "No preference",
        "right-deletedtext": "View deleted text and changes between deleted revisions",
        "right-browsearchive": "Search deleted pages",
        "right-undelete": "Undelete a page",
-       "right-suppressrevision": "Review and restore revisions hidden from administrators",
+       "right-suppressrevision": "View, hide and unhide specific revisions of pages from any user",
+       "right-viewsuppressed": "View revisions hidden from any user",
        "right-suppressionlog": "View private logs",
        "right-block": "Block other users from editing",
        "right-blockemail": "Block a user from sending email",
        "recentchanges-legend-bot": "{{int:recentchanges-label-bot}}",
        "recentchanges-legend-unpatrolled": "{{int:recentchanges-label-unpatrolled}}",
        "recentchanges-legend-plusminus": "(<em>±123</em>)",
-       "rcnotefrom": "Below are the changes since <strong>$2</strong> (up to <strong>$1</strong> shown).",
+       "rcnotefrom": "Below {{PLURAL:$5|is the change|are the changes}} since <strong>$3, $4</strong> (up to <strong>$1</strong> shown).",
        "rclistfrom": "Show new changes starting from $2, $3",
        "rcshowhideminor": "$1 minor edits",
        "rcshowhideminor-show": "Show",
        "license-header": "Licensing",
        "nolicense": "None selected",
        "licenses": "-",
+       "licenses-edit": "Edit license options",
        "license-nopreview": "(Preview not available)",
-       "upload_source_url": "(a valid, publicly accessible URL)",
-       "upload_source_file": "(a file on your computer)",
+       "upload_source_url": "(your chosen file from a valid, publicly accessible URL)",
+       "upload_source_file": "(your chosen file from your computer)",
        "listfiles-delete": "delete",
        "listfiles-summary": "This special page shows all uploaded files.",
        "listfiles_search_for": "Search for media name:",
        "randomincategory": "Random page in category",
        "randomincategory-invalidcategory": "\"$1\" is not a valid category name.",
        "randomincategory-nopages": "There are no pages in the [[:Category:$1|$1]] category.",
-       "randomincategory-selectcategory": "Get random page from category: $1 $2.",
-       "randomincategory-selectcategory-submit": "Go",
+       "randomincategory-category": "Category:",
+       "randomincategory-legend": "Random page in category",
        "randomredirect": "Random redirect",
        "randomredirect-nopages": "There are no redirects in the namespace \"$1\".",
        "statistics": "Statistics",
        "wantedfiles": "Wanted files",
        "wantedfiles-summary": "",
        "wantedfiletext-cat": "The following files are used but do not exist. Files from foreign repositories may be listed despite existing. Any such false positives will be <del>struck out</del>. Additionally, pages that embed files that do not exist are listed in [[:$1]].",
+       "wantedfiletext-cat-noforeign": "The following files are used but do not exist. Additionally, pages that embed files that do not exist are listed in [[:$1]].",
        "wantedfiletext-nocat": "The following files are used but do not exist. Files from foreign repositories may be listed despite existing. Any such false positives will be <del>struck out</del>.",
+       "wantedfiletext-nocat-noforeign": "The following files are used but do not exist.",
        "wantedtemplates": "Wanted templates",
        "wantedtemplates-summary": "",
        "mostlinked": "Most linked-to pages",
        "trackingcategories-desc": "Category inclusion criteria",
        "noindex-category-desc": "The page is not indexed by robots because it has the magic word <code><nowiki>__NOINDEX__</nowiki></code> on it and is in a namespace where that flag is allowed.",
        "index-category-desc": "The page has a <code><nowiki>__INDEX__</nowiki></code> on it (and is in a namespace where that flag is allowed), and hence is indexed by robots where it normally wouldn't be.",
-       "post-expand-template-inclusion-category-desc": "After expanding all the templates, the page size is bigger than <code>$wgMaxArticleSize</code>, so some templates weren't expanded.",
-       "post-expand-template-argument-category-desc": "After expanding a template argument (something in triple braces, like <code>{{{Foo}}}</code>), the page is bigger than <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Too many expensive parser functions (like <code>#ifexist</code>) included on a page. See [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Category added if the page contains a broken file link (a link to embed a file when the file does not exist).",
-       "hidden-category-category-desc": "This is a category with <code><nowiki>__HIDDENCAT__</nowiki></code> on it, which prevents it from showing up in the category links box on pages, by default.",
+       "post-expand-template-inclusion-category-desc": "The page size is bigger than <code>$wgMaxArticleSize</code> after expanding all the templates, so some templates were not expanded.",
+       "post-expand-template-argument-category-desc": "The page is bigger than <code>$wgMaxArticleSize</code> after expanding a template argument (something in triple braces, like <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "The page uses too many expensive parser functions (like <code>#ifexist</code>). See [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "The page contains a broken file link (a link to embed a file when the file does not exist).",
+       "hidden-category-category-desc": "The category contains <code><nowiki>__HIDDENCAT__</nowiki></code> in its page content, which prevents it from showing up in the category links box on pages by default.",
        "trackingcategories-nodesc": "No description available.",
        "trackingcategories-disabled": "Category is disabled",
        "mailnologin": "No send address",
        "mywatchlist": "Watchlist",
        "watchlistfor2": "For $1 $2",
        "nowatchlist": "You have no items on your watchlist.",
-       "watchlistanontext": "Please $1 to view or edit items on your watchlist.",
+       "watchlistanontext": "Please login to view or edit items on your watchlist.",
        "watchnologin": "Not logged in",
        "addwatch": "Add to watchlist",
        "addedwatchtext": "The page \"[[:$1]]\" has been added to your [[Special:Watchlist|watchlist]].\nFuture changes to this page and its associated talk page will be listed there.",
        "watchlist-details": "{{PLURAL:$1|$1 page|$1 pages}} on your watchlist, not separately counting talk pages.",
        "wlheader-enotif": "Email notification is enabled.",
        "wlheader-showupdated": "Pages that have been changed since you last visited them are shown in <strong>bold</strong>.",
-       "wlnote2": "Below are the changes in the last {{PLURAL:$1|hour|<strong>$1</strong> hours}}, as of $2, $3.",
+       "wlnote": "Below {{PLURAL:$1|is the last change|are the last <strong>$1</strong> changes}} in the last {{PLURAL:$2|hour|<strong>$2</strong> hours}}, as of $3, $4.",
        "wlshowlast": "Show last $1 hours $2 days $3",
        "watchlist-options": "Watchlist options",
        "watching": "Watching...",
        "exbeforeblank": "content before blanking was: \"$1\"",
        "delete-confirm": "Delete \"$1\"",
        "delete-legend": "Delete",
-       "historywarning": "<strong>Warning:</strong> The page you are about to delete has a history with approximately $1 {{PLURAL:$1|revision|revisions}}:",
+       "historywarning": "<strong>Warning:</strong> The page you are about to delete has a history with $1 {{PLURAL:$1|revision|revisions}}:",
        "confirmdeletetext": "You are about to delete a page along with all of its history.\nPlease confirm that you intend to do this, that you understand the consequences, and that you are doing this in accordance with [[{{MediaWiki:Policy-url}}|the policy]].",
        "actioncomplete": "Action complete",
        "actionfailed": "Action failed",
        "delete-edit-reasonlist": "Edit deletion reasons",
        "delete-toobig": "This page has a large edit history, over $1 {{PLURAL:$1|revision|revisions}}.\nDeletion of such pages has been restricted to prevent accidental disruption of {{SITENAME}}.",
        "delete-warning-toobig": "This page has a large edit history, over $1 {{PLURAL:$1|revision|revisions}}.\nDeleting it may disrupt database operations of {{SITENAME}};\nproceed with caution.",
+       "deleteprotected": "You cannot delete this page because it has been protected.",
        "deleting-backlinks-warning": "'''Warning:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Other pages]] link to or transclude the page you are about to delete.",
        "rollback": "Roll back edits",
        "rollback_short": "Rollback",
        "block": "Block user",
        "unblock": "Unblock user",
        "unblock-summary": "",
-       "blockip": "Block user",
+       "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).",
        "ipaddressorusername": "IP address or username:",
        "ipb-unblock-addr": "Unblock $1",
        "ipb-unblock": "Unblock a username or IP address",
        "ipb-blocklist": "View existing blocks",
-       "ipb-blocklist-contribs": "Contributions for $1",
+       "ipb-blocklist-contribs": "Contributions for {{GENDER:$1|$1}}",
        "unblockip": "Unblock user",
        "unblockiptext": "Use the form below to restore write access to a previously blocked IP address or username.",
        "ipusubmit": "Remove this block",
        "unblocked": "[[User:$1|$1]] has been unblocked.",
        "unblocked-range": "$1 has been unblocked.",
        "unblocked-id": "Block $1 has been removed.",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] has been unblocked.",
        "blocklist": "Blocked users",
        "ipblocklist": "Blocked users",
        "ipblocklist-legend": "Find a blocked user",
        "import-summary": "",
        "importinterwiki": "Transwiki import",
        "import-interwiki-text": "Select a wiki and page title to import.\nRevision dates and editors' names will be preserved.\nAll transwiki import actions are logged at the [[Special:Log/import|import log]].",
-       "import-interwiki-source": "Source wiki/page:",
+       "import-interwiki-sourcewiki": "Source wiki:",
+       "import-interwiki-sourcepage": "Source page:",
        "import-interwiki-history": "Copy all history revisions for this page",
        "import-interwiki-templates": "Include all templates",
        "import-interwiki-submit": "Import",
        "import-upload": "Upload XML data",
        "import-token-mismatch": "Loss of session data.\nPlease try again.",
        "import-invalid-interwiki": "Cannot import from the specified wiki.",
-       "import-error-edit": "Page \"$1\" is not imported because you are not allowed to edit it.",
-       "import-error-create": "Page \"$1\" is not imported because you are not allowed to create it.",
-       "import-error-interwiki": "Page \"$1\" is not imported because its name is reserved for external linking (interwiki).",
-       "import-error-special": "Page \"$1\" is not imported because it belongs to a special namespace that does not allow pages.",
-       "import-error-invalid": "Page \"$1\" is not imported because its name is invalid.",
+       "import-error-edit": "Page \"$1\" was not imported because you are not allowed to edit it.",
+       "import-error-create": "Page \"$1\" was not imported because you are not allowed to create it.",
+       "import-error-interwiki": "Page \"$1\" was not imported because its name is reserved for external linking (interwiki).",
+       "import-error-special": "Page \"$1\" was not imported because it belongs to a special namespace that does not allow pages.",
+       "import-error-invalid": "Page \"$1\" was not imported because the name to which it would be imported is invalid on this wiki.",
        "import-error-unserialize": "Revision $2 of page \"$1\" could not be unserialized. The revision was reported to use content model $3 serialized as $4.",
        "import-error-bad-location": "Revision $2 using content model $3 cannot be stored on \"$1\" on this wiki, since that model is not supported on that page.",
        "import-options-wrong": "Wrong {{PLURAL:$2|option|options}}: <nowiki>$1</nowiki>",
        "importlogpage": "Import log",
        "importlogpagetext": "Administrative imports of pages with edit history from other wikis.",
        "import-logentry-upload": "imported [[$1]] by file upload",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revision|revisions}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revision|revisions}} imported",
        "import-logentry-interwiki": "transwikied $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revision|revisions}} from $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revision|revisions}} imported from $2",
        "javascripttest": "JavaScript testing",
        "javascripttest-backlink": "< $1",
        "javascripttest-title": "Running $1 tests",
        "autosumm-replace": "Replaced content with \"$1\"",
        "autoredircomment": "Redirected page to [[$1]]",
        "autosumm-new": "Created page with \"$1\"",
+       "autosumm-newblank": "Created blank page",
        "autoblock_whitelist": "AOL http://webmaster.info.aol.com/proxyinfo.html\n*64.12.96.0/19\n*149.174.160.0/20\n*152.163.240.0/21\n*152.163.248.0/22\n*152.163.252.0/23\n*152.163.96.0/22\n*152.163.100.0/23\n*195.93.32.0/22\n*195.93.48.0/22\n*195.93.64.0/19\n*195.93.96.0/19\n*195.93.16.0/20\n*198.81.0.0/22\n*198.81.16.0/20\n*198.81.8.0/23\n*202.67.64.128/25\n*205.188.192.0/20\n*205.188.208.0/23\n*205.188.112.0/20\n*205.188.146.144/30\n*207.200.112.0/21",
        "size-bytes": "$1 B",
        "size-kilobytes": "$1 KB",
        "timezone-utc": "UTC",
        "unknown_extension_tag": "Unknown extension tag \"$1\"",
        "duplicate-defaultsort": "<strong>Warning:</strong> Default sort key \"$2\" overrides earlier default sort key \"$1\".",
+       "duplicate-displaytitle": "<strong>Warning:</strong> Display title \"$2\" overrides earlier display title \"$1\".",
        "version": "Version",
        "version-summary": "",
        "version-extensions": "Installed extensions",
        "version-software": "Installed software",
        "version-software-product": "Product",
        "version-software-version": "Version",
-       "version-db-mysql-url": "http://www.mysql.com/",
-       "version-db-mariadb-url": "http://mariadb.org/",
+       "version-db-mysql-url": "https://www.mysql.com/",
+       "version-db-mariadb-url": "https://mariadb.org/",
        "version-db-percona-url": "http://www.percona.com/software/percona-server",
        "version-db-postgres-url": "http://www.postgresql.org/",
        "version-db-oracle-url": "http://www.oracle.com/database/",
-       "version-db-sqlite-url": "http://www.sqlite.org/",
-       "version-db-mssql-url": "http://www.microsoft.com/sql/",
+       "version-db-sqlite-url": "https://www.sqlite.org/",
+       "version-db-mssql-url": "https://www.microsoft.com/sql/",
        "version-entrypoints": "Entry point URLs",
        "version-entrypoints-header-entrypoint": "Entry point",
        "version-entrypoints-header-url": "URL",
        "logentry-rights-rights": "$1 {{GENDER:$2|changed}} group membership for $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",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|uploaded}} a new version of $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|uploaded}} $3",
        "rightsnone": "(none)",
        "revdelete-logentry": "changed revision visibility of \"[[$1]]\"",
        "logdelete-logentry": "changed event visibility of \"[[$1]]\"",
        "action-pagelang": "change the page language",
        "log-name-pagelang": "Change language log",
        "log-description-pagelang": "This is a log of changes in page languages.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|changed}} page language for $3 from $4 to $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|changed}} page language for $3 from $4 to $5.",
+       "default-skin-not-found": "Whoops! The default skin for your wiki, defined in <code dir=\"ltr\">$wgDefaultSkin</code> as <code>$1</code>, is not available.\n\nYour installation seems to include the following skins. See [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Skin configuration] for information how to enable them and choose the default.\n\n$2\n\n; If you have just installed MediaWiki:\n: You probably installed from git, or directly from the source code using some other method. This is expected. Try installing some skins from [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's skin directory], by:\n:* Downloading the [https://www.mediawiki.org/wiki/Download tarball installer], which comes with several skins and extensions. You can copy and paste the <code>skins/</code> directory from it.\n:* Cloning one of the <code>mediawiki/skins/*</code> repositories via git into the <code dir=\"ltr\">skins/</code> directory of your MediaWiki installation.\n: Doing this should not interfere with your git repository if you're a MediaWiki developer.\n\n; If you have just upgraded MediaWiki:\n: MediaWiki 1.24 and newer no longer automatically enables installed skins (see [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: Skin autodiscovery]). You can paste the following lines into <code>LocalSettings.php</code> to enable all currently installed skins:\n\n<pre dir=\"ltr\">$3</pre>\n\n; If you have just modified <code>LocalSettings.php</code>:\n: Double-check the skin names for typos.",
+       "default-skin-not-found-no-skins": "Whoops! The default skin for your wiki, defined in <code>$wgDefaultSkin</code> as <code>$1</code>, is not available.\n\nYou have no installed skins.\n\n; If you have just installed or upgraded MediaWiki:\n: You probably installed from git, or directly from the source code using some other method. This is expected. MediaWiki 1.24 and newer doesn't include any skins in the main repository. Try installing some skins from [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's skin directory], by:\n:* Downloading the [https://www.mediawiki.org/wiki/Download tarball installer], which comes with several skins and extensions. You can copy and paste the <code>skins/</code> directory from it.\n:* Cloning one of the <code>mediawiki/skins/*</code> repositories via git into the <code dir=\"ltr\">skins/</code> directory of your MediaWiki installation.\n: Doing this should not interfere with your git repository if you're a MediaWiki developer. See [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Skin configuration] for information how to enable skins and choose the default.\n",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (enabled)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''disabled''')"
 }
index 45dc6b7..303a4c6 100644 (file)
@@ -37,7 +37,8 @@
                        "Yekrats",
                        "Александр Сигачёв",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Fitoschido"
                ]
        },
        "tog-underline": "Substreki ligilojn",
        "talkpagelinktext": "Diskuto",
        "specialpage": "Speciala Paĝo",
        "personaltools": "Personaj iloj",
-       "postcomment": "Nova sekcio",
        "articlepage": "Rigardi artikolon",
        "talk": "Diskuto",
        "views": "Vidoj",
        "hidetoc": "kaŝi",
        "collapsible-collapse": "kaŝi",
        "collapsible-expand": "Montri",
+       "confirmable-yes": "Jes",
+       "confirmable-no": "Ne",
        "thisisdeleted": "Vidi aŭ restarigi $1?",
        "viewdeleted": "Ĉu rigardi $1?",
        "restorelink": "{{PLURAL:$1|unu forigitan version|$1 forigitajn versiojn}}",
        "externaldberror": "Aŭ estis datenbaza eraro rilate al ekstera aŭtentikigado, aŭ vi ne rajtas ĝisdatigi vian eksteran konton.",
        "login": "Ensaluti",
        "nav-login-createaccount": "Ensaluti / Krei novan konton",
-       "loginprompt": "Via foliumilo nepre permesu kuketojn por ensaluti en la {{SITENAME}}.",
        "userlogin": "Ensaluti / Krei novan konton",
        "userloginnocreate": "Ensaluti",
        "logout": "Elsaluti",
        "revdelete-offender": "Aŭtoro de revizio:",
        "suppressionlog": "Protokolo pri subigado",
        "suppressionlogtext": "Malsupre estas listo de forigoj kaj forbaroj pri enhavo kaŝita de administrantoj.\nRigardu la [[Special:BlockList|forbarliston]] por la listo de nune operaciaj forbaroj kaj forigoj.",
-       "mergehistory": "Kunfandigi historiojn de paĝoj",
+       "mergehistory": "Kunigi historiojn de paĝoj",
        "mergehistory-header": "Ĉi tiu paĝo permesas al vi kunigi versiojn de la historio de unu fonta paĝo en pli novan paĝon.\nCertigu ke ĉi tiu ŝanĝo tenos kontinuecon de la historia paĝo.",
        "mergehistory-box": "Kunigi versiojn de du paĝoj:",
        "mergehistory-from": "Fontpaĝo:",
        "editundo": "malfari",
        "diff-empty": "(Neniu diferenco)",
        "diff-multi-sameuser": "({{PLURAL:$1|Unu meza versio|$1 mezaj versioj}} de la sama uzanto ne montriĝas)",
-       "diff-multi-otherusers": "({{PLURAL:$1|Unu meza versio|$1 mezaj versioj}} de {{PLURAL:$2|alia uzanto|$2 uzoj}} ne montriĝas)",
+       "diff-multi-otherusers": "({{PLURAL:$1|Unu meza versio|$1 mezaj versioj}} de {{PLURAL:$2|alia uzanto|$2 uzantoj}} ne montriĝas)",
        "diff-multi-manyusers": "({{PLURAL:$1|Unu intermeza versio|$1 intermezaj versioj}} de pli ol {{PLURAL:$2|unu uzanto|$2 uzantoj}} ne estas {{PLURAL:$1|montrata|montrataj}}.)",
        "difference-missing-revision": "{{PLURAL:$2|Unu revizio|$2 revizioj}} de ĉi tiu malsameco ($1) ne {{PLURAL:$2|estis|estis}} trovebla.\n\nLa kutima kaŭzo estas sekvi malaktualan malsamo-ligilon al paĝo forviŝita.\nDetaloj troveblos en la [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de forviŝoj].",
        "searchresults": "Serĉrezultoj",
        "searchprofile-advanced-tooltip": "Serĉi en specialaj nomspacoj",
        "search-result-size": "$1 ({{PLURAL:$2|1 vorto|$2 vortoj}})",
        "search-result-category-size": "{{PLURAL:$1|1 membro|$1 membroj}} ({{PLURAL:$2|1 subkategorio|$2 subkategorioj}}, {{PLURAL:$3|1 dosiero|$3 dosieroj}})",
-       "search-result-score": "Trafeco: $1%",
        "search-redirect": "(alidirektilo $1)",
        "search-section": "(sekcio $1)",
        "search-suggest": "Ĉu vi intenciis: $1",
        "powersearch-togglelabel": "Elekti:",
        "powersearch-toggleall": "Ĉion",
        "powersearch-togglenone": "Nenion",
+       "powersearch-remember": "Memori elekton por estontaj serĉoj",
        "search-external": "Ekstera serĉo",
        "searchdisabled": "<p>Oni provizore malŝaltis serĉadon per la plenteksta\nindekso pro troŝarĝita servilo. Intertempe, vi povas serĉi per <i>guglo</i> aŭ per <i>jahu!</i>:</p>",
        "search-error": "Okazis eraro dum serĉado: $1",
        "right-upload": "Alŝuti dosierojn",
        "right-reupload": "Anstataŭigi ekzistantan dosieron",
        "right-reupload-own": "Anstataŭigi ekzistantan dosieron alŝutitan de la sama uzanto",
-       "right-reupload-shared": "Anstataŭigi dosierojn en la komuna bildprovizejo loke",
+       "right-reupload-shared": "Anstataŭigi dosierojn en la komuna bildprovizejo ĉi-loke",
        "right-upload_by_url": "Alŝuti dosieron de URL-adreso",
        "right-purge": "Refreŝigi la retejan kaŝmemoron por paĝo sen konfirma paĝo",
        "right-autoconfirmed": "Redakti duone protektitajn paĝojn",
        "right-deletedtext": "Rigardi forigitan tekston kaj ŝanĝojn inter forigitaj revizioj.",
        "right-browsearchive": "Serĉi forigitajn paĝojn",
        "right-undelete": "Restarigi paĝon",
-       "right-suppressrevision": "Kontroli kaj restarigi versiojn kaŝitajn de administrantoj",
+       "right-suppressrevision": "Montri, kaŝi kaj malkaŝi specifajn paĝajn versiojn de ajna uzanto",
        "right-suppressionlog": "Vidi privatajn protokolojn",
        "right-block": "Forbari aliajn uzantoj de redaktado",
        "right-blockemail": "Forbari uzanton de retpoŝta sendado",
        "uploadwarning": "Alŝuta averto",
        "uploadwarning-text": "Bonvolu ŝanĝi la dosieran priskribon kaj reprovi.",
        "savefile": "Konservi dosieron",
-       "uploadedimage": "alŝutis \"[[$1]]\"",
-       "overwroteimage": "alŝutis novan version de \"[[$1]]\"",
        "uploaddisabled": "Alŝutado estas malŝaltita",
        "copyuploaddisabled": "Alŝuto de URL malfunkciigita.",
        "uploaddisabledtext": "Alŝutado de dosieroj estas malebligita.",
        "license-nopreview": "(Antaŭvido ne montrebla)",
        "upload_source_url": " (valida, publike atingebla URL-o)",
        "upload_source_file": " (dosiero en via komputilo)",
+       "listfiles-delete": "forigi",
        "listfiles-summary": "Ĉi tiu speciala paĝo montras ĉiujn alŝutitajn dosierojn.\nKiam oni filtras ĝin laŭ uzanto, nur la aktuala versio de la dosiero estos montrita.",
        "listfiles_search_for": "Serĉi dosieran nomon:",
        "imgfile": "dosiero",
        "randomincategory": "Hazarda paĝo en kategorio",
        "randomincategory-invalidcategory": "\"$1\" ne estas valida kategoria nomo.",
        "randomincategory-nopages": "Ne estas paĝoj en la kategorio [[:Category:$1|$1]].",
-       "randomincategory-selectcategory": "Iri al hazarda paĝo el kategorio: $1 $2.$1",
-       "randomincategory-selectcategory-submit": "Ek!",
        "randomredirect": "Hazarda alidirekto",
        "randomredirect-nopages": "Estas neniuj alidirektiloj en la nomspaco \"$1\".",
        "statistics": "Statistiko",
        "listgrouprights-namespaceprotection-header": "Nomspacaj restriktoj",
        "listgrouprights-namespaceprotection-namespace": "Nomspaco",
        "listgrouprights-namespaceprotection-restrictedto": "Rajtoj, kiuj permesas al uzanto redakti",
+       "trackingcategories": "Kategorioj por kontrolado",
+       "trackingcategories-summary": "Ĉi tiu paĝo listigas kategoriojn por kontrolado, aŭtomate farita de la Mediavikia programaro. Ties nomoj estas ŝanĝebla, ŝanĝante la paran sistemmesaĝon en la nomspaco {{ns:8}}.",
+       "trackingcategories-msg": "Kategorio pri kontrolado",
        "trackingcategories-name": "Nomo de mesaĝo",
+       "trackingcategories-desc": "Kriterio por inkluzivi kategorion",
        "trackingcategories-nodesc": "Neniu priskribo estas disponebla.",
        "trackingcategories-disabled": "Kategorio estas malaktivigita",
        "mailnologin": "Neniu alsendota adreso",
        "addedwatchtext": "La paĝo \"[[:$1]]\" aldoniĝis al via [[Special:Watchlist|atentaro]]. Estontaj ŝanĝoj de tiu paĝo kaj de ĝia rilata diskutpaĝo aperos tie.",
        "removewatch": "Forigi el atentaro",
        "removedwatchtext": "La paĝo \"[[:$1]]\" estas forigita el via [[Special:Watchlist|atentaro]].",
+       "removedwatchtext-short": "La paĝo \"$1\" estis forigita el via atento-listo.",
        "watch": "Atenti",
        "watchthispage": "Priatenti paĝon",
        "unwatch": "Malatenti",
        "watchlist-details": "{{PLURAL:$1|$1 paĝo|$1 paĝoj}} en via atentaro, ne aparte kalkulante diskutpaĝojn.",
        "wlheader-enotif": "Retpoŝta sciigo estas ŝalta.",
        "wlheader-showupdated": "Paĝoj montriĝis per '''dikaj literoj''' kiuj estis ŝanĝitaj ekde vi laste vizitis.",
-       "wlnote2": "Malsupre estas la ŝanĝoj en la {{PLURAL:$1|lasta horo|lastaj <strong>$1</strong> horoj}}, ekde $2, $3.",
+       "wlnote": "Jen la {{PLURAL:$1|lasta redakto|lastaj <strong>$1</strong> redaktoj}} dum la {{PLURAL:$2|lasta horo|lastaj <strong>$2</strong> horoj}}, ekde $3, $4.",
        "wlshowlast": "Montri el lastaj $1 horoj $2 tagoj $3",
        "watchlist-options": "Opcioj por atentaro",
        "watching": "Aldonante al la atentaro...",
        "import": "Importi paĝojn",
        "importinterwiki": "Transvikia importo",
        "import-interwiki-text": "Elektu vikion kaj paĝan titolon por importi.\nDatoj de versioj kaj nomoj de redaktantoj estos preservitaj.\nĈiuj transvikaj importoj estas raportitaj ĉe la [[Special:Log/import|loglibro de importoj]].",
-       "import-interwiki-source": "Fonta vikio/paĝo:",
        "import-interwiki-history": "Kopiu ĉiujn historiajn versiojn por ĉi tiu pago.",
        "import-interwiki-templates": "Inkluzivi ĉiujn ŝablonojn",
        "import-interwiki-submit": "Importi",
        "newimages-summary": "Ĉi tiu speciala paĝo montras la lastajn alŝutitajn dosierojn.",
        "newimages-legend": "Dosiernomo",
        "newimages-label": "Dosiernomo (aŭ parto de ĝi):",
+       "newimages-showbots": "Montri alŝutojn per robotoj",
        "noimages": "Nenio videbla.",
        "ilsubmit": "Serĉi",
        "bydate": "laŭ dato",
        "version-hook-name": "Nomo de hoko",
        "version-hook-subscribedby": "Abonita de",
        "version-version": "($1)",
+       "version-no-ext-name": "[sen nomo]",
        "version-license": "Permesilo de MediaWiki",
        "version-ext-license": "Permesilo",
        "version-ext-colheader-name": "Etendilo",
+       "version-skin-colheader-name": "Etoso",
        "version-ext-colheader-version": "Versio",
        "version-ext-colheader-license": "Permesilo",
        "version-ext-colheader-description": "Priskribo",
        "expand_templates_remove_nowiki": "Nuligi <nowiki> etikedojn en rezulto",
        "expand_templates_generate_xml": "Montri XML-sintaksarbon",
        "expand_templates_generate_rawhtml": "Montri krudan HTML-n",
-       "expand_templates_preview": "Antaŭrigardo"
+       "expand_templates_preview": "Antaŭrigardo",
+       "pagelang-name": "Paĝo",
+       "pagelang-language": "Lingvo",
+       "pagelang-use-default": "Uzi defaŭltan lingvon",
+       "pagelang-select-lang": "Elekti la lingvon",
+       "right-pagelang": "Ŝanĝi paĝan lingvon",
+       "action-pagelang": "ŝanĝi la lingvon de la paĝo",
+       "log-name-pagelang": "Ŝanĝi la lingvan protokolon",
+       "log-description-pagelang": "Jen protokolo pri ŝanĝoj de paĝaj lingvoj.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|ŝanĝis}} la paĝan lingvon por $3 de $4 al $5."
 }
index fa41f55..00a866a 100644 (file)
                        "Wifidel",
                        "Macofe",
                        "Koavf",
-                       "Themasterriot"
+                       "Themasterriot",
+                       "AVIADOR",
+                       "F3RaN",
+                       "Amitie 10g"
                ]
        },
        "tog-underline": "Subrayar los enlaces:",
        "tog-watchdefault": "Añadir las páginas y archivos que edite a mi lista de seguimiento",
        "tog-watchmoves": "Añadir las páginas y archivos que mueva a mi lista de seguimiento",
        "tog-watchdeletion": "Añadir las páginas y archivos que borre a mi lista de seguimiento",
+       "tog-watchrollback": "Añadir las páginas donde realicé una reversión a mi lista de seguimento",
        "tog-minordefault": "Marcar todas las ediciones como menores de manera predeterminada",
        "tog-previewontop": "Mostrar previsualización antes del cuadro de edición",
        "tog-previewonfirst": "Mostrar previsualización en la primera edición",
        "talkpagelinktext": "Discusión",
        "specialpage": "Página especial",
        "personaltools": "Herramientas personales",
-       "postcomment": "Sección nueva",
        "articlepage": "Ver artículo",
        "talk": "Discusión",
        "views": "Vistas",
        "otherlanguages": "Otros idiomas",
        "redirectedfrom": "(Redirigido desde «$1»)",
        "redirectpagesub": "Página de redirección",
-       "lastmodifiedat": "Esta página fue modificada por última vez el $1, a las $2.",
+       "redirectto": "Redirigir a:",
+       "lastmodifiedat": "Esta página fue modificada por última vez el $1 a las $2.",
        "viewcount": "Esta página se ha visitado {{PLURAL:$1|una vez|$1 veces}}.",
        "protectedpage": "Página protegida",
        "jumpto": "Saltar a:",
        "jumptosearch": "buscar",
        "view-pool-error": "Lo sentimos, los servidores están sobrecargados en este momento.\nHay demasiados usuarios que están tratando de ver esta página.\nEspera un momento antes de tratar de acceder nuevamente a esta página.\n\n$1",
        "generic-pool-error": "Lo sentimos, los servidores están sobrecargados en este momento.\nHay demasiados usuarios que están tratando de ver este recurso.\nEspera un momento antes de tratar de acceder nuevamente a este recurso.",
-       "pool-timeout": "Tiempo limite agotado para el bloqueo",
+       "pool-timeout": "Se agotó el tiempo de espera del candado",
        "pool-queuefull": "La cola de trabajo está llena",
        "pool-errorunknown": "Error desconocido",
-       "pool-servererror": "El servicio de contador de la piscina no está disponible ($1).",
+       "pool-servererror": "El servicio de gestión de procesos agrupados no está disponible ($1).",
        "aboutsite": "Acerca de {{SITENAME}}",
        "aboutpage": "Project:Acerca de",
-       "copyright": "El contenido está disponible bajo  $1  a menos que se indique lo contrario.",
+       "copyright": "El contenido está disponible bajo la licencia $1 a menos que se indique lo contrario.",
        "copyrightpage": "{{ns:project}}:Derechos de autor",
        "currentevents": "Actualidad",
        "currentevents-url": "Project:Actualidad",
        "versionrequiredtext": "Se necesita la versión $1 de MediaWiki para utilizar esta página. Para más información, consultar [[Special:Version|la página de versión]]",
        "ok": "Aceptar",
        "retrievedfrom": "Obtenido de «$1»",
-       "youhavenewmessages": "Tienes $1 ($2).",
-       "youhavenewmessagesfromusers": "Tienes $1 de {{PLURAL:$3|otro usuario|$3 usuarios}} ($2).",
+       "youhavenewmessages": "{{PLURAL:$3|Tienes}} $1 ($2).",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|Tienes}} $1 de {{PLURAL:$3|otro usuario|$3 usuarios}} ($2).",
        "youhavenewmessagesmanyusers": "Tienes $1 de muchos usuarios ($2).",
        "newmessageslinkplural": "{{PLURAL:$1|un mensaje nuevo|999=mensajes nuevos}}",
        "newmessagesdifflinkplural": "{{PLURAL:$1|último cambio|999=últimos cambios}}",
        "editlink": "modificar",
        "viewsourcelink": "ver código",
        "editsectionhint": "Editar sección: $1",
-       "toc": "Contenidos",
+       "toc": "Contenido",
        "showtoc": "mostrar",
        "hidetoc": "ocultar",
        "collapsible-collapse": "Contraer",
        "collapsible-expand": "Expandir",
+       "confirmable-confirm": "¿Estás {{GENDER:$1|seguro|segura}}?",
+       "confirmable-yes": "Sí",
+       "confirmable-no": "No",
        "thisisdeleted": "¿Ver o restaurar $1?",
        "viewdeleted": "¿Quieres ver $1?",
        "restorelink": "{{PLURAL:$1|una edición borrada|$1 ediciones borradas}}",
        "invalidtitle-knownnamespace": "El título con el espacio de nombres «$2» y el texto «$3» no es válido",
        "invalidtitle-unknownnamespace": "El título con el espacio de nombres desconocido (n.º $1) y el texto «$2» no es válido",
        "exception-nologin": "No has iniciado sesión",
-       "exception-nologin-text": "[[Special:Userlogin|Inicia sesión]] para acceder a esta página o acción.",
+       "exception-nologin-text": "Necesitas acceder para ver esta página o llevar a cabo esta acción.",
        "exception-nologin-text-manual": "Necesitas $1 para acceder a esta página o acción.",
        "virus-badscanner": "Configuración incorrecta: antivirus desconocido: <em>$1</em>",
        "virus-scanfailed": "falló el análisis (código $1)",
        "yourdomainname": "Tu dominio:",
        "password-change-forbidden": "No puedes cambiar las contraseñas en este wiki.",
        "externaldberror": "Hubo un error de autenticación de la base de datos o bien no tienes autorización para actualizar tu cuenta externa.",
-       "login": "Iniciar sesión",
+       "login": "Acceder",
        "nav-login-createaccount": "Acceder/crear cuenta",
-       "loginprompt": "Hay que activar las ''cookies'' en el navegador para iniciar sesión en {{SITENAME}}.",
        "userlogin": "Acceder/crear cuenta",
        "userloginnocreate": "Acceder",
        "logout": "Salir",
        "userlogin-resetlink": "¿Olvidaste tus datos de acceso?",
        "userlogin-resetpassword-link": "¿Has olvidado tu contraseña?",
        "userlogin-helplink2": "Ayuda con el acceso",
-       "userlogin-loggedin": "Ya estás conectado como {{GENDER:$1|$1}}.\nUsa el formulario de abajo para iniciar sesión como otro usuario.",
-       "userlogin-createanother": "Crear otra cuenta",
        "createacct-emailrequired": "Dirección de correo electrónico",
        "createacct-emailoptional": "Dirección de correo electrónico (opcional)",
        "createacct-email-ph": "Escribe tu dirección de correo electrónico",
        "createaccount-text": "Alguien creó en {{SITENAME}} ($4) una cuenta asociada a este correo electrónico con el nombre «$2» y contraseña «$3». Por favor entra ahora y cambia tu contraseña.\n\nPuedes ignorar este mensaje si esta cuenta fue creada por error.",
        "login-throttled": "Has intentado demasiadas veces iniciar sesión recientemente. Por favor espera $1 antes de intentarlo nuevamente.",
        "login-abort-generic": "Tu inicio de sesión no fue exitoso - Cancelado",
+       "login-migrated-generic": "Tu cuenta se ha migrado y tu nombre de usuario ya no existen en este wiki.",
        "loginlanguagelabel": "Idioma: $1",
        "suspicious-userlogout": "Tu solicitud de desconexión ha sido denegada, pues parece haber sido enviada desde un navegador defectuoso o un proxy caché.",
        "createacct-another-realname-tip": "El nombre real es opcional.\nSi se proporciona, se usará para dar al usuario la atribución de su trabajo.",
        "preview": "Previsualizar",
        "showpreview": "Mostrar previsualización",
        "showdiff": "Mostrar los cambios",
-       "anoneditwarning": "<strong>Advertencia:</strong> No has iniciado sesión.\nTu dirección IP se almacenará en el historial de edición de esta página.",
+       "blankarticle": "<strong>Aviso:</strong> estás a punto de crear una página vacía.\nSi pulsas en «{{int:savearticle}}» de nuevo, se creará la página sin ningún contenido.",
+       "anoneditwarning": "<strong>Advertencia:</strong> No has iniciado sesión. Tu dirección IP será visible públicamente si haces cualquier edición. Si <strong>[$1 inicias sesión]</strong> o <strong>[$2 creas una cuenta]</strong>, tus ediciones se atribuirán a tu nombre de usuario, junto con otros beneficios.",
        "anonpreviewwarning": "<em>No has iniciado sesión. Al guardar los cambios se almacenará tu dirección IP en el historial de edición de esta página.</em>",
        "missingsummary": "<strong>Recordatorio:</strong> No has escrito un resumen de edición.\nSi haces clic nuevamente en «{{int:savearticle}}» tu edición se grabará sin él.",
        "missingcommenttext": "Escribe un comentario a continuación.",
        "parser-template-recursion-depth-warning": "Se ha excedido el límite de recursión de plantillas ($1)",
        "language-converter-depth-warning": "El límite de profundidad del convertidor de idioma ha excedido ($1)",
        "node-count-exceeded-category": "Páginas donde se supera el número de nodos",
-       "node-count-exceeded-category-desc": "Una categoría para las páginas donde se supera el número de nodos.",
+       "node-count-exceeded-category-desc": "La página supera el número máximo de nodos.",
        "node-count-exceeded-warning": "Página que ha superado el número de nodos",
        "expansion-depth-exceeded-category": "Páginas donde se supera la profundidad de expansión",
-       "expansion-depth-exceeded-category-desc": "Esta es una categoría para las páginas donde se supera la profundidad de expansión.",
+       "expansion-depth-exceeded-category-desc": "Esta página supera el límite de extensión.",
        "expansion-depth-exceeded-warning": "Página que ha superado la profundidad de expansión",
        "parser-unstrip-loop-warning": "Se ha detectado un bucle \"unstrip\"",
        "parser-unstrip-recursion-limit": "Se ha superado el límite de recursión de \"unstrip\" ($1)",
        "rev-deleted-event": "(entrada borrada)",
        "rev-deleted-user-contribs": "[nombre de usuario o dirección IP eliminada - edición ocultada de la lista de contribuciones]",
        "rev-deleted-text-permission": "Esta revisión de la página ha sido '''borrada'''.\nPuede haber detalles en el [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de borrados].",
+       "rev-suppressed-text-permission": "Esta revisión de la página se <strong>suprimió</strong>.\nLos detalles se pueden ver en el [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registro de supresión].",
        "rev-deleted-text-unhide": "Esta revisión de la página ha sido '''borrada'''.\nPuede haber más detalles en el [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de borrados].\nComo administrador todavía puedes [$1 ver esta revisión] si así lo deseas.",
        "rev-suppressed-text-unhide": "Esta revisión de la página ha sido '''suprimida'''.\nPuede haber más detalles en el [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registro de supresiones].\nComo administrador podrá seguir [$1 viendo esta revisión] si desea continuar.",
        "rev-deleted-text-view": "Esta revisión de la página ha sido '''borrada'''.\nAún tiene la posibilidad de verla; puede ampliar los detalles en el [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de borrados].",
        "revdelete-text-text": "Las revisiones eliminadas aún aparecerán en el historial de la página, pero parte de su contenido será inaccesible para el público.",
        "revdelete-text-file": "Las versiones de los archivos eliminados aún aparecerán en el historial del archivo, pero partes de su contenido serán inaccesibles para el público.",
        "logdelete-text": "Las revisiones eliminadas aún aparecerán en el historial de la página, pero parte de su contenido será inaccesible para el público.",
-       "revdelete-text-others": "Otros administradores en {{SITENAME}} aun serán capaces de acceder a los contenidos ocultos y pueden restaurarlos a través de esta interfaz, a menos que se establezcan restricciones adicionales.",
+       "revdelete-text-others": "Otros administradores aun serán capaces de acceder a los contenidos ocultos y restaurarlos, a menos que se establezcan restricciones adicionales.",
        "revdelete-confirm": "Por favor confirma que deseas realizar la operación, que entiendes las consecuencias y que estás ejecutando dicha acción acorde con [[{{MediaWiki:Policy-url}}|las políticas]].",
        "revdelete-suppress-text": "La herramienta de supresión '''solo''' debería usarse en los siguientes casos:\n* información potencialmente injuriosa o calumniante.\n* información personal inapropiada, tal como:\n*: ''nombres, domicilios, números de teléfono, números de la seguridad social e información análoga.''",
        "revdelete-legend": "Establecer restricciones de revisión:",
        "mergehistory-go": "Mostrar ediciones fusionables",
        "mergehistory-submit": "Fusionar revisiones",
        "mergehistory-empty": "No hay revisiones fusionables.",
-       "mergehistory-success": "$3 {{PLURAL:$3|revisión|revisiones}} de [[:$1]] fusionadas de forma exitosa en [[:$2]].",
+       "mergehistory-success": "Se {{PLURAL:$3|fusionó $3 revisión|fusionaron $3 revisiones}} de «[[:$1]]» en «[[:$2]]» correctamente.",
        "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-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.",
        "nextn-title": "Próximos $1 {{PLURAL:$1|resultado|resultados}}",
        "shown-title": "Mostrar $1 {{PLURAL:$1|resultado|resultados}} por página",
        "viewprevnext": "Ver ($1 {{int:pipe-separator}} $2) ($3).",
-       "searchmenu-exists": "'''Hay una página llamada «[[:$1]]» en este wiki.'''",
+       "searchmenu-exists": "<strong>Hay una página llamada «[[:$1]]» en este wiki.</strong> {{PLURAL:$2|0=|Véase también los otros resultados de búsqueda encontrados.}}",
        "searchmenu-new": "<strong>Crear la página «[[:$1]]» en este wiki.</strong> {{PLURAL:$2|0=|Véase también la página encontrada con la búsqueda.|Véanse también los resultados de la búsqueda.}}",
        "searchprofile-articles": "Páginas de contenido",
        "searchprofile-images": "Multimedia",
        "searchprofile-advanced-tooltip": "Buscar en espacios de nombres personalizados",
        "search-result-size": "$1 ({{PLURAL:$2|1 palabra|$2 palabras}})",
        "search-result-category-size": "{{PLURAL:$1|1 miembro|$1 miembros}} ({{PLURAL:$2|1 subcategoría|$2 subcategorías}}, {{PLURAL:$3|1 fichero|$3 ficheros}})",
-       "search-result-score": "Relevancia: $1%",
        "search-redirect": "(redirige desde $1)",
        "search-section": "(sección $1)",
        "search-file-match": "(coincide con el contenido del archivo)",
        "searchall": "todos",
        "showingresults": "Abajo se {{PLURAL:$1|muestra '''1''' resultado|muestran hasta '''$1''' resultados}} comenzando por el n.º '''$2'''.",
        "showingresultsinrange": "Abajo se muestran hasta {{PLURAL:$1|<strong>1</strong> resultado|<strong>$1</strong> resultados}} en el rango #<strong>$2</strong> hasta #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Resultado '''$1''' de '''$3'''|Resultados '''$1-$2''' de '''$3'''}} para '''$4'''",
        "search-nonefound": "No hay resultados que cumplan los criterios de búsqueda.",
        "powersearch-legend": "Búsqueda avanzada",
        "powersearch-ns": "Buscar en los espacios de nombres:",
        "preferences": "Preferencias",
        "mypreferences": "Preferencias",
        "prefs-edits": "Cantidad de ediciones:",
-       "prefsnologintext2": "Necesitas $1 para definir las preferencias del usuario.",
+       "prefsnologintext2": "Es necesario acceder para cambiar las preferencias del usuario.",
        "prefs-skin": "Apariencia",
        "skin-preview": "Previsualizar",
        "datedefault": "Sin preferencia",
        "searchresultshead": "Búsquedas",
        "stub-threshold": "Límite para formato de <a href=\"#\" class=\"stub\">enlace a esbozo</a> (bytes):",
        "stub-threshold-disabled": "Desactivado",
-       "recentchangesdays": "Días a mostrar en cambios recientes:",
+       "recentchangesdays": "Días que mostrar en Cambios recientes:",
        "recentchangesdays-max": "(máximo {{PLURAL:$1|un día|$1 días}})",
-       "recentchangescount": "Número de ediciones a mostrar de manera predeterminada:",
+       "recentchangescount": "N.º de ediciones que mostrar de manera predeterminada:",
        "prefs-help-recentchangescount": "Esto incluye cambios recientes, historiales de página, y registros.",
        "prefs-help-watchlist-token2": "Esta es la clave secreta para el canal de contenido web de tu lista de seguimiento.\nCualquier persona que la conozca podría leer tu lista, así que no la compartas.\n[[Special:ResetTokens|Pulsa aquí si necesitas restablecerla]].",
        "savedprefs": "Se han guardado tus preferencias.",
        "gender-unknown": "Prefiero no especificarlo",
        "gender-male": "Masculino",
        "gender-female": "Femenino",
-       "prefs-help-gender": "Opcional: empleado para que sea usado correctamente el género por parte del software. Esta información será pública.",
+       "prefs-help-gender": "Opcional: el software utiliza esta preferencia para dirigirse a ti con el género gramatical apropiado. Esta información es pública.",
        "email": "Correo electrónico",
        "prefs-help-realname": "El nombre real es opcional. Si decides proporcionarlo, se usará para dar atribución a tu trabajo.",
        "prefs-help-email": "La dirección de correo electrónico es opcional, pero es necesaria para el restablecimiento de tu contraseña, en caso de que la olvides.",
        "right-deletedtext": "Ver texto borrado y cambios entre revisiones borradas",
        "right-browsearchive": "Buscar páginas borradas",
        "right-undelete": "Restaurar una página",
-       "right-suppressrevision": "Revisar y restaurar revisiones escondidas por administradores",
+       "right-suppressrevision": "Ver, ocultar y mostrar revisiones específicas de páginas de cualquier usuario",
+       "right-viewsuppressed": "Ver revisiones ocultas de cualquier usuario",
        "right-suppressionlog": "Ver registros privados",
        "right-block": "Bloquear a otros usuarios para que no editen",
        "right-blockemail": "Bloquear a un usuario para que no pueda mandar correos electrónicos",
        "recentchanges-label-plusminus": "El tamaño de la página cambió esta cantidad de bytes",
        "recentchanges-legend-heading": "'''Leyenda:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (véase también la [[Special:NewPages|lista de páginas nuevas]])",
-       "rcnotefrom": "A continuación se presentan los cambios desde <strong> $2 </strong> (hasta <strong> $1 </strong> se muestra).",
+       "rcnotefrom": "Debajo está{{PLURAL:$5|el cambio|n los cambios}} desde <strong>$3, $4</strong> (se muestran hasta <strong>$1</strong>).",
        "rclistfrom": "Mostrar nuevos cambios desde $2, $3",
        "rcshowhideminor": "$1 ediciones menores",
        "rcshowhideminor-show": "Mostrar",
        "uploadwarning": "Advertencia de subida de archivo",
        "uploadwarning-text": "Por favor, modifique la descripción del archivo abajo indicada e inténtelo de nuevo.",
        "savefile": "Guardar archivo",
-       "uploadedimage": "subió «[[$1]]»",
-       "overwroteimage": "subió una nueva versión de «[[$1]]»",
-       "uploaddisabled": "Subida de archivos deshabilitada",
+       "uploaddisabled": "Se desactivó la carga de archivos.",
        "copyuploaddisabled": "Carga por URL deshabilitada.",
-       "uploaddisabledtext": "No es posible subir archivos.",
+       "uploaddisabledtext": "Se desactivó la carga de archivos.",
        "php-uploaddisabledtext": "La subida de archivos está deshabilitada en PHP. Por favor compruebe <code>file_uploads</code> en php.ini.",
        "uploadscripted": "Este archivo contiene script o código HTML que puede ser interpretado erróneamente por un navegador web.",
        "uploadscriptednamespace": "Este archivo SVG contiene un espacio de nombre no permitido '$1'",
        "license": "Licencia:",
        "license-header": "Licencia",
        "nolicense": "Ninguna seleccionada",
+       "licenses-edit": "Editar las opciones de licencia",
        "license-nopreview": "(Previsualización no disponible)",
-       "upload_source_url": " (una URL válida y accesible públicamente)",
-       "upload_source_file": "(un archivo en tu computadora)",
+       "upload_source_url": "(un archivo elegido de una URL válida y accesible públicamente)",
+       "upload_source_file": "(un archivo elegido de tu computadora)",
+       "listfiles-delete": "borrar",
        "listfiles-summary": "Esta página especial muestra todos los archivos subidos.\nCuando el usuario la filtra, solo se muestran los archivos cargados por el usuario en su versión más reciente.",
        "listfiles_search_for": "Buscar por nombre de imagen:",
        "imgfile": "archivo",
        "randomincategory": "Página aleatoria en categoría",
        "randomincategory-invalidcategory": "\"$1\" no es una categoría válida.",
        "randomincategory-nopages": "No hay páginas en la categoría [[:Category:$1|$1]].",
-       "randomincategory-selectcategory": "Obtener una página aleatoria de categoría: $1 $2.",
-       "randomincategory-selectcategory-submit": "Ir",
+       "randomincategory-category": "Categoría:",
+       "randomincategory-legend": "Página aleatoria en categoría",
        "randomredirect": "Ir a una redirección cualquiera",
        "randomredirect-nopages": "No hay redirecciones en el espacio de nombres «$1».",
        "statistics": "Estadísticas",
        "wantedpages-badtitle": "Título inválido en conjunto de resultados: $1",
        "wantedfiles": "Ficheros requeridos",
        "wantedfiletext-cat": "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>. De igual manera, las páginas que incluyen archivos inexistentes se enumeran en [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Los siguientes archivos están en uso, pero no existen. Además, las páginas con archivos que no existen están listadas en [[:$1]].",
        "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",
        "mostlinkedcategories": "Categorías más enlazadas",
        "index-category-desc": "La página contiene la palabra mágica <code><nowiki>__INDEX__</nowiki></code> (y está en un espacio de nombres donde la función está activada); y por ello los robots la indizarán.",
        "post-expand-template-inclusion-category-desc": "Después de expandir todas las plantillas, el tamaño de la página es más grande que <code>$wgMaxArticleSize</code>, así que algunas plantillas no se expandieron.",
        "post-expand-template-argument-category-desc": "Después de expandir un argumento de plantilla (algunos en tres llaves, como <code>{{{Foo}}})</code>, la página es más grande que <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Páginas que contienen demasiadas funciones sintácticas muy costosas (como <code>#ifexist</code>). Consulta [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Categoría añadida cuando una página contiene enlaces rotos a archivos (enlaces a archivos incrustados cuando el archivo no existe).",
-       "hidden-category-category-desc": "Esta es una categoría con <code><nowiki>__HIDDENCAT__</nowiki></code> en ella, que evita que aparezca en el cuadro de enlace de la categoría en las páginas, de forma predeterminada.",
+       "expensive-parserfunction-category-desc": "La página usa demasiadas funciones sintácticas costosas (como <code>#ifexist</code>). Consulta [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "La página contiene un enlace roto a archivos (un enlace para incrustar un archivo cuando el archivo no existe).",
+       "hidden-category-category-desc": "La categoría contiene <code><nowiki>__HIDDENCAT__</nowiki></code> en su página de contenido, lo que evita que aparezca en el cuadro de enlaces de categorías en las páginas, de forma predeterminada.",
        "trackingcategories-nodesc": "No hay descripción disponible.",
        "trackingcategories-disabled": "La categoría está desactivada",
        "mailnologin": "Ninguna dirección de envio",
        "mywatchlist": "Lista de seguimiento",
        "watchlistfor2": "Para $1 $2",
        "nowatchlist": "No tienes ninguna página en tu lista de seguimiento.",
-       "watchlistanontext": "Para ver o editar las entradas de tu lista de seguimiento es necesario $1.",
+       "watchlistanontext": "Es necesario acceder para ver o editar los elementos de tu lista de seguimiento.",
        "watchnologin": "No has iniciado sesión",
        "addwatch": "Añadir a la lista de seguimiento",
        "addedwatchtext": "La página «[[:$1]]» ha sido añadida a tu [[Special:Watchlist|lista de seguimiento]]. Los cambios futuros en esta página y en su página de discusión asociada se indicarán ahí.",
        "watchlist-details": "{{PLURAL:$1|$1 página|$1 páginas}} en su lista de seguimiento, sin contar las de discusión.",
        "wlheader-enotif": "La notificación por correo está activada.",
        "wlheader-showupdated": "Las páginas modificadas desde su última visita aparecen en '''negrita'''.",
-       "wlnote2": "A continuación se muestran los cambios de  {{PLURAL:$1|la última hora|las últimas <strong>$1</strong> horas}}, a partir del $2, $3.",
+       "wlnote": "A continuación {{PLURAL:$1|se muestra el último cambio|se muestran los últimos '''$1''' cambios}} en {{PLURAL:$2|la última hora|las últimas '''$2''' horas}} a fecha de $4 $3.",
        "wlshowlast": "Ver los cambios de las últimas $1 horas, $2 días  $3",
        "watchlist-options": "Opciones de la lista de seguimiento",
        "watching": "Vigilando...",
        "exbeforeblank": "El contenido antes de blanquear era: «$1»",
        "delete-confirm": "Borrar «$1»",
        "delete-legend": "Borrar",
-       "historywarning": "'''Aviso:''' La página que estás a punto de borrar tiene un historial de aproximadamente $1 {{PLURAL:$1|revisión|revisiones}}:",
+       "historywarning": "<strong>Atención:</strong> la página que estás a punto de borrar tiene un historial con $1 {{PLURAL:$1|revisión|revisiones}}:",
        "confirmdeletetext": "Estás a punto de borrar una página en forma permanente, así como todo su historial.\nPor favor, confirma que realmente quieres hacer eso, que entiendes las\nconsecuencias, y que lo estás haciendo de acuerdo con [[{{MediaWiki:Policy-url}}|las políticas]].",
        "actioncomplete": "Acción completada",
        "actionfailed": "Acción fallida",
        "delete-edit-reasonlist": "Editar razones de borrado",
        "delete-toobig": "Esta página tiene un historial muy grande, con más de $1 {{PLURAL:$1|revisión|revisiones}}. Borrar este tipo de páginas ha sido restringido para prevenir posibles problemas en {{SITENAME}}.",
        "delete-warning-toobig": "Esta página tiene un historial de más de $1 {{PLURAL:$1|revisión|revisiones}}. Eliminarla puede perturbar las operaciones de la base de datos de {{SITENAME}}. Ten cuidado al borrar.",
+       "deleteprotected": "No puedes eliminar esta página porque ha sido protegida.",
        "deleting-backlinks-warning": "'''Advertencia:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Otras páginas]] enlazan o transcluyen la página que vas a eliminar.",
        "rollback": "Revertir ediciones",
        "rollback_short": "Revertir",
        "autoblockid": "Bloqueo automático #$1",
        "block": "Bloquear usuario",
        "unblock": "Desbloquear usuario",
-       "blockip": "Bloquear usuario",
+       "blockip": "Bloquear {{GENDER:$1|al usuario|a la usuaria}}",
        "blockip-legend": "Bloquear usuario",
        "blockiptext": "Usa el siguiente formulario para bloquear el acceso de escritura desde una dirección IP específica o nombre de usuario.\nEsto debería hacerse sólo para prevenir vandalismos, y de acuerdo a las [[{{MediaWiki:Policy-url}}|políticas]].\nExplica la razón específica del bloqueo (por ejemplo, citando las páginas en particular que han sido objeto de vandalismo).",
        "ipaddressorusername": "Dirección IP o nombre de usuario:",
        "ipb-unblock-addr": "Desbloquear $1",
        "ipb-unblock": "Desbloquear un usuario o una IP",
        "ipb-blocklist": "Ver bloqueos vigentes",
-       "ipb-blocklist-contribs": "Contribuciones de $1",
+       "ipb-blocklist-contribs": "Contribuciones de {{GENDER:$1|$1}}",
        "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",
        "blocklist-userblocks": "Ocultar bloqueos de cuenta",
        "blocklist-tempblocks": "Ocultar bloqueos temporales",
        "blocklist-addressblocks": "Ocultar bloqueos de una sola dirección IP",
-       "blocklist-rangeblocks": "Ocultar bloqueos de rango",
+       "blocklist-rangeblocks": "Ocultar bloqueos por intervalo",
        "blocklist-timestamp": "Fecha y hora",
        "blocklist-target": "Destino",
        "blocklist-expiry": "Caduca",
        "import": "Importar páginas",
        "importinterwiki": "Importación transwiki",
        "import-interwiki-text": "Selecciona un wiki y un título de página para importar.\nLas fechas de revisiones y los nombres de editores se preservarán.\nTodas las importaciones transwiki se registran en el [[Special:Log/import|registro de importaciones]].",
-       "import-interwiki-source": "Wiki o página origen:",
+       "import-interwiki-sourcewiki": "Wiki de origen:",
+       "import-interwiki-sourcepage": "Página de origen:",
        "import-interwiki-history": "Copiar todas las versiones históricas para esta página",
        "import-interwiki-templates": "Incluir todas las plantillas",
        "import-interwiki-submit": "Importar",
        "import-upload": "Subir datos XML",
        "import-token-mismatch": "Pérdida de datos de sesión. Por favor, inténtalo de nuevo.",
        "import-invalid-interwiki": "No se puede importar de la wiki especificada.",
-       "import-error-edit": "La página $1 no se importó porque no tienes permisos para editarla.",
-       "import-error-create": "La página «$1» no se importó porque no tienes permisos para crearla.",
-       "import-error-interwiki": "La página \"$1\" no se ha importado porque su nombre está reservado para la vinculación externa (interwikis).",
-       "import-error-special": "La página \"$1\" no se ha importado porque pertenece a un espacio de nombres especial que no admite páginas.",
-       "import-error-invalid": "La página \"$1\" no se ha importado porque su nombre no es válido.",
+       "import-error-edit": "No se importó la página «$1» porque no tienes permisos para editarla.",
+       "import-error-create": "No se importó la página «$1» porque no tienes permisos para crearla.",
+       "import-error-interwiki": "No se importó la página «$1» porque su nombre está reservado para los enlaces externos (interwiki).",
+       "import-error-special": "No se importó la página «$1» porque pertenece a un espacio de nombres especial que no admite páginas.",
+       "import-error-invalid": "No se importó la página «$1» porque el nombre de destino para su importación no es válido en este wiki.",
        "import-error-unserialize": "La revisión $2 de la página \"$1\" no pudo dejar de hacerse en serie. Se informó de la revisión para utilizar el modelo de contenidos $3 ejecutado en serie como $4.",
        "import-error-bad-location": "La revisión $2 utilizando el modelo de contenido $3 no se pueden almacenar en \"$1\" en este wiki, ya que ese modelo no es compatible en esa página.",
        "import-options-wrong": "{{PLURAL:$2|Opción errónea|Opciones erróneas}}: <nowiki>$1</nowiki>",
        "importlogpage": "Registro de importaciones",
        "importlogpagetext": "Importaciones administrativas de páginas con historial desde otros wikis.",
        "import-logentry-upload": "importó [[$1]] por subida de archivo",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revisión|revisiones}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revisión importada|revisiones importadas}}",
        "import-logentry-interwiki": "transwikificada $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisión|revisiones}} desde $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisión importada|revisiones importadas}} desde $2",
        "javascripttest": "Pruebas de JavaScript",
        "javascripttest-title": "Pruebas de $1 en ejecución",
        "javascripttest-pagetext-noframework": "Esta página está reservada para ejecutar pruebas de JavaScript.",
        "autosumm-replace": "Página reemplazada por «$1»",
        "autoredircomment": "Página redirigida a [[$1]]",
        "autosumm-new": "Página creada con «$1»",
+       "autosumm-newblank": "Se creó una página vacía",
        "lag-warn-normal": "Los cambios realizados en {{PLURAL:$1|el último segundo|los últimos $1 segundos}} podrían no mostrarse en esta lista.",
        "lag-warn-high": "Debido a una alta latencia el servidor de base de datos, los cambios realizados en {{PLURAL:$1|el último segundo|los últimos $1 segundos}} podrían no mostrarse en esta lista.",
        "watchlistedit-normal-title": "Editar lista de seguimiento",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discusión]])",
        "unknown_extension_tag": "Etiqueta desconocida «$1»",
        "duplicate-defaultsort": "'''Atención:''' La clave de ordenamiento predeterminada «$2» anula la clave de ordenamiento anterior «$1».",
+       "duplicate-displaytitle": "<strong>Advertencia:</strong> El título visualizado \"$2\" sobreescribe al anterior \"$1\".",
        "version": "Versión",
        "version-extensions": "Extensiones instaladas",
        "version-skins": "Temas instalados",
        "revdelete-unrestricted": "restricciones para administradores eliminadas",
        "logentry-move-move": "$1 movió la página $3 a $4",
        "logentry-move-move-noredirect": "$1 movió la página $3 a $4 sin dejar una redirección",
-       "logentry-move-move_redir": "$1 movió la página $3 a $4 sobre una redirección",
-       "logentry-move-move_redir-noredirect": "$1 movió la página $3 a $4 sobre una redirección y sin dejar una redirección",
+       "logentry-move-move_redir": "$1 {{GENDER:$2|trasladó}} la página $3 a $4 sobre una redirección",
+       "logentry-move-move_redir-noredirect": "$1 {{GENDER:$2|trasladó}} la página $3 a $4 sobre una redirección y sin dejar una redirección",
        "logentry-patrol-patrol": "$1 {{GENDER:$2|marcó}} como patrullada la edición $4 de la página $3",
        "logentry-patrol-patrol-auto": "$1 {{GENDER:$2|marcó}} automáticamente la edición $4 de la página $3 como patrullada",
        "logentry-newusers-newusers": "La cuenta de usuario $1 ha sido {{GENDER:$2|creada}}",
        "logentry-rights-rights": "$1 modificó los grupos a los que pertenece $3: de $4 a $5",
        "logentry-rights-rights-legacy": "$1 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",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|subió}} una nueva versión de $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|subió}} $3",
        "rightsnone": "(ninguno)",
        "feedback-bugornote": "Si estás preparado para describir en detalle un problema técnico, [$1 informa de un bug] por favor.\n\nEn otro caso, puedes usar el siguiente formulario. Tu comentario será añadido a la página [$3 $2], junto con tu nombre de usuario y el navegador que usas.",
        "feedback-subject": "Asunto:",
        "action-pagelang": "cambiar el idioma de la página",
        "log-name-pagelang": "Registro de cambios en idiomas",
        "log-description-pagelang": "Este es un registro de los cambios en los idiomas de las páginas.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|cambió}} el idioma de la página «$3» del $4 al $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|cambió}} el idioma de la página «$3» del $4 al $5.",
+       "default-skin-not-found": "¡Oops! La apariencia por defecto de la wiki (<code>$wgDefaultSkin</code>), <code>$1</code>, no está disponible.\n\nLa instalación parece poseer las siguientes opciones de apariencia. Por favor revise [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Skin configuration] para mayor información sobre cómo configurarla y seleccionar la apariencia por defecto.\n\n$2\n\n; Si acaba de instalar MediaWiki:\n: Probablemente la haya instalado desde git, o directamente desde el código fuente usando algún otro método. Esto es lo esperado. Intente instalar algunos sets de apariencia desde [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's skin directory]:\n:* Descargando [https://www.mediawiki.org/wiki/Download el instalador tarball], el cual contiene varios sets de apariencia y extensiones. Puede copiar y pegar el directorio <code>skins/</code> desde ahi.\n:* Clonando uno de los repositorios en <code>mediawiki/skins/*</code> via git dentro del directorio <code>skins/</code> de su instaación de MediaWiki.\n: Haciendo esto no debería interferir con su repositorio git si usted es un desarrollador de MediaWiki.\n\n; Si acaba de actualizar MediaWiki:\n: MediaWiki 1.24 y versiones posteriores ya no tiene habilitada la actualización de apariencia (revise [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: Skin autodiscovery]). Puede pegar las siguientes lineas <code>LocalSettings.php</code> para habilitar todos los sets de apariencia que haya configurado:\n\n<pre>$3</pre>\n\n; Si acaba de modificar <code>LocalSettings.php</code>:\n: Compruebe detenidamente posibles errores tipográficos en los nombres de los sets de apariencias.",
+       "default-skin-not-found-no-skins": "¡Vaya! La apariencia predeterminada de tu wiki (<code>$wgDefaultSkin</code>), <code>$1</code>, no está disponible.\n\nNo tienes apariencias instaladas.\n\n; Si has instalado o actualizado MediaWiki recientemente:\n: Probablemente has instalado desde git, o directamente desde el código fuente usando algún otro método. Esto es lo esperado. MediaWiki 1.24 y versiones posteriores no incluyen ninguna apariencia en el repositorio principal. Trata de instalar algunas apariencias desde el [https://www.mediawiki.org/wiki/Category:All_skins directorio de apariencias de mediawiki.org], siguiendo el siguiente procedimiento:\n:* Descarga el [https://www.mediawiki.org/wiki/Download instalador tarball], que viene con varias apariencias y extensiones. Puedes copiar y pegar el directorio <code>skins/</code> desde ahí.\n:* Clonando alguno de los repositorios en <code>mediawiki/skins/*</code> usando git en el directorio <code>skins/</code> de tu instalación de MediaWiki.\n: Hacer esto no debería interferir con tu repositorio de MediaWiki si eres un desarrollador de MediaWiki. Revisa [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Skin configuration] para información sobre cómo habilitar las apariencias y seleccionar la apariencia predeterminada.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (activado)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''desactivado''')"
 }
index 05c0e32..a98fcf5 100644 (file)
@@ -21,7 +21,8 @@
                        "Silvar",
                        "Võrok",
                        "WikedKentaur",
-                       "לערי ריינהארט"
+                       "לערי ריינהארט",
+                       "Boxmein"
                ]
        },
        "tog-underline": "Linkide allakriipsutus:",
@@ -38,6 +39,7 @@
        "tog-watchdefault": "Lisa jälgimisloendisse minu muudetud leheküljed ja failid",
        "tog-watchmoves": "Lisa jälgimisloendisse minu teisaldatud leheküljed ja failid",
        "tog-watchdeletion": "Lisa jälgimisloendisse minu kustutatud leheküljed ja failid",
+       "tog-watchrollback": "Lisa jälgimisloendisse leheküljed, kus olen muudatuse tühistanud",
        "tog-minordefault": "Märgi kõik parandused vaikimisi pisiparandusteks",
        "tog-previewontop": "Näita eelvaadet toimetamiskasti ees",
        "tog-previewonfirst": "Näita eelvaadet esimesel redigeerimisel",
        "category-file-count-limited": "{{PLURAL:$1|Järgmine fail|Järgmised $1 faili}} on selles kategoorias.",
        "listingcontinuesabbrev": "jätk",
        "index-category": "Indeksiga leheküljed",
-       "noindex-category": "Indeksita leheküljed",
+       "noindex-category": "Indekseerimata leheküljed",
        "broken-file-category": "Katkiste pildilinkidega leheküljed",
        "about": "Tiitelandmed",
        "article": "artikkel",
        "talkpagelinktext": "arutelu",
        "specialpage": "Erilehekülg",
        "personaltools": "Personaalsed tööriistad",
-       "postcomment": "Uus alaosa",
        "articlepage": "Artiklilehekülg",
        "talk": "Arutelu",
        "views": "vaatamisi",
        "otherlanguages": "Teistes keeltes",
        "redirectedfrom": "(Ümber suunatud leheküljelt $1)",
        "redirectpagesub": "Ümbersuunamisleht",
+       "redirectto": "Ümber suunatud lehekülje:",
        "lastmodifiedat": "Viimane muutmine: $2, $1",
        "viewcount": "Seda lehekülge on külastatud {{PLURAL:$1|üks kord|$1 korda}}.",
        "protectedpage": "Kaitstud lehekülg",
        "jumptosearch": "otsi",
        "view-pool-error": "Serverid on hetkel üle koormatud.\nLiiga palju kasutajaid üritab seda lehte vaadata.\nPalun oota hetk, enne kui uuesti proovid.\n\n$1",
        "generic-pool-error": "Kahjuks on serverid praegu üle koormatud.\nLiiga palju kasutajaid proovivad seda ressurssi vaadata.\nPalun oota natuke, enne kui proovid uuesti selle ressursi juurde pääseda.",
+       "pool-timeout": "Ajalõpp luku ootamisel",
+       "pool-queuefull": "Protsessikogumi järjekord on täis.",
        "pool-errorunknown": "Teadmata tõrge",
+       "pool-servererror": "Protsessikogumi loendurteenus pole saadaval ($1).",
        "aboutsite": "{{GRAMMAR:genitive|{{SITENAME}}}} tiitelandmed",
        "aboutpage": "Project:Tiitelandmed",
        "copyright": "Sisu on kasutatav litsentsi $1 tingimustel, kui pole öeldud teisiti.",
        "hidetoc": "peida",
        "collapsible-collapse": "Peida",
        "collapsible-expand": "Näita",
+       "confirmable-confirm": "Kas {{GENDER:$1|oled}} kindel?",
+       "confirmable-yes": "Jah",
+       "confirmable-no": "Ei",
        "thisisdeleted": "Vaata $1 või taasta?",
        "viewdeleted": "Vaata $1?",
        "restorelink": "{{PLURAL:$1|üht|$1}} kustutatud versiooni",
        "badarticleerror": "Seda toimingut ei saa sellel leheküljel sooritada.",
        "cannotdelete": "Lehekülge või faili \"$1\" ei saa kustutada.\nVõimalik, et keegi on selle juba kustutanud.",
        "cannotdelete-title": "Lehekülge \"$1\" ei saa kustutada",
+       "delete-hook-aborted": "Haak katkestas kustutamise.\nSeletust pole toodud.",
        "no-null-revision": "Lehekülje \"$1\" nullredaktsiooni ei õnnestunud teha.",
        "badtitle": "Vigane pealkiri",
        "badtitletext": "Soovitud lehekülje pealkiri oli vigane, tühi või teisest keeleversioonist või vikist valesti lingitud.\nSee võib sisaldada ühte või enamat märki, mida ei saa pealkirjades kasutada.",
        "invalidtitle-knownnamespace": "Vigane pealkiri nimeruumis \"$2\" tekstiga \"$3\"",
        "invalidtitle-unknownnamespace": "Vigane pealkiri nimeruuminumbriga $1 ja tekstiga \"$2\"",
        "exception-nologin": "Sisse logimata",
-       "exception-nologin-text": "Selle lehekülje või toimingu jaoks [[Special:Userlogin|logi]] palun sisse.",
+       "exception-nologin-text": "Selle lehekülje või toimingu jaoks logi palun sisse.",
        "exception-nologin-text-manual": "Pead $1, et sellele leheküljele või toimingule ligi pääseda.",
        "virus-badscanner": "Viga konfiguratsioonis: tundmatu viirusetõrje: ''$1''",
        "virus-scanfailed": "skaneerimine ebaõnnestus (veakood $1)",
        "welcomecreation-msg": "Sinu konto on loodud.\nÄra unusta seada oma {{GRAMMAR:genitive|{{SITENAME}}}} [[Special:Preferences|eelistusi]].",
        "yourname": "Kasutajanimi:",
        "userlogin-yourname": "Kasutajanimi",
-       "userlogin-yourname-ph": "Sisesta oma kasutajanimi",
+       "userlogin-yourname-ph": "Sisesta kasutajanimi",
        "createacct-another-username-ph": "Sisesta kasutajanimi",
        "yourpassword": "Parool:",
        "userlogin-yourpassword": "Parool",
-       "userlogin-yourpassword-ph": "Sisesta oma parool",
+       "userlogin-yourpassword-ph": "Sisesta parool",
        "createacct-yourpassword-ph": "Sisesta parool",
        "yourpasswordagain": "Sisesta parool uuesti:",
        "createacct-yourpasswordagain": "Parooli kinnitus",
        "yourdomainname": "Sinu domeen:",
        "password-change-forbidden": "Selles vikis ei saa paroole muuta.",
        "externaldberror": "Esines autentimistõrge või sul pole õigust konto andmeid muuta.",
-       "login": "Logi sisse",
+       "login": "Sisselogimine",
        "nav-login-createaccount": "Logi sisse või registreeru kasutajaks",
-       "loginprompt": "Sisselogimiseks peavad küpsised lubatud olema.",
        "userlogin": "Sisselogimine või kasutajakonto loomine",
        "userloginnocreate": "Sisselogimine",
        "logout": "Logi välja",
        "userlogin-joinproject": "Ühine projektiga {{SITENAME}}",
        "nologin": "Kas sul pole kontot? $1.",
        "nologinlink": "Registreeru siin",
-       "createaccount": "Loo uus konto",
+       "createaccount": "Konto loomine",
        "gotaccount": "Kui sul on juba konto, '''$1'''.",
        "gotaccountlink": "logi sisse",
        "userlogin-resetlink": "Kas oled unustanud oma sisselogimisandmed?",
        "userlogin-resetpassword-link": "Kas unustasid parooli?",
        "userlogin-helplink2": "Sisselogimisabi",
-       "userlogin-loggedin": "Oled juba sisse logitud nimega {{GENDER:$1|$1}}.\nKasuta allolevat vormi, et logida sisse teise kasutajaga.",
-       "userlogin-createanother": "Loo teine konto",
        "createacct-emailrequired": "E-posti aadress",
        "createacct-emailoptional": "E-posti aadress (valikuline)",
-       "createacct-email-ph": "Sisesta oma e-posti aadress",
+       "createacct-email-ph": "Sisesta e-posti aadress",
        "createacct-another-email-ph": "Sisesta e-posti aadress",
        "createaccountmail": "Kasuta juhuslikku parooli ja saada see määratud e-posti aadressile",
        "createacct-realname": "Pärisnimi (valikuline)",
        "createacct-reason-ph": "Miks lood teist kontot?",
        "createacct-captcha": "Turvakontroll",
        "createacct-imgcaptcha-ph": "Sisesta ülalnähtav tekst",
-       "createacct-submit": "Loo oma konto",
+       "createacct-submit": "Loo konto",
        "createacct-another-submit": "Loo teine konto",
        "createacct-benefit-heading": "{{SITENAME}} on sinusuguste inimeste tehtud.",
        "createacct-benefit-body1": "{{PLURAL:$1|muudatus|muudatust}}",
        "createaccount-text": "Keegi on loonud {{GRAMMAR:illative|{{SITENAME}}}} ($4) sinu e-posti aadressile vastava kasutajatunnuse \"$2\". Parooliks seati \"$3\". Logi sisse ja muuda oma parool.\n\nKui kasutajakonto loomine on eksitus, võid käesolevat sõnumit lihtsalt eirata.",
        "login-throttled": "Oled lühikese aja jooksul proovinud liiga palju kordi sisse logida.\nPalun oota $1, enne kui uuesti proovid.",
        "login-abort-generic": "Sisselogimine ebaõnnestus – Katkestatud",
+       "login-migrated-generic": "Sinu konto on migreeritud ja sinu kasutajanime pole enam selles vikis.",
        "loginlanguagelabel": "Keel: $1",
        "suspicious-userlogout": "Sinu väljalogimiskatse nurjus, sest see näis olevat katkise veebilehitseja või puhverserveri saadetud.",
        "createacct-another-realname-tip": "Tegelik nimi on valikuline.\nKui otsustad selle sisestada, kasutatakse seda kasutaja töö temale omistamiseks.",
        "preview": "Eelvaade",
        "showpreview": "Näita eelvaadet",
        "showdiff": "Näita muudatusi",
-       "anoneditwarning": "'''Hoiatus:''' Sa pole sisse logitud.\nSelle lehe redigeerimislogisse salvestatakse su IP-aadress.",
+       "blankarticle": "<strong>Hoiatus:</strong> Lehekülg, mida alustad, on tühi.\nKui klõpsad uuesti \"{{int:savearticle}}\", luuakse lehekülg ilma sisuta.",
+       "anoneditwarning": "<strong>Hoiatus:</strong> Sa pole sisse logitud. Sinu IP-aadress on kõigile nähtav, kui muudatusi teed. Kui <strong>[$1 logid sisse]</strong> või <strong>[$2 lood konto]</strong>, siis teiste eeliste seas omistatakse sinu muudatused sulle kasutajanime järgi.",
        "anonpreviewwarning": "''Sa pole sisse logitud. Selle lehe redigeerimislogisse salvestatakse su IP-aadress.''",
        "missingsummary": "'''Meeldetuletus:''' Sa ei ole lisanud muudatuse resümeed.\nKui vajutad uuesti salvestamise nupule, salvestatakse muudatus ilma resümeeta.",
        "missingcommenttext": "Palun sisesta siit allapoole kommentaar.",
        "session_fail_preview_html": "'''Vabandust! Meil ei õnnestunud seansiandmete kaotuse tõttu sinu muudatust töödelda.'''\n\n''Kuna {{GRAMMAR:inessive|{{SITENAME}}}} on toor-HTML lubatud, on eelvaade JavaScripti-rünnakute vastase ettevaatusabinõuna peidetud.''\n\n'''Kui see on õigustatud redigeerimiskatse, proovi palun uuesti.'''\nKui see ikka ei tööta, proovi [[Special:UserLogout|välja]] ja tagasi sisse logida.",
        "token_suffix_mismatch": "'''Muudatus lükati tagasi, kuna sinu klienttarkvara ei suuda õigesti kirjavahemärke kasutada.'''\nMuudatus lükati tagasi, et vältida lehekülje segiminekut.\nSee juhtub mõnikord siis, kui kasutatakse vigast veebipõhist anonüümsusserverit.",
        "edit_form_incomplete": "'''Redigeerimisvormi mõni osa ei jõudnud serverisse; kontrolli, kas sinu tehtud muudatused on alles, ja proovi uuesti.'''",
-       "editing": "Muutmisel on $1",
-       "creating": "Alustamisel on $1",
-       "editingsection": "Muutmisel on osa leheküljest $1",
+       "editing": "Muutmisel on \"$1\"",
+       "creating": "Alustamisel on \"$1\"",
+       "editingsection": "Muutmisel on osa leheküljest \"$1\"",
        "editingcomment": "Muutmisel on $1 (uus alaosa)",
        "editconflict": "Redigeerimiskonflikt: $1",
        "explainconflict": "Keegi teine on muutnud seda lehekülge pärast seda, kui sina seda redigeerima hakkasid.\nÜlemine toimetamiskast sisaldab teksti viimast versiooni.\nSinu muudatused on alumises kastis.\nSul tuleb need viimasesse versiooni üle viia.\nKui klõpsad nupule \"{{int:savearticle}}\", salvestub '''ainult''' ülemises toimetamiskastis olev tekst.",
        "parser-template-recursion-depth-warning": "Malli rekursiivse kasutamise limiit on ületatud ($1)",
        "language-converter-depth-warning": "Keeleteisendaja sügavuspiir ületatud ($1)",
        "node-count-exceeded-category": "Ületatud sõlmemääraga leheküljed",
-       "node-count-exceeded-category-desc": "Ületatud sõlmemääraga lehekülgede kategooria.",
+       "node-count-exceeded-category-desc": "Lehekülg ületab sõlmede ülemmäära.",
        "node-count-exceeded-warning": "Lehekülg ületas sõlmemäära.",
        "expansion-depth-exceeded-category": "Ületatud hõrendussügavusega leheküljed",
-       "expansion-depth-exceeded-category-desc": "Ületatud hõrendussügavusega lehekülgede kategooria.",
+       "expansion-depth-exceeded-category-desc": "Lehekülg ületab hõrendussügavuse ülemmäära.",
        "expansion-depth-exceeded-warning": "Lehekülg ületas hõrendussügavuse.",
+       "parser-unstrip-loop-warning": "''Unstrip''-funktsiooni silmus tuvastatud",
+       "parser-unstrip-recursion-limit": "''Unstrip''-funktsioonis rekursiooni piirmäär ületatud ($1)",
        "converter-manual-rule-error": "Tõrge keelevariandi käsivahetusreeglis",
        "undo-success": "Selle redaktsiooni käigus tehtud muudatusi saab eemaldada. Palun kontrolli allolevat võrdlust veendumaks, et tahad need muudatused tõepoolest eemaldada. Seejärel saad lehekülje salvestada.",
        "undo-failure": "Muudatust ei saa vahapeal tehtud redigeerimiste tõttu tühistada.",
        "undo-summary": "Eemaldatud muudatus $1, mille tegi [[Special:Contributions/$2|$2]] ([[User talk:$2|arutelu]])",
        "undo-summary-username-hidden": "Eemaldatud redaktsioon $1, mille tegi peidetud kasutaja",
        "cantcreateaccounttitle": "Ei saa kontot luua",
-       "cantcreateaccount-text": "Kasutaja [[User:$3|$3]] on blokeerinud kasutajanime loomise sellelt IP-aadressilt ('''$1''').\nKasutaja $3 märkis põhjuseks ''$2''",
+       "cantcreateaccount-text": "[[User:$3|$3]] on blokeerinud konto loomise sellelt IP-aadressilt (<strong>$1</strong>).\n\n$3 märkis järgmise põhjuse: <em>$2</em>",
        "cantcreateaccount-range-text": "Kontode loomine IP-aadressidelt vahemikus '''$1''', millesse jääb sinu IP-aadress ('''$4'''), on blokeeritud. Blokeeris kasutaja [[User:$3|$3]].\n\n$3 tõi järgmise põhjuse: ''$2''",
        "viewpagelogs": "Vaata selle lehe logisid",
        "nohistory": "Sellel leheküljel ei ole eelmisi redaktsioone.",
        "rev-deleted-event": "(logitoiming eemaldatud)",
        "rev-deleted-user-contribs": "[kasutajanimi või IP-aadress eemaldatud – muudatust ei näidata]",
        "rev-deleted-text-permission": "See lehekülje redaktsioon on '''kustutatud'''.\nÜksikasju võib olla [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} kustutamise logis].",
+       "rev-suppressed-text-permission": "Lehekülje see redaktsioon on <strong>varjatud</strong>.\nÜksikasju leiad [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} varjamislogist].",
        "rev-deleted-text-unhide": "See lehekülje redaktsioon on '''kustutatud'''.\n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} Kustutamislogis] võib leiduda üksikasju.\nSoovi korral saad siiski [$1 seda redaktsiooni] näha.",
        "rev-suppressed-text-unhide": "See redaktsioon leheküljest on '''varjatud'''.\n[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Varjamislogis] võib leiduda üksikasju.\nSaad soovi korral siiski [$1 seda redaktsiooni vaadata].",
        "rev-deleted-text-view": "See lehekülje redaktsioon on '''kustutatud'''.\nSaad seda näha. [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} Kustutamislogis] võib leiduda üksikasju.",
        "revdelete-text-text": "Kustutatud redaktsioonid jäävad lehekülje ajalukku alles, aga osa nende sisust pole kõigile juurdepääsetav.",
        "revdelete-text-file": "Kustutatud failiversioonid jäävad faili ajalukku alles, aga osa nende sisust pole kõigile juurdepääsetav.",
        "logdelete-text": "Kustutatud logisündmused jäävad logisse alles, aga osa nende sisust pole kõigile juurdepääsetav.",
-       "revdelete-text-others": "Teised {{GRAMMAR:genitive|{{SITENAME}}}} administraatorid pääsevad ikkagi peidetud sisu juurde ja saavad sama liidese kaudu selle taastada, kui seatud pole lisapiiranguid.",
+       "revdelete-text-others": "Teised administraatorid pääsevad ikkagi peidetud sisu juurde ja saavad selle taastada, kui seatud pole lisapiiranguid.",
        "revdelete-confirm": "Kinnita, et soovid tõesti seda teha ning et saad aru tagajärgedest ja tegevus on kooskõlas [[{{MediaWiki:Policy-url}}|siinsete kokkulepetega]].",
        "revdelete-suppress-text": "Andmed tuleks varjata '''ainult''' järgmistel juhtudel:\n* võimalik laim\n* sobimatu isiklik teave\n*: ''kodune aadress ja telefoninumber, isikukood jne''",
        "revdelete-legend": "Nähtavuse piirangute seadmine",
        "shown-title": "Näita lehekülje kohta $1 {{PLURAL:$1|tulemus|tulemust}}",
        "viewprevnext": "Näita ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "'''Lehekülg pealkirjaga \"[[:$1]]\" on olemas.'''",
-       "searchmenu-new": "<strong>Loo lehekülg pealkirjaga \"[[:$1]]\".</strong> {{PLURAL:$2|0=|Vaata ka leitud lehekülge.|Vaata ka leitud otsitulemusi.}}",
+       "searchmenu-new": "<strong>Alusta lehekülge \"[[:$1]]\".</strong> {{PLURAL:$2|0=|Vaata ka leitud lehekülge.|Vaata ka leitud otsitulemusi.}}",
        "searchprofile-articles": "Sisuleheküljed",
        "searchprofile-images": "Multimeedia",
        "searchprofile-everything": "Kõik",
        "searchprofile-advanced-tooltip": "Otsi kohandatud nimeruumidest",
        "search-result-size": "$1 ({{PLURAL:$2|1 sõna|$2 sõna}})",
        "search-result-category-size": "{{PLURAL:$1|1 lehekülg|$1 lehekülge}} ({{PLURAL:$2|1 alamkategooria|$2 alamkategooriat}}, {{PLURAL:$3|1 fail|$3 faili}})",
-       "search-result-score": "Vastavus: $1%",
        "search-redirect": "(ümbersuunamine $1)",
        "search-section": "(alaosa $1)",
        "search-file-match": "(vastab faili sisule)",
        "searchall": "kõik",
        "showingresults": "Allpool näidatakse '''{{PLURAL:$1|ühte|$1}}''' tulemust alates '''$2'''. tulemusest.",
        "showingresultsinrange": "Allpool näidatakse {{PLURAL:$1|<strong>üht</strong>|<strong>$1</strong>}} tulemust vahemikus <strong>$2</strong>–<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|'''$1''' '''$3'''-st vastest|Vasted '''$1–$2''' '''$3'''-st}} päringule '''$4'''",
        "search-nonefound": "Päringule ei leitud vasteid.",
        "powersearch-legend": "Täpsem otsing",
        "powersearch-ns": "Otsing nimeruumidest:",
        "preferences": "Eelistused",
        "mypreferences": "Eelistused",
        "prefs-edits": "Redigeerimiste arv:",
-       "prefsnologintext2": "Pead $1, et oma eelistusi muuta.",
+       "prefsnologintext2": "Palun logi sisse, et oma eelistusi muuta.",
        "prefs-skin": "Kujundus",
        "skin-preview": "eelvaade",
        "datedefault": "Eelistus puudub",
        "prefs-watchlist-edits-max": "Ülemmäär: 1000",
        "prefs-watchlist-token": "Jälgimisloendi luba:",
        "prefs-misc": "Muu",
-       "prefs-resetpass": "Muuda parooli",
+       "prefs-resetpass": "Muuda parool",
        "prefs-changeemail": "Muuda e-posti aadressi",
        "prefs-setemail": "Määra e-posti aadress",
        "prefs-email": "E-posti sätted",
        "prefs-namespaces": "Nimeruumid",
        "default": "vaikeväärtus",
        "prefs-files": "Failid",
-       "prefs-custom-css": "kohandatud CSS",
-       "prefs-custom-js": "kohandatud JS",
-       "prefs-common-css-js": "Kõigi kujunduste ühine CSS/JS:",
+       "prefs-custom-css": "Kohandatud CSS",
+       "prefs-custom-js": "Kohandatud JavaScript",
+       "prefs-common-css-js": "Kõigi kujunduste ühine CSS/JavaScript:",
        "prefs-reset-intro": "Sellel leheküljel saad oma eelistused lähtestada võrgukoha vaike-eelistusteks.\nToimingut ei saa hiljem tühistada.",
        "prefs-emailconfirm-label": "E-posti kinnitus:",
        "youremail": "E-posti aadress:",
        "right-deletedtext": "Vaadata kustutatud teksti ja võrrelda kustutatud redaktsioone",
        "right-browsearchive": "Otsida kustutatud lehekülgi",
        "right-undelete": "Taastada lehekülg",
-       "right-suppressrevision": "Üle vaadata ja taastada administraatorite eest peidetud redaktsioone",
+       "right-suppressrevision": "Vaadata, peita ja taastada kõigi kasutajate eest varjatud kindlaid redaktsioone",
+       "right-viewsuppressed": "Vaadata kõigi kasutajate eest varjatud redaktsioone",
        "right-suppressionlog": "Vaadata eralogisid",
        "right-block": "Keelata lehekülgede muutmist mõnel kasutajal",
        "right-blockemail": "Keelata kasutajal e-kirjade saatmine",
        "right-override-export-depth": "Eksportida lehekülgi, kaasates viidatud leheküljed kuni viienda tasemeni",
        "right-sendemail": "Saata teistele kasutajatele e-kirju",
        "right-passwordreset": "Vaadata parooli lähtestamise e-kirju",
-       "newuserlogpage": "Kasutaja loomise logi",
+       "newuserlogpage": "Konto loomise logi",
        "newuserlogpagetext": "Siin on logitud kasutajate registreerimine.",
        "rightslog": "Kasutajaõiguste logi",
        "rightslogtext": "See on logi kasutajate õiguste muutuste kohta.",
        "action-deletedhistory": "selle lehekülje kustutatud ajalugu vaadata",
        "action-browsearchive": "kustutatud lehekülgi otsida",
        "action-undelete": "lehekülgi taastada",
-       "action-suppressrevision": "seda peidetud redaktsiooni vaadata ja taastada",
+       "action-suppressrevision": "seda peidetud redaktsiooni vaadata ega taastada",
        "action-suppressionlog": "seda eralogi vaadata",
        "action-block": "selle kasutaja redigeerimisõigust blokeerida",
        "action-protect": "selle lehekülje kaitsetasemeid muuta",
        "recentchanges-label-plusminus": "Lehekülje suuruse muutus baitides",
        "recentchanges-legend-heading": "'''Seletus:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vaata ka [[Special:NewPages|uute lehekülgede loendit]])",
-       "rcnotefrom": "Allpool on toodud muudatused alates: <strong>$2</strong> (näidatakse kuni <strong>$1</strong> muudatust)",
+       "rcnotefrom": "Allpool on toodud {{PLURAL:$5|muudatus|muudatused}} alates: <strong>$3, kell $4</strong> (näidatakse kuni <strong>$1</strong> muudatust)",
        "rclistfrom": "Näita muudatusi alates: $3, kell $2",
        "rcshowhideminor": "Pisiparandused ($1)",
        "rcshowhideminor-show": "näita",
        "uploadwarning": "Üleslaadimise hoiatus",
        "uploadwarning-text": "Muuda allpool olevat faili kirjeldust ning proovi uuesti.",
        "savefile": "Salvesta fail",
-       "uploadedimage": "laadis üles faili \"[[$1]]\"",
-       "overwroteimage": "laadis üles faili \"[[$1]]\" uue versiooni",
        "uploaddisabled": "Üleslaadimine hetkel keelatud",
        "copyuploaddisabled": "Internetiaadressilt üleslaadimine on keelatud.",
        "uploaddisabledtext": "Faili üleslaadimine on keelatud.",
        "backend-fail-read": "Faili $1 ei saa lugeda.",
        "backend-fail-create": "Faili $1 ei saa kirjutada.",
        "backend-fail-maxsize": "Faili $1 ei saa kirjutada, sest see on {{PLURAL:$2|ühest baidist|$2 baidist}} suurem.",
+       "backend-fail-readonly": "Tagamälu \"$1\" on praegu kirjutuskaitstud. Põhjus: \"<em>$2</em>\"",
+       "backend-fail-synced": "Faili \"$1\" olek sisemälus on ühtimatu.",
+       "backend-fail-connect": "Ühendus tagamäluga \"$1\" ebaõnnestus.",
+       "backend-fail-internal": "Tagamälus \"$1\" esines tundmatu tõrge.",
        "backend-fail-contenttype": "Faili, mida soovitakse talletada asukohas \"$1\", sisutüüpi saanud kindlaks teha.",
+       "backend-fail-batchsize": "Tagamällu edastati {{PLURAL:$1|ühest|$1}} failioperatsioonist koosnev pakk; ülemmäär on {{PLURAL:$2|üks operatsioon|$2 operatsiooni}}.",
        "backend-fail-usable": "Faili $1 ei saa ebapiisavate õiguste või puuduvate kataloogide/konteinerite tõttu lugeda ega kirjutada.",
+       "filejournal-fail-dbconnect": "Tagamälus \"$1\" ebaõnnestus ühendumine päevikuga.",
+       "filejournal-fail-dbquery": "Tagamälus \"$1\" ebaõnnestus päeviku värskendamine.",
        "lockmanager-notlocked": "Rada \"$1\" ei saa lukust lahti teha, sest see pole lukus.",
        "lockmanager-fail-closelock": "Raja \"$1\" lukustusfaili ei saa sulgeda.",
        "lockmanager-fail-deletelock": "Raja \"$1\" lukustusfaili ei saa kustutada.",
+       "lockmanager-fail-acquirelock": "Ressursi \"$1\" luku hankimine ebaõnnestus.",
        "lockmanager-fail-openlock": "Raja \"$1\" lukustusfaili ei saa avada.",
+       "lockmanager-fail-releaselock": "Ressursi \"$1\" lukku ei õnnestunud vabastada.",
+       "lockmanager-fail-db-bucket": "Komplektis $1 ei õnnestunud saada ühendust piisavalt paljude lukustusandmebaasidega.",
+       "lockmanager-fail-db-release": "Andmebaasis $1 ei õnnestunud lukke vabastada.",
+       "lockmanager-fail-svr-acquire": "Serveris $1 ei õnnestunud lukke hankida.",
+       "lockmanager-fail-svr-release": "Serveris $1 ei õnnestunud lukke vabastada.",
        "zip-file-open-error": "Faili avamisel ZIP-kontrolliks tekkis tõrge.",
        "zip-wrong-format": "Valitud fail ei ole ZIP-fail.",
        "zip-bad": "See ZIP-fail on kas rikutud või muul põhjusel loetamatu.\nSelle turvalisust ei saa kontrollida.",
        "license": "Litsents:",
        "license-header": "Litsents",
        "nolicense": "pole valitud",
+       "licenses-edit": "Redigeeri litsentsivalikut",
        "license-nopreview": "(Eelvaade ei ole saadaval)",
-       "upload_source_url": "(avalikult ligipääsetav URL)",
-       "upload_source_file": "(fail sinu arvutis)",
+       "upload_source_url": "(avalikult juurdepääsetavalt internetiaadressilt valitud fail)",
+       "upload_source_file": "(sinu arvutist valitud fail)",
+       "listfiles-delete": "kustuta",
        "listfiles-summary": "Sellel erileheküljel näidatakse kõiki üles laaditud faile.",
        "listfiles_search_for": "Nimeotsing:",
        "imgfile": "fail",
        "randomincategory": "Juhuslik lehekülg kategoorias",
        "randomincategory-invalidcategory": "\"$1\" pole sobiv kategooria nimi.",
        "randomincategory-nopages": "Kategoorias \"[[:Category:$1|$1]]\" puuduvad leheküljed.",
-       "randomincategory-selectcategory": "Hangi juhuslik lehekülg kategooriast: $1 $2.",
-       "randomincategory-selectcategory-submit": "Mine",
+       "randomincategory-category": "Kategooria:",
+       "randomincategory-legend": "Juhuslik lehekülg kategoorias",
        "randomredirect": "Juhuslik ümbersuunamine",
        "randomredirect-nopages": "Nimeruumis \"$1\" ei ole ümbersuunamislehekülgi.",
        "statistics": "Arvandmestik",
        "wantedpages-badtitle": "Tulemuste seas on vigane pealkiri: $1",
        "wantedfiles": "Kõige oodatumad failid",
        "wantedfiletext-cat": "Järgmised failid puuduvad, aga on lehekülgedel kasutuses. Siin võivad olla loetletud ka välistes hoidlates asuvad failid, hoolimata sellest, et nad tegelikult olemas on. Loendi sellised valeliikmed on <del>läbi kriipsutatud</del>. Lisaks on puuduvaid faile sisaldavad leheküljed loetletud asukohas [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Järgmised failid puuduvad, aga on kasutuses. Peale selle, leheküljel [[:$1]] on loetletud leheküljed, kus kasutatakse puuduvaid faile.",
        "wantedfiletext-nocat": "Järgmised failid puuduvad, aga on lehekülgedel kasutuses. Siin võivad olla loetletud ka välistes hoidlates asuvad failid, hoolimata sellest, et nad tegelikult olemas on. Loendi sellised valeliikmed on <del>läbi kriipsutatud</del>.",
+       "wantedfiletext-nocat-noforeign": "Järgmised failid puuduvad, aga on kasutuses.",
        "wantedtemplates": "Kõige oodatumad mallid",
        "mostlinked": "Kõige viidatumad leheküljed",
        "mostlinkedcategories": "Kõige viidatumad kategooriad",
        "index-category-desc": "Leheküljel on <code><nowiki>__INDEX__</nowiki></code> ja lehekülg on nimeruumis, kus see silt on lubatud ning seetõttu indekseerivad robotid lehekülge seal, kus nad muidu seda ei teeks.",
        "post-expand-template-inclusion-category-desc": "Kõigi mallide hõrendamise järel on lehekülg suurem kui <code>$wgMaxArticleSize</code>, mistõttu jäid mõned mallid hõrendamata.",
        "post-expand-template-argument-category-desc": "Malli argumendi (midagi kolmekordsete looksulgude vahel, näiteks <code>{{{Foo}}})</code> hõrendamise järel on lehekülg suurem kui <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Leheküljel on liiga palju kulukaid parserifunktsioone nagu <code>#ifexist</code>. Vaata [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit dokumentatsiooni].",
-       "broken-file-category-desc": "Kategooria lisatakse, kui leheküljel on katkine pildilink, millega manustatakse fail, mida pole olemas.",
+       "expensive-parserfunction-category-desc": "Lehekülg kasutab liiga palju kulukaid parserifunktsioone nagu <code>#ifexist</code>. Vaata [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit dokumentatsiooni].",
+       "broken-file-category-desc": "Leheküljel on katkine pildilink, millega manustatakse fail, mida pole olemas.",
        "hidden-category-category-desc": "Selle kategooria leheküljel on <code><nowiki>__HIDDENCAT__</nowiki></code>, mis vaikimisi ei lase näidata seda kategooriat lehekülgedel kategoorialinkide kastis.",
        "trackingcategories-nodesc": "Kirjeldus puudub.",
        "trackingcategories-disabled": "Kategooria on keelatud.",
        "mywatchlist": "Jälgimisloend",
        "watchlistfor2": "Kasutaja $1 $2 jaoks",
        "nowatchlist": "Sinu jälgimisloend on tühi.",
-       "watchlistanontext": "Oma jälgimisloendi nägemiseks ja muutmiseks pead $1.",
+       "watchlistanontext": "Palun logi sisse, et oma jälgimisloendit näha või muuta.",
        "watchnologin": "Ei ole sisse logitud",
        "addwatch": "Lisa jälgimisloendisse",
        "addedwatchtext": "Lehekülg \"[[:$1]]\" on lisatud sinu [[Special:Watchlist|jälgimisloendisse]].\nEdasised muudatused sellel leheküljel ja seotud aruteluleheküljel tuuakse ära jälgimisloendis.",
        "watchlist-details": "Jälgimisloendis on {{PLURAL:$1|üks lehekülg|$1 lehekülge}}. Arutelulehekülgi pole eraldi välja toodud.",
        "wlheader-enotif": "E-posti teel teavitamine on lubatud.",
        "wlheader-showupdated": "Leheküljed, mida on muudetud peale sinu viimast külastust, on '''rasvases kirjas'''.",
-       "wlnote2": "Allpool on viimase {{PLURAL:$1|tunni|<strong>$1</strong> tunni}} jooksul tehtud muudatused seisuga $2, $3.",
+       "wlnote": "Allpool on {{PLURAL:$1|viimane muudatus|viimased <strong>$1</strong> muudatust}} viimase {{PLURAL:$2|tunni|<strong>$2</strong> tunni}} jooksul seisuga $3, kell $4.",
        "wlshowlast": "Näita viimast $1 tundi $2 päeva. $3",
        "watchlist-options": "Jälgimisloendi seaded",
        "watching": "Jälgimine...",
        "exbeforeblank": "sisu enne lehekülje tühjendamist: '$1'",
        "delete-confirm": "Lehekülje \"$1\" kustutamine",
        "delete-legend": "Kustutamine",
-       "historywarning": "'''Hoiatus:''' Kustutataval leheküljel on ligikaudu {{PLURAL:$1|ühe redaktsiooniga|$1 redaktsiooniga}} ajalugu:",
+       "historywarning": "<strong>Hoiatus:</strong> Kustutataval leheküljel on {{PLURAL:$1|ühe redaktsiooniga|$1 redaktsiooniga}} ajalugu:",
        "confirmdeletetext": "Sa oled andmebaasist kustutamas lehekülge koos kogu tema ajalooga.\nPalun kinnita, et tahad seda tõepoolest teha, et sa mõistad tagajärgi ja et sinu tegevus on kooskõlas siinse [[{{MediaWiki:Policy-url}}|sisekorraga]].",
        "actioncomplete": "Toiming sooritatud",
        "actionfailed": "Toiming ebaõnnestus",
        "delete-edit-reasonlist": "Redigeeri kustutamise põhjuseid",
        "delete-toobig": "See lehekülg on pika redigeerimisajalooga – üle {{PLURAL:$1|ühe muudatuse|$1 muudatuse}}.\nSelle kustutamine on keelatud, et ära hoida ekslikku {{GRAMMAR:genitive|{{SITENAME}}}} töö häirimist.",
        "delete-warning-toobig": "See lehekülg on pika redigeerimislooga – üle {{PLURAL:$1|ühe muudatuse|$1 muudatuse}}.\nEttevaatust, selle kustutamine võib esile kutsuda häireid {{GRAMMAR:genitive|{{SITENAME}}}} andmebaasi töös.",
+       "deleteprotected": "Seda lehekülge ei saa kustutada, sest see on kaitstud.",
        "deleting-backlinks-warning": "'''Hoiatus:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Teised leheküljed]] viitavad leheküljele, mida oled kustutamas, või see lehekülg on kasutuses mallina.",
        "rollback": "Tühista muudatused",
        "rollback_short": "Tühista",
        "autoblockid": "Automaatblokeering #$1",
        "block": "Kasutaja blokeerimine",
        "unblock": "Kasutaja blokeeringu eemaldamine",
-       "blockip": "Kasutaja blokeerimine",
+       "blockip": "Blokeeri {{GENDER:$1|kasutaja}}",
        "blockip-legend": "Kasutaja blokeerimine",
        "blockiptext": "See vorm on kindla IP-aadressi või kasutajanime kirjutamisõiguste blokeerimiseks.\nSeda tohib teha ainult vandalismi vältimiseks ja kooskõlas [[{{MediaWiki:Policy-url}}|{{GRAMMAR:genitive|{{SITENAME}}}} sisekorraga]].\nTäida ka põhjuse väli, näiteks viidates lehekülgedele, mis rikuti.",
        "ipaddressorusername": "IP-aadress või kasutajanimi:",
        "lockfilenotwritable": "Andmebaasi lukufail ei ole kirjutatav.\nAndmebaasi lukustamiseks ja avamiseks peavad veebiserveril olema sellele kirjutusõigused.",
        "databasenotlocked": "Andmebaas ei ole lukustatud.",
        "lockedbyandtime": "(lukustas $1; $2, kell $3)",
-       "move-page": "Teisalda $1",
+       "move-page": "Lehekülje \"$1\" teisaldamine",
        "move-page-legend": "Lehekülje teisaldamine",
        "movepagetext": "Allolevat vormi kasutades saad lehekülje ümber nimetada. Lehekülje ajalugu tõstetakse uue pealkirja alla automaatselt.\nPraeguse pealkirjaga leheküljest saab ümbersuunamislehekülg uuele leheküljele.\nSaad senisele pealkirjale viitavad ümbersuunamised automaatselt parandada.\nKui sa seda ei tee, kontrolli, et teisaldamise tõttu ei jää maha [[Special:DoubleRedirects|kahekordseid]] ega [[Special:BrokenRedirects|katkiseid ümbersuunamisi]].\nSinu kohus on hoolitseda selle eest, et kõik jääks toimima, nagu ette nähtud.\n\nPane tähele, et lehekülge '''ei teisaldata''' juhul, kui uue pealkirjaga lehekülg on juba olemas. Erandiks on juhud, kui viimane on redigeerimisajaloota ümbersuunamislehekülg.\nSee tähendab, et kogemata ei saa üle kirjutada juba olemasolevat lehekülge, kuid saab ebaõnnestunud ümbernimetamise tagasi pöörata.\n\n'''Hoiatus!'''\nTegu võib olla väga loetava lehekülje jaoks tõsise ja ootamatu muudatusega;\nenne jätkamist teadvusta palun tagajärgi.",
        "movepagetext-noredirectfixer": "Allolevat vormi kasutades saad lehekülje ümber nimetada. Lehekülje ajalugu tõstetakse uue pealkirja alla automaatselt.\nPraeguse pealkirjaga leheküljest saab ümbersuunamislehekülg uuele leheküljele.\nKontrolli, et teisaldamise tõttu ei jää maha [[Special:DoubleRedirects|kahekordseid]] ega [[Special:BrokenRedirects|katkiseid ümbersuunamisi]].\nSinu kohus on hoolitseda selle eest, et kõik jääks toimima, nagu ette nähtud.\n\nPane tähele, et lehekülge '''ei teisaldata''' juhul, kui uue pealkirjaga lehekülg on juba olemas. Erandiks on juhud, kui olemasolev lehekülg on tühi või redigeerimisajaloota ümbersuunamislehekülg.\nSee tähendab, et kogemata ei saa üle kirjutada juba olemasolevat lehekülge, kuid saab ebaõnnestunud ümbernimetamise tagasi pöörata.\n\n'''Hoiatus!'''\nTegu võib olla väga loetava lehekülje jaoks tõsise ja ootamatu muudatusega;\nenne jätkamist teadvusta palun tagajärgi.",
        "import": "Lehekülgede import",
        "importinterwiki": "Vikidevaheline import",
        "import-interwiki-text": "Vali importimiseks viki ja lehekülje pealkiri.\nRedigeerimisajad ja kaastööliste nimed säilitatakse.\nKõik vikidevahelised toimingud on [[Special:Log/import|impordilogis]].",
-       "import-interwiki-source": "Lähteviki/lehekülg:",
+       "import-interwiki-sourcewiki": "Lähteviki:",
+       "import-interwiki-sourcepage": "Alliklehekülg:",
        "import-interwiki-history": "Kopeeri selle lehekülje kogu ajalugu",
        "import-interwiki-templates": "Liida kõik mallid",
        "import-interwiki-submit": "Impordi",
        "import-invalid-interwiki": "Määratud vikist ei saa importida.",
        "import-error-edit": "Lehekülge \"$1\" ei imporditud, sest sul pole õigust seda muuta.",
        "import-error-create": "Lehekülge \"$1\" ei imporditud, sest sul pole õigust seda luua.",
-       "import-error-interwiki": "Lehekülge \"$1\" ei impordita, sest selle pealkirja hoitakse välislinkide (interviki) jaoks.",
-       "import-error-special": "Lehekülge \"$1\" ei impordita, sest see kuulub erinimeruumi, kus pole leheküljed lubatud.",
-       "import-error-invalid": "Lehekülge \"$1\" ei impordita, sest selle pealkiri on vigane.",
+       "import-error-interwiki": "Lehekülge \"$1\" ei imporditud, sest selle pealkirja hoitakse välislinkide (interviki) jaoks.",
+       "import-error-special": "Lehekülge \"$1\" ei imporditud, sest see kuulub erinimeruumi, kus pole leheküljed lubatud.",
+       "import-error-invalid": "Lehekülge \"$1\" ei imporditud, sest pealkiri, mille alla see siin toodaks, on vigane.",
+       "import-error-unserialize": "Lehekülje \"$1\" jadastatud redaktsiooni $2 ei õnnestunud tagasi muundada. Teate järgi kasutas redaktsioon vormingus $4 jadastatud sisumudelit $3.",
        "import-error-bad-location": "Redaktsiooni $2 sisumudeliga $3 ei saa talletada siin vikis leheküljel \"$1\", mis seda mudelit ei toeta.",
        "import-options-wrong": "{{PLURAL:$2|Vale valik|Valed valikud}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "Etteantud juurlehekülje pealkiri on vigane.",
        "importlogpage": "Impordilogi",
        "importlogpagetext": "Importimislogi kuvab leheküljed, mille redigeerimisajalugu pärineb teistest vikidest.",
        "import-logentry-upload": "importis faili üleslaadimisega lehekülje [[$1]]",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|redaktsioon|redaktsiooni}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|redaktsioon|redaktsiooni}} imporditud",
        "import-logentry-interwiki": "importis teisest vikist lehekülje $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|redaktsioon|redaktsiooni}} asukohast $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|redaktsioon|redaktsiooni}} imporditud asukohast $2",
        "javascripttest": "JavaScripti katsetamine",
        "javascripttest-title": "$1-katse käitus",
        "javascripttest-pagetext-noframework": "Seda lehekülge hoitakse JavaScripti katsete jaoks.",
        "tooltip-preferences-save": "Salvesta eelistused",
        "tooltip-summary": "Kirjuta lühike kokkuvõte",
        "common.css": "/* Siin olevat CSS-i kasutavad kõik kujundused. */",
+       "group-autoconfirmed.css": "/* Siin asuv kaskaadilaadistik puudutab ainult automaatselt kinnitatud kasutajaid. */",
+       "group-user.css": "/* Siin asuv kaskaadilaadistik puudutab ainult registreeritud kasutajaid. */",
+       "group-bot.css": "/* Siin asuv kaskaadilaadistik puudutab ainult roboteid. */",
+       "group-sysop.css": "/* Siin asuv kaskaadilaadistik puudutab ainult administraatoreid. */",
+       "group-bureaucrat.css": "/* Siin asuv kaskaadilaadistik puudutab ainult bürokraate. */",
        "common.js": "/* Siinne JavaScript laaditakse igale kasutajatele igal laaditud leheküljel. */",
+       "group-autoconfirmed.js": "/* Siin asuv JavaScript laaditakse ainult automaatselt kinnitatud kasutajate jaoks. */",
+       "group-user.js": "/* Siin asuv JavaScript laaditakse ainult registreeritud kasutajate jaoks. */",
+       "group-bot.js": "/* Siin asuv JavaScript laaditakse ainult robotite jaoks. */",
+       "group-sysop.js": "/* Siin asuv JavaScript laaditakse ainult administraatorite jaoks. */",
+       "group-bureaucrat.js": "/* Siin asuv JavaScript laaditakse ainult bürokraatide jaoks. */",
        "anonymous": "{{GRAMMAR:genitive|{{SITENAME}}}} {{PLURAL:$1|anonüümne kasutaja|anonüümsed kasutajad}}",
        "siteuser": "{{GRAMMAR:genitive|{{SITENAME}}}} kasutaja $1",
        "anonuser": "{{GRAMMAR:genitive|{{SITENAME}}}} anonüümne kasutaja $1",
        "autosumm-replace": "Lehekülg asendatud tekstiga '$1'",
        "autoredircomment": "Ümbersuunamine lehele [[$1]]",
        "autosumm-new": "Uus lehekülg: '$1'",
+       "autosumm-newblank": "Alustatud tühja leheküljega",
        "lag-warn-normal": "Viimase {{PLURAL:$1|ühe sekundi|$1 sekundi}} jooksul tehtud muudatused ei pruugi selles loendis näha olla.",
        "lag-warn-high": "Andmebaasiserveri töö viivituste tõttu ei pruugi viimase {{PLURAL:$1|ühe sekundi|$1 sekundi}} jooksul tehtud muudatused selles loendis näha olla.",
        "watchlistedit-normal-title": "Jälgimisloendi redigeerimine",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|arutelu]])",
        "unknown_extension_tag": "Tundmatu lisa silt \"$1\".",
        "duplicate-defaultsort": "'''Hoiatus:''' Järjestamisvõti \"$2\" tühistab eespool oleva järjestamisvõtme \"$1\".",
+       "duplicate-displaytitle": "<strong>Hoiatus:</strong> Kuvatava pealkirjaga \"$2\" kirjutatakse üle varasem kuvatav pealkiri \"$1\".",
        "version": "Versioon",
        "version-extensions": "Paigaldatud lisad",
        "version-skins": "Paigaldatud kujundused",
        "logentry-rights-rights": "$1 {{GENDER:$2|muutis}} kasutaja $3 rühmaliikmesust; enne oli $4, nüüd on $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|muutis}} kasutaja $3 rühmaliikmesust",
        "logentry-rights-autopromote": "$1 {{GENDER:$2|viidi}} automaatselt üle teise rühma; enne oli $4, nüüd on $5",
+       "logentry-upload-upload": "$1 {{GENDER:$2|laadis üles}} faili $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|laadis üles}} uue versiooni failist $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|laadis üles}} faili $3",
        "rightsnone": "(puudub)",
        "feedback-bugornote": "Kui arvad, et oskad tehnilist probleemi üksikasjalikult kirjeldada, [$1 teata veast].\nKui ei, kasuta allolevat lihtsat vormi. Sinu kommentaar lisatakse koos kasutajanime ja teabega kasutatava võrgulehitsejaga kohta leheküljele \"[$3 $2]\".",
        "feedback-subject": "Teema:",
        "action-pagelang": "muuta lehekülje keelt",
        "log-name-pagelang": "Keele muutmise logi",
        "log-description-pagelang": "Siia on logitud lehekülgede keele muutmised.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|muutis}} lehekülje \"$3\" keelt: $4 → $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|muutis}} lehekülje \"$3\" keelt: $4 → $5.",
+       "default-skin-not-found": "Oih! Sinu viki vaikekujundus (<code>$wgDefaultSkin</code>) <code>$1</code> pole saadaval.\n\nPaistab, et sinu install sisaldab järgmisi kujundusi. Vaata [https://www.mediawiki.org/wiki/Manual:Skin_configuration kujunduste häälestusjuhendist], kuidas neid lubada ja kuidas valida vaikekujundus.\n\n$2\n\n; Kui oled MediaWiki just paigaldanud:\n: Paigaldasid tarkvara ilmselt Giti kaudu või otse lähtekoodist või mõnel muul viisil. See on ootuspärane. Proovi [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org-i kujunduste kataloogist] mõni kujundus paigaldada. Selleks saad:\n:* laadida alla [https://www.mediawiki.org/wiki/Download lintarhiivi paigaldaja], mis sisaldab mitut kujundust ja tarkvaralisa. Saad sealt kleepimiseks kopeerida kausta <code>skins/</code>;\n:* kopeerida Giti kaudu ühe hoidla (<code>mediawiki/skins/*</code>) oma MediaWiki installi kausta <code>skins/</code>.\n: Selle tegemine ei tohiks häirida Giti hoidlat, kui oled MediaWiki arendaja.\n\n; Kui oled MediaWikit just täiendanud:\n: MediaWiki 1.24-s ja uuemates versioonides pole paigaldatud kujundused enam automaatselt lubatud (vaata juhendist [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery kujunduste automaatse leidmise] kohta). Saad kleepida järgmised read leheküljele <code>LocalSettings.php</code>, et lubada kõik praegu paigaldatud kujundused:\n\n<pre>$3</pre>\n\n; Kui oled lehekülge <code>LocalSettings.php</code> just muutnud:\n: Kontrolli üle, ega kujunduste nimedes pole trükivigu.",
+       "default-skin-not-found-no-skins": "Oih! Sinu viki vaikekujundus (<code>$wgDefaultSkin</code>) <code>$1</code> pole saadaval.\n\nÜhtegi kujundust pole paigaldatud.\n\n; Kui oled MediaWiki just paigaldanud või täiendasid seda:\n: Paigaldasid tarkvara ilmselt Giti kaudu või otse lähtekoodist või mõnel muul viisil. See on ootuspärane. MediaWiki 1.24 ja uuemad versioonid ei sisalda peahoidlas ühtegi kujundust. Proovi [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org-i kujunduste kataloogist] mõni kujundus paigaldada. Selleks saad:\n:* laadida alla [https://www.mediawiki.org/wiki/Download lintarhiivi paigaldaja], mis sisaldab mitut kujundust ja tarkvaralisa. Saad sealt kleepimiseks kopeerida kausta <code>skins/</code>;\n:* kopeerida Giti kaudu ühe hoidla (<code>mediawiki/skins/*</code>) oma MediaWiki installi kausta <code>skins/</code>.\n: Selle tegemine ei tohiks häirida Giti hoidlat, kui oled MediaWiki arendaja. Vaata [https://www.mediawiki.org/wiki/Manual:Skin_configuration kujunduste häälestusjuhendist], kuidas kujundusi lubada ja kuidas valida vaikekujundus.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (lubatud)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''keelatud''')"
 }
index 4f10d30..a235031 100644 (file)
@@ -19,7 +19,8 @@
                        "לערי ריינהארט",
                        "පසිඳු කාවින්ද",
                        "아라",
-                       "Joxemai"
+                       "Joxemai",
+                       "Arkaitz Barnetik"
                ]
        },
        "tog-underline": "Loturak azpimarratu:",
        "talkpagelinktext": "Eztabaida",
        "specialpage": "Aparteko orrialdea",
        "personaltools": "Tresna pertsonalak",
-       "postcomment": "Atal berria",
        "articlepage": "Artikulua ikusi",
        "talk": "Eztabaida",
        "views": "Ikustaldiak",
        "hidetoc": "ezkutatu",
        "collapsible-collapse": "Itxi",
        "collapsible-expand": "Zabaldu",
+       "confirmable-yes": "Bai",
+       "confirmable-no": "Ez",
        "thisisdeleted": "$1 ikusi edo leheneratu?",
        "viewdeleted": "$1 ikusi?",
        "restorelink": "{{PLURAL:$1|ezabatutako aldaketa bat|ezabatutako $1 aldaketa}}",
        "externaldberror": "Kanpoko datu-base autentifikazio errorea gertatu da edo ez duzu zure kanpo kontua eguneratzeko baimenik.",
        "login": "Saioa hasi",
        "nav-login-createaccount": "Saioa hasi / kontua sortu",
-       "loginprompt": "Cookieak gaituta izatea beharrezkoa da {{SITENAME}}(e)n saioa hasteko.",
        "userlogin": "Saioa hasi / kontua sortu",
        "userloginnocreate": "Saioa hasi",
        "logout": "Saioa itxi",
        "gotaccountlink": "Saioa hasi",
        "userlogin-resetlink": "Saioa hasteko datuak ahaztu dituzu?",
        "userlogin-resetpassword-link": "Zure pasahitza ahaztu duzu?",
-       "userlogin-loggedin": "Dagoeneko izena emana zaude {{GENDER:$1|$1}}.\nBeheko formularioa erabil ezazu beste erabiltzaile baten izenean sartzeko.",
-       "userlogin-createanother": "Beste kontu bat sortu",
        "createacct-emailrequired": "E-posta helbidea",
        "createacct-emailoptional": "E-posta helbidea (hautazkoa)",
        "createacct-email-ph": "Sartu zure e-posta helbidea",
        "searchprofile-advanced-tooltip": "Lankideen izen zehatzetan bilatu",
        "search-result-size": "$1 ({{PLURAL:$2|hitz bat|$2 hitz}})",
        "search-result-category-size": "{{PLURAL:$1|kide 1|$1 kide}} ({{PLURAL:$2|azpikategoria 1|$2 azpikategoria}}, {{PLURAL:$3|fitxategi 1|$3 fitxategi}})",
-       "search-result-score": "Garrantzia: %$1",
        "search-redirect": "(«$1» orritik birbideratua)",
        "search-section": "($1 atala)",
        "search-suggest": "$1 esan nahi zenuen",
        "uploadwarning": "Igotzeko oharra",
        "uploadwarning-text": "Aldatu beheko fitxategiaren deskribapena, mesedez, eta saiatu berriz.",
        "savefile": "Fitxategia gorde",
-       "uploadedimage": "\"[[$1]]\" igo da",
-       "overwroteimage": "\"[[$1]]\"ren bertsio berri bat igo",
        "uploaddisabled": "Igoerak ezgaituta daude",
        "copyuploaddisabled": "URL bidezko igoera desaktibatuta.",
        "uploaddisabledtext": "Fitxategiak igotzea ezgaituta dago.",
        "license-nopreview": "(Aurreikuspenik ez)",
        "upload_source_url": " (baliozko URL publikoa)",
        "upload_source_file": " (zure ordenagailuko fitxategi bat)",
+       "listfiles-delete": "ezabatu",
        "listfiles-summary": "Orri berezi honek igotako fitxategi guztiak erakusten ditu.\nBerez, azken igotako fitxategiak zerrendaren goiko aldean azaltzen dira.",
        "listfiles_search_for": "Irudiaren izenagatik bilatu:",
        "imgfile": "fitxategia",
        "randomincategory": "Kategoriako ausazko orrialdea",
        "randomincategory-invalidcategory": "\"$1\" ez da kategoria izen baliagarri bat.",
        "randomincategory-nopages": "Ez dago orrialderik [[:Category:$1|$1]] kategorian.",
-       "randomincategory-selectcategory": "Lortu kategoria honetako ausazko orrialdea: $1 $2.",
-       "randomincategory-selectcategory-submit": "Joan",
        "randomredirect": "Ausazko birbideratzea",
        "randomredirect-nopages": "Ez dago birzuzenketarik \"$1\" izen-tartean.",
        "statistics": "Estatistikak",
        "watchlist-details": "{{PLURAL:$1|Orrialde $1|$1 orrialde}} jarraitzen, eztabaida orrialdeak kontuan hartu gabe.",
        "wlheader-enotif": "Posta bidezko ohartarazpena gaituta dago.",
        "wlheader-showupdated": "Bisitatu zenituen azken alditik aldaketak izan dituzten orrialdeak '''beltzez''' nabarmenduta daude.",
+       "wlnote": "Jarraian {{PLURAL:$2|ikus daiteke azken orduko|ikus daitezke azken '''$2''' orduetako}} azken {{PLURAL:$1|aldaketa|'''$1''' aldaketak}}, $3, $4 gisa.",
        "wlshowlast": "Erakutsi azken $1 orduak $2 egunak $3",
        "watchlist-options": "Jarraitze-zerrendaren aukerak",
        "watching": "Zerrendan gehitzen...",
        "import": "Orrialdeak inportatu",
        "importinterwiki": "Wikien arteko inportazioa",
        "import-interwiki-text": "Aukeratu inportatzeko wiki eta orrialde izenburu bat. Berrikuspenen datak eta egileak gorde egingo dira. Inportazio ekintza guzti hauek [[Special:Log/import|inportazio erregistroan]] gordetzen dira.",
-       "import-interwiki-source": "Jatorrizko wiki/orrialdea:",
        "import-interwiki-history": "Orrialde honen historiako bertsio guztiak kopiatu",
        "import-interwiki-templates": "Txantiloi guztiak sartu",
        "import-interwiki-submit": "Inportatu",
        "confirm-purge-bottom": "Orrialdea purgatzean katxea ezabatzen du eta orrialdearen bertsiorik eguneratuena erakustera behartzen du.",
        "confirm-watch-button": "Ados",
        "confirm-unwatch-button": "Ados",
+       "quotation-marks": "«$1»",
        "imgmultipageprev": "&larr; aurreko orrialdea",
        "imgmultipagenext": "hurrengo orrialdea &rarr;",
        "imgmultigo": "Joan!",
        "limitreport-expansiondepth": "Gehienezko espantsio sakonera",
        "limitreport-expensivefunctioncount": "Parser funtzio kontaketa garestia",
        "expandtemplates": "Txantiloi ordezkatzailea",
-       "expand_templates_intro": "Aparteko orrialde honek modu errekurtsiboan txantiloiak ordezkatu egiten ditu.\nFuntzioak ere ordezkatu egiten ditu, hala nola\n<code><nowiki>{{</nowiki>#language:…}}</code>, eta\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code> bezalako aldagaiak ere.\nKortxete bikoitzarekin hobeto egiten da lan.",
+       "expand_templates_intro": "Orri berezi honek testua hartu eta txantiloi guztiak modu errekurtsiboan zabaltzen ditu.\nOnartutako funtzio sintaktikoak ere ordezkatzen ditu, hala nola\n<code><nowiki>{{</nowiki>#language:…}}</code>; eta aldagaiak ere, hala nola\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nIzan ere, kortxete bikoitzen arteko ia edozer zabaltzen du.",
        "expand_templates_title": "Izenburua ({{FULLPAGENAME}} ordezkatzeko, eta abar):",
        "expand_templates_input": "Sarrerako testua:",
        "expand_templates_output": "Emaitza",
index 224adac..b4eb8d5 100644 (file)
        "talkpagelinktext": "Caraba",
        "specialpage": "Página Especial",
        "personaltools": "Herramientas presonalis",
-       "postcomment": "Nueva seción",
        "articlepage": "Vel artículu",
        "talk": "Caraba",
        "views": "Guipás",
        "externaldberror": "Marru d'autentificación esterna e la basi e datus, u bien nu t'alcuentras autorizau p'atualizal la tu cuenta esterna.",
        "login": "Entral",
        "nav-login-createaccount": "Entral/Crial cuenta",
-       "loginprompt": "Ebis atival las cookies pa entral en {{SITENAME}}.",
        "userlogin": "Entral/Crial cuenta",
        "userloginnocreate": "Entral",
        "logout": "Salil",
        "searchprofile-images-tooltip": "Landeal archivus",
        "searchprofile-everything-tooltip": "Landeal tol conteniu (encruyendu carabas)",
        "search-result-size": "$1 ({{PLURAL:$2|1 letra|$2 letras}})",
-       "search-result-score": "Emportáncia: $1%",
        "search-redirect": "(rederihil $1)",
        "search-section": "(seción $1)",
        "search-suggest": "Quieis izil: $1",
        "file-exists-duplicate": "Esti archivu es un dupricau {{PLURAL:$1|el siguienti archivu|los siguientis archivus}}:",
        "uploadwarning": "Avisu d´empuntu",
        "savefile": "Emburacal archivu",
-       "uploadedimage": "emputau \"[[$1]]\"",
-       "overwroteimage": "empuntá una nueva velsión de \"[[$1]]\"",
        "uploaddisabled": "Empuntus desativaus",
        "uploaddisabledtext": "El empuntu d'archivus está desativau.",
        "uploadscripted": "Esti archivu contieni script u cóigu HTML que puei sel mal entelpretau pol un escrucaol.",
        "watchlist-details": "{{PLURAL:$1|$1 artículu|$1 artículus}} vehilaus (sin contal las carabas).",
        "wlheader-enotif": "Se premitin notificacionis pol email.",
        "wlheader-showupdated": "Las páhinas que s'án emburacau dendi la úrtima vezi que las visoreasti son muestrás en '''negrina'''",
+       "wlnote": "Embahu {{PLURAL:$1|es el úrtimu chambu|son los úrtimus '''$1''' chambus}} enas úrtimas {{PLURAL:$2|oras|'''$2''' oras}}.",
        "wlshowlast": "Muestral úrtimus $1 oras $2 dias $3",
        "watchlist-options": "Ocionis de la mi lista e seguimientu",
        "watching": "Vehilandu...",
index 77c1b16..989e86a 100644 (file)
                        "درفش کاویانی",
                        "محک",
                        "아라",
-                       "Mostafadaneshvar"
+                       "Mostafadaneshvar",
+                       "Pouyana",
+                       "Oldstoneage",
+                       "Omid.koli",
+                       "Alirezaaa",
+                       "Mogoeilor"
                ]
        },
-       "tog-underline": "خط کشیدن زیر پیوندها:",
+       "tog-underline": "خطکشیدن زیر پیوندها:",
        "tog-hideminor": "تغییرات جزئی از فهرست تغییرات اخیر پنهان شوند",
        "tog-hidepatrolled": "ویرایش‌های گشت‌خورده از فهرست تغییرات اخیر پنهان شوند",
        "tog-newpageshidepatrolled": "صفحه‌های گشت‌خورده از فهرست صفحه‌های تازه پنهان شوند",
-       "tog-extendwatchlist": "گسترش فهرست پیگیری‌ها برای نمایش همهٔ تغییرات، نه فقط آخرین‌ها",
-       "tog-usenewrc": "گروه‌بندی تغییرات بر پایهٔ صفحه‌های تغییرات اخیر و فهرست پیگیری‌ها (نیازمند جاوااسکریپت)",
+       "tog-extendwatchlist": "گسترش فهرست پیگیری‌ها برای نمایش همهٔ تغییرات، نه فقط آخرین‌ها",
+       "tog-usenewrc": "گروه‌بندی تغییرات بر پایهٔ صفحات تغییرات اخیر و فهرست پیگیری‌ها",
        "tog-numberheadings": "شماره‌گذاری خودکار عنوان‌ها",
-       "tog-showtoolbar": "نوار ابزار جعبهٔ ویرایش نمایش یابد",
-       "tog-editondblclick": "ویرایش صفحه‌ها با دوکلیک (نیازمند جاوااسکریپت)",
-       "tog-editsectiononrightclick": "امکان ویرایش بخش‌ها با کلیک راست روی عنوان‌های بخش (نیازمند جاوااسکریپت)",
-       "tog-watchcreations": "صفحه‌هایی که می‌سازم و پرونده‌هایی که بارگذاری می‌کنم به فهرست پیگیری‌هایم افزوده شود",
-       "tog-watchdefault": "صفحه‌ها و پرونده‌هایی که ویرایش می‌کنم به فهرست پیگیری‌هایم افزوده شود",
+       "tog-showtoolbar": "نوار ابزار ویرایش نمایش یابد",
+       "tog-editondblclick": "ویرایش صفحات با دو کلیک",
+       "tog-editsectiononrightclick": "فعال‌کردن ویرایش بخش‌ها با کلیک راست روی عنوان بخش‌ها",
+       "tog-watchcreations": "صفحه‌هایی که می‌سازم و پرونده‌هایی که بارگذاری می‌کنم به فهرست پیگیری‌هایم افزوده شود",
+       "tog-watchdefault": "صفحه‌ها و پرونده‌هایی که ویرایش می‌کنم به فهرست پیگیری‌هایم افزوده شود",
        "tog-watchmoves": "صفحه‌ها و پرونده‌هایی که منتقل می‌کنم به فهرست پی‌گیری‌هایم افزوده شود",
-       "tog-watchdeletion": "صفحه‌ها و پرونده‌هایی که حذف می‌کنم به فهرست پی‌گیری‌هایم افزوده شود",
+       "tog-watchdeletion": "صفحات و پرونده‌هایی که حذف می‌کنم به فهرست پی‌گیری‌هایم افزوده شود",
+       "tog-watchrollback": "افزودن صفحاتی که واگردانی کردم برای فهرست پیگیری‌هایم",
        "tog-minordefault": "همهٔ ویرایش‌ها به طور پیش‌فرض به عنوان «جزئی» علامت بخورد",
        "tog-previewontop": "پیش‌نمایش قبل از جعبهٔ ویرایش نمایش یابد",
        "tog-previewonfirst": "پیش‌نمایش هنگام اولین ویرایش نمایش یابد",
        "category_header": "صفحه‌های ردهٔ «$1»",
        "subcategories": "زیررده‌ها",
        "category-media-header": "پرونده‌های ردهٔ «$1»",
-       "category-empty": "''این رده در حال حاضر حاوی هیچ صفحه یا پرونده‌ای نیست.''",
+       "category-empty": "<em>این رده در حال حاضر حاوی هیچ صفحه یا پرونده‌ای نیست.</em>",
        "hidden-categories": "{{PLURAL:$1|ردهٔ پنهان|رده‌های پنهان}}",
        "hidden-category-category": "رده‌های پنهان",
        "category-subcat-count": "{{PLURAL:$2|این رده تنها حاوی زیرردهٔ زیر است.|{{PLURAL:$1|این زیررده|این $1 زیررده}} در این رده قرار {{PLURAL:$1|دارد|دارند}}؛ این رده در کل حاوی $2 زیررده است.}}",
        "category-file-count": "{{PLURAL:$2|این رده تنها حاوی پروندهٔ زیر است.|{{PLURAL:$1|این پرونده|این $1 پرونده}} در این رده قرار {{PLURAL:$1|دارد|دارند}}؛ این رده در کل حاوی $2 پرونده است.}}",
        "category-file-count-limited": "{{PLURAL:$1|پروندهٔ|$1 پروندهٔ}} زیر در ردهٔ فعلی قرار دارند.",
        "listingcontinuesabbrev": "(ادامه)",
-       "index-category": "صفحه‌های نمایه‌شده",
-       "noindex-category": "صفحه‌های نمایه‌نشده",
-       "broken-file-category": "صفحه‌های دارای پیوند خراب به پرونده",
+       "index-category": "صفحات فهرست‌شده",
+       "noindex-category": "صفحات فهرست‌نشده",
+       "broken-file-category": "صفحات دارای پیوند خراب به پرونده",
        "about": "درباره",
        "article": "صفحهٔ محتوایی",
-       "newwindow": "(در Ù¾Ù\86جرÙ\87Ù\94 Ø¬Ø¯Û\8cد باز می‌شود)",
+       "newwindow": "(در Ù¾Ù\86جرÙ\87Ù\94 ØªØ§Ø²Ù\87 باز می‌شود)",
        "cancel": "لغو",
        "moredotdotdot": "بیشتر...",
        "morenotlisted": "این فهرست کامل نیست.",
        "mypage": "صفحه",
        "mytalk": "بحث",
-       "anontalk": "بحث Ø¨Ø±Ø§Û\8c Ø§Û\8cÙ\86 آی‌پی",
-       "navigation": "گشتن",
+       "anontalk": "بحث Ø¯Ø±Ø¨Ø§Ø±Ù\87 Ø§Û\8cÙ\86 Ù\86شاÙ\86Û\8c آی‌پی",
+       "navigation": "ناوبری",
        "and": "&#32;و",
        "qbfind": "یافتن",
        "qbbrowse": "مرور",
        "qbedit": "ویرایش",
        "qbpageoptions": "این صفحه",
-       "qbmyoptions": "صفحه‌های من",
+       "qbmyoptions": "صفحات من",
        "faq": "پرسش‌های متداول",
        "faqpage": "Project:پرسش‌های متداول",
        "actions": "عملکردها",
        "create-this-page": "ایجاد این صفحه",
        "delete": "حذف",
        "deletethispage": "حذف این صفحه",
-       "undeletethispage": "احÛ\8cای این صفحه",
+       "undeletethispage": "بازگرداÙ\86ی این صفحه",
        "undelete_short": "احیای {{PLURAL:$1|یک ویرایش|$1 ویرایش}}",
        "viewdeleted_short": "نمایش {{PLURAL:$1|یک ویرایش حذف‌شده|$1 ویرایش حذف‌شده}}",
        "protect": "محافظت",
        "protect_change": "تغییر",
        "protectthispage": "محافظت از این صفحه",
-       "unprotect": "تغییر سطح محافظت",
-       "unprotectthispage": "تغییر سطح محافظت این صفحه",
-       "newpage": "صÙ\81Ø­Ù\87Ù\94 Ø¬Ø¯Û\8cد",
+       "unprotect": "تغییر محافظت",
+       "unprotectthispage": "تغییر محافظت این صفحه",
+       "newpage": "صÙ\81Ø­Ù\87Ù\94 ØªØ§Ø²Ù\87",
        "talkpage": "بحث دربارهٔ این صفحه",
        "talkpagelinktext": "بحث",
        "specialpage": "صفحهٔ ویژه",
        "personaltools": "ابزارهای شخصی",
-       "postcomment": "بخش جدید",
        "articlepage": "نمایش مقاله",
        "talk": "بحث",
        "views": "بازدیدها",
        "otherlanguages": "به زبان‌های دیگر",
        "redirectedfrom": "(تغییرمسیر از $1)",
        "redirectpagesub": "صفحهٔ تغییرمسیر",
+       "redirectto": "تغییر مسیر به:",
        "lastmodifiedat": "این صفحه آخرین‌بار در $1 ساعت $2 تغییر یافته‌است.",
        "viewcount": "از این صفحه {{PLURAL:$1|یک‌بار|$1بار}} بازدید شده‌است.",
        "protectedpage": "صفحهٔ محافظت‌شده",
        "youhavenewmessages": "$1 دارید ($2).",
        "youhavenewmessagesfromusers": "شما از {{PLURAL:$3|یک کاربر دیگر|$3  کاربر}} $1 دارید ($2).",
        "youhavenewmessagesmanyusers": "شما از تعدادی کاربر $1 دارید ($2).",
-       "newmessageslinkplural": "{{PLURAL:$1|Ù¾Û\8cاÙ\85 Ø¬Ø¯Û\8cد|999=Ù¾Û\8cاÙ\85â\80\8cÙ\87اÛ\8c Ø¬Ø¯Û\8cد}}",
+       "newmessageslinkplural": "{{PLURAL:$1|Ù¾Û\8cاÙ\85 Ø¬Ø¯Û\8cد|999=Ù¾Û\8cاÙ\85â\80\8cÙ\87اÛ\8c ØªØ§Ø²Ù\87}}",
        "newmessagesdifflinkplural": "{{formatnum:$1}} {{PLURAL:$1|تغییر|999=تغییر}} اخیر",
        "youhavenewmessagesmulti": "پیام‌های جدیدی در $1 دارید.",
        "editsection": "ویرایش",
        "hidetoc": "نهفتن",
        "collapsible-collapse": "نهفتن",
        "collapsible-expand": "گسترش",
+       "confirmable-confirm": "{{GENDER:$1|شما}} مطمئن هستید؟",
+       "confirmable-yes": "بله",
+       "confirmable-no": "خیر",
        "thisisdeleted": "نمایش یا احیای $1؟",
        "viewdeleted": "نمایش $1؟",
        "restorelink": "{{PLURAL:$1|یک|$1}} ویرایش حذف‌شده",
        "laggedslavemode": "'''هشدار:''' صفحه ممکن است به‌روزرسانی‌های اخیر را شامل نشود.",
        "readonly": "پایگاه داده قفل شد",
        "enterlockreason": "دلیلی برای قفل کردن ذکر کنید، که حاوی تقریبی از زمانی باشد که قفل برداشته خواهد شد",
-       "readonlytext": "پایگاه داده در حال حاضر در برابر تغییرات و ایجاد صفحه‌ها قفل شده‌است؛ این وضعیت احتمالاً به خاطر بهینه‌سازی و رسیدگی‌های معمول است که پس از آن وضع به حالت عادی بازخواهد گشت.\n\nمدیری که آن را قفل کرده این توضیح را ارائه کرده‌است: $1",
+       "readonlytext": "پایگاه داده در حال حاضر در برابر تغییرات و ایجاد صفحات قفل شده‌است؛ این وضعیت احتمالاً به خاطر بهینه‌سازی و رسیدگی‌های معمول است که پس از آن وضع به حالت عادی بازخواهد گشت.\n\nمدیری که آن را قفل کرده این توضیح را ارائه کرده‌است: $1",
        "missing-article": "پایگاه داده متن صفحهٔ با نام «$1» $2 را که باید پیدا می‌کرد نیافت.\n\nاین مشکل معمولاً به علت دنبال‌کردن یک پیوند تفاوت تاریخ‌گذشته یا تاریخچهٔ صفحه‌ای که حذف شده‌است، رخ می‌دهد.\n\nدر غیر این صورت ممکن است اشکالی در نرم‌افزار پیدا کرده باشد.\nلطفاً این مشکل را با ذکر نشانی اینترنتی به یکی از [[Special:ListUsers/sysop|مدیران]] گزارش دهید.",
        "missingarticle-rev": "(شمارهٔ نسخه: $1)",
        "missingarticle-diff": "(تفاوت: $1، $2)",
        "externaldberror": "خطایی در ارتباط با پایگاه داده رخ داده‌است یا اینکه شما اجازهٔ به‌روزرسانی حساب خارجی خود را ندارید.",
        "login": "ورود به سامانه",
        "nav-login-createaccount": "ورود به سامانه / ایجاد حساب کاربری",
-       "loginprompt": "برای ورود به {{SITENAME}} باید کوکی‌ها را فعال کنید.",
        "userlogin": "ورود به سامانه / ایجاد حساب کاربری",
        "userloginnocreate": "ورود به سامانه",
        "logout": "خروج از سامانه",
        "userlogin-noaccount": "حساب کاربری ندارید؟",
        "userlogin-joinproject": "در {{SITENAME}} نام‌نویسی کنید!",
        "nologin": "حساب کاربری ندارید؟ $1.",
-       "nologinlink": "Û\8cÚ© Ø­Ø³Ø§Ø¨ Ú©Ø§Ø±Ø¨Ø±Û\8c Ø¬Ø¯Û\8cد بسازید",
+       "nologinlink": "Û\8cÚ© Ø­Ø³Ø§Ø¨ Ú©Ø§Ø±Ø¨Ø±Û\8c ØªØ§Ø²Ù\87 بسازید",
        "createaccount": "ایجاد حساب کاربری",
        "gotaccount": "حساب کاربری دارید؟ $1.",
        "gotaccountlink": "به سامانه وارد شوید",
        "userlogin-resetlink": "جزئیات ورود را فراموش کرده‌اید؟",
        "userlogin-resetpassword-link": "گذرواژه‌تان را فراموش کردید؟",
        "userlogin-helplink2": "کمک با ورود",
-       "userlogin-loggedin": "شما در حال حاضر به‌عنوان {{GENDER:$1|$1}} وارد شده‌اید.\nاز فرم پایین برای ورود به‌عنوان یک کاربر دیگر استفاده کنید.",
-       "userlogin-createanother": "ایجاد یک حساب کاربری دیگر",
        "createacct-emailrequired": "نشانی رایانامه",
        "createacct-emailoptional": "نشانی رایانامه (اختیاری)",
        "createacct-email-ph": "نشانی رایانامه را وارد کنید",
        "noname": "شما نام کاربری معتبری مشخص نکرده‌اید.",
        "loginsuccesstitle": "ورود موفقیت‌آمیز به سامانه",
        "loginsuccess": "'''شما اکنون با نام «$1» به {{SITENAME}} وارد شده‌اید.'''",
-       "nosuchuser": "کاربرÛ\8c Ø¨Ø§ Ù\86اÙ\85 Â«$1» Ù\88جÙ\88د Ù\86دارد.\nÙ\86اÙ\85 Ú©Ø§Ø±Ø¨Ø±Û\8c Ø¨Ù\87 Ø¨Ø²Ø±Ú¯Û\8c Ù\88 Ú©Ù\88Ú\86Ú©Û\8c Ø­Ø±Ù\88Ù\81 Ø­Ø³Ø§Ø³ Ø§Ø³Øª.\nاÙ\85Ù\84اÛ\8c Ù\86اÙ\85 Ø±Ø§ Ø¨Ø±Ø±Ø³Û\8c Ú©Ù\86Û\8cدØ\8c Û\8cا [[Special:UserLogin/signup|Û\8cÚ© Ø­Ø³Ø§Ø¨ Ú©Ø§Ø±Ø¨Ø±Û\8c Ø¬Ø¯Û\8cد بسازید]].",
+       "nosuchuser": "کاربرÛ\8c Ø¨Ø§ Ù\86اÙ\85 Â«$1» Ù\88جÙ\88د Ù\86دارد.\nÙ\86اÙ\85 Ú©Ø§Ø±Ø¨Ø±Û\8c Ø¨Ù\87 Ø¨Ø²Ø±Ú¯Û\8c Ù\88 Ú©Ù\88Ú\86Ú©Û\8c Ø­Ø±Ù\88Ù\81 Ø­Ø³Ø§Ø³ Ø§Ø³Øª.\nاÙ\85Ù\84اÛ\8c Ù\86اÙ\85 Ø±Ø§ Ø¨Ø±Ø±Ø³Û\8c Ú©Ù\86Û\8cدØ\8c Û\8cا [[Special:UserLogin/signup|Û\8cÚ© Ø­Ø³Ø§Ø¨ Ú©Ø§Ø±Ø¨Ø±Û\8c ØªØ§Ø²Ù\87 بسازید]].",
        "nosuchusershort": "هیچ کاربری با نام ''$1'' وجود ندارد.\nاملایتان را وارسی کنید.",
        "nouserspecified": "باید یک نام کاربری مشخص کنید.",
        "login-userblocked": "این کاربر بسته شده‌است. ورود به سامانه مجاز نیست.",
        "createaccount-text": "یک نفر برای رایانامه شما یک حساب کاربری در {{SITENAME}} با نام «$2» ایجاد کرده‌است ($4)، که گذرواژهٔ آن چنین است: $3\nشما باید به سامانه وارد شوید تا گذرواژهٔ خود را تغییر بدهید.\n\nاگر این حساب اشتباهی ساخته شده است، این پیغام را نادیده بگیرید.",
        "login-throttled": "شما به تازگی چندین‌بار برای ثبت ورود تلاش کرده‌اید.\nلطفاً پیش از آنکه دوباره تلاش کنید $1 صبر کنید.",
        "login-abort-generic": "ورود شما ناموفق بود - خاتمهٔ ناگهانی داده شد",
+       "login-migrated-generic": "حساب کاربری شما منتقل شده‌است، و نام کاربری‌تان دیگر در این ویکی وجود ندارد.",
        "loginlanguagelabel": "زبان: $1",
        "suspicious-userlogout": "درخواست شما برای خروج از سامانه رد شد زیرا به نظر می‌رسد که این درخواست توسط یک مرورگر معیوب یا پروکسی میانگیر ارسال شده باشد.",
        "createacct-another-realname-tip": "نام واقعی اختیاری است.\nاگر آن را وارد کنید هنگام ارجاع به آثارتان و انتساب آن‌ها به شما از نام واقعی‌تان استفاده خواهد شد.",
        "resetpass_text": "<!-- اینجا متن اضافه کنید -->",
        "resetpass_header": "تغییر گذرواژهٔ حساب کاربری",
        "oldpassword": "گذرواژهٔ پیشین:",
-       "newpassword": "گذرÙ\88اÚ\98Ù\87Ù\94 Ø¬Ø¯Û\8cد:",
-       "retypenew": "گذرÙ\88اÚ\98Ù\87Ù\94 Ø¬Ø¯Û\8cد را دوباره وارد کنید",
+       "newpassword": "گذرÙ\88اÚ\98Ù\87Ù\94 ØªØ§Ø²Ù\87:",
+       "retypenew": "گذرÙ\88اÚ\98Ù\87Ù\94 ØªØ§Ø²Ù\87 را دوباره وارد کنید",
        "resetpass_submit": "تنظیم گذرواژه و ورود به سامانه",
        "changepassword-success": "گذرواژهٔ شما با موفقیت تغییر داده شد!",
        "changepassword-throttled": "شما به تازگی چندین‌بار برای ثبت ورود تلاش کرده‌اید.\nلطفاً پیش از آنکه دوباره تلاش کنید $1 صبر کنید.",
        "resetpass-no-info": "برای دسترسی مستقیم به این صفحه شما باید به سامانه وارد شده باشید.",
        "resetpass-submit-loggedin": "تغییر گذرواژه",
        "resetpass-submit-cancel": "لغو",
-       "resetpass-wrong-oldpass": "گذرÙ\88اÚ\98Ù\87Ù\94 Ù\85Ù\88Ù\82ت Û\8cا Ø§Ø®Û\8cر Ù\86اÙ\85عتبر.\nÙ\85Ù\85Ú©Ù\86 Ø§Ø³Øª Ú©Ù\87 Ø´Ù\85ا Ù\87Ù\85Û\8cÙ\86Ú© Ú¯Ø°Ø±Ù\88اÚ\98Ù\87â\80\8cتاÙ\86 Ø±Ø§ Ø¨Ø§ Ù\85Ù\88Ù\81Ù\82Û\8cت ØªØºÛ\8cÛ\8cر Ø¯Ø§Ø¯Ù\87 Ø¨Ø§Ø´Û\8cد Û\8cا Ø¯Ø±Ø®Ù\88است Û\8cÚ© Ú¯Ø°Ø±Ù\88اÚ\98Ù\87Ù\94 Ù\85Ù\88Ù\82ت Ø¬Ø¯Û\8cد کرده باشید.",
+       "resetpass-wrong-oldpass": "گذرÙ\88اÚ\98Ù\87Ù\94 Ù\85Ù\88Ù\82ت Û\8cا Ø§Ø®Û\8cر Ù\86اÙ\85عتبر.\nÙ\85Ù\85Ú©Ù\86 Ø§Ø³Øª Ú©Ù\87 Ø´Ù\85ا Ù\87Ù\85Û\8cÙ\86Ú© Ú¯Ø°Ø±Ù\88اÚ\98Ù\87â\80\8cتاÙ\86 Ø±Ø§ Ø¨Ø§ Ù\85Ù\88Ù\81Ù\82Û\8cت ØªØºÛ\8cÛ\8cر Ø¯Ø§Ø¯Ù\87 Ø¨Ø§Ø´Û\8cد Û\8cا Ø¯Ø±Ø®Ù\88است Û\8cÚ© Ú¯Ø°Ø±Ù\88اÚ\98Ù\87Ù\94 Ù\85Ù\88Ù\82ت ØªØ§Ø²Ù\87 کرده باشید.",
        "resetpass-recycled": "لطفاً رمز عبور خود را به چیز دیگری غیر از رمز عبور فعلی تنظیم کنید.",
        "resetpass-temp-emailed": "شما با یک کد رایانامه شدهٔ موقت وارد شده‌اید.\nبرای پایان ورود، شما باید رمز عبور جدیدی اینجا وارد کنید:",
        "resetpass-temp-password": "گذرواژهٔ موقت:",
        "resetpass-abort-generic": "تغییر گذرواژه به دست یکی از افزونه‌ها لغو شده است.",
        "resetpass-expired": "رمز عبور شما منقضی شده‌است. لطفاً برای ورود رمز عبور جدیدی را تنظیم کنید.",
        "resetpass-expired-soft": "رمز عبور شما منقضی شده‌است، و نیاز به تنظیم مجدد دارد. لطفاً اکنون رمز عبور جدیدی را انتخاب کنید، یا برای تنظیم مجدد آن بعدآً، دکمه \"{{int:resetpass-submit-cancel}}\" را کلیک کنید.",
-       "resetpass-validity-soft": "گذرÙ\88اÙ\87Ù\94 Ø´Ù\85ا ØµØ­Û\8cØ­ Ù\86Û\8cست: $1\n\nÙ\84Ø·Ù\81اÙ\8b Û\8cÚ© Ú¯Ø°Ø±Ù\88اÚ\98Ù\87Ù\94 Ø¬Ø¯Û\8cد الآن انتخاب کنید یا بر «{{int:resetpass-submit-cancel}}» کلیک کنید که دوباره آن را بعداً انتخاب کنید.",
+       "resetpass-validity-soft": "گذرÙ\88اÙ\87Ù\94 Ø´Ù\85ا ØµØ­Û\8cØ­ Ù\86Û\8cست: $1\n\nÙ\84Ø·Ù\81اÙ\8b Û\8cÚ© Ú¯Ø°Ø±Ù\88اÚ\98Ù\87Ù\94 ØªØ§Ø²Ù\87 الآن انتخاب کنید یا بر «{{int:resetpass-submit-cancel}}» کلیک کنید که دوباره آن را بعداً انتخاب کنید.",
        "passwordreset": "بازنشانی گذرواژه",
        "passwordreset-text-one": "برای بازنشانی گذرواژه‌تان این فرم را کامل کنید.",
        "passwordreset-text-many": "{{PLURAL:$1|برای دریافت یک گذرواژهٔ موقت از راه رایانامه، یکی از زمینه‌ها را پر کنید.}}",
        "changeemail-text": "این فرم را تکمیل کنید تا آدرس رایانامه‌تان تغییر یابد. برای این که این تغییر را تأیید کنید لازم است گذرواژهٔ خود را وارد کنید.",
        "changeemail-no-info": "برای دسترسی مستقیم به این صفحه شما باید به سامانه وارد شده باشید.",
        "changeemail-oldemail": "نشانی رایانامهٔ کنونی:",
-       "changeemail-newemail": "Ù\86شاÙ\86Û\8c Ø±Ø§Û\8cاÙ\86اÙ\85Ù\87Ù\94 Ø¬Ø¯Û\8cد:",
+       "changeemail-newemail": "Ù\86شاÙ\86Û\8c Ø±Ø§Û\8cاÙ\86اÙ\85Ù\87Ù\94 ØªØ§Ø²Ù\87:",
        "changeemail-none": "(هیچ)",
        "changeemail-password": " {{SITENAME}} رمز عبور شما:",
        "changeemail-submit": "تغییر رایانامه",
        "preview": "پیش‌نمایش",
        "showpreview": "پیش‌نمایش",
        "showdiff": "نمایش تغییرات",
-       "anoneditwarning": "'''هشدار:''' شما به سامانه وارد نشده‌اید.\nنشانی آی‌پی شما در تاریخچهٔ ویرایش این صفحه ثبت خواهد شد.",
+       "blankarticle": "<strong>هشدار:</strong> شما در حال ایجاد صفحه خالی هستید.\nاگر \"{{int:savearticle}}\" را دوباره کلیک کنید، صفحه بدون محتوا ایجاد می‌شود.",
+       "anoneditwarning": "<strong>هشدار:</strong> شما وارد نشده‌اید. نشانی آی‌پی شما برای عموم قابل مشاهده خواهد بود اگر هر تغییری ایجاد کنید. اگر <strong>[$1 وارد شوید]</strong> یا <strong>[$2 یک حساب کاربری بسازید]</strong>، ویرایش‌هایتان به نام کاربری‌تان نسبت داده خواهد شد، همراه با مزایای دیگر.",
        "anonpreviewwarning": "''شما به سامانه وارد نشده‌اید. ذخیره کردن باعث می‌شود که نشانی آی‌پی شما در تاریخچهٔ این صفحه ثبت گردد.''",
        "missingsummary": "'''یادآوری:''' شما خلاصهٔ ویرایش ننوشته‌اید.\nاگر دوباره دکمهٔ «{{int:savearticle}}» را فشار دهید ویرایش شما بدون آن ذخیره خواهد شد.",
        "missingcommenttext": "لطفاً توضیحی در زیر بیفزایید.",
        "autoblockedtext": "دسترسی نشانی آی‌پی شما قطع شده‌است، زیرا این نشانی آی‌پی توسط کاربر دیگری استفاده شده که دسترسی او توسط $1 قطع شده‌است.\nدلیل ارائه‌شده چنین است:\n\n:''$2''\n\n* شروع قطع دسترسی: $8\n* پایان قطع دسترسی: $6\n* کاربری هدف قطع دسترسی: $7\n\nشما می‌توانید با $1 یا  [[{{MediaWiki:Grouppage-sysop}}|مدیری]] دیگر تماس بگیرید و در این باره صحبت کنید.\nتوجه کنید که شما نمی‌توانید از ویژگی «فرستادن رایانامه به این کاربر» استفاده کنید مگر آنکه نشانی رایانامه معتبری در [[Special:Preferences|ترجیحات کاربری]] خودتان ثبت کرده باشید و نیز باید امکان استفاده از این ویژگی برای شما قطع نشده باشد.\nنشانی آی‌پی فعلی شما $3 و شمارهٔ قطع دسترسی شما $5 است.\nلطفاً تمامی جزئیات فوق را در کلیهٔ درخواست‌هایی که در این باره مطرح می‌کنید ذکر کنید.",
        "blockednoreason": "دلیلی مشخص نشده‌است",
        "whitelistedittext": "برای ویرایش مقاله‌ها باید $1.",
-       "confirmedittext": "شما باید، پیش از ویرایش صفحه‌ها، نشانی رایانامهٔ خود را مشخص و تأیید کنید. لطفاً از طریق [[Special:Preferences|ترجیحات کاربر]] این کار را صورت دهید.",
+       "confirmedittext": "شما باید، پیش از ویرایش صفحات، نشانی رایانامهٔ خود را مشخص و تأیید کنید. لطفاً از طریق [[Special:Preferences|ترجیحات کاربر]] این کار را صورت دهید.",
        "nosuchsectiontitle": "چنین بخشی پیدا نشد",
        "nosuchsectiontext": "شما تلاش کرده‌اید یک بخش در صفحه را ویرایش کنید که وجود ندارد.\nممکن است در مدتی که شما صفحه را مشاهده می‌کردید این بخش جا به جا یا حذف شده باشد.",
        "loginreqtitle": "ورود به سامانه لازم است",
        "loginreqpagetext": "برای دیدن صفحه‌های دیگر باید $1.",
        "accmailtitle": "گذرواژه فرستاده شد.",
        "accmailtext": "یک گذرواژهٔ تصادفی برای [[User talk:$1|$1]] به $2 فرستاده شد. می‌توان آن را از صفحهٔ ''[[Special:ChangePassword|تغییر گذرواژه]]'' که هنگام ثبت ورود نمایش می‌یابد تغییر داد.",
-       "newarticle": "(جدÛ\8cد)",
+       "newarticle": "(تازÙ\87)",
        "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}}}} سیاهه‌های مرتبط را جستجو کنید]،\nیا [{{fullurl:{{FULLPAGENAME}}|action=edit}} این صفحه را ویرایش کنید]</span>.",
-       "noarticletext-nopermission": "این صفحه هم‌اکنون متنی ندارد.\nشما می‌توانید در دیگر صفحه‌ها [[Special:Search/{{PAGENAME}}|این عنوان را جستجو کنید]]،\nیا <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} سیاهه‌های مرتبط را بگردید]</span> ولی شما اجازه ایجاد این صفحه را ندارید.",
+       "noarticletext-nopermission": "این صفحه هم‌اکنون متنی ندارد.\nشما می‌توانید در دیگر صفحات [[Special:Search/{{PAGENAME}}|این عنوان را جستجو کنید]]،\nیا <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لطفاً مطمئن شوید که می‌خواهید این صفحه را ایجاد یا ویرایش کنید.",
        "userpage-userdoesnotexist-view": "حساب کاربری «$1» ثبت نشده‌است.",
        "editing": "در حال ویرایش $1",
        "creating": "ایجاد $1",
        "editingsection": "در حال ویرایش $1 (بخش)",
-       "editingcomment": "در Ø­Ø§Ù\84 Ù\88Û\8cراÛ\8cØ´ $1 (بخش Ø¬Ø¯Û\8cد)",
+       "editingcomment": "در Ø­Ø§Ù\84 Ù\88Û\8cراÛ\8cØ´ $1 (بخش ØªØ§Ø²Ù\87)",
        "editconflict": "تعارض ویرایشی: $1",
        "explainconflict": "از وقتی ویرایش این صفحه را آغاز کرده‌اید شخص دیگری آن را تغییر داده‌است.\nناحیهٔ متنی بالایی شامل متن صفحه به شکل کنونی آن است.\nتغییرات شما در ناحیهٔ متنی پایینی نشان داده شده‌است.\nشما باید تغییراتتان را با متن کنونی ترکیب کنید.\nبا فشردن دکمهٔ «{{int:savearticle}}» '''فقط''' متن ناحیهٔ متنی بالایی ذخیره خواهد شد.",
        "yourtext": "متن شما",
        "storedversion": "نسخهٔ ذخیره شده",
-       "nonunicodebrowser": "'''هشدار: مرورگر شما با استانداردهای یونیکد سازگار نیست.'''\nراه حلی به کار گرفته شده تا شما بتوانید صفحه‌ها را با امنیت ویرایش کنید: کاراکترهای غیر ASCII به صورت کدهایی در مبنای شانزده به شما نشان داده می‌شوند.",
+       "nonunicodebrowser": "'''هشدار: مرورگر شما با استانداردهای یونیکد سازگار نیست.'''\nراه حلی به کار گرفته شده تا شما بتوانید صفحات را با امنیت ویرایش کنید: کاراکترهای غیر ASCII به صورت کدهایی در مبنای شانزده به شما نشان داده می‌شوند.",
        "editingold": "'''هشدار: شما در حال ویرایش نسخه‌ای قدیمی از این صفحه هستید.'''\nاگر ذخیره‌اش کنید، هر تغییری که پس از این نسخه انجام شده‌است از بین خواهد رفت.",
        "yourdiff": "تفاوت‌ها",
        "copyrightwarning": "لطفاً توجه داشته باشید که فرض می‌شود کلیهٔ مشارکت‌های شما با {{SITENAME}} تحت «$2» منتشر می‌شوند (برای جزئیات بیشتر به $1 مراجعه کنید).\nاگر نمی‌خواهید نوشته‌هایتان بی‌رحمانه ویرایش شده و به دلخواه توزیع شود، اینجا نفرستیدشان.<br />\nهمچنین شما دارید به ما قول می‌دهید که خودتان این را نوشته‌اید، یا آن را از یک منبع آزاد با مالکیت عمومی یا مشابه آن برداشته‌اید.\n'''کارهای دارای حق تکثیر (copyright) را بی‌اجازه نفرستید!'''",
        "template-semiprotected": "(نیمه‌حفاظت‌شده)",
        "hiddencategories": "این صفحه در {{PLURAL:$1|یک ردهٔ پنهان|$1 ردهٔ پنهان}} قرار دارد:",
        "edittools": "<!-- متن این قسمت زیر صفحه‌های ویرایش و بارگذاری نشان داده می‌شود -->",
-       "nocreatetext": "{{SITENAME}} Ù\82ابÙ\84Û\8cت Ø§Û\8cجاد ØµÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8c Ø¬Ø¯Û\8cد را محدود کرده‌است.\nمی‌توانید بازگردید و صفحه‌ای موجود را ویرایش کنید یا اینکه  [[Special:UserLogin|به سامانه وارد شوید یا حساب کاربری ایجاد کنید]].",
-       "nocreate-loggedin": "Ø´Ù\85ا Ø§Ø¬Ø§Ø²Ù\87Ù\94 Ø§Û\8cجاد ØµÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8c Ø¬Ø¯Û\8cد را ندارید.",
+       "nocreatetext": "{{SITENAME}} Ù\82ابÙ\84Û\8cت Ø§Û\8cجاد ØµÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8c ØªØ§Ø²Ù\87 را محدود کرده‌است.\nمی‌توانید بازگردید و صفحه‌ای موجود را ویرایش کنید یا اینکه  [[Special:UserLogin|به سامانه وارد شوید یا حساب کاربری ایجاد کنید]].",
+       "nocreate-loggedin": "Ø´Ù\85ا Ø§Ø¬Ø§Ø²Ù\87Ù\94 Ø§Û\8cجاد ØµÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8c ØªØ§Ø²Ù\87 را ندارید.",
        "sectioneditnotsupported-title": "ویرایش بخش‌ها پشتیبانی نمی‌شود",
        "sectioneditnotsupported-text": "این صفحه از ویرایش بخش‌ها پشتیبانی نمی‌کند.",
        "permissionserrors": "خطای سطح دسترسی",
        "postedit-confirmation-created": "صفحه ایجاد شده است.",
        "postedit-confirmation-restored": "صفحه بازیابی شده است.",
        "postedit-confirmation-saved": "ویرایش شما ذخیره شد.",
-       "edit-already-exists": "اÙ\85کاÙ\86 Ø³Ø§Ø®ØªÙ\86 ØµÙ\81Ø­Ù\87Ù\94 Ø¬Ø¯Û\8cد وجود ندارد.\nاین صفحه از قبل وجود داشته‌است.",
+       "edit-already-exists": "اÙ\85کاÙ\86 Ø³Ø§Ø®ØªÙ\86 ØµÙ\81Ø­Ù\87Ù\94 ØªØ§Ø²Ù\87 وجود ندارد.\nاین صفحه از قبل وجود داشته‌است.",
        "defaultmessagetext": "متن پیش‌فرض پیغام",
        "content-failed-to-parse": "عدم موفقیت در تجزیه محتوای $2 برای مدل $1: $3",
        "invalid-content-data": "داده محتوای نامعتبر",
        "parser-template-recursion-depth-warning": "محدودیت عمق بازگشت الگو رد شد ($1)",
        "language-converter-depth-warning": "محدودیت عمق مبدل زبانی رد شد ($1)",
        "node-count-exceeded-category": "صفحه‌هایی که از حداکثر تعداد گره تجاوز کرده‌اند",
-       "node-count-exceeded-category-desc": "ردÙ\87 Ø¨Ø±Ø§Û\8c ØµÙ\81حاتÛ\8c Ú©Ù\87 Ø¯Ø± Ø¢Ù\86Ù\87ا Ø´Ù\85ارÙ\86دÙ\87 فراتر رفته است.",
-       "node-count-exceeded-warning": "صفحه از حداکثر تعداد گره تجاوز کرد",
+       "node-count-exceeded-category-desc": "اÛ\8cÙ\86 ØµÙ\81Ø­Ù\87 Ø§Ø² ØªØ¹Ø¯Ø§Ø¯ Ø­Ø¯Ø§Ú©Ø«Ø± Ø§Ø´Ú©Ø§Ù\84 فراتر رفته است.",
+       "node-count-exceeded-warning": "صفحه از حداکثر تعداد گره فراتر رفته‌است",
        "expansion-depth-exceeded-category": "صفحه‌هایی که از حداکثر عمق بسط دادن تجاوز کرده‌اند",
-       "expansion-depth-exceeded-category-desc": "رده برای صفحاتی که در آنها عمق گسترش فراتر رفته است.",
+       "expansion-depth-exceeded-category-desc": "ردÙ\87 Ø¨Ø±Ø§Û\8c ØµÙ\81حاتÛ\8c Ú©Ù\87 Ø¯Ø± Ø¢Ù\86Ù\87ا Ø§Ø² Ø¹Ù\85Ù\82 Ú¯Ø³ØªØ±Ø´ Ù\81راتر Ø±Ù\81تÙ\87 Ø§Ø³Øª.",
        "expansion-depth-exceeded-warning": "صفحه حداکثر عمق بسط دادن تجاوز کرد",
        "parser-unstrip-loop-warning": "حلقه در دستور unstrip پیدا شد",
        "parser-unstrip-recursion-limit": "از حداکثر ارجاع در دستور unstrip تجاوز شد ($1)",
        "undo-success": "این ویرایش را می‌توان خنثی کرد.\nلطفاً تفاوت زیر را بررسی کنید تا تأیید کنید که این چیزی است که می‌خواهید انجام دهید، سپس تغییرات زیر را ذخیره کنید تا خنثی‌سازی ویرایش را به پایان ببرید.",
        "undo-failure": "به علت تعارض با ویرایش‌های میانی، این ویرایش را نمی‌توان خنثی کرد.",
        "undo-norev": "این ویرایش را نمی‌توان خنثی کرد چون وجود ندارد یا حذف شده‌است.",
-       "undo-nochange": "بÙ\87 Ù\86ظر Ù\85Û\8câ\80\8cرسد Ù\88Û\8cراÛ\8cØ´ Ø¯Ø± Ø­Ø§Ù\84 Ø­Ø§Ø¶Ø± Ø¨Ø§Ø·Ù\84 Ø¨Ù\88ده است.",
+       "undo-nochange": "بÙ\87 Ù\86ظر Ù\85Û\8câ\80\8cرسد Ù\88Û\8cراÛ\8cØ´ Ø§Ø² Ù¾Û\8cØ´ Ù\88اگرداÙ\86Û\8c Ø´ده است.",
        "undo-summary": "خنثی‌سازی ویرایش $1 توسط [[Special:Contributions/$2|$2]] ([[User talk:$2|بحث]])",
        "undo-summary-username-hidden": "خنثی‌سازی نسخهٔ $1 به دست یک کاربر پنهان‌شده",
        "cantcreateaccounttitle": "نمی‌توان حساب باز کرد",
        "history-feed-title": "تاریخچهٔ ویرایش‌ها",
        "history-feed-description": "تاریخچهٔ ویرایش‌های این صفحه در ویکی",
        "history-feed-item-nocomment": "$1 در $2",
-       "history-feed-empty": "صفحهٔ درخواست شده وجود ندارد.\nممکن است که از ویکی حذف یا اینکه نامش تغییر داده شده باشد.\nصفحه‌های جدید را برای موارد مرتبط در این ویکی [[Special:Search|جستجو کنید]].",
+       "history-feed-empty": "صفحهٔ درخواست شده وجود ندارد.\nممکن است که از ویکی حذف یا اینکه نامش تغییر داده شده باشد.\nصفحات تازه را برای موارد مرتبط در این ویکی [[Special:Search|جستجو کنید]].",
        "rev-deleted-comment": "(خلاصه ویرایش حذف شد)",
        "rev-deleted-user": "(نام کاربری حذف شد)",
        "rev-deleted-event": "(مورد از سیاهه پاک شده)",
        "rev-deleted-user-contribs": "[نام کاربری یا نشانی آی‌پی حذف شده - ویرایش مخفی شده در مشارکت‌ها]",
        "rev-deleted-text-permission": "این ویرایش از این صفحه '''حذف شده‌است'''.\nممکن است اطلاعات مرتبط با آن در [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سیاههٔ حذف] موجود باشد.",
+       "rev-suppressed-text-permission": "این ویرایش از این صفحه '''حذف شده‌است'''.\nشما می‌توانید آن را ببینید؛ ممکن است اطلاعات مرتبط با آن در [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} سیاههٔ حذف] موجود باشد.",
        "rev-deleted-text-unhide": "این ویرایش از این صفحه '''حذف شده‌است'''.\nممکن است اطلاعات مرتبط با آن در [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سیاههٔ حذف] موجود باشد.\nشما کماکان می‌توانید در صورت تمایل [$1 این نسخه را ببینید].",
        "rev-suppressed-text-unhide": "این ویرایش از این صفحه '''فرونشانده شده‌است'''.\nممکن است اطلاعات مرتبط با آن در [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} سیاههٔ فرونشانی] موجود باشد.\nشما کماکان می‌توانید در صورت تمایل [$1 این نسخه را ببینید].",
        "rev-deleted-text-view": "این ویرایش از این صفحه '''حذف شده‌است'''.\nشما می‌توانید آن را ببینید؛ ممکن است اطلاعات مرتبط با آن در [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سیاههٔ حذف] موجود باشد.",
        "revdelete-text-text": "نسخه‌های حذف‌شده همچنان در تارییخچه نمایان خواند بود ولی قسمت‌هایی از محتویات غبرقابل دسترس برای عموم خواهد بود.",
        "revdelete-text-file": "نسخه‌های حذف‌شده همچنان در تاریخچهٔ پرونده نمایان خواهد بود ولی قسمت‌هایی از محتویات آن‌ها برای عموم غیرقابل دسترس خواهد بود.",
        "logdelete-text": "نسخه‌های حذف‌شده همچنان در سیاهه‌های نمایان خواهد بود ولی قسمت‌هایی از محتویات آن‌ها غیرقابل دسترس برای عموم خواهد بود.",
-       "revdelete-text-others": "سایر مدیران {{SITENAME}} هنوز می‌توانند این محتوای پنهان را ببینند و از همین طریق موارد حذف شده را احیا کنند، مگر آن که محدودیت‌های دیگری اعمال گردد.",
+       "revdelete-text-others": "سایر مدیران هنوز می‌توانند این محتوای پنهان را ببینند و از همین طریق موارد حذف شده را احیا کنند، مگر آن که محدودیت‌های دیگری اعمال گردد.",
        "revdelete-confirm": "لطفاً تأیید کنید که می‌خواهید این کار را انجام دهید، عواقب آن را درک می‌کنید و این کار را طبق [[{{MediaWiki:Policy-url}}|سیاست‌ها]] انجام می‌دهید.",
        "revdelete-suppress-text": "فرونشانی باید '''تنها''' برای موارد زیر استفاده شود:\n* اطلاعات به طور بالقوه افتراآمیز\n* اطلاعات نامناسب شخصی\n*: ''نشانی منزل، شماره تلفن، کد ملی و غیره.''",
        "revdelete-legend": "تنظیم محدودیت‌های پیدایی",
        "revdelete-radio-set": "پنهان",
        "revdelete-radio-unset": "نمایان",
        "revdelete-suppress": "از دسترسی مدیران به داده نیز مانند سایر کاربران جلوگیری به عمل آید.",
-       "revdelete-unsuppress": "خاتÙ\85Ù\87Ù\94 Ù\85حدÙ\88دÛ\8cتâ\80\8cÙ\87ا Ø¯Ø± Ù\85Ù\88رد Ù\86سخÙ\87â\80\8cÙ\87اÛ\8c Ø§Ù\86تخاب شده",
+       "revdelete-unsuppress": "حذÙ\81 Ù\85حدÙ\88دÛ\8cتâ\80\8cÙ\87ا Ø¯Ø± Ø¨Ø§Ø²Ø¨Û\8cÙ\86Û\8câ\80\8cÙ\87اÛ\8c ØªØ±Ù\85Û\8cÙ\85â\80\8cشده",
        "revdelete-log": "دلیل:",
        "revdelete-submit": "اعمال بر {{PLURAL:$1|نسخهٔ|نسخه‌های}} انتخاب شده",
        "revdelete-success": "'''پیدایی نسخه با موفقیت به روز شد.'''",
        "revdelete-offender": "نویسنده نسخه:",
        "suppressionlog": "سیاههٔ فرونشانی",
        "suppressionlogtext": "در زیر فهرستی از آخرین حذف‌ها و قطع دسترسی‌هایی که حاوی محتوایی هستند که از مدیران پنهان شده‌اند را می‌بینید.\nبرای مشاهدهٔ فهرستی از قطع دسترسی‌های فعال [[Special:BlockList|فهرست بسته‌شده‌ها]] را ببینید.",
-       "mergehistory": "ادغام تاریخچه صفحه‌ها",
+       "mergehistory": "ادغام تاریخچه صفحات",
        "mergehistory-header": "این صفحه به شما این امکان را می‌دهد که نسخه‌های تاریخچهٔ یک مقاله را با یک مقاله دیگر ادغام کنید.\nاطمینان حاصل کنید که این تغییر به توالی زمانی ویرایش‌ها لطمه نخواهد زد.",
        "mergehistory-box": "ادغام نسخه‌های دو صفحه:",
        "mergehistory-from": "صفحهٔ مبدأ:",
        "mergehistory-go": "نمایش تاریخچه قابل ادغام",
        "mergehistory-submit": "ادغام نسخه‌ها",
        "mergehistory-empty": "هیچ‌یک از نسخه‌ها قابل ادغام نیستند.",
-       "mergehistory-success": "$3 نسخه از [[:$1]]  با موفقیت در [[:$2]] ادغام {{PLURAL:$3|شد|شدند}}.",
+       "mergehistory-success": "$3 نسخه از [[:$1]]  با موفقیت در [[:$2]] ادغام {{PLURAL:$3|شد}}.",
        "mergehistory-fail": "ادغام تاریخچه ممکن نیست، لطفاً گزینه‌های صفحه و زمان را بازبینی کنید.",
        "mergehistory-fail-toobig": "نمی‌توان ادغام تاریخچه را انجام داد که بیشتر از محدودیت $1 {{PLURAL:$1|نسخه}} انتقال داده خواهد شد.",
        "mergehistory-no-source": "صفحهٔ مبدأ $1 وجود ندارد.",
        "mergelogpagetext": "در زیر سیاههٔ آخرین موارد ادغام تاریخچهٔ یک صفحه در صفحه‌ای دیگر را می‌بینید.",
        "history-title": "$1: تاریخچهٔ ویرایش‌ها",
        "difference-title": "$1: تفاوت بین نسخه‌ها",
-       "difference-title-multipage": "$1 و $2: تفاوت بین صفحه‌ها",
-       "difference-multipage": "(تفاوت بین صفحه‌ها)",
+       "difference-title-multipage": "$1 و $2: تفاوت بین صفحات",
+       "difference-multipage": "(تفاوت بین صفحات)",
        "lineno": "سطر $1:",
        "compareselectedversions": "مقایسهٔ نسخه‌های انتخاب‌شده",
-       "showhideselectedversions": "نمایش/نهفتن نسخه‌های انتخاب شده",
+       "showhideselectedversions": "تغییر پدیداری بازبینی‌های انتخاب‌شده",
        "editundo": "خنثی‌سازی",
        "diff-empty": "(بدون تفاوت)",
        "diff-multi-sameuser": "({{PLURAL:$1|یک نسخهٔ میانی|$1 نسخهٔ میانی}} توسط کاربر مشابهی که نشان داده نشده)",
        "shown-title": "نمایش $1 {{PLURAL:$1|نتیجه|نتیجه}} در هر صفحه",
        "viewprevnext": "نمایش ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "'''صفحه‌ای با عنوان «[[:$1]]» در این ویکی وجود دارد.'''",
-       "searchmenu-new": "<strong>اÛ\8cجاد ØµÙ\81Ø­Ù\87Ù\94 Â«[[:$1]]» Ø¯Ø± Ø§Û\8cÙ\86 Ù\88Û\8cÚ©Û\8c!</strong> {{PLURAL:$2|0=|Ù\87Ù\85Ú\86Ù\86Û\8cÙ\86 Ù\85شاÙ\87دÙ\87Ù\94 ØµÙ\81Ø­Ù\87Ù\94 Ù¾Û\8cدا Ø´Ø¯Ù\87 Ø¨Ø§ Ø¬Ø³ØªØ¬Ù\88Û\8c Ø´Ù\85ا.|Ù\87Ù\85Ú\86Ù\86Û\8cÙ\86 Ù\85شاÙ\87دÙ\87Ù\94 Ø¬Ø³ØªØ¬Ù\88Û\8c Ù\86تاÛ\8cج Ù¾Û\8cدا Ø´Ø¯Ù\87.}}",
+       "searchmenu-new": "<strong>صÙ\81Ø­Ù\87Ù\94 Â«[[:$1]]» Ø±Ø§ Ø¯Ø± Ø§Û\8cÙ\86 Ù\88Û\8cÚ©Û\8c Ø¨Ø³Ø§Ø²Û\8cد!</strong> {{PLURAL:$2|0=Ù\87Ù\85Ú\86Ù\86Û\8cÙ\86 ØµÙ\81Ø­Ù\87Ù\94 Û\8cاÙ\81تâ\80\8cشدÙ\87 Ø¨Ø§ Ø¬Ø³ØªØ¬Ù\88Û\8cتاÙ\86 Ø±Ø§ Ø¨Ø¨Û\8cÙ\86Û\8cد.|Ù\87Ù\85Ú\86Ù\86Û\8cÙ\86 Ù\86تاÛ\8cج Ø¬Ø³ØªØ¬Ù\88Û\8c Û\8cاÙ\81تâ\80\8cشدÙ\87 Ø±Ø§ Ø¨Ø¨Û\8cÙ\86Û\8cد.}}",
        "searchprofile-articles": "صفحه‌های محتوایی",
        "searchprofile-images": "چندرسانه‌ای",
        "searchprofile-everything": "همه‌چیز",
        "searchprofile-advanced-tooltip": "جستجو در فضاهای نام دلخواه",
        "search-result-size": "$1 ({{PLURAL:$2|یک واژه|$2 واژه}})",
        "search-result-category-size": "{{PLURAL:$1|یک عضو|$1 عضو}} ({{PLURAL:$2|یک زیررده|$2 زیررده}}، {{PLURAL:$3|یک پرونده|$3 پرونده}})",
-       "search-result-score": "ارتباط: $1٪",
        "search-redirect": "(تغییرمسیر $1)",
        "search-section": "(بخش $1)",
        "search-file-match": "(تشابه محتوی پرونده)",
        "searchall": "همه",
        "showingresults": "نمایش حداکثر {{PLURAL:$1|'''۱''' نتیجه|'''$1''' نتیجه}} در پایین، آغاز از شماره '''$2'''.",
        "showingresultsinrange": "نمایش در پائین تا {{PLURAL:$1|<strong>1</strong> نتیجه|<strong>$1</strong> نتیجه}} in range #<strong>$2</strong> تا #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|نتیجهٔ '''$1''' از '''$3'''|نتایج '''$1 تا $2''' از '''$3'''}} برای '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|نتایج <strong>$1</strong> از <strong>$3</strong>|نتایج <strong>$1 - $2</strong از <strong>$3</strong>}}",
        "search-nonefound": "نتیجه‌ای منطبق با درخواست پیدا نشد.",
        "powersearch-legend": "جستجوی پیشرفته",
        "powersearch-ns": "جستجو در فضاهای نام:",
        "preferences": "ترجیحات",
        "mypreferences": "ترجیحات",
        "prefs-edits": "تعداد ویرایش‌ها:",
-       "prefsnologintext2": "لطفاً  $1  برای تنظیم ترجیحات کاربر.",
+       "prefsnologintext2": "خواهشمند است برای تغییر تنظیمات‌تان وارد شوید.",
        "prefs-skin": "پوسته",
        "skin-preview": "پیش‌نمایش",
        "datedefault": "بدون ترجیح",
        "yourlanguage": "زبان:",
        "yourvariant": "گویش زبان محتوا:",
        "prefs-help-variant": "گویش انتخابی شما برای نمایش محتوای صفحه‌ها در این ویکی.",
-       "yournick": "اÙ\85ضاÛ\8c Ø¬Ø¯Û\8cد:",
+       "yournick": "اÙ\85ضاÛ\8c ØªØ§Ø²Ù\87:",
        "prefs-help-signature": "نظرهای نوشته‌شده در صفحهٔ بحث باید با «<nowiki>~~~~</nowiki>» امضا شوند؛ این علامت به‌صورت خودکار به امضای شما و مهر تاریخ تبدیل خواهد شد.",
        "badsig": "امضای خام نامجاز.\nلطفاً برچسب‌های اچ‌تی‌ام‌ال را بررسی کنید.",
        "badsiglength": "امضای شما بیش از اندازه طولانی است.\nامضا باید کمتر از $1 {{PLURAL:$1|نویسه}} طول داشته باشد.",
        "right-createaccount": "ایجاد حساب‌های کاربری",
        "right-minoredit": "علامت‌زدن ویرایش‌ها به‌عنوان جزئی",
        "right-move": "انتقال صفحه",
-       "right-move-subpages": "انتقال صفحÙ\87â\80\8cÙ\87ا Ø¨Ù\87 Ù\87Ù\85راÙ\87 Ø²Û\8cرâ\80\8cصÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8cشاÙ\86",
+       "right-move-subpages": "انتقال صفحات Ø¨Ù\87 Ù\87Ù\85راÙ\87 Ø²Û\8cرâ\80\8cصÙ\81حاتâ\80\8cشاÙ\86",
        "right-move-rootuserpages": "انتقال صفحه‌های کاربری سرشاخه",
        "right-move-categorypages": "انتقال صفحهٔ رده",
        "right-movefile": "انتقال پرونده‌ها",
        "right-purge": "پاک‌کردن میانگیر صفحه بدون مشاهدهٔ صفحهٔ تأیید",
        "right-autoconfirmed": "از محدودیت‌های سرعت آی‌پی‌-محور تاثیر نمی‌گیرد",
        "right-bot": "تلقی‌شده به عنوان یک فرآیند خودکار",
-       "right-nominornewtalk": "Ù\88Û\8cراÛ\8cØ´ Ø¬Ø²Ø¦Û\8c ØµÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8c Ø¨Ø­Ø« Ø¨Ù\87 Ø´Ú©Ù\84Û\8c Ú©Ù\87 Ø¨Ø§Ø¹Ø« Ø§Ø¹Ù\84اÙ\86 Ù¾Û\8cغاÙ\85 Ø¬Ø¯Û\8cد نشود",
+       "right-nominornewtalk": "Ù\88Û\8cراÛ\8cØ´ Ø¬Ø²Ø¦Û\8c ØµÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8c Ø¨Ø­Ø« Ø¨Ù\87 Ø´Ú©Ù\84Û\8c Ú©Ù\87 Ø¨Ø§Ø¹Ø« Ø§Ø¹Ù\84اÙ\86 Ù¾Û\8cغاÙ\85 ØªØ§Ø²Ù\87 نشود",
        "right-apihighlimits": "سقف بالاتر استفاده از API",
        "right-writeapi": "استفاده از API مربوط به نوشتن",
-       "right-delete": "حذف صفحه‌ها",
+       "right-delete": "حذف صفحات",
        "right-bigdelete": "حذف صفحه‌های دارای تاریخچهٔ بزرگ",
        "right-deletelogentry": "حذف و احیای مدخل‌های خاصی از سیاهه",
        "right-deleterevision": "حذف و احیای نسخه‌های خاصی از صفحه",
        "right-deletedhistory": "مشاهدهٔ موارد حذف‌شده از تاریخچه، بدون دیدن متن آن‌ها",
        "right-deletedtext": "مشاهدهٔ متن حذف‌شده و تغییرات بین نسخه‌های حذف‌شده",
        "right-browsearchive": "جستجوی صفحه‌های حذف‌شده",
-       "right-undelete": "احیای صفحه‌ها",
-       "right-suppressrevision": "بازبینی و احیای ویرایش‌هایی که از مدیران پنهان شده‌اند",
+       "right-undelete": "احیای صفحات",
+       "right-suppressrevision": "مشاهده  و احیای ویرایش‌هایی که از کاربران پنهان شده‌اند",
+       "right-viewsuppressed": "مشاهده نسخه‌هایی که از کاربران مخفی شده‌اند",
        "right-suppressionlog": "مشاهدهٔ سیاهه‌های خصوصی",
        "right-block": "قطع دسترسی ویرایشی دیگر کاربران",
        "right-blockemail": "قطع دسترسی دیگر کاربران برای ارسال رایانامه",
        "right-ipblock-exempt": "تاثیر نپذیرفتن از قطع دسترسی‌های آی‌پی، خودکار یا فاصله‌ای",
        "right-proxyunbannable": "تاثیر نپذیرفتن از قطع دسترسی خودکار پروکسی‌ها",
        "right-unblockself": "بازکردن دسترسی خود",
-       "right-protect": "تغییر میزان محافظت صفحه‌ها و ویرایش صفحه‌های محافظت‌شده آبشاری",
-       "right-editprotected": "ویرایش صفحه‌های محافظت شده به عنوان \"{{int:protect-level-sysop}}\"",
+       "right-protect": "تغییر میزان محافظت صفحات و ویرایش صفحات محافظت‌شده آبشاری",
+       "right-editprotected": "ویرایش صفحه‌های محافظت‌شده به‌عنوان «{{int:protect-level-sysop}}»",
        "right-editsemiprotected": "ویرایش صفحه حفاظت‌شده به عنوان \"{{int:protect-level-autoconfirmed}}\"",
        "right-editinterface": "ویرایش واسط کاربری",
        "right-editusercssjs": "ویرایش صفحه‌های CSS و JS دیگر کاربرها",
        "right-editmyusercss": "پرونده‌های سی‌اس‌اس کاربری خود را ویرایش کنید",
        "right-editmyuserjs": "پرونده‌های جاوااسکریپت کاربری خود را ویرایش کنید",
        "right-viewmywatchlist": "فهرست پیگیری‌های خود را ببینید",
-       "right-editmywatchlist": "فهرست پیگیری‌های خود را ویرایش کنید. توجه داشته باشید برخی از اقدامات حتی بدون این دسترسی هم صفحه‌ها را اضافه می‌کنند.",
+       "right-editmywatchlist": "فهرست پیگیری‌های خود را ویرایش کنید. توجه داشته باشید برخی از اقدامات حتی بدون این دسترسی هم صفحات را اضافه می‌کنند.",
        "right-viewmyprivateinfo": "داده‌های خصوصی خود را ببینید (مانند رایانشانی و نام واقعی)",
        "right-editmyprivateinfo": "داده‌های خصوصی خود را ویرایش کنید (مانند رایانشانی و نام واقعی)",
        "right-editmyoptions": "ترجیحات خود را ویرایش",
        "right-autopatrol": "گشت زدن خودکار ویرایش‌های خودش",
        "right-patrolmarks": "مشاهدهٔ برچسب گشت تغییرات اخیر",
        "right-unwatchedpages": "مشاهدهٔ فهرست صفحه‌هایی که پی‌گیری نمی‌شوند",
-       "right-mergehistory": "ادغام تاریخچهٔ صفحه‌ها",
+       "right-mergehistory": "ادغام تاریخچهٔ صفحات",
        "right-userrights": "ویرایش تمام اختیارات کاربرها",
        "right-userrights-interwiki": "ویرایش اختیارات کاربرهای ویکی‌های دیگر",
        "right-siteadmin": "قفل‌کردن و بازکردن پایگاه داده‌ها",
        "recentchanges-summary": "آخرین تغییرات ویکی را در این صفحه پی‌گیری کنید.",
        "recentchanges-noresult": "هیچ تغییری در طول دورهٔ تعیین‌شده با این معیارها هم‌خوانی نداشت.",
        "recentchanges-feed-description": "آخرین تغییرات ویکی را در این خوراک پی‌گیری کنید.",
-       "recentchanges-label-newpage": "اÛ\8cÙ\86 Ù\88Û\8cراÛ\8cØ´ ØµÙ\81Ø­Ù\87â\80\8cاÛ\8c Ø¬Ø¯Û\8cد ایجاد کرد",
+       "recentchanges-label-newpage": "اÛ\8cÙ\86 Ù\88Û\8cراÛ\8cØ´ ØµÙ\81Ø­Ù\87â\80\8cاÛ\8c ØªØ§Ø²Ù\87 ایجاد کرد",
        "recentchanges-label-minor": "این یک ویرایش جزئی‌است",
        "recentchanges-label-bot": "این ویرایش را یک ربات انجام داده‌است",
        "recentchanges-label-unpatrolled": "این ویرایش هنوز گشت‌زنی نشده‌است",
        "recentchanges-label-plusminus": "حجم صفحه به اندازه این بایت‌ها تغییر یافته‌است",
        "recentchanges-legend-heading": "'''اختصارها:'''",
-       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (Ù\87Ù\85Ú\86Ù\86Û\8cÙ\86 Ø¨Ù\87 [[Special:NewPages|Ù\81Ù\87رست ØµÙ\81حات Ø¬Ø¯Û\8cد]] نگاه کنید)",
-       "recentchanges-legend-plusminus": "('' ±۱۲۳'')",
-       "rcnotefrom": "در زیر تغییرات از <strong>$2</strong> (تا <strong>$1</strong> نشان داده شده‌است).",
-       "rclistfrom": "Ù\86Ù\85اÛ\8cØ´ ØªØºÛ\8cÛ\8cرات Ø¬Ø¯Û\8cد با شروع از $3 $2",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (Ù\87Ù\85Ú\86Ù\86Û\8cÙ\86 Ø¨Ù\87 [[Special:NewPages|Ù\81Ù\87رست ØµÙ\81حات ØªØ§Ø²Ù\87]] نگاه کنید)",
+       "recentchanges-legend-plusminus": "(<em>±۱۲۳</em>)",
+       "rcnotefrom": "در زیر تغییرات از <strong>$3, $4</strong> (تا <strong>$1</strong> {{PLURAL:$5|نشان داده شده‌است|نشان داده شده‌اند}}).",
+       "rclistfrom": "Ù\86Ù\85اÛ\8cØ´ ØªØºÛ\8cÛ\8cرات ØªØ§Ø²Ù\87 با شروع از $3 $2",
        "rcshowhideminor": "$1 ویرایش‌های جزئی",
        "rcshowhideminor-show": "نمایش",
        "rcshowhideminor-hide": "پنهان‌کردن",
        "upload_directory_read_only": "شاخهٔ بارگذاری ($1) از طرف سرور وب قابل نوشتن نیست.",
        "uploaderror": "خطای بارگذاری",
        "upload-recreate-warning": "'''هشدار: پرونده‌ای با این نام حذف یا منتقل شده است.'''\n\nبرای راحتی، سیاههٔ حذف و انتقال برای این صفحه در زیر آمده است:",
-       "uploadtext": "از فرم زیر برای بارگذاری کردن پرونده‌های جدید استفاده کنید.\nبرای دیدن پرونده‌هایی که قبلاً بارگذاری شده‌اند به [[Special:FileList|فهرست پرونده‌ها]] بروید. بارگذاری نیز مجدد در [[Special:Log/upload|سیاههٔ بارگذاری‌ها]] و حذف پرونده‌ها در [[Special:Log/delete|deletion log]] ثبت می‌شود.\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|alt text]]</nowiki></code>''' برای استفاده از یک نسخه ۲۰۰ پیکسلی از پرونده درون یک جعبه در سمت چپ متن که عبارت alt text در آن به عنوان توضیح استفاده شده\n*'''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' برای ایجاد یک پیونده مستقیم به پرونده بدون نمایش پرونده",
+       "uploadtext": "از فرم زیر برای بارگذاری کردن پرونده‌های جدید استفاده کنید.\nبرای دیدن پرونده‌هایی که قبلاً بارگذاری شده‌اند به [[Special:FileList|فهرست پرونده‌ها]] بروید. بارگذاری نیز مجدد در [[Special:Log/upload|سیاههٔ بارگذاری‌ها]] و حذف پرونده‌ها در [[Special:Log/delete|deletion log]] ثبت می‌شود.\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|alt text]]</nowiki></code>''' برای استفاده از یک نسخه ۲۰۰ پیکسلی از پرونده درون یک جعبه در سمت چپ متن که عبارت alt text در آن به عنوان توضیح استفاده شده\n*'''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' برای ایجاد یک پیونده مستقیم به پرونده بدون نمایش پرونده",
        "upload-permitted": "انواع مجاز پرونده‌ها: $1.",
        "upload-preferred": "انواع ترجیح‌داده شده پرونده‌ها: $1.",
        "upload-prohibited": "انواع نامجاز پرونده‌ها: $1.",
        "ignorewarning": "چشم‌پوشی از هشدار و ذخیرهٔ پرونده.",
        "ignorewarnings": "چشم‌پوشی از همهٔ هشدارها",
        "minlength1": "نام پرونده دست کم باید یک حرف باشد.",
-       "illegalfilename": "نام پرونده «$1» نویسه‌هایی را شامل می‌شود که در نام صفحه‌ها مجاز نیستند.\nلطفاً نام پرونده را تغییر دهید و آن را دوباره بارگذاری کنید.",
+       "illegalfilename": "نام پرونده «$1» نویسه‌هایی را شامل می‌شود که در نام صفحات مجاز نیستند.\nلطفاً نام پرونده را تغییر دهید و آن را دوباره بارگذاری کنید.",
        "filename-toolong": "نام پرونده نباید از ۲۴۰ بایت طولانی‌تر باشد.",
        "badfilename": "نام پرونده به «$1» تغییر کرد.",
        "filetype-mime-mismatch": "پسوند پرونده «$1.‎» با نوع MIME آن ($2) مطابقت ندارد.",
        "uploadwarning": "هشدار بارگذاری",
        "uploadwarning-text": "لطفاً توضیحات پرونده را در زیر تغییر دهید و دوباره تلاش کنید.",
        "savefile": "ذخیرهٔ پرونده",
-       "uploadedimage": "«[[$1]]» را بارگذاری کرد",
-       "overwroteimage": "نسخه جدیدی از  «[[$1]]» را بارگذاری کرد",
        "uploaddisabled": "بارگذاری غیرفعال است.",
        "copyuploaddisabled": "بارگذاری از طریق نشانی اینترنتی غیرفعال است.",
        "uploaddisabledtext": "امکان بارگذاری پرونده غیرفعال است.",
        "license": "اجازه‌نامه:",
        "license-header": "اجازه‌نامه",
        "nolicense": "هیچ کدام انتخاب نشده‌است",
+       "licenses-edit": "گزینه‌های مجوز ویرایش",
        "license-nopreview": "(پیش‌نمایش وجود ندارد)",
-       "upload_source_url": "(یک نشانی اینترنتی معتبر و قابل دسترسی برای عموم)",
-       "upload_source_file": "(پرونده‌ای در رایانهٔ شما)",
+       "upload_source_url": "(شما یک پرونده انتخاب از یک URL معتبر و دسترس عموم انتخاب کردید)",
+       "upload_source_file": "(پرونده‌ای از رایانهٔ شما انتخاب شده‌است)",
+       "listfiles-delete": "حذف",
        "listfiles-summary": "این صفحهٔ ویژه تمام پرونده‌های بارگذاری‌شده را نمایش می‌دهد.",
        "listfiles_search_for": "جستجو به دنبال نام پرونده چندرسانه‌ای:",
        "imgfile": "پرونده",
        "filerevert-comment": "دلیل:",
        "filerevert-defaultcomment": "واگردانی به نسخهٔ $1 ساعت $2",
        "filerevert-submit": "برو",
-       "filerevert-success": "''[[Media:$1|$1]]''' به [$4 نسخهٔ مورخ $2 ساعت $3] واگردانده شد.",
+       "filerevert-success": "<strong>[[Media:$1|$1]]</strong> به [$4 نسخهٔ مورخ $2 ساعت $3] واگردانده شد.",
        "filerevert-badversion": "نسخهٔ قدیمی‌تری از این پرونده وجود نداشت.",
        "filedelete": "حذف $1",
        "filedelete-legend": "حذف پرونده",
        "listduplicatedfiles-summary": "این فهرست پرونده‌هایی با نسخه‌های اخیر این پرونده تکراری است که نسخه‌های اخبر سایر پرونده‌ها است. فقط پرونده‌های محلی در نظر گرفته شده‌اند.",
        "listduplicatedfiles-entry": "[[:File:$1|$1]][[$3|{{PLURAL:$2|یک تکرار|$2 تکرار}}]] دارد.",
        "unusedtemplates": "الگوهای استفاده‌نشده",
-       "unusedtemplatestext": "این صفحه همهٔ صفحه‌هایی در فضای نام {{ns:template}} را که در هیچ صفحه‌ای به کار نرفته‌اند، فهرست می‌کند.\nبه یاد داشته باشید که پیش از پاک‌کردن این صفحه‌ها پیوندهای دیگر به آنها را هم وارسی کنید.",
+       "unusedtemplatestext": "این صفحه همهٔ صفحاتی در فضای نام {{ns:template}} را که در هیچ صفحه‌ای به کار نرفته‌اند، فهرست می‌کند.\nبه یاد داشته باشید که پیش از پاک‌کردن این صفحات پیوندهای دیگر به آنها را هم وارسی کنید.",
        "unusedtemplateswlh": "پیوندهای دیگر",
        "randompage": "مقالهٔ تصادفی",
        "randompage-nopages": "هیچ صفحه‌ای در این {{PLURAL:$2|فضای نام|فضاهای نام}} موجود نیست: $1.",
        "randomincategory": "صفحهٔ تصادفی در رده",
        "randomincategory-invalidcategory": "«$1» نامی معتبر برای یک ردهٔ نیست.",
        "randomincategory-nopages": "هیج صفحه‌ای در رده [[:Category:$1|$1]] وجود ندارد.",
-       "randomincategory-selectcategory": "دریافت صفحه‌ای تصادفی از دسته‌بندی: $1 $2.",
-       "randomincategory-selectcategory-submit": "برو",
+       "randomincategory-category": "رده:",
+       "randomincategory-legend": "صفحهٔ تصادفی در رده",
        "randomredirect": "تغییرمسیر تصادفی",
        "randomredirect-nopages": "هیج صفحهٔ تغییرمسیری در فضای نام «$1» موجود نیست.",
        "statistics": "آمار",
-       "statistics-header-pages": "آمار صفحه‌ها",
+       "statistics-header-pages": "آمار صفحه",
        "statistics-header-edits": "آمار ویرایش‌ها",
        "statistics-header-views": "آمار بازدیدها",
        "statistics-header-users": "آمار کاربران",
        "statistics-header-hooks": "آمارهای دیگر",
        "statistics-articles": "صفحه‌های محتوایی",
-       "statistics-pages": "صفحه‌ها",
+       "statistics-pages": "صفحات",
        "statistics-pages-desc": "تمام صفحه‌های این ویکی، از جمله صفحه‌های بحث، تغییرمسیر و غیره",
        "statistics-files": "پرونده‌های بارگذاری‌شده",
        "statistics-edits": "ویرایش صفحه‌ها از هنگامی که {{SITENAME}} راه‌اندازی شده",
        "brokenredirects-edit": "ویرایش",
        "brokenredirects-delete": "حذف",
        "withoutinterwiki": "صفحه‌های بدون پیوند میان‌ویکی",
-       "withoutinterwiki-summary": "این صفحه‌ها پیوندی به صفحه‌ای به زبان دیگر نمی‌دارند:",
+       "withoutinterwiki-summary": "این صفحات پیوندی به صفحه‌ای به زبان دیگر نمی‌دارند:",
        "withoutinterwiki-legend": "پیشوند",
        "withoutinterwiki-submit": "نمایش",
        "fewestrevisions": "مقاله‌های دارای کمترین شمار ویرایش",
        "wantedpages-badtitle": "عنوان نامجاز در مجموعهٔ نتایج: $1",
        "wantedfiles": "پرونده‌های مورد نیاز",
        "wantedfiletext-cat": "پرونده‌های زیر استفاده می‌شوند اما موجود نیستند. همچنین ممکن است پرونده‌های مخازن خارجی با وجود موجود بودن در اینجا فهرست شوند. هرگونه رتبه مثبت کاذب <del>خط خواهد خورد.</del> علاوه بر این، صفحاتی که پرونده‌هایی ناموجود را در خود جای داده‌اند در [[:$1]] فهرست شده‌اند.",
+       "wantedfiletext-cat-noforeign": "پرونده‌های زیر استفاده می‌شود اما وجود ندارد. علاوه بر این، صفحاتی که پرونده‌ها در آنها وجود دارند فهرست شده‌اند در [[:$1]].",
        "wantedfiletext-nocat": "پرونده‌های زیر استفاده می‌شوند اما موجود نیستند. همچنین ممکن است پرونده‌های مخازن خارجی با وجود موجود بودن در اینجا فهرست شوند. هرگونه رتبهٔ مثبت کاذب <del>خط خواهد خورد.</del>",
+       "wantedfiletext-nocat-noforeign": "پرونده‌های زیر استفاده می‌شوند اما وجود ندارد.",
        "wantedtemplates": "الگوهای مورد نیاز",
        "mostlinked": "صفحه‌هایی که بیشتر از همه به آن‌ها پیوند داده شده‌است",
        "mostlinkedcategories": "رده‌هایی که بیشتر از همه به آن‌ها پیوند داده شده‌است",
-       "mostlinkedtemplates": "ببشترین صفحه‌های تراگنجایش‌شده",
+       "mostlinkedtemplates": "ببشترین صفحات تراگنجانده‌شده",
        "mostcategories": "صفحه‌های دارای بیشترین رده",
        "mostimages": "پرونده‌هایی که بیشتر از همه به آن‌ها پیوند داده شده‌است",
        "mostinterwikis": "صفحه‌های دارای بیشترین میان‌ویکی",
        "mostrevisions": "صفحه‌های دارای بیشترین نسخه",
-       "prefixindex": "تمام صفحه‌ها با پیشوند",
+       "prefixindex": "تمام صفحات با پیشوند",
        "prefixindex-namespace": "همهٔ صفحه‌های دارای پیشوند (فضای‌نام $1)",
        "prefixindex-strip": "حذف پیشوند در فهرست",
        "shortpages": "صفحه‌های کوتاه",
        "usercreated": "{{GENDER:$3|ایجادشده}} در تاریخ $1 در ساعت $2",
        "newpages": "صفحه‌های تازه",
        "newpages-username": "نام کاربری:",
-       "ancientpages": "قدیمی‌ترین صفحه‌ها",
+       "ancientpages": "قدیمی‌ترین صفحات",
        "move": "انتقال",
        "movethispage": "انتقال این صفحه",
        "unusedimagestext": "پرونده‌های زیر موجودند اما در هیچ صفحه‌ای به کار نرفته‌اند.\nلطفاً توجه داشته باشید که دیگر وبگاه‌ها ممکن است با یک نشانی اینترنتی مستقیم به یک پرونده پیوند دهند، و با وجود این که در استفادهٔ فعال هستند در این جا فهرست شوند.",
        "alllogstext": "نمایش یک‌جای تمام سیاهه‌های موجود در {{SITENAME}}.\nمی‌توانید با انتخاب نوع سیاهه، نام کاربری (حساس به کوچکی و بزرگی حروف) و صفحه‌های تغییریافته (حساس به بزرگی و کوچکی حروف)، نمایش را محدودتر سازید.",
        "logempty": "مورد منطبق با منظور شما در سیاهه یافت نشد.",
        "log-title-wildcard": "صفحه‌هایی را جستجو کن که عنوانشان با این عبارت آغاز می‌شود",
-       "showhideselectedlogentries": "نمایش/نهفتن موارد انتخابی در سیاهه",
-       "allpages": "همهٔ صفحه‌ها",
+       "showhideselectedlogentries": "تغییر پدیداری موارد انتخاب‌شده سیاهه",
+       "allpages": "همهٔ صفحات",
        "nextpage": "صفحهٔ بعد ($1)",
        "prevpage": "صفحهٔ قبلی ($1)",
-       "allpagesfrom": "نمایش صفحه‌ها با شروع از:",
-       "allpagesto": "نمایش صفحه‌ها با پایان در:",
-       "allarticles": "همهٔ صفحه‌ها",
-       "allinnamespace": "همهٔ صفحه‌ها (فضای نام $1)",
+       "allpagesfrom": "نمایش صفحات با شروع از:",
+       "allpagesto": "نمایش صفحات با پایان در:",
+       "allarticles": "همهٔ صفحات",
+       "allinnamespace": "همهٔ صفحات (فضای نام $1)",
        "allpagessubmit": "برو",
        "allpagesprefix": "نمایش صفحه‌های دارای پیشوند:",
-       "allpagesbadtitle": "عنوان صفحهٔ داده‌شده نامعتبر است یا اینکه دارای پیشوندی بین‌زبانی یا بین‌ویکی‌ای است. ممکن است نویسه‌هایی بدارد که نمی‌توان از آنها در عنوان صفحه‌ها استفاده کرد.",
+       "allpagesbadtitle": "عنوان صفحهٔ داده‌شده نامعتبر است یا اینکه دارای پیشوندی بین‌زبانی یا بین‌ویکی‌ای است. ممکن است نویسه‌هایی بدارد که نمی‌توان از آنها در عنوان صفحات استفاده کرد.",
        "allpages-bad-ns": "{{SITENAME}} دارای فضای نام «$1» نیست.",
        "allpages-hide-redirects": "پنهان‌کردن تغییرمسیرها",
        "cachedspecial-viewing-cached-ttl": "شما در حال مشاهدهٔ نسخه‌ای از این صفحه که در میانگیر قرار دارد هستید که ممکن است برای $1 قبل باشد.",
        "cachedspecial-viewing-cached-ts": "شما در حال مشاهدهٔ نسخه‌ای از این صفحه که در میانگیر قرار دارد هستید، و این نسخه ممکن است کاملاً واقعی نباشد.",
        "cachedspecial-refresh-now": "مشاهده آخرین.",
        "categories": "رده‌ها",
-       "categoriespagetext": "{{PLURAL:$1|ردهٔ|رده‌های}} زیر دارای صفحه‌ها یا پرونده‌هایی {{PLURAL:$1|است|هستند}}.\n[[Special:UnusedCategories|رده‌های استفاده‌نشده]] در اینجا نمایش داده نشده‌اند.\nهمچنین [[Special:WantedCategories|رده‌های مورد نیاز]] را ببینید.",
+       "categoriespagetext": "{{PLURAL:$1|ردهٔ|رده‌های}} زیر دارای صفحات یا پرونده‌هایی {{PLURAL:$1|است|هستند}}.\n[[Special:UnusedCategories|رده‌های استفاده‌نشده]] در اینجا نمایش داده نشده‌اند.\nهمچنین [[Special:WantedCategories|رده‌های مورد نیاز]] را ببینید.",
        "categoriesfrom": "نمایش رده‌ها با شروع از:",
        "special-categories-sort-count": "مرتب کردن بر اساس تعداد",
        "special-categories-sort-abc": "مرتب کردن الفبایی",
        "noindex-category-desc": "این صفحه توسط ربات‌ها فهرست‌نشده‌است به این دلیل که واژه جادویی <code><nowiki>__NOINDEX__</nowiki></code> در آن یا در فضای که پرچم مجاز است دارد.",
        "index-category-desc": "این صفحه <code><nowiki>__INDEX__</nowiki></code> درونش دارد (و در فضای نامی است که پرچم مجاز است)، و به این دلیل توسط ربات مجاز است که به‌صورت عادی نباید می‌شد.",
        "post-expand-template-inclusion-category-desc": "پس از گسترش همهٔ الگوها، حجم صفحه بزرگتر از <code>$wgMaxArticleSize</code> است بنابراین بعضی از الگو گسترش نیافته‌اند.",
-       "post-expand-template-argument-category-desc": "پس از گسترش یک آرگومان الگو (چیزی بین آکولادهای سه‌تایی، مانند <code>{{{Foo}}}</code>) صفحه بزرگتر از <code>$wgMaxArticleSize</code> می‌شود.",
-       "expensive-parserfunction-category-desc": "تÙ\88ابع Ù\87زÛ\8cÙ\86Ù\87â\80\8cبر Ú¯Ø±Ø§Ù\86 (Ù\85اÙ\86Ù\86د <code>#ifexist</code>) Ø²Û\8cادÛ\8c Ø¯Ø± ØµÙ\81جÙ\87 Ø´Ø§Ù\85Ù\84 Ø´Ø¯Ù\87â\80\8cاست. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit] را ببینید.",
-       "broken-file-category-desc": "ردÙ\87 Ø§Ù\81زÙ\88د Ù\85Û\8câ\80\8cØ´Ù\88د Ø§Ú¯Ø± ØµÙ\81Ø­Ù\87 Ø´Ø§Ù\85Ù\84 Û\8cÚ© Ù¾Û\8cÙ\88Ù\86د Ø´Ú©Ø³ØªÙ\87 Ø¨Ø§Ø´Ø¯ (Û\8cا Û\8cÚ© Ù¾Ø¨Ù\88Ù\86د Ø¨Ù\87 Ù¾Ø±Ù\88Ù\86دÙ\87Ù\94 ØªÙ\88کارÛ\8c Ø§Ø³Øª Ú©Ù\87 Ù\88جÙ\88د Ù\86دارد)",
-       "hidden-category-category-desc": "اÛ\8cÙ\86 Û\8cÚ© Ø±Ø¯Ù\87Ù\94 <code><nowiki>__HIDDENCAT__</nowiki></code> Ø¯Ø±Ù\88Ù\86Ø´ Ø§Ø³Øª Ú©Ù\87 Ø§Ø² Ù\86Ù\85اÛ\8cشش Ø¯Ø± Ø¬Ø¹Ø¨Ù\87Ù\94 Ù¾Û\8cÙ\88Ù\86دÙ\87اÛ\8c Ø±Ø¯Ù\87 Ø¨Ù\87â\80\8cصÙ\88رت Ù¾Û\8cØ´â\80\8cÙ\81رض جلوگیری می‌کند.",
+       "post-expand-template-argument-category-desc": "پس از گسترش یک آرگومان الگو (چیزی بین آکولادهای سه‌تایی، مانند <code>{{{Foo}}}</code>) صفحه بزرگتر از <code>$wgMaxArticleSize</code> می‌شود.",
+       "expensive-parserfunction-category-desc": "تÙ\88ابع Ù\87زÛ\8cÙ\86Ù\87â\80\8cبر Ú¯Ø±Ø§Ù\86 (Ù\85اÙ\86Ù\86د <code>#ifexist</code>) Ø²Û\8cادÛ\8c Ø¯Ø± ØµÙ\81جÙ\87 Ø§Ø³ØªÙ\81ادÙ\87 Ø´Ø¯Ù\87â\80\8c است. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit] را ببینید.",
+       "broken-file-category-desc": "صÙ\81Ø­Ù\87 Ø´Ø§Ù\85Ù\84 Û\8cÚ© Ù¾Û\8cÙ\88Ù\86د Ù¾Ø±Ù\88Ù\86دÙ\87 Ø®Ø±Ø§Ø¨ Ø§Ø³Øª (Ù¾Û\8cÙ\88Ù\86دÛ\8c Ø¨Ø±Ø§Û\8c Ø¬Ø§Ø³Ø§Ø²Û\8câ\80\8cکردÙ\86 Û\8cÚ© Ù¾Ø±Ù\88Ù\86دÙ\87 Ù\87Ù\86گاÙ\85Û\8c Ú©Ù\87 Ø¢Ù\86 Ù¾Ø±Ù\88Ù\86دÙ\87 Ù\88جÙ\88د Ù\86دارد).",
+       "hidden-category-category-desc": "ردÙ\87 Ø¯Ø± Ù\85حتÙ\88اÛ\8c ØµÙ\81Ø­Ù\87â\80\8cاش Ø´Ø§Ù\85Ù\84 <code><nowiki>__HIDDENCAT__</nowiki></code> Ø§Ø³ØªØ\8c Ú©Ù\87 Ø§Ø² Ø¨Ù\87 Ø·Ù\88ر Ù¾Û\8cØ´â\80\8cÙ\81رض Ù\86شاÙ\86â\80\8cدادÙ\86 Ø¬Ø¹Ø¨Ù\87 Ù¾Û\8cÙ\88Ù\86دÙ\87اÛ\8c Ø±Ø¯Ù\87 Ø¯Ø± ØµÙ\81حات جلوگیری می‌کند.",
        "trackingcategories-nodesc": "توضیحی وجود ندارد.",
        "trackingcategories-disabled": "رده غیرفعال‌شده است",
        "mailnologin": "نشانی‌ای از فرستنده موجود نیست",
        "watchlist-details": "بدون احتساب صفحه‌های جداگانهٔ بحث، {{PLURAL:$1|$1 صفحه|$1 صفحه}} در فهرست پی‌گیری‌های شما قرار {{PLURAL:$1|دارد|دارند}}.",
        "wlheader-enotif": "آگاه‌سازی رایانامه‌ای فعال است.",
        "wlheader-showupdated": "صفحه‌هایی که پس از آخرین بازدید شما تغییر کرده‌اند '''پررنگ''' نمایش داده شده‌اند.",
-       "wlnote2": "در زیر تغییرات اخیر وجود دارد {{PLURAL:$1|ساعت|<strong>$1</strong> ساعت‌ها}}, به عنوان $2, $3.",
+       "wlnote": "در زیر {{PLURAL:$1|تغییری|<strong>$1</strong> تغییری}} که در {{PLURAL:$2|ساعت|<strong>$2</strong> ساعت}} گذشته انجام شده موجود است، تاریخ آخرین بازیابی: $3، $4",
        "wlshowlast": "نمایش آخرین $1 ساعت $2 روز $3",
        "watchlist-options": "گزینه‌های پی‌گیری",
        "watching": "پی‌گیری...",
        "unwatching": "توقف پی‌گیری...",
        "watcherrortext": "ایرادی در هنگام عوض کردن تنظیمات فهرست پیگیرتان برای «$1» رخ داد.",
-       "enotif_reset": "نشان‌گذاری همهٔ صفحه‌ها به‌عنوان بازدیدشده",
+       "enotif_reset": "نشان‌گذاری همهٔ صفحات به‌عنوان بازدیدشده",
        "enotif_impersonal_salutation": "کاربر {{SITENAME}}",
        "enotif_subject_deleted": "{{SITENAME}} صفحهٔ $1 توسط {{gender:$2|$2}} حذف شد.",
        "enotif_subject_created": "{{SITENAME}} صفحهٔ $1 توسط {{gender:$2|$2}} ایجاد شده.",
        "exbeforeblank": "محتوای صفحه قبل از خالی‌کردن این بود: «$1»",
        "delete-confirm": "حذف «$1»",
        "delete-legend": "حذف",
-       "historywarning": "'''هشدار!''' صفحه‌ای که قصد دارید حذف کنید تاریخچه‌ای با حدود $1 {{PLURAL:$1|نسخه|نسخه}} دارد:",
+       "historywarning": "<strong>هشدار:</strong> صفحه‌ای که در حال پاک‌کردن آن هستید دارای یک تاریخچه همراه $1 {{PLURAL:$1|بازبینی|بازبینی‌ها}} است:",
        "confirmdeletetext": "شما در حال حذف کردن یک صفحه یا تصویر از پایگاه داده‌ها همراه با تمام تاریخچهٔ آن هستید.\nلطفاً این عمل را تأیید کنید و اطمینان حاصل کنید که عواقب این کار را می‌دانید و این عمل را مطابق با [[{{MediaWiki:Policy-url}}|سیاست‌ها]] انجام می‌دهید.",
        "actioncomplete": "عمل انجام شد",
        "actionfailed": "عمل ناموفق بود",
        "deletereasonotherlist": "دلیل دیگر",
        "deletereason-dropdown": "*دلایل متداول حذف\n** هرزنگار\n** خرابکاری\n** نقض حق تکثیر\n** درخواست کاربر\n** تغییرمسیر شکسته",
        "delete-edit-reasonlist": "ویرایش دلایل حذف",
-       "delete-toobig": "این صفحه تاریخچهٔ ویرایشی بزرگی دارد، که شامل بیش از $1 {{PLURAL:$1|نسخه|نسخه}} است.\nبه منظور جلوگیری از اختلال ناخواسته در {{SITENAME}} حذف این گونه صفحه‌ها محدود شده‌است.",
+       "delete-toobig": "این صفحه تاریخچهٔ ویرایشی بزرگی دارد، که شامل بیش از $1 {{PLURAL:$1|نسخه|نسخه}} است.\nبه منظور جلوگیری از اختلال ناخواسته در {{SITENAME}} حذف این گونه صفحات محدود شده‌است.",
        "delete-warning-toobig": "این صفحه تاریخچهٔ ویرایشی بزرگی دارد، که شامل بیش از $1 {{PLURAL:$1|نسخه|نسخه}} است.\nحذف آن ممکن است که عملکرد پایگاه دادهٔ {{SITENAME}} را مختل کند;\nبا احتیاط ادامه دهید.",
-       "deleting-backlinks-warning": "''' هشدار:''' پیوند [[Special:WhatLinksHere/{{FULLPAGENAME}}|صفحات دیگر]] یا تراگنجایش صفحهٔ شما برای حذف.",
+       "deleteprotected": "شما نمی‌توانید این صفحه را پاک کنید چون که از آن محافظت شده‌است.",
+       "deleting-backlinks-warning": "''' هشدار:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|صفحه‌های دیگری]] هستند که به صفحه‌ای که شما در حال حذف آن هستید پیوند دارند یا آن را تراگنجانیده‌اند.",
        "rollback": "واگردانی ویرایش‌ها",
        "rollback_short": "واگردانی",
        "rollbacklink": "واگردانی",
        "protect_expiry_old": "زمان سرآمدن در گذشته‌است.",
        "protect-unchain-permissions": "باز کردن سایر گزینه‌های محافظت",
        "protect-text": "شما می‌توانید سطح محافظت صفحهٔ '''$1''' را ببینید و از اینجا آن را تغییر دهید.",
-       "protect-locked-blocked": "شما در مدتی که دسترسی‌تان قطع است نمی‌توانید سطح محافظت صفحه‌ها را تغییر دهید.\nتنظیمات فعلی صفحهٔ '''$1''' از این قرار است:",
+       "protect-locked-blocked": "شما در مدتی که دسترسی‌تان قطع است نمی‌توانید سطح محافظت صفحات را تغییر دهید.\nتنظیمات فعلی صفحهٔ '''$1''' از این قرار است:",
        "protect-locked-dblock": "به دلیل قفل شدن پایگاه داده، امکان تغییر سطح محافظت صفحه وجود ندارد.\nتنظیمات فعلی صفحهٔ '''$1''' به این قرار است:",
        "protect-locked-access": "حساب کاربری شما اجازهٔ تغییر سطح محافظت صفحه را ندارد.\nتنظیمات فعلی صفحهٔ '''$1''' به این قرار است:",
        "protect-cascadeon": "این صفحه  در حال حاضر محافظت شده‌است زیرا در {{PLURAL:$1|صفحهٔ|صفحه‌های}} زیر که گزینهٔ محافظت آبشاری {{PLURAL:$1|آن|آن‌ها}} فعال است، گنجانده شده است.\nتغییراتی به سطح محافظت این صفحه به محافظت ابشاری تأثیر نخواهد گذاشت.",
        "undeleteviewlink": "نمایش",
        "undeleteinvert": "وارونه کردن انتخاب",
        "undeletecomment": "دلیل:",
-       "undeletedrevisions": "$1 نسخه احیا {{PLURAL:$1|شد|شدند}}",
+       "undeletedrevisions": "$1 نسخه احیا {{PLURAL:$1|شد}}",
        "undeletedrevisions-files": "$1 نسخه و $2 پرونده احیا {{PLURAL:$1|شد|شدند}}.",
        "undeletedfiles": "$1 پرونده احیا {{PLURAL:$1|شد|شدند}}.",
        "cannotundelete": "احیا ناموفق بود:\n$1",
        "undelete-header": "برای دیدن صفحه‌های حذف‌شدهٔ اخیر [[Special:Log/delete|سیاههٔ حذف]] را ببینید.",
        "undelete-search-title": "جستجوی صفحه‌های حذف‌شده",
        "undelete-search-box": "جستجوی صفحه‌های حذف‌شده.",
-       "undelete-search-prefix": "نمایش صفحه‌ها با شروع از:",
+       "undelete-search-prefix": "نمایش صفحات با شروع از:",
        "undelete-search-submit": "برو",
        "undelete-no-results": "هیچ صفحهٔ منطبقی در بایگانی حذف‌شده‌ها یافت نشد.",
        "undelete-filename-mismatch": "امکان احیای نسخهٔ $1 وجود ندارد: نام پرونده مطابقت نمی‌کند.",
        "sp-contributions-search": "جستجوی مشارکت‌ها",
        "sp-contributions-username": "نشانی آی‌پی یا نام کاربری:",
        "sp-contributions-toponly": "فقط ویرایش‌هایی که آخرین نسخه‌اند نمایش داده شود",
-       "sp-contributions-newonly": "Ù\81Ù\82Ø· Ù\86Ù\85اÛ\8cØ´ Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 ØªÙ\88Ù\84Û\8cدâ\80\8cÙ\87اÛ\8c صفحه هستند",
+       "sp-contributions-newonly": "Ù\81Ù\82Ø· Ù\86Ù\85اÛ\8cØ´ Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ø§Û\8cجاد صفحه هستند",
        "sp-contributions-submit": "جستجو",
        "whatlinkshere": "پیوندها به این صفحه",
        "whatlinkshere-title": "صفحه‌هایی که به «$1» پیوند دارند",
        "autoblockid": "شناسه قطع دسترسی خودکار #$1",
        "block": "بستن کاربر",
        "unblock": "بازکردن کاربر",
-       "blockip": "بستن کاربر",
+       "blockip": "مسدودکردن {{GENDER:$1|کاربر}}",
        "blockip-legend": "بستن کاربر",
        "blockiptext": "از فرم زیر برای بستن دسترسی ویرایش یک نشانی آی‌پی یا نام کاربری مشخص استفاده کنید.\nاین کار فقط فقط باید برای جلوگیری از خرابکاری و بر اساس [[{{MediaWiki:Policy-url}}|سیاست قطع دسترسی]] انجام شود.\nدلیل مشخص این کار را در زیر ذکر کنید (مثلاً با ذکر صفحه‌های به‌خصوصی که مورد خرابکاری واقع شده‌اند).",
        "ipaddressorusername": "نشانی آی‌پی یا نام کاربری:",
        "ipbexpiry": "زمان سرآمدن:",
        "ipbreason": "دلیل:",
-       "ipbreason-dropdown": "*دلایل متداول قطع دسترسی\n**واردکردن اطلاعات نادرست\n**پاک‌کردن اطلاعات مفید از صفحه‌ها\n**هرزنگاری از طریق درج مکرر پیوند به وب‌گاه‌ها\n**درج چرندیات یا نوشته‌های بی‌معنا در صفحه‌ها\n**تهدید یا ارعاب دیگر کاربران\n**سوء استفاده از چند حساب کاربری\n**نام کاربری نامناسب",
+       "ipbreason-dropdown": "*دلایل متداول قطع دسترسی\n**واردکردن اطلاعات نادرست\n**پاک‌کردن اطلاعات مفید از صفحات\n**هرزنگاری از طریق درج مکرر پیوند به وب‌گاه‌ها\n**درج چرندیات یا نوشته‌های بی‌معنا در صفحات\n**تهدید یا ارعاب دیگر کاربران\n**سوء استفاده از چند حساب کاربری\n**نام کاربری نامناسب",
        "ipb-hardblock": "جلوگیری از ویرایش کردن کاربران ثبت نام کرده از طریق این نشانی آی‌پی",
        "ipbcreateaccount": "جلوگیری از ایجاد حساب",
        "ipbemailban": "جلوگیری از ارسال رایانامه",
        "unblocked": "دسترسی [[User:$1|$1]] دوباره برقرار شد",
        "unblocked-range": "$1 باز شد",
        "unblocked-id": "قطع دسترسی شماره $1 خاتمه یافت",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] رفع قطع دسترسی شد.",
        "blocklist": "کاربران بسته‌شده",
        "ipblocklist": "کاربران بسته‌شده",
        "ipblocklist-legend": "جستجوی کاربر بسته شده",
        "ipbnounblockself": "شما مجاز به باز کردن دسترسی خود نیستید.",
        "lockdb": "قفل کردن پایگاه داده",
        "unlockdb": "از قفل در آوردن پایگاه داده",
-       "lockdbtext": "قفل کردن پایگاه داده امکان ویرایش صفحه‌ها، تغییر تنظیمات، ویرایش پی‌گیری‌ها، و سایر تغییراتی را که نیازمند تغییری در پایگاه داده است، از همهٔ کاربران سلب می‌کند.\nلطفاً تأیید کنید که همین کار را می‌خواهید انجام دهید، و در اولین فرصت پایگاه داده را از حالت قفل شده خارج خواهید کرد.",
-       "unlockdbtext": "از قفل در آوردن پایگاه داده به تمامی کاربران اجازه می‌دهد که توانایی ویرایش صفحه‌ها، تغییر تنظیمات، تغییر پی‌گیری‌ها و هر تغییر دیگری که نیازمند تغییر در پایگاه داده باشد را دوباره به دست بیاورند.\nلطفاً تأیید کنید که همین کار را می‌خواهید انجام دهید.",
+       "lockdbtext": "قفل کردن پایگاه داده امکان ویرایش صفحات، تغییر تنظیمات، ویرایش پی‌گیری‌ها، و سایر تغییراتی را که نیازمند تغییری در پایگاه داده است، از همهٔ کاربران سلب می‌کند.\nلطفاً تأیید کنید که همین کار را می‌خواهید انجام دهید، و در اولین فرصت پایگاه داده را از حالت قفل شده خارج خواهید کرد.",
+       "unlockdbtext": "از قفل در آوردن پایگاه داده به تمامی کاربران اجازه می‌دهد که توانایی ویرایش صفحات، تغییر تنظیمات، تغییر پی‌گیری‌ها و هر تغییر دیگری که نیازمند تغییر در پایگاه داده باشد را دوباره به دست بیاورند.\nلطفاً تأیید کنید که همین کار را می‌خواهید انجام دهید.",
        "lockconfirm": "بله، من جداً می‌خواهم پایگاه داده را قفل کنم.",
        "unlockconfirm": "بله، من جداً می‌خواهم پایگاه داده را از قفل در آورم.",
        "lockbtn": "قفل کردن پایگاه داده",
        "lockedbyandtime": "(به وسیلهٔ $1 در $2 ساعت $3)",
        "move-page": "انتقال $1",
        "move-page-legend": "انتقال صفحه",
-       "movepagetext": "با استفاده از فرم زیر نام صفحه تغییر خواهد کرد، و تمام تاریخچه‌اش به نام جدید منتقل خواهد شد.\nعنوان قدیمی تبدیل به یک صفحهٔ تغییرمسیر به عنوان جدید خواهد شد.\nشما می‌توانید تغییرمسیرهایی که به عنوان اصلی اشاره دارند را به صورت خودکار به‌روزرسانی کنید.\nپیوندهای که به عنوان صفحهٔ قدیمی وجود دارند، تغییر نخواهند کرد؛ حتماً تغییرمسیرهای [[Special:DoubleRedirects|دوتایی]] یا [[Special:BrokenRedirects|خراب]] را بررسی کنید.\n'''شما''' مسئول اطمینان از این هستید که پیوندها هنوز به همان‌جایی که قرار است بروند.\n\nتوجه کنید که اگر از قبل صفحه‌ای در عنوان جدید وجود داشته باشد صفحه منتقل '''نخواهد شد'''،\nمگر این آخرین ویرایش تغییرمسیر باشد و در  تاریخچهٔ ویرایشی نداشته باشد.\nاین یعنی اگر اشتباه کردید می‌توانید صفحه را به همان جایی که از آن منتقل شده بود برگردانید، و این که نمی‌توانید روی صفحه‌ها موجود بنویسید.\n\n'''هشدار!'''\nانتقال صفحه‌ها به نام جدید ممکن است تغییر اساسی و غیرمنتظره‌ای برای صفحه‌های محبوب باشد؛\nلطفاً مطمئن شوید که قبل از انتقال دادن صفحه، عواقب این کار را درک می‌کنید.",
+       "movepagetext": "با استفاده از فرم زیر نام صفحه تغییر خواهد کرد، و تمام تاریخچه‌اش به نام جدید منتقل خواهد شد.\nعنوان قدیمی تبدیل به یک صفحهٔ تغییرمسیر به عنوان جدید خواهد شد.\nشما می‌توانید تغییرمسیرهایی که به عنوان اصلی اشاره دارند را به صورت خودکار به‌روزرسانی کنید.\nپیوندهای که به عنوان صفحهٔ قدیمی وجود دارند، تغییر نخواهند کرد؛ حتماً تغییرمسیرهای [[Special:DoubleRedirects|دوتایی]] یا [[Special:BrokenRedirects|خراب]] را بررسی کنید.\n'''شما''' مسئول اطمینان از این هستید که پیوندها هنوز به همان‌جایی که قرار است بروند.\n\nتوجه کنید که اگر از قبل صفحه‌ای در عنوان جدید وجود داشته باشد صفحه منتقل '''نخواهد شد'''،\nمگر این آخرین ویرایش تغییرمسیر باشد و در  تاریخچهٔ ویرایشی نداشته باشد.\nاین یعنی اگر اشتباه کردید می‌توانید صفحه را به همان جایی که از آن منتقل شده بود برگردانید، و این که نمی‌توانید روی صفحات موجود بنویسید.\n\n'''هشدار!'''\nانتقال صفحات به نام جدید ممکن است تغییر اساسی و غیرمنتظره‌ای برای صفحات محبوب باشد؛\nلطفاً مطمئن شوید که قبل از انتقال دادن صفحه، عواقب این کار را درک می‌کنید.",
        "movepagetext-noredirectfixer": "استفاده از فرم زیر سبب تغییر نام یک صفحه و انتقال تمام تاریخچهٔ آن به نام جدید می‌شود.\nعنوان پیشین تغییرمسیری به عنوان جدید خواهد شد.\nبه خاطر داشته باشید که [[Special:DoubleRedirects|تغییرمسیرهای دوتایی]] یا [[Special:BrokenRedirects|تغییرمسیرهای خراب]] را بررسی کنید.\nشما مسئولید که مطمئن شوید پیوندها به جایی اشاره می‌کنند که قرار است بروند.\n\nتوجه کنید که اگر صفحه‌ای تحت عنوان جدید از قبل موجود باشد، انتقال انجام '''نخواهد شد'''، مگر اینکه صفحه خالی و یا تغییرمسیر باشد و تاریخچهٔ ویرایشی دیگری نداشته باشد.\nاین یعنی اگر صفحه را به نامی اشتباه منتقل کردید می‌توانید این تغییر را واگردانی کنید، اما نمی‌توانید به صفحه‌ای که از قبل موجود است انتقال دهید.\n\n'''هشدار!'''\nانتقال صفحه‌های پربیننده ممکن است عملی غیرمنتظره باشد؛\nلطفاً پیش از انتقال مطمئن شوید از نتیجهٔ کار آگاهید.",
        "movepagetalktext": "صفحهٔ بحث مربوط، اگر وجود داشته باشد، بطور خودکار همراه با مقالهٔ اصلی منتقل خواهد شد '''مگر اینکه''' :\n* در حال انتقال صفحه از این فضای نام به فضای نام دیگری باشید،\n* یک صفحهٔ بحث غیرخالی تحت این نام جدید وجود داشته باشد، یا\n* جعبهٔ زیر را تیک نزده باشید.\n\nدر این حالات، باید صفحه را بطور دستی انتقال داده و یا محتویات دو صفحه را با ویرایش ادغام کنید.",
        "movearticle": "انتقال صفحه:",
        "moveuserpage-warning": "'''هشدار:''' شما در حال انتقال دادن یک صفحهٔ کاربر هستید. توجه داشته باشید که تنها صفحه منتقل می‌شود و نام کاربر تغییر '''نمی‌یابد'''.",
        "movecategorypage-warning": "<strong>هشدار:</strong> شما در حال انتقال صفحه رده هستید. لطفاً توجه داشته باشید که فقط صفحه منتقل خواهد شد و  صفحات در رده قدیمی می‌مانند و به رده جدید <em>نمی‌روند</em>.",
-       "movenologintext": "برای انتقال صفحه‌ها باید کاربر ثبت‌شده بوده و [[Special:UserLogin|به سامانه وارد شوید]].",
-       "movenotallowed": "شما اجازهٔ انتقال دادن صفحه‌ها را ندارید.",
+       "movenologintext": "برای انتقال صفحات باید کاربر ثبت‌شده بوده و [[Special:UserLogin|به سامانه وارد شوید]].",
+       "movenotallowed": "شما اجازهٔ انتقال دادن صفحات را ندارید.",
        "movenotallowedfile": "شما اجازهٔ انتقال پرونده‌ها را ندارید.",
        "cant-move-user-page": "شما اجازه ندارید صفحه‌های کاربری سرشاخه را انتقال دهید.",
        "cant-move-to-user-page": "شما اجازه ندارید که یک صفحه را به یک صفحهٔ کاربر انتقال دهید (به استثنای زیر صفحه‌های کاربری).",
        "cant-move-category-page": "شما اجازهٔ انتقال دادن صفحهٔ رده‌ها را ندارید.",
        "cant-move-to-category-page": "شما مجوز برای انتقال صفحه به صفحه رده ندارید.",
-       "newtitle": "به‌عنوان جدید",
+       "newtitle": "به عنوان تازه:",
        "move-watch": "پی‌گیری صفحه‌های مبدأ و مقصد",
        "movepagebtn": "صفحه منتقل شود",
        "pagemovedsub": "انتقال با موفقیت انجام شد",
        "movepage-page-unmoved": "صفحهٔ $1 را نمی‌توان به $2 انتقال داد.",
        "movepage-max-pages": "حداکثر تعداد صفحه‌های ممکن ($1 {{PLURAL:$1|صفحه|صفحه}}) که می‌توان انتقال داد منتقل شدند و صفحه‌های دیگر را نمی‌توان به طور خودکار منتقل کرد.",
        "movelogpage": "سیاههٔ انتقال",
-       "movelogpagetext": "در زیر فهرستی از انتقال صفحه‌ها آمده است.",
+       "movelogpagetext": "در زیر فهرستی از انتقال صفحات آمده‌است.",
        "movesubpage": "{{PLURAL:$1|زیرصفحه|زیرصفحه‌ها}}",
        "movesubpagetext": "این صفحه $1 زیرصفحه دارد که در زیر نمایش {{PLURAL:$1|یافته‌است|یافته‌اند}}.",
        "movenosubpage": "این صفحه هیچ زیرصفحه‌ای ندارد.",
        "bad-target-model": "مقصد مورد نظر از مدل محتوایی متفاوتی استفاده می‌کند. تبدیل $1 به $2 ممکن نیست.",
        "imagenocrossnamespace": "امکان انتقال تصویر به فضای نام غیر پرونده وجود ندارد",
        "nonfile-cannot-move-to-file": "امکان انتقال محتوای غیر پرونده به فضای نام پرونده وجود ندارد",
-       "imagetypemismatch": "پسÙ\88Ù\86د Ù¾Ø±Ù\88Ù\86دÙ\87 Ø¬Ø¯Û\8cد با نوع آن سازگار نیست",
+       "imagetypemismatch": "پسÙ\88Ù\86د Ù¾Ø±Ù\88Ù\86دÙ\87 ØªØ§Ø²Ù\87 با نوع آن سازگار نیست",
        "imageinvalidfilename": "نام پروندهٔ هدف نامجاز است",
        "fix-double-redirects": "به روز کردن تمامی تغییرمسیرهایی که به مقالهٔ اصلی اشاره می‌کنند",
        "move-leave-redirect": "بر جا گذاشتن یک تغییرمسیر",
        "semiprotectedpagemovewarning": "'''تذکر:''' این صفحه قفل شده‌است به طوری که تنها کاربران ثبت نام کرده می‌توانند آن را انتقال دهند.\nآخرین موارد سیاهه در زیر آمده است:",
        "move-over-sharedrepo": "== پرونده موجود است ==\n[[:$1]] در یک مخزن مشترک وجود دارد. انتقال یک پرونده به این نام باعث باطل شدن پرونده مشترک خواهد شد.",
        "file-exists-sharedrepo": "نام پرونده انتخاب شده از قبل در یک مخزن مشترک استفاده شده‌است.\nلطفاً یک نام دیگر برگزینید.",
-       "export": "برون‌بری صفحه‌ها",
-       "exporttext": "شما می‌توانید متن و تاریخچهٔ ویرایش یک صفحهٔ مشخص یا مجموعه‌ای از صفحه‌ها را به شکل پوشیده در اکس‌ام‌ال برون‌بری کنید.\nاین اطلاعات را می‌توان در ویکی دیگری که نرم‌افزار «مدیاویکی» را اجرا می‌کند از طریق [[Special:Import|صفحهٔ درون‌ریزی]] وارد کرد.\n\nبرای برون‌بری صفحه‌ها، عنوان آن‌ها را در جعبهٔ زیر وارد کنید (در هر سطر فقط یک عنوان) و مشخص کنید که آیا نسخهٔ اخیر صفحه را به همراه نسخه‌های قدیمی‌تر و تاریخچهٔ صفحه می‌خواهید، یا تنها نسخهٔ اخیر صفحه و اطلاعات آخرین ویرایش را می‌خواهید.\n\nدر حالت دوم، شما می‌توانید از یک پیوند استفاده کنید، مثلاً [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] برای صفحهٔ «[[{{MediaWiki:Mainpage}}]]».",
-       "exportall": "برون‌بری همهٔ صفحه‌ها",
+       "export": "برون‌بری صفحات",
+       "exporttext": "شما می‌توانید متن و تاریخچهٔ ویرایش یک صفحهٔ مشخص یا مجموعه‌ای از صفحات را به شکل پوشیده در اکس‌ام‌ال برون‌بری کنید.\nاین اطلاعات را می‌توان در ویکی دیگری که نرم‌افزار «مدیاویکی» را اجرا می‌کند از طریق [[Special:Import|صفحهٔ درون‌ریزی]] وارد کرد.\n\nبرای برون‌بری صفحات، عنوان آن‌ها را در جعبهٔ زیر وارد کنید (در هر سطر فقط یک عنوان) و مشخص کنید که آیا نسخهٔ اخیر صفحه را به همراه نسخه‌های قدیمی‌تر و تاریخچهٔ صفحه می‌خواهید، یا تنها نسخهٔ اخیر صفحه و اطلاعات آخرین ویرایش را می‌خواهید.\n\nدر حالت دوم، شما می‌توانید از یک پیوند استفاده کنید، مثلاً [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] برای صفحهٔ «[[{{MediaWiki:Mainpage}}]]».",
+       "exportall": "برون‌بری همهٔ صفحات",
        "exportcuronly": "فقط نسخهٔ فعلی شامل شود، نه کل تاریخچه",
-       "exportnohistory": "----\n'''توجه:''' امکان برون‌بری تاریخچهٔ کامل صفحه‌ها از طریق این صفحه به دلایل اجرایی از کار انداخته شده‌است.",
+       "exportnohistory": "----\n'''توجه:''' امکان برون‌بری تاریخچهٔ کامل صفحات از طریق این صفحه به دلایل اجرایی از کار انداخته شده‌است.",
        "exportlistauthors": "شامل فهرست کامل مشارکت‌کنندگان هر صفحه",
        "export-submit": "برون‌بری",
-       "export-addcattext": "افزودن صفحه‌ها از رده:",
+       "export-addcattext": "افزودن صفحات از رده:",
        "export-addcat": "افزودن",
-       "export-addnstext": "افزودن صفحه‌ها از فضای نام:",
+       "export-addnstext": "افزودن صفحات از فضای نام:",
        "export-addns": "افزودن",
        "export-download": "ذخیره به صورت پرونده",
        "export-templates": "شامل شدن الگوها",
        "thumbnail_gd-library": "تنظیمات ناقص کتابخانهٔ GD: عملکرد $1 وجود ندارد",
        "thumbnail_image-missing": "پرونده به نظر گم شده‌است: $1",
        "thumbnail_image-failure-limit": "تلاش‌های ناموفق اخیر بسیاری ($1 یا بیشتر) برای ارائهٔ این تصویر کوچک وجود داشته‌ است. لطفأ بعداً دوباره تلاش کنید.",
-       "import": "درون‌ریزی صفحه‌ها",
+       "import": "درون‌ریزی صفحات",
        "importinterwiki": "درون‌ریزی تراویکی",
-       "import-interwiki-text": "یک ویکی و یک نام صفحه را انتخاب کنید تا اطلاعات از آن درون‌ریزی شود.\nتاریخ نسخه‌ها و نام ویرایش‌کنندگان ثابت خواهد ماند.\nاطلاعات مربوط به درون‌ریزی صفحه‌ها در [[Special:Log/import|سیاههٔ درون‌ریزی‌ها]] درج خواهد شد.",
-       "import-interwiki-source": "ویکی/صفحهٔ منبع:",
+       "import-interwiki-text": "یک ویکی و یک نام صفحه را انتخاب کنید تا اطلاعات از آن درون‌ریزی شود.\nتاریخ نسخه‌ها و نام ویرایش‌کنندگان ثابت خواهد ماند.\nاطلاعات مربوط به درون‌ریزی صفحات در [[Special:Log/import|سیاههٔ درون‌ریزی‌ها]] درج خواهد شد.",
+       "import-interwiki-sourcewiki": "ویکی منبع:",
+       "import-interwiki-sourcepage": "صفحهٔ مبدأ:",
        "import-interwiki-history": "تمام نسخه‌های تاریخچهٔ این صفحه انتقال داده شود",
        "import-interwiki-templates": "تمام الگوها را شامل شود",
        "import-interwiki-submit": "درون‌ریزی شود",
        "import-upload-filename": "نام پرونده:",
        "import-comment": "توضیح:",
        "importtext": "لطفاً پرونده را از ویکی منبع با کمک [[Special:Export|ابزار برون‌بری]] دریافت کنید.\nسپس آن را روی دستگاه‌تان ذخیره کنید و اینجا بارگذاری نمایید.",
-       "importstart": "در حال درون‌ریزی صفحه‌ها...",
+       "importstart": "در حال درون‌ریزی صفحات...",
        "import-revision-count": "$1 {{PLURAL:$1|ویرایش|ویرایش}}",
        "importnopages": "صفحه‌ای برای درون‌ریزی نیست.",
        "imported-log-entries": "$1 {{PLURAL:$1|مورد سیاهه|مورد سیاهه}} درون ریزی شد.",
-       "importfailed": "درون‌ریزی صفحه‌ها شکست خورد: <nowiki>$1</nowiki>",
+       "importfailed": "درون‌ریزی صفحات شکست خورد: <nowiki>$1</nowiki>",
        "importunknownsource": "نوع مأخذ درون‌ریزی معلوم نیست",
-       "importcantopen": "پروندهٔ درون‌ریزی صفحه‌ها باز نشد",
+       "importcantopen": "پروندهٔ درون‌ریزی صفحات باز نشد",
        "importbadinterwiki": "پیوند میان‌ویکی نادرست",
        "importsuccess": "درون‌ریزی با موفقیت انجام شد!",
        "importnosources": "هیچ منبعی برای درون‌ریزی اطلاعات از ویکی دیگر تعریف نشده‌است.",
        "import-upload": "بارگذاری داده اکس‌ام‌ال",
        "import-token-mismatch": "از دست رفتن اطلاعات نشست کاربری. لطفاً دوباره امتحان کنید.",
        "import-invalid-interwiki": "از ویکی مشخص شده نمی‌توان درون‌ریزی انجام داد.",
-       "import-error-edit": "صفحهٔ «$1» وارد نمی‌شود، چون شما مجاز به ویرایش آن نیستید.",
-       "import-error-create": "صفحهٔ «$1» وارد نمی‌شود، چون شما مجاز به ایجاد آن نیستید.",
+       "import-error-edit": "صفحهٔ «$1» وارد نشد، چون شما مجاز به ویرایش آن نیستید.",
+       "import-error-create": "صفحهٔ «$1» وارد نشد، چون شما مجاز به ایجاد آن نیستید.",
        "import-error-interwiki": "صفحه «$1» وارد نشد. چون نام آن برای پیوند خارجی (interwiki) رزرو شده‌است.",
        "import-error-special": "صفحهٔ «$1» درون‌ریزی نشد، چرا که متعلق به فضای نام نامجاز است.",
-       "import-error-invalid": "صفحه \"$1\" به دلیل نامعتبر بودن نامش وارد نمی‌شود.",
+       "import-error-invalid": "صفحه \"$1\" به دلیل نامعتبر بودن نامش که ممکن بود در ویکی نامعتبر باشد، وارد نشد.",
        "import-error-unserialize": "امکان خارج کردن نسخهٔ $2 از صفحهٔ «$1» از حالت سریال‌شده وجود نداشت. گزارش شد که نسخه از مدل محتوای $3 استفاده می‌کند که به صورت $4 سریال شده‌است.",
        "import-error-bad-location": "بازبینی $2 با استفاده از مدل محتوای $3 نمی‌تواند در \"$1\" در این ویکی ذخیره شده باشد، از آنجایی که مدل در آن صفحه پشتیبانی نشده‌است.",
        "import-options-wrong": "{{PLURAL:$2|جزئیات|جزئیات}} اشتباه: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "با توجه به ریشه صفحه عنوان نامعتبر است.",
        "import-rootpage-nosubpage": "فضای نام  \"$1\" صفحهٔ مبنا اجازهٔ زیرصفحه نمی‌دهد.",
        "importlogpage": "سیاههٔ درون‌ریزی‌ها",
-       "importlogpagetext": "درون‌ریزی صفحه‌ها به همراه تاریخچهٔ ویرایش آن‌ها از ویکی‌های دیگر.",
+       "importlogpagetext": "درون‌ریزی صفحات به همراه تاریخچهٔ ویرایش آن‌ها از ویکی‌های دیگر.",
        "import-logentry-upload": "[[$1]] را از طریق بارگذاری پرونده درون‌ریزی کرد",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|نسخه|نسخه}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|نسخه|نسخه}} واردشده",
        "import-logentry-interwiki": "$1 را تراویکی کرد",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|نسخه|نسخه}} از $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|نسخه|نسخه}} واردشده از $2",
        "javascripttest": "آزمایش جاوا اسکریپت",
        "javascripttest-title": "در حال اجرای آزمایش‌های $1",
        "javascripttest-pagetext-noframework": "این صفحه برای اجرای آزمایش‌های جاوا اسکریپت کنار گذاشته شده‌است.",
        "tooltip-ca-unwatch": "حذف این صفحه از فهرست پی‌گیری‌هایتان",
        "tooltip-search": "جستجو در {{SITENAME}}",
        "tooltip-search-go": "در صورت امکان به صفحه‌ای با همین نام برو",
-       "tooltip-search-fulltext": "جستجوی این عبارت در صفحه‌ها",
+       "tooltip-search-fulltext": "جستجوی این عبارت در صفحات",
        "tooltip-p-logo": "مشاهدهٔ صفحهٔ اصلی",
        "tooltip-n-mainpage": "مشاهدهٔ صفحهٔ اصلی",
        "tooltip-n-mainpage-description": "مشاهدهٔ صفحهٔ اصلی",
        "creditspage": "اعتبارات این صفحه",
        "nocredits": "اطلاعات سازندگان این صفحه موجود نیست.",
        "spamprotectiontitle": "پالایهٔ هرزنگاری‌ها",
-       "spamprotectiontext": "از Ø°Ø®Û\8cرÙ\87 Ú©Ø±Ø¯Ù\86 ØµÙ\81Ø­Ù\87 ØªÙ\88سط Ù¾Ø§Ù\84اÛ\8cÙ\87Ù\94 Ù\87رزÙ\86گارÛ\8câ\80\8cÙ\87ا Ø¬Ù\84Ù\88Ú¯Û\8cرÛ\8c Ø´Ø¯.\nÙ\85عÙ\85Ù\88Ù\84اÙ\8b Ø§Û\8cÙ\86 Ø§ØªÙ\81اÙ\82 Ø²Ù\85اÙ\86Û\8c Ù\85Û\8câ\80\8cاÙ\81تد Ú©Ù\87 Ù\85تÙ\86 Ø¬Ø¯Û\8cد صفحه، حاوی پیوندی به یک نشانی وب باشد که در فهرست سیاه قرار دارد.",
+       "spamprotectiontext": "از Ø°Ø®Û\8cرÙ\87 Ú©Ø±Ø¯Ù\86 ØµÙ\81Ø­Ù\87 ØªÙ\88سط Ù¾Ø§Ù\84اÛ\8cÙ\87Ù\94 Ù\87رزÙ\86گارÛ\8câ\80\8cÙ\87ا Ø¬Ù\84Ù\88Ú¯Û\8cرÛ\8c Ø´Ø¯.\nÙ\85عÙ\85Ù\88Ù\84اÙ\8b Ø§Û\8cÙ\86 Ø§ØªÙ\81اÙ\82 Ø²Ù\85اÙ\86Û\8c Ù\85Û\8câ\80\8cاÙ\81تد Ú©Ù\87 Ù\85تÙ\86 ØªØ§Ø²Ù\87 صفحه، حاوی پیوندی به یک نشانی وب باشد که در فهرست سیاه قرار دارد.",
        "spamprotectionmatch": "متن زیر چیزی‌است که پالایهٔ هرزه‌نگاری ما را به کارانداخت: $1",
        "spambot_username": "هرزه‌تمیزکارِ مدیاویکی",
        "spam_reverting": "واگردانی به آخرین نسخه‌ای که پیوندی به $1 ندارد.",
        "pageinfo-magic-words": "{{PLURAL:$1|حرف|حروف}} جادویی ($1)",
        "pageinfo-hidden-categories": "{{PLURAL:$1| ردهٔ|ردهٔ}} پنهان ( $1 )",
        "pageinfo-templates": "{{PLURAL:$1|الگو|الگو}} استفاده‌شده ($1)",
-       "pageinfo-transclusions": "{{PLURAL:$1|صفحهٔ|صفحه‌های}} تراگنجایش‌شده در ($1)",
+       "pageinfo-transclusions": "{{PLURAL:$1|صفحهٔ|صفحه‌های}} تراگنجانش‌شده در ($1)",
        "pageinfo-toolboxlink": "اطلاعات صفحه",
        "pageinfo-redirectsto": "تغییرمسیر به",
        "pageinfo-redirectsto-info": "اطلاعات",
        "pageinfo-protect-cascading-yes": "بله",
        "pageinfo-protect-cascading-from": "محافظت آبشاری از",
        "pageinfo-category-info": "اطلاعات رده",
-       "pageinfo-category-pages": "تعداد صفحه‌ها",
+       "pageinfo-category-pages": "تعداد صفحات",
        "pageinfo-category-subcats": "تعداد زیررده‌ها",
        "pageinfo-category-files": "تعداد پرونده‌ها",
        "markaspatrolleddiff": "برچسب گشت بزن",
        "autosumm-blank": "صفحه را خالی کرد",
        "autosumm-replace": "جایگزینی صفحه با '$1'",
        "autoredircomment": "تغییرمسیر به [[$1]]",
-       "autosumm-new": "صفحه‌ای جدید حاوی «$1» ایجاد کرد",
+       "autosumm-new": "صفحه‌ای تازه حاوی «$1» ایجاد کرد",
+       "autosumm-newblank": "ایجاد صفحه خالی",
        "size-bytes": "$1 بایت",
        "size-kilobytes": "$1 کیلوبایت",
        "size-megabytes": "$1 مگابایت",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|بحث]])",
        "unknown_extension_tag": "برچسب ناشناختهٔ افزونه «$1»",
        "duplicate-defaultsort": "هشدار: ترتیب پیش‌فرض «$2» ترتیب پیش‌فرض قبلی «$1» را باطل می‌کند.",
+       "duplicate-displaytitle": "<strong>هشدار:</strong> نمایش عنوان \" $2 \"باعث ابطال پیش نمایش عنوان\" $1 \" می‌شود.",
        "version": "نسخه",
        "version-extensions": "افزونه‌های نصب‌شده",
        "version-skins": "پوسته‌های نصب شده",
        "specialpages-group-media": "گزارش بارگذاری رسانه‌ها",
        "specialpages-group-users": "کاربرها و دسترسی‌ها",
        "specialpages-group-highuse": "صفحه‌های پربازدید",
-       "specialpages-group-pages": "فهرست‌های صفحه‌ها",
-       "specialpages-group-pagetools": "ابزارهای صفحه‌ها",
+       "specialpages-group-pages": "فهرست‌های صفحات",
+       "specialpages-group-pagetools": "ابزارهای صفحات",
        "specialpages-group-wiki": "داده و ابزارها",
        "specialpages-group-redirects": "صفحه‌های ویژهٔ تغییرمسیر دهنده",
        "specialpages-group-spam": "ابزارهای هرزنگاری",
        "tags": "برچسب‌های تغییر مجاز",
        "tag-filter": "پالایش [[Special:Tags|برچسب‌ها]]:",
        "tag-filter-submit": "پالایه",
-       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|برچسب|برچسب}}]]: $2)",
+       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|برچسب|برچسب‌ها}}]]: $2)",
        "tags-title": "برچسب‌ها",
        "tags-intro": "این صفحه فهرستی‌است از برچسب‌هایی که نرم‌افزار با آن‌ها ویرایش‌ها را علامت‌گذری می‌کند، به همراه معانی آن‌ها.",
        "tags-tag": "نام برچسب",
        "tags-active-no": "خیر",
        "tags-edit": "ویرایش",
        "tags-hitcount": "$1 {{PLURAL:$1|تغییر|تغییر}}",
-       "comparepages": "مقایسهٔ صفحه‌ها",
+       "comparepages": "مقایسهٔ صفحات",
        "compare-page1": "صفحهٔ ۱",
        "compare-page2": "صفحهٔ ۲",
        "compare-rev1": "نسخهٔ ۱",
        "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 {{GENDER:$2|بارگذاری کرد}} $3",
        "rightsnone": "(هیچ)",
        "feedback-bugornote": "اگر آماده‌اید تا مشکلی فنی را با جزئیاتش شرح دهید لطفاً [$1 یک ایراد گزارش دهید]. در غیر این صورت می‌توانید از فرم سادهٔ زیر استفاده کنید. نظر شما به همراه نام کاربری و مرورگرتان به صفحهٔ «[$3 $2]» افزوده خواهد شد.",
        "feedback-subject": "موضوع:",
        "feedback-thanks": "سپاس! بازخورد شما در صفحهٔ «[$1 $2]» ثبت شد.",
        "feedback-close": "انجام شد",
        "feedback-bugcheck": "عالی‌است! فقط بررسی کنید که از [$1 ایرادهای شناخته‌شده] نباشد.",
-       "feedback-bugnew": "بررسÛ\8c Ú©Ø±Ø¯Ù\85. Ø§Û\8cرادÛ\8c Ø¬Ø¯Û\8cد را گزارش بده",
+       "feedback-bugnew": "بررسÛ\8c Ú©Ø±Ø¯Ù\85. Ø§Û\8cرادÛ\8c ØªØ§Ø²Ù\87 را گزارش بده",
        "searchsuggest-search": "جستجو",
        "searchsuggest-containing": "صفحه‌های دربردارنده...",
        "api-error-badaccess-groups": "شما اجازهٔ بارگذاری پرونده‌ها را در این ویکی ندارید.",
        "duration-millennia": "{{PLURAL:$1|هزار سال |$1 هزار سال}}",
        "rotate-comment": "تصویر به دست $1 {{PLURAL:$1|درجهٔ|درجهٔ}} ساعت‌گرد چرخانده شد",
        "limitreport-title": "داده‌های رخ‌نمانگاری تجزیه‌کننده:",
-       "limitreport-cputime": "زمان مصرف سی‌پی‌یو",
+       "limitreport-cputime": "زمان مصرفی سی‌پی‌یو",
        "limitreport-cputime-value": "$1 {{PLURAL:$1|ثانیه}}",
-       "limitreport-walltime": "استÙ\81ادÙ\87 Ø²Ù\85اÙ\86 واقعی",
+       "limitreport-walltime": "زÙ\85اÙ\86 Ù\85صرÙ\81Û\8c واقعی",
        "limitreport-walltime-value": "$1 {{PLURAL:$1|ثانیه|ثانیه}}",
-       "limitreport-ppvisitednodes": "شمارش گرهٔ پیش‌پردازنده مشاهده‌شده",
-       "limitreport-ppgeneratednodes": "شمارش گره پیش‌پردازنده تولیدشده",
-       "limitreport-postexpandincludesize": "شاÙ\85Ù\84 Ø§Ù\86دازÙ\87 Ù¾Ø³ گسترش",
+       "limitreport-ppvisitednodes": "شمارندهٔ گره بازدیدشدهٔ پیش‌پردازنده",
+       "limitreport-ppgeneratednodes": "شمارندهٔ گره تولیدی پیش‌پردازنده",
+       "limitreport-postexpandincludesize": "اÙ\86دازÙ\87Ù\94 Ø¯Ø±Ø¨Ø±Ú¯Û\8cرÙ\86دÙ\87 Ù¾Ø³ Ø§Ø² گسترش",
        "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|بایت|بایت}}",
-       "limitreport-templateargumentsize": "اÙ\86دازÙ\87 Ø¹Ù\85Ù\84گر الگو",
+       "limitreport-templateargumentsize": "اÙ\86دازÙ\87 Ø¢Ø±Ú¯Ù\88Ù\85اÙ\86 الگو",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|بایت|بایت}}",
        "limitreport-expansiondepth": "بیشترین عمق گسترش",
        "limitreport-expensivefunctioncount": "تعداد تابع تجزیه‌گر پرمصرف",
        "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 dir=\"ltr\"<$wgDefaultSkin</code> به‌عنوان <code>$1</code>، در دسترس نیست.\n\nبه نظر می‌آید نصب شما شامل پوسته‌های زیر می‌شود. [https://www.mediawiki.org/wiki/Manual:Skin_configuration راهنما: تنظیمات پوسته] را برای کسب اطلاعات در باره چگونگی فعال‌ساختن آن‌ها و انتخاب پیش‌فرض ببینید.\n\n$2\n\n; اگر اخیراً مدیاویکی را نصب کرده‌اید:\n: احتمالاً از گیت، یا به طور مستقیم از کد مبدأ که از چند متد دیگر استفاده می‌کند نصب کردید. انتظار می‌رود. چند پوسته از [https://www.mediawiki.org/wiki/Category:All_skins فهرست پوسته mediawiki.org] نصب کنید، که همراه چندین پوسته و افزونه هستند. شما می‌توانید شاخه <code>skins/</code> را از آن نسخه‌برداری کرده و بچسبانید.\n\n:* همسانه‌سازی یکی از مخازن <code>mediawiki/skins/*</code> از طریق گیت به داخل شاخه <code dir=\"ltr\">skins/</code> از نصب مدیاویکی‌تان.\n: انجام این کار با مخزن گیت‌تان تداخل نمی‌کند اگر توسعه‌دهنده مدیاویکی هستید.\n\n; اگر اخیراً مدیاویکی را ارتقاء دادید:\n: مدیاویکی ۱٫۲۴ و تازه‌تر دیگر به طور خودکار پوسته‌های نصب‌شده را فعال نمی‌کند ([https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery راهنما: کشف خودکار پوسته] را ببینید). شما می‌توانید خطوط زیر را به داخل <code>LocalSettings.php</code> بچسبانید تا همه پوسته‌های نصب‌شده جاری را فعال کنید:\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شما پوسته‌ها را نصب نکرده‌اید.\n\n:اگر مدیاویکی را به‌روز یا نصب کرده‌اید:\n:ممکن است از گیت یا از کند منبع با روش های دیگر نصب کرده‌اید. انتظار می‌رود MediaWiki 1.24 یا جدیدتر در پوشهٔ اصلی هیچ پوسته‌ای نداشته باشند.\nسعی کنید تعدادی پوسته از [https://www.mediawiki.org/wiki/Category:All_skins پوشهٔ پوسته‌های مدیاویکی]، با:\n:*دانلود کردن [https://www.mediawiki.org/wiki/Download نصب‌کننده تاربال]، که با چندین پوسته و افزونه هست. شما می توانید پوستهٔ <code>skins/</code> را  از آن کپی و پیست کنید.\n:*کلون کردن یکی از <code dir=\"ltr\">mediawiki/skins/*</code> از ریپوزیتوری در پوشهٔ <code>skins/</code> مدیاویکی‌تان.\n:اگر توسعه‌دهندهٔ مدیاویکی هستید، انجام این کار نباید تعارضی با ریپوزیتوری گیت شما داشته باشد. برای اطلاعات بیشتر و فعال کردن پوسته‌ها و انتخاب آنها به عنوان پیش‌فرض [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: تنظیمات پوسته] را مشاهده کنید.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (فعال)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''غیر فعال''')"
 }
index d554fe6..7ed7e1a 100644 (file)
@@ -39,7 +39,8 @@
                        "ZeiP",
                        "לערי ריינהארט",
                        "아라",
-                       "Syreeni"
+                       "Syreeni",
+                       "MrTapsa"
                ]
        },
        "tog-underline": "Linkkien alleviivaus:",
@@ -56,6 +57,7 @@
        "tog-watchdefault": "Lisää muokkaamani sivut ja tiedostot tarkkailulistalleni",
        "tog-watchmoves": "Lisää siirtämäni sivut ja tiedostot tarkkailulistalleni",
        "tog-watchdeletion": "Lisää poistamani sivut ja tiedostot tarkkailulistalleni",
+       "tog-watchrollback": "Lisää tarkkailulistalleni ne sivut, joissa olen käyttänyt palautus-toimintoa.",
        "tog-minordefault": "Merkitse kaikki muutokset oletusarvoisesti pieniksi",
        "tog-previewontop": "Näytä esikatselu muokkauskentän yläpuolella",
        "tog-previewonfirst": "Näytä esikatselu heti, kun muokkaus aloitetaan",
@@ -84,7 +86,7 @@
        "underline-never": "Ei koskaan",
        "underline-default": "Ulkoasun tai selaimen oletustapa",
        "editfont-style": "Muokkauskentän kirjasintyyppi",
-       "editfont-default": "Selaimen oletus",
+       "editfont-default": "Selaimen vakioasetus",
        "editfont-monospace": "Tasalevyinen kirjasin",
        "editfont-sansserif": "Sans-serif-kirjasin",
        "editfont-serif": "Serif-kirjasin",
        "talkpagelinktext": "keskustelu",
        "specialpage": "Toimintosivu",
        "personaltools": "Henkilökohtaiset työkalut",
-       "postcomment": "Uusi osio",
        "articlepage": "Näytä varsinainen sivu",
        "talk": "Keskustelu",
        "views": "Näkymät",
        "otherlanguages": "Muilla kielillä",
        "redirectedfrom": "Ohjattu sivulta $1",
        "redirectpagesub": "Ohjaussivu",
+       "redirectto": "Ohjaus sivulle:",
        "lastmodifiedat": "Sivua on viimeksi muutettu $1 kello $2.",
        "viewcount": "Tämä sivu on näytetty {{PLURAL:$1|yhden kerran|$1 kertaa}}.",
        "protectedpage": "Suojattu sivu",
        "hidetoc": "piilota",
        "collapsible-collapse": "Supista",
        "collapsible-expand": "Laajenna",
+       "confirmable-confirm": "Oletko varma?",
+       "confirmable-yes": "Kyllä",
+       "confirmable-no": "Ei",
        "thisisdeleted": "Näytä tai palauta $1?",
        "viewdeleted": "Näytä $1?",
        "restorelink": "{{PLURAL:$1|yksi poistettu muokkaus|$1 poistettua muokkausta}}",
        "invalidtitle-knownnamespace": "Virheellinen sivunimi, nimiavaruus \"$2\" ja teksti \"$3\"",
        "invalidtitle-unknownnamespace": "Virheellinen sivunimi, tuntematon nimiavaruus numero $1 ja teksti \"$2\"",
        "exception-nologin": "Et ole kirjautunut sisään",
-       "exception-nologin-text": "Ole hyvä ja [[Special:Userlogin|kirjaudu sisään]], niin pääset tälle sivulle tai tähän toimintoon.",
+       "exception-nologin-text": "Ole hyvä ja kirjaudu sisään, niin pääset tälle sivulle tai tähän toimintoon.",
        "exception-nologin-text-manual": "Sinun pitää $1 jotta pääset tälle sivulle tai toimintoon.",
        "virus-badscanner": "Virheellinen asetus: Tuntematon virustutka: ''$1''",
        "virus-scanfailed": "virustarkistus epäonnistui virhekoodilla $1",
        "externaldberror": "Tapahtui virhe ulkoisen autentikointitietokannan käytössä tai sinulla ei ole lupaa päivittää tunnustasi.",
        "login": "Kirjaudu sisään",
        "nav-login-createaccount": "Kirjaudu sisään tai luo tunnus",
-       "loginprompt": "Sinun täytyy sallia evästeet, jotta voit kirjautua sivustolle {{SITENAME}}.",
        "userlogin": "Kirjaudu sisään tai luo tunnus",
        "userloginnocreate": "Kirjaudu sisään",
        "logout": "Kirjaudu ulos",
        "userlogin-resetlink": "Unohditko salasanasi?",
        "userlogin-resetpassword-link": "Unohditko salasanasi?",
        "userlogin-helplink2": "Apua sisäänkirjautumiseen",
-       "userlogin-loggedin": "Olet jo kirjautunut sisään tunnuksella {{GENDER:$1|$1}}.\nKäytä alla olevaa lomaketta kirjautuaksesi sisään toisena käyttäjänä.",
-       "userlogin-createanother": "Luo toinen käyttäjätunnus",
        "createacct-emailrequired": "Sähköpostiosoite",
        "createacct-emailoptional": "Sähköpostiosoite (vapaaehtoinen)",
        "createacct-email-ph": "Anna sähköpostiosoitteesi",
        "createaccount-text": "Joku on luonut tunnuksen $2 {{GRAMMAR:illative|{{SITENAME}}}} ($4).\nTunnus on \"$2\" ja sen salasana on \"$3\". Sinun on syytä kirjautua sisään ja vaihtaa salasanasi heti.\n\nSinun ei tarvitse välittää tästä viestistä, jos tämä tunnus on luotu virheellisesti.",
        "login-throttled": "Olet tehnyt liian monta kirjautumisyritystä.\nOdota $1 ennen kuin yrität uudelleen.",
        "login-abort-generic": "Kirjautuminen epäonnistui – keskeytetty",
+       "login-migrated-generic": "Tunnuksesi on siirretty, ja käyttäjänimeäsi ei löydy enää tästä wikistä.",
        "loginlanguagelabel": "Kieli: $1",
        "suspicious-userlogout": "Pyyntösi kirjautua ulos evättiin, koska se näytti rikkinäisen selaimen tai välimuistipalvelimen lähettämältä.",
        "createacct-another-realname-tip": "Vapaaehtoinen.\nNimesi näytetään käyttäjätunnuksesi sijasta sivun tekijäluettelossa.",
        "preview": "Esikatselu",
        "showpreview": "Esikatsele",
        "showdiff": "Näytä muutokset",
-       "anoneditwarning": "'''Varoitus:''' Et ole kirjautunut sisään.\nIP-osoitteesi kirjataan tämän sivun muutoshistoriaan.",
+       "blankarticle": "<strong>Varoitus:</strong> Sivu, jota olet luomassa, on tyhjä.\nJos napsautat \"{{int:savearticle}}\" uudelleen, sivu luodaan ilman sisältöä.",
+       "anoneditwarning": "<strong>Varoitus:</strong> Et ole kirjautunut sisään. IP-osoitteesi näkyy julkisesti kaikille, jos muokkaat. Jos <strong>[$1 kirjaudut sisään]</strong> tai <strong>[$2 luot tunnuksen]</strong>, muokkauksesi kirjataan käyttäjätunnuksesi tekemiksi ja samalla saat käyttöösi hyödyllisiä välineitä.",
        "anonpreviewwarning": "''Et ole kirjautunut sisään. Tallentaminen kirjaa IP-osoitteesi tämän sivun muutoshistoriaan.''",
        "missingsummary": "Et ole antanut yhteenvetoa. Jos valitset Tallenna uudelleen, niin muokkauksesi tallennetaan ilman yhteenvetoa.",
        "missingcommenttext": "Kirjoita viesti alle.",
        "parser-template-recursion-depth-warning": "Mallineen rekursioraja ylittyi ($1)",
        "language-converter-depth-warning": "Kielimuuntimen syvyysraja ylittyi ($1)",
        "node-count-exceeded-category": "Sivut, joissa solmumäärä on ylitetty",
-       "node-count-exceeded-category-desc": "Luokka sivuille, joissa solmujen lukumäärä (node-count) on ylitetty.",
-       "node-count-exceeded-warning": "Sivu ylitti solmumäärän",
+       "node-count-exceeded-category-desc": "Tämä sivu ylittää suurimman sallitun solmujen lukumäärän (node count).",
+       "node-count-exceeded-warning": "Sivu ylitti solmumäärän (node count)",
        "expansion-depth-exceeded-category": "Sivut, joissa laajentamissyvyys on ylitetty",
-       "expansion-depth-exceeded-category-desc": "Tämä on luokka sivuille, joissa laajentamissyvyys (expansion depth) on ylitetty.",
+       "expansion-depth-exceeded-category-desc": "Tämä sivu ylittää suurimman sallitun laajentamissyvyyden (expansion depth).",
        "expansion-depth-exceeded-warning": "Sivu ylitti laajentamissyvyyden.",
        "parser-unstrip-loop-warning": "Unstrip-silmukka havaittiin",
        "parser-unstrip-recursion-limit": "Unstrip-rekursion enimmäissyvyys ($1) ylitettiin",
        "rev-deleted-event": "(lokitapahtuma poistettu)",
        "rev-deleted-user-contribs": "[käyttäjätunnus tai IP-osoite poistettu – muokkaus on piilotettu muokkausluettelosta]",
        "rev-deleted-text-permission": "Tämä versio sivusta on '''poistettu'''.\nLisätietoja löytyy [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} poistolokista].",
+       "rev-suppressed-text-permission": "Tämä versio sivusta on <strong>häivytetty</strong>.\nLisätietoja löytyy [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}}  häivytyslokista].",
        "rev-deleted-text-unhide": "Tämä versio sivusta on '''poistettu'''.\nLisätietoja löytyy [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} poistolokista].\nVoit silti [$1 nähdä tämän muutoksen], jos haluat jatkaa.",
        "rev-suppressed-text-unhide": "Tämä versio sivusta on '''häivytetty'''.\nLisätietoja löytyy [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} häivytyslokista].\nVoit silti [$1 nähdä tämän muutoksen], jos haluat jatkaa.",
        "rev-deleted-text-view": "Tämä versio sivusta on '''poistettu'''.\nVoit silti nähdä sen. Lisätietoja löytyy [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} poistolokista].",
        "revdelete-text-text": "Poistetut versiot näkyvät edelleen sivun historiassa, mutta osa niiden sisällöstä ei enää ole saatavilla julkisesti.",
        "revdelete-text-file": "Poistetut tiedostoversiot näkyvät yhä sivun historiassa, mutta osa niiden sisällöstä ei ole saatavilla julkisesti.",
        "logdelete-text": "Poistetut lokimerkinnät näkyvät edelleen lokeissa, mutta osa niiden sisällöstä ei enää ole saatavilla julkisesti.",
-       "revdelete-text-others": "Muut ylläpitäjät sivustolla {{SITENAME}} kykenevät silti näkemään piilotetun sisällön ja voivat palauttaa sen takaisin näkyviin tämän saman käyttöliittymän kautta, paitsi silloin kun lisärajoituksia on asetettu.",
+       "revdelete-text-others": "Muut ylläpitäjät kykenevät silti näkemään piilotetun sisällön ja voivat palauttaa sen takaisin näkyviin, paitsi silloin kun lisärajoituksia on asetettu.",
        "revdelete-confirm": "Varmista, että haluat tehdä tämän – ymmärrät seuraukset ja teet tämän [[{{MediaWiki:Policy-url}}|käytäntöjen]] mukaisesti.",
        "revdelete-suppress-text": "Häivytystä pitäisi käyttää '''vain''' seuraavissa tapauksissa:\n* Mahdollisesti henkilön kunniaa loukkaavia tietoja\n* Sopimattomat henkilötiedot\n*: ''kotiosoitteet, puhelinnumerot, henkilötunnukset ja muut.''",
        "revdelete-legend": "Aseta version näkyvyyden rajoitukset",
        "suppressionlog": "Häivytysloki",
        "suppressionlogtext": "Alla on luettelo poistoista ja muokkausestoista, jotka sisältävät ylläpitäjiltä piilotettua materiaalia.\n[[Special:BlockList|Estolistassa]] on lueteltu voimassa olevat muokkauskiellot ja muokkausestot.",
        "mergehistory": "Yhdistä sivujen muutoshistoriat",
-       "mergehistory-header": "Tämä sivu mahdollistaa sivun muutoshistorian yhdistämisen uudemman sivun muutoshistoriaan.\nUuden ja vanhan sivun muutoksien pitää muodostaa jatkumo – ne eivät saa mennä ristikkäin.",
-       "mergehistory-box": "Yhdistä kahden sivun muutoshistoria",
-       "mergehistory-from": "Lähdesivu",
-       "mergehistory-into": "Kohdesivu",
+       "mergehistory-header": "Tällä sivulla voit yhdistää lähdesivun sivuhistorian versioita uudemman sivun historiaan.\nVarmista, että sivujen yhtenäinen muokkaushistoria säilyy eikä mene ristikkäin sekaisin!",
+       "mergehistory-box": "Yhdistä kahden sivun versioita:",
+       "mergehistory-from": "Lähdesivu:",
+       "mergehistory-into": "Kohdesivu:",
        "mergehistory-list": "Sivuhistoria, joka voidaan yhdistää",
-       "mergehistory-merge": "Seuraavat sivun [[:$1]] muutokset voidaan liittää sivun [[:$2]] muutoshistoriaan. Voit valita version, jota myöhempiä muutoksia ei liitetä. Selainlinkkien käyttäminen kadottaa tämän valinnan.",
-       "mergehistory-go": "Etsi muutokset",
+       "mergehistory-merge": "Seuraavat versiot sivusta [[:$1]] voidaan yhdistää sivuun [[:$2]]. \n\nValintamerkin sijoituksella voit yhdistää vain ne versiot, jotka on luotu valittuna ajankohtana tai sitä ennen (listassa alaspäin). \nOta huomioon, että jos käytät navigaatiolinkkejä, tekemäsi valinta poistuu.",
+       "mergehistory-go": "Etsi muokkaukset, jotka voidaan yhdistää",
        "mergehistory-submit": "Yhdistä versiot",
-       "mergehistory-empty": "Ei liitettäviä muutoksia.",
-       "mergehistory-success": "{{PLURAL:$3|Yksi versio|$3 versiota}} sivusta [[:$1]] liitettiin sivuun [[:$2]].",
-       "mergehistory-fail": "Muutoshistorian liittäminen epäonnistui. Tarkista määritellyt sivut ja versiot.",
+       "mergehistory-empty": "Mitään versioita ei voida yhdistää.",
+       "mergehistory-success": "$3 {{PLURAL:$3|versio|versiota}} sivusta [[:$1]] yhdistettiin onnistuneesti sivuun [[:$2]].",
+       "mergehistory-fail": "Sivuhistorioiden yhdistämistä ei voida suorittaa. Tarkista lähde- ja kohdesivujen nimet sekä versioiden aikamääritys.",
        "mergehistory-fail-toobig": "Sivuhistorian yhdistämistä ei voi tehdä, koska enemmän kuin sallittu määrä $1 {{PLURAL:$1|versio|versiota}} siirrettäisiin.",
        "mergehistory-no-source": "Lähdesivua $1 ei ole olemassa.",
        "mergehistory-no-destination": "Kohdesivua $1 ei ole olemassa.",
-       "mergehistory-invalid-source": "Lähdesivulla pitää olla kelvollinen nimi.",
-       "mergehistory-invalid-destination": "Kohdesivulla pitää olla kelvollinen nimi.",
-       "mergehistory-autocomment": "Yhdisti sivun [[:$1]] sivuun [[:$2]]",
+       "mergehistory-invalid-source": "Lähdesivun nimen pitää olla kelvollinen.",
+       "mergehistory-invalid-destination": "Kohdesivun nimen pitää olla kelvollinen.",
+       "mergehistory-autocomment": "Ak: Yhdisti sivun [[:$1]] sivuun [[:$2]]",
        "mergehistory-comment": "Yhdisti sivun [[:$1]] sivuun [[:$2]]: $3",
        "mergehistory-same-destination": "Lähde- ja kohdesivut eivät voi olla samat",
        "mergehistory-reason": "Syy:",
        "mergelog": "Yhdistämisloki",
-       "pagemerge-logentry": "liitti sivun [[$1]] sivuun [[$2]] (muokkaukseen $3 asti)",
-       "revertmerge": "Kumoa yhdistäminen",
+       "pagemerge-logentry": "yhdisti kohteen [[$1]] kohteeseen [[$2]] (versiot $3 saakka)",
+       "revertmerge": "Peru yhdistäminen",
        "mergelogpagetext": "Alla on loki viimeisimmistä muutoshistorioiden yhdistämisistä.",
        "history-title": "Sivun ”$1” muutoshistoria",
        "difference-title": "Ero sivun ”$1” versioiden välillä",
        "compareselectedversions": "Vertaile valittuja versioita",
        "showhideselectedversions": "Näytä tai piilota valitut versiot",
        "editundo": "kumoa",
-       "diff-empty": "(ei eroavaisuuksia)",
+       "diff-empty": "(ei mitään eroa)",
        "diff-multi-sameuser": "({{PLURAL:$1|Yhtä välissä olevaa versiota|$1 välissä olevaa versiota}} samalta käyttäjältä ei näytetä)",
        "diff-multi-otherusers": "({{PLURAL:$1|Yhtä välissä olevaa versiota|$1 välissä olevaa versiota}} {{PLURAL:$2|toisen käyttäjän tekemänä|$2 käyttäjän tekeminä}} ei näytetä)",
        "diff-multi-manyusers": "(Versioiden välissä on {{PLURAL:$1|yksi muu muokkaus|$1 muuta muokkausta, jotka on tehnyt {{PLURAL:$2|yksi käyttäjä|yli $2 eri käyttäjää}}}}.)",
        "searchprofile-advanced-tooltip": "Etsi määritellyistä nimiavaruuksista",
        "search-result-size": "$1 ({{PLURAL:$2|1 sana|$2 sanaa}})",
        "search-result-category-size": "{{PLURAL:$1|1 jäsen|$1 jäsentä}} ({{PLURAL:$2|1 alaluokka|$2 alaluokkaa}}, {{PLURAL:$3|1 tiedosto|$3 tiedostoa}})",
-       "search-result-score": "Asiaankuuluvuus: $1%",
        "search-redirect": "(ohjaus $1)",
        "search-section": "(osio $1)",
        "search-file-match": "(vastaa tiedoston sisältöä)",
        "searchall": "kaikki",
        "showingresults": "Alla on vain {{PLURAL:$1|<strong>1</strong> hakutulos|<strong>$1</strong> hakutulosta}} alkaen tuloksesta nro <strong>$2</strong>.",
        "showingresultsinrange": "Alla näytetään {{PLURAL:$1|<strong>1</strong> tulos|<strong>$1</strong> tulosta}} väliltä <strong>$2</strong> – <strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Tulokset '''$1'''–'''$3'''|Tulokset '''$1'''–'''$2''' kaikkiaan '''$3''' osuman joukosta}} haulle '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Tulos <strong>$1</strong> enimmäismäärästä <strong>$3</strong>|Tulokset <strong>$1 - $2</strong> enimmäismäärästä <strong>$3</strong>}}",
        "search-nonefound": "Hakusi ei tuottanut tulosta.",
        "powersearch-legend": "Laajennettu haku",
        "powersearch-ns": "Hae nimiavaruuksista:",
        "preferences": "Asetukset",
        "mypreferences": "Asetukset",
        "prefs-edits": "Muokkauksia",
-       "prefsnologintext2": "Sinun pitää $1 ennen kuin voit muuttaa käyttäjän asetuksia.",
+       "prefsnologintext2": "Sinun pitää kirjautua sisään ennen kuin voit muuttaa omia asetuksiasi.",
        "prefs-skin": "Ulkoasu",
        "skin-preview": "esikatselu",
        "datedefault": "Ei omaa määrittelyä",
        "group-bot": "botit",
        "group-sysop": "ylläpitäjät",
        "group-bureaucrat": "byrokraatit",
-       "group-suppress": "häivytysoikeuden käyttäjät",
+       "group-suppress": "häivyttäjät",
        "group-all": "(kaikki)",
        "group-user-member": "{{GENDER:$1|käyttäjä}}",
        "group-autoconfirmed-member": "{{GENDER:$1|automaattisesti hyväksytty käyttäjä}}",
        "group-bot-member": "{{GENDER:$1|botti}}",
        "group-sysop-member": "{{GENDER:$1|ylläpitäjä}}",
        "group-bureaucrat-member": "{{GENDER:$1|byrokraatti}}",
-       "group-suppress-member": "{{GENDER:$1|häivytysoikeuden käyttäjä}}",
+       "group-suppress-member": "{{GENDER:$1|häivyttäjä}}",
        "grouppage-user": "{{ns:project}}:Käyttäjät",
        "grouppage-autoconfirmed": "{{ns:project}}:Automaattisesti hyväksytyt käyttäjät",
        "grouppage-bot": "{{ns:project}}:Botit",
        "right-deletedtext": "Tarkastella poistettujen sivujen tekstiä ja muutoksia poistettujen versioiden välillä",
        "right-browsearchive": "Hakea poistettuja sivuja",
        "right-undelete": "Palauttaa poistettuja sivuja",
-       "right-suppressrevision": "Tarkastella ja palauttaa ylläpitäjiltä piilotettuja versioita",
+       "right-suppressrevision": "Katsoa, piilottaa ja tuoda näkyviin tiettyjä sivujen versioita kaikilta käyttäjiltä",
+       "right-viewsuppressed": "Katsoa versioita, jotka on piilotettu jokaiselta käyttäjältä",
        "right-suppressionlog": "Tarkastella yksityisiä lokeja",
        "right-block": "Asettaa toiselle käyttäjälle muokkausesto",
        "right-blockemail": "Estää käyttäjää lähettämästä sähköpostia",
        "recentchanges-legend-heading": "'''Selitys:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (katso myös [[Special:NewPages|lista uusista sivuista]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Alla ovat muutokset <strong>$2</strong> lähtien. (Enintään <strong>$1</strong> näytetään.)",
+       "rcnotefrom": "Alla ovat muutokset <strong>$3, $4</strong> lähtien. (Enintään <strong>$1</strong> näytetään.)",
        "rclistfrom": "Näytä uudet muutokset $3 $2 alkaen",
        "rcshowhideminor": "$1 pienet muutokset",
        "rcshowhideminor-show": "Näytä",
        "recentchangeslinked-feed": "Linkitettyjen sivujen muutokset",
        "recentchangeslinked-toolbox": "Linkitettyjen sivujen muutokset",
        "recentchangeslinked-title": "Sivulta $1 linkitettyjen sivujen muutokset",
-       "recentchangeslinked-summary": "Tämä toimintosivu näyttää muutokset sivuihin, joihin on viitattu tältä sivulta. [[Special:Watchlist|Tarkkailulistallasi]] olevat sivut on '''lihavoitu'''.",
-       "recentchangeslinked-page": "Sivu",
-       "recentchangeslinked-to": "Näytä muutokset sivuihin, joilla on linkki annettuun sivuun",
+       "recentchangeslinked-summary": "Tämä on luettelo muutoksista, jotka on viimeksi tehty niihin sivuihin, joihin johtaa linkki tietystä sivusta (tai jonkun määrätyn luokan sisältämistä sivuista). Omalla [[Special:Watchlist|tarkkailulistallasi]] olevat sivut on <strong>lihavoitu</strong>.",
+       "recentchangeslinked-page": "Sivun nimi:",
+       "recentchangeslinked-to": "Näytä sen sijaan muutokset sivuihin, joista on linkki tähän sivuun",
        "upload": "Tallenna tiedosto",
        "uploadbtn": "Tallenna tiedosto",
        "reuploaddesc": "Peruuta tallennus ja palaa tallennuslomakkeelle.",
        "uploadwarning": "Tallennusvaroitus",
        "uploadwarning-text": "Muuta alla olevaa tiedostokuvausta ja yritä uudelleen.",
        "savefile": "Tallenna",
-       "uploadedimage": "tallensi tiedoston [[$1]]",
-       "overwroteimage": "tallensi uuden version [[$1]]",
        "uploaddisabled": "Tiedostojen tallennus ei ole käytössä.",
        "copyuploaddisabled": "Tallennus URL:n kautta on poistettu käytöstä.",
        "uploaddisabledtext": "Tiedostojen tallennus on poistettu käytöstä.",
        "license": "Lisenssi",
        "license-header": "Lisenssi",
        "nolicense": "Ei lisenssiä",
+       "licenses-edit": "Muokkaa lisenssivaihtoehtoja",
        "license-nopreview": "(esikatselua ei saatavilla)",
-       "upload_source_url": " (julkinen verkko-osoite)",
-       "upload_source_file": " (tiedosto tietokoneella)",
+       "upload_source_url": "(valitsemasi tiedosto kelvollisesta ja julkisesta verkko-osoitteesta)",
+       "upload_source_file": "(valitsemasi tiedosto omasta tietokoneestasi)",
+       "listfiles-delete": "poista",
        "listfiles-summary": "Tämä toimintosivu näyttää kaikki tallennetut tiedostot.",
-       "listfiles_search_for": "Nimihaku",
+       "listfiles_search_for": "Etsi tiedoston nimellä:",
        "imgfile": "tiedosto",
        "listfiles": "Tiedostoluettelo",
        "listfiles_thumb": "Pienoiskuva",
        "filerevert-success": "'''[[Media:$1|$1]]''' on palautettu takaisin [$4 versioon, joka luotiin $2 kello $3].",
        "filerevert-badversion": "Tiedostosta ei ole luotu versiota kyseisellä ajan hetkellä.",
        "filedelete": "Poistetaan tiedosto $1",
-       "filedelete-legend": "Tiedoston poisto",
-       "filedelete-intro": "Olet poistamassa tiedoston '''[[Media:$1|$1]]''' ja kaiken sen historian.",
+       "filedelete-legend": "Poista tiedosto",
+       "filedelete-intro": "Olet poistamassa tiedoston '''[[Media:$1|$1]]''' ja lisäksi koko sen muokkaushistorian.",
        "filedelete-intro-old": "<span class=\"plainlinks\">Olet poistamassa tiedoston '''[[Media:$1|$1]]''' [$4 päivämäärällä $2 kello $3 luotua versiota].</span>",
        "filedelete-comment": "Syy:",
        "filedelete-submit": "Poista",
        "randomincategory": "Satunnainen sivu luokasta",
        "randomincategory-invalidcategory": "$1 ei ole kelvollinen luokan nimi.",
        "randomincategory-nopages": "Luokassa [[:Category:$1|$1]] ei ole sivuja.",
-       "randomincategory-selectcategory": "Hae satunnainen sivu luokasta: $1 $2",
-       "randomincategory-selectcategory-submit": "Hae",
+       "randomincategory-category": "Luokka:",
+       "randomincategory-legend": "Satunnainen sivu luokassa",
        "randomredirect": "Satunnainen ohjaus",
        "randomredirect-nopages": "Nimiavaruudessa ”$1” ei ole ohjaussivuja.",
        "statistics": "Tilastot",
        "wantedpages-badtitle": "Virheellinen otsikko tuloksissa: $1",
        "wantedfiles": "Halutut tiedostot",
        "wantedfiletext-cat": "Seuraavia tiedostoja käytetään, mutta niitä ei ole olemassa. Ulkopuolissa mediavarastoissa olevat tiedostot voivat näkyä tällä listalla, vaikka ne ovat olemassa. Tällaiset väärät merkinnät on <del>yliviivattu</del>. Lisäksi sellaiset sivut, joihin on sisällytetty tiedostoja, jotka eivät ole olemassa, on luetteloitu [[:$1|täällä]].",
+       "wantedfiletext-cat-noforeign": "Seuraavat tiedostot ovat käytössä vaikka niitä ei ole olemassa. Luettelo sellaisista sivuista, joihin on upotettu olemattomia tiedostoja, on [[:$1]].",
        "wantedfiletext-nocat": "Seuraavia tiedostoja käytetään, mutta niitä ei ole olemassa. Ulkopuolissa mediavarastoissa olevat tiedostot voivat näkyä tällä listalla, vaikka ne ovat olemassa. Tällaiset väärät merkinnät on <del>yliviivattu</del.>",
+       "wantedfiletext-nocat-noforeign": "Seuraavia tiedostoja käytetään vaikka niitä ei ole olemassa.",
        "wantedtemplates": "Halutut mallineet",
        "mostlinked": "Viitatuimmat sivut",
        "mostlinkedcategories": "Viitatuimmat luokat",
        "protectedtitles": "Suojatut sivunimet",
        "protectedtitles-summary": "Tällä sivulla on lueteltu ne sivut, jotka on tällä hetkellä suojattu uudelleenluonnilta. Nähdäksesi luettelon olemassaolevista suojatuista sivuista katso [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
        "protectedtitlesempty": "Ei suojattuja sivunimiä näillä hakuehdoilla.",
-       "listusers": "Käyttäjälista",
+       "listusers": "Käyttäjien luettelo",
        "listusers-editsonly": "Näytä vain käyttäjät, joilla on muokkauksia",
        "listusers-creationsort": "Lajittele tunnuksen luontipäivämäärän mukaan",
        "listusers-desc": "Lajittele alenevassa järjestyksessä",
        "unusedimagestext": "Seuraavat tiedostot ovat olemassa, mutta niitä ei käytetä millään sivulla.\nHuomaa, että muut verkkosivut saattavat viitata tiedostoon suoran URL:n avulla, jolloin tiedosto saattaa olla tässä listassa, vaikka sitä käytetäänkin.",
        "unusedcategoriestext": "Nämä luokat ovat olemassa, mutta niitä ei käytetä.",
        "notargettitle": "Ei kohdetta",
-       "notargettext": "Et ole määritellyt kohdesivua tai -käyttäjää johon toiminto kohdistuu.",
+       "notargettext": "Et ole määritellyt kohteeksi sivua tai käyttäjää, johon toiminto suoritetaan.",
        "nopagetitle": "Kohdesivua ei ole olemassa.",
        "nopagetext": "Määritettyä kohdesivua ei ole olemassa.",
        "pager-newer-n": "← {{PLURAL:$1|1 uudempi|$1 uudempaa}}",
        "trackingcategories-desc": "Kriteerit luokkaan joutumiselle",
        "noindex-category-desc": "Tätä sivua eivät hakurobotit indeksoi, koska sivulla on taikasana <code><nowiki>__NOINDEX__</nowiki></code> ja koska sivu on sellaisessa nimiavaruudessa, jossa taikasanan käyttö on sallittua.",
        "index-category-desc": "Tällä sivulla on koodi <code><nowiki>__INDEX__</nowiki></code> ja sivu on sellaisessa nimiavaruudessa, jossa koodin käyttö on sallittua. Tämän vuoksi hakurobotit indeksoivat tämän sivun, vaikka ilman koodia sivua ei indeksoitaisi normaalisti.",
-       "post-expand-template-inclusion-category-desc": "Jos kaikki mallineet laajennetaan, sivun koko on suurempi kuin <code>$wgMaxArticleSize</code>. Tämän vuoksi kaikkia mallineita ei laajennettu.",
-       "post-expand-template-argument-category-desc": "Kun mallineen argumentti on laajennettu (argumentti on merkkijono kolmen kaarisulun sisällä kuten <code>{{{Foo}}}</code>), sivu on suurempi kuin <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Liian monta resursseja vaativaa jäsenninfunktiota (esimerkiksi <code>#ifexist</code>) on sisällytetty sivulle. Katso [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Tämä luokka sisältää ne sivut, joissa on rikkinäinen tiedostolinkki. Tällä tarkoitetaan linkkiä sellaiseen tiedostoon, jota ei olemassa.",
-       "hidden-category-category-desc": "Tämä on luokka, joka sisältää koodin <code><nowiki>__HIDDENCAT__</nowiki></code>. Koodi estää luokan näkymisen sivujen alareunassa olevassa luokkien laatikossa oletusarvoisesti.",
+       "post-expand-template-inclusion-category-desc": "Sivun koko on suurempi kuin <code>$wgMaxArticleSize</code>, kun kaikki mallineet on laajennettu. Tämän vuoksi joitakin mallineita ei laajennettu.",
+       "post-expand-template-argument-category-desc": "Sivu on suurempi kuin <code>$wgMaxArticleSize</code>, kun mallineen argumentti on laajennettu (argumentti on merkkijono kolmen aaltosulun sisällä kuten <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "Tämä sivu käyttää liian monta resursseja vaativaa jäsenninfunktiota (kuten <code>#ifexist</code>). Katso [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "Tämä sivu sisältää rikkinäisen tiedostolinkin. Tällä tarkoitetaan linkkiä sellaiseen tiedostoon, jota ei olemassa.",
+       "hidden-category-category-desc": "Tämä luokka sisältää koodin <code><nowiki>__HIDDENCAT__</nowiki></code> sen tekstisisällössä. Koodi estää luokan näkymisen sivujen alareunassa olevassa luokkien laatikossa kuten yleensä.",
        "trackingcategories-nodesc": "Ei kuvausta olemassa.",
        "trackingcategories-disabled": "Luokka on poistettu käytöstä",
        "mailnologin": "Lähettäjän osoite puuttuu",
        "mywatchlist": "Tarkkailulista",
        "watchlistfor2": "Käyttäjälle $1 $2",
        "nowatchlist": "Tarkkailulistallasi ei ole sivuja.",
-       "watchlistanontext": "Sinun täytyy $1, jos haluat käyttää tarkkailulistaa.",
+       "watchlistanontext": "Sinun täytyy kirjautua sisään, jos haluat nähdä oman tarkkailulistasi.",
        "watchnologin": "Et ole kirjautunut sisään",
        "addwatch": "Lisää tarkkailulistalle",
        "addedwatchtext": "Sivu '''[[:$1]]''' on lisätty [[Special:Watchlist|tarkkailulistallesi]].\nTulevaisuudessa sivuun ja sen keskustelusivuun tehtävät muutokset listataan täällä.",
        "watchlist-details": "Tarkkailulistallasi on {{PLURAL:$1|$1 sivu|$1 sivua}}. Keskustelusivuja ei lasketa mukaan.",
        "wlheader-enotif": "Sähköposti-ilmoitus on käytössä.",
        "wlheader-showupdated": "Sivut, joita on muokattu viimeisen käyntisi jälkeen, on '''lihavoitu'''.",
-       "wlnote2": "Alla on muutokset viimeisen {{PLURAL:$1|tunnin|<strong>$1</strong> tunnin}} ajalta $2 kello $3 asti.",
-       "wlshowlast": "Näytä viimeiset $1 tuntia tai $2 päivää, $3",
+       "wlnote": "Alla {{PLURAL:$1|on viimeisin muutos|ovat viimeisimmät <strong>$1</strong> muutosta}} edellisen {{PLURAL:$2|tunnin|<strong>$2</strong> tunnin}} ajalta $3 kello $4 lukien.",
+       "wlshowlast": "Näytä edelliset $1 tuntia tai $2 päivää tai $3",
        "watchlist-options": "Tarkkailulistan asetukset",
        "watching": "Lisätään tarkkailulistalle...",
        "unwatching": "Poistetaan tarkkailulistalta...",
        "exbeforeblank": "ennen tyhjentämistä sisälsi: ”$1”",
        "delete-confirm": "Poista ”$1”",
        "delete-legend": "Sivun poisto",
-       "historywarning": "'''Varoitus:''' Sivua, jota olet poistamassa, on muokattu noin $1 {{PLURAL:$1|kerta|kertaa}}:",
+       "historywarning": "<strong>Varoitus:</strong> Sivulla, jota olet poistamassa, on muokkaushistoriaa ja sitä on muokattu $1 {{PLURAL:$1|kerran|kertaa}}:",
        "confirmdeletetext": "Olet poistamassa sivun tai tiedoston ja kaiken sen historian. Ymmärrä teon seuraukset ja tee poisto {{GRAMMAR:genitive|{{SITENAME}}}} [[{{MediaWiki:Policy-url}}|käytäntöjen]] mukaisesti.",
        "actioncomplete": "Toiminto suoritettu",
        "actionfailed": "Toiminto epäonnistui",
        "dellogpagetext": "Alla on loki viimeisimmistä poistoista.",
        "deletionlog": "poistoloki",
        "reverted": "Palautettu aikaisempaan versioon",
-       "deletecomment": "Syy",
+       "deletecomment": "Syy:",
        "deleteotherreason": "Muu syy tai tarkennus",
        "deletereasonotherlist": "Muu syy",
        "deletereason-dropdown": "* Yleiset poistosyyt\n** Spam tai mainossivu\n** Vandalismi\n** Tekijänoikeusrikkomus\n** Sivun tekijän pyyntö\n** Virheellinen ohjaus",
        "delete-edit-reasonlist": "Muokkaa poistosyitä",
        "delete-toobig": "Tällä sivulla on pitkä muutoshistoria – yli $1 {{PLURAL:$1|versio|versiota}}. Näin suurien muutoshistorioiden poistamista on rajoitettu suorituskykysyistä.",
        "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.",
        "rollback": "palauta aiempaan versioon",
        "rollback_short": "Palautus",
        "protectlogpage": "Suojausloki",
        "protectlogtext": "Alla on loki muutoksista sivujen suojauksiin. Luettelo tällä hetkellä suojatuista sivuista löytyy [[Special:ProtectedPages|suojattujen sivujen luettelosta]].",
        "protectedarticle": "suojasi sivun [[$1]]",
-       "modifiedarticleprotection": "muutti sivun [[$1]] suojaustasoa",
+       "modifiedarticleprotection": "muutti sivun [[$1]] suojausasetuksia",
        "unprotectedarticle": "poisti suojauksen sivulta [[$1]]",
        "movedarticleprotection": "siirsi suojausasetukset sivulta [[$2]] sivulle [[$1]]",
        "protect-title": "Muuta suojausta sivulla ”$1”",
-       "protect-title-notallowed": "Sivun $1 suojaustaso",
+       "protect-title-notallowed": "Katsele kohteen $1 suojauksen tasoa",
        "prot_1movedto2": "siirsi sivun [[$1]] uudelle nimelle [[$2]]",
        "protect-badnamespace-title": "Nimiavaruus ei suojattavissa",
        "protect-badnamespace-text": "Tämän nimiavaruuden sivuja ei voi suojata.",
        "sp-contributions-blocked-notice": "Tämä käyttäjä on tällä hetkellä estetty. Alla on viimeisin estolokin tapahtuma:",
        "sp-contributions-blocked-notice-anon": "Tämä IP-osoite on tällä hetkellä estetty.\nAlla on viimeisin estolokin tapahtuma:",
        "sp-contributions-search": "Etsi muokkauksia",
-       "sp-contributions-username": "IP-osoite tai käyttäjätunnus",
+       "sp-contributions-username": "IP-osoite tai käyttäjätunnus:",
        "sp-contributions-toponly": "Näytä vain muokkaukset, jotka ovat viimeisimpiä versioita",
        "sp-contributions-newonly": "Näytä vain muokkaukset, joilla on luotu sivu",
        "sp-contributions-submit": "Hae",
        "whatlinkshere": "Tänne viittaavat sivut",
        "whatlinkshere-title": "Sivut, jotka viittaavat sivulle $1",
-       "whatlinkshere-page": "Sivu",
+       "whatlinkshere-page": "Sivu:",
        "linkshere": "Seuraavilta sivuilta on linkki sivulle <strong>[[:$1]]</strong>:",
        "nolinkshere": "Sivulle <strong>[[:$1]]</strong> ei ole linkkejä.",
        "nolinkshere-ns": "Sivulle <strong>[[:$1]]</strong> ei ole linkkejä valitussa nimiavaruudessa.",
        "autoblockid": "Automaattinen esto #$1",
        "block": "Estä käyttäjä",
        "unblock": "Poista käyttäjän esto",
-       "blockip": "Estä käyttäjä",
+       "blockip": "Estä {{GENDER:$1|käyttäjä}}",
        "blockip-legend": "Estä käyttäjä",
        "blockiptext": "Tällä toiminnolla voit estää käyttäjätunnusta tai IP-osoitetta muokkaamasta.<br />\nTällainen muokkausesto pitäisi asettaa vain vandalismin torjumiseksi ja [[{{MediaWiki:Policy-url}}|käytännön]] mukaisesti.\nKirjoita eston syy alla olevaan kenttään.",
-       "ipaddressorusername": "IP-osoite tai käyttäjätunnus",
+       "ipaddressorusername": "IP-osoite tai käyttäjätunnus:",
        "ipbexpiry": "Vanhentuu:",
        "ipbreason": "Syy:",
        "ipbreason-dropdown": "*Yleiset estosyyt\n** Väärän tiedon lisääminen\n** Sisällön poistaminen\n** Mainoslinkkien lisääminen\n** Sotkeminen tai roskan lisääminen\n** Häiriköinti\n** Useamman käyttäjätunnuksen väärinkäyttö\n** Sopimaton käyttäjätunnus",
        "ipbemailban": "Estä käyttäjää lähettämästä sähköpostia",
        "ipbenableautoblock": "Estä automaattisesti viimeisin IP-osoite, josta käyttäjä on muokannut, sekä ne osoitteet, joista hän jatkossa yrittää muokata.",
        "ipbsubmit": "Estä",
-       "ipbother": "Muu kesto",
+       "ipbother": "Muu aikamääre:",
        "ipboptions": "2 tuntia:2 hours,1 päivä:1 day,3 päivää:3 days,1 viikko:1 week,2 viikkoa:2 weeks,1 kuukausi:1 month,3 kuukautta:3 months,6 kuukautta:6 months,1 vuosi:1 year,ikuinen:infinite",
        "ipbhidename": "Piilota tunnus muokkauksista ja listauksista",
        "ipbwatchuser": "Tarkkaile tämän käyttäjän käyttäjä- ja keskustelusivua",
        "ipb-unblock-addr": "Poista käyttäjän $1 esto",
        "ipb-unblock": "Poista käyttäjän tai IP-osoitteen muokkausesto",
        "ipb-blocklist": "Näytä voimassa olevat estot",
-       "ipb-blocklist-contribs": "Käyttäjän $1 muokkaukset",
+       "ipb-blocklist-contribs": "Käyttäjän {{GENDER:$1|$1}} muokkaukset",
        "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",
        "unblocked": "Käyttäjän [[User:$1|$1]] esto on poistettu",
        "unblocked-range": "$1 ei ole enää estettynä",
        "unblocked-id": "Esto $1 on poistettu",
+       "unblocked-ip": "Käyttäjän [[Special:Contributions/$1|$1]] esto on poistettu.",
        "blocklist": "Estetyt käyttäjät",
        "ipblocklist": "Estetyt käyttäjät",
        "ipblocklist-legend": "Haku",
        "movetalk": "Siirrä myös keskustelusivu",
        "move-subpages": "Siirrä kaikki alasivut (enintään $1)",
        "move-talk-subpages": "Siirrä kaikki keskustelusivun alasivut (enintään $1)",
-       "movepage-page-exists": "Sivu $1 on jo olemassa ja sitä ei voi automaattisesti korvata.",
+       "movepage-page-exists": "Sivu $1 on jo olemassa ja sen päälle ei voida automaattisesti siirtää.",
        "movepage-page-moved": "Sivu $1 on siirretty nimelle $2.",
        "movepage-page-unmoved": "Sivua $1 ei voitu siirtää nimelle $2.",
        "movepage-max-pages": "Enimmäismäärä sivuja on siirretty, eikä enempää siirretä enää automaattisesti.\n$1 {{PLURAL:$1|sivu|sivua}} siirrettiin.",
        "movelogpage": "Siirtoloki",
-       "movelogpagetext": "Tämä on loki siirretyistä sivuista.",
+       "movelogpagetext": "Tämä on luettelo kaikista sivujen siirroista.",
        "movesubpage": "{{PLURAL:$1|Alasivu|Alasivut}}",
        "movesubpagetext": "Tällä sivulla on $1 {{PLURAL:$1|alasivu|alasivua}}, jotka näkyvät alla.",
        "movenosubpage": "Tällä sivulla ei ole alasivuja.",
        "export-pagelinks": "Sisällytä linkkien kohteina olevat sivut syvyydelle:",
        "allmessages": "Järjestelmäviestit",
        "allmessagesname": "Nimi",
-       "allmessagesdefault": "Oletusarvo",
-       "allmessagescurrent": "Nykyinen arvo",
+       "allmessagesdefault": "Viestin tekstin perusmuoto",
+       "allmessagescurrent": "Viestin teksti tällä hetkellä",
        "allmessagestext": "Tämä on luettelo järjestelmäviesteistä, jotka ovat saatavilla MediaWiki-nimiavaruudessa.\nJos haluat muokata MediaWikin yleistä kotoistusta, käy [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWikin kotoistussivuilla] ja sivustolla [//translatewiki.net translatewiki.net].",
        "allmessagesnotsupportedDB": "Tämä sivu ei ole käytössä, koska <tt>$wgUseDatabaseMessages</tt>-asetus on pois päältä.",
        "allmessages-filter-legend": "Suodata",
        "import": "Tuo sivuja",
        "importinterwiki": "Tuo sivuja muista wikeistä (transwiki import)",
        "import-interwiki-text": "Valitse wiki ja sivun nimi tuontia varten.\nVersioiden päivämäärät ja muokkaajien nimet säilyvät ennallaan. \nKaikki wikienväliset tuontitapahtumat kirjataan [[Special:Log/import|tuontilokiin]].",
-       "import-interwiki-source": "Lähdewiki/sivu:",
+       "import-interwiki-sourcewiki": "Lähdewiki:",
+       "import-interwiki-sourcepage": "Lähdesivu:",
        "import-interwiki-history": "Kopioi sivun koko historia ja kaikki versiot",
        "import-interwiki-templates": "Ota mukaan kaikki mallineet",
        "import-interwiki-submit": "Tuo",
        "import-error-create": "Sivua $1 ei tuotu, koska sinulla ei ole oikeutta luoda sitä.",
        "import-error-interwiki": "Sivua $1 ei tuotu, koska sen nimi on varattu ulkoiseen linkittämiseen (interwiki).",
        "import-error-special": "Sivua $1 ei tuotu, koska se kuuluu erityiseen nimiavaruuteen, joka ei salli sivuja.",
-       "import-error-invalid": "Sivua $1 ei tuotu, koska sen nimi ei kelpaa.",
+       "import-error-invalid": "Sivua $1 ei tuotu, koska se nimi, jolle se tuotaisiin, ei ole kelvollinen tässä wikissä.",
        "import-error-unserialize": "Versiota $2 sivusta $1 ei voida jakaa osiin. Version ilmoitettiin käyttävän sisältömallia $3 ja sarjoitusmuotoilua $4.",
        "import-error-bad-location": "Sivun versiota $2, joka käyttää sisällön mallia $3, ei voi tallettaa kohteeseen \"$1\" tässä wikissä, koska tuota mallia ei tueta kyseisellä sivulla.",
        "import-options-wrong": "{{PLURAL:$2|Väärä asetus|Väärät asetukset}}: <nowiki>$1</nowiki>",
        "importlogpage": "Tuontiloki",
        "importlogpagetext": "Loki ylläpitäjien toisista wikeistä tuomista sivuista, joissa on muokkaushistoriaa.",
        "import-logentry-upload": "toi sivun [[$1]] tiedostomuodossa",
-       "import-logentry-upload-detail": "{{PLURAL:$1|yksi versio|$1 versiota}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|versio|versiota}} tuotiin",
        "import-logentry-interwiki": "toi toisesta wikistä sivun $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|versio|versiota}} tuotiin wikistä $2",
        "javascripttest": "JavaScriptin testaus",
        "autosumm-replace": "Ak: Sivun sisältö korvattiin sisällöllä ”$1”",
        "autoredircomment": "Ak: Ohjaus sivulle [[$1]]",
        "autosumm-new": "Ak: Uusi sivu: $1",
+       "autosumm-newblank": "Ak: Luotiin tyhjä sivu",
        "size-kilobytes": "$1 KiB",
        "size-megabytes": "$1 MiB",
        "size-gigabytes": "$1 GiB",
+       "size-terabytes": "$1 TiB",
+       "size-petabytes": "$1 PiB",
+       "size-exabytes": "$1 EiB",
+       "size-zetabytes": "$1 ZiB",
+       "size-yottabytes": "$1 YiB",
+       "bitrate-bits": "$1 bit/s",
+       "bitrate-kilobits": "$1 kbit/s",
+       "bitrate-megabits": "$1 Mbit/s",
+       "bitrate-gigabits": "$1 Gbit/s",
+       "bitrate-terabits": "$1 Tbit/s",
+       "bitrate-petabits": "$1 Pbit/s",
+       "bitrate-exabits": "$1 Ebit/s",
+       "bitrate-zetabits": "$1 Zbit/s",
+       "bitrate-yottabits": "$1 Ybit/s",
        "lag-warn-normal": "Muutokset, jotka ovat uudempia kuin $1 {{PLURAL:$1|sekunti|sekuntia}}, eivät välttämättä näy tällä sivulla.",
        "lag-warn-high": "Tietokannoilla on työjonoa. Muutokset, jotka ovat uudempia kuin $1 {{PLURAL:$1|sekunti|sekuntia}}, eivät välttämättä näy tällä sivulla.",
        "watchlistedit-normal-title": "Tarkkailulistan muokkaus",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|keskustelu]])",
        "unknown_extension_tag": "Tuntematon laajennuskoodi ”$1”.",
        "duplicate-defaultsort": "'''Varoitus:''' Oletuslajitteluavain ”$2” korvaa aiemman oletuslajitteluavaimen ”$1”.",
+       "duplicate-displaytitle": "<strong>Varoitus:</strong> Näytettävä otsikko \"$2\" päällekirjoittaa edellisen otsikon \"$1\".",
        "version": "Versio",
        "version-extensions": "Asennetut laajennukset",
        "version-skins": "Asennetut ulkoasut",
        "logentry-newusers-autocreate": "Käyttäjätunnus $1 {{GENDER:$2|luotiin}} automaattisesti",
        "logentry-rights-rights": "$1 {{GENDER:$2|muutti}} käyttäjän $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": "$1 {{GENDER:$2|muutettiin}} automaattisesti ryhmistä $4 ryhmiin $5",
+       "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",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|tallensi}} uuden version tiedostosta $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|tallensi}} tiedoston $3",
        "rightsnone": "(ei oikeuksia)",
        "feedback-bugornote": "Jos voit kuvailla teknisen ongelman tarkasti – [$1 ilmoita ohjelmointivirheestä].\nMuussa tapauksessa voit käyttää alla olevaa helpompaa lomaketta. Kommenttisi lisätään sivulle [$3 $2], ja siinä on mukana käyttäjätunnuksesi.",
        "feedback-subject": "Otsikko",
        "api-error-illegal-filename": "Tiedoston nimi ei kelpaa.",
        "api-error-internal-error": "Sisäinen virhe: jotain meni vikaan tallennuksesi käsittelyssä.",
        "api-error-invalid-file-key": "Sisäinen virhe: tiedostoa ei löytynyt välikaisvarastosta.",
-       "api-error-missingparam": "Sisäinen virhe: pyynnöstä puutuu parametrejä.",
+       "api-error-missingparam": "Sisäinen virhe: pyynnöstä puutuu parametreja.",
        "api-error-missingresult": "Sisäinen virhe: ei voitu varmistaa, että tallennus onnistui.",
        "api-error-mustbeloggedin": "Sinun pitää olla kirjautunut sisään, jotta voisit tallentaa tiedostoja.",
        "api-error-mustbeposted": "Sisäinen virhe: HTTP POST-pyyntö edellytetty.",
        "pagelang-language": "Kieli",
        "pagelang-use-default": "Käytä oletuskieltä",
        "pagelang-select-lang": "Valitse kieli",
-       "right-pagelang": "Vaihda sivun kieli",
+       "right-pagelang": "Vaihtaa sivun kieli",
        "action-pagelang": "muuttaa sivun kieliasetuksia",
        "log-name-pagelang": "Kielenvaihtoloki",
        "log-description-pagelang": "Tämä on loki, johon merkitään muutokset sivujen kieliasetuksissa.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|muutti}} sivun kieltä sivulla $3 kielestä $4 kieleksi $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|muutti}} sivun kieltä sivulla $3 kielestä $4 kieleksi $5.",
+       "default-skin-not-found": "Hupsista! Oletuksena tuleva ulkoasu sinun wikillesi, joka on määritelty koodissa <code dir=\"ltr\">$wgDefaultSkin</code> muotoon <code>$1</code>, ei ole saatavilla.\n\n\n<strong>Alla on ohjeita englanniksi:</strong>\n\n\nYour installation seems to include the following skins. See [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Skin configuration] for information how to enable them and choose the default.\n\n$2\n\n; If you have just installed MediaWiki: \n: You probably installed from git, or directly from the source code using some other method. This is expected. Try installing some skins from [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's skin directory], by: :* Downloading the [https://www.mediawiki.org/wiki/Download tarball installer], which comes with several skins and extensions. You can copy and paste the <code>skins/</code> directory from it. \n:* Cloning one of the <code>mediawiki/skins/*</code> repositories via git into the <code>skins/</code> directory of your MediaWiki installation. \n: Doing this should not interfere with your git repository if you're a MediaWiki developer.\n\n\n; If you have just upgraded MediaWiki: \n: MediaWiki 1.24 and newer no longer automatically enables installed skins (see [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: Skin autodiscovery]). You can paste the following lines into <code>LocalSettings.php</code> to enable all currently installed skins:\n\n<pre>$3</pre>\n\n; If you have just modified <code>LocalSettings.php</code>: \n: Double-check the skin names for typos.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (käytössä)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''ei käytössä''')"
 }
index 5a3397d..3bc686f 100644 (file)
@@ -2,7 +2,8 @@
        "@metadata": {
                "authors": [
                        "Kaganer",
-                       "Mestos"
+                       "Mestos",
+                       "아라"
                ]
        },
        "tog-underline": "Linkitten alleviivaus",
@@ -15,7 +16,6 @@
        "tog-showtoolbar": "Näytä työneuvopalkki (JavaScript)",
        "tog-editondblclick": "Mookkaa sivuja kaksoisknapituksella (JavaScript)",
        "tog-editsectiononrightclick": "Aktiveeraa seksuuni mookkaus oikeapuolen klikkauksella seksuuni tittelhiin (JavaScript)",
-       "tog-rememberpassword": "Muista minun lokkauksen tässä weppilukijassa (eninthään $1 {{PLURAL:$1|päivä|päivää}})",
        "tog-watchcreations": "Lissää sivut mitä luon valvontasivule",
        "tog-watchdefault": "Lissää sivut mitä mie mookkaan valvontasivule",
        "tog-watchmoves": "Lissää sivut mitä mie siirän minun valvontasivule",
        "qbmyoptions": "Minun inställninkit",
        "faq": "Useasti kysytyt kysymykset",
        "faqpage": "Project:Useasti kysytyt kysymykset",
-       "vector-action-addsection": "Lissää aine",
-       "vector-action-delete": "Ota poies",
-       "vector-action-move": "Siirä",
-       "vector-action-protect": "Suojaa",
-       "vector-action-undelete": "Pane takashiin",
-       "vector-action-unprotect": "Muuta suojaa",
-       "vector-view-create": "Luo",
-       "vector-view-edit": "Mookkaa",
-       "vector-view-history": "Näytä histuuria",
-       "vector-view-view": "Lue",
-       "vector-view-viewsource": "Näytä lähekooti",
        "actions": "Toiminat",
        "namespaces": "Nimityhjyyet",
        "variants": "Varianttia",
        "remembermypassword": "Muista minun lokkauksen tässä taattorissa (korkeinthaans $1 {{PLURAL:$1|päivä|päivää}})",
        "login": "Lokkaa sisäle",
        "nav-login-createaccount": "Lokkaa sisäle / luo konttu",
-       "loginprompt": "Lokkauksheen tähhään {{SITENAME}} tarvithaan ette olet aktiveeranu kuukit .",
        "userlogin": "Lokkaa sisäle/ luo konttu",
        "userlogout": "Lokkaa ulos",
        "nologin": "Eikos sulla ole käyttäjäkonttua, '''$1'''.",
        "searchmenu-exists": "'''Sivu [[:$1]] löytyy tästä wikistä.'''",
        "searchmenu-new": "'''Luo sivu ''[[:$1]]'' tähhaän wikhiin.'''",
        "searchprofile-articles": "Sisältösivut",
-       "searchprofile-project": "Apu ja prujektisivut",
        "searchprofile-images": "Mylttimeetia",
        "searchprofile-everything": "Kaikki",
        "searchprofile-advanced": "Avanseerattu",
        "searchprofile-articles-tooltip": "Hae nimityhjyyestä $1",
-       "searchprofile-project-tooltip": "Hae nimityhjyyestä $1",
        "searchprofile-images-tooltip": "Hae fiiliä",
        "searchprofile-everything-tooltip": "Hae kaikesta (keskustelusivut kans)",
        "searchprofile-advanced-tooltip": "Hae tietyissä nimityhjyissä",
        "recentchanges-label-bot": "Tämän muutoksen teki botti",
        "recentchanges-label-unpatrolled": "Tätä muutosta ei ole vielä tarkistettu",
        "rcnotefrom": "Alla on muutokset '''$2'''lähtien. (korkeinthaans '''$1''' näytethään).",
-       "rclistfrom": "Näytä uuet muutokset jälkhiin $1",
+       "rclistfrom": "Näytä uuet muutokset jälkhiin $3 $2",
        "rcshowhideminor": "$1 pienet muutokset",
        "rcshowhidebots": "$1 ropootit",
        "rcshowhideliu": "\n$1 sisäle lokaattuja käyttäjiä",
        "upload": "Lattaa ylös fiili",
        "uploadlogpage": "Ylöslattauksen loki",
        "filedesc": "Yhteenveto",
-       "uploadedimage": "lattasi ylös [[$1]]",
        "license": "Lisensi",
        "license-header": "Lisensi",
        "file-anchor-link": "Fiili",
        "booksources-go": "Mene",
        "log": "Lokit",
        "allpages": "Kaikki sivut",
-       "alphaindexline": "$1…$2",
        "allarticles": "Kaikki sivut",
        "allpagessubmit": "Mene",
        "categories": "Katekuurit",
index 2e56326..40620b4 100644 (file)
        "talkpagelinktext": "Kjak",
        "specialpage": "Serstøk síða",
        "personaltools": "Persónlig amboð",
-       "postcomment": "Nýtt brot",
        "articlepage": "Vís síðu við innihaldi",
        "talk": "Kjak",
        "views": "Skoðanir",
        "externaldberror": "Antin var talan um ein atgongd dátubasu feil, ella hevur tú ikki loyvi til at dagføra tína eksternu kontu.",
        "login": "Rita inn",
        "nav-login-createaccount": "Stovna kontu ella rita inn",
-       "loginprompt": "Cookies má verða sett til fyri at innrita á {{SITENAME}}.",
        "userlogin": "Stovna kontu ella rita inn",
        "userloginnocreate": "Rita inn",
        "logout": "Útrita",
        "searchprofile-advanced-tooltip": "Leita í ávísum navnaøkjum",
        "search-result-size": "$1 ({{PLURAL:$2|1 orð|$2 orð}})",
        "search-result-category-size": "{{PLURAL:$1|1 limur|$1 limir}} ({{PLURAL:$2|1 undirbólkur|$2 undirbólkar}}, {{PLURAL:$3|1 fíla|$3 fílur}})",
-       "search-result-score": "Viðkomandi: $1%",
        "search-redirect": "(umstilling $1)",
        "search-section": "(sektión $1)",
        "search-suggest": "Meinti tú: $1",
        "uploadwarning": "Ávaring",
        "uploadwarning-text": "Vinarliga broyt frágreiðingina fyri fíluna og royn umaftur.",
        "savefile": "Goym fílu",
-       "uploadedimage": "sent \"[[$1]]\" upp",
-       "overwroteimage": "legði út eina nýggja versjón av \"[[$1]]\"",
        "uploaddisabled": "Útleggjan av fílum er óvirkin.",
        "copyuploaddisabled": "Útleggjan frá URL er óvirkið.",
        "uploaddisabledtext": "Útleggjan av fílum er óvirkið.",
        "watchlist-details": "{{PLURAL:$1|$1 síða|$1 síður}} á tínum vaktarlista, kjaksíður ikki íroknaðar.",
        "wlheader-enotif": "Tað ber nú til at senda teldupost.",
        "wlheader-showupdated": "Síður sum eru broyttar síðan tú seinast vitjaði tær, eru vístar við '''feitum'''.",
+       "wlnote": "Niðanfyri {{PLURAL:$1|stendur seinasta broytingin|standa seinastu '''$1''' broytingarnar}} seinasta/u {{PLURAL:$2| tíman|'''$2''' tímarnar}} hin $3 kl. $4",
        "wlshowlast": "Vís seinastu $1 tímar $2 dagar $3",
        "watchlist-options": "Møguleikar í ansingarlistanum",
        "watching": "Eftirlitir...",
index cb06d62..082013a 100644 (file)
                        "Scoopfinder",
                        "Akeron",
                        "Linedwell",
-                       "Yona b"
+                       "Yona b",
+                       "SnowedEarth",
+                       "Orikrin1998",
+                       "Automatik",
+                       "Elodark"
                ]
        },
        "tog-underline": "Souligner les liens :",
        "tog-watchdefault": "Ajouter les pages et les fichiers que je modifie à ma liste de suivi",
        "tog-watchmoves": "Ajouter les pages et les fichiers que je renomme à ma liste de suivi",
        "tog-watchdeletion": "Ajouter les pages et les fichiers que je supprime à ma liste de suivi",
+       "tog-watchrollback": "Ajouter à ma liste de suivi les pages sur lesquelles j’ai effectué une révocation",
        "tog-minordefault": "Marquer toutes mes modifications comme mineures par défaut",
        "tog-previewontop": "Afficher la prévisualisation au-dessus de la zone de modification",
        "tog-previewonfirst": "Afficher la prévisualisation lors de la première modification",
-       "tog-enotifwatchlistpages": "M'avertir par courriel lorsqu'une page ou un fichier de ma liste de suivi est modifiée",
+       "tog-enotifwatchlistpages": "M'avertir par courriel lorsqu'une page ou un fichier de ma liste de suivi est modifié",
        "tog-enotifusertalkpages": "M'avertir par courriel si ma page de discussion est modifiée",
        "tog-enotifminoredits": "M'avertir par courriel également lors des modifications mineures de pages ou de fichiers",
        "tog-enotifrevealaddr": "Afficher mon adresse de courriel dans les courriels de notification",
        "edit": "Modifier",
        "edit-local": "Modifier la description locale",
        "create": "Créer",
-       "create-local": "ajouter une description locale",
+       "create-local": "Ajouter une description locale",
        "editthispage": "Modifier cette page",
        "create-this-page": "Créer cette page",
        "delete": "Supprimer",
        "deletethispage": "Supprimer cette page",
-       "undeletethispage": "Annuler la suppression de cette page",
+       "undeletethispage": "Restaurer cette page",
        "undelete_short": "Restaurer {{PLURAL:$1|une modification|$1 modifications}}",
        "viewdeleted_short": "Voir {{PLURAL:$1|une modification supprimée|$1 modifications supprimées}}",
        "protect": "Protéger",
        "talkpagelinktext": "discuter",
        "specialpage": "Page spéciale",
        "personaltools": "Outils personnels",
-       "postcomment": "Nouvelle section",
        "articlepage": "Voir la page de contenu",
        "talk": "Discussion",
        "views": "Affichages",
        "otherlanguages": "Autres langues",
        "redirectedfrom": "(Redirigé depuis $1)",
        "redirectpagesub": "Page de redirection",
+       "redirectto": "Rediriger vers :",
        "lastmodifiedat": "Dernière modification de cette page le $1 à $2.<br />",
        "viewcount": "Cette page a été consultée {{PLURAL:$1|une fois|$1 fois}}.",
        "protectedpage": "Page protégée",
        "jumpto": "Aller à :",
        "jumptonavigation": "navigation",
        "jumptosearch": "rechercher",
-       "view-pool-error": "Désolé, les serveurs sont surchargés en ce moment.\nTrop d'utilisateurs cherchent à consulter cette page.\nVeuillez attendre un moment avant de retenter l'accès à cette page.\n\n$1",
+       "view-pool-error": "Désolé, les serveurs sont surchargés en ce moment.\nTrop d'utilisateurs cherchent à consulter cette page.\nVeuillez attendre un moment avant de retenter l'accès à celle ci.\n$1",
        "generic-pool-error": "Désolé, les serveurs sont surchargés pour le moment.\nTrop d’utilisateurs essayent de consulter cette ressource.\nVeuillez attendre un peu avant de réessayer d’accéder à celle-ci.",
        "pool-timeout": "Délai d'attente dépassé",
        "pool-queuefull": "La file d'attente est pleine",
        "badaccess-group0": "Vous n’avez pas les droits suffisants pour réaliser l’action demandée.",
        "badaccess-groups": "L’action que vous essayez de réaliser n’est permise qu’aux utilisateurs {{PLURAL:$2|du groupe|d'un des groupes}} : $1.",
        "versionrequired": "Version $1 de MediaWiki nécessaire",
-       "versionrequiredtext": "La version $1 de MediaWiki est nécessaire pour utiliser cette page. Consultez [[Special:Version|la page des versions]]",
+       "versionrequiredtext": "La version $1 de MediaWiki est nécessaire pour utiliser cette page. Consultez [[Special:Version|la page des versions]].",
        "ok": "Valider",
        "pagetitle": "$1 — {{SITENAME}}",
        "retrievedfrom": "Récupérée de « $1 »",
        "hidetoc": "masquer",
        "collapsible-collapse": "masquer",
        "collapsible-expand": "afficher",
+       "confirmable-confirm": "Êtes-vous sûr{{GENDER:||e|(e)}} ?",
+       "confirmable-yes": "Oui",
+       "confirmable-no": "Non",
        "thisisdeleted": "Désirez-vous afficher ou restaurer $1 ?",
        "viewdeleted": "Voir $1 ?",
        "restorelink": "{{PLURAL:$1|la modification effacée|les $1 modifications effacées}}",
        "invalidtitle-knownnamespace": "Titre invalide avec l'espace de noms « $2 » et l'intitulé « $3 »",
        "invalidtitle-unknownnamespace": "Titre invalide avec le numéro d'espace de noms $1 et l'intitulé « $2 » inconnus",
        "exception-nologin": "Non connecté",
-       "exception-nologin-text": "Veuillez [[Special:Userlogin|vous connecter]] pour pouvoir accéder à cette page ou cette action.",
+       "exception-nologin-text": "Veuillez vous connecter pour pouvoir accéder à cette page ou cette action.",
        "exception-nologin-text-manual": "Veuillez $1 pour pouvoir accéder à cette page ou cette action.",
        "virus-badscanner": "Mauvaise configuration : scanneur de virus inconnu : ''$1''",
        "virus-scanfailed": "Échec de la recherche (code $1)",
        "virus-unknownscanner": "antivirus inconnu :",
-       "logouttext": "'''Vous êtes à présent déconnecté.'''\n\nNotez que certaines pages peuvent être encore affichées comme si vous étiez toujours connecté, jusqu’à ce que vous effaciez le cache de votre navigateur.",
+       "logouttext": "'''Vous êtes à présent déconnecté{{GENDER:||e|(e)}}.'''\n\nNotez que certaines pages peuvent être encore affichées comme si vous étiez toujours connecté, jusqu’à ce que vous effaciez le cache de votre navigateur.",
        "welcomeuser": "Bienvenue, $1&nbsp;!",
        "welcomecreation-msg": "Votre compte a été créé.\nN'oubliez pas de modifier [[Special:Preferences|vos préférences pour {{SITENAME}}]].",
        "yourname": "Nom d'utilisateur :",
        "externaldberror": "Une erreur s'est produite avec la base de données d'authentification externe, ou bien vous n'êtes pas autorisé{{GENDER:||e|(e)}} à mettre à jour votre compte externe.",
        "login": "Connexion",
        "nav-login-createaccount": "Créer un compte ou se connecter",
-       "loginprompt": "Vous devez activer les cookies pour vous connecter à {{SITENAME}}.",
        "userlogin": "Créer un compte ou se connecter",
        "userloginnocreate": "Connexion",
        "logout": "Se déconnecter",
        "userlogin-resetlink": "Vous avez oublié vos détails de connexion ?",
        "userlogin-resetpassword-link": "Mot de passe oublié ?",
        "userlogin-helplink2": "Aide à la connexion",
-       "userlogin-loggedin": "Vous êtes déjà connecté{{GENDER:$1||e}} en tant que {{GENDER:$1|$1}}.\nUtilisez le formulaire ci-dessous pour vous connecter avec un autre compte utilisateur.",
-       "userlogin-createanother": "Créer un autre compte",
        "createacct-emailrequired": "Adresse de courriel",
        "createacct-emailoptional": "Adresse de courriel (facultative)",
        "createacct-email-ph": "Entrez votre adresse de courriel",
        "password-login-forbidden": "L'utilisation de ce nom d'utilisateur et de ce mot de passe a été interdite.",
        "mailmypassword": "Réinitialiser le mot de passe",
        "passwordremindertitle": "Nouveau mot de passe temporaire pour {{SITENAME}}",
-       "passwordremindertext": "Quelqu'un (probablement vous, ayant l'adresse IP $1) a demandé un nouveau mot de\npasse pour {{SITENAME}} ($4 ). Un mot de passe temporaire a été créé pour\nl'utilisateur « $2 » et est « $3 ». Si cela était votre intention, vous devrez\nvous connecter et choisir un nouveau mot de passe.\nVotre mot de passe temporaire expirera dans $5 jour{{PLURAL:$5||s}}.\n\nSi vous n'êtes pas l'auteur de cette demande, ou si vous vous souvenez à présent\nde votre ancien mot de passe et que vous ne souhaitez plus en changer, vous\npouvez ignorer ce message et continuer à utiliser votre ancien mot de passe.",
+       "passwordremindertext": "Quelqu'un (probablement vous, ayant l'adresse IP $1) a demandé un nouveau mot de\npasse pour {{SITENAME}} ($4). Un mot de passe temporaire a été créé pour\nl'utilisateur « $2 » et est « $3 ». Si cela était votre intention, vous devrez\nvous connecter et choisir un nouveau mot de passe.\nVotre mot de passe temporaire expirera dans $5 jour{{PLURAL:$5||s}}.\n\nSi vous n'êtes pas l'auteur de cette demande, ou si vous vous souvenez à présent\nde votre ancien mot de passe et que vous ne souhaitez plus en changer, vous\npouvez ignorer ce message et continuer à utiliser votre ancien mot de passe.",
        "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.",
        "createaccount-text": "Quelqu’un a créé un compte pour votre adresse de courriel sur {{SITENAME}} ($4) intitulé « $2 », avec le mot de passe « $3 ».\nVous devriez ouvrir une session et modifier dès à présent votre mot de passe.\n\nIgnorez ce message si ce compte a été créé par erreur.",
        "login-throttled": "Vous avez tenté un trop grand nombre de connexions dernièrement.\nVeuillez attendre $1 avant d'essayer à nouveau.",
        "login-abort-generic": "Votre tentative de connexion a échoué",
+       "login-migrated-generic": "Votre compte a été migré, et votre nom d’utilisateur n’existe plus sur ce wiki.",
        "loginlanguagelabel": "Langue : $1",
        "suspicious-userlogout": "Votre demande de déconnexion a été refusée car il semble qu'elle a été envoyée par un navigateur cassé ou la mise en cache d'un proxy.",
        "createacct-another-realname-tip": "Le vrai nom est optionnel.\nSi vous décidez de le fournir, il sera utilisé pour attribuer à l’utilisateur ses travaux.",
        "resetpass-submit-cancel": "Annuler",
        "resetpass-wrong-oldpass": "Mot de passe actuel ou temporaire invalide.\nVous avez peut-être déjà changé votre mot de passe ou demandé un nouveau mot de passe temporaire.",
        "resetpass-recycled": "Veuillez réinitialiser votre mot de passe à quelque chose d’autre que l’actuel.",
-       "resetpass-temp-emailed": "Vous êtes connecté avec un code temporaire fourni par courriel.\nPour terminer la connexion, vous devez fournir un nouveau mot de passe ici :",
+       "resetpass-temp-emailed": "Vous êtes connecté{{GENDER:||e|(e)}} avec un code temporaire fourni par courriel.\nPour terminer la connexion, vous devez fournir un nouveau mot de passe ici :",
        "resetpass-temp-password": "Mot de passe temporaire :",
        "resetpass-abort-generic": "La modification du mot de passe a été annulée par une extension.",
        "resetpass-expired": "Votre mot de passe a expiré. Veuillez en fournir un nouveau pour vous connecter.",
        "passwordreset-emaildisabled": "Les fonctionnalités e-mail ont été désactivées sur ce wiki.",
        "passwordreset-username": "Nom d'utilisateur :",
        "passwordreset-domain": "Domaine :",
-       "passwordreset-capture": "Voir le courriel résultant?",
+       "passwordreset-capture": "Voir le courriel résultant ?",
        "passwordreset-capture-help": "Si vous cochez cette case, le courriel (avec le mot de passe temporaire) vous sera affiché en même temps qu'il sera envoyé à l'utilisateur.",
        "passwordreset-email": "Adresse de courriel :",
        "passwordreset-emailtitle": "Détails du compte sur {{SITENAME}}",
-       "passwordreset-emailtext-ip": "Quelqu'un (probablement vous, depuis l'adresse IP $1) a demandé un réinitialisation de votre mot de passe pour {{SITENAME}} ($4). {{PLURAL:$3|Le compte utilisateur suivant est associé|Les comptes utilisateurs suivants sont associés}} à cette adresse de courriel :\n\n$2\n\n{{PLURAL:$3|Ce mot de passe temporaire expirera|Ces mots de passe temporaires expireront}} dans {{PLURAL:$5|un jour|$5 jours}}. Vous devez maintenant vous connecter et choisir un nouveau mot de passe. Si cette demande ne provient pas de vous, ou que vous vous êtes souvenu de votre mot de passe initial, et ne souhaitez plus le modifier, vous pouvez ignorer ce message et continuer à utiliser votre ancien mot de passe.",
-       "passwordreset-emailtext-user": "L'utilisateur $1 sur {{SITENAME}} a demandé un réinitialisation de votre mot de passe pour {{SITENAME}} ($4). {{PLURAL:$3|Le compte utilisateur suivant est associé|Les comptes utilisateurs suivants sont associés}} à cette adresse de courriel :\n\n$2\n\n{{PLURAL:$3|Ce mot de passe temporaire expirera|Ces mots de passe temporaires expireront}} dans {{PLURAL:$5|un jour|$5 jours}}. Vous devez maintenant vous connecter et choisir un nouveau mot de passe. Si cette demande ne provient pas de vous, ou que vous vous êtes souvenu de votre mot de passe initial, et ne souhaitez plus le modifier, vous pouvez ignorer ce message et continuer à utiliser votre ancien mot de passe.",
+       "passwordreset-emailtext-ip": "Quelqu'un (probablement vous, depuis l'adresse IP $1) a demandé un réinitialisation de votre mot de passe pour {{SITENAME}} ($4). {{PLURAL:$3|Le compte utilisateur suivant est associé|Les comptes utilisateurs suivants sont associés}} à cette adresse de courriel :\n\n$2\n\n{{PLURAL:$3|Ce mot de passe temporaire expirera|Ces mots de passe temporaires expireront}} dans {{PLURAL:$5|un jour|$5 jours}}. Vous devez maintenant vous connecter et choisir un nouveau mot de passe. Si cette demande ne provient pas de vous, ou que vous vous êtes souvenu{{GENDER:||e|(e)}} de votre mot de passe initial, et ne souhaitez plus le modifier, vous pouvez ignorer ce message et continuer à utiliser votre ancien mot de passe.",
+       "passwordreset-emailtext-user": "L'utilisateur $1 sur {{SITENAME}} a demandé un réinitialisation de votre mot de passe pour {{SITENAME}} ($4). {{PLURAL:$3|Le compte utilisateur suivant est associé|Les comptes utilisateurs suivants sont associés}} à cette adresse de courriel :\n\n$2\n\n{{PLURAL:$3|Ce mot de passe temporaire expirera|Ces mots de passe temporaires expireront}} dans {{PLURAL:$5|un jour|$5 jours}}. Vous devez maintenant vous connecter et choisir un nouveau mot de passe. Si cette demande ne provient pas de vous, ou que vous vous êtes souvenu{{GENDER:||e|(e)}} de votre mot de passe initial, et ne souhaitez plus le modifier, vous pouvez ignorer ce message et continuer à utiliser votre ancien mot de passe.",
        "passwordreset-emailelement": "Nom d'utilisateur : $1\nMot de passe temporaire : $2",
        "passwordreset-emailsent": "Un courriel de réinitialisation de mot de passe a été envoyé.",
        "passwordreset-emailsent-capture": "Un courriel de réinitialisation de mot de passe a été envoyé, qui est affiché ci-dessous.",
-       "passwordreset-emailerror-capture": "Un courriel de réinitialisation de mot de passe a été généré, qui est affiché ci-dessous, mais l'envoi à l'{{GENDER:$2|utilisateur}} a échoué : $1",
+       "passwordreset-emailerror-capture": "Un courriel de réinitialisation de mot de passe a été généré, qui est affiché ci-dessous, mais l'envoi à l'{{GENDER:$2|utilisateur|utilisatrice}} a échoué : $1",
        "changeemail": "Changer l’adresse de courriel",
        "changeemail-header": "Changer l’adresse de courriel du compte",
        "changeemail-text": "Remplissez ce formulaire pour changer votre adresse de courriel. Vous devrez entrer votre mot de passe pour confirmer ce changement.",
        "preview": "Prévisualisation",
        "showpreview": "Prévisualiser",
        "showdiff": "Voir les modifications",
-       "anoneditwarning": "<strong>Attention :</strong> Vous n’êtes pas identifié(e). Votre adresse IP sera enregistrée dans l’historique de cette page.",
+       "blankarticle": "<strong>Attention :</strong> La page que vous créez est vide.\nSi vous cliquez de nouveau sur « {{int:savearticle}} », la page sera créée sans aucun contenu.",
+       "anoneditwarning": "<strong>Attention :</strong> Vous n’êtes pas connecté. Votre adresse IP sera visible de tout le monde si vous faites des modifications. Si vous <strong>[$1 vous connectez]</strong> ou <strong>[$2 créez un compte]</strong>, vos modifications seront attribuées à votre nom d’utilisateur, entre autres avantages.",
        "anonpreviewwarning": "''Vous n’êtes pas identifié(e). Sauvegarder enregistrera votre adresse IP dans l’historique des modifications de la page.''",
        "missingsummary": "'''Rappel :''' vous n'avez pas encore fourni le résumé de votre modification.\nSi vous cliquez de nouveau sur le bouton « {{int:savearticle}} », la publication sera faite sans nouvel avertissement.",
        "missingcommenttext": "Veuillez entrer un commentaire ci-dessous.",
        "content-failed-to-parse": "Échec de l’analyse syntaxique du contenu de $2 pour le modèle $1: $3",
        "invalid-content-data": "Données du contenu non valides",
        "content-not-allowed-here": "Le contenu « $1 » n’est pas autorisé sur la page [[$2]]",
-       "editwarning-warning": "Quitter cette page vous fera perdre toutes les modifications que vous avez faites.\nSi vous êtes connecté, vous pouvez désactiver cet avertissement dans la section « {{int:prefs-editing}} » de vos préférences.",
+       "editwarning-warning": "Quitter cette page vous fera perdre toutes les modifications que vous avez faites.\nSi vous êtes connecté{{GENDER:||e|(e)}}, vous pouvez désactiver cet avertissement dans la section « {{int:prefs-editing}} » de vos préférences.",
        "editpage-notsupportedcontentformat-title": "Format de contenu non pris en charge",
        "editpage-notsupportedcontentformat-text": "Le format de contenu $1 n'est pas pris en charge par le modèle de contenu $2 .",
        "content-model-wikitext": "wikitexte",
        "parser-template-recursion-depth-warning": "Limite de profondeur des appels de modèles dépassée ($1)",
        "language-converter-depth-warning": "Limite de profondeur du convertisseur de langue dépassée ($1)",
        "node-count-exceeded-category": "Pages où nombre de nœuds est dépassé",
-       "node-count-exceeded-category-desc": "Une catégorie pour les pages où le nombre de nœuds est dépassé.",
+       "node-count-exceeded-category-desc": "Cette page dépasse le nombre maximal de nœuds.",
        "node-count-exceeded-warning": "Page dépassant le nombre de nœuds",
        "expansion-depth-exceeded-category": "Pages où la profondeur d'expansion est dépassée",
-       "expansion-depth-exceeded-category-desc": "Ceci est une catégorie pour les pages où la profondeur d’expansion est dépassée.",
+       "expansion-depth-exceeded-category-desc": "La page dépasse la profondeur d’expansion maximale.",
        "expansion-depth-exceeded-warning": "Page dépassant la profondeur d'expansion",
        "parser-unstrip-loop-warning": "Boucle non démontable détectée",
        "parser-unstrip-recursion-limit": "Limite de récursion non démontable dépassée ($1)",
        "rev-deleted-event": "(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 effacements].",
+       "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 suppressions].",
        "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 effacements].\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 suppression].\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 effacements].",
        "revdelete-nooldid-title": "Version cible non valide",
        "revdelete-nooldid-text": "Vous n'avez pas précisé la version cible de cette fonction, elle n'existe pas, ou il s'agit de la version actuelle.",
        "revdelete-no-file": "Le fichier spécifié n'existe pas.",
-       "revdelete-show-file-confirm": "Êtes-vous sûr de vouloir voir la révision supprimée du fichier « <nowiki>$1</nowiki> » datant du $2 à $3 ?",
+       "revdelete-show-file-confirm": "Êtes-vous sûr{{GENDER:||e|(e)}} de vouloir voir la révision supprimée du fichier « <nowiki>$1</nowiki> » datant du $2 à $3 ?",
        "revdelete-show-file-submit": "Oui",
        "revdelete-selected-text": "{{PLURAL:$1|Révision sélectionnée|Révisions sélectionnées}} de [[:$2]] :",
        "revdelete-selected-file": "{{PLURAL:$1|Version de fichier sélectionnée|Versions de fichier sélectionnées}} de [[:$2]] :",
        "revdelete-text-text": "Les révisions supprimées continueront à apparaître dans l’historique de la page, mais une partie de leur contenu sera inaccessible au public.",
        "revdelete-text-file": "Les versions de fichier supprimées continueront à apparaître dans l’historique des fichiers, mais une partie de leur contenu sera indisponible au public.",
        "logdelete-text": "Les évènements du journal supprimés continueront à apparaître dans les journaux, mais une partie de leur contenu sera indisponible au public.",
-       "revdelete-text-others": "Les autres administrateurs de {{SITENAME}} seront toujours capables d'accéder au contenu caché et peuvent le restaurer à nouveau par cette interface, à moins que des restrictions additionnelles soient définies.",
+       "revdelete-text-others": "Les autres administrateurs seront toujours en mesure d'accéder au contenu caché et le restaurer, à moins que des restrictions supplémentaires soient fixées.",
        "revdelete-confirm": "Confirmez que vous voulez effectuer cette action, que vous en comprenez les conséquences, et que vous le faites en accord avec [[{{MediaWiki:Policy-url}}|les règles]].",
        "revdelete-suppress-text": "La suppression ne doit être utilisée '''que''' dans les cas suivants :\n* Informations potentiellement diffamatoires\n* Informations personnelles inappropriées\n*: ''adresse, numéro de téléphone, numéro de sécurité sociale, …''",
        "revdelete-legend": "Mettre en place des restrictions de visibilité :",
        "searchprofile-advanced-tooltip": "Choisir les espaces de noms pour la recherche",
        "search-result-size": "$1 ($2 mot{{PLURAL:$2||s}})",
        "search-result-category-size": "$1 membre{{PLURAL:$1||s}} ($2 sous-catégorie{{PLURAL:$2||s}}, $3 fichier{{PLURAL:$3||s}})",
-       "search-result-score": "Pertinence : $1%",
        "search-redirect": "(redirection depuis $1)",
        "search-section": "(section $1)",
        "search-file-match": "(correspond au contenu du fichier)",
        "searchall": "tout",
        "showingresults": "Affichage de <b>$1</b> résultat{{PLURAL:$1||s}} à partir du n°<b>$2</b>.",
        "showingresultsinrange": "Afficher ci-dessous jusqu’à {{PLURAL:$1|<strong>1</strong> résultat|<strong>$1</strong> résultats}} dans la série #<strong>$2</strong> à #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Résultat '''$1'''|Résultats '''$1–$2'''}} de '''$3''' pour '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Résultat <strong>$1</strong> parmi <strong>$3</strong>|Résultats <strong>$1 à $2</strong> parmi <strong>$3</strong>}}",
        "search-nonefound": "Il n'y a aucun résultat correspondant à la requête.",
        "powersearch-legend": "Recherche avancée",
        "powersearch-ns": "Rechercher dans les espaces de noms :",
        "preferences": "Préférences",
        "mypreferences": "Préférences",
        "prefs-edits": "Nombre de modifications :",
-       "prefsnologintext2": "Veuillez $1 pour définir les préférences utilisateur.",
+       "prefsnologintext2": "Veuillez vous connecter pour modifier vos préférences.",
        "prefs-skin": "Habillage",
        "skin-preview": "Prévisualiser",
        "datedefault": "Aucune préférence",
        "userrights-lookup-user": "Gestion des groupes d'utilisateurs",
        "userrights-user-editname": "Entrez un nom d'utilisateur :",
        "editusergroup": "Modification des groupes d'utilisateurs",
-       "editinguser": "Modification des droits de l'{{GENDER:$1|utilisateur|utilisatrice}} '''[[User:$1|$1]]''' $2",
+       "editinguser": "Modification des droits de l’{{GENDER:$1|utilisateur|utilisatrice}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Modifier les groupes de l'utilisateur",
        "saveusergroups": "Enregistrer les groupes de l'utilisateur",
        "userrights-groupsmember": "Membre de :",
        "right-deletedtext": "Voir le texte supprimé et les différences entre les versions supprimées",
        "right-browsearchive": "Rechercher des pages supprimées",
        "right-undelete": "Restaurer une page supprimée",
-       "right-suppressrevision": "Examiner et restaurer les versions masquées aux administrateurs",
+       "right-suppressrevision": "Afficher, masquer et démasquer des révisions spécifiques de pages pour n’importe quel utilisateur",
+       "right-viewsuppressed": "Afficher les révisions masquées pour n’importe quel utilisateur",
        "right-suppressionlog": "Voir les journaux privés",
        "right-block": "Bloquer en écriture d'autres utilisateurs",
        "right-blockemail": "Empêcher un utilisateur d'envoyer des courriels",
        "recentchanges-legend-heading": "'''Légende :'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (voir aussi la [[Special:NewPages|liste des nouvelles pages]]).",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Ci-dessous les modifications effectuées depuis le <strong>$2</strong> (jusqu’à <strong>$1</strong> affichés).",
+       "rcnotefrom": "Ci-dessous {{PLURAL:$5|la modification effectuée|les modifications effectuées}} depuis le <strong>$3, $4</strong> (affichées jusqu’à <strong>$1</strong>).",
        "rclistfrom": "Afficher les nouvelles modifications depuis le $3 à $2",
        "rcshowhideminor": "$1 les modifications mineures",
        "rcshowhideminor-show": "Afficher",
        "uploadwarning": "Attention !",
        "uploadwarning-text": "Modifiez la description du fichier et essayez de nouveau.",
        "savefile": "Sauvegarder le fichier",
-       "uploadedimage": "a importé « [[$1]] »",
-       "overwroteimage": "a importé une nouvelle version de « [[$1]] »",
        "uploaddisabled": "Désolé, l’import de fichiers est désactivé.",
        "copyuploaddisabled": "Import de fichier par URL désactivé.",
        "uploaddisabledtext": "L’import de fichiers est désactivé sur ce wiki.",
        "license": "Licence",
        "license-header": "Conditions d'utilisation",
        "nolicense": "Aucune licence sélectionnée",
+       "licenses-edit": "Modifier les options de licence",
        "license-nopreview": "(Prévisualisation non disponible)",
-       "upload_source_url": " (une URL valide et accessible publiquement)",
-       "upload_source_file": " (un fichier sur votre ordinateur)",
+       "upload_source_url": "(le fichier que vous avez choisi depuis une URL valide et accessible publiquement)",
+       "upload_source_file": "(votre fichier choisi depuis votre ordinateur)",
+       "listfiles-delete": "supprimer",
        "listfiles-summary": "Cette page spéciale permet de lister tous les fichiers importés.",
        "listfiles_search_for": "Rechercher un nom de média :",
        "imgfile": "fichier",
        "randomincategory": "Page au hasard dans la catégorie",
        "randomincategory-invalidcategory": "« $1 » n’est pas un nom de catégorie valide.",
        "randomincategory-nopages": "Il n’y a pas de page dans [[:Category:$1]].",
-       "randomincategory-selectcategory": "Prendre une page au hasard dans la catégorie : $1 $2.",
-       "randomincategory-selectcategory-submit": "Aller",
+       "randomincategory-category": "Catégorie :",
+       "randomincategory-legend": "Page aléatoire dans la catégorie",
        "randomredirect": "Page de redirection au hasard",
        "randomredirect-nopages": "Il n'y a aucune page de redirection dans l'espace de noms « $1 ».",
        "statistics": "Statistiques",
        "wantedpages-badtitle": "Titre invalide dans les résultats : $1",
        "wantedfiles": "Fichiers les plus demandés",
        "wantedfiletext-cat": "Les fichiers suivants sont utilisés, mais n'existent pas localement. S'ils se trouvent sur un dépôt partagé, ils peuvent être listés ici, bien qu'ils soient, de fait, déjà disponibles. Tous ces faux positifs seront <del>barrés</del>. En outre, les pages qui intègrent des fichiers qui n'existent pas sont répertoriées dans [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Les fichiers suivants sont utilisés mais n'existent pas. De plus, les pages qui intègrent les fichiers qui n'existent pas sont listés dans [[:$1]].",
        "wantedfiletext-nocat": "Les fichiers suivants sont utilisés, mais n'existent pas localement. S'ils se trouvent sur un dépôt partagé, ils peuvent être listés ici, bien qu'ils soient, de fait, déjà disponibles. Tous ces faux positifs seront <del>barrés</del>.",
+       "wantedfiletext-nocat-noforeign": "Les fichiers suivants sont utilisés mais n'existent pas.",
        "wantedtemplates": "Modèles demandés",
        "mostlinked": "Pages les plus liées",
        "mostlinkedcategories": "Catégories les plus utilisées",
        "trackingcategories-desc": "Critère d’inclusion de la catégorie",
        "noindex-category-desc": "La page contient <code><nowiki>__NOINDEX__</nowiki></code> et est dans un espace de noms où ce marquage est autorisé ; elle ne sera donc pas indexée par les robots.",
        "index-category-desc": "La page contient <code><nowiki>__INDEX__</nowiki></code> et est dans un espace de noms où ce marquage est autorisé ; elle sera donc indexée par les robots alors qu’elle ne l’aurait pas été normalement.",
-       "post-expand-template-inclusion-category-desc": "Après avoir développé tous les modèles, la taille de la page dépasse <code>$wgMaxArticleSize</code> ; certains modèles n’ont donc pas été développés.",
-       "post-expand-template-argument-category-desc": "Après avoir développé l’argument d’un modèle (quelque chose entre accolades triples, comme <code>{{{Foo}}}</code>), la page dépasse <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Trop de fonctions coûteuses de l’analyseur (comme <code>#ifexist</code>) sont incluses dans une page. Voyez [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "La catégorie ajoutée sur la page contient un lien de fichier incorrect (un lien pour inclure un fichier alors que celui-ci n’existe pas).",
-       "hidden-category-category-desc": "Catégorie contenant <code><nowiki>__HIDDENCAT__</nowiki></code>, ce qui empêche son affichage dans la zone des liens de catégorie sur les pages, par défaut.",
+       "post-expand-template-inclusion-category-desc": "La taille de la page dépasse <code>$wgMaxArticleSize</code> après le développement de tous ses modèles ; certains n’ont donc pas été développés.",
+       "post-expand-template-argument-category-desc": "La page dépasse <code>$wgMaxArticleSize</code> après avoir développé l’argument d’un modèle (quelque chose entre accolades triples, comme <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "La page utilise trop de fonctions coûteuses de l’analyseur (comme <code>#ifexist</code>). Voyez [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "La page contient un lien de fichier incorrect (un lien pour inclure un fichier alors que celui-ci n’existe pas).",
+       "hidden-category-category-desc": "La catégorie contient <code><nowiki>__HIDDENCAT__</nowiki></code> dans son contenu, ce qui empêche son affichage dans la zone des liens de catégorie sur les pages, par défaut.",
        "trackingcategories-nodesc": "Aucune description disponible.",
        "trackingcategories-disabled": "La catégorie est désactivée",
        "mailnologin": "Pas d'adresse d'expéditeur",
        "emailuser-title-notarget": "Envoyer un courriel à l'utilisateur",
        "emailpage": "Envoyer un courriel à l'utilisateur",
        "emailpagetext": "Vous pouvez utiliser le formulaire ci-dessous pour envoyer un courriel à {{GENDER:$1|cet utilisateur|cette utilisatrice}}.\nL'adresse électronique que vous avez indiquée dans [[Special:Preferences|vos préférences]] apparaîtra dans le champ « Expéditeur » de votre message ; ainsi, le destinataire pourra vous répondre directement.",
-       "defemailsubject": "{{SITENAME}} Courriel de l'utilisateur « $1 »",
+       "defemailsubject": "Courriel de {{SITENAME}} de l'utilisateur « $1 »",
        "usermaildisabled": "L'envoi de courriels entre utilisateurs est désactivé",
        "usermaildisabledtext": "Vous ne pouvez pas envoyer de courriels à d'autres utilisateurs sur ce wiki",
        "noemailtitle": "Aucune adresse de courriel",
        "mywatchlist": "Liste de suivi",
        "watchlistfor2": "Pour $1 $2",
        "nowatchlist": "Votre liste de suivi ne référence aucune page.",
-       "watchlistanontext": "Veuillez vous $1 pour visualiser ou modifier les éléments de votre liste de suivi.",
+       "watchlistanontext": "Veuillez vous connecter pour visualiser ou modifier les éléments de votre liste de suivi.",
        "watchnologin": "Non connecté",
        "addwatch": "Ajouter à la liste de suivi",
        "addedwatchtext": "La page « [[:$1]] » a été ajoutée à votre [[Special:Watchlist|liste de suivi]].\nLes prochaines modifications de cette page et de la page de discussion associée y seront répertoriées.",
        "watchlist-details": "{{PLURAL:$1|$1 page|$1 pages}} dans votre liste de suivi, sans compter les pages de discussion.",
        "wlheader-enotif": "La notification par courriel est activée.",
        "wlheader-showupdated": "Les pages qui ont été modifiées depuis votre dernière visite sont affichées en '''gras'''.",
-       "wlnote2": "Ci-dessous les modifications dans {{PLURAL:$1|la dernière heure|les <strong>$1</strong> dernières heures}}, à partir de $2, $3.",
+       "wlnote": "Ci-dessous {{PLURAL:$1|figure la dernière modification effectuée|figurent les <strong>$1</strong> dernières modifications effectuées}} durant {{PLURAL:$2|la dernière heure|les <strong>$2</strong> dernières heures}}, depuis $3, $4.",
        "wlshowlast": "Montrer les dernières $1 heures, les derniers $2 jours ou bien $3",
        "watchlist-options": "Options de la liste de suivi",
        "watching": "Suivi…",
        "exbeforeblank": "contenait avant blanchiment « $1 »",
        "delete-confirm": "Supprimer « $1 »",
        "delete-legend": "Supprimer",
-       "historywarning": "'''Attention :''' la page que vous êtes sur le point de supprimer a un historique avec environ $1 {{PLURAL:$1|version|versions}} :",
+       "historywarning": "<strong>Attention :</strong> la page que vous êtes sur le point de supprimer a un historique avec $1 {{PLURAL:$1|version|versions}} :",
        "confirmdeletetext": "Vous êtes sur le point de supprimer une page ou un fichier, ainsi que toutes ses versions antérieures historisées. Veuillez confirmer que c’est bien là ce que vous voulez faire, que vous en comprenez les conséquences et que vous faites ceci en accord avec les [[{{MediaWiki:Policy-url}}|règles internes]].",
        "actioncomplete": "Action effectuée",
        "actionfailed": "L'action a échoué",
        "delete-edit-reasonlist": "Modifier les motifs de suppression de page",
        "delete-toobig": "Cette page possède un historique important de modifications, dépassant $1 version{{PLURAL:$1||s}}.\nLa suppression de telles pages a été restreinte pour prévenir des perturbations accidentelles de {{SITENAME}}.",
        "delete-warning-toobig": "Cette page possède un historique important de modifications, dépassant $1 version{{PLURAL:$1||s}}.\nLa supprimer peut perturber le fonctionnement de la base de données de {{SITENAME}} ;\nveuiller ne procéder qu'avec prudence.",
+       "deleteprotected": "Vous ne pouvez pas supprimer cette page car elle a été protégée.",
        "deleting-backlinks-warning": "'''Attention :''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|D’autres pages]] ont un lien vers ou incorporent la page que vous allez supprimer.",
        "rollback": "Révoquer les modifications",
        "rollback_short": "Révoquer",
        "autoblockid": "Blocage automatique #$1",
        "block": "Bloquer l’utilisateur",
        "unblock": "Débloquer l’utilisateur",
-       "blockip": "Bloquer l’utilisateur",
+       "blockip": "Bloquer l’{{GENDER:$1|utilisateur|utilisatrice}}",
        "blockip-legend": "Bloquer l’utilisateur",
        "blockiptext": "Utilisez le formulaire ci-dessous pour bloquer les tentatives de modification faites à partir d’une adresse IP spécifique ou d’un nom d’utilisateur.\nUne telle mesure ne devrait être prise que pour prévenir le vandalisme et en accord avec les [[{{MediaWiki:Policy-url}}|règles internes]].\nDonnez ci-dessous un motif précis (par exemple en citant les pages qui ont été vandalisées).",
        "ipaddressorusername": "Adresse IP ou nom d'utilisateur :",
        "ipb-unblock-addr": "Débloquer $1",
        "ipb-unblock": "Débloquer un compte utilisateur ou une adresse IP",
        "ipb-blocklist": "Voir les blocages existants",
-       "ipb-blocklist-contribs": "Contributions pour $1",
+       "ipb-blocklist-contribs": "Contributions pour {{GENDER:$1|$1}}",
        "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",
        "unblocked": "[[User:$1|$1]] a été débloqué{{GENDER:$1||e}}",
        "unblocked-range": "Le compte $1 a été débloqué",
        "unblocked-id": "Le blocage $1 a été enlevé",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] a été débloqué.",
        "blocklist": "Utilisateurs bloqués",
        "ipblocklist": "Utilisateurs bloqués",
        "ipblocklist-legend": "Chercher un utilisateur bloqué",
        "import": "Importer des pages",
        "importinterwiki": "Importation inter-wiki",
        "import-interwiki-text": "Sélectionnez un wiki et un titre de page à importer.\nLes dates des versions et les noms des contributeurs seront préservés.\nToutes les actions d'importation inter-wiki sont consignées dans l'[[Special:Log/import|historique des importations]].",
-       "import-interwiki-source": "Wiki et page sources :",
+       "import-interwiki-sourcewiki": "Wiki source :",
+       "import-interwiki-sourcepage": "Page source :",
        "import-interwiki-history": "Copier toutes les versions de l’historique de cette page",
        "import-interwiki-templates": "Inclure tous les modèles",
        "import-interwiki-submit": "Importer",
        "import-upload": "Import de données XML",
        "import-token-mismatch": "Perte des données de session. Veuillez réessayez.",
        "import-invalid-interwiki": "Impossible d'importer depuis le wiki spécifié.",
-       "import-error-edit": "La page « $1 » n'a pas été importée parce que vous n'êtes pas autorisés à la modifier.",
-       "import-error-create": "La page « $1 » n'a pas été importée parce que vous n'êtes pas autorisés à la créer.",
-       "import-error-interwiki": "La page « $1 » n'est pas importée parce que son nom est réservé pour un lien externe (interwiki).",
-       "import-error-special": "La page « $1 » n'est pas importée parce qu'elle appartient à un espace de noms spécial qui n'en autorise aucune.",
-       "import-error-invalid": "Page « $1 » n'est pas importée parce que son nom n'est pas valide.",
+       "import-error-edit": "La page « $1 » n’a pas été importée parce que vous n’êtes pas autorisé à la modifier.",
+       "import-error-create": "La page « $1 » n’a pas été importée parce que vous n’êtes pas autorisé à la créer.",
+       "import-error-interwiki": "La page « $1 » n’a pas été importée parce que son nom est réservé pour un lien externe (interwiki).",
+       "import-error-special": "La page « $1 » n’a pas été importée parce qu’elle appartient à un espace de noms spécial qui n’autorise aucune page.",
+       "import-error-invalid": "Page « $1 » n’a pas été importée parce que le nom sous lequel elle aurait été importée n’est pas valide sur ce wiki.",
        "import-error-unserialize": "La révision $2 de la page « $1 » ne peut pas être désérialisée. La révision est indiquée comme utilisant le modèle de contenu $3 sérialisé en $4.",
        "import-error-bad-location": "La révision $2 utilisant le modèle de contenu $3 n’a pas pu être stocké sur « $1 » sur ce wiki, car ce modèle n’est pas supporté sur cette page.",
        "import-options-wrong": "{{PLURAL:$2|Mauvaise option|Mauvaises options}} : <nowiki>$1</nowiki>",
        "importlogpage": "Journal des importations",
        "importlogpagetext": "Importations administratives de pages d'autres wikis, avec leur historique de modification.",
        "import-logentry-upload": "a importé [[$1]] par envoi de fichier",
-       "import-logentry-upload-detail": "$1 version{{PLURAL:$1||s}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|révision importée|révisions importées}}",
        "import-logentry-interwiki": "a importé $1 d'un wiki à l'autre",
-       "import-logentry-interwiki-detail": "$1 version{{PLURAL:$1||s}} depuis $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|révision importée|révisions importées}} depuis $2",
        "javascripttest": "Test de JavaScript",
        "javascripttest-title": "Exécution des tests $1",
        "javascripttest-pagetext-noframework": "Cette page est réservée pour l'exécution des tests JavaScript.",
        "tooltip-ca-nstab-help": "Voir la page d'aide",
        "tooltip-ca-nstab-category": "Voir la page de la catégorie",
        "tooltip-minoredit": "Marquer mes modifications comme mineures",
-       "tooltip-save": "Enregister vos modifications",
+       "tooltip-save": "Enregistrer vos modifications",
        "tooltip-preview": "Merci de prévisualiser vos modifications avant de les publier",
        "tooltip-diff": "Affiche les modifications que vous avez apportées au texte",
        "tooltip-compareselectedversions": "Afficher les différences entre deux versions de cette page",
        "autosumm-replace": "Contenu remplacé par « $1 »",
        "autoredircomment": "Page redirigée vers [[$1]]",
        "autosumm-new": "Page créée avec « $1 »",
+       "autosumm-newblank": "Page vide créée",
        "size-bytes": "$1&nbsp;o",
        "size-kilobytes": "$1&nbsp;Kio",
        "size-megabytes": "$1&nbsp;Mio",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discussion]])",
        "unknown_extension_tag": "Balise d’extension « $1 » inconnue",
        "duplicate-defaultsort": "Attention : la clé de tri par défaut « $2 » écrase la précédente clé « $1 ».",
+       "duplicate-displaytitle": "<strong>Attention :</strong> Le titre d'affichage «$2» remplace l'ancien titre d'affichage «$1».",
        "version": "Version",
        "version-extensions": "Extensions installées",
        "version-skins": "Habillages installés",
        "logentry-rights-rights": "$1 {{GENDER:$2|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",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|a téléchargé}} une nouvelle version de $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|a téléchargé}} $3",
        "rightsnone": "(aucun)",
-       "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 et le navigateur que vous utilisez.",
+       "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-subject": "Objet :",
        "feedback-message": "Message :",
        "feedback-cancel": "Annuler",
        "action-pagelang": "changer la langue de la page",
        "log-name-pagelang": "Tracer les changements de langue",
        "log-description-pagelang": "Ceci est un journal des changements dans les langues des pages.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|a changé}} la langue de la page $3 de $4 à $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|a changé}} la langue de la page $3 de $4 à $5.",
+       "default-skin-not-found": "Oups ! L’habillage par défaut pour votre wiki, défini par <code dir=\"ltr\">$wgDefaultSkin</code> comme <code>$1</code>, n’est pas disponible.\n\nVotre installation semble inclure les habillages suivants. Voyez [https://www.mediawiki.org/wiki/Manual:Skin_configuration le manuel de configuration des habillages] pour savoir comment les activer et choisir celui par défaut.\n\n$2\n\n; Si vous venez juste d’installer MediaWiki :\n: Vous l’avez probablement installé depuis git, ou directement depuis le code source avec une autre méthode. C’est normal. Essayez d’installer des habillages depuis [https://www.mediawiki.org/wiki/Category:All_skins le répertoire des habillages de mediawiki.org], en:\n:* Téléchargeant le [https://www.mediawiki.org/wiki/Download fichier tar de l’installeur], qui comprend plusieurs habillages et extensions. Vous pouvez copier et coller le répertoire <code>skins/</code> depuis là.\n:* Clonant un des dépôts <code>mediawiki/skins/*</code> via git dans le répertoire <code dir=\"ltr\">skins/</code> de votre installation de MediaWiki.\n: Faire ainsi ne devrait pas interférer avec votre dépôt git, si vous êtes un développeur de MediaWiki.\n\n; Si vous venez juste de mettre à jour MediaWiki :\n: MediaWiki 1.24 et au-delà n’active plus automatiquement les habillages installés (voyez [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery le manuel sur la découverte automatique des habillages]). Vous pouvez coller les lignes suivantes dans <code>LocalSettings.php</code> pour activer tous les habillages actuellement installés :\n\n<pre dir=\"ltr\">$3</pre>\n\n; Si vous venez de modifier <code>LocalSettings.php</code> :\n: Vérifiez deux fois le nom des habillages pour éviter les erreurs de frappe.",
+       "default-skin-not-found-no-skins": "Oups ! L’habillage par défaut pour votre wiki , défini par <code>$wgDefaultSkin</code> comme <code>$1</code>, n’est pas disponible.\n\nVous n’avez aucun habillage d’installé.\n\n; Si vous venez juste d’installer ou de mettre à jour MediaWiki :\n: Vous l’avez sans doute fait depuis git, ou directement depuis le code source avec une autre méthode. C’est normal. MediaWiki 1.24 et au-delà n’inclut aucun habillage dans le dépôt principal. Essayez d’installer des habillages depuis [https://www.mediawiki.org/wiki/Category:All_skins le répertoire des habillages de mediawiki.org], en :\n:* Téléchargeant [https://www.mediawiki.org/wiki/Download le fichier tar de l’installeur], qui comprend différents habillages et extensions. Vous pouvez copier et coller le répertoire <code>skins/</code> depuis là.\n:*Clonant un des dépôts <code>mediawiki/skins/*</code> via git dans le répertoire <code dir=\"ltr\">skins/</code> de votre installation de MediaWiki.\n: Faire ainsi ne devrait pas interférer avec votre dépôt git si vous êtes un développeur de MediaWiki. Voyez [https://www.mediawiki.org/wiki/Manual:Skin_configuration le manuel de la configuration des habillages] pour des instructions sur la manière d’activer les habillages et choisir celui par défaut.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (activé)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''désactivé''')"
 }
index 02f26b9..29c6d43 100644 (file)
        "talkpagelinktext": "discutar",
        "specialpage": "Pâge spèciâla",
        "personaltools": "Outils a sè",
-       "postcomment": "Novèla sèccion",
        "articlepage": "Vêde la pâge de contegnu",
        "talk": "Discussion",
        "views": "Vues",
        "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|(ye)}} a betar a jorn voutron compto de defôr.",
        "login": "Branchement",
        "nav-login-createaccount": "Sè branchiér / fâre un compto",
-       "loginprompt": "Vos dête activar los tèmouens (''cookies'') por vos branchiér a {{SITENAME}}.",
        "userlogin": "Sè branchiér / fâre un compto",
        "userloginnocreate": "Sè branchiér",
        "logout": "Sè dèbranchiér",
        "searchprofile-advanced-tooltip": "Chouèsir los èspâços de noms por la rechèrche",
        "search-result-size": "$1 ($2 mot{{PLURAL:$2||s}})",
        "search-result-category-size": "$1 membro{{PLURAL:$1||s}} ($2 sot-catègorie{{PLURAL:$2||s}}, $3 fichiér{{PLURAL:$3||s}})",
-       "search-result-score": "Rapôrt : $1%",
        "search-redirect": "(redirèccion dês $1)",
        "search-section": "(sèccion $1)",
        "search-suggest": "Voléd-vos dére : $1",
        "uploadwarning": "Semonce pendent lo tèlèchargement",
        "uploadwarning-text": "Se vos plét, changiéd la dèscripcion du fichiér ce-desot et pués tornâd èprovar.",
        "savefile": "Encartar lo fichiér",
-       "uploadedimage": "at tèlèchargiê « [[$1]] »",
-       "overwroteimage": "at tèlèchargiê na novèla vèrsion de « [[$1]] »",
        "uploaddisabled": "Tèlèchargements dèsactivâs.",
        "copyuploaddisabled": "Tèlèchargement per URL dèsactivâ.",
        "uploaddisabledtext": "Los tèlèchargements de fichiérs sont dèsactivâs.",
        "watchlist-details": "Y at $1 pâge{{PLURAL:$1||s}} dedens voutra lista de siuvu, sen comptar 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 $3",
        "watchlist-options": "Chouèx de la lista de siuvu",
        "watching": "Siuvu...",
        "duplicate-defaultsort": "'''Atencion :''' la cllâf de tri per dèfôt « $2 » ècllafe cela « $1 ».",
        "version": "Vèrsion",
        "version-extensions": "Èxtensions enstalâs",
+       "version-skins": "Habelyâjos",
        "version-specialpages": "Pâges spèciâles",
        "version-parserhooks": "Grèfons du parsor",
        "version-variables": "Variâbles",
        "version-antispam": "Prèvencion du spame",
-       "version-skins": "Habelyâjos",
        "version-other": "De totes sôrtes",
        "version-mediahandlers": "Maneyors de mèdia",
        "version-hooks": "Grèfons",
index 6bb0457..f37822e 100644 (file)
@@ -24,6 +24,7 @@
        "tog-watchdefault": "Salew feranert sidjen an datein leewen uun't uug behual",
        "tog-watchmoves": "Salew fersköwen sidjen an datein leewen uun't uug behual",
        "tog-watchdeletion": "Salew stregen sidjen an datein leewen uun't uug behual",
+       "tog-watchrollback": "Sidjen, diar ik turagsaat haa, uun't uug behual",
        "tog-minordefault": "Aanj feranrangen üs \"letjen\" kääntiakne",
        "tog-previewontop": "\"Iarst ans luke\" boowen faan't wönang tu bewerkin",
        "tog-previewonfirst": "Bi't iarst bewerkin \"iarst ans luke\" uunwise",
        "moredotdotdot": "Muar ...",
        "morenotlisted": "Detdiar list as ei komplet.",
        "mypage": "Sidj",
-       "mytalk": "Diskusjuun",
+       "mytalk": "Diskuschuun",
        "anontalk": "Diskusjuunssidj faan detdiar IP",
        "navigation": "Nawigatjuun",
        "and": "&#32;an",
        "unprotectthispage": "Sääkering aphääwe",
        "newpage": "Nei sidj",
        "talkpage": "Detdiar sidj diskutiare",
-       "talkpagelinktext": "Diskusjuun",
+       "talkpagelinktext": "Diskuschuun",
        "specialpage": "Spezial-sidj",
        "personaltools": "Min werktjüügen",
-       "postcomment": "Nei kirew",
        "articlepage": "Artiikel wise",
-       "talk": "Diskusjuun",
+       "talk": "Diskuschuun",
        "views": "Uunsichten",
        "toolbox": "Werktjüügen",
        "userpage": "Brükersidj uunwise",
        "templatepage": "Föörlaagensidj uunwise",
        "viewhelppage": "Halepsidj uunwise",
        "categorypage": "Kategoriisidj uunwise",
-       "viewtalkpage": "Diskusjuun uunluke",
+       "viewtalkpage": "Diskuschuun uunluke",
        "otherlanguages": "Uun ööder spriaken",
        "redirectedfrom": "(Widjerfeerd faan $1)",
        "redirectpagesub": "Widjerfeerang",
        "hidetoc": "Fersteeg",
        "collapsible-collapse": "Tuupdoble",
        "collapsible-expand": "Wise",
+       "confirmable-confirm": "Beest {{GENDER:$1|dü}} seeker?",
+       "confirmable-yes": "Ja",
+       "confirmable-no": "Naan",
        "thisisdeleted": "$1 uunluke of weder iinstel",
        "viewdeleted": "$1 uunluke?",
        "restorelink": "$1 {{PLURAL:$1|stregen werjuun|stregen werjuunen}}",
        "invalidtitle-knownnamespace": "Ferkiard auerskraft uun di nöömrüm „$2“ an tekst „$3“",
        "invalidtitle-unknownnamespace": "Ferkiard auerskraft uun di ünbekäänd nöömrüm „$1“ an tekst „$2“",
        "exception-nologin": "Ei uunmeldet",
-       "exception-nologin-text": "Wees so gud an [[Special:Userlogin|melde di uun]], am detdiar sidj of aktjuun ütjtufeeren.",
+       "exception-nologin-text": "Wees so gud an melde di uun, am detdiar sidj of aktjuun ütjtufeeren.",
        "exception-nologin-text-manual": "Wees so gud an $1 , am detdiar sidj of aktjuun ütjtufeeren.",
        "virus-badscanner": "Ferkiard iinstelang: Ünbekäänd wiirenscanner: ''$1''",
        "virus-scanfailed": "scan ging skiaf (code $1)",
        "externaldberror": "Deer läit en fäägel bai jü äkstärn autentifisiiring for, unti dü möist din äkstärn brükerkonto äi aktualisiire.",
        "login": "Uunmelde",
        "nav-login-createaccount": "Melde di uun of skriiw di iin",
-       "loginprompt": "För't uunmeldin tu {{SITENAME}} skel bi dan browser cookies aktiwiaret wees.",
        "userlogin": "Melde di uun of skriiw di iin",
        "userloginnocreate": "Uunmelde",
        "logout": "Ufmelde",
        "userlogin-resetlink": "Heest dü din login dooten ferjiden?",
        "userlogin-resetpassword-link": "Paaswurd ferjiden?",
        "userlogin-helplink2": "Halep bi't uunmeldin",
-       "userlogin-loggedin": "Du beest al üs {{GENDER:$1|$1}} uunmeldet.\nBrük det formulaar diar oner, am di mä en öödern nööm uuntumeldin.",
-       "userlogin-createanother": "En ööder brükerkonto iinracht",
        "createacct-emailrequired": "E-mail adres",
        "createacct-emailoptional": "E-mail adres (optional)",
        "createacct-email-ph": "Du din e-mail adres iin",
        "preview": "Iarst ans luke",
        "showpreview": "Iarst ans luke",
        "showdiff": "Feranrangen wise",
-       "anoneditwarning": "'''Paase üüb:''' Dü bewerkest detdiar sidj anonüüm. Wan dü det seekerst, woort din aktuel IP-adres uun a ferluup aptiakent, an as diarmä '''för arken''' iintusen.",
+       "blankarticle": "<strong>Paase üüb:</strong> Dü maagest en leesag sidj.\nWan dü üüb \"{{int:savearticle}}\" trakst, woort det sidj iinracht saner wat uun.",
+       "anoneditwarning": "'''Paase üüb:''' Dü beest ei uunmeldet. Din aktuel IP-adres komt tu sen, wan dü feranrangen föörnamst. Wan dü di <strong>[$1 uunmeldest]</strong> of <strong>[$2 en konto iinrachtst]</strong>, wurd din feranrangen mä dan brükernööm ferbünjen, tuup mä ööder föördialen.",
        "anonpreviewwarning": "\"Dü beest ei uunmeldet. Bi't seekrin woort din IP-adres uun a ferluup faan werjuunen aptiakent.\"",
        "missingsummary": "'''Paase üüb:''' Dü heest det ei tuupfaadet.\nWan dü det sidj seekerst, woort det saner en kurtfaadet beskriiwang auernimen.",
        "missingcommenttext": "Faade det oner tuup.",
        "parser-template-recursion-depth-warning": "Tuföl föörlaagen uun föörlaagen ($1)",
        "language-converter-depth-warning": "Spriakenkonwerter auerläästet ($1)",
        "node-count-exceeded-category": "Jodiar sidjen haa tuföl ferbinjangen (nodes)",
-       "node-count-exceeded-category-desc": "En kategorii för sidjen mä tuföl knooter (nodes).",
+       "node-count-exceeded-category-desc": "Detdiar sidj brükt tuföl knooter (nodes).",
        "node-count-exceeded-warning": "Detdiar sidj hää tuföl ferbinjangen (nodes)",
        "expansion-depth-exceeded-category": "Jodiar sidjen haa tuföl ütjwidjangen (expansion)",
-       "expansion-depth-exceeded-category-desc": "Det as en kategorii för sidjen mä tuföl ütjwidjangen.",
+       "expansion-depth-exceeded-category-desc": "Detdiar sidj hää tuföl ütjwidjangen.",
        "expansion-depth-exceeded-warning": "Detdiar sidj hää tuföl ütjwidjangen (expansion)",
        "parser-unstrip-loop-warning": "Diar as en jinsidjag ferwisang",
        "parser-unstrip-recursion-limit": "Tuföl jinsidjag ferwisangen bi $1",
        "undo-failure": "Det feranrang küd ei stregen wurd, auer di kirew uuntesken feranert wurden as.",
        "undo-norev": "Det feranrang küd ei turagsaat wurd, auer diar niks as of auer det sidj stregen wurden as.",
        "undo-nochange": "Detdiar feranrang as wel al ans turagsaat wurden.",
-       "undo-summary": "Feranrang $1 faan [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskusjuun]]) turagsaat.",
+       "undo-summary": "Feranrang $1 faan [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskuschuun]]) turagsaat.",
        "undo-summary-username-hidden": "Feranrang $1 faan en ferbürgenen brüker turagsaat",
        "cantcreateaccounttitle": "Det brükerkonto koon ei iinracht wurd",
        "cantcreateaccount-text": "Det iinrachten faan en brükerkonto faan det IP-adres '''($1)''' as faan [[User:$3|$3]] speret wurden.\n\nGrünj för det sper: ''$2''",
        "rev-deleted-event": "(Logbuk-iindrach stregen)",
        "rev-deleted-user-contribs": "[Brükernööm of IP-adres wechnimen - Feranrangen uun bidracher ferbürgen]",
        "rev-deleted-text-permission": "Detdiar werjuun as '''stregen''' wurden.\nUun't [{{fullurl:{{#special:Log}}/delete|page={{FULLPAGENAMEE}}}} strik-logbuk] stäänt muar diartu.",
+       "rev-suppressed-text-permission": "Detdiar werjuun as '''ferbürgen''' wurden.\nDü könst det noch uunluke uun't [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} fersteeg-logbuk].",
        "rev-deleted-text-unhide": "Detdiar werjuun as '''stregen''' wurden.\nUun't [{{fullurl:{{#special:Log}}/delete|page={{FULLPAGENAMEE}}}} strik-logbuk] stäänt muar diartu.\nDü könst [$1 detdiar werjuun uunluke], wan dü wel.",
        "rev-suppressed-text-unhide": "Detdiar werjuun as '''ferbürgen''' wurden.\nUun't [{{fullurl:{{#special:Log}}/suppress|page={{FULLPAGENAMEE}}}} fersteeg-logbuk] stäänt muar diartu.\nDü könst [$1 detdiar werjuun uunluke], wan dü wel.",
        "rev-deleted-text-view": "Detdiar werjuun as '''stregen''' wurden.\nDü könst det noch uunluke. Uun't [{{fullurl:{{#special:Log}}/delete|page={{FULLPAGENAMEE}}}} strik-logbuk] stäänt muar diartu.",
        "revdelete-text-text": "Stregen werjuunen bliiw uun't werjuunshistoore, man dialen diarfaan san ei för arken tu sen.",
        "revdelete-text-file": "Stregen datei-werjuunen bliiw uun't werjuunshistoore, man dialen diarfaan san ei för arken tu sen.",
        "logdelete-text": "Stregen logbuk-iindracher bliiw uun a logbuken, man dialen diarfaan san ei för arken tu sen.",
-       "revdelete-text-others": "Ööder administratooren faan {{SITENAME}} kön widjerhen ales uunluke an kön det uk weder mä detheer spezial-sidj iinstel, wan diar niks ööders uun a wai as.",
+       "revdelete-text-others": "Ööder administratooren kön widjerhen ales uunluke an kön det uk weder iinstel, wan diar niks ööders uun a wai as.",
        "revdelete-confirm": "Ferseekre noch ans, dat dü det würelk du wel, dat dü witjst, wat dü dääst, an dat det mä a [[{{MediaWiki:Policy-url}}|bestemangen]] auerian stemet.",
        "revdelete-suppress-text": "Det skul '''bluas''' onertrakt wurd bi:\n* Persöönelk informatsjuunen, diar näämen wat uungung\n*: ''Adresen, tilefoonnumern, ferseekerangsnumern an sowat''",
        "revdelete-legend": "Iinstelangen, hüföl tu sen wees skal",
        "searchprofile-advanced-tooltip": "Uun ööder nöömrümer schük",
        "search-result-size": "$1 ({{PLURAL:$2|1 wurd|$2 wurden}})",
        "search-result-category-size": "{{PLURAL:$1|1 sidj|$1 sidjen}} ({{PLURAL:$2|1 onerkategorii|$2 onerkategoriin}}, {{PLURAL:$3|1 datei|$3 datein}})",
-       "search-result-score": "Relewans: $1 %",
        "search-redirect": "(widjerfeerd faan „$1“)",
        "search-section": "(kirew $1)",
        "search-file-match": "(fünjen tekst)",
        "searchall": "aaltumaal",
        "showingresults": "Heer {{PLURAL:$1|as '''1''' resultaat|san '''$1''' resultaaten}}, jo began mä numer '''$2.'''",
        "showingresultsinrange": "Oner {{PLURAL:$1|woort <strong>ian</strong> resultaat|wurd bit tu <strong>$1</strong> resultaaten}} tesken <strong>$2</strong> an <strong>$3</strong> uunwiset.",
-       "showingresultsheader": "{{PLURAL:$5|resultaat '''$1''' faan '''$3'''|resultaaten '''$1-$2''' faan '''$3'''}}, för '''$4.'''",
        "search-nonefound": "För din uunfraag san nian resultaaten fünjen wurden.",
        "powersearch-legend": "Ütjwidjet schüken",
        "powersearch-ns": "Schük uun nöömrümer:",
        "preferences": "Iinstelangen",
        "mypreferences": "Iinstelangen",
        "prefs-edits": "Taal faan feranrangen:",
-       "prefsnologintext2": "Wees so gud an $1 , am din brüker-iinstelangen fäästtuleien.",
+       "prefsnologintext2": "Wees so gud an meldi di uun, am din brüker-iinstelangen tu feranrin.",
        "prefs-skin": "Skak",
        "skin-preview": "Föörskau",
        "datedefault": "Föör-iinstelang",
        "right-deletedtext": "Stregen tekst an feranrangen tesken stregen werjuunen uunluke",
        "right-browsearchive": "Schük stregen sidjen",
        "right-undelete": "Stregen sidjen turaghaale",
-       "right-suppressrevision": "Werjuunen uunluke an turaghaale, diar uk för administratooren ei tu sen san",
+       "right-suppressrevision": "Werjuunen faan sidjen för arke brüker fersteeg, turaghaale an uunluke.",
+       "right-viewsuppressed": "För arke brüker ferbürgen werjuunen uunluke.",
        "right-suppressionlog": "Priwoot logbuken uunluke",
        "right-block": "Brükern spere (för't skriiwen)",
        "right-blockemail": "Brüker spere för't e-mail schüüren",
        "uploadwarning": "Wäärnang",
        "uploadwarning-text": "Feranre det datei-beskriiwang an ferschük det noch ans nei.",
        "savefile": "Datei seekre",
-       "uploadedimage": "hää \"[[$1]]\" huuchschüürd",
-       "overwroteimage": "hää en nei werjuun faan „[[$1]]“ huuchschüürd",
        "uploaddisabled": "Huuchschüüren as ei aktiwiaret",
        "copyuploaddisabled": "Huuchschüüren faan URLs as ei aktiwiaret.",
        "uploaddisabledtext": "Det huuchschüüren faan datein as ei aktiwiaret.",
        "randomincategory": "Tufelag sidj uun't kategorii",
        "randomincategory-invalidcategory": "\"$1\" as üs kategoriinööm ei tuläät.",
        "randomincategory-nopages": "Diar san nian sidjen uun [[:Category:$1]].",
-       "randomincategory-selectcategory": "Tufelag sidj uun't kategorii: $1 $2.",
-       "randomincategory-selectcategory-submit": "Widjer",
        "randomredirect": "Tufelag widjerfeerang",
        "randomredirect-nopages": "Uun di nöömrüm „$1“ san nian widjerfeerangen.",
        "statistics": "Statistik",
        "watchlist-details": "Dü behäälst {{PLURAL:$1|1 sidj|$1 sidjen}} uun't uug, diarbi wurd diskuschuunsidjen ei mätääld.",
        "wlheader-enotif": "Di e-mail siinst as aktiif.",
        "wlheader-showupdated": "Nei feranert sidjen wurd '''fäät''' uunwiset.",
-       "wlnote2": "Diar stun a feranrangen faan a leetst {{PLURAL:$1|stünj|<strong>$1</strong> stünjen}}, üüb a stant faan $2, $3.",
+       "wlnote": "Diar {{PLURAL:$1|stäänt det leetst feranrang|stun a leetst '''$1''' feranrangen}} faan a leetst {{PLURAL:$2|stünj|'''$2''' stünjen}}. Stant: $3, klook $4.",
        "wlshowlast": "Wise a feranrangen faan leetst $1 stünjen, $2 daar of $3.",
        "watchlist-options": "Iinstelangen för't uunwisin",
        "watching": "Uun't uug behual ...",
        "rollbacklinkcount-morethan": "Muar üs $1 {{PLURAL:$1|werjuun|werjuunen}} turagsaat",
        "rollbackfailed": "Bi't turagsaaten as wat skiaf gingen.",
        "cantrollback": "Det feranrang koon ei turagsaat wurd, diar san nian ööder skriiwern weesen.",
-       "alreadyrolled": "A anrangen faan [[User:$2|$2]] ([[User talk:$2|Diskusjuun]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) bi [[:$1]] kön ei turagsaat wurd. Diar hää uuntesken en öödern brüker det sidj feranert.\n\nDet leetst feranrang as faan [[User:$3|$3]] ([[User talk:$3|Diskusjuun]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
+       "alreadyrolled": "A feranrangen faan [[User:$2|$2]] ([[User talk:$2|Diskuschuun]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) bi [[:$1]] kön ei turagsaat wurd. Diar hää uuntesken en öödern brüker det sidj feranert.\n\nDet leetst feranrang as faan [[User:$3|$3]] ([[User talk:$3|Diskuschuun]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Tuupfaadet feranrang: ''„$1“''.",
-       "revertpage": "Feranrangen faan [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskusjuun]]) san üüb di leetst stant faan [[User:$1|$1]] turagsaat wurden.",
+       "revertpage": "Feranrangen faan [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskuschuun]]) san üüb di leetst stant faan [[User:$1|$1]] turagsaat wurden.",
        "revertpage-nouser": "Feranrangen faan en ferbürgenen brüker turagsaat an det leetst werjuun faan {{GENDER:$1|[[User:$1|$1]]}} weder iinsteld.",
        "rollback-success": "Feranrangen faan $1 turagsaat an det leetst werjuun faan $2 weder iinsteld.",
        "sessionfailure-title": "session feeler",
        "sp-contributions-deleted": "Stregen bidracher",
        "sp-contributions-uploads": "Huuchschüürd bilen",
        "sp-contributions-logs": "Logbuken",
-       "sp-contributions-talk": "Diskusjuun",
+       "sp-contributions-talk": "Diskuschuun",
        "sp-contributions-userrights": "Brükerrochten",
        "sp-contributions-blocked-notice": "Didiar brüker as speret. Det stäänt uun't sperlogbuk:",
        "sp-contributions-blocked-notice-anon": "Detdiar IP-adres as speret. Det stäänt uun't sperlogbuk:",
        "import": "Sidjen importiare",
        "importinterwiki": "Transwiki import",
        "import-interwiki-text": "Schük en Wiki an en sidj tu importiarin ütj. A werjuunen an brükernöömer bliiw erhäälen.\nTranswiki-import-aktjuunen wurd uun't [[Special:Log/import|Import-logbuk]] fäästhäälen.",
-       "import-interwiki-source": "Faan hün Wiki/sidj:",
        "import-interwiki-history": "Aal a werjuunen faan det sidj importiare",
        "import-interwiki-templates": "Mä aal a föörlaagen",
        "import-interwiki-submit": "Import",
        "tooltip-pt-userpage": "Din brükersidj",
        "tooltip-pt-anonuserpage": "Brükersidj faan det IP-adres, faan huar ütj dü werkest",
        "tooltip-pt-mytalk": "Din diskusjuunssidj",
-       "tooltip-pt-anontalk": "Diskusjuun auer feranrangen faan detdiar IP-adres",
+       "tooltip-pt-anontalk": "Diskuschuun auer feranrangen faan detdiar IP-adres",
        "tooltip-pt-preferences": "Min iinstelangen",
        "tooltip-pt-watchlist": "Sidjen, diar dü uun't uug behual wel",
        "tooltip-pt-mycontris": "List mä aanj bidracher",
        "tooltip-pt-login": "Wan dü di uunmeldest, heest dü muar mögelkhaiden. Dü säärst det oober ei.",
        "tooltip-pt-logout": "Ufmelde",
-       "tooltip-ca-talk": "Diskusjuun auer di artiikel",
+       "tooltip-ca-talk": "Diskuschuun auer di artiikel",
        "tooltip-ca-edit": "Sidj bewerke. Luke di det iarst ans uun, iar dü det seekerst.",
        "tooltip-ca-addsection": "Nei kirew began",
        "tooltip-ca-viewsource": "Detdiar sidj as seekert wurden.\nDü könst di kweltekst uunluke.",
        "scarytranscludefailed-httpstatus": "[Ufrepen faan föörlaagen för $1 as skiaf gingen: HTTP  $2]",
        "scarytranscludetoolong": "[URL as tu lung]",
        "deletedwhileediting": "'''Paase üüb:''' Det sidj as stregen wurden, üs dü diar jüst bi werket heest!\nUun't [{{fullurl:{{#special:Log}}|type=delete&page={{FULLPAGENAMEE}}}} Strik-logbuk] fanjst dü di grünj för't striken. Wan dü det sidj seekerst, woort det nei uunlaanj.",
-       "confirmrecreate": "Di brüker [[User:$1|$1]] ([[User talk:$1|Diskusjuun]]) hää det sidj stregen, üs dü diar jüst bi werket heest. Di grünj wiar:\n:''$2''\nFerseekre, dat dü det sidj würelk nei maage wel.",
-       "confirmrecreate-noreason": "Di brüker [[User:$1|$1 ]] ([[User talk:$1|Diskusjuun]]) hää det sidj stregen, huar dü jüst bi werket heest. Ferseekre, dat dü det sidj würelk nei maage wel.",
+       "confirmrecreate": "Di brüker [[User:$1|$1]] ([[User talk:$1|Diskuschuun]]) hää det sidj stregen, üs dü diar jüst bi werket heest. Di grünj wiar:\n:''$2''\nFerseekre, dat dü det sidj würelk nei maage wel.",
+       "confirmrecreate-noreason": "Di brüker [[User:$1|$1 ]] ([[User talk:$1|Diskuschuun]]) hää det sidj stregen, huar dü jüst bi werket heest. Ferseekre, dat dü det sidj würelk nei maage wel.",
        "recreate": "Nei maage",
        "confirm_purge_button": "OK",
        "confirm-purge-top": "Det sidj ütj a cache strik?",
        "watchlisttools-view": "Uun't uug behual: Feranrangen",
        "watchlisttools-edit": "Normool bewerke",
        "watchlisttools-raw": "Uun't listenformoot bewerke",
-       "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|Diskusjuun]])",
+       "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|Diskuschuun]])",
        "unknown_extension_tag": "Ünbekäänd ''tag'' „$1“",
        "duplicate-defaultsort": "'''Paase üüb:''' Di sortiarkai \"$2\" auerskraft di ual sortiarkai \"$1\"",
        "version": "Werjuun",
index ff1c4e3..18b5c72 100644 (file)
        "talkpagelinktext": "discussion",
        "specialpage": "Pagjine speciâl",
        "personaltools": "Imprescj personâi",
-       "postcomment": "Gnove sezion",
        "articlepage": "Cjale la vôs",
        "talk": "Discussion",
        "views": "Visitis",
        "yourdomainname": "Il to domini",
        "login": "Jentre",
        "nav-login-createaccount": "Regjistriti o jentre",
-       "loginprompt": "Tu âs di vê abilitâts i cookies par jentrâ in {{SITENAME}}.",
        "userlogin": "Regjistriti o jentre",
        "userloginnocreate": "Jentre",
        "logout": "Jes",
        "searchprofile-advanced-tooltip": "Cîr tai spazis dai nons personalizâts",
        "search-result-size": "$1 ({{PLURAL:$2|une peraule|$2 peraulis}})",
        "search-result-category-size": "{{PLURAL:$1|1 membri|$1 membris}} ({{PLURAL:$2|1 sotcategorie|$2 sotcategoriis}}, {{PLURAL:$3|1 file|$3 files}})",
-       "search-result-score": "Rilevance: $1%",
        "search-redirect": "(re-indreçament $1)",
        "search-section": "(sezion $1)",
        "search-suggest": "Forsit tu cirivis: $1",
        "filetype-missing": "Il file nol à une estension (par esempli \".jpg\").",
        "file-exists-duplicate": "Chest file al è un duplicât {{PLURAL:$1|dal file |dai files ca sot:}}",
        "savefile": "Salve file",
-       "uploadedimage": "cjamât sù \"$1\"",
-       "overwroteimage": "al à cjamât une gnove version di «[[$1]]»",
        "uploaddisabled": "Nus displâs, par cumò no si pues cjamâ sù robe.",
        "uploaddisabledtext": "Lis cjamadis di files a son disativadis.",
        "sourcefilename": "Non dal file origjinâl:",
        "watchlist-details": "{{PLURAL:$1|E je $1 pagjine tignude|A son $1 pagjinis tignudis}} di voli, cence contâ lis pagjinis di discussion.",
        "wlheader-enotif": "Notifiche par pueste eletroniche ativade.",
        "wlheader-showupdated": "Lis pagjinis gambiadis de ultime volte che tu lis âs cjaladis a son mostradis in '''gruessut'''",
+       "wlnote": "Ca sot {{PLURAL:$1|al è il cambiament plui recent|a son i '''$1''' cambiaments plui recents}} {{PLURAL:$2|inte ultime ore|intes '''$2''' oris passadis}}.",
        "wlshowlast": "Mostre ultimis $1 oris $2 zornadis $3",
        "watchlist-options": "Opzions pe liste dai tignûts di voli",
        "watching": "Daûr a zontâ aes pagjinis tignudis di voli...",
index 0851cc8..9c23ae8 100644 (file)
        "talkpagelinktext": "Oerlis",
        "specialpage": "Bysûndere side",
        "personaltools": "Persoanlike ynstellings",
-       "postcomment": "Skriuw in opmerking",
        "articlepage": "Side lêze",
        "talk": "Oerlis",
        "views": "Aspekten/aksjes",
        "externaldberror": "Der is in fout by it oanmelden by de database of jo hawwe gjin tastimming om jo ekstern account by te wurkjen.",
        "login": "Oanmelde",
        "nav-login-createaccount": "Oanmelde",
-       "loginprompt": "Jo moatte 'cookies' oanstean hawwe om yn jo oan te melden by {{SITENAME}}.",
        "userlogin": "Oanmelde",
        "userloginnocreate": "Ynlogge",
        "logout": "Ofmelde",
        "searchprofile-everything-tooltip": "Alle ynhâld trochsykje (ynklusyf oerlissiden)",
        "searchprofile-advanced-tooltip": "Sykje yn oanjûne nammerûmten",
        "search-result-size": "$1 ({{PLURAL:$2|1 wurd|$2 wurden}})",
-       "search-result-score": "Relevante: $1%",
        "search-redirect": "(trochferwizing $1)",
        "search-section": "(seksje $1)",
        "search-suggest": "Bedoele jo: $1",
        "file-deleted-duplicate": "In bestân idintyk oan dit bestân ([[:$1]]) is foarhinne fuorthelle.\nRieplachtsje it fuorthel-logboek foar't jo fierder geane.",
        "uploadwarning": "Oanbied-warskôging",
        "savefile": "Lis triem fêst",
-       "uploadedimage": " \"[[$1]]\" oanbean",
-       "overwroteimage": "hat in nije ferzje fan \"[[$1]]\" tafoege",
        "uploaddisabled": "Sorry, op dizze tsjinner kin net oanbean wurde.",
        "uploaddisabledtext": "It oanbieden fan triemmen is útskeakele.",
        "php-uploaddisabledtext": "PHP-triemuploads binne útskeakele. Kontrolearje a.j.w. de triem_uploads-ynstelling.",
        "unwatchthispage": "Ferjit dizze side",
        "notanarticle": "Dit kin net folge wurde.",
        "watchlist-details": "Jo folchlist hat {{PLURAL:$1|$1 side|$1 siden}}, oerlissiden net meiteld.",
+       "wlnote": "Dit {{PLURAL:$1|is de lêste feroaring|binne de lêste '''$1''' feroarings}} yn de lêste {{PLURAL:$2|oer|'''$2''' oeren}}.",
        "wlshowlast": "Lit feroarings sjen fan de lêste $1 oeren $2 dagen $3",
        "watching": "Dwaande mei op'e folchlist te setten ...",
        "unwatching": "Dwaande mei fan'e folchlist ôf te heljen ...",
index 0fe4dfa..42bf7e9 100644 (file)
        "talkpagelinktext": "Plé",
        "specialpage": "Leathanach Speisialta",
        "personaltools": "Do chuid uirlisí",
-       "postcomment": "Mír nua",
        "articlepage": "Féach ar an alt",
        "talk": "Plé",
        "views": "Radhairc",
        "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",
        "nav-login-createaccount": "Logáil isteach",
-       "loginprompt": "Tá sé riachtanach fianáin a chur i ngníomh chun logáil isteach a dhéanamh ag {{SITENAME}}.",
        "userlogin": "Logáil isteach / cruthaigh cuntas",
        "userloginnocreate": "Logáil isteach",
        "logout": "Logáil amach",
        "fileexists-forbidden": "Tá comhad eile leis an ainm seo ann fós, agus ní féidie é a forscríobh.\nMá theastáilann uait do chomhad a uaslódáil fós, téigh ar ais agus úsáid ainm nua, le do thoil. [[File:$1|thumb|center|$1]]",
        "uploadwarning": "Rabhadh suaslódála",
        "savefile": "Sábháil comhad",
-       "uploadedimage": "uaslódáladh \"[[$1]]\"",
        "uploaddisabled": "Tá brón orainn, ní féidir aon rud a uaslódáil faoi láthair.",
        "uploaddisabledtext": "Tá cosc ar uaslódáil comhad.",
        "uploadvirus": "Tá víreas ann sa comhad seo! Eolas: $1",
        "watchlist-details": "Tá tú ag faire ar {{PLURAL:$1|leathanach amháin|$1 leathanaigh}}, gan leathanaigh phlé a chur san áireamh.",
        "wlheader-enotif": "Cumasaíodh fógraí riomhphoist.",
        "wlheader-showupdated": "Tá '''cló trom''' ar leathanaigh a athraíodh ón uair is deireanaí a d'fhéach tú orthu.",
+       "wlnote": "Is {{PLURAL:$1|é seo thíos an t-athrú deireanach|iad seo thíos na '''$1''' athruithe deireanacha}} {{PLURAL:$2|san uair deireanach|sna '''$2''' uaire deireanacha}}.",
        "wlshowlast": "Líon na n-uair is déanaí le taispeáint: $1. Líon na laethanta is déanaí le taispeáint: $2. Taispeáin $3.",
        "watchlist-options": "Roghanna don liosta faire",
        "watching": "Ag faire...",
index ba65dc6..eca10f7 100644 (file)
        "talkpagelinktext": "Konuşmaa",
        "specialpage": "Maasus Sayfa",
        "personaltools": "Personal instrumentlär",
-       "postcomment": "Yorum ekle",
        "articlepage": "Yazıya bak",
        "talk": "Dartışma",
        "views": "Görünüşler",
        "yourdomainname": "Domen adınız",
        "login": "Gir",
        "nav-login-createaccount": "Gir / esap yarat",
-       "loginprompt": "Bak: {{SITENAME}} saytında sessiya açmaa için tarayıcınızda läazım cookies aktivat olsun. <br />\nKullanıcı adınız '''var nicä içersin'''gagauzça nışan, boşluk . Savaşın kullanıcı adınıza e-mail adresi '''girmemää'''.",
        "userlogin": "Gir / esap yarat",
        "logout": "Sessiyanı kapat",
        "userlogout": "Oturmaa kapat",
        "upload": "Fayl ükle",
        "uploadbtn": "Fayl ükle",
        "uploadlogpage": "Fayl üklemäk jurnalları",
-       "uploadedimage": "Üklenen: \"[[$1]]\"",
        "listfiles": "Pätret listası",
        "file-anchor-link": "Fayl",
        "filehist": "Fayl istoriyası",
index b15deea..5c67aa4 100644 (file)
        "talkpagelinktext": "谈詑",
        "specialpage": "特殊页",
        "personaltools": "个人工具",
-       "postcomment": "话滴想法",
        "articlepage": "看吖文章",
        "talk": "谈詑",
        "views": "眵",
        "externaldberror": "外部验证数据库出错,或倷更新伓正倷𠮶外部帐户。",
        "login": "登入",
        "nav-login-createaccount": "登入/新开只帐户",
-       "loginprompt": "要开到cookies才登入得正{{SITENAME}}。",
        "userlogin": "登入/新开只帐户",
        "userloginnocreate": "登入",
        "logout": "退出",
        "fileexists-shared-forbidden": "到共用档案库里度有嘞同名𠮶档案;请回头并换过只新𠮶名称来上传个只档案。[[File:$1|thumb|center|$1]]",
        "uploadwarning": "上传警告",
        "savefile": "保存盘案",
-       "uploadedimage": "上传正嘞\"[[$1]]\"",
-       "overwroteimage": "上传正嘞\"[[$1]]\"𠮶新版本",
        "uploaddisabled": "上传伓正",
        "uploaddisabledtext": "上传伓正文件到{{SITENAME}}。",
        "uploadscripted": "个只档案包到可能会误导网络浏览器错误解释𠮶 HTML 或脚本代码。",
        "watchlist-details": "$1只页面(伓算讨论页) 拖眏到哩",
        "wlheader-enotif": "启动嘞email通知功能。",
        "wlheader-showupdated": "上回倷眵𠮶页面改动𠮶部分用'''粗体'''显到",
+       "wlnote": "下底系最近'''$2'''钟头内𠮶最晏'''$1'''道修改:",
        "wlshowlast": "显示近来$1钟头$2日$3𠮶改动",
        "watchlist-options": "监视清单选项",
        "watching": "眏到...",
index 8320af5..8e2a350 100644 (file)
@@ -9,7 +9,9 @@
                        "Vipuser",
                        "Xiaomingyan",
                        "아라",
-                       "Mywood"
+                       "Mywood",
+                       "Impersonator 1",
+                       "LNDDYL"
                ]
        },
        "tog-underline": "下劃連結",
        "talkpagelinktext": "談詑",
        "specialpage": "特殊頁",
        "personaltools": "個人工具",
-       "postcomment": "話滴想法",
        "articlepage": "看吖文章",
        "talk": "談詑",
        "views": "望下",
        "externaldberror": "外部驗證資料庫出錯,或倷更新伓正倷嗰外部帳戶。",
        "login": "登入",
        "nav-login-createaccount": "登入/新開隻帳戶",
-       "loginprompt": "要開到cookies才登入得正{{SITENAME}}。",
        "userlogin": "登入/新開隻帳戶",
        "userloginnocreate": "登入",
        "logout": "退出",
        "fileexists-shared-forbidden": "到共用檔案庫裡度有嘞同名嗰檔案;請回頭並換過隻新嗰名稱來上傳箇隻檔案。[[File:$1|thumb|center|$1]]",
        "uploadwarning": "上傳警告",
        "savefile": "保存檔案",
-       "uploadedimage": "上傳正哩\"[[$1]]\"",
-       "overwroteimage": "上傳正哩\"[[$1]]\"嗰新版本",
        "uploaddisabled": "上傳伓正",
        "uploaddisabledtext": "上傳伓正文件到{{SITENAME}}。",
        "uploadscripted": "箇隻檔案包到可能會誤導網絡瀏覽器錯誤解釋嗰 HTML 或腳本代碼。",
        "watchlist-details": "$1隻頁面(伓算討論頁) 拕眏到哩",
        "wlheader-enotif": "啟動哩email通知功能。",
        "wlheader-showupdated": "上回倷眵嗰頁面改動嗰部分用'''粗體'''顯到",
+       "wlnote": "下底係最近'''$2'''鐘頭內嗰最晏'''$1'''道修改:",
        "wlshowlast": "顯示箇日子$1鐘頭$2日$3嗰改動",
        "watchlist-options": "監視清單選項",
        "watching": "眏到...",
index b329eb0..cd72433 100644 (file)
        "help": "Cobhair",
        "search": "Lorg",
        "searchbutton": "Lorg",
-       "go": "Rach",
-       "searcharticle": "Rach",
+       "go": "Siuthad",
+       "searcharticle": "Siuthad",
        "history": "Eachdraidh na duilleige",
        "history_short": "Eachdraidh",
        "updatedmarker": "air ùrachadh on turas mu dheireadh a thadhail mi air",
        "talkpagelinktext": "Deasbaireachd",
        "specialpage": "Duilleag shònraichte",
        "personaltools": "Innealan pearsanta",
-       "postcomment": "Earrann ùr",
        "articlepage": "Seall duilleag na susbainte",
        "talk": "Deasbaireachd",
        "views": "Tadhalan",
        "userlogin-yourpassword-ph": "Cuir a-steach am facal-faire agad",
        "createacct-yourpassword-ph": "Cuir a-steach facal-faire",
        "yourpasswordagain": "Ath-sgrìobh facal-faire",
-       "createacct-yourpasswordagain": "Dearbh am facal-faire",
+       "createacct-yourpasswordagain": "Dearbhaich am facal-faire",
        "createacct-yourpasswordagain-ph": "Cuir a-steach am facal-faire a-rithist",
        "remembermypassword": "Cuimhnich gu bheil mi air logadh a-steach air a' choimpiutair seo (suas gu $1 {{PLURAL:$1|latha|latha|làithean|latha}})",
        "userlogin-remembermypassword": "Cum air logadh a-steach mi",
        "externaldberror": "Thachair mearachd le dearbhadh an stòir-dhàta air neo chan eil cead agad an cunntas agad air an taobh a-muigh ùrachadh.",
        "login": "Log a-steach",
        "nav-login-createaccount": "Log a-steach / cruthaich cunntas",
-       "loginprompt": "Feumaidh briosgaidean a bhith ceadaichte mus dèan thu logadh a-steach do {{SITENAME}}.",
        "userlogin": "Log a-steach / cruthaich cunntas",
        "userloginnocreate": "Log a-steach",
        "logout": "Log a-mach",
        "emailauthenticated": "Chaidh an seòladh puist-d agad a dhearbhadh $2 aig $3.",
        "emailnotauthenticated": "Cha deach am post-d agad a dhearbhadh fhathast.\nCha dèid post-d a chur airson gin dhe na feartan a leanas.",
        "noemailprefs": "Sònraich post-d sna roghainnean agad gus na feartan seo a chur an comas.",
-       "emailconfirmlink": "Dearbh an seòladh puist-dhealain agad",
+       "emailconfirmlink": "Dearbhaich an seòladh puist-dhealain agad",
        "invalidemailaddress": "Chan urrainn dhuinn gabhail ris an t-seòladh seo a chionn 's gu bheil coltas cearr air.\nCuir a-steach seòladh san fhòrmat cheart no falamhaich an raon sin.",
        "cannotchangeemail": "Cha ghabh na puist-d a tha co-cheangailte ri cunntas atharrachadh air an uicipeid seo.",
        "emaildisabled": "Chan urrainn dhut puist-d a chur air an làrach seo.",
        "parser-unstrip-loop-warning": "Mhothaich sinn do lùb unstrip",
        "parser-unstrip-recursion-limit": "Chaidheas thairis air crìoch unstrip recursion ($1)",
        "converter-manual-rule-error": "Mhothaich sinn do mhearachd san riaghailt iompachadh làimhe airson cànan",
-       "undo-success": "Gabhaidh an deasachadh seo a neo-dhèanamh.\nThoir sùil air a' choimeas gu h-ìosal is dearbh gur e sin a tha fa-near dhut agus sàbhail na h-atharraichean gu h-ìosal gus neo-dhèanamh an deasachaidh a choileanadh.",
+       "undo-success": "Gabhaidh an deasachadh seo a neo-dhèanamh.\nThoir sùil air a' choimeas gu h-ìosal is dearbhaich gur e sin a tha fa-near dhut agus sàbhail na h-atharraichean gu h-ìosal gus neo-dhèanamh an deasachaidh a choileanadh.",
        "undo-failure": "Cha b' urrainn dhuinn an deasachadh a neo-dhèanamh air sgàth 's gun robh deasachaidhean eile sa mheadhan.",
        "undo-norev": "Cha b' urrainn dhuinn an deasachadh a neo-dhèanamh a chionn 's nach robh e ann no gun deach a sguabadh às.",
        "undo-nochange": "Tha coltas gun deach am mùthadh seo a neo-dhèanamh mu thràth.",
        "revdelete-text-file": "Nochdaidh tionndaidhean dhen fhaidhle a chaidh a sguabadh às ann an eachdraidh na duilleige fhathast ach chan fhaic buill a' phobaill cuid dhen t-susbaint aca.",
        "logdelete-text": "Nochdaidh tachartasan san loga a chaidh a sguabadh às ann an eachdraidh na duilleige fhathast ach chan fhaic buill a' phobaill cuid dhen t-susbaint aca.",
        "revdelete-text-others": "Gheibh rianairean eile air {{SITENAME}} cothrom air an t-susbaint fhalaichte fhathast agus is urrainn dhaibh an sguabadh às a neo-dhèanamh san dearbh eadar-aghaidh mur an deach cuingeachaidhean a bharrachd a chur orra.",
-       "revdelete-confirm": "Dearbh gu bheil thu airson seo a dhèanamh, gu bheil thu a' tuigsinn na thachras ri linn agus gu bheil thu a' dèanamh seo a-rèir [[{{MediaWiki:Policy-url}}|a' phoileasaidh]].",
+       "revdelete-confirm": "Dearbhaich gu bheil thu airson seo a dhèanamh, gu bheil thu a' tuigsinn na thachras ri linn agus gu bheil thu a' dèanamh seo a-rèir [[{{MediaWiki:Policy-url}}|a' phoileasaidh]].",
        "revdelete-suppress-text": "Cha bu chòir dhut mùchadh a chleachdadh <strong>ach</strong> ann an suidheachaidhean mar seo:\n* Fiosrachadh a dh'fhaodadh a bhith dìteachail\n* Fiosrachadh pearsanta a tha cearr\n*: <em>seòladh taighe, àireamhan fòn, àireamhan NI is msaa.</em>",
        "revdelete-legend": "Suidhich cuingeachaidhean na faicsinneachd",
        "revdelete-hide-text": "Teacsa a' mhùthaidh",
        "searchprofile-advanced-tooltip": "Lorg am broinn ainm-spàsan gnàthaichte",
        "search-result-size": "$1 ({{PLURAL:$2|$2 fhacal|$2 fhacal|$2 faclan|$2 facal}})",
        "search-result-category-size": "{{PLURAL:$1|$1 bhall|$1 bhall|$1 bhuill|$1 ball}} ({{PLURAL:$2|$2 fho-roinn-seòrsa|$2 fho-roinn-seòrsa|$2 fo-roinnean-seòrsa|$2 fo-roinn-seòrsa}}, {{PLURAL:$3|$3 fhaidhle|$3 fhaidhle|$3 faidhlichean|$3 faidhle}})",
-       "search-result-score": "Buntainneas: $1%",
        "search-redirect": "(ag ath-sheòladh $1)",
        "search-section": "(earrann $1)",
        "search-file-match": "{a' freagairt ri susbaint an fhaidhle)",
        "recentchangeslinked-feed": "Mùthaidhean buntainneach",
        "recentchangeslinked-toolbox": "Mùthaidhean buntainneach",
        "recentchangeslinked-title": "Mùthaidhean co-cheangailte ri \"$1\"",
-       "recentchangeslinked-summary": "Seo liosta nam mùthaidhean a chaidh a chur air duilleagan a tha a' ceangal o dhuilleag shònraichte (no ri buill ann an roinn-seòrsa sònraichte).\nTha duilleagan air [[Special:Watchlist|do chlàr-faire]] ann an litrichean <strong>troma</strong>.",
+       "recentchangeslinked-summary": "Seo liosta nam mùthaidhean a chaidh a chur air duilleagan a tha a' ceangal o dhuilleag shònraichte (no ri buill ann an roinn-seòrsa sònraichte).\nTha duilleagan air a' [[Special:Watchlist|chlàr-fhaire]] agad ann an litrichean <strong>troma</strong>.",
        "recentchangeslinked-page": "Ainm na duilleige:",
        "recentchangeslinked-to": "Seall mùthaidhean nan duilleagan a tha a' ceangal ris an duilleag sin 'na àite",
        "upload": "Luchdaich suas faidhle",
        "uploadwarning": "Rabhadh luchdaidh suas",
        "uploadwarning-text": "Atharraich tuairisgeul an fhaidhle gu h-ìosal 's feuch ris a-rithist.",
        "savefile": "Sàbhail faidhle",
-       "uploadedimage": "a luchdaich suas \"[[$1]]\"",
-       "overwroteimage": "luchdaich suas tionndadh ùr de \"[[$1]]\"",
        "uploaddisabled": "Tha an luchdadh suas à comas.",
        "copyuploaddisabled": "Tha an luchdadh suas o URL à comas.",
        "uploaddisabledtext": "Tha luchdadh suas fhaidhlichean à comas.",
        "allpagesto": "Seall duilleagan a tha a' crìochnachadh aig:",
        "allarticles": "A h-uile duilleag",
        "allinnamespace": "A h-uile duilleag (ainm-spàs $1)",
-       "allpagessubmit": "Rach",
+       "allpagessubmit": "Siuthad",
        "allpagesprefix": "Seall na duilleagan leis an ro-leasachan:",
        "allpagesbadtitle": "Chaidh tiotal duilleige mì-dhligheach a thoirt seachad no bha ro-leasachan eadar-cànain no eadar-uicidh aige.\nFaodaidh gu bheil aon no barrachd charactaran ann nach urrainn dhut a chleachdadh ann an tiotal.",
        "allpages-bad-ns": "Chan eil an t-ainm-spàs \"$1\" aig {{SITENAME}}.",
        "watchlistanontext": "$1 gus nithean air a' chlàr-fhaire agad a shealltainn no a dheasachadh.",
        "watchnologin": "Chan eil thu air logadh a-steach",
        "addwatch": "Cuir air a' chlàr-fhaire",
-       "addedwatchtext": "Chaidh an duilleag \"[[:$1]]\" a chur ri [[Special:Watchlist|do chlàr-faire]].\nNochdaidh mùthaidhean a nithear air an duilleag seo 's air an duilleag deasbaireachd a tha co-cheangailte ris an-seo san àm ri teachd.",
+       "addedwatchtext": "Chaidh an duilleag \"[[:$1]]\" a chur ris a' [[Special:Watchlist|chlàr-fhaire]] agad.\nNochdaidh mùthaidhean a nithear air an duilleag seo 's air an duilleag deasbaireachd a tha co-cheangailte ris an-seo san àm ri teachd.",
        "addedwatchtext-short": "Chaidh an duilleag \"$1\" a chur ris a' chlàr-fhaire agad.",
        "removewatch": "Thoir air falbh on chlàr-fhaire",
-       "removedwatchtext": "Chaidh an duilleag \"[[:$1]]\" a thoirt air falbh o [[Special:Watchlist|do chlàr-faire]].",
+       "removedwatchtext": "Chaidh an duilleag \"[[:$1]]\" a thoirt air falbh on [[Special:Watchlist|chlàr-fhaire]] agad.",
        "removedwatchtext-short": "Chaidh an duilleag \"$1\" a thoirt ait falbh on chlàr-fhaire agad.",
        "watch": "Cum sùil air",
        "watchthispage": "Cum sùil air an duilleag seo",
        "watchlist-details": "Tha {{PLURAL:$1|$1 duilleag|$1 dhuilleag|$1 duilleagan|$1 duilleag}} air a' chlàr-fhaire agad, gun luaidh air na duilleagan deasbaireachd.",
        "wlheader-enotif": "Tha brathan-naidheachd air a' phost-d an comas.",
        "wlheader-showupdated": "Tha clò <strong>trom</strong> air duilleagan a chaidh atharrachadh on turas mu dheireadh a thadhail thu orra.",
-       "wlnote2": "Chì thu na h-atharraichean {{PLURAL:$1|san <strong>$1</strong> uair|san <strong>$1</strong> uair|sna <strong>$1</strong> uairean|san <strong>$1</strong> uair}} a thìde seo chaidh aig $3 air $2.",
+       "wlnote": "Seo {{PLURAL:$1|an $1 mhùthadh|$1 mhùthadh|na $1 mùthaidhean|$1 mùthadh}} mu dheireadh san {{PLURAL:$2|$2 uair a thìde|$2 uair a thìde|$2 uairean a thìde|$2 uair a thìde}} mu dheireadh, mar a bha e $3, $4.",
        "wlshowlast": "Seall na $1 uairean a thìde mu dheireadh $2 làithean mu dheireadh $3",
        "watchlist-options": "Roghainnean mo chlàir-faire",
        "watching": "'Ga chur air a' chlàr-fhaire...",
        "tooltip-preview": "Ro-sheall na mùthaidhean agad; saoil an cleachd thu seo mus sàbhail thu iad?",
        "tooltip-diff": "Seall na mùthaidhean a chuir mi air an teacs",
        "tooltip-compareselectedversions": "Seall an diofar eadar an dà mhùthadh dhen duilleag seo a thagh thu",
-       "tooltip-watch": "Cuir an duilleag seo air do chlàr-faire",
+       "tooltip-watch": "Cuir an duilleag seo ris a' chlàr-fhaire agad",
        "tooltip-watchlistedit-normal-submit": "Thoir tiotalan air falbh",
        "tooltip-watchlistedit-raw-submit": "Ùraich an clàr-faire",
        "tooltip-recreate": "Ath-chruthaich an duilleag seo ged a chaidh a sguabadh às",
        "watchlistall2": "na h-uile",
        "namespacesall": "na h-uile",
        "monthsall": "na h-uile",
-       "confirmemail": "Dearbh an seòladh puist-dhealain",
+       "confirmemail": "Dearbhaich an seòladh puist-dhealain",
        "confirmemail_noemail": "Cha dug thu seachad seòladh puist-d dligheach ann an [[Special:Preferences|roghainnean a' chleachdaiche]] agad.",
-       "confirmemail_text": "Iarraidh {{SITENAME}} ort gun dearbh thu an seòladh puist-d agad mus cleachd thu feartan puist-d.\nCleachd am putan gu h-ìosal gus post-d dearbhaidh a chur dhan t-seòladh agad.\nBidh ceangal le còd sa phost-d ud;\nluchdaich an ceangal sa bhrabhsair agad airson dearbhadh gu bheil an seòladh puist-d agad dligheach.",
+       "confirmemail_text": "Iarraidh {{SITENAME}} ort gun dearbhaich thu an seòladh puist-d agad mus cleachd thu feartan puist-d.\nCleachd am putan gu h-ìosal gus post-d dearbhaidh a chur dhan t-seòladh agad.\nBidh ceangal le còd sa phost-d ud;\nluchdaich an ceangal sa bhrabhsair agad airson dearbhadh gu bheil an seòladh puist-d agad dligheach.",
        "confirmemail_pending": "Chaidh còd dearbhaidh a chur thugad air a' phost-d mar-thà;\nma tha thu air a' chunntas agad a chruthachadh o chionn goirid, 's math dh'fhaoidte gum b' feairrde thu feitheamh mionaid no dhà ach an ruig e thu mus iarr thu còd ùr.",
        "confirmemail_send": "Cuir còd dearbhaidh thugam",
        "confirmemail_sent": "Chaidh post-d dearbhaidh a chur.",
        "feedback-error3": "Mearachd: Cha d' fhuair sinn freagairt on API",
        "feedback-thanks": "Mòran taing! Chaidh do bheachd a phostadh air an duilleag \"[$2 $1]\".",
        "feedback-close": "Dèanta",
-       "feedback-bugcheck": "Taghta! Dearbh nach eil e air [$1 liosta nam bugaichean air a bheil sinn eòlach] mar-thà.",
+       "feedback-bugcheck": "Taghta! Dearbhaich nach eil e air [$1 liosta nam bugaichean air a bheil sinn eòlach] mar-thà.",
        "feedback-bugnew": "Dhearbh mi seo. Dèan aithris air buga ur",
        "searchsuggest-search": "Lorg",
        "searchsuggest-containing": "anns a bheil...",
index d72e97a..f8345fe 100644 (file)
@@ -14,7 +14,8 @@
                        "Vivaelcelta",
                        "Xosé",
                        "לערי ריינהארט",
-                       "Fitoschido"
+                       "Fitoschido",
+                       "McDutchie"
                ]
        },
        "tog-underline": "Subliñar as ligazóns:",
@@ -31,6 +32,7 @@
        "tog-watchdefault": "Engadir as páxinas e os ficheiros que edite á miña lista de vixilancia",
        "tog-watchmoves": "Engadir as páxinas e os ficheiros que mova á miña lista de vixilancia",
        "tog-watchdeletion": "Engadir as páxinas e os ficheiros que borre á miña lista de vixilancia",
+       "tog-watchrollback": "Engadir as páxinas nas que realice unha reversión á miña lista de vixilancia",
        "tog-minordefault": "Marcar por omisión todas as edicións como pequenas",
        "tog-previewontop": "Mostrar a vista previa antes da caixa de edición",
        "tog-previewonfirst": "Mostrar a vista previa na primeira edición",
        "talkpagelinktext": "Conversa",
        "specialpage": "Páxina especial",
        "personaltools": "Ferramentas persoais",
-       "postcomment": "Nova sección",
        "articlepage": "Ver a páxina de contido",
        "talk": "Conversa",
        "views": "Vistas",
        "hidetoc": "agochar",
        "collapsible-collapse": "Contraer",
        "collapsible-expand": "Expandir",
+       "confirmable-confirm": "Está {{GENDER:$1|seguro|segura}}?",
+       "confirmable-yes": "Si",
+       "confirmable-no": "Non",
        "thisisdeleted": "Quere ver ou restaurar $1?",
        "viewdeleted": "Quere ver $1?",
        "restorelink": "{{PLURAL:$1|unha edición borrada|$1 edicións borradas}}",
        "invalidtitle-knownnamespace": "Título inválido co espazo de nomes \"$2\" e o texto \"$3\"",
        "invalidtitle-unknownnamespace": "Título inválido cun número de espazo de nomes, $1, descoñecido e o texto \"$2\"",
        "exception-nologin": "Non accedeu ao sistema",
-       "exception-nologin-text": "[[Special:Userlogin|Acceda ao sistema]] para poder realizar esa acción ou acceder a esa páxina.",
+       "exception-nologin-text": "Acceda ao sistema para poder realizar esa acción ou acceder a esa páxina.",
        "exception-nologin-text-manual": "Debe $1 para poder realizar esa acción ou acceder a esa páxina.",
        "virus-badscanner": "Configuración errónea: escáner de virus descoñecido: ''$1''",
        "virus-scanfailed": "fallou o escaneado (código $1)",
        "externaldberror": "Ou ben se produciu un erro da base de datos na autenticación externa ou ben non se lle permite actualizar a súa conta externa.",
        "login": "Acceder ao sistema",
        "nav-login-createaccount": "Rexistro",
-       "loginprompt": "Debe habilitar as cookies para acceder a {{SITENAME}}.",
        "userlogin": "Rexistro",
        "userloginnocreate": "Rexistro",
        "logout": "Saír ao anonimato",
        "userlogin-resetlink": "Esqueceu os seus datos de rexistro?",
        "userlogin-resetpassword-link": "Esqueceu o contrasinal?",
        "userlogin-helplink2": "Axuda co rexistro",
-       "userlogin-loggedin": "Xa accedeu ao sistema como {{GENDER:$1|$1}}.\nUtilice o formulario inferior para acceder como outro usuario.",
-       "userlogin-createanother": "Crear outra conta",
        "createacct-emailrequired": "Enderezo de correo electrónico",
        "createacct-emailoptional": "Enderezo de correo electrónico (opcional)",
        "createacct-email-ph": "Insira o seu enderezo de correo electrónico",
        "createaccount-text": "Alguén creou unha conta chamada \"$2\" para o seu enderezo de correo electrónico en {{SITENAME}} ($4), e con contrasinal \"$3\".\nDebe acceder ao sistema e mudar o contrasinal agora.\n\nPode facer caso omiso desta mensaxe se se creou esta conta por erro.",
        "login-throttled": "Fixo demasiados intentos de acceder ao sistema.\nPor favor, agarde $1 antes de probar outra vez.",
        "login-abort-generic": "Acceso ao sistema incorrecto; abortado",
+       "login-migrated-generic": "A súa conta foi migrada, e o seu nome de usuario xa non existe nesta wiki.",
        "loginlanguagelabel": "Lingua: $1",
        "suspicious-userlogout": "Rexeitouse a súa petición de saír do sistema porque semella que a enviou un navegador roto ou a caché dun proxy.",
        "createacct-another-realname-tip": "O nome real é opcional.\nSe escolle dalo utilizarase para atribuír ao usuario o seu traballo.",
        "preview": "Vista previa",
        "showpreview": "Mostrar a vista previa",
        "showdiff": "Mostrar os cambios",
-       "anoneditwarning": "'''Aviso:''' Non accedeu ao sistema.\nO seu enderezo IP quedará rexistrado no historial de revisións desta páxina.",
+       "blankarticle": "<strong>Advertencia:</strong> A páxina que está a piques de crear está baleira.\nSe preme no botón \"{{int:savearticle}}\" outra vez, a páxina crearase sen contido.",
+       "anoneditwarning": "<strong>Aviso:</strong> Non accedeu ao sistema. O seu enderezo IP será rexistado no histórico de edicións desta páxina. Se <strong>[$1 accede ao sistema]</strong> ou <strong>[$2 crea unha conta]</strong>, as súas edicións serán rexistadas co seu nome de usuario, ademais doutros beneficios.",
        "anonpreviewwarning": "''Non accedeu ao sistema. Se garda a páxina, o seu enderezo IP quedará rexistrado no historial de edicións.''",
        "missingsummary": "'''Aviso:''' Esqueceu incluír o texto do campo resumo.\nSe preme en \"{{int:savearticle}}\" a súa edición gardarase sen ningunha descrición da edición.",
        "missingcommenttext": "Por favor, escriba un comentario a continuación.",
        "parser-template-recursion-depth-warning": "Excedeuse o límite de profundidade de recursión do modelo ($1)",
        "language-converter-depth-warning": "Excedeuse o límite de profundidade do convertedor de lingua ($1)",
        "node-count-exceeded-category": "Páxinas nas que se supera o número de nodos",
-       "node-count-exceeded-category-desc": "Unha categoría para as páxinas que superan o número de nodos.",
+       "node-count-exceeded-category-desc": "A páxina supera o número máximo de nodos.",
        "node-count-exceeded-warning": "A páxina supera o número de nodos",
        "expansion-depth-exceeded-category": "Páxinas nas que se supera a profundidade de expansión",
-       "expansion-depth-exceeded-category-desc": "Esta é unha categoría para as páxinas que superan a profundidade de expansión.",
+       "expansion-depth-exceeded-category-desc": "A páxina supera a profundidade de expansión máxima.",
        "expansion-depth-exceeded-warning": "A páxina supera a profundidade de expansión",
        "parser-unstrip-loop-warning": "Detectouse un bucle inamovible",
        "parser-unstrip-recursion-limit": "Excedeuse o límite de recursión inamovible ($1)",
        "rev-deleted-event": "(entrada eliminada)",
        "rev-deleted-user-contribs": "[nome de usuario ou enderezo IP eliminado; edición agochada das contribucións]",
        "rev-deleted-text-permission": "Esta revisión da páxina foi '''borrada'''.\nPode ampliar os detalles no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} rexistro de borrados].",
+       "rev-suppressed-text-permission": "Esta revisión da páxina foi <strong>suprimida</strong>.\nPode ampliar os detalles no [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} rexistro de supresións].",
        "rev-deleted-text-unhide": "Esta revisión da páxina foi '''borrada'''.\nPode ampliar os detalles no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} rexistro de borrados].\nAínda pode [$1 ver esta revisión] se quere.",
        "rev-suppressed-text-unhide": "Esta revisión da páxina foi '''suprimida'''.\nPode ampliar os detalles no [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} rexistro de supresións].\nAínda pode [$1 ver esta revisión] se quere.",
        "rev-deleted-text-view": "Esta revisión da páxina foi '''borrada'''.\nAínda ten a posibilidade de vela; pode ampliar os detalles no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} rexistro de borrados].",
        "revdelete-text-text": "As revisións borradas seguirán aparecendo no historial da páxina, pero partes do seu contido serán inaccesibles para o público.",
        "revdelete-text-file": "As revisións borradas do ficheiro seguirán aparecendo no historial do ficheiro, pero partes do seu contido serán inaccesibles para o público.",
        "logdelete-text": "Os rexistros de eventos borrados seguirán aparecendo nos rexistros, pero partes do seu contido serán inaccesibles para o público.",
-       "revdelete-text-others": "Os outros administradores de {{SITENAME}} seguirán tendo acceso aos contidos agochados e poderán restauralos a través desta mesma interface, a menos que se definan restricións adicionais.",
+       "revdelete-text-others": "Os outros administradores seguirán tendo acceso aos contidos agochados e poderán restauralos, a menos que se definan restricións adicionais.",
        "revdelete-confirm": "Por favor, confirme que quere levar a cabo esta acción, que comprende as consecuencias e que o fai de acordo [[{{MediaWiki:Policy-url}}|coas políticas]].",
        "revdelete-suppress-text": "A eliminación '''unicamente''' debería utilizarse nos seguintes casos:\n* Información potencialmente difamatoria\n* Información persoal inapropiada\n*: ''domicilios e números de teléfono, números da seguridade social etc.''",
        "revdelete-legend": "Aplicar restricións de visibilidade",
        "revdelete-offender": "Autor da revisión:",
        "suppressionlog": "Rexistro de supresións",
        "suppressionlogtext": "A continuación móstrase unha lista coas eliminacións e cos bloqueos recentes, que inclúen contido oculto dos administradores.\nOlle a [[Special:BlockList|lista de bloqueos]] para comprobar os bloqueos vixentes.",
-       "mergehistory": "Fusionar os historiais das páxinas",
-       "mergehistory-header": "Esta páxina permítelle fusionar revisións dos historiais da páxina de orixe nunha nova páxina.\nAsegúrese de que esta modificación da páxina mantén a continuidade histórica.",
+       "mergehistory": "Fusionar os historiais de páxinas",
+       "mergehistory-header": "Esta páxina permítelle fusionar as revisións dos historiais da páxina de orixe nunha nova páxina.\nAsegúrese de que esta modificación mantén a continuidade histórica da páxina.",
        "mergehistory-box": "Fusionar as revisións de dúas páxinas:",
        "mergehistory-from": "Páxina de orixe:",
        "mergehistory-into": "Páxina de destino:",
-       "mergehistory-list": "Historial de edicións fusionables",
-       "mergehistory-merge": "As revisións seguintes de [[:$1]] pódense fusionar con [[:$2]]. Use a columna de botóns de selección para fusionar só as revisións creadasen e antes da hora indicada. Teña en conta que se usa as ligazóns de navegación a columna limparase.",
+       "mergehistory-list": "Historial de edicións que se pode fusionar",
+       "mergehistory-merge": "As seguintes revisións de \"[[:$1]]\" pódense fusionar con \"[[:$2]]\".\nUtilice a columna de caixas de selección para fusionar só as revisións creadas ata a hora indicada, esta incluída.\nTeña en conta que o uso das ligazóns de navegación ha borrar a selección da columna.",
        "mergehistory-go": "Mostrar as edicións que se poden fusionar",
        "mergehistory-submit": "Fusionar as revisións",
        "mergehistory-empty": "Non hai revisións que se poidan fusionar.",
-       "mergehistory-success": "{{PLURAL:$3|Unha revisión|$3 revisións}} de [[:$1]] {{PLURAL:$3|fusionouse|fusionáronse}} sen problemas en [[:$2]].",
-       "mergehistory-fail": "Non se puido fusionar o historial; comprobe outra vez os parámetros de páxina e hora.",
+       "mergehistory-success": "{{PLURAL:$3|Unha revisión|$3 revisións}} de \"[[:$1]]\" {{PLURAL:$3|fusionouse|fusionáronse}} sen problemas con \"[[:$2]]\".",
+       "mergehistory-fail": "Non se puido fusionar o historial; comprobe outra vez os parámetros de páxina e data.",
+       "mergehistory-fail-toobig": "Non se puido fusionar o historial, xa que supón trasladar máis revisións que o límite de $1 {{PLURAL:$1|revisión|revisións}}.",
        "mergehistory-no-source": "Non existe a páxina de orixe \"$1\".",
        "mergehistory-no-destination": "Non existe a páxina de destino \"$1\".",
        "mergehistory-invalid-source": "A páxina de orixe ten que ter un título válido.",
        "mergehistory-invalid-destination": "A páxina de destino ten que ter un título válido.",
-       "mergehistory-autocomment": "\"[[:$1]]\" fusionouse en \"[[:$2]]\"",
-       "mergehistory-comment": "\"[[:$1]]\" fusionouse en \"[[:$2]]\": $3",
-       "mergehistory-same-destination": "A orixe das páxinas e o seu destino non poden ser os mesmos",
+       "mergehistory-autocomment": "\"[[:$1]]\" fusionouse con \"[[:$2]]\"",
+       "mergehistory-comment": "\"[[:$1]]\" fusionouse con \"[[:$2]]\": $3",
+       "mergehistory-same-destination": "A páxina de orixe e a páxina de destino non pode ser a mesma",
        "mergehistory-reason": "Motivo:",
        "mergelog": "Rexistro de fusións",
-       "pagemerge-logentry": "fusionou \"[[$1]]\" con \"[[$2]]\" (revisións até o $3)",
+       "pagemerge-logentry": "fusionou \"[[$1]]\" con \"[[$2]]\" (revisións ata o $3)",
        "revertmerge": "Desfacer a fusión",
        "mergelogpagetext": "A continuación hai unha lista coas fusións máis recentes do historial dunha páxina co doutra.",
        "history-title": "Historial de revisións de \"$1\"",
        "searchprofile-advanced-tooltip": "Procurar nos espazos de nomes elixidos",
        "search-result-size": "$1 ({{PLURAL:$2|1 palabra|$2 palabras}})",
        "search-result-category-size": "{{PLURAL:$1|1 membro|$1 membros}} ({{PLURAL:$2|1 subcategoría|$2 subcategorías}}, {{PLURAL:$3|1 ficheiro|$3 ficheiros}})",
-       "search-result-score": "Relevancia: $1%",
        "search-redirect": "(redirixido desde \"$1\")",
        "search-section": "(sección \"$1\")",
        "search-file-match": "(coincide co contido do ficheiro)",
        "searchall": "todo",
        "showingresults": "{{PLURAL:$1|Móstrase '''1''' resultado|Móstranse '''$1''' resultados}}, comezando polo número '''$2'''.",
        "showingresultsinrange": "{{PLURAL:$1|Móstrase <strong>1</strong> resultado|Móstranse <strong>$1</strong> resultados}}, comezando polo número <strong>$2</strong> e rematando polo número <strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Resultado '''$1''' de '''$3'''|Resultados do '''$1''' ao '''$2''', dun total de '''$3''',}} para \"'''$4'''\"",
        "search-nonefound": "Non se atopou ningún resultado que coincidise coa procura.",
        "powersearch-legend": "Busca avanzada",
        "powersearch-ns": "Procurar nos espazos de nomes:",
        "preferences": "Preferencias",
        "mypreferences": "Preferencias",
        "prefs-edits": "Número de edicións:",
-       "prefsnologintext2": "Debe $1 para definir as preferencias de usuario.",
+       "prefsnologintext2": "Acceda ao sistema para modificar as súas preferencias.",
        "prefs-skin": "Aparencia",
        "skin-preview": "Vista previa",
        "datedefault": "Ningunha preferencia",
        "right-deletedtext": "Ver texto borrado e cambios entre revisións eliminadas",
        "right-browsearchive": "Procurar páxinas borradas",
        "right-undelete": "Restaurar unha páxina",
-       "right-suppressrevision": "Revisar e restaurar as revisións agochadas dos administradores",
+       "right-suppressrevision": "Revisar, agochar e restaurar revisións específicas de páxinas de calquera usuario",
+       "right-viewsuppressed": "Ver revisións agochadas por calquera usuario",
        "right-suppressionlog": "Ver rexistros privados",
        "right-block": "Bloquear outros usuarios fronte á edición",
        "right-blockemail": "Bloquear un usuario fronte ao envío dun correo electrónico",
        "recentchanges-legend-heading": "'''Lenda:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (véxase tamén a [[Special:NewPages|lista de páxinas novas]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "A continuación móstranse os cambios feitos desde o <strong>$3</strong> ás <strong>$4</strong> (móstranse <strong>$1</strong> como máximo).",
+       "rcnotefrom": "A continuación {{PLURAL:$5|móstrase o cambio feito|móstranse os cambios feitos}} desde o <strong>$3</strong> ás <strong>$4</strong> (móstranse <strong>$1</strong> como máximo).",
        "rclistfrom": "Mostrar os cambios novos desde o $3 ás $2",
        "rcshowhideminor": "$1 as edicións pequenas",
        "rcshowhideminor-show": "Mostrar",
        "largefileserver": "Este ficheiro é de maior tamaño ca o permitido pola configuración do servidor.",
        "emptyfile": "O ficheiro que cargou semella estar baleiro.\nIsto pode deberse a un erro ortográfico no seu nome.\nPor favor, verifique se realmente quere cargar este ficheiro.",
        "windows-nonascii-filename": "Este wiki non soporta os nomes de ficheiros con caracteres especiais.",
-       "fileexists": "Xa existe un ficheiro con ese nome. Por favor, comprobe \"<strong>[[:$1]]</strong>\" se non está seguro de querer cambialo.\n[[$1|thumb]]",
+       "fileexists": "Xa existe un ficheiro con ese nome. Por favor, comprobe \"<strong>[[:$1]]</strong>\" se non está {{GENDER:|seguro|segura}} de querer cambialo.\n[[$1|thumb]]",
        "filepageexists": "A páxina de descrición deste ficheiro xa foi creada en <strong>[[:$1]]</strong>, pero polo de agora non existe ningún ficheiro con este nome.\nO resumo que escribiu non aparecerá na páxina de descrición.\nPara facer que o resumo apareza alí, necesitará editar a páxina manualmente.\n[[$1|thumb]]",
        "fileexists-extension": "Xa existe un ficheiro cun nome semellante: [[$2|thumb]]\n* Nome do ficheiro que intenta cargar: <strong>[[:$1]]</strong>\n* Nome de ficheiro existente: <strong>[[:$2]]</strong>\nPor favor, escolla un nome diferente.",
        "fileexists-thumbnail-yes": "Semella que o ficheiro é unha imaxe de tamaño reducido ''(miniatura)''.\n[[$1|thumb]]\nPor favor, comprobe o ficheiro <strong>[[:$1]]</strong>.\nSe o ficheiro seleccionado é a mesma imaxe en tamaño orixinal non é preciso enviar unha miniatura adicional.",
        "uploadwarning": "Advertencia ao cargar o ficheiro",
        "uploadwarning-text": "Por favor, modifique a descrición do ficheiro e inténteo de novo.",
        "savefile": "Gardar o ficheiro",
-       "uploadedimage": "cargou \"[[$1]]\"",
-       "overwroteimage": "enviou unha nova versión de \"[[$1]]\"",
        "uploaddisabled": "Sentímolo, a subida de ficheiros está desactivada.",
        "copyuploaddisabled": "A carga mediante URL está desactivada.",
        "uploaddisabledtext": "A carga de ficheiros está desactivada.",
        "license": "Licenza:",
        "license-header": "Licenza",
        "nolicense": "Ningunha seleccionada",
+       "licenses-edit": "Editar as opcións de licenza",
        "license-nopreview": "(A vista previa non está dispoñible)",
-       "upload_source_url": "  (un URL válido e accesible publicamente)",
-       "upload_source_file": "  (un ficheiro no seu ordenador)",
+       "upload_source_url": "(o ficheiro elixido, cun URL válido e accesible publicamente)",
+       "upload_source_file": "(o ficheiro elixido do seu ordenador)",
+       "listfiles-delete": "borrar",
        "listfiles-summary": "Esta páxina especial mostra todos os ficheiros cargados.",
        "listfiles_search_for": "Buscar polo nome do ficheiro multimedia:",
        "imgfile": "ficheiro",
        "filedelete-maintenance": "Os borrados e restauracións de ficheiros están desactivados temporalmente durante o mantemento.",
        "filedelete-maintenance-title": "Non se pode borrar o ficheiro",
        "mimesearch": "Busca MIME",
-       "mimesearch-summary": "Esta páxina permite filtrar os ficheiros segundo o seu tipo MIME.\nEntrada: tipodecontido/subtipo, por exemplo <code>image/jpeg</code>.",
+       "mimesearch-summary": "Esta páxina permite filtrar os ficheiros segundo o seu tipo MIME.\nEntrada: tipodecontido/subtipo ou tipodecontido/*; por exemplo, <code>image/jpeg</code>.",
        "mimetype": "Tipo MIME:",
        "download": "descargar",
        "unwatchedpages": "Páxinas non vixiadas",
        "randomincategory": "Páxina aleatoria na categoría",
        "randomincategory-invalidcategory": "\"$1\" non é un nome de categoría válido.",
        "randomincategory-nopages": "Non hai páxinas na [[:Category:$1]].",
-       "randomincategory-selectcategory": "Ir a unha páxina ao chou da categoría: $1 $2.",
-       "randomincategory-selectcategory-submit": "Ir",
+       "randomincategory-category": "Categoría:",
+       "randomincategory-legend": "Páxina aleatoria na categoría",
        "randomredirect": "Redirección aleatoria",
        "randomredirect-nopages": "Non hai redireccións no espazo de nomes \"$1\".",
        "statistics": "Estatísticas",
        "wantedpages-badtitle": "Título inválido fixado nos resultados: $1",
        "wantedfiles": "Ficheiros requiridos",
        "wantedfiletext-cat": "Os seguintes ficheiros están en uso, pero non existen. É posible que aparezan ficheiros de repositoroios externos, malia que existan. Calquera falso positivo estará <del>riscado</del>. Ademais, as páxinas que inclúen ficheiros que non existen están listadas en [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Os seguintes ficheiros están en uso, pero non existen. Ademais, as páxinas que inclúen ficheiros que non existen están listadas en [[:$1]].",
        "wantedfiletext-nocat": "Os seguintes ficheiros están en uso, pero non existen. É posible que aparezan ficheiros de repositoroios externos, malia que existan. Calquera falso positivo estará <del>riscado</del>.",
+       "wantedfiletext-nocat-noforeign": "Os seguintes ficheiros están en uso, pero non existen.",
        "wantedtemplates": "Modelos requiridos",
        "mostlinked": "Páxinas máis ligadas",
        "mostlinkedcategories": "Categorías máis ligadas",
-       "mostlinkedtemplates": "Modelos máis ligados",
+       "mostlinkedtemplates": "Modelos máis transcluídos",
        "mostcategories": "Páxinas con máis categorías",
        "mostimages": "Ficheiros máis usados",
        "mostinterwikis": "Páxinas con máis interwikis",
        "trackingcategories-desc": "Criterio de inclusión da categoría",
        "noindex-category-desc": "A páxina non está indexada polos bots porque contén a palabra máxica <code><nowiki>__NOINDEX__</nowiki></code> e está nun espazo de nomes no que esa marca está permitida.",
        "index-category-desc": "A páxina contén a palabra máxica <code><nowiki>__INDEX__</nowiki></code> (e está nun espazo de nomes no que esa marca está permitida) e, polo tanto, será indexada polos bots cando non debera selo normalmente.",
-       "post-expand-template-inclusion-category-desc": "Despois de expandir todos os modelos, o tamaño da páxina é maior que <code>$wgMaxArticleSize</code>; algúns modelos non se expandiron.",
-       "post-expand-template-argument-category-desc": "Despois de expandir o argumento dun modelo (algo entre chaves triples, como <code>{{{Proba}}}</code>), a páxina é maior que <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Hai demasiadas funcións analíticas custosas (como <code>#ifexist</code>) incluídas nunha páxina. Consulte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Categoría engadida se a páxina contén unha ligazón de ficheiro rota (unha ligazón para incorporar un ficheiro cando o ficheiro non existe).",
-       "hidden-category-category-desc": "Esta é unha categoría coa palabra máxica <code><nowiki>__HIDDENCAT__</nowiki></code>, que impide que se mostre por defecto na caixa de categorías das páxinas.",
+       "post-expand-template-inclusion-category-desc": "O tamaño da páxina é maior que <code>$wgMaxArticleSize</code> despois de expandir todos os modelos; algúns modelos non se expandiron.",
+       "post-expand-template-argument-category-desc": "A páxina é maior que <code>$wgMaxArticleSize</code> despois de expandir o argumento dun modelo (algo entre chaves triples, como <code>{{{Proba}}}</code>).",
+       "expensive-parserfunction-category-desc": "A páxina utiliza demasiadas funcións analíticas custosas (como <code>#ifexist</code>). Consulte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "A páxina contén unha ligazón de ficheiro rota (unha ligazón para incorporar un ficheiro que non existe).",
+       "hidden-category-category-desc": "A categoría contén a palabra máxica <code><nowiki>__HIDDENCAT__</nowiki></code>, que impide que se mostre por defecto na caixa de categorías das páxinas.",
        "trackingcategories-nodesc": "Non hai ningunha descrición dispoñible.",
        "trackingcategories-disabled": "A categoría está desactivada",
        "mailnologin": "Non existe enderezo para o envío",
        "mywatchlist": "Lista de vixilancia",
        "watchlistfor2": "De $1 $2",
        "nowatchlist": "Non ten elementos na súa lista de vixilancia.",
-       "watchlistanontext": "Debe $1 para ver ou editar os elementos da súa lista de vixilancia.",
+       "watchlistanontext": "Acceda ao sistema para ver ou editar os elementos da súa lista de vixilancia.",
        "watchnologin": "Non accedeu ao sistema",
        "addwatch": "Engadir á lista vixilancia",
        "addedwatchtext": "A páxina \"[[:$1]]\" foi engadida á súa [[Special:Watchlist|lista de vixilancia]].\nOs cambios futuros nesta páxina e na súa páxina de conversa asociada serán listados alí.",
        "watchlist-details": "Hai {{PLURAL:$1|unha páxina|$1 páxinas}} na súa lista de vixilancia, sen contar as de conversa.",
        "wlheader-enotif": "A notificación por correo electrónico está activada.",
        "wlheader-showupdated": "As páxinas que cambiaron desde a súa última visita móstranse en '''negra'''.",
-       "wlnote2": "A continuación están as modificacións feitas {{PLURAL:$1|na última hora|nas últimas <strong>$1</strong> horas}}, ata o $2 ás $3.",
+       "wlnote": "A continuación {{PLURAL:$1|está a última modificación|están as últimas <strong>$1</strong> modificacións}} {{PLURAL:$2|na última hora|nas últimas <strong>$2</strong> horas}} ata o $3 ás $4.",
        "wlshowlast": "Mostrar as últimas $1 horas, os últimos $2 días ou $3",
        "watchlist-options": "Opcións de vixilancia",
        "watching": "Vixiando...",
        "exbeforeblank": "o contido antes do baleirado era: \"$1\"",
        "delete-confirm": "Borrar \"$1\"",
        "delete-legend": "Borrar",
-       "historywarning": "'''Atención:''' A páxina que está a piques de borrar ten un historial con aproximadamente $1 {{PLURAL:$1|revisión|revisións}}:",
+       "historywarning": "<strong>Atención:</strong> A páxina que está a piques de borrar ten un historial con $1 {{PLURAL:$1|revisión|revisións}}:",
        "confirmdeletetext": "Está a piques de borrar de xeito permanente unha páxina ou imaxe con todo o seu historial na base de datos.\nPor favor, confirme que é realmente a súa intención, que comprende as consecuencias e que está obrando de acordo coas regras [[{{MediaWiki:Policy-url}}|da política e normas]].",
        "actioncomplete": "Completouse a acción",
        "actionfailed": "Fallou a acción",
        "delete-edit-reasonlist": "Editar os motivos de borrado",
        "delete-toobig": "Esta páxina conta cun historial longo, de máis {{PLURAL:$1|dunha revisión|de $1 revisións}}.\nLimitouse a eliminación destas páxinas para previr problemas de funcionamento accidentais en {{SITENAME}}.",
        "delete-warning-toobig": "Esta páxina conta cun historial de edicións longo, de máis {{PLURAL:$1|dunha revisión|de $1 revisións}}.\nAo eliminala pódense provocar problemas de funcionamento nas operacións da base de datos de {{SITENAME}};\nproceda con coidado.",
+       "deleteprotected": "Non pode borrar esta páxina porque está protexida.",
        "deleting-backlinks-warning": "'''Atención:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Outras páxinas]] conteñen unha ligazón ou unha transclusión da páxina que está a piques de borrar.",
        "rollback": "Reverter as edicións",
        "rollback_short": "Reverter",
        "autoblockid": "Bloqueo automático nº$1",
        "block": "Bloquear un usuario",
        "unblock": "Desbloquear un usuario",
-       "blockip": "Bloquear o usuario",
+       "blockip": "Bloquear {{GENDER:$1|o usuario|a usuaria}}",
        "blockip-legend": "Bloquear un usuario",
        "blockiptext": "Use o seguinte formulario para bloquear o acceso de escritura desde un enderezo IP ou para bloquear un usuario específico.\nIsto debería facerse só para previr vandalismo, e de acordo coa [[{{MediaWiki:Policy-url}}|política e normas]] vixentes.\nExplique a razón específica do bloqueo (por exemplo, citando as páxinas concretas que sufriron vandalismo).",
        "ipaddressorusername": "Enderezo IP ou nome de usuario:",
        "ipb-unblock-addr": "Desbloquear a $1",
        "ipb-unblock": "Desbloquear un usuario ou enderezo IP",
        "ipb-blocklist": "Ver os bloqueos vixentes",
-       "ipb-blocklist-contribs": "Contribucións de $1",
+       "ipb-blocklist-contribs": "Contribucións de {{GENDER:$1|$1}}",
        "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": "Importar páxinas",
        "importinterwiki": "Importación transwiki",
        "import-interwiki-text": "Seleccione o wiki e o título da páxina que queira importar.\nAs datas das revisións e os nomes dos editores manteranse.\nTodas as accións relacionadas coa importación entre wikis poden verse no [[Special:Log/import|rexistro de importacións]].",
-       "import-interwiki-source": "Wiki/Páxina de orixe:",
+       "import-interwiki-sourcewiki": "Wiki de orixe:",
+       "import-interwiki-sourcepage": "Páxina de orixe:",
        "import-interwiki-history": "Copiar todas as versións que hai no historial desta páxina",
        "import-interwiki-templates": "Incluír todos os modelos",
        "import-interwiki-submit": "Importar",
        "import-upload": "Cargar datos XML",
        "import-token-mismatch": "Perdéronse os datos da sesión. Por favor, inténteo de novo.",
        "import-invalid-interwiki": "Non se pode importar desde o wiki escificado.",
-       "import-error-edit": "Non se pode importar a páxina \"$1\" porque non ten os permisos necesarios para editala.",
-       "import-error-create": "Non se pode importar a páxina \"$1\" porque non ten os permisos necesarios para creala.",
-       "import-error-interwiki": "Non se pode importar a páxina \"$1\" porque o seu nome está reservado para unha ligazón externa (interwiki).",
-       "import-error-special": "Non se pode importar a páxina \"$1\" porque pertence a un espazo de nomes especial que non o permite.",
-       "import-error-invalid": "Non se pode importar a páxina \"$1\" porque o seu nome non é válido.",
+       "import-error-edit": "Non foi posible importar a páxina \"$1\" porque non ten os permisos necesarios para editala.",
+       "import-error-create": "Non foi posible importar a páxina \"$1\" porque non ten os permisos necesarios para creala.",
+       "import-error-interwiki": "Non foi posible importar a páxina \"$1\" porque o seu nome está reservado para unha ligazón externa (interwiki).",
+       "import-error-special": "Non foi posible importar a páxina \"$1\" porque pertence a un espazo de nomes especial que non o permite.",
+       "import-error-invalid": "Non foi posible importar a páxina \"$1\" porque o nome co que se importaría non é válido neste wiki.",
        "import-error-unserialize": "Non se puido deserializar a revisión $2 da páxina \"$1\". Informouse de que a revisión usa o modelo de contido $3 serializado como $4.",
        "import-error-bad-location": "Non se pode almacenar a revisión $2 que usa o modelo de contido $3 na páxina \"$1\" deste wiki, dado que ese modelo non está soportado nesa páxina.",
        "import-options-wrong": "{{PLURAL:$2|Opción incorrecta|Opcións incorrectas}}: <nowiki>$1</nowiki>",
        "importlogpage": "Rexistro de importacións",
        "importlogpagetext": "Rexistro de importación de páxinas xunto co seu historial de edicións procedentes doutros wikis.",
        "import-logentry-upload": "importou \"[[$1]]\" mediante a carga dun ficheiro",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revisión|revisións}}",
+       "import-logentry-upload-detail": "{{PLURAL:$1|Importouse $1 revisión|Importáronse $1 revisións}}",
        "import-logentry-interwiki": "importou \"$1\"",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisión|revisións}} de $2",
+       "import-logentry-interwiki-detail": "{{PLURAL:$1|Importouse $1 revisión|Importáronse $1 revisións}} desde $2",
        "javascripttest": "Proba de JavaScript",
        "javascripttest-title": "Executando probas de $1",
        "javascripttest-pagetext-noframework": "Esta páxina está reservada para executar probas do JavaScript.",
        "markedaspatrollederror-noautopatrol": "Non está permitido que un mesmo marque as propias edicións como revisadas.",
        "markedaspatrollednotify": "A modificación feita en \"$1\" marcouse como revisada.",
        "markedaspatrollederrornotify": "Erro ao marcar como revisada.",
-       "patrol-log-page": "Rexistro de revisións",
+       "patrol-log-page": "Rexistro de revisións patrulladas",
        "patrol-log-header": "Este é un rexistro das revisións patrulladas.",
        "log-show-hide-patrol": "$1 o rexistro de patrullas",
        "deletedrevision": "A revisión vella $1 foi borrada.",
        "autosumm-replace": "O contido da páxina foi substituído por \"$1\"",
        "autoredircomment": "Redirixida cara a \"[[$1]]\"",
        "autosumm-new": "Nova páxina: \"$1\"",
+       "autosumm-newblank": "A páxina creouse sen contido",
        "size-kilobytes": "$1 kB",
        "lag-warn-normal": "Pode que os cambios feitos {{PLURAL:$1|no último segundo|nos últimos $1 segundos}} non aparezan nesta lista.",
        "lag-warn-high": "Debido a unha gran demora do servidor da base de datos, pode que nesta lista non aparezan os cambios feitos {{PLURAL:$1|no último segundo|nos últimos $1 segundos}}.",
        "watchlisttools-raw": "Editar a lista de vixilancia simple",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|conversa]])",
        "unknown_extension_tag": "Etiqueta de extensión descoñecida \"$1\"",
-       "duplicate-defaultsort": "'''Aviso:''' A clave de ordenación por defecto \"$2\" anula a clave de ordenación anterior por defecto \"$1\".",
+       "duplicate-defaultsort": "<strong>Aviso:</strong> A clave de ordenación por defecto \"$2\" anula a clave de ordenación anterior por defecto \"$1\".",
+       "duplicate-displaytitle": "'''Aviso:''' O título mostrado \"$2\" anula o título anterior \"$1\".",
        "version": "Versión",
        "version-extensions": "Extensións instaladas",
+       "version-skins": "Aparencias instaladas",
        "version-specialpages": "Páxinas especiais",
        "version-parserhooks": "Asociadores analíticos",
        "version-variables": "Variables",
        "version-antispam": "Prevención contra spam",
-       "version-skins": "Aparencias",
        "version-other": "Outros",
        "version-mediahandlers": "Executadores de multimedia",
        "version-hooks": "Asociadores",
        "version-hook-name": "Nome do asociador",
        "version-hook-subscribedby": "Subscrito por",
        "version-version": "($1)",
+       "version-no-ext-name": "[sen nome]",
        "version-license": "Licenza de MediaWiki",
        "version-ext-license": "Licenza",
        "version-ext-colheader-name": "Extensión",
+       "version-skin-colheader-name": "Aparencia",
        "version-ext-colheader-version": "Versión",
        "version-ext-colheader-license": "Licenza",
        "version-ext-colheader-description": "Descrición",
        "logentry-rights-rights": "$1 {{GENDER:$2|cambiou}} o grupo ao que pertence $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\"",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|cargou}} unha nova versión de \"$3\"",
+       "logentry-upload-revert": "$1 {{GENDER:$2|cargou}} \"$3\"",
        "rightsnone": "(ningún)",
        "feedback-bugornote": "Se está listo para describir un problema técnico en detalle, [$1 informe do erro].\nEn caso contrario, pode empregar o formulario sinxelo inferior. O seu comentario aparecerá na páxina \"[$3 $2]\" xunto ao seu nome de usuario e o navegador que está usando.",
        "feedback-subject": "Asunto:",
        "expand_templates_remove_nowiki": "Suprimir as etiquetas <nowiki> no resultado",
        "expand_templates_generate_xml": "Mostrar as árbores de análise XML",
        "expand_templates_generate_rawhtml": "Mostrar o HTML en bruto",
-       "expand_templates_preview": "Vista previa"
+       "expand_templates_preview": "Vista previa",
+       "pagelanguage": "Selector de lingua da páxina",
+       "pagelang-name": "Páxina",
+       "pagelang-language": "Lingua",
+       "pagelang-use-default": "Utilizar a lingua por defecto",
+       "pagelang-select-lang": "Seleccionar a lingua",
+       "right-pagelang": "Cambiar a lingua da páxina",
+       "action-pagelang": "cambiar a lingua da páxina",
+       "log-name-pagelang": "Rexistro de cambios de lingua",
+       "log-description-pagelang": "Este é un rexistro dos cambios na lingua das páxinas.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|cambiou}} a lingua da páxina \"$3\" do $4 ao $5.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code>/$2 (activada)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code>/$2 ('''desactivada''')"
 }
index 7cc5f1b..8d7786e 100644 (file)
@@ -3,7 +3,8 @@
                "authors": [
                        "Deepak D'Souza",
                        "Isidore Dantas",
-                       "The Discoverer"
+                       "The Discoverer",
+                       "아라"
                ]
        },
        "underline-always": "Soddankal",
@@ -80,6 +81,7 @@
        "category-article-count": "{{PLURAL:$2|Hea vorgan fokot hi ek pan asa.|Hea vorgan {{PLURAL:$1|hi pan asa|him $1 panam asat}} beriz $2 panam modem.}}",
        "category-file-count": "{{PLURAL:$2|Hea vorgan fokot hi ek fail asa.|Hea vorgan {{PLURAL:$1|hi fail asa|heo $1 faili asat}}, beriz $2 faili modem.}}",
        "listingcontinuesabbrev": "chalu",
+       "index-category": "Suchi-potran zodlelim panam",
        "noindex-category": "Suchi-potran zoddunk-naslelim panam",
        "about": "Hea vixoiavoir",
        "article": "Vixoi sombondhi pan",
        "cancel": "Rod'd kor",
        "mytalk": "Bhasabhas",
        "navigation": "Dixa-niontronn",
+       "and": "&#32;ani",
        "qbfind": "Sod",
        "qbedit": "Bodol",
        "faq": "Choddxe vicharlole prosn",
-       "vector-action-addsection": "Vixoi zodd",
-       "vector-action-delete": "Kadd",
-       "vector-action-move": "Fuddem voch",
-       "vector-action-protect": "Rakh",
-       "vector-view-create": "Roch",
-       "vector-view-edit": "Sudar",
-       "vector-view-history": "Itihas polloi",
-       "vector-view-view": "Vach",
-       "vector-view-viewsource": "Mull polloi",
        "actions": "Karvaio",
        "namespaces": "Nanv-thollam",
        "variants": "Dusre",
        "history_short": "Itihas",
        "printableversion": "Chapp'pachi avruti",
        "permalink": "Togpi zodd",
+       "print": "Chap",
        "view": "Poloi",
        "edit": "Sudar",
        "create": "Roch",
        "remembermypassword": "Hea internet browseran mhojem sotrachem ugdas dovor (chodan chod $1 {{PLURAL:$1|disak|disank}})",
        "login": "Sotrromb kor",
        "nav-login-createaccount": "Sotrrombh kor / khato roch",
-       "loginprompt": "{{SITENAME}}, hea siticher sotrorombh korunktujea internet browseran ''cookies'' suru asunk zai.",
        "userlogin": "Sotrrombh kor / khatem roch",
        "logout": "Bhair podd",
        "userlogout": "Sotracho xevott",
        "gotaccount": "Tuje kodem khatem asa? $1.",
        "gotaccountlink": "Sotrorombh kor",
        "userlogin-resetlink": "Sotrorombh korpacheo bariksai visorlai?",
-       "mailmypassword": "Novem gupitutor email kor",
+       "mailmypassword": "Novem gupitutor",
        "loginlanguagelabel": "Bhas: $1",
        "bold_sample": "Datt mozkur",
        "bold_tip": "Datt mozkur",
        "viewpagelogs": "Hea panachim sotram polloi",
        "currentrev-asof": "$1, hachi halinchi uzollnni",
        "revisionasof": "$1 hachi uzollnni",
-       "revision-info": "$2 hannem $1, hachi uzollnni",
+       "revision-info": "$1 porian, $2 hannem kelli uzollnni",
        "previousrevision": "← Adli uzollnni",
        "nextrevision": "Novi uzolnni →",
        "currentrevisionlink": "Sogleanvon novi uzollnni",
        "shown-title": "Dor panar {{PLURAL:$1|porinam|porinam}} dakhoi",
        "viewprevnext": "($1 {{int:pipe-separator}} $2) ($3) poloi",
        "searchmenu-exists": "'''Hea Wikicher \"[[:$1]]\" nanvanche pan asa.'''",
-       "searchmenu-new": "'''\"[[:$1]]\" hem pan hea vikint roch!'''",
+       "searchmenu-new": "<strong>\"[[:$1]]\" hem pan hea vikint roch!<strong> {{PLURAL:$2|0=|Tujea sodan mellelem panui polloi.|Tujea sodan mellelem panamui polloi.}}",
        "searchprofile-articles": "Mozkurachim panam",
-       "searchprofile-project": "Adar ani Project panam",
        "searchprofile-images": "Bhovmadhiom",
        "searchprofile-everything": "Sogllem",
        "searchprofile-advanced": "Sodpache poryay",
        "searchprofile-articles-tooltip": "$1 hantunt sod",
-       "searchprofile-project-tooltip": "$1 hantunt sod",
        "searchprofile-images-tooltip": "Faili sod",
        "searchprofile-everything-tooltip": "Akhea sitin sod (Bhasabhas panant'ui)",
        "searchprofile-advanced-tooltip": "chalu nanvthollancher sod",
        "recentchanges-label-minor": "Ho ek dhaktto sudar",
        "recentchanges-label-bot": "Hem bodlop eka robotan kel'lem",
        "recentchanges-label-unpatrolled": "Hem sudharop azun topasunk nam",
-       "rcnotefrom": "Sokoil '''$2''' savn zalelim bodolpam dileant ( '''$1'''meren dakhoileant).",
-       "rclistfrom": "$1 savn suru zatelim novim bodolpam dakhoi",
+       "rcnotefrom": "Sokoil <strong>$2<strong> savn zalelim bodolpam dileant ( <strong>$1<strong> meren dakhoileant).",
+       "rclistfrom": "$3 $2 savn suru zatelim novim bodolpam dakhoi",
        "rcshowhideminor": "$1 dhaktteo sudarnneo",
        "rcshowhidebots": "$1 robot",
-       "rcshowhideliu": "$1 sotrromb kelele vapuddpi",
+       "rcshowhideliu": "$1 nond zalele vapuddpi",
        "rcshowhideanons": "$1 nanv-naslelim vapurpi",
        "rcshowhidepatr": "$1 topaslele sudharop",
        "rcshowhidemine": "Mhojem sudarop $1",
        "upload": "Fail upload kor",
        "uploadlogpage": "Uploadachem sotr",
        "filedesc": "Sar",
-       "uploadedimage": " \"[[$1]]\" upload zalem",
        "watchthisupload": "Hea faylar dixtt dovor",
        "license": "Porvangi",
        "license-header": "Porvangi",
        "speciallogtitlelabel": "Vishoi vo vapurpi:",
        "log": "Sotram",
        "allpages": "Sogllim panam",
-       "alphaindexline": "$1 savn $2",
        "nextpage": "Mukklem pan ($1)",
        "prevpage": "Ad'dlem pan ($1)",
        "allpagesfrom": "Hanga thavn suru zatelea panank dakhoi:",
        "watch": "Sadur rav",
        "watchthispage": "Hea panar dixtt dovor",
        "unwatch": "Nodor kadd",
-       "watchlist-details": "Tujea sadurvollerint {{PLURAL:$1|$1 pan asa|$1 panam asat}}, ulovpachim panam mezonastanam.",
+       "watchlist-details": "Tujea sadurvollerint {{PLURAL:$1|$1 pan asa|$1 panam asat}}, ulovpachim panam veglim mezonastanam.",
        "wlheader-showupdated": "Tujea fatle bhette san bodol'lean tim panam '''datt''' dakhoileant.",
        "wlshowlast": "Xevottchim $1 voram $2 dis $3 dakhoi",
        "watchlist-options": "Sadurvollericheo poryay",
index 36237d0..01dc517 100644 (file)
        "talkpagelinktext": "Διαλέγεσθαι",
        "specialpage": "Εἰδικὴ δέλτος",
        "personaltools": "Ἴδια ἐργαλεῖα",
-       "postcomment": "Νέον τμῆμα",
        "articlepage": "Χρήματος δέλτον ὁρᾶν",
        "talk": "Διάλεξις",
        "views": "Προβολαί",
        "externaldberror": "Συνέβη εἴτε σφάλμα τι πιστοποιήσεως τῆς βάσεως δεδομένων εἴτε οὐκ ἔξεστί σοι ἐνημεροῦν τὸν ἐξωτερικὸν λογισμόν σου.",
        "login": "Συνδεῖσθαι",
        "nav-login-createaccount": "Συνδεῖσθαι/λογισμὸν ποιεῖν",
-       "loginprompt": "Δεῖ ἐνεργὰ τὰ HTTP-πύσματα εἶναι πρὸ τοῦ συνδεῖσθαι τῷ {{SITENAME}}.",
        "userlogin": "Συνδεῖσθαι/λογισμὸν ποιεῖν",
        "userloginnocreate": "Συνδεῖσθαι",
        "logout": "Ἐξέρχεσθαι",
        "searchprofile-everything-tooltip": "Πανταχοῖ (καὶ τὰς δέλτους διαλέξεως) ζητεῖν.",
        "searchprofile-advanced-tooltip": "Ζητεῖν εἰς συνήθη ὀνοματεῖα",
        "search-result-size": "$1 ({{PLURAL:$2|1 λέξις|$2 λέξεις}})",
-       "search-result-score": "Σχετικότης: $1%",
        "search-redirect": "(ἀναδιευθύνειν $1)",
        "search-section": "(τμῆμα $1)",
        "search-suggest": "Συνίης: $1",
        "file-exists-duplicate": "Τὸ ἀρχεῖον ἐστὶ διπλότυπον τοῦ/τῶν ἑξῆς {{PLURAL:$1|ἀρχείου|ἀρχείων}}:",
        "uploadwarning": "Προμήνυσις ἐπιφορτίσεως",
        "savefile": "Σῴζειν ἀρχεῖον",
-       "uploadedimage": "ἐπιπεφορτισμένον \"[[$1]]\"",
-       "overwroteimage": "νέα ἔκδοσις τῆς \"[[$1]]\" ἐπιπεφορτισμένη",
        "uploaddisabled": "Μὴ ἐνεργαὶ αἱ ἐπιφορτίσεις",
        "uploaddisabledtext": "Ἐπιφορτίσεις ἀρχείων μὴ ἐνεργαὶ.",
        "php-uploaddisabledtext": "Αἱ ἐπιφορτώσεις ἀρχείων εἰσὶν ἀνενεργοὶ ἐν τῇ PHP.\nἜλεγξον τὴν ῥύθμισιν file_uploads.",
        "notvisiblerev": "Ἀναθεώρησις διαγεγραμμένη",
        "watchlist-details": "{{PLURAL:$1|$1 δέλτος|$1 δέλτοι}} ἐφορωμέναι, ἄνευ τῶν δέλτων διαλέξεως περιλαμβανομένων.",
        "wlheader-enotif": "Σύστημα εἰδήσεως μέσῳ ἠλ-ἐπιστολῶν ἐνεργόν.",
+       "wlnote": "Κατωτέρω {{PLURAL:$1|ἐστὶν ἡ ὑστάτη μεταβολὴ|εἰσὶν αἱ ὑστάται  '''$1'''  μεταβολαὶ}} ἐν {{PLURAL:$2|τῇ ὑστάτῃ μίᾳ ὥρᾳ|ταῖς ὑστάταις '''$2''' ὥραις}}.",
        "wlshowlast": "Ἐμφάνισις τῶν τελευταίων $1 ὡρῶν $2 ἡμερῶν $3",
        "watchlist-options": "Ἐπιλογαὶ ἐφοροδιαλογῆς",
        "watching": "Ἐφορῶν...",
index d47eab5..97e5b09 100644 (file)
        "permalink": "Bschtändigi URL",
        "print": "Drucke",
        "view": "Aaluege",
+       "view-foreign": "Uf $1 aaluege",
        "edit": "Ändere",
+       "edit-local": "Lokali Bschrybig bearbeite",
        "create": "Erstelle",
+       "create-local": "Lokali Bschrybig zuefiege",
        "editthispage": "Syte bearbeite",
        "create-this-page": "Die Syte afange",
        "delete": "Lesche",
        "talkpagelinktext": "Diskussion",
        "specialpage": "Spezialsyte",
        "personaltools": "Persönlichi Wärkzüg",
-       "postcomment": "Neje Abschnitt",
        "articlepage": "Syte",
        "talk": "Diskussion",
        "views": "Wievylmol agluegt",
        "jumptonavigation": "Navigation",
        "jumptosearch": "Suech",
        "view-pool-error": "Excusez, d Server sin zur Zyt iberlaschtet.\nS versueche grad zvyl Benutzer die Syte aazluege.\nBitte wart e paar Minute, voreb Du s nomol versuechsch.\n\n$1",
+       "generic-pool-error": "Excusez, d Server sin zur Zyt iberlaschtet.\nS versueche grad zvyl Benutzer die Ressource aazluege.\nBitte wart e paar Momänt, voreb Du s nomol versuechsch.",
        "pool-timeout": "\nDi maximal Wartezyt fir e Lock isch umme",
        "pool-queuefull": "D Warteschlang isch voll",
        "pool-errorunknown": "Nit bekannte Fähler",
+       "pool-servererror": "Dr Poolzellerdienscht isch nit verfiegbar ($1).",
        "aboutsite": "Über {{GRAMMAR:akkusativ|{{SITENAME}}}}",
        "aboutpage": "Project:Über {{UCFIRST:{{GRAMMAR:akkusativ|{{SITENAME}}}}}}",
        "copyright": "Dr Inhalt vu dere Syte stoht unter dr Lizänz $1, wänn s nit andersch aagee isch.",
        "externaldberror": "Entwäder s lit e Fähler bi dr externe Authentifizierung vor, oder Du derfsch Dyy extern Benutzerkonto nid aktualisiere.",
        "login": "Aamälde",
        "nav-login-createaccount": "Aamälde / Konto aalege",
-       "loginprompt": "<small>Für di bir {{SITENAME}} aazmälde, muesch Cookies erloube!</small>",
        "userlogin": "Aamälde/Konto aalege",
        "userloginnocreate": "Aamälde",
        "logout": "Abmälde",
        "gotaccountlink": "»Login fir Benutzer, wu scho aagmäldet sin«",
        "userlogin-resetlink": "Hesch Dyy Aamäldedate vergässe?",
        "userlogin-resetpassword-link": "Passwort vergässe?",
+       "userlogin-helplink2": "Hilf bim Aamälde",
        "userlogin-loggedin": "Du bisch scho as {{GENDER:$1|$1}} aagmäldet.\nBruuch s Formular unte go Di unter eme andere Benutzername aamälde.",
        "userlogin-createanother": "En ander Benutzerkonto aalege",
        "createacct-emailrequired": "E-Mail-Adräss",
        "user-mail-no-addy": "Es isch versuecht worde e E-Mail ohni Angab vunere E-Mail-Adräss z verschigge.",
        "user-mail-no-body": "S isch versuecht wore, ne E-Mail mit eme lääre oder z churze Tekscht z verschicke.",
        "changepassword": "Passwort ändere",
-       "resetpass_announce": "Aamäldig mit em Code, wu per Mail zuegschickt woren isch. Zum d Aamäldig abzschliesse, muesch jetz e nej Passwort wehle.",
+       "resetpass_announce": "Go d Aamäldig abzschließe, muesch e nej Passwort feschtlege.",
        "resetpass_text": "<!-- Tue do dr Text ergänze -->",
        "resetpass_header": "Passwort zrucksetze",
        "oldpassword": "Alts Passwort",
        "retypenew": "Nöis Passwort (es zwöits Mal)",
        "resetpass_submit": "Passwort ibermittle un aamälde",
        "changepassword-success": "Dyy Passwort isch erfolgryych gänderet wore.",
+       "changepassword-throttled": "Du hesch z vilmol versuecht Di aazmälde. Bitte wart $1, voreb Du s non emol versuechsch.",
        "resetpass_forbidden": "S Passwort cha nid gänderet wäre.",
        "resetpass-no-info": "Du muesch Di aamälde zum uf die Syte diräkt zuegryfe z chenne.",
        "resetpass-submit-loggedin": "Passwort ändere",
        "resetpass-submit-cancel": "Abbräche",
        "resetpass-wrong-oldpass": "S temporär oder aktuäll Passwort isch nimi giltig.\nVillicht hesch Dyy Passwort scho gänderet oder e nej temporär Passwort aagforderet.",
+       "resetpass-recycled": "Bitte due Dy Passwort ändere.",
+       "resetpass-temp-emailed": "Du hesch Di mit eme temporäre E-Mail-Code aagmäldet.\nGo d Aamäldig abzschließe, muesch e jetz no ne nej Passwort feschtlege:",
        "resetpass-temp-password": "Temporär Passwort:",
        "resetpass-abort-generic": "D Passwortänderig isch dur e Erwyterig abbroche wore.",
+       "resetpass-expired": "Dy Passwort isch abglofe. Bitte leg e nej Passwort fir d Aamäldig fescht.",
        "passwordreset": "Passwort zruggsetze",
        "passwordreset-text-one": "Fill des Formular uus go Dy Passwort zrucksetze.",
        "passwordreset-text-many": "{{PLURAL:$1|Fill eis vu dr Fälder uus go Dy Passwort zrucksetze.}}",
        "searchprofile-advanced-tooltip": "Suech in wytere Namensryym",
        "search-result-size": "$1 ({{PLURAL:$2|1 Wort|$2 Werter}})",
        "search-result-category-size": "{{PLURAL:$1|1 Kategorii|$1 Kategorie}} ({{PLURAL:$2|1 Unterkategorii|$2 Unterkategorie}}, {{PLURAL:$3|1 Datei|$3 Dateie}})",
-       "search-result-score": "Relevanz: $1 %",
        "search-redirect": "(Wyterleitig $1)",
        "search-section": "(Abschnitt $1)",
        "search-suggest": "Hesch „$1“ gmeint?",
        "uploadwarning": "Warnig",
        "uploadwarning-text": "Bitte tue unte d Dateibsschryybig ändere un versuech s nomol.",
        "savefile": "Datei spychere",
-       "uploadedimage": "het „[[$1]]“ ufeglade",
-       "overwroteimage": "het e neiji Version vu „[[$1]]“ uffeglade",
        "uploaddisabled": "Uffelade deaktiviert",
        "copyuploaddisabled": "S Uffelade iber URL isch abschalte wore.",
        "uploaddisabledtext": "S Uffelade vu Dateie isch deaktiviert.",
        "watchlist-details": "{{PLURAL:$1|1 Syte wird|$1 Sytene wärde}} beobachtet (Diskussionssyte nid zelt, aber ou beobachtet).",
        "wlheader-enotif": "Dr E-Mail-Benochrichtigungsdienscht isch aktiviert.",
        "wlheader-showupdated": "Syte mit Anderige, wu no nit aagluegt sin, sin '''fett''' dargstellt.",
+       "wlnote": "Do {{PLURAL:$1|chunnt di letscht Änderig|chemme di letschte '''$1''' Änderige}} vu dr letschte {{PLURAL:$2|Stund|'''$2''' Stunde}}. Stand: $3, $4 Uhr.",
        "wlshowlast": "Zeig di letschte $1 Stunde $2 Tage $3",
        "watchlist-options": "Aazeigoptione",
        "watching": "Am beobachte …",
        "duplicate-defaultsort": "Obacht: Dr Sortierigsschlüssel „$2“ iberschrybt dr vorig brucht Schlüssel „$1“.",
        "version": "Version",
        "version-extensions": "Installierti Erwyterige",
+       "version-skins": "Benutzeroberflechine",
        "version-specialpages": "Spezialsyte",
        "version-parserhooks": "Parser-Schnittstelle",
        "version-variables": "Variable",
        "version-antispam": "Spamschutz",
-       "version-skins": "Benutzeroberflechine",
        "version-other": "Anders",
        "version-mediahandlers": "Medie-Handler",
        "version-hooks": "Schnittstelle ''(Hook)''",
index 46f1539..26fa4cb 100644 (file)
        "permalink": "સ્થાયી કડી",
        "print": "છાપો",
        "view": "જુઓ",
+       "view-foreign": "$1 પર જુઓ",
        "edit": "ફેરફાર કરો",
+       "edit-local": "સ્થાનિક વર્ણનમાં ફેરફાર કરો",
        "create": "બનાવો",
+       "create-local": "સ્થાનિક વર્ણન ઉમેરો",
        "editthispage": "આ પાનામાં ફેરફાર કરો",
        "create-this-page": "આ પાનું બનાવો",
        "delete": "રદ કરો",
        "talkpagelinktext": "ચર્ચા",
        "specialpage": "ખાસ પાનું",
        "personaltools": "વ્યક્તિગત સાધનો",
-       "postcomment": "નવો વિભાગ",
        "articlepage": "લેખનું પાનું જુઓ",
        "talk": "ચર્ચા",
        "views": "દેખાવો",
        "hidetoc": "છુપાવો",
        "collapsible-collapse": "સંકેલો",
        "collapsible-expand": "વિસ્તારો",
+       "confirmable-confirm": "શું {{GENDER:$1|તમે}} ચોક્કસ છો?",
+       "confirmable-yes": "હા",
+       "confirmable-no": "ના",
        "thisisdeleted": "જુઓ અથવા મૂળરૂપે ફેરવો $1?",
        "viewdeleted": "$1 જોવું છે?",
        "restorelink": "{{PLURAL:$1|એક ભુસીનાખેલો ફેરફાર|$1 ભુસીનાખેલા ફેરફારો}}",
        "externaldberror": "પ્રમાણભૂતતાની ત્રુટી આવી અથવા તમારૂ બહારનુ ખાતું અપડેટ કરવાનો અધિકાર તમને નથી.",
        "login": "પ્રવેશ કરો",
        "nav-login-createaccount": "પ્રવેશ કરો / નવું ખાતું ખોલો",
-       "loginprompt": "{{SITENAME}}માં પ્રવેશ કરવા માટે તમારા બ્રાઉઝરમાં કુકીઝ એનેબલ કરેલી હોવી જોઇશે.",
        "userlogin": "પ્રવેશ કરો / નવું ખાતું ખોલો",
        "userloginnocreate": "પ્રવેશ કરો",
        "logout": "બહાર નીકળો",
        "suspicious-userlogout": "લોગ આઉટ કરવાની તમારી વિનંતિ પૂરી ન કરી શકાઇ. એમ લાગે છે કે તેને તૃટિ પામેલ બ્રાઉઝર કે પ્રોક્સી દ્વારા મોકલાઈ હતી.",
        "createacct-another-realname-tip": "સાચું નામ મરજીયાત છે.\nજો તમે તે આપવાનું પસંદ કરશો, તો તેનો ઉપયોગ તમે કરેલ યોગદાનનું શ્રેય આપવા માટે થશે.",
        "pt-login": "પ્રવેશ કરો",
+       "pt-login-button": "પ્રવેશો",
        "pt-createaccount": "ખાતું બનાવો",
        "pt-userlogout": "બહાર નીકળો",
        "php-mail-error-unknown": "PHPની મેલ() કામગીરીમાં અજ્ઞાત ત્રુટિ",
        "edit-gone-missing": "આ પાને અધ્યતન ન બનાવી શકાયું \nલાગે છે કોઇએ આ પાનું હટાવી દીધું છે",
        "edit-conflict": "સંપાદન સંઘર્ષ.",
        "edit-no-change": "તમારા ફેરફારો અવગણાયા, કેમકે અક્ષરકાયામાં કોઈ ફેરફારાના હતો",
+       "postedit-confirmation-created": "પાનું બનાવવામાં આવ્યું.",
        "postedit-confirmation-saved": "તમે કરેલો ફેરફાર સચવાઈ ગયો છે.",
        "edit-already-exists": "નવું પાનું બનાવી ન શકાયું\nતે પહેલેથી હાજર છે.",
        "defaultmessagetext": "મૂળભૂત સંદેશ લખાણ",
        "invalid-content-data": "અયોગ્ય વિગત માહિતી",
        "content-not-allowed-here": "\"$1\" વિગત [[$2]] પાનાં પર માન્ય નથી",
-       "editwarning-warning": "àª\86 àªªàª¾àª¨à«\81àª\82 àª\9bà«\8bડà«\80 àª¦à«\87શà«\8b àª¤à«\8b àª¤àª®àª¾àª°àª¾ àª«à«\87રફારà«\8b àª¸àª\9aવાશà«\87 àª¨àª¹à«\80àª\82.\nàª\9cà«\8b àª¤àª®à«\87 àªªà«\8dરવà«\87શ àª\95રà«\87લà«\8b àª¹à«\8bય àª¤à«\8b àª¤àª®à«\87 àª\86 àª\9aà«\87તવણà«\80નà«\87 àª¤àª®àª¾àª°à«\80 àªªàª¸àª\82દના \"ફà«\87રફાર\" વિભાગના વિકલ્પો બદલીને બંધ કરી શકો છો.",
+       "editwarning-warning": "àª\86 àªªàª¾àª¨à«\81àª\82 àª\9bà«\8bડà«\80 àª¦à«\87શà«\8b àª¤à«\8b àª¤àª®àª¾àª°àª¾ àª«à«\87રફારà«\8b àª¤àª®à«\87 àª\97à«\81માવà«\80 àª¶àª\95à«\8b àª\9bà«\8b.\nàª\9cà«\8b àª¤àª®à«\87 àªªà«\8dરવà«\87શ àª\95રà«\87લà«\8b àª¹à«\8bય àª¤à«\8b, àª¤àª®à«\87 àª\86 àª\9aà«\87તવણà«\80નà«\87 àª¤àª®àª¾àª°à«\80 àªªàª¸àª\82દàª\97à«\80ના \"{{int:prefs-editing}}\" વિભાગના વિકલ્પો બદલીને બંધ કરી શકો છો.",
        "content-model-wikitext": "વિકિલખાણ",
        "content-model-text": "સાદું લખાણ",
        "content-model-javascript": "જાવાસ્ક્રિપ્ટ",
        "searchprofile-advanced-tooltip": "સ્થાનીય નામસ્થળોમાં શોધો:",
        "search-result-size": "$1 ({{PLURAL:$2|૧ શબ્દ|$2 શબ્દો}})",
        "search-result-category-size": "{{PLURAL:$1|1 સભ્ય|$1 સભ્યો}} ({{PLURAL:$2|1 ઉપ શ્રેણી|$2 ઉપ શ્રેણીઓ}}, {{PLURAL:$3|1 ફાઇલ|$3 ફાઇલો}})",
-       "search-result-score": "પ્રસ્તુતિ: $1%",
        "search-redirect": "(અન્યત્ર પ્રસ્થાન $1)",
        "search-section": "(વિભાગ $1)",
        "search-suggest": "શું તમે $1 કહેવા માંગો છો?",
        "preferences": "પસંદ",
        "mypreferences": "પસંદગીઓ",
        "prefs-edits": "સંપાદનોની સંખ્યા",
-       "prefsnologintext2": "તમારી પસંદગીઓ બદલવા માટે મહેરબાની કરી $1 કરો.",
+       "prefsnologintext2": "તમારી પસંદગીઓ બદલવા માટે મહેરબાની કરી પ્રવેશ કરો.",
        "prefs-skin": "ફલક",
        "skin-preview": "ફેરફાર બતાવો",
        "datedefault": "મારી પસંદ",
        "uploadwarning": "ફાઇલ ચઢાવ ચેતવણી",
        "uploadwarning-text": "કૃપયા ફાઈલ સંબધી વર્ણન સુધારો અને ફરી પ્રયત્ન કરો",
        "savefile": "સાચવો",
-       "uploadedimage": "\"[[$1]]\" ચઢાવ્યું",
-       "overwroteimage": " \"[[$1]]\" ની નવી આવૃત્તિ ચઢાવો.",
        "uploaddisabled": "ફાઇલ ચઢાવ પ્રતિબંધિત",
        "copyuploaddisabled": "URL દ્વાર ફાઇલ ચઢાવ પ્રતિબંધિત",
        "uploaddisabledtext": "ફાઇલ ચઢાવવું નિષ્ક્રીય બનાવ્યું છે",
        "license-header": "પરવાના",
        "nolicense": "કોઇ વિકલ્પ પસંદ નથી કરાયો",
        "license-nopreview": "(ઝલક મોજુદ નથી)",
-       "upload_source_url": " (એક વૈધ , જાહેર URL)",
-       "upload_source_file": "(તમારા કોમ્પ્યુટર પરની એક ફાઇલ)",
+       "upload_source_url": "(યોગ્ય, જાહેર URL માંથી તમે પસંદ કરેલ ફાઇલ)",
+       "upload_source_file": "(તમારા àª\95à«\8bમà«\8dપà«\8dયà«\81àª\9fર àªªàª°àª¨à«\80 àª¤àª®à«\87 àªªàª¸àª\82દ àª\95રà«\87લà«\80 àª\8fàª\95 àª«àª¾àª\87લ)",
        "listfiles-summary": "આ વિશિષ્ટ પાનું બધી અપલોડ કરાયેલી ફાઈલો દર્શાવે છે.",
        "listfiles_search_for": "મિડિયા નામ શોધો:",
        "imgfile": "ફાઇલ",
        "protectedpages-indef": "ફક્ત અનિશ્ચિત સુરક્ષા ધરાવતા પાના",
        "protectedpages-cascade": "માત્ર પગથિયામય સુરક્ષા વાળા પગ",
        "protectedpagesempty": "આ વિકલ્પો દ્વારા કોઈ પાના સુરક્ષિત કરાયા નથી.",
+       "protectedpages-timestamp": "સમયછાપ",
        "protectedpages-page": "પાનું",
+       "protectedpages-expiry": "સમાપ્તિ",
        "protectedpages-reason": "કારણ",
        "protectedpages-unknown-timestamp": "અજ્ઞાત",
        "protectedpages-unknown-performer": "અજ્ઞાત સભ્ય",
        "listgrouprights-removegroup-self": "તેમના પોતાના ખાતમાંથી  {{PLURAL:$2|group|groups}}  હટાવો : $1",
        "listgrouprights-addgroup-self-all": "દરેક જૂથને તેમના પોતાના ખાતા માં ઉમેરો",
        "listgrouprights-removegroup-self-all": "બધા જૂથને તેમના પોતાના ખાતામાંથી હટાવો",
+       "listgrouprights-namespaceprotection-namespace": "નામાવકાશ",
+       "trackingcategories-name": "સંદેશ નામ",
        "mailnologin": "મેળવનારનું સરનામું નથી",
        "mailnologintext": "અન્ય સભ્યને ઇ-મેલ મોકલવા માટે તમે [[Special:UserLogin|logged in]] પ્રવેશ કરેલ હોવો જોઈએ અને તમારા[[Special:Preferences|preferences]] વિકલ્પોમાં તમારા ઈ-મેલ સરનામાની પુષ્ટિ થયેલી હોવી જોઈએ",
        "emailuser": "સભ્યને ઇ-મેલ કરો",
        "watchlist-details": "ચર્ચાનાં પાનાં ન ગણતા {{PLURAL:$1|$1 પાનું|$1 પાનાં}} ધ્યાનસૂચીમાં છે.",
        "wlheader-enotif": "ઈમેલ સૂચના પદ્ધતિ સક્રીય કરાઈ.",
        "wlheader-showupdated": "તમારી છેલ્લી મુલાકાત પછી બદલાયેલાં પાના  '''ઘાટા''' અક્ષરો વડે દર્શાવ્યાં છે.",
+       "wlnote": "નીચે $3, $4 વાગ્યા સુધીના છેલ્લા {{PLURAL:$2|એક કલાક|'''$2''' કલાક}}માં થયેલા {{PLURAL:$1|ફેરફાર|'''$1''' ફેરફારો }} દર્શાવ્યા છે.",
        "wlshowlast": "છેલ્લા $1 કલાક $2 દિવસ $3 બતાવો",
        "watchlist-options": "ધ્યાનસૂચિના વિકલ્પો",
        "watching": "નજર રાખી રહ્યાં છો...",
        "autoblockid": "ઓટોબ્લોક #$1",
        "block": "સભ્ય પર પ્રતિબંધ મુકો",
        "unblock": "સભ્ય પરનો પ્રતિબંધ હટાવો",
-       "blockip": "સભ્ય પર પ્રતિબંધ મુકો",
+       "blockip": "{{GENDER:$1|સભ્ય}} પર પ્રતિબંધ મુકો",
        "blockip-legend": "સભ્ય પર પ્રતિબંધ મુકો",
        "blockiptext": "કોઈ ચોક્કસ IP સરનામું કે સભ્યના લેખન યોગદાન પર પ્રતિબંધ મુકવા નીચેનું ફોર્મ વાપરો.\nતેનો ઉપયોગ માત્ર ભાંગફોડિયા પ્રવૃત્તિઓને રોકવા અને  [[{{MediaWiki:Policy-url}}|નીતિ]] અનુસાર જ હોવો જોઈએ.\nકારણનું ખાનું અવશ્ય ભરશો (દા.ત. અમુક ભાંગફોડ કરાયેલા પાનાનો સંદર્ભ).",
        "ipaddressorusername": "IP સરનામું અથવા સભ્યનામ:",
        "ipb-unblock-addr": "$1 પરનો પ્રતિબંધ ઉઠાવો",
        "ipb-unblock": "સભ્યનામ કે  IP સરનામું અપ્રતિબંધિત કરો.",
        "ipb-blocklist": "વિહરમાન પ્રતિબંધો જુઓ",
-       "ipb-blocklist-contribs": "સભ્ય $1નું યોગદાન",
+       "ipb-blocklist-contribs": "{{GENDER:$1|$1}} નું યોગદાન",
        "unblockip": "સભ્ય પરનો પ્રતિબંધ હટાવો",
        "unblockiptext": "પહેલા રોક લગાડેલ IP સરનામા કે સભ્ય ના પ્રવેશને પુનઃસ્થાપિત કરવા નીચેનું ફોર્મેટ વાપરો.",
        "ipusubmit": "આપ્રતિબંધન હટાવો",
        "import-upload": "XML માહિતી ચઢાવો",
        "import-token-mismatch": "સત્ર સમાપ્ત\nફરી પ્રયત્ન કરો",
        "import-invalid-interwiki": "દર્શાવેલ વિકિ પરથી આયાત નહીં કરી શકાય",
-       "import-error-edit": "પાનà«\81àª\82 \"$1\" àª\86યાત àª¨ àª\95રà«\80 àª¶àª\95ાયà«\81àª\82 àª\95à«\87મàª\95à«\87 àª¤à«\87નà«\87 àª¸àª\82પાદિત àª\95રવાનà«\8b àª¹àª\95à«\8dàª\95 àª¤àª®àª¨à«\87 àªªà«\8dરાપત àª¨àª¥à«\80.",
+       "import-error-edit": "પાનું \"$1\" આયાત ન કરી શકાયું કેમકે તેને સંપાદિત કરવાનો હક્ક તમને નથી.",
        "import-error-create": "પાનું \"$1\" આયાત ન કરી શકાયું કેમકે તેને બનાવવાના હક્ક તમને પ્રાપત નથી.",
        "import-error-interwiki": "\"$1\" પાનું અહીં આયાત કરી ન શકાયું કેમકે તે નામ બાહ્ય કડીઓ  (interwiki) માટે આરક્ષીત છે",
        "import-error-special": "પાનું \"$1\" આયાત કરી શકાયું નહીં કેમકે તે ખાસ નામસ્થળનો ભાગ જે અન્ય પાના ની રજા આપનો નથી.",
-       "import-error-invalid": "\"$1\" આ પાનુમ્ આયાત ન થયું કેમકે નામ અવૈધ છે.",
+       "import-error-invalid": "પાનું \"$1\" આયાત થયું નથી કારણ કે તેનું નામ આ વિકિ માટે અયોગ્ય છે.",
        "importlogpage": "આયાત માહિતિ પત્રક",
        "importlogpagetext": "અન્ય  વિકિમાંથી ઈતિહાસ સહિત પાનાની પ્રબંધકીય આયાત",
        "import-logentry-upload": "ફાઇલ ચઢાવનાર દ્વારા [[$1]] આયાત કરાઇ",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|પુનરાવર્તન|પુનરાવર્તનો}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|પુનરાવર્તન|પુનરાવર્તનો}} આયાત કરેલ છે",
        "import-logentry-interwiki": "આંતરવિકિ  $1",
-       "import-logentry-interwiki-detail": "$2 àª¥à«\80 $1 {{PLURAL:$1|પુનરાવર્તન|પુનરાવર્તનો}}",
+       "import-logentry-interwiki-detail": "$2 àª®àª¾àª\82થà«\80 àª\86યાત àª\95રà«\87લ $1 {{PLURAL:$1|પુનરાવર્તન|પુનરાવર્તનો}}",
        "javascripttest": "જાવા સ્ક્રીપ્ટ પરીક્ષણ",
        "javascripttest-title": "$1 પરીક્ષણ જારી",
        "javascripttest-pagetext-noframework": "આ પાનું જાવા સ્ક્રીપ્ટ ચલાવવા આરક્ષિત છે.",
        "pageinfo-redirects-name": "આ પાનાં પર દિશાનિર્દેશનોની સંખ્યા",
        "pageinfo-subpages-name": "આ પાનાંનું ઉપપાનું",
        "pageinfo-firstuser": "પૃષ્ઠ સર્જક",
-       "pageinfo-firsttime": "પà«\83ષà«\8dઠ àª¸àª°à«\8dàª\9cનની તારીખ",
+       "pageinfo-firsttime": "પાનાàª\82 àª¬àª¨àª¾àªµàªµàª¾ની તારીખ",
        "pageinfo-lastuser": "છેલ્લો ફેરફાર કરનાર",
        "pageinfo-lasttime": "છેલ્લા ફેરફારની તારીખ",
        "pageinfo-edits": "કુલ સંપાદનોની સંખ્યા",
        "months": "{{PLURAL:$1|$1 મહિનો|$1 મહિનાઓ}}",
        "years": "{{PLURAL:$1|$1 વર્ષ|$1 વર્ષો}}",
        "ago": "$1 પહેલાં",
-       "just-now": "હમણાં",
+       "just-now": "હમણાં જ",
        "hours-ago": "$1 {{PLURAL:$1|કલાક|કલાકો}} ago",
        "minutes-ago": "$1 {{PLURAL:$1|મિનિટ|મિનિટો}} ago",
        "seconds-ago": "$1 {{PLURAL:$1|સેકંડ|સેકંડો}} ago",
        "confirm-watch-top": "આ પાનું તમારી ધ્યાનસૂચિમાં ઉમેરો?",
        "confirm-unwatch-button": "બરાબર",
        "confirm-unwatch-top": "આ પાનું તમારી ધ્યાનસૂચીમાથી કાઢી નાખો",
+       "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← પાછલું પાનું",
        "imgmultipagenext": "આગલું પાનું →",
        "imgmultigo": "જાઓ!",
        "watchlistedit-raw-done": "તમારી ધ્યાના સૂચિ અધ્યતન કરાઈ.",
        "watchlistedit-raw-added": "{{PLURAL:$1|1 શીર્ષક |$1 શીર્ષકો}} ઉમેરાયા :",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1 શીર્ષક |$1 શીર્ષકો  }} હટાવાયા :",
+       "watchlistedit-clear-titles": "શીર્ષકો:",
        "watchlisttools-view": "બંધબેસતાં ફેરફારો નિહાળો",
        "watchlisttools-edit": "ધ્યાનસૂચી જુઓ અને બદલો",
        "watchlisttools-raw": "કાચી ધ્યાનસૂચિમાં ફેરફાર કરો",
        "duplicate-defaultsort": "'''ચેતવણી:'''  કી \"$2\" આગળનામૂળે પ્રસ્થાપિત ક્રમિકાવર્ગીકરણ કી \"$1\"નું સ્થાન લઈ લેશે..",
        "version": "આવૃત્તિ",
        "version-extensions": "પ્રસ્થાપિત વિસ્તારકો",
+       "version-skins": "સ્થાપિત ફલકો",
        "version-specialpages": "ખાસ પાનાં",
        "version-parserhooks": "પદચ્છેદ ખૂંટો",
        "version-variables": "ચલ",
        "version-antispam": "સ્પેમ સંરક્ષણ",
-       "version-skins": "ફલક",
        "version-other": "અન્ય",
        "version-mediahandlers": "દ્રશ્યશ્રાવ્ય માધ્યમના ધારક",
        "version-hooks": "ખૂંટા",
        "version-hook-name": "ખૂંટાનું નામ્",
        "version-hook-subscribedby": "દ્વ્રારા લાભાન્વીત",
        "version-version": "(આવૃત્તિ $1)",
+       "version-no-ext-name": "[નામ નથી]",
        "version-license": "મીડિઆવિકિ લાયસન્સ",
        "version-ext-license": "લાયસન્સ",
+       "version-skin-colheader-name": "ફલક",
        "version-ext-colheader-version": "આવૃત્તિ",
        "version-ext-colheader-license": "લાયસન્સ",
        "version-ext-colheader-description": "વર્ણન",
        "htmlform-no": "ના",
        "htmlform-yes": "હા",
        "htmlform-chosen-placeholder": "વિકલ્પ પસંદ કરો",
+       "htmlform-cloner-create": "વધુ ઉમેરો",
+       "htmlform-cloner-delete": "હટાવો",
        "sqlite-has-fts": "$1 પૂર્ણ શબ્દ શોધ સહીત",
        "sqlite-no-fts": "$1 પૂર્ણ શબ્દ  શોધ વિકલ્પ વગર",
        "logentry-delete-delete": "$1 દ્વારા પાનું $3 {{GENDER:$2|દૂર કરવામાં આવ્યું}}",
        "expand_templates_xml_output": "XML આઉટપુટ",
        "expand_templates_ok": "મંજૂર",
        "expand_templates_remove_comments": "ટીપ્પણીઓ દૂર કરો",
-       "expand_templates_preview": "પૂર્વાવલોકન"
+       "expand_templates_preview": "પૂર્વાવલોકન",
+       "pagelang-name": "પાનું",
+       "pagelang-language": "ભાષા",
+       "pagelang-select-lang": "ભાષા પસંદ કરો",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (સક્રિય)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''નિષ્ક્રિય''')"
 }
index 23cbf79..ebce018 100644 (file)
        "talkpagelinktext": "Resoonaght",
        "specialpage": "Duillag er lheh",
        "personaltools": "Greienyn persoonagh",
-       "postcomment": "Meer noa",
        "articlepage": "Jeeagh er y duillag chummal",
        "talk": "Resoonaght",
        "views": "Reayrtyn",
        "remembermypassword": "Cooinnee m'ockle arrey (rish wheesh as $1 {{PLURAL:$1|laa|laa|laa|laaghyn}})",
        "login": "Log stiagh",
        "nav-login-createaccount": "Log stiagh / croo coontys",
-       "loginprompt": "Shegin dhyt cur pooar da minniagyn dy loggal stiagh ayns {{SITENAME}}.",
        "userlogin": "Log stiagh / croo coontys",
        "userloginnocreate": "Log stiagh",
        "logout": "Log magh",
        "searchprofile-images-tooltip": "Ronsee coadanyn",
        "searchprofile-everything-tooltip": "Ronsee dagh red (goaill stiagh duillagyn resoonaght)",
        "search-result-size": "$1 ({{PLURAL:$2|1 fockle|$2 'ockle|$2 'ockle|$2 focklyn}})",
-       "search-result-score": "Bentynys: $1%",
        "search-redirect": "(aa-enmyssit ass $1)",
        "search-section": "(rheynn $1)",
        "search-suggest": "R'ou çheet er: $1",
        "filesource": "Bun:",
        "badfilename": "T'ennym y choadan aa-enmyssit myr \"$1\".",
        "savefile": "Sauail y coadan",
-       "uploadedimage": "\"[[$1]]\" laadit neese",
        "uploadvirus": "Ta veerys 'sy choadan! Mynphoyntyn: $1",
        "watchthisupload": "Freill arrey er y choadan shoh",
        "upload-file-error": "Marranys ynveanagh",
index 3f4f994..76e5945 100644 (file)
@@ -1,7 +1,8 @@
 {
        "@metadata": {
                "authors": [
-                       "Mladanali"
+                       "Mladanali",
+                       "아라"
                ]
        },
        "tog-underline": "A shaya zaruruwa",
@@ -14,7 +15,6 @@
        "tog-showtoolbar": "A nuna sandar kayan aiki ta gyarawa (ana buƙatar JavaScript)",
        "tog-editondblclick": "A gyara shafuna da dabar-kiliki (ana buƙatar JavaScript)",
        "tog-editsectiononrightclick": "A lamunta gyara shashe da kilikin dama a kan kanun shashe (ana buƙatar JavaScript)",
-       "tog-rememberpassword": "A adana bayanan loginkina a wannan kwamfyuta (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "tog-watchcreations": "A daɗa shafunan da na ƙirƙira a cikin jerina na kan ido",
        "tog-watchdefault": "A daɗa shafunan da na gyara a cikin jerina na kan ido",
        "tog-watchmoves": "A daɗa shafunan da na gusar a cikin jerina na kan ido",
        "navigation": "Shawagi",
        "qbfind": "Nemo",
        "qbedit": "Gyarawa",
-       "vector-action-delete": "Soke",
-       "vector-action-move": "Gusarwa",
-       "vector-action-protect": "A kare",
-       "vector-view-create": "Ƙirƙira",
        "errorpagetitle": "Tangarɗa",
        "returnto": "Koma $1",
        "tagline": "Daga {{SITENAME}}",
        "searchall": "duka",
        "powersearch-legend": "Sahihin nema",
        "powersearch-ns": "Binciki sararen sunaye:",
-       "powersearch-redir": "Nuna turawa gaba",
        "powersearch-toggleall": "Duka",
        "preferences": "Saituttuka",
        "mypreferences": "Saituttukana",
        "recentchanges": "Sauye-sauyen baya-bayan nan",
        "recentchanges-legend": "Zaɓi na sauye-sauyen baya-bayan nan",
        "recentchanges-feed-description": "Bi sawun sauye-sauyen ƙarshe na wikin da ke cikin wannan kwarare",
-       "rclistfrom": "Nuna sabbin sauye-sauye tun daga $1",
+       "rclistfrom": "Nuna sabbin sauye-sauye tun daga $3 $2",
        "rcshowhideminor": "$1 ƙananen sauye-sauye",
        "rcshowhidebots": "Rabuwat $1",
        "rcshowhideliu": "$1 Ma'aikata logaggi",
        "uploadlogpage": "Rajistan girke fayiloli",
        "filedesc": "Taƙaici",
        "fileuploadsummary": "Taƙaici:",
-       "uploadedimage": "an girke \"[[$1]]\"",
        "filehist": "Tarihin fayil",
        "filehist-help": "ku Latsa rana/lokaci ku ga fayil yadda yake a wannan lokaci",
        "filehist-deleteone": "soke",
        "booksources-go": "Mu je",
        "log": "Rajistoci ayyuka",
        "allpages": "Duka shafuna",
-       "alphaindexline": "$1 zuwa $2",
        "prevpage": "Shafi na baya ($1)",
        "allpagesfrom": "Nuna shafuna farawa daga:",
        "allpagesto": "Nuna shafuna har:",
index a900ad5..cb43f56 100644 (file)
@@ -10,7 +10,9 @@
                        "Urhixidur",
                        "Xiaomingyan",
                        "아라",
-                       "Mywood"
+                       "Mywood",
+                       "Impersonator 1",
+                       "LNDDYL"
                ]
        },
        "tog-underline": "鏈接加底線:",
        "talkpagelinktext": "交流",
        "specialpage": "特殊頁面",
        "personaltools": "私人工具",
-       "postcomment": "新段落",
        "articlepage": "查看內容頁面",
        "talk": "討論",
        "views": "查看數",
        "externaldberror": "邇可能係由於驗證數據庫差錯或者汝分系統禁止更新汝嘅外部賬號。",
        "login": "登入",
        "nav-login-createaccount": "登入/建立新帳號",
-       "loginprompt": "汝必須啟用Cookies正做得成功登入{{SITENAME}}。",
        "userlogin": "登入/建立新帳號",
        "userloginnocreate": "登入",
        "logout": "登出",
        "fileexists-shared-forbidden": "在共享文件庫中既存在同名文件。\n係話汝仍然想愛上載其嘅話,請返回並用一隻新名來上傳邇隻文件。[[File:$1|thumb|center|$1]]",
        "uploadwarning": "上傳警告",
        "savefile": "保存文件",
-       "uploadedimage": "已上傳“[[$1]]”",
        "uploaddisabled": "上傳己停用。",
        "uploaddisabledtext": "Tóng-on song-chhòn chhai chhṳ́ miong-chham put hí-khó yung.",
        "php-uploaddisabledtext": "PHP文件上傳已經停用。請檢查file_uploads設定。",
        "watchlist-details": "毋包含交流頁,汝嘅監視列表上有$1隻頁面。",
        "wlheader-enotif": "Yí-kîn khí-thung email thûng-tî kûng-nèn.",
        "wlheader-showupdated": "Chhai ngì song-chhṳ kiám-sṳ heu yû pûn chhùng-siû ko ke vùn-chông chiông-voi hién-sṳ vi '''chhû-thí'''.",
+       "wlnote": "Yî-ha he chui-khiûn <b>$2</b> séu-sṳ̀ nui-ke chui-heu $1-chhṳ chin-siû.",
        "wlshowlast": "展示最近$1隻鐘頭,$2日或$3嘅更改。",
        "watchlist-options": "監視列表選項",
        "watching": "監視中...",
index bfba9bb..acb72ef 100644 (file)
        "talkpagelinktext": "Walaʻau",
        "specialpage": "‘Ao‘ao kūikawā",
        "personaltools": "Hāmeʻa ponoʻī",
-       "postcomment": "Māhele hou",
        "articlepage": "Nānā i ka ʻaoʻao mealoko",
        "talk": "walaʻau",
        "views": "Nānaina",
        "copyrightpage": "{{ns:project}}:Kūleana kope",
        "currentevents": "Nūhou",
        "currentevents-url": "Project:Nūhou",
-       "disclaimers": "Nā Akahele",
+       "disclaimers": "Akahana",
        "disclaimerpage": "Project:Akahele Laulaha",
        "edithelp": "Kōkua ho‘ololi",
        "mainpage": "Papa Kinohi",
        "hidetoc": "hoʻohūnā",
        "collapsible-collapse": "Hoʻoliʻi",
        "collapsible-expand": "Hoʻākea",
+       "confirmable-confirm": "He ʻoiaʻiʻo nō?",
+       "confirmable-yes": "ʻAe",
+       "confirmable-no": "ʻAʻole",
        "thisisdeleted": "Nānā ai‘ole hō‘āla iā $1?",
        "viewdeleted": "Nānā iā $1?",
        "restorelink": "{{PLURAL:$1|kekahi loli holoi|$1 mau loli holoi}}",
        "cascadeprotected": "Ho‘omalu ‘ia kēia ‘ao‘ao mai e ho‘opololei ana, no ka mea, hoʻokomo pū ‘ia ‘oia ma aia {{PLURAL:$1|‘ao‘ao|nā ‘ao‘ao}} i lalo, ho‘omalu ‘ia me ka \"e wailele ana\" koho:\n$2",
        "ns-specialprotected": "‘A‘ole hiki ke ho‘ololi i nā ‘ao‘ao kūikawā",
        "exception-nologin": "ʻE‘e ʻole",
+       "exception-nologin-text": "E ʻoluʻolu e ʻeʻe no ke komo ʻana i kēia ʻaoʻao a i ʻole ka ʻae no kēia hana.",
+       "exception-nologin-text-manual": "E ʻoluʻolu, e $1 no ke komo ʻana i kēia ʻaoʻao a i ʻole ka ʻae no kēia hana.",
        "welcomeuser": "Welina mai e $1!",
        "yourname": "Inoa mea ho'ohana:",
        "userlogin-yourname": "Inoa mea hoʻohana",
        "userlogin-remembermypassword": "Hoʻomanaʻo iaʻu",
        "login": "ʻEʻe",
        "nav-login-createaccount": "ʻEʻe / Kāinoa",
-       "loginprompt": "Pono ʻoe e hoʻā i nā makana no ka ʻeʻe ʻana iā {{SITENAME}}.",
        "userlogin": "ʻEʻe / Kāinoa",
        "userloginnocreate": "ʻEʻe",
        "logout": "Haʻalele",
        "pt-createaccount": "Kāinoa",
        "pt-userlogout": "Haʻalele",
        "changepassword": "E hoʻololi i ka ʻōlelo hūnā",
+       "resetpass_header": "Hoʻololi i ka ʻōlelo hūnā moʻokāki",
        "oldpassword": "ʻŌlelo hūnā kahiko:",
        "newpassword": "ʻŌlelo hūnā hou:",
        "retypenew": "E kikokiko hou i ka ʻōlelo hūnā hou:",
        "resetpass_submit": "Kau i ka ʻōlelo hūnā a ʻeʻe",
        "changepassword-success": "Ua hoʻololi ‘ia kāu hua‘ōlelo huna!",
+       "changepassword-throttled": "Nui ʻino ka hana ʻeʻe ʻana.\nE kali no $1 ma mua o ka hana hou ʻana ke ʻoluʻolu.",
+       "resetpass_forbidden": "ʻAʻole hiki ke hoʻololi i nā ʻōlelo hūnā",
+       "resetpass-no-info": "Pono ʻoe e ʻeʻe no ke komo pono ʻana o kēia ʻaoʻao.",
        "resetpass-submit-loggedin": "Hoʻololi i ka ʻōlelo hūnā",
        "resetpass-submit-cancel": "Hoʻōki",
        "resetpass-temp-password": "ʻŌlelo hūnā kūikawā:",
+       "resetpass-expired": "Ua pau kāu ʻōlelo hūnā. E ʻoluʻolu, e loaʻa kahi ʻōlelo hūnā hou no ka ʻeʻe ʻana.",
        "passwordreset": "Kāinoa hou i ka ʻōlelo hūnā",
        "passwordreset-legend": "Kāinoa hou i ka ʻōlelo hūnā",
        "passwordreset-username": "Inoa mea ho'ohana:",
        "passwordreset-email": "Wahinoho lekauila:",
+       "changeemail": "Hoʻololi i ka wahinoho lekauila",
+       "changeemail-header": "Hoʻololi i ka wahinoho lekauila moʻokāki",
        "changeemail-oldemail": "Wahinoho lekauila hananei:",
        "changeemail-newemail": "Wahinoho lekauila hou:",
        "changeemail-none": "(ʻaʻohe)",
        "showpreview": "E hō'ike i ka nāmua",
        "showdiff": "E hō'ike i nā loli",
        "anoneditwarning": "<strong>E akahele:</strong> ʻAʻole ʻoe ʻeʻe nei.\nE hoʻopaʻa ʻia ana kāu IP ma ko kēia ʻaoʻao mōʻaukala hoʻololi.",
+       "missingcommenttext": "E kikokiko i kekahi kaumanaʻo i lalo, ke ʻoluʻolu.",
        "summary-preview": "Nāmua hōʻuluʻulu manaʻo:",
        "blockedtitle": "Ua pale ‘ia ka mea ho‘ohana",
        "blockednoreason": "‘a‘ohe kumu",
+       "whitelistedittext": "E ʻoluʻolu, e $1 no ka hoʻololi ʻaoʻao ʻana.",
        "loginreqtitle": "Noi i ka ʻeʻe ʻana",
        "loginreqlink": "ʻeʻe",
        "accmailtitle": "Ua ho‘ouna ‘ia ka ‘ōlelo hūnā",
        "anontalkpagetext": "----\n<em>ʻO kēia ka ʻaoʻao kūkākūkā no kekahi mea ho‘ohana me ka inoa ʻole.</em>\nNo laila, pono mākou e ho‘ohana i ka IP no ka hōʻoia ʻana iā ia a hiki i kekahi mau mea hoʻohana ke hoʻokaʻana i kēia  IP.\nInā he mea ho‘ohana inoa ʻole ʻoe a loaʻa kekahi mau manaʻo nāuʻole, e ʻoluʻolu [[Special:UserLogin/signup|e kāinoa]] a i ʻole [[Special:UserLogin|e ʻeʻe]].''",
        "noarticletext": "ʻAʻohe kikokikona a kēia ʻaoʻao.\nHiki iā ʻoe ke [[Special:Search/{{PAGENAME}}|huli no kēia inoa ʻaoʻao]] i nā ʻaoʻao ʻē aʻe, <span class=\"plainlinks\">[{{fullurl:SpecialLog|page={{FULLPAGENAMEE}}}} huli i nā moʻolelo pili], a i ʻole [{{fullurl:{{FULLPAGENAME}}|action=edit}} hoʻololi i kēia ʻaoʻao]</span>.",
        "noarticletext-nopermission": "ʻAʻohe kikokikona a kēia ʻaoʻao.\nHiki iā ʻoe ke [[Special:Search/{{PAGENAME}}|huli no kēia inoa ʻaoʻao]] i nā ʻaoʻao ʻē aʻe aiʻole <span class=\"plainlinks\">[{{fullurl:SpecialLog|page={{FULLPAGENAMEE}}}} huli i nā moʻolelo pili]</span>, akā hiki ʻole iā ʻoe ke hoʻololi i kēia ʻaoʻao.",
+       "userpage-userdoesnotexist-view": "ʻAʻole kāinoa ʻia ka moʻokāki mea hoʻohana ʻo \"$1\".",
        "updated": "(Hoʻopuka hou ʻia)",
        "note": "<strong>E noka:</strong>",
        "previewnote": "<strong>ʻO kēia ka nāmua wale nō.</strong>\n‘A‘ole mālama ‘ia nā ho‘ololi!",
        "protectedpagewarning": "<strong>E akahele:  Ua hoʻomalu ‘ia kēia ‘ao‘ao, pēlā, hiki i nā \"kahu\" ke ho‘ololi wale nō.</strong>\nAia nā loli hanalohi i lalo no ka ʻikena:",
        "templatesused": "{{PLURAL:$1|anakuhi|mau anakuhi}} e hana ʻia ma kēia ʻaoʻao:",
        "templatesusedpreview": "Hoʻohana ʻia kēia {{PLURAL:$1|anakuhi|mau anakuhi}} i kēia nāmua:",
+       "templatesusedsection": "{{PLURAL:$1|Ka anakuhi|Nā anakuhi}} e hana ʻia i kēia mahele:",
        "template-protected": "(ho‘omalu ‘ia)",
        "template-semiprotected": "(hapa-ho‘omalu ‘ia)",
        "hiddencategories": "ʻO kēia ʻaoʻao he lālā o {{PLURAL:$1|1 mahele hūnā|$1 mau māhele hūnā}}:",
        "recreate-moveddeleted-warn": "<strong>E akahele: Ke haku nei ʻoe i kekahi ʻaoʻao i holoi ʻia.</strong>\n\nPono ʻoe e noʻonoʻo e pili ana ka pono o ka hoʻomau ʻana o ka hoʻololi ʻana o kēia ʻaoʻao.\nAia ka moʻolelo holoi a hoʻoneʻe no kēia ʻaoʻao ma ʻaneʻi:",
        "moveddeleted-notice": "Ua holoi ʻia kēia ʻaoʻao.\nHoʻolako ʻia ka moʻolelo holoi a hoʻoneʻe no kēia ʻaoʻao i lalo no ke kūmole.",
        "log-fulllog": "Nānā i ka moʻolelo piha",
+       "postedit-confirmation-created": "Ua haku ʻia ka ʻaoʻao.",
        "postedit-confirmation-saved": "Ua mālama ʻia kāu hoʻololi",
        "defaultmessagetext": "Kikokikona pūlono pa‘amau",
        "content-model-wikitext": "kikokikonawiki",
        "content-model-javascript": "IawaSikulipa",
+       "content-model-css": "CSS",
        "post-expand-template-inclusion-warning": "<strong>E akahele:</strong> Hoʻokela ʻia ka palena nui o ke anakuhi.\nHoʻohui ʻole i kekahi mau anakuhi.",
        "post-expand-template-inclusion-category": "Nā ʻaoʻao me nā anakuhi e hoʻokela i ka palenanui",
        "post-expand-template-argument-warning": "<strong>E akahele:</strong> Aia ma kēia ʻaoʻao i kekahi a ʻoi pilikia anakuhi e loaʻa i kekahi nui hoʻonui nunui loa.\nUa waiho ʻia kēia mau pilikia.",
        "history-feed-title": "Mōʻaukala kāmua",
        "history-feed-description": "Mōʻaukala kāmua no kēia ʻaoʻao ma ka wiki",
        "history-feed-item-nocomment": "$1 ma $3 ma ka hola $4",
+       "rev-deleted-comment": "wehe ʻia ka hōʻuluʻulu manaʻo hoʻololi)",
+       "rev-deleted-user": "(wehe ʻia ka inoa mea hoʻohana)",
        "rev-delundel": "hoʻololi ka nānā ʻana",
        "rev-showdeleted": "hōʻike",
        "revisiondelete": "Holoi/holoi ʻole i nā kāmua",
        "revdelete-reasonotherlist": "Nā kumu ʻē aʻe",
        "revdelete-edit-reasonlist": "Hoʻololi i nā kumu holoi",
        "revdelete-offender": "Mea kākau kāmua:",
+       "mergehistory": "Hoʻokuʻi pū i nā mōʻaukala ʻaoʻao",
        "mergehistory-from": "ʻAoʻao kūmole:",
        "mergehistory-into": "ʻAoʻao helewahi:",
        "mergehistory-reason": "Kumu:",
+       "mergelog": "Moʻolelo hoʻokuʻi pū",
        "revertmerge": "Hoʻokuʻipū ʻole",
        "history-title": "Mōʻaukala kāmua o \"$1\"",
        "lineno": "Laina $1:",
        "search-external": "Huli kūwaho",
        "preferences": "Kaʻu makemake",
        "mypreferences": "Ka‘u makemake",
+       "prefs-edits": "Helu o nā hoʻololi:",
+       "prefsnologintext2": "E ʻeʻe no ka hoʻololi ʻana o kāu makemake, ke ʻoluʻolu.",
        "prefs-skin": "ʻIli",
        "skin-preview": "Nāmua",
        "datedefault": "ʻAʻohe makemake",
        "prefs-namespaces": "Lewainoa",
        "default": "paʻamau",
        "prefs-files": "Waihona",
+       "prefs-emailconfirm-label": "Hōʻoia lekauila:",
        "youremail": "Lekauila:",
        "username": "{{GENDER:$1|Inoa mea hoʻohana}}:",
        "prefs-memberingroups": "{{GENDER:$2|He lālā}} o {{PLURAL:$1|hui|mau hui}}:",
        "prefs-diffs": "ʻOkoʻa",
        "prefs-help-prefershttps": "E hana ana kēia makemake i ka ʻeʻe hou ana.",
        "userrights": "Ho‘oponopono ‘ana o nā kuleana",
+       "userrights-user-editname": "E kikokiko i kekahi inoa mea hoʻohana:",
+       "editusergroup": "Hoʻololi i nā hui mea hoʻohana",
+       "userrights-editusergroup": "Hoʻololi i nā hui mea hoʻohana",
+       "saveusergroups": "Mālama i nā hui mea hoʻohana",
        "userrights-groupsmember": "He lālā o:",
        "userrights-reason": "Kumu:",
        "group": "Hui:",
        "right-bigdelete": "Holoi i nā ʻaoʻao me he mōʻaukala nui",
        "right-browsearchive": "Huli i nā ʻaoʻao holoi",
        "right-undelete": "Holoi ʻole i kekahi ʻaoʻao",
+       "right-suppressionlog": "Nānā i nā moʻolelo pilikino",
        "right-block": "Pale i nā mea hoʻohana ʻē aʻe mai ka hoʻololi ʻana",
        "right-blockemail": "Pale i nā mea hoʻohana ʻē aʻe mai ka lekauila ʻana",
        "right-hideuser": "Pale i ka inoa mea hoʻohana, no laila ʻaʻole hōʻike i ka lehulehu",
        "action-createpage": "haku ʻaoʻao",
        "action-createtalk": "haku ʻaoʻao kūkākūkā",
        "action-createaccount": "kāinoa i kēia moʻokāki mea hoʻohana",
+       "action-move": "hoʻoneʻe i kēia ʻaoʻao",
+       "action-move-subpages": "hoʻoneʻe i kēia ʻaoʻao a me nā ʻaoʻao kūloko hoʻi.",
+       "action-movefile": "hoʻoneʻe i kēia waihona",
+       "action-upload": "hoʻouka i kēia waihona",
+       "action-delete": "holoi i kēia ʻaoʻao",
+       "action-sendemail": "lekauila",
        "nchanges": "$1 {{PLURAL:$1|loli|mau loli}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|mai kāu kipana aku nei}}",
        "enhancedrc-history": "mōʻaukala",
        "filesource": "Kumu:",
        "uploadwarning": "Akahele hoʻouka",
        "savefile": "Waihona mālama",
-       "uploadedimage": "ua hoʻouka iā \"[[$1]]\"",
        "upload-source": "Waihona kūmole",
        "sourcefilename": "Inoa waihona kūmole:",
        "sourceurl": "URL kūmole:",
        "filedelete-reason-otherlist": "Nā kumu ʻē aʻe",
        "download": "hoʻoili",
        "randompage": "ʻAtikala Kaulele",
-       "randomincategory-selectcategory-submit": "Huli",
        "statistics": "ʻIkepilihelu",
        "statistics-header-pages": "ʻIkepilihelu ʻaoʻao",
        "statistics-header-edits": "ʻIkepilihelu hoʻololi",
        "watchlisttools-raw": "Hoʻololi i ka papakiaʻi maka",
        "duplicate-defaultsort": "<strong>E akahele:</strong> Mauʻaʻe ke kī kaʻalike paʻamau \"$2\" i ke kī kaʻalike paʻamau \"$1\" mai ka wā mua.",
        "version-specialpages": "Nā ‘Ao‘ao kūikawā",
-       "version-poweredby-translators": "Mea unuhi translatewiki.net",
+       "version-poweredby-translators": "nā mea unuhi ma translatewiki.net",
        "version-software-version": "Mana",
        "redirect": "Kiahou e ka waihona, ka mea hoʻohana, ka ʻaoʻao aiʻole ka ID loihape",
        "redirect-legend": "Kiahou i kekahi waihona aiʻole kekahi ʻaoʻao",
index d4e2ecf..a39efc3 100644 (file)
@@ -43,6 +43,7 @@
        "tog-watchdefault": "מעקב אחרי דפים וקבצים שערכתי",
        "tog-watchmoves": "מעקב אחרי דפים וקבצים שהעברתי",
        "tog-watchdeletion": "מעקב אחרי דפים וקבצים שמחקתי",
+       "tog-watchrollback": "מעקב אחרי דפים שבהם ביצעתי שחזור מהיר",
        "tog-minordefault": "הגדרת כל פעולת עריכה כמשנית אם לא צוין אחרת",
        "tog-previewontop": "הצגת תצוגה מקדימה לפני תיבת העריכה",
        "tog-previewonfirst": "הצגת תצוגה מקדימה בעריכה ראשונה",
        "talkpagelinktext": "שיחה",
        "specialpage": "דף מיוחד",
        "personaltools": "כלים אישיים",
-       "postcomment": "פסקה חדשה",
        "articlepage": "צפייה בדף התוכן",
        "talk": "שיחה",
        "views": "צפיות",
        "otherlanguages": "דף זה בשפות אחרות",
        "redirectedfrom": "(הופנה מהדף $1)",
        "redirectpagesub": "דף הפניה",
+       "redirectto": "הפניה ל:",
        "lastmodifiedat": "שונה לאחרונה ב־$2, $1.",
        "viewcount": "דף זה נצפה {{PLURAL:$1|פעם אחת|פעמיים|$1 פעמים}}.",
        "protectedpage": "דף מוגן",
        "privacypage": "Project:מדיניות הפרטיות",
        "badaccess": "שגיאה בהרשאות",
        "badaccess-group0": "אינכם מורשים לבצע את הפעולה שביקשתם.",
-       "badaccess-groups": "הפעולה שביקשתם לבצע מוגבלת למשתמשים ב{{PLURAL:$2|קבוצה הבאה|אחת הקבוצות הבאות}}: $1.",
+       "badaccess-groups": "הפעולה שביקשת לבצע מוגבלת למשתמשים ב{{PLURAL:$2|קבוצה הבאה|אחת הקבוצות הבאות}}: $1.",
        "versionrequired": "נדרשת גרסה $1 של מדיה־ויקי",
        "versionrequiredtext": "גרסה $1 של מדיה־ויקי נדרשת לשימוש בדף זה. למידע נוסף, ראו את [[Special:Version|דף הגרסה]].",
        "ok": "אישור",
        "hidetoc": "הסתרה",
        "collapsible-collapse": "הסתרה",
        "collapsible-expand": "הצגה",
+       "confirmable-confirm": "האם {{GENDER:$1|ברצונך}} להמשיך?",
+       "confirmable-yes": "כן",
+       "confirmable-no": "לא",
        "thisisdeleted": "לשחזר או להציג $1?",
        "viewdeleted": "להציג $1?",
        "restorelink": "{{PLURAL:$1|גרסה מחוקה אחת|$1 גרסאות מחוקות}}",
        "viewsource": "הצגת מקור",
        "viewsource-title": "הצגת המקור של $1",
        "actionthrottled": "הפעולה הוגבלה",
-       "actionthrottledtext": "×\9b×\90×\9eצע×\99 × ×\92×\93 ×¡×¤×\90×\9d, ×\90×\99× ×\9b×\9d ×\9e×\95רש×\99×\9d ×\9c×\91צע ×¤×¢×\95×\9c×\94 ×\96×\95 ×¤×¢×\9e×\99×\9d ×¨×\91×\95ת ×\9e×\93×\99 ×\91×\96×\9e×\9f ×§×¦×¨. אנא נסו שוב בעוד מספר דקות.",
+       "actionthrottledtext": "×\9b×\90×\9eצע×\99 × ×\92×\93 ×¡×¤×\90×\9d, ×§×\99×\99×\9eת ×\9e×\92×\91×\9c×\94 ×¢×\9c ×\91×\99צ×\95×¢ ×¤×¢×\95×\9c×\94 ×\96×\95 ×¤×¢×\9e×\99×\9d ×¨×\91×\95ת ×\9e×\93×\99 ×\91×\96×\9e×\9f ×§×¦×¨, ×\95×\97ר×\92ת×\9d ×\9e×\94×\9e×\92×\91×\9c×\94 ×\94×\96×\95.\nאנא נסו שוב בעוד מספר דקות.",
        "protectedpagetext": "דף זה מוגן כדי למנוע עריכה ופעולות אחרות.",
        "viewsourcetext": "באפשרותך לצפות בטקסט המקור של הדף ולהעתיקו:",
        "viewyourtext": "באפשרותכם לצפות בטקסט המקור של '''העריכות שלכם''' של הדף ולהעתיקו:",
        "editinginterface": "'''אזהרה:''' הדף שאתם עורכים הוא אחד הדפים המספקים הודעות מערכת לתוכנה.\nשינויים בדף זה ישפיעו על תצוגת ממשק המשתמש של משתמשים אחרים באתר ויקי זה.\nכדי להוסיף או לשנות תרגומים בכל אתרי הוויקי, אנא השתמשו ב־[//translatewiki.net/ translatewiki.net], פרויקט התרגום של מדיה־ויקי.",
        "cascadeprotected": "דף זה מוגן מעריכה כי הוא מוכלל {{PLURAL:$1|בדף הבא, שמופעלת עליו|בדפים הבאים, שמופעלת עליהם}} הגנה מדורגת:\n$2",
        "namespaceprotected": "אינכם מורשים לערוך דפים במרחב השם '''$1'''.",
-       "customcssprotected": "×\90×\99× ×\9b×\9d ×\9e×\95רש×\99×\9d ×\9cער×\95×\9a ×\93×£ CSS ×\96×\94, ×\9b×\99×\95×\95×\9f ×©×\94×\95×\90 ×\9b×\95×\9c×\9c ×\90ת ×\94×\94×\92×\93ר×\95ת ×\94אישיות של משתמש אחר.",
-       "customjsprotected": "×\90×\99× ×\9b×\9d ×\9e×\95רש×\99×\9d ×\9cער×\95×\9a ×\93×£ JavaScript ×\96×\94, ×\9b×\99×\95×\95×\9f ×©×\94×\95×\90 ×\9b×\95×\9c×\9c ×\90ת ×\94×\94×\92×\93ר×\95ת ×\94אישיות של משתמש אחר.",
+       "customcssprotected": "×\90×\99× ×\9a ×\9e×\95רש×\94 ×\9cער×\95×\9a ×\93×£ CSS ×\96×\94 ×\9b×\99×\95×\95×\9f ×©×\94×\95×\90 ×\9b×\95×\9c×\9c ×\94×\92×\93ר×\95ת אישיות של משתמש אחר.",
+       "customjsprotected": "×\90×\99× ×\9a ×\9e×\95רש×\94 ×\9cער×\95×\9a ×\93×£ JavaScript ×\96×\94 ×\9b×\99×\95×\95×\9f ×©×\94×\95×\90 ×\9b×\95×\9c×\9c ×\94×\92×\93ר×\95ת אישיות של משתמש אחר.",
        "mycustomcssprotected": "אינכם מורשים לערוך דף CSS זה.",
        "mycustomjsprotected": "אינכם מורשים לערוך דף JavaScript זה.",
        "myprivateinfoprotected": "אין לך הרשאה לערוך את המידע הפרטי שלך",
        "invalidtitle-knownnamespace": "כותרת בלתי־תקינה עם מרחב השם \"$2\" ושם דף \"$3\"",
        "invalidtitle-unknownnamespace": "כותרת בלתי־תקינה עם מרחב שם בלתי־ידוע מספר $1 ושם דף \"$2\"",
        "exception-nologin": "לא בחשבון",
-       "exception-nologin-text": "אנא [[Special:Userlogin|היכנסו לחשבון]] כדי לראות את הדף הזה או לבצע את הפעולה הזו.",
+       "exception-nologin-text": "אנא היכנסו לחשבון כדי לראות את הדף הזה או לבצע את הפעולה הזו.",
        "exception-nologin-text-manual": "אנא $1 כדי לראות את הדף הזה או לבצע את הפעולה הזו.",
        "virus-badscanner": "הגדרות שגויות: סורק הווירוסים אינו ידוע: ''$1''",
        "virus-scanfailed": "הסריקה נכשלה (קוד: $1)",
        "externaldberror": "הייתה שגיאה בבסיס הנתונים של ההזדהות, או שאינכם רשאים לעדכן את חשבונכם החיצוני.",
        "login": "כניסה לחשבון",
        "nav-login-createaccount": "כניסה לחשבון / הרשמה",
-       "loginprompt": "לפני הכניסה לחשבון ב{{grammar:תחילית|{{SITENAME}}}}, עליכם לוודא כי ה\"עוגיות\" (Cookies) מופעלות.",
        "userlogin": "כניסה לחשבון / הרשמה",
        "userloginnocreate": "כניסה לחשבון",
        "logout": "יציאה מהחשבון",
        "userlogin-resetlink": "שכחת את פרטי הכניסה?",
        "userlogin-resetpassword-link": "שכחת את הסיסמה?",
        "userlogin-helplink2": "עזרה בכניסה לחשבון",
-       "userlogin-loggedin": "אתם כבר מחוברים לחשבון {{GENDER:$1|$1}}.\nהשתמשו בטופס שלהלן כדי להתחבר לחשבון אחר.",
-       "userlogin-createanother": "יצירת חשבון אחר",
        "createacct-emailrequired": "כתובת דוא\"ל",
        "createacct-emailoptional": "כתובת דוא\"ל (לא חובה)",
        "createacct-email-ph": "יש להקליד את כתובת הדוא\"ל שלך",
        "noemail": "לא רשומה כתובת דואר אלקטרוני עבור ה{{GENDER:$1|משתמש|משתמשת}} \"$1\".",
        "noemailcreate": "יש לספק כתובת דואר אלקטרוני תקינה.",
        "passwordsent": "סיסמה חדשה נשלחה לכתובת הדואר האלקטרוני הרשומה עבור \"$1\".\nאנא היכנסו חזרה לאתר אחרי שתקבלו אותה.",
-       "blocked-mailpassword": "×\9bת×\95×\91ת ×\94Ö¾IP ×©×\9c×\9b×\9d ×\97ס×\95×\9e×\94 ×\9eער×\99×\9b×\94, ×\95×\9cפ×\99×\9b×\9a ×\90×\99× ×\9b×\9d ×\9e×\95רש×\99×\9d ×\9c×\94שת×\9eש ×\91×\90פשר×\95ת ×©×\97×\96×\95ר ×\94ס×\99ס×\9e×\94 כדי למנוע ניצול לרעה של התכונה.",
+       "blocked-mailpassword": "×\9bת×\95×\91ת ×\94Ö¾IP ×©×\9c×\9a × ×\97ס×\9e×\94 ×\9eער×\99×\9b×\94, ×\95×\9cפ×\99×\9b×\9a ×\90×\99× ×\9a ×\9e×\95רש×\94 ×\9c×\94שת×\9eש ×\91×\90פשר×\95ת ×©×\97×\96×\95ר ×\94ס×\99ס×\9e×\94, ×\95×\96×\90ת כדי למנוע ניצול לרעה של התכונה.",
        "eauthentsent": "דוא\"ל אימות נשלח לכתובת הדוא\"ל שצוינה.\nלפני שדברי דוא\"ל אחרים יישלחו לחשבון הזה, יהיה עליכם לפעול לפי ההוראות בדוא\"ל, כדי לאשר שהחשבון אכן שייך לכם.",
        "throttled-mailpassword": "כבר נשלח דוא\"ל לאיפוס הסיסמה ב{{PLURAL:$1|שעה האחרונה|שעתיים האחרונות|־$1 השעות האחרונות}}.\nכדי למנוע ניצול לרעה, יכול להישלח רק דוא\"ל אחד כזה בכל {{PLURAL:$1|שעה|שעתיים|$1 שעות}}.",
        "mailerror": "שגיאה בשליחת דואר: $1",
        "createaccount-text": "מישהו יצר חשבון בשם $2 ב{{grammar:תחילית|{{SITENAME}}}} ($4), והסיסמה הזמנית של החשבון היא \"$3\". עליכם להיכנס ולשנות עכשיו את הסיסמה.\n\nבאפשרותכם להתעלם מהודעה זו, אם החשבון נוצר בטעות.",
        "login-throttled": "ביצעתם לאחרונה ניסיונות רבים מדי להיכנס לחשבון זה.\nאנא המתינו $1 לפני שתנסו שוב.",
        "login-abort-generic": "הכניסה לחשבון לא הצליחה - היא הופסקה",
+       "login-migrated-generic": "חשבון המשתמש שלך הועבר, ושם המשתמש שלך כבר לא קיים באתר ויקי זה.",
        "loginlanguagelabel": "שפה: $1",
        "suspicious-userlogout": "בקשתך לצאת מהחשבון נדחתה כיוון שנראה שהיא נשלחה על־ידי דפדפן שבור או שרת פרוקסי עם זיכרון מטמון.",
        "createacct-another-realname-tip": "השם האמיתי הוא אופציונאלי.\nאם תבחרו לספקו, הוא ישמש לייחוס עבודת המשתמש אליו.",
        "changeemail": "שינוי כתובת דוא\"ל",
        "changeemail-header": "שינוי כתובת הדואר האלקטרוני בחשבון",
        "changeemail-text": "מלאו טופס זה כדי לשנות את כתובת הדואר האלקטרוני שלכם. יהיה עליכם למלא סיסמה כדי לאשר את השינוי.",
-       "changeemail-no-info": "×¢×\9c×\99×\9b×\9d להיכנס לחשבון כדי לגשת לדף זה ישירות.",
+       "changeemail-no-info": "×\99ש להיכנס לחשבון כדי לגשת לדף זה ישירות.",
        "changeemail-oldemail": "כתובת דוא\"ל נוכחית:",
        "changeemail-newemail": "כתובת דוא\"ל חדשה:",
        "changeemail-none": "(אין)",
        "preview": "תצוגה מקדימה",
        "showpreview": "תצוגה מקדימה",
        "showdiff": "הצגת שינויים",
-       "anoneditwarning": "'''אזהרה:''' אינכם מחוברים לחשבון. כתובת ה־IP שלכם תירשם בהיסטוריית העריכות של הדף.",
+       "blankarticle": "<strong>אזהרה:</strong> הדף שאתם יוצרים הוא ריק.\nאם תלחצו שוב על \"{{int:savearticle}}\", הדף ייווצר ללא תוכן.",
+       "anoneditwarning": "<strong>אזהרה:</strong> אינכם מחוברים לחשבון. כתובת ה־IP שלכם תוצג בפומבי אם תבצעו עריכות כלשהן. אם <strong>[$1 תיכנסו לחשבון]</strong> או <strong>[$2 תיצרו חשבון]</strong>, העריכות שלכם תיוחסנה לשם המשתמש שלכם ותקבלו גם יתרונות אחרים.",
        "anonpreviewwarning": "''אינכם מחוברים לחשבון. שמירה תגרום לכתובת ה־IP שלכם להירשם בהיסטוריית העריכות של הדף.''",
        "missingsummary": "'''תזכורת:''' לא הזנתם תקציר עריכה.\nאם תלחצו שוב על הכפתור \"{{int:savearticle}}\", עריכתכם תישמר בלעדיו.",
        "missingcommenttext": "אנא הקלידו את ההודעה למטה.",
        "subject-preview": "תצוגה מקדימה של הנושא/הכותרת:",
        "blockedtitle": "המשתמש חסום",
        "blockedtext": "'''שם המשתמש או כתובת ה־IP שלכם נחסמו.'''\n\nהחסימה בוצעה על ידי $1. הסיבה שניתנה לכך היא '''$2'''.\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותכם ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון על החסימה.\nאינכם יכולים להשתמש בתכונת \"שליחת דואר אלקטרוני למשתמש זה\" אם לא ציינתם כתובת דוא\"ל תקפה ב[[Special:Preferences|העדפות המשתמש שלכם]] או אם נחסמתם משליחת דוא\"ל.\nכתובת ה־IP שלכם היא $3, ומספר החסימה שלכם הוא #$5.\nאנא ציינו את כל הפרטים הללו בכל פנייה למפעילי המערכת.",
-       "autoblockedtext": "×\9bת×\95×\91ת ×\94Ö¾IP ×©×\9c×\9b×\9d × ×\97ס×\9e×\94 ×\91×\90×\95פ×\9f ×\90×\95×\98×\95×\9e×\98×\99 ×\9b×\99×\95×\95×\9f ×©×\9eשת×\9eש ×\90×\97ר, ×©× ×\97ס×\9d ×¢×\9cÖ¾×\99×\93×\99 $1, ×¢×©×\94 ×\91×\94 ×©×\99×\9e×\95ש.\n×\94ס×\99×\91×\94 ×©× ×\99תנ×\94 ×\9c×\97ס×\99×\9e×\94 ×\94×\99×\90:\n\n:<em>$2</em>\n\n* ×ª×\97×\99×\9cת ×\94×\97ס×\99×\9e×\94: $8\n* ×¤×§×\99עת ×\94×\97ס×\99×\9e×\94: $6\n* ×\94×\97ס×\99×\9e×\94 ×©×\91×\95צע×\94: $7\n\n×\91×\90פשר×\95ת×\9b×\9d ×\9c×\99צ×\95ר ×§×©×¨ ×¢×\9d $1 ×\90×\95 ×¢×\9d ×\9b×\9c ×\90×\97×\93 ×\9e[[{{MediaWiki:Grouppage-sysop}}|×\9eפע×\99×\9c×\99 ×\94×\9eער×\9bת]] ×\94×\90×\97ר×\99×\9d ×\9b×\93×\99 ×\9c×\93×\95×\9f ×\91×\97ס×\99×\9e×\94.\n\n×\91×\90פשר×\95ת×\9b×\9d ×\9c×\94שת×\9eש ×\91ת×\9b×\95נת \"{{int:emailuser}}\", ×\90×\9c×\90 ×\90×\9d ×\9c×\90 ×¦×\99×\99נת×\9d ×\9bת×\95×\91ת ×\93×\95×\90\"×\9c ×ª×§×¤ה ב[[Special:Preferences|העדפות המשתמש שלכם]] או אם נחסמתם משליחת דוא\"ל.\n\nכתובת ה־IP שלכם היא $3, ומספר החסימה שלכם הוא #$5.\nאנא ציינו את כל הפרטים הללו בכל פנייה למפעילי המערכת.",
+       "autoblockedtext": "×\9bת×\95×\91ת ×\94Ö¾IP ×©×\9c×\9b×\9d × ×\97ס×\9e×\94 ×\91×\90×\95פ×\9f ×\90×\95×\98×\95×\9e×\98×\99 ×\9b×\99×\95×\95×\9f ×©×\9eשת×\9eש ×\90×\97ר, ×©× ×\97ס×\9d ×¢×\9cÖ¾×\99×\93×\99 $1, ×\94שת×\9eש ×\91×\94.\n×\94ס×\99×\91×\94 ×©× ×\99תנ×\94 ×\9c×\97ס×\99×\9e×\94 ×\94×\99×\90:\n\n:<em>$2</em>\n\n* ×ª×\97×\99×\9cת ×\94×\97ס×\99×\9e×\94: $8\n* ×¤×§×\99עת ×\94×\97ס×\99×\9e×\94: $6\n* ×\94×\97ס×\99×\9e×\94 ×©×\91×\95צע×\94: $7\n\n×\91×\90פשר×\95ת×\9b×\9d ×\9c×\99צ×\95ר ×§×©×¨ ×¢×\9d $1 ×\90×\95 ×¢×\9d ×\9b×\9c ×\90×\97×\93 ×\9e[[{{MediaWiki:Grouppage-sysop}}|×\9eפע×\99×\9c×\99 ×\94×\9eער×\9bת]] ×\94×\90×\97ר×\99×\9d ×\9b×\93×\99 ×\9c×\93×\95×\9f ×\91×\97ס×\99×\9e×\94.\n\n×\91×\90פשר×\95ת×\9b×\9d ×\9c×\94שת×\9eש ×\91ת×\9b×\95נת \"ש×\9c×\99×\97ת ×\93×\95×\90ר ×\90×\9cק×\98ר×\95× ×\99 ×\9c×\9eשת×\9eש ×\96×\94\", ×\90×\9c×\90 ×\90×\9d ×\9c×\90 ×¦×\99×\99נת×\9d ×\9bת×\95×\91ת ×\93×\95×\90\"×\9c ×ª×§×\99× ה ב[[Special:Preferences|העדפות המשתמש שלכם]] או אם נחסמתם משליחת דוא\"ל.\n\nכתובת ה־IP שלכם היא $3, ומספר החסימה שלכם הוא #$5.\nאנא ציינו את כל הפרטים הללו בכל פנייה למפעילי המערכת.",
        "blockednoreason": "לא ניתנה סיבה",
        "whitelistedittext": "עליכם $1 כדי לערוך דפים.",
        "confirmedittext": "עליכם לאמת את כתובת הדוא\"ל שלכם לפני שתוכלו לערוך דפים. אנא הגדירו ואמתו את כתובת הדוא\"ל שלכם באמצעות [[Special:Preferences|העדפות המשתמש]] שלכם.",
        "accmailtext": "סיסמה אקראית עבור [[User talk:$1|$1]] נשלחה אל $2. ניתן לשנותה בדף '''[[Special:ChangePassword|שינוי הסיסמה]]''' לאחר הכניסה.",
        "newarticle": "(חדש)",
        "newarticletext": "הגעתם לדף שעדיין איננו קיים.\nכדי ליצור את הדף הזה, התחילו להקליד בתיבת הטקסט למטה (ראו את [$1 דף העזרה] למידע נוסף).\nאם הגעתם לכאן בטעות, לחצו על כפתור ה<strong>חזרה</strong> (Back) בדפדפן שלכם.",
-       "anontalkpagetext": "----\n'''זהו דף שיחה של משתמש אנונימי שעדיין לא יצר חשבון במערכת, או שהוא לא משתמש בו. כיוון שכך, אנו צריכים להשתמש בכתובת ה־IP כדי לזהותו. ייתכן שכתובת IP זו תייצג מספר משתמשים. אם אתם משתמשים אנונימיים ומרגישים שקיבלתם הודעות בלתי רלוונטיות, אנא [[Special:UserLogin|היכנסו לחשבון]] או [[Special:UserLogin/signup|הירשמו לאתר]] כדי להימנע מבלבול עתידי עם משתמשים אנונימיים נוספים.'''\n----",
+       "anontalkpagetext": "----\n<em>זהו דף שיחה של משתמש אנונימי שעדיין לא יצר חשבון במערכת, או שהוא לא משתמש בו.</em>\nלכן עלינו להשתמש בכתובת ה־IP המספרית כדי לזהותו.\nייתכן שכתובת IP זו תהיה משותפת למספר משתמשים.\nאם אתם משתמשים אנונימיים ומרגישים שקיבלתם הודעות בלתי רלוונטיות, אנא [[Special:UserLogin/signup|צרו חשבון]] או [[Special:UserLogin|היכנסו לחשבון]] כדי להימנע מבלבול עתידי עם משתמשים אנונימיים נוספים.",
        "noarticletext": "אין כרגע טקסט בדף זה.\nבאפשרותכם [[Special:Search/{{PAGENAME}}|לחפש את כותרת הדף]] בדפים אחרים,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} לחפש ביומנים הרלוונטיים],\nאו [{{fullurl:{{FULLPAGENAME}}|action=edit}} לערוך דף זה]</span>.",
        "noarticletext-nopermission": "אין כרגע טקסט בדף זה.\nבאפשרותכם [[Special:Search/{{PAGENAME}}|לחפש את כותרת הדף]] בדפים אחרים,\nאו <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} לחפש ביומנים הרלוונטיים]</span>,\nאך אינכם מורשים ליצור את הדף.",
        "missing-revision": "גרסה #$1 של הדף \"{{FULLPAGENAME}}\" אינה קיימת.\n\nזה נגרם בדרך כלל על־ידי לחיצה על קישור ישן לגרסה קודמת של דף שנמחק.\nאפשר למצוא פרטים ב[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} יומן המחיקות].",
        "parser-template-recursion-depth-warning": "עומק התבניות המוכללות זו בזו עבר את המגבלה ($1)",
        "language-converter-depth-warning": "עומק ממיר השפה עבר את המגבלה ($1)",
        "node-count-exceeded-category": "דפים שבהם מספר הצמתים גדול מדי",
-       "node-count-exceeded-category-desc": "ק×\98×\92×\95ר×\99×\94 ×\9c×\93פ×\99×\9d ×©×\9eספר ×\94צ×\9eת×\99×\9d ×\91×\94×\9d ×\92×\93×\95×\9c ×\9e×\93י.",
+       "node-count-exceeded-category-desc": "×\9eספר ×\94צ×\9eת×\99×\9d ×\91×\93×£ ×\92×\93×\95×\9c ×\9e×\94×\9eספר ×\94×\9eר×\91י.",
        "node-count-exceeded-warning": "מספר הצמתים בדף גדול מדי",
        "expansion-depth-exceeded-category": "דפים שבהם עומק ההרחבה גדול מדי",
-       "expansion-depth-exceeded-category-desc": "×\96×\95×\94×\99 ×§×\98×\92×\95ר×\99×\94 ×\9c×\93פ×\99×\9d ×©×\91×\94×\9d ×¢×\95×\9eק ×\94×\94ר×\97×\91×\94 ×\92×\93×\95×\9c ×\9e×\93י.",
+       "expansion-depth-exceeded-category-desc": "×¢×\95×\9eק ×\94×\94ר×\97×\91×\94 ×\91×\93×£ ×\92×\93×\95×\9c ×\9e×\94×¢×\95×\9eק ×\94×\9eר×\91י.",
        "expansion-depth-exceeded-warning": "עומק ההרחבה בדף גדול מדי",
        "parser-unstrip-loop-warning": "נמצאה לולאה בפריסה",
        "parser-unstrip-recursion-limit": "עומק הרקורסיה של הפריסה עבר את המגבלה ($1)",
        "rev-deleted-user": "(שם המשתמש הוסר)",
        "rev-deleted-event": "(פעולת היומן הוסרה)",
        "rev-deleted-user-contribs": "[שם המשתמש או כתובת ה־IP הוסרו – העריכה הוסתרה מדף התרומות]",
-       "rev-deleted-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}}/suppress|page={{FULLPAGENAMEE}}}} יומן ההסתרות].\nאתם עדיין יכולים [$1 לצפות בגרסה] אם ברצונכם להמשיך.",
+       "rev-deleted-text-permission": "גרסת הדף הזו <strong>נמחקה</strong>.\nניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} יומן המחיקות].",
+       "rev-suppressed-text-permission": "גרסת הדף הזו <strong>הועלמה</strong>.\nניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} יומן ההעלמות].",
+       "rev-deleted-text-unhide": "גרסת הדף הזו <strong>נמחקה</strong>.\nניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} יומן המחיקות].\nאתם עדיין יכולים [$1 לצפות בגרסה הזו] אם ברצונכם להמשיך.",
+       "rev-suppressed-text-unhide": "גרסת הדף הזו <strong>הועלמה</strong>.\nניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} יומן ההעלמות].\nאתם עדיין יכולים [$1 לצפות בגרסה הזו] אם ברצונכם להמשיך.",
        "rev-deleted-text-view": "גרסת הדף הזו '''נמחקה'''.\nאתם יכולים לצפות בה; ניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} יומן המחיקות].",
-       "rev-suppressed-text-view": "גרסת הדף הזו '''הוסתרה'''.\nאתם יכולים לצפות בה; ניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} יומן ההסתרות].",
+       "rev-suppressed-text-view": "גרסת הדף הזו <strong>הועלמה</strong>.\nאתם יכולים לצפות בה; ניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} יומן ההעלמות].",
        "rev-deleted-no-diff": "אינכם יכולים לצפות בהבדלים בין הגרסאות שציינתם משום שאחת מהן '''נמחקה'''.\nניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} יומן המחיקות].",
        "rev-suppressed-no-diff": "אינכם יכולים לצפות בהבדלים בין הגרסאות שציינתם משום שאחת מהן '''נמחקה'''.",
        "rev-deleted-unhide-diff": "אחת מהגרסאות שביקשתם להשוות '''נמחקה'''.\nניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} יומן המחיקות].\nאתם עדיין יכולים [$1 לצפות בהבדלים בין הגרסאות] אם ברצונכם להמשיך.",
-       "rev-suppressed-unhide-diff": "אחת מהגרסאות שביקשתם להשוות '''הוסתרה'''.\nניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/suppress|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": "אחת מהגרסאות שביקשתם להשוות '''הוסתרה'''.\nאתם יכולים לצפות בהבדלים בין הגרסאות; ניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} יומן ההסתרות].",
+       "rev-suppressed-diff-view": "אחת מהגרסאות שביקשתם להשוות <strong>הועלמה</strong>\nאתם יכולים לצפות בהבדלים בין הגרסאות; ניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} יומן  ההעלמות].",
        "rev-delundel": "הצגה/הסתרה",
        "rev-showdeleted": "הצגה",
        "revisiondelete": "מחיקה ושחזור של גרסאות",
        "revdelete-text-text": "גרסאות שנמחקו עדיין תופענה בהיסטוריית הדף, אך חלקים מהתוכן שלהן לא יהיו זמינים לציבור.",
        "revdelete-text-file": "גרסאות קבצים שנמחקו עדיין תופענה בהיסטוריית הקובץ, אך חלקים מהתוכן שלהן לא יהיו זמינים לציבור.",
        "logdelete-text": "פעולות יומן שנמחקו עדיין תופענה בדפי היומנים, אך חלקים מהתוכן שלהן לא יהיו זמינים לציבור.",
-       "revdelete-text-others": "×\9eפע×\99×\9c×\99 ×\9eער×\9bת ×\90×\97ר×\99×\9d ×\91×\90תר ×¢×\93×\99×\99×\9f ×\99×\95×\9b×\9c×\95 ×\9c×\92שת ×\9cת×\95×\9b×\9f ×\94נסתר ×\95×\99×\95×\9b×\9c×\95 ×\9cש×\97×\96ר ×\90×\95ת×\95 ×©×\95×\91 ×\93ר×\9a ×\94×\9e×\9eשק ×\94×\96×\94, אלא אם כן תוגדרנה הגבלות נוספות.",
+       "revdelete-text-others": "×\9eפע×\99×\9c×\99 ×\9eער×\9bת ×\90×\97ר×\99×\9d ×¢×\93×\99×\99×\9f ×\99×\95×\9b×\9c×\95 ×\9c×\92שת ×\9cת×\95×\9b×\9f ×\94נסתר ×\9b×\93×\99 ×\9cש×\97×\96ר ×\90×\95ת×\95, אלא אם כן תוגדרנה הגבלות נוספות.",
        "revdelete-confirm": "אנא אשרו שזה אכן מה שאתם מתכוונים לעשות, שאתם מבינים את התוצאות של מעשה כזה, ושהמעשה מבוצע בהתאם ל[[{{MediaWiki:Policy-url}}|נוהלי האתר]].",
-       "revdelete-suppress-text": "×\99ש ×\9c×\94שת×\9eש ×\91×\94סתר×\94 ×\9e×\9c×\90×\94 '''×\90×\9a ×\95רק''' ×\91×\9eקר×\99×\9d ×\94×\91×\90×\99×\9d:\n* ×\9e×\99×\93×¢ ×©×¢×\9c×\95×\9c ×\9c×\94×\99×\95ת ×\9cש×\95×\9f ×\94רע\n* ×\97ש×\99פת ×\9e×\99×\93×¢ ×\90×\99ש×\99\n*: '''×\9bת×\95×\91×\95ת ×\91ת×\99×\9d ×\95×\9eספר×\99 ×\98×\9cפ×\95×\9f, ×\9eספר×\99 ×\96×\99×\94×\95×\99 ×\9e×\93×\99נת×\99×\99×\9d, ×\95×\9b×\93×\95×\9e×\94'''",
+       "revdelete-suppress-text": "×\99ש ×\9c×\94שת×\9eש ×\91×\94×¢×\9c×\9e×\94 '''×\90×\9a ×\95רק''' ×\91×\9eקר×\99×\9d ×\94×\91×\90×\99×\9d:\n* ×\9e×\99×\93×¢ ×©×¢×\9c×\95×\9c ×\9c×\94×\99×\95ת ×\9cש×\95×\9f ×\94רע\n* ×\97ש×\99פת ×\9e×\99×\93×¢ ×\90×\99ש×\99\n*: <em>×\9bת×\95×\91×\95ת ×\91ת×\99×\9d ×\95×\9eספר×\99 ×\98×\9cפ×\95×\9f, ×\9eספר×\99 ×\96×\94×\95ת, ×\95×\9b×\95'</em>",
        "revdelete-legend": "הגדרת הגבלות התצוגה",
        "revdelete-hide-text": "תוכן הגרסה",
        "revdelete-hide-image": "הסתרת תוכן הקובץ",
        "revdelete-hide-name": "הסתרת הפעולה ודף היעד",
        "revdelete-hide-comment": "תקציר העריכה",
        "revdelete-hide-user": "שם המשתמש או כתובת ה־IP של העורך",
-       "revdelete-hide-restricted": "×\94סתרת המידע גם ממפעילי המערכת",
+       "revdelete-hide-restricted": "×\94×¢×\9c×\9eת המידע גם ממפעילי המערכת",
        "revdelete-radio-same": "(ללא שינוי)",
        "revdelete-radio-set": "מוסתר",
        "revdelete-radio-unset": "גלוי",
-       "revdelete-suppress": "×\94סתרת המידע גם ממפעילי המערכת",
+       "revdelete-suppress": "×\94×¢×\9c×\9eת המידע גם ממפעילי המערכת",
        "revdelete-unsuppress": "הסרת הגבלות בגרסאות המשוחזרות",
        "revdelete-log": "סיבה:",
        "revdelete-submit": "ביצוע על {{PLURAL:$1|הגרסה שנבחרה|הגרסאות שנבחרו}}",
        "revdelete-modify-missing": "שגיאה בשינוי פריט מספר $1: הוא אינו נמצא בבסיס הנתונים!",
        "revdelete-no-change": "'''אזהרה:''' לפריט מתאריך $2, $1 כבר יש את הגדרות ההצגה הנדרשות.",
        "revdelete-concurrent-change": "שגיאה בשינוי הפריט מתאריך $2, $1: נראה שמצבו שונה על־ידי מישהו אחר בזמן שאתם ניסיתם לשנות אותו.\nאנא בדקו ביומנים.",
-       "revdelete-only-restricted": "ש×\92×\99×\90×\94 ×\91×\94סתרת ×\94פר×\99×\98 ×\9eת×\90ר×\99×\9a $2, $1: ×\90×\99×\9f ×\91×\90פשר×\95ת×\9a ×\9c×\94סת×\99ר ×¤×¨×\99×\98×\99×\9d ×\9e×\9eפע×\99×\9c×\99 ×\94×\9eער×\9bת ×\9e×\91×\9c×\99 ×\9c×\91×\97×\95ר ×\92×\9d ×\91×\90×\97ת ×\9e×\90פשר×\95×\99×\95ת ×\94×\94סתר×\94 האחרות.",
+       "revdelete-only-restricted": "ש×\92×\99×\90×\94 ×\91×\94סתרת ×\94פר×\99×\98 ×\9eת×\90ר×\99×\9a $2, $1: ×\90×\99×\9f ×\91×\90פשר×\95ת×\9a ×\9c×\94×¢×\9c×\99×\9d ×¤×¨×\99×\98×\99×\9d ×\9e×\9eפע×\99×\9c×\99 ×\94×\9eער×\9bת ×\9e×\91×\9c×\99 ×\9c×\91×\97×\95ר ×\92×\9d ×\91×\90×\97ת ×\9e×\90פשר×\95×\99×\95ת ×\94נר×\90×\95ּת האחרות.",
        "revdelete-reason-dropdown": "* סיבות מחיקה נפוצות\n** הפרת זכויות יוצרים\n** תקציר עריכה או מידע אישי לא הולמים\n** שם משתמש לא הולם\n** מידע שעלול להיות לשון הרע",
        "revdelete-otherreason": "סיבה אחרת/נוספת:",
        "revdelete-reasonotherlist": "סיבה אחרת",
        "revdelete-edit-reasonlist": "עריכת סיבות המחיקה",
        "revdelete-offender": "מחבר הגרסה:",
-       "suppressionlog": "×\99×\95×\9e×\9f ×\94סתרות",
+       "suppressionlog": "×\99×\95×\9e×\9f ×\94×¢×\9c×\9eות",
        "suppressionlogtext": "להלן רשימת המחיקות והחסימות הכוללות תוכן המוסתר ממפעילי המערכת.\nראו את [[Special:BlockList|רשימת החסומים]] לרשימת החסימות הפעילות כעת.",
        "mergehistory": "מיזוג גרסאות של דפים",
        "mergehistory-header": "דף זה מאפשר לכם למזג גרסאות מהיסטוריית הדף של דף מקור לתוך דף חדש יותר.\nאנא ודאו ששינוי זה לא יפגע בהמשכיות השינויים בדף הישן.\n\n'''לפחות גרסה אחת של דף המקור חייבת להישאר בו.'''",
        "pagemerge-logentry": "מיזג את [[$1]] לתוך [[$2]] (גרסאות עד $3)",
        "revertmerge": "ביטול המיזוג",
        "mergelogpagetext": "זוהי רשימה של המיזוגים האחרונים של גרסאות מדף אחד לתוך דף שני.",
-       "history-title": "$1: היסטוריית גרסאות",
-       "difference-title": "$1: הבדלים בין גרסאות",
+       "history-title": "היסטוריית גרסאות של הדף \"$1\"",
+       "difference-title": "הבדלים בין גרסאות בדף \"$1\"",
        "difference-title-multipage": "$1 ו{{GRAMMAR:תחילית|$2}}: הבדלים בין דפים",
        "difference-multipage": "(הבדלים בין דפים)",
        "lineno": "שורה $1:",
        "shown-title": "הצגת {{PLURAL:$1|תוצאה אחת|$1 תוצאות}} בדף",
        "viewprevnext": "צפייה ב: ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "'''קיים דף בשם \"[[:$1]]\" באתר זה.'''",
-       "searchmenu-new": "<strong>'''×\99צ×\99רת ×\94×\93×£ \"[[:$1]]\" ×\91×\90תר ×\96×\94.'''</strong> \n{{PLURAL:$2|0=|ר×\90×\95 ×\92×\9d ×\90ת ×\94×\93×£ ×©× ×\9eצ×\90 ×\91×\97×\99פ×\95ש ×©×\9c×\9b×\9d.|ר×\90×\95 ×\92×\9d ×\90ת ×ª×\95צ×\90×\95ת ×\94×\97×\99פ×\95ש ×©×\9c×\9b×\9d.}}",
+       "searchmenu-new": "<strong>'''×\99צ×\99רת ×\94×\93×£ \"[[:$1]]\" ×\91×\90תר ×\94×\95×\95×\99ק×\99 ×\94×\96×\94.'''</strong>\n{{PLURAL:$2|0=|ר' ×\92×\9d ×\90ת ×\94×\93×£ ×©× ×\9eצ×\90 ×\91×\97×\99פ×\95ש.|ר' ×\92×\9d ×\90ת ×ª×\95צ×\90×\95ת ×\94×\97×\99פ×\95ש.}}",
        "searchprofile-articles": "דפי תוכן",
        "searchprofile-images": "מולטימדיה",
        "searchprofile-everything": "הכול",
        "searchprofile-advanced-tooltip": "חיפוש במרחבי שם מותאמים אישית",
        "search-result-size": "$1 ({{PLURAL:$2|מילה אחת|$2 מילים}})",
        "search-result-category-size": "{{PLURAL:$1|חבר אחד|$1 חברים}} ({{PLURAL:$2|קטגוריית משנה אחת|$2 קטגוריות משנה}}, {{PLURAL:$3|קובץ אחד|$3 קבצים}})",
-       "search-result-score": "רלוונטיוּת: $1%",
        "search-redirect": "(הפניה $1)",
        "search-section": "(פסקה $1)",
        "search-file-match": "(התאמה בתוכן הקובץ)",
        "searchall": "הכול",
        "showingresults": "{{PLURAL:$1|מוצגת תוצאה <strong>אחת</strong>|מוצגות עד <strong>$1</strong> תוצאות}} החל ממספר <strong>$2</strong>:",
        "showingresultsinrange": "{{PLURAL:$1|מוצגת תוצאה <strong>אחת</strong>|מוצגות עד <strong>$1</strong> תוצאות}} בין המספרים <strong>$2</strong> ו‏‏־<strong>$3</strong>:",
-       "showingresultsheader": "{{PLURAL:$5|תוצאה '''$1''' מתוך '''$3'''|תוצאות '''$1 - $2''' מתוך '''$3'''}} עבור '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|תוצאה <strong>$1</strong> מתוך <strong>$3</strong>|תוצאות <strong>$1 - $2</strong> מתוך <strong>$3</strong>}}",
        "search-nonefound": "לא נמצאו תוצאות המתאימות לחיפוש.",
        "powersearch-legend": "חיפוש מתקדם",
        "powersearch-ns": "חיפוש על־פי מרחבי שם:",
        "preferences": "העדפות",
        "mypreferences": "העדפות",
        "prefs-edits": "מספר עריכות:",
-       "prefsnologintext2": "×¢×\9c×\99×\9b×\9d $1 כדי לשנות העדפות משתמש.",
+       "prefsnologintext2": "×\90× ×\90 ×\94×\99×\9bנס×\95 ×\9c×\97ש×\91×\95×\9f כדי לשנות העדפות משתמש.",
        "prefs-skin": "עיצוב",
        "skin-preview": "תצוגה מקדימה",
        "datedefault": "ברירת המחדל",
        "timezoneregion-europe": "אירופה",
        "timezoneregion-indian": "האוקיינוס ההודי",
        "timezoneregion-pacific": "האוקיינוס השקט",
-       "allowemail": "קבלת דוא\"ל ממשתמשים אחרים",
+       "allowemail": "×\9c×\90פשר ×§×\91×\9cת ×\93×\95×\90\"×\9c ×\9e×\9eשת×\9eש×\99×\9d ×\90×\97ר×\99×\9d",
        "prefs-searchoptions": "חיפוש",
        "prefs-namespaces": "מרחבי שם",
        "default": "ברירת מחדל",
        "prefs-help-gender": "אין חובה למלא העדפה זו.\nהמערכת משתמשת במידע זה כדי לפנות אליך/אלייך ולציין את שם המשתמש שלך במין הדקדוקי הנכון.\nהמידע יהיה ציבורי.",
        "email": "דוא\"ל",
        "prefs-help-realname": "השם האמיתי הוא אופציונאלי.\nאם תבחרו לספקו, הוא ישמש לייחוס עבודתכם אליכם.",
-       "prefs-help-email": "×\9bת×\95×\91ת ×\93×\95×\90ר ×\90×\9cק×\98ר×\95× ×\99 ×\94×\99×\90 ×\90×\95פצ×\99×\95× ×\90×\9c×\99ת, ×\90×\9a ×\94×\99×\90 ×\93ר×\95ש×\94 ×\9c×\90×\99פ×\95ס ×\94ס×\99ס×\9e×\94 ×\91×\9eקר×\94 ×©×ª×©×\9b×\97×\95 ×\90ת ×\94ס×\99ס×\9eה.",
+       "prefs-help-email": "×\9bת×\95×\91ת ×\93×\95×\90ר ×\90×\9cק×\98ר×\95× ×\99 ×\94×\99×\90 ×\90×\95פצ×\99×\95× ×\90×\9c×\99ת, ×\90×\91×\9c ×\94×\99×\90 ×\97×\99×\95× ×\99ת ×\9c×\90×\99פ×\95ס ×\94ס×\99ס×\9e×\94 ×\91×\9eקר×\94 ×©×ª×©×\9b×\97×\95 ×\90×\95תה.",
        "prefs-help-email-others": "באפשרותך גם לבחור לאפשר לאחרים ליצור איתך קשר באמצעות דוא\"ל דרך קישור בדף המשתמש או בדף השיחה שלך.\nכתובת הדוא\"ל שלך לא תיחשף כשמשתמשים אחרים ייצרו קשר איתך.",
        "prefs-help-email-required": "כתובת דואר אלקטרוני נדרשת לכתיבה באתר.",
        "prefs-info": "מידע בסיסי",
        "userrights-no-interwiki": "אין לכם הרשאה לערוך הרשאות משתמש באתרים אחרים.",
        "userrights-nodatabase": "בסיס הנתונים $1 אינו קיים או אינו מקומי.",
        "userrights-nologin": "עליכם [[Special:UserLogin|להיכנס לחשבון]] עם הרשאות מתאימות כדי לשנות הרשאות של משתמשים.",
-       "userrights-notallowed": "×\90×\99×\9f ×\9c×\9b×\9d הרשאה להוסיף או להסיר הרשאות של משתמשים.",
+       "userrights-notallowed": "×\90×\99×\9f ×\9c×\9a הרשאה להוסיף או להסיר הרשאות של משתמשים.",
        "userrights-changeable-col": "קבוצות שבאפשרותכם לשנות",
        "userrights-unchangeable-col": "קבוצות שאין באפשרותכם לשנות",
        "userrights-conflict": "התנגשות בין שינויי הרשאות משתמש! אנא בדקו את השינויים שלכם ואשרו אותם.",
        "right-deletedtext": "צפייה בטקסט מחוק ובהבדלים בין גרסאות מחוקות",
        "right-browsearchive": "חיפוש דפים מחוקים",
        "right-undelete": "שחזור דף מחוק",
-       "right-suppressrevision": "בדיקה ושחזור של גרסאות המוסתרות ממפעילי המערכת",
+       "right-suppressrevision": "הצגה, הסתרה וביטול הסתרה של גרסאות מסוימות של דפים מכל המשתמשים",
+       "right-viewsuppressed": "הצגת גרסאות שמוסתרות מכל המשתמשים",
        "right-suppressionlog": "צפייה ביומנים פרטיים",
        "right-block": "חסימת משתמשים אחרים מעריכה",
        "right-blockemail": "חסימת משתמש משליחת דואר אלקטרוני",
        "recentchanges-legend-heading": "'''מקרא:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (ראו גם [[Special:NewPages|רשימת דפים חדשים]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "להלן השינויים שבוצעו החל מ‏‏֫־<b>$2</b> (עד <b>$1</b> מוצגים).",
+       "rcnotefrom": "להלן {{PLURAL:$5|השינוי שבוצע|השינויים שבוצעו}} החל מ‏‏֫־<b>$2</b> (עד <b>$1</b> מוצגים).",
        "rclistfrom": "הצגת שינויים חדשים החל מ־$2, $3",
        "rcshowhideminor": "$1 שינויים משניים",
        "rcshowhideminor-show": "הצגת",
        "fileexists-shared-forbidden": "קובץ בשם זה כבר קיים כקובץ משותף.\nאם אתם עדיין מעוניינים להעלות קובץ זה, אנא חזרו לדף הקודם והעלו את הקובץ תחת שם חדש.\n[[File:$1|thumb|center|$1]]",
        "file-exists-duplicate": "קובץ זה זהה {{PLURAL:$1|לקובץ הבא|לקבצים הבאים}}:",
        "file-deleted-duplicate": "קובץ זהה לקובץ זה ([[:$1]]) נמחק בעבר.\nאנא בדקו את היסטוריית המחיקה של הקובץ לפני שתעלו אותו מחדש.",
-       "file-deleted-duplicate-notitle": "ק×\95×\91×¥ ×\96×\94×\94 ×\9cק×\95×\91×¥ ×\96×\94 × ×\9e×\97ק ×\91×¢×\91ר, ×\95×\94×\9b×\95תרת ×©×\9c×\95 ×\94×\95סתר×\94.\n×\90× ×\90 ×\91קש×\95 ×\9e×\9e×\99ש×\94×\95 ×©×\99×\9b×\95×\9c ×\9cר×\90×\95ת ×\9e×\99×\93×¢ ×¢×\9c ×§×\91צ×\99×\9d ×©×\94×\95סתרו לבדוק את המצב לפני שתעלו אותו מחדש.",
+       "file-deleted-duplicate-notitle": "ק×\95×\91×¥ ×\96×\94×\94 ×\9cק×\95×\91×¥ ×\96×\94 × ×\9e×\97ק ×\91×¢×\91ר, ×\95×\94×\9b×\95תרת ×©×\9c×\95 ×\94×\95×¢×\9c×\9e×\94.\n×\90× ×\90 ×\91קש×\95 ×\9e×\9e×\99ש×\94×\95 ×©×\99×\9b×\95×\9c ×\9cר×\90×\95ת × ×ª×\95× ×\99×\9d ×¢×\9c ×§×\91צ×\99×\9d ×©×\94×\95×¢×\9c×\9eו לבדוק את המצב לפני שתעלו אותו מחדש.",
        "uploadwarning": "אזהרת העלאת קבצים",
        "uploadwarning-text": "אנא שנו את תיאור הקובץ שלמטה ונסו שוב.",
        "savefile": "שמירת קובץ",
-       "uploadedimage": "העלה את הקובץ [[$1]]",
-       "overwroteimage": "העלה גרסה חדשה של הקובץ [[$1]]",
        "uploaddisabled": "העלאת קבצים מבוטלת.",
        "copyuploaddisabled": "העלאת קבצים מכתובת URL מבוטלת.",
        "uploaddisabledtext": "אפשרות העלאת הקבצים מבוטלת.",
        "license": "רישיון:",
        "license-header": "רישיון",
        "nolicense": "אין",
+       "licenses-edit": "עריכת אפשרויות רישיון",
        "license-nopreview": "(תצוגה מקדימה לא זמינה)",
-       "upload_source_url": "(כתובת URL תקפה ונגישה)",
-       "upload_source_file": "(קובץ במחשב שלך)",
+       "upload_source_url": "(קובץ שבחרת מכתובת URL תקינה ונגישה לציבור)",
+       "upload_source_file": "(קובץ שבחרת מהמחשב שלך)",
+       "listfiles-delete": "מחיקה",
        "listfiles-summary": "דף מיוחד זה מציג את כל הקבצים שהועלו.",
        "listfiles_search_for": "חיפוש קובץ מדיה בשם:",
        "imgfile": "קובץ",
        "randomincategory": "דף אקראי בקטגוריה",
        "randomincategory-invalidcategory": "\"$1\" אינו שם תקין לקטגוריה.",
        "randomincategory-nopages": "אין דפים בקטגוריה [[:Category:$1|$1]].",
-       "randomincategory-selectcategory": "קבלת דף אקראי מהקטגוריה: $1 $2.",
-       "randomincategory-selectcategory-submit": "מעבר",
+       "randomincategory-category": "קטגוריה:",
+       "randomincategory-legend": "דף אקראי בקטגוריה",
        "randomredirect": "הפניה אקראית",
        "randomredirect-nopages": "אין הפניות במרחב השם \"$1\".",
        "statistics": "סטטיסטיקות",
        "wantedpages-badtitle": "כותרת בלתי תקינה ברשימת התוצאות: $1",
        "wantedfiles": "קבצים מבוקשים",
        "wantedfiletext-cat": "הקבצים הבאים נמצאים בשימוש, אך אינם קיימים. ייתכן שקבצים ממאגרים חיצוניים יהיו רשומים אף על פי שהם קיימים, אך שגיאות כאלה יהיו <del>מחוקות</del>. בנוסף, דפים שמשתמשים בקבצים שאינם קיימים רשומים בדף [[:$1]].",
+       "wantedfiletext-cat-noforeign": "הקבצים הבאים נמצאים בשימוש, אבל אינם קיימים. כמו־כן, דפים שמשתמשים בקבצים שאינם קיימים רשומים בדף [[:$1]].",
        "wantedfiletext-nocat": "הקבצים הבאים נמצאים בשימוש, אך אינם קיימים. ייתכן שקבצים ממאגרים חיצוניים יהיו רשומים אף על פי שהם קיימים, אך שגיאות כאלה יהיו <del>מחוקות</del>.",
+       "wantedfiletext-nocat-noforeign": "הקבצים הבאים נמצאים בשימוש, אבל אינם קיימים.",
        "wantedtemplates": "תבניות מבוקשות",
        "mostlinked": "הדפים המקושרים ביותר",
        "mostlinkedcategories": "הקטגוריות המקושרות ביותר",
        "speciallogtitlelabel": "יעד (כותרת או משתמש):",
        "log": "יומנים",
        "all-logs-page": "כל היומנים הציבוריים",
-       "alllogstext": "תצוגה משולבת של כל סוגי היומנים הזמינים ב{{grammar:תחילית|{{SITENAME}}}}.\nניתן לצמצם את התצוגה על ידי בחירת סוג היומן, שם המשתמש (תלוי רישיות) או הדף המושפע (גם כן תלוי רישיות).",
+       "alllogstext": "תצוגה משולבת של כל סוגי היומנים הזמינים ב{{grammar:תחילית|{{SITENAME}}}}.\nניתן לצמצם את התצוגה על־ידי בחירת סוג היומן, שם המשתמש (תלוי רישיות) או הדף המושפע (גם כן תלוי רישיות).",
        "logempty": "אין פריטים תואמים ביומן.",
        "log-title-wildcard": "חיפוש כותרות המתחילות באותיות אלה",
        "showhideselectedlogentries": "הצגת/הסתרת פעולות היומן שנבחרו",
        "allpagessubmit": "הצגה",
        "allpagesprefix": "הדפים ששמם מתחיל ב:",
        "allpagesbadtitle": "כותרת הדף שניתנה הייתה בלתי־תקינה או שהייתה בה קידומת של קישור לשפה אחרת או לוויקי אחר.\nייתכן שהיא מכילה תו אחד או יותר האסורים לשימוש בכותרות.",
-       "allpages-bad-ns": "×\90×\99×\9f ×\9eר×\97×\91 ×©×\9d ×\91ש×\9d \"$1\".",
+       "allpages-bad-ns": "×\9eר×\97×\91 ×\94ש×\9d \"$1\" ×\9c×\90 ×§×\99×\99×\9d ×\91{{grammar:ת×\97×\99×\9c×\99ת|{{SITENAME}}}}.",
        "allpages-hide-redirects": "הסתרת הפניות",
        "cachedspecial-viewing-cached-ttl": "זוהי גרסה שמורה בזיכרון המטמון של דף זה, שעשויה להיות בת $1.",
        "cachedspecial-viewing-cached-ts": "זוהי גרסה שמורה בזיכרון המטמון של דף זה, שעשויה שלא להיות מעודכנת.",
        "trackingcategories-desc": "הקריטריון להכללה בקטגוריה",
        "noindex-category-desc": "הדף אינו מאונדקס על‏‏־ידי רובוטים כיוון שהוא כולל את מילת הקסם <code><nowiki>__NOINDEX__</nowiki></code> והוא במרחב שם שבו דגל כזה מותר לשימוש.",
        "index-category-desc": "הדף כולל את מילת הקסם <code><nowiki>__INDEX__</nowiki></code> (והוא במרחב שם שבו דגל כזה מותר לשימוש), ולכן הוא מאונדקס על‏‏֫־ידי רובוטים אף שכברירת מחדל הוא לא היה מאונדקס על ידם.",
-       "post-expand-template-inclusion-category-desc": "×\9c×\90×\97ר ×\94ר×\97×\91ת ×\9b×\9c ×\94ת×\91× ×\99×\95ת, ×\92×\95×\93×\9c ×\94×\93×£ ×\92×\93×\95×\9c ×\9eâ\80\8fâ\80\8fÖ«Ö¾<code>$wgMaxArticleSize</code>, ×\95×\9c×\9b×\9f ×\9eספר ×ª×\91× ×\99×\95ת ×\90×\99× ×\9f ×\9e×\95ר×\97×\91×\95ת.",
-       "post-expand-template-argument-category-desc": "×\9c×\90×\97ר ×\94ר×\97×\91ת ×\90ר×\92×\95×\9e× ×\98 ×©×\9c ×ª×\91× ×\99ת (×\9eש×\94×\95 ×\91ס×\95×\92ר×\99×\99×\9d ×\9eש×\95×\9cש×\99×\9d, ×\9b×\92×\95×\9f <code>{{{Foo}}})</code>, ×\94×\93×£ ×\92×\93×\95×\9c ×\9eâ\80\8fâ\80\8fÖ«â\80\8fâ\80\8fÖ«Ö¾<code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "×\99×\95תר ×\9e×\93×\99 ×¤×\95נקצ×\99×\95ת ×\9eפענ×\97 ×\99קר×\95ת ×\9cש×\99×\9e×\95ש (×\9b×\92×\95×\9f #ק×\99×\99×\9d) ×\9e×\95×\9b×\9c×\9c×\95ת ×\91×\93×£. ראו [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "×\94ק×\98×\92×\95ר×\99×\94 × ×\95ספת ×\90×\9d ×\94×\93×£ ×\9b×\95×\9c×\9c ×§×\99ש×\95ר ×©×\91×\95ר ×\9cק×\95×\91×¥ (ק×\99ש×\95ר ×\9c×\94×\98×\9eעת ×§×\95×\91×¥ ×\9b×\90שר ×\94ק×\95×\91×¥ ×\90×\99× ×\95 ×§×\99×\99×\9d).",
-       "hidden-category-category-desc": "ק×\98×\92×\95ר×\99×\94 ×\96×\95 ×\9b×\95×\9c×\9cת ×\90ת ×\9e×\99×\9cת ×\94קס×\9d <nowiki>__ק×\98×\92×\95ר×\99×\94\9e×\95סתרת__</nowiki>, ×©×\92×\95ר×\9eת ×\9c×\94 ×\9c×\90 ×\9c×\94×\95פ×\99×¢ בתיבת קישורי הקטגוריות בדפים כברירת מחדל.",
+       "post-expand-template-inclusion-category-desc": "×\92×\95×\93×\9c ×\94×\93×£ ×\92×\93×\95×\9c ×\9eâ\80\8fâ\80\8fÖ¾<code>$wgMaxArticleSize</code> ×\9c×\90×\97ר ×\94ר×\97×\91ת ×\9b×\9c ×\94ת×\91× ×\99×\95ת, ×\95×\9c×\9b×\9f ×\9b×\9e×\94 ×ª×\91× ×\99×\95ת ×\9c×\90 ×\94×\95ר×\97×\91×\95.",
+       "post-expand-template-argument-category-desc": "×\94×\93×£ ×\92×\93×\95×\9c ×\9eÖ¾<code>$wgMaxArticleSize</code> ×\9c×\90×\97ר ×\94ר×\97×\91ת ×\90ר×\92×\95×\9e× ×\98 ×©×\9c ×ª×\91× ×\99ת (×\9eש×\94×\95 ×\91ס×\95×\92ר×\99×\99×\9d ×\9eש×\95×\9cש×\99×\9d, ×\9b×\92×\95×\9f <code>{{{Foo}}})</code>).",
+       "expensive-parserfunction-category-desc": "×\94×\93×£ ×\9eשת×\9eש ×\91×\99×\95תר ×\9e×\93×\99 ×¤×\95נקצ×\99×\95ת ×\9eפענ×\97 ×\99קר×\95ת ×\9cש×\99×\9e×\95ש (×\9b×\92×\95×\9f #ק×\99×\99×\9d). ראו [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "הדף כולל קישור שבור לקובץ (קישור להטמעת קובץ כאשר הקובץ אינו קיים).",
+       "hidden-category-category-desc": "×\94ק×\98×\92×\95ר×\99×\94 ×\9b×\95×\9c×\9cת ×\90ת ×\94×\98קס×\98 <code><nowiki>__ק×\98×\92×\95ר×\99×\94\9e×\95סתרת__</nowiki></code> ×\91ת×\95×\9b×\9f ×\94×\93×£ ×©×\9c×\94, ×\95×\9c×\9b×\9f ×\94×\99×\90 ×\9c×\90 ×\9e×\95פ×\99×¢×\94 בתיבת קישורי הקטגוריות בדפים כברירת מחדל.",
        "trackingcategories-nodesc": "התיאור אינו זמין.",
        "trackingcategories-disabled": "הקטגוריה מבוטלת",
        "mailnologin": "אין כתובת לשליחה",
        "mywatchlist": "רשימת מעקב",
        "watchlistfor2": "עבור $1 $2",
        "nowatchlist": "אין דפים ברשימת המעקב.",
-       "watchlistanontext": "×¢×\9c×\99×\9b×\9d $1 כדי לצפות או לערוך פריטים ברשימת המעקב.",
+       "watchlistanontext": "×\90× ×\90 ×\94×\99×\9bנס×\95 ×\9c×\97ש×\91×\95×\9f כדי לצפות או לערוך פריטים ברשימת המעקב.",
        "watchnologin": "לא נכנסת לחשבון",
        "addwatch": "הוספה לרשימת המעקב",
        "addedwatchtext": "הדף \"[[:$1]]\" נוסף ל[[Special:Watchlist|רשימת המעקב]].\nשינויים שייערכו בעתיד בדף זה ובדף השיחה שלו, יוצגו ברשימת המעקב.",
        "watchlist-details": "ברשימת המעקב יש {{PLURAL:$1|דף אחד|$1 דפים}}, כאשר דפי השיחה אינם נספרים בנפרד.",
        "wlheader-enotif": "הודעות דוא\"ל מאופשרות.",
        "wlheader-showupdated": "דפים שהשתנו מאז ביקורך האחרון בהם מוצגים ב'''הדגשה'''.",
-       "wlnote2": "להלן השינויים האחרונים {{PLURAL:$1|בשעה האחרונה|בשעתיים האחרונות|ב‏‏־<strong>$1</strong> השעות האחרונות}}, עד $3, $2.",
+       "wlnote": "להלן {{PLURAL:$1|השינוי האחרון|<strong>$1</strong> השינויים האחרונים}} {{PLURAL:$2|בשעה האחרונה|בשעתיים האחרונות|ב־<strong>$2</strong> השעות האחרונות}}, עד $4, $3.",
        "wlshowlast": "(הצגת $1 שעות אחרונות | $2 ימים אחרונים | $3)",
        "watchlist-options": "אפשרויות ברשימת המעקב",
        "watching": "בהוספה לרשימת המעקב…",
        "exbeforeblank": "התוכן לפני שרוקן היה: \"$1\"",
        "delete-confirm": "מחיקת $1",
        "delete-legend": "מחיקה",
-       "historywarning": "'''אזהרה:''' לדף שאתם עומדים למחוק יש היסטוריית שינויים של {{PLURAL:$1|גרסה אחת|$1 גרסאות}}:",
+       "historywarning": "<strong>אזהרה:</strong> לדף שאתם עומדים למחוק יש היסטוריית שינויים של {{PLURAL:$1|גרסה אחת|$1 גרסאות}}:",
        "confirmdeletetext": "אתם עומדים למחוק דף יחד עם כל ההיסטוריה שלו.\n\nאנא אשרו שזה אכן מה שאתם מתכוונים לעשות, שאתם מבינים את התוצאות של מעשה כזה, ושהמעשה מבוצע בהתאם ל[[{{MediaWiki:Policy-url}}|נוהלי האתר]].",
        "actioncomplete": "הפעולה בוצעה",
        "actionfailed": "הפעולה נכשלה",
        "delete-edit-reasonlist": "עריכת סיבות המחיקה",
        "delete-toobig": "דף זה כולל מעל {{PLURAL:$1|גרסה אחת|$1 גרסאות}} בהיסטוריית העריכות שלו. מחיקת דפים כאלה הוגבלה כדי למנוע פגיעה בביצועי האתר.",
        "delete-warning-toobig": "דף זה כולל מעל {{PLURAL:$1|גרסה אחת|$1 גרסאות}} בהיסטוריית העריכות שלו. מחיקה שלו עלולה להפריע לפעולות בבסיס הנתונים; אנא שקלו שנית את המחיקה.",
+       "deleteprotected": "אין באפשרותך למחוק את הדף כי הוא מוגן.",
        "deleting-backlinks-warning": "'''אזהרה:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|דפים אחרים]] מקשרים לדף שאתם עומדים למחוק או מכלילים אותו.",
        "rollback": "שחזור עריכות",
        "rollback_short": "שחזור",
        "sp-contributions-newbies-sub": "עבור משתמשים חדשים",
        "sp-contributions-newbies-title": "תרומות של משתמשים חדשים",
        "sp-contributions-blocklog": "יומן חסימות",
-       "sp-contributions-suppresslog": "תר×\95×\9e×\95ת ×\9eשת×\9eש ×\9e×\95סתרות",
+       "sp-contributions-suppresslog": "תר×\95×\9e×\95ת ×\9eשת×\9eש ×\9e×\95×¢×\9c×\9eות",
        "sp-contributions-deleted": "תרומות משתמש מחוקות",
        "sp-contributions-uploads": "העלאות",
        "sp-contributions-logs": "יומנים",
        "autoblockid": "חסימה אוטומטית #$1",
        "block": "חסימת משתמש",
        "unblock": "שחרור משתמש",
-       "blockip": "חסימת משתמש",
+       "blockip": "חסימת {{GENDER:$1|משתמש|משתמשת}}",
        "blockip-legend": "חסימת משתמש",
        "blockiptext": "השתמשו בטופס שלהלן כדי לחסום את הרשאות הכתיבה מכתובת IP או משתמש מסוימים.\nחסימות כאלה צריכות להתבצע רק כדי למנוע השחתה, ובהתאם ל[[{{MediaWiki:Policy-url}}|נהלים]].\nאנא מלאו את הסיבה הפרטנית לחסימה להלן (לדוגמה, באמצעות ציון דפים מסוימים שהשחית המשתמש).",
        "ipaddressorusername": "כתובת IP או שם משתמש:",
        "blockipsuccesssub": "החסימה הושלמה בהצלחה",
        "blockipsuccesstext": "{{GENDER:$1|המשתמש|המשתמשת}} [[Special:Contributions/$1|$1]] {{GENDER:$1|נחסם|נחסמה}}.\n\nראו את [[Special:BlockList|רשימת החסומים]] כדי לצפות בחסימות.",
        "ipb-blockingself": "אתם עומדים לחסום את עצמכם! האם אתם בטוחים שברצונכם לעשות זאת?",
-       "ipb-confirmhideuser": "×\90ת×\9d ×¢×\95×\9e×\93×\99×\9d ×\9c×\97ס×\95×\9d ×\9eשת×\9eש ×¢×\9d ×\94×\90פשר×\95ת \"×\94סתרת ×\9eשת×\9eש\". ×¤×¢×\95×\9c×\94 ×\96×\95 ×ª×¡×ª×\99ר את שם המשתמש בכל הרשימות ופעולות היומן. האם אתם בטוחים שברצונכם לעשות זאת?",
+       "ipb-confirmhideuser": "×\90ת×\9d ×¢×\95×\9e×\93×\99×\9d ×\9c×\97ס×\95×\9d ×\9eשת×\9eש ×¢×\9d ×\94×\90פשר×\95ת \"×\94סתרת ×\9eשת×\9eש\". ×\96×\94 ×\99×¢×\9c×\99×\9d את שם המשתמש בכל הרשימות ופעולות היומן. האם אתם בטוחים שברצונכם לעשות זאת?",
        "ipb-confirmaction": "אם אתם באמת בטוחים שברצונכם לעשות זאת, אנא סמנו את השדה \"{{int:ipb-confirm}}\" שבתחתית.",
        "ipb-edit-dropdown": "עריכת סיבות החסימה",
        "ipb-unblock-addr": "הסרת חסימה של $1",
        "ipb-unblock": "הסרת חסימה של שם משתמש או כתובת IP",
        "ipb-blocklist": "הצגת החסימות הנוכחיות",
-       "ipb-blocklist-contribs": "התרומות של $1",
+       "ipb-blocklist-contribs": "התרומות של {{GENDER:$1|$1}}",
        "unblockip": "שחרור חסימה",
        "unblockiptext": "השתמשו בטופס שלהלן כדי להחזיר את הרשאות הכתיבה למשתמש או כתובת IP חסומים.",
        "ipusubmit": "שחרור חסימה",
        "unblocked": "[[User:$1|$1]] {{GENDER:$1|שוחרר מחסימתו|שוחררה מחסימתה}}.",
        "unblocked-range": "$1 שוחרר מחסימתו.",
        "unblocked-id": "חסימה מספר $1 שוחררה.",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] שוחררה מחסימתה.",
        "blocklist": "משתמשים חסומים",
        "ipblocklist": "משתמשים חסומים",
        "ipblocklist-legend": "מציאת משתמש חסום",
        "autoblocker": "נחסמתם באופן אוטומטי משום שאתם חולקים את כתובת ה־IP שלכם עם [[User:$1|$1]].\nהסיבה שניתנה לחסימת $1 היא \"$2\"",
        "blocklogpage": "יומן חסימות",
        "blocklog-showlog": "משתמש זה נחסם בעבר.\nיומן החסימות מוצג להלן:",
-       "blocklog-showsuppresslog": "×\9eשת×\9eש ×\96×\94 × ×\97ס×\9d ×\95×\94×\95סתר ×\91×¢×\91ר.\n×\99×\95×\9e×\9f ×\94×\94סתרות מוצג להלן:",
+       "blocklog-showsuppresslog": "×\9eשת×\9eש ×\96×\94 × ×\97ס×\9d ×\95×\94×\95סתר ×\91×¢×\91ר.\n×\99×\95×\9e×\9f ×\94×\94×¢×\9c×\9eות מוצג להלן:",
        "blocklogentry": "חסם את [[$1]] למשך $2 $3",
        "reblock-logentry": "שינה את הגדרות החסימה של [[$1]] עם זמן פקיעה של $2 $3",
        "blocklogtext": "זהו יומן פעולות החסימה והשחרור של משתמשים.\nכתובות IP שנחסמו אוטומטית אינן מופיעות.\nראו גם את [[Special:BlockList|רשימת החסומים]] לרשימה של החרמות וחסימות פעילות כעת.",
        "range_block_disabled": "האפשרות לחסום טווח כתובות אינה פעילה.",
        "ipb_expiry_invalid": "זמן פקיעת החסימה אינו תקין.",
        "ipb_expiry_temp": "חסימות הכוללות הסתרת שם משתמש חייבות להיות לזמן בלתי מוגבל.",
-       "ipb_hide_invalid": "×\9c×\90 × ×\99ת×\9f ×\9c×\94סת×\99ר ×©×\9d ×\9eשת×\9eש זה; {{PLURAL:$1|בוצעה ממנו יותר מעריכה אחת|בוצעו ממנו יותר מ‏‏֫־$1 עריכות}}.",
+       "ipb_hide_invalid": "×\9c×\90 × ×\99ת×\9f ×\9c×\94×¢×\9c×\99×\9d ×\90ת ×\94×\97ש×\91×\95×\9f ×\94זה; {{PLURAL:$1|בוצעה ממנו יותר מעריכה אחת|בוצעו ממנו יותר מ‏‏֫־$1 עריכות}}.",
        "ipb_already_blocked": "המשתמש \"$1\" כבר נחסם.",
        "ipb-needreblock": "$1 כבר נחסם. האם ברצונכם לשנות את הגדרות החסימה?",
        "ipb-otherblocks-header": "{{PLURAL:$1|חסימה אחרת|חסימות אחרות}}",
        "movepage-moved-redirect": "נוצרה הפניה.",
        "movepage-moved-noredirect": "יצירת ההפניה בוטלה.",
        "articleexists": "קיים כבר דף באותו שם, או שהשם שבחרת אינו תקין.\nנא לבחור שם אחר.",
-       "cantmove-titleprotected": "×\90×\99× ×\9b×\9d ×\99×\9b×\95×\9c×\99×\9d ×\9c×\94×¢×\91×\99ר ×\90ת ×\94×\93×£ ×\9cש×\9d ×\96×\94, כיוון שהשם החדש מוגן מפני יצירה",
+       "cantmove-titleprotected": "×\90×\99× ×\9a ×\9e×\95רש×\94 ×\9c×\94×¢×\91×\99ר ×\90ת ×\94×\93×£ ×\9cש×\9d ×\96×\94 כיוון שהשם החדש מוגן מפני יצירה",
        "movetalk": "העברה גם של דף השיחה",
        "move-subpages": "העברת כל דפי המשנה (עד $1)",
        "move-talk-subpages": "העברת כל דפי המשנה של דף השיחה (עד $1)",
        "import": "ייבוא דפים",
        "importinterwiki": "ייבוא בין־אתרי",
        "import-interwiki-text": "אנא בחרו אתר ויקי וכותרת דף לייבוא.\nתאריכי העריכות ושמות העורכים יישמרו.\nכל פעולות הייבוא הבין־אתרי נשמרות ב[[Special:Log/import|יומן הייבוא]].",
-       "import-interwiki-source": "אתר/דף המקור:",
+       "import-interwiki-sourcewiki": "אתר המקור:",
+       "import-interwiki-sourcepage": "דף המקור:",
        "import-interwiki-history": "העתקת כל היסטוריית העריכות של דף זה",
        "import-interwiki-templates": "ייבוא גם של כל התבניות המוכללות בדף",
        "import-interwiki-submit": "ייבוא",
        "importlogpage": "יומן ייבוא",
        "importlogpagetext": "ייבוא מנהלי של דפים (כולל היסטוריית העריכות שלהם) מאתרי ויקי אחרים.",
        "import-logentry-upload": "ייבא את [[$1]] באמצעות העלאת קובץ",
-       "import-logentry-upload-detail": "{{PLURAL:$1|גרסה אחת|$1 גרסאות}}",
+       "import-logentry-upload-detail": "{{PLURAL:$1|גרסה אחת יובאה|$1 גרסאות יובאו}}",
        "import-logentry-interwiki": "ייבא את $1 בייבוא בין־אתרי",
-       "import-logentry-interwiki-detail": "{{PLURAL:$1|גרסה אחת|$1 גרסאות}} של הדף $2",
+       "import-logentry-interwiki-detail": "{{PLURAL:$1|גרסה אחת של הדף $2 יובאה|$1 גרסאות של הדף $2 יובאו}}",
        "javascripttest": "בדיקת JavaScript",
        "javascripttest-title": "הרצת בדיקות $1",
        "javascripttest-pagetext-noframework": "דף זה שמור להרצת בדיקות JavaScript.",
        "sunday-at": "ביום ראשון בשעה $1",
        "yesterday-at": "אתמול בשעה $1",
        "bad_image_list": "דרך הכתיבה בהודעה היא כמתואר להלן:\n\nרק פריטי רשימה (שורות המתחילות עם *) נחשבים.\nהקישור הראשון בשורה חייב להיות קישור לקובץ בעייתי.\nכל הקישורים הבאים באותה השורה נחשבים לחריגים, כלומר לדפים שבהם ניתן להציג את הקובץ.",
-       "metadata": "×\9e×\99×\93×¢ × ×\95סף ×¢×\9c ×\94ק×\95×\91×¥",
+       "metadata": "×\9e×\98×\90־נת×\95× ×\99×\9d",
        "metadata-help": "קובץ זה מכיל מידע נוסף, שכנראה הגיע ממצלמה דיגיטלית או מסורק שבהם הקובץ נוצר או עבר דיגיטציה.\nאם הקובץ שונה ממצבו הראשוני, כמה מהנתונים להלן עלולים שלא לשקף באופן מלא את הקובץ הנוכחי.",
        "metadata-expand": "הצגת פרטים מורחבים",
        "metadata-collapse": "הסתרת פרטים מורחבים",
        "autosumm-replace": "החלפת הדף בתוכן \"$1\"",
        "autoredircomment": "הפניה לדף [[$1]]",
        "autosumm-new": "יצירת דף עם התוכן \"$1\"",
+       "autosumm-newblank": "יצירת דף ריק",
        "size-bytes": "$1 בייט",
        "size-kilobytes": "$1 קילו־בייט",
        "size-megabytes": "$1 מגה־בייט",
        "watchlistedit-raw-added": "{{PLURAL:$1|כותרת אחת נוספה|$1 כותרות נוספו}}:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|כותרת אחת הוסרה|$1 כותרות הוסרו}}:",
        "watchlistedit-clear-title": "רשימת המעקב נמחקה",
-       "watchlistedit-clear-legend": "×\9e×\97×\99קת רשימת המעקב",
+       "watchlistedit-clear-legend": "× ×\99ק×\95×\99 רשימת המעקב",
        "watchlistedit-clear-explain": "כל הכותרות של הדפים שיוסרו מרשימת המעקב",
        "watchlistedit-clear-titles": "כותרות:",
-       "watchlistedit-clear-submit": "×\9e×\97×\99קת רשימת המעקב (לצמיתות!)",
-       "watchlistedit-clear-done": "רש×\99×\9eת ×\94×\9eעק×\91 ×©×\9c×\9a × ×\9e×\97קה.",
+       "watchlistedit-clear-submit": "× ×\99ק×\95×\99 רשימת המעקב (לצמיתות!)",
+       "watchlistedit-clear-done": "רש×\99×\9eת ×\94×\9eעק×\91 ×©×\9c×\9a × ×\95קתה.",
        "watchlistedit-clear-removed": "{{PLURAL:$1|כותרת אחת הוסרה|$1 כותרות הוסרו}}:",
        "watchlistedit-too-many": "יש יותר מדי דפים ולא ניתן להציגם כאן.",
-       "watchlisttools-clear": "×\9e×\97×\99קת רשימת המעקב",
+       "watchlisttools-clear": "× ×\99ק×\95×\99 רשימת המעקב",
        "watchlisttools-view": "הצגת השינויים הרלוונטיים",
        "watchlisttools-edit": "הצגה ועריכה של רשימת המעקב",
        "watchlisttools-raw": "עריכת הרשימה הגולמית",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|שיחה]])",
        "unknown_extension_tag": "תגית בלתי ידועה: \"$1\"",
        "duplicate-defaultsort": "'''אזהרה:''' המיון הרגיל \"$2\" דורס את המיון הרגיל המוקדם ממנו \"$1\".",
+       "duplicate-displaytitle": "<strong>אזהרה:</strong> כותרת התצוגה \"$2\" דורסת את כותרת התצוגה הקודמת \"$1\".",
        "version": "גרסת התוכנה",
        "version-extensions": "הרחבות מותקנות",
        "version-skins": "עיצובים מותקנים",
        "logentry-delete-revision": "$1 {{GENDER:$2|שינה|שינתה}} את מצב התצוגה של {{PLURAL:$5|גרסה|$5 גרסאות}} בדף $3: $4",
        "logentry-delete-event-legacy": "$1 {{GENDER:$2|שינה|שינתה}} את מצב התצוגה של פעולות יומן של $3",
        "logentry-delete-revision-legacy": "$1 {{GENDER:$2|שינה|שינתה}} את מצב התצוגה של גרסאות בדף $3",
-       "logentry-suppress-delete": "$1 {{GENDER:$2|×\94סת×\99ר|×\94סת×\99ר×\94}} ×\9c×\97×\9c×\95×\98×\99×\9f את הדף $3",
+       "logentry-suppress-delete": "$1 {{GENDER:$2|×\94×¢×\9c×\99×\9d\94×¢×\9c×\99×\9e×\94}} את הדף $3",
        "logentry-suppress-event": "$1 {{GENDER:$2|שינה|שינתה}} בסודיות את מצב התצוגה של {{PLURAL:$5|פעולת יומן|$5 פעולות יומן}} של $3: $4",
        "logentry-suppress-revision": "$1 {{GENDER:$2|שינה|שינתה}} בסודיות את מצב התצוגה של {{PLURAL:$5|גרסה|$5 גרסאות}} בדף $3: $4",
        "logentry-suppress-event-legacy": "$1 {{GENDER:$2|שינה|שינתה}} בסודיות את מצב התצוגה של פעולות יומן של $3",
        "logentry-newusers-create2": "חשבון המשתמש $3 נוצר על־ידי $1",
        "logentry-newusers-byemail": "חשבון המשתמש $3 נוצר על־ידי $1 והסיסמה נשלחה בדוא\"ל",
        "logentry-newusers-autocreate": "חשבון המשתמש $1 {{GENDER:$2|נוצר}} אוטומטית",
-       "logentry-rights-rights": "$1 {{GENDER:$2|שינה|שינתה}} את ההרשאות של $3 מ$4 ל$5&rlm;",
-       "logentry-rights-rights-legacy": "$1 {{GENDER:$2|שינה|שינתה}} את ההרשאות של $3",
+       "logentry-rights-rights": "$1 {{GENDER:$2|שינה|שינתה}} את ההרשאות של $3 מ{{GRAMMAR:תחילית|$4}} ל{{GRAMMAR:תחילית|$5}}&rlm;",
+       "logentry-rights-rights-legacy": "$1 {{GENDER:$2|שינה|שינתה}} את ההרשאות של $3&rlm;",
        "logentry-rights-autopromote": "$1 קודם אוטומטית מ$4 ל$5",
+       "logentry-upload-upload": "$1 {{GENDER:$2|העלה|העלתה}} את $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|העלה|העלתה}} גרסה חדשה של $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|העלה|העלתה}} את $3",
        "rightsnone": "(כלום)",
        "feedback-bugornote": "אם אתם מוכנים לתאר בעיה טכנית בפרטים, אנא [$1 דווחו באג].\nאחרת, תוכלו להשתמש בטופס הפשוט שלהלן. הערתכם תתווסף לדף \"[$3 $2]\", יחד עם שם המשתמש שלכם.",
        "feedback-subject": "נושא:",
        "feedback-bugnew": "בדקתי. נא לדווח כבאג חדש",
        "searchsuggest-search": "חיפוש",
        "searchsuggest-containing": "כולל...",
-       "api-error-badaccess-groups": "×\90×\99× ×\9b×\9d ×\9e×\95רש×\99×\9d להעלות קבצים לאתר הוויקי הזה.",
-       "api-error-badtoken": "ש×\92×\99×\90×\94 ×¤× ×\99×\9e×\99ת: ×\90ס×\99×\9e×\95×\9f ×¨×¢.",
+       "api-error-badaccess-groups": "×\90×\99× ×\9a ×\9e×\95רש×\94 להעלות קבצים לאתר הוויקי הזה.",
+       "api-error-badtoken": "ש×\92×\99×\90×\94 ×¤× ×\99×\9e×\99ת: ×\90ס×\99×\9e×\95×\9f ×©×\91×\95ר.",
        "api-error-copyuploaddisabled": "העלאה לפי כתובת כובתה בשרת זה.",
        "api-error-duplicate": "כבר יש באתר הוויקי {{PLURAL:$1|[$2 קובץ אחר] בעל|[$2 קבצים אחרים] בעלי}} אותו תוכן.",
        "api-error-duplicate-archive": "באתר כבר {{PLURAL:$1|היה [$2 קובץ אחר]|היו [$2 קבצים אחרים]}} עם אותו תוכן, אבל {{PLURAL:$1|הוא נמחק|הם נמחקו}}.",
        "api-error-duplicate-archive-popup-title": "{{PLURAL:$1|קובץ כפול שכבר נמחק|קבצים כפולים שכבר נמחקו}}",
        "api-error-duplicate-popup-title": "{{PLURAL:$1|קובץ כפול|קבצים כפולים}}",
-       "api-error-empty-file": "הקובץ ששלחתם היה ריק.",
+       "api-error-empty-file": "הקובץ ששלחת היה ריק.",
        "api-error-emptypage": "יצירת דפים חדשים ריקים אינה אפשרית.",
        "api-error-fetchfileerror": "שגיאה פנימית: משהו השתבש בזמן אחזור הקובץ.",
        "api-error-fileexists-forbidden": "קובץ בשם \"$1\" כבר קיים ואי־אפשר לדרוס אותו.",
        "api-error-fileexists-shared-forbidden": "קובץ בשם \"$1\" כבר קיים במאגר הקבצים המשותף ואי־אפשר לדרוס אותו.",
-       "api-error-file-too-large": "הקובץ ששלחתם היה גדול מדי.",
+       "api-error-file-too-large": "הקובץ ששלחת היה גדול מדי.",
        "api-error-filename-tooshort": "שם הקובץ קצר מדי.",
        "api-error-filetype-banned": "סוג קובץ זה חסום.",
        "api-error-filetype-banned-type": "$1 {{PLURAL:$4|הוא סוג קובץ אסור להעלאה|הם סוגי קבצים אסורים להעלאה}}. {{PLURAL:$3|סוג הקובץ המותר הוא|סוגי הקבצים המותרים הם}} $2.",
        "api-error-filetype-missing": "חסרה סיומת לשם הקובץ.",
-       "api-error-hookaborted": "השינוי שניסיתם לעשות נחסם על ידי הרחבה.",
+       "api-error-hookaborted": "השינוי שניסית לעשות נחסם על־ידי הרחבה.",
        "api-error-http": "שגיאה פנימית: לא ניתן להתחבר לשרת.",
        "api-error-illegal-filename": "שם הקובץ הזה אינו מורשה.",
-       "api-error-internal-error": "ש×\92×\99×\90×\94 ×¤× ×\99×\9e×\99ת: ×\9eש×\94×\95 ×\94שת×\91ש ×\91עת ×¢×\99×\91×\95×\93 ×\94×\94×¢×\9c×\90×\94 ×©×\9c×\9b×\9d באתר הוויקי.",
+       "api-error-internal-error": "ש×\92×\99×\90×\94 ×¤× ×\99×\9e×\99ת: ×\9eש×\94×\95 ×\94שת×\91ש ×\91עת ×¢×\99×\91×\95×\93 ×\94×\94×¢×\9c×\90×\94 ×©×\9c×\9a באתר הוויקי.",
        "api-error-invalid-file-key": "שגיאה פנימית: הקובץ לא נמצא במאגר הזמני.",
        "api-error-missingparam": "שגיאה פנימית: פרמטרים חסרים בבקשה שנשלחה.",
        "api-error-missingresult": "שגיאה פנימית: לא ניתן לקבוע אם ההעתקה הצליחה.",
        "api-error-timeout": "השרת לא השיב בזמן המצופה.",
        "api-error-unclassified": "אירעה שגיאה בלתי ידועה.",
        "api-error-unknown-code": "שגיאה בלתי ידועה: \"$1\".",
-       "api-error-unknown-error": "ש×\92×\99×\90×\94 ×¤× ×\99×\9e×\99ת: ×\9eש×\94×\95 ×\94שת×\91ש ×\91עת × ×\99ס×\99×\95×\9f ×\9c×\94×¢×\9c×\95ת ×\90ת ×\94ק×\95×\91×¥ ×©×\9c×\9b×\9d.",
+       "api-error-unknown-error": "ש×\92×\99×\90×\94 ×¤× ×\99×\9e×\99ת: ×\9eש×\94×\95 ×\94שת×\91ש ×\91עת × ×\99ס×\99×\95×\9f ×\9c×\94×¢×\9c×\95ת ×\90ת ×\94ק×\95×\91×¥ ×©×\9c×\9a.",
        "api-error-unknown-warning": "אזהרה בלתי ידועה: \"$1\".",
        "api-error-unknownerror": "שגיאה בלתי ידועה: \"$1\".",
        "api-error-uploaddisabled": "ההעלאה מבוטלת באתר הוויקי הזה.",
        "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 dir=\"ltr\">$wgDefaultSkin</code> כ־<code>$1</code>, אינו זמין.\n\nנראה שההתקנה שלכם כוללת את העיצובים הבאים. ראו מידע בדף [https://www.mediawiki.org/wiki/Manual:Skin_configuration \"הגדרת עיצובים\" במדריך] על האפשרות להפעיל אותם ולבחור את עיצוב ברירת המחדל.\n\n$2\n\n; אם כרגע התקנתם את מדיה־ויקי:\n: נראה שזו התקנה מ־git, או ישירות מקוד המקור בשיטה אחרת כלשהי. במקרה הזה, בעיה זו צפויה. נסו להתקין כמה עיצובים מ[https://www.mediawiki.org/wiki/Category:All_skins ספריית העיצובים של mediawiki.org], על־ידי:\n:* הורדת [https://www.mediawiki.org/wiki/Download קובץ ה־tar להתקנה], שכולל מספר עיצובים והרחבות. באפשרותכם להעתיק ולהדביק מתוכו את תיקיית ה‏‏־<code>skins/</code>.\n:* שכפול (clone) אחד מהמאגרים ב־<code dir=\"ltr\">mediawiki/skins/*</code> בעזרת git לתוך תיקיית ה־<code dir=\"ltr\">skins/</code> בהתקנת מדיה־ויקי שלכם.\n: אם תעשו זאת, זה לא אמור להפריע ל‏‏מאגר ה־git שלכם אם אתם מפתחים של מדיה־ויקי.\n\n; אם כרגע שדרגתם את מדיה־ויקי:\n: מדיה־ויקי 1.24 וגרסאות חדשות יותר כבר לא מפעילות עיצובים מותקנים באופן אוטומטי (ראו [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery \"גילוי אוטומטי של עיצובים\" במדריך]). תוכלו להעתיק את השורות הבאות לתוך הקובץ <code>LocalSettings.php</code> כדי להפעיל את כל העיצובים המותקנים כעת:\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 וגרסאות חדשות יותר אינן כוללות עיצובים ב־git repository הראשי. נסו להתקין כמה עיצובים מ[https://www.mediawiki.org/wiki/Category:All_skins ספריית העיצובים של mediawiki.org], על־ידי:\n:* הורדת [https://www.mediawiki.org/wiki/Download קובץ ה‏‏־tar להתקנה], שכולל מספר עיצובים והרחבות. באפשרותכם להעתיק ולהדביק מתוכו את תיקיית ה‏‏־<code>skins/</code>.\n:* שכפול (clone) אחד ממאגרים ב־<code>mediawiki/skins/*</code> בעזרת git לתוך תיקיית ה־<code dir=\"ltr\">skins/</code> בהתקנת מדיה־ויקי שלכם.\n: אם תעשו זאת, זה לא אמור להפריע ל‏‏מאגר ה־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 ('''מבוטל''')"
 }
index 6845717..81a03f4 100644 (file)
@@ -54,7 +54,8 @@
                        "לערי ריינהארט",
                        "आलोक",
                        "रोहित रावत",
-                       "아라"
+                       "아라",
+                       "संजीव कुमार"
                ]
        },
        "tog-underline": "कड़ियाँ अधोरेखन:",
@@ -71,6 +72,7 @@
        "tog-watchdefault": "मेरे द्वारा सम्पादित पृष्ठों और फ़ाइलों को मेरी ध्यानसूची में जोड़ें",
        "tog-watchmoves": "मेरे द्वारा स्थानांतरित पृष्ठों एवं फ़ाइलों को मेरी ध्यानसूची में जोड़ें",
        "tog-watchdeletion": "मेरे द्वारा हटाए गए पृष्ठों एवं फ़ाइलों को मेरी ध्यानसूची में जोड़ें",
+       "tog-watchrollback": "मेरे द्वारा प्रत्यापन्न (रोलबैक) किये हुये पृष्ठों को मेरी ध्यानसूची में जोड़ें।",
        "tog-minordefault": "मेरे सभी सम्पादन छोटे बदलाव हैं",
        "tog-previewontop": "सम्पादन बक्से के ऊपर झलक दिखाएँ",
        "tog-previewonfirst": "प्रथम सम्पादन के बाद झलक दिखाएँ",
        "view": "दर्शाव",
        "view-foreign": "$1 पर देखें",
        "edit": "सम्पादन",
+       "edit-local": "स्थानीय विवरण सम्पादन",
        "create": "बनाएँ",
+       "create-local": "स्थानीय विवरण निर्माण",
        "editthispage": "इस पृष्ठ को बदलें",
        "create-this-page": "यह पृष्ठ बनाएँ",
        "delete": "हटाएँ",
        "talkpagelinktext": "चर्चा",
        "specialpage": "विशेष पृष्ठ",
        "personaltools": "वैयक्तिक औज़ार",
-       "postcomment": "नया अनुभाग",
        "articlepage": "सामग्री पृष्ठ देखें",
        "talk": "चर्चा",
        "views": "दर्शाव",
        "jumptonavigation": "भ्रमण",
        "jumptosearch": "खोज",
        "view-pool-error": "क्षमा करें, इस समय सर्वरों पर अतिभार है।\nबहुत सारे प्रयोक्ता इस पृष्ठ को देखने का प्रयास कर रहे हैं।\nकृपया कुछ समय प्रतीक्षा कर फिर से इस पृष्ठ को देखने का प्रयास करें।\n\n$1",
+       "generic-pool-error": "क्षमा करें, इस समय सर्वरों पर अत्यधिक भार है।\nइस सामग्री को बहुत अधिक प्रयोक्ता देखने का प्रयत्न कर रहे हैं।\nकृपया इसे देखने का पुनः यत्न कुछ समय पश्चात करें।",
        "pool-timeout": "तालाबन्दी के लिए प्रतीक्षा समय समाप्त",
        "pool-queuefull": "पूल पंक्ति भरी हुई है",
        "pool-errorunknown": "अज्ञात त्रुटि",
        "hidetoc": "छुपाएँ",
        "collapsible-collapse": "छोटा करें",
        "collapsible-expand": "विस्तार करें",
+       "confirmable-confirm": "क्या {{GENDER:$1|आप}} निश्चित हो?",
+       "confirmable-yes": "हाँ",
+       "confirmable-no": "नहीं",
        "thisisdeleted": "$1 देखें या वापिस लाएँ?",
        "viewdeleted": "$1 दिखायें?",
        "restorelink": "{{PLURAL:$1|एक हटाया हुआ|$1 हटाये हुए}} बदलाव",
        "externaldberror": "या तो प्रमाणिकरण डाटाबेस में त्रुटि हुई है या फिर आपको अपना बाह्य खाता अपडेट करने की अनुमति नहीं है।",
        "login": "लॉग इन",
        "nav-login-createaccount": "सत्रारंभ / खाता खोलें",
-       "loginprompt": "{{SITENAME}} पर लॉग इन करने के लिए अपने ब्राउज़र पर कुकीज़ (cookies) सक्षम करें।",
        "userlogin": "सत्रारंभ / खाता खोलें",
        "userloginnocreate": "लॉग इन",
        "logout": "सत्रांत",
        "gotaccountlink": "लॉग इन",
        "userlogin-resetlink": "अपनी प्रवेश जानकारी भूल गए हैं?",
        "userlogin-resetpassword-link": "अपना पासवर्ड भूल गए?",
-       "userlogin-loggedin": "आप {{GENDER:$1|$1}} के रूप में पहले से लॉग्ड इन हैं।\nकिसी अन्य सदस्य के रूप में लॉग इन करने के लिए निम्नलिखित फ़ॉर्म का प्रयोग करें।",
-       "userlogin-createanother": "एक अन्य खाता खोलें",
+       "userlogin-helplink2": "लॉग इन करने में सहायता",
        "createacct-emailrequired": "ई-मेल पता",
        "createacct-emailoptional": "ई-मेल पता (वैकल्पिक)",
        "createacct-email-ph": "अपना ई-मेल पता लिखें",
        "edit-gone-missing": "पृष्ठ अद्यतित न किया जा सका।\nलगता है यह हटा दिया गया है।",
        "edit-conflict": "संपादन अंतर्विरोध",
        "edit-no-change": "आपने कोई बदलाव ही नहीं किए, अतः आपके इस संपादन को नज़रंदाज़ कर दिया गया है।",
+       "postedit-confirmation-created": "पृष्ठ निर्मित किया गया है।",
+       "postedit-confirmation-restored": "पृष्ठ पुरानी स्थिति पर लाया गया है।",
        "postedit-confirmation-saved": "आपका सम्पादन सहेजा गया है।",
        "edit-already-exists": "नया पृष्ठ बनाया नहीं जा सका।\nयह पहले से मौजूद है।",
        "defaultmessagetext": "संदेश का डिफ़ॉल्ट पाठ",
        "parser-template-loop-warning": "साँचा चक्र मिला: [[$1]]",
        "parser-template-recursion-depth-warning": "साँचा पुनरावर्ती गहराई सीमा पार ($1)",
        "language-converter-depth-warning": "भाषा कन्वर्टर गहराई सीमा से बाहर गया ( $1 )",
-       "node-count-exceeded-category": "पृष्ठ जिनमें नोड-संख्या पार की गई है",
+       "node-count-exceeded-category": "पृष्ठ जिनमें नोड-संख्या सीमा पार की गई है",
+       "node-count-exceeded-category-desc": "यह उन पृष्ठों की श्रेणी है जिनमें नोड-संख्या सीमा पार की गयी है।",
        "node-count-exceeded-warning": "पृष्ठ ने नोड-संख्या पार की है",
        "expansion-depth-exceeded-category": "पृष्ठ जिनमें विस्तार गहराई पार की गई है",
+       "expansion-depth-exceeded-category-desc": "यह पृष्ठ विस्तार गहराई पार करता है।",
        "expansion-depth-exceeded-warning": "पृष्ठ में विस्तार गहराई पार की गई है",
        "parser-unstrip-loop-warning": "Unstrip लूप पाया गया",
        "parser-unstrip-recursion-limit": "Unstrip पुनरावर्तन सीमा पार की गई ($1)",
        "currentrev": "सद्य अवतरण",
        "currentrev-asof": "$1 के समय का अवतरण",
        "revisionasof": "$1 का अवतरण",
-       "revision-info": "$2 द्वारा परिवर्तित $1 का अवतरण",
+       "revision-info": "{{GENDER:$6|$2}} द्वारा परिवर्तित $1 का अवतरण$7",
        "previousrevision": "← पुराना अवतरण",
        "nextrevision": "नया अवतरण →",
        "currentrevisionlink": "वर्तमान अवतरण",
        "revdelete-no-file": "निर्दिष्ट फ़ाइल मौजूद नहीं है।",
        "revdelete-show-file-confirm": "क्या आप वाकई फ़ाइल \"<nowiki>$1</nowiki>\" के $2 को $3 बजे बने, हटाए जा चुके अवतरण को देखना चाहते हैं?",
        "revdelete-show-file-submit": "हाँ",
+       "revdelete-selected-text": "[[:$2]] {{PLURAL:$1|का|के}} चयनित अवतरण:",
+       "revdelete-selected-file": "[[:$2]] {{PLURAL:$1|का|के}} चयनित फ़ाइल अवतरण:",
        "logdelete-selected": "{{PLURAL:$1|चुना हुआ|चुने हुए}} लॉग इवेंट:",
        "revdelete-confirm": "पुष्टि करें कि आप यह कार्य करना चाहते हैं, आप इसका परिणाम समझते हैं, और आप ये [[{{MediaWiki:Policy-url}}|नीति]] के अनुसार कर रहे हैं।",
        "revdelete-suppress-text": "छिपाने का प्रयोग <strong>केवल</strong> इन परिस्थितियों में होना चाहिए:\n* संभावित अपमानजनक जानकारी\n* अनुपयुक्त निजी जानकारी\n*: <em>घर के पते व दूरभाष, राष्ट्रीय पहचान क्रमांक आदि।</em>",
        "searchprofile-advanced-tooltip": "विशेष नामस्थानों में खोजें",
        "search-result-size": "$1 ({{PLURAL:$2|$2 शब्द}})",
        "search-result-category-size": "{{PLURAL:$1|$1 सदस्य}} ({{PLURAL:$2|$2 उपश्रेणी|$2 उपश्रेणियाँ}}, {{PLURAL:$3|$3 सञ्चिका|$3 सञ्चिकाएँ}})",
-       "search-result-score": "संबद्ध: $1%",
        "search-redirect": "($1 से पुनर्निर्देशित)",
        "search-section": "(अनुभाग $1)",
        "search-file-match": "(फ़ाइल सामग्री से मेल खाता है)",
        "right-move": "पृष्ठ स्थानांतरित करें",
        "right-move-subpages": "पृष्ठ उपपृष्ठों सहित स्थानांतरीत करें",
        "right-move-rootuserpages": "मूल सदस्य पृष्ठ स्थानांतरित करें",
+       "right-move-categorypages": "श्रेणी पृष्ठ स्थानांतरित करें",
        "right-movefile": "संचिकाएँ स्थानांतरित करें",
        "right-suppressredirect": "पृष्ठ स्थानांतरित करते समय पुनर्निर्देश ना छोड़ें",
        "right-upload": "फ़ाइल अपलोड करें",
        "action-createpage": "पृष्ठ बनाने",
        "action-createtalk": "वार्ता पृष्ठ बनाने",
        "action-createaccount": "यह सदस्य खाता खोलने",
+       "action-history": "इस पृष्ठ का इतिहास देखने",
        "action-minoredit": "इस बदलाव को छोटा बदलाव चिन्हित करने",
        "action-move": "इस पृष्ठ को स्थानांतरित करने",
        "action-move-subpages": "इस पृष्ठ व इसके उप-पृष्ठों को स्थानांतरित करने",
        "action-move-rootuserpages": "मूल सदस्य पृष्ठों को स्थानांतरित करने",
+       "action-move-categorypages": "श्रेणी पृष्ठ स्थानांतरित करने",
        "action-movefile": "इस फ़ाइल को स्थानांतरित करने",
        "action-upload": "इस फ़ाइल को अपलोड करने",
        "action-reupload": "मौजूदा फ़ाइल के स्थान पर नई सामग्री डालने",
        "windows-nonascii-filename": "यह विकि विशेष कैरैक्टरों के साथ फ़ाइल के नामों को स्वीकार नहीं करता।",
        "fileexists": "इस नाम की फ़ाइल पहले से मौजूद है, यदि यह फ़ाइल बदलने में आप साशंक हैं तो कृपया <strong>[[:$1]]</strong> देखें। [[$1|thumb]]",
        "filepageexists": "इस फ़ाइल के लिए विवरण पृष्ठ पहले ही <strong>[[:$1]]</strong> पर बनाया जा चुका है, पर इस नाम की कोई फ़ाइल अभी उपस्थित नहीं है। \nआप जो विवरण देंगे वह विवरण पृष्ठ पर नहीं दिखेगा। \nआपको अपने विवरण को वहाँ डालने के लिए उसका हस्त्य सम्पादन करना पड़ेगा।\n[[$1|thumb]]",
-       "fileexists-extension": "à¤\87स à¤¨à¤¾à¤® à¤¸à¥\87 à¤®à¤¿à¤²à¤¤à¥\87-à¤\9cà¥\81लतà¥\87 à¤¨à¤¾à¤® à¤\95à¥\80 à¤\8fà¤\95 à¤«à¤¼à¤¾à¤\87ल à¤ªà¤¹à¤²à¥\87 à¤¸à¥\87 à¤¹à¥\88: [[$2|thumb]]\n* à¤\85पलà¥\8bड à¤¹à¥\8b à¤°à¤¹à¥\80 à¤«à¤¼à¤¾à¤\87ल à¤\95ा à¤¨à¤¾à¤®: <strong>[[:$1]]</strong>\n* à¤®à¥\8cà¤\9cà¥\82दा à¤«à¤¼à¤¾à¤\87ल à¤\95ा à¤¨à¤¾à¤®: <strong>[[:$2]]</strong>\nà¤\95à¥\83पया à¤\85नà¥\8dय à¤¨à¤¾à¤® à¤\9aà¥\81नà¥\87à¤\82।",
+       "fileexists-extension": "à¤\87स à¤¨à¤¾à¤® à¤¸à¥\87 à¤®à¤¿à¤²à¤¤à¥\87-à¤\9cà¥\81लतà¥\87 à¤¨à¤¾à¤® à¤\95à¥\80 à¤\8fà¤\95 à¤«à¤¼à¤¾à¤\87ल à¤ªà¤¹à¤²à¥\87 à¤¸à¥\87 à¤¹à¥\88: [[$2|thumb]]\n* à¤\85पलà¥\8bड à¤¹à¥\8b à¤°à¤¹à¥\80 à¤«à¤¼à¤¾à¤\87ल à¤\95ा à¤¨à¤¾à¤®: <strong>[[:$1]]</strong>\n* à¤®à¥\8cà¤\9cà¥\82दा à¤«à¤¼à¤¾à¤\87ल à¤\95ा à¤¨à¤¾à¤®: <strong>[[:$2]]</strong>\nशायद à¤\86प à¤\87ससà¥\87 à¤µà¤¿à¤¶à¤¿à¤·à¥\8dà¤\9f à¤¨à¤¾à¤® à¤\95ा à¤ªà¥\8dरयà¥\8bà¤\97 à¤\95रना à¤\9aाहà¥\87à¤\82à¤\97à¥\87?",
        "fileexists-thumbnail-yes": "यह फ़ाइल बड़े चित्र का छोटा आकार ''(अंगूठाकार)'' प्रतीत होता है। [[$1|thumb]]\n<strong>[[:$1]]</strong> फ़ाइल को देखें।\nअगर जाँची गई फ़ाइल इसी आकार की है तो छोटे आकार की फ़ाइल अपलोड करने की आवश्यकता नहीं है।",
        "file-thumbnail-no": "इस फ़ाइल का नाम <strong>$1</strong> से शुरू हो रहा है।\nयह आकार घटाई हुई ''(अंगूठाकार)'' हो सकती है।\nअगर यह चित्र अपने मूल आकार में है तो इसे अपलोड करें, नहीं तो फ़ाइल बदलें।",
        "fileexists-forbidden": "इस नाम की फ़ाइल पहले ही मौजूद है, और इसकी जगह और नहीं अपलोड की जा सकती।\nयदि आप इस फ़ाइल को फिर भी अपलोड करना चाहते हैं, तो कृपया वापस जा के इसके लिए कोई अन्य नाम चुनें।\n[[File:$1|thumb|center|$1]]",
        "uploadwarning": "अपलोड चेतावनी",
        "uploadwarning-text": "फ़ाइल विवरण को संशोधित कर फिर कोशिश करें।",
        "savefile": "फ़ाइल संजोयें",
-       "uploadedimage": "\"[[$1]]\" अपलोड करी",
-       "overwroteimage": "\"[[$1]]\" का नया अवतरण अपलोड किया",
        "uploaddisabled": "अपलोड प्रतिबंधित हैं।",
        "copyuploaddisabled": "यू॰आर॰एल द्वारा अपलोड अक्षम हैं।",
        "uploaddisabledtext": "फ़ाइल अपलोड अक्षम हैं।",
        "php-uploaddisabledtext": "पी॰एच॰पी में फ़ाइल अपलोड बंद हैं।\nकृपया file_uploads जमाव की जाँच करें।",
        "uploadscripted": "इस फ़ाइल में एच॰टी॰एम॰एल या स्क्रिप्ट कोड है, जो वेब ब्राउज़र द्वारा गलत पढ़ा जा सकता है।",
+       "uploadscriptednamespace": "इस एस॰वी॰जी फ़ाइल में अमान्य नामस्थान \"$1\" है।",
        "uploadinvalidxml": "अपलोड की गई फ़ाइल में स्थित XML पार्स नहीं की जा सकी।",
        "uploadvirus": "इस फ़ाइल में व्हाईरस हैं! अधिक जानकारी: $1",
        "uploadjava": "यह फ़ाइल एक ज़िप फ़ाइल है जिसमें एक जावा .class फ़ाइल है।\nजावा फ़ाइलों को अपलोड करना वर्जित है, क्योंकि इनके कारण सुरक्षा बाधाएँ पार की जा सकती हैं।",
        "license": "लाइसेन्सिंग:",
        "license-header": "लाइसेन्सिंग",
        "nolicense": "कुछ भी नहीं चुना",
+       "licenses-edit": "लाइसेंस विकल्प सम्पादन",
        "license-nopreview": "(झलक उपलब्ध नहीं है)",
        "upload_source_url": " (एक वैध, सभी जगहों से उपलब्ध यू॰आर॰एल)",
        "upload_source_file": " (आपके कम्प्यूटर से फ़ाइल)",
+       "listfiles-delete": "हटाएँ",
        "listfiles-summary": "यह विशेष पृष्ठ सभी अपलोड की गई फ़ाइलें दर्शाता है।",
        "listfiles_search_for": "मीडिया नाम के लिये खोजें:",
        "imgfile": "फ़ाइल",
        "filedelete-maintenance": "रखरखाव चल रहा है और रखरखाव के दौरान फ़ाइलों को हटाना और पुनर्स्थापित करना अक्षम है।",
        "filedelete-maintenance-title": "फ़ाइल हटा नहीं सकते",
        "mimesearch": "MIME खोज",
-       "mimesearch-summary": "MIME-प्रकारों के अनुसार फ़ाइलें खोजने के लिये इस पृष्ठ का इस्तेमाल किया जा सकता है।\nइनपुट: फ़ाइल का प्रकार/उपप्रकार, उदा. <code>image/jpeg</code>.",
+       "mimesearch-summary": "MIME-प्रकारों के अनुसार फ़ाइलें खोजने के लिये इस पृष्ठ का इस्तेमाल किया जा सकता है।\nइनपुट: फ़ाइल का प्रकार/उपप्रकार या प्रकार/*, उदा. <code>image/jpeg</code>।",
        "mimetype": "MIME प्रकार:",
        "download": "डाउनलोड",
        "unwatchedpages": "ध्यान न दिये हुए पृष्ठ",
        "randomincategory": "श्रेणी में यादृच्छिक (रैंडम) पृष्ठ",
        "randomincategory-invalidcategory": "\"$1\" एक मान्य श्रेणी नाम नहीं है।",
        "randomincategory-nopages": "[[:Category:$1|$1]] श्रेणी में कोई पृष्ठ नहीं हैं।",
-       "randomincategory-selectcategory": "श्रेणी से यादृच्छिक (रैंडम) पृष्ठ खोलें: $1 $2",
-       "randomincategory-selectcategory-submit": "खोलें",
        "randomredirect": "किसी एक पुनर्निर्देशन पर जाएँ",
        "randomredirect-nopages": "नामस्थान \"$1\" में कोई पुनर्निर्देशन नहीं हैं।",
        "statistics": "आँकड़े",
        "wantedtemplates": "वांछित साँचे",
        "mostlinked": "सर्वाधिक से जुड़े हुए पृष्ठ",
        "mostlinkedcategories": "सर्वाधिक से जुड़ी हुई श्रेणियाँ",
-       "mostlinkedtemplates": "सरà¥\8dवाधिà¤\95 à¤¸à¥\87 à¤\9cà¥\81ड़à¥\87 à¤¹à¥\81à¤\8f à¤¸à¤¾à¤\81à¤\9aà¥\87",
+       "mostlinkedtemplates": "सरà¥\8dवाधिà¤\95 à¤\9fà¥\8dराà¤\82सà¤\95à¥\8dलà¥\82ड à¤\95ियà¥\87 à¤\97यà¥\87 à¤ªà¥\83षà¥\8dठ",
        "mostcategories": "सर्वाधिक श्रेणियों वाले पृष्ठ",
        "mostimages": "सर्वाधिक से जुड़ी हुई फ़ाइलें",
        "mostinterwikis": "सर्वाधिक अंतरविकी कड़ियों वाले पृष्ठ",
        "watchlist-details": "वार्ता पृष्ठों के अलावा {{PLURAL:$1|$1 पृष्ठ}} आपकी ध्यानसूची में हैं।",
        "wlheader-enotif": "ई-मेल नोटिफ़िकेशन सक्षम हैं।",
        "wlheader-showupdated": "पृष्ठ जो आपके द्वारा देखे जाने के बाद बदले गये हैं '''बोल्ड''' दिखेंगे।",
-       "wlnote2": "$2,$3 तक आखरी {{PLURAL:$1|घंटे|<strong>$1</strong> घंटों}} में बदलाव निम्नलिखित हैं।",
+       "wlnote": "$3 को $4 बजे तक पिछले '''$2''' {{PLURAL:$2|घंटे|घंटों}} में {{PLURAL:$1|हुआ एक|हुए '''$1'''}} परिवर्तन निम्न {{PLURAL:$1|है|हैं}}।",
        "wlshowlast": "पिछले $1 घंटे $2 दिन $3 देखें",
        "watchlist-options": "ध्यानसूची विकल्प",
        "watching": "ध्यान दे रहे हैं...",
        "import": "पृष्ठ इम्पोर्ट करें",
        "importinterwiki": "ट्रान्सविकि आयात",
        "import-interwiki-text": "आयात करने के लिये एक विकि और एक पृष्ठ चुनें।\nअवतरण दिनांक और संपादक नाम ज्यों-के-त्यों रखे जाएँगे।\nसभी ट्रान्सविकि आयात क्रियाएँ [[Special:Log/import|आयात लॉग]] में डाली जाती हैं।",
-       "import-interwiki-source": "स्रोत विकि/पृष्ठ:",
        "import-interwiki-history": "इस पृष्ठ के सभी इतिहास अवतरण कॉपी करें",
        "import-interwiki-templates": "सभी साँचे शामिल करें",
        "import-interwiki-submit": "आयात",
        "duplicate-defaultsort": "'''Warning:''' पुरानी मूल क्रमांकन कुंजी \"$1\" के बजाय अब मूल क्रमांकन कुंजी \"$2\" होगी।",
        "version": "रूपान्तर",
        "version-extensions": "इन्स्टॉल की हुई एक्स्टेंशन",
+       "version-skins": "इन्स्टॉल की गयी त्वचाएँ",
        "version-specialpages": "विशेष पृष्ठ",
        "version-parserhooks": "पार्सर हूक",
        "version-variables": "वेरिएबल",
        "version-antispam": "अवांछित-ईमेल रोकथाम",
-       "version-skins": "त्वचाएं",
        "version-other": "अन्य",
        "version-mediahandlers": "मीडिया संचालक",
        "version-hooks": "हूक",
index 21f50ce..0062c26 100644 (file)
@@ -10,7 +10,8 @@
                        "Malafaya",
                        "Thakurji",
                        "아라",
-                       "Soul Train"
+                       "Soul Train",
+                       "Filipinayzd"
                ]
        },
        "tog-underline": "Jorr ke niche line khicho:",
        "talkpagelinktext": "Baat",
        "specialpage": "Khaas Panna",
        "personaltools": "Aapan aujaar",
-       "postcomment": "Nawaa section",
        "articlepage": "Content waala panna ke dekho",
        "talk": "Salah",
        "views": "Bichar",
        "externaldberror": "Koi bahaari database authentication error hai, nai to aap ke bahaari account badle ke adhikar nai hai.",
        "login": "Log in karo",
        "nav-login-createaccount": "Log in karo/ nawaa account banao",
-       "loginprompt": "Login kare ke khatir  {{SITENAME}} cookies ke laabu kare ke chaahi.",
        "userlogin": "Log in karo/ nawaa account banao",
        "userloginnocreate": "Log in karo",
        "logout": "Log out",
        "searchprofile-advanced-tooltip": "Custom namespaces me khojo",
        "search-result-size": "$1 ({{PLURAL:$2|1 sabd|$2 sabd}})",
        "search-result-category-size": " {{PLURAL:$1|1 sadasya|$1 sadasya}} ({{PLURAL:$2|1 chhota vibhag|$2 chhota vibhag}}, {{PLURAL:$3|1 file|$3 files}})",
-       "search-result-score": "Len den: $1%",
        "search-redirect": "(redirect $1)",
        "search-section": "(section $1)",
        "search-suggest": "Ka aap ke matlab rahaa: $1",
        "saveprefs": "Save karo",
        "restoreprefs": "Sab default settings ke pahile jaise karo (sab vibhag me)",
        "prefs-editing": "Badaltaa hai",
-       "rows": "Line:",
+       "rows": "Taytay:",
        "columns": "Column:",
        "searchresultshead": "Khojo",
        "stub-threshold": "Threshold ke khatir <a href=\"#\" class=\"stub\">stub link</a> formatting (bytes):",
        "uploadwarning": "Upload ke baare me chetauni",
        "uploadwarning-text": "Meharbani kar ke file ke baaare me aur jankari ke niche badal ke aur fir se kosis karo.",
        "savefile": "File ke save karo",
-       "uploadedimage": "\"[[$1]]\" ke upload kar dewa gae",
-       "overwroteimage": "\"[[$1]]\" ke nawaa version ke upload karaa gais hai",
        "uploaddisabled": "Uploads ke disable kar dewa gais hai",
        "copyuploaddisabled": "URL se upload kare pe rok lagae dewa gais hae.",
        "uploaddisabledtext": "File uploads ke disable kar dewa gais hai.",
        "watchlist-details": "{{PLURAL:$1|$1 panna|$1 panna}} pe dhyan dewa jae hai, baat waala panna ke chhorr ke.",
        "wlheader-enotif": "E-mail notification ke enable kar dewa gais hai.",
        "wlheader-showupdated": "Panna jiske aap ke pichhla visit ke ke baad badal dewa gais hia ke '''bold''' me dekhawa jaawe hai.",
+       "wlnote": "Niche ke {{PLURAL:$1|pahile waala badlao hai| pahile '''$1''' badlao hai}} pichhle {{PLURAL:$2|ghanta|'''$2''' ghanta}} me as of $3, $4..",
        "wlshowlast": "Pichhla $1 ghanta $2 din $3 ke dekhao",
        "watchlist-options": "Dhyan suchi ke options",
        "watching": "Dekhtaa...",
index 255e77f..1600b9d 100644 (file)
        "talkpagelinktext": "Hisayranay",
        "specialpage": "Espesyal nga panid",
        "personaltools": "Mga kinaugalingon nga galamiton",
-       "postcomment": "Bag-o nga seksyon",
        "articlepage": "Lantawon ang panid sang ka-undan",
        "talk": "Paghisayranay",
        "views": "Mga talanawon",
        "externaldberror": "Mahimo nga may ara sang sala sa pagpamatood sang database ukon wala ka sa lugar nga magbag-o sang imo pang-guha nga akawnt.",
        "login": "Mag sulod",
        "nav-login-createaccount": "Magsulod / maghimo account",
-       "loginprompt": "Kinahanglan mo nga pasugtan ang kokes agod nga makasulod ka sa {{SITENAME}}.",
        "userlogin": "Mag sulod / maghimo account",
        "userloginnocreate": "Magsulod",
        "logout": "Mag guha",
        "searchprofile-advanced-tooltip": "Pangitaon sa pahungod nga espasyo sang pangalan",
        "search-result-size": "$1 ({{PLURAL:$2|1 pulong|$2 pulong}})",
        "search-result-category-size": "{{PLURAL:$1|1 ka miyembro|$1 ka mga miyembro}} ({{PLURAL:$2|1 ka subcategoriya|$2 ka mga subcategoriya}}, {{PLURAL:$3|1 ka hilera|$3 ka mga hilera}})",
-       "search-result-score": "Pagkaangot: $1%",
        "search-redirect": "(gindirekta liwat $1)",
        "search-section": "(seksiyon $1)",
        "search-suggest": "Ang buot mo silingon: $1",
        "file-too-large": "Ang dokumeto ginapadala mo madako gid.",
        "filename-tooshort": "Ang ngalan sang dokumento malipot gid.",
        "filetype-banned": "Ini sari ni dokumento madumili.",
-       "uploadedimage": "na-uplod \"[[$1]]\"",
        "watchthisupload": "Bantayan ining panid",
        "license": "Pagpanglisensya",
        "license-header": "Pagpanglisensya",
index f2cf581..c68547b 100644 (file)
        "tog-showtoolbar": "Prikaži traku s alatima za uređivanje (zahtijeva JavaScript)",
        "tog-editondblclick": "Dvoklik otvara uređivanje stranice (JavaScript)",
        "tog-editsectiononrightclick": "Pritiskom na desnu tipku miša otvori uređivanje pojedinih odlomaka (JavaScript)",
-       "tog-watchcreations": "Dodaj članke koje kreiram na moj popis praćenja",
+       "tog-watchcreations": "Dodaj stranice koje sam stvorio na moj popis praćenja",
        "tog-watchdefault": "Dodaj svaku stranicu koju uredim na moj popis praćenja",
        "tog-watchmoves": "Dodaj stranice i datoteke koje premjestim na moj popis praćenja",
        "tog-watchdeletion": "Dodaj stranice i datoteke koje izbrišem na popis praćenja",
+       "tog-watchrollback": "Dodaj stranice na kojima sam vratio uređivanja na popis praćenja",
        "tog-minordefault": "Normalno označavaj sve moje izmjene kao manje",
        "tog-previewontop": "Prikaži kako će stranica izgledati iznad okvira za uređivanje",
        "tog-previewonfirst": "Prikaži kako će stranica izgledati čim otvorim uređivanje",
        "view": "Vidi",
        "view-foreign": "vidi na projektu $1",
        "edit": "uredi",
+       "edit-local": "Uredi lokalni opis",
        "create": "Započni",
        "create-local": "dodaj lokalni opis",
        "editthispage": "Uredi ovu stranicu",
        "talkpagelinktext": "razgovor",
        "specialpage": "Posebna stranica",
        "personaltools": "Osobni alati",
-       "postcomment": "Novi odlomak",
        "articlepage": "Vidi članak",
        "talk": "Razgovor",
        "views": "Pogledi",
        "externaldberror": "Došlo je do pogreške s vanjskom autorizacijom ili Vam nije dopušteno osvježavanje vanjskog suradničkog računa.",
        "login": "Prijavi se",
        "nav-login-createaccount": "Prijavi se",
-       "loginprompt": "Za prijavu na sustav {{SITENAME}} morate u pregledniku uključiti kolačiće (cookies).",
        "userlogin": "Prijavi se / stvori račun",
        "userloginnocreate": "Prijavi se",
        "logout": "Odjavi se",
        "gotaccountlink": "Prijavite se",
        "userlogin-resetlink": "Zaboravili ste detalje vaše prijave?",
        "userlogin-resetpassword-link": "Zaboravili ste zaporku?",
-       "userlogin-loggedin": "Već ste prijavljeni kao {{GENDER:$1|$1}}.\nRabite donji obrazac da biste se prijavili kao drugi suradnik.",
-       "userlogin-createanother": "Stvori još jedan račun",
        "createacct-emailrequired": "Adresa e-pošte",
        "createacct-emailoptional": "Adresa e-pošte",
        "createacct-email-ph": "Upišite svoju adresu e-pošte",
        "createacct-benefit-heading": "{{SITENAME}} su stvorili ljudi poput Vas.",
        "createacct-benefit-body1": "{{PLURAL:$1|uređivanje|uređivanja}}",
        "createacct-benefit-body2": "{{PLURAL:$1|stranica|stranice|stranica}}",
-       "createacct-benefit-body3": "nedavnih {{PLURAL:$1|suradnik|suradnika}}",
+       "createacct-benefit-body3": "{{PLURAL:$1|nedavni suradnik|nedavnih suradnika}}",
        "badretype": "Unesene lozinke nisu istovjetne.",
        "userexists": "Uneseno suradničko ime već je u upotrebi.\nUnesite neko drugo ime.",
        "loginerror": "Pogrješka u prijavi",
        "login-userblocked": "Ovaj je suradnik blokiran. Prijava nije dopuštena.",
        "wrongpassword": "Lozinka koju ste unijeli nije ispravna. Pokušajte ponovno.",
        "wrongpasswordempty": "Niste unijeli lozinku. Pokušajte ponovno.",
-       "passwordtooshort": "Lozinka mora sadržavati najmanje {{PLURAL:$1|1 znak|$1 znaka|$1 znakova}}.",
+       "passwordtooshort": "Zaporka mora sadržavati najmanje {{PLURAL:$1|1 znak|$1 znaka|$1 znakova}}.",
        "password-name-match": "Vaša lozinka mora biti različita od Vašeg suradničkog imena.",
        "password-login-forbidden": "Uporaba ovog suradničkog imena i lozinke nije dozvoljena.",
        "mailmypassword": "Pošalji mi novu lozinku",
        "passwordremindertext": "Netko je (vjerojatno Vi, s IP adrese $1) zatražio novu lozinku za projekt {{SITENAME}} ($4).\nPrivremena lozinka za suradnika \"$2\" je postavljena na \"$3\".\nUkoliko ste to Vi učinili, molimo Vas da se prijavite i promijenite lozinku.\nPrivremena lozinka vrijedi još {{PLURAL:$5|$5 dan|$5 dana}}.\n\nUkoliko niste zatražili novu lozinku, ili ste se sjetili stare lozinke i\nviše ju ne želite promijeniti, slobodno zanemarite ovu poruku i nastavite\nkoristiti staru lozinku.",
        "noemail": "Suradnik \"$1\" nema zapisanu e-mail adresu.",
        "noemailcreate": "Morate navesti važeću e-mail adresu",
-       "passwordsent": "Nova je lozinka poslana na e-mail adresu suradnika \"$1\"",
+       "passwordsent": "Nova je zaporka poslana na adresu elektroničke pošte suradnika \"$1\"",
        "blocked-mailpassword": "Vašoj IP adresi je blokirano uređivanje stranica, a da bi se spriječila nedopuštena radnja, mogućnost zahtijevanja nove lozinke je također onemogućena.",
        "eauthentsent": "Na navedenu adresu poslana je e-poruka s potvrdom.\nPrije nego što pošaljemo daljnje poruke, molimo Vas otvorite e-poruku i slijedite u njemu sadržana uputstva kako biste potvrdili da je adresa e-pošte zaista Vaša.",
        "throttled-mailpassword": "Već Vam je poslan e-mail za promjenu zaporke, u {{PLURAL:$1|posljednjih sat vremena|posljednja $1 sata|posljednjih $1 sati}}.\nDa bi spriječili zloupotrebu, moguće je poslati samo jedan e-mail za promjenu zaporke {{PLURAL:$1|svakih sat vremena|svaka $1 sata|svakih $1 sati}}.",
        "php-mail-error-unknown": "Nepoznata pogrješka u funkciji PHP-poruke()",
        "user-mail-no-addy": "Pokušaj slanja e-maila bez e-mail adrese.",
        "user-mail-no-body": "Pokušali ste poslati e-mail bez sadržaja ili s prekratkim sadržajem.",
-       "changepassword": "Promjena lozinke",
+       "changepassword": "Promjena zaporke",
        "resetpass_announce": "Da biste završili proces mijenjanja lozinke, upišite \nnovu lozinku.",
        "resetpass_header": "Promijeni lozinku računa",
        "oldpassword": "Stara lozinka",
        "passwordreset": "Ponovno postavi lozinku",
        "passwordreset-text-one": "Ispunite ovaj obrazac ako želite ponovno postaviti Vašu zaporku.",
        "passwordreset-text-many": "{{PLURAL:$1|Ispunite jedno od polja da biste dobili privremenu zaporku e-poštom.}}",
-       "passwordreset-legend": "Poništi lozinku",
+       "passwordreset-legend": "Poništi zaporku",
        "passwordreset-disabled": "Poništavanje lozinke je onemogućeno na ovom wikiju.",
        "passwordreset-emaildisabled": "Funkcija e-pošte je onemogućena na ovom wikiju.",
        "passwordreset-username": "Suradničko ime:",
        "passwordreset-emailsent-capture": "Poslan Vam je podsjetnik kao e-pošta (tekst je prikazan dolje).",
        "passwordreset-emailerror-capture": "Napravljena je e-poruka za ponovno postavljanje zaporke (prikazana ispod), ali njeno slanje suradniku nije uspjelo: $1",
        "changeemail": "Promijeni e-mail adresu",
-       "changeemail-header": "Promijeni e-mail adresu računa",
+       "changeemail-header": "Promijeni adresu e-pošte računa",
        "changeemail-text": "Za promjenu e-mail adrese popunite ovaj obrazac. Morat ćete unijeti svoju lozinku da potvrdite ovu promjenu.",
        "changeemail-no-info": "Morate biti prijavljeni da biste izravno pristupili ovoj stranici.",
-       "changeemail-oldemail": "Trenutna E-mail adresa:",
-       "changeemail-newemail": "Nova E-mail adresa:",
+       "changeemail-oldemail": "Trenutačna adresa e-pošte:",
+       "changeemail-newemail": "Nova adresa e-pošte:",
        "changeemail-none": "(ništa)",
        "changeemail-password": "Zaporka za {{SITENAME}}:",
        "changeemail-submit": "Promijeni E-mail",
        "autoblockedtext": "Vaša IP adresa automatski je blokirana zbog toga što ju je koristio drugi suradnik, kojeg je blokirao $1.\nRazlog blokiranja je sljedeći:\n\n:''$2''\n\n* Početak blokade: $8\n* Blokada istječe: $6\n* Ime blokiranog suradnika: $7\n\nMožete kontaktirati $1 ili jednog od [[{{MediaWiki:Grouppage-sysop}}|administratora]] kako bi Vam pojasnili razlog blokiranja.\n\nPrimijetite da ne možete rabiti opciju \"Pošalji mu e-poruku\" ako niste upisali valjanu adresu e-pošte u Vašim [[Special:Preferences|suradničkim postavkama]] i ako niste u tome onemogućeni prilikom blokiranja.\n\nVaša trenutačna IP adresa je $3, a oznaka bloka #$5. Molimo navedite ovaj broj kod svakog upita vezano za razlog blokiranja.",
        "blockednoreason": "bez obrazloženja",
        "whitelistedittext": "Za uređivanje stranice morate se $1.",
-       "confirmedittext": "Morate potvrditi Vašu e-mail adresu prije nego što Vam bude omogućeno uređivanje. Molim unesite i ovjerite Vašu e-mail adresu u [[Special:Preferences|suradničkim postavkama]].",
+       "confirmedittext": "Morate potvrditi Vašu adresu e-pošte prije nego što Vam bude omogućeno uređivanje. Molim unesite i ovjerite Vašu adresu e-pošte u [[Special:Preferences|suradničkim postavkama]].",
        "nosuchsectiontitle": "Ne mogu pronaći odlomak",
        "nosuchsectiontext": "Pokušali ste uređivati odlomak koji ne postoji.\nMožda je premješten ili izbrisan dok ste pregledavali stranicu.",
        "loginreqtitle": "Nužna prijava",
        "edit-conflict": "Sukob uređivanja.",
        "edit-no-change": "Vaše uređivanje je zanemareno, jer nikakva promjena sadržaja nije napravljena.",
        "postedit-confirmation-created": "Stranica je stvorena.",
+       "postedit-confirmation-restored": "Stranica je vraćena.",
        "postedit-confirmation-saved": "Vaše je uređivanje sačuvano.",
        "edit-already-exists": "Neuspješno stvaranje nove stranice.\nStranica već postoji.",
        "defaultmessagetext": "Prvotni tekst poruke",
        "revdelete-selected-file": "{{PLURAL:$1|Označena inačica|Označene inačice}} datoteke [[:$2]]:",
        "logdelete-selected": "{{PLURAL:$1|Odabrani zapis u evidenciji|Odabrani zapisi u evidenciji}}:",
        "revdelete-text-text": "Izbrisane izmjene će i dalje biti vidljive u povijesti stranice, ali dijelovi sadržaja neće biti vidljivi javno.",
+       "logdelete-text": "Izbrisane izmjene i dalje će biti vidljive u zapisnicima, ali dijelovi njihova sadržaja biti će nedostupni za javnost.",
        "revdelete-text-others": "Ostali administratori na projektu {{SITENAME}} će moći vidjeti i vratiti izbrisani sadržaj na isti način, osim ako nisu postavljena dodatna ograničenja.",
        "revdelete-confirm": "Molimo potvrdite da namjeravate ovo učiniti, da razumijete posljedice i da to činite u skladu s [[{{MediaWiki:Policy-url}}|pravilima]].",
        "revdelete-suppress-text": "Sklanjanje uređivanja treba raditi '''iznimno''' u slijedećih par slučajeva:\n* Privatne informacije neprilične javnom mediju tipa\n*: ''kućna adresa i broj telefona, JMBG ili OIB, itd.''",
        "revdelete-failure": "'''Vidljivost inačice nije mogla biti ažurirana:'''\n$1",
        "logdelete-success": "'''Vidljivost uređivanja uspješno postavljena.'''",
        "logdelete-failure": "'''Vidljivost evidencije ne može biti postavljena:'''\n$1",
-       "revdel-restore": "Promijeni dostupnost",
+       "revdel-restore": "promijeni dostupnost",
        "pagehist": "stare izmjene",
        "deletedhist": "Obrisana povijest",
        "revdelete-hide-current": "Pogrješka u skrivanju stavke datirane $2, $1: ovo je trenutačna inačica. Ne može biti skrivena.",
        "searchprofile-advanced-tooltip": "Traži u zadanom imenskom prostoru",
        "search-result-size": "$1 ({{PLURAL:$2|1 riječ|$2 riječi}})",
        "search-result-category-size": "{{PLURAL:$1|1 član|$1 člana|$1 članova}} ({{PLURAL:$2|1 potkategorija|$2 potkategorije|$2 potkategorija}}, {{PLURAL:$3|1 datoteka|$3 datoteke|$3 datoteka}})",
-       "search-result-score": "Povezanost: $1%",
        "search-redirect": "(preusmjeravanje $1)",
        "search-section": "(odlomak $1)",
        "search-suggest": "Mislili ste: $1",
        "searchall": "sve",
        "showingresults": "Dolje {{PLURAL:$1|je prikazan '''$1''' rezultat|su prikazana '''$1''' rezultata|je prikazano '''$1''' rezultata}}, počevši od '''$2'''.",
        "showingresultsinrange": "Dolje {{PLURAL:$1|je prikazan '''$1''' rezultat|su prikazana '''$1''' rezultata|je prikazano '''$1''' rezultata}}, u rasponu od '''$2''' do '''$3'''.",
-       "showingresultsheader": "{{PLURAL:$5|Rezultat '''$1''' od '''$3'''|Rezultati '''$1 - $2''' od '''$3'''}} za '''$4'''",
        "search-nonefound": "Ne postoje rezultati koji se podudaraju s upitom.",
        "powersearch-legend": "Napredno pretraživanje",
        "powersearch-ns": "Traži u imenskom prostoru:",
        "prefs-watchlist-token": "Token popisa praćenja:",
        "prefs-misc": "Razno",
        "prefs-resetpass": "Promijeni lozinku",
-       "prefs-changeemail": "Promijeni E-mail",
+       "prefs-changeemail": "promijeni adresu e-pošte",
        "prefs-setemail": "Postavite E-mail adresu",
        "prefs-email": "Mogućnosti e-maila",
        "prefs-rendering": "Izgled",
        "recentchanges-noresult": "U zadanom vremenu nema promjena za zadane kriterije.",
        "recentchanges-feed-description": "Na ovoj stranici možete pratiti nedavne promjene u wikiju.",
        "recentchanges-label-newpage": "Ova izmjena stvorila je novu stranicu",
-       "recentchanges-label-minor": "Ovo je manja izmjena",
-       "recentchanges-label-bot": "Ovu izmjenu napravio je bot",
-       "recentchanges-label-unpatrolled": "Ova izmjena još nije pregledana",
+       "recentchanges-label-minor": "Manja izmjena",
+       "recentchanges-label-bot": "Izmjenu napravio bot",
+       "recentchanges-label-unpatrolled": "Nepregledana izmjena",
        "recentchanges-label-plusminus": "Promjena veličine stranice (u bajtovima)",
        "recentchanges-legend-heading": "'''Legenda:'''",
-       "recentchanges-legend-newpage": "$1 - nova stranica",
+       "recentchanges-legend-newpage": "Nova stranica",
        "rcnotefrom": "Slijede promjene od <b>$2</b> (prikazano ih je do <b>$1</b>).",
        "rclistfrom": "Prikaži nove promjene počevši od $3 $2",
        "rcshowhideminor": "$1 manje promjene",
        "uploadwarning": "Upozorenje kod postavljanja",
        "uploadwarning-text": "Molimo izmijenite opis datoteke ispod i pokušajte kasnije.",
        "savefile": "Sačuvaj datoteku",
-       "uploadedimage": "je postavio \"$1\"",
-       "overwroteimage": "postavljena nova inačica od \"[[$1]]\"",
        "uploaddisabled": "Postavljanje je onemogućeno",
        "copyuploaddisabled": "Postavljanje URL-om onemogućeno.",
        "uploaddisabledtext": "Postavljanje datoteka je onemogućeno.",
        "listfiles_size": "Veličina (u bajtovima)",
        "listfiles_description": "Opis",
        "listfiles_count": "Inačice",
+       "listfiles-show-all": "Uključujući starije inačice slika",
+       "listfiles-latestversion": "Trenutačna inačica",
        "listfiles-latestversion-yes": "Da",
        "listfiles-latestversion-no": "Ne",
        "file-anchor-link": "Slika",
        "filerevert-legend": "Vrati datoteku",
        "filerevert-intro": "Vraćate '''[[Media:$1|$1]]''' na [$4 promjenu od $3, $2].",
        "filerevert-comment": "Razlog:",
-       "filerevert-defaultcomment": "Vraćeno na inačicu od $2, $1",
+       "filerevert-defaultcomment": "vraćeno na inačicu od $1 ($2)",
        "filerevert-submit": "Vrati",
        "filerevert-success": "'''[[Media:$1|$1]]''' je vraćena na [$4 promjenu od $3, $2].",
        "filerevert-badversion": "Nema prethodne lokalne inačice datoteke s zadanim datumom i vremenom.",
        "unusedtemplateswlh": "druge poveznice",
        "randompage": "Slučajna stranica",
        "randompage-nopages": "Nema stranica u {{PLURAL:$2|imenskom prostoru|imenskim prostorima}}: $1.",
-       "randomincategory-selectcategory-submit": "Idi",
        "randomredirect": "Slučajno preusmjeravanje",
        "randomredirect-nopages": "Nema preusmjeravanja u imenskom prostoru \"$1\".",
        "statistics": "Statistika",
        "statistics-users-active": "Aktivni suradnici",
        "statistics-users-active-desc": "Suradnici koji su napravili neku od radnji u posljednjih {{PLURAL:$1|dan|$1 dana}}",
        "statistics-mostpopular": "Najposjećenije stranice",
+       "pageswithprop": "Stranice sa osobinom stranice",
+       "pageswithprop-legend": "Stranice sa osobinom stranice",
        "pageswithprop-prop": "Ime osobine:",
        "pageswithprop-submit": "Idi",
        "doubleredirects": "Dvostruka preusmjeravanja",
        "watchlist-details": "{{PLURAL:$1|$1 stranica|$1 stranice|$1 stranica}} se nalazi na popisu praćenja, ne brojeći stranice za razgovor.",
        "wlheader-enotif": "Uključeno je izvješćivanje e-poštom.",
        "wlheader-showupdated": "Stranice koje su promijenjene od Vašeg posljednjeg posjeta prikazane su '''podebljano'''",
+       "wlnote": "Ovdje {{PLURAL:$1|je posljednja $1 promjena|su posljednje $1 promjene|je posljednjih $1 promjena}} u {{PLURAL:$2|posljednjem '''$2''' satu|posljednja '''$2''' sata|posljednjih '''$2''' sati}}, od $3, $4.",
        "wlshowlast": "Prikaži posljednjih $1 sati $2 dana $3",
        "watchlist-options": "Izbornik popisa praćenja",
        "watching": "Pratim...",
        "blocklogpage": "Evidencija blokiranja",
        "blocklog-showlog": "Ovaj suradnik je ranije blokiran.\nEvidencija blokiranja je prikazan ispod kao napomena:",
        "blocklog-showsuppresslog": "Ovaj suradnik je ranije blokiran i skriven.\nZapisnik skrivanja je prikazan ispod kao napomena:",
-       "blocklogentry": "Blokiran je \"[[$1]]\" na rok $2 $3",
+       "blocklogentry": "Blokiran je \"[[$1]]\" na rok $2 $3.",
        "reblock-logentry": "promijenjene postavke blokiranja za [[$1]] na rok od $2 $3",
        "blocklogtext": "Ovo je evidencija blokiranja i deblokiranja.\nNa popisu nema automatski blokiranih IP adresa.\nZa popis trenutačnih zabrana i blokiranja vidi [[Special:BlockList|popis blokiranja]].",
-       "unblocklogentry": "Deblokiran \"$1\"",
+       "unblocklogentry": "Deblokiran je \"$1\".",
        "block-log-flags-anononly": "samo za neprijavljene suradnike",
        "block-log-flags-nocreate": "otvaranje novih suradničkih imena nije moguće",
        "block-log-flags-noautoblock": "autoblok je onemogućen",
        "import": "Uvezi stranice",
        "importinterwiki": "Transwiki uvoz",
        "import-interwiki-text": "Izaberite wiki i ime stranice za uvoz.\nPovijest stranice i imena suradnika će biti sačuvani.\nTranswiki uvoz stranica je zabilježen u [[Special:Log/import|evidenciji uvoza stranica]].",
-       "import-interwiki-source": "Izvor wiki/stranica:",
        "import-interwiki-history": "Prenesi sve inačice ove stranice",
        "import-interwiki-templates": "Uključi sve predloške",
        "import-interwiki-submit": "Uvezi",
        "markedaspatrollednotify": "Uređivanje stranice $1 označeno je pregledanim.",
        "markedaspatrollederrornotify": "Označavanje stranice pregledanom nije uspjelo.",
        "patrol-log-page": "Evidencija pregledavanja promjena",
-       "patrol-log-header": "Ovo su evidencije patroliranih izmjena.",
+       "patrol-log-header": "Ovo su evidencije ophođenih izmjena.",
        "log-show-hide-patrol": "$1 evidenciju patroliranja",
        "deletedrevision": "Izbrisana stara inačica $1",
        "filedeleteerror-short": "Pogrješka u brisanju datoteke: $1",
        "watchlistall2": "sve",
        "namespacesall": "sve",
        "monthsall": "sve",
-       "confirmemail": "Potvrda e-mail adrese",
+       "confirmemail": "Potvrdite adresu e-pošte",
        "confirmemail_noemail": "Niste unijeli važeću e-mail adresu u Vaše [[Special:Preferences|suradničke postavke]].",
        "confirmemail_text": "U ovom wikiju morate prije korištenja e-mail naredbi potvrditi svoju e-mail adresu. Kliknite na gumb ispod kako biste poslali poruku s potvrdom na Vašu adresu. U poruci će biti poveznica koju morate otvoriti u svom web pregledniku i time potvrditi svoju e-mail adresu.",
        "confirmemail_pending": "Već Vam je e-mailom poslan potvrdni kôd;\nako ste upravo otvorili suradnički račun, molimo pričekajte još nekoliko minuta da e-mail stigne prije nego što zatražite novi kôd.",
        "confirmemail_invalid": "Pogrešna potvrda. Kôd je možda istekao.",
        "confirmemail_needlogin": "Molimo $1 kako biste potvrdili Vašu e-mail adresu.",
        "confirmemail_success": "Vaša je e-mail adresa potvrđena. Možete se prijaviti i uživati u wikiju.",
-       "confirmemail_loggedin": "Vaša je e-mail adresa potvrđena.",
+       "confirmemail_loggedin": "Vaša je adresa e-pošte potvrđena.",
        "confirmemail_subject": "{{SITENAME}}: potvrda e-mail adrese",
-       "confirmemail_body": "Netko, vjerojatno Vi, s IP adrese $1 je otvorio\nsuradnički račun pod imenom \"$2\" s ovom e-mail adresom na {{SITENAME}}.\n\nKako biste potvrdili da je ovaj suradnički račun uistinu Vaš i\nomogućili e-mail funkcije na {{SITENAME}}, otvorite u Vašem\npregledniku sljedeću poveznicu:\n\n$3\n\nAko to *niste* Vi, slijedite ovaj link za poništavanje potvrde:\n\n$5\n\nValjanost ovog potvrdnog koda istječe na $4.",
+       "confirmemail_body": "Netko, vjerojatno Vi, s IP adrese $1 otvorio je\nsuradnički račun pod imenom \"$2\" s ovom adresom e-pošte na {{SITENAME}}.\n\nKako biste potvrdili da je ovaj suradnički račun uistinu Vaš i\nomogućili funkcije e-pošte na {{SITENAME}}, otvorite u Vašem\npregledniku sljedeću poveznicu:\n\n$3\n\nAko to *niste* Vi, slijedite ovu poveznicu za poništavanje potvrde:\n\n$5\n\nValjanost ovog potvrdnog kȏda istječe na $4.",
        "confirmemail_body_changed": "Netko, vjerojatno Vi, s IP adrese $1,\npromijenio je adresu e-pošte suradničkog računa \"$2\" u ovu adresu na {{SITENAME}}.\n\nKako biste potvrdili da je ovaj suradnički račun uistinu Vaš te uključili\nmogućnosti e-pošte na {{SITENAME}}, otvorite u Vašem pregledniku sljedeću poveznicu:\n\n$3\n\nUkoliko suradnički račun *ne* pripada Vama, slijedite ovu poveznicu\nza poništavanje potvrde adrese e-pošte:\n\n$5\n\nValjanost ovog potvrdnog koda istječe $4.",
        "confirmemail_body_set": "Netko, najvjerojatnije vi, s IP adrese $1,\notvorio je suradnički račun pod imenom \"$2\" s ovom adresom e-pošte na {{SITENAME}}.\n\nKako biste potvrdili da je ovaj suradnički račun uistinu vaš i uključili \nmogućnosti e-poruka na {{SITENAME}}, otvorite u vašem pregledniku sljedeću poveznicu:\n\n$3\n\nAko ovaj suradnički račun *ne* pripada vama, slijedite ovaj link \nkako biste poništili potvrdu adrese elektroničke pošte:\n\n$5\n\nValjanost ovog potvrdnog kȏda istječe u $4",
        "confirmemail_invalidated": "Potvrda E-mail adrese je otkazana",
        "logentry-rights-rights": "$1 {{GENDER:$2|je promijenio|je promijenila}} suradnička prava računa $3 iz $4 u $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|je promijenio|je promijenila}} članstvo skupine suradničkog računa $3",
        "logentry-rights-autopromote": "Suradničkom računu $1 {{GENDER:$1| automatski je promijenjeno članstvo|automatski su promijenjena članstva}} iz $4 u $5",
+       "logentry-upload-upload": "$1 је {{GENDER:$2|postavio|postavila}} $3",
+       "logentry-upload-overwrite": "$1 је {{GENDER:$2|postavio|postavila}} novu inačicu $3",
+       "logentry-upload-revert": "$1 је {{GENDER:$2|postavio|postavila}} $3",
        "rightsnone": "(suradnik)",
        "feedback-bugornote": "Ako ste spremni detaljno opisati tehnički problem molimo [$1 prijavite \"bug\"].\nInače, možete ispuniti jednostavan obrazac u nastavku. Vaš komentar biti će dodan na stranicu \"[$3 $2]\", zajedno s vašim suradničkim imenom i imenom internetskog preglednika koji rabite.",
        "feedback-subject": "Tema:",
index b952766..d51bf83 100644 (file)
        "talkpagelinktext": "Diskussion",
        "specialpage": "Spezialseit",
        "personaltools": "Meine Werkzeiche",
-       "postcomment": "Neier Abschnitt",
        "articlepage": "Inhaltsseit oonzeiche",
        "talk": "Diskussion",
        "views": "Ansichte",
        "externaldberror": "Entweder es lieht en Fehler bei der externe Authentifizierung voar orrer du därrefst dein externes Benutzerkonto net aktualisiere.",
        "login": "Oonmelde",
        "nav-login-createaccount": "Oonmelde / Benutzerkonto erstelle",
-       "loginprompt": "Zur Oonmeldung müsse Cookies aktiviert sin.",
        "userlogin": "Oonmelde / Benutzerkonto erstelle",
        "userloginnocreate": "Oonmelde",
        "logout": "Abmelde",
        "searchprofile-advanced-tooltip": "Such in weitre Noomeräume",
        "search-result-size": "$1 ({{PLURAL:$2|1 Wort|$2 Wörter}})",
        "search-result-category-size": "{{PLURAL:$1|1 Seit|$1 Seite}} ({{PLURAL:$2|1 Unnerkategorie|$2 Unnerkategorie}}, {{PLURAL:$3|1 Datei|$3 Dateie}})",
-       "search-result-score": "Relevanz: $1 %",
        "search-redirect": "(Weiterleitung von „$1“)",
        "search-section": "(Abschnitt $1)",
        "search-file-match": "(treffende Dateiinhalte)",
        "uploadwarning": "Hochloodewarnung",
        "uploadwarning-text": "Bittschön änner unner die Dateibeschreibung und versuch das nochmo erneit.",
        "savefile": "Datei speichre",
-       "uploadedimage": "lud „[[$1]]“ hoch",
-       "overwroteimage": "Hot en nei Version von \"[[$1]]\" hochgelood",
        "uploaddisabled": "Hochloode deaktiviert",
        "copyuploaddisabled": "Das Hochloode von URLs ist deaktiviert",
        "uploaddisabledtext": "Das Hochloode von Dateie ist deaktiviert.",
        "watchlist-details": "Du beobachtest {{PLURAL:$1|en Seit|$1 Seite}}, ohne dass Diskussionsseite getrennt gezählt werre.",
        "wlheader-enotif": "Der E-Mail-Benachrichtigungsdienst ist aktiviert.",
        "wlheader-showupdated": "Seite mit noch net gesiehne Ännrunge werre'''fett''' dorgestellt.",
-       "wlnote2": "Do folliche die Ändrunge von der letzte {{PLURAL:$1|Stund|<strong>$1</strong> Stunne}}. Stand: $2, $3.",
        "wlshowlast": "Zeich die Ännrunge von der letzte $1 Stunde, $2 Tooch orrer $3.",
        "watchlist-options": "Oonzeichoptione",
        "watching": "Beobachte …",
        "duplicate-defaultsort": "Achtung: Der Sortierungsschlüssel „$2“ üwerschreibt den voarher verwenndte Schlüssel „$1“.",
        "version": "Version",
        "version-extensions": "Installierte Erweitrunge",
+       "version-skins": "Benutzeroberfläche",
        "version-specialpages": "Erweitrungen mit Spezialseite",
        "version-parserhooks": "Parsererweitrunge",
        "version-variables": "Variable",
        "version-antispam": "Spamschutzerweitrunge",
-       "version-skins": "Benutzeroberfläche",
        "version-other": "Sonstiche Erweitrungen",
        "version-mediahandlers": "Medienutzungserweitrunge",
        "version-hooks": "Schnittstelle ''(Hooks)''",
index 3677994..dd5afbf 100644 (file)
@@ -11,7 +11,8 @@
                        "Tchoř",
                        "Tlustulimu",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Mikławš"
                ]
        },
        "tog-underline": "Wotkazy podšmórnić:",
        "talkpagelinktext": "diskusija",
        "specialpage": "Specialna strona",
        "personaltools": "Wosobinske nastroje",
-       "postcomment": "Nowy wotrězk",
        "articlepage": "Nastawk",
        "talk": "diskusija",
        "views": "Zwobraznjenja",
        "hidetoc": "schować",
        "collapsible-collapse": "Schować",
        "collapsible-expand": "Pokazać",
+       "confirmable-confirm": "Sy {{GENDER:$1|sej}} wěsty?",
+       "confirmable-yes": "Haj",
+       "confirmable-no": "Ně",
        "thisisdeleted": "$1 pokazać abo wobnowić?",
        "viewdeleted": "$1 pokazać?",
        "restorelink": "{{PLURAL:$1|1 wušmórnjenu wersiju|$1 wušmórnjenej wersiji|$1 wušmórnjene wersije|$1 wušmórnjenych wersijow}}",
        "perfcached": "Slědowace daty pochadźeja z pufrowaka a njejsu snano cyle aktualne. Maksimalnje {{PLURAL:$1|jedyn wuslědk|$1 wuslědkaj|$1 wuslědki|$1 wuslědkow}} w pufrowaku k dispoziciji {{PLURAL:$1|steji|stejitej|steja|steji}}.",
        "perfcachedts": "Slědowace daty su z pufrowaka a buchu $1 posledni raz zaktualizowane. Maksimalnje {{PLURAL:$4|jedyn wuslědk|$4 wuslědkaj|$4 wuslědki|$4 wuslědkow}} w pufrowaku k dispoziciji {{PLURAL:$4|steji|stejitej|steja|steji}}.",
        "querypage-no-updates": "Aktualizacije za tutu stronu su tuchwilu znjemóžnjene. Daty so hač na dalše njewobnowja.",
-       "viewsource": "žórÅ\82o wobhladaÄ\87",
+       "viewsource": "ŽórÅ\82owy tekst",
        "viewsource-title": "Žórłowy tekst za $1 sej wobhladać",
        "actionthrottled": "Akcije wobmjezowane",
        "actionthrottledtext": "Jako připrawa přećiwo spamej, je častosć wuwjedźenja tuteje akcije w krótkej dobje wobmjezowana a ty sy tutón limit překročił. Prošu spytaj za něšto mjeńšiny hišće raz.",
        "invalidtitle-knownnamespace": "Njepłaćiwy titul z mjenowym rumom \"$2\" a tekstom \"$3\"",
        "invalidtitle-unknownnamespace": "Njepłaćiwy titul z njeznatym mjenowym rumom $1 a tekstom \"$2\"",
        "exception-nologin": "Njejsy přizjewjeny",
-       "exception-nologin-text": "Prošu [[Special:Userlogin|přizjew so]], zo by přistup na tutu stronu abo akciju měł.",
+       "exception-nologin-text": "Prošu přizjew so, zo by přistup na tutu stronu abo akciju měł.",
        "exception-nologin-text-manual": "Zo by přistup na tutu stronu abo akciju měł, dyrbiš so $1.",
        "virus-badscanner": "Špatna konfiguracija: Njeznaty wirusowy skener: ''$1''",
        "virus-scanfailed": "Skenowanje njeporadźiło (kode $1)",
        "externaldberror": "Běše pak eksterny zmylk awtentifikacije datoweje banki, pak njesměš swoje eksterne konto aktualizować.",
        "login": "Přizjewić",
        "nav-login-createaccount": "Konto wutworić abo so přizjewić",
-       "loginprompt": "Za přizjewjenje do {{GRAMMAR:genitiw|{{SITENAME}}}} dyrbja placki zmóžnjene być.",
        "userlogin": "Załožće konto abo přizjewće so",
        "userloginnocreate": "Přizjewić",
        "logout": "wotzjewić",
        "userlogin-resetlink": "Přizjewjenske daty zabył?",
        "userlogin-resetpassword-link": "Sy swoje hesło zabył?",
        "userlogin-helplink2": "Pomoc při přizjewjenju",
-       "userlogin-loggedin": "Sy hižo jako {{GENDER:$1|$1 přizjewjeny|$1 přizjewjena}}. Wužij slědowacy formular, zo by so jako druhi wužiwar přizjewił.",
-       "userlogin-createanother": "Dalše konto załožić",
        "createacct-emailrequired": "E-mejlowa adresa",
        "createacct-emailoptional": "E-mejlowa adresa (opcionalny)",
        "createacct-email-ph": "Zapodaj swoju e-mejlowu adresu",
        "searchprofile-advanced-tooltip": "W swójskich mjenowych rumach pytać",
        "search-result-size": "$1 ({{PLURAL:$2|1 słowo|$2 słowje|$2 słowa|$2 słowow}})",
        "search-result-category-size": "{{PLURAL:$1|1 čłon|$1 čłonaj|$1 čłonojo|$1 čłonow}} ({{PLURAL:$2|1 podkategorija|$2 podkategoriji|$2 podkategorije|$2 podkategorijow}}, {{PLURAL:$3|1 dataja|$3 dataji|$3 dataje|$3 datajow}})",
-       "search-result-score": "Relewanca: $1 %",
        "search-redirect": "(Daleposrědkowanje $1)",
        "search-section": "(wotrězk $1)",
        "search-file-match": "(wotpowěduje datajowemu wobsahej)",
        "searchall": "wšě",
        "showingresults": "Deleka so hač {{PLURAL:$1|'''1''' wuslědk pokazuje|'''$1''' wuslědkaj pokazujetej|'''$1''' wuslědki pokazuja|'''$1''' wuslědkow pokazuje}}, započinajo z #'''$2'''.",
        "showingresultsinrange": "Deleka so do {{PLURAL:$1|<strong>1</strong> wuslědka|<strong>$1</strong> wuslědkow}} we wobłuku <strong>$2</strong> hač do <strong>$3</strong> pokazuje.",
-       "showingresultsheader": "{{PLURAL:$5|Wuslědk '''$1''' z '''$3'''|Wuslědki '''$1 - $2''' z '''$3'''}} za '''$4'''",
        "search-nonefound": "Njebuchu wuslědki namakane, kotrež naprašowanju wotpowěduja.",
        "powersearch-legend": "Rozšěrjene pytanje",
        "powersearch-ns": "W mjenowych rumach pytać:",
        "right-browsearchive": "Zhašane strony pytać",
        "right-undelete": "Strony wobnowić",
        "right-suppressrevision": "Wersije, kotrež su před administratorami schowane, přepruwować a wobnowić",
+       "right-viewsuppressed": "Před wužiwarjemi schowane wersije sej wobhladać",
        "right-suppressionlog": "Priwatne protokole wobhladać",
        "right-block": "Druhich wužiwarjow při wobdźěłowanju haćić",
        "right-blockemail": "Wužiwarja při słanju e-mejlow haćić",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (hlej tež [[Special:NewPages|lisćinu nowych stronow]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "rcnotefrom": "Deleka so změny wot <strong>$2</strong> pokazuja (hač k <strong>$1</strong>).",
-       "rclistfrom": "Nowe změny pokazać, započinajo z $3 $2",
+       "rclistfrom": "Jenož změny wot $3, $2 pokazać.",
        "rcshowhideminor": "snadne změny $1",
-       "rcshowhideminor-show": "Pokazać",
-       "rcshowhideminor-hide": "Schować",
+       "rcshowhideminor-show": "pokazać",
+       "rcshowhideminor-hide": "schować",
        "rcshowhidebots": "Boćiki $1",
-       "rcshowhidebots-show": "Pokazać",
-       "rcshowhidebots-hide": "Schować",
+       "rcshowhidebots-show": "pokazać",
+       "rcshowhidebots-hide": "schować",
        "rcshowhideliu": "Zregistrowani wužiwarjo $1",
-       "rcshowhideliu-show": "Pokazać",
-       "rcshowhideliu-hide": "Schować",
+       "rcshowhideliu-show": "pokazać",
+       "rcshowhideliu-hide": "schować",
        "rcshowhideanons": "Anonymni wužiwarjo $1",
-       "rcshowhideanons-show": "Pokazać",
-       "rcshowhideanons-hide": "Schować",
+       "rcshowhideanons-show": "pokazać",
+       "rcshowhideanons-hide": "schować",
        "rcshowhidepatr": "Dohladowane změny $1",
        "rcshowhidepatr-show": "Pokazać",
        "rcshowhidepatr-hide": "Schować",
        "rcshowhidemine": "moje změny $1",
-       "rcshowhidemine-show": "Pokazać",
-       "rcshowhidemine-hide": "Schować",
-       "rclinks": "Poslednje $1 změnow poslednich $2 dnjow pokazać<br />$3",
+       "rcshowhidemine-show": "pokazać",
+       "rcshowhidemine-hide": "schować",
+       "rclinks": "Pokazuj poslednje $1 změny poslednich $2 dnjow.<br />$3",
        "diff": "rozdźěl",
        "hist": "wersije",
        "hide": "schować",
        "uploadwarning": "Warnowanje",
        "uploadwarning-text": "Prošu změń slědowace datajowe wopisanje a spytaj hišće raz.",
        "savefile": "Dataju składować",
-       "uploadedimage": "je dataju „[[$1]]” nahrał",
-       "overwroteimage": "je nowu wersiju dataje „[[$1]]“ nahrał",
        "uploaddisabled": "Wodaj, nahraće je znjemóžnjene.",
        "copyuploaddisabled": "Nahraće přez URL znjemóžnjene.",
        "uploaddisabledtext": "Nahraće datajow je znjemóžnjene.",
        "license": "Licenca:",
        "license-header": "Licencowanje",
        "nolicense": "žadyn wuběr",
+       "licenses-edit": "Licencne nastajenja wobdźěłać",
        "license-nopreview": "(žadyn přehlad k dispoziciji)",
-       "upload_source_url": " (płaćiwy, zjawnje docpějomny URL)",
-       "upload_source_file": " (dataja na twojim ličaku)",
+       "upload_source_url": " (twoja wubrana dataja z płaćiweho, zjawnje přistupneho URL)",
+       "upload_source_file": " (twoja wubrana dataja z twojeho ličaka)",
+       "listfiles-delete": "zhašeć",
        "listfiles-summary": "Tuta specialna strona pokazuje wšě nahrate dataje.",
        "listfiles_search_for": "Za mjenom wobraza pytać:",
        "imgfile": "dataja",
        "randomincategory": "Připadna strona w kategoriji",
        "randomincategory-invalidcategory": "\"$1\" płaćiwe kategorijowe mjeno njeje.",
        "randomincategory-nopages": "W kategoriji [[:Category:$1|$1]] žane strony njejsu.",
-       "randomincategory-selectcategory": "Připadna strona z kategorija: $1 $2",
-       "randomincategory-selectcategory-submit": "Wotesłać",
+       "randomincategory-category": "Kategorija:",
+       "randomincategory-legend": "Připadna strona w kategoriji",
        "randomredirect": "Připadne daleposrědkowanje",
        "randomredirect-nopages": "Žane daleposrědkowanja w mjenowym rumje \"$1\".",
        "statistics": "Statistika",
        "wantedfiles": "Požadane dataje",
        "wantedfiletext-cat": "Slědowace dataje so wužiwaja, ale njeeksistuju. Dataje z cuzych repozitorijow hodźa so nalistować, byrnjež eksistowali. Tajke wopačne pozitiwy su <del>přešmórnjene</del>. Nimo toho so strony w [[:$1]] nalistuja, kotrež dataje zasadźuja, kotrež njeeksistuja.",
        "wantedfiletext-nocat": "Slědowace dataje so wužiwaja, ale njeeksistuja. Dataje z cuzych repozitorijow hodźa so nalistować, byrnjež eksistowali. Tajke wopačne pozitiwy su <del>přešmórnjene</del>.",
+       "wantedfiletext-nocat-noforeign": "Slědowace dataje so wužiwaja, ale njeeksistuja.",
        "wantedtemplates": "Falowace předłohi",
        "mostlinked": "Z najwjace stronami zwjazane strony",
        "mostlinkedcategories": "Z najwjace stronami zwjazane kategorije",
        "watchlist-details": "{{PLURAL:$1|$1 wobkedźbowana strona|$1 wobkedźbowanej stronje|$1 wobkedźbowane strony|$1 wobkedźbowanych stronow}}, bjeztoho zo so diskusijne strony dźělene liča.",
        "wlheader-enotif": "E-mejlowa zdźělenska słužba je zmóžnjena.",
        "wlheader-showupdated": "Strony, kotrež su so po twojim poslednim wopyće změnili, so '''tučne''' pokazuja.",
-       "wlnote2": "Slěduja změny {{PLURAL:$1|zańdźeneje hodźiny|zańdźeneju <strong>$1</strong> hodźinow|zańdźenych <strong>$1</strong> hodźin}} Staw: $2, $3.",
+       "wlnote": "Deleka {{PLURAL:$1|je poslednja změna|stej poslednjej '''$1''' změnje|su poslednje '''$1''' změny|je poslednich '''$1''' změnow}} za {{PLURAL:$2|poslednju hodźinu|poslednje '''$2''' hodźinje|poslednje '''$2''' hodźiny|poslednje '''$2''' hodźin}}, staw : $3, $4.",
        "wlshowlast": "Poslednje $1 hodź. - $2 dnjow - $3 pokazać",
        "watchlist-options": "Opcije wobkedźbowankow",
        "watching": "Wobkedźbuju…",
        "autoblockid": "#$1 awtomatisce blokować",
        "block": "Wužiwarja blokować",
        "unblock": "Blokowanje wužiwarja zběhnyć",
-       "blockip": "Wužiwarja zablokować",
+       "blockip": "{{GENDER:$1|Wužiwarja|Wužiwarku}} blokować",
        "blockip-legend": "Wužiwarja blokować",
        "blockiptext": "Wužij slědowacy formular deleka, zo by pisanski přistup za podatu IP-adresu abo wužiwarske mjeno blokował. To měło so jenož stać, zo by wandalizmej zadźěwało a woptpowědujo [[{{MediaWiki:Policy-url}}|zasadam]]. Zapodaj deleka přičinu (na př. citujo wosebite strony, kotrež běchu z woporom wandalizma).",
        "ipaddressorusername": "IP-adresa abo wužiwarske mjeno",
        "ipb-unblock-addr": "zablokowanje wužiwarja „$1“ zběhnyć",
        "ipb-unblock": "zablokowanje wužiwarja abo IP-adresy zběhnyć",
        "ipb-blocklist": "tuchwilne blokowanja zwobraznić",
-       "ipb-blocklist-contribs": "Přinoški za $1",
+       "ipb-blocklist-contribs": "Přinoški za {{GENDER:$1|$1}}",
        "unblockip": "Zablokowanje zběhnyć",
        "unblockiptext": "Wužij formular deleka, zo by blokowanje IP-adresy abo wužiwarskeho mjena zběhnył.",
        "ipusubmit": "Tute blokěrowanje skónčić",
        "import": "Strony importować",
        "importinterwiki": "Import z druheho wikija",
        "import-interwiki-text": "Wuběr wiki a stronu za importowanje. Daty wersijow a mjena awtorow so zachowaja. Wšě akcije za transwiki-importy so w [[Special:Log/import|protokolu importow]] protokoluja.",
-       "import-interwiki-source": "Žórłowy wiki/Žórłowa strona:",
        "import-interwiki-history": "Wšě wersije ze stawiznow tuteje strony kopěrować",
        "import-interwiki-templates": "Wšě předłohi zapřijeć",
        "import-interwiki-submit": "Importować",
        "autosumm-replace": "Strona bu z hinašim tekstom přepisana: '$1'",
        "autoredircomment": "posrědkuju k stronje „[[$1]]”",
        "autosumm-new": "Wutwori stronu z '$1'",
+       "autosumm-newblank": "Prózdna strona wutworjena",
        "size-kilobytes": "$1 kB",
        "lag-warn-normal": "Změny {{PLURAL:$1|zašłeje $1 sekundy|zašłeju $1 sekundow|zašłych $1 sekundow|zašłych $1 sekundow}} so w tutej lisćinje hišće njezwobraznjeja.",
        "lag-warn-high": "Wućeženja datoweje banki dla so změny {{PLURAL:$1|zašłeje $1 sekundy|zašłeje $1 sekundow|zašłych $1 sekundow|zašłych $1 sekundow}} w tutej lisćinje hišće njepokazuja.",
        "duplicate-defaultsort": "Warnowanje: Standardny sortěrowonski kluč (DEFAULTSORTKEY) \"$2\" přepisa prjedawšu sortěrowanski kluč \"$1\".",
        "version": "Wersija",
        "version-extensions": "Instalowane rozšěrjenja",
-       "version-skins": "Šaty",
+       "version-skins": "Instalowane drasty",
        "version-specialpages": "Specialne strony",
        "version-parserhooks": "Parserowe hoki",
        "version-variables": "Wariable",
        "version-hook-name": "Mjeno hoki",
        "version-hook-subscribedby": "Abonowany wot",
        "version-version": "(Wersija $1)",
+       "version-no-ext-name": "[žane mjeno]",
        "version-license": "Licenca MediaWiki",
        "version-ext-license": "Licenca",
        "version-ext-colheader-name": "Rozšěrjenje",
+       "version-skin-colheader-name": "Drasta",
        "version-ext-colheader-version": "Wersija",
        "version-ext-colheader-license": "Licenca",
        "version-ext-colheader-description": "Wopisanje",
        "logentry-rights-rights": "$1 je skupinske čłonstwo za $3 z $4 do $5 {{GENDER:$2|změnił|změniła}}",
        "logentry-rights-rights-legacy": "$1 je skupinske čłonstwo za $3 {{GENDER:$2|změnił|změniła}}",
        "logentry-rights-autopromote": "$1 je so awtomatisce wot $4 do $5 {{GENDER:$2|přirjadował|přirjadowała}}",
+       "logentry-upload-upload": "$1 je $3 {{GENDER:$2|nahrał|nahrała}}",
+       "logentry-upload-overwrite": "$1 je nowu wersiju $3 {{GENDER:$2|nahrał|nahrała}}",
+       "logentry-upload-revert": "$1 je $3 {{GENDER:$2|nahrał|nahrała}}",
        "rightsnone": "(ničo)",
        "feedback-bugornote": "Jeli sy zwólniwy, techniski problem nadrobnje wopisać, [$1 zdźěl prošu zmylk].\nHewak móžeš slědowacy jednory formular wužiwać. Twój komentar přida so stronje \"[$3 $2]\", z twojim wužiwarskim mjenom a z wobhladowakom, kotryž wužiwaš.",
        "feedback-subject": "Tema:",
        "expand_templates_remove_nowiki": "Taflički <nowiki> we wuslědku potłóčić",
        "expand_templates_generate_xml": "Analyzowy štom XML pokazać",
        "expand_templates_generate_rawhtml": "Hruby HTML pokazać",
-       "expand_templates_preview": "Přehlad"
+       "expand_templates_preview": "Přehlad",
+       "pagelanguage": "Selektor rěče strony",
+       "pagelang-name": "Strona",
+       "pagelang-language": "Rěč",
+       "pagelang-use-default": "Standardnu rěč wužiwać",
+       "pagelang-select-lang": "Rěč wubrać",
+       "right-pagelang": "Rěč strony změnić",
+       "action-pagelang": "rěč strony změnić",
+       "log-name-pagelang": "Protokol změnow rěče",
+       "log-description-pagelang": "To je protokol změnow na rěčach stronow.",
+       "logentry-pagelang-pagelang": "$1 je rěč strony za $3 wot $4 do $5 {{GENDER:$2|změnił|změniła}}.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (zmóžnjeny)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''znjemóžnjeny''')"
 }
index 6759eb6..f006760 100644 (file)
        "talkpagelinktext": "Diskite",
        "specialpage": "Paj Espesyal",
        "personaltools": "Zouti pèsonèl yo",
-       "postcomment": "Nouvo seksyon",
        "articlepage": "Wè paj atik",
        "talk": "Diskisyon",
        "views": "Afichay yo",
        "externaldberror": "Li sanble ke yon erè pwodui ak bazdone a pou idantifikasyon ki pa nan sistèm an, oubyen ou pa otorize pou mete a jou kont ou genyen nan lòt sistèm yo.",
        "login": "Konekte ou",
        "nav-login-createaccount": "Kreye yon kont oubyen konekte ou",
-       "loginprompt": "Ou dwe aksepte (aktive) koukiz (cookies) yo pou ou kapab konekte nan {{SITENAME}}.",
        "userlogin": "Kreye yon kont oubyen konekte ou",
        "userloginnocreate": "Konekte ou",
        "logout": "Dekonekte ou",
        "upload": "Chaje yon fichye",
        "uploadbtn": "Chaje yon fichye",
        "uploadlogpage": "Jounal chajman pou fichye yo",
-       "uploadedimage": "chaje « [[$1]] »",
        "listfiles": "Lis fichye yo",
        "file-anchor-link": "Fichye",
        "filehist": "Istorik fichye a",
index 6f410c1..0e05dcf 100644 (file)
@@ -35,7 +35,8 @@
                        "Xbspiro",
                        "아라",
                        "Csega",
-                       "ViDam"
+                       "ViDam",
+                       "Adam78"
                ]
        },
        "tog-underline": "Hivatkozások aláhúzása:",
        "permalink": "Hivatkozás erre a változatra",
        "print": "Nyomtatás",
        "view": "Olvasás",
+       "view-foreign": "Megtekintés ezen: $1",
        "edit": "Szerkesztés",
        "edit-local": "Helyi leírás szerkesztése",
        "create": "Létrehozás",
        "talkpagelinktext": "vitalap",
        "specialpage": "Speciális lap",
        "personaltools": "Személyes eszközök",
-       "postcomment": "Új szakasz",
        "articlepage": "Szócikk megtekintése",
        "talk": "Vitalap",
        "views": "Nézetek",
        "jumptonavigation": "navigáció",
        "jumptosearch": "keresés",
        "view-pool-error": "A szerverek jelenleg túl vannak terhelve, mert túl sok felhasználó próbálta megtekinteni ezt az oldalt.\nKérjük, várj egy kicsit, mielőtt újra próbálkoznál a lap megtekintésével!\n\n$1",
+       "generic-pool-error": "Sajnálom, a szerverek jelenleg túl vannak terhelve.\nTúl sok felhasználó próbálja ezt az oldalt megtekinteni.\nKérjük, várj egy kicsit, mielőtt újra próbálkoznál az oldal megtekintésével!",
        "pool-timeout": "Letelt a zárolás feloldására szánt várakozási idő",
        "pool-queuefull": "A pool sor megtelt",
        "pool-errorunknown": "Ismeretlen hiba",
        "externaldberror": "Hiba történt a külső adatbázis hitelesítése közben, vagy nem vagy jogosult a külső fiókod frissítésére.",
        "login": "Bejelentkezés",
        "nav-login-createaccount": "Bejelentkezés / fiók létrehozása",
-       "loginprompt": "Engedélyezned kell a sütiket (''cookie''), hogy bejelentkezhess a(z) {{SITENAME}} wikibe.",
        "userlogin": "Bejelentkezés / fiók létrehozása",
        "userloginnocreate": "Bejelentkezés",
        "logout": "Kijelentkezés",
        "userlogin-resetlink": "Elfelejtetted a bejelentkezési adataidat?",
        "userlogin-resetpassword-link": "Elfelejtetted a jelszavad?",
        "userlogin-helplink2": "Segítség a bejelentkezéshez",
-       "userlogin-loggedin": "Már be vagy jelentkezve mint {{GENDER:$1|$1}}. Ha más néven akarsz belépni, alább megteheted.",
-       "userlogin-createanother": "Felhasználói fiók létrehozása",
        "createacct-emailrequired": "E-mail cím",
        "createacct-emailoptional": "E-mail cím (opcionális)",
        "createacct-email-ph": "Add meg e-mail címed",
        "preview": "Előnézet",
        "showpreview": "Előnézet megtekintése",
        "showdiff": "Változtatások megtekintése",
-       "anoneditwarning": "'''Figyelem:''' Nem vagy bejelentkezve, ha szerkesztesz, az IP-címed látható lesz a laptörténetben.",
+       "blankarticle": "<strong>Figyelem:</strong> A létrehozandó szócikk üres.\nHa ismét a \"{{int:savearticle}}\" gombra kattintasz, a szócikket tartalom nélkül fogod létrehozni.",
+       "anoneditwarning": "'''Figyelem:''' Nem vagy bejelentkezve. Ha szerkesztesz, az IP-címed látható lesz a laptörténetben.",
        "anonpreviewwarning": "''Nem vagy bejelentkezve. A mentéskor az IP-címed rögzítve lesz a laptörténetben.''",
        "missingsummary": "'''Emlékeztető:''' Nem adtál meg szerkesztési összefoglalót. Ha összefoglaló nélkül akarod elküldeni a szöveget, kattints újra a mentésre.",
        "missingcommenttext": "Kérjük, írj összefoglalót a szerkesztésedhez.",
        "parser-template-recursion-depth-warning": "A sablon rekurzív beillesztésének mélysége átlépte a határérékét ($1)",
        "language-converter-depth-warning": "A nyelvátalakító rekurzióinak száma túllépve ($1)",
        "node-count-exceeded-category": "Lapok, ahogy a csomópont szám túl nagy",
+       "node-count-exceeded-category-desc": "Azon oldalaknak a kategóriája, ahol a csomópont szám túl nagy.",
        "node-count-exceeded-warning": "Az oldal meghaladta a csomópont számot",
        "expansion-depth-exceeded-category": "Lapok, melyeken a sablonok kibontása meghaladja a megengedett szintet",
        "expansion-depth-exceeded-warning": "A lap meghaladta az engedélyezett kiterjesztési mélységet",
        "undo-norev": "A szerkesztés nem állítható vissza, mert nem létezik vagy törölve lett.",
        "undo-nochange": "A szerkesztés már vissza lett állítva.",
        "undo-summary": "Visszavontam [[Special:Contributions/$2|$2]] ([[User talk:$2|vita]] | [[Special:Contributions/$2|{{MediaWiki:Contribslink}}]]) szerkesztését (oldid: $1)",
+       "undo-summary-username-hidden": "A rejtett felhasználó által végzett $1 változat visszavonása",
        "cantcreateaccounttitle": "Felhasználói fiók létrehozása sikertelen",
        "cantcreateaccount-text": "Erről az IP-címről ('''$1''') nem lehet regisztrálni, mert [[User:$3|$3]] blokkolta az alábbi indokkal:\n\n:''$2''",
+       "cantcreateaccount-range-text": "A regisztrációt a(z) '''$1''' IP-címtartományban, amelybe a te IP-címed ('''$4''') is tartozik, [[User:$3|$3]] blokkolta.",
        "viewpagelogs": "A lap a rendszernaplókban",
        "nohistory": "A lap nem rendelkezik laptörténettel.",
        "currentrev": "Aktuális változat",
        "revdelete-no-file": "A megadott fájl nem létezik.",
        "revdelete-show-file-confirm": "Biztosan meg szeretnéd nézni a(z) „<nowiki>$1</nowiki>” $2, $3-i törölt változatát?",
        "revdelete-show-file-submit": "Igen",
+       "revdelete-selected-text": "[[:$2]] {{PLURAL:$1|kiválasztott változata|kiválasztott változatai}}",
        "logdelete-selected": "{{PLURAL:$1|Kiválasztott naplóesemény|Kiválasztott naplóesemények}}:",
        "revdelete-confirm": "Kérlek erősítsd meg, hogy valóban ezt szeretnéd tenni; megértetted a következményeket, és amit teszel, az összhangban van [[{{MediaWiki:Policy-url}}|az irányelvekkel]].",
        "revdelete-suppress-text": "Az elrejtés '''csak''' a következő esetekben használható:\n* Illetlen személyes információk\n*: ''otthoni cím, telefonszámok, társadalombiztosítási számok stb.''",
        "searchprofile-advanced-tooltip": "Keresés adott névterekben",
        "search-result-size": "$1 ({{PLURAL:$2|egy|$2}} szó)",
        "search-result-category-size": "$1 oldal, $2 alkategória, $3 fájl",
-       "search-result-score": "Relevancia: $1%",
        "search-redirect": "(átirányítva innen: $1)",
        "search-section": "($1 szakasz)",
        "search-suggest": "Keresési javaslat: $1",
        "searchrelated": "kapcsolódó",
        "searchall": "mind",
        "showingresults": "Lent '''{{PLURAL:$1|egy|$1}}''' találat látható, az eleje '''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|'''$1'''|'''$1 - $2'''}}. találat a(z) '''$4''' kifejezésre (összesen: '''$3''')",
        "search-nonefound": "Nincs egyezés a megadott szöveggel.",
        "powersearch-legend": "Részletes keresés",
        "powersearch-ns": "Névterek:",
        "preferences": "Beállítások",
        "mypreferences": "Beállítások",
        "prefs-edits": "Szerkesztéseid száma:",
+       "prefsnologintext2": "Kérjük, jelentkezz be a beállítások módosításához.",
        "prefs-skin": "Felület",
        "skin-preview": "előnézet",
        "datedefault": "Nincs beállítás",
        "right-move": "lapok átnevezése",
        "right-move-subpages": "lapok átnevezése az allapjukkal együtt",
        "right-move-rootuserpages": "szerkesztői lapok mozgatása",
+       "right-move-categorypages": "kategóriák átnevezése",
        "right-movefile": "fájlok átnevezése",
        "right-suppressredirect": "nem készít átirányítást a régi néven lapok átnevezésekor",
        "right-upload": "fájlok feltöltése",
        "right-reupload-shared": "felülírhatja a közös megosztóhelyen lévő fájlokat helyben",
        "right-upload_by_url": "fájl feltöltése URL-cím alapján",
        "right-purge": "oldal gyorsítótárának ürítése megerősítés nélkül",
-       "right-autoconfirmed": "félig védett lapok szerkesztése",
+       "right-autoconfirmed": "Nem érinti az IP-alapú szerkesztéskorlátozás",
        "right-bot": "automatikus folyamatként való kezelés",
        "right-nominornewtalk": "felhasználói lapok nem apró szerkesztésével megjelenik az új üzenet szöveg",
        "right-apihighlimits": "nagyobb mennyiségű lekérdezés az API-n keresztül",
        "right-deletedtext": "törölt változatok szövegének és a változatok közötti eltérés megtekintése",
        "right-browsearchive": "keresés a törölt lapok között",
        "right-undelete": "lap helyreállítása",
-       "right-suppressrevision": "az adminisztrátorok elől elrejtett változatok megtekintése és helyreállítása",
+       "right-suppressrevision": "Bármely felhasználó által végzett változatok megtekintése, elrejtése és felfedése",
        "right-suppressionlog": "privát naplók megtekintése",
        "right-block": "szerkesztők blokkolása",
        "right-blockemail": "szerkesztő e-mail küldési lehetőségének blokkolása",
        "right-proxyunbannable": "proxyk automatikus blokkjainak megkerülése",
        "right-unblockself": "saját felhasználói fiók blokkjának feloldása",
        "right-protect": "védelmi szintek megváltoztatása és kaszkádolt védelemmel rendelkező lapok szerkesztése",
-       "right-editprotected": "\"{{int:protect-level-sysop}}\" védelmi szintű lapok szerkesztése",
+       "right-editprotected": "„{{int:protect-level-sysop}}” védelmi szintű lapok szerkesztése",
+       "right-editsemiprotected": "„{{int:protect-level-autoconfirmed}}” védelmi szintű lapok szerkesztése",
        "right-editinterface": "felhasználói felület szerkesztése",
        "right-editusercssjs": "más felhasználók CSS és JS fájljainak szerkesztése",
        "right-editusercss": "más felhasználók CSS fájljainak szerkesztése",
        "right-edituserjs": "más felhasználók JS fájljainak szerkesztése",
        "right-editmyusercss": "A saját szerkesztői CSS-fájlok szerkesztése",
        "right-editmyuserjs": "Saját szerkesztői JavaScript-fájlok szerkesztése",
-       "right-viewmywatchlist": "Saját figyelőlista megtekintése",
-       "right-editmyoptions": "Saját beállítások szerkesztése",
+       "right-viewmywatchlist": "saját figyelőlista megtekintése",
+       "right-editmywatchlist": "saját figyelőlista szerkesztése; bizonyos műveletek képesek lapok figyelőlistához adására ezen jog nélkül is",
+       "right-viewmyprivateinfo": "saját személyes adatok megtekintése (pl. e-mail cím, valódi név)",
+       "right-editmyprivateinfo": "saját személyes adatok szerkesztése (pl. e-mail cím, valódi név)",
+       "right-editmyoptions": "saját beállítások szerkesztése",
        "right-rollback": "a lap utolsó szerkesztésének gyors visszaállítása",
        "right-markbotedits": "visszaállított szerkesztések botként való jelölése",
        "right-noratelimit": "sebességkorlát figyelmen kívül hagyása",
        "recentchanges-label-plusminus": "Az oldal mérete ennyi bájttal módosult",
        "recentchanges-legend-heading": "Jelmagyarázat:",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (lásd még: [[Special:NewPages|új lapok listája]])",
-       "rcnotefrom": "Alább a <b>$2</b> óta történt változtatások láthatóak (legfeljebb <b>$1</b> db).",
+       "rcnotefrom": "Alább a <strong>$3 $4</strong> óta történt változtatások láthatóak (legfeljebb <b>$1</b> db).",
        "rclistfrom": "$3 $2 után történt változtatások megtekintése",
        "rcshowhideminor": "apró szerkesztések $1",
        "rcshowhideminor-show": "megjelenítése",
        "largefileserver": "A fájl mérete meghaladja a kiszolgálón beállított maximális értéket.",
        "emptyfile": "Az általad feltöltött fájl üresnek tűnik.\nEz valószínűleg azért van, mert hibásan adtad meg a feltöltendő fájl nevét.\nEllenőrizd, hogy valóban fel akarod-e tölteni ezt a fájlt.",
        "windows-nonascii-filename": "A wiki nem támogatja a speciális karaktereket tartalmazó fájlneveket.",
-       "fileexists": "<strong>[[:$1]]</strong> névvel már létezik egy állomány.\nEllenőrizd, hogy biztosan felül akarod-e írni! [[$1|thumb]]",
+       "fileexists": "<strong>[[:$1]]</strong> névvel már létezik egy állomány. Ellenőrizd, hogy biztosan felül akarod-e írni!\n[[$1|thumb]]",
        "filepageexists": "Ehhez a fájlnévhez már létezik leírás a <strong>[[:$1]]</strong> lapon, de jelenleg nincs feltöltve ilyen nevű fájl.\nA leírás, amit ebbe az űrlapba írsz, nem fogja felülírni a már létezőt.\nHa meg szeretnéd változtatni a leírást, meg kell nyitnod szerkesztésre a lapjot.\n[[$1|thumb]]",
-       "fileexists-extension": "Már van egy hasonló nevű feltöltött fájl: [[$2|thumb]]\n* A feltöltendő fájl neve: <strong>[[:$1]]</strong>\n* A már létező fájl neve: <strong>[[:$2]]</strong>\nKérjük, hogy válassz másik nevet.",
+       "fileexists-extension": "Már van egy hasonló nevű feltöltött fájl: [[$2|thumb]]\n* A feltöltendő fájl neve: <strong>[[:$1]]</strong>\n* A már létező fájl neve: <strong>[[:$2]]</strong>\nSzeretnél egy jobban megkülönböztethető nevet használni?",
        "fileexists-thumbnail-yes": "A fájl egy kisméretű képnek ''(bélyegképnek)'' tűnik. [[$1|thumb]]\nKérjük, hogy ellenőrizd a(z) <strong>[[:$1]]</strong> fájlt.\nHa az ellenőrzött fájl ugyanakkora, mint az eredeti méretű kép, akkor nincs szükség bélyegkép feltöltésére.",
        "file-thumbnail-no": "A fájlnév a(z) <strong>$1</strong> karakterlánccal kezdődik.\nÚgy tűnik, hogy ez egy kisméretű kép ''(bélyegkép)''.\nHa rendelkezel a teljesméretű képpel, akkor töltsd fel azt, egyébként kérjük, hogy változtasd meg a fájlnevet.",
        "fileexists-forbidden": "Már létezik egy ugyanilyen nevű fájl, és nem lehet felülírni.\nHa még mindig fel szeretnéd tölteni a fájlt, menj vissza, és adj meg egy új nevet. [[File:$1|thumb|center|$1]]",
        "uploadwarning": "Feltöltési figyelmeztetés",
        "uploadwarning-text": "Kérlek módosítsd a fájl leírását alább, majd próbáld újra.",
        "savefile": "Fájl mentése",
-       "uploadedimage": "„[[$1]]” felküldve",
-       "overwroteimage": "feltöltötte a(z) „[[$1]]” fájl új változatát",
        "uploaddisabled": "Feltöltések kikapcsolva",
        "copyuploaddisabled": "A feltöltés URL alapján le van tiltva.",
        "uploaddisabledtext": "A fájlfeltöltés nem engedélyezett.",
        "license-header": "Licenc",
        "nolicense": "Válassz licencet!",
        "license-nopreview": "(Előnézet nem elérhető)",
-       "upload_source_url": " (egy érvényes, nyilvánosan elérhető URL)",
-       "upload_source_file": " (egy fájl a számítógépeden)",
+       "upload_source_url": "(a kiválasztott fájlod egy nyilvánosan elérhető URL-ről)",
+       "upload_source_file": "(a számítógépeden kiválasztott fájl)",
+       "listfiles-delete": "törlés",
        "listfiles-summary": "Ezen a speciális lapon látható az összes feltöltött fájl.",
        "listfiles_search_for": "Keresés fájl nevére:",
        "imgfile": "fájl",
        "statistics-mostpopular": "Legtöbbször megtekintett lapok",
        "doubleredirects": "Dupla átirányítások",
        "doubleredirectstext": "Ez a lap azokat a lapokat listázza, melyek átirányító lapokra irányítanak át.\nMinden sor tartalmaz egy hivatkozást az első, valamint a második átirányításra, valamint a második átirányítás céljára, ami általában a valódi céllap, erre kellene az első átirányításnak mutatnia.\nAz <del>áthúzott</del> sorok a lista elkészülése óta javítva lettek.",
-       "double-redirect-fixed-move": "[[$1]] átnevezve, a továbbiakban átirányításként működik a(z) [[$2]] lapra",
+       "double-redirect-fixed-move": "[[$1]] áthelyezve.\nAutomatikusan frissült, és mostantól a(z) [[$2]] lapra irányít át.",
        "double-redirect-fixed-maintenance": "[[$1]] dupla átirányítás automatikus javítása karbantartás során a következőre: [[$2]]",
        "double-redirect-fixer": "Átirányításjavító",
        "brokenredirects": "Nem létező lapra mutató átirányítások",
        "protectedpages-indef": "Csak a meghatározatlan idejű védelmek",
        "protectedpages-cascade": "Csak a kaszkádvédelmek",
        "protectedpagesempty": "Jelenleg nincsenek ilyen paraméterekkel védett lapok.",
+       "protectedpages-timestamp": "Időbélyeg",
+       "protectedpages-expiry": "Lejárat",
+       "protectedpages-reason": "Indoklás",
+       "protectedpages-unknown-timestamp": "Ismeretlen",
+       "protectedpages-unknown-performer": "Ismeretlen felhasználó",
        "protectedtitles": "Létrehozás ellen védett lapok",
        "protectedtitlesempty": "Jelenleg nincsenek ilyen típusú védett lapok.",
        "listusers": "Szerkesztők",
        "listgrouprights-removegroup-self": "eltávolíthatja a következő {{PLURAL:$2|csoportból|csoportokból}} a saját fiókját: $1",
        "listgrouprights-addgroup-self-all": "az összes csoportot hozzáadhatja a saját fiókjához",
        "listgrouprights-removegroup-self-all": "az összes csoporból eltávolíthatja a saját fiókját",
+       "listgrouprights-namespaceprotection-namespace": "Névtér",
+       "trackingcategories-nodesc": "Nem található leírás.",
+       "trackingcategories-disabled": "A kategória le van tiltva",
        "mailnologin": "Nincs feladó",
        "mailnologintext": "Ahhoz hogy másoknak e-mailt küldhess, [[Special:UserLogin|be kell jelentkezned]] és meg kell adnod egy érvényes e-mail címet a [[Special:Preferences|beállításaidban]].",
        "emailuser": "E-mail küldése ezen szerkesztőnek",
        "watchlist-details": "A vitalapokon kívül {{PLURAL:$1|egy|$1}} lap van a figyelőlistádon.",
        "wlheader-enotif": "Az e-mailen keresztül történő értesítés engedélyezve.",
        "wlheader-showupdated": "Azok a lapok, amelyek megváltoztak, mióta utoljára megnézted őket, '''vastagítva''' láthatók.",
-       "wlnote2": "Alább az utolsó {{PLURAL:$1| <strong> $1 </strong> óra}} változásai láthatók. A lista frissítésének ideje  $2 $3",
+       "wlnote": "Alább {{PLURAL:$1|az utolsó változás|az utolsó <strong>$1</strong> változás}} látható az elmúlt {{PLURAL:$2|órában|<strong>$2</strong> órában}}, $3 $4-kor.",
        "wlshowlast": "Az elmúlt $1 órában | $2 napon | $3 történt változtatások legyenek láthatóak",
        "watchlist-options": "A figyelőlista beállításai",
        "watching": "Figyelés...",
        "enotif_reset": "Az összes lap megjelölése felkeresettként",
        "enotif_impersonal_salutation": "{{SITENAME}} felhasználó",
        "enotif_subject_deleted": "$2 törölte a $1 {{SITENAME}} oldalt.",
+       "enotif_subject_created": "$2 létrehozta a(z) $1 {{SITENAME}} oldalt",
        "enotif_subject_moved": "$2 átmozgatta a $1 {{SITENAME}} oldalt.",
        "enotif_subject_restored": "$2 visszaállította a $1 {{SITENAME}} oldalt.",
-       "enotif_subject_changed": "$2 megváltoztatta a $1 {{SITENAME}} oldalt.",
+       "enotif_subject_changed": "$2 megváltoztatta a(z) $1 {{SITENAME}} oldalt",
        "enotif_body_intro_deleted": "$2 törölte a $1 {{SITENAME}} oldalt $PAGEEDITDATE-kor, lásd $3.",
        "enotif_body_intro_created": "$2 létrehozta a $1 {{SITENAME}} oldalt $PAGEEDITDATE-kor, lásd az aktuális verziót itt: $3.",
        "enotif_body_intro_moved": "$2 átmozgatta a $1 {{SITENAME}} oldalt $PAGEEDITDATE-kor, lásd az aktuális verziót itt: $3.",
        "protect-locked-blocked": "Nem változtathatod meg a védelmi szinteket, amíg blokkolnak. Itt vannak a(z)\n'''$1''' lap jelenlegi beállításai:",
        "protect-locked-dblock": "A védelmi szinteket egy aktív adatbázis zárolás miatt nem változtathatod meg.\nItt vannak a(z) '''$1''' lap jelenlegi beállításai:",
        "protect-locked-access": "A fiókod számára nem engedélyezett a védelmi szintek megváltoztatása.\nItt vannak a(z) '''$1''' lap jelenlegi beállításai:",
-       "protect-cascadeon": "A lap le van védve, mert {{PLURAL:$1|tartalmazza az alábbi lap, amelyen|tartalmazzák az alábbi lapok, amelyeken}}\nbe van kapcsolva a kaszkád védelem.\nMegváltoztathatod ezen lap védelmi szintjét, de az nem lesz hatással a kaszkád védelemre.",
+       "protect-cascadeon": "A lap jelenleg le van védve, mert {{PLURAL:$1|tartalmazza az alábbi lap, amelyen|tartalmazzák az alábbi lapok, amelyeken}} be van kapcsolva a kaszkád védelem.\nEzen lap védelmi szintjének megváltoztatása nem lesz hatással a kaszkád védelemre.",
        "protect-default": "Minden szerkesztő számára engedélyezett",
        "protect-fallback": "\"$1\" engedély szükséges hozzá",
-       "protect-level-autoconfirmed": "Csak automatikusan ellenőrzött szerkesztőknek engedélyezett (nem vagy frissen regisztráltaknak nem)",
-       "protect-level-sysop": "Csak adminisztrátoroknak engedélyezett",
+       "protect-level-autoconfirmed": "Csak automatikusan megerősített szerkesztőknek engedélyezett (nem vagy frissen regisztráltaknak nem)",
+       "protect-level-sysop": "csak adminisztrátoroknak engedélyezett",
        "protect-summary-cascade": "kaszkád védelem",
        "protect-expiring": "lejár: $1 (UTC)",
        "protect-expiring-local": "lejárat: $1",
        "sp-contributions-search": "Közreműködések szűrése",
        "sp-contributions-username": "IP-cím vagy felhasználónév:",
        "sp-contributions-toponly": "Csak a jelenleg utolsónak számító változtatásokat mutassa",
+       "sp-contributions-newonly": "Csak az új oldalt létrehozó szerkesztéseket mutassa",
        "sp-contributions-submit": "Keresés",
        "whatlinkshere": "Mi hivatkozik erre",
        "whatlinkshere-title": "A(z) „$1” lapra hivatkozó lapok",
        "allmessages-prefix": "Előtag szerint:",
        "allmessages-language": "Nyelv:",
        "allmessages-filter-submit": "Szűrés",
+       "allmessages-filter-translate": "Fordítás",
        "thumbnail-more": "A kép nagyítása",
        "filemissing": "A fájl nincs meg",
        "thumbnail_error": "Hiba a bélyegkép létrehozásakor: $1",
        "import": "Lapok importálása",
        "importinterwiki": "Transwiki importálása",
        "import-interwiki-text": "Válaszd ki az importálandó wikit és lapcímet.\nA változatok dátumai és a szerkesztők nevei megőrzésre kerülnek.\nValamennyi transwiki importálási művelet az [[Special:Log/import|importálási naplóban]] kerül naplózásra.",
-       "import-interwiki-source": "Forrás wiki/lap:",
        "import-interwiki-history": "A lap összes előzményváltozatainak másolása",
        "import-interwiki-templates": "Az összes sablon hozzáadása",
        "import-interwiki-submit": "Importálás",
        "import-error-create": "„$1” lap nem került importálásra, mert nem hozhatod létre azt.",
        "import-error-interwiki": "„$1” lap nem került importálásra, mert a név külső hivatkozásokra van fenntartva (interwiki).",
        "import-error-special": "„$1” lap nem került importálásra, mert olyan speciális névtérbe tartozik, amelyen nem engedélyezettek a lapok.",
-       "import-error-invalid": "„$1” lap nem került importálásra, mert a neve nem érvényes.",
+       "import-error-invalid": "„$1” lap nem került importálásra, mert a név, amelyen importálásra kerülne nem érvényes ezen a wikin.",
        "import-options-wrong": "Rossz {{PLURAL:$2|opció|opciók}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "A megadott gyökér oldal címe érvénytelen.",
        "import-rootpage-nosubpage": "A(z) \"$1\" névtér nem engedi meg aloldalak használatát.",
        "importlogpage": "Importnapló",
        "importlogpagetext": "Lapok szerkesztési előzményekkel történő adminisztratív imporálása más wikikből.",
        "import-logentry-upload": "[[$1]] importálása fájlfeltöltéssel kész",
-       "import-logentry-upload-detail": "{{PLURAL:$1|egy|$1}} változat",
+       "import-logentry-upload-detail": "$1 változat importálva",
        "import-logentry-interwiki": "$1 más wikiből áthozva",
-       "import-logentry-interwiki-detail": "{{PLURAL:$1|egy|$1}} változat innen: $2",
+       "import-logentry-interwiki-detail": "$1 változat innen: $2",
        "javascripttest": "JavaScript tesztelés",
        "javascripttest-title": "$1 tesztek futtatása",
        "javascripttest-pagetext-noframework": "Ez az oldal JavaStript tesztek futtatására van fenntartva.",
        "version-entrypoints": "Belépési pont URL-címek",
        "version-entrypoints-header-entrypoint": "Belépési pont",
        "version-entrypoints-header-url": "URL",
+       "redirect-lookup": "Keresés:",
+       "redirect-value": "Érték:",
        "redirect-user": "Felhasználói azonosító",
+       "redirect-page": "Lapazonosító",
        "redirect-revision": "Oldal felülvizsgálata",
        "redirect-file": "Fájlnév",
        "redirect-not-exists": "Érték nem található",
        "htmlform-selectorother-other": "egyéb",
        "htmlform-no": "Nem",
        "htmlform-yes": "Igen",
+       "htmlform-chosen-placeholder": "Válasszon egy opciót",
+       "htmlform-cloner-delete": "Eltávolítás",
+       "htmlform-cloner-required": "Legalább egy érték szükséges.",
        "sqlite-has-fts": "$1 teljes szöveges keresés támogatással",
        "sqlite-no-fts": "$1 teljes szöveges keresés támogatása nélkül",
        "logentry-delete-delete": "$1 törölte a következő lapot: $3",
        "api-error-overwrite": "Létező fájlok felülírására nem engedélyezett.",
        "api-error-stashfailed": "Belső hiba: a kiszolgálünak nem sikerült eltárolni az ideiglenes fájlt.",
        "api-error-publishfailed": "Belső hiba: a kiszolgálónak nem sikerült közzétennie az ideiglenes fájlt.",
+       "api-error-stasherror": "Hiba történt a fájl feltöltése közben.",
        "api-error-timeout": "A kiszolgáló nem adott választ a várt időn belül.",
        "api-error-unclassified": "Ismeretlen hiba történt",
        "api-error-unknown-code": "Ismeretlen hiba: „$1”",
        "duration-centuries": "{{PLURAL:$1|egy|$1}} évszázad",
        "duration-millennia": "{{PLURAL:$1|egy|$1}} évezred",
        "rotate-comment": "Elforgattam a képet $1 fokkal, az óramutató járásával megegyező irányban",
+       "limitreport-cputime": "A CPU idő használata",
+       "limitreport-cputime-value": "$1 másodperc",
        "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|bájt}}",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|bájt}}",
        "expandtemplates": "Sablonok kibontása",
index 52c0fa0..a9b16e6 100644 (file)
@@ -16,7 +16,8 @@
                        "Xelgen",
                        "Համլետ",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Lilitik22"
                ]
        },
        "tog-underline": "ընդգծել հղումները՝",
        "tog-hidepatrolled": "Թաքցնել պարեկված խմբագրումները վերջին փոփոխությունների ցանկից",
        "tog-newpageshidepatrolled": "Թաքցնել պարեկված էջերը նոր էջերի ցանկից",
        "tog-extendwatchlist": "Ընդարձակել հսկացանկը՝ ցույց տալով բոլոր փոփոխությունները, այլ ոչ միայն վերջինները",
-       "tog-usenewrc": "Ô½Õ´Õ¢Õ¡Õ¾Õ¸Ö\80Õ¥Õ¬ Ö\83Õ¸Ö\83Õ¸Õ­Õ¸Ö\82Õ©ÕµÕ¸Ö\82Õ¶Õ¶Õ¥Ö\80Õ¨ Õ\8eերջին փոփոխություններում և հսկացանկում (պահանջում է JavaScript)",
+       "tog-usenewrc": "Ô½Õ´Õ¢Õ¡Õ¾Õ¸Ö\80Õ¥Õ¬ Ö\83Õ¸Ö\83Õ¸Õ­Õ¸Ö\82Õ©ÕµÕ¸Ö\82Õ¶Õ¶Õ¥Ö\80Õ¨ Õ¾երջին փոփոխություններում և հսկացանկում (պահանջում է JavaScript)",
        "tog-numberheadings": "Ինքնաթվագրել վերնագրերը",
        "tog-showtoolbar": "Ցույց տալ խմբագրումների գործիքների վահանակը",
        "tog-editondblclick": "Խմբագրել էջերը կրկնակի մատնահարմամբ",
        "tog-editsectiononrightclick": "Խմբագրել բաժինները վերնագրի աջ մատնահարմամբ",
-       "tog-watchcreations": "Ô±Õ¾Õ¥Õ¬Õ¡Ö\81Õ¶Õ¥Õ¬ Õ«Õ´ Õ½Õ¿Õ¥Õ²Õ®Õ¡Õ® Õ§Õ»Õ¥Ö\80Õ¨ Ö\87 Õ¢Õ¥Õ¼Õ¶Õ¡Õ® Õ¶Õ«Õ·Ö\84Õ¥Ö\80Õ¨ Õ°Õ½Õ¯Õ¡Ö\81Õ¡Õ¶Õ¯Õ«Õ¶",
-       "tog-watchdefault": "Ô±Õ¾Õ¥Õ¬Õ¡Ö\81Õ¶Õ¥Õ¬ Õ«Õ´ Õ­Õ´Õ¢Õ¡Õ£Ö\80Õ¡Õ® Õ§Õ»Õ¥Ö\80Õ¨ Ö\87 Õ¶Õ«Õ·Ö\84Õ¥Ö\80Õ¨ Õ°Õ½Õ¯Õ¡Ö\81Õ¡Õ¶Õ¯Õ«Õ¶",
-       "tog-watchmoves": "Ô±Õ¾Õ¥Õ¬Õ¡Ö\81Õ¶Õ¥Õ¬ Õ«Õ´ Õ¾Õ¥Ö\80Õ¶Õ¡Õ¾Õ¡Õ¶Õ¡Õ® Õ§Õ»Õ¥Ö\80Õ¨ Ö\87 Õ¶Õ«Õ·Ö\84Õ¥Ö\80Õ¨ Õ°Õ½Õ¯Õ¡Ö\81Õ¡Õ¶Õ¯Õ«Õ¶",
-       "tog-watchdeletion": "Ô±Õ¾Õ¥Õ¬Õ¡Ö\81Õ¶Õ¥Õ¬ Õ«Õ´ Õ»Õ¶Õ»Õ¡Õ® Õ§Õ»Õ¥Ö\80Õ¨ Ö\87 Õ¶Õ«Õ·Ö\84Õ¥Ö\80Õ¨ Õ«Õ´ Õ°Õ½Õ¯Õ¡Ö\81Õ¡Õ¶Õ¯Õ«Õ¶",
-       "tog-minordefault": "Նշել խմբագրումները որպես չնչին ըստ լռության",
+       "tog-watchcreations": "Ô±Õ¾Õ¥Õ¬Õ¡Ö\81Õ¶Õ¥Õ¬ Õ«Õ´ Õ½Õ¿Õ¥Õ²Õ®Õ¡Õ® Õ§Õ»Õ¥Ö\80Õ¨ Ö\87 Õ¢Õ¥Õ¼Õ¶Õ¡Õ® Õ¶Õ«Õ·Ö\84Õ¥Ö\80Õ¨ Õ°Õ½Õ¯Õ¡Ö\81Õ¡Õ¶Õ¯Õ¸Ö\82Õ´",
+       "tog-watchdefault": "Ô±Õ¾Õ¥Õ¬Õ¡Ö\81Õ¶Õ¥Õ¬ Õ«Õ´ Õ­Õ´Õ¢Õ¡Õ£Ö\80Õ¡Õ® Õ§Õ»Õ¥Ö\80Õ¨ Ö\87 Õ¶Õ«Õ·Ö\84Õ¥Ö\80Õ¨ Õ°Õ½Õ¯Õ¡Ö\81Õ¡Õ¶Õ¯Õ¸Ö\82Õ´",
+       "tog-watchmoves": "Ô±Õ¾Õ¥Õ¬Õ¡Ö\81Õ¶Õ¥Õ¬ Õ«Õ´ Õ¾Õ¥Ö\80Õ¶Õ¡Õ¾Õ¡Õ¶Õ¡Õ® Õ§Õ»Õ¥Ö\80Õ¨ Ö\87 Õ¶Õ«Õ·Ö\84Õ¥Ö\80Õ¨ Õ°Õ½Õ¯Õ¡Ö\81Õ¡Õ¶Õ¯Õ¸Ö\82Õ´",
+       "tog-watchdeletion": "Ô±Õ¾Õ¥Õ¬Õ¡Ö\81Õ¶Õ¥Õ¬ Õ«Õ´ Õ»Õ¶Õ»Õ¡Õ® Õ§Õ»Õ¥Ö\80Õ¨ Ö\87 Õ¶Õ«Õ·Ö\84Õ¥Ö\80Õ¨ Õ°Õ½Õ¯Õ¡Ö\81Õ¡Õ¶Õ¯Õ¸Ö\82Õ´",
+       "tog-minordefault": "Խմբագրումները լռելյայն նշել որպես չնչին",
        "tog-previewontop": "Ցույց տալ նախադիտումը խմբագրման դաշտից առաջ",
        "tog-previewonfirst": "Նախադիտել մինչև առաջին խմբագրությունը",
        "tog-enotifwatchlistpages": "էլ-փոստով տեղեկացնել հսկվող էջերում փոփոխությունների մասին",
        "permalink": "Մշտական հղում",
        "print": "Տպել",
        "view": "Դիտել",
+       "view-foreign": "Նայել $1-ում",
        "edit": "Խմբագրել",
+       "edit-local": "Խմբագրել տեղական նկարագրությունը",
        "create": "Ստեղծել",
        "editthispage": "Խմբագրել այս էջը",
        "create-this-page": "Ստեղծել այս էջը",
        "talkpagelinktext": "Քննարկում",
        "specialpage": "Սպասարկող էջ",
        "personaltools": "Անձնական գործիքներ",
-       "postcomment": "Նոր բաժին",
        "articlepage": "Դիտել հոդվածը",
        "talk": "Քննարկում",
        "views": "Դիտումները",
        "otherlanguages": "Այլ լեզուներով",
        "redirectedfrom": "(Վերահղված է $1ից)",
        "redirectpagesub": "Վերահղման էջ",
+       "redirectto": "Վերահղել դեպի՝",
        "lastmodifiedat": "Այս էջը վերջին անգամ փոփոխվել է ժամը $2-ին, $1 թվին։",
        "viewcount": "Այս էջին դիմել են {{PLURAL:$1|մեկ անգամ|$1 անգամ}}։",
        "protectedpage": "Պաշտպանված էջ",
        "jumptonavigation": "նավարկություն",
        "jumptosearch": "որոնում",
        "view-pool-error": "Ներեցեք՝ սերվերները գերբեռնված են այս պահին։\nՉափից շատ օգտվողներ փորձում են դիտել այս էջը։\nԽնդրում ենք սպասել որոշ ժամանակ էջը դիտելու կրկին հայցում անելուց առաջ։\n\n$1",
+       "generic-pool-error": "Ներեցեք՝ սերվերները գերբեռնված են այս պահին։\nՉափից շատ օգտվողներ փորձում են դիտել այս էջը։\nԽնդրում ենք սպասել որոշ ժամանակ էջը դիտելու կրկին հայցում անելուց առաջ։",
        "pool-errorunknown": "Անհայտ սխալ",
        "aboutsite": "{{grammar:genitive|{{SITENAME}}}} մասին",
        "aboutpage": "Project:Էությունը",
        "hidetoc": "թաքցնել",
        "collapsible-collapse": "Ծալել",
        "collapsible-expand": "Բացել",
+       "confirmable-confirm": "{{GENDER:$1|Դուք}} վստա՞հ եք:",
+       "confirmable-yes": "Այո",
+       "confirmable-no": "Ոչ",
        "thisisdeleted": "Դիտե՞լ կամ վերականգնե՞լ $1։",
        "viewdeleted": "Դիտե՞լ $1։",
        "restorelink": "{{PLURAL:$1|մեկ ջնջված խմբագրում|$1 ջնջված խմբագրում}}",
        "viewsource-title": "Դիտել $1 էջի աղբյուրը",
        "actionthrottled": "Գործողությունը արգելափակվեց",
        "actionthrottledtext": "Որպես հակա-սպամային միջոց, այս գործողության չափից շատ կատարումը կարճ ժամանակահատվածի ընթացքում սահմանափակված է։ Խնդրում ենք փորձել կրկին մի քանի րոպե անց։",
-       "protectedpagetext": "Այս էջը կողպված խմբագրման համար։",
+       "protectedpagetext": "Ô±ÕµÕ½ Õ§Õ»Õ¨ Õ¯Õ¸Õ²ÕºÕ¾Õ¡Õ® Õ§ Õ­Õ´Õ¢Õ¡Õ£Ö\80Õ´Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö\80Ö\89",
        "viewsourcetext": "Դուք կարող եք դիտել և պատճենել այս էջի ելատեքստը.",
        "viewyourtext": "Դուք կարող եք դիտել «ձեր ներդրումների» աղբյուրը և պատճենել այս էջ",
        "protectedinterface": "Այս էջը պարունակում է ծրագրային ապահովման միջերեսի տեքստ, և պաշտպանված է չարաշահումների կանխարգելման նպատակով։\nԲոլոր վիքիների թարգմանությունները փոփոխելու կամ ավելացնելու համար, խնդրում ենք այցելել ՄեդիաՎիքիի տեղայնացման նախագիծը՝ [//translatewiki.net/ translatewiki.net]։",
        "externaldberror": "Տեղի է ունեցել վավերացման արտաքին տվյալների բազայի սխալ, կամ դուք չունեք բավարար իրավունքներ ձեր արտաքին հաշվի փոփոխման համար։",
        "login": "Մտնել համակարգ",
        "nav-login-createaccount": "Մտնել / Գրանցվել",
-       "loginprompt": "{{SITENAME}} մուտք գործելու համար հարկավոր է քուքիները թույլատրել։",
        "userlogin": "Մտնել / Գրանցվել",
        "userloginnocreate": "Մտնել",
        "logout": "Դուրս գալ համակարգից",
        "gotaccountlink": "Մուտք գործեք համակարգ",
        "userlogin-resetlink": "Մոռացե՞լ եք Ձեր հաշվի տվյալները։",
        "userlogin-resetpassword-link": "Մոռացե՞լ եք գաղտնաբառը",
-       "userlogin-createanother": "Ստեղծել այլ հաշիվ",
        "createacct-emailrequired": "Էլ–փոստի հասցե",
        "createacct-emailoptional": "Էլ–փոստի հասցե (ոչ պարտադիր)",
        "createacct-email-ph": "Մուտքագրեք ձեր էլ–փոստի հասցեն",
        "badretype": "Ձեր մուտքագրած գաղտնաբառերը չեն համընկնում։",
        "userexists": "Այս մասնակցի անունը արդեն զբաղված է։ Խնդրում ենք ընտրել մեկ այլ անուն։",
        "loginerror": "Մուտքի սխալ",
+       "createacct-error": "Հաշվի ստեղծման սխալ",
        "createaccounterror": "Չհաջողվեց ստեղծել մասնակցային հաշիվ. $1",
        "nocookiesnew": "Մասնակցային հաշիվը ստեղծված է, սակայն մուտքը համակարգ չհաջողվեց։ {{SITENAME}} կայքը օգտագործում է «քուքիներ» մասնակիցների վավերացման համար։ Ձեր մոտ «քուքիները» արգելված են։ Խնդրում ենք թույլատրել սրանք, ապա մտնել համակարգ ձեր նոր մասնակցի անունով և գաղտնաբառով։",
        "nocookieslogin": "{{SITENAME}} կայքը օգտագործում է «քուքիներ» մասնակիցների վավերացման համար։ Ձեր մոտ «քուքիները» արգելված են։ Խնդրում ենք թույլատրել սրանք և փորձել կրկին։",
        "passwordtooshort": "Գաղտնաբառը պետք է պարունակի առնվազն {{PLURAL:$1|1 սիմվոլ|$1 սիմվոլ}}։",
        "password-name-match": "Գաղտնաբառը պետք է տարբեր լինել ձեր մասնակցի անունից։",
        "password-login-forbidden": "Այս ծածկանվան և գաղտնաբառի օգտագործումն արգելված է",
-       "mailmypassword": "Õ\88Ö\82Õ²Õ¡Ö\80Õ¯Õ¥Õ¬ Õ¶Õ¸Ö\80 Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼ Õ§Õ¬â\80\93Ö\83Õ¸Õ½Õ¿Õ¸Õ¾",
+       "mailmypassword": "Õ\8eÕ¥Ö\80Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨",
        "passwordremindertitle": "Նոր ժամանակավոր գաղտնաբառ {{grammar:genitive|{{SITENAME}}}} համար",
        "passwordremindertext": "Ինչ-որ մեկը (հավանաբար դուք՝ $1 IP-հասցեից) խնդրել է նոր գաղտնաբառ {{grammar:genitive|{{SITENAME}}}} ($4)։ «$2» մասնակցի ժամանակավոր գաղտնաբառն է՝ <code>$3</code>։ Եթե սա իսկապես ձեր մտադրություններ, ապա ձեզ հարկավոր է մտնել համակարգ և փոխել գաղտնաբառը։ Ձեր ժամանակավոր գաղտնաբառը գործելու է {{PLURAL:$5|օր|$5 օր}}։\n\nԵթե դուք չեք արել այսպիսի հայցում կամ արդեն հիշել եք ձեր գաղտնաբառը և մտադրություն չունեք այն փոխել, ապա կարող եք անտեսել այս ուղերձը և շարունակել օգտվել ձեր հին գաղտնաբառից։",
        "noemail": "«$1» մասնակցի համար էլ-փոստի հասցե չի նշվել։",
        "invalidemailaddress": "Նշված էլ-փոստի հասցեն անընդունելի է, քանի որ այն ունի անթույլատրելի ֆորմատ։ Խնդրում ենք նշել ճշմարիտ հասցե կամ այս դաշտը թողնել դատարկ։",
        "emaildisabled": "Այս կայքը չի կարող ուղարկել էլ․ նամակներ։",
        "accountcreated": "Հաշիվը ստեղծված է",
-       "accountcreatedtext": "$1 մասնակցի հաշիվը ստեղծված է։",
+       "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|քննարկում]]) մասնակցի հաշիվը ստեղծված է։",
        "createaccount-title": "{{SITENAME}}. մասնակցային հաշվի ստեղծում",
        "createaccount-text": "Ինչ-որ մեկը ստեղծել է «$2» անվանմամբ մասնակցային հաշիվ «$3» գաղտնաբառով {{SITENAME}} ($4) նախագծում՝ նշելով ձեր էլ-հասցեն։ Ձեզ անհրաժեշտ է մտնել համակարգ և փոխել գաղտնաբառը։\n\nԿարող եք անտեսել այս հաղորդագրությունը, եթե հաշիվը ստեղծվել է սխալմամբ։",
        "login-throttled": "Դուք կատարել եք չափից շատ մուտքի փորձ։\nԽնդրում ենք սպասել որոշ ժամանակ կրկին փորձելուց առաջ։",
        "loginlanguagelabel": "Լեզու՝ $1",
        "pt-login": "Մտնել",
+       "pt-login-button": "Մտնել",
        "pt-createaccount": "Ստեղծել մասնակցի հաշիվ",
        "pt-userlogout": "Դուրս գալ",
        "php-mail-error-unknown": "Անհայտ սխալ PHP-ի mail() ֆունկցիայում",
        "newpassword": "Նոր գաղտնաբառը.",
        "retypenew": "Հաստատեք նոր գաղտնաբառը.",
        "resetpass_submit": "Հաստատել գաղտնաբառը և մտնել համակարգ",
-       "changepassword-success": "Ձեր գաղտնաբառը փոխված է։ Մուտք համակարգ…",
+       "changepassword-success": "Ձեր գաղտնաբառը հաջողությամբ փոխված է։",
        "resetpass_forbidden": "Գաղտնաբառը չի կարող փոխվել",
        "resetpass-no-info": "Այս էջին ուղիղ դիմելու համար անհրաժեշտ է մտնել համակարգ։",
        "resetpass-submit-loggedin": "Փոխել գաղտնաբառը",
        "changeemail-password": "Քո {{SITENAME}} գաղտնաբառը՝",
        "changeemail-submit": "Փոխել էլ․ հասցեն",
        "changeemail-cancel": "Չեղարկել",
+       "resettokens-tokens": "Կտրոններ՝",
        "bold_sample": "Թավատառ տեքստ",
        "bold_tip": "Թավատառ տեքստ",
        "italic_sample": "Շեղատառ տեքստ",
        "notextmatches": "Չկան համընկած տեքստերով էջեր",
        "prevn": "նախորդ {{PLURAL:$1|$1}}",
        "nextn": "հաջորդ {{PLURAL:$1|$1}}",
+       "prevn-title": "Նախկին $1 {{PLURAL:$1|արդյունքը|արդյունքները}}",
+       "nextn-title": "Հաջորդ $1 {{PLURAL:$1|արդյունքը|արդյունքները}}",
        "viewprevnext": "Դիտել ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "'''Այս վիքիում, գոյություն ունի \"[[:$1]]\" անվանումով էջը։'''",
        "searchmenu-new": "'''Ստեղծե՛լ \"[[:$1]]\" էջը այս վիքիում'''",
        "searchprofile-advanced-tooltip": "Որոնել նշված անվանատարածքներում",
        "search-result-size": "$1 ({{PLURAL:$2|1 բառ|$2 բառ}})",
        "search-result-category-size": "{{PLURAL:$1|անդամ}} ({{PLURAL:$2|ենթակատեգորիա}}, {{PLURAL:$3|նիշք}})",
-       "search-result-score": "Համընկնում $1%",
        "search-redirect": "(վերահղում $1)",
        "search-section": "(բաժին $1)",
        "search-suggest": "Գուցե նկատի ունե՞ք՝ $1",
        "searchrelated": "հարակից",
        "searchall": "բոլոր",
        "showingresults": "Ստորև բերված է մինչև {{PLURAL:$1|'''1''' արդյունք|'''$1''' արդյունք}}՝ սկսած №&nbsp;<strong>$2</strong>-ից։",
-       "showingresultsheader": "{{PLURAL:$5|'''$1''' արդյունք '''$3'''-ից|'''$1 - $2''' արդյունքներ '''$3'''-ից}}  '''$4'''-ի համար",
        "search-nonefound": "Որոնմանը համապատասխանող արդյունքներ չեն գտնվել։",
        "powersearch-legend": "Ընդլայնված որոնում",
        "powersearch-ns": "Որոնել անվանատարածքում.",
        "prefs-skin": "Տեսք",
        "skin-preview": "նախադիտել",
        "datedefault": "Առանց նախընտրության",
+       "prefs-user-pages": "Մասնակցային էջերը",
        "prefs-personal": "Անձնական",
        "prefs-rc": "Վերջին փոփոխություններ",
        "prefs-watchlist": "Հսկացանկ",
        "prefs-watchlist-days": "Հսկացանկում ցուցադրվող օրերի թիվը՝",
-       "prefs-watchlist-days-max": "Maximum $1 {{PLURAL:$1|day|days}}",
+       "prefs-watchlist-days-max": "Առավելագույնը $1 {{PLURAL:$1|օր}}",
        "prefs-watchlist-edits": "Ընդարձակված հսկացանկում ցուցադրվող օրերի թիվը՝",
-       "prefs-watchlist-edits-max": "(1000-ից ոչ ավել)",
+       "prefs-watchlist-edits-max": "1000-ից ոչ ավել",
        "prefs-watchlist-token": "Հսկացանկի կտրոն.",
        "prefs-misc": "Այլ",
        "prefs-resetpass": "Փոխել գաղտնաբառը",
        "prefs-email": "Էլ-հասցեի ընտրանքներ",
        "prefs-rendering": "Արտաքին տեսք",
        "saveprefs": "Հիշել",
-       "restoreprefs": "Զրոյացնել, բերելով իլռելայն նախընտրանքներին",
+       "restoreprefs": "Զրոյացնել, բերելով իլռելայն նախընտրանքներին (բոլոր բաժիններում)",
        "prefs-editing": "Խմբագրում",
        "rows": "Տողեր`",
        "columns": "Սյունակներ",
        "searchresultshead": "Որոնում",
        "stub-threshold": "<a href=\"#\" class=\"stub\">Պատառ հոդվածների հղումների</a> ձևավորման որոշման սահմանը.",
+       "stub-threshold-disabled": "Անջատված է",
        "recentchangesdays": "Վերջին փոփոխություններում ցուցադրվող օրերի թիվը՝",
        "recentchangesdays-max": "($1 {{PLURAL:$1|օրից|օրից}} ոչ ավել)",
        "recentchangescount": "Խմբագրումների թիվը ըստ լռության.",
        "prefs-help-recentchangescount": "Ներառում է վերջին փոփոխությունները, էջերի պատմությունը և տեղեկամատյանները։",
+       "prefs-help-watchlist-token2": "Սա գաղտնի բանալի է հսկականկի օգնույամբ նորություն ստանալու համար:\nՈվ որ գիտի այն կարող է կարդալ ձեր հսկացանկը, ուստի մի տարածեք այն:\nԵթե ձեզ պետք է զրոյացնել հսկացանկի կտրոնը, [[Special:ResetTokens| սեղմեք այստեղ]]:",
        "savedprefs": "Ձեր նախընտրությունները հիշված են։",
        "timezonelegend": "Ժամային գոտի.",
        "localtime": "Տեղական ժամանակ.",
-       "timezoneuseserverdefault": "Օգտագործել սերվերի ժամանակը",
+       "timezoneuseserverdefault": "Օգտագործել սերվերի ժամանակը ($1)",
        "timezoneuseoffset": "Այլ (նշեք տարբերությունը)",
        "servertime": "Սերվերի ժամանակ.",
        "guesstimezone": "Լրացնել բրաուզերից",
        "fileexists-shared-forbidden": "Այսպիսի անվանմամբ նիշք արդեն գոյություն ունի նիշքերի ընդհանուր զետեղարանում։ Խնդրում ենք հետ վերադառնալ և բեռնել նիշքը նոր անվանմամբ։ [[File:$1|thumb|center|$1]]",
        "uploadwarning": "Զգուշացում",
        "savefile": "Հիշել ֆայլը",
-       "uploadedimage": "բեռնվեց «[[$1]]»",
-       "overwroteimage": "բեռնվեց «[[$1]]» նիշքի նոր տարբերակ",
        "uploaddisabled": "Բեռնումները արգելված են",
        "uploaddisabledtext": "Նիշքերի բեռնումը արգելափակված է։",
        "uploadscripted": "Այս նիշքը պարունակում է HTML-կոդ կամ գրվածք (սկրիպտ), որը կարող է սխալ մեկնաբանվել զննարկիչի կողմից։",
        "watchlist-details": "Ձեր հսկացանկում կա {{PLURAL:$1|$1 էջ|$1 էջ}}` քննարկման էջերը չհաշված։",
        "wlheader-enotif": "Էլ-փոստով տեղեկացումը միացված է։",
        "wlheader-showupdated": "Էջերը, որոնք փոփոխվել են ձեր դրանց վերջին այցից հետո բերված են '''թավատառ'''։",
+       "wlnote": "Ստորև բերված {{PLURAL:$1|է վերջին փոփոխությունը|են վերջին '''$1''' փոփոխությունները}} վերջին <strong>$2</strong> ժամվա ընթացքում։",
        "wlshowlast": "Ցուցադրել վերջին $1 ժամերը $2 օրերը $3",
        "watchlist-options": "Հսկացանկի նախընտրություններ",
        "watching": "Հսկվում է...",
index ca955f2..3edf919 100644 (file)
@@ -29,6 +29,7 @@
        "tog-watchdefault": "Adder le paginas e files que io modifica a mi observatorio",
        "tog-watchmoves": "Adder le paginas e files que io renomina a mi observatorio",
        "tog-watchdeletion": "Adder le paginas e files que io dele a mi observatorio",
+       "tog-watchrollback": "Adder a mi observatorio le paginas in que io ha effectuate un revocation",
        "tog-minordefault": "Marcar omne modificationes initialmente como minor",
        "tog-previewontop": "Monstrar previsualisation ante le quadro de modification",
        "tog-previewonfirst": "Monstrar previsualisation al prime modification",
        "talkpagelinktext": "Discussion",
        "specialpage": "Pagina special",
        "personaltools": "Instrumentos personal",
-       "postcomment": "Nove section",
        "articlepage": "Vider pagina de contento",
        "talk": "Discussion",
        "views": "Representationes",
        "otherlanguages": "In altere linguas",
        "redirectedfrom": "(Redirigite ab $1)",
        "redirectpagesub": "Pagina de redirection",
+       "redirectto": "Rediriger verso:",
        "lastmodifiedat": "Ultime modification de iste pagina: le $1 a $2.",
        "viewcount": "Iste pagina ha essite visitate {{PLURAL:$1|un vice|$1 vices}}.",
        "protectedpage": "Pagina protegite",
        "hidetoc": "celar",
        "collapsible-collapse": "Plicar",
        "collapsible-expand": "Displicar",
+       "confirmable-confirm": "Es {{GENDER:$1|tu}} secur?",
+       "confirmable-yes": "Si",
+       "confirmable-no": "No",
        "thisisdeleted": "Vider o restaurar $1?",
        "viewdeleted": "Vider $1?",
        "restorelink": "{{PLURAL:$1|un modification|$1 modificationes}} delite",
        "invalidtitle-knownnamespace": "Titulo invalide con spatio de nomines \"$2\" e texto \"$3\"",
        "invalidtitle-unknownnamespace": "Titulo invalide con spatio de nomines incognite $1 e texto \"$2\"",
        "exception-nologin": "Non identificate",
-       "exception-nologin-text": "[[Special:Userlogin|Aperi session]] pro poter acceder a iste pagina o action.",
+       "exception-nologin-text": "Aperi session pro poter acceder a iste pagina o action.",
        "exception-nologin-text-manual": "Es necessari $1 pro poter acceder a iste pagina o action.",
        "virus-badscanner": "Configuration incorrecte: programma antivirus non cognoscite: ''$1''",
        "virus-scanfailed": "scannamento fallite (codice $1)",
        "externaldberror": "O il occurreva un error in le base de datos de authentication, o tu non ha le autorisation de actualisar tu conto externe.",
        "login": "Aperir session",
        "nav-login-createaccount": "Aperir session / crear conto",
-       "loginprompt": "Tu debe haber activate le cookies pro poter aperir un session in {{SITENAME}}.",
        "userlogin": "Aperir session / crear conto",
        "userloginnocreate": "Aperir session",
        "logout": "Clauder session",
        "userlogin-resetlink": "Datos de authentication oblidate?",
        "userlogin-resetpassword-link": "Contrasigno oblidate?",
        "userlogin-helplink2": "Adjuta al accesso",
-       "userlogin-loggedin": "Tu ha jam aperite session como {{GENDER:$1|$1}}.\nUsa le formulario sequente pro aperir session como altere usator.",
-       "userlogin-createanother": "Crear un altere conto",
        "createacct-emailrequired": "Adresse de e-mail",
        "createacct-emailoptional": "Adresse de e-mail (optional)",
        "createacct-email-ph": "Entra tu adresse de e-mail",
        "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-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.",
        "createacct-another-realname-tip": "Le nomine real es optional.\nSi tu opta pro dar lo, isto essera usate pro dar al usator attribution pro su contributiones.",
        "preview": "Previsualisation",
        "showpreview": "Monstrar previsualisation",
        "showdiff": "Detaliar modificationes",
-       "anoneditwarning": "'''Attention:''' Tu non ha aperite un session.\nTu adresse IP essera registrate in le historia de modificationes de iste pagina.",
+       "blankarticle": "<strong>Advertimento:</strong> Le pagina que tu vole crear es vacue.\nSi tu clicca de novo sur \"{{int:savearticle}}\", le pagina essera create sin contento.",
+       "anoneditwarning": "<strong>Attention:</strong> Tu non ha aperite un session. Le adresse IP tue essera publicamente visibile si tu face modificationes. Si tu <strong>[$1 aperi un session]</strong> o <strong>[$2 crea un conto]</strong>, le modificationes essera attribuite al nomine de usator tue, inter altere avantages.",
        "anonpreviewwarning": "''Tu non ha aperite un session. Salveguardar registrara tu adresse IP in le historia de modificationes de iste pagina.''",
        "missingsummary": "'''Rememoration:''' Tu non ha specificate un summario del modification.\nSi tu clicca super \"{{int:savearticle}}\" de novo, le modification essera publicate sin summario.",
        "missingcommenttext": "Per favor entra un commento infra.",
        "parser-template-recursion-depth-warning": "Limite de recursion del patrono excedite ($1)",
        "language-converter-depth-warning": "Limite de profunditate del conversor de lingua excedite ($1)",
        "node-count-exceeded-category": "Paginas in que le numero de nodos excede le limite",
-       "node-count-exceeded-category-desc": "Un categoria pro paginas ubi le numero de nodos ha essite excedite.",
+       "node-count-exceeded-category-desc": "Le pagina excede le numero maxime de nodos.",
        "node-count-exceeded-warning": "Le numero de nodos in iste pagina excede le limite",
        "expansion-depth-exceeded-category": "Paginas in que le profunditate de expansion excede le limite",
-       "expansion-depth-exceeded-category-desc": "Isto es un categoria pro paginas in le quales le profunditate de expansion ha essite excedite.",
+       "expansion-depth-exceeded-category-desc": "Le pagina excede le profunditate de expansion maxime.",
        "expansion-depth-exceeded-warning": "Le profunditate de expansion in iste pagina excede le limite",
        "parser-unstrip-loop-warning": "Bucla de \"unstrip\" detegite",
        "parser-unstrip-recursion-limit": "Limite de recursion de \"unstrip\" excedite ($1)",
        "rev-deleted-event": "(entrata eliminate)",
        "rev-deleted-user-contribs": "[nomine de usator o adresse IP removite - modification celate ab contributiones]",
        "rev-deleted-text-permission": "Iste version del pagina ha essite '''delite'''.\nEs possibile que se trova detalios in le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de deletiones].",
+       "rev-suppressed-text-permission": "Iste version del pagina ha essite <strong>supprimite</strong>.\nDetalios se trova in le [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registro de suppressiones].",
        "rev-deleted-text-unhide": "Iste version del pagina ha essite '''delite'''.\nDetalios se trova in le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de deletiones].\nTu pote totevia [$1 vider iste version] si tu vole.",
        "rev-suppressed-text-unhide": "Iste version del pagina ha essite '''supprimite'''.\nDetalios se trova in le [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registro de suppressiones].\nTu pote totevia [$1 vider iste version] si tu vole.",
        "rev-deleted-text-view": "Iste version del pagina ha essite '''delite'''.\nTu pote vider lo;\ndetalios se trova in le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de deletiones].",
        "revdelete-text-text": "Versiones delite continua a apparer in le historia del pagina, ma parte de lor contento essera inaccessibile pro le publico.",
        "revdelete-text-file": "Versiones delite de un file continua a apparer in le historia del file, ma parte de lor contento essera inaccessibile pro le publico.",
        "logdelete-text": "Eventos delite continua a apparer in le registros, ma parte de lor contento essera inaccessibile pro le publico.",
-       "revdelete-text-others": "Altere administratores in {{SITENAME}} continua a poter acceder al contento abscondite e pote restaurar lo per medio de iste mesme interfacie, a minus que additional restrictiones ha essite definite.",
+       "revdelete-text-others": "Altere administratores continua a poter acceder al contento celate e restaurar lo, a minus que additional restrictiones ha essite definite.",
        "revdelete-confirm": "Per favor confirma que tu ha le intention de facer isto, que tu comprende le consequentias, e que tu face isto in accordo con [[{{MediaWiki:Policy-url}}|le politica]].",
        "revdelete-suppress-text": "Le suppression debe '''solmente''' esser usate pro le sequente casos:\n* Information potentialmente diffamatori\n* Information personal inappropriate\n*: ''adresses de domicilio e numeros de telephono, numeros de securitate social, etc.''",
        "revdelete-legend": "Definir restrictiones de visibilitate",
        "searchprofile-advanced-tooltip": "Cercar in spatios de nomines personalisate",
        "search-result-size": "$1 ({{PLURAL:$2|1 parola|$2 parolas}})",
        "search-result-category-size": "{{PLURAL:$1|1 membro|$1 membros}} ({{PLURAL:$2|1 subcategoria|$2 subcategorias}}, {{PLURAL:$3|1 file|$3 files}})",
-       "search-result-score": "Relevantia: $1%",
        "search-redirect": "(redirection ab $1)",
        "search-section": "(section $1)",
        "search-file-match": "(corresponde al contento del file)",
        "searchall": "totes",
        "showingresults": "Infra se monstra non plus de {{PLURAL:$1|'''1''' resultato|'''$1''' resultatos}} a partir del numero '''$2'''.",
        "showingresultsinrange": "In basso es monstrate usque a {{PLURAL:$1|<strong>1</strong> resultato|<strong>$1</strong> resultatos}} inter #<strong>$2</strong> e #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Resultato '''$1'''|Resultatos '''$1 - $2'''}} de '''$3''' pro '''$4'''",
        "search-nonefound": "Le recerca non ha producite resultatos.",
        "powersearch-legend": "Recerca avantiate",
        "powersearch-ns": "Cercar in spatios de nomines:",
        "preferences": "Preferentias",
        "mypreferences": "Preferentias",
        "prefs-edits": "Numero de modificationes:",
-       "prefsnologintext2": "Es necessari $1 pro definir le preferentias de usator.",
+       "prefsnologintext2": "Es necessari aperir session pro cambiar le preferentias.",
        "prefs-skin": "Apparentia",
        "skin-preview": "Previsualisation",
        "datedefault": "Nulle preferentia",
        "right-deletedtext": "Vider texto delite e differentias inter versiones delite",
        "right-browsearchive": "Cercar in paginas delite",
        "right-undelete": "Restaurar un pagina",
-       "right-suppressrevision": "Revider e restaurar versiones celate ab administratores",
+       "right-suppressrevision": "Vider, celar e revelar versiones specific de paginas de qualcunque usator",
+       "right-viewsuppressed": "Vider versiones celate de qualcunque usator",
        "right-suppressionlog": "Vider registros private",
        "right-block": "Blocar altere usatores de facer modificationes",
        "right-blockemail": "Blocar un usator de inviar e-mail",
        "recentchanges-legend-heading": "'''Legenda:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vide etiam le [[Special:NewPages|lista de nove paginas]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Ecce le modificationes a partir del <strong>$3 a $4</strong> (usque a <strong>$1</strong> entratas).",
+       "rcnotefrom": "Ecce le {{PLURAL:$5|modification|modificationes}} a partir del <strong>$3 a $4</strong> (usque a <strong>$1</strong> entratas monstrate).",
        "rclistfrom": "Monstrar nove modificationes a partir de $3 $2",
        "rcshowhideminor": "$1 modificationes minor",
        "rcshowhideminor-show": "Monstrar",
        "uploadwarning": "Advertimento de incargamento",
        "uploadwarning-text": "Per favor modifica le description del file ci infra e reproba.",
        "savefile": "Salveguardar file",
-       "uploadedimage": "incargava \"[[$1]]\"",
-       "overwroteimage": "incargava un nove version de \"[[$1]]\"",
        "uploaddisabled": "Incargamento de files disactivate",
        "copyuploaddisabled": "Incargamento per URL disactivate.",
        "uploaddisabledtext": "Le incargamento de files es disactivate.",
        "license": "Licentia:",
        "license-header": "Licentia",
        "nolicense": "Nulle licentia seligite",
+       "licenses-edit": "Modificar optiones de licentia",
        "license-nopreview": "(Previsualisation non disponibile)",
-       "upload_source_url": " (un adresse URL valide e publicamente accessibile)",
-       "upload_source_file": " (un file in tu computator)",
+       "upload_source_url": "(le file de tu preferentia ab un adresse URL valide e publicamente accessibile)",
+       "upload_source_file": "(le file de tu preferentia ab tu computator)",
+       "listfiles-delete": "deler",
        "listfiles-summary": "Iste pagina special monstra tote le files incargate.",
        "listfiles_search_for": "Cercar un nomine de media:",
        "imgfile": "file",
        "randomincategory": "Pagina aleatori in categoria",
        "randomincategory-invalidcategory": "\"$1\" non es un nomine de categoria valide.",
        "randomincategory-nopages": "Il non ha paginas in [[:Category:$1]].",
-       "randomincategory-selectcategory": "Prender un pagina qualcunque del categoria: $1 $2.",
-       "randomincategory-selectcategory-submit": "Va",
+       "randomincategory-category": "Categoria:",
+       "randomincategory-legend": "Pagina aleatori in categoria",
        "randomredirect": "Redirection aleatori",
        "randomredirect-nopages": "Il non ha redirectiones in le spatio de nomines \"$1\".",
        "statistics": "Statisticas",
        "wantedpages-badtitle": "Titulo invalide in le gruppo de resultatos: $1",
        "wantedfiles": "Files desirate",
        "wantedfiletext-cat": "Le sequente files es usate ma non existe. Le files ab repositorios externe pote esser listate malgrado que illos existe. Omne tal false positivos essera <del>cancellate</del>. In addition, paginas que incorpora files que non existe es listate in [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Le sequente files es usate ma non existe. In addition, paginas que incorpora files que non existe es listate in [[:$1]].",
        "wantedfiletext-nocat": "Le sequente files es usate ma non existe. Files ab repositorios externe pote esser listate malgrado que illos existe. Omne tal false positivos essera <del>cancellate</del>.",
+       "wantedfiletext-nocat-noforeign": "Le sequente files es usate ma non existe.",
        "wantedtemplates": "Patronos desirate",
        "mostlinked": "Paginas le plus ligate",
        "mostlinkedcategories": "Categorias le plus ligate",
        "trackingcategories-desc": "Criterios pro inclusion in categoria",
        "noindex-category-desc": "Iste pagina es excludite del indice perque illo contine le marca <code><nowiki>__NOINDEX__</nowiki></code> e es in un spatio de nomines ubi le uso de iste marca es permittite.",
        "index-category-desc": "Iste pagina contine le marca <code><nowiki>__INDEX__</nowiki></code> (e es in un spatio de nomines ubi le uso de iste marca es permittite), e dunque es includite in le indice mesmo si illo normalmente non lo esserea.",
-       "post-expand-template-inclusion-category-desc": "Le expansion de tote le patronos facerea le dimension del pagina exceder le limite de <code>$wgMaxArticleSize</code>, dunque alcun patronos non ha essite expandite.",
-       "post-expand-template-argument-category-desc": "Post le expansion de un parametro de patrono (qualcosa inter accolladas triple, como <code>{{{Exemplo}}}</code>), le dimension del pagina excede le limite de <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Troppo de functiones costose de analysator syntactic (como <code>#ifexist</code>) ha essite includite in un pagina. Vide [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Iste categoria es addite si le pagina contine un ligamine de file rupte (un ligamine pro incorporar un file quando le file non existe).",
-       "hidden-category-category-desc": "Iste categoria contine le marca <code><nowiki>__HIDDENCAT__</nowiki></code>, impediente lo de apparer in le quadro de ligamines de categoria in paginas, si non configurate alteremente.",
+       "post-expand-template-inclusion-category-desc": "Le dimension del pagina es plus grande de <code>$wgMaxArticleSize</code> post le expansion de tote le patronos, dunque alcun patronos non ha essite expandite.",
+       "post-expand-template-argument-category-desc": "Le dimension del pagina es plus grande de <code>$wgMaxArticleSize</code> post le expansion de un parametro de patrono (qualcosa inter accolladas triple, como <code>{{{Exemplo}}}</code>).",
+       "expensive-parserfunction-category-desc": "Le pagina usa troppo de functiones costose de analysator syntactic (como <code>#ifexist</code>). Vide [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "Le pagina contine un ligamine de file rupte (un ligamine pro incorporar un file quando le file non existe).",
+       "hidden-category-category-desc": "Le categoria contine <code><nowiki>__HIDDENCAT__</nowiki></code> in su contento de pagina, impediente que illo appare in le quadro de ligamines de categoria in paginas, si non configurate alteremente.",
        "trackingcategories-nodesc": "Nulle description disponibile.",
        "trackingcategories-disabled": "Le categoria es disactivate",
        "mailnologin": "Necun adresse de invio",
        "mywatchlist": "Observatorio",
        "watchlistfor2": "De $1 $2",
        "nowatchlist": "Tu non ha paginas sub observation.",
-       "watchlistanontext": "Tu debe $1 pro poter vider o modificar entratas in tu observatorio.",
+       "watchlistanontext": "Per favor, aperi session pro poter vider o modificar entratas in tu observatorio.",
        "watchnologin": "Tu non ha aperite un session",
        "addwatch": "Adder al observatorio",
        "addedwatchtext": "Le pagina \"[[:$1]]\" ha essite addite a tu [[Special:Watchlist|observatorio]].\nLe modificationes futur in iste pagina e in le pagina de discussion associate essera listate in illo.",
        "watchlist-details": "{{PLURAL:$1|$1 pagina|$1 paginas}} in tu observatorio. Le paginas de discussion non es contate separatemente.",
        "wlheader-enotif": "Le notification via e-mail es active.",
        "wlheader-showupdated": "Le paginas que ha essite modificate post tu ultime visita se monstra in litteras '''grasse'''.",
-       "wlnote2": "Ecce le cambiamentos in le ultime {{PLURAL:$1|hora|<strong>$1</strong> horas}}, a partir del $2 a $3.",
+       "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": "Revelar ultime $1 horas $2 dies $3",
        "watchlist-options": "Optiones del observatorio",
        "watching": "Observation in curso...",
        "exbeforeblank": "contento ante radimento esseva: '$1'",
        "delete-confirm": "Deler \"$1\"",
        "delete-legend": "Deler",
-       "historywarning": "'''Attention:''' Le pagina que tu vole deler ha un historia de circa $1 {{PLURAL:$1|version|versiones}}:",
+       "historywarning": "<strong>Attention:</strong> Le pagina que tu vole deler ha un historia de circa $1 {{PLURAL:$1|version|versiones}}:",
        "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-edit-reasonlist": "Modificar le motivos pro deletion",
        "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.",
        "rollback": "Revocar modificationes",
        "rollback_short": "Revocar",
        "autoblockid": "Auto-blocada №$1",
        "block": "Blocar usator",
        "unblock": "Disblocar usator",
-       "blockip": "Blocar 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).",
        "ipaddressorusername": "Adresse IP o nomine de usator:",
        "ipb-unblock-addr": "Disblocar $1",
        "ipb-unblock": "Disblocar un nomine de usator o un adresse IP",
        "ipb-blocklist": "Vider blocadas existente",
-       "ipb-blocklist-contribs": "Contributiones de $1",
+       "ipb-blocklist-contribs": "Contributiones de {{GENDER:$1|$1}}",
        "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",
        "import": "Importar paginas",
        "importinterwiki": "Importation transwiki",
        "import-interwiki-text": "Selige le wiki e le titulo del pagina a importar.\nLe datas del versiones e nomines del contributores essera preservate.\nTote le actiones de importation transwiki se registra in le [[Special:Log/import|registro de importationes]].",
-       "import-interwiki-source": "Wiki/pagina de origine:",
+       "import-interwiki-sourcewiki": "Wiki de origine:",
+       "import-interwiki-sourcepage": "Pagina de origine:",
        "import-interwiki-history": "Copiar tote le versiones del historia de iste pagina",
        "import-interwiki-templates": "Includer tote le patronos",
        "import-interwiki-submit": "Importar",
        "import-upload": "Incargar datos XML",
        "import-token-mismatch": "Perdita del datos del session. Per favor reprova.",
        "import-invalid-interwiki": "Non pote importar ab le wiki specificate.",
-       "import-error-edit": "Le pagina \"$1\" non es importate perque tu non ha le permission de modificar lo.",
-       "import-error-create": "Le pagina \"$1\" non es importate perque tu non ha le permission de crear lo.",
-       "import-error-interwiki": "Le pagina \"$1\" non es importate perque su nomine es reservate pro ligation externe (interwiki).",
-       "import-error-special": "Le pagina \"$1\" non es importate perque illo pertine a un spatio de nomines special que non permitte paginas.",
-       "import-error-invalid": "Le pagina \"$1\" non es importate perque su nomine es invalide.",
+       "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-error-interwiki": "Le pagina \"$1\" non ha essite importate perque su nomine es reservate pro un ligamine externe (interwiki).",
+       "import-error-special": "Le pagina \"$1\" non ha essite importate perque illo pertine a un spatio de nomines special que non permitte paginas.",
+       "import-error-invalid": "Le pagina \"$1\" non ha essite importate perque le nomine sub le qual illo haberea essite importate non es valide in iste wiki.",
        "import-error-unserialize": "Le version $2 del pagina \"$1\" non pote esser disserialisate. Il ha essite reportate que iste version usa le modello de contento $3 serialisate como $4.",
        "import-error-bad-location": "Le version $2 que usa le modello de contento $3 non pote esser immagazinate in \"$1\" in iste wiki, perque iste modello non es supportate in iste pagina.",
        "import-options-wrong": "Mal {{PLURAL:$2|option|optiones}}: <nowiki>$1</nowiki>",
        "importlogpage": "Registro de importationes",
        "importlogpagetext": "Importationes administrative de paginas con historia de modificationes desde altere wikis.",
        "import-logentry-upload": "importava [[$1]] per incargamento de file",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|version|versiones}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|version|versiones}} importate",
        "import-logentry-interwiki": "importava $1 transwiki",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|version|versiones}} desde $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|version|versiones}} importate desde $2",
        "javascripttest": "Test de JavaScript",
        "javascripttest-title": "Execution de $1 tests",
        "javascripttest-pagetext-noframework": "Iste pagina es reservate pro le execution de tests de JavaScript.",
        "autosumm-replace": "Contento reimplaciate per '$1'",
        "autoredircomment": "Redirection verso [[$1]]",
        "autosumm-new": "Pagina create con '$1'",
+       "autosumm-newblank": "Pagina vacue create",
        "lag-warn-normal": "Le modificationes plus nove que $1 {{PLURAL:$1|secunda|secundas}} possibilemente non se revela in iste lista.",
        "lag-warn-high": "Le servitor del base de datos es in retardo; modificationes facite durante le ultime $1 {{PLURAL:$1|secunda|secundas}} possibilemente non appare in iste lista.",
        "watchlistedit-normal-title": "Modificar observatorio",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discussion]])",
        "unknown_extension_tag": "Etiquetta de extension incognite \"$1\"",
        "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\".",
        "version": "Version",
        "version-extensions": "Extensiones installate",
        "version-skins": "Apparentias installate",
        "logentry-rights-rights": "$1 {{GENDER:$2|cambiava}} le appertinentia a gruppos pro $3 de $4 a $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|cambiava}} le appertinentia a gruppos pro $3",
        "logentry-rights-autopromote": "$1 ha essite automaticamente {{GENDER:$2|promovite}} de $4 a $5",
+       "logentry-upload-upload": "$1 {{GENDER:$2|ha incargate}} $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|ha incargate}} un nove version de $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|ha incargate}} $3",
        "rightsnone": "(nulle)",
        "feedback-bugornote": "Si tu es preste a describer un problema technic in detalio, per favor [$1 reporta un falta].\nSi non, tu pote usar le formulario facile hic infra. Tu commento essera addite al pagina \"[$3 $2]\", con tu nomine de usator e le navigator del web que tu usa.",
        "feedback-subject": "Subjecto:",
        "pagelang-use-default": "Usar lingua predefinite",
        "pagelang-select-lang": "Selige lingua",
        "right-pagelang": "Cambiar lingua del pagina",
-       "action-pagelang": "Cambiar lingua del pagina",
+       "action-pagelang": "cambiar le lingua del pagina",
        "log-name-pagelang": "Registro de cambios de lingua",
        "log-description-pagelang": "Isto es un registro de cambios de lingua in paginas.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|cambiava}} le lingua del pagina $3 de $4 a $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|cambiava}} le lingua del pagina $3 de $4 a $5.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (activate)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''disactivate''')"
 }
index b23e77e..3712ee9 100644 (file)
        "talkpagelinktext": "bicara",
        "specialpage": "Halaman istimewa",
        "personaltools": "Peralatan pribadi",
-       "postcomment": "Bagian baru",
        "articlepage": "Lihat halaman isi",
        "talk": "Pembicaraan",
        "views": "Tampilan",
        "externaldberror": "Telah terjadi kesalahan otentikasi basis data eksternal atau Anda tidak diizinkan melakukan kemaskini terhadap akun eksternal Anda.",
        "login": "Masuk log",
        "nav-login-createaccount": "Masuk log / buat akun",
-       "loginprompt": "Anda harus mengaktifkan kuki untuk dapat masuk log ke {{SITENAME}}.",
        "userlogin": "Masuk log / buat akun",
        "userloginnocreate": "Masuk log",
        "logout": "Keluar log",
        "userlogout": "Keluar log",
        "notloggedin": "Belum masuk log",
        "userlogin-noaccount": "Belum punya akun?",
-       "userlogin-joinproject": "Join {{SITENAME}}",
+       "userlogin-joinproject": "Gabung {{SITENAME}}",
        "nologin": "Belum mempunyai akun? $1.",
        "nologinlink": "Daftarkan akun baru",
        "createaccount": "Buat akun baru",
        "userlogin-resetlink": "Lupa detail info masuk Anda?",
        "userlogin-resetpassword-link": "Lupa kata sandi?",
        "userlogin-helplink2": "Bantuan masuk log",
-       "userlogin-loggedin": "Andan telah masuk log sebagai $1.\nGunakan formulir di bawah untuk masuk log sebagai pengguna lain.",
-       "userlogin-createanother": "Buat akun lain",
        "createacct-emailrequired": "Alamat surel",
        "createacct-emailoptional": "Alamat surel (opsional)",
        "createacct-email-ph": "Masukkan alamat surel Anda",
        "mergehistory-empty": "Tidak ada revisi yang dapat digabung.",
        "mergehistory-success": "$3 {{PLURAL:$3|revisi|revisi}} dari [[:$1]] berhasil digabungkan ke [[:$2]].",
        "mergehistory-fail": "Tidak dapat melakukan penggabungan, harap periksa kembali halaman dan parameter waktu.",
+       "mergehistory-fail-toobig": "Tidak dapat melakukan penggabungan sebagai lebih dari batas dari $1 {{PLURAL:$1|revisi|revisi}} akan dipindahkan.",
        "mergehistory-no-source": "Halaman sumber $1 tidak ada.",
        "mergehistory-no-destination": "Halaman tujuan $1 tidak ada.",
        "mergehistory-invalid-source": "Judul halaman sumber haruslah judul yang berlaku.",
        "searchprofile-advanced-tooltip": "Pencarian di ruang nama tertentu",
        "search-result-size": "$1 ({{PLURAL:$2|1 kata|$2 kata}})",
        "search-result-category-size": "{{PLURAL:$1|1 anggota|$1 anggota}} ({{PLURAL:$2|1 subkategori|$2 subkategori}}, {{PLURAL:$3|1 berkas|$3 berkas}})",
-       "search-result-score": "Relevansi: $1%",
        "search-redirect": "(pengalihan $1)",
        "search-section": "(bagian $1)",
        "search-file-match": "(cocok dengan isi berkas)",
        "searchall": "semua",
        "showingresults": "Di bawah ini ditampilkan hingga {{PLURAL:$1|'''1''' hasil|'''$1''' hasil}}, dimulai dari #'''$2'''.",
        "showingresultsinrange": "Menampilkan sampai dengan {{PLURAL:$1|<strong>1</strong> hasil|<strong>$1</strong> hasil}} dalam jangkauan #<strong>$2</strong> sampai #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Hasil '''$1''' dari '''$3'''|Hasil '''$1 - $2''' dari '''$3'''}} untuk '''$4'''",
        "search-nonefound": "Tidak ada hasil yang sesuai dengan kriteria.",
        "powersearch-legend": "Pencarian lanjut",
        "powersearch-ns": "Mencari di ruang nama:",
        "powersearch-togglelabel": "Pilih:",
        "powersearch-toggleall": "Semua",
        "powersearch-togglenone": "Tidak ada",
-       "powersearch-remember": "Ingar pilihan untuk pencarian selanjutnya",
+       "powersearch-remember": "Ingat pilihan untuk pencarian selanjutnya",
        "search-external": "Pencarian eksternal",
        "searchdisabled": "Pencarian {{SITENAME}} sementara dimatikan.\nAnda dapat mencari melalui Google untuk sementara waktu.\nPerlu diingat bahwa indeks Google untuk konten {{SITENAME}} mungkin belum mencakup perubahan-perubahan terakhir.",
        "search-error": "Kesalahan terjadi saat mencari: $1",
        "largefileserver": "Berkas ini lebih besar dari pada yang diizinkan server.",
        "emptyfile": "Berkas yang Anda muatkan kelihatannya kosong. Hal ini mungkin disebabkan karena adanya kesalahan ketik pada nama berkas. Silakan pastikan apakah Anda benar-benar ingin memuatkan berkas ini.",
        "windows-nonascii-filename": "Wiki ini tidak mendukung nama berkas dengan karakter istimewa.",
-       "fileexists": "Suatu berkas dengan nama tersebut telah ada, harap periksa <strong>[[:$1]]</strong> jika Anda tidak yakin untuk mengubahnya.\n[[$1|thumb]]",
+       "fileexists": "Suatu berkas dengan nama tersebut telah ada, harap periksa <strong>[[:$1]]</strong> jika {{GENDER:|Anda}} tidak yakin untuk mengubahnya.\n[[$1|thumb]]",
        "filepageexists": "Halaman deskripsi untuk berkas ini telah dibuat di <strong>[[:$1]]</strong>, tapi saat ini tak ditemukan berkas dengan nama tersebut. Ringkasan yang Anda masukkan tidak akan tampil pada halaman deskripsi. Untuk memunculkannya, Anda perlu untuk menyuntingnya secara manual.\n[[$1|thumb]]",
-       "fileexists-extension": "Berkas dengan nama serupa telah ada: [[$2|thumb]]\n* Nama berkas yang akan dimuat: <strong>[[:$1]]</strong>\n* Nama berkas yang telah ada: <strong>[[:$2]]</strong>\nMohon gunakan nama yang berbeda.",
+       "fileexists-extension": "Berkas dengan nama serupa telah ada: [[$2|thumb]]\n* Nama berkas yang akan dimuat: <strong>[[:$1]]</strong>\n* Nama berkas yang telah ada: <strong>[[:$2]]</strong>\nApakah Anda mungkin ingin menggunakan nama yang lebih khas?",
        "fileexists-thumbnail-yes": "Berkas ini tampaknya merupakan gambar yang ukurannya diperkecil ''(miniatur)''. [[$1|thumb]]\nHarap periksa berkas <strong>[[:$1]]</strong> tersebut.\nJika berkas tersebut memang merupakan gambar dalam ukuran aslinya, Anda tidak perlu untuk memuat kembali miniatur lainnya.",
        "file-thumbnail-no": "Nama berkas dimulai dengan <strong>$1</strong>.\nTampaknya berkas ini merupakan gambar dengan ukuran diperkecil ''(miniatur)''.\nJika Anda memiliki versi resolusi penuh dari gambar ini, harap muatkan berkas tersebut. Jika tidak, harap ubah nama berkas ini.",
        "fileexists-forbidden": "Suatu berkas dengan nama ini telah ada dan tak dapat ditimpa.\nJika Anda masih ingin memuat berkas Anda, silakan kembali dan gunakan nama baru. [[File:$1|thumb|center|$1]]",
        "uploadwarning": "Peringatan pemuatan",
        "uploadwarning-text": "Mohon perbaiki keterangan berkas di bawah dan coba lagi.",
        "savefile": "Simpan berkas",
-       "uploadedimage": "memuat \"[[$1]]\"",
-       "overwroteimage": "memuat versi baru dari \"[[$1]]\"",
        "uploaddisabled": "Maaf, fasilitas pemuatan dimatikan.",
        "copyuploaddisabled": "Pengunggahan dengan URL dimatikan.",
        "uploaddisabledtext": "Pemuatan berkas tidak diizinkan.",
        "license-nopreview": "(Pratayang tak tersedia)",
        "upload_source_url": " (suatu URL valid yang dapat diakses publik)",
        "upload_source_file": " (suatu berkas di komputer Anda)",
+       "listfiles-delete": "hapus",
        "listfiles-summary": "Halaman istimewa ini menampilkan semua berkas yang telah diunggah.\nKetika disaring oleh pengguna, hanya versi berkas terbaru dari berkas yang diunggah oleh pengguna tersebut yang ditampilkan.",
        "listfiles_search_for": "Cari nama berkas:",
        "imgfile": "berkas",
        "filedelete-maintenance": "Penghapusan dan pengembalian berkas sementara dinonaktifkan selama perawatan.",
        "filedelete-maintenance-title": "Tidak dapat menghapus berkas",
        "mimesearch": "Pencarian MIME",
-       "mimesearch-summary": "Halaman ini menyediakan fasilitas menyaring berkas berdasarkan tipe MIME-nya. Masukkan: contenttype/subtype, misalnya <code>image/jpeg</code>.",
+       "mimesearch-summary": "Halaman ini menyediakan fasilitas menyaring berkas berdasarkan tipe MIME-nya. Masukkan: contenttype/subtype atau contenttype/*, misalnya <code>image/jpeg</code>.",
        "mimetype": "Tipe MIME:",
        "download": "unduh",
        "unwatchedpages": "Halaman yang tak dipantau",
        "randomincategory": "Halaman acak dalam kategori",
        "randomincategory-invalidcategory": "\"$1\" bukanlah nama kategori yang berlaku.",
        "randomincategory-nopages": "Tidak ada halaman dalam [[:Category:$1]].",
-       "randomincategory-selectcategory": "Dapatkan halaman acak dari kategori: $1 $2.",
-       "randomincategory-selectcategory-submit": "Lanjut",
        "randomredirect": "Pengalihan sembarang",
        "randomredirect-nopages": "Tak terdapat pengalihan pada ruang nama \"$1\".",
        "statistics": "Statistik",
        "wantedpages-badtitle": "Judul tak valid dalam himpunan hasil: $1",
        "wantedfiles": "Berkas yang diinginkan",
        "wantedfiletext-cat": "Berkas-berkas berikut digunakan tetapi tidak ada. Berkas dari repositori asing mungkin tercantum meskipun ada. Setiap \"false positive\" akan <del>dicoret</del>. Selain itu, halaman yang menggunakan berkas yang tidak ada akan dicantumkan dalam [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Berkas berikut ini digunakan tetapi tidak ada. Selain itu, halaman yang menanamkan berkas yang tidak ada tercantum dalam [[:$1]].",
        "wantedfiletext-nocat": "Berkas-berkas berikut digunakan tetapi tidak ada. Berkas dari repositori asing mungkin tercantum meskipun ada. Setiap \"false positive\" akan <del>dicoret</del>.",
+       "wantedfiletext-nocat-noforeign": "Berkas berikut ini digunakan tetapi tidak ada.",
        "wantedtemplates": "Templat yang diinginkan",
        "mostlinked": "Halaman yang tersering dituju",
        "mostlinkedcategories": "Kategori yang tersering digunakan",
-       "mostlinkedtemplates": "Templat yang tersering digunakan",
+       "mostlinkedtemplates": "Halaman yang paling ditransklusikan",
        "mostcategories": "Halaman dengan kategori terbanyak",
        "mostimages": "Berkas yang tersering digunakan",
        "mostinterwikis": "Halaman dengan interwiki terbanyak",
        "watchlist-details": "Terdapat {{PLURAL:$1|$1 halaman|$1 halaman}} di daftar pantauan Anda, tidak termasuk halaman pembicaraan.",
        "wlheader-enotif": "Notifikasi surel diaktifkan.",
        "wlheader-showupdated": "Halaman-halaman yang telah berubah sejak kunjungan terakhir Anda ditampilkan dengan '''huruf tebal'''.",
-       "wlnote2": "Di bawah ini adalah perubahan yang terjadi dalam {{PLURAL:$1|sejam|<strong>$1</strong> jam}} terakhir, per $2, $3.",
+       "wlnote": "Di bawah ini adalah {{PLURAL:$1|perubahan|'''$1''' perubahan}} terakhir dalam '''$2''' jam terakhir, per $3, $4.",
        "wlshowlast": "Tampilkan $1 jam $2 hari terakhir $3",
        "watchlist-options": "Opsi daftar pantauan",
        "watching": "Memantau...",
        "import": "Impor halaman",
        "importinterwiki": "Impor transwiki",
        "import-interwiki-text": "Pilih suatu wiki dan judul halaman yang akan di impor.\nTanggal revisi dan nama penyunting akan dipertahankan.\nSemua aktivitas impor transwiki akan dicatat di [[Special:Log/import|log impor]].",
-       "import-interwiki-source": "Wiki/halaman sumber:",
        "import-interwiki-history": "Salin semua versi terdahulu dari halaman ini",
        "import-interwiki-templates": "Sertakan semua templat",
        "import-interwiki-submit": "Impor",
        "timezone-utc": "UTC",
        "unknown_extension_tag": "Tag ekstensi tidak dikenal \"$1\"",
        "duplicate-defaultsort": "Peringatan: Kunci pengurutan baku \"$2\" mengabaikan kunci pengurutan baku \"$1\" sebelumnya.",
+       "duplicate-displaytitle": "<strong>Peringatan:</strong> Menampilkan judul \"$2\" menimpa judul tampilan \"$1\" sebelumnya.",
        "version": "Versi",
        "version-extensions": "Ekstensi terinstal",
-       "version-skins": "Kulit",
+       "version-skins": "Kulit yang diinstal",
        "version-specialpages": "Halaman istimewa",
        "version-parserhooks": "Kait parser",
        "version-variables": "Variabel",
        "version-hook-name": "Nama kait",
        "version-hook-subscribedby": "Dilanggani oleh",
        "version-version": "(Versi $1)",
+       "version-no-ext-name": "[tanpa nama]",
        "version-svn-revision": "(r$2)",
        "version-license": "Lisensi MediaWiki",
        "version-ext-license": "Lisensi",
        "version-ext-colheader-name": "Ekstensi",
+       "version-skin-colheader-name": "Kulit",
        "version-ext-colheader-version": "Versi",
        "version-ext-colheader-license": "Lisensi",
        "version-ext-colheader-description": "Deskripsi",
        "expand_templates_remove_nowiki": "Tidak menampilkan tag <nowiki> pada hasilnya",
        "expand_templates_generate_xml": "Tampilkan pohon parser XML",
        "expand_templates_generate_rawhtml": "Tampilkan HTML mentah",
-       "expand_templates_preview": "Pratayang"
+       "expand_templates_preview": "Pratayang",
+       "pagelanguage": "Pemilih bahasa halaman",
+       "pagelang-name": "Halaman",
+       "pagelang-language": "Bahasa",
+       "pagelang-use-default": "Gunakan bahasa default",
+       "pagelang-select-lang": "Pilih bahasa",
+       "right-pagelang": "Ubah bahasa halaman",
+       "action-pagelang": "mengubah bahasa halaman",
+       "log-name-pagelang": "Ubah bahasa log",
+       "log-description-pagelang": "Ini adalah log perubahan dalam bahasa halaman.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|mengubah}} bahasa halaman $3 dari $4 menjadi $5."
 }
index 6e09f82..b1f5651 100644 (file)
        "talkpagelinktext": "Conversation",
        "specialpage": "Págine special",
        "personaltools": "Mi utensiles",
-       "postcomment": "Nov division",
        "articlepage": "Vider li articul",
        "talk": "Discussion",
        "views": "Aspectes",
        "yourdomainname": "Tui dominia:",
        "login": "Aperter session",
        "nav-login-createaccount": "Crear un conto o intrar",
-       "loginprompt": "Cookies deve esser permisset por intrar in {{SITENAME}}.",
        "userlogin": "Crear un conto o intrar",
        "userloginnocreate": "Intrar",
        "logout": "Surtida",
        "uploadwarning": "Advertiment de cargament",
        "uploadwarning-text": "Pleser modificar li descrition de file infra e prova denov.",
        "savefile": "Conservar file",
-       "uploadedimage": "cargat \"[[$1]]\"",
        "uploadscripted": "Ti file contene HTML o code scrite que posse esser interpretet erroremen per un navigator web.",
        "uploadvirus": "Li file contene un virus!\nDetallies: $1",
        "upload-maxfilesize": "Mesura maxim de file: $1",
        "watchlist-details": "{{PLURAL:$1|$1 págine|$1 págines}} in tui liste de págines vigilat, sin págines de discussion.",
        "wlheader-enotif": "Li notification de e-mail es permisset.",
        "wlheader-showupdated": "Págines quel hat esset mutat desde tui ultim visitation es monstrat in '''nigri'''",
+       "wlnote": "Infra {{PLURAL:$1|es li ultim change|es li ultim '''$1''' changes}} in li ultim {{PLURAL:$2|hor|'''$2''' hores}}.",
        "wlshowlast": "Monstra ultim $1 hores $2 dies $3",
        "watchlist-options": "Optiones de liste de págines vigilat",
        "watching": "Vigilant...",
index 88015ef..e976fac 100644 (file)
        "talkpagelinktext": "Okwu",
        "specialpage": "Ihü mkpà",
        "personaltools": "Ngwa nkem",
-       "postcomment": "Nkeji ohúrù",
        "articlepage": "Zi ihü iheníle",
        "talk": "Akíkó",
        "views": "Há hụrụ ya olé",
        "yourdomainname": "Obí gi:",
        "login": "Banyé",
        "nav-login-createaccount": "Banyé / ké buwá",
-       "loginprompt": "Í gi nwé cookies Í chórí bátá {{SITENAME}}.",
        "userlogin": "Banyé / ké buwá",
        "userloginnocreate": "Banyé",
        "logout": "Fwuör",
        "searchprofile-everything-tooltip": "Tùwé ihe nile (na okwu ihü)",
        "searchprofile-advanced-tooltip": "Chọwa na ímé áhàámá nke gí Í kèrè",
        "search-result-size": "$1 ({{PLURAL:$2|mkpurụ edemede 1|$2 mkpurụ edemede}})",
-       "search-result-score": "Otu o di nkpà: $1%",
        "search-redirect": "(kúfù $1)",
        "search-section": "(nkeji $1)",
        "search-suggest": "Ị̀ kwèshirí dé: $1",
        "filereuploadsummary": "Gbanwere maka usòrò:",
        "filesource": "Mkpọlọ́gwụ̀:",
        "savefile": "Domá usòrò",
-       "uploadedimage": "\"[[$1]]\" dị na élú",
        "upload-source": "Usòrò mkpọlógwù",
        "sourcefilename": "Áhà usòrò mkpọlógwù:",
        "sourceurl": "URL mkpọlógwù:",
        "watchlisttools-edit": "Lé na rü na ndetù ńlé",
        "watchlisttools-raw": "Rüo ndetù nlènlé mèpòrò",
        "version": "Ùdị",
-       "version-specialpages": "Ihü mkpà",
        "version-skins": "Akpụkpọ",
+       "version-specialpages": "Ihü mkpà",
        "version-other": "Nke ozor",
        "version-hooks": "Nyazo",
        "version-hook-name": "Áhà nyazo",
index 617110a..360cf5c 100644 (file)
                ]
        },
        "tog-underline": "Pinag-ugisan ti silpo:",
-       "tog-hideminor": "Ilemmeng dagiti bassit a panagbaliw kadagiti naudi a sinuk-sukatan",
-       "tog-hidepatrolled": "Ilemmeng dagiti napatruliaan nga inurnos kadagiti naudi a sinuk-sukatan",
+       "tog-hideminor": "Ilemmeng dagiti bassit a inurnos iti kaudian a balbaliw",
+       "tog-hidepatrolled": "Ilemmeng dagiti napatruliaan nga inurnos iti kaudian a balbaliw",
        "tog-newpageshidepatrolled": "Ilemmeng dagiti napatruliaan a panid manipud ti baro a listaan ti panid",
-       "tog-extendwatchlist": "Ipalawa ti listaan ti bambantayan tapno maipakita amin a nasukatan, tapno saan laeng a dagiti nabiit",
-       "tog-usenewrc": "Dagiti grupo a panagbaliw babaen ti panid kadagiti kinaudi a panagbaliw ken banbantayan",
+       "tog-extendwatchlist": "Ipalawa ti listaan ti bambantayan tapno maipakita amin a nasukatan, saan laeng a ti kabiitan",
+       "tog-usenewrc": "Dagiti grupo a panagbaliw babaen ti panid ti kaudian a balbaliw ken listaan ti bambantayan",
        "tog-numberheadings": "Automatiko a pabilangan dagiti paulo",
        "tog-showtoolbar": "Ipakita ti baras ti ramit ti panag-urnos",
        "tog-editondblclick": "Urnosen dagiti panid iti mamindua a panagpindut",
-       "tog-editsectiononrightclick": "Pakabaelan ti panag-urnos ti paset babaen ti kanawan a panagpindut kadagiti titulo ti paset",
-       "tog-watchcreations": "Agnayon kadagiti panid a pinartuatko ken papeles nga inkargak idiay listaan ti bambantayak",
-       "tog-watchdefault": "Agnayon kadagiti panid ken papeles nga inurnosko idiay listaan ti bambantayak",
-       "tog-watchmoves": "Agnayon kadagiti panid ken papeles nga inyalisko idiay listaan ti bambantayak",
-       "tog-watchdeletion": "Agnayon kadagiti panid ken papeles nga inikkatko idiay listaan ti bambantayak",
-       "tog-minordefault": "Markaan amin nga inurnos a kas sigud a bassit",
+       "tog-editsectiononrightclick": "Pakabaelan ti panag-urnos iti paset babaen ti panagpindut iti kanawan kadagiti titulo ti paset",
+       "tog-watchcreations": "Agnayon kadagiti panid a pinartuatko ken papeles nga inkargak iti listaan ti bambantayak",
+       "tog-watchdefault": "Agnayon kadagiti panid ken papeles nga inurnosko iti listaan ti bambantayak",
+       "tog-watchmoves": "Agnayon kadagiti panid ken papeles nga inyalisko iti listaan ti bambantayak",
+       "tog-watchdeletion": "Agnayon kadagiti panid ken papeles nga inikkatko iti listaan ti bambantayak",
+       "tog-minordefault": "Markaan amin dagiti inurnos a kas bassit babaen ti kasisigud",
        "tog-previewontop": "Ipakita ti panagipadas sakbay ti pagurnosan a kahon",
        "tog-previewonfirst": "Ipakita ti pinadas iti umuna a panag-urnos",
-       "tog-enotifwatchlistpages": "Esuratannak no mabaliwan ti panid wenno papeles idiay listaan dagiti bambantayak",
+       "tog-enotifwatchlistpages": "Esuratannak no mabaliwan ti panid wenno papeles iti listaan dagiti bambantayak",
        "tog-enotifusertalkpages": "Esuratannak no mabaliwan ti panid ti tungtungak",
        "tog-enotifminoredits": "Esuratannak pay para kadagiti bassit a panag-urnos kadagiti panid ken papeles",
-       "tog-enotifrevealaddr": "Iparang ti pagtaengan ti esuratko kadagiti panagipakaaammo nga esurat",
+       "tog-enotifrevealaddr": "Iparang ti pagtaengan ti esuratko iti panagipakaaammo kadagiti esurat",
        "tog-shownumberswatching": "Ipakita ti bilang dagiti agbuybuya nga agar-aramat",
        "tog-oldsig": "Ti adda a pirma:",
-       "tog-fancysig": "Tratuen ti pirma a kas wikitext (nga awan ti automatiko a panagsilpo)",
-       "tog-uselivepreview": "Usaren ti agdama a panagipadas (eksperimento)",
-       "tog-forceeditsummary": "Pakaammuannak no sumrek ti blanko a pakabuklan ti panag-urnos",
+       "tog-fancysig": "Tratuen ti pirma a kas wikitext (nga awan ti automatiko a silpo)",
+       "tog-uselivepreview": "Usaren ti agdama a panagipadas (eksperimental)",
+       "tog-forceeditsummary": "Pakaammuannak no sumrek iti blanko a pakabuklan ti panag-urnos",
        "tog-watchlisthideown": "Ilemmeng dagiti inurnosko manipud ti listaan ti bambantayan",
        "tog-watchlisthidebots": "Ilemmeng dagiti inurnos ti bot manipud ti listaan ti bambantayan",
        "tog-watchlisthideminor": "Ilemmeng dagiti bassit nga inurnos manipud ti listaan ti bambantayan",
-       "tog-watchlisthideliu": "Ilemmeng dagiti inurnos ti nakasterk nga agar-aramat manipud ti listaan ti bambantayan",
-       "tog-watchlisthideanons": "Ilemmeng dagiti inurnos ti di am-ammo nga agar-aramat manipud ti listaan ti bambantayan",
+       "tog-watchlisthideliu": "Ilemmeng dagiti inurnos babaen dagiti nakastrek nga agar-aramat manipud ti listaan ti bambantayan",
+       "tog-watchlisthideanons": "Ilemmeng dagiti inurnos babaen dagiti di ammo nga agar-aramat manipud ti listaan ti bambantayan",
        "tog-watchlisthidepatrolled": "Ilemmeng dagiti napatruliaan nga inurnos manipud ti listaan ti bambantayan",
-       "tog-ccmeonemails": "Patulodandak kadagiti kopia ti esurat nga ipatulodko kadagiti sabsabali nga agar-aramat",
+       "tog-ccmeonemails": "Patulodandak kadagiti kopia ti esurat nga ipatulodko kadagiti sabali nga agar-aramat",
        "tog-diffonly": "Saan nga iparang ti linaon ti panid dita baba dagiti pagiddiatan",
        "tog-showhiddencats": "Ipakita dagiti nailemmeng a kategoria",
        "tog-norollbackdiff": "Laksiden ti paggiddiatan kalpasan ti panagaramid ti panagisubli",
-       "tog-useeditwarning": "Pakaunaannak no pumanawak iti maysa pagurnosan a panid no adda ti saan a naidulin a sinuksukatan",
-       "tog-prefershttps": "Kankanayon nga agusar ti natalged a pannakaisilpo no nakastrek",
+       "tog-useeditwarning": "Pakaunaannak no pumanawak iti maysa pagurnosan a panid nga addaan iti saan a naidulin a sinuksukatan",
+       "tog-prefershttps": "Kankanayon nga agusar ti natalged a koneksion no nakastrek",
        "underline-always": "Kanayon",
        "underline-never": "Saan uray kaanoman",
-       "underline-default": "Kasisigud a kudil wenno pagbasabasa",
-       "editfont-style": "Urnosen ti kita ti letra iti lugar:",
+       "underline-default": "Kudil wenno kasisigud a pagbasabasa",
+       "editfont-style": "Estilo ti kita ti letra ti pagurnosan a lugar:",
        "editfont-default": "Kasisigud a pagbasabasa",
        "editfont-monospace": "Monospaced a kita ti letra",
        "editfont-sansserif": "Sans-serif a kita ti letra",
        "editfont-serif": "Serif a kita ti letra",
-       "sunday": "Dominggo",
+       "sunday": "Domingo",
        "monday": "Lunes",
        "tuesday": "Martes",
        "wednesday": "Mierkoles",
@@ -66,9 +66,9 @@
        "sun": "Dom",
        "mon": "Lun",
        "tue": "Mar",
-       "wed": "Mie",
+       "wed": "Mier",
        "thu": "Hue",
-       "fri": "Bie",
+       "fri": "Bier",
        "sat": "Sab",
        "january": "Enero",
        "february": "Pebrero",
        "category_header": "Pampanid iti kategoria \"$1\"",
        "subcategories": "Dagiti subkategoria",
        "category-media-header": "Dagiti midia iti kategoria \"$1\"",
-       "category-empty": "''Daytoy a kategoria ket agdama a saan nga aglaon kadagiti panid wenno midia.''",
+       "category-empty": "<em>Daytoy a kategoria ket agdama a saan nga aglaon kadagiti panid wenno midia.</em>",
        "hidden-categories": "{{PLURAL:$1|Nailemmeng a kategoria|Nailemmeng a katkategoria}}",
        "hidden-category-category": "Nailemmeng a katkategoria",
-       "category-subcat-count": "{{PLURAL:$2|Daytoy a kategoria ket adda laeng ti sumaganad a subkategoria.|Daytoy a kategoria ket addaan ti sumaganad a {{PLURAL:$1|a subkategoria|$1 a subkatkategoria}}, manipud ti $2 a dagup.}}",
+       "category-subcat-count": "{{PLURAL:$2|Daytoy a kategoria ket addaan laeng ti sumaganad a subkategoria.|Daytoy a kategoria ket addaan ti sumaganad a {{PLURAL:$1|a subkategoria|$1 a subkatkategoria}}, manipud ti $2 a dagup.}}",
        "category-subcat-count-limited": "Daytoy a kategoria ket addaan ti sumaganad a {{PLURAL:$1|a subkategoria|$1 a subkatkategoria}}.",
        "category-article-count": "{{PLURAL:$2|Daytoy a kategoria ket aglaon laeng ti sumaganad a panid.|Ti sumaganad a {{PLURAL:$1|a panid ket|$1 a pampanid ket dagiti}} adda iti daytoy a kategoria, manipud ti $2 a dagup.}}",
        "category-article-count-limited": "Ti sumaganad a {{PLURAL:$1|panid |$1 a pampanid}} ket adda iti agdama a kategoria.",
        "category-file-count-limited": "Ti sumaganad a {{PLURAL:$1|papeles|$1 a pappapeles}} ket adda iti agdama a kategoria.",
        "listingcontinuesabbrev": "tuloy.",
        "index-category": "Naipagsurotan a pampanid",
-       "noindex-category": "Di naipasurotan a pampanid",
-       "broken-file-category": "Pampanid nga adda nadadael a silsilpo kadagiti papeles",
+       "noindex-category": "Di naipagsurotan a pampanid",
+       "broken-file-category": "Pampanid nga addaan kadagiti nadadael a silpo ti papeles",
        "about": "Maipanggep",
        "article": "Naglaon a panid",
-       "newwindow": "(aglukat iti sabali a tawa)",
+       "newwindow": "(aglukat iti baro a tawa)",
        "cancel": "Ukasen",
        "moredotdotdot": "Adu pay...",
        "morenotlisted": "Daytoy a listaan ket saan a kompleto.",
        "actions": "Dagiti aramid",
        "namespaces": "Dagiti nagan ti espasio",
        "variants": "Sab-sabali a pagsasao",
-       "navigation-heading": "Pagdaliasatan ti pagpilian",
+       "navigation-heading": "Listaan ti pagdaliasatan",
        "errorpagetitle": "Biddut",
        "returnto": "Agsubli idiay $1.",
        "tagline": "Naggapo idiay {{SITENAME}}",
        "view-foreign": "Kitaen idiay $1",
        "edit": "Urnosen",
        "edit-local": "Urnosen ti lokal a deskripsion",
-       "create": "Agaramid",
+       "create": "Agpartuat",
        "create-local": "Agnayon ti lokal a deskripsion",
        "editthispage": "Urnosen daytoy a panid",
        "create-this-page": "Partuaten daytoy a panid",
        "talkpagelinktext": "Tungtungan",
        "specialpage": "Espesial a panid",
        "personaltools": "Bukod a ram-ramit",
-       "postcomment": "Baro a paset",
        "articlepage": "Kitaen ti naglaon a panid",
        "talk": "Pagtungtungan",
        "views": "Dagiti pangkitaan",
        "categorypage": "Kitaen ti panid ti kategoria",
        "viewtalkpage": "Kitaen ti pagtungtungan",
        "otherlanguages": "Kadagiti sabali a pagsasao",
-       "redirectedfrom": "(Naibaw-ing manipud idiay $1)",
+       "redirectedfrom": "(Naibaw-ing manipud iti $1)",
        "redirectpagesub": "Baw-ing a panid",
-       "lastmodifiedat": "Daytoy a panid ket naudi a nabaliwan idi $1, idi $2.",
-       "viewcount": "Naserrekan daytoy a panid {{PLURAL:$1|iti naminsan|kadagiti $1 a beses}}.",
+       "lastmodifiedat": "Daytoy a panid ket naudi a nabaliwan idi $1, $2.",
+       "viewcount": "Naserrekanen daytoy a panid {{PLURAL:$1|iti naminsan|kadagiti $1 a beses}}.",
        "protectedpage": "Nasalakniban a panid",
        "jumpto": "Lumaktaw idiay:",
        "jumptonavigation": "pagdaliasatan",
        "jumptosearch": "biruken",
-       "view-pool-error": "Pasensian, dagiti servers ket nadagsenan unay tattan.\nAdu unay dagiti agar-aramat nga agbuy-buya ti daytoy a panid.\nPangaasi nga agurayka met bassit sakbay a padasem manen ti mangserrek daytoy a panid.\n\n$1",
-       "generic-pool-error": "Pasensian, dagiti server ket agdama a nadagsenan unay.\nAdu unay dagiti agar-aramat nga agbuybuya ti daytoy a rekurso.\nPangngaasi nga agurayka bassit sakbay a padasem manen a serrekan daytoy a rekurso.",
+       "view-pool-error": "Pasensian, dagiti server ket nadagsenan unay iti agdama.\nAdu unay dagiti agar-aramat nga agpadpadas nga agbuya iti daytoy a panid.\nPangngaasi nga agurayka bassit sakbay a padasem manen a serrekan daytoy a panid.\n\n$1",
+       "generic-pool-error": "Pasensian, dagiti server ket agdama a nadagsenan iti agdama.\nAdu unay dagiti agar-aramat nga agpadpadas nga agbuya iti daytoy a rekurso.\nPangngaasi nga agurayka bassit sakbay a padasem manen a serrekan daytoy a rekurso.",
        "pool-timeout": "Madamdama agur-uray para iti kandado",
-       "pool-queuefull": "Napunnon ti nagyanan ti pagur-urayan",
-       "pool-errorunknown": "Di am-ammo a biddut",
-       "pool-servererror": "Ti serbisio ti pagbilangan ti pisina ket saan a magun-od ($1).",
+       "pool-queuefull": "Napunnon ti pagyanan ti pagur-urayan",
+       "pool-errorunknown": "Di ammo a biddut",
+       "pool-servererror": "Ti serbisio ti pagbilangan ti pagyanan ti pagur-urayan ket saan a magun-od ($1).",
        "aboutsite": "Maipanggep ti {{SITENAME}}",
        "aboutpage": "Project:Maipanggep",
        "copyright": "Ti linaon ket magun-od babaen ti $1 malaksid no adda sabali a naibaga.",
        "privacypage": "Project:Annuroten ti kinapribado",
        "badaccess": "Biddut ti pammalubos",
        "badaccess-group0": "Awan pammalubosmo a mangpataray ti kiniddawmo nga aramid.",
-       "badaccess-groups": "Ti kiniddawmo nga aramid ket limitado laeng kadagiti agar-aramat {{PLURAL:$2|iti grupo|iti maysa kadagiti grupo}}: ti $1.",
+       "badaccess-groups": "Ti kiniddawmo nga aramid ket limitado laeng kadagiti agar-aramat {{PLURAL:$2|iti grupo|iti maysa kadagiti grupo}}: $1.",
        "versionrequired": "Masapul ti bersion $1 ti MediaWiki",
        "versionrequiredtext": "Masapul ti bersion $1 ti MediaWiki tapno maaramat daytoy a panid. \nKitaen ti [[Special:Version|panid ti bersion]].",
        "ok": "Sige",
        "retrievedfrom": "Naala manipud idiay \"$1\"",
-       "youhavenewmessages": "Addaanka ti $1 ($2).",
-       "youhavenewmessagesfromusers": "Adda $1 manipud {{PLURAL:$3|ti sabali nga agar-aramat|kadagiti $3 a sabsabali nga agar-aramat}} ($2).",
-       "youhavenewmessagesmanyusers": "Adda $1 manipud kadagiti adu nga agar-aramat ($2).",
-       "newmessageslinkplural": "{{PLURAL:$1|a baro a mensahem|999=a baro a menmensahem}}",
-       "newmessagesdifflinkplural": "kinaudi a {{PLURAL:$1|sinukatan|999=sinuksukatan}}",
-       "youhavenewmessagesmulti": "Adda dagiti baro a mensahem iti $1",
+       "youhavenewmessages": "{{PLURAL:$3|Addaanka}} $1 ($2).",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|Addaanka}} $1 manipud {{PLURAL:$3|ti sabali nga agar-aramat|kadagiti $3 a sabali nga agar-aramat}} ($2).",
+       "youhavenewmessagesmanyusers": "Addaanka $1 manipud kadagiti adu nga agar-aramat ($2).",
+       "newmessageslinkplural": "{{PLURAL:$1|iti baro a mensahe|999=kadagiti baro a mensahe}}",
+       "newmessagesdifflinkplural": "naudi a {{PLURAL:$1|sinukatan|999=sinuksukatan}}",
+       "youhavenewmessagesmulti": "Addaanka kadagiti baro a mensahe iti $1",
        "editsection": "urnosen",
        "editold": "urnosen",
        "viewsourceold": "kitaen ti taudan",
        "hidetoc": "ilemmeng",
        "collapsible-collapse": "Rebbaen",
        "collapsible-expand": "Palawaen",
-       "thisisdeleted": "Kitaen wenno isubli ti $1?",
-       "viewdeleted": "Kitaen ti $1?",
+       "thisisdeleted": "Kitaen wenno ipulang $1?",
+       "viewdeleted": "Kitaen $1?",
        "restorelink": "{{PLURAL:$1|ti maysa a naikkat a naurnos|dagiti $1 a naikkat a naurnos}}",
        "feedlinks": "Pakan:",
        "feed-invalid": "Imbalido a kita ti suskrision a pakan.",
        "feed-unavailable": "Saan a magun-od dagiti sindikasion ti pakan",
-       "site-rss-feed": "$1 a pakan ti RSS",
-       "site-atom-feed": "$1 a pakan ti Atom",
-       "page-rss-feed": "\"$1\" a pakan ti RSS",
-       "page-atom-feed": "Pakan nga Atom ti \"$1\"",
+       "site-rss-feed": "Pakan ti RSS ti $1",
+       "site-atom-feed": "Pakan ti Atom ti $1",
+       "page-rss-feed": "Pakan ti RSS ti \"$1\"",
+       "page-atom-feed": "Pakan ti Atom ti \"$1\"",
        "red-link-title": "$1 (awan ti panid)",
        "sort-descending": "Ilasin nga agpababa",
        "sort-ascending": "Ilasin nga agpangato",
        "nstab-help": "Panid ti tulong",
        "nstab-category": "Kategoria",
        "nosuchaction": "Awan ti kasta nga aramid",
-       "nosuchactiontext": "Ti tignay a nainaganan babaen ti URL ket imbalido.\nMabalin a madi ti naimakiniliam nga URL, wenno sinurotmo ti saan nga agpayso a silpo.\nMabalin a daytoy ket kiteb ti sopwer nga us-usaren babaen ti {{SITENAME}}.",
+       "nosuchactiontext": "Ti aramid a nainaganan babaen ti URL ket imbalido.\nMabalin a madi ti naimakiniliam nga URL, wenno sinurotmo ti saan a nasayaat a silpo.\nMabalinmo pay nga ibaga ti parikut ti sopwer nga us-usaren babaen ti {{SITENAME}}.",
        "nosuchspecialpage": "Awan ti kasta nga espesial a panid",
-       "nospecialpagetext": "<strong>Nagkiddawka ti imbalido nga espesial a panid.</strong>\n\nMasarakan ti listaan dagiti umisu nga espesial a pampanid iti [[Special:SpecialPages|{{int:specialpages}}]].",
+       "nospecialpagetext": "<strong>Nagkiddawka ti imbalido nga espesial a panid.</strong>\n\nTi listaan dagiti umisu nga espesial a pampanid ket mabirukan iti [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Biddut",
        "databaseerror": "Biddut iti database",
-       "databaseerror-text": "Adda napasamak a biddut ti usisa ti database.\nDaytoy ket mabalin a mangibagbaga ti parikut ti sopwer.",
-       "databaseerror-textcl": "Adda napasamak a biddut ti usisa ti database.",
+       "databaseerror-text": "Adda napasamak a biddut ti panagusisa ti database.\nDaytoy ket mabalin a mangibagbaga ti parikut ti sopwer.",
+       "databaseerror-textcl": "Adda napasamak a biddut ti pangusisa ti database.",
        "databaseerror-query": "Usisa: $1",
        "databaseerror-function": "Annong: $1",
        "databaseerror-error": "Biddut: $1",
-       "laggedslavemode": "'''Ballaag:''' Ti panid ket mabalin a saan nga aglaon kadagiti kinaudi a panagpabaro.",
+       "laggedslavemode": "<strong>Ballaag:</strong> Ti panid ket mabalin a saan nga aglaon kadagiti kinaudi a panagpabaro.",
        "readonly": "Narikepan ti database",
-       "enterlockreason": "Agikabil ti rason para iti pannakarikep, agraman ti maysa a karkulo no kaanonto a maluktan",
-       "readonlytext": "Ti database ket agdama a nairikpan kadagiti baro a panagikabil ken panagbaliw, mabalin a gapu dagiti kadawyan a pagsimpa, no malpas kadawyanto nga agsubli.\n\nTi administrador a nangrikep ket nangited ti daytoy a palawag: $1",
-       "missing-article": "Ti database ket saan a nakabiruk ti testo ti panid a mabirukanna koma, a napanaganan ti \"$1\" $2.\n\nDaytoy ket kadawyan a gapuanan babaen ti sumaganad a baak a paggiddiatan wenno silpo ti pakasaritaan ti maysa panid a dati a naikkat.\n\nNo saan a kasta, mabalin a nakasarakka ti kiteb ti sopwer.\n\nPangngaasi nga ipadamagmo kadagiti [[Special:ListUsers/sysop|administrador]], isuratmo ti pakaammo dayta nga URL.",
-       "missingarticle-rev": "(binaliwan#: $1)",
-       "missingarticle-diff": "(Sabali: $1, $2)",
-       "readonly_lag": "Automatiko a narikpan ti database kabayatan a dagiti tagabu a database server ket kumamakam iti agturay",
+       "enterlockreason": "Agikabil ti rason para iti pannakarikep, mangiraman ti maysa a karkulo no kaanonto a malukatan",
+       "readonlytext": "Ti database ket agdama a narikpan kadagiti baro a panagikabil ken panagbaliw, mabalin a gapu dagiti kadawyan a pagsimpa, kalpasanna a normalto nga agsubli.\n\nTi administrador a nangrikep ket nangited iti daytoy a palawag: $1",
+       "missing-article": "Ti database ket saan a nakabiruk ti testo ti panid a mabirukanna koma, a nanaganan ti \"$1\" $2.\n\nDaytoy ket kadawyan a gapuanan babaen ti sumaganad a baak a paggiddiatan wenno silpo ti pakasaritaan ti maysa panid a dati a naikkat.\n\nNo saan a kasta, mabalin a nakasarakka ti parikut ti sopwer.\n\nPangngaasi nga ipadamagmo kadagiti [[Special:ListUsers/sysop|administrador]], isuratmo ti pakaammo dayta nga URL.",
+       "missingarticle-rev": "(rebision#: $1)",
+       "missingarticle-diff": "(Dip: $1, $2)",
+       "readonly_lag": "Automatiko a narikpan ti database kabayatan a dagiti tagabu a server ti database ket kumamakam iti agturay",
        "internalerror": "Akin-uneg a biddut",
        "internalerror_info": "Akin-uneg a biddut: $1",
        "filecopyerror": "Saan a makopia ti papeles $1 iti $2.",
        "filerenameerror": "Saan a managanan manen ti papeles \"$1\" iti \"$2\".",
-       "filedeleteerror": "Saan a maikkat ti papeles  \"$1\".",
-       "directorycreateerror": "Saan a maaramid ti direktorio \"$1\".",
+       "filedeleteerror": "Saan a maikkat ti papeles \"$1\".",
+       "directorycreateerror": "Saan a mapartuat ti direktorio \"$1\".",
        "filenotfound": "Saan a mabirukan ti papeles \"$1\".",
-       "unexpected": "Di mapakpakadaaan a pateg: \"$1\"=\"$2\".",
+       "unexpected": "Di nanamnama a pateg: \"$1\"=\"$2\".",
        "formerror": "Biddut: saan a maited ti porma.",
        "badarticleerror": "Saan a matungpal daytoy nga aramid iti daytoy a panid.",
-       "cannotdelete": "Ti panid wenno ti papeles \"$1\" ket saan a maikkat.\nAmangan no adda sabali a nangikkaten.",
-       "cannotdelete-title": "Saan a maikkat ti panid  \"$1\"",
-       "delete-hook-aborted": "Inukas ti kawit ti panagborra.\nAwan ti intedna a palawag.",
-       "no-null-revision": "Saan a makaaramid ti awan serbina a panagbaliw para iti panid \"$1\"",
+       "cannotdelete": "Ti panid wenno papeles ti \"$1\" ket saan a maikkat.\nAmangan no adda sabali a nangikkaten.",
+       "cannotdelete-title": "Saan a maikkat ti panid ti \"$1\"",
+       "delete-hook-aborted": "Pinasardeng ti panagikkat babaen ti kawit.\nAwan ti intedna a palawag.",
+       "no-null-revision": "Saan a makapartuat ti awan serbina a panagbaliw para iti panid ti \"$1\"",
        "badtitle": "Madi a titulo",
-       "badtitletext": "Ti kiniddaw idi a titulo ti panid ket imbalido, blanko, wenno maysa a saan nga husto a naisilpo a silpo ti pagsasao wenno interwiki a titulo.\nMabalin nga aglaon ti a maysa wenno ad-adu a karakter a saan a mausar kadagiti titulo.",
+       "badtitletext": "Ti kiniddaw idi a titulo ti panid ket imbalido, blanko, wenno maysa a saan a husto a naisilpo a silpo ti pagsasao wenno interwiki a titulo.\nMabalin nga aglaon ti a maysa wenno ad-adu a karakter a saan a mausar kadagiti titulo.",
        "perfcached": "Ti sumaganad a datos ket naidulin ken mabalin a saan a napabaro. Ti kaadu {{PLURAL:$1|iti maysa a nagbanagan|dagiti $1 a nagbanagan}} ket magun-od idiay nagidulinan.",
-       "perfcachedts": "Ti sumaganad a datos ket naidulin, ken naudi a napabaro idi $1. Ti kaadu a {{PLURAL:$4|iti maysa a nagbanagan |dagiti $4 nagbanagan}} ket magun-od idiay pagidulinan.",
-       "querypage-no-updates": "Dagiti panangpabaro iti daytoy a panid ket agdama a nabaldado. \nSaan a mipasaradiwa ita dagiti datos ditoy.",
+       "perfcachedts": "Ti sumaganad a datos ket naidulin, ken naudi a napabaro idi $1. Ti kaadu {{PLURAL:$4|iti maysa a nagbanagan|kadagiti $4 a nagbanagan}} ket magun-od iti pagidulinan.",
+       "querypage-no-updates": "Dagiti panangpabaro iti daytoy a panid ket agdama a nabaldado. \nSaan a mapasadiwa ita dagiti datos ditoy.",
        "viewsource": "Kitaen ti taudan",
        "viewsource-title": "Kitaen ti taudan para iti $1",
        "actionthrottled": "Napabuntog ti aramid",
        "actionthrottledtext": "Para iti pagkontra ti spam, naipatinggaka nga agramid iti daytoy a tignay iti adu unay a beses iti nasiket nga oras, ken nalabsamon daytoy a patingga.\nPangngaasi nga ipadasmo manen no madamdama.",
        "protectedpagetext": "Nasalakniban daytoy a panid tapno mapawilan ti panag-urnos wenno dagiti dadduma pay a tignay.",
        "viewsourcetext": "Mabalinmo a kitaen ken tuladen ti taudan daytoy a panid:",
-       "viewyourtext": "Mabalinmo a makita ken tuladen ti taudan dagiti '''inurnosmo''' ditoy a panid:",
-       "protectedinterface": "Daytoy a panid ket mangited ti testo nga interface para iti sopwer iti daytoy a wiki, ken nasalakniban tapno mapawilan ti panag-abuso.\nTi aginayon wenno panagibaliw kadagiti panagipatarus para kadagiti amin a wiki,  pangngaasi nga usaren ti [//translatewiki.net/ translatewiki.net], ti lokalisasion a gandat ti MediaWiki.",
-       "editinginterface": "'''Ballaag:''' Ur-urnosem ti maysa a panid a maar-aramat a mangted iti testo ti interface para iti sopwer.\nDagiti panagsukat iti daytoy a panid ket maarigan ti langa ti panagaramat nga interface dagiti sabali nga agar-aramat iti daytoy a wiki.\nTi aginayon wenno panagibaliw kadagiti panagipatarus para kadagiti amin a wiki,  pangngaasi nga usaren ti [//translatewiki.net/ translatewiki.net], ti lokalisasion a gandat ti MediaWiki.",
-       "cascadeprotected": "Daytoy a panid ket nasalakniban para iti panag-urnos ngamin ket nairaman kadagiti sumaganad {{PLURAL:$1|a panid, a|a pampanid, a}} nasalakniban nga adda ti napili nga \"agsariap\"  :\n$2",
-       "namespaceprotected": "Awan ti pammalubosmo nga agurnos kadagiti panid iti '''$1''' a nagan ti espasio.",
-       "customcssprotected": "Awan ti pammalubosmo nga agurnos iti daytoy panid ti CSS, ngamin ket adda linaonna a tagikua dagiti agar-aramat ti sabali a kasasaad.",
-       "customjsprotected": "Awan ti pammalubosmo nga agurnos iti daytoy a panid ti JavaScript, ngamin ket adda linaonna a tagikua dagiti agar-aramat ti sabali a kasasaad.",
+       "viewyourtext": "Mabalinmo a makita ken tuladen ti taudan dagiti <strong>inurnosmo</strong> iti daytoy panid:",
+       "protectedinterface": "Daytoy a panid ket mangited ti testo ti interface para iti sopwer iti daytoy a wiki, ken nasalakniban tapno mapawilan ti panag-abuso.\nTi aginayon wenno panagibaliw kadagiti panagipatarus para kadagiti amin a wiki,  pangngaasi nga usaren ti [//translatewiki.net/ translatewiki.net], ti lokalisasion a gandat ti MediaWiki.",
+       "editinginterface": "<strong>Ballaag:</strong> Ur-urnosem ti maysa a panid a maar-aramat a mangted iti testo ti interface para iti sopwer.\nDagiti panagsukat iti daytoy a panid ket maarigan ti langa ti interface ti agar-aramat para kadagiti sabali nga agar-aramat iti daytoy a wiki.\nTi aginayon wenno panagibaliw kadagiti panagipatarus para kadagiti amin a wiki,  pangngaasi nga usaren ti [//translatewiki.net/ translatewiki.net], ti lokalisasion a gandat ti MediaWiki.",
+       "cascadeprotected": "Daytoy a panid ket nasalaknibanen para iti panag-urnos ngamin ket nairaman kadagiti sumaganad {{PLURAL:$1|a panid, a|a pampanid, a}} nasalakniban iti nalukatan a pagpilian ti \"sariap\":\n$2",
+       "namespaceprotected": "Awan ti pammalubosmo nga agurnos kadagiti panid iti nagan ti espasio ti <strong>$1</strong>.",
+       "customcssprotected": "Awan ti pammalubosmo nga agurnos iti daytoy panid ti CSS, ngamin ket naglaon ti personal a pannakaisaad iti sabali agar-aramat.",
+       "customjsprotected": "Awan ti pammalubosmo nga agurnos iti daytoy a panid ti JavaScript, ngamin ket naglaon ti personal a pannakaisaad iti sabali agar-aramat.",
        "mycustomcssprotected": "Awan pammalubosmo nga agurnos iti daytoy a panid ti CSS.",
        "mycustomjsprotected": "Awan pammalubosmo nga agurnos iti daytoy a panid ti JavaScript.",
        "myprivateinfoprotected": "Awan pammalubosmo nga agurnos iti pribado a pakaammom.",
        "mypreferencesprotected": "Awan pammalubosmo nga agurnos kadagiti kakaykayatam.",
        "ns-specialprotected": "Saan a mabalin nga urnosen dagiti espesial a panid.",
-       "titleprotected": "Daytoy a titulo ket nasalakniban manipud ti panakapartuat babaen ni [[User:$1|$1]].\nTi naited a rason ket ''$2''.",
-       "filereadonlyerror": "Di nabaliwan ti papeles \"$1\" gapu ket ti repositorio ti papeles \"$2\" ket mabasa laeng a moda.\n\nTi administrador a nangserra ket nagited iti daytoy a panagilawlawag \"''$3''\".",
+       "titleprotected": "Daytoy a titulo ket nasalakniban manipud ti pannakapartuat babaen ni [[User:$1|$1]].\nTi naited a rason ket \"<em>$2</em>\".",
+       "filereadonlyerror": "Di nabaliwan ti papeles ti \"$1\" gapu ket ti repositorio ti papeles ti \"$2\" ket mabasa laeng a moda.\n\nTi administrador a nangserra ket nangited iti daytoy a panagilawlawag \"''$3''\".",
        "invalidtitle-knownnamespace": "Imbalido a titulo iti nagan ti espasio \"$2\" ken testo \"$3\"",
-       "invalidtitle-unknownnamespace": "Imbalido a titulo iti di-amammo a nagan ti espasio a numero $1 ken testo \"$2\"",
+       "invalidtitle-unknownnamespace": "Imbalido a titulo iti di ammo a nagan ti espasio a bilang $1 ken testo \"$2\"",
        "exception-nologin": "Saan a nakastrek",
        "exception-nologin-text": "Pangngaasi a [[Special:Userlogin|sumrek]] tapno maserrekam daytoy a panid wenno tignay.",
        "exception-nologin-text-manual": "Pangngaasi a $1 tapno maserrekan daytoy a panid wenno tignay.",
-       "virus-badscanner": "Madi di panaka-aramidna: Di am-ammo a birus a panagskan: \"$1\"",
-       "virus-scanfailed": "napaay ti panagskan (kodigo $1)",
-       "virus-unknownscanner": "di am-ammo a pagpaksiat ti \"birus\":",
-       "logouttext": "'''Nakaruarkan.'''\n\nLaglagipen nga adda met dagiti panid nga agtultuloy a maiparang a kasla nakastreka pay, aginggana no dalusam ti pannakaidulin ti pagbasabasam.",
+       "virus-badscanner": "Madi ti konpigurasion: Di ammo a panagsukimat ti birus: <em>$1</em>",
+       "virus-scanfailed": "napaay ti panagsukimat (kodigo $1)",
+       "virus-unknownscanner": "di ammmo nga antibirus:",
+       "logouttext": "<strong>Nakaruarkan.</strong>\n\nLaglagipen nga adda met dagiti panid nga agtultuloy a maiparang a kasla nakastrekka pay, aginggana no dalusam ti pannakaidulin ti pagbasabasam.",
        "welcomeuser": "Naragsak nga isasangbay, $1!",
-       "welcomecreation-msg": "Naaramiden ti pakabilangam.\nDimo liplipatan a sukatan dagiti kakaykayatam idiay [[Special:Preferences|{{SITENAME}} kakaykayatan]].",
+       "welcomecreation-msg": "Napartuaten ti pakabilangam.\nNo kayatmo mabaliwamon dagiti [[Special:Preferences|kakaykayatam]] ti {{SITENAME}}.",
        "yourname": "Nagan ti agar-aramat:",
        "userlogin-yourname": "Nagan ti agar-aramat",
        "userlogin-yourname-ph": "Ikabil ti naganmo nga agar-aramat",
        "yourpassword": "Kontrasenias:",
        "userlogin-yourpassword": "Kontrasenias",
        "userlogin-yourpassword-ph": "Ikabilmo ti kontrasenias",
-       "createacct-yourpassword-ph": "Agikabil ti kontrasenias",
-       "yourpasswordagain": "Uliten ti kontrasenias:",
+       "createacct-yourpassword-ph": "Ikabil ti kontrasenias",
+       "yourpasswordagain": "Imakinilya manen ti kontrasenias:",
        "createacct-yourpasswordagain": "Pasingkedan ti kontrasenias",
        "createacct-yourpasswordagain-ph": "Ikabil manen ti kontrasenias",
        "remembermypassword": "Laglagipem ti iseserrekko iti daytoy a pagbasabasa (para iti kapaut iti $1 {{PLURAL:$1|nga aldaw|nga al-aldaw}})",
        "userlogin-remembermypassword": "Taginayonennak nga iserrek",
-       "userlogin-signwithsecure": "Usaren ti natalged a pannakaisilpo",
-       "yourdomainname": "Ti bukodmo a pagturayan:",
-       "password-change-forbidden": "Saanmo a mabalin ti mangbaliw kadagiti kontrasenias iti daytoy a wiki.",
-       "externaldberror": "Adda biddut idi ti panakapasingked ti database wenno saanmo a mabalin ti agpabaro ti bukodmo nga akin-ruar a pakabilangan.",
+       "userlogin-signwithsecure": "Usaren ti natalged a koneksion",
+       "yourdomainname": "Ti bukodmo a dominio:",
+       "password-change-forbidden": "Saanmo a mabaliwan dagiti kontrasenias iti daytoy a wiki.",
+       "externaldberror": "Mabalin nga adda biddut iti pannakapasingked ti database wenno saanka a mapalubosan a mangpabaro ti akin-ruar a pakabilangam.",
        "login": "Sumrek",
-       "nav-login-createaccount": "Sumrek / agaramid ti pakabilangan",
-       "loginprompt": "Nasken a napakabaelam dagiti \"galietas\" tapno makastrekka iti {{SITENAME}}.",
-       "userlogin": "Sumrek / agaramid ti pakabilangan",
+       "nav-login-createaccount": "Sumrek / agpartuat ti pakabilangan",
+       "userlogin": "Sumrek / agpartuat ti pakabilangan",
        "userloginnocreate": "Sumrek",
        "logout": "Rummuar",
        "userlogout": "Rummuar",
        "userlogin-noaccount": "Awan ti pakabilangam?",
        "userlogin-joinproject": "Tumipon iti {{SITENAME}}",
        "nologin": "Awan pakabilangam? $1.",
-       "nologinlink": "Agaramid ti pakabilangan",
-       "createaccount": "Agaramid ti pakabilangan",
-       "gotaccount": "Addaanka kadin ti pakabilangam? $1.",
+       "nologinlink": "Agpartuat ti pakabilangan",
+       "createaccount": "Agpartuat ti pakabilangan",
+       "gotaccount": "Addaanka kadin iti pakabilangan? $1.",
        "gotaccountlink": "Sumrek",
-       "userlogin-resetlink": "Nalipatam dagiti salaysay ti pagserrekmo?",
+       "userlogin-resetlink": "Nalipatam dagiti salaysay ti panagserrekmo?",
        "userlogin-resetpassword-link": "Nalipatam ti kontraseniasmo?",
        "userlogin-helplink2": "Tulong iti panagserrek",
        "userlogin-loggedin": "Nakastrekkan a kas ni {{GENDER:$1|$1}}.\nUsaren ti porma dita baba tapno sumrek a kas sabali nga agar-aramat.",
-       "userlogin-createanother": "Agaramid pay ti sabali a pakabilangan",
+       "userlogin-createanother": "Agpartuat ti sabali a pakabilangan",
        "createacct-emailrequired": "Esurat a pagtaengan",
        "createacct-emailoptional": "Esurat a pagtaengan (pagpilian)",
        "createacct-email-ph": "Ikabil ti esurat a pagtaengam",
        "createacct-another-email-ph": "Ikabil ti esurat a pagtaengan",
-       "createaccountmail": "Agusar ti pugto a temporario a kontrasenias ken ipatulod idiay naisangayan nga esurat a pagtaengan",
+       "createaccountmail": "Agusar ti pugto a temporario a kontrasenias ken ipatulod iti naisangayan nga esurat a pagtaengan",
        "createacct-realname": "Pudno a nagan (pagpilian)",
        "createaccountreason": "Rason:",
        "createacct-reason": "Rason",
        "createacct-reason-ph": "Apay nga agparpartuatka manen ti sabali a pakabilangan",
-       "createacct-captcha": "Panagkita ti seguridad",
+       "createacct-captcha": "Panagpatalged ti seguridad",
        "createacct-imgcaptcha-ph": "Ikabil ti testo a makitam dita ngato",
        "createacct-submit": "Partuatem ti pakabilangam",
-       "createacct-another-submit": "Agaramid pay ti sabali a pakabilangan",
+       "createacct-another-submit": "Agpartuat ti sabali a pakabilangan",
        "createacct-benefit-heading": "Ti {{SITENAME}} ket inar-aramid babaen ti tattao a kasla kenka.",
        "createacct-benefit-body1": "{{PLURAL:$1|nga inurnos|nga inur-urnos}}",
        "createacct-benefit-body2": "{{PLURAL:$1|a panid|a pampanid}}",
        "createacct-benefit-body3": "nga agdama a {{PLURAL:$1|nagparawad|nagparparawad}}",
        "badretype": "Saan nga agpada dagiti inkabilmo a kontrasenias.",
-       "userexists": "Maus-usaren ti inkabilmo a nagan.\nPangngaasi nga agpilika ti sabali a nagan.",
+       "userexists": "Maus-usaren ti inkabilmo a nagan.\nPangngaasi nga agpilika iti sabali a nagan.",
        "loginerror": "Biddut ti iseserrek",
        "createacct-error": "Biddut ti panagpartuat ti pakabilangan",
-       "createaccounterror": "Saan a makaaramid ti pakabilangan: $1",
-       "nocookiesnew": "Naaramid ti pakabilangan ti agar-aramat, ngem saanka a nakastrek.\nTi {{SITENAME}} ket agus-usar kadagiti \"galietas\" tapno maiserrek dagiti agar-aramat.\nNabaldado dagiti galietam.\nPangngaasi a pakabaelam ida, ken sumrekka nga agusar ti baro a naganmo ken kontrasenias.",
+       "createaccounterror": "Saan a makapartuat ti pakabilangan: $1",
+       "nocookiesnew": "Napartuaten ti pakabilangan ti agar-aramat, ngem saanka a nakastrek.\nTi {{SITENAME}} ket agus-usar kadagiti galietas tapno maiserrek dagiti agar-aramat.\nNabaldado dagiti galietam.\nPangngaasi a pakabaelam ida, ken sumrekka nga agusar iti baro a naganmo ken kontrasenias.",
        "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 naaramid, saanmi a mapasingkedan ti taudanna.\nSiguraduem a napakabaelan dagita galietam, ikargam manen daytoy a panid ken padasem manen.",
-       "noname": "Saanmo a nainaganan ti agpayso a nagan ti agar-aramat.",
+       "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",
-       "loginsuccess": "'''Nakastrekkan iti {{SITENAME}} a kas ni \"$1\".'''",
-       "nosuchuser": "Awan ti agar-aramat nga agnagan iti \"$1\". \n\nDagiti nagan ti agar-aramat ket sensitibo ti kadakkel ti letra.\n\nKitaem ti panangiletra, wenno [[Special:UserLogin/signup|agaramidka ti baro a pakabilangan]].",
+       "loginsuccess": "<strong>Nakastrekkan iti {{SITENAME}} a kas ni \"$1\".</strong>",
+       "nosuchuser": "Awan ti agar-aramat nga agnagan ti \"$1\". \n\nDagiti nagan ti agar-aramat ket sensitibo ti kadakkel ti letra.\n\nKitaem ti panangiletram, wenno [[Special:UserLogin/signup|agpartuat ti baro a pakabilangan]].",
        "nosuchusershort": "Awan ti agar-aramat nga agnagan ti \"$1\".\nKitaem ti panangiletram.",
-       "nouserspecified": "Nasken nga agikabilka ti nagan ti agar-aramat.",
+       "nouserspecified": "Nasken nga inaganam ti nagan ti agar-aramat.",
        "login-userblocked": "Naserraan daytoy nga agar-aramat. Saan a mapalubosan ti sumrek.",
-       "wrongpassword": "Saan a husto ti naikabil a kontrasenias. \nPangngaasi a padasem manen.",
-       "wrongpasswordempty": "Blanko ti naikabil a kontrasenias. \nPangngaasi a padasem manen.",
+       "wrongpassword": "Saan a husto ti naikabil a kontrasenias. \nPangngaasi a padasen manen.",
+       "wrongpasswordempty": "Blanko ti naikabil a kontrasenias. \nPangngaasi a padasen manen.",
        "passwordtooshort": "Dagiti kontrasenias ket nasken a saan a basbasit ngem {{PLURAL:$1|1 a karakter|$1 a karkarakter}}.",
        "password-name-match": "Nasken a ti kontrasenias ket maigiddiat manipud ti naganmo.",
-       "password-login-forbidden": "Ti panag-usar ti daytoy a nagan ti agar-aramat ken kontrasenias ket naipariten.",
-       "mailmypassword": "Iyasentar manen ti kontrasenias",
+       "password-login-forbidden": "Ti panag-usar iti daytoy a nagan ti agar-aramat ken kontrasenias ket naipariten.",
+       "mailmypassword": "Isaad manen ti kontrasenias",
        "passwordremindertitle": "Baro a temporario a kontrasenias para iti {{SITENAME}}",
-       "passwordremindertext": "Adda maysa a tao (mabalin a sika met laeng, manipud iti IP a pagtaengan a $1) ket nagkiddaw ti baro\na kontrasenias para iti {{SITENAME}} ($4). Ti saan nga agnayon a kontrasenias ti agususar\n\"$2\" ket naaramiden ken naidisso iti \"$3\". No kastan ti kinayatmo,\nmasapul a sumrek ka ta agpili ka ti baro a kontrasenias.\nTi temporario a bukodmo a kontrasenias ket agpaso  {{PLURAL:$5|iti maysa nga aldaw|kadagiti $5 nga aldaw}}.\n\nNo sabali ti nagkiddaw, wenno no malagipmo pay ti kontrasenias mo ket dimon kayat a suktan daytoy, mabalin a dimo lattan ikaskaso daytoy a mensahe ket itultuloymo latta nga usaren ti daan a kontrasenias.",
-       "noemail": "Awan ti esurat a pagtaengan a nairehistro para  iti agar-aramat a ni \"$1\".",
+       "passwordremindertext": "Adda maysa a tao (mabalin a sika met laeng, manipud iti IP a pagtaengan a $1) ket nagkiddaw ti baro a kontrasenias para iti {{SITENAME}} ($4). Ti temporario a kontrasenias para kenni agar-aramat \"$2\" ket napartuaten ken naisaad iti \"$3\". No kastan ti kinayatmo, nasken itan a sumrekka ken agpili ti baro a kontrasenias.\nTi temporario a kontraseniasmo ket agpaso {{PLURAL:$5|iti maysa nga aldaw|kadagiti $5 nga aldaw}}.\n\nNo sabali ti nagkiddaw, wenno nalagipmon ti kontraseniasmo,\nken dimo kayaten a sukatan daytoy, mabalinmo a di ikaskaso daytoy a mensahe ken agtuloy nga usaren ti daan a kontraseniasmo.",
+       "noemail": "Awan ti esurat a pagtaengan a nairehistro para iti agar-aramat a ni \"$1\".",
        "noemailcreate": "Nasken a mangitedka ti pudno nga esurat a pagtaengan.",
        "passwordsent": "Naipatuloden ti baro a kontrasenias iti esurat a pagtaengan a nairehistro kenni \"$1\".\nPangngaasi a sumrekka manen kalpasan ti pannakaawatmo.",
-       "blocked-mailpassword": "Ti IP a pagtaengam ket naserraan manipud ti panag-urnos, isunga saan a mapalubosan nga agusar ti annong ti panagipulang ti kontrasenias tapno mapawilan ti panag-abuso.",
+       "blocked-mailpassword": "Ti IP a pagtaengam ket naserraan manipud ti panag-urnos, ken isu a saan a mapalubosan nga agusar ti annong ti panagipulang ti kontrasenias tapno mapawilan ti panag-abuso.",
        "eauthentsent": "Naipatuloden ti pammatalged nga esurat iti naikeddeng nga esurat a pagtaengan.\nSakbay a maipatulod ti aniaman nga esurat iti pakabilangan, masapul a surotem dagiti maibagbaga iti esurat, tapno mapatalgedan ti pakabilangan ket agpayso a kukuam.",
-       "throttled-mailpassword": "Ti panangiyasentar manen ti kontrasenias ket naipatuloden, iti kaunegan ti napalabas a {{PLURAL:$1|nga oras|$1 nga or-oras}}.\nTapno maipawilan ti panag-abuso, maysa laeng a panangiyasentar manen ti kontrasenias ti maipatulod iti kada {{PLURAL:$1|nga oras|$1 nga or-oras}}.",
+       "throttled-mailpassword": "Ti panangisaad manen ti kontrasenias ket naipatuloden, iti kaunegan ti napalabas a {{PLURAL:$1|nga oras|$1 nga or-oras}}.\nTapno maipawilan ti panag-abuso, maysa laeng a panangisaad manen ti kontrasenias ti maipatulod iti kada {{PLURAL:$1|nga oras|$1 nga or-oras}}.",
        "mailerror": "Biddut iti panangipatulod ti surat: $1",
-       "acct_creation_throttle_hit": "Dagiti sumarungkar ti daytoy a wiki nga agus-usar ti IP a pagtaengan ket nakaaramid {{PLURAL:$1|iti 1 a pakabilangan|kadagiti $1 a pakabilangan}} iti nasakbayan nga aldaw, nga isu laeng ti kaadu a maipalubos iti daytoy a paset ti panawen.\nA kas ti nagbanagan, dagiti agsarsarungkar nga agus-usar ti IP a pagtaengan ket agdama a saanda a mabalin a makaaramid kadagiti pakabilangan.",
-       "emailauthenticated": "Ti esurat a pagtaengam ket napatalgedan idi $2 idi $3.",
+       "acct_creation_throttle_hit": "Dagiti sumarungkar iti daytoy a wiki nga agus-usar ti IP a pagtaengan ket nakapartuat {{PLURAL:$1|iti 1 a pakabilangan|kadagiti $1 a pakabilangan}} iti nasakbayan nga aldaw, nga isu laeng ti kaadu a maipalubos iti daytoy a paset ti panawen.\nA kas ti nagbanagan, dagiti agsarsarungkar nga agus-usar ti IP a pagtaengan ket agdama a saanda a mabalin a makapartuat kadagiti pakabilangan.",
+       "emailauthenticated": "Ti esurat a pagtaengam ket napatalgedan idi $2, $3.",
        "emailnotauthenticated": "Saan pay a napatalgedan ti esuratmo a pagtaengan.\nAwanto ti esurat a maipatulod para kadagiti sumaganad a langa.",
        "noemailprefs": "Ipanaganan ti esurat a pagtaengan tapno agbalin dagitoy a langa.",
        "emailconfirmlink": "Pasingkedam ti esurat a pagtaengam",
        "invalidemailaddress": "Ti esurat a pagtaengan ket saan a maawat ngamin ket kasla adda ti saan a napudno a porma.\nPangngaasi nga agikabil ti nasayaat a porma ti pagtaengan wenno ikkaten amin a naikabil.",
        "cannotchangeemail": "Dagiti pakabilangan nga esurat a pagtaengan ket saan a mabaliwan iti daytoy a wiki.",
-       "emaildisabled": "Daytoy a pagsaaadan ket saan a makaipatulod kadagiti esurat.",
-       "accountcreated": "Naaramiden ti pakabilangan",
+       "emaildisabled": "Daytoy a sitio ket saan a makaipatulod kadagiti esurat.",
+       "accountcreated": "Napartuaten ti pakabilangan",
        "accountcreatedtext": "Ti pakabilangan ti agar-aramat para kenni [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|tungtungan]]) ket napartuaten.",
-       "createaccount-title": "Panagaramid ti pakabilangan para iti {{SITENAME}}",
-       "createaccount-text": "Adda nagaramid ti pakabilangan para iti esurat a pagtaengam idiay {{SITENAME}} ($4) nga agnagan  ti \"$2\", iti kontrasenias a \"$3\".\nNasken a sumrekka ken sukatam ti kontraseniasmo tattan.\n\nMabalinmo ti saan a mangikaskaso ti daytoy a mensahe, no biddut a naaramid daytoy a pakabilangan.",
-       "login-throttled": "Adu unay ti panagpadasmo a sumrek.\nPangngaasi nga agurayka ti $1 sakbay a padasem manen.",
+       "createaccount-title": "Panagpartuat ti pakabilangan para iti {{SITENAME}}",
+       "createaccount-text": "Adda nagpartuat ti pakabilangan para iti esurat a pagtaengam iti {{SITENAME}} ($4) nga agnagan  ti \"$2\", iti kontrasenias a \"$3\".\nNasken a sumrekka ken sukatam ti kontraseniasmo tattan.\n\nMabalinmo ti saan a mangikaskaso iti daytoy a mensahe, no biddut a naaramid daytoy a pakabilangan.",
+       "login-throttled": "Adu unay ti panagpadasmo a sumrek.\nPangngaasi nga agurayka ti $1 sakbay a padasen manen.",
        "login-abort-generic": "Napaay ti panagserrekmo - Napasardeng",
        "loginlanguagelabel": "Pagsasao: $1",
        "suspicious-userlogout": "Naiparit ti panagkiddawmo a rummuar ngamin ket kasla inpatulod ti nadadael a panagbasabasa wenno pannakaidulin a pannakbagi.",
        "createacct-another-realname-tip": "Saan a nasken ti pudno a nagan.\nNo kayatmo nga ited, mausarto daytoy para iti panangited ti pammadayaw para kadagiti obrada.",
        "pt-login": "Sumrek",
        "pt-login-button": "Sumrek",
-       "pt-createaccount": "Agaramid ti pakabilangan",
+       "pt-createaccount": "Agpartuat ti pakabilangan",
        "pt-userlogout": "Rummuar",
-       "php-mail-error-unknown": "Di ammo a biddut ti surat ti PHP() nga annong.",
-       "user-mail-no-addy": "Pinadas nga inpatulod ti esurat nga awan ti esurat a pagtaengan.",
-       "user-mail-no-body": "Pinadas nga inpatulod ti esurat nga awan linaonna wenno ababa laeng a bagi.",
+       "php-mail-error-unknown": "Di ammo a biddut iti surat ti annong ti PHP().",
+       "user-mail-no-addy": "Pinadas nga inpatulod ti esurat nga awan ti maysa nga esurat a pagtaengan.",
+       "user-mail-no-body": "Pinadas nga inpatulod ti esurat nga awan ti maysa a linaonna wenno ababa unay a bagi.",
        "changepassword": "Baliwan ti kontrasenias",
-       "resetpass_announce": "Tapno malpas ti panagserrek, nasken a mangiyasentarka ti baro a kontrasenias.",
+       "resetpass_announce": "Tapno malpas ti panagserrek, nasken a mangisaadka ti baro a kontrasenias.",
        "resetpass_header": "Sukatan ti kontrasenias ti pakabilangan",
        "oldpassword": "Daan a kontrasenias:",
        "newpassword": "Baro a kontrasenias:",
        "retypenew": "Imakinilya manen ti baro a kontrasenias:",
-       "resetpass_submit": "Ikabil ti kontrasenias ken sumrek",
+       "resetpass_submit": "Isaad ti kontrasenias ken sumrek",
        "changepassword-success": "Balligi a nasukatan ti kontraseniasmo!",
        "changepassword-throttled": "Nakaaramidka kadagiti adu unay a nabiit a panangipadas ti panagserrek.\nPangngaasi nga aguray ti $1 sakbay a padasen manen.",
        "resetpass_forbidden": "Saan a masukatan dagiti kontrasenias",
        "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-recycled": "Pangngaasi nga iyasentar 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 mangiyasentarka ti baro a kontrasenias ditoy:",
+       "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:",
        "resetpass-abort-generic": "Ti panagsukat ti kontrasenias ket pinasardeng babaen ti maysa a pagpaatiddog.",
-       "resetpass-expired": "Nagpason ti kontraseniasmo. Pangngaasi a mangiyasentar ti baro a kontrasenias tapno makastrek.",
-       "resetpass-expired-soft": "Nagpason ti kontraseniasmo, ken nasken a maiyasentar manen. Pangngaasi nga agpili tattan ti baro a kontrasenias, wenno pinduten ti \"{{int:resetpass-submit-cancel}}\"  tapno maiyasentarto intono madamdama.",
-       "resetpass-validity-soft": "Saan nga umiso ti kontraseniasmo: $1\n\nAgpilika tattan ti baro a kontrasenias, wenno pinduten ti \"{{int:resetpass-submit-cancel}}\" tapno isaad intono madamdama.",
-       "passwordreset": "Iyasentar manen ti kontrasenias",
-       "passwordreset-text-one": "Lippasem daytoy a porma tapno maiyasentar manen ti bukodmo a kontrasenias.",
+       "resetpass-expired": "Nagpason ti kontraseniasmo. Pangngaasi a mangisaad ti baro a kontrasenias tapno makastrek.",
+       "resetpass-expired-soft": "Nagpason ti kontraseniasmo, ken nasken a maisaad manen. Pangngaasi nga agpili tattan ti baro a kontrasenias, wenno pinduten ti \"{{int:resetpass-submit-cancel}}\"  tapno maisaad intono madamdama.",
+       "resetpass-validity-soft": "Saan nga umiso ti kontraseniasmo: $1\n\nAgpilika tattan ti baro a kontrasenias, wenno pinduten ti \"{{int:resetpass-submit-cancel}}\" tapno maisaad intono madamdama.",
+       "passwordreset": "Isaad manen ti kontrasenias",
+       "passwordreset-text-one": "Kompletuen daytoy a porma tapno makaawat iti temporario a kontrasenias babaen ti esurat.",
        "passwordreset-text-many": "{{PLURAL:$1|Agpunno ti maysa kadagiti pagikabilan tapno makaawat ti temporario a kontrasenias babaen ti esurat.}}",
-       "passwordreset-legend": "Iyasentar manen ti kontrasenias",
-       "passwordreset-disabled": "Nabaldado dagiti panangiyasentar manen ti kontrasenias iti daytoy a wiki.",
+       "passwordreset-legend": "Isaad manen ti kontrasenias",
+       "passwordreset-disabled": "Nabaldado dagiti panangisaad manen ti kontrasenias iti daytoy a wiki.",
        "passwordreset-emaildisabled": "Dagiti langa ti esurat ket nabaldado iti daytoy a wiki.",
        "passwordreset-username": "Nagan ti agar-aramat:",
-       "passwordreset-domain": "Pagturayan:",
-       "passwordreset-capture": "Kitaen ti nagbanagan ti esurat?",
-       "passwordreset-capture-help": "No markaam daytoy a kahon, ti esurat (nga adda ti temporario a kontrasenias) ket maipakita kenka ken maipatulod iti agar-aramat.",
+       "passwordreset-domain": "Dominio:",
+       "passwordreset-capture": "Kitaen ti nagbanagan nga esurat?",
+       "passwordreset-capture-help": "No markaam daytoy a kahon, ti esurat (nga adda ti temporario a kontrasenias) ket maipakitanto kenka ken maipatulodto iti agar-aramat.",
        "passwordreset-email": "Esurat a pagtaengan:",
-       "passwordreset-emailtitle": "Salaysay ti pakabilangan iti {{SITENAME}}",
-       "passwordreset-emailtext-ip": "Adda (baka sika, ti naggapuan ti IP a pagtaengan $1) a nagkiddaw ti maysa a panangiyasentar manen ti kontrasenias para iti {{SITNAME}} ($4) . {{PLURAL:$3|Ti |Dagiti}} sumaganad a pakabilangan ti agar-aramat ket\nnakairaman iti daytoy nga esurat a pagtaengan:\n\n$2\n\n{{PLURAL:$3|Daytoy temporario a kontrasenias|Dagitoy temporario a kontrasenias}} ket agpaso {{PLURAL:$5|iti maysa nga aldaw|kadagiti $5 nga aldaw}}.\nSumrekka koman tapno agpilika ti baro a kontraseniasmo tattan. No adda met sabali a nagaramid daytoy a \npanagkiddaw, wenno malagipmo ti dati a kontraseniasmo, ket saanmo a kayaten a sukatan, saanmo nga ikaskaso daytoy a mensahe ken \nagtuloyka nga agusar ti daan a kontrasenias.",
-       "passwordreset-emailtext-user": "Daytoy nga agar-aramat $1 iti {{SITENAME}} ket nagkiddaw ti maysa a panangiyasentar manen ti bukod a kontrasenias para iti {{SITENAME}}\n($4) . {{PLURAL:$3|Ti|Dagiti}} sumaganad a pakabilanagan ti agar-aramat ket\nnakairaman iti daytoy nga esurat a pagtaengan:\n\n$2\n\n{{PLURAL:$3|Daytoy temporario a kontrasenias|Dagitoy temporario a kontrasenias}} ket agpaso {{PLURAL:$5|iti maysa nga aldaw|kadagiti $5 nga aldaw}}.\nSumrekka koman tapno agpili ka ti baro a kontraseniasmo tattan. No adda met sabali a nagaramid daytoy a \npanagkiddaw, wenno malagipmo ti dati a kontraseniasmo, ket saan mo a kayaten a sukatan, saanmo nga ikaskaso daytoy a mensahe ken \nagtuloykan nga agusar ti daan a kontraseniasmo.",
+       "passwordreset-emailtitle": "Dagiti salaysay ti pakabilangan iti {{SITENAME}}",
+       "passwordreset-emailtext-ip": "Adda (baka sika, ti naggapuan ti IP a pagtaengan $1) a nagkiddaw ti maysa a panangisaad manen ti kontrasenias para iti {{SITNAME}} ($4) . {{PLURAL:$3|Ti |Dagiti}} sumaganad a pakabilangan ti agar-aramat ket\nmainaig iti daytoy nga esurat a pagtaengan:\n\n$2\n\n{{PLURAL:$3|Daytoy temporario a kontrasenias|Dagitoy temporario a kontrasenias}} ket agpaso {{PLURAL:$5|iti maysa nga aldaw|kadagiti $5 nga aldaw}}.\nSumrekka koman tapno agpilika ti baro a kontraseniasmo tattan. No adda met sabali a nagaramid daytoy a \npanagkiddaw, wenno malagipmo ti dati a kontraseniasmo, ket saanmo a kayaten a sukatan, saanmo nga ikaskaso daytoy a mensahe ken \nagtuloyka nga agusar ti daan a kontrasenias.",
+       "passwordreset-emailtext-user": "Daytoy nga agar-aramat $1 iti {{SITENAME}} ket nagkiddaw ti maysa a panangisaad manen ti bukod a kontrasenias para iti {{SITENAME}}\n($4) . {{PLURAL:$3|Ti|Dagiti}} sumaganad a pakabilangan ti agar-aramat ket\nmainaig iti daytoy nga esurat a pagtaengan:\n\n$2\n\n{{PLURAL:$3|Daytoy temporario a kontrasenias|Dagitoy temporario a kontrasenias}} ket agpaso {{PLURAL:$5|iti maysa nga aldaw|kadagiti $5 nga aldaw}}.\nSumrekka koman tapno agpilika ti baro a kontraseniasmo tattan. No adda met sabali a nagaramid daytoy a \npanagkiddaw, wenno malagipmo ti dati a kontraseniasmo, ken saanmo a kayaten a sukatan, saanmo nga ikaskaso daytoy a mensahe ken \nagtuloykan nga agusar ti daan a kontraseniasmo.",
        "passwordreset-emailelement": "Nagan ti agar-aramat: $1\nTemporario a kontrasenias: $2",
-       "passwordreset-emailsent": "Ti maysa nga esurat ti panangiyasentar manen ti kontrasenias ket naipatuloden.",
-       "passwordreset-emailsent-capture": "Ti maysa nga esurat ti panangiyasentar manen ti kontrasenias ket naipatuloden, a napaikita dita baba.",
-       "passwordreset-emailerror-capture": "Naaramid ti maysa nga esurat a panangyasentar manen ti kontrasenias, a napaikita dita baba, ngem ti panangitulod kenni {{GENDER:$2|agar-aramat}} ket napaay: $1",
+       "passwordreset-emailsent": "Ti maysa nga esurat ti panangisaad manen ti kontrasenias ket naipatuloden.",
+       "passwordreset-emailsent-capture": "Ti maysa nga esurat ti panangisaad manen ti kontrasenias ket naipatuloden, a naipakita dita baba.",
+       "passwordreset-emailerror-capture": "Naaramid ti maysa nga esurat a panangisaad manen ti kontrasenias, a napaikita dita baba, ngem ti panangitulod kenni {{GENDER:$2|agar-aramat}} ket napaay: $1",
        "changeemail": "Sukatan ti esurat a pagtaengan",
        "changeemail-header": "Sukatan ti esurat a pagtaengan ti pakabilangan",
-       "changeemail-text": "Lippasem daytoy a porma ti panagsukat ti esurat a pagtaengam. Nasken nga ikabilmo ti kontrasenias tapno mapasingkedan daytoy a panagsukat.",
+       "changeemail-text": "Kompletuen daytoy a porma ti panagsukat ti esurat a pagtaengam. Nasken nga ikabilmo ti kontrasenias tapno mapasingkedan daytoy a panagsukat.",
        "changeemail-no-info": "Masapul a nakastrekka tapno dagus a makapan iti ditoy a panid.",
        "changeemail-oldemail": "Agdama nga esurat a pagtaengan:",
        "changeemail-newemail": "Baro nga esurat a pagtaengan:",
        "changeemail-submit": "Sukatan ti esurat",
        "changeemail-cancel": "Ukasen",
        "changeemail-throttled": "Adu unay ti panagpadasmo a sumrek.\nPangngaasi nga aguray ti $1 sakbay a padasen manen.",
-       "resettokens": "Iyasentar manen dagiti tandaan",
-       "resettokens-text": "Mabalinmo nga iyasentar dagiti tandaan a mangpalubos ti panagserrek ti naisangayan a pribado datos a mainaig ti pakabilangam ditoy.\n\nAramidem daytoy no aksidente nga inbingaymo dagitoy iti sabali wenno ti pakabilangam ket nakomprimiso.",
-       "resettokens-no-tokens": "Awan dagiti maiyasentar manen a tandaan.",
-       "resettokens-legend": "Iyasentar manen dagiti tandaan",
+       "resettokens": "Isaad manen dagiti tandaan",
+       "resettokens-text": "Mabalinmo nga isaad manen dagiti tandaan a mangpalubos ti panagserrek ti naisangayan a pribado datos a mainaig ti pakabilangam ditoy.\n\nAramidem daytoy no aksidente nga inbingaymo dagitoy iti sabali wenno ti pakabilangam ket nakomprimiso.",
+       "resettokens-no-tokens": "Awan dagiti maisaad manen a tandaan.",
+       "resettokens-legend": "Isaad manen dagiti tandaan",
        "resettokens-tokens": "Dagiti tandaan:",
        "resettokens-token-label": "$1 (agdama a pateg: $2)",
-       "resettokens-watchlist-token": "Tandaan para iti pakan ti web (Atom/RSS) kadagiti [[Special:Watchlist|panagbalbaliw ti pampanid idiay bambantayam]]",
-       "resettokens-done": "Naiyasentar manen dagiti tandaan.",
-       "resettokens-resetbutton": "Iyasentar manen  dagiti napili a tandaan",
+       "resettokens-watchlist-token": "Tandaan para iti pakan ti web (Atom/RSS) kadagiti [[Special:Watchlist|panagbalbaliw ti pampanid iti listaan ti bambantayam]]",
+       "resettokens-done": "Naisaad manen dagiti tandaan.",
+       "resettokens-resetbutton": "Isaad manen  dagiti napili a tandaan",
        "bold_sample": "Napuskol a testo",
        "bold_tip": "Napuskol a testo",
-       "italic_sample": "Nakairig a testo",
-       "italic_tip": "Nakairig a testo",
+       "italic_sample": "Italiko a testo",
+       "italic_tip": "Italiko a testo",
        "link_sample": "Titulo ti silpo",
        "link_tip": "Akin-uneg a silpo",
        "extlink_sample": "http://www.example.com titulo ti silpo",
-       "extlink_tip": "Akin-ruar a silpo (laglagipen ti http:// a pasaruno)",
+       "extlink_tip": "Akinruar a silpo (laglagipen ti http:// a pasakbay)",
        "headline_sample": "Testo ti paulo",
        "headline_tip": "Maika-2 nga agasmang ti paulo",
        "nowiki_sample": "Isengngat ti saan a naporma a testo ditoy",
-       "nowiki_tip": "Saan nga ikaskaso ti panakaporma ti wiki",
+       "nowiki_tip": "Saan nga ikaskaso ti pannakaporma ti wiki",
        "image_tip": "Naisengngat a papeles",
        "media_tip": "Silpo ti papeles",
-       "sig_tip": "Ti pirmam nga adda ti oras ken petsa",
-       "hr_tip": "Pakuros a linia (manmano laeng nga aramaten)",
+       "sig_tip": "Ti pirmam nga addaan iti oras ken petsa",
+       "hr_tip": "Horisontal a linia (manmano laeng nga aramaten)",
        "summary": "Pakabuklan:",
        "subject": "Suheto/paulo:",
        "minoredit": "Daytoy ket bassit a panag-urnos",
        "preview": "Ipadas",
        "showpreview": "Ipakita ti ipadas",
        "showdiff": "Ipakita dagiti sinukatan",
-       "anoneditwarning": "'''Ballaag:''' Saanka a nakastrek.\nMairehistro ti IP a pagtaengam iti pakasaritaan ti panagurnos iti daytoy a panid.",
-       "anonpreviewwarning": "\" Saanka a nakastrek. Ti panagidulin ket agirehistro ti IP a pagtaengam kadagitoy a  pakasaritaan ti panagurnos iti daytoy a panid.\"",
-       "missingsummary": "'''Palagip:''' Saanka a nakaited iti pakabuklan ti panag-urnos.\nNo ipindutmo ti manen ti \"{{int:savearticle}}\", maidulin ti inurnosmo nga awan ti pakabuklanna.",
+       "blankarticle": "<strong>Ballaag:</strong> Ti panid a parpatuatem ket blanko.\nNo pindutem manen ti \"{{int:savearticle}}\", ti panid ket mapartuatto nga awan ti aniaman a linaon.",
+       "anoneditwarning": "<strong>Ballaag:</strong> Saanka a nakastrek.\nMairehistro ti IP a pagtaengam iti pakasaritaan ti panag-urnos iti daytoy a panid.",
+       "anonpreviewwarning": "<em>Saanka a nakastrek. Ti panagidulin ket agirehistro ti IP a pagtaengam kadagitoy a pakasaritaan ti panag-urnos iti daytoy a panid.</em>",
+       "missingsummary": "<strong>Palagip:</strong> Saanka a nakaited iti pakabuklan ti panag-urnos.\nNo pindutem manen ti \"{{int:savearticle}}\", maidulin ti inurnosmo nga awan ti pakabuklanna.",
        "missingcommenttext": "Pangngaasi nga agikabil ti komentario dita baba.",
-       "missingcommentheader": "'''Palagip:''' Saanka a nakaited  iti suheto/paulo para iti daytoy a komentario.\nNo ipindutmo manen ti \"{{int:savearticle}}\", maidulin ti inurnosmo nga awan ti pakabuklanna.",
-       "summary-preview": "Naipadas a  pakabuklan:",
+       "missingcommentheader": "<strong>Palagip:</strong> Saanka a nakaited  iti suheto/paulo para iti daytoy a komentario.\nNo pindutem manen ti \"{{int:savearticle}}\", maidulin ti inurnosmo nga awan ti pakabuklanna.",
+       "summary-preview": "Naipadas a pakabuklan:",
        "subject-preview": "Suheto/naipadas a paulo:",
        "blockedtitle": "Naseraan ti agar-aramat",
-       "blockedtext": "'''Naseraan ti naganmo nga agar-aramat wenno ti IP a pagtaengam.'''\n\nNi $1 ti nangserra kenka. \nTi rason ket ''$2''.\n\n* Rugi ti panangserra: $8\n* Panagpaso ti panangserra: $6\n* Ti koma serraanna: $7\n\nMabalinmo a kontaken ni $1 wenno sabali pay nga [[{{MediaWiki:Grouppage-sysop}}|administrador]] no kayatmo a maipalawag daytoy a panag-serra.\nDimo mabalin nga aramaten ti ramit nga esuratan daytoy nga agar-aramat malaksid no adda napudno nga esurat a pagtaengan a naipan iti [[Special:Preferences|pakabilangan ti kaykayatmo]] ken no saanka a naparitan nga agaramat iti daytoy.\nTi agdama nga IP a pagtaengam ket $3, ti naserraan nga ID ket #$5. Pangngaasi nga iramanmo nga ited ti aniaman wenno agpada kadagitoy iti aniaman a panagsaludsodmo.",
-       "autoblockedtext": "Ti IP a pagtaengam ket na-automatiko a naserraan ngamin ket inusar ti sabali nga agar-aramat, a sinerraan ni $1.\nTi rason nga inted ket:\n\n:''$2''\n\n* Rugi ti panag-serra: $8\n* Panagpaso ti panag-serra: $6\n* Ti serraanna koma: $7\n\nMabalinmo a kontaken ni $1 wenno maysa kadagiti [[{{MediaWiki:Grouppage-sysop}}|administrador]] tapno maipalawag daytoy a panag-serra.\n\nLaglagipem a saanmo a mabalin nga usaren ti \"esuratan daytoy nga agar-aramat\" a langa malaksid no addaanka ti napudno nga esurat a pagtaengan a nakarehistro idiay [[Special:Preferences|kakaykayatam]] ken saanka a naserraan manipud ti panag-usar daytoy.\n\nTi tatta nga IP a pagtaengam ket $3, ken ti ID ti naserraan ket #$5.\nPangaasi nga iramanmo amin dagiti salaysay kadagiti amin a panagsaludsodmo.",
+       "blockedtext": "<strong>Naseraan ti naganmo nga agar-aramat wenno ti IP a pagtaengam.</strong>\n\nTi serra ket inaramid babaen ni $1. \nTi rason a naited ket <em>$2</em>.\n\n* Rugi ti serra: $8\n* Panagpaso ti serra: $6\n* Naikeddeng a serraanna: $7\n\nMabalinmo a kontaken ni $1 wenno sabali pay nga [[{{MediaWiki:Grouppage-sysop}}|administrador]] no kayatmo a maipalawag daytoy a panagserra.\nDimo mabalin nga aramaten ti ramit nga esuratan daytoy nga agar-aramat malaksid no adda napudno nga esurat a pagtaengan a nainaganan iti [[Special:Preferences|pakabilangan ti kakaykayatm]] ken no saanka a naparitan nga agaramat iti daytoy.\nTi agdama nga IP a pagtaengam ket $3, ti naserraan nga ID ket #$5. \nPangngaasi nga iramanmo amin dagiti salaysay dita ngato kadagiti aniaman nga aramidem nga usisa.",
+       "autoblockedtext": "Ti IP a pagtaengam ket automatiko a naserraan ngamin ket inusar ti sabali nga agar-aramat, a sinerraan ni $1.\nTi rason nga inted ket:\n\n:<em>$2</em>\n\n* Rugi ti serra: $8\n* Panagpaso ti serra: $6\n* Naikeddenga a serraanna: $7\n\nMabalinmo a kontaken ni $1 wenno maysa kadagiti [[{{MediaWiki:Grouppage-sysop}}|administrador]] tapno maipalawag daytoy a panagserra.\n\nLaglagipem a saanmo a mabalin nga usaren ti \"esuratan daytoy nga agar-aramat\" a langa malaksid no addaanka ti napudno nga esurat a pagtaengan a nakarehistro iti [[Special:Preferences|kakaykayatam]] ken saanka a naserraan manipud ti panag-usar daytoy.\n\nTi tatta nga IP a pagtaengam ket $3, ken ti ID ti naserraan ket #$5.\nPangngaasi nga iramanmo amin dagiti salaysay dita ngato kadagiti aniaman nga aramidem nga usisa.",
        "blockednoreason": "awan ti naited a rason",
        "whitelistedittext": "Nasken ti $1 tapno maurnosmo dagitoy a panid.",
-       "confirmedittext": "Masapul a pasingkedam ti esurat sakbay a makaurnos kadagitoy a panid.\nPangngaasim nga ikabil ken ipapudnom ti esuratmo idiay [[Special:Preferences|kaykayat dagiti agar-aramat ]].",
+       "confirmedittext": "Masapul a pasingkedam ti esurat sakbay a makaurnos kadagitoy a panid.\nPangngaasi nga isaad ken ipapudnom ti esuratmo babaen ti [[Special:Preferences|kakaykayatan ti agar-aramat]].",
        "nosuchsectiontitle": "Saan a mabirukan ti paset",
        "nosuchsectiontext": "Pinadasmo nga inurnos ti awan a paset.\nMabalin a naiyalis wenno naikkat bayat idi kitkitaem ti panid.",
        "loginreqtitle": "Masapul ti sumrek",
        "loginreqlink": "sumrek",
-       "loginreqpagetext": "Naskenka a $1 tapno makakitaka kadagiti sabsabali a pampanid.",
-       "accmailtitle": "Naipatuloden ti kontrasenias.",
-       "accmailtext": "Ti pugto a napartuat a kontrasenias para kenni [[User talk:$1|$1]] ket naipatuloden idiay $2. Mabalin a masukatan idiay\n''[[Special:ChangePassword|pagsukatan ti kontrasenias]]'' a panid no sumrekka.",
+       "loginreqpagetext": "Pangngaasi a $1 tapno makitam dagiti sabali a panid.",
+       "accmailtitle": "Naipatuloden ti kontrasenias",
+       "accmailtext": "Ti pugto a napartuat a kontrasenias para kenni [[User talk:$1|$1]] ket naipatuloden iti $2. Mabalin a masukatan iti\n<em>[[Special:ChangePassword|pagsukatan ti kontrasenias]]</em> a panid no sumrekka.",
        "newarticle": "(Baro)",
-       "newarticletext": "Nasurotmo ti silpo ti awan pay a panid. \nTi mangpartuat ti panid, rugiamon ti agmakinilia iti kahon dita baba (kitaen ti [$1 panid ti tulong] para iti adu pay a pakaammo). \nNo addaka ditoy babaen ti biddut, pindutem ti buton ti <strong>agsubli</strong> ti pagbasabasam.",
-       "anontalkpagetext": "----\n''Daytoy ti pakitungtungan a panid para iti di am-ammo nga agar-aramat a saan pay a nakaaramid ti pakabilangan, wenno saanna nga us-usaren.\nDakami ket agusar kami ti numero nga IP a pagtaengan ti panangilasin dagiti lalaki/babai.\nTi kastoy nga IP a pagtaengan ket us-usaren a bingayan ti adu pay a sabsabali nga agar-aramat.\nNo sika ket maysa a di am-ammo nga agar-aramat ken dagiti awan ti kapategan a komentario ket napaitudo kenka, pangngaasi nga [[Special:UserLogin/signup|agaramid ka ti pakabilangam]] wenno [[Special:UserLogin|sumrekka]] \ntapno maawanan ti panakaulaw kadagiti sabali a di am-ammo nga agar-aramat.",
-       "noarticletext": "Awan ti agdama a testo daytoy a panid.\nMabalinmo ti [[Special:Search/{{PAGENAME}}|agsapul iti kastoy a titulo ti panid]] kadagiti sabsabali a pampanid,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} birukem dagiti mainaig a listaan],\nwenno [{{fullurl:{{NAMESPACE}}:{{PAGENAME}}|action=edit}} urnosem daytoy a panid].",
-       "noarticletext-nopermission": "Awan ti agdama  a linaon daytoy a panid.\nMabalinmo ti [[Special:Search/{{PAGENAME}}|agbiruk para iti titulo ti daytoy a panid]] kadagiti sabali a panid, wenno <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} agbiruk kadagiti mainaig a listaan]</span>, ngem awan ti pammalubosmo a mangpartuat ti daytoy a panid.",
+       "newarticletext": "Nasurotmo ti silpo ti awan pay a panid. \nTi mangpartuat ti panid, rugiamon ti agmakinilia iti kahon dita baba (kitaen ti [$1 panid ti tulong] para iti adu pay a pakaammo). \nNo addaka ditoy babaen ti biddut, pindutem ti buton ti <strong>back</strong> ti pagbasabasam.",
+       "anontalkpagetext": "----\n<em>Daytoy ti pakitungtungan a panid para iti di ammo nga agar-aramat a saan pay a nakapartuat ti pakabilangan, wenno saanna nga us-usaren.</em>\nIsu nga agusarkami ti numero nga IP a pagtaengan tapno mailasin isuda a lalaki/babai.\nTi kastoy nga IP a pagtaengan ket us-usaren a bingayan babaen ti nadumaduma nga agar-aramat.\nNo sika ket maysa a di ammo nga agar-aramat ken dagiti awan ti pategna a komentario ket napaitudo kenka, pangngaasi nga [[Special:UserLogin/signup|agpartuatka ti pakabilangam]] wenno [[Special:UserLogin|sumrekka]] \ntapno maliklikan ti pannakaiyallilaw kadagiti sabali a di ammo nga agar-aramat.",
+       "noarticletext": "Awan ti agdama a testo daytoy a panid.\nMabalinmo ti [[Special:Search/{{PAGENAME}}|agbiruk iti kastoy a titulo ti panid]] kadagiti sabali a panid,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} agbiruk kadagiti mainaig a listaan],\nwenno [{{fullurl:{{NAMESPACE}}:{{PAGENAME}}|action=edit}} urnosem daytoy a panid]</span>.",
+       "noarticletext-nopermission": "Awan ti agdama  a linaon daytoy a panid.\nMabalinmo ti [[Special:Search/{{PAGENAME}}|agbiruk para iti titulo ti daytoy a panid]] kadagiti sabali a panid, wenno <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} agbiruk kadagiti mainaig a listaan]</span>, ngem awan ti pammalubosmo a mangpartuat iti daytoy a panid.",
        "missing-revision": "Ti panagbalbaliw ti #$1 iti daytoy a panid a nanaganan ti \"{{FULLPAGENAME}}\" ket awan.\n\nDaytoy ket kadawyan a gapuanan babaen ti sumaganad a silpo ti baak a pakasaritaan iti maysa a naikkaten a panid.\nDagiti salaysay ket mabalin a mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti panagikkat].",
-       "userpage-userdoesnotexist": "Ti pakabilangan ti agar-aramat \"$1\" ket saan a nakarehistro. \nPangngaasi a kitaem no kayatmo ti agaramid/urnosen daytoy a panid.",
-       "userpage-userdoesnotexist-view": "Ti pakabilangan ti agar-aramat \"$1\" ket saan a nakarehistro.",
-       "blocked-notice-logextract": "Agdama a naserraan daytoy nga agar-aramat.\nTi naudi a listaan ti panaka-serra ket adda dita baba tapno mausar a reperensia:",
-       "clearyourcache": "'''Pakaammo:''' No nalpaskan nga agiduldulin, koma ket masapul nga ipalabas ti cahe ti pagbasabasam tapno makita dagiti sinukatam.\n* '''Firefox / Safari:''' Tenglen ti ''Sukatan'' bayat nga ipindut ti ''Ikarga manen'', wenno ipindut ti ''Ctrl-F5'' wenno''Ctrl-R'' (''⌘-R'' Mac)\n* '''Google Chrome:''' Ipindut ti ''Ctrl-Shift-R'' (''⌘-Shift-R'' iti Mac)\n* '''Internet Explorer:''' Tenglen ti ''Ctrl'' bayat nga ipindut ti ''Ipasaradiwa'', wenno ipindut ti ''Ctrl-F5''\n* '''Opera:''' Dalusan ti cache iti ''Ramramit → Kakaykayatan''",
-       "usercssyoucanpreview": "'''Paammo:''' Usaren ti \"{{int:showpreview}}\" a buton ti panagsubok ti baro a CSS sakbay nga idulinmo.",
-       "userjsyoucanpreview": "'''Paammo:''' Usaren ti \"{{int:showpreview}}\" a buton ti panagsubok ti baro a JavaScript sakbay nga idulinmo.",
-       "usercsspreview": "'''Laglagipem nga ipadpadasmo laeng daytoy a CSS.'''\n'''Saan pay a naidulin!'''",
-       "userjspreview": "'''Laglagipem nga ipadpadasmo laeng daytoy a JavaScript.'''\n'''Saan pay a naidulin!'''",
-       "sitecsspreview": "'''Laglagipem nga ipadpadasmo laeng daytoy a CSS.'''\n'''Saan pay a naidulin!'''",
-       "sitejspreview": "'''Laglagipem nga ipadpadasmo laeng ti kodigo daytoy a JavaScript.'''\n'''Saan pay nga naidulin!'''",
-       "userinvalidcssjstitle": "'''Ballaag:''' Awan ti kudil a \"$1\".\nAnnawid a .css ken .js dagiti titulo ket agususar ti babassit a letra, a kas dagiti {{ns:user}}:Foo/vector.css saan ket a {{ns:user}}:Foo/Vector.css.",
+       "userpage-userdoesnotexist": "Ti pakabilangan ti agar-aramat ni \"$1\" ket saan a nakarehistro. \nPangngaasi a kitaem no kayatmo ti agpartuat/agurnos iti daytoy a panid.",
+       "userpage-userdoesnotexist-view": "Ti pakabilangan ti agar-aramat ni \"$1\" ket saan a nakarehistro.",
+       "blocked-notice-logextract": "Agdama a naserraan daytoy nga agar-aramat.\nTi naudi a listaan ti pannakaserra ket naited dita baba para iti reperensia:",
+       "clearyourcache": "<strong>Nota:</strong> Kalpasan ti panangidulin, koma ket masapul nga ipalabas ti cahe ti pagbasabasam tapno makita dagiti sinukatam.\n* <strong>Firefox / Safari:</strong>  Tenglen ti <em>Shift</em> bayat a pinduten ti <em>Reload</em>, wenno talmegan ti <em>Ctrl-F5</em> wenno <em>Ctrl-R</em> (<em>⌘-R</em> iti Mac)\n* <strong>Google Chrome:</strong> Talmegan ti <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> iti Mac)\n* <strong>Internet Explorer:</strong> Tenglen ti <em>Ctrl</em> bayat a pinduten ti <em>Refresh</em>, wenno talmegan ti <em>Ctrl-F5</em>\n* <strong>Opera:</strong> Dalusan ti cache idiay <em>Tools → Preferences</em>",
+       "usercssyoucanpreview": "<strong>Paammo:</strong>  Usaren ti buton ti \"{{int:showpreview}}\" tapno masubokan ti baro a CSS sakbay nga agidulin.",
+       "userjsyoucanpreview": "<strong>Pammo:</strong> Usaren ti buton ti \"{{int:showpreview}}\" tapno masubokan ti baro a JavaScript sakbay nga agidulin.",
+       "usercsspreview": "<strong>Laglagipem nga ipadpadasmo laeng ti bukodmo a CSS ti agar-aramat.\nSaan pay a naidulin!</strong>",
+       "userjspreview": "<strong>Laglagipem a subsubokam/ipadpadasmo ti bukodmo a JavaScript ti agar-aramat.\nSaan pay a naidulin!</strong>",
+       "sitecsspreview": "<strong>Laglagipem nga ipadpadasmo laeng daytoy a CSS.\nSaan pay a naidulin!</strong>",
+       "sitejspreview": "<strong>Laglagipem nga ipadpadasmo laeng daytoy a kodigo ti JavaScript.\nSaan pay nga naidulin!</strong>",
+       "userinvalidcssjstitle": "<strong>Ballaag:</strong> Awan ti kudil a \"$1\".\nDagiti panid ti naiduma a .css ken .js ket agus-usar ti titulo ti bassit a letra, kas ti {{ns:user}}:Foo/vector.css saan a kas ti {{ns:user}}:Foo/Vector.css.",
        "updated": "(Napabaro)",
-       "note": "'''Paammo:'''",
-       "previewnote": "'''Laglagipem a daytoy ket panagipadas laeng.'''\nDagiti sinukatam ket saan pay a naidulin!",
+       "note": "<strong>Nota:</strong>",
+       "previewnote": "<strong>Laglagipem a daytoy ket panagipadas laeng.</strong>\nDagiti sinukatam ket saan pay a naidulin!",
        "continue-editing": "Mapan idiay pagurnosan a lugar",
-       "previewconflict": "Daytoy a panagpadas ket agiparang ti testo dita ngato a panagurnos a lugar a kasla agparang no kayatmo nga idulin.",
-       "session_fail_preview": "'''Pasensia! Saanmi a maaramid ti panag-urnos gapu ngamin ta naawanan ti gimong ti data.'''\nPangngaasi a padasem manen.\nNo saan pay a mabalin, padasem ti [[Special:UserLogout|rummuar]] ken sumrekka manen.",
-       "session_fail_preview_html": "'''Pasensia! Saanmi a maaramid ti panagurnosmo ngamin ket naawanan ti gimong ti datos.'''\n\n''Gapu ti {{SITENAME}} ket addaa ti nakilaw a HTML a nakapabaelan, ti panagpadas ket nailemmeng a kas pagan-annadan kadagiti panagraut ti dakes a JavaScript.''\n\n'''No daytoy ket pudno a panag-urnos, pangngaasi a padasem manen.'''\nNo saan pay a mabalin, padasem ti [[Special:UserLogout|rummuar]] ken sumrekka manen.",
-       "token_suffix_mismatch": "'''Ti panag-urnosmo ket saan a naawat ngamin ket ti klientem ket dinadaelna ti kuldit ti kababalin idiay panagpudno ti panag-urnos.'''\nTi panag-urnos ket saan a naawat tapno mapawilan ti panakadadael ti testo ti panid.\nMapasamak daytoy no agus-usarka ti saan a nasayaat a naibasta ti sapot a di ammo a pannakbagi a panagserbi.",
-       "edit_form_incomplete": "'''Adda dagiti paset ti panag-urnos a porma a saan a nakadanon dita server; kitkitaen nga dagiti panag-urnosmo ket saan a naikkatan ken padasem manen.'''",
+       "previewconflict": "Daytoy a panagpadas ket mangipakita ti testo iti lugar ti akin-ngato a pangurnosan ti testo a kasla agparang no piliem nga idulin.",
+       "session_fail_preview": "<strong>Pasensia! Saanmi a maproseso ti panag-urnosmo gapu ta naawanan ti sesion ti datos.</strong>\nPangngaasi a padasen manen.\nNo saan pay a mabalin, padasen ti [[Special:UserLogout|rummuar]] ken sumrek manen.",
+       "session_fail_preview_html": "<strong>Pasensia! Saanmi a maproseso ti panag-urnosmo gapu ta naawanan ti sesion ti datos.</strong>'\n\n<em>Gapu ta ti {{SITENAME}} ket addaan iti naata a HTML a nakapabaelan, ti panagpadas ket nailemmeng a kas pagan-annadan kadagiti panagraut ti dakes a JavaScript.</em>\n\n<strong>No daytoy ket pudno a panag-urnos, pangngaasi a padasem manen.</strong>\nNo saan pay a mabalin, padasen ti [[Special:UserLogout|rummuar]] ken sumrek manen.",
+       "token_suffix_mismatch": "<strong>Ti panag-urnosmo ket saan a naawat ngamin ket ti klientem ket dinadaelna dagiti karakter ti tuldek iti tandaan ti panag-urnos.</strong>\nTi panag-urnos ket saan a naawat tapno mapawilan ti pannakadadael ti testo ti panid.\nSagpaminsan a mapasamak daytoy no agus-usarka ti saan a nasayaat a naibatay ti web ti di ammo a pannakbagi a serbisio.",
+       "edit_form_incomplete": "<strong>Adda dagiti paset ti pagurnosan a porma a saan a nakadanon dita server; mamindua a kitaen dagiti panag-urnosmo ket sibubukel ken padasen manen.</strong>",
        "editing": "Ur-urnosen ti $1",
        "creating": "Agparpartuat ti $1",
        "editingsection": "Ur-urnosen ti $1 (paset)",
        "editingcomment": "Ur-urnosen ti $1 (baro a paset)",
-       "editconflict": "Adda kasinnungat ti panag-urnos: $1",
-       "explainconflict": "Adda sabali a nagsukat iti daytoy a panid idi nangrugika a nagurnos.\nTi ngato a lugar ti testo ket adda dagiti nagyanna a testo ti panid a kasla agdama a kitana.\nTi inurnosmo ket maipakita dita babba a lugar ti testo\nIpatiponmo dagiti sinukatam idiay lugar ti testo.\n'''Iti laeng''' testo dita ngato a lugar ti testo ti maidulin no pindutem ti \"{{int:savearticle}}\".",
+       "editconflict": "Agsinnungat a panag-urnos: $1",
+       "explainconflict": "Adda sabali a nagsukat iti daytoy a panid idi nangrugika a nagurnos.\nTi akinngato a lugar ti testo ket aglaon ti testo ti panid iti agdama kaddana.\nDagiti sinukatam ket maipakita iti akinbabba a lugar ti testo.\nNasken nga itiponmoto dagiti sinukatam iti adda a testo.\nTi <strong>laeng</strong> testo iti akinngato a lugar ti testo ti maidulinto no talmegam ti \"{{int:savearticle}}\".",
        "yourtext": "Ti testom",
-       "storedversion": "Bersion a naidulin",
-       "nonunicodebrowser": "'''Ballaag: Ti  pabasabasam ket saan a naikeddeng ti Unicode .'''\nAdda sabali a mausar tapno makaurnoska kadagiti panid: Ti saan nga-ASCII a kababalin ket agparang iti pagurnosan a kahon a kas dagiti heksadesimal a kodigo.",
-       "editingold": "'''Ballag: Ur-urnosem ti daan a panag-baliw iti daytoy a panid.'''\nNo idulinmo, mapukaw amin a sinukatam iti daytoy a panag-baliw.",
-       "yourdiff": "Dagiti nagdudumaan",
-       "copyrightwarning": "Laglagipenyo koma, apo, nga amin a maiparawad iti {{SITENAME}} ket maibilang a mairuar babaen ti $2 (kitaen ti $1 para kadagiti salaysay). \nNo dimo kayat a ti sinuratmo ket maurnos nga awanan-asi ken maiwaras nga awan sungsungbatan kenka, saanmo laengen nga ip-ipan wenno ipabpablaak ditoy.<br />\nKasta met nga ikarim kadakami a bukodmo a sinurat wenno gapuanan daytoy, wenno tinuladmo manipud ti maysa a nawaya a pagturayan ti publiko wenno ti kapadpadana a nawaya a nagtaudan.\n '''Saan a mangited ti adda karbenganna a panagipablaak nga obra no awan ti  pammalubos!'''",
-       "copyrightwarning2": "Pangngaasiyo, apo, a laglagipen nga amin a maiparawad iti {{SITENAME}} ket mabalin a maurnos, masuktan, wenno ikkaten dagiti sabali pay nga agar-aramat.\nNo dimo kayat a ti sinuratmo ket maurnos nga awanan-asi ken maiwaras nga awan sungsungbatan kenka, saanmo laengen nga ip-ipan wenno ipabpablaak ditoy.<br />\nKasta met nga ikarim kadakami a bukodmo a sinurat wenno gapuanan daytoy, wenno tinuladmo manipud ti maysa a nawaya a pagturayan ti publiko wenno ti kapadpadana a nawaya a pagtaudan (kitaen ti $1 para iti salaysay).\n'''Saan a mangipan iti adda ti karbenganna a panagpablaak nga obra no awan ti  pammalubos!'''",
-       "longpageerror": "'''Biddut: Ti testo nga intedmo ket {{PLURAL:$1|maysa a kilobyte|$1 kil-kilobyte}} a katiddog, nga at-atiddog ngem ti kangatuan iti  {{PLURAL:$2|maysa a kilobyte|$2 kil-kilobyte}}.'''\nIsu ti gapuna a saan a maidulin.",
-       "readonlywarning": "'''Ballaag: Narikepan ti database tapno mataripatu, isu a saanmo a mabalin nga idulin dagita inurnosmo tattan.'''\nMabalinmo ti agkopia ken agikabil ti testom iti maysa a testo a papeles ken idulinmo para iti panagusar no madamdama.\n\nTi administrador a nangrikep ket nangited iti daytoy a palawag: $1",
-       "protectedpagewarning": "'''Ballaag:  Daytoy a panid ket nasalakniban tapno dagiti laeng agar-aramat nga adda ti gundaway nga administrador ti makaurnos ditoy.'''\nTi nakaudi a naikabil a listaan ket adda dita baba tapno usaren a reperensia:",
-       "semiprotectedpagewarning": "'''Pakaammo:'''Nasalakniban daytoy a panid tapno dagiti laeng nakarehistro nga agar-aramat ti makaurnos ditoy.\nTi naudi a naikabil a listaan ket adda dita baba tapno usaren a reperensia:",
-       "cascadeprotectedwarning": "'''Ballaag:''' Daytoy a panid ket nasalakniban tapno dagiti laeng administrador nga adda ti pammalubos ti makaurnos ngamin ket nairaman kadagiti sumaganad a nasalakniban iti sariap\n{{PLURAL:$1|a panid|a pampanid}}:",
-       "titleprotectedwarning": "'''Ballaag:  Nasalakniban daytoy a panid tapno [[Special:ListGroupRights|dagiti naisangayan a karbengan ]] ket nasken ti makapartuat iti daytoy.'''\nTi kinaudi a naikabil iti listaan ket naikabil dita baba tapno usaren a reperensia:",
+       "storedversion": "Rebision a naidulin",
+       "nonunicodebrowser": "<strong>Ballaag: Ti pabasabasam ket saan a maitunos iti Unicode .</strong>\nAdda sabali a mausar tapno makaurnoska kadagiti panid: Ti saan nga-ASCII a karakter ket agparang iti pagurnosan a kahon a kas dagiti heksadesimal a kodigo.",
+       "editingold": "<strong>Ballag: Ur-urnosem ti daan a rebision iti daytoy a panid.</strong>\nNo idulinmo, ti aniaman a naramid a binaliwan manipud iti daytoy a rebision ket mapukawto.",
+       "yourdiff": "Paggigiddiatan",
+       "copyrightwarning": "Pangngaasi a laglagipen nga amin a kontribusion iti {{SITENAME}} ket naikeddeng a naipablaak babaen ti babaen ti $2 (kitaen ti $1 para kadagiti salaysay). \nNo dimo kayat a ti sinuratmo ket maurnos nga awanan-asi ken maiwaras nga awan sungsungbatan kenka, saanmon nga ited ditoy.<br />\nIkarkarim pay kadakami a bukodmo a sinurat daytoy, wenno kinopia manipud ti publiko a dominio wenno ti kapadpadana a nawaya a nagtaudan.\n<strong>Saan a mangited ti nakarbengan ti kopia nga obra no awan iti pammalubos!</strong>",
+       "copyrightwarning2": "Pangngaasi a laglagipen nga amin a kontribusion iti {{SITENAME}} ket mabalin a maurnos, mabaliwan, wenno ikkaten dagiti sabali a kontributor.\nNo dimo kayat a ti sinuratmo ket maurnos nga awanan-asi ken maiwaras nga awan sungsungbatan kenka, saanmon nga ited ditoy.<br />\nIkarkarim pay kadakami a bukodmo a sinurat daytoy, wenno kinopia manipud ti publiko a dominio wenno ti kapadpadana a nawaya a nagtaudan. (kitaen ti $1 para kadagiti salaysay).\n<strong>Saan a mangited ti nakarbengan ti kopia nga obra no awan iti pammalubos!</strong>",
+       "longpageerror": "<strong>Biddut: Ti testo nga intedmo ket {{PLURAL:$1|maysa a kilobyte|$1 kil-kilobyte}} ti katiddogna, nga at-atiddog ngem ti kangatuan iti  {{PLURAL:$2|maysa a kilobyte|$2 kil-kilobyte}}.</strong>\nSaan a mabalin a maidulin.",
+       "readonlywarning": "<strong>Ballaag: Narikepan ti database tapno mataripato, isu a saanmo a mabalin nga idulin dagita inurnosmo tattan.</strong>\nMabalinmo ti agkopia ken agipegket ti testom iti papeles ti testo ken idulinmo daytoy intono madamdama.\n\nTi administrador a nangrikep ket nangited iti daytoy a palawag: $1",
+       "protectedpagewarning": "<strong>Ballaag: Daytoy a panid ket nasalakniban tapno dagiti laeng agar-aramat nga addaan iti gundaway nga administrador ti makaurnos ditoy.</strong>\nTi naudi a naikabil iti listaan ket naited dita baba para iti reperensia:",
+       "semiprotectedpagewarning": "<strong>Nota:</strong> Nasalakniban daytoy a panid tapno dagiti laeng nakarehistro nga agar-aramat ti makaurnos ditoy.\nTi naudi a naikabil iti listaan ket naited dita baba para iti reperensia:",
+       "cascadeprotectedwarning": "<strong>Ballaag:</strong> Daytoy a panid ket nasalakniban tapno dagiti laeng agar-aramat nga addaan iti gundaway nga administrador ti makaurnos ngamin ket nairaman kadagiti sumaganad a nasalakniban iti sariap\n{{PLURAL:$1|a panid|a pampanid}}:",
+       "titleprotectedwarning": "<strong>Ballaag:  Nasalakniban daytoy a panid tapno [[Special:ListGroupRights|dagiti naisangayan ti karbengan]] ket nasken a makapartuat iti daytoy.</strong>\nTi naudi a naikabil iti listaan ket naited dita baba para iti reperensia:",
        "templatesused": "{{PLURAL:$1|Ti plantilia|Dagiti plantilia}} a naaramat iti daytoy a panid:",
        "templatesusedpreview": "{{PLURAL:$1|Ti plantilia|Dagiti plantilia}} a naaramat iti daytoy a panagpadas:",
        "templatesusedsection": "{{PLURAL:$1|Ti plantilia|Dagiti plantilia}} a naaramat iti daytoy a paset:",
        "template-protected": "(nasalakniban)",
        "template-semiprotected": "(nasalakniban-bassit)",
-       "hiddencategories": "Daytoy a panid ket kameng  {{PLURAL:$1|ti 1 a nailemmeng a kategoria|dagiti $1 a nailemmeng a kategoria}}:",
-       "nocreatetext": "Pinaritan ti {{SITENAME}} ti pannakabael a panagaramid iti kabarbaro a pampanid.\nMabalinmo ti agsubli ken urnosen ti adda a panid, wenno [[Special:UserLogin|sumrek wenno agaramid ti pakabilangan]].",
+       "hiddencategories": "Daytoy a panid ket kameng {{PLURAL:$1|ti 1 a nailemmeng a kategoria|dagiti $1 a nailemmeng a kategoria}}:",
+       "nocreatetext": "Ginawidan ti {{SITENAME}} ti abilidad nga agpartuat kadagiti baro a panid.\nMabalinmo ti agsubli ken agurnos ti adda a panid, wenno [[Special:UserLogin|sumrek wenno agapartuat ti pakabilangan]].",
        "nocreate-loggedin": "Awan ti pammalubosmo nga agpartuat kadagiti baro a panid.",
-       "sectioneditnotsupported-title": "Saan a nasuportaran ti panagurnos ti paset",
+       "sectioneditnotsupported-title": "Saan a nasuportaran ti panag-urnos ti paset",
        "sectioneditnotsupported-text": "Saan a nasuportaran ti panag-urnos ti paset iti daytoy a panid.",
        "permissionserrors": "Biddut ti pammalubos",
        "permissionserrorstext": "Awan ti pammalubosmo nga agaramid iti dayta, gapu ti sumaganad {{PLURAL:$1|a rason|a rasrason}}:",
        "permissionserrorstext-withaction": "Awan ti pammalubosmo nga $2, gapu ti sumaganad a {{PLURAL:$1|rason|rasrason}}:",
-       "recreate-moveddeleted-warn": "'''Ballaag: Agparpartuatka manen ti dati a naikkat a panid'''\n\nNasken a siguraduem no maikanatad nga ituloymo nga urnosen daytoy a panid.\nTi pannakaikkat ken pannakaiyalis a listaan para iti daytoy a panid ket adda ditoy a pakakitaan:",
-       "moveddeleted-notice": "Naikkaten daytoy a panid.\nTi listaan a pannakaikkat ken pannakaiyalis ti panid ket naikabil dita baba tapno usaren a reperensia.",
+       "recreate-moveddeleted-warn": "<strong>Ballaag: Agparpartuatka manen ti dati a naikkat a panid.</strong>\n\nUsigem koma no maitutop ti agtuloy nga agurnos iti daytoy a panid.\nTi listaan ti pannakaikkat ken pannakaiyalis para iti daytoy a panid ket naited ditoy para iti pakainugotan:",
+       "moveddeleted-notice": "Naikkaten daytoy a panid.\nTi listaan ti pannakaikkat ken pannakaiyalis para iti panid ket naited dita baba para iti reperensia.",
        "log-fulllog": "Kitaem ti napno a listaan",
        "edit-hook-aborted": "Ti panag-urnos ket pinasardeng babaen ti kawit.\nAwan ti intedna a palawag.",
        "edit-gone-missing": "Saan a mapabaro daytoy a panid.\nKasla met naikkaten.",
-       "edit-conflict": "Adda kasinnungat ti panag-urnos.",
-       "edit-no-change": "Ti inurnosmo ket saan a naikaskaso, ngamin ket awan ti nasukatan a testo.",
+       "edit-conflict": "Kasinnungat ti panag-urnos.",
+       "edit-no-change": "Ti inurnosmo ket saan a naikaskaso ngamin ket awan ti naaramid a pannakasukat iti testo.",
        "postedit-confirmation-created": "Ti panid ket napartuaten.",
-       "postedit-confirmation-restored": "Ti panid ket naisublin.",
+       "postedit-confirmation-restored": "Ti panid ket naipulangen.",
        "postedit-confirmation-saved": "Ti inurnosmo ket naidulinen.",
        "edit-already-exists": "Saan a makaaramid ti baro a panid.\nAdda met daytoyen.",
        "defaultmessagetext": "Kasisigud a testo ti mensahe",
-       "content-failed-to-parse": "Napaay a nausig ti $2 a linaon para iti $1 a modelo: $3",
+       "content-failed-to-parse": "Napaay a mawaswas ti $2 a linaon para iti $1 a modelo: $3",
        "invalid-content-data": "Imbalido a datos ti linaon",
-       "content-not-allowed-here": "Ti \"$1\" a linaon ket saan a maipalubos idiay panid ti [[$2]]",
-       "editwarning-warning": "Ti ipapanaw iti daytoy a panid ket makapataud ti pannakapukaw kadagiti aniaman a binalbaliwam.\nNo nakastrekka, mabalinmo nga ibaldado daytoy a ballaag idiay \"{{int:prefs-editing}}\" a paset kadagiti kakaykayatam.",
+       "content-not-allowed-here": "Ti \"$1\" a linaon ket saan a maipalubos iti panid ti [[$2]]",
+       "editwarning-warning": "Ti ipapanaw iti daytoy a panid ket makapataud ti pannakapukaw kadagiti aniaman a binalbaliwam.\nNo nakastrekka, mabalinmo nga ibaldado daytoy a ballaag iti \"{{int:prefs-editing}}\" a paset kadagiti kakaykayatam.",
        "editpage-notsupportedcontentformat-title": "Ti pormat ti linaon ket saan a nasuportaran",
        "editpage-notsupportedcontentformat-text": "Ti pormat ti linaon ti $1 ket saan a nasuportaran babaen ti modelo ti linaon ti $2.",
        "content-model-wikitext": "wikitext",
        "content-model-text": "naranas a testo",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
-       "expensive-parserfunction-warning": "'''Ballaag:''' Daytoy a panid ket adu unay kadagiti nangina a parser a pamay-an  a panagtawtawag.\n\nAdda koman basbasit ngem $2 {{PLURAL:$2|a panagtawtawag|kadagiti panagtawtawag}}, adda {{PLURAL:$1|tattan $1 a panagtawtawag|tattan kadagiti $1 a panagtawtawag}}.",
+       "expensive-parserfunction-warning": "<strong>Ballaag:</strong> Daytoy a panid ket adu unay kadagiti nangina a parser a pamay-an a panagtawtawag.\n\nAdda koman basbasit ngem $2 {{PLURAL:$2|a panagtawtawag|kadagiti panagtawtawag}}, adda {{PLURAL:$1|tattan iti $1 a panagtawtawag|tattan kadagiti $1 a panagtawtawag}}.",
        "expensive-parserfunction-category": "Dagiti panid nga adda ti adu unay a nangina a parser a pamay-an a panagtawtawag",
-       "post-expand-template-inclusion-warning": "'''Ballaag:''' Dakkel unay ti nairaman a kadakkel ti plantilia.\nAdda dagiti plantilia a saanto a mairaman.",
+       "post-expand-template-inclusion-warning": "<strong>Ballaag:</strong> Dakkel unay ti nairaman a kadakkel ti plantilia.\nAdda dagiti plantilia a saanto a mairaman.",
        "post-expand-template-inclusion-category": "Pampanid nga ayan ti plantilia a nagsobra ti kadakkel ti rukod a nairaman",
-       "post-expand-template-argument-warning": "'''Ballaag:''' Daytoy a panid ket aglaon ti saan a basbasit ngem maysa a panangipalawag ti plantilia a dakkel unay ti panagpadakkelna.\nDagitoy a panangipalawag ket naikkaten.",
-       "post-expand-template-argument-category": "Dagiti panid a naglaon ti naikkat a plantilia kadagiti kasinnungat",
-       "parser-template-loop-warning": "Adda nasarakan a silo ti plantilia: [[$1]]",
-       "parser-template-recursion-depth-warning": "Ti kinauneg ti panagdullit ti plantilia ket nagpatingga ti napalabes ($1)",
-       "language-converter-depth-warning": "Ti kauneg ti panagaramid ti pagsasao ket napalabes ti agpatingga a ($1)",
+       "post-expand-template-argument-warning": "<strong>Ballaag:</strong> Daytoy a panid ket aglaon ti saan a basbasit ngem maysa a panangipalawag ti plantilia a dakkel unay ti panagpadakkelna.\nDagitoy nga argumento ket saanen a nairaman.",
+       "post-expand-template-argument-category": "Pampanid a naglaon dagiti saan a nairaman nga argumento ti plantilia",
+       "parser-template-loop-warning": "Nakaduktal ti silo ti plantilia: [[$1]]",
+       "parser-template-recursion-depth-warning": "Nalabsan ti patingga ti panagdullit ti kinauneg ti plantilia ($1)",
+       "language-converter-depth-warning": "Nalabsan ti patingga ti pagbaliwen a kinauneg ti pagsasao ($1)",
        "node-count-exceeded-category": "Dagiti panid a simmurok ti bilang ti nodo",
        "node-count-exceeded-category-desc": "Ti kategoria para kadagiti panid a nalabsan ti bilang ti nodo.",
        "node-count-exceeded-warning": "Ti panid ket nasurokanna ti bilang ti nodo",
        "expansion-depth-exceeded-category": "Dagiti panid a nasurokan ti kauneg ti panagpadakkel",
        "expansion-depth-exceeded-category-desc": "Daytoy ket kategoria para kadagiti panid a nalabsan ti kauneg ti panagpadakkel.",
        "expansion-depth-exceeded-warning": "Ti panid ket nasurokanna ti kauneg ti panagpadakkel",
-       "parser-unstrip-loop-warning": "Adda nakita a di-naukisan a silo",
-       "parser-unstrip-recursion-limit": "Ti di-naukisan a panagsumro manen a patingga ket nasurokan ($1)",
-       "converter-manual-rule-error": "Adda biddut a naduktalan idiay manual nga alagaden ti panagbalbaliw ti pagsasao",
-       "undo-success": "Ti panag-urnos ket saan a maisubli.\nPangngaasi a kitaen ti pagipadaan dita baba tapno maamuan no agpaypayso ti kayatmo nga aramiden, ken idulin dagiti sinukatan dita baba tapno malpas ti panagsubli ti inurnos.",
+       "parser-unstrip-loop-warning": "Nakaduktal ti di-naukisan a silo",
+       "parser-unstrip-recursion-limit": "Nalabsan ti patingga ti panagdullit ti di-naukisan ($1)",
+       "converter-manual-rule-error": "Adda biddut a naduktalan iti manual nga alagaden ti panagbalbaliw ti pagsasao",
+       "undo-success": "Ti panag-urnos ket saan a maisubli.\nPangngaasi a kitaen ti panangipada dita baba tapno maammuan no daytoy ti kayatmo nga aramiden, ken kalpasanna idulin dagiti sinukatan dita baba tapno malpas ti panagsubli ti inurnos.",
        "undo-failure": "Ti inurnos ket saan a maipasubli gaputa adda dagiti nakisinnungat a patingnga a naurnos.",
        "undo-norev": "Saan a maibabawi ti naurnos ngamin ket awan daytoy wenno mabalin a naikkaten.",
        "undo-nochange": "Ti inurnos ket kasla naibabawin.",
        "undo-summary": "Ibabawi ti $1 a binaliwan babaen ni [[Special:Contributions/$2|$2]] ([[User talk:$2|tungtungan]])",
        "undo-summary-username-hidden": "Isubli ti $1 a binaliwan babaen ti nailemmeng nga agar-aramat",
-       "cantcreateaccounttitle": "Saan a makaaramid ti pakabilangan",
-       "cantcreateaccount-text": "Ti panagaramid ti pakabilangan manipud ti daytoy nga IP a pagtaengan ('''$1''') ket sinerraan babaen ni [[User:$3|$3]].\n\nTi inted a rason babaen ni $3 ket ''$2''",
-       "cantcreateaccount-range-text": "Ti pannakapartuat ti pakabilangan manipud kadagiti pagtaengan ti IP iti sakop ti '''$1''', a mairaman ti IP a pagtaengam ('''$4'''), ket sinerraan babaen ni [[User:$3|$3]].\n\nTi inted a rason babaen ni $3 ket ''$2''",
+       "cantcreateaccounttitle": "Saan a makapartuat ti pakabilangan",
+       "cantcreateaccount-text": "Ti panagpartuat ti pakabilangan manipud ti daytoy nga IP a pagtaengan (<strong>$1</strong>) ket sinerraan babaen ni [[User:$3|$3]].\n\nTi inted a rason babaen ni $3 ket <em>$2</em>",
+       "cantcreateaccount-range-text": "Ti panagpartuat ti pakabilangan manipud kadagiti pagtaengan ti IP iti sakop ti '''$1''', a mairaman ti IP a pagtaengam ('''$4'''), ket sinerraan babaen ni [[User:$3|$3]].\n\nTi inted a rason babaen ni $3 ket ''$2''",
        "viewpagelogs": "Kitaen dagiti listaan para iti daytoy a panid",
        "nohistory": "Awan ti pakasaritaan ti panag-urnos iti daytoy a panid.",
-       "currentrev": "Kinaudi a binaliwan",
-       "currentrev-asof": "Kinaudi a panagbalbaliw manipud idi $1",
-       "revisionasof": "Panagbalbaliw manipud idi $1",
-       "revision-info": "Panagbaliw manipud idi $1 babaen ni {{GENDER:$6|$2}}$7",
-       "previousrevision": "←Daan a panagbalbaliw",
-       "nextrevision": "Nabarbaro a panagbalbaliw→",
-       "currentrevisionlink": "Kinaudi a binaliwan",
+       "currentrev": "Kinaudi a rebision",
+       "currentrev-asof": "Kinaudi a rebision manipud idi $1",
+       "revisionasof": "Rebision manipud idi $1",
+       "revision-info": "Rebision manipud idi $1 babaen ni {{GENDER:$6|$2}}$7",
+       "previousrevision": "← Nadadaan a rebision",
+       "nextrevision": "Nabarbaro a rebision →",
+       "currentrevisionlink": "Kinaudi a rebision",
        "cur": "agdama",
        "next": "sumaruno",
        "last": "naudi",
        "page_first": "umuna",
        "page_last": "naudi",
-       "histlegend": "Panagpili ti diperensia: Markaan dagiti kahon ti radio kadagiti panagbaliw tapno maipada ken pinduten ti serrek wenno ti buton dita baba.<br />\nLeyenda: <strong>({{int:cur}})</strong> = naggidiatan ti kinaudi a panagbaliw, <strong>({{int:last}})</strong> = naggidiatan ti sarsarunuen a panagbaliw , <strong>{{int:minoreditletter}}</strong> = bassit a panagbaliw.",
+       "histlegend": "Panagpili ti diperensia: Markaan dagiti kahon ti radio kadagiti rebision tapno maipada ken pinduten ti enter wenno ti buton dita baba.<br />\nLeyenda: <strong>({{int:cur}})</strong> = naggidiatan ti kinaudi a rebision, <strong>({{int:last}})</strong> = naggidiatan ti sarsarunuen a rebision, <strong>{{int:minoreditletter}}</strong> = bassit nga urnos.",
        "history-fieldset-title": "Agbasabasa ti pakasaritaan",
        "history-show-deleted": "Naikkat laeng",
        "histfirst": "kadaanan",
        "histlast": "kabaruan",
        "historysize": "({{PLURAL:$1|1 byte|dagiti $1 a byte}})",
-       "historyempty": "(blanko)",
-       "history-feed-title": "Pakasaritaan ti panagbalbaliw",
-       "history-feed-description": "Pakasaritaan ti panagbalbaliw para iti daytoy a panid ditoy a wiki",
-       "history-feed-item-nocomment": "$1 iti $2",
+       "historyempty": "(awan linaon)",
+       "history-feed-title": "Pakasaritaan ti rebision",
+       "history-feed-description": "Pakasaritaan ti rebision para iti daytoy a panid ditoy a wiki",
+       "history-feed-item-nocomment": "$1 idi $2",
        "history-feed-empty": "Awan ti kiniddaw a panid.\nMabalin a naikkat manipud ti daytoy a wiki, wenno nanaganan manen.\nPadasem ti [[Special:Search|agbiruk ditoy a wiki]] para kadagiti maitutop a baro a panid.",
        "rev-deleted-comment": "(naikkat ti pakabuklan ti inurnos)",
        "rev-deleted-user": "(naikkat ti nagan ti agar-aramat)",
-       "rev-deleted-event": "(naikkat ti aramid a listaan)",
-       "rev-deleted-user-contribs": "[ti nagan ti agar-aramat wenno IP a pagtaengan ket naikkat - ti inurnos ket nailemmeng kadagiti nagparawad]",
-       "rev-deleted-text-permission": "Ti pannakabaliw daytoy a panid ket '''naikkaten'''.\nDagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti naikkat].",
-       "rev-deleted-text-unhide": "Ti pannakabaliw daytoy a panid ket '''naikkaten'''.\nDagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti naikkat].\nMabalinmo pay a [$1 makita daytoy a panakabaliw] no kayatmo ti agtuloy.",
-       "rev-suppressed-text-unhide": "Ti pannakabaliw daytoy a panid ket '''napasardeng'''.\nDagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} listaan ti napasardeng].\nMabalinmo pay a [$1 makita daytoy a panakabaliw] no kayatmo ti agtuloy.",
-       "rev-deleted-text-view": "Ti pannakabaliw daytoy a panid ket '''naikkaten'''.\nMabalinmo a kitaen; dagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti naikkat].",
-       "rev-suppressed-text-view": "Ti pannakabaliw daytoy a panid ket '''napasardeng'''.\nMabalinmo a kitaen; dagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} listaan ti napasardeng].",
-       "rev-deleted-no-diff": "Saanmo a makita daytoy a paggiddiatan ngamin ket ti maysa a panagbaliw ket '''naikkat''.\nDagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti naikkat].",
-       "rev-suppressed-no-diff": "Saanmo a makita daytoy a paggiddiatan ngamin ket maysa a panagbaliwan ket '''naikkat''.",
-       "rev-deleted-unhide-diff": "Maysa a panagbaliw iti daytoy a paggiddiatan ket '''naikkaten'''.\nDagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti naikkat].\nMabalinmo pay a [$1 makita daytoy a paggiddiatan] no kayatmo ti agtuloy.",
-       "rev-suppressed-unhide-diff": "Maysa a panagbaliw iti daytoy a paggiddiatan ket '''napasardeng'''.\nDagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} listaan ti napasardeng].\nMabalinmo pay a [$1 makita daytoy a paggiddiatan] no kayatmo ti agtuloy.",
-       "rev-deleted-diff-view": "Maysa a panagbaliw iti daytoy a paggiddiatan ket '''naikkaten'''.\nMabalinmo pay a kitaen daytoy a paggiddiatan; dagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti naikkat].",
-       "rev-suppressed-diff-view": "Maysa a panagbaliw iti daytoy a paggiddiatan ket '''napasardeng'''.\nMabalinmo pay a kitaen daytoy a paggiddiatan; dagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} listaan ti napasardeng].",
-       "rev-delundel": "ipakita/ilemmeng",
+       "rev-deleted-event": "(naikkat ti listaan ti tignay)",
+       "rev-deleted-user-contribs": "[naikkat ti nagan ti agar-aramat wenno IP a pagtaengan - ti inurnos ket nailemmeng manipud kadagiti kontributor]",
+       "rev-deleted-text-permission": "Ti rebision daytoy a panid ket <strong>naikkaten</strong>.\nDagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti panagikkat].",
+       "rev-suppressed-text-permission": "Ti rebision daytoy a panid ket <strong>napasardeng</strong>.\nDagiti salaysay ket mabalin a mabirukan idiay [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} listaan ti panagpasardeng].",
+       "rev-deleted-text-unhide": "Ti rebision daytoy a panid ket <strong>naikkaten</strong>.\nDagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti panagikkat].\nMabalinmo pay a [$1 makita daytoy a rebision] no kayatmo ti agtuloy.",
+       "rev-suppressed-text-unhide": "Ti rebision daytoy a panid ket <strong>napasardeng</strong>.\nDagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} listaan ti panagpasardeng].\nMabalinmo pay a [$1 makita daytoy a rebision] no kayatmo ti agtuloy.",
+       "rev-deleted-text-view": "Ti rebision daytoy a panid ket <strong>naikkaten</strong>.\nMabalinmo a kitaen; dagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti panagikkat].",
+       "rev-suppressed-text-view": "Ti rebision daytoy a panid ket <strong>napasardeng</strong>.\nMabalinmo a kitaen; dagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} listaan ti panagpasardeng].",
+       "rev-deleted-no-diff": "Saanmo a makita daytoy a paggiddiatan ngamin ket ti maysa a rebision ket <strong>naikkaten</strong>.\nDagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti panagikkat].",
+       "rev-suppressed-no-diff": "Saanmo a makita daytoy a paggiddiatan ngamin ket maysa kadagiti rebision ket <strong>naikkaten</strong>.",
+       "rev-deleted-unhide-diff": "Maysa a rebision iti daytoy a paggiddiatan ket <strong>naikkaten</strong>.\nDagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti panagikkat].\nMabalinmo pay a laeng a [$1 makita daytoy a paggiddiatan] no kayatmo ti agtuloy.",
+       "rev-suppressed-unhide-diff": "Maysa a rebision iti daytoy a paggiddiatan ket <strong>napasardeng</strong>.\nDagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} listaan ti panagpasardeng].\nMabalinmo pay a laeng a [$1 makita daytoy a paggiddiatan] no kayatmo ti agtuloy.",
+       "rev-deleted-diff-view": "Maysa a rebision iti daytoy a paggiddiatan ket <strong>naikkaten</strong>.\nMabalinmo pay a kitaen daytoy a paggiddiatan; dagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti panagikkat].",
+       "rev-suppressed-diff-view": "Maysa a rebision iti daytoy a paggiddiatan ket <strong>napasardeng</strong>..\nMabalinmo pay a kitaen daytoy a paggiddiatan; dagiti salaysay ket mabirukan idiay [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} listaan ti panagpasardeng].",
+       "rev-delundel": "baliwan ti pannakakita",
        "rev-showdeleted": "ipakita",
-       "revisiondelete": "Ikkaten/isubli dagiti naikkat a panagbaliw",
-       "revdelete-nooldid-title": "Imbalido ti napuntaan a panagbaliw",
-       "revdelete-nooldid-text": "Mabalin a saanmo nga imbaga ti pagpuntaan ti panagbaliw  (dagiti panagbaliwan) ti panagaramid daytoy,\nawan ti naibaga a panagbaliw, wenno padpadasem nga ilemlemmeng ti agdama a panagbaliw.",
+       "revisiondelete": "Ikkaten/isubli dagiti naikkat a rebision",
+       "revdelete-nooldid-title": "Imbalido ti puntaan a rebision",
+       "revdelete-nooldid-text": "Mabalin a saanmo nga imbaga dagiti puntaan a rebision iti panagaramid daytoy nga annong, awan ti nainaganan a rebision, wenno padpadasem nga ilemlemmeng ti agdama a rebision.",
        "revdelete-no-file": "Awan dayta nainaganan a papeles.",
-       "revdelete-show-file-confirm": "Sigurado kadi a kayatmo ti mangkita ti naikkat a baliwan ti papeles \"<nowiki>$1</nowiki>\" a naggapu idi $2 idi $3?",
+       "revdelete-show-file-confirm": "Siguradoka kadi a kayatmo ti mangkita ti naikkat a rebision ti papeles ti \"<nowiki>$1</nowiki>\" manipud idi $2 idi $3?",
        "revdelete-show-file-submit": "Wen",
-       "revdelete-selected-text": "{{PLURAL:$1|Napili a nabaliwan|Dagiti napili a nabaliwan}} iti [[:$2]]:",
+       "revdelete-selected-text": "{{PLURAL:$1|Napili a rebision|Dagiti napili a rebision}} iti [[:$2]]:",
        "revdelete-selected-file": "{{PLURAL:$1|Napili a bersion ti papeles|Dagiti napili a bersion ti papeles}} iti [[:$2]]:",
        "logdelete-selected": "{{PLURAL:$1|Ti napili a listaan ti napasamak|Dagiti napili a listaan ti napasamak}}:",
        "revdelete-text-text": "Dagiti naikkat a rebision ket agparangto pay laeng iti panid ti pakasaritaan, ngem dagiti paset ti linaonda ket saanton a publiko a maserrekan.",
        "revdelete-text-file": "Dagiti naikkat a bersion ti papeles ket agparangto pay laeng iti pakasaritaan ti papeles, ngem dagiti paset ti linaonda ket saanton a publiko a maserrekan.",
        "logdelete-text": "Dagiti naikkat a listaan ti pasamak ket agparangto pay laeng kadagiti listaan, ngem dagiti paset ti linaonda ket saanton a publiko a maserrekan.",
-       "revdelete-text-others": "Dagiti sabali nga administrador iti {{SITENAME}} ket mabalindanto pay laeng a maserrekan ti nailemmeng a linaon ken mabalindanto manen ti mangisubli ti pannakaikkat babaen iti daytoy nga isu met laeng nga interface, malaksid no adda dagiti maipatinayon a maisaad a panangigawid.",
-       "revdelete-confirm": "Pangngaasi a pasingkedam a kayatmo nga aramiden daytoy, a maawatam dagiti pagbanagan, ket araramidem daytoy a segun iti [[{{MediaWiki:Policy-url}}|ti annuroten]].",
-       "revdelete-suppress-text": "Ti panagdepdep ket usaren '''laeng''' kadagiti sumaganad a kaso;\n* Makapataud ti libelo a pakaammo\n* Di maiparbeng a personal a pakaammo\n* : ''dagiti pagtaengan ken numero ti telepono, dagiti numero ti nailian a pakaipakaammuan, ken dadduma pay.''",
-       "revdelete-legend": "Ikabil dagiti panagiparit ti panagkita",
-       "revdelete-hide-text": "Testo ti binaliwan",
+       "revdelete-text-others": "Dagiti sabali nga administrador ket mabalindanto pay laeng a maserrekan ti nailemmeng a linaon ken mangisubli daytoy, malaksid no adda dagiti maipatinayon a maisaad a panangigawid.",
+       "revdelete-confirm": "Pangngaasi a pasingkedam a kayatmo nga aramiden daytoy, a maawatam dagiti pagbanagan, ken araramidem daytoy segun [[{{MediaWiki:Policy-url}}|ti annuroten]].",
+       "revdelete-suppress-text": "Ti panagdepdep ket usaren <strong>laeng</strong> kadagiti sumaganad a kaso;\n* Makapataud ti libelo a pakaammo\n* Di maiparbeng a personal a pakaammo\n* : <em>dagiti adres ti balay ken numero ti telepono, dagiti numero ti nailian a pakaipakaammuan, kdpy.</em>",
+       "revdelete-legend": "Isaad dagiti panangigawid ti panagkita",
+       "revdelete-hide-text": "Testo ti rebision",
        "revdelete-hide-image": "Ilemmeng ti linaon ti papeles",
        "revdelete-hide-name": "Ilemmeng ti aramid ken puntaan",
        "revdelete-hide-comment": "Pakabuklan ti inurnos",
-       "revdelete-hide-user": "Nagan ti agar-amat/ti IP a pagtaengan",
-       "revdelete-hide-restricted": "Depdepen ti datos a naggapu kadagiti administrador ken dagiti sabsabali",
+       "revdelete-hide-user": "Nagan ti agar-amat/IP a pagtaengan ti editor",
+       "revdelete-hide-restricted": "Depdepen ti datos manipud kadagiti administrador ken dagiti pay sabali",
        "revdelete-radio-same": "(saan a sukatan)",
        "revdelete-radio-set": "Nailemmeng",
        "revdelete-radio-unset": "Makita",
-       "revdelete-suppress": "Depdepen ti datos manipud kadagiti administrador ken dagiti sabsabali",
-       "revdelete-unsuppress": "Ikkaten dagiti pannakaiparit kadagiti naisubli a binaliwan",
+       "revdelete-suppress": "Depdepen ti datos manipud kadagiti administrador ken dagiti pay sabali",
+       "revdelete-unsuppress": "Ikkaten dagiti panangigawid kadagiti naipulang a rebision",
        "revdelete-log": "Rason:",
-       "revdelete-submit": "Ipakat {{PLURAL:$1|ti napili a panagbalbaliw|dagiti napili a panagbalbaliw}}",
-       "revdelete-success": "'''Balligi ti panagpabaro ti panagkita ti binalbaliwan.'''",
-       "revdelete-failure": "'''Saan a napabaro ti panagkita ti binalbaliwan.'''\n$1",
-       "logdelete-success": "'''Balligi ti panagikabil ti listaan ti panagkita.'''",
-       "logdelete-failure": "'''Napaay ti panagikabil ti listaan ti panagkita:'''\n$1",
+       "revdelete-submit": "Ipakat {{PLURAL:$1|ti napili a rebision|dagiti napili a rebision}}",
+       "revdelete-success": "<strong>Balligi ti panagpabaro ti panagkita ti rebision.</strong>",
+       "revdelete-failure": "<strong>Saan a napabaro ti panagkita ti rebision.</strong>\n$1",
+       "logdelete-success": "<strong>Balligi ti pannakaisaad ti listaan ti panagkita.</strong>",
+       "logdelete-failure": "<strong>Napaay ti pannakaisaad ti listaan ti panagkita:</strong>\n$1",
        "revdel-restore": "sukatan ti panagkita",
        "pagehist": "Pakasaritaan ti panid",
        "deletedhist": "Naikkat a pakasaritaan",
-       "revdelete-hide-current": "Biddut ti pannakailemmeng ti banag a napetsado a $2, $1: Daytoy ti kinaudi a panagbaliw\nSaan a mabalin a mailemmeng.",
-       "revdelete-show-no-access": "Biddut ti panangipakita ti banag a petsado a $2, $1: Daytoy ket namarkaan a \"nakedngan\".\nSaanmo a mabalin a serrekan.",
-       "revdelete-modify-no-access": "Biddut ti panagpabaro ti banag a petsado a $2, $1: Daytoy ket namarkaan a \"nakedngan\".\nSaanmo a mabalin a serrekan.",
-       "revdelete-modify-missing": "Biddut ti panagpabaro daytoy ID $1: Saan a nasarakan idiay database!",
-       "revdelete-no-change": "'''Ballaag:''' Daytoy a banag a napetsado ti  $2, $1 ket addaan ti kiniddaw kadagiti panagkita a kasasaad.",
-       "revdelete-concurrent-change": "Biddut ti panagpabaro daytoy a banag a napetsado ti  $2, $1: Ti panakaikabilna ket mabalin a nasuktanen ti sabsabli idi pinada mo a pinabaro.\nPangngaasi a kitaen dagiti listaan.",
-       "revdelete-only-restricted": "Biddut ti panagilemmeng daytoy banag a napetsado ti $2, $1: Saanmo a maidepdep dagita iti panagkita dagiti adminitrador no saanmo a pilian ti maysa kadagiti pinagpili ti panagkita.",
-       "revdelete-reason-dropdown": "*Dagiti kadawyan a rason ti panagikkat\n** Panaglabsing ti karbengan ti kopia\n** Di maiparbeng a komentario wenno kabukbukodan a pakaammo\n** Di maiparbeng a nagan ti agar-aramat\n** Adda pannakabalinna a pammadpadakes a pakaammo",
+       "revdelete-hide-current": "Biddut ti pannakailemmeng ti banag a napetsado ti $2, $1: Daytoy ti kinaudi a rebision.\nSaan a mabalin a mailemmeng.",
+       "revdelete-show-no-access": "Biddut ti panangipakita ti banag a petsado ti $2, $1: Daytoy ket namarkaan a \"nagawidan\".\nSaanmo a mabalin a serrekan.",
+       "revdelete-modify-no-access": "Biddut ti panagpabaro ti banag a petsado ti $2, $1: Daytoy ket namarkaan a \"nagawidan\".\nSaanmo a mabalin a serrekan.",
+       "revdelete-modify-missing": "Biddut ti panagpabaro daytoy ID $1: Awan daytoy manipud ti database!",
+       "revdelete-no-change": "<strong>Ballaag:</strong> Daytoy a banag a napetsado ti $2, $1 ken addaan ti kiniddaw a panagkita ti pannakaisaad.",
+       "revdelete-concurrent-change": "Biddut ti panagpabaro daytoy a banag a napetsado ti  $2, $1: Ti kasasaadna ket mabalin a nasukatanen ti sabali idi pinadasmo a pinabaro.\nPangngaasi a kitaen dagiti listaan.",
+       "revdelete-only-restricted": "Biddut ti panagilemmeng daytoy banag a napetsado ti $2, $1: Saanmo a maidepdep dagita iti panagkita dagiti adminitrador no saanmo a pilien ti maysa kadagiti pagpilian ti panagkita.",
+       "revdelete-reason-dropdown": "*Dagiti kadawyan a rason ti panagikkat\n** Panaglabsing ti karbengan ti kopia\n** Di maiparbeng a komentario wenno kabukbukodan a pakaammo\n** Di maiparbeng a nagan ti agar-aramat\n** Mabalin a pammadpadakes a pakaammo",
        "revdelete-otherreason": "Sabali/maipatinayon a rason:",
        "revdelete-reasonotherlist": "Sabali a rason",
        "revdelete-edit-reasonlist": "Urnosen dagiti rason ti panagikkat",
-       "revdelete-offender": "Nangsukat a mannurat:",
+       "revdelete-offender": "Mannurat ti rebision:",
        "suppressionlog": "Listaan ti nadepdepan",
-       "suppressionlogtext": "Dita baba ket addaan dagiti listaan ti pinagikkat ken panagserra a nairaman dagiti linaon a nailemmeng manipud kadagiti administrador.\nKitaen ti [[Special:BlockList|Listaan ti lapden nga IP]] para iti listaan kadagiti agdama nga operasional a panagparit ken panagserra.",
-       "mergehistory": "Pagtiponen dagiti pakasaritaan ti pampanid",
-       "mergehistory-header": "Daytoy a panid ket mabalinmo ti agitipon kadagiti pinagbaliwan ti pakasaritaan iti maysa a taudan idiay barbaro a panid.\nMasapul a sigaraduem a daytoy a panagsukat ket agsustento ti panakaituloy ti pakasaritaan ti panid.",
-       "mergehistory-box": "Pagtiponen dagiti nasukatan iti dua a pampanid:",
+       "suppressionlogtext": "Dita baba ket listaan dagiti panagikkat ken panagserra a nairaman kadagiti linaon a nailemmeng manipud kadagiti administrador.\nKitaen ti [[Special:BlockList|listaan ti serra]] para iti listaan kadagiti agdama nga operasional a panagiparit ken dagiti panagserra.",
+       "mergehistory": "Pagtiponen dagiti pakasaritaan ti panid",
+       "mergehistory-header": "Daytoy a panid ket mangpakabael kenka nga agitipon kadagiti rebision ti pakasaritaan iti maysa a taudan iti barbaro a panid.\nMasapul a siguraduen no daytoy a panagsukat ket agsustento ti pannakaituloy ti pakasaritaan ti panid.",
+       "mergehistory-box": "Pagtiponen dagiti rebision iti dua a pampanid:",
        "mergehistory-from": "Taudan ti panid:",
        "mergehistory-into": "Pangipanan a panid:",
        "mergehistory-list": "Mabalin nga itipon a pakasaritaan ti inurnos",
-       "mergehistory-merge": "Dagiti sumaganad a panagbaliw iti [[:$1]] ket mabalin nga itipon iti [[:$2]].\nUsaren ti radio a buton a tukol ti pinagtipon iti laeng panagbaliw a naaramid idiay ken sakbay ti nainagan nga oras.",
+       "mergehistory-merge": "Dagiti sumaganad a rebision iti [[:$1]] ket mabalin nga itipon iti [[:$2]].\nUsaren ti radio a buton a tukol ti panagtipon iti laeng panagbaliw a napartuat iti ken sakbay ti nainagan nga oras.\nLaglagipen a ti panag-usar kadagiti silpo ti pagdaliasatan ket mangisaad manen iti daytoy a batong.",
        "mergehistory-go": "Ipakita dagiti mabalin a maitipon a panag-urnos",
-       "mergehistory-submit": "Pagtitiponen dagiti binalbaliwan",
-       "mergehistory-empty": "Awan dagiti mabalin nga itipon ti panagbalbaliw.",
-       "mergehistory-success": "$3 {{PLURAL:$3|a binaliwan|dagiti binaliwan}} ti [[:$1]] balligi ti panagitipon idiay [[:$2]].",
-       "mergehistory-fail": "Saan a nakaaramid ti panagtipon ti pakasaritaan, pangngaasi ta kitaen ti panid ken parametro ti oras.",
-       "mergehistory-no-source": "Awan ti taudan ti panid a $1.",
-       "mergehistory-no-destination": "Awan ti papanan ti panid a $1.",
+       "mergehistory-submit": "Pagtitiponen dagiti rebision",
+       "mergehistory-empty": "Awan dagiti rebision ti mabalin nga itipon.",
+       "mergehistory-success": "$3 {{PLURAL:$3|a rebision|dagiti rebision}} iti [[:$1]] ket nagballigi a naitipon iti [[:$2]].",
+       "mergehistory-fail": "Saan a nakaaramid ti panagtipon ti pakasaritaan, pangngaasi a kitaen ti panid ken dagiti parametro ti oras.",
+       "mergehistory-fail-toobig": "Di naaramid ti panagtipon ti pakasaritaan gapu ta ad-adu ti patingga ti $1 {{PLURAL:$1|a rebision|kadagiti rebision}} ti maiyalisto.",
+       "mergehistory-no-source": "Awan ti taudan ti panid ti $1.",
+       "mergehistory-no-destination": "Awan ti papanan ti panid ti $1.",
        "mergehistory-invalid-source": "Masapul nga adda ti umisu a titulo ti taudan ti panid.",
-       "mergehistory-invalid-destination": "Ti pangipanan ti panid ket masapul nga umisu a titulo.",
+       "mergehistory-invalid-destination": "Ti pangipanan a panid ket masapul nga umisu a titulo.",
        "mergehistory-autocomment": "Naitipon ti [[:$1]] iti [[:$2]]",
        "mergehistory-comment": "Naitipon ti [[:$1]] iti [[:$2]]: $3",
        "mergehistory-same-destination": "Ti nagtaudan ken ti pangipanan ti panid ket saan a mabalin nga agpada",
        "mergehistory-reason": "Rason:",
        "mergelog": "Listaan ti panagtipon",
-       "pagemerge-logentry": "itipon ti [[$1]] iti [[$2]] (dagiti binaliwan aginggana iti $3)",
+       "pagemerge-logentry": "itipon ti [[$1]] iti [[$2]] (dagiti rebision aginggana iti $3)",
        "revertmerge": "Pagsinaen",
-       "mergelogpagetext": "Adda dita baba ti listaan dagiti kinaudian a panagtipon ti maysa a panid ti pakasaritaan iti maysa a sabali.",
-       "history-title": "Panagbalbaliw a pakasaritaan iti \"$1\"",
-       "difference-title": "Paggiddiatan a nagbaetan dagiti panagbalbaliw iti \"$1\"",
+       "mergelogpagetext": "Dita baba ket ti listaan dagiti kaudian a panagtipon ti maysa a pakasaritaan ti panid iti sabali.",
+       "history-title": "Pakasaritaan a rebision iti \"$1\"",
+       "difference-title": "Paggiddiatan a nagbaetan dagiti rebision iti \"$1\"",
        "difference-title-multipage": "Paggiddiatan a nagbaetan dagiti panid  \"$1\" ken \"$2\"",
        "difference-multipage": "(Paggiddiatan dagiti panid)",
        "lineno": "Linia $1:",
-       "compareselectedversions": "Ipada dagiti pinili a binaliwan",
-       "showhideselectedversions": "Ipakita/ilemmeng dagiti napili a nabaliwan",
+       "compareselectedversions": "Ipada dagiti pinili a rebision",
+       "showhideselectedversions": "Ipakita/ilemmeng dagiti napili a rebision",
        "editundo": "ibabawi",
-       "diff-empty": "(Awan ti paggiddiatan)",
-       "diff-multi-sameuser": "({{PLURAL:$1|Maysa nga agtengnga a panagbaliw|Dagiti $1 nga agtengnga a panagbaliw}} babaen ti isu met laeng nga agar-aramat a saan a naipakita)",
-       "diff-multi-otherusers": "({{PLURAL:$1|Maysa nga agtengnga a panagbaliw|Dagiti $1 nga agtengnga a panagbaliw}} babaen {{PLURAL:$2|ti maysa a sabali nga agar-aramat|dagiti $2 nga agar-aramat}} a saan a naipakita)",
-       "diff-multi-manyusers": "({{PLURAL:$1|Maysa nga agtengnga a panangbalbaliw|Dagiti $1 nga agtengnga a panangbalbaliw}} babaen ti ad-adu ngem $2 {{PLURAL:$2|nga agar-aramat|kadagiti agar-aramat}} ti saan a naipakita)",
-       "difference-missing-revision": "{{PLURAL:$2|Maysa a panagbalbaliw|$2 kadagiti panagbalbaliw}} iti daytoy a paggiddiatan ($1) {{PLURAL:$2|ket ti|ket dagiti}} saan a naburikan.\n\nDaytoy ket kadawyan a gapuanan babaen ti sumaganad a nabaak a panilpo tipaggiddiatan ti maysa a panid a naikkaten.\nDagiti salaysay ket mabalin a mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti panagikkat].",
+       "diff-empty": "(Awan paggiddiatan)",
+       "diff-multi-sameuser": "({{PLURAL:$1|Maysa nga agtengnga a rebision|Dagiti $1 nga agtengnga a rebision}} babaen ti isu met laeng nga agar-aramat a saan a naipakita)",
+       "diff-multi-otherusers": "({{PLURAL:$1|Maysa nga agtengnga a rebision|Dagiti $1 nga agtengnga a rebision}} babaen {{PLURAL:$2|ti maysa a sabali nga agar-aramat|dagiti $2 nga agar-aramat}} a saan a naipakita)",
+       "diff-multi-manyusers": "({{PLURAL:$1|Maysa nga agtengnga a rebision|Dagiti $1 nga agtengnga a rebision}} babaen ti ad-adu ngem $2 {{PLURAL:$2|nga agar-aramat|kadagiti agar-aramat}} ti saan a naipakita)",
+       "difference-missing-revision": "{{PLURAL:$2|Maysa a rebision|$2 kadagiti rebision}} iti daytoy a paggiddiatan ($1) {{PLURAL:$2|ket ti|ket dagiti}} saan a naburikan.\n\nDaytoy ket kadawyan a gapuanan babaen ti sumaganad a nabaak a silpo ti paggiddiatan ti maysa a panid a naikkaten.\nDagiti salaysay ket mabalin a mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti panagikkat].",
        "searchresults": "Dagiti nagbanagan ti panagbiruk",
        "searchresults-title": "Dagiti nabirukan a nagbanagan para iti \"$1\"",
        "titlematches": "Dagiti kapadpada a titulo ti panid",
        "textmatches": "Dagiti agpapada a testo ti panid",
        "notextmatches": "Awan dagiti kapadpada a testo ti panid",
-       "prevn": "napalabas {{PLURAL:$1|$1}}",
-       "nextn": "sumaruno {{PLURAL:$1|$1}}",
+       "prevn": "napalabas {{PLURAL:$1|$1}}",
+       "nextn": "sumaruno {{PLURAL:$1|$1}}",
        "prevn-title": "Napalabas a $1 {{PLURAL:$1|a nagbanagan|kadagiti nagbanagan}}",
        "nextn-title": "Sumaruno a $1 {{PLURAL:$1|a nagbanagan|kadagiti nagbanagan}}",
        "shown-title": "Ipakita ti $1 {{PLURAL:$1|a nagbanagan|kadagiti nagbanagan}}  ti tunggal maysa a panid",
-       "viewprevnext": "Kitaen ($1 {{int:pipe-separator}} $2) ($3)",
-       "searchmenu-exists": "'''Adda panid a nanaganan ti \"[[:$1]]\" iti daytoy a wiki.'''",
+       "viewprevnext": "Kitaen dagiti ($1 {{int:pipe-separator}} $2) ($3)",
+       "searchmenu-exists": "<strong>Adda panid a nanaganan ti \"[[:$1]]\" iti daytoy a wiki.</strong> {{PLURAL:$2|0=|Kitaen pay ti sabali a nabirukan a nagbanagan ti panagbiruk.}}",
        "searchmenu-new": "<strong>Partuaten ti panid ti \"[[:$1]]\" iti daytoy a wiki!</strong> {{PLURAL:$2|0=|Kitaen pay ti panid a nabirukan ti panagbirukmo.|Kitaen pay dagiti resulta a nabirukan ti panagbiruk.}}",
        "searchprofile-articles": "Dagiti naglaon a panid",
-       "searchprofile-images": "Sabsabali a midia",
+       "searchprofile-images": "Multimidia",
        "searchprofile-everything": "Amin amin",
        "searchprofile-advanced": "Napasayaat",
        "searchprofile-articles-tooltip": "Agbirukka idiay $1",
        "searchprofile-images-tooltip": "Agbirukka para iti papeles",
-       "searchprofile-everything-tooltip": "Birukem amin a linaon (uray dagiti makipatangan a panid)",
-       "searchprofile-advanced-tooltip": "Agbirukka kadagiti naiduma a \"nagan ti espasio\"",
+       "searchprofile-everything-tooltip": "Birukem amin a linaon (uray dagiti tungtungan a panid)",
+       "searchprofile-advanced-tooltip": "Agbirukka kadagiti naiduma a nagan ti espasio",
        "search-result-size": "$1 ({{PLURAL:$2|iti 1 a balikas|kadagiti $2 a balikas}})",
-       "search-result-category-size": "{{PLURAL:$1|1 a kameng| dagiti $1 a kameng}} ({{PLURAL:$2|1 a subkategoria|dagiti $2  a sukategoria}}, {{PLURAL:$3|1 a papeles|dagiti $3 a papeles}})",
-       "search-result-score": "Kaitutopan: $1%",
-       "search-redirect": "(ibaw-ing ti $1)",
+       "search-result-category-size": "{{PLURAL:$1|1 a kameng| dagiti $1 a kameng}} ({{PLURAL:$2|1 a subkategoria|dagiti $2  a subkategoria}}, {{PLURAL:$3|1 a papeles|dagiti $3 a papeles}})",
+       "search-redirect": "(baw-ing ti $1)",
        "search-section": "(paset $1)",
        "search-file-match": "(maipada ti linaon a papeles)",
        "search-suggest": "Daytoy kadi: $1",
        "search-relatedarticle": "Mainaig",
        "searchrelated": "mainaig",
        "searchall": "amin",
-       "showingresults": "Maiparang dita baba agingga {{PLURAL:$1|iti '''1''' a nagbanagan|dagiti '''$1''' a nagbanagan}} a mangrugi iti #'''$2'''.",
+       "showingresults": "Maiparang dita baba agingga {{PLURAL:$1|iti <strong>1</strong> a nagbanagan|dagiti <strong>$1</strong> a nagbanagan}} a mangrugi ti #<strong>$2</strong>.",
        "showingresultsinrange": "Mangipakpakita aginggana {{PLURAL:$1|iti <strong>1</strong> a resulta|dagiti <strong>$1</strong> a resulta}} iti sakop ti #<strong>$2</strong> aginggana ti #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Nagbanagan a '''$1''' iti '''$3'''|Dagiti Nagbanagan a '''$1 - $2''' iti '''$3'''}} para iti '''$4'''",
-       "search-nonefound": "Awan ti nagbanagan a kapadpada ti sinapul.",
+       "showingresultsheader": "{{PLURAL:$5|Nagbanagan a <strong>$1</strong> iti <strong>$3</strong>|Dagiti Nagbanagan a <strong>$1 - $2</strong> iti <strong>$3</strong>}} para iti <strong>$4</strong>",
+       "search-nonefound": "Awan dagiti nagbanagan a maipada ti usisa.",
        "powersearch-legend": "Napasayat a panagbiruk",
-       "powersearch-ns": "Agbirukka kadagiti nagan ti espasio:",
+       "powersearch-ns": "Agbiruk kadagiti nagan ti espasio:",
        "powersearch-togglelabel": "Markaan:",
        "powersearch-toggleall": "Amin",
        "powersearch-togglenone": "Awan",
        "powersearch-remember": "Lagipen ti napili para kadagiti masakbayan a panagbiruk",
        "search-external": "Akinruar a panagbiruk",
        "searchdisabled": "Ti panagbiruk iti {{SITENAME}} ket nabaldado.\nMabalinmo ti agbiruk idiay Google tattan.\nLaglagipem laeng a dagiti pagsurotan nagyan ti {{SITENAME}} ket baka baak.",
-       "search-error": "Adda maysa a biddut  napasamak bayat nga agbirbiruk:$1",
+       "search-error": "Adda maysa a biddut a napasamak bayat nga agbirbiruk:$1",
        "preferences": "Kakaykayatan",
        "mypreferences": "Kakaykayatan",
        "prefs-edits": "Bilang dagiti inurnos:",
        "prefs-labs": "Dagiti subokan a langa",
        "prefs-user-pages": "Dagiti panid ti agar-aramat",
        "prefs-personal": "Bariweswes ti agar-aramat",
-       "prefs-rc": "Kinaudi a binalbaliwan",
+       "prefs-rc": "Kaudian a balbaliw",
        "prefs-watchlist": "Listaan ti bambantayan",
-       "prefs-watchlist-days": "Al-aldaw nga iparang idiay listaan ti bambantayan:",
+       "prefs-watchlist-days": "Al-aldaw nga iparang iti listaan ti bambantayan:",
        "prefs-watchlist-days-max": "Kapaut nga $1 {{PLURAL:$1|nga aldaw|nga al-aldaw}}",
-       "prefs-watchlist-edits": "Kaadu a bilang ti ipakita kadagiti sinukatan iti napadakkel a bambantayan:",
+       "prefs-watchlist-edits": "Kaadu a bilang ti ipakita kadagiti sinukatan iti napadakkel a listaan ti bambantayan:",
        "prefs-watchlist-edits-max": "Kaadu a bilang: 1000",
-       "prefs-watchlist-token": "Tandaan ti bambantayan:",
+       "prefs-watchlist-token": "Tandaan ti listaan ti bambantayan:",
        "prefs-misc": "Sabsabali",
        "prefs-resetpass": "Sukatan ti kontrasenias",
        "prefs-changeemail": "Sukatan ti esurat a pagtaengan",
-       "prefs-setemail": "Ikabil ti esurat a pagtaengan",
-       "prefs-email": "Pagpilian ti esurat",
+       "prefs-setemail": "Isaad ti esurat a pagtaengan",
+       "prefs-email": "Dagiti pagpilian ti esurat",
        "prefs-rendering": "Tabas",
        "saveprefs": "Idulin",
-       "restoreprefs": "Isubli amin dagiti kasisigud a pannakaiyasentar (kadagiti amin a paset)",
+       "restoreprefs": "Isubli amin dagiti kasisigud a pannakaisaad (kadagiti amin a paset)",
        "prefs-editing": "Ur-urnosen",
        "rows": "Ar-aray:",
        "columns": "Tuk-tukol:",
        "searchresultshead": "Biruken",
        "stub-threshold": "Pagpatinggaan para iti panagporma ti <a href=\"#\" class=\"stub\">pungol a silpo</a> (dagiti byte):",
        "stub-threshold-disabled": "Nabaldado",
-       "recentchangesdays": "Al-aldaw nga ipakita dagiti kinaudi a binalbaliwan:",
+       "recentchangesdays": "Al-aldaw nga ipakita iti kaudian a balbaliw:",
        "recentchangesdays-max": "Kapaut nga $1 {{PLURAL:$1|nga aldaw|nga al-aldaw}}",
-       "recentchangescount": "Dagiti bilang dagiti naurnos a kinasigud a maiparang:",
-       "prefs-help-recentchangescount": "Nairaman dagiti kinaudian a baliwan, dagiti pakasaritaan ti panid, ken dagiti listaan.",
-       "prefs-help-watchlist-token2": "Daytoy ti sekreto a tulbek iti pakan ti web iti listaan ti banbantayam.\nTi sinoman a makaammo daytoy ket mabalinda a basaen ti listaan ti banbantayam, isunga saanmo nga ipabingay.\n[[Special:ResetTokens|Pindutem ditoy no kayatmo nga iyasentar manen]].",
+       "recentchangescount": "Bilang dagiti inurnos nga ipakita babaen ti kinasigud:",
+       "prefs-help-recentchangescount": "Daytoy ket mangiraman iti kaudian a balbaliw, dagiti pakasaritaan ti panid, ken dagiti listaan.",
+       "prefs-help-watchlist-token2": "Daytoy ti sekreto a tulbek iti pakan ti web iti listaan ti bambantayam.\nTi sinoman a makaammo daytoy ket mabalinda a basaen ti listaan ti bambantayam, isu a saanmo nga ipabingay.\nNo masapulmo, [[Special:ResetTokens|mabalinmo nga isaad manen]].",
        "savedprefs": "Naidulinen dagiti kakaykayatam.",
        "timezonelegend": "Sona ti oras:",
        "localtime": "Lokal nga oras:",
-       "timezoneuseserverdefault": "Usaren ti wiki a kasisigud ($1)",
-       "timezoneuseoffset": "Sabsabali (inaganan ti tangdan)",
+       "timezoneuseserverdefault": "Usaren ti kasisigud ti wiki ($1)",
+       "timezoneuseoffset": "Sabali (inaganan ti timbengan)",
        "servertime": "Oras ti server:",
-       "guesstimezone": "Agikabil manipud idiay pabasabasam",
+       "guesstimezone": "Punuen manipud ti pagbasabasa",
        "timezoneregion-africa": "Aprika",
        "timezoneregion-america": "Amerika",
        "timezoneregion-antarctica": "Antartika",
        "timezoneregion-europe": "Europa",
        "timezoneregion-indian": "Taaw Indiano",
        "timezoneregion-pacific": "Taaw Pasipiko",
-       "allowemail": "Pakabaelam ti esurat a naggapu kadagiti sabali nga agar-aramat",
+       "allowemail": "Pakabaelam ti esurat a naggapo kadagiti sabali nga agar-aramat",
        "prefs-searchoptions": "Biruken",
        "prefs-namespaces": "Dagiti nagan ti espasio",
        "default": "kasisigud",
        "prefs-custom-css": "Naiduma a CSS",
        "prefs-custom-js": "Naiduma a JavaScript",
        "prefs-common-css-js": "Bingay a CSS/JavaScript dagiti amin a kudil:",
-       "prefs-reset-intro": "Mabalinmo nga usaren daytoy a panid tapno maisublim dagita kakaykayatam iti kasisigud ti daytoy a wiki.\nNgem saanto a mabalinen nga ipasubli.",
+       "prefs-reset-intro": "Mabalinmo nga usaren daytoy a panid tapno maisublim dagita kakaykayatam iti kasisigud iti daytoy a wiki.\nNgem saanto a mabalinen nga ipasubli.",
        "prefs-emailconfirm-label": "Pammasingked ti esurat:",
        "youremail": "Esurat:",
        "username": "{{GENDER:$1|Nagan ti agar-aramat}}:",
        "yourrealname": "Pudno a nagan:",
        "yourlanguage": "Pagsasao:",
        "yourvariant": "Linaon ti sabali a pagsasao:",
-       "prefs-help-variant": "Ti kinaykayatmo a kita ti pagsasao wenno sabali a panagsurat a maipakita kadagiti linaon ti panid daytoy a wiki.",
+       "prefs-help-variant": "Ti kinaykayatmo a kita ti pagsasao wenno sabali a panagsurat a maipakita kadagiti linaon ti panid iti daytoy a wiki.",
        "yournick": "Baro a pirma:",
-       "prefs-help-signature": "Dagiti komentario kadagiti tungtungan a panid ket mapirmaan koma iti \"<nowiki>~~~~</nowiki>\" nga agpabalin ti pirmam ken ti petsa.",
-       "badsig": "Saan a pudno a kilaw a pirma.\nIkur-it dagiti HTML nga etiketa.",
-       "badsiglength": "Atiddog unay ti pirmam.\nMasapul a nababbaba ngem $1 {{PLURAL:$1| a karakter|kadagiti karakter}} ti kaatiddogna.",
+       "prefs-help-signature": "Dagiti komentario kadagiti tungtungan a panid ket mapirmaan koma iti \"<nowiki>~~~~</nowiki>\" a pabaliwento iti pirmam ken ti petsa.",
+       "badsig": "Imbalido a naata a pirma.\nKitaen dagiti etiketa ti HTML.",
+       "badsiglength": "Atiddog unay ti pirmam.\nMasapul a saan nga ad-adu ngem $1 {{PLURAL:$1| a karakter|a karkarakter}} ti kaatiddogna.",
        "yourgender": "Kasano kadi ti kayatmo a pannakaibaga?",
        "gender-unknown": "Kaykayatko a saan nga ibaga",
        "gender-male": "Isuna ket lalaki nga agur-urnos ti pampanid ti wiki",
        "gender-female": "Isuna ket babai nga agur-urnos ti pampanid ti wiki",
-       "prefs-help-gender": "Ti panangiyasentar daytoy a kakaykayatan ket saan a nasken.\nTi sopwer ket agus-usar ti pategna daytoy ti panagtawagna kenka ken ti panangibaga ti dadduma ti maitunos gramatika a panangibaga kenka.\nDaytoy a pakaammo ket makita ti publiko.",
+       "prefs-help-gender": "Ti panangisaad daytoy a kakaykayatan ket saan a nasken.\nTi sopwer ket agus-usar iti pategna tapno tawagannaka ken ibaganaka kadagiti sabali nga agus-usar iti maitunos gramatika ti henero.\nDaytoy a pakaammo ket makitanto iti publiko.",
        "email": "Esurat",
-       "prefs-help-realname": "Saan a nasken ti pudno a nagan.\nNgem no kayatmo nga ited, maaramat daytoy a kas pammadayaw ken pangpatalged iti obram.",
-       "prefs-help-email": "Ti esurat a pagtaengan ket saan a masapul, ngem masapul no agsukatka ti kontrasenias, no baka malipatam ti kontraseniasmo.",
-       "prefs-help-email-others": "Mabalinmo nga agpili tapno dagiti sabsabali nga agar-aramat ket ma esuratandaka idiay panagsilpo ti panidmo wenno ti panid ti tungtungam.\nTi esurat a pagtaengam ket saan a maipakita kadagiti agar-aramat nga agkontak kenka.",
-       "prefs-help-email-required": "Masapul ti e-surat a pagtaengan.",
+       "prefs-help-realname": "Saan a nasken ti pudno a nagan.\nNgem no kayatmo nga ited, maaramatto daytoy a kas pammadayaw ken pangpatalged para iti obram.",
+       "prefs-help-email": "Ti esurat a pagtaengan ket saan a masapul, ngem masapul kadagiti panangisaad manen ti kontrasenias, no malipatam ti kontraseniasmo.",
+       "prefs-help-email-others": "Mabalinmo pay ti agpili tapno dagiti sabali nga agar-aramat ket mabalin nga esuratandaka babaen ti silpo ti panidmo wenno ti panid ti tungtungam.\nTi esurat a pagtaengam ket saan a maipakita no agkontak kenka dagiti agar-aramat.",
+       "prefs-help-email-required": "Masapul ti esurat a pagtaengan.",
        "prefs-info": "Kangrunaan a pakaammo",
        "prefs-i18n": "Internasionalisasion",
        "prefs-signature": "Pirma",
-       "prefs-dateformat": "Kita ti petsa",
-       "prefs-timeoffset": "Tangda ti oras",
+       "prefs-dateformat": "Pormat ti petsa",
+       "prefs-timeoffset": "Timbengan ti oras",
        "prefs-advancedediting": "Dagiti sapasap a pagpilian",
        "prefs-editor": "Mannurat",
        "prefs-preview": "Ipadas",
        "prefs-displayrc": "Ipakita dagiti pagpilian",
        "prefs-displaywatchlist": "Ipakita dagiti pagpilian",
        "prefs-tokenwatchlist": "Tandaan",
-       "prefs-diffs": "Sabali",
+       "prefs-diffs": "Paggigiddiatan",
        "prefs-help-prefershttps": "Daytoy a kakaykayatan ket mapakabaelanto iti sumaruno nga iseserrekmo.",
        "prefs-tabs-navigation-hint": "Pakaammo: Mabalinmo nga usaren dagiti kanigid ken kanawan a tekla ti pana tapno madaliasat ti baetan dagiti etiketa iti listaan dagiti etiketa.",
        "email-address-validity-valid": "Ti esurat a pagtaengan ket kasla umiso",
        "email-address-validity-invalid": "Ikabil ti umiso nga esurat a pagtaengan",
        "userrights": "Panagtaripato kadagiti karbengan ti agar-aramat",
        "userrights-lookup-user": "Agtaripato kadagiti grupo ti agar-aramat",
-       "userrights-user-editname": "Mangiserrek iti nagan-agar-aramat:",
+       "userrights-user-editname": "Mangiserrek iti nagan ti agar-aramat:",
        "editusergroup": "Urnosen dagiti grupo ti agar-aramat",
-       "editinguser": "Suksukatan ti karbengan ti agar-aramat ni '''[[User:$1|$1]]''' $2",
+       "editinguser": "Suksukatan ti karbengan ti agar-aramat ni '''[[User:$1|$1]]''' $2",
        "userrights-editusergroup": "Urnosen dagiti grupo ti agar-aramat",
        "saveusergroups": "Idulin dagiti grupo ti agar-aramat",
        "userrights-groupsmember": "Kameng iti:",
        "userrights-groupsmember-auto": "Napudno a kameng iti:",
-       "userrights-groups-help": "Mabaliwam dagiti ayan a grupo ti agar-aramat:\n* Ti nakur-it a kahon ket kayatna a saoen nga adda ti agar-aramat dita a grupo.\n* Ti saan a nakur-it a kahon ket kayatna a saoen nga awan ti agar-aramat dita a grupo.\n* A * ti kunana ket saanmo a maikkat ti grupo no nainayonmon, wenno pagbalittaden.",
+       "userrights-groups-help": "Mabaliwam dagiti ayan a grupo ti agar-aramat:\n* Ti nakur-it a kahon ket kayatna a saoen nga adda ti agar-aramat dita a grupo.\n* Ti saan a nakur-it a kahon ket kayatna a saoen nga awan ti agar-aramat dita a grupo.\n* A * mangipakita a saanmo a maikkat ti grupo no nainayonmon, wenno pagbalittaden.",
        "userrights-reason": "Rason:",
        "userrights-no-interwiki": "Awan ti pammalubosmo nga agurnos ti karbengan ti agar-aramat kadagiti sabali a wiki.",
        "userrights-nodatabase": "Awan ti database a $1 wenno saan a lokal.",
-       "userrights-nologin": "Masapul a [[Special:UserLogin|sumrekka]] nga adda pakabilangan nga administrador ti magted kadagiti karbengan ti agar-aramat.",
+       "userrights-nologin": "Masapul a [[Special:UserLogin|sumrekka]] nga addaan iti pakabilangan ti administrador tapno makaited kadagiti karbengan ti agar-aramat.",
        "userrights-notallowed": "Awan ti pammalubos nga agnayon wenno agikkat kadagiti karbengan ti agar-aramat.",
        "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 karbengam. Isu a kastoyen ket saanmo a mabalin a pastrekan daytoy a panid.",
+       "userrights-removed-self": "Nagballigika a nagikkat 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",
        "grouppage-suppress": "{{ns:project}}:Pagpansin",
        "right-read": "Basaen dagiti panid",
        "right-edit": "Agurnos kadagiti panid",
-       "right-createpage": "Agaramid kadagiti panid (saan a pagtutungtongan a pampanid)",
-       "right-createtalk": "Agaramid ti pagtungtungan a pampanid",
-       "right-createaccount": "Agaramid kadagiti baro a pakabilangan ti agar-aramat",
-       "right-minoredit": "Markaan a bassit dagiti inurnos",
-       "right-move": "Iyalis dagiti panid",
-       "right-move-subpages": "Iyalis dagiti panid a kakuyog dagiti subpanidda.",
-       "right-move-rootuserpages": "Iyalis dagiti ramut a panid ti agar-aramat",
-       "right-move-categorypages": "Iyalis ti pampanid ti kategoria",
-       "right-movefile": "Iyalis dagiti papeles",
-       "right-suppressredirect": "Saan nga agaramid ti baw-ing a naggapo iti taudan no iyalis dagiti panid",
-       "right-upload": "Agipan ti papeles",
-       "right-reupload": "Suratam manen dagiti adda a papeles",
-       "right-reupload-own": "Pasuratam manen dagiti addaan ti pinag-ipanmo a papeles",
-       "right-reupload-shared": "Paawanen dagiti papeles idiay pagbingayan ti nakaikabilan ti midia a lokal",
-       "right-upload_by_url": "Pag-ipan ti papeles a naggapu ti URL",
-       "right-purge": "Purgaen ti pagidulinan ti pagsaadan a ti panid nga awan ti panagpasingked",
-       "right-autoconfirmed": "Saanto a mabanagan babaen dagiti patingga ti gatad a naibatay ti IP",
-       "right-bot": "Matrato a kas automatiko a pamay-an",
+       "right-createpage": "Agpartuat kadagiti panid (saan a pagtutungtongan a pampanid)",
+       "right-createtalk": "Agpartuat ti pagtungtungan a pampanid",
+       "right-createaccount": "Agpartuat kadagiti baro a pakabilangan ti agar-aramat",
+       "right-minoredit": "Markaan dagiti inurnos a kas bassit",
+       "right-move": "Agiyalis kadagiti panid",
+       "right-move-subpages": "Agiyalis kadagiti panid a kakuyog dagiti subpanidda",
+       "right-move-rootuserpages": "Agiyalis kadagiti ramut a panid ti agar-aramat",
+       "right-move-categorypages": "Agiyalis ti pampanid ti kategoria",
+       "right-movefile": "Agiyalis kadagiti papeles",
+       "right-suppressredirect": "Saan nga agpartuat kadagiti baw-ing manipud ti taudan ti pampanid no agiyalis kadagiti panid",
+       "right-upload": "Agikarga kadagiti papeles",
+       "right-reupload": "Agisurat manen kadagiti addan a papeles",
+       "right-reupload-own": "Agisurat manen kadagiti addan a papeles a bukod nga inkarga",
+       "right-reupload-shared": "Lokal a mangtuon kadagiti papeles idiay pagbingayan a repsitorio ti midia",
+       "right-upload_by_url": "Agikarga kadagiti papeles manipud ti URL",
+       "right-purge": "Agpurga ti cache ti sitio para iti panid nga awan ti pammasingked",
+       "right-autoconfirmed": "Saan a mabanagan babaen dagiti patingga ti gatad a naibatay ti IP",
+       "right-bot": "Matrato a kas maysa nga automatiko a proseso",
        "right-nominornewtalk": "Nga awanan ti bassit a panagurnos dagiti tungtungan a panid ti mangkalbit dagiti agpakabil ti baro a mensahe",
-       "right-apihighlimits": "Agusar ti nangatngato a patingga kadagiti panagsapul ti API.",
+       "right-apihighlimits": "Agusar kadagiti nangatngato a patingga kadagiti usisa ti API.",
        "right-writeapi": "Panagusar ti panagsurat nga API",
-       "right-delete": "Ikkaten dagiti panid",
-       "right-bigdelete": "Ikkaten dagiti panid nga adda dagiti dakkel a pakasaritaanna",
-       "right-deletelogentry": "Ikkaten ken isubli ti panagikkat dagiti naisangsangayan a naikabil ti listaan",
-       "right-deleterevision": "Ikkaten ken ipasubli dagiti nainagan a panagbaliw ti panid",
-       "right-deletedhistory": "Kitaen dagiti naikabil a pakasaritaan, nga awan kaniada kadagiti nairaman a testo",
-       "right-deletedtext": "Kitaen dagiti naikkat a testo ken dagiti nasukatan a nagbaetan dagiti binaliwan",
-       "right-browsearchive": "Biruken dagiti naikkat a panid",
-       "right-undelete": "Isubli ti naikkat a panid",
-       "right-suppressrevision": "Kitaen ken ipasubli dagiti binaliwan a nailemmeng manipud kadagiti administrador",
-       "right-suppressionlog": "Kitaen dagita pribado a listaan",
-       "right-block": "Serraan dagiti sabali nga agar-aramat manipud iti panag-urnos",
-       "right-blockemail": "Serraan dagiti agar-aramat nga agpatulod manipud ti esurat",
-       "right-hideuser": "Serraan ti maysa a nagan ti agar-aramat, ilemmeng manipud ti publiko",
-       "right-ipblock-exempt": "Labsan dagiti IP a serra, dagiti automatiko a serra ken dagiti nasakup a serra.",
-       "right-proxyunbannable": "Labsan dagiti automatiko a serra dagiti pannakbagi",
-       "right-unblockself": "Ikkaten ti kabukbukodan a pannaka-serra",
-       "right-protect": "Sukatan dagiti agpang ti salaknib ken urnosen dagiti nasalakniban ti sariap a panid",
-       "right-editprotected": "Urnosen dagiti panid a nasalakniban a kas \"{{int:protect-level-sysop}}\"",
-       "right-editsemiprotected": "Urnosen dagiti panid a nasalakniban a kas \"{{int:protect-level-autoconfirmed}}\"",
-       "right-editinterface": "Urnosen ti \"interface\" ti agar-aramat",
-       "right-editusercssjs": "Urnosen dagiti CSS ken JavaScript a papeles dagiti sabsabali nga agar-aramat",
-       "right-editusercss": "Urnosen dagiti CSS a papeles dagiti sabsabali nga agar-aramat",
-       "right-edituserjs": "Urnosen dagiti JavaScript a papeles dagiti sabsabali nga agar-aramat",
-       "right-editmyusercss": "Urnosem dagiti bukodmo a papeles ti CSS ti agar-aramat",
-       "right-editmyuserjs": "Urnosem dagiti bukodmo a papeles ti JavaScript ti agar-aramat",
-       "right-viewmywatchlist": "Kitaem ti bukodmo a listaan ti banbantayan",
-       "right-editmywatchlist": "Urnosem ti bukodmo a listaan ti agar-aramat. Laglagipen nga adda dagiti tignay a mangnayonto pay laeng ti pampanid urayno awan daytoy a karbengan.",
-       "right-viewmyprivateinfo": "Kitaem ti bukodmo a pribado a datos (kasla ti esurat a pagtaengan, pudno a nagan)",
-       "right-editmyprivateinfo": "Urnosem ti bukodmo a pribado a datos (kasla ti esurat a pagtaengan, pudno a nagan)",
-       "right-editmyoptions": "Urnosem dagiti bukodmo a kakaykayatan",
-       "right-rollback": "Pardasan nga ipasubli dagiti inurnos ti naudi nga agar-aramat a nagurnos ti kakasta a panid",
-       "right-markbotedits": "Markaan dagiti napasubli nga urnos a kas inurnos dagiti bot",
-       "right-noratelimit": "Saan a maaringan kadagiti patingga a pagpataray",
-       "right-import": "Agala ti pampanid manipud kadagiti sabsabali a wiki",
-       "right-importupload": "Agala kadagiti panid a naggapu iti papeles ti pinag-ipan",
-       "right-patrol": "Markaan a kas napatruliaan dagiti inurnos ti dadduma",
-       "right-autopatrol": "Dagiti inurnosmo ket mamarkaan nga automatiko a kas napatruliaan",
-       "right-patrolmarks": "Kitaen dagiti kinaudian a binaliwan a  napatruliaan a marka",
-       "right-unwatchedpages": "Kitaen ti listaan dagiti saan a nabambantayan a panid",
-       "right-mergehistory": "Pagtitiponen ti pakasaritaan dagiti panid",
-       "right-userrights": "Urnosen amin dagiti karbengan ti agar-aramat",
-       "right-userrights-interwiki": "Urnosen dagiti karbengan ti agar-aramat kadagiti agar-aramat iti sabsabali a wiki",
-       "right-siteadmin": "Ikandado ken lukatan ti database",
-       "right-override-export-depth": "Ipan dagiti panid ken iraman dagiti nasilpo a panid iti kauneg nga 5",
-       "right-sendemail": "Agpatulod ti esurat kadagiti sabali nga agar-aramat",
-       "right-passwordreset": "Kitaen dagiti esurat a panangiyasentar manen kadagiti kontrasenias",
-       "newuserlogpage": "Listaan dagiti naaramid nga agar-aramat",
-       "newuserlogpagetext": "Daytoy ket listaan ti pannakaramid dagiti agar-aramat.",
+       "right-delete": "Agikkat kadagiti panid",
+       "right-bigdelete": "Agikkat kadagiti panid nga addaan kadagiti dakkel a pakasaritaan",
+       "right-deletelogentry": "Agikkat ken agisubli iti panagikkat kadagiti naisangsangayan a naikabil ti listaan",
+       "right-deleterevision": "Agikkat ken agisubli kadagiti naisangayan a rebision ti panid",
+       "right-deletedhistory": "Agkita kadagiti naikabil a naikkat a pakasaritaan, nga awan kadagiti mainaig a testo",
+       "right-deletedtext": "Agkita kadagiti naikkat a testo ken dagiti nasukatan a nagbaetan dagiti naikkat a rebision",
+       "right-browsearchive": "Agbiruk kadagiti naikkat a panid",
+       "right-undelete": "Agisubli ti pannakaikkat ti panid",
+       "right-suppressrevision": "Agkita, agilemmeng ken agisubli ti pannakakita dagiti naisangayan a rebision dagiti panid manipud ti sinoman nga agar-aramat",
+       "right-viewsuppressed": "Agkita kadagiti rebision a nailemmeng manipud ti sinoman nga agar-aramat",
+       "right-suppressionlog": "Agkita kadagiti pribado a listaan",
+       "right-block": "Agserra kadagiti sabali nga agar-aramat manipud iti panag-urnos",
+       "right-blockemail": "Agserra iti agar-aramat manipud ti panagipatulod ti esurat",
+       "right-hideuser": "Agserra iti nagan ti agar-aramat, ken agilemmeng manipud ti publiko",
+       "right-ipblock-exempt": "Labsanna dagiti serra ti IP, dagiti automatiko a serra ken dagiti sakop a serra.",
+       "right-proxyunbannable": "Labsanna dagiti automatiko a serra dagiti pannakbagi",
+       "right-unblockself": "Bukod nga agikkat it pannaka-serra",
+       "right-protect": "Agsukat kadagiti agpang ti salaknib ken agurnos kadagiti nasalakniban ti sariap a panid",
+       "right-editprotected": "Agurnos kadagiti panid a nasalakniban a kas \"{{int:protect-level-sysop}}\"",
+       "right-editsemiprotected": "Agurnos kadagiti panid a nasalakniban a kas \"{{int:protect-level-autoconfirmed}}\"",
+       "right-editinterface": "Agurnos iti interface ti agar-aramat",
+       "right-editusercssjs": "Agurnos kadagiti papales ti CSS ken JavaScript dagiti sabali nga agar-aramat",
+       "right-editusercss": "Agurnos kadagiti papeles ti CSS dagiti sabali nga agar-aramat",
+       "right-edituserjs": "Agurnos kadagiti papales ti JavaScript dagiti sabali nga agar-aramat",
+       "right-editmyusercss": "Agurnos kadagiti bukodmo a papeles ti CSS ti agar-aramat",
+       "right-editmyuserjs": "Agurnos kadagiti bukodmo a papeles ti JavaScript ti agar-aramat",
+       "right-viewmywatchlist": "Agkita iti bukodmo a listaan ti bambantayan",
+       "right-editmywatchlist": "Agurnos iti bukodmo a listaan ti bambantayan. Laglagipen nga adda dagiti tignay a mangnayonto pay laeng ti pampanid urayno awan daytoy a karbengan.",
+       "right-viewmyprivateinfo": "Agkita iti bukodmo a pribado a datos (kasla ti esurat a pagtaengan, pudno a nagan)",
+       "right-editmyprivateinfo": "Agurnos iti bukodmo a pribado a datos (kasla ti esurat a pagtaengan, pudno a nagan)",
+       "right-editmyoptions": "Agurnos kadagiti bukodmo a kakaykayatan",
+       "right-rollback": "Napardas a mangisubli kadagiti inurnos ti naudi nga agar-aramat a nagurnos iti naisangayan a panid",
+       "right-markbotedits": "Agmarka kadagiti naipasubli nga urnos a kas inurnos dagiti bot",
+       "right-noratelimit": "Saan a maaringan babaen dagiti patingga ti gatad",
+       "right-import": "Agala ti pampanid manipud kadagiti sabali a wiki",
+       "right-importupload": "Agala kadagiti panid manipud ti naikarga a papeles",
+       "right-patrol": "Markaanna dagiti inurnos ti dadduma a kas napatruliaan",
+       "right-autopatrol": "Automatiko a mamarkaanna ti bukod nga inurnos a kas napatruliaan",
+       "right-patrolmarks": "Agkita kadagiti kaudian a binaliwan dagiti marka ti napatruliaan",
+       "right-unwatchedpages": "Agkita ti listaan dagiti saan a nabambantayan a panid",
+       "right-mergehistory": "Mangitipon ti pakasaritaan dagiti panid",
+       "right-userrights": "Agurnos kadagiti amin a karbengan ti agar-aramat",
+       "right-userrights-interwiki": "Agurnos kadagiti karbengan ti agar-aramat kadagiti agar-aramat iti sabsabali a wiki",
+       "right-siteadmin": "Mangikandado ken manglukat iti database",
+       "right-override-export-depth": "Agipan kadagiti panid a mairaman dagiti naisilpo a panid agingana iti kauneg ti 5",
+       "right-sendemail": "Agipatulod ti esurat kadagiti sabali nga agar-aramat",
+       "right-passwordreset": "Agkita kadagiti esurat ti panangisaad manen ti kontrasenias",
+       "newuserlogpage": "Listaan ti panagpartuat ti agar-aramat",
+       "newuserlogpagetext": "Daytoy ket listaan dagiti pannakapartuat iti agar-aramat.",
        "rightslog": "Listaan dagiti karbengan ti agar-aramat",
        "rightslogtext": "Daytoy ket listaan dagiti sinukatan a karbengan ti agar-aramat.",
-       "action-read": "basaen datoy a panid",
-       "action-edit": "agurnos iti datoy a panid",
+       "action-read": "agbasa iti datoy a panid",
+       "action-edit": "agurnos iti daytoy a panid",
        "action-createpage": "agpartuat kadagiti panid",
-       "action-createtalk": "agaramid kadagiti pagtungtungan a panid",
-       "action-createaccount": "agpartuat ti pakabilangan daytoy nga agar-aramat",
-       "action-history": "kitaen ti pakasaritaan daytoy a panid",
-       "action-minoredit": "markaam a bassit nga urnos daytoy",
-       "action-move": "iyalis daytoy a panid",
-       "action-move-subpages": "iyalis daytoy a panid, ken dagiti subpanidna",
-       "action-move-rootuserpages": "iyalis dagiti ramut a panid ti agar-aramat",
-       "action-move-categorypages": "iyalis ti pampanid ti kategoria",
-       "action-movefile": "iyalis daytoy a papeles",
-       "action-upload": "ikarga daytoy a papeles",
-       "action-reupload": "suratam manen dagiti adda a papeles",
-       "action-reupload-shared": "tuonan daytoy a papeles idiay pagbingayan a repositorio",
-       "action-upload_by_url": "ikarga daytoy a papeles manipud ti URL",
-       "action-writeapi": "usaren ti panagsurat ti API",
-       "action-delete": "ikkaten daytoy a panid",
-       "action-deleterevision": "ikkaten daytoy a binaliwan",
-       "action-deletedhistory": "kitaen dagiti naikkat a pakasaritaan daytoy a panid",
-       "action-browsearchive": "birukem dagiti naikkat a panid",
-       "action-undelete": "isublim ti panakaikkat daytoy a panid",
-       "action-suppressrevision": "kitaen ken ipasubli daytoy nailemmeng a panagbaliw",
-       "action-suppressionlog": "kitaen ti listaan a pribado",
-       "action-block": "serraan daytoy nga agar-aramat manipud ti panag-urnos",
-       "action-protect": "sukatan dagiti lessaad ti salaknib iti daytoy a panid",
-       "action-rollback": "pardasan nga ipasubli dagiti inurnos ti kinaudi nga agar-aramat a nagurnos ti naisangsangayan a panid",
+       "action-createtalk": "agpartuat kadagiti pagtungtungan a panid",
+       "action-createaccount": "agpartuat iti pakabilangan daytoy nga agar-aramat",
+       "action-history": "agkita iti pakasaritaan daytoy a panid",
+       "action-minoredit": "agmarka iti daytoy nga inurnos a kas bassit",
+       "action-move": "agiyalis iti daytoy a panid",
+       "action-move-subpages": "agiyalis iti daytoy a panid, ken dagiti subpanidna",
+       "action-move-rootuserpages": "agiyalis kadagiti ramut a panid ti agar-aramat",
+       "action-move-categorypages": "agiyalis iti pampanid ti kategoria",
+       "action-movefile": "agiyalis iti daytoy a papeles",
+       "action-upload": "agikarga iti daytoy a papeles",
+       "action-reupload": "agsurat manen iti daytoy nga adda a papeles",
+       "action-reupload-shared": "mangtuon iti daytoy a papeles idiay pagbingayan a repositorio",
+       "action-upload_by_url": "agikarga iti daytoy a papeles manipud ti URL",
+       "action-writeapi": "agusar iti panagsurat ti API",
+       "action-delete": "agikkat iti daytoy a panid",
+       "action-deleterevision": "agikkat iti daytoy a rebision",
+       "action-deletedhistory": "agkita kadagiti naikkat a pakasaritaan iti daytoy a panid",
+       "action-browsearchive": "agbiruk kadagiti naikkat a panid",
+       "action-undelete": "agisubli iti pannakaikkat iti daytoy a panid",
+       "action-suppressrevision": "agrepaso ken agisubli iti daytoy a nailemmeng a rebision",
+       "action-suppressionlog": "agkita iti daytoy a pribalo a listaan",
+       "action-block": "agserra iti daytoy nga agar-aramat manipud ti panag-urnos",
+       "action-protect": "mangsukat kadagiti lessaad ti salaknib para iti daytoy a panid",
+       "action-rollback": "napardas a mangisubli kadagiti inurnos ti kinaudi nga agar-aramat a nagurnos iti naisangsangayan a panid",
        "action-import": "agala ti pampanid manipud ti sabali a wiki",
-       "action-importupload": "agala ti pampanid manipud ti naipan a papeles",
-       "action-patrol": "markaan a kas napatruliaan dagiti inurnos ti dadduma",
-       "action-autopatrol": "markaam dagiti napatruliam nga inurnos",
-       "action-unwatchedpages": "kitaen ti listaan dagiti saan a nabambantayan a panid",
-       "action-mergehistory": "pagtitiponen ti pakasaritaan daytoy a panid",
-       "action-userrights": "urnosen amin dagiti karbengan ti agar-aramat",
-       "action-userrights-interwiki": "urnosen dagiti karbengan ti agar-aramat iti agar-aramat kadagiti sabsabali a wiki",
-       "action-siteadmin": "kandaduan wenno lukatan daytoy \"database\"",
+       "action-importupload": "agala ti pampanid manipud ti naikarga a papeles",
+       "action-patrol": "agmarka kadagiti inurnos ti dadduma a kas napatruliaan",
+       "action-autopatrol": "agmarka iti bukodmo nga inurnos a kas napatrulian",
+       "action-unwatchedpages": "agkita ti listaan dagiti saan a nabambantayan a panid",
+       "action-mergehistory": "mangitipon ti pakasaritaan iti daytoy a panid",
+       "action-userrights": "agurnos kadagiti amin a karbengan ti agar-aramat",
+       "action-userrights-interwiki": "agurnos kadagiti karbengan ti agar-aramat dagiti agar-aramat kadagiti sabali a wiki",
+       "action-siteadmin": "mangkandado wenno manglukat ti database",
        "action-sendemail": "agipatulod kadagiti esurat",
-       "action-editmywatchlist": "urnosem ti bukodmo a listaan ti banbantayan",
-       "action-viewmywatchlist": "kitaem ti bukodmo a listaan ti banbantayan",
-       "action-viewmyprivateinfo": "kitaem ti bukodmo a pribado a pakaammo",
-       "action-editmyprivateinfo": "urnosem ti bukodmo a pribado a pakaammo",
+       "action-editmywatchlist": "agurnos iti bukodmo a listaan ti bambantayan",
+       "action-viewmywatchlist": "agkita iti bukodmo a listaan ti bambantayan",
+       "action-viewmyprivateinfo": "agkita iti bukodmo a pribado a pakaammo",
+       "action-editmyprivateinfo": "agurnos iti bukodmo a pribado a pakaammo",
        "nchanges": "$1 {{PLURAL:$1|sinukatan|dagiti sinukatan}}",
-       "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|manipud idi naudi a panagsarungkar}}",
+       "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|manipud ti naudi a panagsarungkar}}",
        "enhancedrc-history": "pakasaritaan",
        "recentchanges": "Kaudian a balbaliw",
-       "recentchanges-legend": "Pagpilian kadagiti kaudian a balbaliw",
-       "recentchanges-summary": "Siputen dagiti kinaudi a panagbalbaliw ti wiki iti daytoy a panid.",
+       "recentchanges-legend": "Pagpilian iti kaudian a balbaliw",
+       "recentchanges-summary": "Siputen ti kaudian a balbaliw iti wiki iti daytoy a panid.",
        "recentchanges-noresult": "Awan ti nasuksukatan iti las-ud ti naited a paset ti panawen a kapada dagitoy a kriteria.",
-       "recentchanges-feed-description": "Siputen dagiti kinaudi a panagbalbaliw ti wiki iti daytoy a pakan.",
-       "recentchanges-label-newpage": "Daytoy a panag-urnos ket nakapartuat ti baro a panid",
+       "recentchanges-feed-description": "Siputen ti kaudian a balbaliw iti wiki iti daytoy a pakan.",
+       "recentchanges-label-newpage": "Daytoy a panag-urnos ket nakapartuat iti baro a panid",
        "recentchanges-label-minor": "Daytoy ket bassit a panag-urnos",
-       "recentchanges-label-bot": "Daytoy a panag-urnos ket inaramid babaen ti maysa a bot",
+       "recentchanges-label-bot": "Daytoy a panag-urnos ket inaramid babaen ti bot",
        "recentchanges-label-unpatrolled": "Daytoy a panag-urnos ket saan pay a napatruliaan",
        "recentchanges-label-plusminus": "Ti panagbaliw ti kadakkel ti panid babaen ti bilang dagiti byte",
        "recentchanges-legend-heading": "'''Leyenda:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (kitaen pay ti [[Special:NewPages|listaan ti baro a pampanid]])",
-       "rcnotefrom": "Dita baba ket dagiti sinukatan manipud idi strong>$2</strong> (agingga iti <strong>$1</strong> a naipakita).",
-       "rclistfrom": "Ipakita dagiti kabarbaro a sinukatan a mangrugi manipud idi $3 $2",
+       "rcnotefrom": "Dita baba ket {{PLURAL:$5|ti sinukatan|dagiti sinukatan}} manipud idi <strong>$3, $4</strong> (aginggana iti <strong>$1</strong> a naipakita).",
+       "rclistfrom": "Ipakita dagiti kabarbaro a sinukatan a mangrugi manipud idi $2, $3",
        "rcshowhideminor": "$1 dagiti bassit a panag-urnos",
        "rcshowhideminor-show": "Ipakita",
        "rcshowhideminor-hide": "Ilemmeng",
        "rcshowhideliu": "$1 dagiti nakarehistro nga agar-aramat",
        "rcshowhideliu-show": "Ipakita",
        "rcshowhideliu-hide": "Ilemmeng",
-       "rcshowhideanons": "$1 dagiti di am-ammo nga agar-aramat",
+       "rcshowhideanons": "$1 dagiti di ammo nga agar-aramat",
        "rcshowhideanons-show": "Ipakita",
        "rcshowhideanons-hide": "Ilemmeng",
        "rcshowhidepatr": "$1 dagiti napatrulian a panag-urnos",
        "rcshowhidemine-show": "Ipakita",
        "rcshowhidemine-hide": "Ilemmeng",
        "rclinks": "Ipakita dagiti naudi a $1 a sinukatan iti kallabes a $2 nga al-aldaw<br />$3",
-       "diff": "sabali",
-       "hist": "saritaan",
+       "diff": "dip",
+       "hist": "hist",
        "hide": "Ilemmeng",
        "show": "Ipakita",
        "minoreditletter": "m",
        "newpageletter": "B",
        "boteditletter": "b",
        "number_of_watching_users_pageview": "[$1 nga agbuybuya {{PLURAL:$1|nga agar-aramat|kadagiti agar-aramat}}]",
-       "rc_categories": "Patingga dagiti kategoria (pagsisinaen ti \"|\")",
+       "rc_categories": "Patingga dagiti kategoria (pagsinaen iti \"|\")",
        "rc_categories_any": "Uray ania",
        "rc-change-size-new": "$1 {{PLURAL:$1|a byte|kadagiti byte}} kalpasan ti panag-sukat",
        "newsectionsummary": "/* $1 */ baro a paset",
        "recentchangeslinked-feed": "Mainaig a sinukatan",
        "recentchangeslinked-toolbox": "Mainaig a sinuksukatan",
        "recentchangeslinked-title": "Sinukatan a mainaig iti \"$1\"",
-       "recentchangeslinked-summary": "Listaan daytoy dagiti kaudian a sinukatan kadagiti pampanid a nakasilpo manipud iti maysa a napili a panid (wenno kadagiti kameng ti maysa a nainaganan a kategoria).\nDagiti panid iti [[Special:Watchlist|listaan ti bambantayam]] ket '''napuskol'''.",
+       "recentchangeslinked-summary": "Daytoy ket listaan dagiti kaudian a sinukatan kadagiti pampanid a nakasilpo manipud iti naisangayan a panid (wenno kadagiti kameng ti maysa a nainaganan a kategoria).\nDagiti panid iti [[Special:Watchlist|listaan ti bambantayam]] ket dagiti <strong>napuskol</strong>.",
        "recentchangeslinked-page": "Nagan ti panid:",
-       "recentchangeslinked-to": "Ipakita dagiti sinukatan a panid nga embes a naisilpo iti naited a panid",
-       "upload": "Mangipan iti papeles",
-       "uploadbtn": "Mangipan iti papeles",
-       "reuploaddesc": "Ukasen ti pag-ipan ken agsubli idiay kabuklan ti pag-ipan",
-       "upload-tryagain": "Ited ti napabaro a panagipalawag ti papeles",
+       "recentchangeslinked-to": "Ipakita dagiti sinukatan kadagiti panid nga imbes a naisilpo iti naited a panid",
+       "upload": "Agikarga iti papeles",
+       "uploadbtn": "Agikarga iti papeles",
+       "reuploaddesc": "Ukasen ti panagikarga ken agsubli idiay porma ti panagikarga",
+       "upload-tryagain": "Mangited ti napabaro a deskripsion ti papeles",
        "uploadnologin": "Saan a nakastrek",
-       "uploadnologintext": "Nasken ti $1 tapno makaipanka iti papeles.",
-       "upload_directory_missing": "Ti direktorio ti pag-ipan ($1) ket napukaw ken saan a mabalin nga aramiden iti webserver.",
-       "upload_directory_read_only": "Ti pagipanan a direktoria ($1) ket saan a masuratan ti webserver.",
-       "uploaderror": "Biddut ti panang-ipan",
-       "upload-recreate-warning": "'''Ballag: Ti papeles babaen ti dayta a nagan ket naikkat wenno naiyalis.'''\n\nTi listaan ti panagikkat ken panagiyalis para iti daytoy a panid ket adda ditoy tapno makitam:",
-       "uploadtext": "Usaren ti kabuklan dita baba ti pinag-ipan ti papeles.\nTi panagkita wenno panagbiruk ti napalubos a pinag-ipan ti papeles mapan ka idiay [[Special:FileList|listaan dagiti napag-ipan a papeles]], dagiti pinag-ipan wenno pinag-ipan manen ket nakalista pay idiay [[Special:Log/upload|listaan ti pinag-ipan]], dagiti panagikkat ket idiay [[Special:Log/delete|listaan ti panagikkat]].\n\nTi panagikabil ti papeles iti panid, usaren ti panilpo a kas dagiti sumaganad a kabuklan:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code>''' ti panag-usar ti dakkel a bersion ti papeles\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|alt text]]</nowiki></code>''' ti agusar ti 200 pixel a kaakaba  a panagparang iti kahon idiay kannigid nga adda 'sabali a testo' ti panagipalpalawag\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' ti dagus a panagsilpo idiay papeles nga awan ti panagparang ti papeles",
+       "uploadnologintext": "Pangngaasi a $1 tapno makaikarga kadagiti papeles.",
+       "upload_directory_missing": "Ti pagikargaan a direktorio ($1) ket awan ken saan a mabalin a mapartuat babaen ti webserver.",
+       "upload_directory_read_only": "Ti pagikargaan a direktorio ($1) ket saan a masuratan babaen ti webserver.",
+       "uploaderror": "Biddut ti panagikarga",
+       "upload-recreate-warning": "<strong>Ballag: Ti papeles babaen ti dayta a nagan ket naikkat wenno naiyalis.</strong>\n\nTi listaan ti panagikkat ken panagiyalis para iti daytoy a panid ket naited ditoy para iti pakainugotan:",
+       "uploadtext": "Usaren ti porma dita baba tapno makaikarga iti papeles.\nTi panagkita wenno panagbiruk ti dati a naikarga a papeles mapan idiay [[Special:FileList|listaan dagiti naikarga a papeles]], dagiti naikarga wenno naikarga manen ket nailista pay idiay [[Special:Log/upload|listaan ti panagikarga]], dagiti panagikkat ket idiay [[Special:Log/delete|listaan ti panagikkat]].\n\nTi panangiraman ti papeles iti panid, usaren ti silpo a kas dagiti sumaganad a porma:\n* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code></strong> tapno mausar ti napno a bersion ti papeles \n* <strong><code><nowiki>[[</nowiki>{{ns:file<nowiki>:File.png|200px|thumb|left|alt text]]</nowiki></code></strong> tapno mausar ti 200 a piksel a kalawa a panagiparang iti kanigid a margin nga addaan iti \"alt text\"a kas ti deskripsion\n* <strong><code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code></strong> para iti dagus a panangisilpo iti papeles nga awan ti panangipakita ti papeles",
        "upload-permitted": "Dagiti mapalubosan a kita ti papeles: $1.",
-       "upload-preferred": "Dagiti mabalbalin a kita ti papeles: $1.",
+       "upload-preferred": "Dagiti kaykayat a kita ti papeles: $1.",
        "upload-prohibited": "Dagiti maiparit a kita ti papeles: $1.",
-       "uploadlogpage": "Listaan ti pagipanan",
-       "uploadlogpagetext": "Adda dita baba ti listaan dagiti kaudian a naipan a papeles.\nKitaen dagiti [[Special:NewFiles|galleria ti baro a papeles]] para iti adu pay a pakabuklan apanagkita.",
+       "uploadlogpage": "Listaan ti panagikarga",
+       "uploadlogpagetext": "Dita baba ket ti listaan dagiti kaudian a panangikarga iti papeles.\nKitaen ti [[Special:NewFiles|galeria dagiti baro a papeles]] para iti adu pay a bisual a pakabuklan.",
        "filename": "Nagan ti papeles",
        "filedesc": "Pakabuklan",
        "fileuploadsummary": "Pakabuklan:",
-       "filereuploadsummary": "Dagiti panagsukat ti papeles:",
-       "filestatus": "Kasasaad ti karbengan ti panagipablaak:",
+       "filereuploadsummary": "Dagiti pannakasukat ti papeles:",
+       "filestatus": "Kasasaad ti karbengan ti kopia:",
        "filesource": "Taudan:",
        "ignorewarning": "Di ikaskaso ti ballaag ket idulin latta ti papeles",
-       "ignorewarnings": "Di ikaskaso dagiti ania man a ballaag",
-       "minlength1": "Dagiti nagan ti papeles ket nasken uray a maysa laeng a letra wenno nasursurok.",
-       "illegalfilename": "Ti nagan ti papeles \"$1\" ket adda nagyan na a kababalin a saan a mabalin kadagiti titulo ti panid.\nPangngaasi ta naganan manen ti papeles ken padasen manen nga ipapan.",
-       "filename-toolong": "Dagiti nagan ti papeles ket saan a mabalin nga at-atiddog ngem dagiti 240 a byte.",
-       "badfilename": "Nasukatan ti nagan ti papeles iti \"$1\".",
-       "filetype-mime-mismatch": "Ti pagpa-atiddog ti papeles \".$1\" ket saan a kapada ti nakitaan a kita ti MIME iti papeles ($2).",
-       "filetype-badmime": "Dagiti papeles a kas MIME a kita \"$1\" ket saan a mapalubosan a maipan.",
-       "filetype-bad-ie-mime": "Saan a makapag-ipan ti papeles ngamin ket masarakan ti Internet Explorer a kas \"$1\", a saan a mabalin ken makapataud a dakes a kita ti papeles.",
-       "filetype-unwanted-type": "'''\".$1\"''' ti saan a mapalubusan a kita ti papeles.\nTi mapalubusan  {{PLURAL:$3|a kita ti papeles ket|kadagiti kita ti papeles ket}} $2.",
-       "filetype-banned-type": "Ti '''\".$1\"''' {{PLURAL:$4|ket saan a mapalubusan a kita ti papeles|ket dagiti saan a mapalubusan a kita ti papeles}}.\nTi mapalubusan {{PLURAL:$3|a kita ti papeles ket|kadagiti kita ti papeles ket}} $2.",
-       "filetype-missing": "Daytoy a papeles ket awan ti kita na a (kasla \".jpg\").",
-       "empty-file": "Ti papeles nga intedmo ket awan ti nagyanna.",
+       "ignorewarnings": "Di ikaskaso dagiti aniaman a ballaag",
+       "minlength1": "Dagiti nagan ti papeles ket nasken a saan a basbassit ngem maysa a letra.",
+       "illegalfilename": "Ti nagan ti papeles ti \"$1\" ket aglaon kadagiti karakter a saan a maipalubos kadagiti titulo ti panid.\nPangngaasi a naganan manen ti papeles ken padasen manen nga ikarga.",
+       "filename-toolong": "Dagiti nagan ti papeles ket nasken a saan nga at-atiddog ngem dagiti 240 a byte.",
+       "badfilename": "Nasukatanen ti nagan ti papeles iti \"$1\".",
+       "filetype-mime-mismatch": "Ti pagpa-atiddog ti papeles ti \".$1\" ket saan a maipada iti naduktalan a kita ti MIME iti papeles ($2).",
+       "filetype-badmime": "Dagiti papeles a kita ti MIME ti \"$1\" ket saan a maipalubos a maikarga.",
+       "filetype-bad-ie-mime": "Saan a maikarga daytoy a papeles gapu ta maduktalan ti Internet Explorer a kas \"$1\", a saan a maipalubos ken makapataud ti dakes a kita ti papeles.",
+       "filetype-unwanted-type": "Ti <strong>\".$1\"</strong> ket mays a di kayat a kita ti papeles.\nTi kaykayat {{PLURAL:$3|a kita ti papeles ket|a kita dagiti papeles ket}} $2.",
+       "filetype-banned-type": "Ti <strong>\".$1\"</strong> {{PLURAL:$4|ket saan a maipalubos a kita ti papeles|ket dagiti saan a maipalubos a kita ti papeles}}.\nTi mapalubosan {{PLURAL:$3|a kita ti papeles ket|a kita dagiti papeles ket}} $2.",
+       "filetype-missing": "Daytoy a papeles ket awan ti pagpaatiddogna (kasla ti \".jpg\").",
+       "empty-file": "Ti papeles nga intedmo ket awan linaonna.",
        "file-too-large": "Ti papeles nga intedmo ket dakkel unay.",
        "filename-tooshort": "Ti nagan daytoy a papeles ket bassit unay.",
-       "filetype-banned": "Ti kita daytoy a papeles ket maiparit.",
-       "verification-error": "Daytoy a papeles ket saan a nakapasa ti pagsingkedan.",
-       "hookaborted": "Ti panagbabaro a pinadasmo ket napasardeng babaen ti pangpa-atiddog a kawit.",
-       "illegal-filename": "Ti nagan daytoy a papeles ket saan a maipalubos.",
-       "overwrite": "Saan a mabalin a suratan manen iti papeles nga adda ditan.",
-       "unknown-error": "Adda di amammo a biddut.",
-       "tmp-create-error": "Saan a makaaramid ti saan nga agnayon a papeles.",
-       "tmp-write-error": "Biddut ti pannakaisurat dagiti saan nga agnanayon a papeles.",
-       "large-file": "Ti maipatalked a papeles ket saan koma a dakdakkel ngem $1;\ndaytoy a papeles ket $2.",
-       "largefileserver": "Daytoy a papeles ket dakdakel ngem ti naaramid a mabalin para iti server.",
-       "emptyfile": "Ti papeles nga ipanmo ket kasla awan ti nagyan na.\nBaka daytoy ket gapu ti kamali ti inkabil a nagan ti papeles.\nPangngaasi ta kitaem no kayatmo latta nga ipapan daytoy a papeles.",
-       "windows-nonascii-filename": "Daytoy a wiki ket saanna a suportaran dagiti nagan ti papeles nga addaan kadagiti espesial a karakter.",
-       "fileexists": "Ti papeles nga agnagan ti kastoy ket addan, pangngaasi a kitaem ti <strong>[[:$1]]</strong> no saanka a sigurado no kayatmo a sukatan.\n[[$1|thumb]]",
-       "filepageexists": "Ti panangipalpalawag a panid para iti daytoy a papeles ket naaramiden idiay <strong>[[:$1]]</strong>, ngem awan ti agdama nga agnagan ti kastoy a papeles.\nTi pakabuklan nga inkabilmo ket saan nga agparang idiay deskripsion ti panid.\nTapno agparang ti pakabuklan idiay, masapul a manual a baliwam.\n[[$1|thumb]]",
-       "fileexists-extension": "Adda papeles nga agnagan ti kastoy: [[$2|thumb]]\n* Nagan ti naipapan a papeles: <strong>[[:$1]]</strong>\n* Nagan ti adda a papeles: <strong>[[:$2]]</strong>\nPangngaasi nga agpili ti sabali a nagan.",
-       "fileexists-thumbnail-yes": "Daytoy a papeles ket kasla ladawan a napabassit ''(thumbnail)''.\n[[$1|thumb]]\nPangngaasi a kitaem ti papeles a <strong>[[:$1]]</strong>.\nNo ti nakitam a papeles ket isu ti ladawan iti dati a kadakkel saanen a nasken ti agipan ti maysa a napabassit a ladawan.",
-       "file-thumbnail-no": "Ti nagan ti papeles ket mangrugi iti <strong>$1</strong>.\nKasla ladawan a napabassit ''(thumbnail)''.\nNo addaanka ti napno a resolusion ipanmo daytoy, no saan pangngaasi a sukatam ti nagan ti papeles.",
-       "fileexists-forbidden": "Daytoy a nagan ti papeles ket adda dita, ken saan a mabalin a masuratan manen.\nNo kayatmo pay latta nga ipan ti papeles, pangngaasi nga agsublika ken usarem ti baro a nagan.\n[[File:$1|thumb|center|$1]]",
-       "fileexists-shared-forbidden": "Daytoy a nagan ti papeles ket adda dita pagbingayan a nagikabilan ti papeles.\nNo kayatmo pay latta nga ipan ti papeles, pangngaasi nga agsublika ken usarem ti baro a nagan.\n[[File:$1|thumb|center|$1]]",
+       "filetype-banned": "Daytoy a kita ti papeles ket maiparit.",
+       "verification-error": "Daytoy a papeles ket saan a nakapasa iti pammasingked iti papeles.",
+       "hookaborted": "Ti panagbabaro a pinadasmo ket napasardeng babaen ti pangpaatiddog.",
+       "illegal-filename": "Ti nagan ti papeles ket saan a maipalubos.",
+       "overwrite": "Saan a maipalubos ti mangsurat manen iti addan a papeles.",
+       "unknown-error": "Napasamak ti maysa a di ammo a biddut.",
+       "tmp-create-error": "Saan a makapartuat ti temporario a papeles.",
+       "tmp-write-error": "Biddut ti panagsurat iti temporario a papeles.",
+       "large-file": "Maisingasing a dagiti papeles ket saan a dakdakkel ngem $1;\ndaytoy a papeles ket $2.",
+       "largefileserver": "Daytoy a papeles ket dakdakel ngem ti ipalubos a pannakaaramid ti server.",
+       "emptyfile": "Ti papeles nga inkargam ket kasla awan linaon.\nBaka daytoy ket gapu ti kamali iti nagan ti papeles.\nPangngaasi ta kitaem no kayatmo latta nga ikarga daytoy a papeles.",
+       "windows-nonascii-filename": "Daytoy a wiki ket saan a mangsuporta kadagiti nagan ti papeles nga addaan kadagiti espesial a karakter.",
+       "fileexists": "Ti papeles nga agnagan ti kastoy ket addan, pangngaasi a kitaem ti <strong>[[:$1]]</strong> no {{GENDER:|saanka}} a sigurado a kayatmo a sukatan daytoy.\n[[$1|thumb]]",
+       "filepageexists": "Ti deskripsion a panid para iti daytoy a papeles ket napartuaten idiay <strong>[[:$1]]</strong>, ngem awan ti agdama nga agnagan ti kastoy a papeles.\nTi pakabuklan nga inkabilmo ket saan nga agparang iti deskripsion ti panid.\nTapno agparang ti pakabuklan idiay, masapul a manual nga urnosem.\n[[$1|thumb]]",
+       "fileexists-extension": "Adda papeles nga agnaganen iti kastoy: [[$2|thumb]]\n* Nagan ti naikarga a papeles: <strong>[[:$1]]</strong>\n* Nagan ti adda a papeles: <strong>[[:$2]]</strong>\nKayatmo kadi ti agusar ti naisangsangayan a nagan?",
+       "fileexists-thumbnail-yes": "Daytoy a papeles ket kasla ladawan a napabassit a kadakkel <em>(thumbnail)</em>..\n[[$1|thumb]]\nPangngaasi a kitaem ti papeles ti <strong>[[:$1]]</strong>.\nNo ti nakitam a papeles ket isu ti ladawan iti dati a kadakkel saanen a nasken ti agikarga ti maysa a napabassit unay a ladawan.",
+       "file-thumbnail-no": "Ti nagan ti papeles ket mangrugi iti <strong>$1</strong>.\nKasla ti ladawan a napabassit ti kadakkel <em>(thumbnail)</em>.\nNo addaanka iti daytoy a ladawan iti napno a resolusion ikargam dayta, no saan pangngaasi a sukatam ti nagan ti papeles.",
+       "fileexists-forbidden": "Daytoy a nagan ti papeles ket addan, ken saan a mabalin a masuratan manen.\nNo kayatmo pay latta nga ikarga ti papelesmo, pangngaasi nga agsublika ken agusar iti baro a nagan.\n[[File:$1|thumb|center|$1]]",
+       "fileexists-shared-forbidden": "Ti papeles iti daytoy a nagan ket addan iti pagbingayan a repositorio ti papeles.\nNo kayatmo pay latta nga ikarga ti papeles, pangngaasi nga agsublika ken agusar iti baro a nagan.\n[[File:$1|thumb|center|$1]]",
        "file-exists-duplicate": "Daytoy a papeles ket duplikado kadagiti sumaganad a {{PLURAL:$1|papeles|pappapeles}}:",
-       "file-deleted-duplicate": "Ti papeles a kapadpada ti papeles a ([[:$1]]) ket naikkat idin.\nKitaem koma ti pakasaritaan a panakaikkat ti papeles sakbay a mangirugika ti pinag-ipan.",
-       "file-deleted-duplicate-notitle": "Ti papales a kapada ti daytoy a papeles ket dati a naikkat, ken nalapdan ti titulo.\nNasken nga agdamagka ti addaan ti abilidad a mangkita ti nalapdan a datos ti papeles tapno marepaso ti kasasaad sakbay a mapan nga ikarga manen daytoy.",
-       "uploadwarning": "Ballaag iti pinag-ipan",
-       "uploadwarning-text": "Pangngaasi a baliwam ti deskripsion ti papeles ken padasem manen.",
+       "file-deleted-duplicate": "Ti papeles a kapadpada ti papeles a ([[:$1]]) ket dati a naikkat.\nKitaem koma ti pakasaritaan a pannakaikkat ti papeles sakbay a mangirugika a mangikarga manen.",
+       "file-deleted-duplicate-notitle": "Ti papales a kapada iti daytoy a papeles ket dati a naikkat, ken nalapdan ti titulo.\nNasken nga agdamagka iti sabali nga addaan iti abilidad a mangrepaso ti nalapdan a datos ti papeles tapno marepaso ti kasasaad sakbay a mapan nga agikarga manen iti daytoy.",
+       "uploadwarning": "Ballaag ti panagikarga",
+       "uploadwarning-text": "Pangngaasi a baliwam ti deskripsion ti papeles dita baba ken padasen manen.",
        "savefile": "Idulin ti papeles",
-       "uploadedimage": "naipanen ti \"[[$1]]\"",
-       "overwroteimage": "naipan ti baro a bersion ti \"[[$1]]\"",
-       "uploaddisabled": "Naiddep ti pinag-ipan.",
-       "copyuploaddisabled": "Naiddep ti pinag-ipan iti URL.",
-       "uploaddisabledtext": "Napawilan ti pinag-ipan iti papeles.",
-       "php-uploaddisabledtext": "Ti pinag-ipan ti papeles ket naiddep idiay PHP.\nPanngaasi a kitaem ti pannakaikabil ti pinag-ipan ti papeles.",
-       "uploadscripted": "Daytoy a papeles ket adda nagyanna a HTML wenno panagsurat a kodigo a mabalin nga agpakamali ti panagbasa ti sapot a pagbasabasa.",
+       "uploaddisabled": "Nabaldado dagiti panagikarga.",
+       "copyuploaddisabled": "Nabaldado ti panagikarga babaen ti URL.",
+       "uploaddisabledtext": "Nabaldado dagiti panagikarga ti papeles.",
+       "php-uploaddisabledtext": "Dagiti panangikarga ti papeles ket nabaldado iti PHP.\nPanngaasi a kitaem ti pannakaisaad ti panagikarga ti papeles.",
+       "uploadscripted": "Daytoy a papeles ket naglaon ti HTML wenno eskritu ti kodigo a mabalin a kamali nga inpatarus babaen ti pagbasabasa ti web.",
        "uploadscriptednamespace": "Daytoy a papeles ti SVG ket aglaon ti maysa a saan a mabalin a nagan ti espasio ti \"$1\"",
        "uploadinvalidxml": "Ti XML iti naikarga a papeles ket saan a maiwaswas.",
-       "uploadvirus": "Addaan ti birus daytoy a papeles! Salaysay: $1",
-       "uploadjava": "Daytoy a papeles ket ZIP a papeles nga adda nagyanna a Java .a kita ti papeles.\nSaan a mabalin ti pinag-ipan ti Java a papeles, ngamin ket palabsanda dagiti seguridad a pangrestrikto.",
+       "uploadvirus": "Ti papeles ket aglaon ti birus! \nDagiti salaysay: $1",
+       "uploadjava": "Daytoy a papeles ket papeles ti ZIP nga aglaon ti Java .a klase ti papeles.\nTi panangikarga ti papales ti Java ket saan a maipalubos gapu ta makapataudda a manglabas kadagiti panangigawid ti seguridad.",
        "upload-source": "Taudan ti papeles",
        "sourcefilename": "Taudan a nagan ti papeles:",
        "sourceurl": "Taudan ti URL:",
        "destfilename": "Pangipanan ti nagan ti papeles:",
-       "upload-maxfilesize": "Kadakkel a rukod ti papeles: $1",
-       "upload-description": "Panagipalpalawag ti papeles",
-       "upload-options": "Pagpilian ti pinag-ipan",
+       "upload-maxfilesize": "Kadakkelan a rukod ti papeles: $1",
+       "upload-description": "Deskripsion ti papeles",
+       "upload-options": "Dagiti pagpilian ti panagikarga",
        "watchthisupload": "Bantayan daytoy a papeles",
-       "filewasdeleted": "Ti papeles a nanaganan ti kastoy ket naipapan idin ken napaikkaten.\nKitaem ti $1 sakbay ka nga agi pag-ipan manen.",
-       "filename-bad-prefix": "Ti nagan ti papeles nga inpanmo ket mangrugi ti '''\"$1\"''', ket saan a maipalpalawag a nagan a kayarigan a naipusgan nga automatiko kadagiti digital a pangretrato.\nPangngaasi ti agpili ti maikapalpalawag a nagan ti papelesmo.",
-       "upload-success-subj": "Balligi ti pinag-ipan",
-       "upload-success-msg": "Ti panag-ipan a naggapu idiay [$2] ket naballigi. Ket adda ditoy: [[:{{ns:file}}:$1]]",
-       "upload-failure-subj": "Parikut ti pinag-ipan",
-       "upload-failure-msg": "Addaan ti parikut ti pinag-ipanmo a naggapu idiay [$2]:\n\n$1",
-       "upload-warning-subj": "Ballaag iti pinag-ipan",
-       "upload-warning-msg": "Addaan a parikut ti panag-ipan a naggapu idiay [$2]. Mabalinmo ti agsubli ti [[Special:Upload/stash/$1|nakabuklan ti pag-ipan]] tapno masimpaan ti parikut.",
+       "filewasdeleted": "Ti papeles iti daytoy a nagan ket dati a naikarga ken kanungpalan a naikkat.\nNasken a kitaem ti $1 sakbay nga agtuloy a mangikarga manen.",
+       "filename-bad-prefix": "Ti nagan ti papeles nga ikarkargam ket mangrugi iti <strong>\"$1\"</strong>,  ken saan a deskriptibo a nagan a kadawyan nga automatiko nga ited babaen dagiti digital a kamera.\nPangngaasi nga agpili ti nasaysayaat a deskriptibo a nagan ti papelesmo.",
+       "upload-success-subj": "Balligi ti panagikarga",
+       "upload-success-msg": "Ti panagikargam manipud ti [$2] ket nagballigi. Daytoy ket magun-od ditoy [[:{{ns:file}}:$1]]",
+       "upload-failure-subj": "Parikut ti panagikarga",
+       "upload-failure-msg": "Adda parikut ti panagikargam manipud ti [$2]:\n\n$1",
+       "upload-warning-subj": "Ballaag ti panagikarga",
+       "upload-warning-msg": "Adda parikut iti panagikargam manipud ti [$2]. Mabalinmo ti agsubli iti [[Special:Upload/stash/$1|porma ti panagikarga]] tapno masimpa daytoy a parikut.",
        "upload-proto-error": "Saan a husto a protokol",
-       "upload-proto-error-text": "Dagiti adayo a pinag-ipan ket makasapul kadagiti URL a mangrugi iti <code>http://</code> wenno <code>ftp://</code>.",
+       "upload-proto-error-text": "Ti adayo a panagikarga ket makasapul kadagiti URL a mangrugi iti <code>http://</code> wenno <code>ftp://</code>.",
        "upload-file-error": "Akin-uneg a biddut",
-       "upload-file-error-text": "Adda biddut a naggapu iti uneg idi padasen ti agaramid ti saan nga agnayon a papeles dita server.\nPangngaasi a kontaken ti [[Special:ListUsers/sysop|administrador]]",
-       "upload-misc-error": "Di ammo a biddut ti panag-ipan",
-       "upload-misc-error-text": "Adda saan nga ammo a biddut ti napasamak idi agdama a nag-ipan.\nPangngaasi a  kitaen ti URL ket umisu  ken maserrekan ken padasem manen.\nNo ti parikut ket agsubli latta, kontaken ti [[Special:ListUsers/sysop|administrador]].",
-       "upload-too-many-redirects": "Adu unay ti baw-ing daytoy nga URL",
-       "upload-http-error": "Naka-adda ti biddut ti HTTP: $1",
-       "upload-copy-upload-invalid-domain": "Ti kopia a panagipan ket saan a magun-od manipud iti daytoy a pagturayan.",
-       "backend-fail-stream": "Saan a maiwaig ti papeles $1.",
-       "backend-fail-backup": "Saan a maidulin ti papeles $1.",
-       "backend-fail-notexists": "Ti papeles a $1 ket awanen.",
-       "backend-fail-hashes": "Saan a maala dagiti papeles a hash tapno maipada.",
-       "backend-fail-notsame": "Addaan ti saan a kapada ti papeles idiay $1.",
-       "backend-fail-invalidpath": "$1 ket imbalido a pagnaan ti pagidulinan.",
-       "backend-fail-delete": "Saan a maikkat ti papeles $1.",
-       "backend-fail-describe": "Saam a mabaliwan ti metadata para iti papeles ti \"$1\".",
-       "backend-fail-alreadyexists": "Ti papeles $1 ket addan.",
-       "backend-fail-store": "Saan a maidulin ti papeles $1 idiay $2.",
-       "backend-fail-copy": "Saan a makopia ti papeles $1 idiay $2.",
-       "backend-fail-move": "Saan a maiyalis ti papeles $1 idiay $2.",
+       "upload-file-error-text": "Adda napasamak nga akin-uneg a biddut idi nagpadpadas nga agpartuat ti temporario a papeles iti server.\nPangngaasi a kontaken ti maysa nga [[Special:ListUsers/sysop|administrador]].",
+       "upload-misc-error": "Di ammo a biddut ti panagikarga",
+       "upload-misc-error-text": "Adda napasamak a di ammo a biddut idi las-ud ti panagikarga.\nPangngaasi a pasingkedan ti URL ket umisu ken maserrekan ken padasem manen.\nNo ti parikut ket agsubli latta, kontaken ti maysa nga [[Special:ListUsers/sysop|administrador]].",
+       "upload-too-many-redirects": "Ti URL ket naglaon kadagiti adu unay a baw-ing",
+       "upload-http-error": "Adda napasamak a biddut ti HTTP: $1",
+       "upload-copy-upload-invalid-domain": "Dagiti kopia a panagikarga ket saan a magun-od manipud ti daytoy a dominio.",
+       "backend-fail-stream": "Saan a maipan ti papeles $1.",
+       "backend-fail-backup": "Saan a makaidulin ti kapada ti papeles ti $1.",
+       "backend-fail-notexists": "Awan ti papeles ti $1.",
+       "backend-fail-hashes": "Saan a makaala kadagiti hash ti papeles para iti panangipada.",
+       "backend-fail-notsame": "Addan ti awan kapada a papeles idiay \"$1\".",
+       "backend-fail-invalidpath": "Ti \"$1\" ket imbalido a dalan ti pagidulinan.",
+       "backend-fail-delete": "Saan a maikkat ti papeles ti \"$1\".",
+       "backend-fail-describe": "Saan a mabaliwan ti metadata para iti papeles ti \"$1\".",
+       "backend-fail-alreadyexists": "Addan ti papeles ti \"$1\".",
+       "backend-fail-store": "Saan a maidulin ti papeles ti \"$1\" iti \"$2\".",
+       "backend-fail-copy": "Saan a makopia ti papeles ti \"$1\" iti \"$2\".",
+       "backend-fail-move": "Saan a maiyalis ti papeles ti \"$1\" iti \"$2\".",
        "backend-fail-opentemp": "Saan a malukatan ti temporario a papeles.",
        "backend-fail-writetemp": "Saan a masuratan ti temporario a papeles.",
        "backend-fail-closetemp": "Saan a marikpan ti temporario a papeles.",
-       "backend-fail-read": "Saan a mabasa ti papeles $1.",
-       "backend-fail-create": "Saan a masuratan ti papeles $1.",
-       "backend-fail-maxsize": "Saan a masuratan ti papeles $1 gaputa dakdakkel ngem {{PLURAL:$2|maysa a byte|dagiti $2 a byte}}.",
-       "backend-fail-readonly": "Ti pagidulinan a kalikudan ti \"$1\" ket agdama a mabasa laeng. Ti rason a naited idi ket: \"$2\"",
-       "backend-fail-synced": "Ti papeles \"$1\" ket bangking ti kasasaadna iti kinauneg a pagidulinan ti kalikudan",
-       "backend-fail-connect": "Saan a makaikapet idiay pagidulinan a kalikudan  \"$1\".",
-       "backend-fail-internal": "Adda di amammo a biddut ti napasamak idiay pagidulinan a kalikudan \"$1\".",
-       "backend-fail-contenttype": "Saan a maammoan ti kita ti linaon ti papeles nga idulin idiay \"$1\".",
-       "backend-fail-batchsize": "Nagited ti nagipenpenan ti bunggoy iti $1 a papeles {{PLURAL:$1|nga aramid|nga ar-aramid}}; ti patingga ket $2 {{PLURAL:$2|nga aramid|nga ar-aramid}}.",
-       "backend-fail-usable": "Saan a mabasa wenno masuratan ti papeles $1 gaputa awan ti makaanay a pammalubos wenno awan dagiti direktorio/pangikabilan.",
-       "filejournal-fail-dbconnect": "Saan a maikapet idiay warnakan a database para iti likudan a pagipenpenan \"$1\".",
-       "filejournal-fail-dbquery": "Saan a makapabaro idiay warnakan a database para iti likudan a pagipenpenan \"$1\".",
+       "backend-fail-read": "Saan a mabasa ti papeles ti \"$1\".",
+       "backend-fail-create": "Saan a masuratan ti papeles ti \"$1\".",
+       "backend-fail-maxsize": "Saan a masuratan ti papeles ti \"$1\" gapu ta daytoy ket dakdakkel ngem {{PLURAL:$2|maysa a byte|dagiti $2 a byte}}.",
+       "backend-fail-readonly": "Ti pagidulinan a kalikudan ti \"$1\" ket agdama a mabasa laeng. Ti rason a naited idi ket: \"<em>$2</em>\"",
+       "backend-fail-synced": "Ti papeles ti \"$1\" ket bangking ti kasasaadna iti kaunegan a pagidulinan dagiti kalikudan",
+       "backend-fail-connect": "Saan a makaikapet idiay pagidulinan a kalikudan ti \"$1\".",
+       "backend-fail-internal": "Adda napasamak a di ammo a biddut idiay pagidulinan a kalikudan ti \"$1\".",
+       "backend-fail-contenttype": "Saan a maikeddeng ti kita ti linaon iti papeles a maidulin iti \"$1\".",
+       "backend-fail-batchsize": "Ti pagidulinan a likudan ket naited a paset ti papeles ti $1 nga {{PLURAL:$1|operasion|op-operasion}}; ti patingga ket $2 nga {{PLURAL:$2|operasion|op-operasion}}.",
+       "backend-fail-usable": "Saan a mabasa wenno masuratan ti papeles ti \"$1\" gapu ta awan ti makaanay a pammalubos wenno awan dagiti direktorio/pagikabilan.",
+       "filejournal-fail-dbconnect": "Saan a maikapet iti database ti warnakan a para iti likudan a pagipenpenan ti \"$1\".",
+       "filejournal-fail-dbquery": "Saan a makapabaro ti database ti warnakan para iti likudan a pagipenpenan ti \"$1\".",
        "lockmanager-notlocked": "Saan a malukatan ti \"$1\"; saan a nakandaduan.",
        "lockmanager-fail-closelock": "Saan a marikepan ti nakandaduan a papeles para iti \"$1\".",
-       "lockmanager-fail-deletelock": "Saan a maikkat ti nakandaduan a papeles para iti \"$1\".",
+       "lockmanager-fail-deletelock": "Saan a maikkat ti kandado ti papeles para iti \"$1\".",
        "lockmanager-fail-acquirelock": "Saan a makaala ti kandado para iti \"$1\".",
        "lockmanager-fail-openlock": "Saan a malukatan ti kandado ti papeles para iti \"$1\".",
        "lockmanager-fail-releaselock": "Saan a maibbatan ti kandado para iti \"$1\".",
-       "lockmanager-fail-db-bucket": "Saan a makasilpo ti umanay a kandado kadagiti database idiay timba $1.",
-       "lockmanager-fail-db-release": "Saan a maibbatan dagiti kandado idiay database $1.",
-       "lockmanager-fail-svr-acquire": "Saan a makaala kadagiti kandado ti server $1.",
-       "lockmanager-fail-svr-release": "Saan a maibbatan dagiti kandado idiay server $1.",
-       "zip-file-open-error": "Adda biddut a nasarakan idi panaglukat ti papeles ti panagkita a ZIP.",
-       "zip-wrong-format": "Ti nainagan a papeles ket saan a ZIP a papeles.",
-       "zip-bad": "Daytoy a papeles ket nadadael wenno saan a mabasa a kas ZIP a papeles.\nSaan a mabalin a nasayaat a makita para iti seguridad.",
-       "zip-unsupported": "Ti papeles ket ZIP a papeles nga agus-usar ti ZIP a langa a saan a sinuportaran babaen ti MediaWiki .\nSaan a mabalin a nasayaat a makita para iti seguridad.",
-       "uploadstash": "Pinag-ipan ti stash",
-       "uploadstash-summary": "Daytoy a panid ket mangted ti panagserrek kadagiti papeles a napag-ipan (wenno nairugi a naipan) ngem saan pay a naipablaak iti wiki. Dagitoy a papeles ket saan a makita ti sabsabali ngem laeng ti agar-aramat a nag-ipan kaniada.",
+       "lockmanager-fail-db-bucket": "Saan a makakontak ti umanay a kandado dagiti database idiay timba ti $1.",
+       "lockmanager-fail-db-release": "Saan a maibbatan dagiti kandado iti database ti $1.",
+       "lockmanager-fail-svr-acquire": "Saan a makaala kadagiti kandado ti server ti $1.",
+       "lockmanager-fail-svr-release": "Saan a maibbatan dagiti kandado iti server ti $1.",
+       "zip-file-open-error": "Adda napasamak a biddut idi lukluktan ti papeles para kadagiti panagkita ti ZIP.",
+       "zip-wrong-format": "Ti nainagan a papeles ket saan a papeles ti ZIP.",
+       "zip-bad": "Daytoy a papeles ket nadadael wenno saan a mabasa a papeles ti ZIP.\nSaan a mabalin a nasayaat a makita para iti seguridad.",
+       "zip-unsupported": "Ti papeles ket papales ti ZIP nga agus-usar ti ZIP a langa a saan a masuportaran babaen ti MediaWiki .\nSaan a mabalin a nasayaat a makita para iti seguridad.",
+       "uploadstash": "Panagikarga ti stash",
+       "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 panag-urnos ket nagpaso. Padasem manen.",
+       "uploadstash-badtoken": "Ti panag-tungpal dayta nga aramid ket napaay, ngamin ta dagiti talekmo ti panag-urnos ket nagpason. Padasen manen.",
        "uploadstash-errclear": "Ti panagdalus kadagiti papeles ket napaay.",
-       "uploadstash-refresh": "Pasadiwaam dagiti listaan ti papeles",
-       "invalid-chunk-offset": "Imbalido ti maysa a tangdan",
-       "img-auth-accessdenied": "naiparit ti iseserrek",
-       "img-auth-nopathinfo": "Ti servermo ket mabalin nga agipasa iti daytoy a pakaammo.\nBaka met laeng naibasta ti CGI ken saan na a tapayaen ti img_auth.\nKitaen ti https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization .",
-       "img-auth-notindir": "Ti kiniddaw a dalan ket saan a ti naaramid a direktorio ti pag-ipan",
-       "img-auth-badtitle": "Saan a makaaramid ti umisu a titulo a naggapu idiay \"$1\".",
+       "uploadstash-refresh": "Pasadiwaen dagiti listaan ti papeles",
+       "invalid-chunk-offset": "Imbalido a pirgis ti timbengan",
+       "img-auth-accessdenied": "Nalibak ti iseserrek",
+       "img-auth-nopathinfo": "Ti servermo ket saan a naisaad nga agipasa iti daytoy a pakaammo.\nMabalin a naibatay iti CGI ken saan a makasuporta ti img_auth.\nKitaen ti https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization .",
+       "img-auth-notindir": "Ti kiniddaw a dalan ket saan nga adda iti naaramid a direktorio ti pagikargaan",
+       "img-auth-badtitle": "Saan a makaaramid ti umisu a titulo manipud ti \"$1\".",
        "img-auth-nologinnWL": "Saanka a nakastrek ken ti \"$1\" ket awan idiay mabalin a listaan.",
-       "img-auth-nofile": "Ti papeles \"$1\" ket awan dita.",
-       "img-auth-isdir": "Agserserrekka ti direktorio ti papeles \"$1\".\nTi iseserrek ti papeles ti mabalin laeng.",
-       "img-auth-streaming": "Agwaig \"$1\".",
-       "img-auth-public": "Ti pamay-an ti img_auth.php ket mangiruar kadagiti papeles manipud ti pribado a wiki.\nDaytoy a wiki naipabalin a kas publiko a wiki.\nPara iti kangatuan a talinaay, nabaldado ti img_auth.php.",
-       "img-auth-noread": "Ti agar-aramat ket awan ti pammalubosna nga agbasa \"$1\".",
+       "img-auth-nofile": "Awan ti papeles ti \"$1\".",
+       "img-auth-isdir": "Padpadasem ti mangserrek ti direktorio ti \"$1\".\nTi laeng panagserrek ti papeles ti maipalubos.",
+       "img-auth-streaming": "Agip-ipan ti \"$1\".",
+       "img-auth-public": "Ti annong ti img_auth.php ket ti mangiruar kadagiti papeles manipud ti pribado a wiki.\nDaytoy a wiki naaramid a kas publiko a wiki.\nPara iti kangatuan a seguridad, nabaldado ti img_auth.php.",
+       "img-auth-noread": "Ti agar-aramat ket awan ti pammalubosna nga agbasa ti \"$1\".",
        "http-invalid-url": "Imbalido nga URL: $1",
-       "http-invalid-scheme": "Ti URL nga adda ti \"$1\" a pamuspusan ket saan a masuportaran.",
+       "http-invalid-scheme": "Dagiti URL nga addaan iti \"$1\" a pamuspusan ket saan a masuportaran.",
        "http-request-error": "Ti panagkiddaw ti HTTP ket napaay gapu ti di ammo a biddut.",
        "http-read-error": "Biddut ti panagbasa ti HTTP.",
        "http-timed-out": "Nagsardeng ti panagkiddaw ti HTTP.",
        "http-curl-error": "Biddut ti panagala ti URL: $1",
        "http-bad-status": "Adda pakirut idi las-ud ti panagkiddaw ti HTTP: $1 $2",
        "upload-curl-error6": "Di madanon ti URL",
-       "upload-curl-error6-text": "Ti URL a naited ket saan a madanon.\nPangngaasi a kitaem manen no husto ti URL ken adda dayta a pagsaadan.",
-       "upload-curl-error28": "Nagsardeng ti panag-ipan",
-       "upload-curl-error28-text": "Ti pagsaadan ket nabayag unay a simmungbat.\nPangngaasi a kitaen no naipatakder ti pagsaadan, aguray no madamdama ket padasem manen.\nBaka kayatmo a padasen no saan a makumikom nga oras.",
-       "license": "Lisensia:",
-       "license-header": "Lisensia",
+       "upload-curl-error6-text": "Ti URL a naited ket saan a madanon.\nPangngaasi a kitaem manen no husto ti URL ken adda dayta a sitio.",
+       "upload-curl-error28": "Nagsardeng ti panagikarga",
+       "upload-curl-error28-text": "Ti sitio ket nabayag unay a simmungbat.\nPangngaasi a kitaen no naipatakder ti sito, aguray no madamdama ket padasen manen.\nBaka kayatmo a padasen iti saan a makumikom nga oras.",
+       "license": "Panaglisensia:",
+       "license-header": "Panaglisensia",
        "nolicense": "Awan ti napili",
-       "license-nopreview": "(Saan a mabalin nga ipadas)",
-       "upload_source_url": " (maysa nga umisu, ken maserrekan ti publiko nga URL)",
-       "upload_source_file": "(papeles iti kompiutermo)",
-       "listfiles-summary": "Daytoy nga espesial a panid ket agiparang kadagiti amin a naipan a papeles.",
-       "listfiles_search_for": "Agsapul para iti nagan ti midia:",
+       "licenses-edit": "Urnosen dagiti pagpilian ti lisensia",
+       "license-nopreview": "(Saan a magun-od ti panagipadas)",
+       "upload_source_url": "(ti pinilim a papeles manipud ti umiso, ken publiko a maserrekan nga URL)",
+       "upload_source_file": "(ti pinilim a papeles manipud ti kompiutermo)",
+       "listfiles-delete": "ikkaten",
+       "listfiles-summary": "Daytoy nga espesial a panid ket agiparang kadagiti amin a naikarga a papeles.",
+       "listfiles_search_for": "Agbiruk para iti nagan ti midia:",
        "imgfile": "papeles",
        "listfiles": "Listaan ti papeles",
        "listfiles_thumb": "Bassit a ladawan",
        "listfiles_name": "Nagan",
        "listfiles_user": "Agar-aramat",
        "listfiles_size": "Kadakkel",
-       "listfiles_description": "Panagipalpalawag",
+       "listfiles_description": "Deskripsion",
        "listfiles_count": "Dagiti bersion",
        "listfiles-show-all": "Iraman dagiti daan a bersion dagiti ladawan",
        "listfiles-latestversion": "Agdama a bersion",
        "listfiles-latestversion-no": "Saan",
        "file-anchor-link": "Papeles",
        "filehist": "Pakasaritaan ti papeles",
-       "filehist-help": "Ipindut ti maysa a petsa/oras tapno makitam ti papeles iti kasisigud a langana iti dayta nga oras.",
+       "filehist-help": "Pinduten iti petsa/oras tapno makita ti papeles a kas naiparang iti dayta a panawen.",
        "filehist-deleteall": "ikkaten amin",
        "filehist-deleteone": "ikkaten",
        "filehist-revert": "isubli",
        "filehist-datetime": "Petsa/Oras",
        "filehist-thumb": "Bassit a ladawan",
        "filehist-thumbtext": "Bassit a ladawan para iti bersion manipud idi $1",
-       "filehist-nothumb": "Awan ti napabassit a ladawan",
+       "filehist-nothumb": "Awan ti bassit a ladawan",
        "filehist-user": "Agar-aramat",
        "filehist-dimensions": "Dagiti rukod",
        "filehist-filesize": "Kadakkel ti papeles",
        "filehist-comment": "Komentario",
-       "imagelinks": "Panagusar ti papeles",
-       "linkstoimage": "Ti sumaganad {{PLURAL:$1|a silpo ti panid|kadagiti $1 a silpo ti panid}} ditoy a papeles:",
-       "linkstoimage-more": "Ad-adu ngem $1 {{PLURAL:$1|a silsilpo ti panid|silpo ti pampanid}} iti daytoy a papeles.\nTi sumaganad a listaan ket agipakita {{PLURAL:$1|ti umona a silpo ti panid|kadagiti umuna a $1 a silpo ti panid}} iti daytoy laeng a papeles.\nMagun-od ti [[Special:WhatLinksHere/$2|kompleto a listaan]].",
+       "imagelinks": "Panag-usar ti papeles",
+       "linkstoimage": "Ti sumaganad {{PLURAL:$1|a silsilpo ti panid|kadagiti $1 a silpo ti pampanid}} iti daytoy a papeles:",
+       "linkstoimage-more": "Ad-adu ngem $1 {{PLURAL:$1|a silsilpo ti panid|a silpo ti pampanid}} iti daytoy a papeles.\nTi sumaganad a listaan ket mangipakita {{PLURAL:$1|ti umona a silpo ti panid|kadagiti umuna a $1 a silsilpo ti panid}} iti daytoy laeng a papeles.\nMagun-od ti [[Special:WhatLinksHere/$2|kompleto a listaan]].",
        "nolinkstoimage": "Awan ti pampanid a nakasilpo iti daytoy a papeles.",
-       "morelinkstoimage": "Kitaen ti [[Special:WhatLinksHere/$1|ad-adu pay a silpo]] iti daytoy a papeles.",
+       "morelinkstoimage": "Kitaen ti [[Special:WhatLinksHere/$1|adu pay a silsilpo]] iti daytoy a papeles.",
        "linkstoimage-redirect": "$1 (baw-ing ti papeles) $2",
-       "duplicatesoffile": "Ti sumaganad a {{PLURAL:$1|papeles ket duplikado|a $1 a pappapeles ket duplikado}} iti daytoy a papeles ([[Special:FileDuplicateSearch/$2|adu pay a salaysay]]):",
-       "sharedupload": "Daytoy a papeles ket naggapu idiay $1 ken mabalin a mausar kadagiti sabsabali a gandat.",
-       "sharedupload-desc-there": "Daytoy a papeles ket naggapu idiay $1 ken mabalin a mausar kadagiti sabsabali a gandat.\nPangngaasi a kitaem ti [$2 pagipalpalawag ti panid] para iti adu pay a pakaammo.",
-       "sharedupload-desc-here": "Daytoy a papeles ket naggapu idiay $1 ken mabalin a mausar kadagiti sabsabali a gandat.\nTi pagipalpalawagna idiay [$2 pagipalpalawag a panid ti papeles ] ket naipakita dita baba.",
-       "sharedupload-desc-edit": "Daytoy a papeles ket naggapu manipud idiay $1 ken mabalin a mausar babaen dagiti sabali a gandat.\nBaka kayatmo nga urnosen ti bukodna a deskripsion idiay [$2 deskripsion ti papeles a panid].",
-       "sharedupload-desc-create": "Daytoy a papeles ket naggapu manipud idiay $1 ken mabalin a mausar babaen dagiti sabali a gandat.\nBaka kayatmo nga urnosen ti bukodna a deskripsion idiay [$2 deskripsion ti papeles a panid].",
+       "duplicatesoffile": "Ti sumaganad a {{PLURAL:$1|papeles ket duplikado|a $1 a pappapeles ket duplikado}} iti daytoy a papeles ([[Special:FileDuplicateSearch/$2|adu pay a salaysay]]):",
+       "sharedupload": "Daytoy a papeles ket manipud ti $1 ken mabalin a mausar babaen dagiti sabali a gandat.",
+       "sharedupload-desc-there": "Daytoy a papeles ket manipud ti $1 ken mabalin a mausar babaen dagiti sabali a gandat.\nPangngaasi a kitaem ti [$2 panid ti deskripsion ti papeles] para iti adu pay a pakaammo.",
+       "sharedupload-desc-here": "Daytoy a papeles ket manipud ti $1 ken mabalin a mausar babaen dagiti sabali a gandat.\nTi deskripsion iti [$2 panid ti deskripsion ti papelesna] idiay ket naipakita dita baba.",
+       "sharedupload-desc-edit": "Daytoy a papeles ket manipud ti $1 ken mabalin a mausar babaen dagiti sabali a gandat.\nMabalin a kayatmo nga urnosen ti bukodna a deskripsion idiay [$2 panid ti deskripsion ti papeles].",
+       "sharedupload-desc-create": "Daytoy a papeles ket manipud ti $1 ken mabalin a mausar babaen dagiti sabali a gandat.\nMabalin a kayatmo nga urnosen ti bukodna a deskripsion idiay [$2 panid ti deskripsion ti papeles].",
        "filepage-nofile": "Awan ti agnagan ti kasta a papeles.",
-       "filepage-nofile-link": "Awan ti agnagan ti kastoy a papeles, ngem mabalinmo ti [$1 mangipan].",
-       "uploadnewversion-linktext": "Mangipan ti kabarbaro a bersion iti daytoy a papeles",
-       "shared-repo-from": "Naggapo iti $1",
-       "shared-repo": "iti pagbingbingayan a nagikabilan",
-       "upload-disallowed-here": "Saanmo a masuratan manen daytoy a ladawan.",
+       "filepage-nofile-link": "Awan ti agnagan ti kastoy a papeles, ngem mabalinmo ti [$1 agikarga].",
+       "uploadnewversion-linktext": "Agikarga ti baro a bersion iti daytoy a papeles",
+       "shared-repo-from": "manipud ti $1",
+       "shared-repo": "ti pagbingbingayan a repositorio",
+       "upload-disallowed-here": "Saanmo a masuratan manen daytoy a papeles.",
        "filerevert": "Isubli ti $1",
        "filerevert-legend": "Isubli ti papeles",
-       "filerevert-intro": "Mangrugrugika nga agipasubli ti papeles '''[[Media:$1|$1]]''' iti [$4 bersion ti oras ket petsa nga $3, $2].",
+       "filerevert-intro": "Mangrugrugika nga agipasubli ti papeles ti <strong>[[Media:$1|$1]]</strong> iti [$4 bersion manipud idi $3, $2].",
        "filerevert-comment": "Rason:",
-       "filerevert-defaultcomment": "Naisubli ti bersion manipud idi $2, $1",
+       "filerevert-defaultcomment": "Naisubli iti bersion manipud idi $2, $1",
        "filerevert-submit": "Isubli",
-       "filerevert-success": "Ti '''[[Media:$1|$1]]''' ket naipasubli idiay [$4 bersion ti oras ken petsa $3, $2].",
-       "filerevert-badversion": "Awan ti dati a lokal a bersion daytoy a papeles a naited ti dayta nga oras ken petsa.",
+       "filerevert-success": "Ti <strong>[[Media:$1|$1]]</strong> ket naipasubli iti [$4 bersion manipud idi $3, $2].",
+       "filerevert-badversion": "Awan ti dati a lokal a bersion iti daytoy a papeles a naited ti dayta nga oras ken petsa.",
        "filedelete": "Ikkaten ti $1",
        "filedelete-legend": "Ikkaten ti papeles",
-       "filedelete-intro": "Mangrugrugika nga agikkat ti '''[[Media:$1|$1]]''' ken mairaman amin a pakasaritaanna.",
-       "filedelete-intro-old": "Ikikkatem ti bersion iti '''[[Media:$1|$1]]''' manipud idi [$4 $3, $2].",
+       "filedelete-intro": "Mangrugrugika nga agikkat ti <strong>[[Media:$1|$1]]</strong> ken mairaman amin a pakasaritaanna.",
+       "filedelete-intro-old": "Ikikkatem ti bersion iti <strong>[[Media:$1|$1]]</strong> manipud idi [$4 $3, $2].",
        "filedelete-comment": "Rason:",
        "filedelete-submit": "Ikkaten",
-       "filedelete-success": "Naikkaten ti '''$1'''.",
-       "filedelete-success-old": "Ti bersion iti '''[[Media:$1|$1]]''' manipud idi $3, $2 ket naikkaten.",
-       "filedelete-nofile": "awan ti '''$1''' .",
-       "filedelete-nofile-old": "Awan ti naidulin a bersion ti '''$1''' nga addaan ti naited a kakitkitana.",
+       "filedelete-success": "Naikkaten ti <strong>$1</strong>.",
+       "filedelete-success-old": "Ti bersion iti <strong>[[Media:$1|$1]]</strong> manipud idi $3, $2 ket naikkaten.",
+       "filedelete-nofile": "awan ti <strong>$1</strong> .",
+       "filedelete-nofile-old": "Awan ti naidulin a bersion ti <strong>$1</strong> nga addaan kadagiti naited a gupit.",
        "filedelete-otherreason": "Sabali/maipatinayon a rason:",
        "filedelete-reason-otherlist": "Sabali a rason",
-       "filedelete-reason-dropdown": "*Kadawyan a rasrason ti pannakaikkat\n** Panagsalungasing iti karbengan ti panagkopia\n** Nadoble a papeles",
+       "filedelete-reason-dropdown": "*Kadawyan a rasrason ti pannakaikkat\n** Panagsalungasing iti karbengan ti kopia\n** Duplikado a papeles",
        "filedelete-edit-reasonlist": "Urnosen dagiti rason ti panagikkat",
        "filedelete-maintenance": "Ti panagikkat ken panagisubli kadagiti papaeles ket nabaldado iti las-ud ti panagtartaripato.",
-       "filedelete-maintenance-title": "Saan a maikkat daytoy a papeles",
+       "filedelete-maintenance-title": "Saan a maikkat ti papeles",
        "mimesearch": "Pagbiruk ti MIME",
-       "mimesearch-summary": "Daytoy a panid ket pakabaelanna ti panagsagat ti papeles iti MIME a kitada.\nIkabil: kita ti nagyan/subtipo, a kas ti <code>image/jpeg</code>.",
+       "mimesearch-summary": "Daytoy a panid ket pakabaelanna ti panagsagat kadagiti papeles iti MIME a kitada.\nIkabil: kita ti linaon/subtipo wenno kita ti linaon/*, a kas ti <code>image/jpeg</code>.",
        "mimetype": "Kita ti MIME:",
        "download": "ikarga",
        "unwatchedpages": "Di mabambantayan a pampanid",
        "listduplicatedfiles-summary": "Daytoy ket listaan dagiti papeles a ti kaudian unay a bersion ti papeles ket duplikado ti kaudian unay a bersion iti sabali a papeles. Dagiti laeng lokal a papeles ti maikeddeng.",
        "listduplicatedfiles-entry": "Ti [[:File:$1|$1]] ket addaan [[$3|{{PLURAL:$2|iti duplikado|kadagiti $2 a duplikado}}]].",
        "unusedtemplates": "Dagiti saan a nausar a plantilia",
-       "unusedtemplatestext": "Daytoy a panid ket ilistana dagiti panid idiay {{ns:template}} a nagan ti espasio a saan a nairaman iti sabali a panid.\nLaglagipem ti agkita kadagiti sabsabali a silpo ti plantilia sakbay nga ikkatem ida.",
-       "unusedtemplateswlh": "dagiti sabali a silpo",
+       "unusedtemplatestext": "Daytoy a panid ket ilistana dagiti panid iti nagan ti espasio ti {{ns:template}} a saan a nairaman iti sabali a panid.\nLaglagipem a kitaen dagiti sabali a silpo dagiti plantilia sakbay nga ikkaten ida.",
+       "unusedtemplateswlh": "sabali a silsilpo",
        "randompage": "Pugto a panid",
        "randompage-nopages": "Awan ti pampanid iti sumaganad a {{PLURAL:$2|nagan ti espasio|nagnagan ti espasio}}: $1.",
        "randomincategory": "Pugto a panid iti kategoria",
        "randomincategory-invalidcategory": "Ti \"$1\" ket saan nga umisu a nagan ti kategoria.",
-       "randomincategory-nopages": "Awan ti pampanid iti [[:Category:$1]].",
+       "randomincategory-nopages": "Awan ti pampanid iti kategoria ti [[:Category:$1]].",
        "randomincategory-selectcategory": "Agala ti pugto a panid manipud ti kategoria: $1 $2.",
        "randomincategory-selectcategory-submit": "Inkan",
        "randomredirect": "Pugto a baw-ing",
        "randomredirect-nopages": "Awan dagiti baw-ing iti daytoy a nagan ti espasio ti \"$1\".",
        "statistics": "Estadistika",
        "statistics-header-pages": "Estadistika ti panid",
-       "statistics-header-edits": "Estadistika ti inurnos",
+       "statistics-header-edits": "Estadistika ti panag-urnos",
        "statistics-header-views": "Estadistika ti panagkita",
        "statistics-header-users": "Estadistika ti agar-aramat",
-       "statistics-header-hooks": "Estadistika a sabsabali",
+       "statistics-header-hooks": "Sabali nga estadistika",
        "statistics-articles": "Dagiti naglaon a panid",
        "statistics-pages": "Pampanid",
-       "statistics-pages-desc": "Dagiti amin a panid ti wiki, a mairaman dagiti tungtungan a panid, dagiti baw-ing, ken dadduma pay",
-       "statistics-files": "Ti naipapan a papeles",
+       "statistics-pages-desc": "Amin a pampanid iti wiki, a mairaman dagiti tungtungan a panid, dagiti baw-ing, kdpy.",
+       "statistics-files": "Dagiti naikarga a papeles",
        "statistics-edits": "Dagiti naurnos a panid manipud idi nairugi ti {{SITENAME}}",
-       "statistics-edits-average": "Pagtengngaan nga urnos ti tunggal maysa a panid",
+       "statistics-edits-average": "Dagiti pagtengngaan nga inurnos iti tunggal maysa a panid",
        "statistics-views-total": "Dagiti dagup ti panagkita",
-       "statistics-views-total-desc": "Saan a naikabil ti panagkita dagiti awan a panid ken dagiti espesial a panid",
-       "statistics-views-peredit": "Panagkita ti tunggal maysa nga urnos",
+       "statistics-views-total-desc": "Dagiti panagkita ti awan a pampanid ken saan a mairaman dagiti espesial a panid",
+       "statistics-views-peredit": "Panagkita iti tunggal maysa a panag-urnos",
        "statistics-users": "Dagiti nakarehistro nga [[Special:ListUsers|agar-aramat]]",
-       "statistics-users-active": "Dagiti nasiglat nga agar-aramat",
-       "statistics-users-active-desc": "Dagiti agar-aramat a nagtungpal ti aramid ti napalabas nga {{PLURAL:$1|aldaw|$1 nga al-aldaw}}",
+       "statistics-users-active": "Dagiti aktibo nga agar-aramat",
+       "statistics-users-active-desc": "Dagiti agar-aramat a nagtungpal ti aramid iti napalabas nga {{PLURAL:$1|aldaw|$1 nga al-aldaw}}",
        "statistics-mostpopular": "Kaaduan a nabuya a pampanid",
-       "pageswithprop": "Pampanid nga adda maysa a tagikua ti panid",
-       "pageswithprop-legend": "Pampanid nga adda maysa a tagikua ti panid",
+       "pageswithprop": "Pampanid nga adda tagikua ti panid",
+       "pageswithprop-legend": "Pampanid nga adda tagikua ti panid",
        "pageswithprop-text": "Daytoy a panid ket ilistana ti pampanid nga agus-usar ti naisangayan a tagikua ti panid.",
        "pageswithprop-prop": "Nagan ti tagikua:",
        "pageswithprop-submit": "Inkan",
-       "pageswithprop-prophidden-long": "atiddog a testo ti tagikua a nailemmeng ($1)",
+       "pageswithprop-prophidden-long": "atiddog a testo ti pateg ti tagikua a nailemmeng ($1)",
        "pageswithprop-prophidden-binary": "binario a pateg ti tagikua a nailemmeng ($1)",
        "doubleredirects": "Dagiti namindua a naibaw-ing",
-       "doubleredirectstext": "Daytoy a panid ket ilistana dagiti panid nga agbaw-ing kadagiti sabsabali a baw-ing a pampanid.\nIti tunggal maysa nga aray ket adda nagyanna kadagiti silpo iti umuna ken maikadua a baw-ing, ken iti puntaan iti maikadua a baw-ing, nga isu ti \"pudno\" a puntaan ti panid, nga ti umuna a baw-ing ket isu ti ipatudona.\n<del>Nakurosan</del> dagita naikabil ket napadtuan.",
-       "double-redirect-fixed-move": "Naiyalisen ti [[$1]].\nAutomatiko idi a napabaro ken naibaw-ing tattan idiay [[$2]].",
-       "double-redirect-fixed-maintenance": "Automatiko a simsimpaen ti doble a baw-ing manipud ti [[$1]] idiay [[$2]] iti panagtaripato nga obra.",
+       "doubleredirectstext": "Daytoy a panid ket ilistana dagiti panid nga agbaw-ing kadagiti sabali a baw-ing a pampanid.\nIti tunggal maysa nga aray ket aglaon kadagiti silpo iti umuna ken maikadua a baw-ing, ken ti pay puntaan ti maikadua a baw-ing, nga isu ti \"pudno\" a puntaan ti panid, nga ti umuna a baw-ing ket isu koma ti pakaituduanna.\nNasolbaren dagiti <del>nakurosan</del> a naikabil.",
+       "double-redirect-fixed-move": "Naiyalisen ti [[$1]].\nAutomatiko idi a napabaro ken naibaw-ing tattan iti [[$2]].",
+       "double-redirect-fixed-maintenance": "Automatiko nga agsimsimpa ti doble a baw-ing manipud ti [[$1]] iti [[$2]] iti panagtaripato nga obra.",
        "double-redirect-fixer": "Panagsimpa ti baw-ing",
        "brokenredirects": "Dagiti naputed a baw-ing",
-       "brokenredirectstext": "Dagitoy sumaganad a baw-ing ket nakasilpo kadagiti awan a panid:",
+       "brokenredirectstext": "Dagiti sumaganad a baw-ing ket nakasilpo kadagiti awan a panid:",
        "brokenredirects-edit": "urnosen",
        "brokenredirects-delete": "ikkaten",
-       "withoutinterwiki": "Dagiti panid nga awan ti silpona ti pagsasao",
-       "withoutinterwiki-summary": "Dagitoy a pampanid ket saan a nakasilpo ti sabali a bersion ti pagsasao.",
+       "withoutinterwiki": "Pampanid nga awan kadagiti silpo ti pagsasao",
+       "withoutinterwiki-summary": "Dagiti sumaganad a pampanid ket saan a nakasilpo kadagiti sabali a bersion ti pagsasao.",
        "withoutinterwiki-legend": "Pagpasaruno",
        "withoutinterwiki-submit": "Ipakita",
-       "fewestrevisions": "Dagiti panid nga adda kadagiti kabassitan a panangbalbaliw",
+       "fewestrevisions": "Dagiti panid nga adda kadagiti kabassitan a rebision",
        "nbytes": "$1 {{PLURAL:$1|a byte|dagiti byte}}",
        "ncategories": "$1 {{PLURAL:$1|a kategoria|a katkategoria}}",
        "ninterwikis": "$1 {{PLURAL:$1|nga interwiki|dagiti interwiki}}",
        "nlinks": "$1 {{PLURAL:$1|a silpo|kadagiti silpo}}",
        "nmembers": "$1 {{PLURAL:$1|a kameng|kamkameng}}",
        "nmemberschanged": "$1 → $2 {{PLURAL:$2|kameng|kamkameng}}",
-       "nrevisions": "$1 {{PLURAL:$1|a panagbalbaliw|kadagiti panagbalbaliw}}",
+       "nrevisions": "$1 {{PLURAL:$1|a rebison|kadagiti rebision}}",
        "nviews": "$1 {{PLURAL:$1|a panangkita|kadagiti panangkita}}",
-       "nimagelinks": "Inusar idiay $1 {{PLURAL:$1|a panid|a pampanid}}",
-       "ntransclusions": "inusar idiay $1 {{PLURAL:$1|a panid|a pampanid}}",
-       "specialpage-empty": "Awan dagiti nagbanaganna daytoy a padamag.",
+       "nimagelinks": "Inusar iti $1 {{PLURAL:$1|a panid|a pampanid}}",
+       "ntransclusions": "inusar iti $1 {{PLURAL:$1|a panid|a pampanid}}",
+       "specialpage-empty": "Awan dagiti nagbanagan daytoy a reporta.",
        "lonelypages": "Dagiti naulila a panid",
-       "lonelypagestext": "Dagiti sumaganad a panid ket saan a nakasilpo idiay wenno naipakita kadagiti sabali a panid idiay {{SITENAME}}.",
+       "lonelypagestext": "Dagiti sumaganad a panid ket saan a nakasilpo wenno nailak-am kadagiti sabali a panid iti {{SITENAME}}.",
        "uncategorizedpages": "Dagiti saan a nakategoria a panid",
        "uncategorizedcategories": "Dagiti saan a nakategoria a kategoria",
        "uncategorizedimages": "Dagiti saan a nakategoria a papeles",
        "popularpages": "Dagiti nadayeg a panid",
        "wantedcategories": "Dagiti makiddaw a kategoria",
        "wantedpages": "Dagiti makiddaw a panid",
-       "wantedpages-badtitle": "Saan nga umisu a titulo idiay naikabil a pagbanagan: $1",
+       "wantedpages-badtitle": "Imbalido a titulo iti agasmang ti nagbanagan: $1",
        "wantedfiles": "Dagiti makiddaw a papeles",
-       "wantedfiletext-cat": "Dagiti sumaganad a papeles ket maus-usar ngem awanda met. Dagiti papeles a naggapu kadagiti ganganaet a repositorio ket mailista uray pay no addaan da. No adda dagiti kasla adda dagitoy ket <del>maikkat</del> to. A maipanayon pay, dagiti pampanid nga agisengngat kadagiti papeles nga awan ket nailista idiay [[:$1]].",
-       "wantedfiletext-nocat": "Dagiti sumaganad a papeles ket maus-usar ngem awanda met. Dagiti papeles a naggapu kadagiti ganganaet a repositorio ket mailista uray pay no addaan da. No adda dagiti kasla adda dagitoy ket <del>maikkat</del> to.",
+       "wantedfiletext-cat": "Dagiti sumaganad a papeles ket maus-usar ngem awanda met. Dagiti papeles manipud kadagiti ganganaet a repositorio ket mabalin a mailista urayno adda. Ti kasta man a saan nga umno a positibo ket <del>maikkatto</del>. Iti maipatinayon, dagiti panid nga agisengngat kadagiti papeles nga awan ket nailista iti [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Dagiti sumaganad a papeles ket naus-usar ngem awanda met. Iti maipatinayon, dagiti panid a mangipenpen kadagiti papeles ket nailista iti [[:$1]].",
+       "wantedfiletext-nocat": "Dagiti sumaganad a papeles ket maus-usar ngem awanda met. Dagiti papeles manipud ti ganganaet a repositorio ket mabalin a mailista urayno adda. No adda dagiti kasta a saan nga umno a positibo ket <del>maikkatto</del>.",
+       "wantedfiletext-nocat-noforeign": "Dagiti sumaganad a papeles ket naus-usar ngem awanda met.",
        "wantedtemplates": "Dagiti makiddaw a plantilia",
        "mostlinked": "Dagiti panid a kaaduan iti nakasilpo",
        "mostlinkedcategories": "Dagiti kategoria a kaaduan iti nakasilpo",
-       "mostlinkedtemplates": "Dagiti plantilia a kaaduan iti nakasilpo",
+       "mostlinkedtemplates": "Kaaduan a nailak-am a pampanid",
        "mostcategories": "Dagiti panid a kaaduan kadagiti kategoria",
        "mostimages": "Dagiti papeles a kaaduan iti nakasilpo",
        "mostinterwikis": "Dagiti panid a kaaduan kadagiti interwiki",
-       "mostrevisions": "Dagiti artikulo a kaaduan ti pannakabalbaliwna",
+       "mostrevisions": "Dagiti artikulo a kaaduan kadagiti rebision",
        "prefixindex": "Dagiti amin a panid nga addaan iti pasaruno",
-       "prefixindex-namespace": "Amin a panid nga addaan ti pasaruno ($1 a nagan ti espasio)",
+       "prefixindex-namespace": "Amin a pampanid nga addaan iti pasaruno (nagan ti espasio ti $1)",
        "prefixindex-strip": "Ikkaten ti pasaruno iti listaan",
        "shortpages": "Dagiti ababa a panid",
        "longpages": "Dagiti atiddog a panid",
        "deadendpages": "Dagiti ngudo a panid",
-       "deadendpagestext": "Dagitoy a pampanid ket saan a nakasilpo ti sabali a pampanid ditoy {{SITENAME}} .",
+       "deadendpagestext": "Dagiti sumaganad a panid ket saan a nakasilpo kadagiti sabali a panid iti {{SITENAME}}.",
        "protectedpages": "Dagiti nasalakniban a panid",
-       "protectedpages-indef": "Inggat ingana a salakniban laeng",
+       "protectedpages-indef": "Dagiti inggat ingana a salaknib laeng",
        "protectedpages-summary": "Daytoy a panid ket ilistana dagiti panid nga agdama a nasalakniban. Para iti listaan dagiti titulo a nasalakniban manipud ti pannakapartuat, kitaen ti [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Dagiti sariap a salaknib laeng",
        "protectedpages-noredirect": "Ilemmeng dagiti baw-ing",
        "protectedpages-unknown-performer": "Di ammo nga agar-aramat",
        "protectedtitles": "Dagiti nasalakniban a titulo",
        "protectedtitles-summary": "Daytoy a panid ket ilistana dagiti titulo nga agdama a nasalakniban manipud ti pannakapartuat. Para iti listaan dagiti adda a panid a nasalakniban, kitaen ti  [[{{#special:ProtectedPages}}|{{int:protectedpages}}]]..",
-       "protectedtitlesempty": "Awan dagiti titulo nga agdama a nasalakniban iti dagitoy a parametro.",
-       "listusers": "Listaan dagiti agar-aramat",
-       "listusers-editsonly": "Ipakita laeng dagiti agar-aramat nga adda inurnosda",
-       "listusers-creationsort": "Ilasin no ania a petsa ti pannakaaramid",
-       "listusers-desc": "Paglalasinen iti agpababa nga urnos",
+       "protectedtitlesempty": "Awan dagiti titulo nga agdama a nasalakniban kadagitoy a parametro.",
+       "listusers": "Listaan ti agar-aramat",
+       "listusers-editsonly": "Ipakita laeng dagiti agar-aramat nga addaan kadagiti inurnos",
+       "listusers-creationsort": "Ilasin babaen ti petsa a pannakapartuat",
+       "listusers-desc": "Ilasin iti agpababa nga urnos",
        "usereditcount": "$1 {{PLURAL:$1|nga inurnos|kadagiti inurnos}}",
-       "usercreated": "{{GENDER:$3|Inaramid}} idi $1 idi $2",
+       "usercreated": "{{GENDER:$3|Pinartuat}} idi $1, $2",
        "newpages": "Baro a pampanid",
        "newpages-username": "Nagan ti agar-aramat:",
        "ancientpages": "Dagiti kadaanan a panid",
        "move": "Iyalis",
        "movethispage": "Iyalis daytoy a panid",
-       "unusedimagestext": "Adda dagiti sumaganad a papeles ngem saanda a naikabil iti ania man a panid.\nPangngaasi a laglagipen a dagiti sabali a sapot ti pagsaadan  ket makasilpoda ti papeles iti dagus a URL, ken isu pay a nailista da ditoy urayno saanda a naus-usar iti agdama.",
-       "unusedcategoriestext": "Adda dagiti sumaganad a kategoria a panid, ngem awan ti sabali a panid wenno kategoria ti agus-usar kaniada.",
-       "notargettitle": "Awan ti napuntaan",
-       "notargettext": "Saanmo a nainagan ti puntaan a panid wenno agar-aramat ti mangtungpal daytoy nga opisio.",
+       "unusedimagestext": "Adda dagiti sumaganad a papeles ngem saanda a naikabil iti aniaman a panid.\nPangngaasi a laglagipen a dagiti sabali a sitio ti web ket mabalin a nakasilpoda iti papeles iti dagus a URL, ken mabalin pay a nailista ditoy urayno saanda nga aktibo a maus-usar.",
+       "unusedcategoriestext": "Ti sumaganad a kategoria ti pampanid ket adda,urayno awan ti sabali a panid wenno kategoria ti agus-usar kaniada.",
+       "notargettitle": "Awan ti puntaan",
+       "notargettext": "Saanmo a nainagan ti puntaan a panid wenno agar-aramat ti mangtungpal iti daytoy nga annong.",
        "nopagetitle": "Awan ti kasta a puntaan a panid",
        "nopagetext": "Awan ti puntaan a panid a nainaganam.",
-       "pager-newer-n": "{{PLURAL:$1|nabarbaro 1|dagiti nabarbaro $1}}",
-       "pager-older-n": "{{PLURAL:$1|nadadaan 1|nadadaan $1}}",
+       "pager-newer-n": "{{PLURAL:$1|nabarbaro a 1|nabarbaro a $1}}",
+       "pager-older-n": "{{PLURAL:$1|nadadaan a 1|nadadaan a $1}}",
        "suppress": "Pakapansin",
-       "querypage-disabled": "Daytoy a nangruna a panid ket nabaldado gapu kadagiti rason a panagtungpal.",
+       "querypage-disabled": "Daytoy nga espesial a panid ket nabaldado gapu kadagiti rason ti kasayaat ti panagpataray.",
        "booksources": "Dagiti taudan ti libro",
-       "booksources-search-legend": "Agsapul para kadagiti taudan ti libro",
+       "booksources-search-legend": "Agbiruk para kadagiti taudan ti libro",
        "booksources-go": "Inkan",
-       "booksources-text": "Dita baba ket listaan dagiti silpo ti sabsali a lugar nga aglaklako ti liblibro, ken baka adda pay adu a pakaammoda kadagiti liblibro a kitkitaem:",
-       "booksources-invalid-isbn": "Ti naited nga ISBN ket kasla saan nga umisu; kitaen dagiti biddut ti panagtulad kadagiti naggappuanna a taudan.",
-       "specialloguserlabel": "Ti nagtungpal:",
+       "booksources-text": "Dita baba ket listaan dagiti silpo ti sabali a sitio nga aglaklako ti baro ken saan a nausar a liblibro, ken mabalin nga addaan pay iti adu a pakaammo a maipanggep kadagiti libro a birbirukem:",
+       "booksources-invalid-isbn": "Ti naited nga ISBN ket kasla saan nga umisu; kitaen dagiti biddut ti panagtulad manipud ti kasisigud a taudan.",
+       "specialloguserlabel": "Perpormer:",
        "speciallogtitlelabel": "Puntaan (titulo wenno agar-aramat):",
        "log": "Dagiti listaan",
        "all-logs-page": "Amin a listaan a publiko",
-       "alllogstext": "Naipagtipon a pinagpakita kadagiti amin nga adda a listaan ti {{SITENAME}}.\nMapabassitmo ti pinagpakita no piliam ti kita ti listaan, ti nagan ti agar-aramat (sensitibo ti kadakkel ti letra), wenno ti naapektaran a panid (ket sensitibo met ti kadakkel ti letra).",
-       "logempty": "Awan ti agpada a bagay dita listaan.",
-       "log-title-wildcard": "Agsapul kadagiti titulo nga agrugi iti daytoy a testo",
-       "showhideselectedlogentries": "Ipakita/ilemmeng dagiti napili a naikabil ti listaan",
+       "alllogstext": "Naikaykaysa a panagiparang kadagiti amin a magun-od a listaan iti {{SITENAME}}.\nMapabassitmo ti panagkita babaen ti panagpili ti kita ti listaan, ti nagan ti agar-aramat (sensitibo ti kadakkel ti letra), wenno ti naapektaran a panid (sensitibo pay ti kadakkel ti letra).",
+       "logempty": "Awan dagiti maipada a banag iti listaan.",
+       "log-title-wildcard": "Agbiruk kadagiti titulo a mangrugi iti daytoy a testo",
+       "showhideselectedlogentries": "Baliwan ti panagkita kadagiti napili a naikabil iti listaan",
        "allpages": "Amin a pampanid",
        "nextpage": "sumaruno a panid ($1)",
        "prevpage": "Napalabas a panid ($1)",
        "allpagesfrom": "Ipakita dagiti panid a mangrugi iti:",
        "allpagesto": "Ipakita dagiti panid nga agpatingga iti:",
        "allarticles": "Amin a pampanid",
-       "allinnamespace": "Amin a pampanid ($1 a nagan ti espasio)",
+       "allinnamespace": "Amin a pampanid (nagan ti espasio ti $1)",
        "allpagessubmit": "Inkan",
        "allpagesprefix": "Iparang dagiti pampanid nga adda pasarunona:",
-       "allpagesbadtitle": "Ti naited a titulo ti panid ket imbalido wenno adda idi ti sabali a pagsasao wenno interwiki a pasarunona.",
-       "allpages-bad-ns": "Awan ti {{SITENAME}} iti nagan ti espasio a \"$1\".",
+       "allpagesbadtitle": "Ti naited a titulo ti panid ket imbalido wenno adda idi ti sabali a pagsasao wenno interwiki a pasarunona.\nDaytoy ket mabalin nga aglaon iti maysa wenno ad-adu a karkarakter a saan a mausar kadagiti titulo.",
+       "allpages-bad-ns": "Ti {{SITENAME}} ket awan iti nagan ti espasio iti \"$1\".",
        "allpages-hide-redirects": "Ilemmeng dagiti baw-ing",
-       "cachedspecial-viewing-cached-ttl": "Kitkitaem ti naidulin a bersion iti daytoy a panid, nga addan ti kadaanan a $1.",
-       "cachedspecial-viewing-cached-ts": "Kitkitaem ti maysa a naidulin a bersion iti daytoy a panid, a baka daytoy ket saan a kompleto nga agpayso.",
+       "cachedspecial-viewing-cached-ttl": "Kitkitaem ti naidulin a bersion iti daytoy a panid, a mabalin nga agduog iti $1.",
+       "cachedspecial-viewing-cached-ts": "Kitkitaem ti maysa a naidulin a bersion iti daytoy a panid, a mabalin daytoy a saan a kompleto nga agpayso.",
        "cachedspecial-refresh-now": "Kitaen ti kinaudian.",
        "categories": "Katkategoria",
        "categoriespagetext": "Ti sumaganad a {{PLURAL:$1|kategoria ket aglaon|katkategoria ket aglaon}} kadagiti panid wenno midia.\n[[Special:UnusedCategories|Dagiti saan a nausar a kategoria]] ket saan a maiparang ditoy.\nKitaen met [[Special:WantedCategories|dagiti makiddaw a kategoria]].",
        "categoriesfrom": "Ipakita dagiti kategoria a mangrugi iti:",
-       "special-categories-sort-count": "paglalasinen babaen ti bilang",
-       "special-categories-sort-abc": "paglalasinen nga alpabetiko",
-       "deletedcontributions": "Dagiti naikkat nga inararamid ti agar-aramat",
-       "deletedcontributions-title": "Dagiti naikkat nga inararamid ti agar-aramat",
-       "sp-deletedcontributions-contribs": "naar-aramid",
+       "special-categories-sort-count": "ilasin babaen ti bilang",
+       "special-categories-sort-abc": "ilasin nga alpabetiko",
+       "deletedcontributions": "Dagiti naikkat a kontribusion ti agar-aramat",
+       "deletedcontributions-title": "Dagiti naikkat a kontribusion ti agar-aramat",
+       "sp-deletedcontributions-contribs": "dagiti kontribusion",
        "linksearch": "Dagiti panagbiruk ti ruar a silpo",
        "linksearch-pat": "Tabas ti panagbiruk:",
        "linksearch-ns": "Nagan ti espasio:",
        "linksearch-ok": "Biruken",
-       "linksearch-text": "Ti naataap a tarheta a kas ti \"*.wikipedia.org\" ket mabalin nga usaren.\nMasapul ti kangatuan a pagturayan, a kaspagarigan \"*.org\".<br />\n{{PLURAL:$2|Ti protokol|Dagiti protokol}} a nasuportaran: <code>$1</code> (naipakasigud ti http:// no awan ti protokol a nainaganan).",
-       "linksearch-line": "Ti $1 ket nakasilpo idiay $2",
-       "linksearch-error": "Ti naatap a tarheta ket agparang laeng iti panagrugi ti nagan ti agsangaili.",
+       "linksearch-text": "Dagiti naatap a tarheta a kas ti \"*.wikipedia.org\" ket mabalin nga usaren.\nMasapul ti saan a basbassit ngem kangatuan a dominio, kas pagarigan \"*.org\".<br />\n{{PLURAL:$2|Ti protokol|Dagiti protokol}} a nasuportaran: <code>$1</code> (kasisigud iti http:// no awan ti nainaganan a protokol).",
+       "linksearch-line": "Ti $1 ket naisilpo manipud ti $2",
+       "linksearch-error": "Ti naatap a tarheta ket mabalin nga agparang laeng iti rugi ti nagan ti agsangaili.",
        "listusersfrom": "Iparang dagiti agar-aramat a mangrugi iti:",
        "listusers-submit": "Ipakita",
        "listusers-noresult": "Awan ti nasarakan nga agar-aramat.",
        "listusers-blocked": "(naserraan)",
-       "activeusers": "Listaan dagiti nasiglat nga agar-aramat",
-       "activeusers-intro": "Daytoy ti listaan dagiti agar-aramat nga adda inararamidda kadagiti napalabas a $1 {{PLURAL:$1|nga aldaw|nga al-aldaw}}.",
-       "activeusers-count": "$1 {{PLURAL:$1|a tignay|tigtignay}} idi kalpasan ti {{PLURAL:$3|nga aldaw|$3 nga al-aldaw}}",
+       "activeusers": "Listaan dagiti aktibo nga agar-aramat",
+       "activeusers-intro": "Daytoy ti listaan dagiti agar-aramat nga adda inar-aramid iti kaunegan dagiti napalabas a $1 {{PLURAL:$1|nga aldaw|nga al-aldaw}}.",
+       "activeusers-count": "$1 a {{PLURAL:$1|tignay|tigtignay}} iti napalabas {{PLURAL:$3|nga aldaw|a $3 nga al-aldaw}}",
        "activeusers-from": "Iparang dagiti agar-aramat a mangrugi iti:",
        "activeusers-hidebots": "Ilemmeng dagiti bot",
        "activeusers-hidesysops": "Ilemmeng dagiti administrador",
        "activeusers-noresult": "Awan ti nasarakan nga agar-aramat.",
        "listgrouprights": "Dagiti karbengan ti grupo ti agar-aramat",
-       "listgrouprights-summary": "Dagiti sumaganad a listaan ti grupo ti agar-aramat a naipalawag iti daytoy a wiki, a nairaman dagiti karbengan ti panagserrekda.\nAdda pay mabalin nga [[{{MediaWiki:Listgrouprights-helppage}}|adu a pakaammo]] a maipapan kadagiti bukbukod a karbengan.",
-       "listgrouprights-key": "Sarita: \n* <span class=\"listgrouprights-granted\">Naited a karbengan</span> \n* <span class=\"listgrouprights-revoked\">Naukas a karbengan</span>",
+       "listgrouprights-summary": "Dagiti sumaganad a listaan ti grupo ti agar-aramat a naipalawag iti daytoy a wiki, a nairaman dagiti mainaig a karbengan ti panagserrekda.\nAdda pay mabalin nga [[{{MediaWiki:Listgrouprights-helppage}}|adu a pakaammo]] a maipanggep kadagiti kabukbuodan a karbengan.",
+       "listgrouprights-key": "Leyenda: \n* <span class=\"listgrouprights-granted\">Naited a karbengan</span> \n* <span class=\"listgrouprights-revoked\">Naukas a karbengan</span>",
        "listgrouprights-group": "Grupo",
        "listgrouprights-rights": "Dagiti karbengan",
        "listgrouprights-helppage": "Help:Dagiti karbengan ti grupo",
        "listgrouprights-members": "(listaan ti kamkameng)",
-       "listgrouprights-addgroup": "Agnayon ti {{PLURAL:$2|a grupo|kadagiti grupo}} : $1",
-       "listgrouprights-removegroup": "Aggikkat ti {{PLURAL:$2|a grupo|kadagiti grupo}}: $1",
+       "listgrouprights-addgroup": "Agnayon {{PLURAL:$2|iti grupo|kadagiti grupo}} : $1",
+       "listgrouprights-removegroup": "Aggikkat {{PLURAL:$2|iti grupo|kadagiti grupo}}: $1",
        "listgrouprights-addgroup-all": "Inayon amin dagiti grupo",
        "listgrouprights-removegroup-all": "Ikkatem amin dagiti grupo",
-       "listgrouprights-addgroup-self": "Agnayon ti {{PLURAL:$2|a grupo|kadagiti grupo}} iti bukod a pakabilangan: $1",
-       "listgrouprights-removegroup-self": "Agikkat ti {{PLURAL:$2|a grupo|kadagiti grupo}} manipud ti bukod a pakabilangan: $1",
+       "listgrouprights-addgroup-self": "Agnayon {{PLURAL:$2|iti grupo|kadagiti grupo}} iti bukod a pakabilangan: $1",
+       "listgrouprights-removegroup-self": "Agikkat {{PLURAL:$2|iti grupo|kadagiti grupo}} manipud ti bukod a pakabilangan: $1",
        "listgrouprights-addgroup-self-all": "Inayon amin dagiti grupo iti bukod a pakabilangan",
        "listgrouprights-removegroup-self-all": "Ikkatem amin dagiti grupo manipud ti bukod a pakabilangan",
        "listgrouprights-namespaceprotection-header": "Dagiti panangigawid ti nagan ti espasio",
        "index-category-desc": "Ti panid ket addaan iti <code><nowiki>__INDEX__</nowiki></code> (ken adda iti nagan ti espasio a maipalubos ti wagayway), ken isu a naipagsurotan babaen dagiti robot ngem no iti kadawyan ket saan.",
        "post-expand-template-inclusion-category-desc": "Kalpasan ti panagpadakkel kadagiti amin a plantilia, ti kadakkel ti panid ket dakdakkel ngem ti <code>$wgMaxArticleSize</code>, isu a dagiti plantilia ket saan a napadakkel.",
        "post-expand-template-argument-category-desc": "Kalpasan ti panagpadakkel ti argumento ti plantilia (dagiti addaan iti tallo a pangrikep, kasla ti <code>{{{Foo}}}</code>), ti panid ket dakdakkel ngem ti <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Adu unay dagiti nangina nga annong ti parser (kasla ti <code>#ifexist</code>) a nairaman iti panid. Kitaen ti[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "expensive-parserfunction-category-desc": "Adu unay dagiti nangina nga annong ti parser (kasla ti <code>#ifexist</code>) a nairaman iti panid. Kitaen ti [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
        "broken-file-category-desc": "Kategoria a nainayon no ti panid ket aglaon ti nadadael a silpo ti papeles (ti silpo a panangisengngat ti papeles no awan ti papeles).",
-       "hidden-category-category-desc": "Daytoy ket kategoria nga addaan iti <code><nowiki>__HIDDENCAT__</nowiki></code> , a mangpawil daytoy nga agparang kadagiti silpo ti kahon ti kategoria kadagiti panid, bbabaen ti kasisigud.",
+       "hidden-category-category-desc": "Daytoy ket kategoria nga addaan iti <code><nowiki>__HIDDENCAT__</nowiki></code> , a mangpawil daytoy nga agparang kadagiti silpo ti kahon ti kategoria kadagiti panid, babaen ti kasisigud.",
        "trackingcategories-nodesc": "Awan ti magun-od a deskripsion.",
        "trackingcategories-disabled": "Nabaldado ti kategoria",
        "mailnologin": "Awan ti pagipatulodan a pagtaengan",
-       "mailnologintext": "Masapul a [[Special:UserLogin|nakastrekka]] ken adda umisu nga esurat a pagtaengan idiay [[Special:Preferences|kaykayatmo]] ti agipatulod ti esurat kadagiti sabsabali nga agar-aramat.",
+       "mailnologintext": "Masapul a [[Special:UserLogin|nakastrekka]] ken adda umisu nga esurat a pagtaengan idiay [[Special:Preferences|kaykayatam]] tapno makaipatulod iti esurat kadagiti sabali nga agar-aramat.",
        "emailuser": "Esuratan daytoy nga agar-aramat",
        "emailuser-title-target": "Esuratam daytoy nga {{GENDER:$1|agar-aramat}}",
        "emailuser-title-notarget": "Esuratan ti agar-aramat",
        "emailpage": "Esuratan ti agar-aramat",
-       "emailpagetext": "Mabalinmo nga usaren ti kinabuklan dita baba nga agipatulod ti e-surat a mensahe ti daytoy nga {{GENDER:$1|agar-aramat}}.\nTi e-surat nga inkabilmo idiay  [[Special:Preferences|kakaykayatam]] ket agparang a kas \"Naggapu\" a pagtaengan ti e-surat, tapno ti nagipatulodam ket makasungbat kenka.",
+       "emailpagetext": "Mabalinmo nga usaren ti porma dita baba tapno makaipatulod ti esurat a mensahe iti daytoy nga {{GENDER:$1|agar-aramat}}.\nTi esurat nga inkabilmo iti [[Special:Preferences|kakaykayatam]] ket agparang a kas \"Naggapu\" a pagtaengan ti esurat, tapno ti nagipatulodam ket makasungbat kenka.",
        "defemailsubject": "Esurat ti {{SITENAME}} a naggapo kenni \"$1\"",
        "usermaildisabled": "Saanmo a mabalin ti agipatulod ti esurat",
-       "usermaildisabledtext": "Saanmo a mabalin ti agipatulod ti esurat kadagiti sabali nga agar-aramat ditoy a wiki",
+       "usermaildisabledtext": "Saanmo a mabalin ti agipatulod ti esurat kadagiti sabali nga agar-aramat iti daytoy a wiki",
        "noemailtitle": "Awan ti esurat a pagtaengan",
        "noemailtext": "Ti agar-aramat ket saan a nanginagan ti umisu nga esurat a pagtaengan.",
        "nowikiemailtext": "Ti agar-aramat ket mabalinna ti agpili a saan nga umawat iti esurat kadagiti sabali nga agar-aramat.",
        "emailccsubject": "Kopia ti mensahem kenni $1: $2",
        "emailsent": "Naipatuloden ti esurat",
        "emailsenttext": "Naipatuloden ti esurat a mensahem.",
-       "emailuserfooter": "Daytoy nga esurat ket impatulod ni $1 kenni $2 iti \"Esurat\" a panagararamid idiay {{SITENAME}}",
-       "usermessage-summary": "Agibatbati ti mesahe iti sistema.",
-       "usermessage-editor": "Mensahero iti sistema",
+       "emailuserfooter": "Daytoy nga esurat ket impatulod babaen ni $1 kenni $2 iti \"Esurat\" nga annong iti {{SITENAME}}",
+       "usermessage-summary": "Pumanpanaw iti mesahe ti sistema.",
+       "usermessage-editor": "Mensahero ti sistema",
        "watchlist": "Bambantayan",
        "mywatchlist": "Bambantayan",
        "watchlistfor2": "Para iti $1 $2",
        "nowatchlist": "Awan ti banag iti listaan dagiti bambantayam.",
        "watchlistanontext": "Pangngaasim ti $1 tapno makitam dagiti inurnosmo dita bambantayam.",
        "watchnologin": "Saan a nakastrek",
-       "addwatch": "Inayon iti bambantayan",
+       "addwatch": "Inayon iti listaan ti bambantayan",
        "addedwatchtext": "Ti panid iti \"[[:$1]]\" ket nainayonen idiay [[Special:Watchlist|listaan ti bambantayam]].\nDagiti masakbayan a panagsukat iti daytoy a panid ken dagiti mainaig a tungtunganna a panid ket mailistanto idiay.",
        "addedwatchtext-short": "Ti panid ti \"$1\" ket nainayonen iti listaan ti bambantayam.",
-       "removewatch": "Ikkaten dita bambantayan",
+       "removewatch": "Ikkaten manipud ti listaan ti bambantayan",
        "removedwatchtext": "Daytoy a panid  \"[[:$1]]\" ket naikkat idiay [[Special:Watchlist|bambantayam]].",
        "removedwatchtext-short": "Ti panid ti \"$1\" ket naikkaten manipud ti listaan ti bambantayam.",
-       "watch": "bantayan",
+       "watch": "Bantayan",
        "watchthispage": "Bantayan daytoy a panid",
        "unwatch": "Saanen a bantayan",
        "unwatchthispage": "Isardeng a bantayan daytoy a panid",
        "notanarticle": "Saan a naglaon a panid",
-       "notvisiblerev": "Ti panagbalbaliw ti sabali nga agar-aramat ket naikkaten",
-       "watchlist-details": "{{PLURAL:$1|$1 panid|$1 dagiti panid}} a bambantayam, saan a naisina a mairaman dagiti panid ti tungtungan.",
+       "notvisiblerev": "Ti naudi a rebision babaen ti sabali nga agar-aramat ket naikkaten",
+       "watchlist-details": "{{PLURAL:$1|$1 a panid|$1 a pampanid}} iti listaan ti bambantayam, a saan a naisina a mairaman dagiti panid ti tungtungan.",
        "wlheader-enotif": "Napakabaelan ti panangipakaammo ti esurat.",
-       "wlheader-showupdated": "Dagiti panid a nasukatanen manipud ti kinaudi a panagsarungkarmo ket naipakita iti '''napuskol'''",
-       "wlnote2": "Dita baba ket dagiti binalbaliwan {{PLURAL:$1|iti napalabas nga oras|kadagiti napalabas a <strong>$1</strong> nga oras}}, manipud idi $2, $3.",
+       "wlheader-showupdated": "Dagiti panid a nasukatanen manipud ti kinaudi a panagsarungkarmo ket naipakita iti <strong>napuskol</strong>.",
+       "wlnote": "Dita baba ket {{PLURAL:$1|naudi a sinukatan|dagiti naudi a <strong>$1</strong> a sinukatan}} iti napalabas {{PLURAL:$2|nga oras|a <strong>$2</strong> nga or-oras}}, manipud idi $3, $4.",
        "wlshowlast": "Ipakita dagiti naudi a $1 nga or-oras $2 nga al-aldaw $3",
        "watchlist-options": "Dagiti pagpilian ti listaan a bambantayan",
        "watching": "Bambantayan...",
        "unwatching": "Saanen a bantayan...",
-       "watcherrortext": "Adda nagkabiddut idi suksukatam ti kita ti bambantayam \"$1\".",
+       "watcherrortext": "Adda napasamak a biddut bayat a suksukatam dagiti pannakaisaad ti listaan ti bambantayam para iti \"$1\".",
        "enotif_reset": "Markaan amin a pampanid a kas nasarungkaran",
        "enotif_impersonal_salutation": "Agar-aramat ti {{SITENAME}}",
        "enotif_subject_deleted": "Ti {{SITENAME}} a panid ti $1 ket inikkat idin babaen ni {{gender:$2|$2}}",
-       "enotif_subject_created": "Ti {{SITENAME}} a panid ti $1 ket napartuat idin babaen ni {{gender:$2|$2}}",
-       "enotif_subject_moved": "Ti {{SITENAME}} panid ti $1 ket naiyalis idin babaen ni {{gender:$2|$2}}",
-       "enotif_subject_restored": "Ti {{SITENAME}} a panid ti $1 ket naipasubli idin babaen ni {{gender:$2|$2}}",
-       "enotif_subject_changed": "Ti {{SITENAME}} a panid ti $1 ket nasukatan idin babaen ni {{gender:$2|$2}}",
-       "enotif_body_intro_deleted": "Ti {{SITENAME}} a panid ti $1 ket {{GENDER:$2|naikkaten}} idiay $PAGEEDITDATE babaen ni $2, kitaen ti $3.",
-       "enotif_body_intro_created": "Ti {{SITENAME}} a panid ti $1 ket napartuat idin idiay $PAGEEDITDATE babaen ni {{gender:$2|$2}}, kitaen ti $3 para iti agdama panagbaliw.",
-       "enotif_body_intro_moved": "Ti {{SITENAME}} a panid ti $1 ket naiyalis idin idiay $PAGEEDITDATE babaen ni {{gender:$2|$2}}, kitaen ti $3 para iti agdama panagbaliw.",
-       "enotif_body_intro_restored": "Ti {{SITENAME}} a panid ti $1 ket naipasubli idi idiay $PAGEEDITDATE babaen ni {{gender:$2|$2}}, kitaen ti $3 para iti agdama panagbaliw.",
-       "enotif_body_intro_changed": "Ti {{SITENAME}} a panid ti $1 ket nasukatan idin idiay $PAGEEDITDATE babaen ni {{gender:$2|$2}}, kitaen ti $3 para iti agdama panagbaliw.",
+       "enotif_subject_created": "Ti {{SITENAME}} a panid ti $1 ket pinartuat idin babaen ni {{gender:$2|$2}}",
+       "enotif_subject_moved": "Ti {{SITENAME}} panid ti $1 ket inyalis idin babaen ni {{gender:$2|$2}}",
+       "enotif_subject_restored": "Ti {{SITENAME}} a panid ti $1 ket inpulang idin babaen ni {{gender:$2|$2}}",
+       "enotif_subject_changed": "Ti {{SITENAME}} a panid ti $1 ket sinukatan idin babaen ni {{gender:$2|$2}}",
+       "enotif_body_intro_deleted": "Ti {{SITENAME}} a panid ti $1 ket {{GENDER:$2|naikkat}} idi $PAGEEDITDATE babaen ni $2, kitaen ti $3.",
+       "enotif_body_intro_created": "Ti {{SITENAME}} a panid ti $1 ket napartuaten idi $PAGEEDITDATE babaen ni {{gender:$2|$2}}, kitaen ti $3 para iti agdama panagbaliw.",
+       "enotif_body_intro_moved": "Ti {{SITENAME}} a panid ti $1 ket naiyalisen idi $PAGEEDITDATE babaen ni {{gender:$2|$2}}, kitaen ti $3 para iti agdama panagbaliw.",
+       "enotif_body_intro_restored": "Ti {{SITENAME}} a panid ti $1 ket naipulangen idi $PAGEEDITDATE babaen ni {{gender:$2|$2}}, kitaen ti $3 para iti agdama panagbaliw.",
+       "enotif_body_intro_changed": "Ti {{SITENAME}} a panid ti $1 ket nasukatanen idi $PAGEEDITDATE babaen ni {{gender:$2|$2}}, kitaen ti $3 para iti agdama panagbaliw.",
        "enotif_lastvisited": "Kitaen ti $1 para iti am-amin a panagsukat sipud ti naudi nga isasarungkarmo.",
        "enotif_lastdiff": "Kitaen ti $1 tapno mabuya daytoy a panagsukat.",
        "enotif_anon_editor": "di am-ammo nga agar-aramat $1",
-       "enotif_body": "Nadungngo a $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nPakabuklan ti mannurat: $PAGESUMMARY $PAGEMINOREDIT\n\nKontaken ti mannurat:\nsurat: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nAwanton dagiti sabali a pakaammo iti kaso ti adu pay a panagtigtignay malaksid no sarungkaram datoy a panid bayat a nakastrekka. Mabalinmo pay nga iyasentar manen dagiti wagayway ti pakaammo para kadagiti amin a bambantayam a panid idiay listaan ti bambantayam.\n\nTi mannakigayyem a sistema ti panagpaammo ti {{SITENAME}} \n\n--\nTi panagsukat ti kasasaad ti esurat a pagpa-ammom, sarungkaram ti\n{{canonicalurl:{{#special:Preferences}}}}\n\nTi panagsukat kadagiti kasasaad ti bambantayam, sarungkaram ti\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nTi panag-ikkat ti panid kadagiti bambantayam, sarungkaram ti\n$UNWATCHURL\n\nTi makunkunam ken no masapulmo pay ti tulong:\n$HELPPAGE",
+       "enotif_body": "Nadungngo a $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nPakabuklan ti mannurat: $PAGESUMMARY $PAGEMINOREDIT\n\nKontaken ti mannurat:\nsurat: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nAwanton dagiti sabali a pakaammo iti kaso ti adu pay a panagtigtignay malaksid no sarungkaram datoy a panid bayat a nakastrekka. Mabalinmo pay nga isaad manen dagiti wagayway ti pakaammo para kadagiti amin a bambantayam a panid idiay listaan ti bambantayam.\n\nTi mannakigayyem a sistema ti panagpaammo ti {{SITENAME}} \n\n--\nTi panagsukat ti kasasaad ti esurat a pagpa-ammom, sarungkaram ti\n{{canonicalurl:{{#special:Preferences}}}}\n\nTi panagsukat kadagiti kasasaad ti listaan ti bambantayam, sarungkaram ti\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nTi panagikkat ti panid kadagiti listaan ti bambantayam, sarungkaram ti\n$UNWATCHURL\n\nTi makunkunam ken no masapulmo pay ti tulong:\n$HELPPAGE",
        "created": "naaramid",
        "changed": "nasukatan",
        "deletepage": "Ikkaten ti panid",
        "confirm": "Pasingkedan",
        "excontent": "ti linaon idi ket: '$1'",
-       "excontentauthor": "ti linaonna idi ket: \"$1\" (ken ti laeng nakaaramid idi ket ni \"[[Special:Contributions/$2|$2]]\")",
+       "excontentauthor": "ti linaonna idi ket: \"$1\" (ken ti laeng kontributor idi ket ni \"[[Special:Contributions/$2|$2]]\")",
        "exbeforeblank": "ti linaon sakbay idi nablanko ket: \"$1\"",
        "delete-confirm": "Ikkaten ti \"$1\"",
        "delete-legend": "Ikkaten",
-       "historywarning": "'''Ballaag: ''' Ti panid a kayatmo nga ikkaten ket adda pakasaritaanna ti agarup a $1 {{PLURAL:$1|a binaliwan|kadagiti binaliwan}}:",
-       "confirmdeletetext": "Ikkatemon ti maysa a panid agraman am-amin a pakasaritaanna.\nPangngaasim ta pasingkedam a talaga a kayatmo nga aramiden daytoy, a maawatam ti bunga ti panangikkatmo, ken aramidem daytoy kas maiyannugot iti [[{{MediaWiki:Policy-url}}|annuroten]].",
-       "actioncomplete": "Nalpasen a naaramid",
+       "historywarning": "<strong>Ballaag:</strong> Ti panid a kayatmo nga ikkaten ket adda pakasaritaanna ti agarup a $1 {{PLURAL:$1|a rebision|kadagiti rebision}}:",
+       "confirmdeletetext": "Mangrugrugika a mangikkat ti maysa a panid a kakuyogna amin ti pakasaritaanna.\nPangngaasi a pasingkedam a talaga a kayatmo nga aramiden daytoy, a maawatam ti bunga ti panangikkatmo, ken aramidem daytoy kas maiyannugot iti [[{{MediaWiki:Policy-url}}|annuroten]].",
+       "actioncomplete": "Nalpasen ti aramid",
        "actionfailed": "Napaay ti aramid",
-       "deletedtext": "Naikkaten ti \"$1\".\nKitaen ti $2 para iti pannakrehistro dagiti naudi a naikkat.",
+       "deletedtext": "Naikkaten ti \"$1\".\nKitaen ti $2 para iti pannakairehistro dagiti naudi a pangikkat.",
        "dellogpage": "Listaan ti panagikkat",
        "dellogpagetext": "Adda dita baba ti listaan dagiti kaudian a panangikkat.",
        "deletionlog": "listaan ti panagikkat",
-       "reverted": "Naisubli iti immuna a panagbalbaliw",
+       "reverted": "Naisubli iti nasapsapa a rebision",
        "deletecomment": "Rason:",
        "deleteotherreason": "Sabali/maipatinayon a rason:",
        "deletereasonotherlist": "Sabali a rason",
-       "deletereason-dropdown": "* Kadawyan a rasrason ti panagikkat\n** Spam\n** Bandalismo\n** Panaglabsing iti karbengan ti panagipablaak\n** Kiddaw ti mannurat\n** Naputed a baw-ing",
+       "deletereason-dropdown": "* Kadawyan a rasrason ti panagikkat\n** Spam\n** Bandalismo\n** Panaglabsing iti karbengan ti kopia\n** Kiddaw ti mannurat\n** Naputed a baw-ing",
        "delete-edit-reasonlist": "Urnosen dagiti rason ti panagikkat",
        "delete-toobig": "Daytoy a panid ket dakkel ti pakasaritaanna, sumurok a  $1 {{PLURAL:a panagbaliwan|dagiti panagbaliwan}}.\nTi panagikkat ti kastoy a pammpanid ket naparitan tapno mapawilan ti saan nga inkarkaro a pannakadadael ti {{SITENAME}}.",
        "delete-warning-toobig": "Daytoy a panid ket adda ti dakkel unay a pakasaritaan ti panag-urnos, ti kaadu nga $1 {{PLURAL:$1|panagbaliw|dagiti panagbaliw}}.\nTi panagikkat ket madisturbo ti panagpataray ti database ti {{SITNAME}};\nagal-aluadka a mangrugi.",
        "rollback": "Isubli dagiti panag-urnos",
        "rollback_short": "Isubli",
        "rollbacklink": "isubli",
-       "rollbacklinkcount": "agisubli ti $1 {{PLURAL:$1|nga inurnos|nga inururnos}}",
-       "rollbacklinkcount-morethan": "agisubli ti ad-adu ngem $1 {{PLURAL:$1|nga inurnos|nga inururnos}}",
+       "rollbacklinkcount": "agisubli ti $1 {{PLURAL:$1|nga inurnos|nga inur-urnos}}",
+       "rollbacklinkcount-morethan": "agisubli ti ad-adu ngem $1 {{PLURAL:$1|nga inurnos|nga inur-urnos}}",
        "rollbackfailed": "Napaay ti panangisubli",
-       "cantrollback": "Saan a maisubli ti panagurnos;\nti naudi a nakaaramid ket iti laeng nagsurat daytoy a panid..",
+       "cantrollback": "Saan a maisubli ti panagurnos;\nti naudi a nakaaramid ket iti laeng nagsurat iti daytoy a panid.",
        "alreadyrolled": "Saan a maipasubli ti kinaudi a panagurnos iti [[:$1]] babaen ni [[User:$2|$2]] ([[User talk:$2|tungtungan]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]);\nadda sabali a naurnos wenno nagipasubli ti panid.\n\nTi kinaudi a panagurnos ti daytoy a panid ket babaen ni [[User:$3|$3]] ([[User talk:$3|tungtungan]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
-       "editcomment": "Ti panagurnos a pakabuklan idi ket: \"''$1''\".",
-       "revertpage": "Insubli ti panagurnos babaen ni [[Special:Contributions/$2|$2]] ([[User talk:$2|tungtungan]]), naisubli ti kinaudi a panagbaliw babaen ni [[User:$1|$1]]",
-       "revertpage-nouser": "Naisubli dagiti inurnos babaen ti nailemmeng nga agar-aramat iti kinaudi a panagbalbaliw babaen ni {{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "Naibabawi dagiti panag-urnos babaen ni $1;\nnaisubli manen ti naudi a panagbaliw babaen ni $2.",
-       "sessionfailure-title": "Napaay ti gimong",
-       "sessionfailure": "Adda parikut ti gimong ti panagserrekmo;\ndaytoy nga aramid ket naibabawi a kas pagpawilan ti panaghijack ti gimong.\nAgsubli ka ti naggapuam a panid, ikargam ti panid ken padasem manen.",
+       "editcomment": "Ti pakabuklan ti panag-urnos idi ket: \"''$1''\".",
+       "revertpage": "Insubli ti panag-urnos babaen ni [[Special:Contributions/$2|$2]] ([[User talk:$2|tungtungan]]), naisubli ti kinaudi a rebision babaen ni [[User:$1|$1]]",
+       "revertpage-nouser": "Naisubli dagiti inurnos babaen ti nailemmeng nga agar-aramat iti kinaudi a rebision babaen ni {{GENDER:$1|[[User:$1|$1]]}}",
+       "rollback-success": "Naibabawi dagiti panag-urnos babaen ni $1;\nnaisubli manen ti naudi a rebision babaen ni $2.",
+       "sessionfailure-title": "Napaay ti sesion",
+       "sessionfailure": "Adda parikut ti sesion ti panagserrekmo;\ndaytoy nga aramid ket naibabawi a kas pagpawilan ti panaghijack ti sesion.\nAgsublika iti naggapuam a panid, ikargam manen ti panid ken padasen manen.",
        "protectlogpage": "Listaan ti panagsalaknib",
        "protectlogtext": "Dita baba ket adda listaan dagiti sinukatan a salaknib ti panid.\nKitaen ti [[Special:ProtectedPages|listaan kadagiti nasalakniban a panid]] ti listaan kadagiti agdama a panagpataray a panagsalaknib ti panid.",
        "protectedarticle": "nasalakniban ti \"[[$1]]\"",
        "modifiedarticleprotection": "nasukatan ti agpang ti salaknib para iti \"[[$1]]\"",
-       "unprotectedarticle": "naikkat ti salaknib ti \"[[$1]]\"",
-       "movedarticleprotection": "iyalis ti kasasaad ti salaknib manipud iti \"[[$2]]\" idiay \"[[$1]]\"",
+       "unprotectedarticle": "naikkat ti salaknib manipud ti \"[[$1]]\"",
+       "movedarticleprotection": "iyalis ti kasasaad ti salaknib manipud ti \"[[$2]]\" iti \"[[$1]]\"",
        "protect-title": "Sukatan ti agpang ti salaknib para iti \"$1\"",
        "protect-title-notallowed": "Kitaen ti agpang ti salaknib ti \"$1\"",
        "prot_1movedto2": "[[$1]] naiyalis iti [[$2]]",
        "protect-badnamespace-title": "Saan a mabalin a salakniban a nagan ti espasio",
-       "protect-badnamespace-text": "Dagiti panid ditoy a nagan ti espasio ket saan a mabalin a masalakniban.",
-       "protect-norestrictiontypes-text": "Daytoy a panid ket saan a mabalin a masalakniban gaputa awan dagiti maiparit a kita a magun-od.",
+       "protect-badnamespace-text": "Dagiti panid iti daytoy a nagan ti espasio ket saan a mabalin a masalakniban.",
+       "protect-norestrictiontypes-text": "Daytoy a panid ket saan a mabalin a masalakniban gapu ta awan dagiti magun-od a kita ti panangigawid.",
        "protect-norestrictiontypes-title": "Di masalakniban a panid",
        "protect-legend": "Pasingkedan ti panagsalaknib",
        "protectcomment": "Rason:",
        "protect_expiry_invalid": "Imbalido ti oras a panagpaso.",
        "protect_expiry_old": "Napalabasen ti oras ti panagpaso.",
        "protect-unchain-permissions": "Lukatan dagiti pagpilian ti salaknib",
-       "protect-text": "Mabalinmo a kitaen ken sukatan ti agpang ti salaknib para iti panid ti '''$1'''.",
-       "protect-locked-blocked": "Saanmo a mabalin a sukatan dagiti kita ti salaknib no naserraanka.\nAdda ditoy kadagiti agdama a kasasaad ti panid '''$1''':",
-       "protect-locked-dblock": "Ti kita ti salaknib ket saan a masukatan gapu ti agdama a kandado ti database.\nAdda ditoy kadagiti agdama a kasasaad ti panid '''$1''':",
-       "protect-locked-access": "Awan ti pammalubos ti pakabilangam a mangsukat kadagiti lessaad ti salaknib ti panid.\nDagitoy dagiti agdama a kasasaad ti panid a '''$1''':",
-       "protect-cascadeon": "Daytoy a panid ket agdama a nasalakniban gapu ta nairaman kadagiti sumaganad a {{PLURAL:$1|panid, nga addaan|pampanid, nga addaan}} iti sipapakat a salaknib a sariap.\nDagiti panagbaliw iti agpang ti salaknib iti daytoy a panid ket saan a mabanagan ti salaknib a sariap.",
+       "protect-text": "Mabalinmo a kitaen ken sukatan ti agpang ti salaknib para iti panid ti <strong>$1</strong>.",
+       "protect-locked-blocked": "Saanmo a mabalin a sukatan dagiti kita ti salaknib no naserraanka.\nAdda ditoy kadagiti agdama a kasasaad ti panid ti <strong>$1</strong>:",
+       "protect-locked-dblock": "Ti kita ti salaknib ket saan a masukatan gapu ti agdama a kandado ti database.\nAdda ditoy kadagiti agdama a kasasaad ti panid ti <strong>$1</strong>:",
+       "protect-locked-access": "Ti pakabilangam ket awan pammalubosna a mangsukat kadagiti agpang ti salaknib ti panid.\nDagitoy ti agdama a pannakaisaad para iti panid ti <strong>$1</strong>:",
+       "protect-cascadeon": "Daytoy a panid ket agdama a nasalakniban gapu ta nairaman kadagiti sumaganad a {{PLURAL:$1|panid, nga addaan|pampanid, nga addaan}} iti nalukatan a salaknib ti sariap.\nDagiti panagbaliw iti agpang ti salaknib iti daytoy a panid ket saan a mabanagan ti salaknib ti sariap.",
        "protect-default": "Palubosan amin nga agar-aramat",
        "protect-fallback": "Palubosan laeng dagiti agar-aramat nga adda iti \"$1\" a pammalubos",
        "protect-level-autoconfirmed": "Palubosan laeng dagiti automatiko a napasingkedan nga agar-aramat",
        "protect-existing-expiry": "Ti adda a panagpaso ti oras: $3, $2",
        "protect-otherreason": "Sabali/maipatinayon a rason:",
        "protect-otherreason-op": "Sabali a rason",
-       "protect-dropdown": "*Kadawyan a rasrason ti panagsalaknib\n** Adu unay a bandalismo\n** Adu unay a panagspam\n** Saan a produktibo ti kasinnungat a panag-urnos\n** Adu unay nga agbuybuya ti panid",
+       "protect-dropdown": "*Kadawyan a rasrason ti panagsalaknib\n** Adu unay a bandalismo\n** Adu unay a panagspam\n** Saan a produktibo ti agsinnungat a panag-urnos\n** Adu unay nga agbuybuya iti panid",
        "protect-edit-reasonlist": "Urnosen dagiti rason ti salaknib",
        "protect-expiry-options": "1 nga oras:1 hour,1 nga aldaw:1 day,1 a lawas:1 week,2 a lawas:2 weeks,1 a bulan:1 month,3 a bulan:3 months,6 a bulan:6 months,1 a tawen:1 year,awan inggana:infinite",
        "restriction-type": "Pammalubos:",
-       "restriction-level": "Agpang ti pannakaiparit:",
-       "minimum-size": "Kinababa a kadakkel:",
-       "maximum-size": "Kinangato a kadakkel:",
+       "restriction-level": "Agpang ti panangigawid:",
+       "minimum-size": "Kababaan a kadakkel:",
+       "maximum-size": "Kangatuan a kadakkel:",
        "pagesize": "(dagiti byte)",
        "restriction-edit": "Urnosen",
        "restriction-move": "Iyalis",
-       "restriction-create": "Aramiden",
-       "restriction-upload": "Pang-ipan",
+       "restriction-create": "Agpartuat",
+       "restriction-upload": "Agikarga",
        "restriction-level-sysop": "napno a nasalakniban",
        "restriction-level-autoconfirmed": "nasalakniban bassit",
        "restriction-level-all": "aniaman nga agpang",
        "undelete": "Kitaen dagiti naikkat a panid",
        "undeletepage": "Kitaen ken isubli dagiti naikkat a panid",
-       "undeletepagetitle": "'''Ti sumaganad ket buklen dagiti naikkat a panagbaliw ni [[:$1|$1]]'''.",
+       "undeletepagetitle": "<strong>Ti sumaganad ket buklen dagiti naikkat a rebision ti [[:$1|$1]]</strong>.",
        "viewdeletedpage": "Kitaen dagiti naikkat a panid",
        "undeletepagetext": "Ti sumaganad a {{PLURAL:$1|panid ket naikkaten ngem|$1 pampanid ket naikkaten ngem}} adda pay naarkibo ken mabalin pay a maipasubli .\nTi arkibo ket mabalin a sagpaminsan a madalusan.",
-       "undelete-fieldset-title": "Ipasubli dagiti binaliwan",
-       "undeleteextrahelp": "Tapno maipasubli ti intero a pakasaritaan ti panid, ibatim a saan nga nakur-itan dagita kahon ken ipindut ti '''''{{int:undeletebtn}}'''''.\nTi agaramid ti napilian a panagisubli, ikur-it dagita napilim kadagiti kahon ti kayatmo nga ipasubli, ken ipindut ti '''''{{int:undeletebtn}}'''''.",
-       "undeleterevisions": "$1 {{PLURAL:$1|a binalbaliwan|kadagiti binalbaliwan}} ti nailebben",
-       "undeletehistory": "No ipasublim daytoy a panid, amin dagiti pinagbaliwan ket maipasubli idiay pakasaritaan.\nKet no adda baro a panid a kanagnagan na a naaramid ti napalabas a pinagikkat, dagiti naipasubli a pinagbaliwan ket agparang idiay napalabas a pakasaritaan.",
-       "undeleterevdel": "Ti panagikkat ket saan a maaramid no agbanag iti rabaw ti panid, wenno ti pinagbaliwan ti papeles ket maikkatan ti bassit.\nIti kastoy a kaso, masapul nga ikkatem ti kur-it wenno ikkatem ti lemmeng dagiti kabarbaro a naikkat a binalbaliwan.",
-       "undeletehistorynoadmin": "Daytoy a panid ket naikkaten.\nTi rason ti panagikkat ket naipakita ti pakabuklan dita baba, ken dagita dsalaysay ti agar-aramat a nagpabaliw ditoy a panid sakbay a naikkat.\nTi husto a testo ti nabaliwan a panagbaliw ket adda kadagiti administrador laeng.",
-       "undelete-revision": "Naikkat ti binaliwan a $1 (manipud idi $4, idi $5) babaen ni $3:",
-       "undeleterevision-missing": "Imbalido wenno napukaw a panagbaliw.\nAddaanka ngata ti madi a silpo, wenno ti panagbaliw ket naipasubli wenno naikkat manipud idiay nailebbeng.",
-       "undelete-nodiff": "Awan ti nasarakan kadagiti dati a nabalbaliwan.",
+       "undelete-fieldset-title": "Ipasubli dagiti rebision",
+       "undeleteextrahelp": "Tapno maipasubli ti intero a pakasaritaan ti panid, ibatim a saan nga nakur-itan dagita kahon ken pinduten ti '''''{{int:undeletebtn}}'''''.\nTi agaramid ti napilian a panagisubli, ikur-it dagita napilim kadagiti kahon ti kayatmo nga ipasubli, ken pinduten ti '''''{{int:undeletebtn}}'''''.",
+       "undeleterevisions": "$1 {{PLURAL:$1|a rebision|kadagiti rebision}} ti naarkibo",
+       "undeletehistory": "No ipasublim daytoy a panid, amin dagiti rebision ket maipasubli iti pakasaritaan.\nKet no adda baro a panid a kanagnaganna a naaramid ti napalabas a panagikkat, dagiti naipasubli a rebision ket agparang iti napalabas a pakasaritaan.",
+       "undeleterevdel": "Ti panagikkat ket saan a maaramid no agbanag iti rabaw ti panid, wenno ti rebision ti papeles ket maikkatan ti bassit.\nIti kastoy a kaso, masapul nga ikkatem ti kur-it wenno ikkatem ti lemmeng dagiti kabarbaro a naikkat a rebision.",
+       "undeletehistorynoadmin": "Daytoy a panid ket naikkaten.\nTi rason ti panagikkat ket naipakita iti pakabuklan dita baba, ken dagita a salaysay ti agar-aramat a nagurnos iti daytoy a panid sakbay a naikkat.\nTi husto a testo dagitoy a naikat a rebision ket magun-od laeng dagiti administrador.",
+       "undelete-revision": "Naikkat ti rebision ti $1 (manipud idi $4, $5) babaen ni $3:",
+       "undeleterevision-missing": "Imbalido wenno napukaw a rebision.\nAddaanka ngata ti madi a silpo, wenno ti rebision ket mabalin a naipasubli wenno naikkat manipud ti arkibo.",
+       "undelete-nodiff": "Awan ti nasarakan kadagiti dati a rebision.",
        "undeletebtn": "Isubli",
        "undeletelink": "kitaen/isubli",
        "undeleteviewlink": "kitaen",
        "undeleteinvert": "Baliktaden ti napili",
        "undeletecomment": "Rason:",
-       "undeletedrevisions": "{{PLURAL:$1|1 a  binaliwan|dagiti $1 a binaliwan}} ti naisubli",
-       "undeletedrevisions-files": "{{PLURAL:$1|1 a binaliwan|dagiti $1 a binaliwan}} ken {{PLURAL:$2|1 a papeles|dagiti $2 a papeles}} ti naisubli",
+       "undeletedrevisions": "{{PLURAL:$1|1 a rebision|dagiti $1 a rebision}} ti naisubli",
+       "undeletedrevisions-files": "{{PLURAL:$1|1 a rebision|dagiti $1 a rebision}} ken {{PLURAL:$2|1 a papeles|dagiti $2 a papeles}} ti naisubli",
        "undeletedfiles": "{{PLURAL:$1|1 a papeles|dagiti $1 a papeles}} ti naisubli",
-       "cannotundelete": "Napaay ti panagikkat:\n$1",
-       "undeletedpage": "'''Naisublin ti $1'''\n\nBinsiren ti [[Special:Log/delete|listaan ti naik-ikkat]] para iti listaan dagiti naudi a naik-ikkat ken naisubsubli.",
-       "undelete-header": "Kitaen [[Special:Log/delete|ti listaan ti pinagikkat]] kadagiti kinaudian a naikkat a panid.",
+       "cannotundelete": "Napaay ti panagisubli iti panagikkat:\n$1",
+       "undeletedpage": "<strong>Naisublin ti $1</strong>\n\nBinsiren ti [[Special:Log/delete|listaan ti panagikkat]] para iti rehistro dagiti kaudian panagikkat ken naisubsubli.",
+       "undelete-header": "Kitaen [[Special:Log/delete|ti listaan ti panagikkat]] kadagiti kaudian a naikkat a panid.",
        "undelete-search-title": "Biruken dagiti naikkat a panid",
        "undelete-search-box": "Biruken dagiti naikkat a panid",
        "undelete-search-prefix": "Ipakita dagiti panid a mangrugi iti:",
        "undelete-search-submit": "Biruken",
-       "undelete-no-results": "Awan dagiti kapada ti panid a nasarakan idiay lebben ti panagikkat.",
-       "undelete-filename-mismatch": "Saan maisubli ti panagikkat ti pinagbaliwan ti papeles nga adda oras ket petsana a $1: Saan nga agpada ti nagan ti papeles.",
-       "undelete-bad-store-key": "Saan a maisubli ti pinagikkat ti pinagbaliwan ti papeles nga adda oras ket petsana a $1: Ti papeles ket napukaw sakbay a naikkat.",
-       "undelete-cleanup-error": "Biddut ti panagikkat ti saan a naus-usar a naidulin a papeles \"$1\".",
-       "undelete-missing-filearchive": "Saan a naipabalin ti panagisubli ti ID ti papeles a nailebben $1 ngamin ket awan idiay database.\nMabalin daytoy a naikkaten.",
-       "undelete-error": "Ballaag ti panagisubli ti panagikkat ti panid",
-       "undelete-error-short": "Biddut ti pannakaikkat ti papeles: $1",
-       "undelete-error-long": "Adda nasarakan a biddut idi panagisubli ti panagikkat ti papeles:\n\n$1",
-       "undelete-show-file-confirm": "Sigurado a kayatmo ti mangkita ti naikkat a panagbaliw ti papeles \"<nowiki>$1</nowiki>\" manipud idi $2 idi $3?",
+       "undelete-no-results": "Awan dagiti kapada ti panid a nasarakan idiay arkibo ti panagikkat.",
+       "undelete-filename-mismatch": "Saan maisubli ti panagikkat ti rebision ti papeles nga adda oras ket petsana a $1: Saan nga agpada ti nagan ti papeles.",
+       "undelete-bad-store-key": "Saan a maisubli ti pinagikkat ti rebision ti papeles nga adda oras ket petsana a $1: Ti papeles ket napukaw sakbay a naikkat.",
+       "undelete-cleanup-error": "Biddut ti panagikkat ti saan a naus-usar a naarkibo a papeles ti \"$1\".",
+       "undelete-missing-filearchive": "Saan a naipasubli ti ID ti arkibo ti papeles ti $1 ngamin ket awan idiay database.\nMabalin naikkaten daytoy.",
+       "undelete-error": "Biddut ti panagisubli ti panagikkat ti panid",
+       "undelete-error-short": "Biddut ti panagisubli ti pannakaikkat ti papeles: $1",
+       "undelete-error-long": "Adda dagiti nasarakan a biddut bayat ti panagisubli ti panagikkat ti papeles:\n\n$1",
+       "undelete-show-file-confirm": "Sigurado a kayatmo ti mangkita ti naikkat a rebision ti papeles \"<nowiki>$1</nowiki>\" manipud idi $2, $3?",
        "undelete-show-file-submit": "Wen",
        "namespace": "Nagan ti espasio:",
        "invert": "Baliktaden ti napili",
        "tooltip-invert": "Ikur-it daytoy a kahon ti panagilemmeng kadagiti sinukatan a panid iti uneg ti napili a nagan ti espasio (ken ti nairaman a nagan ti espasio no naikur-it)",
-       "namespace_association": "Nairaman a nagan ti espasio",
-       "tooltip-namespace_association": "Ikur-it daytoy a kahon ti panagiraman ti kapatangan wenno suheto ti nagan ti espasio a nairaman kadagiti napili a nagan ti espasio.",
+       "namespace_association": "Mainaig a nagan ti espasio",
+       "tooltip-namespace_association": "Ikur-it daytoy a kahon ti panagiraman ti tungtungan wenno suheto ti nagan ti espasio a nairaman kadagiti napili a nagan ti espasio",
        "blanknamespace": "(Umuna)",
-       "contributions": "Naar-aramid ti {{GENDER:$1|Agar-aramat}}",
-       "contributions-title": "Inar-aramid ti agar-aramat para kenni $1",
-       "mycontris": "Naar-aramid",
+       "contributions": "Dagiti kontribusion ti {{GENDER:$1|agar-aramat}}",
+       "contributions-title": "Kontribusion ti agar-aramat para kenni $1",
+       "mycontris": "Inar-aramid",
        "contribsub2": "Para kenni {{GENDER:$3|$1}} ($2)",
-       "contributions-userdoesnotexist": "Ti pakabilangan ti agar-aramat \"$1\" ket saan a nakarehistro.",
-       "nocontribs": "Awan ti nasarakan a nasukatan a kapada daytoy a kita.",
+       "contributions-userdoesnotexist": "Ti pakabilangan ti agar-aramat ni \"$1\" ket saan a nakarehistro.",
+       "nocontribs": "Awan ti nasarakan a nasukatan a kapada dagitoy a kriteria.",
        "uctop": "(agdama)",
-       "month": "Manipud iti bulan ti (ken nasapsapa pay):",
-       "year": "Manipud iti tawen (ken nasapsapa pay):",
-       "sp-contributions-newbies": "Iparang dagiti inar-aramid dagiti kabarbaro a pakabilangan laeng",
+       "month": "Manipud ti bulan (ken nasapsapa):",
+       "year": "Manipud ti tawen (ken nasapsapa):",
+       "sp-contributions-newbies": "Iparang dagiti kontribusion dagiti kabarbaro a pakabilangan laeng",
        "sp-contributions-newbies-sub": "Para kadagiti kabarbaro a pakabilangan",
-       "sp-contributions-newbies-title": "Dagiti inar-aramid ti agar-aramat iti baro a pakabilangan",
-       "sp-contributions-blocklog": "listaan ti naserraan",
+       "sp-contributions-newbies-title": "Dagiti kontribusion para kadagiti baro a pakabilangan",
+       "sp-contributions-blocklog": "listaan ti serra",
        "sp-contributions-suppresslog": "pasardengen dagiti kontribusion ti agar-aramat",
-       "sp-contributions-deleted": "dagiti naikkat nga inar-aramid ti agar-aramat",
-       "sp-contributions-uploads": "dagiti pang-ipan",
-       "sp-contributions-logs": "listaan",
+       "sp-contributions-deleted": "dagiti naikkat a kontribusion ti agar-aramat",
+       "sp-contributions-uploads": "dagiti naikarga",
+       "sp-contributions-logs": "dagiti listaan",
        "sp-contributions-talk": "tungtungan",
        "sp-contributions-userrights": "panagtaripato kadagiti karbengan ti agar-aramat",
-       "sp-contributions-blocked-notice": "Naserraan tatta daytoy nga agar-aramat.\nTi naudi a listaan ti pannakaserra ket adda dita baba tapno mausar a reperensia:",
-       "sp-contributions-blocked-notice-anon": "Daytoy nga IP a pagtaengan ket naserraan.\nTi naudi a listaan ti pannakaserra ket adda dita baba tapno mausar a reperensia:",
-       "sp-contributions-search": "Agsapul para kadagiti naar-aramid",
+       "sp-contributions-blocked-notice": "Adama a naserraan daytoy nga agar-aramat.\nTi naudi a naikabil iti listaan ti pannakaserra ket naited dita baba para iti reperensia:",
+       "sp-contributions-blocked-notice-anon": "Daytoy nga IP a pagtaengan ket agdama a naserraan.\nTi naudi a naikabil iti listaan ti pannakaserra ket adda dita baba para iti reperensia:",
+       "sp-contributions-search": "Agbiruk para kadagiti kontribusion",
        "sp-contributions-username": "IP a pagtaengan wenno nagan ti agar-aramat:",
-       "sp-contributions-toponly": "Ipakita laeng dagiti inurnos a kinaudian a panagbaliw",
+       "sp-contributions-toponly": "Ipakita laeng dagiti inurnos dagiti kaudian a rebision",
        "sp-contributions-newonly": "Ipakita laeng dagiti inurnos a pannakapartuat ti pampanid",
        "sp-contributions-submit": "Biruken",
        "whatlinkshere": "Dagiti nakasilpo ditoy",
        "whatlinkshere-title": "Pampanid a nakasilpo iti \"$1\"",
        "whatlinkshere-page": "Panid:",
-       "linkshere": "Dagiti sumaganad a panid ket nakasilpo iti '''[[:$1]]''':",
-       "nolinkshere": "Awan ti pampanid a nakasilpo iti '''[[:$1]]'''.",
-       "nolinkshere-ns": "Awan ti pampanid a nakasilpo idiay '''[[:$1]]''' iti napili a nagan ti espasio.",
+       "linkshere": "Dagiti sumaganad a panid ket nakasilpo iti <strong>[[:$1]]</strong>:",
+       "nolinkshere": "Awan ti pampanid a nakasilpo iti <strong>[[:$1]]</strong>.",
+       "nolinkshere-ns": "Awan ti pampanid a nakasilpo iti <strong>[[:$1]]</strong> iti napili a nagan ti espasio.",
        "isredirect": "baw-ing a panid",
        "istemplate": "mailak-am",
        "isimage": "silpo ti papeles",
        "whatlinkshere-next": "{{PLURAL:$1|sumaruno|sumaruno a $1}}",
        "whatlinkshere-links": "← silsilpo",
        "whatlinkshere-hideredirs": "$1 dagiti baw-ing",
-       "whatlinkshere-hidetrans": "$1 dagiti mailaklak-am",
+       "whatlinkshere-hidetrans": "$1 dagiti mailak-am",
        "whatlinkshere-hidelinks": "$1 dagiti silpo",
-       "whatlinkshere-hideimages": "$1 a silsilpo ti papeles",
+       "whatlinkshere-hideimages": "$1 dagiti silpo ti papeles",
        "whatlinkshere-filters": "Dagiti sagat",
        "autoblockid": "Auto a panagserra #$1",
        "block": "Seraan ti agar-aramat",
        "unblock": "Ikkaten ti serra ti agar-aramat",
        "blockip": "Serraan ti agar-aramat",
        "blockip-legend": "Serraan ti agar-aramat",
-       "blockiptext": "Usaren ti kinabuklan dita baba tapno maserraan ti panagsurat manipud iti naisangayan nga IP a pagtaengan wenno nagan ti agar-aramat.\nUsaren laeng daytoy tapno pawilan ti bandalismo, ken panagtunos iti [[{{MediaWiki:Policy-url}}|annuroten]].\nIkkan ti naisangayan a rason dita baba (kas pagarigan, dakamaten ti maysa a panid a na-bandalismo) .",
+       "blockiptext": "Usaren ti porma dita baba tapno maserraan ti panagsurat manipud iti naisangayan nga IP a pagtaengan wenno nagan ti agar-aramat.\nUsaren laeng daytoy tapno pawilan ti bandalismo, ken panagtunos iti [[{{MediaWiki:Policy-url}}|annuroten]].\nIkkan ti naisangayan a rason dita baba (kas pagarigan, dakamaten ti maysa a panid a na-bandalismo) .",
        "ipaddressorusername": "IP a pagtaengan wenno nagan ti agar-aramat:",
        "ipbexpiry": "Agpaso:",
        "ipbreason": "Rason:",
-       "ipbreason-dropdown": "*Dagiti kadawyan a rason ti panagserra\n** Agikabil kadagiti  madi a pakaammo\n** Agikkat kadagiti linaon ti pampanid\n** Agikabil ti spam a silpo iti ruar\n** Agikabil ti minamaag/saan a maawatan a pampanid\n** Nabutbuteng a panagkukua /agriribok\n** Agab-abuso kadagiti sabsabali a pakabilangan\n** Saan a maawat a nagan ti agar-aramat",
-       "ipb-hardblock": "Iparit kadagiti nakastrek nga agar-aramat manipud ti panagurnos manipud ti naggapo ditoy nga IP a pagtaengan",
+       "ipbreason-dropdown": "*Dagiti kadawyan a rason ti panagserra\n** Agikabil kadagiti  madi a pakaammo\n** Agikkat kadagiti linaon ti pampanid\n** Agikabil ti spam a silpo iti ruar\n** Agikabil ti minamaag/saan a maawatan a pampanid\n** Mangbutbuteng a panagkukua /mangriribok\n** Agab-abuso kadagiti nadumaduma a pakabilangan\n** Saan a maawat a nagan ti agar-aramat",
+       "ipb-hardblock": "Iparit dagiti nakastrek nga agar-aramat manipud ti panagurnos manipud ti daytoy nga IP a pagtaengan",
        "ipbcreateaccount": "Pawilan ti panagpartuat iti pakabilangan",
        "ipbemailban": "Pawilan ti agar-aramat nga agipatulod ti esurat",
-       "ipbenableautoblock": "Automatiko ti serra ti naudi nga IP a pagtaengan nga inusar daytoy nga agar-aramat, ken dagiti sumaruno nga IP a pagtaengan a padasenda nga agpabaliw",
+       "ipbenableautoblock": "Automatiko a mangserra ti naudi nga IP a pagtaengan nga inusar daytoy nga agar-aramat, ken dagiti sumaruno nga IP a pagtaengan nga ayan ti pangipadasanda nga agurnos",
        "ipbsubmit": "Serraan daytoy nga agar-aramat",
        "ipbother": "Sabali nga oras:",
        "ipboptions": "2 nga oras:2 hours,1 nga aldaw:1 day,3 nga aldaw:3 days,1 a lawas:1 week,2 a lawas:2 weeks,1 a bulan:1 month,3 a bulan:3 months,6 a bulan:6 months,1 a tawen:1 year,awan inggana:infinite",
        "ipbhidename": "Ilemmeng ti nagan ti agar-aramat kadagiti listaan ken inurnos",
        "ipbwatchuser": "Bantayan ti panid ti agar-ramat ken panid ti tungtungan daytoy nga agar-aramat",
-       "ipb-disableusertalk": "Pawilan daytoy nga agar-aramat nga agurnos kadagiti bukodda a tungtungan a panid no naserraan",
-       "ipb-change-block": "Serraan manen ti agar-aramat kadagitoy a disso",
+       "ipb-disableusertalk": "Pawilan daytoy nga agar-aramat nga agurnos kadagiti bukodda a tungtungan a panid bayat a naserraan",
+       "ipb-change-block": "Serraan manen ti agar-aramat kadagitoy a pannakaisaad",
        "ipb-confirm": "Pasingkedan ti serra",
        "badipaddress": "Imbalido nga IP a pagtaengan",
        "blockipsuccesssub": "Balligi ti panangserra",
-       "blockipsuccesstext": "[[Special:Contributions/$1|$1]] ket naserraanen.<br />\nKitaen ti [[Special:BlockList|listaan ti lapden nga IP ]] tapno marepaso dagiti serra.",
+       "blockipsuccesstext": "Ni [[Special:Contributions/$1|$1]] ket naserraanen.<br />\nKitaen ti [[Special:BlockList|listaan ti serra]] tapno marepaso dagiti serra.",
        "ipb-blockingself": "Mangrugrugika nga agserra kenka! Sigurado a kayatmo nga aramiden daytoy?",
-       "ipb-confirmhideuser": "Mangrugrugika ti mangserra ti agar-aramat nga adda ti napabalinna nga \"ilemmeng ti agar-aramat\". Iddeppenna ti nagan daytoy nga agar-aramat kadagiti amin a listaan ken dagiti naikabkabil ti listaan. Siguradoka a kasta ti kayatmo?",
-       "ipb-confirmaction": "No segurado a kayatmo nga aramiden daytoy, pangngaasi a kitaen ti \"{{int:ipb-confirm}}\" a pagikabilan dita baba.",
+       "ipb-confirmhideuser": "Mangrugrugika ti mangserra iti agar-aramat a napakabaelan iti \"ilemmeng ti agar-aramat\". Iddeppenna ti nagan daytoy nga agar-aramat kadagiti amin a listaan ken dagiti naikabkabil ti listaan. Siguradoka a kasta ti kayatmo?",
+       "ipb-confirmaction": "No sigurado a kayatmo nga aramiden daytoy, pangngaasi a kitaen ti \"{{int:ipb-confirm}}\" a pagikabilan dita baba.",
        "ipb-edit-dropdown": "Urnosen dagiti rason ti panagserra",
        "ipb-unblock-addr": "Lukatan ti serra ni $1",
        "ipb-unblock": "Lukatan ti serra ti nagan ti agar-aramat wenno IP a pagtaengan",
        "ipb-blocklist": "Kitaen dagiti adda a serra",
-       "ipb-blocklist-contribs": "Dagiti inaramid ni $1",
+       "ipb-blocklist-contribs": "Dagiti kontribusion para kenni $1",
        "unblockip": "Lukatan ti serra ti agar-aramat",
-       "unblockiptext": "Usaren ti porma dita baba ti panangisubli ti panagserrek nga agsurat ti napalabas a naserran nga IP a pagtaengan wenno nagan ti agar-aramat.",
+       "unblockiptext": "Usaren ti porma dita baba tapno maisubli ti panagserrek ti panagsurat ti dati a naserran nga IP a pagtaengan wenno nagan ti agar-aramat.",
        "ipusubmit": "Ikkaten daytoy a serra",
        "unblocked": "Naikkat ti pannakaserra ni [[User:$1|$1]].",
-       "unblocked-range": "Naikkat ti serra ti $1.",
+       "unblocked-range": "Naikkaten ti serra ti $1.",
        "unblocked-id": "Naikkaten ti serra ti $1.",
        "blocklist": "Dagiti naserraan nga agar-aramat",
        "ipblocklist": "Dagiti naserraan nga agar-aramat",
        "blocklist-userblocks": "Ilemmeng dagiti serra ti pakabilangan",
        "blocklist-tempblocks": "Ilemmeng dagiti temporario a serra",
        "blocklist-addressblocks": "Ilemmeng ti maysa a serra dagiti IP",
-       "blocklist-rangeblocks": "Ilemmeng dagiti nasakup a serra",
+       "blocklist-rangeblocks": "Ilemmeng dagiti nasakop a serra",
        "blocklist-timestamp": "Petsa ken oras",
        "blocklist-target": "Puntaan",
        "blocklist-expiry": "Agpaso",
        "blocklist-by": "Ti nagserra nga admin",
-       "blocklist-params": "Parametro ti serra",
+       "blocklist-params": "Dagiti parametro ti serra",
        "blocklist-reason": "Rason",
        "ipblocklist-submit": "Biruken",
        "ipblocklist-localblock": "Lokal a serra",
        "ipblocklist-otherblocks": "Sabali {{PLURAL:$1|a serra|kadagiti serra}}",
        "infiniteblock": "inggana't inggana",
-       "expiringblock": "agpaso intono $1 ti oras nga $2",
-       "anononlyblock": "di am-ammo laeng",
-       "noautoblockblock": "nabaldado ti auto a serra",
+       "expiringblock": "agpaso intono $1, $2",
+       "anononlyblock": "di ammo laeng",
+       "noautoblockblock": "nabaldado ti automatiko a serra",
        "createaccountblock": "naserraan ti pannakapartuat ti pakabilangan",
-       "emailblock": "naserraan ti esurat",
+       "emailblock": "nabaldado ti esurat",
        "blocklist-nousertalk": "saan a mabalin nga agurnos ti bukod a tungtungan a panid",
-       "ipblocklist-empty": "Awan nagyan ti listaan ti serra.",
-       "ipblocklist-no-results": "Ti kiniddaw nga IP a pagtaengan wenno nagan ti agar-aramat ket saan a naserraan",
+       "ipblocklist-empty": "Awan linaon ti listaan ti serra.",
+       "ipblocklist-no-results": "Ti kiniddaw nga IP a pagtaengan wenno nagan ti agar-aramat ket saan a naserraan.",
        "blocklink": "serraan",
-       "unblocklink": "saanen a naserraan",
-       "change-blocklink": "baliwan  ti serra",
+       "unblocklink": "ikkaten ti serra",
+       "change-blocklink": "baliwan ti serra",
        "contribslink": "aramid",
        "emaillink": "ipatulod ti esurat",
        "autoblocker": "Automatiko a naserraan ngamin ket ti IP a pagtaengam ket naudi nga inusar babaen ni \"[[User:$1|$1]]\".\nTi inted a rason para iti serra ni $1 ket: \"$2\"",
-       "blocklogpage": "Listaan ti naserraan",
-       "blocklog-showlog": "Daytoy nga agar-aramat ket dati a naserraan.\nTi listaan ti serra ket naikabil dita baba tapno mausar a reperensia:",
-       "blocklog-showsuppresslog": "Daytoy nga agar-aramat ket dati a naserraan ken nailemmeng.\nTi listaan ti napasardeng ket naikabil dita baba tapno mausar a reperensia:",
+       "blocklogpage": "Listaan ti serra",
+       "blocklog-showlog": "Daytoy nga agar-aramat ket dati a naserraan.\nTi listaan ti serra ket naikabil dita baba para iti reperensia:",
+       "blocklog-showsuppresslog": "Daytoy nga agar-aramat ket dati a naserraan ken nailemmeng.\nTi listaan ti panagpasardeng ket naikabil dita baba para iti reperensia:",
        "blocklogentry": "naserraan ni [[$1]] nga adda ti oras a panagpaso iti $2 $3",
-       "reblock-logentry": "sinukatan ti pannakaserra para kenni [[$1]] nga adda ti oras a panagpaso iti  $2 $3",
-       "blocklogtext": "Daytoy ket listaan ti agar-aramat kadagiti panagserra ken panaglukat ti serra\nDagiti na-atomatiko a panakaserra ti IP a pagtaengan ket saan a nailista.\nKitaen ti [[Special:BlockList|Listaan ti lapden nga IP]] para iti listaan kadagiti agdama a naiparit a pagpataray ken dagiti serra.",
+       "reblock-logentry": "sinukatan ti pannakaserra para kenni [[$1]] nga adda ti oras a panagpaso iti $2 $3",
+       "blocklogtext": "Daytoy ket listaan ti agar-aramat kadagiti panagserra ken panaglukat ti serra\nDagiti automatiko a panakaserra ti IP a pagtaengan ket saan a nailista.\nKitaen ti [[Special:BlockList|listaan ti serra]] para iti listaan kadagiti agdama a naiparit a pagpataray ken dagiti serra.",
        "unblocklogentry": "lukatan ti serra ni $1",
-       "block-log-flags-anononly": "dagiti di am-ammo nga agar-aramat laeng",
+       "block-log-flags-anononly": "dagiti di ammo nga agar-aramat laeng",
        "block-log-flags-nocreate": "nabaldado ti panagpartuat ti pakabilangan",
-       "block-log-flags-noautoblock": "naiddep ti auto-serra",
-       "block-log-flags-noemail": "naserraan ti esurat",
+       "block-log-flags-noautoblock": "nabaldado ti automatiko a serra",
+       "block-log-flags-noemail": "nabaldado ti esurat",
        "block-log-flags-nousertalk": "saan a mabalin nga agurnos ti bukodna a tungtungan a panid",
-       "block-log-flags-angry-autoblock": "napabalin ti napasayaat nga auto-serra",
+       "block-log-flags-angry-autoblock": "napakabaelan ti napasayaat nga automatiko a serra",
        "block-log-flags-hiddenname": "nailemmeng ti nagan ti agar-aramat",
-       "range_block_disabled": "Ti abilidad ti administrador nga agaramid ti nasakupan a serra ket naiddep.",
+       "range_block_disabled": "Ti abilidad ti administrador nga agpartuat ti nasakupan a serra ket nabaldado.",
        "ipb_expiry_invalid": "Imbalido ti oras a panagpaso.",
        "ipb_expiry_temp": "Ti serra ti nagan ti agar-aramat ket masapul a permanente.",
-       "ipb_hide_invalid": "Saan a mapasardeng daytoy a pakabilangan; daytoy ket addaan ti ad-adu ngem {{PLURAL:$1|maysa nga inurnos|dagiti $1 nga inurnos}}.",
-       "ipb_already_blocked": " \"$1\" ket naserraan",
-       "ipb-needreblock": "$1 ket naseraan. Kayatmo a sukatan ti serrana?",
+       "ipb_hide_invalid": "Saan a mapasardeng daytoy a pakabilangan; daytoy ket addaan iti ad-adu ngem {{PLURAL:$1|maysa nga inurnos|dagiti $1 nga inurnos}}.",
+       "ipb_already_blocked": "Ni \"$1\" ket naserraanen.",
+       "ipb-needreblock": "Ni $1 ket naseraanen. Kayatmo a sukatan ti serrana?",
        "ipb-otherblocks-header": "Sabali {{PLURAL:$1|a naserraan|kadagiti naserraan}}",
        "unblock-hideuser": "Saanmo a maisubli ti serra daytoy nga agar-aramat, nailemmengen ti nagan daytoy nga agar-aramat.",
-       "ipb_cant_unblock": "Biddut: ID $1 ti serra a nabirukan. Baka nalukatan ti serranan.",
-       "ipb_blocked_as_range": "Ballag: Ti IP a pagtaengan $1 ket saan a dagus a naserraan ken saan a malukatan ti serrana.\nNgem, nupay kasta, naserran a kas paset ti sakup ti $2, a mabalin a malukatan ti serrana.",
-       "ip_range_invalid": "Imbalido a sakup ti IP.",
-       "ip_range_toolarge": "Dagiti serra a nasakup a dakdakkel ngem /$1 ket saan a maipalubos.",
+       "ipb_cant_unblock": "Biddut: San a nabirukan ti ID $1 ti serra. Mabalin a nalukatanen ti serrana.",
+       "ipb_blocked_as_range": "Biddut: Ti IP a pagtaengan ti $1 ket saan a dagus a naserraan ken saan a malukatan ti serrana.\nNgem, nupay kasta, naserran a kas paset ti sakop ti $2, a mabalin a malukatan ti serrana.",
+       "ip_range_invalid": "Imbalido a sakop ti IP.",
+       "ip_range_toolarge": "Dagiti serra a nasakop a dakdakkel ngem /$1 ket saan a maipalubos.",
        "proxyblocker": "Pannakbagi a panagserra",
-       "proxyblockreason": "Ti IP a pagtaengam ket naserraan ngamin ket daytoy ket nakalukat a panakbagi.\nPangngaasi ta kontakem ti agit-ited ti serbisio ti Internetmo wenno teknikal a suporta ti kaurnusam ken ibagam kaniada ti nakaro a parikut ti seguridad.",
-       "sorbsreason": "Ti IP a pagtaengam ket nakalista a kasla \"nalukatan a pannakbagi\" idiay DNSBL nga inusar ti {{SITNAME}}.",
-       "sorbs_create_account_reason": "Ti IP a pagtaengam ket nakalista a kasla \"nalukatan a pannakbagi\" idiay DNSBL nga inusar ti {{SITNAME}}.\nSaanka a makaaramid ti pakabilangan",
+       "proxyblockreason": "Ti IP a pagtaengam ket naserraan ngamin ket daytoy ket nakalukat a panakbagi.\nPangngaasi a kontakem ti agit-ited ti serbisio ti Internetmo wenno teknikal a suporta ti gunglom ken ibagam kaniada ti nakaro a parikut ti seguridad.",
+       "sorbsreason": "Ti IP a pagtaengam ket nailista a kasla \"nalukatan a pannakbagi\" iti DNSBL nga inusar babaen ti {{SITNAME}}.",
+       "sorbs_create_account_reason": "Ti IP a pagtaengam ket nailista a kasla \"nalukatan a pannakbagi\" iti DNSBL nga inusar babaen ti {{SITNAME}}.\nSaanka a makapartuat ti pakabilangan.",
        "xffblockreason": "Ti maysa nga IP a pagtaengan nga adda iti X-Forwarded-For header, mabalin a kukuam wenno ti pannakbagi a server nga us-usarem, ket naserraan. Ti kasisigud a rason ti pannakaserra idi ket: $1",
-       "cant-see-hidden-user": "Ti agar-aramat a kayatmo a serraan ket naserraan ken nailemmeng.\nKet awan met ti karbengam nga agilemming ti agar-aramat, saan mo a makita wenno mabaliwan ti serra ti agar-aramat.",
-       "ipbblocked": "Saanmo a mabalin ti agserra wenno agikkat ti serra ti sabali nga agar-aramat, ngamin ket naserraan ka met.",
-       "ipbnounblockself": "Saanmo a mabalin a lukatan ti serram",
+       "cant-see-hidden-user": "Ti agar-aramat a kayatmo a serraan ket naserraanen ken nailemmeng.\nGapu ta awan met ti karbengam nga agilemming ti agar-aramat, saanmo a makita wenno maurnos ti serra ti agar-aramat.",
+       "ipbblocked": "Saanmo a mabalin ti agserra wenno agikkat ti serra ti sabali nga agar-aramat, ngamin ket naserraanka met.",
+       "ipbnounblockself": "Saanmo a mabalin a lukatan ti serram.",
        "lockdb": "Balunetan ti database",
        "unlockdb": "Lukatan ti database",
-       "lockdbtext": "Ti panagserra ti database ket makaikkat ti abilidad kadagiti amin nga agar-aramat ti agurnos kadagiti panid, ti panagsukat dagiti kaykayatda, ti panagurnos dagiti bambantayanda, ken dagiti sabsabali pay a masapul ti panagsukat idiay database.\nPangngaasi a pasingkedam daytoy no kayatmo nga aramiden, ken luktam dayta database no malpas kan nga agsimpa.",
-       "unlockdbtext": "Ti panaglukat ti database ket mangipasubli ti abilidad dagiti amin nga agar-aramat ti panagurnos kadagiti panid, ti panagsukat dagiti kaykayatda, ti panagurnos dagiti bambantayanda, ken dagiti amin a makasapul ti panagsukat idiay database.\nPangngaasi a pasingkedam a daytoy no kayatmo nga aramiden.",
+       "lockdbtext": "Ti panagserra ti database ket makaikkat ti abilidad kadagiti amin nga agar-aramat ti agurnos kadagiti panid, ti panagsukat dagiti kakaykaytanda, ti panagurnos dagiti listaan ti bambantayanda, ken dagiti sabali pay a masapul ti panagsukat iti database.\nPangngaasi a pasingkedam daytoy no kayatmo nga aramiden, ken luktam dayta database no malpaskan nga agsimpa.",
+       "unlockdbtext": "Ti panaglukat ti database ket mangipasubli ti abilidad dagiti amin nga agar-aramat ti panagurnos kadagiti panid, ti panagsukat kadagiti kakaykayatanda, ti panagurnos dagiti listaan bambantayanda, ken dagiti amin a makasapul ti panagsukat iti database.\nPangngaasi a pasingkedam a daytoy no kayatmo nga aramiden.",
        "lockconfirm": "Wen, talaga a kayatko a balunetan ti database.",
        "unlockconfirm": "Wen, talaga a kayatko a balunetan ti database.",
        "lockbtn": "Balunetan ti database",
        "unlockdbsuccesssub": "Naikkaten ti balunet ti database",
        "lockdbsuccesstext": "Nabalunetan ti database.<br />\nLaglagipem nga [[Special:UnlockDB|ikkaten ti balunetna]] kalpasan a malpaska nga agsimpa.",
        "unlockdbsuccesstext": "Nalukatanen ti database.",
-       "lockfilenotwritable": "Ti serra a papeles ti database ket saan a masuratan.\nTi agserra ken aglukat iti database, masapul a masuratan ti web server.",
+       "lockfilenotwritable": "Ti papeles ti balunet ti database ket saan a masuratan.\nTapno mabalunetan ken malukatan ti database, nasken daytoy a masuratan babaen ti web server.",
        "databasenotlocked": "Saan a nabalunetan ti database.",
-       "lockedbyandtime": "(ni {{GENDER:$1|$1}} idi $2 ti oras $3)",
+       "lockedbyandtime": "(ni {{GENDER:$1|$1}} idi $2, $3)",
        "move-page": "Iyalis ti $1",
        "move-page-legend": "Iyalis ti panid",
-       "movepagetext": "Ti panagusar ti kinabuklan dita baba, ket mangnagan manen ti panid, a mangiyalis amin ti pakasaritaanna idiay baro a nagan.\nTi daan a titulo ket agbalin a baw-ing a panid idiay baro a titulo.\nMapabarom a kas automatiko dagiti baw-ing a nakatudo dita kasisigud a titulo.\nNo agpilika a saanmo a kayat, pasaraduam a kitaen ti [[Special:DoubleRedirects|doble]] wenno [[Special:BrokenRedirects|nadadael a baw-ing]].\nRenbbengmo ti mangpatalged nga amin a silpo ket agtultuloy a nakatudo iti nasken a papananda.\n\nLaglagipen a ti panid ket '''saan''' a maiyalis no addan sigud a panid iti baro a titulo, malaksid no ti kinaudi ket maysa a baw-ing ken awan ti napalabas a pakasaritaan ti panag-urnos. \nKayat a sawen daytoy a mabalinmo a suktan ti nagan ti maysa a panid manipud iti punto ti pannakasukat ti nagan no nagbiddutka, ken saan mo a mabalin a suratan manen ti addaan a panid.\n\n'''Ballaag!'''\nMabalin a maysa daytoy a nakaro ken saan a bigla a panagbaliw iti maysa a nasikat a panid;\npangngaasim a pasingkedam a maawatam ti ibunga daytoy sakbay nga agtuloyka a mangbaliw.",
-       "movepagetext-noredirectfixer": "Ti panagusar ti kinabuklan dita baba, ket panaganan ti panid, iyalis na amin ti pakasaritaan na idiay baro a nagan.\nTi daan a titulo ket agbalin baw-ing a panid idiay baro a titulo.\nPasaruduam a kitaen ti [[Special:DoubleRedirects|doble]] wenno [[Special:BrokenRedirects|nadadael a baw-ing]].\nRebbengem ti mangpatalged nga amin a panilpo ket agtultuloy a nakatudo iti nasken a papananda.\n\nLaglagipen a ti panid ket '''saan''' a maiyalis no addan sigud a panid iti baro a titulo, malaksid no awan linaonna wenno no maysa a baw-ing a panid ken awan ti panagbaliw iti pakasaritaan ti napalabas. \nKayat a sawen daytoy a mabalinmo a suktan ti nagan ti maysa a panid manipud iti punto ti pannakasukat ti nagan no nagbiddutka, ken saan mo a mabalin a suratan manen ti addaan a panid.\n\n'''Ballaag!'''\nMabalin a maysa daytoy a nakaro ken saan a bigla a panagbaliw iti maysa a nasikat a panid;\npangngaasim ta pasingkedam a maawatam ti ibunga daytoy sakbay nga agtuloyka a mangbaliw.",
-       "movepagetalktext": "Ti mainaig a tungtungan ti panid ket giddato a maiyalis a karamanna '''malaksid:'''\n*No addan sigud nga awan linaonna a tungtungan ti panid babaen ti baro a nagan, wenno\n*No ikkatem ti kur-itna ti kahon iti baba.\n\nKadagitoy a kaso, masapul nga iyalis wenno itiponmo a manual ti panid no kayatmo.",
+       "movepagetext": "Ti panagusar ti porma dita baba, ket mangnagan manen ti panid, a mangiyalis amin ti pakasaritaanna iti baro a nagan.\nTi daan a titulo ket agbalin a baw-ing a panid iti baro a titulo.\nMapabarom a kas automatiko dagiti baw-ing a nakatudo dita kasisigud a titulo.\nNo agpilika a saanmo a kayat, siguraduem a kitaen ti [[Special:DoubleRedirects|doble]] wenno [[Special:BrokenRedirects|nadadael a baw-ing]].\nRenbbengmo ti mangpatalged nga amin a silpo ket agtultuloy a nakatudo iti nasken a papananda.\n\nLaglagipen a ti panid ket <strong>saan</strong> a maiyalis no addan sigud a panid iti baro a titulo, malaksid no ti kinaudi ket maysa a baw-ing ken awan ti napalabas a pakasaritaan ti panag-urnos. \nKayat a sawen daytoy a mabalinmo a suktan ti nagan ti maysa a panid manipud iti punto ti pannakasukat ti nagan no nagbiddutka, ken saan mo a mabalin a suratan manen ti addaan a panid.\n\n<strong>Ballaag!</strong>\nMabalin a maysa daytoy a nakaro ken saan a bigla a panagbaliw iti maysa a nasikat a panid;\npangngaasim a pasingkedam a maawatam ti ibunga daytoy sakbay nga agtuloyka a mangbaliw.",
+       "movepagetext-noredirectfixer": "Ti panagusar ti kinabuklan dita baba, ket panaganan ti panid, iyalisna amin ti pakasaritaanna iti baro a nagan.\nTi daan a titulo ket agbalin baw-ing a panid idiay baro a titulo.\nPasaruduam a kitaen ti [[Special:DoubleRedirects|doble]] wenno [[Special:BrokenRedirects|nadadael a baw-ing]].\nRebbengem ti mangpatalged nga amin a silpo ket agtultuloy a nakatudo iti nasken a papananda.\n\nLaglagipen a ti panid ket <strong>saan</strong> a maiyalis no addan sigud a panid iti baro a titulo, malaksid no awan linaonna wenno no maysa a baw-ing a panid ken awan ti panagbaliw iti pakasaritaan ti napalabas. \nKayat a sawen daytoy a mabalinmo a suktan ti nagan ti maysa a panid manipud iti punto ti pannakasukat ti nagan no nagbiddutka, ken saanmo a mabalin a suratan manen ti addaan a panid.\n\n<strong>Ballaag!</strong>\nMabalin a maysa daytoy a nakaro ken saan a bigla a panagbaliw iti maysa a nasikat a panid;\npangngaasim ta pasingkedam a maawatam ti ibunga daytoy sakbay nga agtuloyka a mangbaliw.",
+       "movepagetalktext": "Ti mainaig a tungtungan ti panid ket automatikonto a maiyalis a karamanna <strong>malaksid:</strong>\n*Ti addan ti awan linaon a tungtungan ti panid babaen ti baro a nagan, wenno\n*No ikkatem ti kur-itna ti kahon iti baba.\n\nKadagitoy a kaso, masapul nga iyalis wenno manual nga itiponmo ti panid no kayatmo.",
        "movearticle": "Iyalis ti panid:",
-       "moveuserpage-warning": "'''Ballaag:''' Mangrugrugika nga agiyalis ti panid ti agar-aramat. Pangngaasi a laglapipen a ti panid ket isu laeng ti mabalin nga iyalis ken ti agar-aramat ket ''saan'' a managanan.",
+       "moveuserpage-warning": "<strong>Ballaag:</strong> Mangrugrugika nga agiyalis ti panid ti agar-aramat. Pangngaasi a laglapipen a ti panid ket isu laeng ti maiyalis ken ti agar-aramat ket <em>saanto</em> a managanan.",
        "movecategorypage-warning": "<strong>Ballaag:</strong> Mangiyal-aliskan iti panid ti kategoria. Pangngaasi a laglagipen a ti maiyalisto laeng ket ti panid ken ti aniaman a pampanid iti daan a kategoria ket <em>saanto</em> a maikategoria iti baro.",
        "movenologintext": "Masapul a nakarehistroka nga agar-aramat ken [[Special:UserLogin|nakastrek]] tapno makaiyalis iti panid.",
        "movenotallowed": "Awan ti pammalubosmo nga agiyalis kadagiti panid.",
        "movenotallowedfile": "Awan ti pammalubosmo nga agiyalis kadagiti papeles.",
-       "cant-move-user-page": "Awan ti pammalubos mo nga agiyalis kadagiti panid ti agar-aramat (malaksid kadaiti subpanid).",
-       "cant-move-to-user-page": "Awan ti pammalubos mo nga agiyalis ti panid idiay panid ti agar-aramat (malaksid kadagiti subpanid ti agar-aramat).",
+       "cant-move-user-page": "Awan ti pammalubosmo nga agiyalis kadagiti panid ti agar-aramat (malaksid kadagiti subpanid).",
+       "cant-move-to-user-page": "Awan ti pammalubosmo nga agiyalis ti panid iti panid ti agar-aramat (malaksid kadagiti subpanid ti agar-aramat).",
        "cant-move-category-page": "Awan ti pammalubosmo nga agiyalis kadagiti panid ti kategoria.",
        "cant-move-to-category-page": "Awan ti pammalubosmo nga agiyalis ti panid iti panid ti kategoria.",
        "newtitle": "Iti baro a titulo:",
-       "move-watch": "Bantayan daytoy a panid",
+       "move-watch": "Bantayan ti taudan a panid ken puntaan a panid",
        "movepagebtn": "Iyalis ti panid",
        "pagemovedsub": "Balligi ti panangiyalis",
-       "movepage-moved": "Naiyalis ti '''\"$1\" iti \"$2\"'''",
+       "movepage-moved": "<strong>Naiyalisen ti \"$1\" iti \"$2\"</strong>",
        "movepage-moved-redirect": "Napartuaten ti maysa a baw-ing.",
-       "movepage-moved-noredirect": "Ti panagaramid ti baw-ing ket napasardeng.",
-       "articleexists": "Adda panid nga adda ti kasta a nagan, wenno ti nagan a pinilim ket saan a mabalin.\nPangngaasim a mangpilika iti sabali a nagan.",
-       "cantmove-titleprotected": "Saanmo a maiyalis ti panid iti daytoy a lokasion, ngamin ket ti baro a titulo ket nasalakniban para iti panakapartuat.",
+       "movepage-moved-noredirect": "Ti pannakapartuat ti baw-ing ket napasardeng.",
+       "articleexists": "Adda panid nga adda ti kastan a nagan, wenno ti nagan a pinilim ket saan a mabalin.\nPangngaasi nga agpili ti sabali a nagan.",
+       "cantmove-titleprotected": "Saanmo a maiyalis ti panid iti daytoy a lokasion ngamin ket ti baro a titulo ket nasalakniban manipud ti pannakapartuat",
        "movetalk": "Iyalis ti mainaig a panid ti tungtungan",
-       "move-subpages": "Iyalis dagiti subpanid (aginggana ti $1)",
-       "move-talk-subpages": "Iyalis dagiti subpanid ti tungtungan ti panid (aginggana ti $1)",
-       "movepage-page-exists": "Ti panid ti $1 ket addan ken saan a mautomatiko a suratan manen.",
-       "movepage-page-moved": "Naiyalis ti panid a $1 iti $2.",
-       "movepage-page-unmoved": "Saan a maiyalis ti panid $1 iti $2.",
-       "movepage-max-pages": "Ti kaadu iti $1 a {{PLURAL:$1|panid|pampanid}} ket naiyalis ken awanen ti automatiko a maiyalis.",
+       "move-subpages": "Iyalis dagiti subpanid (aginggana iti $1)",
+       "move-talk-subpages": "Iyalis dagiti subpanid ti tungtungan ti panid (aginggana iti $1)",
+       "movepage-page-exists": "Ti panid ti $1 ket addan ken saan a mabalin nga automatiko a masuratan manen.",
+       "movepage-page-moved": "Ti panid ti $1 ket naiyalisen iti $2.",
+       "movepage-page-unmoved": "Ti panid ti $1 ket saan a maiyalis iti $2.",
+       "movepage-max-pages": "Ti kaaduan iti $1 a {{PLURAL:$1|panid|pampanid}} ket naiyalisen ken awanton ti automatiko a maiyalis.",
        "movelogpage": "Listaan ti naiyalis",
-       "movelogpagetext": "Adda dita baba ti listaan dagiti naiyalis a panid.",
+       "movelogpagetext": "Adda dita baba ti listaan dagiti amin a naiyalis a panid.",
        "movesubpage": "{{PLURAL:$1|Subpanid|Dagiti subpanid}}",
-       "movesubpagetext": "Daytoy a panid ket adda $1 {{PLURAL:$1|a subpanid|kadagiti subpanid}} a naipakita dita baba.",
+       "movesubpagetext": "Daytoy a panid ket addaan iti $1 {{PLURAL:$1|a subpanid|kadagiti subpanid}} a naipakita dita baba.",
        "movenosubpage": "Daytoy a panid ket awan ti subpanidna.",
        "movereason": "Rason:",
        "revertmove": "isubli",
        "delete_and_move": "Ikkaten ken iyalis",
-       "delete_and_move_text": "== Masapul nga ikkaten ==\nTi pangipanan ti panid ket \"[[:$1]]\" addan.\nKayatmo nga ikkaten  tapno makaiyaliska?",
+       "delete_and_move_text": "== Masapul nga ikkaten ==\nTi pangipanan ti panid ket \"[[:$1]]\" addan.\nKayatmo nga ikkaten tapno makaiyaliska?",
        "delete_and_move_confirm": "Wen, ikkaten ti panid",
-       "delete_and_move_reason": "Naikkat tapno mawayaan ti pannaka-iyalis idiay \"[[$1]]\"",
+       "delete_and_move_reason": "Naikkat tapno mawayaan ti pannaka-iyalis manipud ti \"[[$1]]\"",
        "selfmove": "Ti titulo ti taudan ken ti pangipanan ket agpadpada;\nsaanmo a maiyalis ti panid ti isu met laeng a panid.",
-       "immobile-source-namespace": "Saan a maiyalis dagiti panid idiay nagan ti espasio ti  \"$1\"",
-       "immobile-target-namespace": "Saan a maiyalis dagiti panid idiay nagan ti espasio ti \"$1\"",
+       "immobile-source-namespace": "Saan a maiyalis dagiti panid iti nagan ti espasio ti \"$1\"",
+       "immobile-target-namespace": "Saan a maiyalis dagiti panid iti nagan ti espasio ti \"$1\"",
        "immobile-target-namespace-iw": "Ti silpo nga interwiki ket saan nga umiso a puntaan para iti panagiyalis ti panid.",
        "immobile-source-page": "Saan a mabalin nga iyalis daytoy a panid.",
-       "immobile-target-page": "Saan a maiyalis iti dayata a pangipanan a titulo.",
-       "bad-target-model": "Ti kinaykayat a pangipanan ket agus-usar ti sabali a modelo ti linaon. Saan a maipabalin manipud ti $1 iti $2.",
-       "imagenocrossnamespace": "Saan a maiyalis ti papeles idiay saan a papeles a nagan ti espasio",
-       "nonfile-cannot-move-to-file": "Saan a maiyalis ti saan a papeles idiay papeles a nagan ti espasio",
-       "imagetypemismatch": "Ti baro a pagpaatiddog ti papeles ket saan nga agpada ti kitana",
+       "immobile-target-page": "Saan a maiyalis iti dayta a pangipanan a titulo.",
+       "bad-target-model": "Ti kinaykayat a pangipanan ket agus-usar ti sabali a modelo ti linaon. Saan a mapagbaliwen manipud ti $1 iti $2.",
+       "imagenocrossnamespace": "Saan a maiyalis ti papeles iti saan nagan ti espasio ti papeles",
+       "nonfile-cannot-move-to-file": "Saan a maiyalis ti saan a papeles iti nagan ti espasio ti papeles",
+       "imagetypemismatch": "Ti baro a pagpaatiddog ti papeles ket saan a maipada iti bukodna a kita",
        "imageinvalidfilename": "Ti puntaan a nagan ti papeles ket imbalido",
-       "fix-double-redirects": "Agpabaro ti amin a baw-ing a mangipatudo ti kasisigud a titulo",
+       "fix-double-redirects": "Agpabaro kadagiti aniaman a baw-ing a mangipatudo ti kasisigud a titulo",
        "move-leave-redirect": "Mangibati ti baw-ing",
-       "protectedpagemovewarning": "'''Ballaag:''' Daytoy a panid ket nasalakniban tapno dagiti laeng agar-aramat nga addaan ti gundaway nga administrador ti makaiyalis.\nTi kinaudi a naikabil ti listaan ket adda dita baba tapno mausar a reperensia:",
-       "semiprotectedpagemovewarning": "'''Pakaammo:''' Nasalakniban daytoy a panid tapno dagiti laeng nakarehistro nga agar-aramat ti makaiyalis daytoy.\nTi kinaudi a naikabil ti listaan ket adda iti baba tapno mausar a reperensia:",
-       "move-over-sharedrepo": "== Addaan ti papeles ==\n[[:$1]] addaan idiay pagbingayan a repositorio. Ti panagiyalis ti papeles iti titulo nga itoy ket paawanenna ti pagbingayan a papeles.",
-       "file-exists-sharedrepo": "Ti napilim a nagan ti papeles ket naususaren idiay pagbingayan a pagikabilan.\nPangngaasi nga agpilika ti sabali a nagan.",
+       "protectedpagemovewarning": "<strong>Balaag:</strong> Daytoy a panid ket nasalakniban tapno dagiti laeng agar-aramat nga addaan ti gundaway nga administrador ti makaiyalis.\nTi naudi a naikabil iti listaan ket naited dita baba para iti reperensia:",
+       "semiprotectedpagemovewarning": "<strong>Nota:</strong> Nasalakniban daytoy a panid tapno dagiti laeng nakarehistro nga agar-aramat ti makaiyalis daytoy.\nTi naudi a naikabil iti listaan ket naited dita baba para iti reperensia:",
+       "move-over-sharedrepo": "== Addaan ti papeles ==\nTi [[:$1]] addaan iti pagbingayan a repositorio. Ti panagiyalis ti papeles iti daytoy a titulo ket tuonenna ti pagbingayan a papeles.",
+       "file-exists-sharedrepo": "Ti napilim a nagan ti papeles ket naususaren iti pagbingayan a repositorio.\nPangngaasi nga agpilika ti sabali a nagan.",
        "export": "Agipan kadagiti panid",
        "exporttext": "Maipanmo ti testo ken pakasaritaan ti inurnos iti maysa a panid wenno pampanid a nabalkut ti XML.\nDaytoy ket mabalin a maikabil iti sabali a wiki nga agususar ti MediaWiki nga usaren ti [[Special:Import|pinagala ti panid]].\n\nTi pinagipan ti panid, ikabil ti titulo dita kahon ti testo dita baba, maysa a titulo iti maysa a linia, ken agpili ka no ti kayatmo ket ti agdama a pinagbaliw ken amin nga daan a panagbalbaliw, nga addaan ti linia ti pakasaritaan ti pampanid, wenno ti agdama a panagbaliw nga addaan ti pakaammo a maipapan ti kinaudi a panagurnos.\n\nNo iti kinaudi a kaso mabalinmo nga usaren ti silpo, a kas pagarigan [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] para iti panid \"[[{{MediaWiki:Mainpage}}]]\".",
        "exportall": "Ipan amin a pampanid",
        "exportcuronly": "Iraman laeng ti kinaudi a panagbaliw, saan a ti napno a pakasaritaan",
-       "exportnohistory": "----\n'''Palagip:''' Ti pagipapan dagiti napno a pakasaritaan dagiti panid iti daytoy a kinabuklan ket nabaldado gapu dagiti pannakalaing ti panagandar a rason.",
+       "exportnohistory": "----\n<strong>Nota:</strong> Ti pagipapan dagiti napno a pakasaritaan dagiti panid iti daytoy a kinabuklan ket nabaldado gapu dagiti pannakalaing ti panagandar a rason.",
        "exportlistauthors": "Iraman ti amin a listaan kadagiti nagaramid iti tunggal a maysa a panid",
        "export-submit": "Agipan",
-       "export-addcattext": "Agnayon kadagiti panid a naggapu idiay kategoria:",
+       "export-addcattext": "Agnayon kadagiti panid manipud ti kategoria:",
        "export-addcat": "Inayon",
-       "export-addnstext": "Nayunan dagiti panid a naggapu idiay nagan ti espasio:",
+       "export-addnstext": "Agnayon kadagiti panid manipud ti nagan ti espasio:",
        "export-addns": "Inayon",
        "export-download": "Idulin a kas papeles",
        "export-templates": "Mangiraman kadagiti plantilia",
        "allmessagesname": "Nagan",
        "allmessagesdefault": "Kasisigud a testo ti mensahe",
        "allmessagescurrent": "Agdama a testo ti mensahe",
-       "allmessagestext": "Daytoy ti listaan dagiti mensahe ti sistema a magun-od idiay MediaWiki a nagan ti espasio.\nPangngaasi a bisitaen ti [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Lokalisasion ti MediaWiki] ken [//translatewiki.net translatewiki.net] no kayatmo ti agparawad kadagiti sapasap a panagipatarus ti MediaWiki.",
-       "allmessagesnotsupportedDB": "Saan a mausar daytoy a panid ngamin ket ti '''$wgUseDatabaseMessages''' ket nabaldado.",
+       "allmessagestext": "Daytoy ti listaan dagiti mensahe ti sistema a magun-od iti nagan ti espasio ti MediaWiki.\nPangngaasi a bisitaen ti [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Lokalisasion ti MediaWiki] ken [//translatewiki.net translatewiki.net] no kayatmo ti agparawad kadagiti sapasap a panagipatarus ti MediaWiki.",
+       "allmessagesnotsupportedDB": "Daytoy a panid ket saan a musar gapu ta nabaldado ti <strong>$wgUseDatabaseMessages</strong>.",
        "allmessages-filter-legend": "Sagat",
        "allmessages-filter": "Sagaten babaen ti naipaduma a kasasaad:",
        "allmessages-filter-unmodified": "Saan a nabaliwan",
        "allmessages-filter-submit": "Inkan",
        "allmessages-filter-translate": "Ipatarus",
        "thumbnail-more": "Padakkelen",
-       "filemissing": "Napukaw ti papeles",
-       "thumbnail_error": "Biddut ti panagaramid ti bassit a ladawan: $1",
+       "filemissing": "Awan ti papeles",
+       "thumbnail_error": "Biddut ti panagpartuat ti bassit a ladawan: $1",
        "thumbnail_error_remote": "Biddut a mensahe manipud ti $1: \n$2",
-       "djvu_page_error": "Ti DjVu a panid ket saan a nasakup",
+       "djvu_page_error": "Ti DjVu a panid ket saan a masakop",
        "djvu_no_xml": "Saan a naala ti XML iti DjVu a papeles",
-       "thumbnail-temp-create": "Saan a makaaramid ti temporario a bassit a ladawan ti papeles",
+       "thumbnail-temp-create": "Saan a makapartuat ti temporario a bassit a ladawan ti papeles",
        "thumbnail-dest-create": "Saan a maidulin ti basit a ladawan idiay pagipanan",
-       "thumbnail_invalid_params": "Imbalido a parametro ti bassit a ladawan",
-       "thumbnail_dest_directory": "Saan a nakaaramid ti pangipanan a direktorio.",
-       "thumbnail_image-type": "Daytoy a kita ti ladawan ket saan a nasuportaran.",
-       "thumbnail_gd-library": "Saan a kompleto a GD biblioteka a pannakaaramid: Awan ti opisio ti $1",
-       "thumbnail_image-missing": "Daytoy a papeles ket kasla napukaw: $1",
+       "thumbnail_invalid_params": "Imbalido dagiti parametro ti bassit a ladawan",
+       "thumbnail_dest_directory": "Saan a nakapartuat ti pangipanan a direktorio.",
+       "thumbnail_image-type": "Daytoy a kita ti ladawan ket saan a nasuportaran",
+       "thumbnail_gd-library": "Saan a kompleto a konpigurasion ti biblioteka ti GD: Awan ti annong ti $1",
+       "thumbnail_image-missing": "Kasla awan daytoy a papeles: $1",
        "thumbnail_image-failure-limit": "Adu unayen dagiti nabiit a napaay a panagipadas ($1 wenno ad-adu) a panangiparamg daytoy bassit a ladawan. Pangngaasi a padasen manen intono madamdama.",
        "import": "Agala kadagiti panid",
        "importinterwiki": "Agala ti transwiki",
-       "import-interwiki-text": "Agpilika ti wiki ken titulo ti panid nga alaem.\nDagit panagbaliw a petsa ken dagiti nagan ti mannurat ket maipreserba.\nAmin a transwiki nga alaem ket mailista idiay [[Special:Log/import|listaan ti pinagala]].",
+       "import-interwiki-text": "Agpilika ti wiki ken titulo ti panid nga alaem.\nDagiti rebision ti petsa ken dagiti nagan ti mannurat ket maipreserba.\nAmin a transwiki nga alaem ket mailista iti [[Special:Log/import|listaan ti panagala]].",
        "import-interwiki-source": "Taudan ti wiki/panid:",
-       "import-interwiki-history": "Kopiaen amin dagiti bersion ti pakasaritaan daytoy a panid",
+       "import-interwiki-history": "Kopiaen amin dagiti rebision ti pakasaritaan daytoy a panid",
        "import-interwiki-templates": "Iraman amin dagiti plantilia",
        "import-interwiki-submit": "Agala",
        "import-interwiki-namespace": "Pangipanan a nagan ti espasio:",
        "import-interwiki-rootpage": "Papanan a ramut ti panid (pagpilian):",
        "import-upload-filename": "Nagan ti papeles:",
        "import-comment": "Komentario:",
-       "importtext": "Pangngaasi nga ipanmo ti papeles a naggapu iti nagtaudan a wiki nga agusar ti [[Special:Export|agipan]].",
-       "importstart": "Agal-ala dagiti panid...",
-       "import-revision-count": "$1 {{PLURAL:$1|a pinagbaliwan|kadagiti pinagbaliwan}}",
-       "importnopages": "Awan dagiti panid ti maala.",
+       "importtext": "Pangngaasi nga ipanmo ti papeles manipud ti nagtaudan a wiki nga agusar ti [[Special:Export|ramit ti panagipan]].\nIdulinmo iti bukodmo a kompiuter ken ikarga ditoy.",
+       "importstart": "Agal-ala kadagiti panid...",
+       "import-revision-count": "$1 {{PLURAL:$1|a rebision|kadagiti rebision}}",
+       "importnopages": "Awan dagiti maala a panid.",
        "imported-log-entries": "Naala ti $1 {{PLURAL:$1|a nailista|kadagiti nailista}}.",
        "importfailed": "Napaay ti panagala: <nowiki>$1</nowiki>",
-       "importunknownsource": "Di amammo a kita ti taudan ti innala",
+       "importunknownsource": "Di ammmo a kita ti taudan ti innala",
        "importcantopen": "Saan a maluktan ti innala a papeles",
        "importbadinterwiki": "Saan a nasayaat a silpo ti interwiki",
-       "importsuccess": "Nalpasen ti pinagala!",
-       "importnosources": "Awan ti innala a taudan ti transwiki ti naipalawag ken ti dagus a pakasaritaan ti pinag-ipan ket nabaldado.",
-       "importnofile": "Awan ti inalam a papeles a naipapan.",
-       "importuploaderrorsize": "Ti pinag-ipan ti innala a papeles ket napaay.\nTi papeles ket dakdakel ngem ti mabalin a kadakkel ti pang-ipan.",
-       "importuploaderrorpartial": "Ti pinag-ipan ti innala a papeles ket napaay.\nPaset laeng ti papeles ti napag-ipan.",
-       "importuploaderrortemp": "Ti pinag-ipan ti papeles ket napaay.\nAwan ti saan nga agnayon a polder.",
-       "import-parse-failure": "Napaay ti pinagala ti XML parse",
+       "importsuccess": "Nalpasen ti panagala!",
+       "importnosources": "Awan ti innala a taudan ti transwiki ti naipalawag ken ti dagus a pakasaritaan ti panagikarga ket nabaldado.",
+       "importnofile": "Awan ti innalam a papeles ti naikarga.",
+       "importuploaderrorsize": "Ti panagikarga ti innala a papeles ket napaay.\nTi papeles ket dakdakel ngem ti maipalubos a kadakkel ti maikarga.",
+       "importuploaderrorpartial": "Ti panagikarga ti innala a papeles ket napaay.\nPaset laeng ti papeles ti naikarga.",
+       "importuploaderrortemp": "Ti panagikarga ti innala a papeles ket napaay.\nAwan ti temporario a polder.",
+       "import-parse-failure": "Napaay ti panagala ti panagwaswas ti XML",
        "import-noarticle": "Awan ti panid a maaala!",
-       "import-nonewrevisions": "Awan dagiti naala panagbalbaliw (mabalin nga adda amin dagitoyen, wenno nalabsan gapu kadagiti biddut).",
+       "import-nonewrevisions": "Awan dagiti naala a rebision (mabalin nga adda amin dagitoyen, wenno nalabsan gapu kadagiti biddut).",
        "xml-error-string": "$1 iti linia $2, tukol $3 (byte $4): $5",
-       "import-upload": "Ipan ti XML data",
-       "import-token-mismatch": "Napukaw ti gimong ti datos.\nPangngaasi a padasem manen.",
-       "import-invalid-interwiki": "Saan a makaala dita naited a wiki.",
-       "import-error-edit": "Ti panid ti \"$1\" ket saan a naala ngamin ket saanmo a mabalin nga urnosen.",
-       "import-error-create": "Ti panid ti \"$1\" ket saan a naala ngamin ket saanmo a mabalin nga aramiden.",
-       "import-error-interwiki": "Ti panid ti \"$1\" ket saan a naala ngamin ket ti nagan ket nailasin para iti ruar a panagsilpo (interwiki).",
-       "import-error-special": "Ti panid ti \"$1\" ket saan a naala ngamin ket bukod ti  espesial a nagan a lugar a saan nga agpalubos ti pampanid.",
-       "import-error-invalid": "Ti panid ti \"$1\" ket saan a naala ngamin ket ti nagan ket imbalido.",
-       "import-error-unserialize": "Ti panagbaliw ti $2 iti panid ti \"$1\" ket di maipagsasaruno. Ti panagbalbaliw ket naireporta idi nga agus-usar ti modelo ti $3 a naipagsasaruno a kas $4.",
-       "import-error-bad-location": "Ti panagbaliw ti $2 nga agus-usar ti modelo a linaon ti $3 ket saan a maipenpen iti \"$1\" iti daytoy a wiki, gapu ta dayta a modelo ket saan a nasuportaran iti dayta a panid.",
+       "import-upload": "Ikarga ti datos ti XML",
+       "import-token-mismatch": "Napukaw ti sesion ti datos.\nPangngaasi a padasen manen.",
+       "import-invalid-interwiki": "Saan a makaala manipud ti nainaganan a wiki.",
+       "import-error-edit": "Ti panid ti \"$1\" ket saan idi a naala ngamin ket saanmo a mabalin nga urnosen.",
+       "import-error-create": "Ti panid ti \"$1\" ket saan idi a naala ngamin ket saanmo a mabalin a partuaten.",
+       "import-error-interwiki": "Ti panid ti \"$1\" ket saan idi a naala ngamin ket ti nagan ket naireserba para iti ruar a panagsilpo (interwiki).",
+       "import-error-special": "Ti panid ti \"$1\" ket saan idi a naala ngamin ket bukod ti espesial a nagan ti espasio ket saan nga agpalubos iti pampanid.",
+       "import-error-invalid": "Ti panid ti \"$1\" ket saan idi a naala ngamin ket ti nagan a pakaalaanna ket imbalido iti daytoy a wiki.",
+       "import-error-unserialize": "Ti rebisionn ti $2 iti panid ti \"$1\" ket di maipagsasaruno. Ti rebision ket naireporta idi nga agus-usar ti modelo ti $3 a naipagsasaruno a kas $4.",
+       "import-error-bad-location": "Ti rebision ti $2 nga agus-usar ti modelo a linaon ti $3 ket saan a maipenpen iti \"$1\" iti daytoy a wiki, gapu ta dayta a modelo ket saan a nasuportaran iti dayta a panid.",
        "import-options-wrong": "Saan a husto {{PLURAL:$2|a pagpilian|a pagpilpilian}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "Ti naited a ramut ti panid ket imbalido a titulo.",
-       "import-rootpage-nosubpage": "Ti nagan ti lugar ti \"$1\" iti ramut ti panid ket saan amangpalubos kadagiti apo ti panid.",
-       "importlogpage": "Alaen ti listaan",
-       "importlogpagetext": "Ti administratibo a panagala dagiti panid nga adda ti pakasaritaanna nga urnos kadagiti sabsabali a wiki.",
-       "import-logentry-upload": "innala ti [[$1]] iti papeles a pinag-ipan",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|a pinagbaliwan|kadagiti pinagbaliwan}}",
-       "import-logentry-interwiki": "nai-transwiki ti $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|pinagbaliwan|dagiti pinagbaliwan}} manipud iti $2",
-       "javascripttest": "Subsubokan ti JavaScript",
-       "javascripttest-title": "Agpatpataray ti $1 a subsubokan",
-       "javascripttest-pagetext-noframework": "Daytoy a panid ket nailasin para iti panagpataray ti subsubokan a JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Di amamo a pagsubsubokan a tabas \"$1\".",
-       "javascripttest-pagetext-frameworks": "Pangngaasi nga agpili ti maysa kadagiti sumaganad a pagsubokan a tabas: $1",
-       "javascripttest-pagetext-skins": "Agpili ti kudil a pangipatarayan ti pagsubokan:",
+       "import-rootpage-nosubpage": "Ti nagan ti espasio ti \"$1\" iti ramut ti panid ket saan a mangpalubos kadagiti subpanid.",
+       "importlogpage": "Listaan ti panagala",
+       "importlogpagetext": "Dagiti administratibo a panagala kadagiti panid nga addaan iti pakasaritaan ti panag-urnos manipud kadagiti sabali a wiki.",
+       "import-logentry-upload": "innala ti [[$1]] babaen ti panagikarga ti papeles",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|a rebision|kadagiti rebision}} ti naala",
+       "import-logentry-interwiki": "nai-transwiki iti $1",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|rebision|dagiti rebision}} ti naala manipud ti $2",
+       "javascripttest": "Panagsubok ti JavaScript",
+       "javascripttest-title": "Agpatpataray kadagiti panagsubok ti $1",
+       "javascripttest-pagetext-noframework": "Daytoy a panid ket naireserba para iti panagpataray kadagiti panagsubok ti JavaScript.",
+       "javascripttest-pagetext-unknownframework": "Di ammo a tabas ti panagsubok ti \"$1\".",
+       "javascripttest-pagetext-frameworks": "Pangngaasi nga agpili ti maysa kadagiti sumaganad a tabas ti panagsubok: $1",
+       "javascripttest-pagetext-skins": "Agpili ti kudil a pangipatarayan kadagiti panagsubok:",
        "javascripttest-qunit-intro": "Kitaen ti [ $1 dukomentasion ti panagsubok] idiay mediawiki.org.",
        "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit test suite",
        "tooltip-pt-userpage": "Panidmo nga agar-aramat",
-       "tooltip-pt-anonuserpage": "Ti panid ti agar-aramat daytoy nga IP a pagtaengan nga urnosem a  kasla",
-       "tooltip-pt-mytalk": "Pakitungtungam a panid",
-       "tooltip-pt-anontalk": "Pakitungtungan a maipapan ti panagurnos a naggapu ditoy nga IP a pagtaengan",
+       "tooltip-pt-anonuserpage": "Ti panid ti agar-aramat para iti daytoy nga IP a pagtaengan a kas ur-urnosem",
+       "tooltip-pt-mytalk": "Tungtungam a panid",
+       "tooltip-pt-anontalk": "Pakitungtungan a maipanggep kadagiti panagurnos manipud ti daytoy nga IP a pagtaengan",
        "tooltip-pt-preferences": "Dagiti kakaykayatam",
-       "tooltip-pt-watchlist": "Listaan dagiti panid a sipsiputem para iti panakabalbaliw",
-       "tooltip-pt-mycontris": "Listaan dagiti inaramidmo",
+       "tooltip-pt-watchlist": "Listaan dagiti panid a sipsiputem para iti pannakabalbaliw",
+       "tooltip-pt-mycontris": "Ti listaan dagiti kontribusionmo",
        "tooltip-pt-login": "Maisingasing a sumrekka; nupay kasta, daytoy ket saan a maipapilit",
        "tooltip-pt-logout": "Rummuar",
        "tooltip-ca-talk": "Pagtungtungan a maipapan ti linaon ti panid",
        "tooltip-ca-edit": "Mabalinmo nga urnosen daytoy a panid. Pangngaasi nga aramatem ti buton ti panagipadas sakbay nga agidulin",
        "tooltip-ca-addsection": "Mangirugi ti baro a paset",
        "tooltip-ca-viewsource": "Nasalakniban daytoy a panid.\nMabalinmo a kitaen ti taudanna.",
-       "tooltip-ca-history": "Dagiti napalabas a panagbalbaliw iti daytoy a panid.",
+       "tooltip-ca-history": "Dagiti napalabas a rebision iti daytoy a panid.",
        "tooltip-ca-protect": "Salakniban daytoy a panid",
        "tooltip-ca-unprotect": "Sukatan ti salaknib daytoy a panid",
        "tooltip-ca-delete": "Ikkaten daytoy a panid",
-       "tooltip-ca-undelete": "Isubli dagiti inurnos ti daytoy a panid sakbay idi naikkat",
+       "tooltip-ca-undelete": "Isubli dagiti inurnos a naaramid iti daytoy a panid sakbay idi naikkat",
        "tooltip-ca-move": "Iyalis daytoy a panid",
-       "tooltip-ca-watch": "Inayon daytoy a panid kadagiti bambantayam",
-       "tooltip-ca-unwatch": "Ikkatem daytoy a panid kadagiti bambantayam",
-       "tooltip-search": "Biruken idiay {{SITENAME}}",
+       "tooltip-ca-watch": "Inayon daytoy a panid iti listaan ti bambantayam",
+       "tooltip-ca-unwatch": "Ikkaten daytoy a panid manipud ti listan ti bambantayam",
+       "tooltip-search": "Agbiruk iti {{SITENAME}}",
        "tooltip-search-go": "Inka idiay panid nga adda kastoy a naganna no adda",
        "tooltip-search-fulltext": "Biruken dagiti panid para iti daytoy a testo",
        "tooltip-p-logo": "Sarungkaran ti umuna a panid",
        "tooltip-n-mainpage": "Sarungkaran ti umuna a panid",
        "tooltip-n-mainpage-description": "Sarungkaran ti umuna a panid",
-       "tooltip-n-portal": "Maipapan ti gandat, ti aniaman a maaramidam, no sadino ti pagbirukam kadagiti banbanag",
-       "tooltip-n-currentevents": "Agsapul iti lugar ti likud a pakaammo kadagiti agdama a paspasamak",
-       "tooltip-n-recentchanges": "Listaan dagiti naudi a sinukatan iti wiki.",
-       "tooltip-n-randompage": "Mangiparuar iti pugto a panid",
+       "tooltip-n-portal": "Maipapan ti gandat, ti aniaman a maaramidmo, no sadino ti pagbirukam kadagiti banbanag",
+       "tooltip-n-currentevents": "Agsapul ti pakaammo kadagiti agdama a paspasamak",
+       "tooltip-n-recentchanges": "Listaan dagiti naudi a sinukatan iti wiki",
+       "tooltip-n-randompage": "Agikarga iti pugto a panid",
        "tooltip-n-help": "Ti lugar a pagsapulan",
-       "tooltip-t-whatlinkshere": "Listaan ti am-amin a pampanid ti wiki a nakasilpo ditoy",
-       "tooltip-t-recentchangeslinked": "Kinaudian a sinukatan  dagiti panid a nakasilpo ditoy a panid",
+       "tooltip-t-whatlinkshere": "Listaan ti amin a pampanid ti wiki a nakasilpo ditoy",
+       "tooltip-t-recentchangeslinked": "Kaudian a balbaliw kadagiti panid a naisilpo manipud ti daytoy a panid",
        "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": "Kitaen ti listaan dagiti naaramid daytoy nga agar-aramat",
+       "tooltip-t-contributions": "Ti lstaan dagiti kontribusion iti daytoy nga agar-aramat",
        "tooltip-t-emailuser": "Patulodan ti esurat daytoy nga agar-aramat",
-       "tooltip-t-upload": "Agipan iti papeles",
+       "tooltip-t-upload": "Agikarga kadagiti papeles",
        "tooltip-t-specialpages": "Listaan ti amin nga espesial a pampanid",
-       "tooltip-t-print": "Maimaldit a bersion ti panid",
-       "tooltip-t-permalink": "Agnanayon a silpo ti daytoy a panagbaliw ti panid",
+       "tooltip-t-print": "Maimaldit a bersion iti daytoy a panid",
+       "tooltip-t-permalink": "Permanente a silpo iti daytoy a rebision ti panid",
        "tooltip-ca-nstab-main": "Kitaen ti naglaon a panid",
        "tooltip-ca-nstab-user": "Kitaen ti panid ti agar-aramat",
        "tooltip-ca-nstab-media": "Kitaen ti panid ti midia",
-       "tooltip-ca-nstab-special": "Maysa daytoy nga espesial a panid, saanmo a mismo a maurnos daytoy a panid",
+       "tooltip-ca-nstab-special": "Daytoy ket espesial a panid, saanmo a mismo a maurnos daytoy a panid",
        "tooltip-ca-nstab-project": "Kitaen ti panid ti gandat",
        "tooltip-ca-nstab-image": "Kitaen ti panid ti papeles",
        "tooltip-ca-nstab-mediawiki": "Kitaen ti mensahe ti sistema",
        "tooltip-ca-nstab-category": "Kitaen ti panid ti kategoria",
        "tooltip-minoredit": "Markaan daytoy a kas bassit a panag-urnos",
        "tooltip-save": "Idulin dagiti sinukatam",
-       "tooltip-preview": "Ipadas dagiti sinukatam, pangngaasim nga usarem daytoy sakbay nga idulinmo ti panid!",
+       "tooltip-preview": "Ipadas dagiti sinukatam, pangngaasi nga usarem daytoy sakbay nga idulin ti panid!",
        "tooltip-diff": "Ipakita no ania dagiti sinukatan nga inaramidmo iti testo",
-       "tooltip-compareselectedversions": "Kitaen ti naggidiatan dagiti dua a napili a bersion ti daytoy a panid.",
-       "tooltip-watch": "Inayon daytoy a panid idiay listaan dagiti bambantayam",
+       "tooltip-compareselectedversions": "Kitaen ti naggidiatan dagiti dua a napili a bersion iti daytoy a panid.",
+       "tooltip-watch": "Inayon daytoy a panid iti listaan ti bambantayam",
        "tooltip-watchlistedit-normal-submit": "Ikkaten dagiti titulo",
        "tooltip-watchlistedit-raw-submit": "Pabaruen ti listaan ti bambantayan",
-       "tooltip-recreate": "Aramidem manen ti panid urayno dati a naikkat.",
-       "tooltip-upload": "Rugian ti agip-ipan",
-       "tooltip-rollback": "\"Baliktaden\"   isubli ti inurnos (dagiti inurnos) ti daytoy a panid ti kinaudi a nangaramid iti maysa a takla",
-       "tooltip-undo": "\"Ibabawi\" ipasubli daytoy nga urnos ken lukatanna ti kinabuklan ti urnos iti panagpadas. Agpabalin daytoy a mangikabil ti rason idiay pinakabuklan.",
+       "tooltip-recreate": "Partuaten manen ti panid urayno dati a naikkat.",
+       "tooltip-upload": "Irugi ti panagikarga",
+       "tooltip-rollback": "\"Baliktaden\"  isubli ti inurnos (dagiti inurnos) iti daytoy a panid iti naudi a kontributor iti maysa a pindut",
+       "tooltip-undo": "\"Ibabawi\" ipasubli daytoy nga urnos ken lukatanna ti porma ti pagurnosan iti panagpadas a moda. Mangpalubos daytoy ti agikabil ti rason iti pakabuklan.",
        "tooltip-preferences-save": "Idulin dagiti kakaykayatam",
-       "tooltip-summary": "Ikabil ti bassit a pakabuklan",
-       "anonymous": "Di am-ammo {{PLURAL:$1|nga agar-aramat|kadagiti agar-aramat}} iti {{SITENAME}}",
+       "tooltip-summary": "Agikabil ti bassit a pakabuklan",
+       "anonymous": "Di ammo {{PLURAL:$1|nga agar-aramat|kadagiti agar-aramat}} iti {{SITENAME}}",
        "siteuser": "{{SITENAME}} nga agar-aramat $1",
-       "anonuser": "{{SITENAME}} di amammo nga agar-aramat $1",
-       "lastmodifiedatby": "Daytoy a panid ket naudi a binalbaliwan idi $2, $1 ni $3.",
+       "anonuser": "{{SITENAME}} di ammo nga agar-aramat $1",
+       "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",
-       "anonusers": "{{SITENAME}} di am-ammo {{PLURAL:$2|nga agar-aramat|a digiti agar-aramat}} $1",
-       "creditspage": "Dagiti pagdaydayaw ti panid",
-       "nocredits": "Awan dagiti pakaammo ti pammadayaw nga adda ditoy a panid.",
-       "spamprotectiontitle": "Panagsalaknib a sagat  para ti spam",
-       "spamprotectiontext": "Ti testo a kayatmo nga idulin ket sinerraan ti sagat ti spam.\nDaytoy ket mabalin a gapuanan babaen ti silpo a naiparit ti akin ruar a pagsaadan.",
-       "spamprotectionmatch": "Ti sumaganad a testo ti nangirugi ti sagat ti spam: $1",
-       "spambot_username": "Panagdalus iti MediaWiki spam",
-       "spam_reverting": "Ipasubli ti kinaudi a panagbaliw nga awan dagiti linaon a silpo idiay $1",
-       "spam_blanking": "Dagiti amin a panagbaliw ket aglaon kadagiti silpo idiay $1, iblanko",
-       "spam_deleting": "Dagiti amin a panagbaliw ket naglaon kadagiti silpo idiay $1, ik-ikkaten",
-       "simpleantispam-label": "Kontra-spam a panagkita.\n '''Saan''' a suratan daytoy!",
+       "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.",
+       "spamprotectiontitle": "Panagsalaknib a sagat para iti spam",
+       "spamprotectiontext": "Ti testo a kayatmo nga idulin ket sinerraan babaen ti sagat ti spam.\nDaytoy ket mabalin a gapuanan babaen ti silpo a naiparit ti akin ruar a sitio.",
+       "spamprotectionmatch": "Ti sumaganad a testo ket isu ti nangkalbit ti sagat ti spam: $1",
+       "spambot_username": "Panagdalus iti spam ti MediaWiki",
+       "spam_reverting": "Ipasubli ti naudi a rebision nga awan dagiti linaon a silpo iti $1",
+       "spam_blanking": "Amin dagiti rebision ket aglaon kadagiti silpo iti $1, iblanko",
+       "spam_deleting": "Amin dagiti rebision ket aglaon kadagiti silpo iti $1, ik-ikkaten",
+       "simpleantispam-label": "Pammasingked ti anti-spam.\n<strong>SAAN</strong> a kargaan daytoy!",
        "pageinfo-title": "Pakaammo para iti \"$1\"",
-       "pageinfo-not-current": "Pasensia, saan a mabalin ti mangited ti pakaammo para kadagiti daan a panagbalbaliw.",
+       "pageinfo-not-current": "Pasensia, saan a mabalin ti mangited ti pakaammo para kadagiti daan a rebision.",
        "pageinfo-header-basic": "Kangrunaan a pakaammo",
        "pageinfo-header-edits": "Pakasaritaan ti inurnos",
        "pageinfo-header-restrictions": "Panagsalaknib ti panid",
        "pageinfo-redirects-name": "Bilang dagiti baw-ing iti daytoy a panid",
        "pageinfo-subpages-name": "Bilang dagiti subpanid iti daytoy a panid",
        "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|baw-ing|bawbaw-ing}}; $3 {{PLURAL:$3|saan a baw-ing|saan a bawbaw-ing}})",
-       "pageinfo-firstuser": "Nagpartuat ti panid",
+       "pageinfo-firstuser": "Nagpartuat iti panid",
        "pageinfo-firsttime": "Petsa a pannakapartuat ti panid",
-       "pageinfo-lastuser": "Kinaudi a nagurnos",
+       "pageinfo-lastuser": "Kinaudi nga editor",
        "pageinfo-lasttime": "Petsa ti kinaudi a panag-urnos",
        "pageinfo-edits": "Dagup a bilang dagiti inurnos",
        "pageinfo-authors": "Dagup a bilang dagiti naisangsangayan a mannurat",
        "pageinfo-templates": "Nailak-am {{PLURAL:$1|a plantilia|a planplantilia}} ($1)",
        "pageinfo-transclusions": "{{PLURAL:$1|Panid|Pampanid}} a nakailak-aman ($1)",
        "pageinfo-toolboxlink": "Pakaammo ti panid",
-       "pageinfo-redirectsto": "Maibaw-ing idiay",
+       "pageinfo-redirectsto": "Maibaw-ing iti",
        "pageinfo-redirectsto-info": "pakaammo",
        "pageinfo-contentpage": "Naibilang a kas naglaon a panid",
        "pageinfo-contentpage-yes": "Wen",
        "pageinfo-protect-cascading": "Dagiti panagsalaknib ket agsariap manipud ditoy",
        "pageinfo-protect-cascading-yes": "Wen",
-       "pageinfo-protect-cascading-from": "Dagiti panagsalaknib ket agsariap manipud idiay",
+       "pageinfo-protect-cascading-from": "Dagiti panagsalaknib ket agsariap manipud ti",
        "pageinfo-category-info": "Pakaammo ti kategoria",
        "pageinfo-category-pages": "Bilang dagiti panid",
        "pageinfo-category-subcats": "Bilang dagiti subkategoria",
        "markaspatrolleddiff": "Markaan a kas napatruliaan",
        "markaspatrolledtext": "Markaan daytoy a panid a kas napatruliaan",
        "markedaspatrolled": "Markaan a kas napatruliaan",
-       "markedaspatrolledtext": "Ti napili a panagbaliw iti [[:$1]] ket namarkaan a kas napatrulian.",
-       "rcpatroldisabled": "Nabaldado ti panagpatrulia kadagiti kinaudi a pinagbaliw",
-       "rcpatroldisabledtext": "Dagiti langa a patrulia ti kinaudi a pinagbaliw ket agdama a nabaldado",
+       "markedaspatrolledtext": "Ti napili a rebision iti [[:$1]] ket namarkaan a kas napatrulian.",
+       "rcpatroldisabled": "Nabaldado ti panagpatrulia iti kaudian balbaliw",
+       "rcpatroldisabledtext": "Dagiti langa ti patrulia iti kaudian a balbaliw ket agdama a nabaldado.",
        "markedaspatrollederror": "Madi a mamarkaan a kas napatruliaan",
        "markedaspatrollederrortext": "Nasken a naganam ti maysa a rebision tapno mamarkaan a kas napatruliaan.",
        "markedaspatrollederror-noautopatrol": "Saanmo a mabalin a markaan dagita sinukatam a kas napatruliaan.",
-       "markedaspatrollednotify": "Daytoy a panagbaliw ti $1 ket namarkaanen a kas napatruliaan.",
+       "markedaspatrollednotify": "Daytoy a panagbaliw iti $1 ket namarkaanen a kas napatruliaan.",
        "markedaspatrollederrornotify": "Ti panagmarka a kas napatruliaan ket napaay.",
        "patrol-log-page": "Listaan ti napatruliaan",
-       "patrol-log-header": "Daytoy ket listaan dagiti napatruliaan a panagbabaliw.",
+       "patrol-log-header": "Daytoy ket listaan dagiti napatruliaan a rebision.",
        "log-show-hide-patrol": "$1 listaan ti napatruliaan",
-       "deletedrevision": "Naikkat ti daan a binaliwan $1",
+       "deletedrevision": "Naikkat a daan a rebision ti $1",
        "filedeleteerror-short": "Biddut ti panakaikkat ti papeles: $1",
        "filedeleteerror-long": "Adda nasarakan a biddut idi agikikkat ti papeles:\n\n$1",
-       "filedelete-missing": "Ti papeles \"$1\" ket saan a maikkat, ngamin ket awanen dita.",
-       "filedelete-old-unregistered": "Ti nainagan a pinagbaliw ti papeles \"$1\" ket awan idiay database.",
-       "filedelete-current-unregistered": "Ti nainagan a papeles \"$1\" ket awan idiay database.",
-       "filedelete-archive-read-only": "Ti pagidulinan a direktorio \"$1\" ket saan a masuratan ti webserver.",
-       "previousdiff": "← Napalabas a naurnos",
-       "nextdiff": "Sumaruno a naurnos →",
-       "mediawarning": "'''Ballaag'': Daytoy a papeles ket naglaon ti dakes a kodigo.\nNo usarem daytoy, baka makompromiso ti sistema.",
-       "imagemaxsize": "Ti patingga a kadakkel ti papeles:<br />''(para dagiti pagpalpalawag ti papeles a panid)''",
+       "filedelete-missing": "Ti papeles ti \"$1\" ket saan a maikkat, ngamin ket awanen dita.",
+       "filedelete-old-unregistered": "Ti nainagan a rebison ti papeles ti \"$1\" ket awan iti database.",
+       "filedelete-current-unregistered": "Ti nainagan a papeles ti \"$1\" ket awan iti database.",
+       "filedelete-archive-read-only": "Ti arkibo a direktorio ti \"$1\" ket saan a masuratan babaen ti webserver.",
+       "previousdiff": "← Nadadaan nga urnos",
+       "nextdiff": "Barbaro nga urnos →",
+       "mediawarning": "<strong>Ballaag:</strong> Daytoy a papeles ket naglaon ti dakes a kodigo.\nNo usarem daytoy, baka makompromiso ti sistema.",
+       "imagemaxsize": "Ti patingga a kadakkel ti papeles:<br /><em>(para kadagiti panid ti deskripsion ti papeles)</em>",
        "thumbsize": "Rukod ti bassit a ladawan:",
        "widthheightpage": "$1 × $2, $3 a {{PLURAL:$3|panid|pampanid}}",
        "file-info": "kadakkel ti papeles: $1, MIME a kita: $2",
        "show-big-image-other": "Sabali {{PLURAL:$2|a resolusion|kadagiti resolusion}}: $1.",
        "show-big-image-size": "$1 × $2 dagiti piksel",
        "file-info-gif-looped": "nasiluan",
-       "file-info-gif-frames": "$1 {{PLURAL:$1|a kuadro| kadagiti kuadro}}",
+       "file-info-gif-frames": "$1 {{PLURAL:$1|a kuadro|a kuadkuadro}}",
        "file-info-png-looped": "nasiluan",
        "file-info-png-repeat": "inay-ayam ti $1 {{PLURAL:$1|a beses|a besbeses}}",
-       "file-info-png-frames": "$1 {{PLURAL:$1|a kuadro| kadagiti kuadro}}",
-       "file-no-thumb-animation": "'''Paammo: Gapu kadagiti teknikal a pannakaipatingga, dagiti bassit a ladawan ti daytoy a papeles ket saanto a maanimado.'''",
-       "file-no-thumb-animation-gif": "'''Paammo: Gapu kadagiti teknikal a pannakaipatingga, dagiti bassit a ladawan ti nangato a resolusion dagiti GIF a ladawan a kas daytoy ket saanto a maanimado.'''",
-       "newimages": "Galeria dagiti kabarbaro a papeles",
-       "imagelisttext": "Adda dita baba ti listaan ti ''$1''' {{PLURAL:$1|a papeles|dagiti papeles}} a nailasin a kas $2.",
-       "newimages-summary": "Daytoy nga espesial a panid ket ipakitana ti kinaudi a pinag-ipan kadagiti papeles.",
+       "file-info-png-frames": "$1 {{PLURAL:$1|a kuadro| a kuadkuadro}}",
+       "file-no-thumb-animation": "<strong>Nota: Gapu kadagiti teknikal a pannakaipatingga, dagiti bassit a ladawan iti daytoy a papeles ket saanto a maanimado.</strong>",
+       "file-no-thumb-animation-gif": "<strong>Nota: Gapu kadagiti teknikal a pannakaipatingga, dagiti bassit a ladawan ti nangato a resolusion dagiti GIF a ladawan a kas daytoy ket saanto a maanimado.</strong>",
+       "newimages": "Galeria dagiti baro a papeles",
+       "imagelisttext": "Adda dita baba ti listaan ti <strong>$1</strong> {{PLURAL:$1|a papeles|a pappapeles}} a nailasin a kas $2.",
+       "newimages-summary": "Daytoy nga espesial a panid ket ipakitana ti naudi a panagikarga kadagiti papeles.",
        "newimages-legend": "Sagat",
-       "newimages-label": "Nagan ti papeles (wenno paset na) :",
+       "newimages-label": "Nagan ti papeles (wenno pasetna) :",
        "newimages-showbots": "Ipakita dagiti naikarga babaen dagiti bot",
        "noimages": "Awan ti makita.",
        "ilsubmit": "Biruken",
        "bydate": "babaen ti petsa",
-       "sp-newimages-showfrom": "Iparang dagiti baro a papeles mangrugi iti $2, $1",
-       "seconds": "{{PLURAL:$1|$1 segundo|$1 segundo}}",
-       "minutes": "{{PLURAL:$1|$1 minuto|$1 minutos}}",
+       "sp-newimages-showfrom": "Iparang dagiti baro a papeles a mangrugi manipud idi $2, $1",
+       "seconds": "{{PLURAL:$1|$1 a segundo|$1 a segsegundo}}",
+       "minutes": "{{PLURAL:$1|$1 a minuto|$1 a minminuto}}",
        "hours": "{{PLURAL:$1|$1 nga oras|$1 nga or-oras}}",
        "days": "{{PLURAL:$1|$1 nga aldaw|$1 nga al-aldaw}}",
        "weeks": "{{PLURAL:$1|$1 a lawas|$1 a law-lawas}}",
        "months": "{{PLURAL:$1|$1 a bulan|$1 a bulbulan}}",
        "years": "{{PLURAL:$1|$1 a tawen|$1 a tawtawen}}",
-       "ago": "$1 nagtapos",
+       "ago": "nagtapos idi $1",
        "just-now": "tatta laeng",
-       "hours-ago": "$1 nga {{PLURAL:$1|oras|or-oras}} ti napalabas",
-       "minutes-ago": "$1 a {{PLURAL:$1|minuto|minutos}} ti napalabas",
-       "seconds-ago": "$1 a {{PLURAL:$1|segundo|seg-segundo}} ti napalabas",
-       "monday-at": "Lunes idiay $1",
-       "tuesday-at": "Martes idiay $1",
-       "wednesday-at": "Mierkoles idiay $1",
-       "thursday-at": "Huebes idiay $1",
-       "friday-at": "Biernes idiay $1",
-       "saturday-at": "Sabado idiay $1",
-       "sunday-at": "Dominggo idiay $1",
-       "yesterday-at": "Idi kalman idiay $1",
-       "bad_image_list": "Ti kinabuklan ket kas iti sumaganad:\n\nDagiti laeng banag iti listaan (linlinia a mangrugi iti *) ti mabalin.\nTi umuna a silpo iti maysa a linia ket nasken a nakasilpo iti maysa a saan a nasayaat a papeles.\nAnia man a sumarsaruno a silsilpo iti isu met laeng a linia ket maikonsidera kas mailaksid, kas pagarigan, dagiti panid a pakasarakan ti papeles a kas nakalinia.",
+       "hours-ago": "$1 nga {{PLURAL:$1|oras|or-oras}} ti nagtapos",
+       "minutes-ago": "$1 a {{PLURAL:$1|minuto|minminuto}} ti nagtapos",
+       "seconds-ago": "$1 a {{PLURAL:$1|segundo|segsegundo}} ti nagtapos",
+       "monday-at": "Lunes iti $1",
+       "tuesday-at": "Martes iti $1",
+       "wednesday-at": "Mierkoles iti $1",
+       "thursday-at": "Huebes iti $1",
+       "friday-at": "Biernes iti $1",
+       "saturday-at": "Sabado iti $1",
+       "sunday-at": "Domingo iti $1",
+       "yesterday-at": "Idi kalman iti $1",
+       "bad_image_list": "Ti pormat ket kas iti sumaganad:\n\nDagiti laeng banag iti listaan (linlinia a mangrugi iti *) ti mabalin.\nTi umuna a silpo iti maysa a linia ket nasken a nakasilpo iti maysa a saan a nasayaat a papeles.\nAnia man a sumarsaruno a silsilpo iti isu met laeng a linia ket maikonsidera kas mailaksid, kas pagarigan, dagiti panid a pakasarakan ti papeles a kas nakalinia.",
        "metadata": "Metadata",
        "metadata-help": "Daytoy a papeles ket naglaon ti naipatinayon a pakaammo, a mabalin a nainayon manipud ti dihital a kamera wenno skanner a naaramat a pangpartuat wenno pang-digitize itoy.\nNo ti papeles ket saan a nabalbaliwan manipud iti kasisigud a kasasaad, adda dagiti sumagmamano a salaysay a mabalin a saan a napno a maipakita ti nabaliwan a papeles.",
        "metadata-expand": "Ipakita dagiti napaatiddog a salaysay",
        "exif-orientation": "Pagturongan",
        "exif-samplesperpixel": "Bilang dagiti komponente",
        "exif-planarconfiguration": "Pannaka-urnos ti datos",
-       "exif-ycbcrsubsampling": "Subsampling ratio ti Y iti C",
+       "exif-ycbcrsubsampling": "Subwadan pannakaibagi ti Y iti C",
        "exif-ycbcrpositioning": "Y ken C a panakaipatakderan",
        "exif-xresolution": "Horisontal a resolusion",
-       "exif-yresolution": "nakatakder a resolusion",
-       "exif-stripoffsets": "Lokasion ti datos ti imahen",
-       "exif-rowsperstrip": "Bilang ti ar-aray tunggal maysa a strip",
-       "exif-stripbytecounts": "Bytes per compressed strip",
-       "exif-jpeginterchangeformat": "Offset to JPEG SOI",
-       "exif-jpeginterchangeformatlength": "Bytes ti JPEG a datos",
-       "exif-whitepoint": "White point chromaticity",
-       "exif-primarychromaticities": "Chromaticities dagiti primarities",
-       "exif-referenceblackwhite": "Reperensia a kuwenta iti agparis a nangisit ken puraw",
+       "exif-yresolution": "Bertikal a resolusion",
+       "exif-stripoffsets": "Lokasion ti datos ti ladawan",
+       "exif-rowsperstrip": "Bilang ti ar-aray tunggal maysa a pirgis",
+       "exif-stripbytecounts": "Dagiti byte tunggal maysa a natalmegan  a pirgis",
+       "exif-jpeginterchangeformat": "Timbengan iti JPEG SOI",
+       "exif-jpeginterchangeformatlength": "Dagiti byte ti datos ti JPEG",
+       "exif-whitepoint": "Kromatisidad ti puntos ti puraw",
+       "exif-primarychromaticities": "Dagiti kromasidad dagiti primaridad",
+       "exif-referenceblackwhite": "Reperensia a patpateg iti agparis a nangisit ken puraw",
        "exif-datetime": "Panagsukat ti papeles ti petsa ken oras",
-       "exif-imagedescription": "Titulo ti imahen",
+       "exif-imagedescription": "Titulo ti ladawan",
        "exif-make": "Nangpartuat iti kamera",
        "exif-model": "Modelo ti kamera",
-       "exif-software": "Naaramat a software",
+       "exif-software": "Naaramat a sopwer",
        "exif-artist": "Mannurat",
-       "exif-copyright": "Nakatengngel iti kaberngan ti kopia",
-       "exif-exifversion": "Exif a bersion",
-       "exif-flashpixversion": "Nasuportaran a Flashpix a bersion",
-       "exif-colorspace": "Kolor ti lugar",
-       "exif-componentsconfiguration": "Ti kayat a saoen ti tunggal maysa a nagyan",
-       "exif-compressedbitsperpixel": "Moda ti kompresion ti imahen",
-       "exif-pixelydimension": "Kaaba ti imahen",
-       "exif-pixelxdimension": "Katayag ti imahen",
+       "exif-copyright": "Nakatengngel iti karbengan ti kopia",
+       "exif-exifversion": "Bersion ti Exif",
+       "exif-flashpixversion": "Nasuportaran a bersion ti Flashpix",
+       "exif-colorspace": "Espasio ti maris",
+       "exif-componentsconfiguration": "Kaibuksilan iti tunggal maysa a komponente",
+       "exif-compressedbitsperpixel": "Moda ti kompresion ti ladawan",
+       "exif-pixelydimension": "Kaakaba ti ladawan",
+       "exif-pixelxdimension": "Katayag ti ladawan",
        "exif-usercomment": "Dagiti komentario ti agar-aramat",
-       "exif-relatedsoundfile": "Mainaig nga nangnangeg a papeles",
-       "exif-datetimeoriginal": "Petsa ken oras ti panakaaramid ti datos",
-       "exif-datetimedigitized": "Petsa ken oras ti panang-digitizing",
+       "exif-relatedsoundfile": "Mainaig a papeles ti audio",
+       "exif-datetimeoriginal": "Petsa ken oras ti pannakaaramid ti datos",
+       "exif-datetimedigitized": "Petsa ken oras ti panang-dihitado",
        "exif-subsectime": "DateTime subseconds",
        "exif-subsectimeoriginal": "DateTimeOriginal subseconds",
        "exif-subsectimedigitized": "DateTimeDigitized subseconds",
        "exif-gpstrackref": "Reperensia iti direksion ti panaggunay",
        "exif-gpstrack": "Direksion ti kuti",
        "exif-gpsimgdirectionref": "Reperensia iti direksion ti imahen",
-       "exif-gpsimgdirection": "Direksion ti imahen",
-       "exif-gpsmapdatum": "Naaramat a geodetic survey data",
-       "exif-gpsdestlatituderef": "Reperensia iti latitude a papanan",
-       "exif-gpsdestlatitude": "Latitude ti papanan",
-       "exif-gpsdestlongituderef": "Reperensia iti longitude a papanan",
-       "exif-gpsdestlongitude": "Longitude ti papanan",
+       "exif-gpsimgdirection": "Direksion ti ladawan",
+       "exif-gpsmapdatum": "Datos nga inaramat ti geodetiko a panagsukimat",
+       "exif-gpsdestlatituderef": "Reperensia iti papanan a latitud",
+       "exif-gpsdestlatitude": "Papanan a latitud",
+       "exif-gpsdestlongituderef": "Reperensia iti papanan a longitud",
+       "exif-gpsdestlongitude": "Papanan a longitud",
        "exif-gpsdestbearingref": "Reperensia iti dalan a papanan",
        "exif-gpsdestbearing": "Dalan ti papanan",
        "exif-gpsdestdistanceref": "Reperensia ti kaadayo  ti papanan",
-       "exif-gpsdestdistance": "Kaadayo iti papanan na",
-       "exif-gpsprocessingmethod": "Nagan ti kastoy a pinagaramid ti GPS",
-       "exif-gpsareainformation": "Nagan ti GPS area",
+       "exif-gpsdestdistance": "Kaadayo iti papanan",
+       "exif-gpsprocessingmethod": "Nagan ti panagproseo a pamay-an ti GPS",
+       "exif-gpsareainformation": "Nagan ti lugar ti GPS",
        "exif-gpsdatestamp": "Petsa ti GPS",
-       "exif-gpsdifferential": "Nasimpa apaggiddiatan ti GPS",
-       "exif-jpegfilecomment": "Komento ti JPEG a papeles",
-       "exif-keywords": "Nangnangruna a bal-balikas",
-       "exif-worldregioncreated": "Ti parte ti lubong nga nakaalaan ti litrato",
-       "exif-countrycreated": "Ti pagilian nga nakaalaan ti litrato",
-       "exif-countrycodecreated": "Kodigo ti pagilian nga nakaalaan ti litrato",
-       "exif-provinceorstatecreated": "Probinsia wenno estado nga nakaalaan ti litrato",
-       "exif-citycreated": "Ti siudad nga nakaalaan ti litrato",
+       "exif-gpsdifferential": "Nasimpa a paggiddiatan ti GPS",
+       "exif-jpegfilecomment": "Komentario ti papeles ti JPEG",
+       "exif-keywords": "Nangruna a balbalikas",
+       "exif-worldregioncreated": "Rehion ti lubong a nakaalaan ti retrato",
+       "exif-countrycreated": "Pagilian a nakaalaan ti retrato",
+       "exif-countrycodecreated": "Kodigo ti pagilian a nakaalaan ti retrato",
+       "exif-provinceorstatecreated": "Probinsia wenno estado a nakaalaan ti retrato",
+       "exif-citycreated": "Siudad a nakaalaan ti retrato",
        "exif-sublocationcreated": "Sabali pay a lokasion ti siudad a nakaalaan ti retrato",
-       "exif-worldregiondest": "Paset ti lubong a naipakita",
+       "exif-worldregiondest": "Rehion ti lubong a naipakita",
        "exif-countrydest": "Naipakita a pagilian",
-       "exif-countrycodedest": "Kodigo ti pagilian a naipakita",
+       "exif-countrycodedest": "Kodigo para ti pagilian a naipakita",
        "exif-provinceorstatedest": "Probinsia wenno estado a naipakita",
        "exif-citydest": "Naipakita a siudad",
-       "exif-sublocationdest": "Sabali pay a lokasion ti siudad a naipakita",
-       "exif-objectname": "Pandek a titulo",
+       "exif-sublocationdest": "Sublokasion ti siudad a naipakita",
+       "exif-objectname": "Ababa a titulo",
        "exif-specialinstructions": "Kangrunaan a panagipalpalawag",
        "exif-headline": "Paulo",
        "exif-credit": "Pammadayaw/Nangted",
        "exif-source": "Taudan",
-       "exif-editstatus": "Panagurnos a kasasaad ti imahen",
+       "exif-editstatus": "Panagurnos a kasasaad ti ladawan",
        "exif-urgency": "Ganat",
        "exif-fixtureidentifier": "Nagan ti naikabit a banag",
        "exif-locationdest": "Lugar a naibaga",
        "exif-iimversion": "Bersion ti IIM",
        "exif-iimcategory": "Kategoria",
        "exif-iimsupplementalcategory": "Dagiti sabali pay a kategoria",
-       "exif-datetimeexpires": "Saan nga usaren ti kallabes nga",
+       "exif-datetimeexpires": "Saan nga usaren kalpasanna",
        "exif-datetimereleased": "Nakairuar idi",
-       "exif-originaltransmissionref": "Kinasigud a pinagipatulod iti kodigo ti papanan",
-       "exif-identifier": "Panagilasin",
+       "exif-originaltransmissionref": "Kasisigud a transmision ti kodigo ti lokasion",
+       "exif-identifier": "Panangilasin",
        "exif-lens": "Lente nga inusar",
        "exif-serialnumber": "Agsasaruno a numero ti kamera",
        "exif-cameraownername": "Akinkukua ti kamera",
        "exif-label": "Etiketa",
        "exif-datetimemetadata": "Petsa ti kinaudi a panagbaliw ti metadata",
-       "exif-nickname": "Di pormal a nagan ti imahen",
-       "exif-rating": "Pategan (ti maysa kadagiti  5)",
-       "exif-rightscertificate": "Paneknek ti panagtaripatu dagiti karbengan",
-       "exif-copyrighted": "Kasasaad ti karbengan-panagipablaak",
-       "exif-copyrightowner": "Akinkukua ti kaberngan-pinagipablaak",
-       "exif-usageterms": "Panag-uasar a ban-banag",
-       "exif-webstatement": "Sarita ti insao ti karbengan ti kopia nga addan ti online",
-       "exif-originaldocumentid": "Naisangsangyan nga ID iti kinasigud a dokumento",
-       "exif-licenseurl": "URL iti ti karbengan ti kopia a lisensia",
+       "exif-nickname": "Di pormal a nagan ti ladwan",
+       "exif-rating": "Pategan (ti maysa kadagiti 5)",
+       "exif-rightscertificate": "Sertipikado ti panagtaripato kadagiti karbengan",
+       "exif-copyrighted": "Kasasaad ti karbengan ti kopia",
+       "exif-copyrightowner": "Akinkukua ti karbengan ti kopia",
+       "exif-usageterms": "Dagiti termino ti panag-usar",
+       "exif-webstatement": "Insasao ti karbengan ti kopia nga addaan iti online",
+       "exif-originaldocumentid": "Naisangayan nga ID iti kinasigud a dokumento",
+       "exif-licenseurl": "URL para iti lisensia ti karbengan ti kopia",
        "exif-morepermissionsurl": "Sabali a pakaammo ti lisensia",
-       "exif-attributionurl": "No usaren manen daytoy nga obra, pangngaasi nga agisilpo idiay",
-       "exif-preferredattributionname": "No usaren manen daytoy nga obra, pangngaasi a padayawen ni",
-       "exif-pngfilecomment": "Komentario ti PNG a papeles",
+       "exif-attributionurl": "No usaren manen daytoy nga obra, pangngaasi nga isilpo iti",
+       "exif-preferredattributionname": "No usaren manen daytoy nga obra, pangngaasi a padayawan ni",
+       "exif-pngfilecomment": "Komentario ti papeles ti PNG",
        "exif-disclaimer": "Renunsia",
-       "exif-contentwarning": "Ballaag ti nagyan",
-       "exif-giffilecomment": "Komentario ti GIF a papeles",
+       "exif-contentwarning": "Ballaag ti linaon",
+       "exif-giffilecomment": "Komentario ti papeles ti GIF",
        "exif-intellectualgenre": "Kita ti banag",
        "exif-subjectnewscode": "Kodigo ti suheto",
-       "exif-scenecode": "Buya ti kodigo nga IPTC",
-       "exif-event": "Paspasamak a naibaga",
-       "exif-organisationinimage": "Kaurnusan a naibaga",
-       "exif-personinimage": "Ti tao a naibaga",
-       "exif-originalimageheight": "Kangato ti imahen sakbay nga naputed",
-       "exif-originalimagewidth": "Kalawa ti imahen sakbay nga naputed",
+       "exif-scenecode": "Buya ti kodigo ti IPTC",
+       "exif-event": "Pasamak a naibaga",
+       "exif-organisationinimage": "Gunglo a naibaga",
+       "exif-personinimage": "Tao a naibaga",
+       "exif-originalimageheight": "Katayag ti ladawan sakbay a naputed",
+       "exif-originalimagewidth": "Kaakaba ti ladawan sakbay a naputed",
        "exif-compression-1": "Saan a napespes",
-       "exif-copyrighted-true": "Nakarbengan a kopia",
-       "exif-copyrighted-false": "Saan a naiyasentar ti kasasaad ti karbengan ti kopia",
+       "exif-copyrighted-true": "Nakarbengan ti kopia",
+       "exif-copyrighted-false": "Saan a naisaad ti kasasaad ti karbengan ti kopia",
        "exif-unknowndate": "Di ammo a petsa",
        "exif-orientation-1": "Kadawyan",
-       "exif-orientation-2": "Binaliktad a nagilad",
+       "exif-orientation-2": "Horisontal a binaliktad",
        "exif-orientation-3": "Naipusipus iti 180°",
-       "exif-orientation-4": "Binaliktad nga agpangato",
-       "exif-orientation-5": "Naipisipus iti 90° CCW ken nabaliktad nga agtindek",
+       "exif-orientation-4": "Bertikal a binaliktad",
+       "exif-orientation-5": "Naipisipus iti 90° CCW ken bertikal a binaliktad",
        "exif-orientation-6": "Naipusipus iti 90° CCW",
-       "exif-orientation-7": "Naipisipus iti 90° CW ken nabaliktad nga agtindek",
+       "exif-orientation-7": "Naipisipus iti 90° CW ken bertikal a nabaliktad",
        "exif-orientation-8": "Naipusipus iti 90° CW",
        "exif-planarconfiguration-1": "chunky format",
        "exif-planarconfiguration-2": "planar format",
        "exif-exposureprogram-0": "Saan a naipalpalawag",
        "exif-exposureprogram-1": "Manual",
        "exif-exposureprogram-2": "Kadawyan a programa",
-       "exif-exposureprogram-3": "Aperture priority",
+       "exif-exposureprogram-3": "Prioridad ti apertura",
        "exif-exposureprogram-4": "Shutter priority",
        "exif-exposureprogram-5": "Kreatibo a programa (di nalinteg iti  kauneg ti pagikabilan)",
        "exif-exposureprogram-6": "Aktion a programa (di nalinteg iti kapartak ti napardas a shutter)",
-       "exif-exposureprogram-7": "Retrato a kita (para iti naasideg nga imahen nga addaan ti lugar ti likud a saan a nai-focus)",
-       "exif-exposureprogram-8": "Ladawan ti daga a kita (para iti ladawan ti daga nga imahen nga addaan ti lugar ti likud a pinag- focus)",
-       "exif-subjectdistance-value": "$1 a metro",
-       "exif-meteringmode-0": "Di am-ammo",
-       "exif-meteringmode-1": "Napipia",
+       "exif-exposureprogram-7": "Retrato a kita (para iti asideg a ladladawan nga addaan ti lugar ti likud a saan a naipatengnga)",
+       "exif-exposureprogram-8": "Moda ti ladawan ti daga (para iti ladawan ti daga a retato nga addaan ti lugar ti likud a panaptengna)",
+       "exif-subjectdistance-value": "$1 a metmetro",
+       "exif-meteringmode-0": "Di ammo",
+       "exif-meteringmode-1": "Natimbeng",
        "exif-meteringmode-2": "Napipia nga agtennga a pinadagsenan",
        "exif-meteringmode-3": "Disso",
        "exif-meteringmode-4": "Sabsabali a disso",
-       "exif-meteringmode-5": "Alagad",
+       "exif-meteringmode-5": "Tabas",
        "exif-meteringmode-6": "Sangkapaset laeng",
        "exif-meteringmode-255": "Sabali",
        "exif-lightsource-0": "Di ammo",
        "scarytranscludefailed": "[Napaay ti panagala ti plantilia para iti $1]",
        "scarytranscludefailed-httpstatus": "[Napaay ti panagala ti plantilia para iti $1: HTTP $2]",
        "scarytranscludetoolong": "[Atiddog unay ti URL]",
-       "deletedwhileediting": "'''Ballaag''': Naikkaten daytoy a panid kalpasan a rinugiam nga agurnos!",
+       "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.",
        "recreate": "Partuaten manen",
-       "confirm_purge_button": "OK",
+       "confirm_purge_button": "Sige",
        "confirm-purge-top": "Dalusan ti cache daytoy a panid?",
-       "confirm-purge-bottom": "Ti panagpurga ti panid ket dalusanna ti cache ken pursaranna nga agparang dagiti kinaudi a panagbaliw.",
-       "confirm-watch-button": "OK",
-       "confirm-watch-top": "Inayon daytoy a panid kadagiti bambantayam",
-       "confirm-unwatch-button": "OK",
-       "confirm-unwatch-top": "Ikkatem daytoy a panid ti bambantayam",
+       "confirm-purge-bottom": "Ti panagpurga ti panid ket dalusanna ti cache ken pursaranna nga iparang dagiti agdama rebision.",
+       "confirm-watch-button": "Sige",
+       "confirm-watch-top": "Inayon daytoy a panid iti listaan ti bambantayam?",
+       "confirm-unwatch-button": "Sige",
+       "confirm-unwatch-top": "Ikkatem daytoy a panid manipud ti listaan ti bambantayam?",
        "imgmultipageprev": "← napalabas a panid",
        "imgmultipagenext": "sumaruno a panid →",
        "imgmultigo": "Inkan!",
        "table_pager_prev": "Napalabas a panid",
        "table_pager_first": "Umuna a panid",
        "table_pager_last": "Maudi a panid",
-       "table_pager_limit": "Mangipakita iti $1 a banag tunggal maysa  a panid",
+       "table_pager_limit": "Mangipakita iti $1 a banag tunggal maysa a panid",
        "table_pager_limit_label": "Banag tunggal maysa a panid:",
        "table_pager_limit_submit": "Inkan",
        "table_pager_empty": "Awan dagiti nagbanagan",
        "autosumm-blank": "Naikkat amin ti linaon ti panid",
-       "autosumm-replace": "Sinukatan ti linaon iti '$1'",
+       "autosumm-replace": "Sinukatan ti linaon iti \"$1\"",
        "autoredircomment": "Naibaw-ing ti panid iti [[$1]]",
        "autosumm-new": "Pinartuat ti panid iti \"$1\"",
-       "lag-warn-normal": "Dagiti panangbalbaliw a nabarbaro ngem $1 {{PLURAL:$1|a segundo|kadagiti segundo}} ket mabalin a saan a maiparang itoy a listaan.",
-       "lag-warn-high": "Gapu ti kinabuntog ti database server, dagiti nasukatan a barbaro ngem $1 {{PLURAL:$1|a segundo|kadagiti segundo}} ket mabalin a saan nga agparang ditoy a listaan.",
-       "watchlistedit-normal-title": "Urnosem ti listaan ti bambantayan",
+       "autosumm-newblank": "Nagpartuat ti blanko a panid",
+       "lag-warn-normal": "Dagiti panangbalbaliw a nabarbaro ngem $1 {{PLURAL:$1|a segundo|a segsegundo}} ket mabalin a saan a maiparang iti daytoy a listaan.",
+       "lag-warn-high": "Gapu ti kinabuntog ti database server, dagiti nasukatan a barbaro ngem $1 {{PLURAL:$1|a segundo|a segegundo}} ket mabalin a saan nga agparang iti daytoy a listaan.",
+       "watchlistedit-normal-title": "Urnosen ti listaan ti bambantayan",
        "watchlistedit-normal-legend": "Ikkaten dagiti titulo manipud ti listaan ti bambantayam",
-       "watchlistedit-normal-explain": "Dagiti titulo ti listaan ti bambantayam ket naipakita dita baba.\nTi mangikkat ti titulo, ikur-it ti kaaripingna a kahon, ken agtakla ti \"{{int:Watchlistedit-normal-submit}}\".\nMabalinmo pay nga [[Special:EditWatchlist/raw|urnosen ti kilaw a listaan]].",
+       "watchlistedit-normal-explain": "Dagiti titulo ti listaan ti bambantayam ket naipakita dita baba.\nTi mangikkat ti titulo, ikur-it ti kaaripingna a kahon, ken pinduten ti \"{{int:Watchlistedit-normal-submit}}\".\nMabalinmo pay nga [[Special:EditWatchlist/raw|urnosen ti naata a listaan]].",
        "watchlistedit-normal-submit": "Ikkaten dagiti titulo",
-       "watchlistedit-normal-done": "{{PLURAL:$1|1 ti titulo a|$1 dagiti titulo a}} naikkat iti listaan ti bambantayam:",
-       "watchlistedit-raw-title": "Urnosen ti kilaw a listaan ti bambantayan",
-       "watchlistedit-raw-legend": "Urnosen ti kilaw a listaan ti bambantayan",
-       "watchlistedit-raw-explain": "Dagiti titulo ti listaan ti bambantayam ket naipakita dita baba, ken mabaliwam nga urnosen babaen ti panagnayon ken panagkissay manipud ti listaan;\nmaysa a titulo tunggal maysa a linia.\nNo malpaska, itakla ti \"{{int:Watchlistedit-raw-submit}}\".\nMabalinmo pay nga [[Special:EditWatchlist|usaren ti dati a panagurnos]].",
+       "watchlistedit-normal-done": "{{PLURAL:$1|1 ti titulo|$1 dagiti titulo}} a naikkat manipud ti listaan ti bambantayam:",
+       "watchlistedit-raw-title": "Urnosen ti naata a listaan ti bambantayan",
+       "watchlistedit-raw-legend": "Urnosen ti naata a listaan ti bambantayan",
+       "watchlistedit-raw-explain": "Dagiti titulo ti listaan ti bambantayam ket naipakita dita baba, ken mabaliwam nga urnosen babaen ti panagnayon ken panagkissay manipud ti listaan;\nmaysa a titulo tunggal maysa a linia.\nNo malpaska, pinduten ti \"{{int:Watchlistedit-raw-submit}}\".\nMabalinmo pay nga [[Special:EditWatchlist|usaren ti pagalagadan nga editor]].",
        "watchlistedit-raw-titles": "Dagiti titulo:",
        "watchlistedit-raw-submit": "Pabaruen ti listaan ti bambantayan",
-       "watchlistedit-raw-done": "Napabaro ti listaan ti bambantayam.",
-       "watchlistedit-raw-added": "{{PLURAL:$1|1 a titulo ti|dagiti $1 a titulo ti}} nainayon:",
-       "watchlistedit-raw-removed": "{{PLURAL:$1|1 a titulo ti|dagiti $1 dagiti titulo ti}} naikkat:",
+       "watchlistedit-raw-done": "Napabaron ti listaan ti bambantayam.",
+       "watchlistedit-raw-added": "{{PLURAL:$1|1 a titulo|$1 kadagiti titulo}} ti nainayon:",
+       "watchlistedit-raw-removed": "{{PLURAL:$1|1 a titulo|$1 kadagiti titulo}} ti naikkat:",
        "watchlistedit-clear-title": "Nadalusanen ti listaan ti bambantayan",
        "watchlistedit-clear-legend": "Dalusan ti listaan ti bambantayan",
-       "watchlistedit-clear-explain": "Amin dagiti titulo ket maikkatto manipud ti listaan ti bambantayam.",
+       "watchlistedit-clear-explain": "Amin dagiti titulo ket maikkatto manipud ti listaan ti bambantayam",
        "watchlistedit-clear-titles": "Dagiti titulo:",
        "watchlistedit-clear-submit": "Dalusan ti listaan ti bambantayan (Daytoy ket permanente!)",
        "watchlistedit-clear-done": "Nadalusanen ti bambantayam.",
        "watchlisttools-clear": "Dalusan ti listaan ti bambantayan",
        "watchlisttools-view": "Kitaen dagiti maitunos a sinukatan",
        "watchlisttools-edit": "Kitaen ken urnosen ti listaan ti bambantayan",
-       "watchlisttools-raw": "Urnosen ti kilaw a listaan ti bambantayan",
+       "watchlisttools-raw": "Urnosen ti naata a listaan ti bambantayan",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|tungtungan]])",
-       "unknown_extension_tag": "Di ammo a pagpaatiddog nga etiketa \"$1\"",
-       "duplicate-defaultsort": "'''Ballaag:''' Kinasigud a panagilasin ti \"$2\" ket sukatanna ti immuna a kinasigud a panagilasin \"$1\".",
+       "unknown_extension_tag": "Di ammo a pagpaatiddog nga etiketa ti \"$1\"",
+       "duplicate-defaultsort": "<strong>Ballag:</strong> Kasisigud a panagilasin ti \"$2\" ket tuonana ti immuna a kasisigud a panagilasin ti \"$1\".",
+       "duplicate-displaytitle": "<strong>Ballaag:</strong> Ti maiparang a titulo ti \"$2\" ket tuonanna ti immmuna a maiparang a titulo ti \"$1\".",
        "version": "Bersion",
        "version-extensions": "Dagiti naisaad a pagpaatiddog",
+       "version-skins": "Naisaad a kudkudil",
        "version-specialpages": "Espesial a pampanid",
        "version-parserhooks": "Dagiti parser a kawit",
        "version-variables": "Nadumaduma a kita",
-       "version-antispam": "Pawilan ti spam",
-       "version-skins": "Dagiti Kudil",
+       "version-antispam": "Panagpawil iti spam",
        "version-other": "Sabali",
-       "version-mediahandlers": "Agtengtengngel kadagiti midia",
+       "version-mediahandlers": "Panagtengngel kadagiti midia",
        "version-hooks": "Dagiti kawit",
-       "version-parser-extensiontags": "Dagiti parser a pagpaatiddog nga etiketa",
-       "version-parser-function-hooks": "Parser a pamay-an dagiti kawit",
+       "version-parser-extensiontags": "Dagiti etiketa ti pagpaatiddog ti parser",
+       "version-parser-function-hooks": "Dagiti kawit nga annong ti parser",
        "version-hook-name": "Nagan ti kawit",
        "version-hook-subscribedby": "Umanamong babaen ti",
        "version-version": "($1)",
+       "version-no-ext-name": "[awan nagan]",
        "version-license": "Lisensia ti MediaWiki",
        "version-ext-license": "Lisensia",
        "version-ext-colheader-name": "Pagpaatiddog",
+       "version-skin-colheader-name": "Kudil",
        "version-ext-colheader-version": "Bersion",
        "version-ext-colheader-license": "Lisensia",
        "version-ext-colheader-description": "Deskripsion",
        "version-license-not-found": "Awan ti nabirukan a naisalaysay a pakaammo ti lisensia para iti daytoy a pagpaatiddog.",
        "version-credits-title": "Dagiti pammadayaw para iti $1",
        "version-credits-not-found": "Awan dagiti nabirukan a naisalaysay a pammadayaw para iti daytoy a pagpaatiddog.",
-       "version-poweredby-credits": "Daytoy a wiki ket pinaandar ti '''[https://www.mediawiki.org/ MediaWiki]''', karbengan a kopia © 2001-$1 $2.",
+       "version-poweredby-credits": "Daytoy a wiki ket pinaandar babaen ti '''[https://www.mediawiki.org/ MediaWiki]''', karbengan ti kopia © 2001-$1 $2.",
        "version-poweredby-others": "dadduma pay",
-       "version-poweredby-translators": "agipatpatarus ti translatewiki.net",
-       "version-credits-summary": "Kayatmi koma a pammadayawan dagiti sumaganad a tao para kadagiti inparawadda iti [[Special:Version|MediaWiki]].",
-       "version-license-info": "Ti MediaWiki ket nawaya a sopwer; maiwarasmo ken/wenno mabaliwam babaen ti banag iti GNU General Public License a naipablaak babaen ti Free Software Foundation; nupay iti bersion 2 iti Lisensia, wenno (ti panagpilim) ti  aniaman a bersion.\n\nTi MediaWiki ket naiwarwaras nga adda ti namnama a makatulong, ngem AWAN TI ANIA MAN A GARANTIA; nga awan pay ti naibagbaga a PANAKAILAKO wenno KALAINGAN NA ITI DAYTOY A PANGGEP. Kitaen ti GNU Sapasap a Publiko a Lisensia para kadagiti adu pay a salaysay.\n\nNaka-awatka koman ti [{{SERVER}}{{SCRIPTPATH}}/COPYING kopia iti GNU Sapasap a  Publiko a Lisensia] a nairaman iti daytoy a programa; no saan, agsuratka idiay Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA wenno [//www.gnu.org/licenses/old-licenses/gpl-2.0.html basaem idiay online].",
+       "version-poweredby-translators": "dagiti agipatpatarus ti translatewiki.net",
+       "version-credits-summary": "Kayatmi koma a pammadayawan dagiti sumaganad a tao para kadagiti kontribusonda iti [[Special:Version|MediaWiki]].",
+       "version-license-info": "Ti MediaWiki ket nawaya a sopwer; mabalinmo nga iwaras ken/wenno baliwan babaen kadagiti termino ti GNU General Public License a naipablaak babaen ti Free Software Foundation; wenno bersion 2 iti Lisensia, wenno (ti panagpilim) ti  aniaman a naudi a bersion.\n\nTi MediaWiki ket naiwarwaras iti namnama a makatulongto, ngem AWAN TI ANIA MAN A GARANTIA; nga awan pay ti naibagbaga a PANNAKAILAKO wenno KALAINGANNA ITI DAYTOY A PANGGEP. Kitaen ti GNU General Public License para kadagiti adu pay a salaysay.\n\nNaka-awatka koman ti [{{SERVER}}{{SCRIPTPATH}}/COPYING kopia iti GNU General Public License] a nairaman iti daytoy a programa; no saan, agsuratka idiay Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA wenno [//www.gnu.org/licenses/old-licenses/gpl-2.0.html basaem iti online].",
        "version-software": "Naisaad a sopwer",
        "version-software-product": "Produkto",
        "version-software-version": "Bersion",
        "version-entrypoints": "Pagserrekan a puntos dagiti URL",
        "version-entrypoints-header-entrypoint": "Pagserrekan a puntos",
        "version-entrypoints-header-url": "URL",
-       "redirect": "Ibaw-ing babaen ti papeles, agar-aramat, panid wenno ID ti panagbaliw",
+       "redirect": "Ibaw-ing babaen ti papeles, agar-aramat, panid wenno ID ti rebision",
        "redirect-legend": "Ibaw-ing iti papeles wenno panid",
-       "redirect-summary": "Daytoy nga espesial a panid ket maibaw-ing iti papeles (iti nagan ti papeles), ti panid (iti ID wenno panid ti panagbaliw), wenno ti panid ti agar-aramat (iti numeriko nga ID ti agar-aramat). Panag-usar:\n[[{{#Special:Redirect}}/file/Example.jpg]], \n[[{{#Special:Redirect}}/page/64308]], \n[[{{#Special:Redirect}}/revision/328429]], wenno\n[[{{#Special:Redirect}}/user/101]].",
+       "redirect-summary": "Daytoy nga espesial a panid ket maibaw-ing iti papeles (iti nagan ti papeles), ti panid (iti ID ti rebision wenno ID ti panid), wenno ti panid ti agar-aramat (iti numeriko nga ID ti agar-aramat). Panag-usar:\n[[{{#Special:Redirect}}/file/Example.jpg]], \n[[{{#Special:Redirect}}/page/64308]], \n[[{{#Special:Redirect}}/revision/328429]], wenno\n[[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Inkan",
        "redirect-lookup": "Kitaen:",
        "redirect-value": "Pateg:",
        "redirect-user": "ID ti agar-aramat",
        "redirect-page": "ID ti panid",
-       "redirect-revision": "Panagbaliw ti panid",
+       "redirect-revision": "Rebision ti panid",
        "redirect-file": "Nagan ti papeles",
        "redirect-not-exists": "Saan a nabirukan ti pateg",
        "fileduplicatesearch": "Agbiruk kadagiti duplikado a papeles",
-       "fileduplicatesearch-summary": "Agbiruk kadagiti duplikado a papeles a naibatay kadagiti \"hash\" a pateg.",
-       "fileduplicatesearch-legend": "Agsapul iti duplikado",
+       "fileduplicatesearch-summary": "Agbiruk kadagiti duplikado a papeles a naibatay kadagiti pateg ti hash.",
+       "fileduplicatesearch-legend": "Agbiruk para iti duplikado",
        "fileduplicatesearch-filename": "Nagan ti papeles:",
        "fileduplicatesearch-submit": "Biruken",
-       "fileduplicatesearch-info": "$1 × $2 pixel<br />Rukod ti papeles: $3<br />Kita ti MIME: $4",
-       "fileduplicatesearch-result-1": "Awan ti kapadpadana a duplikado ti papeles a \"$1\".",
-       "fileduplicatesearch-result-n": "Ti papeles a \"$1\" ket addaan {{PLURAL:$2|1 nga agpadpada a duplikado|dagiti $2  nga agpadpada a duplikado}}.",
-       "fileduplicatesearch-noresults": "Awan ti nagan ti papeles a \"$1\" ti nabirukan.",
+       "fileduplicatesearch-info": "$1 × $2 a piksel<br />Rukod ti papeles: $3<br />Kita ti MIME: $4",
+       "fileduplicatesearch-result-1": "Awan ti kapadpadana a duplikado ti papeles ti \"$1\".",
+       "fileduplicatesearch-result-n": "Ti papeles ti \"$1\" ket addaan {{PLURAL:$2|iti 1 nga agpadpada a duplikado|kadagiti $2 nga agpadpada a duplikado}}.",
+       "fileduplicatesearch-noresults": "Awan ti nabirukan a papeles a nanaganan ti \"$1\".",
        "specialpages": "Espesial a pampanid",
        "specialpages-note-top": "Leyenda",
        "specialpages-note": "* Kadawyan nga espesial a pampanid.\n* <span class=\"mw-specialpagerestricted\">Nagawidan nga espesial a pampanid.</span>",
-       "specialpages-group-maintenance": "Dagiti padamag ti panagtaripato",
-       "specialpages-group-other": "Sabsabali pay nga espesial a pampanid",
-       "specialpages-group-login": "Sumrek / agaramid ti pakabilangan",
-       "specialpages-group-changes": "Kaudian a sinukatan ken listaan",
-       "specialpages-group-media": "Dagiti padamag ti midia ken panag-ipan",
+       "specialpages-group-maintenance": "Dagiti reporta ti panagtaripato",
+       "specialpages-group-other": "Sabali nga espesial a pampanid",
+       "specialpages-group-login": "Sumrek / agpartuat ti pakabilangan",
+       "specialpages-group-changes": "Kaudian a balbaliw ken lislistaan",
+       "specialpages-group-media": "Dagiti reporta ti midia ken dagiti panagikarga",
        "specialpages-group-users": "Dagiti agar-aramat ken karkarbengan",
-       "specialpages-group-highuse": "Adu ti pannaka-usar a pampanid",
-       "specialpages-group-pages": "Listaan dagiti panid",
+       "specialpages-group-highuse": "Adu ti pannakausar a pampanid",
+       "specialpages-group-pages": "Lislistaan ti pampanid",
        "specialpages-group-pagetools": "Ramramit ti panid",
        "specialpages-group-wiki": "Datos ken ramramit",
        "specialpages-group-redirects": "Panangibaw-ing kadagiti espesial a pampanid",
        "blankpage": "Blanko a panid",
        "intentionallyblankpage": "Daytoy a panid  ket naigagara a blanko.",
        "external_image_whitelist": " #Baybayan daytoy a linia a kastoy<pre>\n#Ikabil ti \"regular expression fragments\" (idiay laeng paset nga ikabil ti tengnga ti  //) dita baba\n#Dagitoy ipada na ti URLs ti ruar (ti napudot a naikapet) imahen \n#Dagiti agpada ket agparang nga  imahen, ket no saan ti panilpo ti imahen ti agparang laeng\n#Dagiti linia nga umuna iti # ket maipabalin a komentario\n#Daytoy ket \"sensetibo ti kadakkel ti letra\"\n\n#Ikabil dagita \"regex fragment\" ti ngato daytoy a linia. Baybay-an a kastoy daytoy a linia</pre>",
-       "tags": "Umisu a sukatan dagiti etiketa",
-       "tag-filter": "[[Special:Tags|Ti etiketa]] a sagat:",
+       "tags": "Dagiti etiketa ti umiso a panagbaliw",
+       "tag-filter": "Sagat ti [[Special:Tags|etiketa]]:",
        "tag-filter-submit": "Sagat",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Etiketa|Et-etiketa}}]]: $2)",
        "tags-title": "Dagiti etiketa",
-       "tags-intro": "Daytoy a panid ket ilistana dagiti etiketa nga usaren ti sopwer nga agmarka ti panag-urnos, ken dagiti kaibuksilanda.",
+       "tags-intro": "Daytoy a panid ket ilistana dagiti etiketa a mablin nga usaren ti sopwer a mangmarka iti urnos, ken dagiti kaibuksilanda.",
        "tags-tag": "Nagan ti etiketa",
        "tags-display-header": "Tabas dagiti listaan ti panagsukat",
-       "tags-description-header": "Napno a panangipalpalawag iti kayatna a saoen.",
+       "tags-description-header": "Napno a deskripsion ti kaibuksilan.",
        "tags-active-header": "Aktibo?",
-       "tags-hitcount-header": "Dagiti etiketa a sinukatan",
+       "tags-hitcount-header": "Dagiti adda etiketana a sinukatan",
        "tags-active-yes": "Wen",
        "tags-active-no": "Saan",
        "tags-edit": "urnosen",
-       "tags-hitcount": "$1 {{PLURAL:$1|a sinukatan|kadagiti sinukatan}}",
+       "tags-hitcount": "$1 {{PLURAL:$1|a sinukatan|a sinuksukatan}}",
        "comparepages": "Ipada dagiti panid",
        "compare-page1": "Panid 1",
        "compare-page2": "Panid 2",
-       "compare-rev1": "Panagbaliw 1",
-       "compare-rev2": "Panagbaliw 2",
+       "compare-rev1": "Rebision 1",
+       "compare-rev2": "Rebision 2",
        "compare-submit": "Ipada",
-       "compare-invalid-title": "Ti titulo nga intedmo ket imbalido.",
-       "compare-title-not-exists": "Awan met dayta titulo a nainaganam.",
-       "compare-revision-not-exists": "Awan met ti pinagbaliw dayta titulo a nainaganam.",
-       "dberr-problems": "Pasensian a! Daytoy a pagsaadan ket agdadama ti teknikal a pagrigrigatan.",
-       "dberr-again": "Padasem ti agururay to manu a minutos ken agikarga.",
-       "dberr-info": "(Saan a makontak ti database server: $1)",
-       "dberr-info-hidden": "(Saan a makontak ti database server)",
-       "dberr-usegoogle": "Padasem  ti agbiruk idiay Google tatta.",
-       "dberr-outofdate": "Palagip a dagiti listaan da kadagiti kukuami a nagyan ket baka nagpaso.",
+       "compare-invalid-title": "Ti titulo nga innaganam ket imbalido.",
+       "compare-title-not-exists": "Awan ti innaganam a titulo.",
+       "compare-revision-not-exists": "Awan ti innaganam a rebision.",
+       "dberr-problems": "Pasensia! Daytoy a sitio ket agdadama nga agsansanay kadagiti teknikal a pagrigatan.",
+       "dberr-again": "Padasem ti aguray kadagiti mano a minuto ken agikarga manen.",
+       "dberr-info": "(Saan a makontak ti server ti database: $1)",
+       "dberr-info-hidden": "(Saan a makontak ti server ti database)",
+       "dberr-usegoogle": "Iti agdama mabalinmo a padasen ti agbiruk babaen ti Google.",
+       "dberr-outofdate": "Palagip a dagiti listaanda kadagiti kukuami a linaon ket mabalin a nagpaso.",
        "dberr-cachederror": "Daytoy ket naidulin a kopia ti kiniddawmo a panid, ken mabalin a saan a kabarbaro.",
-       "htmlform-invalid-input": "Adda pakirut kadagiti inkabilmo",
-       "htmlform-select-badoption": "Ti kuwenta a nainaganam ket saan a mabalin a pagpilian.",
-       "htmlform-int-invalid": "Ti kuwenta a nainaganam ket saan a sibubukel.",
-       "htmlform-float-invalid": "Ti kuwenta a nainaganam ket saan a numero.",
-       "htmlform-int-toolow": "Ti kuwenta a nainaganam ket baba ti mabalin a kababaan ti $1",
-       "htmlform-int-toohigh": "Ti kuwenta a nainaganam ket ngato ti mabalin a kangatuan ti $1",
-       "htmlform-required": "Masapul daytoy a kuwenta",
+       "htmlform-invalid-input": "Adda pakirut kadagiti dadduma nga inkabilmo.",
+       "htmlform-select-badoption": "Ti pateg a nainaganam ket saan a mabalin a pagpilian.",
+       "htmlform-int-invalid": "Ti pateg a nainaganam ket saan a maysa a sibubukel.",
+       "htmlform-float-invalid": "Ti pateg a nainaganam ket saan a numero.",
+       "htmlform-int-toolow": "Ti pateg a nainaganam ket baba ti mabalin a kababaan ti $1.",
+       "htmlform-int-toohigh": "Ti pateg a nainaganam ket ngato ti mabalin a kangatuan ti $1.",
+       "htmlform-required": "Masapul daytoy a pateg.",
        "htmlform-submit": "Ited",
-       "htmlform-reset": "Ibabawi ti sinukatan",
+       "htmlform-reset": "Ibabawi dagiti sinukatan",
        "htmlform-selectorother-other": "Sabali",
        "htmlform-no": "Saan",
        "htmlform-yes": "Wen",
-       "htmlform-chosen-placeholder": "Agpili ti pagpilian",
+       "htmlform-chosen-placeholder": "Agpili ti maysa a pagpilian",
        "htmlform-cloner-create": "Agnayon pay ti adu",
        "htmlform-cloner-delete": "Ikkaten",
        "htmlform-cloner-required": "Saan a basbassit ngem maysa a pateg ti masapul.",
-       "sqlite-has-fts": "$1 adda ti suporta ti napno a testo ti panagbiruk",
-       "sqlite-no-fts": "$1 awan ti suporta ti napno a testo ti panagbiruk",
+       "sqlite-has-fts": "Ti $1 nga addaan iti suporta ti panagbiruk ti napno a testo",
+       "sqlite-no-fts": "Ti $1 nga awan iti suporta ti panagbiruk ti napno a testo",
        "logentry-delete-delete": "Ni $1 ket {{GENDER:$2|inikkatna}} ti panid ti $3",
        "logentry-delete-restore": "Ni $1 ket {{GENDER:$2|insublina}} ti panid ti $3",
        "logentry-delete-event": "Ni $1 ket {{GENDER:$2|binaliwanna}} ti panagkita {{PLURAL:$5|iti listaan ti pasamak |dagiti $5 a listaan ti pasamak }} iti $3: $4",
        "logentry-delete-revision": "Ni $1 ket {{GENDER:$2|binaliwanna}} ti panagkita  {{PLURAL:$5|iti panagbaliw |dagiti $5 a panagbaliw}} iti panid $3: $4",
-       "logentry-delete-event-legacy": "Ni $1 ket {{GENDER:$2|binaliwanna}} ti panagkita ti listaan dagiti pasamak idiay $3",
-       "logentry-delete-revision-legacy": "Ni $1 ket {{GENDER:$2|binaliwanna}} ti panagkita dagiti panagbaliw idiay panid $3",
+       "logentry-delete-event-legacy": "Ni $1 ket {{GENDER:$2|binaliwanna}} ti panagkita ti listaan dagiti pasamak iti $3",
+       "logentry-delete-revision-legacy": "Ni $1 ket {{GENDER:$2|binaliwanna}} ti panagkita dagiti rebision iti panid ti $3",
        "logentry-suppress-delete": "Ni $1 ket {{GENDER:$2|pinasardengna}} ti panid ti $3",
        "logentry-suppress-event": "Ni $1 ket sekreto a {{GENDER:$2|binaliwanna}} ti panagkita {{PLURAL:$5|iti listaan ti pasamak |dagiti $5 a listaan ti pasamak }} iti $3: $4",
        "logentry-suppress-revision": "Ni $1 ket sekreto a {{GENDER:$2|binaliwanna}} ti panagkita {{PLURAL:$5|iti panagbaliw |dagiti $5 a panagbaliw}} iti panid $3: $4",
-       "logentry-suppress-event-legacy": "Ni $1 ket sekreto a {{GENDER:$2|binaliwanna}} ti panagkita ti listaan dagiti pasamak idiay $3",
-       "logentry-suppress-revision-legacy": "Ni $1 ket sekreto a {{GENDER:$2|binaliwanna}} ti panagkita dagiti panagbaliw idiay panid $3",
-       "revdelete-content-hid": "nailemmeng ti nagyanna",
-       "revdelete-summary-hid": "nailemmeng ti pakabuklan a naurnos",
+       "logentry-suppress-event-legacy": "Ni $1 ket sekreto a {{GENDER:$2|binaliwanna}} ti panagkita ti listaan dagiti pasamak iti $3",
+       "logentry-suppress-revision-legacy": "Ni $1 ket sekreto a {{GENDER:$2|binaliwanna}} ti panagkita dagiti panagbaliw iti panid ti $3",
+       "revdelete-content-hid": "nailemmeng ti linaon",
+       "revdelete-summary-hid": "nailemmeng ti pakabuklan ti inurnos",
        "revdelete-uname-hid": "nailemmeng ti nagan ti agar-aramat",
-       "revdelete-content-unhid": "saan a nailemmeng ti nagyanna",
-       "revdelete-summary-unhid": "saan a nailemmeng ti  pakabuklan a naurnos",
+       "revdelete-content-unhid": "saan a nailemmeng ti linaon",
+       "revdelete-summary-unhid": "saan a nailemmeng ti pakabuklan ti inurnos",
        "revdelete-uname-unhid": "saan a nailemmeng ti nagan ti agar-aramat",
-       "revdelete-restricted": "naipakat dagiti pammarit kadagiti administrador",
-       "revdelete-unrestricted": "naikkat dagiti pammarit para kadagiti administrador",
-       "logentry-move-move": "Ni $1 ket {{GENDER:$2|inyalisna}} ti panid $3 idiay $4",
-       "logentry-move-move-noredirect": "Ni $1 ket {{GENDER:$2|inyalisna}} ti panid ti $3 idiay $4 a saan a nangibati ti baw-ing",
-       "logentry-move-move_redir": "Ni $1 ket {{GENDER:$2|inyalisna}} ti panid ti $3 idiay $4 nga adda iti maysa a baw-ing",
-       "logentry-move-move_redir-noredirect": "Ni $1 ket {{GENDER:$2|inyalisna}} ti panid ti $3 idiay $4 nga adda iti maysa a baw-ing a saan a nangibati ti baw-ing",
-       "logentry-patrol-patrol": "Ni $1 ket {{GENDER:$2|minarkaanna}} ti panagbaliw a $4 ti panid ti $3 a napatruliaan",
-       "logentry-patrol-patrol-auto": "Ni $1 ket automatiko a {{GENDER:$2|minarkaanna}} ti panagbaliw a $4 ti panid ti $3 a napatruliaan",
+       "revdelete-restricted": "naipakat dagiti panangigawid kadagiti administrador",
+       "revdelete-unrestricted": "inikkat dagiti panangigawid para kadagiti administrador",
+       "logentry-move-move": "Ni $1 ket {{GENDER:$2|inyalisna}} ti panid $3 iti $4",
+       "logentry-move-move-noredirect": "Ni $1 ket {{GENDER:$2|inyalisna}} ti panid ti $3 iti $4 a saan a nangibati ti baw-ing",
+       "logentry-move-move_redir": "Ni $1 ket {{GENDER:$2|inyalisna}} ti panid ti $3 iti $4 a nagtuon iti baw-ing",
+       "logentry-move-move_redir-noredirect": "Ni $1 ket {{GENDER:$2|inyalisna}} ti panid ti $3 iti $4 a nagtuon iti baw-ing a saan a nangibati ti baw-ing",
+       "logentry-patrol-patrol": "Ni $1 ket {{GENDER:$2|minarkaanna}} ti rebision ti $4 iti panid ti $3 a napatruliaan",
+       "logentry-patrol-patrol-auto": "Ni $1 ket automatiko a {{GENDER:$2|minarkaanna}} ti rebision ti $4 iti panid ti $3 a napatruliaan",
        "logentry-newusers-newusers": "Ti pakabilangan idi ni $1 ket {{GENDER:$2|napartuat}}",
        "logentry-newusers-create": "Ti pakabilangan idi ni $1 ket {{GENDER:$2|napartuat}}",
        "logentry-newusers-create2": "Ti pakabilangan ti agar-aramat $3 ket {{GENDER:$2|napartuat}} idi babaen ni $1",
        "logentry-rights-rights-legacy": "Ni $1 ket {{GENDER:$2|binaliwanna}} ti grupo a pannakaikameng para kenni $3",
        "logentry-rights-autopromote": "Ni $1 ket automatiko idi a {{GENDER:$2|naipangato}} manipud ti $4 iti $5",
        "rightsnone": "(awan)",
-       "feedback-bugornote": "No agsagana kan nga agibaga ti teknikal a pakirut a naisalaysay pangngaasi nga [$1 ireporta ti kiteb].\nNupay kasta, mau-sarmo ti nakabuklan dita baba. Ti komentario nga itedmo ket mainayon iti panid \"[$3 $2], a mairaman ti naganmo nga agar-aramat ken no ania ti pagbasabasa nga us-sarem.",
+       "feedback-bugornote": "No sisasagakan nga agibaga ti teknikal a pakirut a naisalaysay pangngaasi nga [$1 ireporta ti parikut].\nNupay kasta, mausarmo ti nalaka a porma dita baba. Ti komentario nga itedmo ket mainayon iti panid \"[$3 $2], a mairaman ti naganmo nga agar-aramat ken no ania ti pagbasabasa nga us-sarem.",
        "feedback-subject": "Suheto:",
        "feedback-message": "Mensahe:",
        "feedback-cancel": "Ukasen",
-       "feedback-submit": "Agited ti Pagipagarupan",
-       "feedback-adding": "Agnaynayon ti pagipagarupan iti panid...",
-       "feedback-error1": "Biddut: Saan a malasin dagiti nagbanagan manipud iti API",
+       "feedback-submit": "Agited ti Feedback",
+       "feedback-adding": "Agnaynayon ti feedback iti panid...",
+       "feedback-error1": "Biddut: Saan a malasin dagiti nagbanagan manipud ti API",
        "feedback-error2": "Biddut: Napaay ti panagurnos",
-       "feedback-error3": "Biddut: Awan ti sungbat manipud iti API",
-       "feedback-thanks": "Agyaman! Ti panangparupaam ket naipablaak iti panid \"[$2 $1]\".",
+       "feedback-error3": "Biddut: Awan ti sungbat manipud ti API",
+       "feedback-thanks": "Agyaman! Ti feedbackmo ket naipablaak iti panid \"[$2 $1]\".",
        "feedback-close": "Nalpasen",
-       "feedback-bugcheck": "Nasayaaten! Kitaem tapno saan a dagiti adda idin a [$1 nga amammo a kitkiteb].",
-       "feedback-bugnew": "Kinitak. Ireporta ti baro a kiteb",
+       "feedback-bugcheck": "Nasayaaten! Kitaem tapno saan a dagiti adda idin a [$1 nga ammo a parparikut].",
+       "feedback-bugnew": "Kinitak. Agireporta ti baro a parikut",
        "searchsuggest-search": "Biruken",
        "searchsuggest-containing": "naglaon ti...",
-       "api-error-badaccess-groups": "Saanmo a mabalin ti agipan kadagiti papeles iti daytoy a wiki.",
-       "api-error-badtoken": "Kinauneg a biddut: Dakes a tandaan.",
-       "api-error-copyuploaddisabled": "Ti mangipan babaen ti URL ket nabaldado ditoy a server.",
-       "api-error-duplicate": "Adda {{PLURAL:$1|ket [$2 a sabali a papeles] |dagiti [$2 sabsabali a papeles]}} nga addan ditoy a pagsaadan nga agpada ti nagyanda.",
-       "api-error-duplicate-archive": "Adda {{PLURAL:$1|idi [$2 sabali a papeles]|dagidi [$2 sabali a papeles]}} nga adda ditoy a pagsaadan nga agpada ti nagyan da, ngem {{PLURAL:$1|daytoy|dagitoy}} ket naikkat.",
+       "api-error-badaccess-groups": "Saanka mapalubosan nga agikarga kadagiti papeles iti daytoy a wiki.",
+       "api-error-badtoken": "Akin-uneg a biddut: Dakes a tandaan.",
+       "api-error-copyuploaddisabled": "Ti panagikarga babaen ti URL ket nabaldado iti daytoy server.",
+       "api-error-duplicate": "Adda {{PLURAL:$1|ket [$2 a sabali a papeles] |dagiti [$2 sabsabali a papeles]}} nga addaan ditoy a sitio nga agpada ti linaon.",
+       "api-error-duplicate-archive": "Adda {{PLURAL:$1|idi [$2 sabali a papeles]|dagidi [$2 sabali a papeles]}} nga addaan ditoy a sitio nga agpada ti linaonda, ngem {{PLURAL:$1|daytoy|dagitoy}} ket naikkat.",
        "api-error-duplicate-archive-popup-title": "Duplikado {{PLURAL:$1|ti papeles|dagiti papeles}} a naikkaten.",
        "api-error-duplicate-popup-title": "Duplikado {{PLURAL:$1|ti papeles|dagiti papeles}}.",
-       "api-error-empty-file": "Ti papeles nga intedmo ket awan ti nagyanna.",
-       "api-error-emptypage": "Agar-aramid ti baro, dagiti awan ti linaonna a panid ket saan a maipalubos.",
-       "api-error-fetchfileerror": "Kinauneg a biddut: Addaan ti dakes a napasamak idi agalala ti papeles.",
+       "api-error-empty-file": "Ti papeles nga intedmo ket awan linaon.",
+       "api-error-emptypage": "Agparprtuat ti baro, dagiti awan ti linaon a panid ket saan a maipalubos.",
+       "api-error-fetchfileerror": "Akin-uneg a biddut: Addaan ti dakes a napasamak bayat nga agal-ala ti papeles.",
        "api-error-fileexists-forbidden": "Ti papeles nga agnagan ti \"$1\" ket addan, ken saan a mabalin a masuratan manen.",
        "api-error-fileexists-shared-forbidden": "Ti papeles nga agnagan ti \"$1\" ket adda idiay pagbibingayan a repositorio ti papeles, ken saan a mabalin a masuratan manen.",
        "api-error-file-too-large": "Ti papeles nga intedmo ket dakkel unay.",
        "api-error-filename-tooshort": "Ti nagan daytoy a papeles ket bassit unay.",
        "api-error-filetype-banned": "Ti kita daytoy a papeles ket maiparit.",
-       "api-error-filetype-banned-type": "Ti $1 {{PLURAL:$4|ket saan a mapalubusan a kita ti papeles|ket dagiti saan a mapalubusan a kita ti papeles}}. Ti mapalubusan {{PLURAL:$3|a kita ti papeles ket|kadagiti kita ti papeles ket}} $2.",
-       "api-error-filetype-missing": "Ti papeles ket agkurang ti pagpa-atiddog.",
-       "api-error-hookaborted": "Ti panagbabaro a pinadasmo ket napasardeng iti pangpa-atiddog a kawit.",
-       "api-error-http": "Kinauneg a biddut: Saan a makaikabit idiay server.",
+       "api-error-filetype-banned-type": "Ti $1 {{PLURAL:$4|ket saan a mapalubosan a kita ti papeles|ket dagiti saan a mapalubusan a kita ti papeles}}. Ti mapalubosan {{PLURAL:$3|a kita ti papeles ket|kadagiti kita ti papeles ket}} $2.",
+       "api-error-filetype-missing": "Ti papeles ket awan ti maysa a pagpaatiddog.",
+       "api-error-hookaborted": "Ti panagbabaro a pinadasmo ket pinasardeng babaen ti maysa a pagpaatiddog.",
+       "api-error-http": "Akin-uneg a biddut: Saan a makaikabit iti server.",
        "api-error-illegal-filename": "Ti nagan daytoy a papeles ket saan a maipalubos.",
-       "api-error-internal-error": "Kinauneg a biddut: Addaan ti dakes a napasamak ti panagaramid ti panagipanmo iti daytoy a wiki.",
-       "api-error-invalid-file-key": "Kinauneg a biddut: Saan a nabirukan ti papeles idiay temporario a nagidulinan.",
-       "api-error-missingparam": "Kinauneg a biddut: Kurang dagiti parametro iti kiddaw.",
-       "api-error-missingresult": "Kinauneg a biddut: Saan a na-ammoan no ti kopia ket nagballigi.",
-       "api-error-mustbeloggedin": "Masapul a nakastrek ka tapno makaipan ka kadagiti papeles.",
-       "api-error-mustbeposted": "Kinauneg a biddut: Ti kiddaw ket masapul ti HTTP POST.",
-       "api-error-noimageinfo": "Balligi ti panag-ipan, ngem ti server ket saan a nagited kadakami ti pakaammo a maipanggep iti daytoy a papeles.",
-       "api-error-nomodule": "Kinauneg a biddut: Awan ti panagipan a modulo a disso.",
-       "api-error-ok-but-empty": "Kinauneg a biddut: Awan ti sungbat manipud idiay server.",
-       "api-error-overwrite": "Saan a mabalin a suratan manen iti papeles nga adda ditan.",
-       "api-error-stashfailed": "Kinauneg a biddut: Napaay ti server ti agidulin ti temporario a papeles",
-       "api-error-publishfailed": "Kinauneg a biddut: Napaay ti server a nagipablaak ti temporario a papeles.",
+       "api-error-internal-error": "Akin-uneg a biddut: Addaan ti dakes a napasamak iti panagproseso ti inkargam iti daytoy a wiki.",
+       "api-error-invalid-file-key": "Akin-uneg a biddut: Saan a nabirukan ti papeles idiay temporario a nagidulinan.",
+       "api-error-missingparam": "Akin-uneg a biddut: Awan dagiti parametro iti kiddaw.",
+       "api-error-missingresult": "Akin-uneg a biddut: Saan a naikeddeng no ti kopia ket nagballigi.",
+       "api-error-mustbeloggedin": "Masapul a nakastrekka tapno makaikarga kadagiti papeles.",
+       "api-error-mustbeposted": "Akin-uneg a biddut: Ti kiddaw ket masapul ti HTTP POST.",
+       "api-error-noimageinfo": "Balligi ti panagikarga, ngem ti server ket saan a nagited kadakami ti aniaman a pakaammo a maipanggep iti daytoy a papeles.",
+       "api-error-nomodule": "Akin-uneg a biddut: Awan ti naisad a modulo ti panagikarga.",
+       "api-error-ok-but-empty": "Akin-uneg a biddut: Awan ti sungbat manipud ti server.",
+       "api-error-overwrite": "Saan a maipalubos a suratan manen iti papeles nga addan.",
+       "api-error-stashfailed": "Akin-uneg a biddut: Napaay ti server nga agidulin ti temporario a papeles.",
+       "api-error-publishfailed": "Akin-uneg a biddut: Napaay ti server nga agipablaak ti temporario a papeles.",
        "api-error-stasherror": "Adda maysa a biddut bayat nga agikarkarga ti papeles iti stash.",
        "api-error-timeout": "Saan a simmungbat ti server iti nanamnama nga oras.",
-       "api-error-unclassified": "Adda di amammo a biddut a rumsua.",
-       "api-error-unknown-code": "Di am-ammo a biddut: \"$1\".",
-       "api-error-unknown-error": "Kinauneg a biddut: Addaan ti dakes a napasamak idi nagipadaska ti agipan ti papelesmo.",
-       "api-error-unknown-warning": "Di am-ammo a ballaag: \"$1\".",
-       "api-error-unknownerror": "Di am-ammo a biddut: \"$1\".",
-       "api-error-uploaddisabled": "Nabaldado ti mangipapan iti daytoy a wiki.",
-       "api-error-verification-error": "Dakes ngata daytoy a papeles, wenno addaan ti madi a pagpa-atiddog.",
-       "duration-seconds": "$1 {{PLURAL:$1|segundo|seg-segundo}}",
-       "duration-minutes": "$1 {{PLURAL:$1|minuto|min-minuto}}",
-       "duration-hours": "$1 {{PLURAL:$1|oras|or-oras}}",
-       "duration-days": "$1 {{PLURAL:$1|aldaw|al-aldaw}}",
-       "duration-weeks": "$1 {{PLURAL:$1|lawas|law-lawas}}",
-       "duration-years": "$1 {{PLURAL:$1|tawen|taw-tawen}}",
-       "duration-decades": "$1 {{PLURAL:$1|dekada|dek-dekada}}",
-       "duration-centuries": "$1 {{PLURAL:$1|siglo|sig-siglo}}",
-       "duration-millennia": "$1 {{PLURAL:$1|milenio|mil-milenio}}",
-       "rotate-comment": "Ti ladawan ket napusipos babaen ti $1 {{PLURAL:$1|a degrado|a degdegrado}} nga agpakanawan",
+       "api-error-unclassified": "Adda rimsua a di ammo a biddut.",
+       "api-error-unknown-code": "Di ammo a biddut: \"$1\".",
+       "api-error-unknown-error": "Akin-uneg a biddut: Addaan ti dakes a napasamak bayat idi nagipadaska nga agikarga iti papelesmo.",
+       "api-error-unknown-warning": "Di ammo a ballaag: \"$1\".",
+       "api-error-unknownerror": "Di ammo a biddut: \"$1\".",
+       "api-error-uploaddisabled": "Nabaldado ti panagikarga iti daytoy a wiki.",
+       "api-error-verification-error": "Mabalin a dakes daytoy a papeles, wenno addaan iti madi a pagpaatiddog.",
+       "duration-seconds": "$1 a {{PLURAL:$1|segundo|segsegundo}}",
+       "duration-minutes": "$1 a {{PLURAL:$1|minuto|minminuto}}",
+       "duration-hours": "$1 nga {{PLURAL:$1|oras|or-oras}}",
+       "duration-days": "$1 nga {{PLURAL:$1|aldaw|al-aldaw}}",
+       "duration-weeks": "$1 {{PLURAL:$1|lawas|lawlawas}}",
+       "duration-years": "$1 {{PLURAL:$1|tawen|tawtawen}}",
+       "duration-decades": "$1 {{PLURAL:$1|dekada|dekdekada}}",
+       "duration-centuries": "$1 {{PLURAL:$1|siglo|sigsiglo}}",
+       "duration-millennia": "$1 {{PLURAL:$1|milenio|milmilenio}}",
+       "rotate-comment": "Ti ladawan ket napusipos babaen ti $1 {{PLURAL:$1|a grado|a gradgrado}} nga agpakanawan",
        "limitreport-title": "Panagbariweswes a datos ti parser:",
        "limitreport-cputime": "Panagusar nga oras ti CPU",
-       "limitreport-cputime-value": "$1 {{PLURAL:$1|segundo|seg-segundo}}",
+       "limitreport-cputime-value": "$1 {{PLURAL:$1|segundo|segsegundo}}",
        "limitreport-walltime": "Pudno nga oras a panagusar",
-       "limitreport-walltime-value": "$1 {{PLURAL:$1|segundo|seg-segundo}}",
+       "limitreport-walltime-value": "$1 {{PLURAL:$1|segundo|segsegundo}}",
        "limitreport-ppvisitednodes": "Nabisita a bilang ti nodo ti preproseso",
        "limitreport-ppgeneratednodes": "Napataud a bilang ti nodo ti preproseso",
        "limitreport-postexpandincludesize": "Pannakairaman a kadakkel ti kalpasan a panagpadakkel",
        "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|a byte|kadagiti byte}}",
-       "limitreport-templateargumentsize": "Argumento a kadakkel ti plantilia",
+       "limitreport-templateargumentsize": "Kadakkel ti argumento ti plantilia",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|a byte|kadagiti byte}}",
-       "limitreport-expansiondepth": "Kangatuan a panagpadakkel ti kauneg",
+       "limitreport-expansiondepth": "Kangatuan a kauneg ti panagpadakkel",
        "limitreport-expensivefunctioncount": "Bilang ti nangina nga annong ti parser",
        "expandtemplates": "Palawaen dagiti plantilia",
-       "expand_templates_intro": "Daytoy nga espesial a panid ket agala ti testo ken palawaenna amin dagiti plantilia iti unegna a minaig iti daytoy.\nPalawaenna pay dagiti nasuportaran a parser a pamay-an a kas ti\n<code><nowiki>{{</nowiki>#language:…}}</code> ken dagiti nadumaduma a kita a kas ti\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>. \nIti kinapudno, palawaenna amin dagiti adda ti doble a tukol.",
+       "expand_templates_intro": "Daytoy nga espesial a panid ket agala ti testo ken palawaenna amin dagiti plantilia iti unegna a minaig iti daytoy.\nPalawaenna pay dagiti nasuportaran a parser a pamay-an a kas ti\n<code><nowiki>{{</nowiki>#language:…}}</code> ken dagiti nadumaduma a kita a kas ti\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>. \nIti kinapudno, palawaenna amin dagiti addaan iti doble a pangrikep.",
        "expand_templates_title": "Titulo ti kontesto, para iti {{FULLPAGENAME}} kdpy.:",
        "expand_templates_input": "Maikabil a testo:",
        "expand_templates_output": "Nagbanagan",
-       "expand_templates_xml_output": "XML a maiparang",
+       "expand_templates_xml_output": "Maiparuar a XML",
        "expand_templates_html_output": "Naata a maiparuar a HTML",
-       "expand_templates_ok": "OK",
+       "expand_templates_ok": "Sige",
        "expand_templates_remove_comments": "Ikkaten dagiti komentario",
-       "expand_templates_remove_nowiki": "Parmeken dagiti <nowiki> nga etiketa kadagiti nagbanagan",
-       "expand_templates_generate_xml": "Iparang ti XML parse a kayo",
+       "expand_templates_remove_nowiki": "Parmeken dagiti etiketa ti <nowiki> iti nagbanagan",
+       "expand_templates_generate_xml": "Iparang ti pangwaswas a kayo ti XML",
        "expand_templates_generate_rawhtml": "Ipakita ti naata a HTML",
-       "expand_templates_preview": "Pamadasan"
+       "expand_templates_preview": "Ipadas",
+       "pagelanguage": "Pagpilian ti pagsasao ti panid",
+       "pagelang-name": "Panid",
+       "pagelang-language": "Pagsasao",
+       "pagelang-use-default": "Usaren ti kasisigud a pagsasao",
+       "pagelang-select-lang": "Agpili iti pagsasao",
+       "right-pagelang": "Baliwan ti pagsasao ti panid",
+       "action-pagelang": "baliwan ti pagsasao ti panid",
+       "log-name-pagelang": "Listaan ti panagbaliw ti pagsasao",
+       "log-description-pagelang": "Daytoy ket listaan dagiti panagbaliw kadagiti pagsasao ti panid.",
+       "logentry-pagelang-pagelang": "Ni $1 ket {{GENDER:$2|binaliwanna}} ti pagsasao ti panid para iti $3 manipud ti $4 iti $5."
 }
index 5ed80a3..d350f64 100644 (file)
        "talkpagelinktext": "дувцам",
        "specialpage": "ГӀулакха оагӀув",
        "personaltools": "Са гӀорсаш",
-       "postcomment": "Керда декъам",
        "articlepage": "Йоазув тӀа бӀаргтасса",
        "talk": "Дувцам",
        "views": "БӀаргтассамаш",
        "yourdomainname": "Шун цӀеноагӀув:",
        "login": "Чувала/яла",
        "nav-login-createaccount": "ЦӀи яьккха/Ший oагӀув ела",
-       "loginprompt": "Укх белхацхьоагIоца доттагӀал лаца, шун \"cookies\" йийла хьалдеза.",
        "userlogin": "ЦӀи яьккха/ОагӀув ела",
        "userloginnocreate": "Чувала/яла",
        "logout": "Аравала/яла",
        "uploadlogpage": "Чуяьккхамий тептар",
        "filedesc": "Лоаца лоацам",
        "fileuploadsummary": "Лоаца лоацам:",
-       "uploadedimage": "\"[[$1]]\" чуяьккхай",
        "license": "ЦIийяздар",
        "license-header": "ЦIийяздар",
        "imgfile": "паьл",
index 01f4b3e..a519039 100644 (file)
        "talkpagelinktext": "Diskutez",
        "specialpage": "Specala pagino",
        "personaltools": "Personala utensili",
-       "postcomment": "Nova seciono",
        "articlepage": "Regardar artiklo",
        "talk": "Diskuto",
        "views": "Apari",
        "yourdomainname": "Vua domano:",
        "login": "Enirar",
        "nav-login-createaccount": "Enirar",
-       "loginprompt": "Vu mustas permisar ''cookies'' por enirar a {{SITENAME}}.",
        "userlogin": "Enirar / krear konto",
        "userloginnocreate": "Enirar",
        "logout": "Ekirar",
        "searchprofile-articles-tooltip": "Serchez en $1",
        "searchprofile-images-tooltip": "Serchez arkivi",
        "search-result-size": "$1 ({{PLURAL:$2|1 vorto|$2 vorti}})",
-       "search-result-score": "Importo: $1%",
        "search-redirect": "(ridirektilo $1)",
        "search-section": "(seciono $1)",
        "search-suggest": "Ka vu volis dicar: $1",
        "fileexists": "Arkivo kun ica nomo ja existas.\nVolutez kontrolar <strong>[[:$1]]</strong> se vu ne esas certa pri chanjar olu.\n[[$1|thumb]]",
        "uploadwarning": "Averto pri la adkargo di arkivo",
        "savefile": "Registragar arkivo",
-       "uploadedimage": "adkargita \"[[$1]]\"",
        "uploaddisabled": "Pardonez, la adkargo esas desaktiva.",
        "watchthisupload": "Surveyar ica arkivo",
        "upload-success-subj": "Adcharjo sucesoza",
        "unwatch": "Ne plus surveyar",
        "unwatchthispage": "Ne plus surveyar",
        "notanarticle": "Ne esas artiklo",
+       "wlnote": "Infre esas la lasta {{PLURAL:$1|chanjo|'''$1''' chanji}} dum la lasta {{PLURAL:$2|horo|'''$2''' hori}}.",
        "wlshowlast": "Montrar la lasta $1 hori $2 dii $3",
        "watchlist-options": "Surveryo-listo selekti",
        "watching": "Surveyanta…",
index 2837738..64dee56 100644 (file)
        "talkpagelinktext": "Spjall",
        "specialpage": "Kerfissíða",
        "personaltools": "Tenglar",
-       "postcomment": "Nýr hluti",
        "articlepage": "Sýna núverandi síðu",
        "talk": "Spjall",
        "views": "Sýn",
        "invalidtitle-knownnamespace": "Ógildur titill í nafnrými \"$2\" og með textann \"$3\"",
        "invalidtitle-unknownnamespace": "Ógildur titill með óþekkt nafnrými númer $1 og texta \"$2\"",
        "exception-nologin": "Óinnskráð(ur)",
-       "exception-nologin-text": "Vinsamlegast [[Special:Userlogin|skráðu þig inn]] til þess að hafa aðgang að þessari síðu eða aðgerð.",
+       "exception-nologin-text": "Vinsamlegast skráðu þig inn til þess að hafa aðgang að þessari síðu eða aðgerð.",
        "virus-badscanner": "Slæm stilling: óþekktur veiruskannari: ''$1''",
        "virus-scanfailed": "skönnun mistókst (kóði $1)",
        "virus-unknownscanner": "óþekkt mótveira:",
        "externaldberror": "Uppfærsla mistókst. Annaðhvort varð villa í gagnasafninu eða að þér sé óheimilt að uppfæra aðra aðganga.",
        "login": "Innskrá",
        "nav-login-createaccount": "Innskrá / Búa til aðgang",
-       "loginprompt": "Þú verður að leyfa vefkökur til þess að geta skráð þig inn á {{SITENAME}}.",
        "userlogin": "Innskrá / Búa til aðgang",
        "userloginnocreate": "Innskrá",
        "logout": "Útskráning",
        "gotaccountlink": "Skráðu þig inn",
        "userlogin-resetlink": "Gleymdir þú notendaupplýsingunum þínum?",
        "userlogin-resetpassword-link": "Gleymdiru lykilorðinu þínu?",
-       "userlogin-loggedin": "Þú ert búin(n) að skrá þig inn sem {{GENDER:$1|$1}}.\nNotaðu eyðablaðið fyrir neðan til að skrá þig inn sem annar notandi.",
-       "userlogin-createanother": "Stofna annan aðgang",
        "createacct-emailrequired": "Netfang",
        "createacct-emailoptional": "Netfang (valfrjálst)",
        "createacct-email-ph": "Skrifaðu niður netfangið þitt",
        "preview": "Forskoða",
        "showpreview": "Forskoða",
        "showdiff": "Sýna breytingar",
-       "anoneditwarning": "'''Viðvörun:''' Þú ert ekki innskráð(ur). Vistfang þitt skráist í breytingaskrá síðunnar.",
+       "anoneditwarning": "<strong>Viðvörun:</strong> Þú ert ekki innskráð(ur). Vistfang þitt verður sýnt opinberlega ef þú gerir einhverjar breytingar. Ef þú <strong>[$1 skráir þig inn]</strong> eða <strong>[$2 stofnar aðgang]</strong> munu breytingarnar þínar vera tengdar við notendanafn þitt, ásamt öðrum kostum.",
        "anonpreviewwarning": "Þú ert ekki innskráð(ur). Vistfang þitt skráist í breytingaskrá síðunnar.",
        "missingsummary": "'''Áminning:''' Þú hefur ekki skrifað breytingarágrip.\nEf þú smellir á Vista aftur, verður breyting þín vistuð án þess.",
        "missingcommenttext": "Gerðu svo vel og skrifaðu athugasemd fyrir neðan.",
        "loginreqlink": "innskrá",
        "loginreqpagetext": "Þú þarft að $1 þig til að geta séð aðrar síður.",
        "accmailtitle": "Lykilorð sent.",
-       "accmailtext": "Lykilorðið fyrir [[User talk:$1|$1]] hefur verið sent á $2.\n\nHægt er að breyta lykilorðinu fyrir aðganginn á ''[[Special:ChangePassword|change password]]'' þegar notandinn hefur skráð sig inn.",
+       "accmailtext": "Lykilorðið fyrir [[User talk:$1|$1]] hefur verið sent á $2. Hægt er að breyta því á síðunni ''[[Special:ChangePassword|breyta lykilorði]]'' þegar notandinn hefur skráð sig inn.",
        "newarticle": "(Ný)",
        "newarticletext": "Þú hefur fylgt tengli á síðu sem ekki er til ennþá.\nÞú getur búið til síðu með þessu nafni með því að skrifa í formið fyrir neðan\n(meiri upplýsingar í [$1 hjálpinni]).\nEf þú hefur óvart villst hingað geturðu notað '''til baka'''-hnappinn í vafranum þínum.",
        "anontalkpagetext": "----''Þetta er spjallsíða fyrir óþekktan notanda sem hefur ekki búið til aðgang ennþá, eða notar hann ekki.\nÞar af leiðandi þurfum við að nota vistfang til að bera kennsli á hann/hana.\nNokkrir notendur geta deilt sama vistfangi.\nEf þú ert óþekktur notandi og finnst að óviðkomandi athugasemdum hafa verið beint að þér, gjörðu svo vel og [[Special:UserLogin/signup|búðu til aðgang]] eða [[Special:UserLogin|skráðu þig inn]] til þess að koma í veg fyrir þennan rugling við aðra óþekkta notendur í framtíðinni.''",
        "searchprofile-advanced-tooltip": "Leita í ákveðnum nafnrýmum",
        "search-result-size": "$1 ({{PLURAL:$2|1 orð|$2 orð}})",
        "search-result-category-size": "{{PLURAL:$1|1 meðlimur|$1 meðlimir}} ({{PLURAL:$2|1 undirflokks|$2 undirflokka}}, {{PLURAL:$3|1 skrá|$3 skrár}})",
-       "search-result-score": "Gildi: $1%",
        "search-redirect": "(tilvísun $1)",
        "search-section": "(hluti $1)",
        "search-file-match": "(passar við innihald skráa)",
        "search-suggest": "Varstu að leita að: $1",
        "search-interwiki-caption": "Systurverkefni",
-       "search-interwiki-default": "$1 útkomur:",
+       "search-interwiki-default": "Útkomur frá $1:",
        "search-interwiki-more": "(fleiri)",
        "search-relatedarticle": "Tengt",
        "searchrelated": "tengt",
        "searchall": "öllum",
        "showingresults": "Sýni <strong>$1</strong> {{PLURAL:$1|niðurstöðu|niðurstöður}} frá og með #<strong>$2</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Niðurstaða '''$1''' af '''$3'''|Niðurstöður'''$1 - $2''' af '''$3'''}} fyrir '''$4'''",
        "search-nonefound": "Engar niðurstöður pössuðu við fyrirspurnina.",
        "powersearch-legend": "Ítarlegri leit",
        "powersearch-ns": "Leita í nafnrýmum:",
        "right-deletedtext": "Sjá eyddan texta og breytingar á milli eyddra útgáfna",
        "right-browsearchive": "Leita í eyddum síðum",
        "right-undelete": "Endurvekja eydda síðu",
-       "right-suppressrevision": "Skoða og endurvekja breytingar faldar fyrir stjórnendum",
+       "right-suppressrevision": "Skoða, fela og endurvekja ákveðnar breytingar síðna frá öllum notendum",
        "right-suppressionlog": "Skoða einrænar aðgerðaskrár",
        "right-block": "Banna öðrum notendum að gera breytingar",
        "right-blockemail": "Banna notanda að senda tölvupóst",
        "recentchanges-label-bot": "Þessi breyting var gerð af vélmenni",
        "recentchanges-label-unpatrolled": "Þessi breyting hefur ekki verið yfirfarin",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (sjá einng [[Special:NewPages|lista yfir nýjar síður]])",
-       "rcnotefrom": "Að neðan eru breytingar síðan <strong>$2<strong> (allt að <strong>$1<strong> sýndar).",
+       "rcnotefrom": "Að neðan {{PLURAL:$5|er breyting síðan|eru breytingar síðan}} <strong>$3, $4</strong> (allt að <strong>$1</strong> sýndar).",
        "rclistfrom": "Sýna breytingar frá og með $3 $2",
        "rcshowhideminor": "$1 minniháttar breytingar",
        "rcshowhideminor-show": "Sýna",
        "rcshowhidebots": "$1 vélmenni",
        "rcshowhidebots-show": "Sýna",
        "rcshowhidebots-hide": "Fela",
-       "rcshowhideliu": "$1 skráðir notendur",
+       "rcshowhideliu": "$1 skráða notendur",
        "rcshowhideliu-show": "Sýna",
        "rcshowhideliu-hide": "Fela",
        "rcshowhideanons": "$1 óinnskráða notendur",
        "largefileserver": "Þessi skrá er of stór. Vefþjónninn getur ekki tekið við skránni.",
        "emptyfile": "Skráin sem þú hlóðst inn virðist vera tóm.\nÞetta gæti verið vegna ásláttarvillu í skráarnafninu.\nVinsamlegast athugaðu hvort þú viljir hlaða skránni inn.",
        "windows-nonascii-filename": "Þessi wiki styður ekki skráarnöfn með sérstökum stöfum",
-       "fileexists": "Skrá með þessu nafni er þegar til, skoðaðu <strong>[[:$1]]</strong> ef þú ert óviss um hvort þú viljir breyta henni, ekki verður skrifað yfir gömlu skránna hlaðiru inn nýrri með sama nafni heldur verður núverandi útgáfa geymd í útgáfusögu.\n[[$1|thumb]]",
+       "fileexists": "Skrá með þessu nafni er þegar til, skoðaðu <strong>[[:$1]]</strong> ef þú ert óviss um hvort þú viljir breyta henni.\n[[$1|thumb]]",
        "filepageexists": "Myndasíðan fyrir þessa síðu hefur þegar verið búin til <strong>[[:$1]]</strong>, en engin skrá er til með þessu nafni.\nLýsingin sem þú skrifaðir verður ekki birt á myndasíðunni.\nTil þess að lýsingin geti birst á síðunni, þá þarft þú að breyta síðunni sérstaklega.\n[[$1|thumb]]",
        "fileexists-extension": "Skrá með svipuðu nafni er til: [[$2|thumb]]\n*Nafn skráarinnar sem hlaða á inn: <strong>[[:$1]]</strong>\n*Nafn skráarinnar sem er þegar til: <strong>[[:$2]]</strong>\nVilt þú kanski nota annað nafn sem er meira lýsandi fyrir skránna ?",
        "fileexists-thumbnail-yes": "Skráin virðist vera smámynd [[$1|thumb]]\nVinsamlegast athugaðu skránna <strong>[[:$1]]</strong>.\nEf skráin er sama myndin í upprunalegri stærð er ekki þörf á annari smámynd.",
        "uploadwarning": "Aðvörun",
        "uploadwarning-text": "Vinsamlegast breyttu myndalýsingunni hér fyrir neðan og reyndu aftur.",
        "savefile": "Vista",
-       "uploadedimage": "hlóð inn „[[$1]]“",
-       "overwroteimage": "hlóð inn nýrri útgáfu af \"[[$1]]\"",
        "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.",
        "license-header": "Leyfisupplýsingar:",
        "nolicense": "Ekkert valið",
        "license-nopreview": "(Forskoðun ekki fáanleg)",
-       "upload_source_url": "(gild, aðgengileg vefslóð)",
-       "upload_source_file": "(skrá á tölvunni þinni)",
+       "upload_source_url": "(þín valda skrá frá gildri, aðgengilegri vefslóð)",
+       "upload_source_file": "(þín valda skrá frá tölvunni þinni)",
        "listfiles-summary": "Þessi kerfissíða sýnir allar upphlaðnar skrár.",
        "listfiles_search_for": "Leita að miðilsnafni:",
        "imgfile": "skrá",
        "filedelete-maintenance": "Á meðan viðhaldi stendur er lokað fyrir eyðingu og endurvakningu skráa.",
        "filedelete-maintenance-title": "Mistókst að eyða 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ð, t.d. <code>image/jpeg</code>.",
+       "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 efnistag/*, t.d. <code>image/jpeg</code>.",
        "mimetype": "MIME-tegund:",
        "download": "Hlaða niður",
        "unwatchedpages": "Óvaktaðar síður",
        "randomincategory": "Handhófsvalin síða í flokki",
        "randomincategory-invalidcategory": "„$1“ er ekki gilt flokkarheiti",
        "randomincategory-nopages": "Það eru engar síður í flokkinum [[:Category:$1|$1]].",
-       "randomincategory-selectcategory": "Fá handhófsvalda síðu úr flokkinum: $1 $2.",
-       "randomincategory-selectcategory-submit": "Fara",
        "randomredirect": "Handahófsvalin tilvísun",
        "randomredirect-nopages": "Það eru engar tilvísanir í nafnrýminu „$1“.",
        "statistics": "Tölfræði",
        "mywatchlist": "Vaktlisti",
        "watchlistfor2": "Eftir $1 $2",
        "nowatchlist": "Vaktlistinn er tómur.",
-       "watchlistanontext": "Vinsamlegast $1ðu þig til að skoða eða breyta vaktlistanum þínum.",
+       "watchlistanontext": "Vinsamlegast skráðu þig til að skoða eða breyta hlutum á vaktlistanum þínum.",
        "watchnologin": "Óinnskráð(ur)",
        "addwatch": "Bæta á vaktlistann",
        "addedwatchtext": "Síðunni „[[:$1]]“ hefur verið bætt á [[Special:Watchlist|vaktlistann]] þinn.\nFrekari breytingar á henni eða spjallsíðu hennar munu verða sýndar þar.",
        "watchlist-details": "{{PLURAL:$1|$1 síða|$1 síður}} á vaktlistanum þínum, fyrir utan spjallsíður.",
        "wlheader-enotif": "Tilkynning með tölvupósti er virk.",
        "wlheader-showupdated": "Síðum sem hefur verið breytt síðan þú skoðaðir þær síðast eru '''feitletraðar'''.",
+       "wlnote": "Hér fyrir neðan {{PLURAL:$1|er síðasta <strong>$1</strong> breyting|eru síðustu <strong>$1</strong> breytingar}} {{PLURAL:$2|síðustu <strong>$2</strong> klukkutímann|síðastliðna <strong>$2</strong> klukkutímana}}, frá $3, $4.",
        "wlshowlast": "Sýna síðustu $1 klukkutíma, $2 daga, $3",
        "watchlist-options": "Vaktlistastillingar",
        "watching": "Vakta...",
        "enotif_lastvisited": "Heimsóttu eftirfarandi tengil til að sjá allar breytingar síðan \nþú heimsóttir síðuna síðast:\n  $1",
        "enotif_lastdiff": "Einnig getur þú heimsótt eftirfarandi tengil til að skoða þessa breytingu:\n  $1",
        "enotif_anon_editor": "ónefndum notanda $1",
-       "enotif_body": "Kæri $WATCHINGUSERNAME,\n\n$PAGEINTRO\n$NEWPAGE\n\nTil þess að hafa samband við $PAGEEDITOR, smelltu á:\n\n   $PAGEEDITOR_WIKI\n\nAthugaðu að frekari breytingar á $PAGETITLE leiða\nekki af sér fleiri tilkynningar fyrr en þú hefur heimsótt síðuna á meðan þú ert skráð/ur inn.\n\nKveðja,\n{{SITENAME}}\n\n--\n\nTil þess að breyta stillingum um hvenær þú færð sendar tilkynningar, smelltu á:\n\n{{canonicalurl:{{#special:Preferences}}}}\n\n\nTil þess að hætta að fylgjast með „$PAGETITLE”, smelltu á:\n\n$UNWATCHURL",
+       "enotif_body": "Kæri $WATCHINGUSERNAME,\n\n$PAGEINTRO\n$NEWPAGE\n\n$PAGEEDITOR skildi eftir eftirfarandi breytingarágrip: $PAGESUMMARY $PAGEMINOREDIT\n\nTil þess að hafa samband við $PAGEEDITOR, smelltu á $PAGEEDITOR_WIKI eða sentu tölvupóst á $PAGEEDITOR_EMAIL\n\nAthugaðu að frekari aðgerðir á $PAGETITLE leiða\nekki af sér fleiri tilkynningar fyrr en þú hefur heimsótt síðuna á meðan þú ert skráð/ur inn. Þú getur einnig endursett tilkynningar fyrir allar þær síður sem þú fylgist með.\n\nKveðja,\n{{SITENAME}}\n\n--\n\nTil þess að breyta stillingum um hvenær þú færð sendar tilkynningar, smelltu á:\n\n{{canonicalurl:{{#special:Preferences}}}}\n\n\nTil þess að hætta að fylgjast með „$PAGETITLE”, smelltu á:\n\n$UNWATCHURL\n\nFrekari hjálp er að finna á $HELPPAGE.",
        "created": "búin til",
        "changed": "breytt",
        "deletepage": "Eyða",
        "exbeforeblank": "innihald fyrir tæmingu var: '$1'",
        "delete-confirm": "Eyða „$1“",
        "delete-legend": "Eyða",
-       "historywarning": "'''Viðvörun:''' Síðan sem þú ert um það bil að eyða hefur breytingarskrá með $1 {{PLURAL:$1|breytingu|breytingum}}:",
+       "historywarning": "<strong>Viðvörun:</strong> Síðan sem þú ert um það bil að eyða hefur breytingarskrá með $1 {{PLURAL:$1|breytingu|breytingum}}:",
        "confirmdeletetext": "Þú ert um það bil að eyða síðu ásamt breytingaskrá hennar.\nVinsamlegast staðfestu það að þú ætlir að gera svo, það að þú skiljir afleiðingarnar, og að þú sért að gera þetta í samræmi við [[{{MediaWiki:Policy-url}}]].",
        "actioncomplete": "Aðgerð lokið",
        "actionfailed": "Aðgerð mistókst",
        "protect-locked-blocked": "Þú getur ekki breytt verndunarstigi á meðan þú ert bannaður.\nHérna er núverandi verndunarstig fyrir síðuna '''$1''':",
        "protect-locked-dblock": "Á meðan gangnabankinn er læstur er ekki hægt að breyta verndunarstigi.\nHér eru núverandi verndunarstig fyrir síðuna '''$1''':",
        "protect-locked-access": "Þú hefur ekki heimild til þess að vernda eða afvernda síður.\nNúverandi staða síðunnar er '''$1''':",
-       "protect-cascadeon": "Þessi síða er vernduð vegna þess að hún er innifalin í eftirfarandi {{PLURAL:$1|síðu, sem er keðjuvernduð|síðum, sem eru keðjuverndaðar}}.\nÞú getur breytt verndunarstigi þessarar síðu, en það mun ekki hafa áhrif á keðjuverndunina.",
+       "protect-cascadeon": "Þessi síða er vernduð vegna þess að hún er innifalin í eftirfarandi {{PLURAL:$1|síðu, sem er keðjuvernduð|síðum, sem eru keðjuverndaðar}}.\nBreytingar á verndunarstigi þessarar síðu munu ekki hafa áhrif á keðjuverndunina.",
        "protect-default": "Leyfa öllum notendum",
        "protect-fallback": "Leyfa eingöngu notendur með „$1“ réttindi",
        "protect-level-autoconfirmed": "Leyfa aðeins sjálkrafa staðfesta notendur",
        "autoblockid": "Sjálfvirkt bann $1",
        "block": "Banna notanda",
        "unblock": "Afbanna notanda",
-       "blockip": "Banna notanda",
+       "blockip": "Banna {{GENDER:$1|notanda}}",
        "blockip-legend": "Banna notanda",
        "blockiptext": "Notaðu eyðublaðið hér að neðan til þess að banna ákveðið vistfang eða notandanafn.\nÞetta ætti einungis að gera til þess að koma í veg fyrir skemmdarverk, og í samræmi við [[{{MediaWiki:Policy-url}}|samþykktir]].\nGefðu nákvæma skýringu að neðan (til dæmis, með því að vísa í þær síður sem skemmdar voru).",
        "ipaddressorusername": "Vistfang eða notandanafn:",
        "ipb-unblock-addr": "Afbanna $1",
        "ipb-unblock": "Afbanna notanda eða vistfang",
        "ipb-blocklist": "Sjá núverandi bönn",
-       "ipb-blocklist-contribs": "Framlög fyrir $1",
+       "ipb-blocklist-contribs": "Framlög fyrir {{GENDER:$1|$1}}",
        "unblockip": "Afbanna notanda",
        "unblockiptext": "Endurvekja skrifréttindi bannaðra notenda eða vistfanga.",
        "ipusubmit": "Afbanna",
        "import": "Flytja inn síður",
        "importinterwiki": "Milli-Wiki innflutningur",
        "import-interwiki-text": "Veldu Wiki-kerfi og síðutitil til að flytja inn.\nBreytingaupplýsingar s.s. dagsetningar og höfundanöfn eru geymd.\nAllir innflutningar eru skráð í [[Special:Log/import|innflutningsskránna]].",
-       "import-interwiki-source": "Uppruni wiki síðunnar:",
        "import-interwiki-history": "Afrita allar breytingar þessarar síðu",
        "import-interwiki-templates": "Innifala öll snið með",
        "import-interwiki-submit": "Flytja inn",
        "import-error-create": "Síðan \"$1\" var ekki flutt inn því þú hefur ekki réttindi til að stofna hana.",
        "import-error-interwiki": "Síðan \"$1\" var ekki flutt inn því nafn hennar er frátekið fyrir ytri tengla (tungumálatengla).",
        "import-error-special": "Síðan \"$1\" var ekki flutt inn því hún tilheyrir ákveðnu nafnrými sem leyfir ekki síður.",
-       "import-error-invalid": "Síðan \"$1\" var ekki flutt inn því nafn hennar er ógilt.",
+       "import-error-invalid": "Síðan \"$1\" var ekki flutt inn því nafnið sem hún yrði flutt á er ógilt á þessum wiki.",
        "import-error-unserialize": "Ekki unnt að afraða útgáfu $2 af síðunni „$1“. Útgáfan var sögð nota innihaldslíkan $3 raðað sem $4.",
        "import-options-wrong": "{{PLURAL:$2|Rangur möguleiki|Rangir möguleikar}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "Uppgefin móðursíða hefur ógildan titil.",
        "importlogpage": "Innflutningsskrá",
        "importlogpagetext": "Hér er listi yfir innflutninga möppdýra á síðum ásamt breytingarskránni frá öðrum wiki.",
        "import-logentry-upload": "flutti inn [[$1]] frá skrá",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|breyting|breytingar}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|breyting flutt|breytingar fluttar}} inn",
        "import-logentry-interwiki": "flutti inn $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|breyting|breytingar}} frá $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|breyting flutt|breytingar fluttar}} inn frá $2",
        "javascripttest": "JavaScript prófun",
        "javascripttest-title": "Keyri $1 prófun",
        "javascripttest-pagetext-noframework": "Þessi síða er frátekin fyrir JavaScript prófanir.",
index 4a8673a..0eab06d 100644 (file)
@@ -72,7 +72,9 @@
                        "לערי ריינהארט",
                        "PeppeAeco",
                        "아라",
-                       "Lucas2"
+                       "Lucas2",
+                       "Taxandru",
+                       "C.R."
                ]
        },
        "tog-underline": "Sottolinea i collegamenti:",
        "tog-watchdefault": "Aggiungi le pagine e i file modificati agli osservati speciali",
        "tog-watchmoves": "Aggiungi le pagine e i file spostati agli osservati speciali",
        "tog-watchdeletion": "Aggiungi le pagine e i file cancellati agli osservati speciali",
+       "tog-watchrollback": "Aggiungi agli osservati speciali le pagine su cui ho effettuato un rollback",
        "tog-minordefault": "Indica ogni modifica come minore (solo come predefinito)",
        "tog-previewontop": "Mostra l'anteprima sopra la casella di modifica e non sotto",
-       "tog-previewonfirst": "Mostra l'anteprima almeno una volta prima di salvare",
+       "tog-previewonfirst": "Mostra l'anteprima sulla prima modifica",
        "tog-enotifwatchlistpages": "Inviami una email quando viene modificata una pagina o un file presente tra gli osservati speciali",
        "tog-enotifusertalkpages": "Inviami una email quando viene modificata la mia pagina di discussione",
        "tog-enotifminoredits": "Inviami una email anche per le modifiche minori di pagine e file",
        "tog-enotifrevealaddr": "Mostra il mio indirizzo nelle e-mail di notifica",
        "tog-shownumberswatching": "Mostra il numero di utenti che hanno la pagina in osservazione",
        "tog-oldsig": "Firma attuale:",
-       "tog-fancysig": "Tratta la firma come wikitesto (senza collegamento automatico)",
+       "tog-fancysig": "Gestisci la firma come wikitesto (senza collegamento automatico)",
        "tog-uselivepreview": "Abilita la funzione ''Live preview'' (anteprima in diretta - sperimentale)",
        "tog-forceeditsummary": "Chiedi conferma se il campo oggetto è vuoto",
        "tog-watchlisthideown": "Nascondi le mie modifiche negli osservati speciali",
        "tog-prefershttps": "Usa sempre una connessione sicura quando si effettua l'accesso",
        "underline-always": "Sempre",
        "underline-never": "Mai",
-       "underline-default": "Mantieni le impostazioni del browser o della skin",
+       "underline-default": "Impostazioni predefinite del browser o della skin",
        "editfont-style": "Stile del carattere nella casella di modifica:",
        "editfont-default": "Predefinito del browser",
        "editfont-monospace": "Carattere a larghezza fissa",
        "listingcontinuesabbrev": "cont.",
        "index-category": "Pagine indicizzate",
        "noindex-category": "Pagine non indicizzate",
-       "broken-file-category": "Pagine che includono file inesistenti",
+       "broken-file-category": "Pagine che richiamano file inesistenti",
        "about": "Informazioni",
        "article": "Voce",
        "newwindow": "(si apre in una nuova finestra)",
        "talkpagelinktext": "Discussione",
        "specialpage": "Pagina speciale",
        "personaltools": "Strumenti personali",
-       "postcomment": "Nuova sezione",
        "articlepage": "Visualizza la voce",
        "talk": "Discussione",
        "views": "Visite",
        "otherlanguages": "In altre lingue",
        "redirectedfrom": "(Reindirizzamento da '''$1''')",
        "redirectpagesub": "Pagina di reindirizzamento",
+       "redirectto": "Reindirizza a:",
        "lastmodifiedat": "Questa pagina è stata modificata per l'ultima volta il $1 alle $2.",
        "viewcount": "Questa pagina è stata letta {{PLURAL:$1|una volta|$1 volte}}.",
        "protectedpage": "Pagina protetta",
        "hidetoc": "nascondi",
        "collapsible-collapse": "Comprimi",
        "collapsible-expand": "Espandi",
+       "confirmable-confirm": "Sei {{GENDER:$1|sicuro|sicura}}?",
+       "confirmable-yes": "Sì",
+       "confirmable-no": "No",
        "thisisdeleted": "Vedi o ripristina $1?",
        "viewdeleted": "Vedi $1?",
        "restorelink": "{{PLURAL:$1|una modifica cancellata|$1 modifiche cancellate}}",
        "invalidtitle-knownnamespace": "Titolo non valido con namespace \"$2\" e testo \"$3\"",
        "invalidtitle-unknownnamespace": "Titolo non valido con namespace sconosciuto \"$1\" e testo \"$2\"",
        "exception-nologin": "Accesso non effettuato",
-       "exception-nologin-text": "Si prega di [[Special:Userlogin|eseguire l'accesso]] per poter accedere a questa pagina o azione.",
+       "exception-nologin-text": "Per poter accedere a questa pagina o azione è necessario eseguire l'accesso.",
        "exception-nologin-text-manual": "Si prega di $1 per poter accedere a questa pagina o azione.",
        "virus-badscanner": "Errore di configurazione: antivirus sconosciuto: ''$1''",
        "virus-scanfailed": "scansione fallita (codice $1)",
        "externaldberror": "Si è verificato un errore con il server di autenticazione esterno, oppure non si dispone delle autorizzazioni necessarie per aggiornare il proprio accesso esterno.",
        "login": "Entra",
        "nav-login-createaccount": "Entra / registrati",
-       "loginprompt": "Per accedere a {{SITENAME}} è necessario abilitare i cookie.",
        "userlogin": "Entra / registrati",
        "userloginnocreate": "Entra",
        "logout": "Esci",
        "userlogin-resetlink": "Hai dimenticato i tuoi dati di accesso?",
        "userlogin-resetpassword-link": "Hai dimenticato la password?",
        "userlogin-helplink2": "Aiuto con l'accesso",
-       "userlogin-loggedin": "Sei già connesso come {{GENDER:$1|$1}}.\nUsa il modulo sottostante per accedere come altro utente.",
-       "userlogin-createanother": "Crea un'altra utenza",
        "createacct-emailrequired": "Indirizzo email",
        "createacct-emailoptional": "Indirizzo di posta elettronica (opzionale)",
        "createacct-email-ph": "Inserisci il tuo indirizzo email",
        "createaccount-text": "Qualcuno ha creato un accesso a {{SITENAME}} ($4) a nome di $2, associato a questo indirizzo di posta elettronica. La password per l'utente \"$2\" è impostata a \"$3\".\nÈ opportuno eseguire un accesso quanto prima e cambiare la password immediatamente.\n\nSe l'accesso è stato creato per errore, si può ignorare questo messaggio.",
        "login-throttled": "Sono stati effettuati troppi tentativi di accesso in breve tempo.\nAttendi $1 e riprova in seguito.",
        "login-abort-generic": "Il tuo login non ha avuto successo - Annullato",
+       "login-migrated-generic": "La tua utenza è stata migrata, e il tuo nome utente non esiste più su questo wiki.",
        "loginlanguagelabel": "Lingua: $1",
        "suspicious-userlogout": "La tua richiesta di disconnessione è stata negata perché sembra inviata da un browser non funzionante o un proxy di caching.",
        "createacct-another-realname-tip": "L'indicazione del proprio nome vero è opzionale; se si sceglie di inserirlo, verrà utilizzato per attribuire la paternità dei contenuti inviati.",
        "passwordreset-domain": "Dominio:",
        "passwordreset-capture": "Visualizzare il contenuto del messaggio e-mail?",
        "passwordreset-capture-help": "Se si seleziona questa casella, l'indirizzo e-mail (con la password temporanea), verrà mostrato a voi, oltre ad essere inviato all'utente.",
-       "passwordreset-email": "Indirizzo e-mail:",
+       "passwordreset-email": "Indirizzo email:",
        "passwordreset-emailtitle": "Dettagli dell'utente su {{SITENAME}}",
        "passwordreset-emailtext-ip": "Qualcuno (probabilmente tu, con indirizzo IP $1) ha richiesto l'invio di una nuova password per l'accesso a {{SITENAME}} ($4). {{PLURAL:$3|L'utente associato|Gli utenti associati}} a questo indirizzo email sono:\n\n$2\n\n{{PLURAL:$3|Questa password temporanea scadrà|Queste password temporanee scadranno}} dopo {{PLURAL:$5|un giorno|$5 giorni}}.\nDovresti accedere e scegliere una nuova password ora. \n\nSe non sei stato tu a fare la richiesta, o se ti sei ricordato la password originale e non vuoi più cambiarla, puoi ignorare questo messaggio e continuare al utilizzare la tua vecchia password.",
        "passwordreset-emailtext-user": "L'utente $1 di {{SITENAME}} ha richiesto l'invio di una nuova password per l'accesso a {{SITENAME}} ($4). {{PLURAL:$3|L'utente associato|Gli utenti associati}} a questo indirizzo email sono:\n\n$2\n\n{{PLURAL:$3|Questa password temporanea scadrà|Queste password temporanee scadranno}} dopo {{PLURAL:$5|un giorno|$5 giorni}}.\nDovresti accedere e scegliere una nuova password ora. \n\nSe non sei stato tu a fare la richiesta, o se ti sei ricordato la password originale e non vuoi più cambiarla, puoi ignorare questo messaggio e continuare al utilizzare la tua vecchia password.",
        "preview": "Anteprima",
        "showpreview": "Visualizza anteprima",
        "showdiff": "Mostra modifiche",
-       "anoneditwarning": "'''Attenzione:''' Accesso non effettuato. Nella cronologia della pagina verrà registrato il tuo indirizzo IP.",
+       "blankarticle": "<strong>Attenzione:</strong> la pagina che stai creando è vuota.\nCliccando nuovamente su \"{{int:savearticle}}\", la pagina sarà creata senza alcun contenuto.",
+       "anoneditwarning": "<strong>Attenzione:</strong> Accesso non effettuato. Se effettuerai delle modifiche il tuo indirizzo IP sarà visibile pubblicamente. Se <strong>[$1 accedi]</strong> o <strong>[$2 crei un'utenza]</strong>, le tue modifiche saranno attribuite al tuo nome utente, insieme ad altri benefici.",
        "anonpreviewwarning": "''Non è stato eseguito il login. Salvando la pagina, il proprio indirizzo IP sarà registrato nella cronologia.''",
        "missingsummary": "'''Attenzione:''' non è stato specificato l'oggetto di questa modifica. Premendo di nuovo \"{{int:savearticle}}\" la modifica verrà salvata con l'oggetto vuoto.",
        "missingcommenttext": "Inserire un commento qui sotto.",
        "noarticletext": "In questo momento la pagina richiesta è vuota. È possibile [[Special:Search/{{PAGENAME}}|cercare questo titolo]] nelle altre pagine del sito, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} cercare nei registri correlati] oppure [{{fullurl:{{FULLPAGENAME}}|action=edit}} modificare la pagina ora]</span>.",
        "noarticletext-nopermission": "In questo momento la pagina richiesta è vuota. È possibile [[Special:Search/{{PAGENAME}}|cercare questo titolo]] nelle altre pagine del sito o <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} cercare nei registri correlati]</span>, ma non hai i permessi per creare questa pagina.",
        "missing-revision": "La versione #$1 della pagina \"{{FULLPAGENAME}}\" non esiste.\n\nQuesto si verifica solitamente seguendo un collegamento a una pagina cancellata, in una cronologia non aggiornata.\nI dettagli possono essere trovati nel [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro delle cancellazioni].",
-       "userpage-userdoesnotexist": "L'account \"<nowiki>$1</nowiki>\" non corrisponde a un utente registrato. Verificare che si intenda davvero creare o modificare questa pagina.",
+       "userpage-userdoesnotexist": "L'account \"$1\" non corrisponde a un utente registrato.\nVerificare che si intenda davvero creare o modificare questa pagina.",
        "userpage-userdoesnotexist-view": "L'account utente \"$1\" non è registrato.",
        "blocked-notice-logextract": "Questo utente è attualmente bloccato.\nL'ultimo elemento del registro dei blocchi è riportato di seguito per informazione:",
        "clearyourcache": "'''Nota:''' dopo aver salvato, potrebbe essere necessario pulire la cache del proprio browser per vedere i cambiamenti. \n*'''Firefox / Safari''': tenere premuto il tasto delle maiuscole e fare clic su ''Ricarica'', oppure premere ''Ctrl-F5'' o ''Ctrl-R'' (''⌘-R'' su Mac)\n*'''Google Chrome''': premere ''Ctrl-Shift-R'' (''⌘-Shift-R'' su un Mac)\n*'''Internet Explorer''': tenere premuto il tasto ''Ctrl'' mentre si fa clic su ''Refresh'', oppure premere ''Ctrl-F5''\n*'''Opera''': svuotare completamente la cache dal menu ''Strumenti → Preferenze''",
        "permissionserrors": "Permessi non sufficienti",
        "permissionserrorstext": "Non si dispone dei permessi necessari ad eseguire l'azione richiesta, per {{PLURAL:$1|il seguente motivo|i seguenti motivi}}:",
        "permissionserrorstext-withaction": "Non si dispone dei permessi necessari per $2, per {{PLURAL:$1|il seguente motivo|i seguenti motivi}}:",
-       "recreate-moveddeleted-warn": "'''Attenzione: si sta per ricreare una pagina già cancellata in passato.'''\n\nAccertarsi che sia davvero opportuno continuare a modificare questa pagina.\nL'elenco delle relative cancellazioni e degli spostamenti viene riportato di seguito per comodità:",
+       "recreate-moveddeleted-warn": "<strong>Attenzione: si sta per ricreare una pagina già cancellata in passato.</strong>\n\nAccertarsi che sia davvero opportuno continuare a modificare questa pagina.\nL'elenco delle relative cancellazioni e degli spostamenti viene riportato di seguito per comodità:",
        "moveddeleted-notice": "Questa pagina è stata cancellata. L'elenco delle relative cancellazioni e degli spostamenti viene riportato di seguito per informazione.",
        "log-fulllog": "Visualizza log completo",
        "edit-hook-aborted": "La modifica è stata annullata dall'hook.\nNon è stata restituita alcuna spiegazione.",
        "content-model-css": "CSS",
        "expensive-parserfunction-warning": "'''Attenzione:''' Questa pagina contiene troppe chiamate alle parser functions.\n\nDovrebbe averne meno di $2, al momento ce {{PLURAL:$1|n'è $1|ne sono $1}}.",
        "expensive-parserfunction-category": "Pagine con troppe chiamate alle funzioni parser",
-       "post-expand-template-inclusion-warning": "'''Attenzione:''' la dimensione dei template inclusi è troppo grande.\nAlcuni template non verranno inclusi.",
+       "post-expand-template-inclusion-warning": "<strong>Attenzione:</strong> la dimensione dei template inclusi è troppo grande.\nAlcuni template non verranno inclusi.",
        "post-expand-template-inclusion-category": "Pagine per le quali la dimensione dei template inclusi supera il limite consentito",
        "post-expand-template-argument-warning": "'''Attenzione:''' questa pagina contiene uno o più argomenti di template troppo grandi per essere espansi. Tali argomenti verranno omessi.",
        "post-expand-template-argument-category": "Pagine contenenti template con argomenti mancanti",
        "parser-template-recursion-depth-warning": "È stato raggiunto il limite di ricorsione nel template ($1)",
        "language-converter-depth-warning": "Limite di profondità del convertitore di lingua superato ($1)",
        "node-count-exceeded-category": "Pagine dove viene superato il numero di nodi",
-       "node-count-exceeded-category-desc": "Una categoria per pagine dove viene superato il numero di nodi.",
+       "node-count-exceeded-category-desc": "La pagina supera il numero massimo di nodi.",
        "node-count-exceeded-warning": "Questa pagina ha superato il numero di nodi",
        "expansion-depth-exceeded-category": "Pagine nelle quali è superata la profondità di espansione",
-       "expansion-depth-exceeded-category-desc": "Questa è una categoria per pagine dove viene superata la profondità di espansione.",
+       "expansion-depth-exceeded-category-desc": "La pagina supera la profondità massima di espansione.",
        "expansion-depth-exceeded-warning": "Questa pagina ha superato la profondità di espansione",
        "parser-unstrip-loop-warning": "Rilevato ciclo di Unstrip",
        "parser-unstrip-recursion-limit": "Superati i limiti di ricorsione di Unstrip ($1)",
        "rev-deleted-event": "(azione del log rimossa)",
        "rev-deleted-user-contribs": "[nome utente o indirizzo IP rimosso - edit nascosto dalla cronologia]",
        "rev-deleted-text-permission": "Questa versione della pagina è stata '''cancellata'''.\nConsultare il [{{fullurl:{{#Special:Log}}/delete|page={{PAGENAMEE}}}} log delle cancellazioni] per ulteriori dettagli.",
+       "rev-suppressed-text-permission": "Questa versione della pagina è stata '''soppressa'''.\nConsultare il [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} log delle soppressioni] per ulteriori dettagli.",
        "rev-deleted-text-unhide": "Questa versione della pagina è stata '''cancellata'''.\nConsultare il [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log delle cancellazioni] per ulteriori dettagli.\nAgli amministratori è ancora consentito [$1 visualizzare questa versione] se necessario.",
        "rev-suppressed-text-unhide": "Questa versione della pagina è stata '''rimossa'''.\nConsultare il [{{fullurl:{{#Special:Log}}/suppress|page={{PAGENAMEE}}}} log di rimozione] per ulteriori dettagli.\nAgli amministratori è ancora consentito [$1 visualizzare questa versione] se necessario.",
        "rev-deleted-text-view": "Questa versione della pagina è stata '''cancellata'''.\nGli amministratori possono ancora visualizzarla; consultare il [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log delle cancellazioni] per ulteriori dettagli.",
        "revdelete-show-file-confirm": "Si desidera visualizzare la versione cancellata del file \"<nowiki>$1</nowiki>\" del $2 alle $3?",
        "revdelete-show-file-submit": "Sì",
        "revdelete-selected-text": "{{PLURAL:$1|Versione selezionata|Versioni selezionate}} di [[:$2]]:",
-       "revdelete-selected-file": "{{PLURAL:$1|Versione selezionata|Versioni selezionate}} del file di [[:$2]]:",
-       "logdelete-selected": "{{PLURAL:$1|Evento del registro selezionato|Eventi del registro selezionati}}:",
+       "revdelete-selected-file": "{{PLURAL:$1|Versione selezionata|Versioni selezionate}} del file [[:$2]]:",
+       "logdelete-selected": "{{PLURAL:$1|Evento del registro selezionato|Eventi del registro selezionato}}:",
        "revdelete-text-text": "Le versioni cancellate appariranno ancora nella cronologia della pagina, ma parte del loro contenuto sarà inaccessibile al pubblico.",
        "revdelete-text-file": "Le versioni di file cancellati appariranno ancora nella cronologia del file, ma parti del loro contenuto sarà inaccessibile al pubblico.",
        "logdelete-text": "Gli eventi cancellati appariranno ancora nei registri, ma parti del loro contenuto sarà inaccessibile al pubblico.",
-       "revdelete-text-others": "Altri amministratori di {{SITENAME}} saranno ancora in grado di accedere ai contenuti nascosti e potranno ripristinarli nuovamente attraverso questa stessa interfaccia, se non sono state impostate restrizioni aggiuntive.",
+       "revdelete-text-others": "Altri amministratori saranno ancora in grado di accedere ai contenuti nascosti e potranno ripristinarli, se non sono state impostate restrizioni aggiuntive.",
        "revdelete-confirm": "Per favore conferma che questo è quanto intendi fare, che sei consapevole delle conseguenze, e che stai facendo questo nel rispetto delle [[{{MediaWiki:Policy-url}}|linee guida]].",
        "revdelete-suppress-text": "La rimozione dovrebbe essere utilizzata '''unicamente''' nei seguenti casi:\n* informazioni potenzialmente diffamatorie\n* dati personali inopportuni\n*: ''indirizzi, numeri di telefono, codici fiscali, ecc.''",
        "revdelete-legend": "Imposta le seguenti limitazioni sulle versioni cancellate:",
        "mergehistory-empty": "Nessuna versione da unire.",
        "mergehistory-success": "{{PLURAL:$3|Una versione di [[:$1]] è stata unita|$3 versioni di [[:$1]] sono state unite}} alla cronologia di [[:$2]].",
        "mergehistory-fail": "Impossibile unire le cronologie. Verificare la pagina e i parametri temporali.",
-       "mergehistory-fail-toobig": "Impossibile eseguire l'unione della cronologia con oltre $1 {{PLURAL:$1|revisione|revisioni}} da spostare.",
+       "mergehistory-fail-toobig": "Impossibile eseguire l'unione della cronologia essendoci oltre $1 {{PLURAL:$1|versione|versioni}} da spostare.",
        "mergehistory-no-source": "La pagina di origine $1 non esiste.",
        "mergehistory-no-destination": "La pagina di destinazione $1 non esiste.",
        "mergehistory-invalid-source": "La pagina di origine deve avere un titolo corretto.",
        "showhideselectedversions": "Mostra/nascondi versioni selezionate",
        "editundo": "annulla",
        "diff-empty": "(Nessuna differenza)",
-       "diff-multi-sameuser": "({{PLURAL:$1|Una versione intermedia|$1 versioni intermedie}} di uno stesso utente non sono mostrate )",
+       "diff-multi-sameuser": "({{PLURAL:$1|Una versione intermedia|$1 versioni intermedie}} di uno stesso utente non {{PLURAL:$1|è mostrata|sono mostrate}})",
        "diff-multi-otherusers": "({{PLURAL:$1|Una versione intermedia|$1 versioni intermedie}} di {{PLURAL:$2|un altro utente|$2 utenti}} non mostrate)",
        "diff-multi-manyusers": "({{PLURAL:$1|Una versione intermedia|$1 versioni intermedie}} di oltre $2 {{PLURAL:$2|utente|utenti}} non {{PLURAL:$1|mostrata|mostrate}})",
        "difference-missing-revision": "{{PLURAL:$2|Una versione|$2 versioni}} di questa differenza ($1) {{PLURAL:$2|non è stata trovata|non sono state trovate}}.\n\nQuesto si verifica solitamente seguendo un collegamento obsoleto di un diff a una pagina cancellata.\nI dettagli possono essere trovati nel [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro delle cancellazioni].",
        "searchprofile-advanced-tooltip": "Cerca nei namespace personalizzati",
        "search-result-size": "$1 ({{PLURAL:$2|una parola|$2 parole}})",
        "search-result-category-size": "{{PLURAL:$1|1 utente|$1 utenti}} ({{PLURAL:$2|1 sottocategoria|$2 sottocategorie}}, {{PLURAL:$3|1 file|$3 files}})",
-       "search-result-score": "Rilevanza: $1%",
        "search-redirect": "(redirect $1)",
        "search-section": "(sezione $1)",
        "search-file-match": "(corrispondenza nel contenuto del file)",
        "searchall": "tutti",
        "showingresults": "Di seguito {{PLURAL:$1|viene presentato al massimo '''1''' risultato|vengono presentati al massimo '''$1''' risultati}} a partire dal numero '''$2'''.",
        "showingresultsinrange": "{{PLURAL:$1|Viene mostrato|Vengono mostrati}} sotto {{PLURAL:$1|<strong>1</strong> risultato|<strong>$1</strong> risultati}} dal <strong>$2</strong> al <strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Risultato '''$1''' di '''$3'''|Risultati '''$1 - $2''' di '''$3'''}} per '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Risultato <strong>$1</strong> di <strong>$3</strong>|Risultati <strong>$1 - $2</strong> di <strong>$3</strong>}}",
        "search-nonefound": "La ricerca non ha prodotto risultati.",
        "powersearch-legend": "Ricerca avanzata",
        "powersearch-ns": "Cerca nei namespace:",
        "preferences": "Preferenze",
        "mypreferences": "preferenze",
        "prefs-edits": "Modifiche effettuate:",
-       "prefsnologintext2": "Si prega di $1 per impostare le preferenze dell'utente.",
+       "prefsnologintext2": "Per modificare le tue preferenze è necessario eseguire l'accesso.",
        "prefs-skin": "Aspetto grafico (skin)",
        "skin-preview": "Anteprima",
        "datedefault": "Nessuna preferenza",
        "right-deletedtext": "Visualizza testo cancellato e modifiche fra versioni cancellate",
        "right-browsearchive": "Ricerca nelle pagine cancellate",
        "right-undelete": "Recupera una pagina",
-       "right-suppressrevision": "Rivede e recupera versioni nascoste agli amministratori",
+       "right-suppressrevision": "Vede, nasconde e ripristina versioni specifiche delle pagine a qualsiasi utente",
+       "right-viewsuppressed": "Vede versioni nascoste a qualsiasi utente",
        "right-suppressionlog": "Visualizza i registri privati",
        "right-block": "Blocca le modifiche da parte di altri utenti",
        "right-blockemail": "Impedisce a un utente di inviare email",
        "recentchanges-legend-heading": "'''Legenda:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vedi [[Special:NewPages|le nuove pagine]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Di seguito sono elencate le modifiche apportate a partire da <strong>$2</strong> (mostrate fino a <strong>$1</strong>).",
+       "rcnotefrom": "Di seguito {{PLURAL:$5|è elencata la modifica apportata|sono elencate le modifiche apportate}} a partire da <strong>$3, $4</strong> (mostrate fino a <strong>$1</strong>).",
        "rclistfrom": "Mostra le modifiche apportate a partire da $3 $2",
        "rcshowhideminor": "$1 le modifiche minori",
        "rcshowhideminor-show": "Mostra",
        "upload_directory_missing": "La directory di upload ($1) non esiste e non può essere creata dal server web.",
        "upload_directory_read_only": "Il server web non è in grado di scrivere nella directory di upload ($1).",
        "uploaderror": "Errore nel caricamento",
-       "upload-recreate-warning": "'Attenzione'': un file con questo nome è stato cancellato o spostato.'''\nIll log delle cancellazioni e degli spostamenti di questa pagina viene qui riportato per comodità:",
+       "upload-recreate-warning": "'Attenzione'': un file con questo nome è stato cancellato o spostato.'''\nIl log delle cancellazioni e degli spostamenti di questa pagina viene qui riportato per comodità:",
        "uploadtext": "Usare il modulo sottostante per caricare nuovi file. Per visualizzare o ricercare i file già caricati, consultare il [[Special:FileList|log dei file caricati]]. Caricamenti di file e di nuove versioni di file sono registrati nel [[Special:Log/upload|log degli upload]], le cancellazioni nell'[[Special:Log/delete|apposito]].\n\nPer inserire un file all'interno di una pagina, fare un collegamento di questo tipo:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code>''' per usare la versione completa del file\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|testo alternativo]]</nowiki></code>''' per usare una versione larga 200 pixel inserita in un box, allineata a sinistra e con 'testo alternativo' come didascalia\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' per generare un collegamento diretto al file senza visualizzarlo",
        "upload-permitted": "Tipi di file consentiti: $1.",
        "upload-preferred": "Tipi di file consigliati: $1.",
        "filesource": "Fonte:",
        "ignorewarning": "Ignora l'avviso e salva comunque il file",
        "ignorewarnings": "Ignora i messaggi di avvertimento del sistema",
-       "minlength1": "Il nome del file dev'essere composto da almeno un carattere.",
+       "minlength1": "Il nome del file dev'essere composto da almeno una lettera.",
        "illegalfilename": "Il nome \"$1\" contiene dei caratteri non ammessi nei titoli delle pagine. Dare al file un nome diverso e provare a caricarlo di nuovo.",
        "filename-toolong": "I nomi dei file non possono superare i 240 byte.",
        "badfilename": "Il nome del file è stato convertito in \"$1\".",
        "uploadwarning": "Avviso di caricamento",
        "uploadwarning-text": "Per favore modifica qui sotto la descrizione del file e prova di nuovo.",
        "savefile": "Salva file",
-       "uploadedimage": "ha caricato \"[[$1]]\"",
-       "overwroteimage": "ha caricato una nuova versione di \"[[$1]]\"",
        "uploaddisabled": "Il caricamento dei file è disabilitato.",
        "copyuploaddisabled": "Il caricamento tramite URL è disabilitato.",
        "uploaddisabledtext": "Il caricamento dei file non è attivo.",
        "uploadscriptednamespace": "Questo file SVG contiene un namespace '$1' non consentito",
        "uploadinvalidxml": "Il codice XML nel file caricato non può essere elaborato.",
        "uploadvirus": "Questo file contiene un virus! Dettagli: $1",
-       "uploadjava": "Questo file è un file ZIP che contiene un file .class Java.\nCarica i file Java non è consentito, perché possono causare l'aggiramento delle restrizioni di sicurezza.",
+       "uploadjava": "Questo file è un file ZIP che contiene un file .class Java.\nCaricare i file Java non è consentito, perché possono causare l'aggiramento delle restrizioni di sicurezza.",
        "upload-source": "File di origine",
        "sourcefilename": "Nome del file di origine:",
        "sourceurl": "URL di origine:",
        "backend-fail-backup": "Impossibile eseguire il backup del file $1 .",
        "backend-fail-notexists": "Il file $1 non esiste.",
        "backend-fail-hashes": "Impossibile ottenere hash dei file per confronto.",
-       "backend-fail-notsame": "Esiste già un file non identico a  $1 .",
+       "backend-fail-notsame": "Esiste già un file non identico a \"$1\".",
        "backend-fail-invalidpath": "$1 non è un percorso di archiviazione valido.",
        "backend-fail-delete": "Impossibile cancellare il file $1.",
        "backend-fail-describe": "Impossibile modificare i metadati del file \"$1\".",
        "license": "Licenza:",
        "license-header": "Licenza",
        "nolicense": "Nessuna licenza indicata",
+       "licenses-edit": "Modifica opzioni di licenza",
        "license-nopreview": "(Anteprima non disponibile)",
-       "upload_source_url": " (una URL corretta e accessibile)",
-       "upload_source_file": " (un file sul proprio computer)",
+       "upload_source_url": "(un file da un URL valido e accessibile pubblicamente)",
+       "upload_source_file": "(un file dal tuo computer)",
+       "listfiles-delete": "cancella",
        "listfiles-summary": "Questa pagina speciale mostra tutti i file caricati.",
        "listfiles_search_for": "Ricerca immagini per nome:",
        "imgfile": "file",
        "randomincategory": "Pagina casuale in una categoria",
        "randomincategory-invalidcategory": "\"$1\" non è un nome di categoria valido.",
        "randomincategory-nopages": "Non ci sono pagine in [[:Category:$1]].",
-       "randomincategory-selectcategory": "Ottieni una pagina casuale dalla categoria: $1 $2.",
-       "randomincategory-selectcategory-submit": "Vai",
+       "randomincategory-category": "Categoria:",
+       "randomincategory-legend": "Pagina casuale in una categoria",
        "randomredirect": "Un redirect a caso",
        "randomredirect-nopages": "Non ci sono redirect nel namespace \"$1\".",
        "statistics": "Statistiche",
        "wantedpages": "Pagine più richieste",
        "wantedpages-badtitle": "Titolo non valido nel gruppo di risultati: $1",
        "wantedfiles": "File richiesti",
-       "wantedfiletext-cat": "I seguenti file sono richiamati da wikilink, ma non esistono. I file ospitati su repository esterni potrebbero essere elencati anche se di fatto esistenti. Questi falsi positivi saranno <del>barrati</del>. Le pagine che incorporano i file che non esistono sono elencate in [[:$1]].",
+       "wantedfiletext-cat": "I seguenti file sono utilizzati, ma non esistono. I file ospitati su repository esterni potrebbero essere elencati anche se di fatto esistenti. Questi falsi positivi saranno <del>barrati</del>. Le pagine che incorporano i file che non esistono sono elencate in [[:$1]].",
+       "wantedfiletext-cat-noforeign": "I seguenti file sono utilizzati, ma non esistono. Inoltre, le pagine che incorporano questi file sono elencate nella [[:$1]].",
        "wantedfiletext-nocat": "I seguenti file sono richiamati da wikilink, ma non esistono. I file ospitati su repository esterni potrebbero essere elencati anche se di fatto esistenti. Questi falsi positivi saranno <del>barrati</del>.",
+       "wantedfiletext-nocat-noforeign": "I seguenti file sono utilizzati, ma non esistono.",
        "wantedtemplates": "Template richiesti",
        "mostlinked": "Pagine più richiamate",
        "mostlinkedcategories": "Categorie più richiamate",
-       "mostlinkedtemplates": "Pagine più inlcuse",
+       "mostlinkedtemplates": "Pagine più incluse",
        "mostcategories": "Pagine con più categorie",
        "mostimages": "File più richiamati",
        "mostinterwikis": "Pagine con più interwiki",
        "trackingcategories-desc": "Criteri per l'inclusione nella categoria",
        "noindex-category-desc": "La pagina non è indicizzata dai robot perché contiene la parola magica <code><nowiki>__NOINDEX__</nowiki></code> e si trova in un namespace dove tale flag è consentito.",
        "index-category-desc": "La pagina contiene <code><nowiki>__INDEX__</nowiki></code> (e si trova in un namespace dove tale flag è consentito) e quindi è indicizzata dai robot, anche se normalmente non lo sarebbe.",
-       "post-expand-template-inclusion-category-desc": "Dopo aver espanso tutti i template, la dimensione della pagina sarà più grande di <code>$wgMaxArticleSize</code>, e dunque alcuni non si espanderanno.",
-       "post-expand-template-argument-category-desc": "Dopo aver espanso il parametro di un template (qualcosa tra parentesi graffe, come <code>{{{Foo}}})</code>, la pagina sarà più grande di <code>$wgMaxArticleSize</code>.",
+       "post-expand-template-inclusion-category-desc": "La dimensione della pagina sarà più grande di <code>$wgMaxArticleSize</code> dopo aver espanso tutti i template, e dunque alcuni non si espanderanno.",
+       "post-expand-template-argument-category-desc": "La pagina sarà più grande di <code>$wgMaxArticleSize</code> dopo aver espanso il parametro di un template (qualcosa tra tre parentesi graffe, come <code>{{{Foo}}}</code>).",
        "expensive-parserfunction-category-desc": "La pagina usa troppe funzioni parser (come <code>#ifexist</code>). Vedi [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Categoria aggiunta se la pagina contiene un collegamento interrotto ad un file (un collegamento per incorporare un file quando questo non esiste).",
-       "hidden-category-category-desc": "Questa è una categoria che contiene <code><nowiki>__HIDDENCAT__</nowiki></code>, il quale impedisce che venga mostrata, in modo predefinito, nel riquadro dei collegamenti alle categorie delle pagine.",
+       "broken-file-category-desc": "La pagina contiene un collegamento interrotto ad un file (un collegamento per incorporare un file quando questo non esiste).",
+       "hidden-category-category-desc": "Questa categoria contiene <code><nowiki>__HIDDENCAT__</nowiki></code> nella sua pagina, il quale impedisce che venga mostrata, in modo predefinito, nel riquadro dei collegamenti alle categorie delle pagine.",
        "trackingcategories-nodesc": "Nessuna descrizione disponibile.",
        "trackingcategories-disabled": "La categoria è disabilitata",
        "mailnologin": "Nessun indirizzo cui inviare il messaggio",
        "mywatchlist": "osservati speciali",
        "watchlistfor2": "Dell'utente $1 $2",
        "nowatchlist": "La lista degli osservati speciali è vuota.",
-       "watchlistanontext": "Per visualizzare e modificare l'elenco degli osservati speciali è necessario $1.",
+       "watchlistanontext": "Per visualizzare e modificare l'elenco degli osservati speciali è necessario eseguire l'accesso.",
        "watchnologin": "Accesso non effettuato",
        "addwatch": "Aggiungi agli osservati speciali",
        "addedwatchtext": "La pagina \"[[:$1]]\" è stata aggiunta alla propria [[Special:Watchlist|lista degli osservati speciali]].\nD'ora in poi, le modifiche apportate alla pagina e alla sua discussione verranno elencate in quella sede.",
        "watchlist-details": "La lista degli osservati speciali contiene {{PLURAL:$1|una pagina (e la rispettiva pagina di discussione)|$1 pagine (e le rispettive pagine di discussione)}}.",
        "wlheader-enotif": "La notifica via email è attiva.",
        "wlheader-showupdated": "Le pagine che sono state modificate dopo l'ultima visita sono evidenziate in '''grassetto'''.",
-       "wlnote2": "Di seguito le modifiche {{PLURAL:$1|nell'ultima ora|nelle ultime <strong>$1</strong> ore}}, da $2, $3.",
+       "wlnote": "Di seguito {{PLURAL:$1|è elencata la modifica più recente apportata|sono elencate le <strong>$1</strong> modifiche più recenti apportate}} {{PLURAL:$2|nella scorsa ora|nelle scorse <strong>$2</strong> ore}}; i dati sono aggiornati alle $4 del $3.",
        "wlshowlast": "Mostra le ultime $1 ore $2 giorni $3",
        "watchlist-options": "Opzioni osservati speciali",
        "watching": "Aggiunta agli osservati speciali...",
        "exbeforeblank": "Il contenuto prima dello svuotamento era: '$1'",
        "delete-confirm": "Cancella \"$1\"",
        "delete-legend": "Cancella",
-       "historywarning": "'''Attenzione:''' La pagina che stai per cancellare ha una cronologia con approssimativamente $1 {{PLURAL:$1|versione|versioni}}:",
+       "historywarning": "'''Attenzione:''' La pagina che stai per cancellare ha una cronologia con $1 {{PLURAL:$1|versione|versioni}}:",
        "confirmdeletetext": "Stai per cancellare una pagina con tutta la sua cronologia. Per cortesia, conferma che è tua intenzione procedere a tale cancellazione, che hai piena consapevolezza delle conseguenze della tua azione e che essa è conforme alle linee guida stabilite in [[{{MediaWiki:Policy-url}}]].",
        "actioncomplete": "Azione completata",
        "actionfailed": "Azione fallita",
        "delete-edit-reasonlist": "Modifica i motivi di cancellazione",
        "delete-toobig": "La cronologia di questa pagina è molto lunga (oltre $1 {{PLURAL:$1|versione|versioni}}). La sua cancellazione è stata limitata per evitare di creare accidentalmente dei problemi di funzionamento al database di {{SITENAME}}.",
        "delete-warning-toobig": "La cronologia di questa pagina è molto lunga (oltre $1 {{PLURAL:$1|versione|versioni}}). La sua cancellazione può creare dei problemi di funzionamento al database di {{SITENAME}}; procedere con cautela.",
+       "deleteprotected": "Non puoi cancellare questa pagina perché è stata protetta.",
        "deleting-backlinks-warning": "'''Attenzione:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|altre pagine]] contengono collegamenti o inclusioni alla pagina che stai per cancellare.",
        "rollback": "Annulla le modifiche",
        "rollback_short": "Rollback",
        "autoblockid": "Autoblocco #$1",
        "block": "Blocca utente",
        "unblock": "Sblocca utente",
-       "blockip": "Blocco utente",
+       "blockip": "Blocca {{GENDER:$1|utente}}",
        "blockip-legend": "Blocca l'utente",
        "blockiptext": "Usare il modulo sottostante per bloccare l'accesso in scrittura a uno specifico indirizzo IP o a un utente registrato.\nIl blocco dev'essere operato per prevenire atti di vandalismo e in stretta osservanza delle [[{{MediaWiki:Policy-url}}|regole di {{SITENAME}}]].\nIndicare il motivo specifico per il quale si procede al blocco (per esempio, citando i titoli di eventuali pagine oggetto di vandalismo).",
        "ipaddressorusername": "Indirizzo IP o nome utente:",
        "ipb-unblock-addr": "Sblocca $1",
        "ipb-unblock": "Sblocca un utente o un indirizzo IP",
        "ipb-blocklist": "Elenca i blocchi attivi",
-       "ipb-blocklist-contribs": "Contributi di $1",
+       "ipb-blocklist-contribs": "Contributi di {{GENDER:$1|$1}}",
        "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",
        "unblocked": "L'utente [[User:$1|$1]] è stato sbloccato",
        "unblocked-range": "$1 è stato sbloccato",
        "unblocked-id": "Il blocco $1 è stato rimosso",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] è stato sbloccato.",
        "blocklist": "Utenti bloccati",
        "ipblocklist": "Utenti bloccati",
        "ipblocklist-legend": "Cerca un utente bloccato",
        "movepagetalktext": "La corrispondente pagina di discussione, se esiste, sarà spostata automaticamente insieme alla pagina principale, '''tranne che nei seguenti casi''':\n* lo spostamento della pagina è tra namespace diversi;\n* in corrispondenza del nuovo titolo esiste già una pagina di discussione (non vuota);\n* la casella qui sotto è stata deselezionata.\n\nIn questi casi, se lo si ritiene opportuno, occorre spostare o aggiungere manualmente le informazioni contenute nella pagina di discussione.",
        "movearticle": "Sposta la pagina:",
        "moveuserpage-warning": "'''Attenzione:''' Si sta per spostare una pagina utente. Nota che verrà spostata solamente la pagina. L'utente ''non'' sarà rinominato.",
-       "movecategorypage-warning": "<strong>Attenzione:</strong> stai per spostare una categoria. Solo la pagina verrà spostata, ma tutte le pagine nella vecchia categoria <em>non</em> saranno inserite nella nuova.",
+       "movecategorypage-warning": "<strong>Attenzione:</strong> si sta per spostare una categoria. Solo questa pagina verrà spostata: tutte le pagine nella vecchia categoria <em>non</em> saranno inserite nella nuova.",
        "movenologintext": "Lo spostamento delle pagine è consentito solo agli utenti registrati che hanno eseguito l'[[Special:UserLogin|accesso]] al sito.",
        "movenotallowed": "Non si dispone dei permessi necessari per spostare le pagine.",
        "movenotallowedfile": "Non si dispone dei permessi necessari per spostare i file.",
        "import": "Importa pagine",
        "importinterwiki": "Importazione transwiki",
        "import-interwiki-text": "Selezionare un progetto wiki e il titolo della pagina da importare.\nLe date di pubblicazione e i nomi degli autori delle varie versioni saranno conservati.\nTutte le operazioni di importazione trans-wiki sono registrate nel [[Special:Log/import|log di importazione]].",
-       "import-interwiki-source": "Sorgente wiki/pagina:",
+       "import-interwiki-sourcewiki": "Wiki di origine:",
+       "import-interwiki-sourcepage": "Pagina di origine:",
        "import-interwiki-history": "Copia l'intera cronologia di questa pagina",
        "import-interwiki-templates": "Includi tutti i template",
        "import-interwiki-submit": "Importa",
        "import-invalid-interwiki": "Impossibile importare dal progetto wiki indicato.",
        "import-error-edit": "La pagina \"$1\" non è stata importata poiché non sei autorizzato a modificarla.",
        "import-error-create": "La pagina \"$1\" non è stata importata poiché non sei autorizzato a crearla.",
-       "import-error-interwiki": "La pagina \"$1\" non viene importata perché il suo nome è riservato per il collegamento esterno (interwiki).",
-       "import-error-special": "La pagina \"$1\" non viene importata perché appartiene a un namespace speciale che non permette pagine.",
-       "import-error-invalid": "La pagina \"$1\" non viene importata perché il suo nome non è valido.",
+       "import-error-interwiki": "La pagina \"$1\" non è stata importata perché il suo nome è riservato per il collegamento esterno (interwiki).",
+       "import-error-special": "La pagina \"$1\" non è stata importata perché appartiene a un namespace speciale che non permette pagine.",
+       "import-error-invalid": "La pagina \"$1\" non è stata importata perché il nome a cui sarebbe stata importata non è valido su questo wiki.",
        "import-error-unserialize": "La versione $2 della pagina \"$1\" non può essere de-serializzata. La versione è stata segnalata per utilizzare il modello di contenuto $3 serializzato come $4.",
        "import-error-bad-location": "La versione $2 usa un modello di contenuto $3 che non può essere memorizzato in \"$1\" di questo wiki, poiché la pagina non supporta questo modello.",
        "import-options-wrong": "{{PLURAL:$2|Opzione sbagliata|Opzioni sbagliate}}: <nowiki>$1</nowiki>",
        "autosumm-replace": "Pagina sostituita con '$1'",
        "autoredircomment": "Redirect alla pagina [[$1]]",
        "autosumm-new": "Creata pagina con \"$1\"",
+       "autosumm-newblank": "Creata pagina vuota",
        "size-bytes": "$1 byte",
        "lag-warn-normal": "Le modifiche apportate {{PLURAL:$1|nell'ultimo secondo|negli ultimi $1 secondi}} potrebbero non apparire in questa lista.",
        "lag-warn-high": "A causa di un eccessivo ritardo nell'aggiornamento del server di database, le modifiche apportate {{PLURAL:$1|nell'ultimo secondo|negli ultimi $1 secondi}} potrebbero non apparire in questa lista.",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discussioni]])",
        "unknown_extension_tag": "Tag estensione sconosciuto: \"$1\"",
        "duplicate-defaultsort": "Attenzione: la chiave di ordinamento predefinita \"$2\" sostituisce la precedente \"$1\".",
+       "duplicate-displaytitle": "<strong>Attenzione:</strong> il titolo visualizzato \"$2\" sostituisce il precedente titolo \"$1\".",
        "version": "Versione",
        "version-extensions": "Estensioni installate",
        "version-skins": "Skin installate",
        "logentry-rights-rights": "$1 {{GENDER:$2|ha modificato}} l'appartenenza di $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",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|ha caricato}} una nuova versione di $3.",
+       "logentry-upload-revert": "$1 {{GENDER:$2|ha caricato}} $3",
        "rightsnone": "(nessuno)",
        "feedback-bugornote": "Se si è in grado di descrivere il problema tecnico riscontrato in maniera precisa, [$1 segnalate il bug]. In alternativa, si può usare il modulo semplificato sottostante. Il commento inserito sarà aggiunto alla pagina \"[$3 $2]\", insieme al proprio nome utente e al browser in uso.",
        "feedback-subject": "Oggetto:",
        "action-pagelang": "modificare la lingua della pagina",
        "log-name-pagelang": "Modifiche lingua",
        "log-description-pagelang": "Questo è un registro delle modifiche alla lingua delle pagine.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|ha modificato}} la lingua della pagina $3 da $4 a $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|ha modificato}} la lingua della pagina $3 da $4 a $5.",
+       "default-skin-not-found": "Oops! La skin predefinita per il tuo wiki, definita in <code dir=\"ltr\">$wgDefaultSkin</code> come <code>$1</code>, non è disponibile.\n\nLa tua installazione sembra includere le seguenti skin. Vedi [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manuale: configurazione skin] per informazioni su come abilitarle e scegliere quella predefinita.\n\n$2\n\n; Se hai appena installato MediaWiki:\n: Probabilmente lo hai installato da git, o direttamente dal codice sorgente usando qualche altro metodo. Ciò era previsto. Prova ad installare alcune skin dalla [https://www.mediawiki.org/wiki/Category:All_skins directory su mediawiki.org], tramite:\n:* Scaricando il [https://www.mediawiki.org/wiki/Download programma di installazione tarball], che viene fornito con diverse skin ed estensioni. Puoi fare copia ed incolla della directory <code dir=\"ltr\">skins/</code> da lì.\n:* Clonando uno dei repository <code>mediawiki/skins/*</code> tramite git nella directory <code>skins/</code> della tua installazione MediaWiki.\n: In questo modo non dovrebbe interferire con il tuo repository git se sei uno sviluppatore MediaWiki.\n\n; Se hai appena aggiornato MediaWiki:\n: MediaWiki 1.24 e versioni successive non abilità più automaticamente le skin installate (vedi [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manuale: rilevamento automatico skin]). Puoi copiare le seguenti linee nel <code>LocalSettings.php</code> per abilitare tutte le skin attualmente installate:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Se hai appena modificato <code>LocalSettings.php</code>:\n: Ricontrolla i nomi delle skin per errori di battitura.",
+       "default-skin-not-found-no-skins": "Oops! La skin predefinita per il tuo wiki, definita in <code>$wgDefaultSkin</code> come <code>$1</code>, non è disponibile.\n\nNon hai skin installate.\n\n; Se hai appena installato o aggiornato MediaWiki:\n: Probabilmente lo hai installato da git, o direttamente dal codice sorgente usando qualche altro metodo. Ciò era previsto. MediaWiki 1.24 e versioni successive non include alcuna skin nel repository principale. Prova ad installare alcune skin dalla [https://www.mediawiki.org/wiki/Category:All_skins directory su mediawiki.org], tramite:\n:* Scaricando il [https://www.mediawiki.org/wiki/Download programma di installazione tarball], che viene fornito con diverse skin ed estensioni. Puoi fare copia ed incolla della directory <code>skins/</code> da lì.\n:* Clonando uno dei repository <code>mediawiki/skins/*</code> tramite git nella directory <code dir=\"ltr\">skins/</code> della tua installazione MediaWiki.\n: In questo modo non dovrebbe interferire con il tuo repository git se sei uno sviluppatore MediaWiki. Vedi [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manuale: configurazione skin] per informazioni su come abilitarle e scegliere quella predefinita.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (abilitata)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''disabilitata''')"
 }
index 4457755..66f0fea 100644 (file)
@@ -77,6 +77,7 @@
        "tog-watchdefault": "自分が編集したページやファイルをウォッチリストに追加",
        "tog-watchmoves": "自分が移動したページやファイルをウォッチリストに追加",
        "tog-watchdeletion": "自分が削除したページやファイルをウォッチリストに追加",
+       "tog-watchrollback": "ロールバックしたページをウォッチリストに追加",
        "tog-minordefault": "細部の編集に既定でチェックを入れる",
        "tog-previewontop": "プレビューを編集ボックスの前に配置",
        "tog-previewonfirst": "編集開始時にもプレビューを表示",
        "tog-fancysig": "署名をウィキ文として扱う (自動リンクなし)",
        "tog-uselivepreview": "ライブプレビューを使用 (開発中)",
        "tog-forceeditsummary": "要約欄が空欄の場合に確認を促す",
-       "tog-watchlisthideown": "ウォッチリストに自分の編集を表示しない",
-       "tog-watchlisthidebots": "ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88ã\81«ã\83\9cã\83\83ã\83\88ã\81«ã\82\88ã\82\8bç·¨é\9b\86ã\82\92表示しない",
-       "tog-watchlisthideminor": "ウォッチリストに細部の編集を表示しない",
-       "tog-watchlisthideliu": "ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88ã\81«ã\83­ã\82°ã\82¤ã\83³å\88©ç\94¨è\80\85ã\81«ã\82\88ã\82\8bç·¨é\9b\86ã\82\92表示しない",
-       "tog-watchlisthideanons": "ウォッチリストに匿名利用者による編集を表示しない",
-       "tog-watchlisthidepatrolled": "ウォッチリストに巡回済みの編集を表示しない",
+       "tog-watchlisthideown": "自分の編集をウォッチリストに表示しない",
+       "tog-watchlisthidebots": "ã\83\9cã\83\83ã\83\88ã\81«ã\82\88ã\82\8bç·¨é\9b\86ã\82\92ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88ã\81«表示しない",
+       "tog-watchlisthideminor": "細部の編集をウォッチリストに表示しない",
+       "tog-watchlisthideliu": "ã\83­ã\82°ã\82¤ã\83³å\88©ç\94¨è\80\85ã\81«ã\82\88ã\82\8bç·¨é\9b\86ã\82\92ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88ã\81«表示しない",
+       "tog-watchlisthideanons": "匿名利用者による編集をウォッチリストに表示しない",
+       "tog-watchlisthidepatrolled": "巡回済みの編集をウォッチリストに表示しない",
        "tog-ccmeonemails": "他の利用者に送信したメールの控えを自分にも送信",
        "tog-diffonly": "差分の下にページ内容を表示しない",
        "tog-showhiddencats": "隠しカテゴリを表示",
        "newwindow": "(新しいウィンドウで開きます)",
        "cancel": "中止",
        "moredotdotdot": "続き...",
-       "morenotlisted": "ã\81\93ã\81®ä¸\80覧ã\81®ç¶\9aã\81\8d",
+       "morenotlisted": "ã\81\93ã\81®ä¸\80覧ã\81¯å®\8cå\85¨ã\81§ã\81¯ã\81\82ã\82\8aã\81¾ã\81\9bã\82\93ã\80\82",
        "mypage": "ページ",
-       "mytalk": "トーク",
-       "anontalk": "ã\81\93ã\81®IPã\82¢ã\83\89ã\83¬ã\82¹ã\81®ã\83\88ã\83¼ã\82¯",
+       "mytalk": "議論",
+       "anontalk": "ã\81\93ã\81®IPã\82¢ã\83\89ã\83¬ã\82¹ã\81«ã\81¤ã\81\84ã\81¦ã\81®è­°è«\96",
        "navigation": "案内",
-       "and": "&#32;ã\81\8aã\82\88ã\81³&#32;",
+       "and": "&#32;ã\81¨",
        "qbfind": "検索",
        "qbbrowse": "閲覧",
        "qbedit": "編集",
        "searcharticle": "表示",
        "history": "ページの履歴",
        "history_short": "履歴",
-       "updatedmarker": "最終閲覧以降に変更されました",
+       "updatedmarker": "前回の閲覧以降に更新されました",
        "printableversion": "印刷用バージョン",
        "permalink": "この版への固定リンク",
        "print": "印刷",
        "talkpagelinktext": "トーク",
        "specialpage": "特別ページ",
        "personaltools": "個人用ツール",
-       "postcomment": "新しい節",
        "articlepage": "本文を表示",
        "talk": "議論",
        "views": "表示",
        "hidetoc": "非表示",
        "collapsible-collapse": "折り畳む",
        "collapsible-expand": "展開する",
+       "confirmable-confirm": "{{GENDER:$1|}}本当によろしいですか?",
+       "confirmable-yes": "はい",
+       "confirmable-no": "いいえ",
        "thisisdeleted": "$1を閲覧または復元しますか?",
        "viewdeleted": "$1を閲覧しますか?",
        "restorelink": "{{PLURAL:$1|削除された$1編集}}",
        "invalidtitle-knownnamespace": "名前空間名「$2」と名前「$3」の組み合わせはページ名として無効です",
        "invalidtitle-unknownnamespace": "不明な名前空間番号 $1 と名前「$2」の組み合わせはページ名として無効です",
        "exception-nologin": "ログインしていません",
-       "exception-nologin-text": "このページまたは操作にアクセスできるようにするには[[Special:Userlogin|ログイン]]してください。",
+       "exception-nologin-text": "このページまたは操作にアクセスできるようにするにはログインしてください。",
        "exception-nologin-text-manual": "このページまたは操作にアクセスできるようにするには$1してください。",
        "virus-badscanner": "環境設定が不適合です: 不明なウイルス対策ソフトウェア: <em>$1</em>",
        "virus-scanfailed": "スキャンに失敗しました (コード $1)",
        "externaldberror": "認証データベースでエラーが発生した、または外部アカウントの更新が許可されていません。",
        "login": "ログイン",
        "nav-login-createaccount": "ログインまたはアカウント作成",
-       "loginprompt": "{{SITENAME}}にログインするにはCookieを有効にする必要があります。",
        "userlogin": "ログインまたはアカウント作成",
        "userloginnocreate": "ログイン",
        "logout": "ログアウト",
        "userlogin-resetlink": "ログイン情報をお忘れですか?",
        "userlogin-resetpassword-link": "パスワードをお忘れですか?",
        "userlogin-helplink2": "ログインについてのヘルプ",
-       "userlogin-loggedin": "{{GENDER:$1|$1}} として既にログインしています。\n別の利用者としてログインするには下のフォームを使用してください。",
-       "userlogin-createanother": "別アカウントを作成",
        "createacct-emailrequired": "メールアドレス",
        "createacct-emailoptional": "メールアドレス (省略可能)",
        "createacct-email-ph": "メールアドレスを入力",
        "createaccount-text": "誰か (おそらくあなた) が、{{SITENAME}} ($4) にあなたのメールアドレスのアカウントを作成しました。\nアカウント名「$2」、パスワード「$3」です。\n今すぐログインしてパスワードを変更してください。\n\nこのアカウントが何かの手違いで作成された場合は、このメッセージを無視してください。",
        "login-throttled": "ログインの失敗が制限回数を超えました。\n$1待ってから再度試してください。",
        "login-abort-generic": "ログインに失敗しました - 中止",
+       "login-migrated-generic": "あなたのアカウントは移行が完了しており、その利用者名はこのウィキにはもう存在しません。",
        "loginlanguagelabel": "言語: $1",
        "suspicious-userlogout": "壊れたブラウザーまたはキャッシュプロキシによって送信された可能性があるため、ログアウト要求は拒否されました。",
        "createacct-another-realname-tip": "本名は省略できます。\n入力すると、その利用者の著作物の帰属表示に使われます。",
        "preview": "プレビュー",
        "showpreview": "プレビューを表示",
        "showdiff": "差分を表示",
-       "anoneditwarning": "<strong>警告:</strong> ログインしていません。\n編集すると、IPアドレスがこのページの編集履歴に記録されます。",
+       "blankarticle": "<strong>警告:</strong>作成しようとしているページの内容がありません。{{Int:savearticle}}\"をもう一度クリックすると、中身の無いページが作成されます。",
+       "anoneditwarning": "<strong>警告:</strong> ログインしていません。編集を行うと、あなたの IP アドレスが公開されます。<strong>[$1 ログイン]</strong>または<strong>[$2 アカウントを作成]</strong>すれば、あなたの編集はその利用者名とともに表示されるほか、その他の利点もあります。",
        "anonpreviewwarning": "<em>ログインしていません。投稿を保存すると、ご使用中のIPアドレスがこのページの履歴に記録されます。</em>",
        "missingsummary": "<strong>注意:</strong> 編集内容の要約が空欄です。\n「{{int:savearticle}}」をもう一度クリックすると、編集内容は要約なしで保存されます。",
        "missingcommenttext": "以下にコメントを入力してください。",
        "parser-template-recursion-depth-warning": "テンプレートの再帰の深さ ($1) が上限を超えました",
        "language-converter-depth-warning": "言語変換機能の深さ ($1) が制限を超えました",
        "node-count-exceeded-category": "ノード数が制限を超えたページ",
-       "node-count-exceeded-category-desc": "ノード数が制限を超えたページを列挙するカテゴリです。",
+       "node-count-exceeded-category-desc": "ノード数が上限を超えたページ。",
        "node-count-exceeded-warning": "ページがノード数の制限を超えました",
        "expansion-depth-exceeded-category": "展開の深さ制限を超えたページ",
-       "expansion-depth-exceeded-category-desc": "このカテゴリでは、展開の深さが制限を超えたページを列挙します。",
+       "expansion-depth-exceeded-category-desc": "展開の深さが上限を超えたページ。",
        "expansion-depth-exceeded-warning": "ページが展開の深さ制限を超えました",
        "parser-unstrip-loop-warning": "unstrip のループを検出しました",
        "parser-unstrip-recursion-limit": "unstrip の再帰 ($1) が上限を超えました",
        "rev-deleted-event": "(記録は除去されています)",
        "rev-deleted-user-contribs": "[利用者名またはIPアドレスは除去されました - その編集は投稿記録で非表示にされています]",
        "rev-deleted-text-permission": "この版は<strong>削除されています</strong>。\n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 削除記録]に詳細情報があるかもしれません。",
+       "rev-suppressed-text-permission": "この版は<strong>秘匿されています</strong>。[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 秘匿記録]に詳細情報があるかもしれません。",
        "rev-deleted-text-unhide": "この版は<strong>削除されています</strong>。\n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 削除記録]に詳細情報があるかもしれません。\nこのまま[$1 この版を閲覧]できます。",
        "rev-suppressed-text-unhide": "この版は<strong>秘匿されています</strong>。\n[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 秘匿記録]に詳細情報があるかもしれません。\nこのまま[$1 この版を閲覧]できます。",
        "rev-deleted-text-view": "この版は<strong>削除されています</strong>。\n内容を閲覧できます。[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 削除記録]に詳細情報があるかもしれません。",
        "logdelete-selected": "{{PLURAL:$1|選択された記録項目}}:",
        "revdelete-text-text": "削除された版は履歴に表示され続けますが、一般の利用者が内容を閲覧できなくなります。",
        "revdelete-text-file": "削除されたファイルの版はファイルの履歴に表示されつづけますが、一般の利用者はその内容の一部を閲覧できなくなります。",
-       "logdelete-text": "削除された記録項目は記録に表示されつづけますが、一般の利用者はその内容の一部を閲覧できなくなります。",
-       "revdelete-text-others": "追加の制限を設定しない限り、{{SITENAME}} の他の管理者は非表示コンテンツにまだアクセスでき、この同じインターフェースを通してそれを復元することができます。",
+       "logdelete-text": "削除された記録項目は記録に表示されけますが、一般の利用者はその内容の一部を閲覧できなくなります。",
+       "revdelete-text-others": "追加の制限を設定しない限り、他の管理者は非表示コンテンツにまだアクセスすることも復元することもできます。",
        "revdelete-confirm": "この操作を行おうとしていること、その結果を理解していること、[[{{MediaWiki:Policy-url}}|方針]]に従っていること、を確認してください。",
        "revdelete-suppress-text": "秘匿は、<strong>以下の場合に限って</strong>使用すべきです:\n* 名誉毀損のおそれがある記述\n* 非公開個人情報\n*: <em>自宅の住所、電話番号、個人を識別できる公的な番号など</em>",
        "revdelete-legend": "閲覧レベル制限を設定",
        "searchprofile-advanced-tooltip": "特定の名前空間内を検索",
        "search-result-size": "$1 ({{PLURAL:$2|$2 単語}})",
        "search-result-category-size": "{{PLURAL:$1|$1 件}} ({{PLURAL:$2|$2 下位カテゴリ}}、{{PLURAL:$3|$3 ファイル}})",
-       "search-result-score": "関連度: $1%",
        "search-redirect": "($1からのリダイレクト)",
        "search-section": "($1の節)",
        "search-file-match": "(ファイルの内容との一致)",
        "searchall": "すべて",
        "showingresults": "<strong>$2</strong> 件目以降の最大 {{PLURAL:$1|<strong>$1</strong> 件の結果}}を表示しています。",
        "showingresultsinrange": "<strong>$2</strong> 件目から<strong>$3</strong> 件目までの範囲内で最大 {{PLURAL:$1|<strong>$1</strong> 件の結果}}を表示しています。",
-       "showingresultsheader": "「<strong>$4</strong>」の検索結果 {{PLURAL:$5|<strong>$3</strong> 件中の <strong>$1</strong> 件目|<strong>$3</strong> 件中の <strong>$1</strong> 件目から <strong>$2</strong> 件目}}",
        "search-nonefound": "問い合わせに合致する検索結果はありませんでした。",
        "powersearch-legend": "高度な検索",
        "powersearch-ns": "名前空間を指定して検索:",
        "preferences": "個人設定",
        "mypreferences": "個人設定",
        "prefs-edits": "編集回数:",
-       "prefsnologintext2": "個人設定を変更するには$1してください。",
+       "prefsnologintext2": "個人設定を変更するにはログインしてください。",
        "prefs-skin": "外装",
        "skin-preview": "プレビュー",
        "datedefault": "選択なし",
        "right-deletedtext": "削除された本文と削除された版間の差分を閲覧",
        "right-browsearchive": "削除されたページを検索",
        "right-undelete": "ページを復元",
-       "right-suppressrevision": "管理者から隠された版を確認/復元",
+       "right-suppressrevision": "すべての利用者からの特定の版を見る、隠す、あるいは隠すのをやめる",
+       "right-viewsuppressed": "すべての利用者から隠された版を閲覧",
        "right-suppressionlog": "非公開記録を閲覧",
        "right-block": "他の利用者の編集をブロック",
        "right-blockemail": "利用者のメール送信をブロック",
        "recentchanges-legend-heading": "'''凡例:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|新しいページ一覧]]も参照)",
        "recentchanges-legend-plusminus": "(<em>±123</em>)",
-       "rcnotefrom": "以下は<strong>$2</strong>以降の更新です (最大 <strong>$1</strong> 件)。",
+       "rcnotefrom": "以下は<strong>$3 $4</strong>以降の{{PLURAL:$5|更新です}} (最大 <strong>$1</strong> 件)。",
        "rclistfrom": "$3の$2以降の更新を表示する",
        "rcshowhideminor": "細部の編集を$1",
        "rcshowhideminor-show": "表示",
        "uploadwarning": "アップロード警告",
        "uploadwarning-text": "下記のファイル解説を修正して再試行してください。",
        "savefile": "ファイルを保存",
-       "uploadedimage": "「[[$1]]」をアップロードしました",
-       "overwroteimage": "「[[$1]]」の新しい版をアップロードしました",
        "uploaddisabled": "アップロード機能は無効になっています。",
        "copyuploaddisabled": "URL からのアップロードは無効になっています。",
        "uploaddisabledtext": "ファイルのアップロードは、無効になっています。",
        "license": "ライセンス:",
        "license-header": "ライセンス",
        "nolicense": "選択なし",
+       "licenses-edit": "ライセンスオプションを編集",
        "license-nopreview": "(プレビューはありません)",
-       "upload_source_url": "(有効かつ一般に公開されている URL)",
-       "upload_source_file": "(あなたのコンピューター上のファイル)",
+       "upload_source_url": "(一般に公開されている、有効な URL からファイルを選択)",
+       "upload_source_file": "(あなたのコンピューター上からファイルを選択)",
+       "listfiles-delete": "削除",
        "listfiles-summary": "この特別ページでは、アップロードされたファイルをすべて表示します。",
        "listfiles_search_for": "検索するメディア名:",
        "imgfile": "ファイル",
        "randomincategory": "カテゴリ内でおまかせ表示",
        "randomincategory-invalidcategory": "「$1」は有効なカテゴリ名ではありません。",
        "randomincategory-nopages": "カテゴリ [[:Category:$1|$1]] にはページがありません。",
-       "randomincategory-selectcategory": "以下のカテゴリでおまかせ表示: $1 $2",
-       "randomincategory-selectcategory-submit": "表示",
+       "randomincategory-category": "カテゴリ:",
+       "randomincategory-legend": "カテゴリ内でおまかせ表示",
        "randomredirect": "おまかせリダイレクト",
        "randomredirect-nopages": "「$1」名前空間に転送ページはありません。",
        "statistics": "統計",
        "wantedpages-badtitle": "結果が、無効なページ名を含んでいます: $1",
        "wantedfiles": "ファイル情報ページが存在しないファイル",
        "wantedfiletext-cat": "以下のファイルは使用されていますが存在しません。外部リポジトリ由来のファイルは、存在していてもここに列挙される場合があります。その場合は<del>取り消し線</del>が付きます。さらに、存在しないファイルを埋め込んでいるページは[[:$1]]に列挙されます。",
+       "wantedfiletext-cat-noforeign": "以下のファイルは使用されていますが存在しません。さらに、存在しないファイルを埋め込んでいるページは[[:$1]]に列挙されます。",
        "wantedfiletext-nocat": "以下のファイルは使用されていますが存在しません。外部リポジトリ由来のファイルは、存在していてもここに列挙される場合があります。その場合は<del>取り消し線</del>が付きます。",
+       "wantedfiletext-nocat-noforeign": "以下のファイルは使用されていますが存在しません。",
        "wantedtemplates": "呼び出し先が存在しないテンプレート呼び出し",
        "mostlinked": "被リンク数の多いページ",
        "mostlinkedcategories": "被リンク数の多いカテゴリ",
        "post-expand-template-inclusion-category-desc": "テンプレートを展開したあとのページ サイズが <code>$wgMaxArticleSize</code> よりも大きいため、一部のテンプレートが展開されなかった",
        "post-expand-template-argument-category-desc": "テンプレート引数 (<code>{{{Foo}}}</code> のような三重中括弧部分) を展開したあとのページが <code>$wgMaxArticleSize</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> を含むカテゴリ。このカテゴリは、既定ではページのカテゴリ リンク ボックス内に表示されません。",
+       "broken-file-category-desc": "リンク切れしたファイルを含むページ (ファイルを埋め込むリンクがあり、そのファイルが存在しない)",
+       "hidden-category-category-desc": "ページの本文に <code><nowiki>__HIDDENCAT__</nowiki></code> を含むカテゴリ。このカテゴリは既定ではページのカテゴリ リンク ボックス内に表示されません。",
        "trackingcategories-nodesc": "説明はありません。",
        "trackingcategories-disabled": "このカテゴリは無効化されています",
        "mailnologin": "送信アドレスがありません",
        "mywatchlist": "ウォッチリスト",
        "watchlistfor2": "利用者: $1 $2",
        "nowatchlist": "ウォッチリストには何も項目がありません。",
-       "watchlistanontext": "ウォッチリストにある項目を閲覧または編集するには、$1してください。",
+       "watchlistanontext": "ウォッチリストにある項目を閲覧または編集するには、ログインしてください。",
        "watchnologin": "ログインしていません",
        "addwatch": "ウォッチリストに追加",
        "addedwatchtext": "ページ「[[:$1]]」を[[Special:Watchlist|ウォッチリスト]]に追加しました。\nこのページまたはそのトークページが変更されると、ウォッチリストに表示されます。",
        "watchlist-details": "ウォッチリストには {{PLURAL:$1|$1 ページ}}が登録されています (トークページを除く)。",
        "wlheader-enotif": "メール通知が有効になっています。",
        "wlheader-showupdated": "最終訪問以降に変更されたページは、<strong>太字</strong>で表示されます。",
-       "wlnote2": "以下は $2 $3 までの {{PLURAL:$1|<strong>$1</strong> 時間}}でなされた変更です。",
-       "wlshowlast": "次の期間で表示: $1時間、$2日間、$3",
+       "wlnote": "$3 $4 までの{{PLURAL:$2|<strong>$2</strong>時間}}になされた{{PLURAL:$1|<strong>$1</strong>件の変更}}は以下の通りです。",
+       "wlshowlast": "表示する期間: $1時間、$2日間、$3",
        "watchlist-options": "ウォッチリストのオプション",
        "watching": "ウォッチリストに追加中...",
        "unwatching": "ウォッチリストから除去中...",
        "exbeforeblank": "白紙化前の内容:「$1」",
        "delete-confirm": "「$1」の削除",
        "delete-legend": "削除",
-       "historywarning": "<strong>警告:</strong> 削除しようとしているページには、$1版の履歴があります:",
+       "historywarning": "<strong>警告:</strong> 削除しようとしているページには、$1版の履歴があります:",
        "confirmdeletetext": "ページをすべての履歴とともに削除しようとしています。\n本当にこの操作を行いたいか、操作の結果を理解しているか、およびこの操作が[[{{MediaWiki:Policy-url}}|方針]]に従っているかどうか、確認してください。",
        "actioncomplete": "操作を完了しました",
        "actionfailed": "操作に失敗しました",
        "delete-edit-reasonlist": "削除理由を編集",
        "delete-toobig": "このページには、$1版を超える編集履歴があります。\nこのようなページの削除は、{{SITENAME}}の偶発的な問題を避けるため、制限されています。",
        "delete-warning-toobig": "このページには、 $1版を超える編集履歴があります。\n削除すると、{{SITENAME}}のデータベース処理に大きな負荷がかかります。\n十分に注意してください。",
+       "deleteprotected": "このページは保護されているため削除できません。",
        "deleting-backlinks-warning": "'''警告:''' 削除しようとしているページは、[[Special:WhatLinksHere/{{FULLPAGENAME}}|他のページ]]からリンクまたは参照読み込みされています。",
        "rollback": "編集を巻き戻し",
        "rollback_short": "巻き戻し",
        "autoblockid": "自動ブロック #$1",
        "block": "利用者をブロック",
        "unblock": "利用者のブロックを解除",
-       "blockip": "利用者をブロック",
+       "blockip": "{{GENDER:$1|利用者}}をブロック",
        "blockip-legend": "利用者をブロック",
        "blockiptext": "以下のフォームを使用して、指定したIPアドレスまたは利用者からの書き込みアクセスをブロックできます。\nこのような措置は、荒らしからの防御の目的のみに行われるべきで、また[[{{MediaWiki:Policy-url}}|方針]]に沿ったものであるべきです。\n以下にブロックの理由を具体的に書いてください (例えば、荒らされたページへの言及など)。",
        "ipaddressorusername": "IPアドレスまたは利用者名:",
        "ipb-unblock-addr": "$1のブロックを解除",
        "ipb-unblock": "利用者またはIPアドレスのブロックを解除",
        "ipb-blocklist": "現在有効なブロックを表示",
-       "ipb-blocklist-contribs": "$1の投稿の一覧",
+       "ipb-blocklist-contribs": "{{GENDER:$1|$1}}の投稿の一覧",
        "unblockip": "ブロックを解除",
        "unblockiptext": "以下のフォームで利用者またはIPアドレスのブロックを解除できます。",
        "ipusubmit": "このブロックを解除",
        "import": "ページデータの取り込み",
        "importinterwiki": "ウィキ間移動の取り込み",
        "import-interwiki-text": "取り込むウィキとページ名を選択してください。\n版の日付と編集者名は保持されます。\nウィキ間移動のすべての取り込み操作は[[Special:Log/import|取り込み記録]]に記録されます。",
-       "import-interwiki-source": "取り込み元のウィキ/ページ:",
+       "import-interwiki-sourcewiki": "取り込み元のウィキ:",
+       "import-interwiki-sourcepage": "取り込み元のページ:",
        "import-interwiki-history": "このページのすべての版を複製する",
        "import-interwiki-templates": "すべてのテンプレートを含める",
        "import-interwiki-submit": "取り込み",
        "import-error-edit": "あなたにそのページを編集する許可がないため、ページ「$1」は取り込まれませんでした。",
        "import-error-create": "あなたにそのページを作成する許可がないため、ページ「$1」は取り込まれませんでした。",
        "import-error-interwiki": "ページ名が外部リンク (ウィキ間リンク) に予約されているため、ページ「$1」を取り込みませんでした。",
-       "import-error-special": "ページ「$1」は、ページが許可されない特別名前空間に属しているため取り込みません。",
-       "import-error-invalid": "名前が正しくないため、ページ「$1」を取り込みませんでした。",
+       "import-error-special": "ã\83\9aã\83¼ã\82¸ã\80\8c$1ã\80\8dã\81¯ã\80\81ã\83\9aã\83¼ã\82¸ã\81\8c許å\8f¯ã\81\95ã\82\8cã\81ªã\81\84ç\89¹å\88¥å\90\8då\89\8d空é\96\93ã\81«å±\9eã\81\97ã\81¦ã\81\84ã\82\8bã\81\9fã\82\81å\8f\96ã\82\8aè¾¼ã\81¿ã\81¾ã\81\9bã\82\93ã\81§ã\81\97ã\81\9fã\80\82",
+       "import-error-invalid": "ページ「$1」は、このウィキでは名前が無効であるため、取り込めませんでした。",
        "import-error-unserialize": "ページ「$1」の版 $2 はシリアライズ解除できませんでした。この版は $4 としてシリアライズされたコンテンツモデル $3 を使用していると報告されています。",
        "import-error-bad-location": "コンテンツモデル $3 はこのページではサポート外のため、モデル $3 を使用している版 $2 はこのウィキ上の「$1」に保存できません。",
        "import-options-wrong": "間違った{{PLURAL:$2|オプション}}です: <nowiki>$1</nowiki>",
        "importlogpage": "取り込み記録",
        "importlogpagetext": "管理された他のウィキから編集履歴を伴ったページ取り込みです。",
        "import-logentry-upload": "ファイルのアップロードにより[[$1]]を取り込みました",
-       "import-logentry-upload-detail": "$1{{PLURAL:$1|版}}",
+       "import-logentry-upload-detail": "$1{{PLURAL:$1|版}} をインポートしました",
        "import-logentry-interwiki": "$1をウィキ間移動しました",
-       "import-logentry-interwiki-detail": "$2の$1{{PLURAL:$1|版}}",
+       "import-logentry-interwiki-detail": "$2ã\81\8bã\82\89ã\82¤ã\83³ã\83\9dã\83¼ã\83\88æ¸\88ã\81¿ã\81®$1{{PLURAL:$1|ç\89\88}}",
        "javascripttest": "JavaScript をテスト中",
        "javascripttest-title": "$1 のテストの実行",
        "javascripttest-pagetext-noframework": "このページは JavaScript のテストを実行するために予約されています。",
        "autosumm-replace": "内容を「$1」で置換",
        "autoredircomment": "[[$1]]への転送ページ",
        "autosumm-new": "ページの作成:「$1」",
+       "autosumm-newblank": "空白のページを作成しました",
        "size-bytes": "$1バイト",
        "size-kilobytes": "$1キロバイト",
        "size-megabytes": "$1メガバイト",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|トーク]])",
        "unknown_extension_tag": "不明な拡張機能タグ「$1」です",
        "duplicate-defaultsort": "<strong>警告:</strong> 既定のソートキー「$2」が、その前に書かれている既定のソートキー「$1」を上書きしています。",
+       "duplicate-displaytitle": "<strong>警告:</strong> 既定のDISPLAYTITLE「$2」が、その前に書かれている既定のDISPLAYTITLE「$1」を上書きしています。",
        "version": "バージョン情報",
        "version-extensions": "インストール済み拡張機能",
        "version-skins": "インストール済み外装",
        "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|アップロードしました}}",
        "rightsnone": "(なし)",
        "feedback-bugornote": "技術的な問題の詳細を説明する準備ができている場合は、[$1 バグ報告]をお願いします。\n準備ができていない場合は、下の簡易フォームを使用してください。あなたのコメントと利用者名が、ページ「[$3 $2]」に追加されます。",
        "feedback-subject": "件名:",
        "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>$1</code>」 (<code>$wgDefaultSkin</code>)は利用できません。\n\nあなたのインストールには以下の外装が含まれています。外装の有効化と既定の選択については、[https://www.mediawiki.org/wiki/Manual:Skin_configuration マニュアル: 外装設定] をご覧ください。\n\n$2\n\n; MediaWikiをインストールしたばかりの場合:\n: gitからインストールしたか、その他の何らかの方法でソースコードから直接インストールした場合には、これは期待されたとおりの動作です。\n:* [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's skin directory] から外装をインストールしてみてください。\n:* [https://www.mediawiki.org/wiki/Download tarball installer] をダウンロードしてみてください。これにはいくつかの外装と拡張機能が含まれています。 <code>skins/</code> ディレクトリからコピー&ペーストできます。\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>$1</code>」 (<code>$wgDefaultSkin</code>)は利用できません。\n\n外装をインストールしていません。\n\n; MediaWikiをインストールしたばかりの場合:\n: gitからインストールしたか、その他の何らかの方法でソースコードから直接インストールした場合には、これは期待されたとおりの動作です。\n:* [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's skin directory] から外装をインストールしてみてください。\n:* [https://www.mediawiki.org/wiki/Download tarball installer] をダウンロードしてみてください。これには外装と拡張機能がいくつか含まれています。 <code>skins/</code> ディレクトリからコピー&ペーストできます。\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 ('''無効''')"
 }
index d7054bf..81bc7a8 100644 (file)
        "talkpagelinktext": "Chat",
        "specialpage": "Peshal piej",
        "personaltools": "Persnal tuuldem",
-       "postcomment": "Nyuu sekshan",
        "articlepage": "Vyuu kantent piej",
        "talk": "Diskoshan",
        "views": "Vyuu",
        "externaldberror": "Aida aatentikieshan dietabies era okor ar yu no lou fi opdiet yu extoernal akount.",
        "login": "Lag iin",
        "nav-login-createaccount": "Lag iin / kriet akount",
-       "loginprompt": "Yu mos ab kukidem eniebl fi lag iin tu {{SITENAME}}.",
        "userlogin": "Lag iin / kriet akount",
        "userloginnocreate": "Lag iin",
        "logout": "Lag out",
        "recentchangeslinked-to": "Shuo chienjdem tu piej wa lingk tu di gibn piej insted",
        "upload": "Opluod fail",
        "uploadlogpage": "Opluod lag",
-       "uploadedimage": "opluodid \"[[$1]]\"",
        "filehist": "Fail ischri",
        "filehist-help": "Klik pan a diet/taim fi vyuu di fail az ou iapier a di taim.",
        "filehist-current": "korant",
index 4f91578..1e4aa6b 100644 (file)
@@ -6,7 +6,8 @@
                        "Urhixidur",
                        "Xabier Armendaritz",
                        "Ælsån",
-                       "Midnight Gambler"
+                       "Midnight Gambler",
+                       "아라"
                ]
        },
        "tog-underline": "Understreg henvesnenger",
@@ -17,7 +18,6 @@
        "tog-showtoolbar": "Ves værktøjslenje til redigærenge",
        "tog-editondblclick": "Redigær sider ve dåbeltklik",
        "tog-editsectiononrightclick": "Redigær åfsnet ve at klikke på deres titler",
-       "tog-rememberpassword": "Husk adgengskode til næste besøĝ frå denne kompjuter (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "tog-watchcreations": "Tilføj sider a åpretter til miin åvervågnengsliste",
        "tog-watchdefault": "Tilføj sider a redigærer til miin åvervågnengsliste",
        "tog-watchmoves": "Tilføj sider a flytter til miin åvervågnengsliste",
        "talkpagelinktext": "diskusje",
        "specialpage": "Sonst side",
        "personaltools": "Personlige værktø'r",
-       "postcomment": "Tilføj en biskrevselenger",
        "articlepage": "Se'n ertikel",
        "talk": "Diskusje",
        "views": "Vesnenger",
        "filedeleteerror": "Kan ekke slette'n file \"$1\".",
        "directorycreateerror": "Kan ekke åprette katalåget \"$1\".",
        "filenotfound": "Kan ekke finde'n file \"$1\".",
-       "fileexistserror": "Kan ekke åprette \"$1\": æ file findes ålrede",
        "unexpected": "Uventet værdi: \"$1\"=\"$2\".",
        "formerror": "Fejl: Kan ekke åfsende formulær",
        "badtitle": "Førkert skrevselenger",
        "remembermypassword": "Husk min adgangskode til næste gang (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "login": "Loĝ på",
        "nav-login-createaccount": "Åpret æ konto æller loĝ på",
-       "loginprompt": "Du skal have cookies slået til før at kunne loĝge på {{SITENAME}}.",
        "userlogin": "Åpret æ konto æller loĝ på",
        "logout": "Loĝ åf",
        "userlogout": "Loĝ åf",
        "recentchanges": "Seneste ændrenger",
        "recentchanges-feed-description": "Ve dette fiid ken du følge de seneste ændrenger på {{SITENAME}}.",
        "rcnotefrom": "Nedenfør ses ændrengerne frå '''$2''' til '''$1''' vest.",
-       "rclistfrom": "Ves nye ændrenger startende frå $1",
+       "rclistfrom": "Ves nye ændrenger startende frå $3 $2",
        "rcshowhideminor": "$1 lile ændrenger",
        "rcshowhidebots": "$1 råbotter",
        "rcshowhideliu": "$1 regestrerede brugere",
        "upload": "Læĝ æ billet åp",
        "uploadbtn": "Læĝ æ gøret åp",
        "uploadlogpage": "Åplægnengslog",
-       "uploadedimage": "Låĝde \"[[$1]]\" åp",
        "listfiles": "Billetliste",
        "file-anchor-link": "Billet",
        "filehist": "Billetskigt",
        "log": "Loglister",
        "all-logs-page": "Åle loglister",
        "allpages": "Åle ertikler",
-       "alphaindexline": "$1 til $2",
        "nextpage": "Næste side ($1)",
        "prevpage": "Førge side ($1)",
        "allpagesfrom": "Ves sider startende frå:",
index 3a6b61b..0f1efd1 100644 (file)
        "talkpagelinktext": "Wicara",
        "specialpage": "Kaca astaméwa",
        "personaltools": "Piranti pribadi",
-       "postcomment": "Bagéyan anyar",
        "articlepage": "nDeleng artikel",
        "talk": "Dhiskusi",
        "views": "Tampilan",
        "externaldberror": "Ana kasalahan otèntikasi basis dhata èksternal utawa panjenengan ora pareng nglakoni pemutakhiran marang akun èksternal panjenengan.",
        "login": "Mlebu log",
        "nav-login-createaccount": "Log mlebu / nggawé rékening (akun)",
-       "loginprompt": "Panjenengan kudu ngaktifaké ''cookies'' supaya bisa mlebu (log in) ing {{SITENAME}}.",
        "userlogin": "Mlebu log / gawé rékening (akun)",
        "userloginnocreate": "Mlebu log",
        "logout": "Oncat",
        "searchprofile-advanced-tooltip": "Panggolèkan ing bilik jeneng biasa (''custom'')",
        "search-result-size": "$1 ({{PLURAL:$2|1 tembung|$2 tembung}})",
        "search-result-category-size": "{{PLURAL:$1|1 anggota|$1 anggota}} ({{PLURAL:$2|1 subkatégori|$2 subkatégori}}, {{PLURAL:$3|1 berkas|$3 berkas}})",
-       "search-result-score": "Relevansi: $1%",
        "search-redirect": "(pangalihan $1)",
        "search-section": "(sèksi $1)",
        "search-suggest": "Apa panjenengan kersané: $1",
        "uploadwarning": "Pèngetan pangunggahan berkas",
        "uploadwarning-text": "Mangga owah katrangan berkas nèng ngisor lan coba manèh.",
        "savefile": "Simpen berkas",
-       "uploadedimage": "gambar \"[[$1]]\" kaunggahaké",
-       "overwroteimage": "ngunggahaké vèrsi anyar saka \"[[$1]]\"",
        "uploaddisabled": "Nuwun sèwu, fasilitas pangunggahan dipatèni.",
        "copyuploaddisabled": "Ngunggah mawa URL dipatèni.",
        "uploaddisabledtext": "Pangunggahan berkas ora diidinaké.",
        "watchlist-details": "Ngawasaké {{PLURAL:$1|$1 kaca|$1 kaca}}, ora kalebu kaca-kaca dhiskusi.",
        "wlheader-enotif": "Notifikasi layang elektronik diaktifaké.",
        "wlheader-showupdated": "Kaca-kaca sing wis owah wiwit ditiliki panjenengan kaping pungkasan, dituduhaké mawa '''aksara kandel'''",
+       "wlnote": "Ngisor iki {{PLURAL:$1|owahan pungkasan|'''$1''' owahan pungkasan}} {{PLURAL:$2|jam|'''$2''' jam}} kapungkur, per $3, $4.",
        "wlshowlast": "Tuduhna $1 jam $2 dina $3 pungkasan",
        "watchlist-options": "Opsi daftar pangawasan",
        "watching": "Ngawasi...",
        "duplicate-defaultsort": "Pènget: Kunci pilih asal (''Default sort key'') \"$2\" nggantèkaké kunci pilih asal sadurungé \"$1\".",
        "version": "Versi",
        "version-extensions": "Èkstènsi sing wis diinstalasi",
+       "version-skins": "Kulit",
        "version-specialpages": "Kaca astaméwa (kaca kusus)",
        "version-parserhooks": "Canthèlan parser",
        "version-variables": "Variabel",
        "version-antispam": "Pambendhung spam",
-       "version-skins": "Kulit",
        "version-other": "Liyané",
        "version-mediahandlers": "Pananganan média",
        "version-hooks": "Canthèlan-canthèlan",
index 857fa17..71bb713 100644 (file)
        "talkpagelinktext": "განხილვა",
        "specialpage": "სპეციალური გვერდი",
        "personaltools": "პირადი ხელსაწყოები",
-       "postcomment": "ახალი სექცია",
        "articlepage": "სტატიის ნახვა",
        "talk": "განხილვა",
        "views": "გადახედვა",
        "hidetoc": "დამალვა",
        "collapsible-collapse": "ჩაკეცვა",
        "collapsible-expand": "გაშლა",
+       "confirmable-confirm": "{{GENDER:$1|დარწმუნებული}} ხართ?",
+       "confirmable-yes": "დიახ",
+       "confirmable-no": "არა",
        "thisisdeleted": "$1-ის ჩვენება თუ აღდგენა?",
        "viewdeleted": "იხილე $1?",
        "restorelink": "{{PLURAL:$1|ერთი წაშლილი რედაქტირება|$1 წაშლილი რედაქტირება}}",
        "invalidtitle-knownnamespace": "დაუშვებელი სათაური სახელთა სივრცე \"$2\" და ტექსტი \"$3\"-თან",
        "invalidtitle-unknownnamespace": "დაუშვებელი სათაური უცნობი სახელთა სივრცის ნომერი $1 და ტექსტი \"$2\"-ით",
        "exception-nologin": "შესვლა არ განხორციელდა",
-       "exception-nologin-text": "á\83\90á\83\9b á\83\92á\83\95á\83\94á\83 á\83\93á\83\98á\83¡ á\83¡á\83\90á\83\9cá\83\90á\83®á\83\90á\83\95á\83\90á\83\93 á\83\90á\83\9c á\83\9bá\83\9dá\83\97á\83®á\83\9dá\83\95á\83\9cá\83\98á\83\9aá\83\98 á\83\9bá\83\9dá\83¥á\83\9bá\83\94á\83\93á\83\94á\83\91á\83\98á\83¡ á\83¨á\83\94á\83¡á\83\90á\83¡á\83 á\83£á\83\9aá\83\94á\83\91á\83\9aá\83\90á\83\93 á\83¡á\83\90á\83­á\83\98á\83 á\83\9dá\83\90 [[Special:Userlogin|á\83¡á\83\98á\83¡á\83¢á\83\94á\83\9bá\83\90á\83¨á\83\98 á\83¨á\83\94á\83¡á\83\95á\83\9aá\83\90]].",
+       "exception-nologin-text": "á\83\90á\83\9b á\83\92á\83\95á\83\94á\83 á\83\93á\83\96á\83\94 á\83¬á\83\95á\83\93á\83\9dá\83\9bá\83\98á\83¡á\83\90á\83\97á\83\95á\83\98á\83¡ á\83\90á\83\9c á\83\9bá\83\9dá\83¥á\83\9bá\83\94á\83\93á\83\94á\83\91á\83\98á\83¡á\83\97á\83\95á\83\98á\83¡ á\83¡á\83\90á\83­á\83\98á\83 á\83\9dá\83\90 á\83¡á\83\98á\83¡á\83¢á\83\94á\83\9bá\83\90á\83¨á\83\98 á\83¨á\83\94á\83¡á\83\95á\83\9aá\83\90.",
        "virus-badscanner": "შეცდომა. ვირუსთა უცნობი სკანერი: ''$1''",
        "virus-scanfailed": "სკანირების შეცდომა  (კოდი $1)",
        "virus-unknownscanner": "უცნობი ანტივირუსი:",
        "externaldberror": "საგარეო მონაცემთა ბაზაში აუტენტიფიკაციის შეცდომაა, ან თქვენ არ გაქვთ საკმარისი უფლებები საგარეო ანგარიშში ცვლილებების შესატანად.",
        "login": "შესვლა",
        "nav-login-createaccount": "შესვლა / რეგისტრაცია",
-       "loginprompt": "{{SITENAME}}-ში შესასვლელად საჭიროა კუკის (cookies) გააქტიურება.",
        "userlogin": "შესვლა/ანგარიშის შექმნა",
        "userloginnocreate": "შესვლა",
        "logout": "გასვლა",
        "userlogin-resetlink": "ავტორიზაციის მონაცემები დაგავიწყდათ?",
        "userlogin-resetpassword-link": "დაგავიწყდათ პაროლი?",
        "userlogin-helplink2": "დახმარება:შესვლა",
-       "userlogin-createanother": "სხვა ანგარიშის შექმნა",
        "createacct-emailrequired": "ელ. ფოსტის მისამართი",
        "createacct-emailoptional": "ელ. ფოსტის მისამართი (არასავალდებულო)",
        "createacct-email-ph": "შეიყვანეთ თქვენი ელ. ფოსტის მისამართი",
        "currentrev": "მიმდინარე შესწორება",
        "currentrev-asof": "მიმდინარე ცვლილება $1 მდგომარეობით",
        "revisionasof": "$1-ის ვერსია",
-       "revision-info": "$1-ის ვერსია, შეტანილი $2-ის მიერ",
+       "revision-info": "$1-ის ვერსია, {{GENDER:$6|$2}}$7",
        "previousrevision": "←წინა ვერსია",
        "nextrevision": "შემდეგი ვერსია→",
        "currentrevisionlink": "მიმდინარე ვერსია",
        "searchprofile-advanced-tooltip": "ძიება სახელთა მოცემულ სივრცეში",
        "search-result-size": "$1 ($2 სიტყვა)",
        "search-result-category-size": "{{PLURAL:$1|$1 ელემენტი|$1 ელემენტი|$1 ელემენტები}} ({{PLURAL:$2|$2 ქვეკატეგორია|$2 ქვეკატეგორიები|$2 ქვეკატეგორიები}}, {{PLURAL:$3|$3 ფაილი|$3 ფაილი|$3 ფაილი}})",
-       "search-result-score": "რელევანტურობა $1 %",
        "search-redirect": "(გადამისამართება $1)",
        "search-section": "(სექცია $1)",
        "search-file-match": "(ემთხვევა ფაილის შინაარსს)",
        "right-deletedtext": "წაშლილი ტექსტის და განსხვავებების ხილვა.",
        "right-browsearchive": "წაშლილი გვერდების ძიება",
        "right-undelete": "გვერდის აღდგენა",
-       "right-suppressrevision": "á\83\90á\83\93á\83\9bá\83\98á\83\9cá\83\97á\83\90á\83\92á\83\90á\83\9c á\83\93á\83\90á\83\9bá\83\90á\83\9aá\83£á\83\9aá\83\98 á\83\92á\83\95á\83\94á\83 á\83\93á\83\94á\83\91á\83\98á\83¡ á\83®á\83\98á\83\9aá\83\95á\83\90 á\83\93á\83\90 á\83\90á\83¦á\83\93á\83\92á\83\94á\83\9cá\83\90",
+       "right-suppressrevision": "á\83\92á\83\95á\83\94á\83 á\83\93á\83\94á\83\91á\83\98á\83¡ á\83\93á\83\90á\83\9bá\83\90á\83\9aá\83£á\83\9aá\83\98 á\83\95á\83\94á\83 á\83¡á\83\98á\83\94á\83\91á\83\98á\83¡ á\83®á\83\98á\83\9aá\83\95á\83\90, á\83\93á\83\90á\83\9bá\83\90á\83\9aá\83\95á\83\90 á\83\93á\83\90 á\83\90á\83¦á\83\93á\83\92á\83\94á\83\9cá\83\90 á\83§á\83\95á\83\94á\83\9aá\83\90 á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\9aá\83\98á\83¡á\83\92á\83\90á\83\9c",
        "right-suppressionlog": "კერძო ჟურნალების ნახვა",
        "right-block": "სხვა მომხმარებლების მიერ რედაქტირების აკრძალვა",
        "right-blockemail": "ელ ფოსტის გაგზავნის აკრძალვა",
        "uploadwarning": "გადატვირთვის შეხსენება",
        "uploadwarning-text": "გთხოვთ ჩაასწოროთ ფაილის აღწერა ქვევით და ხელმეორედ სცადოთ.",
        "savefile": "ფაილის შენახვა",
-       "uploadedimage": "აიტვირთა „[[$1]]“",
-       "overwroteimage": "ატვირთულია „[[$1]]-ის“ ახალი ვერსია",
        "uploaddisabled": "ატვირთვა გამორთულია.",
        "copyuploaddisabled": "URL ატვირთვა გაღიშულია",
        "uploaddisabledtext": "ფაილების ატვირთვა შეუძლებელია.",
        "license-header": "ლიცენზია",
        "nolicense": "არაფერი არის მონიშნული",
        "license-nopreview": "(წინასწარ გადახედვა არ არის ხელმისაწვდომი)",
-       "upload_source_url": " (სწორი, საზოგადოდ ხელმისაწვდომი URL)",
-       "upload_source_file": " (ფაილი შენს კომპიუტერზე)",
+       "upload_source_url": "(თქვენ აირჩიეთ სწორი, საზოგადოდ ხელმისაწვდომი URL)",
+       "upload_source_file": "(თქვენ აირჩიეთ ფაილი თქვენი კომპიუტერიდან)",
+       "listfiles-delete": "წაშლა",
        "listfiles-summary": "ეს სპეციალური გვერდი აჩვენებს ყველა ატვირთულ ფაილს.",
        "listfiles_search_for": "ძიება სურათის სახელის მიხედვით:",
        "imgfile": "ფაილი",
        "randompage-nopages": "{{PLURAL:$2|სახელთა შემდეგი სივრცე|სახელთა შემდეგ სივრცეში}} \"$1\" არ არის გვერდები.",
        "randomincategory": "კატეგორიის შემთხვევითი გვერდი",
        "randomincategory-invalidcategory": "კატეგორია „$1“ არ არსებობს.",
-       "randomincategory-selectcategory-submit": "მიდი",
        "randomredirect": "ნებისმიერი გადამისამართება",
        "randomredirect-nopages": "სახელთა სივრცეში „$1“ არ არის გადამისამართებები.",
        "statistics": "სტატისტიკა",
        "protectedpages": "დაცული გვერდები",
        "protectedpages-indef": "მხოლოდ უვადო დაცვები",
        "protectedpages-cascade": "მხოლოდ კასკადური დაცვა",
+       "protectedpages-noredirect": "გადამისამართებების დამალვა",
        "protectedpagesempty": "ამ დროისთვის არ არსებობს დაცული გვერდები მოთხოვნილი პარამეტრებით.",
+       "protectedpages-timestamp": "თარიღი/დრო",
        "protectedpages-page": "გვერდი",
        "protectedpages-expiry": "ვადა გასდის",
+       "protectedpages-performer": "მომხმარებლის დაცვა",
+       "protectedpages-params": "დაცვის პარამეტრები",
        "protectedpages-reason": "მიზეზი",
        "protectedpages-unknown-timestamp": "უცნობი",
        "protectedpages-unknown-performer": "უცნობი მომხმარებელი",
        "watchlist-details": "$1 გვერდია თქვენი კონტროლის სიაში განხილვის გვერდების ჩაუთვლელად.",
        "wlheader-enotif": "ელ.ფოსტით შეტყობინება ჩართულია.",
        "wlheader-showupdated": "თქვენი ბოლო ვიზიტის შემდეგ შეცვლილი გვერდები, აღნიშნულია '''მუქად'''.",
+       "wlnote": "ქვემოთ {{PLURAL:$1|ნაჩვენებია ბოლო ცვლილება|ნაჩვენებია ბოლო '''$1''' ცვლილება}} უკანასკნელი {{PLURAL:$2|საათის|'''$2''' საათის}} მანძილზე, $3, $4 მდგომარეობით.",
        "wlshowlast": "აჩვენე ბოლო $1 საათის $2 დღის $3",
        "watchlist-options": "კონტროლის სიის პარამეტრები",
        "watching": "კონტროლებადი...",
        "autoblockid": "ავტომატური ბლოკირება #$1",
        "block": "მომხმარებლის დაბლოკვა",
        "unblock": "მომხმარებელზე ბლოკის მოხსნა",
-       "blockip": "á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\9aá\83\98á\83¡ á\83\90á\83\9c IP á\83\9bá\83\98á\83¡á\83\90á\83\9bá\83\90á\83 á\83\97á\83\98á\83¡ á\83\91á\83\9aá\83\9dá\83\99á\83\98á\83 á\83\94á\83\91á\83\90",
+       "blockip": "á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\94á\83\9a {{GENDER:$1|á\83\93á\83\90á\83\91á\83\9aá\83\9dá\83\99á\83\95á\83\90}}",
        "blockip-legend": "მომხმარებლის დაბლოკვა",
        "blockiptext": "გამოიყენეთ ქვემოთ მოყვანილი ფორმა სპეციფიური IP მისამართის\nან მომხმარებლისთვის რედაქტირების ბლოკირებისთვის.\nამის გაკეთება შეიძლება მხოლოდ ვანდალიზმის ასარიდებლად,\nდა [[{{MediaWiki:Policy-url}}|პოლიტიკასთან]] თანხმობაში.\nჩაწერეთ სპეციფიური მიზეზი ქვემოთ (მაგ. მიუთითეთ გვერდები,\nრომლებზეც ვანდალიზმი განხორციელდა).",
        "ipaddressorusername": "IP მისამართი ან მომხმარებლის სახელი",
        "ipb-unblock-addr": "ბლოკის მოხსნა $1",
        "ipb-unblock": "მომხმარებლის სახელზე ან IP მისამართზე ბლოკის მოხსნა",
        "ipb-blocklist": "იხილე არსებული ბლოკირებები",
-       "ipb-blocklist-contribs": "$1 მომხმარებლის წვლილი",
+       "ipb-blocklist-contribs": "მომხმარებელ {{GENDER:$1|$1}} წვლილი",
        "unblockip": "მომხმარებელზე ბლოკის მოხსნა",
        "unblockiptext": "გამოიყენეთ ქვემოთ მოცემული ფორმულარი, რათა  დაბლოკილი IP მისამართი ან მომხმარებლის სახელი აღადგინოთ.",
        "ipusubmit": "ამ ბლოკის მოხსნა",
        "import": "გვერდების იმპორტი",
        "importinterwiki": "ტრანსვიკი იმპორტი",
        "import-interwiki-text": "წარმოადგინეთ ვიკი და იმპორტირებადი გვერდის სახელი.\nცვლილებათა რიცხვები და ავტორთა სახელები შენნარჩუნდება.\nტრანსვიკი იმპორტის ყველა ოპერაცია რეგისტრირდება [[Special:Log/import|სპეციალურ ჟურნალში]].",
-       "import-interwiki-source": "ვიკი წყარო/გვერდი:",
        "import-interwiki-history": "ამ გვერდის ცვლილებათა ისტორიის კოპირება.",
        "import-interwiki-templates": "ყველა თარგის ჩართვა",
        "import-interwiki-submit": "იმპორტირება",
        "duplicate-defaultsort": "'''ყურადღება.'''სორტირების გასაღებს «$2»-ს გააჭრის წინა გასაღებს «$1»-ს.",
        "version": "ვერსია",
        "version-extensions": "დაყენებული გაფართოებები",
+       "version-skins": "იერსახე",
        "version-specialpages": "სპეციალური გვერდები",
        "version-parserhooks": "სინტაქსური ანალიზატორის ჰუკები",
        "version-variables": "ცვალებადი",
        "version-antispam": "სპამის პრევენცია",
-       "version-skins": "იერსახე",
        "version-api": "API",
        "version-other": "სხვა",
        "version-mediahandlers": "მედია დამუშავება",
        "version-hook-name": "ჰუკის სახელი",
        "version-hook-subscribedby": "ჩაწერილია",
        "version-version": "(ვერსია $1)",
+       "version-no-ext-name": "[სახელის გარეშე]",
        "version-svn-revision": "(r$2)",
        "version-license": "მედიავიკის ლიცენზია",
        "version-ext-license": "ლიცენზია",
        "version-ext-colheader-name": "გაფართოებები",
+       "version-skin-colheader-name": "იერსახე",
        "version-ext-colheader-version": "ვერსია",
        "version-ext-colheader-license": "ლიცენზია",
        "version-ext-colheader-description": "აღწერა",
        "expand_templates_ok": "შესრულება",
        "expand_templates_remove_comments": "კომენტარების წაშლა",
        "expand_templates_remove_nowiki": "ტეგების დათრგუნვა <nowiki> შედეგში",
-       "expand_templates_preview": "წინა"
+       "expand_templates_preview": "წინა",
+       "pagelanguage": "გვერდის ენის არჩევა",
+       "pagelang-name": "გვერდი",
+       "pagelang-language": "ენა",
+       "pagelang-use-default": "საწყისი ენის გამოყენება",
+       "pagelang-select-lang": "აირჩიეთ ენა",
+       "right-pagelang": "გვერდის ენის შეცვლა",
+       "action-pagelang": "გვერდის ენის შეცვლა",
+       "log-name-pagelang": "ენის ცვლილებების ჟურნალი",
+       "log-description-pagelang": "ეს არის გვერდის ენის ცვლილებების ჟურნალი",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (ჩართულია)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''გამორთულია''')"
 }
index 8380ac5..f5237ee 100644 (file)
        "talkpagelinktext": "Sa'wbet",
        "specialpage": "Arnawlı bet",
        "personaltools": "Paydalanıwshı a'sbapları",
-       "postcomment": "Taza bo'lim",
        "articlepage": "Mag'lıwmat betin ko'riw",
        "talk": "Diskussiya",
        "views": "Ko'rinis",
        "yourdomainname": "Sizin' domen:",
        "login": "Kiriw",
        "nav-login-createaccount": "Kiriw / akkaunt jaratıw",
-       "loginprompt": "{{SITENAME}} saytına kiriw ushın kukiler qosılg'an bolıwı kerek.",
        "userlogin": "Kiriw / akkaunt jaratıw",
        "logout": "Shıg'ıw",
        "userlogout": "Shıg'ıw",
        "searchprofile-everything-tooltip": "Barlıq betlerde izlew (sa'wbet betlerin qosıp)",
        "searchprofile-advanced-tooltip": "Berilgen isimler ko'pliginde izlew",
        "search-result-size": "$1 ({{PLURAL:$2|1 so'z|$2 so'z}})",
-       "search-result-score": "Qatnasıqlıg'ı: $1%",
        "search-redirect": "(qayta bag'ıtlandırıw $1)",
        "search-section": "(bo'lim $1)",
        "search-suggest": "Ba'lkim, siz bunı na'zerde tutqan shig'arsız: $1",
        "largefileserver": "Bul faildın mo'lsheri serverdin' ruxsatınan u'lken.",
        "uploadwarning": "Aploud eskertiwi",
        "savefile": "Fayldı saqla",
-       "uploadedimage": "«[[$1]]» faylı aploud qılındı",
-       "overwroteimage": "\"[[$1]]\" faylının' jan'a nusqası aploud qılındı",
        "uploaddisabled": "Aploudqa ruxsat berilmegen",
        "uploaddisabledtext": "Fayllardı aploud qılıw toqtatılg'an.",
        "uploadvirus": "Bul failda virus bar! Mag'lıwmat: $1",
        "notvisiblerev": "Nusqa o'shirildi",
        "watchlist-details": "Baqlaw dizimin'izde (sa'wbet betlerin esapqa almag'anda) {{PLURAL:$1|1 bet|$1 bet}} bar.",
        "wlheader-enotif": "E-mail arqalı eskertiw qosılg'an.",
+       "wlnote": "To'mende aqırg'ı {{PLURAL:$2|saattag'ı|'''$2''' saattag'ı}} {{PLURAL:$1|aqırg'ı o'zgeris bar|aqırg'ı '''$1''' o'zgeris bar}}.",
        "wlshowlast": "Aqırg'ı $1 saat, $2 ku'n, $3 ko'rset",
        "watchlist-options": "Baqlaw diziminin' sazlawları",
        "watching": "Baqlaw...",
index acd010c..256af44 100644 (file)
        "talkpagelinktext": "Mmeslay",
        "specialpage": "Asebter uslig",
        "personaltools": "Dduzan inu",
-       "postcomment": "Azen awennit",
        "articlepage": "Ẓer ayen yellan deg usebter",
        "talk": "Amyannan",
        "views": "Tuẓrin",
        "externaldberror": "Yella ugul aberrani n database neɣ ur tettalaseḍ ara ad tbeddleḍ isem an wemseqdac aberrani inek.",
        "login": "Kcem",
        "nav-login-createaccount": "Kcem / Xleq isem n wemseqdac",
-       "loginprompt": "Yessefk ad teǧǧiḍ ikukiyen (cookies) iwakken ad tkecmeḍ ar {{SITENAME}}.",
        "userlogin": "Kcem / Xleq isem n wemseqdac",
        "userloginnocreate": "Qqen",
        "logout": "Ffeɣ",
        "searchprofile-advanced-tooltip": "Fren ideggen n isemawen i unadi",
        "search-result-size": "$1 ({{PLURAL:$2|1 awal|$2 awalen}})",
        "search-result-category-size": "$1 {{PLURAL:$1|amseqdac|imseqdacen}} $2 ({{PLURAL:$2|adu-taggayt|adu-tiggayin}}, $3 {{PLURAL:$3|afaylu|ifuyla}})",
-       "search-result-score": "Taflest : $1%",
        "search-redirect": "(asemmimeḍ $1)",
        "search-section": "(tigezmi $1)",
        "search-file-match": "(yzega i ugbur n ufaylu)",
        "uploadwarning": "Aɣtal deg wazan n ufayluwen",
        "uploadwarning-text": "Beddel aglam n ufaylu dɣa ɛreḍ tikkelt nniḍen",
        "savefile": "Smekti afaylu",
-       "uploadedimage": "\"[[$1]]\" yettwazen",
-       "overwroteimage": "yekter lqem amaynut n « [[$1]] »",
        "uploaddisabled": "Suref-aɣ, azen n ufayluwen yettwakkes",
        "copyuploaddisabled": "Taktert n ufaylu s URL yensan.",
        "uploaddisabledtext": "Azen n ifuyla yettwakkes deg wiki agi.",
        "watchlist-details": "ttɛassaɣ {{PLURAL:$1|$1 usebter|$1 n isebtaren}} mebla isebtaren \"amyannan\".",
        "wlheader-enotif": "Talɣut s email yessermed.",
        "wlheader-showupdated": "Isebtar ttubeddlen segwasmi tkecmeḍ tikelt taneggarut ttbanen-d s uḍris '''aberbuz'''.",
-       "wlnote2": "Ddaw agi ibeddilen deg {{PLURAL:$1|asrag aneggaru|<strong>$1</strong> isragen ineggura}}, seg $2, $3.",
+       "wlnote": "Ddaw agi  {{PLURAL:$1|yella abeddel aneggaru|llan '''$1''' ibeddilen ineggura}} n {{PLURAL:$2|usrag aneggaru|'''$2''' isragen ineggura}}, seg $3 af $4.",
        "wlshowlast": "Ssken $1 n swayeɛ $2 n wussan neɣ $3 ineggura",
        "watchlist-options": "Tifranin n umuɣ n uɛessi",
        "watching": "Ad iɛass...",
        "duplicate-defaultsort": "Ɣur-wet : tasarut n ufran m-ulac « $2 » atsefεej tasarut n uqbel « $1 ».",
        "version": "Lqem",
        "version-extensions": "Isiɣzaf i serkeben",
+       "version-skins": "Igelman",
        "version-specialpages": "isebtar usligen",
        "version-parserhooks": "Imguden n umsisleḍ n taseddast",
        "version-variables": "Imuttiyen",
        "version-antispam": "Aḥezzeb n spam",
-       "version-skins": "Igelman",
        "version-other": "Nniḍen",
        "version-mediahandlers": "Amsqerdec n imediaten",
        "version-hooks": "Imguden",
index 0ccb278..29f6f2e 100644 (file)
        "talkpagelinktext": "Тепсэлъыхьыгъуэ",
        "specialpage": "Лэжыгъэ напэкӀуэцӀ",
        "personaltools": "Уи Ӏэмэпсымэхэр",
-       "postcomment": "ЛъэныкъуэщӀэ",
        "articlepage": "Тхыгъэм хэплъэн",
        "talk": "Тепсэлъэхьыгъуэ",
        "views": "Зыхэплъахэр",
        "externaldberror": "Щэуэгъуэ хъуа, аутентификациэ щекӀуэкӀым иэ апхуэдиз пӀалъэ уиӀу щыткъым, уи нэкугъуэ аккаунтыр зэпхъуэкӀын.",
        "login": "Системэм зыкъегъэцIыхуын",
        "nav-login-createaccount": "Ихьэн/щӀэуэ зитхэн",
-       "loginprompt": "«Cookies» уиӀэн хуэй, системэм уихьэн щхьэкӀэ.",
        "userlogin": "Ихьэн/зыхэтхэн",
        "userloginnocreate": "Системэм зыкъегъэцӀыхуын",
        "logout": "ИкӀыжын",
        "upload": "Файл илъхьэн",
        "uploadnologin": "Системэм зыкъебгъэцӀыхуакъым",
        "uploadlogpage": "Иралъхьахэм и тхыдэ-тхылъыр",
-       "uploadedimage": "изылъхьар \"[[$1]]\"",
        "filehist": "Файлым и тхыдэ",
        "filehist-help": "Махуэ/зэманым текъузэ файлыр дэпщэщ дэуэду щытами уеплъынумэ",
        "filehist-current": "иджырер",
index 9a5181c..f9976fa 100644 (file)
        "talkpagelinktext": "مشقولگی",
        "specialpage": "خصوصی صفحہ",
        "personaltools": "ذاتی سماند",
-       "postcomment": "پروشٹیو حصّہ",
        "articlepage": "مندرجاتی صفحہو لوڑے",
        "talk": "تبادلہٴ خیال",
        "views": "خیالات",
        "externaldberror": "یا تھے توثیقی ڈیٹابیسا خطا واقع بیتی شیر یا تتے بیریو کھاتو بتاریخ کوریکو اِجازت نیکی",
        "login": "داخل بوس",
        "nav-login-createaccount": "کھاتہ کھولاو کورے یا اندراج کورے",
-       "loginprompt": "{{SITENAME}} کھوار ویکیپیڈیا داخلو بچے تہ سوم پاسورڈ بیک ضروری شیر",
        "userlogin": "کھاتہ ساوزاوے یا اندراج کورے",
        "userloginnocreate": "داخل نوشتہ بوس",
        "logout": "لاگ آوٹ",
        "uploadlogpage": "نوشتۂ زبراثقال (اپ لوڈ لاگ)",
        "filename": "فایلو نام",
        "filedesc": "خلاصہ",
-       "uploadedimage": "زبراثقال (اپ لوڈ) براۓ \"[[$1]]\"",
        "license": "لایسنس",
        "license-header": "لایسنسنگ",
        "file-anchor-link": "فایل",
index c5d401d..4b2bf84 100644 (file)
        "talkpagelinktext": "Hurênayis",
        "specialpage": "Pela xısusiye",
        "personaltools": "Hacetê keşi",
-       "postcomment": "Qısımo newe",
        "articlepage": "Pela zerreki bıvêne",
        "talk": "Hurênais",
        "views": "Asaişi",
        "externaldberror": "Cıfeteliyaisê naskerdene de ya xeta esta ya ki tebera vırastena hesabê sıma rê destur çino.",
        "login": "Cı kuye",
        "nav-login-createaccount": "Cı kuye / hesab vıraze",
-       "loginprompt": "Cıkotena {{SITENAME}} rê gunê ''cookies'' akerdey bê.",
        "userlogin": "Cı kuye / hesab vıraze",
        "userloginnocreate": "Cı kuye",
        "logout": "Veciye",
        "mergehistory-into": "Pela hedefi:",
        "mergehistory-reason": "Sebeb:",
        "revertmerge": "Cia ke",
-       "history-title": "Rewizyonê $1:",
+       "history-title": "Tarixê çımraviyarnayişê \"$1\"",
        "lineno": "Rêza $1i:",
        "compareselectedversions": "Varyantunê weçinıtun têver sane",
        "editundo": "peyser bia",
        "filesource": "Çıme:",
        "empty-file": "Dosya ke ti şawit veng biy.",
        "savefile": "Dosya qeyd ke",
-       "uploadedimage": "\"[[$1]]\" bar bi",
        "upload-source": "Dosya çımey",
        "sourcefilename": "Namê dosya çımey:",
        "watchthisupload": "Na dosya de şêr ke",
index 97df37b..e70e9c8 100644 (file)
        "talkpagelinktext": "تالقىلاۋى",
        "specialpage": "ارنايى بەت",
        "personaltools": "جەكە قۇرالدار",
-       "postcomment": "ماندەمە جونەلتۋ",
        "articlepage": "ماعلۇمات بەتىن قاراۋ",
        "talk": "تالقىلاۋ",
        "views": "كورىنىس",
        "externaldberror": "وسى ارادا نە شەتتىك راستاۋ دەرەكقورىندا قاتە بولدى, نەمەسە شەتتىك تىركەلگىڭىزدى جاڭالاۋ رۇقساتى جوق.",
        "login": "كىرۋ",
        "nav-login-createaccount": "كىرۋ / تىركەلگى جاساۋ",
-       "loginprompt": "{{SITENAME}} تورابىنا كىرۋىڭىز ٴۇشىن «cookies» قوسىلۋى ٴجون.",
        "userlogin": "كىرۋ / تىركەلگى جاساۋ",
        "logout": "شىعۋ",
        "userlogout": "شىعۋ",
        "nextn": "كەلەسى {{PLURAL:$1|$1}}",
        "viewprevnext": "كورسەتىلۋى: ($1 {{int:pipe-separator}} $2) ($3) جازبا",
        "search-result-size": "$1 ($2 ٴسوز)",
-       "search-result-score": "اراقاتىناستىلىعى: $1 %",
        "search-redirect": "(ايداعىش $1)",
        "search-section": "(ٴبولىم $1)",
        "search-suggest": "بۇنى ىزدەدىڭىز بە: $1",
        "file-exists-duplicate": "بۇل فايل كەلەسى {{PLURAL:$1|فايلدىڭ|فايلدارىنىڭ}} تەلنۇسقاسى:",
        "uploadwarning": "قوتارىپ بەرۋ جونىندە قۇلاقتاندىرۋ",
        "savefile": "فايلدى ساقتاۋ",
-       "uploadedimage": "«[[$1]]» فايلىن قوتارىپ بەردى",
-       "overwroteimage": "«[[$1]]» فايلىننىڭ جاڭا نۇسقاسىن قوتارىپ بەردى",
        "uploaddisabled": "قوتارىپ بەرۋ وشىرىلگەن",
        "uploaddisabledtext": "{{SITENAME}} جوباسىندا فايل قوتارىپ بەرۋى وشىرىلگەن.",
        "uploadscripted": "بۇل فايلدا ۆەب شولعىشتى قاتەلىكپەن تالداتقىزاتىن HTML نە ٴامىر كودى بار.",
        "watchlist-details": "تالقىلاۋ بەتتەرىن ساناماعاندا $1 بەت باقلانىلادى.",
        "wlheader-enotif": "ەسكەرتۋ حات جىبەرۋى قوسىلعان.",
        "wlheader-showupdated": "سوڭعى كەلىپ-كەتۋىڭىزدەن بەرى وزگەرتىلگەن بەتتەردى '''جۋان''' قارىپىمەن كورسەت",
+       "wlnote": "تومەندە سوڭعى {{PLURAL:$2|ساعاتتا|'''$2''' ساعاتتا}} بولعان, {{PLURAL:$1|جۋىقتاعى وزگەرىس|جۋىقتاعى '''$1''' وزگەرىس}} كورسەتىلەدى.",
        "wlshowlast": "سوڭعى $1 ساعاتتاعى, $2 كۇندەگى, $3 بولعان وزگەرىستى كورسەتۋ",
        "watching": "باقىلاۋدا…",
        "unwatching": "باقىلاماۋدا…",
index f962fa6..b61b250 100644 (file)
@@ -7,7 +7,8 @@
                        "Bakytgul Salykhova",
                        "Daniyar",
                        "GaiJin",
-                       "Kaztrans"
+                       "Kaztrans",
+                       "Balnur.s"
                ]
        },
        "tog-underline": "Сілтеменің астын сызу:",
        "talkpagelinktext": "Талқылауы",
        "specialpage": "Арнайы бет",
        "personaltools": "Жеке құралдар",
-       "postcomment": "Жаңа бөлім",
        "articlepage": "Мәлімет бетін қарау",
        "talk": "Талқылау",
        "views": "Көрініс",
        "hidetoc": "жасыру",
        "collapsible-collapse": "Түру",
        "collapsible-expand": "Жазу",
+       "confirmable-yes": "Иә",
+       "confirmable-no": "Жоқ",
        "thisisdeleted": "$1 қарайсыз ба немесе қалпына келтіресіз бе?",
        "viewdeleted": "$1 қарайсыз ба?",
        "restorelink": "{{PLURAL:$1|жойылған өңдемені|$1 жойылған өңдемені}}",
        "externaldberror": "Осы арада не шеттік растау дерекқорында қате болды, немесе шеттік тіркелгіңізді жаңалау рұқсаты жоқ.",
        "login": "Кіру",
        "nav-login-createaccount": "Кіру / Тіркелу",
-       "loginprompt": "{{SITENAME}} торабына кіруіңіз үшін «cookies» қосылуы керек.",
        "userlogin": "Кіру / Тіркелу",
        "userloginnocreate": "Кіру",
        "logout": "Шығу",
        "userlogin-resetlink": "Қатысушы атын не құпия сөзді ұмыттыңыз ба?",
        "userlogin-resetpassword-link": "Құпия сөздіңізді ұмыттыңыз ба?",
        "userlogin-helplink2": "Кіруге көмек",
-       "userlogin-loggedin": "{{GENDER:$1|$1}} ретінде әлдеқашан кіргенсіз.\nТөмендегі пішінді басқа қатысушы кіруі ретінде қолданыңыз.",
-       "userlogin-createanother": "Басқа тіркелгі жасау",
        "createacct-emailrequired": "Е-пошта мекен-жайы",
        "createacct-emailoptional": "Е-пошта мекен-жайы (міндетті емес)",
        "createacct-email-ph": "Е-пошта мекен-жайыңызды енгізіңіз",
        "preview": "Қарап шығу",
        "showpreview": "Алдын-ала қарау",
        "showdiff": "Өзгерістерді көрсет",
+       "blankarticle": "<strong>Ескерту:</strong> Сіз бастамақшы болған бет бос.\nЕгер сіз «{{int:savearticle}}» дегенші қайта шертсеңіз бет қандайда бір мағлұматсыз басталады.",
        "anoneditwarning": "<strong> Ескерту:</strong>  Сіз жүйеге кірмегенсіз.\nIP мекенжайыңыз бұл беттің өңделу тарихында жазылып алынады.",
        "anonpreviewwarning": "<em>Сіз жүйеге кірмегенсіз. IP мекенжайыңыз бұл беттің өңделу тарихында жазылып алынады.</em>",
        "missingsummary": "<strong>Ескерту:</strong> Өңдеменің қысқаша түйіндемесін енгізбепсіз.\n«{{int:savearticle}}» батырмасын қайта бассаңыз өңденмеңіз түйіндемесіз сақталады.",
        "clearyourcache": "<strong>Ескерту:</strong> Сақтағаннан кейін өзгерістерді көру үшін броузеріңіздің бүркемесін (кэшін) тазарту керек болуы мүмкін. \n* <strong>Firefox / Safari:</strong> <em>Қайта жүктеуді</em> нұқығанда <em>Shift</em> басып тұрыңыз немесе <em>Ctrl-F5</em> не <em>Ctrl-Shift-R</em> екеуінің біреуін басыңыз (Mac — <em>⌘-R</em>) \n* <strong>Google Chrome:</strong>  <em>Ctrl-Shift-R</em> басыңыз (Mac — <em>⌘-Shift-R</em>)\n* <strong>Internet Explorer:</strong> <em>Жаңарту</em> батырмасын нұқығанда <em>Ctrl</em> басып тұрыңыз немесе <em>Ctrl-F5</em> басыңыз;  не <em>F5</em> басыңыз \n* <strong>Opera:</strong> <em>Құралдар → Бапталымдар</em> дегеннен бүркемесін тазарту керек.",
        "usercssyoucanpreview": "<strong>Кеңес:</strong> Жаңа CSS файлыңызды сақтау алдында «{{int:showpreview}}» батырмасын қолданып сынақтаңыз.",
        "userjsyoucanpreview": "<strong>Кеңес:</strong> Жаңа JavaScript файлыңызды сақтау алдында «{{int:showpreview}}» батырмасын қолданып сынақтаңыз.",
-       "usercsspreview": "</strong>Бұл тек қатысушы CSS файлыңызды қарап шығу екенін ұмытпаңыз, ол әлі сақталған жоқ!</strong>",
+       "usercsspreview": "<strong>Бұл тек қатысушы CSS файлыңызды қарап шығу екенін ұмытпаңыз, ол әлі сақталған жоқ!</strong>",
        "userjspreview": "<strong>Мынау JavaScript қатысушы бағдарламасын тынау/қарап шығу екенін ұмытпаңыз, ол әлі сақталған жоқ!</strong>",
        "sitecsspreview": "<strong>Мынау тек бұл CSS файлын қарап шығуыңыз екенін ұмытпаңыз, ол әлі сақталған жоқ!</strong>",
        "sitejspreview": "<strong>Мынау тек бұл JavaScript кодын алдын-ала қарап алу екенін ұмытпаңыз, ол әлі сақталған жоқ!</strong>",
        "userinvalidcssjstitle": "</strong>Ескерту:</strong> Осы арада «$1» деген еш мәнер жоқ.\nҚалыпты .css және .js беттерінің атауына кіші әріп қолданыңыз, мысалы {{ns:user}}:Foo/vector.css дегенді {{ns:user}}:Foo/Vector.css дегенмен салыстырып қараңыз.",
        "updated": "(Жаңартылған)",
        "note": "'''Ескерту:'''",
-       "previewnote": "</strong>Бұл тек қарап шығу екенін ұмытпаңыз.</strong> \nӨзгертулеріңіз әлі сақталған жоқ!",
+       "previewnote": "<strong>Бұл тек қарап шығу екенін ұмытпаңыз.</strong> \nӨзгертулеріңіз әлі сақталған жоқ!",
        "continue-editing": "Өңдеу аумағына өту",
        "previewconflict": "Бұл қарап шығу беті жоғарғы кірістіру орнындағы мәтінді қамтиды да және сақталғандағы өңді көрсетпек.",
        "session_fail_preview": "<strong>Кешіріңіз! Сессия деректері жоғалуы салдарынан өңдемеңізді бітіре алмаймыз.</strong>\nҚайта байқап көріңіз. \nЕгер бұл әлі істелмесе [[Special:UserLogout|шығуды]] және қайта кіруді байқап көріңіз.",
        "undo-failure": "Бұл өңдеме жоққа шығарылмайды, себебі арада қақтығысты өңдемелер бар.",
        "undo-norev": "Бұл өңдеме жоққа шығарылмайды, себебі бұл бет жоқ немесе жойылған.",
        "undo-nochange": "Өңдеме әлдеқашан жоққа шығарылғаны анықталды.",
-       "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|т]]) істеген нөмір $1 түзетуін жоққа шығарды",
+       "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|т]]) істеген нөмір $1 нұсқасын жоққа шығарды",
        "undo-summary-username-hidden": "$1 нұсқасын жасырылған қатысушы жоққа шығарды",
        "cantcreateaccounttitle": "Тіркелгі жасалмады",
        "cantcreateaccount-text": "Бұл IP мекенжайдан (<strong>$1</strong>) жаңа тіркелгі жасауын [[User:$3|$3]] бұғаттаған.\n\n$3 есімді қатысушының келтіріген себебі: <em>$2</em>",
        "pagemerge-logentry": "[[$1]] деген [[$2]] дегенге біріктірілді ($3 дейінгі түзетулері)",
        "revertmerge": "Біріктіруді болдырмау",
        "mergelogpagetext": "Төменде бір беттің тарихы өзге бетке біріктіру ең соңғы тізімі келтіріледі.",
-       "history-title": "«$1» дегеннің өңдеу тарихы",
+       "history-title": "«$1» дегеннің өңделу тарихы",
        "difference-title": "$1 — нұсқалар арасындағы айырмашылық",
        "difference-title-multipage": "\"$1\" және \"$2\" беттерінің арасындағы айырмашылық",
        "difference-multipage": "(Беттер арасындағы айырмашылық)",
        "searchprofile-advanced-tooltip": "Әдепкі есім кеңістігінен іздеу",
        "search-result-size": "$1 ({{PLURAL:$2|1 сөз|$2 сөз}})",
        "search-result-category-size": "{{PLURAL:$1|1 мүше|$1 мүше}} ({{PLURAL:$2|1 санатша|$2 санатша}}, {{PLURAL:$3|1 файл|$3 файл}})",
-       "search-result-score": "Арақатынастылығы: $1 %",
        "search-redirect": "(айдағыш $1)",
        "search-section": "(бөлім $1)",
        "search-suggest": "Мүмкін осы болар: $1",
        "searchrelated": "қатысты",
        "searchall": "барлық",
        "showingresults": "Төменде нөмір '''$2''' орнынан бастап барынша '''$1''' нәтиже көрсетіледі.",
-       "showingresultsheader": "«<strong>$4</strong>» сұранысына {{PLURAL:$5|тек <strong>$1</strong> нәтиже табылды|табылған <strong>$3</strong> нәтиженің <strong>$1 - $2</strong> аралығы көрсетілген}}",
        "search-nonefound": "Сұрауға сәйкес нәтижелер табылмады.",
        "powersearch-legend": "Кеңейтілген іздеу",
        "powersearch-ns": "Атау кеңістіктері бойынша іздеу:",
        "file-exists-duplicate": "Бұл файл келесі {{PLURAL:$1|файлдың|файлдарының}} телнұсқасы:",
        "uploadwarning": "Жүктеу жөнінде құлақтандыру",
        "savefile": "Файлды сақтау",
-       "uploadedimage": "«[[$1]]» файлын жүктеді",
-       "overwroteimage": "«[[$1]]» деген файлдың жаңа нұсқасын жүктеді",
        "uploaddisabled": "Жүктеу өшірілген",
        "copyuploaddisabled": "URL арқылы жүктеу өшірілген.",
        "uploaddisabledtext": "Файл жүктеу өшірілген.",
        "license-nopreview": "(Қарап шығу жетімді емес)",
        "upload_source_url": "(жарамды, баршаға қатынаулы URL)",
        "upload_source_file": "(компьютеріңіздегі файл)",
+       "listfiles-delete": "жою",
        "listfiles-summary": "Бұл арнайы бетте барлық жүктелген файлдар көрсетіледі.",
        "listfiles_search_for": "Медиа атауын іздеу:",
        "imgfile": "файл",
        "randomincategory": "Санаттағы кездейсоқ бет",
        "randomincategory-invalidcategory": "\"$1\" жарамды санат аты емес.",
        "randomincategory-nopages": "Бұлар [[:Category:$1]] беттері мес.",
-       "randomincategory-selectcategory-submit": "Өту",
        "randomredirect": "Кездейсоқ айдағыш",
        "randomredirect-nopages": "Бұл есім аясында еш айдағыш жоқ \"$1\".",
        "statistics": "Санақ",
        "watchlist-details": "Бақылау тізіміңізде {{PLURAL:$1|$1 бет|$1 бет}} бар (талқылау беттері жекелей саналмайды).",
        "wlheader-enotif": "Ескерту хат жіберуі қосылған.",
        "wlheader-showupdated": "Соңғы келіп-кетуіңізден бері өзгертілген беттер '''жуан''' қаріпімен көрсетіледі.",
-       "wlnote2": "Төменде $2, $3 кезіне дейінгі соңғы {{PLURAL:$1|сағаттағы|<strong>$1</strong> сағаттағы}} өзгерістер көрсетілген.",
+       "wlnote": "Төменде $3, $4 кезіне дейінгі соңғы {{PLURAL:$2|сағатта|'''$2''' сағатта}} болған, {{PLURAL:$1|жуықтағы өзгеріс|жуықтағы '''$1''' өзгеріс}} көрсетіледі.",
        "wlshowlast": "Соңғы $1 сағаттағы, $2 күндегі, $3 болған өзгерісті көрсету",
        "watchlist-options": "Бақылау тізімінің баптаулары",
        "watching": "Бақылауда…",
        "exbeforeblank": "тазарту алдындағы болған мағлұматы: $1",
        "delete-confirm": "«$1» дегенді жою",
        "delete-legend": "Жою",
-       "historywarning": "'''Ескету:'' Жоюы көзделген бетте бет тарихында шамамен $1 {{PLURAL:$1|түзетілуі|түзетілулері}} бар:",
+       "historywarning": "<strong>Ескету:</strong> Сіз жоймақшы болған бет тарихында шамамен $1 {{PLURAL:$1|түзетілуі|түзетілулері}} бар:",
        "confirmdeletetext": "Бетті бүкіл тарихымен бірге жойғалы жатырсыз.\nМұны жасауға сенімді екеніңізді, салдары есепке алынғанын және әрекетіңіз [[{{MediaWiki:Policy-url}}|ережелерге]] лайықты болғанын тағы бір рет тексеріп шығуыңызды сұраймыз.",
        "actioncomplete": "Әрекет орындалды",
        "actionfailed": "Әрекет орындалмады",
        "rollbacklinkcount-morethan": "$1-нан аса {{PLURAL:$1|өңдемені|өңдемелерді}} шегіндіру",
        "rollbackfailed": "Шегіндіру орындалмады",
        "cantrollback": "Өңдеме қайтарылмады;\nсоңғы үлескері тек осы беттің бастаушысы болды.",
-       "alreadyrolled": "[[User:$2|$2]] ([[User talk:$2|талқылауы]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) істеген [[:$1]] соңғы өңдемесі шегіндірілмеді;\nбасқа біреу бұл бетті әлдеқашан өңдеген немесе шегіндірген.\n\nБетті [[User:$3|$3]] ([[User talk:$3|talk]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]) соңғы рет өңдеген.",
+       "alreadyrolled": "[[User:$2|$2]] ([[User talk:$2|талқылауы]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) істеген [[:$1]] бетіндегі соңғы өңдемесі шегіндірілмеді, себебі басқа біреу бұл бетті әлдеқашан өңдеген немесе шегіндірген.\n\nБетті [[User:$3|$3]] ([[User talk:$3|талқылауы]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]) соңғы рет өңдеген.",
        "editcomment": "Болған өңдеме түйіндемесі: «''$1''».",
        "revertpage": "[[Special:Contributions/$2|$2]] ([[User talk:$2|т]]) өңдемелерінен [[User:$1|$1]] соңғы нұсқасына қайтарды",
        "revertpage-nouser": "Жасырылған қатысушы өңдемелерінен {{GENDER:$1|[[User:$1|$1]]}} соңғы нұсқасына қайтарды",
        "import": "Беттерді сырттан алу",
        "importinterwiki": "Уики-апару үшін сырттан алу",
        "import-interwiki-text": "Сырттан алынатын уикиді және беттің тақырып атын бөлектеңіз.\nТүзету күн-айы және өңдеуші есімдері сақталады.\nУики-апару үшін сырттан алу барлық әрекеттер [[{{#special:Log}}/import|сырттан алу журналына]] жазылып алынады.",
-       "import-interwiki-source": "Қайнар уики/бет:",
        "import-interwiki-history": "Бұл беттің барлық тарихи нұсқаларын көшіру",
        "import-interwiki-templates": "Кірістірілген барлық үлгілер",
        "import-interwiki-submit": "Сырттан алу",
        "pageinfo-header-edits": "Өңдеу тарихы",
        "pageinfo-header-restrictions": "Бет қорғалуы",
        "pageinfo-header-properties": "Бет сипаттары",
-       "pageinfo-display-title": "Бейнебет атауы",
+       "pageinfo-display-title": "Көрініс атауы",
+       "pageinfo-default-sort": "Әдепкі іріктеу кілті",
        "pageinfo-length": "Бет ұзындығы (байтпен)",
        "pageinfo-article-id": "Бет ID-і",
        "pageinfo-language": "Бет мәлімет тілі",
        "pageinfo-content-model": "Бет мағлұмат қалпы",
-       "pageinfo-robot-policy": "Индекстеуді робот жүргізеді",
-       "pageinfo-robot-index": "Рұқсат берілген",
-       "pageinfo-robot-noindex": "Рұқсат етілмеген",
+       "pageinfo-robot-policy": "Индекстеуді робот жүргізуге",
+       "pageinfo-robot-index": "рұқсат берілген",
+       "pageinfo-robot-noindex": "рұқсат етілмеген",
        "pageinfo-views": "Қараушылар саны",
        "pageinfo-watchers": "Бетті қараушылар саны",
        "pageinfo-few-watchers": "$1 азырақ {{PLURAL:$1|қараушы|қараушы}}",
-       "pageinfo-redirects-name": "Ð\91ұл Ð±ÐµÑ\82ке Ð°Ð¹Ð´Ð°Ñ\82Ñ\8bлғандар саны",
+       "pageinfo-redirects-name": "Ð\91ұл Ð±ÐµÑ\82ке Ð±Ð°Ò\93Ñ\8bÑ\82Ñ\82алғандар саны",
        "pageinfo-subpages-name": "Бұл беттің төменгі беттер саны",
        "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|айдатқыш|айдатқыш}}; $3 {{PLURAL:$3|айдатқыш емес|айдатқыш емес}})",
        "pageinfo-firstuser": "Бетті бастаушы",
        "pageinfo-toolboxlink": "Бұл бет туралы мәлімет",
        "pageinfo-redirectsto": "Айдатылғандар",
        "pageinfo-redirectsto-info": "Информация",
+       "pageinfo-contentpage": "Контент бетке санала ма?",
        "pageinfo-contentpage-yes": "Иә",
        "pageinfo-protect-cascading": "Баулы қорғаулылар мұнда",
        "pageinfo-protect-cascading-yes": "Иә",
index cbec7b2..a3a4cd8 100644 (file)
        "talkpagelinktext": "Talqılawı",
        "specialpage": "Arnaýı bet",
        "personaltools": "Jeke quraldar",
-       "postcomment": "Mändeme jöneltw",
        "articlepage": "Mağlumat betin qaraw",
        "talk": "Talqılaw",
        "views": "Körinis",
        "externaldberror": "Osı arada ne şettik rastaw derekqorında qate boldı, nemese şettik tirkelgiñizdi jañalaw ruqsatı joq.",
        "login": "Kirw",
        "nav-login-createaccount": "Kirw / Tirkelgi jasaw",
-       "loginprompt": "{{SITENAME}} torabına kirwiñiz üşin «cookies» qosılwı jön.",
        "userlogin": "Kirw / Tirkelgi jasaw",
        "logout": "Şığw",
        "userlogout": "Şığw",
        "nextn": "kelesi {{PLURAL:$1|$1}}",
        "viewprevnext": "Körsetilwi: ($1 {{int:pipe-separator}} $2) ($3) jazba",
        "search-result-size": "$1 ($2 söz)",
-       "search-result-score": "Araqatınastılığı: $1 %",
        "search-redirect": "(aýdağış $1)",
        "search-section": "(bölim $1)",
        "search-suggest": "Bunı izdediñiz be: $1",
        "file-exists-duplicate": "Bul faýl kelesi {{PLURAL:$1|faýldıñ|faýldarınıñ}} telnusqası:",
        "uploadwarning": "Qotarıp berw jöninde qulaqtandırw",
        "savefile": "Faýldı saqtaw",
-       "uploadedimage": "«[[$1]]» faýlın qotarıp berdi",
-       "overwroteimage": "«[[$1]]» faýlınnıñ jaña nusqasın qotarıp berdi",
        "uploaddisabled": "Qotarıp berw öşirilgen",
        "uploaddisabledtext": "{{SITENAME}} jobasında faýl qotarıp berwi öşirilgen.",
        "uploadscripted": "Bul faýlda veb şolğıştı qatelikpen taldatqızatın HTML ne ämir kodı bar.",
        "watchlist-details": "Talqılaw betterin sanamağanda $1 bet baqlanıladı.",
        "wlheader-enotif": "Eskertw xat jiberwi qosılğan.",
        "wlheader-showupdated": "Soñğı kelip-ketwiñizden beri özgertilgen betterdi '''jwan''' qaripimen körset",
+       "wlnote": "Tömende soñğı {{PLURAL:$2|sağatta|'''$2''' sağatta}} bolğan, {{PLURAL:$1|jwıqtağı özgeris|jwıqtağı '''$1''' özgeris}} körsetiledi.",
        "wlshowlast": "Soñğı $1 sağattağı, $2 kündegi, $3 bolğan özgeristi körsetw",
        "watching": "Baqılawda…",
        "unwatching": "Baqılamawda…",
index c6a3dc8..1c97771 100644 (file)
        "talkpagelinktext": "ការពិភាក្សា",
        "specialpage": "ទំព័រពិសេស",
        "personaltools": "ឧបករណ៍ផ្ទាល់ខ្លួន",
-       "postcomment": "ផ្នែកថ្មី",
        "articlepage": "មើលខ្លឹមសារទំព័រ​",
        "talk": "ការពិភាក្សា",
        "views": "គំហើញ",
        "externaldberror": "មាន​​បញ្ហាក្នុងការ​បញ្ជាក់​ផ្ទៀង​ផ្ទាត់​​មូលដ្ឋាន​ទិន្នន័យ​ ឬ​អ្នក​មិន​ត្រូវ​បាន​អនុញ្ញាត​ឲ្យ​បន្ទាន់​សម័យ​គណនី​ខាង​ក្រៅ​របស់​អ្នក​។​\n​",
        "login": "កត់ឈ្មោះចូល",
        "nav-login-createaccount": "កត់ឈ្មោះចូលឬបង្កើតគណនី",
-       "loginprompt": "អ្នក​ត្រូវតែ​មាន​ខូគី ដើម្បី​អាច​កត់ឈ្មោះចូល​{{SITENAME}}បាន។",
        "userlogin": "កត់ឈ្មោះចូលឬបង្កើតគណនី",
        "userloginnocreate": "កត់ឈ្មោះចូល",
        "logout": "កត់ឈ្មោះចេញ",
        "searchprofile-advanced-tooltip": "ស្វែងរកក្នុងប្រភេទកំណត់ដោយអ្នកប្រើប្រាស់",
        "search-result-size": "$1({{PLURAL:$2|១ពាក្យ|$2ពាក្យ}})",
        "search-result-category-size": "{{PLURAL:$1|សមាជិកម្នាក់|សមាជិក$1នាក់}} ({{PLURAL:$2|កូនចំណាត់ថ្នាក់ក្រុម១|$2 កូនចំណាត់ថ្នាក់ក្រុម}}, {{PLURAL:$3|1 ឯកសារ|$3 ឯកសារ}})",
-       "search-result-score": "កម្រិតទាក់ទិន៖ $1%",
        "search-redirect": "(បញ្ជូនបន្ត $1)",
        "search-section": "(ផ្នែក $1)",
        "search-suggest": "ប្រហែលជាអ្នកចង់រក៖ $1",
        "uploadwarning": "ប្រយ័ត្ន",
        "uploadwarning-text": "សូមកែការពិពណ៌នារបស់ឯកសារខាងក្រោម រួចសាកល្បងម្ដងទៀត។",
        "savefile": "រក្សាឯកសារទុក",
-       "uploadedimage": "បានផ្ទុកឡើង \"[[$1]]\"",
-       "overwroteimage": "បានផ្ទុកឡើងកំណែថ្មីរបស់\"[[$1]]\"",
        "uploaddisabled": "មិនអនុញ្ញាតអោយផ្ទុកឯកសារឡើង",
        "copyuploaddisabled": "មានអោយប្រើការផ្ទុកឡើងដោយ URL។",
        "uploaddisabledtext": "ការផ្ទុកឯកសារ​ឡើង​គឺ​មិន​ត្រូវបាន​អនុញ្ញាត​ទេ​។",
        "watchlist-details": "{{PLURAL:$1|$1 page|ទំព័រ $1}}នៅក្នុងបញ្ជីតាមដានរបស់អ្នក ដោយមិនរាប់បញ្ចូលទំព័រពិភាក្សា។",
        "wlheader-enotif": "បើកប្រើការផ្ដល់ដំណឹងតាមរយៈអ៊ីមែល។",
        "wlheader-showupdated": "ទំព័រដែលត្រូវបានផ្លាស់ប្តូរតាំងពីពេលចូលមើលចុងក្រោយរបស់អ្នក ត្រូវបានបង្ហាញជា '''អក្សរដិត'''។",
+       "wlnote": "ខាងក្រោមនេះជា {{PLURAL:$1|បំលាស់ប្តូរចុងក្រោយ|'''$1'''បំលាស់ប្តូរចុងក្រោយ}}ក្នុងរយះពេល{{PLURAL:$2|'''$2'''ម៉ោង}}ចុងក្រោយ គិតចាប់ពី $3, $4។",
        "wlshowlast": "បង្ហាញ $1ម៉ោងចុងក្រោយ $2ថ្ងៃចុងក្រោយ ឬ$3",
        "watchlist-options": "ជម្រើសនានាក្នុងបញ្ជីតាមដាន",
        "watching": "កំពុង​តាមដាន...",
        "unknown_extension_tag": "ស្លាក​នៃផ្នែកបន្ថែម \"$1\" មិនស្គាល់",
        "version": "កំណែ",
        "version-extensions": "ផ្នែកបន្ថែមដែលបានដំឡើង",
+       "version-skins": "សំបក",
        "version-specialpages": "ទំព័រពិសេសៗ",
        "version-variables": "អថេរ",
        "version-antispam": "ការបង្ការស្ប៉ាម",
-       "version-skins": "សំបក",
        "version-other": "ផ្សេង",
        "version-mediahandlers": "កម្មវិធី​បើក​មេឌា​ (Media handlers)",
        "version-hook-name": "ឈ្មោះ​ Hook",
index cbd849c..b24c1bb 100644 (file)
        "talkpagelinktext": "ಚರ್ಚೆ",
        "specialpage": "ವಿಶೇಷ ಪುಟ",
        "personaltools": "ವೈಯಕ್ತಿಕ ಉಪಕರಣಗಳು",
-       "postcomment": "ಹೊಸ ವಿಭಾಗ",
        "articlepage": "ಲೇಖನ ಪುಟವನ್ನು ವೀಕ್ಷಿಸಿ",
        "talk": "ಚರ್ಚೆ",
        "views": "ನೋಟಗಳು",
        "password-change-forbidden": "ನೀವು ಈ ವಿಕಿಯಲ್ಲಿ ಪ್ರವೇಶಪದವನ್ನು ಬದಲಾಯಿಸಲು ಸಾದ್ಯವಿಲ್ಲ.",
        "login": "ಲಾಗ್ ಇನ್",
        "nav-login-createaccount": "ಲಾಗ್ ಇನ್ - log in",
-       "loginprompt": "{{SITENAME}} ತಾಣಕ್ಕೆ ಲಾಗ್ ಇನ್ ಆಗಲು ನಿಮ್ಮ ಗಣಕಯಂತ್ರದಲ್ಲಿ ಕುಕೀ (cookie) ಸೌಲಭ್ಯವಿರಬೇಕು.",
        "userlogin": "ಲಾಗ್ ಇನ್ - log in",
        "userloginnocreate": "ಲಾಗ್ ಇನ್",
        "logout": "ಲಾಗ್ ಔಟ್",
        "searchprofile-everything-tooltip": "ಹುದುಕಿ ಯಲ ಸುಮನು (ಇಥಿಯದಿ ಮಾಥು ಹಲೆ)",
        "searchprofile-advanced-tooltip": "ಹುಧುಕಿ ನಮ ಜಾಗ ಹೆಸರುಸ್ತಲ್ಲ",
        "search-result-size": "$1 ({{PLURAL:$2|೧ ಪದ|$2 ಪದಗಳು}})",
-       "search-result-score": "ಸಂಬದ್ಧತೆ: $1%",
        "search-redirect": "(ಪುನರ್ನಿರ್ದೇಶನ $1)",
        "search-section": "(ವಿಭಾಗ $1)",
        "search-suggest": "ನೀವು ಇದನ್ನು ಹುಡುಕುತ್ತಿರುವಿರೆ: $1",
        "fileexists-shared-forbidden": "ಆ ಹೆಸರಿನಲ್ಲಿ ಫೈಲೊಂದು ಸಾಮೂಹಿಕ ಫೈಲಿನ ಆಗರದಲ್ಲಿ ಆಗಲೆ ಇದೆ;\nದಯವಿಟ್ಟು ಹಿಂದಕ್ಕೆ ಹೋಗಿ ಈ ಫೈಲನ್ನು ಹೊಸ ಹೆಸರಿನಲ್ಲಿ ಅಪ್ಲೋಡ್ ಮಾಡಿ. [[File:$1|thumb|center|$1]]",
        "uploadwarning": "ಅಪ್ಲೋಡ್ ಎಚ್ಚರಿಕೆ",
        "savefile": "ಕಡತವನ್ನು ಉಳಿಸಿ",
-       "uploadedimage": "\"[[$1]]\" ಅಪ್ಲೋಡ್ ಆಯಿತು",
-       "overwroteimage": "\"[[$1]]\" ಫೈಲಿನ ಹೊಸ ಆವೃತ್ತಿಯನ್ನು ಅಪ್ಲೋಡ್ ಮಾಡಲಾಯಿತು",
        "uploaddisabled": "ಅಪ್ಲೋಡ್‍ಗಳು ನಿರ್ಬಂಧಿತವಾಗಿದೆ",
        "uploaddisabledtext": "{{SITENAME}} ತಾಣದಲ್ಲಿ ಫೈಲುಗಳ ಅಪ್ಲೋಡ್ ಮಾಡುವಿಕೆ ತಡೆಗಟ್ಟಲ್ಪಟ್ಟಿದೆ.",
        "uploadvirus": "ಈ ಫೈಲಿನಲ್ಲಿ ಒಂದು ವೈರಸ್ ಇದೆ! ಮಾಹಿತಿ: $1",
        "linkstoimage": "ಈ ಕೆಳಗಿನ {{PLURAL:$1|ಪುಟವು|$1 ಪುಟಗಳು}} ಈ ಚಿತ್ರಕ್ಕೆ ಸಂಪರ್ಕ {{PLURAL:$1|ಹೊಂದಿದೆ|ಹೊಂದಿವೆ}}:",
        "nolinkstoimage": "ಈ ಫೈಲಿಗೆ ಯಾವ ಪುಟವೂ ಸಂಪರ್ಕ ಹೊಂದಿಲ್ಲ.",
        "sharedupload": "ಈ ಫೈಲು $1 ಇಂದ. ಇದು ಇತರ ಯೋಜನೆಗಳಲ್ಲಿ ಉಪಯೋಗದಲ್ಲಿರಬಹುದು.",
-       "sharedupload-desc-here": "ಈಧು ಬನ್ದಿರುವುಧು $1 ಮಥು ಹಲವು ಯೋಜನೆ  ಯಲ್ಲಿ ಉಪಯೊಗ ವಗುಥದೆ. \nಕೊಟುರುವ   ವಿವರನೆ [$2 ಕತಥೆ ವಿವರನೆ ಪುಟಾ] ಕೆಲ್ಲಕೆ ನೊಡೀ.",
+       "sharedupload-desc-here": "ಈ ಕಡತವು $1 ಇಂದ ಬಂದಿದ್ದು, ಬೇರೆ ಯೋಜನೆಗಳಲ್ಲೂ ಉಪಯೋಗಿಸಲ್ಪಡಬಹುದು. \n[[$2 ಕಡತ ವಿವರಣಾ ಪುಟ]]ದಲ್ಲಿರುವ ವಿವರಣೆಯನ್ನು ಕೆಳಗೆ ಕೊಡಲಾಗಿದೆ.",
        "filepage-nofile": "ಈ ಹೆಸರಿನ ಫೈಲ್ ಅಸ್ತಿತ್ವದಲ್ಲಿಲ್ಲ",
        "filepage-nofile-link": "ಈ ಹೆಸರಿನ ಫೈಲ್ ಅಸ್ತಿತ್ವದಲ್ಲಿಲ್ಲ ಆದರೆ ನೀವು ಇದನ್ನು [$1 ನಕಲೆರಿಸಬಹುದು ]",
        "uploadnewversion-linktext": "ಈ ಫೈಲಿನ ಹೊಸ ಆವೃತ್ತಿಯನ್ನು ಅಪ್ಲೋಡ್ ಮಾಡಿ",
        "unusedtemplateswlh": "ಇತರ ಕೊಂಡಿಗಳು",
        "randompage": "ಯಾದೃಚ್ಛಿಕ ಪುಟ",
        "randompage-nopages": "ಈ ಪುಟಪ್ರಬೇಧದಲ್ಲಿ ಯಾವ ಪುಟವೂ ಇಲ್ಲ.",
-       "randomincategory-selectcategory-submit": "ಹೋಗು",
        "randomredirect": "ಯದೃಚ್ಛಿಕ ಪುನರ್ನಿರ್ದೇಶಿತ ಪುಟ",
        "randomredirect-nopages": "ಈ ಪುಟಪ್ರಬೇಧದಲ್ಲಿ ಯಾವ ಪುನರ್ನಿರ್ದೇಶನಗಳೂ ಇಲ್ಲ.",
        "statistics": "ಅಂಕಿ ಅಂಶಗಳು",
index 159b32b..2e7f7e9 100644 (file)
                        "관인생략",
                        "아라",
                        "Keysuck",
-                       "Infinity"
+                       "Infinity",
+                       "Bluemersen",
+                       "Revi"
                ]
        },
        "tog-underline": "링크에 밑줄:",
        "tog-hideminor": "최근 바뀜에서 사소한 편집을 숨기기",
-       "tog-hidepatrolled": "최근 바뀜에서 검토한 편집을 숨기기",
+       "tog-hidepatrolled": "최근 바뀜에서 점검한 편집을 숨기기",
        "tog-newpageshidepatrolled": "새 문서 목록에서 검토한 문서를 숨기기",
        "tog-extendwatchlist": "주시문서 목록에서 가장 최근의 편집만이 아닌 모든 편집을 보기",
        "tog-usenewrc": "최근 바뀜과 주시문서 목록의 문서별 그룹 바뀜",
@@ -55,6 +57,7 @@
        "tog-watchdefault": "내가 편집하는 문서와 파일을 주시문서 목록에 추가",
        "tog-watchmoves": "내가 이동하는 문서와 파일을 주시문서 목록에 추가",
        "tog-watchdeletion": "내가 삭제하는 문서와 파일을 주시문서 목록에 추가",
+       "tog-watchrollback": "내가 되돌리기 기능을 사용한 문서를 주시문서 목록에 추가",
        "tog-minordefault": "모든 편집에 기본적으로 사소한 편집을 표시",
        "tog-previewontop": "편집 상자 앞에 미리 보기 보이기",
        "tog-previewonfirst": "처음 편집할 때 미리 보기 보이기",
@@ -72,7 +75,7 @@
        "tog-watchlisthideminor": "주시문서 목록에서 사소한 편집을 숨기기",
        "tog-watchlisthideliu": "주시문서 목록에서 로그인한 사용자의 편집을 숨기기",
        "tog-watchlisthideanons": "주시문서 목록에서 익명 사용자의 편집을 숨기기",
-       "tog-watchlisthidepatrolled": "주시문서 목록에서 검토한 편집을 숨기기",
+       "tog-watchlisthidepatrolled": "주시문서 목록에서 점검한 편집을 숨기기",
        "tog-ccmeonemails": "이메일을 보낼 때 내 이메일로 복사본을 보내기",
        "tog-diffonly": "편집 차이를 비교할 때 문서 내용을 보지 않기",
        "tog-showhiddencats": "숨은 분류 보이기",
        "talkpagelinktext": "토론",
        "specialpage": "특수 문서",
        "personaltools": "개인 도구",
-       "postcomment": "새 문단",
        "articlepage": "문서 보기",
        "talk": "토론",
        "views": "보기",
        "otherlanguages": "다른 언어",
        "redirectedfrom": "($1에서 넘어옴)",
        "redirectpagesub": "넘겨주기 문서",
+       "redirectto": "넘겨줄 대상:",
        "lastmodifiedat": "이 문서는 $1 $2에 마지막으로 바뀌었습니다.",
        "viewcount": "이 문서는 {{PLURAL:$1|한 번|$1번}} 읽혔습니다.",
        "protectedpage": "보호된 문서",
        "hidetoc": "숨기기",
        "collapsible-collapse": "접기",
        "collapsible-expand": "펼치기",
+       "confirmable-confirm": "{{GENDER:$1|}}확실합니까?",
+       "confirmable-yes": "예",
+       "confirmable-no": "아니오",
        "thisisdeleted": "$1 문서를 보거나 되살리겠습니까?",
        "viewdeleted": "$1 문서를 보겠습니까?",
        "restorelink": "{{PLURAL:$1|삭제된 편집}} $1개",
        "invalidtitle-knownnamespace": "제목 오류: \"$2\" 이름공간과 \"$3\" 텍스트",
        "invalidtitle-unknownnamespace": "제목 오류: 알 수 없는 $1 이름공간 번호와, \"$2\" 텍스트",
        "exception-nologin": "로그인하지 않음",
-       "exception-nologin-text": "ì\9d´ ë¬¸ì\84\9cì\97\90 ì \91ê·¼í\95\98ê±°ë\82\98 ì\9d´ ëª\85ë ¹ì\9d\84 ì\88\98í\96\89í\95\98려면 [[Special:Userlogin|ë¡\9cê·¸ì\9d¸]]하세요.",
+       "exception-nologin-text": "ì\9d´ ë¬¸ì\84\9cì\97\90 ì \91ê·¼í\95\98ê±°ë\82\98 ì\9d´ ë\8f\99ì\9e\91ì\9d\84 ì\88\98í\96\89í\95\98려면 ë¡\9cê·¸ì\9d¸하세요.",
        "exception-nologin-text-manual": "이 문서에 접근하거나 이 명령을 수행하려면 $1하세요.",
        "virus-badscanner": "잘못된 설정: 알 수 없는 바이러스 검사기: '''$1'''",
        "virus-scanfailed": "검사 실패 (코드 $1)",
        "externaldberror": "바깥 인증 데이터베이스에 오류가 있거나 바깥 계정을 새로 고칠 권한이 없습니다.",
        "login": "로그인",
        "nav-login-createaccount": "로그인 / 계정 만들기",
-       "loginprompt": "{{SITENAME}}에 로그인하려면 쿠키를 사용할 수 있어야 합니다.",
        "userlogin": "로그인 / 계정 만들기",
        "userloginnocreate": "로그인",
        "logout": "로그아웃",
        "nologin": "계정이 없나요? $1.",
        "nologinlink": "계정을 만드세요",
        "createaccount": "계정 만들기",
-       "gotaccount": "계정이 이미 있다면, $1.",
+       "gotaccount": "계정이 이미 있습니까? $1.",
        "gotaccountlink": "로그인하세요",
        "userlogin-resetlink": "로그인 정보를 잊으셨나요?",
        "userlogin-resetpassword-link": "비밀번호를 잊으셨나요?",
        "userlogin-helplink2": "로그인에 대한 도움말",
-       "userlogin-loggedin": "이미 $1로 로그인되어 있습니다. 아래의 양식을 사용하여 다른 계정으로 로그인하세요.",
-       "userlogin-createanother": "다른 계정 만들기",
        "createacct-emailrequired": "이메일 주소",
        "createacct-emailoptional": "이메일 주소 (선택 사항)",
        "createacct-email-ph": "이메일 주소를 입력하세요",
        "loginerror": "로그인 오류",
        "createacct-error": "계정 만들기 오류",
        "createaccounterror": "계정을 만들수 없습니다: $1",
-       "nocookiesnew": "사용자 계정을 만들었지만, 아직 로그인하지 않았습니다.\n{{SITENAME}}에서는 로그인 정보를 저장하기 위해 쿠키를 사용합니다.\n지금 사용하는 웹 브라우저는 쿠키를 사용하지 않도록 설정되어 있습니다.\n로그인하기 전에 웹 브라우저에서 쿠키를 사용하도록 설정해주세요.",
+       "nocookiesnew": "사용자 계정을 만들었지만, 아직 로그인하고 있지 않습니다.\n{{SITENAME}}에서는 로그인 정보를 저장하기 위해 쿠키를 사용합니다.\n지금 사용하는 웹 브라우저는 쿠키를 사용하지 않도록 설정되어 있습니다.\n로그인하기 전에 웹 브라우저에서 쿠키를 사용하도록 설정해주세요.",
        "nocookieslogin": "{{SITENAME}}에서는 로그인을 위해 쿠키를 사용합니다.\n쿠키가 비활성되어 있습니다.\n쿠키 사용을 활성화한 다음 다시 시도하세요.",
        "nocookiesfornew": "요청의 출처를 확인할 수 없기 때문에 사용자 계정이 만들어지지 않았습니다.\n쿠키를 허용한 것을 확인한 후에 이 문서를 새로 고치고 나서 다시 시도하세요.",
        "noname": "사용자 계정 이름이 올바르지 않습니다.",
        "createaccount-text": "누군가가 {{SITENAME}} ($4)에서 사용자 이름 \"$2\", 비밀번호 \"$3\"로 당신의 이메일 주소가 등록된 계정을 만들었습니다. \n지금 로그인하여 비밀번호를 바꾸십시오.\n\n실수로 계정을 잘못 만들었다면 이 메시지는 무시해도 됩니다.",
        "login-throttled": "로그인에 연속으로 실패하였습니다.\n$1 기다렸다가 다시 시도하세요.",
        "login-abort-generic": "로그인에 실패했습니다 - 중지됨",
+       "login-migrated-generic": "당신의 계정이 마이그레이션되었으며, 당신의 사용자 이름이 더 이상 이 위키에 존재하지 않습니다.",
        "loginlanguagelabel": "언어: $1",
        "suspicious-userlogout": "브라우저에 이상이 있거나 캐싱 프록시에서 로그아웃을 요청했기 때문에 로그아웃이 거부되었습니다.",
        "createacct-another-realname-tip": "실명은 선택 사항입니다.\n실명을 입력하면 문서 기여에 사용자의 이름이 들어가게 됩니다.",
        "preview": "미리 보기",
        "showpreview": "미리 보기",
        "showdiff": "차이 보기",
-       "anoneditwarning": "'''경고''': 로그인하고 있지 않습니다.\nIP 주소가 문서 역사에 남게 됩니다.",
-       "anonpreviewwarning": "'''로그인하고 있지 않습니다. 문서를 저장하면 당신의 IP 주소가 문서 역사에 남게 됩니다.'''",
+       "blankarticle": "<strong>경고:</strong> 만들려는 문서가 비어 있습니다.\n\"{{int:savearticle}}\"을 다시 클릭하면, 문서에 내용이 없이 만들어집니다.",
+       "anoneditwarning": "<strong>경고:</strong> 로그인하고 있지 않습니다. 편집하면 당신의 IP 주소가 공개적으로 보여집니다. <strong>[$1 로그인]</strong>하거나 <strong>[$2 계정을 만들면]</strong>, 당신의 편집에 다른 이익과 함께, 사용자 이름이 표시됩니다.",
+       "anonpreviewwarning": "<em>로그인하고 있지 않습니다. 문서를 저장하면 당신의 IP 주소가 문서의 편집 역사에 남게 됩니다.</em>",
        "missingsummary": "'''알림:''' 편집 요약을 적지 않았습니다.\n이대로 \"{{int:savearticle}}\"을 클릭하면 편집 요약 없이 저장됩니다.",
        "missingcommenttext": "아래에 내용을 채워 넣어 주세요.",
        "missingcommentheader": "'''알림:''' 글의 제목을 입력하지 않았습니다.\n다시 \"{{int:savearticle}}\" 버튼을 클릭하면 글이 제목 없이 저장됩니다.",
        "node-count-exceeded-category-desc": "노드 횟수를 초과하는 문서의 분류입니다.",
        "node-count-exceeded-warning": "문서가 노드 수를 초과하였습니다.",
        "expansion-depth-exceeded-category": "문서가 확장 깊이를 초과하였습니다.",
-       "expansion-depth-exceeded-category-desc": "확장 깊이를 초과하는 문서의 분류입니다.",
+       "expansion-depth-exceeded-category-desc": "최대 확장 깊이를 초과하는 문서입니다.",
        "expansion-depth-exceeded-warning": "문서가 확장 깊이를 초과하였습니다",
        "parser-unstrip-loop-warning": "Unstrip의 반복을 감지했습니다",
        "parser-unstrip-recursion-limit": "Unstrip의 재귀 한도를 초과했습니다 ($1)",
        "currentrev": "최신판",
        "currentrev-asof": "$1 기준 최신판",
        "revisionasof": "$1 판",
-       "revision-info": "{{GENDER:$6|$2}} 사용자의 $1 판$1",
+       "revision-info": "{{GENDER:$6|$2}} 사용자의 $1 판$7",
        "previousrevision": "← 이전 판",
        "nextrevision": "다음 판 →",
        "currentrevisionlink": "최신판",
        "revdelete-text-text": "삭제된 판은 여전히 문서 역사에 남게 되지만, 그 내용의 일부는 다른 사람들이 접근할 수 없게 됩니다.",
        "revdelete-text-file": "삭제된 파일 버전은 계속 파일 역사에 남게 되지만, 내용의 일부는 다른 사람들이 접근할 수 없게 됩니다.",
        "logdelete-text": "삭제된 로그 내용은 로그에 보여지겠지만, 내용의 일부는 다른 사람들이 접근할 수 없게 됩니다.",
-       "revdelete-text-others": "{{SITENAME}}에 있는 다른 관리자는 여전히 숨겨진 내용에 접근할 수 있고 추가 제한이 설정되어 있지 않으면, 이 같은 인터페이스를 통해 다시 되살릴 수 있습니다.",
+       "revdelete-text-others": "다른 관리자는 여전히 숨겨진 내용에 접근할 수 있고 추가 제한이 설정되어 있지 않으면, 다시 되살릴 수 있습니다.",
        "revdelete-confirm": "이 작업을 수행하는 것의 결과를 알고 있으며, [[{{MediaWiki:Policy-url}}|정책]]에 맞는 행동인지 확인해주세요.",
        "revdelete-suppress-text": "숨기기는 '''다음 경우에만''' 사용되어야 합니다:\n* 잠재적인 비방 정보\n* 부적절한 개인 정보\n*: 집 주소, 전화번호, 주민등록번호 등",
        "revdelete-legend": "보이기 제한을 설정",
        "searchprofile-advanced-tooltip": "다음 설정한 이름공간에서 검색",
        "search-result-size": "$1 ({{PLURAL:$2|1 단어|$2 단어}})",
        "search-result-category-size": "{{PLURAL:$1|문서 1개|문서 $1개}}, {{PLURAL:$2|하위 분류 1개|하위 분류 $2개}}, {{PLURAL:$3|파일 1개|파일 $3개}}",
-       "search-result-score": "유사도: $1%",
        "search-redirect": "($1에서 넘어옴)",
        "search-section": "($1 문단)",
        "search-file-match": "(내용이 일치하는 파일 있음)",
        "searchall": "모두",
        "showingresults": "'''$2'''번 부터의 {{PLURAL:$1|결과 '''1'''개|결과 '''$1'''개}}입니다.",
        "showingresultsinrange": "#<strong>$2</strong>부터 #<strong>$3</strong>까지의 범위에서 <strong>$1</strong>개의 {{PLURAL:$1|결과}}가 아래에 보입니다.",
-       "showingresultsheader": "'''$4''' 검색어에 대한 {{PLURAL:$5|결과 '''$3'''개 중 '''$1'''개|결과 '''$3'''개 중 '''$1 - $2'''번째}}",
        "search-nonefound": "검색어와 일치하는 결과가 없습니다.",
        "powersearch-legend": "고급 검색",
        "powersearch-ns": "다음 이름공간에서 검색:",
        "preferences": "사용자 환경 설정",
        "mypreferences": "환경 설정",
        "prefs-edits": "편집 수:",
-       "prefsnologintext2": "사용자 환경 설정을 설정하려면 $1하십시오.",
+       "prefsnologintext2": "사용자 환경 설정을 변경하려면 로그인하십시오.",
        "prefs-skin": "스킨",
        "skin-preview": "미리 보기",
        "datedefault": "설정하지 않음",
        "prefs-dateformat": "날짜 형식",
        "prefs-timeoffset": "시차 설정",
        "prefs-advancedediting": "일반 설정",
-       "prefs-editor": "편집",
+       "prefs-editor": "편집",
        "prefs-preview": "미리 보기",
        "prefs-advancedrc": "고급 설정",
        "prefs-advancedrendering": "고급 설정",
        "right-browsearchive": "삭제된 문서 검색",
        "right-undelete": "삭제된 문서 되살리기",
        "right-suppressrevision": "관리자가 보지 못하도록 숨겨진 판을 검토하고 되살리기",
+       "right-viewsuppressed": "어떤 사용자가 숨긴 판 보기",
        "right-suppressionlog": "숨겨진 기록을 보기",
        "right-block": "다른 사용자가 편집을 못하도록 차단",
        "right-blockemail": "다른 사용자가 이메일을 보내지 못하도록 차단",
        "right-noratelimit": "속도 제한에 영향을 받지 않음",
        "right-import": "다른 위키에서 문서 가져오기",
        "right-importupload": "파일 올리기를 통해 문서 가져오기",
-       "right-patrol": "다른 사용자의 편집을 검토",
-       "right-autopatrol": "자신의 편집을 자동으로 검토",
-       "right-patrolmarks": "최근 바뀜에서 검토 표시를 보기",
+       "right-patrol": "다른 사용자의 편집을 점검된 것으로 표시",
+       "right-autopatrol": "자신의 편집을 자동으로 점검된 판으로 표시",
+       "right-patrolmarks": "최근 바뀜에서 점검 표시를 보기",
        "right-unwatchedpages": "주시되지 않은 문서 목록 보기",
        "right-mergehistory": "문서의 역사를 합침",
        "right-userrights": "사용자의 모든 권한 조정",
        "action-rollback": "특정 문서를 마지막으로 편집한 사용자의 모든 편집을 간편하게 되돌리기",
        "action-import": "다른 위키에서 문서 가져오기",
        "action-importupload": "파일 올리기를 통해 문서를 가져오기",
-       "action-patrol": "다른 사용자의 편집을 검토된 것으로 표시하기",
-       "action-autopatrol": "자신의 편집을 검토된 것으로 표시할",
+       "action-patrol": "다른 사용자의 편집을 점검된 것으로 표시할",
+       "action-autopatrol": "자신의 편집을 점검된 것으로 표시할",
        "action-unwatchedpages": "주시되지 않은 문서 목록 보기",
        "action-mergehistory": "이 문서의 역사 합치기",
        "action-userrights": "사용자의 모든 권한 조정",
        "recentchanges-legend-heading": "'''범례:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|새 문서 목록]]도 보세요)",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "다음은 <strong>$2</strong>에서부터 바뀐 문서 <strong>$1</strong>개입니다.",
+       "rcnotefrom": "아래는 <strong>$3, $4</strong>부터 시작하는 {{PLURAL:$5|바뀜이 있습니다}}. (최대 <strong>$1</strong>개가 보여집니다)",
        "rclistfrom": "$3 $2부터 시작하는 새로 바뀐 문서 보기",
        "rcshowhideminor": "사소한 편집을 $1",
        "rcshowhideminor-show": "보이기",
        "rcshowhideanons": "익명 사용자를 $1",
        "rcshowhideanons-show": "보이기",
        "rcshowhideanons-hide": "숨기기",
-       "rcshowhidepatr": "ì\88\9cì°°ë\90\9c í\8e¸ì§\91ì\9d\84 $1",
+       "rcshowhidepatr": "ì \90ê²\80í\95\9c í\8e¸ì§\91ì\9d\84 $1",
        "rcshowhidepatr-show": "보이기",
        "rcshowhidepatr-hide": "숨기기",
        "rcshowhidemine": "내 편집을 $1",
        "rcshowhidemine-show": "보이기",
        "rcshowhidemine-hide": "숨기기",
        "rclinks": "최근 $2일간의 $1개 바뀐 문서 보기<br />$3",
-       "diff": "비교",
+       "diff": "차이",
        "hist": "역사",
        "hide": "숨기기",
        "show": "보이기",
        "uploadwarning": "올리기 경고",
        "uploadwarning-text": "아래의 파일 설명을 수정하고 다시 시도해 주세요.",
        "savefile": "파일 저장",
-       "uploadedimage": "사용자가 \"[[$1]]\" 파일을 올렸습니다.",
-       "overwroteimage": "사용자가 \"[[$1]]\" 파일의 새 판을 올렸습니다.",
        "uploaddisabled": "올리기 비활성화됨",
        "copyuploaddisabled": "URL로 파일 올리기가 비활성화되어 있습니다.",
        "uploaddisabledtext": "파일 올리기 기능이 비활성화되어 있습니다.",
        "license": "라이선스:",
        "license-header": "라이선스",
        "nolicense": "선택하지 않음",
+       "licenses-edit": "라이선스 옵션 편집",
        "license-nopreview": "(미리 보기 불가능)",
        "upload_source_url": "(올바르고, 공개적으로 접근할 수 있는 URL)",
-       "upload_source_file": " (당신의 컴퓨터에 있는 파일)",
+       "upload_source_file": "(당신의 컴퓨터에서 선택한 파일)",
+       "listfiles-delete": "삭제",
        "listfiles-summary": "이 특수 문서는 모든 올려진 파일을 보여줍니다.",
        "listfiles_search_for": "다음 미디어 이름 검색:",
        "imgfile": "파일",
        "randomincategory": "분류 안의 임의 문서",
        "randomincategory-invalidcategory": "\"$1\"(은)는 올바른 분류 이름이 아닙니다.",
        "randomincategory-nopages": "[[:Category:$1]]에 문서가 없습니다.",
-       "randomincategory-selectcategory": "분류에서 임의 문서 얻기: $1 $2",
-       "randomincategory-selectcategory-submit": "보기",
+       "randomincategory-category": "분류:",
+       "randomincategory-legend": "분류 안의 임의 문서",
        "randomredirect": "임의 넘겨주기 문서로",
        "randomredirect-nopages": "\"$1\" 이름공간에서 해당하는 넘겨주기 문서가 없습니다.",
        "statistics": "통계",
        "wantedpages-badtitle": "문서 제목이 잘못되었습니다: $1",
        "wantedfiles": "필요한 파일 목록",
        "wantedfiletext-cat": "다음 파일은 쓰이고는 있지만 없는 파일입니다. 바깥 저장소에 있는 파일은 실제로는 있지만 여기 올라 있을 수 있습니다. 그런 오류는 <del>삭제선</del>이 그어질 것입니다. 또한 없는 파일을 포함하고 있는 문서는 [[:$1]]에 올라 있습니다.",
-       "wantedfiletext-nocat": "다음 파일은 쓰이고는 있지만 없는 파일입니다. 바깥 저장소에 있는 파일은 실제로는 있지만 여기 올라 있을 수 있습니다. 그런 오류는 <del>삭제선</del>이 그어질 것입니다.",
+       "wantedfiletext-cat-noforeign": "다음 파일은 쓰이고 있지만 존재하지 않습니다. 또한, 존재하지 않는 파일이 포함된 문서가 [[:$1]]에 나열되어 있습니다.",
+       "wantedfiletext-nocat": "다음 파일은 쓰이고 있지만 존재하지 않습니다. 바깥 저장소에 있는 파일은 실제로는 있지만 여기 올라 있을 수 있습니다. 그런 오류는 <del>삭제선</del>이 그어질 것입니다.",
+       "wantedfiletext-nocat-noforeign": "다음 파일은 쓰이고 있지만 존재하지 않습니다.",
        "wantedtemplates": "필요한 틀 목록",
        "mostlinked": "가장 많이 연결된 문서 목록",
        "mostlinkedcategories": "가장 많이 연결된 분류 목록",
        "trackingcategories-desc": "분류 포함 기준",
        "noindex-category-desc": "문서는 그것과 그 플래그가 허용된 곳에 있는 이름공간에서 <code><nowiki>__NOINDEX__</nowiki></code> 특수 명령이 있기 때문에 로봇이 색인하지 않습니다.",
        "index-category-desc": "문서는 그것(과 플래그가 허용된 곳에 있는 이름공간에 있는 것)에 <code><nowiki>__INDEX__</nowiki></code>가 있어서, 정상적이지 않을 곳에 로봇에 의해 색인됩니다.",
-       "post-expand-template-inclusion-category-desc": "모든 틀을 확장하고 나서, 문서 크기가 <code>$wgMaxArticleSize</code>보다 커지므로, 어떤 틀은 확장하지 않았습니다.",
+       "post-expand-template-inclusion-category-desc": "모든 틀을 전개하였을 때, 문서 크기가 <code>$wgMaxArticleSize</code>보다 커지므로, 어떤 틀은 전개하지 않았습니다.",
        "post-expand-template-argument-category-desc": "틀 변수 (<code>{{{Foo}}}</code>와 같은, 중괄호가 세 개 있는 무언가)를 확장하고 나서, 문서는 <code>$wgMaxArticleSize</code>보다 커집니다.",
        "expensive-parserfunction-category-desc": "(<code>#ifexist</code>와 같은) 느린 파서 함수가 너무 많이 문서에 포함되어 있습니다. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit]를 보세요.",
        "broken-file-category-desc": "분류가 깨진 파일 링크 (파일이 존재하지 않을 때 포함되는 링크)가 있는 문서가 있다면 추가됩니다.",
        "watchlist-details": "별도의 토론 문서를 세지 않고, 주시문서 목록에 {{PLURAL:$1|문서 $1개}}가 있습니다.",
        "wlheader-enotif": "이메일 알림 기능이 활성화되었습니다.",
        "wlheader-showupdated": "마지막으로 방문한 이후에 바뀐 문서는 '''굵은 글씨'''로 보입니다.",
-       "wlnote2": "아래는 $2, $3 기준으로 지난 {{PLURAL:$1|한 시간|<strong>$1</strong>시간}} 동안의 바뀜입니다.",
+       "wlnote": "다음은 최근 {{PLURAL:$2|'''$2'''시간}} 동안 {{PLURAL:$1|바뀐 문서 '''$1'''개 입니다}}. ($3 $4 기준)",
        "wlshowlast": "최근 $1시간 $2일 또는 $3 동안에 바뀐 문서 보기",
        "watchlist-options": "주시문서 목록 설정",
        "watching": "주시 추가 중…",
        "delete-edit-reasonlist": "삭제 이유 편집",
        "delete-toobig": "이 문서에는 {{PLURAL:$1|편집 역사}}가 $1개 있습니다.\n편집 역사가 긴 문서를 삭제하면 {{SITENAME}}에 큰 혼란을 줄 수 있기 때문에 삭제할 수 없습니다.",
        "delete-warning-toobig": "이 문서에는 {{PLURAL:$1|편집 역사}}가 $1개 있습니다.\n편집 역사가 긴 문서를 삭제하면 {{SITENAME}} 데이터베이스 동작에 큰 영향을 줄 수 있습니다.\n주의해 주세요.",
+       "deleteprotected": "이 문서가 잠겨 있기 때문에 삭제할 수 없습니다.",
        "deleting-backlinks-warning": "'''경고:''' 삭제하려는 문서가 [[Special:WhatLinksHere/{{FULLPAGENAME}}|다른 문서]]에 링크되어 있거나 끼워져 있습니다.",
        "rollback": "편집 되돌리기",
        "rollback_short": "되돌리기",
        "undeletepagetext": "다음 {{PLURAL:$1|문서는 삭제되었지만|문서 $1개는 삭제되었지만}} 아직 보관되어 있고 되살릴 수 있습니다.\n보관된 문서는 주기적으로 삭제될 것입니다.",
        "undelete-fieldset-title": "문서 되살리기",
        "undeleteextrahelp": "문서 역사 전체를 되살리려면 모든 체크박스의 선택을 해제하고 '''{{int:undeletebtn}}'''를 누르세요.\n특정한 버전만 되살리려면 되살리려는 버전을 선택하고 '''{{int:undeletebtn}}'''를 누르세요.",
-       "undeleterevisions": "{{PLURAL:$1|판}} $1개 보관 중",
+       "undeleterevisions": "{{PLURAL:$1|판}} $1개가 보존되어 있습니다",
        "undeletehistory": "문서를 되살리면 모든 역사가 같이 복구됩니다.\n문서가 삭제된 뒤 같은 이름의 문서가 만들어졌다면, 복구되는 역사는 지금 역사의 과거 부분에 나타날 것입니다.",
        "undeleterevdel": "복구하려는 문서의 최신판이 삭제되어 있는 경우 문서를 되살릴 수 없습니다.\n이러한 경우 삭제된 최신판 문서의 확인 상자를 선택 해제하거나 숨김을 해제해야 합니다.",
        "undeletehistorynoadmin": "이 문서는 삭제되었습니다.\n삭제된 이유와 삭제되기 전에 이 문서를 편집한 사용자가 아래에 나와 있습니다.\n삭제된 문서의 내용을 보려면 관리자 권한이 필요합니다.",
        "undeletedrevisions-files": "{{PLURAL:$1|판 1개|판 $1개}}와 {{PLURAL:$2|파일 1개|파일 $2개}}를 되살렸습니다",
        "undeletedfiles": "{{PLURAL:$1|파일 1개|파일 $1개}}를 되살렸습니다",
        "cannotundelete": "되살리는 데 실패했습니다:\n$1",
-       "undeletedpage": "'''$1 문서를 되살렸습니다.'''\n\n[[Special:Log/delete|삭제 기록]]에서 최근의 삭제와 되살리기 기록을 볼 수 있습니다.",
+       "undeletedpage": "<strong>$1 문서를 되살렸습니다.</strong>\n\n[[Special:Log/delete|삭제 기록]]에서 최근의 삭제 및 되살리기 기록을 볼 수 있습니다.",
        "undelete-header": "최근에 삭제한 문서에 대한 기록은 [[Special:Log/delete|여기]]에서 볼 수 있습니다.",
        "undelete-search-title": "삭제된 문서 검색",
        "undelete-search-box": "삭제된 문서 검색",
        "autoblockid": "자동 차단 #$1",
        "block": "사용자 차단",
        "unblock": "사용자 차단 해제",
-       "blockip": "사용자 차단",
+       "blockip": "{{GENDER:$1|사용자}} 차단",
        "blockip-legend": "사용자 차단",
        "blockiptext": "차단할 IP 주소나 사용자 이름을 아래에 적어 주세요.\n차단은 문서 훼손을 막기 위해, [[{{MediaWiki:Policy-url}}|정책]]에 의해서만 이루어져야 합니다.\n차단 이유를 같이 적어주세요(예: 특정 문서 훼손).",
        "ipaddressorusername": "IP 주소 또는 사용자 이름:",
        "ipb-unblock-addr": "$1 차단 해제하기",
        "ipb-unblock": "사용자 또는 IP 주소 차단 해제하기",
        "ipb-blocklist": "현재 차단 기록 보기",
-       "ipb-blocklist-contribs": "$1의 기여",
+       "ipb-blocklist-contribs": "{{GENDER:$1|$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": "차단된 사용자 찾기",
        "import": "문서 가져오기",
        "importinterwiki": "다른 위키에서 문서 가져오기",
        "import-interwiki-text": "문서를 가져올 위키를 선택하고 문서 제목을 입력해주세요.\n편집 날짜와 편집자의 이름이 보존될 것입니다.\n모든 가져오기는 [[Special:Log/import|가져오기 기록]]에 기록될 것입니다.",
-       "import-interwiki-source": "원본 위키/문서:",
+       "import-interwiki-sourcewiki": "원본 위키:",
+       "import-interwiki-sourcepage": "원본 문서:",
        "import-interwiki-history": "이 문서의 모든 역사를 가져오기",
        "import-interwiki-templates": "모든 틀을 포함하기",
        "import-interwiki-submit": "가져오기",
        "importlogpage": "가져오기 기록",
        "importlogpagetext": "다른 위키에서 가져온 문서 기록입니다.",
        "import-logentry-upload": "사용자가 파일 올리기를 통해 [[$1]] 문서를 가져왔습니다",
-       "import-logentry-upload-detail": "{{PLURAL:$1|판}} $1개",
+       "import-logentry-upload-detail": "{{PLURAL:$1|판}} $1개를 가져왔습니다",
        "import-logentry-interwiki": "$1 문서를 다른 위키에서 가져왔습니다",
        "import-logentry-interwiki-detail": "$2에서 {{PLURAL:$1|판}} $1개를 가져왔습니다",
        "javascripttest": "자바스크립트 테스트",
        "pageinfo-category-pages": "문서 수",
        "pageinfo-category-subcats": "하위 분류 수",
        "pageinfo-category-files": "파일 수",
-       "markaspatrolleddiff": "검토한 문서로 표시",
-       "markaspatrolledtext": "이 문서를 검토한 것으로 표시",
-       "markedaspatrolled": "검토한 문서로 표시",
+       "markaspatrolleddiff": "점검한 문서로 표시",
+       "markaspatrolledtext": "이 문서를 점검한 것으로 표시",
+       "markedaspatrolled": "점검한 문서로 표시",
        "markedaspatrolledtext": "[[:$1]] 문서의 선택한 판을 순찰한 것으로 표시하였습니다.",
-       "rcpatroldisabled": "최근 바뀜 검토 기능 비활성화됨",
-       "rcpatroldisabledtext": "최근 바뀜 검토 기능은 현재 비활성화되어 있습니다.",
-       "markedaspatrollederror": "검토한 것으로 표시할 수 없습니다.",
-       "markedaspatrollederrortext": "검토한 것으로 표시할 판을 지정해야 합니다.",
-       "markedaspatrollederror-noautopatrol": "자신의 편집은 스스로 검토할 수 없습니다.",
-       "markedaspatrollednotify": "$1에 대한 바뀜을 검토한 것으로 표시했습니다.",
-       "markedaspatrollederrornotify": "검토한 것으로 표시를 실패했습니다.",
-       "patrol-log-page": "검토 기록",
-       "patrol-log-header": "문서 검토에 대한 기록입니다.",
-       "log-show-hide-patrol": "검토 기록을 $1",
+       "rcpatroldisabled": "최근 바뀜 점검 기능 비활성화됨",
+       "rcpatroldisabledtext": "최근 바뀜 점검 기능은 현재 비활성화되어 있습니다.",
+       "markedaspatrollederror": "점검한 것으로 표시할 수 없습니다.",
+       "markedaspatrollederrortext": "점검한 것으로 표시할 판을 지정해야 합니다.",
+       "markedaspatrollederror-noautopatrol": "자신의 편집은 스스로 점검할 수 없습니다.",
+       "markedaspatrollednotify": "$1에 대한 바뀜을 점검한 것으로 표시했습니다.",
+       "markedaspatrollederrornotify": "점검한 것으로 표시를 실패했습니다.",
+       "patrol-log-page": "점검 기록",
+       "patrol-log-header": "문서 점검에 대한 기록입니다.",
+       "log-show-hide-patrol": "점검 기록을 $1",
        "deletedrevision": "예전 $1 판이 삭제되었습니다.",
        "filedeleteerror-short": "파일 삭제 오류: $1",
        "filedeleteerror-long": "파일을 삭제하는 도중 오류가 발생했습니다:\n\n$1",
        "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": "주시문서 목록 편집하기",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|토론]])",
        "unknown_extension_tag": "알 수 없는 확장 기능 태그 \"$1\"",
        "duplicate-defaultsort": "'''경고:''' 기본 정렬 키 \"$2\"가 이전의 기본 정렬 키 \"$1\"를 덮어쓰고 있습니다.",
+       "duplicate-displaytitle": "<strong>경고:</strong> \"$2\" 제목 표시는 기존의 표시되는 제목 \"$1\"을 덮어씁니다.",
        "version": "버전",
        "version-extensions": "설치된 확장 기능",
        "version-skins": "설치된 스킨",
        "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-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-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|올렸습니다}}",
        "rightsnone": "(없음)",
        "feedback-bugornote": "기술적 문제를 구체적으로 설명할 준비가 되었다면 [$1 버그를 신고]해 주세요.\n아니면 아래에 쉬운 양식을 쓸 수 있습니다. 의견은 사용자 이름과 함께 \"[$3 $2]\"에 남겨질 것입니다.",
        "feedback-subject": "제목:",
        "expand_templates_remove_nowiki": "결과에서 <nowiki> 태그를 숨기기",
        "expand_templates_generate_xml": "XML 구문 트리 보기",
        "expand_templates_generate_rawhtml": "원본 HTML 보이기",
-       "expand_templates_preview": "미리 보기"
+       "expand_templates_preview": "미리 보기",
+       "pagelanguage": "문서 언어 선택기",
+       "pagelang-name": "문서",
+       "pagelang-language": "언어",
+       "pagelang-use-default": "기본 언어 사용",
+       "pagelang-select-lang": "언어 선택",
+       "right-pagelang": "문서 언어 바꾸기",
+       "action-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 (활성화)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''비활성화''')"
 }
index 9df747a..4cded69 100644 (file)
@@ -2,7 +2,8 @@
        "@metadata": {
                "authors": [
                        "Enye Lav",
-                       "Yufereff"
+                       "Yufereff",
+                       "아라"
                ]
        },
        "underline-always": "Пыр",
@@ -85,8 +86,6 @@
        "qbmyoptions": "Листбоккезö",
        "faq": "Отир сё юасьö",
        "faqpage": "Project:отир сё юасьö",
-       "vector-action-delete": "Чышкыны",
-       "vector-view-view": "Лыддьöтны",
        "variants": "Варианттэз",
        "errorpagetitle": "Сорасьöм",
        "returnto": "Бертны $1-öдз.",
        "talkpagelinktext": "Сёрнитан",
        "specialpage": "Тодильнöй листбок",
        "personaltools": "Аслат керöтаннэз",
-       "postcomment": "Виль юкöт",
        "talk": "Сёрни",
        "views": "Видзöтöммез",
        "toolbox": "Керöтаннэз",
        "viewprevnext": "Видзöтны ($1 {{int:pipe-separator}} $2) ($3)",
        "searchprofile-everything": "Быдлаись",
        "searchprofile-articles-tooltip": "Кошшан $1ын",
-       "searchprofile-project-tooltip": "Кошшан $1ын",
        "search-result-size": "$1 ({{PLURAL:$2|1=1 кыв|$2 кыв}})",
        "search-redirect": "(иньдöтöм $1 вылiсь)",
        "search-section": "(юкöт № $1)",
        "searchall": "быдöс",
        "powersearch-legend": "Паськытжыка кошшан",
        "powersearch-ns": "Ним чукöррезiсь кошшан:",
-       "powersearch-redir": "Мöдлаö иньдöтöммез ним сьöртi",
        "powersearch-toggleall": "Быдöс",
        "powersearch-togglenone": "Нем",
        "preferences": "Лöсьöтаннэз",
        "timezoneregion-pacific": "Лöнь океан",
        "youremail": "Электрон пошта:",
        "username": "Уджкерисьлöн ним:",
-       "uid": "Уджкерисьлöн лыддьöса пас:",
        "yourrealname": "Быльнöй нимыт:",
        "yourlanguage": "Кыв:",
        "yournick": "Виль кырымпас:",
        "recentchanges": "Медбöрья вильмöтöммез",
        "recentchanges-legend": "Медбöрья вильмöтöммез понда лöсьöтаннэз",
        "recentchanges-feed-description": "Синмавны медбöрья вильмöтöммез этiя вики визылын.",
-       "rclistfrom": "Мыччавны вильмöтöмсö  $1-сянь",
+       "rclistfrom": "Мыччавны вильмöтöмсö  $3 $2-сянь",
        "rcshowhideminor": "$1 невунка мöдкöдьсьöтыштöм",
        "rcshowhidebots": "$1 бот",
        "rcshowhideliu": "Ас нимöн $1 уджкерись",
        "recentchangeslinked-to": "Мыччавны мöдкодьсьöтöммез листбоккез вылын, кöдна асьныс ыстiсьöны этiя листбок вылö",
        "upload": "Кышавны файл",
        "uploadlogpage": "Тöбалöм сьöртi журнал",
-       "uploadedimage": "тöбалiс ''[[$1]]''",
        "filehist": "Файллöн история",
        "filehist-help": "Нырышт дата/кад, мед адззыны, кытшöмöн сэк вöлi файлыс.",
        "filehist-current": "öння",
        "booksources-go": "Кошшыны",
        "log": "Журналлэз",
        "allpages": "Быдöс листбоккез",
-       "alphaindexline": "$1-сянь $2-дынö",
        "prevpage": "Одзжыкся листбок ($1)",
        "allpagesfrom": "Мыччавны листбоккез, кöдна пондöтчöны сiдз:",
        "allpagesto": "Мыччавны листбоккез татшöмöдз:",
index fdd1d4e..d027276 100644 (file)
        "talkpagelinktext": "сюзюу",
        "specialpage": "Къуллукъ бет",
        "personaltools": "Энчи адырла",
-       "postcomment": "Джангы бёлюм",
        "articlepage": "Статьягъа къарау",
        "talk": "Сюзюу",
        "views": "Къараула",
        "externaldberror": "Тыш информация базаны болушлугъу бла аутентификация, халатлы болду, неда тыш аккаунтугъузну тюрлендирирге хакъларагъыз джетмейди.",
        "login": "Системагъа кириу",
        "nav-login-createaccount": "Системагъа кириу / Аккаунт къурау",
-       "loginprompt": "{{SITENAME}} сайтха кирир ючюн «cookies» эркин этерге керексиз.",
        "userlogin": "Кир / регистрация эт",
        "userloginnocreate": "Кириу",
        "logout": "Чыгъыу",
        "searchprofile-advanced-tooltip": "Энчи ат аланладада изле",
        "search-result-size": "$1 ({{PLURAL:$2|1 сёз|$2 сёз}})",
        "search-result-category-size": "{{PLURAL:$1|1=1 элемент|$1 элемент}} ({{PLURAL:$2|1=1 тюбкатегория|$2 тюбкатегория}}, {{PLURAL:$3|1=1 файл|$3 файл}})",
-       "search-result-score": "Келишиулюк: $1%",
        "search-redirect": "(Джиберилиниу $1)",
        "search-section": "($1 бёлюм)",
        "search-file-match": "(файлны ичиндегиси бла бирди)",
        "uploadwarning": "Эсгертиу",
        "uploadwarning-text": "Файлны тюбюрекде келтирилген ачыкълауун тюрлендиригиз да джангыдан кёрюгюз.",
        "savefile": "Файлны сакълат",
-       "uploadedimage": "«[[$1]]» джюкленнгенди",
-       "overwroteimage": "«[[$1]]» суратны джангы версиясы джюкленнгенди",
        "uploaddisabled": "Джюклеуге эркинлик джокъду",
        "copyuploaddisabled": "URL кёре джюклеу джукъланыбды.",
        "uploaddisabledtext": "Файлланы джюклеу мадар джукъланыбды",
        "watchlist-details": "Кёздеги тизмегизде сюзюу бетлери саналмай {{PLURAL:$1|бет|бет}} барды.",
        "wlheader-enotif": "E-mail бла хапар бериу джандырылыбды.",
        "wlheader-showupdated": "Ахыр кириуюгюзден сора бетни тюрлениулери '''къалын''' джазыу бла кёргюзюлгенди.",
-       "wlnote2": "Тюбюнде, ахыр {{PLURAL:$1|сагъатны|<strong>$1</strong> сагъатны}} ичинден этилген тюрлениуле кёрюнедиле, $2, $3 заманда болумгъа кёре.",
+       "wlnote": "Тюбюндеди кёргюзюлгенди: ахыр '''$2''' сагъатха этилген ахыр '''$1''' тюрлениу, $3 $4 заманнга дери.",
        "wlshowlast": "Арт $1 сагъат $2 кюннге $3 кёргюз",
        "watchlist-options": "Кёзде тургъан тизмени джарашдырыулары",
        "watching": "Кёзде тургъан тизмеге къошуу...",
index 794bfbc..5cb828e 100644 (file)
@@ -6,8 +6,35 @@
                        "Protostar"
                ]
        },
+       "tog-underline": "Link ùndarlaintin",
        "tog-hideminor": "Haid dhi lili chenjdèm na dhi resènt chenj list",
+       "tog-hidepatrolled": "Haid patrol èditdèm na risènt chenjdèm",
+       "tog-newpageshidepatrolled": "Haid patrol pejdèm na dhi nyu pej list",
        "tog-extendwatchlist": "Èkspand dhi wachlist fòr show òll dhi chenjdèm,  pas dhi resènt chenjdèm nòmòr",
+       "tog-usenewrc": "Grup chenjdèm bay pej na dhi risènt chenj wachlist",
+       "tog-numberheadings": "Auto-nùmbar hedtindèm",
+       "tog-showtoolbar": "Show dhi èdit tulbar",
+       "tog-editondblclick": "Èdit pejdèm with tutèm klik",
+       "tog-editsectiononrightclick": "Ebul sèkshòn èdit whe yu raiht klik pan sèkshòn tituldèm",
+       "tog-watchcreations": "Add pejdèm whe a kreat èn faildèm whe a ùplod tu mi wachlist",
+       "tog-watchdefault": "Add pejdèm èn faildèm whe a èdit tu mi wachlist.",
+       "tog-watchmoves": "Add dhi pejdèm we a muf go mi wachlist",
+       "tog-watchdeletion": "Add dhi pejdèm èn faildèm we a delet go mi wachlist",
+       "tog-minordefault": "Mark òll èditdèm lèkkè minòr bay default",
+       "tog-previewontop": "Show prevyu bifor èdit bòks",
+       "tog-previewonfirst": "Show prevyu we dhi fùrs èdit dòn",
+       "tog-enotifwatchlistpages": "Sèn mi e-mel wan pej òr fail na mi wachlist chenj",
+       "tog-enotifusertalkpages": "Sèn mi e-mel whe mi yuzar tòk pej chenj",
+       "tog-enotifminoredits": "Sèn mi e-mel fòr minòr pej èn fail èditdèm",
+       "tog-enotifrevealaddr": "Show mi e-mel addrèss na mi notifakshòn e-meldèm",
+       "tog-shownumberswatching": "Show dhi nùmbàr dhi yuzardèm we de wach",
+       "tog-oldsig": "Signatura we èksist",
+       "tog-fancysig": "Trit signatura lèkkè wikitext (withaut automatik link)",
+       "tog-uselivepreview": "Yuz laive prevyu (èkspèrimèntlèkk)",
+       "tog-forceeditsummary": "Tèllmi we a de èntar blank èdit sùmmari",
+       "tog-watchlisthideown": "Haid mi èditdèm kòmòt mi wachlist",
+       "tog-watchlisthidebots": "Haid bòtèdit kòmòt dhi wachlist",
+       "tog-watchlisthideminor": "Haid minòr èditdèn kòmòt dhi wachlist",
        "sunday": "Sandey",
        "monday": "Mundey",
        "tuesday": "Tyrdey",
        "navigation": "Navigatio",
        "qbedit": "Èdit",
        "faq": "Kwèstiòn dèndeaks bòku",
-       "faqpage": "Projèkt:Kuèstiòndèm we òllman de ask",
-       "vector-action-addsection": "Add tòpik",
-       "vector-action-delete": "Delet",
-       "vector-action-move": "Muf",
-       "vector-action-protect": "Protèkt",
-       "vector-view-create": "Kreat",
-       "vector-view-edit": "Chenj",
-       "vector-view-history": "Luk historia",
-       "vector-view-view": "Rid",
-       "vector-view-viewsource": "Luk dhi sòrs",
+       "faqpage": "Project:Kuèstiòndèm we de ask bòku",
        "actions": "Actiòndèm",
        "namespaces": "Nemspasiodèm",
        "variants": "Variantdèm",
        "talkpagelinktext": "Tòk",
        "specialpage": "Spèsial Pej",
        "personaltools": "Pèrsònal tuldèm",
-       "postcomment": "Nyu sèktiòn",
        "articlepage": "Luk kòntènt pej",
        "talk": "Diskùssiòn",
        "views": "Vyudèm",
        "jumptosearch": "Luk fòr",
        "aboutsite": "Na bòt {{SITENAME}}",
        "aboutpage": "Project:Na bòt",
-       "copyright": "Dis kontent de onda $1 .",
+       "copyright": "Dhis kòntènt avelebul ùndar $1 .",
        "currentevents": "Kùrrènt evèntdèm",
        "currentevents-url": "Project:Kùrrènt evèntdèm",
        "disclaimers": "Disklamardèm",
        "yourpasswordagain": "Retayp passwòrd",
        "login": "Lògin",
        "nav-login-createaccount": "Lògin / Mek yu yon akkaunt",
-       "loginprompt": "Yu gèt fòde yuz kukidèm fòr ebul fòrlogin {{SITENAME}}.",
        "userlogin": "Lògin / Mek yu yon akkaunt",
        "logout": "Lògòt",
        "userlogout": "Lògòt",
        "createaccount": "Kreat yu yon akkaunt",
        "gotaccount": "Yu dòn mek yu akkaunt? '''$1'''.",
        "gotaccountlink": "Lògin",
-       "createaccountmail": "wit imel",
+       "createaccountmail": "Yuz shòrttèm randòm passwòrd èn sèn am go dhi imel address we spesifay",
        "badretype": "Dhi passwòrddèm we yu taip nò mach.",
        "userexists": "Odhar pòrsin de yuz dha yuzmannem.\nYu go gèt fòr pik differènt wan.",
        "mailmypassword": "Resèt passwòrd",
        "savearticle": "Sev dis pej",
        "preview": "Prevyu",
        "showpreview": "Luk dhi prevyu",
-       "showlivepreview": "Luk dhi laiv prevyu",
        "showdiff": "Sho wetin dòn chenj",
        "anoneditwarning": "'''Tek tèm o:''' Yu nò lògin yet.\nSo dèn go sev yu IP addrèss na dhi pejim èdithistoria",
        "missingsummary": "'''Mèmbar se:''' yu nò mek èditsùmmari.\nIf yu prèss sev bak, dhèm go sev yu èdit nòmor.",
        "shown-title": "Show $1 {{PLURAL:$1|resùlt|resùltdèm}} fòr pej",
        "viewprevnext": "Vyu ($1 {{int:pipe-separator}} $2) ($3)",
        "searchprofile-articles": "Kòntèntpejdèm",
-       "searchprofile-project": "Hèp èn Protèkt pejdèm",
        "searchprofile-images": "Mùltimedia",
        "searchprofile-everything": "Òllthin",
        "searchprofile-advanced": "We advans",
        "searchprofile-articles-tooltip": "Sarch na $1",
-       "searchprofile-project-tooltip": "Sarch na $1",
        "searchprofile-images-tooltip": "Sarch fòr faildèm",
        "search-result-size": "$1 ({{PLURAL:$2|1 wòrd|$2 wòrddèm}})",
        "search-section": "(sèkshòn $1)",
        "search-nonefound": "Resùltdèm we mach dhi kweri nò de",
        "powersearch-legend": "Advanssarch",
        "powersearch-ns": "Sarch na nemspatiodèm:",
-       "powersearch-redir": "List de sèn yu go",
        "search-external": "Èksternal sarch",
        "searchdisabled": "{{websaitim nem}} Dhi sarch nò de work.\nNa dhi mintèm yuz Google fòr sarch.\nMèmbar se sòmtèm dhèm indèksdèm na {{SITENAME}}go dòn datòt.",
        "mypreferences": "Prèfèrèntiadèm",
        "searchresultshead": "Sarch",
        "youremail": "Emel:",
-       "username": "Yuzanem:",
+       "username": "Yuzmannem:",
        "yourrealname": "Real nem",
        "newuserlogpage": "Yuzman kreattin lòg",
        "action-edit": "èdit dhis pej",
        "booksources-go": "Go",
        "log": "Lògdèm",
        "allpages": "Òll pejdèm",
-       "alphaindexline": "$1 go $2",
        "allarticles": "Òll pejdèm",
        "allpagessubmit": "Go",
        "categories": "Katègòridèm",
index 583b573..da11257 100644 (file)
        "talkpagelinktext": "Klaaf",
        "specialpage": "{{int:nstab-special}}",
        "personaltools": "Metmaacher Werkzüch",
-       "postcomment": "Neu Avschnedd op de Klaafsigg donn",
        "articlepage": "Aanluure wat op dä Sigg drop steiht",
        "talk": "Klaafe",
        "views": "Aansichte",
        "externaldberror": "Do wor ene Fähler en de externe Daatebank, oder Do darfs Ding extern Daate nit ändere. Dat Aanmelde jingk jedenfalls donevve.",
        "login": "Enlogge",
        "nav-login-createaccount": "Enlogge, Aanmälde",
-       "loginprompt": "Öm heh enlogge ze künne, muss De de <i lang=\"en\">Cookies</i> en Dingem Brauser enjeschalt han.",
        "userlogin": "Enlogge odder Metmaacher wääde",
        "userloginnocreate": "Enlogge",
        "logout": "Ußlogge",
        "searchprofile-advanced-tooltip": "Donn en ußjesohte Appachtemangs sööke",
        "search-result-size": "$1 ({{PLURAL:$2|Eij Woot|$2 Wööter|Keij Woot}})",
        "search-result-category-size": "{{PLURAL:$1|1 Saach|$1 Saache|0 Saache}} ({{PLURAL:$2|1 Ongerjropp|$2 Ongerjroppe|0 Ongerjroppe}}, {{PLURAL:$3|1 Datei|$3 Dateie|0 Dateie}})",
-       "search-result-score": "Jeweesch: $1%",
        "search-redirect": "(Ömleitung $1)",
        "search-section": "(Avschnett $1)",
        "search-file-match": "(en dä Dattei dren)",
        "uploadwarning": "Warnung beim Huhlade",
        "uploadwarning-text": "Donn onge dä Täx övver di Dattei ändere, un versöhg_et norr_ens.",
        "savefile": "Datei avspeichere",
-       "uploadedimage": "hät huhjelade: „[[$1]]“",
-       "overwroteimage": "hät en neue Version huhjelade vun: „[[$1]]“",
        "uploaddisabled": "Huhlade jesperrt",
        "copyuploaddisabled": "Et Huhlaade us URLs es afjeschalldt",
        "uploaddisabledtext": "Et Huhlade es jesperrt.",
        "license-nopreview": "(Kein Vör-Aansich ze hann)",
        "upload_source_url": " (richtije öffentlije URL)",
        "upload_source_file": " (en Datei op Dingem Kompjuter)",
+       "listfiles-delete": "fottschmieße",
        "listfiles-summary": "Heh sin de huhjelade Dateije opjeleß.",
        "listfiles_search_for": "Sök noh däm Name vun dä Datei:",
        "imgfile": "Dattei",
        "watchlist-details": "Do häß {{PLURAL:$1|ein Sigg|$1 Sigge|kein Sigg}} en Dinge Oppaßleß{{PLURAL:$1|, un di Klaafsigg dohzoh|, un de Klaafsigge dohzoh|}}.",
        "wlheader-enotif": "Et <i lang=\"en\">e-mail</i> Schecke es enjeschalt.",
        "wlheader-showupdated": "Wann se Einer jeändert hätt, zickdäm De se et letzte Mol aanjeluurt häs, sin die Sigge <strong>extra markeet</strong>.",
-       "wlnote2": "Heh sin de Änderonge us de läzde {{PLURAL:$1|Schtond|<strong>$1</strong> Schtonde|kein Schtond}} bes zom $2 öm $3 Uhr.",
+       "wlnote": "{{PLURAL:$1|Hee es de letzte Änderung us|Hee sin de letzte <strong>$1</strong> Änderunge us|Mer han kein Äbderunge en}} de letzte {{PLURAL:$2|Stund|<strong>$2</strong> Stunde|<strong>noll</strong> Stunde}} zigg em $3 öm $4 Uhr.",
        "wlshowlast": "Zeich de letzte | $1 | Stunde | $2 | Dage | $3 | aan, dun",
        "watchlist-options": "Eijeschaffte fun de Oppassless",
        "watching": "Drop oppasse…",
        "autosumm-replace": "Dä jannze Enhallt fon dä Sigk ußjetuusch: '$1'",
        "autoredircomment": "Leit öm op „[[$1]]“",
        "autosumm-new": "De Sigg wood neu aanjelaat met däm Aanfang: $1",
+       "autosumm-newblank": "En läddijje Sigg wood aanjelaat",
        "size-bytes": "$1&nbsp;Bytes",
        "size-kilobytes": "$1&nbsp;KB",
        "size-megabytes": "$1&nbsp;MB",
        "version-hook-name": "De Schnettstelle ier Name",
        "version-hook-subscribedby": "Opjeroofe vun",
        "version-version": "(Väsjohn $1)",
+       "version-no-ext-name": "[keine Nahme]",
        "version-license": "MediaWiki sing Lėzänz",
        "version-ext-license": "‎Lėzänz",
        "version-ext-colheader-name": "Zohsazprojramm",
+       "version-skin-colheader-name": "Et Ußsinn",
        "version-ext-colheader-version": "Väsjohn",
        "version-ext-colheader-license": "Lėzänz",
        "version-ext-colheader-description": "Beschrevve",
        "expand_templates_remove_nowiki": "Donn de <nowiki>-Befähle ongerdröcke en dämm, wadd_eruß kütt",
        "expand_templates_generate_xml": "Och dä XML-Parser-Boum zeije",
        "expand_templates_generate_rawhtml": "Donn de Röh HTML Ußjaav aanzeije",
-       "expand_templates_preview": "Vör-Aansich"
+       "expand_templates_preview": "Vör-Aansich",
+       "pagelanguage": "De Schprohch för di Sigg faßlääje",
+       "pagelang-name": "Sigg",
+       "pagelang-language": "De Schprooch",
+       "pagelang-use-default": "Nemm de Schtandatt_Schprohch",
+       "pagelang-select-lang": "Söhg_en Schprooch uß"
 }
index f4ecf82..07a1d75 100644 (file)
        "talkpagelinktext": "gotûbêj",
        "specialpage": "Rûpela taybet",
        "personaltools": "Amûrên kesane",
-       "postcomment": "Beşeke nû",
        "articlepage": "Li rûpela naverokê binêre",
        "talk": "Gotûbêj",
        "views": "Dîtin",
        "externaldberror": "Çewtiyeke bingeha daneyan heye, an jî destûra te ya rojanekirina hesabê xweyê navxweyî nîne.",
        "login": "Têkeve",
        "nav-login-createaccount": "Têkeve / hesabekî nû çêke",
-       "loginprompt": "<b>Eger tu xwe nû tomar bikî, nav û şîfreya xwe hilbijêre.</b> Ji bo tomarkirina te ya di {{SITENAME}} de divê ku ''cookies'' gengaz bin.",
        "userlogin": "Têkeve an hesabekî nû çêke",
        "userloginnocreate": "Têkeve",
        "logout": "Derkeve",
        "gotaccountlink": "Têkeve",
        "userlogin-resetlink": "Te agahiyên hesabê xwe ji bîr kirin?",
        "userlogin-resetpassword-link": "Şîfreyê ji nû ve çêke",
+       "userlogin-helplink2": "Alîkariya têketinê",
        "createacct-emailrequired": "E-name",
        "createaccountmail": "Use a temporary random password and send it to the email address specified below",
        "createaccountreason": "Sedem:",
        "searchprofile-articles-tooltip": "Di $1 da lêbigere",
        "searchprofile-images-tooltip": "Li pelan bigere",
        "search-result-size": "$1 ({{PLURAL:$2|peyvek|$2 peyv}})",
-       "search-result-score": "Lêhatin: $1%",
        "search-redirect": "(beralîkirin $1)",
        "search-section": "(beş $1)",
        "search-suggest": "Gelo mebesta te ev bû: $1",
        "recentchanges-legend": "Vebijarkên guherandinên dawî",
        "recentchanges-summary": "Guhertinên herî dawî yên wîkiyê li ser vê rûpelê bişopîne.",
        "recentchanges-label-minor": "Ev guhertineka biçûk e",
-       "recentchanges-legend-newpage": "$1 - rûpela nû",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (also see [[Special:NewPages|list of new pages]])",
        "rclistfrom": "Guherandinên ji $3 $2 şûnde nîşan bide",
        "rcshowhideminor": "Guherandinên biçûk $1",
+       "rcshowhideminor-show": "nîşan bide",
+       "rcshowhideminor-hide": "veşêre",
        "rcshowhidebots": "Bot'an $1",
-       "rcshowhideliu": "Bikarhênerên qeydkirî $1",
-       "rcshowhideanons": "Bikarhênerên neqeydkirî (IP) $1",
+       "rcshowhidebots-show": "nîşan bide",
+       "rcshowhidebots-hide": "veşêre",
+       "rcshowhideliu": "Bikarhênerên tomarkirî $1",
+       "rcshowhideliu-show": "nîşan bide",
+       "rcshowhideliu-hide": "veşêre",
+       "rcshowhideanons": "Bikarhênerên netomarkirî (IP) $1",
+       "rcshowhideanons-show": "nîşan bide",
+       "rcshowhideanons-hide": "veşêre",
        "rcshowhidepatr": "Guherandinên kontrolkirî $1",
        "rcshowhidemine": "Guherandinên min $1",
+       "rcshowhidemine-show": "nîşan bide",
+       "rcshowhidemine-hide": "veşêre",
        "rclinks": "$1 guherandinên di $2 rojên dawî de nîşan bide<br />$3",
        "diff": "cudahî",
        "hist": "dîrok",
        "fileexists-forbidden": "Medyayek bi vê navî heye; xêra xwe şonda here û vê medyayê bi navekî din barbike.\n[[File:$1|thumb|center|$1]]",
        "uploadwarning": "Hişyariya barkirinê",
        "savefile": "Dosyayê tomar bike",
-       "uploadedimage": "\"[[$1]]\" hate barkirin",
-       "overwroteimage": "versiyonekî nû ya \"[[$1]]\" hate barkirin",
        "uploaddisabled": "Barkirin hatîye qedexekirin",
        "uploaddisabledtext": "Barkirinê data'yan  hatiye qedexekirin.",
        "uploadvirus": "Di vê data'yê da vîrûsek heye! Înformasyon: $1",
        "watchlist-details": "{{PLURAL:$1|Rûpeleka|$1 rûpel}} li ser lîsteya te ya şopandinê, rûpelên gotûbêjê nayên jimartin.",
        "wlheader-enotif": "Agahdariya E-nameyê pêk tê.",
        "wlheader-showupdated": "Ev rûpela hatî guhertin dema te lê meyzand bi '''nivîsa stûr''' tê xuyakirin.",
+       "wlnote": "Niha {{PLURAL:$1|xeyrandinê|'''$1''' xeyrandinên}} dawî yê {{PLURAL:$2|seetê|'''$2''' seetên}} dawî {{PLURAL:$1|tê|tên}} dîtin.",
        "wlshowlast": "Guhertinên berî $1 saetan, $2 rojan, ya $3 nîşan bide",
        "watchlist-options": "Vebijarkên lîsteya şopandinê",
        "watching": "Bişopîne...",
index 5461859..e8320d8 100644 (file)
        "talkpagelinktext": "keskows",
        "specialpage": "Folen arbennek",
        "personaltools": "Toulys personel",
-       "postcomment": "Tregh nowyth",
        "articlepage": "Gweles an folen",
        "talk": "Keskows",
        "views": "Gwelyansow",
        "password-change-forbidden": "Ny yllir chanjya geryow tremena war an wiki-ma.",
        "login": "Omgelmi",
        "nav-login-createaccount": "Omgelmi / Gwruthyl akont nowyth",
-       "loginprompt": "Res yw dhywgh galosegi cookies rag omgelmi orth {{SITENAME}}.",
        "userlogin": "Omgelmi / gwruthyl akont nowyth",
        "userloginnocreate": "Omgelmi",
        "logout": "Digelmi",
        "fileuploadsummary": "Berrskrif:",
        "filesource": "Pennfenten:",
        "savefile": "Gwitha restren",
-       "uploadedimage": "\"[[$1]]\" ughkergys",
        "watchthisupload": "Golya an folen-ma",
        "imgfile": "restren",
        "listfiles_date": "Dedhyans",
        "unwatch": "Diswolya",
        "watchlist-details": "Yma {{PLURAL:$1|$1 folen}} war agas rol wolya, marnas folennow keskows.",
        "wlheader-showupdated": "Yn '''tew''' y tiskwedhir folennow re beu chanjyes a-dhia agas vysytyans diwettha.",
+       "wlnote": "A-woles yma an {{PLURAL:$1|chanj diwettha|'''$1''' chanj diwettha}} y'n {{PLURAL:$2|our|'''$2''' our}} diwettha, a-dhia $3, $4.",
        "wlshowlast": "Diskwedhes an $1 our diwettha, an $2 dydh diwettha, po $3",
        "watchlist-options": "Etholyow an rol wolya",
        "watching": "Ow kolya...",
index a64f675..f3fb4ec 100644 (file)
        "talkpagelinktext": "Талкуулоо",
        "specialpage": "Кызматтык барак",
        "personaltools": "Жеке аспаптар",
-       "postcomment": "Жаңы бөлүм",
        "articlepage": "Макаланы кароо",
        "talk": "Талкуу",
        "views": "Көрсөтүүлөр",
        "externaldberror": "Маалымат базасында ката кетти же сизге сырткы эсебиңизди жаңыртууга уруксат берилген эмес.",
        "login": "Кирүү",
        "nav-login-createaccount": "Кирүү / Катталуу",
-       "loginprompt": "{{SITENAME}} сайтына кириш үчүн сиз «кукилерге» уруксат беришиңиз керек.",
        "userlogin": "Кирүү / Катталуу",
        "userloginnocreate": "Кирүү",
        "logout": "Чыгуу",
        "searchprofile-advanced-tooltip": "Белгиленген аталыш мейкиндиктеринде издөө",
        "search-result-size": "$1 ({{PLURAL:$2|1 сөз|$2 сөздөр}})",
        "search-result-category-size": "{{PLURAL:$1|1 мүчө|$1 мүчөлөр}} ({{PLURAL:$2|1 ички категория|$2 ички категориялар}}, {{PLURAL:$3|1 файл|$3 файлдар}})",
-       "search-result-score": "Релеванттуулук: $1%",
        "search-redirect": "($1 багыттама)",
        "search-section": "($1 бөлүмү)",
        "search-suggest": "Балким, издегениңиз бул: $1",
        "ignorewarnings": "Болгон эскертүүлөрдү этибар албоо",
        "filetype-banned-type": "'''\".$1\"''' {{PLURAL:$4|уруксат болбогон файл тиби|уруксат болбогон файл типтери}}.\nУруксат болгон {{PLURAL:$3|файл тиби|файл типтери}} $2.",
        "savefile": "Файлды сактоо",
-       "uploadedimage": "\"[[$1]]\" жүктөлдү",
        "upload-source": "Баштапкы файл",
        "sourcefilename": "Булактын файл аты:",
        "sourceurl": "Булактын URL-дареги:",
index 14f9fa3..decfd86 100644 (file)
        "searcharticle": "Ire",
        "history": "Historia paginae",
        "history_short": "Historia",
+       "updatedmarker": "mutata postquam vidi",
        "printableversion": "Forma impressibilis",
        "permalink": "Nexus perpetuus",
        "print": "Imprimere",
        "view": "Legere",
+       "view-foreign": "Legere apud {{grammar:accusative|$1}}",
        "edit": "Recensere",
        "create": "Creare",
        "editthispage": "Recensere hanc paginam",
        "talkpagelinktext": "Disputatio",
        "specialpage": "Pagina specialis",
        "personaltools": "Instrumenta personalia",
-       "postcomment": "Nova pars",
        "articlepage": "Videre rem",
        "talk": "Disputatio",
        "views": "Visae",
        "yourdomainname": "Regnum tuum:",
        "login": "Conventum aperire",
        "nav-login-createaccount": "Conventum aperire / conventum creare",
-       "loginprompt": "Cookies potestatem facere debes ut conventum aperire.",
        "userlogin": "Conventum aperire / conventum creare",
        "userloginnocreate": "Conventum aperire",
        "logout": "Conventum concludere",
        "gotaccount": "Habesne iam rationem? '''$1'''.",
        "gotaccountlink": "Conventum aperi",
        "userlogin-resetlink": "Num tesserae tuae oblitus es?",
+       "userlogin-resetpassword-link": "Num tesserae oblivisceris?",
        "createacct-emailrequired": "Inscriptio electronica",
        "createacct-emailoptional": "Inscriptio electronica (non necesse)",
        "createacct-email-ph": "Inscriptionem electronicam tuam inscribe",
        "searchprofile-everything-tooltip": "Omnia perscrutari (etiam paginae disputationis)",
        "searchprofile-advanced-tooltip": "In spatiis nominalibus accommotis quaerere",
        "search-result-size": "$1 ({{PLURAL:$2|1 verbum|$2 verba}})",
-       "search-result-score": "Gravitas: $1%",
        "search-redirect": "(redirectio $1)",
        "search-section": "(pars $1)",
        "search-suggest": "Nonne dicere voluisti: $1",
        "editinguser": "Modificare potestates usoris '''[[User:$1|$1]]''' $2",
        "userrights-editusergroup": "Greges usorum recensere",
        "saveusergroups": "Greges usorum servare",
-       "userrights-groupsmember": "In grege aut in gregibus:",
+       "userrights-groupsmember": "{{PLURAL:$1|In grege|In gregibus}}:",
        "userrights-reason": "Causa:",
        "userrights-changeable-col": "Greges quos tibi oportet mutare",
        "userrights-unchangeable-col": "Greges quos tibi non oportet mutare",
        "rcnotefrom": "Subter sunt '''$1''' nuperrime mutata in proxima '''$2''' die.",
        "rclistfrom": "Monstrare mutata nova incipiens ab $3 $2",
        "rcshowhideminor": "$1 recensiones minores",
+       "rcshowhideminor-show": "Monstrare",
+       "rcshowhideminor-hide": "Celare",
        "rcshowhidebots": "$1 automata",
+       "rcshowhidebots-show": "Monstrare",
+       "rcshowhidebots-hide": "Celare",
        "rcshowhideliu": "$1 usores notos",
+       "rcshowhideliu-show": "Monstrare",
+       "rcshowhideliu-hide": "Celare",
        "rcshowhideanons": "$1 usores ignotos",
+       "rcshowhideanons-show": "Monstrare",
+       "rcshowhideanons-hide": "Celare",
        "rcshowhidepatr": "$1 recensiones circumitae",
+       "rcshowhidepatr-show": "Monstrare",
+       "rcshowhidepatr-hide": "Celare",
        "rcshowhidemine": "$1 conlationes meas",
+       "rcshowhidemine-show": "Monstrare",
+       "rcshowhidemine-hide": "Celare",
        "rclinks": "Monstrare $1 nuperrime mutata in $2 diebus proximis.<br />$3",
        "diff": "diss",
        "hist": "hist",
        "large-file": "Suasum est ut fasciculi $1 magnitudine non excedant; magnitudo huius fasciculi est $2.",
        "uploadwarning": "Monitus imponendi",
        "savefile": "Servare fasciculum",
-       "uploadedimage": "imposuit \"[[$1]]\"",
        "uploaddisabled": "Fasciculos imponere prohibitum est",
        "uploaddisabledtext": "Fasciculos imponere prohibitum est.",
        "uploadvirus": "Fasciculi huic est virus! Singula: $1",
        "unusedtemplateswlh": "nexus alii",
        "randompage": "Pagina fortuita",
        "randompage-nopages": "Non est ulla pagina {{PLURAL:$2|hoc in spatio nominale|in his spatiis nominalibus}}: $1.",
-       "randomincategory-selectcategory-submit": "Pergere",
        "randomredirect": "Redirectio fortuita",
        "randomredirect-nopages": "Non est ulla redirectio in spatio nominali \"$1\".",
        "statistics": "Census",
        "notanarticle": "Res non est",
        "notvisiblerev": "Emendatio deleta est",
        "watchlist-details": "{{PLURAL:$1|$1 pagina|$1 paginae}} in indice paginarum custoditarum tuarum, sine paginis disputationis.",
+       "wlnote": "Subter {{PLURAL:$1|est mutatio proxima|sunt '''$1''' mutationes proximae}} in {{PLURAL:$2|proxima hora|proximis '''$2''' horis}} ex $4, $3.",
        "wlshowlast": "Monstrare proximas $1 horas $2 dies $3",
        "watchlist-options": "Indicis paginarum custoditarum praeferentiae",
        "watching": "Custodiens...",
        "djvu_page_error": "Pagina DjVu extra latitudinem",
        "import": "Paginas importare",
        "importinterwiki": "Adportatio transvici",
-       "import-interwiki-source": "Vici et pagina fons:",
        "import-interwiki-submit": "Importare",
        "import-interwiki-namespace": "Spatium nominale destinatum:",
        "import-upload-filename": "Nomen fasciculi:",
        "tooltip-pt-userpage": "Pagina usoris tua",
        "tooltip-pt-mytalk": "Pagina disputationis tua",
        "tooltip-pt-preferences": "Praeferentiae tuae",
-       "tooltip-pt-watchlist": "Paginae quae custodis ut eorum mutationes facilius vides",
+       "tooltip-pt-watchlist": "Paginae quas custodis ut earum mutationes facilius videas",
        "tooltip-pt-mycontris": "Index conlationum tuarum",
        "tooltip-pt-login": "Te conventum aperire hortamur, non autem requisitum",
        "tooltip-pt-logout": "Conventum concludere",
index c1e5ee6..db68ff1 100644 (file)
        "talkpagelinktext": "Messaje",
        "specialpage": "Hoja Especial",
        "personaltools": "Aparates personales",
-       "postcomment": "Capítůlo muevo",
        "articlepage": "Ver el artícůlo de contenido",
        "talk": "Diskusyón",
        "views": "Vistas",
        "password-change-forbidden": "No se puede kambiar contrasenyas en este viki.",
        "login": "Entrar",
        "nav-login-createaccount": "Entrar / criar un cuento",
-       "loginprompt": "Kale tener \"cookies\" aktivadas enel navegador para enrejistrarse en {{SITENAME}}",
        "userlogin": "Entrar / Criar cuento",
        "logout": "Salir",
        "userlogout": "Salir",
        "filesource": "Fuente:",
        "filename-tooshort": "El nombre del archivo es muy kurto.",
        "savefile": "Guardar archivo",
-       "uploadedimage": "suvió «[[$1]]»",
        "backend-fail-notexists": "El archivo $1 no egziste.",
        "backend-fail-alreadyexists": "El archivo \"$1\" ya egziste.",
        "img-auth-nofile": "El archivo \"$1\" no egziste.",
index db9af3d..c09a4d1 100644 (file)
@@ -32,6 +32,7 @@
        "tog-watchdefault": "Säiten a Fichieren déi ech änneren op meng Iwwerwaachungslëscht derbäisetzen",
        "tog-watchmoves": "Säiten a Fichieren déi ech réckelen automatesch op meng Iwwerwaachungslëscht derbäisetzen",
        "tog-watchdeletion": "Säiten a Fichieren déi ech läschen op meng Iwwerwaachungslëscht derbäisetzen",
+       "tog-watchrollback": "Säiten déi ech zréckgesat hunn op meng Iwwerwaachungslëscht derbäisetzen",
        "tog-minordefault": "All Ännerungen automatesch als 'Kleng Ännerungen' markéieren.",
        "tog-previewontop": "Déi ''nach-net gespäichert Versioun'' iwwer der Ännerungsfënster weisen",
        "tog-previewonfirst": "Beim éischten Änneren déi  ''nach net gespäichert Versioun'' weisen.",
        "talkpagelinktext": "Diskussioun",
        "specialpage": "Spezialsäit",
        "personaltools": "Perséinlech Tools",
-       "postcomment": "Neien Abschnitt",
        "articlepage": "Säit",
        "talk": "Diskussioun",
        "views": "Affichagen",
        "otherlanguages": "An anere Sproochen",
        "redirectedfrom": "(Virugeleet vu(n) $1)",
        "redirectpagesub": "Viruleedungssäit",
+       "redirectto": "Viruleeden op:",
        "lastmodifiedat": "Dës Säit gouf de(n) $1 ëm $2 Auer fir d'lescht geännert.",
        "viewcount": "Dës Säit gouf bis elo {{PLURAL:$1|emol|$1-mol}} ofgefrot.",
        "protectedpage": "Gespaart Säit",
        "hidetoc": "verstoppen",
        "collapsible-collapse": "Zesummeklappen",
        "collapsible-expand": "Opklappen",
+       "confirmable-confirm": "Sidd {{GENDER:$1|Dir}} sécher?",
+       "confirmable-yes": "Jo",
+       "confirmable-no": "Neen",
        "thisisdeleted": "$1 kucken oder zrécksetzen?",
        "viewdeleted": "Weis $1?",
        "restorelink": "$1 geläscht {{PLURAL:$1|Versioun|Versiounen}}",
        "invalidtitle-knownnamespace": "Net valabelen Titel mam Nummraum \"$2\" a mam Text \"$3\"",
        "invalidtitle-unknownnamespace": "Net valabelen Titel mat der onbekannter Nummraum-Zuel $1 a mam Text \"$2\"",
        "exception-nologin": "Net ageloggt",
-       "exception-nologin-text": "[[Special:Userlogin|Loggt Iech w.e.g. a]] fir op dës Säit oder dës Aktioun zougräifen ze kënnen.",
+       "exception-nologin-text": "Loggt Iech w.e.g. a fir op dës Säit oder dës Aktioun zougräifen ze kënnen.",
        "exception-nologin-text-manual": "Dir musst Iech $1 fir dës Säit kucken ze kënne respektiv fir dës Aktioun ze maachen.",
        "virus-badscanner": "Schlecht Konfiguratioun: onbekannte Virescanner: ''$1''",
        "virus-scanfailed": "De Scan huet net funktionéiert (Code $1)",
        "externaldberror": "Entweder ass e Feeler bei der externer Authentifizéierung geschitt, oder Dir däerft Ären externe Benotzerkont net aktualiséieren.",
        "login": "Aloggen",
        "nav-login-createaccount": "Aloggen / Benotzerkont uleeën",
-       "loginprompt": "Fir sech op {{SITENAME}} aloggen ze kënnen, mussen d'Cookien aktivéiert sinn.",
        "userlogin": "Aloggen / Benotzerkont uleeën",
        "userloginnocreate": "Umellen",
        "logout": "Ofmellen",
        "userlogin-resetlink": "Hutt Dir d'Detailer vun Ärem Login vergiess?",
        "userlogin-resetpassword-link": "Hutt Dir Äert Passwuert vergiess?",
        "userlogin-helplink2": "Hëllef beim Aloggen",
-       "userlogin-loggedin": "Dir sidd schonn als {{GENDER:$1|$1}} ageloggt.\nBenotzt de Formulaire hei drënner fir Iech als een anere Benotzer anzeloggen.",
-       "userlogin-createanother": "Maacht een anere Benotzerkont op",
        "createacct-emailrequired": "E-Mail-Adress",
        "createacct-emailoptional": "E-Mailadress (fakultativ)",
        "createacct-email-ph": "Gitt Är E-Mail-Adress an",
        "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-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.",
        "createacct-another-realname-tip": "De richtegen Numm ass fakultativ.\n\nWann Dir en ugitt, gëtt e benotzt fir d'Benotzerattributiounen fir Är Aarbecht zouzeuerdnen.",
        "preview": "Kucken ouni ofzespäicheren",
        "showpreview": "Kucken ouni ofzespäicheren",
        "showdiff": "Ännerunge weisen",
-       "anoneditwarning": "'''Opgepasst:''' Dir sidd net ageloggt. Dowéinst gëtt amplaz vun engem Benotzernumm Är IP Adress am Historique vun dëser Säit gespäichert.",
+       "blankarticle": "<strong>Opgepasst:</strong> D'Säit déi Dir uleet ass eidel.\nWann Dir nach eng Kéier op \"{{int:savearticle}}\" klickt, da gëtt d'Säit ugeluecht.",
+       "anoneditwarning": "<strong>Opgepasst:</strong> Dir sidd net ageloggt. Dowéinst gëtt amplaz vun engem Benotzernumm Är IP Adress ëffentlech gewise wann Dir Ännerunge maacht. Wann Dir <strong>[$1 Iech aloggt]</strong> oder <strong>[$2 e Bnotzerkont opmaachen]</strong>, Är Ännerunge ginn dann Ärem Benotzerkont zougedeelt, genee wéi aner Avantagen.",
        "anonpreviewwarning": "''Dir sidd net ageloggt. Wann Dir ofspäichert gëtt Är IP-Adress an der Lëscht vun de Versioune vun dëser Säit enregistréiert.''",
        "missingsummary": "'''Erënnerung:''' Dir hutt kee Resumé aginn.\nWann Dir nacheemol op \"{{int:savearticle}}\" klickt, gëtt Är Ännerung ouni Resumé ofgespäichert.",
        "missingcommenttext": "Gitt w.e.g. eng Bemierkung an.",
        "parser-template-loop-warning": "Endlos Schleef an der Schabloun: [[$1]] entdeckt",
        "parser-template-recursion-depth-warning": "D'Limit vun der Zuel vun de Verschachtelunge vu Schabloune gouf iwwerschratt ($1)",
        "language-converter-depth-warning": "D'Limite vun der déift vun der Sproochëmwandlung gouf iwwerschratt ($1)",
-       "node-count-exceeded-category-desc": "Eng Kategorie fir Säiten an deenen d'Zuel vun de Kniet (Node-count) ze grouss ass.",
+       "node-count-exceeded-category-desc": "D'Säit huet méi wéi déi maximal Zuel vu Kniet (Node-count).",
        "parser-unstrip-loop-warning": "Endlos Schleef entdeckt",
        "converter-manual-rule-error": "An der Regel iwwer déi manuell Ëmwandlung vun der Sprooch gouf e Feeler fonnt",
        "undo-success": "D'Ännerung gëtt réckgängeg gemaach. Iwwerpréift w.e.g. de Verglach ënnendrënner fir nozekuckeen ob et sou richteg ass, duerno späichert w.e.g d'Ännerungen of, fir dës Aktioun ofzeschléissen.",
        "rev-deleted-event": "(Aktioun aus dem Logbuch erausgeholl)",
        "rev-deleted-user-contribs": "[Benotzernumm oder IP-Adress ewechgeholl - Ännerung an der Lescht vun de Kontributioune verstoppt]",
        "rev-deleted-text-permission": "Dës Versioun vun der Säit gouf '''geläscht'''.\nDir fannt eventuell méi Informatiounen an der [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Läsch-Logbuch].",
+       "rev-suppressed-text-permission": "Dës Versioun vun der Säit gouf <strong>geläscht</strong>..\nDetailer fannt Dir am [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Läsch-Logbuch].",
        "rev-deleted-text-unhide": "Dës Versioun vun der Säit gouf '''geläscht'''.\nDetailer kënnen am [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Läsch-Logbuch] fonnt ginn.\nDir kënnt [$1 dës Versioun nach ëmmer kucke] wann Dir weiderfuere wëllt.",
        "rev-suppressed-text-unhide": "Dës Versioun vun der Säit gouf '''geläscht'''.\nDetailer kënnen am  [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Läschlogbuch] sinn.\nDir kënnt [$1 dës Versioun gesi] wann Dir weiderfuere wëllt.",
        "rev-deleted-text-view": "Dës Versioun vun der Säit gouf '''geläscht'''.\nDir kënnt se gesinn; Dir fannt Detailer am  [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Läsch-Logbuch].",
        "revdelete-selected-text": "{{PLURAL:$1|Erausgesicht Versioun|Erausgesicht Versioune}} vu(n) [[:$2]]:",
        "revdelete-selected-file": "{{PLURAL:$1|Erausgesicht Versioun|Erausgesicht Versioune}} vum Fichier vu(n) [[:$2]]:",
        "logdelete-selected": "Ausgewielten {{PLURAL:$1|Evenement|Evenementer}} aus dem Logbuch:",
-       "revdelete-text-others": "Aner Administrateuren op {{SITENAME}} kënnen nach ëmmer de verstoppten Inhalt gesinn an en iwwer deeselwechten Interface nees restauréieren, ausser wann zousätzlech Limitatiounen agestallt sinn.",
+       "revdelete-text-text": "Geläscht Versioune bleiwen am Historique vun der Säit, awer Deeler vun hirem Inhalt sinn net ëffentlech zougänglech.",
+       "revdelete-text-file": "Geläscht Versioune vu Fichiere bleiwen am Historique vum Fichier awer Deeler vun hirem Inhalt sinn net ëffentlech zougänglech.",
+       "revdelete-text-others": "Aner Administrateure kënnen nach ëmmer de verstoppten Inhalt gesinn an en nees restauréieren, ausser wann zousätzlech Limitatiounen agestallt sinn.",
        "revdelete-confirm": "Confirméiert w.e.g. datt Dir dat maache wëllt, datt Dir d'Konsequenze verstitt an datt Dir dëst an Aklang mat de [[{{MediaWiki:Policy-url}}|Richtlinne]] maacht.",
        "revdelete-suppress-text": "Ënnerdréckung sollt '''nëmmen''' an dëse Fäll benotzt ginn:\n* Informatiounen déi beleidege kéinten\n* Net ubruechte perséinlechen Informatiounen\n*: ''Adressen, Telefonsnummeren, Sozialversécherungsnummeren asw.''",
        "revdelete-legend": "Limitatioune fir d'Sichtbarkeet festleeën",
        "mergehistory-go": "Weis déi Versiounen, déi zesummegeluecht kënne ginn",
        "mergehistory-submit": "Versioune verschmelzen",
        "mergehistory-empty": "Et kënne keng Versioune zesummegeluecht ginn.",
-       "mergehistory-success": "{{PLURAL:$3|1 Versioun gouf|$3 Versioune goufe}} vun [[:$1]] op [[:$2]] zesummegeluecht.",
+       "mergehistory-success": "{{PLURAL:$3|1 Versioun gouf|$3 Versioune goufe}} vu(n) [[:$1]] op [[:$2]] zesummegeluecht.",
        "mergehistory-fail": "Versiounszesummeleeung war net méiglech, kuckt w.e.g. d'Säiten an d'Zäit-Parameter no.",
        "mergehistory-no-source": "Originalsäit \"$1\" gëtt et net.",
        "mergehistory-no-destination": "Zilsäit \"$1\" gëtt et net.",
        "searchprofile-advanced-tooltip": "Sich an den Nummraim déi an de perséinlichen Astellungen festgeluecht sinn",
        "search-result-size": "$1 ({{PLURAL:$2|1 Wuert|$2 Wierder}})",
        "search-result-category-size": "{{PLURAL:$1|1 Säit|$1 Säiten}} ({{PLURAL:$2|1 Ënnerkategorie|$2 Ënnerkategorien}}, {{PLURAL:$3|1 Fichier|$3 Fichieren}})",
-       "search-result-score": "Relevanz: $1 %",
        "search-redirect": "(Viruleedung $1)",
        "search-section": "(Abschnitt $1)",
        "search-file-match": "(Inhalt vum Fichier passt)",
        "searchrelated": "a Verbindng",
        "searchall": "all",
        "showingresults": "Hei gesitt der  {{PLURAL:$1| '''1''' Resultat|'''$1''' Resultater}}, ugefaange mat #'''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|Resultat '''$1''' vu(n) '''$3'''|Resultater '''$1 - $2''' vu(n) '''$3'''}} fir '''$4'''",
        "search-nonefound": "Fir Är Ufro gouf näischt fonnt.",
        "powersearch-legend": "Erweidert Sich",
        "powersearch-ns": "Sichen an den Nummraim:",
        "powersearch-togglelabel": "Markéieren:",
        "powersearch-toggleall": "All",
        "powersearch-togglenone": "Keen",
+       "powersearch-remember": "Auswiel fir zukünfteg Sichufroe verhalen",
        "search-external": "Extern sichen",
        "searchdisabled": "D'Sichfunktioun op {{SITENAME}} ass ausgeschalt. Dir kënnt iwwerdeems mat Hëllef vu Google sichen. Bedenkt awer, datt deenen hire  Sichindex fir {{SITENAME}} eventuell net dem aktuellste Stand entsprecht.",
        "search-error": "Beim Sichen ass e Feeler geschitt: $1",
        "preferences": "Astellungen",
        "mypreferences": "Astellungen",
        "prefs-edits": "Zuel vun den Ännerungen:",
-       "prefsnologintext2": "Dir musst Iech $1 fir Är Benotzerastellunge festzeleeën",
+       "prefsnologintext2": "Loggt Iech a fir Är Benotzerastellungen z'änneren.",
        "prefs-skin": "Skin",
        "skin-preview": "Kucken",
        "datedefault": "Egal (Standard)",
        "right-deletedtext": "Geläschten Text an d'Ännerungen tëscht de geläschte Versioune weisen",
        "right-browsearchive": "Geläscht Säite sichen",
        "right-undelete": "Eng Säit restauréieren",
-       "right-suppressrevision": "Virun den Administrateure verstoppte Versiounen nokucken a restauréieren",
+       "right-suppressrevision": "Spezifesch Versioune vun alle Benotzer weisen, verstoppen a restauréieren",
+       "right-viewsuppressed": "Verstoppt Versioune weisen déi fir all Benotzer verstoppt sinn",
        "right-suppressionlog": "Privat Lëschte kucken",
        "right-block": "Aner Benotzer fir Ännerunge spären",
        "right-blockemail": "E Benotzer späre sou datt hie keng Maile verschécke kann",
        "recentchanges-legend-heading": "'''Legend:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (kuckt och [[Special:NewPages|Lëscht vun den neie Säiten]])",
        "recentchanges-legend-plusminus": "''(±123)''",
-       "rcnotefrom": "Ugewise ginn d'Ännerunge vum <strong>$2</strong> un (maximal <strong>$1</strong> Ännerunge gi gewisen).",
+       "rcnotefrom": "Hei drënner {{PLURAL:$5|gëtt d'Ännerung|ginn d'Ännerungen}} zanter <strong>$3, $4</strong> (maximal <strong>$1</strong> Ännerunge gi gewisen).",
        "rclistfrom": "Nei Ännerunge vu(n) $3 $2 u weisen",
        "rcshowhideminor": "Kleng Ännerunge $1",
        "rcshowhideminor-show": "Weisen",
        "uploadwarning": "Opgepasst",
        "uploadwarning-text": "Ännert d'Beschreiwung hei ënnedrënner w.e.g. a versicht et nach eng Kéier.",
        "savefile": "Fichier späicheren",
-       "uploadedimage": "huet \"[[$1]]\" eropgelueden",
-       "overwroteimage": "huet eng nei Versioun vun \"[[$1]]\" eropgelueden",
        "uploaddisabled": "Pardon, d'Eropluede vu Fichieren ass ausgeschalt.",
        "copyuploaddisabled": "D'Eroplueden iwwer URL ass desaktivéiert.",
        "uploaddisabledtext": "D'Eropluede vu Fichieren ass ausgeschalt.",
        "uploadstash-errclear": "D'Läsche vun de Fichieren huet net funktionéiert.",
        "uploadstash-refresh": "Lëscht vun de Fichieren aktualiséieren",
        "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-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.",
        "img-auth-badtitle": "Aus \"$1\" ka kee valabelen Titel gemaach ginn.",
        "img-auth-nologinnWL": "Dir sidd net ageloggt a(n) \"$1\" ass net op der Wäisser Lëscht.",
        "license": "Lizenz",
        "license-header": "Lizenz",
        "nolicense": "Keng Lizenz ausgewielt",
+       "licenses-edit": "Lizenzoptiounen änneren",
        "license-nopreview": "(Kucken ouni ofzespäichere geet net)",
-       "upload_source_url": " (gëlteg, ëffentlech zougänglech URL)",
-       "upload_source_file": " (e Fichier op Ärem Computer)",
+       "upload_source_url": "(Äre Fichier deen Dir op enger gëlteger, ëffentlech zougänglecher URL erausgesicht hutt)",
+       "upload_source_file": "(den erausgesichte Fichier vun Ärem Computer)",
+       "listfiles-delete": "läschen",
        "listfiles-summary": "Op dëser Spezialsäit stinn all déi eropgeluede Fichieren.",
        "listfiles_search_for": "Sicht nom Fichier:",
        "imgfile": "Fichier",
        "unwatchedpages": "Net iwwerwaacht Säiten",
        "listredirects": "Lëscht vun de Viruleedungen",
        "listduplicatedfiles": "Lëscht vu Fichiere mat Doublonen",
+       "listduplicatedfiles-summary": "Dëst ass eng Lëscht vu Fichiere wou déi lescht Versioun vum Fichier en Doublon vun der leschter Versioun vun engem anere Fichier ass. Et ginn nëmme lokal Fichiere consideréiert.",
        "listduplicatedfiles-entry": "[[:File:$1|$1]] huet [[$3|{{PLURAL:$2|een Doublon|$2 Doublonen}}]].",
        "unusedtemplates": "Net benotzt Schablounen",
        "unusedtemplatestext": "Op dëser Säit stinn all Säiten aus dem {{ns:template}} Nummraum, déi a kenger anerer Säit benotzt ginn. Vergiesst net nozekucken, ob et keng aner Linken op dës Schabloune gëtt, ier Dir eng Schabloun läscht.",
        "randomincategory": "Zoufälleg Säit an der Kategorie",
        "randomincategory-invalidcategory": "\"$1\" ass kee valabelen Numm fir eng Kategorie.",
        "randomincategory-nopages": "Et gëtt keng Säiten an der [[:Category:$1]].",
-       "randomincategory-selectcategory": "Eng zoufälleg Säit aus der Kategorie: $1 $2 opruffen",
-       "randomincategory-selectcategory-submit": "Lass",
+       "randomincategory-category": "Kategorie:",
+       "randomincategory-legend": "Zoufälleg Säit an der Kategorie",
        "randomredirect": "Zoufälleg Viruleedung",
        "randomredirect-nopages": "Am Nummraum $1 gëtt et keng Viruleedungen.",
        "statistics": "Statistik",
        "wantedfiles": "Gewënscht Fichieren",
        "wantedfiletext-cat": "Dës Fichiere gi benotzt awer et gëtt se net. Fichiere aus frieme Repositorie kënnen hei gewise ginn och wann et se gëtt. All sou falsch Positiver ginn <del>duerchgestrach</del>. Zousätzlech gi Säiten an deene Fichieren dra sinn déi et net gëtt op [[:$1]] gewisen.",
        "wantedfiletext-nocat": "Dës Fichiere gi benotzt existéieren awer net. Fichieren aus frieme Repertoiren kënnen trotzdeem opgelëscht ginn. All dës positiv Fichiere ginn <del>duergestrach</del>.",
+       "wantedfiletext-nocat-noforeign": "Dës Fichiere gi benotzt awer et gëtt se net.",
        "wantedtemplates": "Gewënscht Schablounen",
        "mostlinked": "Dacks verlinkt Säiten",
        "mostlinkedcategories": "Dacks benotzt Kategorien",
        "trackingcategories-msg": "Tracking-Kategorie",
        "trackingcategories-name": "Numm vum Message",
        "noindex-category-desc": "D'Säit gëtt net vu Botten indexéiert, well dat magescht Wuert <code><nowiki>__NOINDEX__</nowiki></code> dran ass a well se an engem Nummraum ass, an deem déi Markéierung erlaabt ass.",
-       "hidden-category-category-desc": "Dëst ass eng Kategorie an där <code><nowiki>__HIDDENCAT__</nowiki></code> drasteet, dat verhënnert datt se standardméisseg an der këscht mat de Kategorielinken op der Säit gewise gëtt.",
+       "index-category-desc": "D'Säit huet <code><nowiki>__INDEX__</nowiki></code> an ass an engem Nummraum, wou déi Markéierung erlaabt ass an dofir gëtt d'Säit vu Sichroboter indexéiert wou dat normalerweis net de Fall wier.",
+       "post-expand-template-inclusion-category-desc": "D'Säit ass méi grouss wéi <code>$wgMaxArticleSize</code> nom expandéiere vun alle Schablounen, dofir goufen e puer Schablounen net expandéiert.",
+       "broken-file-category-desc": "D'Säit huet e futtise Link op e Fichier (e Link op en agebonnene Fichier wann et de Fichier net gëtt).",
+       "hidden-category-category-desc": "D'Kategorie huet <code><nowiki>__HIDDENCAT__</nowiki></code> an hirer Säit drastoen, dat verhënnert datt se standardméisseg an der Këscht mat de Kategorielinken op der Säit gewise gëtt.",
        "trackingcategories-nodesc": "Keng Beschreiwung disponibel.",
        "trackingcategories-disabled": "Kategorie ass desaktivéiert",
        "mailnologin": "Keng E-Mailadress",
        "mywatchlist": "Iwwerwaachungslëscht",
        "watchlistfor2": "Vum $1 $2",
        "nowatchlist": "Är Iwwerwaachungslëscht ass eidel.",
-       "watchlistanontext": "Dir musst $1 fir Säiten op ärer Iwwerwaachungslëscht ze gesinn oder z'änneren.",
+       "watchlistanontext": "Loggt Iech a fir Elementer op Ärer Iwwerwaachungslëscht ze gesinn oder z'änneren.",
        "watchnologin": "Net ageloggt",
        "addwatch": "Op d'Iwwerwaachungslëscht derbäisetzen",
        "addedwatchtext": "D'Säit \"[[:$1]]\" gouf op är [[Special:Watchlist|Iwwerwaachungslëscht]] gesat.\nAll weider Ännerungen op dëser Säit an der associéierter Diskussiounssäit ginn hei opgelëscht.",
        "watchlist-details": "{{PLURAL:$1|1 Säit|$1 Säiten}} sinn op ärer Iwwerwaachungsklëscht, d'Diskussiounssäiten net matgezielt.",
        "wlheader-enotif": "E-Mail-Notifikatioun ass ageschalt.",
        "wlheader-showupdated": "Säiten déi zanter Ärer leschter Visite geännert goufen, si '''fett''' geschriwwen",
-       "wlnote2": "Hei sinn déi lescht Ännerunge aus {{PLURAL:$1|der leschter Stonn|de leschte(n) <strong>$1</strong> Stonnen}}, Stand: $2 ëm $3 Auer.“",
+       "wlnote": "Hei {{PLURAL:$1|ass déi lescht Ännerung|sinn déi lescht <strong>$1</strong> Ännerunge}} vun {{PLURAL:$2|der leschter Stonn|de leschte(n) <strong>$2</strong> Stonnen}}, Stand: $3 ëm $4 Auer.",
        "wlshowlast": "D'Ännerunge vun de leschte(n) $1 Stonnen, $2 Deeg oder $3 (an de leschten 30 Deeg) weisen.",
        "watchlist-options": "Optioune vun der Iwwerwaachungslëscht",
        "watching": "Iwwerwaachen …",
        "exbeforeblank": "Den Inhalt virum Läsche war: '$1'",
        "delete-confirm": "Läsche vu(n) \"$1\"",
        "delete-legend": "Läschen",
-       "historywarning": "'''Opgepasst:''' Déi Säit déi Dir läsche wëllt huet en Historique mat ongeféier $1 {{PLURAL:$1|Versioun|Versiounen}}:",
+       "historywarning": "<strong>Opgepasst:</strong> D'Säit déi Dir läsche wëllt huet en Historique mat $1 {{PLURAL:$1|Versioun|Versiounen}}:",
        "confirmdeletetext": "Dir sidd am Gaang, eng Säit mat hirem kompletten Historique vollstänneg aus der Datebank ze läschen.\nW.e.g. confirméiert, datt Dir dëst wierklech wëllt, datt Dir d'Konsequenze verstitt, an datt dat Ganzt am Aklang mat de [[{{MediaWiki:Policy-url}}|Richtlinne]] geschitt.",
        "actioncomplete": "Aktioun ofgeschloss",
        "actionfailed": "Aktioun huet net funktionéiert",
        "delete-edit-reasonlist": "Läschgrënn änneren",
        "delete-toobig": "Dës Säit huet e laangen Historique, méi wéi $1 {{PLURAL:$1|Versioun|Versiounen}}.\nD'Läsche vu sou Säite gouf limitéiert fir ongewollte Stéierungen op {{SITENAME}} ze verhënneren.",
        "delete-warning-toobig": "Dës Säit huet eng laang Versiounsgeschicht, méi wéi $1 {{PLURAL:$1|Versioun|Versiounen}}.\nD'Läschen dovu kann zu Stéierungen am Fonctionnement vun {{SITENAME}} féieren;\ndës Aktioun soll mat Virsiicht gemaach ginn.",
+       "deleteprotected": "Dir däerft dëst Säit net läsche well se gespaart ass.",
        "deleting-backlinks-warning": "'''Opgepasst:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Aner Säite]] linken op déi Säit déi Dir am Gaang sidd ze läschen oder déi Säit Déi Dir am Gaang sidd ze läschen ass an aner Säiten agebonn.",
        "rollback": "Ännerungen zrécksetzen",
        "rollback_short": "Zrécksetzen",
        "autoblockid": "Automatesch Spär #$1",
        "block": "Benotzer spären",
        "unblock": "D'Spär vum Benotzer ophiewen",
-       "blockip": "Benotzer spären",
+       "blockip": "{{GENDER:$1|Benotzer}} spären",
        "blockip-legend": "Benotzer spären",
        "blockiptext": "Benotzt dëse Formulaire fir eng spezifesch IP-Adress oder e Benotzernumm ze spären. Dëst soll nëmmen am Fall vu Vandalismus gemaach ginn, en accordance mat den [[{{MediaWiki:Policy-url}}|interne Richlinen]]. Gitt e spezifesche Grond un (zum Beispill Säite wou Vandalismus virgefall ass).",
        "ipaddressorusername": "IP-Adress oder Benotzernumm:",
        "ipb-unblock-addr": "Spär vum $1 ophiewen",
        "ipb-unblock": "Spär vun enger IP-Adress oder engem Benotzer ophiewen",
        "ipb-blocklist": "Kuckt aktuell Spären",
-       "ipb-blocklist-contribs": "Kontributioune fir $1",
+       "ipb-blocklist-contribs": "Kontributioune vum {{GENDER:$1|$1}}",
        "unblockip": "Spär vum Benotzer ophiewen",
        "unblockiptext": "Benotzt dëse Formulaire fir enger IP-Adress oder engem Benotzer seng Spär opzehiewen.",
        "ipusubmit": "Des Spär ophiewen",
        "unblocked": "D'Spär fir de [[User:$1|Benotzer $1]] gouf opgehuewen",
        "unblocked-range": "D'Spär vum $1 gouf opgehuewen",
        "unblocked-id": "D'Spär $1 gouf opgehuewen",
+       "unblocked-ip": "D'Spär vum [[Special:Contributions/$1|$1]] gouf opgehuewen.",
        "blocklist": "Gespaart Benotzer",
        "ipblocklist": "Gespaart Benotzer",
        "ipblocklist-legend": "No engem gespaarte Benotzer sichen",
        "unlockdbsuccesssub": "D'Spär vun der Datebank gouf opgehuewen",
        "lockdbsuccesstext": "D'{{SITENAME}}-Datebank gouf gespaart. <br />\nDenkt drun [[Special:UnlockDB|d'Spär erëm ewechzehuele]] soubaal d'Maintenance-Aarbechte fäerdeg sinn.",
        "unlockdbsuccesstext": "D'Spär vun der Datebank ass opgehuewen.",
-       "lockfilenotwritable": "De Fichier mat de Späre vun der Datebank kann net geännert ginn.\nFir d'Datebank ze spären oder fir d'Spär opzehiewen muss dëse Fichier vum Webserver geännert kënne ginn.",
+       "lockfilenotwritable": "De Fichier mat de Späre vun der Datebank kann net geännert ginn.\nFir d'Datebank ze spären oder fir d'Spär opzehiewe muss dëse Fichier vum Webserver geännert kënne ginn.",
        "databasenotlocked": "D'Datebank ass net gespaart.",
        "lockedbyandtime": "(vum $1 de(n) $2 ëm $3 Auer)",
        "move-page": "Réckel $1",
        "movepagetalktext": "D'associéiert Diskussiounssäit, am Fall wou  eng do ass, gëtt automatesch matgeréckelt, '''ausser:'''\n*D'Säit gëtt an een aneren Nummraum geréckelt.\n*Et gëtt schonn eng Diskussiounssäit mat dësem Numm, oder\n*Dir klickt d'Këschtchen ënnendrënner net un.\n\nAn deene Fäll musst Dir d'Diskussiounssäit manuell réckelen oder fusionéieren.",
        "movearticle": "Säit réckelen:",
        "moveuserpage-warning": "'''Opgepasst:''' Dir sidd am gaang eng Benotzersäit ze réckelen. Denkt w.e.g. dorunn datt just d'Säit geréckelt gëtt an datt de Benotzer ''net'' ëmbenannt gëtt.",
+       "movecategorypage-warning": "<strong>Opgepasst:</strong> Dir sidd am Gaang eng Kategorie-Säit ze réckelen. Denkt drun datt nëmmen déi Säit geréckelt gëtt an all Säiten an der aler Kategorie ginn <em>net</em> an déi nei ëmkategoriséiert.",
        "movenologintext": "Dir musst e registréierte Benotzer an [[Special:UserLogin|ageloggt]] sinn, fir eng Säit ze réckelen.",
        "movenotallowed": "Dir hutt net déi néideg Rechter fir Säiten ze réckelen.",
        "movenotallowedfile": "Dir hutt net d'Recht fir Fichieren ze réckelen.",
        "thumbnail_image-missing": "De Fichier schengt ze feelen: $1",
        "import": "Säiten importéieren",
        "importinterwiki": "Transwiki-Import",
-       "import-interwiki-text": "Sicht eng Wiki an e Säitentitel eraus fir z'importéieren.\nD'Versiounsdatumen an d'Benotzernimm bleiwen derbäi erhalen.\nAll Transwiki-Import-Aktioune ginn am [[Special:Log/import|Import-Logbuch]] protokolléiert.",
-       "import-interwiki-source": "Quelle Wiki/Säit:",
+       "import-interwiki-text": "Sicht eng Wiki an e Säitentitel eraus fir z'importéieren.\nD'Versiounsdatumen an d'Benotzernimm bleiwen dobäi erhalen.\nAll Transwiki-Import-Aktioune ginn am [[Special:Log/import|Import-Logbuch]] protokolléiert.",
+       "import-interwiki-sourcewiki": "Quellwiki:",
+       "import-interwiki-sourcepage": "Originalsäit:",
        "import-interwiki-history": "Importéier all d'Versioune vun dëser Säit",
        "import-interwiki-templates": "Mat alle Schablounen",
        "import-interwiki-submit": "Import",
        "import-error-create": "D'Säit \"$1\" gouf net importéiert well Dir se net uleeën däerft.",
        "import-error-interwiki": "D'Säit  \"$1\" gouf net importéiert well deen Numm fir extern Linken (Interwiki) reservéiert ass.",
        "import-error-special": "D'Säit \"$1\" gouf net importéiert well se zu engem speziellen Nummraum gehéiert an deem et keng Säite gëtt.",
-       "import-error-invalid": "D'Säit \"$1\" gouf net importéiert well hiren Numm net valabel ass.",
+       "import-error-invalid": "D'Säit \"$1\" gouf net importéiert well den Numm op se importéiert gouf an dëser Wiki net valabel ass.",
        "import-error-unserialize": "D'Versioun $2 vun der Säit \"$1\" konnt net deserialiséiert ginn. Et gouf uginn datt déi Versioun den Inhaltsmodell $3 benotzt deen als $4 serialiséiert ass.",
        "import-options-wrong": "Falsch {{PLURAL:$2|Optioun|Optiounen}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "Déi Basis-Säit déi Dir uginn hutt ass kee valabelen Titel.",
        "importlogpage": "Lëscht vun den Säitenimporten",
        "importlogpagetext": "Administrativen Import vu Säite mam Historique vun den Ännerungen aus anere Wikien.",
        "import-logentry-upload": "huet [[$1]] vun engem Fichier duerch Eroplueden importéiert",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|Versioun|Versiounen}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|Versioun|Versiounen}} importéiert",
        "import-logentry-interwiki": "huet $1 importéiert (Transwiki)",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|Versioun|Versioune}} vum $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|Versioun|Versiounen}} importéiert vu(n) $2",
        "javascripttest": "JavaScript-Test",
        "javascripttest-title": "$1-Tester ginn elo gemaach",
        "javascripttest-pagetext-noframework": "Dës Säit ass fir Java-Script-Tester reservéiert.",
        "confirmemail_pending": "Dir krut schonn e Confirmatiouns-Code per E-Mail geschéckt. Wenn Dir Äre Benotzerkont eréischt elo kuerz opgemaach hutt, da gedëllegt Iech nach e puer Minutten bis Är E-Mail ukomm ass, ier Dir een neie Code ufrot.",
        "confirmemail_send": "Confirmatiouns-E-Mail schécken",
        "confirmemail_sent": "Confirmatiouns-E-Mail gouf geschéckt.",
-       "confirmemail_oncreate": "E Confirmatiouns-Code gouf op Är E-Mail-Adress geschéckt.\nDëse Code gëtt fir d'Umeldung net gebraucht. Dir braucht en awer bei der Aktivéierung vun den E-Mail-Funktiounen bannert der Wiki.",
+       "confirmemail_oncreate": "E Confirmatiouns-Code gouf op Är E-Mail-Adress geschéckt.\nDëse Code gëtt fir d'Umeldung net gebraucht. Dir braucht en awer bei der Aktivéierung vun den E-Mail-Funktioune bannert der Wiki.",
        "confirmemail_sendfailed": "{{SITENAME}} konnt är Confirmatiouns-E-Mail net schécken.\nIwwerpréift w.e.g. är E-Mailadress op ongëlteg Zeechen.\n\nFeelermeldung vum Mailserver: $1",
        "confirmemail_invalid": "Ongëltege Confirmatiounscode. Eventuell ass d'Gëltegkeetsdauer vum Code ofgelaf.",
        "confirmemail_needlogin": "Dir musst Iech $1, fir Är E-Mail-Adress ze confirméieren.",
        "confirmemail_loggedin": "Är E-Mail-Adress gouf elo confirméiert.",
        "confirmemail_subject": "Confirmatioun vun der E-Mail-Adress fir {{SITENAME}}",
        "confirmemail_body": "E Benotzer, waarscheinlech dir selwer, hutt mat der IP Adress $1 de Benotzerkont \"$2\" um Site {{SITENAME}} opgemaach.\n\nFir ze bestätegen, datt dee Kont iech wierklech gehéiert a fir d'E-Mail-Funktiounen um Site {{SITENAME}} z'aktivéieren, maacht w.e.g. dëse Link an ärem Browser op:\n$3\n\nWann dir dëse Benotzerkont *net* opgemaach hutt, maacht w.e.g. dëse Link an ärem Browser op fir d'E-Mailconfirmation z'annulléieren:\n\n$5\n\nSollt et sech net ëm äre Benotzerkont handelen, da maacht de Link *net* op. De Confirmatiounscode ass gëlteg bis de(n) $4.",
-       "confirmemail_body_changed": "E Benotzer, wahrscheinlech Dir selwer, vun der IP-Adress $1,\nhuet d'E-Mail-Adress vum Benotzerkont \"$2\" op dës Adress op {{SITENAME}} geännert.\n\nFir ze confirméieren datt dëse Benotzerkont Iech wierklech gehéiert a fir d'E-Mailfonctiounen op {{SITENAME}} ze reaktivéieren, maacht dës Link an Ärem Browser op:\n\n$3\n\nWann de Benotzerkont Iech *net* gehéiert, da klickt op dëse Link fir d'Confirmatioun vun der E-Mail-Adress auszeschalten:\n\n$5\n\nDëse Confirmatiounscode leeft den $4 of.",
+       "confirmemail_body_changed": "E Benotzer, wahrscheinlech Dir selwer, vun der IP-Adress $1,\nhuet d'E-Mail-Adress vum Benotzerkont \"$2\" op dës Adress op {{SITENAME}} geännert.\n\nFir ze confirméieren datt dëse Benotzerkont Iech wierklech gehéiert a fir d'E-Mailfonctiounen op {{SITENAME}} ze reaktivéieren, maacht dëse Link an Ärem Browser op:\n\n$3\n\nWann de Benotzerkont Iech *net* gehéiert, da klickt op dëse Link fir d'Confirmatioun vun der E-Mail-Adress auszeschalten:\n\n$5\n\nDëse Confirmatiounscode leeft den $4 of.",
        "confirmemail_body_set": "Iergendeen, wahrscheinlech Dir selwer, vun der IP-Adress $1,\nhuet d'E-Mail-Adress vum Benotzerkont \"$2\" op dës Adress op {{SITENAME}} geännert.\n\nFir ze confirméieren datt dëse Benotzerkont Iech wierklech gehéiert a fir d'E-Mailfonctiounen op {{SITENAME}} ze reaktivéieren, maacht dës Link an Ärem Browser op:\n\n$3\n\nWann de Benotzerkont Iech *net* gehéiert, da klickt op dëse Link fir d'Confirmatioun vun der E-Mail-Adress auszeschalten:\n\n$5\n\nDëse Confirmatiounscode leeft den $4 of.",
        "confirmemail_invalidated": "Confirmatioun vun der E-Mail-Adress annulléiert",
        "invalidateemail": "Annulléier d'E-Mailconfirmation",
        "autosumm-replace": "Säitinhalt gëtt ersat duerch '$1'",
        "autoredircomment": "Virugeleet op [[$1]]",
        "autosumm-new": "Säit ugeluecht mat: '$1'",
+       "autosumm-newblank": "Eidel Säit ugeluecht",
        "lag-warn-normal": "Ännerunge vun {{PLURAL:$1|der leschter Sekonn|de leschte(n) $1 Sekonnen}} kënnen an dëser Lëscht net gewise ginn.",
        "lag-warn-high": "Duerch eng héich Serverbelaaschtung kënne Verännerungen déi viru manner wéi $1 {{PLURAL:$1|Sekonn|Sekonne}} gemaach goufen, net an dëser Lëscht ugewise ginn.",
        "watchlistedit-normal-title": "Iwwerwaachungslëscht änneren",
        "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",
+       "logentry-upload-upload": "$1 huet $3 {{GENDER:$2|eropgelueden}}",
+       "logentry-upload-overwrite": "$1 huet eng nei Versioun vu(n) $3 {{GENDER:$2|eropgelueden}}",
+       "logentry-upload-revert": "$1 huet $3 {{GENDER:$2|eropgelueden}}",
        "rightsnone": "(keen)",
        "feedback-bugornote": "Wann Dir bereet sidd fir en technesche Problem am Detail ze beschreiwen da [$1 mellt w.e.g. e Feeler (Bug)].\nSoss kënnt Dir den einfache Formulär hei drënner benotzen. Är Bemierkung gëtt op d'Säit \"[$3 $2]\" derbäigesat, zesumme mat Ärem Benotzernumm an dem Numm vum Browser deen Dir benotzt.",
        "feedback-subject": "Sujet:",
        "pagelang-select-lang": "Sprooch eraussichen",
        "right-pagelang": "Sprooch vun der Säit änneren",
        "action-pagelang": "d'Sprooch vun der Säit änneren",
-       "log-description-pagelang": "Dëst ass a Log mat den Ännerunge vun de Sprooche vun de Säiten."
+       "log-name-pagelang": "Log vum Ännere vun der Sprooch",
+       "log-description-pagelang": "Dëst ass a Log mat den Ännerunge vun de Sprooche vun de Säiten.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (aktivéiert)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''desaktivéiert''')"
 }
index 3cbf19c..69b197c 100644 (file)
        "talkpagelinktext": "Рахун",
        "specialpage": "Куьмекчи ччин",
        "personaltools": "Кьилди вичин алатар",
-       "postcomment": "ЦӀйий пай",
        "articlepage": "Къене авайбурун ччиндиз килигун",
        "talk": "Веревирд авун",
        "views": "Килигунар",
        "yourdomainname": "Куь домен",
        "login": "Гьахьун",
        "nav-login-createaccount": "Гьахьун/аккаунт туькӀуьрун",
-       "loginprompt": "Системадиз гьахьун патал \"куки\" -яр куькӀуьрна кӀанзава",
        "userlogin": "Гьахьун/аккаунт туькӀуьрун",
        "userloginnocreate": "Гьахьун",
        "logout": "ЭкъечӀун",
        "filereuploadsummary": "Файлдин къене дегишвилер:",
        "filestatus": "Автордин ихтиярдин статус:",
        "filesource": "Чешме:",
-       "uploadedimage": "\"[[$1]]\" ппарна",
        "upload-source": "Чешмедин файл",
        "sourcefilename": "Чешмедин тир файлдин тIвар:",
        "sourceurl": "Чешмедин URL-адрес:",
        "watchlisttools-raw": "Текст хьиз дуьзар хъувун",
        "duplicate-defaultsort": "'''Дикъет:''' Авайд хьиз кьунвай жуьрейриз ччара авунин \"$2\" куьлег  виликан \"$1\" жуьрейриз ччара авунин куьлег гьич йийзва.",
        "version": "Жуьре",
-       "version-antispam": "Спамдин вилик пад атIун",
        "version-skins": "КЪайдадиз ттунин темаяр",
+       "version-antispam": "Спамдин вилик пад атIун",
        "version-other": "Муькуьбур",
        "specialpages": "КьетӀен ччинар",
        "external_image_whitelist": " #И цӀар авайд хьиз тур<pre>\n#Агъада вахт акадар тийиз жезвай (гьамиша къайдадалди) лугьунрин кьатӀар эцига (// арада авай кӀус).\n#Ибур кьецепатан суьретрин URL галаз гекъигда.\n#Дуьзкъвезвайбур суьретар хьиз къалурда, муькуьбур суьретриз тухузвай элячӀунар хьиз къалурда.\n#«#» галаз эгечӀзавай цӀарариз къейдериз хьиз килигда.\n#ЦӀарар регистрдиз фад кьатӀудайбур я.\n\n#ЦӀарцин винел вири вахт акадар тийиз жезвай лугьунрин кьатӀар эцига. И цӀар авайд хьиз тур</pre>",
index f11f156..b7592f5 100644 (file)
        "talkpagelinktext": "Parla",
        "specialpage": "Paje spesial",
        "personaltools": "Utiles personal",
-       "postcomment": "Sesion nova",
        "articlepage": "Vide la paje de contenis",
        "talk": "Discutes",
        "views": "Vides",
        "yourdomainname": "Tu domina:",
        "login": "Identifia",
        "nav-login-createaccount": "Sinia per entra",
-       "loginprompt": "Tu debe engrana \"tortetas\" per entra {{SITENAME}}.",
        "userlogin": "Sinia per entra",
        "logout": "Retira",
        "userlogout": "Sinia per retira",
        "uploadbtn": "Envia la fix",
        "uploadlogpage": "Envia arcivo",
        "savefile": "Fisa fix",
-       "uploadedimage": "\"[[$1]]\" es enviada",
        "upload-file-error": "Era interna",
        "imgfile": "fix",
        "listfiles": "Lista de imajes",
index 25010fe..ee0185a 100644 (file)
        "talkpagelinktext": "Yogera nange",
        "specialpage": "Olupapula olwawule",
        "personaltools": "Ebikola ku akawunti n'enfo yo",
-       "postcomment": "Kitundu kipya",
        "articlepage": "Kebera olupapula",
        "talk": "Emboozi",
        "views": "Kyusa endabika ya by'olaba wano",
        "externaldberror": "Waliwo kiremya mu ggwanika lya data ekozesebwa okukakasa bamemba oba tokkirizibwa okukyusa ku akawunti yo ey'awalala.",
        "login": "Yingira",
        "nav-login-createaccount": "Yingira / kolawo akawunti",
-       "loginprompt": "Okuyingira {{SITENAME}}, kalambula-neti yo erina okukkirizako kuki.",
        "userlogin": "Yingira / kolawo akawunti",
        "userloginnocreate": "Yingira",
        "logout": "Vaamu",
        "recentchangeslinked-to": "Nonamu eby'empapula ezikuggusa ku luno zokka",
        "upload": "Teekayo fayiro",
        "uploadlogpage": "Likooda eya fayiro eziteekedwa ku wiki",
-       "uploadedimage": "yateekayo \"[[$1]]\"",
        "listfiles_user": "Memba",
        "file-anchor-link": "Fayiro",
        "filehist": "Ebyafaayo ebya fayiro eno",
index 255d832..bf80d69 100644 (file)
        "talkpagelinktext": "Euverlègk",
        "specialpage": "Speciaal pagina",
        "personaltools": "Persuunlike hulpmiddele",
-       "postcomment": "Nuuj sectie",
        "articlepage": "Artikel",
        "talk": "Euverlègk",
        "views": "Weergave",
        "externaldberror": "d'r Is 'n fout opgetraoje biej 't aanmelje biej de database of doe höbs gén toesjtömming diene externe gebroeker biej te wèrke.",
        "login": "Aanmèlde",
        "nav-login-createaccount": "Aanmelje / registrere",
-       "loginprompt": "Diene browser mót ''cookies'' acceptere óm in te logge op {{SITENAME}}.",
        "userlogin": "Aanmelde / registrere",
        "userloginnocreate": "Mèlj aan",
        "logout": "Aafmelde",
        "searchprofile-advanced-tooltip": "Zeuke in aongegeve naamruumdes",
        "search-result-size": "$1 ({{PLURAL:$2|1 waord|$2 wäörd}})",
        "search-result-category-size": "{{PLURAL:$1|1 categorielid|$1 categorielede}} ({{PLURAL:$2|1 ongercategorie|$2 ongercategorieë}}, {{PLURAL:$3|1 bestandj|$3 bestenj}})",
-       "search-result-score": "Relevantie: $1%",
        "search-redirect": "(doorverwiezing $1)",
        "search-section": "(subkop $1)",
        "search-suggest": "Meins te sóms: $1",
        "uploadwarning": "Upload waarsjuwing",
        "uploadwarning-text": "Pas de ongerstaonde bestandjsbesjrieving aan en perbeer t daonao opnuuj.",
        "savefile": "Bestand opsjlaon",
-       "uploadedimage": "haet ge-upload: [[$1]]",
-       "overwroteimage": "haet 'ne nuuje versie van \"[[$1]]\" toegevoeg",
        "uploaddisabled": "Uploade is oetgesjakeld",
        "copyuploaddisabled": "t Uploade van bestenj via nen URL is oetgezat.",
        "uploaddisabledtext": "'t uploade van bestenj is oetgesjakeld.",
        "watchlist-details": "D'r {{PLURAL:$1|sjteit ein pagina|sjtaon $1 pagina's}} op dien volglies mit oetzunjering van de euverlèkpagina's.",
        "wlheader-enotif": "Doe wörs per e-mail gewaarsjuwd",
        "wlheader-showupdated": "Pazjena's die verangerd zeen saers doe ze veur 't lètste bekeeks sjtaon '''vet'''",
+       "wlnote": "Hieónger {{PLURAL:$1|steit de lètste verangering|staon de lètste $1 verangeringe}} van {{PLURAL:$2|'t lètste oer|de lètste <b>$2</b> oer}} óp $3 óm $4.",
        "wlshowlast": "Tuin lètste $1 ore $2 daag $3",
        "watchlist-options": "Opties veur volglies",
        "watching": "Bezig mit plaatse op de volglies...",
        "import": "Pazjena's importere",
        "importinterwiki": "Transwiki-import",
        "import-interwiki-text": "Selecteer 'ne wiki en pazjenanaam om te importere.\nVersie- en auteursgegaeves blieve hiej bie bewaard.\nAlle transwiki-importhanjelinge waere opgeslage in 't [[Special:Log/import|importlogbook]].",
-       "import-interwiki-source": "Bronwiki/pagina:",
        "import-interwiki-history": "Volledige gesjiedenis van deze pazjena ouch kopiëre",
        "import-interwiki-templates": "Alle sjablone opnaeme",
        "import-interwiki-submit": "Importere",
        "duplicate-defaultsort": "Waarsjuwing: De standaardsortering \"$2\" krieg veurrang veur de sortering \"$1\".",
        "version": "Versie",
        "version-extensions": "Geïnstalleerde oetbreijinge",
+       "version-skins": "Vörmgevinge",
        "version-specialpages": "Speciaal pazjena's",
        "version-parserhooks": "Parserheuk",
        "version-variables": "Variabele",
        "version-antispam": "Spampreventie",
-       "version-skins": "Vörmgevinge",
        "version-other": "Euverige",
        "version-mediahandlers": "Mediaverwerkers",
        "version-hooks": "Heuk",
        "htmlform-selectorother-other": "Anges",
        "sqlite-has-fts": "Zeuk versie $1 mit óngersteuning veur \"full-text\"",
        "sqlite-no-fts": "Zeuk versie $1 zónger óngersteuning veur \"fulltext\"",
-       "logentry-delete-delete": "$1 haef de pagina $3 gewösj",
+       "logentry-delete-delete": "$1 {{GENDER:$1|haet}} de pagina $3 gewösj",
        "logentry-delete-restore": "$1 haet de pagina $3 trögkgezat",
        "logentry-delete-event": "$1 haet de zichbaarheid van {{PLURAL:$5|'ne logbookregel|$5 logbookregels}} van $3 gewiezig: $4",
        "logentry-delete-revision": "$1 haet de zichbaarheid van {{PLURAL:$5|'n versie|$5 versies}} van $3 gewiezig: $4",
index 98789dd..c475327 100644 (file)
        "talkpagelinktext": "Ciæti",
        "specialpage": "Pagina speçiâ",
        "personaltools": "Strùmenti personâli",
-       "postcomment": "Noeuva seçion",
        "articlepage": "Veddi a voxe",
        "talk": "Ciæti",
        "views": "Vìxite",
        "password-change-forbidden": "No ti peu cangiâ poula segretta in questa wiki.",
        "login": "Intra",
        "nav-login-createaccount": "Intra / Registrate",
-       "loginprompt": "Pe fâ l'accesso inte {{SITENAME}} ti g'hæ da  abilitâ i cookie.",
        "userlogin": "Intra / Registrite",
        "userloginnocreate": "Intra",
        "logout": "Sciorti",
        "fileexists": "Un papê co sto nomme o existe de zà, pe piaxei da unn'euggiâ a <strong>[[:$1]]</strong> se non ti tei seguo de voleilo cangiâ.\n[[$1|thumb]]",
        "fileexists-forbidden": "Un papê co sto nomme o existe de zà, pe piaxei vanni in derrê e carega sto papê co un ätro nomme. [[File:$1|thumb|center|$1]]",
        "savefile": "Sarva o papê",
-       "uploadedimage": "O l'ha caregòu \"[[$1]]\"",
        "uploaddisabledtext": "In {{SITENAME}} non se peu caregâ de papê.",
        "uploadvirus": "O papê gha un virus!! Dettaggi: $1",
        "sourcefilename": "Nomme do papê d'origine:",
index d36102c..727743d 100644 (file)
@@ -4,7 +4,8 @@
                        "Andrijko Z.",
                        "Erdemaslancan",
                        "Ohpuu",
-                       "Warbola"
+                       "Warbola",
+                       "아라"
                ]
        },
        "sunday": "pivāpǟva",
        "navigation": "Navigīerimi",
        "qbfind": "Vȯtšõgid",
        "faq": "SKK",
-       "vector-action-addsection": "Pangid jūrõ tēma",
-       "vector-action-delete": "Kištāntõgid jarā",
-       "vector-action-move": "Vīž jarā",
-       "vector-action-protect": "Kaitsõmi",
-       "vector-view-create": "Lūo",
-       "vector-view-edit": "Redigīer",
-       "vector-view-history": "Nägţ istōrijõ",
-       "vector-view-view": "Vaņ",
-       "vector-view-viewsource": "Vaņ ovāt tekstõ",
        "actions": "Tīemizt",
        "namespaces": "Nim-rūimõd",
        "variants": "Varianţõd",
        "remembermypassword": " Mǟdlõgid sallisõnā (kuņtš $1 {{PLURAL:$1|päuvõ|päuvõ}})",
        "login": "Log sīezõ",
        "nav-login-createaccount": "Log sīezõ agā registrīer kȭlbatijizõks",
-       "loginprompt": "Sīezõ loggimizõks täddõn um āndamizt lubā \"kūkid\" (''cookies'') pierāst",
        "userlogin": "Sīezõ loggimi agā kȭlbatijiz-konto lūomi",
        "logout": "Log ulzõ",
        "userlogout": "Log ulzõ",
        "searchmenu-exists": "'''Lēḑ pēļizkēraks \"[[:$1]]\" um vȯlmizõs.'''",
        "searchmenu-new": "'''Lūo lēḑ pēļizkēraks \"[[:$1]]\".'''",
        "searchprofile-articles": "Sižāliz lēḑõd",
-       "searchprofile-project": "Ab ja projekt lēḑõd",
        "searchprofile-images": "Multimēdij",
        "searchprofile-everything": "Tikkiž",
        "searchprofile-advanced": "Jo akurāt vȯtšimi",
        "searchprofile-articles-tooltip": "Vȯtšõgid nim-rūimstõ $1",
-       "searchprofile-project-tooltip": "Vȯtšõgid nim-rūimstõ $1",
        "searchprofile-images-tooltip": "Fail vȯtšimi",
        "searchprofile-everything-tooltip": "Vȯtšõgid amā sižāliz sizāld (ka nõvpidāmiz-lēḑõd pǟld)",
        "searchprofile-advanced-tooltip": "Vȯtšõgid andtõd nim-rūimšti",
        "search-nonefound": "Vȯtšimizõn vȯtšimi äb lieudtõd vastūkst.",
        "powersearch-legend": " Juo akurāt vȯtšimi",
        "powersearch-ns": "Vȯtšimi nim-rūimšti:",
-       "powersearch-redir": "Jeddõpēḑõn sōtimizt nimkēra",
        "preferences": "Mīeldõbõd ulzõ-vēļimizt",
        "mypreferences": "Min mīeldõbõd ulzõ-vēļimizt",
        "youremail": "E-kēra adres:",
        "recentchanges-label-bot": "Sīe mõitõks tei ikš robot",
        "recentchanges-label-unpatrolled": "Se mõitõks tēji vȯļ ikš robot",
        "rcnotefrom": "Allõ-pūol um tūodõd mõitõkst  '''$2''' sōņõst: (nägţõbõd amā jemīņ '''$1''' mõitõkst)",
-       "rclistfrom": "Nägţ mõitõkši sōņõst: $1",
+       "rclistfrom": "Nägţ mõitõkši sōņõst: $3 $2",
        "rcshowhideminor": "$1 piškizt parāmtimizt",
        "rcshowhidebots": "$1 robōtõd",
        "rcshowhideliu": "$1 sīezõ loggõnd kȭlbatijizt",
        "upload": "Fail ilzõ-lōţimi",
        "uploadlogpage": "Ilzõ-lōţimiz log",
        "filedesc": "Kubbõ võtāmi:",
-       "uploadedimage": "lōţiz ilzõ fail \"[[$1]]\"",
        "license": "Litsents:",
        "license-header": "Litsents:",
        "file-anchor-link": "Bīlda",
        "booksources-go": "Li",
        "log": "Logūd",
        "allpages": "Amād lēḑõd",
-       "alphaindexline": "$1 sōņist $2 sōņõ",
        "prevpage": "Jedmõli lēḑ ($1)",
        "allpagesfrom": " Nägţ līedidi pēļizkērast sōņõst:",
        "allpagesto": " Nägţ līedidi sīe pēļikēra sōņõ:",
index cf83330..80bfa6b 100644 (file)
        "talkpagelinktext": "Ciciarada",
        "specialpage": "Pagina speciala",
        "personaltools": "Istrüment persunaj",
-       "postcomment": "Sezión növa",
        "articlepage": "Varda l'articul",
        "talk": "Discüssión",
        "views": "Vìste",
        "externaldberror": "Gh'è 'n erùr söl server de autenticasiù estèrno o sedenò se g'ha mìa le autorizasiù nesesàre per agiurnà i dati de registrasiù estèrni.",
        "login": "Va dent",
        "nav-login-createaccount": "Vena denter / Crea un cünt",
-       "loginprompt": "Par cunett a {{SITENAME}}, a duvii abilitá i galet.",
        "userlogin": "Vegní denter - Creè un cünt",
        "userloginnocreate": "Vegn denter",
        "logout": "Va fö",
        "searchprofile-everything-tooltip": "Cerca depertüt (anca int i paginn de discüssion)",
        "searchprofile-advanced-tooltip": "Cerca int i namespace persunalizaa",
        "search-result-size": "$1 ({{PLURAL:$2|1 parola|$2 paroll}})",
-       "search-result-score": "Atinènsa: $1%",
        "search-redirect": "(redirezión $1)",
        "search-section": "(sessión $1)",
        "search-file-match": "(corespondènsa endèl test de l'archivi)",
        "ignorewarnings": "Ignora tücc i avertimeent",
        "largefileserver": "Chel archivi-chí al è püssee graant che ul serviduur al sía cunfigüraa da permett.",
        "savefile": "Salva l'archivi",
-       "uploadedimage": "l'ha cargaa \"[[$1]]\"",
        "sourcefilename": "Nomm da l'archivi surgeent:",
        "destfilename": "Nomm da l'archivi da destinazziun:",
        "imgfile": "archivi",
index d7eb71b..5e8fda1 100644 (file)
@@ -3,12 +3,12 @@
                "authors": [
                        "Bombo (on ln.wikipedia.org)",
                        "Eruedin",
-                       "Moyogo"
+                       "Moyogo",
+                       "TMg"
                ]
        },
        "tog-underline": "Kotíya sulimá na bikangisi:",
        "tog-showtoolbar": "Komɔ́nisa ndámbo-ndámbo (esengélí JavaScript)",
-       "tog-rememberpassword": "Komíkundola bokitoli na molúki (ekosúkisa na {{PLURAL:$1|mokɔlɔ|mikɔlɔ}} $1)",
        "underline-always": "Mikɔlɔ yɔ́nsɔ",
        "underline-never": "Libélá tɛ́",
        "sunday": "Lomíngo",
@@ -53,8 +53,8 @@
        "feb": "s2",
        "mar": "s3",
        "apr": "s4",
-       "may": "s4",
-       "jun": "s5",
+       "may": "s5",
+       "jun": "s6",
        "jul": "s7",
        "aug": "s8",
        "sep": "s9",
        "qbpageoptions": "Lonkásá óyo",
        "qbmyoptions": "Lonkásá na ngáí",
        "faq": "Mitúná Mizóngelaka (MM)",
-       "vector-action-addsection": "Kobakisa mpɔ̂",
-       "vector-action-delete": "Kolímwisa",
-       "vector-action-move": "Kobóngola nkómbó",
-       "vector-action-protect": "Kobátela",
-       "vector-action-undelete": "Kolímwisa tɛ̂",
-       "vector-action-unprotect": " Kobátela tɛ̂",
-       "vector-view-create": "Kokela",
-       "vector-view-edit": "Kobɔngisa",
-       "vector-view-history": "Komɔ́nisa mokóló",
-       "vector-view-view": "Kotánga",
-       "vector-view-viewsource": "Komɔ́nisa mosólo",
        "namespaces": "Ntáká ya nkómbó",
        "errorpagetitle": "Mbéba",
        "returnto": "Kozóngisa na $1.",
        "talkpagelinktext": "Ntembe",
        "specialpage": "Lonkásá gudi",
        "personaltools": "Bisáleli ya moto-mɛ́i",
-       "postcomment": "Sɛksió sika",
        "articlepage": "Komɔ́nisa káti",
        "talk": "Ntembe",
        "views": "Bomɔ́nisi",
        "searchprofile-images": "Mitímediá",
        "searchprofile-everything": "Yɔ́nsɔ",
        "searchprofile-articles-tooltip": "Koluka na $1",
-       "searchprofile-project-tooltip": "Koluka na $1",
        "search-result-size": "$1 ({{PLURAL:$2|lokomá 1|nkomá $2}})",
-       "search-result-score": "Ntína : $1%",
        "search-redirect": "(boyendisi útá $1)",
        "search-section": "(sɛksió ya $1)",
        "search-suggest": "Ómeka na lokomá : $1",
        "searchall": "nyɔ́nsɔ",
        "powersearch-legend": "Boluki bopúsání",
        "powersearch-ns": "Koluka o ntáká ya nkómbó :",
-       "powersearch-redir": "Kotíya molɔngɔ́ mwa mayendisi",
        "powersearch-toggleall": "Nyɔ́nsɔ",
        "powersearch-togglenone": "Mɔ́kɔ́ tɛ́",
        "preferences": "Malúli",
        "uploadlogpage": "Zuluná ya botómbisi likoló",
        "filedesc": "Likwé ya mokusé:",
        "savefile": "kobómbisa kásá-kásá",
-       "uploadedimage": "«[[$1]]» etómbísámí likoló",
        "listfiles_date": "Mokɔlɔ",
        "file-anchor-link": "Elilingi",
        "filehist": "Mokóló mwa kásá",
        "booksources-go": "Kɛndɛ́",
        "log": "Bapasɔ́",
        "allpages": "Nkásá ínsɔ",
-       "alphaindexline": "$1 kina $2",
        "nextpage": "Lonkásá ya nsima ($1)",
        "prevpage": "Lonkasá o libosó ($1)",
        "allarticles": "Nkásá ínsɔ",
        "watchthispage": "Kolanda lonkásá óyo",
        "unwatch": "Kolanda tɛ́",
        "watchlist-details": "{{PLURAL:$1|Lonkásá $1 elandámí|Nkásá $1 bilandámí}}, longola nkásá ya ntembe.",
+       "wlnote": "Áwa o nsé {{PLURAL:$1|ezalí mbóngwana ya nsúka|izalí mbóngwana '''$1''' ya nsúka}} o {{PLURAL:$2|ngonga|ngonga '''$2'''}} ya nsúka.",
        "wlshowlast": "Komɔ́nisa ngónga $1 ya nsúka, mikɔlɔ $2 mya nsúka tǒ $3",
        "watching": "Kolanda...",
        "unwatching": "Kolanda tɛ́...",
index 4990cb2..dfffb14 100644 (file)
        "yourdomainname": "ໂດເມນ ຂອງ ທ່ານ",
        "login": "ເຊັນເຂົ້າ",
        "nav-login-createaccount": "ເຊັນເຂົ້າ / ສ້າງບັນຊີ",
-       "loginprompt": "ທ່ານຕ້ອງຮັບຄຸກກີ້ ເພື່ອ ເຊັນເຂົ້າ {{SITENAME}}.",
        "userlogin": "ເຊັນເຂົ້າ / ສ້າງບັນຊີ",
        "logout": "ເຊັນອອກ",
        "userlogout": "ເຊັນອອກ",
        "nextn": "{{PLURAL:$1|$1}} ຕໍ່ໄປ",
        "viewprevnext": "ເບິ່ງ ($1 {{int:pipe-separator}} $2) ($3).",
        "search-result-size": "$1 ({{PLURAL:$2|1 ຄຳ|$2 ຄຳ}})",
-       "search-result-score": "ຄວາມກ່ຽວຂ້ອງ: $1%",
        "search-redirect": "(ໂອນ $1)",
        "search-relatedarticle": "ກ່ຽວຂ້ອງ",
        "searchrelated": "ກ່ຽວຂ້ອງ",
index fdeafee..7f03841 100644 (file)
        "talkpagelinktext": "Bulelezi",
        "specialpage": "Petulo Zwenti",
        "personaltools": "Solume sisebelisoni",
-       "postcomment": "Bulelezi mulumiwa",
        "articlepage": "Kamukile petulo",
        "talk": "Bulelezi",
        "views": "Kamukile",
        "yourdomainname": "Zwa domeni:",
        "login": "Menuhile",
        "nav-login-createaccount": "Menuhile / ipupezi sebelu",
-       "loginprompt": "A sa nyembulisize di kukina di menuhile kwa {{SITENAME}}.",
        "userlogin": "Menuhile / ipupezi sebelu",
        "logout": "Ile",
        "userlogout": "Ile",
        "fileuploadsummary": "Lyangutukezi:",
        "filesource": "Ng'i",
        "savefile": "Bulukezi imegi",
-       "uploadedimage": "sa uplodezi \"[[$1]]\"",
-       "overwroteimage": "sa uplodezi nca imegi petuho di \"[[$1]]\"",
        "sourcefilename": "Ng'i di imegi",
        "watchthisupload": "Kentezi bye petulo",
        "upload-file-error": "Interni bufosi",
index 5352d96..8328041 100644 (file)
@@ -20,6 +20,7 @@
        "tog-watchdefault": "بلگیا و فایلایی که مه ویرایشت کمه اضاف کو د سیل برگم",
        "tog-watchmoves": "بلگیاو فایلیایی که مه جاوه جا کمه د سیل برگم اضاف کو",
        "tog-watchdeletion": "بلگیا و فایلایی که مه پاک کمه اضاف کو د سیل برگم",
+       "tog-watchrollback": "همه بلگه یا نه د جایی که مه د سیل برگم می کم اضاف کو.",
        "tog-minordefault": "همه ویرایشتیا کؤچک نه وا پیش فرض بیئن نشو دار کو.",
        "tog-previewontop": "پیش سیل نه دما جعوه ویرایشت نشو بیئه",
        "tog-previewonfirst": "پیش سیل نه د اولین ویرایشت نشو بیئه",
        "index-category": "بلگيا سيائه دار",
        "noindex-category": "بلگيا بی سيائه",
        "broken-file-category": "بلگیایی که هوم پیوند فایلیا اشکسه دارن",
+       "categoryviewer-pagedlinks": "($1) ($2)",
        "about": "دباره",
        "article": "محتوا بلگه",
        "newwindow": "(نيمدری  تازه وا کو)",
        "view": "ديئن",
        "view-foreign": "د $1 نه بوینیت",
        "edit": "ويرايشت",
+       "edit-local": "توضیح ولات نشینی نه ویرایشت بکیت",
        "create": "راس كردن",
+       "create-local": "یه گل توضیح ولات نشینی اضاف بکیتو",
        "editthispage": "ويرايشت ای بلگه",
        "create-this-page": "راس كردن ای بلگه",
        "delete": "حذف كردن",
        "deletethispage": "ای بلگه نه حذف بكيد",
        "undeletethispage": "ای بلگه نه حذف نكيد",
        "undelete_short": "زنه کردن {{جمی:$1|یه گل ویرایشت|$1 ویرایشتیا}}",
-       "viewdeleted_short": "بوینیت {{[جمی:$1|یه گل ویرایشت پاک بیه|$1ویرایشتیا پاک بیه}}",
+       "viewdeleted_short": "بوینیت {{[جمی:$1|یه گل ویرایشت پاکسا بیه|$1ویرایشتیا پاکسا بیه}}",
        "protect": "حمايت بكيد",
        "protect_change": "آلشت بكيد",
        "protectthispage": "ای بلگه نه حفاظت بكيد",
        "talkpagelinktext": "وت و واچ",
        "specialpage": "بلگه ويجه",
        "personaltools": "اوزاريا شصقی",
-       "postcomment": "بشه تازه",
        "articlepage": "ديئن محتوا بلگه",
        "talk": "گپ",
        "views": "ديئنيا",
        "otherlanguages": "د زونيا هنی",
        "redirectedfrom": "(ورگشتن د$1)",
        "redirectpagesub": "بلگه دوباره ورگشتن",
+       "redirectto": "واگردونی سی:",
        "lastmodifiedat": "ای بلگه تازه ايا وضع آلشت بيه د $1, د $2.",
        "viewcount": "ای بلگه قاول دسترسی بيه {{PLURAL:$1|once|$1 times}}.",
        "protectedpage": "بلگه حفاظت بيه",
        "jumpto": "پئرستن د",
        "jumptonavigation": "ناوگشتن",
        "jumptosearch": "پی جوری",
+       "view-pool-error": "د بدبختی،ایسنی سروریا فره شلوغ.\nکاریاریا فره زیادی میهان ای بلگه نه بوینن.\nیه گری صب بکیتو دما یه که میهات دوواره ای بلگه نه بوینیت.",
+       "generic-pool-error": "د بدبختی،ایسنی سروریا فره شلوغ.\nکاریاریا فره زیادی میهان ای بلگه نه بوینن.\nیه گری صب بکیتو دما یه که میهات دوواره ای بلگه نه بوینیت.",
        "pool-timeout": "وخت سی تیه وه ره منن سی قلف بیئن تموم بی",
        "pool-queuefull": "ذخیره گی گرتن پر بیه",
        "pool-errorunknown": "خطا ناشناس",
+       "pool-servererror": "پول سنتر خذمتگه د دسرس نئ($1).",
        "aboutsite": "دباره {{SITENAME}}",
        "aboutpage": "پروجه:دباره",
        "copyright": "محتوا د دسرس هئ سی $1 مر وه شلک هنی نوشته بوئه",
        "mainpage-description": "سرآسونه",
        "policy-url": "پروجه:خط و مش",
        "portal": "درآسونه کومله یکی",
-       "portal-url": "پرÙ\88جÙ\87ªÙ\84Ú¯ه کومله یکی",
+       "portal-url": "پرÙ\88جÙ\87³Ø±Ø¢Ø³Ù\88Ù\86ه کومله یکی",
        "privacy": "رهبرد رازداری",
        "privacypage": "پروجه: خط مشی راز واداشتن",
        "badaccess": "خطا :اجازه بئیر",
        "badaccess-group0": "شما اجازه انجوم کاری که حاستیت نارین",
        "badaccess-groups": "ای کاری که شما هاستیته سی کاروریا د  {{جمی:$2|گرو|یکی د گرویا}}: $1 مئدود بیه",
        "versionrequired": "یه نسقه د نیازمنیا ویکی رسانه\n$1",
-       "versionrequiredtext": "نسقه $1 ویکی مدیا سی استفاده د ای بلگه لازم هئی .\nوه نه بوینیت [[ویجه:نسقه|نسقه بلگه]].",
+       "versionrequiredtext": "نسقه $1 ویکی مدیا سی وه کار بستن د ای بلگه لازم هئی .\nوه نه بوینیت [[ویجه:نسقه|نسقه بلگه]].",
        "ok": "خوئه",
+       "pagetitle": "$1 - {{SITENAME}}",
+       "pagetitle-view-mainpage": "{{SITENAME}}",
+       "backlinksubtitle": "← $1",
        "retrievedfrom": "بازيافته د\"$1\"",
        "youhavenewmessages": "شما داريت $1($2)",
        "youhavenewmessagesfromusers": "{{جمی:$4|شما }} $1 د {{جمی:$3|کارور هنی|$3 کاروریا}}داریتو($2).",
        "editlink": "ويرايشت",
        "viewsourcelink": "سرچشمه نه بوينيت",
        "editsectionhint": "ويرايشت يه بشق:$1",
-       "toc": "محتوايا",
+       "toc": "مینونه یا",
        "showtoc": "نشو دائن",
        "hidetoc": "قام كردن",
        "collapsible-collapse": "جم كردن",
        "collapsible-expand": "وا كردن",
+       "confirmable-confirm": "{{GENDER:$1|شما}} مطئمنیت?",
+       "confirmable-yes": "هری",
+       "confirmable-no": "نه",
        "thisisdeleted": "دیئن یا ورگنين $1?",
        "viewdeleted": "دیئن$1?",
        "restorelink": "{{جمی:$1|یه گل ویرایشت پاک بیه|$1 ویرایشتیا پاک بیه}}",
-       "feedlinks": "غذا Ø¯Ù\87Ù\86Ù\87:",
+       "feedlinks": "Ø®Ù\88رحÙ\88:",
        "feed-invalid": "نوع مشترک بین خورحو نامعتور",
        "feed-unavailable": "خور حونیا د دسرس نئین",
        "site-rss-feed": "خورخو RSS سی $1",
        "site-atom-feed": "خور حون Atom سی $1",
-       "page-rss-feed": "Ø®Ù\88رخو RSS سی «$1»",
+       "page-rss-feed": "Ø®Ù\88رحو RSS سی «$1»",
        "page-atom-feed": "خور حون Atom سی $1",
+       "feed-atom": "اتم",
+       "feed-rss": "آر اس اس",
        "red-link-title": "$1(بلگه وجود ناره)",
        "sort-descending": "كم بيئن منظم",
        "sort-ascending": "زياد بيئن منظم",
        "nstab-project": "بلگه پروجه",
        "nstab-image": "جانیا",
        "nstab-mediawiki": "پيغوم",
-       "nstab-template": "قالو",
+       "nstab-template": "چوئه",
        "nstab-help": "بلگه هومياری",
        "nstab-category": "دسه",
        "nosuchaction": "چنو كاری وجود ناره",
        "no-null-revision": "سی بلگه$1 دوواره خنثی دیئن راس بکید",
        "badtitle": "موضو گن",
        "badtitletext": "عنوان بلگه حاسته بیه معتور نی،یا  یه گل مئن زونی یا مئن ویکی عنوان غلطه.\nیه شایت شومل یکی با یا بیشتر کاراکتریا نبوئه سی ای موضوعیا استفاده بوئن",
+       "perfcached": "رسینه یا نهایی د ویرگه نهونی موکشت بینه و شایت هنی وه هنگوم سازی نبینه.بیشترونه {{جمی:$4|یه گل نتیجه|$4 یه گل نتیجه}} د ویرگه نهونی هان د دسرس.",
+       "perfcachedts": "رسینه یا نهایی د ویرگه نهونی موکشت بینه و شایت هنی وه هنگوم سازی نبینه.بیشترونه {{جمی:$4|یه گل نتیجه|$4 یه گل نتیجه}} د ویرگه نهونی هان د دسرس.",
+       "querypage-no-updates": "نبوئه ای بلگه وه هنگوم سازی با.\nرسینه یا ایچه تازه نبیه.",
        "viewsource": "سرچشمه نه بوينيت",
        "viewsource-title": "سرچشمه $1 بوينيت",
-       "actionthrottled": "عمل جلوگئری بیه",
+       "actionthrottled": "کنشت جلوگئری بیه",
+       "actionthrottledtext": "سی جلوگئری د درتیچ اسپم نبوئه که شما چنی کارینه د یه گات کؤچک چن گل انجوم بیئتو.\nلطفن مئن چن دیقه هنی تلاش بکیت.",
        "protectedpagetext": "دای بلگه نبوئه ویرایشت یا کاریا هنی بکید",
        "viewsourcetext": "شما تونیت سرچشمه ای بلگه نه بوینیت و دش ورداریت:",
        "viewyourtext": "شما تونیت سرچشمه ویرایشتیا تونه ای د بلگه بوینیت و دشو ورداریت",
+       "protectedinterface": "ای بلگه سی نرم افزار د ای ویکی نیسسه آماده می که، و د   .\nسی اضاف کردن یا آلشت دئن د همه ویکی یا لطفا [//translatewiki.net/ translatewiki.net] نه به کار بؤریت، ولات نشین کنی پروجه ویکی وارسگر.",
+       "editinginterface": "<strong>زئنار دئن:</strong> شما داریت بلگه ای نه که سی      بیه ویرایشت می کید.",
+       "cascadeprotected": "ای بلگه د ویرایشت محافظت بیه سی یه که {{جمی:$1|وه بلگه یه |ونو بلگه یان}} که ها دش د                 :\n$2",
+       "namespaceprotected": "شما حقی سی ویرایشت بلگه یایی که هان د نومجا  <strong>$1</strong> ناریت.",
+       "customcssprotected": "شما سی ویرایشت ای بلگه سی اس اس اجازه ناریت سی یه که میزونکاری دونسمنیا شخصی یه کاریار هنی ها د وه.",
+       "customjsprotected": "شما سی ویرایشت ای بلگه جاوا اسکریپت اجازه ناریت سی یه که میزونکاری دونسمنیا شخصی یه کاریار هنی ها د وه.",
        "mycustomcssprotected": "شما حق ناریت ای بلگه سی اس اس نه ویرایشت بکید",
        "mycustomjsprotected": "شما حق ناریت ای بلگه جاوا اسکریپت نه ویرایشت بکید",
        "myprivateinfoprotected": "شما حق ناریت دونسمنیا خصوصی نه ویرایشت بکید",
        "mypreferencesprotected": "شما حق ناریت ویجگی یا هنی تونه ویرایشت بکید",
        "ns-specialprotected": "بلگیا ویجه نتونن ویرایشت بوئن",
+       "titleprotected": "ای دیارگر د دروس بیئن وه دس [[کاریار:$1|$1]].\n نهاگری بیه.\nدلیلش ونه\"<em>$2</em>\".",
+       "filereadonlyerror": "نبوئه جانیا \"$1\" آلشت بکیتو سی یه که اماییه گه \"$2\" فقط د حال و بال حننیه.\n\nدیوونداری که یه نه قلف کرده موئه د واشکافت \"$3\" بکیتو.",
        "invalidtitle-knownnamespace": "نوم نامعتور سی نوم جا \"$2\" و نیسه \"$3\"",
        "invalidtitle-unknownnamespace": "نوم نامعتور سی شماره نومجا ناشناس $1 و نیسه \"$2\"",
        "exception-nologin": "نبوئه وارد بوئيد",
+       "exception-nologin-text": "شما وارد [[ویجه:وامین اومائن کاریار|وامین اومائن]] بوئیت سی یه تونستویت که د ای بلگه یا کنشت دسرسی داشتویت.",
        "exception-nologin-text-manual": "خواهشمنیدم که $1 تونسه بوئه د ای بلگه دسرسی داشتوه یا کاری انجوم بیئه.",
+       "virus-badscanner": "سازواره گن:ویروس ناشناس:<em>$1</em>",
        "virus-scanfailed": "زل بیئن شکست حرد($1)",
        "virus-unknownscanner": "ويروس كش ناآشگار",
+       "logouttext": "<strong>شما هنی نریتته وه در.</strong>\n\nد ویرتو با که ویرگه نهو انجومیارتو نه پاکسا نکیت، سی یه پاره ای د بلگه یا ممکنه جوری نشو دئه بوئن چی یه که منیستی  شما هنی هایین وامین.",
        "welcomeuser": "خوش اومايت،$1!",
+       "welcomecreation-msg": "حساوتو دروس بیه.\nد ویرتو نروئه که{{نوم دیارگه}} [[Special:Preferences|preferences]]  خوتونه آلشت بکیت",
        "yourname": "نوم کاریاری:",
        "userlogin-yourname": "نوم كاروری",
        "userlogin-yourname-ph": "نوم کاریاری تو نه وارد بكيد",
        "userlogin-signwithsecure": "د وصل بيئن امن استفاده كو",
        "yourdomainname": "پوشگیر شما:",
        "password-change-forbidden": "شما نتونید پاسوردیانه د ای ویکی آلشت بکید",
+       "externaldberror": "اشتوایی د ارتواط وا رسینه گا پیش اومائه یا ینه که شما اجازه وه هنگوم سازی حساو خارجی تونه ناریت.",
        "login": "اومائن",
        "nav-login-createaccount": " اومائن د سيستم/راس كردن حساو",
-       "loginprompt": "شما وا کوکیانه سی اومائن د {{SITENAME}} کوکیانه فعال بکید.",
        "userlogin": " اومائن د سيستم/راس كردن حساو",
        "userloginnocreate": "اومائن",
        "logout": "رئتن",
        "userlogin-resetlink": "جزییات وامین اومائن تونه د ویر بردیته",
        "userlogin-resetpassword-link": "پاسورد د ویرتو رئته؟",
        "userlogin-helplink2": "هومیاری وا مین اومائن",
-       "userlogin-loggedin": "شما ایسه د عنوان {{جنس:$1|$1}} اومایته وا مین.\nد فرم هاری سی وا مین اومائن وه عنوان کاریار هنی استفاده بکیتو.",
-       "userlogin-createanother": "يه گل حساوهنی راست بكيد",
        "createacct-emailrequired": "نشونی ايميل",
        "createacct-emailoptional": "نشونی ايميل",
        "createacct-email-ph": "نوم نشون ايميلتونه وارد بكيت",
        "nocookiesnew": "حساو کاروری راس بی،اما شما وامئن نیامایئته.{{نوم مالگه}} د کوکیا سی اومائن د سیستم کاروریا استفاده می که.کوکیا شما د کار افتائه.لطفن وا کارشو بونیت، اوسه وا نوم کاروری تازه و پسورد هنی بیایت وا مئن.",
        "nocookieslogin": "{{نوم مالگه}} د کوکیا سی وامئن اومائن کاروریا استفاده می که. کوکیا شما د کار افتائه.\nلطف بکید د کارشو بونیت و دوواره تلاش بکید.",
        "nocookiesfornew": "حساو کاروری راس نبیه، سی یه ایما نتونیم سرچشمه ونه مئکم بکیم.\nمطمئن بوئیت که کوکیا فعال بینه، ای بلگه نه د نو سوار بکید و د نو تلاش بکید.",
+       "nocookiesforlogin": "{{int:nocookieslogin}}",
        "noname": "شما یه گل نوم کاروری خو ناریت",
        "loginsuccesstitle": "اومائن د سيستم موفق بی",
        "loginsuccess": "شما ایسه وارد بیته {{SITENAME}} د دعنوان \"$1\".'",
-       "nosuchuser": "چنی کاروری و نوم  \"$1\" نئیش.\nنوم کاروری وه حرفیا حساس هئ.\nروشت نیسنن تونه وارسی بکید،یا [[ویجه:وامین اومائن کارور/ثوت نام کردن|یه گل حساو تازه راس بکید]].",
+       "nosuchuser": "چنی کاریاری و نوم  \"$1\" نئیش.\nنوم کاریاری وه حرفیا حساس هئ.\nروشت نیسنن تونه وارسی بکید،یا [[ویجه:وامین اومائن کاریار/ثوت نام کردن|یه گل حساو تازه راس بکید]].",
        "nosuchusershort": "چنو کاروری وا ای نوم $1 نی ئیش.\nنیسنن تونه دوواره نئری بکیتو",
        "nouserspecified": "شما باید یه نوم کارور اختصاص بئیتو",
        "login-userblocked": "کارور قلف بیه.وامین اومائن اجازه نی ئن",
        "password-login-forbidden": "وه کار گرتن ای پاسوردو نوم کاروری ممنو بیه.",
        "mailmypassword": "د نۈ وارد كردن رمز",
        "passwordremindertitle": "پاسورد موقت تازه سی {{SITENAME}}",
+       "passwordremindertext": "یه نفر(شات خوتو،د تیرنشون آی پی $1) یه گل رازینه گواردن هنی سی {{نوم دیارگه}}($4) حاسته.یه گل رازینه گواردن موقتی سی کاریاری\"$2\" دروس بیه و د \"$3\" جاگر بیه. ار قصدتو یه بیه،شما واس ایسه روئیت وامین و یه گل رازینه گواردن هنی انتخاو بکید.\nرازینه گورادن موقتی د  {{جمی:$5|یه رو|$5 رو}}  تموم بوئه.\n\nار یه نفر هنی یه حاست داشتوئه،یا ار رازینه گورادن تونه د ویرتو اوما، و ار نحاستیت ونه آلشت بکیت، شما شایت د ای پیغوم تیه پوش بکیت و بحایت د وه کار بسن رازینه گواردن دماترتو دماداری بکیت.",
        "noemail": "هیچ نشونی ایمیلی سی کارور $1 ضفط نبیه.",
        "noemailcreate": "شما باید یه نشونی نومه معتور فراهم بکید",
+       "passwordsent": "یه گل پاسورد هنی سی تیرنشون انجانامه ای که \"$1\" واش ثوت نام کرده بی کل بیه.\nخواهش میکیم هنی رویئت وامین و اوسه بئریتش.",
+       "blocked-mailpassword": "نها آی پی شما سی ویرایشت گرته بیه، و",
+       "eauthentsent": "یه گل انجومانامه پشت راس کردنی د یه گل تیرنشون ویجه کل بیه.\nدما یه که یه گل انجومانامه هنی د حساو کل بوئه، شما واس دما رئنمونی نه د انجومانامه بئریت، سی یه که حساو شما راستکی پشت راست بوئه.",
+       "throttled-mailpassword": "یه گل پسورد دواره زنه بیه ایسه کل بیه، د آخری {{جمی:$1|ساعت|$1 ساعتیا}}.\nسی نهاگری د اذیت دئن،فقط یه گل رازینه گواردن د انجومانامه دواره زنه بیه د هر {{جمی:$1|ساعت|$1 ساعتیا}} کل بیه.",
        "mailerror": "خطا داره کل موئه:$1",
+       "acct_creation_throttle_hit": "سیل کریا ای ویکی د تیرنشون آی پی شما استفاده کردنه د روز دمایی {{جمی:$1|1 حساو|$1 حساویا}} نه دروس کردنه، و وه د بیشترونه صلا دئن د ای دوره گاتی انجوم بیه.\nد نتیجه، سیل کریایی که د ای تیرنشون آی پی استفاده کردنه نمی تونن  حساویا بیشتری د ای گات دروس بکن.",
        "emailauthenticated": "نشونی انجومانامه تونه د $2 سی 3$ مئکم بیه.",
+       "emailnotauthenticated": "تیرنشون انجومانامه شما تا ایسه پشت راسگری نبیه.\nهنی انجومانامه ای سی چیا ری به نها کل نبیه.",
+       "noemailprefs": "یه گل تیرنشون انجومانامه د الویتیاتو سی یه که ای ویجه گیا کار بکن انتخاو بکیت.",
        "emailconfirmlink": "نشونی ايملتو نه محكم بكيد",
+       "invalidemailaddress": "تیرنشون انجومانامه حاستنی نئ شکل وه چوئه خوئی ناره.\nلطفن یه گل تیرنشون چوئه دار وارد بکیت یا ای رشنه گه نه حالی بنیت.",
        "cannotchangeemail": "نشونی ایمیل حساو نتونه د ای ویکی آلشت بوئه.",
        "emaildisabled": "ای مالگه نتونه ایمیل بفرسنه",
        "accountcreated": "حساو راس بی",
+       "accountcreatedtext": "حساو کاریاری سی [[{{ns:کاریار}}:$1|$1]] ([[{{ns:کاریار چک چنه}}:$1|چک چنه]]) دروس بیه.",
        "createaccount-title": "حساو راس کرده سی  {{SITENAME}}",
+       "createaccount-text": "یه نفر وا تیرنشون انجونامه تو یه گل حساو راس کرده{{نوم دیارگه}} ($4) نومشه نیائه\"$2\", با پاسورد \"$3\".\nشما همی ایسه باید روئیت وامین و پاسوردتونه آلشت بکیت.\n\nار شما ای پیغوم نه وش التفات نکیت، د راس بیین ای حساو خطا دروس موئه.",
        "login-throttled": "شما ایسنی فره سی وامین اومائن تلاش کردیته.\n$1 لطفن سی تلاش هنی صبر بکید",
        "login-abort-generic": "اومائن وامین تو شکست حرد-شکست حرده",
+       "login-migrated-generic": "حساو کاریاری شما جا وه جا بیه، و نوم کاریاری شما دیه د ای ویکی نیئش.",
        "loginlanguagelabel": "زون:$1",
+       "suspicious-userlogout": "درحاست وه در رئتن شما انکار بیه سی یه کل وه نظر میا که د یه گل دووارته نیئر گن یا یه گل پروکسی که ها د ویرگه نهو کل بیه",
+       "createacct-another-realname-tip": "نوم راستکی دل به حائه.\nار شما وه نه نهااماییه بکیت، یه سی هوم نسبت دئن وه کاریار   سی کاریاش استفاده بوئه.",
        "pt-login": "وا مین اومائن",
        "pt-login-button": "وا مین اومائن",
        "pt-createaccount": "يه گل حساو راست بكيد",
        "user-mail-no-body": "سی کل کردن ایمیل وا مینونه حالی یا کؤچک بیئن سی دلیل غیر علقمنی تلاش بکید.",
        "changepassword": "پاسورد نه آلشت بكيت",
        "resetpass_announce": "سی تموم کردن وا مین اومائن، شما باید یه گل پاسورد هنی وارد بکیتو.",
+       "resetpass_text": "<!-- یه گل نیسسه ایچه اضاف بکیت -->",
        "resetpass_header": "پاسورد حساوتونه آلشت بکید",
        "oldpassword": "پاسورد قدیمی:",
        "newpassword": "پاسورد تازه:",
        "retypenew": "رمز تازه نه دوواره بنیسید:",
        "resetpass_submit": "پاسور بنیت و وامین بیایت",
        "changepassword-success": "پاسورد شما وا موفقیت آلشت بی",
+       "changepassword-throttled": "شما ایسنی فره سی وامین اومائن تلاش کردیته.\n$1 لطفن سی تلاش هنی صبر بکید",
        "resetpass_forbidden": "پاسوردیا نتونن آلشت بوئن",
        "resetpass-no-info": "شما با بیایت د سیستم تا د ای بلگه دسرسی داشتویت",
        "resetpass-submit-loggedin": "پاسورد نه آلشت بكيت",
        "resetpass-submit-cancel": "انجوم شیوسن",
+       "resetpass-wrong-oldpass": "رازینه گواردن تازه یا موقتی نامعتور.\nشات شما ایسنی یا رازینه گواردن خوتونه د خوئی آلشت دئیته یا یه گل رازینه گواردن موقت هنی درحاست دئیته.",
+       "resetpass-recycled": "لطفن رازینه گواردن خوتونه سی چیا تر د رازینه گواردن ایسنی د نو زنه بکیت",
+       "resetpass-temp-emailed": "شما وا یه گل رازینه موقتی که انجوما گر بیه  اومایته وامین.\nسی تموم کردن اومائن وامین، یه گل رازینه گواردن هنی د ایچه  جاگر بکیت.",
        "resetpass-temp-password": "رمز موقت:",
+       "resetpass-abort-generic": "آلشت دئن رازینه گواردن وا یه گل فره پوش خرو بیه.",
+       "resetpass-expired": "رازینه گواردن شما منقضی بیه. لطفن یه گل رازینه گواردن هنی سی وامین اومائن جاگری بکیت.",
+       "resetpass-expired-soft": "رازینه گواردن شما منقضی بیه و واس د نو زنه با. لطفن یه گل رازینه هنی انتخاو بکیت، یا سی د نو زنه کردن د نهاتر د ایچه \"{{int:resetpass-submit-cancel}}\" بپورنیت.",
+       "resetpass-validity-soft": "زازینه گواردتون تو معتور نئ:$1\n\nلطفن یه گل رازینه گواردن هنی انتخاو بکیت، یا ری ایچه \"{{int:resetpass-submit-cancel}}\" سی د نو زنه کردن وه د نهاتر بپورنیت.",
        "passwordreset": "د نۈ وارد كردن رمز",
+       "passwordreset-text-one": "ای نوم بلگه نه سی گرتن یه گل رازینه گواردن موقتی وا انجومانامه پر بکیت.",
+       "passwordreset-text-many": "{{جمی:$1|یه گل د رشنه گه یا نه سی یه که رازینه گواردن موقتی وا انجومانامه گرته بوئه پر بکیت}}",
        "passwordreset-legend": "د نۈ وارد كردن رمز",
        "passwordreset-disabled": "نو کرد پاسورد د ای ویکی غیرفعال بیه.",
        "passwordreset-emaildisabled": "چی یا هنی ایمیل د ای ویکی غیرفعال بیه.",
        "passwordreset-capture-help": "ار شما ای جعوه نه وارسی بکید. ایمیل و خوئی اوسه که سی کارور کل بیه بوئه بوینیتش.",
        "passwordreset-email": "نشونی ايميل",
        "passwordreset-emailtitle": "جزئیات حساو ها د {{نوم مالگه}}",
+       "passwordreset-emailtext-ip": "یه کسی(شات خوتو، وا تیرنشون آی پی $1) سی د نو زنه کردن رازینه گواردن تو د {{SITENAME}}  درحاست کرده($4).\nسی کاریار «$2» یه گل رازینه گواردن موقتی دروس بیه و و هؤمبراور «$3» ئه.\nار تمارزو تو یه بیه ایسه باید بیایت وامین سامونه و یه گل رازینه گواردن هنی بهاییت\nرازینه گواردن شما د طیل {{PLURAL:$5|یه رو|$5 رو}} باطل بوئه.\n\nار کس هنی چنی درحاستی کرده یا یه که شما رازینه گواردن دمایی خوتونه د ویر اوردیت و تر نمیهایت ونه آلشت بیئت، می تونیت د ای پیغوم تیه پوشی بکیت و همو رازینه گواردن دمایی نه وه کار به ونیت.",
+       "passwordreset-emailtext-user": "کاریار $1 د {{SITENAME}} د نو زنه کردن رازینه گواردن شمانه د{{SITENAME}} ($4) کرده. {{PLURAL:$3|حساو|حساویا}} کاریاری که هان د هار د وا ای تیرنشون انجومانامه ها د ارتواط:\n\n$2\n\n{{PLURAL:$3|ای رازینه گواردن موقت|ای رازینه گواردنیا موقت}} تا {{PLURAL:$5|یه رو|$5 رو}} باطل بوئه.\nار کس هنی چنی درحاستی کرده یا یه که شما رازینه گواردن دمایی خوتونه د ویر اوردیت و تر نمیهایت ونه آلشت بیئت، می تونیت د ای پیغوم تیه پوشی بکیت و همو رازینه گواردن دمایی نه وه کار به ونیت.",
        "passwordreset-emailelement": "نوم کاروری: $1\nپاسورد موقتی: $2",
        "passwordreset-emailsent": "پاسورد هنی سی ایمیل کل بیه.",
        "passwordreset-emailsent-capture": "پاسورد تازه تو د ایمیلتو که د هار نشو دئه بیه کل بیه",
+       "passwordreset-emailerror-capture": "رازینه گواردن د انجومانامه د نو زنه کننه راس بیه، و وه د هار دیاری می که، اما کل بیین وه د{{جنس:$2|کاریار}} شکست حرده:$1",
        "changeemail": "ایمیل تو نه آلشت بکید",
        "changeemail-header": "ایمیل حساوتونه آلشت بکید",
+       "changeemail-text": "ای نوم بلگه نه سی آلشت دئن تیرنشون انجومانامه تو پر بکیت. شما سی پشت راس کردن ای آلشت واس رازینه گواردن خوتونه وارد بکیت.",
        "changeemail-no-info": "شما با بیایت د سیستم تا د ای بلگه دسرسی داشتویت",
        "changeemail-oldemail": "نشونی ایمیل تازه باو:",
        "changeemail-newemail": "نشونی ایمیل تازه",
        "changeemail-password": "شما {{SITENAME}} پاسورد:",
        "changeemail-submit": "آلشت کردن ایمیل",
        "changeemail-cancel": "انجوم شیوسن",
+       "changeemail-throttled": "شما ایسنی فره سی وامین اومائن تلاش کردیته.\n$1 لطفن سی تلاش هنی صبر بکید.",
        "resettokens": "تازه کردن نشونه یا",
+       "resettokens-text": "شما سی صلا دئن دسرسی وه رسینه یا خصوصی که ها د حساو ایچنی تو می تونیت دیارگریا نه د نو زنه بکیت.\n\nشما اوسنی واس ای کار بکیت که رسینه یا شما سی یه کسی تر بئر بیه یا د حساو شما چل بیه.",
        "resettokens-no-tokens": "هیژ نشونه ای سی تازه کردن نئ.",
        "resettokens-legend": "تازه کردن نشونه یا",
        "resettokens-tokens": "نشونه یا:",
        "resettokens-token-label": "$1 (ارزشت تازه: $2)",
+       "resettokens-watchlist-token": "دیارگر سی حردنی تورگه(اتم/آر اس اس) سی [[ویجه:سیل برگ|آلشت دئن بلگه یا د سیل برگتو]]",
        "resettokens-done": "نشونه یا تازه بیه.",
        "resettokens-resetbutton": "نشونه یا انتخاو بیه تازه بوئن",
        "bold_sample": "متن توپر بيه",
        "headline_tip": "قدم 2 خط سر ون",
        "nowiki_sample": "د ایچه یه گل متن بی شلک وارد بکید",
        "nowiki_tip": "شلک ویکی نه ندید بگر",
+       "image_sample": "Example.jpg",
        "image_tip": "جانیا محاط بيه",
+       "media_sample": "Example.ogg",
        "media_tip": "فایل هوم پیوند",
        "sig_tip": "امضا شما و برچسو وخت",
        "hr_tip": "خط افق ونه(سوا سوا دش استفاده کو)",
        "preview": "پيش سيل",
        "showpreview": "پيش نمائش نشون بيئه",
        "showdiff": "آلشتيانه نشون بيئه",
-       "anoneditwarning": "زنهار شما وامین نیومایته.\nنشونی آی پی تو د ویرگار ویرایشت ای بلگه ضفط بوئه",
+       "blankarticle": "<strong>زنئار:</strong> بلگه ای که شما دروس کردیته حالیه.\nار شما د نو ری \"{{int:savearticle}}\" بپورنیت, بلگه وه شکل که هیچ مینونه ای دش نبا دروس بوئه.",
+       "anoneditwarning": "<strong>زئنار:</strong> شما هنی نیوماته وامین. تیرنشون آی پی شما هر گاتی که آلشتی راس بکیت سی کل خلک دیاره. ار <strong>[$1 روئیت وامین]</strong> یا <strong>[$2 یه گل حساو کاریاری راس بکیت]</strong>، ویرایشتیا شما وه نوم کاریاری خوتون دیاری می که، و وا چیا بیتر هنی.",
+       "anonpreviewwarning": "<em>شما نیومائته وامین. تیرنشون آی پی شما د ویرگار ویرایشت ای بلگه اماییه بوئه.</em>",
+       "missingsummary": "<strong>د ویر ونا:</strong> شما هنی یه گل چکسته ویرایشتی نها اماییه نکردیته.\nار شما د نو د ری\"{{int:savearticle}}\" بپورنیت, ویرایشت شما حالی اماییه بوئه.",
        "missingcommenttext": "لطفن د ایچه نظر بیئتو",
+       "missingcommentheader": "<strong>د ویر ونا:</strong> شما هنی یه گل موضوع/سرخط سی ای ویر و باور نها اماییه نکردیته.\nار شما د نو د ری\"{{int:savearticle}}\" بپورنیت, ویرایشت شما حالی اماییه بوئه.",
        "summary-preview": "چکسته پیش سیل:",
        "subject-preview": "پیش سیل موضو سرخط",
        "blockedtitle": "كارور قلف بيه",
+       "blockedtext": "<strong>نوم کاریاری شما یا تیرنشون آی پی شما قلف بیه.</strong>\n\n\n$1 ونه قلف کرده.\nدلیل ها د ایچه<em>$2</em>.\n\nشرو د قلف بیین:$8\nآخر قلف بیین:$6\nکاریار ورتیه قلف بیه:$7\n\nشما می تونیت وا $1 یا [[{{MediaWiki:Grouppage-sysop}}|دیووندار]] هنی پیوند بئریت و سی قلف کردن چک چنه بزنیت.\nالوت د ویر داشتویت که شما نمی تونیت د خصوصیت انجومانامه کل کردن سی ای کاربر استفاده بکیت مئر  یه گل تیرنشون انجومانامه معتور د [[Special:Preferences|ترجیحیا کاریاری]] خوتو معلوم کرده بویت و باید امکان وه کار بستن وه نه داشتویتو\nتیرنشون آی پی ایسنی شما $3 ئه، و نوم دیارکن قلف کردن #$5 ئه.\nلطفا همه جزئیات نه د هر حاسته ای که داریت بوئیت.",
+       "autoblockedtext": "نوم کاریاری شما یا تیرنشون آی پی شما سی یه که یه گل کاریاری هنی وه کارش بسته خودانجومن قلف بیه $1 ونه قلف کرده.\nدلیل ها د ایچه\n\n:<em>$2</em>.\n\nشرو د قلف بیین:$8\nآخر قلف بیین:$6\nکاریار ورتیه قلف بیه:$7\n\nشما می تونیت وا $1 یا [[{{MediaWiki:Grouppage-sysop}}|دیووندار]] هنی پیوند بئریت و سی قلف کردن چک چنه بزنیت.\n\nالوت د ویر داشتویت که شما نمی تونیت د خصوصیت انجومانامه کل کردن سی ای کاربر استفاده بکیت مئر  یه گل تیرنشون انجومانامه معتور د [[Special:Preferences|ترجیحیا کاریاری]] خوتو معلوم کرده بویت و باید امکان وه کار بستن وه نه داشتویت.\n\nتیرنشون آی پی ایسنی شما $3 ئه، و نوم دیارکن قلف کردن #$5 ئه.\nلطفا همه جزئیات نه د هر حاسته ای که داریت بوئیت.",
        "blockednoreason": "هیژ دلیلی دئه نبیه",
        "whitelistedittext": "شما باید $1 سی ویرایشت بلگیا",
+       "confirmedittext": "شما واس دما ویرایشت کردن بلگه یا تیرنشون انجومانامه تونه پشت راس بکیت.\nلطفا یه گل تیرنشون خو سی [[Special:اولویتیا|اولویتیا کاریار]] بنیت.",
        "nosuchsectiontitle": "نبوئه بشخ پیدا بوئه",
+       "nosuchsectiontext": "شما سی ویرایشت کردن جایی که وجود ناره تلاش کردیته.\nشات وه اوسه که شما بلگه نه می دیئته جا وه جا بیه یا پاکسا بیه.",
        "loginreqtitle": "وامین اومائن لازمه",
        "loginreqlink": "اومائن",
        "loginreqpagetext": "$1 لطف بکید بلگه یا هنی نه بوینیت",
        "accmailtitle": "پاسورد کل بی",
+       "accmailtext": "یه گل رازینه گواردن شامسکی سی[[چک چنه کاریار:$1|$1]] سی $2 کل بیه.بوئه وه نه د گات وه کار بستن بلگه اومائن وامین د <em>[[Special:آلشت دئن رازینه گواردن|آلشت دئن رازینه گواردن]]</em>  آلشت دئه بوئه.",
        "newarticle": "تازه",
        "newarticletext": "شما وادما هوم پیوندی هئیت که وجود ناره.\nسی راس کردن بلگه.شرو د نیسنن مئن جعوه هاری بکید(سیل[$1 ] سی دونسمنی بیشتر بکید).\nار شما سی اشتوا کردن هایئن ایچه، دگمه وادما رئتن مرورگر تونه بپورنیت.",
+       "anontalkpagetext": "----",
        "noarticletext": "د تازه یا د ای بلگه متن نی.\nشما تونید د[[Special:Search/{{PAGENAME}}|search for this page title]] بگردید د ای بلگه یا د بلگیا هنی یا<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}   د هنی پی جوری بوئه  logs]</span>   \n   [{{fullurl:{{FULLPAGENAME}}|action=edit}} یای ای بلگه نه ویرایشت بکیدpage]</span>.",
        "noarticletext-nopermission": "د تازه یا د ای بلگه متن نی.\nشما تونید د[[Special:Search/{{PAGENAME}}|search for this page title]] بگردید د ای بلگه یا د بلگیا هنی یا<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}   د هنی پی جوری بوئه  logs]</span>      اما شما حق ناریتو ای بلگه نه راس بکیت",
+       "missing-revision": "وانئیری #$1 د بلگه ای که نومش ونه \"{{FULLPAGENAME}}\" وجود ناره.\n\nشایت بانی جاونه وه وا یه گل ویرگار وه هنگوم نبیه که د یه گل بلگه پاکسا بیه هوم پیوند بیه بوئه.\nشایت جزئیات د   [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log]  پیدا بوئن.",
+       "userpage-userdoesnotexist": "حساو کاریاری\"$1\" ثوت نام نبیه.\nار میهایت ای بلگه نه بسازیتو یا ویرایشت بکیت یه گل وارسی انجوم بئیت.",
        "userpage-userdoesnotexist-view": "حساو کارور\"$1\" ثوت نبیه.",
        "blocked-notice-logextract": "ای کارور ایسنی دسرسی ناره.\nآخری نشون قلف ورودی د هار ایچه سی سرچشمه آماده بیه:",
+       "clearyourcache": "<strong>توجه داشتویت:</strong> نها اماییه کاری, شات مژبور وه وه کار ونن ویرگه نهو دوارته نیئر خوتو سی دیئن ای آلشتیا بوئیت .\n* <strong>فایرفاکس/ سفری:</strong> بپورنیت ری<em>شیفت</em> اوسه که می پورنیت<em>د نو سوار بوئه</em>یا هنی ری <em>Ctrl-F5</em> بپورنیت یا<em>Ctrl-R</em> (<em>⌘-R</em> د سامونه مک)\n* <strong>گوگل کروم:</ strong>بپورنیت ری <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> یا د سامونه)\n* <strong>اینترنت اکسپلورر:</strong> <em>Ctrl</em> واداریت اوسه که می پورنیت ری <em>Refresh</em>, یل بپورنیت ری<em>Ctrl-F5</em>\n* <strong>اوپرا:</strong> ویرگه نهو نه د <em>اوزاریا→ اولویتیا پاک بکیت</em>",
+       "usercssyoucanpreview": "<strong>نکته:</strong> د دگمه \"{{int:showpreview}}\" سی آزماشت کردن سی اس اس تازه دما اماییه کاری استفاده بکیت .",
+       "userjsyoucanpreview": "<strong>نکته:</strong> د دگمه \"{{int:showpreview}}\" سی آزماشت کردن دما اماییه کاری جاوا اسکریپت تازه استفاده بکیت .",
+       "usercsspreview": "<strong>د ویر داشتوئیت که شما فقط می تونیت سی اس اس کاریاری تونه پیش سیل بکیت. وه د ایسنی هنی اماییه نبیه!</strong>",
+       "userjspreview": "<strong>د ویر داشتوئیت که شما فقط می تونیت جاوا اسکریپت کاریاری تونه پیش سیل بکیت. وه د ایسنی هنی اماییه نبیه!</strong>",
+       "sitecsspreview": "<strong>د ویر داشتوئیت که شما فقط می تونیت ای سی اس اس  نه فقط پیش سیل بکیت. وه د ایسنی هنی اماییه نبیه!</strong>",
+       "sitejspreview": "<strong>د ویر داشتوئیت که شما فقط می تونیت ای ای جاوا اسکریپت نه فقط پیش سیل بکیت. وه د ایسنی هنی اماییه نبیه!</strong>",
+       "userinvalidcssjstitle": "<strong>زئنار:</strong> پوسه \"$1\" نیئش.\nسی اس اس جاونه و بلگه یا جاوا اسکریپت  سرون وا حرف کؤچک نه وه کار بسته، همچنو{{ns:کاریار}}:فو/وکتور.سی اس اس چی د ضد{{ns:کاریار}}:فو/وکتور. سی اس اسه.",
        "updated": "(تازه بيه)",
        "note": "'''نيسنن:'''",
        "previewnote": "فقط ای پیش سیل د ویرتو با.\nآلشتیاتو هنی اماییه نبیه.",
        "continue-editing": "رو د راساگه ویرایشت",
+       "previewconflict": "ورگشت پیش سیل د نیسسه د راساگه وارو ویرایشت چی شکل دیار بیین بوئه ار شما وه نه سی اماییه کردن انتخاو بکیت.",
+       "session_fail_preview": "<strong>د بدبختی ما سی یه که رسینه یا جلسه مونه د دس دئیمه نمی تونیم کار پردازشت ویرایشت شمانه انجوم بیئمو.</strong>\nلطفن هنی تلاش بکیت.\nار هنی کار وه دروس کار نکرد،[[Special:UserLogout|اومائن وه در]] نه ازمایشت بکیت و د نو بیایت وامین.",
+       "session_fail_preview_html": "<strong>د بدبختی ما سی یه که رسینه یا جلسه مونه د دس دئیمه نمی تونیم کار پردازشت ویرایشت شمانه انجوم بیئمو.</strong>\nلطفن هنی تلاش بکیت.\n\n<em>سی یه که {{نوم دیارگه}} یه گل ردیف اچ تی ام ال کنشتگر بیه داره، پیش سیل سی یه که د دس حمله یا جاوا اسکریپ د امون با قام کرده بیه..</em>\n\n<strong>ار وه گات قانونی تلاش سی ویرایشته،لطفا د نو تلاش بکیت.</strong>\nار هنی کار وه دروس کار نکرد،[[Special:UserLogout|اومائن وه در]] نه ازمایشت بکیت و د نو بیایت وامین.",
+       "token_suffix_mismatch": "<strong>ویرایشتیا شما سی یه که دووارته نئر شما نیسسه یا نقطه نیائن نه د رازینه امنیتی ویرایشت د یک تیچسه.</strong>\nویرایشت سی یه که د خراو بیئن نیسسه بلگه نهاگری با رد بیه.\nای رخ ون د گاتیایی پیش میا که شما د یه گل رسینه جا پروکسی استفاده می کیت.",
+       "edit_form_incomplete": "<strong>پاره ای د ویرایشتا وه رسینه جا نمی رسن، هنی وارسی بکیت سی یه که بوینیت ویرایشتیا شما خوئه و هنی تلاش بکیت .</strong>",
        "editing": "د حالت ويرايشت$1",
        "creating": "راس كردن $1",
        "editingsection": "د حال ویرایشت$1(بشخ)",
        "explainconflict": "داوسه که شما شرو د ویرایشت ای بلگه کردیته، یه نفر هنی ای بلگه نه آلشت دئه.\nراساگه روئی متن بلگه متن نه چی یه که وجود داشتوه د ور میئره.\nآلشتیا شما د متن هاری نشو دئه هئ.\nشما با آلشتیاتونه د متن که هئش یکی بکید.\nفقط متنی که ها د رو د وختی که شما\"{{رقم:ذخیره گوتار}}\" نه گزارشت می کید اماییه بوئه",
        "yourtext": "متن شما",
        "storedversion": "دوواره دیئن انبار بیه.",
+       "nonunicodebrowser": "<strong>زئنار:دووارته نئر شما وا نیسسه یا یونیکد سازگاری ناره.</strong>\nیه گل راحل وه کار گرته بیه سی یه که شما بلگه یا نه وا امنیت ویرایشت بکیت:\nنیسه یا غیر-ASCII  د پایه رازینه یا 16 تایی دتو نشو دئه بوئه.",
+       "editingold": "<strong>زئنار:شما داریت یه گل وانئری نا به هنگوم بیه نه سی ای بلگه ویرایشت می کید</strong>\nار شما ونه اماییه بکیت،هر آلشتی که د اول سی ای وانئری انجوم بیه گم بوئه.",
        "yourdiff": "فرخيا",
-       "templatesused": "{{جمی:$1|قالو|قالویا}}د ای بلگه استفاده بیه:",
-       "templatesusedpreview": "{{جمی:$1|قالو|قالویا}}استفاده بیه د ای پیش سیل:",
-       "templatesusedsection": "{{جمی:$1|قالو|قالویا}} استفاده بیه د ای بخش:",
+       "copyrightwarning": "لطفن د ویرتو با که ایچه فرض بوئه که همه هومیاریا شما وا{{SITENAME}} د شکل «$2» درتیچ بوئن(سی چیا تر روئیت وه $1).\nار نمیهایت که که نیسسه یاتو که فره ویرایشت بینه و دلحا درتیچ بان، د ایچه کلشو نکیت.<br />\nهمچنو شما داریت وه ایما قول میئیت که خوتو ونونن نویسنیته، یا ونه د یه گل سرچشمه آزاد وا بئرکرد همگونی یا چی وه ؤرداشتیته.\n'''کاریایی که حق درتیچسن (copyright) دارن بی صلا کل نکیت!'''",
+       "copyrightwarning2": "لطفن د ویرتو با که ایچه فرض بوئه که همه هومیاریا شما وا{{SITENAME}} د شکل «$2» درتیچ بوئن(سی چیا تر روئیت وه $1).\nار نمیهایت که که نیسسه یاتو که فره ویرایشت بینه و دلحا درتیچ بان، د ایچه کلشو نکیت.<br />\nهمچنو شما داریت وه ایما قول میئیت که خوتو ونونن نویسنیته، یا ونه د یه گل سرچشمه آزاد وا بئرکرد همگونی یا چی وه ؤرداشتیته.\n'''کاریایی که حق درتیچسن (copyright) دارن بی صلا کل نکیت!'''",
+       "longpageerror": "<strong>خطا:نیسسه شما  {{جمی:$1|یه کلوبایت|$1 کلوبایت}}  درازی نه دئه، که ونو د بیشرونه انازه{{جمی:$2|یه کلوبایت|$2 کلوبایت}} گپترن.</strong>\nنبوئه وه اماییه با.",
+       "readonlywarning": "<strong>زئنار:رسینه گا سی واداشت قلف بیه، سی یه نه که شما ایسه نمی تونیت ویرایشتیاتونه اماییه بکیت.</strong>\nشات شما بحایت که نیسسه خوتونه د جانیا نیسسه ای وردار بدیس بکیت و ونه سی نهاتر اماییه بکیت.\n\nدیوونداری که ونه قلف کرده چنی گوته:$1",
+       "protectedpagewarning": "<strong>زئنار:ای بلگه سی یه پر و پیم بیه که کاریاریایی که دسرسی دیوونداری دارن فقط بتونن دش ویرایشت بکن.</strong>\nآخرین سیائه سی سرچشمه یا د هار اماییه کاری بیه:",
+       "semiprotectedpagewarning": "<strong>د ویر داشتویت:</strong> ای بلگه سی یه که فقط کاریاریا ثوت نام کرده تونستون دش ویرایشت بکه ن پر و پیم بیه.\nآخرین پهرستنومه دئه بیه سی سرچشمه هار نها اماییه بیه:",
+       "cascadeprotectedwarning": "<strong>زئنار:</strong> ای بلگه",
+       "titleprotectedwarning": "<strong>زئنار:ای بلگه پر و پیم بیه سی یه که[[ویجه:نوم گه حقوق گرو|حقوق ویجه]] باید ونه دروس بکن .</strong>\nآخرین پهرستنومه دئه بیه سی سرچشمه دئن نهااماییه بیه:",
+       "templatesused": "{{جمی:$1|چوئه|چوئه یا}}د ای بلگه استفاده بیه:",
+       "templatesusedpreview": "{{جمی:$1|چوئه|چوئه یا}}استفاده بیه د ای پیش سیل:",
+       "templatesusedsection": "{{جمی:$1|چوئه|چوئه یا}} استفاده بیه د ای بخش:",
        "template-protected": "(حمايت بيه)",
        "template-semiprotected": "(نيم-حفاظت بيه)",
        "hiddencategories": "ای بلگه يه اندوم د{{PLURAL:$1|1 hidden category|$1 hidden categories}}: هئ",
-       "nocreatetext": "{{نوم مالگه}} سی راس کردن بلگه یا تازه محدود بیه.\nشما تونید روئیت وادما و بلگه ای که هئیش ویرایشت بکید ، یا [[ویجه:وامین اومائن کارور|بیایت وامین یا یه گل حساو بسازیت]].",
+       "edittools-upload": "-",
+       "nocreatetext": "{{نوم مالگه}} سی راس کردن بلگه یا تازه محدود بیه.\nشما تونید روئیت وادما و بلگه ای که هئیش ویرایشت بکید ، یا [[ویجه:وامین اومائن کاریار|بیایت وامین یا یه گل حساو بسازیت]].",
        "nocreate-loggedin": "شما حق ناریت  که بلگه یا تازه نه راس بکید.",
        "sectioneditnotsupported-title": "ویرایشت بخش حمایت نبوئه",
        "sectioneditnotsupported-text": "ویرایشت بشقی د ای بلگه نئیش.",
        "permissionserrors": "خطا اجازه دئین",
        "permissionserrorstext": "شما حق ناریت ونه انجوم بیئت, سی{{جمی:$1|دلیل|دلیلیا}} نهایی:",
        "permissionserrorstext-withaction": "شما سی $2 اجازه ناریت\nسی دمال کردن{{PLURAL:$1|reason|reasons}}:",
-       "recreate-moveddeleted-warn": "'''زنهار شما بلگه ای که وادما پاک بیه هنی راس کردیته'''\nشما باید دونسه بایت که آیا هنی سی نها گرتن ویرایشت ای بلگه خوئه.\nپاک بیئن و جمشت سی ای بلگه سی راحتی تو فراهم بیه:",
+       "recreate-moveddeleted-warn": "'''زنهار شما بلگه ای که وادما پاکسا بیه هنی راس کردیته'''\nشما باید دونسه بایت که آیا هنی سی نها گرتن ویرایشت ای بلگه خوئه.\nپاکسا بیئن و جمشت سی ای بلگه سی راحتی تو فراهم بیه:",
        "moveddeleted-notice": "ای بلگه پاک بیه.\nپاک بین و جمشت ای بلگه سی سرچشمه دئین فراهم بیه",
        "log-fulllog": "دیئن همه پهرستنومه یا",
+       "edit-hook-aborted": "ویرایشت وا قلاو جلوگری بیه.\nهیچ توضیئ سیش نئ.",
+       "edit-gone-missing": "نبوئه ای بلگه نه وه هنگوم بکیت.\nوه نظر میا که وه پاکسا بیه.",
        "edit-conflict": "مخالفت نه ویرایشت بکید",
+       "edit-no-change": "سی یه که آلشتیا د یه گل نیسسه دروس بیه د ویرایشت شما تیه پوشی بیه.",
+       "postedit-confirmation-created": "بلگه دروس بیه.",
+       "postedit-confirmation-restored": "بلگه د نو اماییه بیه.",
        "postedit-confirmation-saved": "ویرایشتتو اماییه بی",
        "edit-already-exists": "نبوئه یه گل بلگه تازه راس بکید.\nوه هئیش.",
        "defaultmessagetext": "متن پیغوم پیش فرض",
        "content-failed-to-parse": "د یک تیچیسن چیا مئن $2 د مدل $1:$3",
        "invalid-content-data": "دنسمنی مینونه نامعتور",
        "content-not-allowed-here": " مینونه\"$1\" سی بلگه [[$2]] اجازه نه دئه بیه",
+       "editwarning-warning": "ار ای بلگه نه ول بکیت هر آلشتی که دئیته پاک بوئه.\nار شما هاییت وا مین،شما می تونیت ای زئنار نه د \"{{int:prefs-editing}}\" که ها د بخش اولویتیا شما ناکشتگر بکیت.",
        "editpage-notsupportedcontentformat-title": "شلک مینونه دماگری نبیه",
+       "editpage-notsupportedcontentformat-text": "وضع و بار مینونه $1 د مدل مینونه $2 حامین نبوئه.",
        "content-model-wikitext": "ويكی متن",
        "content-model-text": "متن ساده",
        "content-model-javascript": "جاوا اسكريپت",
        "content-model-css": "سی اس اس",
+       "expensive-parserfunction-warning": "<strong>زئنار:</strong>ای بلگه مینونه دار واحونی دستوریا مئن اشکافت فره ای هئ.\n\nانازه و باید د کمتر با$2 {{جمی:$2|واحونی|واحونیا}}، ایسه {{جمی:$1|$1 واحونی|$1 واحونیا}}ئه.",
+       "expensive-parserfunction-category": "بلگه یایی که واحونی پیوندگر خطا گرون فره ای ها دشو",
        "post-expand-template-inclusion-warning": "زنئار قالو شومل انازه ای یه که فره گپه.پاره ای د قالویا نه د بر نگره",
        "post-expand-template-inclusion-category": "بلگیا شومل قالوی ین که انازش د حد اومائه وه در",
        "post-expand-template-argument-warning": "زنهار ای بلگه شومل حداقل یه قالو سی چک چنه یه که انازه فره گپه.\nگپسنیا پاک بینه.",
        "post-expand-template-argument-category": "بلگه شومل قالو چک چنیا د بین رئته",
        "parser-template-loop-warning": "حلقه قالو کشف بیه:[[$1]]",
+       "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": "زیر دسه سی بلگه یایی که د ونو پی یا ووله بیین فره پئشکرد کرده.",
+       "expansion-depth-exceeded-warning": "بلگه د پی یا ووله بیین پئشکرد کرد",
+       "parser-unstrip-loop-warning": "گردوله د فرمونه Unstrip پیدا بیه",
+       "parser-unstrip-recursion-limit": "د بیشترونه د سرچشمه رئتن د دستور Unstrip واروتر رئتیته($1)",
+       "converter-manual-rule-error": "خطا د قانون دسی زون",
+       "undo-success": "نبوئه ویرایشت نه انجومشیو بکیت.\nلطفا ای فرخی که ها د هار نه وارسی بکیت تا یه کاریه که میهات انجوم بئیت، و اوسه آلشتیا هار نه اماییه بکیت سی یه که خمثی کردن ویرایشت نه انجوم بئیت.",
+       "undo-failure": "سی ری به ری بیئن ای ویرایشت وا ویرایشتیا مینجایی، نبوئه ای ویرایشت نه خومثی بکیت.",
+       "undo-norev": "نبوئه ای ویرایشت نه خومثی بکیت سی یه که یا وجود ناره یا پاکسا بیه.",
+       "undo-nochange": "وه نظر میا که ای ویرایشت د ایسنیا خومثی بیه.",
+       "undo-summary": "خومثی بیئن وانئری وا $1[[ویجه:هومیاریا/$2|$2]] ([[چک چنه کاریار:$2|چک چنه]])",
+       "undo-summary-username-hidden": "خومثی بیئن وانئری $1 وا یه گل کاریار قام بیه",
        "cantcreateaccounttitle": "نبوئه حساو راس بکید",
+       "cantcreateaccount-text": "حساو دروس بیه و ا ای تیرنشون آی پی(<strong>$1</strong>) وه دس ای [[کاریار:$3|$3]] قلف بیه.\n\n\nدلیل دئه بیه وا $3 ها د<em>$2</em>",
+       "cantcreateaccount-range-text": "حساو دروس بیه وا تیرنشون آی پی که د پوشینه '''$1''' ، که وه ئم مینونه دار تیرنشون آی پی شما ئم هئ('''$4''')، وه دس [[کاریار:$3|$3]]قلف بیه.\n\nدلیل دئه بیه وا $3، \"$2\" ئه.",
        "viewpagelogs": "سی ای بلگه بوینتو.",
        "nohistory": "هیچ ویرگار ویرایشتی د ای بلگه نئ.",
        "currentrev": "آخرین دوواره دیئن",
        "page_last": "آخر",
        "histlegend": "انتخاو فرخدار:جعویا رادیو نه سی دوواره دیئن و وارسی نشو دار بکید و یا ری رئتن کلیک بکید .<br />\nشرح نوشته: '''({{int:cur}})''' = وا آخری دوواره دیئن فرخ داره '''({{ int:last}})'''= وا دواره دیئن انجوم دئنی فرخ داره  '''{{int:minoreditletter}}''' =ویرایشت کؤچک.",
        "history-fieldset-title": "ویرگار مرور ون",
-       "history-show-deleted": "فقط پاك بيه",
+       "history-show-deleted": "فقط پاكسا بيه",
        "histfirst": "قديمي تري",
        "histlast": "تازه تري",
        "historysize": "({{جمی:$1|1 بایت|$1 بایتیا}})",
        "history-feed-title": "ویرگار دوواره دیئن",
        "history-feed-description": "دوواره دیئن ویرگار سی بلگه د ویکی",
        "history-feed-item-nocomment": "$1 د\n$2",
-       "history-feed-empty": "بلگه حاسته بیه وجود ناره.\nشایت وه د ویکی پاک بیه، یا نومش آلشت بیه.\nسی بلگیا مرتوط تازه [[ویجه:پی جوری|پی جوری د ویکی]] کوششت بکید.",
+       "history-feed-empty": "بلگه حاسته بیه وجود ناره.\nشایت وه د ویکی پاکسا بیه، یا نومش آلشت بیه.\nسی بلگیا مرتوط تازه [[ویجه:پی جوری|پی جوری د ویکی]] کوششت بکید.",
        "rev-deleted-comment": "(ویرایشت چکسته جا وه جا بیه)",
        "rev-deleted-user": "(نوم کاروری جا وه جا بیه)",
        "rev-deleted-event": "(انجوم گر پهرستنومه جا وه جا بیه)",
        "rev-deleted-user-contribs": "[نوم کاروری یا نشونی آی پی جا وه جا بیه - چیا قام بیه د ور هوم یاریانه ویرایشت بکید]",
+       "rev-deleted-text-permission": "وانئری ای بلگه <strong>پاکسا بیه</strong>.\nجزئیات هان د  [{{fullurl:{{#Special:Log}}/پاکسا کردن|بلگه={{نوم کامل بلگه}}}} پهرستنومه پاکساکردن].",
+       "rev-suppressed-text-permission": "وانئری بلگه <strong>پاکساگری</strong>.\nجزئیات هان د  [{{fullurl:{{#Special:Log}}/پاکساگری کردن|بلگه={{نوم کامل بلگه}}}} پهرستنومه پاکساگری کردن].",
+       "rev-deleted-text-unhide": "وانئری ای بلگه <strong>پاکسا بیه</strong>.\nجزئیات هان د  [{{fullurl:{{#Special:Log}}/پاکسا کردن|بلگه={{نوم کامل بلگه}}}} پهرستنومه پاکساکردن].\nشما  هنی تونیت [$1ای وانئری نه بونیت] ار بهاییت.",
+       "rev-suppressed-text-unhide": "وانئری بلگه <strong>پاکساگری</strong>.\nجزئیات هان د  [{{fullurl:{{#Special:Log}}/پاکساگری کردن|بلگه={{نوم کامل بلگه}}}} پهرستنومه پاکساگری کردن].\nشما  هنی تونیت [$1ای وانئری نه بونیت] ار بهاییت.",
+       "rev-deleted-text-view": "وانئری ای بلگه <strong>پاکسا بیه</strong>.\nجزئیات هان د  [{{fullurl:{{#Special:Log}}/پاکسا کردن|بلگه={{نوم کامل بلگه}}}} پهرستنومه پاکساکردن].",
+       "rev-suppressed-text-view": "وانئری بلگه <strong>پاکساگری</strong>.\nجزئیات هان د  [{{fullurl:{{#Special:Log}}/پاکساگری کردن|بلگه={{نوم کامل بلگه}}}} پهرستنومه پاکساگری کردن].",
+       "rev-deleted-no-diff": "شما نمی تونیت ای فرخ نه بونیت سی یه که یه گل د وانئریا <strong>پاکسا بیه</strong>.\nجزئیات هان د  [{{fullurl:{{#Special:Log}}/پاکساگری کردن|بلگه={{نوم کامل بلگه}}}} پهرستنومه پاکساگری کردن].",
+       "rev-suppressed-no-diff": "شما نمی تونیت ای فرخ نه بونیت سی یه که یه گل د وانئریا <strong>پاکسا بیه</strong>.",
+       "rev-deleted-unhide-diff": "وانئری ای بلگه <strong>پاکسا بیه</strong>.\nجزئیات هان د  [{{fullurl:{{#Special:Log}}/پاکسا کردن|بلگه={{نوم کامل بلگه}}}} پهرستنومه پاکساکردن].\nشما  هنی تونیت [$1ای وانئری نه بونیت] ار بهاییت.",
+       "rev-suppressed-unhide-diff": "وانئری ای بلگه <strong>پاکساگری بیه</strong>.\nجزئیات هان د  [{{fullurl:{{#Special:Log}}/پاکساگری کردن|بلگه={{نوم کامل بلگه}}}} پهرستنومه پاکساگری کردن].\nشما  هنی تونیت [$1ای وانئری نه بونیت] ار بهاییت.",
+       "rev-deleted-diff-view": "وانئری ای بلگه <strong>پاکسا بیه</strong>.\nجزئیات هان د  [{{fullurl:{{#Special:Log}}/پاکسا کردن|بلگه={{نوم کامل بلگه}}}} پهرستنومه پاکساکردن].",
+       "rev-suppressed-diff-view": "وانئری بلگه <strong>پاکساگری</strong>.\nجزئیات هان د  [{{fullurl:{{#Special:Log}}/پاکساگری کردن|بلگه={{نوم کامل بلگه}}}} پهرستنومه پاکساگری کردن].",
        "rev-delundel": "آلشت وضئيت ديئن",
        "rev-showdeleted": "نشو دائن",
-       "revisiondelete": "پاک کردن/زنه کردن وانئریا",
+       "revisiondelete": "پاکسا کردن/زنه کردن وانئریا",
        "revdelete-nooldid-title": "وانیری تمارزی بیه نامعتوره",
+       "revdelete-nooldid-text": "شما وانئریا حاسنی نه سی انجوم دئن ای کار ره ون تیاری نکردیته، یا وانئریا تیارگر بیه وجود نارن، یا یه که شما میهایت وانئری ایسنی نه قام بکیت.",
        "revdelete-no-file": "فایل مشقص بیه وجود ناره.",
+       "revdelete-show-file-confirm": "شما د دل میهایت که وانئری پاکسا بیه ای جانیا نه بونیت \"<nowiki>$1</nowiki>\" د $2 تا $3؟",
        "revdelete-show-file-submit": "هری",
        "revdelete-selected-text": "{{جمی:$1|وانیری گل گر بیه|وانیری گل گر بیه}} د [[:$2]]:",
        "revdelete-selected-file": "{{جمی:$1|وانیری گل گر بیه|وانیری گل گر بیه}} د [[:$2]]:",
+       "logdelete-selected": "{{جمی:$1|پهرستنومه رخ ونیا انتخاو بیه|پهرستنومه رخ ونیا انتخاو بیه}}:",
+       "revdelete-text-text": "وانئریا پاکسا بیه هنی د بلگه ویرگار دیاری می کن،اما به شیا مینونه یاشو د مین خلک دیار نیئن.",
+       "revdelete-text-file": "وانئریا پاکسا بیه هنی د بلگه ویرگار دیاری می کن،اما به شیا مینونه یاشو د مین خلک دیار نیئن.",
+       "logdelete-text": "وانئریا پاکسا بیه هنی د بلگه ویرگار دیاری می کن،اما به شیا مینونه یاشو د مین خلک دیار نیئن.",
+       "revdelete-text-others": "دیوونداریا هنی می تونن د مینونه یا قام بیه دسرسی داشتوئن و ونه د نو زنه بکن، مه ر محدودیتیا اضافی میزوکاری بان.",
+       "revdelete-confirm": "لطفن بکید پشت راسی بکیت که میهایت ای کار نه انجوم بیئت، و یه دل بایت که شما نتیجه یا ای کار نه فئمستیته و ای کار نه  مطاوق وا  [[{{MediaWiki:Policy-url}}|the policy]].انجوم می ئیت",
+       "revdelete-suppress-text": "پاکساگری فقط با <strong>تئنا</strong> سی جایایی که هان د هار وه کار گرته بوئه:\n*دونسمنیایی که فره تنادارن\n*دونسمنیا نامناسو شخصی\n*: <em>تیرنشون حونه، شماره تیلیفون،رازینه زایاره ای و چیا تر</em>",
+       "revdelete-legend": "میزونکاری محدودیتیا دیار بیین.",
        "revdelete-hide-text": "متن دوواره دیئن",
        "revdelete-hide-image": "چی یا مئن فایل قام کو",
        "revdelete-hide-name": "آرمون و انجوم گر نه قام بکید",
        "revdelete-hide-comment": "چکسه نه ویرایشت بکید",
        "revdelete-hide-user": "نوم کاروری ویرایشتگر/نشونی آی پی",
+       "revdelete-hide-restricted": "پاکساگری کردن رسینه یا سی دیوونداریا و کسونا تر",
        "revdelete-radio-same": "آلشت نکید",
        "revdelete-radio-set": "قام بیه",
        "revdelete-radio-unset": "دیینی",
+       "revdelete-suppress": "پاکساگری کردن رسینه یا سی دیوونداریا و کسونا تر",
        "revdelete-unsuppress": "محدودیتیانه د وانیریا امباربیه جا وه جا بکید",
        "revdelete-log": "دلیل:",
        "revdelete-submit": "سی {{جمی:$1|وانیری|وانیریا}} انتخاو بیه وه کار بوریتو",
        "revdelete-success": "'''دیئن وانیری وه خوئی وه هنگوم بی.'''",
        "revdelete-failure": "'''دیئن وانیری وه خوئی وه هنگوم نبی:'''$1",
+       "logdelete-success": "<strong>پهرستنومه دیار بیین د خوئی میزونکاری بی.</strong>",
+       "logdelete-failure": "<strong>پهرستنومه دیار بیین نبوئه میزونکاری با.</strong> $1",
        "revdel-restore": "آلشت وضئيت ديئن",
        "pagehist": "ويرگار بلگه",
-       "deletedhist": "ویرگار پاک بیه",
+       "deletedhist": "ویرگار پاکسا بیه",
+       "revdelete-hide-current": "خطا د قام کردن چی که ها د ویرگار $2 ساعت $1: ای نسقه، نسقه ایسنی یه و نبوئه نهوش بکیت.",
+       "revdelete-show-no-access": "خطا د قام کردن چیی که ها د ویرگار $2 ساعت $1: ای نسقه نشون «مئن تنگلا بیئن» داره و شما نمی تونیت وه ش دسرسی داشتویت.",
+       "revdelete-modify-no-access": "خطا د قام کردن چیی که ها د ویرگار $2 ساعت $1: ای نسقه نشون «مئن تنگلا بیئن» داره و شما نمی تونیت وه ش دسرسی داشتویت.",
+       "revdelete-modify-missing": "خطا د قام کردن چی شمارهٔ $1: ای نسقه د رسینه گا نیئش!",
+       "revdelete-no-change": "'''زئنار:''' چی که ها د ویرگا $2 ساعت $1 د دماتر دیاری میزونکاری حاسته بینه داشته.",
+       "revdelete-concurrent-change": "خطا د قام کردن چیی که ها د ویرگار $2 ساعت $1: وه ویر و باور میا که د او گاتی که شما سی آلشت دئن حال و بار وه سعی می کردیته، حال و بارش وه دس کسی تر آلشت دئه بیه.\nلطفن پهرستنومه یا نه وارسی بکیت.",
+       "revdelete-only-restricted": "خطا د قام کردن چیی که ها د ویرگار $2 ساعت $1: شما نیمی تونیت چیانه د ورتیه دیوونداریا قام بکیتو مر یه که یه گل د گزینه یا دیاری کردن هنی نه انتخاو بکیت.",
+       "revdelete-reason-dropdown": "*دلیلیا جاونه سی پاکسا کردن\n** تیه پوشی د حق درتیچ کردن\n** ویر و باور یا دونسمنیا شخصی نامناسو\n** نوم کاریاری نامناسو\n** دونسمنیا فره تنادار",
        "revdelete-otherreason": "دلیل هنی:",
        "revdelete-reasonotherlist": "دلیل هنی",
-       "revdelete-edit-reasonlist": "دلیلیا پاک کردنه نه ویرایشت بکید",
+       "revdelete-edit-reasonlist": "دلیلیا پاکسا کردنه نه ویرایشت بکید",
        "revdelete-offender": "نیسنه وانیری:",
+       "suppressionlog": "پهرستنومه پاکسازی",
+       "suppressionlogtext": "د هار یه گل نوم گه ای هئ که مینونه یا پاکسا بیه و قلف بیه  که هان دش د ورتیه دیوونداریا قام بینه.\n[[ویجه:نوم گه قلف بیه|نوم گه قلف بیئنیا]]نه سی نوم گه ایی که انجومکاریا قدقن بیه و قلف بینیا هان دش بونیت.",
        "mergehistory": "ویرگاریا بلگه نه یکی بکید",
        "mergehistory-header": "ای بلگه وه شما اجازه می ئه که وانیریانه ویرگار سرچشمه بلگه نه د یه گل بلگه تازه سریک سازی بکید.\nمطمئن بویت که ای آلشت د لحاظ ویرگاری د مین بلگه موندگار هئ.",
        "mergehistory-box": "دوواره دیئن دوبلگه ای نه سر یک سازی کو:",
        "mergehistory-from": "بلگه سرچشمه:",
        "mergehistory-into": "بلگه مقصد:",
        "mergehistory-list": "ویرگار ویرایشت سر یک سازی بیئنی",
+       "mergehistory-merge": "نسقه یا هاری که د [[:$1]] وه یک شیوسنی وا[[:$2]] هئن.\nستین دگمه یا رادیویی نه به کار به ونیت سی یه که نسقه یایی نه که د گاتی دماتر دروس بینه انتخاو بکیت.\nد ویرتو با که پورسن ری پیوندیا باعث بوئه که ستین وه شکل اولیه خوش ؤرئرده.",
        "mergehistory-go": "ویرایشتیایی که سریک سازی بوئن نشو بیئه",
        "mergehistory-submit": "سر یک سازی دوواره دیئنیا",
        "mergehistory-empty": "هیپ دوواره دیئنی نبوئه یکی سازی بوئه.",
        "mergehistory-success": "$3 {{جمی:$3|وانیری|وانیریا}} د [[:$1]] وه خوئی د [[:$2]] سریک سازی بی.",
        "mergehistory-fail": "سریک سازی ویرگار انجوم نبوئه، لطفن پینیاریا زمون و بلگه نه د نو وارسی بکید.",
+       "mergehistory-fail-toobig": "نبوئه وه یک شیوسن ویرگان انجوم دئه سی یکه وه بیشتر د محدودیت $1 {{PLURAL:$1|نسقه}}جا وه جا موئه.",
        "mergehistory-no-source": "سرچشمه بلگه $1 وجود ناره.",
        "mergehistory-no-destination": "بلگه مقصد $1 وجود ناره.",
        "mergehistory-invalid-source": "نوم ون بلگه سرچشمه با معتور بوئه.",
        "mergehistory-comment": " [[:$1]]وا[[:$2]] یکی بیه:$3",
        "mergehistory-same-destination": "سرچشمه و بلگه یا مقصد نبوئه یکی بوئن",
        "mergehistory-reason": "دليل:",
+       "mergehistory-revisionrow": "$1 ($2) $3 . . $4 $5 $6",
        "mergelog": "سریک سازی پهرستنومه",
        "pagemerge-logentry": " [[$1]] وا [[$2]] سریک سازی بی (وانیریا که د $3 فره تر هئن)",
        "revertmerge": "بی لوئه",
+       "mergelogpagetext": "شما د هار نوم گه آخرین چیا وه یک شیوسن ویرگار یه بلگه نه د بلگه تر میئنیت.",
        "history-title": "دوواره دیئن ویرگار$1",
        "difference-title": "فرخ مینجا وانیریا \"$1\"",
        "difference-title-multipage": "فرخ مینجا بلگه یا \"$1\" و \"$2\"",
        "showhideselectedversions": "شلک دیئن وانیریا انتخاو بیه نه آلشت بکید",
        "editundo": "رد كردن",
        "diff-empty": "(بی فرق)",
+       "diff-multi-sameuser": "({{PLURAL:$1|یه گل نسقه مینجایی|$1 نسقه یا مینجایی}} وه دس{{PLURAL:$2|کاریاری تر|$2 کاریاریا}} نشو دئه نبیه)",
+       "diff-multi-otherusers": "({{PLURAL:$1|یه گل نسقه مینجایی|$1 نسقه یا مینجایی}} وه دس{{PLURAL:$2|کاریاری تر|$2 کاریاریا}} نشو دئه نبیه)",
        "diff-multi-manyusers": "({{جمی:$1|یه گل وانیری مینجاگرته|$1وانیریا مینجا گرته}} بیشتر د $2 {{جمی:$2|کارور|کاروریا}} نشو دئه نبیه)",
+       "difference-missing-revision": "{{PLURAL:$2|یه گل ویرایشت|$2 ویرایشت}} د فرق مینجا($1) {{PLURAL:$2|پیدا نبی|پیدا نبینه}}.\n\nشایت بانی جاونه وه وا یه گل ویرگار وه هنگوم نبیه که د یه گل بلگه پاکسا بیه هوم پیوند بیه بوئه.\nشایت جزئیات د   [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log]  پیدا بوئن.",
        "searchresults": "نتيجه يا پی جوری",
        "searchresults-title": "نتيجه يا پی جوری سی \"$1\"",
        "titlematches": "عنوان بلگه مطاوقت داره",
+       "textmatches": "هومسازی نیسسه بلگه.",
+       "notextmatches": "نیسسه بلگه هومسازی ناره",
        "prevn": "وادما {{PLURAL:$1|$1}}",
        "nextn": "نيايی {{PLURAL:$1|$1}}",
        "prevn-title": "پيشتر $1 {{PLURAL:$1|نتيجه|نتيجيا}}",
        "searchprofile-images-tooltip": "بگرد سی فايليا",
        "searchprofile-everything-tooltip": "همه محتوا نه پی جوری كو (شاملا بلگيا چك چنه)",
        "searchprofile-advanced-tooltip": "نوم جايا نوم ديار بگرد",
-       "search-result-size": "$1 ({{جمی:$2|بی واچه يل|واچه تكی|واچه يل|$2 واچه يل|$2 واچه}})",
+       "search-result-size": "$1 ({{جمی:$2|1 کلیمه|$2 کلیمه یا}})",
        "search-result-category-size": "{{جمی:$1|1 اندوم|$1 اندومیا}} ({{جمی:$2|1 زیردسه|$2 زیردسه یا}}, {{جمی:$3|1 جانیا|$3 جانیایا}}",
        "search-redirect": "(ورگشتن $1)",
        "search-section": "(بشق $1)",
        "search-relatedarticle": "مرتوط",
        "searchrelated": "مرتوط",
        "searchall": "همه",
-       "showingresultsheader": "{{PLURAL:$5|نتيجه '''$1''' د'''$3'''|نتيجه يا '''$1 - $2''' د'''$3'''}} سيli'''$4'''",
+       "showingresults": "نمائشت بیشترونه {{PLURAL:$1|'''۱''' نتیجه|'''$1''' نتیجه}} د هار، شرو د شماره'''$2'''.",
+       "showingresultsinrange": "نمائشت بیشترونه {{PLURAL:$1|'''۱''' نتیجه|'''$1''' نتیجه}} د هار، شرو د شماره'''$2''' تا شماره '''$3'''.",
+       "search-showingresults": "{{PLURAL:$4|نتیجه یا<strong>$1</strong> د <strong>$3</strong>|نتیجه یا<strong>$1 - $2</strong د <strong>$3</strong>}}",
        "search-nonefound": "هیژ نتیجه یی سی پی جست تو مطاوقت نکرده",
        "powersearch-legend": "پی جوری پیشبرده",
        "powersearch-ns": "نوم جايا نوم ديار بگرد:",
        "powersearch-togglelabel": "چك كردن:",
        "powersearch-toggleall": "همه",
        "powersearch-togglenone": "هيش كوم",
+       "powersearch-remember": "د ویر داشتن انتخاو سی پی جوریا نهایی",
        "search-external": "پی جوری د در",
+       "searchdisabled": "مئن جوری د {{SITENAME}} کنشتگر نئ.\nموقتاً می تونیت مئن جوری Google نه بونیت وه کار.\nد ویرتو با که نتیجه یایی که د مئن جوری وا او روشت وه دست میان شایت وه روز نبان.",
        "search-error": "یه گل خطا سی اوسنی که پی جوری می کردیت اتفاق افتائه:$1",
        "preferences": "خصوصيات هنی",
        "mypreferences": "خصوصيات هنی",
        "prefs-edits": "شماره ویرایشتا:",
+       "prefsnologintext2": "لطف بکیت بیایت وامین و ترجیحات خوتونه آلشت بئیت.",
        "prefs-skin": "پوست",
        "skin-preview": "پیش سیل",
+       "datedefault": "هیچ ترجیحات دش نئ",
+       "prefs-labs": "گزینشتیا آزمایشتی",
        "prefs-user-pages": "بلگیا كارور",
        "prefs-personal": "پروفایل کارور",
        "prefs-rc": "آلشتیا تازه باو",
        "prefs-watchlist": "سیل برگ",
        "prefs-watchlist-days": "روزیا نه د سیل برگ نشو دئه بو:",
+       "prefs-watchlist-days-max": "$1 بیشترونه {{جمی:$1|روز|روزیا}}",
+       "prefs-watchlist-edits": "بیشترونه انازه آلشتیایی که د سیل برگ گپ بیه نشو دئه بیه:",
        "prefs-watchlist-edits-max": "شماره بیشترونه:1000",
+       "prefs-watchlist-token": "نشونه سیل برگ:",
        "prefs-misc": "شيوسن",
        "prefs-resetpass": "پاسورد نه آلشت بكيت",
        "prefs-changeemail": "نشونی ایمیل تو نه آلشت بکید",
        "prefs-email": "چیا هنی انجومانامه",
        "prefs-rendering": "شلک و ری",
        "saveprefs": "اماییه كردن",
+       "restoreprefs": "د نو زنه کردن همه میزونکاریا پیش فرض(د همه جایا)",
        "prefs-editing": "د حالت ويرايشت",
        "rows": "رديفيا:",
        "columns": "ستينا:",
        "searchresultshead": "پی جوری",
+       "stub-threshold": "آستونه ویرایشتیا د یک دیسسه<a href=\"#\" class=\"stub\">ناقص</a> (بایت):",
        "stub-threshold-disabled": "د كار ونن",
        "recentchangesdays": "روزیا آلشتیا تازه باو نه نشو بیه:",
        "recentchangesdays-max": "$1 بیشترونه {{جمی:$1|روز|روزیا}}",
+       "recentchangescount": "انازه ویرایشتیایی که دیاری می که:",
        "prefs-help-recentchangescount": "یه شامل آلشتیا تازه،ویرگاریا بلگه و پهرستنومه یا هئ.",
+       "prefs-help-watchlist-token2": "یه یه گل کلیت رازینه دار سی خوارک تیارگه سیل برگه شمانه.\nهر کسی که شما مئشناسیت می تونه سیل برگ شما نه بوحونه،په ونه هومبئری نکیت.[[Special:ResetTokens|ار لازمه ونه آلشت بئیت ایچه نه بپورنیت]].",
        "savedprefs": "ویجه گیا هنی تو اماییه بیه.",
        "timezonelegend": "وخت راساگه",
        "localtime": "وخت ولاتی:",
        "timezoneuseserverdefault": "وخت راساگه",
+       "timezoneuseoffset": "هنی",
        "servertime": "وخت سرور:",
        "guesstimezone": "وا جاگرد پر بوئه",
        "timezoneregion-africa": "افرقا",
        "prefs-namespaces": "نوم جایا",
        "default": "پيش فرض",
        "prefs-files": "فايلا",
+       "prefs-custom-css": "سی اس اس جاافتائه",
+       "prefs-custom-js": "جاوا نیسسه جاافتائه",
        "prefs-common-css-js": " سی اس اس/جاوا اسکریپت بهر بیه سی همه پوسه یا:",
+       "prefs-reset-intro": "شما می تونیت ای بلگه سی د نو زنه کردن ترجیحات خوت وه شکل تیارگه پیش فرض وه کار بوونیت.\nیه ورئشت پذیر نئ.",
        "prefs-emailconfirm-label": "مئکم کردن ایمیل:",
        "youremail": "ايميل:",
        "username": "{{جنس:$1|نوم کاروری}}:",
        "prefs-memberingroups": "{{جنس:$2|اندوم}}  {{جمی:$1|گرویا|گرویا}}:",
+       "prefs-memberingroups-type": "$1",
        "prefs-registration": "موقع ثوت نام:",
+       "prefs-registration-date-time": "$1",
        "yourrealname": "نوم راستكی:",
        "yourlanguage": "زون:",
        "yourvariant": "محتوا آلشتگر زون:",
+       "prefs-help-variant": "قسه وری انتخاوی شما سی نمائشت مینونه بلگه یا د ای ویکی.",
        "yournick": "امضا تازه:",
+       "prefs-help-signature": "ویر و باوریا نیسسه بیه د بلگه چک چنه باید وا«<nowiki>~~~~</nowiki>» امضا بان؛ ای نشون وه شکل خودانجومی وه امضا شما و مؤر ویرگار تبدیل بوئه.",
+       "badsig": "امضا خؤم بی اعتوار.\nسردیسیا اچ تی ام ال نه وارسی بکیت.",
+       "badsiglength": "امضا شما فره گپه.\nطیل امضا باید کمتر  د $1 {{PLURAL:$1|نیسه}} بوئه.",
        "yourgender": "شما بیشتر میهایت که چه جوری گوته بوئه؟",
        "gender-unknown": "مه میهام چی یی نموئم",
        "gender-male": "وه(پیا) بلگه یا ویکی نه ویرایشت می که",
        "gender-female": "وه(زئنه)بلگه یا ویکی نه ویرایشت می که",
+       "prefs-help-gender": "انجوم دئن ای میزونکاری دل به هاییه.\nنرم افزار سی هشاره درست وه جنسیت و گوتن شما سی کسونا تر د شکل درست وه کار بسن یه گل دستور زون یه نه وه کار می بنه.\nای دونسمنیا سی کل خلک دیارن.",
        "email": "پیومک برقی",
+       "prefs-help-realname": "نوم راستکی دل به حائه.\nار شما ونه وارد بکیت د گات واگردونی وه آرنگیاتو و نسوت دئن ونو وه خوتو د نوم راستکی استفاده بوئه.",
        "prefs-help-email": "نشونی ایمیل اختیاری هئ.اما سی بازجست پاسورد دش نیاز بوئه.شما باید پاسوردتونه د ویر بوریت",
        "prefs-help-email-others": "شما می تونید سی پیوند گرتن تو وا نهایین ایمیل مئن یه هوم پیوند د بلگه کاروری یا بلگه چک چنه تو انتخاو بکید.\nنشونی ایمیلتو وختی که کاروریا هنی وا تو پیوند می گرن دیار نی.",
        "prefs-help-email-required": "نشونی ایمیل لازم هئ.",
        "prefs-i18n": "جهون ولاتمنی",
        "prefs-signature": "امضا",
        "prefs-dateformat": "شلک وخت",
+       "prefs-timeoffset": "جا وه جایی زمونی",
        "prefs-advancedediting": "گزینه یا عمومی",
        "prefs-editor": "ويرايشتگر",
        "prefs-preview": "پیش سیل",
        "prefs-advancedwatchlist": "گزینه یا پیشکرده",
        "prefs-displayrc": "گزینه یا نه نشو بیه",
        "prefs-displaywatchlist": "گزینه یا نه نشو بیه",
+       "prefs-tokenwatchlist": "نشو",
        "prefs-diffs": "فرخیا",
+       "prefs-help-prefershttps": "کارگرایی ای ترجیح نها وامین اومائن نهایی شما وه کار گرته بوئه.",
+       "prefs-tabs-navigation-hint": "نکته: شما می تونید د کلیتیا لادیار کن چپ و راست نه سی رئتن مین تبیا که هان د نوم گه تبیا وه کار بونیت.",
        "email-address-validity-valid": "نشونی ایمیل دیار بیه خوئه",
        "email-address-validity-invalid": "یه گل نشونی ایمیل خو وارد بکید",
+       "userrights": "حقوق دیوونداری کاریار",
        "userrights-lookup-user": "دسه یا کاروری نه دیوون داری بکیت",
        "userrights-user-editname": "نوم كاروری ته وارد كو",
        "editusergroup": "ویرایشت گرویا کاروری",
+       "editinguser": "آلشت دئن حقوق کاریاری کاریار'''[[کاریار:$1|$1]]''' $2",
        "userrights-editusergroup": "ویرایشت گرویا کاروری",
        "saveusergroups": "اماییه کردن گرویا کاریاری",
        "userrights-groupsmember": "اندوم:",
+       "userrights-groupsmember-auto": "اندوم ضمنی:",
+       "userrights-groupsmember-type": "$1",
+       "userrights-groups-help": "شما می تونیت دسه یای که ای کاریار ها دشو آلشت بئیتو:\n* جعوه نشودار وه ای مئنیه که کاریار ها د او دسه.\n* جعوه بی نشون وه ای مئنیه که کاریار د او دسه نئ.\n* نشون* د ای مئنیه که ار شما او دسه نه اضاف بکیتو د نهاتر نموئه ؤردارینش یا برعسگش.",
        "userrights-reason": "دليل:",
        "userrights-no-interwiki": "شما سی ویرایشت حقوق کارور د ویکی یا هنی دسرسی ناریت.",
        "userrights-nodatabase": "پاگا دونسمنی $1 یا نیئش یا د ولاتنشین نئ.",
+       "userrights-nologin": "شما باید وا یه گل حساو کاریاری دیووندار [[Special:UserLogin|روئیت وامین ]] تا تونستوییت حقوق کاریاری کاریار نه گماشته کاری بکیت.",
        "userrights-notallowed": "شما سی اضاف کردن  حقوق کارور یا ورداشتنش دسرسی ناریت.",
        "userrights-changeable-col": "گرویایی که شما تونیت ویرایشت بکید",
        "userrights-unchangeable-col": "گرویایی که شما نتونیت ویرایشت بکید",
+       "userrights-irreversible-marker": "$1*",
+       "userrights-conflict": "تعارض دسرسیا کاریاری! لطف بکیت یه گل وارسی انجوم بئیت و آلشتانه پشت راس بکیت.",
+       "userrights-removed-self": "شما د خوئی حقوق خوتونه ؤرداشتیته، چی یه که مثلا شما تر نمی تونیت وه ای بلگه دسرسی داشتویت.",
        "group": "گرو",
        "group-user": "کاروریا",
        "group-autoconfirmed": "کاروریا خودوادار",
        "group-bot": "بتیا",
        "group-sysop": "مدیریا",
        "group-bureaucrat": "بروکراتیا",
+       "group-suppress": "تیه پایا",
        "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|تیه پا}}",
        "grouppage-user": "{{ns:project}}:کاروریا",
+       "grouppage-autoconfirmed": "{{ns:project}}:کاریار خودانجومکار",
        "grouppage-bot": "{{ns:project}}:بوت یا",
+       "grouppage-sysop": "{{ns:project}}:دیوونداریا",
        "grouppage-bureaucrat": "{{ns:project}}:دیوونداریا",
+       "grouppage-suppress": "{{ns:project}}:تیه پا",
        "right-read": "حنن بلگیا",
        "right-edit": "ویرایشت بلگیا",
+       "right-createpage": "بلگه یا نه راس بکیت(ونو که دشو بلگه یا چک چنه نئ)",
        "right-createtalk": "بلگه یا چک چنه نه راس بکید",
        "right-createaccount": "یه گل حساو کاروری تازه راس بکیت",
+       "right-minoredit": "نشودار کردن همه ویرایشتیا چی حیرده",
        "right-move": "بلگه یا جا وه جا کو",
        "right-move-subpages": "بلگه یا و زیر بلگه یا شونه جا وه جا کو",
        "right-move-rootuserpages": "بلگه یا ریشه ای کارور نه جا وه جا کو",
+       "right-move-categorypages": "دسه بلگه یا نه جا وه جا بکیت",
        "right-movefile": "فایلیا نه جا وه جا کو",
        "right-suppressredirect": "اوسه که بلگه یا د بین رئتنه هیچ واگردونی سی بلگه یا سرچشمه دروس نبیه",
        "right-upload": "سوار کردن فايلا",
+       "right-reupload": "سوارکرد هنی جانیایی که دماتر بئیشه",
+       "right-reupload-own": "سوارکرد هنی جانیایی که د دماتر وه دس همو کاریار سوارکرد بیه.",
+       "right-reupload-shared": "باطل‌کردن ولات نشینی جانیایا هومبئر بیه",
        "right-upload_by_url": "سوار کرد فایلیا د یو آر ال",
+       "right-purge": "پاک کردن مینجاگر بلگه بی یه که بلگه پشت راس کردن دیاری بکه",
+       "right-autoconfirmed": "د محدودیتیا سرعت آی پی-پایه کارگرایی ناره",
+       "right-bot": "باور بیه چی یه گل پردازشت خودانجوم",
+       "right-nominornewtalk": "حیرده ویرایشت بلگه یا چک چنه وه شکلی که باعث گوتن پیغوم تازه نبوئه.",
+       "right-apihighlimits": "سخم بالاتر د وه کار بسن API",
        "right-writeapi": "د نیسنن ای پی آی استفاده بکید",
-       "right-delete": "بلگیا نه پاک کو",
+       "right-delete": "بلگیا نه پاکسا کو",
+       "right-bigdelete": "بلگه یایی که ویرگار گپی دارن پاکسا بکیت",
+       "right-deletelogentry": "پاکسا کردن و ناپاکسا کردن داده واریایی ویجه ای د پهرستنومه",
+       "right-deleterevision": "پاکساکردن و ناپاکساکردن وانئریا ویجه ای د بلگه یا",
+       "right-deletedhistory": "دیئن چیا پاکسا بیه د ویرگار، بی یه که نیسسه ونونه بؤنیت.",
+       "right-deletedtext": "دیئن نیسسه پاکسا بیه و آلشتیایی که هان مینجا وانئریا پاکسا بیه",
        "right-browsearchive": "بلگه یا پاک بیه نه پی جوری کو",
        "right-undelete": "ای بلگه نه حذف نكيد",
+       "right-suppressrevision": "دیئن و زنه کردن وانئریایی بلگه یایی که د دس کاریاریا نهو بینه",
+       "right-viewsuppressed": "دیئن وانئریایی که د تیه هر کاریاری قام بیه",
        "right-suppressionlog": "دیئن پهرستنومه یا خصوصی",
+       "right-block": "کاریاریا هنی د ویرایشت منع بوئن",
+       "right-blockemail": "کاریار نه د کل کردن انجومانامه منع کو",
+       "right-hideuser": "قلف کردن یه گل نوم کاریاری،قام کردن وه د ور تیه کل خلک",
+       "right-ipblock-exempt": "کارگرایی نگرتن د قطع دسرسیا آی پی، خودانجوم یا فاصله دار",
+       "right-proxyunbannable": "کارگرایی نگرتن د قطع دسرسی خودکار پروکسیا",
        "right-unblockself": "خوشه قلف نکید",
+       "right-protect": "آلشت دئن انازه پر و پیم کردن بلگه یا و ویرایشت بلگه یا پر و پیم بیه تافی",
+       "right-editprotected": "ویرایشت بلگه یا پر و پیم بیه چی «{{int:protect-level-sysop}}»",
+       "right-editsemiprotected": "ویرایشت بلگه یا پر و پیم بیه چی «{{int:protect-level-autoconfirmed}}»",
        "right-editinterface": "راوط کارور نه ویرایشت کو",
        "right-editusercssjs": "فایلیا جاوا اسکریپت و سی اس اس کاروریا هنی نه ویرایشت کو",
        "right-editusercss": "فایلیا سی اس اس کاروریا هنی نه ویرایشت کو",
        "right-editmyusercss": "فایلیا سی اس اس کارور خوتو نه ویرایشت کو",
        "right-editmyuserjs": "فایلیا جاوا اسکریپت کارور خوتو نه ویرایشت کو",
        "right-viewmywatchlist": "سیل برگ خوتونه بوینیت",
+       "right-editmywatchlist": "سیل برگ خوتونه ویرایشت بکیت. د ویرتو با که پاره ای د انجومکاریا بی دسرسی ئم می تونن ای بلگه یا نه اضافه بکن.",
        "right-viewmyprivateinfo": "دونسمنیا شصقی خوتونه بوینیت(چی نشونی ایمیل،نوم راستکی)",
        "right-editmyprivateinfo": "دونسمنیا شصقی خوتونه ویرایشت بکید(چی نشونی ایمیل،نوم راستکی)",
+       "right-editmyoptions": "اولویتیا تونه ویرایشت بکیت",
+       "right-rollback": "چواشه کردن سریع ویرایشتیا آخری کاریاری که یه بلگه ویجه نه ویرایشت دئه",
+       "right-markbotedits": "نشودار کردن ویرایشتیا چواشه بیه چی ویرایشتیا یه گل بات",
+       "right-noratelimit": "کارگرا نبیئن د محدودیت سرعت",
+       "right-import": "بلگه یا نه د ویکی هنی وارد بکید",
        "right-importupload": "دئن بلگه یا د یه گل جانیا سوار بیه",
+       "right-patrol": "سردیاری کردن د ویرایشتیا کسونا تر",
+       "right-autopatrol": "سردیاری کردن خودانجوم د ویرایشتیا خوش",
+       "right-patrolmarks": "دیئن سردیس سردیاری کردن د آلشتیا ایسنی",
        "right-unwatchedpages": "دیئن نوم گه بلگه یا دیئه نبیه",
+       "right-mergehistory": "وه یک شیوسن ویرگار ای بلگه",
        "right-userrights": "حقوق همه کاروریانه ویرایشت بکید",
        "right-userrights-interwiki": "حقوق همه کاروریانه د ویکی یا هنی ویرایشت بکید",
        "right-siteadmin": "پاگا دونسمنی نه قلف بکید یا نکید",
+       "right-override-export-depth": "وه در دئن بلگه یایی که بلگه یا هوم پیوند بیه تا پی یا 5 ها دشو",
        "right-sendemail": "سی کاروریا هنی ایمیل کل بکید",
        "right-passwordreset": "پاسورد ایمیلیا د نو دئه بیه نه بوینیت",
        "newuserlogpage": "راس بیه وا کارور",
        "newuserlogpagetext": "یه پهرستنومه راس بیئن کارور هئ.",
+       "rightslog": "پهرستنومه حقوق کاریار",
        "rightslogtext": "یه پهرستنومه آلشتیا حقوق کارور هئ.",
        "action-read": "ای بلگه نه بحون",
        "action-edit": "ای بلگه نه ويرايشت بكيد",
        "action-createpage": "راس کردن بلگیا",
        "action-createtalk": "بلگه یا چک چنه نه راس بکید",
        "action-createaccount": "حساو ای کارور نه راس بکید",
+       "action-history": "ویرگار ای بلگه نه بوینیت",
        "action-minoredit": "ای ویرایشت نه چی یه حیرده ویرایشت نشو بیئت",
        "action-move": "لی بلگه جا وه جا کو",
        "action-move-subpages": "ای بلگه و زیر بلگه یاشه جا وه جا بکید",
        "action-move-rootuserpages": "بلگه یا ریشه ای کارور نه جا وه جا بکید",
+       "action-move-categorypages": "جا وه جا کردن دسه بلگه یا",
        "action-movefile": "ای فایل جا وه جا بکید",
        "action-upload": "ای فایل سوار بکید",
+       "action-reupload": "نیسئین ری جانیا ایسنی",
+       "action-reupload-shared": "باطل کردن ای جانیا ری یه گل گنجینه هومبئر",
        "action-upload_by_url": "ای فایله نه د یو آر ال سوار بکید",
        "action-writeapi": "د نیسنن ای پی آی استفاده بکید",
-       "action-delete": "ای بلگه نه پاک کو",
+       "action-delete": "ای بلگه نه پاکسا کو",
        "action-deleterevision": "ای بازدئین پاک کو",
-       "action-deletedhistory": "ویرگار پاک بیه ای بلگه نه بوینیت",
+       "action-deletedhistory": "ویرگار پاکسا بیه ای بلگه نه بوینیت",
        "action-browsearchive": "بلگه یا پاک بیه نه پی جوری بکید",
        "action-undelete": "ای بلگه نه پاک نکو",
+       "action-suppressrevision": "وانئری و زنه کردن وانئریا پاک بیه",
        "action-suppressionlog": "ای پهرستنومه خصوصی نه بوینیت",
        "action-block": "ای کارور نه د ویرایشت کردن منع کو",
        "action-protect": "ریترازیا حفاظت د ای بلگه نه آلشت بکید",
+       "action-rollback": "چواشه کردن سریع ویرایشتیا آخری کاریاری که یه بلگه ویجه نه ویرایشت دئه",
        "action-import": "بلگه یا نه د ویکی هنی وارد بکید",
        "action-importupload": "بلگه یا نه د فایل سوار بیه وارد بکید",
+       "action-patrol": "سردیاری کردن د ویرایشتیا کسونا تر",
+       "action-autopatrol": "سردیاری کردن د ویرایشتیا خوتو",
        "action-unwatchedpages": "دیئن نوم گه بلگه یا دیئه نبیه",
+       "action-mergehistory": "وه یک شیوسن ویرگار ای بلگه",
        "action-userrights": "حقوق همه کاروریانه ویرایشت بکید",
        "action-userrights-interwiki": "حقوق همه کاروریانه د ویکی یا هنی ویرایشت بکید",
        "action-siteadmin": "پاگا دونسمنی نه قلف بکید یا نکید",
        "enhancedrc-history": "ويرگار",
        "recentchanges": "تغيريا تازه",
        "recentchanges-legend": "گزينه يا آلشتيا تازه",
+       "recentchanges-summary": "دو بیشتر آلشتیا تازباو نه د ویکی نه د ای بلگه پیگری کو.",
+       "recentchanges-noresult": "هیژ آلشتی د طیل دوره دیار بیه وا ای معیاریا یکی نبی.",
        "recentchanges-feed-description": "دو بیشتر آلشتیا تازباو نه د ویکی که ها د هوال حون پیگری کو.",
        "recentchanges-label-newpage": "ای ويرايشت يه بلگه تازه راس كرده",
        "recentchanges-label-minor": "يه ويرايشت كؤچكيه",
        "recentchanges-label-bot": "ای ويرايشت نه يه بوت انجوم ديئه",
        "recentchanges-label-unpatrolled": "ای ويرايشت هنی تيه واداشت نبيه",
+       "recentchanges-label-plusminus": "انازه بلگه وه شمار ای بایتیا آلشت کرده.",
        "recentchanges-legend-heading": "'''میراث:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (همچنو بوینیت [[ویجه:بلگیا تازه|نوم گه بلگیا تازه]])",
+       "recentchanges-legend-plusminus": "(<em>±123</em>)",
        "rcnotefrom": "د هار آلشتیا د $2 هیئن(د بال د $1 نشون دئه بیه)",
        "rclistfrom": "آلشتیا تازه ایی که وا $3 $2 شرو بیه نشونش بئه",
        "rcshowhideminor": "ويرايشتيا کؤچک $1",
        "minoreditletter": "م",
        "newpageletter": "ن",
        "boteditletter": "ب",
+       "unpatrolledletter": "!",
        "number_of_watching_users_pageview": "[$1 دینه {{جمی:$1|کاریار|کاریاریا}}]",
        "rc_categories": "دسه یا نه محدود کو(وا \"|\" جگا بوئن",
        "rc_categories_any": "هرکوم",
+       "rc-change-size": "$1",
        "rc-change-size-new": "$1 {{جمی:$1|بایت|بایتیا}} نها آلشت",
        "newsectionsummary": "/* $1 */ بخش تازه",
        "rc-enhanced-expand": "جزيات نشون بيئه",
        "upload": "بلم گير كردن فايلا",
        "uploadbtn": "سوار کردن فایل",
        "reuploaddesc": "سوار کردن نه انجوم شیو بکیت و د ورئردیت جابلگ سوارکرد",
+       "upload-tryagain": "کل کردن توضیحیا آلشت دئیه بیه جانیا",
        "uploadnologin": "وارد نبیه",
        "uploadnologintext": "لطفن $1 سی سوارکرد جانیایا.",
+       "upload_directory_missing": "نشونگه سوارکرد ($1) وجود ناره و نبوئه دروسش بکی.",
+       "upload_directory_read_only": "نشونگه سوارکرد($1) د لا سرور قاول نیسنن نئ.",
        "uploaderror": "خطا د سوار کردن",
+       "upload-recreate-warning": "'''زئنار: جانیایی که وه ای نومه یا پاکسا بیه یا جا وه جا بیه.'''\n\nسی رائتی، نومگه پاکساگری و جا وه جا کردن ای بلگه ها د هار:",
+       "uploadtext": "دسی دئین جانیایی که  د دماتر سوار بینه روئیت وه  [[Special:FileList|نوم گه جانیایا]] . د نو سوارکردن  د [[Special:Log/upload|نوم گه سوارکردیا]] و پاکساگری جانیایا د [[Special:Log/delete|deletion log]] جاگئر موئه.\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|alt text]]</nowiki></code>''' سی به کار بسن یه گل نسقه 200 پیکسلی  د جانیایی که ها د مینه یه گل جعوه  که ها د لا چپ نیسسه که د وه عبارت alt text چی توضیح وه کار بسه بیه\n*'''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' سی دروس کردن یه گل هوم پیوند سرراست وه جانیا بی یه که جانیا دیاری بکه نوم بلگه هاری سی سوارکرد جانیایا تازه استفاده بکیت.",
+       "upload-permitted": "جورا جانیا مجاز:$1.",
+       "upload-preferred": "جورا جانیا مجاز:$1.",
+       "upload-prohibited": "جورا جانیا مجاز:$1.",
        "uploadlogpage": "سوارکرد",
+       "uploadlogpagetext": "نومگه هاری یه گل نومگه د آخری سوارکرد جانیایا هئ.\nسی د نو سیل کردن[[Special:NewFiles|عسگدونی جانیایا تازه نه]] به ونیت.",
        "filename": "نوم فایل",
        "filedesc": "چكسته",
        "fileuploadsummary": "چکسه",
        "filereuploadsummary": "آلشتیا فایل:",
        "filestatus": "حال و بال کپی رایت",
        "filesource": "سرچشمه:",
+       "ignorewarning": "تیه پوشی د زئنار و اماییه کردن جانیا",
        "ignorewarnings": "د هر زنهار تیه پوشی کو",
+       "minlength1": "نوم جانیا باید حداقل یه حرف داشتوئه.",
+       "illegalfilename": "نوم جانیا «$1» د وه گیرنه نیسه یایی که د نوم بلگه یا صاحاو اجاره نیئن.\nلطفن نوم جانیا نه آلشت بئیت و ونه د نو نوم بنیت.",
+       "filename-toolong": "نوم جانیا شایت گپتر د 240 بایت نبا.",
        "badfilename": "نوم جانیا د \"$1\" آلشت بیه.",
+       "filetype-mime-mismatch": "دماون جانیا «$1.‎» وا نوع MIME وه($2) یکی نئ.",
+       "filetype-badmime": "جانیایی که نوع MIME ونو $1 بوئه سی سوارکرد اجازه دار نیئن.",
+       "filetype-bad-ie-mime": "نبوئه ای جانیانه سوار بکیت سی یه که اینترنت اکسپلورر ونه چی «$1» میشناسه، سی یه که وه یه گل جانیا ناصلادار و شات خطردار با.",
+       "filetype-unwanted-type": "'''«‎.‎$1»''' یه گل جانیا حاستنی نئ.\n{{PLURAL:$3|جانیا ورتیه گر|جانیایا ورتیه گر}} د ای قرارن: $2 .",
+       "filetype-banned-type": "&lrm;'''\".$1\"''' {{PLURAL:$4|یه گل جانیا ناصلاداره|جانیایایی که صلادار نیئن}}.\n{{PLURAL:$3|جانیا صلادار|جانیایا صلادار}} د ای قرارن: $2.",
+       "filetype-missing": "ای جانیا هیچ اضاف کردی ناره(چی \"جی پی جی\")",
        "empty-file": "فایلی که دئی ته حالی بیه.",
        "file-too-large": "فایلی که دئی ته فره گپ بی.",
        "filename-tooshort": "نوم فایل فره کؤچکه.",
+       "filetype-banned": "چنی جانیا قدقه بیه.",
+       "verification-error": "جانیا د ازمایشت پشت راسگری نگوارد.",
+       "hookaborted": "آلشتی که میهاستیت دروس بکیت وا یه گل قلاو اضاف کرد انجوم نگرت.",
        "illegal-filename": "نوم فایل اجاره ندئه بیه.",
+       "overwrite": "نیسنن ری یه گل جانیایی که هیئش صلا ندئه بیه",
        "unknown-error": "یه گل خطا نادیار ری ون کرده.",
+       "tmp-create-error": "نبوئه جانیا موقتی نه راس بکیتو.",
+       "tmp-write-error": "خطا د نیسنن جانیا موقتی.",
+       "large-file": "د تو میهایم که جانیایا د $1 گپتر نبان؛\nانازه ای جانیا $2 ئه.",
+       "largefileserver": "ای جانیا د انازه ای که د وه سرور میزونکاری بیه تا ونه بیئره گپتره.",
+       "emptyfile": "جانیایی که سوار بیه د نظر میا حالی با.\nای مشگل شایت سی خطا انجومیار نویسی د نوم جانیا با.\nلطف بکید که یه نه وارسی بکیت که میهایت ونه وا ای شرایط سوار بکیت.",
+       "windows-nonascii-filename": "ای ویکی حامین دار نوم جانیایا که نیسه یا خاصی نه دارن نئ.",
+       "fileexists": "جانیایی وا ای نوم ایسه هیئش، ار دل مئکم {{GENDER:|نیئت}} که میهایت او جانیا نه آلشت بکیت، لطفن <strong>[[:$1]]</strong> نه وارسی بکیت.\n[[$1|thumb]]",
+       "filepageexists": "بلگه توضیح سی ای جانیا د دماتر د <strong>[[:$1]]</strong> دروس بیه، اما جانیایی وه ای نوم نیئش.\nچکسه ای که وارد می کیت د بلگه توضیح نشو دئه نبوئه.\nسی یه که چکسه شما نشو دئه بوئه، باید ونه وه شکل دسی ویرایشت بکیت.\n[[$1|thumb]]",
+       "fileexists-extension": "جانیایی وه نوم چی ای نوم هیئش: [[$2|thumb]]\n* نوم جانیایی که سوار می کردیت: <strong>[[:$1]]</strong>\n* نوم جانیایی که د دماتر بیئشه: <strong>[[:$2]]</strong>\nمیهایت د یه گل نوم دیارتر استفاده بکیت؟",
+       "fileexists-thumbnail-yes": "د ویر و باور میا که ای جانیا، یه گل عسگ کؤچک بیه (''بن کلیکی'' یا ''thumbnail'') بوئه.\n[[$1|thumb]]\nلطفن جانیا<strong>[[:$1]]</strong> نه وارسی بکیت.\nار جانیایی که وارسی کردیت، همی عسگ د انازه خوشه، نمیحا یه عسگ بن کلیکی اضاف بکیت.",
+       "file-thumbnail-no": "نوم جانیا وا <strong>$1</strong> شرو موئه.\nد ویر و باور میا که ای جانیا، یه گل عسگ ''بندانگشتی'' ''(thumbnail)'' د عسگ گپتر و اصلی با.\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|جانیا|جانیایا}} هاری با:",
+       "file-deleted-duplicate": "یه گل جانیا چی ای جانیا([[:$1]]) د دماتر پاکسا بیه.\nشما واس ویرگارچه پاکسا بیین او جانیانه دما یه که میهایت سوارش بکیت به ونیت.",
+       "file-deleted-duplicate-notitle": "یه گل جانیا هومبراور وا ای جانیا د دماتر پاکسا بیه و عنوانش پاکساگری بیه.\nشما باس د کسی که د دیئن جانیا پاکساگری بیه دسرسی داره، بهایت که شرایط نه دما سوارکردن هنی وارسی بکه.",
+       "uploadwarning": "هشدار سوارکرد",
+       "uploadwarning-text": "لطف بکیت توضیحات جانیا هاری نه آلشت بئیت و د نو تلاش بکیت.",
        "savefile": "جانیا نه اماییه کو",
-       "uploadedimage": "سوارکرد\"[[$1]]\"",
-       "overwroteimage": "یه گل نسقه تازه د \"[[$1]]\" سوار بیه",
        "uploaddisabled": "سوار کردن د کار نئ.",
        "copyuploaddisabled": "سوار کردن وا یو آر ال د کار نئ.",
        "uploaddisabledtext": "سوار کرد فایلیا د کار نئ.",
+       "php-uploaddisabledtext": "سوارکرد جانیایا د پی اچ پی ناکشتگر بیه.\nلطفن میزونکاری سوارکرد جانیا نه وارسی بکیت.",
+       "uploadscripted": "ای بلگه مینونه دار رازینه اچ تی امل یا نیسسه یه که شایت وه ناخوشی وا دوراته نیئر واشکافت با.",
+       "uploadscriptednamespace": "ای جانیا اس‌ وی‌ جی نوم جا غیرقانونی '$1' داره.",
        "uploadinvalidxml": "ایکس ام الی که سوار بیه نبوئه نوتیج با.",
+       "uploadvirus": "د ای جانیا ویروس هئ!\nجزیات:$1",
+       "uploadjava": "ای جانیا یه گل جانیا زیپه که مینونه دار جانیایی د نوع کلاس جاوائه.\nسوارکردن جانیایا جاوا قدقن بیه، سی یه که شایت ونو صلا دور زئن محدودیتیا امنیتی نه بی ئن.",
        "upload-source": "سرچشمه فایل",
        "sourcefilename": "سرچشمه نوم جانیا:",
        "sourceurl": "سرچشمه يو آر ال:",
        "destfilename": "نوم فایل مقصد:",
+       "upload-maxfilesize": "بیشترونه انازه جانیا:$1",
+       "upload-description": "شرح جانیا",
+       "upload-options": "گزینه یا سوارکرد",
        "watchthisupload": "ای جانیا نه بوینیت",
+       "filewasdeleted": "جانیایی وا همی نوم دماتر سوار بیه و نهاش پاکسا بیه\nشما واس $1 نه دما یه که میهایت سوار بکیت بینیتش.",
+       "filename-bad-prefix": "نوم جانیایی که سوار می کیت وا شرو '''$1''' موئه که دماون ویجه سی عسگیا ثوت بیه وا دیربین یا دیجیتاله.\nلطفن یه گل نوم بی تر سی جانیا انتخاو بکیت.",
        "upload-success-subj": "سوار کرد خوش سرانجوم",
        "upload-success-msg": "سوارکرد شما سی [$2] خوو بی.وه د ایچه هئش:[[:{{ns:file}}:$1]]",
        "upload-failure-subj": "مشگل د سوارکردن",
        "upload-failure-msg": "یه گل مشلگل د سوارکردتو سی [$2] بی:$1",
+       "upload-warning-subj": "هشدار سوارکرد",
+       "upload-warning-msg": "د نوم بلگه سوارکرد مشگلی بی [$2]. شما می تونیت د[[Special:Upload/stash/$1|نوم بلگه سوارکرد]] ؤیرذیت تا ای مشگل نه برطرف بکیت.",
        "upload-proto-error": "پروتکل نادروس",
+       "upload-proto-error-text": "سوارکرد د د دیرادیر ائتیاج وه تیرنشونیایی داره که وا <code dir=ltr>http://</code> یا <code dir=ltr>ftp://</code> شرو بان.",
        "upload-file-error": "خطا مینونه",
+       "upload-file-error-text": "گات تلاش سی راس کردن یه گل جانیا موقتی د سرور یه گل خطا مینونه پیش اومائه.\nلطفن وا یه گل [[Special:ListUsers/sysop|دیووندار]] تماس بئریت.",
        "upload-misc-error": "خطا سوار کرد ناشناخته",
+       "upload-misc-error-text": "د گات سوارکرد خطایی نادیاری پیش اومائه.\nلطف بکیت یه دل بایت که تیرنشون اینترنتی خو و د دسرسه و هنی تلاش بکیت.\nار مشگل هنی بیئش وا یه گل [[Special:ListUsers/sysop|دیوونداریا]] تماس بئیریت.",
        "upload-too-many-redirects": "ای یو آر ال د ورگیرنه واگردونیا فرئی هئ",
+       "upload-http-error": "یه گل خطا اچ تی تی پی پیش اومائه:$1",
        "upload-copy-upload-invalid-domain": "ورداشتن سوارکردیا د ای پوشگئر د دسرس نئ.",
+       "backend-fail-stream": "نبوئه جانیا\"$1\" کل بوئه.",
+       "backend-fail-backup": "نبوئه سی \"$1\" پشتجا گرت.",
        "backend-fail-notexists": "فایل $1 وجود ناره.",
-       "backend-fail-delete": "نبوئه جانیا $1 پاک بوئه",
+       "backend-fail-hashes": "گرتن هش یا جانیا سی ری به ری یک نیاین د خوئی انجوم نگرت.",
+       "backend-fail-notsame": "جانیا ناهمتایی ها د $1 .",
+       "backend-fail-invalidpath": "\"$1\" ره خوئی سی امائیه کردن نئ.",
+       "backend-fail-delete": "نبوئه جانیا $1 پاکسا بوئه",
        "backend-fail-describe": "نبوئه گپ دونسمنیا سی جانیا\"$1\" آلشت بوئه.",
+       "backend-fail-alreadyexists": "جانیا \"$1\" ایسه هیئش.",
        "backend-fail-store": "نبوئه جانیا \"$1\" د \"$2\" امبار بوئه.",
+       "backend-fail-copy": "نبوئه جانیا $1 د $2 ورداشته بوئه",
        "backend-fail-move": "نبوئه جانیا \"$1\" د \"$2\" جا وه جا بوئه",
        "backend-fail-opentemp": "نبوئه جانیا موقتی وا بوئه.",
        "backend-fail-writetemp": "نبوئه د جانیا موقتی چی بنیسیت.",
+       "backend-fail-closetemp": "نبوئه جانیا موقتی بسته با.",
        "backend-fail-read": "نبوئه جانیا\"$1\" حنه بوئه.",
+       "backend-fail-create": "نبوئه د جانیا\"$1\" نوشته با.",
+       "backend-fail-maxsize": "نبوئه ری جانیا $1 دونسمنیایی نی سن سی یه که گپتر د{{PLURAL:$2|به بایت|$2 بایت}} ئه.",
+       "backend-fail-readonly": "حامین «$1» د ایسنی د حال و بار فقط حننیه.دلیل دئه بیه ینه: «$2»",
+       "backend-fail-synced": "جانیا «$1» ها د حامین داریا اماییه بیه مینونه دار که حال و بارش لیزنگرته یه.",
+       "backend-fail-connect": "وا حامین دار اماییه «$1» ارتواط جاگیری نبی.",
+       "backend-fail-internal": "خطا نادیاری د حامین دار اماییه «$1»  پیش اوما.",
+       "backend-fail-contenttype": "دیارکرد نوع مینونه جانیا سی اماییه «$1» د انجومشیو بی.",
+       "backend-fail-batchsize": "یه گل دسه مینونه دار $1 {{PLURAL:$1|انجومگری|انجومگری}} جانیا وه حامین اماییه دئه بیه؛ بیشترونه مجاز $2 {{PLURAL:$2|انجومگر|انجومگر}} ئه.",
+       "backend-fail-usable": "امکان حنن یا نیسنن جانیا $1 وجود ناشت سی یه که ری تراز دسرسی خو نئ یا لشک/اماییه دار حاستنی نیئش.",
+       "filejournal-fail-dbconnect": "امکان وصل بیئن د رسینه گا نوشتگه سی حامین داری د اماییه کاری «$1» وجود ناشت.",
+       "filejournal-fail-dbquery": "امکان وصل بیئن د رسینه گا نوشتگه سی حامین داری د اماییه کاری «$1» وجود ناشت.",
+       "lockmanager-notlocked": "نبوئه قلف $1 نه وا بکیت؛ سی یه که وه قلف نبیه.",
        "lockmanager-fail-closelock": "نبوئه قلف جانیا سی \"$1\" بسه بوئه.",
+       "lockmanager-fail-deletelock": "نبوئه قلف جانیا سی \"$1\" پاکسا بوئه.",
+       "lockmanager-fail-acquirelock": "نبوئه سی «$1» قلف وه دس اورد.",
        "lockmanager-fail-openlock": "نبوئه قلف جانیا سی \"$1\" وا بوئه.",
+       "lockmanager-fail-releaselock": "نبوئه قلف «$1» نه وا کرد .",
+       "lockmanager-fail-db-bucket": "امکان ارتواط خو وا رسینه گا قلفیا د اماییه دار $1 وجود ناشت.",
+       "lockmanager-fail-db-release": "نبوئه قلفیا سرور $1 نه وا بکیت.",
+       "lockmanager-fail-svr-acquire": "نبوئه سی «$1» قلف وه دس اورد.",
+       "lockmanager-fail-svr-release": "نبوئه قلفیا سرور $1 نه وا بکیت.",
+       "zip-file-open-error": "د گات واکردن جانیا زیپ سی وارسی مینونه ش یه گل خطا پیش اومائه.",
+       "zip-wrong-format": "جانیا تیار بیه جانیا زیپ نئ.",
+       "zip-bad": "جانیا زیپ خرؤ یا حننی نئ.\nنبوئه مینونه شه د لحاظ امنیتی وه خوئی وارسی کرد.",
+       "zip-unsupported": "جانیا زیپ چیایی نه وه کار بسه که ویکی وارسگر حامین دارشو نئ.\nنبوئه مینونه ونه د لحاظ امنیتی وه خوئی وارسی کرد.",
+       "uploadstash": "اماییه جا سوارکرد",
+       "uploadstash-summary": "ای بلگه سی دسرسی وه جانیایایی یه  که سوار بینه(یا د حالت سوارکردن) ولی تا ایسه د ویکی درتیچ نبینه.ای جانیایا فقط وا کاریاریایی که ونونه سوارکردنه قاول دیئن هئن.",
+       "uploadstash-clear": "پاک کردن جانیایا اماییه بیه",
+       "uploadstash-nofiles": "شما هیژ جانیا اماییه بیه ای ناریت.",
+       "uploadstash-badtoken": "انجوم دئن ای کاریا د خوئی صورت نگرت، شایت سی یه با که اعتوار ویرایشت شما تموم بیه. هنی تلاش بکیت.",
+       "uploadstash-errclear": "پاک کردن جانیایا د خوئی شکل نگرت.",
        "uploadstash-refresh": "نومه گه جانیایا نه د نو تازه کو",
+       "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 سیل بکیت.",
+       "img-auth-notindir": "مسیر حاسته بیه د لشک سوارکرد میزونکاری بیه نئ.",
+       "img-auth-badtitle": "امکان راس کردن یه سرون مجازی د «$1» وجود ناره.",
+       "img-auth-nologinnWL": "شما هنی نیومایته وامین و «$1» د نوم گه اسبئ نیئش.",
        "img-auth-nofile": "فایل $1 وجود ناره.",
+       "img-auth-isdir": "شما سی رسسن وه لشگ «$1» تلاش کردیته.\nتئنا می تونیت وه جانیا دسرسی داشتویت.",
+       "img-auth-streaming": "د حال کل کردن \"$1\".",
+       "img-auth-public": "آلشت ون img_auth.php درده ای د جانیایا یه گل ویکی خصوصیه.\nای ویکی وه عنوان یه گل ویکی خلک من میزونکاری بیه.\nسی امنیت خوتر، img_auth.php ناکنشتگر بیه.",
+       "img-auth-noread": "کاریار وه حنن «$1» دسرسی ناره.",
        "http-invalid-url": "یو آر ال نامعتور:$1",
+       "http-invalid-scheme": "تیرنشونیا اینترنتی وا شمایه «$1» حامین داری نبوئن.",
+       "http-request-error": "درحاست اچ تی تی پی سی یه گل خطا نادیار، انجومشیو بیه.",
        "http-read-error": "خطا د حنن اچ تی تی پی.",
+       "http-timed-out": "گات حاستن اچ تی تی پی وه سر اوما.",
+       "http-curl-error": "خطا د اوردن تیرنشون اینترنتی: $1",
+       "http-bad-status": "د گات حاستن اچ تی تی پی  خطایی پیش اوما: $1 $2",
        "upload-curl-error6": "نبوئه د یو آر ال برسیت",
+       "upload-curl-error6-text": "تیرنشون اینترنتی که دئیته د دسرس نئ.\nلطف بکیت درستیشه و یه نه که تیرنشون اینترنی میزونکاری بیه وارسی بکیت.",
        "upload-curl-error28": "تموم بیئن مئلت سی سوار کرد",
+       "upload-curl-error28-text": "ای دیارگه فره دیر دتو واکنشت نشو دئه.\nلطف بکیت سی یه که دیارگه کنشگتر و ری خطه یه گل وارسی بکیت، اوسه یه گر واستید و هنی تلاش بکیت.\nشایت بیتر با که د گات خلوتری هنی تلاش بکیت.",
        "license": "ليانس دار بيئن",
        "license-header": "د شكل ليسانس دار بيئن",
        "nolicense": "هیچی انتخاو نبیه",
+       "licenses-edit": "گزینه یا مجوز ویرایشت",
        "license-nopreview": "(پیش سیل د دسرس نئ)",
-       "upload_source_file": "(یه گل فایل د انجومیار تو)",
+       "upload_source_url": "(شما یه گل جانیا د یه گل یو آر ال د دسرس خلک و معتور ورچئ کردیته)",
+       "upload_source_file": "(یه گل جانیا د انجومیار تو انتخاو بکیت)",
+       "listfiles-delete": "پاکسا کردن",
        "listfiles-summary": "ای بلگه یا ویجه همه جانیایا سوار بیه نه نشو می ئین.",
        "listfiles_search_for": "پی جوری سی نوم رسانه:",
        "imgfile": "فايل",
        "listfiles_name": "نوم",
        "listfiles_user": "کاریار",
        "listfiles_size": "انازه",
+       "listfiles_description": "شرح",
        "listfiles_count": "نسقیا",
        "listfiles-show-all": "شومل نسقه یا نهاتری عسگیا",
        "listfiles-latestversion": "نسقه تازه",
        "file-anchor-link": "فايل",
        "filehist": "ويرگار فايل",
        "filehist-help": "ری  ويرگاريا بپورنيت تا نسقه مرتوط بونيت.",
-       "filehist-deleteall": "همه نه پاک کو",
+       "filehist-deleteall": "همه نه پاکسا کو",
        "filehist-deleteone": "پاك كردن",
        "filehist-revert": "ورگنین",
        "filehist-current": "تازه باو",
        "filehist-comment": "نظر",
        "imagelinks": "استفاده د فايل",
        "linkstoimage": "دمال بيه {{PLURAL:$1|ديس ونيا بلگه|$1 ديس ون بلگيا}} دای فایل:",
+       "linkstoimage-more": "بیشتر د $1 بلگه د ای جانیا هوم پیوند {{PLURAL:$1|بیه|بینه}}.\nنومگه هاری تئنا {{PLURAL:$1|اولین هوم پیوند|اولین $1 هوم پیوند}} د ای بلگه نه نشو می ئه.\n[[Special:WhatLinksHere/$2|نومگه کامل]] ئم هیئش.",
        "nolinkstoimage": "ایچه هیژ بلگه ای سی هوم پیوند بیئن وا ای فایل نی",
-       "morelinkstoimage": " [[ویجه:چه هوم پیوندی ها ایچه/$1|هوم پیوندیا هنی]]سی ای فایل بونیت.",
+       "morelinkstoimage": " [[ویجه:چه هوم پیوندی ها ایچه/$1|هوم پیوندیا هنی]]سی ای جانیا نه بونیت.",
        "linkstoimage-redirect": "$1 (واگردونی جانیا) $2",
+       "duplicatesoffile": "{{PLURAL:$1|جانیا|جانیایا}} هاری نسقه تکراری ای جانیا {{PLURAL:$1|هئ|هئن}} ([[Special:FileDuplicateSearch/$2|دونسمنیا هنی]]):",
        "sharedupload": "ای جانیا که د $1 هئ شایت د پروجه یا هنی استفاده بیه.",
+       "sharedupload-desc-there": "ای جانیا ها د $1و شایت د پروجه یا هنی وه کار گرته بوئه.\nسی دونسمنیا هنی لطفن [$2 بلگه توضیحیا جانیا] نه سیل بکیت.",
        "sharedupload-desc-here": "فایلی که د $1 شایت د مئن پروجیا هنی استفاده بیه.\nتوضی دباره[$2 file description page] د هار نشو دئئه بیه",
+       "sharedupload-desc-edit": "ای جانیا د $1 ئه و می تونه د پروجه یا هنی وه کار گرت بوئه.\nار حاستیت می تونیت توضیحیا حانیا نه د [$2 بلگه توضیحیا خوش] د اوچه ویرایشت بکیت.",
+       "sharedupload-desc-create": "ای جانیا د $1 ئه و می تونه د پروجه یا هنی وه کار گرت بوئه.\nار حاستیت می تونیت توضیحیا حانیا نه د [$2 بلگه توضیحیا خوش] د اوچه ویرایشت بکیت.",
        "filepage-nofile": "چنو فایلی وا ای نوم نئ.",
+       "filepage-nofile-link": "جانیایی د ای نوم نیئش، اما شما تونیت ونه د [$1 سوار بکیت].",
        "uploadnewversion-linktext": "یه گل نسقه تازه د ای جانیا سوار بکید",
        "shared-repo-from": "د $1",
+       "shared-repo": "یه گنجینه هومبئر",
+       "upload-disallowed-here": "شما نمی تونیت ای جانیانه د نو سوار بکیت",
+       "filerevert": "د سرگرتن سی $1",
+       "filerevert-legend": "د سرگرتن جانیا",
+       "filerevert-intro": "شما د حال و بار لرسن'''[[Media:$1|$1]]''' وه [$4 نسقه ای که ها د ویرگار$2 ساعت $3] هیئت.",
        "filerevert-comment": "دليل:",
+       "filerevert-defaultcomment": "لرسن وه نسقه $1 ساعت $2",
        "filerevert-submit": "ورگنین",
-       "filedelete": "$1 پاک کو",
+       "filerevert-success": "''[[Media:$1|$1]]''' وه[$4 نسقه ای که ها د ویرگار$2 ساعت $3] لرسه بی.",
+       "filerevert-badversion": "نسقه دماتری د ای نسقه وجود ناشت.",
+       "filedelete": "$1 پاکسا کو",
        "filedelete-legend": "فایل نه پاک کو",
+       "filedelete-intro": "شما د حال و بار پاکسا کردن جانیا'''[[Media:$1|$1]]''' وا تموم ویرگارچه وه هیئت.",
+       "filedelete-intro-old": "شما د حال و بار پاکسا کردن نسقه'''[[Media:$1|$1]]''' که ها د ویرگار[$4 $2 ساعت $3] هیئت.",
        "filedelete-comment": "دليل:",
-       "filedelete-submit": "پاك كردن",
-       "filedelete-success": "$1 پاک بیه.",
+       "filedelete-submit": "پاكسا كردن",
+       "filedelete-success": "$1 پاکسا بیه.",
+       "filedelete-success-old": "نسقه'''[[Media:$1|$1]]''' که ها د ویرگار $2 ساعت $3 پاکسا بیه.",
        "filedelete-nofile": "'''$1''' وجود ناره.",
+       "filedelete-nofile-old": "نسقه مال دیاری  بیه ای د '''$1''' وا چیا دئه بیه، وجود ناره.",
        "filedelete-otherreason": "دلیل هنی:",
        "filedelete-reason-otherlist": "دليل هنی",
+       "filedelete-reason-dropdown": "* دلیلیا جاافتائه سی پاکسا کردن\n** تیه پوشی د کپی رایت\n** جانیا تکراری",
        "filedelete-edit-reasonlist": "دلیلیا پاک کردنه نه ویرایشت بکید",
-       "filedelete-maintenance-title": "نبوئه ای فایل پاک بوئه",
+       "filedelete-maintenance": "پاکسا کردن و د نو زنه کردن د گات واداشتن تقریبا ناکشتگر بیه.",
+       "filedelete-maintenance-title": "نبوئه ای فایل پاکسا بوئه",
        "mimesearch": "پی جوری ام آی ام ای",
+       "mimesearch-summary": "وا هومیاری ای بلگه شما می تونیت جانیایایی که حال و بارMIME ویجه ای دارن نه بجوریت.\nدرینده: وه شکلcontenttype/subtype یا contenttype/*&lrm;، چی <code>image/jpeg</code>.",
+       "mimetype": "نوع MIME:",
        "download": "گرتن",
        "unwatchedpages": "بلگه یا ندئیه بیه",
        "listredirects": "نوم گه واگردونیا",
+       "listduplicatedfiles": "نومگه همه جانیایا واگرد دواره اومائه یا",
+       "listduplicatedfiles-summary": "ای نومگه د جانیایا وا نسقه یا ایسنی ای جانیا تکراریه که نسقه یا ایسنی جانیایا هنیه. فقط جانیایا ولات نشین هان د ویر و باور ایما.",
+       "listduplicatedfiles-entry": "[[:جانیا:$1|$1]][[$3|{{PLURAL:$2|یه گل تکرار|$2 تکرار}}]] داره.",
        "unusedtemplates": "قالویا وه کار نبرده بیه.",
+       "unusedtemplatestext": "ای بلگه همه بلگه یایی که هان د نومجا {{ns:template}}و د هیچ بلگه ای وه کار گرته نبینه، نوم بنی می که.\nد ویرتو با که دما یه که بهایت بلگه یا هوم پیوند هنی نه پاکسا بکیت دشو وارسی ای انجوم بئیت.",
        "unusedtemplateswlh": "هوم پیوندیا هنی",
        "randompage": "بلگه بختكی",
+       "randompage-nopages": "هیچ بلگه ای د ای {{PLURAL:$2|نومجا|نومجایا}}  نئ:$1.",
        "randomincategory": "بلگه بختی د ای دسه",
        "randomincategory-invalidcategory": "\"$1\"  نوم دسه معتوری نئ.",
        "randomincategory-nopages": "هیچ بلگه ای د ای  [[:دسه نئ:$1|$1]] دسه.",
-       "randomincategory-selectcategory-submit": "رو",
+       "randomincategory-category": "دسه:",
+       "randomincategory-legend": "بلگه بختی د ای دسه",
        "randomredirect": "واگردونی بختکی",
+       "randomredirect-nopages": "هیچ واگردونی د نومجا \"$1\" نئ.",
        "statistics": "آماريا",
        "statistics-header-pages": "بلگه آماریا",
        "statistics-header-edits": "آماریا نه ویرایشت بکید",
        "statistics-pages": "بلگیا",
        "statistics-pages-desc": "همه بلگه یا د ویکی،د ور گیرنه بلگه یا چک چنه،واگردونیا و چیا هنیه.",
        "statistics-files": "جانیا یا سوار بیه",
+       "statistics-edits": "ویرایشت بلگه یا د گاتی که  {{SITENAME}} دروس بیه",
        "statistics-edits-average": "میانگین ویرایشت یا سی هر بلگه",
        "statistics-views-total": "همه نه بوینیت",
+       "statistics-views-total-desc": "دیئن بلگه یایی که وجود نارن و بلگه یا ویجه د ور گرته نئ",
        "statistics-views-peredit": "هر ویرایشت نه بوینیت",
        "statistics-users": "ثوت نام بیه [[ویجه:نوم گه کاریاریا|کاریاریا]]",
        "statistics-users-active": "کاروریا کارکو",
+       "statistics-users-active-desc": "کاریاریایی که د {{PLURAL:$1|رو|$1 رو}} دماتر کنشتگر بینه",
        "statistics-mostpopular": "بلگه یایی که بیشتر دیئه بینه",
+       "pageswithprop": "بلگه یایی که خاصیت صفحه ها دشو",
+       "pageswithprop-legend": "بلگه یایی که خاصیت صفحه ها دشو",
+       "pageswithprop-text": "ای بلگه نومگه ای یه د بلگه یایی که یه گل ویجه گی د یه بلگه خاص نه وه کار می بنن.",
+       "pageswithprop-prop": "نوم خاصیت:",
        "pageswithprop-submit": "رو",
+       "pageswithprop-prophidden-long": "جزییات قام بیه یه گل نیسه دراز($1)",
+       "pageswithprop-prophidden-binary": "جزییات انازه قام بیه دوتا دوتایی ($1)",
        "doubleredirects": "واگردونیا دوتایی",
+       "doubleredirectstext": "ای بلگه نومگه ای د بلگه واگردونی نه نشو می یه که وه یه گل بلگه واگردونی هنی هشاره می کن.\nهر خط مینونه دار هوم پیوندیا واگردونی اول و دویم و همچنو مقصد واگردونی دویمه، که معمولند بلگه مقصد راستکی یه و اولین واگردونی واس د وه هشاره بکه.\nچیا <del>خط حرده</del> دروس بینه.",
        "double-redirect-fixed-move": "[[$1]]جا وه جا بیه .\nوه خودکارونه وه روز بیه و ایسه وه د[[$2]] واگردونی بیه.",
+       "double-redirect-fixed-maintenance": "برطرف بیین خودانجوم دوتای د [[$1]] وه [[$2]] د مسیر واداشت.",
        "double-redirect-fixer": "تعمیر کننه واگردونی",
+       "brokenredirects": "واگردونیا بی سرانجوم",
        "brokenredirectstext": "واگردونیا نهاتر د بلگه یایی که وجود نارن هوم پیوند بینه.",
        "brokenredirects-edit": "ویرایشت",
-       "brokenredirects-delete": "پاك كردن",
+       "brokenredirects-delete": "پاكسا كردن",
        "withoutinterwiki": "بلگه یایی که هوم پیوند زون نارن",
+       "withoutinterwiki-summary": "بلگه یا هاری وه زون نسقه یا زونا تر هوم پیوند نبیه.",
        "withoutinterwiki-legend": "پیشون",
        "withoutinterwiki-submit": "نشون دائن",
-       "nbytes": "$1{{جمی:$1|كلی|بايت|بايت}}",
-       "ncategories": "{{جمی:$1|دسه|دسه يا}}",
+       "fewestrevisions": "بلگه یایی که کمتری وانئری نه دارن",
+       "nbytes": "$1{{جمی:$1|بايت|بایتیا}}",
+       "ncategories": "$1{{جمی:$1|دسه|دسه يا}}",
        "ninterwikis": "$1 {{جمی:$1|مئن ویکی|مئن ویکیا}}",
        "nlinks": "$1 {{جمی:$1|هوم پیوند|هوم پیوندیا}}",
        "nmembers": "$1 {{PLURAL:$1|اندوم|اندوميا}}",
        "nmemberschanged": "$1 → $2 {{جمی:$2|اندوم|اندومیا}}",
+       "nrevisions": "$1 {{جمس:$1|وانئری|وانئریا}}",
        "nviews": "$1 {{جمی:$1|دیئن|دیئنیا}}",
        "nimagelinks": "$1 {{جمی:$1|بلگه|بلگيا}} استفاده بیه",
        "ntransclusions": "$1 {{جمی:$1|بلگه|بلگيا}} استفاده بیه",
+       "specialpage-empty": "نتیجه ای د ای گزارشت نئ.",
        "lonelypages": "بلگه یا تک منه",
+       "lonelypagestext": "د بلگه یا هاری هیچ بلگه هنی د {{SITENAME}} هوم پیوند نبیه و د هیچ بلگه هنی مین چین نبیه.",
        "uncategorizedpages": "بلگه یا دسه بنی نبیه",
        "uncategorizedcategories": "دسه یا دسه بنی نبیه",
        "uncategorizedimages": "فایلیا دسه بنی نبیه",
        "popularpages": "بلگه یا حاستنی",
        "wantedcategories": "بلگه یا حاستنی",
        "wantedpages": "بلگه یا حاستنی",
+       "wantedpages-badtitle": "سرون نامعتور د کومله نتیجه یا:$1",
        "wantedfiles": "فایلیا حاستنی",
+       "wantedfiletext-cat": "جانیایا هاری وه کار گرته بوئن ولی وجود نارن. همچنو شایت جانیایا وه دری وا یه که ایچه هیئشون نومگه کاری بینه.هر گرینج مثبت دورویی  <del>خط مئوره.</del> به اضافه یه، بلگه یایی که که جانیایا بی وجودن نه د خوشو دارن د [[:$1]] نومگه کاری بینه.",
+       "wantedfiletext-nocat-noforeign": "جانیایا هاری وه کار گرته بوئن ولی نیئشو.",
        "wantedtemplates": "قالویا حاستنی",
        "mostlinked": "بلگه یا که بیشتر هوم پیوند بینه",
        "mostlinkedcategories": "دسه یایی که بیشتر هوم پیوند بیه",
-       "mostlinkedtemplates": "قالویایی که بیشتر هوم پیوند بینه",
+       "mostlinkedtemplates": "چوئه یایی که بیشتر هوم پیوند بینه",
        "mostcategories": "بلگه یا که بیشتر دسه بنی بینه",
        "mostimages": "فایلیایی که بیشتر هوم پیوند بینه",
+       "mostinterwikis": "بلگه یایی که بیشتری مینجا ویکی نه دارن",
+       "mostrevisions": "بلگه یایی که بیشتری وانئری نه دارن",
        "prefixindex": "همه بلگيا وا پيشون",
+       "prefixindex-namespace": "تموم بلگه یا وا دماون(نومجا $1)",
+       "prefixindex-strip": "پاکسا کردن دماون د نومگه",
        "shortpages": "بلگه یا کؤچک",
        "longpages": "بلگه یا گپ",
        "deadendpages": "بلگه یا نابود بیئنی",
+       "deadendpagestext": "بلگه یا هاری وه هیچ بلگه هنی د {{SITENAME}} هوم پیوند نبینه.",
        "protectedpages": "بلگه یا حفاظت بيه",
+       "protectedpages-indef": "فقط پر و پیم بیین یا بی زمون",
+       "protectedpages-cascade": "فقط پر و پیم بیین تافنمایی",
        "protectedpages-noredirect": "واگردونیا قام بیه",
+       "protectedpages-timestamp": "سردیس گات",
        "protectedpages-page": "بلگه",
        "protectedpages-expiry": "تموم بیه آ",
        "protectedpages-performer": "کارور حفاظت بیه",
+       "protectedpages-params": "پارامتریا پر و پیم کردن",
        "protectedpages-reason": "دلیل",
        "protectedpages-unknown-timestamp": "ناشناس",
        "protectedpages-unknown-performer": "کارور ناشناس",
+       "protectedtitles": "سرونیا پر و پیم بیه",
        "listusers": "نوم گه کارور",
        "listusers-editsonly": "فقط کاروریایی که ویرایشت می کن نشو بیه",
+       "listusers-creationsort": "سرجاخودگری د اساس گات دروس بیین",
+       "listusers-desc": "سرجاخودگری د اساس گپ د کؤچک",
+       "usereditcount": "$1{{جمی:$1|ویرایشت|ویرایشتیا}}",
        "usercreated": "{{جنسیت:$3|راس بیه}}د $1 at $2",
        "newpages": "بلگيا نو",
        "newpages-username": "نوم كاروری:",
        "ancientpages": "بلگه یا نهاتر",
        "move": "جاوه جا بوئيت",
        "movethispage": "ای بگله نه جا وه جا كو",
+       "notargettitle": "رسینه جایی نئ",
+       "nopagetitle": "چنی بلگه ای نیئش",
        "pager-newer-n": "{{جمی:$1|وانها تر 1وانها تر $1}}",
        "pager-older-n": "{{جمی:$1|گپسالتر 1|گپسالتر $1}}",
+       "suppress": "پائیئن",
        "booksources": "سرچشمه يل كتاو",
        "booksources-search-legend": "پی جوری سی سرچشمه یا کتاو",
+       "booksources-isbn": "آی اس بی ان:",
        "booksources-go": "رو",
+       "specialloguserlabel": "انجومکار:",
+       "speciallogtitlelabel": "حاستنی(موضوع یا کاریار):",
        "log": "نیسنن رخ ونیا",
        "all-logs-page": "همه پهرستنومه یا عمومی",
+       "logempty": "او چی ای که شما میهایت د پهرستنومه نیئش.",
+       "showhideselectedlogentries": "آلشت دئن ورتیه گر پهرستنومه یا انتخاو بیه",
        "allpages": "همه بلگيا",
        "nextpage": "بلگه نهایی($1)",
        "prevpage": "بلگه دمایی($1)",
+       "allpagesfrom": "بلگه یای که د شرو بینه نشو بیه:",
+       "allpagesto": "بلگه یایی که د تموم بینه نشو بیه.",
        "allarticles": "همه بلگيا",
+       "allinnamespace": "همه بلگه یا($1 نوم جا)",
        "allpagessubmit": "رو",
+       "allpagesprefix": "بلگه یایی که پس نوم دارن نشو بیه:",
        "allpagesbadtitle": "عنوان بلگه حاسته بیه معتور نی،یا  یه گل مئن زونی یا مئن ویکی عنوان غلطه.\nیه شایت شومل یکی با یا بیشتر کاراکتریا نبوئه که سی ای موضوعیا استفاده بوئن",
+       "allpages-bad-ns": "{{نوم دیارگه}} د ای نوم جا نئ \"$1\".",
        "allpages-hide-redirects": "واگردونیا قام بیه",
        "cachedspecial-refresh-now": "دیئن آخری.",
        "categories": "دسه يا",
-       "deletedcontributions": "هومیاریا پاک بیه کارور",
+       "categoriesfrom": "دسه یایی که د شرو بینه نشو بیه:",
+       "special-categories-sort-count": "سرجاخودگری د اساس شمارشت",
+       "special-categories-sort-abc": "سرجاخودگری د اساس الفبا",
+       "deletedcontributions": "هومیاریا پاکسا بیه کارور",
        "deletedcontributions-title": "هومیاریا پاک بیه کارور",
        "sp-deletedcontributions-contribs": "هومیاریا",
+       "linksearch": "هوم پیوند پی جوری خارجی",
+       "linksearch-pat": "سازه یار پی جوری:",
        "linksearch-ns": "نوم جا:",
        "linksearch-ok": "پی جوری",
        "linksearch-line": "$1 داره د $2 هوم پیوند بوئه",
+       "listusersfrom": "کاریاریایی که د شرو بینه نشو بیه:",
        "listusers-submit": "نشو دئن",
        "listusers-noresult": "هیچ کاروری پیدا نبی",
        "listusers-blocked": "(قلف بيه)",
        "activeusers": "نوم گه کاروریا کارکو",
+       "activeusers-from": "کاریاریایی که د شرو بینه نشو بیه:",
        "activeusers-hidebots": "بوتیا قام کو",
        "activeusers-hidesysops": "دیوون داریا نه قام کو",
        "activeusers-noresult": "هیچ کاروری پیدا نبی",
+       "listgrouprights": "حقوق گرو کاریاری",
+       "listgrouprights-key": "Legend:\n* <span class=\"listgrouprights-granted\">دئه بیه د سمت راست</span>\n* <span class=\"listgrouprights-revoked\">انجوم شیو بیه د سمت راست</span>",
        "listgrouprights-group": "دسه",
        "listgrouprights-rights": "حقوقیا",
+       "listgrouprights-helppage": "هومیاری:حقوق گرو",
        "listgrouprights-members": "(نوم گه اندومیا)",
+       "listgrouprights-right-display": "<span class=\"listgrouprights-granted\">$1 <code>($2)</code></span>",
+       "listgrouprights-right-revoked": "<span class=\"listgrouprights-revoked\">$1 <code>($2)</code></span>",
+       "listgrouprights-addgroup": "{{جمی:$2|گرویا|گرویا}} اضاف بکیتو: $1",
+       "listgrouprights-removegroup": "{{جمی:$2|گرویا|گرویا}} ورداریت: $1",
        "listgrouprights-addgroup-all": "همه گرویا نه اضاف کو",
        "listgrouprights-removegroup-all": "همه گرویا نه وردار",
        "listgrouprights-addgroup-self": " {{جمی:$2|گروه|گرویا}} نه د حساو: $1 اضاف کو",
+       "listgrouprights-removegroup-self": "{{جمی:$2|گرویا|گرویا}} نه د حساو ورداریت: $1",
+       "listgrouprights-addgroup-self-all": "همه گرویا نه د حساو خوشو اضاف بکیت",
+       "listgrouprights-removegroup-self-all": "همه گرویا نه د حساو خوشو ورداریت",
+       "listgrouprights-namespaceprotection-header": "محدودیت نومجا",
+       "listgrouprights-namespaceprotection-namespace": "نوم جا",
+       "listgrouprights-namespaceprotection-restrictedto": "دسرسیا مجاز کاریار سی ویرایشت",
+       "trackingcategories": "دما گری دسه یا",
+       "trackingcategories-msg": "دماگری دسه",
+       "trackingcategories-name": "نوم پیغوم",
+       "trackingcategories-desc": "جادیارکنیا گنجایشت دسه",
+       "trackingcategories-nodesc": "هیچ شرحی د دسرس نئ.",
+       "trackingcategories-disabled": "دسه ناکشتگر بیه",
        "mailnologin": "هیپچ نشونی یی کل نبیه",
        "emailuser": "ای كارور نه ايميل كو",
        "emailuser-title-target": "ایمیل سی ای {{جنس:$1|کارور}}",
        "emailpage": "ایمیل کارور",
        "defemailsubject": "{{نوم سیل جا}} ایمیل د کارور \"$1\"",
        "usermaildisabled": "ایمیل کارور د کار افتائه",
+       "usermaildisabledtext": "شما نمی تونیت سی کاریار هنی د ای ویکی انجومانامه کل بکیت",
        "noemailtitle": "هیچ نشونی ایمیلی نئ",
+       "noemailtext": "ای کاریار تیرنشون انجومانامه خووی ناره.",
+       "nowikiemailtext": "ای کاریار میها که د کاریاریا هنی انجومانامه نگره.",
+       "emailnotarget": "نوم کاریاری که وجود ناره یا سی گیرنه نامعتوره",
+       "emailtarget": "یه گل نوم کاریاری سی پذریشتگر وارد بکیت",
        "emailusername": "نوم كاروری:",
        "emailusernamesubmit": "دئن",
+       "email-legend": "کل کردن یه گل انجومانامه سی یه گل کاریار هنی د {{SITENAME}}",
        "emailfrom": "د:",
        "emailto": "سی:",
        "emailsubject": "سرون:",
        "emailccsubject": " پیغومتو سی $1:$2 ورداشته بی",
        "emailsent": "ایمیل کل بیه",
        "emailsenttext": "پیغوم ایمیلی تو کل بیه.",
+       "usermessage-summary": "رئتن د سامونه پیغوم",
        "usermessage-editor": "پیغوم فرسن سیستم",
+       "usermessage-template": "ویکی وارسگر:پیغوم کاریار",
        "watchlist": "سیل برگ",
        "mywatchlist": "سیل برگ",
        "watchlistfor2": "سي $1 $2",
+       "nowatchlist": "شما هیچی د سیل برگ خوتو ناریت",
+       "watchlistanontext": "لطفن بیایت وامین و ویرایشتیا نه د سیل برگتو سیل بکیت.",
        "watchnologin": "وارد نبیه",
+       "addwatch": "اضاف کردن د سیل برگ",
+       "addedwatchtext-short": "بلگه \"$1\" وه سیل برگ شما اضاف بیه.",
+       "removewatch": "جا وه جا کردن د سیل برگ",
+       "removedwatchtext": "بلگه\"[[:$1]]\" د [[Special:سیل برگ|سیل برگ خوتو]] جا وه جا بیه.",
+       "removedwatchtext-short": "بلگه \"$1\" د سیل برگ جا وه جا بیه.",
        "watch": "سيل كردن",
        "watchthispage": "ديئن ای بلگه",
        "unwatch": "ديه نبيه",
        "unwatchthispage": "واداشتن دیئن",
        "notanarticle": "مینونه هیچ بلگه ای نئ",
-       "watchlist-details": "{{جمی:$1|$1 بلگه|$1 بلگیا}} د سیل برگتو هیش بلگه قسه کردن نی .",
+       "notvisiblerev": "آخری وانئری که د دس یه کاریار هنی انجوم بیه پاکسا بیه.",
+       "watchlist-details": "{{جمی:$1|$1 بلگه|$1 بلگیا}} د سیل برگتو هیش بلگه قسه کردن نی.",
        "wlheader-enotif": "وارسیاری ایمیل فعال بیه.",
        "wlheader-showupdated": "بلگه یایی که د آخرین کرتی که شما دشو دیئن کردیته آلشت بینه د <strong>توپر</strong>نشون دئه بینه",
+       "wlnote": "د هار {{PLURAL:$1|آلشت|<strong>$1</strong> آلشتی}} که د {{PLURAL:$2|ساعت|<strong>$2</strong> ساعت}} دماتر انجوم بیه هیئش، ویرگار آخرین واجوری انجام شده موجود است، ویرگار آخری واجوری: $3، $4",
        "wlshowlast": "آخرین$1 ساعتیا $2و روزیا $3 نشو بیئه",
        "watchlist-options": "گزینیا سیل برگ",
        "watching": "د حال دیئن...",
        "unwatching": "د حال ندیئن...",
        "enotif_reset": "همه بلگه یا دیئه بینه نشودار بکید",
        "enotif_impersonal_salutation": "{{نوم سیلجا}} کارور",
+       "enotif_subject_deleted": "{{SITENAME}} بلگه$1 وه دس{{gender:$2|$2}} پاکسا بیه.",
+       "enotif_subject_created": "{{SITENAME}} بلگه$1 وه دس{{gender:$2|$2}} دروس بیه.",
+       "enotif_subject_moved": "{{SITENAME}} بلگه$1 وه دس{{gender:$2|$2}} جا وه جا بیه.",
+       "enotif_subject_restored": "{{SITENAME}} بلگه$1 وه دس{{gender:$2|$2}} د نو زنه بیه.",
+       "enotif_subject_changed": "{{SITENAME}} بلگه$1 وه دس{{gender:$2|$2}} آلشت بیه.",
        "enotif_lastvisited": "همه آلشتیا$1 د اوسه که شما د آخرین بار دیئته بوینیت.",
+       "enotif_lastdiff": "سی دیئن ای آلشتیا $1 نه سیل بکیت.",
        "enotif_anon_editor": "کارو ناشناس$1",
+       "created": "دروس بیه",
+       "changed": "آلشت بیه",
        "deletepage": "پاک کردن بلگه",
        "confirm": "مئكم كردن",
        "excontent": "مینونه :\"$1\" بی",
        "exbeforeblank": "مینونه حالی دمایی:\"$1\" بی",
-       "delete-confirm": "پاک کردن\"$1\"",
+       "delete-confirm": "پاکسا کردن\"$1\"",
        "delete-legend": "پاك كردن",
        "actioncomplete": "عملكرد كامل بيه",
        "actionfailed": "عملكرد شكست حرده",
        "dellogpage": "لاگ پاك كردن",
        "deletionlog": "پهرستنومه پاک بیئن",
+       "reverted": "لرسه د نزیکترین وانئری",
        "deletecomment": "دليل:",
        "deleteotherreason": "دليليا هنی:",
        "deletereasonotherlist": "دلیل هنی",
-       "deletereason-dropdown": "* دلیلیا پاک کردن رسم بیه\n** اسپم\n** خراوکاری\n** رعایت نبین کپی رایت\n** درحاست نیسنه\n** نهاورگشت شکست حرده",
+       "deletereason-dropdown": "* دلیلیا پاکسا کردن رسم بیه\n** اسپم\n** خراوکاری\n** رعایت نبین کپی رایت\n** درحاست نیسنه\n** نهاورگشت شکست حرده",
+       "delete-edit-reasonlist": "دلیلیا پاکسا کردنه نه ویرایشت بکید",
+       "rollback": "چواشه کردن ویرایشتیا",
+       "rollback_short": "چواشه کردن",
        "rollbacklink": "ورگشتن",
+       "rollbackfailed": "چواشه کردن د خوئی انجوم نبی",
+       "editcomment": "ویرایشت چکشه وه: \"''$1''\" بی.",
        "sessionfailure-title": "شکست حردن نشینگه",
        "protectlogpage": "حفاظت کردن",
        "protectedarticle": "حفاظت بيه [[$1]]",
        "modifiedarticleprotection": "ریتراز حفاظت د \"[[$1]]\" آلشت بیه",
        "protect-title": "ریتراز حفاظت د \"$1\" آلشت بیه",
        "prot_1movedto2": "[[$1]] د [[$2]] جا وه جا بی",
+       "protect-norestrictiontypes-title": "بلگه بی حامین گر",
+       "protect-legend": "پشت راس کردن حامین گری",
+       "protectcomment": "دلیل:",
+       "protectexpiry": "تموم بين:",
+       "protect_expiry_invalid": "گات تموم بیین نامعتوره.",
+       "protect_expiry_old": "گات تموم بیین مال دماتره.",
        "protect-default": "همه کاروریا اجازه دارن",
+       "protect-summary-desc": "[$1=$2] ($3)",
+       "protect-summary-cascade": "د حال و بال تافنمایی",
+       "protect-expiry-indefinite": "بی زمون",
        "protect-othertime": "وخت هنی:",
+       "protect-othertime-op": "گات هنی",
+       "protect-otherreason": "دلیل اضافی/هنی:",
+       "protect-otherreason-op": "دلیل هنی",
+       "protect-edit-reasonlist": "دلیلا پر و پیم بیین ویرایشت",
        "protect-expiry-options": "1 ساعت:1 ساعت,1 روز:1 روز,1 هفته:1 هفته,2 هفته:2 هفته,1 ما:1 ما,3 ما:3 ما,6 ما:6 ما,1 سال:1 سال,بی حساو:بی حساو",
        "restriction-type": "دسرسی:",
+       "minimum-size": "انازه کمترونه",
+       "maximum-size": "انازه بیشترونه",
+       "pagesize": "(بایتیا)",
        "restriction-edit": "ويرايشت",
        "restriction-move": "جاوه جا بوئيت",
        "restriction-create": "راس كردن",
        "restriction-upload": "سوار کرد",
+       "restriction-level-sysop": "کلا پر و پیم بیه",
+       "restriction-level-autoconfirmed": "نصم و نیمه پر و پیم بیه",
        "restriction-level-all": "هر ریترازی",
+       "undelete": "دیئن بلگه یا پاکسا بیه",
+       "undeletepage": "دیئن و  ؤرگشتن بلگه یا پاکسا بیه",
+       "viewdeletedpage": "دیئن بلگه یا پاکسا بیه",
+       "undeletebtn": "د نو زنه کردن",
        "undeletelink": "بوين/دوواره آماده با",
        "undeleteviewlink": "ديئن",
+       "undeleteinvert": "انتخاو برعسك بوئه",
        "undeletecomment": "دليل:",
+       "undeletedfiles": "{{PLURAL:$1|1 جانیا|$1 جانیایا}} د نو زنه بیه",
        "cannotundelete": "زنه کردن انجوم نبی:$1",
-       "undelete-search-title": "بلگه یا پاک بیه نه پی جوری کو",
+       "undelete-search-title": "بلگه یا پاکسا بیه نه پی جوری کو",
+       "undelete-search-box": "پی جوری بلگه یا پاکسا بیه",
+       "undelete-search-prefix": "بلگه یایی که وا شرو بیه نشو بیه:",
        "undelete-search-submit": "پی جوری",
        "undelete-error-short": "خطا پاک نبیئن جانیا:$1",
        "undelete-show-file-submit": "هری",
+       "undelete-revision-row": "$1 $2 ($3) $4 . . $5 $6 $7 $8 $9",
        "namespace": "نوم جا:",
        "invert": "انتخاو برعسك بوئه",
        "blanknamespace": "اصلی",
        "month": "د ما(یا زیتر)",
        "year": "د سال",
        "sp-contributions-newbies": "فقط هومیاری یایی که د حساو تازه بیه نشون بئه",
+       "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-talk": "چك چنه",
+       "sp-contributions-userrights": "دیوونداری حقوق کاریار",
        "sp-contributions-search": "سی هومیاریا پی جور با",
        "sp-contributions-username": "نوم نشون آی پی يا نوم كاروری:",
        "sp-contributions-toponly": "فقط ویرایشتیایی که جزئه آخرین دوواره دیئن هئین نشو بیه",
        "whatlinkshere-hidelinks": "هوم پیوندیا $1",
        "whatlinkshere-hideimages": "فایل هوم پیوندیا $1",
        "whatlinkshere-filters": "فيلتريا",
+       "autoblockid": "خود نهاگری #$1",
        "block": "منع کارور",
-       "blockip": "منع کارور",
+       "unblock": "کاریار نهاگری نبیه",
+       "blockip": "نهاگری{{GENDER:$1|کاریار}}",
+       "blockip-legend": "نهاگری کاریار",
+       "ipaddressorusername": "نوم نشون آی پی يا نوم كاروری:",
+       "ipbexpiry": "تموم بين:",
        "ipbreason": "دليل:",
+       "ipbcreateaccount": "نهاگری دروس کردن حساو",
+       "ipbemailban": "نهاگرتن کاریار د کل کردن انجومانامه",
+       "ipbsubmit": "نهاگری ای کاریار",
        "ipbother": "وخت هنی:",
        "ipboptions": "2 ساعتیا:2 ساعت,1 رو:1 رو,3 روزا:3 رو,1 هفته:1 هفته,2 هفته یا:2 هفته,1 ما:1 ما,3 ما:3 میا,6 ما:6 مایا,1 سال:1سال,بی حساو:بی حساو",
        "ipbhidename": "نوم کاروری نه سی ویرایشت یا و نوم گه یا قام کو",
+       "ipb-disableusertalk": "نها ای کاریار نه اوسه که میها د بلگه چک چنه ش ویرایشت بکه و وه قلف بیه بئر",
+       "ipb-confirm": "پشت راس کردن قلف",
+       "badipaddress": "تیرنشون نامعتور آی پی",
+       "blockipsuccesssub": "قلف کردن د خوئی انجوم بی",
+       "ipb-edit-dropdown": "ویرایشت دلیلیا نهاگرتن",
        "unblockip": "کارور منع نبیه",
+       "ipusubmit": "ای قلف نه ؤردار",
        "blocklist": "كاروريا منع بيه",
        "ipblocklist": "كاروريا منع بيه",
        "ipblocklist-legend": "یه گل کارور منع بیه بجوریت",
        "blocklist-timestamp": "چسب ون وخت",
+       "blocklist-reason": "دلیل",
        "ipblocklist-submit": "پی جوری",
+       "ipblocklist-localblock": "نهاگری ولات نشینی",
+       "ipblocklist-otherblocks": "هنی{{PLURAL:$1|نهاگرتن|نهاگرتنیا}}",
+       "infiniteblock": "بی زمون",
+       "emailblock": "انجومانامه ناکشتگر بیه",
        "blocklist-nousertalk": "نبوئه بلگه چک چنه خوتونه ویرایشت بکید",
        "ipblocklist-empty": "جاگه نوم گه حالیه",
        "blocklink": "بسته بوئه",
        "unblocklink": "بی قطی",
        "change-blocklink": "اجازه نديئن سی  آلشت",
        "contribslink": "هومكاری",
+       "emaillink": "انجومانامه نه کل کو",
        "blocklogpage": "قلف",
        "blocklogentry": " [[$1]] وا یه گل وخت تموم بیئن $2 و $3  قلف بیه",
        "block-log-flags-nocreate": "حساو راس کردن عاجز بیه.",
+       "block-log-flags-noemail": "انجومانامه ناکشتگر بیه",
        "block-log-flags-nousertalk": "نبوئه بلگه چک چنه خوتونه ویرایشت بکید",
+       "block-log-flags-hiddenname": "نوم کاروری قام بیه",
+       "ipb_already_blocked": "\"$1\" ایسه نهاگری بیه.",
+       "ipb-otherblocks-header": "هنی{{PLURAL:$1|نهاگرتن|نهاگرتنیا}}",
+       "ip_range_invalid": "پوشگر نامعتور آی پی",
+       "proxyblocker": "قلف کننه پروکسی",
+       "sorbs": "دی ان اس بی ال",
        "lockdb": "قلف کردن رسینه گا",
+       "unlockdb": "رسینه گا قلف نبیه",
        "unlockconfirm": "هره، مه واقعند میهام که رسینه گا وا بوئه.",
+       "lockbtn": "قلف کردن رسینه گا",
        "unlockbtn": "رسینه گا قلف نبیه",
        "lockdbsuccesssub": "رسینه گا د خوئی قلف بیه",
+       "unlockdbsuccesssub": "قلف رسینه گا ؤرداشته بیه",
        "move-page": "$1 جا وه جا کو",
+       "move-page-legend": "بلگه نه جا وه جا کو",
+       "movearticle": "جا وه جا کردن بلگه:",
        "movenotallowed": "شما وه جا وه جا کردن بلگه دسرسی ناریت",
        "movenotallowedfile": "شما وه جا وه جا کردن جانیایا دسرسی ناریت",
+       "newtitle": "سی سرون هنی:",
        "movepagebtn": "بلگه جا وه جا کو",
+       "pagemovedsub": "د خوئی جا وه جا بیه",
        "movepage-moved-redirect": "یه گل واگردونی دروس بیه.",
        "movelogpage": "جاوه جا کردن",
        "movelogpagetext": "د هار یه گل نوم گه د جا وه جایی یا بلگه هئ",
+       "movereason": "دلیل:",
        "revertmove": "لرستن",
-       "delete_and_move": "پاک و جا وه جا بوئه",
+       "delete_and_move": "پاکسا و جا وه جا بوئه",
+       "delete_and_move_confirm": "هری بلگه نه پاکسا کو",
        "export": "وه صحرا ديئن بلگيا",
+       "exportall": "وه صحرا ديئن همه بلگيا",
+       "export-submit": "وه در ديئن",
+       "export-addcat": "اضاف کو",
+       "export-addns": "اضاف كو",
        "export-download": "ذخیره کردن جانیا",
+       "export-templates": "شامل چوئه یا",
+       "allmessages": "سامونه پیغومیا",
        "allmessagesname": "نوم",
        "allmessagesdefault": "سفارشت متنی پيش فرض",
+       "allmessages-filter-legend": "فیلتر",
+       "allmessages-filter-unmodified": "آلشت نبیه",
+       "allmessages-filter-all": "همه",
+       "allmessages-filter-modified": "آلشت بیه",
+       "allmessages-prefix": "فیلتر بیه وا نهاون:",
        "allmessages-language": "زون:",
        "allmessages-filter-submit": "رو",
+       "allmessages-filter-translate": "والرن",
        "thumbnail-more": "گپ كردن",
        "filemissing": "گم بیئن جانیا",
        "thumbnail_error": "خطا د راس بیئن بن کلئکی:$1",
+       "import-interwiki-sourcewiki": "سرچشمه ویکی:",
+       "import-interwiki-sourcepage": "بلگه سرچشمه:",
+       "import-interwiki-submit": "وامین اوردن",
+       "import-interwiki-namespace": "نومجا مقصد:",
        "import-upload-filename": "نوم جانیا:",
        "import-comment": "ویر و باور:",
+       "importstart": "د حال و بار وامین اوردن",
+       "import-revision-count": "$1 {{جمی:$1|وانئری|وانئریا}}",
+       "importnopages": "هیچ بلگه ای وامین نیومائه.",
+       "importfailed": "وامین اوردن شکست حرده: <nowiki>$1</nowiki>",
        "importcantopen": "نبوئه جانیا دئه بیه نه وا بکید",
+       "importbadinterwiki": "هوم پیوند مینجاویکی گن",
+       "importsuccess": "وامین اوردن تموم بی!",
        "importnofile": "هیچ جانیا دئه بیه ای سوار نبیه.",
+       "import-noarticle": "هیچ بلگه ای سی وامین اوردن نئ!",
        "import-upload": "سوار کرد دونسمنیا ایکس ام ال",
        "import-token-mismatch": "کمبود د دونسمنیا نشینگه.\nلطفن هنی کوششت بکید.",
        "importlogpage": "پهرستنومه دئن",
+       "javascripttest": "ازمایشت کردن جاوا اسکریپت",
        "tooltip-pt-userpage": "بلگه كارورتو",
        "tooltip-pt-mytalk": "بلگه قسه كردن شما",
        "tooltip-pt-preferences": "اولويتيا شما",
        "tooltip-ca-viewsource": "ای بلگه حفاظت بيه.\nشما تونيت سرچمه ش بئوينيت",
        "tooltip-ca-history": "دوواره ديئن ای بلگه",
        "tooltip-ca-protect": "ای بلگه نه حفاظت بكيد",
-       "tooltip-ca-delete": "ای بلگه نه حذف بكيد",
+       "tooltip-ca-delete": "ای بلگه نه پاکسا کو",
        "tooltip-ca-move": "ای بگله نه جا وه جا كو",
        "tooltip-ca-watch": "اضاف کردن ای بلگه وه نوم نوشت پیگئریاتو",
        "tooltip-ca-unwatch": "ورداشتن ای بلگه وه نوم نوشت پیگئریاتو",
        "tooltip-n-help": "جاگه سی فهمسن",
        "tooltip-t-whatlinkshere": "سيائه تمؤم بلگيایی كه ايچه چسب ون دارن",
        "tooltip-t-recentchangeslinked": "تغيريا تازه باو مئن بلگيايي كه د ای بلگه چسب وند بيئنه",
+       "tooltip-feed-rss": "هوال حون آر اس اس سی ای بلگه",
        "tooltip-feed-atom": "تغذيه كؤچك سی ای بلگه",
        "tooltip-t-contributions": "یه نوم گه د هومیاریا ای کارور",
        "tooltip-t-emailuser": "سی ای كارور ايميل كل كو",
        "tooltip-t-permalink": "چسب ون هميشئی د دوواره بينی ای بلگه",
        "tooltip-ca-nstab-main": "ديئن محتوا بلگه",
        "tooltip-ca-nstab-user": "ديئن بلگه كارور",
+       "tooltip-ca-nstab-media": "دیئن بلگه وارسگر",
        "tooltip-ca-nstab-special": "اي بلگه ويجه يه، شما نتونيت خود اي بلگه نه ويرايشت بكيد",
        "tooltip-ca-nstab-project": "ديئن بلگه پروجه",
        "tooltip-ca-nstab-image": "ديئن بلگه فايل",
+       "tooltip-ca-nstab-mediawiki": "دیئن پیغوم سامونه",
        "tooltip-ca-nstab-template": "ديئن قالو",
+       "tooltip-ca-nstab-help": "ديئن بلگه هومیاری",
        "tooltip-ca-nstab-category": "ديئن بلگه دسه بنی",
        "tooltip-minoredit": "یه نه د عنوان حیرده ویرایشت ثوت کو",
        "tooltip-save": "آلشتياتونه اماییه بكيد",
        "tooltip-diff": "آلشتیا نه که شما د ای متن راس کردیته نشو بیئه",
        "tooltip-compareselectedversions": "فرخیا مینجا دو تا د دو بار دیئن ای بلگه نه بوینیت",
        "tooltip-watch": "ای بلگه نه د سیل برگتو اضاف بکید",
+       "tooltip-watchlistedit-raw-submit": "وه هنگوم سازی سیل برگ",
        "tooltip-upload": "شرو د سوار کرد",
        "tooltip-rollback": "\"ورگشتن\" لرستن د حالت اول  سی ای بلگه  که سی  يه كه هومياری  نيايی اصلاح بيه وا يه پورنسن",
        "tooltip-undo": "انجوم نگرتن ای ویرایشت ورگن و همه فرمیا ویرایشت تانه که حالت پیش سیل واکو.یه اجازه میئه سی اضاف کردن یه دلیل د چکسته.",
        "tooltip-summary": "يه چكسته كؤچك وارد بكيد",
        "interlanguage-link-title": "$1-$2",
+       "interlanguage-link-title-nonlang": "$1 – $2",
        "anonymous": "ناشناس {{جمی:$1|کارور|کاروریا}}  {{سیل جا}}",
        "anonuser": "{{سیل جا}}  کارور ناشناس $1",
+       "others": "دیه رون",
        "siteusers": "{{نوم سیل جا}} {{جمی:$2|کارور|کاروریا}} $1",
+       "creditspage": "اعتوار بلگه",
+       "pageinfo-title": "دونسمنیا سی \"$1\"",
+       "pageinfo-header-basic": "دونسمنیا پایه",
+       "pageinfo-header-edits": "ویرایشت ویرگار",
+       "pageinfo-header-restrictions": "پر و پیم کردن بلگه",
+       "pageinfo-header-properties": "چیا بلگه",
+       "pageinfo-length": "انازه بلگه(وه بایت)",
+       "pageinfo-article-id": "نوم دیار کن بلگه",
        "pageinfo-language": "بلگه مینونه زون",
        "pageinfo-content-model": "شلگ مینونه بلگه",
+       "pageinfo-views": "شماره دیئن یا",
+       "pageinfo-watchers": "شماره سیل کننه بلگه یا",
        "pageinfo-redirects-name": "شماره واگردونیا ای بلگه",
+       "pageinfo-redirects-value": "$1",
+       "pageinfo-firstuser": "بلگه راس کن",
+       "pageinfo-firsttime": "گات دروس بیین بلگه",
+       "pageinfo-lastuser": "آخری ویرایشتگر",
+       "pageinfo-lasttime": "گات آخری ویرایشت",
+       "pageinfo-edits": "شماره همه ویرایشتیا",
+       "pageinfo-toolboxlink": "دونسمنیا بلگه",
        "pageinfo-redirectsto": "واگردونی سی",
+       "pageinfo-redirectsto-info": "دونسمنیا",
+       "pageinfo-contentpage": "اشمارده بیه وه عنوان مینونه بلگه",
+       "pageinfo-contentpage-yes": "هری",
+       "pageinfo-protect-cascading": "پر و پیم بیین تافنمایی د ایچه",
+       "pageinfo-protect-cascading-yes": "هری",
+       "pageinfo-protect-cascading-from": "پر و پیم بیین تافنمایی د",
+       "pageinfo-category-info": "دونسمنیا دسه ای",
+       "pageinfo-category-pages": "شماره بلگيا",
+       "pageinfo-category-subcats": "شماره زیر دسه یا",
        "pageinfo-category-files": "شماره جانیایا",
        "patrol-log-page": "پهرستنومه گشتن",
        "filedeleteerror-short": "خطا پاک نبیئن جانیا:$1",
        "previousdiff": "← ويرايشت كۈهنه تر",
        "nextdiff": "ويرايشت تازه تر",
+       "widthheight": "$1 × $2",
+       "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|بلگه|بلگه یا}}",
+       "file-info": "انازه جانیا: $1, MIME type: $2",
        "file-info-size": "$1 × $2 پیکسل, انازه فایل: $3, MIME نوع: $4",
+       "file-info-size-pages": "$1 × $2 pixels, انازه جانیا: $3, MIME type: $4, $5 {{PLURAL:$5|بلگه|بلگه یا}}",
        "file-nohires": "عسك ون بالاتري دش ني",
        "svg-long-desc": "اس وی جی فايل.نومنا $1 $2 پيكسل",
        "show-big-image": "فایل اصلی",
+       "show-big-image-size": "$1 × $2 pixels",
+       "file-info-gif-looped": "حلقه دار",
+       "file-info-png-looped": "حلقه دار",
        "file-info-png-repeat": "$1 بازی کرده{{جمی:$1|وخت|وختیا}}",
        "newimages": "عسگدونی جانیایا تازه",
        "newimages-summary": "ای بلگه یا ویجه همه جانیایا سوار بیه نه نشو می ئین.",
+       "newimages-legend": "فیلتر",
        "newimages-label": "نوم جانیا(یا بشقی د وه):",
+       "noimages": "هیچی سی دیئن نئ",
        "ilsubmit": "پی جوری",
+       "bydate": "وا گات",
        "sp-newimages-showfrom": "جانیایا تازه نه که $2 ، $2 شرو بینه نشو بیه",
+       "video-dims": "$1, $2 × $3",
+       "seconds-abbrev": "$1 s",
+       "minutes-abbrev": "$1 دیقه",
+       "hours-abbrev": "$1 ساعت",
+       "days-abbrev": "$1 گات",
+       "seconds": "{{PLURAL:$1|$1 ثانیه|$1 ثانیه یا}}",
+       "minutes": "{{PLURAL:$1|$1 دیقه|$1 دیقه یا}}",
+       "hours": "{{PLURAL:$1|$1 ساعت|$1 ساعت یا}}",
        "days": "{{جمی:$1|1$ روز|$1 روز}}",
+       "weeks": "{{PLURAL:$1|$1 هفته|$1 هفته یا}}",
        "months": "{{جمی:$1|$1 ما|$1 مایا}}",
        "years": "{{جمی:$1|$1 سال|$1 سال}}",
+       "ago": "$1 دماتر",
+       "just-now": "فقط ایسه",
+       "hours-ago": "$1 {{PLURAL:$1|ساعت |ساعتیا}} دماتر",
+       "minutes-ago": "$1 {{PLURAL:$1|دیقه|دیقه یا}} دماتر",
+       "seconds-ago": "$1 {{PLURAL:$1|ثانیه|ثانیه یا}} دماتر",
        "monday-at": "دوشمه د $1",
        "bad_image_list": "دونسمنديانه وه ای شلگ وارد بكيت:\n\nفقط سرخط يایی که وا * شرو بوئن د وير گرته بوئن. اولی چسب ون مئن هر سرخط، باید چسب ونی وه یک عسگ گن با.\nچسب ونيا نيایی د همو سرخط، وه عنوان چيا استثنادار د وير گرته بوئن",
        "metadata": "داديا  فره گپ",
        "metadata-help": "ای فایل شومل دونسمنیا هنی یه.شایت د دیربین رقم ون یا اسکنری که سی راس کردنشو استفاده بیه،وه ایچه اضاف بیه",
        "metadata-fields": "رشته یا گپ دونسمنیا که د ای پیغوم نوم ون بینه شومل بلگه عسگ ن که وختی که جدول گپ دونسمنیا وا بوئه نشون دئیه بوئن.\nچی یا هنی سی یه که پیش فرضن قام بوئن.\n*راست کو\n*مدل\n*دم وخت اصل\n*وخت آشگار\n*اف ان شماره\n*ایزو نرخ من سرعت\n*فوکالنس\n*هنرمن\n*کپی رایت\n*حالت جی پی اس \n*جی پی اس گپ حالت\n*جی پی اس همه حالت",
+       "metadata-langitem": "<strong>$2:</strong> $1",
+       "metadata-langitem-default": "$1",
+       "exif-imagewidth": "پئنا",
+       "exif-imagelength": "بلنگی",
+       "exif-planarconfiguration": "سرجایک کردن رسینه",
        "exif-datetime": "آلشت دئن وخت و دمون جانیا",
        "exif-make": "سازنه دیربین",
+       "exif-artist": "نیسنه",
+       "exif-pixelydimension": "پئنا عسگ",
        "exif-usercomment": "ویر و باوریا کارور",
        "exif-relatedsoundfile": "جانیا دنگ دار مرتوط",
        "exif-datetimeoriginal": "دمون و وخت راس بیئن دونسمنیا",
        "exif-filesource": "سرچشمه جانیا",
        "exif-gpstimestamp": "وخت جی پی اس (ساعت اتمی)",
+       "exif-coordinate-format": "$1° $2′ $3″ $4",
        "exif-jpegfilecomment": "ویر و باور فایل پی ان جی",
+       "exif-keywords": "کلیمه یا کلیتی",
+       "exif-countrycodecreated": "رازینه سی ولاتی که عسگ د وه گرته بیه",
        "exif-citycreated": "شهری که عسگ دش گرته بیه",
+       "exif-countrycodedest": "رازینه سی ولات نمائشت دئه بیه",
        "exif-citydest": "شهر دیار بیه",
+       "exif-source": "سرچشمه",
        "exif-fixtureidentifier": "نوم ثاوت",
+       "exif-writer": "نیسنه",
        "exif-languagecode": "زون",
+       "exif-iimcategory": "دسه",
        "exif-datetimeexpires": "وا نها دش استفاده نبوئه",
+       "exif-datetimereleased": "ول بیه د",
+       "exif-label": "ری دیار",
        "exif-pngfilecomment": "ویر و باور فایل جی پی ان جی",
        "exif-giffilecomment": "ویر و باور فایل جی آی اف",
+       "exif-contact-value": "$1\n\n$2\n<div class=\"adr\">\n$3\n\n$4, $5, $6 $7\n</div>\n$8",
+       "exif-orientation-1": "عادی",
        "exif-componentsconfiguration-0": "نی یش",
        "exif-exposureprogram-1": "دسی",
+       "exif-meteringmode-0": "نادیار",
+       "exif-meteringmode-1": "میانگین",
+       "exif-lightsource-0": "نادیار",
        "exif-lightsource-1": "روشنایی روز",
+       "exif-focalplaneresolutionunit-2": "ائنج",
        "exif-scenecapturetype-3": "چی شو",
+       "exif-gaincontrol-0": "هیش کوم",
+       "exif-contrast-0": "عادی",
+       "exif-contrast-1": "نرم",
+       "exif-contrast-2": "سفت",
+       "exif-saturation-0": "عادی",
+       "exif-sharpness-0": "عادی",
+       "exif-sharpness-1": "نرم",
+       "exif-sharpness-2": "سفت",
+       "exif-subjectdistancerange-0": "نادیار",
+       "exif-subjectdistancerange-1": "گپ",
        "exif-gpsaltitude-above-sealevel": "$1 {{جمی:$1|متر|متریا}} وارؤ د ریتراز دریا",
        "exif-gpsaltitude-below-sealevel": "$1 {{جمی:$1|متر|متریا}} وارؤ د ریتراز دریا",
+       "exif-gpsdestdistance-m": "مایل",
        "exif-gpsdop-good": "خو ($1)",
        "exif-iimcategory-ace": "هنریا، رهزیشت و زیستگه",
+       "exif-iimcategory-lab": "کار",
        "watchlistall2": "همه شو",
        "namespacesall": "همه شو",
        "monthsall": "همه",
+       "confirmemail_send": "کل کردن رازینه پشت راس کاری",
+       "recreate": "د نو راس کردن",
+       "confirm_purge_button": "خوئه",
+       "confirm-watch-button": "خوئه",
+       "confirm-watch-top": "ای بلگه نه د سیل برگتو اضاف می کید؟",
+       "confirm-unwatch-button": "خوئه",
+       "confirm-unwatch-top": "ای بلگه نه د سیل برگتو ؤرمیداریت؟",
+       "semicolon-separator": ";&#32;",
+       "comma-separator": ",&#32;",
+       "colon-separator": ":&#32;",
+       "pipe-separator": "&#32;|&#32;",
+       "word-separator": "&#32;",
+       "ellipsis": "...",
+       "percent": "$1%",
+       "parentheses": "($1)",
+       "brackets": "[$1]",
+       "quotation-marks": "\"$1\"",
+       "imgmultipageprev": "بلگه دمايی",
+       "imgmultipagenext": "بلگه نهایی",
        "imgmultigo": "رؤ!",
+       "img-lang-opt": "$2 ($1)",
        "img-lang-default": "(زون پیش زمینه)",
        "img-lang-go": "رو",
+       "table_pager_next": "بلگه نهایی",
+       "table_pager_prev": "بلگه دمايی",
+       "table_pager_first": "سرآسونه",
+       "table_pager_last": "بلگه آخری",
        "table_pager_limit_submit": "رو",
        "autosumm-replace": "مینونه وا \"َ$1\" جاگزین بی",
        "autoredircomment": "بلگه واگردونی بیه سی[[$1]]",
+       "watchlistedit-normal-title": "ویرایشت سیل برگ",
+       "watchlisttools-clear": "پاک کردن سیل برگ",
        "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": "اسفند",
+       "hijri-calendar-m1": "محرم",
+       "hijri-calendar-m2": "صفر",
+       "hijri-calendar-m3": "ربیع الاول",
+       "hijri-calendar-m4": "رجو",
+       "timezone-utc": "UTC",
        "duplicate-defaultsort": "زنهار کلیت پیش فرض جور بیه $2 تازه ای یا کلید پیش فرض جوربیه $1 رد بیه.",
+       "version": "نسقه",
+       "version-variables": "آلشت ونا",
+       "version-antispam": "نهاگرتن هرزنومه",
+       "version-other": "هنی",
        "version-ext-license": "ليسانس",
+       "version-skin-colheader-name": "پوسه",
        "version-ext-colheader-version": "نسقه",
        "version-ext-colheader-license": "ليسانس",
+       "version-ext-colheader-description": "شرح",
        "version-ext-colheader-credits": "نیسنه یا",
+       "version-poweredby-others": "دیه رون",
+       "version-software-version": "نسقه",
+       "version-entrypoints-header-url": "يو آر ال",
+       "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Article path]",
+       "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Script path]",
        "redirect": "واگردونی وا جانیا،بلگه یا وانیئری نوم دیارکو",
        "redirect-submit": "رو",
+       "redirect-value": "ارزایشت:",
+       "redirect-user": "نوم دياركن کاریار:",
+       "redirect-page": "نوم دیار کن بلگه",
        "redirect-file": "نوم جانیا",
        "fileduplicatesearch-filename": "نوم جانیا:",
+       "fileduplicatesearch-submit": "پی جوری",
+       "fileduplicatesearch-info": "$1 × $2 pixel<br />انازه جانیا: $3<br />MIME type: $4",
        "specialpages": "بلگيا ويجه",
        "specialpages-group-changes": "آلشتیا تازه و پهرستنومه یا",
        "specialpages-group-media": "گزارشتیا رسانه و سوارکردیا",
        "specialpages-group-users": "کاروریا و حقوق",
        "specialpages-group-pages": "نوم گه بلگه یا",
+       "specialpages-group-wiki": "رسینه و اوزاریا",
        "specialpages-group-redirects": "بلگه ویجه واگردونی بیه",
        "external_image_whitelist": "یه خط نه ول بکید چی وه<pre>",
        "tag-filter": "فيلتر [[Special:Tags|Tag]]:",
        "tags-display-header": "دیاری کردن د نوم گه آلشتیا",
+       "tags-active-header": "کنشتگره؟",
+       "tags-active-yes": "هری",
+       "tags-active-no": "نه",
+       "tags-edit": "ویرایشت",
+       "tags-hitcount": "$1 {{جمی:$1|آلشت|آلشتیا}}",
+       "comparepages": "کنار یک نیاین بلگه یا",
+       "compare-page1": "بلگه 1",
+       "compare-page2": "بلگه 2",
+       "compare-rev1": "دوواره ديئن1",
+       "compare-submit": "کنار یک نیاین",
        "compare-title-not-exists": "سرون مشقص بیه وجود ناره.",
        "compare-revision-not-exists": "وانئری که شما تی دیار کردیته وجود ناره.",
+       "htmlform-submit": "دئن",
+       "htmlform-selectorother-other": "هنی",
+       "htmlform-no": "نه",
+       "htmlform-yes": "هری",
+       "htmlform-cloner-delete": "ؤرداشتن",
        "revdelete-content-hid": "مینونه قام بیه",
        "revdelete-uname-hid": "نوم کاروری قام بیه",
        "revdelete-content-unhid": "مینونه قام نبیه",
        "revdelete-uname-unhid": "نوم کاروری قام نبیه",
+       "rightsnone": "(هيش كوم)",
+       "feedback-subject": "سرون:",
+       "feedback-message": "پيغوم:",
+       "feedback-cancel": "انجوم شیوسن",
+       "feedback-submit": "کل کردن نهاهوال حون",
        "feedback-close": "انجوم بی",
        "searchsuggest-search": "پی جوری",
        "api-error-badaccess-groups": "شما سی سوار کرد جانیایا د ای ویکی اجازه ناریت.",
        "api-error-illegal-filename": "نوم جانیا اجازه دئه نئ.",
        "api-error-mustbeloggedin": "شما سی سوارکردن فایلیا با بیایت وامین",
        "duration-days": "$1{{جمی:$1|روز|روزیا}}",
+       "duration-weeks": "$1 {{جمی:$1|هفته|هفته یا}}",
        "duration-years": "$1{{جمی:$1| سال|سالیا}}",
-       "expand_templates_remove_comments": "جا وه جا بیئن ویر و باوریا"
+       "limitreport-ppvisitednodes-value": "$1/$2",
+       "limitreport-ppgeneratednodes-value": "$1/$2",
+       "limitreport-expansiondepth-value": "$1/$2",
+       "limitreport-expensivefunctioncount-value": "$1/$2",
+       "expand_templates_output": "نتیجه",
+       "expand_templates_ok": "خوئه",
+       "expand_templates_remove_comments": "جا وه جا بیئن ویر و باوریا",
+       "expand_templates_preview": "پيش سيل",
+       "pagelanguage": "بلگه انتخاو زون",
+       "pagelang-name": "بلگه",
+       "pagelang-language": "زون",
+       "pagelang-use-default": "وه کار بسن زون پیش دیه",
+       "pagelang-select-lang": "انتخاو زون",
+       "right-pagelang": "آلشت دئن زون بلگه",
+       "action-pagelang": "آلشت دئن زون بلگه",
+       "log-name-pagelang": "آلشت دئن زون پهرستنومه",
+       "log-description-pagelang": "ای پهرستنومه در بلگه زونا آلشت گرته.",
+       "default-skin-not-found-row-enabled": "* <رازینه>$1</رازینه> / $2 ('''ناکنشتگر بیه''')",
+       "default-skin-not-found-row-disabled": "* <رازینه>$1</رازینه> / $2 ('''ناکنشتگر بیه''')"
 }
index ed606d2..d883947 100644 (file)
        "talkpagelinktext": "Aptarimas",
        "specialpage": "Specialusis puslapis",
        "personaltools": "Asmeniniai įrankiai",
-       "postcomment": "Rašyti komentarą",
        "articlepage": "Rodyti turinio puslapį",
        "talk": "Aptarimas",
        "views": "Žiūrėti",
        "hidetoc": "slėpti",
        "collapsible-collapse": "Sutraukti",
        "collapsible-expand": "Išplėsti",
+       "confirmable-yes": "Taip",
+       "confirmable-no": "Ne",
        "thisisdeleted": "Žiūrėti ar atkurti $1?",
        "viewdeleted": "Rodyti $1?",
        "restorelink": "$1 {{PLURAL:$1|ištrintą keitimą|ištrintus keitimus|ištrintų keitimų}}",
        "externaldberror": "Yra arba išorinė autorizacijos duomenų bazės klaida arba jums neleidžiama atnaujinti jūsų išorinės paskyros.",
        "login": "Prisijungti",
        "nav-login-createaccount": "Prisijungti / sukurti paskyrą",
-       "loginprompt": "Įjunkite slapukus, jei norite prisijungti prie {{SITENAME}}.",
        "userlogin": "Prisijungti / sukurti paskyrą",
        "userloginnocreate": "Prisijungti",
        "logout": "Atsijungti",
        "searchprofile-advanced-tooltip": "Ieškoti skirtingose vardų srityse",
        "search-result-size": "$1 ({{PLURAL:$2|1 žodis|$2 žodžiai|$2 žodžių}})",
        "search-result-category-size": "{{PLURAL:$1|1 narys|$1 narių}} ({{PLURAL:$2|1 subkategorijoje|$2 subkategorijų}}, {{PLURAL:$3|1 failas|$3 failų}})",
-       "search-result-score": "Tinkamumas: $1%",
        "search-redirect": "(peradresavimas $1)",
        "search-section": "(skyrius $1)",
        "search-suggest": "Galbūt norėjote $1",
        "uploadwarning": "Dėmesio",
        "uploadwarning-text": "Prašome pakeisti failo aprašymą ir bandykite dar kartą.",
        "savefile": "Išsaugoti failą",
-       "uploadedimage": "įkėlė „[[$1]]“",
-       "overwroteimage": "įkėlė naują „[[$1]]“ versiją",
        "uploaddisabled": "Įkėlimai uždrausti",
        "copyuploaddisabled": "Įkėlimas pagal URL išjungtas.",
        "uploaddisabledtext": "Failų įkėlimai yra uždrausti.",
        "unusedtemplateswlh": "kitos nuorodos",
        "randompage": "Atsitiktinis puslapis",
        "randompage-nopages": "{{PLURAL:$2|Šioje vardų srityje|Šiose vardų srityse}} nėra jokių puslapių: $1.",
-       "randomincategory-selectcategory-submit": "Pirmyn",
        "randomredirect": "Atsitiktinis peradresavimas",
        "randomredirect-nopages": "Vardų srityje „$1“ nėra jokių peradresavimų.",
        "statistics": "Statistika",
        "watchlist-details": "Stebima {{PLURAL:$1|$1 puslapis|$1 puslapiai|$1 puslapių}} neskaičiuojant aptarimų puslapių.",
        "wlheader-enotif": "El. pašto pranešimai yra įjungti.",
        "wlheader-showupdated": "Puslapiai pakeisti nuo tada, kai paskutinį kartą apsilankėte juose, yra pažymėti '''pastorintai'''",
+       "wlnote": "{{PLURAL:$1|Rodomas '''$1''' paskutinis pakeitimas, atliktas|Rodomi '''$1''' paskutiniai pakeitimai, atlikti|Rodoma '''$1''' paskutinių pakeitimų, atliktų}} per '''$2''' {{PLURAL:$2|paskutinę valandą|paskutines valandas|paskutinių valandų}}, nuo $3 $4.",
        "wlshowlast": "Rodyti paskutinių $1 valandų, $2 dienų ar $3 pakeitimus",
        "watchlist-options": "Stebimųjų sąrašo parinktys",
        "watching": "Įtraukiama į stebimųjų sąrašą...",
        "import": "Importuoti puslapius",
        "importinterwiki": "Tarpprojektinis importas",
        "import-interwiki-text": "Pasirinkite projektą ir puslapio pavadinimą importavimui.\nVersijų datos ir redaktorių vardai bus išlaikyti.\nVisi tarpprojektiniai importo veiksmai yra registruojami  [[Special:Log/import|importo istorijoje]].",
-       "import-interwiki-source": "Šaltinio wiki projektas/puslapis:",
        "import-interwiki-history": "Kopijuoti visas istorijos versijas šiam puslapiui",
        "import-interwiki-templates": "Įtraukti visus šablonus",
        "import-interwiki-submit": "Importuoti",
        "pageinfo-article-id": "Puslapio ID",
        "pageinfo-language": "Puslapio turinio kalba",
        "pageinfo-robot-policy": "Paieškos variklio būsena",
-       "pageinfo-robot-index": "Indeksuotas",
-       "pageinfo-robot-noindex": "Neindeksuotas",
+       "pageinfo-robot-index": "Leidžiama",
+       "pageinfo-robot-noindex": "Neleidžiama",
        "pageinfo-views": "Peržiūrų skaičius",
        "pageinfo-watchers": "Puslapio stebėtojų skaičius",
        "pageinfo-redirects-name": "Nukreipimai į šį puslapį",
        "duplicate-defaultsort": "Įspėjimas: Numatytasis rikiavimo raktas „$2“ pakeičia ankstesnį numatytąjį rikiavimo raktą „$1“.",
        "version": "Versija",
        "version-extensions": "Įdiegti priedai",
+       "version-skins": "Išvaizda",
        "version-specialpages": "Specialieji puslapiai",
        "version-parserhooks": "Analizatoriaus gaudliai",
        "version-variables": "Kintamieji",
        "version-antispam": "Apsauga nuo šlamšto",
-       "version-skins": "Išvaizda",
        "version-other": "Kita",
        "version-mediahandlers": "Daugialypės terpės grotuvai",
        "version-hooks": "Gaudliai",
        "version-hook-name": "Gaudlio pavadinimas",
        "version-hook-subscribedby": "Užsakyta",
        "version-version": "(Versija $1)",
-       "version-license": "Licencija",
+       "version-license": "MediaWiki licencija",
        "version-poweredby-credits": "Šis projektas naudoja '''[https://www.mediawiki.org/ MediaWiki]''', autorystės teisės © 2001-$1 $2.",
        "version-poweredby-others": "kiti",
        "version-credits-summary": "Už indėlį kuriant [[Special:Version|MediaWiki]] dėkojame",
index 151cac7..717c2be 100644 (file)
        "talkpagelinktext": "sprīža",
        "specialpage": "Specialuo puslopa",
        "personaltools": "Muni reiki",
-       "postcomment": "Dalikt komentaru",
        "articlepage": "Apsavērt rakstīņu",
        "talk": "Sprīža",
        "views": "Vierīņi",
        "uploadbtn": "Īsyuteit failu",
        "uploadlogpage": "Davīnuotūs failu registrs",
        "savefile": "Izglobuot failu",
-       "uploadedimage": "davīnuots \"[[$1]]\"",
        "license": "Liceņceja:",
        "license-header": "Liceņceja",
        "imgfile": "fails",
index a133150..c4a82fa 100644 (file)
        "talkpagelinktext": "Sawihona",
        "specialpage": "Vohbik phek",
        "personaltools": "Mimal hmanruate",
-       "postcomment": "Thuhlawm thar",
        "articlepage": "A chhungthu enna",
        "talk": "Sawihona",
        "views": "Thlirna",
        "externaldberror": "Insawifiahna felfai lo a awm lo a nih loh vëk pawhin i pawnlam siangchan tihdanglam phalsak i ni lo a ni ang.",
        "login": "Luhna",
        "nav-login-createaccount": "Luhna / siangchan siamna",
-       "loginprompt": "{{SITENAME}}-a lût tùrin cookie i zuah zalen a ngai.",
        "userlogin": "Luhna/Siangchan siamna",
        "userloginnocreate": "Inziah luhna",
        "logout": "Chhuahna",
        "searchprofile-advanced-tooltip": "Hminghmun thlansa-ah zawng rawh",
        "search-result-size": "$1 ({{PLURAL:$2|Thumal 1 |Thumal $2 }})",
        "search-result-category-size": "{{PLURAL:$1|Tel 1 |Tel $1 }} ({{PLURAL:$2|Pawlpéng 1 |Pawlpéng $2}}, {{PLURAL:$3|Taksa 1 |Taksa $3 f}})",
-       "search-result-score": "Intûkna: $1%",
        "search-redirect": "($1 aţanga hruailuh)",
        "search-section": "(hlawm $1)",
        "search-suggest": "$1 i tihna a ni a ni zawk em?",
        "largefileserver": "Hë taksa hi rawngbawltu phaltir zât aia ritsak a ni.",
        "windows-nonascii-filename": "Hë wiki hian taksahminga chhinchhiahna bîk tel a pawm thei lo.",
        "savefile": "Taksa dahṭhatna",
-       "uploadedimage": "hlankai: \"[[$1]]\"",
        "uploadvirus": "I taksa hlànkài tumin hrik a päi!\nChanchin kimchang: $1",
        "upload-source": "Hnar taksa",
        "sourcefilename": "Hnar taksahming:",
index 70c362e..dc9e449 100644 (file)
        "talkpagelinktext": "Diskusija",
        "specialpage": "Īpašā Lapa",
        "personaltools": "Lietotāja rīki",
-       "postcomment": "Pievienot komentāru",
        "articlepage": "Apskatīt rakstu",
        "talk": "Diskusija",
        "views": "Apskates",
        "hidetoc": "paslēpt",
        "collapsible-collapse": "paslēpt",
        "collapsible-expand": "rādīt",
+       "confirmable-yes": "Jā",
+       "confirmable-no": "Nē",
        "thisisdeleted": "Apskatīt vai atjaunot $1?",
        "viewdeleted": "Skatīt $1?",
        "restorelink": "$1 {{PLURAL:$1|dzēsto versiju|dzēstās versijas}}",
        "externaldberror": "Notikusi vai nu ārējās autentifikācijas datubāzes kļūda, vai arī tev nav atļauts izmainīt savu ārējo kontu.",
        "login": "Pieslēgties",
        "nav-login-createaccount": "Izveidot jaunu lietotāju vai doties iekšā",
-       "loginprompt": "Lai ieietu {{grammar:lokatīvs|{{SITENAME}}}}, tavam datoram ir jāpieņem sīkdatnes (<i>cookies</i>).",
        "userlogin": "Izveidot jaunu lietotāju vai doties iekšā",
        "userloginnocreate": "Pieslēgties",
        "logout": "Iziet",
        "gotaccount": "Tev jau ir lietotājvārds? '''$1'''!",
        "gotaccountlink": "Pieslēgties",
        "userlogin-resetlink": "Esat aizmirsis savu pieslēgšanās informāciju?",
-       "userlogin-loggedin": "Tu esi pieslēdzies ar lietotājvārdu {{GENDER:$1|$1}}.\nLai pieslēgtos ar citu lietotājvārdu, aizpildi šo formu.",
-       "userlogin-createanother": "Izveidot citu kontu",
+       "userlogin-resetpassword-link": "Aizmirsi savu paroli?",
+       "userlogin-helplink2": "Palīdzība ar pieslēgšanos",
        "createacct-emailrequired": "E-pasta adrese",
        "createacct-emailoptional": "E-pasta adrese (nav obligāta)",
        "createacct-email-ph": "Ievadiet savu e-pasta adresi",
        "searchprofile-advanced-tooltip": "Izvēlēties nosaukumvietas, kurās meklēt",
        "search-result-size": "$1 ({{PLURAL:$2|1 vārds|$2 vārdi}})",
        "search-result-category-size": "$1 {{PLURAL:$1|apakšelements|apakšelementi}} ($2 {{PLURAL:$2|apakškategorija|apakškategorijas}}, $3 {{PLURAL:$3|fails|faili}})",
-       "search-result-score": "Atbilstība: $1%",
        "search-redirect": "(pāradresēts no $1)",
        "search-section": "(sadaļa $1)",
+       "search-file-match": "(atbilst faila saturam)",
        "search-suggest": "Vai jūs domājāt: $1",
        "search-interwiki-caption": "Citi projekti",
        "search-interwiki-default": "Rezultāti no $1:",
        "searchrelated": "saistītais",
        "searchall": "viss",
        "showingresults": "Šobrīd ir {{PLURAL:$1|redzama|redzamas}} '''$1''' {{PLURAL:$1|lapa|lapas}}, sākot ar #'''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|Šobrīd ir redzama '''$1''' lapa no '''$3'''|Šobrīd ir redzamas '''$1 — $2''' lapas no '''$3'''}}, kas satur '''$4'''",
        "search-nonefound": "Nav atrasti pieprasījumam atbilstoši rezultāti.",
        "powersearch-legend": "Izvērstā meklēšana",
        "powersearch-ns": "Meklēt šajās lapu grupās:",
        "powersearch-togglelabel": "Pārbaudīt:",
        "powersearch-toggleall": "Viss",
        "powersearch-togglenone": "Neviena",
+       "powersearch-remember": "Atcerēties izvēli turpmākajā meklēšanā",
        "search-external": "Ārējā meklēšana",
        "searchdisabled": "Meklēšana {{grammar:lokatīvs|{{SITENAME}}}} šobrīd ir atslēgta darbības traucējumu dēļ.\nPagaidām vari meklēt, izmantojot Google vai Yahoo.\nŅem vērā, ka meklētāju indeksētais {{grammar:ģenitīvs|{{SITENAME}}}} saturs var būt novecojis.",
        "preferences": "Izvēles",
        "rcshowhidebots": "$1 botus",
        "rcshowhideliu": "$1 reģistrētos lietotājus",
        "rcshowhideanons": "$1 anonīmos",
-       "rcshowhidepatr": "$1 pārbaudītie labojumi",
+       "rcshowhidepatr": "$1 pārbaudītos labojumus",
        "rcshowhidemine": "$1 manus",
        "rclinks": "Parādīt pēdējās $1 izmaiņas pēdējās $2 dienās.<br />$3",
        "diff": "izmaiņas",
        "uploadwarning": "Augšupielādes brīdinājums",
        "uploadwarning-text": "Lūdzu, pārveido zemāk esošo faila aprakstu un mēģini vēlreiz.",
        "savefile": "Saglabāt failu",
-       "uploadedimage": "augšupielādēja \"[[$1]]\"",
-       "overwroteimage": "augšupielādēta jauna \"[[$1]]\" versija",
        "uploaddisabled": "Augšupielāde atslēgta",
        "copyuploaddisabled": "URL augšupielādes nav atļautas.",
        "uploaddisabledtext": "Failu augšupielāde ir atslēgta.",
        "license-nopreview": "(Priekšskatījums nav pieejams)",
        "upload_source_url": "(derīgs, publiski pieejams URL)",
        "upload_source_file": "(fails datorā)",
+       "listfiles-delete": "dzēst",
        "listfiles-summary": "Šajā īpašajā lapā ir redzami visi augšupielādētie faili.",
        "listfiles_search_for": "Meklēt failu pēc vārda:",
        "imgfile": "fails",
        "randompage": "Nejauša lapa",
        "randomincategory": "Nejauša lapa kategorijā",
        "randomincategory-invalidcategory": "\"$1\" nav derīgs kategorijas nosaukums.",
-       "randomincategory-selectcategory-submit": "Aiziet",
        "randomredirect": "Nejauša pāradresācijas lapa",
        "statistics": "Statistika",
        "statistics-header-pages": "Lapu statistika",
        "statistics-users-active": "Aktīvi lietotāji",
        "statistics-users-active-desc": "Lietotāji, kas ir veikuši jebkādu darbību {{PLURAL:$1|iepriekšējā dienā|iepriekšējās $1 dienās}}",
        "statistics-mostpopular": "Visvairāk skatītās lapas",
+       "pageswithprop-prop": "Īpašības nosaukums:",
        "pageswithprop-submit": "Aiziet",
        "doubleredirects": "Divkāršas pāradresācijas lapas",
        "doubleredirectstext": "Šajā lapā ir uzskaitītas pāradresācijas lapas, kuras pāradresē uz citām pāradresācijas lapām.\nKatrā rindiņā ir saites uz pirmo un otro pāradresācijas lapu, kā arī pirmā rindiņa no otrās pāradresācijas lapas teksta, kas parasti ir faktiskā \"gala\" lapa, uz kuru vajadzētu būt saitei pirmajā lapā.\n<del>Nosvītrotie</del> ieraksti jau ir tikuši salaboti.",
        "protectedpages-indef": "Tikai bezgalīgas aizsardzības",
        "protectedpages-cascade": "Tikai kaskādes aizsardzības",
        "protectedpages-noredirect": "Paslēpt pāradresācijas",
+       "protectedpages-page": "Lapa",
+       "protectedpages-reason": "Iemesls",
+       "protectedpages-unknown-timestamp": "Nav zināms",
+       "protectedpages-unknown-performer": "Nezināms lietotājs",
        "protectedtitles": "Aizsargātie nosaukumi",
        "protectedtitlesempty": "Pagaidām nevienas lapas nosaukums nav aizsargāts ar šiem paraametriem.",
        "listusers": "Lietotāju uzskaitījums",
        "movepagetext": "Šajā lapā tu vari pārdēvēt vai pārvietot lapu, kopā tās izmaiņu hronoloģiju pārvietojot to uz citu nosaukumu.\nIepriekšējā lapa kļūs par lapu, kas pāradresēs uz jauno lapu.\nŠeit var automātiski izmainīt visas pāradresācijas (redirektus) uz šo lapu (2. ķeksis apakšā).\nSaites pārējās lapās uz iepriekšējo lapu netiks mainītas. Ja izvēlies neizmainīt pāradresācijas automātiski, noteikti pārbaudi un izlabo, izskaužot [[Special:DoubleRedirects|dubultu pāradresāciju]] vai [[Special:BrokenRedirects|pāradresāciju uz neesošu lapu]].\nTev ir jāpārliecinās, vai saites vēl aizvien ved tur, kur tās ir paredzētas.\n\nŅem vērā, ka lapa '''netiks''' pārvietota, ja jau eksistē kāda cita lapa ar vēlamo nosaukumu (izņemot gadījumus, kad tā ir tukša vai kad tā ir pāradresācijas lapa, kā arī tad, ja tai nav izmaiņu hronoloģijas).\nTas nozīmē, ka tu vari pārvietot lapu atpakaļ, no kurienes tu jau reiz to esi pārvietojis, ja būsi kļūdījies, bet tu nevari pārrakstīt jau esošu lapu.\n\n'''BRĪDINĀJUMS!'''\nPopulārām lapām tā var būt krasa un negaidīta pārmaiņa;\npirms turpināšanas vēlreiz pārdomā, vai tu izproti visas iespējamās sekas.",
        "movepagetalktext": "Saistītā diskusiju lapa, ja tāda eksistē, tiks automātiski pārvietota, '''izņemot gadījumus, kad''':\n*tu pārvieto lapu uz citu palīglapu,\n*ar jauno nosaukumu jau eksistē diskusiju lapa, vai arī\n*atzīmēsi zemāk atrodamo lauciņu.\n\nJa tomēr vēlēsies, tad tev šī diskusiju lapa būs jāpārvieto vai jāapvieno pašam.",
        "movearticle": "Pārvietot lapu",
+       "movecategorypage-warning": "<strong>Brīdinājums:</strong> Tu grasies pārvietot kategoriju. Lūgums ievērot, ka pārvietota tiks tikai šī lapa, kategorijas saturs <em>netiks</em> pārvietots.",
        "movenologintext": "Tev ir jābūt reģistrētam lietotājam un jābūt [[Special:UserLogin|iegājušam]] {{grammar:lokatīvs|{{SITENAME}}}}, lai pārvietotu lapu.",
        "movenotallowed": "Tev nav atļaujas pārvietot lapas.",
        "movenotallowedfile": "Tev nav atļaujas pārvietot failus.",
        "thumbnail_image-missing": "Šķiet, ka fails ir pazudis: $1",
        "import": "Importēt lapas",
        "importinterwiki": "Starpviki importēšana",
-       "import-interwiki-source": "Avota viki/lapa:",
        "import-interwiki-history": "Nokopēt visas šīs lapas hronoloģijā atrodamās versijas",
        "import-interwiki-templates": "Iekļaut visas veidnes",
        "import-interwiki-submit": "Importēt",
        "pageinfo-edits": "Kopējais izmaiņu skaits",
        "pageinfo-authors": "Kopējais atsevišķu autoru skaits",
        "pageinfo-toolboxlink": "Lapas informācija",
+       "pageinfo-redirectsto": "Pāradresē uz",
        "pageinfo-redirectsto-info": "info",
+       "pageinfo-contentpage": "Skaitīta kā satura lapa",
        "pageinfo-contentpage-yes": "Jā",
        "pageinfo-protect-cascading-yes": "Jā",
        "pageinfo-category-info": "Kategorijas informācija",
        "file-info-png-frames": "$1 {{PLURAL:$1|kadrs|kadri}}",
        "newimages": "Jauno attēlu galerija",
        "imagelisttext": "Šobrīd redzams $1 {{PLURAL:$1|attēla|attēlu}} uzskaitījums, kas sakārtots $2.",
-       "newimages-summary": "Šeit var apskatīties pēdējos šeit augšuplādētos failus.",
+       "newimages-summary": "Šeit var apskatīties pēdējos augšuplādētos failus šajā Vikipēdijā",
        "newimages-legend": "Filtrs",
        "newimages-label": "Faila nosaukums (vai tā daļa):",
+       "newimages-showbots": "Parādīt botu augšupielādētos failus",
        "noimages": "Nav nekā ko redzēt.",
        "ilsubmit": "Meklēt",
        "bydate": "<b>pēc datuma</b>",
        "exif-specialinstructions": "Īpašas norādes",
        "exif-headline": "Virsraksts",
        "exif-source": "Avots",
+       "exif-locationdest": "Attēlotā vieta",
+       "exif-locationdestcode": "Attēlotās vietas kods",
        "exif-contact": "Kontaktinformācija",
        "exif-languagecode": "Valoda",
        "exif-iimversion": "IIM versija",
        "watchlistedit-raw-done": "Tavs uzraugāmo rakstu saraksts tika atjaunots.",
        "watchlistedit-raw-added": "{{PLURAL:$1|1 lapa tika pievienota|$1 lapas tika pievienotas}}:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1 lapa tika noņemta|$1 lapas tika noņemtas}}:",
+       "watchlistedit-clear-titles": "Nosaukumi:",
        "watchlisttools-view": "Skatīt atbilstošās izmaiņas",
        "watchlisttools-edit": "Apskatīt un izmainīt uzraugāmo rakstu sarakstu",
        "watchlisttools-raw": "Izmainīt uzraugāmo rakstu saraksta kodu",
        "duplicate-defaultsort": "'''Brīdinājums:''' Noklusējuma kārtošanas atslēga \"$2\" ignorē kārtošanas atslēga \"$1\".",
        "version": "Versija",
        "version-extensions": "Ieinstalētie paplašinājumi",
-       "version-skins": "Apdares",
+       "version-skins": "Uzstādītās apdares",
        "version-specialpages": "Īpašās lapas",
        "version-variables": "Mainīgie",
        "version-antispam": "Spama aizsardzība",
        "version-hooks": "Aizķeres",
        "version-hook-name": "Aizķeres nosaukums",
        "version-version": "(Versija $1)",
+       "version-no-ext-name": "[bez nosaukuma]",
        "version-license": "MediaWiki licence",
+       "version-ext-license": "Licence",
+       "version-ext-colheader-name": "Paplašinājums",
+       "version-skin-colheader-name": "Apdare",
+       "version-ext-colheader-version": "Versija",
+       "version-ext-colheader-license": "Licence",
+       "version-ext-colheader-description": "Apraksts",
+       "version-ext-colheader-credits": "Autori",
        "version-poweredby-credits": "Šis viki darbojas ar '''[https://www.mediawiki.org/ MediaWiki]''' programmatūru, autortiesības © 2001-$1 $2.",
        "version-poweredby-others": "citi",
        "version-poweredby-translators": "translatewiki.net tulkotāji",
        "htmlform-no": "Nē",
        "htmlform-yes": "Jā",
        "htmlform-chosen-placeholder": "Izvēlieties iespēju",
+       "htmlform-cloner-create": "Pievienot vairāk",
        "sqlite-has-fts": "$1 ar pilnteksta meklēšanas atbalstu",
        "sqlite-no-fts": "$1 bez pilnteksta meklēšanas atbalsta",
        "logentry-delete-delete": "$1 {{GENDER:$2|izdzēsa}} lapu $3",
index 967370c..ecf17a3 100644 (file)
@@ -11,7 +11,9 @@
                        "Super Wang",
                        "Xiaomingyan",
                        "Yanteng3",
-                       "아라"
+                       "아라",
+                       "LNDDYL",
+                       "Jason924tw"
                ]
        },
        "tog-underline": "鏈墊線:",
@@ -42,7 +44,7 @@
        "tog-forceeditsummary": "漏概醒之",
        "tog-watchlisthideown": "不哨己文",
        "tog-watchlisthidebots": "不哨僕文",
-       "tog-watchlisthideminor": "不哨纂",
+       "tog-watchlisthideminor": "不哨纂",
        "tog-watchlisthideliu": "不哨有簿",
        "tog-watchlisthideanons": "不哨無簿",
        "tog-watchlisthidepatrolled": "不哨已巡",
        "history_short": "誌",
        "updatedmarker": "新也",
        "printableversion": "印本",
-       "permalink": "æ\81\86é\8f\88",
+       "permalink": "æ\81\86é\80\9a",
        "print": "印",
        "view": "察",
        "edit": "纂",
        "talkpagelinktext": "議",
        "specialpage": "特查",
        "personaltools": "家私",
-       "postcomment": "評",
        "articlepage": "閱內文",
        "talk": "議",
        "views": "覽",
        "copyright": "文奉$1行。",
        "copyrightpage": "{{ns:project}}:版權",
        "currentevents": "世事",
-       "currentevents-url": "Project:世事",
+       "currentevents-url": "Wikipedia:世事",
        "disclaimers": "免責宣",
        "disclaimerpage": "Project:免責宣",
        "edithelp": "助纂塾",
        "youhavenewmessages": "有$1書至子書房也。($2)",
        "youhavenewmessagesfromusers": "子有 $1 自 {{PLURAL:$3|一簿戶也|$3 簿戶也}} ($2)。",
        "youhavenewmessagesmanyusers": "子有 $1 自多簿戶 ( $2 )",
-       "newmessageslinkplural": "{{PLURAL:$1|一新訊息|新訊息}}",
-       "newmessagesdifflinkplural": "新{{PLURAL:$1|易|易}}",
+       "newmessageslinkplural": "{{PLURAL:$1|一新訊|999=新訊}}",
+       "newmessagesdifflinkplural": "新",
        "youhavenewmessagesmulti": "新訊於$1",
        "editsection": "纂",
        "editold": "纂",
        "hidetoc": "藏",
        "collapsible-collapse": "摺",
        "collapsible-expand": "展",
+       "confirmable-yes": "是",
+       "confirmable-no": "否",
        "thisisdeleted": "還$1或閱之?",
        "viewdeleted": "閱$1之?",
        "restorelink": "$1已刪",
        "nospecialpagetext": "<strong>無此特查。</strong>\n\n見[[Special:SpecialPages|{{int:specialpages}}]]。",
        "error": "有誤",
        "databaseerror": "庫藏誤然",
+       "databaseerror-query": "尋:$1",
+       "databaseerror-error": "錯:$1",
        "laggedslavemode": "警示,此頁不新",
        "readonly": "鎖庫藏",
        "enterlockreason": "何以鎖之?何日啟之?",
        "externaldberror": "認庫之錯或禁更爾之外簿。",
        "login": "登簿",
        "nav-login-createaccount": "登簿、增簿",
-       "loginprompt": "登簿{{SITENAME}}須cookies,請准之。",
        "userlogin": "登簿、增簿",
        "userloginnocreate": "登簿",
        "logout": "去簿",
        "yourtext": "子也",
        "storedversion": "時也",
        "nonunicodebrowser": "'''警示:覽器不識萬國碼,以十六進位數代之,以保纂可也。'''",
-       "editingold": "''''''警示'''子纂舊然。強儲之,則新易失焉。'''",
+       "editingold": "'''\"警示\"子纂舊然。強儲之,則新易失焉。'''",
        "yourdiff": "異",
        "copyrightwarning": "{{SITENAME}}全文皆循$2,詳見$1。不喜他纂,但去可矣。文務親撰,或謄公本,\n'''萬勿盜版!'''",
        "copyrightwarning2": "{{SITENAME}}全文,允眾人撰、纂、刪、校。不喜他纂,但去可矣。<br />\n文務親撰,或謄公本,如$1。'''萬勿盜版!'''",
        "revertmerge": "悔併",
        "mergelogpagetext": "下乃近頁之誌併至二頁之表也。",
        "history-title": "$1之誌",
-       "difference-title": "$1各本之",
+       "difference-title": "$1各本之",
        "difference-title-multipage": "$1、$2之异",
        "difference-multipage": "(辨頁)",
        "lineno": "第$1行:",
        "shown-title": "每頁示 $1",
        "viewprevnext": "見($1 {{int:pipe-separator}} $2)($3)",
        "searchmenu-exists": "'''在此wiki中有頁為\"[[:$1]]\"。'''",
-       "searchmenu-new": "'''在此wiki上建頁\"[[:$1]]\"!'''",
+       "searchmenu-new": "'''在此共筆上建頁\"[[:$1]]\"!'''",
        "searchprofile-articles": "容",
        "searchprofile-images": "媒",
        "searchprofile-everything": "全",
        "searchprofile-advanced-tooltip": "自定名集中尋",
        "search-result-size": "$1 ($2字)",
        "search-result-category-size": "{{PLURAL:$1|一員|員有$1}}({{PLURAL:$2|一子類有|子類有$2}},{{PLURAL:$3|檔有一|檔有$3}})",
-       "search-result-score": "關:$1%",
        "search-redirect": "(轉 $1)",
        "search-section": "(節 $1)",
        "search-suggest": "爾否解之:$1",
        "searchrelated": "關",
        "searchall": "全",
        "showingresults": "見'''$1'''尋,自'''$2'''始:",
-       "showingresultsheader": "見'''$4''',{{PLURAL:$5|'''$1''''''$3'''之尋|'''$1 - $2''',共'''$3'''之尋}}",
        "search-nonefound": "詢中無結。",
        "powersearch-legend": "尋",
        "powersearch-ns": "尋名集:",
        "preferences": "簿註",
        "mypreferences": "簿註",
        "prefs-edits": "數計:",
+       "prefsnologintext2": "登簿以更簿註",
        "prefs-skin": "面版",
        "skin-preview": "草覽",
        "datedefault": "原註",
        "prefs-watchlist-token": "哨幣:",
        "prefs-misc": "雜",
        "prefs-resetpass": "更符節",
+       "prefs-changeemail": "更郵址",
        "prefs-email": "傳書",
        "prefs-rendering": "觀",
        "saveprefs": "儲",
        "action-userrights-interwiki": "纂他wiki上之權",
        "action-siteadmin": "鎖及解鎖其庫",
        "nchanges": "$1易",
+       "enhancedrc-since-last-visit": "$1未示",
        "enhancedrc-history": "誌",
        "recentchanges": "近易",
        "recentchanges-legend": "近易項",
        "recentchanges-label-minor": "此乃細纂",
        "recentchanges-label-bot": "此乃機纂",
        "recentchanges-label-unpatrolled": "是纂未巡",
-       "recentchanges-legend-newpage": "$1 - 新頁",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}}([[Special:NewPages|新灶]])",
        "rcnotefrom": "下為自'''$2'''至'''$1'''之易也。",
        "rclistfrom": "自$3 $2起之易也",
        "rcshowhideminor": "$1校",
        "uploadwarning": "慎焉!",
        "uploadwarning-text": "改下檔述再試之。",
        "savefile": "存之",
-       "uploadedimage": "進獻\"[[$1]]\"",
-       "overwroteimage": "新置「[[$1]]」矣",
        "uploaddisabled": "進獻已阻",
        "copyuploaddisabled": "由URL之貢被禁也。",
        "uploaddisabledtext": "檔之貢被禁也。",
        "filehist-thumb": "縮",
        "filehist-thumbtext": "於$1之縮",
        "filehist-nothumb": "無縮",
-       "filehist-user": "",
+       "filehist-user": "簿",
        "filehist-dimensions": "度",
        "filehist-filesize": "檔幅",
        "filehist-comment": "註",
        "unusedtemplates": "墨乾",
        "unusedtemplatestext": "此表閒模,篤刪前惠考支鏈。",
        "unusedtemplateswlh": "支鏈",
-       "randompage": "風掀",
+       "randompage": "清風翻書",
        "randompage-nopages": "下列{{PLURAL:$2|名集}}中無頁也:$1",
-       "randomincategory-selectcategory-submit": "往",
        "randomredirect": "任渡",
        "randomredirect-nopages": "「$1」名冊內無渡也。",
        "statistics": "彙統",
        "double-redirect-fixer": "修渡",
        "brokenredirects": "斷渡",
        "brokenredirectstext": "頁下斷渡。",
-       "brokenredirects-edit": "",
+       "brokenredirects-edit": "",
        "brokenredirects-delete": "刪",
        "withoutinterwiki": "孤語",
        "withoutinterwiki-summary": "頁下無鏈他語。",
        "mostcategories": "跨船",
        "mostimages": "名檔",
        "mostrevisions": "屢審",
-       "prefixindex": "以é\8f\88å¤\96æ\9f¥",
+       "prefixindex": "ä¾\9då\90\8dç´¢å¼\95",
        "shortpages": "短篇",
        "longpages": "長言",
        "deadendpages": "此無路也",
        "nowatchlist": "無哨",
        "watchlistanontext": "$1以治哨",
        "watchnologin": "未登簿",
+       "addwatch": "增至哨站",
        "addedwatchtext": "\"[[:$1]]\"哨派矣。後有易、議者可見於[[Special:Watchlist|哨站]],且'''粗體'''列於[[Special:RecentChanges|近易]]。",
        "removedwatchtext": "\"[[:$1]]\"[[Special:Watchlist|哨]]撤矣。",
        "watch": "派哨",
        "watchlist-details": "哨上有$1,不含議論。",
        "wlheader-enotif": "*准報信。",
        "wlheader-showupdated": "*易者'''粗體'''。",
+       "wlnote": "近<b>$2</b>時有$1者易。",
        "wlshowlast": "見近$1時、$2天、$3時易",
        "watchlist-options": "哨項",
        "watching": "出陣…",
        "exbeforeblank": "清文前乃為:「$1」",
        "delete-confirm": "刪\"$1\"",
        "delete-legend": "刪",
-       "historywarning": "警示,此頁有誌$1:",
+       "historywarning": "警示,此頁有誌$1:",
        "confirmdeletetext": "欲刪此物與誌,知後果、合[[{{MediaWiki:Policy-url}}]]後再為之。",
        "actioncomplete": "成矣",
        "actionfailed": "未竟",
        "cannotundelete": "無以還檔;或復矣。",
        "undeletedpage": "'''$1還矣'''\n近刪新還,見[[Special:Log/delete|刪還誌]]。",
        "undelete-header": "欲覽近刪,見[[Special:Log/delete|誌刪]]。",
+       "undelete-search-title": "尋刪頁",
        "undelete-search-box": "尋刪",
        "undelete-search-prefix": "見頁始如",
        "undelete-search-submit": "尋",
        "namespace": "名冊:",
        "invert": "反相",
        "blanknamespace": "主",
-       "contributions": "{{GENDER:$1|簿}} 之功績",
+       "contributions": "功績",
        "contributions-title": "$1之功績",
        "mycontris": "吾績",
        "contribsub2": "$1勛($2)",
        "import": "圖入匯",
        "importinterwiki": "維基互匯",
        "import-interwiki-text": "欲入匯,擇維基、揀題文,審時、纂者隨記也。互匯錄於[[Special:Log/import|誌入]]。",
-       "import-interwiki-source": "來源wiki/頁:",
+       "import-interwiki-sourcepage": "源頁:",
        "import-interwiki-history": "審、誌同匯",
        "import-interwiki-submit": "入匯",
        "import-interwiki-namespace": "入名集:",
        "spambot_username": "MediaWiki清濫",
        "spam_reverting": "還新審之無鏈$1者。",
        "spam_blanking": "審皆鏈$1,遂令白頁。",
+       "pageinfo-header-restrictions": "頁錮",
        "pageinfo-toolboxlink": "文訊",
        "markaspatrolleddiff": "派哨",
        "markaspatrolledtext": "哨此報",
        "duplicate-defaultsort": "警:預之排鍵「$2」蓋前之排鍵「$1」。",
        "version": "版",
        "version-extensions": "裝展",
+       "version-skins": "皮",
        "version-specialpages": "奇頁",
        "version-parserhooks": "語鈎",
        "version-variables": "變數",
        "version-antispam": "垃圾之防",
-       "version-skins": "皮",
        "version-other": "他",
        "version-mediahandlers": "媒處",
        "version-hooks": "鈎",
        "sqlite-no-fts": "$1 不含全文之尋",
        "revdelete-restricted": "應限至有秩",
        "revdelete-unrestricted": "除限自有秩",
-       "rightsnone": "(凡)"
+       "rightsnone": "(凡)",
+       "searchsuggest-search": "尋"
 }
index 1379130..bbae542 100644 (file)
@@ -8,11 +8,11 @@
                        "Erdemaslancan",
                        "Ibero-kolxi",
                        "Reedy",
-                       "The Evil IP address"
+                       "The Evil IP address",
+                       "아라"
                ]
        },
        "tog-underline": "Link'iş tude kogu3’uxaçki:",
-       "tog-rememberpassword": "Parola-skani goişini (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "tog-showhiddencats": "Şinaxeri k'at'egorepe ko3'iri",
        "underline-always": "P'anda",
        "underline-never": "P'ot'e",
        "oct": "Gum",
        "nov": "Çxa",
        "dec": "Xri",
+       "january-date": "3ʼanağani $1",
+       "february-date": "Kʼundura $1",
+       "march-date": "Martʼi $1",
+       "april-date": "Apʼrili $1",
+       "may-date": "Maisi $1",
+       "june-date": "Mbuliştuta $1",
+       "july-date": "X3ala $1",
+       "august-date": "Maraşina $1",
+       "september-date": "Stʼaroşina $1",
+       "october-date": "Gumatuta $1",
+       "november-date": "Çxalva $1",
+       "december-date": "Xristʼana $1",
        "pagecategories": "Butʼkʼaşi {{PLURAL:$1|kʼatʼegori|kʼatʼegorepe}}",
        "category_header": "\"$1\" kʼatʼegoris butʼkʼape",
        "subcategories": "Tudekʼategorepe",
@@ -83,7 +95,7 @@
        "newwindow": "(ağne penceres guin3ʼkʼen)",
        "cancel": "İpʼtʼali qʼvi",
        "moredotdotdot": "Çkva…",
-       "mypage": "Çkimi sayfa",
+       "mypage": "Stʼatʼia",
        "mytalk": "Çkimi mesajepe",
        "anontalk": "Am IP'şi mesajepe",
        "navigation": "Goxtima",
        "qbedit": "Doktiri",
        "qbpageoptions": "Am sayfa",
        "qbmyoptions": "Çkimi sayfape",
-       "vector-action-delete": "Jili",
-       "vector-action-move": "Tori",
-       "vector-action-protect": "İçvi",
-       "vector-view-create": "dokʼidi",
-       "vector-view-edit": "Doktiri",
-       "vector-view-view": "İǩitxi",
        "variants": "Variant'epe",
        "errorpagetitle": "Çilata",
        "returnto": "$1 butʼkʼaşa goikti.",
        "youhavenewmessagesmulti": "$1's ağne mesajepe giğun",
        "editsection": "doktiri",
        "editold": "Doktiri",
+       "viewsourceold": "odude koz*iri",
        "editlink": "Doktiri",
        "viewsourcelink": "odude koz*iri",
        "editsectionhint": "$1 burme muşi doktiri",
        "toc": "Temaşi dudi-coxope",
        "showtoc": "ko3ʼiri",
        "hidetoc": "Doşinaxi",
+       "collapsible-collapse": "Nok’açi",
+       "viewdeleted": "Koziri $1?",
+       "feedlinks": "Omgvani:",
        "site-rss-feed": "$1 RSS-iş Feedi",
        "site-atom-feed": "$1 Atʼom-iş feedi",
        "page-rss-feed": "\"$1\" RSS-iş Feedi",
        "nstab-image": "Dosya",
        "nstab-mediawiki": "Mesaji",
        "nstab-template": "Şabloni",
+       "nstab-help": "Meşvelaşi but’k’a",
        "nstab-category": "Kʼatʼegori",
+       "error": "Çilata",
        "missing-article": "Datʼabeizik, na igoren \"$1\" $2 coxoni butʼkʼaşi tekstʼi var az*iru.\n\nMuşeni? Çunki am butʼkʼa, jileri na ren a butʼkʼaşi golaxteri versiyoni ren.\n\nEger sebebi aya na va renna, pʼrogramis ar çilata z*irit.\nMu iqʼven! Aya, a [[Special:ListUsers/sysop|adminis]], URL-ti çʼareli şekʼilite rapʼortʼi doçʼarit.",
        "missingarticle-rev": "(revizyoni#: $1)",
        "badtitle": "Varixmarinen boxoxia",
        "badtitletext": "Na içʼaren butʼkʼaşi coxo ya çilatoni ren ya boşi ren varna inter-nena do inter-vikʼişi kʼontʼaktʼis na uğutʼu şeni mtini varen.\nDudicoxopes oxmaruşi yasaği na ren ar, varna daha dido kʼarakʼtʼeri uğun.",
        "viewsource": "Odudes o3ʼkʼedi",
+       "welcomeuser": "K'aobaten, $1!",
        "yourname": "Skani maxmare-coxo:",
+       "userlogin-yourname": "Skani maxmare-coxo",
        "yourpassword": "Pʼarola-skani:",
+       "userlogin-yourpassword": "Pʼarola-skani",
        "remembermypassword": "Parola-skani goişini (for a maximum of $1 {{PLURAL:$1|day|days}})",
+       "yourdomainname": "Skani domaini:",
        "login": "Sitʼeşa amaxti",
        "nav-login-createaccount": "Sitʼeşa amaxti / hesabi dokʼidi",
        "userlogin": "Sitʼeşa amaxti / hesabi dokʼidi",
+       "userloginnocreate": "Sitʼeşa amaxti",
        "logout": "Siteşen Kogamaxti",
        "userlogout": "Siteşen Kogamaxti",
+       "userlogin-joinproject": "{{SITENAME}}işe ak’ati",
        "nologin": "Hesabi va giğuni? '''$1'''",
        "nologinlink": "Hesabi dokʼidi.",
        "createaccount": "Hesabi dokʼidi",
        "gotaccountlink": "Sitʼeşa amaxti",
+       "createaccountreason": "Muşen:",
+       "createacct-reason": "Muşen",
        "mailmypassword": "Ağne pʼarola-çkimi moncğoni",
        "loginlanguagelabel": "Nena: $1",
        "oldpassword": "Mcveşi p'arola:",
        "newpassword": "Ağani P'arola:",
+       "passwordreset-username": "Skani maxmare-coxo:",
        "bold_sample": "Mçxu nçʼara",
        "bold_tip": "Mçxu nçʼara",
        "italic_sample": "Elakteri nçʼara",
        "nextrevision": "Ağani xali-muşi →",
        "currentrevisionlink": "İrişen ağne xali-muşi ko3ʼiri",
        "cur": "farkʼi",
+       "next": "ok’uleni",
        "last": "çodina",
+       "page_first": "iptineri",
+       "page_last": "çodina",
        "histlegend": "Farkʼiş 3xuna: o3xunu şeni na ginon 2 versiyoniş na go3ʼadgin dairepeşa gebaz*gi, do ukvule entʼerişa gebaz*gi varna butʼkʼaşi tude na dgin tʼuşişa gebaz*gi.<br />\nOxo3ʼonapape: (a3ʼineri) = a3ʼineri versiyoni kʼala na ren farkʼi,\n(iptineri) = iptineri versiyoni kʼala na ren farkʼi, Çʼ = çʼitʼa oktiroba.",
        "history-fieldset-title": "Golaxteris o3ʼkʼedi",
        "history-show-deleted": "Xvala nijilenepe",
        "histfirst": "irişen mcveşi",
        "histlast": "irişen ağani",
        "rev-delundel": "ko3ʼiri/doşinaxi",
-       "revdelete-radio-set": "Ho",
+       "rev-showdeleted": "ko3ʼiri",
+       "revdelete-show-file-submit": "Ho",
+       "revdelete-radio-set": "Şinaxeri",
        "revdelete-radio-unset": "Var",
        "revdel-restore": "Ozʼiramuşi doktiri",
        "revertmerge": "Artikʼartişen okʼo3ʼkʼi",
        "search-section": "(burme $1)",
        "search-suggest": "Aya çʼari-i: $1",
        "search-interwiki-caption": "Cuma projepe",
-       "search-interwiki-default": "$1 sonucepe:",
+       "search-interwiki-default": "$1'işi sonucepe:",
        "search-interwiki-more": "(çkva)",
        "searchall": "mteli",
        "powersearch-legend": "Mordineri ogoru",
        "powersearch-ns": "Svacoxo-s mgori:",
-       "powersearch-redir": "Redirektʼepe ilistʼeli",
+       "powersearch-toggleall": "İri",
+       "powersearch-togglenone": "Çkari",
        "preferences": "Tercihepe",
        "mypreferences": "Çkimi tercihepe",
        "searchresultshead": "Mgori",
        "timezoneregion-antarctica": "Antartik'a",
        "timezoneregion-asia": "Asya",
        "timezoneregion-europe": "Avrop'a",
+       "prefs-searchoptions": "Mgori",
        "youremail": "E-maili:",
        "yourrealname": "Coxo skani:",
        "yourlanguage": "Nena skani:",
-       "gender-male": "Biç'i",
-       "gender-female": "Bozo (K'ulani)",
+       "gender-male": "Biç'ik wikişi but'k'ape nkturams",
+       "gender-female": "Bozok wikişi but'k'ape nkturams",
        "email": "E-maili",
        "group": "Grubi:",
+       "group-user": "K'oçepe",
+       "group-bot": "Botepe",
        "group-sysop": "Adminepe",
+       "group-all": "(iri)",
        "grouppage-sysop": "{{ns:project}}:Adminepe",
+       "right-read": "But’k’ape ik’itxi",
+       "right-edit": "But'k'ape nkturi",
        "right-delete": "Am sayfape jili",
        "newuserlogpage": "Ağani maxmareş kʼayitʼepe",
        "rightslog": "Maxmareş hakʼişi kʼayitʼepe",
        "recentchanges": "Çodinaşi oktirobape",
        "recentchanges-legend": "Çodinaşi oktirobape tercihepe",
        "recentchanges-feed-description": "Am feedis vikiʼs na ixvenu irişen sonni oktirobape gatxozi.",
-       "rclistfrom": "$1 tarixişen doni na ixvenu oktirobape ko3ʼiri",
+       "rclistfrom": "$3 $2 tarixişen doni na ixvenu oktirobape ko3ʼiri",
        "rcshowhideminor": "çʼitʼa oktirobape $1",
+       "rcshowhideminor-show": "Ko3ʼiri",
+       "rcshowhideminor-hide": "Şinaxi",
        "rcshowhidebots": "botʼepe $1",
+       "rcshowhidebots-show": "Ko3ʼiri",
+       "rcshowhidebots-hide": "Şinaxi",
        "rcshowhideliu": "meçʼareri maxmarepe $1",
+       "rcshowhideliu-show": "Ko3ʼiri",
+       "rcshowhideliu-hide": "Şinaxi",
        "rcshowhideanons": "anonimuri maxmarepe $1",
+       "rcshowhideanons-show": "Ko3ʼiri",
+       "rcshowhideanons-hide": "Şinaxi",
+       "rcshowhidepatr-show": "Ko3ʼiri",
+       "rcshowhidepatr-hide": "Şinaxi",
        "rcshowhidemine": "çkimi oktirobape $1",
+       "rcshowhidemine-show": "Ko3ʼiri",
+       "rcshowhidemine-hide": "Şinaxi",
        "rclinks": "Çodinaşi $2 ndğas na ixvenu çodinaşi $1 oktiroba ko3ʼiri;<br /> $3",
        "diff": "farkʼi",
        "hist": "tarixi",
        "recentchangeslinked-to": "Na niçinen butʼkʼa yeine na niçinen butʼkʼaşa kʼontʼaktʼi meçameri na renan butʼkʼape ko3ʼiri",
        "upload": "Dosya doloxe kamaxvi",
        "uploadlogpage": "Dosya oncğonu kʼayitʼepe",
-       "uploadedimage": "Siteşa na incğonen resimi: \"[[$1]]\"",
        "license-header": "Lisans",
        "file-anchor-link": "Dosya",
        "filehist": "Dosyaşi tarixi",
        "booksources-go": "İgzali",
        "log": "Kʼayitʼepe",
        "allpages": "Mteli butʼkʼape",
-       "alphaindexline": "$1 butʼkʼa muşişen $2 butʼkʼa muşişa",
        "prevpage": "İptineri butʼkʼa ($1)",
        "allpagesfrom": "Olistʼeluşa na geiçʼkʼasen harfepe:",
        "allpagesto": "Amu kʼala na içodu butʼkʼape ko3ʼiri:",
index d71bd77..b1d5f3b 100644 (file)
@@ -17,7 +17,8 @@
                        "Rillke",
                        "Umeshberma",
                        "Vinitutpal",
-                       "아라"
+                       "아라",
+                       "बिप्लब आनन्द"
                ]
        },
        "tog-underline": "लिंककेँ रेखांकित करू:",
@@ -25,7 +26,7 @@
        "tog-hidepatrolled": "सन्निकट परिवर्त्तनमे छोट परिवर्त्तन नुकाऊ",
        "tog-newpageshidepatrolled": "नियंत्रित सम्पादनकेँ नव पन्ना सूचीसँ नुकाऊ",
        "tog-extendwatchlist": "ध्यानसूचीमे सभ परिवर्तन देखाऊ,खाली हालक परिवर्तन नै",
-       "tog-usenewrc": "नà¥\80à¤\95 à¤¸à¤¨à¥\8dनिà¤\95à¤\9f à¤ªà¤°à¤¿à¤µà¤°à¥\8dतà¥\8dतन à¤ªà¥\8dरयà¥\8bà¤\97 à¤\95रà¥\82 (à¤\9cावासà¥\8dà¤\95à¥\8dरिपà¥\8dà¤\9f à¤\9aाहà¥\80)",
+       "tog-usenewrc": "नीक सन्निकट परिवर्तन प्रयोग करू (जावास्क्रिप्ट चाही)",
        "tog-numberheadings": "शीर्षक स्वयं-क्रमांकित करू",
        "tog-showtoolbar": "संपादन ओजारपेटी देखाऊ (जावास्क्रीप्ट)",
        "tog-editondblclick": "दू बेर क्लीक कए पन्ना संपादित करू (जावास्क्रीप्ट)",
@@ -34,6 +35,7 @@
        "tog-watchdefault": "हमर संपादित पृष्ठ हमर साकांक्ष सूचीमे देखाऊ",
        "tog-watchmoves": "हमरा द्वारा हटाओल पृष्ठ हमर साकांक्ष सूचीमे राखू",
        "tog-watchdeletion": "हमरा द्वारा हटाओल पृष्ठ हमर साकांक्ष सूचीमे राखू",
+       "tog-watchrollback": "हमरा द्वारा जोडलगेल पृष्ठ हमार सांकक्ष सूचीमे राखू",
        "tog-minordefault": "हमर सभ सम्पादन पूर्वन्यस्त रूपेँ मामूली कहू",
        "tog-previewontop": "संपादन पेटीक ऊपर दृश्य देखाऊ",
        "tog-previewonfirst": "पहिल सम्पादनक बाद पूर्वावलोकन देखाउ",
@@ -56,6 +58,8 @@
        "tog-diffonly": "फाइल-अन्तर प्रणालीक नीचाँ पन्नाक सामिग्री नै देखाउ",
        "tog-showhiddencats": "नुकाएल संवर्ग देखाउ",
        "tog-norollbackdiff": "प्रत्यावर्तनक बाद फाइल-अन्तर प्रणालीकेँ बिसरू",
+       "tog-useeditwarning": "जब हम कोनो संपादन पृष्ठके बिना सुरक्षित केनै बदलाव संग छोइड दि त हमरा सूचित करु ।",
+       "tog-prefershttps": "सम्प्रवेशित करलाक बाद सदैव सुरक्षित कनेक्शनके प्रयोग करु",
        "underline-always": "सदिखन",
        "underline-never": "कखनो नै",
        "underline-default": "पूर्वन्यस्त गवेषक",
        "oct": "अक्टू.",
        "nov": "नव.",
        "dec": "दिस.",
+       "january-date": "जनवरी $1",
+       "february-date": "फरवरी $1",
+       "march-date": "मार्च $1",
+       "april-date": "अप्रैल $1",
+       "may-date": "मई $1",
+       "june-date": "जून $1",
+       "july-date": "जुलाई $1",
+       "august-date": "अगस्त $1",
+       "september-date": "सितम्बर $1",
+       "october-date": "अक्टूबर $1",
+       "november-date": "नवम्बर $1",
+       "december-date": "दिसम्बर $1",
        "pagecategories": "{{PLURAL:$1|खाढी|कएटा खाढी}}",
        "category_header": "संवर्ग \"$1\" मे पन्ना सभ",
        "subcategories": "उपसंवर्ग",
        "newwindow": "(नव खिड़कीसँ खुजैछ)",
        "cancel": "समाप्त",
        "moredotdotdot": "आर...",
+       "morenotlisted": "ई पुरा सूची नै अछी ।",
        "mypage": "हमर पन्ना",
        "mytalk": "वार्त्ता",
        "anontalk": "ऐ अनिकेत पता लेल विमर्श",
        "actions": "क्रिया सभ",
        "namespaces": "चेन्हासी समूह सभ",
        "variants": "प्रकार सभ",
+       "navigation-heading": "दिक्चालन सूची",
        "errorpagetitle": "गलती",
        "returnto": "$1 पर घुरु।",
        "tagline": "कतयसँ {{SITENAME}}",
        "permalink": "स्थायी लिंक",
        "print": "छापू",
        "view": "देखू",
+       "view-foreign": "$1 पर देखु",
        "edit": "संपादन",
+       "edit-local": "स्थानीय विवरण संपादन",
        "create": "बनाउ",
+       "create-local": "स्थानीय विवरण निर्माण",
        "editthispage": "एहि पृष्ठक संपादन",
        "create-this-page": "ई पन्ना बनाउ",
        "delete": "मेटाउ",
        "deletethispage": "ई पन्ना मेटाउ",
+       "undeletethispage": "ई पन्ना मेटाउ",
        "undelete_short": "आपस आनू  {{PLURAL:$1|एक सम्पादनt|$1 सम्पादन सभ}}",
        "viewdeleted_short": "देखू {{PLURAL:$1|एकटा मेटाएल सम्पादन|$1 मेटाएल सम्पादन सभ}}",
        "protect": "बचाउ",
        "talkpagelinktext": "कहू",
        "specialpage": "विशेष पन्ना",
        "personaltools": "व्यक्तिगत उपकरण",
-       "postcomment": "नव खण्ड",
        "articlepage": "विषय-सूची पन्ना देखू",
        "talk": "वार्तालाप",
        "views": "दृष्टि",
        "jumptonavigation": "हेलू",
        "jumptosearch": "ताकू",
        "view-pool-error": "दुखी छी, वितरक सभ एखन व्यस्त अछि।\nबड्ड बेशी लोक ऐ पन्नाकेँ देखबामे लागल छथि।\nऐ पन्नाकेँ फेरसँ देखबा लेल कनी बिलमू। \n$1",
+       "generic-pool-error": "दुखी छी, वितरक सभ एखन व्यस्त अछि।\nबड्ड बेशी लोक ऐ पन्नाकेँ देखबामे लागल छथि।\nऐ पन्नाकेँ फेरसँ देखबा लेल कनी बिलमू। \n$1",
        "pool-timeout": "प्रतीक्षा निगृहीत कालावसान",
        "pool-queuefull": "प्रतीक्षा-पाँती पौती भरल",
        "pool-errorunknown": "अज्ञात भ्रम",
+       "pool-servererror": "पूल काउंटर सेवा उपलब्ध नै अछि ($1)।",
        "aboutsite": "विषयमे {{SITENAME}}",
        "aboutpage": "Project:विवरण",
        "copyright": "$1क अंतर्गत विषय सूची उपलब्ध अछि",
        "backlinksubtitle": "← $1",
        "retrievedfrom": "प्राप्ति स्थल \"$1\"",
        "youhavenewmessages": "अहाँ लग अछि $1 ($2).",
+       "youhavenewmessagesfromusers": "अहाके लेल {{PLURAL:$3|एक अन्य सदस्य|$3 अन्य सदस्यसभ}} के $1 छि । ($2)",
+       "youhavenewmessagesmanyusers": "अहाके $1 छि । ($2)",
+       "newmessageslinkplural": "{{PLURAL:$1|एगो नया पत्र|999=नया पत्र}}",
+       "newmessagesdifflinkplural": "$1 {{PLURAL:$1|परिवर्तन|परिवर्तन सभ}}",
        "youhavenewmessagesmulti": "$1 पर अहाँ लेल नव सन्देश अछि",
        "editsection": "संपादन करू",
        "editold": "सम्पादित करू",
        "hidetoc": "नुकाऊ",
        "collapsible-collapse": "भखड़ाउ",
        "collapsible-expand": "बढ़ाउ",
+       "confirmable-confirm": "कि {{GENDER:$1|अहाँ}} छी?",
+       "confirmable-yes": "हँ",
+       "confirmable-no": "नै",
        "thisisdeleted": "देखू वा जाउ $1?",
        "viewdeleted": "देखू $1?",
        "restorelink": "{{PLURAL:$1|एकटा मेटाएल सम्पादन|$1 मेटाएल सम्पादन सभ}}",
        "nospecialpagetext": "<strong> अहाँ एकटा अमान्य पन्नाक आग्रह केने छी। </strong>\nमान्य विशेष पन्नाक सूची एतए अछि [[Special:SpecialPages|{{int:specialpages}}]]।",
        "error": "भ्रम",
        "databaseerror": "दत्तनिधि भ्रम",
+       "databaseerror-text": "डाटाबेस अनुरोध त्रुटि भेल अछि।\nसंभवतः सफ्टवेयरमे गड़बड़ी अछि।",
+       "databaseerror-textcl": "डाटाबेस अनुरोध त्रुटि भेल अछि।",
+       "databaseerror-query": "अनुरोध: $1",
+       "databaseerror-function": "फंक्सन: $1",
+       "databaseerror-error": "त्रुटि: $1",
        "laggedslavemode": "'''चेतौनी:''' पन्नापर सम्भव जे अद्यतन परिवर्तन नै हुअए।",
        "readonly": "दत्तनिधि प्रतिबन्धित",
        "enterlockreason": "प्रतिबन्ध लेल कारण बताउ, संगमे एकटा अंदाज सेहो बताउ जे कखन ई प्रतिबन्ध हटाएल जाएत।",
        "badarticleerror": "ई क्रिया ऐ पन्नापर नै कएल जा सकैए।",
        "cannotdelete": "पन्ना व संचिका \"$1\" मेटाएल नै जा सकल।",
        "cannotdelete-title": "पन्ना \"$1\" नै मेटा सकल",
+       "delete-hook-aborted": "सम्पादन नोकसीसँ खतम भेल।\nई कोनो कारण नै देलक।",
        "badtitle": "खराप शीर्षक",
        "badtitletext": "आग्रह कएल पन्नाक शीर्षक गलत, खाली, वा गलत सम्बन्धित अन्तर-न्हाषा अन्तर विकी शीर्षक छी। ई एक वा बेशी कलाकार युक्त भऽ सकैए जे शीर्षकमे प्रयुक्त नै कएल जा सकैए।",
-       "perfcached": "ई दत्तांश उपस्मृतिक आधारपर अछि आ भऽ सकैए जे अद्यतन नै हुअए। A maximum of {{PLURAL:$1|one result is|$1 results are}} available in the cache.",
+       "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": "जड़ि देखू",
        "namespaceprotected": "अहाँकेँ '''$1''' नाम-पेटारमे सम्पादनक अनुमति नै अछि।",
        "customcssprotected": "अहांकें ऐ सी.एस.एस.पन्नाकें सम्पादित करबाक अधिकार नै अछि, कारण ऐमे दोसर प्रयोक्ताक व्यक्तिगत विकल्प छै।",
        "customjsprotected": "अहांकें ऐ जावास्क्रिप्ट पन्नाकें सम्पादित करबाक अधिकार नै अछि, कारण ऐमे दोसर प्रयोक्ताक व्यक्तिगत विकल्प छै।",
+       "mycustomcssprotected": "अहाके लेल ई CSS पन्नाके सम्पादित करवाक अधिकार नै अछि।",
+       "mycustomjsprotected": "अहके लेल इ जावास्क्रिप्ट पन्नाके सम्पादित करवाक अधिकार नै अछि।",
+       "myprivateinfoprotected": "अहाके अपन व्यक्तिगत जानकारी बदलैक अनुमति नै अछि।",
+       "mypreferencesprotected": "अहाके अपन प्राथमिकता बदलैक अनुमति नै अछि।",
        "ns-specialprotected": "विशेष पन्ना सभकेँ सम्पादित नै कएल जा सकैए।",
        "titleprotected": "ऐ शीर्षकक निर्माण प्रतिबन्धित अछि [[User:$1|$1]] द्वारा।\nकारण एतऽ देल अछि \"''$2''\"।",
+       "filereadonlyerror": "\"$1\" फाइलके बदलैलेल अक्षम कियाक भण्डार \"$2\" इ समय 'मात्र पाठन के लेल' (रीड ओनली) अछि।\n\nजे प्रबंधक इ प्रबंध लगोनै अछि हुनका निम्न विवरण प्रदान कएल गेल अछि: \"$3\"।",
+       "invalidtitle-knownnamespace": "\"$2\" नामस्थान आर \"$3\" नाम बला गलत शीर्षक",
+       "invalidtitle-unknownnamespace": "अज्ञात नामस्थान संख्या $1 आर नाम \"$2\" वाला गलत शीर्षक",
+       "exception-nologin": "सम्प्रवेशित नै",
+       "exception-nologin-text": "इ पन्ना वा काजके सक्षम करवाक लेल कृपया प्रवेश करु।",
+       "exception-nologin-text-manual": "इ पन्ना वा काजके सक्षम करवाक लेल कृपया $1 करु।",
        "virus-badscanner": "खराप विन्यास: अज्ञात विषविधि बिम्बक: ''$1''",
        "virus-scanfailed": "बिम्ब विफल (विध्यादेश $1)",
        "virus-unknownscanner": "अज्ञात विषविधि निरोधक",
        "logouttext": "'''अहाँ निष्क्रमण कऽ गेल छी।'''\n\nअहाँ {{अन्तर्जाल}} प्रयोग अनाम भऽ कऽ सकै छी, वा अहाँ <span class='plainlinks'>[$1 log in again]</span> वएह आकि कोनो आन प्रयोक्ताक रूपमे सेहू प्रयोक कऽ सकै छी।\nई मोन राखू जे किछु पन्ना एना देखा पड़ि सकैए जेना अहाँ अखनो सम्प्रवेशित होइ, जावत अहाँ अपन गवेषकक उपस्मृति मेटा नै दै छी।",
+       "welcomeuser": "अहाके स्वागत अछि, $1!",
+       "welcomecreation-msg": "अहाके खाता बनावोल गेल अछि ।\nअपन [[Special:Preferences|{{SITENAME}} प्राथमिकतासभ]] बदलैल नै बिसरब।",
        "yourname": "प्रयोक्ता:",
+       "userlogin-yourname": "प्रयोक्ता:",
+       "userlogin-yourname-ph": "अपन प्रयोक्तानाम लिखु",
+       "createacct-another-username-ph": "एकटा प्रयोक्तानाम लिखू:",
        "yourpassword": "कूटशब्द:",
+       "userlogin-yourpassword": "कूटशब्द:",
+       "userlogin-yourpassword-ph": "अपन कूटशब्द लिखु",
+       "createacct-yourpassword-ph": "कूटशब्द ई ठाम राखु",
        "yourpasswordagain": "कूटशब्द फेरसँ टाइप करू:",
+       "createacct-yourpasswordagain": "कूटशब्दके जाँच करु",
+       "createacct-yourpasswordagain-ph": "कूटशब्द पुनः लिखु",
        "remembermypassword": "हमर सम्प्रवेश ऐ गवेषकपर मोन राखू (बेशीसँ बेशी $1 {{PLURAL:$1|दिन|दिन}})",
+       "userlogin-remembermypassword": "हमरा सम्प्रवेशित राखु",
+       "userlogin-signwithsecure": "सुरक्षित कनेक्शनके प्रयोग करु",
        "yourdomainname": "अहाँक प्रभावक्षेत्र:",
+       "password-change-forbidden": "अहा इ विकिमे कूटशब्द नै बदल सकैत छि ।",
        "externaldberror": "खाहे सत्यापन दतांश भ्रम छल वा अहाँ अपन बाह्य खाताकेँ अद्यतन करबामे असमर्थ छी।",
        "login": "सम्प्रवेश",
        "nav-login-createaccount": "सदस्य लॉग इन",
-       "loginprompt": "{{अन्तर्जाल}} सम्प्रवेश लेल अहाँकेँ आवश्यक रूपेँ ज्ञापक सक्रिय करबाक चाही।",
        "userlogin": "लॉग इन / खेसरा बनाऊ",
        "userloginnocreate": "सम्प्रवेश",
        "logout": "निष्क्रमण",
        "userlogout": "फेर आयब",
        "notloggedin": "सम्प्रवेशित नै छी",
+       "userlogin-noaccount": "खाता नै अछि?",
+       "userlogin-joinproject": "{{SITENAME}} से जोडु",
        "nologin": "खाता नै अछि? $1।",
        "nologinlink": "नव खाता खोलू",
        "createaccount": "खाता खोली",
        "gotaccount": "पहिनहियेसँ खाता अछि? $1",
        "gotaccountlink": "सम्प्रवेश",
        "userlogin-resetlink": "अपन सम्प्रवेश विवरण बिसरि गेलहुँ?",
+       "userlogin-resetpassword-link": "अपन कूटशब्द बिसर गेलौ ?",
+       "userlogin-helplink2": "सम्प्रवेशित करवाकलेल मदत",
+       "createacct-emailrequired": "ई-पत्र संकेत",
+       "createacct-emailoptional": "ई-पत्र संकेत (वैकल्पिक)",
+       "createacct-email-ph": "अपन ई-पत्र संकेत सत्यापित करू",
+       "createacct-another-email-ph": "ई-पत्र संकेत सत्यापित करू",
        "createaccountmail": "ई-पत्र द्वारा",
+       "createacct-realname": "असली नाम (वैकल्पिक)",
        "createaccountreason": "कारण:",
+       "createacct-reason": "कारण:",
+       "createacct-reason-ph": "अहा इगो आर दोसर खाता कियाक बनउने जा रहल छि",
+       "createacct-captcha": "सुरक्षा जाँच",
+       "createacct-imgcaptcha-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कृपा कऽ ओकरा सक्रिय करू आ फेरसँ प्रयास करू।",
        "emailconfirmlink": "अपन ई-पत्र संकेत सत्यापित करू",
        "invalidemailaddress": "अमान्य प्रारूपक कारण ऐ ई-पत्र संकेतकेँ स्वीकार नै कएल जा सकैए।\nएकटा मान्य ई-पत्र संकेत लिखू वा ओइ स्थानकेँ खाली करू।",
        "cannotchangeemail": "खाता ई-पत्र संकेत ऐ विकीपर बदलल नै जा सकैए।",
+       "emaildisabled": "ई साइट ई-पत्र नै पठाएत।",
        "accountcreated": "खाता खुजि गेल",
        "accountcreatedtext": "$1 लेल प्रयोक्ता खाता खुजि गेल।",
        "createaccount-title": "{{अन्तर्जाल}} लेल खाता निर्माण",
        "login-abort-generic": "अहाँक सम्प्रवेश सफल नै भेल- खतम",
        "loginlanguagelabel": "भाषा : $1",
        "suspicious-userlogout": "अहाँक निष्क्रमणक अनुरोध नै मानल गेल कारण ई लागल जे ई पुरान गवेषकक लागि वा दोसराइत उपस्मृति द्वारा पठाओल गेल छल।",
+       "createacct-another-realname-tip": "मूल नाम वैकल्पिक अछि।\nजँ अहाँ एकरा देबा लेल प्रयोग करै छी, ई अहाँकेँ काजक श्रेय देबा लेल एकर प्रयोग कएल जाएत।",
+       "pt-login": "सम्प्रवेश",
+       "pt-login-button": "सम्प्रवेश",
+       "pt-createaccount": "खाता खोली",
+       "pt-userlogout": "निष्क्रमण",
        "php-mail-error-unknown": "पी.एच.पी.क संदेश कार्य() मे अज्ञात दोष",
        "user-mail-no-addy": "बिन ई-पत्र संकेतक ई-पत्र पठेबाक प्रयास",
+       "user-mail-no-body": "एकटा खाली वा बहुत कनिका ई-पत्र भेजवाक प्रयास कल गेल ।",
        "changepassword": "कूटशब्द बदलू",
-       "resetpass_announce": "अहाँ अस्थायी ई-पत्र विध्यादेशसँ सम्प्रवेश केने छी।\nसम्प्रवेश सम्पूर्ण करबा लेल, अहाँ एकटा नव कूटशब्द एतए निर्धारित करू:",
+       "resetpass_announce": "अहाँ अस्थायी ई-पत्र विध्यादेशसँ सम्प्रवेश केने छी।\nसम्प्रवेश सम्पूर्ण करबा लेल, अहाँ एकटा नव कूटशब्द एतए निर्धारित करू:",
        "resetpass_text": "<!-- पाठ एतऽ लिखू -->",
        "resetpass_header": "खाता कूटशब्द बदलू",
        "oldpassword": "पुरान कूटशब्द",
        "newpassword": "नव कूटशब्द",
        "retypenew": "नव कूटशब्द फेरसँ टंकित करू",
        "resetpass_submit": "कूटशब्द बनाउ आ सम्प्रवेश करू",
-       "changepassword-success": "अहाँक कूटशब्द सफलतासँ बदलि देल गेल!\nआब अहाँकेँ सम्प्रवेशित कऽ रहल छी...",
+       "changepassword-success": "अहाँक कूटशब्द सफलतासँ बदलि देल गेल!",
+       "changepassword-throttled": "अहाँ ढ़ेर रास सम्प्रवेश प्रयास केलहुँ।\nफेर प्रयास करबासँ पहिने कने काल थम्हू।",
        "resetpass_forbidden": "कूटशब्द सभ नै बदलल जा सकैए।",
        "resetpass-no-info": "अहाँकेँ ऐ पन्नाकेँ पढ़बाले सम्प्रवेशित हुअए पड़त।",
        "resetpass-submit-loggedin": "कूटशब्द बदलू",
        "resetpass-submit-cancel": "खतम करू",
        "resetpass-wrong-oldpass": "अमान्य अस्थायी वा अखुनका कूटशब्द।\nअहाँ पहिनहिये सफलतासँ कूटशब्द बदलि लेने छी वा एकटा नव अस्थायी कूटशब्द लेल आग्रह केने छी।",
+       "resetpass-recycled": "रीसेट करएके लेल नयाँ कूटशब्दमे कृपया अपन वर्तमान कूटशब्द नै द के नयाँ देल जाउ।",
        "resetpass-temp-password": "तात्कालिक कूटशब्द",
+       "resetpass-abort-generic": "कूटशब्दमें बदलाव कोनो एक्सटेंशन द्वारा रोक देल गएल अछि ।",
+       "resetpass-expired": "अहाँके कूटशब्दक वैधता अवधि खत्तम भ गेल अछि । कृपया सम्प्रवेशित करवाक लेल नयाँ कूटशब्द राखु।",
        "passwordreset": "कूटशब्द फेरसँ बनाउ",
+       "passwordreset-text-one": "अपन कूटशब्द रीसेट करवाक लेल इ फारम भरु ।",
+       "passwordreset-text-many": "{{PLURAL:$1|ई-पत्रके माध्यमसऽ एकटा अस्थायी कूटशब्द पावैलेल कोनो एकटा डिब्बा भरु ।}}",
        "passwordreset-legend": "कूटशब्द फेरसँ बनाउ",
        "passwordreset-disabled": "कूटशब्द फेरसँ बनाएब ऐ विकीपर अक्षम कएल अछि।",
+       "passwordreset-emaildisabled": "कूटशब्द फेरसँ बनाएब ऐ विकीपर अक्षम कएल अछि।",
        "passwordreset-username": "प्रयोक्तानाम",
        "passwordreset-domain": "क्षेत्र:",
        "passwordreset-capture": "परिणाम ई-पत्र देखू?",
        "changeemail-oldemail": "अखुनका ई-पत्र संकेत:",
        "changeemail-newemail": "नव ई-पत्र संकेत:",
        "changeemail-none": "(कोनो नै)",
+       "changeemail-password": "अहाके {{SITENAME}} कूटशब्द:",
        "changeemail-submit": "ई-पत्र संकेत बदलू",
        "changeemail-cancel": "खतम",
+       "changeemail-throttled": "अहाँ ढ़ेर रास सम्प्रवेश प्रयास केलहुँ।\nफेर प्रयास करबासँ पहिने कने काल थम्हू।",
+       "resettokens": "टोकन रीसेट करी",
+       "resettokens-no-tokens": "रीसेट करवाक लेल कोनो टोकन नै अछि।",
+       "resettokens-legend": "टोकन रीसेट करी",
+       "resettokens-tokens": "टोकन:",
+       "resettokens-token-label": "$1 (वर्तमान मूल्य: $2)",
+       "resettokens-done": "टोकन रीसेट भेल अछि।",
+       "resettokens-resetbutton": "छानल टोकन रीसेट करु",
        "bold_sample": "गँहीर लेखन",
        "bold_tip": "गँहीर लेखन",
        "italic_sample": "कटि लेखन",
        "updated": "(अद्यतन  कएल)",
        "note": "'''टिप्पणी:'''",
        "previewnote": "'''मोन राखू ई मातर पूर्वावलोकन छी।'''\nअहाँक परिवर्तन अखन धरि सँचिआएल नै गेल अछि!",
+       "continue-editing": "संपादन क्षेत्र जाउ",
        "previewconflict": "ई पूर्वदृश्य देखबैए उपरका सम्पादन क्षेत्रक पाठ , ई आएत जखन अहाँ संरक्षित करब।",
        "session_fail_preview": "''' दुखी छी! अहाँक सत्रक दत्तांश खतम भऽ गेल तै कारणसँ अहाँक सम्पादनक निपटारा नै भऽ सकल।'''\nफेरसँ प्रयास करू।\nजँ ई फेरसँ काज नै करैए, प्रयोग करू [[Special:UserLogout|निष्क्रमण]] आ फेर सम्प्रवेश करू।",
        "session_fail_preview_html": "''' दुखी छी! हम अहाँक सम्पादनक निष्पादन नै कऽ सकलहुँ कारण सत्रक दत्तांश खतम भऽ गेल।'''\n''कारण {{अन्तर्जाल}} लग काँच एच.टी.एम.एल. दत्तांश सक्रिय छै, पूर्वदृश्य जावास्क्रिप्ट आक्रमणक डरसँ नुकाएल राखल गेल अछि।''\n'''जँ ई वैध सम्पादन प्रयास अछि, कृपा कऽ पुनः प्रयास करू।'''\nजँ ई अखनो काज नै कऽ रहल अछि, प्रयास करू [[Special:UserLogout|निष्क्रमण कऽ रहल छी]] आ फेरसँ सम्प्रवेश।",
        "token_suffix_mismatch": "'''अहाँक सम्पादन अस्वीकार कऽ देल गेल अछि कारण अहाँक ग्राहक प्रेष्यमान अंक विधानक विराम चेन्ह सभकेँ नष्ट कऽ देलन्हि।'''\nई सम्पादन पन्नाक पाठकेँ दूषित होएबासँ बचेबा लेल अमान्य कऽ देल गेल।\nई कखनो काल होइए जखन अहाँ जाल आधारित अनाम दोसरा लेल चल सेवा प्रयुक्त करै छी।",
        "edit_form_incomplete": "'''सम्पादन आवेदनक किछु भाग वितरक धरि नै पहुँचल; एक बेर फेर देखू जे अहाँक सम्पादन दुरुस्त अछि आ फेरसँ प्रयास करू।'''",
        "editing": "सम्पादन होइए $1",
+       "creating": "$1 बनाउ",
        "editingsection": "सम्पादन कऽ रहल छी $1 (खण्ड)",
        "editingcomment": "सम्पादन कऽ रहल छी $1 (नव खण्ड)",
        "editconflict": "सम्पादन अन्तर: $1",
        "edit-gone-missing": "पन्ना अद्यतन नै भऽ सकल।\nलगैए जे ई मेटा देल गेल अछि।",
        "edit-conflict": "सम्पादन अन्तर",
        "edit-no-change": "अहाँक सम्पादनपर ध्यान नै देल गेल, कारण ऐ सँ पाठमे कोनो परिवर्तन नै आएल।",
+       "postedit-confirmation-created": "पन्ना निर्माण करल गेल अछि ।",
+       "postedit-confirmation-restored": "पन्नाके पुराण स्थितिमे लौने गेल अछि ।",
+       "postedit-confirmation-saved": "अहाके संपादनके सुरक्षित भेल ।",
        "edit-already-exists": "नव पन्नाक निर्माण नै भऽ सकल।\nई पहिनहियेसँ वर्तमान अछि।",
+       "defaultmessagetext": "पूर्वनिर्धारित संदेश पाठ",
+       "invalid-content-data": "अवैध डाटा सामग्री",
+       "editpage-notsupportedcontentformat-title": "सामग्री स्वरूप समर्थित नै अछि",
+       "content-model-wikitext": "विकिटेक्स्ट",
+       "content-model-text": "सामान्य पाठ",
+       "content-model-javascript": "जावास्क्रिप्ट",
+       "content-model-css": "सी॰एस॰एस",
        "expensive-parserfunction-warning": "'''चेतौनी:''' ई पन्ना बड्ड बेसी महग विभाजक प्रकार्य आह्वान करैत अछि।\n एकरा $2 सँ कम {{PLURAL:$2|call|calls}}, ओतऽ {{PLURAL:$1|ई अछि $1 call|ई सभ अछि $1 calls}}",
        "expensive-parserfunction-category": "बड बेसी महग विभाजक आह्वानबला पन्ना सभ",
        "post-expand-template-inclusion-warning": "'''चेतौनी:''' नमूना लेबाक आकार बड्ड पैघ अछि।\nकिछु नमूना नै लेल जा सकत।",
        "revertmerge": "नै मिज्झर",
        "mergelogpagetext": "नीचाँ एक पन्ना इतिहासक दोसरमे अद्यतन मिश्रणक सूची अछि।",
        "history-title": "\"$1\" क संशोधन इतिहास",
+       "difference-title": "\"$1\" के अवतरणसभमे अंतर",
+       "difference-title-multipage": "\"$1\" आर \"$2\" पृष्ठसभ मे अंतर",
        "difference-multipage": "(पन्ना सभक बीचमे अन्तर)",
        "lineno": "पंक्त्ति $1:",
        "compareselectedversions": "चयन कएल संशोधन सभक तुलना करू",
        "showhideselectedversions": "देखाउ/ नुकाउ चयनित संशोधन सभ",
        "editundo": "असंपादन",
+       "diff-empty": "(कोनो अंतर नै)",
+       "diff-multi-sameuser": "(इ प्रयोक्ताद्वारा {{PLURAL:$1|कएल गेल बीचके एक अवतरण नै देखाओल गेल |कएल गेल बीचके $1 अवतरण नै देखाओल गेल}})",
+       "diff-multi-otherusers": "({{PLURAL:$1|एकटा मध्यस्थ संशोधन|$1 मध्यस्थ संशोधन सभ}} $2 सँ बेसी {{PLURAL:$2|प्रयोक्ता|प्रयोक्ता सभ}} नै देखाएल)",
        "diff-multi-manyusers": "({{PLURAL:$1|एकटा मध्यस्थ संशोधन|$1 मध्यस्थ संशोधन सभ}} $2 सँ बेसी {{PLURAL:$2|प्रयोक्ता|प्रयोक्ता सभ}} नै देखाएल)",
+       "difference-missing-revision": "इ अंतर {{PLURAL:$2|के एकटा अवतरण|के $2 अवतरण}} ($1) नै {{PLURAL:$2|पाओल गेल|पाओल गेल}}।\n\nइ सामन्य ढंगमे हटाओल गेल पृष्ठके अवतरसभ मे अंतर खोजला स होएत अछि । आर जानकारी [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} हटाओल लग] मे भेट सकैत अछि।",
        "searchresults": "तकबाक फलाफल",
        "searchresults-title": "तकबाक फलाफल \"$1\" लेल",
        "titlematches": "पन्ना शीर्ष मेल",
        "searchprofile-advanced-tooltip": "बनाएल नामस्थान सभमे ताकू",
        "search-result-size": "$1 ({{PLURAL:$2|1 शब्द|$2 शब्द सभ}})",
        "search-result-category-size": "{{PLURAL:$1|1 सदस्य|$1 सदस्य}} ({{PLURAL:$2|1 उपसंवर्ग|$2 उपसंवर्ग}}, {{PLURAL:$3|1 संचिका|$3 संचिका}})",
-       "search-result-score": "काज: $1%",
        "search-redirect": "(रस्ता बदलेन $1)",
        "search-section": "(शाखा $1)",
+       "search-file-match": "(फाइल सामग्रीसे मेल खेलक अछि)",
        "search-suggest": "अहाँ मोने अछि जे:$1",
        "search-interwiki-caption": "सम्बन्धित परियोजना सभ",
        "search-interwiki-default": "$1 सभटा परिणाम:",
        "searchrelated": "सम्बन्धी",
        "searchall": "सभटा",
        "showingresults": "नीचाँ एतऽ धरि {{PLURAL:$1|'''1''' परिणाम|'''$1''' परिणाम सभ}}  #'''$2''' सँ प्रारम्भ भऽ कऽ।",
-       "showingresultsheader": "{{PLURAL:$5|परिणाम '''$1''' एकर '''$3'''|परिणाम सभ '''$1 - $2''' एकर '''$3'''}} ऐ लेल '''$4'''",
+       "showingresultsinrange": "नीचाँ एतऽ धरि {{PLURAL:$1|'''1''' परिणाम|'''$1''' परिणाम सभ}}  #'''$2''' सँ प्रारम्भ भऽ कऽ।",
        "search-nonefound": "अभ्यर्थनासँ मेल खाइत कोनो परिणाम नै भेटल।",
        "powersearch-legend": "विशेष खोज",
        "powersearch-ns": "निर्धारकमे खोज",
        "powersearch-togglelabel": "जाँचू:",
        "powersearch-toggleall": "सभटा",
        "powersearch-togglenone": "कोनो नै",
+       "powersearch-remember": "याद राखु भविष्यकऽ खोजीके लेल",
        "search-external": "बाह्य खोज",
        "searchdisabled": "{{अन्तर्जाल}} खोज बन्न अछि।\nअहाँक गूगलक माध्यमसँ ऐ बीच ताकि सकै छी।\nमोन राखू जे तकर विवरणी {{अन्तर्जाल}} सामिग्री समयातीत भऽ सकैए।",
+       "search-error": "खोजवाके समय निम्न त्रुटि उत्पन्न भेल: $1",
        "preferences": "विकल्प",
        "mypreferences": "खासमखास",
        "prefs-edits": "सम्पादनक संख्या",
+       "prefsnologintext2": "अपन वरीयतासभके बदलैक लेल $1 करू।",
        "prefs-skin": "रूप",
        "skin-preview": "पूर्वावलोकन",
        "datedefault": "कोनो मोनपसंद नै",
        "prefs-labs": "प्रायोगिक गुण सभ",
+       "prefs-user-pages": "उपयोगकर्ताक पृष्ठ",
        "prefs-personal": "प्रयोक्ता परिचय",
        "prefs-rc": "हालक परिवर्तन",
        "prefs-watchlist": "साकांक्ष-सूची",
        "prefs-watchlist-days": "साकांक्ष-सूचीमे एतेक दिन देखाएल:",
-       "prefs-watchlist-days-max": "Maximum $1 {{PLURAL:$1|day|days}}",
+       "prefs-watchlist-days-max": "बेसीसँ बेसी $1 {{PLURAL:$1|दिन|दिन}}",
        "prefs-watchlist-edits": "बढ़ाएल साकांक्ष सूचीमे अधिकतम परिवर्तन देखाएब:",
        "prefs-watchlist-edits-max": "बेसीसँ बेसी:१०००",
        "prefs-watchlist-token": "साकांक्ष-सूची खेप:",
        "recentchangesdays-max": "बेसीसँ बेसी $1 {{PLURAL:$1|दिन|दिन}}",
        "recentchangescount": "पूर्वनिर्धारित रूपेँ एतेक सम्पादन देखाएल गेल:",
        "prefs-help-recentchangescount": "ऐ मे सम्मिलित अछि आइ-काल्हिक परिवर्तन, पन्नाक इतिहास आ वृत्तलेख",
+       "prefs-help-watchlist-token2": "इ अहाँके कंक्षाकसूचीके वेब फिडके गोपनीय चाभी छी ।\nइ जे कोइ लंग अछि उ अपन कंक्षाकसूची पैढ सकैत अछि, ऐ लेल इ क्यों गोटा स नै बाटब ।\n[[Special:ResetTokens|एकरा रीसेट करवाक लेल यै ठाम क्लिक करु]]।",
        "savedprefs": "अहाँक पसिन्न सुरक्षित कएल गेल",
        "timezonelegend": "समय क्षेत्र",
        "localtime": "स्थानीय समए:",
        "prefs-dateformat": "तिथिक बगेबानी",
        "prefs-timeoffset": "समए संशोधक",
        "prefs-advancedediting": "विशिष्ट विकल्प सभ",
+       "prefs-editor": "संपादक",
+       "prefs-preview": "पूर्वावलोकन",
        "prefs-advancedrc": "विशिष्ट विकल्प सभ",
        "prefs-advancedrendering": "विशिष्ट विकल्प सभ",
        "prefs-advancedsearchoptions": "विशिष्ट विकल्प सभ",
        "prefs-advancedwatchlist": "विशिष्ट विकल्प सभ",
        "prefs-displayrc": "दृश्य विकल्प सभ",
        "prefs-displaywatchlist": "दृश्य विकल्प सभ",
+       "prefs-tokenwatchlist": "टोकन",
        "prefs-diffs": "अन्तर निर्धारक सभ",
+       "prefs-help-prefershttps": "इ प्राथमिकता अहाँके फेर स सम्प्रवेश करलाक बाद प्रभाव पडत।",
+       "prefs-tabs-navigation-hint": "सुझाव: अहाँ टैब्स सूचीमे टैब्सके बीच आवागमन करवाक लेल बाम आर दाहिना बागलके कुंजिसभके उपयोग कइर सकैत छी।",
        "email-address-validity-valid": "ई-पत्र संकेत मान्य बुझाइत अछि",
        "email-address-validity-invalid": "एकटा मान्य ई-पत्र संकेत लिखू",
        "userrights": "प्रयोक्ता अधिकारक प्रबन्धन",
        "userrights-changeable-col": "वर्ग जे अहाँ बदलि सकै छी",
        "userrights-unchangeable-col": "वर्ग जे अहाँ नै बदलि सकै छी",
        "userrights-irreversible-marker": "$1*",
+       "userrights-conflict": "प्रयोक्ता अधिकार बदलावक समयमे अंतर्विरोध! कृपया अपन बदलाव जाँच करु आ पुनः सुनिश्चित करु।",
+       "userrights-removed-self": "अहाँ सफलतापूर्वक अपन अधिकार हटा देने छी। अतः अहाँ आब ई पृष्ठ नै देख सकैत छी।",
        "group": "वर्ग:",
        "group-user": "प्रयोक्ता सभ",
        "group-autoconfirmed": "स्वतःअनुमोदित प्रयोक्ता सभ",
        "right-move": "पन्ना सभ घसकाउ",
        "right-move-subpages": "पन्ना सभकेँ उपपन्ना सभक संग घसकाउ",
        "right-move-rootuserpages": "मूल प्रयोक्ता पन्ना सभ घसकाउ",
+       "right-move-categorypages": "श्रेणी पृष्ठ स्थानांतरित करू",
        "right-movefile": "संचिका सभकेँ घसकाउ",
        "right-suppressredirect": "पन्ना घसकेबा काल मूल पन्ना सभसँ लागि सभ नै बनाउ",
        "right-upload": "संचिका सभ उपारोपित करू",
        "right-writeapi": "लेख्य ए.पी.आइ.क प्रयोग",
        "right-delete": "पन्ना सभकेँ मेटाउ",
        "right-bigdelete": "बेशी इतिहास बला पन्ना सभकेँ मेटाउ",
+       "right-deletelogentry": "विशिष्ट लग प्रविष्टिसभके नुकाउ आ देखाउ",
        "right-deleterevision": "निर्धारित संशोधित पन्ना मेटाउ आ फेरसँ आनू",
        "right-deletedhistory": "मेटाएल इतिहास प्रविष्टि देखू, बिना लागिक पाठक",
        "right-deletedtext": "मेटाएल पाठ आ दूटा मेटाएल संशोधनक बीचक परिवर्तन देखू",
        "right-browsearchive": "मेटाएल पन्ना सभकेँ ताकू",
        "right-undelete": "पन्ना फेरसँ आनू",
        "right-suppressrevision": "संचालकसँ नुकाएल संशोधनकेँ पुनरीक्षित करू आ फेरसँ आनू",
+       "right-viewsuppressed": "कोनो प्रयोक्ताके नुकाएल संसोधन देखु",
        "right-suppressionlog": "व्यक्तिगत वृत्तलेख देखू",
        "right-block": "दोसर प्रयोक्ताकेँ सम्पादनसँ रोकू",
        "right-blockemail": "प्रयोक्ताकेँ ई-पत्र पठेबासँ रोकू",
        "right-unblockself": "स्वयंकेँ प्रतिबन्धसँ हटाउ",
        "right-protect": "सुरक्षा स्तर बदलू आ संरक्षित पन्ना सम्पादित करू",
        "right-editprotected": "संरक्षित पन्ना सम्पादित करू (बिना तराउपड़ी सुरक्षाक)",
+       "right-editsemiprotected": "संरक्षित पन्ना सम्पादित करू (बिना तराउपड़ी सुरक्षाक)",
        "right-editinterface": "प्रयोक्ता मध्यस्थक सम्पादन करू",
        "right-editusercssjs": "दोसर प्रयोक्ताक सी.एस.एस. आ जावास्क्रिप्ट संचिका सभक सम्पादन करू",
        "right-editusercss": "दोसर प्रयोक्ता सभक सी.एस.एस. संचिका सभक सम्पादन करू",
        "right-edituserjs": "दोसर प्रयोक्ताक जावास्क्रिप्ट संचिका सभक सम्पादन करू",
+       "right-editmyusercss": "अपन प्रयोक्ता स्तरके सी.एस.एस.फाइल स संपादित करु",
+       "right-editmyuserjs": "दोसर प्रयोक्ताक जावास्क्रिप्ट संचिका सभक सम्पादन करू",
+       "right-viewmywatchlist": "अपन काँच साकांक्षसूची देखु",
+       "right-editmywatchlist": "अपनी साकांक्षसूची सम्पादित करु । ध्यान दियो कि कोनो काज इ अधिकारके नै भेलाके बादो साकांक्षसूचीमे पृष्ठ जोडत।",
+       "right-viewmyprivateinfo": "अपन व्यक्तिगत डाटा देखु (जेना ई-मेल पता, असली नाम)",
+       "right-editmyprivateinfo": "अपन व्यक्तिगत डाटा सम्पादित करू (जेना ई-मेल पता, असली नाम)",
+       "right-editmyoptions": "अपन वरीयतासभ सम्पादित करु",
        "right-rollback": "कृपा कऽ अन्तिम प्रयोक्ताक सम्पादन सभकेँ प्रत्यावर्तित करू जे एक खास पन्नाकेँ सम्पादित केलन्हि",
        "right-markbotedits": "प्रत्यावर्तित सम्पादन सभकेँ स्वचालित सम्पादन देखाउ",
        "right-noratelimit": "दरक सीमासँ प्रभावित नै",
        "action-createpage": "पन्ना सभ बनाउ",
        "action-createtalk": "वार्ता पन्ना सभ बनाउ",
        "action-createaccount": "ई प्रयोक्ता खाता बनाउ",
+       "action-history": "पन्नाक इतिहासकेँ मिज्झर करू",
        "action-minoredit": "ऐ सम्पादनकेँ मामूली कहू",
        "action-move": "ऐ पृष्ठकेँ घसकाउ",
        "action-move-subpages": "ऐ पन्ना आ एकर उपपन्नाकेँ घसकाउ",
        "action-move-rootuserpages": "मूल प्रयोक्ता पन्ना सभ घसकाउ",
+       "action-move-categorypages": "श्रेणी पृष्ठ स्थानांतरित करू",
        "action-movefile": "ऐ संचिकाकेँ घसकाउ",
        "action-upload": "ऐ संचिकाकेँ उपारोपित करू",
        "action-reupload": "ऐ संचिकाक पुनर्लेखन करू",
        "action-userrights-interwiki": "दोसर विकीपर प्रयोक्ताक प्रयोक्ता अधिकारक सम्पादन करू",
        "action-siteadmin": "दत्तनिधिकेँ प्रतिबन्धित करू आ फेर प्रतिबन्ध हटाउ",
        "action-sendemail": "ई-पत्र पठाउ",
+       "action-editmywatchlist": "काँच साकांक्षसूची संपादित करू",
+       "action-viewmywatchlist": "अपन काँच साकांक्षसूची देखु",
+       "action-viewmyprivateinfo": "अपन व्यक्तिगत जानकारी देखु",
+       "action-editmyprivateinfo": "अपन व्यक्तिगत जानकारी संपादित करु",
        "nchanges": "$1 {{PLURAL:$1|परिवर्त्तन|परिवर्त्तन}}",
+       "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|अंतिम बेर देखला के बाद स}}",
+       "enhancedrc-history": "इतिहास",
        "recentchanges": "लगक परिवर्तन सभ",
        "recentchanges-legend": "नव परिवर्तन सभक विकल्प सभ",
        "recentchanges-summary": "ऐ पन्नापर विकीमे भेल सभसँ अद्यतन परिवर्तनपर नजरि राखू।",
+       "recentchanges-noresult": "इ अवधिके दौरान इ मापदंडके पूर्ण करेत समय कोनो परिवर्तन नै केएल गेल अछि।",
        "recentchanges-feed-description": "ऐ सूचना-तंत्रांशमे विकीमे भेल सभसँ लगक परिवर्तन ताकू",
        "recentchanges-label-newpage": "ई सम्पादन एकटा नव पन्नाक निर्माण केलक।",
        "recentchanges-label-minor": "ई एकटा लघु सम्पादन छी",
        "recentchanges-label-bot": "ई सम्पादन यांत्रिक छल।",
        "recentchanges-label-unpatrolled": "ऐ सम्पादनक पुनरीक्षण अखन धरि नै कएल गेल अछि।",
+       "recentchanges-label-plusminus": "पन्नाके आकार इ बाइट संख्यासे बदलल गेल",
+       "recentchanges-legend-heading": "'''कुंजी:'''",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|नयाँ पन्नसभके सूची]] सहो देखु)",
        "rcnotefrom": "नीचाँमे '''$2''' सँ भेल परिवर्तन अछि ('''$1''' धरि देखाएल)।",
        "rclistfrom": "$3 $2 सँ शुरू भेल नव परिवर्तन देखू",
        "rcshowhideminor": "$1 अल्प संपादन",
+       "rcshowhideminor-show": "देखाउ",
+       "rcshowhideminor-hide": "नुकाऊ",
        "rcshowhidebots": "$1 स्वचालक सभ",
+       "rcshowhidebots-show": "देखाउ",
+       "rcshowhidebots-hide": "नुकाऊ",
        "rcshowhideliu": "$1 सम्प्रवेशित प्रयोक्ता सभ",
+       "rcshowhideliu-show": "देखाउ",
+       "rcshowhideliu-hide": "नुकाऊ",
        "rcshowhideanons": "$1 अज्ञात प्रयोक्ता सभ",
+       "rcshowhideanons-show": "देखाऊ",
+       "rcshowhideanons-hide": "नुकाऊ",
        "rcshowhidepatr": "$1 संचालित सम्पादन",
+       "rcshowhidepatr-show": "देखाउ",
+       "rcshowhidepatr-hide": "नुकाऊ",
        "rcshowhidemine": "$1 हमर सम्पादन सभ",
+       "rcshowhidemine-show": "देखाउ",
+       "rcshowhidemine-hide": "नुकाऊ",
        "rclinks": "देखाऊ अंतिम $1 परिवर्त्तन अंतिम $2 दिनमे<br />$3",
        "diff": "अंतर",
        "hist": "इति.",
        "rc_categories": "संवर्ग सीमित (\"|\" सँ हटाउ)",
        "rc_categories_any": "कोनो",
        "rc-change-size": "$1",
+       "rc-change-size-new": "बदललाके बाद $1 {{PLURAL:$1|बाइट}}",
        "newsectionsummary": "/* $1 */ नव संवर्ग",
        "rc-enhanced-expand": "वर्णन देखाउ (जावास्क्रिप्ट चाही)",
        "rc-enhanced-hide": "वर्णन नुकाउ",
+       "rc-old-title": "मूल रूप स \"$1\" नाम स बनाएल गेल रह",
        "recentchangeslinked": "संबंधित परिवर्त्तन",
        "recentchangeslinked-feed": "संबंधित परिवर्त्तन",
        "recentchangeslinked-toolbox": "संबंधित परिवर्त्तन",
        "fileexists-shared-forbidden": "ऐ नामसँ एकटा संचिका साझी संचिका बखारीमे पहिनहियेसँ अछि।\nजँ अहाँ अखनो अपन संचिका उपारोपित करए चाहै छी, कृपा कऽ पाछाँ जाउ आ एकटा नव नाम चुनू।\n[[File:$1|thumb|center|$1]]",
        "file-exists-duplicate": "ई फाइल एकर {{PLURAL:$1|file|files}} द्वितीयक अछि:",
        "file-deleted-duplicate": "ऐ संचिका ([[:$1]]) सँ मेल खाइत संचिका पहिनहिये मेटा देल गेल अछि।\nअहाँ ओइ संचिकाक मेटाएल जएबाक इतिहास फेरसँ उपारोपित करबासँ पहिने देखू।",
+       "file-deleted-duplicate-notitle": "ऐ स पहिले इ फाइलके अहिने एगो फाइलके हटाएल गेल अछि , आर शीर्षक नुकाएल गेल अछि।\nएकरा फेर स अपलोड करै स पहिले अहाँ कोनो एहन व्यक्ति स स्थितिके  समीक्षा करै लेल कहु जेकरा लंग नुकाएल गेल फाइल देखवाक क्षमता अछि।",
        "uploadwarning": "उपारोपण चेतौनी",
        "uploadwarning-text": "कृपा कऽ नीचाँ देल संचिका वर्णनकेँ संशोधित करू आ फेरसँ प्रयास करू।",
        "savefile": "संचिका संरक्षण करू",
-       "uploadedimage": "अपलोड भेल \"[[$1]]\"",
-       "overwroteimage": "एकर \"[[$1]]\" नव संस्करण उपारोपित भेल।",
        "uploaddisabled": "उपारोपण सभ अशक्त कएल गेल।",
        "copyuploaddisabled": "सार्वत्रिक विभव संकेत उपारोपण अशक्त कएल गेल।",
        "uploaddisabledtext": "संचिका उपारोपण सभ अशक्त अछि।",
        "php-uploaddisabledtext": "पी.एच.पी.मे संचिका उपारोपण अशक्त अछि।\nकृपा कऽ संचिका उपारोपण विकल्प जाँचू।",
        "uploadscripted": "ई संचिका पर्यंकभाषा वा कूटलिपि युक्त अछि जे गवेषक द्वारा गलत रूपमे व्याख्यायित कएल जा सकैए।",
+       "uploadscriptednamespace": "इ एस॰वी॰जी फाइलमे अमान्य नामस्थान \"$1\" अछि।",
+       "uploadinvalidxml": "अपलोड केएल गेल फाइलमे स्थित XML पार्स नै केएल जा सकैत अछि।",
        "uploadvirus": "ई संचिका विषविधियुक्त अछि।\nवर्णन:$1",
        "uploadjava": "ई संचिका एकटा संकुचित संचिका अछि जइमे अछि एकटा जावा .class संचिका।\nजावा संचिका सभक उपारोपण प्रतिबन्धित अछि, कारण ओ सभ सुरक्षा प्रतिबन्ध सभ छी जकरासँ ई तड़पल जा सकैए।",
        "upload-source": "मूल संचिका",
        "upload-misc-error-text": "उपारोपण काल एकटा विचित्र भ्रम आएल।\nकृपा कऽ जाँचू कि सार्वत्रिक विभव संकेत मान्य आ प्रवेश-उपयुक्त अछि आ फेरसँ प्रयास करू।\nजँ समस्या रहिते अछि तँ [[Special:ListUsers/sysop|संचालक]] सँ सम्पर्क करू।",
        "upload-too-many-redirects": "ई सार्वत्रिक विभव संकेत बड्ड बेसी घुमौआ लागिक संग अछि।",
        "upload-http-error": "परिसंविद भ्रम आएल:$1",
+       "upload-copy-upload-invalid-domain": "कपि अपलोड इ डोमेन स उपलब्ध नै अछि।",
+       "backend-fail-stream": "\"$1\" केँ नै स्ट्रिम क सकल।",
+       "backend-fail-backup": "\"$1\" केँ नै ब्याकअप क सकल।",
+       "backend-fail-notexists": "फाइल $1 नै अछि।",
+       "backend-fail-hashes": "तुलना के लेल फाइलसहके हैश नै मिलल।",
+       "backend-fail-notsame": "एकटा गैर-समान फाइल $1 मे पहिले स अछि।",
+       "backend-fail-invalidpath": "$1 मान्य भंडारण पथ नै छी।",
+       "backend-fail-delete": "\"$1\" फाइल केँ नै मेटा सकल।",
+       "backend-fail-describe": "फाइल \"$1\" के मेटाडाटा बदल नै सकल।",
+       "backend-fail-alreadyexists": "फाइल $1 पहिने स अछि।",
+       "backend-fail-store": "फाइल $1, $2 मे संग्रहीत नै कऽ सकल।",
+       "backend-fail-copy": "फाइल $1 के $2 मे प्रतिलिपि नै कऽ सकल।",
+       "backend-fail-move": "फाइल $1 सऽ $2 मे स्थानांतरित नै भऽ सकल।",
+       "backend-fail-opentemp": "अस्थायी संचिका नै खोइज सकल।",
+       "backend-fail-writetemp": "अस्थायी संचिका पर नै लिखाल जा सकल।",
+       "backend-fail-closetemp": "अस्थायी संचिका नै बन्द भऽ सकल।",
+       "backend-fail-read": "फाइल $1 पैढ नै जा सकल ।",
+       "backend-fail-create": "फाइल $1 नै लिखल जा सकल।",
+       "backend-fail-maxsize": "फाइल $1 नै लिखल जा सकल कियाक कि ई {{PLURAL:$2|$2 बाईट}} सऽ बडका अछि।",
        "zip-file-open-error": "संकुचित संचिका जाँचमे संचिका खोललापर एकटा भ्रम आएल।",
        "zip-wrong-format": "खास संचिका संकुचित संचिका नै छी।",
        "zip-bad": "ई संचिका एकटा टूटल आ ओहिनो बिन पढ़बा योग्य संकुचित फाइल छी।",
        "license-nopreview": "(पूर्वावलोकन उपलब्ध नै अछि)",
        "upload_source_url": "(एकटा मान्य, सार्वजनिक प्रवेशबला सार्वत्रिक विभव संकेत)",
        "upload_source_file": "(अहाँक संगणकपर एकटा संचिका)",
+       "listfiles-delete": "मिटाउ",
        "listfiles-summary": "ई विशिष्ट पन्ना सभटा उपारोपित संचिका देखबैए।\nप्रयोक्ता द्वारा चुनलापर अन्तिम उपारोपित संचिका देखबैत अछि।",
        "listfiles_search_for": "ऐ दृश्य-श्रव्य नामले ताकू:",
        "imgfile": "संचिका",
        "listfiles_size": "आकार",
        "listfiles_description": "वर्णन",
        "listfiles_count": "संस्करण सभ",
+       "listfiles-latestversion": "बर्तमान भर्जन",
+       "listfiles-latestversion-yes": "हँ",
+       "listfiles-latestversion-no": "नै",
        "file-anchor-link": "संचिका",
        "filehist": "फाइल इतिहास",
        "filehist-help": "तखुनका तिथि/ समए पर क्लिक करू जखुनका फाइल देखबाक अछि",
        "protectedpages": "संरक्षित पन्ना सभ",
        "protectedpages-indef": "अनन्तकालिक सुरक्षा मात्र",
        "protectedpages-cascade": "तराउपड़ी सुरक्षा मात्र",
+       "protectedpages-noredirect": "पुनर्निर्देश नुकाऊँ",
        "protectedpagesempty": "कोनो पन्ना ऐ सभ परिमिति लेल सुरक्षित नै राखल गेल अछि।",
+       "protectedpages-timestamp": "समएकाल",
+       "protectedpages-page": "पृष्ठ",
+       "protectedpages-expiry": "खतम हएत:",
+       "protectedpages-performer": "सुरक्षित करै वाला सदस्य",
+       "protectedpages-params": "सुरक्षा प्राचल",
+       "protectedpages-reason": "कारण:",
+       "protectedpages-unknown-timestamp": "अज्ञात",
+       "protectedpages-unknown-performer": "अज्ञात सदस्य",
        "protectedtitles": "संरक्षित शीर्षक सभ",
        "protectedtitlesempty": "कोनो पन्ना ऐ सभ परिमिति लेल सुरक्षित नै राखल गेल अछि।",
        "listusers": "प्रयोक्ता सूची",
        "allpagesprefix": "उपसर्गक संग दृश्य पन्ना सभ:",
        "allpagesbadtitle": "देल पन्नाक शीर्षक गलत, गलत सम्बन्धित अन्तर-भाषा अन्तर विकी शीर्षक छी। ई एक वा बेशी कलाकार युक्त भऽ सकैए जे शीर्षकमे प्रयुक्त नै कएल जा सकैए।",
        "allpages-bad-ns": "{{जालस्थल}} मे \"$1\" नामगाम नै अछि।",
+       "cachedspecial-refresh-now": "लब्का देखु",
        "categories": "संवर्ग सभ",
        "categoriespagetext": "ई {{PLURAL:$1|संवर्गमे अछि|संवर्ग सभमे अछि}} पन्ना वा मीडिया।\n[[Special:UnusedCategories|Unused categories]] एतए देखाएल नै अछि।\nईहो देखू [[Special:WantedCategories|wanted categories]]।",
        "categoriesfrom": "पन्ना प्रदर्शन प्रारम्भ भेल:",
        "listgrouprights-removegroup-self": "निकालू {{PLURAL:$2|वर्ग|वर्ग}} अपन खातामे: $1",
        "listgrouprights-addgroup-self-all": "सभटा वर्गकेँ अपन खातामे जोड़ू",
        "listgrouprights-removegroup-self-all": "सभटा वर्गकेँ अपन खातासँ निकालू",
+       "listgrouprights-namespaceprotection-header": "नामस्थान वर्जित",
+       "listgrouprights-namespaceprotection-namespace": "नामस्थान :",
+       "listgrouprights-namespaceprotection-restrictedto": "सांच(सभ) के संपादन करए लेल",
+       "trackingcategories": "श्रेणीके ट्रयाक करु",
        "mailnologin": "कोनो पठेबाक पता नै",
        "mailnologintext": "अहाँ [[Special:UserLogin|सम्प्रवेशित]] हेबाक चाही आ अहाँक विकल्प [[Special:Preferences|preferences]]  मे एकटा मान्य ई-पत्र संकेत दोसर प्रयोक्ताकेँ पठेबा लेल हेबाक चाही।",
        "emailuser": "ऐ प्रयोक्ताकेँ ई-पत्र पठाउ",
        "watchlist-details": "{{PLURAL:$1|$1 पन्ना|$1 पन्ना सभ}} अहाँक साकांक्षसूचीमे, चौबटिया पन्ना नै गानल गेल।",
        "wlheader-enotif": "ई-पत्र सूचना लागू अछि।",
        "wlheader-showupdated": "पन्ना सभ जे अहाँक एतए अन्तिम बेर अएलाक बाद बदलल अछि तकर सूची देल अछि '''गाढ़''' मे",
+       "wlnote": "नीचाँ {{PLURAL:$1|is the last change|are the last '''$1''' changes}} अन्तिम {{PLURAL:$2|hour|'''$2''' hours}} $3, $4 जेना।",
        "wlshowlast": "देखाउ अन्तिम $1 घण्टा $2 दिन $3",
        "watchlist-options": "साकांक्षसूचीक विकल्प सभ",
        "watching": "ताकिमे...",
        "enotif_lastvisited": "देखू $1 अपन अन्तिम बेर अएलाक बादक परिवर्तन लेल।",
        "enotif_lastdiff": "ऐ परिवर्तनकेँ देखबा लेल $1 देखू।",
        "enotif_anon_editor": "गुप्त प्रयोक्ता $1",
-       "enotif_body": "पà¥\8dरिय $WATCHINGUSERNAME,\n\n\nà¤\88 {{à¤\85नà¥\8dतरà¥\8dà¤\9cाल}} à¤ªà¤¨à¥\8dना $पनà¥\8dनाशà¥\80रà¥\8dषà¤\95 $CHANGEDORCREATED à¤\95à¤\8fल à¤\97à¥\87ल $PAGEEDITDATE à¤¤à¤¿à¤¥à¤¿à¤\95à¥\87à¤\81 $PAGEEDITOR à¤¦à¥\8dवारा, à¤¦à¥\87à¤\96à¥\82 $PAGETITLE_URL à¤µà¤°à¥\8dतमान à¤¸à¤\82सà¥\8dà¤\95रण à¤²à¥\87ल।\n\n$NEWPAGE\n\nसमà¥\8dपादà¤\95à¥\80य: $PAGESUMMARY $PAGEMINOREDIT\n\nसमà¥\8dपादà¤\95सà¤\81 à¤¸à¤®à¥\8dपरà¥\8dà¤\95 à¤\95रà¥\82:\nà¤\88-पतà¥\8dर: $PAGEEDITOR_EMAIL\nविà¤\95à¥\80: $PAGEEDITOR_WIKI\n\nà¤\86न à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤­à¥\87लापर à¤\95à¥\8bनà¥\8b à¤¸à¥\82à¤\9aना à¤¨à¥\88 à¤¦à¥\87ल à¤\9cाà¤\8fत à¤\9cà¤\81 à¤\85हाà¤\81 à¤\88 à¤ªà¤¨à¥\8dना à¤¨à¥\88 à¤¦à¥\87à¤\96ब।\nà¤\85पन à¤¸à¤¾à¤\95ाà¤\82à¤\95à¥\8dष à¤¸à¥\82à¤\9aà¥\80à¤\95 à¤¸à¥\82à¤\9aना à¤ªà¥\87बाà¤\95 à¤ªà¥\8dरà¤\95ार à¤\85हाà¤\81 à¤¬à¤¦à¤²à¤¿ à¤¸à¤\95à¥\88 à¤\9bà¥\80।\n\n             à¤\85हाà¤\81à¤\95 à¤ªà¥\8dरिय {{ानà¥\8dतर्जाल}} सूचना प्रणाली\n\n--\nअपन ई-पत्र सूचना प्रकार बदलबाक लेल देखू\n{{canonicalurl:{{#special:Preferences}}}}\nअपन साकांक्ष-सूची सूचना प्रकार बदलबाक लेल देखू\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nअपन साकांक्ष-सूचीसँ कोनो पन्ना मेटेबाक लेल देखू\n$UNWATCHURL\n\nअपन अनुभव बतेबा वा कोनो सहायता लेल:\n$HELPPAGE",
+       "enotif_body": "पà¥\8dरिय $WATCHINGUSERNAME,\n\n\nà¤\88 {{à¤\85नà¥\8dतरà¥\8dà¤\9cाल}} à¤ªà¤¨à¥\8dना $पनà¥\8dनाशà¥\80रà¥\8dषà¤\95 $CHANGEDORCREATED à¤\95à¤\8fल à¤\97à¥\87ल $PAGEEDITDATE à¤¤à¤¿à¤¥à¤¿à¤\95à¥\87à¤\81 $PAGEEDITOR à¤¦à¥\8dवारा, à¤¦à¥\87à¤\96à¥\82 $PAGETITLE_URL à¤µà¤°à¥\8dतमान à¤¸à¤\82सà¥\8dà¤\95रण à¤²à¥\87ल।\n\n$NEWPAGE\n\nसमà¥\8dपादà¤\95à¥\80य: $PAGESUMMARY $PAGEMINOREDIT\n\nसमà¥\8dपादà¤\95सà¤\81 à¤¸à¤®à¥\8dपरà¥\8dà¤\95 à¤\95रà¥\82:\nà¤\88-पतà¥\8dर: $PAGEEDITOR_EMAIL\nविà¤\95à¥\80: $PAGEEDITOR_WIKI\n\nà¤\86न à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤­à¥\87लापर à¤\95à¥\8bनà¥\8b à¤¸à¥\82à¤\9aना à¤¨à¥\88 à¤¦à¥\87ल à¤\9cाà¤\8fत à¤\9cà¤\81 à¤\85हाà¤\81 à¤\88 à¤ªà¤¨à¥\8dना à¤¨à¥\88 à¤¦à¥\87à¤\96ब।\nà¤\85पन à¤¸à¤¾à¤\95ाà¤\82à¤\95à¥\8dष à¤¸à¥\82à¤\9aà¥\80à¤\95 à¤¸à¥\82à¤\9aना à¤ªà¥\87बाà¤\95 à¤ªà¥\8dरà¤\95ार à¤\85हाà¤\81 à¤¬à¤¦à¤²à¤¿ à¤¸à¤\95à¥\88 à¤\9bà¥\80।\n\n             à¤\85हाà¤\81à¤\95 à¤ªà¥\8dरिय {{à¤\85à¤\82तर्जाल}} सूचना प्रणाली\n\n--\nअपन ई-पत्र सूचना प्रकार बदलबाक लेल देखू\n{{canonicalurl:{{#special:Preferences}}}}\nअपन साकांक्ष-सूची सूचना प्रकार बदलबाक लेल देखू\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nअपन साकांक्ष-सूचीसँ कोनो पन्ना मेटेबाक लेल देखू\n$UNWATCHURL\n\nअपन अनुभव बतेबा वा कोनो सहायता लेल:\n$HELPPAGE",
        "created": "बनाएल गेल",
        "changed": "बदलल गेल",
        "deletepage": "पन्ना मेटाउ",
        "import": "पन्ना सभकेँ आनू",
        "importinterwiki": "ट्रान्सविकी आनू",
        "import-interwiki-text": "एकटा विकी आ पन्ना शीर्षक अनबाले चुनू।\nसंशोधन तिथि आ सम्पादकक नाम सुरक्षित रहत।\nसभटा ट्रान्सविकी आयात क्रिया सम्प्रवेशित अछि [[Special:Log/import|import log]] पर।",
-       "import-interwiki-source": "मूल विकी/ पन्ना:",
        "import-interwiki-history": "अए पन्नाक सभटा इतिहास संशोधनक द्वितीयक बनाउ",
        "import-interwiki-templates": "सभटा नमूना शामिल करू",
        "import-interwiki-submit": "आनू",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|सुधार|सुधार सभ}}",
        "import-logentry-interwiki": "$1 क विकीअन्तरण",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|सुधार|सुधार सभ}} $2 सँ",
+       "javascripttest": "जावास्क्रिप्ट परिक्षण",
        "tooltip-pt-userpage": "अहाँक खेसरा पन्ना",
        "tooltip-pt-anonuserpage": "सम्पाद्न कएल जा रहल स्थानक  अनिकेतक प्रयोक्ता पन्ना",
        "tooltip-pt-mytalk": "अहाँक वार्त्ता पृष्ठ",
        "spam_blanking": "सभटा संशोधन $1 लागिसँ युक्त अि, खतम कऽ रहल छी",
        "pageinfo-title": "\"$1\"पृष्ठक लेल नब गप",
        "pageinfo-header-edits": "संपादन",
+       "pageinfo-header-restrictions": "पन्ना संरक्षण",
        "pageinfo-views": "देखहि बला के संख्या",
        "pageinfo-watchers": "जानकारक संख्या",
        "pageinfo-edits": "सम्पादनक संख्या",
        "duplicate-defaultsort": "'''चेतौनी:''' पूर्वनिर्धारित विन्यास चाभी \"$2\" पहिलुका पूर्वनिर्धारित विन्यास चाभी \"$1\" केँ खतम करैए।",
        "version": "संस्करण",
        "version-extensions": "संस्करणक आगाँ",
+       "version-skins": "रूप",
        "version-specialpages": "खास पन्ना",
        "version-parserhooks": "पार्सर हूक",
        "version-variables": "विकारी",
        "version-antispam": "अनिष्ट संदेश प्रतिबन्ध",
-       "version-skins": "रूप",
        "version-other": "आन",
        "version-mediahandlers": "मीडिया संचालक",
        "version-hooks": "हूक",
        "version-hook-name": "खुट्टीक नाम",
        "version-hook-subscribedby": "ई सदस्यता लेलनि",
        "version-version": "(संस्करण $1)",
+       "version-no-ext-name": "[कोनो नाम नै]",
        "version-license": "अधिकार",
+       "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-credits-title": "$1 के लेल श्रेय",
        "version-poweredby-credits": "ई विकी चालित अछि '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2",
        "version-poweredby-others": "आन",
+       "version-poweredby-translators": "translatewiki.net अनुवादक",
+       "version-credits-summary": "[[Special:Version|मिडियाविकि]]",
        "version-license-info": "मीडियाविकी एकटा मंगनीक तंत्रांश अछि; अहाँ एकरा बाँटि सकै छी आ/ वा संशोधित कऽ सकै छीगी.एन.यू. सामान्य जन लाइसेन्सक अन्तर्गत जेना फ्री सॉफ्टवेयर फाउन्डेशन एकरा प्रकाशित केने अछि; चाहे तँ लाइसेन्सक संस्करण २, वा (अहाँक विकल्पपर) कोनो बादक दोसर संस्करणक अन्तर्गत।\n\nमीडियाविकी ऐ आशामेँ बाँटल जा रहल अछि कि ई उपयोगी हएत, मुदा बिना कोनो गारन्टीक; बिना कोनो व्यापारिक अन्तर्निहित वारन्टीक वा कोनो विशेष काजक लेल उपयोगी हेबाले। देखू गी.एन.यू. सामान्य जन लाइसेन्स विशेष वर्णन लेल।\n\nअहाँ प्राप्त केने हएब [{{SERVER}}{{SCRIPTPATH}}/ अनुकरण गी.एन.यू. सामान्य जन लाइसेन्सक प्रति] ऐ तंत्रांशक संग; जँ नै, लिखू फ्री सॉफ्टवेयर फाउन्डेशन, आइ.एन.सी., ५१, फ्रैंकलिन स्ट्रीट, पाँचम तल, बोस्टन, एम.ए. ०२११०-१३०१, यू.एस.ए. वा [//www.gnu.org/licenses/old-licenses/gpl-2.0.html अन्तर्भूत पढ़बा लेल]।",
        "version-software": "प्रतिष्ठापित तंत्रांश",
        "version-software-product": "उत्पाद",
        "version-software-version": "संस्करण",
+       "version-entrypoints-header-url": "यू॰आर॰एल",
        "fileduplicatesearch": "द्वितीयक संचिका ताकू",
        "fileduplicatesearch-summary": "हैश मानक आधारपर द्वितीयक संचिका ताकू।",
        "fileduplicatesearch-legend": "द्वितीयक ताकू",
        "tags-tag": "चेन्हक नाम",
        "tags-display-header": "परिवर्तन सूची सभक रूपरंग",
        "tags-description-header": "अर्थक पूर्ण विवरण",
+       "tags-active-header": "सक्रिय?",
        "tags-hitcount-header": "चेन्हयुक्त परिवर्तन सभ",
+       "tags-active-yes": "हँ",
+       "tags-active-no": "नै",
        "tags-edit": "सम्पादन करू",
        "tags-hitcount": "$1 {{PLURAL:$1|परिवर्तन|परिवर्तन सभ}}",
        "comparepages": "पन्ना सभक तुलना करू",
        "dberr-problems": "दुखी छी! ई जालस्थल तकनीकी समस्या अनुभव कऽ अछि।",
        "dberr-again": "किछु काल बाट ताकू आ फेरसँ भारित करू।",
        "dberr-info": "(दत्तनिधि वितरककेँ सम्पर्क नै कऽ सकल: $1)",
+       "dberr-info-hidden": "(दत्तनिधि वितरककेँ सम्पर्क नै कऽ सकल: $1)",
        "dberr-usegoogle": "ऐ बीचमे अहाँ गूगलसँ खोज कऽ सकै छी।",
        "dberr-outofdate": "मोन राखू जे हमर सामिग्रीक ओकर सूची पुरान भऽ सकैए।",
        "dberr-cachederror": "ई आग्रह कएल पन्नाक उपस्मृति संरक्षित द्वितीयक अछि, आ भऽ सकैए जे अद्यतन नै हुअए।",
        "htmlform-submit": "दिअ",
        "htmlform-reset": "परिवर्तन खतम करू",
        "htmlform-selectorother-other": "आन",
+       "htmlform-no": "नै",
+       "htmlform-yes": "हँ",
+       "htmlform-chosen-placeholder": "एकटा विकल्प चुनु",
+       "htmlform-cloner-create": "आर जोडु",
+       "htmlform-cloner-delete": "हटाउ",
        "sqlite-has-fts": "$1 पूर्ण-पाठ खोज सहायता युक्त",
        "sqlite-no-fts": "$1 बिन पूर्ण-पाठ खोज सहायताक",
        "logentry-delete-delete": "$1 {{लिंग:$2|deleted}} page $3",
        "logentry-newusers-create2": "$1 {{लिंग:$2|बनाएल}} {{लिंग:$4|एकटा प्रयोक्ता खाता}} $3",
        "logentry-newusers-autocreate": "खाता $1 छल {{लिंग:$2|बनाएल}} स्वतः",
        "rightsnone": "(कोनो नै)",
+       "feedback-subject": "विषय:",
+       "feedback-message": "संदेश:",
+       "feedback-cancel": "रद्द करु",
+       "feedback-submit": "प्रतिक्रिया भेजु",
+       "feedback-adding": "पन्ना उपर प्रतिक्रिया जोडु ...",
+       "feedback-error2": "त्रुटि: संपादन विफल भेल",
+       "feedback-close": "भ गेल",
+       "feedback-bugcheck": "बहुत निक! जांच करु कि [ $1 known bugs] पहिले स त नै अछि ।",
+       "searchsuggest-search": "ताकू",
+       "searchsuggest-containing": "...सऽ युक्त",
        "api-error-badaccess-groups": "अहि विकी सें अहां कोनो प्रारूप लोड नहि क सकब.",
        "api-error-filename-tooshort": "ई संचिका नाम बड छोट अछि |",
        "api-error-filetype-banned": "ऐ तरहक संचिका नाम प्रतिबंधित  अछि।",
        "api-error-ok-but-empty": "आन्तरिक भ्रम: वितरकसँ कोनो सम्पर्क नै",
        "api-error-unclassified": "एकटा अबूझ भ्रम आएल",
        "api-error-unknown-code": "अबूझ भ्रम:\"$1\"",
-       "api-error-uploaddisabled": "ऐ विकीपर उपारोपण अशक्त कएल गेल अछि।"
+       "api-error-uploaddisabled": "ऐ विकीपर उपारोपण अशक्त कएल गेल अछि।",
+       "pagelang-name": "पन्ना",
+       "pagelang-language": "भाषा"
 }
index a652ff8..90ac544 100644 (file)
        "talkpagelinktext": "Dopokan",
        "specialpage": "Kaca khusus",
        "personaltools": "Piranti pribadi",
-       "postcomment": "Bagéyan anyar",
        "articlepage": "Deleng isi tulisan",
        "talk": "bahas",
        "views": "Tampilan",
        "externaldberror": "Ana kesalahan otentikasi basis data utawa Rika ora olih nglakokna pemutakhiran maring akun eksternale Rika.",
        "login": "Melebu",
        "nav-login-createaccount": "Mlebu / gawe kaca anggota (akun)",
-       "loginprompt": "Rika kudu ngaktifna ''cookies'' ben teyeng mlebu log maring {{SITENAME}}.",
        "userlogin": "Melebu / gawe kaca anggota (account)",
        "userloginnocreate": "Mlebu log",
        "logout": "Metu Log",
        "searchprofile-advanced-tooltip": "Goleti nang bilik jeneng biasa",
        "search-result-size": "$1 ({{PLURAL:$2|1 tembung|$2 tembung}})",
        "search-result-category-size": "{{PLURAL:$1|1 anggota|$1 anggota}} ({{PLURAL:$2|1 subkategori|$2 subkategori}}, {{PLURAL:$3|1 berkas|$3 berkas}})",
-       "search-result-score": "Relevansi: $1%",
        "search-redirect": "(pangalihan $1)",
        "search-section": "(bagiyan $1)",
        "search-suggest": "Apa maksude Rika kuwe: $1",
        "ignorewarning": "Lirwakna pèngetan lan langsung simpen berkas.",
        "ignorewarnings": "Lirwakna pèngetan apa baen",
        "minlength1": "Jeneng berkas seora-orane kudu ana seaksara.",
-       "uploadedimage": "ngunggahna\"[[$1]]\"",
        "license": "Jenis lisènsi:",
        "license-header": "Jinis lisènsi",
        "listfiles_date": "Tanggal",
index 57fe8cf..bdd4460 100644 (file)
        "oct": "Кем",
        "nov": "Эйн",
        "dec": "Куч",
+       "january-date": "Кельмеков $1",
+       "february-date": "Уфайков $1",
+       "march-date": "Марайков $1",
+       "april-date": "Шудиков $1",
+       "may-date": "Панжиков $1",
+       "june-date": "Лямбеков $1",
+       "july-date": "Псиков $1",
+       "august-date": "Сёроньков $1",
+       "september-date": "Тюжягов $1",
+       "october-date": "Кельмазаков $1",
+       "november-date": "Эйндамков $1",
+       "december-date": "Кучкаков $1",
        "pagecategories": "{{PLURAL:$1|Категорие|Категориет}}",
        "category_header": "\"$1\" категориеса лопатне",
        "subcategories": "Субкатегориет",
        "newwindow": "(панчсеви од вальмаса)",
        "cancel": "Мърдамс меки",
        "moredotdotdot": "Сяда лама...",
-       "mypage": "Монь лопазе",
-       "mytalk": "Монь корхтамазе",
+       "morenotlisted": "Лемгярькссь апак тик",
+       "mypage": "Лопазе",
+       "mytalk": "Корхтамазе",
        "anontalk": "Корхтамс тя IP-ть мархта",
        "navigation": "Навигацие",
        "and": "&#32;эди",
        "actions": "Тефне",
        "namespaces": "Лемботмот",
        "variants": "Вариатт",
+       "navigation-heading": "Навигациень меню",
        "errorpagetitle": "Эльбятькс",
        "returnto": "Мърдамс $1-с.",
        "tagline": "{{SITENAME}}ста",
        "permalink": "Ялань сюлмафкс",
        "print": "Нолдамс",
        "view": "Ваномс",
+       "view-foreign": "Ванк $1са",
        "edit": "Петнеме",
+       "edit-local": "Петнемс тя азондомать",
        "create": "Тиемс",
+       "create-local": "Поладомс азондомать",
        "editthispage": "Петнемс тя лопать",
        "create-this-page": "Тиемс тя лопать",
        "delete": "Нардамс",
        "deletethispage": "Нардамс тя лопать",
+       "undeletethispage": "Мърдафтомс лопать",
        "undelete_short": "Мърдафтомс {{PLURAL:$1|петнема|$1 петнемат}}",
        "viewdeleted_short": "Ваномс {{PLURAL:$1|фкя нардаф видептема|$1 нардаф видептемат}}",
        "protect": "Араламс",
        "talkpagelinktext": "Корхтама",
        "specialpage": "Башка тевонь лопа",
        "personaltools": "Эсь кядьёнкст",
-       "postcomment": "Од пакш",
        "articlepage": "Ваномс потмакслопать",
        "talk": "Корхнема",
        "views": "Ванфт",
-       "toolbox": "Кядьёнкс кярькс",
+       "toolbox": "Кядьёнкст",
        "userpage": "Ваномс тиить лопанц",
        "projectpage": "Ваномс проектть лопанц",
        "imagepage": "Ваномс файлонь лопать",
        "jumptonavigation": "навигацие",
        "jumptosearch": "вешендема",
        "view-pool-error": "Ужяль, тя пингть серверхнень вийсна аф сатовихть.\nВельф лама тиихть тяряфнихть ваномс тя лопать.\nЭняльттяма учт аф ламос тя лопанди одукс сама инголе.\n$1",
+       "generic-pool-error": "Ужяль, тя пингть серверхнень вийсна аф сатыхть.\nВельф лама тиида тяряфнихть ваномс тя лопать лангс.\nЭняльттяма учт аф ламос тя лопанди одукс самда инголе.",
        "pool-timeout": "Пигонь кирдемась учи пякстаманц",
        "pool-queuefull": "Тяряфнемада вельф лама",
        "pool-errorunknown": "Аф содаф эльбятькс",
+       "pool-servererror": "Пърдафкс лувома лезкссь аф сатови ($1).",
        "aboutsite": "{{SITENAME}} колга",
        "aboutpage": "Project:Колга",
-       "copyright": "Сёрматфсь ули кода мумс $1-са.",
+       "copyright": "Сёрматфсь ули кода мумс $1са, къда илякс апак аст.",
        "copyrightpage": "{{ns:project}}:Копияма видекст",
        "currentevents": "Мезе тяса моли",
        "currentevents-url": "Project:Мезе тяса моли",
        "nospecialpagetext": "<strong>Аш стама башка лопа.</strong>\n\nВанк [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Эльбятькс",
        "databaseerror": "Датабаза эльбятькс",
+       "databaseerror-text": "Содамошинь паргонь вешемста лиссь эльбятькс.\nУлема, програмонь лездомбяльсь аржиясь.",
        "laggedslavemode": "Шарфтк мяльце: Тя лопась, улема, сирелгодсь.",
        "readonly": "Датабазась пякстаф",
        "enterlockreason": "Сёрматк тязк пякстама туфтал тонь арьсемацень мархта эли няфтть тяса мъзярда ули кода пякстамать валхтомс.",
        "externaldberror": "Лиссь эльбятькс ушеширень датабазонь вельде кемокстакшнембачк эли тондейть аф мярьгови полафнемс тонь ушеширень сёрматфтомацень.",
        "login": "Сувама",
        "nav-login-createaccount": "Сувама / сёрматфтома",
-       "loginprompt": "Тондейть эряви нолдамс тевс cookies {{SITENAME}}с суваманди.",
        "userlogin": "Сувама / сёрматфтома",
        "userloginnocreate": "Сувамс",
        "logout": "Лисема",
        "searchprofile-advanced-tooltip": "Вешендемс кърдань лемботмова",
        "search-result-size": "$1 ({{PLURAL:$2|1 вал|$2 валхт}})",
        "search-result-category-size": "{{PLURAL:$1|1 якай|$1 якайхть}} ({{PLURAL:$2|1 субкатегорие|$2 субкатегориет}}, {{PLURAL:$3|1 файла|$3 файлат}})",
-       "search-result-score": "Малавиксши: $1%",
        "search-redirect": "(шашфтт $1с)",
        "search-section": "(пялькс $1)",
        "search-suggest": "Афкукс тонь мяльсот: $1",
        "file-deleted-duplicate": "Файлсь сяка кода файл ([[:$1]]) нардафоль. Ванк файлонь нардама историянц сонь одукс тонгоманза инголе.",
        "uploadwarning": "Тонгодемань инголе кардама",
        "savefile": "Ванфтомс файл",
-       "uploadedimage": "тонгозь \"[[$1]]\"",
-       "overwroteimage": "тонгозь \"[[$1]]\" од верзиенц",
        "uploaddisabled": "Тонгодемать лоткозь",
        "uploaddisabledtext": "Файл тонгодемась лоткаф.",
        "uploadscripted": "Тя файлса ащи HTML эли програм, конат аф морафтовихть интернет полатксть вельде.",
        "watchlist-details": "{{PLURAL:$1|$1 лопа|$1 лопат}} мельгеваномацень ала корхнема лопат аф лувомок.",
        "wlheader-enotif": "Электрононь сёрма вельде пачфнема нолдаф тевс.",
        "wlheader-showupdated": "Лопат конань полафтозь тонь мекольце сувсемадот меле няфтевсть '''эчке тяшкса'''.",
+       "wlnote": "Ала {{PLURAL:$1|мекольце полафнема|'''$1''' мекольце полафнемат}} ётай {{PLURAL:$2| ойста (часста)|'''$2''' ойста (часста)}}.",
        "wlshowlast": "Няфтемс мекольце $1 ойхть (част) $2 шит $3",
        "watchlist-options": "Мельгеваномать латцемасна",
        "watching": "Ванома...",
index ccaae87..43756bd 100644 (file)
@@ -24,6 +24,7 @@
        "tog-watchdefault": "Hanaraka ny pejy ary ny rakitra ovaiko",
        "tog-watchmoves": "Hanaraka ny pejy ary ny rakitra ovaiko anarana",
        "tog-watchdeletion": "Hanaraka ny pejy ary ny rakitra voafafako",
+       "tog-watchrollback": "Hanaraka pejy nanaovako famoana",
        "tog-minordefault": "Mariho ho madinika foana aloha ny fanovana rehetra",
        "tog-previewontop": "Asehoy alohan'ny boaty fanovana ny tsipalotra",
        "tog-previewonfirst": "Asehoy ny tsipalotra amin'ny fanovana voalohany",
        "talkpagelinktext": "Dinika",
        "specialpage": "Pejy manokana",
        "personaltools": "Fitaovana manokana",
-       "postcomment": "Hametraka fanamarihana",
        "articlepage": "Hijery ny votoatin'ny pejy",
        "talk": "dinika",
        "views": "Fijerena",
        "otherlanguages": "Amin'ny tenim-pirenena hafa",
        "redirectedfrom": "(tonga teto avy amin'ny $1)",
        "redirectpagesub": "Pejy fihodinana",
+       "redirectto": "Mihodina mankany:",
        "lastmodifiedat": "Voaova farany tamin'ny $1 amin'ny $2 ity pejy ity<br />",
        "viewcount": "voastsidika in-$1 ity pejy ity.{{PLURAL:}}",
        "protectedpage": "Pejy voaaro",
        "hidetoc": "afeno",
        "collapsible-collapse": "Vonkinina",
        "collapsible-expand": "Itarina",
+       "confirmable-yes": "Eny",
+       "confirmable-no": "Tsia",
        "thisisdeleted": "Hojerena sa haverina i $1?",
        "viewdeleted": "Hijery an'i $1?",
        "restorelink": "ny fanovàna voafafa $1{{PLURAL:}}",
        "invalidtitle-knownnamespace": "Lohateny tsy miady amin'ny fepetra miaraka amin'ny anaram-balam-pejy \"$2\" ary soratra \"$3\"",
        "invalidtitle-unknownnamespace": "Lohateny tsy ekena miaraka amin'ny laharana anaran-tsehatra $1 ary soratra \"$2\"",
        "exception-nologin": "Tsy tafiditra",
-       "exception-nologin-text": "[[Special:Userlogin|Midira]]  mba hahafahanao manao ilay asa na hahafahanao mijery ity pejy ity",
+       "exception-nologin-text": "Midira amin'ny kaontinao azafady mba hahafahana manao ilay asa na mitsidika ilay pejy",
        "exception-nologin-text-manual": "$1 ianao mba ho tonga eo amin'ilay pejy na hanatanteraka ilay asa.",
        "virus-badscanner": "Diso : Tsy fantatray ny mpitady virus ''$1''",
        "virus-scanfailed": "Tsy mety alefa ny fitadiavana (kaody $1)",
        "externaldberror": "Nisy tsy fetezana angamba teo amin'ny fanamarinana anao tamin'ny sehatra ivelan'ity wiki ity, na tsy manana alalana hanova ny kaontinao ivelany ianao.",
        "login": "Midira",
        "nav-login-createaccount": "Ampidiro ny solonanarana",
-       "loginprompt": "\nMila manaiky cookies ianao raha te hiditra amin'ny {{SITENAME}}.",
        "userlogin": "Hiditra na hanokatra kaonty",
        "userloginnocreate": "hiditra",
        "logout": "Hiala",
        "userlogin-resetlink": "Adinonavo ve ny antsipihan'ny fidiranao ?",
        "userlogin-resetpassword-link": "Hadino ny tenimiafina?",
        "userlogin-helplink2": "Fanampiana amin'ny fidirana",
-       "userlogin-loggedin": "Efa tafiditra amin'ny anaran'i {{GENDER:$1|$1}} ianao. Ampiasao ny fôrmiolera eo ambany raha hiditra amin'ny anaran'ny mpikambana hafa.",
-       "userlogin-createanother": "Hamorona kaonty hafa",
        "createacct-emailrequired": "Adiresy mailaka :",
        "createacct-emailoptional": "Adiresy mailaka (azo tsy atao) :",
        "createacct-email-ph": "Atsofohy ny adiresy mailakao",
        "preview": "Topi-maso",
        "showpreview": "Asehoy aloha",
        "showdiff": "Asehoy ny fiovana",
-       "anoneditwarning": "'''Tandremo''' : Tsy nisoratra tato amin'ny sehtatra ianao. Ho voatahiry ao amin'ny tantaram-pejy ny adiresy IP anao.",
+       "anoneditwarning": "<strong>Fampitandremana :</strong> Tsy niditra tamin'ny kaontinao ianao. Ho hitan'ny vahoaka ny adiresy IP-nao raha manova inona na inona ianao. Raha <strong>[$1 miditra amin'ny kaontinao]</strong> ianao dia ho anisan'ny tombontsoa anananao ny fanaovana ny fiovana amin'ny solonanaranao.",
        "anonpreviewwarning": "''Tsy niditra ianao. Hampitahiry ny adiresy IP anao ao amin'ny tantaram-panovan'ity pejy ity ny fitehirizana ny fanovana.''",
        "missingsummary": "'''Hafatra fampantsiahivana''' : tsy mbola nanome ny ambangovangom-panovanao ianao.\nRaha mbola tsindriano fanindroany eo amin'ny bokotra {{int:savearticle}}, ho voatahiry tsy fanambarana ny fanovanao.",
        "missingcommenttext": "Ampidiro ny ambangovangony azafady.",
        "permissionserrorstext-withaction": "{{PLURAL:$1|Tsy manana alalàna ianao|Tsy manana alalàna ianao}} $2. Io ny antony ($2):",
        "recreate-moveddeleted-warn": "'''Tandremo''' : Mamerina pejy efa voafafa ianareo.'''\n\nMarino raha tsara tohizana ny fanovana eto amin'ity pejy ity. Ny laogim-pamafana sy ny famindran-toerana dia eo ambany :",
        "moveddeleted-notice": "Voafafa ity pejy ity.\nEo ambany eo any laogin'ny famindran-toerana sy ny famafana ho an'ny antsipirihany.",
-       "log-fulllog": "Hijery ny tatitr’asa (log)",
+       "log-fulllog": "Hijery ny laogy manontolo",
        "edit-hook-aborted": "Tsy nety ny fanovàna\nTsy nanome antony",
        "edit-gone-missing": "Tsy afaka natao update ilay pejy.\nMety voafafa angamba izy.",
        "edit-conflict": "Adi-panovàna.",
        "parser-template-recursion-depth-warning": "Fetran'ny halalin'ny fiantsoana endrika voahoatra ($1).",
        "language-converter-depth-warning": "Mihoatra ny fetran-kalalin'ny mpamadika teny ($1)",
        "node-count-exceeded-category": "Pejy izay ahitana fihoatran'ny isam-patotra (node)",
-       "node-count-exceeded-category-desc": "Sokajy ho an'ny pejy ahitana isan'ny naody mihoatra.",
+       "node-count-exceeded-category-desc": "Mihoatra ny isam-patotra eto amin'ity pejy ity",
        "node-count-exceeded-warning": "Pejy manana isam-patotra mihoatra",
        "expansion-depth-exceeded-category": "Pejy manana halalim-panitarana mihoatra",
        "expansion-depth-exceeded-category-desc": "Sokajy ho an'ny pejy ahitana halalim-piitarana mihoatra.",
        "undo-summary-username-hidden": "Namafa ny famerenana $1 nataom-pikambana afenina",
        "cantcreateaccounttitle": "Tsy afaka manokatra kaonty ianao.",
        "cantcreateaccount-text": "Voasakan'i [[User:$3|$3]] ny fanokafana kaonty avy amin'ity adiresy IP (<b>$1</b>)\n\n''$2'' ny antony.",
+       "cantcreateaccount-range-text": "Nosakanan'i [[User:$3|$3]] ny fanokafana kaonty avy amin'ny adiresy IP ao amin'ny elanelana '''$1''' izay ahitana ny adiresy IP-nao ('''$4''').",
        "viewpagelogs": "Hijery ny fanovan'ity pejy ity",
        "nohistory": "Tsy manana tantaram-panovana io pejy io.",
        "currentrev": "Votoatiny ankehitriny",
        "currentrev-asof": "Endrika tamin'ity $1 ity",
        "revisionasof": "Endrik'io pejy io tamin'ny $1",
-       "revision-info": "Endrika tamin'ny $1 nataon'i $2",
+       "revision-info": "Endrika tamin'ny $1 nataon'i {{GENDER:$6|$2}}$7",
        "previousrevision": "← Endrika tranainy kokoa",
        "nextrevision": "Endrika vaovao kokoa →",
        "currentrevisionlink": "Endrika farany indrindra",
        "rev-deleted-user": "(solonanarana nesorina)",
        "rev-deleted-event": "(nesorina ny fampidirana)",
        "rev-deleted-user-contribs": "[anaram-pikambana na adiresy IP voafafa - fanovana nasitria teo amin'ny fandraisan'anjara modification]",
-       "rev-deleted-text-permission": "'''Voafafa''' ny santiônan'ity pejy ity.\nMety misy ny antsipirihany angamba ny [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAME}}}} laogy momban'ny famafàna pejy].",
+       "rev-deleted-text-permission": "<strong>Voafafa</strong> ny santiônan'ity pejy ity.\nMety misy ny antsipirihany angamba ny [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAME}}}} laogim-pamafàna pejy].",
        "rev-deleted-text-unhide": "Ity versionan'ity pejy ity dia '''voafafa'''.\nHita ao amin'ny [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} laogim-pamafana] ny antsipirihany.\nAfaka [$1 mijery ilay versiona] ianao raha tianao.",
        "rev-suppressed-text-unhide": "'''Nofafana''' ity versiom-pejy ity.\nAzo jerena ao amin'ny [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} laogim-pamafana] ny antsipirihany.\nAzonao [$1 jerena foana ilay santiôna] raha tianao.",
        "rev-deleted-text-view": "'''Nofafana''' ity versiom-pejy ity.\nAzonao jerena ity santiôna voafafa ity ; misy antsipirihany ao amin'ny [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} laogim-pamafana].",
        "rev-suppressed-text-view": "'''Nofafana''' ity versiom-pejy ity.\nAzonao jerena ilay versiona voafafa ; ny antsipirihany dia ao amin'ny [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} laogim-pamafana].",
-       "rev-deleted-no-diff": "Tsy afaka mijery anio diff io ianao satria misy santôna '''voafafa''' ao aminy.\nMety any amin'ny [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAME}}}} laogy momban'ny famafàna pejy] ny antsipirihany.",
+       "rev-deleted-no-diff": "Tsy afaka mijery anio fampitahana (diff) io ianao satria misy versiona '''voafafa''' ao aminy.\nMety any amin'ny [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAME}}}} laogy momban'ny famafàna pejy] ny antsipirihany.",
        "rev-suppressed-no-diff": "Tsy azo jerenao io diff io satria '''voafafa''' ny iraika amin'ny reviziônany.",
        "rev-deleted-unhide-diff": "Nisy '''voafafa''' ny iraika amin'ny reviziôna an'ity diff ity.\nNy antsipirihany dia mety hita ao amin'ny [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} laogin'ny famafana].\n[$1 Azonao jerena foana ilay diff] raha tianao.",
        "rev-suppressed-unhide-diff": "Nisy '''voafafa''' ny iraika amin'ny versiona an'ity diff ity.\nNy antsipirihany dia mety hita ao amin'ny [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} laogin'ny famafana].\n[$1 Azonao jerena foana ilay diff] raha tianao.",
        "logdelete-selected": "{{PLURAL:$1||}}Laogy voafidy :",
        "revdelete-confirm": "Amafiso eto ny hevitrao raha hanao io ianao, raha azonao sary an-tsaina ny mety ho vokany, ary raha araka ny [[{{MediaWiki:Policy-url}}|fepetra mihatra]] ny zavatra ataonao.",
        "revdelete-suppress-text": "Ny famafàna pejy dia ampiasaina rehefa :\n* Fampahalalana mampiely lainga\n* Misy fampahalalana tsy sarababem-bahoaka tsy metimety\n*: ''Adiresy onenana, laharana antso an-tariby, sns.''",
-       "revdelete-legend": "Ampetraho ny fepetra momban'ny fahitana :",
+       "revdelete-legend": "Hametraka ny fe-pahitana",
        "revdelete-hide-text": "Tahirintsoratry ny versiona",
        "revdelete-hide-image": "asitriho ny votoatin'ilay rakitra",
        "revdelete-hide-name": "Asitriho ny asa sy ny tanjona",
        "revdelete-submit": "Hampiharina amin'ny versiona nofidiana {{PLURAL:$1}}",
        "revdelete-success": "'''Voaova soa aman-tsara ny fahitana ny versiona.'''",
        "revdelete-failure": "'''Ny fisehon'ity versiona ity dia tsy afaka natao update'''\n$1",
-       "logdelete-success": "'''Voaova soa aman-tsara ny fisehon'ny tatitr’asa.'''",
-       "logdelete-failure": "'''Tsy afaka novaina ny fisehon'ny tatitr’asa'''\n$1",
+       "logdelete-success": "<strong>Voaova soa aman-tsara ny fisehon'ny laogy.</strong>",
+       "logdelete-failure": "<strong>Tsy afaka novaina ny fisehon'ny laogy</strong>\n$1",
        "revdel-restore": "Ovay ny fahitàna",
        "pagehist": "Tantaran'ilay pejy",
        "deletedhist": "Tantara voafafa",
        "revdelete-concurrent-change": "Tsi-fetezana teo am-panovana ny zavatra voadaty tamin'ny $1 tamin'ny $2 : ny satany dia voaovan' olon-kafa tamin'ianao nanova azy.\nJereo ny laogy.",
        "revdelete-only-restricted": "Tsi-fetezana teo am-panitrihana ny zavatra voadaty tamin'ny $1 tamin'ny $2 : tsy azonao fafana ireo zavatra ireo amin'ny mpandrindra raha tsy misafidy famafana.",
        "revdelete-reason-dropdown": "* Antom-pamafana matetika :\n** Tsifanajakan ny zom-pamrona;\n** Famoahan-kevitra na fampahalalana ho ann'ny olon-tokana tsy tokony haseho;\n** Fampahalalana mety mifototra amin'ny lainga.",
-       "revdelete-otherreason": "Antony hafa / antony miampy :",
+       "revdelete-otherreason": "Antony hafa/miampy :",
        "revdelete-reasonotherlist": "Antony hafa",
        "revdelete-edit-reasonlist": "Hanova ny anton'ny famafàna",
        "revdelete-offender": "Mpanao ilay reviziôna :",
-       "suppressionlog": "tatitr’asa momban’ny famafana pejy",
+       "suppressionlog": "Laogim-pamafana",
        "suppressionlogtext": "Ity ny lisitry ny famafana ary ny sakana mikasika ny votoatiny asitrika amin'ny mpandrindra. Jereo ny [[Special:BlockList|lisitry ny sakana]] ho an'ny lisitry ny fandroahana ary ny sakana mbola mihatra amin'izao fotoana.",
        "mergehistory": "Atsonika ny tantara ny pejy",
        "mergehistory-header": "Amin'ity pejy ity, afaka manonika santiônan'ny tantara pejy iaviana makany amina pejy vaovao ianao.\nMarino raha manohy ny tantaram-pejy ity asa ity.",
        "mergehistory-comment": "natambatra miarak'amin'ny [[:$2]] ny/i [[:$1]] : $3",
        "mergehistory-same-destination": "Ny pejy iaviana sy ny pejy tanjona dia tsy mahazo mitovy",
        "mergehistory-reason": "Antony :",
-       "mergelog": "Tatitr’asa momban’ny fitambarana",
+       "mergelog": "Laogim-fampitambarana",
        "pagemerge-logentry": "voatambatra tamin'ny [[$2]] [[$1]] (fanovàna hatramin'ny $3)",
        "revertmerge": "Saraho",
        "mergelogpagetext": "Ity ny lisitry ny fanambarana ny tantaram-pejy vao haingana",
        "searchprofile-advanced-tooltip": "Hitady ny anaran-tsehatra ho an'ny fikarohana",
        "search-result-size": "$1 ({{PLURAL:$2|teny|teny}} $2)",
        "search-result-category-size": "Mpiray sokajy $1{{PLURAL:$1}} (zana-tsokajy $2{{PLURAL:}}, rakitra $3{{PLURAL:}})",
-       "search-result-score": "Fifanarahana : $1%",
        "search-redirect": "(redirect avy amin'ny/amin'i $1)",
        "search-section": "(fizaràna $1)",
        "search-file-match": "(miady amin'ny votoatin-drakitra)",
        "searchrelated": "voadinika",
        "searchall": "rehetra",
        "showingresults": "Omeo ny valiny{{PLURAL:$1||}} miisa hatramin'ny <b>$1</b> manomboka ny #<b>$2</b>.",
-       "showingresultsheader": "{{PLURAL:$5}}Valim-pikaronhana '''$1x–$2''' an'i '''$3''' ho an'i '''$4'''",
        "search-nonefound": "Tsy nahitana valiny ilay fanontaniana.",
        "powersearch-legend": "Fikarohana havanana",
        "powersearch-ns": "Hitady anatin'ny anaran-tsehatra :",
        "powersearch-togglelabel": "Marihana:",
        "powersearch-toggleall": "Rehetra",
        "powersearch-togglenone": "Tsy misy",
+       "powersearch-remember": "Tadidio ho an'ny karoka manaraka ity safidy ity",
        "search-external": "Hikaroka any ivelany",
        "searchdisabled": "Tsy nalefa ny karoka eto amin'i {{SITENAME}}. Afaka mampiasa an'i Google aloha ianao mandra-paha. Nefa fantaro fa mety ho efa lany daty ny valiny omeny.",
        "search-error": "Hadisoana nitranga tam-pikarohana: $1",
        "preferences": "Ny momba anao",
        "mypreferences": "Safidy",
        "prefs-edits": "isa ny fanovàna :",
-       "prefsnologintext2": "$1 ianao hahafahanao mamaritra ny safidim-pikambana",
+       "prefsnologintext2": "Midira amin'ny kaontinao azafady mba hahafahanao mamaritra ny safidim-pikambana",
        "prefs-skin": "Endrika",
        "skin-preview": "Tsipalotra",
        "datedefault": "Tsy misy safidy",
        "right-move": "Manakisaka pejy",
        "right-move-subpages": "Manakisaka pejy miarak'amin'ny zana-pejiny",
        "right-move-rootuserpages": "Mamindra ny renipejin'ny mpikambana",
+       "right-move-categorypages": "Hanetsika ny pejin-tsokajy",
        "right-movefile": "Manova anarana rakitra",
        "right-suppressredirect": "Afaka tsy manometraka redirect avy amin'ny lohateny fiavina",
        "right-upload": "Mampidi-drakitra",
        "right-deletedtext": "Mijery ny lahatsoratra voafafa sy ny fampitahana anelanelan'ny versiona voafafa",
        "right-browsearchive": "Mitady pejy voafafa",
        "right-undelete": "Mamerina pejy voafafa",
-       "right-suppressrevision": "Mandinika sy mamerina ny version asitrika amin'ny mpandrindra",
+       "right-suppressrevision": "Mandinika sy mamerina ny version asitrika amin'ny mpikambana rehetra",
        "right-suppressionlog": "Mijery ny tao tsy sarababem-bahoaka",
        "right-block": "Manakana ny mpikambana mba tsy hanova",
        "right-blockemail": "Manakana ny mpikambana mba tsy handefa imailaka",
        "right-passwordreset": "Hijery ny imailaka famerenana ny tenimiafina",
        "newuserlogpage": "Tatitr’asan’ny fanokafana kaontim-pikambana",
        "newuserlogpagetext": "Ity pejy ity dia maneho ny tantaran'asan'ny fampidirana mpikambana vaovao.",
-       "rightslog": "Tatitr’asa momban’ny fanovana satam-pikambana",
-       "rightslogtext": "Ity ny laogy momban'ny fanovana ny zom-pikambana.",
+       "rightslog": "Laogim-piovan'ny zom-pikambana",
+       "rightslogtext": "Ity ny laogim-piovan'ny zom-pikambana",
        "action-read": "mamaky ity pejy ity",
        "action-edit": "manova ity pejy ity",
        "action-createpage": "hanao pejy",
        "action-createtalk": "hanao pejin-dresaka",
        "action-createaccount": "amboary io kaontim-pikambana io",
+       "action-history": "hijery ny tantaran'ity pejy ity",
        "action-minoredit": "Mariho ho kely ity fanovana ity",
        "action-move": "hamindra io pejy io",
        "action-move-subpages": "hamindra io pejy io sy ny zanapejiny",
        "action-move-rootuserpages": "hanolo anaran'ny pejin'ny mpikambana",
+       "action-move-categorypages": "hanetsika ny pejin-tsokajy",
        "action-movefile": "manova anaran'ny rakitra iray",
        "action-upload": "hampiditra io rakitra io",
        "action-reupload": "Hanolo io rakitra efa misy io",
        "recentchanges-label-plusminus": "IO ny isan'ny oktety niova tamin'ilay pejy",
        "recentchanges-legend-heading": "'''Maribolana:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (jereo koa ny [[Special:NewPage|lisitry ny pejy vaovao]])",
-       "rcnotefrom": "Ity eto ambany ity ny lisitry ny vao niova manomboka ny <b>$2</b> (hatramin'ny <b>$1</b> no miseho).",
+       "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",
        "rcshowhideminor-show": "Haneho",
        "uploadwarning": "Fampitandremana",
        "uploadwarning-text": "Ovay ny fanoritan' ilay rakitra ary andrao fanindroany.",
        "savefile": "Tehirizo ny rakitra",
-       "uploadedimage": "tonga ny rakitra\"[[$1]]\"",
-       "overwroteimage": "nampiditra versiona vaovao ny «[[$1]]»",
        "uploaddisabled": "Miala tsiny! Tsy azo atao ny mandefa rakitra.",
        "copyuploaddisabled": "Tsy alefa ny fandefasan-drakitra amin'ny alalan'ny URL.",
        "uploaddisabledtext": "Tsy afaka andefasana rakitra aloha eto amin'ity wiki ity.",
        "http-invalid-url": "URL diso : $1",
        "http-invalid-scheme": "Tsy zaka ny URL miaraka amin'ny sema « $1 »",
        "http-request-error": "Tsi-fetezana tsy fantam-piaviana teo ampandefasana ilay hataka.",
-       "http-read-error": "Tsy fetezana momban'ny famakiana HTTP.",
+       "http-read-error": "Hadisoam-pamakiana HTTP.",
        "http-timed-out": "Ny fangatahana HTTP dia efa lany daty.",
        "http-curl-error": "Tsi-fetezana teo am-pangalana ny URL : $1",
        "http-bad-status": "Nisy tsi-fetezana teo ampandefasana ny hataka HTTP: $1 $2",
        "license-nopreview": "(Tsy misy topi-maso)",
        "upload_source_url": " (URL misy ary azo vangian'ny daholobe)",
        "upload_source_file": " (rakitra eo amin'ny milinao)",
+       "listfiles-delete": "fafao",
        "listfiles-summary": "Ahitana ny rakitra rehetra nampidirina ity pejy manokana ity.",
        "listfiles_search_for": "Hitady anarana media :",
        "imgfile": "rakitra",
        "listfiles_size": "Habe",
        "listfiles_description": "Visavisa",
        "listfiles_count": "Version",
+       "listfiles-show-all": "Hampiditra ny versiona talohan'ny sary",
        "listfiles-latestversion": "Filaza ankehitriny",
        "listfiles-latestversion-yes": "Eny",
        "listfiles-latestversion-no": "Tsia",
        "randomincategory": "Pejy kisendra ao amin'ny sokajy",
        "randomincategory-invalidcategory": "Tsy anaran-tsokajy azo raisina \"$1\"",
        "randomincategory-nopages": "Tsy misy pejy ao amin'i [[:Category:$1]]",
-       "randomincategory-selectcategory": "Haka pejy kisendra ao amin'ny sokajy: $1 $2",
-       "randomincategory-selectcategory-submit": "Alefa",
        "randomredirect": "Pejy fihodinana kisendra",
        "randomredirect-nopages": "Tsy misy pejy fihodinana eo amin'ny anaran-tsehatra «$1»",
        "statistics": "Statistika",
        "booksources": "boky tsiahy",
        "booksources-search-legend": "hikaroka anatin'ny boky todika",
        "booksources-go": "Ataovy lisitra",
-       "booksources-text": "Ity misy lisitra maneho ny rohy makany amin'ny sehatra mivarotra boky vaovao sy efa vaky ary mety ahitanao fampahalalàna momban'ny boky sy soratra notadiavinao :",
+       "booksources-text": "Ity misy lisitra maneho ny rohy makany amin'ny sehatra mivarotra boky vaovao sy efa vaky ary mety ahitanao fampahalalàna momba ny boky sy soratra notadiavinao :",
        "booksources-invalid-isbn": "Ny ISBN nomena dia mety diso ; marino raha diso ianao teo am-pandikanana ny loharano fotony.",
        "specialloguserlabel": "Mpikambana nanao :",
        "speciallogtitlelabel": "Tanjona (lohateny na mpikambana) :",
        "log": "Tatitr’asa",
-       "all-logs-page": "Ny tatitr’asa",
+       "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",
        "watchlist-details": "Pejy $1{{PLURAL:}} ao amin'ny lisitry ny pejy arahanao, tsy isaina ny pejin-dresaka.",
        "wlheader-enotif": "Alefa ny fampilazana amin'ny mailaka.",
        "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 $3",
        "watchlist-options": "Safidy ny lisitry ny pejy arahana",
        "watching": "Fanarahana...",
        "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.",
-       "protectlogpage": "Tatitr’asa momban’ny fiarovana",
+       "protectlogpage": "Laogim-piarovana",
        "protectlogtext": "Eto ambany ny lisitry ny fiarovana/fanalana hidy ny pejy. \nHo ann'y fanazavana fanampiny, jereo [[Special:ProtectedPages|ny lisitry ny pejy voaaro]] ho an'ny pejy fiarovana amin'izao fotoana izao.",
        "protectedarticle": "voaaro ny pejy \"[[$1]]\"",
        "modifiedarticleprotection": "nanova ny haabo ny fiarovana ho an'ny « [[$1]] »",
        "import": "Hampidi-pejy",
        "importinterwiki": "fampidirana interwiki",
        "import-interwiki-text": "Safidio wiki loharano iray ary ny lohatenin'ilay pejy ho ampidirina eto.\nHo voatazona ao amin'ny tantara ny datin'ny santiôna sy ny anaran'ny mpandray anjara.\nHo voasoratra ao amin'ny [[Special:Log/import|laogim-pampidirana]] ny tao rehetra mikasika ny fampidirana pejy interwiki",
-       "import-interwiki-source": "Wiki sy pejy fango :",
        "import-interwiki-history": "Handika ny santiônan'ny tantaran'ity pejy ity",
        "import-interwiki-templates": "Ataovy ao ny endrika rehetra",
        "import-interwiki-submit": "Hampiditra",
        "tooltip-n-mainpage": "Jereo ny renipejy",
        "tooltip-n-mainpage-description": "hitsidika ny renipejy",
        "tooltip-n-portal": "Ny mombamomba ny tetikasa",
-       "tooltip-n-currentevents": "Hidady ny rohy momban'ny vaovao ankehitriny",
+       "tooltip-n-currentevents": "Hikaroka torohay fototra mikasika ny vaovao",
        "tooltip-n-recentchanges": "Lisitra ny fanovàna farany efa vita eto amin'ity wiki ity",
        "tooltip-n-randompage": "Hjery pejy aki-sendra",
        "tooltip-n-help": "fanoroana",
        "tooltip-ca-nstab-user": "Jereo ny pejin'ny mpikambana",
        "tooltip-ca-nstab-media": "Hijery ny pejin'ny Media",
        "tooltip-ca-nstab-special": "Pejy manokana ity pejy ity, ny rindrankajy wiki no mitantana ity pejy ity",
-       "tooltip-ca-nstab-project": "Jereo ny pejy momban'ny tetikasa",
+       "tooltip-ca-nstab-project": "Hijery ny pejin-tetikasa",
        "tooltip-ca-nstab-image": "jereo ny pejy an'io rakitra io",
        "tooltip-ca-nstab-mediawiki": "Hijery ny hafatra ampiasain'ny rindrankajy",
        "tooltip-ca-nstab-template": "Jereo ny endrika  (môdely)",
        "tooltip-ca-nstab-help": "Hijery ny pejy fanoroana",
-       "tooltip-ca-nstab-category": "Hijery ny pejy momban'ilay sokajy",
+       "tooltip-ca-nstab-category": "Hijery ny pejin'ilay sokajy",
        "tooltip-minoredit": "Mariho ho fanovana madinika ihany",
        "tooltip-save": "Tehirizo ny fanovana",
        "tooltip-preview": "Topazy maso ny fanovana nataonao, iangaviana ianao mba hijery tsipalotra mialoha ny fitahirizana ny fanovana!",
index 99d471f..c1e5e2a 100644 (file)
        "talkpagelinktext": "Каҥашымаш",
        "specialpage": "Лӱмын ыштыме лаштык",
        "personaltools": "Паша ӱзгар",
-       "postcomment": "У ужаш",
        "articlepage": "Лаштыкыште возымым ончыкташ",
        "talk": "Каҥашымаш",
        "views": "Ончалаш",
        "yourdomainname": "Тендан домен:",
        "login": "Шке денет палдаре",
        "nav-login-createaccount": "Пураш/Регистрацийым эрте",
-       "loginprompt": "{{SITENAME}} шке денет палдарыме деч ончыч компьютерыштет «cookies»-ым чӱктыман.",
        "userlogin": "Пураш/Регистрацийым эрташ",
        "logout": "Лекташ",
        "userlogout": "Лекташ",
        "uploadlogpage": "Оптымаш-влак журнал",
        "filedesc": "Файл нерген кӱчыкын увертараш",
        "fileuploadsummary": "Тидын нерген кӱчыкын:",
-       "uploadedimage": "«[[$1]]» пуртыш",
        "watchthisupload": "Тиде файлым эскераш",
        "license-header": "Лицензирований",
        "imgfile": "файл",
index 01cd28e..2af3d81 100644 (file)
        "talkpagelinktext": "maota",
        "specialpage": "Laman istimewa",
        "personaltools": "Pakakeh pribadi",
-       "postcomment": "Bagian baru",
        "articlepage": "Lihek isi laman",
        "talk": "Rundiang",
        "views": "Caliak",
        "externaldberror": "Alah tajadi kasalahan otentikasi basis data eksternal atau Sanak indak diizinan malakuan pabaruan tahadok akun eksternal Sanak.",
        "login": "Masuak log",
        "nav-login-createaccount": "Masuak log / buek akun",
-       "loginprompt": "Sanak musti mangaktipan ''cookies'' pado paramban Sanak untuak dapek masuak log ka {{SITENAME}} ko.",
        "userlogin": "Masuak log / buek akun",
        "userloginnocreate": "Masuak log",
        "logout": "Kalua log",
        "searchprofile-advanced-tooltip": "Pacarian di ruang namo tatantu",
        "search-result-size": "$1 ({{PLURAL:$2|$2 kato}})",
        "search-result-category-size": "{{PLURAL:$1|$1 anggota}} ({{PLURAL:$2|$2 subkategori}}, {{PLURAL:$3|$3 berkas}})",
-       "search-result-score": "Relevansi: $1%",
        "search-redirect": "(pangaliahan $1)",
        "search-section": "(bagian $1)",
        "search-suggest": "Mungkin makasuiknyo: $1",
        "filetype-bad-ie-mime": "Indak dapek mamuek berkas dek Internet Explorer mandeteksinyo sabagai \"$1\", nan indak diizinkan dan marupokan tipe berkas bapotensi bahayo.",
        "fileexists-thumbnail-yes": "Berkas ko nampaknyo marupoan gambar nan ukurannyo dipaketek ''(miniatua)''. [[$1|thumb]]\nCubo pareso berkas <strong>[[:$1]]</strong> tasabuik.\nKoq berkas tu samemang marupoan gambar dalam ukuran aslinyo, Sanak indak paralu untuak mamuak baliak miniatur lainnyo.",
        "file-thumbnail-no": "Namo berkas dimulai jo <strong>$1</strong>.\nNampaknyo berkas ko marupoan gambar jo ukuran dipaketek ''(miniatua)''.\nKoq Sanak ado versi resolusi panuah dari gambar ko, cubolah muekan berkas tasabuik. Koq indak, harap ubah namo berkas ko.",
-       "uploadedimage": "mamuek \"[[$1]]\"",
        "upload-source": "Berkas sumber",
        "sourcefilename": "Namo berkas sumber:",
        "sourceurl": "URL sumber:",
        "unwatchthispage": "Batal pantau laman ko",
        "watchlist-details": "{{PLURAL:$1|$1 laman}} dalam daftar pantau Sanak, indak tamasuak laman rundiangnyo.",
        "wlheader-showupdated": "Laman nan alah barubah sajak kunjuangan tarakhia Sanak ditunjuakan jo '''hurup taba'''",
+       "wlnote": "Di bawah ko ado $1 {{PLURAL:$1|parubahan}} dalam {{PLURAL:$2|'''$2''' jam}} iko, sampai tanggal $3, pukua $4.",
        "wlshowlast": "Tunjuakan $1 jam parubahan dalam $2 hari tarakhia $3",
        "watchlist-options": "Piliahan daftar pantau",
        "watching": "Mamantau...",
        "duplicate-defaultsort": "'''Peringatan:''' Kunci panguruitan default \"$2\" sabalunnyo mangabaikan kunci panguruitan default \"$1\".",
        "version": "Versi",
        "version-extensions": "Ekstensi tarinstal",
+       "version-skins": "Kulik",
        "version-specialpages": "Laman istimewa",
        "version-parserhooks": "Kaik parser",
        "version-variables": "Variabel",
        "version-antispam": "Pancagahan spam",
-       "version-skins": "Kulik",
        "version-other": "Lain-lain",
        "version-version": "(Versi $1)",
        "version-license": "Lisensi",
index 8f27297..1ff5e3c 100644 (file)
@@ -14,7 +14,8 @@
                        "Spacebirdy",
                        "Urhixidur",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Milicevic01"
                ]
        },
        "tog-underline": "Потцртување на врски:",
@@ -31,6 +32,7 @@
        "tog-watchdefault": "Додавај ги страниците и податотеките што ги уредувам во списокот на набљудувања",
        "tog-watchmoves": "Додавај ги страниците и податотеките што ги преместувам во списокот на набљудувања",
        "tog-watchdeletion": "Додавај ги страниците и податотеките што ги бришам во списокот на набљудувања",
+       "tog-watchrollback": "Додај ги страниците сум ги отповикал во набљудувани",
        "tog-minordefault": "Обележувај ги сите уредувања како ситни по основно",
        "tog-previewontop": "Прикажи го прегледот пред кутијата за уредување",
        "tog-previewonfirst": "Прикажи преглед на првото уредување",
        "newpage": "Нова страница",
        "talkpage": "Разговор",
        "talkpagelinktext": "Разговор",
-       "specialpage": "СпеÑ\86иÑ\98ална страница",
+       "specialpage": "СлÑ\83жбена страница",
        "personaltools": "Лични алатки",
-       "postcomment": "Ново заглавие",
        "articlepage": "Преглед на содржината",
        "talk": "Разговор",
        "views": "Посети",
        "otherlanguages": "На други јазици",
        "redirectedfrom": "(Пренасочено од $1)",
        "redirectpagesub": "Пренасочувачка страница",
+       "redirectto": "Пренасочи кон:",
        "lastmodifiedat": "Последната промена на страницава е извршена на $1 г. во $2 ч.",
        "viewcount": "Оваа страница била посетена {{PLURAL:$1|еднаш|$1 пати}}.",
        "protectedpage": "Заштитена страница",
        "hidetoc": "скриј",
        "collapsible-collapse": "Собери",
        "collapsible-expand": "прикажи",
+       "confirmable-confirm": "Дали {{GENDER:$1|сте}} сигурни?",
+       "confirmable-yes": "Да",
+       "confirmable-no": "Не",
        "thisisdeleted": "Да прикажам или вратам $1?",
        "viewdeleted": "Да погледате $1?",
        "restorelink": "{{PLURAL:$1|едно избришано уредување|$1 избришани уредувања}}",
        "nstab-main": "Страница",
        "nstab-user": "Корисник",
        "nstab-media": "Мултимедијална податотека",
-       "nstab-special": "СпеÑ\86иÑ\98ална страница",
+       "nstab-special": "СлÑ\83жбена страница",
        "nstab-project": "Проектна страница",
        "nstab-image": "Податотека",
        "nstab-mediawiki": "Порака",
        "nstab-category": "Категорија",
        "nosuchaction": "Нема такво дејство",
        "nosuchactiontext": "Дејството укажано во URL-адресата е погрешно.\nМожеби имате грешка во пишувањето на адресата, или пак имате проследено погрешна врска.\nОва може да се должи и на грешка во програмската опрема на {{SITENAME}}.",
-       "nosuchspecialpage": "Ð\9dе Ð¿Ð¾Ñ\81Ñ\82ои Ñ\82аква Ñ\81пеÑ\86иÑ\98ална страница",
-       "nospecialpagetext": "<strong>Ð\9fобаÑ\80авÑ\82е Ð½ÐµÐ¿Ð¾Ñ\81Ñ\82оеÑ\87ка Ñ\81пеÑ\86иÑ\98ална Ñ\81Ñ\82Ñ\80аниÑ\86а.</strong>\n\nСпиÑ\81окоÑ\82 Ð½Ð° Ð¿Ð¾Ñ\81Ñ\82оеÑ\87ки Ñ\81пеÑ\86иÑ\98ални страници: [[Special:SpecialPages|{{int:specialpages}}]].",
+       "nosuchspecialpage": "Ð\9dе Ð¿Ð¾Ñ\81Ñ\82ои Ñ\82аква Ñ\81лÑ\83жбена страница",
+       "nospecialpagetext": "<strong>Ð\9fобаÑ\80авÑ\82е Ð½ÐµÐ¿Ð¾Ñ\81Ñ\82оеÑ\87ка Ñ\81лÑ\83жбена Ñ\81Ñ\82Ñ\80аниÑ\86а.</strong>\n\nСпиÑ\81окоÑ\82 Ð½Ð° Ð¿Ð¾Ñ\81Ñ\82оеÑ\87ки Ñ\81лÑ\83жбени страници: [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Грешка",
        "databaseerror": "Грешка во базата",
        "databaseerror-text": "Се појави грешка во барањето од базата.\nОва може да значи програмска грешка (бубачка).",
        "mycustomjsprotected": "Немате дозвола да ја уредувате оваа страница со JavaScript.",
        "myprivateinfoprotected": "Немате дозвола да ги уредувате вашите лични информации.",
        "mypreferencesprotected": "Немате дозвола да ги уредувате вашите нагодувања.",
-       "ns-specialprotected": "СпеÑ\86иÑ\98ални страници не може да се уредуваат.",
+       "ns-specialprotected": "СлÑ\83жбени страници не може да се уредуваат.",
        "titleprotected": "Овој наслов од страна на [[User:$1|$1]] е заштитен и не може да се создаде.\nПричината за тоа е: ''$2''.",
        "filereadonlyerror": "Не можам да ја изменам податотеката „$1“ бидејќи складиштето „$2“ е во незаписен режим.\n\t\nАдминистраторот што ја заклучи го понуди следново образложение: „''$3''“.",
        "invalidtitle-knownnamespace": "Неважечки наслов со именски простор „$2“ и текст „$3“",
        "invalidtitle-unknownnamespace": "Неважечки наслов со именски простор бр. $1 и текст „$2“",
        "exception-nologin": "Не сте најавени",
-       "exception-nologin-text": "[[Special:Userlogin|Најавете се]] за да добиете пристап до страницата или дејството.",
+       "exception-nologin-text": "Најавете се за да добиете пристап до страницата или дејството.",
        "exception-nologin-text-manual": "Треба да сте $1 за да имате пристап до страницата или дејството.",
        "virus-badscanner": "Лоша поставка: непознат проверувач на вируси: ''$1''",
        "virus-scanfailed": "неуспешно скенирање (код $1)",
        "externaldberror": "Настана грешка при надворешното најавување на базата или пак немате дозвола да ја подновите вашата надворешна сметка.",
        "login": "Најава",
        "nav-login-createaccount": "Најава / регистрација",
-       "loginprompt": "За да се најавите на {{SITENAME}} мора да користите колачиња.",
        "userlogin": "Најава / регистрација",
        "userloginnocreate": "Најава",
        "logout": "Одјава",
        "userlogin-resetlink": "Си ги заборавивте податоците за најава?",
        "userlogin-resetpassword-link": "Ја заборавивте лозинката?",
        "userlogin-helplink2": "Помош за најава",
-       "userlogin-loggedin": "Веќе сте најавени како {{GENDER:$1|$1}}.\nСо образецот подолу можете да се најавите како друг корисник.",
-       "userlogin-createanother": "Направи нова сметка",
        "createacct-emailrequired": "Е-пошта",
        "createacct-emailoptional": "Е-пошта (незадолжително)",
        "createacct-email-ph": "Внесете е-пошта",
        "createaccount-text": "Некој направил сметка со вашата е-поштенска адреса на {{SITENAME}} ($4) со име „$2“ и  лозинка „$3“.\nБи требало сега да се пријавите и да ја промените вашата лозинка.\n\nМожете да ја занемарите оваа порака ако сметката била направена по грешка.",
        "login-throttled": "Имате премногу обиди за најава за кратко време.\nПочекајте $1 пред да се обидете повторно.",
        "login-abort-generic": "Најавата е неуспешна - Прекинато",
+       "login-migrated-generic": "Вашата сметка е пренесена и корисничкото име веќе не постои на ова вики.",
        "loginlanguagelabel": "Јазик: $1",
        "suspicious-userlogout": "Вашето барање за одјава е одбиено бидејќи се чини дека е испратено од расипан прелистувач или кеширачки застапник (proxy).",
        "createacct-another-realname-tip": "Вистинското име е незадолжително.\nДоколку изберете да го внесете, тоа може да се искористи за оддавање на заслуги за Вашата работа.",
        "preview": "Преглед",
        "showpreview": "Преглед",
        "showdiff": "Прикажи промени",
-       "anoneditwarning": "'''Предупредување:''' Не сте најавени.\nВашата IP-адреса ќе биде заведена во историјата на уредување на страницата.",
+       "blankarticle": "<strong>Предупредување:</strong> Страницата што ја создавате е празна.\nАко повторно стиснете на „{{int:savearticle}}“, страницата ќе биде создадена без никаква содржина во неа.",
+       "anoneditwarning": "<strong>Предупредување:</strong> Не сте најавени. Вашата IP-адреса ќе биде јавно видлива ако уредувате. Ако <strong>[$1 се најавите]</strong> или <strong>[$2 направите сметка]</strong>, тогаш уредувањата ќе се припишуваат на вашето корисничко име, покрај другите погодности.",
        "anonpreviewwarning": "''Не сте најавени. Ако ја зачувате, Вашата IP-адреса ќе биде заведена во историјата на уредување на страницата.''",
        "missingsummary": "'''Потсетник:''' Не внесовте опис на измените. Ако притиснете Зачувај повторно, вашите измени ќе се зачуваат без опис.",
        "missingcommenttext": "Ве молиме внесете коментар подолу.",
        "parser-template-recursion-depth-warning": "Пречекорена е границата на длабочината на рекурзијата во шаблонот ($1)",
        "language-converter-depth-warning": "Пречекорена е границата на длабочината на јазичниот претворач ($1)",
        "node-count-exceeded-category": "Страници каде е надминат бројот на јазли",
-       "node-count-exceeded-category-desc": "Ð\9aаÑ\82егоÑ\80иÑ\98а Ð·Ð° Ñ\81Ñ\82Ñ\80аниÑ\86и ÐºÐ°Ð´Ðµ Ðµ Ð½Ð°Ð´Ð¼Ð¸Ð½Ð°Ñ\82 Ð±Ñ\80оÑ\98оÑ\82 на јазли.",
+       "node-count-exceeded-category-desc": "СÑ\82Ñ\80аниÑ\86аÑ\82а Ð³Ð¾ Ð½Ð°Ð´Ð¼Ð¸Ð½Ñ\83ва Ð¼Ð°ÐºÑ\81ималниоÑ\82 Ð±Ñ\80оÑ\98 на јазли.",
        "node-count-exceeded-warning": "Страницата го надмина бројот на јазли",
        "expansion-depth-exceeded-category": "Страници каде е пречекорена длабочината на проширувањето",
-       "expansion-depth-exceeded-category-desc": "Ð\9eва Ðµ ÐºÐ°Ñ\82егоÑ\80иÑ\98а Ð½Ð°Ð¼ÐµÐ½ÐµÑ\82а Ð·Ð° Ñ\81Ñ\82Ñ\80аниÑ\86и Ñ\81о Ð½Ð°Ð´Ð¼Ð¸ната длабочина на проширување.",
+       "expansion-depth-exceeded-category-desc": "СÑ\82Ñ\80аниÑ\86аÑ\82а Ñ\98а Ð½Ð°Ð´Ð¼Ð¸Ð½Ñ\83ва Ð¼Ð°ÐºÑ\81ималната длабочина на проширување.",
        "expansion-depth-exceeded-warning": "Страницата ја надмина длабочината на проширувањето",
        "parser-unstrip-loop-warning": "Утврдена е јамка",
        "parser-unstrip-recursion-limit": "Пречекорена е границата на рекурзија ($1)",
        "undo-failure": "Уредувањето не можеше да се откаже заради меѓувремени спротиставени уредувања.",
        "undo-norev": "Измената не можеше да биде вратена бидејќи не постои или била избришана.",
        "undo-nochange": "Се чини дека измената (уредувањето) е веќе вратена.",
-       "undo-summary": "Откажано уредувањето $1 на уредникот [[Special:Contributions/$2|$2]] ([[User talk:$2|разговор]])",
+       "undo-summary": "Откажано уредувањето $1 на уредникот [[Special:Contribs/$2|$2]] ([[User talk:$2|разговор]])",
        "undo-summary-username-hidden": "Поништи ја преработката $1 на скриен корисник",
        "cantcreateaccounttitle": "Не може да се создаде корисничка сметка",
        "cantcreateaccount-text": "Создавањето на корисничка сметка од оваа IP-адреса ('''$1''') е блокирано од страна на [[User:$3|$3]].\n\nОбразложението дадено од страна на $3 е ''$2''",
        "rev-deleted-event": "(избришан запис на дејство)",
        "rev-deleted-user-contribs": "[отстрането е корисничкото име или IP-адресата - уредувањето нема да се прикаже на списокот на придонеси]",
        "rev-deleted-text-permission": "Оваа преработка страницата е <strong>избришана</strong>.\nМожеби има подробности во [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} дневникот на бришења].",
+       "rev-suppressed-text-permission": "Оваа преработка на страницата е <strong>притаена</strong>. Повеќе подробности ќе најдете во [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} дневникот на скривања].",
        "rev-deleted-text-unhide": "Оваа преработка на страницата е '''избришана'''.\nПовеќе подробности ќе најдете во [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} дневникот на бришења].\nСепак можете [$1 да ја погледнете оваа преработка] ако сакате да продолжите.",
        "rev-suppressed-text-unhide": "Оваа преработка на страница е '''притаена'''.\nПовеќе подробности ќе најдете во [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} дневникот на прикривања].\nСепак можете да ја [$1 погледнете оваа преработка] ако сакате да продолжите.",
        "rev-deleted-text-view": "Оваа преработка на страницата е '''избришана'''.\nМожете да ја погледнете; повеќе подробности ќе најдете во [{{fullurl:Special:Log/delete|page={{FULLPAGENAMEE}}}} дневникот на бришења].",
        "revdelete-text-text": "Избришаните преработки сепак се појавуваат во историјата, но делови од нивната содржина ќе бидат недостапни за јавноста.",
        "revdelete-text-file": "Избришаните верзии на податотеките сепак се појавуваат во нејзината историја, но делови од нивната содржина ќе бидат недостапни за јавноста.",
        "logdelete-text": "Избришаните дневнички ставки сепак се појавуваат во дневниците, но делови од нивната содржина ќе бидат недостапни за јавноста.",
-       "revdelete-text-others": "Другите администратори на {{SITENAME}} сепак ќе имаат пристап до скриените содржини и ќе можат да го повратат избришаното преку овој ист посредник, доколку не ставите дополнителни ограничувања.",
+       "revdelete-text-others": "Другите администратори на сепак ќе имаат пристап до скриените содржини и ќе можат да го повратат избришаното преку овој ист посредник, доколку не ставите дополнителни ограничувања.",
        "revdelete-confirm": "Потврдете дека сакате да го направите ова, дека ги сфаќате последиците, и дека тоа го правите во согласност со [[{{MediaWiki:Policy-url}}|правилата]].",
        "revdelete-suppress-text": "Притајувањето се користи '''само''' во следниве случаи:\n* Потенцијално клеветнички информации\n* Несоодветни лични информации\n*: ''домашни адреси и телефонски броеви, матични броеви и тн.''",
        "revdelete-legend": "Постави ограничувања за видливост",
        "searchprofile-advanced-tooltip": "Пребарување во именски простори по избор",
        "search-result-size": "$1 ({{PLURAL:$2|еден збор|$2 збора}})",
        "search-result-category-size": "{{PLURAL:$1|1 член|$1 члена}} ({{PLURAL:$2|1 поткатегорија|$2 поткатегории}}, {{PLURAL:$3|1 податотека|$3 податотеки}})",
-       "search-result-score": "Релевантност: $1%",
        "search-redirect": "(пренасочување $1)",
        "search-section": "(пасус $1)",
        "search-file-match": "(се совпаѓа со содржината на податотеката)",
        "searchall": "сè",
        "showingresults": "Подолу {{PLURAL:$1|е прикажан '''1''' резултат|се прикажани '''$1''' резултати}} почнувајќи од бр. '''$2'''.",
        "showingresultsinrange": "Долу {{PLURAL:$1|е прикажан до <strong>еден</strong> резултат|се прикажани до <strong>$1</strong> резултати}} во опсег од <strong>$2</strong> до <strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Резултат '''$1''' од '''$3'''|Резултати '''$1 - $2''' од '''$3'''}} за '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Резултат <strong>$1</strong> од <strong>$3</strong>|Резултати <strong>$1 - $2</strong> од <strong>$3</strong>}}",
        "search-nonefound": "Нема резултати што одговараат на бараното.",
        "powersearch-legend": "Напредно пребарување",
        "powersearch-ns": "Пребарај во следниве именски простори:",
        "powersearch-togglelabel": "Одбери:",
        "powersearch-toggleall": "Сè",
        "powersearch-togglenone": "Ништо",
-       "powersearch-remember": "Запамти го изборот за идни пребарувања",
+       "powersearch-remember": "Запoмни го изборот за идни пребарувања",
        "search-external": "Надворешно пребарување",
        "searchdisabled": "{{SITENAME}} пребарувањето е оневозможено.\nВо меѓувреме, можете да пребарувате преку Google.\nДа напоменеме дека нивното индексирање на {{SITENAME}} содржините може да биде застарено.",
        "search-error": "Се појави грешка при пребарувањето: $1",
        "preferences": "Нагодувања",
        "mypreferences": "нагодувања",
        "prefs-edits": "Број на уредувања:",
-       "prefsnologintext2": "ТÑ\80еба Ð´Ð° Ñ\81Ñ\82е $1 Ð·Ð° Ð´Ð° Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð³Ð¸ Ð¿Ð¾Ñ\81Ñ\82авÑ\83вате корисничките нагодувања.",
+       "prefsnologintext2": "Ð\9dаÑ\98авеÑ\82е Ñ\81е Ð·Ð° Ð´Ð° Ð³Ð¸ Ð¸Ð·Ð¼ÐµÐ½Ð¸те корисничките нагодувања.",
        "prefs-skin": "Руво",
        "skin-preview": "Преглед",
        "datedefault": "Небитно",
        "right-deletedtext": "Прегледување на избришан текст и промени помеѓу избришани преработки",
        "right-browsearchive": "Пребарување на избришани страници",
        "right-undelete": "Обновување избришана страница",
-       "right-suppressrevision": "Прегледување и враќање на преработки скриени од администратори",
+       "right-suppressrevision": "Прегледување, скривање и откривање на поединечни преработки на страници од било кој корисник",
+       "right-viewsuppressed": "Преглед на праработки скриени од било кој корисник",
        "right-suppressionlog": "Гледање на лични дневници",
        "right-block": "Оневозможување на останати корисници да уредуваат",
        "right-blockemail": "Оневозможување корисници да праќаат е-пошта",
        "recentchanges-legend-heading": "'''Легенда:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (погл. и [[Special:NewPages|списокот на нови страници]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Подолу се промените направени од <strong>$2</strong> наваму (се прикажуваат до <b>$1</b>).",
+       "rcnotefrom": "Подолу {{PLURAL:$5|е прикажана промената|се прикажани промените}} почнувајќи од <strong>$3, $4</strong>  (се прикажуваат до <b>$1</b>).",
        "rclistfrom": "Прикажи нови промени почнувајќи од $3 $2",
        "rcshowhideminor": "$1 ситни промени",
        "rcshowhideminor-show": "Прикажи",
        "large-file": "Се препорачува податотеките да не бидат поголеми од $1; оваа податотека е $2.",
        "largefileserver": "Големината на оваа податотека е поголема од максимално дозволената големина од серверот.",
        "emptyfile": "Податотеката што ја подигнавте е празна.\nОва може да се должи на грешка во нејзиното име.\nПроверете дали навистина сакате да ја подигнете ваквата податотека.",
-       "windows-nonascii-filename": "Опслужувачот не поддржува податотечни имиња со специјални знаци.",
+       "windows-nonascii-filename": "Опслужувачот не поддржува податотечни имиња со псоебни знаци.",
        "fileexists": "Податотека со ова име веќе постои. Проверете <strong>[[:$1]]</strong> ако не {{GENDER:|сте}} сигурни дали сакате да ја промените.\n[[$1|thumb]]",
        "filepageexists": "Описната страница на оваа податотека е веќе создадена на <strong>[[:$1]]</strong>, но не постои податотека со тоа име.\nОписот кој го внесовте нема да стои на описната страница.\nДоколку сакате описот да стои тука, ќе морате да го уредите рачно.\n[[$1|thumb]]",
        "fileexists-extension": "Податотека со слично име веќе постои: [[$2|thumb]]\n* Име на податотека која се подигнува: <strong>[[:$1]]</strong>\n* Име на постоечката податотека: <strong>[[:$2]]</strong>\nДали можеби би сакале да користите покарактеристично име.",
        "uploadwarning": "Предупредување при подигање",
        "uploadwarning-text": "Изменете го описот на податотеката подолу и обидете се повторно.",
        "savefile": "Зачувај податотека",
-       "uploadedimage": "подигнато „[[$1]]“",
-       "overwroteimage": "подигнато нова верзија на „[[$1]]“",
        "uploaddisabled": "Забрана за подигања",
        "copyuploaddisabled": "Подигањето од URL е оневозможено.",
        "uploaddisabledtext": "Подигањето на податотеки е оневозможено.",
        "upload-misc-error": "Непозната грешка при подигањето",
        "upload-misc-error-text": "Се појави грешка при подигањето.\nПроверете дали URL-адресата е правилна и достапна, па обидете се повторно.\nАко пак се појави проблем, обратете се кај некој [[Special:ListUsers/sysop|администратор]].",
        "upload-too-many-redirects": "Оваа URL адреса содржеше премногу пренасочувања",
-       "upload-http-error": "HTTP грешка: $1",
+       "upload-http-error": "Се појави грешка во HTTP: $1.",
        "upload-copy-upload-invalid-domain": "Примероци од подигањата не се достапни на овој домен.",
        "backend-fail-stream": "Не можев да ја емитувам податотеката $1.",
        "backend-fail-backup": "Не можев да направам резерва на податотеката $1.",
        "license": "Лиценцирање:",
        "license-header": "Лиценцирање",
        "nolicense": "Нема",
+       "licenses-edit": "Измени лиценцни можности",
        "license-nopreview": "(Прегледот не е достапен)",
-       "upload_source_url": " (важечка, јавно достапна URL-адреса)",
-       "upload_source_file": "(податотека на вашиот компјутер)",
-       "listfiles-summary": "Оваа специјална страница ги прикажува сите подигнати податотеки.",
+       "upload_source_url": "(податотеката што се ја одбрале од важечка, јавно достапна URL-адреса)",
+       "upload_source_file": "(податотеката што се ја одбрале од  вашиот сметач)",
+       "listfiles-delete": "избриши",
+       "listfiles-summary": "Оваа службена страница ги прикажува сите подигнати податотеки.",
        "listfiles_search_for": "Побарај име на податотека:",
        "imgfile": "податотека",
        "listfiles": "Список на податотеки",
        "randomincategory": "Случајна страница во категоријата",
        "randomincategory-invalidcategory": "„$1“ не претставува важечка категорија.",
        "randomincategory-nopages": "Нема страници во [[:Category:$1]].",
-       "randomincategory-selectcategory": "Дај случајна страница од категоријата: $1 $2.",
-       "randomincategory-selectcategory-submit": "Оди",
+       "randomincategory-category": "Категорија:",
+       "randomincategory-legend": "Случајна страница во категорија",
        "randomredirect": "Случајно пренасочување",
        "randomredirect-nopages": "Нема пренасочувања во именскиот простор „$1“.",
        "statistics": "Статистики",
        "statistics-edits": "Број на уредувања од започнувањето на {{SITENAME}}",
        "statistics-edits-average": "Просечен број на уредувања по страница",
        "statistics-views-total": "Вкупно посети",
-       "statistics-views-total-desc": "Ð\9dе Ñ\81е Ð²ÐºÐ»Ñ\83Ñ\87ени Ð¿Ñ\80егледÑ\83ваÑ\9aа Ð½Ð° Ð½ÐµÐ¿Ð¾Ñ\81Ñ\82оеÑ\87ки Ð¸ Ñ\81пеÑ\86иÑ\98ални страници",
+       "statistics-views-total-desc": "Ð\9dе Ñ\81е Ð²ÐºÐ»Ñ\83Ñ\87ени Ð¿Ñ\80егледÑ\83ваÑ\9aа Ð½Ð° Ð½ÐµÐ¿Ð¾Ñ\81Ñ\82оеÑ\87ки Ð¸ Ñ\81лÑ\83жбени страници",
        "statistics-views-peredit": "Посети по уредување",
        "statistics-users": "Регистрирани [[Special:ListUsers|корисници]]",
        "statistics-users-active": "Активни корисници",
        "wantedpages-badtitle": "Невалиден наслов во резултатите: $1",
        "wantedfiles": "Потребни податотеки",
        "wantedfiletext-cat": "Следниве податотеки се користат, но не постојат. Податотеките од други складишта може да се наведени дури и ако постојат. Таквите ќе бидат <del>поништени</del> од списокот. Покрај ова, страниците што содржат податотеки кои не постојат се наведени на [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Следниве податотеки се користат, но не постојат. Покрај ова, страниците што ги содржат непостоечките податотеки се наведени во [[:$1]].",
        "wantedfiletext-nocat": "Следниве податотеки се користат, но не постојат. Податотеките од други складишта може да се наведени дури и ако постојат. Таквите ќе бидат <del>поништени</del> од списокот.",
+       "wantedfiletext-nocat-noforeign": "Следниве податотеки се користат, но не постојат.",
        "wantedtemplates": "Потребни шаблони",
        "mostlinked": "Најмногу врски до страници",
        "mostlinkedcategories": "Најмногу врски до категории",
        "pager-newer-n": "{{PLURAL:$1|понова 1|понови $1}}",
        "pager-older-n": "{{PLURAL:$1|постара 1|постари $1}}",
        "suppress": "Скривање",
-       "querypage-disabled": "Ð\9eваа Ñ\81пеÑ\86иÑ\98ална страница е оневозможена за да не попречува на делотворноста.",
+       "querypage-disabled": "Ð\9eваа Ñ\81лÑ\83жбена страница е оневозможена за да не попречува на делотворноста.",
        "booksources": "Печатени извори",
        "booksources-search-legend": "Пребарување на извори за книга",
        "booksources-isbn": "ISBN:",
        "trackingcategories-desc": "Критериуми за вклучување",
        "noindex-category-desc": "Роботите не ја индексираат страницава бидејќи го содржи волшебниот збор <code><nowiki>__NOINDEX__</nowiki></code> и се наоѓа во именски простор кајшто е дозволен.",
        "index-category-desc": "Страницата содржи <code><nowiki>__INDEX__</nowiki></code> (и се наоѓа во именски простор кајшто ова е дозволено), па затоа се индексира од роботи, што инаку не би било.",
-       "post-expand-template-inclusion-category-desc": "Ð\9fо Ð¿Ñ\80оÑ\88иÑ\80Ñ\83ваÑ\9aеÑ\82о Ð½Ð° Ñ\81иÑ\82е Ñ\88аблони, Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а Ðµ Ð¿Ð¾Ð³Ð¾Ð»ÐµÐ¼Ð° Ð¾Ð´ <code>$wgMaxArticleSize</code>, Ð¿Ð° Ð·Ð°Ñ\82оа некои шаблони не се проширени.",
-       "post-expand-template-argument-category-desc": "Ð\9fо Ð¿Ñ\80оÑ\88иÑ\80Ñ\83ваÑ\9aе Ð½Ð° Ñ\88аблонÑ\81ки Ð°Ñ\80гÑ\83менÑ\82 (неÑ\88Ñ\82о Ð²Ð¾ Ñ\82Ñ\80оÑ\98ни ÐºÐ°Ð´Ñ\80ави Ð·Ð°Ð³Ñ\80ади, ÐºÐ°ÐºÐ¾ Ð½Ð° Ð¿Ñ\80. <code>{{{Foo}}})</code>, Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а Ðµ Ð¿Ð¾Ð³Ð¾Ð»ÐµÐ¼Ð° Ð¾Ð´ <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Ð\92о Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а Ð¸Ð¼Ð° премногу оптоварувачки расчленувачки функции (како <code>#ifexist</code>). Погл. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Ð\9aаÑ\82егоÑ\80Ñ\98аÑ\82а Ñ\81е Ñ\81Ñ\82ава Ð°ÐºÐ¾ Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а Ñ\81одÑ\80жи Ð½ÐµÐ¸Ñ\81пÑ\80авна Ð¿Ð¾Ð´Ð°Ñ\82оÑ\82еÑ\87ка врска (врска за вметнување на податотека што не постои).",
-       "hidden-category-category-desc": "Ð\9eва Ðµ ÐºÐ°Ñ\82егоÑ\80иÑ\98а Ñ\88Ñ\82о содржи <code><nowiki>__HIDDENCAT__</nowiki></code>, што значи дека по основно не се прикажува во страниците.",
+       "post-expand-template-inclusion-category-desc": "СÑ\82Ñ\80аниÑ\86аÑ\82а Ðµ Ð¿Ð¾Ð³Ð¾Ð»ÐµÐ¼Ð° Ð¾Ð´ <code>$wgMaxArticleSize</code> Ð¿Ð¾ Ð¿Ñ\80оÑ\88иÑ\80Ñ\83ваÑ\9aеÑ\82о Ð½Ð° Ñ\81иÑ\82е Ñ\88аблони. Ð\97аÑ\82оа, некои шаблони не се проширени.",
+       "post-expand-template-argument-category-desc": "СÑ\82Ñ\80аниÑ\86аÑ\82а Ðµ Ð¿Ð¾Ð³Ð¾Ð»ÐµÐ¼Ð° Ð¾Ð´ <code>$wgMaxArticleSize</code> Ð¿Ð¾ Ð¿Ñ\80оÑ\88иÑ\80Ñ\83ваÑ\9aе Ð½Ð° Ñ\88аблонÑ\81киоÑ\82 Ð°Ñ\80гÑ\83менÑ\82 (неÑ\88Ñ\82о Ð²Ð¾ Ñ\82Ñ\80оÑ\98ни ÐºÐ°Ð´Ñ\80ави Ð·Ð°Ð³Ñ\80ади, ÐºÐ°ÐºÐ¾ <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "СÑ\82Ñ\80аниÑ\86аÑ\82а ÐºÐ¾Ñ\80иÑ\81Ñ\82и премногу оптоварувачки расчленувачки функции (како <code>#ifexist</code>). Погл. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "СÑ\82Ñ\80аниÑ\86аÑ\82а Ñ\81одÑ\80жи Ð½ÐµÐ¸Ñ\81пÑ\80авна Ð¿Ð¾Ð´Ð°Ñ\82оÑ\82еÑ\87на врска (врска за вметнување на податотека што не постои).",
+       "hidden-category-category-desc": "Ð\9aаÑ\82егоÑ\80иÑ\98аÑ\82а содржи <code><nowiki>__HIDDENCAT__</nowiki></code>, што значи дека по основно не се прикажува во страниците.",
        "trackingcategories-nodesc": "Нема опис.",
        "trackingcategories-disabled": "Категоријата е оневозможена",
        "mailnologin": "Нема адреса за праќање",
        "mywatchlist": "Набљудувања",
        "watchlistfor2": "За $1 $2",
        "nowatchlist": "Немате ништо во списокот на набљудувања.",
-       "watchlistanontext": "ТÑ\80еба Ð´Ð° Ñ\81Ñ\82е $1 за да можете да го прегледувате и уредувате списокот на набљудувања.",
+       "watchlistanontext": "Ð\9dаÑ\98авеÑ\82е Ñ\81е за да можете да го прегледувате и уредувате списокот на набљудувања.",
        "watchnologin": "Не сте најавени",
        "addwatch": "Додај во списокот на набљудувања",
        "addedwatchtext": "Страницата „[[:$1]]“ е додадена во [[Special:Watchlist|списокот на набљудувања]].\nИдните промени на оваа страница и нејзината страница за разговор ќе се прикажуваат таму.",
        "watchlist-details": "{{PLURAL:$1|$1 страница|$1 страници}} во вашиот список на набљудувања, не броејќи ги посебно страниците за разговор.",
        "wlheader-enotif": "Известувањето по е-пошта е вклучено.",
        "wlheader-showupdated": "Страниците што се изменети од вашата последна посета се прикажани со '''задебелени''' букви",
-       "wlnote2": "Подолу се прикажани промените направени во {{PLURAL:$1|последниов час|последните <strong>$1</strong> часа}}, согласно $2, $3.",
+       "wlnote": "Подолу {{PLURAL:$1|е прикажана последната промена|се прикажани последните <strong>$1</strong> промени}} во {{PLURAL:$2|последниов час|последниве <strong>$2</strong> часа}}, заклучно со $3, $4 ч.",
        "wlshowlast": "Прикажи ги последните $1 часа, $2 дена, $3",
        "watchlist-options": "Поставки за список на набљудувања",
        "watching": "Набљудување...",
        "exbeforeblank": "содржината пред бришењето беше: '$1'",
        "delete-confirm": "Бришење на „$1“",
        "delete-legend": "Бришење",
-       "historywarning": "'''Предупредување:''' Страницата што сакате да ја избришете има историја со околу $1 {{PLURAL:$1|преработка|преработки}}:",
+       "historywarning": "<strong>Предупредување:</strong> Страницата што сакате да ја избришете има историја со {{PLURAL:$1|една преработка|$1 преработки}}:",
        "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}};\nпродолжете доколку сте сигруни дека треба тоа да го сторите.",
+       "deleteprotected": "Не можете да ја избришете страницава бидејќи е заштитена.",
        "deleting-backlinks-warning": "'''Предупредување:''' До страницата што сакате да ја избришете водат [[Special:WhatLinksHere/{{FULLPAGENAME}}|други страници]] или пак се превметнуваат во неа.",
        "rollback": "Отповикај промени",
        "rollback_short": "Отповикај",
        "autoblockid": "Автоблок бр. $1",
        "block": "Блокирај корисник",
        "unblock": "Одблокирај корисник",
-       "blockip": "Блокирај корисник",
+       "blockip": "Блокирај {{GENDER:$1|корисник}}",
        "blockip-legend": "Блокирај корисник",
        "blockiptext": "Користете го долниот образец за да го забраните пристапот за пишување од одредена IP-адреса или корисничко име.\nОва единствено треба да се прави за да се спречи вандализам, во согласност со [[{{MediaWiki:Policy-url}}|правилата на Википедија]].\nИзберете конкретна причина подолу (на пр. наведувајќи ги страниците што биле вандализирани).",
        "ipaddressorusername": "IP-адреса или корисничко име:",
        "ipb-unblock-addr": "Одблокирај го $1",
        "ipb-unblock": "Одблокирај корисник или IP-адреса",
        "ipb-blocklist": "Преглед на активни блокирања",
-       "ipb-blocklist-contribs": "Придонеси на $1",
+       "ipb-blocklist-contribs": "Придонеси на {{GENDER:$1|$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": "Најди блокиран корисник",
        "import": "Увезување на страници",
        "importinterwiki": "Меѓувики увоз",
        "import-interwiki-text": "Избери вики и наслов на страница за увоз.\nДатумите и имињата на уредниците ќе бидат зачувани.\nСите постапки при увозот од другото вики се заведуваат во [[Special:Log/import|дневникот на увезувања]].",
-       "import-interwiki-source": "Извор вики/страница:",
+       "import-interwiki-sourcewiki": "Изворно вики:",
+       "import-interwiki-sourcepage": "Изворна страница:",
        "import-interwiki-history": "Копирај ги сите постари верзии за оваа страница",
        "import-interwiki-templates": "Вклучи ги сите шаблони",
        "import-interwiki-submit": "Увези",
        "import-error-create": "Страницата „$1“ не е увезена бидејќи не ви е дозволено да ја создадете.",
        "import-error-interwiki": "Страницата „$1“ не е увезена бидејќи името е резервирано за надворешни врски (меѓувики).",
        "import-error-special": "Страницата „$1“ не е увезена бидејќи припаѓа на посебен именски простор што не дозволува страници.",
-       "import-error-invalid": "Страницата „$1“ не е увезена бидејќи името ѝ е неважечко.",
+       "import-error-invalid": "Страницата „$1“ не е увезена бидејќи името ѝ е неважечко на ова вики.",
        "import-error-unserialize": "Преработката $2 на страницата „$1“ не може да се отсеријализира. Утврдено е дека користи содржинскиот модел $3 што е серијализиран како $4.",
        "import-error-bad-location": "Преработката $2 што го користи содржинскиот модел $3 не може да се складира во „$1“ на ова вики бидејќи тој модел не е поддржан на таа страница.",
        "import-options-wrong": "{{PLURAL:$2|Погрешна можност|Погрешни можности}}: <nowiki>$1</nowiki>",
        "importlogpage": "Дневник на увезувања",
        "importlogpagetext": "Административно увезување на страници со историја на уредување од други викија.",
        "import-logentry-upload": "увезена [[$1]] со подигање на податотека",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|преработка|преработки}}",
+       "import-logentry-upload-detail": "{{PLURAL:$1|Увезена е една преработка|Увезени се $1 преработки}}",
        "import-logentry-interwiki": "трансвикифиран $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|преработка|преработки}} од $2",
+       "import-logentry-interwiki-detail": "{{PLURAL:$1|Увезена е една преработка|Увезени се $1 преработки}} од $2",
        "javascripttest": "Проба на JavaScript",
        "javascripttest-title": "Вршам $1 проби",
        "javascripttest-pagetext-noframework": "Оваа страница е резервирана за вршење на проби со JavaScript.",
        "tooltip-t-contributions": "Список на придонеси на овој корисник",
        "tooltip-t-emailuser": "Испрати е-пошта на овој корисник",
        "tooltip-t-upload": "Подигни податотеки",
-       "tooltip-t-specialpages": "СпиÑ\81ок Ð½Ð° Ñ\81иÑ\82е Ñ\81пеÑ\86иÑ\98ални страници",
+       "tooltip-t-specialpages": "СпиÑ\81ок Ð½Ð° Ñ\81иÑ\82е Ñ\81лÑ\83жбени страници",
        "tooltip-t-print": "Верзија за печатење на оваа страница",
        "tooltip-t-permalink": "Постојана врска до оваа верзија на страницата",
        "tooltip-ca-nstab-main": "Преглед на содржината",
        "tooltip-ca-nstab-user": "Преглед на корисничката страница",
        "tooltip-ca-nstab-media": "Преглед на мултимедијалната податотека",
-       "tooltip-ca-nstab-special": "Ð\9eва Ðµ Ñ\81пеÑ\86иÑ\98ална Ñ\81Ñ\82Ñ\80аниÑ\86а, не можете да ја уредувате",
+       "tooltip-ca-nstab-special": "Ð\9eва Ðµ Ñ\81лÑ\83жбена Ñ\81Ñ\82Ñ\80аниÑ\86а Ð¸ Ð·Ð°Ñ\82оа не можете да ја уредувате",
        "tooltip-ca-nstab-project": "Преглед на проектната страница",
        "tooltip-ca-nstab-image": "Преглед на страницата на податотеката",
        "tooltip-ca-nstab-mediawiki": "Преглед на системската порака",
        "file-no-thumb-animation-gif": "'''Напомена: Поради технички ограничувања, минијатурите на GIF-слики со висока разложеност како оваа нема да се анимираат.'''",
        "newimages": "Галерија на нови податотеки",
        "imagelisttext": "Следи список на '''$1''' {{PLURAL:$1|податотека|податотеки}} подредени $2.",
-       "newimages-summary": "Ð\9eваа Ñ\81пеÑ\86иÑ\98ална страница ги покажува скоро подигнатите податотеки.",
+       "newimages-summary": "Ð\9eваа Ñ\81лÑ\83жбена страница ги покажува скоро подигнатите податотеки.",
        "newimages-legend": "Филтрирај",
        "newimages-label": "Име на податотека (или дел од името):",
        "newimages-showbots": "Прикажувај подигања од ботови",
        "autosumm-replace": "Ја заменувам страницата со '$1'",
        "autoredircomment": "Пренасочување кон [[$1]]",
        "autosumm-new": "Создадена страница со: $1",
+       "autosumm-newblank": "Создадена празна страница",
        "size-bytes": "$1 Б",
        "size-kilobytes": "$1 КБ",
        "size-megabytes": "$1 МБ",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|разговор]])",
        "unknown_extension_tag": "Непозната ознака на додатокот „$1“",
        "duplicate-defaultsort": "Предупредување: Основниот клуч за подредување „$2“ го поништува претходниот основен клуч за подредување „$1“.",
+       "duplicate-displaytitle": "<strong>Предупредување:</strong> Приказниот наслов „$2“ го заменува претходнито приказен наслов „$1“.",
        "version": "Верзија",
        "version-extensions": "Воспоставени додатоци",
        "version-skins": "Воспоставени рува",
-       "version-specialpages": "СпеÑ\86иÑ\98ални страници",
+       "version-specialpages": "СлÑ\83жбени страници",
        "version-parserhooks": "Расчленувачки куки",
        "version-variables": "Променливи",
        "version-antispam": "Спречување на спам",
        "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath?uselang=mk Скрипта]",
        "redirect": "Пренасочување по податотеки, корисник или назнака на преработка",
        "redirect-legend": "Пренасочување кон податотека или страница",
-       "redirect-summary": "Ð\9eваа Ñ\81пеÑ\86иÑ\98ална страница пренасочува кон податотека (се задава името), страница (се задава назнаката на преработката или страницата) или корисничка странца (се задава бројчената назнака на корисникот). Употреба: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] или [[{{#Special:Redirect}}/user/101]].",
+       "redirect-summary": "Ð\9eваа Ñ\81лÑ\83жбена страница пренасочува кон податотека (се задава името), страница (се задава назнаката на преработката или страницата) или корисничка странца (се задава бројчената назнака на корисникот). Употреба: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] или [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Оди",
        "redirect-lookup": "Пребарај:",
        "redirect-value": "Вредност:",
        "fileduplicatesearch-result-1": "Податотеката „$1“ нема истоветни дупликати.",
        "fileduplicatesearch-result-n": "Податотеката „$1“ има {{PLURAL:$2|еден истоветен дупликат|$2 истоветни дупликати}}.",
        "fileduplicatesearch-noresults": "Не пронајдов податотека со име „$1“.",
-       "specialpages": "СпеÑ\86иÑ\98ални страници",
+       "specialpages": "СлÑ\83жбени страници",
        "specialpages-note-top": "Легенда",
-       "specialpages-note": "* Ð\9dоÑ\80мални Ñ\81пеÑ\86иÑ\98ални Ñ\81Ñ\82Ñ\80аниÑ\86и.\n* <span class=\"mw-specialpagerestricted\">Ð\9eгÑ\80аниÑ\87ени Ñ\81пеÑ\86иÑ\98ални страници.</span>",
+       "specialpages-note": "* Ð\9dоÑ\80мални Ñ\81лÑ\83жбени Ñ\81Ñ\82Ñ\80аниÑ\86и.\n* <span class=\"mw-specialpagerestricted\">Ð\9eгÑ\80аниÑ\87ени Ñ\81лÑ\83жбени страници.</span>",
        "specialpages-group-maintenance": "Извештаи за одржување",
-       "specialpages-group-other": "Ð\94Ñ\80Ñ\83ги Ñ\81пеÑ\86иÑ\98ални страници",
+       "specialpages-group-other": "Ð\94Ñ\80Ñ\83ги Ñ\81лÑ\83жбени страници",
        "specialpages-group-login": "Најава / регистрација",
        "specialpages-group-changes": "Скорешни промени и дневници",
        "specialpages-group-media": "Извештаи за мултимедијални содржини и подигања",
        "specialpages-group-pages": "Списоци на страници",
        "specialpages-group-pagetools": "Алатки за страници",
        "specialpages-group-wiki": "Податоци и алатки",
-       "specialpages-group-redirects": "Ð\9fÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aе Ð½Ð° Ñ\81пеÑ\86иÑ\98ални страници",
+       "specialpages-group-redirects": "Ð\9fÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aе Ð½Ð° Ñ\81лÑ\83жбени страници",
        "specialpages-group-spam": "Алатки против спам",
        "blankpage": "Празна страница",
        "intentionallyblankpage": "Оваа страница намерно е оставена празна",
        "logentry-rights-rights": "$1 {{GENDER:$2|го измени}} групното членство на $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",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|подигна}} нова верзија на $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|ја подигна}} $3",
        "rightsnone": "(нема)",
        "feedback-bugornote": "Ако сте спремни подробно да го опишете техничкиот проблем, тогаш [$1 пријавете грешка]. \nВо спротивно, послужете се со едноставниот образец подолу. Вашиот коментар ќе стои на страницата „[$3 $2]“, заедно со корисничкото име и прелистувачот што го користите.",
        "feedback-subject": "Наслов:",
        "limitreport-expansiondepth": "Најголема длабочина на проширувањето",
        "limitreport-expensivefunctioncount": "Бр. на сложени расчленувачки функции",
        "expandtemplates": "Прошири шаблони",
-       "expand_templates_intro": "Ð\9eваа Ñ\81пеÑ\86иÑ\98ална страница зема еден текст и рекурзивно ги проширува сите шаблони во него.\nИсто така проширува и расчленувачки функции како\n<code><nowiki>{{</nowiki>#language:…}}</code> и променливи како\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nВсушност, го проширува сето она што стои во двојни аглести загради.",
+       "expand_templates_intro": "Ð\9eваа Ñ\81лÑ\83жбена страница зема еден текст и рекурзивно ги проширува сите шаблони во него.\nИсто така проширува и расчленувачки функции како\n<code><nowiki>{{</nowiki>#language:…}}</code> и променливи како\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nВсушност, го проширува сето она што стои во двојни аглести загради.",
        "expand_templates_title": "Наслов на контекстот, за {{FULLPAGENAME}} и тн.:",
        "expand_templates_input": "Влезен текст:",
        "expand_templates_output": "Извод",
        "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 dir=\"ltr\">$wgDefaultSkin</code> as <code>$1</code> не е достапно.\n\nВашата воспоставка ги опфаќа следниве рува. Погледајте [https://www.mediawiki.org/wiki/Manual:Skin_configuration Прирачник: Поставување на рува] за да дознаете како да ги вклучите и како да го изберете основното.\n\n$2\n\n; Ако штотуку го имате воспоставено МедијаВики:\n: Веројатно сте го воспоставиле од git, или пак непосредно од изворниот код на некој друг начин. Ова е очекувано. Пробајте да воспоставите некои рува од [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's именикот на рува] вака:\n* Со преземање на [https://www.mediawiki.org/wiki/Download tarball-воспоставувачот], кој самиот содржи неколку рува и додатоци. Можете да ја прекопирате папката <code>skins/</code> од него.\n* Клонирајќи едно од складиштата <code>mediawiki/skins/*</code> преку git во папката <code dir=\"ltr\">skins/</code> на вашата воспоставка на МедијаВики.\n: Ова не би требало да прави пречки на вашето git-складиште ако сте програмер на МедијаВики.\n\n; Ако штотуку го имате надградено МедијаВики:\n: МедијаВики 1.24 и поновите верзии повеќе не ги вклучуваат воспоставените рува автоматски (погл. [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Прирачник: Самооткривање на рува]). Можете да ги прекопирате следниве редови во <code>LocalSettings.php</code> за да ги вклучите сите моментално воспоставени рува:\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Немате воспоставено ниедно руво.\n\n; Ако штотуку го имате воспоставено или надградено МедијаВики:\n: Веројатно сте го воспоставиле од git, или пак непосредно од изворниот код на некој друг начин. Ова е очекувано. МедијаВики 1.24 и поновите верзии немаат рува во главното складиште. Пробајте да воспоставите некои рува од [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's именикот на рува] вака:\n:* Со преземање на [https://www.mediawiki.org/wiki/Download tarball-воспоставувачот], кој самиот содржи неколку рува и додатоци. Можете да ја прекопирате папката <code dir=\"ltr\">skins/</code> од него.\n: Ова не би требало да прави пречки на вашето 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 ('''исклучено''')"
 }
index 56c62e6..3de847e 100644 (file)
@@ -44,6 +44,7 @@
        "tog-watchdefault": "ഞാൻ തിരുത്തുന്ന താളുകളും പ്രമാണങ്ങളും ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിൽ ചേർക്കുക",
        "tog-watchmoves": "ഞാൻ തലക്കെട്ടു മാറ്റുന്ന താളുകളും പ്രമാണങ്ങളും ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിൽ ചേർക്കുക",
        "tog-watchdeletion": "ഞാൻ നീക്കം ചെയ്യുന്ന താളുകളും പ്രമാണങ്ങളും ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിൽ ചേർക്കുക",
+       "tog-watchrollback": "ഞാൻ മുൻപ്രാപനം ചെയ്ത താളുകളും ഞാൻ ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിൽ ചേർക്കുക",
        "tog-minordefault": "എല്ലാ തിരുത്തുകളും സ്വതേ ചെറുതിരുത്തുകളായി അടയാളപ്പെടുത്തുക",
        "tog-previewontop": "തിരുത്തൽ പെട്ടിക്കു മുകളിൽ പ്രിവ്യൂ കാണിക്കുക",
        "tog-previewonfirst": "ആദ്യത്തെ തിരുത്തിന്റെ പ്രിവ്യൂ കാണിക്കുക",
        "talkpagelinktext": "സംവാദം",
        "specialpage": "പ്രത്യേക താൾ",
        "personaltools": "സ്വകാര്യതാളുകൾ",
-       "postcomment": "അഭിപ്രായം ചേർക്കുക",
        "articlepage": "ലേഖനം കാണുക",
        "talk": "സംവാദം",
        "views": "ദർശനീയത",
        "hidetoc": "മറയ്ക്കുക",
        "collapsible-collapse": "ചുരുക്കുക",
        "collapsible-expand": "വികസിപ്പിക്കുക",
+       "confirmable-confirm": "{{GENDER:$1|താങ്കൾക്ക്}} ഉറപ്പാണോ?",
+       "confirmable-yes": "അതെ",
+       "confirmable-no": "അല്ല",
        "thisisdeleted": "$1 കാണുകയോ പുനഃസ്ഥാപിക്കുകയോ ചെയ്യേണ്ടതുണ്ടോ?",
        "viewdeleted": "$1 കാണണോ?",
        "restorelink": "{{PLURAL:$1|നീക്കംചെയ്ത ഒരു തിരുത്ത്|നീക്കംചെയ്ത $1 തിരുത്തുകൾ}}",
        "invalidtitle-knownnamespace": "നാമമേഖല \"$2\", എഴുത്ത് \"$3\" എന്നിവ ഉപയോഗിച്ചുള്ള അസാധുവായ തലക്കെട്ട്",
        "invalidtitle-unknownnamespace": "അപരിചിതമായ നാമമേഖലാ സംഖ്യ $1, എഴുത്ത് \"$2\" എന്നിവ ഉപയോഗിച്ചുള്ള അസാധുവായ തലക്കെട്ട്",
        "exception-nologin": "ലോഗിൻ ചെയ്തിട്ടില്ല",
-       "exception-nologin-text": "ഈ വിക്കിയിൽ ഈ താൾ അല്ലെങ്കിൽ പ്രവൃത്തി ലഭ്യമാകാൻ ദയവായി [[Special:Userlogin|പ്രവേശിക്കുക]].",
+       "exception-nologin-text": "ഈ വിക്കിയിൽ ഈ താൾ അല്ലെങ്കിൽ പ്രവൃത്തി ലഭ്യമാകാൻ ദയവായി പ്രവേശിക്കുക.",
        "exception-nologin-text-manual": "ഈ താൾ അല്ലെങ്കിൽ പ്രവൃത്തി ഉപയോഗിക്കാൻ ദയവായി $1.",
        "virus-badscanner": "തെറ്റായ ക്രമീകരണങ്ങൾ: അപരിചിതമായ വൈറസ് തിരച്ചിൽ ഉപാധി :  ''$1''",
        "virus-scanfailed": "വൈറസ് സ്കാനിങ് പരാജയപ്പെട്ടു (code $1)",
        "externaldberror": "ഒന്നുകിൽ ഡേറ്റാബേസ് സാധൂകരണത്തിൽ പ്രശ്നം ഉണ്ടായിരുന്നു അല്ലെങ്കിൽ നവീകരിക്കുവാൻ താങ്കളുടെ ബാഹ്യ അംഗത്വം താങ്കളെ അനുവദിക്കുന്നില്ല.",
        "login": "പ്രവേശിക്കുക",
        "nav-login-createaccount": "പ്രവേശിക്കുക / അംഗത്വമെടുക്കുക",
-       "loginprompt": "{{SITENAME}} സംരംഭത്തിൽ ലോഗിൻ ചെയ്യാൻ താങ്കൾ കുക്കികൾ (Cookies) സജ്ജമാക്കിയിരിക്കണം.",
        "userlogin": "പ്രവേശിക്കുക / അംഗത്വമെടുക്കുക",
        "userloginnocreate": "പ്രവേശിക്കുക",
        "logout": "ലോഗൗട്ട്",
        "userlogin-resetlink": "താങ്കളുടെ ലോഗിൻ വിവരങ്ങൾ മറന്നു പോയോ?",
        "userlogin-resetpassword-link": "താങ്കൾ രഹസ്യവാക്ക് മറന്നോ?",
        "userlogin-helplink2": "പ്രവേശിക്കാൻ സഹായമാവശ്യമെങ്കിൽ",
-       "userlogin-loggedin": "താങ്കൾ ഇപ്പോൾ തന്നെ {{GENDER:$1|$1}} ആയി പ്രവേശിച്ചിരിക്കുന്നു.\nതാഴെ ഉള്ള ഫോം ഉപയോഗിച്ച് മറ്റൊരു ഉപയോക്താവായി പ്രവേശിക്കാവുന്നതാണ്.",
-       "userlogin-createanother": "മറ്റൊരു അംഗത്വമെടുക്കുക",
        "createacct-emailrequired": "ഇമെയിൽ വിലാസം",
        "createacct-emailoptional": "ഇമെയിൽ വിലാസം (നിർബന്ധമില്ല)",
        "createacct-email-ph": "താങ്കളുടെ ഇമെയിൽ വിലാസം നൽകുക",
        "preview": "എങ്ങനെയുണ്ടെന്നു കാണുക",
        "showpreview": "എങ്ങനെയുണ്ടെന്നു കാണുക",
        "showdiff": "മാറ്റങ്ങൾ കാണിക്കുക",
-       "anoneditwarning": "'''മുന്നറിയിപ്പ്:''' താങ്കൾ ലോഗിൻ ചെയ്തിട്ടില്ല. താങ്കളുടെ ഐ.പി. വിലാസം താളിന്റെ തിരുത്തൽ ചരിത്രത്തിൽ ചേർക്കുന്നതാണ്.",
+       "blankarticle": "<strong>മുന്നറിയിപ്പ്:</strong> താങ്കൾ സൃഷ്ടിക്കുന്ന താൾ ശൂന്യമാണ്.\n\"{{int:savearticle}}\" ഒന്നുകൂടി അമർത്തിയാൽ, ഉള്ളടക്കമൊന്നുമില്ലാതെ താൾ സൃഷ്ടിക്കപ്പെടും.",
+       "anoneditwarning": "<strong>മുന്നറിയിപ്പ്:</strong> താങ്കൾ ലോഗിൻ ചെയ്തിട്ടില്ല. താങ്കൾ തിരുത്തുകളെന്തെങ്കിലും ചെയ്യുകയാണെങ്കിൽ താങ്കളുടെ ഐ.പി. വിലാസം എല്ലാവർക്കും ലഭ്യമായിരിക്കും. താങ്കൾ <strong>[$1 ലോഗിൻ ചെയ്യുകയോ]</strong>  <strong>[$2 അംഗത്വമെടുക്കുകയോ]</strong> ചെയ്യുന്നതുവഴി മറ്റ് ഗുണങ്ങളോടൊപ്പം താങ്കളുടെ തിരുത്തുകൾ ഉപയോക്തൃനാമത്തിലാവും അറിയപ്പെടുക.",
        "anonpreviewwarning": "''താങ്കൾ ലോഗിൻ ചെയ്തിട്ടില്ല. സേവ് ചെയ്യുമ്പോൾ താളിന്റെ തിരുത്തൽ ചരിത്രത്തിൽ താങ്കളുടെ ഐ.പി. വിലാസം ചേർത്തു സൂക്ഷിക്കപ്പെടും.''",
        "missingsummary": "'''ഓർമ്മക്കുറിപ്പ്:''' താങ്കൾ തിരുത്തലിന്റെ ചുരുക്കരൂപം നൽകിയിട്ടില്ല. ''സേവ് ചെയ്യുക'' ബട്ടൺ ഒരുവട്ടം കൂടി അമർത്തിയാൽ താങ്കൾ വരുത്തിയ മാറ്റം കാത്തുസൂക്ഷിക്കുന്നതാണ്.",
        "missingcommenttext": "താങ്കളുടെ അഭിപ്രായം ദയവായി താഴെ രേഖപ്പെടുത്തുക.",
        "parser-template-recursion-depth-warning": "ഫലകത്തിന്റെ പുനരാവർത്തന ആഴത്തിന്റെ പരിധി കഴിഞ്ഞിരിക്കുന്നു ($1)",
        "language-converter-depth-warning": "ഭാഷ മാറ്റൽ ഉപകരണത്തിന്റെ ആഴത്തിന്റെ പരിധി കവിഞ്ഞിരിക്കുന്നു ($1)",
        "node-count-exceeded-category": "നോഡ്-എണ്ണം അധികരിച്ച താളുകൾ",
-       "node-count-exceeded-category-desc": "à´¨àµ\8bà´¡àµ\8d-à´\8eà´£àµ\8dà´£à´\82 à´\85ധിà´\95à´°à´¿à´\9aàµ\8dà´\9a à´¤à´¾à´³àµ\81à´\95ൾà´\95àµ\8dà´\95àµ\81à´³àµ\8dà´³ à´µàµ¼à´\97àµ\8dà´\97à´\82.",
-       "node-count-exceeded-warning": "താൾ നോഡ്-എണ്ണം അധികരിച്ചിരിക്കുന്നു",
+       "node-count-exceeded-category-desc": "താളിൽ à´¨àµ\8bà´¡àµ\8d-à´\8eà´£àµ\8dà´£à´\82 à´\85ധിà´\95à´°à´¿à´\9aàµ\8dà´\9aà´¿à´°à´¿à´\95àµ\8dà´\95àµ\81à´¨àµ\8dà´¨àµ\81.",
+       "node-count-exceeded-warning": "താളിൽ നോഡ്-എണ്ണം അധികരിച്ചിരിക്കുന്നു",
        "expansion-depth-exceeded-category": "വികസന ആഴം അധികരിച്ച താളുകൾ",
-       "expansion-depth-exceeded-category-desc": "വിà´\95സന à´\86à´´à´\82 à´\85ധിà´\95à´°à´¿à´\9aàµ\8dà´\9a à´¤à´¾à´³àµ\81à´\95ൾà´\95àµ\8dà´\95àµ\81à´³àµ\8dà´³ à´µàµ¼à´\97àµ\8dà´\97à´\82.",
+       "expansion-depth-exceeded-category-desc": "താളിലàµ\86 à´µà´¿à´\95സന à´\86à´´à´\82 à´\85ധിà´\95à´°à´¿à´\9aàµ\8dà´\9aà´¿à´°à´¿à´\95àµ\8dà´\95àµ\81à´¨àµ\8dà´¨àµ\81.",
        "expansion-depth-exceeded-warning": "താളിന്റെ വികസന ആഴം അധികരിച്ചിരിക്കുന്നു",
        "parser-unstrip-loop-warning": "അൺസ്ട്രിപ്പ് (Unstrip) പാഴ്സർ ഫങ്ഷനിൽ കുരുക്ക് കണ്ടെത്തി",
        "parser-unstrip-recursion-limit": "അൺസ്ട്രിപ്പ് (Unstrip) പാഴ്സർ ഫങ്ഷന്റെ പുനരാവർത്തന പരിധി അധികരിച്ചിരിക്കുന്നു ($1)",
        "rev-deleted-event": "(പ്രവൃത്തിയുടെ രേഖ ഒഴിവാക്കിയിരിക്കുന്നു)",
        "rev-deleted-user-contribs": "[ഉപയോക്തൃനാമം അഥവാ ഐ.പി. വിലാസം ഒഴിവാക്കപ്പെട്ടിരിക്കുന്നു - തിരുത്തൽ സേവനങ്ങളിൽ നിന്നും മറച്ചിരിക്കുന്നു]",
        "rev-deleted-text-permission": "താളിന്റെ ഈ നാൾപ്പതിപ്പ് '''മായ്ച്ചിരിക്കുന്നു'''.\nകൂടുതൽ വിവരങ്ങൾ [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} മായ്ക്കൽ രേഖയിൽ] കാണാവുന്നതാണ്.",
+       "rev-suppressed-text-permission": "താളിന്റെ ഈ സംശോധനം <strong>ഒതുക്കിയിരിക്കുന്നു</strong>.\nകൂടുതൽ വിവരങ്ങൾ [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ഒതുക്കൽ രേഖയിൽ] ഉണ്ട്.",
        "rev-deleted-text-unhide": "താളിന്റെ ഈ നാൾപ്പതിപ്പ് '''മായ്ച്ചിരിക്കുന്നു'''.\nകൂടുതൽ വിവരങ്ങൾ [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} മായ്ക്കൽ രേഖയിൽ] ഉണ്ടായിരിക്കും.\nതാങ്കളാഗ്രഹിക്കുന്നെങ്കിൽ ഇപ്പോഴും [$1 ഈ നാൾപ്പതിപ്പ് കാണാവുന്നതാണ്].",
        "rev-suppressed-text-unhide": "താളിന്റെ ഈ സംശോധനം '''ഒതുക്കപ്പെട്ടിരിക്കുന്നു'''.\nകൂടുതൽ വിവരങ്ങൾ [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ഒതുക്കൽ രേഖയിൽ] ഉണ്ടാകും.\nതാങ്കൾക്ക് ആവശ്യമെങ്കിൽ ഇപ്പോഴും [$1 ഈ സംശോധനം കാണാൻ] കഴിയുന്നതാണ്.",
        "rev-deleted-text-view": "ഈ താളിന്റെ പതിപ്പുകൾ '''മായ്ച്ചിരിക്കുന്നു'''.\n\nതാങ്കൾക്ക് അവ കാണാവുന്നതാണ്;  കൂടുതൽ വിവരങ്ങൾ [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} മായ്ക്കൽ രേഖയിൽ] ഉണ്ട്.",
        "revdelete-text-text": "മായ്ക്കപ്പെട്ട നാൾപ്പതിപ്പുകൾ താളിന്റെ നാൾവഴിയിൽ കാണാവുന്നതായിരിക്കുമെങ്കിലും, അവയുടെ ഉള്ളടക്കത്തിന്റെ ചില ഭാഗങ്ങൾ പൊതുജനങ്ങൾക്ക് ലഭ്യമായിരിക്കണമെന്നില്ല.",
        "revdelete-text-file": "പ്രമാണത്തിന്റെ മായ്ക്കപ്പെട്ട പതിപ്പുകൾ താളിന്റെ നാൾവഴിയിൽ കാണാവുന്നതായിരിക്കുമെങ്കിലും, അവയുടെ ഉള്ളടക്കത്തിന്റെ ചില ഭാഗങ്ങൾ പൊതുജനങ്ങൾക്ക് ലഭ്യമായിരിക്കണമെന്നില്ല.",
        "logdelete-text": "മായ്ക്കപ്പെട്ട പ്രവൃത്തികൾ പ്രവർത്തന രേഖകളിൽ കാണാവുന്നതായിരിക്കുമെങ്കിലും, അവയുടെ ഉള്ളടക്കത്തിന്റെ ചില ഭാഗങ്ങൾ പൊതുജനങ്ങൾക്ക് ലഭ്യമായിരിക്കണമെന്നില്ല.",
-       "revdelete-text-others": "{{SITENAME}} സംരംഭത്തിലെ മറ്റ് കാര്യനിർവ്വാഹകർക്ക് മറയ്ക്കപ്പെട്ട ഉള്ളടക്കം ഇപ്പോഴും എടുക്കാവുന്നതും ആവശ്യമെങ്കിൽ ഇതേ സമ്പർക്കമുഖം ഉപയോഗിച്ച് പുനഃസ്ഥാപിക്കാനോ അല്ലെങ്കിൽ കൂടുതൽ നിബന്ധനകൾ ചേർക്കാനോ കഴിയുന്നതുമാണ്.",
+       "revdelete-text-others": "കൂടുതൽ നിബന്ധനകൾ ചേർക്കാത്ത പക്ഷം, മറ്റ് കാര്യനിർവ്വാഹകർക്ക് മറയ്ക്കപ്പെട്ട ഉള്ളടക്കം എടുക്കാനും പുനഃസ്ഥാപിക്കാനും കഴിയുന്നതാണ്.",
        "revdelete-confirm": "ഇതിന്റെ അനന്തരഫലങ്ങളെക്കുറിച്ചറിയാമെന്നും, [[{{MediaWiki:Policy-url}}|നയങ്ങൾ]] പാലിച്ചാണ് താങ്കളിത് ചെയ്യുന്നതെന്നും ഉറപ്പാക്കുക.",
        "revdelete-suppress-text": "താഴെ പറയുന്ന സാഹചര്യങ്ങളിൽ '''മാത്രമേ''' ഒതുക്കൽ ഉപയോഗിക്കാവൂ:\n* അപകീർത്തികരമായ വിവരങ്ങൾ അടങ്ങിയവ\n* അനുയോജ്യമല്ലാത്ത വ്യക്തി വിവരങ്ങൾ\n*: ''വീട്ടുവിലാസങ്ങൾ, ടെലിഫോൺ നമ്പറുകൾ, സാമൂഹിക സുരക്ഷാ നമ്പരുകൾ, തുടങ്ങിയവ.''",
        "revdelete-legend": "നാൾപ്പതിപ്പിന്റെ ദർശനീയത സജ്ജീകരിക്കുക",
        "mergehistory-into": "ലക്ഷ്യതാൾ:",
        "mergehistory-list": "സം‌യോജിപ്പിക്കാവുന്ന തിരുത്തൽ നാൾവഴി",
        "mergehistory-merge": "[[:$1]]ന്റെ താഴെ കാണിച്ചിരിക്കുന്ന പതിപ്പുകൾ [[:$2]] ലേക്കു സം‌യോജിപ്പിക്കാവുന്നതാണ്‌‍. റേഡിയോ ബട്ടൺ കോളം ഉപയോഗിച്ച് സം‌യോജിപ്പിക്കാനുള്ള പതിപ്പുകളുടെ സമീപത്തുള്ള സമയം തിരഞ്ഞെടുക്കുക. താങ്കൾ തിരഞ്ഞെടുക്കുന്ന സമയത്തോ അതിനു മുൻപോ സൃഷ്ടിക്കപ്പെട്ട പതിപ്പുകൾ തിരഞ്ഞെടുക്കുക. നാവിഗേഷണൽ കണ്ണികൾ ഉപയോഗിക്കുന്നതു ഈ കോളത്തെ പുനഃക്രമീകരിക്കും.",
-       "mergehistory-go": "à´¸à´\82â\80\8cà´¯àµ\8bà´\9cà´¿à´ªàµ\8dപിà´\95àµ\8dà´\95ാവàµ\81à´¨àµ\8dà´¨ à´¤à´¿à´°àµ\81à´¤àµ\8dതലàµ\81à´\95ൾ à´\95à´¾à´\9fàµ\8dà´\9fàµ\81à´\95",
+       "mergehistory-go": "സം‌യോജിപ്പിക്കാവുന്ന തിരുത്തുകൾ കാട്ടുക",
        "mergehistory-submit": "പതിപ്പുകൾ സം‌യോജിപ്പിക്കുക",
        "mergehistory-empty": "സം‌യോജിപ്പിക്കാവുന്ന പതിപ്പുകളൊന്നും ഇല്ല.",
        "mergehistory-success": "[[:$1]]-ന്റെ {{PLURAL:$3|പതിപ്പ്|പതിപ്പുകൾ}} [[:$2]]-ലേക്കു വിജയകരമായി സം‌യോജിപ്പിച്ചിരിക്കുന്നു.",
        "searchprofile-advanced-tooltip": "തിരഞ്ഞെടുത്ത നാമമേഖലകളിൽ തിരച്ചിൽ നടത്തുവാൻ",
        "search-result-size": "$1 ({{PLURAL:$2|ഒരു വാക്ക്|$2 വാക്കുകൾ}})",
        "search-result-category-size": "{{PLURAL:$1|ഒരു അംഗം|$1 അംഗങ്ങൾ}} ({{PLURAL:$2|ഒരു ഉപവർഗ്ഗം|$2 ഉപവർഗ്ഗങ്ങൾ}}, {{PLURAL:$3|ഒരു പ്രമാണം|$3 പ്രമാണങ്ങൾ}})",
-       "search-result-score": "സാംഗത്യം: $1%",
        "search-redirect": "(തിരിച്ചുവിടൽ താൾ $1)",
        "search-section": "(വിഭാഗം $1)",
        "search-file-match": "(പ്രമാണ ഉള്ളടക്കവുമായി ഒത്തുപോകുന്നുണ്ട്)",
        "preferences": "ക്രമീകരണങ്ങൾ",
        "mypreferences": "ക്രമീകരണങ്ങൾ",
        "prefs-edits": "ആകെ തിരുത്തുകൾ:",
-       "prefsnologintext2": "താങ്കളുടെ ഉപയോക്തൃക്രമീകരണങ്ങൾ സജ്ജീകരിക്കാൻ ദയവായി $1.",
+       "prefsnologintext2": "താങ്കളുടെ ഉപയോക്തൃക്രമീകരണങ്ങൾ സജ്ജീകരിക്കാൻ ദയവായി പ്രവേശിക്കുക.",
        "prefs-skin": "ദൃശ്യരൂപം",
        "skin-preview": "എങ്ങനെയുണ്ടെന്നു കാണുക",
        "datedefault": "ക്രമീകരണങ്ങൾ വേണ്ട",
        "prefs-watchlist-days": "ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിൽ പ്രദർശിപ്പിക്കേണ്ട പരമാവധി ദിവസങ്ങൾ:",
        "prefs-watchlist-days-max": "പരമാവധി {{PLURAL:$1|ഒരു ദിവസം|$1 ദിവസങ്ങൾ}}",
        "prefs-watchlist-edits": "ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയുടെ വികസിത രൂപത്തിൽ പ്രദർശിപ്പിക്കേണ്ട പരമാവധി മാറ്റങ്ങൾ:",
-       "prefs-watchlist-edits-max": "പരമാവധി 1000 à´¤à´¿à´°àµ\81à´¤àµ\8dതലàµ\81à´\95ൾ",
+       "prefs-watchlist-edits-max": "പരമാവധി 1000 തിരുത്തുകൾ",
        "prefs-watchlist-token": "ശ്രദ്ധിക്കുന്നവയുടെ പട്ടികയ്ക്കുള്ള അടയാളപദം:",
        "prefs-misc": "പലവക",
        "prefs-resetpass": "രഹസ്യവാക്ക് മാറ്റുക",
        "right-deletedtext": "മായ്ക്കപ്പെട്ട എഴുത്തും താളിന്റെ മായ്ക്കപ്പെട്ട പതിപ്പുകൾ തമ്മിലുള്ള വ്യത്യാസവും കാണുക",
        "right-browsearchive": "നീക്കം ചെയ്യപ്പെട്ട താളുകളിൽ തിരയുക",
        "right-undelete": "താൾ പുനഃസ്ഥാപിക്കുക",
-       "right-suppressrevision": "കാര്യനിർവാഹകരിൽ നിന്നും മറയ്ക്കപ്പെട്ട നാൾപ്പതിപ്പുകൾ സംശോധനം ചെയ്യുക, പുനഃസ്ഥാപിക്കുക",
+       "right-suppressrevision": "മറ്റുപയോക്താക്കൾക്കായി താളുകളുടെ നാൾപ്പതിപ്പുകൾ കാണാൻ കഴിയുന്നതാക്കുക, മറയ്ക്കുക, മറയ്ക്കൽ മാാറ്റുക",
+       "right-viewsuppressed": "മറ്റുപയോക്താക്കളിൽ നിന്നും മറയ്ക്കപ്പെട്ട നാൾപ്പതിപ്പുകൾ കാണുക",
        "right-suppressionlog": "പരസ്യമല്ലാത്ത രേഖകൾ കാണുക",
        "right-block": "മറ്റുള്ള ഉപയോക്താക്കളെ മാറ്റിയെഴുതുന്നതിൽനിന്നും തടയുക",
        "right-blockemail": "ഇമെയിൽ അയക്കുന്നതിൽ നിന്നും ഉപയോക്താവിനെ തടയുക",
        "right-noratelimit": "പ്രവർത്തനങ്ങൾക്ക് പരിധികൾ ബാധകമല്ല",
        "right-import": "മറ്റുള്ള വിക്കികളിൽ നിന്നും താളുകൾ ഇറക്കുമതി ചെയ്യുക",
        "right-importupload": "അപ്‌‌ലോഡ് ചെയ്ത പ്രമാണത്തിൽ നിന്നും താളുകൾ ഇറക്കുമതി ചെയ്യുക",
-       "right-patrol": "മറàµ\8dà´±àµ\81à´³àµ\8dളവരàµ\81à´\9fàµ\86 à´¤à´¿à´°àµ\81à´¤àµ\8dതലàµ\81à´\95ൾ à´±àµ\8bà´¨àµ\8dà´¤àµ\81à´\9aàµ\81à´±àµ\8dറിയതായി à´\85à´\9fയാളപàµ\8dà´ªàµ\86à´\9fàµ\81à´¤àµ\8dà´¤àµ\81à´\95",
-       "right-autopatrol": "à´¸àµ\8dവനàµ\8dà´¤à´\82 à´¤à´¿à´°àµ\81à´¤àµ\8dതലàµ\81à´\95ൾ à´±àµ\8bà´¨àµ\8dà´¤àµ\81 à´\9aàµ\81à´±àµ\8dറിയതായി à´\85à´\9fയാളപàµ\8dà´ªàµ\86à´\9fàµ\81à´¤àµ\8dà´¤àµ\81à´\95",
+       "right-patrol": "മറ്റുള്ളവരുടെ തിരുത്തുകൾ റോന്തുചുറ്റിയതായി അടയാളപ്പെടുത്തുക",
+       "right-autopatrol": "സ്വന്തം തിരുത്തുകൾ റോന്തു ചുറ്റിയതായി അടയാളപ്പെടുത്തുക",
        "right-patrolmarks": "പുതിയ മാറ്റങ്ങളിലെ റോന്തുചുറ്റൽ രേഖകൾ പരിശോധിക്കുക",
        "right-unwatchedpages": "ശ്രദ്ധിക്കാത്ത താളുകളുടെ പട്ടിക കാണുക",
        "right-mergehistory": "താളുകളുടെ നാൾവഴികൾ ലയിപ്പിക്കുക",
        "recentchanges-label-plusminus": "താളിന്റെ വലിപ്പം ഇത്രയും ബൈറ്റുകൾ മാറിയിരിക്കുന്നു",
        "recentchanges-legend-heading": "'''സൂചന:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|പുതിയ താളുകളുടെ പട്ടികയും]] കാണുക)",
-       "rcnotefrom": "<strong>$2</strong> മുതലുള്ള മാറ്റങ്ങൾ (<strong>$1</strong> എണ്ണം വരെ കാണാം).",
+       "rcnotefrom": "<strong>$3, $4</strong> മുതലുള്ള {{PLURAL:$5|മാറ്റം|മാറ്റങ്ങൾ}} ആണ് താഴെയുള്ളത്  (<strong>$1</strong> എണ്ണം വരെ കൊടുക്കുന്നതാണ്).",
        "rclistfrom": "$3 $2 മുതലുള്ള മാറ്റങ്ങൾ പ്രദർശിപ്പിക്കുക",
        "rcshowhideminor": "ചെറുതിരുത്തലുകൾ $1",
        "rcshowhideminor-show": "പ്രദർശിപ്പിക്കുക",
        "rcshowhidepatr": "റോന്തു ചുറ്റിയ മാറ്റങ്ങൾ $1",
        "rcshowhidepatr-show": "പ്രദർശിപ്പിക്കുക",
        "rcshowhidepatr-hide": "മറയ്ക്കുക",
-       "rcshowhidemine": "à´\8eà´¨àµ\8dà´±àµ\86 à´¤à´¿à´°àµ\81à´¤àµ\8dതലàµ\81à´\95ൾ $1",
+       "rcshowhidemine": "എന്റെ തിരുത്തുകൾ $1",
        "rcshowhidemine-show": "പ്രദർശിപ്പിക്കുക",
        "rcshowhidemine-hide": "മറയ്ക്കുക",
        "rclinks": "കഴിഞ്ഞ $2 ദിവസങ്ങൾക്കുള്ളിലുണ്ടായ $1 മാറ്റങ്ങൾ പ്രദർശിപ്പിക്കുക<br />$3",
        "uploadwarning": "അപ്‌ലോഡ് മുന്നറിയിപ്പ്",
        "uploadwarning-text": "ദയവായി താഴെയുള്ള പ്രമാണ വിവരണങ്ങൾ പുതുക്കി വീണ്ടും ശ്രമിക്കുക.",
        "savefile": "പ്രമാണം കാത്ത് സൂക്ഷിക്കുക",
-       "uploadedimage": "\"[[$1]]\" അപ്‌ലോഡ് ചെയ്തു.",
-       "overwroteimage": "\"[[$1]]\" എന്ന പ്രമാണത്തിന്റെ പുതിയ പതിപ്പ് അപ്‌ലോഡ് ചെയ്തിരിക്കുന്നു",
        "uploaddisabled": "അപ്‌ലോഡുകൾ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു.",
        "copyuploaddisabled": "യൂ.ആർ.എൽ. വഴിയുള്ള അപ്‌‌ലോഡ് നിർജ്ജീവമാക്കിയിരിക്കുന്നു.",
        "uploaddisabledtext": "പ്രമാണം അപ്‌ലോഡ് ചെയ്യുന്നതു സാദ്ധ്യമല്ലാതാക്കിയിരിക്കുന്നു.",
        "license": "പകർപ്പവകാശ വിവരങ്ങൾ:",
        "license-header": "അനുമതി",
        "nolicense": "ഒന്നും തിരഞ്ഞെടുത്തിട്ടില്ല",
+       "licenses-edit": "ഉപയോഗാനുമതി ഐച്ഛികങ്ങൾ തിരുത്തുക",
        "license-nopreview": "(പ്രിവ്യൂ ലഭ്യമല്ല)",
-       "upload_source_url": "(സാധുവായ, ആർക്കും ഉപയോഗിക്കാവുന്ന യൂ.ആർ.എൽ.)",
-       "upload_source_file": "(താങ്കളുടെ കമ്പ്യൂട്ടറിലുള്ള ഒരു പ്രമാണം)",
+       "upload_source_url": "(താങ്കൾ തിരഞ്ഞെടുത്ത പ്രമാണം സാധുവായ, ആർക്കും ഉപയോഗിക്കാവുന്ന യൂ.ആർ.എലിൽ നിന്നാണ്)",
+       "upload_source_file": "(താങ്കൾ തിരഞ്ഞെടുത്തത് താങ്കളുടെ കമ്പ്യൂട്ടറിലുള്ള പ്രമാണമാണ്)",
+       "listfiles-delete": "മായ്ക്കുക",
        "listfiles-summary": "അപ്‌ലോഡ് ചെയ്തിട്ടുള്ള എല്ലാ പ്രമാണങ്ങളും ഈ പ്രത്യേക താളിൽ കാണാവുന്നതാണ്.",
        "listfiles_search_for": "മീഡിയ പ്രമാണം തിരയുക:",
        "imgfile": "പ്രമാണം",
        "listfiles_count": "പതിപ്പുകൾ",
        "listfiles-show-all": "ചിത്രത്തിന്റെ പഴയ പതിപ്പുകളും ഉൾപ്പെടുത്തുക",
        "listfiles-latestversion": "ഇപ്പോഴത്തെ പതിപ്പ്",
-       "listfiles-latestversion-yes": "ശരി",
-       "listfiles-latestversion-no": "à´µàµ\87à´£àµ\8dà´\9f",
+       "listfiles-latestversion-yes": "à´\85à´¤àµ\86",
+       "listfiles-latestversion-no": "à´\85à´²àµ\8dà´²",
        "file-anchor-link": "പ്രമാണം",
        "filehist": "പ്രമാണ നാൾവഴി",
        "filehist-help": "ഏതെങ്കിലും തീയതി/സമയ കണ്ണിയിൽ ഞെക്കിയാൽ പ്രസ്തുതസമയത്ത് ഈ പ്രമാണം എങ്ങനെയായിരുന്നു എന്നു കാണാം.",
        "randomincategory": "വർഗ്ഗത്തിൽ നിന്ന് ക്രമരഹിതമായി എടുക്കുന്ന താൾ",
        "randomincategory-invalidcategory": "\"$1\" സാധുതയുള്ള വർഗ്ഗത്തിന്റെ പേരല്ല.",
        "randomincategory-nopages": "[[:Category:$1|വർഗ്ഗം:$1]] എന്നതിൽ താളുകളൊന്നുമില്ല.",
-       "randomincategory-selectcategory": "ഈ വർഗ്ഗത്തിൽ നിന്നും ഏതെങ്കിലും താൾ എടുക്കുക: $1 $2.",
-       "randomincategory-selectcategory-submit": "പോകൂ",
+       "randomincategory-category": "വർഗ്ഗം:",
+       "randomincategory-legend": "വർഗ്ഗത്തിൽ നിന്ന് ക്രമരഹിതമായി എടുക്കുന്ന താൾ",
        "randomredirect": "ക്രമരഹിതമായ തിരിച്ചുവിടൽ",
        "randomredirect-nopages": "\"$1\" എന്ന നാമമേഖലയിൽ തിരിച്ചുവിടൽ താളുകളൊന്നുമില്ല.",
        "statistics": "സ്ഥിതിവിവരക്കണക്കുകൾ",
        "statistics-pages": "താളുകൾ",
        "statistics-pages-desc": "സം‌വാദത്താളുകൾ, തിരിച്ചുവിടലുകൾ തുടങ്ങിയവയടക്കം വിക്കിയിലെ എല്ലാ താളുകളും.",
        "statistics-files": "അപ്‌ലോഡ് ചെയ്തിട്ടുള്ള പ്രമാണങ്ങൾ",
-       "statistics-edits": "{{SITENAME}} à´¸à´\82â\80\8cà´°à´\82à´­à´¤àµ\8dതിനàµ\8dà´±àµ\86 à´¤àµ\81à´\9fà´\95àµ\8dà´\95à´\82 à´®àµ\81തലàµ\81à´³àµ\8dà´³ à´¤à´¿à´°àµ\81à´¤àµ\8dതലàµ\81à´\95ൾ",
-       "statistics-edits-average": "à´\92à´°àµ\81 à´¤à´¾à´³à´¿à´²àµ\86 à´¶à´°à´¾à´¶à´°à´¿ à´¤à´¿à´°àµ\81à´¤àµ\8dതലàµ\81à´\95ൾ",
+       "statistics-edits": "{{SITENAME}} സം‌രംഭത്തിന്റെ തുടക്കം മുതലുള്ള തിരുത്തുകൾ",
+       "statistics-edits-average": "ഒരു താളിലെ ശരാശരി തിരുത്തുകൾ",
        "statistics-views-total": "ആകെ സന്ദർശനങ്ങൾ",
        "statistics-views-total-desc": "നിലവില്ലാത്ത താളുകളിലും പ്രത്യേക താളുകളിലും ഉള്ള എടുത്തുനോക്കലുകൾ ഉൾപ്പെടുത്തിയിട്ടില്ല",
        "statistics-views-peredit": "ഓരോ തിരുത്തലിലും ഉള്ള എടുത്തുനോട്ടങ്ങൾ",
        "wantedpages-badtitle": "ഫലങ്ങളുടെ ഗണത്തിൽ അസാധുവായ തലക്കെട്ട്: $1",
        "wantedfiles": "ആവശ്യമുള്ള പ്രമാണങ്ങൾ",
        "wantedfiletext-cat": "താഴെക്കൊടുത്തിരിക്കുന്ന പ്രമാണങ്ങൾ ഉപയോഗിച്ചിട്ടുണ്ടെങ്കിലും നിലവിലില്ല. ബാഹ്യ റെപ്പോസിറ്ററികളിൽ നിന്നുള്ള പ്രമാണങ്ങൾ നിലവിലുണ്ടെങ്കിലും പട്ടികയിൽ ഉൾപ്പെട്ടിട്ടുണ്ടാവാം. അത്തരത്തിൽ തെറ്റായി ഉൾപ്പെടുത്തിയിരിക്കുന്നവ <del>വെട്ടിക്കളയുക</del>. കൂടുതലായി, നിലവിലില്ലാത്ത പ്രമാണങ്ങൾ ഉൾപ്പെടുത്തിയിട്ടുള്ള താളുകൾ കാണാൻ [[:$1]] സന്ദർശിക്കുക.",
+       "wantedfiletext-cat-noforeign": "താഴെക്കൊടുക്കുന്ന പ്രമാണങ്ങൾ നിലവിലില്ലെങ്കിലും ഉപയോഗിച്ചിട്ടുണ്ട്. കൂടുതലായി നിലവിലില്ലാത്ത എന്നാൽ ഉപയോഗിച്ചിട്ടുള്ള പ്രമാണങ്ങൾ [[:$1]] എന്ന താളിൽ കൊടുത്തിട്ടുണ്ട്.",
        "wantedfiletext-nocat": "താഴെക്കൊടുത്തിരിക്കുന്ന പ്രമാണങ്ങൾ ഉപയോഗിച്ചിട്ടുണ്ടെങ്കിലും നിലവിലില്ല. ബാഹ്യ റെപ്പോസിറ്ററികളിൽ നിന്നുള്ള പ്രമാണങ്ങൾ നിലവിലുണ്ടെങ്കിലും പട്ടികയിൽ ഉൾപ്പെട്ടിട്ടുണ്ടാവാം. അത്തരത്തിൽ തെറ്റായി ഉൾപ്പെടുത്തിയിരിക്കുന്നവ <del>വെട്ടിക്കളയുക</del>.",
+       "wantedfiletext-nocat-noforeign": "താഴെക്കൊടുത്തിരിക്കുന്ന പ്രമാണങ്ങൾ ഉപയോഗിച്ചിട്ടുണ്ടെങ്കിലും നിലവിലില്ലാത്തവയാണ്.",
        "wantedtemplates": "അവശ്യ ഫലകങ്ങൾ",
        "mostlinked": "ഏറ്റവുമധികം കണ്ണികളാൽ ചേർത്തിരിക്കുന്ന താളുകൾ",
        "mostlinkedcategories": "ഏറ്റവുമധികം താളുകൾ ചേർത്തിട്ടുള്ള വർഗ്ഗങ്ങൾ",
        "protectedtitles-summary": "സൃഷ്ടിക്കുന്നതിൽ നിന്നും സംരക്ഷിക്കപ്പെട്ടിട്ടുള്ള താളുകളുടെ പട്ടിക ഇവിടെ കാണാം. സംരക്ഷിക്കപ്പെട്ടിട്ടുള്ളതും എന്നാൽ നിലവിലുള്ളതുമായ താളുകൾക്കായി [[{{#special:ProtectedPages}}|{{int:protectedpages}}]] കാണുക.",
        "protectedtitlesempty": "ഈ ചരങ്ങൾ ഉപയോഗിച്ചു തലക്കെട്ടുകൾ ഒന്നും തന്നെ സം‌രക്ഷിക്കപ്പെട്ടിട്ടില്ല.",
        "listusers": "ഉപയോക്താക്കളുടെ പട്ടിക",
-       "listusers-editsonly": "തിരàµ\81à´¤àµ\8dതലàµ\81à´\95ൾ à´\9aàµ\86à´¯àµ\8dതിà´\9fàµ\8dà´\9fàµ\81à´³àµ\8dà´³ à´\89പയàµ\8bà´\95àµ\8dതാà´\95àµ\8dà´\95à´³àµ\86 à´®à´¾à´¤àµ\8dà´°à´\82 à´\95ാണിà´\95àµ\8dà´\95àµ\81à´\95",
+       "listusers-editsonly": "തിരുത്തുകൾ ചെയ്തിട്ടുള്ള ഉപയോക്താക്കളെ മാത്രം കാണിക്കുക",
        "listusers-creationsort": "സൃഷ്ടിക്കപ്പെട്ട തീയതി അനുസരിച്ച് ക്രമീകരിക്കുക",
        "listusers-desc": "അവരോഹണക്രമത്തിൽ ആക്കുക",
        "usereditcount": "{{PLURAL:$1|ഒരു തിരുത്തൽ|$1 തിരുത്തലുകൾ}}",
        "post-expand-template-inclusion-category-desc": "എല്ലാ ഫലകങ്ങളും വികസിപ്പിച്ചു കഴിയുമ്പോൾ, താളിന്റെ വലിപ്പം <code>$wgMaxArticleSize</code> എന്നതിലും കൂടുതലാവുമെന്നതിനാൽ, ചില ഫലകങ്ങൾ വികസിപ്പിച്ചിരുന്നില്ല.",
        "post-expand-template-argument-category-desc": "ഫലകത്തിലേയ്ക്കുള്ള ചരം വികസിപ്പിച്ച ശേഷം (<code>{{{പന}}}</code> പോലെയുള്ള മൂന്ന് കോഷ്ഠകങ്ങളിലെ എഴുത്ത്), താളിന്റെ വലിപ്പം <code>$wgMaxArticleSize</code> എന്നതിലും കൂടുതലായി.",
        "expensive-parserfunction-category-desc": "നിരവധി വ്യയമേറിയ പാഴ്സർ ഫങ്ഷനുകൾ ( #എങ്കിൽ പോലെയുള്ളവ) താളിൽ ഉൾപ്പെടുത്തിയിരിക്കുന്നു. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit] കാണുക.",
-       "broken-file-category-desc": "താളിൽ à´¨à´¿à´²à´µà´¿à´²à´¿à´²àµ\8dലാതàµ\8dà´¤ à´ªàµ\8dരമാണതàµ\8dതിലàµ\8bà´\9fàµ\8dà´\9fàµ\8d à´\95à´£àµ\8dണി à´\9aàµ\87ർതàµ\8dതിà´\9fàµ\8dà´\9fàµ\81à´£àµ\8dà´\9fàµ\86à´\99àµ\8dà´\95ിൽ à´µàµ¼à´\97àµ\8dà´\97à´\82 à´\9aàµ\87ർà´\95àµ\8dà´\95à´ªàµ\8dà´ªàµ\86à´\9fàµ\81à´\82.",
+       "broken-file-category-desc": "താളിൽ à´¨à´¿à´²à´µà´¿à´²à´¿à´²àµ\8dലാതàµ\8dà´¤ à´ªàµ\8dരമാണതàµ\8dതിലàµ\8bà´\9fàµ\8dà´\9fàµ\8d à´\95à´£àµ\8dണി à´\9aàµ\87ർതàµ\8dതിà´\9fàµ\8dà´\9fàµ\81à´£àµ\8dà´\9fàµ\8d (നിലവിലിലàµ\8dലാതàµ\8dà´¤ à´ªàµ\8dരമാണà´\82 à´\89ൾപàµ\8dà´ªàµ\86à´\9fàµ\81à´¤àµ\8dതാനàµ\81à´³àµ\8dà´³ à´\95à´£àµ\8dണി).",
        "hidden-category-category-desc": "ഈ വർഗ്ഗത്തിൽ <code><nowiki>__HIDDENCAT__</nowiki></code> ഉള്ളതിനാൽ, താളുകളിലെ വർഗ്ഗങ്ങളുടെ കണ്ണികൾ കാണിക്കുന്ന പെട്ടിയിൽ സ്വതേ പ്രത്യക്ഷപ്പെടുന്നതല്ല.",
        "trackingcategories-nodesc": "വിവരണം ലഭ്യമല്ല.",
        "trackingcategories-disabled": "വർഗ്ഗം നിർജ്ജീവമാക്കിയിരിക്കുന്നു",
        "mywatchlist": "ശ്രദ്ധിക്കുന്നവ",
        "watchlistfor2": "ഉപയോക്താവ്:$1 $2",
        "nowatchlist": "താങ്കൾ ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിൽ ഇനങ്ങളൊന്നുമില്ല.",
-       "watchlistanontext": "താങ്കൾ ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടിക കാണുവാനോ തിരുത്തുവാനോ $1.",
+       "watchlistanontext": "താങ്കൾ ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടിക കാണുവാനോ തിരുത്തുവാനോ പ്രവേശിക്കുക.",
        "watchnologin": "ലോഗിൻ ചെയ്തിട്ടില്ല",
        "addwatch": "ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിലേക്കു ചേർക്കുക",
        "addedwatchtext": "താങ്കൾ [[Special:Watchlist|ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിലേക്ക്]] \"[[:$1]]\" എന്ന ഈ താൾ ചേർത്തിരിക്കുന്നു. ഇനി മുതൽ ഈ താളിലും ബന്ധപ്പെട്ട സം‌വാദം താളിലും ഉണ്ടാകുന്ന മാറ്റങ്ങൾ ആ പട്ടികയിൽ ദൃശ്യമാവും.",
        "watchlist-details": "സം‌വാദത്താളുകൾ ഉൾപ്പെടുത്താതെ {{PLURAL:$1|ഒരു താൾ|$1 താളുകൾ}} താങ്കൾ ശ്രദ്ധിക്കുന്നവയുടെ പട്ടികയിലുണ്ട്.",
        "wlheader-enotif": "ഇമെയിൽ അറിയിപ്പുകൾ സജ്ജമാക്കിയിരിക്കുന്നു.",
        "wlheader-showupdated": "താങ്കളുടെ അവസാന സന്ദർശനത്തിനു ശേഷം മാറ്റം വന്ന താളുകൾ  '''കടുപ്പിച്ച്''' കാണിച്ചിരിക്കുന്നു",
-       "wlnote2": "$2, $3-നു കഴിഞ്ഞ {{PLURAL:$1|ഒരു മണിക്കൂറിലെ|<strong>$1</strong> മണിക്കൂറുകളിലെ}} മാറ്റങ്ങൾ താഴെക്കൊടുത്തിരിക്കുന്നു.",
+       "wlnote": "$3, $4-നു കഴിഞ്ഞ {{PLURAL:$2|മണിക്കൂറിൽ|<strong>$2</strong> മണിക്കൂറിൽ}} നടന്ന {{PLURAL:$1|ഒരു പുതിയ മാറ്റം|<strong>$1</strong> പുതിയ മാറ്റങ്ങൾ}} താഴെ പ്രദർശിപ്പിച്ചിരിക്കുന്നു.",
        "wlshowlast": "ഒടുവിലത്തെ $1 മണിക്കൂറുകൾ $2 ദിനങ്ങൾ, $3 പ്രദർശിപ്പിക്കുക",
        "watchlist-options": "ശ്രദ്ധിക്കുന്ന താളുകളുടെ സജ്ജീകരണങ്ങൾ",
        "watching": "ശ്രദ്ധിക്കുന്നു...",
        "exbeforeblank": "ശൂന്യമാക്കപ്പെടുന്നതിനു മുമ്പുള്ള ഉള്ളടക്കം: '$1'",
        "delete-confirm": "\"$1\" മായ്ക്കുക",
        "delete-legend": "മായ്ക്കുക",
-       "historywarning": "'''മുന്നറിയിപ്പ്''': താങ്കൾ മായ്ക്കുവാൻ പോകുന്ന താളിനു ഏകദേശം {{PLURAL:$1|ഒരു നാൾപ്പതിപ്പ്|$1 നാൾപ്പതിപ്പുകൾ}} ഉള്ള നാൾവഴി ഉണ്ട്:",
+       "historywarning": "<strong>മുന്നറിയിപ്പ്</strong>: താങ്കൾ മായ്ക്കുവാൻ പോകുന്ന താളിനു {{PLURAL:$1|ഒരു നാൾപ്പതിപ്പ്|$1 നാൾപ്പതിപ്പുകൾ}} ഉള്ള നാൾവഴി ഉണ്ട്:",
        "confirmdeletetext": "താങ്കൾ ഒരു താൾ അതിന്റെ നാൾവഴിയടക്കം മായ്ക്കുവാൻ പോവുകയാണ്. ഈ ചെയ്തിയുടെ പരിണതഫലം താങ്കൾക്കറിയാമെന്നും, ഈ നടപടി [[{{MediaWiki:Policy-url}}|വിക്കിയുടെ നയം]] അനുസരിച്ചാണു ചെയ്യുന്നതെന്നും ഉറപ്പാക്കുക.",
        "actioncomplete": "പ്രവൃത്തി പൂർത്തിയായിരിക്കുന്നു",
        "actionfailed": "പ്രവൃത്തി പരാജയപ്പെട്ടിരിക്കുന്നു",
        "delete-edit-reasonlist": "മായ്ക്കലിന്റെ കാരണം തിരുത്തുക",
        "delete-toobig": "ഈ താളിനു വളരെ വിപുലമായ തിരുത്തൽ ചരിത്രമുണ്ട്. $1 മേൽ {{PLURAL:$1|പതിപ്പുണ്ട്|പതിപ്പുകളുണ്ട്}}. ഇത്തരം താളുകൾ മായ്ക്കുന്നതു {{SITENAME}} സം‌രംഭത്തിന്റെ നിലനില്പ്പിനെ തന്നെ ബാധിക്കുമെന്നതിനാൽ ഈ താൾ മായ്ക്കുന്നതിനുള്ള അവകാശം പരിമിതപ്പെടുത്തിയിരിക്കുന്നു.",
        "delete-warning-toobig": "ഈ താളിനു വളരെ വിപുലമായ തിരുത്തൽ ചരിത്രമുണ്ട്. അതായത്, ഇതിനു് $1 മേൽ {{PLURAL:$1|പതിപ്പുണ്ട്|പതിപ്പുകളുണ്ട്}}. ഇത്തരം താളുകൾ മായ്ക്കുന്നതു {{SITENAME}} സം‌രംഭത്തിന്റെ ഡാറ്റാബേസ് ഓപ്പറേഷനെ ബാധിച്ചേക്കാം. അതിനാൽ വളരെ ശ്രദ്ധാപൂർവ്വം തുടർനടപടികളിലേക്കു നീങ്ങുക.",
+       "deleteprotected": "ഈ താൾ സംരക്ഷിക്കപ്പെട്ടിരിക്കുന്നതിനാൽ താങ്കൾക്കിത് മായ്ക്കാനാവില്ല.",
        "deleting-backlinks-warning": "'''മുന്നറിയിപ്പ്:''' മറ്റു താളുകളിൽ നിന്നും [[Special:WhatLinksHere/{{FULLPAGENAME}}|താളിലേയ്ക്കുള്ള കണ്ണികൾ]] അല്ലെങ്കിൽ ഉൾപ്പെടുത്തിയിട്ടുള്ള താളുകൾ താങ്കൾ മായ്ക്കാൻ പോവുകയാണ്.",
-       "rollback": "തിരàµ\81à´¤àµ\8dതലàµ\81à´\95ൾ à´±àµ\8bൾബാà´\95àµ\8dà´\95àµ\8d à´\9aàµ\86à´¯àµ\8dà´¯àµ\81à´\95",
+       "rollback": "തിരുത്തുകൾ റോൾബാക്ക് ചെയ്യുക",
        "rollback_short": "റോൾബാക്ക്",
        "rollbacklink": "റോൾബാക്ക്",
        "rollbacklinkcount": "{{PLURAL:$1|ഒരു തിരുത്ത്|$1 തിരുത്തുകൾ}} മുൻപ്രാപനം ചെയ്യുക",
        "uctop": "(നിലവിലുള്ളത്)",
        "month": "മാസം:",
        "year": "വർഷം:",
-       "sp-contributions-newbies": "à´ªàµ\81തിയ à´\85à´\82à´\97à´\99àµ\8dà´\99ൾ à´¨à´\9fà´¤àµ\8dതിയ à´¤à´¿à´°àµ\81à´¤àµ\8dതലàµ\81à´\95ൾ à´®à´¾à´¤àµ\8dà´°à´\82",
+       "sp-contributions-newbies": "പുതിയ അംഗങ്ങൾ നടത്തിയ തിരുത്തുകൾ മാത്രം",
        "sp-contributions-newbies-sub": "പുതിയ ഉപയോക്താക്കൾ ചെയ്തവ",
        "sp-contributions-newbies-title": "പുതിയ അംഗത്വമെടുത്ത ഉപയോക്താക്കളുടെ സേവനങ്ങൾ",
        "sp-contributions-blocklog": "തടയൽ രേഖ",
        "autoblockid": "സ്വയം തടയൽ #$1",
        "block": "ഉപയോക്താവിനെ തടയുക",
        "unblock": "ഉപയോക്താവിനുള്ള തടയൽ നീക്കുക",
-       "blockip": "ഉപയോക്താവിനെ തടയുക",
+       "blockip": "{{GENDER:$1|ഉപയോക്താവിനെ}} തടയുക",
        "blockip-legend": "ഉപയോക്താവിനെ തടയുക",
        "blockiptext": "ഏതെങ്കിലും ഐ.പി. വിലാസത്തേയോ ഉപയോക്താവിനേയോ തടയുവാൻ താഴെയുള്ള ഫോം ഉപയോഗിക്കുക.\n[[{{MediaWiki:Policy-url}}|വിക്കിയുടെ നയം]] അനുസരിച്ച് നശീകരണപ്രവർത്തനം തടയാൻ മാത്രമേ ഇതു ചെയ്യാവൂ.\nതടയാനുള്ള വ്യക്തമായ കാരണം (ഏതു താളിലാണു നശീകരണപ്രവർത്തനം നടന്നത് എന്നതടക്കം) താഴെ രേഖപ്പെടുത്തിയിരിക്കണം.",
        "ipaddressorusername": "ഐ.പി. വിലാസം അല്ലെങ്കിൽ ഉപയോക്തൃനാമം:",
        "ipb-unblock-addr": "$1 അംഗത്വത്തിനുള്ള തടയൽ നീക്കുക",
        "ipb-unblock": "ഒരു ഐ.പി. വിലാസത്തിനോ ഉപയോക്താവിനോ ഉള്ള തടയൽ നീക്കംചെയ്യുക",
        "ipb-blocklist": "നിലവിലുള്ള തടയലുകൾ",
-       "ipb-blocklist-contribs": "$1 നൽകിയ സംഭാവനകൾ",
+       "ipb-blocklist-contribs": "{{GENDER:$1|$1}} നൽകിയ സംഭാവനകൾ",
        "unblockip": "ഉപയോക്താവിനുള്ള തടയൽ നീക്കുക",
        "unblockiptext": "മുൻപ് തടയപ്പെട്ട ഐ.പി.യുടേയും ഉപയോക്താവിന്റേയും തിരുത്തൽ അവകാശം പുനഃസ്ഥാപിക്കാൻ താഴെയുള്ള ഫോം ഉപയോഗിക്കുക.",
        "ipusubmit": "ഈ വിലക്ക് ഒഴിവാക്കുക",
        "import": "താളുകൾ ഇറക്കുമതി ചെയ്യുക",
        "importinterwiki": "അന്തർവിക്കി ഇറക്കുമതി",
        "import-interwiki-text": "വിക്കിയും ഇറക്കുമതി ചെയ്യാനുള്ള താളും തിരഞ്ഞെടുക്കുക.\nപുതുക്കൽ തീയതികളും തിരുത്തിയ ആളുകളുടെ പേരും സൂക്ഷിക്കപ്പെടും.\nഅന്തർവിക്കി ഇറക്കുമതിയുടെ എല്ലാ വിവരങ്ങളും [[Special:Log/import|ഇറക്കുമതി പ്രവർത്തനരേഖ]] എന്ന താളിൽ ശേഖരിക്കപ്പെടും.",
-       "import-interwiki-source": "മൂല വിക്കി/താൾ:",
+       "import-interwiki-sourcewiki": "സ്രോതസ്സ് വിക്കി:",
+       "import-interwiki-sourcepage": "സ്രോതസ്സ് താൾ:",
        "import-interwiki-history": "ഈ താളിന്റെ എല്ലാ പൂർവ്വചരിത്രവും പകർത്തുക",
        "import-interwiki-templates": "എല്ലാ ഫലകങ്ങളും ഉൾപ്പെടുത്തുക",
        "import-interwiki-submit": "ഇറക്കുമതി",
        "import-error-create": "\"$1\" എന്ന താൾ സൃഷ്ടിക്കാനുള്ള അനുമതി താങ്കൾക്ക് ഇല്ലാത്തതിനാൽ അത് ഇറക്കുമതി ചെയ്തില്ല.",
        "import-error-interwiki": "ബാഹ്യ കണ്ണിചേർക്കലിനു (അന്തർവിക്കി) കരുതിവെച്ചിരിക്കുന്ന പേര് ആയതിനാൽ, \"$1\" എന്ന താൾ ഇറക്കുമതി ചെയ്തില്ല.",
        "import-error-special": "താളുകൾ അനുവദിക്കാത്ത പ്രത്യേക നാമമേഖലയിൽ പെടുന്നതായതിനാൽ \"$1\" എന്ന താൾ ഇറക്കുമതി ചെയ്തില്ല.",
-       "import-error-invalid": "à´ªàµ\87à´°àµ\8d à´\85സാധàµ\81വായതിനാൽ \"$1\" à´\8eà´¨àµ\8dà´¨ à´¤à´¾àµ¾ à´\87à´±à´\95àµ\8dà´\95àµ\81മതി à´\9aàµ\86à´¯àµ\8dà´¯ില്ല.",
+       "import-error-invalid": "à´\87à´±à´\95àµ\8dà´\95àµ\81മതി à´\9aàµ\86à´¯àµ\8dയപàµ\8dà´ªàµ\86à´\9fàµ\8dà´\9fാൽ à´ªàµ\87à´°àµ\8d à´\88 à´µà´¿à´\95àµ\8dà´\95ിയിൽ à´\85സാധàµ\81വാà´\95àµ\81à´®àµ\86à´¨àµ\8dനതിനാൽ \"$1\" à´\8eà´¨àµ\8dà´¨ à´¤à´¾àµ¾ à´\87à´±à´\95àµ\8dà´\95àµ\81മതി à´\9aàµ\86à´¯àµ\8dà´¤ില്ല.",
        "import-options-wrong": "തെറ്റായ {{PLURAL:$2|ഐച്ഛികം|ഐച്ഛികങ്ങൾ}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "നൽകിയ മൂലതാൾ അസാധുവാണ്.",
        "import-rootpage-nosubpage": "മൂലതാളിന്റെ നാമമേഖലയായ \"$1\" ഉപതാളുകൾ അനുവദിക്കുന്നില്ല.",
        "importlogpage": "ഇറക്കുമതി പ്രവർത്തനരേഖ",
        "importlogpagetext": "മറ്റു വിക്കികളിൽ നിന്ന് താളുകൾ നാൾവഴിയടക്കം എടുക്കുന്ന കാര്യനിർവാഹക ഇറക്കുമതി.",
        "import-logentry-upload": "പ്രമാണ അപ്‌‌ലോഡ് വഴി [[$1]] ഇറക്കുമതി ചെയ്തിരിക്കുന്നു",
-       "import-logentry-upload-detail": "{{PLURAL:$1|ഒരു പതിപ്പ്|$1 പതിപ്പുകൾ}}",
+       "import-logentry-upload-detail": "{{PLURAL:$1|ഒരു പതിപ്പ്|$1 പതിപ്പുകൾ}} ഇറക്കുമതി ചെയ്തു",
        "import-logentry-interwiki": "$1 അന്തർവിക്കി ഇറക്കുമതി ചെയ്തു",
-       "import-logentry-interwiki-detail": "$2 എന്നതിൽ നിന്ന് {{PLURAL:$1|ഒരു പതിപ്പ്|$1 പതിപ്പുകൾ}}",
+       "import-logentry-interwiki-detail": "$2 എന്നതിൽ നിന്ന് {{PLURAL:$1|ഒരു പതിപ്പ്|$1 പതിപ്പുകൾ}} ഇറക്കുമതി ചെയ്തു",
        "javascripttest": "ജാവാസ്ക്രിപ്റ്റ് പരീക്ഷണം",
        "javascripttest-title": "$1 പരീക്ഷണങ്ങൾ നടക്കുന്നുണ്ട്",
        "javascripttest-pagetext-noframework": "ഈ താൾ ജാവാസ്ക്രിപ്റ്റ് പരീക്ഷണങ്ങൾ നടത്താനായി മാറ്റിവെച്ചിരിക്കുന്നതാണ്.",
        "autosumm-replace": "താളിലെ വിവരങ്ങൾ $1 എന്നാക്കിയിരിക്കുന്നു",
        "autoredircomment": "[[$1]] എന്ന താളിലേക്ക് തിരിച്ചുവിടുന്നു",
        "autosumm-new": "'$1' താൾ സൃഷ്ടിച്ചിരിക്കുന്നു",
+       "autosumm-newblank": "ശൂന്യമായ താൾ സൃഷ്ടിച്ചു",
        "size-bytes": "$1 ബൈ",
        "size-kilobytes": "$1 കെ.ബി.",
        "size-megabytes": "$1 എം.ബി.",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|സംവാദം]])",
        "unknown_extension_tag": "അജ്ഞാതമായ അനുബന്ധ റ്റാഗ് \"$1\"",
        "duplicate-defaultsort": "'''മുന്നറിയിപ്പ്:''' ക്രമപ്പെടുത്താനുള്ള ചാവിയായ \"$2\" മുമ്പ് ക്രമപ്പെടുത്താനുള്ള ചാവിയായിരുന്ന \"$1\" എന്നതിനെ അതിലംഘിക്കുന്നു.",
+       "duplicate-displaytitle": "<strong>മുന്നറിയിപ്പ്:</strong> പ്രദർശിപ്പിക്കുന്ന തലക്കെട്ട് \"$2\" മുമ്പ് പ്രദർശിപ്പിച്ചിരുന്ന തലക്കെട്ട് \"$1\" എന്നതിനെ അതിലംഘിക്കുന്നു.",
        "version": "പതിപ്പ്",
        "version-extensions": "ഇൻസ്റ്റോൾ ചെയ്തിട്ടുള്ള അനുബന്ധങ്ങൾ",
        "version-skins": "ഇൻസ്റ്റോൾ ചെയ്തിട്ടുള്ള ദൃശ്യരൂപങ്ങൾ",
        "version-parser-function-hooks": "പാഴ്‌സർ ഫങ്ഷൻ കൊളുത്തുകൾ",
        "version-hook-name": "കൊളുത്തിന്റെ പേര്",
        "version-hook-subscribedby": "വരിക്കാരനായത്",
-       "version-version": "(പതിപ്പ് $1)",
+       "version-version": "($1)",
        "version-no-ext-name": "[[പേര് നൽകിയിട്ടില്ല]",
        "version-license": "മീഡിയവിക്കി ഉപയോഗാനുമതി",
        "version-ext-license": "അനുമതി",
        "logentry-rights-rights": "$3 എന്ന ഉപയോക്താവിന്റെ സംഘ അംഗത്വം, $4 എന്നതിൽ നിന്നു $5 എന്നതിലേക്കു, $1 {{GENDER:$2|മാറ്റിയിരിക്കുന്നു}}",
        "logentry-rights-rights-legacy": "$3 എന്ന ഉപയോക്താവിന്റെ സംഘ അംഗത്വം $1 {{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|അപ്‌ലോഡ് ചെയ്തു}}",
        "rightsnone": "(ഒന്നുമില്ല)",
        "feedback-bugornote": "സാങ്കേതിക പ്രശ്നം എന്താണെന്ന് വിവരിച്ചെഴുതാൻ താങ്കൾ തയ്യാറാണെങ്കിൽ [$1 ബഗ് അറിയിക്കുക].\nഅല്ലെങ്കിൽ താങ്കൾക്ക് താഴെ എളുപ്പത്തിനായി നൽകിയിരിക്കുന്ന ഫോം ഉപയോഗിക്കാം. താങ്കളുടെ കുറിപ്പ് \"[$3 $2]\" താളിൽ, താങ്കളുടെ ഉപയോക്തൃനാമത്തിന്റെയും ഉപയോഗിക്കുന്ന ബ്രൗസറിന്റെ പേരിന്റെയും ഒപ്പം ചേർക്കുന്നതായിരിക്കും.",
        "feedback-subject": "വിഷയം:",
        "action-pagelang": "താളിന്റെ ഭാഷ മാറ്റുക",
        "log-name-pagelang": "ഭാഷ മാറ്റലിന്റെ രേഖ",
        "log-description-pagelang": "താളുകളുടെ ഭാഷകൾ മാറ്റിയതിന്റെ രേഖകൾ ഇവിടെക്കാണാം.",
-       "logentry-pagelang-pagelang": "$3 എന്ന താളിന്റെ ഭാഷയായിരുന്ന $4, $1 $5 ആയി {{GENDER:$2|മാറ്റി}}."
+       "logentry-pagelang-pagelang": "$3 എന്ന താളിന്റെ ഭാഷയായിരുന്ന $4, $1 $5 ആയി {{GENDER:$2|മാറ്റി}}.",
+       "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; താങ്കൾ മീഡിയവിക്കി ഇൻസ്റ്റോൾ ചെയ്തതേ ഉള്ളുവെങ്കിൽ:\n: ഗിറ്റിൽ നിന്ന് അല്ലെങ്കിൽ മറ്റെങ്കിലും മാർഗ്ഗം ഉപയോഗിച്ച് സോഴ്സ് കോഡ് നേരിട്ട് ഉപയോഗിക്കുകയായിരിന്നെങ്കിൽ ഇത് സംഭവിച്ചേക്കാം. [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's ദൃശ്യരൂപ ഡയറക്ടറിയിൽ നിന്ന്], ഇനിക്കൊടുക്കുന്ന മാർഗ്ഗങ്ങൾ ഉപയോഗിച്ച് ഏതാനം ദൃശ്യരൂപങ്ങൾ ഇൻസ്റ്റോൾ ചെയ്യാൻ നോക്കുക:\n:* [https://www.mediawiki.org/wiki/Download ടാർബോൾ ഇൻസ്റ്റോളർ] ഡൗൺലോഡ് ചെയ്യുക, അതിൽ നിരവധി ദൃശ്യരൂപങ്ങളും അനുബന്ധങ്ങളും ഉൾപ്പെടുത്തിയിരിക്കുന്നു. അതിൽ നിന്നും താങ്കൾക്ക് <code>skins/</code> ഡയറക്ടറി പകർത്താവുന്നതാണ്.\n:* താങ്കളുടെ മീഡിയവിക്കി ഇൻസ്റ്റലേഷന്റെ <code>skins/</code> ഡയറക്ടറിയിലേക്ക് ഗിറ്റ് ഉപയോഗിച്ച് <code>mediawiki/skins/*</code> റെപ്പോസിറ്ററികളിലൊന്ന് ക്ലോൺ ചെയ്യുക.\n: താങ്കളൊരു മീഡിയവിക്കി ഡവലപ്പറാണെങ്കിൽ ഇത് താങ്കളുടെ ഗിറ്റ് ഡെപ്പോസിറ്ററിയെ ബാധിക്കുന്നതല്ല.\n\n; മീഡിയവിക്കി താങ്കൾ അപ്ഗ്രേഡ് ചെയ്തതേ ഉള്ളുവെങ്കിൽ:\n: മീഡിയവിക്കി 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; താങ്കൾ മീഡിയവിക്കി ഇൻസ്റ്റോൾ ചെയ്തതേ അല്ലെങ്കിൽ അപ്‌ഗ്രേഡ് ചെയ്തതേ ഉള്ളുവെങ്കിൽ:\n: ഗിറ്റിൽ നിന്ന് അല്ലെങ്കിൽ മറ്റെങ്കിലും മാർഗ്ഗം ഉപയോഗിച്ച് സോഴ്സ് കോഡ് നേരിട്ട് ഉപയോഗിക്കുകയായിരിന്നെങ്കിൽ ഇത് സംഭവിച്ചേക്കാം. [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's ദൃശ്യരൂപ ഡയറക്ടറിയിൽ നിന്ന്], ഇനിക്കൊടുക്കുന്ന മാർഗ്ഗങ്ങൾ ഉപയോഗിച്ച് ഏതാനം ദൃശ്യരൂപങ്ങൾ ഇൻസ്റ്റോൾ ചെയ്യാൻ നോക്കുക:\n:* [https://www.mediawiki.org/wiki/Download ടാർബോൾ ഇൻസ്റ്റോളർ] ഡൗൺലോഡ് ചെയ്യുക, അതിൽ നിരവധി ദൃശ്യരൂപങ്ങളും അനുബന്ധങ്ങളും ഉൾപ്പെടുത്തിയിരിക്കുന്നു. അതിൽ നിന്നും താങ്കൾക്ക് <code>skins/</code> ഡയറക്ടറി പകർത്താവുന്നതാണ്.\n:* താങ്കളുടെ മീഡിയവിക്കി ഇൻസ്റ്റലേഷന്റെ <code>skins/</code> ഡയറക്ടറിയിലേക്ക് ഗിറ്റ് ഉപയോഗിച്ച് <code>mediawiki/skins/*</code> റെപ്പോസിറ്ററികളിലൊന്ന് ക്ലോൺ ചെയ്യുക.\n: താങ്കളൊരു മീഡിയവിക്കി ഡവലപ്പറാണെങ്കിൽ ഇത് താങ്കളുടെ ഗിറ്റ് ഡെപ്പോസിറ്ററിയെ ബാധിക്കുന്നതല്ല. ദൃശ്യരൂപങ്ങൾ എങ്ങനെ ക്രമീകരിക്കാം എന്നും സ്വതേ വേണ്ടത് എങ്ങനെ സജ്ജമാക്കാം എന്നും [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 ('''സജ്ജമല്ല''')"
 }
index 67e82db..e60c7dc 100644 (file)
        "talkpagelinktext": "Яриа",
        "specialpage": "Тусгай хуудас",
        "personaltools": "Өөрийн багаж хэрэгслүүд",
-       "postcomment": "Шинэ хэсэг",
        "articlepage": "Өгүүллийг үзэх",
        "talk": "Хэлэлцүүлэг",
        "views": "Харагдацууд",
        "hidetoc": "хумих",
        "collapsible-collapse": "хумих",
        "collapsible-expand": "дэлгэх",
+       "confirmable-confirm": "{{GENDER:$1|Та}} итгэлтэй байна уу?",
+       "confirmable-yes": "Тийм",
+       "confirmable-no": "Үгүй",
        "thisisdeleted": "$1-г харах эсвэл сэргээх үү?",
        "viewdeleted": "$1-г харах уу?",
        "restorelink": "{{PLURAL:$1|арилгасан засвар|арилгасан $1 засварууд}}",
        "externaldberror": "Нэг бол гадны баталгаажуулах мэдээллийн сангийн алдаа гарсан, эсвэл та өөрийн гадны бүртгэлээ шинэчлэх эрхгүй байна.",
        "login": "Нэвтрэх",
        "nav-login-createaccount": "Нэвтрэх / Бүртгүүлэх",
-       "loginprompt": "Та {{SITENAME}}-д нэвтрэхийн тулд күүкинүүд ашиглагдана.",
        "userlogin": "Нэвтрэх / Бүртгүүлэх",
        "userloginnocreate": "Нэвтрэх",
        "logout": "Гарах",
        "gotaccountlink": "Нэвтрэх",
        "userlogin-resetlink": "Нэвтрэх мэдээллээ мартаа юу?",
        "userlogin-resetpassword-link": "Нууц үгээ мартсан уу?",
-       "userlogin-loggedin": "Та {{GENDER:$1|$1}} нэрээр нэвтэрсэн байна.\nӨөр нэрээр нэвтрэх бол доорх маягтыг ашиглана уу.",
-       "userlogin-createanother": "Өөр бүртгэл үүсгэх",
        "createacct-emailrequired": "Цахим шуудангийн хаяг",
        "createacct-email-ph": "Цахим шуудангийн хаягаа оруулна уу",
        "createacct-another-email-ph": "Цахим шуудангийн хаяг оруулна уу",
        "searchprofile-advanced-tooltip": "Сонгосон нэрний зайнуудаас хайх",
        "search-result-size": "$1 (нийт $2 үг)",
        "search-result-category-size": "{{PLURAL:$1|1 гишүүн|$1 гишүүн}} ({{PLURAL:$2|1 дэд ангилал|$2 дэд ангилал}}, {{PLURAL:$3|1 файл|$3 файл}})",
-       "search-result-score": "Холбоо хамаарал: $1%",
        "search-redirect": "(чиглүүлэгч $1)",
        "search-section": "(Хэсэг $1)",
        "search-suggest": "Та $1 гэж хайя гэсэн үү?",
        "preferences": "Хэрэглэгчийн тохиргоо",
        "mypreferences": "Миний тохиргоо",
        "prefs-edits": "Засваруудын тоо:",
+       "prefsnologintext2": "Өөрийн тохиргоогоо өөрчлөхийн тулд логин хийнэ үү.",
        "prefs-skin": "Арьс",
        "skin-preview": "Урьдчилж харах",
        "datedefault": "Анхны байдал",
        "uploadwarning": "Хуулах үеийн анхааруулга",
        "uploadwarning-text": "Доорх файлын тодорхойлолтыг өөрчлөөд дахин оролдоно уу.",
        "savefile": "Файлыг хадгалах",
-       "uploadedimage": "\"[[$1]]\"-г орууллаа",
-       "overwroteimage": "\"[[$1]]\"-н шинэ хувилбарыг орууллаа",
        "uploaddisabled": "Файл оруулах боломжгүй байна.",
        "copyuploaddisabled": "URL-аас оруулж болохгүй.",
        "uploaddisabledtext": "Файл оруулалтуудыг идэвхижүүлээгүй байна.",
        "unusedtemplateswlh": "бусад холбоосууд",
        "randompage": "Санамсаргүй хуудас",
        "randompage-nopages": "Дараах {{PLURAL:$2|нэрний зайнд|нэрний зайнд}} хуудас байхгүй байна : $1. \\",
+       "randomincategory-category": "Ангилал:",
+       "randomincategory-legend": "Ангилалд багтсан дурын хуудас",
        "randomredirect": "Санамсаргүй чиглүүлэгч",
        "randomredirect-nopages": "\"$1\" нэрний зайд чиглүүлэгч байхгүй байна.",
        "statistics": "Статистик мэдээлэл",
        "watchlist-details": "Хяналтын жагсаалтад {{PLURAL:$1|$1 хуудас|$1 хуудаснууд}} байна.",
        "wlheader-enotif": "И-мэйл мэдэгдэл хүчинтэй боллоо.",
        "wlheader-showupdated": "Таны хамгийн сүүлд айлчилснаас хойш өөрчлөгдсөн хуудсууд '''тодоор''' бичигдсэн байгаа",
+       "wlnote": "Энд нь {{PLURAL:$2|цагийн|'''$2''' цагийн}} өмнө хамгийн сүүлд хийсэн {{PLURAL:$1|өөрчлөлт| '''$1''' өөрчлөлтүүд}} байна.",
        "wlshowlast": "Сүүлийн $1 цагийн $2 өдрийн $3-г харуул",
        "watchlist-options": "Хянаж буй хуудсуудын жагсаалтны сонголтууд",
        "watching": "Хянаж байна...",
        "delete-edit-reasonlist": "Устгах шалтгаануудыг засварлах",
        "delete-toobig": "Уг хуудасны засварын түүх маш их, $1 {{PLURAL:$1|засвар|гаруй засвартай}} байна.\n{{SITENAME}}-н аюулгүй байдлын үүднээс дээрх хуудсыг устгахыг хорьсон байна.",
        "delete-warning-toobig": "Энэ хуудасны засварын түүх маш том байгаа бөгөөд {{PLURAL:$1| гаруй засвар| гаруй засварууд}} байна.\nУстгавал {{SITENAME}}-н мэдээллийн сангийн үйл ажиллагаанд нөлөөлж магадгүй тул та анхаарна уу.",
+       "deleteprotected": "Энэ хуудас хамгаалалттай тул устгаж болохгүй.",
        "rollback": "Засваруудыг буцаах",
        "rollback_short": "Буцаах",
        "rollbacklink": "буцаах",
        "whatlinkshere-filters": "Шүүлтүүрүүд",
        "block": "Хэрэглэгчийг блок хийх",
        "unblock": "Хэрэглэгчийг блокоос гаргах",
-       "blockip": "Хэрэглэгчийг түгжих",
+       "blockip": "{{GENDER:$1|хэрэглэгчийн}} түгжих",
        "blockip-legend": "Хэрэглэгчийг түгжих",
        "blockiptext": "Доорх маягтыг ашиглан тодорхой IP хаяг эсвэл хэрэглэгчийн нэрийг засвар хийхээс түгжинэ үү.\nЭнэ нь зөвхөн вандализм үйлдэх явдлаас сэргийлэхийн тулд, [[{{MediaWiki:Policy-url}}|бодлого, баримтлалын]] дагуу хийгдэх ёстой.\nДоор тодорхой шалтгаанаа бичнэ үү.",
        "ipaddressorusername": "IP хаяг буюу хэрэглэгчийн нэр",
        "ipb-unblock-addr": "$1-н түгжээг тайлах",
        "ipb-unblock": "Хэрэглэгчийн нэр эсвэл IP хаягийн түгжээг тайлах",
        "ipb-blocklist": "Байгаа түгжээнүүдийг харах",
-       "ipb-blocklist-contribs": "$1-н хувь нэмэр",
+       "ipb-blocklist-contribs": "{{GENDER:$1|$1}}-н хувь нэмэр",
        "unblockip": "Хэрэглэгчийг идэвхижүүлэх",
        "unblockiptext": "Өмнө нь хориг тавьсан интернет хаяг юм уу хэрэглэгчийн бичих эрхийг сэргээхийн тулд дорх маягтыг ашигла.",
        "ipusubmit": "Энэ түгжээг цуцлах",
        "import": "Хуудаснуудыг импортлох",
        "importinterwiki": "Транс-викигийн импорт",
        "import-interwiki-text": "Импортлох вики болон хуудасны нэрийг сонгоно уу.\nЗасварын огноонууд болон засварлагчдын нэрс хэвээр үлдэнэ.\n[[Special:Log/import|Импортын логоос]] бүх транс-викигийн үйлдлүүд жагсаагдсан байгаа.",
-       "import-interwiki-source": "Эх үүсвэр вики/хуудас:",
+       "import-interwiki-sourcewiki": "wiki -ын эх сурвалж:",
+       "import-interwiki-sourcepage": "Эх хуудас:",
        "import-interwiki-history": "Энэ хуудсын бүх хувилбаруудын түүхийг хуулах",
        "import-interwiki-templates": "Бүх загварыг оруулах",
        "import-interwiki-submit": "Импортлох",
        "duplicate-defaultsort": "'''Анхаар:''' \"$2\" гэсэн default sort key нь \"$1\" гэсэн өмнөх key-н дээгүүр бичигдэх болж байна.",
        "version": "Хувилбар",
        "version-extensions": "Суулгасан өргөтгөлүүд",
+       "version-skins": "Арьс",
        "version-specialpages": "Тусгай хуудсууд",
        "version-parserhooks": "Парсер хүүкүүд",
        "version-variables": "Хувьсагчууд",
        "version-antispam": "Спамаас сэргийлэх",
-       "version-skins": "Арьс",
        "version-other": "Бусад",
        "version-mediahandlers": "Медиа боловсруулагч",
        "version-hooks": "Гогцоо",
index d7c946f..942ddb7 100644 (file)
        "talkpagelinktext": "चर्चा",
        "specialpage": "विशेष पृष्ठ",
        "personaltools": "वैयक्तिक साधने",
-       "postcomment": "नवीन विभाग",
        "articlepage": "लेख पृष्ठ",
        "talk": "चर्चा",
        "views": "दृष्ये",
        "externaldberror": "विदागार ’खातरजमा’ (प्रमाणितीकरण) त्रुटी होती अथवा तुम्हाला तुमचे बाह्य खाते अद्ययावत  करण्याची परवानगी नाही.",
        "login": "सनोंद-प्रवेश(लॉग-ईन)",
        "nav-login-createaccount": "सनोंद-प्रवेश / सदस्यखाते उघडा",
-       "loginprompt": "{{SITENAME}}मध्ये सनोंद-प्रवेशासाठी  स्मृतिशेष सक्षम (कुकिज एनेबल)असणे आवश्यक आहे.",
        "userlogin": "सनोंद-प्रवेश करा /सदस्यखाते उघडा",
        "userloginnocreate": "सनोंद-प्रवेश",
        "logout": "सनोंद-निर्गम",
        "searchprofile-advanced-tooltip": "निवडलेल्या नामविश्वांमध्ये शोधा:",
        "search-result-size": "$1 ({{PLURAL:$2|१ शब्द|$2 शब्द}})",
        "search-result-category-size": "{{PLURAL:$1|१ सदस्य|$1 सदस्य}} ({{PLURAL:$2|१ उपवर्ग|$2 उपवर्ग}}, {{PLURAL:$3|1 संचिका|$3 संचिका}})",
-       "search-result-score": "अन्वर्थकता: $1%",
        "search-redirect": "(पुनर्निर्देशन $1)",
        "search-section": "(विभाग $1)",
        "search-suggest": "तुम्हाला हेच म्हणायचे का: $1",
        "uploadwarning": "चढवताना सूचना",
        "uploadwarning-text": "कृपया खालील संचिका वर्णन संपादित करून पुनर्प्रयत्न करा.",
        "savefile": "संचिका जतन करा",
-       "uploadedimage": "\"[[$1]]\" चे अपभारण केले",
-       "overwroteimage": "\"[[$1]]\" या संचिकेची नवीन आवृत्ती चढविली.",
        "uploaddisabled": "संचिका चढविण्यास बंदी घालण्यात आलेली आहे.",
        "copyuploaddisabled": "आंतरजालपत्त्याद्वारे चढवणे प्रतिबंधित आहे.",
        "uploaddisabledtext": "{{SITENAME}} वर संचिका चढविण्यास बंदी घालण्यात आलेली आहे.",
        "watchlist-details": "पहाऱ्याच्या सूचीमधील {{PLURAL:$1|$1 पान|$1 पाने}}, यात चर्चा पाने मोजलेली नाहीत.",
        "wlheader-enotif": "विपत्र अधिसूचना सुविधा शक्य केली.",
        "wlheader-showupdated": "ती पाने, जी आपण दिलेल्या शेवटच्या भेटीनंतर बदललेली आहेत, '''ठळक''' दाखवली आहेत.",
+       "wlnote": "खाली $3, $4 पर्यंतचे गेल्या {{PLURAL:$2| '''१''' तासातील|'''$2''' तासातील}} {{PLURAL:$1|शेवटचा बदल दिला आहे|शेवटाचे '''$1'''बदल दिले आहेत}}.",
        "wlshowlast": "मागील $1 तास $2 दिवस $3 पहा",
        "watchlist-options": "पहाऱ्याच्या सूचीचे पर्याय",
        "watching": "पहारा देत आहे...",
        "duplicate-defaultsort": "'''ताकिद:''' डिफॉल्ट सॉर्ट की \"$2\" ओवर्राइड्स अर्लीयर डिफॉल्ट सॉर्ट की \"$1\".",
        "version": "आवृत्ती",
        "version-extensions": "स्थापित विस्तार",
+       "version-skins": "त्वचा",
        "version-specialpages": "विशेष पाने",
        "version-parserhooks": "पृथकक अंकुश",
        "version-variables": "चल",
        "version-antispam": "उत्पात प्रतिबंधन",
-       "version-skins": "त्वचा",
        "version-other": "इतर",
        "version-mediahandlers": "मिडिया हॅंडलर",
        "version-hooks": "अंकुश",
index 727e2ab..d78e552 100644 (file)
@@ -2,7 +2,8 @@
        "@metadata": {
                "authors": [
                        "Amdf",
-                       "Andrijko Z."
+                       "Andrijko Z.",
+                       "아라"
                ]
        },
        "tog-underline": "Ажедмӓшвлӓм ыдыралаш",
@@ -15,7 +16,6 @@
        "tog-showtoolbar": "Текстӹм тӧрлӹмӹ годым кӱшӹл панельӹм анжыкташ (JavaScript)",
        "tog-editondblclick": "Ӹлӹшташвлӓм кок гӓнӓ темдӓл, тӧрлӓш (JavaScript)",
        "tog-editsectiononrightclick": "Секцим тӧрлӹмӹ годым артикль лӹмӹм каля доно вургымлашты темдӓлӓш (JavaScript)",
-       "tog-rememberpassword": "Мӹньӹн шотыш нӓлмӹ сирмӓшем ти компьютерӹштӹ ӓштӓш (максимум $1 {{PLURAL:$1|1=кечы|кечы}})",
        "tog-watchcreations": "Мӹньӹн ӹштӹмӹ ӹлӹштӓшвлӓэм вӓнгӹмӹ списокыш пырташ",
        "tog-watchdefault": "Мӹньӹн вашталтымы ӹлӹштӓшвлӓэм вӓнгӹмӹ списокыш пырташ",
        "tog-watchmoves": "Мӹньӹн лӹмӹм вашталтымы ӹлӹштӓшвлӓэм вӓнгӹмӹ списокыш пырташ",
        "navigation": "Навигаци",
        "qbfind": "Кӹчӓлӓш",
        "qbedit": "Торлӓш",
-       "vector-action-delete": "Карангдаш",
-       "vector-action-move": "Лӹмӹм вашталташ",
-       "vector-action-protect": "Ӹшӹклӓш",
-       "vector-view-create": "Ӹштӓш",
-       "vector-view-edit": "Тӧрлӹмӓш",
-       "vector-view-history": "Историм анжымаш",
-       "vector-view-view": "Лыдмаш",
-       "vector-view-viewsource": "Сек пӹтӓриш кодым анжалаш",
        "errorpagetitle": "Самынь",
        "returnto": "Мӹнгеш ӹлӹштӓшӹш $1.",
        "tagline": "гӹц материал {{grammar:genitive|{{SITENAME}}}}",
        "search-interwiki-more": "(эче)",
        "powersearch-legend": "Кымдан кӹчӓлмӓш",
        "powersearch-ns": "Кымдецвлӓштӹ лӹмвлӓм кӹчӓлмӓш:",
-       "powersearch-redir": "Ажедмӓшвлӓм анжыкташ",
        "preferences": "Настройкывлӓ",
        "mypreferences": "Настройкывлӓ",
        "group-sysop": "Администраторвлӓ",
        "recentchanges": "У тӧрлӹмӓшвлӓ",
        "recentchanges-legend": "У тӧрлӹмашвлӓн настройкышты",
        "recentchanges-feed-description": "Ти лиништӹ Викиштӹш вашталтмашвлӓм анжалаш.",
-       "rclistfrom": "$1 доно вашталтмашвлӓм анжыкташ",
+       "rclistfrom": "$3 $2 доно вашталтмашвлӓм анжыкташ",
        "rcshowhideminor": "$1 изи тӧрлӹмаш",
        "rcshowhidebots": "$1 бот",
        "rcshowhideliu": "$1 тинӓрӹн сирӓлтӹнӹт",
        "recentchangeslinked-to": "Анешлӓ, тӹ ӹлыштӓшвлӓштӹш вашталтымашвлӓм анжыкташ, кыдывлӓ ти ӹлӹштӓшӹшкӹ ажедӹт",
        "upload": "Файлым темӓш",
        "uploadlogpage": "Оптымашвлӓн журналышты",
-       "uploadedimage": "оптымы «[[$1]]»",
        "filehist": "Файлын историжӹ",
        "filehist-help": "Файл тӹнӓм махань ылын, тидӹм ужаш манын датым темдӓлдӓ.",
        "filehist-current": "кӹзӹтшӹ",
        "booksources-go": "Моаш",
        "log": "Журналвлӓ",
        "allpages": "Цилӓ ӹлӹштӓш",
-       "alphaindexline": "$1 гӹц $2 якте",
        "prevpage": "Анзыл ӹлӹштӓш ($1)",
        "allpagesfrom": "Анжыкташ тӹ ӹлӹштӓшвлӓм , кыдывлӓ тӹнгӓлӓлтӹт:",
        "allpagesto": "Лыкмашым тишӓк шагалташ:",
index 4953184..250ccd3 100644 (file)
                ]
        },
        "tog-underline": "Garis bawah pautan:",
-       "tog-hideminor": "Sembunyikan suntingan kecil dalam laman perubahan terkini",
-       "tog-hidepatrolled": "Sorokkan suntingan yang telah dironda daripada laman perubahan terkini",
+       "tog-hideminor": "Sembunyikan suntingan kecil daripada perubahan terkini",
+       "tog-hidepatrolled": "Sembunyikan suntingan yang telah dironda daripada perubahan terkini",
        "tog-newpageshidepatrolled": "Sorokkan laman yang telah dironda daripada senarai laman baru",
        "tog-extendwatchlist": "Kembangkan senarai pantau untuk memaparkan semua perubahan, bukan hanya yang terkini",
-       "tog-usenewrc": "Perubahan kumpulan mengikut laman dalam perubahan terkini dan senarai pantau",
+       "tog-usenewrc": "Kumpulkan perubahan mengikut laman dalam perubahan terkini dan senarai pantau",
        "tog-numberheadings": "Nomborkan tajuk secara automatik",
-       "tog-showtoolbar": "Tunjukkan palang sunting (perlukan JavaScript)",
-       "tog-editondblclick": "Dwiklik untuk sunting laman (JavaScript)",
+       "tog-showtoolbar": "Tunjukkan palang alat sunting",
+       "tog-editondblclick": "Dwiklik untuk menyunting laman",
        "tog-editsectiononrightclick": "Bolehkan penyuntingan bahagian dengan mengklik kanan pada tajuk bahagian",
-       "tog-watchcreations": "Tambahkan laman yang saya buat dan fail yang saya muat naik ke dalam senarai pantau",
-       "tog-watchdefault": "Tambahkan laman dan fail yang saya sunting ke dalam senarai pantau",
-       "tog-watchmoves": "Tambahkan laman dan fail yang saya pindahkan ke dalam senarai pantau",
-       "tog-watchdeletion": "Tambahkan laman dan fail yang saya hapuskan ke dalam senarai pantau",
-       "tog-minordefault": "Tandakan semua suntingan sebagai kecil secara asali",
+       "tog-watchcreations": "Tambahkan laman-laman yang saya cipta dan fail-fail yang saya muat naik ke dalam senarai pantau saya",
+       "tog-watchdefault": "Tambahkan laman-laman dan fail-fail yang saya sunting ke dalam senarai pantau saya",
+       "tog-watchmoves": "Tambahkan laman-laman dan fail-fail yang saya pindah ke dalam senarai pantau saya",
+       "tog-watchdeletion": "Tambahkan laman-laman dan fail-fail yang saya hapuskan ke dalam senarai pantau saya",
+       "tog-watchrollback": "Tambahkan laman-laman yang saya undurkan ke dalam senarai pantau saya",
+       "tog-minordefault": "Tandakan semua suntingan sebagai kecil secara lalai",
        "tog-previewontop": "Tunjukkan pralihat di atas kotak sunting",
        "tog-previewonfirst": "Tunjukkan pralihat pada suntingan pertama",
-       "tog-enotifwatchlistpages": "E-mel kepada saya tentang perubahan pada halaman-halaman dan fail-fail dalam senarai pantau saya",
-       "tog-enotifusertalkpages": "E-melkan saya apabila berlaku perubahan pada laman perbincangan saya",
-       "tog-enotifminoredits": "Juga e-mel kepada saya tentang suntingan kecil pada halaman-halaman dan fail-fail",
+       "tog-enotifwatchlistpages": "E-melkan saya apabila sebuah laman atau fail dalam senarai pantau saya diubah",
+       "tog-enotifusertalkpages": "E-melkan saya apabila laman perbincangan saya diubah",
+       "tog-enotifminoredits": "Juga e-melkan saya untuk suntingan-suntingan laman dan fail yang kecil",
        "tog-enotifrevealaddr": "Serlahkan alamat e-mel saya dalam e-mel pemberitahuan",
        "tog-shownumberswatching": "Tunjukkan bilangan pemantau",
        "tog-oldsig": "Tanda tangan yang sedia ada:",
        "tog-watchlisthideown": "Sembunyikan suntingan saya daripada senarai pantau",
        "tog-watchlisthidebots": "Sembunyikan suntingan bot daripada senarai pantau",
        "tog-watchlisthideminor": "Sembunyikan suntingan kecil daripada senarai pantau",
-       "tog-watchlisthideliu": "Sembunyikan suntingan oleh pengguna log masuk daripada senarai pantau",
+       "tog-watchlisthideliu": "Sembunyikan suntingan oleh pengguna yang telah log masuk daripada senarai pantau",
        "tog-watchlisthideanons": "Sembunyikan suntingan oleh pengguna tanpa nama daripada senarai pantau",
-       "tog-watchlisthidepatrolled": "Sorokkan suntingan yang telah dironda daripada senarai pantau",
+       "tog-watchlisthidepatrolled": "Sembunyikan suntingan yang telah dironda daripada senarai pantau",
        "tog-ccmeonemails": "Kirimkan saya salinan e-mel yang saya hantar kepada pengguna lain",
        "tog-diffonly": "Jangan tunjukkan kandungan laman di bawah perbezaan",
        "tog-showhiddencats": "Tunjukkan kategori tersembunyi",
        "tog-norollbackdiff": "Abaikan perbezaan selepas melakukan pengunduran suntingan.",
-       "tog-useeditwarning": "Beri saya amaran apabila saya meninggalkan sesebuah laman penyuntingan tanpa menyimpan perubahan.",
+       "tog-useeditwarning": "Berikan saya amaran apabila saya meninggalkan sesebuah laman penyuntingan tanpa menyimpan perubahan",
        "tog-prefershttps": "Sentiasa gunakan sambungan terlindung apabila log masuk",
        "underline-always": "Sentiasa",
        "underline-never": "Jangan",
        "talkpagelinktext": "Perbincangan",
        "specialpage": "Laman khas",
        "personaltools": "Alatan peribadi",
-       "postcomment": "Bahagian baru",
        "articlepage": "Lihat laman kandungan",
        "talk": "Perbincangan",
        "views": "Rupa",
        "pool-timeout": "Menunggu sebentar untuk dikunci",
        "pool-queuefull": "Giliran kolam telah penuh",
        "pool-errorunknown": "Ralat tak diketahui",
+       "pool-servererror": "Perkhidmatan kaunter tabung tidak disediakan ($1).",
        "aboutsite": "Perihal {{SITENAME}}",
        "aboutpage": "Project:Perihal",
        "copyright": "Kandungan disediakan di bawah $1 melainkan dinyatakan sebaliknya.",
        "hidetoc": "sorokkan",
        "collapsible-collapse": "Lipat",
        "collapsible-expand": "Kembangkan",
+       "confirmable-confirm": "Pastikah {{GENDER:$1|anda}}?",
+       "confirmable-yes": "Ya",
+       "confirmable-no": "Tidak",
        "thisisdeleted": "Lihat atau pulihkan $1?",
        "viewdeleted": "Lihat $1?",
        "restorelink": "{{PLURAL:$1|satu|$1}} suntingan dihapuskan",
        "laggedslavemode": "Amaran: Laman ini mungkin bukan yang terkini.",
        "readonly": "Pangkalan data dikunci",
        "enterlockreason": "Sila nyatakan sebab penguncian dan jangkaan\nbila kunci ini akan dibuka.",
-       "readonlytext": "Pangkalan data sedang dikunci. Hal ini mungkin disebabkan oleh penyenggaraan rutin, dan akan dibuka semula selepas proses penyenggaraan ini siap.\n\nPentadbir yang menguncinya memberi penjelasan ini: $1",
-       "missing-article": "Teks bagi laman \"$1\" $2 tidak dijumpai dalam pangkalan data.\n\nPerkara ini biasanya disebabkan oleh perbuatan mengikuti pautan perbezaan yang lama atau pautan ke laman yang telah dihapuskan.\n\nJika bukan ini sebabnya, anda mungkin telah menjumpai pepijat dalam perisian ini.\nSila catat URL bagi laman ini dan laporkan perkara ini kepada seorang [[Special:ListUsers/sysop|pentadbir]].",
+       "readonlytext": "Pangkalan data telah dikunci daripada penyertaan baru dan perubahan-perubahan lain, mungkin untuk penyenggaraan pangkalan data yang rutin, dan akan dibuka semula selepas ia disiapkan.\n\nPenyelia yang menguncinya telah memberi penjelasan ini: $1",
+       "missing-article": "Teks bagi laman \"$1\" $2 tidak dijumpai dalam pangkalan data.\n\nPerkara ini biasanya disebabkan oleh perbuatan mengikuti pautan perbezaan yang lama atau pautan ke sejarah laman yang telah dihapuskan.\n\nJika ini bukan sebabnya, anda mungkin telah menjumpai pepijat dalam perisian ini.\nSila catat URL bagi laman ini dan laporkan perkara ini kepada seorang [[Special:ListUsers/sysop|penyelia]].",
        "missingarticle-rev": "(semakan $1)",
        "missingarticle-diff": "(Beza: $1, $2)",
        "readonly_lag": "Pangkalan data telah dikunci secara automatik sementara semua pelayan pangkalan data diselaraskan.",
        "mypreferencesprotected": "Anda tidak mempunyai kebenaran untuk menyunting tetapan keutamaan anda.",
        "ns-specialprotected": "Laman khas tidak boleh disunting.",
        "titleprotected": "Tajuk ini telah dilindungi oleh [[User:$1|$1]] daripada dicipta. Sebab yang diberikan ialah ''$2''.",
-       "filereadonlyerror": "Fail \"$1\" tidak dapat diubah suai kerana repositori fail \"$2\" berada dalam ragam baca sahaja.\n\nPentadbir yang menguncinya memberikan penjelasan yang berikut: \"$3\".",
+       "filereadonlyerror": "Fail \"$1\" tidak dapat diubah suai kerana repositori fail \"$2\" berada dalam mod baca sahaja.\n\nPenyelia yang telah menguncinya memberikan penjelasan berikut: \"$3\".",
        "invalidtitle-knownnamespace": "Tajuk tidak sah dengan ruang nama \"$2\" dan teks \"$3\"",
        "invalidtitle-unknownnamespace": "Tajuk tidak sah dengan nombor ruang nama tidak dikenali $1 dan teks \"$2\"",
        "exception-nologin": "Belum log masuk",
-       "exception-nologin-text": "Sila [[Special:Userlogin|log masuk]] untuk dapat mengakses halaman atau tindakan ini.",
+       "exception-nologin-text": "Sila log masuk untuk mendapat akses kepada laman atau tindakan ini.",
        "exception-nologin-text-manual": "Sila $1 untuk dapat mengakses halaman atau tindakan ini.",
        "virus-badscanner": "Konfigurasi rosak: pengimbas virus yang tidak diketahui: ''$1''",
        "virus-scanfailed": "pengimbasan gagal (kod $1)",
        "externaldberror": "Berlaku ralat pangkalan data bagi pengesahan luar atau anda tidak dibenarkan mengemaskinikan akaun luar anda.",
        "login": "Log masuk",
        "nav-login-createaccount": "Log masuk / buka akaun",
-       "loginprompt": "Anda mesti membenarkan kuki untuk log masuk ke dalam {{SITENAME}}.",
        "userlogin": "Log masuk / buka akaun",
        "userloginnocreate": "Log masuk",
        "logout": "Log keluar",
        "userlogin-resetlink": "Lupa nama pengguna/kata laluan anda?",
        "userlogin-resetpassword-link": "Lupa kata laluan anda?",
        "userlogin-helplink2": "Bantuan untuk log masuk",
-       "userlogin-loggedin": "Anda sudah log masuk sebagai {{GENDER:$1|$1}}. Gunakan borang di bawah untuk log masuk sebagai pengguna lain.",
-       "userlogin-createanother": "Buka satu lagi akaun",
        "createacct-emailrequired": "Alamat e-mel",
        "createacct-emailoptional": "Alamat e-mel (pilihan)",
        "createacct-email-ph": "Isikan alamt e-mel anda",
        "preview": "Pralihat",
        "showpreview": "Paparkan pralihat",
        "showdiff": "Lihat perubahan",
+       "blankarticle": "<strong>Amaran:</strong> Laman yang anda sedang menciptakan adalah kosong.\nJika akan menklik \"{{int:savearticle}}\" sekali lagi, laman ini akan diciptakan tanpa sebarang kandungan.",
        "anoneditwarning": "'''Amaran:''' Anda tidak log masuk. Alamat IP anda akan direkodkan dalam sejarah suntingan laman ini.",
        "anonpreviewwarning": "''Anda belum log masuk. Jika anda menyimpan laman ini, alamat IP anda akan direkodkan dalam sejarah penyuntingan laman ini.''",
        "missingsummary": "'''Peringatan:''' Anda tidak menyatakan ringkasan suntingan. Klik '''Simpan''' sekali lagi untuk menyimpan suntingan ini tanpa ringkasan.",
        "summary-preview": "Pralihat ringkasan:",
        "subject-preview": "Pralihat tajuk:",
        "blockedtitle": "Pengguna disekat",
-       "blockedtext": "'''Nama pengguna atau alamat IP anda telah disekat.'''\n\nSekatan ini dilakukan oleh $1 dengan sebab ''$2''.\n\n* Mula: $8\n* Tamat: $6\n* Pengguna sasaran: $7\n\nSila hubungi $1 atau [[{{MediaWiki:Grouppage-sysop}}|pentadbir]] yang lain untuk untuk berunding mengenai sekatan ini.\n\nAnda tidak boleh menggunakan ciri \"e-melkan pengguna ini\" kecuali sekiranya anda telah menetapkan alamat e-mel yang sah dalam [[Special:Preferences|keutamaan]] anda dan anda tidak disekat daripada menggunakannya.\n\nAlamat IP semasa anda ialah $3, dan ID sekatan ialah #$5. Sila sertakan maklumat-maklumat ini dalam pertanyaan nanti.",
-       "autoblockedtext": "Alamat IP anda telah disekat secara automatik kerana ia digunakan oleh pengguna lain yang disekat oleh $1.\nYang berikut ialah sebab yang dinyatakan:\n\n:''$2''\n\n* Mula: $8\n* Tamat: $6\n* Pengguna sasaran: $7\n\nAnda boleh menghubungi $1 atau [[{{MediaWiki:Grouppage-sysop}}|pentadbir]] lain untuk berunding mengenai sekatan ini.\n\nSila ambil perhatian bahawa anda tidak boleh menggunakan ciri \"e-melkan pengguna ini\" kecuali sekiranya anda telah menetapkan alamat e-mel yang sah dalam [[Special:Preferences|laman keutamaan]] anda dan anda tidak disekat daripada menggunakannya.\n\nAlamat IP semasa anda ialah $3, dan ID sekatan ialah #$5. Sila sertakan maklumat-maklumat ini dalam pertanyaan nanti.",
+       "blockedtext": "<strong>Nama pengguna atau alamat IP anda telah disekat.</strong>\n\nSekatan ini dilakukan oleh $1.\nSebab yang telah diberikan ialah <em>$2</em>.\n\n* Sekatan mula: $8\n* Sekatan tamat: $6\n* Pengguna sasaran: $7\n\nAnda boleh hubungi $1 atau [[{{MediaWiki:Grouppage-sysop}}|penyelia]] yang lain untuk membincangkan sekatan ini.\n\nSila ambil perhatian bahawa anda tidak boleh menggunakan ciri \"kirim e-mel kepada pengguna ini\" kecuali sekiranya anda telah menetapkan alamat e-mel yang sah dalam [[Special:Preferences|keutamaan pengguna]] anda dan anda tidak disekat daripada menggunakannya.\n\nAlamat IP semasa anda ialah $3, dan ID sekatan ialah #$5.\nSila sertakan maklumat-maklumat di atas dalam sebarang pertanyaan yang anda membuat.",
+       "autoblockedtext": "Alamat IP anda telah disekat secara automatik kerana ia digunakan oleh pengguna lain yang disekat oleh $1.\nSebab yang dinyatakan ialah:\n\n:<em>$2</em>\n\n* Sekatan mula: $8\n* Sekatan tamat: $6\n* Pengguna sasaran: $7\n\nAnda boleh menghubungi $1 atau seorang [[{{MediaWiki:Grouppage-sysop}}|penyelia]] yang lain untuk membincangkan sekatan ini.\n\nSila ambil perhatian bahawa anda tidak boleh menggunakan ciri \"kirim e-mel kepada pengguna ini\" kecuali sekiranya anda telah menetapkan alamat e-mel yang sah dalam [[Special:Preferences|keutamaan pengguna]] anda dan anda tidak disekat daripada menggunakannya.\n\nAlamat IP semasa anda ialah $3, dan ID sekatan ialah #$5.\nSila sertakan maklumat-maklumat di atas dalam sebarang pertanyaan yang anda membuat.",
        "blockednoreason": "tiada sebab diberikan",
        "whitelistedittext": "Anda hendaklah $1 terlebih dahulu untuk menyunting laman.",
        "confirmedittext": "Anda perlu mengesahkan alamat e-mel anda terlebih dahulu untuk menyunting mana-mana laman. Sila tetapkan dan sahkan alamat e-mel anda melalui [[Special:Preferences|laman keutamaan]].",
        "token_suffix_mismatch": "'''Suntingan anda telah ditolak kerana pelanggan anda memusnahkan aksara tanda baca\ndalam token suntingan. Suntingan tersebut telah ditolak untuk menghalang kerosakan teks laman.\nHal ini kadangkala berlaku apabila anda menggunakan khidmat proksi tanpa nama berdasarkan web yang bermasalah.'''",
        "edit_form_incomplete": "'''Beberapa bahagian dari bentuk edit tidak mencapai pelayan, periksa bahawa suntingan anda utuh dan cuba lagi'.'''",
        "editing": "Menyunting $1",
-       "creating": "Membuat $1",
+       "creating": "Mencipta $1",
        "editingsection": "Menyunting $1 (bahagian)",
        "editingcomment": "Menyunting $1 (bahagian baru)",
        "editconflict": "Percanggahan penyuntingan: $1",
        "parser-template-recursion-depth-warning": "Had pengulangan templat dilebihi ($1)",
        "language-converter-depth-warning": "Had kedalaman penukar bahasa dilepasi ($1)",
        "node-count-exceeded-category": "Laman yang melebihi had kiraan nod",
-       "node-count-exceeded-warning": "Laman terlebih kiraan nod",
+       "node-count-exceeded-category-desc": "Laman telah melebihi kiraan kod maksimum.",
+       "node-count-exceeded-warning": "Laman telah melebihi bilangan nod",
        "expansion-depth-exceeded-category": "Laman yang melebihi had kedalaman peluasan",
+       "expansion-depth-exceeded-category-desc": "Laman telah melebihi kedalaman peluasan maksimum.",
        "expansion-depth-exceeded-warning": "Laman terlebih dalam peluasan",
        "parser-unstrip-loop-warning": "Gelung unstrip dikesan",
        "parser-unstrip-recursion-limit": "Had rekursi unstrip dilampaui ($1)",
        "currentrev": "Semakan semasa",
        "currentrev-asof": "Semakan semasa pada $1",
        "revisionasof": "Semakan pada $1",
-       "revision-info": "Semakan pada $1 oleh $2",
+       "revision-info": "Semakan $3 pada $1 oleh {{GENDER:$6|$2}}$7",
        "previousrevision": "←Semakan sebelumnya",
        "nextrevision": "Semakan berikutnya→",
        "currentrevisionlink": "Semakan semasa",
        "rev-deleted-event": "(entri dibuang)",
        "rev-deleted-user-contribs": "[nama pengguna atau alamat IP dibuang - suntingan disembunyikan daripada sumbangan]",
        "rev-deleted-text-permission": "Semakan laman ini telah '''dihapuskan'''.\nPerinciannya mungkin ada di dalam [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log penghapusan].",
+       "rev-suppressed-text-permission": "Semakan bagi laman ini telah <strong>diselindungkan</strong>.\nButiran boleh didapati dalam [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} log penyelindungan].",
        "rev-deleted-text-unhide": "Semakan laman ini telah '''dihapuskan'''.\nButiran lanjut boleh didapati dalam [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log penghapusan].\nAnda masih boleh [$1 melihat semakan ini] jika anda ingin teruskan.",
        "rev-suppressed-text-unhide": "Semakan laman ini telah '''diselindungkan'''.\nButiran lanjut boleh didapati dalam [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} log penyelindungan].\nAnda masih boleh [$1 melihat semakan ini] jika anda ingin.",
        "rev-deleted-text-view": "Semakan laman ini telah '''dihapuskan'''.\nAnda boleh melihatnya; butiran lanjut boleh didapati dalam [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log penghapusan].",
        "rev-suppressed-no-diff": "Anda tidak boleh melihat perbezaan ini kerana salah satu semakannya telah '''dihapuskan'''.",
        "rev-deleted-unhide-diff": "Salah satu semakan perbezaan ini telah '''dihapuskan'''.\nButiran lanjut boleh didapati dalam [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log penghapusan].\nAnda masih boleh [$1 melihat semakan ini] jika anda ingin teruskan.",
        "rev-suppressed-unhide-diff": "Salah satu semakan perbezaan ini telah '''diselindungkan'''.\nButiran lanjut boleh didapati dalam [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} log penyelindungan].\nAnda masih boleh [$1 melihat perbezaan ini] jika anda ingin teruskan.",
-       "rev-deleted-diff-view": "Salah satu semakan perbezaan ini telah '''dihapuskan'''.\nSebagai pentadbir anda boleh melihat perbezaan ini; butiran boleh didapati di [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log penghapusan].",
+       "rev-deleted-diff-view": "Salah satu semakan perbezaan ini telah <strong>dihapuskan</strong>.\nAnda boleh melihat perbezaan ini; butiran boleh didapati di dalam [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log penghapusan].",
        "rev-suppressed-diff-view": "Salah satu semakan perbezaan ini telah '''dipendam'''.\nAnda boleh melihat perbezaan ini; butiran boleh didapati di [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log penyelindungan].",
        "rev-delundel": "tunjukkan/sorokkan",
        "rev-showdeleted": "tunjukkan",
        "revdelete-text-text": "Semakan-semakan yang terhapus masih akan terdapat dalam sejarah halaman, tetapi sesetengah isi kandungannya tidak akan boleh diakses oleh orang awam.",
        "revdelete-text-file": "Versi-versi yang terhapus masih akan terdapat dalam sejarah fail, tetapi sesetengah isi kandungannya tidak akan boleh diakses oleh orang awam.",
        "logdelete-text": "Peristiwa-peristiwa log yang terhapus masih akan terdapat dalam log, tetapi sesetengah isi kandungannya tidak akan boleh diakses oleh orang awam.",
-       "revdelete-text-others": "Penyelia-penyelia yang lain di {{SITENAME}} masih akan dapat mengakses dan memulihkan kandungan yang tersembunyi menerusi antaramuka yang sama ini, melainkan ditetapkannya sekatan tambahan.",
+       "revdelete-text-others": "Penyelia-penyelia yang lain masih dapat memasuki dan menyahhapuskannya, kecuali jika batasan tambahan telah ditetapkan.",
        "revdelete-confirm": "Sila sahkan bahawa anda bertujuan melakukan ini, bahawa anda faham akibatnya, dan anda melakukannya menurut [[{{MediaWiki:Policy-url}}| polisi]].",
        "revdelete-suppress-text": "Sekatan seharusnya digunakan '''hanya''' untuk kes-kes berikut:\n* maklumat yang mungkin berunsur fitnah\n* maklumat peribadi tidak sesuai\n*: ''alamat rumah dan nombor telefon, nombor keselamatan sosial, dsbg.''",
        "revdelete-legend": "Tetapkan batasan:",
        "revdelete-modify-missing": "Ralat menyunting item ID $1: ia tiada dalam pangkalan data!",
        "revdelete-no-change": "'''Amaran:''' item bertarikh $2, $1 telah mempunyai aturan penglihatan yang diminta.",
        "revdelete-concurrent-change": "Ralat ketika mengubahsuai item bertarikh $2, $1: kelihatan statusnya telah diubah oleh orang lain ketika anda cuba untuk mengubahsuainya.\nMohon semak log.",
-       "revdelete-only-restricted": "Ralat menyembunyikan item bertarikh $2, $1: anda tidak boleh menyekat item-item dari pandangan pentadbir-pentadbir tanpa memilih juga salah satu pilihan pandangan lain.",
+       "revdelete-only-restricted": "Ralat menyembunyikan item bertarikh $2, $1: Anda tidak boleh menyekat item-item dari pandangan penyelia-penyelia tanpa memilih juga salah satu pilihan pandangan yang lain.",
        "revdelete-reason-dropdown": "*Sebab penghapusan yang biasa\n** Pencabulan hak cipta\n** Ulasan atau maklumat peribadi tidak sesuai\n** Nama pengguna tidak sesuai\n** Maklumat berkemungkinan fitnah",
        "revdelete-otherreason": "Sebab lain/tambahan:",
        "revdelete-reasonotherlist": "Sebab lain",
        "revdelete-edit-reasonlist": "Ubah sebab-sebab hapus",
        "revdelete-offender": "Pengarang semakan:",
        "suppressionlog": "Log penahanan",
-       "suppressionlogtext": "Berikut adalah daftar penghapusan dan sekatan yang melibatkan kandungan yang disembunyikan daripada pentadbir.\nLihat [[Special:BlockList|senarai sekatan]] untuk senarai larangan dan sekatan semasa.",
+       "suppressionlogtext": "Berikut adalah senarai penghapusan dan sekatan yang melibatkan kandungan yang telah disembunyikan daripada penyelia.\nLihat [[Special:BlockList|senarai sekatan]] untuk senarai larangan dan sekatan semasa.",
        "mergehistory": "Gabungkan sejarah laman",
        "mergehistory-header": "Anda boleh menggabungkan semua semakan dalam sejarah bagi sesebuah laman sumber ke dalam laman lain.\nSila pastikan bahawa perubahan ini akan mengekalkan kesinambungan sejarah laman.\n\n'''Setidak-tidaknya semakan semasa bagi laman sumber akan ditinggalkan.'''",
        "mergehistory-box": "Gabungkan semakan bagi dua laman:",
        "mergehistory-empty": "Tiada semakan yang boleh digabungkan",
        "mergehistory-success": "$3 semakan bagi [[:$1]] telah digabungkan ke dalam [[:$2]].",
        "mergehistory-fail": "Gagal melaksanakan penggabungan sejarah, sila semak semula laman tersebut dan parameter waktu.",
+       "mergehistory-fail-toobig": "Tidak dapat melakukan gabungan sejarah sebab lebih daripada had $1 semakan perlu dipindahkan.",
        "mergehistory-no-source": "Laman sumber $1 tidak wujud.",
        "mergehistory-no-destination": "Laman destinasi $1 tidak wujud.",
        "mergehistory-invalid-source": "Laman sumber mestilah merupakan tajuk yang sah.",
        "searchprofile-advanced-tooltip": "Cari dalam ruang nama yang tersuai",
        "search-result-size": "$1 ({{PLURAL:$2|$2 patah perkataan}})",
        "search-result-category-size": "$1 {{PLURAL:$1|ahli|ahli}} ($2 {{PLURAL:$2|subkategori|subkategori}}, $3 {{PLURAL:$3|fail|fail}})",
-       "search-result-score": "Kaitan: $1%",
        "search-redirect": "(pelencongan $1)",
        "search-section": "(bahagian $1)",
        "search-file-match": "(sepadan dengan kandungan fail)",
        "searchall": "semua",
        "showingresults": "Yang berikut ialah '''$1''' hasil bermula daripada yang {{PLURAL:$2|pertama|ke-'''$2'''}}.",
        "showingresultsinrange": "Yang berikut adalah {{PLURAL:$1|<strong>satu</strong> hasil|sebanyak <strong>$1</strong> hasil}} dalam julat #<strong>$2</strong> hingga #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Keputusan '''$1''' daripada '''$3'''|Keputusan '''$1 - $2''' daripada '''$3'''}} untuk '''$4'''",
        "search-nonefound": "Tiada hasil yang sepadan dengan pertanyaan.",
        "powersearch-legend": "Carian lanjutan",
        "powersearch-ns": "Cari dalam ruang nama:",
        "powersearch-togglelabel": "Pilih:",
        "powersearch-toggleall": "Semua",
        "powersearch-togglenone": "Tiada",
+       "powersearch-remember": "Ingatkan pilihan untuk carian pada masa depan",
        "search-external": "Carian luar",
        "searchdisabled": "Ciri pencarian dalam {{SITENAME}} dimatikan. Anda boleh mencari melalui Google. Sila ambil perhatian bahawa indeks dalam Google mungkin bukan yang terkini.",
        "search-error": "Berlakunya ralat ketika mencari: $1",
        "preferences": "Keutamaan",
        "mypreferences": "Keutamaan",
        "prefs-edits": "Jumlah suntingan:",
-       "prefsnologintext2": "Sila $1 untuk melihat hasil suntingan anda.",
+       "prefsnologintext2": "Sila log masuk untuk mengubah keutamaan anda.",
        "prefs-skin": "Rupa",
        "skin-preview": "Pralihat",
        "datedefault": "Tiada keutamaan",
        "prefs-advancedwatchlist": "Pilihan lanjutan",
        "prefs-displayrc": "Pilihan paparan",
        "prefs-displaywatchlist": "Pilihan paparan",
+       "prefs-tokenwatchlist": "Token",
        "prefs-diffs": "Beza",
        "prefs-help-prefershttps": "Keutamaan inu akan berkuatkuasa pada lain kali anda log masuk.",
        "prefs-tabs-navigation-hint": "Petua: Anda boleh menggunakan kekunci anak panah kiri atau kanan untuk beralihan dari tab ke tab pada senarai tab.",
        "userrights-reason": "Sebab:",
        "userrights-no-interwiki": "Anda tidak mempunyai keizinan untuk mengubah hak-hak pengguna di wiki lain.",
        "userrights-nodatabase": "Pangkalan data $1 tiada atau bukan tempatan.",
-       "userrights-nologin": "Anda mesti [[Special:UserLogin|log masuk]] dengan akaun pentadbir terlebih dahulu untuk memperuntukkan hak-hak pengguna.",
+       "userrights-nologin": "Anda mesti [[Special:UserLogin|log masuk]] dengan akaun penyelia terlebih dahulu untuk memperuntukkan hak-hak pengguna.",
        "userrights-notallowed": "Akuan anda tidak dibenarkan untuk menambah atau membuang hak pengguna.",
        "userrights-changeable-col": "Kumpulan yang anda boleh ubah",
        "userrights-unchangeable-col": "Kumpulan yang anda tak boleh ubah",
        "group-user": "Pengguna",
        "group-autoconfirmed": "Pengguna sah automatik",
        "group-bot": "Bot",
-       "group-sysop": "Pentadbir",
+       "group-sysop": "Penyelia",
        "group-bureaucrat": "Birokrat",
        "group-suppress": "Penyemak",
        "group-all": "(semua)",
        "group-user-member": "{{GENDER:$1|pengguna}}",
        "group-autoconfirmed-member": "{{GENDER:$1|pengguna sah automatik}}",
        "group-bot-member": "{{GENDER:$1|bot}}",
-       "group-sysop-member": "{{GENDER:$1|pentadbir}}",
+       "group-sysop-member": "{{GENDER:$1|penyelia}}",
        "group-bureaucrat-member": "{{GENDER:$1|birokrat}}",
        "group-suppress-member": "{{GENDER:$1|penyemak}}",
        "grouppage-user": "{{ns:project}}:Pengguna",
        "grouppage-autoconfirmed": "{{ns:project}}:Pengguna yang disahkan secara automatik",
        "grouppage-bot": "{{ns:project}}:Bot",
-       "grouppage-sysop": "{{ns:project}}:Pentadbir",
+       "grouppage-sysop": "{{ns:project}}:Penyelia",
        "grouppage-bureaucrat": "{{ns:project}}:Birokrat",
        "grouppage-suppress": "{{ns:project}}:Penyemak",
        "right-read": "Membaca laman",
        "right-move": "Memindahkan laman",
        "right-move-subpages": "Memindahkan laman berserta sublaman",
        "right-move-rootuserpages": "Memindahkan laman induk pengguna",
+       "right-move-categorypages": "Pindah laman kategori",
        "right-movefile": "Memindahkan fail",
        "right-suppressredirect": "Memindahkan sesebuah laman tanpa mencipta lencongan",
        "right-upload": "Memuat naik fail",
        "right-deletedtext": "Melihat teks yang telah dihapuskan dan perubahan antara semakan-semakan yang telah dihapuskan",
        "right-browsearchive": "Mencari laman-laman yang telah dihapuskan",
        "right-undelete": "Mengembalikan laman yang telah dihapuskan (nyahhapus)",
-       "right-suppressrevision": "Memeriksa dan memulihkan semakan yang terselindung daripada pentadbir",
+       "right-suppressrevision": "Lihat, sembunyi dan nyahsembunyikan semakan-semakan laman yang khusus dari sesiapa pengguna",
+       "right-viewsuppressed": "Lihat semakan-semakan yang disembunyikan daripada sesiapa pengguna",
        "right-suppressionlog": "Melihat log rahsia",
        "right-block": "Menyekat pengguna lain daripada menyunting",
        "right-blockemail": "Menyekat pengguna lain daripada mengirim e-mel",
        "action-move": "memindahkan laman ini",
        "action-move-subpages": "memindahkan laman ini dan sublaman-sublamannya",
        "action-move-rootuserpages": "memindahkan laman induk pengguna",
+       "action-move-categorypages": "memindah laman-laman kategori",
        "action-movefile": "pindah fail ini",
        "action-upload": "memuat naik fail ini",
        "action-reupload": "menulis ganti fail ini",
        "recentchanges-label-plusminus": "Saiz laman telah berubah sebanyak jumlah bait ini",
        "recentchanges-legend-heading": "'''Petunjuk:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (lihat juga [[Special:NewPages|senarai laman baru]])",
-       "rcnotefrom": "Yang berikut adalah semua suntingan sejak <b>$2</b> (yang dipaparkan sehingga <b>$1</b>).",
+       "rcnotefrom": "Yang berikut adalah {{PLURAL:$5|suntingan|suntingan-suntingan}} sejak <strong>$3, $4</strong> (selebihi <strong>$1</strong> dipaparkan).",
        "rclistfrom": "Paparkan perubahan sejak $3 $2",
        "rcshowhideminor": "$1 suntingan kecil",
        "rcshowhideminor-show": "Paparkan",
        "largefileserver": "Fail ini telah melebihi had muat naik pelayan web.",
        "emptyfile": "Fail yang dimuat naik adalah kosong. Ini mungkin disebabkan oleh kesilapan menaip nama fail. Sila pastikan bahawa anda betul-betul mahu memuat naik fail ini.",
        "windows-nonascii-filename": "Wiki ini tidak menyokong nama fail yang mengandungi aksara khas.",
-       "fileexists": "Sebuah fail dengan nama ini telah pun wujud.\nSila semak <strong>[[:$1]]</strong> sekiranya anda tidak pasti bahawa anda mahu menukarnya atau tidak.\n[[$1|thumb]]",
+       "fileexists": "Sebuah fail dengan nama ini sudah wujud. Sila semak <strong>[[:$1]]</strong> sekiranya {{GENDER:|anda}} tidak pasti jika anda mahu menukarnya.\n[[$1|thumb]]",
        "filepageexists": "Laman penerangan untuk fail ini telah pun dicipta di <strong>[[:$1]]</strong>, tetapi tiada fail dengan nama ini wujud.\nRingkasan yang anda masukkan tidak akan muncul di laman penerangan tersebut. Untuk memastikannya muncul, anda perlu menyuntingnya secara manual.\n[[$1|thumb]]",
-       "fileexists-extension": "Sebuah fail dengan nama yang sama telah pun wujud: [[$2|thumb]]\n* Nama fail yang dimuat naik: <strong>[[:$1]]</strong>\n* Nama fail yang sedia ada: <strong>[[:$2]]</strong>\nSila pilih nama lain.",
+       "fileexists-extension": "Sebuah fail dengan nama yang serupa sudah wujud: [[$2|thumb]]\n* Nama fail yang hendak dimuat naik: <strong>[[:$1]]</strong>\n* Nama fail yang sudah sedia ada: <strong>[[:$2]]</strong>\nAdakah anda mungkin mahu menggunakan nama yang lebih tersendiri?",
        "fileexists-thumbnail-yes": "Fail ini kelihatan seperti sebuah imej yang telah dikecilkan ''(gambar kenit)''. [[$1|thumb]]\nSila semak fail <strong>[[:$1]]</strong>.\nJika fail yang disemak itu adalah sama dengan yang saiz asal, maka anda tidak perlu memuat naik gambar kenit tambahan.",
        "file-thumbnail-no": "Nama fail ini bermula dengan <strong>$1</strong>.\nBarangkali ia adalah sebuah imej yang telah dikecilkan ''(gambar kenit)''.\nJika anda memiliki imej ini dalam leraian penuh, sila muat naik fail tersebut. Jika tidak, sila tukar nama fail ini.",
        "fileexists-forbidden": "Sebuah fail dengan nama ini telah pun wujud, dan tidak boleh ditulis ganti. Jika anda masih mahu memuat naik fail ini, sila berundur dan muat naik fail ini dengan nama lain. [[File:$1|thumb|center|$1]]",
        "uploadwarning": "Amaran muat naik",
        "uploadwarning-text": "Sila ubah keterangan fail di bawah dan cuba lagi.",
        "savefile": "Simpan fail",
-       "uploadedimage": "memuat naik \"[[$1]]\"",
-       "overwroteimage": "memuat naik versi baru bagi \"[[$1]]\"",
        "uploaddisabled": "Ciri muat naik dimatikan",
        "copyuploaddisabled": "Ciri muat naik melalui URL telah dilumpuhkan.",
        "uploaddisabledtext": "Ciri muat naik fail dimatikan.",
        "upload-proto-error": "Protokol salah",
        "upload-proto-error-text": "Muat naik jauh memerlukan URL yang dimulakan dengan <code>http://</code> atau <code>ftp://</code>.",
        "upload-file-error": "Ralat dalaman",
-       "upload-file-error-text": "Ralat dalaman telah berlaku ketika cuba mencipta fail sementara pada komputer pelayan.\nSila hubungi [[Special:ListUsers/sysop|pentadbir sistem]].",
+       "upload-file-error-text": "Ralat dalaman telah berlaku ketika mencubai menciptakan fail sementara pada komputer pelayan.\nSila hubungi seorang [[Special:ListUsers/sysop|penyelia]].",
        "upload-misc-error": "Ralat muat naik yang tidak diketahui",
-       "upload-misc-error-text": "Ralat yang tidak diketahui telah berlaku ketika muat naik. Sila pastikan bahawa URL tersebut sah dan boleh dicapai kemudian cuba lagi. Jika masalah ini berterusan, sila hubungi pentadbir sistem.",
+       "upload-misc-error-text": "Ralat yang tidak diketahui telah berlaku ketika muat naik.\nSila pastikan bahawa URL tersebut sah dan boleh dicapai, kemudian cuba lagi.\nJika masalah ini berterusan, sila hubungi seorang [[Special:ListUsers/sysop|penyelia]].",
        "upload-too-many-redirects": "URL ini mengandungi terlalu banyak lencongan",
        "upload-http-error": "Berlaku ralat HTTP: $1",
        "upload-copy-upload-invalid-domain": "Muat naik salin tidak terdapat dari domain ini.",
        "license": "Lesen:",
        "license-header": "Perlesenan",
        "nolicense": "Tidak dipilih",
+       "licenses-edit": "Ubah tetapan lesen",
        "license-nopreview": "(Tiada pralihat)",
-       "upload_source_url": " (URL yang boleh diakses oleh orang awam)",
-       "upload_source_file": " (fail dalam komputer anda)",
+       "upload_source_url": "(fail pilihan anda dari URL sah yang boleh dimasuki oleh orang awam)",
+       "upload_source_file": "(fail pilihan anda dari komputer anda)",
+       "listfiles-delete": "hapus",
        "listfiles-summary": "Laman khas ini memaparkan semua fail yang telah dimuat naik.",
        "listfiles_search_for": "Cari nama imej:",
        "imgfile": "fail",
        "filedelete-maintenance": "Ciri penghapusan dan pemulihan fail telah dilumpuhkan buat sementara sepanjang proses penyenggaraan.",
        "filedelete-maintenance-title": "Fail tidak boleh dihapuskan",
        "mimesearch": "Carian MIME",
-       "mimesearch-summary": "Anda boleh menggunakan laman ini untuk mencari fail mengikut jenis MIME. Format input ialah \"jenis/subjenis\", contohnya <code>image/jpeg</code>.",
+       "mimesearch-summary": "Laman ini membolehkan turasan fail-fail untuk jenis MIME mereka.\nMasukkan: jeniskandungan/subjenis atau jeniskandungan/*, contohnya <code>image/jpeg</code>.",
        "mimetype": "Jenis MIME:",
        "download": "muat turun",
        "unwatchedpages": "Laman tidak dipantau",
        "randomincategory": "Laman rawak dalam kategori",
        "randomincategory-invalidcategory": "\"$1\" bukan nama kategori yang sah.",
        "randomincategory-nopages": "Tiada halaman di [[:Category:$1]].",
-       "randomincategory-selectcategory": "Dapatkan halaman pilihan rawak dari kategori: $1 $2.",
-       "randomincategory-selectcategory-submit": "Pergi",
+       "randomincategory-category": "Kategori:",
+       "randomincategory-legend": "Laman rawak dalam kategori",
        "randomredirect": "Lencongan rawak",
        "randomredirect-nopages": "Tiada lencongan dalam ruang nama \"$1\".",
        "statistics": "Statistik",
        "wantedpages": "Laman dikehendaki",
        "wantedpages-badtitle": "Tajuk tidak sah dalam set keputusan: $1",
        "wantedfiles": "Fail dikehendaki",
-       "wantedfiletext-cat": "Fail-fail yang berikut digunakan tetapi tidak wujud. Fail-fail dari repositori asing mungkin tersenarai walaupun wujud. Sebarang positif palsu sedemikian akan <del>dipotong</del>. Begitu juga, laman-laman yang terbenam fail-fail yang tidak wujud adalah tersenarai dalam [[:$1]].",
-       "wantedfiletext-nocat": "Fail-fail yang berikut digunakan tetapi tidak wujud. Fail-fail dari repositori asing mungkin tersenarai walaupun wujud. Sebarang positif palsu sedemikian akan <del>dipotong</del>.",
+       "wantedfiletext-cat": "Fail-fail berikut sedang digunakan tetapi tidak wujud. Fail-fail dari repositori asing mungkin tersenarai walaupun wujud. Sebarang positif palsu sedemikian akan <del>dipotong</del>. Tambahannya, laman-laman yang membenamkan fail-fail yang tidak wujud disenaraikan dalam [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Fail-fail berikut sedang digunakan tetapi tidak wujud. Juga, laman-laman yang membenamkan fail-fail yang tidak wujud disenaraikan dalam [[:$1]].",
+       "wantedfiletext-nocat": "Fail-fail berikut sedang digunakan tetapi tidak wujud. Fail-fail dari repositori asing mungkin tersenarai walaupun wujud. Sebarang positif palsu sedemikian akan <del>dipotong</del>.",
+       "wantedfiletext-nocat-noforeign": "Fail-fail berikut sedang digunakan tetapi tidak wujud.",
        "wantedtemplates": "Templat dikehendaki",
        "mostlinked": "Laman dipaut terbanyak",
        "mostlinkedcategories": "Kategori dipaut terbanyak",
-       "mostlinkedtemplates": "Templat dipaut terbanyak",
+       "mostlinkedtemplates": "Laman dipaut terbanyak",
        "mostcategories": "Rencana dengan kategori terbanyak",
        "mostimages": "Imej dipaut terbanyak",
        "mostinterwikis": "Laman yang paling banyak pautan interwiki",
        "protectedpages-unknown-timestamp": "Tidak diketahui",
        "protectedpages-unknown-performer": "Pengguna tidak dikenali",
        "protectedtitles": "Tajuk dilindungi",
+       "protectedtitles-summary": "Laman ini menyenaraikan tajuk-tajuk yang telah dilindungi daripada penciptaan. Untuk senarai semua laman sedia ada yang telah dilindungi, lihat [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
        "protectedtitlesempty": "Tiada tajuk yang dilindungi yang sepadan dengan kriteria yang diberikan.",
        "listusers": "Senarai pengguna",
        "listusers-editsonly": "Hanya papar pengguna yang telah membuat suntingan",
        "activeusers-count": "$1 tindakan sejak {{PLURAL:$3|semalam|$3 hari lalu}}",
        "activeusers-from": "Tunjukkan pengguna bermula pada:",
        "activeusers-hidebots": "Sorokkan bot",
-       "activeusers-hidesysops": "Sorokkan pentadbir",
+       "activeusers-hidesysops": "Sorokkan penyelia",
        "activeusers-noresult": "Tiada pengguna dijumpai.",
        "listgrouprights": "Hak kumpulan pengguna",
-       "listgrouprights-summary": "Yang berikut ialah senarai kumpulan pengguna yang ditubuhkan di wiki ini dengan hak-hak masing-masing.\nAnda boleh mengetahui [[{{MediaWiki:Listgrouprights-helppage}}|maklumat tambahan]] mengenai setiap hak.",
+       "listgrouprights-summary": "Berikut adalah senarai kumpulan pengguna yang ditubuhkan di wiki ini, dengan hak-hak mereka masing-masing.\nMungkin terdapat [[{{MediaWiki:Listgrouprights-helppage}}|maklumat tambahan]] mengenai setiap hak.",
        "listgrouprights-key": "Petunjuk:\n* <span class=\"listgrouprights-granted\">Hak ditunaikan</span>\n* <span class=\"listgrouprights-revoked\">Hak dibatalkan</span>",
        "listgrouprights-group": "Kumpulan",
        "listgrouprights-rights": "Hak",
        "listgrouprights-removegroup-self": "Keluar daripada {{PLURAL:$2|kumpulan|kumpulan-kumpulan}}: $1",
        "listgrouprights-addgroup-self-all": "Menyertai semua kumpulan",
        "listgrouprights-removegroup-self-all": "Keluar daripada semua kumpulan",
-       "listgrouprights-namespaceprotection-header": "Sekatan ruang nama",
+       "listgrouprights-namespaceprotection-header": "Batasan ruang nama",
        "listgrouprights-namespaceprotection-namespace": "Ruang nama",
-       "trackingcategories": "Kategori penjejak",
+       "listgrouprights-namespaceprotection-restrictedto": "Hak(-hak) yang membenarkan pengguna untuk menyunting",
+       "trackingcategories": "Kategori-kategori penjejak",
+       "trackingcategories-summary": "Laman ini menyenaraikan kategori-kategori penjejak yang diisikan oleh perisian MediaWiki secara automatik. Nama-nama mereka boleh ditukarkan dengan mengubah pesanan-pesanan sistem berkenaan dalam ruang nama {{ns:8}}.",
        "trackingcategories-msg": "Kategori penjejak",
        "trackingcategories-name": "Nama pesanan",
+       "trackingcategories-desc": "Kriteria kemasukan kategori",
+       "noindex-category-desc": "Laman tidak didaftar oleh robot kerana ia mempunyai kata ajaib <code><nowiki>__NOINDEX__</nowiki></code> padanya dan terdapat dalam ruang nama di mana tanda tersebut adalah dibenarkan.",
+       "index-category-desc": "Laman mempunyai <code><nowiki>__INDEX__</nowiki></code> padanya (dan terdapat dalam ruang nama di mana tanda tersebut dibenarkan), dan oleh itu adalah didaftar oleh robot di mana ia biasanya tidak akan.",
+       "post-expand-template-inclusion-category-desc": "Saiz laman melebihi <code>$wgMaxArticleSize</code> setelah semua templat telah dikembangkan; oleh itu beberapa templat tidak dikembangkan.",
+       "post-expand-template-argument-category-desc": "Laman menjadi lebih besar daripada <code>$wgMaxArticleSize</code> setelah mengembangkan sebuah hujah templat (sebarang dalam tiga kurungan, seperti <code>{{{Foo}}}</code>.)",
+       "expensive-parserfunction-category-desc": "Laman menggunakan terlalu banyak fungsi parser yang mahal (seperti <code>#ifexist</code>). Lihat [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "Laman mempunyai pautan fail yang putus (pautan untuk membenam sebuah fail apabila fail tersebut tidak wujud).",
+       "hidden-category-category-desc": "Kategori mengandungi <code><nowiki>__HIDDENCAT__</nowiki></code> dalam kandungan laman, menghalangkannya daripada paparan dalam kotak pautan kategori pada laman-laman secara asli.",
        "trackingcategories-nodesc": "Tiada keterangan tersedia.",
+       "trackingcategories-disabled": "Kategori telah dimatikan",
        "mailnologin": "Tiada alamat e-mel",
        "mailnologintext": "Anda perlu [[Special:UserLogin|log masuk]]\nterlebih dahulu dan mempunyai alamat e-mel yang sah dalam\n[[Special:Preferences|laman keutamaan]] untuk mengirim e-mel kepada pengguna lain.",
        "emailuser": "Kirim e-mel kepada pengguna ini",
        "mywatchlist": "Senarai pantau",
        "watchlistfor2": "Bagi $1 $2",
        "nowatchlist": "Tiada item dalam senarai pantau anda.",
-       "watchlistanontext": "Sila $1 terlebih dahulu untuk melihat atau menyunting senarai pantau anda.",
+       "watchlistanontext": "Sila log masuk untuk melihat atau menyunting senarai pantau anda.",
        "watchnologin": "Belum log masuk",
        "addwatch": "Tambahkan ke senarai pantau",
        "addedwatchtext": "Halaman \"[[:$1]]\" telah dimasukkan ke dalam [[Special:Watchlist|senarai pantau anda]].\nPerubahan-perubahan pada halaman ini dan halaman perbualannya pada masa akan datang akan tersenarai di dalam senarai itu.",
+       "addedwatchtext-short": "Laman \"$1\" telah ditambahkan kepada senarai pantau anda.",
        "removewatch": "Buang dari senarai pantau",
        "removedwatchtext": "Laman \"[[:$1]]\" telah dibuang daripada [[Special:Watchlist|senarai pantau anda]].",
+       "removedwatchtext-short": "Laman \"$1\" telah dikeluarkan dari senarai pantau anda.",
        "watch": "Pantau",
        "watchthispage": "Pantau laman ini",
        "unwatch": "Nyahpantau",
        "watchlist-details": "$1 laman dipantau ,tidak termasuk laman perbincangan.",
        "wlheader-enotif": "Pemberitahuan melalui e-mel dibolehkan.",
        "wlheader-showupdated": "Laman-laman yang telah diubah sejak kunjungan terakhir anda dipaparkan dalam '''teks tebal'''.",
-       "wlnote2": "Yang berikut adalah perubahan dalam {{PLURAL:$1|sejam|<strong>$1</strong> jam}} yang lepas, setakat $2, $3.",
+       "wlnote": "Yang berikut ialah <strong>$1</strong> perubahan terakhir sejak $2 jam yang lalu, sehingga $3, $4.",
        "wlshowlast": "Tunjukkan $1 jam / $2 hari yang lalu / $3.",
        "watchlist-options": "Pilihan senarai pantau",
        "watching": "Memantau...",
        "exbeforeblank": "kandungan sebelum pengosongan ialah: '$1'",
        "delete-confirm": "Hapus \"$1\"",
        "delete-legend": "Hapuskan",
-       "historywarning": "'''Amaran:''' Laman yang ingin anda hapuskan mengandungi sejarah dengan kira-kira $1 {{PLURAL:$1|semakan|semakan}}:",
+       "historywarning": "<strong>Amaran:</strong> Laman yang ingin anda hapuskan mempunyai sejarah dengan $1 semakan:",
        "confirmdeletetext": "Anda sudah hendak menghapuskan sebuah laman berserta semua sejarahnya.\nSila sahkan bahawa anda memang hendak berbuat demikian, anda faham akan\nakibatnya, dan perbuatan anda mematuhi [[{{MediaWiki:Policy-url}}|dasar kami]].",
        "actioncomplete": "Tindakan berjaya",
        "actionfailed": "Tindakan gagal",
        "delete-edit-reasonlist": "Ubah sebab-sebab hapus",
        "delete-toobig": "Laman ini mempunyai sejarah yang besar, iaitu melebihi $1 jumlah semakan. Oleh itu, laman ini dilindungi daripada dihapuskan untuk mengelak kerosakan di {{SITENAME}} yang tidak disengajakan.",
        "delete-warning-toobig": "Laman ini mempunyai sejarah yang besar, iaitu melebihi $1 jumlah semakan. Menghapuskannya boleh mengganggu perjalanan pangkalan data {{SITENAME}}. Sila berhati-hati.",
+       "deleteprotected": "Anda tidak boleh menghapuskan laman ini kerana ia telah dilindungi.",
        "deleting-backlinks-warning": "'''Amaran:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Terdapat laman lain]] yang berpaut atau bertransklusi dengan laman yang hendak anda hapus ini.",
        "rollback": "Undurkan suntingan.",
        "rollback_short": "Undur",
        "protect-default": "Benarkan semua pengguna",
        "protect-fallback": "Benarkan pengguna yang berizin \"$1\" sahaja",
        "protect-level-autoconfirmed": "Benarkan pengguna yang diautosahkan sahaja",
-       "protect-level-sysop": "Benarkan pentadbir sahaja",
+       "protect-level-sysop": "Benarkan penyelia sahaja",
        "protect-summary-cascade": "melata",
        "protect-expiring": "sehingga $1 (UTC)",
        "protect-expiring-local": "luput $1",
        "undeleterevisions": "$1 semakan telah diarkibkan.",
        "undeletehistory": "Jika anda memulihkan laman tersebut, semua semakan akan dipulihkan kepada sejarahnya. Jika sebuah laman baru yang mempunyai nama yang sama telah dicipta sejak penghapusan, semakan yang dipulihkan akan muncul dalam sejarah terdahulu.",
        "undeleterevdel": "Penyahhapusan tidak akan dilaksanakan sekiranya ia menyebabkan sebahagian semakan puncak dihapuskan.\nDalam hal tersebut, anda perlu membuang semak atau menyemak semakan yang baru dihapuskan. Semakan fail\nyang anda tidak dibenarkan melihatnya tidak akan dipulihkan.",
-       "undeletehistorynoadmin": "Rencana ini telah dihapuskan. Sebab penghapusan\nditunjukkan dalam ringkasan di bawah, berserta butiran bagi pengguna-pengguna yang telah menyunting laman ini\nsebelum penghapusan. Teks sebenar bagi semua semakan yang dihapuskan hanya boleh dilihat oleh para pentadbir.",
+       "undeletehistorynoadmin": "Laman ini telah dihapuskan.\nSebab penghapusan ditunjukkan dalam ringkasan di bawah, berserta butiran pengguna-pengguna yang telah menyunting laman ini sebelum penghapusan.\nTeks sebenar bagi semakan yang dihapuskan berikut hanya boleh dilihat oleh para penyelia.",
        "undelete-revision": "Menghapuskan semakan bagi $1 (pada $4, $5) oleh $3:",
        "undeleterevision-missing": "Semakan tersebut tidak sah atau tidak dijumpai. Mungkin anda telah mengikuti pautan yang rosak\natau semakan tersebut telah dipulihkan atau dibuang daripada arkib.",
        "undelete-nodiff": "Tiada semakan sebelumnya.",
        "sp-contributions-newbies-sub": "Bagi akaun-akaun baru",
        "sp-contributions-newbies-title": "Sumbangan oleh pengguna baru",
        "sp-contributions-blocklog": "log sekatan",
+       "sp-contributions-suppresslog": "sumbangan pengguna tersembunyi",
        "sp-contributions-deleted": "sumbangan dihapuskan",
        "sp-contributions-uploads": "muat naik",
        "sp-contributions-logs": "log",
        "autoblockid": "Sekat #$1 secara automatik",
        "block": "Sekat pengguna",
        "unblock": "Nyahsekat pengguna",
-       "blockip": "Sekat pengguna",
+       "blockip": "Sekat {{GENDER:$1|pengguna}}",
        "blockip-legend": "Sekat pengguna",
        "blockiptext": "Gunakan borang di bawah untuk menyekat\npenyuntingan daripada alamat IP atau pengguna tertentu.\nTindakan ini perlu dilakukan untuk menentang vandalisme sahaja dan selaras\ndengan [[{{MediaWiki:Policy-url}}|dasar {{SITENAME}}]].\nSila masukkan sebab sekatan di bawah (umpamannya, sebutkan laman yang telah\ndirosakkan).",
        "ipaddressorusername": "Alamat IP atau nama pengguna:",
        "ipb-unblock-addr": "Nyahsekat $1",
        "ipb-unblock": "Nyahsekat nama pengguna atau alamat IP",
        "ipb-blocklist": "Lihat sekatan sedia ada",
-       "ipb-blocklist-contribs": "Sumbangan oleh $1",
+       "ipb-blocklist-contribs": "Sumbangan oleh {{GENDER:$1|$1}}",
        "unblockip": "Nyahsekat pengguna",
        "unblockiptext": "Gunakan borang di bawah untuk membuang sekatan bagialamat IP atau nama pengguna yang telah disekat.",
        "ipusubmit": "Tarik balik sekatan ini",
        "blocklist-timestamp": "Cop masa",
        "blocklist-target": "Sasaran",
        "blocklist-expiry": "Luput",
-       "blocklist-by": "Pentadbir sekatan",
+       "blocklist-by": "Penyelia sekatan",
        "blocklist-params": "Parameter sekatan",
        "blocklist-reason": "Sebab",
        "ipblocklist-submit": "Cari",
        "movepagetalktext": "Laman perbincangan yang berkaitan, jika ada, akan dipindahkan bersama-sama laman ini secara automatik '''kecuali''':\n* Sebuah laman perbincangan dengan nama baru telah pun wujud, atau\n* Anda membuang tanda kotak di bawah.\n\nDalam kes tersebut, anda terpaksa melencongkan atau menggabungkan laman secara manual, jika perlu.",
        "movearticle": "Pindahkan laman:",
        "moveuserpage-warning": "'''Amaran:''' Anda sudah hendak memindahkan suatu laman pengguna. Sila ambil perhatian bahawa hanya laman tersebut akan dipindahkan dan nama pengguna yang berkenaan ''tidak'' berubah.",
+       "movecategorypage-warning": "<strong>Amaran:</strong> Anda hendak memindahkan sebuah laman kategori. Sila ambil perhatian bahawa hanya laman akan dipindahkan dan sebarang laman dalam kategori laman <em>tidak</em> akan dikategorikan semula ke dalam yang baru.",
        "movenologintext": "Anda mesti [[Special:UserLogin|log masuk]] terlebih dahulu untuk memindahkan laman.",
        "movenotallowed": "Anda tidak mempunyai keizinan untuk memindahkan laman.",
        "movenotallowedfile": "Anda tidak mempunyai keizinan untuk memindahkan fail.",
        "cant-move-user-page": "Anda tidak mempunyai keizinan untuk memindahkan laman pengguna (tidak termasuk sublaman-sublamannya).",
        "cant-move-to-user-page": "Anda tidak mempunyai keizinan untuk memindahkan sesebuah laman ke mana-mana laman pengguna (kecuali sebagai sublamannya sahaja).",
+       "cant-move-category-page": "Anda tidak mempunyai kebenaran untuk memindah laman-laman kategori.",
+       "cant-move-to-category-page": "Anda tidak mempunyai kebenaran untuk memindah sebuah laman ke sebuah laman kategori.",
        "newtitle": "Ke tajuk baru:",
        "move-watch": "Pantau laman ini",
        "movepagebtn": "Pindahkan laman",
        "thumbnail_image-type": "Jenis imej tidak disokong",
        "thumbnail_gd-library": "Tatarajah perpustakaan GD tidak lengkap: kehilangan fungsi $1",
        "thumbnail_image-missing": "Fail ini nampaknya hilang: $1",
+       "thumbnail_image-failure-limit": "Terdapat terlalu banyak percubaan yang gagal ($1 atau lebih) untuk memaparkan thumbnail ini. Sila cuba lagi kemudian.",
        "import": "Import laman",
        "importinterwiki": "Import transwiki",
        "import-interwiki-text": "Sila pilih wiki dan tajuk laman yang ingin diimport.\nSemua tarikh semakan dan nama penyunting akan dikekalkan.\nSemua tindakan import transwiki dicatatkan dalam [[Special:Log/import|log import]].",
-       "import-interwiki-source": "Sumber wiki/halaman:",
+       "import-interwiki-sourcewiki": "Wiki sumber:",
+       "import-interwiki-sourcepage": "Laman sumber:",
        "import-interwiki-history": "Salin semua versi sejarah bagi laman ini",
        "import-interwiki-templates": "Sertakan semua templat",
        "import-interwiki-submit": "Import",
        "import-error-create": "Laman \"$1\" tidak diimport kerana anda tidak dibenarkan untuk menciptanya.",
        "import-error-interwiki": "Laman \"$1\" tidak diimport kerana namanya ditempah untuk pemautan luaran (antara wiki).",
        "import-error-special": "Laman \"$1\" tidak diimport kerana ia tergolong dalam ruang nama khas yang tidak membenarkan laman.",
-       "import-error-invalid": "Laman \"$1\" tidak diimport kerana namanya tidak sah.",
+       "import-error-invalid": "Laman \"$1\" tidak diimport kerana nama yang ia akan diimport kepada tidak sah pada wiki ini.",
        "import-error-unserialize": "Semakan $2 dari halaman \"$1\" tidak dapat dinyahsirikan. Semakan ini dilaporkan telah menggunakan model kandungan $3 yang disirikan sebagai $4.",
        "import-error-bad-location": "Semakan $2 yang menggunakan model kandungan $3 tidak boleh disimpan pada \"$1\" di wiki ini kerana model itu tidak disokong pada halaman tersebut.",
        "import-options-wrong": "{{PLURAL:$2|Pilihan|Pilihan-pilihan}} salah: <nowiki>$1</nowiki>",
        "importlogpage": "Log import",
        "importlogpagetext": "Senarai tindakan import laman dengan keseluruhan sejarah suntingannya daripada wiki lain.",
        "import-logentry-upload": "mengimport [[$1]] dengan memuat naik fail",
-       "import-logentry-upload-detail": "$1 semakan",
+       "import-logentry-upload-detail": "$1 semakan diimportkan",
        "import-logentry-interwiki": "$1 dipindahkan ke wiki lain",
-       "import-logentry-interwiki-detail": "$1 semakan daripada $2",
+       "import-logentry-interwiki-detail": "$1 semakan diimportkan daripada $2",
        "javascripttest": "Ujian JavaScript",
        "javascripttest-title": "Ujian $1 sedang dijalankan",
        "javascripttest-pagetext-noframework": "Laman ini ditempah untuk menjalankan ujian JavaScript.",
        "tooltip-preferences-save": "Simpan keutamaan",
        "tooltip-summary": "Berikan ringkasan",
        "common.css": "/* CSS yang terletak di sini akan digunakan pada semua kulit */",
+       "print.css": "/* CSS yang diletakkan di sini akan memberi kesan kepada hasil cetak */",
+       "noscript.css": "/* CSS yang diletakkan di sini akan memberi kesan kepada pengguna dengan JavaScript dimatikan */",
+       "group-autoconfirmed.css": "/* CSS yang diletakkan di sini akan memberi kesan kepada pengguna-pengguna sah automatik sahaja */",
+       "group-user.css": "/* CSS yang diletakkan di sini akan memberi kesan kepada pengguna-pengguna berdaftar sahaja */",
+       "group-bot.css": "/* CSS yang diletakkan di sini akan memberi kesan kepada bot sahaja */",
+       "group-sysop.css": "/* CSS yang diletakkan di sini akan memberi kesan kepada penyelia-penyelia sahaja */",
+       "group-bureaucrat.css": "/* CSS yang diletakkan di sini akan memberi kesan kepada birokrat-birokrat sahaja */",
+       "common.js": "/* Sebarang JavaScript di sini akan dimuatkan untuk semua pengguna pada setiap pemuatan laman. */",
+       "group-autoconfirmed.js": "/* Sebarang JavaScript di sini akan dimuatkan untuk pengguna-pengguna sah automatik sahaja */",
+       "group-user.js": "/* Sebarang JavaScript di sini akan dimuatkan untuk pengguna-pengguna berdaftar sahaja */",
+       "group-bot.js": "/* Sebarang JavaScript di sini akan dimuatkan untuk bot sahaja */",
+       "group-sysop.js": "/* Sebarang JavaScript di sini akan dimuatkan untuk penyelia-penyelia sahaja */",
+       "group-bureaucrat.js": "/* Sebarang JavaScript di sini akan dimuatkan untuk birokrat-birokrat sahaja */",
        "anonymous": "{{PLURAL:$1|Pengguna|Pengguna-pengguna}} {{SITENAME}} tanpa nama",
        "siteuser": "Pengguna {{SITENAME}}, $1",
        "anonuser": "Pengguna {{SITENAME}} tanpa nama $1",
        "newimages-summary": "Laman khas ini memaparkan senarai fail muat naik terakhir.",
        "newimages-legend": "Penapis",
        "newimages-label": "Nama fail (atau sebahagian daripadanya):",
+       "newimages-showbots": "Paparkan muat naik oleh bot",
        "noimages": "Tiada imej.",
        "ilsubmit": "Cari",
        "bydate": "mengikut tarikh",
        "confirm-watch-top": "Tambahkan laman ini ke dalam senarai pantau anda?",
        "confirm-unwatch-button": "OK",
        "confirm-unwatch-top": "Buang laman ini daripada senarai pantau anda?",
+       "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← halaman sebelumnya",
        "imgmultipagenext": "halaman berikutnya →",
        "imgmultigo": "Pergi!",
        "autosumm-replace": "Mengganti laman dengan '$1'",
        "autoredircomment": "Melencong ke [[$1]]",
        "autosumm-new": "Mencipta laman baru dengan kandungan '$1'",
+       "autosumm-newblank": "Mencipta laman kosong",
        "lag-warn-normal": "Sebarang perubahan baru yang melebihi $1 saat mungkin tidak ditunjukkan dalam senarai ini.",
        "lag-warn-high": "Disebabkan oleh kelambatan pelayan pangkalan data, sebarang perubahan baru yang melebihi $1 saat mungkin tidak ditunjukkan dalam senarai ini.",
        "watchlistedit-normal-title": "Sunting senarai pantau",
        "watchlistedit-raw-done": "Senarai pantau anda telah dikemaskinikan.",
        "watchlistedit-raw-added": "$1 tajuk ditambah:",
        "watchlistedit-raw-removed": "$1 tajuk telah dibuang:",
+       "watchlistedit-clear-title": "Senarai pantau kosong",
+       "watchlistedit-clear-legend": "Kosongkan senarai pantau",
+       "watchlistedit-clear-explain": "Semua tajuk akan dikeluarkan dari senarai pantau anda",
+       "watchlistedit-clear-titles": "Tajuk-tajuk:",
+       "watchlistedit-clear-submit": "Kosongkan senarai pantau (Ini adalah kekal!)",
+       "watchlistedit-clear-done": "Senarai pantau anda telah dikosongkan.",
+       "watchlistedit-clear-removed": "{{PLURAL:$1|Satu|$1}} tajuk telah dikeluarkan.",
+       "watchlistedit-too-many": "Terdapat terlalu banyak laman untuk dipaparkan di sini.",
+       "watchlisttools-clear": "Kosongkan senarai pantau",
        "watchlisttools-view": "Lihat perubahan",
        "watchlisttools-edit": "Sunting senarai pantau",
        "watchlisttools-raw": "Sunting senarai pantau mentah",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|bincang]])",
        "unknown_extension_tag": "Tag penyambung \"$1\" tidak dikenali",
        "duplicate-defaultsort": "'''Amaran''': Kunci susunan asali \"$2\" membatalkan kunci susunan asali \"$1\" yang sebelumnya.",
+       "duplicate-displaytitle": "<strong>Amaran:</strong> Tajuk paparan \"$2\" mengatasi tajuk paparan awal \"$1\".",
        "version": "Versi",
        "version-extensions": "Penyambung yang dipasang",
+       "version-skins": "Rupa-rupa yang telah dipasangkan",
        "version-specialpages": "Laman khas",
        "version-parserhooks": "Penyangkuk penghurai",
        "version-variables": "Pemboleh ubah",
        "version-antispam": "Pencegahan spam",
-       "version-skins": "Rupa",
        "version-other": "Lain-lain",
        "version-mediahandlers": "Pengelola media",
        "version-hooks": "Penyangkuk",
        "version-hook-name": "Nama penyangkuk",
        "version-hook-subscribedby": "Dilanggan oleh",
        "version-version": "(Versi $1)",
+       "version-no-ext-name": "[tiada nama]",
        "version-license": "Lesen MediaWiki",
        "version-ext-license": "Lesen",
        "version-ext-colheader-name": "Sambungan",
+       "version-skin-colheader-name": "Rupa",
        "version-ext-colheader-version": "Versi",
        "version-ext-colheader-license": "Lesen",
        "version-ext-colheader-description": "Keterangan",
        "tags": "Label perubahan yang sah",
        "tag-filter": "Tapis [[Special:Tags|label]]:",
        "tag-filter-submit": "Tapis",
-       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Teg}}]]: $2)",
+       "tag-list-wrapper": "([[Special:Tags|Label]]: $2)",
        "tags-title": "Label",
        "tags-intro": "Yang berikut ialah senarai label yang digunakan untuk menanda suntingan, berserta maknanya.",
        "tags-tag": "Nama label",
        "htmlform-no": "Tidak",
        "htmlform-yes": "Ya",
        "htmlform-chosen-placeholder": "Pilih satu pilihan",
+       "htmlform-cloner-create": "Tambah lebih",
+       "htmlform-cloner-delete": "Buang",
+       "htmlform-cloner-required": "Sekurang-kurangnya satu nilai diperlukan.",
        "sqlite-has-fts": "$1 dengan sokongan carian teks penuh",
        "sqlite-no-fts": "$1 tanpa sokongan carian teks penuh",
        "logentry-delete-delete": "$1 telah {{GENDER:$2|menghapuskan}} laman $3",
        "logentry-rights-rights": "$1 telah {{GENDER:$2|menukar}} keahlian kumpulan untuk $3 dari $4 ke $5",
        "logentry-rights-rights-legacy": "$1 telah {{GENDER:$2|menukar}} keahlian kumpulan untuk $3",
        "logentry-rights-autopromote": "$1 telah {{GENDER:$2|dinaik pangkat}} secara automatik dari $4 ke $5",
+       "logentry-upload-upload": "$1 telah {{GENDER:$2|muat naik}} $3",
+       "logentry-upload-overwrite": "$1 telah {{GENDER:$2|muat naik}} versi baru $3",
+       "logentry-upload-revert": "$1 telah {{GENDER:$2|muat naik}} $3",
        "rightsnone": "(tiada)",
        "feedback-bugornote": "Jika anda bersedia untuk menerangkan masalah teknikal secara terperinci, sila [$1 laporkan pepijat]. \nAtaupun, anda boleh menggunakan borang yang mudah di bawah. Ulasan anda akan dicatatkan pada laman \"[$3 $2]\", beserta nama pengguna anda dan pelayar yang anda gunakan.",
        "feedback-subject": "Perkara:",
        "expand_templates_remove_nowiki": "Sekat tag <nowiki> dalam hasil",
        "expand_templates_generate_xml": "Papar pepohon hurai XML",
        "expand_templates_generate_rawhtml": "Paparkan HTML mentah",
-       "expand_templates_preview": "Pralihat"
+       "expand_templates_preview": "Pralihat",
+       "pagelanguage": "Pemilih bahasa laman",
+       "pagelang-name": "Laman",
+       "pagelang-language": "Bahasa",
+       "pagelang-use-default": "Gunakan bahasa asli",
+       "pagelang-select-lang": "Pilih bahasa",
+       "right-pagelang": "Mengubah bahasa laman",
+       "action-pagelang": "mengubah bahasa laman",
+       "log-name-pagelang": "Log perubahan bahasa",
+       "log-description-pagelang": "Ini adalah log untuk perubahan-perubahan bahasa laman.",
+       "logentry-pagelang-pagelang": "$1 telah {{GENDER:$2|mengubahkan}} bahasa untuk laman $3 dari $4 ke $5.",
+       "default-skin-not-found": "Whoops! Rupa asli untuk wiki anda (<code>$wgDefaultSkin</code>), <code>$1</code>, tidak disediakan.\n\nPasangan anda kelihatan untuk mempunyai rupa-rupa berikut. Lihat [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual:Skin configuration] untuk maklumat cara membolehkan mereka dan memilih yang asli.\n\n$2\n\n; Jika anda baru sahaja memasang MediaWiki:\n: Anda kemungkinan memasang dari git, atau terus dari kod sumber melalui cara lain. Ini adalah dijangka. Cubalah memasang beberapa rupa dari [https://www.mediawiki.org/wiki/Category:All_skins panduan rupa mediawiki.org], dengan:\n:* Memuat turun [https://www.mediawiki.org/wiki/Download pemasang tarball] yang terlengkap dengan beberapa rupa dan sambungan. Anda boleh menyalin dan menampal direktori <code>skins/</code> terus darinya.\n:* Mengeklon salah satu repositori <code>mediawiki/skins/*</code> melalui git ke dalam direktori <code>skins/</code> pasangan MediaWiki anda.\n: Perbuatan ini tidak patut mengganggu repositori git anda jika anda seorang pembangun MediaWiki.\n\n; Jika anda baru sahaja menaik taraf MediaWiki:\n: MediaWiki 1.24 dan ke atas tidak lagi membolehkan rupa-rupa yang dipasang secara automatik (lihat [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual:Skin autodiscovery]). Anda boleh menampalkan baris-baris berikut ke dalam <code>LocalSettings.php</code> untuk membolehkan semua rupa yang semasa dipasang:\n\n<pre>$3</pre>\n\n; Jika anda baru sahaja mengubah <code>LocalSettings.php</code>:\n: Semakkan lagi nama-nama rupa untuk kesalahan ejaan.",
+       "default-skin-not-found-no-skins": "Whoops! Rupa asli untuk wiki anda (<code>$wgDefaultSkin</code>), <code>$1</code>, tidak disediakan.\n\nAnda tidak mempunyai rupa-rupa yang dipasang.\n\n; Jika anda baru sahaja memasang atau menaik taraf MediaWiki:\n: Anda kemungkinan memasang dari git, atau terus dari kod sumber melalui cara lain. Ini adalah dijangka. MediaWiki 1.24 dan ke atas tidak memasuki sebarang rupa dalam repositori utama. Cubalah memasang beberapa rupa dari [https://www.mediawiki.org/wiki/Category:All_skins panduan rupa mediawiki.org], dengan:\n:* Memuat turun [https://www.mediawiki.org/wiki/Download pemasang tarball] yang terlengkap dengan beberapa rupa dan sambungan. Anda boleh menyalin dan menampal direktori <code>skins/</code> terus darinya.\n:* Mengeklon salah satu repositori <code>mediawiki/skins/*</code> melalui git ke dalam direktori <code>skins/</code> pasangan MediaWiki anda.\n: Perbuatan ini tidak patut mengganggu repositori git anda jika anda seorang pembangun MediaWiki. Lihat [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual:Skin configuration] untuk maklumat cara membolehkan mereka dan memilih yang asli.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (dibolehkan)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''dimatikan''')"
 }
index d707821..1f9e32a 100644 (file)
        "talkpagelinktext": "Diskussjoni",
        "specialpage": "Paġna speċjali",
        "personaltools": "Għodda personali",
-       "postcomment": "Sezzjoni ġdida",
        "articlepage": "Ara l-artiklu",
        "talk": "Diskussjoni",
        "views": "Veduti",
        "jumptonavigation": "navigazzjoni",
        "jumptosearch": "fittex",
        "view-pool-error": "Jiddispjaċina, imma fil-mument is-servers jinsabu mgħobbija ż-żejjed.\nĦafna utenti qegħdin jippruvaw jaraw din il-paġna.\nJekk jogħġbok stenna ftit qabel ma terġa' tipprova tuża' din il-paġna.\n\n$1",
+       "generic-pool-error": "Jiddispjaċina, imma bħalissa is-servers jinsabu mgħobbija ż-żejjed.\nĦafna utenti qegħdin jippruvaw jaraw din ir-riżorsa.\nJekk jogħġbok stenna ftit qabel ma terġa' tipprova ttella' din ir-riżorsa.",
+       "pool-timeout": "Il-ħin tal-iskadenza qiegħed jistenna l-iżblokk.",
        "pool-queuefull": "Il-kju tal-''pool'' hi mimlija",
        "pool-errorunknown": "Problema mhux magħrufa",
+       "pool-servererror": "Is-servizz kontra l-pool mhux disponibbli ($1).",
        "aboutsite": "Dwar {{SITENAME}}",
        "aboutpage": "Project:Dwar",
-       "copyright": "Kontenut aċċessibli taħt $1.",
+       "copyright": "Il-kontenut huwa disponibbli taħt il-liċenzja $1 sakemm mhux indikat mod ieħor.",
        "copyrightpage": "{{ns:project}}:Copyright",
        "currentevents": "Ġrajjiet kurrenti",
        "currentevents-url": "Project:Ġrajjiet kurrenti",
        "ok": "OK",
        "retrievedfrom": "Miġjub minn \"$1\"",
        "youhavenewmessages": "Għandek $1 ($2).",
+       "youhavenewmessagesfromusers": "Għandek $1 minn {{PLURAL:$3|utent ieħor|$3utenti oħra}} ($2).",
        "youhavenewmessagesmanyusers": "Għandek $1 mingħand ħafna utenti ($2).",
-       "newmessageslinkplural": "{{PLURAL:$1|messaġġ ġdid|messaġġi ġodda}}",
-       "newmessagesdifflinkplural": "l-aħħar {{PLURAL:$1|bidla|bidliet}}",
+       "newmessageslinkplural": "{{PLURAL:$1|messaġġ ġdid|999=messaġġi ġodda}}",
+       "newmessagesdifflinkplural": "l-aħħar {{PLURAL:$1|bidla|999=bidliet}}",
        "youhavenewmessagesmulti": "Għandek messaġġi ġodda fuq $1",
        "editsection": "editja",
        "editold": "editja",
        "nospecialpagetext": "<strong>Inti għamilt rikjesta għal paġna speċjali invalida.</strong>\n\nLista ta' paġni speċjali validi tinsab hawn [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Problema",
        "databaseerror": "Problema fid-database",
+       "databaseerror-text": "Sar żball f'kunsltazzjoni tal-bażi tad-dejta. Dan jista' jindika difett fis-softwer.",
+       "databaseerror-textcl": "Sar żball f'kunsultazzjoni tal-bażi tad-dejta.",
+       "databaseerror-query": "Kunsultazzjoni $1",
+       "databaseerror-function": "Funzjoni:$1",
+       "databaseerror-error": "Żball:$1",
        "laggedslavemode": "Twissija: Il-Paġna jista' ma jkollhiex l-affarijiet aġġornati.",
        "readonly": "Database magħluq",
        "enterlockreason": "Daħħal raġuni għala qiegħed tagħlqu, inkludi l-istima ta' meta l-għeluq se tieħu effett",
        "badarticleerror": "Din l-azzjoni ma setgħetx isseħħ fuq din il-paġna.",
        "cannotdelete": "Il-paġna jew il-fajl \"$1\" ma jistax jiġi mħassar.\nJista' jkun li diġà ġie mħassar minn xi ħaddieħor.",
        "cannotdelete-title": "Il-paġna \"$1\" ma setgħetx titħassar",
+       "delete-hook-aborted": "Il-modifika ġiet abbandunata mill-''hook''.\nMa ngħatat l-ebda spjegazzjoni.",
+       "no-null-revision": "Ma setghitx tinħoloq reviżjoni nulla ġdida għall-paġna \"$1\"",
        "badtitle": "Titlu ħażin",
        "badtitletext": "It-titlu tal-paġna rikjesta huwa invalidu, vojt, jew ġej minn żball fil-ħolqa bejn siti wiki differenti jew verżjonijiet ta' lingwi differenti tal-istess sit. Jista' wkoll ikollu wieħed jew aktar karattri li ma jistgħux jintużaw għat-titli.",
        "perfcached": "L-informazzjoni li jmiss huwa kopja ''cache'' u jista' ma jkunx aġġornat. A maximum of {{PLURAL:$1|one result is|$1 results are}} available in the cache.",
        "namespaceprotected": "Inti m'għandhekx il-permess li timodifika paġni fin-''namespace'' '''$1''.",
        "customcssprotected": "M'għandekx il-permessi neċessarji sabiex timmodifika din il-paġna tas-CSS, minħabba li għandha tqegħid personali ta' utent ieħor.",
        "customjsprotected": "M'għandekx il-permessi neċessarji sabiex timmodifika din il-paġna tal-JavaScript, minħabba li għandha tqegħid personali ta' utent ieħor.",
+       "mycustomjsprotected": "Ma għandekx permess li teditja din il-paġna JavaScript.",
+       "myprivateinfoprotected": "Ma għandekx permess li teditja l-informazzjoni privata tiegħek.",
+       "mypreferencesprotected": "Ma għandekx permess li teditja l-preferenzi tiegħek.",
        "ns-specialprotected": "Il-paġni speċjali ma jistgħux jiġu mmodifikati.",
        "titleprotected": "Dan it-titlu ġie protett mill-ħolqien minn [[User:$1|$1]].\nIr-raġuni li ġiet mogħtija kienet ''$2''.",
+       "filereadonlyerror": "L-amministratur li sakkar offra din l-ispjegazzjoni: \"$3\".",
+       "invalidtitle-knownnamespace": "Titolu validu bin-namespace \"$2\" u t-test\"$3\"",
+       "invalidtitle-unknownnamespace": "Titolu validu b'numru tan-namespace mhux magħruf  $1 u t-test \"$2\"",
+       "exception-nologin": "Mhux qiegħed fil-kont",
+       "exception-nologin-text": "Jekk jogħġbok [[Special:Userlogin|idħol fil-kont tiegħek]] biex tkun tista' taċċessa din il-paġna jew din l-azzjoni.",
+       "exception-nologin-text-manual": "Jekk jogħġbok $1 sabiex tkuu tista' taċċessa din il-paġna jew din l-azzjoni.",
        "virus-badscanner": "Problema fil-konfigurazzjoni: antivirus mhux magħruf: ''$1''",
        "virus-scanfailed": "Tfittxija falliet (kodiċi $1)",
        "virus-unknownscanner": "antivirus mhux magħruf:",
-       "logouttext": "'''Bħalissa tinsab barra mill-kont tiegħek.'''\n\nTista' tkompli tuża' {{SITENAME}} bħala utent anonimu, jew tista' terġa <span class='plainlinks'>[$1 tidħol]</span> bħala l-istess utent jew wieħed differenti.\nKun af li ċerti paġni jistgħu jkomplu jidhru bħallikieku l-illogjar 'l barra mill-kont qatt ma seħħ, sakemm ma tħassarx il-cache tal-browser.",
+       "logouttext": "<strong>Bħalissa mhux qiegħed fil-kont tiegħek</strong>\n\nJista' jkun li xi paġni jibqgħu jidhru bħalli kieku qiegħed fil-kont, sakemm ma tneddafx il-cache tan-navigatur tiegħek.",
+       "welcomeuser": "Merħba, $1!",
+       "welcomecreation-msg": "Il-kont tiegħek inħoloq.\nJekk trid tista' tibdel il- [[Special:Preferences|preferenzi tas-]]{{SITENAME}}.",
        "yourname": "Isem l-utent:",
        "userlogin-yourname": "Isem l-utent",
        "userlogin-yourname-ph": "Daħħal isem l-utent tiegħek",
+       "createacct-another-username-ph": "Daħħal l-isem tiegħek ta' utent",
        "yourpassword": "Password:",
        "userlogin-yourpassword": "Password",
        "userlogin-yourpassword-ph": "Daħħal il-password tiegħek",
        "userlogin-remembermypassword": "Żommni fil-kont",
        "userlogin-signwithsecure": "Uża konnessjoni sigura",
        "yourdomainname": "Id-dominju tiegħek:",
+       "password-change-forbidden": "Fuq din il-wiki ma tistax tibdel il-kliem tad-dħul (passwords).",
        "externaldberror": "Kien hemm problema esterna ta' awtentiċitá jew m'għandhekx permess neċċessarju sabiex tagħmel aġġornamenti fuq l-aċċess estern.",
        "login": "Idħol",
        "nav-login-createaccount": "Idħol / Oħloq kont",
-       "loginprompt": "Irid ikollok il-cookies mixgħula biex tkun tista' tidħol fuq {{SITENAME}}.",
        "userlogin": "Idħol jew oħloq kont ġdid",
        "userloginnocreate": "Idħol",
        "logout": "Oħroġ",
        "gotaccount": "Diġa għandhek kont? '''$1'''.",
        "gotaccountlink": "Idħol",
        "userlogin-resetlink": "Insejt kif tidħol fil-kont tiegħek?",
-       "userlogin-resetpassword-link": "Irrisettja l-password",
+       "userlogin-resetpassword-link": "Insejt il-kelma tad-dħul (password)?",
+       "userlogin-helplink2": "Għajnuna biex tidħol fil-kont",
        "createacct-emailrequired": "Indirizz elettroniku",
        "createacct-emailoptional": "Indirizz elettroniku (mhux obbligatorju)",
        "createacct-email-ph": "Daħħal l-indirizz elettroniku tiegħek",
-       "createaccountmail": "Uża password każwali temporanja u ibgħatha fuq l-indirizz elettroniku mniżżel hawn taħt",
+       "createacct-another-email-ph": "Daħħal l-indirizz elettroniku",
+       "createaccountmail": "Uża kelma tad-dħul temporanja li tkun u ibgħatha lill-indirizz elettroniku speċifikat",
        "createacct-realname": "Isem proprju (fakultattiv)",
        "createaccountreason": "Raġuni:",
        "createacct-reason": "Raġuni",
        "createacct-captcha": "Kontroll tas-sigurtà",
        "createacct-imgcaptcha-ph": "Daħħal it-test li qed tara hawn fuq",
        "createacct-submit": "Oħloq il-kont",
+       "createacct-another-submit": "Oħloq kont ieħor",
        "createacct-benefit-heading": "{{SITENAME}} hi magħmula minn persuni bħalek.",
        "createacct-benefit-body1": "{{PLURAL:$1|modifika|modifiki}}",
-       "createacct-benefit-body2": "paġna",
+       "createacct-benefit-body2": "{{PLURAL:$1|paġna|paġni}}",
        "createacct-benefit-body3": "{{PLURAL:$1|kontributur|kontributuri}} riċenti",
        "badretype": "Il-passwords li daħħalt ma jaqblux.",
        "userexists": "L-isem l-utent li daħħalt diġà meħud. Jekk jogħġbok, agħżel isem differenti.",
        "passwordtooshort": "Il-password trid tkun mill-inqas {{PLURAL:$1|karattru|$1 karattri}} twila u differenti mill-isem tal-utent.",
        "password-name-match": "Il-password trid tkun differenti mill-isem tal-utent tiegħek.",
        "password-login-forbidden": "L-użu ta' dan l-isem tal-utent u l-password huwa projbit.",
-       "mailmypassword": "Ibgħatli password ġdida",
+       "mailmypassword": "Erġa' waqqaf kelma tad-dħul",
        "passwordremindertitle": "Password temporanju ġdid għal {{SITENAME}}",
        "passwordremindertext": "Xi ħadd (probabbilment int, mill-indirizz IP $1) għamel rikjesta għal password ġdida għal {{SITENAME}} ($4). Password temporanja għall-utent \"$2\" ġiet maħluqa u din hi \"$3\".\nHuwa opportun li inti tidħol issa u tbiddel immedjatament il-password tiegħek. Din il-password il-ġdida se tiskadi fi żmien {{PLURAL:$5|ġurnata|$5 ijiem}}.\n\nJekk xi ħadd ieħor għamel din ir-rikjesta jew jekk int ftakart il-password tiegħek u issa ma tridx tbiddilha, int tista' ma tagħtix każ dan il-messaġġ u tkompli tuża' l-password l-antika.",
        "noemail": "M'hemm l-ebda indirizz ta' posta elettronika għall-utent \"$1\".",
        "noemailcreate": "Huwa neċessarju li tipprovdi indirizz elettroniku validu",
        "passwordsent": "Il-password il-ġdida ntbagħtet fl-indirizz tal-posta elettronika ta' \"$1\".\nJekk jogħġbok, għamel aċċess wara li tasallek.",
        "blocked-mailpassword": "L-indirizz tal-IP tiegħek huwa bblokkjat u miżmum milli jwettaq modifiki. Għaldaqstant, mhuwiex possibli għalik li tuża l-funzjoni sabiex iġġib lura l-password, u dan sabiex ma jkunx hemm abbużi.",
-       "eauthentsent": "Intbagħat messaġġ ta' konferma b'permezz tal-posta elettronika lejn l-indirizz indikat.<br />\nQabel xi posta elettronika oħra tiġi mibgħuta fuq il-kont, trid qabel xejn tesegwixxi l-istruzzjonijiet kif inhuma indikati, sabiex tikkonferma li l-kont huwa tassew tiegħek.",
+       "eauthentsent": "Intbagħtetlek konferma b'permezz ta' messaġġ elettroniku fl-indirizz speċifikat.\nQabel ma tinbagħat xi posta elettronika oħra fuq il-kont, trid issegwi l-istruzzjonijiet indikati fil-messaġġ, sabiex tikkonferma li l-kont huwa tassew tiegħek.",
        "throttled-mailpassword": "Posta elettronika sabiex tfakrek il-password ġiet postjata, fl-aħħar {{PLURAL:$1|siegħa|$1 siegħat}}.\nSabiex jitnaqqas l-abbuż, waħda biss tista' tiġi postjata f'kull {{PLURAL:$1|siegħa|$1 siegħat}}.",
        "mailerror": "Problema bil-postar tal-messaġġ: $1",
        "acct_creation_throttle_hit": "L-utenti ta' din il-wiki li jużaw l-indirizz IP tiegħek ħolqu {{PLURAL:$1|kont|$1 kontijiet}} fl-aħħar ġurnata, li hu n-numru massimu permess f'dan il-perjodu ta' żmien.\nBħala riżultat, il-viżitaturi li jużaw dan l-IP ma jistgħux għall-mument, joħoloqu aktar kontijiet.",
        "login-abort-generic": "Il-login ma kienx suċċess - Imħassar",
        "loginlanguagelabel": "Lingwa: $1",
        "suspicious-userlogout": "Ir-rikjesta tiegħek li toħroġ barra mill-kont tiegħek ġiet miċħuda minħabba li jidher li din intbagħtet minn browser li ma jaħdimx jew minn proxy ta' caching.",
+       "pt-login": "Idħol",
+       "pt-login-button": "Idħol",
+       "pt-createaccount": "Oħloq kont",
+       "pt-userlogout": "Oħroġ",
        "php-mail-error-unknown": "Żball mhux magħruf fil-funzjoni mail() tal-PHP.",
        "user-mail-no-addy": "Pruvajt tibgħat posta elettronika mingħajr indirizz.",
+       "user-mail-no-body": "Ippruvajt tibgħat ittra elettronika b'kontenut vojt jew qasir wisq.",
        "changepassword": "Ibdel il-password",
-       "resetpass_announce": "L-aċċess ġe effetwat permezz ta' kodiċi temporanju, li ntbagħat permezz tal-posta elettronika.\nBiex tkompli l-aċċess tal-kont tiegħek huwa neċessarju li toħloq password ġdida hawnhekk:",
+       "resetpass_announce": "Biex ittemm id-dħul fil-kont tiegħek, jeħtieġ li tissettja password ġdida.",
        "resetpass_text": "<!-- Żied il-kliem hawnhekk -->",
        "resetpass_header": "Biddel il-password tal-kont",
        "oldpassword": "Password antika:",
        "newpassword": "Password ġdida:",
        "retypenew": "Erġa' ikteb il-password il-ġdida:",
        "resetpass_submit": "Issettja l-password u idħol fis-sit",
-       "changepassword-success": "Il-password ġie modifikat. Aċċess fil-proċess...",
+       "changepassword-success": "Il-password inbidlet korrettament!",
+       "changepassword-throttled": "Ippruvajt tidħol wisq drabi.\nJekk jogħġbok stenna $1 qabel ma terġa' tipprova.",
        "resetpass_forbidden": "Mhuwiex possibbli li timmodifika l-passwords",
        "resetpass-no-info": "Trid tkun effetwajt il-login qabel ma taċċessa direttament din il-paġna.",
        "resetpass-submit-loggedin": "Biddel il-password",
        "resetpass-submit-cancel": "Annulla",
        "resetpass-wrong-oldpass": "Password temporanja jew kurrenti invalida.\nJista' jkun li int diġà biddilt il-password, jew għamilt rikjesta għal password temporanja ġdida.",
+       "resetpass-recycled": "Jekk jogħġbok erġa' ssettja l-password għal xi ħaġa oħra li mhijiex il-password li għandek bħalissa.",
+       "resetpass-temp-emailed": "Dħalt b'kodiċi temporanju mibgħut elettronikament.\nBiex ittem id-dħul, jeħtieġ li tissettja password ġdida hawn:",
        "resetpass-temp-password": "Password temporanja:",
+       "resetpass-abort-generic": "Estensjoni ħassret il-bidla tal-password",
+       "resetpass-expired": "Il-password skadiet. Jekk jogħġbok issettja password ġdida biex tidħol.",
+       "resetpass-expired-soft": "Il-password skadiet u jeħtieġ li terġa' tissettjaha. Agħżel password ġdida issa, jew ikklikkja \"{{int:resetpass-tissottometti-tikkanċella}}\" biex tissettjaha aktar tard.",
+       "resetpass-validity-soft": "Il-password tiegħek mhijiex valida $1 \n\nAgħżel password ġdida issa, jew ikklikkja \"{{int:resetpass-submit-cancel}}\" biex tibdilha dan aktar.",
        "passwordreset": "Irrisettja l-password",
        "passwordreset-text-one": "Imla din il-formola sabiex tirrisettja l-password.",
+       "passwordreset-text-many": "{{PLURAL:$1|Imla wieħed mill-oqsma biex tirċievi password temporanja permezz ta' ittra elettronika.}}",
        "passwordreset-legend": "Irrisettja l-password",
        "passwordreset-disabled": "L-irrisettjar tal-password fuq din il-wiki ġie diżattivat.",
+       "passwordreset-emaildisabled": "Karatteristiċi tal-posta elettronika ġew diżattivati fuq din il-wiki.",
        "passwordreset-username": "Isem l-utent:",
        "passwordreset-domain": "Dominju:",
        "passwordreset-capture": "Ara l-kontenut tal-messaġġ?",
        "passwordreset-email": "Indirizz elettroniku:",
        "passwordreset-emailtitle": "Dettalji tal-kont fuq {{SITENAME}}",
        "passwordreset-emailtext-ip": "Xi ħadd (probabbilment int, mill-indirizz IP $1) għamel rikjesta sabiex jingħata password ġdida sabiex jaċċessa l-{{SITENAME}} ($4). L-{{PLURAL:$3|utent assoċjat|utenti assoċjati}} ma' dan l-indirizz elettroniku {{PLURAL:$3|huwa|huma}}:\n\n$2\n\n{{PLURAL:$3|Din il-password temporanja se tiskadi|Dawn il-passwords temporanji se jiskadu}} fi żmien {{PLURAL:$5|ġurnata|$5 jum}}. Inti għadek tidħol fil-kont tiegħek u tagħżel password ġdida issa. Jekk xi ħadd ieħor għamel din ir-rikjesta, jew jekk ftakart il-password oriġinali, u m'għadekx trid tbiddilha, inti tista' tinjora dan il-messaġġ u tibqa' tuża' l-password il-qadima.",
-       "passwordreset-emailtext-user": "L-utent $1 fuq {{SITENAME}} għamel rikjesta sabiex jingħata password ġdida sabiex jaċċessa l-{{SITENAME}} ($4). {{PLURAL:$3|L-utent assoċjat|L-utenti assoċjati}} ma' dan l-indirizz elettroniku huma:\n\n$2\n\n{{PLURAL:$3|Din il-password temporanja se tiskadi|Dawn il-passwords temporanji se jiskadu}} fi żmien {{PLURAL:$5|ġurnata|$5 jum}}. Inti għadek tidħol fil-kont tiegħek u tagħżel password ġdida issa. Jekk xi ħadd ieħor għamel din ir-rikjesta, jew jekk ftakart il-password oriġinali, u m'għadikx trid tbiddilha, inti tista' tinjora dan il-messaġġ u tibqa' tuża' l-password il-qadima.",
+       "passwordreset-emailtext-user": "{{PLURAL:$3|Din il-password temporanja se tiskadi|Dawn il-passwords temporanji se jiskadu}} fi żmien {{PLURAL:$5|ġurnata|$5 jum}}. Inti għadek tidħol fil-kont tiegħek u tagħżel password ġdida issa. Jekk xi ħadd ieħor għamel din ir-rikjesta, jew jekk ftakart il-password oriġinali, u m'għadikx trid tbiddilha, inti tista' tinjora dan il-messaġġ u tibqa' tuża' l-password il-qadima.",
        "passwordreset-emailelement": "Isem tal-utent: $1\nPassword temporanja: $2",
-       "passwordreset-emailsent": "Intbagħtet ittra-e bħala tfakkira.",
-       "passwordreset-emailsent-capture": "Intbagħtet ittra-e bħala tfakkira, bil-kontenut jidher hawn taħt.",
+       "passwordreset-emailsent": "Intbagħtet ittra-e għall-issettjar mill-ġdid tal-password.",
+       "passwordreset-emailsent-capture": "Intbagħtet ittra-e għall-ssettjar mill-ġdid tal-password u l-kontenut jidher hawn taħt.",
        "passwordreset-emailerror-capture": "Ġiet ġenerata ittra-e ta' tfakkira, li l-kontenut tagħha jidher hawn taħt. Madanakollu, il-posta ma ntbagħtitx lill-utent: $1",
        "changeemail": "Biddel l-indirizz elettroniku",
        "changeemail-header": "Biddel l-indirizz elettroniku tal-kont",
        "changeemail-oldemail": "Indirizz elettroniku attwali:",
        "changeemail-newemail": "Indirizz elettroniku ġdid:",
        "changeemail-none": "(xejn)",
+       "changeemail-password": "Il-password tiegħek fuq {{SITENAME}}:",
        "changeemail-submit": "Biddel l-indirizz elettroniku",
        "changeemail-cancel": "Annulla",
+       "changeemail-throttled": "Ippruvajt tidħol wisq drabi.\nJekk jogħġbok stenna $1 qabel ma terġa' tipprova.",
+       "resettokens": "Irrisettja t-tokens",
        "bold_sample": "Tipa ħoxna",
        "bold_tip": "Tipa ħoxna",
        "italic_sample": "Tipa korsiva",
        "preview": "Dehra proviżorja",
        "showpreview": "Dehra proviżorja",
        "showdiff": "Uri t-tibdiliet",
-       "anoneditwarning": "'''Twissija:''' Ma rnexxilekx tidħol.\nL-indirizz tal-IP tiegħek se jiġi reġistrat fil-kronoloġija tal-modifikar ta' din il-paġna.",
+       "anoneditwarning": "'''Attenzjoni:''' Ma dħaltx f'kontok.\nL-indirizz tal-IP tiegħek se jkun jidher pubblikament meta tagħmel xi modifika. Jekk <strong>[$1 tidħol f'kontok]</strong> jew <strong>[$2 toħloq kont]</strong>, il-modifiki li tagħmel jiġu attribwiti lill-ismek ta' utent, flimkien ma benefiċċji oħra.",
        "anonpreviewwarning": "''Bħalissa mintix fil-kont tiegħek. Jekk issalva xi modifiki tiegħek, fil-kronoloġija tal-paġna se jiġi reġistrat l-indirizz IP tiegħek.''",
        "missingsummary": "'''Twissija:''' Ma pprovdejt l-ebda taqsira dwar il-modifika.\nJekk terġa' tagħfas Modifika, l-modifika se tiġi salvata mingħajr waħda.",
        "missingcommenttext": "Jekk jogħġbok ħalli kumment hawn taħt.",
        "searchprofile-advanced-tooltip": "Fittex fi spazji tal-isem personalizzati",
        "search-result-size": "$1 ({{PLURAL:$2|1 word|$2 kliem}})",
        "search-result-category-size": "{{PLURAL:$1|membru wieħed|$1 membri}} ({{PLURAL:$2|sottokategorija waħda|$2 sottokategoriji}}, {{PLURAL:$3|fajl wieħed|$3 fajls}})",
-       "search-result-score": "Relevanza: $1%",
        "search-redirect": "(rindirizza $1)",
        "search-section": "(sezzjoni $1)",
        "search-suggest": "Trid tfisser: $1",
        "action-writeapi": "tuża' l-API fil-ktiba",
        "action-delete": "ħassar din il-paġna",
        "action-deleterevision": "ħassar din ir-reviżjoni",
-       "action-deletedhistory": "ara l-kronoloġija mħassar ta' din il-paġna",
+       "action-deletedhistory": "ara l-kronoloġija mħassra ta' din il-paġna",
        "action-browsearchive": "fittex paġni mħassra",
        "action-undelete": "irkupra din il-paġna",
        "action-suppressrevision": "tirrevedi u treġġa' din ir-reviżjoni moħbija",
        "uploadwarning": "Twissija dwar it-tlugħ tal-fajls",
        "uploadwarning-text": "Jekk jogħġbok immodifika hawn taħt id-deskrizzjoni tal-fajl u pprova mill-ġdid.",
        "savefile": "Salva l-fajl",
-       "uploadedimage": "tella' \"[[$1]]\"",
-       "overwroteimage": "Verżjoni ġdida ġiet imtella' \"[[$1]]\"",
        "uploaddisabled": "Skuzana, però ''uploads'' ta' fajls huwa temporalment sospiż.",
        "copyuploaddisabled": "It-tlugħ mill-URL huwa diżattivat.",
        "uploaddisabledtext": "It-tlugħ ta' fajls mhuwiex attiv.",
        "filehist-comment": "Kumment",
        "imagelinks": "Użu tal-fajl",
        "linkstoimage": "{{PLURAL:$1|Il-Paġna segwenti għandha|Il-$1 paġni segwenti għandhom}} links għal-fajl:",
-       "linkstoimage-more": "Iktar minn {{PLURAL:$1|paġna torbot|$1paġni jorbtu}} lejn dan il-fajl.\nIl-lista segwenti turi {{PLURAL:$1|l-ewwel paġna li tipponta|l-ewwel $1 paġni li jippuntaw}} lejn dan il-fajl.\n[[Special:WhatLinksHere/$2|Lista sħiħa]] hija disponibbli.",
+       "linkstoimage-more": "Aktar minn {{PLURAL:$1|paġna torbot|$1paġni jorbtu}} lejn dan il-fajl.\nIl-lista segwenti turi {{PLURAL:$1|l-ewwel paġna li tipponta|l-ewwel $1 paġni li jippuntaw}} lejn dan il-fajl.\n[[Special:WhatLinksHere/$2|Lista sħiħa]] hija disponibbli.",
        "nolinkstoimage": "M'hemmx paġni li huma relatati ma' dan il-fajl.",
        "morelinkstoimage": "Uri [[Special:WhatLinksHere/$1|aktar links]] għal dan il-fajl.",
        "linkstoimage-redirect": "$1 (rindirizz tal-fajl) $2",
        "sp-deletedcontributions-contribs": "kontribuzzjonijiet",
        "linksearch": "Fittex ħoloq esterni",
        "linksearch-pat": "Mudell ta' tfittxija:",
-       "linksearch-ns": "Spazju tal-isem:",
+       "linksearch-ns": "Spazju tal-ismijiet:",
        "linksearch-ok": "Fittex",
        "linksearch-text": "Tista' tagħmel użu minn metakarattri, per eżempju \"*.wikipedia.org\".<br />\nHuwa neċessarju minn tal-inqas dominju tal-ewwel livell, per eżempju \"*.org\".<br />\nProtokolli aċċettati: <code>$1</code> (jekk ma jiġi speċifikat l-ebda protokol, dan jiġi awtomatikament definit bħala http://).",
        "linksearch-line": "$1 hija marbuta mill-paġna $2",
        "watchlist-details": "Il-lista ta' osservazzjoni fiha {{PLURAL:$1|paġna waħda (u l-paġna ta' diskussjoni tagħha)|$1 paġni (u l-paġni ta' diskussjoni tagħhom)}}.",
        "wlheader-enotif": "In-notifikazzjoni bl-użu tal-posta elettronika hija attivata.",
        "wlheader-showupdated": "Il-paġni li ġew editjati wara l-aħħar żjara tiegħek qed jiġu murija b'tipa '''ħoxna'''",
+       "wlnote": "Hawn taħt hawn {{PLURAL:$1|l-aħħar modifika|l-aħħar '''$1''' modifiki}} fl-aħħar {{PLURAL:$2|siegħa|'''$2''' siegħat}}, sal-$3, fil-$4.",
        "wlshowlast": "Uri l-aħħar $1 siegħat $2 ġranet $3",
        "watchlist-options": "Opzjonijiet tal-lista ta' osservazzjoni",
        "watching": "Imsegwi...",
        "undelete-error-long": "Kien hemm problemi waqt il-fajl kien qiegħed jiġi rkuprat:\n\n$1",
        "undelete-show-file-confirm": "Inti ċert li trid tara reviżjoni imħassra tal-fajl \"<nowiki>$1</nowiki>\" ta' nhar $2, fil-ħin ta' $3?",
        "undelete-show-file-submit": "Iva",
-       "namespace": "Spazju tal-isem:",
+       "namespace": "Spazju tal-ismijiet:",
        "invert": "Aqleb l-għażla",
        "tooltip-invert": "Agħżel din il-kaxxa biex taħbi l-modifiki lejn paġni li jinsabu fl-ispazji tal-isem magħżula (u l-ispazju tal-isem assoċjat jekk hu magħżul)",
-       "namespace_association": "Spazju tal-isem assoċjat",
+       "namespace_association": "Spazju tal-ismijiet assoċjat",
        "tooltip-namespace_association": "Agħżel din il-kaxxa sabiex tinkludi l-paġna ta' diskussjoni jew l-oġġett tal-ispazju tal-isem assoċjat mal-ispazju tal-isem magħżul",
        "blanknamespace": "(Prinċipali)",
        "contributions": "Kontributi tal-{{GENDER:$1|utent}}",
        "import": "Importa paġni",
        "importinterwiki": "Importazzjoni transwiki",
        "import-interwiki-text": "Agħżel wiki u titlu ta' paġna li se timporta.\nDati ta' reviżjonijiet u ismijiet tal-modifikaturi jiġu preservati.\nKull azzjonijiet ta' importazzjoni tal-transwiki jiġu reġistrati fil-[[Special:Log/import|log ta' importazzjoni]].",
-       "import-interwiki-source": "Sors tal-wiki/paġna:",
        "import-interwiki-history": "Kopja l-verżjonijiet tal-kronoloġija kollha għal din il-paġna",
        "import-interwiki-templates": "Inkludi l-mudelli kollha",
        "import-interwiki-submit": "Importa",
        "exif-copyright": "Informazzjoni dwar il-propjetá letterarja",
        "exif-exifversion": "Verżjoni tal-format Exif",
        "exif-flashpixversion": "Verżjoni sapportata ta' Flashpix",
-       "exif-colorspace": "Spazju tal-kulur",
+       "exif-colorspace": "Spazju tal-kuluri",
        "exif-componentsconfiguration": "Tfissira dwar kull komponent",
        "exif-compressedbitsperpixel": "Għamla tal-kompressjoni tal-istampa",
        "exif-pixelydimension": "Wisa' tal-istampa",
        "exif-lightsource": "Sorġent tad-dawl",
        "exif-flash": "Flash",
        "exif-focallength": "Distanza fokali objettiva",
-       "exif-subjectarea": "Spazju tas-suġġett",
+       "exif-subjectarea": "Spazju tas-suġġetti",
        "exif-flashenergy": "Saħħa tal-flash",
        "exif-focalplanexresolution": "Riżoluzzjoni X fuq il-witja fokali",
        "exif-focalplaneyresolution": "Riżoluzzjoni Y fuq il-witja fokali",
index 7ad868f..3e81d22 100644 (file)
        "talkpagelinktext": "Cumbersar",
        "specialpage": "Páigina special",
        "personaltools": "Ferramientas pessonales",
-       "postcomment": "Nuobo cacho",
        "articlepage": "Ber páigina de cuntenido",
        "talk": "Çcusson",
        "views": "Besitas",
        "yourdomainname": "L tou domínio",
        "login": "Antrar",
        "nav-login-createaccount": "Antrar / criar cuonta",
-       "loginprompt": "Tenes que tener ls <i>cookies</i> atibos para te outenticares an{{SITENAME}}.",
        "userlogin": "Antrar / criar cuonta",
        "logout": "Salir",
        "userlogout": "Salir",
        "filesource": "Fuonte:",
        "ignorewarnings": "Eignorar qualquiera abiso",
        "savefile": "Grabar fexeiro",
-       "uploadedimage": "cargou \"[[$1]]\"",
        "watchthisupload": "Begiar este fexeiro",
        "upload-curl-error28": "Ultrapassado l tiempo lhemite pa l ambio de l fexeiro",
        "license": "Lhicença:",
index ed24060..6620607 100644 (file)
        "talkpagelinktext": "ဆွေးနွေးရန်",
        "specialpage": "အထူး စာမျက်နှာ",
        "personaltools": "ကိုယ်ပိုင် ကိရိယာများ",
-       "postcomment": "အပိုင်းသစ်",
        "articlepage": "မာတိကာ ကြည့်ရန်",
        "talk": "ဆွေးနွေးချက်များ",
        "views": "ပုံပန်းသွင်ပြင်",
        "yourdomainname": "သင့်ဒိုမိန်း -",
        "login": "Log in ဝင်ရန်",
        "nav-login-createaccount": "Log in ဝင်ရန်/ အကောင့် လုပ်ရန်",
-       "loginprompt": "{{SITENAME}} သို့ လော့အင်ဝင်ရန် ကွတ်ကီးသုံးနိုင်ရန် ပြုလုပ်ပေးထားရမည်။",
        "userlogin": "Log in ဝင်ရန်/ အကောင့် လုပ်ရန်",
        "userloginnocreate": "Log in ဝင်ရန်",
        "logout": "ထွက်ရန်",
        "searchprofile-advanced-tooltip": "စိတ်ကြိုက်အမည်ညွှန်းများတွင် ရှာရန်",
        "search-result-size": "$1 ({{PLURAL:$2|စကားလုံး 1 လုံး|စကားလုံး $2 လုံး}})",
        "search-result-category-size": "{{PLURAL:$1|အသင်းဝင်တစ်ခု|အသင်းဝင် $1 ခု}} ({{PLURAL:$2|ကဏ္ဍခွဲတစ်ခု|ကဏ္ဍခွဲ $2 ခု}}, {{PLURAL:$3|ဖိုင်တစ်ခု|ဖိုင် $3 ခု}})",
-       "search-result-score": "ကိုက်ညီမှုရာနှုန်း - $1%",
        "search-redirect": "($1 သို့ ပြန်ညွှန်းသည်)",
        "search-section": "(အပိုင်း $1)",
        "search-suggest": "$1 ဟု ဆိုလိုပါသလား။",
        "largefileserver": "ဤဖိုင်သည် ဆာဗာတွင် ခွင့်ပြုရန်သတ်မှတ်ထားသော ဖိုင်အရွယ်အစားထက် ကြီးနေသည်။",
        "uploadwarning": "Upload တင်ရာတွင် သတ်ပေးချက်",
        "savefile": "ဖိုင်သိမ်းရန်",
-       "uploadedimage": "\"[[$1]]\" ပုံကို တင်ပြီးပြီဖြစ်သည်",
-       "overwroteimage": "\"[[$1]]\" ၏ မူသစ်ကို upload တင်လိုက်ပြီ",
        "uploaddisabled": "Upload တင်ခြင်း ပိတ်ထားသည်။",
        "copyuploaddisabled": "URL လင့်မှ Upload တင်ခြင်း ပိတ်ထားသည်။",
        "uploaddisabledtext": "ဖိုင်တင်ခြင်းများကို ပိတ်ထားသည်။",
index 4c29381..c280363 100644 (file)
        "returnto": "Велявтомс $1 лопантень.",
        "tagline": "{{SITENAME}} -нь пельде",
        "help": "Лезкс",
-       "search": "Вешнэмс",
-       "searchbutton": "Вешнэк",
+       "search": "Вешнемс",
+       "searchbutton": "Вешнек",
        "go": "Адя",
        "searcharticle": "Адя",
        "history": "Лопань полавтнемат - витнемат",
        "delete": "Нардамс",
        "deletethispage": "Нардамс те лопанть",
        "undeletethispage": "Вельмевтемс мекев те лопанть",
-       "undelete_short": "Велявтомс нардазенть {{PLURAL:$1|1=вейке витнема-петнема|$1 витнемат-петнемат}}",
-       "viewdeleted_short": "Ваномс {{PLURAL:$1|1=нардазь вейке витнема-петнема|нардазь $1 витнемат-петнемат}}",
+       "undelete_short": "Велявтомс нардазенть {{PLURAL:$1|вейке витнема-петнема|$1 витнемат-петнемат}}",
+       "viewdeleted_short": "Ваномс нардазь {{PLURAL:$1|вейке витнема-петнема|$1 витнемат-петнемат}}",
        "protect": "Аравтомс прянь ванстомас",
        "protect_change": "полавтомс",
        "protectthispage": "Аравтомс те лопанть ванстомас",
        "talkpagelinktext": "Кортнеме",
        "specialpage": "Башка тевень лопа",
        "personaltools": "Эсень кедьёнкст",
-       "postcomment": "Од явкс",
        "articlepage": "Ваномс потмокслопанть",
        "talk": "Кортнеме",
        "views": "Ваномкат",
        "redirectedfrom": "(Ютавтозь $1 вельде)",
        "redirectpagesub": "Лиясто ютавтозь лопа",
        "lastmodifiedat": "Те лопанть меельседе витнезь-петнезь $2, $1.",
-       "viewcount": "Те лопантень совасть {{PLURAL:$1|1=весть|$1-ксть}}.",
+       "viewcount": "Те лопантень совасть {{PLURAL:$1|весть|$1-ксть}}.",
        "protectedpage": "Те лопась ванстомасо",
        "jumpto": "Тёкадемс тей:",
        "jumptonavigation": "Новигациясь-лездамось",
        "collapsible-expand": "Келейгавтомс",
        "thisisdeleted": "$1-нть ваномс эли велявтомс мекев?",
        "viewdeleted": "Ванномс $1?",
-       "restorelink": "{{PLURAL:$1|1=нардазь вейке витнема-петнема|нардазь $1 витнемат-петнемат}}",
+       "restorelink": "{{PLURAL:$1|нардазь вейке витнема-петнема|нардазь $1 витнемат-петнемат}}",
        "feedlinks": "Максовкс:",
        "feed-invalid": "А маштови сёрмадстома каналонть сортозо.",
        "site-rss-feed": "RSS-нть максовкс $1 -нть кисэ",
        "laggedslavemode": "Ванок: Кизды, лопасонть материалось таштомсь.",
        "readonly": "Датабазась панжома экшсэ",
        "enterlockreason": "Сёрмадт мейс сёлгамс эряви, ды ёвтак, зярдо таго арьсят панжови",
-       "missing-article": "Дата йуртсто а муеви эрявикс текстэсь, сонзэ лемезэ \"$1\" $2.\n\nСеде сеедьстэ истя лиси, зярдо таштомозь diff эли историянь сюлмавома песь вети нардань лопас.\n\nЛисиндерясь аволь истя, можок муить программа керьксстэнть (тапавкс тарка) сийне.\nПачтта сёрмине теде [[Special:ListUsers/sysop|системань ветийнень]] URL адресэнть тештязь.",
+       "missing-article": "Дата юртсто а муеви эрявикс текстэсь, сонзэ лемезэ \"$1\" $2.\n\nСеде сеедьстэ истя лиси, зярдо таштомозь diff эли историянь сюлмавома песь вети нардань лопас.\n\nЛисиндерясь аволь истя, можок муить программа керьксстэнть (тапавкс тарка) сийне.\nПачтта сёрмине теде [[Special:ListUsers/sysop|системань ветийнень]] URL адресэнть тештязь.",
        "missingarticle-rev": "(лиякстомтома#: $1)",
        "missingarticle-diff": "(Мейсэ явовить: $1, $2)",
        "internalerror": "Потмоильведькс",
        "password-change-forbidden": "Те викисэнть а полавтсак салававалот.",
        "login": "Совамо",
        "nav-login-createaccount": "Совамо / тейть совамотарка",
-       "loginprompt": "{{SITENAME}} сайтэнтень совамга эряви нолдамс тевс cookies.",
        "userlogin": "Совамо / тейть совамотарка",
        "userloginnocreate": "Совамо",
        "logout": "Лисеме",
        "gotaccountlink": "Совамс",
        "userlogin-resetlink": "Совамо эрявикстнэнь стувтыть?",
        "userlogin-resetpassword-link": "Салававалот стувтовсь?",
-       "userlogin-createanother": "Шкак од совамотарка",
        "createaccountmail": "Тейть кодамо понгсь салававал, кучик сонзэ ало максозь е-сёрмапаргонтень",
        "createaccountreason": "Тувталось:",
        "createacct-reason": "Тувтал",
        "createacct-submit": "Шкик совамотаркат",
        "createacct-another-submit": "Шкак од совамотарка",
        "createacct-benefit-heading": "«{{SITENAME}}» сайтэнть теизь тонь кондямо ломанть.",
-       "createacct-benefit-body2": "{{PLURAL:$1|1=лопа|лопат}}",
+       "createacct-benefit-body2": "{{PLURAL:$1|лопа|лопат}}",
        "badretype": "Сёрмадыть салава валот кавксть: сынь аволь вейкеть.",
        "userexists": "Те лемесь уш саезь.\nАрсека эстеть лия, инеськеть.",
        "loginerror": "Совамсто ильведькс",
        "login-userblocked": "Те теицясь аравтозь саймас. Совамонзо а мерить.",
        "wrongpassword": "Аволь истя сёрмадык совамо валот. Варчыка одов.",
        "wrongpasswordempty": "Салавань валот кадовсь апак сёрмадо. Сёрмадыка одов.",
-       "passwordtooshort": "Совамо Ð²Ð°Ð»Ð¾Ð½Ñ\82Ñ\8c ÐºÑ\83валмозо  {{PLURAL:$1|1=улезэ 1 тешкс| улезт $1 тешкст}}, аволь седе аламо.",
+       "passwordtooshort": "СалававалонÑ\82Ñ\8c ÐºÑ\83валмозо  {{PLURAL:$1|улезэ 1 тешкс| улезт $1 тешкст}}, аволь седе аламо.",
        "password-name-match": "Салава валонтень эряви явовомс теицянь леметь эйстэ.",
        "password-login-forbidden": "Те теицянь лемесь ды салававалось а мерить нолдамс тевс.",
        "mailmypassword": "Одов ладямс салававал",
        "passwordremindertitle": "{{SITENAME}} туртов акуватень од совамо вал",
-       "passwordremindertext": "Кие-бути (кода неяви тон IP-тешксстэнть $1) вешсь,<br />\nкедьстэнек кучомс теицянь од совамо вал {{SITENAME}} ($4) сайтс совамга.<br />\nТеицянтень \"$2\" кучозь нурькине шкань совамо вал, конась  ней \"$3\".<br />\nБути те тон ульнить, сави ней совамс ды кочкамс од совамо вал эстеть.<br />\nНурькине шкань совамо валот нолдави тевс {{PLURAL:$5|1=вейке чи|$5 чить}}.\n\nБути аволь тон вешицясь, эли мелезэть ледстик совамо валонть, иля яво мель те пачтямнэнтень. Нолдык тевс мельсэ аштицянть - мельс ледстязенть.",
+       "passwordremindertext": "Кие-бути (кода неяви тон, IP-тешксстэнть $1) вешсь,<br />\nкедьстэнек кучомс теицянь од салававал {{SITENAME}} ($4) сайтс совамга.<br />\nТеицянтень \"$2\" кучозь нурькине шкань салававал, конась  ней \"$3\".<br />\nБути те тон ульнить, сави ней совамс ды кочкамс од салававал эстеть.<br />\nНурькине шкань салававалот нолдави тевс {{PLURAL:$5|вейке чи|$5 чить}}.\n\nБути аволь тон вешицяселить, эли мелезэть ледстик салававалонть, иля яво мель те пачтямнэнтень. Нолдык тевс мельсэ аштицянть - мельс ледстязенть.",
        "noemail": "\"$1\" теицянть арась е-сёрмапаргозо.",
        "noemailcreate": "Эряви максомс е-сёрмапарго, конась маштови",
        "passwordsent": "$1 -нь е-сёрмань адресэнтень кучозь од совамо вал.<br />\nИнеськеть, кодак валось пачкоди, совака одов.",
        "eauthentsent": "Электрононь сёрмапаргозот кучозь кемекстамонь е-сёрмине.<br /> Сонзэ эйсэ сёрмадозь мезе кода теемс. Ансяк седе мейле, зярдо невтик, сёрмапаргось алкукс эсеть, карматано кучомо лия сёрмат.",
        "mailerror": "Е-сёрма кучомсто ильведькс: $1",
-       "acct_creation_throttle_hit": "Те Ð²Ð¸ÐºÐ¸Ñ\81Ñ\8d Ñ\82онÑ\8c IP Ð°Ð´Ñ\80еÑ\81Ñ\81Ñ\82Ñ\8dÑ\82Ñ\8c Ñ\81оваÑ\81Ñ\82Ñ\8c Ñ\82еиÑ\86Ñ\8fÑ\82, ÐºÐ¾Ð½Ð°Ñ\82 Ñ\82еиÑ\81Ñ\82Ñ\8c {{PLURAL:$1|1=1 Ñ\81Ñ\91Ñ\80мадовкÑ\81|$1 Ñ\81Ñ\91Ñ\80мадовкÑ\81Ñ\82}} Ð¼ÐµÐµÐ»Ñ\8cÑ\81е Ñ\87Ñ\8bнÑ\82Ñ\8c Ð¿ÐµÑ\80Ñ\82Ñ\8c, Ñ\81еде Ð»Ð°Ð¼Ð¾ Ð¿Ð¾Ð»Ð°Ð²Ñ\82омаÑ\82 Ð° Ð¼ÐµÑ\80иÑ\82Ñ\8c Ñ\82еемÑ\81 Ð¸Ñ\81Ñ\82Ñ\8f Ð·Ð½Ñ\8fÑ\80онÑ\8c Ñ\88канÑ\8c Ð¿ÐµÑ\80Ñ\82Ñ\8c.\nТенÑ\8c ÐºÐ¸Ñ\81Ñ\8d, Ñ\82е   IP Ð°Ð´Ñ\80еÑ\81Ñ\8dнÑ\82Ñ\8c ÐºÐ¾Ñ\80Ñ\8fÑ\81 Ñ\81еде Ñ\82ов Ð° Ð¼Ð°Ñ\88Ñ\82ови Ñ\82еемÑ\81\88камÑ\81 Ð¾Ð´ Ñ\81Ñ\91Ñ\80мадовкÑ\81т, зярс.",
+       "acct_creation_throttle_hit": "Те Ð²Ð¸ÐºÐ¸Ñ\81Ñ\8d Ñ\82онÑ\8c IP Ð°Ð´Ñ\80еÑ\81Ñ\81Ñ\82Ñ\8dÑ\82Ñ\8c Ñ\81оваÑ\81Ñ\82Ñ\8c Ñ\82еиÑ\86Ñ\8fÑ\82, ÐºÐ¾Ð½Ð°Ñ\82 Ñ\82ейÑ\81Ñ\82Ñ\8c {{PLURAL:$1|1 Ñ\81овамо Ñ\82аÑ\80ка|$1 Ñ\81овамо Ñ\82аÑ\80каÑ\82}} Ð¼ÐµÐµÐ»Ñ\8cÑ\86е Ñ\87инÑ\82Ñ\8c Ð¿ÐµÑ\80Ñ\82Ñ\8c, Ñ\81еде Ð»Ð°Ð¼Ð¾ Ð¿Ð¾Ð»Ð°Ð²Ñ\82омаÑ\82 Ð° Ð¼ÐµÑ\80иÑ\82Ñ\8c Ñ\82еемÑ\81 Ð¸Ñ\81Ñ\82Ñ\8fнÑ\8c Ð·Ð½Ñ\8fÑ\80онÑ\8c Ñ\88канÑ\8c Ð¿ÐµÑ\80Ñ\82Ñ\8c.\nТенÑ\8c ÐºÐ¸Ñ\81Ñ\8d, Ñ\82е   IP Ð°Ð´Ñ\80еÑ\81Ñ\8dнÑ\82Ñ\8c ÐºÐ¾Ñ\80Ñ\8fÑ\81 Ñ\81еде Ñ\82ов Ð° Ð¼Ð°Ñ\88Ñ\82ови Ñ\82еемÑ\81\88камÑ\81 Ð¾Ð´ Ñ\81овамо Ñ\82аÑ\80кат, зярс.",
        "emailauthenticated": "Е-сёрмапаргот кемекстазель $2 чистэ $3 цяссто.",
        "emailconfirmlink": "Кемекстык е-сёрмапаргот",
        "accountcreated": "Совамо таркась теезь",
        "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|кортнема]]) совицянь таркась теевсь-шкавсь.",
        "loginlanguagelabel": "Кель: $1",
+       "pt-login": "Совамс",
+       "pt-userlogout": "Лисемс",
        "user-mail-no-addy": "Терявтыть кучомс е-сёрма е-сёрмапарговтомо.",
        "changepassword": "Салавань валонь полавтома",
-       "resetpass_announce": "СовавиÑ\82Ñ\8c Ð½Ñ\83Ñ\80Ñ\8cка Ñ\88канÑ\8c Ñ\81алававалÑ\81о, ÐºÐ¾Ð½Ð° ÐºÑ\83Ñ\87озелÑ\8c ÐºÑ\83лÑ\8fпаÑ\80гозоÑ\82. Ð¡Ð¾Ð²Ð°Ð¼Ð¾Ñ\82 Ð¿Ñ\80Ñ\8fдомга Ñ\8dÑ\80Ñ\8fви Ð¿Ñ\83Ñ\82омÑ\81 Ð¾Ð´ Ñ\81алававал Ð²Ð°Ð½Ð° Ñ\82езÑ\8dенÑ\8c:",
+       "resetpass_announce": "СовамоÑ\82 Ñ\82опавÑ\82омга Ñ\8dÑ\80Ñ\8fви Ð¿Ñ\83Ñ\82омÑ\81 Ð¾Ð´ Ñ\81алававал.",
        "resetpass_header": "Полавтомс совамо валот",
        "oldpassword": "Ташто совамо валот:",
        "newpassword": "Од совамо валот:",
        "resetpass-submit-loggedin": "Полавтомс совамо валот",
        "resetpass-submit-cancel": "Саемс мекев",
        "resetpass-temp-password": "А куватень совамо валось:",
+       "resetpass-expired": "Салававалот таштомсь. Аравтт од салававал, мейле совават.",
        "passwordreset": "Совамо валонь лиялгавтома",
        "passwordreset-legend": "Полавтык совамо валонть",
        "passwordreset-username": "Теиця леметь:",
        "copyrightwarning": "Инескеть кирдть мельсэ {{SITENAME}}-сэ весе путовкстнэнь, лововить нолдазекс ало $2  конёвонть коряс (вант $1 педе пес). Арась мелеть витневтемс-петневтемс сёрмадовксот педе пес, иляк сестэ путо сонзэ тезэнь.<br />\nИстяжо тезэнь материалонь максомсот, кемекстат тон тонсь сёрмадык сонзэ, али саик сонзэ вейсэнь ёнксто али олячинь порталсто.\n'''ИЛЯ МАКСО ВАНСТОНЬ ВИДЕЧИСЭ ЛОМАНЕНЬ ВАЖОДЕМАНТЬ АПАК КЕВКСТНЕ!'''",
        "titleprotectedwarning": "'''ВАНОК:  Те лопась сёлгозь, сонзэ шкамга-теемга [[Special:ListGroupRights|башка видечыть]] эрявить.'''\nЖурналонь меельсе сёрмадовксось максозь ало, эрявиндеряй сонзэ ваномс.",
        "templatesused": "Те лопасонть тевс нолдазь {{PLURAL:$1|лопапарцун|лопапарцунт}}:",
-       "templatesusedpreview": "Те икелькс вановкссонть тевс нолдазь  {{PLURAL:$1|1=лопа парцун|лопа парцунт}}:",
-       "templatesusedsection": "Те пелькссэнть тевс нолдазь {{PLURAL:$1|1=лопа парцунось|лопа парцунтнэ}}:",
+       "templatesusedpreview": "Те икелькс вановкссонть тевс нолдазь  {{PLURAL:$1|лопа парцун|лопа парцунт}}:",
+       "templatesusedsection": "Те пелькссэнть тевс нолдазь {{PLURAL:$1|лопа парцунось|лопа парцунтнэ}}:",
        "template-protected": "(ванстозь)",
        "template-semiprotected": "(пельс ванстозь)",
        "hiddencategories": "Те лопась совавтови {{PLURAL:$1|кекшень 1 категорияс|кекшень $1 категорияс}}:",
        "nocreatetext": "Те {{SITENAME}} лопасонть пирязь од лопань теемась. Тонь ули мелеть велявтомс удалов ды  питнемензе-витнемензе улиця лопанть, али [[Special:UserLogin|совамс али теемс од совама]].",
        "nocreate-loggedin": "Тонеть а мерить теемс-шкамс од лопат.",
-       "permissionserrorstext": "ТонеÑ\82Ñ\8c Ð° Ð¼ÐµÑ\80иÑ\82Ñ\8c Ñ\82еемÑ\81 Ñ\82енÑ\8c, Ð²Ð°Ð½Ð° {{PLURAL:$1|1=Ñ\82Ñ\83вÑ\82алоÑ\81Ñ\8c\82Ñ\83вÑ\82алÑ\82нÑ\8d}}:",
-       "permissionserrorstext-withaction": "Тонеть а мерить теемс $2, {{PLURAL:$1|1=тувталось|тувталтнэ}} вана:",
+       "permissionserrorstext": "ТонеÑ\82Ñ\8c Ð° Ð¼ÐµÑ\80еви Ñ\82еемÑ\81 Ñ\82енÑ\8c, Ð²Ð°Ð½Ð° {{PLURAL:$1|Ñ\82Ñ\83вÑ\82алонÑ\82Ñ\8c\82Ñ\83вÑ\82алÑ\82нÑ\8dнÑ\8c}} ÐºÐ¸Ñ\81Ñ\8d:",
+       "permissionserrorstext-withaction": "Тонеть а мерить $2, {{PLURAL:$1|тувталось|тувталтнэ}} вана:",
        "recreate-moveddeleted-warn": "'''Ванок: Вельмевтят лопа, кона нардазель.'''\n\nВасня арьсек, эряви - а эряви полалемс ды витнемс-петнемс те лопанть.\nТе лопанть нардамодо ды печтевтемадо путовкстнэ одов максозь тесэ, улезт шожда ванстнемс:",
        "moveddeleted-notice": "Те лопась нардазь.\nЛопанть нардамодо сёрмадовксось максозь вана ало.",
        "log-fulllog": "Ванномс журналонть весемензэ",
        "currentrev": "Тевате лиякстомтома",
        "currentrev-asof": "Неень верзиясь истямо шкань $1",
        "revisionasof": "$1-це версиясь",
-       "revision-info": "$1 -нь лиякстомтома, конань теизе $2",
+       "revision-info": "$1 -нь лиякстомтома, конань теизе {{GENDER:$6|$2}}$7",
        "previousrevision": "←Седе икелень лиякстомтома",
        "nextrevision": "Седе од вановкс→",
        "currentrevisionlink": "Тевате лиякстомтома",
        "history-show-deleted": "Ансяк нардазь",
        "histfirst": "весемеде умонь",
        "histlast": "Меельце",
-       "historysize": "({{PLURAL:$1|1=1 байт|$1 байтт}})",
+       "historysize": "({{PLURAL:$1|1 байт|$1 байтт}})",
        "historyempty": "(чаво)",
        "history-feed-title": "Лиякстомтомань тевде",
        "history-feed-description": "Викинь тевате лопанть лиякстомтомань тевдензэ",
        "revdelete-show-file-confirm": "Алкукс ули мелеть ваномс «<nowiki>$1</nowiki>» керьмазонть нардазь ревизиянзо, конась саезь $2-нть эйстэ ды ашти тесэ $3?",
        "revdelete-show-file-submit": "Ули",
        "revdelete-legend": "Аравтомс неявомачынь петне",
-       "revdelete-hide-text": "Ð\9aекÑ\88емÑ\81 Ð»Ð¸Ñ\8fкÑ\81Ñ\82омÑ\82оманÑ\8c Ñ\82екÑ\81Ñ\82Ñ\8dнÑ\82ь",
+       "revdelete-hide-text": "Ð\9bиÑ\8fкÑ\81Ñ\82омÑ\82оманÑ\8c Ñ\82екÑ\81Ñ\82Ñ\8dÑ\81ь",
        "revdelete-hide-image": "Кекшемс мезе файлатнесэ",
        "revdelete-hide-name": "Кекшемс тев тееманть ды норовамо тарканзо",
-       "revdelete-hide-comment": "Ð\9aекÑ\88емÑ\81 Ð²Ð¸Ñ\82немадо-пеÑ\82немадо Ð°Ñ\80Ñ\81емаÑ\82ненÑ\8c",
-       "revdelete-hide-user": "Ð\9aекÑ\88емÑ\81 Ð²Ð¸Ñ\82ниÑ\86Ñ\8fнÑ\82Ñ\8c-пеÑ\82ниÑ\86Ñ\8fнÑ\82Ñ\8c Ñ\82еиÑ\86Ñ\8f Ð»ÐµÐ¼ÐµÐ½Ð·Ñ\8d/IP-нзÑ\8d",
+       "revdelete-hide-comment": "Ð\92иÑ\82немÑ\81-пеÑ\82немÑ\81 Ñ\81Ñ\91Ñ\80мадовкÑ\81онÑ\82Ñ\8c Ð·Ñ\8dмензÑ\8d.",
+       "revdelete-hide-user": "Ð\92иÑ\82ниÑ\86Ñ\8fнÑ\82Ñ\8c-пеÑ\82ниÑ\86Ñ\8fнÑ\82Ñ\8c Ñ\81овамолемезÑ\8d/IP Ñ\81Ñ\91Ñ\80мапаÑ\80гозо",
        "revdelete-radio-same": "(иляк лиякстомто)",
        "revdelete-log": "Тувталось:",
-       "revdelete-submit": "Аравтомс кочказь {{PLURAL:$1|1=лиякстомтомантень|лиякстомтоматненень}}",
+       "revdelete-submit": "Аравтомс кочказь {{PLURAL:$1|лиякстомтомантень|лиякстомтоматненень}}",
        "revdel-restore": "Полавтомс неявомачынзэ",
        "pagehist": "Лопанть икелькс умазо",
        "deletedhist": "Нардань икелькс умазо",
        "mergehistory-box": "Совавтомс кавто лопатнень лиякстомтомадо сёрмадовкстнэнь ве лувс:",
        "mergehistory-from": "Лисьмапря лопа:",
        "mergehistory-into": "Совавтома лопа:",
-       "mergehistory-list": "Ð\92ейÑ\82Ñ\8cÑ\81Ñ\8dндÑ\8fвиÑ\86Ñ\8f Ñ\8eÑ\80онзо-пÑ\83Ñ\82овкÑ\81онзо",
+       "mergehistory-list": "Вейсэндявиця юронзо-путовксонзо",
        "mergehistory-go": "Невтемс вейтьс совавтомкс витнемат-петнемат",
        "mergehistory-submit": "Совавтомс лиякстомтоматнень вейтьс",
        "mergehistory-empty": "Вейкеяк лиякстомтома а совавтови вейтьс лия марто.",
        "mergehistory-invalid-destination": "Совавтомкс лопанть улезэ маштовикс лем.",
        "mergehistory-autocomment": "Совавтомс [[:$1]] [[:$2]]-с",
        "mergehistory-reason": "Тувталось:",
-       "mergelog": "Ð\92ейÑ\82Ñ\8cÑ\81Ñ\8dндÑ\8fмÑ\81 Ð»Ð¾Ð³Ð¾Ð½Ñ\82Ñ\8c",
-       "revertmerge": "ЯвомÑ\81 Ð»Ð¾Ð³Ð¾Ð½Ñ\82Ñ\8c Ð¼ÐµÐºÐµÐ², ÐºÐ¾Ð´Ð° Ñ\83лÑ\8cнеÑ\81Ñ\8c Ð²ÐµÐ¹Ñ\82Ñ\8cÑ\81Ñ\8dндÑ\8fмодо Ð¸ÐºÐµÐ»Ðµ",
-       "history-title": "\"$1\"ь полавтнемань историязо",
+       "mergelog": "Вейсэндямс логонть",
+       "revertmerge": "Явомс логонть мекев, кода ульнесь вейсэндямодо икеле",
+       "history-title": "\"$1\" лопанть полавтнемань историязо",
        "difference-multipage": "(Мейсэ лопатне явовить)",
        "lineno": "Киксэсь $1:",
        "compareselectedversions": "Кочказь версиятнень аравтомс карадо-каршо",
        "searchprofile-everything-tooltip": "Вешнемс весе лопатнева (кортнема лопатневаяк)",
        "searchprofile-advanced-tooltip": "Вешнемс башка теезь лемпотмотнестэ",
        "search-result-size": "$1 ({{PLURAL:$2|1 вал|$2 валт}})",
-       "search-result-category-size": "{{PLURAL:$1|1=1 совицязо|$1 совицянзо}} ({{PLURAL:$2|1=1 явкскатегориязо|$2 явкскатегориянзо}}, {{PLURAL:$3|1=1 файла|$3 файлат}})",
+       "search-result-category-size": "{{PLURAL:$1|1 совицязо|$1 совицянзо}} ({{PLURAL:$2|1 явкскатегориязо|$2 явкскатегориянзо}}, {{PLURAL:$3|1 файла|$3 файлат}})",
        "search-redirect": "(йутавтт $1-с)",
        "search-section": "(пелькс $1)",
        "search-suggest": "Истя мерикскелить: $1",
        "search-interwiki-caption": "Дугакс проектт",
-       "search-interwiki-default": "$1 савкс:",
+       "search-interwiki-default": "«$1» викинть эйстэ савкст:",
        "search-interwiki-more": "(седе ламо)",
        "search-relatedarticle": "Малавикс",
        "searchrelated": "малавикс",
        "prefs-personal": "Теицядо",
        "prefs-rc": "Чиень полавтнемат-лиякстомтомат",
        "prefs-watchlist": "Ванома лемрисьме",
-       "prefs-watchlist-days-max": "Весемеде куватьс $1 {{PLURAL:$1|1=чис|чис}}",
+       "prefs-watchlist-days-max": "Весемеде куватьс $1 {{PLURAL:$1|чис|чис}}",
        "prefs-watchlist-edits-max": "Весемеде покш цётось: 1000",
        "prefs-misc": "Минеть-сюнот",
        "prefs-resetpass": "Салавань валонь полавтома",
        "prefs-email": "Е-сёрмат-мезть",
        "prefs-rendering": "Тюсозо-лангозо",
        "saveprefs": "Ванстомс",
-       "restoreprefs": "Велявтомс мекев весе ушодкс ладсематнень",
+       "restoreprefs": "Велявтомс мекев весе ушодкс ладсематнень (весе явкстнэва)",
        "prefs-editing": "Витнема-петнема",
        "rows": "Валчилькстнэ (строкатне):",
        "columns": "Палманть:",
        "searchresultshead": "Вешнема",
        "recentchangesdays": "Зяро чить невтемс чиень полавтнематнесэ-лиякстомтоматнесэ:",
-       "recentchangesdays-max": "Весемеде куватьс $1 {{PLURAL:$1|1=чис|чис}}",
+       "recentchangesdays-max": "Весемеде куватьс $1 {{PLURAL:$1|чис|чис}}",
        "recentchangescount": "Васень аравтоматнень коряс зяро витнемат-петнемат невтемс:",
        "prefs-help-recentchangescount": "Тезэнь совавтозь чиень полавтнемат-лиякстомтомат, лопань лувт-путовкст, журналт.",
        "timezonelegend": "Шкань зонась:",
        "timezoneregion-pacific": "Сэтьме иневедь",
        "prefs-searchoptions": "Вешнем",
        "prefs-namespaces": "Лем потмот",
-       "default": "зярдо лиякс апак йовта",
+       "default": "зярдо лиякс апак ёвта",
        "prefs-files": "Файлат",
        "youremail": "Е-сёрма:",
        "username": "Теицянь леметь:",
        "yourrealname": "Алкуксонь леметь:",
        "yourlanguage": "Келесь:",
        "yournick": "Кедень путома:",
-       "badsiglength": "Кедень путомат пек кувака.\nЭйсэнзэ иляст уле $1 -до ламо {{PLURAL:$1|1=тешкст|тешкст}}.",
-       "yourgender": "СÑ\8bмеÑ\82Ñ\8c (Ñ\86Ñ\91Ñ\80анÑ\8c\82ейÑ\82еÑ\80енÑ\8c):",
+       "badsiglength": "Кедень путомат пек кувака.\nЭйсэнзэ иляст уле $1 -до ламо {{PLURAL:$1|тешкст|тешкст}}.",
+       "yourgender": "ТонÑ\81Ñ\8c ÐºÐ¾Ð´Ð° Ð¼ÐµÑ\80евлиÑ\82Ñ\8c Ñ\8dÑ\81Ñ\8c Ð¿Ñ\80Ñ\8fдоÑ\82?",
        "gender-unknown": "А меревлинь",
        "gender-male": "Сон витни-петни викилопатнесэ",
        "gender-female": "Сон витни-петни викилопатнесэ",
        "right-undelete": "Вельмевтемс нардань лопа",
        "right-block": "Кардамс лия совийтнень-лисийтнень витнемадо-петнемадо",
        "right-blockemail": "Кардамс лия лисийтнень-совийтнень е-сёрмань кучомадо",
-       "right-editinterface": "Витнемс-петнемс теицянь интерчаманть (васодема йожонть)",
+       "right-editinterface": "Витнемс-петнемс теицянь интерчаманть (васодема ёжонть)",
        "right-editusercssjs": "Витнемс-петнемс лия теицятнень CSS ды JS файласт",
        "right-editusercss": "Витнемс-петнемс лия теицятнень CSS файласт",
        "right-edituserjs": "Витнемс-петнемс лия теицятнень JS файласт",
        "right-import": "Ёвкстамс лия Викистэ лопат",
        "right-patrol": "Тешкстамс лиянь витнематнень-петнематнень лувонь кирдиеньсекс",
-       "right-mergehistory": "Ð\92ейÑ\82Ñ\8cÑ\81Ñ\8dндÑ\8fмÑ\81 Ð»Ð¾Ð¿Ð°Ñ\82ненÑ\8c Ñ\8eÑ\80оÑ\81Ñ\82-пÑ\83Ñ\82овкÑ\81оÑ\81Ñ\82",
+       "right-mergehistory": "Вейсэндямс лопатнень юрост-путовксост",
        "right-userrights": "Витнемс-петнемс совицянь весе видечитнень",
        "right-siteadmin": "Датабазань сёлгомо ды панжомо",
        "right-passwordreset": "Ваномс теицянь салава валонь полавтома е-сёрмат",
        "action-move-subpages": "печтевтемс те лопанть, ды алонзо весе лопатнень",
        "action-move-rootuserpages": "печтевтемс теицянь юрт лопатнень",
        "action-movefile": "печтевтемс те файланть",
-       "action-upload": "йовкстамс те файланть",
+       "action-upload": "ёвкстамс те файланть",
        "action-reupload": "уликс файланть полавтомс одонть марто",
        "action-upload_by_url": "ёвкстамс те файланть URL адресстэ",
        "action-writeapi": "нолдамс тевс сёрмадома API-нть",
        "action-block": "кардамс те совицянть витнемадо-петнемадо",
        "action-import": "совавтомс тезэнь лопат лия Викистэ",
        "action-importupload": "совавтомс тезэнь лопат файлань путома юртсто",
-       "action-mergehistory": "вейÑ\82Ñ\8cÑ\81Ñ\8dндÑ\8fмÑ\81 Ñ\82е Ð»Ð¾Ð¿Ð°Ð½Ñ\82Ñ\8c Ñ\8eÑ\80онзо-пÑ\83Ñ\82овкÑ\81онзо",
+       "action-mergehistory": "вейсэндямс те лопанть юронзо-путовксонзо",
        "action-userrights": "витнемс-петнемс совицянь весе видечитнень",
        "action-userrights-interwiki": "витнемс-петнемс лия викитнесэ теицянь видечитнень",
        "action-sendemail": "кучомс е-сёрмат",
        "recentchanges-label-bot": "Те витнеманть-петнеманть теизе кона-кона бот",
        "recentchanges-label-unpatrolled": "",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (вантаять [[Special:NewPages|од лопань лемрисьме]])",
-       "rcnotefrom": "Ð\90ло Ð½ÐµÐ²Ñ\82езÑ\8c  '''$2''' Ð»Ð¸Ñ\8fкÑ\81Ñ\82омÑ\82омаÑ\81Ñ\82о Ñ\81аезÑ\8c ('''$1''' Ð²Ð¸Ð´Ñ\81).",
+       "rcnotefrom": "Ð\90ло Ð¼Ð°ÐºÑ\81озÑ\8c {{PLURAL:$5|лиÑ\8fкÑ\81Ñ\82омÑ\82омаÑ\81Ñ\8c, ÐºÐ¾Ð½Ð°Ñ\81Ñ\8c|лиÑ\8fкÑ\81Ñ\82омÑ\82омаÑ\82не, ÐºÐ¾Ð½Ð°Ñ\82не}} Ñ\82еезÑ\8c <strong>$3, $4</strong> Ñ\88каÑ\81Ñ\82о Ñ\81аезÑ\8c (веÑ\81емеде Ð»Ð°Ð¼Ð¾ Ð½ÐµÐ²Ñ\82езÑ\8c <strong>$1</strong>).",
        "rclistfrom": "Невтемс од витьнематнень $3 $2-нть эйстэ саезь.",
        "rcshowhideminor": "$1 апокшкэ витнемат-петнемат",
        "rcshowhidebots": "$1 ботт",
        "recentchangeslinked-page": "Лопанть лемезэ:",
        "recentchangeslinked-to": "Тень таркас невтить те лопанть марто сюлмазь лопатнесэ полавтнематнень",
        "upload": "Ёкстамс файла",
-       "uploadbtn": "Ð\99овкÑ\81амÑ\81 Ñ\84айланÑ\82Ñ\8c",
+       "uploadbtn": "Ð\81вкÑ\81Ñ\82амÑ\81 Ñ\84айла",
        "uploadnologin": "Эзить сова",
-       "uploaderror": "Ð\99овкстамсто манявома",
+       "uploaderror": "Ð\81вкстамсто манявома",
        "upload-permitted": "Файлань форматт, конат меревить: $1.",
        "upload-preferred": "Файлань типт, конатне паро мельсэ учовить: $1.",
        "upload-prohibited": "Файлань типт, конатне кардазь: $1.",
-       "uploadlogpage": "Файлань йовкстамодо журнал",
+       "uploadlogpage": "Файлань ёвкстамодо журнал",
        "filename": "Файлань лем",
        "filedesc": "Нурькинестэ",
        "fileuploadsummary": "Нурькинестэ:",
        "filename-tooshort": "Файлань лементь а саты кувалмозо.",
        "unknown-error": "А содавикс манявкс лиссь.",
        "file-thumbnail-no": "Файланть лемезэ ушодови  <strong>$1</strong>.\nСонсь маряви вишкалгавтозь фотокуво, покшолмазо ''(кенжешка)''.\nУлиндеряй файланть покш верзиязо, йовкстыка сонзэ  - арась, полавтыка тетень лемензэ.",
-       "file-exists-duplicate": "Те кавонзавкс файла вана {{PLURAL:$1|1=те файланть|неть файлатнень}} эйстэ:",
+       "file-exists-duplicate": "Те кавонзавкс файла вана {{PLURAL:$1|те файланть|неть файлатнень}} эйстэ:",
        "uploadwarning": "Совавтомадо кардамонь пачтямо",
        "savefile": "Ванстомс файланть",
-       "uploadedimage": "йовкстазь \"[[$1]]\"",
-       "overwroteimage": "Ёвкстамс \"[[$1]]\" файлань од версия",
        "uploaddisabled": "Совавтомась лоткавтозь",
        "uploadvirus": "Те файласонть вирус програм! Информация: $1",
        "upload-source": "Лисьмапрякс файла",
        "license-header": "Лицензиянь теема:",
        "nolicense": "Лицензия арась",
        "license-nopreview": "(Васнянь невтевкс арась)",
-       "upload_source_file": " (арси машинасот файла)",
+       "upload_source_file": " (арсимашинастот файла, конань тонсь кочкик)",
        "listfiles_search_for": "Вешнемс медиа лементь:",
        "imgfile": "файл",
        "listfiles": "Файлат-мезть",
        "filepage-nofile": "Истямо лем марто файла арась.",
        "uploadnewversion-linktext": "Йовкстак од версия те файластонть",
        "shared-repo-from": "вана теньстэ $1",
-       "shared-repo": "вейÑ\82Ñ\8cÑ\81Ñ\8dнÑ\8c Ð²Ð°Ð½Ñ\81Ñ\82ома Ñ\82аÑ\80ка",
+       "shared-repo": "вейсэнь ванстома тарка",
        "filerevert": "Велявтомс $1 мекев",
        "filerevert-legend": "Велявтомс файланть",
        "filerevert-comment": "Тувталось:",
        "linksearch": "Ушо ёндонь сюлмавомапенень вешнема",
        "linksearch-pat": "Вешнемкс парцун:",
        "linksearch-ns": "Лем потмозо:",
-       "linksearch-ok": "Вешнэмс",
+       "linksearch-ok": "Вешнемс",
        "linksearch-line": "$1-в сюлмавома песь моли вана тестэ $2",
        "listusers-submit": "Невтемс",
        "listusers-noresult": "Совицязо а муеви",
        "protect-default": "Весе теицятненень маштови",
        "protect-fallback": "Вешеви ве мельс прамось «$1»-нть",
        "protect-level-autoconfirmed": "Саймас аравтомс од ды апак сёрмадстово теицятнень",
-       "protect-level-sysop": "Ансяк администраторт",
+       "protect-level-sysop": "Ансяк администратортнэнень мереви",
        "protect-summary-cascade": "каскадонь ладсо",
        "protect-expiring": "прядови $1 (UTC)",
        "protect-expiry-indefinite": "певтема",
        "undeleteviewlink": "ваномс",
        "undeleteinvert": "Кочказень таркас апаконь кочкамо",
        "undeletecomment": "Тувталось:",
-       "undeletedrevisions": "{{PLURAL:$1|1=1 лиякстомтома|$1 лиякстомтомат}} вельмевтезь",
+       "undeletedrevisions": "{{PLURAL:$1|1 лиякстомтома|$1 лиякстомтомат}} вельмевтезь",
        "undeletedrevisions-files": "{{PLURAL:$1|1=1 лиякстомтома|$1 лиякстомтомат}} ды {{PLURAL:$2|1=1 файла|$2 файлат}} вельмевтезь",
        "undeletedfiles": "{{PLURAL:$1|1=1 файла|$1 файлат}} вельмевтезь",
-       "undelete-search-box": "Ð\92еÑ\88немÑ\81 Ð½Ð°Ñ\80данÑ\8c Ð»Ð¾Ð¿Ð°Ñ\82ненÑ\8c Ð¹Ñ\83тксто",
+       "undelete-search-box": "Ð\92еÑ\88немÑ\81 Ð½Ð°Ñ\80дазÑ\8c Ð»Ð¾Ð¿Ð°Ñ\82ненÑ\8c Ñ\8eтксто",
        "undelete-search-prefix": "Невтемс лопат тестэ саезь:",
-       "undelete-search-submit": "Вешнэмс",
+       "undelete-search-submit": "Вешнемс",
        "undelete-error-short": "\"$1\" файлань вельмевтемстэ лиссь ильведевкс",
        "undelete-show-file-submit": "Истя",
        "namespace": "Лем потмозо:",
        "sp-contributions-search": "Путовксонь вешнеме",
        "sp-contributions-username": "IP адрес эли теицянь лем:",
        "sp-contributions-toponly": "Невтемс ансяк не витнематнень-петнематнень, конат совавтовить меельце верзиятнень юткс",
-       "sp-contributions-submit": "Вешнэмс",
+       "sp-contributions-submit": "Вешнемс",
        "whatlinkshere": "Мезе тезэнь сюлмави",
        "whatlinkshere-title": "$1 марто сюлмазь лопатне",
        "whatlinkshere-page": "Лопась:",
        "whatlinkshere-prev": "{{PLURAL:$1|1=икеле|седе икелень $1}}",
        "whatlinkshere-next": "{{PLURAL:$1|1=сыця|сы $1}}",
        "whatlinkshere-links": "← сюлмавомапеть",
-       "whatlinkshere-hideredirs": "$1 {{PLURAL:$1|1=тарка йутавты|таркат йутавтыть}} тей",
+       "whatlinkshere-hideredirs": "$1 ютавты козонь-козонь",
        "whatlinkshere-hidetrans": "$1 сюлмавозь пелькстнэнь",
        "whatlinkshere-hidelinks": "$1 сюлмавома петь",
        "whatlinkshere-hideimages": "$1 файланть сюлмавомапензэ",
        "blocklist-target": "Норовамо тарка",
        "blocklist-expiry": "Прядови",
        "blocklist-reason": "Тувтал",
-       "ipblocklist-submit": "Вешнэме",
+       "ipblocklist-submit": "Вешнеме",
        "infiniteblock": "певтеме",
        "expiringblock": "саймас саемась прядови $1 $2 цяссто",
        "anononlyblock": "ансяк лемтеме",
        "filemissing": "Файлась а муеви",
        "thumbnail_error": "Миниатюрань теемстэ ильведькс: $1",
        "import": "Таргамс лопатнень",
-       "import-interwiki-source": "Вики лисьмапрякс/лопась:",
        "import-interwiki-templates": "Совавтомс весе лопа парцунтнэнь",
        "import-interwiki-submit": "Таргамс",
        "import-interwiki-namespace": "Норовазь лемпотмось:",
        "tooltip-ca-edit": "Те лопаськак витневи-петневи. Ансяк, ванстомадо икеле яла васнянь невтевкс повнэнть лепштика.",
        "tooltip-ca-addsection": "Ушодомс од явкс.",
        "tooltip-ca-viewsource": "Те лопась ванстозь. Ули меленк ваномонзо сонзе лисмапрянть.",
-       "tooltip-ca-history": "Те лопанть йутазь версиянзо.",
+       "tooltip-ca-history": "Те лопанть ютазь версиянзо.",
        "tooltip-ca-protect": "Аравтомс те лопанть прянь ванстомас",
        "tooltip-ca-delete": "Нардамс те лопанть, илязо улеяк",
        "tooltip-ca-move": "Ютавтык те лопанть лияв",
        "newimages-legend": "Сувтеме",
        "newimages-label": "Файлалем (эли пельксэзэ):",
        "noimages": "Арась мезе ваномс.",
-       "ilsubmit": "Вешнэмс",
+       "ilsubmit": "Вешнемс",
        "bydate": "чинь коряс",
        "ago": "$1-до икеле",
        "bad_image_list": "Лувось-форматось вана истямо:\n\nТесэ ансяк потмонть пакшкетне (рисьметне, конат ушодовить * тешкстсэ) лововить. Рисьмень васень сюлмавома пентень эряви невтемс амаштовикс файла лангс. Секе рисьминентень понгиндеряйть лия сюлмавома петь, сынь лововить башка, лиякс меремс сынь лопат, косо файлат маштовить невтемс.",
        "watchlisttools-raw": "Витнеме-петнеме верек ваномалопанть",
        "duplicate-defaultsort": "'''Ванок!''' Рядс аравтомань те \"$2\" панжомась саеви те \"$1\" панжомадо икеле.",
        "version": "Версия",
+       "version-skins": "Лангт",
        "version-specialpages": "Башка тевень лопат",
        "version-variables": "Полавтневикс тевть",
-       "version-skins": "Лангт",
        "version-other": "Лия",
        "version-hooks": "Кечказт",
        "version-hook-name": "Кечказонть лемезэ",
        "version-software": "Нолдань программат",
        "version-software-product": "Шкавкс-нолдавкс",
        "version-software-version": "Верзия",
-       "fileduplicatesearch": "Вешнэмс кавтаське файлат",
-       "fileduplicatesearch-legend": "Вешнэмс кавтаське",
+       "fileduplicatesearch": "Вешнемс кавтаське файлат",
+       "fileduplicatesearch-legend": "Вешнемс кавтаське",
        "fileduplicatesearch-filename": "Файла лем:",
-       "fileduplicatesearch-submit": "Вешнэмс",
+       "fileduplicatesearch-submit": "Вешнемс",
        "specialpages": "Башка тевень лопат",
        "specialpages-group-other": "Лия башка тевень лопат",
        "specialpages-group-login": "Совамс / шкамс совамотарка",
index ed2cb7a..b93f287 100644 (file)
@@ -9,7 +9,8 @@
                        "Parthava (on mzn.wikipedia.org)",
                        "Spacebirdy",
                        "محک",
-                       "아라"
+                       "아라",
+                       "Alirezaaa"
                ]
        },
        "tog-underline": "پیوندون زیر خط دکشی بواشه",
@@ -77,8 +78,8 @@
        "may_long": "مه",
        "june": "ژوئن",
        "july": "ژوئیه",
-       "august": "ئÙ\80Ù\88Ú¯Ù\80Ù\87â\80\8cسÙ\80ت",
-       "september": "سÙ\80Ù\87â\80\8cÙ¾Ù\80تÙ\80Ù\87â\80\8cÙ\85Ù\80بÙ\80ر",
+       "august": "Ø¢Ú¯Ù\88ست",
+       "september": "سپتاÙ\85بر",
        "october": "اکتبر",
        "november": "نـووه‌مـبـر",
        "december": "دسامبر",
@@ -89,8 +90,8 @@
        "may-gen": "مه",
        "june-gen": "جـون",
        "july-gen": "ژوئیه",
-       "august-gen": "ئÙ\88Ú¯Ù\80Ù\87â\80\8cسÙ\80ت",
-       "september-gen": "سÙ\80Ù\87â\80\8cÙ¾Ù\80تÙ\80Ù\87â\80\8cÙ\85Ù\80بÙ\80ر",
+       "august-gen": "Ø¢Ú¯Ù\88ست",
+       "september-gen": "سپتاÙ\85بر",
        "october-gen": "اکتبر",
        "november-gen": "نـووه‌مـبـر",
        "december-gen": "دسامبر",
        "talkpagelinktext": "گپ",
        "specialpage": "شا صفحه",
        "personaltools": "مه‌شه ابزار",
-       "postcomment": "نو تیکه",
        "articlepage": "نمایش صفحه",
        "talk": "گپ",
        "views": "هارشی‌ئون",
        "editlink": "دچی‌ین",
        "viewsourcelink": "منبع بدی‌ین",
        "editsectionhint": "تیکه: $1 ره دچی‌ین",
-       "toc": "دله",
+       "toc": "فهرست",
        "showtoc": "سِراق هاده",
        "hidetoc": "فرو بور",
        "collapsible-collapse": "دوستن",
        "yourdomainname": "شمه کاروری نوم",
        "login": "دله بوردن",
        "nav-login-createaccount": "دله بوردن / عضو بیّن",
-       "loginprompt": "{{SITENAME}} ره ده‌لـه بیـه‌موئـه‌ن وه‌سه، وه‌نـه cookieئون  کـارسأر بـوئـه‌ن.",
        "userlogin": "دله بموئن / عضو بیّن",
        "userloginnocreate": "دله بموئن",
        "logout": "دربوردن",
        "uploadbtn": "باربی‌یشتن فایل",
        "uploadtext": "فرم زیر جه باربی‌یشتن نو پرونده‌ئون وسّه استفاده هاکنین.\nبدی‌ین پرونده‌ئونی که قبلاً باربی‌یشته بَینه به [[Special:FileList|فهرست پرونده‌ها]] بورین. باربی‌یشتن مجدد [[Special:Log/upload|سیاههٔ بارگذاری‌ها]] و حذف پرونده‌ئون [[Special:Log/delete|deletion log]] دله ثبت وانه.\n\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|alt text]]</nowiki></code>''' استفاده از اتا نسخه ۲۰۰ پیکسلی از پرونده که اتا جعبه سمت چپ متن دله دره و عبارت alt text ونه دله به عنوان توضیح استفاده بیّه وسّه\n*'''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' بساتن اتا پیوند مستقیم به پرونده بدون نمایش پرونده",
        "uploadlogpage": "باربی‌یشتن گزارش",
-       "uploadedimage": "\"[[$1]]\" ره باربی‌یشته",
        "imgfile": "فایل",
        "listfiles": "هارشی ئون ره لیست",
        "listfiles_name": "نـوم",
        "watchlist-details": "بدون حیساب گپ ولگ‌ئون، {{PLURAL:$1|$1 صفحه|$1 صفحه}} شمه دمبال‌هاکردنی‌ئون میون قرار {{PLURAL:$1|دارنه|دانه}}.",
        "wlheader-enotif": "*تونی ایمیل جه مطلع بواشین.",
        "wlheader-showupdated": "*صفحه‌ئونی که بعد از آخرین سربزوئنتون عوض بینه '''پر رنگ''' نشون هدائه بیّه.",
+       "wlnote": "ایجه {{PLURAL:$1|پایانی دأچیه‌ن|پایانی '''$1''' دأچیه‌ن‌ئونی}} هأسه که ای $2 ساعت ده‌له دأکه‌ته.",
        "watchlist-options": "دمبال هاکردن گوزینه‌ها",
        "watching": "ده‌مـبـال هـه‌کـارده‌ن...",
        "unwatching": "ده‌مـبـال نـه‌کـارده‌ن...",
        "revertmove": "واچـیـه‌ن",
        "delete_and_move_confirm": "أره، پاک هاکه‌ن وه ره",
        "export": "دأیابأبه‌رده‌ن ولـگ‌ئون",
-       "exporttext": "شما بتونّی متن و تاریخچهٔ دچی‌یه بیّن اتا صفحهٔ مشخص یا یتـّا مجموعه‌ از صفحه‌ها ره به شکل دپوشنی‌یه اکس‌ام‌ال دله بریم دربَورین.\n\nاین اطلاعات ره بنشنه اتا ویکی دیگه دله که نرم‌افزار «مدیاویکی» ره اجرا کانده از طریق [[Special:Import|صفحهٔ دله‌دشنی‌ین]] وارد هاکردن.\n\nبریم‌دربَوردن صفحه‌ها وسّه، وشون عنوان ره این جعبه دله دشنین (هر سطر فقط اتا عنوان) و معلوم هاکنین که تازه دگاردسته‌ئون صفحه ره همراه نسخه‌ئون قدیمی‌تر و تاریخچهٔ صفحه خوندنّی، یا تازه دگاردسته‌ئون صفحه و اطلاعات آخرین دچی‌یه ره، تیناری اشنّی.\n\nدومین حالت سَره، شما بتونّی اتا لینک جه استفاده هاکنین، مثلاً [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] صفحهٔ «[[{{MediaWiki:Mainpage}}]]» وسّه.",
+       "exporttext": "شما بتونّی متن و تاریخچهٔ دچی‌یه بیّن اتا صفحهٔ مشخص یا یتـّا مجموعه‌ از صفحات ره به شکل دپوشنی‌یه اکس‌ام‌ال دله بریم دربَورین.\n\nاین اطلاعات ره بنشنه اتا ویکی دیگه دله که نرم‌افزار «مدیاویکی» ره اجرا کانده از طریق [[Special:Import|صفحهٔ دله‌دشنی‌ین]] وارد هاکردن.\n\nبریم‌دربَوردن صفحات وسّه، وشون عنوان ره این جعبه دله دشنین (هر سطر فقط اتا عنوان) و معلوم هاکنین که تازه دگاردسته‌ئون صفحه ره همراه نسخه‌ئون قدیمی‌تر و تاریخچهٔ صفحه خوندنّی، یا تازه دگاردسته‌ئون صفحه و اطلاعات آخرین دچی‌یه ره، تیناری اشنّی.\n\nدومین حالت سَره، شما بتونّی اتا لینک جه استفاده هاکنین، مثلاً [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] صفحهٔ «[[{{MediaWiki:Mainpage}}]]» وسّه.",
        "allmessages-filter-all": "همه",
        "thumbnail-more": "گت بوو",
        "import-interwiki-submit": "بیاردن",
index 71e6514..6426b3a 100644 (file)
        "talkpagelinktext": "Tèìxnàmikilistli",
        "specialpage": "Nònkuâkìskàtlaìxtlapalli",
        "personaltools": "In tlein nitēquitiltilia",
-       "postcomment": "Yancuīc xeliuhcāyōtl",
        "articlepage": "Xiquittaz in tlahcuilōlli",
        "talk": "tēixnāmiquiliztli",
        "views": "Tlachiyaliztli",
        "yourdomainname": "Moāxcāyō",
        "login": "Ximomachiyōmaca/Ximocalaqui",
        "nav-login-createaccount": "Ximocalaqui / ximomachiyōmaca",
-       "loginprompt": "Tihuīquilia tiquimpiyāz cookies ic ticalaquīz {{SITENAME}}.",
        "userlogin": "Ximomachiyōmaca/Ximocalaqui",
        "userloginnocreate": "Ximocalaqui",
        "logout": "Tiquīzāz",
        "large-file": "Mā tlahcuilōlli ahmo achi huēiyac $1; inīn cah $2.",
        "fileexists-extension": "Tlahcuilōlli zan iuh tōcātica ia: [[$2|thumb]]\n* Tlahcuilōlli moquetzacah: <strong>[[:$1]]</strong>\n* Tlahcuilōlli tlein ia ītōca: <strong>[[:$2]]</strong>\nTimitztlātlauhtiah, xitlahcuiloa occē tōcāitl.",
        "savefile": "Quipiyāz tlahcuilōlli",
-       "uploadedimage": "ōmoquetz \"[[$1]]\"",
-       "overwroteimage": "ōmoquetz yancuīc \"[[$1]]\" iuhcāyōtl",
        "uploaddisabled": "Ahmo mohuelīti tlahcuilōlquetzā",
        "uploaddisabledtext": "Ahmo huelīti moquetzazqueh tlahcuilōlli.",
        "sourcefilename": "Tōcāhuīcpa:",
index f29574c..9a04abb 100644 (file)
        "moredotdotdot": "Iáu-ū",
        "morenotlisted": "這毋是完整的表",
        "mypage": "Ia̍h",
-       "mytalk": "Góa ê thó-lūn",
+       "mytalk": "Thó-lūn",
        "anontalk": "Chit ê IP ê thó-lūn-ia̍h",
        "navigation": "Se̍h chām",
        "and": "&#32;kap",
        "unprotectthispage": "kái chit ia̍h ê pó-hō͘",
        "newpage": "Sin ia̍h",
        "talkpage": "Thó-lūn chit ia̍h",
-       "talkpagelinktext": "thó-lūn",
+       "talkpagelinktext": "Thó-lūn",
        "specialpage": "Te̍k-sû-ia̍h",
        "personaltools": "Kò-jîn kang-khū",
-       "postcomment": "加一段",
        "articlepage": "Khoàⁿ loē-iông ia̍h",
        "talk": "thó-lūn",
        "views": "Khoàⁿ",
        "editinginterface": "'''Sè-jī:''' Lí tng teh siu-kái 1 bīn thê-kiong nńg-thé kài-bīn bûn-jī ê ia̍h. Jīn-hô kái-piàn to ē éng-hióng tio̍h kî-thaⁿ iōng-chiá ê sú-iōng kài-bīn. Nā beh kái hoan-e̍k, chhiaⁿ khì Ûi-ki Mûi-thé chāi-tē-hoà sū-kang [//translatewiki.net/ translatewiki.net] hiâ.",
        "cascadeprotected": "Chit-ê ia̍h í-keng hông pó-hō͘ bē kái tit. In-ūi i tī ē-bīn {{PLURAL:$1|ê|ê}} liân-só pó-hō͘ lāi-té:\n$2",
        "namespaceprotected": "Lí bô khoân-lī kái '''$1'''  miâ-khong-kan ê ia̍h",
+       "customcssprotected": "你無受權去改這个 CSS頁,因為這个頁有包括別个用者的個人設定。",
+       "customjsprotected": "你無授權去改這个JavaScript頁,因為這个頁包括別个用者的個人設定。",
+       "mycustomcssprotected": "你無授權去改這个CSS頁。",
+       "mycustomjsprotected": "你無授權去改這个JavaScript頁。",
+       "myprivateinfoprotected": "你無授權改你家己的私人資訊。",
+       "mypreferencesprotected": "你無授權改你的家己的喜愛設定。",
+       "ns-specialprotected": "特殊頁袂得改。",
+       "titleprotected": "這个標題已經予[[User:$1|$1]]保護起來,袂得提來用。\n原因是 \"<em>$2</em>。",
+       "filereadonlyerror": "因為檔案庫這馬只會使看,所以袂得改 \"$1\"這个檔案。\n鎖檔案庫的管理員講是因為:\"$3\"。",
        "exception-nologin": "Bô teng-ji̍p",
        "exception-nologin-text": "請先[[Special:Userlogin|登入]]了才有法度看這頁抑對這頁做動作。",
        "exception-nologin-text-manual": "請先$1,才有法度看這頁抑對這頁做動作。",
        "externaldberror": "這可能是資料庫驗證錯誤,抑是無允准你改外部的口座。",
        "login": "Teng-ji̍p",
        "nav-login-createaccount": "Teng-ji̍p / khui sin kháu-chō",
-       "loginprompt": "Thiⁿ ē-kha ê chu-liāu thang khui sin hō·-thâu a̍h-sī teng-ji̍p {{SITENAME}}.",
        "userlogin": "Teng-ji̍p / khui sin kháu-chō",
        "userloginnocreate": "Teng-ji̍p",
        "logout": "Teng-chhut",
        "userlogin-resetlink": "你敢袂記得你登入的資料?",
        "userlogin-resetpassword-link": "袂記得你的密碼?",
        "userlogin-helplink2": "協助你登入",
-       "userlogin-loggedin": "你已經用{{GENDER:$1|$1}}登入,用下跤的表,登入別个名。",
-       "userlogin-createanother": "開另外一个口座",
        "createacct-emailrequired": "電子批地址",
        "createacct-emailoptional": "電子批地址(無一定愛寫)",
        "createacct-email-ph": "拍你的電子批地址",
        "badfilename": "Iáⁿ-siōng ê miâ í-keng kái chò \"$1\".",
        "uploadwarning": "Upload kéng-kò",
        "savefile": "Pó-chûn tóng-àn",
-       "uploadedimage": "thoân \"[[$1]]\" chiūⁿ-bāng",
        "uploaddisabled": "Pháiⁿ-sè, sàng chiūⁿ-bāng ê kong-lêng bô khui.",
        "sourcefilename": "Tóng-àn goân miâ:",
        "destfilename": "Tóng-àn sin miâ:",
        "unusedimagestext": "<p>Chhiáⁿ chù-ì: kî-thaⁿ ê bāng-chām ū khó-lêng iōng URL ti̍t-chiap liân kàu iáⁿ-siōng, só·-í sui-jiân chhiâng-chāi teh iōng, mā sī ē lia̍t tī chia.</p>",
        "unusedcategoriestext": "Ū ē-kha chiah-ê lūi-pia̍t-ia̍h, m̄-koh bô kî-thaⁿ ê bûn-chiuⁿ a̍h-sī lūi-pia̍t lī-iōng.",
        "booksources": "Tô͘-su chu-liāu",
-       "specialloguserlabel": "Iōng-chiá:",
-       "speciallogtitlelabel": "Sû-tiâu:",
+       "specialloguserlabel": "做的人:",
+       "speciallogtitlelabel": "目地(標題抑是用者)",
        "log": "記錄",
        "logempty": "Log lāi-bīn bô sio-tùi ê hāng-bo̍k.",
        "allpages": "Só·-ū ê ia̍h",
        "unwatch": "Mài kàm-sī",
        "unwatchthispage": "Mài koh kàm-sī",
        "watchlist-details": "Kàm-sī-toaⁿ ū {{PLURAL:$1|$1 ia̍h|$1 ia̍h}}, thó-lūn-ia̍h bô sǹg chāi-lāi.",
+       "wlnote": "$3 $4: Ē-kha sī <strong>$2</strong> tiám-cheng í-lāi siōng sin ê <strong>$1</strong> ê kái-piàn.",
        "wlshowlast": "Hián-sī chêng $1 tiám-cheng $2 ji̍t $3",
        "deletepage": "Thâi ia̍h",
        "confirm": "Khak-tēng",
        "watchlistedit-normal-submit": "Mài kàm-sī",
        "watchlistedit-normal-done": "Í-keng ū $1 ia̍h ùi lí ê kám-sī-toaⁿ soá cháu:",
        "watchlisttools-edit": "Khoàⁿ koh kái kàm-sī-toaⁿ",
-       "watchlisttools-raw": "Kái tshing-chheng ê kàm-sī-toaⁿ",
+       "watchlisttools-raw": "Kái chhiⁿ ê kàm-sī-toaⁿ",
        "duplicate-defaultsort": "'''Thê-chhíⁿ lí:'''Siat-piān ê pâi-lia̍t hong-sek \"$2\" thè-oāⁿ chìn-chêng ê siat-piān ê pâi-lia̍t hong-sek \"$1\".",
        "version": "Pán-pún",
        "specialpages": "Te̍k-sû-ia̍h",
index 0d09d74..55472c0 100644 (file)
        "tog-underline": "Sottolinia 'e jonte:",
        "tog-hideminor": "Annascunne 'e cagne piccirille  'int'a ll'úrdeme cagne",
        "tog-hidepatrolled": "Annascunne 'e cagne 'verificate' 'int'a ll'úrdeme cagne",
+       "tog-newpageshidepatrolled": "Annascunne 'e paggene cuntrullate 'a ll'elenco 'e ppaggene",
        "tog-extendwatchlist": "Spanne ll'asservate speciale pe fà vedé tutte 'e cagnàmiente, nun solo l'ultimo",
        "tog-usenewrc": "Urdeme càgnamiente avanzate (JavaScript)",
        "tog-numberheadings": "Annúmmera automatecamente 'e títule",
        "tog-showtoolbar": "Aspone 'a barra d''e stromiente 'e cagno",
        "tog-editondblclick": "Cagna 'e pàggene cliccanno ddoje vote",
-       "tog-editsectiononrightclick": "Permette 'e cangne 'e sezzione cliccanno p''o tasto destro ncopp 'e titule 'e sezzione",
+       "tog-editsectiononrightclick": "Permette 'e cagnà 'e sezzione cliccanno p' 'o tasto dritto ncopp' 'e titule 'e sezzione",
+       "tog-watchcreations": "Azzecca 'e ppaggene criate e li files carrecate ncopp'â l'elenco 'e cuntrollo",
+       "tog-watchdefault": "Azzecca 'e paggene e li files cagnàte a l'elenco 'e cuntrollo",
+       "tog-watchmoves": "Azzecca 'e paggene e li files spustate a l'elenco 'e cuntrollo",
+       "tog-watchdeletion": "Azzecca 'e paggene e li files scancellate a l'elenco 'e cuntrollo",
+       "tog-watchrollback": "Azzecca 'e paggene addò aggio fatto nu rollback a l'elenco 'e cuntrollo",
+       "tog-minordefault": "Indica ogne cagnamento comme piccerillo (predefinito)",
+       "tog-previewontop": "Vide previsióne primma d&#39;'a casella 'e modifica",
+       "tog-previewonfirst": "Vide previsióne 'a primma vota",
+       "tog-enotifwatchlistpages": "Famme na mmasciata mail quanno na paggena o nu file dint'a l'elenco 'e cuntrollo se fosse cagnàta",
+       "tog-enotifusertalkpages": "Famme na masciata mail quanno 'a paggena 'e cchiacchiera mmia se fosse cagnàta",
+       "tog-enotifminoredits": "Famme na masciata mail pure quanno se fanno cagnamiente piccerille 'e paggene e files",
+       "tog-enotifrevealaddr": "Fa' vedé 'o ndirizzo mail ncopp'e mmasciate 'e notifica",
+       "tog-shownumberswatching": "Fa' vedé 'o nummero d'utente che teneno 'a paggena cuntrullata",
+       "tog-oldsig": "Firma 'e mmo:",
+       "tog-fancysig": "Piglia 'a firma comme fosse nu wikitesto (senza fà link automatico)",
+       "tog-uselivepreview": "Abilita 'o \"Live preview\" (sperimentale)",
+       "tog-forceeditsummary": "Chiere a mme quanno se sta azzeccanno nu campo oggetto abbacante",
+       "tog-watchlisthideown": "Annascunne 'e cagnamiente d&#39;'a lista 'e cuntrollo mia",
+       "tog-watchlisthidebots": "Annasconne 'e cagnamiènte d&#39;'e bot ncopp'a l'elenco 'e cuntrollo",
+       "tog-watchlisthideminor": "Annascunne 'e cagnamiente piccerille d&#39;'a lista 'e cuntrollo mia",
+       "tog-watchlisthideliu": "Annascunne 'e cagnamiénte 'e l'utente riggistrate 'a l'elenco 'e cuntrollo",
+       "tog-watchlisthideanons": "Annascunne 'e cagnamiente fatte d'anonime 'a l'elenco 'e cuntrollo",
+       "tog-watchlisthidepatrolled": "Annascunne 'e modifiche cuntrullate 'a l'elenco 'e cuntrollo",
+       "tog-ccmeonemails": "Famme na masciata pùre c&#39;'a copia 'e le mail mannate a l'ati utente",
+       "tog-diffonly": "Nun me fà vedé cuntenute aropp'o cunfronto nfra verziune",
+       "tog-showhiddencats": "Fa' vedé 'e categurie annascunnute",
+       "tog-norollbackdiff": "Nun fà vedé 'o cunfronto nfra verziune quanno se fà nu rollback",
+       "tog-useeditwarning": "Famme sapé quanno lasso na paggena 'e mudifeca senza sarvà 'e cagnamiente",
+       "tog-prefershttps": "Usa sempe na connessione sicura quanno s'accummincia sessione",
        "underline-always": "Sèmpe",
        "underline-never": "Màje",
+       "underline-default": "Tiene sempe le mpostazzione d' 'o navigatóre",
+       "editfont-style": "Stile 'e carattere dint' 'a casella 'e testo",
+       "editfont-default": "Predefinito d' 'o navigatóre",
+       "editfont-monospace": "Carattere a larghezza fissa",
+       "editfont-sansserif": "Carattere sans-serif",
+       "editfont-serif": "Carattere Serif",
        "sunday": "dumméneca",
        "monday": "lunnerì",
        "tuesday": "marterì",
        "category_header": "Paggene rìnt'a categurìa \"$1\"",
        "subcategories": "Categurìe secunnarie",
        "category-media-header": "File 'int'â categuría \"$1\"",
+       "category-empty": "<em>Chista categurìa p' 'o mumento nun tene pàggene o media.</em>",
        "hidden-categories": "{{PLURAL:$1|Categurìa annascusa|Categuríe annascuse}}",
+       "hidden-category-category": "Categurìe annascuse",
        "category-subcat-count": "{{PLURAL:$2|Chesta categurìa cuntene n'unneca sottocategurìa, nzignata 'e seguito.|Chesta categurìa cuntene {{PLURAL:$1|'a sottocategurìa nzignata|'e $1 sottocategurìe nzignate}} 'e seguito, 'a nu totale 'e $2.}}",
+       "category-subcat-count-limited": "Chista categurìa tene sti {{PLURAL:$1|sottocategurìa|$1 sottocategurìe}}.",
        "category-article-count": "{{PLURAL:$2|Chesta categurìa cuntiene un'unneca paggena, nzignata ccà sotto.|Chesta categurìa cuntiene {{PLURAL:$1|'a paggena nzignata|'e $1 paggene nzignate}} ccà sotto, faccenno nu totale 'e $2.}}",
+       "category-article-count-limited": "Chista categurìa téne {{PLURAL:$1|sta pàggena|sti $1 pàggene}} dinto.",
+       "category-file-count": "{{PLURAL:$2|Chista categurìa cunténe nu file solo, nzignato ccà sotto.|Chista categurìa cunténe {{PLURAL:$1|nu file, nzignato|$1 file nzignate}} ccà sotto, faccenno nu totale 'e $2.}}",
+       "category-file-count-limited": "Chista categurìa téne {{PLURAL:$1|sta pàggena|sti $1 pàggene}} dinto.",
        "listingcontinuesabbrev": "cont.",
        "index-category": "Paggene ennecezzate",
        "noindex-category": "Paggene nun ennecezzate",
        "moredotdotdot": "Cchiù...",
        "morenotlisted": "Chisto elenco nun è cumpreto.",
        "mypage": "Paggena",
-       "mytalk": "'E mmie chiàcchieriate",
+       "mytalk": "'E chiàcchieriate mmie",
        "anontalk": "Chiacchierate pe chisto IP",
        "navigation": "Navigazzione",
        "and": "&#32;e",
        "permalink": "Jonta permanente",
        "print": "Stampà",
        "view": "Vere",
+       "view-foreign": "Vide ncopp'a $1",
        "edit": "Càgna",
+       "edit-local": "Càgna descrizione lucale",
        "create": "Cria",
+       "create-local": "Azzecca descrizione lucale",
        "editthispage": "Càgna chesta paggena",
        "create-this-page": "Cria sta paggena",
        "delete": "Scancèlla",
        "deletethispage": "Scancèlla chésta paggena",
-       "undeletethispage": "Ripristina chista paggena",
+       "undeletethispage": "Arrepiglia chista paggena",
+       "undelete_short": "Arremedia {{PLURAL:$1|na verziona|$1 vverziune}}",
+       "viewdeleted_short": "Vide {{PLURAL:$1|nu cagnamiénto scancellato|$1 cagnamiénte scancellate}}",
        "protect": "Prutegge",
        "protect_change": "càgna",
        "protectthispage": "Ferma chesta paggena",
        "talkpagelinktext": "Chiàcchiera",
        "specialpage": "Paggena speciàle",
        "personaltools": "Strumiente perzonale",
-       "postcomment": "Nova sezzione",
        "articlepage": "Vere a paggena e contenuto",
        "talk": "Chiàcchiera",
        "views": "Visite",
        "otherlanguages": "Ate lengue",
        "redirectedfrom": "(Redirect 'a $1)",
        "redirectpagesub": "Paggena 'e redirect",
-       "lastmodifiedat": "Urdema cagnamiénto pe' a paggena: $2, $1.",
-       "viewcount": "Chesta paggena è stata lètta {{PLURAL:$1|una vòta|$1 vòte}}.",
+       "redirectto": "Reindirizza a:",
+       "lastmodifiedat": "Urdemo cagnamiénto pe' a paggena: $2, $1.",
+       "viewcount": "Chesta paggena è stata liggiùta {{PLURAL:$1|una vòta|$1 vòte}}.",
        "protectedpage": "Paggena prutetta",
        "jumpto": "Vaje a:",
        "jumptonavigation": "navigazione",
        "jumptosearch": "truova",
+       "view-pool-error": "Ve cercammo scusa, 'e servers hanno troppo carico mo'.\nTroppe utente stanno cercanno 'e veré sta paggena.\nPe' piacere, aspettate nu poco primma 'e turnà a carrecà sta paggena.\n\n$1",
+       "generic-pool-error": "Ve cercammo scusa, 'e servers hanno troppo carico mo'.\nTroppe utente stanno cercanno 'e veré sta risorsa.\nPe' piacere, aspettate nu poco primma 'e turnà a carrecà sta risorsa.",
+       "pool-timeout": "Tiempo pe' s'aspettà ô blocco",
+       "pool-queuefull": "A córa 'e fatiche è chiena",
        "pool-errorunknown": "Errore scanusciuto",
+       "pool-servererror": "'O servizio contatore d''e fatiche nun è a disposizióne ($1).",
        "aboutsite": "'Nfrummazione ncòpp'a {{SITENAME}}",
        "aboutpage": "Project:'Nfrummazione",
        "copyright": "Cuntenute suggiette a licienza 'e auso $1 se nun fuje ritto atro.",
        "copyrightpage": "{{ns:project}}:Copyrights",
-       "currentevents": "Novità",
+       "currentevents": "Nuvità",
        "currentevents-url": "Project:Novità",
        "disclaimers": "Avvertimiènte",
        "disclaimerpage": "Project:Avvertimiènte generale",
        "privacy": "'Nformazzione ppe a privacy",
        "privacypage": "Project:'Nfrummazione ncopp'â privacy",
        "badaccess": "Nun haje 'e premmesse abbastante.",
+       "badaccess-group0": "Nun v'è permesso 'a ffà l'azione richiesta.",
+       "badaccess-groups": "L'azione ch'ê richiesto è permessa sulamente all'utente ca ce stanno dint'a {{PLURAL:$2|'o gruppo|uno d' 'e gruppe}}: $1.",
+       "versionrequired": "Ce vò 'a verziona $1 'e MediaWiki",
+       "versionrequiredtext": "Pe' usà sta paggena ce vò 'a verziona $1 'e MediaWiki. Vide [[Special:Version|'a paggena 'e verzione]].",
        "ok": "OK",
        "retrievedfrom": "Estratto 'e \"$1\"",
-       "youhavenewmessages": "Haje $1 ($2).",
+       "youhavenewmessages": "{{PLURAL:$3|Tenite}} $1 ($2).",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|Tiene}} $1 'a {{PLURAL:$3|n'atu utente|$3 utente}} ($2).",
+       "youhavenewmessagesmanyusers": "Tiene $1 'a tant'utente ($2).",
+       "newmessageslinkplural": "{{PLURAL:$1|na mmasciata nova|999=mmasciate nnove}}",
+       "newmessagesdifflinkplural": "{{PLURAL:$1|urdemo cagnamiento|999=urdeme cagnamiente}}",
        "youhavenewmessagesmulti": "Tiene nuove mmasciate $1",
        "editsection": "càgna",
        "editold": "càgna",
        "toc": "Énnece",
        "showtoc": "faje vedé",
        "hidetoc": "annascunne",
+       "collapsible-collapse": "Annascunne",
        "collapsible-expand": "faje vede",
-       "thisisdeleted": "Vere o ripristina $1?",
+       "confirmable-confirm": "Site {{GENDER:$1|sicuro|sicura}}?",
+       "confirmable-yes": "Sì",
+       "confirmable-no": "No",
+       "thisisdeleted": "Vedè o arripiglià $1?",
        "viewdeleted": "Vire $1?",
+       "restorelink": "{{PLURAL:$1|nu cagnamiénto scancellato|$1 cagnamiénte scancellate}}",
        "feedlinks": "Feed:",
+       "feed-invalid": "'O tipo 'e sottoscrizione p' 'o feed nun è buono",
+       "feed-unavailable": "Nun ce stanno 'e feed sinnecaziona",
+       "site-rss-feed": "Feed 'e sinnecaziona RSS 'e $1",
        "site-atom-feed": "Feed Atom 'e $1",
+       "page-rss-feed": "Feed RSS pe' \"$1\"",
        "page-atom-feed": "Feed Atom ppe \"$1\"",
        "red-link-title": "$1 ('a paggena nun esiste)",
+       "sort-descending": "Urdinamento dicriscente",
+       "sort-ascending": "Urdinamento criscente",
        "nstab-main": "Articulo",
        "nstab-user": "Paggena utente",
+       "nstab-media": "File multimediale",
        "nstab-special": "Paggena speciale",
        "nstab-project": "Paggena 'e servizio",
        "nstab-image": "Fiùra",
        "nstab-template": "Modello",
        "nstab-help": "Ajùto",
        "nstab-category": "Categurìa",
+       "nosuchaction": "Operazione nun ricanusciuta",
+       "nosuchactiontext": "L'azione specificata dint'a l'URL nun è bbona.\nPuò darse ca l'URL fosse stata digitata 'n modo sbagliàto o che fosse stato seguito nu link sbagliàto.\nChesto putesse innecà pùre nu bug dint'a {{SITENAME}}.",
+       "nosuchspecialpage": "Chista paggena speciale nun ce sta",
+       "nospecialpagetext": "<strong>'A paggena speciale richiesta nun è ricanusciuta.</strong>\n\nL'alenco d' 'e paggene valide spiciale 'o truove int'a [[Special:SpecialPages|l'Elenco d' 'e paggine spiciale]].",
+       "error": "Sbaglio",
+       "databaseerror": "Sbaglio dint'a database",
+       "databaseerror-text": "C'è stato nu sbaglio dint'a na richiesta â database.\nPuò darse ca ce sta nu bug int' 'o software",
+       "databaseerror-textcl": "C'è stato nu sbaglio dint'a na richiesta â database.",
+       "databaseerror-query": "Richiesta: $1",
+       "databaseerror-function": "Funzione: $1",
+       "databaseerror-error": "Sbaglio: $1",
+       "laggedslavemode": "'''Attenzione:''' 'a paggena putesse nun fà vedé ll'aggiornamente cchiù recente.",
+       "readonly": "Database bloccato",
+       "enterlockreason": "Miette 'o mutivo 'e blocco, nzieme a 'o mumento quanno se penza ca 'o blocco se sarrà fernuto",
+       "readonlytext": "Mo' mo' 'o database è bloccato e nun se ponno azzeccà cagnamiente o pàggene. 'O blocco è normalmente azzeccato a n'operazione semprice 'e manutenzione, e quanno s'è fernuta allora 'a paggena addeventa nurmale.\n\nL'ammenistratore d' 'o sistema ch'a fatto 'o blocco ce dà sta spiegazione: $1",
+       "missing-article": "'O database nun trova 'o testo 'e na paggena c'adda stà, c' 'o nomme \"$1\" $2.\n\nNormalmente, chesto succere quanno s'è richiamato, a partire d' 'a cronologgia o pùre a 'o confronto tra verzione, nu cullegamento a na paggena scancellata, a nu confronto tra verziune inesistente o a nu confronto tra verziune re-pulezzate d' 'a cronologgia.\n\n'N caso cuntrario, può darse pure nu sbaglio dint'o software.\nPer piacere, mannate na mmasciata ccà all'[[Special:ListUsers/sysop|amministratore]] annummenanno l'URL 'n quistiona.",
        "missingarticle-rev": "(nummero 'e verzione: $1)",
+       "missingarticle-diff": "(Diff: $1, $2)",
+       "readonly_lag": "'O database s'è bloccato automaticamente pe' tramente ca 'e servers 'e database schiave sincronizzano c' 'o server masto.",
        "internalerror": "Errore 'nterno",
        "internalerror_info": "Errore 'nterno: $1",
+       "filecopyerror": "Nun se può copiare 'o file \"$1\" int'a \"$2\".",
+       "filerenameerror": "Nun se può rinnummenare 'o file \"$1\" into \"$2\".",
        "filedeleteerror": "Nun se pô scancellà 'o file \"$1\"",
+       "directorycreateerror": "Nun se può crià 'a cartella \"$1\".",
+       "filenotfound": "Nun se può truvà 'o file \"$1\".",
+       "unexpected": "Valore imprevisto: \"$1\"=\"$2\".",
+       "formerror": "Sbàglio: nun se può mannà 'o modulo",
+       "badarticleerror": "Chest'azione nun se può fà int'a sta paggena.",
        "cannotdelete": "Nun è possibbele scassà 'a paggena o 'a fiura $1 addamannata. Putria éssere stato già scancellato.",
+       "cannotdelete-title": "Nun se può scancellà 'a paggena \"$1\"",
+       "delete-hook-aborted": "'O scancellamiento è stato annullato 'a 'o «hook».\nNun dette spiegazione nisciuna.",
+       "no-null-revision": "Nun se può crià na nnova revisione nulla p' 'a paggena \"$1\"",
        "badtitle": "'O nnomme nun è jùsto",
+       "badtitletext": "'O titolo d' 'a paggena richiesta è abbacante, sbagliato o pure nun è linkato buono a 'o titolo inter-lengua o inter-wiki.\nPutesse pure tené uno o cchiù carattere ca nun se ponno usà dint'e titule.",
+       "perfcached": "Può darse, ch' 'e ddate ca stanno ccà (\"ncache\") nun song'agghiurnate. Nu massimo 'e {{PLURAL:$1|unu risultato è|$1 risultate songhe}} a disposizione 'n \"cache\".",
+       "perfcachedts": "'E ddate ca stanno ccà songhe asciute 'a na copia \"cache\" d' 'o database, 'o cuale tene l'úrdemo agghiurnamento 'o $1. Nu massimo 'e {{PLURAL:$4|unu risultato è|$4 risultate songhe}} a disposizione dint'a \"cache\".",
+       "querypage-no-updates": "Ll'agghiurnamente pe' sta paggena songo sospese mmo'. 'E ddate cuntenute ccà nun s'agghiurnarranno.",
        "viewsource": "Vere sorgente",
        "viewsource-title": "Vere surgente 'e $1",
+       "actionthrottled": "Azione ritardata",
+       "actionthrottledtext": "Comme misura anti-spam, site lemmetato 'a ffà st'azione troppe vote dint'a nu curto spazio 'e tiempo, e mò stu lèmmeto è stato superato.\nPe' piacere pruvate n'ata vota dint'a cocche minuto.",
+       "protectedpagetext": "Sta paggena s'è prutetta pe' ne bloccà 'a mudifeca o n'ata azione.",
+       "viewsourcetext": "Putisse vedé e copià 'o codece surgiva 'e sta paggena:",
+       "viewyourtext": "Putisse vedé e copià 'o codice surgiva d' 'e <strong>cagnamiénte tuoje</strong> a sta paggena:",
+       "protectedinterface": "Sta paggena nce appruviggióna 'e n'interfaccia testo p' 'o software dint'a sta wiki, e s'è prutetta pe' nce scanzà 'e cocch'abbuso.\nSi se buò azzeccà o cagnà traduzzione ncopp'a tutte 'e wiki, pe piacere ausate [//translatewiki.net/ translatewiki.net], 'o pruggetto Mediawiki p'a localizzaziona dint'a l'ate llengue",
+       "editinginterface": "'''Attenziò:''' 'O testo 'e sta paggena ffà parte 'e ll'interfaccia utente d' 'o sito.\nTutt' 'e cagnamiénte fatte a sta paggena cumpareno dint' 'e mmasciate 'e ll'interfaccia veduta 'a tutte ll'utente dint'a sta wiki.\nSi se buò azzeccà o cagnà traduzzione ncopp'a tutte 'e wiki, pe piacere ausate [//translatewiki.net/ translatewiki.net], 'o pruggetto Mediawiki p'a localizzaziona dint'a l'ate llengue",
+       "cascadeprotected": "Sta paggena è stata prutetta 'a 'o cangamento pecché sta dint'a {{PLURAL:$1|sta paggena, che è prutetta|sti paggene, che songo prutette}} quann' 'a l'ozione \"ricurziva\" è attiva:\n$2",
+       "namespaceprotected": "Nun avite permesso a cagnà 'e paggene dint'a stu namespace '''$1'''.",
+       "customcssprotected": "Nun v'è permesso 'a cagnà sta paggena CSS, pecché cuntene 'e mpustaziune perzunale 'e n'at'utente.",
+       "customjsprotected": "Nun v'è permesso 'a cagnà sta paggena JavaScript, pecché cuntene 'e mpustaziune perzunale 'e n'at'utente.",
+       "mycustomcssprotected": "Nun v'è permesso 'a cagnà sta paggena CSS.",
+       "mycustomjsprotected": "Nun v'è permesso 'a cagnà sta paggena JavaScript.",
+       "myprivateinfoprotected": "Nun v'è permesso a cagnà 'a nfurmaziona privata vuosta.",
+       "mypreferencesprotected": "Nun v'è permesso 'a cagnà 'e preferenze tuoje.",
+       "ns-specialprotected": "'E paggene spiciale nun se ponno cagnà.",
+       "titleprotected": "'A criazione 'e stu titolo è stata bloccata 'a ll'utente [[User:$1|$1]].\n'A ragione è chesta: ''$2''.",
+       "filereadonlyerror": "Nun se può cagnà 'o file \"$1\" pecché 'o repository 'e file \"$2\" sta 'n modo sulo-lettura.\n\nL'ammenistratore che l'ha bloccato ha dato sta ragione: \"$3\".",
+       "invalidtitle-knownnamespace": "Titolo nun buono c' 'o namespace \"$2\" e testo \"$3\"",
+       "invalidtitle-unknownnamespace": "Titolo nun buono c' 'o namespace scanusciuto \"$1\" e testo \"$2\"",
        "exception-nologin": "Acciesso nun affettuato",
-       "logouttext": "'''Site asciùte.'''\n\nNota ca arcune paggene potrebbero cuntinuà ad apparire comme se 'o logout nun fosse avvenuto finché nun venne pulita 'a cache d\"o proprio browser.",
+       "exception-nologin-text": "Pe' piacere facite ll'accieso pe putè accedere a sta paggena o azione.",
+       "exception-nologin-text-manual": "Pe' piacere $1 pe putè trasì dint'a sta paggena o azione.",
+       "virus-badscanner": "Sbaglio 'e configurazione: antivirus scanusciuto: ''$1''",
+       "virus-scanfailed": "scanziona fallita (codece $1)",
+       "virus-unknownscanner": "antivirus scanusciuto:",
+       "logouttext": "'''Site asciùte.'''\n\nNota ca arcune paggene putessero cuntinuà ad cumparì comme se 'o logout nun fosse affettuato fin quanno nun sarrà pulezzata 'a cache d\"o proprio browser.",
        "welcomeuser": "Bemmenuto, $1!",
+       "welcomecreation-msg": "'O cunto vuosto è stato criato.\nMo' putite cagnà 'e [[Special:Preferences|preferenze 'e {{SITENAME}}]].",
        "yourname": "Nomme utente",
        "userlogin-yourname": "Nomme utente",
        "userlogin-yourname-ph": "'Nserisce 'o tujo nomme utente",
        "createacct-yourpasswordagain-ph": "'Nserisce 'e novo 'a password",
        "remembermypassword": "Allicuordate d\"a password (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "userlogin-remembermypassword": "Mantienime cullegato",
+       "userlogin-signwithsecure": "Usa na conessione sicura",
        "yourdomainname": "Spiecà 'o dumminio",
+       "password-change-forbidden": "Nun se ponno cagnà 'e password ncopp'a sta wiki.",
+       "externaldberror": "Ce sta n'errore ch' 'e server d'autenticazione esterno, o pure nun v'è permesso accedere all'aghiurnamento d' 'o cunto sterno vuosto.",
        "login": "Tràse",
        "nav-login-createaccount": "Tràse o cria n'acciesso novo",
        "userlogin": "Tràse o cria n'acciesso novo",
        "logout": "Jèsce",
        "userlogout": "Jèsce",
        "notloggedin": "Acciesso nun affettuato",
-       "userlogin-noaccount": "Nun haje ancora n'acciesso?",
-       "nologin": "Nun haje ancora n'acciesso? '''$1'''.",
+       "userlogin-noaccount": "Nun tenite ancora n'acciesso?",
+       "userlogin-joinproject": "Fà 'o riggistro ncopp'a {{SITENAME}}",
+       "nologin": "Nun tenite ancora n'acciesso? '''$1'''.",
        "nologinlink": "Crialo mmo",
        "createaccount": "Cria nu cunto novo",
        "gotaccount": "Tiene già nu cunto? '''$1'''.",
        "gotaccountlink": "Tràse",
-       "userlogin-resetlink": "Haje dimenticato 'e toje date 'e acciesso?",
+       "userlogin-resetlink": "V'avite scurdato 'e dettaglie d'acciesso vuoste?",
+       "userlogin-resetpassword-link": "Te sì scurdat' 'a password?",
+       "userlogin-helplink2": "Aiuto cu l'accieso",
+       "createacct-emailrequired": "Indirizzo email",
+       "createacct-emailoptional": "Indirizzo 'e posta elettronica (ozzionale)",
+       "createacct-email-ph": "Scrive 'o nderizzo mail tuo",
+       "createacct-another-email-ph": "Scrive nderizzo mail",
+       "createaccountmail": "Usa na password qualunque temporanea e manna sta password a l'indirizzo 'e posta e-mail specificato",
+       "createacct-realname": "Nomme riale (ozzionale)",
        "createaccountreason": "Mutivo:",
        "createacct-reason": "Mutivo",
+       "createacct-reason-ph": "Pecché staje crianno n'at'utenza",
+       "createacct-captcha": "Cuntrollo 'e sicurezza",
+       "createacct-imgcaptcha-ph": "Scrive 'o testo ca vire ncoppa",
        "createacct-submit": "Cria 'a toja utenza",
        "createacct-another-submit": "Cria 'n atro account",
        "createacct-benefit-heading": "{{SITENAME}} è fatta 'e perzone comme te.",
        "createacct-benefit-body1": "{{PLURAL:$1|càgnamiento|càgnamiente}}",
        "createacct-benefit-body2": "{{PLURAL:$1|paggena|paggene}}",
+       "createacct-benefit-body3": "{{PLURAL:$1|contribbutòre recente|contribbuttore recente}}",
+       "badretype": "'E passwords ch'è mis nun songe eguale.",
+       "userexists": "'O nomme utente ch'avete miso è già ausàto.\nPe' piacere sciglite n'atu nomme.",
        "loginerror": "Probblema 'e accièsso",
+       "createacct-error": "Errore 'e criazione 'e cunto",
+       "createaccounterror": "Nun se può crià nu cunto: $1",
+       "nocookiesnew": "'A riggistrazione è stata completata, ma nun se può accedere a {{SITENAME}} pecché 'e cookie songo disattivate. Prova n'ata vota c' 'o nomme e 'a password quanno 'e cookie sarrann'attivate dint'o navigatore stesso.",
+       "nocookieslogin": "{{SITENAME}} usa cookies pe' putè dà accies'a ll'utente.\n'E cookies vuoste songo stutate.\nPe' piacere appicciate 'e cookies dint'o navigatóre e pruvate n'ata vota.",
+       "nocookiesfornew": "'O cunto utente nu s'è criato, pecché nun s'è potuto confirmà d' 'a fonte suja.\nVide si 'e cookies song'appicciate, ricarreca 'a paggena e prova n'ata vota.",
+       "noname": "Nun avite specificato nu nomme valido d'utente.",
        "loginsuccesstitle": "Acciesso affettuato",
        "loginsuccess": "'''Si stato cunnesso ô server 'e {{SITENAME}} cu 'o nomme utente 'e \"$1\".'''",
+       "nosuchuser": "Nun è riggistrato nisciuno utente c' 'o nomme \"$1\".\n'E nomme utente songo sensibbele a 'e maiuscole.\nCuntrolla 'o nomme nzertàto, o [[Special:UserLogin/signup|crìa n'utenza nova]].",
        "nosuchusershort": "Nun ce stanno utente cu o nòmme \"$1\". Cuntrolla si scrivìste buòno.",
        "nouserspecified": "Tiene 'a dìcere nu nomme pricìso.",
+       "login-userblocked": "Chist'utente è bloccato. Nun se può effettuà 'o login.",
+       "wrongpassword": "'A password nzertàta nun è bbona.\nPe' piacere pruvate n'ata vota.",
+       "wrongpasswordempty": "'A password nzertàta è abbacante.\nPe' piacere pruvate n'ata vota.",
+       "passwordtooshort": "'E password hann'avé minimo {{PLURAL:$1|nu carattere|$1 carattere}}.",
+       "password-name-match": "'A password adda essere diverza 'a 'o nomme utente.",
+       "password-login-forbidden": "L'uso 'e stu nomme utente e password è stato proibito.",
+       "mailmypassword": "Riabbìa 'a password",
+       "passwordremindertitle": "Nnova password temporale pe' {{SITENAME}}",
+       "passwordremindertext": "Cocche perzona (pussibbilmente tu, cu n'innerizzo IP $1) ha dimmannato l'invio 'e na password d'accieso nova pe' {{SITENAME}} ($4).\nNa password temporanea e' l'utente \"$2\" s'è abbiata comme \"$3\".\nSi chest'è stata l'intenzione toja, allora hè a trasì dint'o sito e cagnà 'a password mò. 'A password temporanea scade aropp'a {{PLURAL:$5|nu juorno|$5 ghiuorne}}.\n\nSi nun sì stato tu a dimannà 'a password, o pure hè truvat'a password e nun 'a bbuò cagnà cchiù, allora nun fà niente e continua a usare 'a password viecchia.",
+       "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.",
+       "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",
        "acct_creation_throttle_hit": "{{PLURAL:$1|1 registrazzione è già stata effettuata|$1 registrazzione song già state effettuate}} 'e qualcuno cu 'o tujo stisso innerezzo IP dint'ô urdemo juorno: è 'o massimo cunsentito 'n chisto periodo 'e tiempo.\nPerciò, 'e utente ca ausano chisto innerezzo IP nun possono registrarse ppe 'o mumiento.",
+       "emailauthenticated": "'O ndirizzo email è stato cunfermato 'o $2 a 'e $3.",
+       "emailnotauthenticated": "'O ndirizzo 'e posta elettronica nun è stat'ancora cunfermato.\nNun se mannarranno mmasciate e-mail p' ' funzione ccà abbascio.",
+       "noemailprefs": "Avite 'a specificà nu ndirizzo e-mail pe ll'attivà sti funzione.",
+       "emailconfirmlink": "Cunferma 'o nderizzo mail d' 'o tujo.",
+       "invalidemailaddress": "'O nderizzo e-mail scritto nun se può accettà pecché nun tene nu furmatto buono.\nScrive n'ata vota nu nderizzo bbuono o abbacanta 'a casella.",
+       "cannotchangeemail": "'E ccunte mail nun se ponno cagnà dint'a sta wiki.",
+       "emaildisabled": "Chistu sito nun può mannà mmasciate e-mail.",
        "accountcreated": "Cunto criato",
+       "accountcreatedtext": "È stata criata n'utenza pe' [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|mmasciata]]).",
+       "createaccount-title": "Criazione 'e nu cunto pe' {{SITENAME}}",
+       "createaccount-text": "Coccherun ave fatto nu cunto ncoppa {{SITENAME}} ($4) a nomme 'e $2, associato a st'indirizzo 'e posta elettronica. 'A password pe l'utente \"$2\" è abbiàta a comme \"$3\".\nFosse buono 'e trasì ampressa e cagnà 'a password subbeto.\n\nSi 'a criazione d' 'o cunto è stata nu sbaglio, allora putite lassà perde sta mmasciata.",
+       "login-throttled": "Songo state fatte troppe tentative 'a trasì dint'a nu periodo troppo curto.\nAspetta nu $1 e prova aròppo.",
+       "login-abort-generic": "'O login tujo nun ha avuto succiesso - Annullato",
+       "login-migrated-generic": "'O cunto tuo nun sè mmigrato, e l'username d' 'o tuojo nun esiste cchiù dint'a sta wiki.",
        "loginlanguagelabel": "Lengua: $1",
+       "suspicious-userlogout": "'A richiesta 'e disconnessione d' 'a toja è stata negate pecché pare ca fosse mannata 'a nu navigatóre rutto o nu proxy 'e \"caching\".",
+       "createacct-another-realname-tip": "'O nomme overo vuosto è ozzionale.\nSi sciglite 'e nzertà 'o nomme overo, chesto s'ausarrà pe' dà l'utente l'attribuzione d' 'a fatica fatta.",
+       "pt-login": "Tràse",
+       "pt-login-button": "Tràse",
+       "pt-createaccount": "Cria nu cunto nuovo",
+       "pt-userlogout": "Jèsce",
+       "php-mail-error-unknown": "Errore scanusciuto dint'a funzione PHP mail()",
+       "user-mail-no-addy": "Avite cercato 'e mannà na mmasciata e-mail senza indirizzo.",
+       "user-mail-no-body": "Avite cercato 'e mannà na mmasciata e-mail c' 'o testo abbacante o troppo curto.",
        "changepassword": "Cagna password",
+       "resetpass_announce": "Pe' trasì finalmente, avite 'abbià na password nova.",
+       "resetpass_header": "Cagna 'a password d' 'o cunto",
+       "oldpassword": "Password viecchia:",
+       "newpassword": "Password nova:",
+       "retypenew": "Ripete 'a password:",
+       "resetpass_submit": "Stabbelisce 'a password e tràse",
+       "changepassword-success": "'A password è stata cagnata currettamente!",
+       "changepassword-throttled": "Songo state fatte troppe tentative 'a trasì.\nAspetta nu $1 apprimma 'e pruvà n'ata vota.",
+       "resetpass_forbidden": "'E password nun se ponno cagnà",
+       "resetpass-no-info": "Avite 'a trasì ('o login) pe ffà l'acciesso a sta paggena direttamente.",
+       "resetpass-submit-loggedin": "Cagna password",
        "resetpass-submit-cancel": "Canciella",
+       "resetpass-wrong-oldpass": "'A password temporanea o attuale nun è bbona.\n'A password putesse avé cagnato, o pure s'è addimannata na password temporanea nova.",
+       "resetpass-recycled": "Pe piacere riabbiate 'a password e mettete na password differénte a chella 'e mmò.",
+       "resetpass-temp-emailed": "Sì trasuto cu nu codece temporaneo, mannato via e-mail. Pe' fà cumpleta 'a riggistraziona, avite 'e abbià na password nova ccà:",
+       "resetpass-temp-password": "Password temporanea:",
+       "resetpass-abort-generic": "'O cagnamiento d' 'a password s'è spezzato 'a na stensione.",
+       "resetpass-expired": "'A pasword è ammaturata. Avite 'e ffà na password nova pe putè trasì.",
+       "resetpass-expired-soft": "'A pasword toja è ammaturata e s'adda riabbià. Avite 'e scegliere na password nova mò, o ffà click ncopp'a \"{{int:resetpass-submit-cancel}}\" p' 'a riabbià aroppo.",
+       "resetpass-validity-soft": "'A password toja nun è bbona: $1\n\nAvite 'e scegliere na password nova mò, o ffà click ncopp'a \"{{int:resetpass-submit-cancel}}\" p' 'a riabbià aròppo.",
+       "passwordreset": "Riabbìa 'a password",
+       "passwordreset-text-one": "Ghienche stu modulo pe' ricevere na mmasciata e-mail c' 'a password temporanea.",
+       "passwordreset-text-many": "{{PLURAL:$1|Ghienche uno d' 'e campe pe' ricevere na password temporanea cu na mmasciata e-mail.}}",
+       "passwordreset-legend": "Riabbìa 'a password",
+       "passwordreset-disabled": "'A funzione 'e riabbìo d' 'e password è stata stutata dint'a sta wiki.",
+       "passwordreset-emaildisabled": "'E funzione e-mail songo state stutate dint'a sta wiki.",
        "passwordreset-username": "Nomme utente:",
        "passwordreset-domain": "Duminio:",
+       "passwordreset-capture": "Vulite vedé 'e cuntenute d' 'a mmasciata mail?",
+       "passwordreset-capture-help": "Si se seleziona sta cascia, 'a mmasciata e-mail (c' 'a password temporanea), se mmustarrà a vuje e poi pure se mannarrà a l'utente.",
+       "passwordreset-email": "Indirizzo e-mail:",
+       "passwordreset-emailtitle": "Dettaglie d' 'o cunto pe' {{SITENAME}}",
+       "passwordreset-emailtext-ip": "Coccherun (può darse ca sì tu, cu n'indirizzo IP $1) ha addimannato na mmasciata c' 'a password nova pe' putè trasì a {{SITENAME}} ($4). {{PLURAL:$3|L'utente associato|L'utente associate}} a st'indirizze e-mail songo:\n\n$2\n\n{{PLURAL:$3|Sta password temporanea ammaturarrà|Sti password temporanee ammaturarranno}} aropp'a {{PLURAL:$5|nu juorno|$5 ghiuorne}}.\nHè 'a trasì e scegliere na password nova mò. \n\nSi nun sì stato tu a fà sta richiesta, o te sì scurdat' 'a password origginale e nun 'a buò cagnà cchiù, lassa perde sta mmasciata e usa 'a password viecchia.",
+       "passwordreset-emailtext-user": "L'utente $1 di {{SITENAME}} ha addimannato na mmasciata c' 'a password nova pe' putè trasì a {{SITENAME}} ($4). {{PLURAL:$3|L'utente associato|L'utente associate}} a st'indirizze e-mail songo:\n\n$2\n\n{{PLURAL:$3|Sta password temporanea ammaturarrà|Sti password temporanee ammaturarranno}} aropp'a {{PLURAL:$5|nu juorno|$5 ghiuorne}}.\nHè 'a trasì e scegliere na password nova mò. \n\nSi nun sì stato tu a fà sta richiesta, o te sì scurdat' 'a password origginale e nun 'a buò cagnà cchiù, lassa perde sta mmasciata e usa 'a password viecchia.",
+       "passwordreset-emailelement": "Nomme utente: $1\nPassword temporanea: $2",
+       "passwordreset-emailsent": "Na mmasciata e-mail pe' riabbià 'a password è stata mannata.",
+       "passwordreset-emailsent-capture": "Na mmasciata e-mail pe' riabbià 'a password è stata mannata, chista mmasciata 'a putite vedé ccà abbascio.",
+       "passwordreset-emailerror-capture": "Na mmasciata e-mail pe' riabbià 'a password è stata mannata, 'a putite vedé ccà abbascio, ma aita sapé ca nun s'è mannata a {{GENDER:$2|l'utente}} pecché c'è stato cocch'errore: $1",
+       "changeemail": "Cagna l'indirizzo e-mail",
+       "changeemail-header": "Cagna l'indirizzo e-mail d' 'o cunto",
+       "changeemail-text": "Ghienchete stu modulo pe' cangà l'indirizzo mail d' 'o vuosto. Sarrà necessario nzertà 'a password vosta pe' puté cunfermà stu cagnamiento.",
+       "changeemail-no-info": "Avite 'a trasì ('o login) pe ffà l'acciesso a sta paggena direttamente.",
+       "changeemail-oldemail": "Indirizzo email 'e mmò:",
+       "changeemail-newemail": "Indirizzo e-mail nuovo:",
        "changeemail-none": "(nisciuno)",
+       "changeemail-password": "'A password vosta pe' {{SITENAME}}:",
+       "changeemail-submit": "Cagna e-mail",
        "changeemail-cancel": "Canciella",
+       "changeemail-throttled": "Avite fatto troppe tentative 'a trasì.\nAspettate nu $1 apprimma 'e pruvà n'ata vota.",
+       "resettokens": "Riabbìa 'e token",
+       "resettokens-text": "Ccà se ponno riabbià 'e chiave ca permetessero l'acciesso a determinate date private associate a 'o cunto vuosto.\n\nL'aviste 'e ffà quanno l'avete spartuto pe' sbaglio cu cocche perzona o pure quanno 'o cunto d' 'o vuosto è stato compromesso.",
+       "resettokens-no-tokens": "Nun ce stanno token 'a riabbià.",
+       "resettokens-legend": "Riabbìa 'e token",
+       "resettokens-tokens": "Token:",
+       "resettokens-token-label": "$1 (valore 'e mmò: $2)",
+       "resettokens-watchlist-token": "Token p' 'o feed web (Atom/RSS) d' 'e [[Special:Watchlist|cagnamiente a 'e paggene dint'a l'osservate spiciale tuoje]]",
+       "resettokens-done": "Token riabbiate.",
+       "resettokens-resetbutton": "Riabbìa 'e token scigliute",
        "bold_sample": "Grassetto",
        "bold_tip": "Grassetto",
        "italic_sample": "Corsivo",
        "link_sample": "Titulo ddo cullegamente",
        "link_tip": "Jonte nterne",
        "extlink_sample": "http://www.example.com titulo ddo cullegamente",
+       "extlink_tip": "Link esterno (arricuordate 'o prefisso http:// )",
        "headline_sample": "Testate",
        "headline_tip": "Testate 'e 2° livello",
+       "nowiki_sample": "Azzeccà 'o testo nun-furmattato ccà",
+       "nowiki_tip": "Lassa perde' 'a furmattazione wiki",
        "image_sample": "Essempio.jpg",
        "image_tip": "Fiùra ncuorporata",
        "media_tip": "Cullegamente a file multimediale",
+       "sig_tip": "Firma cu data e ora",
+       "hr_tip": "Linea orizzontale (ausà cu gedizzio)",
        "summary": "Énnece",
+       "subject": "Argomiento/titolo:",
        "minoredit": "Chisto è nu cagnamiénto piccerillo",
        "watchthis": "Tiene d'uocchio chesta paggena",
        "savearticle": "Sarva 'a paggena",
        "preview": "Anteprimma",
        "showpreview": "Vere anteprimma",
        "showdiff": "Fa veré 'e cagnamiente",
+       "blankarticle": "<strong>Attenziò:</strong> 'a paggena ca staje crianno è abbacante.\nFà click ncopp'a \"{{int:savearticle}}\" n'ata vota, 'a paggena sarrà criata senza cuntenute.",
+       "anoneditwarning": "'''Attenzione:''' Nun avite fatto l'acciesso. 'A cronologgia d' 'a vosta sarrà visibbele pubbrecamente si facite cocche cagnamiento. Si <strong>[$1 tràse]</strong> o <strong>[$2 crìe nu cunto]</strong>, 'e cagnamiente vuoste ve sarranno attribbuite a vvuje, nzieme a n'ati migliuramente.",
+       "anonpreviewwarning": "''Nun avite fatto 'o login. Sarvann' 'a paggena, l'indirizzo IP d' 'o vuosto sarrà riggistrato dint'a cronologgia.''",
+       "missingsummary": "'''Attenziò:''' nun s'è specificato l'oggetto 'e stu cagnamiento. Clicann' 'a \"{{int:savearticle}}\" n'ata vota 'o cagnamiento sarrà sarvato cu l'oggetto abbacante.",
+       "missingcommenttext": "Pe' piacere scrivete nu commento ccà abbascio.",
+       "missingcommentheader": "'''Attenziò:''' nun s'è specificato l'oggetto/titolo 'e stu commento. Clicann' 'a \"{{int:savearticle}}\" n'ata vota 'o cagnamiento sarrà sarvato c' 'o titolo abbacante.",
+       "summary-preview": "Anteprimma'e l'oggetto:",
+       "subject-preview": "Anteprima 'e l'oggetto/intestazione:",
+       "blockedtitle": "Utente bloccato.",
+       "blockedtext": "<strong>'O nomme utente o ll'IP vuosto è stato bloccato.</strong>\n\n'O blocco è stato mpustato 'a $1. 'O mutivo d' 'o blocco è chesto: ''$2''\n\n* Abbiàta d' 'o blocco: $8\n* Ammaturità d' 'o blocco: $6\n* Tiempo 'e blocco: $7\n\nPutite cuntattà $1 o n'atu [[{{MediaWiki:Grouppage-sysop}}|ammenistratore]] pe' discutere 'o blocco.\n\nVedite c' 'a funzione 'Scrivete a ll'utente' nun è attiva si nun s'è riggistrato 'o ndirizzo e-mail buono dint' 'e [[Special:Preferences|preferenze]] o pùre si ll'uso 'e tale funzione è stato bloccato.\n\n'O ndirizzo IP attuale è $3, 'o nummero ID d' 'o blocco è #$5.\nPe' piacere avite 'e specificà tutte sti dettaglie ccà ncoppa quanno facite cocche dumanna.",
+       "autoblockedtext": "Ll'IP vuosto è stato bloccato pecché 'o steva piglianno n'atu utente, ch'è stato bloccato pe' $1.\n\n'O mutivo d' 'o blocco è chesto:\n\n:''$2''\n\n* Abbiàta d' 'o blocco: $8\n* Ammaturità d' 'o blocco: $6\n* Tiempo 'e blocco: $7\n\nPutite cuntattà $1 o n'atu [[{{MediaWiki:Grouppage-sysop}}|ammenistratore]] pe' discutere 'o blocco.\n\nVedite c' 'a funzione 'Scrivete a ll'utente' nun è attiva si nun s'è riggistrato 'o ndirizzo e-mail buono dint' 'e [[Special:Preferences|preferenze]] o pùre si ll'uso 'e tale funzione è stato bloccato.\n\n'O ndirizzo IP attuale è $3, 'o nummero ID d' 'o blocco è #$5.\nPe' piacere avite 'e specificà tutte sti dettaglie ccà ncoppa quanno facite cocche dumanna.",
+       "blockednoreason": "nisciuna ragione è stata indicata",
+       "whitelistedittext": "Pe' cagnà 'e ppaggene è necessario $1.",
+       "confirmedittext": "Pe puté cagnà paggene avite 'a cunfermà l'indirizzo e-mail.\nPe' piacere abbiate e ffà 'a validazione d' 'o ndirizzo e-mail pe' bbìa d' 'e [[Special:Preferences|preferenze d'utente]].",
+       "nosuchsectiontitle": "Nun se può truvà 'a sezziona",
+       "nosuchsectiontext": "Hè pruvat' 'a cagnà na sezziona ca nun ce sta.\nPuò darse ch'è stata spustata o scancellata pe' tramente ca stive vedenno sta paggena.",
        "loginreqtitle": "Pe' cagnà chesta paggena abbesognate aseguì ll'acciesso ô sito.",
        "loginreqlink": "aseguì ll'acciesso",
        "loginreqpagetext": "Pe' veré ate ppaggene abbesognate $1.",
        "accmailtitle": "'O password è stato mannato.",
        "accmailtext": "'Na password gennerata casualmente ppe [[User talk:$1|$1]] è stata mannata a $2. Chista password può essere càgnata dint'â paggena ppe ''[[Special:ChangePassword|càgna 'a password]]'' subbeto doppo l'acciesso.",
        "newarticle": "(Novo)",
+       "newarticletext": "Site ghiuto/a addò nu link 'e na paggena ca nun esiste ancora.\nP' 'a crià sta paggena, accummenciate a scrivere dint'a cascia cà abbascio (vedite 'a [$1 paggena d'aiuto] pe liegge cchiù nfurmazziune).\nSi site venuto/a ccà pe' sbaglio, vedite 'e sprémmere 'o buttòne '''Arreto''' d' 'o navigatóre.",
+       "anontalkpagetext": "----\n''Chest'è 'a paggena 'e discussione 'e n'utente anonimo, ca nun ave criàt' 'ancora n'utenza o ca nun sta ausanno. Pe' l'identificà avite 'e truvà 'o nummero d' 'o ndirizzo IP d' 'o sujo. L'indirizze IP se ponno spartì però a cchiù 'e n'utente. Si sì n'utente anonimo e pienze ca 'e commente ccà dint'a sta paggena nun parlano 'e tte, allora [[Special:UserLogin/signup|crìa n'utenza nnova]] o [[Special:UserLogin|tràse cu chella ca tiene già]] pe' nun sta' mmescato mmiez'a l'ati utente anonime n futuro.''",
+       "noarticletext": "Mo' mo' 'a paggena richiesta è abbacante. Se pò [[Special:Search/{{PAGENAME}}|ascià stu titolo]] dint'a l'ati paggene d' 'o sito, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ascià dint'e riggistre azzeccate] o pure [{{fullurl:{{FULLPAGENAME}}|action=edit}} cagnà 'a paggena mo']</span>.",
+       "noarticletext-nopermission": "Mo' mo' 'a paggena richiesta è abbacante. Se pò [[Special:Search/{{PAGENAME}}|ascià stu titolo]] dint'a l'ati paggene d' 'o sito, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ascià dint'e riggistre azzeccate]</span>, però nun tenite 'o permesso 'a crià sta paggena.",
+       "missing-revision": "'A verziona #$1 d' 'a paggena \"{{FULLPAGENAME}}\" nun esiste.\n\nChest'è causato quanno se và dint'a nu link a na paggena ch'è stata scancellata.\n'E dettaglie se ponno truvà dint'a [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 'o riggistro 'e scancellamiente].",
+       "userpage-userdoesnotexist": "'O cunto utente \"<nowiki>$1</nowiki>\" nun è riggistrato. Cuntrolla ca si buò overo crià o cagnà sta paggena.",
+       "userpage-userdoesnotexist-view": "'O cunto utente \"$1\" nun è riggistrato.",
+       "blocked-notice-logextract": "St'utente è bloccato mò.\nL'urdemo elemento d' 'o riggistro 'e blocche è ripurtato ccà abbascio p'avé nu riferimento:",
+       "clearyourcache": "'''Nota:''' aropo sarvate putisse necessità 'e pulezzà 'a caché d' 'o navigatóre pe' vedé 'e cagnamiente. \n*'''Firefox / Safari''': sprémme 'o buttóne maiuscole e ffà clic ncopp'a ''Recarreca'', o pure spremme ''Ctrl-F5'' o ''Ctrl-R'' (''⌘-R'' ncopp'a Mac)\n*'''Google Chrome''': spremme ''Ctrl-Shift-R'' (''⌘-Shift-R'' ncopp'a nu Mac)\n*'''Internet Explorer''': spremme 'o buttóne ''Ctrl'' pe' tramente ca faie click ncopp'a ''Refresh'', o pure spremmere ''Ctrl-F5''\n*'''Opera''': abbacanta tutt' 'a cache addò menu ''Strumiente → Preferenze''",
+       "usercssyoucanpreview": "'''Cunziglio:''' spremme 'o buttone 'Vide anteprimma' pe' pruvà 'o CSS nuovo apprimma d' 'o sarvà.",
+       "userjsyoucanpreview": "'''Cunziglio:''' spremme 'o buttone 'Vide anteprimma' pe' pruvà 'o JavaScript nuovo apprimma d' 'o sarvà.",
+       "usercsspreview": "'''Arricuordate ca chest'è sulamente n'anteprimma p' 'o CSS perzunale. 'E cagnamiente nun so' state ancora sarvate!'''",
+       "userjspreview": "'''Arricuordate ca chest'è sulamente n'anteprimma p' 'o JavaScript perzunale. 'E cagnamiente nun so' state ancora sarvate!'''",
+       "sitecsspreview": "'''Arricuordate ca chest'è sulamente n'anteprimma p' 'o CSS. 'E cagnamiente nun so' state ancora sarvate!'''",
+       "sitejspreview": "'''Arricuordate ca chest'è sulamente n'anteprimma p' 'o codece JavaScript. 'E cagnamiente nun so' state ancora sarvate!'''",
+       "userinvalidcssjstitle": "'''Attenziò:''' Nun esiste nisciuna skin c' 'o nomme \"$1\". Vide ch' 'e paggene .css e .js personalezzate teneno nu titolo n minucola, p'esempio {{ns:user}}:Esempio/vector.css e nun {{ns:user}}:Esempio/Vector.css.",
+       "updated": "(Agghiurnato)",
+       "note": "'''Nota:'''",
        "previewnote": "'''Chesta è sola n'anteprimma; 'e cagnamiénte â paggena nun songo ancora sarvate!'''",
+       "continue-editing": "Tràse int'a l'area 'e modifica",
+       "previewconflict": "L'anteprimma currisponne a 'o testo presente dint'a cascia 'e modifica ccà ncoppa e rappresentasse 'a paggena comme cumpare si sciglite 'e Sarvà ind'a stu mumento.",
+       "session_fail_preview": "'''Nun è possibbile prucessà 'o cagnamiento pecché se so' sperdut' 'e date d' 'a sessione.\nProva n'ata vota.\nSi nun funziona ancora, può pruvà 'a te [[Special:UserLogout|n'ascì]] e a trasì n'ata vota.'''",
+       "session_fail_preview_html": "'''Nun è possibbile prucessà 'o cagnamiento pecché se so' sperdut' 'e date d' 'a sessione.\nProva n'ata vota.'''\n''Siccome dint' 'o {{SITENAME}} è abilitato l'uso 'e l'HTML cruro, 'o buttone d'anteprimma nun è abbiàto comme misura 'e sicurezza annanza cocch'attacco JavaScript''\n'''Si chest'era nu tentativo legittimo 'e cagnamiento, prova n'ata vota. Si nun funziona ancora, può pruvà 'a te [[Special:UserLogout|n'ascì]] e a trasì n'ata vota.'''",
+       "token_suffix_mismatch": "'''Stu cagnamiento nun è stato sarvato pecché 'o client ave mmustato nu sbaglio dint'o scrivere d' 'e carattere d' 'a punteggiatura token. Pe luvà na possibbile corruzione d' 'o testo dint'a paggena, s'è rifiutat' 'a modifeca.\n\nSta situazione se può truvà, quanno staje ausanno nu servizio 'e proxy anonime via web cu d' 'e bug.'''",
+       "edit_form_incomplete": "'''Cocche parte d' 'o modulo 'e cagnamiento nun ha arrivato a 'o server; cuntrolla ch' 'e cagnamiente songo intatte e prova n'ata vota.'''",
        "editing": "Cagnamiento 'e $1",
+       "creating": "Staje crianno $1",
        "editingsection": "Cagnamiénto 'e $1 (sezzione)",
+       "editingcomment": "Cagnamiénto 'e $1 (nova sezzione)",
+       "editconflict": "Conflitto d'edizzione: $1",
+       "explainconflict": "N'at'utente ave sarvato na nova verziona d' 'a paggena pe' tramente ca stevate a fà 'e cagnamiente.\n'A cascia 'e mudifeca ncoppa cuntene 'o testo d' 'a paggena ca mò sta online, accussì comme è stato agghiurnato a l'at'utente.\n'A verziona ch' 'e cagnamiente vuoste è stata mmece riportata dint'a cascia 'e mudifeca abbascio.\nSi 'e vulite cunfermà avite 'a ripurtà 'e cagnamiente d' 'e vuoste dint'o testo ca esiste (dint'a cascia ncoppa).\nSpremmendo 'o buttón '{{int:savearticle}}', sarrà sarvato '''sulamente''' 'o testo cuntenuto dint'a cascia 'e cagnamiento ncoppa.",
+       "yourtext": "'O testo vuosto",
+       "storedversion": "A verziona 'n memoria",
+       "nonunicodebrowser": "'''Attenziò: state ausanno nu navigatóre ca nun è compatibbele ch' 'e carattere Unicode. Pe' ve permettere 'o cagnamiento d' 'e paggene senza crià ncunveniente, 'e carattere nun ASCII veneno viste dint' 'a cascia 'e cagnamiento sotto forma 'e codece esadecimale.'''",
+       "editingold": "'''Attenziò: staje cagnanno na verziona nun agghiurnata d' 'a paggena. Si 'a sarve accussì, tutte 'e cagnamiente fatte aropp'a sta verziona sarranno sperdute.'''",
+       "yourdiff": "Differenze",
+       "copyrightwarning": "Pe' piacere tenite a mmente ca tutte 'e contribbute a {{SITENAME}} songo cunziderate pubbrecate dint'e térmene d'uso d' 'a licienza $2 (vedite $1 pe n'avé cchiù dettaglie).\nSi nun vulite ca 'e testi vuoste fossero cagnate e distribuite 'a uno qualunque senza lémmeto, nun 'e mannate ccà.<br />\nMannanno stu testo dichiarate pùre, sott'a responsabilità vuosta, ch'è stato scritto 'a vuje perzunalmente o pure ca è stato copiato 'a na fonte n pubblico dominio o similarmente libbera.\n'''Nun mannate materiale prutetto 'a copyright senz'avé autorizzaziona!'''",
+       "copyrightwarning2": "Pe' piacere tenite a mmente ca tutte 'e contribbute a {{SITENAME}} se ponno cagnà, alterà, o distribbuì pe l'ati cuntribbuttòre.\n\nSi nun vulite ca 'e teste vuoste fossero cagnàte spenzieratamente, nun 'e mannate ccà.<br />\nMannanno stu testo dichiarate pùre, sott'a responsabilità vosta, ch'è stato scritto 'a vuje perzunalmente o pure ca è stato copiato 'a na fonte n pubblico dominio o similarmente libbera (vedete $1 pe' n'avé dettaglie).\n'''Nun mannate materiale prutetto 'a copyright senza n'avé autorizzaziona!'''",
+       "longpageerror": "'''Errore: 'o testo mannato è luongo {{PLURAL:$1|1|$1}} kilobyte, ch'è cchiù grosso d' 'a diminziona massima cunzentita ({{PLURAL:$2|1|$2}} kilobyte).'''\n'O testo nun se pò sarvà.",
+       "readonlywarning": "<strong>Attenziò</strong>: 'o database è bloccato pe se ffà 'a manutenzione. P' 'o mumento nun se ponno sarvà 'e cagnamiente fatte.\nPe' nun 'e sperdere, copia sti cuntenute dint'a nu file 'e testo e sarvatillo pe' tramente c'aspiette 'o sblocco d' 'o database.\n\nL'ammenistratore ca mpustaje 'o blocco ave scritto sta spiegazione: $1.",
+       "protectedpagewarning": "'''Attenziò: sta paggena è stata bloccata 'n modo tale ca sulamente l'utente ch' 'e privilegge d'ammenistratore 'a ponno cagnà.'''\nL'urdemo elemento d' 'o riggistro è scritto ccà abbascio pe' n'avé riferimento:",
+       "semiprotectedpagewarning": "'''Nota:''' Sta paggena è stata bloccata 'n modo ca sulamente l'utente riggistrate 'a ponno cagnà.\nL'urdemo elemento d' 'o riggistro è scritto ccà abbascio pe n'avé nfurmazione:",
+       "cascadeprotectedwarning": "'''Attenziò:''' Sta paggena è stata bloccata 'n modo ca sulamente l'utente ch' 'e privilegge d'ammenistratore 'a ponno cagnà. Chesto succiere pecché 'a paggena è dint'a {{PLURAL:$1|la paggena innecata ccà abbascio, ch'è stata prutetta|'e paggene innecate ccà abbascio, che so' state prutette}} sciglienno 'a prutezione \"ricurziva\":",
+       "titleprotectedwarning": "'''Attenziò: sta paggena è stata bloccata 'n modo ca fossero necessarie [[Special:ListGroupRights|deritte specifici]] p' 'a crià.'''\nL'urdemo elemento d' 'o riggistro è riportato ccà abbascio pe nfurmazione:",
        "templatesused": "{{PLURAL:$1|Template|Templates}} ausate 'a chesta paggena:",
+       "templatesusedpreview": "{{PLURAL:$1|Template|Templates}} ausate dint'a st'anteprimma:",
+       "templatesusedsection": "{{PLURAL:$1|Template|Templates}} ausate dint'a sta sezziona:",
        "template-protected": "(prutetto)",
        "template-semiprotected": "(semi-prutetto)",
+       "hiddencategories": "Sta paggena attócca a {{PLURAL:$1|na categurìa annascunnuta|$1 categurìe annascunnute}}:",
+       "nocreatetext": "{{SITENAME}} ha limitato 'a possibilità 'e crià paggene nnove. Putite turnà e cagnà na paggena ch'esiste già, o pure [[Special:UserLogin|trasì o ve riggistrà]].",
+       "nocreate-loggedin": "Nun v'è permesso 'e crià paggene nnove.",
+       "sectioneditnotsupported-title": "Cagnamiento 'e sezziune nun suppurtato",
+       "sectioneditnotsupported-text": "'O cagnamiento d' 'e sezziune nun è suppurtato dint'a sta paggena.",
+       "permissionserrors": "Nun haje 'e premmesse abbastante.",
+       "permissionserrorstext": "Nun haje premmesse pe lle ffà st'azziune, {{PLURAL:$1|'o mutivo è chesto|'e mutive so' chiste}}:",
+       "permissionserrorstext-withaction": "Nun haje premmesse abbastante pe' $2, {{PLURAL:$1|'o mutivo è chesto|'e mutive so' chiste}}:",
+       "recreate-moveddeleted-warn": "'''Attenziò: staje a crià na paggena scancellata già.'''\n\nVire si è bbuono 'e cuntinuà a cagnà sta paggena. L'alenco ch' 'e relative scancellamiente e spustamente s'è scritto ccà abbascio pe' ffà comodo:",
+       "moveddeleted-notice": "Sta paggena è stata scancellata.\nL'alenco d' 'e relative scancellamiente e spustamente s'è scritto ccà abbascio pe' n'avé nfurmazione.",
+       "log-fulllog": "Vide log sano",
+       "edit-hook-aborted": "'O cagnamiento è stato annullato 'a 'o «hook».\nNun dette spiegazione nisciuna.",
+       "edit-gone-missing": "Nun se può agghiurnà 'a paggena.\nPare ch' 'è stata scancellata.",
+       "edit-conflict": "Conflitto d'edizziona.",
+       "edit-no-change": "'O cagnamiento è stato ignorato pecché nun s'è cagnato niente dint' 'o testo.",
+       "postedit-confirmation-created": "'A paggena è stata criata.",
+       "postedit-confirmation-restored": "'A paggena è stata arripigliata.",
+       "postedit-confirmation-saved": "'O cagnamiento è stato sarvato.",
+       "edit-already-exists": "Nun se può crià na paggena nova.\nEsiste già.",
+       "defaultmessagetext": "Mmasciata 'e testo predefinita",
+       "content-failed-to-parse": "Nun se può analizzare $2 p' 'o mudello $1: $3",
+       "invalid-content-data": "Date cuntenute nun buone",
+       "content-not-allowed-here": "'O cuntenuto \"$1\" nun è permesso dint'a paggena [[$2]]",
+       "editwarning-warning": "Ascenno 'e sta paggena putisse ffà sperdere 'e cagnamiente fatte.\nSi sì trasuto, allora può stutà st'avviso dint'a sezziona \"{{int:prefs-editing}}\" d' 'e preferenze.",
+       "editpage-notsupportedcontentformat-title": "Furmatto d' 'o cuntenuto nun suppurtato",
+       "editpage-notsupportedcontentformat-text": "'O furmatto d' 'o cuntenuto $1 nun è suppurtato d' 'o mudello 'e cuntenuto $2.",
+       "content-model-wikitext": "wikitesto",
+       "content-model-text": "testo nurmale",
+       "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
+       "expensive-parserfunction-warning": "'''Attenziò:''' Sta paggena cuntene troppe chiammate a 'e funzione parser.\n\nN'avesse 'a tené meno 'e $2, p' 'o mumento ce ne {{PLURAL:$1|stà $1|stanno $1}}.",
+       "expensive-parserfunction-category": "Paggene cu troppe chiammate a 'e funzione parser",
+       "post-expand-template-inclusion-warning": "'''Attenzione:''' 'a diminsiona d' 'e template ionte ccà è troppo grossa.\nCocche template se lassarrà fore.",
+       "post-expand-template-inclusion-category": "Paggene addò 'a diminsiona d' 'o template è fore 'o lémmeto",
+       "post-expand-template-argument-warning": "'''Attenziò:''' sta paggena cuntene uno o cchiù argumente 'e template troppo gruosse pe' 'a spannere. Sti argumente se lassarranno fore.",
+       "post-expand-template-argument-category": "Paggene ca cunteneno argumente nun cunziderate",
+       "parser-template-loop-warning": "È stato scummigliato n'aniello d' 'o template: [[$1]]",
+       "parser-template-recursion-depth-warning": "È arrivato 'o lemmeto 'e ricurzione d' 'o template ($1)",
+       "language-converter-depth-warning": "'O fùto d' 'o lemmeto d' 'o scagnatòre 'e lengua è appassato ($1)",
+       "node-count-exceeded-category": "Paggene addò 'o nummero 'e núrece è stato appassato",
+       "node-count-exceeded-category-desc": "'A paggena appassa 'o nummero massimo 'e núrece.",
+       "node-count-exceeded-warning": "Sta paggena ave appassato 'o lemmeto 'e cunto 'e núrece",
+       "expansion-depth-exceeded-category": "Paggene addò 'o fùto 'e spansiona è appassato",
+       "expansion-depth-exceeded-category-desc": "Sta paggena appassa 'o lemmeto d'espansione.",
+       "expansion-depth-exceeded-warning": "Sta paggena ha appassato 'o lemmeto 'e futo 'e spansione",
+       "parser-unstrip-loop-warning": "Scummigliato aniello Unstrip",
+       "parser-unstrip-recursion-limit": "Appassato 'o lémmeto 'e ricurzione d' Unstrip ($1)",
+       "converter-manual-rule-error": "È stato scummigliato n'errore dint'a regola manuale 'e converziona 'e lengua",
+       "undo-success": "'O cagnamiento se può annullà.\nPe' piacere vedete 'e differenze mmustate nfra 'e verziune pe' te ffà capace ca 'e cuntenute songo bbuone, e astipate 'e cagnamiente ccà abbascio pe' fernì e accussì turnà arreto.",
+       "undo-failure": "Nun se può fà turnà arreto 'o cagnamiento pecché ce sta nu conflitto ch' 'e cagnamiente intermedie.",
+       "undo-norev": "Nun se può fà turnà arreto 'o cagnamiento pecché nun esiste o s'è scancellato.",
+       "undo-nochange": "Pare c' 'o cagnamiento s'è già fatto turnà arreto.",
        "undo-summary": "Canciella 'o cagnamiento $1 'e [[Special:Contributions/$2|$2]] ([[User talk:$2|Chiàcchiera]])",
+       "undo-summary-username-hidden": "Annullato 'o cagnamiento $1 pe n'utente annascunnuto",
+       "cantcreateaccounttitle": "Nun se può crià cunto",
+       "cantcreateaccount-text": "'A riggistraziona è stata bloccata 'a l'utente [[User:$3|$3]] 'a st'innerizzo IP ('''$1''').\n\n'O mutivo dato 'a $3 è chistu ccà: ''$2''",
+       "cantcreateaccount-range-text": "'A criazione 'e cunte 'a ll'indirizze int'o ntervallo '''$1''', che cummiglia 'o vuosto ('''$4'''), è stata bloccata 'a l'utente [[User:$3|$3]].\n\n'O mutivo dato 'a $3 è chistu ccà: ''$2''",
+       "viewpagelogs": "Vide 'e log azzeccate a sta paggena",
+       "nohistory": "Nun esiste na cronologgia 'e verziune pe' sta paggena.",
        "currentrev": "Verzione 'e mmo",
        "currentrev-asof": "Vversione attuale dde $1",
        "revisionasof": "Vversione delle $1",
+       "revision-info": "Verziona d' 'o $1 fatta 'a {{GENDER:$6|$2}}$7",
        "previousrevision": "← Verzione 'e primma",
        "nextrevision": "Vversione cchiù recente →",
        "currentrevisionlink": "Verzione 'e mmo",
        "cur": "corr",
+       "next": "successiva",
        "last": "prec",
+       "page_first": "primma",
+       "page_last": "úrdema",
+       "histlegend": "Confronto nfra verziune: sciglite 'e casciulelle c'attoccassero a 'e verziune che vulite cunfruntà e spremmite Invio o pure 'o buttóne ccà abbascio.\n\nLiggenda: '''({{int:cur}})''' = differenze c' 'a verzione 'e mmò, '''({{int:last}})''' = differenze c' 'a verzione 'e primma, '''{{int:minoreditletter}}''' = cagnamiento minore",
+       "history-fieldset-title": "Naviga dint' 'a cronologgia",
        "history-show-deleted": "Solo chille canciellate",
        "histfirst": "primma",
        "histlast": "urdema",
+       "historysize": "({{PLURAL:$1|1 byte|$1 byte}})",
+       "historyempty": "(abbacante)",
+       "history-feed-title": "Cronologgia",
+       "history-feed-description": "Cronologgia d' 'a paggena ncopp'a stu sito",
        "history-feed-item-nocomment": "$1 'o $2",
+       "history-feed-empty": "'A paggena addimannata nun esiste.\nPuò darsi ca è stata scancellata d' 'a wiki, o s'è cagnato 'o nomme.\nProva a vedé [[Special:Search|dint' 'a wiki]] si ce stanno nnove paggene.",
+       "rev-deleted-comment": "(Oggetto d' 'o cagnamiento luvato)",
+       "rev-deleted-user": "(nomme utente luvato)",
+       "rev-deleted-event": "(azione d' 'o log luvata)",
+       "rev-deleted-user-contribs": "[nomme utente o indirizzo IP luvato - cagnamiento annascunnuto d' 'a cronologgia]",
+       "rev-deleted-text-permission": "Sta verziona d' 'a paggena è stata '''scancellata'''.\nAscìa dint' 'o [{{fullurl:{{#Special:Log}}/delete|page={{PAGENAMEE}}}} riggistro d' 'e scancellamiente] pe ne sapé 'e cchiù.",
+       "rev-suppressed-text-permission": "Sta verziona d' 'a paggena è stata '''luvata'''.\nVide 'o [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} riggistro 'e paggene luvate] pe' ne sapé 'e cchiù.",
+       "rev-deleted-text-unhide": "Sta verziona d' 'a paggena è stata '''scancellata'''.\nVide 'o [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log d' 'e scancellamiente] pe' ne sapé 'e cchiù.\nA ll'ammenistrature è cunzentito ancora [$1 'e vedé sta paggena] si vonno.",
+       "rev-suppressed-text-unhide": "Sta verziona d' 'a paggena è stata '''luvata'''.\nVide 'o [{{fullurl:{{#Special:Log}}/suppress|page={{PAGENAMEE}}}} riggistro 'e paggene luvate] pe' ne sapé 'e cchiù.\nA ll'ammenistrature è cunzentito ancora [$1 'e vedé sta verziona] si vonno.",
+       "rev-deleted-text-view": "Sta verziona d' 'a paggena è stata '''scancellata'''.\nLl'ammenistratore 'a ponno veré ancora; e 'a ponno ascìa dint' 'o [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} riggistro d' 'e scancellaziune] pe ne sapé 'e cchiù.",
+       "rev-suppressed-text-view": "Sta verziona d' 'a paggena è stata '''luvata'''.\nSta verziona 'a può veré ancora, 'e dettaglie 'e può cuntrullà dint' 'o [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} riggistro 'e paggene luvate] pe' ne sapé 'e cchiù.",
+       "rev-deleted-no-diff": "Sta cunfronto d' 'a paggena nun 'o può veré pecché una d' 'e verziune è stata '''scancellata'''.\nAscìa dint' 'o [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} riggistro d' 'e scancellamiente] pe ne sapé 'e cchiù.",
+       "rev-suppressed-no-diff": "Nun se può vedé stu cunfronto nfra verziune pecché una d' 'e verziune è stata '''scancellata'''.",
+       "rev-deleted-unhide-diff": "Una d' 'e verziune 'e sta paggena è stata '''scancellata'''.\nVide 'o [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} riggistro d' 'e scancellamiente] pe' ne sapé 'e cchiù.\nPuò ancora [$1 vedé sta paggena] si bbuò.",
+       "rev-suppressed-unhide-diff": "Una d' 'e verziune 'e sta paggena è stata '''luvata'''.\nVide 'o [{{fullurl:{{#Special:Log}}/suppress|page={{PAGENAMEE}}}} riggistro 'e paggene luvate] pe' ne sapé 'e cchiù.\nPuò ancora [$1 vedé sta verziona] si bbuò.",
+       "rev-deleted-diff-view": "Una d' 'e verziune 'e sta paggena è stata '''scancellata'''.\nPuò vedé sta verziona ancora; 'e dettaglie 'e può vedé dint' 'o [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} riggistro d' 'e scancellaziune] pe ne sapé 'e cchiù.",
+       "rev-suppressed-diff-view": "Una d' 'e verziune 'e sta paggena è stata '''luvata'''.\nSta verziona 'a può veré ancora; 'e dettaglie 'e può cuntrullà dint' 'o [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} riggistro 'e paggene luvate] pe' ne sapé 'e cchiù.",
        "rev-delundel": "faje vedé/annascunne",
        "rev-showdeleted": "faje vedé",
+       "revisiondelete": "Scancella o ripiglia verziune",
+       "revdelete-nooldid-title": "Verziona nun specificata",
+       "revdelete-nooldid-text": "Nun è stata specificata nisciuna verziona d' 'a paggena p' 'a secutà sta funzione, 'a verziona specificata nun esiste o pure staje truvann' 'annascónnere 'a verziona 'e mò.",
+       "revdelete-no-file": "'O file specificato nun esiste.",
+       "revdelete-show-file-confirm": "Sì sicuro/a ca vulite veré 'a verziona scancellata d' 'o file \"<nowiki>$1</nowiki>\" d' 'o $2 a 'e $3?",
        "revdelete-show-file-submit": "Sì",
+       "revdelete-selected-text": "{{PLURAL:$1|Verziona scigliuta|Verziune scigliute}} 'e [[:$2]]:",
+       "revdelete-selected-file": "{{PLURAL:$1|Verzione scigliuta|Verziune scigliute}} d' 'o file 'e [[:$2]]:",
+       "logdelete-selected": "{{PLURAL:$1|Fatto scigliuto d' 'o riggistro|Fatte scigliute d' 'o riggistro}}:",
+       "revdelete-text-text": "'E verziune scancellate cumpareno ancora dint' 'a cronologgia d' 'a paggena, ma na parte d' 'o cuntenuto lloro nun sarrà disponibbele a 'o pubbreco.",
+       "revdelete-text-file": "'E verziune 'e file scancellate cumpareno ancora dint' 'a cronologgia d' 'o file, ma parte d' 'o cuntenuto lloro nun sarrà disponibbele a 'o pubbreco.",
+       "logdelete-text": "'E fatte 'e riggistro scancellate cumpareno ancora dint' 'a cronologgia 'e riggistro, ma na parte d' 'o cuntenuto lloro nun sarrà disponibbele a 'o pubbreco.",
+       "revdelete-text-others": "Ll'at'ammenistrature puterranno ancora trasì e arrepiglià 'e cuntenute annascunnute, si nun so' state mpustate cchiù restrizziune.",
+       "revdelete-confirm": "Pe' piacere cunfermate ca overo vulite ffà chesto, ca cunuscete 'e cunseguenze, e ca state facenno chesto rispettanno 'e [[{{MediaWiki:Policy-url}}|linee guida]].",
+       "revdelete-suppress-text": "Sti luvamiente hana essere fatte '''unicamente''' dint' 'e situaziune ccà abbascio:\n* nfurmaziune potenzialmente diffamatorie\n* date perzunale inopportune\n*: ''indirizze, nummeri 'e telefono, codece fiscale, ecc.''",
+       "revdelete-legend": "Miette 'e limmete 'e visibilità",
+       "revdelete-hide-text": "Testo d' 'a verziona",
+       "revdelete-hide-image": "Annascunne 'e cuntenute d' 'o file",
+       "revdelete-hide-name": "Annascunne aziona e l'oggetto 'e cchesta",
+       "revdelete-hide-comment": "Modifeca oggetto",
+       "revdelete-hide-user": "Nomme o indirizzo IP 'e ll'autore",
+       "revdelete-hide-restricted": "Annascunne 'e nfurmaziune 'nnecate pure a l'ammenistrature",
+       "revdelete-radio-same": "(nun cagnà)",
        "revdelete-radio-set": "Nasconde",
        "revdelete-radio-unset": "Faje vedé",
+       "revdelete-suppress": "Annascunne 'e nfurmaziune pure a l'ammenistrature",
+       "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-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-failure": "'''Int'a stu riggistro 'a visibbelità nun se può scegliere:'''\n$1",
        "revdel-restore": "càgna visiblità",
+       "pagehist": "Verziune 'e primma",
+       "deletedhist": "Cronologgia scancellata",
+       "revdelete-hide-current": "Nun se ponno annasconnere ll'item  cu data 2, $1: pecché song'a la verziona 'e mmò.",
+       "revdelete-show-no-access": "Errore a mmustà ll'oggetto cu data $2, $1: St'oggetto è stato nzegnàto comme \"riservato\".\nNun tiene acciesso a chesto.",
+       "revdelete-modify-no-access": "Nun se può cagnà l'oggetto cu data $2, $1: pecché st'oggetto è stato nzegnàto comme \"riservato\".\nVuje nun avete acciesso.",
+       "revdelete-modify-missing": "Nun se può cagnà l'oggetto cu l'ID $1 pecché nun è prisente int' 'o database.",
+       "revdelete-no-change": "'''Attenziò:''' l'oggetto cu data $2, $1 teneva già 'e mpustaziune 'e visibbilità addimannate.",
+       "revdelete-concurrent-change": "Nun se può cagnà l'oggetto cu data $2, $1: 'O status 'e chisto pare ch'è stato cagnato pe cocch'utente pe' tramente ca 'o stavate a cagnà.\nPe' piacere cuntrullate 'o riggistro.",
+       "revdelete-only-restricted": "Errore quanno s'annasconneva l'oggetto cu data $2, $1: Nun può luvà oggette d' 'a vista 'e ll'ammenistratore senza scegliere manco una 'e l'at'opziune 'e visibbelità.",
+       "revdelete-reason-dropdown": "* Mutive comune pe' ffà scancellamiento\n** Violazione d' 'o copyright\n** Cummente o nfurmaziune perzunale inappropriate\n** Nomme utente inappropriato\n** Nfurmazione potenzialmente diffamatoria",
+       "revdelete-otherreason": "Ati/cchiù ragiune:",
+       "revdelete-reasonotherlist": "Ati ragiune",
+       "revdelete-edit-reasonlist": "Càgna 'e mutive pe' fà 'o scancellamiento",
+       "revdelete-offender": "Autore d' 'a verziona:",
+       "suppressionlog": "Riggistro 'e luvamiente",
+       "suppressionlogtext": "Ccà abbascio ce sta n'alenco ch' 'e scancellamiente e blocche ca teneno cuntenute annascunnuto a l'ammenistrature.\nVide l'[[Special:BlockList|elenco d' 'e blocche]] pe' l'elenco e banne e blocche attive 'e mò.",
+       "mergehistory": "Aunisce 'e cronologgie",
+       "mergehistory-header": "Sta paggena te permette d'aunì 'e verziune d' 'a cronologgia 'e na paggena origgine a na paggena nova.\nVedite ca s'avesse 'a nchiantà stu cagnamiento senza scassà 'a continuità storeca d' 'a paggena.",
+       "mergehistory-box": "Aunisce 'a cronologgia 'e ddoje ppaggene:",
+       "mergehistory-from": "Paggena d'origgene:",
+       "mergehistory-into": "Paggena 'e destinazione:",
+       "mergehistory-list": "Cronologgia 'e paggena ca fosse applicabbele pe' se ffà l'unione",
+       "mergehistory-merge": "Se ponno aunì 'e verziune 'e [[:$1]] nzignata ccà int' 'a cronologgia 'e [[:$2]]. Ausàte 'a colonna ch' 'e buttóne d'opziune pe' ffà l'aunione 'e tutt' 'e verziune nfin' 'a data e ora nzignàte.\nVedite ca si s'ausassero 'e buttóne 'e navigazione, 'a culonna ch' 'e buttóne d' 'ozzione fosse rinnovata.",
+       "mergehistory-go": "Vide 'e cagnamiente ca se ponno aunì",
+       "mergehistory-submit": "Aunisce 'e verziune",
+       "mergehistory-empty": "Nun ce stanno virziune pe' putè ffà l'aunione.",
+       "mergehistory-success": "{{PLURAL:$3|Na virziona 'e [[:$1]] è stata aunita|$3 versiune 'e [[:$1]] so' state aunite}} â cronologgia 'e [[:$2]].",
+       "mergehistory-fail": "Nun se ponno aunì 'e cronologgie. Pe' piacere cuntrullate n'ata vota 'a paggena e li parametre tempurale.",
+       "mergehistory-fail-toobig": "Nun se può fà l'aunione d' 'a cronologgia cu nu lémmeto 'e n'ati $1 {{PLURAL:$1|revisione|rivisiune}} 'a cagnà posto.",
+       "mergehistory-no-source": "'A paggena d'origgine $1 nun esiste.",
+       "mergehistory-no-destination": "'A paggena 'e destinazione $1 nun esiste.",
+       "mergehistory-invalid-source": "'A paggena d'origgine add'avé nu titolo bbuono.",
+       "mergehistory-invalid-destination": "'A paggena 'e destinazione add'avé nu titolo bbuono.",
+       "mergehistory-autocomment": "Aunione 'e [[:$1]] int'a [[:$2]]",
+       "mergehistory-comment": "Aunione 'e [[:$1]] int'a [[:$2]]: $3",
+       "mergehistory-same-destination": "'E paggene d'origgine e destinazione nun ponno essere eguale",
+       "mergehistory-reason": "Mutivo:",
+       "mergelog": "Riggistro d'aunione",
+       "pagemerge-logentry": "song'aunite [[$1]] int'a [[$2]] (verziune nfin'a $3)",
+       "revertmerge": "Annulla aunione",
+       "mergelogpagetext": "Ccà abbascio ce sta na lista cu ll'urdeme aunione int'a cronologgia d' 'e ddoje paggene.",
+       "history-title": "$1: cronologgia d' 'e cagnamiente",
+       "difference-title": "Differenze nfra 'e verziune 'e \"$1\"",
+       "difference-title-multipage": "Differenze nfra 'e verziune \"$1\" e \"$2\"",
+       "difference-multipage": "(Differenze nfra 'e paggene)",
        "lineno": "Riga $1:",
+       "compareselectedversions": "Cunfronta 'e verziune scigliute",
+       "showhideselectedversions": "Cagna visibbelità d' 'e verziune scigliute",
        "editundo": "annulla",
+       "diff-empty": "(Nisciuna differenza)",
+       "diff-multi-sameuser": "({{PLURAL:$1|Na verziona ntermedia|$1 verziune ntermedie}} 'e n'utente stisso nun {{PLURAL:$1|è mmustata|songo mmustate}})",
+       "diff-multi-otherusers": "({{PLURAL:$1|Na virzione ntermedia|$1 verziune ntermedie}} 'a {{PLURAL:$2|n'at'utente|$2 n'ati ddoj'utente}} nun è mmustata)",
+       "diff-multi-manyusers": "({{PLURAL:$1|Na virzione ntermedia|$1 verziune ntermedie}} 'a cchiù 'e $2 {{PLURAL:$2|utente|utente}} nun è mmustata)",
+       "difference-missing-revision": "{{PLURAL:$2|Na virziona|$2 verziune}} 'e sta differenza ($1) {{PLURAL:$2|nun è stata truvata|nun so' state truvate}}.\n\nChest'è succiesso quanno s'è secutato nu diff obsoleto a na paggena scancellata.\n'E dettaglie se ponno truvà dint'a [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 'o riggistro 'e scancellamiente].",
        "searchresults": "Risultato d''a recerca",
        "searchresults-title": "Ascià risultate ppe \"$1\"",
+       "titlematches": "Currispunnenze d' 'o titolo d' 'e paggene",
+       "textmatches": "Currispunnenze d' 'o testo d' 'e paggene",
        "notextmatches": "Voce addemannata nun truvata dint' 'e teste 'e articulo",
        "prevn": "{{PLURAL:$1|precedente|precedente $1}}",
        "nextn": "{{PLURAL:$1|successivo|successive $1}}",
        "nextn-title": "{{PLURAL:$1|Risultato successivo|$1 risultate successive}}",
        "shown-title": "Fa vere {{PLURAL:$1|'nu risultato|$1 risultate}} ppe paggena",
        "viewprevnext": "Vere($1 {{int:pipe-separator}} $2) ($3).",
-       "searchmenu-new": "<strong>'''Cria a paggena \"[[:$1]]\" ncopp'â chisto wiki!'''</strong> {{PLURAL:$2|0=|Vede anche 'a paggena truovata cu 'a recerca tuja|Vede anche 'e risultate d\"a recerca}}",
+       "searchmenu-exists": "'''Ncopp' 'o sito esiste na paggena c' 'o nomme \"[[:$1]]\"'''\n{{PLURAL:$2|0=|Vedite pure dint'a l'ati risultate 'e cerca.}}",
+       "searchmenu-new": "<strong>'''Cria a paggena \"[[:$1]]\" ncopp'â chisto wiki!'''</strong> {{PLURAL:$2|0=|Vide anche 'a paggena truovata cu 'a recerca vuosta|Vede anche 'e risultate d\"a recerca}}",
        "searchprofile-articles": "Paggene 'e contenute",
        "searchprofile-images": "Multimedia",
        "searchprofile-everything": "Tutto",
        "searchprofile-advanced": "Avanzate",
        "searchprofile-articles-tooltip": "Circa dint'ô $1",
        "searchprofile-images-tooltip": "Circa file",
+       "searchprofile-everything-tooltip": "Ascìa int'a tutte 'e cuntenute (pure dint' 'e chiacchiere)",
        "searchprofile-advanced-tooltip": "Circa dint'e namespace perzonalizzate",
        "search-result-size": "$1 ({{PLURAL:$2|'na parola|$2 parole}})",
+       "search-result-category-size": "{{PLURAL:$1|1 utente|$1 utente}} ({{PLURAL:$2|1 sottocategurìa|$2 sottocategurìe}}, {{PLURAL:$3|1 file|$3 files}})",
        "search-redirect": "(redirect $1)",
        "search-section": "(sezzione $1)",
+       "search-file-match": "(currispunnenza dint' 'e cuntenute d' 'o file)",
        "search-suggest": "Prova chisto: $1",
        "search-interwiki-caption": "Prugiette frate",
+       "search-interwiki-default": "Risultate 'a $1:",
+       "search-interwiki-more": "(cchiù)",
+       "search-relatedarticle": "Azzeccato",
+       "searchrelated": "azzeccato",
        "searchall": "Tutte",
+       "showingresults": "Ccà abbascio {{PLURAL:$1|s'apprisentano 'o massimo '''1''' risultato|veneno apprisentate massimo '''$1''' risultate}} aropp' 'o nummero '''$2'''.",
+       "showingresultsinrange": "{{PLURAL:$1|Vene mmustato|Veneno mmustate}} abbascio {{PLURAL:$1|<strong>1</strong> risultato|<strong>$1</strong> risultate}} d' 'o <strong>$2</strong> a 'o <strong>$3</strong>.",
+       "search-showingresults": "{{PLURAL:$4|Risultato <strong>$1</strong> 'e <strong>$3</strong>|Risultate <strong>$1 - $2</strong> 'e <strong>$3</strong>}}",
        "search-nonefound": "'A ricerca nun ha produtto risultate.",
+       "powersearch-legend": "Ricerca avanzata",
+       "powersearch-ns": "Ascìa dint' 'o namespace:",
+       "powersearch-togglelabel": "Cuntrolla:",
+       "powersearch-toggleall": "Tutto",
+       "powersearch-togglenone": "Nisciuno",
+       "powersearch-remember": "Arricuòrdate d' 'a selezziona quanno faje ricerche nfuturo",
+       "search-external": "Ricerca 'a fore",
+       "searchdisabled": "'A ricerca dint'a {{SITENAME}} nun è attiva; pe' tramente se putesse ausà nu mutore 'e cerca sterno comm'a Google. (Avite 'e sapé però, ca sti cuntenute d' 'o {{SITENAME}} dint' 'e mutore, può darse ca nun stanno agghiurnate.)",
+       "search-error": "È succiesso n'errore pe' tramente ca se faceva 'a ricerca: $1",
+       "preferences": "Preferenze d''e mmeje",
        "mypreferences": "Preferenze d''e mmeje",
+       "prefs-edits": "Cagnamiente affettuate:",
+       "prefsnologintext2": "Pe' piacere, trasite pe' cagnà 'e preferenze voste.",
+       "prefs-skin": "Aspetto grafeco (skin)",
+       "skin-preview": "Anteprimma",
+       "datedefault": "Nisciuna preferenza",
+       "prefs-labs": "Funzionalità sperimentale",
+       "prefs-user-pages": "Paggene utente",
+       "prefs-personal": "Profilo utente",
        "prefs-rc": "Urdeme nove",
        "prefs-watchlist": "Asservate speciale",
+       "prefs-watchlist-days": "Nummero 'e juorne 'a mmustà dint'a l'elenco 'e cuntrollo:",
+       "prefs-watchlist-days-max": "Massimo $1 {{PLURAL:$1|juorno|juorne}}",
+       "prefs-watchlist-edits": "Numero massimo 'e cagnamiente 'a mmustà ch' 'e funziune avanzate:",
+       "prefs-watchlist-edits-max": "Nummero massimo: 1000",
+       "prefs-watchlist-token": "Token 'e l'alenco 'e cuntrollo:",
+       "prefs-misc": "Varje",
+       "prefs-resetpass": "Cagna 'a password",
+       "prefs-changeemail": "Cagna l'indirizzo e-mail",
+       "prefs-setemail": "Mpizza nu ndirizzo e-mail",
+       "prefs-email": "Opziune e-mail",
+       "prefs-rendering": "Aspetto",
        "saveprefs": "Sarva",
+       "restoreprefs": "Arripiglia 'e mpustaziune predefinite (inta tutte 'e seziune)",
+       "prefs-editing": "Cascia 'e cagnamiento",
+       "rows": "Righe:",
        "columns": "Culonne:",
        "searchresultshead": "Truova",
+       "stub-threshold": "Valore minimo p' 'e <a href=\"#\" class=\"stub\">cullegamiente a 'e stub</a>, 'n byte:",
+       "stub-threshold-disabled": "Stutato",
+       "recentchangesdays": "Nummero 'e juorne a mmustà dint'a l'urdeme cagnamiente:",
+       "recentchangesdays-max": "Massimo $1 {{PLURAL:$1|juorno|juorne}}",
+       "recentchangescount": "Nummero predefinito 'e cagnamiente 'a mmustà:",
+       "prefs-help-recentchangescount": "Chesto ntenne ll'urdeme cagnamiente, 'e cronologgie 'e paggena, e riggistre.",
+       "prefs-help-watchlist-token2": "Chest'è 'a chiave segreta pe se ffà 'o feed web 'e l'alenco 'e cuntrolo d' 'o vuosto.\nSi coccheruno 'a cunoscesse, allora putesse vedé l'alenco 'e cuntrollo, picciò nun 'a spartite. [[Special:ResetTokens|Cliccate ccà se tenite necessità d' 'a rimpizzà]].",
+       "savedprefs": "'E preferenze songo state sarvate.",
+       "timezonelegend": "Fuso orario:",
+       "localtime": "Ora lucale:",
+       "timezoneuseserverdefault": "Aúsa ora predefinita d' 'o wiki ($1)",
+       "timezoneuseoffset": "Ato (specificà 'a differenza)",
+       "servertime": "Ora d' 'o server:",
+       "guesstimezone": "Aúsa l'ora d' 'o navigatóre",
        "timezoneregion-africa": "Afreca",
+       "timezoneregion-america": "Amereca",
+       "timezoneregion-antarctica": "Antartide",
+       "timezoneregion-arctic": "Arteco",
+       "timezoneregion-asia": "Asia",
+       "timezoneregion-atlantic": "Oceano Atlanteco",
+       "timezoneregion-australia": "Australia",
+       "timezoneregion-europe": "Europa",
+       "timezoneregion-indian": "Oceano Indiano",
+       "timezoneregion-pacific": "Oceano Pacifeco",
+       "allowemail": "Abbìa 'a ricezione 'e mmasciate mannate 'a l'ati utente",
+       "prefs-searchoptions": "Ascìa",
+       "prefs-namespaces": "Namespace",
+       "default": "predefinito",
+       "prefs-files": "File",
+       "prefs-custom-css": "CSS personalizzato",
+       "prefs-custom-js": "JavaScript personalizzato",
+       "prefs-common-css-js": "CSS/JavaScript spartuto pe' tutt' 'e skin:",
+       "prefs-reset-intro": "Putisse ausà sta paggena pe' rimpizzà 'e preferenze proprie comme chille predefinite d' 'o sito.\nL'operazione nun se può annullà.",
+       "prefs-emailconfirm-label": "Cunferma 'e ll'e-mail:",
        "youremail": "E-mail:",
        "username": "{{GENDER:$1|Nomme utente}}:",
+       "prefs-memberingroups": "{{GENDER:$2|Membro}} {{PLURAL:$1|d' 'o gruppo|d' 'e gruppe}}:",
+       "prefs-registration": "Data 'e riggistrazione:",
        "yourrealname": "Nomme vero",
        "yourlanguage": "Lengua:",
+       "yourvariant": "Variante d' 'a llengua:",
+       "prefs-help-variant": "'A variante o grafia ca preferite 'e vedé ncopp' 'e paggene 'e chesta wiki.",
+       "yournick": "Soprannomme (nickname):",
+       "prefs-help-signature": "'E cummente dint' 'e paggene 'e chiacchiera hanna essere firmate cu \"<nowiki>~~~~</nowiki>\" ca s'addeventarrà automatecamente 'a firma propria c' 'a data.",
+       "badsig": "Errore 'e firma nun standard, cuntrullate 'e tag HTML.",
+       "badsiglength": "'A firma c'avite scigliuto è troppo luonga, chesta nun avesse 'a superà $1 {{PLURAL:$1|carattere|carattere}}.",
+       "yourgender": "Comme nce referimmo a vvuje?",
+       "gender-unknown": "Preferisco 'e nun 'o ddicere",
+       "gender-male": "È riggistrato ncopp' 'a {{SITENAME}}",
+       "gender-female": "È riggistrata ncopp' 'a {{SITENAME}}",
+       "prefs-help-gender": "Mpizzà sta preferenza è ozzionale.\n'O software aúsa stu valore pe' se vutà a vuje e v'anummenà a l'ati utente ausanno 'o gennere grammatecale buono.\nCheste nfurmaziune sarranno pubbreche.",
+       "email": "E-mail",
+       "prefs-help-realname": "'O nomme overo vuosto è ozzionale.\nSi sciglite 'e nzertà 'o nomme overo, chesto s'ausarrà pe' dà l'utente l'attribuzione d' 'a fatica fatta.",
+       "prefs-help-email": "L'e-mail vuosto è ozzionale, ma permettesse 'e ricevere 'a password propria quanno v' 'a scurdate.",
+       "prefs-help-email-others": "Putite pure scegliere 'e lassà che l'at'utente ve mannassero mmasciate via e-mail cu nu cullegamiento â paggena d'utente o chiacchiera.\nLl'indirizzo e-mail vuosto nun è scummigliato quanno l'at'utente ve cuntattano.",
+       "prefs-help-email-required": "L'indirizzo e-mail è obbligatorio.",
+       "prefs-info": "Nfurmaziune bbase",
+       "prefs-i18n": "Nternaziunalizzazione",
+       "prefs-signature": "Firma",
+       "prefs-dateformat": "Furmato data",
+       "prefs-timeoffset": "Ore 'e differenza",
+       "prefs-advancedediting": "Opziune generale",
+       "prefs-editor": "Editore",
+       "prefs-preview": "Anteprimma",
+       "prefs-advancedrc": "Opziune avanzate",
+       "prefs-advancedrendering": "Opziune avanzate",
+       "prefs-advancedsearchoptions": "Opziune avanzate",
+       "prefs-advancedwatchlist": "Opziune avanzate",
+       "prefs-displayrc": "Opziune 'e visualizzazione",
+       "prefs-displaywatchlist": "Opziune 'e visualizzazione",
+       "prefs-tokenwatchlist": "Token",
+       "prefs-diffs": "Differenze",
+       "prefs-help-prefershttps": "Sta preferenza averrà affetto 'a 'o prossimo acciesso vuosto.",
+       "prefs-tabs-navigation-hint": "Suggerimento: se ponno ausà 'e buttòne 'e freccia a manca e a dritta pe' ve muovere nfra 'e schede dint'a l'alenco d' 'e schede.",
+       "email-address-validity-valid": "L'indirizzo e-mail pare valido",
+       "email-address-validity-invalid": "Nzerta n'indirizzo e-mail valido",
+       "userrights": "Gestione d' 'e permesse 'e l'utente",
+       "userrights-lookup-user": "Gestione 'e gruppe d'utenza",
+       "userrights-user-editname": "Nzertàte nu nomme utente:",
+       "editusergroup": "Cagnate 'e gruppe d'utenze",
+       "editinguser": "Cagnamiento d' 'e deritte d'utente '''[[User:$1|$1]]''' $2",
+       "userrights-editusergroup": "Cagnate 'e gruppe d'utenze",
+       "saveusergroups": "Sarvate 'e gruppe d'utenza",
+       "userrights-groupsmember": "Ffà parte {{PLURAL:$1|d' 'o gruppo|d' 'e gruppe}}:",
+       "userrights-groupsmember-auto": "Membro mplicito 'e:",
+       "userrights-groups-help": "Putite cagnà 'e gruppe assegnate a l'utente:\n* Na cascia 'e spunta scigliuta significasse ca appartenenza 'e l'utente a 'o gruppo\n* Na cascia 'e spunta nun scigliuta significasse 'a nun appartenenza a 'o gruppo.\n* 'O simmolo * significasse ca nun se può scancellà l'appartenenza a 'o gruppo aropp'a ll'avé miso (o viceversa).",
+       "userrights-reason": "Mutivo:",
+       "userrights-no-interwiki": "Nun tenite permesse pe' cagnà 'e deritte 'e l'utente ncopp'a l'ati wiki.",
+       "userrights-nodatabase": "'O database $1 nun esiste o nun è nu database lucale.",
+       "userrights-nologin": "Avite 'a [[Special:UserLogin|trasì]] comme ammenistratore si vulite assegnà 'e deritte 'e l'utente.",
+       "userrights-notallowed": "Nun tenite 'e permesse pe' jognere o luvà 'e permesse utente.",
+       "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.",
+       "group": "Gruppo:",
+       "group-user": "Utente",
+       "group-autoconfirmed": "Utente autocunfermate",
+       "group-bot": "Bot",
+       "group-sysop": "Ammenistrature",
+       "group-bureaucrat": "Burocrate",
+       "group-suppress": "Oversight",
+       "group-all": "(tutte)",
+       "group-user-member": "{{GENDER:$1|utente}}",
+       "group-autoconfirmed-member": "{{GENDER:$1|utente autocunfermato|utente autocunfermata|utente autocunfermato/a}}",
+       "group-bot-member": "{{GENDER:$1|bot}}",
+       "group-sysop-member": "{{GENDER:$1|ammenistratore|ammenistratrice|ammenistratore/trice}}",
+       "group-bureaucrat-member": "{{GENDER:$1|burocrate}}",
+       "group-suppress-member": "{{GENDER:$1|oversight}}",
+       "grouppage-user": "{{ns:project}}:Utente",
+       "grouppage-autoconfirmed": "{{ns:project}}:Utente autocunfermate",
+       "grouppage-bot": "{{ns:project}}:Bot",
+       "grouppage-sysop": "{{ns:project}}:Ammenistrature",
+       "grouppage-bureaucrat": "{{ns:project}}:Burocrate",
+       "grouppage-suppress": "{{ns:project}}:Oversight",
+       "right-read": "Liegge paggene",
+       "right-edit": "Cagna paggene",
+       "right-createpage": "Crìa paggene (ca nun songo paggene 'e chiacchiera)",
+       "right-createtalk": "Crìa chiacchiere 'e paggena",
+       "right-createaccount": "Crìa utenze nove",
+       "right-minoredit": "Nzigna 'e cagnamiente comme minure",
+       "right-move": "Muove 'e paggene",
+       "right-move-subpages": "Muove 'e paggene nzieme ê sottopaggene suje",
+       "right-move-rootuserpages": "Muove 'e paggene princepale d'utente",
+       "right-move-categorypages": "Muove 'e categurìe",
+       "right-movefile": "Muove 'e file",
+       "right-suppressredirect": "Nun crià 'e redirect automateco quanno se muoveno 'e paggene",
+       "right-upload": "Carreca file",
+       "right-reupload": "Sovrascrive nu file ch'esiste",
+       "right-reupload-own": "Sovrascrive nu file esistente carrecat'a l'utente stesso",
+       "right-reupload-shared": "Sovrascrive lucalmente file prisente dint'a l'archivio spartuto",
+       "right-upload_by_url": "Carreca nu file 'a n'indirizzo URL",
+       "right-purge": "Pulezza 'a cache d' 'o sito senza cunferma",
+       "right-autoconfirmed": "Nun suggetto a 'o lemmeto d'aziune 'a l'IP",
+       "right-bot": "S'avesse 'e trattà comm'a nu prucesso automateco",
+       "right-nominornewtalk": "Fa ch' 'e cagnamiente minore a 'e paggene 'e chiacchiera nun facciano scattà l'avviso 'e mmasciata nnova",
+       "right-apihighlimits": "Usa límmete cchiù aute pe l'interrogaziune a ll'API",
+       "right-writeapi": "Usa l'API 'n scrittura",
+       "right-delete": "Scancella paggene",
+       "right-bigdelete": "Scancella paggene ch' 'e cronologgie luonghe",
+       "right-deletelogentry": "Scancella e arripiglia vvoce 'e riggistro specifiche",
+       "right-deleterevision": "Annascunne verziune specifiche d' 'e paggene",
+       "right-deletedhistory": "Vide 'e verziune d' 'a cronologgia scancellate senza 'o testo suoccio a lloro",
+       "right-deletedtext": "Vide 'o testo scancellato e cagnamiente nfra virziune scancellate",
+       "right-browsearchive": "Ascìa dint' 'e paggene scancellate",
+       "right-undelete": "Arripiglia na paggena",
+       "right-suppressrevision": "Vide, annascunne e ripiglia 'e verziune specifiche d' 'e paggene a cocherun'utente",
+       "right-viewsuppressed": "Vide 'e verziune annascunnute a coccherun'utente",
+       "right-suppressionlog": "Vide 'e riggistre private",
+       "right-block": "Blocca 'e cagnamiente 'a parte 'e l'at'utente",
+       "right-blockemail": "Blocca n'utente a mannà e-mail",
+       "right-hideuser": "Blocca n'utente e fallo sparì 'a 'o pubbreco",
+       "right-ipblock-exempt": "Ignora 'e blocche 'e l'IP, 'e blocche automatece e li blocche 'e range 'e l'IP",
+       "right-proxyunbannable": "Passa 'e blocche automatiche d' 'e proxy",
+       "right-unblockself": "Sblocca se stesso",
+       "right-protect": "Cagna 'e livelle 'e prutezione 'e cagna paggene prutette ricurzivamente",
+       "right-editprotected": "Cagna 'e paggene prutette cu \"{{int:protect-level-sysop}}\"",
+       "right-editsemiprotected": "Cagna 'e paggene prutette cu \"{{int:protect-level-autoconfirmed}}\"",
+       "right-editinterface": "Modifeca 'a nterfaccia utente",
+       "right-editusercssjs": "Cagna 'e file CSS e JS e l'at'utente",
+       "right-editusercss": "Cagna 'e file CSS 'e l'at'utente",
+       "right-edituserjs": "Cagna 'e file JS e l'at'utente",
+       "right-editmyusercss": "Cagna 'e proprie file CSS",
+       "right-editmyuserjs": "Cagna 'e proprie file JavaScript",
+       "right-viewmywatchlist": "Vide l'alenco 'e cuntrollo proprio",
+       "right-editmywatchlist": "Cagna l'alenco 'e cuntrollo proprio. Vedete ca cocch'azione putesse jògnere ancora paggene senza stu deritto.",
+       "right-viewmyprivateinfo": "Vide 'e proprie date private (e.g. e-mail, nomme overo)",
+       "right-editmyprivateinfo": "Cagna 'e date perzunale proprie (p'esempio: e-mail, nomme overo)",
+       "right-editmyoptions": "Cagna 'e preferenze proprie",
+       "right-rollback": "Annulla ampresso 'e cagnamiente 'e ll'urdem'utente c'avesse cagnato na paggena particolare",
+       "right-markbotedits": "Nzégna 'e cagnamiente suggette a rollback comme affettuate 'a nu bot",
+       "right-noratelimit": "Nun suggetto a lemmeto d'aziune",
+       "right-import": "Carreca paggene 'a n'ati wiki",
+       "right-importupload": "Carreca paggene 'a n'upload 'e file",
+       "right-patrol": "Nzegna 'e cagnamiente 'e l'ati utente comme cuntrullate",
+       "right-autopatrol": "Nzegna automatecamente 'e cagnamiente proprie comme cuntrullate",
+       "right-patrolmarks": "Vide ll'urdeme cagnamiente int' 'a funzione 'e cuntrollo",
+       "right-unwatchedpages": "Vide n'alenco 'e pagene nun cuntrullate",
+       "right-mergehistory": "Aunisce 'a cronologgia d' 'e paggene",
+       "right-userrights": "Cagna 'e deritte 'e ll'utente",
+       "right-userrights-interwiki": "Cagna 'e deritte 'e ll'utente int'a l'ati wiki",
+       "right-siteadmin": "Blocca e sblocca 'o database",
+       "right-override-export-depth": "Esporta 'e paggene azzeccanno 'e paggene cullegate nfin'a na profondità 'e 5",
+       "right-sendemail": "Manna na mail a ll'at'utente",
+       "right-passwordreset": "Vide 'e mmasciate 'e rimpustazione d' 'a password",
+       "newuserlogpage": "Riggistro 'e nuove utente",
+       "newuserlogpagetext": "Chest'è nu riggistro 'e criazione d'utenze.",
+       "rightslog": "Deritte 'e ll'utente",
+       "rightslogtext": "Ccà abbascio sta nu riggistro d' 'e cagnamiente a 'e deritte 'e ll'utente",
+       "action-read": "lieggere sta paggena",
        "action-edit": "càgna chesta paggena",
+       "action-createpage": "crìa paggene",
+       "action-createtalk": "crìa chiacchiere 'e paggena",
+       "action-createaccount": "crìa stu cunto utente",
+       "action-history": "vide 'a cronologgia 'e sta paggena",
+       "action-minoredit": "nzegnà stu cagnamiento comme minore",
+       "action-move": "Spusta chista paggena",
+       "action-move-subpages": "muovere sta paggena, e le sottopaggene relative",
+       "action-move-rootuserpages": "muove 'e paggene princepale d'utente",
+       "action-move-categorypages": "muove 'e categurìe",
+       "action-movefile": "muove stu file",
+       "action-upload": "carreca stu file",
+       "action-reupload": "sovrascrive stu file esistente",
+       "action-reupload-shared": "sovrascrive stu file prisente dint'a ll'archivio condiviso",
+       "action-upload_by_url": "carreca stu file 'a n'indirizzo URL",
+       "action-writeapi": "usa l'API 'n scrittura",
+       "action-delete": "scancèlla chista paggena",
+       "action-deleterevision": "scancellà sta verziona",
+       "action-deletedhistory": "vide 'a cronologgia scancellata 'e sta paggena",
+       "action-browsearchive": "ascìa dint' 'e paggene scancellate",
+       "action-undelete": "arripiglia chista paggena",
+       "action-suppressrevision": "rivedé e arripiglià 'e cagnamiente annascunnute",
+       "action-suppressionlog": "vide stu riggistro privato",
+       "action-block": "blocca 'e cagnamiente 'a parte 'e st'utente",
+       "action-protect": "cagna 'e livelle 'e prutezione pe' sta paggena",
+       "action-rollback": "annulla ampresso 'e cagnamiente 'e ll'urdem'utente c'avesse cagnato na paggena particolare",
+       "action-import": "carreca paggene 'a n'ata wiki",
+       "action-importupload": "carreca paggene 'a n'upload 'e file",
+       "action-patrol": "nzegna 'e cagnamiente 'e l'ati utente comme cuntrullate",
+       "action-autopatrol": "nzignà 'e proprie cagnamiente comme cuntrullate",
+       "action-unwatchedpages": "vide l'alenco 'e pagene nun cuntrullate",
+       "action-mergehistory": "aunisce 'a cronologgia 'e sta paggena",
+       "action-userrights": "cagna 'e deritte 'e ll'utente",
+       "action-userrights-interwiki": "cagna 'e deritte 'e ll'utente int'a l'ati wiki",
+       "action-siteadmin": "blocca o sblocca 'o database",
+       "action-sendemail": "manna e-mail",
+       "action-editmywatchlist": "cagna l'alenco 'e cuntrolo 'o tuojo",
+       "action-viewmywatchlist": "vide l'alenco 'e cuntrollo proprio",
+       "action-viewmyprivateinfo": "vide 'e date perzunale",
+       "action-editmyprivateinfo": "cagnà 'e proprie date perzunale",
+       "nchanges": "$1 {{PLURAL:$1|cagnamiento|cagnamiente}}",
+       "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|'a ll'urdema visita}}",
+       "enhancedrc-history": "cronologgia",
        "recentchanges": "Urdeme nove",
        "recentchanges-legend": "Opzione urdeme cagnamiénte",
-       "recentchanges-summary": "Ncoppa chesta paggena song' appresentate ll'urdeme cagnamiente fatto ê cuntenute d\"o sito.",
+       "recentchanges-summary": "Ncoppa chesta paggena song' appresentate ll'urdeme cagnamiente fatte ê cuntenute d\"o sito.",
+       "recentchanges-noresult": "Nisciuno cagnamiento dint'o periodo dato ca soddisfà sti criterie.",
+       "recentchanges-feed-description": "Ncoppa chistu feed song' appresentate ll'urdeme cagnamiente fatte ê cuntenute d\"o sito.",
        "recentchanges-label-newpage": "Chista modifica ha criato 'na nova paggena",
        "recentchanges-label-minor": "Chisto è nu cagnamiénto piccerillo",
+       "recentchanges-label-bot": "Cagnamiento affettuato 'a nu bot",
        "recentchanges-label-unpatrolled": "Chista modifica nun è stata 'ncora verificata",
+       "recentchanges-label-plusminus": "'A grannezza d' 'a paggena s'è cagnata pe' bbia 'e stu nummero 'e bytes",
+       "recentchanges-legend-heading": "'''Liggenda:'''",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vide [[Special:NewPages|'e paggene nove]])",
+       "rcnotefrom": "Ccà abbascio {{PLURAL:$5|è alencato 'o cagnamiento appurtato|song' alincate 'e cagnamiente appurtate}} 'a <strong>$3, $4</strong> (mmustate nfin'a <strong>$1</strong>).",
        "rclistfrom": "Faje vedé 'e cagnamiénte fatte a partì 'a $3 $2",
        "rcshowhideminor": "$1 'e cagnamiénte piccerille",
+       "rcshowhideminor-show": "Faje vedé",
+       "rcshowhideminor-hide": "Annascunne",
        "rcshowhidebots": "$1 'e bot",
+       "rcshowhidebots-show": "Faje vedé",
+       "rcshowhidebots-hide": "Annascunne",
        "rcshowhideliu": "$1 ll'utente reggìstrate",
+       "rcshowhideliu-show": "Faje vedé",
+       "rcshowhideliu-hide": "Annascunne",
        "rcshowhideanons": "$1 ll'utente anonime",
+       "rcshowhideanons-show": "Faje vedé",
+       "rcshowhideanons-hide": "Annascunne",
+       "rcshowhidepatr": "$1 cagnamiente cuntrullate",
+       "rcshowhidepatr-show": "Faje vedé",
+       "rcshowhidepatr-hide": "Annascunne",
        "rcshowhidemine": "$1 'e ffatiche mmee",
+       "rcshowhidemine-show": "Faje vedé",
+       "rcshowhidemine-hide": "Annascunne",
        "rclinks": "Faje vedé ll'urdeme $1 cagnamiente dint' ll'urdeme $2 juorne<br />$3",
        "diff": "diff",
        "hist": "cron",
        "minoreditletter": "m",
        "newpageletter": "N",
        "boteditletter": "b",
+       "number_of_watching_users_pageview": "[osservata 'a {{PLURAL:$1|n'utente|$1 utente}}]",
+       "rc_categories": "Lemmeta a 'e categurìe (spartute 'a \"|\")",
        "rc_categories_any": "Qualònca",
+       "rc-change-size-new": "$1 {{PLURAL:$1|byte|byte}} aropp'ô cagnamiento",
+       "newsectionsummary": "/* $1 */ sezziona nnova",
        "rc-enhanced-expand": "Fa vede dettaglie",
        "rc-enhanced-hide": "Annascunne dettaglie",
+       "rc-old-title": "origginariamente criata comme \"$1\"",
        "recentchangeslinked": "Cagnamiénte cullegate",
        "recentchangeslinked-feed": "Cagnamiénte cullegate",
        "recentchangeslinked-toolbox": "Cagnamiénte cullegate",
        "recentchangeslinked-title": "Cagnamiénte cullegate a \"$1\"",
+       "recentchangeslinked-summary": "Chest'è n'alenco d' 'e cagnamiente fatte mò a 'e paggene cullegate 'a chilla specificata (o pe' cuntenute dint'a na categurìa specificata). 'E paggene cuntenute dint' 'o proprio elenco 'e l'[[Special:Watchlist|Paggene cuntrullate]] songo mmustate 'n '''grassetto'''.",
        "recentchangeslinked-page": "Nomme dda paggena",
+       "recentchangeslinked-to": "Mmusta sulamente 'e cagnamiente a 'e paggene cullegate a chilla specificata",
        "upload": "Careca file",
+       "uploadbtn": "Carreca file",
+       "reuploaddesc": "Torna a 'o modulo pe ffà 'a carreca",
+       "upload-tryagain": "Manna 'a descrizione d' 'o file cagnato",
+       "uploadnologin": "Acciesso nun affettuato",
+       "uploadnologintext": "Pe' carrecà 'o file ce vulesse $1.",
+       "upload_directory_missing": "'A cartella 'e carreche ($1) nun esiste e nun se può crià 'a 'o server web.",
+       "upload_directory_read_only": "'O server web nun può scrivere dint' 'a cartella 'e carreca ($1).",
+       "uploaderror": "Errore a carrecà",
+       "upload-recreate-warning": "'Attenziò'': nu file cu stu nomme è stato scancellato o spustato.'''\n'O riggistro d' 'e scancellamiente e d' 'e spustamiente 'e sta paggena è stato scritto ccà abbascio pe' ffà comodo:",
+       "uploadtext": "Ausà 'o modulo ccà sotto pe' carrecà file nuove. Pe' vedé o ascià 'e file carrecate già, vide 'o [[Special:FileList|riggistro 'e file carrecate]]. Càrreche 'e file e virzione nove d' 'e file songo riggistrate dint' 'o [[Special:Log/upload|riggistro d'upload]], 'e scancellamiente dint' 'o [[Special:Log/delete|riggistro ccà]].\n\nPe' nzertà nu file dint'a na paggena, allora facite nu cullegamento 'e stu tipo:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code>''' p'ausà a verziona cumpleta d' 'o file\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|testo alternativo]]</nowiki></code>''' p'ausà na verziona luonga 200 pixel nzertata dint'a na cascia, allineata a manca e cu nu 'testo alternativo' comme didascalia\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' pe' crià nu cullegamento diretto a 'o file senza 'o fà vedé",
+       "upload-permitted": "Tipe 'e file permesse: $1.",
+       "upload-preferred": "Tipe 'e file cunzigliate: $1.",
+       "upload-prohibited": "Tipe 'e file nun permesse: $1.",
+       "uploadlogpage": "Riggistro 'e carreche",
+       "uploadlogpagetext": "Ccà abbascio song'alencate l'urdeme file carrecate.\nCuntrullate 'a [[Special:NewFiles|gallaria d' 'e file nuove]] pe' ve ffà na guardata cchiù visuale 'e tutto.",
+       "filename": "Nomme d' 'o file",
        "filedesc": "Énnece",
-       "uploadedimage": "ha carecato \"[[$1]]\"",
+       "fileuploadsummary": "Dettaglie:",
+       "filereuploadsummary": "Cagnamiente a 'o file:",
+       "filestatus": "Stato d' 'o copyright:",
+       "filesource": "Fonte:",
+       "ignorewarning": "Lassa perde l'avviso e sarva 'o file pure",
+       "ignorewarnings": "Lasa perde ogne mmasciata d'attenzione",
+       "minlength1": "'E nomme d' 'e file hann'avé minimo na lettera.",
+       "illegalfilename": "'O nomme \"$1\" cuntene carattere nun permesse dint' 'e titule 'e paggena.\nPe' piacere date n'atu nomme a 'o file e pruvate a 'o carrecà n'ata vota.",
+       "filename-toolong": "'E nomme d' 'e file nun ponno superà 'e 240 byte.",
+       "badfilename": "'O nomme d' 'o file è stato cagnato a \"$1\".",
+       "filetype-mime-mismatch": "'A stensione d' 'o file \".$1\" nun currisponne a 'o tipo MIME scummigliato a 'o file ($2).",
+       "filetype-badmime": "Nun è permesso carrecà file 'e tipo MIME \"$1\".",
+       "filetype-bad-ie-mime": "Nun se ponno carrecà 'e file pecché Internet Explorer 'o scummigliasse comme \"$1\", che è nu tipo 'e file nun permesso e potenzialmente pericoloso.",
+       "filetype-unwanted-type": "Carrecà file 'e tipo '''\".$1\"''' è scunzigliato. {{PLURAL:$3|'O tipo 'e file cunzigliato è|'E tipe 'e file cunzigliate songo}} $2.",
+       "filetype-banned-type": "'''\".$1\"''' {{PLURAL:$4|nun è nu tipo 'e file permesso|nun songo tipe 'e file permesse}}. {{PLURAL:$3|'O tipo 'e file permesso è|'E tipe 'e file permesse songo}} $2.",
+       "filetype-missing": "'O file nun ave stensione (p'esempio \".jpg\").",
+       "empty-file": "'O file ch'avite mannato è abbacante.",
+       "file-too-large": "'O file ch'avite mannato è troppo gruosso.",
+       "filename-tooshort": "'O nomme d' 'o file è troppo curto.",
+       "filetype-banned": "Stu tipo 'e file nun è permesso.",
+       "verification-error": "Stu file nun ha passat' 'o cuntrollo.",
+       "hookaborted": "'O cagnamiento c'avite pruvato 'e fà è stato spezzato 'a na stensione.",
+       "illegal-filename": "'O nomme d' 'o file nun è permesso.",
+       "overwrite": "Sovrascrivere nu file ch'esiste già nun è permesso.",
+       "unknown-error": "È capitato n'errore scanusciuto.",
+       "tmp-create-error": "Nun se può crià nu file temporaneo.",
+       "tmp-write-error": "Errore a scrivere nu file temporaneo.",
+       "large-file": "S'arraccumanna 'e nun appassà 'e diminsione 'e $1 p'ogne file; stu file è gruosso $2.",
+       "largefileserver": "Stu file appassa 'e dimensiune permesse 'a la configurazione d' 'o server",
+       "emptyfile": "'O file carrecato mò mò pare abbacante. Può darse ch'è stato n'errore int' 'o nomme d' 'o file. Cuntrullate ca vulite overamente carrecà stu file.",
+       "windows-nonascii-filename": "Chista wiki nun supporta nomme d' 'e file cu carattere spiciale",
+       "fileexists": "Nu file cu stu nomme esiste già.\nPe' piacere cuntrullate primma <strong>[[:$1]]</strong> si nun site sicure ca 'o vulite cagnà.\n[[$1|thumb]]",
+       "filepageexists": "'A paggena 'e descrizione 'e stu file è stata già criata a l'indirizzo <strong>[[:$1]]</strong>, pùre si nun esiste ancora nu file cu stu nomme. 'A descrizione 'e l'oggetto nzertàta 'n fase 'e carreca nun cumparerrà ncopp' 'a paggena 'e descrizione. Pe' ffà l'oggetto cumparì ncopp' 'a paggena 'e descrizione, l'avisseve 'a cagnà manualmente.\n[[$1|thumb]]",
+       "fileexists-extension": "Nu file esiste cu nu nomme suoccio a chesto: [[$2|thumb]]\n* Nomme d' 'o file carrecato: <strong>[[:$1]]</strong>\n* Nomme d' 'o file esistente: <strong>[[:$2]]</strong>\nPuò darse ca vulite scegliere nu nomme cchiù specifico?.",
+       "fileexists-thumbnail-yes": "Pare ch' 'o file carrecato fosse na miniatura ''(thumbnail)''. [[$1|thumb]]\nCuntrullate, pe' cunfronto, 'o file <strong>[[:$1]]</strong>.\nSi se trattasse d' 'a stessa immaggene, ch' 'e diminsiune origginale, nun è necessario carrecà ati miniature.",
+       "file-thumbnail-no": "Stu filename accummencia pe' <strong>$1</strong>.\nPare ca ce sta n'immaggene piccerilla <em>(thumbnail)</em>.\nSi tiene st'immaggene 'n risoluzione origginale, pe' piacere carrecatela. Si nò, vedite 'e cagnà 'o nomme d' 'o file.",
+       "fileexists-forbidden": "Nu file cu stu nomme esiste già, e nun se può sovrascrivere.<br/>\nPe' piacere turnat'arreto e cagnàte 'o nomme p' 'o turnà a carrecà.\n[[File:$1|thumb|center|$1]]",
+       "fileexists-shared-forbidden": "Nu file cu stu nomme esiste già dint'a l'archivio 'e risorse multimediale spartute. Si vulite carrecà 'o file ancora, turnat'arreto e cagnate 'o nomme p' 'o turnà a carrecà.\n[[File:$1|thumb|center|$1]]",
+       "file-exists-duplicate": "Stu file è nu duplicato {{PLURAL:$1|d' 'o|d' 'e}} file ccà abbascio:",
+       "file-deleted-duplicate": "Nu file identico a chesto ([[:$1]]) è stato scancellato prima. Cuntrullate 'a cronologgia d' 'e scancellamiente apprimma d' 'o carrecà n'ata vota.",
+       "file-deleted-duplicate-notitle": "Nu file eguale a stu file è stato previamente scancellato, e 'o titolo è stato sbaccantato. Chierete a coccheruno ca tenesse 'a posibbelità 'e vedé file luvate e sbaccantate pe' sapé nquale situazione ve truvate apprimma d' 'o ffà carrecà n'ata vota.",
+       "uploadwarning": "Avviso 'e carreca",
+       "uploadwarning-text": "Pe' piacere cagnate ccà abbascio 'a descrizione d' 'o file 'e pruvate n'ata vota.",
+       "savefile": "Sarva file",
+       "uploaddisabled": "'E càrreche so' state stutate.",
+       "copyuploaddisabled": "'E càrreche pe' bbia 'e l'URL so' state stutate.",
+       "uploaddisabledtext": "'E carreche 'e file so' state stutate.",
+       "php-uploaddisabledtext": "'E càrreche 'e file pe' bbia d' 'o PHP so' state stutate. Cuntrullate 'a configurazione d' 'o file_uploads.",
+       "uploadscripted": "Stu file cuntene codece HTML o script, ca se putesse nterpretà erroneamente 'a nu navigatóre web.",
+       "uploadscriptednamespace": "Stu file SVG cuntene nu namespace '$1' nun permesso.",
+       "uploadinvalidxml": "'O códece XML d' 'o file carrecato nun se può passà.",
+       "uploadvirus": "Stu file cuntene nu virus! Dettaglie: $1",
+       "uploadjava": "Stu file è nu file ZIP ca cuntene nu file .class Java.\nCarrecà 'e file Java nun è permesso, pecché ponno appassà 'e restriziune 'e sicurezza.",
+       "upload-source": "File d'origgine",
+       "sourcefilename": "Nomme d' 'o file d'origgine:",
+       "sourceurl": "URL d'origgine:",
+       "destfilename": "Nomme 'e file 'e destinazione:",
+       "upload-maxfilesize": "Diminsione massima d' 'o file: $1",
+       "upload-description": "Descrizione d' 'o file",
+       "upload-options": "Opziune 'e carreca",
+       "watchthisupload": "Tiene d'uocchio chistu file",
+       "filewasdeleted": "Nu file ca se chiamave cumm'a chillo c'avete primma carrecato e pò è stato scancellato.\nVedite 'e cuntrullà 'o $1 apprimma ca cuntinuate c' 'a carreca.",
+       "filename-bad-prefix": "'O nomme d' 'o file ca state a carrecà accummencia pe' ''\"$1\"''', ca nurmalmente è 'o nomme c'assegnasse na machina fotografeca automatecamente ed è nu nomme nun descrittivo.\nPe' piacere scigliete n'atu nomme ca fosse cchiù descrittivo.",
+       "upload-success-subj": "Carreca ngarrata",
+       "upload-success-msg": "'A carreca tuja d' 'o [$2] è asciuta bona. Mò è disponibbele ccà: [[:{{ns:file}}:$1]]",
+       "upload-failure-subj": "Probblema c' 'a carreca",
+       "upload-failure-msg": "Ce steva nu probblema c' 'a carreca 'a [$2]:\n\n$1",
+       "upload-warning-subj": "Avviso 'e carreca",
+       "upload-warning-msg": "Ce steva nu probblema c' 'a carreca 'a [$2]. Putite turnà arreto a 'o [[Special:Upload/stash/$1|module 'e carreche]] pe pruvà d'aggiustà stu prubblema.",
+       "upload-proto-error": "Prutucollo sbagliato",
+       "upload-proto-error-text": "'E carreche remote hann'abbesuogno 'e l'URL c'accummencieno c' 'a parola <code>http://</code> o <code>ftp://</code>.",
+       "upload-file-error": "Errore 'nterno",
+       "upload-file-error-text": "S'è verificato n'errore interno quanno avete pruvat'a crià nu file temporaneo ncopp' 'o server.\nPe' piacere cuntattate n'[[Special:ListUsers/sysop|ammenistratore]].",
+       "upload-misc-error": "Errore 'e carreche scanusciute",
+       "upload-misc-error-text": "N'errore scanusciuto s'è verificato quanno se steva facenno 'a carreca.\nPe' piacere cuntrullate ca l'URL è valida e accessibbele e pruvate n'ata vota.\nSi 'o probblema è presente ancòra, cuntattate n'[[Special:ListUsers/sysop|ammenistratore]].",
+       "upload-too-many-redirects": "L'URL teneva troppe redirect",
+       "upload-http-error": "N'errore HTTP è succiesso: $1",
+       "upload-copy-upload-invalid-domain": "Nun è permessa 'a carreca 'e copie 'a chistu dumminio.",
+       "backend-fail-stream": "Nun se può mannà 'o file \"$1\".",
+       "backend-fail-backup": "Nun se può ffà 'o backup d' 'o file \"$1\".",
+       "backend-fail-notexists": "'O file $1 nun esiste.",
+       "backend-fail-hashes": "Nun se ponno attené 'e hash d' 'o file pe' ne ffà 'o cunfronto.",
+       "backend-fail-notsame": "Esiste già nu file nun eguale a $1 .",
+       "backend-fail-invalidpath": "$1 nun è un nu posto d'archiviazione bbuono.",
+       "backend-fail-delete": "Nun se può scancellà 'o file \"$1\"",
+       "backend-fail-describe": "Nun se ponno cagnà 'e metadate d' 'o file \"$1\".",
+       "backend-fail-alreadyexists": "'O file $1 esiste già.",
+       "backend-fail-store": "Nun se può astipà 'o file \"$1\" dint'a \"$2\".",
+       "backend-fail-copy": "Nun se può copiare 'o file \"$1\" dint'a \"$2\".",
+       "backend-fail-move": "Nun se può spustà 'o file \"$1\" into \"$2\".",
+       "backend-fail-opentemp": "Nun se può arapì nu file temporaneo.",
+       "backend-fail-writetemp": "Nun se può scrivere nu file temporaneo.",
+       "backend-fail-closetemp": "Nun se può nchiure nu file temporaneo.",
+       "backend-fail-read": "Nun se può lieggere 'o file \"$1\".",
+       "backend-fail-create": "Nun se può scrivere 'o file \"$1\"",
+       "backend-fail-maxsize": "Nun se può scrivere 'o file \"$1\" pecché chist'è cchiù gruosso 'e {{PLURAL:$2|nu byte|$2 byte}}",
+       "backend-fail-readonly": "L'archivio 'e rezza \"$1\" è mò mò 'n sola-lettura. 'O mutivo è: \"$2\"",
+       "backend-fail-synced": "'O file \"$1\" è int' 'a nu stato ncunzistente dint'a l'archivie nterne.",
+       "backend-fail-connect": "Nun se può cunnettà â memoria 'e rezza \"$1\".",
+       "backend-fail-internal": "N'errore scanusciuto s'è verificato int'a l'archivie 'e rezza \"$1\".",
+       "backend-fail-contenttype": "Nun se ponno determinà 'e tipe 'e cuntenute d' 'o file 'a riggistrà dint'a \"$1\".",
+       "backend-fail-batchsize": "L'archivio 'e rezza prugrammaje na rezza 'e $1 {{PLURAL:$1|prucesso|prucesse}} ncopp' 'o file; 'o lémmeto è $2 {{PLURAL:$2|prucesso|prucesse}}.",
+       "backend-fail-usable": "Nun se può lieggere o scrivere 'o file \"$1\" pecché mancano 'e permesse sufficiente o nun esiste 'a cartella/cuntenitore.",
+       "filejournal-fail-dbconnect": "Nun se può fà connessione a l'archivio d' 'o database pe' puté astipà archivie 'n rezza \"$1\".",
+       "filejournal-fail-dbquery": "Nun se può agghiurnà l'archivio d' 'o database pe' puté astipà l'archivie 'n rezza \"$1\".",
+       "lockmanager-notlocked": "Nun se può sbloccà \"$1\"; nun è bluccato.",
+       "lockmanager-fail-closelock": "Nun se può nchiure 'o file 'e blocco pe' \"$1\".",
+       "lockmanager-fail-deletelock": "Nun se può scancellà 'o file 'e blocco pe' \"$1\".",
+       "lockmanager-fail-acquirelock": "Nun se può piglià 'o blocco pe' \"$1\".",
+       "lockmanager-fail-openlock": "Nun se può arapì 'o file 'e blocco pe' \"$1\".",
+       "lockmanager-fail-releaselock": "Nun se può lanzà 'o blocco pe' \"$1\".",
+       "lockmanager-fail-db-bucket": "Nun se ponno cuntattà 'e database 'e blocco necessarie int'a $1.",
+       "lockmanager-fail-db-release": "Nun se ponno lanzà 'e blocche ncopp' 'o database $1.",
+       "lockmanager-fail-svr-acquire": "Nun se ponno piglià 'e blocche ncopp' 'o server $1.",
+       "lockmanager-fail-svr-release": "Nun se ponno lanzà blocche ncopp' 'o server $1.",
+       "zip-file-open-error": "S'è truvato n'errore quanno se steva arapenno nu file pe' ne fà cuntrolle ZIP.",
+       "zip-wrong-format": "'O file specificato nun era nu file ZIP.",
+       "zip-bad": "'O file è corrotto o pure nun è nu file ZIP ca se putesse lieggere.\nNun se può cuntrullà opportunamente pe' sicurezza.",
+       "zip-unsupported": "'O file è nu file ZIP c'ausa servizie ZIP ca nun songo suppurtate 'a MediaWiki.\nNun se può cuntrullà pe' sicurezza.",
+       "uploadstash": "Carreca stash",
+       "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-refresh": "Agghiuorna l'alenco d' 'e file",
+       "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",
+       "img-auth-notindir": "'O percurzo addimannato nun se trova dint' 'e cartelle d'upload configurate.",
+       "img-auth-badtitle": "Nun se può fravecà nu titolo valido 'a \"$1\".",
+       "img-auth-nologinnWL": "Nun site trasuto e \"$1\" nun è dint'a lista janca.",
+       "img-auth-nofile": "File \"$1\" nun esiste.",
+       "img-auth-isdir": "State pruvanno a trasì int' 'a cartella \"$1\".\nSulamente se può trasì a 'e file.",
+       "img-auth-streaming": "\"$1\" 'n streaming.",
+       "img-auth-public": "'A funziona 'e img_auth.php è chella ddà 'e file d'output 'a na wiki privata.\nSta wiki è configurata comm'a na wiki pubbleca.\nPe na sicurezza ottima, img_auth.php è stutato.",
+       "img-auth-noread": "L'utente nun tene acciesso pe lieggere \"$1\".",
+       "http-invalid-url": "URL nun valido: $1",
+       "http-invalid-scheme": "L'URL c' 'o prefisso \"$1\" nun so' suppurtate.",
+       "http-request-error": "Richieste HTTP fallite pe' n'errore scanusciuto.",
+       "http-read-error": "Errore 'e lettura HTTP.",
+       "http-timed-out": "Richieste HTTP fore tiempo.",
+       "http-curl-error": "Errore analizzanno l'URL: $1",
+       "http-bad-status": "C'è stato nu probblema pe' tramente ca se faceva 'a richiesta HTTP: $1, $2",
+       "upload-curl-error6": "Nun se riesce 'arrevà a l'URL",
+       "upload-curl-error6-text": "A l'URL c'avete scritto nun se può arrevà.\nPe' piacere, cuntrullate ca l'URL è curretta e ca 'o sito è appicciato.",
+       "upload-curl-error28": "Fore tiempo p' 'a carreca",
+       "upload-curl-error28-text": "'O sito trica tiempo a risponnere.\nPe piacere, cuntrullate ca 'o sito è appicciato, aspettate nu poco 'e tiempo e pruvate n'ata vota.\nVuje forse vulite aspettà nu poco ca se spiccia 'o traffeco a 'o sito.",
        "license": "Licenze:",
        "license-header": "Licenza",
+       "nolicense": "Nisciuna licienza scigliuta",
+       "licenses-edit": "Càgna opzziune 'e licenza",
+       "license-nopreview": "(Anteprimma nun disponibbele)",
+       "upload_source_url": "(nu file 'a n'URL valido e accessibbele pubblecamente)",
+       "upload_source_file": "(nu file d' 'o computer 'o tuojo)",
+       "listfiles-delete": "scancèlla",
+       "listfiles-summary": "Sta paggena speciale fà vedé tuttequante file carrecate.",
+       "listfiles_search_for": "Ascìa 'e media pe' nomme:",
+       "imgfile": "file",
+       "listfiles": "Lista d' 'e file",
+       "listfiles_thumb": "Miniature",
+       "listfiles_date": "Data",
        "listfiles_name": "Nomme",
+       "listfiles_user": "Utente",
+       "listfiles_size": "Dimenzione",
+       "listfiles_description": "Descrizzione",
+       "listfiles_count": "Verziune",
+       "listfiles-show-all": "Nclude 'e verziune viecchie 'e ll'immaggene",
+       "listfiles-latestversion": "Verzione 'e mo",
+       "listfiles-latestversion-yes": "Sì",
+       "listfiles-latestversion-no": "No",
        "file-anchor-link": "Fiùra",
        "filehist": "Cronologgia d\"o file",
-       "filehist-revert": "ripristina",
+       "filehist-help": "Ffà click su nu gruppo data/ora pe' vedé 'o file comme s'apprisentava ind' 'a chillu mumento.",
+       "filehist-deleteall": "scancella tutto",
+       "filehist-deleteone": "scancèlla",
+       "filehist-revert": "arrepiglia",
        "filehist-current": "attuale",
        "filehist-datetime": "Data/Ora",
        "filehist-thumb": "Miniature",
+       "filehist-thumbtext": "Miniatura d' 'a verziona d' 'o $1",
+       "filehist-nothumb": "Nisciuna miniatura",
        "filehist-user": "Utente",
        "filehist-dimensions": "Dimenzione",
+       "filehist-filesize": "Dimenziune d\"o file",
+       "filehist-comment": "Commento",
        "imagelinks": "Jonte ê ffiure",
+       "linkstoimage": "{{PLURAL:$1|Sta paggena cullega|$1 'e sti paggene cullegano}} a stu file:",
+       "linkstoimage-more": "Cchiù 'e $1 {{PLURAL:$1|paggene cullegano|paggene cullegano}} a stu file.<br />\nL'alenco ccà abbascio fà vedé {{PLURAL:$1|'a primma paggena ca cullega|'e primme $1 paggene ca cullegano}} sulamente a stu file.<br />\nNa [[Special:WhatLinksHere/$2|lista completa]] è disponibbele.",
+       "nolinkstoimage": "Nisciuna paggena cullega a stu file.",
+       "morelinkstoimage": "Vide [[Special:WhatLinksHere/$1|cchiù cullegamiente]] a stu file.",
+       "linkstoimage-redirect": "$1 (redirezionamiente d' 'o file) $2",
+       "duplicatesoffile": "{{PLURAL:$1|'O file ccà abbascio è nu duplicato|'E $1 file ccà abbascio songo duplicate}} 'e stu file ([[Special:FileDuplicateSearch/$2|cchiù nfurmaziune]]):",
+       "sharedupload": "Stu file vène 'a $1 e pò essere ausato 'a n'ati pruggette.",
+       "sharedupload-desc-there": "Stu file vène 'a $1 e pò essere ausato pe n'ati pruggette.<br />\nPe' piacere vedite 'a [$2 pàggena 'e descrizione d' 'o file] pe' n'avé cchiù nfurmaziune.",
+       "sharedupload-desc-here": "Stu file vène 'a $1 e pò essere ausato pe n'ati pruggette.<br />\n'A descriziona ncopp' 'a [$2 pàggena 'e descrizione d' 'o file] se può vedé ccà abbascio.",
+       "sharedupload-desc-edit": "Stu file vène 'a $1 e pò essere ausato pe n'ati pruggette.<br />\nPuò darse ca vulite cagnà 'a descrizione d' 'a [$2 paggena 'e descrizione d' 'o file] ccà.",
+       "sharedupload-desc-create": "Stu file vène 'a $1 e pò essere ausato pe n'ati pruggette.<br />\nPuò darse ca vulite cagnà 'a descrizione dint' 'a [$2 paggena 'e descrizione d' 'o file] ccà.",
+       "filepage-nofile": "Nisciuno file cu stu nomme esiste.",
+       "filepage-nofile-link": "Nisciuno file cu stu nomme esiste, ma 'o putite [$1 carrecà].",
+       "uploadnewversion-linktext": "Càrreca na verziona nova 'e stu file",
+       "shared-repo-from": "'a $1",
+       "shared-repo": "n'archivio cundiviso",
+       "upload-disallowed-here": "Nun se può sovrascrivere stu file.",
+       "filerevert": "Arrepiglia $1",
+       "filerevert-legend": "Arrepiglia 'o file",
+       "filerevert-intro": "State arrepiglianno 'o file '''[[Media:$1|$1]]''' int' 'a [$4 verzione d' 'o $3, $2].",
+       "filerevert-comment": "Mutive:",
+       "filerevert-defaultcomment": "Arripigliata 'a verzione d' 'o $2, $1",
+       "filerevert-submit": "Arrepiglia",
+       "filerevert-success": "'''[[Media:$1|$1]]''' è stat'arripigliato â verziona [$4 d' 'e $3 d' 'o $2].",
+       "filerevert-badversion": "Nun ce sta na virziona lucale 'e stu file cu l'orario addimannato.",
+       "filedelete": "Scancella $1",
+       "filedelete-legend": "Scancella 'o file",
+       "filedelete-intro": "State pe' scancellà 'o file '''[[Media:$1|$1]]''' cu tutta 'a cronologgia 'e chisto.",
+       "filedelete-intro-old": "State a scancellà 'a verziona 'e '''[[Media:$1|$1]]''' d' 'o [$4 $3, $2].",
+       "filedelete-comment": "Mutivo:",
+       "filedelete-submit": "Scancèlla",
+       "filedelete-success": "'O file '''$1''' è stato scancellato.",
+       "filedelete-success-old": "'A verziona d' 'o file '''[[Media:$1|$1]]''' d' 'o  $3, $2  è stata scancellata.",
+       "filedelete-nofile": "Nun esiste nu file '''$1'''.",
+       "filedelete-nofile-old": "Nun ce sta na verziona archiviata 'e '''$1''' cu l'attrebbute specificate.",
+       "filedelete-otherreason": "Ati/cchiù ragiune:",
+       "filedelete-reason-otherlist": "Ati ragiune",
+       "filedelete-reason-dropdown": "*Mutive cchiù comune p' 'o scancellà\n** Violazione d' 'o copyright\n** File duplicato",
+       "filedelete-edit-reasonlist": "Càgna 'e mutive pe' fà 'o scancellamiento",
+       "filedelete-maintenance": "'O scancellamiento e arripiglio 'e file s'è stutato p' 'o mumento, pe' tramente ca se fà 'a manutenzione.",
+       "filedelete-maintenance-title": "Nun se può scancellà 'o file",
+       "mimesearch": "Ascià a sicondo 'o MIME",
+       "mimesearch-summary": "Sta paggena permette filtrà 'e file a sicondo 'o tipo 'e MIME.\nNzertate 'a stringa 'e ricerca comm'a nu tipo/sottotipo o tipo/*, p'esempio: <code>image/jpeg</code>.",
+       "mimetype": "Tipo 'e MIME:",
+       "download": "scarreca",
+       "unwatchedpages": "Paggene fore l'alenco 'e cuntrollo",
+       "listredirects": "Liste 'e ridirezionamiente",
+       "listduplicatedfiles": "Lista d' 'e file duplicate",
+       "listduplicatedfiles-summary": "Chist'è n'alenco 'e file, addò 'a verziona cchiù recente 'e nu file è nu duplicato d' 'a verziona cchiù ricente 'e n'atu file. Songhe cunziderate sulamente 'e file lucale.",
+       "listduplicatedfiles-entry": "[[:File:$1|$1]] ave [[$3|{{PLURAL:$2|nu duplicato|$2 duplicate}}]].",
+       "unusedtemplates": "Template ca nun se song'ausate",
+       "unusedtemplatestext": "Sta paggena alenca tutt' 'e paggene int'a 'o namespace {{ns:template}} ca nun se songo nzertàte dint'a n'ata paggena.\nArricuòrdete 'e cuntrullà l'ati cullegamiente a 'e template apprimm' 'e scancellà.",
+       "unusedtemplateswlh": "ati cullegamiente",
        "randompage": "Na paggena qualsiase",
        "randompage-nopages": "Nun gè song paggene {{PLURAL:$2|dint'ô seguente namespace|dint'ê seguenti namespace}}: $1.",
+       "randomincategory": "Paggena a uocchio dint' 'a categurìa",
+       "randomincategory-invalidcategory": "\"$1\" nun è nu nomme 'e categurìa bbuono.",
+       "randomincategory-nopages": "Non ce stanno pàggene dint' 'a [[:Category:$1]].",
+       "randomincategory-category": "Categurìa:",
+       "randomincategory-legend": "Paggena a uocchio dint' 'a categurìa",
+       "randomredirect": "Redirezionamiento a uocchio",
+       "randomredirect-nopages": "Nun ce stanno redirezionamiente int' 'o namespace \"$1\".",
        "statistics": "Statistiche",
+       "statistics-header-pages": "Statistiche d' 'e paggene",
+       "statistics-header-edits": "Cagna 'e statistiche",
+       "statistics-header-views": "Vide 'e statistiche",
+       "statistics-header-users": "Statistiche 'e l'utente",
+       "statistics-header-hooks": "Ati statistiche",
+       "statistics-articles": "Paggene 'e cuntenute",
+       "statistics-pages": "Paggene",
+       "statistics-pages-desc": "Tutt' 'e paggene dint'a wiki, mettenno 'e chiacchieriate, redirezionamiente, ecc.",
+       "statistics-files": "File carrecate",
+       "statistics-edits": "Cagnamiente d' 'e paggene 'a che {{SITENAME}} s'è accumminciata",
+       "statistics-edits-average": "Cagnamiente medie pe' paggena",
+       "statistics-views-total": "Visite 'n totale",
+       "statistics-views-total-desc": "'E vviste a paggene ca nun esisteno e paggene speciale nun cuntano",
+       "statistics-views-peredit": "Visite pe' cagnamiento",
+       "statistics-users": "[[Special:ListUsers|Utente riggistrate]]",
+       "statistics-users-active": "Utente attive",
+       "statistics-users-active-desc": "Utente c'hanno fatto coccosa dint' 'a {{PLURAL:$1|l'urdemo juorno|l'urdeme $1 juorne}}",
+       "statistics-mostpopular": "Pàggene cchiù visitate",
+       "pageswithprop": "Paggene cu na prupietà 'e paggena",
+       "pageswithprop-legend": "Paggene cu na prupietà 'e paggena",
+       "pageswithprop-text": "Sta paggena alenca 'e paggene c'ausano na prupietà particolare 'e paggena.",
+       "pageswithprop-prop": "Nomme d' 'a prupietà:",
+       "pageswithprop-submit": "Vàje",
+       "pageswithprop-prophidden-long": "valore d' 'a prupietà d' 'o testo luongo annascunnuto ($1)",
+       "pageswithprop-prophidden-binary": "valore 'e prupietà binaria annascunnuto ($1)",
        "doubleredirects": "Redirect duppie",
+       "doubleredirectstext": "Sta paggena alenca 'e paggene ca se ridirezionano a n'ati paggene.\nOgne riga cuntene nu cullegamente a 'o primmo e a 'o sicondo ridirezionamiento pe' ffà vedé addò arriva 'o sicondo ridirezionamiento, 'o quale è nurmalmente 'a paggena 'e destinaziona \"riale\", addò 'o primmo ridirezionaminento avess'a cullegà.\n'A situazione d' 'e <del>ridireziune scancellate</del> è stat'arricettata.",
+       "double-redirect-fixed-move": "[[$1]] è stato spustato.\nÈ stato automaticamente agghiurnato e ora è nu redirect a [[$2]].",
+       "double-redirect-fixed-maintenance": "Curreggenno automaticamente 'o doppio redirect 'a [[$1]] a [[$2]] pe' tramente ca se fà na fatica 'e manutenzione.",
+       "double-redirect-fixer": "Currettore 'e redirezionamiente",
+       "brokenredirects": "Redirezionamiente scassate",
+       "brokenredirectstext": "'E redirezionamiente ccà abbascio vanno a paggene ca nun esisteno:",
+       "brokenredirects-edit": "càgna",
+       "brokenredirects-delete": "scancèlla",
+       "withoutinterwiki": "Paggene senza cullegamiente interwiki",
+       "withoutinterwiki-summary": "'E paggene ccà abbascio nun songo cullegate a nisciun'ata verzione 'e lengua differente.",
+       "withoutinterwiki-legend": "Prefisse",
+       "withoutinterwiki-submit": "Faje vedé",
+       "fewestrevisions": "Paggene cu meno cagnamiente",
        "nbytes": "$1 {{PLURAL:$1|byte|byte}}",
        "ncategories": "$1 {{PLURAL:$1|categoria|categorie}}",
+       "ninterwikis": "$1 {{PLURAL:$1|interwiki}}",
        "nlinks": "$1 {{PLURAL:$1|cullegamiento|cullegamiente}}",
        "nmembers": "$1 {{PLURAL:$1|elemento|elemente}}",
+       "nmemberschanged": "$1 → $2 {{PLURAL:$2|membro|membre}}",
+       "nrevisions": "$1 {{PLURAL:$1|verzione|verziune}}",
+       "nviews": "$1 {{PLURAL:$1|visita|visite}}",
+       "nimagelinks": "Ausate ncopp'a {{PLURAL:$1|na paggena|$1 paggene}}",
+       "ntransclusions": "ausate ncopp'a {{PLURAL:$1|na paggena|$1 paggene}}",
+       "specialpage-empty": "Nun ce stanno risultate pe' stu report.",
+       "lonelypages": "Paggene orfane",
+       "lonelypagestext": "'E paggene ccà abbascio nun so state cullegate o appennute int' 'a n'ati paggene ncopp'a {{SITENAME}}.",
+       "uncategorizedpages": "Paggene senza categurìa",
+       "uncategorizedcategories": "Categurìe senza categurìa",
+       "uncategorizedimages": "File senza categurìa",
+       "uncategorizedtemplates": "Template senza categurìa",
+       "unusedcategories": "Categurìe ca nun s'ausano",
+       "unusedimages": "File ca nun s'ausano",
        "popularpages": "Paggene cchiù 'speziunate",
+       "wantedcategories": "Categurìe addimannate",
        "wantedpages": "Paggene cchiù addemannate",
+       "wantedpages-badtitle": "Titolo invalido mmiez' 'o nzieme 'e risultate: $1",
+       "wantedfiles": "File addimannate",
+       "wantedfiletext-cat": "Chisti file s'ausano ma nun esisteno. 'E file ca veneno 'e n'archivio 'e fore s'alencano ccà senza cuntrullà l'esistenza suja. Sti fauze pusitive sarranno <del>nzignate</del>. 'E paggene ca teneno sti file ca nun esisteno song'alencate dint'a [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Sti file ccà, song'ausate, ma nun esisteno. Anze, 'e paggene c'ausano sti file song'alencate dint'a [[:$1]].",
+       "wantedfiletext-nocat": "'E file ccà abbascio s'ausano ma nun esisteno. 'E file ca veneno 'e n'archivio 'e fore s'alencano ccà senza cuntrullà l'esistenza suja. Sti fauze pusitive sarranno <del>nzignate</del>.",
+       "wantedfiletext-nocat-noforeign": "'E file ccà abbascio s'ausano ma nun esisteno.",
+       "wantedtemplates": "Template addimannate",
+       "mostlinked": "Paggene cchiù addimannate",
+       "mostlinkedcategories": "Categurìe cchiù addimannate",
+       "mostlinkedtemplates": "Paggene cchiù appennute",
+       "mostcategories": "Paggene cu cchiù categurìe",
+       "mostimages": "File cchiù addimannate",
+       "mostinterwikis": "Paggene cu cchiù interwiki",
+       "mostrevisions": "Paggene cu cchiù cagnamiente",
+       "prefixindex": "Tutte 'e paggene cu prefisso",
+       "prefixindex-namespace": "Tutte 'e paggene cu prefisso d' 'o namespace $1",
+       "prefixindex-strip": "Annascunne 'o prefisso int' 'a lista",
        "shortpages": "Paggene curte",
        "longpages": "Paggene cchiú longhe",
+       "deadendpages": "Paggene ca nun spòntano",
+       "deadendpagestext": "'E paggene ccà abbascio nun spontano a n'ati paggene ncopp'a {{SITENAME}}.",
+       "protectedpages": "Paggene prutette",
+       "protectedpages-indef": "Sulamente prutezziune a tiempo nun definito",
+       "protectedpages-summary": "Sta paggena elenca 'e paggene ch'esisteno e ca songo prutette mò. Pe n'avé n'elenco 'e titule prutette â criazione, vedite [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
+       "protectedpages-cascade": "Sulamente prutezziune ricurzive",
+       "protectedpages-noredirect": "Annascunne redirect",
+       "protectedpagesempty": "Nisciuna paggena è prutetta pe mò cu sti parametre.",
+       "protectedpages-timestamp": "Data e ora",
+       "protectedpages-page": "Paggena",
+       "protectedpages-expiry": "Ammatura",
+       "protectedpages-performer": "Prutetta 'a ll'utente",
+       "protectedpages-params": "Parametre 'e prutezione",
+       "protectedpages-reason": "Mutivo",
+       "protectedpages-unknown-timestamp": "Scanusciuto",
+       "protectedpages-unknown-performer": "Utente scanusciuto",
+       "protectedtitles": "Paggene prutette",
+       "protectedtitles-summary": "Sta paggena elenca 'e titule ca song'attualmente prutette 'a criazione. Pe' n'avé n'elenco 'e paggene prutette ch'esisteno, vedite [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
+       "protectedtitlesempty": "Nisciunu titolo è prutetto pe mò cu sti parametre.",
+       "listusers": "Lista 'e l'utente",
+       "listusers-editsonly": "Fà vedé sulamente l'utente cu cagnamiente fatte",
+       "listusers-creationsort": "Arrecetta pe' data 'e criazione",
+       "listusers-desc": "Arrecetta 'a l'auto a 'o vascio",
+       "usereditcount": "{{PLURAL:$1|nu càgnamiento|$1 càgnamiente}}",
        "usercreated": "{{GENDER:$3|Criato/a}} 'o $1 a $2",
        "newpages": "Paggene cchiù frische",
+       "newpages-username": "Nomme utente:",
+       "ancientpages": "Paggene cchiù viecchie",
        "move": "Spusta",
        "movethispage": "Spusta chesta paggena",
+       "unusedimagestext": "'E file ccà abbascio esisteno, ma nun songo appennute dint' 'a nisciuna paggena.\nPe' piacere vedite ca n'ati site ncopp' 'a ll'Internet putessero cullegà cu nu file direttamente cu l'URL, picciò vedite ca putessero stà dint'a sta lista ancora tenenno nu cullegamiento diretto.",
+       "unusedcategoriestext": "'E categurìe ccà abbascio esisteno, ancora ch' 'e categurìe o l'ati paggene nun l'aùsano.",
+       "notargettitle": "Nisciuna destinazione",
+       "notargettext": "Nun avete specificato na paggena o n'utente 'e destinazione pe' putè fa sta operazione.",
+       "nopagetitle": "Nisciuna paggena 'e destinazione",
+       "nopagetext": "'A paggena 'e destinazione c'avite specificato nun esiste.",
+       "pager-newer-n": "{{PLURAL:$1|1 cchiù viecchio|$1 cchiù viecchie}}",
        "pager-older-n": "{{PLURAL:$1|1 cchiù viecchio|$1 cchiù viecchie}}",
+       "suppress": "Supervisione",
+       "querypage-disabled": "Sta paggena speciale è stutata pe' mutive 'e prestaziune.",
        "booksources": "Funte libbrarie",
+       "booksources-search-legend": "Ascìa 'e fonte ncopp' 'e libbre",
        "booksources-go": "Vàje",
+       "booksources-text": "Ccà abbascio ce sta na lista 'e cullegamiente a l'ati site ca venneno libbre nuove e viecchie, ca putessero pure avé cchiù nfurmaziune ncopp' 'e libbre ca jate ascianno:",
+       "booksources-invalid-isbn": "L'ISBN c'avete miso nun pare bbuono; cuntrolla si ce sta cocch'errore quanno stavate cupianno stu nummero d' 'a fonte origginale.",
+       "specialloguserlabel": "Mplementatore:",
+       "speciallogtitlelabel": "Destinazione (titolo o utente):",
        "log": "Logs",
+       "all-logs-page": "Tutte l'archivie pubbleche",
+       "alllogstext": "Visualizzazione mmescata 'e tutte 'e riggistre disponibbele ncopp'a {{SITENAME}}.\nPutite restringere 'a vista a sicondo 'o tipo 'e riggistro, 'o nomme utente (sensibbele a 'e maiuscole), o 'e paggene coinvolte (pure chiste songo sensibbele a 'e maiuscole).",
+       "logempty": "Nun ce sta n'elemento dint' 'o riggistro azzeccato â ricerca.",
+       "log-title-wildcard": "Ascìa titole c'accummencieno cu stu testo",
+       "showhideselectedlogentries": "Cagna visibbelità d' 'e riggistre scigliute",
        "allpages": "Tutte 'e ppaggene",
+       "nextpage": "Paggena appriesso ($1)",
+       "prevpage": "Paggena apprima ($1)",
+       "allpagesfrom": "Fà vedè 'e paggene partenno 'a:",
+       "allpagesto": "Fà vedè 'e paggene ca fernisceno 'o:",
        "allarticles": "Tutt' 'e vvoce",
        "allinnamespace": "Tutt' 'e ppaggene d''o namespace $1",
        "allpagessubmit": "Vàje",
+       "allpagesprefix": "Fà vedè 'e paggene cu 'o prefisso:",
+       "allpagesbadtitle": "'O titolo d' 'a paggena richiesta è invalido o pure nun è linkato buono a 'o titolo inter-lengua o inter-wiki.\nPutesse pure tené uno o cchiù carattere ca nun se ponno usà dint'e titule.",
+       "allpages-bad-ns": "{{SITENAME}} nun ce tene 'o namespace \"$1\".",
+       "allpages-hide-redirects": "Annascunne redirect",
+       "cachedspecial-viewing-cached-ttl": "State a vedé na verzione int' 'a cache 'e sta paggene, 'a quale pò essere agghiurnata 'a $1 fà.",
+       "cachedspecial-viewing-cached-ts": "State vedenno na verzione 'n cache, ca putesse nun essere agghiurnata.",
+       "cachedspecial-refresh-now": "Vide l'urdeme.",
        "categories": "Categurìe",
        "categoriespagetext": "{{PLURAL:$1|'A categurìa 'nnecata 'e seguito cuntiene|'E categurìe 'nnecate 'e seguito cuntengono}} paggene o file multimediale.\n'E [[Special:UnusedCategories|categurìe vuote]] nun song mostrate ccà.\nVere anche 'e [[Special:WantedCategories|categurìe richieste]].",
+       "categoriesfrom": "Fà vedè 'e categurìe partenno 'a:",
+       "special-categories-sort-count": "arricetta pe' cunteggio",
+       "special-categories-sort-abc": "arricetta arfabbeticamente",
+       "deletedcontributions": "Contribbute utente scancellate",
+       "deletedcontributions-title": "Contribbute utente scancellate",
+       "sp-deletedcontributions-contribs": "contribbute",
+       "linksearch": "Ascìa cullegamiente 'a fore",
+       "linksearch-pat": "Ascìa pe' mudello 'e ricerca:",
+       "linksearch-ns": "Namespace:",
        "linksearch-ok": "Truova",
+       "linksearch-text": "'E wildcard cumm'a \"*.wikipedia.org\" ponno essere ausate.<br />\nCe vulesse minimo nu dominio d'auto livello, p'esempio \"*.org\". <br />\n{{PLURAL:$2|Prutucolle}} suppurtate: <code>$1</code> ('o valore 'e bbase è http:// si 'o protocollo nun è stato specificato).",
        "linksearch-line": "$1 presente dint'â paggena $2",
+       "linksearch-error": "'E wildcard ponno essere ausate sulamente a l'inizio d' 'o hostname.",
+       "listusersfrom": "Fà vedè l'utente partenno 'a:",
+       "listusers-submit": "Faje vedé",
+       "listusers-noresult": "Nisciun'utente truvato.",
+       "listusers-blocked": "(bloccate)",
+       "activeusers": "Lista d'utente attive",
+       "activeusers-intro": "Chest'è n'elenco d'utente c'hanno fatto cierti tipe d'attività nfin'a $1 {{PLURAL:$1|juorno|ghiuorne}} fa.",
+       "activeusers-count": "$1 {{PLURAL:$1|cagnamiento|cagnamiente}} int'a l'urdeme {{PLURAL:$3|ghiuorne}}",
+       "activeusers-from": "Fà vedè l'utente partenno 'a:",
+       "activeusers-hidebots": "Annascunne 'e bot",
+       "activeusers-hidesysops": "Annascunne l'ammenistrature",
+       "activeusers-noresult": "Nisciun'utente truvato.",
+       "listgrouprights": "Deritte d' 'e gruppe utente",
+       "listgrouprights-summary": "'A lista ccà abbascio è na lista d' 'e gruppe utente criate int'a sta wiki, ch' 'e diritte associate.\nPonno esistere [[{{MediaWiki:Listgrouprights-helppage}}|nfurmaziune cchiù ndettaglie]] ncopp' 'e deritte ndividuale.",
+       "listgrouprights-key": "* <span class=\"listgrouprights-granted\">Deritto dato</span>\n* <span class=\"listgrouprights-revoked\">Deritto luvato</span>",
+       "listgrouprights-group": "Gruppo",
+       "listgrouprights-rights": "Deritte",
+       "listgrouprights-helppage": "Help:Deritte d' 'o gruppo",
+       "listgrouprights-members": "(lista d' 'e membre)",
+       "listgrouprights-addgroup": "Jogne {{PLURAL:$2|ô gruppo|ê gruppe}}: $1",
+       "listgrouprights-removegroup": "Leva {{PLURAL:$2|d' 'o gruppo|d' 'e gruppe}}: $1",
+       "listgrouprights-addgroup-all": "Jogne tutt' 'e gruppe",
+       "listgrouprights-removegroup-all": "Leva tutt' 'e gruppe",
+       "listgrouprights-addgroup-self": "Jogne {{PLURAL:$2|'o gruppo|'e gruppe}} a 'o cunto utente mio: $1",
+       "listgrouprights-removegroup-self": "Leva {{PLURAL:$2|'o gruppo|'e gruppe}} 'a 'o cunto utente d' 'o mio: $1",
+       "listgrouprights-addgroup-self-all": "Miette tutt' 'e gruppe ncopp' 'o cunto d' 'o mio",
+       "listgrouprights-removegroup-self-all": "Lèva tutt' 'e gruppe 'a 'o cunto utente d' 'o mio",
+       "listgrouprights-namespaceprotection-header": "Restriziune d' 'o namespace",
+       "listgrouprights-namespaceprotection-namespace": "Namespace",
+       "listgrouprights-namespaceprotection-restrictedto": "Diritto 'e cagnamiento 'e l'utente",
+       "trackingcategories": "Categurìe 'e cuntrollo",
+       "trackingcategories-summary": "Sta paggena elenca 'e categurìe ca stann'automaticamente popolate 'a 'o software Mediawiki. 'E nomme 'e lloro se ponno cagnà quanno se cagnano 'e relative mmasciate 'e sistema dint' 'o namespace {{ns:8}}.",
+       "trackingcategories-msg": "Categurìe 'e cuntrollo",
+       "trackingcategories-name": "Nomme d' 'a mmasciata",
+       "trackingcategories-desc": "Criterie p' 'o miettere dint' 'a categurìa",
+       "noindex-category-desc": "'A paggena nun è indicizzata 'a 'e robot pecché cuntene 'a parola maggica <code><nowiki>__NOINDEX__</nowiki></code> e se trova dint'a nu namespace addò chistu flag è permesso.",
+       "index-category-desc": "'A paggena téne 'o codece <code><nowiki>__INDEX__</nowiki></code> dinto (e se trova dint'a nu namespace addò chistu flag è permesso), e picciò è indicizzata 'a 'e robot, pure si normalmente nun fosse accussì.",
+       "post-expand-template-inclusion-category-desc": "'A dimensione d' 'a paggena è cchiù granne 'e <code>$wgMaxArticleSize</code> aropp'a spannere tutt' 'e template, e picciò cocche template nun se so' spannute.",
+       "post-expand-template-argument-category-desc": "'A paggena sarrà cchiù granne 'e <code>$wgMaxArticleSize</code> aropp' 'avé spannuto 'o parametro 'e nu template (coccosa mmiez'a tre parentesi graffe, cumm'a cchesto: <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "'A paggena aúsa troppe funziune parser (comme <code>#ifexist</code>). Vedite [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "'A paggena cuntene nu cullegamiento rutto a nu file (nu link ca spontasse a nu file ancora che chisto nun esiste).",
+       "hidden-category-category-desc": "Chista categurìa cuntene <code><nowiki>__HIDDENCAT__</nowiki></code> dint' 'a paggena suja, 'a quale nun permette ca s'ammustasse, predefinitamente, dint' 'o quadretto d' 'e cullegamiente a 'e categurìe d' 'e paggene.",
+       "trackingcategories-nodesc": "Nisciuna descrizione a disposizione.",
+       "trackingcategories-disabled": "'A categurìa è stutata",
+       "mailnologin": "Nisciuno indirizzo pe' mannà 'e mmasciate",
+       "mailnologintext": "Avite 'a [[Special:UserLogin|trasì]] e avè n'indirizzo e-mail valido int' 'e [[Special:Preferences|preferenze]] d' 'e vuoste pe' mannà na mmasciata e-mail a l'ati utente.",
        "emailuser": "Email chisto utente",
-       "mywatchlist": "osservate speciale",
+       "emailuser-title-target": "Manna n'email a chist'{{GENDER:$1|utente}}",
+       "emailuser-title-notarget": "E-mail 'e l'utente",
+       "emailpage": "E-mail 'e l'utente",
+       "emailpagetext": "Putite ausà 'o modulo ccà abbascio pe' mannà na mmasciata e-mail a st'{{GENDER:$1|utente}}.\nL'indirizzo e-mail ch'avite nzertàto dint' 'e [[Special:Preferences|preferenze vuoste]] accumpararrà dint' 'o campo \"'A\" dint' 'a mmasciata e-mail, accussì chillo ca ricevese 'a mail 'o sape ca v'avess'a risponnere direttamente a vuje.",
+       "defemailsubject": "e-mail 'e {{SITENAME}} 'a l'utente \"$1\"",
+       "usermaildisabled": "L'e-mail utente è stutato",
+       "usermaildisabledtext": "Nun se può mannà n'e-mail a l'at'utente ncopp' 'a sta wiki",
+       "noemailtitle": "Nisciuno indirizzo e-mail",
+       "noemailtext": "St'utente nun ha miso nisciuno indirizzo e-mail valido.",
+       "nowikiemailtext": "St'utente ha scigliuto 'e nun se cuògliere mmasciate e-mail 'a l'at'utente.",
+       "emailnotarget": "Nomme 'e l'utente ca nun esiste o nun è valido.",
+       "emailtarget": "Mettite 'o nomme utente d' 'o destinatario",
+       "emailusername": "Nomme utente:",
+       "emailusernamesubmit": "Manna",
+       "email-legend": "Manna sta mail a n'at'utente 'e {{SITENAME}}",
+       "emailfrom": "'A:",
+       "emailto": "A:",
+       "emailsubject": "Oggetto:",
+       "emailmessage": "Mmasciata:",
+       "emailsend": "Manna",
+       "emailccme": "Manname n'e-mail cu 'na copia d' 'a mmasciata.",
+       "emailccsubject": "Copia d' 'a mmasciata tua 'a $1: $2",
+       "emailsent": "Mmasciata e-mail mannata",
+       "emailsenttext": "'A mmasciata d' 'a toja s'è mannata.",
+       "emailuserfooter": "Chista mmasciata e-mail è stata mannata 'a $1 a $2 p' 'a funziona \"Mmasciata e-mail a l'utente\" 'e {{SITENAME}}.",
+       "usermessage-summary": "Lassanno na mmasciata 'e sistema.",
+       "usermessage-editor": "Mmasciatore d' 'o sistema",
+       "watchlist": "Paggene cuntrullate",
+       "mywatchlist": "Paggene cuntrullate",
        "watchlistfor2": "Ppe $1 $2",
+       "nowatchlist": "Nun tenite paggene dint' 'a l'elenco 'e paggene cuntrullate.",
+       "watchlistanontext": "Pe' piacere, trasite pe' vedé o cagnà l'elenco 'e paggene cuntrullate.",
+       "watchnologin": "Acciesso nun affettuato",
+       "addwatch": "Miette dint' 'a l'elenco 'e paggene cuntrullate",
+       "addedwatchtext": "'A paggena \"[[:$1]]\" è stata azzeccata dint'a l'elenco 'e [[Special:Watchlist|paggene cuntrullate]].\n'E cagnamiente future a sta paggena e a tutt' 'e paggene 'e chiacchiera azzeccate sarranno elencate llà dinto.",
+       "addedwatchtext-short": "Chista paggena \"$1\" è stata azzeccata a l'elenco 'e paggene cuntrullate.",
+       "removewatch": "Leva 'a l'elenco 'e paggene cuntrullate",
+       "removedwatchtext": "'A paggena \"[[:$1]]\" è stata scancellata 'a l'elenco [[Special:Watchlist|'e paggene cuntrullate]] tuojo.",
+       "removedwatchtext-short": "Chista paggena \"$1\" è stata luvata a l'elenco 'e paggene cuntrullate.",
        "watch": "Secuta",
+       "watchthispage": "Tiene d'uocchio chesta paggena",
        "unwatch": "Nun segui",
+       "unwatchthispage": "Nun cuntrullà cchiù sta paggena",
        "notanarticle": "Chesta paggena nun è na voce",
+       "notvisiblerev": "'A verzione è stata scancellata",
+       "watchlist-details": "L'elenco 'e paggene cuntrullate cuntene {{PLURAL:$1|na paggena (e pure 'a paggena 'e chiacchiera)|$1 paggene (e pure 'e paggene 'e chiacchiera}}.",
+       "wlheader-enotif": "'A funzione 'e notifiche e-mail è appicciata.",
+       "wlheader-showupdated": "* 'E paggene cca so' state cagnate a l'urdema visita avevano so' nzignate ccà 'n '''grassetto'''.",
+       "wlnote": "Ccà abbascio {{PLURAL:$1|è elencato 'o cagnamiento cchiù ricente|songo elencate 'e <strong>$1</strong> cagnamiente cchiù recente}} {{PLURAL:$2|int'a ll'urdema ora|int' 'e ll'urdeme <strong>$2</strong> ore}}; 'e date songo agghiurnate 'o $3, $4.",
+       "wlshowlast": "Mmusta ll'urdeme $1 ore $2 ghiuorne $3",
+       "watchlist-options": "Opziune 'a l'elenco 'e paggene cuntrullate",
+       "watching": "Cuntrullanno...",
+       "unwatching": "Lassanno 'e cuntrullà...",
+       "watcherrortext": "N'errore s'è verificato quanno se faceva 'o cagnamiento 'e l'elenco 'e paggene cuntrullate pe' \"$1\".",
+       "enotif_reset": "Nzègna tutt' 'e paggene comme visitate",
+       "enotif_impersonal_salutation": "Utente 'e {{SITENAME}}",
+       "enotif_subject_deleted": "'A paggena $1 'e {{SITENAME}} è stata scancellata 'a {{gender:$2|$2}}",
+       "enotif_subject_created": "'A paggena $1 'e {{SITENAME}} è stata criata 'a {{gender:$2|$2}}",
+       "enotif_subject_moved": "'A paggena $1 'e {{SITENAME}} è stata cagnata 'e posto 'a {{gender:$2|$2}}",
+       "enotif_subject_restored": "'A paggena $1 'e {{SITENAME}} è stata arripigliata 'a {{gender:$2|$2}}",
+       "enotif_subject_changed": "'A paggena $1 'e {{SITENAME}} è stata cagnata 'a {{gender:$2|$2}}",
+       "enotif_body_intro_deleted": "'A paggene $1 'e {{SITENAME}} è stata scancellata 'a copp' 'e $PAGEEDITDATE 'a {{gender:$2|$2}}, vedite $3.",
+       "enotif_body_intro_created": "'A paggena $1 'e {{SITENAME}} è stata criata ncopp'a $PAGEEDITDATE 'a {{gender:$2|$2}}, vedite $3 p' 'a verzione 'e mo.",
+       "enotif_body_intro_moved": "'A paggena $1 'e {{SITENAME}} è stata cagnata 'e posto ncopp'a $PAGEEDITDATE 'a {{gender:$2|$2}}, vedite $3 p' 'a verzione 'e mo.",
+       "enotif_body_intro_restored": "'A paggena $1 'e {{SITENAME}} è stata arripigliata ncopp'a $PAGEEDITDATE 'a {{gender:$2|$2}}, vedite $3 p' 'a verzione 'e mo.",
+       "enotif_body_intro_changed": "'A paggena $1 'e {{SITENAME}} è stata cagnata ncopp'a $PAGEEDITDATE 'a {{gender:$2|$2}}, vedite $3 p' 'a verzione 'e mo.",
+       "enotif_lastvisited": "Vedite $1 pe' tutt' 'e cagnamiente 'a ll'urdema visita vuosta.",
+       "enotif_lastdiff": "Vedite $1 pe' vedè stu cagnamiento.",
+       "enotif_anon_editor": "Utente anonimo $1",
+       "enotif_body": "Caro $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nRiepilego 'e cagnamiente: $PAGESUMMARY $PAGEMINOREDIT\n\nCuntattate l'autore:\ne-mail: $PAGEEDITOR_EMAIL\nncopp' 'o sito: $PAGEEDITOR_WIKI\n\nNun se mannarranno ati notifiche si facite cocch'at'attività senza venì a sta paggena.\nPutite pure cagnà 'e mpustaziune 'e notifeca pe' tutt' 'e paggene cuntrullate dint' 'a l'elenco.\n\nStatteve Bbuon, 'o sistema 'e notifiche ncopp' 'a {{SITENAME}} vuosto\n\n--\nPe' cagnà 'e mpustaziune d' 'e notifiche 'e mmasciate elettroniche, jate ccà: {{canonicalurl:{{#special:Preferences}}}}\n\nPe' cagnà 'e mpustaziune 'e l'elenco 'e paggene cuntrullate vuoste jate ccà: {{canonicalurl:{{#special:EditWatchlist}}}}\n\nPe' scancellà l'elenco 'e paggene cuntrullate vedite $UNWATCHURL\n\nSegnalaziune e at'assistenze:\n$HELPPAGE",
        "changed": "cagnata",
        "deletepage": "Scancella paggena",
+       "confirm": "Cunferma",
        "excontent": "'o cuntenuto era: '$1'",
        "excontentauthor": "'o cuntenuto era: '$1' (e ll'unneco cuntribbutore era '[[Special:Contributions/$2|$2]]')",
        "exbeforeblank": "'O cuntenuto apprimm' 'a ll'arrevacamento era: '$1'",
+       "delete-confirm": "Scancella \"$1\"",
+       "delete-legend": "Scancella",
+       "historywarning": "'''Attenzione:''' 'A paggena ca state pe' scancellà tene na cronologgia cu $1 {{PLURAL:$1|verzione|verziune}}:",
+       "confirmdeletetext": "Vedite bbuono, vedite ca state a scancellà na paggena nziem' 'a tutt' 'a cronologgia.\nPe' piacere cunfermate si overo vulite fà cchesto, ca ve site fatto/a capace 'e l'effette 'e st'azione e ca chest'azione rispetta 'e [[{{MediaWiki:Policy-url}}|reole 'e scancellamiento]].",
        "actioncomplete": "Azzione fernuta",
+       "actionfailed": "Aziona sfalluta",
        "deletedtext": "Qauccheruno ha scancellata 'a paggena \"$1\".  Addumannà 'o $2 pe na lista d\"e ppaggene scancellate urdemamente.",
        "dellogpage": "Scancellazione",
+       "dellogpagetext": "Ccà abbascio sta na lista ch' 'e cchiù recente scancellamiente.",
        "deletionlog": "Log d\"e scancellazione",
+       "reverted": "Turnà a 'a verziona cchiù recente",
        "deletecomment": "Raggióne",
+       "deleteotherreason": "Ati/cchiù ragiune:",
+       "deletereasonotherlist": "Ati ragiune",
+       "deletereason-dropdown": "*Mutive comune de scancellamiento\n** Spam\n** Vandalisme\n** Violazione d' 'o Copyright\n** Richieste 'e l'autore\n** Redirezionamente scassate",
+       "delete-edit-reasonlist": "Càgna 'e mutive 'e scancellamiento",
+       "delete-toobig": "Sta paggena tene na storia 'e cagnamiente troppo longa, ncopp'a $1 {{PLURAL:$1|verzione|verziune}}.\n'O scancellamiento 'e chiste paggene è stato ristretto pe nce 'e putè astipà si ce sta cocche probblema dint' 'o database 'e {{SITENAME}}.",
+       "delete-warning-toobig": "Sta paggena tene na cronologgia troppo longa, ncopp'a $1 {{PLURAL:$1|verzione|verziune}}.\nScancellannole se putesse crià troppo burdello ncopp' 'e operaziune 'e database dint'a {{SITENAME}};\niate cuoncio cuoncio.",
+       "deleteprotected": "Nun putite scancellà sta paggena pecché è stata prutetta.",
+       "deleting-backlinks-warning": "'''Attenzione:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|ati paggene]] cunteneno cullegamiente o paggene appennute â n'ata paggena ca state pe' scancellà.",
        "rollback": "Ausa na revizione 'e primma",
+       "rollback_short": "Annulla",
        "rollbacklink": "a vascio",
+       "rollbacklinkcount": "annulla {{PLURAL:$1|nu cagnamiento|$1 cagnamiente}}",
+       "rollbacklinkcount-morethan": "annulla cchiù 'e {{PLURAL:$1|nu cagnamiento|$1 cagnamiente}}",
+       "rollbackfailed": "Annullamento fallito",
+       "cantrollback": "Nun se può annullà stu cagnamiento;\nsapite ca l'urdemo autore è stato pure sul'isso a faticà dint'a sta paggena (nun ce sta n'at'autore).",
+       "alreadyrolled": "Nun se può turna arreto a l'urdemo cagnamiento [[:$1]] 'a [[User:$2|$2]] ([[User talk:$2|Chiacchiera]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]);\ncocch'ato ha cagnato o annullato 'a paggena già.\n\nL'urdemo cangamiento d' 'a paggena fuje 'a [[User:$3|$3]] ([[User talk:$3|Chiacchiera]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
+       "editcomment": "'O riepilego d' 'o cagnamiento era: \"''$1''\".",
        "revertpage": "Cangiaje 'e cagnamiénte 'e [[Special:Contributions/$2|$2]] ([[User talk:$2|discussione]]), cu â verzione 'e pprimma 'e  [[User:$1|$1]]",
+       "revertpage-nouser": "Annullate 'e cagnamiente 'e n'utente annascunnuto, è stata ripigliata ll'urdema verzione 'e {{GENDER:$1|[[User:$1|$1]]}}",
+       "rollback-success": "Cagnamiente annullate 'a $1;\ns'è turnat arreto a l'urdema verzione 'e $2.",
+       "sessionfailure-title": "Sessione fallita",
+       "sessionfailure": "Pare ca stanno probbleme cu 'a sessiona toja;\nst'azione è stata fermata pe' precauzione annanz' 'e cavall' 'e troia;\nPe' piacere turnate arreto, carrecate n'ata vota 'a paggena pe pruvate n'ata vota.",
+       "protectlogpage": "Riggistro 'e prutezzione",
+       "protectlogtext": "Ccà abbascio sta na lista 'e cagnamiente 'e pruteziune d' 'e paggene.\nVedite 'a [[Special:ProtectedPages|liste d' 'e paggene prutette]] pe n'avé na lista 'e l'operaziune 'e mo ncopp' 'a prutezzione d' 'e paggene.",
        "protectedarticle": "ha prutetto \"[[$1]]\"",
+       "modifiedarticleprotection": "'o livello 'e prutezione è stato cagnato pe' \"[[$1]]\"",
+       "unprotectedarticle": "sprutetto 'a \"[[$1]]\"",
+       "movedarticleprotection": "'mpustaziune 'e protezzione spustate 'a \"[[$2]]\" a \"[[$1]]\"",
+       "protect-title": "Cagna 'o livello 'e prutezione pe' \"[[$1]]\"",
+       "protect-title-notallowed": "Fà vedé 'o livello 'e prutezione pe' \"$1\"",
        "prot_1movedto2": "ha spustato [[$1]] a [[$2]]",
+       "protect-badnamespace-title": "Namespace nun pruteggibbele",
+       "protect-badnamespace-text": "'E paggene int'a stu namespace nun se ponno pruteggere.",
+       "protect-norestrictiontypes-text": "Sta paggena nun se può pruteggere pecché nun ce sta nisciunu tipo 'e restrizione.",
+       "protect-norestrictiontypes-title": "Namespace nun pruteggibbele",
+       "protect-legend": "Cunferma 'a prutezione",
+       "protectcomment": "Mutivo:",
+       "protectexpiry": "Ammatura:",
+       "protect_expiry_invalid": "'O tiempo d'ammaturamiento è invalido.",
+       "protect_expiry_old": "'O tiempo d'ammaturamiento è passato già.",
+       "protect-unchain-permissions": "Sblocca cchiù opziune 'e prutezione",
+       "protect-text": "Ccà putite vedé e cagnà 'o livello 'e prutezione p' 'a paggena <strong>$1</strong>.",
+       "protect-locked-blocked": "Nun può cagnà 'e livelle 'e prutezione pe' tramente ca staje bluccato.\nCcà abbascio stanno 'e mpustaziune 'e mo p' 'a paggena '''$1''':",
+       "protect-locked-dblock": "'E livelle 'e prutezzione nun se ponno cagnà pecché ce sta nu blocco attivo d' 'o database.\nCcà abbascio stanno 'e mpustaziune 'e mo p' 'a paggena '''$1''':",
+       "protect-locked-access": "C' 'o cunto vuosto nun avite permesso pe' putè cagnà 'e livelle 'e prutezioen d' 'e paggene.\nChiste songh' 'e mpustaziune 'e mo p' 'a paggena '''$1''':",
+       "protect-cascadeon": "P' 'o mumento sta paggena è bloccata pecché sta appennuta dint'a {{PLURAL:$1|paggena scritta ccà abbascio, p' 'a quale|'e paggene scritte ccà abbascio p' 'e quale}} è attiva 'a prutezione ricurziva.\n'E cagnamiente a livello 'e prutezione individuale a uno a uno d' 'a paggena, nun tenerranno effette ncopp' 'e mpustaziune pigliate d' 'o fatto 'e se fà na prutezione ricurziva.",
+       "protect-default": "Permette tutte l'utente",
+       "protect-fallback": "Permette sulamente a l'utente c' 'o permesso \"$1\"",
+       "protect-level-autoconfirmed": "Permette sulamente a l'utente autocunvalidate",
+       "protect-level-sysop": "Permette sulamente a l'ammenistrature",
+       "protect-summary-cascade": "ricurziva",
+       "protect-expiring": "ammatura 'o $1 (UTC)",
+       "protect-expiring-local": "ammatura 'o $1",
+       "protect-expiry-indefinite": "indefinite",
+       "protect-cascade": "Prutegge paggene appennute dint'a sta paggena (spanne 'a prutezione a tutt' 'e paggene appennute ccà).",
+       "protect-cantedit": "Nun è possibbele cagnà 'e livelle e prutezione 'e sta paggena, pecchè nun tenite deritto o permesse pe' ne fà 'o cagnamiento.",
+       "protect-othertime": "N'ata durata:",
+       "protect-othertime-op": "ati durate",
+       "protect-existing-expiry": "'O tiempo d'ammaturamiento esistente: $3, $2",
+       "protect-otherreason": "Ati/cchiù ragiune:",
+       "protect-otherreason-op": "Ati ragiune",
+       "protect-dropdown": "*Mutive 'e prutezione comune\n** Vandalisme eccessive\n** Spam eccessivo\n** 'Uerre 'e cagnamiente controproducente\n** Paggena cu troppo traffeco",
+       "protect-edit-reasonlist": "Càgna 'e mutive 'e prutezione",
        "protect-expiry-options": "1 ore:1 hour,1 juorno:1 day,1 semmana:1 week,2 semmane:2 weeks,1 mese:1 month,3 mise:3 months,6 mise:6 months,1 anno:1 year,infinito:infinite",
+       "restriction-type": "Permesse:",
+       "restriction-level": "Livello 'e restrizione:",
+       "minimum-size": "Diminsiune minime:",
+       "maximum-size": "Diminsiune massime:",
+       "pagesize": "(byte)",
+       "restriction-edit": "Càgna",
+       "restriction-move": "Spusta",
+       "restriction-create": "Cria",
+       "restriction-upload": "Carreca",
+       "restriction-level-sysop": "prutetta",
+       "restriction-level-autoconfirmed": "semi-prutetta",
+       "restriction-level-all": "ogne livello",
+       "undelete": "Fà vedé 'e paggene scancellate",
+       "undeletepage": "Fà vedé e arrepiglia 'e paggene scancellate",
+       "undeletepagetitle": "'''Ccà abbascio ce stanno 'e verziune scancellate 'e [[:$1|$1]]'''.",
        "viewdeletedpage": "Vìre 'e ppàggine scancellate",
+       "undeletepagetext": "{{PLURAL:$1|'A paggena ccà abbascio è stata scancellata però|$1 paggene ccà abbascio so' state scancellate però}} stann'ancora dint' 'a l'archivio e se ponno arrepiglià.<br />\nL'archivie s'hanna pulezzà periodicamente.",
+       "undelete-fieldset-title": "Arrepiglia verziune",
+       "undeleteextrahelp": "P'arrepiglià 'a cronologgia completa d' 'a paggena, lassate 'e cascie abbacante e facite click ncopp'a '''''{{int:undeletebtn}}'''''.\nPe' putè arrepiglià selettivamente, miette nu zegno ncopp' 'e casciulele currispunnente a 'e verziune ca vulite arripiglià e po' facite click ncopp'a '''''{{int:undeletebtn}}'''''.",
+       "undeleterevisions": "$1 {{PLURAL:$1|verzione|verziune}} archiviate",
+       "undeletehistory": "Si arrepiglie 'a paggena, tutte 'e verziune sarrann'arrepigliate nziem'a chista.\nSi na paggena nova c' 'o stesso nomme è stata criata 'a che s'è fatto 'o scancellamiento, 'e verziune arripigliate cumparerranno comme cchiù viecchie dint' 'a cronologgia.",
+       "undeleterevdel": "L'arripiglio nun sarrà affettuato si determina 'o scancellamiento parziale d' 'a verzione 'e mo d' 'a paggena o file.\nInt'a sti case, avite 'e smarcà o annasconnere 'e verziune scancellate cchiù nove.",
+       "undeletehistorynoadmin": "Sta paggena è stata scancellata.\n'O mutivo d' 'o scancellamiento 'o truvate scritto dint' 'a 'o riepilego ccà abbascio, nzieme ch' 'e dettaglie 'e l'utente c'hanno cagnato sta paggena apprimma 'e se fà 'o scancellamiento.\n'O testo 'e mo 'e sti verziune è disponibbele sulamente a l'ammenistrature.",
+       "undelete-revision": "Verziune scancellata 'a $1 (comme 'e $4, a $5) 'a $3:",
+       "undeleterevision-missing": "Verziona invalida o mancante.\nPutisseve avé nu cullegamiento sbagliato o 'a verzione, può darse, ca fosse arrepigliata o scancellata 'e l'archivio.",
+       "undelete-nodiff": "Nun s'è truvata nisciuna verzione 'e primma.",
+       "undeletebtn": "Arrepiglia",
+       "undeletelink": "vide/arrepiglia",
        "undeleteviewlink": "vere",
+       "undeleteinvert": "Abbarruca 'a sceveta",
+       "undeletecomment": "Mutivo:",
+       "undeletedrevisions": "{{PLURAL:$1|1 verzione|$1 verziune}} arrepigliate",
+       "undeletedrevisions-files": "{{PLURAL:$1|1 verzione|$1 verziune}} e {{PLURAL:$2|1 file|$2 file}} arrepigliate",
+       "undeletedfiles": "{{PLURAL:$1|1 file arrepigliato|$1 file arrepigliate}}",
+       "cannotundelete": "Arrepiglio fallito:\n$1",
+       "undeletedpage": "'''$1 è stat'arrepigliato'''\n\nLiggiete 'o [[Special:Log/delete|riggistro 'e scancellamiente]] pe n'avé n'elenco 'e l'urdeme scancellamiente e arrepiglie.",
+       "undelete-header": "Vedite [[Special:Log/delete|'o riggistro 'e scancellamiente]] pe l'urdeme paggene scancellate",
+       "undelete-search-title": "Ascìa dint' 'e paggene scancellate",
+       "undelete-search-box": "Ascìa dint' 'e paggene scancellate",
+       "undelete-search-prefix": "Fà vedè 'e paggene c'accumencieno cu:",
+       "undelete-search-submit": "Truova",
+       "undelete-no-results": "Nun ce stanno paggene asciate ca se truvassero dint' 'o riggistro 'e scancellamiento.",
+       "undelete-filename-mismatch": "Nun se può arrepiglià 'a verzione d' 'o file cu l'orario $1: nomme d' 'o file errato",
+       "undelete-bad-store-key": "Nun se può arrepiglià 'a verzione d' 'o file cu orario $1: 'o file è stato sperduto apprimma d' 'o scancellamiento.",
+       "undelete-cleanup-error": "Errore scancellanno n'archivio 'e file nun ausate \"$1\".",
+       "undelete-missing-filearchive": "Non se può arrepiglià l'archivie cu l'ID $1 pecché nun ce stanno dint' 'o database.\nPò darse ca songo già state arrepigliate.",
+       "undelete-error": "Errore quanno s'arrepigliava na paggena",
+       "undelete-error-short": "Errore quanno s'arrepigliava na paggena: $1",
+       "undelete-error-long": "Errore quanno s'arrepigliava na paggena:\n\n$1",
+       "undelete-show-file-confirm": "Site sicuro/a ca vulite veré 'a verziona scancellata d' 'o file \"<nowiki>$1</nowiki>\" d' 'o $2 a 'e $3?",
+       "undelete-show-file-submit": "Sì",
        "namespace": "Namespace:",
        "invert": "abbarruca 'a sceveta",
+       "tooltip-invert": "Nzegna sta casciulella p'annaconnere 'e cagnamiente a 'e paggene ca stanno dint' 'o namespace c'avite scigliuto (e 'o namespace stesso si l'avite scigliuto)",
+       "namespace_association": "Namespace associate",
+       "tooltip-namespace_association": "Nzegna sta casciulella pe ncludere 'e cchiacchiere o l'oggetto d' 'o namespace associato c' 'o namespace scigliuto",
        "blanknamespace": "(Prencepale)",
        "contributions": "Contribbute {{GENDER:$1|utente}}",
+       "contributions-title": "Cuntribbute 'a l'utente pe' $1",
        "mycontris": "'E ffatiche d''e mmeje",
        "contribsub2": "Ppe {{GENDER:$3|$1}} ($2)",
+       "contributions-userdoesnotexist": "'O cunto utente \"$1\" nun è riggistrato.",
+       "nocontribs": "Nisciunu cagnamiento è stato truvato cu sti criterie.",
        "uctop": "(attuale)",
        "month": "D\"o mese (e primma):",
        "year": "'E ll'anno (e primma):",
        "sp-contributions-newbies": "Mosta solo 'e contribbute dde nove utente",
+       "sp-contributions-newbies-sub": "Pe' l'utente nuove",
+       "sp-contributions-newbies-title": "Contribbute 'a l'utente nuove",
        "sp-contributions-blocklog": "blocche",
        "sp-contributions-suppresslog": "contribbute utente scancellate",
+       "sp-contributions-deleted": "contribbute d'utente scancellate",
+       "sp-contributions-uploads": "carreche",
        "sp-contributions-logs": "registre",
        "sp-contributions-talk": "Chiàcchiera",
+       "sp-contributions-userrights": "gestione d' 'e permesse 'e l'utente",
+       "sp-contributions-blocked-notice": "St'utente è bloccato mò.\nL'urdemo elemento d' 'o riggistro 'e blocche è ripurtato ccà abbascio p'avé nu riferimento:",
+       "sp-contributions-blocked-notice-anon": "St'IP è bloccato mò.\nL'urdemo elemento d' 'o riggistro 'e blocche è ripurtato ccà abbascio p'avé nu riferimento:",
+       "sp-contributions-search": "Ascìa 'e contribbute",
        "sp-contributions-username": "Nnerizzo IP o nomme utente",
+       "sp-contributions-toponly": "Facenno vedé sulamente 'e contribbute 'e l'urdeme verziune",
+       "sp-contributions-newonly": "Facenno vedé sulamente 'e contribbute ca songo criazione 'e paggene",
        "sp-contributions-submit": "Truova",
        "whatlinkshere": "Paggene ca cullegano a chesta",
        "whatlinkshere-title": "Paggene ca cullegano a $1",
        "whatlinkshere-page": "Paggena:",
-       "nolinkshere": "Nisciuna paggena cuntene jonte ca mpuntano a '''[[:$1]]'''.",
+       "linkshere": "'E paggene ccà abbascio cunteneno jonte ca spuntano a '''[[:$1]]'''.",
+       "nolinkshere": "Nisciuna paggena cuntene jonte ca spuntasse a <strong>[[:$1]]</strong>.",
+       "nolinkshere-ns": "Nun ce stanno paggene ca spuntassero '''[[:$1]]''' dint' 'o namespace scigliuto.",
        "isredirect": "redirect a paggena",
        "istemplate": "'nclusione",
        "isimage": "Cullegamente a file multimediale",
+       "whatlinkshere-prev": "{{PLURAL:$1|apprima|apprime $1}}",
+       "whatlinkshere-next": "{{PLURAL:$1|appriesso|$1 appriesso}}",
        "whatlinkshere-links": "← jonte",
        "whatlinkshere-hideredirs": "$1 redirects",
        "whatlinkshere-hidetrans": "$1 'nclusione",
        "whatlinkshere-hidelinks": "$1 jonte",
        "whatlinkshere-hideimages": "$1 links ddo file",
        "whatlinkshere-filters": "Filtre",
-       "blockip": "Ferma utelizzatóre",
+       "autoblockid": "Autoblocco #$1",
+       "block": "Blocca l'utente",
+       "unblock": "Sblocca l'utente",
+       "blockip": "Blocca {{GENDER:$1|utente}}",
+       "blockip-legend": "Blocca l'utente",
+       "blockiptext": "Ausa 'o modulo ccà abbascio pe' bluccà l'acciesso 'e scrittura a n'indirizzo IP o utente.\nChisto s'avesse 'a ffà sulamente pe' se pruteggere d' 'o vandalismo, d'accordo ch' [[{{MediaWiki:Policy-url}}|'e reole]].\nMettite pure nu mutivo specifico ccà abbascio (p'esempio, facenno 'o nomme 'e paggene addò se so' fatte 'e vandalisme).",
        "ipaddressorusername": "Nnerizzo IP o nomme utente",
+       "ipbexpiry": "Ammatura:",
+       "ipbreason": "Mutivo:",
+       "ipbreason-dropdown": "* Mutive comune pe' ffà 'o blocco\n** Steva nzertanno nfurmaziune fauze\n** Steva a luvà cuntenute d' 'e paggene\n** Steva a fà spam 'e cullegamiente a 'e site 'e fore\n** Steva a nzertà robbe senza senso dint' 'e paggene\n** Minacce e ntimidaziune\n** Abbuso 'e cunte utente multiple\n** Nomme utente inaccettabbele",
+       "ipb-hardblock": "Nun permettere 'o cagnamiento a l'utente riggistrate ca veneno 'a st'indirizzo IP",
+       "ipbcreateaccount": "Nun fà crià 'o cunto",
+       "ipbemailban": "Blocca utente a mannà e-mail",
+       "ipbenableautoblock": "Automaticamende blocca l'urdeme indirizze IP ausate 'a st'utente, e pure tutte l'IP c'ausasse pe' pruvà 'e fà ati cagnamiente",
+       "ipbsubmit": "Blocca st'utente",
+       "ipbother": "N'ata durata:",
        "ipboptions": "2 ore:2 hours,1 juorno:1 day,3 juorne:3 days,1 semmana:1 week,2 semmane:2 weeks,1 mise:1 month,3 mese:3 months,6 mese:6 months,1 anno:1 year,infinito:infinite",
+       "ipbhidename": "Annascunne 'o nomme utente d' 'a lista 'e cagnamiente e l'ati liste",
+       "ipbwatchuser": "Fà vedé 'a paggena utente e le chiacchieriate 'e st'utente",
+       "ipb-disableusertalk": "Nun permettere a st'utente edità 'a paggena 'e chiacchiera d' 'a soja pe' tramente ch'e bloccato",
+       "ipb-change-block": "Blocca n'ata vota l'utente cu sti mpustaziune",
+       "ipb-confirm": "Cunferma 'o blocco",
+       "badipaddress": "Indirizzo IP nun valido",
        "blockipsuccesssub": "Blocco aseguito",
+       "blockipsuccesstext": "[[Special:Contributions/$1|$1]] è stato bloccato.<br />\nVedite [[Special:BlockList|'a lista 'e l'IP bloccate]] pe' fà vedé n'ata vota 'e blocche.",
+       "ipb-blockingself": "Vuje ve state a bluccà da solo! Site sicuro ca 'o vulite fà?",
+       "ipb-confirmhideuser": "State a bluccà n'utente cu l'opzione \"annascunne utente\" appicciata. St'operazione può luvà 'o nomme 'e l'utente a dint' 'a tutte l'elenche e riggistre. Site sicuro/a ca vulite fà chesto?",
+       "ipb-confirmaction": "Si site sicuro 'e fa chesto overo, cuntrullate 'o campo \"{{int:ipb-confirm}}\" ccà abbascio.",
+       "ipb-edit-dropdown": "Cagna 'e mutive d' 'o blocco",
+       "ipb-unblock-addr": "Sblocca $1",
+       "ipb-unblock": "Sblocca nomme utente o indirizzo IP",
+       "ipb-blocklist": "Fà vedé 'e blocche ch'esisteno",
+       "ipb-blocklist-contribs": "Contribbute 'e {{GENDER:$1|$1}}",
+       "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",
+       "unblocked": "[[User:$1|$1]] è stato sbloccato.",
+       "unblocked-range": "$1 è stato sbloccato",
+       "unblocked-id": "'O blocco $1 è stato luvato.",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] è stato sbluccato.",
+       "blocklist": "Utente bloccate",
        "ipblocklist": "Utenti bloccate",
+       "ipblocklist-legend": "Ascìa n'utente bloccato",
+       "blocklist-userblocks": "Annascunne 'e blocche 'e l'utente riggistrate",
+       "blocklist-tempblocks": "Annascunne 'e blocche temporanee",
+       "blocklist-addressblocks": "Annascunne 'e blocche 'e n'IP sola",
+       "blocklist-rangeblocks": "Annascunne 'e ntervalle 'e blocche",
+       "blocklist-timestamp": "Data e ora",
+       "blocklist-target": "Destinazione",
+       "blocklist-expiry": "Ammatura",
+       "blocklist-by": "Ammenistratore ca 'o bluccaje",
+       "blocklist-params": "Parametre d' 'o blocco",
+       "blocklist-reason": "Mutivo",
+       "ipblocklist-submit": "Ascìa",
+       "ipblocklist-localblock": "Blocco lucale",
+       "ipblocklist-otherblocks": "Ati {{PLURAL:$1|blocche|blocche}}",
+       "infiniteblock": "indefinito",
+       "expiringblock": "ammatura 'o $1 a 'e $2",
+       "anononlyblock": "sulamente l'anonime",
+       "noautoblockblock": "autoblocco stutato",
+       "createaccountblock": "riggistrazione 'e cunte stutata",
+       "emailblock": "mmasciate e-mail stutate",
+       "blocklist-nousertalk": "nun può cagnà 'a paggena 'e chiacchiera d' 'a soja",
+       "ipblocklist-empty": "'A lista 'e blocche è abbacante.",
+       "ipblocklist-no-results": "L'indirizzo IP o nomme utente c'asciate nun songo bloccate.",
        "blocklink": "ferma",
        "unblocklink": "sblocca",
        "change-blocklink": "càgna blocco",
        "contribslink": "contribuzzione",
+       "emaillink": "manna e-mail",
+       "autoblocker": "Autobloccate pecché l'indirizze IP vuosto è stat'ausato urdemamente 'a \"[[User:$1|$1]]\".\n'O mutivo d' 'o blocco 'e $1 è \"$2\"",
        "blocklogpage": "Blocche",
+       "blocklog-showlog": "St'utente è stato bloccato primma.\n'O riggistro d' 'e blocche se può vedé ccà abbascio pe' riferimento:",
+       "blocklog-showsuppresslog": "St'utente è stato bloccato e annascunuto primma.\n'O riggistro d' 'e luvamiente se può vedé ccà abbascio pe' riferimento:",
        "blocklogentry": "ha fermato \"[[$1]]\" pe' nu mumento 'e $2 $3",
+       "reblock-logentry": "cagnate 'e mpustaziune 'e blocco pe' [[$1]] cu na data d'ammaturamiento 'e $2 $3",
        "blocklogtext": "Chesta è 'a lista d''e azzione 'e blocco e sblocco utente.  'E nnerizze IP bloccate automaticamente nun nce so'. Addumannà 'a [[Special:BlockList|lista bloccate]] pp' 'a lista d''e nnerizze e nomme utente 'o ca blocco nce sta.",
+       "unblocklogentry": "sbluccato $1",
+       "block-log-flags-anononly": "sulamente l'utente anonime",
+       "block-log-flags-nocreate": "riggistrazione 'e cunte stutata",
+       "block-log-flags-noautoblock": "autoblocco stutato",
+       "block-log-flags-noemail": "mmasciate e-mail stutate",
+       "block-log-flags-nousertalk": "nun può cagnà 'a paggena 'e chiacchiera d' 'a toja",
+       "block-log-flags-angry-autoblock": "auto blocco avanzato appicciato",
+       "block-log-flags-hiddenname": "nomme utente annascunnuto",
+       "range_block_disabled": "'A possibbilità 'e bluccà ntervalle 'e indirizze IP nun è appicciata.",
+       "ipb_expiry_invalid": "Tiempo d'ammaturamiento invalido.",
+       "ipb_expiry_temp": "'E blocche d' 'e nomme utente annascunnute hanna essere nfinite.",
+       "ipb_hide_invalid": "Nun se può scancellà stu cunto; tène cchiù 'e {{PLURAL:$1|nu cagnamiento|$1 cagnamiente}}.",
+       "ipb_already_blocked": "\"$1\" è già bloccato.",
+       "ipb-needreblock": "$1 è già bloccato. Vulite cagnà 'e mpustaziune?",
+       "ipb-otherblocks-header": "Ati {{PLURAL:$1|blocche|blocche}}",
+       "unblock-hideuser": "Vuje nun putite sbluccà st'utente, pecché 'o nomme utente 'e chisto è stato già annascunnuto.",
+       "ipb_cant_unblock": "Errore: L'ID $1 d' 'o blocco nun se trova.\nPò essere ca 'o blocco è stato luvato già.",
+       "ipb_blocked_as_range": "Errore: l'IP $1 nun è stato bloccato direttamente e nun se può sbluccà.\n'O blocco, è mmece attivo a livello 'e l'intervallo $2, ca pò essere sbloccato.",
+       "ip_range_invalid": "L'itervallo 'e l'IP nun è valido.",
+       "ip_range_toolarge": "L'intervalle 'e blocche cchiù luonghe 'e /$1 nun songo permesse.",
+       "proxyblocker": "Bloccatore 'e proxy",
+       "proxyblockreason": "L'indirizzo IP d' 'o vuosto è stato bloccato pecché è nu proxy araputo.\nPe' piacere, cuntattate 'o provider 'e l'Internet vuosto o lu suppuorto tecnico d' 'aggenzia vuosta pe' le dà nutizia 'e stu probblema gruosso assaje.",
+       "sorbsreason": "L'indirizzo IP vuosto è elencato comm'a nu proxy araputo dint' 'a lista DNSBL ausata 'a {{SITENAME}}.",
+       "sorbs_create_account_reason": "L'indirizzo IP d' 'o vuosto è elencato comm'a nu proxy araputo dint' 'a DNSBL ausata 'a {{SITENAME}}. Nun putite crià nu cunto.",
+       "xffblockreason": "N'indirizzo IP prisente dint' 'e cap'e paggena X-Forwarded-For, o chillu d' 'o vuosto o chillu 'e n'atu server proxy ca stat'ausann, è stato bloccato. 'O mutivo origgenale 'e blocco era: $1",
+       "cant-see-hidden-user": "L'utente ca state a bluccà è stato già bluccato e annascunnuto. Si nun tenite 'o deritto ''hideuser'', nun putite veré stu blocco d'utente.",
+       "ipbblocked": "Nun putite bloccà o sbluccà utente pecche vuje stesso site bluccato.",
+       "ipbnounblockself": "Nun avite permesso a ve bluccà vuje stesso.",
+       "lockdb": "Blocca 'o database",
+       "unlockdb": "Sblocca 'o database",
+       "lockdbtext": "Bluccanno 'o database se luvarranno l'abbilità 'e tutte l'utente 'e cagnà 'e paggene, cagnà 'e preferenze lloro, cagnà 'a lista 'e paggene cuntrullate e ati cose ca richiedessero cagnamiente ô database.\nPe' piacere cunfermate ca chisto e chello ca vulite fà, e ca luvarrate 'o blocco ô database quanno sta manutenziona sarrà fernuta.",
+       "unlockdbtext": "Sbluccanno 'o database se s'arrepigliarranno l'abbilità 'e tutte l'utente 'e cagnà 'e paggene, cagnà 'e preferenze lloro, cagnà 'a lista 'e paggene cuntrullate e ati cose ca richiedessero cagnamiente ô database.\nPe' piacere cunfermate ca chisto e chello ca vulite fà.",
+       "lockconfirm": "Sì, overo vulesse bluccà 'o database.",
+       "unlockconfirm": "Sì, overo vulesse sbluccà 'o database.",
+       "lockbtn": "Blocca 'o database",
+       "unlockbtn": "Sblocca 'o database",
+       "locknoconfirm": "Nun avite scigliuto 'a casciulella 'e cunferma.",
+       "lockdbsuccesssub": "Blocco d' 'o database secutato",
+       "unlockdbsuccesssub": "'O blocco d' 'o database è stato luvato",
+       "lockdbsuccesstext": "'O database è stato bloccato.<br />\nArricuordateve 'e [[Special:UnlockDB|luvà 'o blocco]] appriesso c' 'a manutenziona sarrà fernuta.",
+       "unlockdbsuccesstext": "'O database è stato sbluccato.",
+       "lockfilenotwritable": "Nun se può scrivere ncopp' 'o file 'e blocco d' 'o database.\nPe' bluccà o sbluccà 'o database abbesuogne 'e scrivere dint' 'o server web.",
+       "databasenotlocked": "'O database nun è bluccato.",
+       "lockedbyandtime": "(pe' {{GENDER:$1|$1}} 'o $2 a 'e $3)",
+       "move-page": "Mòve $1",
+       "move-page-legend": "Mòve paggena",
+       "movepagetext": "Ausanno stu modulo ccà abbascio s'anommenarrà 'a paggena n'ata vota, movenno tutt' 'a cronologgia suja a l'atu nomme.\n'O titolo viecchio s'addeventarrà nu redirect â paggena c' 'o titolo nuovo. Putite agghiurnà 'e redirect ca puntassero ô titolo origgenale automaticamente.\nSi chesto nun facite, state sicuro 'e cuntrullà [[Special:DoubleRedirects|doppie ridirezionamiente]] o [[Special:BrokenRedirects|ridirezionamiente scassate]]. Vuje site 'o responsabbile 'e chillo ca cumbinate, assicurateve ca 'o cullegamiento cuntinua a spuntà addò avess'a spuntà.\n\nVedite bbuono ca 'a paggena <strong>nun</strong> se muoverrà si esiste n'ata paggena c' 'o titolo nuovo, a meno ca è abbacante o ca ce sta na paggena 'e ridirezionamiento senza cronologgia. Chesto significasse ca putite fà turnà 'o nomme viecchio â paggena addò ce steva apprimma si avite cumbinato nu nguacchio p'errore, e nun può sovrascrivere 'a paggena ch'esiste già. <strong>Attenzione!</strong> Chisto può essere nu cagnamiento drastico e inaspettato 'e na paggena famosa assaje; pe' piacere, avite 'a essere sicure-sicure d' 'e conseguenze apprimm' 'e cuntinuà.",
+       "movepagetext-noredirectfixer": "Ausanno stu modulo ccà abbascio s'anommenarrà 'a paggena n'ata vota, movenno tutt' 'a cronologgia suja a l'atu nomme.\n'O titolo viecchio s'addeventarrà nu redirect â paggena c' 'o titolo nuovo. State sicuro 'e cuntrullà [[Special:DoubleRedirects|doppie ridirezionamiente]] o [[Special:BrokenRedirects|ridirezionamiente scassate]]. Vuje site 'o responsabbile 'e chillo ca cumbinate, assicurateve ca 'o cullegamiento cuntinua a spuntà addò avess'a spuntà.\n\nVedite bbuono ca 'a paggena <strong>nun</strong> se muoverrà si esiste n'ata paggena c' 'o titolo nuovo, a meno ca è abbacante o ca ce sta na paggena 'e ridirezionamiento senza cronologgia. Chesto significasse ca putite fà turnà 'o nomme viecchio â paggena addò ce steva apprimma si avite cumbinato nu nguacchio p'errore, e nun può sovrascrivere 'a paggena ch'esiste già. <strong>Attenzione!</strong> Chisto può essere nu cagnamiento drastico e inaspettato 'e na paggena famosa assaje; pe' piacere, avite 'a essere sicure-sicure d' 'e conseguenze apprimm' 'e cuntinuà.",
+       "movepagetalktext": "'A paggena 'e chiacchieria suoccia a chesta sarrà spustata automaticamente cu chesta <strong>a meno che:</strong>\n*Esiste na paggena 'e chiacchieria ca nun è abbacante c' 'o nomme nuovo, o\n*Vuje sciglite accussì abbacantanno 'a casciulella ccà abbascio.\n\nInd' 'a sti case, 'a paggena nun se muoverrà, ma 'a putite sempe scagnà manualmente si vulite.",
        "movearticle": "Spusta 'a paggena",
+       "moveuserpage-warning": "<strong>Attenziò:</strong> Vuje state a muovere na paggena utente. Vedite bbuono ca sulamente 'a paggena sarrà spustata e l'utente <em>nun</em> sarrà reanummenato.",
+       "movecategorypage-warning": "<strong>Attenziò:</strong> Vuje state a muovere na categurìa. Vedite bbuono ca sulamente 'a paggena sarrà spustata e 'a categurìa viecchia <em>nun</em> sarrà cagnata â nnova.",
+       "movenologintext": "Vuje avite 'a essere n'utente riggistrato e [[Special:UserLogin|cullegato]] pe' spustà na paggena.",
+       "movenotallowed": "Nun tenite 'o permesso pe' spustà paggene.",
+       "movenotallowedfile": "Nun tenite 'o permesso pe' spustà file.",
+       "cant-move-user-page": "Nun tenite 'o permesso pe' spustà 'e paggene utente (staccannole cumme sottopàggene).",
+       "cant-move-to-user-page": "Nun tenite 'o permesso pe' spustà na paggena 'a na paggena utente (sulamente p' 'e sottopaggene utente).",
+       "cant-move-category-page": "Nun tenite 'o permesso pe' muovere paggene 'e categurìa.",
+       "cant-move-to-category-page": "Nun tenite 'o permesso pe' muovere 'a paggena ncopp' 'a na categurìa",
        "newtitle": "Titulo nuovo:",
+       "move-watch": "Cuntrolla sta paggena",
        "movepagebtn": "Spusta 'a paggena",
+       "pagemovedsub": "Spustamento fatto",
+       "movepage-moved": "<strong>\"$1\" è stata spustata int' 'a \"$2\"</strong>",
+       "movepage-moved-redirect": "Nu redirezionamiento è stato criato.",
+       "movepage-moved-noredirect": "'A criazione o lu redirezionamiento è stato luvato.",
        "articleexists": "Na paggena cu chisto nomme asiste già, o pure 'o nomme scegliuto nun è buono.  Scegliere n'ato titulo.",
+       "cantmove-titleprotected": "Nun putite spustà 'a paggena a stu pizzo pecchè 'o titolo nuovo è stato prutetto 'a criazione",
+       "movetalk": "Muove 'a paggena 'e chiacchiera suoccia a chesta",
+       "move-subpages": "Mòve 'e sottopàggene (nfin' 'a $1)",
+       "move-talk-subpages": "Mòve 'e sottopaggene 'e chiacchiera (nfin' 'a $1)",
+       "movepage-page-exists": "'A paggena $1 esiste già e nun se può scrivere ncoppa.",
+       "movepage-page-moved": "'A paggena $1 s'è spustat' 'a $2.",
+       "movepage-page-unmoved": "'A paggena $1 nun se può spustà a $2.",
+       "movepage-max-pages": "'O massimo 'e $1 {{PLURAL:$1|paggena|paggene}} è stato spustato e nun se ne ponno spustà cchiù 'n automatico.",
        "movelogpage": "Spustamente",
+       "movelogpagetext": "Ccà abbascio sta na lista d' 'e paggene spustate.",
+       "movesubpage": "{{PLURAL:$1|Sottopaggena|Sottopaggene}}",
+       "movesubpagetext": "Sta paggena tene $1 {{PLURAL:$1|sottopaggena|sottopaggene}} ccà abbascio.",
+       "movenosubpage": "Sta paggena nun tene sottopaggene.",
        "movereason": "Raggióne",
-       "revertmove": "ripristina",
+       "revertmove": "arrepiglia",
        "delete_and_move": "Scancèlla e spusta",
+       "delete_and_move_text": "== Scancellamiento richiesto ==\n'A paggena 'e destinazione \"[[:$1]]\" esiste già.\n'A vulite scancellà pe' ne putè ffà 'o spazio abbacante necessario?",
        "delete_and_move_confirm": "Sì, suprascrivi 'a paggena asistente",
+       "delete_and_move_reason": "Scancellata pe ne fà spazio abbacante e putè spustà 'a \"[[$1]]\"",
+       "selfmove": "'O titolo 'e sorgente e destinazione songh' 'e stesse;\nnun se può muovere na paggena ncopp' 'a essa stessa.",
+       "immobile-source-namespace": "Nun se ponno muovere 'e paggene dint' 'o namespace \"$1\"",
+       "immobile-target-namespace": "Nun se ponno muovere 'e paggene dint' 'o namespace \"$1\"",
+       "immobile-target-namespace-iw": "'O cullegamiento interwiki nun è na destinazione bona pe spustà na paggena.",
+       "immobile-source-page": "Sta paggena nun se può spustà.",
+       "immobile-target-page": "Nun se può spustà a chillu titolo 'e destinazione.",
+       "bad-target-model": "'A destinazione scigliuta aùsa nu mudello 'e cuntenute differénte. Nun se può cagnà 'a $1 a $2.",
+       "imagenocrossnamespace": "Nun se può muovere stu file dint' 'a nu namespace nun-file",
+       "nonfile-cannot-move-to-file": "Nun se può muovere n'oggetto ca nun è nu file a dint'o namespace d' 'e file",
+       "imagetypemismatch": "L'estenziona nova d' 'o file nun s'accucchia c' 'o tipo suojo",
+       "imageinvalidfilename": "'O nomme d' 'o file 'e destinazione nun è buono",
+       "fix-double-redirects": "Agghiuorna ogne redirezionamiento ca spuntasse ô titolo origginale",
+       "move-leave-redirect": "Lassa nu ridirezionamiento arreto",
+       "protectedpagemovewarning": "<strong>Attenziò:</strong> sta paggena è stata prutetta 'n modo tale ca sulamente l'utente ch' 'e privilegge d'ammenistratore 'a ponno muovere.\nL'urdemo elemento d' 'o riggistro è scritto ccà abbascio pe' n'avé riferimento:",
+       "semiprotectedpagemovewarning": "'''Nota:''' Sta paggena è prutetta 'n modo ca sulamente l'utente riggistrate 'a ponno mòvere.\nL'urdemo elemento d' 'o riggistro è scritto ccà abbascio pe n'avé nfurmazione:",
+       "move-over-sharedrepo": "== 'O file esiste ==\n[[:$1]] esiste ncopp'a l'archivio spartuto. Spustanno 'o file ncopp'a stu titolo sovrascreverrà 'o file spartuto.",
+       "file-exists-sharedrepo": "'O nomme d' 'o file c'avite scigliuto se sta ausanno dint'a l'archivio spartuto.\nPe' piacere, scigliete n'atu nomme.",
        "export": "Spurta 'e ppaggene",
+       "exporttext": "Vuje putite espurtà 'e teste e cagnà 'a cronologgia 'e na paggena particolare o n'inzieme 'e paggena ca stessero dint' 'a cocche XML.\nChisto po' essere 'mpurtato int'a n'ata wiki ausanno [[Special:Import|mporta pàggene]] 'e MediaWiki.\n\nPe' spurtà paggene, mettite 'o titolo dint' 'e casciulelle ccà abbascio, nu titolo pe' linea e sciglite si vulite 'a verziona 'e mò cu tutt' 'e verziun' 'assieme, o pùre sulamente 'a verziona 'e mò c' 'a nfurmaziona ncopp' 'a ll'urdemo cagnamiento.\n\nComme urtema possibbiletà, putite pure ausà nu cullegamento, p'esempio [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] p' 'a pàggena \"[[{{MediaWiki:Mainpage}}]]\".",
+       "exportall": "Spurta tutt' 'e paggene",
+       "exportcuronly": "Appenne sulamente 'a verziona 'e mo, e nun tutt' 'a cronologgia",
+       "exportnohistory": "----\n'''Vedite bbuono:''' 'A funzione 'esportazione d' 'a storia sana d' 'e paggene, ausanno stu modulo, è stata stutata pe' mutive 'e prestaziune.",
+       "exportlistauthors": "Appenne 'a lista sana 'e cuntribbutore p'ogne paggena",
+       "export-submit": "Esporta",
+       "export-addcattext": "Azzecca paggene d' 'a categurìa:",
+       "export-addcat": "Azzecca",
+       "export-addnstext": "Azzecca paggene d' 'o namespace:",
+       "export-addns": "Azzecca",
+       "export-download": "Astipa comm'a nu file",
+       "export-templates": "Include 'e template",
+       "export-pagelinks": "Include 'e paggene cullegate ca spuntassero nfin' 'a na prufunnità 'e:",
        "allmessages": "'Mmasciate d''o sistema",
        "allmessagesname": "Nomme",
+       "allmessagesdefault": "Mmasciata 'e testo predefinita",
        "allmessagescurrent": "Testo 'e mo",
+       "allmessagestext": "Chest'è na lista 'e tutt' 'e mmasciate 'e sistema ca se ponno ascià dint' 'o namespace 'e Mediawiki.\nPe' piacere vedite [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Lucalizzazione 'e MediaWiki] e [//translatewiki.net translatewiki.net] si vulite cuntribbuì â lucalizzaziona generica 'e MediaWiki.",
+       "allmessagesnotsupportedDB": "Sta paggena nun se può ausà pecché 'a funziona <strong>$wgUseDatabaseMessages</strong> è stata stutata.",
+       "allmessages-filter-legend": "Filtro",
+       "allmessages-filter": "Filtra cu nu stato personalizzate:",
+       "allmessages-filter-unmodified": "Senza cagnamiente",
+       "allmessages-filter-all": "Tutto",
+       "allmessages-filter-modified": "Cagnate",
+       "allmessages-prefix": "Filtra pe' prefisso:",
+       "allmessages-language": "Lengua:",
+       "allmessages-filter-submit": "Vàje",
+       "allmessages-filter-translate": "Traduce",
        "thumbnail-more": "Ingrandisce",
+       "filemissing": "File perdute",
+       "thumbnail_error": "Errore crianno l'anteprimma 'e miniatura: $1",
+       "thumbnail_error_remote": "Mmasciata d'errore 'a $1:\n$2",
+       "djvu_page_error": "Pàggena DjVu fore 'e lemmeto",
+       "djvu_no_xml": "Nun se può piglià 'o XML p' 'o file DjVu",
+       "thumbnail-temp-create": "Nun se può crià na miniatura temporanea d' 'o file",
+       "thumbnail-dest-create": "Nun se può astipà 'a miniatura dint' 'a destinazione",
+       "thumbnail_invalid_params": "Parametre 'e miniatura invalide",
+       "thumbnail_dest_directory": "Nun se può crià 'a cartella 'e destinazione",
+       "thumbnail_image-type": "'O tipo d'immaggene nun è suppurtato",
+       "thumbnail_gd-library": "Configurazione d' 'a libbreria GD incompleta: funziona perza $1",
+       "thumbnail_image-missing": "'O file pare ca nun se trova: $1",
+       "thumbnail_image-failure-limit": "Se so' fatte troppe tentative senza ngarrata ($1 o cchiù) 'a generà sta miniatura. Pruvate n'ata vota cchiù tarde.",
        "import": "Mpurta paggene",
+       "importinterwiki": "Mpurtazione transkwiki",
+       "import-interwiki-text": "Scigliete na wiki e nu titolo 'e paggena 'a mpurtà.\n'E date e l'editore s'astiparranno.\nTutte l'aziune 'e mpurtaziune nfra 'e wiki songo riggistrate dint' 'e [[Special:Log/import|riggistre 'e mpurtazione]].",
+       "import-interwiki-sourcewiki": "Wiki d'origgene:",
+       "import-interwiki-sourcepage": "Paggena d'origgene:",
+       "import-interwiki-history": "Copia tutt' 'a storia d' 'e verziune 'e sta paggena",
+       "import-interwiki-templates": "Include tutt' 'e template",
        "import-interwiki-submit": "Mpurta",
+       "import-interwiki-namespace": "Namespace 'e destinazione:",
+       "import-interwiki-rootpage": "Paggena princepale 'e destinazione (opzionale):",
+       "import-upload-filename": "Nomme d' 'o file",
+       "import-comment": "Commento:",
+       "importtext": "Pe' piacere spurtate 'o file d' 'a wiki surgente ausanno l'[[Special:Export|utilità 'e sportazione]].\nScarrecatevella dint' 'o computer d' 'o vuosto e carrecate n'ata vota ccà.",
+       "importstart": "Mpurtanno 'e paggene...",
+       "import-revision-count": "$1 {{PLURAL:$1|verzione|verziune}}",
+       "importnopages": "Nisciuna pàggene 'a mpurtà.",
+       "imported-log-entries": "Mpurtate $1 {{PLURAL:$1|evento d' 'o riggistro|evente d' 'o riggistro}}.",
+       "importfailed": "Mpurtaziona fallita: <nowiki>$1</nowiki>",
+       "importunknownsource": "Nun se sape 'o tipo 'e sorgente 'e mpurtaziona",
+       "importcantopen": "Nun se può arapì 'o file 'e mpurtaziona",
+       "importbadinterwiki": "Cullegamiento interwiki errato",
+       "importsuccess": "Mpurtaziona fernuta!",
+       "importnosources": "Nisciuna fonte p' 'a mpurtaziona transwiki è stata definita; 'e carreche dirette 'e cronologgia nun songo attivate.",
+       "importnofile": "Nisciunu file 'e mpurtazione è stato carrecato.",
+       "importuploaderrorsize": "'A carreca d' 'o file 'e mpurtazione nun è riuscita.\n'O file è cchiù gruosso d' 'a dimenziona massima 'e carreca.",
+       "importuploaderrorpartial": "'A carreca d' 'o file mpurtato è fallita.\nNa parta d' 'o file file è stata carrecata ma nun a nu piezzo sano sano.",
        "import-logentry-upload": "ha mpurtato [[$1]] trammeto upload",
        "tooltip-pt-userpage": "A toja paggena utente",
        "tooltip-pt-mytalk": "A toja paggena 'e discussione",
index 2aea667..1867460 100644 (file)
@@ -57,6 +57,7 @@
        "tog-watchdefault": "Legg til sider og filer jeg endrer på i min overvåkingsliste",
        "tog-watchmoves": "Legg til sider og filer jeg flytter til min overvåkingsliste",
        "tog-watchdeletion": "Legg til sider og filer jeg sletter i min overvåkingsliste",
+       "tog-watchrollback": "Legg til sider jeg har utført tilbakestilling på i min overvåkningsliste",
        "tog-minordefault": "Merk i utgangspunktet alle redigeringer som mindre",
        "tog-previewontop": "Vis forhåndsvisningen over redigeringsboksen",
        "tog-previewonfirst": "Vis forhåndsvisning når du begynner å redigere",
        "talkpagelinktext": "diskusjon",
        "specialpage": "Spesialside",
        "personaltools": "Personlige verktøy",
-       "postcomment": "Ny seksjon",
        "articlepage": "Vis innholdsside",
        "talk": "Diskusjon",
        "views": "Visninger",
        "hidetoc": "skjul",
        "collapsible-collapse": "skjul",
        "collapsible-expand": "vis",
+       "confirmable-confirm": "Er {{GENDER:$1|du}} sikker?",
+       "confirmable-yes": "Ja",
+       "confirmable-no": "Nei",
        "thisisdeleted": "Se eller gjenopprett $1?",
        "viewdeleted": "Vis $1?",
        "restorelink": "{{PLURAL:$1|én slettet revisjon|$1 slettede revisjoner}}",
        "invalidtitle-knownnamespace": "Ugyldig tittel med navnerommet «$2» og teksten «$3»",
        "invalidtitle-unknownnamespace": "Ugyldig tittel med ukjent navneromsnummer $1 og teksten «$2»",
        "exception-nologin": "Ikke innlogget",
-       "exception-nologin-text": "[[Special:Userlogin|Logg inn]] for å kunne se siden eller utføre denne handlingen.",
+       "exception-nologin-text": "Logg inn for å kunne se siden eller utføre denne handlingen.",
        "exception-nologin-text-manual": "Du må $1 for å få tilgang til denne siden eller handlingen.",
        "virus-badscanner": "Feilkonfigurasjon: Ukjent virusskanner: ''$1''",
        "virus-scanfailed": "skanning mislyktes (kode $1)",
        "externaldberror": "Det var en ekstern autentifiseringsfeil, eller du kan ikke oppdatere din eksterne konto.",
        "login": "Logg inn",
        "nav-login-createaccount": "Logg inn eller opprett en konto",
-       "loginprompt": "Du må ha slått på informasjonskapsler for å logge in på {{SITENAME}}.",
        "userlogin": "Logg inn eller opprett en konto",
        "userloginnocreate": "Logg inn",
        "logout": "Logg ut",
        "userlogin-resetlink": "Har du glemt påloggingsdetaljene dine?",
        "userlogin-resetpassword-link": "Glemt passordet?",
        "userlogin-helplink2": "Hjelp med innlogging",
-       "userlogin-loggedin": "Du er allerede logget inn som {{GENDER:$1|$1}}.\nBruk skjemaet nedenfor for å logge inn som en annen bruker.",
-       "userlogin-createanother": "Opprett ny konto",
        "createacct-emailrequired": "E-postadresse",
        "createacct-emailoptional": "E-postadresse (valgfritt)",
        "createacct-email-ph": "Skriv inn e-postadressen din",
        "preview": "Forhåndsvisning",
        "showpreview": "Forhåndsvisning",
        "showdiff": "Vis endringer",
+       "blankarticle": "<strong>Advarsel:</strong> Siden du er i ferd med å opprette er tom.\nHvis du trykker \"{{int:savearticle}}\" en gang til, vil siden opprettes uten innhold.",
        "anoneditwarning": "'''Advarsel:''' Du er ikke logget inn.\nIP-adressen din blir bevart i sidens redigeringshistorikk.",
        "anonpreviewwarning": "''Du er ikke logget inn. Lagring vil registrere din IP-adresse i sidens redigeringshistorikk.''",
        "missingsummary": "'''Påminnelse:''' Du har ikke lagt inn en redigeringsforklaring.\nVelger du ''Lagre siden'' en gang til blir endringene lagret uten forklaring.",
        "protectedpagewarning": "'''Advarsel: Denne siden har blitt låst slik at kun brukere med administratorrettigheter kan redigere den.'''\nDet siste loggelementet er oppgitt under som referanse:",
        "semiprotectedpagewarning": "'''Merk:''' Denne siden har blitt låst slik at kun registrerte brukere kan endre den.\nDet siste loggelementet er oppgitt under som referanse:",
        "cascadeprotectedwarning": "'''Advarsel:''' Denne siden har blitt låst slik at kun brukere med administratorrettigheter kan redigere den, fordi den inkluderes på følgende dypbeskyttede {{PLURAL:$1|sider}}:",
-       "titleprotectedwarning": "'''Advarsel: Denne siden har blitt låst slik at [[Special:ListGroupRights|spesielle rettigheter]] kreves for å opprette den.'''\nDet siste loggelementet er oppgitt under som referanse:",
+       "titleprotectedwarning": "'''Advarsel: Denne siden har blitt låst slik at [[Special:ListGroupRights|bestemte rettigheter]] kreves for å opprette den.'''\nTil orientering vises den siste loggoppføringen under:",
        "templatesused": "{{PLURAL:$1|Mal|Maler}} som brukes på denne siden:",
        "templatesusedpreview": "{{PLURAL:$1|Mal|Maler}} brukt i denne forhåndsvisningen:",
        "templatesusedsection": "{{PLURAL:$1|Mal|Maler}} brukt i denne seksjonen:",
        "sectioneditnotsupported-text": "Seksjonsredigering støttes ikke på denne siden.",
        "permissionserrors": "Rettighetsfeil",
        "permissionserrorstext": "Du har ikke tillatelse til å utføre dette, av følgende {{PLURAL:$1|grunn|grunner}}:",
-       "permissionserrorstext-withaction": "Du har ikke tillatelse til å $2 {{PLURAL:$1|på grunn av|av følgende grunner}}:",
+       "permissionserrorstext-withaction": "Du har ikke tillatelse til å $2 {{PLURAL:$1|fordi|av følgende grunner}}:",
        "recreate-moveddeleted-warn": "Advarsel: Du er i ferd med å opprette en side som tidligere har blitt slettet.'''\n\nDu bør vurdere om det er passende å fortsette å redigere denne siden.\nSlette- og flytteloggen for denne siden gjengis her:",
        "moveddeleted-notice": "Denne siden har blitt slettet.\nSlette- og flytteloggen vises nedenfor.",
        "log-fulllog": "Vis hele loggen",
        "parser-template-recursion-depth-warning": "Mal er brukt for mange ganger ($1)",
        "language-converter-depth-warning": "Dybdegrense for språkkonvertering overskredet ($1)",
        "node-count-exceeded-category": "Sider hvor antallet noder er overskredet",
-       "node-count-exceeded-category-desc": "En kategori for sider der antallet noder er overskredet.",
-       "node-count-exceeded-warning": "Siden har overskredet antallet noder",
+       "node-count-exceeded-category-desc": "Siden overskriver maksimalt nodeantall.",
+       "node-count-exceeded-warning": "Siden overskred nodeantallet",
        "expansion-depth-exceeded-category": "Sider hvor ekspansjonsdybden er overskredet",
-       "expansion-depth-exceeded-category-desc": "Dette er en kategori for sider hvor ekspansjonsdybden er overskredet.",
+       "expansion-depth-exceeded-category-desc": "Siden overskrider maksimal utvidingsdybde.",
        "expansion-depth-exceeded-warning": "Sida har overskredet ekspansjonsdybden",
        "parser-unstrip-loop-warning": "«Unstrip»-loop påvist",
        "parser-unstrip-recursion-limit": "Rekursjonsgrense for taggfjerning overskredet ($1)",
        "rev-deleted-event": "(fjernet loggoppføring)",
        "rev-deleted-user-contribs": "[brukernavn eller IP-adresse fjernet – redigeringen vises ikke blant bidragene]",
        "rev-deleted-text-permission": "Denne revisjonen har blitt '''slettet'''.\nDet kan være detaljer i [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} slettingsloggen].",
+       "rev-suppressed-text-permission": "Denne siderevisjonen har blitt <strong>skjult</strong>.\nDetaljer finnes i [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} skjulingsloggen].",
        "rev-deleted-text-unhide": "Denne siderevisjonen har blitt '''slettet'''.\nSe etter detaljer i slettingsloggen: [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}}].\nDu kan fortsatt [$1 se revisjonen] om du ønsker det.",
        "rev-suppressed-text-unhide": "Denne siderevisjonen har blitt '''skjult'''.\nInformasjon om dette kan finnes i [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} skjulingsloggen].\nDu kan fortsatt [$1 se revisjonen] om du ønsker det.",
        "rev-deleted-text-view": "Denne siderevisjonen har blitt '''slettet'''.\nDu kan fortsatt se den; detaljer finnes i [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} slettingsloggen].",
        "revdelete-text-text": "Slettede revisjoner vil fortsatt finnes i sidens historikk, men deler av deres innhold vil være utilgjengelige for offentligheten.",
        "revdelete-text-file": "Slettede filversjoner vil fortsatt finnes i filhistorikken, men deler av deres innhold vil være utilgjengelige for offentligheten.",
        "logdelete-text": "Slettede hendelser i loggen vil fortsatt finnes i loggene, men deler av deres innhold vil være utilgjengelige for offentligheten.",
-       "revdelete-text-others": "Andre administratorer på {{SITENAME}} vil fortsatt ha tilgang til det skjulte innholdet og kan rulle det tilbake igjen via det samme grensesnittet, hvis ikke ytterligere begrensinger er satt.",
+       "revdelete-text-others": "Andre administratorer vil fortsatt ha tilgang til det skjulte innholdet og kan hente det frem igjen, hvis ikke ytterligere begrensinger er satt.",
        "revdelete-confirm": "Bekreft at du ønsker å gjøre dette, at du forstår konsekvensene, og at du gjør det i samsvar med [[{{MediaWiki:Policy-url}}|retningslinjene]].",
        "revdelete-suppress-text": "Skjuling bør '''kun''' brukes i følgende tilfeller:\n* Mulig injurierende utsagn\n* Følsomme personlige opplysninger\n*: ''privatadresser og -telefonnumre, fødselsnumre og lignende''",
        "revdelete-legend": "Fastsett synlighetsbegrensninger",
        "mergehistory-empty": "Ingen revisjoner kan flettes.",
        "mergehistory-success": "{{PLURAL:$3|Én revisjon|$3 revisjoner}} av [[:$1]] ble flettet til [[:$2]].",
        "mergehistory-fail": "Klarte ikke å utføre historikkfletting; sjekk siden og tidsparameterne igjen.",
+       "mergehistory-fail-toobig": "Det er ikke mulig å utføre historikk-fletting fordi flere enn tillatte $1 {{PLURAL:$1|revisjon|revisjoner}} ville blitt flyttet.",
        "mergehistory-no-source": "Kildesiden $1 finnes ikke.",
        "mergehistory-no-destination": "Målsiden $1 finnes ikke.",
        "mergehistory-invalid-source": "Kildesiden må ha en gyldig tittel.",
        "showhideselectedversions": "Vis/skjul valgte versjoner",
        "editundo": "fjern",
        "diff-empty": "(Ingen forskjell)",
-       "diff-multi-sameuser": "({{PLURAL:$1|En midlertidig revisjon|$1 midlertidige revisjoner}} av samme bruker vises ikke)",
-       "diff-multi-otherusers": "({{PLURAL:$1|En midlertidig revisjon|$1 midlertidige revisjoner}} av {{PLURAL:$2|en annen bruker|$2 brukere}} er ikke vist)",
+       "diff-multi-sameuser": "({{PLURAL:$1|En mellomliggende revisjon|$1 mellomliggende revisjoner}} av samme bruker vises ikke)",
+       "diff-multi-otherusers": "({{PLURAL:$1|En mellomliggende revisjon|$1 mellomliggende revisjoner}} av {{PLURAL:$2|en annen bruker|$2 brukere}} er ikke vist)",
        "diff-multi-manyusers": "({{PLURAL:$1|Én mellomrevisjon|$1 mellomrevisjoner}} av mer enn $2 {{PLURAL:$2|bruker|brukere}} vises ikke)",
        "difference-missing-revision": "{{PLURAL:$2|En revisjon|$2 revisjoner}} av denne forskjellen ($1) {{PLURAL:$2|ble|ble}} ikke funnet.\n\nDette skyldes som regel at en gammel forskjell-lenke er fulgt til en side som er slettet.\nDetaljer kan finnes i [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} sletteloggen].",
        "searchresults": "Søkeresultater",
        "searchprofile-advanced-tooltip": "Søk i visse navnerom",
        "search-result-size": "$1 ({{PLURAL:$2|ett|$2}} ord)",
        "search-result-category-size": "{{PLURAL:$1|1 medlem|$1 medlemmer}} ({{PLURAL:$2|1 underkategori|$2 underkategorier}}, {{PLURAL:$3|1 fil|$3 filer}})",
-       "search-result-score": "Relevans: $1&nbsp;%",
        "search-redirect": "(omdirigering $1)",
        "search-section": "(avsnitt $1)",
        "search-file-match": "(matcher filinnhold)",
        "searchall": "alle",
        "showingresults": "Nedenfor vises opptil {{PLURAL:$1|'''ett''' resultat|'''$1''' resultater}} fra og med nummer <b>$2</b>.",
        "showingresultsinrange": "Nedenfor vises opptil {{PLURAL:$1|<strong>1</strong> resultat|<strong>$1</strong> resulter}} i området #<strong>$2</strong> til #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Resultat '''$1''' av '''$3'''|Resultat '''$1 - $2''' av '''$3'''}} for '''$4'''",
        "search-nonefound": "Ingen resultater passet til søket.",
        "powersearch-legend": "Avansert søk",
        "powersearch-ns": "Søk i navnerom:",
        "preferences": "Innstillinger",
        "mypreferences": "Innstillinger",
        "prefs-edits": "Antall redigeringer:",
-       "prefsnologintext2": "Vennligst $1 å endre dine preferanser.",
+       "prefsnologintext2": "Logg inn for å endre innstillingene dine.",
        "prefs-skin": "Utseende",
        "skin-preview": "Forhåndsvisning",
        "datedefault": "Ingen foretrukket",
        "right-deletedtext": "Vise slettet tekst og endringer mellom slettede versjoner",
        "right-browsearchive": "Søke i slettede sider",
        "right-undelete": "Gjenopprette sider",
-       "right-suppressrevision": "Se og gjenopprette skjulte siderevisjoner",
+       "right-suppressrevision": "Se på, skjul og hent frem igjen spesifikke siderevisjoner for alle brukere",
+       "right-viewsuppressed": "Se på revisjoner som er skjult for alle brukere",
        "right-suppressionlog": "Se private logger",
        "right-block": "Blokkere andre brukere fra å redigere",
        "right-blockemail": "Blokkere brukere fra å sende e-post",
        "recentchanges-label-minor": "Dette er en mindre endring",
        "recentchanges-label-bot": "Denne redigeringen ble gjort av en bot",
        "recentchanges-label-unpatrolled": "Denne redigeringen har ikke blitt patruljert ennå",
-       "recentchanges-label-plusminus": "Sidestørrelsen kan endres med dette antallet bytes",
+       "recentchanges-label-plusminus": "Sidestørrelsen er endra med dette antallet byte",
        "recentchanges-legend-heading": "'''Tegnforklaring:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (se også [[Special:NewPages|liste av nye sider]])",
        "recentchanges-legend-plusminus": "«(±123)»",
-       "rcnotefrom": "Nedenfor er endringene gjort siden <strong>$2</strong> (frem til <strong>$1</strong> vises).",
+       "rcnotefrom": "Nedenfor er vist {{PLURAL:$5|endringen|endringene}} som er gjort siden <strong>$3, $4</strong> (frem til <strong>$1</strong>).",
        "rclistfrom": "Vis nye endringer fra og med $3 $2",
        "rcshowhideminor": "$1 mindre endringer",
        "rcshowhideminor-show": "Vis",
        "uploadwarning": "Opplastingsadvarsel",
        "uploadwarning-text": "Vennligst endre filbeskrivelsen nedenfor og prøv igjen.",
        "savefile": "Lagre fil",
-       "uploadedimage": "lastet opp «[[$1]]»",
-       "overwroteimage": "last opp en ny versjon av «[[$1]]»",
        "uploaddisabled": "Opplastingsfunksjonen er slått av",
        "copyuploaddisabled": "Opplasting via nettadresse deaktivert.",
        "uploaddisabledtext": "Opplasting er slått av.",
        "license": "Lisens:",
        "license-header": "Lisensiering",
        "nolicense": "Ingen spesifisert",
+       "licenses-edit": "Rediger lisensvalg",
        "license-nopreview": "(Forhåndsvisning ikke tilgjengelig)",
-       "upload_source_url": " (en gyldig, offentlig tilgjengelig adresse)",
-       "upload_source_file": " (en fil på din datamaskin)",
+       "upload_source_url": "(din fil fra en gyldig, offentlig tilgjengelig adresse)",
+       "upload_source_file": "(en fil på din datamaskin)",
+       "listfiles-delete": "slett",
        "listfiles-summary": "Denne spesialsiden viser alle opplastede filer.",
        "listfiles_search_for": "Søk etter filnavn:",
        "imgfile": "fil",
        "randomincategory": "Tilfeldig side innenfor kategorien",
        "randomincategory-invalidcategory": "«$1» er ikke et gyldig kategorinavn.",
        "randomincategory-nopages": "Det finnes ingen sider i [[:Category:$1|$1]]-kategorien.",
-       "randomincategory-selectcategory": "Hent en tilfeldig side fra kategori: $1 $2.",
-       "randomincategory-selectcategory-submit": "Start",
+       "randomincategory-category": "Kategori:",
+       "randomincategory-legend": "Tilfeldig side i kategori",
        "randomredirect": "Tilfeldig omdirigering",
        "randomredirect-nopages": "Det er ingen omdirigeringer i navnerommet $1.",
        "statistics": "Statistikk",
        "wantedpages-badtitle": "Ugyldig tittel i resultatene: $1",
        "wantedfiles": "Ønskede filer",
        "wantedfiletext-cat": "Følgende filer refereres, men eksisterer ikke. Filer fra fremmede samlinger kan listes selv om de ikke finnes. Alle slik falske treff vil <del>strykes</del>. I tillegg er sider som har innebygde, ikke-eksisterende filer listet opp i [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Følgende filer er i bruk, men finnes ikke. I tillegg er sider som inkluderer ikke-eksisterende filer gitt i [[:$1]].",
        "wantedfiletext-nocat": "Følgende filer er referert, men eksisterer ikke. Filer fra fremmede samlinger kan være opplistet selv om de ikke finnes. Alle slike falske referanser vil bli <del>fjernet</del>.",
+       "wantedfiletext-nocat-noforeign": "Følgende filer er i bruk, men finnes ikke.",
        "wantedtemplates": "Etterspurte maler",
        "mostlinked": "Sider med flest lenker til seg",
        "mostlinkedcategories": "Kategorier med flest sider",
        "trackingcategories-desc": "Kategori-inklusjonskriterium",
        "noindex-category-desc": "Denne siden indekseres ikke av roboter fordi den er merket med det magiske ordet <code><nowiki>__NOINDEX__</nowiki></code> og er i navnerom der dette flagget tillates.",
        "index-category-desc": "Denne siden er påført det magiske ordet <code><nowiki>__INDEX__</nowiki></code> (og er i et navnerom hvor flagget er tillatt), og vil derfor bli indeksert av roboter selv når det normalt ikke ville skjedd.",
-       "post-expand-template-inclusion-category-desc": "Etter ekspandering av alle malene ble siden større enn <code>$wgMaxArticleSize</code>, så noen maler kunne ikke ekspanderes.",
-       "post-expand-template-argument-category-desc": "Etter ekspandering av et malargument (noe i trippel krøllparentes, slik som <code>{{{Foo}}})</code>, så er siden større en <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "For mange kostbare parserfunksjoner (som <code>#ifexist</code>) er inkludert på en side. Se [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Kategorien blir lagt til hvis siden inneholder en brutt fil-lenke (en lenke for å bygge inn en fil når filen selv ikke eksisterer).",
-       "hidden-category-category-desc": "Dette er en kategori merket med <code><nowiki>__HIDDENCAT__</nowiki></code>, som hindrer den fra å vises i siders kategorioversikt som standard.",
+       "post-expand-template-inclusion-category-desc": "Sidestørrelsen er større enn <code>$wgMaxArticleSize</code> etter at alle maler er utvidet, så noen maler ble ikke utvidet.",
+       "post-expand-template-argument-category-desc": "Siden er større enn <code>$wgMaxArticleSize</code> etter utvidelse av et malargument (noe i tre krøllparenteser, som <code>{{{foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "Siden bruker for mange dyre parserfunksjoner (som <code>#ifexist</code>). Se [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "Siden inneholder en ødelagt lenkefil (en lenke for å bygge inn en fil når filen ikke eksisterer).",
+       "hidden-category-category-desc": "Kategorien inneholder <code><nowiki>__HIDDENCAT__</code></nowiki> i sideinnholdet, hvilket gjør at den som standard ikke vises i kategorilisten på sider.",
        "trackingcategories-nodesc": "Ingen beskrivelse er tilgjengelig",
        "trackingcategories-disabled": "Kategorien er deaktivert",
        "mailnologin": "Ingen avsenderadresse",
        "mailnologintext": "Du må være [[Special:UserLogin|logget inn]] og ha en gyldig e-postadresse satt i [[Special:Preferences|brukerinnstillingene]] for å sende e-post til andre brukere.",
        "emailuser": "E-post til denne brukeren",
-       "emailuser-title-target": "Send epost til denne {{GENDER:$1|brukeren}}",
+       "emailuser-title-target": "Send e-post til denne {{GENDER:$1|brukeren}}",
        "emailuser-title-notarget": "E-post til bruker",
        "emailpage": "E-post til bruker",
        "emailpagetext": "Du kan bruke skjemaet under for å sende en e-post til denne {{GENDER:$1|brukeren}}.\nE-postadressen du har satt i [[Special:Preferences|innstillingene dine]] vil vises i «Fra»-feltet i e-posten, slik at mottakeren kan svare deg direkte.",
        "mywatchlist": "Overvåkningsliste",
        "watchlistfor2": "For $1 $2",
        "nowatchlist": "Du har ingenting i overvåkningslisten.",
-       "watchlistanontext": "Vennligst $1 for å vise eller redigere sider på overvåkningslisten din.",
+       "watchlistanontext": "Logg inn for å vise eller redigere elementer på overvåkningslisten din.",
        "watchnologin": "Ikke logget inn",
        "addwatch": "Legg til i overvåkningslisten",
        "addedwatchtext": "Siden «[[:$1]]» er lagt til [[Special:Watchlist|overvåkningslisten]] din.\nFremtidige endringer til denne siden og den tilhørende diskusjonssiden blir listet opp der.",
        "unwatchthispage": "Fjerner overvåkning",
        "notanarticle": "Ikke en artikkel",
        "notvisiblerev": "Revisjonen er slettet",
-       "watchlist-details": "{{PLURAL:$1|Én side|$1 sider}} på din overvåkningsliste, teller ikke diskusjonssider.",
+       "watchlist-details": "Du har {{PLURAL:$1|én side|'''$1''' sider}} på [[Hjelp:Overvåke sider|overvåkningslisten]] din (pluss tilhørende [[Hjelp:Diskusjonsside|diskusjonssider]]).",
        "wlheader-enotif": "E-postvarsling er slått på.",
-       "wlheader-showupdated": "Sider som har blitt forandret siden du sist besøkte dem vises i '''fet tekst'''",
-       "wlnote2": "Nedenfor er endringene {{PLURAL:$1|den siste timen|de siste <strong>$1</strong> timene}}, per $2 $3.",
+       "wlheader-showupdated": "Sider som har blitt endret siden du besøkte dem sist vises med '''fet skrift'''.",
+       "wlnote": "Nedenfor er {{PLURAL:$1|den siste endringen|de siste <strong>$1</strong> endringene}} {{PLURAL:$2|den siste timen|de siste <strong>$2</strong> timene}}, per $3 kl. $4",
        "wlshowlast": "Vis siste $1 timer $2 dager $3",
        "watchlist-options": "Alternativ for overvåkningslisten",
        "watching": "Overvåker…",
        "exbeforeblank": "innholdet før siden ble tømt var: «$1»",
        "delete-confirm": "Slett «$1»",
        "delete-legend": "Slett",
-       "historywarning": "Advarsel: Siden du er i ferd med å slette har en historikk med omtrent {{PLURAL:$1|én revisjon|$1 revisjoner}}:",
+       "historywarning": "<strong>Advarsel:</strong> Siden du er i ferd med å slete har en historikk med $1 {{PLURAL:$1|revisjon|revisjoner}}:",
        "confirmdeletetext": "Du holder på å slette en side sammen med historikken.\nBekreft at du virkelig vil slette denne siden, at du forstår konsekvensene og at du gjør det i samsvar med [[{{MediaWiki:Policy-url}}|retningslinjene]].",
        "actioncomplete": "Gjennomført",
        "actionfailed": "Handling mislyktes",
        "delete-edit-reasonlist": "Rediger begrunnelser for sletting",
        "delete-toobig": "Denne siden har en stor redigeringshistorikk, med over {{PLURAL:$1|$1&nbsp;revisjon|$1&nbsp;revisjoner}}. Muligheten til å slette slike sider er begrenset for å unngå utilsiktet forstyrring av {{SITENAME}}.",
        "delete-warning-toobig": "Denne siden har en stor redigeringshistorikk, med over {{PLURAL:$1|$1&nbsp;revisjon|$1&nbsp;revisjoner}}. Sletting av denne siden kan forstyrre databasen til {{SITENAME}}; vær varsom.",
+       "deleteprotected": "Du kan ikke slette denne siden fordi den er beskyttet.",
        "deleting-backlinks-warning": "'''Advarsel:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Andre sider]] lenker til eller inkluderer siden du er i ferd med å slette.",
        "rollback": "Fjern redigeringer",
        "rollback_short": "Tilbakestill",
        "autoblockid": "Autoblokker #$1",
        "block": "Blokker bruker",
        "unblock": "Fjern blokkering av bruker",
-       "blockip": "Blokker bruker",
+       "blockip": "Blokker {{GENDER:$1|bruker}}",
        "blockip-legend": "Blokker bruker",
        "blockiptext": "Bruk skjemaet under for å blokkere en IP-adresses tilgang til å redigere artikler. Dette må kun gjøres for å forhindre hærverk, og i overensstemmelse med [[{{MediaWiki:Policy-url}}|retningslinjene]]. Fyll ut en spesiell begrunnelse under.",
        "ipaddressorusername": "IP-adresse eller brukernavn",
        "ipb-unblock-addr": "Avblokker $1",
        "ipb-unblock": "Avblokker et brukernavn eller en IP-adresse",
        "ipb-blocklist": "Vis gjeldende blokkeringer",
-       "ipb-blocklist-contribs": "Bidrag fra $1",
+       "ipb-blocklist-contribs": "Bidrag fra {{GENDER:$1|$1}}",
        "unblockip": "Opphev blokkering",
        "unblockiptext": "Bruk skjemaet under for å gjenopprette skriveadgangen for en tidligere blokkert adresse eller bruker.",
        "ipusubmit": "Opphev blokkering",
        "import": "Importer sider",
        "importinterwiki": "Transwiki-importering",
        "import-interwiki-text": "Velg en wiki og en side å importere. Revisjonsdatoer og bidragsyteres navn blir bevart. Alle transwiki-importeringer listes i [[Special:Log/import|importloggen]].",
-       "import-interwiki-source": "Kildewiki/side:",
+       "import-interwiki-sourcewiki": "Kildewiki:",
+       "import-interwiki-sourcepage": "Kildeside:",
        "import-interwiki-history": "Kopier all historikk for denne siden",
        "import-interwiki-templates": "Inkluder alle maler",
        "import-interwiki-submit": "Importer",
        "import-upload": "Last opp XML-data",
        "import-token-mismatch": "Sesjonsdata mistet. Venligst prøv igjen.",
        "import-invalid-interwiki": "Kan ikke importere fra angitt wiki.",
-       "import-error-edit": "Siden «$1» ble ikke importert siden du ikke har tillatelse til å redigere den.",
-       "import-error-create": "Siden «$1» ble ikke importert siden du ikke har tillatelse til å opprette den.",
-       "import-error-interwiki": "Siden «$1» ble ikke importert fordi navnet er reservert for ekstern lenking (interwiki).",
-       "import-error-special": "Siden «$1» ble ikke importert fordi den tilhører et spesialnavnerom som ikke tillater sider.",
-       "import-error-invalid": "Siden «$1» ble ikke importert fordi navnet er ugyldig.",
+       "import-error-edit": "Siden «$1» ble ikke importert fordi du ikke har tillatelse til å redigere den.",
+       "import-error-create": "Siden «$1» ble ikke importert fordi du ikke har tillatelse til å opprette den.",
+       "import-error-interwiki": "Siden «$1» ble ikke importert fordi dette navnet er reservert for ekstern lenking (interwiki).",
+       "import-error-special": "Siden «$1» ble ikke importert fordi dette navnet tilhører et spesialnavnerom som ikke tillater sider.",
+       "import-error-invalid": "Siden «$1» ble ikke importert fordi sidenavnet er ugyldig på denne wikien.",
        "import-error-unserialize": "Revisjon $2 av siden «$1» kunne ikke serialiseres. Det ble rapportert at revisjonen bruker innholdsmodellen $3 serialisert som $4.",
        "import-error-bad-location": "Revisjon $2 som bruker innholdsmodell $3 kan ikke lagres til \"$1\" på denne wikien siden denne modellen ikke støttes på den siden.",
        "import-options-wrong": "Feil {{PLURAL:$2|opsjon|opsjoner}}: <nowiki>$1</nowiki>",
        "importlogpage": "Importlogg",
        "importlogpagetext": "Administrativ import av sider med redigeringshistorikk fra andre wikier.",
        "import-logentry-upload": "importerte [[$1]] ved opplasting",
-       "import-logentry-upload-detail": "Importerte {{PLURAL:$1|én revisjon|$1 revisjoner}}",
+       "import-logentry-upload-detail": "{{PLURAL:$1|\\Én revisjon|$1 revisjoner}} er importert",
        "import-logentry-interwiki": "transwikiimporterte $1",
-       "import-logentry-interwiki-detail": "{{PLURAL:$1|Én revisjon|$1 revisjoner}} fra $2",
+       "import-logentry-interwiki-detail": "{{PLURAL:$1|Én revisjon|$1 revisjoner}} er importert fra $2",
        "javascripttest": "JavaScript-testing",
        "javascripttest-title": "Kjører $1 tester",
        "javascripttest-pagetext-noframework": "Denne siden er reservert for å kjøre JavaScript-tester.",
        "autosumm-replace": "Erstatter siden med «$1»",
        "autoredircomment": "Omdirigerer til [[$1]]",
        "autosumm-new": "Ny side: $1",
+       "autosumm-newblank": "Opprettet tom side",
        "lag-warn-normal": "Endringer nyere enn $1 {{PLURAL:$1|sekund|sekunder}} vises muligens ikke i denne listen.",
        "lag-warn-high": "På grunn av stor databaseforsinkelse, vil ikke endringer som er nyere enn $1 {{PLURAL:$1|sekund|sekunder}} vises i denne listen.",
        "watchlistedit-normal-title": "Rediger overvåkningsliste",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|diskusjon]])",
        "unknown_extension_tag": "Ukjent tilleggsmerking «$1»",
        "duplicate-defaultsort": "Advarsel: Standardsorteringen «$2» tar over for den tidligere sorteringen «$1».",
+       "duplicate-displaytitle": "<strong>Advarsel:</strong> Visningstittel \"$2\" erstatter tidligere visningstittel \"$1\".",
        "version": "Versjon",
        "version-extensions": "Installerte utvidelser",
-       "version-skins": "Drakter",
+       "version-skins": "Installerte drakter",
        "version-specialpages": "Spesialsider",
        "version-parserhooks": "Parsertillegg",
        "version-variables": "Variabler",
        "version-hook-name": "Navn",
        "version-hook-subscribedby": "Brukes av",
        "version-version": "(versjon $1)",
+       "version-no-ext-name": "[uten navn]",
        "version-license": "Lisens",
        "version-ext-license": "Lisens",
        "version-ext-colheader-name": "Utvidelse",
+       "version-skin-colheader-name": "Drakt",
        "version-ext-colheader-version": "Versjon",
        "version-ext-colheader-license": "Lisens",
        "version-ext-colheader-description": "Beskrivelse",
        "logentry-rights-rights": "$1 {{GENDER:$2|endret}} gruppemedlemskap for $3 fra $4 til $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|endret}} gruppemedlemskap for $3",
        "logentry-rights-autopromote": "$1 ble automatisk {{GENDER:$2|forfremmet}} fra $4 til $5",
+       "logentry-upload-upload": "$1 {{GENDER:$2|lastet opp}} $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|lastet opp}} en ny versjon av $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|lastet opp}} $3",
        "rightsnone": "(ingen)",
        "feedback-bugornote": "Hvis du er klar til å sende inn en detaljert feilrapport, vennligst [$1 rapporter en feil].\nOm det ikke er tilfellet, kan du bruke det enkle skjemaet som du finner under. Kommentaren din vil bli lagt til siden \"[$3 $2]\", sammen med brukernavnet ditt og informasjon om hvilken nettleser du bruker.",
        "feedback-subject": "Emne:",
        "expand_templates_remove_nowiki": "Ikke vis <nowiki>-merkelapper i resultatet",
        "expand_templates_generate_xml": "Vis parsetre som XML",
        "expand_templates_generate_rawhtml": "Vis ubehandlet HTML",
-       "expand_templates_preview": "Forhåndsvisning"
+       "expand_templates_preview": "Forhåndsvisning",
+       "pagelanguage": "Valg av sidespråk",
+       "pagelang-name": "Side",
+       "pagelang-language": "Språk",
+       "pagelang-use-default": "Bruk standardspråk",
+       "pagelang-select-lang": "Velg språk",
+       "right-pagelang": "Endre sidespråk",
+       "action-pagelang": "endre sidespråket",
+       "log-name-pagelang": "Endre språklogg",
+       "log-description-pagelang": "Dette er en logg som viser endringer i sidespråk",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|endret}} sidespråk for $3 fra $4 til $5.",
+       "default-skin-not-found": "Ops! Standarddrakten for wikien din (<code>$wgDefaultSkin</code>), <code>$1</code>, er ikke tilgjengelig.\n\nInstallasjonen din ser ut til å inneholde følgende drakter. Se [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Skin configuration] for informasjon om hvordan du kan slå disse på eller heller velge en standarddrakt.\n\n$2\n\n; Om du nettopp har installert MediaWiki:\n: Du har trolig installert fra git, eller direkte fra kildekoden med en annen metode. Dette er forventet. Prøv å installere noen drakter fra [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org sin draktbase] ved å\n:* laste ned [https://www.mediawiki.org/wiki/Download tarball-installereren], som kommer med flere drakter og utvidelser. Du kan kopiere og lime inn <code>skins/</code>-mappen fra denne.\n:* klone en av <code>mediawiki/skins/*</code>-lagrene via git inn i <code>skins/</code> -mappen av din MediaWiki-installasjon.\n: Å gjøre dette skal ikke forstyrre git-mappen din om du er en MediaWiki-utvikler.\n\n; Om du nettopp har oppgradert MediaWiki:\n: MediaWiki 1.24 og nyere slår ikke lenger på automatisk installerte drakter (se [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: Skin autodiscovery]). Du kan lime inn følgende linjer i <code>LocalSettings.php</code> for å slå på alle installerte drakter:\n\n<pre>$3</pre>\n\n; Om du nettopp har endret <code>LocalSettings.php</code>:\n: Dobbelsjekk draktnavnene for skrivefeil.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (slått på)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''slått av''')"
 }
index d3c08bb..63be861 100644 (file)
        "talkpagelinktext": "Overleg",
        "specialpage": "Spesiale zied",
        "personaltools": "Persoonlike instellingen",
-       "postcomment": "Niej onderwarp",
        "articlepage": "Artikel",
        "talk": "Overleg",
        "views": "Weergaven",
        "hidetoc": "Verbarg",
        "collapsible-collapse": "Inklappen",
        "collapsible-expand": "Uutklappen",
+       "confirmable-confirm": "{{GENDER:$1|Bi'j}} daor wisse van?",
+       "confirmable-yes": "Ja",
+       "confirmable-no": "Nee",
        "thisisdeleted": "Bekieken of herstellen van $1?",
        "viewdeleted": "Bekiek $1?",
        "restorelink": "{{PLURAL:$1|versie die vortedaon is|versies die vortedaon bin}}",
        "invalidtitle-knownnamespace": "Ongeldige titel mit naamruumte \"$2\" en tekste \"$3\"",
        "invalidtitle-unknownnamespace": "Ongeldige titel mit onbekend naamruumtenummer $1 en tekste \"$2\"",
        "exception-nologin": "Niet an-emeld",
-       "exception-nologin-text": "Um disse zied te bekieken of disse haandeling uut te kunnen voeren mu'j an-emeld ween bie disse wiki.",
+       "exception-nologin-text": "Um disse zied te bekieken of disse haandeling uut te kunnen voeren mu'j [[Special:Userlogin|an-emeld]] ween bie disse wiki.",
        "virus-badscanner": "Slichte konfigurasie: onbekend antivirusprogramma: ''$1''",
        "virus-scanfailed": "inlezen is mislokt (kode $1)",
        "virus-unknownscanner": "onbekend antivirusprogramma:",
        "externaldberror": "Der gung iets fout bie de externe authentisering, of je maggen je gebrukersprofiel niet bewarken.",
        "login": "Anmelden",
        "nav-login-createaccount": "Anmelden",
-       "loginprompt": "Je mutten scheumbestaanden (cookies) an hebben staon um an te kunnen melden bie {{SITENAME}}.",
        "userlogin": "Anmelden / inschrieven",
        "userloginnocreate": "Anmelden",
        "logout": "Aofmelden",
        "gotaccountlink": "Anmelden",
        "userlogin-resetlink": "Bi'j de anmeldgegevens kwiet?",
        "userlogin-resetpassword-link": "Joew wachtwoord vergeten?",
+       "userlogin-helplink2": "Hulpe bie t anmelden",
        "userlogin-loggedin": "Je bin al an-emeld as {{GENDER:$1|$1}}.\nGebruuk t onderstaonde formulier um an te melden as n aandere gebruker.",
        "userlogin-createanother": "n Aandere gebrukerskonto anmaken",
        "createacct-emailrequired": "Netpostadres",
        "searchprofile-advanced-tooltip": "Zeuken in de an-egeven naamruumtes",
        "search-result-size": "$1 ({{PLURAL:$2|1 woord|$2 woorden}})",
        "search-result-category-size": "{{PLURAL:$1|1 kategorielid|$1 kategorielejen}} ({{PLURAL:$2|1 onderkategorie|$2 onderkategorieën}}, {{PLURAL:$3|1 bestaand|$3 bestaanden}})",
-       "search-result-score": "Relevansie: $1%",
        "search-redirect": "(deurverwiezing $1)",
        "search-section": "(onderwarp $1)",
        "search-suggest": "Bedoelden je: $1",
        "uploadwarning": "Waorschuwing",
        "uploadwarning-text": "Pas de bestaandsbeschrieving hieronder an en probeer t opniej",
        "savefile": "Bestaand opslaon",
-       "uploadedimage": "Op-estuurd: [[$1]]",
-       "overwroteimage": "Nieje versie van \"[[$1]]\" op-estuurd",
        "uploaddisabled": "t Opsturen van bestaanden is uutezet.",
        "copyuploaddisabled": "t Opsturen van bestaanden via n webadres is uutezet.",
        "uploaddisabledtext": "t Opsturen van bestaanden is uutezet.",
        "watchlist-details": "Der {{PLURAL:$1|steet één zied|staon $1 ziejen}} op joew volglieste, zonder de overlegziejen mee-erekend.",
        "wlheader-enotif": "Je kriegen bericht per netpost",
        "wlheader-showupdated": "Ziejen die sinds joew leste bezeuk bie-ewörken bin, staon '''vet-edrokt'''.",
+       "wlnote": "Hieronder {{PLURAL:$1|steet de leste wieziging|staon de leste $1 wiezigingen}} in {{PLURAL:$2|t aofgeleupen ure|de leste $2 uren}} vanaof $3 um $4.",
        "wlshowlast": "Laot de veurbieje $1 uur $2 dagen $3 zien",
        "watchlist-options": "Opsies veur de volglieste",
        "watching": "Volg...",
index 8811cd0..109f0ff 100644 (file)
        "talkpagelinktext": "Diskuschoon",
        "specialpage": "Spezialsiet",
        "personaltools": "Persönliche Warktüüch",
-       "postcomment": "Afsnidd tofögen",
        "articlepage": "Artikel",
        "talk": "Diskuschoon",
        "views": "Ansichten",
        "externaldberror": "Dat geev en Fehler bi de externe Authentifizerungsdatenbank oder du dröffst dien extern Brukerkonto nich ännern.",
        "login": "Anmellen",
        "nav-login-createaccount": "Nee Konto anleggen oder anmellen",
-       "loginprompt": "Dat du di bi {{SITENAME}} anmellen kannst, musst du Cookies anstellt hebben.",
        "userlogin": "Nee Konto anleggen oder anmellen",
        "userloginnocreate": "Anmellen",
        "logout": "Afmellen",
        "searchprofile-advanced-tooltip": "Söök in angevene Naamrüüm",
        "search-result-size": "$1 ({{PLURAL:$2|een Woort|$2 Wöör}})",
        "search-result-category-size": "{{PLURAL:$1|1 Sied|$1 Sieden}} ({{PLURAL:$2|1 Ünnerkategorie|$2 Ünnerkategorien}}, {{PLURAL:$3|1 Datei|$3 Datein}})",
-       "search-result-score": "Relevanz: $1 %",
        "search-redirect": "(Redirect $1)",
        "search-section": "(Afsnitt $1)",
        "search-suggest": "Hest du „$1“ meent?",
        "file-deleted-duplicate": "Jüst disse Datei ([[:$1]]) is al mal löscht worrn. Kiek man eerst, wat in dat Löschlogbook steiht, ehrdat du ehr noch wedder hoochlaadst.",
        "uploadwarning": "Wohrschau",
        "savefile": "Datei spiekern",
-       "uploadedimage": "„$1“ hoochladen",
-       "overwroteimage": "Ne’e Version vun „[[$1]]“ hoochlaadt",
        "uploaddisabled": "Dat Hoochladen is deaktiveert.",
        "uploaddisabledtext": "Dat Hoochladen vun Datein is utschalt.",
        "php-uploaddisabledtext": "Dat Hoochladen vun Datein is in PHP utstellt. Kiek de file_uploads-Instellungen na.",
        "watchlist-details": "{{PLURAL:$1|Ene Siet is|$1 Sieden sünd}} op dien Oppasslist (ahn Diskuschoonssieden).",
        "wlheader-enotif": "Benarichtigen per E-Mail is anstellt.",
        "wlheader-showupdated": "Sieden, de siet dien letzten Besöök ännert worrn sünd, warrt '''fett''' wiest.",
+       "wlnote": "Ünnen {{PLURAL:$1|steiht de letzte Ännern|staht de letzten $1 Ännern}} vun de {{PLURAL:$2|letzte Stünn|letzten '''$2''' Stünnen}}.",
        "wlshowlast": "Wies de letzten $1 Stünnen $2 Daag $3",
        "watchlist-options": "Optionen för de Oppasslist",
        "watching": "warrt op de Oppasslist ropsett...",
index bcce965..80dca86 100644 (file)
@@ -84,7 +84,7 @@
        "may_long": "मे",
        "june": "जुन",
        "july": "जुलाई",
-       "august": "à¤\85à¤\97सà¥\8dत",
+       "august": "à¤\85à¤\97सà¥\8dà¤\9f",
        "september": "सेप्टेम्बर",
        "october": "अक्टोबर",
        "november": "नोभेम्बर",
@@ -96,7 +96,7 @@
        "may-gen": "मे",
        "june-gen": "जुन",
        "july-gen": "जुलाई",
-       "august-gen": "à¤\85à¤\97सà¥\8dत",
+       "august-gen": "à¤\85à¤\97सà¥\8dà¤\9f",
        "september-gen": "सेप्टेम्बर",
        "october-gen": "अक्टोबर",
        "november-gen": "नोभेम्बर",
        "talkpagelinktext": "वार्तालाप",
        "specialpage": "विशेष पृष्ठ",
        "personaltools": "व्यक्तिगत औजारहरू",
-       "postcomment": "नयाँ खण्ड",
        "articlepage": "कन्टेन्ट पृष्ठ हेर्नुहोस्",
        "talk": "वार्तालाप",
        "views": "अवलोकनहरू",
        "externaldberror": "यहाँ प्रमाणिकरण डेटाबेस त्रुटि भयो या त तपाईंलाई आफ्नो बाहिरी खाता अद्यतन गर्ने अनुमति छैन।",
        "login": "प्रवेश",
        "nav-login-createaccount": "प्रवेश गर्ने/नयाँ खाता बनाउने",
-       "loginprompt": "तपाईंले {{SITENAME}}मा प्रवेश गर्न कुकीहरू सक्रिय बनाउनुपर्छ ।",
        "userlogin": "प्रवेश गर्ने / नयाँ खाता बनाउने",
        "userloginnocreate": "लग इन",
        "logout": "निर्गमन",
        "searchprofile-advanced-tooltip": "अनुकुल नेमस्पेसमा खोज्ने",
        "search-result-size": "$1 ({{PLURAL:$2|1 शव्द|$2 शव्दहरु}})",
        "search-result-category-size": "{{PLURAL:$1|एक सदस्य|$1 सदस्यहरु}} ({{PLURAL:$2|1 उपश्रेणी|$2  उपश्रेणीहरु}}, {{PLURAL:$3|एउटा फाइल|$3 फाइलहरु}})",
-       "search-result-score": "मिल्ने :$1%",
        "search-redirect": "(जाने $1)",
        "search-section": "(खण्ड $1)",
        "search-suggest": "के तपाईको खोजाई : $1 हो?",
        "uploadwarning": "उर्ध्वभरण चेतावनी",
        "uploadwarning-text": "कृपया तल फाइलको वर्णन परिवर्तन गर्नुहोस र पुन: प्रयास गर्नुहोस् ।",
        "savefile": "फाइल बचत गर्नुहोस्",
-       "uploadedimage": "उर्ध्वभरण(upload) गरियो  \"[[$1]]\"",
-       "overwroteimage": " \"[[$1]]\"को एउटा नयाँ संस्करण उर्ध्वभरण गरियो",
        "uploaddisabled": "उर्ध्वभरण अक्षम पारिएकोछ",
        "copyuploaddisabled": " URL प्रयोग गरी उर्ध्वभरण निश्कृय पारिएको छ।",
        "uploaddisabledtext": "फाइल उर्ध्वभरण अक्षम पारिएकोछ",
        "watchlist-details": "तपाईको निगरानी सूचीमा रहेका{{PLURAL:$1|$1 पृष्ठ|$1 पृष्ठहरु}}वार्तालापमा पृष्ठमा गनिएका छैनन् ।",
        "wlheader-enotif": "ईमेल जानकारी सक्रिय गरियो ।",
        "wlheader-showupdated": "तपाईँले पछिल्लो पल्ट भ्रमण गरेपछि परिवर्तन भएका पृष्ठहरूलाई <strong>गाढा<strong> गरेर देखाइएको छ ।",
+       "wlnote": "$3 र $4 अनुसार विगत {{PLURAL:$2|घण्टामा|'''$2''' घण्टाहरुमा}} {{PLURAL:$1|गरिएको अन्तिम परिवर्तन तल दिइएकोछ|गरिएका अन्तिम  '''$1''' परिवर्तनहरु तल दिइएका छन्}}।",
        "wlshowlast": "पछिल्ला $2 दिनहरूका $3 $1 घण्टाहरूका देखाउनुहोस्",
        "watchlist-options": "निगरानि सूची विकल्प",
        "watching": "निगरानी गर्दै...",
        "duplicate-defaultsort": "'''चेतावनी:''' पूर्व निर्धारित छोटकरी \"$2\" ले पुरानो पूर्वनिर्धारित छोटकरी\"$1\"लाई विस्थापन गरेको छ ।",
        "version": "संस्करण",
        "version-extensions": "स्थापना गरिएका एक्सटेन्सनहरु",
+       "version-skins": "खोलहरु",
        "version-specialpages": "विशेष पृष्ठहरू",
        "version-parserhooks": "पार्सर हुकहरु",
        "version-variables": "चल राशी(variables)",
        "version-antispam": "स्प्याम रोकथाम",
-       "version-skins": "खोलहरु",
        "version-api": "एपिआइ(API)",
        "version-other": "अन्य",
        "version-mediahandlers": "मिडिया  ह्यान्डलरहरू",
index fe962ef..c9faa08 100644 (file)
@@ -57,7 +57,9 @@
                        "לערי ריינהארט",
                        "아라",
                        "Mar(c)",
-                       "Calak"
+                       "Calak",
+                       "Arg",
+                       "NCoppens"
                ]
        },
        "tog-underline": "Koppelingen onderstrepen:",
@@ -74,7 +76,8 @@
        "tog-watchdefault": "Pagina’s en bestanden die ik bewerk automatisch volgen",
        "tog-watchmoves": "Pagina’s en bestanden die ik hernoem automatisch volgen",
        "tog-watchdeletion": "Pagina’s en bestanden die ik verwijder automatisch volgen",
-       "tog-minordefault": "Mijn bewerkingen als ‘klein’ markeren",
+       "tog-watchrollback": "Pagina's waarop ik heb teruggedraaid automatisch volgen",
+       "tog-minordefault": "Mijn bewerkingen standaard als ‘klein’ markeren",
        "tog-previewontop": "Voorvertoning boven bewerkingsveld weergeven",
        "tog-previewonfirst": "Voorvertoning bij eerste bewerking weergeven",
        "tog-enotifwatchlistpages": "Mij e-mailen bij bewerkingen van pagina’s of bestanden op mijn volglijst",
        "talkpagelinktext": "Overleg",
        "specialpage": "Speciale pagina",
        "personaltools": "Persoonlijke instellingen",
-       "postcomment": "Nieuw kopje",
        "articlepage": "Pagina bekijken",
        "talk": "Overleg",
        "views": "Weergaven",
        "otherlanguages": "In andere talen",
        "redirectedfrom": "(Doorverwezen vanaf $1)",
        "redirectpagesub": "Doorverwijspagina",
+       "redirectto": "Doorverwijzen naar:",
        "lastmodifiedat": "Deze pagina is het laatst bewerkt op $1 om $2.",
        "viewcount": "Deze pagina is {{PLURAL:$1|één keer|$1 keer}} bekeken.",
        "protectedpage": "Beveiligde pagina",
        "hidetoc": "verbergen",
        "collapsible-collapse": "Inklappen",
        "collapsible-expand": "Uitvouwen",
+       "confirmable-confirm": "Weet {{GENDER:$1|u}} het zeker?",
+       "confirmable-yes": "Ja",
+       "confirmable-no": "Nee",
        "thisisdeleted": "$1 bekijken of terugplaatsen?",
        "viewdeleted": "$1 bekijken?",
        "restorelink": "$1 verwijderde {{PLURAL:$1|versie|versies}}",
        "invalidtitle-knownnamespace": "Ongeldige titel met naamruimte \"$2\" en tekst \"$3\"",
        "invalidtitle-unknownnamespace": "Ongeldige titel met onbekend naamruimtenummer $1 en tekst \"$2\"",
        "exception-nologin": "Niet aangemeld",
-       "exception-nologin-text": "[[Special:Userlogin|Meld u aan]] om deze pagina te bekijken of deze handeling uit te voeren.",
+       "exception-nologin-text": "Meld u aan om deze pagina te bekijken of deze handeling uit te voeren.",
        "exception-nologin-text-manual": "U moet $1 om deze pagina te kunnen bekijken of de handeling uit te voeren.",
        "virus-badscanner": "Onjuiste configuratie: onbekende virusscanner: ''$1''.",
        "virus-scanfailed": "scannen is mislukt (code $1)",
        "externaldberror": "Er is een fout opgetreden bij het aanmelden bij de database of u hebt geen toestemming uw externe account bij te werken.",
        "login": "Aanmelden",
        "nav-login-createaccount": "Aanmelden / registreren",
-       "loginprompt": "U moet cookies ingeschakeld hebben om u te kunnen aanmelden bij {{SITENAME}}.",
        "userlogin": "Aanmelden / registreren",
        "userloginnocreate": "Aanmelden",
        "logout": "Afmelden",
        "userlogin-resetlink": "Bent u uw aanmeldgegevens vergeten?",
        "userlogin-resetpassword-link": "Wachtwoord vergeten?",
        "userlogin-helplink2": "Hulp bij aanmelden",
-       "userlogin-loggedin": "U bent al aangemeld als {{GENDER:$1|$1}}.\nGebruik het onderstaande formulier om aan te melden als een andere gebruiker.",
-       "userlogin-createanother": "Een andere account aanmaken",
        "createacct-emailrequired": "E-mailadres",
        "createacct-emailoptional": "E-mailadres (optioneel)",
        "createacct-email-ph": "Geef uw e-mailadres op",
        "noname": "U hebt geen geldige gebruikersnaam opgegeven.",
        "loginsuccesstitle": "Aanmelden geslaagd",
        "loginsuccess": "'''U bent nu aangemeld bij {{SITENAME}} als \"$1\".'''",
-       "nosuchuser": "De gebruiker \"$1\" bestaat niet.\nGebruikersnamen zijn hoofdlettergevoelig.\nControleer de schrijfwijze of [[Special:UserLogin/signup|maak een nieuwe gebruiker aan]].",
+       "nosuchuser": "De gebruiker \"$1\" bestaat niet.\nGebruikersnamen zijn hoofdlettergevoelig.\nControleer de schrijfwijze of [[Special:UserLogin/signup|maak een nieuw account aan]].",
        "nosuchusershort": "De gebruiker \"$1\" bestaat niet.\nControleer de schrijfwijze.",
        "nouserspecified": "Geef een gebruikersnaam op.",
        "login-userblocked": "Deze gebruiker is geblokkeerd.\nAanmelden is niet mogelijk.",
        "preview": "Voorvertoning",
        "showpreview": "Bewerking ter controle bekijken",
        "showdiff": "Wijzigingen bekijken",
+       "blankarticle": "<strong>Waarschuwing:</strong> de pagina die u wilt aanmaken is leeg.\nAls u opnieuw op \"{{int:savearticle}}\" klikt, wordt de pagina aangemaakt zonder enige inhoud.",
        "anoneditwarning": "'''Waarschuwing:''' u bent niet aangemeld.\nUw IP-adres wordt opgeslagen als u wijzigingen op deze pagina maakt.",
        "anonpreviewwarning": "''U bent niet aangemeld.''\n''Door uw bewerking op te slaan wordt uw IP-adres opgeslagen in de paginageschiedenis.''",
        "missingsummary": "'''Let op:''' u hebt geen bewerkingssamenvatting opgegeven.\nAls u nogmaals op \"{{int:savearticle}}\" klikt wordt de bewerking zonder samenvatting opgeslagen.",
        "parser-template-recursion-depth-warning": "De recursiediepte voor sjablonen is overschreden ($1)",
        "language-converter-depth-warning": "De dieptelimiet voor de taalconvertor is overschreden ($1)",
        "node-count-exceeded-category": "Pagina's waar het maximaal aantal nodes is overschreden",
-       "node-count-exceeded-category-desc": "Een categorie voor pagina's waar het aantal knooppunten is overschreden.",
-       "node-count-exceeded-warning": "Op de pagina is het maximale aantal nodes overschreden",
+       "node-count-exceeded-category-desc": "De pagina overschrijdt het maximale aantal knooppunten.",
+       "node-count-exceeded-warning": "De pagina overschrijdt het maximale aantal nodes",
        "expansion-depth-exceeded-category": "Pagina's waar de expansiediepte is overschreden",
-       "expansion-depth-exceeded-category-desc": "Dit is een categorie voor pagina's waar de expansiediepte is overschreden.",
+       "expansion-depth-exceeded-category-desc": "De pagina overschrijdt de maximale expansiediepte.",
        "expansion-depth-exceeded-warning": "De pagina bevat te veel sjablonen",
        "parser-unstrip-loop-warning": "Er is een \"unstrip\"-lus gedetecteerd",
        "parser-unstrip-recursion-limit": "De recursielimiet ($1) voor \"unstrip\" is overschreden",
        "revdelete-text-text": "Verwijderde versies zijn nog zichtbaar in de geschiedenis, maar delen van de inhoud zijn niet openbaar.",
        "revdelete-text-file": "Verwijderde versies zijn nog zichtbaar in de bestandsgeschiedenis, maar delen van de inhoud zijn niet openbaar.",
        "logdelete-text": "Verwijderde logboekregels zijn nog zichtbaar in de logboeken, maar delen van de inhoud zijn niet openbaar.",
-       "revdelete-text-others": "Andere beheerders van {{SITENAME}} kunnen de verborgen inhoud nog steeds inzien en weer zichtbaar maken via deze interface, tenzij er aanvullende beperkingen zijn ingesteld.",
+       "revdelete-text-others": "Andere beheerders kunnen de verborgen inhoud nog steeds inzien en weer zichtbaar maken, tenzij er aanvullende beperkingen zijn ingesteld.",
        "revdelete-confirm": "Bevestig dat u dit wilde doen, dat u de consequenties begrijpt en dat u dit doet in overeenstemming met het geldende [[{{MediaWiki:Policy-url}}|beleid]].",
        "revdelete-suppress-text": "Gebruik versies verbergen '''alleen''' in de volgende gevallen:\n* Mogelijk smadelijke informatie;\n* Ongepaste persoonlijke gegevens, zoals:\n*: ''adres, telefoonnummers, identificatienummer, enzovoort.''",
        "revdelete-legend": "Zichtbaarheidsbeperkingen instellen",
        "mergehistory-empty": "Er zijn geen versies die samengevoegd kunnen worden.",
        "mergehistory-success": "$3 {{PLURAL:$3|versie|versies}} van [[:$1]] zijn succesvol samengevoegd naar [[:$2]].",
        "mergehistory-fail": "Kan geen geschiedenis samenvoegen, controleer opnieuw de pagina- en tijdinstellingen.",
+       "mergehistory-fail-toobig": "Niet in staat om geschiedenis samen te voegen omdat meer dan de limiet van $1 {{PLURAL:$1|revisie zou|revisies zouden}} worden verplaatst.",
        "mergehistory-no-source": "De bronpagina $1 bestaat niet.",
        "mergehistory-no-destination": "De bestemmingspagina $1 bestaat niet.",
        "mergehistory-invalid-source": "De bronpagina moet een geldige paginanaam zijn.",
        "searchprofile-advanced-tooltip": "Zoeken in opgegeven naamruimten",
        "search-result-size": "$1 ({{PLURAL:$2|1 woord|$2 woorden}})",
        "search-result-category-size": "{{PLURAL:$1|1 categorielid|$1 categorieleden}} ({{PLURAL:$2|1 ondercategorie|$2 ondercategorieën}}, {{PLURAL:$3|1 bestand|$3 bestanden}})",
-       "search-result-score": "Relevantie: $1%",
        "search-redirect": "(doorverwijzing $1)",
        "search-section": "(subkop $1)",
        "search-file-match": "(komt overeen met de inhoud van het bestand)",
        "searchall": "alle",
        "showingresults": "Hieronder {{PLURAL:$1|staat '''1''' resultaat|staan '''$1''' resultaten}} vanaf #'''$2'''.",
        "showingresultsinrange": "Hieronder {{PLURAL:$1|wordt|worden}} maximaal {{PLURAL:$1|<strong>1</strong> resultaat|<strong>$1 </strong>resultaten}} weergegeven in het bereik #<strong>$2</strong> tot #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Resultaat '''$1''' van '''$3'''|Resultaten '''$1 - $2''' van '''$3'''}} voor '''$4'''",
        "search-nonefound": "Er zijn geen resultaten voor uw zoekopdracht.",
        "powersearch-legend": "Uitgebreid zoeken",
        "powersearch-ns": "Zoeken in naamruimten:",
        "preferences": "Voorkeuren",
        "mypreferences": "Voorkeuren",
        "prefs-edits": "Aantal bewerkingen:",
-       "prefsnologintext2": "U moet $1 om voorkeuren in te stellen.",
+       "prefsnologintext2": "U moet aanmelden om voorkeuren in te stellen.",
        "prefs-skin": "Vormgeving",
        "skin-preview": "Voorvertoning",
        "datedefault": "Geen voorkeur",
        "right-deletedtext": "Verwijderde tekst en wijzigingen tussen verwijderde versies bekijken",
        "right-browsearchive": "Verwijderde pagina's zoeken",
        "right-undelete": "Verwijderde pagina's terugplaatsen",
-       "right-suppressrevision": "Verborgen versies bekijken en terugplaatsen",
+       "right-suppressrevision": "Specifieke versies bekijken, verbergen en weer zichtbaar maken op pagina's van elke gebruiker",
+       "right-viewsuppressed": "Bekijk versies verborgen door elke gebruiker",
        "right-suppressionlog": "Niet-openbare logboeken bekijken",
        "right-block": "Andere gebruikers de mogelijkheid ontnemen te bewerken",
        "right-blockemail": "Een gebruiker het recht ontnemen om e-mail te versturen",
        "recentchanges-summary": "Op deze pagina kunt u de recentste wijzigingen in deze wiki bekijken.",
        "recentchanges-noresult": "Er zijn in deze periode geen wijzigingen gemaakt die aan de criteria voldoen.",
        "recentchanges-feed-description": "Met deze feed kunt u de recentste wijzigingen in deze wiki bekijken.",
-       "recentchanges-label-newpage": "Met deze bewerking is een nieuwe pagina aangemaakt.",
+       "recentchanges-label-newpage": "Met deze bewerking is een nieuwe pagina aangemaakt",
        "recentchanges-label-minor": "Dit is een kleine bewerking",
        "recentchanges-label-bot": "Deze bewerking is uitgevoerd door een bot",
        "recentchanges-label-unpatrolled": "Deze bewerking is nog niet gecontroleerd",
        "recentchanges-label-plusminus": "Deze paginagrootte is met dit aantal bytes gewijzigd",
        "recentchanges-legend-heading": "'''Legenda:'''",
-       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (zie ook de [[Special:NewPages|Lijst met nieuwe pagina's]])",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (zie ook de [[Special:NewPages|lijst met nieuwe pagina's]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "rcnotefrom": "Wijzigingen sinds <strong>$3 om $4</strong> (maximaal <strong>$1</strong> {{PLURAL:$1|wijziging|wijzigingen}}).",
        "rclistfrom": "Wijzigingen bekijken vanaf $3 $2",
        "uploadwarning": "Uploadwaarschuwing",
        "uploadwarning-text": "Pas de onderstaande bestandsbeschrijving aan en probeer het daarna opnieuw.",
        "savefile": "Bestand opslaan",
-       "uploadedimage": "heeft \"[[$1]]\" geüpload",
-       "overwroteimage": "heeft een nieuwe versie van \"[[$1]]\" toegevoegd",
        "uploaddisabled": "Uploaden is uitgeschakeld",
        "copyuploaddisabled": "Het uploaden van bestanden via een URL is uitgeschakeld.",
        "uploaddisabledtext": "Het uploaden van bestanden is uitgeschakeld.",
        "license": "Licentie:",
        "license-header": "Licentie",
        "nolicense": "Maak een keuze",
+       "licenses-edit": "Licentieopties bewerken",
        "license-nopreview": "(Voorvertoning niet beschikbaar)",
-       "upload_source_url": " (een geldige, publiek toegankelijke URL)",
-       "upload_source_file": " (een bestand op uw computer)",
+       "upload_source_url": "(een bestanden van een geldige, publiek toegankelijke URL)",
+       "upload_source_file": "(een bestand op uw computer)",
+       "listfiles-delete": "verwijderen",
        "listfiles-summary": "Op deze speciale pagina zijn alle toegevoegde bestanden te bekijken.",
        "listfiles_search_for": "Zoeken naar bestand:",
        "imgfile": "bestand",
        "randomincategory": "Willekeurige pagina in de categorie",
        "randomincategory-invalidcategory": "\"$1\" is geen geldige categorienaam.",
        "randomincategory-nopages": "Er zijn geen pagina's in de categorie [[:Category:$1|$1]].",
-       "randomincategory-selectcategory": "Geef een willekeurige pagina uit de categorie $1 weer. $2",
-       "randomincategory-selectcategory-submit": "OK",
+       "randomincategory-category": "Categorie:",
+       "randomincategory-legend": "Willekeurige pagina in een categorie",
        "randomredirect": "Willekeurige doorverwijzing",
        "randomredirect-nopages": "Er zijn geen doorverwijzingen in de naamruimte \"$1\".",
        "statistics": "Statistieken",
        "wantedpages-badtitle": "Ongeldige paginanaam in resultaat: $1",
        "wantedfiles": "Niet-bestaande bestanden met koppelingen",
        "wantedfiletext-cat": "De volgende bestanden worden gebruikt maar bestaan niet. Bestanden van externe repositories kunnen zijn opgenomen in de lijst, ondanks dat ze bestaan. Dergelijke vals positieven worden <del>doorgehaald weergegeven</del>. Pagina's die niet-bestaande bestanden insluiten staan op de pagina [[:$1]].",
+       "wantedfiletext-cat-noforeign": "De volgende bestanden zijn in gebruik maar bestaan niet. Daarnaast staan pagina's met niet-bestaande bestanden op [[:$1]].",
        "wantedfiletext-nocat": "De volgende bestanden worden gebruikt maar bestaan niet. Bestanden van externe repositories kunnen zijn opgenomen in de lijst, ondanks dat ze bestaan. Dergelijke vals positieven worden <del>doorgehaald weergegeven</del>.",
+       "wantedfiletext-nocat-noforeign": "De volgende bestanden zijn in gebruik maar bestaan niet.",
        "wantedtemplates": "Niet-bestaande sjablonen met koppelingen",
        "mostlinked": "Pagina's waar het meest naar verwezen wordt",
        "mostlinkedcategories": "Categorieën waar het meest naar verwezen wordt",
        "linksearch-pat": "Zoekpatroon:",
        "linksearch-ns": "Naamruimte:",
        "linksearch-ok": "Zoeken",
-       "linksearch-text": "Wildcards zoals \"*.wikipedia.org\" of \"*.org\" zijn toegestaan.\nHeeft tenminste een topleveldomein nodig, zoals bijvoorbeeld \"*.org\".<br />\n{{PLURAL:$2|Ondersteund protocol|Ondersteunde protocollen}}: <code>$1</code> (wordt \"http://\"als er geen protocol wordt opgegeven).",
+       "linksearch-text": "Wildcards zoals \"*.wikipedia.org\" of \"*.org\" zijn toegestaan.\nHeeft tenminste een topleveldomein nodig, zoals bijvoorbeeld \"*.org\".<br />\n{{PLURAL:$2|Ondersteund protocol|Ondersteunde protocollen}}: <code>$1</code> (wordt \"http://\" als er geen protocol wordt opgegeven).",
        "linksearch-line": "$1 heeft een koppeling in $2",
        "linksearch-error": "Wildcards zijn alleen toegestaan aan het begin van een hostnaam.",
        "listusersfrom": "Gebruikers bekijken vanaf:",
        "trackingcategories-desc": "Opnamecriteria",
        "noindex-category-desc": "De pagina bevat het magische woord <code><nowiki>__NOINDEX__</nowiki></code> (en bevindt zich in een naamruimte waarin dat magische woord is toegestaan), en wordt niet geïndexeerd door robots.",
        "index-category-desc": "De pagina bevat het magische woord <code><nowiki>__INDEX__</nowiki></code> (en bevindt zich in een naamruimte waarin dat magische woord is toegestaan), en wordt geïndexeerd door robots, terwijl dat normaliter niet zou gebeuren.",
-       "post-expand-template-inclusion-category-desc": "Na het uitbreiden van alle sjablonen, is de pagina groter dan <code>$wgMaxArticleSize</code>, dus zijn sommige sjablonen niet uitgebreid.",
-       "post-expand-template-argument-category-desc": "Na het uitbreiden van een sjabloonparameter (iets in de drievoudige accolades, zoals <code>{{{Foo}}})</code>), is de pagina groter dan <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Op de pagina worden te veel kostbare parserfuncties (zoals <code>#ifexist</code>) gebruikt. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Meer informatie].",
-       "broken-file-category-desc": "Een categorie die wordt toegevoegd als een pagina een niet-bestaande koppeling bevat (een koppeling om een bestand toe te voegen als dat bestand niet bestaat).",
-       "hidden-category-category-desc": "Dit is een categoriepagina die het magische woord <code><nowiki>__HIDDENCAT__</nowiki></code> bevat, waardoor de categorie standaard niet zichtbaar is in de lijst met categorieën op pagina's.",
+       "post-expand-template-inclusion-category-desc": "De pagina groter dan <code>$wgMaxArticleSize</code> na het uitbreiden van alle sjablonen, dus zijn sommige sjablonen niet uitgebreid.",
+       "post-expand-template-argument-category-desc": "De pagina is groter dan <code>$wgMaxArticleSize</code> na het uitbreiden van een sjabloonparameter (iets in de drievoudige accolades, zoals <code>{{{Foo}}})</code>).",
+       "expensive-parserfunction-category-desc": "De pagina gebruikt te veel kostbare parserfuncties (zoals <code>#ifexist</code>) gebruikt. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Meer informatie].",
+       "broken-file-category-desc": "De pagina bevat een niet-bestaande koppeling (een koppeling om een bestand toe te voegen als dat bestand niet bestaat).",
+       "hidden-category-category-desc": "De categorie heeft het magische woord <code><nowiki>__HIDDENCAT__</nowiki></code> in de inhoud, waardoor de categorie standaard niet zichtbaar is in de lijst met categorieën op pagina's.",
        "trackingcategories-nodesc": "Geen beschrijving beschikbaar.",
        "trackingcategories-disabled": "Categorie uitgeschakeld",
        "mailnologin": "Geen verzendadres beschikbaar",
        "mywatchlist": "Volglijst",
        "watchlistfor2": "Voor $1 $2",
        "nowatchlist": "Uw volglijst is leeg.",
-       "watchlistanontext": "Om uw volglijst te bekijken of te bewerken moet u zich $1.",
+       "watchlistanontext": "Om uw volglijst te bekijken of te bewerken moet u zich aanmelden.",
        "watchnologin": "U bent niet aangemeld",
        "addwatch": "Toevoegen aan volglijst",
        "addedwatchtext": "De pagina \"[[:$1]]\" is toegevoegd aan uw [[Special:Watchlist|volglijst]].\nToekomstige bewerkingen van deze pagina en de bijbehorende overlegpagina worden daar weergegeven.",
        "watchlist-details": "Er {{PLURAL:$1|staat één pagina|staan $1 pagina's}} op uw volglijst. Overlegpagina's worden niet meegeteld.",
        "wlheader-enotif": "U wordt per e-mail gewaarschuwd.",
        "wlheader-showupdated": "Pagina's die zijn bewerkt sinds uw laatste bezoek worden '''vet''' weergegeven.",
-       "wlnote2": "Hieronder staan de veranderingen in {{PLURAL:$1|het|de}} laatste {{PLURAL:$1|uur|<strong> $1 </strong>uren}}, sinds $2, $3.",
+       "wlnote": "Hieronder {{PLURAL:$1|staat de laaste wijziging|staan de laatste $1 wijzigingen}} in {{PLURAL:$2|het laatste uur|de laatste $2 uur}} per $3 om $4.",
        "wlshowlast": "Laatste $1 uur, $2 dagen bekijken ($3)",
        "watchlist-options": "Opties voor volglijst",
        "watching": "Bezig met plaatsen op volglijst…",
        "exbeforeblank": "De inhoud was: \"$1\"",
        "delete-confirm": "\"$1\" verwijderen",
        "delete-legend": "Verwijderen",
-       "historywarning": "'''Waarschuwing:''' de pagina die u wilt verwijderen heeft ongeveer $1 {{PLURAL:$1|versie|versies}}:",
+       "historywarning": "<strong>Waarschuwing:</strong> de pagina die u wilt verwijderen heeft ongeveer $1 {{PLURAL:$1|versie|versies}}:",
        "confirmdeletetext": "U staat op het punt een pagina te verwijderen, inclusief de geschiedenis.\nBevestig hieronder dat dit inderdaad uw bedoeling is, dat u de gevolgen begrijpt en dat de verwijdering overeenstemt met het [[{{MediaWiki:Policy-url}}|beleid]].",
        "actioncomplete": "Handeling voltooid",
        "actionfailed": "De handeling is mislukt.",
        "delete-edit-reasonlist": "Redenen voor verwijderen bewerken",
        "delete-toobig": "Deze pagina heeft een lange bewerkingsgeschiedenis, meer dan $1 {{PLURAL:$1|versie|versies}}.\nHet verwijderen van dit soort pagina's is met rechten beperkt om het per ongeluk verstoren van de werking van {{SITENAME}} te voorkomen.",
        "delete-warning-toobig": "Deze pagina heeft een lange bewerkingsgeschiedenis, meer dan $1 {{PLURAL:$1|versie|versies}}.\nHet verwijderen van deze pagina kan de werking van de database van {{SITENAME}} verstoren.\nWees voorzichtig.",
+       "deleteprotected": "U kunt deze pagina niet verwijderen omdat hij is beveiligd.",
        "deleting-backlinks-warning": "'''Waarschuwing:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|andere pagina's]] gebruiken of verwijzen naar de pagina die u wilt verwijderen.",
        "rollback": "Wijzigingen ongedaan maken",
        "rollback_short": "Terugdraaien",
        "autoblockid": "Automatische blokkade #$1",
        "block": "Gebruiker blokkeren",
        "unblock": "Gebruiker deblokkeren",
-       "blockip": "Gebruiker blokkeren",
+       "blockip": "{{GENDER:$1|Gebruiker}} blokkeren",
        "blockip-legend": "Gebruiker blokkeren",
        "blockiptext": "Gebruik het onderstaande formulier om schrijftoegang voor een gebruiker of IP-adres in te trekken.\nDoe dit alleen als bescherming tegen vandalisme en in overeenstemming met het [[{{MediaWiki:Policy-url}}|beleid]].\nGeef hieronder een reden op (bijvoorbeeld welke pagina's gevandaliseerd zijn).",
        "ipaddressorusername": "IP-adres of gebruikersnaam:",
        "ipb-unblock-addr": "$1 deblokkeren",
        "ipb-unblock": "Een gebruiker of IP-adres deblokkeren",
        "ipb-blocklist": "Bestaande blokkades bekijken",
-       "ipb-blocklist-contribs": "Bijdragen van $1",
+       "ipb-blocklist-contribs": "Bijdragen van {{GENDER:$1|$1}}",
        "unblockip": "Gebruiker deblokkeren",
        "unblockiptext": "Gebruik het onderstaande formulier om opnieuw schrijftoegang te geven aan een geblokkeerde gebruiker of IP-adres.",
        "ipusubmit": "Blokkade opheffen",
        "import": "Pagina's importeren",
        "importinterwiki": "Transwiki-import",
        "import-interwiki-text": "Selecteer een wiki en paginanaam om te importeren.\nVersie- en auteursgegevens blijven hierbij bewaard.\nAlle transwiki-importhandelingen worden opgeslagen in het [[Special:Log/import|importlogboek]].",
-       "import-interwiki-source": "Bronwiki/pagina:",
+       "import-interwiki-sourcewiki": "Bronwiki:",
+       "import-interwiki-sourcepage": "Bronpagina:",
        "import-interwiki-history": "Volledige geschiedenis van deze pagina ook kopiëren",
        "import-interwiki-templates": "Alle sjablonen opnemen",
        "import-interwiki-submit": "Importeren",
        "importlogpage": "Importlogboek",
        "importlogpagetext": "Administratieve import van pagina's met geschiedenis van andere wiki's.",
        "import-logentry-upload": "heeft [[$1]] geïmporteerd via een bestandsupload",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|versie|versies}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|versie|versies}} geïmporteerd",
        "import-logentry-interwiki": "importeerde $1 via transwiki",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|versie|versies}} van $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|versie|versies}} geïmporteerd uit $2",
        "javascripttest": "JavaScript testen",
        "javascripttest-title": "Tests uitvoeren voor $1",
        "javascripttest-pagetext-noframework": "Deze pagina is gereserveerd voor het uitvoeren van JavaScripttesten.",
        "autosumm-replace": "Tekst vervangen door \"$1\"",
        "autoredircomment": "Verwijst door naar [[$1]]",
        "autosumm-new": "Nieuwe pagina aangemaakt met '$1'",
+       "autosumm-newblank": "Lege pagina aangemaakt",
        "size-kilobytes": "$1 kB",
        "lag-warn-normal": "Wijzigingen in de afgelopen {{PLURAL:$1|seconde|$1 seconden}} worden misschien niet weergegeven in deze lijst.",
        "lag-warn-high": "Door een hoge database-servertoevoer zijn wijzigingen nieuwer dan $1 {{PLURAL:$1|seconde|seconden}} mogelijk niet beschikbaar in de lijst.",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|overleg]])",
        "unknown_extension_tag": "Onbekende tag \"$1\"",
        "duplicate-defaultsort": "'''Waarschuwing:''' de standaardsortering \"$2\" krijgt voorrang voor de sortering \"$1\".",
+       "duplicate-displaytitle": "<strong>Waarschuwing:</strong>Titelweergave \"$2\" overschrijft eerdere titelweergave \"$1\".",
        "version": "Versie",
        "version-extensions": "Geïnstalleerde uitbreidingen",
        "version-skins": "Geïnstalleerde vormgevingen",
        "version-hook-name": "Hooknaam",
        "version-hook-subscribedby": "Geabonneerd door",
        "version-version": "($1)",
+       "version-no-ext-name": "[geen naam]",
        "version-license": "Licentie voor MediaWiki",
        "version-ext-license": "Licentie",
        "version-ext-colheader-name": "Uitbreiding",
        "logentry-patrol-patrol-auto": "$1 {{GENDER:$2|heeft}} versie $4 van pagina $3 automatisch gemarkeerd als gecontroleerd",
        "logentry-newusers-newusers": "Gebruiker $1 {{GENDER:$2|is}} aangemaakt",
        "logentry-newusers-create": "Gebruikersaccount $1 {{GENDER:$2|is}} aangemaakt",
-       "logentry-newusers-create2": "Gebruiker $3 {{GENDER:$2|is}} aangemaakt door $1",
+       "logentry-newusers-create2": "Gebruikersaccount $3 {{GENDER:$2|is}} aangemaakt door $1",
        "logentry-newusers-byemail": "Gebruiker $3 {{GENDER:$2|is}} aangemaakt door $1 en het wachtwoord is per e-mail verzonden",
        "logentry-newusers-autocreate": "Gebruikersaccount $1 {{GENDER:$2|is}} automatisch aangemaakt",
        "logentry-rights-rights": "$1 {{GENDER:$2|heeft}} groepslidmaatschap voor $3 gewijzigd van $4 naar $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|heeft}} het groepslidmaatschap gewijzigd voor $3",
        "logentry-rights-autopromote": "$1 {{GENDER:$2|is}} automatisch gepromoveerd van $4 naar $5",
+       "logentry-upload-upload": "$1 heeft $3 {{GENDER:$2|geupload}}",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|heeft}} een nieuwe versie van $3 geüpload",
+       "logentry-upload-revert": "$1 heeft $3 {{GENDER:$2|geupload}}",
        "rightsnone": "(geen)",
        "feedback-bugornote": "Als u zover bent om een technisch probleem in detail te beschrijven, [$1 rapporteer dan een bug].\nAnders kunt u ook het eenvoudige formulier hieronder gebruiken. Uw reactie wordt dan toegevoegd aan de pagina \"[$3 $2]\", samen met uw gebruikersnaam en de browser die u gebruikt.",
        "feedback-subject": "Onderwerp:",
        "expand_templates_generate_xml": "XML-parserboom bekijken",
        "expand_templates_generate_rawhtml": "Ruwe HTML weergeven",
        "expand_templates_preview": "Voorvertoning",
+       "pagelanguage": "Taal pagina kiezen",
        "pagelang-name": "Pagina",
        "pagelang-language": "Taal",
-       "pagelang-select-lang": "Taal selecteren"
+       "pagelang-use-default": "Gebruik standaard taal",
+       "pagelang-select-lang": "Taal selecteren",
+       "right-pagelang": "Taal van de pagina wijzigen",
+       "action-pagelang": "Taal van de pagina wijzigen",
+       "log-name-pagelang": "Logboek van taalwijzigingen",
+       "log-description-pagelang": "Dit is een logboek van wijzigingen van de taal van pagina's.",
+       "logentry-pagelang-pagelang": "$1 wijzigde de taal van de pagina '$3' van $4 naar $5.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (ingeschakeld)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>uitgeschakeld</strong>)"
 }
index 40d1bee..3d761c7 100644 (file)
        "talkpagelinktext": "Diskusjon",
        "specialpage": "Spesialside",
        "personaltools": "Personlege verktøy",
-       "postcomment": "Ny bolk",
        "articlepage": "Vis innhaldsside",
        "talk": "Diskusjon",
        "views": "Visningar",
        "hidetoc": "gøym",
        "collapsible-collapse": "Slå saman.",
        "collapsible-expand": "Vid ut",
+       "confirmable-confirm": "Er {{GENDER:$1|du}} viss på dette?",
+       "confirmable-yes": "Ja",
+       "confirmable-no": "Nei",
        "thisisdeleted": "Sjå eller attopprett $1?",
        "viewdeleted": "Sjå historikk for $1?",
        "restorelink": "{{PLURAL:$1|Éin sletta versjon|$1 sletta versjonar}}",
        "externaldberror": "Det var anten ein ekstern databasefeil i tilgjengekontrollen, eller du har ikkje løyve til å oppdatere den eksterne kontoen din.",
        "login": "Logg inn",
        "nav-login-createaccount": "Lag brukarkonto / logg inn",
-       "loginprompt": "Nettlesaren din må godta informasjonskapslar for at du skal kunna logge inn.",
        "userlogin": "Lag brukarkonto / logg inn",
        "userloginnocreate": "Logg inn",
        "logout": "Logg ut",
        "searchprofile-advanced-tooltip": "Søk i visse namnerom",
        "search-result-size": "$1 ({{PLURAL:$2|eitt|$2}} ord)",
        "search-result-category-size": "{{PLURAL:$1|1 medlem|$1 medlemmer}} ({{PLURAL:$2|1 underkategori|$2 underkategoriar}}, {{PLURAL:$3|1 fil|$3 filer}})",
-       "search-result-score": "Relevans: $1&nbsp;%",
        "search-redirect": "(omdirigering $1)",
        "search-section": "(bolken $1)",
        "search-suggest": "Meinte du: «$1»",
        "search-interwiki-caption": "Systerprosjekt",
-       "search-interwiki-default": "$1-resultat:",
+       "search-interwiki-default": "Resultat frå $1:",
        "search-interwiki-more": "(meir)",
        "search-relatedarticle": "Relatert",
        "searchrelated": "relatert",
        "searchall": "alle",
        "showingresults": "Nedanfor er opp til {{PLURAL:$1|'''eitt'''|'''$1'''}} resultat som byrjar med nummer '''$2''' vist{{PLURAL:$1||e}}.",
-       "showingresultsheader": "{{PLURAL:$5|Resultat '''$1''' av '''$3'''|Resultat '''$1 - $2''' av '''$3'''}} for '''$4'''",
        "search-nonefound": "Ingen resultat svarte til førespurnaden.",
        "powersearch-legend": "Avansert søk",
        "powersearch-ns": "Søk i namnerom:",
        "powersearch-togglelabel": "Hak av:",
        "powersearch-toggleall": "Alle",
        "powersearch-togglenone": "Ingen",
+       "powersearch-remember": "Hugs utvalet for framtidige søk",
        "search-external": "Eksternt søk",
        "searchdisabled": "Søkjefunksjonen på {{SITENAME}} er slått av akkurat no.\nI mellomtida kan du søkje gjennom Google.\nVer merksam på at registra deira kan vera utdaterte.",
        "search-error": "Det oppstod ein feil under søket: $1",
        "uploadwarning": "Opplastingsåtvaring",
        "uploadwarning-text": "Ver venleg og endra filskildringa nedanfor og prøv på nytt",
        "savefile": "Lagre fil",
-       "uploadedimage": "lasta opp «[[$1]]»",
-       "overwroteimage": "lasta opp ein ny versjon av «[[$1]]»",
        "uploaddisabled": "Beklagar, funksjonen for opplasting er deaktivert på denne nettenaren.",
        "copyuploaddisabled": "Opplasting gjennom URL er slege av.",
        "uploaddisabledtext": "Filopplasting er slått av.",
        "download": "last ned",
        "unwatchedpages": "Uovervaka sider",
        "listredirects": "Omdirigeringsliste",
+       "listduplicatedfiles": "Liste over filer med duplikat",
+       "listduplicatedfiles-summary": "Dette er ei liste over filer der den siste versjonen av fila er eit duplikat av den siste versjonen av ei anna fil. Berre lokale filer vert rekna med.",
+       "listduplicatedfiles-entry": "[[:File:$1|$1]] har [[$3|{{PLURAL:$2|eit duplikat|$2 duplikat}}]].",
        "unusedtemplates": "Ubrukte malar",
        "unusedtemplatestext": "Denne sida viser alle sidene i mal-namnerommet ({{ns:template}}:) som ikkje er brukte på andre sider. Hugs også å sjå etter andre lenkjer til malane før du slettar dei.",
        "unusedtemplateswlh": "andre lenkjer",
        "randompage": "Tilfeldig side",
        "randompage-nopages": "Det finst ingen sider i {{PLURAL:$2|dette namnerommet|desse namneromma}}: $1.",
+       "randomincategory": "Tilfeldig side frå kategori",
+       "randomincategory-invalidcategory": "«$1» er ikkje eit gildt kategorinamn.",
+       "randomincategory-nopages": "Det er ingen sider i kategorien [[:Category:$1|$1]].",
        "randomredirect": "Tilfeldig omdirigering",
        "randomredirect-nopages": "Det finst ingen omdirigeringar i namnerommet «$1».",
        "statistics": "Statistikk",
        "deletedcontributions-title": "Sletta brukarbidrag",
        "sp-deletedcontributions-contribs": "bidrag",
        "linksearch": "Søk i eksterne lenkjer",
-       "linksearch-pat": "Søkemønster:",
+       "linksearch-pat": "Søkjemønster:",
        "linksearch-ns": "Namnerom:",
        "linksearch-ok": "Søk",
        "linksearch-text": "Jokerteikn som «*.wikipedia.org» kan nyttast.\nDet er påkravt med eit toppnivådomene, til dømes «*.org».<br />\n{{PLURAL:$2|Stødd protokoll|Stødde protokollar}}: <code>$1</code> (nyttar http:// som standard om ingen protokoll er oppgjeven)",
        "trackingcategories-name": "Meldingsnamn",
        "trackingcategories-desc": "Inkluderingsgrunnlag",
        "noindex-category-desc": "Sida vert ikkje indeksert av robotar av di ho inneheld trylleordet <code><nowiki>__NOINDEX__</nowiki></code> og er i eit namnerom der dette flagget er tillate.",
+       "trackingcategories-disabled": "Kategorien er avslegen",
        "mailnologin": "Inga avsendaradresse",
        "mailnologintext": "Du lyt vera [[Special:UserLogin|innlogga]] og ha ei gyldig e-postadresse sett i [[Special:Preferences|brukarinnstillingane]] for å sende e-post åt andre brukarar.",
        "emailuser": "Send e-post åt denne brukaren",
        "watchnologin": "Ikkje innlogga",
        "addwatch": "↓Legg til i overvakingslista",
        "addedwatchtext": "Sida «[[:$1]]» er lagd til i [[Special:Watchlist|overvakingslista]] di. Framtidige endringar av henne og den tilhøyrande diskusjonssida hennar vil bli oppførte der.",
+       "addedwatchtext-short": "Sida «$1» vart lagd til i overvakingslista di.",
        "removewatch": "Fjerna frå overvakingslista",
        "removedwatchtext": "Sida «[[:$1]]» er fjerna frå [[Special:Watchlist|overvakingslista di]].",
+       "removedwatchtext-short": "Sida «$1» vart fjerna frå overvakingslista di.",
        "watch": "Overvak",
        "watchthispage": "Overvak sida",
        "unwatch": "Fjern overvaking",
        "unwatchthispage": "Fjern overvaking",
        "notanarticle": "Ikkje innhaldsside",
        "notvisiblerev": "Sideversjonen er sletta",
-       "watchlist-details": "{{PLURAL:$1|Éi side|$1 sider}} er overvaka, utanom diskusjonssider.",
+       "watchlist-details": "{{PLURAL:$1|Éi side|$1 sider}} på overvakingslista di, utan separat teljing av diskusjonssider.",
        "wlheader-enotif": "Funksjonen for endringsmeldingar per e-post er på.",
        "wlheader-showupdated": "Sider som har vorte endra sidan du sist såg på dei er '''utheva'''",
+       "wlnote": "Nedanfor er {{PLURAL:$1|den siste endringa|dei siste '''$1''' endringane}} {{PLURAL:$2|den siste timen|dei siste '''$2''' timane}}, for $3, kl. $4.",
        "wlshowlast": "Vis siste $1 timane $2 dagane $3",
        "watchlist-options": "Alternativ for overvakingslista",
        "watching": "Overvakar...",
        "sp-contributions-search": "Søk etter bidrag",
        "sp-contributions-username": "IP-adresse eller brukarnamn:",
        "sp-contributions-toponly": "Vis berre endringar som er gjeldande versjonar",
+       "sp-contributions-newonly": "Berre vis endringar som oppretta ei side",
        "sp-contributions-submit": "Søk",
        "whatlinkshere": "Lenkjer hit",
        "whatlinkshere-title": "Sider som har lenkje til «$1»",
        "whatlinkshere-filters": "Filter",
        "autoblockid": "Autoblokker #$1",
        "block": "Blokker brukar",
-       "unblock": "Opphev blokkeringa av brukaren",
+       "unblock": "Opphev blokkering av brukar",
        "blockip": "Blokker brukar",
        "blockip-legend": "Blokker brukar",
        "blockiptext": "Bruk skjemaet nedanfor for å blokkere skrivetilgangen frå ei spesifikk IP-adresse eller brukarnamn. Dette bør berre gjerast for å hindre hærverk, og i samsvar med [[{{MediaWiki:Policy-url}}|retningslinene]].",
        "import": "Importer sider",
        "importinterwiki": "Transwikiimport",
        "import-interwiki-text": "Vel ei wiki og ei side å importere. Endringssdatoer og brukarar som har medverka vert bevart. Alle transwiki-importeringar vert vist i [[Special:Log/import|importloggen]].",
-       "import-interwiki-source": "Kjeldewiki/sida:",
        "import-interwiki-history": "Kopier all historikken for denne sida",
        "import-interwiki-templates": "Inkluder alle malar",
        "import-interwiki-submit": "Importer",
        "watchlistedit-raw-done": "Overvakingslista er oppdatert.",
        "watchlistedit-raw-added": "{{PLURAL:$1|Éi side vart lagt til|$1 sider vart lagde til}}:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|Éi side|$1 sider}} vart fjerna:",
+       "watchlistedit-clear-title": "Tømde overvakingslista",
+       "watchlistedit-clear-legend": "Tøm overvakingslista",
+       "watchlistedit-clear-explain": "Alle titlane vert fjerna frå overvakingslista di",
+       "watchlistedit-clear-titles": "Titlar:",
+       "watchlistedit-clear-submit": "Tøm overvakingslista (dette er permanent!)",
+       "watchlistedit-clear-done": "Overvakingslista di vart tømt.",
+       "watchlistedit-clear-removed": "{{PLURAL:$1|éin tittel|$1 titlar}} vart fjerna:",
+       "watchlistedit-too-many": "Det er for mange sider til at dei kan visast her.",
+       "watchlisttools-clear": "Tøm overvakingslista",
        "watchlisttools-view": "Vis relevante endringar",
        "watchlisttools-edit": "Vis og endre overvakingslista",
        "watchlisttools-raw": "Endre på overvakingslista i råformat",
index 8e77368..fa563b2 100644 (file)
        "talkpagelinktext": "Bolela",
        "specialpage": "Matlaka a itšeng",
        "personaltools": "Dithulusu tša gago (''personal'')",
-       "postcomment": "Sekgao se sempsha",
        "articlepage": "Nyakoretša letlakala la mateng",
        "talk": "Poledišano",
        "views": "Dinyakorêtšo",
        "remembermypassword": "Gopola sedi yaka ya go tsena khomphutha ye (bogolo bja  $1 ya {{PLURAL:$1| letšatši le|matšatši a}})",
        "login": "Tsena",
        "nav-login-createaccount": "Tsena / Tlhola tšhupaleloko (''account'')",
-       "loginprompt": "O swanela ke go dumella ''cookies'' go ''browser'' go tsena go {{SITENAME}}.",
        "userlogin": "Tsena / tlhola tšhupaleloko (''account'')",
        "logout": "Etšwa/Tswalela",
        "userlogout": "Etšwa/Tswalela",
        "fileuploadsummary": "Kakaretšo:",
        "filesource": "Mothopo:",
        "savefile": "Boloka faele",
-       "uploadedimage": "\"[[$1]]\" e loketšwe",
        "watchthisupload": "Tlhapetša ''faele'' ye",
        "license": "Laesense/Tumello:",
        "license-header": "Laesense",
index 1d2cd01..d46b17a 100644 (file)
@@ -29,6 +29,7 @@
        "tog-watchdefault": "Apondre las paginas que modifiqui e los fichièrs qu'impòrti a ma lista de seguiment",
        "tog-watchmoves": "Apondre las paginas e los fichièrs que tòrni nomenar a ma lista de seguiment",
        "tog-watchdeletion": "Apondre las paginas e los fichièrs que suprimissi de ma lista de seguiment",
+       "tog-watchrollback": "Apondre a ma lista de seguiment las paginas sus las qualas ai efectuat una revocacion",
        "tog-minordefault": "Considerar mas modificacions coma menoras per defaut",
        "tog-previewontop": "Far veire la previsualizacion al dessús de la zòna de modificacion",
        "tog-previewonfirst": "Far veire la previsualizacion al moment de la primièra edicion",
@@ -94,7 +95,7 @@
        "may-gen": "Mai",
        "june-gen": "Junh",
        "july-gen": "Julhet",
-       "august-gen": "Agost",
+       "august-gen": "d'agost",
        "september-gen": "Setembre",
        "october-gen": "Octobre",
        "november-gen": "Novembre",
        "talkpagelinktext": "Discussion",
        "specialpage": "Pagina especiala",
        "personaltools": "Aisinas personalas",
-       "postcomment": "Seccion novèla",
        "articlepage": "Vejatz l'article",
        "talk": "Discussion",
        "views": "Afichatges",
        "jumptonavigation": "navigacion",
        "jumptosearch": "Recercar",
        "view-pool-error": "O planhèm, los servidors son subrecargats pel moment.\nTròp d’utilizaires cercan a accedir a aquesta pagina.\nEsperatz un moment abans d'ensajar d’accedir a aquesta pagina.\n\n$1",
+       "generic-pool-error": "O planhèm, los servidors son subrecargats pel moment.\nTròp d’utilizaires ensajan de consultar aquesta ressorsa.\nEsperatz un moment abans d'ensajar d’accedir a aquesta pagina.",
        "pool-timeout": "Relambi depassat pendent l'espèra del varrolh",
        "pool-queuefull": "La fila de trabalh es plena",
        "pool-errorunknown": "Error desconeguda",
+       "pool-servererror": "Lo servici de comptatge de la reserva es pas disponible ($1).",
        "aboutsite": "A prepaus de {{SITENAME}}",
        "aboutpage": "Project:A prepaus",
        "copyright": "Lo contengut es disponible jos licéncia $1 levat mencion contrària.",
        "hidetoc": "amagar",
        "collapsible-collapse": "Rebatre",
        "collapsible-expand": "Desplegar",
+       "confirmable-confirm": "Sètz segur{{GENDER:||a|(a)}} ?",
+       "confirmable-yes": "Òc",
+       "confirmable-no": "Non",
        "thisisdeleted": "Desiratz afichar o restablir $1?",
        "viewdeleted": "Veire $1?",
        "restorelink": "{{PLURAL:$1|una edicion escafada|$1 edicions escafadas}}",
        "externaldberror": "Siá una error s’es producha amb la banca de donadas d’autentificacion extèrna, siá sètz pas autorizat a metre a jorn vòstre compte extèrne.",
        "login": "Identificacion",
        "nav-login-createaccount": "Crear un compte o se connectar",
-       "loginprompt": "Vos cal activar los cookies per vos connectar a {{SITENAME}}.",
        "userlogin": "Crear un compte o se connectar",
        "userloginnocreate": "Connexion",
        "logout": "Se desconnectar",
        "userlogin-resetlink": "Avètz doblidat vòstres detalhs de connexion ?",
        "userlogin-resetpassword-link": "Senhal doblidat ?",
        "userlogin-helplink2": "Ajuda a la connexion",
-       "userlogin-loggedin": "Sètz ja connectat en tant que {{GENDER:$1|$1}}.\nUtilizatz lo formulari çaijós per vos connectar amb un autre utilizaire.",
-       "userlogin-createanother": "Crear un autre compte",
        "createacct-emailrequired": "Adreça electronica",
        "createacct-emailoptional": "Adreça de corrièr electronic (facultativa)",
        "createacct-email-ph": "Entratz vòstra adreça de corrièr electronic",
        "resetpass-submit-cancel": "Anullar",
        "resetpass-wrong-oldpass": "Senhal actual o temporari invalid.\nBenlèu ja avètz modificat vòstre senhal o demandat un senhal temporari novèl.",
        "resetpass-recycled": "Reïnicializatz vòstre senhal a quicòm mai que l’actual.",
+       "resetpass-temp-emailed": "Sètz connect{{GENDER:|at|ada}} amb un còde temporari provesit per corrièr electronic.\nPer acabar la connexion, vos cal provesir un senhal novèl aicí :",
        "resetpass-temp-password": "Senhal temporari :",
        "resetpass-abort-generic": "La modificacion del senhal es estada anulada per una extension.",
        "resetpass-expired": "Vòstre senhal a expirat. Provesissètz-ne un novèl per vos connectar.",
+       "resetpass-expired-soft": "Vòstre senhal a expirat, e deu èsser reïnicializat. Causissètz-ne un novèl ara, o clicatz sus « {{int:resetpass-submit-cancel}} » per o far mai tard.",
+       "resetpass-validity-soft": "Vòstre senhal es pas valid : $1\n\nCausissètz un senhal novèl ara, o clicatz sus « {{int:resetpass-submit-cancel}} » per lo reïnicializar mai tard.",
        "passwordreset": "Remesa a zèro del senhal",
        "passwordreset-text-one": "Emplenatz aqueste formulari per reïnicializar vòstre senhal.",
        "passwordreset-text-many": "{{PLURAL:$1|Completatz un d'aqueles camps per recebre un senhal temporari per corrièr electronic.}}",
        "preview": "Previsualizar",
        "showpreview": "Previsualizacion",
        "showdiff": "Veire los cambiaments",
+       "blankarticle": "<strong>Atencion :</strong> La pagina que creatz es voida.\nSe clicatz tornarmai sus « {{int:savearticle}} », la pagina serà creada sens cap de contengut.",
        "anoneditwarning": "'''Atencion :''' sètz pas identificat(ada).\nVòstra adreça IP serà enregistrada dins l’istoric d'aquesta pagina.",
        "anonpreviewwarning": "''Sètz pas identificat. Salvar enregistrarà vòstra adreça IP dins l’istoric de las modificacions de la pagina.''",
        "missingsummary": "'''Atencion :''' avètz pas modificat lo resumit de vòstra modificacion. Se clicatz tornarmai sul boton « Salvar », lo salvament serà fach sens avertiment mai.",
        "parser-template-recursion-depth-warning": "Limit de longor de la recursion del modèl depassat ($1)",
        "language-converter-depth-warning": "Limit de prigondor del convertissor de lenga depassada ($1)",
        "node-count-exceeded-category": "Paginas ont nombre de nosèls es depassat",
-       "node-count-exceeded-warning": "Pagina depassant lo nombre de nosèls",
+       "node-count-exceeded-category-desc": "Aquesta pagina depassa lo nombre maximal de nosèls.",
+       "node-count-exceeded-warning": "Pagina que depassa lo nombre de nosèls",
        "expansion-depth-exceeded-category": "Paginas ont la prigondor d'espandiment es depassada",
+       "expansion-depth-exceeded-category-desc": "La pagina depassa la prigondor d’espandiment maximala.",
        "expansion-depth-exceeded-warning": "Pagina depassant la prigondor d'espandiment",
        "parser-unstrip-loop-warning": "Bocla pas desmontabla detectada",
        "parser-unstrip-recursion-limit": "Limit de recursion pas desmontable depassat ($1)",
        "currentrev": "Version actuala",
        "currentrev-asof": "Version actuala en data del $1",
        "revisionasof": "Version del $1",
-       "revision-info": "Version del $1 per $2",
+       "revision-info": "Version del $1 per {{GENDER:$6|$2}}$7",
        "previousrevision": "← Version precedenta",
        "nextrevision": "Version seguenta →",
        "currentrevisionlink": "vejatz la version correnta",
        "rev-deleted-event": "(entrada suprimida)",
        "rev-deleted-user-contribs": "[nom d'utilizaire o adreça IP suprimida - modificacion amagada sus las contribucions]",
        "rev-deleted-text-permission": "Aquesta version de la pagina es estada '''escafada'''.\nI pòt aver de detalhs dins lo [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} jornal dels escafaments].",
+       "rev-suppressed-text-permission": "Aquesta version de la page es estada <strong>suprimida</strong>.\nLos detalhs se tròban dins lo [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} jornal de las supressions].",
        "rev-deleted-text-unhide": "Aquesta version de la pagina es estada '''escafada'''.\nI pòt aver mai de detalhs dins [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} lo jornal dels escafaments].\nComa administrator, podètz encara [$1 veire aquesta version] s'o volètz.",
        "rev-suppressed-text-unhide": "Aquesta version de la pagina es estada '''suprimida'''.\nI pòt aver mai de detalhs dins [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} lo jornal de las supressions].\nComa administrator, podètz encara [$1 veire aquesta version] s'o volètz.",
        "rev-deleted-text-view": "Aquesta version de la pagina es estada '''escafada'''.\nLa podètz visualizar ; de detalhs son disponibles dins lo [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} jornal dels escafaments].",
        "revdelete-selected-text": "{{PLURAL:$1|Revision seleccionada|Revisions seleccionadas}} de [[:$2]] :",
        "revdelete-selected-file": "{{PLURAL:$1|Version de fichièr seleccionada|Versions de fichièr seleccionadas}} de [[:$2]] :",
        "logdelete-selected": "{{PLURAL:$1|Eveniment d'istoric seleccionat|Eveniments d'istoric seleccionats}} :",
+       "revdelete-text-text": "Las revisions suprimidas contunharàn d'aparéisser dins l’istoric de la pagina, mas una partida de lor contengut serà inaccessibla al public.",
+       "revdelete-text-file": "Las versions de fichièr suprimidas contunharàn d'aparéisser dins l’istoric dels fichièrs, mas una partida de lor contengut serà indisponibla al public.",
+       "logdelete-text": "Los eveniments del jornal suprimits contunharàn d'aparéisser dins los jornals, mas una partida de lor contengut serà indisponibla al public.",
+       "revdelete-text-others": "Los autres administrators seràn totjorn en mesura d'accedir al contengut amagat e de lo restablir, levat se de restriccions suplementàrias son fixadas.",
        "revdelete-confirm": "Confirmatz que volètz efectuar aquesta accion, que ne comprenètz las consequéncias, e qu'o fasètz en acòrd amb [[{{MediaWiki:Policy-url}}|las règlas]].",
        "revdelete-suppress-text": "La supression deu èsser utilizada '''sonque''' dins los cases seguents :\n* Informacions potencialament difamatòrias\n* Informacions personalas inapropriadas\n*: ''adreça, numèro de telefòn, numèro de seguretat sociala, ...''",
        "revdelete-legend": "Metre en plaça de restriccions de version :",
        "mergehistory-empty": "Cap de revision pòt pas èsser fusionada.",
        "mergehistory-success": "$3 {{PLURAL:$3|revision|revisions}} de [[:$1]] {{PLURAL:$3|fusionada|fusionadas}} amb succès amb [[:$2]].",
        "mergehistory-fail": "Impossible de procedir a la fusion dels istorics. Seleccionatz  tornamai la pagina e mai los paramètres de data.",
+       "mergehistory-fail-toobig": "Impossible d’efectuar la fusion de l’istoric perque un nombre de {{PLURAL:$1|revisions}} superior al limit de $1 deuriá èsser desplaçat.",
        "mergehistory-no-source": "La pagina d'origina $1 existís pas.",
        "mergehistory-no-destination": "La pagina de destinacion $1 existís pas.",
        "mergehistory-invalid-source": "La pagina d’origina deu aver un títol valid.",
        "editundo": "desfar",
        "diff-empty": "(Pas cap de diferéncia)",
        "diff-multi-sameuser": "({{PLURAL:$1|Una revision intermediària pel meteis utilizaire pas afichada|$1 revisions intermediàrias pel meteis utilizaire pas afichadas}})",
+       "diff-multi-otherusers": "({{PLURAL:$1|Una revision intermediària|$1 revisions intermediàrias}} per {{PLURAL:$2|un autre utilizaire|$2 utilizaires}} pas {{PLURAL:$1|afichada|afichadas}})",
        "diff-multi-manyusers": "({{PLURAL:$1|Una revision intermediària amagada|$1 revisions intermediàrias amagadas}}) per ({{PLURAL:$2|un utilizaire pas afichada|$2 utilizaires pas afichadas}})",
        "difference-missing-revision": "{{PLURAL:$2|Una revision|$2 revisions}} d'aquesta diferéncia ($1) {{PLURAL:$2|es pas estada trobada|son pas estadas trobadas}}.\n\nAquò se produtz en general en seguent un ligam de diferéncia obsolèta cap a una pagina qu'es estada suprimada.\nPodètz trobar de detalhs dins lo [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} jornal de las supressions].",
        "searchresults": "Resultats de la recèrca",
        "searchprofile-advanced-tooltip": "Recercar dins d'espacis de noms personalizats",
        "search-result-size": "$1 ({{PLURAL:$2|1 mot|$2 mots}})",
        "search-result-category-size": "$1 membre{{PLURAL:$1||s}} ($2 soscategoria{{PLURAL:$2||s}}, $3 fichièr{{PLURAL:$3||s}})",
-       "search-result-score": "Pertinéncia : $1%",
        "search-redirect": "(redireccion cap a $1)",
        "search-section": "(seccion $1)",
        "search-file-match": "(correspond al contengut del fichièr)",
        "powersearch-togglelabel": "Marcar :",
        "powersearch-toggleall": "Tot",
        "powersearch-togglenone": "Pas cap",
+       "powersearch-remember": "Se remembrar de la seleccion per las recèrcas venentas",
        "search-external": "Recèrca extèrna",
        "searchdisabled": "La recèrca sus {{SITENAME}} es desactivada.\nEn esperant la reactivacion, podètz efectuar una recèrca via Google.\nAtencion, lor indexacion de contengut {{SITENAME}} benlèu es pas a jorn.",
        "search-error": "Una error s'es producha en recercant : $1",
        "preferences": "Preferéncias",
        "mypreferences": "Preferéncias",
        "prefs-edits": "Nombre d’edicions :",
-       "prefsnologintext2": "$1 per definir las preferéncias d'utilizaire.",
+       "prefsnologintext2": "Connectatz-vos per modificar vòstras preferéncias.",
        "prefs-skin": "Aparéncia",
        "skin-preview": "Previsualizar",
        "datedefault": "Pas cap de preferéncia",
        "prefs-tokenwatchlist": "Geton",
        "prefs-diffs": "Diferéncias",
        "prefs-help-prefershttps": "Aquesta preferéncia serà efectiva al moment de vòstra connexion que ven.",
+       "prefs-tabs-navigation-hint": "Astúcia : Podètz utilizar las flèchas d'esquèrra e de drecha per navigar entre los onglets.",
        "email-address-validity-valid": "L'adreça electronica sembla bona",
        "email-address-validity-invalid": "entrar una adreça electronica valida",
        "userrights": "Gestion dels dreches d'utilizaire",
        "right-move": "Tornar nomenar de paginas",
        "right-move-subpages": "Desplaçar de paginas amb lor sospaginas",
        "right-move-rootuserpages": "Tornar nomenar las paginas de l’utilizaire de banca.",
+       "right-move-categorypages": "Renomenar de paginas de categoria",
        "right-movefile": "Desplaçar los fichièrs",
        "right-suppressredirect": "Crear pas de redireccion dempuèi la pagina anciana en renomenant la pagina",
        "right-upload": "Telecargar de fichièrs",
        "right-deletedtext": "Veire lo tèxte suprimit e las diferéncias entre las versions suprimidas",
        "right-browsearchive": "Recercar de paginas suprimidas",
        "right-undelete": "Restablir una pagina",
-       "right-suppressrevision": "Examinar e restablir las revisions amagadas als administrators",
+       "right-suppressrevision": "Afichar, amagar e desamagar de revisions especificas de paginas per quin utilizaire que siá.",
+       "right-viewsuppressed": "Afichar las revisions amagadas per quin utilizaire que siá",
        "right-suppressionlog": "Veire los jornals privats",
        "right-block": "Blocar d'autres utilizaires en escritura",
        "right-blockemail": "Empachar un utilizaire de mandar de corrièrs electronics",
        "action-createpage": "crear de paginas",
        "action-createtalk": "crear de paginas de discussion",
        "action-createaccount": "crear aqueste compte d'utilizaire",
+       "action-history": "afichar l’istoric d'aquesta pagina",
        "action-minoredit": "marcar aqueste cambiament coma menor",
        "action-move": "tornar nomenar aquesta pagina",
        "action-move-subpages": "tornar nomenar aquesta pagina e sas sospaginas",
        "action-move-rootuserpages": "tornar nomenar las paginas de l’utilizaire de banca.",
+       "action-move-categorypages": "Renomenar de paginas de categoria",
        "action-movefile": "tornar nomenar aqueste fichièr",
        "action-upload": "importar aqueste fichièr",
        "action-reupload": "espotir aqueste fichièr existent",
        "recentchanges-label-plusminus": "La talha de la pagina a cambiat d'aqueste nombre d’octets.",
        "recentchanges-legend-heading": "'''Legenda :'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (veire tanben la [[Special:NewPages|lista de las paginas novèlas]]).",
-       "rcnotefrom": "Çaijós las modificacions efectuadas dempuèi lo <strong>$2</strong> (fins a <strong>$1</strong> afichats).",
+       "rcnotefrom": "Çaijós {{PLURAL:$5|la modificacion efectuada|las modificacions efectuadas}} dempuèi lo <strong>$3, $4</strong> (afichadas fins a <strong>$1</strong>).",
        "rclistfrom": "Afichar las modificacions novèlas dempuèi lo $3 $2",
        "rcshowhideminor": "$1 los cambiaments menors",
        "rcshowhideminor-show": "Afichar",
        "largefileserver": "La talha d'aqueste fichièr es superiora al maximum autorizat.",
        "emptyfile": "Lo fichièr que volètz importar sembla void. Aquò pòt èsser degut a una error dins lo nom del fichièr. Verificatz que desiratz vertadièrament copiar aqueste fichièr.",
        "windows-nonascii-filename": "Aqueste wiki supòrta pas los noms de fichièrs amb de caractèrs especials.",
-       "fileexists": "Un fichièr amb aqueste nom existís ja.\nMercé de verificar <strong>[[:$1]]</strong>.\nSètz segur de voler modificar aqueste fichièr ? [[$1|thumb]]",
+       "fileexists": "Un fichièr amb aqueste nom existís ja.\nMercé de verificar <strong>[[:$1]]</strong>\nse sètz pas segur{{GENDER:||a|}} que o volètz remplaçar. [[$1|thumb]]",
        "filepageexists": "La pagina de descripcion per aqueste fichièr ja es estada creada aicí <strong>[[:$1]]</strong>, mas cap de fichièr existís pas actualament jos aqueste nom.\nLo resumit qu'anatz especificar apareisserà pas sus la pagina de descripcion.\nPer o far, vos caldrà modificar la pagina manualament. [[$1|vinheta]]",
-       "fileexists-extension": "Un fichièr amb un nom pròchi existís ja : [[$2|thumb]]\n* Nom del fichièr d'importar : <strong>[[:$1]]</strong>\n* Nom del fichièr existent : <strong>[[:$2]]</strong>\nCausissètz-ne un autre.",
+       "fileexists-extension": "Un fichièr amb un nom pròchi existís ja : [[$2|thumb]]\n* Nom del fichièr d'importar : <strong>[[:$1]]</strong>\n* Nom del fichièr existent : <strong>[[:$2]]</strong>\nBenlèu que podètz utilizar un nom mai explicit ?",
        "fileexists-thumbnail-yes": "Lo fichièr sembla èsser un imatge en talha reducha ''(thumbnail)''. [[$1|thumb]]\nVerificatz lo fichièr <strong>[[:$1]]</strong>.\nSe lo fichièr verificat es lo meteis imatge (dins una resolucion melhora), es pas de besonh d’importar una version reducha.",
        "file-thumbnail-no": "Lo nom del fichièr comença per <strong>$1</strong>.\nEs possible que s’agisca d’una version reducha ''(miniatura)''.\nSe dispausatz del fichièr en resolucion nauta, importatz-lo, si que non cambiatz lo nom del fichièr.",
        "fileexists-forbidden": "Un fichièr amb aqueste nom existís ja e pòt pas èsser espotit.\nSe volètz totjorn importar aquel fichièr, mercé de tornar en arrièr e d'utilizar un nom novèl. [[File:$1|thumb|center|$1]]",
        "fileexists-shared-forbidden": "Un fichièr amb lo meteis nom existís ja dins la banca de donadas comuna.\nS'o volètz importar tornamai, tornatz en rèire e importatz-lo jos un autre nom. [[File:$1|thumb|center|$1]]",
        "file-exists-duplicate": "Aqueste fichièr es un doble {{PLURAL:$1|del fichièr seguent|dels fichièrs seguents}} :",
        "file-deleted-duplicate": "Un fichièr identic a aqueste ([[:$1]]) ja es estat suprimit. Vos caldriá verificar lo jornal de las supressions d'aqueste fichièr abans de la tornar telecargar.",
+       "file-deleted-duplicate-notitle": "Un fichièr identic a aqueste fichièr es ja estat suprimit amai lo títol. \nVos caldriá demandar a qualqu'un la possibilitat de verificar lo jornal d'aqueste fichièr suprimit per tal d'examinar la situacion  abans de l'importar tornarmai.",
        "uploadwarning": "Atencion !",
        "uploadwarning-text": "Modificatz la descripcion del fichièr e ensajatz tornarmai.",
        "savefile": "Salvar lo fichièr",
-       "uploadedimage": "«[[$1]]» copiat sul servidor",
-       "overwroteimage": "a importat una version novèla de « [[$1]] »",
        "uploaddisabled": "O planhèm, lo mandadís de fichièr es desactivat.",
        "copyuploaddisabled": "Mandadís de fichièr per URL desactivat.",
        "uploaddisabledtext": "L'impòrt de fichièrs cap al servidor es desactivat.",
        "license": "Licéncia&nbsp;:",
        "license-header": "Publicat jos licéncia(s)",
        "nolicense": "Cap de licéncia seleccionada",
+       "licenses-edit": "Modificar las opcions de licéncia",
        "license-nopreview": "(Previsualizacion impossibla)",
-       "upload_source_url": " (una URL valida e accessibla publicament)",
-       "upload_source_file": " (un fichièr sus vòstre ordenador)",
+       "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)",
+       "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 :",
        "imgfile": "fichièr",
        "filedelete-maintenance": "La supression e lo restabliment de fichièrs es temporàriament desactivada pendent la mantenença.",
        "filedelete-maintenance-title": "Impossible de suprimir lo fichièr",
        "mimesearch": "Recèrca per tipe MIME",
-       "mimesearch-summary": "Aquesta pagina especiala permet de cercar de fichièrs en foncion de lor tipe MIME. Entrada : tipe/sostipe, per exemple <code>image/jpeg</code>.",
+       "mimesearch-summary": "Aquesta pagina vos permet de filtrar los fichièrs en foncion de lor tipe MIME. Entrada : tipe_de_contengut/sostipe o tipe_de_contengut/*, per exemple <code>image/jpeg</code>.",
        "mimetype": "Tipe MIME :",
        "download": "telecargament",
        "unwatchedpages": "Paginas pas seguidas",
        "randomincategory": "Pagina a l'azard dins la categoria",
        "randomincategory-invalidcategory": "« $1 » es pas un nom de categoria valid.",
        "randomincategory-nopages": "I a pas cap de pagina dins [[:Category:$1]].",
-       "randomincategory-selectcategory": "Prene una pagina a l'azard dins la categoria : $1 $2.",
-       "randomincategory-selectcategory-submit": "Anar",
+       "randomincategory-category": "Categoria :",
+       "randomincategory-legend": "Pagina a l'azard dins la categoria",
        "randomredirect": "Una pagina de redireccion a l'azard",
        "randomredirect-nopages": "I a pas cap de redireccion dins l'espaci de nom « $1 ».",
        "statistics": "Estatisticas",
        "nmemberschanged": "$1 → $2 {{PLURAL:$2|membre|membres}}",
        "nrevisions": "$1 {{PLURAL:$1|revision|revisions}}",
        "nviews": "$1 {{PLURAL:$1|consultacion|consultacions}}",
-       "nimagelinks": "Utilisat sus $1 {{PLURAL:$1|pagina|paginas}}",
-       "ntransclusions": "Utilisat sus $1 {{PLURAL:$1|pagina|paginas}}",
+       "nimagelinks": "Utilizat sus $1 {{PLURAL:$1|pagina|paginas}}",
+       "ntransclusions": "Utilizat sus $1 {{PLURAL:$1|pagina|paginas}}",
        "specialpage-empty": "Aquesta pagina es voida.",
        "lonelypages": "Paginas orfanèlas",
        "lonelypagestext": "Las paginas seguentas son pas ligadas o enclusas a partir d’autras paginas de {{SITENAME}}.",
        "wantedpages-badtitle": "Títol invalid dins los resultats : $1",
        "wantedfiles": "Fichièrs desirats",
        "wantedfiletext-cat": "Los fichièrs seguents son utilizats, mas existisson pas localament. Se se tròban sus un depaus partejat, pòdon èsser listats aicí, mentre que sián, de fach, ja disponibles. Totes aqueles falses positius seràn <del>raiats</del>. Amai, las paginas qu'intègran de fichièrs qu'existisson pas son repertoriadas dins [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Los fichièrs seguents son utilizats mas existisson pas. Amai, las paginas qu'intègran los fichièrs qu'existisson pas son listats dins [[:$1]].",
        "wantedfiletext-nocat": "Los fichièrs seguents son utilizats, mas existisson pas localament. Se se tròban sus un depaus partejat, pòdon èsser listats aicí, mentre que sián, de fach, ja disponibles. Totes aqueles falses positius seràn <del>raiats</del>.",
+       "wantedfiletext-nocat-noforeign": "Los fichièrs seguents son utilizats mas existisson pas.",
        "wantedtemplates": "Modèls demandats",
        "mostlinked": "Paginas mai ligadas",
        "mostlinkedcategories": "Categorias mai utilizadas",
-       "mostlinkedtemplates": "Modèls mai utilizats",
+       "mostlinkedtemplates": "Paginas las mai inclusas",
        "mostcategories": "Articles utilizant mai de categorias",
        "mostimages": "Fichièrs mai utilizats",
        "mostinterwikis": "Paginas amb lo mai d'interwikis",
        "mywatchlist": "Lista de seguiment",
        "watchlistfor2": "Per $1 ($2)",
        "nowatchlist": "Vòstra lista de seguiment conten pas cap d'article.",
-       "watchlistanontext": "Per poder afichar o editar los elements de vòstra lista de seguiment, vos cal vos $1.",
+       "watchlistanontext": "Connectatz-vos per visualizar o modificar los elements de vòstra lista de seguiment.",
        "watchnologin": "Vos sètz pas identificat(ada)",
-       "addwatch": "Ajustar a la lista de seguiment",
+       "addwatch": "Apondre a la lista de seguiment",
        "addedwatchtext": "La pagina « [[:$1]] » es estada aponduda a vòstra [[Special:Watchlist|lista de seguiment]]. Las modificacions venentas d'aquesta pagina e de la pagina de discussion associada i seràn repertoriadas.",
+       "addedwatchtext-short": "La pagina « $1 » es estada aponduda a vòstra lista de seguiment.",
        "removewatch": "Suprimir de la lista de seguiment",
        "removedwatchtext": "La pagina « [[:$1]] » es estada levada de vòstra [[Special:Watchlist|lista de seguiment]].",
+       "removedwatchtext-short": "La pagina « $1 » es estada suprimida de vòstra lista de seguiment.",
        "watch": "Seguir",
        "watchthispage": "Seguir aquesta pagina",
        "unwatch": "Arrestar de seguir",
        "watchlist-details": "I a {{PLURAL:$1|$1 pagina|$1 paginas}} dins vòstra lista de seguiment, sens comptar las paginas de discussion.",
        "wlheader-enotif": "La notificacion per corrièr electronic es activada.",
        "wlheader-showupdated": "Las paginas que son estadas modificadas dempuèi vòstra darrièra visita son afichadas en '''gras'''.",
+       "wlnote": "Çaijós {{PLURAL:$1|figura la darrièra modificacion efectuada|figuran las <strong>$1</strong> darrièras modificacions efectuadas}} pendent {{PLURAL:$2|la darrièra ora|las <strong>$2</strong> darrièras oras}}, dempuèi $3, $4.",
        "wlshowlast": "Far veire las darrièras $1 oras, los darrièrs $2 jorns, o $3.",
        "watchlist-options": "Opcions de la lista de seguiment",
        "watching": "Seguit...",
        "exbeforeblank": "lo contengut abans blanquiment èra :'$1'",
        "delete-confirm": "Escafar «$1»",
        "delete-legend": "Escafar",
-       "historywarning": "'''Atencion :''' La pagina que s�tz a mand de suprimir a un istoric que conten aproximadament $1 {{PLURAL:$1|revision|revisions}} :",
+       "historywarning": "<strong>Atencion :</strong> la pagina que sètz a mand de suprimir a un istoric amb $1 {{PLURAL:$1|version|versions}} :",
        "confirmdeletetext": "Sètz a mand de suprimir una pagina o un fichièr, e mai totas sas versions anterioras istorizadas.\nConfirmatz qu'es plan çò que volètz far, que ne comprenètz las consequéncias e que fasètz aquò en acòrdi amb las [[{{MediaWiki:Policy-url}}|règlas intèrnas]].",
        "actioncomplete": "Accion efectuada",
        "actionfailed": "L’accion a fracassat",
        "delete-edit-reasonlist": "Modifica los motius de la supression",
        "delete-toobig": "Aquesta pagina dispausa d'un istoric important, depassant {{PLURAL:$1|revision|revisions}}.\nLa supression de talas paginas es estada limitada per evitar de perturbacions accidentalas de {{SITENAME}}.",
        "delete-warning-toobig": "Aquesta pagina dispausa d'un istoric important, depassant {{PLURAL:$1|revision|revisions}}.\nLa suprimir pòt perturbar lo foncionament de la banca de donada de {{SITENAME}}.\nD'efectuar amb prudéncia.",
+       "deleteprotected": "Podètz pas suprimir aquesta pagina perque es estada protegida.",
        "rollback": "Anullar las modificacions",
        "rollback_short": "Anullar",
        "rollbacklink": "anullar",
        "revertpage": "Anullacion de las modificacions de [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussion]]) cap a la darrièra version de [[User:$1|$1]]",
        "revertpage-nouser": "Revocacion de las modificacions per un utilizaire amagat a la darrièra version per {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Anullacion de las modificacions de $1 ; retorn a la version de $2.",
-       "sessionfailure-title": "La session capitèt mal",
+       "sessionfailure-title": "La sesilha a fracassat",
        "sessionfailure": "Vòstra sesilha de connexion sembla aver de problèmas ;\naquesta accion es estada anullada en prevencion d’un piratatge de sesilha.\nClicatz sus « Precedent » e tornatz cargar la pagina d’ont venètz, puèi ensajatz tornarmai.",
        "protectlogpage": "Istoric de las proteccions",
        "protectlogtext": "Aquí una lista de las modificacions de las proteccions de paginas.\nConsultatz la [[Special:ProtectedPages|lista de las paginas protegidas]] per la lista de las proteccions actualament operacionalas.",
        "autoblockid": "Blocatge automatic #$1",
        "block": "Blocar un utilizaire",
        "unblock": "Desblocar un utilizaire",
-       "blockip": "Blocar en escritura",
+       "blockip": "Blocar l’{{GENDER:$1|utilizaire|utilizaira}}",
        "blockip-legend": "Blocar en escritura",
        "blockiptext": "Utilizatz lo formulari çaijós per blocar l'accès a las modificacions a partir d'una adreça IP especifica o d'un nom d'utilizaire.\nUna tala mesura deu pas èsser presa pas que per empachar lo vandalisme e en acòrdi amb las [[{{MediaWiki:Policy-url}}|règlas intèrnas]].\nDonatz çaijós un motiu precís (per exemple en citant las paginas que son estadas vandalizadas).",
        "ipaddressorusername": "Adreça IP o nom d’utilizaire :",
        "ipb-unblock-addr": "Desblocar $1",
        "ipb-unblock": "Desblocar un compte d'utilizaire o una adreça IP",
        "ipb-blocklist": "Vejatz los blocatges existents",
-       "ipb-blocklist-contribs": "Contribucions per $1",
+       "ipb-blocklist-contribs": "Contribucions per {{GENDER:$1|$1}}",
        "unblockip": "Desblocar un utilizaire o una adreça IP",
        "unblockiptext": "Utilizatz lo formulari çaijós per restablir l'accès en escritura\na partir d'una adreça IP precedentament blocada.",
        "ipusubmit": "Suprimir aqueste blocatge",
        "movenotallowedfile": "Avètz pas la permission de desplaçar los fichièrs.",
        "cant-move-user-page": "Avètz pas la permission de tornar nomenar de paginas d'utilizaires raices sus aqueste wiki.",
        "cant-move-to-user-page": "Avètz pas la permission de tornar nomenar una pagina cap a una pagina d'utilizaire (a l'excepcion d'una sospagina).",
+       "cant-move-category-page": "Avètz pas la permission de renomenar las paginas de categorias.",
        "newtitle": "Títol novèl",
        "move-watch": "Seguir aquesta pagina",
        "movepagebtn": "Tornar nomenar l'article",
        "import": "Importar de paginas",
        "importinterwiki": "Impòrt interwiki",
        "import-interwiki-text": "Seleccionatz un wiki e un títol de pagina d'importar.\nLas datas de las versions e los noms dels editors seràn preservats.\nTotas las accions d’importacion interwiki son conservadas dins lo [[Special:Log/import|jornal d’impòrt]].",
-       "import-interwiki-source": "Wiki e pagina font :",
+       "import-interwiki-sourcewiki": "Wiki font :",
+       "import-interwiki-sourcepage": "Pagina font :",
        "import-interwiki-history": "Copiar totas las versions de l'istoric d'aquesta pagina",
        "import-interwiki-templates": "Enclure totes los modèls",
        "import-interwiki-submit": "Importar",
        "import-invalid-interwiki": "Impossible d'importar dempuèi lo wiki especificat.",
        "import-error-edit": "La pagina « $1 » es pas estada importada perque sètz pas autorizat a la modificar.",
        "import-error-create": "La pagina « $1 » es pas estada importada perque sètz pas autorizat a la crear.",
-       "import-error-invalid": "Pagina « $1 » es pas importada perque son nom es pas valid.",
+       "import-error-invalid": "Pagina « $1 » es pas importada perque lo nom amb lo qual seriá estada importada es pas valid sus aqueste wiki.",
        "import-options-wrong": "{{PLURAL:$2|Marrida opcion|Marridas opcions}} : <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "La pagina raiç provesida es un títol invalid.",
        "import-rootpage-nosubpage": "L'espaci de noms « $1 » de la pagina raiç autoriza pas las sospaginas.",
        "importlogpage": "Istoric de las importacions de paginas",
        "importlogpagetext": "Impòrts administratius de paginas amb l’istoric a partir dels autres wikis.",
        "import-logentry-upload": "a importat (telecargament) [[$1]]",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|version|versions}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revision importada|revisions importadas}}",
        "import-logentry-interwiki": "a importat (transwiki) $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|version|versions}} dempuèi $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revision importada|revisions importadas}} dempuèi $2",
        "javascripttest": "Tèst de JavaScript",
        "javascripttest-title": "Execucion dels tèsts $1",
        "javascripttest-pagetext-noframework": "Aquesta pagina es reservada per l'execucion dels tèsts JavaScript.",
        "newimages-summary": "Aquesta pagina especiala aficha los darrièrs fichièrs importats.",
        "newimages-legend": "Filtre",
        "newimages-label": "Nom del fichièr (o una partida d'aqueste) :",
+       "newimages-showbots": "Afichar los impòrts per de robòts",
        "noimages": "Cap d'imatge d'afichar pas.",
        "ilsubmit": "Cercar",
        "bydate": "per data",
        "scarytranscludetoolong": "[L’URL es tròp longa]",
        "deletedwhileediting": "'''Atencion''' : aquesta pagina es estada suprimida aprèp qu'avètz començat de la modificar !",
        "confirmrecreate": "L'utilizaire [[User:$1|$1]] ([[User talk:$1|talk]]) a suprimit aquesta pagina, alara que l'aviatz començat d'editar, pel motiu seguent:\n: ''$2''\nConfirmatz que desiratz tornar crear aqueste article.",
+       "confirmrecreate-noreason": "L'utilizaire [[User:$1|$1]] ([[User talk:$1|Discussion]]) a suprimit aquesta pagina, mentre qu'aviatz començat de la modificar. Confirmatz que desiratz tornar crear aquesta pagina.",
        "recreate": "Tornar crear",
        "confirm_purge_button": "Confirmar",
        "confirm-purge-top": "Volètz refrescar aquesta pagina (purgar l'escondedor) ?",
        "autosumm-replace": "Resumit automatic : contengut remplaçat per « $1 ».",
        "autoredircomment": "Redireccion cap a [[$1]]",
        "autosumm-new": "Creacion de la pagina amb « $1 »",
+       "autosumm-newblank": "Pagina voida creada",
        "size-bytes": "$1 o",
        "size-kilobytes": "$1 Ko",
        "size-megabytes": "$1 Mo",
        "watchlistedit-raw-done": "Vòstra lista de seguiment es estada mesa a jorn.",
        "watchlistedit-raw-added": "{{PLURAL:$1|Una pagina es estada aponduda|$1 paginas son estadas apondudas}} :",
        "watchlistedit-raw-removed": "{{PLURAL:$1|Una pagina es estada levada|$1 paginas son estadas levadas}} :",
+       "watchlistedit-clear-title": "Lista de seguiment voidada",
+       "watchlistedit-clear-legend": "Escafar la lista de seguiment",
+       "watchlistedit-clear-explain": "Totes los títols seràn suprimits de vòstra lista de seguiment",
+       "watchlistedit-clear-titles": "Títols :",
+       "watchlistedit-clear-submit": "Escafar la lista de seguiment (aquò es permanent !)",
+       "watchlistedit-clear-done": "Vòstra lista de seguiment es estada escafada.",
+       "watchlistedit-clear-removed": "{{PLURAL:$1|Un títol es estat levat|$1 títols son estats levats}} :",
+       "watchlistedit-too-many": "I a tròp de paginas d'afichar aicí.",
+       "watchlisttools-clear": "Escafar la lista de seguiment",
        "watchlisttools-view": "Lista de seguiment",
        "watchlisttools-edit": "Veire e modificar la lista de seguiment",
        "watchlisttools-raw": "Modificar la lista (mòde brut)",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discussion]])",
        "unknown_extension_tag": "Balisa d'extension « $1 » desconeguda",
        "duplicate-defaultsort": "Atencion : La clau de triada per defaut « $2 » espotís la mai recenta « $1 ».",
+       "duplicate-displaytitle": "<strong>Atencion :</strong> Lo títol d'afichatge «$2» remplaça l'ancian títol d'afichatge «$1».",
        "version": "Version",
        "version-extensions": "Extensions installadas",
+       "version-skins": "Abilhatges installats",
        "version-specialpages": "Paginas especialas",
        "version-parserhooks": "Extensions del parser",
        "version-variables": "Variablas",
        "version-antispam": "Prevencion del spam",
-       "version-skins": "Abilhatges",
        "version-other": "Divèrs",
        "version-mediahandlers": "Supòrts mèdia",
        "version-hooks": "Croquets",
        "version-hook-name": "Nom del croquet",
        "version-hook-subscribedby": "Definit per",
        "version-version": "(Version $1)",
+       "version-no-ext-name": "[sens nom]",
        "version-license": "Licéncia de MediaWiki",
        "version-ext-license": "Licéncia",
        "version-ext-colheader-name": "Extensions",
+       "version-skin-colheader-name": "Aparéncia",
+       "version-ext-colheader-version": "Version",
        "version-ext-colheader-license": "Licéncia",
        "version-ext-colheader-description": "Descripcion",
        "version-ext-colheader-credits": "Autors",
        "htmlform-no": "Non",
        "htmlform-yes": "Òc",
        "htmlform-chosen-placeholder": "Causir una opcion",
+       "htmlform-cloner-create": "Apondre encara",
+       "htmlform-cloner-delete": "Suprimir",
+       "htmlform-cloner-required": "Una valor al mens es obligatòria.",
        "sqlite-has-fts": "$1 amb recèrca en tèxte integral suportada",
        "sqlite-no-fts": "$1 sens recèrca en tèxte integral suportada",
        "logentry-delete-delete": "$1 {{GENDER:$2|a suprimit}} la pagina $3",
        "logentry-rights-rights": "$1 {{GENDER:$2|a modificat}} l'apartenéncia al grop per $3 de $4 a $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|a modificat}} l'apartenéncia al grop per $3",
        "logentry-rights-autopromote": "$1 {{GENDER:$2|es estat promolgut}} automaticament de $4 a $5",
+       "logentry-upload-upload": "$1 {{GENDER:$2|a mandat}} $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|a telecargat}} una novèla version de $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|a telecargat}} $3",
        "rightsnone": "(cap)",
        "feedback-subject": "Subjècte :",
        "feedback-message": "Messatge :",
        "expand_templates_remove_nowiki": "Suprimís los marcadors <nowiki> dins lo resultat",
        "expand_templates_generate_xml": "Veire l'arborescéncia XML",
        "expand_templates_generate_rawhtml": "Afichar lo HTML brut",
-       "expand_templates_preview": "Previsualizacion"
+       "expand_templates_preview": "Previsualizacion",
+       "pagelanguage": "Selector de lenga de la pagina",
+       "pagelang-name": "Pagina",
+       "pagelang-language": "Lenga",
+       "pagelang-use-default": "Utilizar la lenga per defaut",
+       "pagelang-select-lang": "Seleccionar la lenga",
+       "right-pagelang": "Cambiar la lenga de la pagina",
+       "action-pagelang": "cambiar la lenga de la pagina",
+       "log-name-pagelang": "Traçar los cambiaments de lenga",
+       "log-description-pagelang": "Aquò es un jornal dels cambiaments dins las lengas de las paginas.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|a cambiat}} la lenga de la pagina $3 de $4 a $5.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (activat)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''desactivat''')"
 }
index b64b5e6..074b9c7 100644 (file)
        "talkpagelinktext": "କଥାଭାଷା",
        "specialpage": "ବିଶେଷ ପୃଷ୍ଠା",
        "personaltools": "ନିଜର ଟୁଲ",
-       "postcomment": "ନୂଆ ଭାଗ",
        "articlepage": "ସୂଚୀ ପୃଷ୍ଠାଟି ଦେଖାଇବେ",
        "talk": "ଆଲୋଚନା",
        "views": "ଦେଖା",
        "externaldberror": "ବୋଧ ହୁଏ ଚିହ୍ନଟ ଡାଟାବେସ ଭୁଲଟିଏ ହୋଇଥିଲା ବା ଆପଣଙ୍କୁ ନିଜର ବାହାର ଖାତା ଅପଡେଟ କରିବା ନିମନ୍ତେ ଅନୁମତି ମିଳିନାହିଁ ।",
        "login": "ଲଗ-ଇନ (Log in)",
        "nav-login-createaccount": "ଲଗ ଇନ /ନୂଆ ଖାତା ଖୋଲନ୍ତୁ",
-       "loginprompt": "{{SITENAME}}ରେ ଲଗ ଇନ କରିବାପାଇଁ ଆପଣଙ୍କୁ '''କୁକି''' ସଚଳ କରିବାକୁ ପଡ଼ିବ ।",
        "userlogin": "ଲଗ ଇନ /ନୂଆ ଖାତା ଖୋଲନ୍ତୁ",
        "userloginnocreate": "ଲଗ-ଇନ (Log in)",
        "logout": "ଲଗଆଉଟ",
        "searchprofile-advanced-tooltip": "ନିଜେ ତିଆରିକରିହେବା ଭଳି ନେମସ୍ପେସରେ ଖୋଜିବେ",
        "search-result-size": "$1 ({{PLURAL:$2|1 ଶବ୍ଦ|$2 ଶବ୍ଦ}})",
        "search-result-category-size": "{{PLURAL:$1|ଜଣେ ସଭ୍ୟ|$1 ଜଣ ସଭ୍ୟ}} ({{PLURAL:$2|ଗୋଟିଏ ଶ୍ରେଣୀy|$2ଟି ଶ୍ରେଣୀ ସମୂହ}}, {{PLURAL:$3|ଗୋଟିଏ ଫାଇଲ|$3ଟି ଫାଇଲ}})",
-       "search-result-score": "ପ୍ରାସଙ୍ଗିକତା: $1%",
        "search-redirect": "($1 କୁ ଆଗକୁ ବଢେଇନିଅ )",
        "search-section": "(ଭାଗ $1)",
        "search-suggest": "ଆପଣ $1 ଭାବି ଖୋଜିଥିଲେ କି?",
        "rcshowhideminor": "ଛୋଟମୋଟ ବଦଳ $1",
        "rcshowhideminor-show": "ଦେଖାଇବେ",
        "rcshowhideminor-hide": "ଲୁଚାଇବେ",
-       "rcshowhidebots": "ସà­\8dà­±à­\9fà¬\82à¬\9aାଳà¬\95&nbsp;(Bot)&nbsp;ଦà­\8dୱାରା&nbsp;ସମ୍ପାଦନା $1",
+       "rcshowhidebots": "ସà­\8dà­±à­\9fà¬\82à¬\9aାଳà¬\95&nbsp;(Bot)&nbsp;ର&nbsp;ସମ୍ପାଦନା $1",
        "rcshowhidebots-show": "ଦେଖାଇବେ",
        "rcshowhidebots-hide": "ଲୁଚାଇବେ",
        "rcshowhideliu": "ପଞ୍ଜୀକୃତ ସଭ୍ୟ $1",
        "uploadwarning": "ଅପଲୋଡ଼ ଚେତାବନୀ",
        "uploadwarning-text": "ତଳେ ଥିବା ଫାଇଲର ବିବରଣୀ ବଦଳାଇ ଆଉ ଥରେ ଚେଷ୍ଟା କରନ୍ତୁ ।",
        "savefile": "ଫାଇଲ ସାଇତିବା",
-       "uploadedimage": "\"[[$1]]\" ଅପଲୋଡ କରାଗଲା",
-       "overwroteimage": "\"[[$1]]\"ର ନୂଆ ସଙ୍କଳନଟିଏ ଅପଲୋଡ଼ କରାଗଲା",
        "uploaddisabled": "ଅପଲୋଡ଼ କରିବା ଅଚଳ କରାଯାଇଅଛି ।",
        "copyuploaddisabled": "URL ଦେଇ ଅପଲୋଡ଼ କରିବାକୁ ଅଚଳ କରାଯାଇଅଛି ।",
        "uploaddisabledtext": "ଫାଇଲ ଅପଲୋଡ଼  ଅଚଳ କରାଯାଇଅଛି ।",
        "unusedtemplateswlh": "ଅନ୍ୟ ସଂଯୋଗ",
        "randompage": "ଯାହିତାହି ପୃଷ୍ଠା",
        "randompage-nopages": "ତଳେ ଥିବା {{PLURAL:$2|ନେମସ୍ପେସ|ନେମସ୍ପେସ}}: $1ରେ ଗୋଟିଏ ବି ପୃଷ୍ଠା ନାହିଁ ।",
-       "randomincategory-selectcategory-submit": "ଯାଆନ୍ତୁ",
        "randomredirect": "ଯାହିତାହି ପୁନପ୍ରେରଣ",
        "randomredirect-nopages": "\"$1\" ନାମରେ ଗୋଟିଏ ବି ପୁନପ୍ରେରଣ ନାହିଁ ।",
        "statistics": "ହିସାବ",
        "watchlist-details": "ଆପଣଙ୍କ ଦେଖଣା ତାଲିକାରେ {{PLURAL:$1|$1 ଟି ପୃଷ୍ଠା|$1 ଟି ପୃଷ୍ଠା}} ଅଛି, ଆଲୋଚନା ପୃଷ୍ଠାମାନଙ୍କୁ ଅଲଗା ଗଣାଯାଇନାହିଁ ।",
        "wlheader-enotif": "ଇମେଲ ସୂଚନା ସଚଳ କରାଗଲା ।",
        "wlheader-showupdated": "ଆପଣ ଶେଷଥର ଦେଖିଥିବା ପୃଷ୍ଠାଗୁଡ଼ିକ '''ମୋଟା ଅକ୍ଷର'''ରେ ଦେଖାଯାଉଅଛି ।",
+       "wlnote": "$3, $4 ସୁଦ୍ଧା ବିଗତ {{PLURAL:$2|ଘଣ୍ଟେ ଭିତରେ|'''$2''' ଘଣ୍ଟା ଭିତରେ}} ଘଟିଥିବା {{PLURAL:$1|ଶେଷ ବଦଳଟି ଅଛି|ଶେଷ '''$1''' ଟି ବଦଳ}} ତଳେ ଦିଆଯାଇଛି ।",
        "wlshowlast": "ଶେଷ $1 ଘଣ୍ଟା $2 ଦିନ $3 ଦେଖାଇବେ",
        "watchlist-options": "ଦେଖଣା ବିକଳ୍ପସବୁ",
        "watching": "ଦେଖୁଛି...",
        "import": "ପୃଷ୍ଠା ଆମଦାନି କରିବେ",
        "importinterwiki": "ଟ୍ରାନ୍ସଉଇକି ଈମ୍ପୋର୍ଟ",
        "import-interwiki-text": "ଏକ ଉଇକି ଓ ପୃଷ୍ଠା ନାମ ଆମଦାନି କରିବା ନିମନ୍ତେ ଦିଅନ୍ତୁ ।\nସଂସ୍କରଣ ତାରିଖ ଓ ସମ୍ପାଦକଙ୍କ ନାମ ସାଇତା ହୋଇ ରହିବ ।\nଅନ୍ତଉଇକି ଆମଦାନି କାମସବୁ [[Special:Log/import|ଆମଦାନି ଇତିହାସ]]ରେ ସାଇଟ ହୋଇ ରହିଛି ।",
-       "import-interwiki-source": "ମୂଳ ଉଇକି/ପୃଷ୍ଠା",
        "import-interwiki-history": "ଏହି ପୃଷ୍ଠା ନିମନ୍ତେ ସବୁଯାକ ସଂସ୍କରଣ ଇତିହାସ ନକଲ କରିନିଅନ୍ତୁ",
        "import-interwiki-templates": "ସବୁଯାକ ଛାଞ୍ଚ ଏହା ଭିତରେ ରଖିବେ",
        "import-interwiki-submit": "ଆମଦାନୀ",
        "pageinfo-length": "ପୃଷ୍ଠା ଲମ୍ବ(ବାଇଟରେ)",
        "pageinfo-article-id": "ପୃଷ୍ଠା ଆଇଡ଼ି",
        "pageinfo-language": "ପୃଷ୍ଠା ବିଷୟବସ୍ତୁର ଭାଷା",
-       "pageinfo-robot-policy": "ସ୍ୱୟଂଚାଳକ (bot) ଦ୍ୱାରା ସୂଚୀ ନିର୍ମିତ",
+       "pageinfo-robot-policy": "ସ୍ୱୟଂଚାଳକ&nbsp;(Bot) ଦ୍ୱାରା ସୂଚୀ ନିର୍ମାଣ",
        "pageinfo-robot-index": "ଅନୁମୋଦିତ",
        "pageinfo-robot-noindex": "ଅନୁନମୋଦିତ",
        "pageinfo-views": "ଦେଖଣା ସଂଖ୍ୟା",
        "duplicate-defaultsort": "'''ସୂଚନା:''' ଆପେଆପେ କାମକରୁଥିବା \"$2\" ଆଗରୁ ଆପେ ଆପେ ସଜାଡୁଥିବା \"$1\"କୁ ବନ୍ଦ କରିଦେଇଛି ।",
        "version": "ସଂସ୍କରଣ",
        "version-extensions": "ଇନଷ୍ଟଲ କରାହୋଇଥିବା ଏକ୍ସଟେନସନସବୁ",
+       "version-skins": "ବହିରାବରଣ",
        "version-specialpages": "ବିଶେଷ ପୃଷ୍ଠା",
        "version-parserhooks": "ପାର୍ସର ହୁକ",
        "version-variables": "ଚଳ",
        "version-antispam": "ଅଦରକାରୀ ମେଲ ଅଟକ",
-       "version-skins": "ବହିରାବରଣ",
        "version-other": "ବାକି",
        "version-mediahandlers": "ମିଡ଼ିଆ ହ୍ୟାଣ୍ଡଲର",
        "version-hooks": "ହୁକ",
index 492a1f4..9ff15c2 100644 (file)
        "talkpagelinktext": "Ныхас",
        "specialpage": "Сæрмагонд фарс",
        "personaltools": "Хион фæрæзтæ",
-       "postcomment": "Ног хай",
        "articlepage": "Фенын уац",
        "talk": "Тæрхон",
        "views": "Æркæстытæ",
        "externaldberror": "Кæнæ аутентификацийы рарддоны рæдыд æрцыдис, кæнæ та дæуæн нæй бар снæуæг кæнын дæ æддаг аккаунт.",
        "login": "Бахизын",
        "nav-login-createaccount": "Бахизын / срегистраци кæнын",
-       "loginprompt": "Дæ cookies хъуамæ иу уой цæмæй дæ бон уа бахизын {{grammar:allative|{{SITENAME}}}}.",
        "userlogin": "Бахизын / регистраци кæнын",
        "userloginnocreate": "Бахизын",
        "logout": "Рахизын",
        "minlength1": "Файлы номы хъуамæ æппынкъаддæр иу дамгъæ уа.",
        "badfilename": "Файлы ном ивд æрцыд {{grammar:allative|«$1»}}.",
        "savefile": "Файл бавæрын",
-       "uploadedimage": "бавгæдта \"[[$1]]\"",
        "uploadvirus": "Файлы ис вирус! \nЛæмбынæг: $1",
        "watchthisupload": "Ацы файлмæ цæст æрдарын",
        "upload-success-subj": "Æвгæд æрцыд",
        "watchthispage": "Цæст дарын ацы фарсмæ",
        "unwatch": "Нал дарын цæст",
        "watchlist-details": "{{PLURAL:$1|$1 фарсмæ|$1 фарсмæ}} дæ цæст дарыс, тæрхоны фæрстæ нæ нымайгæйæ.",
+       "wlnote": "Дæлæ афæстаг '''$2 сахаты дæргъы''' цы $1 {{PLURAL:$1|ивддзинад|ивддзинады}} æрцыди.",
        "wlshowlast": "Фæстæг $1 сахаты, $2 боны дæргъы; $3.",
        "watchlist-options": "Цæстдард рæгъы фадæттæ",
        "watching": "Цæстдард фæрсты номхыгъдмæ афтауын...",
index d66eb12..868b4e2 100644 (file)
        "permalink": "ਪੱਕੀ ਲਿੰਕ",
        "print": "ਛਾਪੋ",
        "view": "ਵੇਖੋ",
+       "view-foreign": "$1 ਉੱਤੇ ਵੇਖੋ",
        "edit": "ਸੋਧੋ",
+       "edit-local": "ਲੋਕਲ ਵੇਰਵਾ ਸੋਧੋ",
        "create": "ਬਣਾਓ",
        "editthispage": "ਇਹ ਸਫ਼ਾ ਸੋਧੋ",
        "create-this-page": "ਇਹ ਸਫ਼ਾ ਬਣਾਓ",
        "talkpagelinktext": "ਗੱਲ-ਬਾਤ",
        "specialpage": "ਖ਼ਾਸ ਸਫ਼ਾ",
        "personaltools": "ਨਿੱਜੀ ਸੰਦ",
-       "postcomment": "ਨਵਾਂ ਭਾਗ",
        "articlepage": "ਸਮੱਗਰੀ ਸਫ਼ਾ ਵੇਖੋ",
        "talk": "ਚਰਚਾ",
        "views": "ਵਿਊ",
        "hidetoc": "ਓਹਲੇ",
        "collapsible-collapse": "ਸਮੇਟੋ",
        "collapsible-expand": "ਫੈਲਾਓ",
+       "confirmable-yes": "ਹਾਂ",
+       "confirmable-no": "ਨਹੀਂ",
        "thisisdeleted": "$1 ਵੇਖੋ ਜਾਂ ਮੁੜ ਸਟੋਰ ਕਰੋ",
        "viewdeleted": "$1 ਵੇਖਣੀਆਂ ਹਨ?",
        "restorelink": "{{PLURAL:$1|ਇਕ ਮਿਟਾਈ ਹੋਈ ਸੋਧ|$1 ਮਿਟਾਈਆਂ ਹੋਈਆਂ ਸੋਧਾਂ}}",
        "externaldberror": "ਜਾਂ ਤਾਂ ਪ੍ਰਮਾਣਕੀ ਡਾਟਾਬੇਸ ਦੋਸ਼ ਆਇਆ ਹੈ ਜਾਂ ਤੁਹਾਨੂੰ ਆਪਣੇ ਬਾਹਰੀ ਖਾਤੇ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ।",
        "login": "ਲਾਗਇਨ",
        "nav-login-createaccount": "ਲਾਗਇਨ/ਖਾਤਾ ਬਣਾਓ",
-       "loginprompt": "ਤੁਹਾਨੂੰ {{SITENAME}} ’ਤੇ ਲਾਗਇਨ ਕਰਨ ਲਈ ਕੂਕੀਸ ਯੋਗ ਕਰਨੇ ਜ਼ਰੂਰੀ ਹਨ।",
        "userlogin": "ਲਾਗਇਨ/ਖਾਤਾ ਬਣਾਓ",
        "userloginnocreate": "ਲਾਗਇਨ",
        "logout": "ਲਾਗ ਆਉਟ",
        "edit-gone-missing": "ਇਹ ਸਫ਼ਾ ਅੱਪਡੇਟ ਨਹੀਂ ਹੋ ਸਕਿਆ।\nਜਾਪਦਾ ਹੈ ਕਿ ਇਹ ਹਟਾਇਆ ਜਾ ਚੁੱਕਾ ਹੈ।",
        "edit-conflict": "ਸੋਧ ਤਕਰਾਰ",
        "edit-no-change": "ਤੁਹਾਡੀ ਸੋਧ ਨਜ਼ਰਅੰਦਾਜ਼ ਕਰ ਦਿੱਤੀ ਗਈ ਹੈ ਕਿਉਂਕਿ ਲਿਖਤ ਵਿਚ ਕੋਈ ਤਬਦੀਲੀ ਨਹੀਂ ਕੀਤੀ ਗਈ।",
+       "postedit-confirmation-created": "ਸਫ਼ਾ ਬਣਾਇਆ ਗਿਆ।",
+       "postedit-confirmation-restored": "ਸਫ਼ੇ ਨੂੰ ਮੁੜ-ਸਟੋਰ ਕੀਤਾ ਗਿਆ।",
        "postedit-confirmation-saved": "ਤੁਹਾਡੀ ਸੋਧ ਸਾਂਭੀ ਗਈ ਹੈ।",
        "edit-already-exists": "ਨਵਾਂ ਸਫ਼ਾ ਨਹੀਂ ਬਣਾਇਆ ਜਾ ਸਕਿਆ।\nਇਹ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ।",
        "defaultmessagetext": "ਮੂਲ ਸੰਦੇਸ਼ ਲਿਖਤ",
        "searchprofile-advanced-tooltip": "ਆਪਣੀਆਂ ਬਣਾਈਆਂ ਨਾਂ-ਥਾਂਵਾਂ ਵਿੱਚ ਖੋਜੋ",
        "search-result-size": "$1 ({{PLURAL:$2|1 ਸ਼ਬਦ|$2 ਸ਼ਬਦ}})",
        "search-result-category-size": "{{PLURAL:$1|1 ਮੈਂਬਰ|$1 ਮੈਂਬਰ}} ({{PLURAL:$2|1 ਉਪਸ਼੍ਰੇਣੀ|$2 ਉਪਸ਼੍ਰੇਣੀਆਂ}}, {{PLURAL:$3|1 ਫ਼ਾਈਲ|$3 ਫ਼ਾਈਲਾਂ}})",
-       "search-result-score": "ਸਹੀ: $1%",
        "search-redirect": "($1 ਰੀਡਿਰੈਕਟ)",
        "search-section": "(ਹਿੱਸਾ $1)",
        "search-suggest": "ਕੀ ਤੁਹਾਡਾ ਮਤਲਬ ਸੀ: $1",
        "rcnotefrom": "'''$2''' ਤੱਕ ('''$1''' ਤੱਕ ਦਿੱਸਦੇ) ਬਦਲਾਵ ਹੇਠ ਦਿੱਤੀਆਂ ਹਨ।",
        "rclistfrom": "$3 $2 ਤੋਂ ਸ਼ੁਰੂ ਕਰਕੇ ਨਵੀਆਂ ਸੋਧਾਂ ਵਖਾਓ",
        "rcshowhideminor": "ਛੋਟੀਆਂ ਤਬਦੀਲੀਆਂ $1",
+       "rcshowhideminor-show": "ਵੇਖੋ",
+       "rcshowhideminor-hide": "ਓਹਲੇ",
        "rcshowhidebots": "$1 ਬੌਟ",
+       "rcshowhidebots-show": "ਵੇਖੋ",
+       "rcshowhidebots-hide": "ਓਹਲੇ",
        "rcshowhideliu": "$1 ਦਾਖ਼ਲ ਹੋਏ ਵਰਤੋਂਕਾਰ",
+       "rcshowhideliu-show": "ਵੇਖੋ",
+       "rcshowhideliu-hide": "ਓਹਲੇ",
        "rcshowhideanons": "$1 ਗੁਮਨਾਮ ਵਰਤੋਂਕਾਰ",
+       "rcshowhideanons-show": "ਵੇਖੋ",
+       "rcshowhideanons-hide": "ਓਹਲੇ",
        "rcshowhidepatr": "ਜਾਂਚੀਆਂ ਹੋਈਆਂ ਤਬਦੀਲੀਆਂ $1",
+       "rcshowhidepatr-show": "ਵੇਖੋ",
+       "rcshowhidepatr-hide": "ਓਹਲੇ",
        "rcshowhidemine": "ਮੇਰੀਆਂ ਤਬਦੀਲੀਆਂ  $1",
+       "rcshowhidemine-show": "ਵੇਖੋ",
+       "rcshowhidemine-hide": "ਓਹਲੇ",
        "rclinks": "ਪਿਛਲੇ $2 ਦਿਨਾਂ ਵਿੱਚ ਹੋਈਆਂ $1 ਤਬਦੀਲੀਆਂ ਵਖਾਓ<br /> $3",
        "diff": "ਫ਼ਰਕ",
        "hist": "ਅਤੀਤ",
        "uploadwarning": "ਅੱਪਲੋਡ ਚਿਤਾਵਨੀ",
        "uploadwarning-text": "ਕਿਰਪਾ ਕਰਕੇ ਹੇਠ ਦਿੱਤਾ ਫ਼ਾਈਲ ਵੇਰਵਾ ਬਦਲੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।",
        "savefile": "ਫ਼ਾਈਲ ਸਾਂਭੋ",
-       "uploadedimage": "\"[[$1]]\" ਅੱਪਲੋਡ ਕੀਤੀ",
-       "overwroteimage": "\"[[$1]]\" ਦਾ ਨਵਾਂ ਰੂਪ ਅੱਪਲੋਡ ਕਰੋ",
        "uploaddisabled": "ਅੱਪਲੋਡ ਆਯੋਗ ਹੈ",
        "copyuploaddisabled": "URL ਰਾਹੀਂ ਅੱਪਲੋਡ ਰੋਕੇ ਹੋਏ ਹਨ।",
        "uploaddisabledtext": "ਫ਼ਾਈਲਾਂ ਦੇ ਅੱਪਲੋਡ ਰੋਕੇ ਹੋਏ ਹਨ।",
        "nolicense": "ਕੁਝ ਵੀ ਚੁਣਿਆ",
        "license-nopreview": "(ਝਲਕ ਉਪਲੱਬਧ ਨਹੀਂ)",
        "upload_source_file": " (ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਉੱਤੇ ਇੱਕ ਫਾਇਲ)",
+       "listfiles-delete": "ਹਟਾਓ",
        "listfiles_search_for": "ਇਸ ਮੀਡੀਆ ਨਾਂ ਨੂੰ ਖੋਜੋ:",
        "imgfile": "ਫ਼ਾਈਲ",
        "listfiles": "ਫ਼ਾਈਲਾਂ ਦੀ ਸੂਚੀ",
        "listfiles_size": "ਆਕਾਰ",
        "listfiles_description": "ਵੇਰਵਾ",
        "listfiles_count": "ਵਰਜਨ",
+       "listfiles-latestversion": "ਮੌਜੂਦਾ ਵਰਜਨ",
        "listfiles-latestversion-yes": "ਹਾਂ",
        "listfiles-latestversion-no": "ਨਹੀਂ",
        "file-anchor-link": "ਫ਼ਾਈਲ",
        "randomincategory": "ਸ਼੍ਰੇਣੀ ਵਿਚਲਾ ਰਲ਼ਵਾਂ ਸਫ਼ਾ",
        "randomincategory-invalidcategory": "\"$1\" ਕੋਈ ਸਹੀ ਸ਼੍ਰੇਣੀ ਦਾ ਨਾਂ ਨਹੀਂ ਹੈ।",
        "randomincategory-nopages": "[[:Category:$1|$1]] ਸ਼੍ਰੇਣੀ ਵਿਚ ਕੋਈ ਸਫ਼ਾ ਨਹੀਂ ਹੈ।",
-       "randomincategory-selectcategory-submit": "ਜਾਓ",
        "randomredirect": "ਰਲ਼ਵਾਂ ਰੀਡਿਰੈਕਟ",
        "statistics": "ਅੰਕੜੇ",
        "statistics-header-pages": "ਸਫ਼ਾ ਅੰਕੜੇ",
        "shortpages": "ਛੋਟੇ ਸਫ਼ੇ",
        "longpages": "ਲੰਮੇ ਸਫ਼ੇ",
        "protectedpages": "ਸੁਰੱਖਿਅਤ ਸਫ਼ੇ",
+       "protectedpages-page": "ਸਫ਼ਾ",
+       "protectedpages-expiry": "ਮਿਆਦ",
+       "protectedpages-reason": "ਕਾਰਨ",
+       "protectedpages-unknown-timestamp": "ਅਣਜਾਣ",
+       "protectedpages-unknown-performer": "ਅਣਜਾਣ ਯੂਜ਼ਰ",
        "protectedtitles": "ਸੁਰੱਖਿਅਤ ਸਿਰਲੇਖ",
        "listusers": "ਯੂਜ਼ਰ ਲਿਸਟ",
        "listusers-editsonly": "ਸਿਰਫ਼ ਸੋਧਾਂ ਵਾਲੇ ਵਰਤੋਂਕਾਰ ਵਿਖਾਓ",
        "listgrouprights-removegroup-all": "ਸਾਰੇ ਸਮੂਹ ਹਟਾਓ",
        "listgrouprights-addgroup-self-all": "ਆਪਣੇ ਖਾਤੇ ਵਿਚ ਸਾਰੇ ਸਮੂਹ ਜੋੜੋ",
        "listgrouprights-removegroup-self-all": "ਆਪਣੇ ਖਾਤੇ ਤੋਂ ਸਾਰੇ ਸਮੂਹ ਹਟਾਓ",
+       "trackingcategories-nodesc": "ਕੋਈ  ਵੇਰਵਾ ਉਪਲੱਬਧ ਨਹੀਂ।",
        "mailnologin": "ਭੇਜਣ ਲਈ ਕੋਈ ਪਤਾ ਨਹੀਂ",
        "mailnologintext": "ਦੂਜੇ ਵਰਤੋਂਕਾਰਾਂ ਨੂੰ ਈ-ਮੇਲ ਭੇਜਣ ਲਈ ਤੁਹਾਨੂੰ [[Special:UserLogin|ਦਾਖ਼ਲ]] ਹੋਣਾ ਪਵੇਗਾ ਅਤੇ ਆਪਣੀਆਂ [[Special:Preferences|ਪਸੰਦਾਂ]] ਵਿਚ ਇੱਕ ਸਹੀ ਈ-ਮੇਲ ਪਤਾ ਦੇਣਾ ਪਵੇਗਾ।",
        "emailuser": "ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਈ-ਮੇਲ ਭੇਜੋ",
        "notanarticle": "ਕੋਈ ਸਮੱਗਰੀ ਸਫ਼ਾ ਨਹੀਂ ਹੈ",
        "notvisiblerev": "ਇੱਕ ਵੱਖਰੇ ਮੈਂਬਰ ਦੀ ਬਣਾਈ ਆਖ਼ਰੀ ਰੀਵਿਜ਼ਨ ਮਿਟਾਈ ਜਾ ਚੁੱਕੀ ਹੈ",
        "watchlist-details": "ਗੱਲ-ਬਾਤ ਸਫ਼ੇ ਨਾ ਗਿਣਦੇ ਹੋਏ, ਤੁਹਾਡੀ ਨਿਗਰਾਨੀ-ਸੂਚੀ ਵਿਚ{{PLURAL:$1|$1 ਸਫ਼ਾ ਹੈ|$1 ਸਫ਼ੇ ਹਨ}}।",
+       "wlnote": "$3, $4 ਮੁਤਾਬਕ ਆਖ਼ਰੀ {{PLURAL:$2|ਘੰਟੇ|'''$2''' ਘੰਟਿਆਂ}} ਵਿਚ {{PLURAL:\n$1|ਤਬਦੀਲੀ ਹੋਈ|'''$1''' ਤਬਦੀਲੀਆਂ ਹੋਈਆਂ}}, ਹੇਠਾਂ ਵੇਖੋ।",
        "wlshowlast": "ਪਿਛਲੇ $1 ਘੰਟੇ $2 ਦਿਨ $3 ਵਖਾਓ",
        "watchlist-options": "ਨਿਗਰਾਨੀ-ਲਿਸਟ ਦੀਆਂ ਚੋਣਾਂ",
        "watching": "ਨਿਗ੍ਹਾ (ਵਾਚ) ਰੱਖੀ ਜਾ ਰਹੀ ਹੈ...",
        "allmessages-prefix": "ਇਸ ਅਗੇਤਰ ਨਾਲ਼ ਛਾਣੋ:",
        "allmessages-language": "ਭਾਸ਼ਾ:",
        "allmessages-filter-submit": "ਜਾਓ",
+       "allmessages-filter-translate": "ਤਰਜਮਾ ਕਰੋ",
        "thumbnail-more": "ਵਧਾਓ",
        "filemissing": "ਫ਼ਾਈਲ ਗੁੰਮ ਹੈ",
        "thumbnail_error": "ਨਮੂਨਾ ਬਣਾਉਣ ਵਿੱਚ ਗਲਤੀ ਹੋਈ ਹੈ: $1",
        "import": "ਸਫ਼ੇ ਮੰਗਾਓ",
        "importinterwiki": "ਅੰਤਰ-ਵਿਕੀ ਮੰਗ",
-       "import-interwiki-source": "ਸਰੋਤ ਵਿਕੀ/ਸਫ਼ਾ:",
        "import-interwiki-templates": "ਸਾਰੇ ਫਰਮੇ ਸ਼ਾਮਲ ਕਰੋ",
        "import-interwiki-submit": "ਮੰਗਾਓ",
        "import-upload-filename": "ਫ਼ਾਈਲ ਦਾ ਨਾਂ:",
        "siteusers": "{{SITENAME}} {{PLURAL:$2|ਵਰਤੋਂਕਾਰ|ਵਰਤੋਂਕਾਰਾਂ}} $1",
        "creditspage": "ਸਫ਼ੇ ਬਾਬਤ ਕਰਜ਼",
        "spamprotectiontitle": "Spam ਸੁਰੱਖਿਆ ਫਿਲਟਰ",
+       "pageinfo-header-basic": "ਮੁੱਢਲੀ ਜਾਣਕਾਰੀ",
        "pageinfo-header-edits": "ਸੋਧਾਂ ਦਾ ਅਤੀਤ",
        "pageinfo-header-restrictions": "ਸਫ਼ੇ ਦੀ ਸੁਰੱਖਿਆ",
+       "pageinfo-header-properties": "ਸਫ਼ਾ ਵਿਸ਼ੇਸ਼ਤਾ",
        "pageinfo-length": "ਸਫ਼ੇ ਦੀ ਲੰਬਾਈ (ਬਾਈਟਾਂ ਵਿਚ)",
        "pageinfo-article-id": "ਸਫ਼ੇ ਦੀ ਸ਼ਨਾਖ਼ਤ",
        "pageinfo-language": "ਸਫ਼ੇ ਦੀ ਸਮੱਗਰੀ ਦੀ ਭਾਸ਼ਾ",
        "file-nohires": "ਇਸ ਤੋਂ ਵੱਡੀ ਤਸਵੀਰ ਮੌਜੂਦ ਨਹੀਂ ਹੈ।",
        "svg-long-desc": "SVG ਫ਼ਾਈਲ, ਆਮ ਤੌਰ ’ਤੇ $1 × $2 ਪਿਕਸਲ, ਫ਼ਾਈਲ ਦਾ ਅਕਾਰ: $3",
        "show-big-image": "ਅਸਲ ਫਾਈਲ",
+       "show-big-image-size": "$1 × $2 ਪਿਕਸਲ",
        "newimages": "ਨਵੀਆਂ ਫ਼ਾਈਲਾਂ ਦੀ ਗੈਲਰੀ",
+       "newimages-legend": "ਫਿਲਟਰ",
        "noimages": "ਵੇਖਣ ਲਈ ਕੁਝ ਨਹੀਂ",
        "ilsubmit": "ਖੋਜ",
        "bydate": "ਮਿਤੀ ਨਾਲ",
        "exif-unknowndate": "ਅਣਪਛਾਤੀ ਮਿਤੀ",
        "exif-orientation-1": "ਸਧਾਰਨ",
        "exif-orientation-3": "੧੮੦° ਘੁਮਾਇਆ ਗਿਆ",
+       "exif-orientation-6": "90° ਖੱਬੇ ਦਾਅ ਘੁੰਮਾਇਆ",
+       "exif-orientation-7": "90° ਸੱਜੇ ਦਾਅ ਘੁੰਮਾਇਆ ਅਤੇ ਖੜ੍ਹਵੇਂ ਰੂਪ ਵਿੱਚ ਪਲਟਿਆ",
+       "exif-orientation-8": "90° ਸੱਜੇ ਦਾਅ ਘੁੰਮਾਇਆ",
        "exif-componentsconfiguration-0": "ਮੌਜੂਦ ਨਹੀਂ ਹੈ",
        "exif-exposureprogram-0": "ਪਰਿਭਾਸ਼ਤ ਨਹੀਂ",
        "exif-exposureprogram-1": "ਦਸਤੀ",
        "confirm-watch-top": "ਇਸ ਸਫ਼ੇ ਨੂੰ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿਚ ਜੋੜਨਾ ਹੈ?",
        "confirm-unwatch-button": "ਠੀਕ ਹੈ",
        "confirm-unwatch-top": "ਇਸ ਸਫ਼ੇ ਨੂੰ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਤੋਂ ਹਟਾਉਣਾ ਹੈ?",
+       "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← ਪਿਛਲਾ ਸਫ਼ਾ",
        "imgmultipagenext": "ਅਗਲਾ ਸਫ਼ਾ →",
        "imgmultigo": "ਜਾਓ!",
        "imgmultigoto": "$1 ਸਫ਼ੇ ਉੱਤੇ ਜਾਓ",
+       "img-lang-default": "(ਮੂਲ ਭਾਸ਼ਾ)",
+       "img-lang-go": "ਜਾਓ",
        "ascending_abbrev": "ਵਧਦਾ",
        "descending_abbrev": "ਘਟਦਾ",
        "table_pager_next": "ਅਗਲਾ ਸਫ਼ਾ",
        "version-hooks": "ਹੁੱਕਾਂ",
        "version-hook-name": "ਹੁੱਕ ਦਾ ਨਾਂ",
        "version-license": "ਲਸੰਸ",
+       "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-credits-title": "$1 ਲਈ ਮਾਣ",
        "version-poweredby-others": "ਹੋਰ",
+       "version-poweredby-translators": "translatewiki.net ਅਨੁਵਾਦਕ",
        "version-software": "ਇਨਸਟਾਲ ਕੀਤਾ ਸਾਫ਼ਟਵੇਅਰ",
        "version-software-product": "ਉਤਪਾਦ",
        "version-software-version": "ਵਰਜਨ",
        "fileduplicatesearch-submit": "ਖੋਜ",
        "fileduplicatesearch-noresults": "\"$1\" ਨਾਂ ਦੀ ਕੋਈ ਫ਼ਾਈਲ ਨਹੀਂ ਲੱਭੀ।",
        "specialpages": "ਖ਼ਾਸ ਸਫ਼ੇ",
+       "specialpages-note-top": "ਸੰਕੇਤ",
        "specialpages-group-maintenance": "ਪ੍ਰਬੰਧਕੀ ਰਪਟਾਂ",
        "specialpages-group-other": "ਹੋਰ ਖ਼ਾਸ ਸਫ਼ੇ",
        "specialpages-group-login": "ਲਾਗਇਨ / ਖਾਤਾ ਬਣਾਓ",
        "tags-title": "ਟੈਗ",
        "tags-tag": "ਟੈਗ ਦਾ ਨਾਮ",
        "tags-description-header": "ਅਰਥ ਦਾ ਪੂਰਾ ਬਿਓਰਾ",
+       "tags-active-header": "ਸਰਗਰਮ?",
        "tags-hitcount-header": "ਟੈਗ ਕੀਤੀਆਂ ਤਬਦੀਲੀਆਂ",
+       "tags-active-yes": "ਹਾਂ",
+       "tags-active-no": "ਨਹੀਂ",
        "tags-edit": "ਸੋਧੋ",
        "tags-hitcount": "$1 {{PLURAL:$1|ਤਬਦੀਲੀ|ਤਬਦੀਲੀਆਂ}}",
        "comparepages": "ਸਫ਼ੇ ਮਿਲਾਓ",
        "htmlform-no": "ਨਹੀਂ",
        "htmlform-yes": "ਹਾਂ",
        "htmlform-chosen-placeholder": "ਕੋਈ ਚੋਣ ਚੁਣੋ",
+       "htmlform-cloner-create": "ਹੋਰ ਜੋੜੋ",
+       "htmlform-cloner-delete": "ਹਟਾਓ",
        "logentry-delete-delete": "$1 ਨੇ ਸਫ਼ਾ $3 ਮਿਟਾਇਆ",
        "revdelete-content-hid": "ਸਮੱਗਰੀ ਲੁਕਾਈ ਹੋਈ",
        "revdelete-summary-hid": "ਸੋਧ ਸਾਰ ਲੁਕਾਈ ਹੋਈ",
        "duration-centuries": "$1 {{PLURAL:$1|ਸਦੀ|ਸਦੀਆਂ}}",
        "duration-millennia": "$1 {{PLURAL:$1|ਸਾਹਸ਼ਤਾਬਦੀ|ਸਾਹਸ਼ਤਾਬਦੀਆਂ}}",
        "rotate-comment": "ਤਸਵੀਰ ਨੂੰ ਘੜੀ ਦੇ ਰੁਖ ਵਿਚ $1 {{PLURAL:$1|ਡਿਗਰੀ|ਡਿਗਰੀਆਂ}} ਨਾਲ਼ ਘੁਮਾਇਆ ਗਿਆ",
-       "expand_templates_preview": "ਝਲਕ"
+       "expand_templates_ok": "ਠੀਕ ਹੈ",
+       "expand_templates_remove_comments": "ਟਿੱਪਣੀਆਂ ਹਟਾਓ",
+       "expand_templates_preview": "ਝਲਕ",
+       "pagelang-name": "ਸਫ਼ਾ",
+       "pagelang-language": "ਭਾਸ਼ਾ",
+       "pagelang-use-default": "ਮੂਲ ਭਾਸ਼ਾ ਵਰਤੋਂ",
+       "pagelang-select-lang": "ਭਾਸ਼ਾ ਚੁਣੋ"
 }
index 3dd109b..010179a 100644 (file)
        "talkpagelinktext": "Pisasabian",
        "specialpage": "Bulung a Makabukud",
        "personaltools": "Sariling kasangkapan",
-       "postcomment": "Magpaskil kang komentu o puna",
        "articlepage": "Lawen me ing kalamnan ning bulung",
        "talk": "Pamisabi-sabi",
        "views": "Pamaglawe",
        "externaldberror": "Mapalyaring mika pamagkamali king external authentication (pamagpatutung panlual) ning database, o ala kang paintulut a i-update ya ing kekang account a panlual (external account).",
        "login": "Mag log in",
        "nav-login-createaccount": "Mag-login / maglalang account",
-       "loginprompt": "Kailangan mo reng cookie a makasalangi (enabled) ba kang makapag log in king {{SITENAME}}.",
        "userlogin": "Mag-login / maglalang account",
        "logout": "Mag-log out",
        "userlogout": "Mag logout",
        "searchprofile-images-tooltip": "Manintun makasimpan",
        "searchprofile-everything-tooltip": "Manintun karing eganaganang laman (kayabe no reng bulung pamisabi-sabi)",
        "search-result-size": "$1 ({{PLURAL:$2|1 a kataya|$2 kataya}})",
-       "search-result-score": "Kaugnayan (relevance): $1%",
        "search-redirect": "(pamanalis direksiun $1)",
        "search-section": "(seksion $1)",
        "search-suggest": "Ing buri mung sabian: $1",
        "fileexists-shared-forbidden": "Atin nang simpan (file) a maki lagyung anti kaniti king abe-abeng simpanan (shared file repository);\nmibalik ka at ilulan (upload) me king lalam ning bayung lagyu. [[File:$1|thumb|center|$1]]",
        "uploadwarning": "Babala king pamaglulan",
        "savefile": "I-save ya ing simpan (file)",
-       "uploadedimage": "milulan ya ing \"[[$1]]\"",
-       "overwroteimage": "milulan ya ing bayung bersion ning \"[[$1]]\"",
        "uploaddisabled": "Makapatda ing pamag-upload",
        "uploaddisabledtext": "Makapatda ing pamag-upload king {{SITENAME}}.",
        "uploadscripted": "Atin yang HTML o script code ing simpan a ini, at maliaring magkamali ya ing web browser king pamamasa kaniti.",
        "watchlist-details": "{{PLURAL:$1|$1 bulung|$1 bulung}} king kekang watchlist, e la kayabe deng ''talk pages''.",
        "wlheader-enotif": "Makasalangi (enabled) ing pamipabalu kapamilatan ning e-mail.",
        "wlheader-showupdated": "'''Makapal''' la pangasulat deng bulung a miyalilan manibat aniang tauli mu lang pintalan.",
+       "wlnote": "{{PLURAL:$1|Ing makatuki ing tauling|Ding makatuki ring tauling '''$1''' miyalilan}} kilub {{PLURAL:$2|ning tauling metung a oras|ding tauling '''$2''' oras}}.",
        "wlshowlast": "Pakit la reng tauling $1 oras $2 aldo $3",
        "watchlist-options": "Deng maliaring gawan kareng listaan da reng babanten (''watchlist'')",
        "watching": "Babanten...",
index f780a0a..2c50096 100644 (file)
        "talkpagelinktext": "Dviser",
        "specialpage": "Pache éspéchiale",
        "personaltools": "Otis dech uzeu",
-       "postcomment": "Nouvèle sekchion",
        "articlepage": "Vir el pache ed ches étnus",
        "talk": "distchuter",
        "views": "Vues",
        "yourdomainname": "Vote donmène:",
        "login": "Intrer",
        "nav-login-createaccount": "Intrer / créer vote conpte",
-       "loginprompt": "I feut avoèr dés coukies pou pouvoèr intrer din {{SITENAME}}.",
        "userlogin": "Intrer / créer vote conpte",
        "logout": "Sortir",
        "userlogout": "Sortir",
        "upload": "Quértcher chés fichiés",
        "uploadlogpage": "Jornal éd chés quértchémints",
        "filedesc": "Résumè",
-       "uploadedimage": "\"[[$1]]\" quértchée",
        "license": "Licince",
        "license-header": "Licince",
        "listfiles": "Lisse des fichiés",
index 036d5c4..caf85e5 100644 (file)
        "filename": "Feilnaame",
        "badfilename": "Daer Feilnaame iss gennert warre nooch „$1“.",
        "savefile": "Feil beilege",
-       "uploadedimage": "hot „[[$1]]“ uffglaade",
-       "overwroteimage": "hot e neie Version vun „[[$1]]“ uffglaade",
        "uploaddisabled": "Ufflaade verbodde",
        "uploaddisabledtext": "Es Ufflaade vun Feils iss verbodde.",
        "watchthisupload": "Watsch des Blatt",
index c5b47ac..f60e1dc 100644 (file)
        "talkpagelinktext": "Dischbediere",
        "specialpage": "Schbezielli Said",
        "personaltools": "Persenlischs Wergzaisch",
-       "postcomment": "Naije Abschnidd",
        "articlepage": "Inhald õgugge",
        "talk": "Dischbediere",
        "views": "Uffruf",
        "remembermypassword": "Moi Kennword uffm Brausa merge (hegschdns fa $1 {{PLURAL:$1|Daach|Daach}})",
        "login": "Õmelde",
        "nav-login-createaccount": "Õmelde / Kondo õleesche",
-       "loginprompt": "Cookies mugschd fa {{SITENAME}} schun õhawe.",
        "userlogin": "Õmelde / Kondo õleesche",
        "userloginnocreate": "Oilogge",
        "logout": "Uffhere",
        "searchprofile-advanced-tooltip": "Gugg in õnnare Nõmensreum",
        "search-result-size": "$1 ({{PLURAL:$2|1 Word|$2 Wärda}})",
        "search-result-category-size": "{{PLURAL:$1|1 Said|$1 Saide}} ({{PLURAL:$2|1 Sachgrubb|$2 Sachgrubbe}}, {{PLURAL:$3|1 Dadai|$3 Dadaije}})",
-       "search-result-score": "Bdaidung: $1%",
        "search-redirect": "(Waidalaidung $1)",
        "search-section": "(Abschnidd $1)",
        "search-suggest": "Hoschd gemäänd: $1",
        "filedesc": "Iwwabligg",
        "fileuploadsummary": "Iwwabligg:",
        "savefile": "Dadai schbaischere",
-       "uploadedimage": "hodd „[[$1]]“ nuffglade",
        "lockmanager-notlocked": "„$1“ hod ned uffgmachd were kenne, s'isch ganed gschberd gwesd.",
        "lockmanager-fail-closelock": "Die gbscherd Dadai „$1“ hod ned gschlosse were kenne.",
        "lockmanager-fail-deletelock": "Die gbscherd Dadai „$1“ hod ned gleschd were kenne.",
index 59574f4..a65ecb6 100644 (file)
@@ -83,6 +83,7 @@
        "tog-watchdefault": "Dodawaj do obserwowanych strony i pliki, które edytuję",
        "tog-watchmoves": "Dodawaj do obserwowanych strony i pliki, które przenoszę",
        "tog-watchdeletion": "Dodawaj do obserwowanych strony i pliki, które usuwam",
+       "tog-watchrollback": "Dodawaj do obserwowanych strony, w których {{GENDER:|wycofałem|wycofałam}} edycję",
        "tog-minordefault": "Wszystkie edycje domyślnie oznaczaj jako drobne",
        "tog-previewontop": "Pokazuj podgląd powyżej obszaru edycji",
        "tog-previewonfirst": "Pokazuj podgląd strony podczas pierwszej edycji",
        "go": "Przejdź",
        "searcharticle": "Przejdź",
        "history": "Historia strony",
-       "history_short": "Historia",
+       "history_short": "historia",
        "updatedmarker": "zmienione od ostatniej wizyty",
        "printableversion": "Wersja do druku",
        "permalink": "Link do tej wersji",
        "talkpagelinktext": "dyskusja",
        "specialpage": "Strona specjalna",
        "personaltools": "Osobiste",
-       "postcomment": "Nowa sekcja",
        "articlepage": "Artykuł",
        "talk": "Dyskusja",
        "views": "Widok",
        "otherlanguages": "W innych językach",
        "redirectedfrom": "(Przekierowano z $1)",
        "redirectpagesub": "Strona przekierowująca",
+       "redirectto": "Przekierowanie do:",
        "lastmodifiedat": "Tę stronę ostatnio zmodyfikowano o $2, $1.",
        "viewcount": "Tę stronę obejrzano {{PLURAL:$1|tylko raz|$1 razy}}.",
        "protectedpage": "Strona zabezpieczona",
        "hidetoc": "ukryj",
        "collapsible-collapse": "Zwiń",
        "collapsible-expand": "Rozwiń",
+       "confirmable-confirm": "Jesteś {{GENDER:$1|pewny|pewna}}?",
+       "confirmable-yes": "Tak",
+       "confirmable-no": "Nie",
        "thisisdeleted": "Pokazać lub odtworzyć $1?",
        "viewdeleted": "Zobacz $1",
        "restorelink": "{{PLURAL:$1|jedną usuniętą wersję|$1 usunięte wersje|$1 usuniętych wersji}}",
        "invalidtitle-knownnamespace": "Nieprawidłowa nazwa w obszarze nazw \"$2\" o treści \"$3\"",
        "invalidtitle-unknownnamespace": "Nieprawidłowa nazwa z nieznaną liczbą przestrzeni nazw  $1  o treści \"$2\"",
        "exception-nologin": "Nie jesteś zalogowany/a",
-       "exception-nologin-text": "Proszę [[Special:Userlogin|zaloguj się]] aby mieć dostęp do tej strony lub akcji.",
+       "exception-nologin-text": "Zaloguj się, aby mieć dostęp do tej strony lub akcji.",
        "exception-nologin-text-manual": "Musisz $1 aby mieć dostęp do tej strony lub akcji.",
        "virus-badscanner": "Zła konfiguracja – nieznany skaner antywirusowy ''$1''",
        "virus-scanfailed": "skanowanie nieudane (błąd $1)",
        "externaldberror": "Wystąpił błąd zewnętrznej bazy autentyfikacyjnej lub nie posiadasz uprawnień koniecznych do aktualizacji zewnętrznego konta.",
        "login": "Zaloguj się",
        "nav-login-createaccount": "Logowanie i rejestracja",
-       "loginprompt": "Musisz mieć włączoną w przeglądarce obsługę ciasteczek, by móc się zalogować do {{GRAMMAR:D.lp|{{SITENAME}}}}.",
        "userlogin": "Logowanie i rejestracja",
        "userloginnocreate": "Zaloguj się",
        "logout": "Wyloguj",
        "userlogin-resetlink": "Zapomniałeś danych do zalogowania się?",
        "userlogin-resetpassword-link": "Nie pamiętasz hasła?",
        "userlogin-helplink2": "Pomoc przy logowaniu",
-       "userlogin-loggedin": "Zalogowano jako {{GENDER:$1|$1}}.\nUżyj poniższego formularza, aby zalogować się jako inny użytkownik.",
-       "userlogin-createanother": "Załóż nowe konto",
        "createacct-emailrequired": "Adres e‐mail",
        "createacct-emailoptional": "Adres e-mail (opcjonalnie)",
        "createacct-email-ph": "Wpisz swój adres e-mail",
        "createaccount-text": "Ktoś utworzył w {{GRAMMAR:MS.lp|{{SITENAME}}}} ($4), podając Twój adres e‐mail, konto „$2”. Aktualnym hasłem jest „$3”.\nZaloguj się teraz i je zmień.\n\nMożesz zignorować tę wiadomość, jeśli konto zostało utworzone przez pomyłkę.",
        "login-throttled": "Zbyt wiele razy próbowałeś zalogować się na to konto.\nOdczekaj $1 zanim ponowisz próbę.",
        "login-abort-generic": "Logowanie nieudane – przerwano",
+       "login-migrated-generic": "Twoje konto zostało poddane migracji i twoja nazwa użytkownika już nie istnieje na tej wiki.",
        "loginlanguagelabel": "Język: $1",
        "suspicious-userlogout": "Żądanie wylogowania zostało odrzucone ponieważ wygląda na to, że zostało wysłane przez uszkodzoną przeglądarkę lub buforujący serwer proxy.",
        "createacct-another-realname-tip": "Wpisanie imienia i nazwiska nie jest obowiązkowe.\nJeśli zdecydujesz się je podać, zostaną użyte, by udokumentować Twoje autorstwo.",
        "media_tip": "Link do pliku",
        "sig_tip": "Twój podpis wraz z datą i czasem",
        "hr_tip": "Linia pozioma (nie nadużywaj)",
-       "summary": "Opis zmian ",
+       "summary": "Opis zmian:",
        "subject": "Temat/nagłówek:",
        "minoredit": "To jest drobna zmiana",
        "watchthis": "Obserwuj",
        "preview": "Podgląd",
        "showpreview": "Pokaż podgląd",
        "showdiff": "Podgląd zmian",
+       "blankarticle": "<strong>Uwaga:</strong> Strona, którą masz zamiar utworzyć jest pusta.\nJeżeli klikniesz \"{{int:savearticle}}\" ponownie, strona zostanie utworzona bez jakiejkolwiek treści.",
        "anoneditwarning": "'''Uwaga:''' Nie jesteś {{GENDER:|zalogowany|zalogowana}}.\nTwój adres IP zostanie zapisany w historii edycji strony.",
        "anonpreviewwarning": "''Nie jesteś zalogowany. Jeśli zapiszesz zmiany, w historii edycji strony zostanie umieszczony Twój adres IP.''",
        "missingsummary": "'''Uwaga:''' Nie wprowadz{{GENDER:|iłeś|iłaś|ono}} opisu zmian.\nJeżeli nie chcesz go wprowadzać, naciśnij przycisk „Zapisz” jeszcze raz.",
        "parser-template-recursion-depth-warning": "Przekroczno limit głębokości rekurencji szablonu ($1)",
        "language-converter-depth-warning": "Przekroczono ograniczenie ($1) głębokości zagnieżdżenia konwersji językowej",
        "node-count-exceeded-category": "Strony, gdzie przekroczono liczbę węzłów",
-       "node-count-exceeded-category-desc": "Kategoria dla stron, na których przekroczono liczbę węzłów.",
+       "node-count-exceeded-category-desc": "Strona przekracza maksymalną liczbę węzłów.",
        "node-count-exceeded-warning": "Strona przekroczyła liczbę węzłów",
        "expansion-depth-exceeded-category": "Strony z przekroczoną głębokością rozbudowy",
-       "expansion-depth-exceeded-category-desc": "Kategoria dla stron, na których przekroczona jest głębokość rozbudowy.",
+       "expansion-depth-exceeded-category-desc": "Strona przekracza maksymalną głębokość rozbudowy.",
        "expansion-depth-exceeded-warning": "Strona przekroczyła głębokość rozbudowy",
        "parser-unstrip-loop-warning": "Wykryto nieskończoną pętlę",
        "parser-unstrip-recursion-limit": "Przekroczono maksymalną głębokość zagnieżdżania ($1)",
        "rev-deleted-event": "(wpis usunięty)",
        "rev-deleted-user-contribs": "[nazwa użytkownika lub adres IP usunięte – edycja ukryta we wkładzie]",
        "rev-deleted-text-permission": "Ta wersja strony została '''usunięta'''.\nSzczegółowe informacje mogą znajdować się w [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} rejestrze usunięć].",
+       "rev-suppressed-text-permission": "Ta wersja strony została <strong>ukryta</strong>.\nSzczegóły można odnaleźć w [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} rejestrze ukryć].",
        "rev-deleted-text-unhide": "Ta wersja strony została '''usunięta'''.\nSzczegółowe informacje mogą znajdować się w [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} rejestrze usunięć].\nJeśli chcesz możesz [$1 obejrzeć tę wersję].",
        "rev-suppressed-text-unhide": "Ta wersja strony została '''utajniona'''.\nSzczegółowe informacje mogą znajdować się w [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} rejestrze utajniania].\nJeśli chcesz możesz [$1 obejrzeć tę wersję].",
        "rev-deleted-text-view": "Ta wersja strony została '''usunięta'''.\nJeśli chcesz możesz ją obejrzeć. Szczegółowe informacje mogą znajdować się w [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} rejestrze usunięć].",
        "revdelete-text-text": "Usunięte wersje będą nadal widoczne w historii strony, ale niektóre fragmenty ich treści nie będą dostępne dla wszystkich.",
        "revdelete-text-file": "Usunięte wersje pliku będą nadal widoczne w historii pliku, ale niektóre fragmenty ich treści nie będą dostępne dla wszystkich.",
        "logdelete-text": "Usunięte wpisy rejestru nadal będą widoczne w rejestrze, ale niektóre fragmenty ich treści nie będą dostępne dla wszystkich.",
-       "revdelete-text-others": "Pozostali administratorzy {{grammar:genitive|{{SITENAME}}}} nadal będą posiadali dostęp do ukrytej treści i będą w stanie odtworzyć ją ponownie za pomocą tego samego interfejsu, jeśli nie zostaną ustawione dodatkowe ograniczenia.",
+       "revdelete-text-others": "Pozostali administratorzy nadal będą posiadali dostęp do ukrytej treści i będą w stanie odtworzyć ją ponownie za pomocą tego samego interfejsu, jeśli nie zostaną ustawione dodatkowe ograniczenia.",
        "revdelete-confirm": "Potwierdź, że chcesz to zrobić zgodnie z [[{{MediaWiki:Policy-url}}|zasadami]] i że rozumiesz konsekwencje.",
        "revdelete-suppress-text": "Ukrywanie powinno być używane '''wyłącznie''' w sytuacji:\n* Informacji, która może być zniesławieniem\n* Ujawnienie danych osobowych\n*: ''adres domowy, numer telefonu, numer PESEL itp''",
        "revdelete-legend": "Ustaw ograniczenia widoczności",
        "searchmenu-exists": "* Strona '''[[$1]]'''",
        "searchmenu-new": "<strong>Utwórz stronę „[[:$1]]” na tej wiki!</strong> {{PLURAL:$2|0=|Zobacz też stronę z wynikami wyszukiwania.|Zobacz też wyniki wyszukiwania.}}",
        "searchprofile-articles": "Strony",
-       "searchprofile-images": "Multimedia",
-       "searchprofile-everything": "Wszystko",
-       "searchprofile-advanced": "Zaawansowane",
+       "searchprofile-images": "w multimediach",
+       "searchprofile-everything": "na wszystkich stronach",
+       "searchprofile-advanced": "zaawansowane",
        "searchprofile-articles-tooltip": "Szukanie w przestrzeni nazw $1",
        "searchprofile-images-tooltip": "Szukanie plików",
        "searchprofile-everything-tooltip": "Szukanie w całej zawartości (także strony dyskusji)",
        "searchprofile-advanced-tooltip": "Szukanie w wybranych przestrzeniach nazw",
        "search-result-size": "$1 ({{PLURAL:$2|1 słowo|$2 słowa|$2 słów}})",
        "search-result-category-size": "{{PLURAL:$1|1 element|$1 elementy|$1 elementów}} ({{PLURAL:$2|1 kategoria|$2 kategorie|$2 kategorii}}, {{PLURAL:$3|1 plik|$3 pliki|$3 plików}})",
-       "search-result-score": "Trafność: $1%",
        "search-redirect": "(przekierowanie $1)",
        "search-section": "(sekcja $1)",
        "search-file-match": "(odpowiada zawartości pliku)",
        "searchall": "wszystkie",
        "showingresults": "Poniżej znajduje się lista {{PLURAL:$1|z '''1''' wynikiem|'''$1''' wyników}}, rozpoczynając od wyniku numer '''$2'''.",
        "showingresultsinrange": "Poniżej wyświetlono co najwyżej {{PLURAL:$1|<strong>1</strong> wynik|<strong>$1</strong> wyniki|<strong>$1</strong> wyników}} w zakresie od <strong>$2</strong> do <strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Wynik '''$1''' z '''$3'''|Wyniki '''$1 – $2''' z '''$3'''}} dla '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Wynik <strong>$1</strong> z <strong>$3</strong>|Wyniki <strong>$1 - $2</strong> z <strong>$3</strong>}}",
        "search-nonefound": "Brak wyników spełniających kryteria podane w zapytaniu.",
        "powersearch-legend": "Wyszukiwanie zaawansowane",
        "powersearch-ns": "Przeszukaj przestrzenie nazw:",
        "preferences": "Preferencje",
        "mypreferences": "Preferencje",
        "prefs-edits": "Liczba edycji:",
-       "prefsnologintext2": "Musisz $1 aby ustawić preferencje.",
+       "prefsnologintext2": "Zaloguj się, aby zmienić swoje preferencje.",
        "prefs-skin": "Skórka",
        "skin-preview": "podgląd",
        "datedefault": "Domyślny",
        "right-browsearchive": "Przeszukiwanie usuniętych stron",
        "right-undelete": "Odtwarzanie usuniętych stron",
        "right-suppressrevision": "Podgląd i odtwarzanie wersji ukrytych przed administratorami",
+       "right-viewsuppressed": "Umożliwia zobaczenie wersji ukrytych przed każdym użytkownikiem",
        "right-suppressionlog": "Podgląd rejestru ukrywania",
        "right-block": "Blokowanie użytkownikom możliwości edycji",
        "right-blockemail": "Blokowanie użytkownikom możliwości wysyłania wiadomości",
        "right-passwordreset": "Sprawdzanie treści e‐maila o resetowaniu hasła",
        "newuserlogpage": "Nowi użytkownicy",
        "newuserlogpagetext": "To jest rejestr ostatnio utworzonych kont użytkowników",
-       "rightslog": "Rejestr uprawnień",
+       "rightslog": "Uprawnienia",
        "rightslogtext": "Rejestr zmian uprawnień użytkowników.",
        "action-read": "przeglądania tej strony",
        "action-edit": "edytowania tej strony",
        "recentchanges-legend-heading": "'''Legenda:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (zobacz też [[Special:NewPages|listę nowych stron]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Poniżej pokazano zmiany wykonane po '''$2''' (nie więcej niż '''$1''' pozycji).",
+       "rcnotefrom": "Poniżej {{PLURAL:$5|pokazano zmianę|pokazano zmiany}} wykonane po <strong>$3, $4</strong> (nie więcej niż '''$1''' pozycji).",
        "rclistfrom": "Pokaż nowe zmiany od $3 $2",
        "rcshowhideminor": "$1 drobne zmiany",
        "rcshowhideminor-show": "Pokaż",
        "uploadwarning": "Ostrzeżenie o przesyłaniu",
        "uploadwarning-text": "Zmień poniższy opis pliku i spróbuj ponownie.",
        "savefile": "Zapisz plik",
-       "uploadedimage": "przesłał [[$1]]",
-       "overwroteimage": "przesłano nową wersję pliku „[[$1]]“",
        "uploaddisabled": "Przesyłanie plików wyłączone",
        "copyuploaddisabled": "Przesyłanie poprzez podanie adres URL jest wyłączone.",
        "uploaddisabledtext": "Możliwość przesyłania plików została wyłączona.",
        "license": "Licencja",
        "license-header": "Licencja",
        "nolicense": "Nie wybrano",
+       "licenses-edit": "Edytuj opcje licencji",
        "license-nopreview": "(Podgląd niedostępny)",
-       "upload_source_url": " (poprawny, publicznie dostępny adres URL)",
-       "upload_source_file": " (plik na twoim komputerze)",
+       "upload_source_url": "(wybrany plik z prawidłowego, publicznie dostępnego adresu URL)",
+       "upload_source_file": "(wybrany plik na twoim komputerze)",
+       "listfiles-delete": "usuń",
        "listfiles-summary": "Na tej stronie specjalnej prezentowane są wszystkie przesłane pliki.",
        "listfiles_search_for": "Szukaj pliku o nazwie",
        "imgfile": "plik",
        "filepage-nofile": "Plik o tej nazwie nie istnieje.",
        "filepage-nofile-link": "Plik o tej nazwie nie istnieje, ale możesz go [$1 przesłać].",
        "uploadnewversion-linktext": "Załaduj nowszą wersję tego pliku",
-       "shared-repo-from": "z $1",
-       "shared-repo": "współdzielone zasoby",
+       "shared-repo-from": "na $1",
+       "shared-repo": "współdzielonych zasobach",
        "filepage.css": "/* Styl CSS tutaj zamieszczony jest dołączany do strony pliku, także na innych wiki */",
        "upload-disallowed-here": "Nie możesz nadpisać tego pliku.",
        "filerevert": "Przywracanie $1",
        "randomincategory": "Losowa strona w kategorii",
        "randomincategory-invalidcategory": "\"$1\" nie jest prawidłową nazwą kategorii.",
        "randomincategory-nopages": "Nie ma żadnych stron w [[:Category:$1]].",
-       "randomincategory-selectcategory": "Pobierz losową stronę z kategorii: $1 $2.",
-       "randomincategory-selectcategory-submit": "Dalej",
+       "randomincategory-category": "Kategoria:",
+       "randomincategory-legend": "Losowa strona w kategorii",
        "randomredirect": "Losowe przekierowanie",
        "randomredirect-nopages": "Brak jakichkolwiek przekierowań w przestrzeni nazw „$1”.",
        "statistics": "Statystyki",
        "wantedpages-badtitle": "Nieprawidłowy tytuł wśród wyników – $1",
        "wantedfiles": "Potrzebne pliki",
        "wantedfiletext-cat": "Następujące pliki są używane, ale nie istnieją. Pliki z obcych repozytoriów mogą być wymienione pomimo istnienia. Takie fałszywe wyniki zostaną <del>przekreślone</del>. Ponadto strony, które osadzają pliki, które nie istnieją, są wymienione w [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Następujące pliki są używane, ale nie istnieją. Dodatkowo strony, które zawierają nieistniejące pliki, są wymienione w [[:$1]].",
        "wantedfiletext-nocat": "Następujące pliki są używane, ale nie istnieją. Pliki z obcych repozytoriów mogą być wymienione pomimo istnienia. Takie fałszywe wyniki zostaną <del>przekreślone</del>.",
+       "wantedfiletext-nocat-noforeign": "Następujące pliki są używane, ale nie istnieją.",
        "wantedtemplates": "Potrzebne szablony",
        "mostlinked": "Najczęściej linkowane strony",
        "mostlinkedcategories": "Kategorie o największej liczbie stron",
        "trackingcategories-desc": "Kryteria włączenia kategorii",
        "noindex-category-desc": "Ta strona nie jest indeksowana przez roboty, ponieważ ma wpisane magiczne słowo <code><nowiki>__NOINDEX__</nowiki></code> i znajduje się w przestrzeni nazw, w której ta flaga jest dozwolona.",
        "index-category-desc": "Na stronie znajduje się magiczne słowo <code><nowiki>__INDEX__</nowiki></code> (i strona znajduje się w przestrzeni nazw, w której jest ono dozwolone), więc jest indeksowana przez wyszukiwarki nawet wtedy, gdy normalnie by się to nie działo.",
-       "post-expand-template-inclusion-category-desc": "Po rozwinięciu wszystkich szablonów, rozmiar strony jest większe niż <code>$wgMaxArticleSize</code>, więc niektóre szablony nie zostały rozwinięte.",
-       "post-expand-template-argument-category-desc": "Po rozwinięciu argumentu szablonu (coś w potrójnych nawiasach, np. <code>{{{Foo}}}</code>) długość strony przekracza <code>$wgMaxArticleSize</code>.",
+       "post-expand-template-inclusion-category-desc": "Rozmiar tej strony jest większy niż <code>$wgMaxArticleSize</code> po rozszerzeniu wszystkich szablonów, więc część szablonów nie jest rozszerzonych.",
+       "post-expand-template-argument-category-desc": "Długość strony przekracza <code>$wgMaxArticleSize</code> po rozwinięciu argumentu szablonu (coś w potrójnych nawiasach, np. <code>{{{Foo}}}</code>).",
        "expensive-parserfunction-category-desc": "Na stronie używanych jest zbyt wiele wymagających funkcji parsera (takich jak <code>#ifexist</code>). Więcej informacji na stronie [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Kategoria dodawana do stron zawierających nieprawidłowe odwołania do plików (odwołania do nieistniejących plików).",
+       "broken-file-category-desc": "Strona zawiera nieprawidłowe odwołania do plików (odwołania do nieistniejących plików).",
        "hidden-category-category-desc": "To jest kategoria z <code><nowiki>__HIDDENCAT__</nowiki></code>, co zapobiega wyświetlaniu jej w sekcji z kategoriami na stronie.",
        "trackingcategories-nodesc": "Opis nie jest dostępny.",
        "trackingcategories-disabled": "Kategoria jest wyłączona",
        "mywatchlist": "Obserwowane",
        "watchlistfor2": "Dla $1 $2",
        "nowatchlist": "Lista obserwowanych przez Ciebie stron jest pusta.",
-       "watchlistanontext": "$1, aby obejrzeć lub edytować elementy listy obserwowanych.",
+       "watchlistanontext": "Zaloguj się, aby obejrzeć lub edytować elementy listy obserwowanych.",
        "watchnologin": "Nie jesteś zalogowany",
        "addwatch": "Dodaj do listy obserwowanych",
        "addedwatchtext": "Strona „[[:$1|$1]]” została dodana do Twojej [[Special:Watchlist|listy obserwowanych]].\nKażda zmiana treści tej strony lub związanej z nią strony dyskusji zostanie odnotowana na tej liście.",
        "watchlist-details": "Lista obserwowanych przez Ciebie stron zawiera {{PLURAL:$1|$1 pozycję|$1 pozycje|$1 pozycji}}, nie licząc oddzielnie stron dyskusji.",
        "wlheader-enotif": "Wysyłanie powiadomień na adres e‐mail jest włączone.",
        "wlheader-showupdated": "'''Wytłuszczone''' zostały strony, które zostały zmodyfikowane od Twojej ostatniej wizyty na nich.",
-       "wlnote2": "Poniżej pokazano zmiany wykonane w ciągu {{PLURAL:$1|ostatniej godziny|ostatnich <strong>$1</strong> godzin}}, licząc od $2, $3.",
+       "wlnote": "Poniżej pokazano {{PLURAL:$1|zmianę wykonaną|<strong>$1</strong> zmiany wykonane|<strong>$1</strong> zmian wykonanych}} w ciągu {{PLURAL:$2|ostatniej godziny|ostatnich <strong>$2</strong> godzin}}, licząc od $4 dnia $3.",
        "wlshowlast": "Pokaż ostatnie $1 godzin, $2 dni ($3)",
        "watchlist-options": "Opcje obserwowanych",
        "watching": "Dodaję do obserwowanych...",
        "exbeforeblank": "poprzednia zawartość, obecnie pustej strony: „$1”",
        "delete-confirm": "Usuwanie „$1”",
        "delete-legend": "Usuń",
-       "historywarning": "'''Uwaga!''' Strona, którą chcesz usunąć, ma w przybliżeniu {{PLURAL:$1|jedną starszą wersję|$1 starsze wersje|$1 starszych wersji}}:",
+       "historywarning": "<strong>Uwaga:</strong> Strona, którą chcesz usunąć, ma {{PLURAL:$1|jedną starszą wersję|$1 starsze wersje|$1 starszych wersji}}:",
        "confirmdeletetext": "Zamierzasz usunąć stronę razem z całą dotyczącą jej historią.\nUpewnij się, czy na pewno chcesz to zrobić, że rozumiesz konsekwencje i że robisz to w zgodzie z [[{{MediaWiki:Policy-url}}|zasadami]].",
        "actioncomplete": "Operacja wykonana",
        "actionfailed": "Działanie nie powiodło się",
-       "deletedtext": "Usunięto „$1”.\nZobacz na stronie $2 rejestr ostatnio wykonanych usunięć.",
+       "deletedtext": "Usunięto „$1”.\nZobacz $2, które zostały ostatnio wykonane.",
        "dellogpage": "Usunięte",
        "dellogpagetext": "Poniżej znajduje się lista ostatnio wykonanych usunięć.",
        "deletionlog": "rejestr usunięć",
        "delete-edit-reasonlist": "Edytuj listę przyczyn usunięcia",
        "delete-toobig": "Ta strona ma bardzo długą historię edycji – ponad $1 {{PLURAL:$1|zmianę|zmiany|zmian}}.<br />\nUsuwanie jej zostało ograniczone ze względu na możliwość zakłócenia pracy {{GRAMMAR:D.lp|{{SITENAME}}}}.",
        "delete-warning-toobig": "Ta strona ma bardzo długą historię edycji – ponad $1 {{PLURAL:$1|zmianę|zmiany|zmian}}.<br />\nBądź ostrożny, ponieważ usunięcie jej może spowodować zakłócenia w pracy {{GRAMMAR:D.lp|{{SITENAME}}}}.",
+       "deleteprotected": "Nie możesz usunąć tej strony, ponieważ została zabezpieczona.",
        "deleting-backlinks-warning": "''' Uwaga:''' Do strony, którą masz zamiar usunąć, odwołują się [[Special:WhatLinksHere/{{FULLPAGENAME}}|inne strony]].",
        "rollback": "Cofnij edycję",
        "rollback_short": "Cofnij",
        "autoblockid": "automatyczna blokada nr $1",
        "block": "Zablokuj użytkownika",
        "unblock": "Odblokuj użytkownika",
-       "blockip": "Zablokuj użytkownika",
+       "blockip": "Zablokuj {{GENDER:$1|użytkownika|użytkowniczkę}}",
        "blockip-legend": "Zablokuj użytkownika",
        "blockiptext": "Użyj poniższego formularza do zablokowania możliwości edycji spod określonego adresu IP lub konkretnemu użytkownikowi.\nBlokować należy jedynie po to, by zapobiec wandalizmom, zgodnie z [[{{MediaWiki:Policy-url}}|przyjętymi zasadami]].\nPodaj powód (np. umieszczając nazwy stron, na których dopuszczono się wandalizmu).",
        "ipaddressorusername": "Adres IP lub nazwa użytkownika",
        "ipb-unblock-addr": "Odblokuj $1",
        "ipb-unblock": "Odblokuj użytkownika lub adres IP",
        "ipb-blocklist": "Zobacz istniejące blokady",
-       "ipb-blocklist-contribs": "Wkład $1",
+       "ipb-blocklist-contribs": "Wkład {{GENDER:$1|$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",
        "unblocked": "[[User:$1|$1]] {{GENDER:$1|został odblokowany|została odblokowana|został odblokowany}}.",
        "unblocked-range": "$1 został odblokowany",
        "unblocked-id": "Blokada $1 została zdjęta",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] został odblokowany.",
        "blocklist": "Zablokowani użytkownicy",
        "ipblocklist": "Zablokowani użytkownicy",
        "ipblocklist-legend": "Znajdź zablokowanego użytkownika",
        "import": "Import stron",
        "importinterwiki": "Import transwiki",
        "import-interwiki-text": "Wybierz wiki i nazwę strony do importowania.\nDaty oraz nazwy autorów zostaną zachowane.\nWszystkie operacje importu transwiki są odnotowywane w [[Special:Log/import|rejestrze importu]].",
-       "import-interwiki-source": "Źródło wiki/strony:",
+       "import-interwiki-sourcewiki": "Źródłowa wiki:",
+       "import-interwiki-sourcepage": "Strona źródłowa:",
        "import-interwiki-history": "Kopiuj całą historię edycji tej strony",
        "import-interwiki-templates": "Załącz wszystkie szablony",
        "import-interwiki-submit": "Importuj",
        "import-error-create": "Strona „$1“ nie została zaimportowana ponieważ nie jesteś uprawniony do jej utworzenia.",
        "import-error-interwiki": "Strona „$1” nie została zaimportowana, ponieważ jej nazwa jest zarezerwowana do linków zewnętrznych (interwiki).",
        "import-error-special": "Strona „$1” nie została zaimportowana, ponieważ należy do specjalnej przestrzeni nazw, która nie zezwala na strony.",
-       "import-error-invalid": "Strona „$1” nie została zaimportowana, ponieważ jej nazwa jest nieprawidłowa.",
+       "import-error-invalid": "Strona „$1” nie została zaimportowana, ponieważ jej nazwa jest nieprawidłowa na tej wiki.",
        "import-error-unserialize": "Wersja $2 strony \"$1\" nie może zostać odserializowana. Wersja używa modelu treści $3 zserializowanego jako $4",
        "import-error-bad-location": "Zmiana $2 używająca modelu danych $3 nie może zostać zapisana na \"$1\" na tej wiki, ze względu na to, że ten model danych nie jest wspierany na tej stronie.",
        "import-options-wrong": "{{PLURAL:$2|Niepoprawna opcja|Niepoprawne opcje}}: <nowiki>$1</nowiki>",
        "pageinfo-not-current": "Niestety, te informacje nie są dostępne dla starych wersji stron.",
        "pageinfo-header-basic": "Podstawowe informacje",
        "pageinfo-header-edits": "Historia edycji",
-       "pageinfo-header-restrictions": "Zabezpieczenie strony",
+       "pageinfo-header-restrictions": "Zabezpieczenie",
        "pageinfo-header-properties": "Właściwości strony",
        "pageinfo-display-title": "Wyświetlany tytuł",
        "pageinfo-default-sort": "Domyślny klucz sortowania",
        "autosumm-replace": "UWAGA! Zastąpienie treści hasła bardzo krótkim tekstem: „$1”",
        "autoredircomment": "Przekierowanie do [[$1]]",
        "autosumm-new": "Utworzono nową stronę \"$1\"",
+       "autosumm-newblank": "Utworzono pustą stronę",
        "size-bytes": "$1&nbsp;B",
        "size-kilobytes": "$1&nbsp;KB",
        "size-megabytes": "$1&nbsp;MB",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|dyskusja]])",
        "unknown_extension_tag": "Nieznany znacznik rozszerzenia „$1”",
        "duplicate-defaultsort": "Uwaga: Domyślnym kluczem sortowania będzie „$2” i zastąpi on wcześniej wykorzystywany klucz „$1”.",
+       "duplicate-displaytitle": "<strong>Uwaga:</strong> Wyświetlenie tytułu „$2” powoduje nadpisanie wcześniej wyświetlanego tytułu „$1”.",
        "version": "Wersja oprogramowania",
        "version-extensions": "Zainstalowane rozszerzenia",
        "version-skins": "Zainstalowane skórki",
        "specialpages-note": "* Normalne strony specjalne.\n* <span class=\"mw-specialpagerestricted\">Zastrzeżone strony specjalne.</span>",
        "specialpages-group-maintenance": "Raporty konserwacyjne",
        "specialpages-group-other": "Inne strony specjalne",
-       "specialpages-group-login": "Zaloguj się / utwórz konto",
+       "specialpages-group-login": "Logowanie / rejestracja",
        "specialpages-group-changes": "Ostatnie zmiany i rejestry",
        "specialpages-group-media": "Pliki",
        "specialpages-group-users": "Użytkownicy i uprawnienia",
        "logentry-rights-rights": "$1 {{GENDER:$2|zmienił|zmieniła}} przynależność $3 do grup ($4 → $5)",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|zmienił|zmieniła}} przynależność $3 do grup",
        "logentry-rights-autopromote": "$1 automatycznie {{GENDER:$2|zmienił|zmieniła}} przynależność ($4 → $5)",
+       "logentry-upload-upload": "$1 {{GENDER:$2|przesłał|przesłała}} $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|przesłał|przesłała}} nową wersję $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|przesłał|przesłała}} $3",
        "rightsnone": "brak",
        "feedback-bugornote": "Jeśli jesteś w stanie szczegółowo opisać problem techniczny, proszę [$1 zgłoś błąd].\nW przeciwnym wypadku można użyć prostego formularza poniżej. Komentarz zostanie dodany do strony \"[$3  $2]\", wraz z nazwą użytkownika.",
        "feedback-subject": "Temat",
        "api-error-invalid-file-key": "Błąd wewnętrzny – nie można odnaleźć pliku w wśród plików tymczasowych.",
        "api-error-missingparam": "Błąd wewnętrzny –  brak jest niektórych wymaganych informacji do realizacji przesłania.",
        "api-error-missingresult": "Błąd wewnętrzny – nie można określić czy kopiowanie się udało.",
-       "api-error-mustbeloggedin": "Musisz się zalogować aby przesyłać pliki.",
+       "api-error-mustbeloggedin": "Aby przesyłać pliki, musisz się zalogować.",
        "api-error-mustbeposted": "Wystąpił błąd w oprogramowaniu. Nie użyto właściwej metody HTTP.",
        "api-error-noimageinfo": "Plik przesłano, ale serwer nie zwrócił informacji na jego temat.",
        "api-error-nomodule": "Błąd wewnętrzny – nie określono modułu przesyłania plików.",
        "action-pagelang": "zmiany języka strony",
        "log-name-pagelang": "Rejestr zmian języka",
        "log-description-pagelang": "Rejestr zmian języków przypisanych do poszczególnych stron",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|zmienił|zmieniła}} język strony $3 z „$4” na „$5”."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|zmienił|zmieniła}} język strony $3 z „$4” na „$5”.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (włączone)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''wyłączone''')"
 }
index 38a7b14..8a34252 100644 (file)
@@ -31,6 +31,7 @@
        "tog-watchdefault": "Gionté le pàgine e j'archivi che i modìfico mi a la lista dle ròbe ch'i ten-o sot-euj",
        "tog-watchmoves": "Gionté le pàgine e j'archivi che i tramudo a lòn che im ten-o sot-euj",
        "tog-watchdeletion": "Gionté le pàgine e j'archivi che i scancelo via a la lista ëd lòn che im ten-o sot-euj",
+       "tog-watchrollback": "Gionté a la lista dle ròbe che i ten-o sot-euj le pàgine anté ch'i l'hai fàit n'operassion ëd riprìstin.",
        "tog-minordefault": "Marché tute le modìfiche coma cite coma predefinission",
        "tog-previewontop": "Smon-e la preuva dzora al quàder ëd modìfica dël test e nen sota",
        "tog-previewonfirst": "Smon-e na preuva la prima vira che as fa na modìfica",
        "talkpagelinktext": "discussion",
        "specialpage": "Pàgina special",
        "personaltools": "Utiss përsonaj",
-       "postcomment": "Session neuva",
        "articlepage": "Vëdde la pàgina ëd contnù",
        "talk": "Discussion",
        "views": "Vìsite",
        "otherlanguages": "Àutre lenghe",
        "redirectedfrom": "(Ridiression da $1)",
        "redirectpagesub": "Pàgina ëd ridiression",
+       "redirectto": "Ridiression a:",
        "lastmodifiedat": "Modificà l'ùltima vira ai $1 a $2.",
        "viewcount": "St'artìcol-sì a l'é stàit lesù {{PLURAL:$1|na vira|$1 vire}}.",
        "protectedpage": "Pàgina proteta",
        "jumptonavigation": "navigassion",
        "jumptosearch": "arserché",
        "view-pool-error": "An dëspias, ij servent a son motobin carià al moment.\nTròpi utent a son an camin ch'a preuvo a lese sta pàgina-sì.\nPër piasì, ch'a speta un pòch prima ëd prové torna a lese costa pàgina.\n\n$1",
+       "generic-pool-error": "An dëspias, ij servent a son motobin carià al moment.\nTròpi utent a son an camin ch'a preuvo a lese costa arsorsa.\nPër piasì, ch'a speta un pò prima ëd prové torna a acede a costa arsorsa.",
        "pool-timeout": "Ël temp a l'é finì antramentre ch'a së spetava la saradura",
        "pool-queuefull": "La coa ëd travaj a l'é pien-a",
        "pool-errorunknown": "Eror pa conossù",
        "hidetoc": "stërmé",
        "collapsible-collapse": "Saré",
        "collapsible-expand": "deurbe",
+       "confirmable-confirm": "{{GENDER:$1|É-lo}} sigur?",
+       "confirmable-yes": "É",
+       "confirmable-no": "Nò",
        "thisisdeleted": "Veul-lo vardé ò ripristiné $1?",
        "viewdeleted": "Veul-lo vardé $1?",
        "restorelink": "{{PLURAL:$1|na modìfica scancelà|$1 modìfiche scancelà}}",
        "invalidtitle-knownnamespace": "Tìtol ch'a va nen bin con lë spassi nominal «$2» e ël test «$3»",
        "invalidtitle-unknownnamespace": "Tìtol pa bon con nùmer dë spassi nominal $1 e test «$2» sconossù",
        "exception-nologin": "Nen rintrà ant ël sistema",
-       "exception-nologin-text": "Për piasì, [[Special:Userlogin|ch'a rintra ant ël sistema]] për podèj acede a costa pàgina o a costa assion.",
+       "exception-nologin-text": "Për piasì, ch'a rintra ant ël sistema për podèj acede a costa pàgina o a costa assion.",
        "exception-nologin-text-manual": "Për piasì, ch'a $1 për podèj acede a costa pàgina o costa assion.",
        "virus-badscanner": "Configurassion falà: antivìrus nen conossù: ''$1''",
        "virus-scanfailed": "scansion falìa (còdes $1)",
        "externaldberror": "Ò che a l'é rivaje n'eror con la base ëd dàit d'autenticassion esterna, ò pura a l'é chiel che a l'é nen autorisà a agiornesse sò cont estern.",
        "login": "Conession",
        "nav-login-createaccount": "Creé un cont o rintré ant ël sistema",
-       "loginprompt": "Che a varda mach che a venta avèj ij bëscotin abilità për podèj rintré an {{SITENAME}}.",
        "userlogin": "Creé un cont o rintré ant ël sistema",
        "userloginnocreate": "Conession",
        "logout": "Seurte da 'nt ël sistema",
        "userlogin-resetlink": "A l'ha dësmentià ij sò detaj për intré ant ël sistema?",
        "userlogin-resetpassword-link": "Ciav dësmentià?",
        "userlogin-helplink2": "Agiut a la conession",
-       "userlogin-loggedin": "A l'é già rintrà an ël sistema tanme {{GENDER:$1|$1}}.\nCh'a deuvra ël formolari sì-sota për rintré coma n'àutr n'utent.",
-       "userlogin-createanother": "Creé n'àutr cont",
        "createacct-emailrequired": "Adrëssa ëd pòsta eletrònica",
        "createacct-emailoptional": "Adrëssa ëd pòsta eletrònica (opsional)",
        "createacct-email-ph": "Ch'a buta soa adrëssa ëd pòsta eletrònica",
        "createaccount-text": "Cheidun a l'ha duvertà un cont për soa adrëssa ëd pòsta eletrònica ansima a {{SITENAME}} ($4) butand da stranòm «$2» e da ciav «$3». A dovrìa rintré ant ël sistema e cambiesse soa ciav pì ampressa ch'a peul.\n\nSe sòn a l'é rivà për eror, a peul lassé perde e fé gnente sensa problema.",
        "login-throttled": "A l'ha fàit tròpi tentativ recent d'intré ant ël sistema.\nPër piasì, ch'a speta $1 prima ëd prové torna.",
        "login-abort-generic": "Sò tentitiv d'intré ant ël sistema a l'é falì - Abortì",
+       "login-migrated-generic": "Sò cont a l'ha emigrà, e sò stranòm a esist pi nen su costa wiki.",
        "loginlanguagelabel": "Lenga: $1",
        "suspicious-userlogout": "Soa arcesta ëd seurte dal sistema a l'é stàita arfudà përchè a smija com s'a fussa stàita mandà da 'n navigador rot o da l'archiviassion an local d'un prëstanòm.",
        "createacct-another-realname-tip": "Ël nòm ver a l'é opsional.\nS'a decid ëd butelo, a sarà dovrà për dé a l'utent ël mérit ëd sò travaj.",
        "preview": "Previsualisassion",
        "showpreview": "Mostré na preuva",
        "showdiff": "Smon-me le modìfiche",
-       "anoneditwarning": "'''Atension:''' A l'é nen rintrà ant ël sistema. Soa adrëssa IP a sarà registrà ant la stòria dle modìfiche ëd sa pàgina.",
+       "blankarticle": "<strong>Atension:</strong> La pàgina ch'a l'ha creà a l'é veuida. S'a sgnaca torna «{{int:savearticle}}», la pàgina a sarà creà sensa contnù.",
+       "anoneditwarning": "<strong>Atension:<strong> A l'é nen rintrà ant ël sistema. Soa adrëssa IP a së sc-iairërà s'a fà dle modìfiche. Si chiel a <strong>[$1 rintra ant ël sistema]</strong> o <strong>[$2 a crea an cont]</strong>, soe modìfiche a saran atribuìe a sò stranòm, ansema a d'àutri vantagg.",
        "anonpreviewwarning": "''A l'é nen rintrà ant ël sistema. An salvand a sarà memorisà soa adrëssa IP ant la stòria dle modìfiche ëd sa pàgina.''",
        "missingsummary": "'''Nòta:''' a l'ha butà gnun resumé dla modìfica. Se a sgnaca «{{int:savearticle}}» n'àutra vira, soa modìfica a resterà salvà sensa resumé.",
        "missingcommenttext": "Për piasì, che a buta un coment sì-sota.",
        "edit-gone-missing": "As peul nen agiornesse la pàgina.\nA smija che a sia stàita scancelà.",
        "edit-conflict": "Conflit ëd modìfiche.",
        "edit-no-change": "Soa modìfica a l'é stàita ignorà, përchè gnun cambiament a l'é stàit fàit al test.",
+       "postedit-confirmation-created": "La pàgina a l'é stàita creà.",
+       "postedit-confirmation-restored": "La pàgina a l'é stàita ripristinà.",
        "postedit-confirmation-saved": "Soa modìfica a l'é stàita salvà.",
        "edit-already-exists": "La neuva pàgina a l'ha nen podù creesse.\nA esist già.",
        "defaultmessagetext": "Test che a-i sarìa se a-i fusso pa 'd modìfiche",
        "parser-template-recursion-depth-warning": "Passà ël lìmit ëd ricorsion dlë stamp ($1)",
        "language-converter-depth-warning": "Lìmit ëd profondità dël convertidor ëd lenga sorpassà ($1)",
        "node-count-exceeded-category": "Pàgine anté che ël nùmer ëd neu a l'é sorpassà",
+       "node-count-exceeded-category-desc": "La pàgina a sorpassa ël nùmer màssim dij neu.",
        "node-count-exceeded-warning": "La pàgina a l'ha sorpassà ël nùmer ëd neu",
        "expansion-depth-exceeded-category": "Pàgine anté che la profondeur d'espansion a l'é sorpassà",
+       "expansion-depth-exceeded-category-desc": "La pàgina a l'ha passà la profondità d'espansion.",
        "expansion-depth-exceeded-warning": "La pàgina a l'ha sorpassà la profondità d'espansion",
        "parser-unstrip-loop-warning": "Trovà un sicl nen dësmontàbil",
        "parser-unstrip-recursion-limit": "Sorpassà ël lìmit d'arcorensa nen dësmontàbil: $1",
        "currentrev": "Version dël dì d'ancheuj",
        "currentrev-asof": "Version corenta dij $1",
        "revisionasof": "Revision $1",
-       "revision-info": "Revision al $1; $2",
+       "revision-info": "Revision al $1 ëd {{GENDER:$6|$2}}$7",
        "previousrevision": "←Version pì veja",
        "nextrevision": "Revision pì neuva →",
        "currentrevisionlink": "Vardé la version corenta",
        "rev-deleted-event": "(assion dël registr gavà)",
        "rev-deleted-user-contribs": "[nòm utent o adrëssa IP gavà - modìfica stërmà ai contributor]",
        "rev-deleted-text-permission": "Sta revision-sì dla pàgina a l'é staita '''scancelà'''.\nA-i peulo essnie dle marche ant ël [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registr ëd jë scancelament].",
+       "rev-suppressed-text-permission": "Costa revision dla pàgina-sì a l'é stàita <stong>gavà via<strong>.\nIj detaj as treuvo ant ël [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registr ëd jë scancelament].",
        "rev-deleted-text-unhide": "Sta version-sì dla pàgina a l'é stàita '''scancelà'''.\nA peulo ess-ie dle marche ant ël [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registr ëd la scancelassion].\nA peul anco' [$1 vardé sta version-sì] se a veul.",
        "rev-suppressed-text-unhide": "Sta version-sì dla pàgina a l'é stàita '''gavà via'''.\nA peulo ess-ie dle marche ant ël [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registr ëd le scancelassion]. \nA peul anco' [$1 vëdde sta version] se a veul.",
        "rev-deleted-text-view": "Costa revision dla pàgina-sì a l'é staita '''scancelà'''.\nChiel a peul ës-ciairela; a peulo ess-ie dle marche ant ël [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registr ëd jë scancelament].",
        "revdelete-text-text": "Le revision ëscancelà a compariran ancora ant la stòria dla pàgina, ma na part ëd sò contnù a sarà inacessìbil al pùblich.",
        "revdelete-text-file": "Le version d'archivi scancelà a compariran ancora ant la stòria dj'archivi, ma na part ëd sò contnù a sarà inacessìbil al pùblich.",
        "logdelete-text": "J'eveniment dl'argistr ëscancelà a compariran ancora ant j'argistr, ma na part ëd sò contnù a sarà inacessìbil al pùblich.",
-       "revdelete-text-others": "J'àutri aministrator ëd {{SITENAME}} a podran sempe acede al contù stërmà e a peulo ripristinelo torna con costa antërfassa, gavà ch'a sio definìe ëd restrission adissionaj.",
+       "revdelete-text-others": "J'àutri aministrator ëd a podran sempe acede al contù stërmà e a peulo ripristinelo torna, gavà ch'a sio definìe ëd restrission adissionaj.",
        "revdelete-confirm": "Për piasì, ch'a confema ch'a veul fé sòn, ch'as rend cont dle conseguense, e ch'a lo fa an acòrd con [[{{MediaWiki:Policy-url}}|le régole]].",
        "revdelete-suppress-text": "La scancelassion a dovrìa '''mach''' esse dovrà an costi cas:\n* Anformassion ch'a podrìo esse difamatòrie\n* Anformassion përsonaj inapropià\n*: ''adrësse ëd ca e nùmer ëd teléfon, còdes fiscaj, e via fòrt''",
        "revdelete-legend": "But-je coste limitassion-sì a le version scancelà:",
        "mergehistory-empty": "Pa gnun-a revision ch'as peula butesse ansema.",
        "mergehistory-success": "$3 {{PLURAL:$3|revision|revision}} ëd [[:$1]] a son ëstàite butà ansema a [[:$2]] sensa problema.",
        "mergehistory-fail": "A l'é nen riessusse a buté ansema le revision, për piasì, ch'as contròla la pàgina e ij temp.",
+       "mergehistory-fail-toobig": "Impossìbil fé la fusion ëd la stòria përchè un nùmer ëd {{PLURAL:$1|revision}} pi grand che $1 a sarìa spostà.",
        "mergehistory-no-source": "La pàgina sorgiss $1 a-i é pa.",
        "mergehistory-no-destination": "La pàgina ëd destinassion $1 a-i é pa.",
        "mergehistory-invalid-source": "La pàgina sorgiss a l'ha d'avèj un tìtol bon.",
        "searchprofile-advanced-tooltip": "Sërché ant jë spassi nominaj përsonalisà",
        "search-result-size": "$1 ({{PLURAL:$2|un|$2}} mòt)",
        "search-result-category-size": "{{PLURAL:$1|1 mèmber|$1 mèmber}} ({{PLURAL:$2|1 sot-categorìa|$2 sot-categorìe}}, {{PLURAL:$3|1 archivi|$3 archivi}})",
-       "search-result-score": "Arlevansa: $1%",
        "search-redirect": "(ridiression $1)",
        "search-section": "(session $1)",
        "search-file-match": "(a corëspond al contnù d'archivi)",
        "searchall": "tuti",
        "showingresults": "Ambelessì-sota a treuva fin a {{PLURAL:$1|'''1'''|'''$1'''}} arzultà, a parte dal nùmer #'''$2'''.",
        "showingresultsinrange": "Smon-e sì-sota fin-a a {{PLURAL:$1|<strong>1</strong>|<strong>$1</strong>}} arzultà ant la serie da #<strong>$2</strong> a #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Arzultà '''$1''' ëd '''$3'''|Arzultà '''$1 - $2''' ëd '''$3'''}} për '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Arzultà <strong>$1</strong> ëd <strong>$3</strong>|Arzultà <strong>da $1 a $2</strong> ëd <strong>$3</strong>}}",
        "search-nonefound": "A-i é gnun arzultà për l'arserca.",
        "powersearch-legend": "Arserca avansà",
        "powersearch-ns": "Sërché ant jë spassi nominaj:",
        "powersearch-togglelabel": "Buté na marca:",
        "powersearch-toggleall": "Tùit",
        "powersearch-togglenone": "Gnun",
+       "powersearch-remember": "Visesse dla selession për j'arserche a vnì",
        "search-external": "Arserca esterna",
        "searchdisabled": "L'arserca anterna ëd {{SITENAME}} a l'é nen abilità; për adess a peul prové a dovré un motor d'arserca estern coma Google. (Però che a ten-a da ment che ij contnù ëd {{SITENAME}} listà ant ij motor pùblich a podrìo ëdcò esse nen d'autut agiornà)",
        "search-error": "A l'é rivaje n'eror durant l'arserca: $1",
        "preferences": "Mè gust",
        "mypreferences": "Gust",
        "prefs-edits": "Nùmer ëd modìfiche fàite:",
-       "prefsnologintext2": "Për piasì, ch'a $1 për definì ij gust d'utent.",
+       "prefsnologintext2": "Për piasì, ch'a rintra ant ël sistema për modifiché ij sò gust d'utent.",
        "prefs-skin": "Facia",
        "skin-preview": "Preuva",
        "datedefault": "Franch l'istess",
        "right-move": "Tramudé le pàgine",
        "right-move-subpages": "Tramudé dle pàgine con soe sot-pàgine",
        "right-move-rootuserpages": "Tramudé le pàgine prinsipaj ëd j'utent",
+       "right-move-categorypages": "Tramudé dle pàgine ëd categorìa",
        "right-movefile": "Tramudé j'archivi",
        "right-suppressredirect": "Creé nen ëd ridiression da la pàgina sorgiss an tramudand le pàgine",
        "right-upload": "Carié d'archivi",
        "right-deletedtext": "Vëdde ël test ëscancelà e le modìfiche antra le revision ëscancelà",
        "right-browsearchive": "Sërché dle pàgine scancelà",
        "right-undelete": "Arcuperé na pàgina",
-       "right-suppressrevision": "Esaminé e arcuperé le revision stërmà da j'aministrator",
+       "right-suppressrevision": "Vëdde, stërmé e smon-e torna dle revision ëspessìfiche ëd pàgine për qualsëssìa utent",
+       "right-viewsuppressed": "Smon-e le revision ëstermà për qualsëssìa utent",
        "right-suppressionlog": "Vardé ij registr privà",
        "right-block": "Bloché le modìfiche d'àutri utent",
        "right-blockemail": "Bloché n'utent da mandé 'd mëssagi an pòsta eletrònica",
        "action-createpage": "creé dle pàgine",
        "action-createtalk": "creé dle pàgine ëd discussion",
        "action-createaccount": "creé ës cont utent",
+       "action-history": "smon-e la stòria ëd costa pàgina",
        "action-minoredit": "marché sta modìfica-sì com minor",
        "action-move": "tramudé sta pàgina-sì",
        "action-move-subpages": "tramudé sta pàgina-sì e soe sot-pàgine",
        "action-move-rootuserpages": "tramudé le pàgine prinsipaj dj'utent",
+       "action-move-categorypages": "tramudé dle pàgine ëd categorìa",
        "action-movefile": "tramudé cost'archivi",
        "action-upload": "carié st'archivi",
        "action-reupload": "coaté cost archivi esistent",
        "recentchanges-legend-heading": "'''Legend:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vëdde ëdcò la [[Special:NewPages|lista dle pàgine neuve]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Ambelessì sota a-i é la lista dle modìfiche da <strong>$2</strong> (mostrà fin-a a <strong>$1</strong>).",
+       "rcnotefrom": "Ambelessì sota a-i é {{PLURAL:$5|la modìfica|le modìfiche}} da <strong>$3, $4</strong> (mostrà fin-a a <strong>$1</strong>).",
        "rclistfrom": "Mostré le modìfiche a parte da $3 $2",
        "rcshowhideminor": "$1 le modìfiche cite",
        "rcshowhideminor-show": "Smon-e",
        "largefileserver": "St'archivi-sì a resta pì gròss che lòn che la màchina sentral a përmet.",
        "emptyfile": "L'archivi che a l'ha pen-a carià a smija veujd.\nSòn a podrìa esse rivà përchè che chiel a l'ha scrivù mal ël nòm dl'archivi midem.\nPër piasì che a contròla se a l'é pro cost l'archivi che a veul carié.",
        "windows-nonascii-filename": "Sta wiki-sì a manten pa ij nòm d'archivi con caràter speciaj.",
-       "fileexists": "N'archivi con ës nòm-sì a-i é già, për piasì che a contròla <strong>[[:$1]]</strong> se a l'é pa sigur dë vorèj cangelo.\n[[$1|thumb]]",
+       "fileexists": "N'archivi con ës nòm-sì a-i é già, për piasì che a contròla <strong>[[:$1]]</strong> se {{GENDER|a}} l'é pa sigur dë vorèj cangelo.\n[[$1|thumb]]",
        "filepageexists": "La pàgina ëd descrission për st'archivi-sì a l'é già stàita creà an <strong>[[:$1]]</strong>, mach ch'a-i é gnun archivi ch'as ciama parèj.\nLòn ch'a buta për somari as ës-ciairerà nen ant la pàgina ëd descrission.\nPër podèj buté sò somari a l'ha da modifichesse la pàgina a man.\n[[$1|thumb]]",
-       "fileexists-extension": "N'archivi con ës nòm-sì a-i é già: [[$2|thumb]]\n* Nòm dl'archivi ch'as carìa: <strong>[[:$1]]</strong>\n* Nòm dl'archivi ch'a-i é già: <strong>[[:$2]]</strong>\nPër piasì, ch'a serna un nòm diferent.",
+       "fileexists-extension": "N'archivi con ës nòm-sì a-i é già: [[$2|thumb]]\n* Nòm dl'archivi ch'as carìa: <strong>[[:$1]]</strong>\n* Nòm dl'archivi ch'a-i é già: <strong>[[:$2]]</strong>\nVeul-lo dle vire dovré un nòm pi esplìssit?",
        "fileexists-thumbnail-yes": "L'archivi a jë smija a na ''figurin-a''. [[$1|thumb]]\nPër piasì, ch'a contròla l'archivi <strong>[[:$1]]</strong>.\nS'a l'é la midema figura a amzura pijn-a, a veul dì ch'a fa nen dë manca dë carié na figurin-a.",
        "file-thumbnail-no": "Ël nòm dl'archivi as anandia con <strong>$1</strong>.\nA jë smija a na ''figurin-a''.\nSe a l'ha na figura a amzura pijn-a a l'é mej ch'a carìa cola-lì, dësnò ch'a-j cangia nòm a l'archivi, për piasì.",
        "fileexists-forbidden": "Belavans n'archivi con ës nòm-sì a-i é già, donca ël nòm as peul pa pì dovresse.\nSe a veul ancó cariè sò archivi, për piasì ch'a torna andré e ch'a deuvra n'àutr nòm. [[File:$1|thumb|center|$1]]",
        "uploadwarning": "Avis che i soma dapress a carié",
        "uploadwarning-text": "Për piasì, ch'a modìfica la descrission ëd l'archivi sì-sota e ch'a preuva torna.",
        "savefile": "Salvé l'archivi",
-       "uploadedimage": "a l'ha carià \"[[$1]]\"",
-       "overwroteimage": "a l'ha carìa na version neuva ëd \"[[$1]]\"",
        "uploaddisabled": "Càrich blocà.",
        "copyuploaddisabled": "Ël càrich për mojen ëd n'adrëssa dl'aragnà a l'é disabilità.",
        "uploaddisabledtext": "La possibilità ëd carié dj'archivi a l'é staita disabilità.",
        "license": "Licensa:",
        "license-header": "Licensa",
        "nolicense": "Gnun-a selession fàita",
+       "licenses-edit": "Modifiché j'opsion Ëd licensa",
        "license-nopreview": "(Gnun-a preuva ch'as peula smon-se)",
-       "upload_source_url": "(n'anliura bon-a e che as peula dovresse)",
-       "upload_source_file": "(n'archivi da sò ordinator)",
+       "upload_source_url": "(l'archivi ch'a l'ha sernù da n'adrëssa an s'Aragnà bon-a e ch'as peula acede ëd fasson pùblica)",
+       "upload_source_file": "(sò archivi sernù da sò ordinator)",
+       "listfiles-delete": "scancelé",
        "listfiles-summary": "Sta pàgina special-sì a smon tuti j'archivi ch'a son ëstàit carià.",
        "listfiles_search_for": "Arserché un nòm d'archivi multimojen:",
        "imgfile": "archivi",
        "filedelete-maintenance": "Lë scancelament e la restaurassion d'archivi a l'é al moment disabilità durant la manutension.",
        "filedelete-maintenance-title": "As peul pa scancelesse l'archivi",
        "mimesearch": "Arserca për sòrt MIME",
-       "mimesearch-summary": "Sta pàgina-sì a lassa filtré j'archivi për sòrt MIME. Buté: sòrt/sotasòrt, pr'es. <code>image/jpeg</code>.",
+       "mimesearch-summary": "Sta pàgina-sì a lassa filtré j'archivi për sòrt MIME. Buté: sòrt/sotasòrt o sòrt/*, pr'es. <code>image/jpeg</code>.",
        "mimetype": "Sòrt MIME:",
        "download": "dëscarié",
        "unwatchedpages": "Pàgine che gnun a ten sot-euj",
        "randomincategory": "Pàgina a l'ancàpit ant la categorìa",
        "randomincategory-invalidcategory": "«$1» a l'é pa un nòm ëd categorìa bon.",
        "randomincategory-nopages": "A-i é gnun-e pàgine ant la categorìa [[:Category:$1|$1]].",
-       "randomincategory-selectcategory": "Pijé na pàgina a l'ancàpit da 'nt la categorìa: $1 $2.",
-       "randomincategory-selectcategory-submit": "Andé",
+       "randomincategory-category": "Categorìa:",
+       "randomincategory-legend": "Pàgina a l'ancàpit ant la categorìa",
        "randomredirect": "Na ridiression qualsëssìa",
        "randomredirect-nopages": "A-i é pa gnun-a ridiression ant lë spassi nominal \"$1\".",
        "statistics": "Statìstiche",
        "doubleredirects": "Ridiression dobie",
        "doubleredirectstext": "Sta pàgina-sì a a lista dle pàgine ch'a armando a d'àutre pàgine ëd ridiression.\nVira riga a l'ha andrinta j'anliure a la prima e a la sconda ridiression, ant sël pat ëd la prima riga ëd test dla seconda ridiression, che për sòlit a l'ha andrinta l'artìcol ëd destinassion vèir, col andoa che a dovrìa ëmné ëdcò la prima ridiression.\nLe ridiression <del>sganfà</del> a son stàite arzolvùe.",
        "double-redirect-fixed-move": "[[$1]] a l'é stàit spostà.\nA l'é stàit agiornà an automàtich e adess a l'é na ridiression a [[$2]].",
-       "double-redirect-fixed-maintenance": "Rangé le ridiression dobie da [[$1]] a [[$2]].",
+       "double-redirect-fixed-maintenance": "Coression automàtica dle ridiression dobie da [[$1]] a [[$2]] ant un travaj ëd manutension.",
        "double-redirect-fixer": "Coretor ëd ridiression",
        "brokenredirects": "Ridiression nen giuste",
        "brokenredirectstext": "Coste ridiression-sì a men-o a d'artìcoj ch'a-i son pa:",
        "wantedpages-badtitle": "Tìtol nen vàlid ant l'ansema dj'arzultà: $1",
        "wantedfiles": "Archivi pì ciamà",
        "wantedfiletext-cat": "J'archivi ch'a ven-o a son dovrà ma a esisto pa. J'archivi dai sò depòsit estern a peulo esse listà sensa consideré l'esistensa. Chèich fàuss positiv a saran <del>sganfà</del>. An pi, le pàgine ch'a conten-o dj'archivi ch'a esisto pa a son listà an [[:$1]].",
+       "wantedfiletext-cat-noforeign": "J'archivi sì-dapress a son dovrà ma a esisto nen. An dzorpì, le pàgina ch'a conten-o d'archivi ch'a esisto nen a son listà an [[:$1]].",
        "wantedfiletext-nocat": "J'archivi sì-dapress a son dovrà ma a esisto pa. J'archivi da depòsit estern a peulo esse listà sensa considerene l'esistensa. Tùit costi fàuss positiv a saran <del>ësganfà</del>.",
+       "wantedfiletext-nocat-noforeign": "J'archivi sì-dapress a son dovrà ma a esisto pa.",
        "wantedtemplates": "Stamp ciamà",
        "mostlinked": "Pàgine che a l'han pì d'anliure che a-i men-o la gent ansima",
        "mostlinkedcategories": "Categorìe che a l'han pì d'anliure che a-i men-o la gent ansima",
-       "mostlinkedtemplates": "Stamp pì dovrà",
+       "mostlinkedtemplates": "Pàgine pi ancludùe",
        "mostcategories": "Artìcoj che a son marcà an pì categorìe",
        "mostimages": "Figure pì dovrà",
        "mostinterwikis": "Pàgine con pi 'd liure antërwiki",
        "trackingcategories-desc": "Criteri d'anclusion dla categorìa",
        "noindex-category-desc": "La pàgina a l'é pa trassà dai robò përchè a conten la paròla màgica <code><nowiki>__NOINDEX__</nowiki></code> andrinta e a l'é an në spassi nominal anté che cost marcagi a l'é autorisà.",
        "index-category-desc": "La pàgina a conten un <code><nowiki>__INDEX__</nowiki></code> (e a l'é an në spassi nominal anté che ëd marcagi a l'é autorisà); a l'é donca trassà dai robò antant che ëd sòlit a lo sarìa nen.",
-       "post-expand-template-inclusion-category-desc": "Apress avèj dësvlupà tuti jë stamp, la taja dla pàgina a sorpassa <code>$wgMaxArticleSize</code>, donca chèich ëstamp a son nen ëstàit dësvlupà.",
-       "post-expand-template-argument-category-desc": "Apress avèj dësvlupà l'argoment ëd në stamp (cheicòs antra tripl agraf, tanme <code>{{{Foo}}}</code>), la pàgina a l'é pi gròssa che <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Tròpe fonsion care ëd l'analisator (parèj ëd <code>#ifexist</code>) contnùe an na pàgina. Ch'a vëdda [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "post-expand-template-inclusion-category-desc": "La taja dla pàgina a sorpassa <code>$wgMaxArticleSize</code> apress avèj dësvlupà tuti jë stamp, donca chèich ëstamp a son nen ëstàit dësvlupà.",
+       "post-expand-template-argument-category-desc": "La pàgina a l'é pi gròssa che <code>$wgMaxArticleSize</code>, apress avèj dësvlupà l'argoment ëd në stamp (cheicòs antra tripl agraf, tanme <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "Costa pàgina a deuvra tròpe fonsion care ëd l'analisator (parèj ëd <code>#ifexist</code>). Ch'a vëdda [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "La pàgina a conten na liura d'archivi cioca (na liura për anclude n'archivi cand l'archivi a esist nen).",
+       "hidden-category-category-desc": "La categorìa a conten <code><nowiki>__HIDDENCAT__</nowiki></code> an sò sontnù, lòn ch'a j'ampediss d'esse smonùa ant la casela dle liure ëd categorìa an sle pàgine, 'me stàndard.",
+       "trackingcategories-nodesc": "Gnun-a descrission disponìbil.",
+       "trackingcategories-disabled": "La categorìa a l'é disabilità",
        "mailnologin": "A-i é pa l'adrëssa për mandé ël mëssagi",
        "mailnologintext": "A dev [[Special:UserLogin|rintré ant ël sistema]]\ne avèj registrà n'adrëssa ëd pòsta eletrònica vàlida ant ij [[Special:Preferences|sò gust]] për podèj mandé dij mëssagi ëd pòsta eletrònica a j'àutri Utent.",
        "emailuser": "Mandeje un mëssagi eletrònich a st'utent-sì",
        "mywatchlist": "Ròba che as ten sot euj",
        "watchlistfor2": "Për $1 $2",
        "nowatchlist": "A l'ha ancó pa marcà dj'artìcoj coma ròba da tnì sot-euj.",
-       "watchlistanontext": "Për piasì, $1 për ës-ciairé ò pura modifiché j'element ëd soa lista dla ròba che as ten sot-euj.",
+       "watchlistanontext": "Për piasì, ch'a rintra ant ël sistema për ës-ciairé ò pura modifiché j'element ëd soa lista dla ròba che as ten sot-euj.",
        "watchnologin": "A l'é ancó nen rintrà ant ël sistema",
        "addwatch": "Gionté a la lista ëd lòn ch'as ten sot-euj",
        "addedwatchtext": "La pàgina «[[:$1]]» a l'é staita giontà a soa [[Special:Watchlist|lista dla ròba da tnì sot-euj]].\nLe modìfiche che a-i saran ant costa pàgina-sì e ant soa pàgina ëd discussion a saran listà ambelessì.",
+       "addedwatchtext-short": "La pàgina «$1» a l'é stàita giontà a la lista ëd lòn ch'as ten sot-euj.",
        "removewatch": "Gavé da la lista ëd lòn ch'as ten sot-euj",
        "removedwatchtext": "La pàgina «[[:$1]]» a l'è staita gavà via da [[Special:Watchlist|soa lista dla ròba da tnì sot-euj]].",
+       "removedwatchtext-short": "La paàgina «$1» a l'é stàita gavà da la lista ëd lòn ch'as ten sot-euj.",
        "watch": "ten-e sot-euj",
        "watchthispage": "Ten-e sot-euj cost artìcol-sì",
        "unwatch": "Chité-lì ëd ten-e sossì sot-euj",
        "unwatchthispage": "Chité-lì ëd ten-e sossì sot-euj",
        "notanarticle": "Sòn a l'é pa n'artìcol",
        "notvisiblerev": "La revision a l'é stàita scancelà",
-       "watchlist-details": "A l'é dëmentrè ch'as ten sot-euj {{PLURAL:$1|$1 pàgina|$1 pàgine}}, nen contand cole ëd discussion.",
+       "watchlist-details": "A l'é dëmentrè ch'as ten sot-euj {{PLURAL:$1|$1 pàgina|$1 pàgine}}, nen contand an manera separà cole ëd discussion.",
        "wlheader-enotif": "La notìfica për pòsta eletrònica a l'é abilità.",
        "wlheader-showupdated": "Le pàgine che a son ëstàite modificà da quand che a l'é passaje ansima l'ùltima vira a resto marcà an '''grassèt'''",
-       "wlnote2": "Sì-sota a-i son le modìfiche {{PLURAL:$1|ant l'ùltima ora|ant j'ùltime <strong>$1</strong> ore}}, a parte da $2, $3.",
+       "wlnote": "Ambelessì sota a-i {{PLURAL:$1|é l'ùltima modìfica|son j'ùltime <strong>$1</strong> modìfiche}} ant {{PLURAL:$2|l'ùltima ora|j'ùltime <strong>$2</strong> ore}}, a parte da $3, $4.",
        "wlshowlast": "Smon-e j'ùltime $1 ore $2 dì $3",
        "watchlist-options": "Opsion ëd la lista dla ròba ch'as ten sot-euj",
        "watching": "Sot-euj...",
        "exbeforeblank": "anans d'esse dësvujdà ël contnù a l'era: «$1»",
        "delete-confirm": "Scancelé «$1»",
        "delete-legend": "Scancelé",
-       "historywarning": "'''Avis:''' La pàgina che a l'é antramentr che a scancela a l'ha na stòria con pi o men $1 {{PLURAL:$1|revision|revision}}:",
+       "historywarning": "<strong>Avis:</strong> La pàgina che a l'é antramentr che a scancela a l'ha na stòria con $1 {{PLURAL:$1|revision}}:",
        "confirmdeletetext": "A sta për scancelé d'autut da 'nt la base dat na pàgina ò pura na figura, ansema a tuta soa cronologìa.<p>\nPër piasì, che an conferma che sòn a l'é da bon sò but, che a as rend cont ëd le conseguense ëd lòn che a fa, e che sòn a resta an pien an régola con lòn che a l'é stabilì ant la [[{{MediaWiki:Policy-url}}]].",
        "actioncomplete": "Travaj fait e finì",
        "actionfailed": "Assion falìa",
        "delete-edit-reasonlist": "Modifiché la rason dlë scancelament",
        "delete-toobig": "Sta pàgina-sì a l'ha na stòria motobin longa, bele pì che $1 {{PLURAL:$1|revision|revision}}.\nLë scancelassion ëd pàgine parèj a l'é stàita limità për evité ch'as fasa darmagi për eror a {{SITENAME}}.",
        "delete-warning-toobig": "Sta pàgina-sì a l'ha na stòria motobin longa, bele pì che $1 {{PLURAL:$1|revision|revision}}.\nA scancelela as peul fesse darmagi a j'operassion dla base ëd dat ëd {{SITENAME}};\nch'a daga da ment a lòn ch'a fa.",
+       "deleteprotected": "A peul nen ëscancelé costa pàgina përchè a l'é proteta.",
        "deleting-backlinks-warning": "'''Avis:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|D'àutre pàgine]] a l'han na liura o a transcludo la pàgina che chiel a veul ëscancelé.",
        "rollback": "Gavé via le modìfiche",
        "rollback_short": "Ripristiné",
        "contributions-title": "Contribussion ëd $1",
        "mycontris": "Contribussion",
        "contribsub2": "Për {{GENDER:$3|$1}} ($2)",
+       "contributions-userdoesnotexist": "Ël cont utent «$1» a l'é pa argistrà.",
        "nocontribs": "A l'é pa trovasse gnun-a modìfica che a fussa conforma a costi criteri-sì",
        "uctop": "(corenta)",
        "month": "Mèis:",
        "sp-contributions-newbies-sub": "Për j'utent neuv",
        "sp-contributions-newbies-title": "Contribussion ëd j'utent për ij neuv cont",
        "sp-contributions-blocklog": "argistr dij blocagi",
+       "sp-contributions-suppresslog": "contribussion eliminà",
        "sp-contributions-deleted": "Modìfiche d'utent scancelà",
        "sp-contributions-uploads": "cariagi",
        "sp-contributions-logs": "registr",
        "autoblockid": "Blocagi automàtich #$1",
        "block": "Bloché l'utent",
        "unblock": "Dësbloché l'utent",
-       "blockip": "Bloché l'utent",
+       "blockip": "Bloché l'{{GENDER:$1|utent}}",
        "blockip-legend": "Bloché l'utent",
        "blockiptext": "Che a deuvra ël mòdulo ëd domanda 'd blocagi ambelessì sota për bloché l'acess con drit dë scritura da chèich adrëssa IP o stranòm.<br />\nËs blocagi-sì as dev dovresse MACH për evité dij comportament vandàlich, ën strèita osservansa ëd tùit ij prinsipi dle [[{{MediaWiki:Policy-url}}|régole ëd {{SITENAME}}]].<br />\nËl blocagi a peul ën gnun-a manera esse dovrà për dle question d'ideologìa.\n\nChe a scriva codì che st'adrëssa IP o së stranòm a dev second chiel esse blocà (pr'esempi, che a buta ij tìtoj ëd pàgine che a l'abio già patì dj'at vandàlich da cost'adrëssa IP o së stranòm).",
        "ipaddressorusername": "Adrëssa IP ò stranòm",
        "ipb-unblock-addr": "Dësbloché $1",
        "ipb-unblock": "Dësbloché n'utent ò n'adrëssa IP",
        "ipb-blocklist": "Vardé ij blocagi ativ",
-       "ipb-blocklist-contribs": "Contribussion për $1",
+       "ipb-blocklist-contribs": "Contribussion për {{GENDER:$1|$1}}",
        "unblockip": "Dësbloché n'utent",
        "unblockiptext": "Che a deuvra ël formolari ambelessì-sota për deje andré ël drit dë scritura a n'adrëssa IP o në stranòm che a l'era stàit blocà.",
        "ipusubmit": "Gavé ës blocagi",
        "unblocked": "[[User:$1|$1]] a l'é stait dësblocà",
        "unblocked-range": "$1 a l'é stàit dësblocà",
        "unblocked-id": "Ël blocagi $1 a l'é stait gavà via",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] a l'é stàit dësblocà.",
        "blocklist": "Utent blocà",
        "ipblocklist": "Utent blocà",
        "ipblocklist-legend": "Trové n'utent blocà",
        "import": "Amportassion ëd pàgine",
        "importinterwiki": "Amportassion da wiki diferente",
        "import-interwiki-text": "Che a selession-a na wiki e ël tìtol dla pàgina da amporté.\nDate dle revision e stranòm dj'editor a resteran piàjit sù 'cò lor.\nTute j'amportassion antra wiki diferente a resto marcà ant ël [[Special:Log/import|Registr dj'amportassion]].",
-       "import-interwiki-source": "Wiki e pàgina sorgiss:",
        "import-interwiki-history": "Copié tute le revision ëd la stòria ëd costa pàgina",
        "import-interwiki-templates": "Anserì tùit jë stamp",
        "import-interwiki-submit": "Amporté",
index 3029c96..edf2a8e 100644 (file)
        "talkpagelinktext": "گل بات",
        "specialpage": "خاص صفحہ",
        "personaltools": "ذاتی اوزار",
-       "postcomment": "نویں ونڈ",
        "articlepage": "مضمون آلا صفحہ",
        "talk": "گل بات",
        "views": "وکھالے",
        "externaldberror": "ڈیٹابیس چ توانوں پہچاننے چ کوئی مسئلہ ہویا اے یا فیر تسی اپنا بارلا کھاتا نئیں بدل سکدے۔",
        "login": "اندر آؤ جی",
        "nav-login-createaccount": "اندر آؤ / کھاتہ کھولو",
-       "loginprompt": "اندر آنے آستے تواڈیاں کوکیز آن ہونیاں چائیدیاں نے {{SITENAME}}.",
        "userlogin": "اندر آؤ / کھاتہ کھولو",
        "userloginnocreate": "اندر آؤ جی",
        "logout": "لاگ توں باہر",
        "searchprofile-advanced-tooltip": "کسٹم ناواں چ لبو",
        "search-result-size": "$1 ({{PLURAL:$2|1 لفظ|$2 الفاظ}})",
        "search-result-category-size": "{{PLURAL:$1|1 سنگی|$1 سنگی}} ({{PLURAL:$2|1 نکیاں گٹھاں|$2 نکیاں گٹھاں}}, {{PLURAL:$3|1 فائل|$3 فائلاں}})",
-       "search-result-score": "مہاندرا:  $1%",
        "search-redirect": "($1 ریڈائریکٹ)",
        "search-section": "($1 ٹوٹا)",
        "search-suggest": "تسی $1 دی گل تے نئیں کر رۓ:",
        "uploadwarning": "فائل چڑانے توں خبردار",
        "uploadwarning-text": "تھلے فائل بارے دس بدلو تے فیر کوشش کرو۔",
        "savefile": "فائل بچاؤ",
-       "uploadedimage": "چڑھائی گئی\"[[$1]]\"",
-       "overwroteimage": "\"[[$1]]\" دا اک نواں ورین چڑھاؤ",
        "uploaddisabled": "فائل چڑانا بند اے",
        "copyuploaddisabled": "یو آر این لے چڑھانا نکارہ کیتا۔",
        "uploaddisabledtext": "فائل چڑانے چ رکاوٹ اے۔",
        "watchlist-details": "{{PLURAL:$1|$1 صفحہ|$1 صفحہ}} تواڈی اکھ تھلے گلاں باتاں شامل نہیں۔",
        "wlheader-enotif": "ای-میل نوٹیفیکیشن قابل",
        "wlheader-showupdated": " صفے جیہڑے بدلے کۓ تھواڈے آخری وار آن مکرون  اونان نوں موٹا کرکے دسیا گیا اے۔",
+       "wlnote": "تھلے {{PLURAL:$1|آخری تبدیلی|آخری تبدیلیاں '''1$''' }} آخر تے {{PLURAL:$2|کینٹہ|'''2$''' کینٹے}} 3$، 4$.",
        "wlshowlast": "آخری $1 گھنٹے $2 دن $3 وکھاؤ",
        "watchlist-options": "نظر تھلے رکھن دیاں راہواں",
        "watching": "نظر تھلے۔۔۔۔",
        "duplicate-defaultsort": "'''خبردار:''' ڈیفالٹ چابی \"$2\" پہلی ڈیفالٹ چابی \"$1\" دے اتے لگ گئی اے۔",
        "version": "ورژن",
        "version-extensions": "انسٹالڈ کیتیاں گیاں ایکسٹنشن",
+       "version-skins": "کھل",
        "version-specialpages": "خاص صفے",
        "version-parserhooks": "پارسر ہکز",
        "version-variables": "ویریایبلز",
        "version-antispam": "سپام بچاؤ",
-       "version-skins": "کھل",
        "version-other": "دوجے",
        "version-mediahandlers": "میڈیا ہینڈلرز",
        "version-hooks": "ہکز",
index eb0d128..b51b871 100644 (file)
        "talkpagelinktext": "Καλάτσεμαν",
        "specialpage": "Ειδικόν σελίδαν",
        "personaltools": "Προσωπικά εργαλεία",
-       "postcomment": "Νέον κομμάτ'",
        "articlepage": "Σελίδα",
        "talk": "Καλάτσεμαν",
        "views": "Τερέματα",
        "yourdomainname": "Το domain εσούν:",
        "login": "Εμπάτε",
        "nav-login-createaccount": "Εμπάτεν / ποισέστεν λογαρίαν",
-       "loginprompt": "Πρέπ' ν' άφτετε τα cookies για εμπείτε σο {{SITENAME}}.",
        "userlogin": "Εμπάτεν / ποισέστεν λογαρίαν",
        "userloginnocreate": "Εμπάτεν",
        "logout": "οξουκά",
        "badfilename": "Τόνεμαν ταρχείου ελλάγεν κιεγέντον \"$1\".",
        "filetype-missing": "Τ' αρχείον τιδέν 'κ έχ' κατάληξην (άμον \".jpg\").",
        "savefile": "Αποθήκεψον τ' αρχείον",
-       "uploadedimage": "Εγέντον το φόρτωμαν τη \"[[$1]]\"",
-       "overwroteimage": "Εφορτώθεν καινούρεον μορφή τη \"[[$1]]\"",
        "watchthisupload": "Ωρίαγμαν τη αρχείου",
        "upload-file-error": "Σφάλμαν απές μερέαν",
        "upload-misc-error": "Αναγνώριμον λάθος φορτωματί",
index 258bdc9..f4f403e 100644 (file)
        "talkpagelinktext": "Diskusiōni",
        "specialpage": "Speciālin pāusan",
        "personaltools": "Persōniskas pagaptis",
-       "postcomment": "Naunā sekciōni",
        "articlepage": "Wīdais ēnturas pāusan",
        "talk": "Diskusiōni",
        "views": "Pawīda",
        "externaldberror": "Tikka izwinaīnas autentikāntin dātanbazin blānda, anga ni assei enwarīntan kāi etnaunīnlai twajjan izwinaīnan rekkenan.",
        "login": "Enjaīs",
        "nav-login-createaccount": "Enjaīs / teīkeis rekkenan",
-       "loginprompt": "Tu turri turītun <i>cookies</i> enklaūtan, kāi enēilai en {{SITENAME}}.",
        "userlogin": "Enjaīs / teīkeis rekkenan",
        "userloginnocreate": "Enjaīs",
        "logout": "Izjaīs",
        "searchprofile-everything-tooltip": "Laukīs en pastippai ēnturan (dīgi en diskusiōnis pāusamans)",
        "searchprofile-advanced-tooltip": "Laukīs en etrinktammans tītelin plattibins",
        "search-result-size": "$1 ({{PLURAL:$2|1 wīrds|$2 wīrdai}})",
-       "search-result-score": "Ebtikewīngisku $1%",
        "search-redirect": "(prawessenis $1)",
        "search-section": "(sekciōni $1)",
        "search-suggest": "Mīriwuns(si) tū ezze: $1",
        "uploadwarning": "Ēmpirsergīsenis ezze enkraūsnan",
        "uploadwarning-text": "Madli kitawīdinais zūrbukes ebpeisāsenis be bandais etkūmps",
        "savefile": "Enpeisāis zūrbrukin",
-       "uploadedimage": "ast enkraūwuns(si) \"[[$1]]\"",
-       "overwroteimage": "ast enkraūwuns(si) nāunan wersiōnin stesse \"[[$1]]\"",
        "uploaddisabled": "Zūrbrukin enkrausnā izklaūtan",
        "uploaddisabledtext": "Zūrbrukin enkrausnā pastāi izklaūtan.",
        "php-uploaddisabledtext": "Zūrbrukin enkrausnā ast drēuditan en PHP.\nIzbandais ensadīnsenin „file_uploads”.",
        "watchlist-details": "Ast {{PLURAL:$1|$1 pāusan|$1 pāusai}} en twajjai listin stēisan nadirītan, ni gīrbawintei diskusiōnis pāusans.",
        "wlheader-enotif": "E-mail pawakīsenei ast enklaūtan.",
        "wlheader-showupdated": "Pastāi '''pastarīntan''' pāusai,  kawīdai bēi kitawīdintan ezze Twajjai panzdauman tenēisan kāimalukisnan..",
+       "wlnote": "Zemmais pawaidinnā di {{PLURAL:$1|panzdauman kitawīdinsnan|panzdaumans '''$1''' kitawīdinsnans}} en {{PLURAL:$2|panzdauman stundin|'''$2''' panzdaumans stundins}}.",
        "wlshowlast": "Waidinnais panzdaumans $1 stūndins, $2 dēinans ($3)",
        "watchlist-options": "Nadirītan listis mazīngiskwas",
        "watching": "As nadirēi...",
index 7ca0e55..dc00401 100644 (file)
        "talkpagelinktext": "خبرې اترې",
        "specialpage": "ځانگړې پاڼه",
        "personaltools": "شخصي اوزار",
-       "postcomment": "نوې برخه",
        "articlepage": "د مخ مېنځپانگه ښکاره کول",
        "talk": "خبرې اترې",
        "views": "کتنې",
        "password-change-forbidden": "تاسې په دې ويکي باندې خپل پټنوم نه شی بدلولی.",
        "login": "ننوتل",
        "nav-login-createaccount": "ننوتل / گڼون جوړول",
-       "loginprompt": "ددې لپاره چې {{SITENAME}} کې ننوځۍ نو بايد ستاسې د کمپيوټر کوکيز چارن وي.",
        "userlogin": "ننوتل / گڼون جوړول",
        "userloginnocreate": "ننوتل",
        "logout": "وتل",
        "searchprofile-advanced-tooltip": "د خپل خوښې په نوم-تشيالونو کې پلټل",
        "search-result-size": "$1 ({{PLURAL:$2|1 ويی|$2 وييونه}})",
        "search-result-category-size": "{{PLURAL:$1|1 غړی|$1 غړي}} ({{PLURAL:$2|1 څېرمه وېشنيزه|$2 څېرمه وېشنيزې}}، {{PLURAL:$3|1 دوتنه|$3 دوتنې}})",
-       "search-result-score": "اړوندتوب: $1%",
        "search-redirect": "(د $1 مخ ګرځونه)",
        "search-section": "(برخه $1)",
        "search-suggest": "آيا همدا مو موخه وه: $1",
        "file-exists-duplicate": "همدا دوتنه د {{PLURAL:$1|لاندينۍ دوتنې|لاندينيو دوتنو}} غبرگه لمېسه ده:",
        "uploadwarning": "د پورته کولو گواښ",
        "savefile": "دوتنه خوندي کړه",
-       "uploadedimage": "\"[[$1]]\" پورته شوه",
        "uploaddisabled": "پورته کول ناچارن شوي",
        "uploaddisabledtext": "د دوتنې پورته کولو آسانتياوې ناچارن شوي.",
        "uploadvirus": "دا دوتنه ويروس لري! تفصيل: $1",
        "watchlist-details": "ستاسې کتنلړ کې {{PLURAL:$1|$1 مخ دی|$1 مخونه دي}}، د خبرو اترو مخونه مو بېل نه دي شمېرلي.",
        "wlheader-enotif": "برېښليک خبرونه چارنه شوې.",
        "wlheader-showupdated": "هغه مخونه چې ستاسې د کتلو نه وروسته بدلون موندلی په '''روڼ''' ليک په نښه شوي.",
+       "wlnote": "دلته لاندې {{PLURAL:$1|وروستی بدلون دی|وروستي '''$1''' بدلونونه دي}} چې په {{PLURAL:$2|تېر ساعت|تېرو '''$2''' ساعتونو}} کې تر $3 نېټې او $4 بجو پېښ شوي.",
        "wlshowlast": "وروستي $1 ساعتونه $2 ورځې $3 ښکاره کړه",
        "watchlist-options": "د کتنلړ خوښنې",
        "watching": "د کتلو په حال کې...",
        "duplicate-defaultsort": "'''گواښنه:'''د \"$2\" تلواليزه اوډون تڼۍ تر دې پخوا ټاکلې تلواليزه اوډون تڼۍ \"$1\" پر ځای چارنه کېږي.",
        "version": "بڼه",
        "version-extensions": "لگېدلي شاتاړي",
-       "version-specialpages": "ځانگړي مخونه",
        "version-skins": "پوښۍ",
+       "version-specialpages": "ځانگړي مخونه",
        "version-other": "بل",
        "version-hooks": "کونډۍ",
        "version-hook-name": "کونډۍ نوم",
index ff4c931..d952210 100644 (file)
@@ -88,6 +88,7 @@
        "tog-watchdefault": "Adicionar as páginas e arquivos que eu editar à minha lista de páginas vigiadas",
        "tog-watchmoves": "Adicionar as páginas e arquivos que eu mover à minha lista de páginas vigiadas",
        "tog-watchdeletion": "Adicionar as páginas e arquivos que eu eliminar à minha lista de páginas vigiadas",
+       "tog-watchrollback": "Adicionar páginas onde fiz uma reversão às minhas páginas vigiadas",
        "tog-minordefault": "Marcar todas as edições como menores por padrão",
        "tog-previewontop": "Mostrar previsão antes da caixa de edição",
        "tog-previewonfirst": "Mostrar previsão na primeira edição",
        "talkpagelinktext": "discussão",
        "specialpage": "Página especial",
        "personaltools": "Ferramentas pessoais",
-       "postcomment": "Nova seção",
        "articlepage": "Ver página de conteúdo",
        "talk": "Discussão",
        "views": "Visualizações",
        "hidetoc": "ocultar",
        "collapsible-collapse": "Ocultar",
        "collapsible-expand": "Expandir",
+       "confirmable-confirm": "{{GENDER:$1|Tem}} a certeza?",
+       "confirmable-yes": "Sim",
+       "confirmable-no": "Não",
        "thisisdeleted": "Ver ou restaurar $1?",
        "viewdeleted": "Ver $1?",
        "restorelink": "{{PLURAL:$1|uma edição eliminada|$1 edições eliminadas}}",
        "sort-descending": "Ordenar por ordem descendente",
        "sort-ascending": "Ordenar por ordem ascendente",
        "nstab-main": "Página",
-       "nstab-user": "Página d{{GENDER:{{#titleparts:{{PAGENAME}}|1|1}}|o usuário|a usuária|e usuário(a)}}",
+       "nstab-user": "Página d{{GENDER:{{BASEPAGENAME}}|o usuário|a usuária|e usuário(a)}}",
        "nstab-media": "Página de mídia",
        "nstab-special": "Página especial",
        "nstab-project": "Página do projeto",
        "invalidtitle-knownnamespace": "Título inválido para o espaço nominal \"$2\" e texto \"$3\"",
        "invalidtitle-unknownnamespace": "Título inválido para o espaço nominal de número desconhecido ($1) e texto \"$2\"",
        "exception-nologin": "Não está autenticado",
-       "exception-nologin-text": "Por favor clique [[Special:Userlogin|log in]] para poder acessar esta página ou ação",
+       "exception-nologin-text": "Por favor clique $1 para poder acessar essa página ou ação.",
        "exception-nologin-text-manual": "Por favor clique $1 para poder acessar essa página ou ação.",
        "virus-badscanner": "Má configuração: antivírus desconhecido: ''$1''",
        "virus-scanfailed": "a verificação falhou (código $1)",
        "externaldberror": "Ocorreu ou um erro no banco de dados durante a autenticação ou não lhe é permitido atualizar a sua conta externa.",
        "login": "Autenticar-se",
        "nav-login-createaccount": "Entrar / criar conta",
-       "loginprompt": "É necessário estar com cookies ativados para poder autenticar-se no wiki {{SITENAME}}.",
        "userlogin": "Entrar / criar conta",
        "userloginnocreate": "Entrar",
        "logout": "Sair",
        "userlogin-resetlink": "Esqueceu-se do seu nome de usuário ou da senha?",
        "userlogin-resetpassword-link": "Esqueceu sua senha?",
        "userlogin-helplink2": "Ajuda com o login",
-       "userlogin-loggedin": "Você já está conectado como {{GENDER:$1|$1}}.\nUse o formulário abaixo para iniciar sessão como outro usuário.",
-       "userlogin-createanother": "Crie uma outra conta",
        "createacct-emailrequired": "Endereço de e-mail",
        "createacct-emailoptional": "Endereço de e-mail (opcional)",
        "createacct-email-ph": "Confirme seu endereço de e-mail",
        "pt-login": "Entrar",
        "pt-login-button": "Entrar",
        "pt-createaccount": "Crie uma conta",
+       "pt-userlogout": "Sair",
        "php-mail-error-unknown": "Erro desconhecido na função mail() do PHP",
        "user-mail-no-addy": "Tentou enviar uma mensagem sem um endereço de e-mail.",
        "user-mail-no-body": "Você tentou enviar com o campo de e-mail vazio ou com poucos caracteres.",
        "preview": "Pré-visualização",
        "showpreview": "Mostrar previsão",
        "showdiff": "Mostrar alterações",
+       "blankarticle": "<strong>Aviso:</strong> A página que está prestes a criar está em branco.  \nSe clicar \"{{int:savearticle}}\" outra vez, a página será criada sem qualquer conteúdo.",
        "anoneditwarning": "'''Atenção''': Você não se encontra autenticado.\nO seu endereço de IP será registrado no histórico de edições desta página.",
        "anonpreviewwarning": "''Você não está logado. Gravar registará o seu endereço IP no histórico de edições desta página.''",
        "missingsummary": "'''Lembrete:''' Você não introduziu um sumário de edição. Se clicar novamente em Salvar, a sua edição será salva sem um sumário.",
        "edit-gone-missing": "Não foi possível atualizar a página.\nEla parece ter sido eliminada.",
        "edit-conflict": "Conflito de edição.",
        "edit-no-change": "A sua edição foi ignorada, uma vez que o texto não sofreu alterações.",
+       "postedit-confirmation-created": "A página foi criada.",
        "postedit-confirmation-restored": "Esta página foi restaurada.",
        "postedit-confirmation-saved": "Sua edição foi salva",
        "edit-already-exists": "Não foi possível criar uma nova página.\nEla já existia.",
        "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)",
        "node-count-exceeded-category": "Páginas em que o total de nós é excedido",
-       "node-count-exceeded-category-desc": "Uma categoria para páginas onde a contagem de nós é ultrapassada.",
+       "node-count-exceeded-category-desc": "A página excede a contagem de nós permitida.",
        "node-count-exceeded-warning": "A página excedeu o total de nós",
        "expansion-depth-exceeded-category": "Páginas em que a profundidade de expansão é excedida",
-       "expansion-depth-exceeded-category-desc": "Esta é uma categoria para as páginas onde a profundidade de expansão é ultrapassada.",
+       "expansion-depth-exceeded-category-desc": "A página excede a profundidade de expansão permitida.",
        "expansion-depth-exceeded-warning": "A página excedeu a profundidade de expansão",
        "parser-unstrip-loop-warning": "Foi detectado um ciclo infinito unstrip",
        "parser-unstrip-recursion-limit": "Limite de recursão do unstrip excedido ($1)",
        "rev-deleted-event": "(entrada removida)",
        "rev-deleted-user-contribs": "[nome de usuário ou endereço de IP eliminado - edição ocultada das contribuições]",
        "rev-deleted-text-permission": "Esta revisão desta página foi '''eliminada'''.\nPodem existir mais detalhes no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de eliminações].",
+       "rev-suppressed-text-permission": "A revisão desta página foi '''eliminada'''.\nVocê pode visualizá-la; podem existir mais detalhes no [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registro de eliminação].",
        "rev-deleted-text-unhide": "Esta revisão desta página foi '''removida'''.\nPoderá haver detalhes no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de eliminação].\nVocê ainda pode [$1 ver esta revisão] se deseja prosseguir.",
        "rev-suppressed-text-unhide": "Esta revisão desta página foi '''removida'''.\nPoderá haver detalhes no [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registro de eliminação].\nVocê ainda pode [$1 ver esta revisão] se deseja prosseguir.",
        "rev-deleted-text-view": "A revisão desta página foi '''eliminada'''.\nVocê pode visualizá-la; pode haver detalhes no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de eliminação].",
        "revdelete-offender": "Autor da revisão:",
        "suppressionlog": "Registro de supressões",
        "suppressionlogtext": "Abaixo está uma lista das eliminações e bloqueios envolvendo conteúdo ocultado por administradores.\nVeja a [[Special:BlockList|lista de bloqueios]] para uma lista de banimentos e bloqueios em efeito neste momento.",
-       "mergehistory": "Fundir histórico de páginas",
+       "mergehistory": "Fundir históricos das páginas",
        "mergehistory-header": "A partir desta página é possível fundir históricos de edições de uma página em outra.\nCertifique-se de que tal alteração manterá a continuidade das ações.",
        "mergehistory-box": "Fundir revisões de duas páginas:",
        "mergehistory-from": "Página de origem:",
        "mergehistory-list": "Histórico de edições habilitadas para fusão",
        "mergehistory-merge": "As edições de [[:$1]] a seguir poderão ser fundidas em [[:$2]]. Utilize a coluna de botões de opção para fundir apenas as edições feitas entre o intervalo de tempo especificado. Note que ao utilizar os links de navegação esta coluna será retornada a seus valores padrão.",
        "mergehistory-go": "Exibir edições habilitadas a serem fundidas",
-       "mergehistory-submit": "Fundir edições",
+       "mergehistory-submit": "Fundir revisões",
        "mergehistory-empty": "Não existem edições habilitadas a serem fundidas.",
        "mergehistory-success": "$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.",
        "searchprofile-advanced-tooltip": "Personalizar os espaços nominais onde pesquisar",
        "search-result-size": "$1 ({{PLURAL:$2|1 palavra|$2 palavras}})",
        "search-result-category-size": "{{PLURAL:$1|1 membro|$1 membros}} ({{PLURAL:$2|1 subcategoria|$2 subcategorias}}, {{PLURAL:$3|1 arquivo|$3 arquivos}})",
-       "search-result-score": "Relevância: $1%",
        "search-redirect": "(redirecionamento de $1)",
        "search-section": "(seção $1)",
        "search-file-match": "(coincide com o conteúdo do arquivo)",
        "searchrelated": "relacionados",
        "searchall": "todos",
        "showingresults": "A seguir {{PLURAL:$1|é mostrado '''um''' resultado|são mostrados até '''$1''' resultados}}, iniciando no '''$2'''º.",
-       "showingresultsheader": "{{PLURAL:$5|Resulado '''$1''' de '''$3'''|Resultados '''$1 - $2''' de '''$3'''}} para '''$4'''",
        "search-nonefound": "Não há resultados que correspondam à consulta.",
        "powersearch-legend": "Pesquisa avançada",
        "powersearch-ns": "Pesquisar nos espaços nominais:",
        "prefs-dateformat": "Formato de data",
        "prefs-timeoffset": "Desvio horário",
        "prefs-advancedediting": "Opções gerais",
+       "prefs-editor": "Editor",
        "prefs-preview": "Pré-visualizar",
        "prefs-advancedrc": "Opções avançadas",
        "prefs-advancedrendering": "Opções avançadas",
        "action-patrol": "marcar as edições de outros usuários como patrulhadas",
        "action-autopatrol": "ter suas edições marcadas como patrulhadas",
        "action-unwatchedpages": "ver a lista de páginas não-vigiadas",
-       "action-mergehistory": "fundir o histórico de edições desta página",
+       "action-mergehistory": "fundir o histórico desta página",
        "action-userrights": "editar todos os privilégios de usuário",
        "action-userrights-interwiki": "editar privilégios de usuários de outros wikis",
        "action-siteadmin": "bloquear ou desbloquear o banco de dados",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (veja também a [[Special:NewPages|lista de páginas novas]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "rcnotefrom": "Abaixo estão mostradas as alterações desde <strong>$2</strong> (até <strong>$1</strong>).",
-       "rclistfrom": "Mostrar as novas alterações a partir das $3 $2",
+       "rclistfrom": "Mostrar as novas alterações a partir das $2 de $3",
        "rcshowhideminor": "$1 edições menores",
        "rcshowhideminor-show": "Exibir",
        "rcshowhideminor-hide": "Ocultar",
        "uploadwarning": "Aviso de envio",
        "uploadwarning-text": "Modifique a descrição do arquivo abaixo e tente novamente.",
        "savefile": "Salvar arquivo",
-       "uploadedimage": "enviou \"[[$1]]\"",
-       "overwroteimage": "enviou uma nova versão de \"[[$1]]\"",
        "uploaddisabled": "Envio de arquivos desativado.",
        "copyuploaddisabled": "O upload por URL encontra-se desativado.",
        "uploaddisabledtext": "O envio de arquivos encontra-se desativado.",
        "license": "Licenciamento:",
        "license-header": "Licenciamento",
        "nolicense": "Nenhuma selecionada",
+       "licenses-edit": "Editar opções de licença",
        "license-nopreview": "(Previsão não disponível)",
        "upload_source_url": " (um URL válido, publicamente acessível)",
        "upload_source_file": " (um arquivo no seu computador)",
+       "listfiles-delete": "apagar",
        "listfiles-summary": "Esta página especial mostra todos os arquivos carregados.",
        "listfiles_search_for": "Pesquisar por nome de mídia:",
        "imgfile": "arquivo",
        "randomincategory": "Página aleatória na categoria",
        "randomincategory-invalidcategory": "\"$1\" não é um nome de categoria válido.",
        "randomincategory-nopages": "Não há paginas em [[:Category:$1]].",
-       "randomincategory-selectcategory": "Obter página aleatória da categoria: $1 $2.",
-       "randomincategory-selectcategory-submit": "Avançar",
+       "randomincategory-category": "Categoria:",
+       "randomincategory-legend": "Página aleatória na categoria",
        "randomredirect": "Redirecionamento aleatório",
        "randomredirect-nopages": "Não há redirecionamentos no espaço nominal \"$1\".",
        "statistics": "Estatísticas",
        "listgrouprights-namespaceprotection-header": "Restrições de namespace",
        "listgrouprights-namespaceprotection-namespace": "Namespace",
        "listgrouprights-namespaceprotection-restrictedto": "Direito(s) permitindo edições do usuário",
-       "trackingcategories": "Monitorando categorias",
+       "trackingcategories": "Categorias de rastreamento",
        "trackingcategories-summary": "Esta página lista categorias de monitoramento que são preenchidas automaticamente pelo software MediaWiki. Seus nomes podem ser alterados através da alteração das mensagens de sistema relevantes no namespace {{ns: 8}}.",
        "trackingcategories-msg": "Categoria de monitoramento",
+       "trackingcategories-name": "Nome da mensagem",
        "trackingcategories-desc": "Critérios de inclusão de categoria",
        "noindex-category-desc": "A página não é indexada por robôs, porque possui a palavra mágica <code><nowiki>__NOINDEX__</nowiki></code> e está em um namespace onde a flag é permitida.",
-       "post-expand-template-inclusion-category-desc": "Após expandir todos as predefinições, o tamanho da página é maior que o valor permitido na variável <code>$wgMaxArticleSize</code>, por isso algumas predefinições não foram expandidas.",
+       "post-expand-template-inclusion-category-desc": "O tamanho da página é superior a <code>$wgMaxArticleSize</code>, após a expansão de todas as predefinições, pelo que algumas predefinições não foram expandidas.",
+       "trackingcategories-nodesc": "Nenhuma descrição disponível.",
        "trackingcategories-disabled": "A categoria está desabilitada",
        "mailnologin": "Nenhum endereço de envio",
        "mailnologintext": "Necessita de estar [[Special:UserLogin|autenticado]] e de possuir um endereço de e-mail válido nas suas [[Special:Preferences|preferências]] para poder enviar um e-mail a outros usuários.",
        "mywatchlist": "Páginas vigiadas",
        "watchlistfor2": "Para $1 $2",
        "nowatchlist": "A sua lista de páginas vigiadas não possui títulos.",
-       "watchlistanontext": "Por favor $1 para ver ou editar os itens na sua lista de páginas vigiadas.",
+       "watchlistanontext": "Por favor, faça login para ver ou editar os itens na sua lista de páginas vigiadas.",
        "watchnologin": "Não está autenticado",
        "addwatch": "Adicionar às páginas vigiadas",
        "addedwatchtext": "A página \"[[:$1]]\" foi adicionada à sua [[Special:Watchlist|lista de páginas vigiadas]].\nFuturas modificações em tal página e páginas de discussão relacionadas serão listadas lá.",
        "watchlist-details": "{{PLURAL:$1|$1 página|$1 páginas}} na sua lista de páginas vigiadas, excluindo as páginas de discussão.",
        "wlheader-enotif": "A notificação por email encontra-se ativada.",
        "wlheader-showupdated": "Páginas modificadas desde a sua última visita são mostradas em '''negrito'''",
-       "wlnote2": "A seguir estão as mudanças nas últimas {{PLURAL:$1|hora|<strong>$1</strong> horas}}, a partir de $2, $3.",
+       "wlnote": "A seguir {{PLURAL:$1|está a última alteração ocorrida|estão as últimas '''$1''' alterações ocorridas}} {{PLURAL:$2|na última hora|nas últimas '''$2''' horas}} a partir de $3, $4.",
        "wlshowlast": "Ver últimas $1 horas $2 dias $3",
        "watchlist-options": "Opções da lista de páginas vigiadas",
        "watching": "Vigiando...",
        "autoblockid": "Autobloqueio #$1",
        "block": "Bloquear usuário",
        "unblock": "Desbloquear usuário",
-       "blockip": "Bloquear usuário",
+       "blockip": "Bloquear {{GENDER:$1|utilizador|utilizadora}}",
        "blockip-legend": "Bloquear usuário",
        "blockiptext": "Utilize o formulário abaixo para bloquear o acesso à escrita de um endereço específico de IP ou nome de usuário.\nIsto só deve ser feito para prevenir vandalismo, e de acordo com a [[{{MediaWiki:Policy-url}}|política]]. Preencha com um motivo específico a seguir (por exemplo, citando páginas que sofreram vandalismo).",
        "ipaddressorusername": "Endereço de IP ou nome de usuário:",
        "import": "Importar páginas",
        "importinterwiki": "Importação transwiki",
        "import-interwiki-text": "Selecione um wiki e um título de página para importar.\nAs datas das edições e os seus editores serão mantidos.\nTodas as ações de importação transwiki são registradas no [[Special:Log/import|Registro de importações]].",
-       "import-interwiki-source": "Wiki/página fonte:",
+       "import-interwiki-sourcewiki": "Fonte wiki:",
+       "import-interwiki-sourcepage": "Página de origem:",
        "import-interwiki-history": "Copiar todas as edições para esta página",
        "import-interwiki-templates": "Incluir todas as predefinições",
        "import-interwiki-submit": "Importar",
        "autosumm-replace": "Página substituída por '$1'",
        "autoredircomment": "Redirecionando para [[$1]]",
        "autosumm-new": "Criou página com '$1'",
+       "autosumm-newblank": "Criar página em branco",
        "lag-warn-normal": "É possível que as alterações que sejam mais recentes do que $1 {{PLURAL:$1|segundo|segundos}} não sejam exibidas nesta lista.",
        "lag-warn-high": "Devido a sérios problemas de latência no servidor do banco de dados, as alterações mais recentes que $1 {{PLURAL:$1|segundo|segundos}} poderão não ser exibidas nesta lista.",
        "watchlistedit-normal-title": "Editar lista de páginas vigiadas",
        "watchlistedit-raw-done": "Sua lista de páginas vigiadas foi atualizada.",
        "watchlistedit-raw-added": "{{PLURAL:$1|Foi adicionado um título|Foram adicionados $1 títulos}}:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|Foi removido um título|Foram removidos $1 títulos}}:",
+       "watchlistedit-clear-title": "Lista de páginas vigiadas limpa",
        "watchlistedit-clear-legend": "Limpar a lista de páginas vigiadas",
        "watchlistedit-clear-explain": "Todos os títulos serão removidos da sua lista de páginas vigiadas",
        "watchlistedit-clear-titles": "Títulos:",
        "version-license": "Licença do MediaWiki",
        "version-ext-license": "Licença",
        "version-ext-colheader-name": "Extensão",
+       "version-skin-colheader-name": "Skin",
        "version-ext-colheader-version": "Versão",
        "version-ext-colheader-license": "Licença",
        "version-ext-colheader-description": "Descrição",
        "htmlform-no": "Não",
        "htmlform-yes": "Sim",
        "htmlform-chosen-placeholder": "Selecione uma opção",
+       "htmlform-cloner-create": "Adicionar mais",
+       "htmlform-cloner-delete": "Remover",
        "htmlform-cloner-required": "Pelo menos um valor é requerido",
        "sqlite-has-fts": "$1 com suporte de pesquisa de texto completo",
        "sqlite-no-fts": "$1 sem suporte de pesquisa de texto completo",
        "expand_templates_generate_xml": "Mostrar árvore de análise (parse) do XML",
        "expand_templates_generate_rawhtml": "Mostrar HTML puro",
        "expand_templates_preview": "Pré-visualização",
+       "pagelang-name": "Página",
+       "pagelang-language": "Idioma",
+       "pagelang-use-default": "Idioma padrão de uso",
        "pagelang-select-lang": "Selecionar idioma",
        "right-pagelang": "Mudar idioma da página",
        "action-pagelang": "mudar idioma da página",
index ac5d18e..156e139 100644 (file)
@@ -60,7 +60,9 @@
                        "Yves Marques Junqueira",
                        "לערי ריינהארט",
                        "555",
-                       "아라"
+                       "아라",
+                       "Leon saudanha",
+                       "Macofe"
                ]
        },
        "tog-underline": "Sublinhar ligações:",
@@ -77,6 +79,7 @@
        "tog-watchdefault": "Adicionar as páginas e ficheiros que eu editar às minhas páginas vigiadas",
        "tog-watchmoves": "Adicionar as páginas e ficheiros que eu mover às minhas páginas vigiadas",
        "tog-watchdeletion": "Adicionar as páginas e ficheiros que eu eliminar às minhas páginas vigiadas",
+       "tog-watchrollback": "Adicionar páginas onde fiz uma reversão às minhas páginas vigiadas",
        "tog-minordefault": "Por omissão, marcar todas as edições como menores",
        "tog-previewontop": "Mostrar a antevisão antes da caixa de edição",
        "tog-previewonfirst": "Mostrar a antevisão na primeira edição",
        "unprotectthispage": "Alterar a proteção desta página",
        "newpage": "Página nova",
        "talkpage": "Discutir esta página",
-       "talkpagelinktext": "discussão",
+       "talkpagelinktext": "Discussão",
        "specialpage": "Página especial",
        "personaltools": "Ferramentas pessoais",
-       "postcomment": "Seção nova",
        "articlepage": "Ver página de conteúdo",
        "talk": "Discussão",
        "views": "Vistas",
        "otherlanguages": "Noutros idiomas",
        "redirectedfrom": "(Redireccionado de $1)",
        "redirectpagesub": "Página de redirecionamento",
+       "redirectto": "Redireciona para:",
        "lastmodifiedat": "Esta página foi modificada pela última vez à(s) $2 de $1.",
        "viewcount": "Esta página foi acedida {{PLURAL:$1|uma vez|$1 vezes}}.",
        "protectedpage": "Página protegida",
        "hidetoc": "esconder",
        "collapsible-collapse": "Ocultar",
        "collapsible-expand": "Expandir",
+       "confirmable-confirm": "{{GENDER:$1|Tem}} a certeza?",
+       "confirmable-yes": "Sim",
+       "confirmable-no": "Não",
        "thisisdeleted": "Ver ou restaurar $1?",
        "viewdeleted": "Ver $1?",
        "restorelink": "{{PLURAL:$1|uma edição eliminada|$1 edições eliminadas}}",
        "sort-descending": "Ordenar por ordem descendente",
        "sort-ascending": "Ordenar por ordem ascendente",
        "nstab-main": "Página",
-       "nstab-user": "Página d{{GENDER:{{#titleparts:{{PAGENAME}}|1|1}}|o utilizador|a utilizadora|e utilizador(a)}}",
+       "nstab-user": "Página d{{GENDER:{{BASEPAGENAME}}|o utilizador|a utilizadora|e utilizador(a)}}",
        "nstab-media": "Multimédia",
        "nstab-special": "Página especial",
        "nstab-project": "Página de projeto",
        "invalidtitle-knownnamespace": "Título inválido com o domínio \"$2\" e texto \"$3\"",
        "invalidtitle-unknownnamespace": "Título inválido com número de domínio $1 desconhecido e texto \"$2\"",
        "exception-nologin": "Não está autenticado",
-       "exception-nologin-text": "Por favor, [[Special:Userlogin|inicie sessão]] para poder aceder a esta página ou acção.",
+       "exception-nologin-text": "Por favor, inicie sessão para poder aceder a esta página ou ação.",
        "exception-nologin-text-manual": "Por favor $1, para poder aceder a esta página ou acção.",
        "virus-badscanner": "Má configuração: antivírus desconhecido: ''$1''",
        "virus-scanfailed": "a verificação falhou (código $1)",
        "externaldberror": "Ocorreu um erro externo à base de dados durante a autenticação ou não lhe é permitido atualizar a sua conta externa.",
        "login": "Entrar",
        "nav-login-createaccount": "Entrar / criar conta",
-       "loginprompt": "É necessário ter os ''cookies'' ativados no seu navegador para poder autenticar-se em {{SITENAME}}.",
        "userlogin": "Criar uma conta ou entrar",
        "userloginnocreate": "Entrar",
        "logout": "Sair",
        "userlogin-resetlink": "Esqueceu-se do seu nome de utilizador ou da palavra-passe?",
        "userlogin-resetpassword-link": "Esqueceu-se da sua palavra-passe?",
        "userlogin-helplink2": "Ajuda para iniciar sessão",
-       "userlogin-loggedin": "Já está {{GENDER:$1|autenticado|autenticada|autenticado}} com o nome $1.\nUse o formulário abaixo para iniciar sessão com outro nome.",
-       "userlogin-createanother": "Criar outra conta",
        "createacct-emailrequired": "Endereço de correio eletrónico",
        "createacct-emailoptional": "Endereço de correio eletrónico (opcional)",
        "createacct-email-ph": "Digite o seu endereço de correio eletrónico",
        "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-migrated-generic": "A sua conta foi migrada e o seu nome de utilizador já não existe nesta wiki.",
        "loginlanguagelabel": "Língua: $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.",
        "createacct-another-realname-tip": "O fornecimento do nome verdadeiro é opcional.\nSe optar por revelá-lo, ele será utilizado para atribuir-lhe crédito pelo seu trabalho.",
        "preview": "Antevisão",
        "showpreview": "Antever resultado",
        "showdiff": "Mostrar alterações",
-       "anoneditwarning": "'''Aviso''': Não iniciou sessão.\nO seu endereço IP será registado no histórico de edições desta página.",
+       "blankarticle": "<strong>Aviso:</strong> A página que está prestes a criar está em branco.  \nSe clicar \"{{int:savearticle}}\" outra vez, a página será criada sem qualquer conteúdo.",
+       "anoneditwarning": "<strong>Aviso</strong>: Não iniciou sessão. O seu endereço IP será registado no histórico de edições desta página. Se <strong>[$1 iniciar sessão]</strong> ou <strong>[$2 criar uma conta]</strong>, as suas edições serão registadas com o seu nome de utilizador(a), bem como usufruir de outros benefícios.",
        "anonpreviewwarning": "''Não iniciou sessão. Ao gravar, registará o seu endereço IP no histórico de edições da página.''",
        "missingsummary": "'''Atenção:''' Não introduziu um resumo da edição.\nSe clicar novamente \"Gravar página\" a sua edição será gravada sem resumo.",
        "missingcommenttext": "Introduza um comentário abaixo, por favor.",
        "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)",
        "node-count-exceeded-category": "Páginas em que o total de nós é excedido",
-       "node-count-exceeded-category-desc": "Uma categoria para páginas onde a contagem dos nós foi excedida.",
+       "node-count-exceeded-category-desc": "A página excede a contagem de nós permitida.",
        "node-count-exceeded-warning": "A página excedeu o total de nós",
        "expansion-depth-exceeded-category": "Páginas em que a profundidade de expansão é excedida",
-       "expansion-depth-exceeded-category-desc": "Uma categoria para páginas onde a profundidade de expansão foi excedida.",
+       "expansion-depth-exceeded-category-desc": "A página excede a profundidade de expansão permitida.",
        "expansion-depth-exceeded-warning": "A página excedeu a profundidade de expansão",
        "parser-unstrip-loop-warning": "Foi detectado um ciclo infinito unstrip",
        "parser-unstrip-recursion-limit": "Limite de recursão do unstrip excedido ($1)",
        "rev-deleted-event": "(entrada removida)",
        "rev-deleted-user-contribs": "[nome de utilizador ou IP removido - edição ocultada das contribuições]",
        "rev-deleted-text-permission": "Esta revisão de página foi <strong>eliminada</strong>.\nEncontrará detalhes no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registo de eliminações].",
+       "rev-suppressed-text-permission": "Esta revisão de página foi <strong>suprimida</strong>.\nPode consultar os detalhes no [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registo de supressões].",
        "rev-deleted-text-unhide": "Esta revisão de página foi <strong>eliminada</strong>.\nEncontrará detalhes no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registo de eliminações].\nPode mesmo assim [$1 ver esta revisão] se deseja prosseguir.",
        "rev-suppressed-text-unhide": "Esta revisão de página foi <strong>suprimida</strong>.\nEncontrará detalhes no [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registo de supressões].\nPode mesmo assim [$1 ver esta revisão] se deseja prosseguir.",
        "rev-deleted-text-view": "Esta revisão de página foi <strong>eliminada</strong>.\nVocê pode vê-la; encontrará detalhes no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registo de eliminações].",
        "revdelete-text-text": "Revisões eliminadas ainda aparecerão no histórico da página, mas parte do seu conteúdo estará inacessível para o público.",
        "revdelete-text-file": "Versões eliminadas do ficheiro ainda aparecerão no histórico da página, mas parte do seu conteúdo estará inacessível para o público.",
        "logdelete-text": "Os eventos eliminados ainda aparecerão no histórico da página, mas pare de seu conteúdo será inacessível ao público.",
-       "revdelete-text-others": "Outros administradores em {{SITENAME}} podem aceder ao conteúdo oculto e torná-lo visível novamente através desta mesma interface, a menos que sejam definidas restrições adicionais.",
+       "revdelete-text-others": "Outros administradores serão ainda capazes de aceder ao conteúdo oculto e torná-lo visível novamente, a menos que sejam definidas restrições adicionais.",
        "revdelete-confirm": "Por favor, confirme que pretende executar esta operação, que compreende as suas consequências e que o faz em concordância com as [[{{MediaWiki:Policy-url}}|políticas e recomendações]].",
        "revdelete-suppress-text": "A supressão '''só''' deverá ser usada nos seguintes casos:\n* Informação potencialmente caluniosa, difamatória ou injuriosa\n* Informação pessoal imprópria\n*: ''endereços de domicílio e números de telefone, números de identificação nacional, etc''",
        "revdelete-legend": "Definir restrições de visibilidade",
        "mergehistory-empty": "Não existem revisões fundíveis.",
        "mergehistory-success": "Foram fundidas $3 {{PLURAL:$3|edição|edições}} de [[:$1]] em [[:$2]].",
        "mergehistory-fail": "Não foi possível fundir os históricos; verifique a página e os parâmetros de tempo, por favor.",
-       "mergehistory-fail-toobig": "Não é possível mesclar 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-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.",
        "mergehistory-invalid-source": "A página de origem precisa ser um título válido.",
        "searchprofile-advanced-tooltip": "Personalizar os domínios onde pesquisar",
        "search-result-size": "$1 ({{PLURAL:$2|1 palavra|$2 palavras}})",
        "search-result-category-size": "{{PLURAL:$1|1 membro|$1 membros}} ({{PLURAL:$2|1 subcategoria|$2 subcategorias}}, {{PLURAL:$3|1 ficheiro|$3 ficheiros}})",
-       "search-result-score": "Relevancia: $1%",
        "search-redirect": "(redirecionamento de $1)",
        "search-section": "(seção $1)",
        "search-file-match": "(coincide com o conteúdo do ficheiro)",
        "searchall": "todos",
        "showingresults": "{{PLURAL:$1|É apresentado '''um''' resultado|São apresentados até '''$1''' resultados}} abaixo{{PLURAL:$1||, começando pelo '''$2'''º}}.",
        "showingresultsinrange": "Apresenta-se abaixo {{PLURAL:$1|<strong>1</strong> resultado|até <strong>$1</strong> resultados}} no intervalo #<strong>$2</strong> a #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Resultado '''$1''' de '''$3'''|Resultados '''$1–$2''' de '''$3'''}} para '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Resultado <strong>$1</strong> de <strong>$3</strong>|Resultados <strong>$1 - $2</strong> de <strong>$3</strong>}}",
        "search-nonefound": "A pesquisa não produziu resultados.",
        "powersearch-legend": "Pesquisa avançada",
        "powersearch-ns": "Pesquisar nos domínios:",
        "preferences": "Preferências",
        "mypreferences": "Preferências",
        "prefs-edits": "Número de edições:",
-       "prefsnologintext2": "Por favor, precisa de $1 para definir as suas preferências.",
+       "prefsnologintext2": "Por favor, inicie sessão para alterar as suas preferências.",
        "prefs-skin": "Tema",
        "skin-preview": "Antever tema",
        "datedefault": "Sem preferência",
        "right-deletedtext": "Ver texto eliminado e mudanças entre revisões eliminadas",
        "right-browsearchive": "Pesquisar páginas eliminadas",
        "right-undelete": "Restaurar uma página",
-       "right-suppressrevision": "Rever e restaurar revisões ocultas dos administradores",
+       "right-suppressrevision": "Ver, ocultar e restaurar revisões de páginas específicas para qualquer utilizador",
+       "right-viewsuppressed": "Ver revisões ocultas para qualquer utilizador",
        "right-suppressionlog": "Ver registos privados",
        "right-block": "Impedir outros utilizadores de editarem",
        "right-blockemail": "Impedir um utilizador de enviar correio eletrónico",
        "recentchanges-legend-heading": "'''Legenda:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|lista de páginas novas]])",
        "recentchanges-legend-plusminus": "(<em>±123</em>)",
-       "rcnotefrom": "Abaixo estão as mudanças desde <strong>$2</strong> (mostradas até <strong>$1</strong>).",
-       "rclistfrom": "Mostrar as novas mudanças a partir das $3 $2",
+       "rcnotefrom": "Abaixo {{PLURAL:$5|está a mudança|estão as mudanças}} desde <strong>$2</strong> (mostradas até <strong>$1</strong>).",
+       "rclistfrom": "Mostrar as novas mudanças a partir das $2 de $3",
        "rcshowhideminor": "$1 edições menores",
        "rcshowhideminor-show": "Mostrar",
        "rcshowhideminor-hide": "Ocultar",
        "uploadwarning": "Aviso de envio",
        "uploadwarning-text": "Modifique a descrição do ficheiro abaixo e tente novamente, por favor.",
        "savefile": "Gravar ficheiro",
-       "uploadedimage": "carregou \"[[$1]]\"",
-       "overwroteimage": "enviou uma nova versão de \"[[$1]]\"",
        "uploaddisabled": "Carregamentos desativados",
        "copyuploaddisabled": "Carregamento por URL desativado.",
        "uploaddisabledtext": "O carregamento de ficheiros está desativado.",
        "license": "Licença:",
        "license-header": "Licenciamento",
        "nolicense": "Nenhuma selecionada",
+       "licenses-edit": "Editar opções de licença",
        "license-nopreview": "(Antevisão indisponível)",
-       "upload_source_url": " (uma URL válida, publicamente acessível)",
-       "upload_source_file": " (um ficheiro no seu computador)",
+       "upload_source_url": "(um ficheiro de uma URL válida, publicamente acessível)",
+       "upload_source_file": "(um ficheiro no seu computador)",
+       "listfiles-delete": "eliminar",
        "listfiles-summary": "Esta página especial mostra todos os ficheiros carregados.",
        "listfiles_search_for": "Pesquisar por nome de imagem:",
        "imgfile": "ficheiro",
        "randomincategory": "Página aleatória na categoria",
        "randomincategory-invalidcategory": "\"$1\" não é um nome de categoria válido",
        "randomincategory-nopages": "Não há páginas na categoria [[:Category:$1|$1]].",
-       "randomincategory-selectcategory": "Obter página aleatória da categoria: $1 $2",
-       "randomincategory-selectcategory-submit": "Ir",
+       "randomincategory-category": "Categoria:",
+       "randomincategory-legend": "Página aleatória na categoria",
        "randomredirect": "Redirecionamento aleatório",
        "randomredirect-nopages": "Não há redirecionamentos no domínio \"$1\".",
        "statistics": "Estatísticas",
        "wantedpages-badtitle": "Título inválido no conjunto de resultados: $1",
        "wantedfiles": "Ficheiros desejados",
        "wantedfiletext-cat": "Os seguintes ficheiros são usados, mas não existem. Ficheiros de repositórios externos podem ser listados apesar de existirem. Tais falsos positivos aparecerão <del>riscados</del>. Adicionalmente, as páginas que incorporam ficheiros que não existem estão listadas em [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Os seguintes ficheiros são usados, mas não existem. Além disso, as páginas que incorporam ficheiros que não existem são listadas em [[:$1]].",
        "wantedfiletext-nocat": "Os seguintes ficheiros são usados, mas não existem. Ficheiros de repositórios externos podem ser listados apesar de existirem. Tais falsos positivos aparecerão <del>riscados</del>.",
+       "wantedfiletext-nocat-noforeign": "Os seguintes ficheiros são usados, mas não existem.",
        "wantedtemplates": "Predefinições desejadas",
        "mostlinked": "Páginas com mais afluentes",
        "mostlinkedcategories": "Categorias com mais membros",
        "trackingcategories-desc": "Critérios de inclusão",
        "noindex-category-desc": "A página não é indexada por robôs porque contém a palavra mágica <code><nowiki>__NOINDEX__</nowiki></code> e está num domínio onde o estatuto é permitido.",
        "index-category-desc": "A página contém a palavra mágica <code><nowiki>__INDEX__</nowiki></code> (e está num domínio em que essa marca é permitida) e, portanto, será indexada pelos robôs mesmo quando normalmente não o seria.",
-       "post-expand-template-inclusion-category-desc": "A expansão de todas as predefinições faria com que o tamanho da página ultrapassasse <code>$wgMaxArticleSize</code>, pelo que algumas predefinições não foram expandidas.",
-       "post-expand-template-argument-category-desc": "A expansão de um argumento de prefefinição (algo em chavetas triplas, como <code>{{{Foo}}}</code> ) torna a página maior do que <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Demasiadas funções do analisador custosas (como <code>#ifexist</code>) incluídas numa página. Consulte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Categoria adicionada se a página contém um link quebrado para um ficheiro (um link para incorporar um ficheiro que não existe).",
-       "hidden-category-category-desc": "Esta é uma categoria com a marca <code><nowiki>__HIDDENCAT__</nowiki></code>, que faz com que ela não apareça na caixa de links de categoria nas páginas, por omissão.",
+       "post-expand-template-inclusion-category-desc": "O tamanho da página é superior a <code>$wgMaxArticleSize</code>, após a expansão de todas as predefinições, pelo que algumas predefinições não foram expandidas.",
+       "post-expand-template-argument-category-desc": "O tamanho da página é superior a <code>$wgMaxArticleSize</code>, após a expansão de um argumento de predefinição (algo em chavetas triplas, como <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "A página tem demasiadas funções do analisador custosas (como <code>#ifexist</code>) incluídas. Consulte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "A página contém uma ligação quebrada para um ficheiro (uma ligação para incorporar um ficheiro que não existe).",
+       "hidden-category-category-desc": "Esta é uma categoria com a marca <code><nowiki>__HIDDENCAT__</nowiki></code>, que faz com que ela não apareça na caixa de ligações de categoria nas páginas, por omissão.",
        "trackingcategories-nodesc": "Nenhuma descrição disponível.",
        "trackingcategories-disabled": "A categoria está desactivada.",
        "mailnologin": "Não existe endereço de envio",
        "mywatchlist": "Páginas vigiadas",
        "watchlistfor2": "Para $1 $2",
        "nowatchlist": "A sua lista de páginas vigiadas está vazia.",
-       "watchlistanontext": "Precisa de $1 para ver ou editar a sua lista de páginas vigiadas, por favor.",
+       "watchlistanontext": "Por favor, inicie sessão para ver ou editar itens da sua lista de páginas vigiadas.",
        "watchnologin": "Não está autenticado(a)",
        "addwatch": "Adicionar às páginas vigiadas",
        "addedwatchtext": "A página \"[[:$1]]\" foi adicionada à sua [[Special:Watchlist|lista de páginas vigiadas]].\nModificações futuras desta página e da respetiva página de discussão serão listadas lá.",
        "unwatchthispage": "Parar de vigiar esta página",
        "notanarticle": "Não é uma página de conteúdo",
        "notvisiblerev": "Edição eliminada",
-       "watchlist-details": "{{PLURAL:$1|Existe $1 página|Existem $1 páginas}} em sua lista de páginas vigiadas, excluindo-se as páginas de discussão.",
+       "watchlist-details": "{{PLURAL:$1|Existe $1 página|Existem $1 páginas}} na sua lista de páginas vigiadas, excluindo-se as páginas de discussão.",
        "wlheader-enotif": "A notificação por correio eletrónico está ativa.",
        "wlheader-showupdated": "As páginas modificadas desde a última vez que as visitou aparecem destacadas a '''negrito'''.",
-       "wlnote2": "Estão listadas abaixo as mudanças realizadas {{PLURAL:$1|na última hora|nas últimas <strong>$1</strong> horas}}, a partir de $2, $3.",
+       "wlnote": "A seguir {{PLURAL:$1|está a última alteração ocorrida|estão as últimas <strong>$1</strong> alterações ocorridas}} {{PLURAL:$2|na última hora|nas últimas <strong>$2</strong> horas}} até $3, $4.",
        "wlshowlast": "Ver últimas $1 horas $2 dias $3",
        "watchlist-options": "Opções da lista de páginas vigiadas",
        "watching": "A vigiar...",
        "exbeforeblank": "o conteúdo antes de esvaziar era: \"$1\"",
        "delete-confirm": "Eliminar \"$1\"",
        "delete-legend": "Eliminar",
-       "historywarning": "'''Aviso:''' A página que está prestes a eliminar tem um histórico com aproximadamente $1 {{PLURAL:$1|revisão|revisões}}:",
+       "historywarning": "<strong>Aviso:</strong> A página que está prestes a eliminar tem um histórico com aproximadamente $1 {{PLURAL:$1|revisão|revisões}}:",
        "confirmdeletetext": "Está prestes a eliminar permanentemente uma página ou uma imagem e todo o seu histórico.\nConfirme que é realmente esta a sua intenção, que compreende as consequências e que o faz de acordo com as [[{{MediaWiki:Policy-url}}|políticas e recomendações]] do projeto, por favor.",
        "actioncomplete": "Operação executada",
        "actionfailed": "Operação falhou",
        "delete-edit-reasonlist": "Editar motivos de eliminação",
        "delete-toobig": "Esta página tem um histórico longo, com mais de $1 {{PLURAL:$1|edição|edições}}.\nA eliminação de páginas como esta foi restringida na {{SITENAME}}, para evitar problemas acidentais.",
        "delete-warning-toobig": "Esta página tem um histórico de edições longo, com mais de $1 {{PLURAL:$1|edição|edições}}.\nEliminá-la poderá causar problemas na base de dados da {{SITENAME}};\nprossiga com precaução.",
-       "deleting-backlinks-warning": "'''Aviso:''' Há [[Special:WhatLinksHere/{{FULLPAGENAME}}|páginas]] que contêm ligações para a página que está prestes a eliminar ou que a transcluem.",
+       "deleteprotected": "Não é possível eliminar esta página porque foi protegida.",
+       "deleting-backlinks-warning": "'''Aviso:''' Existem [[Special:WhatLinksHere/{{FULLPAGENAME}}|páginas]] que contêm ligações para a página que está prestes a eliminar ou que a transcluem.",
        "rollback": "Reverter edições",
-       "rollback_short": "Desfazer",
-       "rollbacklink": "desfazer",
-       "rollbacklinkcount": "desfazer $1 {{PLURAL:$1|edição|edições}}",
-       "rollbacklinkcount-morethan": "desfazer mais do que $1 {{PLURAL:$1|edição|edições}}",
+       "rollback_short": "Reverter",
+       "rollbacklink": "reverter",
+       "rollbacklinkcount": "reverter $1 {{PLURAL:$1|edição|edições}}",
+       "rollbacklinkcount-morethan": "reverter mais do que $1 {{PLURAL:$1|edição|edições}}",
        "rollbackfailed": "A reversão falhou",
        "cantrollback": "Não foi possível reverter a edição; o último contribuidor é o único autor desta página",
        "alreadyrolled": "Não foi possível reverter as edições de [[:$1]] por [[User:$2|$2]] ([[User talk:$2|discussão]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]);\nalguém editou ou já reverteu a página.\n\nA última edição foi de [[User:$3|$3]] ([[User talk:$3|discussão]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "sp-contributions-newonly": "Mostrar só edições que são criações de páginas",
        "sp-contributions-submit": "Pesquisar",
        "whatlinkshere": "Páginas afluentes",
-       "whatlinkshere-title": "Páginas que têm ligações para \"$1\"",
+       "whatlinkshere-title": "Páginas com ligações para \"$1\"",
        "whatlinkshere-page": "Página:",
        "linkshere": "As seguintes páginas têm ligação a '''[[:$1]]''':",
        "nolinkshere": "Não existem afluentes para '''[[:$1]]''' com as condições especificadas.",
        "autoblockid": "Bloqueio automático nº$1",
        "block": "Bloquear utilizador",
        "unblock": "Desbloquear utilizador",
-       "blockip": "Bloquear utilizador",
+       "blockip": "Bloquear {{GENDER:$1|utilizador|utilizadora}}",
        "blockip-legend": "Bloquear utilizador",
        "blockiptext": "Utilize o formulário abaixo para bloquear o acesso de escrita a um endereço IP específico ou a um nome de utilizador.\nIsto só deve ser feito para prevenir vandalismo e de acordo com a [[{{MediaWiki:Policy-url}}|política]]. Indique a seguir um motivo de bloqueio específico (por exemplo, indicando as páginas que foram alvo de vandalismo).",
        "ipaddressorusername": "Endereço de IP ou utilizador(a):",
        "ipb-unblock-addr": "Desbloquear $1",
        "ipb-unblock": "Desbloquear um utilizador ou endereço IP",
        "ipb-blocklist": "Ver bloqueios em vigência",
-       "ipb-blocklist-contribs": "Contribuições de $1",
+       "ipb-blocklist-contribs": "Contribuições de {{GENDER:$1|$1}}",
        "unblockip": "Desbloquear utilizador",
        "unblockiptext": "Utilize o formulário abaixo para restaurar o acesso de escrita de um endereço IP ou utilizador previamente bloqueado.",
        "ipusubmit": "Remover este bloqueio",
        "import": "Importar páginas",
        "importinterwiki": "Importação transwikis",
        "import-interwiki-text": "Selecione uma wiki e um título de página a importar.\nAs datas das edições e os seus editores serão mantidos.\nTodas as ações de importação transwikis são registadas no [[Special:Log/import|Registo de importações]].",
-       "import-interwiki-source": "Wiki ou página de origem:",
+       "import-interwiki-sourcewiki": "Wiki de origem:",
+       "import-interwiki-sourcepage": "Página de origem:",
        "import-interwiki-history": "Copiar todo o histórico de revisões desta página",
        "import-interwiki-templates": "Incluir todas as predefinições",
        "import-interwiki-submit": "Importar",
        "import-error-create": "A página \"$1\" não foi importada porque não tem permissão para criá-la.",
        "import-error-interwiki": "A página \"$1\" não pode ser importada pois o seu nome está reservado para um ligação externa (interlíngua).",
        "import-error-special": "A página \"$1\" não pode ser importada porque pertence a um domínio especial que não permite páginas.",
-       "import-error-invalid": "A página \"$1\" não pode ser importada porque o seu nome é inválido.",
+       "import-error-invalid": "A página \"$1\" não pode ser importada porque o seu nome é inválido nesta wiki.",
        "import-error-unserialize": "Revisão $2 da página \"$1\" não pode ser desserializada. Foi relatado que a revisão usava o modelo de conteúdo $3 serializado como $4.",
        "import-error-bad-location": "A revisão $2, que usa o modelo de conteúdo $3, não pode ser gravada em \"$1\" nesta wiki, porque o modelo não é suportado nessa página.",
        "import-options-wrong": "{{PLURAL:$2|Opção errada|Opções erradas}}: <nowiki>$1</nowiki>",
        "importlogpage": "Registo de importações",
        "importlogpagetext": "Importações administrativas de páginas com a preservação do histórico de edição de outras wikis.",
        "import-logentry-upload": "importou [[$1]] por carregamento de ficheiro",
-       "import-logentry-upload-detail": "{{PLURAL:$1|uma edição|$1 edições}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|edição importada|edições importadas}}",
        "import-logentry-interwiki": "transwikis $1",
-       "import-logentry-interwiki-detail": "{{PLURAL:$1|$1 edição|$1 edições}} de $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|edição importada|edições importadas}} de $2",
        "javascripttest": "Teste de JavaScript",
        "javascripttest-title": "A executar os testes $1",
        "javascripttest-pagetext-noframework": "Esta página é reservada para a execução de testes de JavaScript.",
        "autosumm-replace": "Página substituída por \"$1\"",
        "autoredircomment": "Redirecionamento para [[$1]]",
        "autosumm-new": "Criou a página com \"$1\"",
+       "autosumm-newblank": "Página em branco criada",
        "lag-warn-normal": "Alterações realizadas {{PLURAL:$1|no último segundo|nos últimos $1 segundos}} podem não constar desta lista.",
        "lag-warn-high": "Devido a latência elevada no acesso ao servidor da base de dados, as alterações realizadas {{PLURAL:$1|no último segundo|nos últimos $1 segundos}} podem não constar desta lista.",
        "watchlistedit-normal-title": "Editar lista de páginas vigiadas",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discussão]])",
        "unknown_extension_tag": "\"$1\" é uma marca de extensão desconhecida",
        "duplicate-defaultsort": "<strong>Aviso:</strong> A chave de ordenação padrão \"$2\" sobrepõe-se à anterior \"$1\".",
+       "duplicate-displaytitle": "<strong>Aviso:</strong> Exibir título \"$2\" substituindo o título anteriormente em exibição \"$1\".",
        "version": "Versão",
        "version-extensions": "Extensões instaladas",
        "version-skins": "Temas instalados",
        "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",
+       "logentry-upload-upload": "$1 {{GENDER:$2|carregou}} $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|carregou}} uma nova versão de $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|carregou}} $3",
        "rightsnone": "(nenhum)",
        "feedback-bugornote": "Se está pronto para descrever um problema técnico em detalhe, por favor, [$1 comunique o defeito].\nCaso contrário, pode facilmente usar o formulário abaixo. O seu comentário será adicionado à página \"[$3 $2]\", junto com o seu nome de utilizador e o navegador que está a usar.",
        "feedback-subject": "Assunto:",
        "action-pagelang": "alterar o idioma da página",
        "log-name-pagelang": "Alterar registo de idioma",
        "log-description-pagelang": "Este é um registo de alterações aos idiomas das páginas.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|alterou}} o idioma da página $3 de $4 para $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|alterou}} o idioma da página $3 de $4 para $5.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (ativado)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''desativado''')"
 }
index 78dd1fd..953ce2b 100644 (file)
        "tog-watchdefault": "[[Special:Preferences]], tab 'Watchlist'. Offers user to add edited pages to watchlist. {{Gender}}",
        "tog-watchmoves": "[[Special:Preferences]], tab 'Watchlist'. Offers user to add moved pages to watchlist. {{Gender}}",
        "tog-watchdeletion": "[[Special:Preferences]], tab 'Watchlist'. Offers user to add deleted pages to watchlist. {{Gender}}",
+       "tog-watchrollback": "[[Special:Preferences]], tab 'Watchlist'. Offers user to add pages where the user has rollbacked an edit to watchlist. {{Gender}}\n\nSee also {{msg-mw|tog-watchdefault}}, {{msg-mw|tog-watchcreations}}.",
        "tog-minordefault": "[[Special:Preferences]], tab 'Edit'. Offers user to mark all edits minor by default.  {{Gender}}",
        "tog-previewontop": "Toggle option used in [[Special:Preferences]]. {{Gender}}",
        "tog-previewonfirst": "Toggle option used in [[Special:Preferences]]. {{Gender}}",
        "october-date": "A date in the Gregorian month of October. $1 is the numerical date, for example \"23\".",
        "november-date": "A date in the Gregorian month of November. $1 is the numerical date, for example \"23\".\n{{Identical|November}}",
        "december-date": "A date in the Gregorian month of December. $1 is the numerical date, for example \"23\".",
-       "pagecategories": "Used in the categories section of pages.\n\nFollowed by a colon and a list of categories.\n\nParameters:\n* $1 - number of categories",
+       "pagecategories": "Used in the categories section of pages.\n\nFollowed by a colon and a list of categories.\n\nParameters:\n* $1 - number of categories\n{{Identical|Category}}",
        "pagecategorieslink": "{{notranslate}}",
        "category_header": "In category description page. Parameters:\n* $1 - category name\nSee also:\n* {{msg-mw|Category-media-header}}",
        "subcategories": "Used as a header on category pages that have subcategories.\n{{Identical|Subcategory}}",
        "talkpagelinktext": "Used as name of links going to talk page in some places, like in [[Special:RecentChanges]], [[Special:Allmessages]], [[Special:Logs]], and [[Special:Watchlist/edit]].\n\n{{Identical|Talk}}",
        "specialpage": "{{Identical|Special page}}",
        "personaltools": "Heading for a group of links to your user page, talk page, preferences, watchlist, and contributions. This heading is visible in the sidebar in some skins. For an example, see [{{canonicalurl:Main_Page|useskin=simple}} Main Page using simple skin].",
-       "postcomment": "Used as link text.\n\nThe link points to the talk page and has the parameters \"action=edit&section=new\".",
        "addsection": "{{notranslate}}\nText of the new section tab (the one next to the \"edit\" tab on non-Vector skins).\n\nSee also:\n* {{msg-mw|Addsection}}\n* {{msg-mw|Accesskey-ca-addsection}}\n* {{msg-mw|Tooltip-ca-addsection}}",
        "articlepage": "'Content page' is used for NS_MAIN and any other non-standard namespaces. Only used in the Cologne Blue skin in the bottomLinks part.\n\n{{Identical|Content page}}",
        "talk": "Used as display name for the tab to all {{msg-mw|Talk}} pages. These pages accompany all content pages and can be used for discussing the content page. Example: [[Talk:Example]].\n\nSee also:\n* {{msg-mw|Talk}}\n* {{msg-mw|Accesskey-ca-talk}}\n* {{msg-mw|Tooltip-ca-talk}}\n{{Identical|Discussion}}",
        "otherlanguages": "This message is shown under the toolbox. It is used if there are interwiki links added to the page, like <code><nowiki>[[</nowiki>en:Interwiki article]]</code>.\n{{Identical|Otherlanguages}}",
        "redirectedfrom": "The text displayed when a certain page is redirected to another page. Parameters:\n* $1 - the name of the page user came from",
        "redirectpagesub": "Displayed under the page title of a page which is a redirect to another page, see [{{fullurl:Project:Translators|redirect=no}} Project:Translators] for example.\n\n{{Identical|Redirect page}}",
+       "redirectto": "Alt text of the arrow icon shown on redirect pages ([[commons:File:Sample redirect page.jpg]]).\n\n{{Identical|Redirect page}}",
        "talkpageheader": "{{notranslate}}",
        "lastmodifiedat": "This message is shown below each page, in the footer with the logos and links.\n\nParameters:\n* $1 - date\n* $2 - time\nSee also:\n* {{msg-mw|Lastmodifiedatby}}",
        "viewcount": "Used as page-view counter. Parameters:\n* $1 - number of pageviews",
        "hidetoc": "This is the link used to hide the table of contents\n\n{{Identical|Hide}}",
        "collapsible-collapse": "{{Doc-actionlink}}\nThis is the link used to collapse a collapsible element. (used as plaintext. No wikitext or html is parsed.)\n\nSee also:\n* {{msg-mw|Collapsible-expand}}\n{{Identical|Collapse}}",
        "collapsible-expand": "{{Doc-actionlink}}\nThis is the link used to expand a collapsible element (used as plaintext. No wikitext or html is parsed.)\n\nSee also:\n* {{msg-mw|Collapsible-collapse}}\n\nSee the following example:\n{{Identical|Expand}}",
+       "confirmable-confirm": "Question asking the user to confirm a potentially uncancellable action.\n\"Yes\" and \"No\" buttons are displayed beside it.\n\nSee also:\n* {{msg-mw|confirmable-yes}}\n* {{msg-mw|confirmable-no}}\n{{Identical|Are you sure?}}",
+       "confirmable-yes": "{{Doc-actionlink}}\nText of a button that will confirm triggering of a potentially uncancellable action.\n\nSee also:\n* {{msg-mw|confirmable-confirm}}\n* {{msg-mw|confirmable-no}}\n{{Identical|Yes}}",
+       "confirmable-no": "{{Doc-actionlink}}\nText of a button that will cancel triggering of a potentially uncancellable action.\n\nSee also:\n* {{msg-mw|confirmable-confirm}}\n* {{msg-mw|confirmable-yes}}\n{{Identical|No}}",
        "thisisdeleted": "Message shown on a deleted page when the user has the undelete right. Parameters:\n* $1 - a link to [[Special:Undelete]], with {{msg-mw|restorelink}} as the text\nSee also:\n* {{msg-mw|viewdeleted}}",
        "viewdeleted": "Message shown on a deleted page when the user does not have the undelete right (but has the deletedhistory right).\n\nParameters:\n* $1 - a link to [[Special:Undelete]], with {{msg-mw|restorelink}} as the text\nSee also:\n* {{msg-mw|thisisdeleted}}",
        "restorelink": "This text is always displayed in conjunction with the {{msg-mw|thisisdeleted}} message (View or restore $1?). The user will see\nView or restore <nowiki>{{PLURAL:$1|one deleted edit|$1 deleted edits}}</nowiki>?    i.e ''View or restore one deleted edit?''     or\n''View or restore n deleted edits?''",
        "viewsource-title": "Page title shown when trying to edit a protected page. Parameters:\n* $1 - the name of the page",
        "actionthrottled": "This is the title of an error page. Read it in combination with {{msg-mw|actionthrottledtext}}.",
        "actionthrottledtext": "Used as error message. Read it in combination with {{msg-mw|actionthrottled}}.",
-       "protectedpagetext": "This message is displayed when trying to edit a page you can't edit because it has been protected.\n\nThe title for this message is {{msg-mw|Protectedpage}}.\n\nParameters:\n* $1 - (Unused) the raw name of the right which is needed to edit the page",
+       "protectedpagetext": "This message is displayed when trying to edit a page you can't edit because it has been protected.\n\nThe title for this message is {{msg-mw|Protectedpage}}.\n\nParameters:\n* $1 - (Unused) the raw name of the right which is needed to edit the page\n* $2 - (Unused) the action the user attempted to perform",
        "viewsourcetext": "The text shown when displaying the source of a page that the user has no permission to edit",
        "viewyourtext": "Same as {{msg-mw|viewsourcetext}} but when showing the text submitted by the user, this happens e.g. when the user was blocked while he is editing the page",
-       "protectedinterface": "Message shown if a user without the \"editinterface\" right tries to edit a page in the MediaWiki namespace.\n\nSee also {{msg-mw|editinginterface}}.",
+       "protectedinterface": "Message shown if a user without the \"editinterface\" right tries to edit a page in the MediaWiki namespace.\n\nSee also {{msg-mw|editinginterface}}. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
        "editinginterface": "A message shown when editing pages in the namespace MediaWiki:.\n\nSee also {{msg-mw|protectedinterface}}.",
-       "cascadeprotected": "Parameters:\n* $1 - number of cascade-protected pages, used for PLURAL\n* $2 - list of cascade-protected pages",
-       "namespaceprotected": "Parameters:\n* $1 - namespace name",
-       "customcssprotected": "Used as error message.",
-       "customjsprotected": "Used as error message.",
-       "mycustomcssprotected": "Used as error message.",
-       "mycustomjsprotected": "Used as error message.",
+       "cascadeprotected": "Parameters:\n* $1 - number of cascade-protected pages, used for PLURAL\n* $2 - list of cascade-protected pages\n* $3 - (Unused) the action the user attempted to perform",
+       "namespaceprotected": "Parameters:\n* $1 - namespace name\n* $2 - (Unused) the action the user attempted to perform",
+       "customcssprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
+       "customjsprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
+       "mycustomcssprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
+       "mycustomjsprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
        "myprivateinfoprotected": "Used as error message.",
        "mypreferencesprotected": "Used as error message.",
        "ns-specialprotected": "Error message displayed when trying to edit a page in the Special namespace",
        "externaldberror": "This message is thrown when a valid attempt to change the wiki password for a user fails because of a database error or an error from an external system.",
        "login": "{{Doc-special|UserLogin|unlisted=1}}\n{{Identical|Log in}}",
        "nav-login-createaccount": "Shown to anonymous users in the upper right corner of the page. When you can't create an account, the message {{msg-mw|login}} is shown.\n{{Identical|Log in / create account}}",
-       "loginprompt": "A small notice in the log in form.",
+       "loginprompt": "{{ignored}}",
        "userlogin": "Since 1.22 no longer used in core, but may still be used by extensions. DEPRECATED\n\n{{Identical|Log in / create account}}",
        "userloginnocreate": "Since 1.22 no longer used in core, but may still be used by some extensions. A variant of {{msg-mw|Userlogin}} when the user is not allowed to create a new account. DEPRECATED\n\n{{Identical|Log in}}",
        "logout": "Used as link text in your personal toolbox (upper right side).\n\nSee also:\n* {{msg-mw|Logout}}\n* {{msg-mw|Accesskey-pt-logout}}\n* {{msg-mw|Tooltip-pt-logout}}\n{{Identical|Log out}}",
        "userlogin-resetpassword-link": "Used as link text in the login form.\n\nThe link points to the local page [[Special:PasswordReset]].\n\nSee example: [[Special:UserLogin]]\n\nuserlogin-resetpassword-link may have to be shorter than the old {{msg-mw|userlogin-resetlink}}.\n{{Identical|Forgot your password}}",
        "helplogin-url": "{{doc-important|Do not translate the namespace name <code>Help</code>.}}\nUsed as name of the page that provides information about logging into the wiki.\n\nUsed as a link target in the message {{msg-mw|Userlogin-helplink}}.",
        "userlogin-helplink2": "Label for a link to login help.\n\nSee example: [[Special:UserLogin]]\n\nSee also:\n* {{msg-mw|Helplogin-url}}",
-       "userlogin-loggedin": "Used as warning on [[Special:UserLogin]] when the current user is already logged in.\n\nFollowed by the Login form.\n\nSee example: [[Special:UserLogin]].\n\nParameters:\n* $1 - user name (used for display and for gender support)",
-       "userlogin-createanother": "Used as label for the button on [[Special:UserLogin]] shown when the current user is already logged in.\n{{Identical|Create another account}}",
        "createacct-emailrequired": "Label in create account form for email field when it is required.\n\nSee also:\n* {{msg-mw|Createacct-emailoptional}}\n{{Identical|E-mail address}}",
        "createacct-emailoptional": "Label in vertical-layout create account form for email field when it is optional.\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]\n\nSee also:\n* {{msg-mw|Createacct-emailrequired}}",
        "createacct-email-ph": "Placeholder in vertical-layout create account form for email field.\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]",
        "createaccount-text": "Body of the email sent to the email address entered at [[Special:CreateAccount]] when one user creates an account for another and clicks the checkbox labelled:\n* {{msg-mw|Createaccountmail}}\n\nParameters:\n* $1 - (Unused) IP address\n* $2 - the name entered as username\n* $3 - a password (randomly generated)\n* $4 - a URL to the wiki ('<' + server name + script name + '>')\n* $5 - (Unused) number of days to password expiry date",
        "login-throttled": "Error message shown at [[Special:UserLogin]] after the user has tried to login with incorrect password too many times.\n\nThe user has to wait a certain time before trying to log in again.\n\nParameters:\n* $1 - the time to wait before the next login attempt. Automatically formatted using the following duration messages:\n** {{msg-mw|Duration-millennia}}\n** {{msg-mw|Duration-centuries}}\n** {{msg-mw|Duration-decades}}\n** {{msg-mw|Duration-years}}\n** {{msg-mw|Duration-weeks}}\n** {{msg-mw|Duration-days}}\n** {{msg-mw|Duration-hours}}\n** {{msg-mw|Duration-minutes}}\n** {{msg-mw|Duration-seconds}}\n\nThis is a protection against robots trying to find the password by trying lots of them.\nThe number of attempts and waiting time are configured via [[mw:Manual:$wgPasswordAttemptThrottle|$wgPasswordAttemptThrottle]].\nThis message is used in html.\n{{identical|Login throttled}}",
        "login-abort-generic": "The generic unsuccessful login message is used unless otherwise specified by hook writers",
+       "login-migrated-generic": "The generic unsuccessful login message when the user's account has been updated, and their username no longer exist",
        "loginlanguagelabel": "Used on [[Special:UserLogin]] if $wgLoginLanguageSelector is true. Parameters:\n* $1 - a pipe-separated list built from the names that appear in the message {{msg-mw|Loginlanguagelinks}}.\n{{Identical|Language}}",
        "loginlanguagelinks": "{{notranslate}}",
        "suspicious-userlogout": "Used when the logout request looks suspicious, in Special:UserLogout.",
        "preview": "The title of the Preview page shown after clicking the \"Show preview\" button in the edit page. Since this is a heading, it should probably be translated as a noun and not as a verb.\n\n{{Identical|Preview}}",
        "showpreview": "The text of the button to preview the page you are editing. See also {{msg-mw|showdiff}} and {{msg-mw|savearticle}} for the other buttons.\n\nSee also:\n* {{msg-mw|Showpreview}}\n* {{msg-mw|Accesskey-preview}}\n* {{msg-mw|Tooltip-preview}}\n{{Identical|Show preview}}",
        "showdiff": "Button below the edit page. See also {{msg-mw|Showpreview}} and {{msg-mw|Savearticle}} for the other buttons.\n\nSee also:\n* {{msg-mw|Showdiff}}\n* {{msg-mw|Accesskey-diff}}\n* {{msg-mw|Tooltip-diff}}\n{{Identical|Show change}}",
-       "anoneditwarning": "Shown when editing a page anonymously.\nSee also:\n* {{msg-mw|Sf autoedit anoneditwarning}}\n* {{msg-mw|Wikibase-anonymouseditwarning-property}}\n* {{msg-mw|Wikibase-anonymouseditwarning-item}}\n* {{msg-mw|Anonpreviewwarning}}",
+       "blankarticle": "Notice displayed once after the user tries to save an empty page.",
+       "anoneditwarning": "Shown when editing a page anonymously.\n\nParameters:\n* $1 – A link to log in, <nowiki>{{fullurl:Special:UserLogin|returnto={{FULLPAGENAMEE}}}}</nowiki>\n* $2 – A link to sign up, <nowiki>{{fullurl:Special:UserLogin/signup|returnto={{FULLPAGENAMEE}}}}</nowiki>\n\nSee also:\n* {{msg-mw|mobile-frontend-editor-anoneditwarning}}",
        "anonpreviewwarning": "See also:\n* {{msg-mw|Anoneditwarning}}",
        "missingsummary": "The text \"edit summary\" is in {{msg-mw|Summary}}.\n\nSee also:\n* {{msg-mw|Missingcommentheader}}\n* {{msg-mw|Savearticle}}",
        "missingcommenttext": "This message is shown, when the textbox by a new-section is empty.",
        "session_fail_preview_html": "Used as error message in Preview page.",
        "token_suffix_mismatch": "Error message in Preview page.\n\nSee also:\n* {{msg-mw|Token suffix mismatch}}\n* {{msg-mw|Session fail preview}}\n* {{msg-mw|Edit form incomplete}}",
        "edit_form_incomplete": "Error message in Preview page.\n\nSee also:\n* {{msg-mw|Token suffix mismatch}}\n* {{msg-mw|Session fail preview}}\n* {{msg-mw|Edit form incomplete}}",
-       "editing": "Shown as page title when editing a page. Parameters:\n* $1 - the name of the page that is being edited. e.g. \"Editing Main Page\"\n{{Related|Editing}}",
-       "creating": "Shown as page title when creating a page. Parameters:\n* $1 - the name of the page that is being created. Example: \"Creating Main Page\".\n{{Related|Editing}}",
+       "editing": "Shown as page title when editing a page. Parameters:\n* $1 - the name of the page that is being edited. e.g. \"Editing Main Page\"\n{{Related|Editing}}\n{{Identical|Editing}}",
+       "creating": "Shown as page title when creating a page. Parameters:\n* $1 - the name of the page that is being created. Example: \"Creating Main Page\".\n{{Related|Editing}}\n{{Identical|Creating}}",
        "editingsection": "This message displays at the top of the page when a user is editing a page section. Parameters:\n* $1 - page name\n{{Related|Editing}}",
        "editingcomment": "This message displays at the top of the page when a user is creating a new section. Parameters:\n* $1 - page name\n{{Related|Editing}}",
        "editconflict": "Used as title of error message. Parameters:\n* $1 - page title",
        "rev-deleted-user": "See also:\n* {{msg-mw|Rev-deleted-event}}",
        "rev-deleted-event": "See also:\n* {{msg-mw|Rev-deleted-user}}",
        "rev-deleted-user-contribs": "Part of revision deletion.",
-       "rev-deleted-text-permission": "{{Related|Rev-deleted-text}}",
+       "rev-deleted-text-permission": "This message appears in case a user lacking permission tries to view a past deleted revision of a page, although later revisions of the page still exist.\n{{Related|Rev-deleted-text}}",
+       "rev-suppressed-text-permission": "This message appears in case a user lacking permission tries to view a past suppressed revision of a page, although later revisions of the page still exist.\n{{Related|Rev-deleted-text}}",
        "rev-deleted-text-unhide": "Parameters:\n* $1 - a HTML link to the revision\n{{Related|Rev-deleted-text}}",
        "rev-suppressed-text-unhide": "Parameters:\n* $1 - a HTML link to the revision\n{{Related|Rev-deleted-text}}",
-       "rev-deleted-text-view": "This is an error message which appears if a user tries to view a past revision of a page, where the revision has been hidden from view, although later revisions of the page still exist.",
-       "rev-suppressed-text-view": "{{Related|Rev-deleted-text}}",
+       "rev-deleted-text-view": "This message appears in case a user tries to view a past deleted revision of a page, although later revisions of the page still exist.\n{{Related|Rev-deleted-text}}",
+       "rev-suppressed-text-view": "This message appears in case a user tries to view a past suppressed revision of a page, although later revisions of the page still exist.\n{{Related|Rev-deleted-text}}",
        "rev-deleted-no-diff": "See also:\n* {{msg-mw|Rev-suppressed-no-diff}}",
        "rev-suppressed-no-diff": "See also:\n* {{msg-mw|Rev-deleted-no-diff}}",
        "rev-deleted-unhide-diff": "Parameters:\n* $1 - a HTML link to the diff\n{{Related|Rev-deleted-diff}}",
        "searchprofile-advanced-tooltip": "Used as tooltip for the option {{msg-mw|Searchprofile-advanced}} in [[Special:Search]].\n\nSee also:\n* {{msg-mw|Searchprofile-advanced|message}}\n* {{msg-mw|Searchprofile-advanced-tooltip|tooltip}}",
        "search-result-size": "Shown per line of a [[Special:Search|search result]]\n* $1 - the size of the page in bytes, but no need to add \"byte\" or similar as the unit is added by special function\n* $2 - the sum of all words in this page",
        "search-result-category-size": "Parameters:\n* $1 - number of members in this category. $1 is equal to $2+$3.\n* $2 - number of subcategories\n* $3 - number of files",
-       "search-result-score": "Shown per line of a [[Special:Search|search result]]. Parameters:\n* $1 - the relevance of this result in percent\n{{Identical|Relevance: $1%}}",
        "search-redirect": "\"Redirect\" is a noun here, not a verb.\n\nParameters:\n* $1 - a link to the redirect to the page (so, $1 is the page that the search result is redirected '''from''')",
        "search-section": "This text will be shown on the search result listing after the page title of a result if the search algorithm thinks that section is more relevant than the rest of the page. $1 is a section title.\n{{Identical|Section}}",
        "search-file-match": "This text will be shown on the search result listing after the page title of a result if the search engine got search results from the contents of files, rather than the pages.",
        "searchall": "{{Identical|All}}",
        "showingresults": "This message is used on some special pages such as [[Special:WantedCategories]]. Parameters:\n* $1 - the total number of results in the batch shown\n* $2 - the number of the first item listed\nSee also:\n* {{msg-mw|Showingresultsnum}}",
        "showingresultsinrange": "Used in pagination of [[Special:MostLinkedCategories]]. Parameters:\n* $1 - the total number of results in the batch shown\n* $2 - the number of the first item listed\n* $3 - the number of last item in the batch shown\n\nSee also {{msg-mw|Showingresults}}",
-       "showingresultsheader": "Used in search results of [[Special:Search]]. Parameters:\n* $1 - minimum offset\n* $2 - maximum offset\n* $3 - total number of results\n* $4 - the search term\n* $5 - number of results",
+       "search-showingresults": "Used in search results of [[Special:Search]]. Parameters:\n* $1 - minimum offset\n* $2 - maximum offset\n* $3 - total number of results\n* $4 - number of results",
        "search-nonefound": "Message shown when a search returned no results (when using the default MediaWiki search engine).",
        "powersearch-legend": "Advanced search\n\n{{Identical|Advanced search}}",
        "powersearch-ns": "Used in the extended search form at [[Special:Search]]",
        "preferences": "Title of the [[Special:Preferences]] page.\n{{Identical|Preferences}}",
        "preferences-summary": "{{doc-specialpagesummary|preferences}}",
        "mypreferences": "Action link label that leads to [[Special:Preferences]]; appears in the top menu (e.g. \"Username Talk Preferences Watchlist Contributions Log out\").\n\nSee also:\n* {{msg-mw|Mypreferences}}\n* {{msg-mw|Accesskey-pt-preferences}}\n* {{msg-mw|Tooltip-pt-preferences}}\n{{Identical|Preferences}}",
-       "prefs-edits": "In user preferences.",
-       "prefsnologintext2": "Parameters:\n* $1 - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description",
+       "prefs-edits": "In user preferences.\n{{Identical|Number of edits}}",
+       "prefsnologintext2": "Showed on Special:Userlogin when user tries to access their preferences before logging in",
        "prefs-skin": "Used in user preferences.\n{{Identical|Skin}}",
        "skin-preview": "{{doc-actionlink}}\nThe link beside each skin name in [[Special:Preferences|your user preferences]], tab \"skin\".\n{{Identical|Preview}}",
        "datedefault": "Used as checkbox label in [[Special:Preferences#mw-prefsection-datetime|user preferences]], {{msg-mw|prefs-datetime}} tab.\n\nThis message indicates {{msg-mw|prefs-dateformat}} is default (= not specified).",
        "prefs-labs": "Header of a subsection at [[Special:Preferences]], tab ''{{int:prefs-editing}}'', listing features that are experimental",
-       "prefs-user-pages": "Header of a subsection at [[Special:Preferences]], tab ''{{int:prefs-misc}}'', listing features that are related to user pages",
+       "prefs-user-pages": "Header of a subsection at [[Special:Preferences]], tab ''{{int:prefs-misc}}'', listing features that are related to user pages\n{{Identical|User page}}",
        "prefs-personal": "Title of a tab in [[Special:Preferences]].\n{{Identical|User profile}}",
        "prefs-rc": "Used in user preferences.\n\n{{Identical|Recent changes}}",
        "prefs-watchlist": "Used in user preferences.\n{{Identical|Watchlist}}",
        "timezoneregion-pacific": "Used in \"Time zone\" listbox in [[Special:Preferences#mw-prefsection-datetime|preferences]], \"date and time\" tab.\n{{Related|Timezoneregion}}",
        "allowemail": "Used in [[Special:Preferences]] > {{int:prefs-personal}} > {{int:email}}.",
        "prefs-searchoptions": "{{Identical|Search}}",
-       "prefs-namespaces": "Shown as legend of the second fieldset of the tab 'Search' in [[Special:Preferences]]\n{{Identical|Namespaces}}",
+       "prefs-namespaces": "Shown as legend of the second fieldset of the tab 'Search' in [[Special:Preferences]]\n{{Identical|Namespace}}",
        "default": "{{Identical|Default}}",
        "prefs-files": "Title of a tab in [[Special:Preferences]].\n{{Identical|File}}",
        "prefs-custom-css": "visible on [[Special:Preferences]] -[Skins].\n{{Identical|Custom CSS}}",
        "prefs-custom-js": "visible on [[Special:Preferences]] -[Skins].\n{{Identical|Custom JavaScript}}",
-       "prefs-common-css-js": "Used as label in [[Special:Preferences#mw-prefsection-rendering|preferences]], tab \"Appearance\", section \"Skin\".",
+       "prefs-common-css-js": "Used as label in [[Special:Preferences#mw-prefsection-rendering|preferences]], tab \"Appearance\", section \"Skin\".\n\nSee also:\n* {{msg-mw|Globalcssjs-custom-css-js}}",
        "prefs-reset-intro": "Used in [[Special:Preferences/reset]].",
        "prefs-emailconfirm-label": "Sub-heading in [[Special:Preferences]] > {{int:prefs-personal}} > {{int:email}}.",
        "youremail": "Label of the e-mail text box of the \"E-mail options\" section of [[Special:Preferences]].\nAlso used on create account form.\n\n{{Identical|E-mail}}",
        "group-bureaucrat": "{{doc-group|bureaucrat}}",
        "group-suppress": "{{doc-group|suppress}}\nThis is an optional (disabled by default) user group, meant for the [[mw:RevisionDelete|RevisionDelete]] feature, to change the visibility of revisions through [[Special:RevisionDelete]].\n\n{{Identical|Oversight}}",
        "group-all": "The name of the user group that contains all users, including anonymous users\n\n{{Identical|All}}",
-       "group-user-member": "{{doc-group|user|member}}",
+       "group-user-member": "{{doc-group|user|member}}\n{{Identical|User}}",
        "group-autoconfirmed-member": "{{doc-group|autoconfirmed|member}}",
        "group-bot-member": "{{doc-group|bot|member}}",
-       "group-sysop-member": "{{doc-group|sysop|member}}",
+       "group-sysop-member": "{{doc-group|sysop|member}}\n{{Identical|Administrator}}",
        "group-bureaucrat-member": "{{doc-group|bureaucrat|member}}",
        "group-suppress-member": "{{doc-group|suppress|member}}\nThis is a member of the optional (disabled by default) user group, meant for the [[mw:RevisionDelete|RevisionDelete]] feature, to change the visibility of revisions through [[Special:RevisionDelete]].\n\n{{Identical|Oversight}}",
-       "grouppage-user": "{{doc-group|user|page}}",
+       "grouppage-user": "{{doc-group|user|page}}\n{{Identical|User}}",
        "grouppage-autoconfirmed": "{{doc-group|autoconfirmed|page}}",
        "grouppage-bot": "{{doc-group|bot|page}}\n{{Identical|Bot}}",
        "grouppage-sysop": "{{doc-group|sysop|page}}",
        "right-deletedtext": "{{doc-right|deletedtext}}",
        "right-browsearchive": "{{doc-right|browsearchive}}",
        "right-undelete": "{{doc-right|undelete}}",
-       "right-suppressrevision": "{{doc-right|suppressrevision}}\nThis user right is part of the [[mw:RevisionDelete|RevisionDelete]] feature.\nIt can be given to the group {{msg-mw|group-suppress}}, although that group is disabled by default.\n\nSee also:\n* {{msg-mw|right-suppressionlog}}\n* {{msg-mw|right-hideuser}}\n* {{msg-mw|right-deletelogentry}}\n* {{msg-mw|right-deleterevision}}",
+       "right-suppressrevision": "{{doc-right|suppressrevision}}\nThis user right is part of the [[mw:RevisionDelete|RevisionDelete]] feature.\nIt can be given to the group {{msg-mw|group-suppress}}, although that group is disabled by default.\n\nSee also:\n* {{msg-mw|right-suppressionlog}}\n* {{msg-mw|right-viewsuppressed}}\n* {{msg-mw|right-hideuser}}\n* {{msg-mw|right-deletelogentry}}\n* {{msg-mw|right-deleterevision}}",
+       "right-viewsuppressed": "{{doc-right|viewsuppressed}}\nThis user right is part of the [[mw:RevisionDelete|RevisionDelete]] feature.\nIt can be given to any group for observation of suppression activities.\n\nSee also:\n* {{msg-mw|right-suppressrevision}}",
        "right-suppressionlog": "{{doc-right|suppressionlog}}\nThis user right is part of the [[mw:RevisionDelete|RevisionDelete]] feature.\nIt can be given to the group {{msg-mw|group-suppress}}, although that group is disabled by default.\n\nSee also\n* {{msg-mw|right-suppressrevision}}\n* {{msg-mw|right-hideuser}}\n* {{msg-mw|right-deletelogentry}}\n* {{msg-mw|right-deleterevision}}",
        "right-block": "{{doc-right|block}}",
        "right-blockemail": "{{doc-right|blockemail}}",
        "recentchanges-legend-bot": "Used as legend on [[Special:RecentChanges]] and [[Special:Watchlist]].\n\nRefers to {{msg-mw|Recentchanges-label-bot}}.",
        "recentchanges-legend-unpatrolled": "Used as legend on [[Special:RecentChanges]] and [[Special:Watchlist]].\n\nRefers to {{msg-mw|Recentchanges-label-unpatrolled}}.",
        "recentchanges-legend-plusminus": "{{optional}}\nA plus/minus sign with a number for the legend.",
-       "rcnotefrom": "This message is displayed at [[Special:RecentChanges]] when viewing recentchanges from some specific time.\n\nThe corresponding message is {{msg-mw|Rclistfrom}} (split into date and time).\n\nParameters:\n* $1 - the maximum number of changes that are displayed\n* $2 - a date and time\n* $3 - (Optional) a date\n* $4 - (Optional) a time",
+       "rcnotefrom": "This message is displayed at [[Special:RecentChanges]] when viewing recentchanges from some specific time.\n\nThe corresponding message is {{msg-mw|Rclistfrom}}.\n\nParameters:\n* $1 - the maximum number of changes that are displayed\n* $2 - (Optional) a date and time\n* $3 - a date\n* $4 - a time\n* $5 - Number of changes are displayed, for use with PLURAL",
        "rclistfrom": "Used on [[Special:RecentChanges]]. Parameters:\n* $1 - (Currently not use) date and time. The date and the time adds to the rclistfrom description.\n* $2 - time. The time adds to the rclistfrom link description (with split of date and time).\n* $3 - date. The date adds to the rclistfrom link description (with split of date and time).\n\nThe corresponding message is {{msg-mw|Rcnotefrom}}.",
        "rcshowhideminor": "Option text in [[Special:RecentChanges]]. Parameters:\n* $1 - the \"show/hide\" command, with the text taken from either {{msg-mw|rcshowhideminor-show}} or {{msg-mw|rcshowhideminor-hide}}\n{{Identical|Minor edit}}",
        "rcshowhideminor-show": "{{doc-actionlink}}\nOption text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhideminor}}.\n\nSee also:\n* {{msg-mw|rcshowhideminor-hide}}\n{{Identical|Show}}",
        "uploadwarning": "Used as section header in [[Special:Upload]].",
        "uploadwarning-text": "Used in [[Special:Upload]].",
        "savefile": "When uploading a file",
-       "uploadedimage": "This is the text of an entry in the [[Special:Log|upload log]] (and Recent Changes), after hour (and date, only in the Upload log) and user name. $1 is the name of the file uploaded.",
-       "overwroteimage": "This is the text of an entry in the [[Special:Log|upload log]] (and Recent Changes), after hour (and date, only in the Upload log) and user name. $1 is the name of the file uploaded.",
+       "uploadedimage": "{{ignored}}This is ''logentry'' message only used on IRC. $1 is the name of the file uploaded.",
+       "overwroteimage": "{{ignored}}This is ''logentry'' message only used on IRC. $1 is the name of the file uploaded.",
        "uploaddisabled": "Title of the [[Special:Upload]] page when upload is disabled.\n\nSee also:\n* {{msg-mw|Copyuploaddisabled}}",
        "copyuploaddisabled": "See also:\n* {{msg-mw|Uploaddisabled}}",
        "uploaddisabledtext": "Parameters:\n* $1 - (Optional) the name of the target file. See r22243 and [[bugzilla:8818|bug 8818]].",
        "license-header": "Used as section header in [[Special:Upload]].\n\nSee also:\n* {{msg-mw|Filedesc}}\n* {{msg-mw|Filestatus}}\n* {{msg-mw|Filesource}}\n{{Identical|Licensing}}",
        "nolicense": "{{Identical|None selected}}",
        "licenses": "{{notranslate}}",
+       "licenses-edit": "Label text for a link on Special:Upload to edit MediaWiki:Licenses",
        "license-nopreview": "Error message when a certain license does not exist",
        "upload_source_url": "Used in [[Special:Upload]].\n\nSee also:\n* {{msg-mw|Sourcefilename|label}}\n* {{msg-mw|Sourceurl|label}}\n* {{msg-mw|Upload source file}}\n* {{msg-mw|Upload-maxfilesize}}",
        "upload_source_file": "Used in [[Special:Upload]].\n\nSee also:\n* {{msg-mw|Sourcefilename|label}}\n* {{msg-mw|Sourceurl|label}}\n* {{msg-mw|Upload source url}}\n* {{msg-mw|Upload-maxfilesize}}",
-       "listfiles-delete": "Text of the delete links next to the entries on [[Special:ListFiles]], surrounded by parentheses.",
+       "listfiles-delete": "Text of the delete links next to the entries on [[Special:ListFiles]], surrounded by parentheses.\n{{Identical|Delete}}",
        "listfiles-summary": "This message is displayed at the top of [[Special:ImageList]] to explain how to use that special page.",
        "listfiles_search_for": "Input label for the form displayed on [[Special:ListFiles]].",
        "imgfile": "{{Identical|File}}",
        "randompage": "{{doc-special|RandomPage}}\nSee also:\n* {{msg-mw|Randompage}}\n* {{msg-mw|Accesskey-n-randompage}}\n* {{msg-mw|Tooltip-n-randompage}}\n{{Identical|Random page}}",
        "randompage-nopages": "Parameters:\n* $1 - list of namespaces\n* $2 - number of namespaces, for PLURAL support\nSee also:\n* {{msg-mw|Randomredirect-nopages}}",
        "randompage-url": "{{notranslate}}",
-       "randomincategory": "{{doc-special|RandomInCategory}}",
+       "randomincategory": "{{doc-special|RandomInCategory}}\n{{Identical|Random page in category}}",
        "randomincategory-invalidcategory": "Message shown if an invalid category is specified.\n\nParameters:\n* $1 - the invalid category name given\n\n(Note, if the category is simply empty, but could possibly exist, {{msg-mw|randomincategory-nopages}} is shown instead)",
        "randomincategory-nopages": "Message shown from [[Special:RandomInCategory]] if the category is empty.\n\nParameters:\n* $1 - the category name (without the namespace prefix)",
-       "randomincategory-selectcategory": "Shown on [[Special:RandomInCategory]] if no category is selected.\n\nDisplays a form allowing the user to input a category name.\n\nParameters:\n* $1 - the text field input box\n* $2 - the go button which has the label {{msg-mw|randomincategory-selectcategory-submit}}.",
-       "randomincategory-selectcategory-submit": "Used as label for the Submit button which is used as <code>$2</code> in {{msg-mw|Randomincategory-selectcategory}}.\n{{Identical|Go}}",
+       "randomincategory-category": "Shown on [[Special:RandomInCategory]] as a label for a text box allowing the user to input a category name.\n{{Identical|Category}}",
+       "randomincategory-legend": "Used as fieldset label for the form on [[Special:RandomInCategory]].",
        "randomredirect": "{{doc-special|RandomRedirect}}",
        "randomredirect-nopages": "Parameters:\n* $1 - list of namespaces\n* $2 - (Unused) number of namespaces\nSee also:\n* {{msg-mw|Randompage-nopages}}",
        "statistics": "{{doc-special|Statistics}}\n{{Identical|Statistics}}",
        "popularpages-summary": "{{doc-specialpagesummary|popularpages}}",
        "wantedcategories": "{{doc-special|WantedCategories}}",
        "wantedcategories-summary": "{{doc-specialpagesummary|wantedcategories}}",
-       "wantedpages": "{{doc-special|WantedPages}}",
+       "wantedpages": "{{doc-special|WantedPages}}\n{{Identical|Wanted page}}",
        "wantedpages-summary": "{{doc-specialpagesummary|wantedpages}}",
        "wantedpages-badtitle": "Error message shown when [[Special:WantedPages]] is listing a page with a title that shouldn't exist.\n\nParameters:\n* $1 - a page title",
        "wantedfiles": "{{doc-special|WantedFiles}}",
        "wantedfiles-summary": "{{doc-specialpagesummary|wantedfiles}}",
-       "wantedfiletext-cat": "Message displayed at top of [[special:WantedFiles]]. $1 contains the name of the tracking category for broken files (Including Category prefix). {{msg-mw|wantedfiletext-nocat}} is used if the tracking category is disabled.",
-       "wantedfiletext-nocat": "Message displayed at top of [[special:WantedFiles]] when broken file tracking category is disabled. See {{msg-mw|wantedfiletext-cat}}.",
+       "wantedfiletext-cat": "Message displayed at top of [[special:WantedFiles]] when false positives from foreign file repositories (like commons) are likely. $1 contains the name of the tracking category for broken files (Including Category prefix). {{msg-mw|wantedfiletext-nocat}} is used if the tracking category is disabled.\n\nSee also: {{msg-mw|wantedfiletext-cat-noforeign}}, {{msg-mw|wantedfiletext-nocat}}",
+       "wantedfiletext-cat-noforeign": "Message displayed at top of [[Special:WantedFiles]] when the wiki has no foreign repositories. See also {{msg-mw|wantedfilestext-cat}}. $1 contains the name of the tracking category for broken files (Including Category prefix). {{msg-mw|wantedfiletext-nocat}} is used if the tracking category is disabled.",
+       "wantedfiletext-nocat": "Message displayed at top of [[special:WantedFiles]] when broken file tracking category is disabled and false positives from foreign file repositories (like commons) are likely. See {{msg-mw|wantedfiletext-cat}}.",
+       "wantedfiletext-nocat-noforeign": "Message displayed at top of [[special:WantedFiles]] when broken file tracking category is disabled and their are no foreign file repositories enabled on the wiki. See {{msg-mw|wantedfiletext-cat}}, {{msg-mw|wantedfiletext-nocat}}.",
        "wantedtemplates": "{{doc-special|WantedTemplates}}",
        "wantedtemplates-summary": "{{doc-specialpagesummary|wantedtemplates}}",
        "mostlinked": "{{doc-special|MostLinked}}",
        "mywatchlist": "Link at the upper right corner of the screen.\n\nSee also:\n* {{msg-mw|Mywatchlist}}\n* {{msg-mw|Accesskey-pt-watchlist}}\n* {{msg-mw|Tooltip-pt-watchlist}}\n{{Identical|Watchlist}}",
        "watchlistfor2": "Subtitle on [[Special:Watchlist]].\nParameters:\n* $1 - Username of current user\n* $2 - Tool links (View relevant changes | View and edit watchlist | Edit raw watchlist)\n{{Identical|For $1}}",
        "nowatchlist": "Displayed when there is no pages in the watchlist.",
-       "watchlistanontext": "Parameters:\n* $1 - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description",
+       "watchlistanontext": "Shown on Special:Userlogin when user tries to access their watchlist before logging in",
        "watchnologin": "Used as error page title.\n\nThe error message for this title is:\n* {{msg-mw|Watchnologintext}}\n{{Identical|Not logged in}}",
        "addwatch": "Link to a dialog box, displayed at the end of the list of categories at the foot of each page.\n\nSee also:\n* {{msg-mw|Removewatch}}",
        "addedwatchtext": "Explanation shown when clicking on the {{msg-mw|Watch}} tab. Parameters:\n* $1 - page title\nSee also:\n* {{msg-mw|Addedwatch}}",
        "watchlist-details": "Message on [[Special:Watchlist]]. Parameters:\n* $1 - number of pages in your watchlist\nThis is paired with the message {{msg-mw|Nowatchlist}} which appears instead of Watchlist-details when $1 is 0.\nSee also:\n* {{msg-mw|Watchlist-options|fieldset}}\n* {{msg-mw|Wlheader-enotif|watchlist header}}\n* {{msg-mw|enotif reset|Submit button text}}\n* {{msg-mw|Watchlistcontains}}",
        "wlheader-enotif": "Message at the top of [[Special:Watchlist]], after {{msg-mw|watchlist-details}}. Has to be a full sentence.\n\nSee also:\n* {{msg-mw|Watchlist-options|fieldset}}\n* {{msg-mw|enotif reset|Submit button text}}",
        "wlheader-showupdated": "Message at the top of [[Special:Watchlist]], after {{msg-mw|watchlist-details}}. Has to be a full sentence.",
-       "wlnote2": "Used on [[Special:Watchlist]] when a maximum number of hours or days is specified.\n\nParameters:\n* $1 - the number of hours for which the changes are shown\n* $2 - a date alone\n* $3 - a time alone\nSee also:\n* {{msg-mw|Wlnote}}",
+       "wlnote": "Used on [[Special:Watchlist]] when a maximum number of hours or days is specified.\n\nParameters:\n* $1 - the number of changes shown\n* $2 - the number of hours for which the changes are shown\n* $3 - a date alone\n* $4 - a time alone",
        "wlshowlast": "Appears on [[Special:Watchlist]]. Parameters:\n* $1 - a choice of different numbers of hours (\"1 | 2 | 6 | 12\")\n* $2 - a choice of different numbers of days (\"1 | 3 | 7\")\n* $3 - {{msg-mw|watchlistall2}}\nClicking on your choice changes the list of changes you see (without changing the default in my preferences).",
        "watchlist-options": "Legend of the fieldset of [[Special:Watchlist]]\n\nSee also:\n* {{msg-mw|Watchlist-details|watchlist header}}\n* {{msg-mw|Wlheader-enotif|watchlist header}}\n* {{msg-mw|enotif reset|Submit button text}}",
        "watching": "Text displayed when clicked on the watch tab: {{msg-mw|Watch}}. It means the wiki is adding that page to your watchlist.",
        "excontent": "Automated deletion reason when deleting a page for admins. Parameters:\n* $1 - content before deletion",
        "excontentauthor": "Automated deletion reason when deleting a page for admins providing that the page has one author only.\n\nParameters:\n* $1 - content before deletion\n* $2 - username",
        "exbeforeblank": "Automated deletion reason when deleting a page for admins providing that the page was blanked before deletion.\n\nParameters:\n* $1 - content before blanking",
-       "delete-confirm": "Used as page title. Parameters:\n* $1 - the page title",
+       "delete-confirm": "Used as page title. Parameters:\n* $1 - the page title\n{{Identical|Delete}}",
        "delete-legend": "{{Identical|Delete}}",
-       "historywarning": "Warning when about to delete a page that has history.\n\nFollowed by a link which points to the history page.\n\nParameters:\n* $1 - the <b>approximate</b> number of revisions that the page has, the message should not claim to give an exact count",
+       "historywarning": "Warning when about to delete a page that has history.\n\nFollowed by a link which points to the history page.\n\nParameters:\n* $1 - the number of revisions that the page has",
        "confirmdeletetext": "Introduction shown when deleting a page.\n\nRefers to {{msg-mw|Policy-url}}.",
        "actioncomplete": "Used in several situations, for example when a page has been deleted.\n\nSee also:\n* {{msg-mw|Actionfailed|page title}}",
        "actionfailed": "Used as page title when the submit operation failed, in [[Special:RevisionDelete]].\n\nSee also:\n* {{msg-mw|Actioncomplete|page title}}",
        "delete-edit-reasonlist": "Shown beneath the page deletion form on the right side. It is a link to {{msg-mw|Deletereason-dropdown|notext=1}}.\n\nSee also:\n* {{msg-mw|Ipb-edit-dropdown}}\n* {{msg-mw|Protect-edit-reasonlist}}.\n{{Identical|Edit delete reasons}}",
        "delete-toobig": "Parameters:\n* $1 - the upper limit of number of revisions\nSee also:\n* {{msg-mw|Delete-warning-toobig}}",
        "delete-warning-toobig": "Parameters:\n* $1 - the upper limit of number of revisions\nSee also:\n* {{msg-mw|Delete-toobig}}",
+       "deleteprotected": "Used as error message when deleting the page.\n\n\"If protection keeps them from editing, they shouldn't be able to delete.\"",
        "deleting-backlinks-warning": "A warning shown when a page that is being deleted has at least one link to it or is transcluded in at least one page.",
        "rollback": "{{Identical|Rollback}}",
        "rollback_short": "{{Identical|Rollback}}",
        "protect-summary-cascade": "Used in edit summary when cascade protecting a page. Appears in protection log. See [[Special:Log]] and [[m:Special:Log]].\n\nAlso used in [[Special:ProtectedPages]] when a page is cascade protected. See example: [[m:Special:ProtectedPages]].<br />\nSee also:\n*{{msg-mw|Restriction-level-sysop}}\n*{{msg-mw|Restriction-level-autoconfirmed}}",
        "protect-expiring": "Used as expiry text in page history, and in [[Special:Protectedtitles]], [[Special:Protectedpages]], and extension FlaggedRevs.\n* $1 - a date and time\n* $2 - a date (optional)\n* $3 - a time (optional)\nIf the expiry is indefinite, {{msg-mw|protect-expiry-indefinite}} is used.\n{{Identical|Expires $1 (UTC)}}",
        "protect-expiring-local": "Parameter:\n* $1 - a timestamp like \"22:51, 23 July 2011 (UTC)\" depending on the wiki content language.\n{{Identical|Expire}}",
-       "protect-expiry-indefinite": "Used as expiry text in page history, and in [[Special:Protectedtitles]], [[Special:Protectedpages]], and extension FlaggedRevs.\n\nIf the expiry is definite, {{msg-mw|protect-expiring}} is used.",
+       "protect-expiry-indefinite": "Used as expiry text in page history, and in [[Special:Protectedtitles]], [[Special:Protectedpages]], and extension FlaggedRevs.\n\nIf the expiry is definite, {{msg-mw|protect-expiring}} is used.\n{{Identical|Indefinite}}",
        "protect-cascade": "See [[meta:Protect]] for more information.",
        "protect-cantedit": "Used as error message when changing the protection levels of the page.",
        "protect-othertime": "Used on the page protection form as label for the following input field (text)\n{{Identical|Other time}}",
        "sp-contributions-suppresslog": "Used as a display name for a link to log entries of suppressed edits made by that user.\n\nUsed as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].\n\nSee also {{msg-mw|sp-contributions-deleted}}, {{msg-mw|sp-deletedcontributions-contribs}}, {{msg-mw|contributions}}, {{msg-mw|deletedcontributions-title}}.",
        "sp-contributions-deleted": "This is a link anchor used in [[Special:Contributions]]/''name'', when user viewing the page has the right to delete pages, or to restore deleted pages.\n\nUsed as link title in [[Special:Contributions]].\n\nSee also:\n* {{msg-mw|Sp-contributions-talk}}\n* {{msg-mw|Change-blocklink}}\n* {{msg-mw|Unblocklink}}\n* {{msg-mw|Blocklink}}\n* {{msg-mw|Sp-contributions-blocklog}}\n* {{msg-mw|Sp-contributions-uploads}}\n* {{msg-mw|Sp-contributions-logs}}\n* {{msg-mw|Sp-contributions-userrights}}",
        "sp-contributions-uploads": "Used as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].\n\nSee also:\n* {{msg-mw|Sp-contributions-talk}}\n* {{msg-mw|Change-blocklink}}\n* {{msg-mw|Unblocklink}}\n* {{msg-mw|Blocklink}}\n* {{msg-mw|Sp-contributions-blocklog}}\n* {{msg-mw|Sp-contributions-logs}}\n* {{msg-mw|Sp-contributions-deleted}}\n* {{msg-mw|Sp-contributions-userrights}}\n{{Identical|Upload}}",
-       "sp-contributions-logs": "Appears as an action link in the header of the Special:Contributions/''Username'' pages (e.g. \"For Somebody (talk | block log | logs)\").\n\nUsed as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].\n\nSee also:\n* {{msg-mw|Sp-contributions-talk}}\n* {{msg-mw|Change-blocklink}}\n* {{msg-mw|Unblocklink}}\n* {{msg-mw|Blocklink}}\n* {{msg-mw|Sp-contributions-blocklog}}\n* {{msg-mw|Sp-contributions-uploads}}\n* {{msg-mw|Sp-contributions-deleted}}\n* {{msg-mw|Sp-contributions-userrights}}",
+       "sp-contributions-logs": "Appears as an action link in the header of the Special:Contributions/''Username'' pages (e.g. \"For Somebody (talk | block log | logs)\").\n\nUsed as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].\n\nSee also:\n* {{msg-mw|Sp-contributions-talk}}\n* {{msg-mw|Change-blocklink}}\n* {{msg-mw|Unblocklink}}\n* {{msg-mw|Blocklink}}\n* {{msg-mw|Sp-contributions-blocklog}}\n* {{msg-mw|Sp-contributions-uploads}}\n* {{msg-mw|Sp-contributions-deleted}}\n* {{msg-mw|Sp-contributions-userrights}}\n{{Identical|Log}}",
        "sp-contributions-talk": "This is a link anchor used in the [[Special:Contributions]]/''usernamename'' pages.\nThe link appears in a list of similar ones separated by {{msg-mw|pipe-separator}}, e.g. like this:<br />\n( talk | block log | logs | deleted contributions | rights management )\n\nUsed as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].\n\nSee also:\n* {{msg-mw|change-blocklink}}\n* {{msg-mw|unblocklink}}\n* {{msg-mw|blocklink}}\n* {{msg-mw|sp-contributions-blocklog}}\n* {{msg-mw|sp-contributions-uploads}}\n* {{msg-mw|sp-contributions-logs}}\n* {{msg-mw|sp-contributions-deleted}}\n* {{msg-mw|sp-contributions-userrights}}\n{{Identical|Talk}}",
        "sp-contributions-userrights": "This is a link anchor used in [[Special:Contributions]]/''name'', if the user viewing the page has the right to set or alter user rights.\n\nUsed as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].\n\nSee also:\n* {{msg-mw|Sp-contributions-talk}}\n* {{msg-mw|Change-blocklink}}\n* {{msg-mw|Unblocklink}}\n* {{msg-mw|Blocklink}}\n* {{msg-mw|Sp-contributions-blocklog}}\n* {{msg-mw|Sp-contributions-uploads}}\n* {{msg-mw|Sp-contributions-logs}}\n* {{msg-mw|Sp-contributions-deleted}}",
        "sp-contributions-blocked-notice": "Shown on top of contributions special page of currently blocked users.\n\nParameters:\n* $1 - (Optional) the blocked user. Can be used for GENDER\nAnon version:\n* {{msg-mw|Sp-contributions-blocked-notice-anon}}",
        "whatlinkshere-prev": "This is part of the navigation message on the top and bottom of Whatlinkshere pages, where it is used as the first argument of {{msg-mw|Viewprevnext}}.\n\nParameters:\n* $1 - the number of items shown per page. It is not used when $1 is zero; not sure what happens when $1 is one.\nSpecial pages use {{msg-mw|Prevn}} instead (still as an argument to {{msg-mw|Viewprevnext}}).\n\nSee also:\n* {{msg-mw|Whatlinkshere-next}}\n{{Identical|Previous}}",
        "whatlinkshere-next": "This is part of the navigation message on the top and bottom of Whatlinkshere pages, where it is used as the second argument of {{msg-mw|Viewprevnext}}.\n\nParameters:\n* $1 - the number of items shown per page. It is not used when $1 is zero; not sure what happens when $1 is one.\nSpecial pages use {{msg-mw|Nextn}} instead (still as an argument to {{msg-mw|Viewprevnext}}).\n\nSee also:\n* {{msg-mw|Whatlinkshere-prev}}\n{{Identical|Next}}",
        "whatlinkshere-links": "Used on [[Special:WhatLinksHere]]. It is a link to the WhatLinksHere page of that page.\n\nExample line:\n* [[Main Page]] ([[Special:WhatLinksHere/Main Page|{{int:whatlinkshere-links}}]])\n{{Identical|Link}}",
-       "whatlinkshere-hideredirs": "Filter option in [[Special:WhatLinksHere]]. Parameters:\n* $1 is the {{msg-mw|hide}} or {{msg-mw|show}}",
-       "whatlinkshere-hidetrans": "First filter option in [[Special:WhatLinksHere]]. Parameters:\n* $1 is the {{msg-mw|hide}} or {{msg-mw|show}}",
-       "whatlinkshere-hidelinks": "Filter option in [[Special:WhatLinksHere]]. Parameters:\n* $1 is the {{msg-mw|hide}} or {{msg-mw|show}}",
+       "whatlinkshere-hideredirs": "Filter option in [[Special:WhatLinksHere]]. Parameters:\n* $1 is the {{msg-mw|hide}} or {{msg-mw|show}}\n{{Identical|Redirect}}",
+       "whatlinkshere-hidetrans": "First filter option in [[Special:WhatLinksHere]]. Parameters:\n* $1 is the {{msg-mw|hide}} or {{msg-mw|show}}\n{{Identical|Transclusion}}",
+       "whatlinkshere-hidelinks": "Filter option in [[Special:WhatLinksHere]]. Parameters:\n* $1 is the {{msg-mw|hide}} or {{msg-mw|show}}\n{{Identical|Link}}",
        "whatlinkshere-hideimages": "Filter option in [[Special:WhatLinksHere]]. Parameters:\n* $1 - the {{msg-mw|Hide}} or {{msg-mw|Show}}\n\nSee also:\n*{{msg-mw|Isimage}}\n*{{msg-mw|Media tip}}",
        "whatlinkshere-filters": "{{Identical|Filter}}",
        "autoblockid": "Used as name of autoblock, instead of autoblocked IPs. Parameters:\n* $1 - autoblock ID",
        "block": "{{doc-special|Block}}\n{{Identical|Block user}}",
        "unblock": "{{doc-special|Unblock}}",
        "unblock-summary": "{{doc-specialpagesummary|unblock}}",
-       "blockip": "Used as the text of a link in the sidebar toolbox. Clicking this link takes you to [[Special:Block]], with a relevant username or IP address (e.g. \"Username\" on [[User talk:Username]], [[Special:Contributions/Username]], etc.) already filled in.\n\n{{Identical|Block user}}",
+       "blockip": "Used as the text of a link in the sidebar toolbox. Clicking this link takes you to [[Special:Block]], with a relevant username or IP address (e.g. \"Username\" on [[User talk:Username]], [[Special:Contributions/Username]], etc.) already filled in.\n\nParameters:\n* $1 - username, for GENDER support\n{{Identical|Block user}}",
        "blockip-legend": "Legend/Header for the fieldset around the input form of [[Special:Block]].\n\n{{Identical|Block user}}",
        "blockiptext": "Used in the {{msg-mw|Blockip}} form in [[Special:Block]].\n\nRefers to {{msg-mw|Policy-url}}.\n\nThis message may follow the message {{msg-mw|Ipb-otherblocks-header}} and other block messages.\n\nSee also:\n* {{msg-mw|Unblockiptext}}",
        "ipaddressorusername": "{{Identical|IP address or username}}",
        "ipb-confirmhideuser": "Used as confirmation message in [[Special:Block]].\n\nSee also:\n* {{msg-mw|Ipb-blockingself}}",
        "ipb-confirmaction": "Confirmation message displayed to users asking them to think again before really blocking someone.",
        "ipb-edit-dropdown": "Shown beneath the user block form on the right side. It is a link to {{msg-mw|Ipbreason-dropdown|notext=1}}.\n\nSee also:\n* {{msg-mw|Delete-edit-reasonlist}}\n* {{msg-mw|Protect-edit-reasonlist}}",
-       "ipb-unblock-addr": "Used as page title in [[Special:Block]], if the target user is specified.\n\nParameters:\n* $1 - target username\n\nSee also:\n* {{msg-mw|Ipb-unblock}}",
+       "ipb-unblock-addr": "Used as page title in [[Special:Block]], if the target user is specified.\n\nParameters:\n* $1 - target username\n\nSee also:\n* {{msg-mw|Ipb-unblock}}\n{{Identical|Unblock}}",
        "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",
        "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",
-       "unblocked": "{{doc-important|Do not translate the namespace \"User:\".}}\nParameters:\n* $1 - the IP address or username that was unblocked\nSee also:\n* {{msg-mw|Unblocked-range}}\n* {{msg-mw|Unblocked-id}}",
-       "unblocked-range": "Shown when successfully lifting a rangeblock, so do not link to contributions. Parameters:\n* $1 - the range that was unblocked\nSee also:\n* {{msg-mw|Unblocked}}\n* {{msg-mw|Unblocked-id}}",
+       "unblocked": "{{doc-important|Do not translate the namespace \"User:\".}}\nParameters:\n* $1 - the username that was unblocked\nSee also:\n* {{msg-mw|Unblocked-range}}\n* {{msg-mw|Unblocked-id}}\n*{{msg-mw|Unblocked-ip}}",
+       "unblocked-range": "Shown when successfully lifting a rangeblock, so do not link to contributions. Parameters:\n* $1 - the range that was unblocked\nSee also:\n* {{msg-mw|Unblocked}}\n* {{msg-mw|Unblocked-id}}\n*{{msg-mw|Unblocked-ip}}",
        "unblocked-id": "Used in [[Special:Unblock]]. Parameters:\n* $1 - autoblock ID\nSee also:\n* {{msg-mw|Unblocked}}\n* {{msg-mw|Unblocked-range}}",
+       "unblocked-ip": "{{doc-important|Do not translate the title \"Special:Contributions\".}}\nParameters:\n* $1 - the IP address that was unblocked\nSee also:\n* {{msg-mw|Unblocked-range}}\n* {{msg-mw|Unblocked-id}}\n*{{msg-mw|Unblocked}}",
        "blocklist": "{{doc-special|BlockList}}",
        "ipblocklist": "Title of [[Special:Ipblocklist]].",
        "ipblocklist-legend": "Used as legend of the form in [[Special:BlockList]].\n\nSee also:\n* {{msg-mw|Ipblocklist-legend}}\n* {{msg-mw|Ipblocklist-submit}}",
        "blocklist-addressblocks": "Used as the label for the multi-select checkbox in the form on [[Special:BlockList]].\n{{Related|Blocklist-blocks}}",
        "blocklist-rangeblocks": "Used as the label for the multi-select checkbox in the form on [[Special:BlockList]].\n\nFor an explanation of \"range blocks\", see [[mw:Help:Range_blocks]]\n{{Related|Blocklist-blocks}}",
        "blocklist-timestamp": "This is a column header for dates and times in the table on the page [[Special:BlockList]].\n{{Identical|Timestamp}}",
-       "blocklist-target": "The table header for the column containing the block targets, that is user names or IP-addresses linked to their respective user pages, in the table on the page [[Special:BlockList]].",
+       "blocklist-target": "The table header for the column containing the block targets, that is user names or IP-addresses linked to their respective user pages, in the table on the page [[Special:BlockList]].\n{{Identical|Target}}",
        "blocklist-expiry": "This is a column header in the table on the page [[Special:BlockList]].\n{{Identical|Expire}}",
        "blocklist-by": "This is a column header in the table on the page [[Special:BlockList]].",
        "blocklist-params": "This is a column header in the table on the page [[Special:BlockList]].",
        "lockfilenotwritable": "'No longer needed' on wikipedia.",
        "databasenotlocked": "Used as error message in [[Special:UnlockDB]].\nThe title of this error message is {{msg-mw|Lockdb}}.\n\nSee also:\n* {{msg-mw|Lockdb|title}}\n* {{msg-mw|Databasenotlocked|message}}",
        "lockedbyandtime": "Used as part of the message when a database is locked through [[Special:LockDB]]. Parameters:\n* $1 is the user that locked the database.\n* $2 is the date on which the lock was made\n* $3 is the time at which the lock was made",
-       "move-page": "Used as page title of [[Special:MovePage]] to move pages.\n\nSee example: [[Special:MovePage/Portal:En]].\n\nParameters:\n* $1 - the name of the page to be moved (without link)",
+       "move-page": "Used as page title of [[Special:MovePage]] to move pages.\n\nSee example: [[Special:MovePage/Portal:En]].\n\nParameters:\n* $1 - the name of the page to be moved (without link)\n{{Identical|Move}}",
        "movepage-summary": "{{doc-specialpagesummary|movepage}}",
        "move-page-legend": "Legend of the fieldset around the input form of [[Special:MovePage/testpage]].\n\nSee also:\n* {{msg-mw|movearticle|label for old title}}\n* {{msg-mw|newtitle|label for new title}}\n* {{msg-mw|movereason|label for textarea}}\n* {{msg-mw|movetalk|label for checkbox}}\n* {{msg-mw|move-leave-redirect|label for checkbox}}\n* {{msg-mw|fix-double-redirects|label for checkbox}}\n* {{msg-mw|move-subpages|label for checkbox}}\n* {{msg-mw|move-talk-subpages|label for checkbox}}\n* {{msg-mw|move-watch|label for checkbox}}\n{{Identical|Move page}}",
        "movepagetext": "Introduction shown when moving a page ([[Special:MovePage]]).\n\nSpecial pages mentioned: {{msg-mw|Doubleredirects}}, {{msg-mw|Brokenredirects}}\n\nSee also:\n* {{msg-mw|Movepagetext-noredirectfixer}}",
        "import-summary": "{{doc-specialpagesummary|import}}",
        "importinterwiki": "Used as legend for the Import form in [[Special:Import]].",
        "import-interwiki-text": "Used as summary for the Import form in [[Special:Import]].",
-       "import-interwiki-source": "Used as label for input box in [[Special:Import]].",
+       "import-interwiki-sourcewiki": "Used as label for dropdown box in [[Special:Import]].\n\nSee also:\n* {{msg-mw|Import-interwiki-sourcepage}}",
+       "import-interwiki-sourcepage": "Used as label for input box in [[Special:Import]].\n\nSee also:\n* {{msg-mw|Import-interwiki-sourcewiki}}",
        "import-interwiki-history": "This is an option on [[Special:Import]]. Usually, when unchecked, only the first version of a page is imported. When you check the option, all versions are imported. This is important often to check for licensing reasons.\n\nSee also:\n* {{msg-mw|Import-interwiki-templates}}\n* {{msg-mw|Import-interwiki-namespace}}\n* {{msg-mw|Import-comment}}\n* {{msg-mw|Import-interwiki-rootpage}}\n* {{msg-mw|Import-interwiki-submit}}",
        "import-interwiki-templates": "Used as label for the checkbox in [[Special:Import]].\n\nSee also:\n* {{msg-mw|Import-interwiki-history}}\n* {{msg-mw|Import-interwiki-namespace}}\n* {{msg-mw|Import-comment}}\n* {{msg-mw|Import-interwiki-rootpage}}\n* {{msg-mw|Import-interwiki-submit}}",
        "import-interwiki-submit": "Used as Submit button text in [[Special:Import]].\n\nSee also:\n* {{msg-mw|Import-interwiki-history}}\n* {{msg-mw|Import-interwiki-templates}}\n* {{msg-mw|Import-interwiki-namespace}}\n* {{msg-mw|Import-comment}}\n* {{msg-mw|Import-interwiki-rootpage}}\n{{Identical|Import}}",
        "importlogpage": "{{doc-logpage}}",
        "importlogpagetext": "This text appears at the top of the [{{canonicalurl:Special:Log|type=import}} import log] special page.",
        "import-logentry-upload": "This is the text of an entry in the Import log (and Recent Changes), after hour (and date, only in the Import log) and sysop name:\n* $1 is the name of the imported file",
-       "import-logentry-upload-detail": "Used as success message. Parameters:\n* $1 - number of succeeded revisions\nSee also:\n* {{msg-mw|Import-logentry-interwiki-detail}}",
+       "import-logentry-upload-detail": "Used as success message and log entry. Parameters:\n* $1 - number of succeeded revisions\nSee also:\n* {{msg-mw|Import-logentry-interwiki-detail}}",
        "import-logentry-interwiki": "Used as action listed in the log. Parameters:\n* $1 - page title",
-       "import-logentry-interwiki-detail": "Used as success message. Parameters:\n* $1 - number of succeeded revisions\n* $2 - interwiki name\nSee also:\n* {{msg-mw|Import-logentry-upload-detail}}",
+       "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": "Title of the special page when running a test suite. Parameters:\n* $1 is the name of the framework, for example QUnit.",
        "pageinfo-protect-cascading-yes": "Yes, protections are cascading from here\n*{{msg-mw|Pageinfo-protect-cascading}}\n*{{msg-mw|Pageinfo-protect-cascading-yes}}\n{{Identical|Yes}}",
        "pageinfo-protect-cascading-from": "Key for a list of pages where protections are cascading from",
        "pageinfo-category-info": "Showed on the page displaying information about the current page (add \"?action=info\" to the URL)",
-       "pageinfo-category-pages": "See also:\n* {{msg-mw|Pageinfo-category-subcats}}\n* {{msg-mw|Pageinfo-category-files}}",
+       "pageinfo-category-pages": "See also:\n* {{msg-mw|Pageinfo-category-subcats}}\n* {{msg-mw|Pageinfo-category-files}}\n{{Identical|Number of pages}}",
        "pageinfo-category-subcats": "See also:\n* {{msg-mw|Pageinfo-category-pages}}\n* {{msg-mw|Pageinfo-category-files}}",
        "pageinfo-category-files": "See also:\n* {{msg-mw|Pageinfo-category-pages}}\n* {{msg-mw|Pageinfo-category-subcats}}",
        "markaspatrolleddiff": "{{doc-actionlink}}\nSee also:\n* {{msg-mw|Markaspatrolledtext}}\n{{Identical|Mark as patrolled}}",
        "autosumm-replace": "The auto summary when a user removes a lot of characters in the page.\n\nParameters:\n* $1 - truncated text",
        "autoredircomment": "The auto summary when making a redirect. Parameters:\n* $1 - the page where it redirects to\n* $2 - (Optional) the first X number of characters of the redirect ($2 is usually only used when end users customize the message)",
        "autosumm-new": "The auto summary when creating a new page. $1 are the first X number of characters of the new page.",
+       "autosumm-newblank": "The automatic edit summary when creating a blank page. This is not the same as blanking a page.",
        "autoblock_whitelist": "{{notranslate}}",
        "size-bytes": "{{optional}}\nSize (of a page, typically) in bytes.",
        "size-kilobytes": "{{optional}}\nSize (of a page, typically) in kibibytes (1 kibibyte = 1024 bytes).",
        "timezone-utc": "{{optional}}",
        "unknown_extension_tag": "This is an error shown when you use an unknown extension tag name.\n\nThis feature allows tags like <code><nowiki><pre></nowiki></code> to be called with a parser like <code><nowiki>{{#tag:pre}}</nowiki></code>.\n\nParameters:\n* $1 - the unknown extension tag name",
        "duplicate-defaultsort": "See definition of [[w:Sorting|sort key]] on Wikipedia. Parameters:\n* $1 - old default sort key\n* $2 - new default sort key",
+       "duplicate-displaytitle": "Warning shown when a page has its display title set multiple times. Parameters:\n* $1 - old display title\n* $2 - new display title",
        "version": "{{doc-special|Version}}\n{{Identical|Version}}",
        "version-summary": "{{doc-specialpagesummary|version}}",
        "version-extensions": "Header on [[Special:Version]].",
        "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-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]]}}",
+       "logentry-upload-overwrite": "{{Logentry|[[Special:Log/upload]]}}",
+       "logentry-upload-revert": "{{Logentry|[[Special:Log/upload]]}}",
        "rightsnone": "Default rights for registered users.\n\n{{Identical|None}}",
        "revdelete-logentry": "{{RevisionDelete}}\nThis is the message for the log entry in [[Special:Log/delete]] when changing visibility restrictions for page revisions.\n\nFollowed by the message {{msg-mw|revdelete-log-message}} in brackets.\n\nPreceded by the name of the user doing this task.\n\nParameters:\n* $1 - the page name\nSee also:\n* {{msg-mw|Logdelete-logentry}}",
        "logdelete-logentry": "{{RevisionDelete}}\nThis is the message for the log entry in [[Special:Log/delete]] when changing visibility restrictions for log events.\n\nFollowed by the message {{msg-mw|logdelete-log-message}} in brackets.\n\nPreceded by the name of the user who did this task.\n\nParameters:\n* $1 - the log name in brackets\nSee also:\n* {{msg-mw|Revdelete-logentry}}",
        "action-pagelang": "{{Doc-action|pagelang}}",
        "log-name-pagelang": "Display entry for log name for changes in page language in Special:Log.",
        "log-description-pagelang": "Display description for log name for changes in page language in Special:Log.",
-       "logentry-pagelang-pagelang": "{{Logentry}}\nAdditional parameters:\n* $4 - old language code, or \"[def]\" (hard-coded)\n* $5 - new language code, or \"[def]\" (hard-coded)"
+       "logentry-pagelang-pagelang": "{{Logentry}}\nAdditional parameters:\n* $4 - old language code, or \"[def]\" (hard-coded)\n* $5 - new language code, or \"[def]\" (hard-coded)",
+       "default-skin-not-found": "Message shown when the default skin for this MediaWiki installation can not be found.\n\nParameters:\n* $1: skin identifier for the default skin\n* $2: list of installed skins, composed using {{msg-mw|default-skin-not-found-row-enabled}} and {{msg-mw|default-skin-not-found-row-disabled}}\n* $3: code snippet to use to enable installed skins",
+       "default-skin-not-found-no-skins": "Message shown when the default skin for this MediaWiki installation can not be found and the installation has no skins at all.\n\nParameters:\n* $1: name of the default skin",
+       "default-skin-not-found-row-enabled": "One row of the list of installed skins shown as a part of the following message (for an enabled skin):\n* {{msg-mw|default-skin-not-found}}\n----\nParameters:\n* $1 - skin identifier\n* $2 - human-readable skin name\nSee also:\n* {{msg-mw|Default-skin-not-found-row-disabled}}",
+       "default-skin-not-found-row-disabled": "One row of the list of installed skins shown as a part of the following message (for a disabled skin):\n* {{msg-mw|default-skin-not-found}}\n----\nParameters:\n* $1 - skin identifier\n* $2 - human-readable skin name\nSee also:\n* {{msg-mw|Default-skin-not-found-row-enabled}}"
 }
index b82a39d..b55a995 100644 (file)
        "talkpagelinktext": "rimanakuy",
        "specialpage": "Sapaq p'anqa",
        "personaltools": "Kikin ruraqpa llamk'anankuna",
-       "postcomment": "Musuq raki",
        "articlepage": "Qillqata qhaway",
        "talk": "Rimachina",
        "views": "Rikunakuna",
        "externaldberror": "Hawa yaykuna pantasqam karqan, ichataq manam saqillasunkichu hawa rakiqunaykita musuqchayta.",
        "login": "Yaykuy",
        "nav-login-createaccount": "Yaykuy / rakiqunata kamariy",
-       "loginprompt": "{{SITENAME}}man yaykunaykipaqqa wamp'unaykipi <i>cookies</i> nisqakunaman ari ninaykim tiyan.",
        "userlogin": "Yaykuy / rakiqunata kamariy",
        "userloginnocreate": "Yaykuy",
        "logout": "Lluqsiy",
        "searchprofile-advanced-tooltip": "Akllasqa suti k'itikunapi maskay",
        "search-result-size": "$1 ({{PLURAL:$2|1 rima|$2 rimakuna}})",
        "search-result-category-size": "{{PLURAL:$1|1 wankurisqa|$1 wankurisqa}} ({{PLURAL:$2|1 urin katiguriya|$2 urin katiguriya}}, {{PLURAL:$3|1 willañiqi|$3 willañiqi}})",
-       "search-result-score": "Chaniyuq kaynin: $1%",
        "search-redirect": "(pusapuna $1)",
        "search-section": "(raki $1)",
        "search-file-match": "(willañiqip samiqninta taripan)",
        "largefileserver": "Kay willañiqiqa sirwiqpi allinkachisqakama saqillasqa chhikanmanta aswan hatunmi.",
        "emptyfile": "Churkusqayki willañiqiqa ch'usaqmi rikch'akun. Pantasqa sutinchá. Ama hina kaspa, llanchiy, churkuyman munasqayki willañiqichu.",
        "windows-nonascii-filename": "Kay wikiqa sapaq sananchayuq willañiqi sutikunata manam q'iminchu.",
-       "fileexists": "Kachkanñam kay sutiyuq willañiqi.\nAma hina kaspa, <strong>[[:$1]]</strong> nisqata llanchiy, huknachanaykimanta mana allin yachaspaykiqa.\n[[$1|thumb]]",
+       "fileexists": "Kachkanñam kay sutiyuq willañiqi.\nAma hina kaspa, <strong>[[:$1]]</strong> nisqata llanchiy, {{GENDER:|}}huknachanaykimanta mana allin yachaspaykiqa.\n[[$1|thumb]]",
        "filepageexists": "Kay willañiqipaq sut'ichana p'anqaqa kamarisqañam <strong>[[:$1]]</strong> nisqapi, ichataq kay sutiyuq willañiqi manaraqmi kanchu. Willanayki pisichayqa manam rikch'akunqachu sut'ichana p'anqapi. Rikch'akunanpaqqa, kikiykip makiykiwanmi llamk'apunayki tiyan.\n[[$1|thumb]]",
        "fileexists-extension": "Kay willañiqip sutinman yaqa kaqlla sutiyuq willañiqim kachkanña: [[$2|thumb]]\n* Churkunayasqayki willañiqip sutin: <strong>[[:$1]]</strong>\n* Kachkaqña willañiqip sutin: <strong>[[:$2]]</strong>\nAma hina kaspa, huk sutita akllay.",
        "fileexists-thumbnail-yes": "Willañiqiqa ancha uchuylla rikchamanmi rikch'akun ''(thumbnail)''. [[$1|thumb]]\nAma hina kaspa, <strong>[[:$1]]</strong> nisqa willañiqita llanchiy.\nLlanchisqa willañiqi qallariy chhikan kikin rikchaman kaqlla kaptinqa, huk rikchachata churkunaykiqa manam tiyanchu.",
        "uploadwarning": "Willañiqi churkuymanta paqtataq niy",
        "uploadwarning-text": "Ama hina kaspa, kay qatiqpi kaq willañiqimanta willaykunata hukchaspa musuqmanta ruraykachay.",
        "savefile": "Willañiqita waqaychay",
-       "uploadedimage": "«[[$1]]» churkusqa.",
-       "overwroteimage": "\"[[$1]]\" musuqmanta churkusqa",
        "uploaddisabled": "Willañiqi churkuyman ama nisqa",
        "copyuploaddisabled": "URL-pa churkunanqa manam atinchu.",
        "uploaddisabledtext": "Willañiqi churkuyqa manam saqillasqachu.",
        "watchlist-details": "Watiqana sutisuyuykipiqa {{PLURAL:$1|$1 p'anqam|$1 p'anqakunam}}, rimanakuna p'anqakunata mana yupaspa.",
        "wlheader-enotif": "E-chaskimanta musyachinaman arí nisqañam.",
        "wlheader-showupdated": "Qayna watukamusqaykimantapacha hukchasqa p'anqakunataqa '''yanasapa''' nisqapim rikunki.",
+       "wlnote": "Kay qatiqpiqa {{PLURAL:$1|qhipaq hukchasqam|'''$1''' qhipaq hukchasqakunam}} qhipaq {{PLURAL:$2|urapim|'''$2''' urakunapim}}, musuqchasqa $3, $4.",
        "wlshowlast": "$1 ura, $2 p'unchaw $3-mantapacha hukchasqakunata rikuchiy",
        "watchlist-options": "Watiqana sutisuyupaq allinkachinakuna",
        "watching": "Watiqasqakunaman yapaspa...",
        "duplicate-defaultsort": "Paqtataq: Kikinmanta allinchana llawi «$2» ñawpaq kikinmanta allinchana llawitam «$1» huknachan.",
        "version": "Musuqchasqa",
        "version-extensions": "Tiyachisqa mast'arinakuna",
+       "version-skins": "Churasqa qarakuna",
        "version-specialpages": "Sapaq p'anqakuna",
        "version-parserhooks": "T'ikrana ch'iwinakuna",
        "version-variables": "Hukchakuqkuna",
        "version-antispam": "Spam hark'ay",
-       "version-skins": "Qarakuna",
        "version-other": "Wakin",
        "version-mediahandlers": "Midya llamk'apuq",
        "version-hooks": "Ch'iwinakuna",
index 337f61e..6c78c09 100644 (file)
        "talkpagelinktext": "Rimanakuy",
        "specialpage": "Mana shukkunashina panka",
        "personaltools": "Kikinpak llankanaman yanapanakuna",
-       "postcomment": "Mushuk raki",
        "articlepage": "Pankata rikuna",
        "talk": "Rimanakuna",
        "views": "Rikunakuna",
        "remembermypassword": "Kay Internet-wampunapi {{PLURAL:$1|shuk punchata|$1 punchakunata}} ñuka rurak shutiwan yaykushkami katichiwapay.",
        "login": "Yaykuna",
        "nav-login-createaccount": "Yaykuna",
-       "loginprompt": "{{SITENAME}}man yaykunkapak <i>cookies</i>-man ari ninami kapanki.",
        "userlogin": "Yaykuna",
        "logout": "Llukshina",
        "userlogout": "Llukshina",
        "upload": "Archivuta apamuna",
        "uploadlogpage": "Apamushka archiwukunapa kamu",
        "filedesc": "Uchilla rimay",
-       "uploadedimage": "«[[$1]]» apakushka.",
        "license": "Licencia:",
        "license-header": "Licencia",
        "file-anchor-link": "Archiwu",
index 7b001f2..3e6c421 100644 (file)
@@ -2,7 +2,8 @@
        "@metadata": {
                "authors": [
                        "Reedy",
-                       "Sentruper"
+                       "Sentruper",
+                       "아라"
                ]
        },
        "tog-underline": "Link cun la sotliniadura",
@@ -15,7 +16,6 @@
        "tog-showtoolbar": "Fam avdé la bara d'j strumént (u j vó JavaScript)",
        "tog-editondblclick": "Mudèfiga al pàgin scjazènd do volt (u j vò JavaScript)",
        "tog-editsectiononrightclick": "S't'vù l'abilitaziòn ad cambié al seziòn <br />scjazénd e tast a dèstra sora e titul (u j vò JavaScript)",
-       "tog-rememberpassword": "Arcurdam la parola d'ordin, par piasé (fèn a un masum $1 {{PLURAL:$1|dè|dè}})",
        "tog-watchcreations": "Mett insèn al pàgin ch't'e' fat adès, intla lèsta da tní sot'occ",
        "tog-watchdefault": "Mett insèn al pàgin ch'a j ò lavurè sora int la lèsta dal pàgin da tnì sot'òcc",
        "tog-watchmoves": "Mett insèn al pàgin ch'a j ò spustè int la lèsta dal pàgin da tnì sot'òcc",
        "qbmyoptions": "Al mi pàgin",
        "faq": "Question frequenti",
        "faqpage": "Prugèt:Question frequenti",
-       "vector-action-addsection": "Zonta una cjacarèda",
-       "vector-action-delete": "Scanzèla",
-       "vector-action-move": "Chèmbia nòm",
-       "vector-action-protect": "Metti-j una pruteziò",
-       "vector-action-undelete": "Armett a post",
-       "vector-action-unprotect": "Sbloca",
        "errorpagetitle": "Oci! T'ê fat una capèla",
        "returnto": "Torna indrì a $1.",
        "tagline": "Da {{SITENAME}}",
        "search-interwiki-more": "(ad piò)",
        "powersearch-legend": "Scandaja a fònd",
        "powersearch-ns": "Zerca int'j spàzi d'nom:",
-       "powersearch-redir": "Fà una lèsta d'al ri-direziòn",
        "preferences": "I mì gost",
        "mypreferences": "I mi gòst",
        "group-sysop": "Aministradór",
        "recentchanges": "I ultum cambiamént",
        "recentchanges-legend": "Upziòn d'j ultum cambiamént",
        "recentchanges-feed-description": "Ste canël e' fa avdè i cambiamént piò rezent aj artècul d'sta wiki.",
-       "rclistfrom": "Fam avdè i cambiamént növ a cminzipiè da $1",
+       "rclistfrom": "Fam avdè i cambiamént növ a cminzipiè da $3 $2",
        "rcshowhideminor": "$1 al mudèfghi znini",
        "rcshowhidebots": "$1 i bot",
        "rcshowhideliu": "$1 i patàca registrè",
        "recentchangeslinked-to": "Fam avdé sol i cambiamént al pàgin ch'j va impèt a quèla ch'la m'interèsa a me.",
        "upload": "Carga so un file",
        "uploadlogpage": "Regèstar d'j file carghé",
-       "uploadedimage": "l'à carghé \"[[$1]]\"",
        "filehist": "Stória d'e' file",
        "filehist-help": "Fà clic sora un gròp dèda/ora par avdé cun cl'éra e' file in ch'ë mumént.",
        "filehist-current": "d'adès",
        "booksources-go": "Và pu",
        "log": "Regèstar",
        "allpages": "Tot al pàgin",
-       "alphaindexline": "Da $1 a $2",
        "prevpage": "Pàgina prèma d'questa ($1)",
        "allpagesfrom": "Fam avdè al pàgin cminzipiènd da:",
        "allpagesto": "Fam avdé al pàgin infèn a:",
index 26c258a..98f2951 100644 (file)
@@ -7,7 +7,8 @@
                        "Jose77",
                        "Mmistmurt",
                        "MoubarikBelkasim",
-                       "Urhixidur"
+                       "Urhixidur",
+                       "아라"
                ]
        },
        "sunday": "Asamas (Eřḥedd)",
        "navigation": "Tagriwa",
        "qbfind": "Af",
        "qbedit": "Ẓṛeg",
-       "vector-action-move": "Smuṭṭi",
-       "vector-view-create": "Seɣnu",
-       "vector-view-edit": "Ẓṛeg",
-       "vector-view-history": "Ẓeṛ amezruy",
-       "vector-view-view": "Ɣeṛ",
        "actions": "Timegga",
        "errorpagetitle": "Anezri",
        "returnto": "Dwl ghar $1.",
        "remembermypassword": "ejj (login) inu deg uselkim a (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "login": "Adf",
        "nav-login-createaccount": "Adef / egg amiḍan",
-       "loginprompt": "itxessa ad-teṭfed (''cookies'') bac ad tadfed ɣar {{SITENAME}}.",
        "userlogin": "Adf / egg amiḍan",
        "logout": "Ufugh",
        "userlogout": "Ufugh",
        "viewprevnext": "Ẓeṛ ($1 {{int:pipe-separator}} $2) ($3)",
        "searchprofile-everything": "Marra",
        "searchprofile-articles-tooltip": "Rzu di $1",
-       "searchprofile-project-tooltip": "Rzu di $1",
        "search-result-size": "$1 ({{PLURAL:$2|1 tawalt|$2 tiwalin}})",
        "search-redirect": "(awi $1)",
        "search-suggest": "Ttugha txsd a tinid: $1",
        "recentchanges": "Tiẓṛigin tineggura",
        "recentchanges-feed-description": "Bbar tiẓṛigin timayutin n wiki deg usudem(feed) a .",
        "rcnotefrom": "ɣar wadday d tiẓṛigin zi '''$2''' (ar '''$1''' ).",
-       "rclistfrom": "Ẓar tiẓṛigin timaynutin ig ibeddan zi $1",
+       "rclistfrom": "Ẓar tiẓṛigin timaynutin ig ibeddan zi $3 $2",
        "rcshowhideminor": "$1 tiẓṛigin d-timeẓyanin",
        "rcshowhidebots": "$1 iroboten(robots)",
        "rcshowhideliu": "$1 users ig yudeffen",
        "uploadlogpage": "Zdem-d aɣmis",
        "filedesc": "Asgbr",
        "fileuploadsummary": "Asgbr:",
-       "uploadedimage": "itwazdem-d \"[[$1]]\"",
        "watchthisupload": "Xm tasbtirt a",
        "listfiles": "Tabdart n ifayluten",
        "file-anchor-link": "Afaylu",
        "log": "Aɣmis",
        "all-logs-page": "Maṛṛa iɣmisen",
        "allpages": "Marra tasniwin",
-       "alphaindexline": "$1 ɣa $2",
        "nextpage": "Tasna zzat ($1)",
        "prevpage": "Tasna zzat ($1)",
        "allpagesfrom": "Scan-d Tasniwin beddant zi:",
index e9b0e3d..4217e27 100644 (file)
        "category-empty": "''Questa categoria cuntegna actualmain nagins artitgels e naginas datotecas.''",
        "hidden-categories": "{{PLURAL:$1|Categoria zuppentada|Categorias zuppentadas}}",
        "hidden-category-category": "Categorias zuppentadas",
-       "category-subcat-count": "{{PLURAL:$2|Questa categoria cuntegna be suandanta sutcategoria.|Questa categoria cuntegna {{PLURAL:$1|la suandanta sutcategoria|las $1 suandantas sutcategorias}} da totalmain $2 sutcategoria.}}",
+       "category-subcat-count": "{{PLURAL:$2|Questa categoria cuntegna be suandanta sutcategoria.|Questa categoria cuntegna {{PLURAL:$1|la suandanta sutcategoria|las $1 suandantas sutcategorias}} da totalmain $2 sutcategorias.}}",
        "category-subcat-count-limited": "Questa categoria cuntegna {{PLURAL:$1|suandanta subcategoria|suandantas $1 subcategorias}}:",
        "category-article-count": "{{PLURAL:$2|Questa categoria cuntegna be la suandanta pagina.|{{PLURAL:$1|La suandanta pagina è|Las $1 suandantas paginas èn}} en questa categoria che cuntegna totalmain $2 paginas.}}",
        "category-article-count-limited": "{{PLURAL:$1|La suandanta pagina è|Las suandantas $1 paginas èn}} actualmain en la categoria.",
        "talkpagelinktext": "Discussiun",
        "specialpage": "Pagina speziala",
        "personaltools": "Utensils persunals",
-       "postcomment": "Nova secziun",
        "articlepage": "Mussar la pagina da cuntegn",
        "talk": "Discussiun",
        "views": "Questa pagina",
        "externaldberror": "U ch'i è capità ina errur cun l'autentificaziun externa u che ti na dastgas betg actualisar tes conto extern.",
        "login": "T'annunziar",
        "nav-login-createaccount": "T'annunziar / crear in conto",
-       "loginprompt": "Ti stos avair '''activà ils cookies''' per pudair t'annunziar tar {{SITENAME}}.",
        "userlogin": "T'annunziar / crear in conto",
        "userloginnocreate": "T'annunziar",
        "logout": "Sortir",
        "gotaccountlink": "T'annunziar",
        "userlogin-resetlink": "Emblidà tias datas per s'annunziar?",
        "userlogin-resetpassword-link": "Has emblidà tes pled-clav?",
-       "userlogin-loggedin": "Ti es gia t'annunzià sco {{GENDER:$1|$1}}.\nDovra il suandant formular per t'annunziar cun in auter conto.",
-       "userlogin-createanother": "Crear in auter conto",
        "createacct-emailrequired": "Adressa dad e-mail",
        "createacct-emailoptional": "Adressa dad e-mail (opziunal)",
        "createacct-email-ph": "Endatescha ti'adressa dad e-mail",
        "searchprofile-advanced-tooltip": "Tschertgar en ulteriurs tips da pagina",
        "search-result-size": "$1 ({{PLURAL:$2|in pled|$2 pleds}})",
        "search-result-category-size": "{{PLURAL:$1|1 commember|$1 commembers}} ({{PLURAL:$2|1 sutcategoria|$2 sutcategorias}}, {{PLURAL:$3|1 datoteca|$3 datotecas}})",
-       "search-result-score": "Relevanza: $1 %",
        "search-redirect": "(renvià da $1)",
        "search-section": "(chapitel $1)",
        "search-suggest": "Has ti manegià: $1",
        "uploadwarning": "Attenziun",
        "uploadwarning-text": "Mida per plaschair la descripziun da la datoteca sutvart ed emprova danovamain.",
        "savefile": "Memorisar la datoteca",
-       "uploadedimage": "\"[[$1]]\" è vengì chargià si",
-       "overwroteimage": "ha chargià si ina nova versiun da \"[[$1]]\"",
        "uploaddisabled": "Chargiar si è deactivà.",
        "copyuploaddisabled": "Il transferir per URL è deactivà.",
        "uploaddisabledtext": "La funcziun da chargiar si datotecas è deactivada.",
        "watchlist-details": "Ti has {{PLURAL:$1|$1 pagina|$1 paginas}} sin tia glista d'observaziun, paginas da discussiun exclusas.",
        "wlheader-enotif": "Il servetsch d'infurmaziun per e-mail è activà.",
        "wlheader-showupdated": "Paginas ch'èn vegnidas modifitgadas suenter che ti has vis els la davosa giada èn mussads '''grass'''",
+       "wlnote": "Sutvart {{PLURAL:$1|è l'ultima midada|èn las ultimas '''$1''' midadas}} entaifer {{PLURAL:$2|l'ultima ura|las ultimas '''$2''' uras}}. Actualisà ils $3 las $4.",
        "wlshowlast": "Mussar: las ultimas $1 uras, ils ultims $2 dis u $3.",
        "watchlist-options": "Opziuns per la glista d'observaziun",
        "watching": "observ...",
        "import": "Impurtar paginas",
        "importinterwiki": "Import transwiki",
        "import-interwiki-text": "Tscherna in wiki ed in titel da pagina per importar.\nLas datas da las versiuns ed ils nums dals contribuents vegnan mantegnids.\nTut ils imports transwiki vegnan registrads en il [[Special:Log/import|protocol d'imports]].",
-       "import-interwiki-source": "Wiki/pagina da funtauna:",
        "import-interwiki-history": "Copiar l'entira cronologia da questa pagina",
        "import-interwiki-templates": "Includer tut ils models",
        "import-interwiki-submit": "Importar",
        "duplicate-defaultsort": "'''Attenziun:''' La clav da zavrar da standard \"$2\" remplazza la clav da zavrar da standard veglia \"$1\".",
        "version": "Versiun",
        "version-extensions": "Extensiuns installadas",
+       "version-skins": "Skins",
        "version-specialpages": "Paginas spezialas",
        "version-parserhooks": "Hooks dal parser",
        "version-variables": "Variablas",
        "version-antispam": "Prevenziun da spam",
-       "version-skins": "Skins",
        "version-other": "Auter",
        "version-mediahandlers": "Manipulaturs da meds",
        "version-hooks": "Hooks",
index 4271f79..3b1be72 100644 (file)
@@ -40,6 +40,7 @@
        "tog-watchdefault": "Adaugă paginile și fișierele pe care le modific la lista mea de urmărire",
        "tog-watchmoves": "Adaugă paginile și fișierele pe care le redenumesc la lista mea de urmărire",
        "tog-watchdeletion": "Adaugă paginile și fișierele pe care le șterg la lista mea de urmărire",
+       "tog-watchrollback": "Adaugă în lista mea de pagini urmărite acele pagini asupra cărora am efectuat o revenire",
        "tog-minordefault": "Marchează din oficiu toate modificările ca fiind minore",
        "tog-previewontop": "Arată previzualizarea deasupra căsuței de modificare",
        "tog-previewonfirst": "Arată previzualizarea la prima modificare",
        "category_header": "Pagini din categoria „$1”",
        "subcategories": "Subcategorii",
        "category-media-header": "Fișiere media din categoria „$1”",
-       "category-empty": "''Această categorie nu conține în acest moment niciun articol sau fișier media.''",
+       "category-empty": "''Această categorie nu conține momentan nici o pagină sau fișier media.''",
        "hidden-categories": "{{PLURAL:$1|Categorie ascunsă|Categorii ascunse}}",
        "hidden-category-category": "Categorii ascunse",
        "category-subcat-count": "{{PLURAL:$2|Această categorie conține doar următoarea subcategorie.|Această categorie conține {{PLURAL:$1|următoarea subcategorie|următoarele $1 subcategorii|următoarele $1 de subcategorii}}, dintr-un total de $2.}}",
        "talkpagelinktext": "Discuție",
        "specialpage": "Pagină specială",
        "personaltools": "Unelte personale",
-       "postcomment": "Secțiune nouă",
        "articlepage": "Vedeți articolul",
        "talk": "Discuție",
        "views": "Vizualizări",
        "otherlanguages": "În alte limbi",
        "redirectedfrom": "(Redirecționat de la $1)",
        "redirectpagesub": "Pagină de redirecționare",
+       "redirectto": "Redirecționare către:",
        "lastmodifiedat": "Ultima modificare efectuată la $2, $1.",
        "viewcount": "Pagina a fost vizitată {{PLURAL:$1|o dată|de $1 ori|de $1 de ori}}.",
        "protectedpage": "Pagină protejată",
        "hidetoc": "ascunde",
        "collapsible-collapse": "Restrânge",
        "collapsible-expand": "Extinde",
+       "confirmable-confirm": "Sunteți sigur{{GENDER:$1||ă}}?",
+       "confirmable-yes": "Da",
+       "confirmable-no": "Nu",
        "thisisdeleted": "Vizualizare sau recuperare $1?",
        "viewdeleted": "Vizualizați $1?",
        "restorelink": "{{PLURAL:$1|o modificare ștearsă|$1 modificări șterse|$1 de modificări șterse}}",
        "invalidtitle-knownnamespace": "Titlu invalid cu spațiul de nume „$2” și textul „$3”",
        "invalidtitle-unknownnamespace": "Titlu invalid cu numărul spațiului de nume $1 necunoscut și textul „$2”",
        "exception-nologin": "Neautentificat{{GENDER:||ă}}",
-       "exception-nologin-text": "Vă rugăm să vă [[Special:Userlogin|autentificați]] pentru a accesa această pagină sau acțiune.",
+       "exception-nologin-text": "Vă rugăm să vă autentificați pentru a accesa această pagină sau acțiune.",
        "exception-nologin-text-manual": "Vă rugăm să vă $1 pentru a accesa această pagină sau acțiune.",
        "virus-badscanner": "Configurație greșită: scaner de virus necunoscut: ''$1''",
        "virus-scanfailed": "scanare eșuată (cod $1)",
        "externaldberror": "A fost fie o eroare de bază de date pentru o autentificare extenă sau nu aveți permisiunea să actualizați contul extern.",
        "login": "Autentificare",
        "nav-login-createaccount": "Creare cont / Autentificare",
-       "loginprompt": "Trebuie să ai modulele cookie activate pentru a te autentifica la {{SITENAME}}.",
        "userlogin": "Creare cont / Autentificare",
        "userloginnocreate": "Autentificare",
        "logout": "Închidere sesiune",
        "userlogin-resetlink": "Ați uitat datele de autentificare?",
        "userlogin-resetpassword-link": "V-ați uitat parola?",
        "userlogin-helplink2": "Ajutor la autentificare",
-       "userlogin-loggedin": "Sunteți deja {{GENDER:$1|autentificat|autentificată}} ca {{GENDER:$1|$1}}.\nUtilizați formularul de mai jos pentru a vă autentifica cu alt nume de utilizator.",
-       "userlogin-createanother": "Creează un alt cont",
        "createacct-emailrequired": "Adresă de e-mail",
        "createacct-emailoptional": "Adresă de e-mail (opțională)",
        "createacct-email-ph": "Introduceți adresa dumnevoastră de e-mail",
        "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-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.",
        "createacct-another-realname-tip": "Numele real este opțional.\nDacă decideți furnizarea sa, acesta va fi folosit pentru a atribui utilizatorului munca sa.",
        "preview": "Previzualizare",
        "showpreview": "Previzualizare",
        "showdiff": "Afișare diferențe",
-       "anoneditwarning": "'''Atenție:''' Nu v-ați autentificat. Adresa IP vă va fi înregistrată în istoricul acestei pagini.",
+       "blankarticle": "<strong>Atenție:</strong> Pagina pe care o creați este goală.\nDacă faceți din nou clic pe „{{int:savearticle}}”, pagina va fi creată fără niciun conținut.",
+       "anoneditwarning": "<strong>Atenție:</strong> Nu v-ați autentificat. Adresa dumneavoastră IP va fi vizibilă în mod public dacă efectuați modificări. Dacă vă <strong>[$1 autentificați]</strong> sau vă <strong>[$2 creați un cont]</strong>, modificările dumneavoastră vor fi asociate numelui de utilizator, pe lângă alte beneficii.",
        "anonpreviewwarning": "''Nu v-ați autentificat. Dacă salvați pagina adresa dumneavoastră IP va fi înregistrată în istoric.''",
        "missingsummary": "'''Atenție:''' Nu ați completat caseta „descriere modificări”. Dacă apăsați din nou butonul „salvează pagina” modificările vor fi salvate fără descriere.",
        "missingcommenttext": "Vă rugăm să introduceți un comentariu.",
        "parser-template-recursion-depth-warning": "Limită de adâncime a recursiei depășită ($1)",
        "language-converter-depth-warning": "Limita adâncimii convertorului de limbă a fost depășită ($1)",
        "node-count-exceeded-category": "Pagini unde numărul de noduri este depășit",
-       "node-count-exceeded-category-desc": "O categorie pentru paginile în care numărul de noduri este depășit.",
+       "node-count-exceeded-category-desc": "Pagina depășește numărul maxim de noduri.",
        "node-count-exceeded-warning": "Pagina a depășit numărul de noduri",
        "expansion-depth-exceeded-category": "Pagini unde profunzimea de expansiune este depășită",
-       "expansion-depth-exceeded-category-desc": "Aceasta este o categorie pentru paginile în care a fost depășită profunzimea de expansiune.",
+       "expansion-depth-exceeded-category-desc": "Pagina depășește profunzimea maximă de expansiune.",
        "expansion-depth-exceeded-warning": "Pagina depășește profunzimea de expansiune",
        "parser-unstrip-loop-warning": "Buclă nedetașabilă detectată",
        "parser-unstrip-recursion-limit": "Limita de recursivitate nedetașabilă depășită ($1)",
        "rev-deleted-event": "(intrare ștearsă)",
        "rev-deleted-user-contribs": "[nume de utilizator sau adresă IP ștearsă - modificare ascunsă din contribuții]",
        "rev-deleted-text-permission": "Această versiune a paginii a fost '''ștearsă'''.\nMai multe detalii în [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} jurnalul ștergerilor].",
+       "rev-suppressed-text-permission": "Această versiune a paginii a fost <strong>suprimată</strong>.\nDetalii puteți găsi în [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} jurnalul suprimărilor].",
        "rev-deleted-text-unhide": "Această versiune a paginii a fost '''ștearsă'''.\nDetalii se pot găsi în [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} jurnalul ștergerilor].\nCa administrator puteți [$1 vedea această versiune] în continuare, dacă doriți acest lucru.",
        "rev-suppressed-text-unhide": "Această versiune a paginii a fost '''suprimată'''.\nDetalii se pot găsi în [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} jurnalul suprimărilor].\nCa administrator puteți [$1 vedea această versiune] în continuare, dacă doriți acest lucru.",
        "rev-deleted-text-view": "Această versiune a paginii a fost '''ștearsă'''.\nCa administrator puteți să o vedeți; detalii puteți găsi în [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} jurnalul ștergerilor].",
        "revdelete-text-text": "Versiunile șterse vor continua să fie vizibile în istoricul paginii, însă anumite părți ale conținutului acestora vor fi inaccesibile publicului.",
        "revdelete-text-file": "Versiunile șterse ale fișierului vor continua să fie vizibile în istoricul fișierului, însă anumite părți ale conținutului acestora vor fi inaccesibile publicului.",
        "logdelete-text": "Evenimentele șterse ale jurnalului vor continua să fie vizibile în jurnale, însă anumite părți ale conținutului acestora vor fi inaccesibile publicului.",
-       "revdelete-text-others": "Alți administratori de la {{SITENAME}} vor avea acces în continuare la conținutul ascuns și îl vor putea restaura prin intermediul acestei interfețe, cu excepția cazurilor în care nu sunt activate și restricții suplimentare.",
+       "revdelete-text-others": "Alți administratori vor avea acces în continuare la conținutul ascuns și îl vor restaurarea acestuia, cu excepția cazurilor în care nu sunt activate și restricții suplimentare.",
        "revdelete-confirm": "Vă rugăm să confirmați că intenționați să faceți acest lucru, că înțelegeți consecințele și că faceți asta în conformitate cu [[{{MediaWiki:Policy-url}}|politica]].",
        "revdelete-suppress-text": "Suprimarea trebuie folosită '''doar''' în următoarele cazuri:\n* Informații potențial calomnioase\n* Informații personale inadecvate\n*: ''adrese și numere de telefon personale, CNP, numere de securitate socială etc.''",
        "revdelete-legend": "Restricții de afișare",
        "searchprofile-advanced-tooltip": "Caută în spații de nume personalizate",
        "search-result-size": "$1 ({{PLURAL:$2|1 cuvânt|$2 cuvinte}})",
        "search-result-category-size": "$1 {{PLURAL:$1|element|elemente}} ($2 {{PLURAL:$2|categorie|categorii}}, $3 {{PLURAL:$3|fișier|fișiere}})",
-       "search-result-score": "Relevanță: $1%",
        "search-redirect": "(redirecționare de la $1)",
        "search-section": "(secțiunea $1)",
        "search-file-match": "(se regăsește în conținutul fișierului)",
        "searchall": "toate",
        "showingresults": "Mai jos {{PLURAL:$1|apare '''1''' rezultat|apar '''$1''' rezultate|apar '''$1''' de rezultate}} începând cu nr. <b>$2</b>.",
        "showingresultsinrange": "Mai jos se afișează un număr de până la {{PLURAL:$1|<strong>1</strong> rezultat|<strong>$1</strong> rezultate|<strong>$1</strong> de rezultate}} din intervalul #<strong>$2</strong> la #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Rezultatul '''$1''' din '''$3'''|Rezultatele '''$1 - $2''' din '''$3'''}} pentru '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Rezultatul <strong>$1</strong> din <strong>$3</strong>|Rezultatele <strong>$1 - $2</strong> din <strong>$3</strong>}}",
        "search-nonefound": "Nu sunt rezultate conforme interogării.",
        "powersearch-legend": "Căutare avansată",
        "powersearch-ns": "Căutare în spațiile de nume:",
        "preferences": "Preferințe",
        "mypreferences": "Preferințe",
        "prefs-edits": "Număr de modificări:",
-       "prefsnologintext2": "Vă rugăm să vă $1 pentru a vă seta preferințele de utilizator.",
+       "prefsnologintext2": "Vă rugăm să vă autentificați pentru a vă modifica preferințele de utilizator.",
        "prefs-skin": "Aspect",
        "skin-preview": "Previzualizare",
        "datedefault": "Nici o preferință",
        "right-deletedtext": "Vizualizează textul șters și modificările dintre versiunile șterse",
        "right-browsearchive": "Caută pagini șterse",
        "right-undelete": "Recuperează pagini",
-       "right-suppressrevision": "Examinează și restaurează reviziile ascunse față de administratori",
+       "right-suppressrevision": "Vizualizează, ascunde și restaurează versiuni specifice ale paginilor față de orice utilizator",
+       "right-viewsuppressed": "Vizualizează versiuni ascunse față de orice utilizator",
        "right-suppressionlog": "Vizualizează jurnale private",
        "right-block": "Blochează alți utilizatori la modificare",
        "right-blockemail": "Blochează alți utilizatori la trimiterea e-mailurilor",
        "recentchanges-legend-heading": "'''Legendă:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vedeți și [[Special:NewPages|lista cu pagini noi]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Dedesubt sunt modificările începând cu <b>$2</b> (maximum <b>$1</b> afișate).",
+       "rcnotefrom": "Dedesubt {{PLURAL:$5|se află o modificare|sunt modificările}} începând cu <b>$3, $4</b> (maximum <b>$1</b> afișate).",
        "rclistfrom": "Se afișează modificările începând cu $3, $2",
        "rcshowhideminor": "$1 modificările minore",
        "rcshowhideminor-show": "Arată",
        "uploadwarning": "Avertizare la trimiterea fișierului",
        "uploadwarning-text": "Vă rugăm să modificați descrierea fișierului mai jos și să încercați din nou.",
        "savefile": "Salvează fișierul",
-       "uploadedimage": "a trimis [[$1]]",
-       "overwroteimage": "încărcat o versiune nouă a fișierului \"[[$1]]\"",
        "uploaddisabled": "Ne pare rău, trimiterea de imagini este dezactivată.",
        "copyuploaddisabled": "Trimiterea prin URL este dezactivată.",
        "uploaddisabledtext": "Încărcările de fișiere sunt dezactivate.",
        "license": "Licențiere:",
        "license-header": "Licențiere",
        "nolicense": "Nici una selectată",
+       "licenses-edit": "Modifică opțiunile pentru licență",
        "license-nopreview": "(Previzualizare indisponibilă)",
-       "upload_source_url": " (un URL valid, accesibil public)",
-       "upload_source_file": " (un fișier de pe computerul dv.)",
+       "upload_source_url": "(fișierul ales de dumneavoastră dintr-un URL valid, accesibil public)",
+       "upload_source_file": "(fișierul ales de dumnevoastră de pe calculatorul dv.)",
+       "listfiles-delete": "șterge",
        "listfiles-summary": "Această pagină specială listează toate fișierele încărcate.",
        "listfiles_search_for": "Căutare fișiere după nume:",
        "imgfile": "fișier",
        "randomincategory": "Pagină aleatorie din categorie",
        "randomincategory-invalidcategory": "„$1” nu este un nume de categorie valid.",
        "randomincategory-nopages": "Nu există pagini în [[:Category:$1]].",
-       "randomincategory-selectcategory": "Obțineți, aleatoriu, o pagină din categoria: $1 $2.",
-       "randomincategory-selectcategory-submit": "Du-te",
+       "randomincategory-category": "Categorie:",
+       "randomincategory-legend": "Pagină aleatorie din categoria",
        "randomredirect": "Redirecționare aleatorie",
        "randomredirect-nopages": "Nu există redirecționări în spațiul de nume \"$1\".",
        "statistics": "Statistici",
        "wantedpages-badtitle": "Titlu invalid în rezultatele : $1",
        "wantedfiles": "Fișiere dorite",
        "wantedfiletext-cat": "Următoarele fișiere sunt utilizate, dar nu există. Fișierele provenind din depozite externe pot apărea listate, în ciuda faptului că ele nu există. Orice astfel de pozitive false vor fi <del>tăiate</del>. În plus, paginile care încorporează astfel de fișiere inexistente sunt listate la [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Următoarele fișiere sunt utilizate, dar nu există. În plus, paginile care încorporează astfel de fișiere inexistente sunt listate la [[:$1]].",
        "wantedfiletext-nocat": "Următoarele fișiere sunt utilizate, dar nu există. Fișierele provenind din depozite externe pot apărea listate, în ciuda faptului că ele nu există. Orice astfel de pozitive false vor fi <del>tăiate</del>.",
+       "wantedfiletext-nocat-noforeign": "Următoarele fișiere sunt utilizate, dar nu există.",
        "wantedtemplates": "Formate dorite",
        "mostlinked": "Cele mai căutate articole",
        "mostlinkedcategories": "Cele mai căutate categorii",
        "trackingcategories-desc": "Criteriile de includere în categorie",
        "noindex-category-desc": "Pagina conține cuvântul magic <code><nowiki>__NOINDEX__</nowiki></code> (aflându-se într-un spațiu de nume care permite acest marcaj) și, drept urmare, nu este indexată de roboți.",
        "index-category-desc": "Pagina conține cuvântul magic <code><nowiki>__INDEX__</nowiki></code> (aflându-se într-un spațiu de nume care permite acest marcaj) și, ca urmare, este indexată de roboți, deși în mod normal acest lucru nu s-ar fi întâmplat.",
-       "post-expand-template-inclusion-category-desc": "După extinderea tuturor formatelor, dimensiunea paginii a depășit <code>$wgMaxArticleSize</code>, astfel că anumite formate nu au fost extinse.",
-       "post-expand-template-argument-category-desc": "După extinderea argumentului unui format (ceva plasat între acolade triple, precum <code>{{{Foo}}}</code>), pagina a depășit <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Prea multe funcții costisitoare de analiză (precum <code>#ifexist</code>) incluse într-o pagină. Vedeți [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Categorie adăugată dacă pagina conține o legătură întreruptă către un fișier (o legătură folosită pentru încorporarea unui fișier atunci când fișierul nu există).",
-       "hidden-category-category-desc": "Această categorie conține <code><nowiki>__HIDDENCAT__</nowiki></code>, ceea ce împiedică în mod implicit afișarea ei în zona cu legături către categorii din cadrul paginilor.",
+       "post-expand-template-inclusion-category-desc": "Dimensiunea paginii a depășit <code>$wgMaxArticleSize</code> după extinderea tuturor formatelor, astfel că anumite formate nu au fost extinse.",
+       "post-expand-template-argument-category-desc": "Pagina a depășit <code>$wgMaxArticleSize</code> după extinderea argumentului unui format (ceva plasat între acolade triple, precum <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "Pagina folosește prea multe funcții costisitoare de analiză (precum <code>#ifexist</code>). Vedeți [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "Pagina conține o legătură întreruptă către un fișier (o legătură folosită pentru încorporarea unui fișier atunci când fișierul nu există).",
+       "hidden-category-category-desc": "Categoria conține <code><nowiki>__HIDDENCAT__</nowiki></code> în conținutul său, ceea ce împiedică în mod implicit afișarea ei în zona cu legături către categorii din cadrul paginilor.",
        "trackingcategories-nodesc": "Nicio descriere disponibilă.",
        "trackingcategories-disabled": "Categoria este dezactivată",
        "mailnologin": "Nu există adresă de trimitere",
        "mywatchlist": "Pagini urmărite",
        "watchlistfor2": "Pentru $1 $2",
        "nowatchlist": "Lista dumneavoastră de pagini urmărite nu conține nici o pagină.",
-       "watchlistanontext": "Vă rugăm să vă $1 pentru a vizualiza sau edita elementele din lista dumneavoastră de pagini urmărite.",
+       "watchlistanontext": "Vă rugăm să vă autentificați pentru a vizualiza sau modifica elementele din lista dumneavoastră de pagini urmărite.",
        "watchnologin": "Nu sunteți autentificat",
        "addwatch": "Adăugă la lista de pagini urmărite",
        "addedwatchtext": "Pagina „[[:$1]]” a fost adăugată în lista dumneavoastră de [[Special:Watchlist|pagini urmărite]].\nModificările viitoare efectuate asupra acestei pagini dar și asupra paginii de discuție asociată vor fi listate acolo.",
        "watchlist-details": "{{PLURAL:$1|O pagină|$1 pagini urmărite|$1 de pagini urmărite}}, fără a include separat paginile de discuție.",
        "wlheader-enotif": "Notificarea prin e-mail este activată.",
        "wlheader-showupdated": "Paginile care au fost modificate după ultima dumneavoastră vizită sunt afișate '''îngroșat'''.",
-       "wlnote2": "Mai jos se află schimbările din {{PLURAL:$1|ultima oră|ultimele <strong>$1</strong> ore|ultimele <strong>$1</strong> de ore}}, așa cum era situația la $2, $3.",
+       "wlnote": "Mai jos se află {{PLURAL:$1|ultima schimbare|ultimele <strong>$1</strong> schimbări|ultimele <strong>$1</strong> de schimbări}} din {{PLURAL:$2|ultima oră|ultimele <strong>$2</strong> ore|ultimele <strong>$2</strong> de ore}}, așa cum era situația la $3, $4.",
        "wlshowlast": "Arată ultimele $1 ore $2 zile $3",
        "watchlist-options": "Opțiuni listă de pagini urmărite",
        "watching": "Se urmărește...",
        "exbeforeblank": "conținutul înainte de golire era: '$1'",
        "delete-confirm": "Şterge \"$1\"",
        "delete-legend": "Şterge",
-       "historywarning": "'''Atenție:''' istoricul paginii pe care o ștergeți conține aproximativ $1 {{PLURAL:$1|versiune|versiuni|de versiuni}}:",
+       "historywarning": "<strong>Atenție:</strong> istoricul paginii pe care o ștergeți conține $1 {{PLURAL:$1|versiune|versiuni|de versiuni}}:",
        "confirmdeletetext": "Sunteți pe cale să ștergeți permanent o pagină sau imagine din baza de date, împreună cu istoria asociată acesteia. Vă rugăm să confirmați alegerea făcută de dvs., faptul că înțelegeți consecințele acestei acțiuni și faptul că o faceți în conformitate cu [[{{MediaWiki:Policy-url}}|Politica oficială]].",
        "actioncomplete": "Acțiune completă",
        "actionfailed": "Acțiunea a eșuat",
        "delete-edit-reasonlist": "Modifică motivele ștergerii",
        "delete-toobig": "Această pagină are un istoric al modificărilor important, cu mai mult de $1 {{PLURAL:$1|versiune|versiuni|de versiuni}}.\nȘtergerea unei astfel de pagini a fost restricționată pentru a preveni apariția unor erori în {{SITENAME}}.",
        "delete-warning-toobig": "Această pagină are un istoric al modificărilor mult prea mare, cu mai mult de $1 {{PLURAL:$1|versiune|versiuni|de versiuni}}.\nȘtergerea sa poate afecta baza de date a sitului {{SITENAME}};\nacționați cu precauție.",
+       "deleteprotected": "Nu puteți șterge această pagină, deoarece este protejată.",
        "deleting-backlinks-warning": "'''Atenție:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Alte pagini]] se leagă sau transclud pagina pe care doriți să o ștergeți.",
        "rollback": "Editări de revenire",
        "rollback_short": "Revenire",
        "autoblockid": "Autoblocare #$1",
        "block": "Blocare utilizator",
        "unblock": "Deblocare utilizator",
-       "blockip": "Blocare utilizator",
+       "blockip": "Blocare {{GENDER:$1|utilizator|utilizatoare}}",
        "blockip-legend": "Blocare utilizator/adresă IP",
        "blockiptext": "Pentru a bloca un utilizator completați rubricile de mai jos.<br />\n'''Respectați [[{{MediaWiki:Policy-url}}|politica de blocare]].'''<br />\nPrecizați motivul blocării; de exemplu indicați paginile vandalizate de acest utilizator.",
        "ipaddressorusername": "Adresă IP sau nume de utilizator",
        "ipb-unblock-addr": "Deblochează utilizatorul $1",
        "ipb-unblock": "Deblocați un nume de utilizator sau o adresă IP",
        "ipb-blocklist": "Vezi blocările existente",
-       "ipb-blocklist-contribs": "Contribuțiile utilizatorului $1",
+       "ipb-blocklist-contribs": "Contribuțiile {{GENDER:$1|utilizatorului $1|utilizatoarei $1}}",
        "unblockip": "Deblochează adresă IP",
        "unblockiptext": "Folosiți formularul de mai jos pentru a restaura permisiunea de scriere pentru adrese IP sau nume de utilizator blocate anterior.",
        "ipusubmit": "Elimină blocarea",
        "unblocked": "[[User:$1|$1]] a fost deblocat",
        "unblocked-range": "$1 a fost deblocat",
        "unblocked-id": "Blocarea $1 a fost eliminată",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] a fost deblocat.",
        "blocklist": "Utilizatori blocați",
        "ipblocklist": "Utilizatori blocați",
        "ipblocklist-legend": "Găsire utilizator blocat",
        "import": "Importare pagini",
        "importinterwiki": "Import transwiki",
        "import-interwiki-text": "Selectează un wiki și titlul paginii care trebuie importate. Datele reviziilor și numele editorilor vor fi salvate. Toate acțiunile de import transwiki pot fi găsite la [[Special:Log/import|log import]]",
-       "import-interwiki-source": "Wiki/pagină sursă:",
+       "import-interwiki-sourcewiki": "Wikiul sursă:",
+       "import-interwiki-sourcepage": "Pagina sursă:",
        "import-interwiki-history": "Copiază toate versiunile istoricului acestei pagini",
        "import-interwiki-templates": "Includeți toate formatele",
        "import-interwiki-submit": "Importă",
        "import-upload": "Încărcare date XML",
        "import-token-mismatch": "S-au pierdut datele sesiunii. Vă rugăm să încercați din nou.",
        "import-invalid-interwiki": "Nu se poate importa din wiki-ul specificat.",
-       "import-error-edit": "Pagina „$1” nu este importată deoarece nu vă este permis s-o modificați.",
-       "import-error-create": "Pagina „$1” nu este importată deoarece nu vă este permis s-o creați.",
-       "import-error-interwiki": "Pagina „$1” nu poate fi importată deoarece numele acesteia este rezervat pentru legături externe (interwiki).",
-       "import-error-special": "Pagina „$1” nu poate fi importată deoarece aparține unui spațiu de nume special care nu admite pagini.",
-       "import-error-invalid": "Pagina „$1” nu poate fi importată deoarece numele acesteia este invalid.",
+       "import-error-edit": "Pagina „$1” nu a fost importată deoarece nu vă este permis s-o modificați.",
+       "import-error-create": "Pagina „$1” nu a fost importată deoarece nu vă este permis s-o creați.",
+       "import-error-interwiki": "Pagina „$1” nu a fost importată deoarece numele acesteia este rezervat pentru legături externe (interwiki).",
+       "import-error-special": "Pagina „$1” nu a fost importată deoarece aparține unui spațiu de nume special care nu admite pagini.",
+       "import-error-invalid": "Pagina „$1” nu a fost importată deoarece numele sub care ar fi fost importată nu este valid pe acest wiki.",
        "import-error-unserialize": "Versiunea $2 a paginii „$1” nu poate fi deserializată. Versiunea a fost raportată ca utilizând modelul de conținut $3 serializat ca $4.",
        "import-error-bad-location": "Versiunea $2, care folosește modelul de conținut $3, nu a putut fi stocată în pagina „$1” de pe acest wiki, de vreme ce acel model nu este acceptat pe acea pagină.",
        "import-options-wrong": "{{PLURAL:$2|Opțiune eronată|Opțiuni eronate}}: <nowiki>$1</nowiki>",
        "importlogpage": "Log import",
        "importlogpagetext": "Imoprturi administrative de pagini de la alte wiki, cu istoricul editărilor.",
        "import-logentry-upload": "a importat [[$1]] prin încărcare de fișier",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|versiune|versiuni|de versiuni}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|versiune importată|versiuni importate|de versiuni importate}}",
        "import-logentry-interwiki": "transwikificat $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|versiune|versiuni|de versiuni}} de la $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|versiune|versiuni|de versiuni}} importate de la $2",
        "javascripttest": "Testare JavaScript",
        "javascripttest-title": "Rulare teste pentru $1",
        "javascripttest-pagetext-noframework": "Această pagină este rezervată rulării testelor JavaScript.",
        "yesterday-at": "Ieri, la $1",
        "bad_image_list": "Formatul este următorul:\n\nNumai elementele unei liste sunt luate în considerare. (Acestea sunt linii ce încep cu *)\n\nPrima legătură de pe linie trebuie să fie spre un fișier defectuos.\n\nOrice legături ce urmează pe aceeași linie sunt considerate excepții, adică pagini unde fișierul poate apărea inclus direct.",
        "metadata": "Informații",
-       "metadata-help": "Acest fișier conține informații suplimentare, introduse probabil de aparatul fotografic digital sau scanerul care l-a generat.\nDacă fișierul a fost modificat între timp, este posibil ca unele detalii să nu mai fie valabile.",
+       "metadata-help": "Acest fișier conține informații suplimentare, introduse probabil de aparatul de fotografiat digital sau scanerul care l-a generat.\nDacă fișierul a fost modificat între timp, este posibil ca unele detalii să nu mai fie valabile.",
        "metadata-expand": "Afișează detalii suplimentare",
        "metadata-collapse": "Ascunde detalii suplimentare",
        "metadata-fields": "Câmpurile cu metadatele imaginii listate mai jos vor fi incluse în pagina de afișare a imaginii atunci când tabelul cu metadate este restrâns.\nAltele vor fi ascunse implicit.\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": "Lățime",
        "exif-imagelength": "Înălțime",
-       "exif-bitspersample": "Biți pe componentă",
+       "exif-bitspersample": "Biți per componentă",
        "exif-compression": "Metodă de comprimare",
-       "exif-photometricinterpretation": "Compoziția pixelilor",
+       "exif-photometricinterpretation": "Model de culoare",
        "exif-orientation": "Orientare",
-       "exif-samplesperpixel": "Numărul de componente",
+       "exif-samplesperpixel": "Număr de componente",
        "exif-planarconfiguration": "Aranjarea datelor",
        "exif-ycbcrsubsampling": "Mostră din fracția Y/C",
        "exif-ycbcrpositioning": "Poziționarea Y și C",
        "exif-yresolution": "Rezoluție verticală",
        "exif-stripoffsets": "Locația datelor imaginii",
        "exif-rowsperstrip": "Numărul de linii per bandă",
-       "exif-stripbytecounts": "Biți corespunzători benzii comprimate",
+       "exif-stripbytecounts": "Octeți corespunzători benzii comprimate",
        "exif-jpeginterchangeformat": "Offset pentru JPEG SOI",
-       "exif-jpeginterchangeformatlength": "Biți de date JPEG",
+       "exif-jpeginterchangeformatlength": "Octeți de date JPEG",
        "exif-whitepoint": "Cromaticitatea punctului alb",
        "exif-primarychromaticities": "Coordonatele cromatice ale culorilor primare",
        "exif-ycbcrcoefficients": "Tăria culorii coeficienților matricei de transformare",
        "exif-software": "Software folosit",
        "exif-artist": "Autor",
        "exif-copyright": "Titularul drepturilor de autor",
-       "exif-exifversion": "Versiune exif",
-       "exif-flashpixversion": "Versiune susținută de Flashpix",
+       "exif-exifversion": "Versiune EXIF",
+       "exif-flashpixversion": "Versiune de Flashpix suportată",
        "exif-colorspace": "Spațiu de culoare",
-       "exif-componentsconfiguration": "Semnificația componentelor",
+       "exif-componentsconfiguration": "Semnificația fiecărei componente",
        "exif-compressedbitsperpixel": "Mod de comprimare a imaginii",
        "exif-pixelydimension": "Lățimea imaginii",
        "exif-pixelxdimension": "Înălțimea imaginii",
        "exif-relatedsoundfile": "Fișierul audio asemănător",
        "exif-datetimeoriginal": "Data și ora producerii imaginii",
        "exif-datetimedigitized": "Data și ora digitizării",
-       "exif-subsectime": "Data/Ora milisecunde",
-       "exif-subsectimeoriginal": "Data/Ora/Original milisecunde",
-       "exif-subsectimedigitized": "Milisecunde DateTimeDigitized",
+       "exif-subsectime": "Subsecunde Data/Ora",
+       "exif-subsectimeoriginal": "Subsecunde Data/Ora/Original",
+       "exif-subsectimedigitized": "Subsecunde Data/Ora/Digitizare",
        "exif-exposuretime": "Timp de expunere",
        "exif-exposuretime-format": "$1 sec ($2)",
        "exif-fnumber": "Diafragmă",
        "exif-exposureprogram": "Program de expunere",
        "exif-spectralsensitivity": "Sensibilitate spectrală",
-       "exif-isospeedratings": "Evaluarea vitezei ISO",
+       "exif-isospeedratings": "Sensibilitate ISO",
        "exif-shutterspeedvalue": "Viteza obturatorului în APEX",
        "exif-aperturevalue": "Diafragmă în APEX",
        "exif-brightnessvalue": "Luminozitate în APEX",
        "exif-exposurebiasvalue": "Compensarea expunerii",
-       "exif-maxaperturevalue": "Apertura maximă",
+       "exif-maxaperturevalue": "Diafragmă maximă",
        "exif-subjectdistance": "Distanța față de subiect",
-       "exif-meteringmode": "Forma de măsurare",
+       "exif-meteringmode": "Mod de măsurare",
        "exif-lightsource": "Sursă de lumină",
        "exif-flash": "Bliț",
        "exif-focallength": "Distanța focală a obiectivului",
        "exif-subjectarea": "Suprafața subiectului",
        "exif-flashenergy": "Energie bliț",
-       "exif-focalplanexresolution": "Rezoluția focală plană X",
-       "exif-focalplaneyresolution": "Rezoluția focală plană Y",
-       "exif-focalplaneresolutionunit": "Unitatea de măsură pentru rezoluția focală plană",
+       "exif-focalplanexresolution": "Rezoluția orizontală a panului focal",
+       "exif-focalplaneyresolution": "Rezoluția verticală a panului focal",
+       "exif-focalplaneresolutionunit": "Unitate de măsură pentru rezoluția planului focal",
        "exif-subjectlocation": "Locația subiectului",
        "exif-exposureindex": "Indexul expunerii",
        "exif-sensingmethod": "Metoda sensibilă",
        "exif-filesource": "Fișier sursă",
        "exif-scenetype": "Tipul scenei",
-       "exif-customrendered": "Prelucrarea imaginii",
+       "exif-customrendered": "Prelucrare personalizată",
        "exif-exposuremode": "Mod de expunere",
        "exif-whitebalance": "Balanța albă",
        "exif-digitalzoomratio": "Raportul transfocării digitale",
        "exif-focallengthin35mmfilm": "Distanță focală pentru film de 35 mm",
-       "exif-scenecapturetype": "Tipul de surprindere a scenei",
+       "exif-scenecapturetype": "Tipul de captură a scenei",
        "exif-gaincontrol": "Controlul scenei",
        "exif-contrast": "Contrast",
        "exif-saturation": "Saturație",
        "exif-sharpness": "Ascuțime",
        "exif-devicesettingdescription": "Descrierea reglajelor aparatului",
        "exif-subjectdistancerange": "Distanța față de subiect",
-       "exif-imageuniqueid": "Identificarea imaginii unice",
+       "exif-imageuniqueid": "Identificator unic al imaginii",
        "exif-gpsversionid": "Versiunea de conversie GPS",
        "exif-gpslatituderef": "Latitudine nordică sau sudică",
        "exif-gpslatitude": "Latitudine",
        "exif-sensingmethod-8": "Senzorul linear al culorii secvențiale",
        "exif-filesource-3": "Aparat de fotografiat digital",
        "exif-scenetype-1": "O imagine fotografiată direct",
-       "exif-customrendered-0": "Prelucrare normală",
-       "exif-customrendered-1": "Prelucrare nestandard",
+       "exif-customrendered-0": "Procedeu normal",
+       "exif-customrendered-1": "Procedeu personalizat",
        "exif-exposuremode-0": "Expunere automată",
        "exif-exposuremode-1": "Expunere manuală",
        "exif-exposuremode-2": "Serie automată de expuneri",
-       "exif-whitebalance-0": "Balanță alb automată",
-       "exif-whitebalance-1": "Balanță alb manuală",
+       "exif-whitebalance-0": "Balans de alb automat",
+       "exif-whitebalance-1": "Balans de alb manual",
        "exif-scenecapturetype-0": "Standard",
        "exif-scenecapturetype-1": "Portret",
        "exif-scenecapturetype-2": "Portret",
        "exif-gpsdirection-t": "Direcția reală",
        "exif-gpsdirection-m": "Direcție magnetică",
        "exif-ycbcrpositioning-1": "Centrat",
-       "exif-ycbcrpositioning-2": "Co-amplasat",
+       "exif-ycbcrpositioning-2": "Coamplasat",
        "exif-dc-contributor": "Contribuitori",
        "exif-dc-coverage": "Întinderea spațială sau temporală a elementului media",
        "exif-dc-date": "Data (datele)",
        "autosumm-replace": "Pagină înlocuită cu „$1”",
        "autoredircomment": "Redirecționat înspre [[$1]]",
        "autosumm-new": "Pagină nouă: $1",
+       "autosumm-newblank": "A creat o pagină goală",
        "lag-warn-normal": "Modificările mai noi de $1 {{PLURAL:$1|secondă|seconde}} pot să nu apară în listă.",
        "lag-warn-high": "Serverul bazei de date este suprasolicitat, astfel încît modificările făcute în ultimele $1 {{PLURAL:$1|secundă|secunde}} pot să nu apară în listă.",
        "watchlistedit-normal-title": "Modificare listă pagini urmărite",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discuție]])",
        "unknown_extension_tag": "Extensie etichetă necunoscută „$1”",
        "duplicate-defaultsort": "'''Atenție:''' Cheia de sortare implicită („$2”) o înlocuiește pe precedenta („$1”).",
+       "duplicate-displaytitle": "<strong>Atenție:</strong> Titlul afișat „$2” înlocuieşte titlul afișat anterior, „$1”.",
        "version": "Versiune",
        "version-extensions": "Extensii instalate",
        "version-skins": "Aspecte instalate",
        "logentry-rights-rights": "$1 {{GENDER:$2|a schimbat}} apartenența la grup pentru $3 de la $4 la $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|a schimbat}} apartenența la grup pentru $3",
        "logentry-rights-autopromote": "$1 {{GENDER:$2|a fost promovat|a fost promovată}} în mod automat de la $4 la $5",
+       "logentry-upload-upload": "$1 {{GENDER:$2|a încărcat}} $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|a încărcat}} o nouă versiune pentru $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|a încărcat}} $3",
        "rightsnone": "(niciunul)",
        "feedback-bugornote": "Dacă sunteți pregătit să descrieți o problemă tehnică în detaliu vă rugăm să [$1 raportați un bug].\nÎn caz contrar, puteți utiliza formularul de mai jos. Comentariul dumneavoastră va fi adăugat pe pagina „[$3 $2]”, împreună cu numele de utilizator și numele navigatorului pe care îl folosiți.",
        "feedback-subject": "Subiect:",
        "action-pagelang": "modificați limba paginii",
        "log-name-pagelang": "Jurnal modificare limbă",
        "log-description-pagelang": "Acesta este un jurnal cu modificări ale limbii paginilor.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|a modificat}} limba paginii pentru $3 din $4 în $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|a modificat}} limba paginii pentru $3 din $4 în $5.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (activat)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''dezactivat''')"
 }
index 5004182..493c273 100644 (file)
@@ -5,7 +5,8 @@
                        "Kaganer",
                        "McDutchie",
                        "Reder",
-                       "아라"
+                       "아라",
+                       "C.R."
                ]
        },
        "tog-underline": "Collegaminde sottolinèate:",
        "talkpagelinktext": "Parle",
        "specialpage": "Pàgene Speciele",
        "personaltools": "Struminde personele",
-       "postcomment": "Seziona nove",
        "articlepage": "Vide 'a pàgene de le condenute",
        "talk": "'Ngazzaminde",
        "views": "Visite",
        "externaldberror": "Vide bbuene, o stè 'n'errore de autendicazione a 'u database oppure tu non ge puè aggiorna 'u cunde tue esterne.",
        "login": "Tràse",
        "nav-login-createaccount": "Tràse / Reggistrete",
-       "loginprompt": "Tu a tenè le cookies abilitate pe tràse jndr'à {{SITENAME}}.",
        "userlogin": "Tràse / Reggistrete",
        "userloginnocreate": "Tràse",
        "logout": "Isse",
        "gotaccountlink": "Tràse",
        "userlogin-resetlink": "T'è scurdate le dettaglie pe trasè?",
        "userlogin-resetpassword-link": "T'è scurdate 'a passuord toje?",
-       "userlogin-loggedin": "Tu ste jndre ggià cumme a {{GENDER:$1|$1}}.\nAuse 'u module aqquà sotte pe trasè cumme a 'n'otre utende.",
-       "userlogin-createanother": "Ccreje 'n'otre cunde",
        "createacct-emailrequired": "Indirizze email",
        "createacct-emailoptional": "Indirizze email (opzionale)",
        "createacct-email-ph": "Mitte l'indirizze email tune",
        "searchprofile-advanced-tooltip": "Cirche jndr'à le namespace personalizzete",
        "search-result-size": "$1 ({{PLURAL:$2|1 parole|$2 parole}})",
        "search-result-category-size": "{{PLURAL:$1|1 membre|$1 membre}} ({{PLURAL:$2|1 sottecategorije|$2 sottecategorije}}, {{PLURAL:$3|1 file|$3 file}})",
-       "search-result-score": "'Mbortanze: $1%",
        "search-redirect": "(Redirette $1)",
        "search-section": "(sezione $1)",
        "search-suggest": "Ce signifeche: $1",
        "searchrelated": "colleghete",
        "searchall": "tutte",
        "showingresults": "Stoche a fazze vedè aqquà sotte {{PLURAL:$1|'''1''' resultete|'''$1''' resultete}} ca accumenzene cu #'''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|Resultate '''$1''' de '''$3'''|Resultate '''$1 - $2''' de '''$3'''}} pe '''$4'''",
        "search-nonefound": "Non ge stonne resultete ca soddisfecene l'inderrogazione.",
        "powersearch-legend": "Ricerche avanzete",
        "powersearch-ns": "Cirche jndr'à le namespace:",
        "uploadwarning": "Avvise de carecamende",
        "uploadwarning-text": "Pe piacere cange 'a descrizione d'u file sotte e pruève 'notra vote.",
        "savefile": "Reggistre 'u file",
-       "uploadedimage": "carechete \"[[$1]]\"",
-       "overwroteimage": "ha state carechete 'na versiona nove de \"[[$1]]\"",
        "uploaddisabled": "Carecaminde disabbilitete",
        "copyuploaddisabled": "Carecamende da l'URL disabbilitate.",
        "uploaddisabledtext": "Le carecaminde de le file sonde disabbilitete.",
        "randomincategory": "Pàggene a uecchije jndr'à categorije",
        "randomincategory-invalidcategory": "\"$1\" non g'è 'nu nome d'a categorije valide.",
        "randomincategory-nopages": "Non ge stonne pàggene jndr'à [[:Category:$1]].",
-       "randomincategory-selectcategory": "Pigghie pàggene a uecchije da 'a categorije: $1 $2.",
-       "randomincategory-selectcategory-submit": "Véje",
        "randomredirect": "Redirezionamende a uecchie",
        "randomredirect-nopages": "Non ge stonne redirezionaminde jndr'à 'u namespace \"$1\".",
        "statistics": "Statisteche",
        "watchlist-details": "{{PLURAL:$1|$1 pàgene|$1 pàggene}} jndr'à liste de le pàggene condrollete, scartanne le pàggene de le 'ngazzaminde.",
        "wlheader-enotif": "* Notifiche pe email abbilitate.",
        "wlheader-showupdated": "* Le pàggene ca onne state cangiate da l'urtema visite avènene fatte vedè in '''grascette'''",
+       "wlnote": "Aqquà sotte {{PLURAL:$1|ste l'urteme cangiamende|stonne l'urteme '''$1''' cangiaminde}} jndr'à {{PLURAL:$2|l'urtema ore|l'urteme '''$2''' ore}}, jndr'à $3, $4.",
        "wlshowlast": "Vide l'urteme $1 ore $2 sciurne $3",
        "watchlist-options": "Opzione d'a liste de le pàggene condrollete",
        "watching": "Fà vedè...",
        "undelete-search-submit": "Cirche",
        "undelete-no-results": "Non ge stonne pàggene acchiate jndr'à l'archivije de le scangellaminde.",
        "undelete-filename-mismatch": "Non ge pozze repristinà 'a revisione d'u file cu orarie $1: nome d'u file errate",
-       "undelete-bad-store-key": "Cannot undelete file revision with timestamp $1: file was missing before deletion.\nNon ge pozze repristinà 'a revisione d'u file cu orarie $1: 'u file ha state perdute apprime da scangellazione.",
+       "undelete-bad-store-key": "Non ge pozze repristinà 'a revisione d'u file cu orarie $1: 'u file ha state perdute apprime da scangellazione.",
        "undelete-cleanup-error": "Errore scangellanne 'n'archivije de file non ausate \"$1\".",
-       "undelete-missing-filearchive": "Non ge pozze repristinà 'u file archiviate cu ID $1 purcè non ge stè jndr'à 'u database.\nPò essere ca già ha state scangellate.",
+       "undelete-missing-filearchive": "Non ge pozze repristinà 'u file archiviate cu ID $1 purcè non ge stè jndr'à 'u database.\nPò essere ca già ha state repristinate.",
        "undelete-error": "Errore pàgene none scangellate",
        "undelete-error-short": "Errore file non recuperate: $1",
        "undelete-error-long": "Errore ca s'onne acchiate quanne amme pruvate a reprisitinà 'u file:\n\n$1",
        "import": "Pàggene 'mbortete",
        "importinterwiki": "'Mborte da Transuicchi",
        "import-interwiki-text": "Schacchie 'na Uicchi e 'nu titele de pàgene da 'mbortà.\nLe date d'a revisione e 'u nome de le cangiature avènene preservate.\nTutte le aziune de 'mbortaziune 'mbrà le Uicchi sonde reggistrate jndr'à l'[[Special:Log/import|archivije de le 'mbortaziune]].",
-       "import-interwiki-source": "Sorgende Uicchi/vosce:",
        "import-interwiki-history": "Copie tutte 'a sotrie de le versiune de sta pàgene",
        "import-interwiki-templates": "Inglude tutte le template",
        "import-interwiki-submit": "'Mborte",
index fce8dbb..0fc5aa2 100644 (file)
@@ -67,7 +67,9 @@
                        "아라",
                        "Eroha",
                        "Niklem",
-                       "Agilight"
+                       "Agilight",
+                       "Oleg3280",
+                       "Nirovulf"
                ]
        },
        "tog-underline": "Подчёркивание ссылок:",
@@ -84,6 +86,7 @@
        "tog-watchdefault": "Добавлять в список наблюдения изменённые мной страницы и описания файлов",
        "tog-watchmoves": "Добавлять в список наблюдения переименованные мной страницы и файлы",
        "tog-watchdeletion": "Добавлять в список наблюдения удалённые мной страницы и файлы",
+       "tog-watchrollback": "Добавлять страницы, где я выполнил откат, в мой список наблюдения",
        "tog-minordefault": "Помечать по умолчанию правки как малозначимые",
        "tog-previewontop": "Помещать предпросмотр перед окном редактирования",
        "tog-previewonfirst": "Показывать предпросмотр при переходе к редактированию",
        "broken-file-category": "Страницы с неработающими файловыми ссылками",
        "about": "Описание",
        "article": "Статья",
-       "newwindow": "(в новом окне)",
+       "newwindow": "&nbsp;(в новом окне)",
        "cancel": "Отменить",
        "moredotdotdot": "Далее…",
        "morenotlisted": "Этот список не является полным.",
        "talkpagelinktext": "обсуждение",
        "specialpage": "Служебная страница",
        "personaltools": "Персональные инструменты",
-       "postcomment": "Новый раздел",
        "articlepage": "Просмотреть статью",
        "talk": "Обсуждение",
        "views": "Просмотры",
        "otherlanguages": "На других языках",
        "redirectedfrom": "(перенаправлено с «$1»)",
        "redirectpagesub": "Страница-перенаправление",
+       "redirectto": "Перенаправление на:",
        "lastmodifiedat": "Последнее изменение этой страницы: $2, $1.",
        "viewcount": "К этой странице обращались $1 {{PLURAL:$1|раз|раз|раза}}.",
        "protectedpage": "Защищённая страница",
        "hidetoc": "убрать",
        "collapsible-collapse": "свернуть",
        "collapsible-expand": "развернуть",
+       "confirmable-confirm": "{{GENDER:$1|Вы}} уверены?",
+       "confirmable-yes": "Да",
+       "confirmable-no": "Нет",
        "thisisdeleted": "Просмотреть или восстановить $1?",
        "viewdeleted": "Просмотреть $1?",
        "restorelink": "{{PLURAL:$1|$1 удалённую правку|$1 удалённых правок|$1 удалённые правки|1=удалённую правку}}",
        "invalidtitle-knownnamespace": "Недопустимый заголовок с пространством имен «$2» и текстом «$3»",
        "invalidtitle-unknownnamespace": "Недопустимый заголовок с неизвестным номером пространства $1 и текстом «$2»",
        "exception-nologin": "Вы не представились системе",
-       "exception-nologin-text": "Необходимо [[Special:Userlogin|представиться]], чтобы иметь доступ к этой странице или действию.",
+       "exception-nologin-text": "Необходимо представиться, чтобы иметь доступ к этой странице или действию.",
        "exception-nologin-text-manual": "Необходимо $1, чтобы иметь доступ к этой странице или действию.",
        "virus-badscanner": "Ошибка настройки. Неизвестный сканер вирусов: ''$1''",
        "virus-scanfailed": "ошибка сканирования (код $1)",
        "externaldberror": "Произошла ошибка при аутентификации с помощью внешней базы данных или у вас недостаточно прав для внесения изменений в свою внешнюю учётную запись.",
        "login": "Представиться системе",
        "nav-login-createaccount": "Представиться / зарегистрироваться",
-       "loginprompt": "Вы должны разрешить «cookies», чтобы представиться системе.",
        "userlogin": "Представиться или зарегистрироваться",
        "userloginnocreate": "Представиться",
        "logout": "Завершение сеанса",
        "userlogin-resetlink": "Забыли данные для входа?",
        "userlogin-resetpassword-link": "Сбросить ваш пароль?",
        "userlogin-helplink2": "Помощь по входу",
-       "userlogin-loggedin": "Вы уже вошли как {{GENDER:$1|$1}}.\nИспользуйте форму ниже, чтобы войти под другой учётной записью.",
-       "userlogin-createanother": "Создать другую учётную запись",
        "createacct-emailrequired": "Адрес электронной почты",
        "createacct-emailoptional": "Адрес электронной почты (необязательно)",
        "createacct-email-ph": "Введите свой адрес электронной почты",
        "noemailcreate": "Вам необходимо указать корректный адрес электронной почты",
        "passwordsent": "Новый пароль был выслан на адрес электронной почты, указанный для участника $1.\n\nПожалуйста, представьтесь системе заново после получения пароля.",
        "blocked-mailpassword": "Редактирование с вашего IP-адреса запрещено, поэтому заблокирована и функция восстановления пароля.",
-       "eauthentsent": "На указанный адрес электронной почты отправлено письмо. \nЧтоб получать письма в дальнейшем, следуйте изложенным там инструкциям для подтверждения того, что этот адрес действительно принадлежит вам.",
+       "eauthentsent": "На указанный адрес электронной почты отправлено письмо. \nЧтобы получать письма в дальнейшем, следуйте изложенным там инструкциям для подтверждения, что этот адрес действительно принадлежит вам.",
        "throttled-mailpassword": "Функция напоминания пароля уже использовалась в течение {{PLURAL:$1|1=последнего часа|последних $1 часов}}.\nДля предотвращения злоупотреблений, разрешено запрашивать не более одного напоминания {{PLURAL:$1|за $1 час|за $1 часов|за $1 часа|1=в час}}.",
        "mailerror": "Ошибка при отправке почты: $1",
        "acct_creation_throttle_hit": "За сутки с вашего IP-адреса {{PLURAL:$1|была создана $1 учётная запись участника|было создано $1 учётных записей участников|1=уже была создана учётная запись участника}}, что является пределом для данного отрезка времени.\nТаким образом, пользователи, обладающие данным IP-адресом, в данный момент больше не могут создавать новых учётных записей.",
        "createaccount-text": "Кто-то создал учётную запись «$2» на сервере проекта {{SITENAME}} ($4), указав ваш адрес электронной почты. \n\nПароль учётной записи — «$3». Вам следует авторизоваться на сайте и изменить пароль.\n\nПроигнорируйте данное сообщение, если учётная запись была создана по ошибке.",
        "login-throttled": "Вы сделали слишком много попыток представиться системе.\nПожалуйста, подождите $1 перед тем, как попробовать снова.",
        "login-abort-generic": "Неудачная попытка представиться системе",
+       "login-migrated-generic": "Ваша учётная запись была перенесена, и ваше имя участника больше не существует в этой вики.",
        "loginlanguagelabel": "Язык: $1",
        "suspicious-userlogout": "Ваш запрос на завершение сеанса отклонён, так как он похож на запрос, отправленный некорректным браузером или кэширующим прокси.",
        "createacct-another-realname-tip": "Настоящее имя (необязательное поле).\nЕсли вы укажете его, то оно будет использовано для того, чтобы показать, кем была внесена правка страницы.",
        "preview": "Предпросмотр",
        "showpreview": "Предварительный просмотр",
        "showdiff": "Внесённые изменения",
-       "anoneditwarning": "'''Внимание!''' Вы не авторизовались на сайте.\nВ истории изменений этой страницы будет записан ваш IP-адрес.",
+       "blankarticle": "<strong>Предупреждение:</strong> Страница, которую вы создаёте, пуста.\nЕсли снова нажмёте кнопку «{{int:savearticle}}», страница будет создана без какого-либо содержания.",
+       "anoneditwarning": "<strong>Внимание!</strong> Вы не авторизовались на сайте. Ваш IP-адрес будет публично видимым, если вы будете вносить любые правки. Если вы <strong>[$1 войдёте]</strong> или <strong>[$2 создадите учётную запись]</strong>, правки вместо этого будут связаны с вашим именем пользователя, а также у вас появятся другие преимущества.",
        "anonpreviewwarning": "''Вы не представились системе. Сохранение приведёт к записи вашего IP-адреса в историю изменений страницы.''",
        "missingsummary": "'''Напоминание.''' Вы не дали краткого описания изменений. При повторном нажатии на кнопку «{{int:savearticle}}», ваши изменения будут сохранены без комментария.",
        "missingcommenttext": "Пожалуйста, введите ниже ваше сообщение.",
        "parser-template-recursion-depth-warning": "Превышен предел глубины рекурсии шаблона ($1)",
        "language-converter-depth-warning": "Превышен предел глубины преобразователя языков ($1)",
        "node-count-exceeded-category": "Странице, на которых превышено число узлов",
-       "node-count-exceeded-category-desc": "Ð\9aаÑ\82егоÑ\80иÑ\8f Ð´Ð»Ñ\8f Ñ\81Ñ\82Ñ\80аниÑ\86, Ð½Ð° ÐºÐ¾Ñ\82оÑ\80Ñ\8bÑ\85 Ð¿Ñ\80евÑ\8bÑ\88ено число узлов.",
-       "node-count-exceeded-warning": "Ð\9dа Ñ\81Ñ\82Ñ\80аниÑ\86е Ð¿Ñ\80евÑ\8bÑ\88ено Ñ\87иÑ\81ло Ñ\83злов",
+       "node-count-exceeded-category-desc": "У Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\8b Ð¿Ñ\80евÑ\8bÑ\88ено Ð¼Ð°ÐºÑ\81ималÑ\8cно Ð´Ð¾Ð¿Ñ\83Ñ\81Ñ\82имое число узлов.",
+       "node-count-exceeded-warning": "СÑ\82Ñ\80аниÑ\86а, Ð½Ð° ÐºÐ¾Ñ\82оÑ\80ой Ð¿Ñ\80евÑ\8bÑ\88ено Ð¼Ð°ÐºÑ\81ималÑ\8cно Ð´Ð¾Ð¿Ñ\83Ñ\81Ñ\82имое Ñ\87иÑ\81ло Ñ\83злов.",
        "expansion-depth-exceeded-category": "Страницы с превышением глубины раскрытия",
-       "expansion-depth-exceeded-category-desc": "ЭÑ\82о ÐºÐ°Ñ\82егоÑ\80иÑ\8f Ð´Ð»Ñ\8f Ñ\81Ñ\82Ñ\80аниÑ\86 Ñ\81 Ð¿Ñ\80евÑ\8bÑ\88ением Ð³Ð»Ñ\83бинÑ\8b раскрытия.",
+       "expansion-depth-exceeded-category-desc": "У Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\8b Ð¿Ñ\80евÑ\8bÑ\88ена Ð¼Ð°ÐºÑ\81ималÑ\8cно Ð´Ð¾Ð¿Ñ\83Ñ\81Ñ\82имаÑ\8f Ð³Ð»Ñ\83бина раскрытия.",
        "expansion-depth-exceeded-warning": "На странице превышен предел вложенности",
        "parser-unstrip-loop-warning": "Обнаружен незакрытый pre",
        "parser-unstrip-recursion-limit": "Превышен предел рекурсии ($1)",
        "undo-failure": "Правка не может быть отменена из-за несовместимости промежуточных изменений.",
        "undo-norev": "Правка не может быть отменена, так как её не существует или она была удалена.",
        "undo-nochange": "Правка, похоже, уже была отменена.",
-       "undo-summary": "Отмена правки $1, сделанной {{GENDER:$2|участником|участницей}} [[Special:Contributions/$2|$2]] ([[User talk:$2|обс.]])",
+       "undo-summary": "Отмена правки $1, сделанной {{GENDER:$2|участником|участницей}} [[Special:Contribs/$2|$2]] ([[User talk:$2|обс.]])",
        "undo-summary-username-hidden": "Отмена правки $1, сделанной участником, чьё имя скрыто",
        "cantcreateaccounttitle": "Невозможно создать учётную запись",
        "cantcreateaccount-text": "Создание учётных записей с этого IP-адреса ('''$1''') было заблокировано {{GENDER:$3|участником|участницей|}} [[User:$3|$3]].\n\n$3 {{GENDER:$3|указал|указала}} следующую причину: ''$2''.",
        "rev-deleted-event": "(запись удалена)",
        "rev-deleted-user-contribs": "[имя участника или IP-адрес удалены — правка скрыта со страницы вклада]",
        "rev-deleted-text-permission": "Эта версия страницы была '''удалена'''.\nВозможно, объяснения даны в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале удалений].",
+       "rev-suppressed-text-permission": "Эта версия страницы была <strong>скрыта</strong>.\nОбъяснения удаления приведены в [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале сокрытий].",
        "rev-deleted-text-unhide": "Эта версия страницы была '''удалена'''.\nОбъяснения приведены в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале удалений].\nПри желании вы можете [$1 просмотреть данную версию].",
        "rev-suppressed-text-unhide": "Эта версия страницы была '''скрыта'''.\nОбъяснения приведены в [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале сокрытий].\nПри желании вы можете [$1 просмотреть данную версию].",
        "rev-deleted-text-view": "Эта версия страницы была '''удалена'''.\nВы можете просмотреть её. Объяснения удаления приведены в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале удалений].",
        "revdelete-text-text": "Удалённые версии будут по-прежнему видны в истории страницы, но части их содержимого будут недоступны для участников.",
        "revdelete-text-file": "Удалённые версии файла будут по-прежнему видны в истории страницы, но части их содержимого будут недоступны для участников.",
        "logdelete-text": "Удалённые события в журнале будут по-прежнему видны в журналах, но части их содержимого будут недоступны для участников.",
-       "revdelete-text-others": "Ð\94Ñ\80Ñ\83гие Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñ\81Ñ\82Ñ\80аÑ\82оÑ\80Ñ\8b Ð½Ð° {{grammar:genitive|{{SITENAME}}}} Ð¿Ð¾-пÑ\80ежнемÑ\83 Ð±Ñ\83деÑ\82 Ð¸Ð¼ÐµÑ\82Ñ\8c Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾Ñ\81Ñ\82Ñ\8c Ð´Ð¾Ñ\81Ñ\82Ñ\83па Ðº Ñ\81кÑ\80Ñ\8bÑ\82омÑ\83 Ñ\81одеÑ\80жимомÑ\83 Ð¸ Ñ\81могÑ\83Ñ\82 Ð²Ð¾Ñ\81Ñ\81Ñ\82ановиÑ\82Ñ\8c ÐµÐ³Ð¾ Ñ\81нова Ñ\87еÑ\80ез Ñ\8dÑ\82оÑ\82 Ð¶Ðµ Ð¸Ð½Ñ\82еÑ\80Ñ\84ейÑ\81, если не установлены дополнительные ограничения.",
+       "revdelete-text-others": "Ð\94Ñ\80Ñ\83гие Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñ\81Ñ\82Ñ\80аÑ\82оÑ\80Ñ\8b Ð¿Ð¾-пÑ\80ежнемÑ\83 Ð±Ñ\83дÑ\83Ñ\82 Ð¸Ð¼ÐµÑ\82Ñ\8c Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾Ñ\81Ñ\82Ñ\8c Ð´Ð¾Ñ\81Ñ\82Ñ\83па Ðº Ñ\81кÑ\80Ñ\8bÑ\82омÑ\83 Ñ\81одеÑ\80жимомÑ\83 Ð¸ Ñ\81могÑ\83Ñ\82 Ð²Ð¾Ñ\81Ñ\81Ñ\82ановиÑ\82Ñ\8c ÐµÐ³Ð¾, если не установлены дополнительные ограничения.",
        "revdelete-confirm": "Пожалуйста, подтвердите, что вы действительно желаете совершить это действие, осознаёте последствия, делаете это в соответствии с [[{{MediaWiki:Policy-url}}|правилами]].",
        "revdelete-suppress-text": "Сокрытие может производиться '''только''' в следующих случаях:\n* Потенциально клеветническая информация\n* Неуместная личная информация\n*: ''домашний адрес, номера телефонов, номер паспорта и т. д.''",
        "revdelete-legend": "Установить ограничения:",
        "searchprofile-advanced-tooltip": "Искать в заданных пространствах имён",
        "search-result-size": "$1 ({{PLURAL:$2|$2 слово|$2 слов|$2 слова}})",
        "search-result-category-size": "$1 {{PLURAL:$1|вхождение|вхождений|вхождения}} ($2 {{PLURAL:$2|подкатегория|подкатегорий|подкатегории}}, $3 {{PLURAL:$3|файл|файлов|файла}})",
-       "search-result-score": "Релевантность: $1%.",
        "search-redirect": "(перенаправление с $1)",
        "search-section": "(раздел «$1»)",
        "search-file-match": "(совпадает с содержимым файла)",
        "searchall": "все",
        "showingresults": "Ниже {{PLURAL:$1|1=показан результат|показаны  результаты}} с № '''$2''' и вплоть до № '''$1'''.",
        "showingresultsinrange": "Ниже показано до {{PLURAL:$1|<strong>1</strong> результата|<strong>$1</strong> результатов|<strong>$1</strong> результата}} в диапазоне от <strong>$2</strong> до <strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|1=Результат '''$1''' из '''$3'''|Результаты '''$1—$2''' из '''$3'''}} для «'''$4'''»",
+       "search-showingresults": "{{PLURAL:$4|Результат <strong>$1</strong> из <strong>$3</strong>|Результаты <strong>$1 — $2</strong> из <strong>$3</strong>}}",
        "search-nonefound": "Соответствий запросу не найдено.",
        "powersearch-legend": "Расширенный поиск",
        "powersearch-ns": "Поиск в пространствах имён:",
        "preferences": "Настройки",
        "mypreferences": "Настройки",
        "prefs-edits": "Количество правок:",
-       "prefsnologintext2": "Ð\9dеобÑ\85одимо $1, Ñ\87Ñ\82обÑ\8b Ð¸Ð·Ð¼ÐµÐ½Ñ\8fть настройки.",
+       "prefsnologintext2": "Ð\9fожалÑ\83йÑ\81Ñ\82а, Ð²Ð¾Ð¹Ð´Ð¸Ñ\82е, Ñ\87Ñ\82обÑ\8b Ð¸Ð·Ð¼ÐµÐ½Ð¸ть настройки.",
        "prefs-skin": "Тема оформления",
        "skin-preview": "Предпросмотр",
        "datedefault": "По умолчанию",
        "right-deletedtext": "просмотр удалённого текста и изменений между удалёнными версиями страниц",
        "right-browsearchive": "поиск удалённых страниц",
        "right-undelete": "восстановление страниц",
-       "right-suppressrevision": "просмотр и восстановление скрытых от администраторов версий страниц",
+       "right-suppressrevision": "Просмотр, скрытие и восстановление скрытых версий страниц",
+       "right-viewsuppressed": "Просмотр версий, скрытых от всех участников",
        "right-suppressionlog": "просмотр частных журналов",
        "right-block": "установка ограничений на редактирование для других участников",
        "right-blockemail": "установка запрета на отправку электронной почты",
        "recentchanges-label-bot": "Эта правка сделана ботом",
        "recentchanges-label-unpatrolled": "Эта правка ещё никем не патрулировалась",
        "recentchanges-label-plusminus": "Размер страницы изменился на данное количество байт",
-       "recentchanges-legend-heading": "'''Легенда:'''",
+       "recentchanges-legend-heading": "'''Легенда:&nbsp;'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (см. также [[Special:NewPages|список новых страниц]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Ниже перечислены изменения с <strong>$2</strong> (показано не более <strong>$1</strong>).",
+       "rcnotefrom": "Ниже {{PLURAL:$5|указано изменение|перечислены изменения}} с <strong>$3, $4</strong> (показано не более <strong>$1</strong>).",
        "rclistfrom": "Показать изменения с $3 $2.",
        "rcshowhideminor": "$1 малые правки",
        "rcshowhideminor-show": "Показать",
        "upload-preferred": "Предпочтительные типы файлов: $1.",
        "upload-prohibited": "Запрещённые типы файлов: $1.",
        "uploadlogpage": "Журнал загрузок",
-       "uploadlogpagetext": "Ниже представлен список последних загрузок файлов.\nСм. также [[Special:NewFiles|галерею новых файлов]], где сведения о новых загрузках представлены в более наглядном виде.",
+       "uploadlogpagetext": "Ниже представлен список последних загрузок файлов.\nСм. также [[Special:NewFiles|галерею новых файлов]], где сведения о новых загрузках представлены в более наглядном виде, и [[Special:ListFiles|все загруженные файлы]].",
        "filename": "Имя файла",
        "filedesc": "Краткое описание",
        "fileuploadsummary": "Краткое описание:",
        "uploadwarning": "Предупреждение",
        "uploadwarning-text": "Пожалуйста, измените представленное ниже описание файла и попробуйте ещё раз.",
        "savefile": "Записать файл",
-       "uploadedimage": "загрузил «[[$1]]»",
-       "overwroteimage": "загружена новая версия «[[$1]]»",
        "uploaddisabled": "Загрузка запрещена",
        "copyuploaddisabled": "Загрузка по URL отключена.",
        "uploaddisabledtext": "Загрузка файлов отключена.",
        "license": "Лицензирование:",
        "license-header": "Лицензирование",
        "nolicense": "Отсутствует",
+       "licenses-edit": "Изменить параметры лицензии",
        "license-nopreview": "(Предпросмотр недоступен)",
-       "upload_source_url": " (правильный, публично доступный интернет-адрес)",
-       "upload_source_file": " (файл на вашем компьютере)",
+       "upload_source_url": "(вы выбрали правильный, публично доступный интернет-адрес)",
+       "upload_source_file": "(вы выбрали файл на вашем компьютере)",
+       "listfiles-delete": "удалить",
        "listfiles-summary": "Эта служебная страница показывает все загруженные файлы.",
        "listfiles_search_for": "Поиск по имени файла:",
        "imgfile": "файл",
        "mimesearch": "Поиск по MIME",
        "mimesearch-summary": "Эта страница позволяет фильтровать файлы по их MIME-типу. Формат ввода: типсодержимого/подтип или типсодержимого/*, например <code>image/jpeg</code>.",
        "mimetype": "MIME-тип:",
-       "download": "загрузить",
+       "download": "скачать",
        "unwatchedpages": "Страницы, за которыми никто не следит",
        "listredirects": "Список перенаправлений",
        "listduplicatedfiles": "Список файлов с дубликатами",
        "randomincategory": "Случайная страница в категории",
        "randomincategory-invalidcategory": "Категории «$1» не существует.",
        "randomincategory-nopages": "Нет страниц в категории [[:Category:$1]].",
-       "randomincategory-selectcategory": "Перейти на случайную страницу из категории: $1 $2.",
-       "randomincategory-selectcategory-submit": "Перейти",
+       "randomincategory-category": "Категория:",
+       "randomincategory-legend": "Случайная страница в категории",
        "randomredirect": "Случайное перенаправление",
        "randomredirect-nopages": "Пространство имён «$1» не содержит перенаправлений.",
        "statistics": "Статистика",
        "wantedpages-badtitle": "Ошибочный заголовок в результатах запроса: $1",
        "wantedfiles": "Требуемые файлы",
        "wantedfiletext-cat": "Следующие файлы пытаются использовать, хотя их не существует. В этот список могут ошибочно попасть файлы, находящиеся во внешних хранилищах. Подобные ложные срабатывания будут отмечены <del>зачёркиванием</del>. Кроме того, страницы, содержащие несуществующие файлы, перечислены в [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Следующие файлы используются, но не существуют. Кроме того, страницы, которые ссылаются на эти файлы, не существуют и перечислены на странице [[:$1]].",
        "wantedfiletext-nocat": "Следующие файлы пытаются использовать, хотя их не существует. В этот список могут ошибочно попасть файлы, находящиеся во внешних хранилищах. Подобные ложные срабатывания будут отмечены <del>зачёркиванием</del>.",
+       "wantedfiletext-nocat-noforeign": "Следующие файлы используются, но не существуют.",
        "wantedtemplates": "Требуемые шаблоны",
        "mostlinked": "Страницы, на которые больше всего ссылок",
        "mostlinkedcategories": "Категории, на которые больше всего ссылок",
        "trackingcategories-desc": "Критерий включения в категорию",
        "noindex-category-desc": "Страница не индексируются поисковыми роботами, потому что на ней имеется «волшебное слово» <code><nowiki>__NOINDEX__</nowiki></code>, и она находится в пространстве имён, где разрешён этот флаг).",
        "index-category-desc": "На странице имеется «волшебное слово» __INDEX__ (и страница находится в пространстве имён, где разрешён этот флаг), поэтому она индексируются поисковыми роботами в тех случаях, когда этого обычно не происходит.",
-       "post-expand-template-inclusion-category-desc": "Ð\9fоÑ\81ле Ð¿Ð¾ÐºÐ°Ð·Ð° Ð²Ñ\81еÑ\85 Ñ\88аблонов Ñ\80азмеÑ\80 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\8b Ñ\81Ñ\82анеÑ\82 Ð±Ð¾Ð»Ñ\8cÑ\88е, Ñ\87ем <code>$wgMaxArticleSize</code>, Ð¿Ð¾Ñ\8dÑ\82омÑ\83 Ð½ÐµÐºÐ¾Ñ\82оÑ\80Ñ\8bе Ñ\88аблонÑ\8b не были показаны полностью.",
-       "post-expand-template-argument-category-desc": "Ð\9fоÑ\81ле Ñ\80аÑ\81кÑ\80Ñ\8bÑ\82иÑ\8f Ð°Ñ\80гÑ\83менÑ\82а Ñ\88аблона (Ñ\87Ñ\82о-нибÑ\83дÑ\8c Ð² Ñ\82Ñ\80ойнÑ\8bÑ\85 Ñ\84игÑ\83Ñ\80нÑ\8bÑ\85 Ñ\81кобкаÑ\85, Ð½Ð°Ð¿Ñ\80имеÑ\80, <code>{{{Foo}}})</code>, Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\81Ñ\82анеÑ\82 Ð±Ð¾Ð»Ñ\8cÑ\88е, Ñ\87ем <code>$wgMaxArticleSize</code>.",
+       "post-expand-template-inclusion-category-desc": "РазмеÑ\80 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\8b Ñ\81Ñ\82анеÑ\82 Ð±Ð¾Ð»Ñ\8cÑ\88е <code>$wgMaxArticleSize</code> Ð¿Ð¾Ñ\81ле Ð¿Ð¾ÐºÐ°Ð·Ð° Ð²Ñ\81еÑ\85 Ñ\88аблонов, Ð¿Ð¾Ñ\8dÑ\82омÑ\83 Ð½ÐµÐºÐ¾Ñ\82оÑ\80Ñ\8bе Ð¸Ð· Ð½Ð¸Ñ\85 не были показаны полностью.",
+       "post-expand-template-argument-category-desc": "СÑ\82Ñ\80аниÑ\86а Ñ\81Ñ\82анеÑ\82 Ð±Ð¾Ð»Ñ\8cÑ\88е <code>$wgMaxArticleSize</code> Ð¿Ð¾Ñ\81ле Ñ\80аÑ\81кÑ\80Ñ\8bÑ\82иÑ\8f Ð°Ñ\80гÑ\83менÑ\82а Ñ\88аблона (Ñ\87Ñ\82о-нибÑ\83дÑ\8c Ð² Ñ\82Ñ\80ойнÑ\8bÑ\85 Ñ\84игÑ\83Ñ\80нÑ\8bÑ\85 Ñ\81кобкаÑ\85, Ð½Ð°Ð¿Ñ\80имеÑ\80, <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": "Ð\9aаÑ\82егоÑ\80иÑ\8f Ð´Ð¾Ð±Ð°Ð²Ð»Ñ\8fеÑ\82Ñ\81Ñ\8f, ÐµÑ\81ли Ñ\81траница содержит некорректную файловую ссылку (ссылку на несуществующий файл).",
-       "hidden-category-category-desc": "ЭÑ\82о ÐºÐ°Ñ\82егоÑ\80иÑ\8f Ñ\81 Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð½Ð¾Ð¹ Ð¼ÐµÑ\82кой <code><nowiki>__HIDDENCAT__</nowiki></code> Ð² Ð½ÐµÐ¹, что по умолчанию предотвращает её отображение на страницах в разделе категорий.",
+       "broken-file-category-desc": "Страница содержит некорректную файловую ссылку (ссылку на несуществующий файл).",
+       "hidden-category-category-desc": "ЭÑ\82а ÐºÐ°Ñ\82егоÑ\80иÑ\8f Ñ\81одеÑ\80жиÑ\82 Ð¼ÐµÑ\82кÑ\83 <code><nowiki>__HIDDENCAT__</nowiki></code> Ñ\81одеÑ\80жимом Ñ\81Ñ\82Ñ\80аниÑ\86е, что по умолчанию предотвращает её отображение на страницах в разделе категорий.",
        "trackingcategories-nodesc": "Описание отсутствует.",
        "trackingcategories-disabled": "Категория отключена",
        "mailnologin": "Адрес для отправки отсутствует",
        "mywatchlist": "Список наблюдения",
        "watchlistfor2": "Для $1 $2",
        "nowatchlist": "Ваш список наблюдения пуст.",
-       "watchlistanontext": "Вы должны $1, чтобы просмотреть или отредактировать список наблюдения.",
+       "watchlistanontext": "Вы должны войти, чтобы просмотреть или отредактировать элементы в списке наблюдения.",
        "watchnologin": "Нужно представиться системе",
        "addwatch": "Добавить в список наблюдения",
        "addedwatchtext": "Страница «[[:$1]]» была добавлена в ваш [[Special:Watchlist|список наблюдения]].\nТам будут отмечаться последующие изменения этой страницы, а также связанной с ней страницы обсуждения.",
        "watchlist-details": "В вашем списке наблюдения $1 {{PLURAL:$1|страница|страниц|страницы}}, не считая страниц обсуждений.",
        "wlheader-enotif": "Уведомления по эл. почте включены.",
        "wlheader-showupdated": "Страницы, изменившиеся с вашего последнего их посещения, выделены '''жирным''' шрифтом.",
-       "wlnote2": "Ниже приведены изменения за {{PLURAL:$1|последний час|последние <strong>$1</strong> часов|последние <strong>$1</strong> часа}} на $2 $3.",
+       "wlnote": "Ниже {{PLURAL:$1|показано последнее изменение|показаны <strong>$1</strong> последних изменений|показаны <strong>$1</strong> последние изменения}} за {{PLURAL:$2|последний час|последние <strong>$2</strong> часов|последние <strong>$2</strong> часа}}, по состоянию на $3 $4.",
        "wlshowlast": "Показать за последние $1 часов $2 дней $3",
        "watchlist-options": "Настройки списка наблюдения",
        "watching": "Добавление в список наблюдения…",
        "exbeforeblank": "содержимое до очистки: «$1»",
        "delete-confirm": "$1 — удаление",
        "delete-legend": "Удаление",
-       "historywarning": "'''Внимание:''' эта страница имеет историю изменений приблизительно из $1 {{PLURAL:$1|версии|версий}}:",
+       "historywarning": "<strong>Внимание:</strong> У страницы, которую вы собираетесь удалить, есть история правок, содержащая $1 {{PLURAL:$1|версию|версий}}:",
        "confirmdeletetext": "Вы запросили полное удаление страницы (или изображения) и всей её истории изменений. Пожалуйста, подтвердите, что вы действительно желаете это сделать, понимаете последствия своих действий, и делаете это в соответствии [[{{MediaWiki:Policy-url}}|с правилами]].",
        "actioncomplete": "Действие выполнено",
        "actionfailed": "Действие не выполнено",
        "delete-edit-reasonlist": "Править список причин",
        "delete-toobig": "У этой страницы очень длинная история изменений, более $1 {{PLURAL:$1|версии|версий}}.\nУдаление таких страниц было запрещено во избежание нарушений в работе сайта «{{SITENAME}}».",
        "delete-warning-toobig": "У этой страницы очень длинная история изменений, более $1 {{PLURAL:$1|версии|версий}}.\nЕё удаление может привести к нарушению нормальной работы базы данных сайта «{{SITENAME}}»;\nдействуйте с осторожностью.",
+       "deleteprotected": "Вы не можете удалить эту страницу, поскольку она защищена.",
        "deleting-backlinks-warning": "'''Предупреждение.''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Другие страницы]] ссылаются на страницу, которую вы собираетесь удалить, или содержат её.",
        "rollback": "Откатить изменения",
        "rollback_short": "Откат",
        "autoblockid": "Автоблокировка #$1",
        "block": "Блокировка участника",
        "unblock": "Разблокировка участника",
-       "blockip": "Заблокировать",
+       "blockip": "Заблокировать {{GENDER:$1|участника}}",
        "blockip-legend": "Блокировка участника",
        "blockiptext": "Используйте форму ниже, чтобы заблокировать возможность записи с определённого IP-адреса.\nЭто может быть сделано только для предотвращения вандализма и только в соответствии с [[{{MediaWiki:Policy-url}}|правилами]].\nНиже укажите конкретную причину (к примеру, процитируйте некоторые страницы с признаками вандализма).",
        "ipaddressorusername": "IP-адрес или имя участника:",
        "ipb-unblock-addr": "Разблокировать $1",
        "ipb-unblock": "Разблокировать участника или IP-адрес",
        "ipb-blocklist": "Показать действующие блокировки",
-       "ipb-blocklist-contribs": "Вклад $1",
+       "ipb-blocklist-contribs": "Вклад {{GENDER:$1|$1}}",
        "unblockip": "Разблокировать участника",
        "unblockiptext": "Используйте форму ниже, чтобы восстановить возможность редактирования с ранее заблокированного IP-адреса или учётной записи.",
        "ipusubmit": "Снять эту блокировку",
        "unblocked": "[[User:$1|$1]] {{GENDER:$1|разблокирован|разблокирована}}",
        "unblocked-range": "$1 был разблокирован",
        "unblocked-id": "Блокировка $1 была снята",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] был разблокирован.",
        "blocklist": "Заблокированные участники",
        "ipblocklist": "Заблокированные участники",
        "ipblocklist-legend": "Поиск заблокированного участника",
        "import": "Импортирование страниц",
        "importinterwiki": "Межвики импорт",
        "import-interwiki-text": "Укажите вики и название импортируемой страницы.\nДаты изменений и имена авторов будут сохранены.\nВсе операции межвики импорта регистрируются в [[Special:Log/import|соответствующем журнале]].",
-       "import-interwiki-source": "Вики-источник/страница:",
+       "import-interwiki-sourcewiki": "Исходный вики-проект:",
+       "import-interwiki-sourcepage": "Исходная страница:",
        "import-interwiki-history": "Копировать всю историю изменений этой страницы",
        "import-interwiki-templates": "Включить все шаблоны",
        "import-interwiki-submit": "Импортировать",
        "import-error-create": "Страница «$1» не была импортирована, так как вам не разрешено её создавать.",
        "import-error-interwiki": "Страница «$1» не была импортирована, так как её название зарезервировано для внешних ссылок (интервики).",
        "import-error-special": "Страница «$1» не была импортирована, так как она относится к особому пространству имён, не позволяющему создавать страницы.",
-       "import-error-invalid": "Страница «$1» не была импортирована из-за недопустимого названия.",
+       "import-error-invalid": "Страница «$1» не была импортирована, так как имя, с которым она должна быть импортирована, недопустима в этой вики.",
        "import-error-unserialize": "Версия $2 страницы «$1» не может быть структурирована (десериализована). Получено сообщение, что в этой версии использована модель содержимого $3,  сериализуемая в формате $4.",
        "import-error-bad-location": "Правка $2, использующая модель содержимого $3, не может быть сохранена в «$1» этой вики, потому что эта модель не поддерживается на данной странице.",
        "import-options-wrong": "{{PLURAL:$2|1=Неверная опция|Неверные опции}}: <nowiki>$1</nowiki>",
        "importlogpage": "Журнал импорта",
        "importlogpagetext": "Импортирование администраторами страниц с историей изменений из других вики.",
        "import-logentry-upload": "«[[$1]]» — импорт из файла",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|версия|версий|версии}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|версия импортирована|версий импортировано|версии импортировано}}",
        "import-logentry-interwiki": "«$1» — межвики импорт",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|версия|версий|версии}} из $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|версия импортирована|версий  импортировано|версии импортировано}} из $2",
        "javascripttest": "Проверка JavaScript",
        "javascripttest-title": "Проводится проверка $1",
        "javascripttest-pagetext-noframework": "Эта страница зарезервирована для запуска JavaScript-тестов.",
        "pageinfo-hidden-categories": "{{PLURAL:$1|1=Скрытая категория|Скрытых категорий}} ($1)",
        "pageinfo-templates": "{{PLURAL:$1|1=Шаблон|Шаблонов}} ($1)",
        "pageinfo-transclusions": "{{PLURAL:$1|1=Включаемая страница|Включаемых страниц}} ($1)",
-       "pageinfo-toolboxlink": "Сведения о странице",
+       "pageinfo-toolboxlink": "Сведения о странице",
        "pageinfo-redirectsto": "Перенаправление",
        "pageinfo-redirectsto-info": "сведения",
        "pageinfo-contentpage": "Учитывается счётчиком как содержательная страница",
        "autosumm-replace": "Содержимое страницы заменено на «$1»",
        "autoredircomment": "Перенаправление на [[$1]]",
        "autosumm-new": "Новая страница: «$1»",
+       "autosumm-newblank": "Создана пустая страница",
        "size-bytes": "$1 байт",
        "size-kilobytes": "$1 КБ",
        "size-megabytes": "$1 МБ",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|обсуждение]])",
        "unknown_extension_tag": "Неизвестный тег расширения «$1»",
        "duplicate-defaultsort": "Внимание. Ключ сортировки по умолчанию «$2» переопределяет прежний ключ сортировки по умолчанию «$1».",
+       "duplicate-displaytitle": "<strong>Внимание:</strong> Отображаемое название «$2» переопределяет ранее заданное отображаемое название «$1».",
        "version": "Версия",
        "version-extensions": "Установленные расширения",
        "version-skins": "Установленные темы оформления",
        "logentry-rights-rights": "$1 {{GENDER:$2|изменил|изменила}} членство в группах для $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",
+       "logentry-upload-overwrite": "$1 загрузил{{GENDER:$2||а}} новую версию $3",
+       "logentry-upload-revert": "$1 загрузил{{GENDER:$2||а}} $3",
        "rightsnone": "(нет)",
        "feedback-bugornote": "Если вы готовы подробно описать техническую проблему, пожалуйста, [$1 сообщите об ошибке].\nВ противном случае вы можете использовать данную простую форму. Ваш комментарий будет добавлен на страницу «[$3 $2]» вместе с вашим именем участника и используемым браузером.",
        "feedback-subject": "Тема:",
        "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 Manual:Skin configuration] для получения информации о том, как включить темы оформления и выбрать тему по умолчанию.\n\n\n$ 2\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:* Склонировав один из репозиториев <code>mediawiki/skins/*</code> через git в подпапку <code  dir=\"ltr\">skins/</code> папки, куда установлена MediaWiki.\n: Это не должно навредить вашему репозиторию, если вы MediaWiki-разработчик. См. [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual:Skin configuration] для получения информации о том, как включить темы оформления и выбрать тему по умолчанию.\n; Если вы только что обновили MediaWiki:\n: MediaWiki версии 1.24 и более новых больше не включает автоматически установленные темы (see [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: Skin autodiscovery]).\nВы можете вставить следующие строчки в <code>LocalSettings.php</code>, чтобы включить все установленные темы оформления: \n\n\n<pre dir=\"ltr\">$3</pre>\n\n\n; Если вы только что изменили <code>LocalSettings.php</code>:\n: Перепроверьте названия тем на наличие опечаток.",
+       "default-skin-not-found-no-skins": "Упс! Тема оформления по умолчанию для вашей вики <code>$wgDefaultSkin</code>, <code>$1</code> недоступна.\n\n\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 архив установочных файлов], который содержит несколько тем оформления и расширений. Вы можете скопировать папку <code>skins/</code> из него.\n:* Склонировав один из репозиториев <code>mediawiki/skins/*</code> через git в подпапку <code dir=\"ltr\">skins/</code> папки, куда установлена MediaWiki.\n: Это не должно навредить вашему репозиторию, если вы MediaWiki-разработчик. См. [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual:Skin configuration] для получения информации о том, как включить темы оформления и выбрать тему по умолчанию.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (включено)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''отключено''')"
 }
index f89f060..84d0b22 100644 (file)
        "talkpagelinktext": "діскузія",
        "specialpage": "Шпеціална сторінка",
        "personaltools": "Особны інштрументы",
-       "postcomment": "Нова секція",
        "articlepage": "Посмотрити сторінку",
        "talk": "Діскузія",
        "views": "Перегляды",
        "externaldberror": "Або ся стала хыба екстерной автентіфікачной датабазы, або не маєте дозволено мінити своє екстерне конто.",
        "login": "Приголошіня",
        "nav-login-createaccount": "Приголошіня / створїня конта",
-       "loginprompt": "К приголошіню до {{grammar:2sg|{{SITENAME}}}} мусите мати актівованы cookies.",
        "userlogin": "Приголошіня / створїня конта",
        "userloginnocreate": "Приголошіня",
        "logout": "Одголосити",
        "searchprofile-advanced-tooltip": "Задати просторы назв, де ся мать глядати",
        "search-result-size": "$1 ({{PLURAL:$2|слово|слова|слов}})",
        "search-result-category-size": "{{PLURAL:$1|1 член|$1 члена|$1 членів}} ({{PLURAL:$2|1 підкатеґорія|$2 підкатеґорії|$2 підкатеґорії}}, {{PLURAL:$3|1 файл|$3 файлы|$3 файлів}})",
-       "search-result-score": "Одповідность: $1 %",
        "search-redirect": "(напрямити $1)",
        "search-section": "(секція $1)",
        "search-suggest": "Може сьте мали на мыслї: $1",
        "uploadwarning": "Позірь к наладованю",
        "uploadwarning-text": "Просиме, зміньте опис файлу ниже і спробуйте то знову.",
        "savefile": "Уложыти файл",
-       "uploadedimage": "наладовав \"[[$1]]\"",
-       "overwroteimage": "наладована нова верзія \"[[$1]]\"",
        "uploaddisabled": "Наладовованя файлів заборонене.",
        "copyuploaddisabled": "Наладовованя файлів через URL є выпнуте.",
        "uploaddisabledtext": "Наладовованя файлів є выпнуте.",
        "watchlist-details": "{{PLURAL:$1|Єдна слїдована сторінка|слїдованы сторінкы|слїдованых сторінок}} (не рахувчі діскузны сторінкы).",
        "wlheader-enotif": "Упозорнїня  ел. поштов є запнуте.",
        "wlheader-showupdated": "Сторінкы, котры ся змінили од вашой послїднёй навщівы суть вказаны '''грубо'''",
+       "wlnote": "Ниже є {{PLURAL:$1|остатня зміна|остатнї $1 зміны|остатнїх $1 змін}} за {{PLURAL:$2|остатнїй|остатнї|остатнїх}} <b>$2</b> {{PLURAL:$2|годину|годины|годин}} до do $4, $3.",
        "wlshowlast": "Вказати зміны за послїднїх $1 годин $2 днїв $3",
        "watchlist-options": "Наставлїна списку слїдованых",
        "watching": "Придаваня до списку слїдованя...",
        "duplicate-defaultsort": "Увага: Імпліцітный ключ сортованя (DEFAULTSORTKEY) „$2“ переписує скоре наставлену годноту „$1“.",
        "version": "Верзія",
        "version-extensions": "Наіншталованы росшырїня",
+       "version-skins": "Взгляды",
        "version-specialpages": "Шпеціалны сторінкы",
        "version-parserhooks": "Припойны пункты парсера",
        "version-variables": "Перемінны",
        "version-antispam": "Охрана перед спамом",
-       "version-skins": "Взгляды",
        "version-other": "Інше",
        "version-mediahandlers": "Обслуга медії",
        "version-hooks": "Припойны пункты",
index 37206aa..daff7f8 100644 (file)
 {
-    "@metadata": {
-        "authors": [
-            "D'AroemenenZullenNiVergaan",
-            "Dumitrachi T. Fundu",
-            "Hakka"
-        ]
-    },
-    "tog-underline": "Subliniaḑă ligâtura:",
-    "tog-hideminor": "Ascundeari a alâxiriloru ńiți di-tu nalili alâxiri",
-    "tog-numberheadings": "Numirari automatâ a secțiuniloru",
-    "tog-editondblclick": "Aravdă alâxirea frundzâl'ei ti dublu click (caftă JavaScript)",
-    "underline-always": "Totna",
-    "underline-never": "Vârâoarâ",
-    "sunday": "dumânicâ",
-    "monday": "luni",
-    "tuesday": "marțâ",
-    "wednesday": "ńiercuri",
-    "thursday": "gioi",
-    "friday": "viniri",
-    "saturday": "sâmbâtâ",
-    "january": "Yinaru",
-    "february": "Șcurtu",
-    "march": "Marțu",
-    "april": "Apriiru",
-    "may_long": "Maiu",
-    "june": "Cirișaru",
-    "july": "Alunaru",
-    "august": "Avgustu",
-    "september": "Yizmâciunu",
-    "october": "Sumedru",
-    "november": "Brumaru",
-    "december": "Andreu",
-    "january-gen": "Yinaru",
-    "february-gen": "Șcurtu",
-    "march-gen": "Marțu",
-    "april-gen": "Apriiru",
-    "may-gen": "Maiu",
-    "june-gen": "Cirișaru",
-    "july-gen": "Alunaru",
-    "august-gen": "Avgustu",
-    "september-gen": "Yizmâciunu",
-    "october-gen": "Sumedru",
-    "november-gen": "Brumaru",
-    "december-gen": "Andreu",
-    "jan": "yin",
-    "feb": "șcur",
-    "mar": "mar",
-    "apr": "apr",
-    "may": "mai",
-    "jun": "cir",
-    "jul": "alun",
-    "aug": "avg",
-    "sep": "yiz",
-    "oct": "sum",
-    "nov": "brum",
-    "dec": "andr",
-    "pagecategories": "{{PLURAL:$1|Categorie|Categorii}}",
-    "category_header": "Frânḑâ tu categoria \"$1\"",
-    "hidden-categories": "{{PLURAL:$1|Categorie ascumsâ|Categorii ascumsi}}",
-    "article": "Articolu",
-    "newwindow": "(si discľidi tu unâ nauâ fireastrâ)",
-    "cancel": "Alasã",
-    "moredotdotdot": "Ma multu...",
-    "mytalk": "Zburare-a mea",
-    "navigation": "Navigație",
-    "qbfind": "Caftâ",
-    "qbedit": "Alâxiri",
-    "qbpageoptions": "Aestă frânḑă",
-    "qbmyoptions": "Frânḑili a meali",
-    "vector-action-addsection": "Dimândari nauâ",
-    "vector-view-history": "Veḑ istoricu",
-    "namespaces": "Spațiu di numi",
-    "variants": "Varianti",
-    "tagline": "Di-tu {{SITENAME}}",
-    "help": "Agiutoru",
-    "search": "Câftari",
-    "searchbutton": "Câftari",
-    "go": "Du-vâ",
-    "searcharticle": "Du-vâ",
-    "history_short": "Istoricu",
-    "printableversion": "Verzia ti tipuseare",
-    "permalink": "Ligâturâ permanentâ",
-    "edit": "Alâxire",
-    "delete": "Așcirḑire",
-    "protect": "Apurã",
-    "newpage": "Frânḑâ nauâ",
-    "talkpagelinktext": "Zburari",
-    "talk": "Discusiur",
-    "views": "Videri",
-    "toolbox": "Cutia di hãlate",
-    "otherlanguages": "Pi alte limbe",
-    "jumptonavigation": "Navigatsia",
-    "jumptosearch": "Câftare",
-    "aboutsite": "Tu {{SITENAME}}",
-    "currentevents": "Evenimente di tora",
-    "disclaimers": "Nipricunuschire",
-    "edithelp": "Agiutor ti alãxire",
-    "mainpage": "Prota frânḑâ",
-    "mainpage-description": "Prota frânḑâ",
-    "portal": "Portalu a comunitatiľei",
-    "portal-url": "Proiectu:Portalu a comunitatiľei",
-    "privacy": "Politică di confidențialitate",
-    "youhavenewmessagesmulti": "Aveț năi dimândări pi $1",
-    "editsection": "alâxire",
-    "editold": "Alâxiri",
-    "viewsourceold": "videari izvor",
-    "viewsourcelink": "videari izvor",
-    "editsectionhint": "Alâxire parti: $1",
-    "site-atom-feed": "$1 Atom feed",
-    "red-link-title": "$1 (frânḑa nu easti)",
-    "nstab-main": "Frânḑâ",
-    "nstab-user": "Frânḑâ a utilizatorului",
-    "nstab-special": "Frândzâ specialâ",
-    "nstab-template": "Formatu",
-    "nstab-category": "Categorie",
-    "viewsource": "Videț-u fântânâ",
-    "yourname": "Numa di ufilizitor:",
-    "yourpassword": "Cljao:",
-    "yourpasswordagain": "Bãgats-u cljao iara:",
-    "remembermypassword": "Apurã-u ligãtura-a mea pi compiuterlu aistu (for a maximum of $1 {{PLURAL:$1|day|days}})",
-    "login": "Ligats-vã",
-    "userlogin": "Ligats-vã / Fãtsets Isape",
-    "logout": "Disligats-vã",
-    "userlogout": "Disligats-vã",
-    "notloggedin": "Nu hits ligats",
-    "createaccount": "Fãtsets Isape",
-    "gotaccountlink": "Ligats-vã",
-    "summary": "Rezime:",
-    "minoredit": "Aistã easte alãxire njicã",
-    "watchthis": "Mutrits-u frãndzã aistã",
-    "savearticle": "Avigljats-u frãndzã",
-    "showpreview": "Spuni u-privideare",
-    "showdiff": "Spuni le-alãxirle",
-    "loginreqlink": "Ligats-vã",
-    "lineno": "Linia $1:",
-    "editundo": "arisire",
-    "searchresults": "Rezultate di câftare",
-    "searchresults-title": "Rezultate di câftare ti \"$1\"",
-    "shown-title": "Vedz $1 {{PLURAL:$1|rezultat|rezultate}} pi frândză",
-    "searchprofile-everything": "Tuti",
-    "searchprofile-project-tooltip": "Câftare ti $1",
-    "search-result-size": "$1 ({{PLURAL:$2|1 zbor|$2 zboarâ}})",
-    "search-section": "(partea $1)",
-    "searchall": "tuti",
-    "preferences": "Alidzerle-a meale",
-    "mypreferences": "Alidzerle-a meale",
-    "searchresultshead": "Caftã",
-    "youremail": "E-mail:",
-    "username": "Numa di ufilizitor:",
-    "recentchanges": "Alâxiri",
-    "diff": "dif",
-    "hist": "ist",
-    "show": "Vedz",
-    "recentchangeslinked": "Alãxiri ligate",
-    "recentchangeslinked-feed": "Alãxiri ligate",
-    "recentchangeslinked-toolbox": "Alâxiri ligate",
-    "upload": "Pitritsets file",
-    "uploadbtn": "Pitritsets file",
-    "uploadnologin": "Nu hits ligats",
-    "filedesc": "Rezime",
-    "watchthisupload": "Mutrits-u frãndzã aistã",
-    "file-anchor-link": "Fișier",
-    "randompage": "Frândză di nipandică",
-    "brokenredirects-edit": "Alãxiri",
-    "brokenredirects-delete": "Ashcirdzire",
-    "nbytes": "$1 {{PLURAL:$1|octet|octeți}}",
-    "newpages-username": "Numa di ufilizitor:",
-    "move": "Tradzets",
-    "movethispage": "Tradzets-u frãndza aistã",
-    "booksources-go": "Du-vã",
-    "allpagessubmit": "Du-vã",
-    "watchlist": "Lista-a mea di videare",
-    "mywatchlist": "Lista-a mea di videare",
-    "watchnologin": "Nu hits ligats",
-    "watch": "Videts",
-    "watchthispage": "Mutrits-u frãndzã aistã",
-    "unwatch": "Azãptãsits videare",
-    "prot_1movedto2": "[[$1]] s-trãdzi tu [[$2]]",
-    "restriction-edit": "Alãxiri",
-    "restriction-move": "Tradzets",
-    "undelete-search-submit": "Caftã",
-    "blanknamespace": "(Prota)",
-    "contributions": "Ufilizitor:Contributsiur",
-    "mycontris": "Contributsiile-a meale",
-    "sp-contributions-submit": "Caftã",
-    "whatlinkshere": "Tsi s-leadze cu aistu",
-    "whatlinkshere-page": "Frândză:",
-    "ipbreason": "Itia:",
-    "ipblocklist-submit": "Caftã",
-    "contribslink": "contribuții",
-    "move-page-legend": "Tradzets-u frãndzã",
-    "movearticle": "Tradzets-u frãndzã:",
-    "move-watch": "Mutrits-u frãndzã aistã",
-    "movepagebtn": "Tradzets-u frãndzã",
-    "movereason": "Itia:",
-    "allmessages": "Dimãndãri systemitse",
-    "tooltip-pt-preferences": "Alidzerle-a meale",
-    "tooltip-pt-logout": "Disligats-vã",
-    "tooltip-search": "Câftare tru {{SITENAME}}",
-    "tooltip-p-logo": "Prota frãndzã",
-    "tooltip-n-mainpage": "Vedz prota frândză",
-    "tooltip-t-specialpages": "Unâ listâ di tuti frândzele",
-    "tooltip-ca-nstab-category": "Veḑ categoria",
-    "ilsubmit": "Caftâ",
-    "imgmultigo": "Du-vã!",
-    "table_pager_limit_submit": "Du-vã",
-    "specialpages": "Frândzâ speciale"
+       "@metadata": {
+               "authors": [
+                       "D'AroemenenZullenNiVergaan",
+                       "Dumitrachi T. Fundu",
+                       "Hakka"
+               ]
+       },
+       "tog-underline": "Subliniadzâ ligâtura:",
+       "tog-hideminor": "Ascundi alâxirili minori tu alâxirile proaspite",
+       "tog-hidepatrolled": "Ascundi alâxirili patrulati tu alâxirile proaspite",
+       "tog-newpageshidepatrolled": "Ascundi frândzâli patrulati di-tu lista di frândzâ noi",
+       "tog-extendwatchlist": "Ntindi lista di articoli avinati ca s-u li vedz toati alâxirili adrate, nu mași pe ațeali ma noi",
+       "tog-usenewrc": "Adunâ alâxirili dupu frândzâ anamisa a alâxiriloru proaspite și a listâľei frândzâlor avinati",
+       "tog-numberheadings": "Numirâ automatu secțiunili",
+       "tog-showtoolbar": "Aratâ bara di halati trâ alâxiri",
+       "tog-editondblclick": "Alâxeaști frândzâli pri-tu click duplo",
+       "tog-editsectiononrightclick": "Activeadzâ alâxirea a secțiuniloru pri-tu click ndreapta pi titlu a secțiunâľei",
+       "tog-watchcreations": "Adavgâ frândzâli pi cari li adar și fișierele pi cari li ncari la lista a ńia di frândzâ avinati",
+       "tog-watchdefault": "Adavgâ frândzâli și fișierili pi cari li alâxescu la lista a ńia di avinari",
+       "tog-watchmoves": "Adavgâ frândzâli și fișierili pi cari li dau numâ noao la lista a ńia di avinari",
+       "tog-watchdeletion": "Adavgâ frândzâli și fișierili pi cari li aștergu la lista a ńia di avinari",
+       "tog-watchrollback": "Adavgâ tu lista a ńia di frândzâ avinati ațeali frândzâ cari li turnai la unâ versiuni ma veacľie",
+       "tog-minordefault": "Simneadzâ di-tu ahurhita toati alâxirili câ suntu minori (ńiți)",
+       "tog-previewontop": "Aratâ previzualizarea disuprâ di câsica di alâxiri",
+       "tog-previewonfirst": "Aratâ previzualizarea la prota alâxiri",
+       "tog-enotifwatchlistpages": "Pitreați-ńi unâ carti electronicâ atumțea anda unâ frândzâ icâ unu fișieru di-tu lista a ńia di frândzâ avinati easti alâxitâ",
+       "tog-enotifusertalkpages": "Pitreați-ńi unâ carti electronicâ anda frândza a ńia di muabeț easti alâxitâ",
+       "tog-enotifminoredits": "Pitreați-ńi unâ carti electronicâ ș-canda frândzâ icâ fișieri ľa alâxiri",
+       "tog-enotifrevealaddr": "Lingușeaști-ńi adresa a ńia di carti electronicâ tu mesagili di noauâ",
+       "tog-shownumberswatching": "Aratâ numiru a utilizatorloru cari ti avinu",
+       "tog-oldsig": "Cundiľeauâ di tora:",
+       "tog-fancysig": "Saidiseaști cundiľeaua ca wikitext (fârâ unâ ligâturâ automatâ)",
+       "tog-uselivepreview": "Ufiliseaști previzualizarea tu chiro realu (experimentalu)",
+       "tog-forceeditsummary": "Dzâ-ńi anda mi agârșescu s-fânirusescu alâxirili",
+       "tog-watchlisthideown": "Ascundi alâxirili a meali la lista a ńia di avinari",
+       "tog-watchlisthidebots": "Ascundi alâxirili a boțloru la lista a ńia di avinari",
+       "tog-watchlisthideminor": "Ascundi alâxirili minori (ńiți) a meali la lista a ńia di avinari",
+       "tog-watchlisthideliu": "Ascundi alâxirili adrati di utilizatori ligaț di-tu lista di frândzâ avinati",
+       "tog-watchlisthideanons": "Ascundi alâxirili adrati di utilizatoriľi anonimi di-tu lista di frândzâ avinati",
+       "tog-watchlisthidepatrolled": "Ascundi alâxirili patrulati di-tu lista di frândzâ avinati",
+       "tog-ccmeonemails": "Voi s-așteptu unâ copie a mesagiloru di carti electronicâ pi cari li pitrecu",
+       "tog-diffonly": "Ascundi conținutlu a frândzei sumu dif",
+       "tog-showhiddencats": "Aratâ categoriľi ascumsi",
+       "tog-norollbackdiff": "Ascundi diferența dupu ți s-toarnâ unâ frândzâ",
+       "tog-useeditwarning": "Dzâ-ńi anda alasu unâ frândzâ fârâ s-li pitrecu alâxirili",
+       "tog-prefershttps": "Ufiliseaști daima unâ conexiuni sigurâ anda hiu ligat(â)",
+       "underline-always": "Totna",
+       "underline-never": "Vârnâoarâ",
+       "underline-default": "Standardulu a themâľei icâ a navigatorlui",
+       "editfont-style": "Soea a fontului tu câsica di alâxiri:",
+       "editfont-default": "Standardulu a navigatorlui",
+       "editfont-monospace": "Fontu dipârtatu isea",
+       "editfont-sansserif": "Fontu fârâ serife",
+       "editfont-serif": "Fontu cu serife",
+       "sunday": "dumânicâ",
+       "monday": "luni",
+       "tuesday": "marțâ",
+       "wednesday": "ńiercuri",
+       "thursday": "gioi",
+       "friday": "viniri",
+       "saturday": "sâmbâtâ",
+       "sun": "dum",
+       "mon": "lun",
+       "tue": "mar",
+       "wed": "ńie",
+       "thu": "gio",
+       "fri": "vin",
+       "sat": "sâm",
+       "january": "Yinaru",
+       "february": "Șcurtu",
+       "march": "Marțu",
+       "april": "Apriiru",
+       "may_long": "Maiu",
+       "june": "Cirișaru",
+       "july": "Alunaru",
+       "august": "Avgustu",
+       "september": "Yizmâciunu",
+       "october": "Sumedru",
+       "november": "Brumaru",
+       "december": "Andreu",
+       "january-gen": "Yinaru",
+       "february-gen": "Șcurtu",
+       "march-gen": "Marțu",
+       "april-gen": "Apriiru",
+       "may-gen": "Maiu",
+       "june-gen": "Cirișaru",
+       "july-gen": "Alunaru",
+       "august-gen": "Avgustu",
+       "september-gen": "Yizmâciunu",
+       "october-gen": "Sumedru",
+       "november-gen": "Brumaru",
+       "december-gen": "Andreu",
+       "jan": "Yin",
+       "feb": "Șcur",
+       "mar": "Mar",
+       "apr": "Apr",
+       "may": "Mai",
+       "jun": "Cir",
+       "jul": "Alun",
+       "aug": "Avg",
+       "sep": "Yiz",
+       "oct": "Sum",
+       "nov": "Brum",
+       "dec": "Andr",
+       "january-date": "$1-li di Yinaru",
+       "february-date": "$1-li di Șcurtu",
+       "march-date": "$1-li di Marțu",
+       "april-date": "$1-li di Apriiru",
+       "may-date": "$1-li di Marțu",
+       "june-date": "$1-li di Cirișaru",
+       "july-date": "$1-li di Alunaru",
+       "august-date": "$1-li di Avgustu",
+       "september-date": "$1-li di Yizmâciunu",
+       "october-date": "$1-li di Sumedru",
+       "november-date": "$1-li di Brumaru",
+       "december-date": "$1-li di Andreu",
+       "pagecategories": "{{PLURAL:$1|Categorie|Categorii}}",
+       "category_header": "Frândzâ tu categoria \"$1\"",
+       "subcategories": "Subcategorii",
+       "category-media-header": "Media tu categoria \"$1\"",
+       "category-empty": "<em>Aestâ categorie nu ari tora nițiunu articolu icâ fișieru media.</em>",
+       "hidden-categories": "{{PLURAL:$1|Categorie ascumsâ|Categorii ascumsi}}",
+       "hidden-category-category": "Categorii ascumsi",
+       "category-subcat-count": "{{PLURAL:$2|Categoria conține mași subcategoria aestâ.|Categoria conțini {{PLURAL:$1|aestâ subcategorie|aesti $1 subcategorii}}, di-tu $2.}}",
+       "category-subcat-count-limited": "Această categorie conțini {{PLURAL:$1|subcategorie|$1 subcategorii}}.",
+       "listingcontinuesabbrev": "cont.",
+       "index-category": "Frândzâ indexati",
+       "noindex-category": "Frândzâ neindexati",
+       "broken-file-category": "Frândzâ cu ligâturi invalidi câtră fișieri",
+       "about": "Trâ aestâ",
+       "article": "Articolu",
+       "newwindow": "(si discľidi tu unâ noauâ fireastrâ)",
+       "cancel": "Alasâ",
+       "moredotdotdot": "Ma multu…",
+       "morenotlisted": "Aestâ listâ nu easti completâ (ntreagâ).",
+       "mypage": "Frândzâ",
+       "mytalk": "Muabeț",
+       "anontalk": "Muabeti trâ aestâ adresâ di IP",
+       "navigation": "Navigari",
+       "and": "&#32;și",
+       "qbfind": "Caftâ",
+       "qbbrowse": "Calcâ",
+       "qbedit": "Alâxiri",
+       "qbpageoptions": "Aestâ frândzâ",
+       "qbmyoptions": "Frândzâli a meali",
+       "faq": "Ntribări frecventi",
+       "faqpage": "Proectu:Ntribări frecventi",
+       "actions": "Acțiuni",
+       "namespaces": "Spațiu di numi",
+       "variants": "Varianti",
+       "navigation-heading": "Meniu di navigari",
+       "errorpagetitle": "Eroari (alatus)",
+       "returnto": "Toarnâ-ti $1.",
+       "tagline": "Di-tu {{SITENAME}}",
+       "help": "Agiutoru",
+       "search": "Caftâ",
+       "searchbutton": "Caftâ",
+       "go": "Du-ti",
+       "searcharticle": "Du-ti",
+       "history": "Isturia a frândzâľei",
+       "history_short": "Isturie",
+       "updatedmarker": "alâxitu di canda yinii tu soni",
+       "printableversion": "Versiuni ti tipuseari",
+       "permalink": "Ligâturâ permanentâ",
+       "print": "Tipuseari",
+       "view": "Videari",
+       "view-foreign": "Vedz la $1",
+       "edit": "Alâxire",
+       "edit-local": "Alâxeaști descrierea localâ",
+       "delete": "Așcirḑire",
+       "deletethispage": "Așteardzi frândza",
+       "undeletethispage": "Aflâ frundza aștearsâ",
+       "undelete_short": "Aflâ {{PLURAL:$1|unâ alâxiri aștearsâ|a $1 alâxiri aștearsi|a $1 di alâxiri aștearsi}}",
+       "viewdeleted_short": "Vedz {{PLURAL:$1|unâ alâxiri aștearsâ|$1 (di) alâxiri aștearsi}}",
+       "protect": "Apârâ",
+       "protect_change": "alâxeaști",
+       "protectthispage": "Protejați aestâ frândzâ",
+       "unprotect": "Alâxeaști protecția",
+       "unprotectthispage": "Alâxeaști nivellu di protejari a frândzâľei",
+       "newpage": "Frânḑâ nauâ",
+       "talkpage": "Muabeti trâ aestâ frândzâ",
+       "talkpagelinktext": "Zburari",
+       "specialpage": "Frândzâ specialâ",
+       "personaltools": "Halatili a meali",
+       "articlepage": "Vedz articolu",
+       "talk": "Muabeț",
+       "views": "Videri",
+       "toolbox": "Hâlati",
+       "userpage": "Vedz frândza a utilizatorlui",
+       "projectpage": "Vedz frândza a proectului",
+       "imagepage": "Vedz frândza fișierlui",
+       "mediawikipage": "Vedz frândza dimândăriľei",
+       "templatepage": "Vedz frândza formatlui",
+       "viewhelppage": "Vedz frânzda di agiutoru",
+       "categorypage": "Vedz-u frândza categoriľei",
+       "viewtalkpage": "Vedz muabetea",
+       "otherlanguages": "Pi alanti limbi",
+       "redirectedfrom": "(yinitâ di la $1)",
+       "redirectpagesub": "Frândzâ di redirecționari",
+       "lastmodifiedat": "Aestâ frândzâ fu alâxitâ di-tu soni pi $1, la $2.",
+       "viewcount": "Aestâ frândzâ fu mutritâ di {{PLURAL:$1|mași unâ oarâ|$1 ori}}.",
+       "protectedpage": "Frândzâ protejatâ",
+       "jumpto": "Ansari la:",
+       "jumptonavigation": "navigari",
+       "jumptosearch": "câftari",
+       "view-pool-error": "Ti jali serverili a noastri suntu xanaufilisiti tu aestu chiro.\nCama mulțâ utilizatori câtâpâtsescu s-veadâ aestâ frândzâ.\nVâ pâlâcârsimu s-așteptați unu momentu nainti s-ncârcați aestâ frândzâ diznou.\n\n$1",
+       "generic-pool-error": "Ti jali serverili a noastri suntu xanaufilisiti tu aestu chiro.\nCama mulțâ utilizatori câtâpâtsescu s-veadâ aestâ resursâ.\nVâ pâlâcârsimu s-așteptați unu momentu nainti s-ncârcați aestâ resursâ diznou.",
+       "pool-timeout": "Chirolu trâ aștiptăriľei trâ blocari (ncľideari) d-dusi",
+       "pool-queuefull": "Coada di aștiptari easti mplinâ",
+       "pool-errorunknown": "Eroari (alatusu) nicunuscutâ",
+       "pool-servererror": "Serviciulu di contorizari a rezervâľei nu ma easti disponibilu ($1).",
+       "aboutsite": "Trâ {{SITENAME}}",
+       "aboutpage": "Project:Trâ aestâ",
+       "copyright": "Conținutlu easti disponibilu sum $1, fârâ chirolu tu cari s-specificâ altâ.",
+       "copyrightpage": "{{ns:project}}:Ndirepturi di autoru",
+       "currentevents": "Evenimenti di tora",
+       "currentevents-url": "Project:Cafine",
+       "disclaimers": "Termeni",
+       "disclaimerpage": "Project:Termeni",
+       "edithelp": "Agiutoru trâ alâxiri",
+       "mainpage": "Prota frândzâ",
+       "mainpage-description": "Prota frândzâ",
+       "policy-url": "Project:Politicâ",
+       "portal": "Portalu a comunitatiľei",
+       "portal-url": "Project:Portalu a comunitatiľei",
+       "privacy": "Politicâ di confidențialitati",
+       "privacypage": "Project:Politicâ di confidențialitati",
+       "badaccess": "Eroare (alatusu) permisiuni",
+       "badaccess-group0": "Execuția a acțiuniľei țiruti nu easti permisâ.",
+       "badaccess-groups": "Acțiunea țerută easte mași trâ utilizatorii di-tu {{PLURAL:$2|gruplu|unlu di-tu grupurili}}: $1.",
+       "versionrequired": "Caftâ versiunea $1 MediaWiki",
+       "versionrequiredtext": "Versiunea $1 MediWiki easti câftatâ trâ aestâ frândzâ.\nCaftâ [[Special:Version|versiunea frândzâľei]].",
+       "ok": "Ghini",
+       "retrievedfrom": "Yinitâ di la „$1”",
+       "youhavenewmessages": "Ai $1 ($2).",
+       "youhavenewmessagesfromusers": "Ai $1 di la {{PLURAL:$3|unu altu utilizatoru|$3 utilizatori}} ($2).",
+       "youhavenewmessagesmanyusers": "Ai $1 di la cama mulțâ utilizatori ($2).",
+       "newmessageslinkplural": "{{PLURAL:$1|unâ dimândari noao|999=dimândări noi}}",
+       "newmessagesdifflinkplural": "{{PLURAL:$1|alâxirea di-tu soni|999=alâxirili proaspiti}}",
+       "youhavenewmessagesmulti": "Aveț dimândări noi la $1",
+       "editsection": "alâxire",
+       "editold": "alâxire",
+       "viewsourceold": "vez-u textu",
+       "editlink": "alâxire",
+       "viewsourcelink": "vez-u textu",
+       "editsectionhint": "Alâxeaști secțiunea: $1",
+       "toc": "Conținutu",
+       "showtoc": "aratâ",
+       "hidetoc": "ascundi",
+       "collapsible-collapse": "Apreadunâ",
+       "collapsible-expand": "Tindi",
+       "confirmable-confirm": "Hii sigur{{GENDER:$1||â}}?",
+       "confirmable-yes": "E",
+       "confirmable-no": "Nu",
+       "thisisdeleted": "Vedz icâ adu napoea $1?",
+       "viewdeleted": "Vedz $1?",
+       "restorelink": "Vedz {{PLURAL:$1|unâ alâxiri aștearsâ|$1 (di) alâxiri aștearsi}}",
+       "site-rss-feed": "$1 Abonari RSS",
+       "site-atom-feed": "$1 Abonari Atomu",
+       "page-rss-feed": "„$1” Abonari RSS",
+       "page-atom-feed": "$1 Abonari Atomu",
+       "red-link-title": "$1 (frândza nu easti)",
+       "sort-descending": "Aratâ di la nai ma marli",
+       "sort-ascending": "Aratâ di la nai ma ńițli",
+       "nstab-main": "Frândzâ",
+       "nstab-user": "Frândzâ di utilizatoru",
+       "nstab-media": "Frândzâ media",
+       "nstab-special": "Frândzâ specialâ",
+       "nstab-project": "Proectu",
+       "nstab-image": "Fișieru",
+       "nstab-mediawiki": "Dimândari",
+       "nstab-template": "Formatu",
+       "nstab-help": "Agiutoru",
+       "nstab-category": "Categorie",
+       "nosuchaction": "Aeastâ acțiuni nu easti",
+       "databaseerror-error": "Eroari (alutusu): $1",
+       "readonly": "Baza di dati easti blocatâ (ncľisâ) la nyrâpseari",
+       "viewsource": "Vez-u textu",
+       "yourname": "Numa di utilizatoru:",
+       "userlogin-yourname": "Numa di utilizatoru:",
+       "userlogin-yourname-ph": "Bagâ-u numa a ta di utilizatoru",
+       "createacct-another-username-ph": "Bagâ-u numa di utilizatoru",
+       "yourpassword": "Zboru cľeae:",
+       "yourpasswordagain": "Bagâ-u cľeae diznou:",
+       "remembermypassword": "Țâni minti ligâtura a mea pi browserlu aestu (cheari dupu $1 {{PLURAL:$1|dzuuâ|dzâli}})",
+       "login": "Leagâ-ti",
+       "nav-login-createaccount": "Leagâ-ti / Fă contu (isape)",
+       "userlogin": "Leagâ-ti / Fă contu (isape)",
+       "userloginnocreate": "Leagâ-ti",
+       "logout": "Dizleagâ-ti",
+       "userlogout": "Dizleagâ-ti",
+       "notloggedin": "Nu hii ligatu",
+       "userlogin-noaccount": "N-ai nicâ contu (isape)?",
+       "nologin": "N-ai nicâ contu (isape)? $1.",
+       "nologinlink": "Fă unu utilizatoru a tău tora",
+       "createaccount": "Fă contu (isape)",
+       "gotaccountlink": "Leagâ-ti",
+       "createacct-emailrequired": "Adresâ di carti electronicâ",
+       "createacct-emailoptional": "Adresâ di carti electronicâ (opționalu)",
+       "createacct-email-ph": "Bagâ-u adresa a ta di carti electronicâ",
+       "createacct-another-email-ph": "Bagâ-u adresa di carti electronicâ",
+       "createacct-realname": "Numa realâ (opționalu)",
+       "createaccountreason": "Furńie:",
+       "createacct-reason": "Furńie",
+       "summary": "Rezumatu:",
+       "minoredit": "Aestâ easti unâ alâxiri minorâ (ńicâ)",
+       "watchthis": "Mutrea-u frândzâ aestâ",
+       "savearticle": "Avigľea-u frândzâ",
+       "showpreview": "Previzualizare",
+       "showdiff": "Aratâ alâxirile",
+       "loginreqlink": "leagâ-ti",
+       "lineno": "Linia $1:",
+       "editundo": "turnari",
+       "searchresults": "Rezultatili câftăriľei",
+       "searchresults-title": "Rezultatili câftăriľei trâ „$1”",
+       "shown-title": "Aratâ $1 {{PLURAL:$1|rezultatu|rezultati}} pi frândzâ",
+       "searchprofile-everything": "Tutu",
+       "search-result-size": "$1 ({{PLURAL:$2|1 zboru|$2 zboarâ}})",
+       "search-section": "(secțiunea $1)",
+       "searchall": "tuti",
+       "preferences": "Prutimisiri",
+       "mypreferences": "Prutimisiri",
+       "searchresultshead": "Caftâ",
+       "youremail": "Adresâ di carti electronicâ:",
+       "username": "{{GENDER:$1|Numa di utilizatoru}}:",
+       "recentchanges": "Alâxiri",
+       "diff": "dif",
+       "hist": "ist",
+       "show": "Vedz",
+       "recentchangeslinked": "Alâxiri ligate",
+       "recentchangeslinked-feed": "Alâxiri ligate",
+       "recentchangeslinked-toolbox": "Alâxiri ligate",
+       "upload": "Pitreați fișieru",
+       "uploadbtn": "Pitreați fișieru",
+       "uploadnologin": "Nu hii ligatu",
+       "filedesc": "Rezumatu:",
+       "watchthisupload": "Mutreaști fișierlu aestu",
+       "file-anchor-link": "Fișieru",
+       "randompage": "Frândzâ di nipandicâ",
+       "brokenredirects-edit": "alâxire",
+       "brokenredirects-delete": "așteardziri",
+       "nbytes": "$1 {{PLURAL:$1|octetu|octeți}}",
+       "newpages-username": "Numa di utilizatoru:",
+       "move": "Mutari",
+       "movethispage": "Mutâ frândza aestâ",
+       "booksources-go": "Du-ti",
+       "allpagessubmit": "Du-ti",
+       "watchlist": "Frândzâ avinati",
+       "mywatchlist": "Frândzâ avinati",
+       "watchnologin": "Nu hii ligatu",
+       "watch": "Avinari",
+       "watchthispage": "Mutrea-u frândzâ aestâ",
+       "unwatch": "Scoati di-tu lista di avinari",
+       "prot_1movedto2": "[[$1]] s-mutâ tu [[$2]]",
+       "restriction-edit": "Alâxire",
+       "restriction-move": "Mutari",
+       "undelete-search-submit": "Caftâ",
+       "blanknamespace": "(Prota)",
+       "contributions": "Contribuții {{GENDER:$1|utilizatoru}}",
+       "mycontris": "Contribuții",
+       "sp-contributions-submit": "Caftâ",
+       "whatlinkshere": "Ți s-leadzi cu aestu",
+       "whatlinkshere-page": "Frândzâ:",
+       "ipbreason": "Furńie:",
+       "ipblocklist-submit": "Caftâ",
+       "contribslink": "contribuții",
+       "move-page-legend": "Mutari frândzâ",
+       "movearticle": "Mutari frândzâ",
+       "move-watch": "Mutrea-u frândzâ aestâ",
+       "movepagebtn": "Mutari frândzâ",
+       "movereason": "Furńie:",
+       "allmessages": "Mesagi di systemu",
+       "tooltip-pt-preferences": "Prutimisirili a meali",
+       "tooltip-pt-logout": "Dizleagâ-ti",
+       "tooltip-search": "Câftari tu {{SITENAME}}",
+       "tooltip-p-logo": "Vedz prota frândzâ",
+       "tooltip-n-mainpage": "Vedz prota frândzâ",
+       "tooltip-t-specialpages": "Unâ listâ cu toati frândzili speciali (di soe)",
+       "tooltip-ca-nstab-category": "Vedz-u categoria",
+       "ilsubmit": "Caftâ",
+       "imgmultigo": "Du-ti!",
+       "table_pager_limit_submit": "Du-ti",
+       "specialpages": "Frândzâ speciali"
 }
index c2d4562..3fb3add 100644 (file)
        "talkpagelinktext": "सम्भाषणम्",
        "specialpage": "विशेषपृष्ठम्",
        "personaltools": "वैयक्तिकोपकरणानि",
-       "postcomment": "नवीनः विभागः",
        "articlepage": "लेखः दृश्यताम्",
        "talk": "सम्भाषणम्",
        "views": "मतानि",
        "externaldberror": "दत्तांशे प्रामाणिकताविषयकः (authentication database) दोषः  स्यात् । अथवा स्वस्य बाह्यसदस्यतायां  (external account) परिवर्तनं कर्तुम् अनुमतिः न भवेत् ।",
        "login": "प्रविश्यताम्",
        "nav-login-createaccount": "प्रविश्यताम् / सदस्यता प्राप्यताम्",
-       "loginprompt": "{{SITENAME}} इत्यत्र प्रवेष्टुं ज्ञापकानि (cookies)  समर्थीकरणीयानि ।",
        "userlogin": "प्रविश्यताम् / सदस्यता प्राप्यताम्",
        "userloginnocreate": "प्रविश्यताम्",
        "logout": "निर्गमनम्",
        "searchprofile-advanced-tooltip": "नामाकाशेषु अन्विष्यताम्",
        "search-result-size": "$1 ({{PLURAL:$2|1 शब्दः|$2 शब्दाः}})",
        "search-result-category-size": "{{PLURAL:$1|1 योजकः|$1 योजकाः}} ({{PLURAL:$2|1 उपवर्गः|$2 उपवर्गाः}}, {{PLURAL:$3|1 सञ्चिका|$3 सञ्चिकाः}})",
-       "search-result-score": "सम्बन्धः : $1%",
        "search-redirect": "($1 तः अनुप्रेषितम्)",
        "search-section": "(विभागः $1)",
        "search-file-match": "(सञ्चिकापाठेन सह मेलः अस्ति)",
        "uploadwarning": "उत्तारणस्य पूर्वसूचना ।",
        "uploadwarning-text": "अधो दत्तं सञ्चिकाविवरणं संस्कृत्य पुनः यतताम् ।",
        "savefile": "सञ्चिकां संरक्षतु ।",
-       "uploadedimage": "\"[[$1]]\" उपारोहितानि (uploaded)",
-       "overwroteimage": "\"[[$1]]\" इत्यस्य नूतनावतरणम् उत्तारयतु ।",
        "uploaddisabled": "सक्रियम् उत्तारयतु ।",
        "copyuploaddisabled": "निष्क्रियतः यु.आर्.एल् तः उत्तारयतु  ।",
        "uploaddisabledtext": "उत्तारितसञ्चिकाः निष्क्रियाः ।",
        "watchlist-details": "सम्भाषणपृष्ठानि विहाय {{PLURAL:$1|$1 पृष्ठं|$1 पृष्ठानि}} भवतः/भवत्याः अवेक्षणाऽऽवलिः ।",
        "wlheader-enotif": "विद्युन्मानपत्रस्य सूचनाः सक्रियाः ।",
        "wlheader-showupdated": "भवतः सन्दर्शनस्य पश्चात् परिवर्तितानि पुटानि स्थूलाक्षरैः निर्दिष्टानि ।",
+       "wlnote": "अधस्तात् {{PLURAL:$1|'''1''' परिवर्तनमस्ति|अन्तिमानि '''$1''' परिवर्तनानि सन्ति}},{{PLURAL:$2|गते दिवसे|'''$2''' गतेषु दिवसेषु}}, , $3, $4. इति",
        "wlshowlast": "अन्तिमाः $1 होराः, अन्तिमानि $2 दिनानि $3 दृश्यन्ताम्",
        "watchlist-options": "अवेक्षणाऽऽवलेः विकल्पाः",
        "watching": "निरीक्षते...",
        "import": "पृष्ठानां निर्यातं करोतु",
        "importinterwiki": "ट्रान्स् विकि आयातकाः",
        "import-interwiki-text": "आयातं कर्तुं एकां विकिं एकं पुटं चिनोतु ।  \nपुनरावृत्तीनां दिनाङ्कानि, सम्पादनानि च सुरक्षितानि भविष्यन्ति। \nसर्वाः ट्रान्सविक्यायातक्रियाः नामाभिलेखिताः [[Special:Log/import|आयातसूचिकासु]] स्थापिताः ।",
-       "import-interwiki-source": "स्रोतविकि/पुटम्",
        "import-interwiki-history": "एतत्पुटार्थं सर्वेतिहासान् पुनरावृत्तीः च प्रकृतीः करोतु ।",
        "import-interwiki-templates": "प्राकृतीः अनर्भावयतु ।",
        "import-interwiki-submit": "आयातं करोतु ।",
        "watchlisttools-view": "योग्यपरिवर्तनानि दृश्यन्ताम्",
        "watchlisttools-edit": "अवेक्षणाऽऽवलिः दृश्यतां, सम्पाद्यतां च",
        "watchlisttools-raw": "विवरणरहिता अवलोकनावलिः सम्पाद्यताम्",
-       "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|à¤\85म्भाषणम्]])",
+       "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|सम्भाषणम्]])",
        "unknown_extension_tag": "अज्ञातं वर्तमानसूत्रम् $1",
        "duplicate-defaultsort": "'''पूर्वसूचना''' \"$1\" इति पुरातनं मूलक्रमाङ्कनकुड्मलं विहाय  \"$2\" इति नवीनं मूलक्रमाङ्कनकुण्डलत्वेन स्वयमेव नयति एतत् ।",
        "version": "आवृत्तिः",
        "version-extensions": "अनुस्थापितानि विस्तरणानि ।",
+       "version-skins": "छादन",
        "version-specialpages": "विशेषपृष्ठानि",
        "version-parserhooks": "विन्यासस्य आलम्बः ।",
        "version-variables": "भङ्गुरम्",
        "version-antispam": "अनिष्टस्य अवरोधः ।",
-       "version-skins": "छादन",
        "version-other": "अन्यत्",
        "version-mediahandlers": "माध्यनिर्वाहकाः ।",
        "version-hooks": "आलम्बाः ।",
index 7ffcdeb..63186ce 100644 (file)
@@ -26,6 +26,7 @@
        "tog-watchdefault": "Уларыппыт сирэйдэрбин уонна билэлэрбин кэтээн көрүү тиһигэр киллэрэн ис",
        "tog-watchmoves": "Аатын уларыппыт сирэйдэрбин уонна билэлэрбин кэтээн көрүү тиһигэр киллэрэн ис",
        "tog-watchdeletion": "Соппут сирэйдэрбин уонна билэлэрбин кэтээн көрүү тиһигэр киллэрэн ис",
+       "tog-watchrollback": "Төннөрбүт сирэйдэрбин кэтэбилим тиһигэр киллэрэн ис",
        "tog-minordefault": "Уларытыылары атын этиллибэтэҕинэ кыра уларытыы курдук бэлиэтээ",
        "tog-previewontop": "Хайдах буоларын уларытар түннүк үрдүнэн (иннигэр) көрдөр",
        "tog-previewonfirst": "Хайдах буоларын тута көрдөр",
        "talkpagelinktext": "Ырытыы",
        "specialpage": "Анал сирэй",
        "personaltools": "Тус бэйэ туттар тэриллэрэ",
-       "postcomment": "Саҥа түһүмэх",
        "articlepage": "Ыстатыйаны көр",
        "talk": "Ырытыы",
        "views": "Көрүү",
        "hidetoc": "көрдөрүмэ",
        "collapsible-collapse": "Сабыы",
        "collapsible-expand": "Тэнитии",
+       "confirmable-confirm": "{{GENDER:$1|Бигэргэтэҕин}} дуо?",
+       "confirmable-yes": "Сөп",
+       "confirmable-no": "Суох",
        "thisisdeleted": "$1 көрдөрөбүн эбэтэр хостуубун дуу?",
        "viewdeleted": "$1 көрдөрөбүн?",
        "restorelink": "{{PLURAL:$1|биир сотторуллубут көннөрүү|$1 сотторуллубут көннөрүүлэр}}",
        "databaseerror-text": "Билии олоҕор алҕас таҕыста.\nБырагыраамма алҕаһа буолуон сөп.",
        "databaseerror-textcl": "Билии олоҕор алҕас таҕыста.",
        "databaseerror-query": "Ыйытык: $1",
+       "databaseerror-function": "Функция: $1",
        "databaseerror-error": "Алҕас: $1",
        "laggedslavemode": "Болҕой: Бу сирэй бүтэһик уларытыылара суох буолуон сөп",
        "readonly": "Билии олоҕун уларытар бобуллубут",
        "invalidtitle-knownnamespace": "«$2» аат далыгар маннык тиэкистээх «$3» сатаммат аат",
        "invalidtitle-unknownnamespace": "Биллибэт аат дала $1 нүөмэрдээх, \"$2\" тиэкистээх сатаммат аат",
        "exception-nologin": "Ааккын билиһиннэрбэтэххин",
-       "exception-nologin-text": "Маны көрөргө эбэтэр оҥорорго [[Special:Userlogin|ааккын билиһиннэриэхтээххин]].",
+       "exception-nologin-text": "Маны көрөргө эбэтэр оҥорорго ааккын билиһиннэриэхтээххин.",
        "exception-nologin-text-manual": "Көрөргө эбэтэр оҥорорго маны гыныахтааххын: $1.",
        "virus-badscanner": "Сатаммата. Вирус сканера биллибэтэ: ''$1''",
        "virus-scanfailed": "скан сыыһата (куода $1)",
        "externaldberror": "Тас киирии билиитин олоҕун сыыһата буолла, эбэтэр тас киирии билииҥ олоҕун саҥардар кыаҕыҥ суох.",
        "login": "Киир",
        "nav-login-createaccount": "Киир / бэлиэтэн",
-       "loginprompt": "{{SITENAME}} саайтыгар киирэргэ «cookies» туттары көҥүллээ.",
        "userlogin": "Киир / бэлиэтэн",
        "userloginnocreate": "Киир",
        "logout": "Тахсыы",
        "userlogin-resetlink": "Киирэр тылгын умнубуккун дуо?",
        "userlogin-resetpassword-link": "Киирии тылгын санаттараҕын дуо?",
        "userlogin-helplink2": "Киирэргэ көмө",
-       "userlogin-loggedin": "Маннык аатынан киирбиккин {{GENDER:$1|$1}}.\nАтын аатынан киирэргэ аллара көстөр форманы туһан.",
-       "userlogin-createanother": "Атын аатынан бэлиэтэн",
        "createacct-emailrequired": "Email аадырыс",
        "createacct-emailoptional": "Email аадырыс (булгуччута суох)",
        "createacct-email-ph": "Эл аадырыскын суруй",
        "preview": "Холоон көрүү",
        "showpreview": "Уларытыах иннинэ көрүү",
        "showdiff": "Уларытыылар",
+       "blankarticle": "<strong>Сэрэтии:</strong> Оҥорор сирэйиҥ кураанах.\nБу тимэҕи «{{int:savearticle}}» хос баттаатаххына кураанах сирэй оҥоһуллуо.",
        "anoneditwarning": "'''Болҕой:''' Системаҕа киирбэтэххин. Онон аатыҥ оннугар IP аадаырыһыҥ бу сирэй историятыгар киириэ.",
        "anonpreviewwarning": "''Эн тиһиккэ ааккын эппэттэххин. Уларытыыгын бигэргэттэххинэ IP-аадырыһыҥ сирэй устуоруйатыгар суруллуо.''",
        "missingsummary": "'''Санатыы:''' Уларыппытыҥ кылгас быһаарыытын суруйбатаххын. Уларытыыны бигэргэттэххинэ улартытыыҥ хос быһаарыыта суох барыа.",
        "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": "Сирэй аһыллыытын дириҥэ куоһарыллыбыт.",
        "expansion-depth-exceeded-warning": "Сирэйгэ угуллубут билэлэр аһара элбээбиттэр",
        "parser-unstrip-loop-warning": "Сабыллыбатах pre көһүннэ",
        "parser-unstrip-recursion-limit": "Рекурсия ахсаана таһынан барбыт ($1)",
        "currentrev": "Билиҥҥи барыл",
        "currentrev-asof": "Билиҥҥи торум манна: $1",
        "revisionasof": "$1 барыл",
-       "revision-info": "Ð\92еÑ\80Ñ\81иÑ\8f Ð¾Ñ\82 $1; $2",
+       "revision-info": "Ð\91аÑ\80Ñ\8bл $1; {{GENDER:$6|$2}}$7",
        "previousrevision": "←Инники барыл",
        "nextrevision": "Аныгыскы барыл→",
        "currentrevisionlink": "Билиҥҥи барыл",
        "rev-deleted-event": "(бэлиэтээһин дьайыыта сотулунна)",
        "rev-deleted-user-contribs": "[кыттааччы аата эбэтэр IP-аадырыһа сотуллубуттар — уларытыы көстүбэт оҥоһуллубут]",
        "rev-deleted-text-permission": "Сирэй бу барыла '''сотуллубут'''.\nБыһаарыыта  [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} манна] баар буолуон сөп.",
+       "rev-suppressed-text-permission": "Сирэй бу барыла <strong>кистэммит</strong>.\nБыһаарыы [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} кистээһин сурунаалыгар] баар.",
        "rev-deleted-text-unhide": "Сирэй ити барыла '''сотуллубут'''.\nБаҕар ол туһунан [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} сотуу сурунаалыгар] баара буолуо.\nОл да буоллар эн дьаһабыл буоларыҥ быһыытынан [$1 барылы көрүөххүн сөп].",
        "rev-suppressed-text-unhide": "Сирэй бу барыла '''кистэммит'''.\nБыһаарыы баҕара [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} кистээһин сурунаалыгар] баара буолуо.\nЭн дьаһабыл буоларыҥ быһыытынан [ол барылы көрүөххүн $1] сөп.",
        "rev-deleted-text-view": "Ыстатыйа бу барыла '''сотуллубут'''.\nОл эрэн ону көрүөххүн сөп.\nТоҕо сотуллубутун быһаарыыта [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} манна] баар буолуон сөп.",
        "revdelete-text-text": "Сотуллубут барыллар уруккутун курдук сирэй устуоруйатыгар көстүөхтэрэ, ол эрэн иһинээҕитэ сорҕото киэҥ эйгэҕэ көрдөрүллүө суоҕа.",
        "revdelete-text-file": "Билэ сотуллубут барыллара уруккутун курдук сирэй устуоруйатыгар көстүөхтэрэ, ол эрэн иһинээҕитэ сорҕото киэҥ эйгэҕэ көрдөрүллүө суоҕа.",
        "logdelete-text": "Сурунаалтан сотуллубут уруккутун курдук сурунаал устуоруйатыгар көстүөҕэ, ол эрэн иһинээҕитин сорҕото киэҥ эйгэҕэ көрдөрүллүө суоҕа.",
-       "revdelete-text-others": "Өскөтүн эбии хааччах турбатах буоллаҕына, {{grammar:genitive|{{SITENAME}}}} атын дьаһабыллара урукку курдук кистэммити көрөр уонна чөлүгэр түһэрэр кыахтаахтар.",
+       "revdelete-text-others": "Өскөтүн эбии хааччах турбатах буоллаҕына, атын дьаһабыллар урукку курдук кистэммити көрөр уонна чөлүгэр түһэрэр кыахтаахтар.",
        "revdelete-confirm": "Бука диэн кырдьык бу дьайыыны онороргун, содула туох буоларын өйдүүргүн уонна [[{{MediaWiki:Policy-url}}|сиэри]] тутуһаргын бигэргэт.",
        "revdelete-suppress-text": "Кистээһин маннык түбэлтэлэргэ '''эрэ''' оҥоһуллар:\n* Баһааҕырдар буолуон сөптөөҕү суруйуу\n* Киһи бэйэтин туһунан тоҕооһо суохтук суруллубут буоллаҕына\n*: <em>дьиэтин аадырыһа, төлөппүөннэрин нүөмэрэ, пааспарын нүөмэрэ уо.д.а.</em>",
        "revdelete-legend": "Хааччахтары туруоруу:",
        "searchprofile-advanced-tooltip": "Этиллибит аат далларыгар көрдөөһүн",
        "search-result-size": "$1 ({{PLURAL:$2|1 тыл|$2 тыл}})",
        "search-result-category-size": "{{PLURAL:$1|$1 элэмиэн|$1 элэмиэннэр}} ({{PLURAL:$2|$2 субкатегория|$2 субкатегориялар}}, {{PLURAL:$3|$3 билэ|$3 билэлэр}})",
-       "search-result-score": "Релевантноһа: $1%",
        "search-redirect": "(утаарыы $1)",
        "search-section": "($1 сиэксийэ)",
        "search-file-match": "(билэ иһинээҕитин кытта сөп түбэһэр)",
        "uploadwarning": "Сэрэтии",
        "uploadwarning-text": "Бука диэн аллара баар билэ туһунан суругу уларыт уонна өссө хатылаа.",
        "savefile": "Билэни суруттарыы",
-       "uploadedimage": "суруттарылынна \"[[$1]]\"",
-       "overwroteimage": "\"[[$1]]\" киллэриллибит саҥа торума",
        "uploaddisabled": "Суруттарыы бобуллубут",
        "copyuploaddisabled": "URL көмөтүнэн хачайдыыр кыах араарыллыбыт.",
        "uploaddisabledtext": "Билэлэри суруттарар көҥүллэммэт.",
        "randomincategory": "Категория түбэспиччэ ыстатыйата",
        "randomincategory-invalidcategory": "\"$1\" диэн категория суох эбит.",
        "randomincategory-nopages": "Бу категорияҕа [[:Category:$1]] киирэр ыстатыйалар суохтар.",
-       "randomincategory-selectcategory": "Категория түбэспиччэ сирэйигэр көс: $1 $2.",
-       "randomincategory-selectcategory-submit": "Көс",
        "randomredirect": "Түбэспиччэ утаарыы",
        "randomredirect-nopages": "Бу аат далыгар($1) көһөрөр ыйынньыктар суохтар.",
        "statistics": "Статистика",
        "watchlist-details": "Ырытыы сирэйдэрин аахпатахха {{PLURAL:$1|$1 сирэйи кэтиигин|$1 сирэй эн кэтэбилгэр сылдьар}}.",
        "wlheader-enotif": "Эл. почтанан биллэрии холбоммут.",
        "wlheader-showupdated": "Бүтэһик киирииҥ кэннэ уларыйбыт сирэйдэр '''модьу''' бичигинэн бэлиэтэннилэр.",
-       "wlnote2": "Манна {{PLURAL:$1|кэнники чааска|кэнники <strong>$1</strong> чааска}} оҥоһуллубут уларытыылар көстөллөр, $2 $3.",
+       "wlnote": "Манна кэлиҥҥи {{PLURAL:$2|чаас|'''$2''' чаас}} иһигэр оҥоһуллубут бүтэһик $1 уларытыы көрдөрүлүннэ, бу кэмҥэ туругунан $3 $4.",
        "wlshowlast": "бүтэһик $1 чааска $2 күҥҥэ $3 көрдөр",
        "watchlist-options": "Кэтээн көрүү туруоруутун уларытыы",
        "watching": "Кэтээ...",
        "import": "Сирэйдэри импортааһын",
        "importinterwiki": "Биики ыккардынааҕы импорт",
        "import-interwiki-text": "Биикини уонна импортанар сирэй аатын киллэр.\nУларытыылар күннэрэ-ыйдара уонна аапптардар ааттара оннуларынан хаалыахтара.\nБиики ыккардынааҕы импорт дьайыылара [[Special:Log/import|аналлаах сурунаалга]] суруллаллар.",
-       "import-interwiki-source": "Ылыллыбыт биикитэ/сирэйэ:",
        "import-interwiki-history": "Сирэй туох баар историятын көһөрөргө",
        "import-interwiki-templates": "Бары халыыптары киллэр",
        "import-interwiki-submit": "Импортаа",
        "duplicate-defaultsort": "Болҕой: Наардааһын «$2» күлүүһэ урукку «$1» күлүүһү сабар (Ключ сортировки переопределяет прежний ключ).",
        "version": "MediaWiki барыла (биэрсийэтэ)",
        "version-extensions": "Туруоруллубут расширениялар",
+       "version-skins": "Тас көстүү барыллара",
        "version-specialpages": "Аналлаах сирэйдэр",
        "version-parserhooks": "синтаксическай анализатор перехватчиктара",
        "version-variables": "Уларыйар дааннайдар (переменнайдар)",
        "version-antispam": "Спаамтан көмүскэнии",
-       "version-skins": "Тас көстүү барыллара",
        "version-other": "Атын",
        "version-mediahandlers": "Медиа уларытааччылар",
        "version-hooks": "Перехватчиктар",
index dc1661a..0811190 100644 (file)
        "talkpagelinktext": "Ro̠ṛme",
        "specialpage": "Osokayteaḱ sakam",
        "personaltools": "Nijaḱ jontropạti",
-       "postcomment": "Nãwã pahaṭa",
        "articlepage": "Menaḱ sakam uduḱme",
        "talk": "Galmarao",
        "views": "Ñel koyoḱ",
        "externaldberror": "Hoe daṛeyaḱa jahan bahre reaḱ jacaeaḱ ḍaṭabes vul hoeakana se amaḱ bahre reaḱ ekaunṭ do nahaḱ halot aguire ạidạri bạnuḱa.",
        "login": "bolok' duar",
        "nav-login-createaccount": "Boloḱ́ duạr / ekaunt tearme",
-       "loginprompt": "{{SITENAME}}-re boloḱem meneḱ khan amaḱ sendrare kuki kạmi ehoṕ hoyoḱtama.",
        "userlogin": "Bhitri bolon / ekaunṭ tear",
        "userloginnocreate": "Bhitri bolo",
        "logout": "Bahre oḍoń",
        "filedesc": "Guṭ katha",
        "fileuploadsummary": "Guṭ katha",
        "savefile": "Rẽt rukhiyaymẽ",
-       "uploadedimage": "\"[[$1]]\" rakaṕ huyena",
        "upload-description": "Rẽt reaḱ jạṛ",
        "watchthisupload": "Noa rẽt ńelmẽ",
        "upload-file-error": "Bhitri reaḱ bhul",
index b2c68bb..b63d78c 100644 (file)
@@ -7,54 +7,59 @@
                        "Node ue",
                        "לערי ריינהארט",
                        "아라",
-                       "Via maxima"
+                       "Via maxima",
+                       "Uharteko",
+                       "Taxandru"
                ]
        },
-       "tog-underline": "Sutalìnea is cullegamentos",
+       "tog-underline": "Sutalìnia sos ligòngios",
        "tog-hideminor": "Cua is acontzos minores in sa pàgina de is ùrtimas mudàntzias",
-       "tog-hidepatrolled": "Cua is acontzos verificados in is ùrtimas mudàntzias",
-       "tog-newpageshidepatrolled": "Cua is pàginas verificadas dae sa lista de is pàginas noas",
-       "tog-extendwatchlist": "Ammània sa watchlist pro ammustrare totu is mudàntzias, non feti is prus reghentes",
-       "tog-usenewrc": "Poni a pari is mudàntzias de dònnia pàgina in is ùrtimas mudàntzias e in watchlist",
-       "tog-numberheadings": "Auto-numeratzione de is tìtulos",
-       "tog-showtoolbar": "Amosta s'amusta de is ainas pro is acontzos",
-       "tog-editondblclick": "Acontza pàginas cun dòpiu click",
-       "tog-editsectiononrightclick": "Abilita s'acontzu de is setziones cun click a dereta in is tìtulos de is setziones",
-       "tog-watchcreations": "Aciungi is pàginas chi apo creadu e is files chi apo carrigau a sa watchlist mea",
-       "tog-watchdefault": "Aciungi pàginas e files chi apo acontzadu a sa watchlist mea",
-       "tog-watchmoves": "Aciungi pàginas e files chi apo mòvidu a sa watchlist mea",
-       "tog-watchdeletion": "Aciungi pàginas e files chi apo fuliadu a sa watchlist mea",
-       "tog-minordefault": "Signa totu is acontzos comente minores pro difetu",
-       "tog-previewontop": "Ammustra s'antiprima a subra sa casella de acontzu e no a suta",
-       "tog-previewonfirst": "Ammustra s'antiprima pro su primu acontzu",
-       "tog-enotifwatchlistpages": "Spedi·mi una missada eletrònica cando una pàgina o file de sa watchlist mea est acontzada",
-       "tog-enotifusertalkpages": "Spedi·mi una missada eletrònica cando sa pàgina de is cuntierras mias est acontzada",
-       "tog-enotifminoredits": "Spedi·mi una missada eletrònica fintzas pro is acontzos minores de is pàginas e files",
-       "tog-enotifrevealaddr": "Faghe schire s'indiritzu e-mail miu in is notìficas de is e-mails",
-       "tog-shownumberswatching": "Ammustra su nùmeru de is usuàrios ca sunt ponende ogru a sa pàgina",
+       "tog-hidepatrolled": "Cua is mudas verificadas in is ùrtimos càmbios",
+       "tog-newpageshidepatrolled": "Cua sas pàginas verificadas dae sa lista de sas pàginas noas",
+       "tog-extendwatchlist": "Ammània sa watchlist pro ammustrare totu sos càmbios, non sos prus reghentes ebbia",
+       "tog-usenewrc": "Pone in pare sos càmbios de cada pàgina in sos ùrtimos càmbios e in sa watchlist",
+       "tog-numberheadings": "Auto-numeratzione de sos tìtulos",
+       "tog-showtoolbar": "Ammustra sa mustra de sa barra de sas ainas",
+       "tog-editondblclick": "Càmbia pàginas cun duos click",
+       "tog-editsectiononrightclick": "Abìlita su càmbiu de sas setziones cun click de dereta in sos tìtulos de sas setziones",
+       "tog-watchcreations": "Agiunghe sas pàginas chi apo creadu e sos documentos chi apo carrigadu in sa watchlist mea",
+       "tog-watchdefault": "Agiunghe pàginas e documentos chi apo cambiadu in sa watchlist mea",
+       "tog-watchmoves": "Agiunghe pàginas e documentos chi apo mòvidu in sa watchlist mea",
+       "tog-watchdeletion": "Agiunghe pàginas e documentos chi apo fuliadu in sa watchlist mea",
+       "tog-watchrollback": "Pone is pàginas innue apo fatu su rollback in is pàginas annotadas",
+       "tog-minordefault": "Marca comente minores pro difetu totu sos càmbios",
+       "tog-previewontop": "Ammustra s'anteprima in subra de sa casella de càmbiu e no in suta",
+       "tog-previewonfirst": "Ammustra s'anteprima pro sa prima muda",
+       "tog-enotifwatchlistpages": "Imbia·mi una post.el. cando b'at àpidu unu càmbiu in una pàgina o in unu documentu de sa watchlist mea",
+       "tog-enotifusertalkpages": "Imbia·mi una post.el. cando sa pàgina de sas cuntierras meas est cambiada",
+       "tog-enotifminoredits": "Imbia·mi una post.el. fintzas pro sos càmbios minores de sas pàginas e documentos",
+       "tog-enotifrevealaddr": "Faghe ischire s'indiritzu de sa post.el. mea in sas notìficas de sa post.els",
+       "tog-shownumberswatching": "Ammustra su nùmeru de is impitadores chi ant annotadu sa pàgina",
        "tog-oldsig": "Firma atuale:",
-       "tog-fancysig": "Trata sa firma comente unu testu wiki (chentza cullegamentos automaticos)",
-       "tog-uselivepreview": "Imprea sa funtzione \"live preview\" (sperimentale)",
-       "tog-forceeditsummary": "Avertimì si su campu ogetu est buidu",
-       "tog-watchlisthideown": "Cua is acontzos meos dae sa watclist",
-       "tog-watchlisthidebots": "Cua is acontzos de is bots dae sa watchlist",
-       "tog-watchlisthideminor": "Cua is acontzos minores dae sa watchlist",
-       "tog-watchlisthideliu": "Cua is acontzos de is usuàrios intraus dae sa watchlist",
-       "tog-watchlisthideanons": "Cua is acontzos de is usuàrios anonimus dae sa watchlist",
-       "tog-watchlisthidepatrolled": "Cua acontzos verificados dae sa watchlist",
-       "tog-ccmeonemails": "Spedi·mi is còpias de is e-mails ca spedu a is àteros usuàrios",
-       "tog-showhiddencats": "Ammustra is categorias cuadas",
-       "tog-useeditwarning": "Amonestamì si lassu una pagina cun mudantzias chena de sarvai.",
-       "tog-prefershttps": "Impera sempiri una linia segura candu fatzu s'intrada.",
+       "tog-fancysig": "Trata sa firma comente unu testu wiki (sena ligàmenes automàticos)",
+       "tog-uselivepreview": "Imprea sa funtzione \"anteprima bia\" (isperimentale)",
+       "tog-forceeditsummary": "Averte·mi si su campu ogetu est bòidu",
+       "tog-watchlisthideown": "Cua sas mudas meas dae sa watclist",
+       "tog-watchlisthidebots": "Cua sas mudas de sos bots dae sa watchlist",
+       "tog-watchlisthideminor": "Cua sos càmbios minores dae sa watchlist",
+       "tog-watchlisthideliu": "Cua is càmbios de is impitadores identificados dae sa lista de pàginas annotadas",
+       "tog-watchlisthideanons": "Cua is càmbios de is impitadores anònimos dae sa lista de pàginas annotadas",
+       "tog-watchlisthidepatrolled": "Cua mudas verificadas dae sa watchlist",
+       "tog-ccmeonemails": "Imbia·mi sas còpias de is emails chi imbio a is àteros impitadores",
+       "tog-diffonly": "No ammustras su cuntènnidu de sa pàgina a pustis de sa bisura de is diferèntzias",
+       "tog-showhiddencats": "Ammustra sas categorias cuadas",
+       "tog-norollbackdiff": "Cua sa bisura de is diferèntzias a pustis de su rollback",
+       "tog-useeditwarning": "Averte·mi si lassu una pàgina cun càmbios sena de sarbare",
+       "tog-prefershttps": "Imprea semper una lìnia segura candu fatzo s'intrada.",
        "underline-always": "Semper",
        "underline-never": "Mai",
-       "underline-default": "Definiduras dae su browser tuo",
-       "editfont-style": "Stile lìteras in s'àrea de acontzu:",
-       "editfont-default": "Definidu dae su browser",
-       "editfont-monospace": "Font monospàtziu",
-       "editfont-sansserif": "Font sans-serif",
-       "editfont-serif": "Font serif",
-       "sunday": "Domìnigu",
+       "underline-default": "Definitziones dae su navigadore tuo",
+       "editfont-style": "Istile de sos caràteres in s'àrea de càmbiu:",
+       "editfont-default": "Definidu dae su navigadore",
+       "editfont-monospace": "Caràtere monospàtziu",
+       "editfont-sansserif": "Caràtere sena gràtzias",
+       "editfont-serif": "Caràtere cun gràtzias",
+       "sunday": "Domìniga",
        "monday": "Lunis",
        "tuesday": "Martis",
        "wednesday": "Mèrcuris",
        "aug": "Aus",
        "sep": "Cab",
        "oct": "Stg",
-       "nov": "Std",
+       "nov": "Sta",
        "dec": "Nad",
-       "january-date": "Gennàrgiu $1",
-       "february-date": "Friàrgiu $1",
+       "january-date": "Ghennàrgiu $1",
+       "february-date": "Freàrgiu $1",
        "march-date": "Martzu $1",
-       "april-date": "Abrili $1",
+       "april-date": "Abrile $1",
        "may-date": "Maju $1",
        "june-date": "Làmpadas $1",
        "july-date": "Trìulas $1",
        "august-date": "Austu $1",
        "september-date": "Cabudanni $1",
-       "october-date": "Santuaine $1",
-       "november-date": "Onniassantu $1",
-       "december-date": "Mesi de Nadali $1",
+       "october-date": "Santugaine $1",
+       "november-date": "Santandria $1",
+       "december-date": "Nadale $1",
        "pagecategories": "{{PLURAL:$1|Categoria|Categorias}}",
        "category_header": "Pàginas in sa categoria \"$1\"",
        "subcategories": "Subcategorias",
        "category-media-header": "Mèdios in sa categoria \"$1\"",
-       "category-empty": "''In custa categoria non bi est peruna pàgina o mèdiu.''",
+       "category-empty": "''In custa categoria non ddu at peruna pàgina o documentu multimediale.''",
        "hidden-categories": "{{PLURAL:$1|Categoria cuada|Categorias cuadas}}",
        "hidden-category-category": "Categorias cuadas",
-       "category-subcat-count": "{{PLURAL:$2|Custa categoria cuntenet un'ùnica subcategoria ammustrada a suta.|Custa categoria cuntenet {{PLURAL:$1|sa subcategoria indicada|$1 subcategorias indicadas}} a suta, de $2 totales.}}",
-       "category-subcat-count-limited": "Custa categoria tenet {{PLURAL:$1|una subcategoria, ammustrada|$1 subcategorias, ammustradas}} a suta.",
-       "category-article-count": "{{PLURAL:$2|Custa categoria cuntènnit isceti sa pàgina chi sighit.|Custa categoria cuntènnit {{PLURAL:$1|sa pàgina indicada|is $1 pàginas indicadas}} a suta, dae unu totale de $2.}}",
-       "category-article-count-limited": "{{PLURAL:$1|Sa pàgina ki sighit est|Is $1 pàginas ki sighint sunt}} in custa categoria.",
-       "category-file-count": "{{PLURAL:$2|Custa categoria cuntenet feti su file ki sighit.|{{PLURAL:$1|Su file ki sighit est|Is $1 files ki sighint sunt}} in custa categoria, dae $2 totales.}}",
-       "category-file-count-limited": "{{PLURAL:$1|Su file ki sighit est|Is $1 files ki sighint sunt}} in sa categoria currente.",
+       "category-subcat-count": "{{PLURAL:$2|Custa categoria cuntenet un'ùnica subcategoria ammustrada in suta.|Custa categoria cuntenet {{PLURAL:$1|sa subcategoria indicada|$1 subcategorias indicadas}} in suta, dae $2 totales.}}",
+       "category-subcat-count-limited": "Custa categoria tenet {{PLURAL:$1|una subcategoria, ammustrada|$1 subcategorias, ammustradas}} in suta.",
+       "category-article-count": "{{PLURAL:$2|Custa categoria cuntenet feti sa pàgina chi sighit.|Custa categoria cuntenet {{PLURAL:$1|sa pàgina indicada|is $1 pàginas indicadas}} in suta, dae unu totale de $2.}}",
+       "category-article-count-limited": "{{PLURAL:$1|Sa pàgina chi sighit est|Is $1 pàginas chi sighint sunt}} in custa categoria.",
+       "category-file-count": "{{PLURAL:$2|Custa categoria cuntenet feti su documentu chi sighit.|{{PLURAL:$1|Su documentu chi sighit est|Is $1 documentos chi sighint sunt}} in custa categoria, dae $2 totales.}}",
+       "category-file-count-limited": "{{PLURAL:$1|Su documentu chi sighit est|Is $1 documentos chi sighint sunt}} in sa categoria currente.",
        "listingcontinuesabbrev": "sighit",
-       "index-category": "Pàginas indicizadas",
-       "noindex-category": "Pàginas no indicitzadas",
+       "index-category": "Pàginas inditzizadas",
+       "noindex-category": "Pàginas no inditzitzadas",
+       "broken-file-category": "Pàginas cun ligàmenes a sos documentos non funtzionantes",
        "about": "A propòsitu de",
        "article": "Artìculu",
-       "newwindow": "(aberit in una bentana noa)",
+       "newwindow": "(aberret in una bentana noa)",
        "cancel": "Burra",
        "moredotdotdot": "Àteru…",
        "morenotlisted": "Sa lista no est cumpreta",
        "mypage": "Pàgina",
-       "mytalk": "Cuntierras meas",
-       "anontalk": "Cuntierras pro custu IP",
-       "navigation": "Navigadura",
+       "mytalk": "Cuntierras mias",
+       "anontalk": "Cuntierras pro custu indiritzu IP",
+       "navigation": "Navigatzione",
        "and": "&#32;e",
        "qbfind": "Busca",
        "qbbrowse": "Nàviga",
-       "qbedit": "Acontza",
+       "qbedit": "Càmbia",
        "qbpageoptions": "Possibilidades de sa pàgina",
-       "qbmyoptions": "Is preferèntzias meas",
-       "faq": "Pregontas/Respostas (FAQ)",
+       "qbmyoptions": "Sas preferèntzias meas",
+       "faq": "Pregontas fitianas",
        "faqpage": "Project:FAQ",
        "actions": "Atziones",
        "namespaces": "Nùmene-logos",
        "variants": "Variantes",
-       "navigation-heading": "Menu po nàvigu",
+       "navigation-heading": "Menu pro navigatzione",
        "errorpagetitle": "Faddina",
        "returnto": "Torra a $1.",
        "tagline": "Dae {{SITENAME}}",
        "searcharticle": "Bae",
        "history": "Istòria de sa pàgina",
        "history_short": "Istòria",
-       "updatedmarker": "agiornada dae s'ùrtima bìsita mia",
+       "updatedmarker": "atualizada dae s'ùrtima vìsita mea",
        "printableversion": "Versione de imprenta",
-       "permalink": "Acàpiu fitianu",
+       "permalink": "Ligòngiu permanente",
        "print": "Imprenta",
-       "view": "Amosta",
-       "view-foreign": "Amosta in $1",
-       "edit": "Acontza",
-       "edit-local": "Acontza sa descridura locali",
+       "view": "Ammustra",
+       "view-foreign": "Ammustra in $1",
+       "edit": "Càmbia",
+       "edit-local": "Càmbia sa descritzione locale",
        "create": "Crea",
-       "create-local": "Aciungi descridura locali",
-       "editthispage": "Acontza custa pàgina",
+       "create-local": "Agiunghe descritzione locale",
+       "editthispage": "Càmbia custa pàgina",
        "create-this-page": "Crea custa pàgina",
-       "delete": "Fùlia",
-       "deletethispage": "Fùlia custa pàgina",
-       "undeletethispage": "Torrandi custa pàgina",
-       "undelete_short": "Restaurare {{PLURAL:$1|un acontzu|$1 acontzos}}",
-       "viewdeleted_short": "Amosta {{PLURAL:$1|unu acontzu burradu|$1 acontzos burrados}}",
-       "protect": "Ampara",
-       "protect_change": "mudàntzia",
+       "delete": "Burra",
+       "deletethispage": "Burra custa pàgina",
+       "undeletethispage": "Non burres custa pàgina",
+       "undelete_short": "Non burres {{PLURAL:$1|unu càmbiu|$1 càmbios}}",
+       "viewdeleted_short": "Ammustra {{PLURAL:$1|unu càmbiu burradu|$1 càmbios burrados}}",
+       "protect": "Barda",
+       "protect_change": "càmbia",
        "protectthispage": "Ampara custa pàgina",
        "unprotect": "Muda amparu",
        "unprotectthispage": "Muda amparu de custa pàgina",
        "talkpagelinktext": "Cuntierra",
        "specialpage": "Pàgina Ispetziale",
        "personaltools": "Ainas personales",
-       "postcomment": "Setzione noa",
        "articlepage": "Càstia s'artìculu",
        "talk": "Cuntierras",
-       "views": "Bisuras",
+       "views": "Bìsitas",
        "toolbox": "Ainas",
-       "userpage": "Càstia sa pàgina usuàriu",
+       "userpage": "Càstia sa pàgina impitadore",
        "projectpage": "Càstia sa pàgina meta",
-       "imagepage": "Càstia sa pàgina de su file",
+       "imagepage": "Càstia sa pàgina de su documentu",
        "mediawikipage": "Càstia su messàgiu",
-       "templatepage": "Càstia su template",
+       "templatepage": "Càstia su modellu de documentu",
        "viewhelppage": "Càstia sa pàgina de agiudu",
        "categorypage": "Càstia sa categoria",
        "viewtalkpage": "Càstia cuntierras",
        "otherlanguages": "Àteras limbas",
        "redirectedfrom": "(Reindiritzadu dae $1)",
-       "redirectpagesub": "Pàgina de reindiritzadura",
-       "lastmodifiedat": "Ùrtimu acontzu su $1, a is $2.",
-       "viewcount": "Custu artìculu est stadu lìgiu {{PLURAL:$1|borta|$1 bortas}}.",
+       "redirectpagesub": "Pàgina de reindiritzamentu",
+       "redirectto": "Reindiritzat a:",
+       "lastmodifiedat": "Ùrtimu càmbiu su $1, a is $2.",
+       "viewcount": "Custu artìculu l'ant lèghidu {{PLURAL:$1|borta|$1 bortas}}.",
        "protectedpage": "Pàgina amparada",
        "jumpto": "Bae a:",
-       "jumptonavigation": "navigadura",
+       "jumptonavigation": "navigatzione",
        "jumptosearch": "chirca",
-       "view-pool-error": "Teni passièntzia, is servers funt càrrigus de traballu.\nIn medas megant de biri custa pàgina.\nPo praxeri, torra a provai tra unu pagu.\n\n$1",
-       "generic-pool-error": "Teni passièntzia, is servers funt càrrigus de traballu.\nIn medas megant de biri custa risorsa.\nPo praxeri, torra a provai tra unu pagu.",
+       "view-pool-error": "Tene passèntzia, sos servidores sunt càrrigos de traballu.\nIn medas chircant de castiare custa pàgina.\nPro praghere, torra a tenteare posca.\n\n$1",
+       "generic-pool-error": "Tene passèntzia, sos servidores sunt càrrigos de traballu.\nIn medas chircant de castiare custa risorsa.\nPro praghere, torra a provare luego.",
+       "pool-timeout": "Timeout abetende pro s'arreu",
+       "pool-queuefull": "Sa coa pro su traballu de su protzessu est prena",
        "pool-errorunknown": "Faddina disconnota",
+       "pool-servererror": "Su servìtziu de contadore de su protzessu no est disponìbile ($1).",
        "aboutsite": "A propòsitu de {{SITENAME}}",
        "aboutpage": "Project:Informatziones",
-       "copyright": "Cuntènnidu a suta licèntzia $1.",
-       "copyrightpage": "{{ns:project}}:Copyrights",
+       "copyright": "Cuntenutu suta de lissèntzia $1.",
+       "copyrightpage": "{{ns:project}}: Deretos de còpia",
        "currentevents": "Noas",
        "currentevents-url": "Project:Noas",
-       "disclaimers": "Abbertimentos",
-       "disclaimerpage": "Project:Abbertimentos generales",
-       "edithelp": "Agiudu pro s'acontzu o sa scritura",
+       "disclaimers": "Avertèntzias",
+       "disclaimerpage": "Project:Avertèntzias generales",
+       "edithelp": "Agiudu pro su càmbiu o s'iscritura",
        "mainpage": "Pàgina Base",
        "mainpage-description": "Pàgina Base",
        "policy-url": "Project:Polìticas",
        "portal": "Portale comunidade",
+       "portal-url": "Project:Portale comunidade",
        "privacy": "Polìtica pro is datos privados",
        "privacypage": "Project:Polìtica pro is datos privados",
        "badaccess": "Permissu non bastante",
-       "ok": "OK",
+       "badaccess-group0": "Non ses autorizadu a fàghere s'atzione chi boles",
+       "badaccess-groups": "S'atzione chi as rechestu est limitada a impitadores in {{PLURAL:$2|su grupu|unu de is grupos}}: $1.",
+       "versionrequired": "Bi bolet sa version $1 de MediaWiki",
+       "versionrequiredtext": "Bi bolet sa versione $1 de MediaWiki pro impreare custa pàgina.\nCàstia [[Special:Version|version page]].",
+       "ok": "Andat bene",
        "pagetitle": "$1 - {{SITENAME}}",
        "pagetitle-view-mainpage": "{{SITENAME}}",
-       "retrievedfrom": "Bogau dae  \"$1\"",
+       "retrievedfrom": "Bogadu dae  \"$1\"",
        "youhavenewmessages": "Tenes $1 ($2).",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|Tenes}} $1 dae {{PLURAL:$3|un'àteru impitadore|$3 impitadores}} ($2).",
+       "youhavenewmessagesmanyusers": "Tenes $1 dae unos cantos impitadores ($2).",
+       "newmessageslinkplural": "{{PLURAL:$1|unu messàggiu nou|999=messàggios noos}}",
+       "newmessagesdifflinkplural": "{{PLURAL:$1|ùrtima muda|999=ùrtimas mudàntzias}}",
        "youhavenewmessagesmulti": "Tenes messàgios noos in $1",
-       "editsection": "acontza",
-       "editold": "acontza",
-       "viewsourceold": "càstia mitza",
-       "editlink": "acontza",
-       "viewsourcelink": "càstia mitza",
-       "editsectionhint": "Acontza sa setzione: $1",
+       "editsection": "càmbia",
+       "editold": "càmbia",
+       "viewsourceold": "càstia testu codificadu",
+       "editlink": "càmbia",
+       "viewsourcelink": "càstia testu codificadu",
+       "editsectionhint": "Càmbia sa setzione: $1",
        "toc": "Cuntènnidu",
        "showtoc": "ammustra",
        "hidetoc": "cua",
-       "collapsible-collapse": "Serra e stringi",
+       "collapsible-collapse": "Serra e istringhe",
        "collapsible-expand": "Aberi",
+       "confirmable-confirm": "Ses {{GENDER:$1|seguru|segura}}?",
+       "confirmable-yes": "Eja",
+       "confirmable-no": "No",
        "thisisdeleted": "Càstiare o recuperare $1?",
-       "viewdeleted": "Bisi $1?",
-       "restorelink": "{{PLURAL:$1|unu acontzu burradu|$1 acontzos burrados}}",
-       "feedlinks": "Feed:",
+       "viewdeleted": "Vista $1?",
+       "restorelink": "{{PLURAL:$1|unu càmbiu burradu|$1 càmbios burrados}}",
+       "feedlinks": "Alimentatzione:",
+       "feed-invalid": "Tipu de canale de sutiscritzione invàlida.",
+       "feed-unavailable": "Non sunt disponìbiles feeds",
        "site-rss-feed": "Feed Atom de $1",
        "site-atom-feed": "Feed Atom de $1",
        "page-rss-feed": "Feed RSS pro \"$1\"",
        "feed-atom": "Atom",
        "feed-rss": "RSS",
        "red-link-title": "$1 (sa pàgina no esistit)",
+       "sort-descending": "Òrdine in falada",
+       "sort-ascending": "Òrdine in artziada",
        "nstab-main": "Pàgina",
-       "nstab-user": "Pàgina usuàriu",
-       "nstab-media": "File multimediale",
+       "nstab-user": "Pàgina impitadore",
+       "nstab-media": "Documentu multimediale",
        "nstab-special": "Pàgina ispetziale",
        "nstab-project": "Pàgina de servìtziu",
-       "nstab-image": "File",
+       "nstab-image": "Documentu",
        "nstab-mediawiki": "Messàgiu",
        "nstab-template": "Template",
        "nstab-help": "Agiudu",
        "nstab-category": "Categoria",
-       "nosuchaction": "No esistit tale atzione",
-       "nosuchactiontext": "S'atzione spetzificada in sa URL no est vàlida.\nEst possìbile ki sa URL siat stada carcada male, o si siat sighidu unu cullegamentu non vàlidu.\nCustu diat a pòder èsser unu \"bug\" de {{SITENAME}}.",
+       "nosuchaction": "No esistit custa atzione",
+       "nosuchactiontext": "S'atzione ispetzificada in sa URL no est vàlida.\nEst possìbile chi sa URL siat istada carcada male, o si siat sighidu unu ligàmene non vàlidu.\nCustu diat pòdere èssere unu \"bug\" de {{SITENAME}}.",
        "nosuchspecialpage": "Custa pàgina ispetziale no esistit",
-       "nospecialpagetext": "<strong>As pediu una pàgina ispetziale non balida.</strong>\n\nUna lista de pàginas ispetziales bàlidas d'agatas in [[Special:SpecialPages|{{int:specialpages}}]].",
+       "nospecialpagetext": "<strong>As pedidu una pàgina ispetziale non vàlida.</strong>\n\nUna lista de pàginas ispetziales vàlidas dd'agatas in [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Faddina",
        "databaseerror": "Faddina de su database",
+       "databaseerror-text": "B'est istadu un'errore cun una rechesta a sa base de sos datos.\nCustu podet indicare unu problema in su programma.",
+       "databaseerror-textcl": "B'est istadu un'errore cun una rechesta a sa base de sos datos.",
+       "databaseerror-query": "Rechesta: $1",
+       "databaseerror-function": "Funtzione: $1",
+       "databaseerror-error": "Faddina: $1",
+       "laggedslavemode": "<strong>Atentzione:</strong> Sa pàgina podet non cuntènnere sos agiornamentos prus novos.",
        "readonly": "Database bloccadu",
-       "enterlockreason": "Inserta su motivu de su bloccu, ispetzifichende su momentu probabile chi su bloccu at a acabai",
+       "enterlockreason": "Inserta su motivu de su blocu, ispetzifichende su momentu probàbile chi su blocu at a acabbare",
        "readonlytext": "In custu momentu su database est bloccadu dae aciunturas e àteras modificas, probabilmente pro ordinaria manutentzione a su database, a pustis de custas at a èssere normale torra.\n\nS'aministradore chi dd'at bloccadu at donadu custa ispiegatzione: $1",
-       "missing-article": "Su database no at agatadu su testu de una pàgina ki diat àer agatadu a suta de su nùmene \"$1\" $2.\n\nCustu a su sòlitu si verìficat cando bi est unu ligàmine in sa stòria o in unu cunfrontu intre revisiones de una pàgina ki est stada fuliada.\n\nSi no est custu su casu, s'est agatada una faddina de su software.\nPro praxere signa s'acuntèssidu a unu [[Special:ListUsers/sysop|amministradore]] spetzifichende su URL de sa faddina.",
+       "missing-article": "Su database no at agatadu su testu de una pàgina chi diat àere agatadu a suta de su nùmene \"$1\" $2.\n\nCustu a su sòlitu si verìficat cando bi est unu ligòngiu in s'istòria o in unu cunfrontu intre revisiones de una pàgina chi est istada fuliada.\n\nSi no est custu su casu, s'est agatada una faddina de su software.\nPro praghere signa s'acontèssidu a unu [[Special:ListUsers/sysop|amministradore]] ispetzifichende su URL de sa faddina.",
        "missingarticle-rev": "(revisione nùmeru: $1)",
        "missingarticle-diff": "(Dif: $1, $2)",
+       "readonly_lag": "Sa base de sos datos (database) est istada arreada automaticamente in su mentres chi sos servidores iscraos si sincronizzana cun su printzipale.",
        "internalerror": "Faddina interna",
        "internalerror_info": "Faddina interna: $1",
        "filecopyerror": "No est stadu possìbile copiare su file \"$1\" comente \"$2\".",
        "filerenameerror": "No est stadu possìbile re-numenare su file \"$1\" in \"$2\".",
        "filedeleteerror": "No est stadu possìbile cantzellare su file \"$1\".",
+       "directorycreateerror": "Non si podet creare sa directory \"$1\".",
        "filenotfound": "No est stadu possìbile agatare \"$1\".",
        "unexpected": "Valore non previstu: \"$1\"=\"$2\".",
        "formerror": "Errore: impossìbile imbiare su modellu",
        "badarticleerror": "Operatzione non cunsentida pro custa pàgina.",
        "cannotdelete": "No est stadu possìbile burrare sa pàgina o su file \"$1\".\nPodet èsser stadu burradu dae calicunu àteru.",
+       "cannotdelete-title": "Impossìbile burrare sa pàgina \"$1\"",
+       "delete-hook-aborted": "Sa burradura est istada annuddada dae su hook de s'estensione.\nNo est istadu datu acrarimentu.",
+       "no-null-revision": "Non si podet creare una versione lulla pro sa pàgina \"$1\"",
        "badtitle": "Tìtulu malu",
-       "badtitletext": "Su tìtulu de sa pàgina ch'as pediu est bùidu, isballiau, o iscritu in is cullegamentus inter-wiki in manera non currègia o cun caràteres no amìtius.",
+       "badtitletext": "Su tìtulu de sa pàgina chi as pregontadu est bùidu, isballiadu, o iscritu in is cullegamentus inter-wiki a manera non currègia.\nPodet cuntènnere uno o unos cantos caràteres no ammìtidos pro is tìtulos.",
        "viewsource": "Càstia mitza",
+       "viewsource-title": "Càstia sa mitza de $1",
        "actionthrottled": "Atzione rimandada",
-       "namespaceprotected": "Non tenes su permissu de acontzare is pàginas in su nùmene-lugu '''$1'''.",
+       "protectedpagetext": "Custa pàgina est istada amparada pro nde prevenner su càmbiu o àteras fatas.",
+       "viewsourcetext": "Podes bìere o copiare su còdighe mitza de custa pàgina:",
+       "viewyourtext": "Càstia e còpia su còdighe mitza de is <strong>mudàntzias tuas</strong> in custa pàgina:",
+       "namespaceprotected": "Non tenes su permissu de cambiare is pàginas in su nùmene-lugu '''$1'''.",
+       "customcssprotected": "Non tenes sos permissos pro cambiare custa pàgina CSS proite cuntènnidi sas impostaduras pessonales de un'àteru impitadore.",
+       "customjsprotected": "Non tenes sos permissos pro cambiare custa pàgina JavaScript proite cuntènnidi sas impostaduras pessonales de un'àteru impitadore.",
+       "mycustomcssprotected": "Non tenes sos permissos pro cambiare custa pàgina CSS.",
+       "mycustomjsprotected": "Non tenes sos permissos pro cambiare custa pàgina JavaScript.",
        "ns-specialprotected": "Is pàginas ispetziales non podent èssere acontzadas.",
+       "titleprotected": "Sa creatzione de una pàgina cun custu tìtulu est istada arreada dae [[User:$1|$1]].\nSa motivatzione est \"<em>$2</em>\".",
        "exception-nologin": "Non ses intrau",
+       "exception-nologin-text": "Pro atzèdere a custa pàgina o atzione est netzessàriu a ti identificare.",
        "virus-scanfailed": "scansione faddida (còdixe $1)",
        "virus-unknownscanner": "antivirus disconnotu:",
-       "logouttext": "'''As acabadu sa sessione.'''\n\nImmoe podes sighire a impreare {{SITENAME}} in forma anònima, o ti podes <span class='plainlinks'>[$1 identificare torra]</span> comente su de prima o comente usuàriu diferente.\nTene contu ca is pàginas ki sunt giai abertas in àteras bentanas podent sighire a pàrrer comente cando fias identificadu, fintzas a cando non ddas renfriscas.",
-       "yourname": "Nùmene usuàriu",
+       "logouttext": "<strong>As acabadu sa sessione.</strong>\n\nTene contu ca is pàginas ki sunt giai abertas in àteras bentanas podent sighire a pàrrer comente cando fias identificadu, fintzas a cando non ddas renfriscas dae su browser tuo.",
+       "welcomeuser": "Benénnidu, $1!",
+       "welcomecreation-msg": "Su contu tuo est istadu creadu.\nSi boles podes cambiare is [[Special:Preferences|prefèntzias tuas]] pro {{SITENAME}}",
+       "yourname": "Nùmene impitadore:",
+       "userlogin-yourname": "Nùmene impitadore",
+       "userlogin-yourname-ph": "Inserta su nùmene impitadore tuo",
+       "createacct-another-username-ph": "Inserta su nùmene impitadore:",
        "yourpassword": "Password:",
+       "userlogin-yourpassword": "Password",
+       "userlogin-yourpassword-ph": "Inserta sa password tua",
+       "createacct-yourpassword-ph": "Inserta una password",
        "yourpasswordagain": "Repite sa password:",
-       "remembermypassword": "Ammenta sa password in custu carculadore (pro unu màssimu de $1 {{PLURAL:$1|die|dies}})",
-       "yourdomainname": "Spetzificare su domìniu",
+       "createacct-yourpasswordagain": "Cunfirma sa password",
+       "createacct-yourpasswordagain-ph": "Inserta sa password torra",
+       "remembermypassword": "Ammenta sa password in custu navigadore (pro unu màssimu de $1 {{PLURAL:$1|die|dies}})",
+       "userlogin-remembermypassword": "Mantènnemi cullegadu",
+       "userlogin-signwithsecure": "Imprea una cunnessione segura",
+       "yourdomainname": "Ispetzìfica su domìniu",
+       "password-change-forbidden": "Non podes cambiare sa password in custa wiki.",
        "login": "Intra",
-       "nav-login-createaccount": "Intra / crea account",
-       "loginprompt": "Est netzessàriu abilitare is ''cookies'' pro si registrare in {{SITENAME}}.",
-       "userlogin": "Intra / crea account",
+       "nav-login-createaccount": "Intra / crea contu",
+       "userlogin": "Intra / crea contu",
        "userloginnocreate": "Intra",
        "logout": "Serra sessione",
        "userlogout": "Essida",
        "notloggedin": "Non ses intradu",
-       "nologin": "Non tenes unu account? '''$1'''.",
-       "nologinlink": "Crea unu account",
-       "createaccount": "Crea account",
-       "gotaccount": "Tenes giai unu account? $1.",
-       "gotaccountlink": "Identifica·ti",
-       "createaccountmail": "via e-mail",
+       "userlogin-noaccount": "Non tenes unu contu?",
+       "userlogin-joinproject": "Registra⋅ti a {{SITENAME}}",
+       "nologin": "Non tenes unu contu? '''$1'''.",
+       "nologinlink": "Crea unu contu",
+       "createaccount": "Crea contu",
+       "gotaccount": "Tenes giai unu contu? $1.",
+       "gotaccountlink": "Identìfica·ti",
+       "userlogin-resetpassword-link": "As ismentigadu sa password?",
+       "userlogin-helplink2": "Agiudu pro s'atzessu",
+       "createacct-emailrequired": "Indirutzu Email",
+       "createacct-emailoptional": "Indiritzu email (optzionale)",
+       "createacct-email-ph": "Inserta s'indiritzu email tuo",
+       "createacct-another-email-ph": "Inserta s'indiritzu email",
+       "createaccountmail": "Imprea una password a sorte e ispedidda a su indiritzu email ispetzificadu",
+       "createacct-realname": "Nùmene beru (optzionale)",
        "createaccountreason": "Motivu:",
-       "badretype": "Sas passwords chi as insertau non currenspundint.",
-       "userexists": "Su nùmene usuàriu insertadu est giai impreadu.\nSèbera unu nùmene diferente.",
+       "createacct-reason": "Motivu",
+       "createacct-reason-ph": "Proite ses creande un àteru contu",
+       "createacct-captcha": "Còmpudu de siguresa",
+       "createacct-imgcaptcha-ph": "Inserta su testu chi bides aissusu",
+       "createacct-submit": "Crea su contu tuo",
+       "createacct-another-submit": "Crea un àteru contu",
+       "createacct-benefit-heading": "{{SITENAME}} est òpera de gente che tue.",
+       "createacct-benefit-body1": "{{PLURAL:$1|acontzu|acontzos}}",
+       "createacct-benefit-body2": "{{PLURAL:$1|pàgina|pàginas}}",
+       "createacct-benefit-body3": "{{PLURAL:$1|contribudore retzente|contribudores retzentes}}",
+       "badretype": "Is passwords chi as insertadu non currispondent.",
+       "userexists": "Su nùmene impitadore insertadu est giai impreadu.\nSèbera unu nùmene diferente.",
        "loginerror": "Faddina de identificatzione",
-       "noname": "Su nùmene usuàriu insertadu no est vàlidu.",
+       "createacct-error": "Faddina in sa creatzione de su contu",
+       "createaccounterror": "Impossìbile creare su contu: $1",
+       "nocookiesnew": "Su contu de s'impitadore est istadu creadu, ma no est istadu possìbile fàghere s'atzessu a {{SITENAME}} proite sos \"cookies\" sunt deativados.\nTorra a proare a pustis de los àere ativados.",
+       "nocookieslogin": "{{SITENAME}} imprea is cookies pro identificare is impitadores.\nTue tenes is cookies disativados.\nAtivaddos e prova torra.",
+       "noname": "Su nùmene impitadore insertadu no est vàlidu.",
        "loginsuccesstitle": "Ti ses identificadu",
-       "loginsuccess": "'''Immoe ses intradu in {{SITENAME}} cun su nùmene usuàriu \"$1\".'''",
-       "nosuchuser": "Non bi est usuàriu cun su nùmene \"$1\".\nIs nùmenes usuàriu sunt sensìbiles a is lìteras mannas.\nVerìfica su nùmene insertadu o [[Special:UserLogin/signup|crea unu account nou]].",
-       "nouserspecified": "Depes spetzificare unu nùmene usuàriu.",
-       "wrongpassword": "Sa password insertada no est bona. Prova torra.",
-       "wrongpasswordempty": "No as scritu sa password.\nProva torra.",
+       "loginsuccess": "'''Immoe ses intradu in {{SITENAME}} cun su nùmene impitadore \"$1\".'''",
+       "nosuchuser": "Non b'at impitadore cun su nùmene \"$1\".\nIs nùmenes impitadore sunt sensìbiles a is lìteras mannas.\nVerìfica su nùmene insertadu o [[Special:UserLogin/signup|crea unu contu nou]].",
+       "nouserspecified": "Depes ispetzificare unu nùmene impitadore.",
+       "login-userblocked": "{{GENDER:$1|Custu impitadore est arreadu|Custa impidadora est arreada}}. Atzessu impossìbile.",
+       "wrongpassword": "Sa paràula de òrdine insertada no est bona. Prova torra.",
+       "wrongpasswordempty": "No as iscritu sa paràula de òrdine.\nProva torra.",
        "passwordtooshort": "Is passwords depent tènner a su mancu {{PLURAL:$1|1 caràtere|$1 caràteres}}.",
-       "password-name-match": "Sa password tua depet èsser diferente dae su nùmene usuàriu tuo.",
-       "mailmypassword": "Ispedi una password noa a s'indiritzu e-mail miu",
-       "passwordremindertitle": "Servitziu Password Reminder di {{SITENAME}}",
-       "passwordremindertext": "Calicunu (probabilmenti tue, cun s'indiritzu IP $1) at pediu de arritziri una password noa pro intrare a {{SITENAME}} ($4).\nUna password temporanea pro s'usuàriu \"$2\" est istada impostada a \"$3\".\nChi custu fiat ne is intentziones tuas, depis intrare (log in) e scioberari una password noa.\nSa password temporanea tua at a iscadiri in {{PLURAL:$5|una die|$5 dies}}.\n\nChi non ses istadu a pediri sa password, o chi as torrau a agatare sa password torra e non da depis cambiari prus, non cunsideras custu messagiu e sighi a impreare sa password beccia.",
-       "noemail": "Peruna e-mail resurtat registrada pro s'usuàriu \"$1\".",
-       "passwordsent": "Una password noa est stada mandada a s'indiritzu e-mail de s'usuàriu \"$1\".\nPro praxere, cando dda retzis identìfica·ti torra.",
+       "password-name-match": "Sa password tua depet èsser diferente dae su nùmene impitadore tuo.",
+       "password-login-forbidden": "S'impreau de custu nùmene impitadore e de custa password est istadu proibidu.",
+       "mailmypassword": "Reseta sa password",
+       "passwordremindertitle": "Servìtziu Password Reminder de {{SITENAME}}",
+       "passwordremindertext": "Calicunu (probabilmenti tue, cun s'indiritzu IP $1) at pediu de arritziri una password noa pro intrare a {{SITENAME}} ($4).\nUna password temporanea pro s'impitadore \"$2\" est istada impostada a \"$3\".\nChi custu fiat ne is intentziones tuas, depis intrare (log in) e scioberari una password noa.\nSa password temporanea tua at a iscadiri in {{PLURAL:$5|una die|$5 dies}}.\n\nChi non ses istadu a pediri sa password, o chi as torrau a agatare sa password torra e non da depis cambiari prus, non cunsideras custu messagiu e sighi a impreare sa password beccia.",
+       "noemail": "Peruna email resurtat registrada pro s'impitadore \"$1\".",
+       "passwordsent": "Una password noa est stada mandada a s'indiritzu email de s'impitadore \"$1\".\nPro praxere, cando dda retzis identìfica·ti torra.",
        "mailerror": "Faddina imbiende su messàgiu: $1",
        "emailauthenticated": "S'indiritzu e-mail tuo est istadu autenticau su $2 a is $3.",
        "emailconfirmlink": "Cunfirma s'indiritzu e-mail tuo",
-       "accountcreated": "Account creadu",
-       "accountcreatedtext": "S'account usuàriu pro $1 est stadu creadu.",
-       "createaccount-title": "Creatzione de unu account pro {{SITENAME}}",
+       "emaildisabled": "Custu giassu non podet imbiare emails.",
+       "accountcreated": "Contu creadu",
+       "accountcreatedtext": "Su contu de s'impitadore [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) est stadu creadu.",
+       "createaccount-title": "Creatzione de unu contu pro {{SITENAME}}",
+       "login-abort-generic": "S'identificatzione tua est andada male - Iscontzada",
        "loginlanguagelabel": "Limba: $1",
        "createacct-another-realname-tip": "Su nomini beru pois fai de mancu de ddu ponni.\nSi sceberas de du ponni, at a essi imperau po arreconnosci a tui su traballu tuu.",
        "pt-login": "Intra",
        "pt-login-button": "Intra",
-       "pt-createaccount": "Arregistradì",
-       "pt-userlogout": "Bessida",
+       "pt-createaccount": "Registra·ti",
+       "pt-userlogout": "Essida",
        "changepassword": "Càmbia password",
-       "resetpass_header": "Càmbia sa password de su account",
+       "resetpass_header": "Càmbia sa password de su contu",
        "oldpassword": "Password betza:",
        "newpassword": "Password noa:",
-       "retypenew": "Re-scrie sa password noa:",
+       "retypenew": "Torra a iscrìere sa password noa:",
        "resetpass_submit": "Càmbia sa password e identifica·ti",
-       "resetpass_forbidden": "No est possìbile cambiare is passwords",
+       "changepassword-success": "Sa password tua est istada cambiada in manera currègida!",
+       "resetpass_forbidden": "Non faghet a cambiare sa password",
        "resetpass-no-info": "Depes èsser identificadu pro abèrrer custa pàgina deretu.",
        "resetpass-submit-loggedin": "Càmbia password",
        "resetpass-submit-cancel": "Burra",
        "resetpass-temp-password": "Password temporànea:",
-       "bold_sample": "Grassu",
-       "bold_tip": "Grassu",
-       "italic_sample": "Corsivu",
-       "italic_tip": "Corsivu",
-       "link_sample": "Tìtulu cullegamentu",
-       "link_tip": "Cullegamentu internu",
-       "extlink_sample": "http://www.example.com tìtulu de s'acàpiu",
-       "extlink_tip": "Acàpiu a foras (ammenta su prefissu http://)",
+       "passwordreset": "Reseta sa password",
+       "passwordreset-legend": "Reseta sa password",
+       "passwordreset-username": "Nùmene impitadore:",
+       "passwordreset-domain": "Domìniu:",
+       "passwordreset-email": "Indiritzu email:",
+       "passwordreset-emailtitle": "Particulares de s'impitadore in {{SITENAME}}",
+       "passwordreset-emailelement": "Nùmene impitadore: $1\nPassword temporànea: $2",
+       "changeemail": "Càmbia indiritzu email",
+       "changeemail-header": "Càmbia s'indirìtzu email de su contu",
+       "changeemail-oldemail": "Indiritzu email atuale:",
+       "changeemail-newemail": "Indiritzu email nou:",
+       "changeemail-none": "(nudda)",
+       "changeemail-password": "Sa password tua pro {{SITENAME}}:",
+       "changeemail-submit": "Càmbia email",
+       "changeemail-cancel": "Annudda",
+       "resettokens": "Reseta tokens",
+       "resettokens-token-label": "$1 (valore atuale: $2)",
+       "bold_sample": "Testu grassu",
+       "bold_tip": "Testu grassu",
+       "italic_sample": "Testu cursivu",
+       "italic_tip": "Testu cursivu",
+       "link_sample": "Tìtulu ligòngiu",
+       "link_tip": "Ligòngiu internu",
+       "extlink_sample": "http://www.example.com tìtulu de su ligòngiu",
+       "extlink_tip": "Ligòngiu a foras (regorda su prefissu http://)",
        "headline_sample": "Testu de su tìtulu",
        "headline_tip": "Tìtulu de su de duos livellu",
        "nowiki_sample": "Inserta su testu non-formatadu inoghe",
        "image_sample": "Esèmpiu.jpg",
        "image_tip": "Incòrpora una pintura",
        "media_sample": "Esèmpiu.ogg",
-       "media_tip": "Cullegamentu a unu file",
-       "sig_tip": "Firma cun data e ora",
-       "hr_tip": "Lìnia orizontale (de usare cun critèriu)",
+       "media_tip": "Ligòngiu a unu file multimediale",
+       "sig_tip": "Firma·ti cun data e ora",
+       "hr_tip": "Lìnia orizontale (de impreare cun critèriu)",
        "summary": "Ogetu:",
        "subject": "Tema/tìtulu:",
-       "minoredit": "Custu est un'acontzu minore:",
-       "watchthis": "Pone custa pàgina in sa watchlist mea",
+       "minoredit": "Custu est unu càmbiu minore",
+       "watchthis": "Annota custa pàgina",
        "savearticle": "Sarva sa pàgina",
        "preview": "Antiprima",
        "showpreview": "Ammustra s'antiprima",
-       "showdiff": "Ammustra is mudàntzias",
-       "anoneditwarning": "'''Atentzione:''' Non ses identificadu (log in).\nS'indiritzu IP tuo at a èsser registradu in sa stòria de custa pàgina.",
-       "anonpreviewwarning": "''Non ses identificadu. Sarbende s'indiritzu IP tuo at a èsser registradu in sa stòria de sa pàgina.''",
-       "missingcommenttext": "Inserta unu cummentu inoghe suta.",
+       "showdiff": "Ammustra is càmbios",
+       "anoneditwarning": "<strong>Atentzione:</strong> Non ses identificadu.\nS'indiritzu IP tuo at a èssere annòtidu si faghes unos cantos càmbios. Si <strong>idendificas</strong> tibe o <strong>[$2 creas unu contu]</strong>, is càmbios tuos ant a esser marcados cun su nùmene impitadore tuo, paris a àteros giuamentos.",
+       "anonpreviewwarning": "''Non ses identificadu. Sarvende s'indiritzu IP tuo at a èssere registradu in s'istòria de sa pàgina.''",
+       "missingcommenttext": "Inserta unu cummentu inoghe suta.",
        "summary-preview": "Antiprima ogetu:",
        "subject-preview": "Antiprima tema/tìtulu:",
-       "blockedtitle": "S'usuàriu est istadu bloccau",
-       "blockedtext": "'''Custu nùmene usuàriu o indiritzu IP est stadu bloccadu.'''\n\nSu bloccu est stadu postu dae $1. Su motivu de su bloccu est: ''$2''\n\n* Su bloccu incumentzat: $8\n* Su bloccu scadit: $6\n* Intervallu de bloccu: $7\n\nSi boles, podes tzerriare $1 o un'àteru [[{{MediaWiki:Grouppage-sysop}}|amministradore]] pro faeddare de su bloccu.\n\nNota ca sa funtzione 'Ispedi un'e-mail a custu usuàriu' no est ativa ki no est stadu registradu un'indiritzu e-mail vàlidu in is [[Special:Preferences|preferèntzias]] tuas o ki s'usu de custa funtzione est stadu bloccadu.\n\nS'indiritzu IP atuale est $3, su nùmeru ID de su bloccu est #$5.\nPro praxere spetzìfica totu is particulares in antis in carche siat pregunta de acrarimentu.",
-       "blockednoreason": "perunu motivu indicadu",
-       "loginreqtitle": "Identificatzione rekesta",
-       "loginreqlink": "identifica·ti",
+       "blockedtitle": "S'impitadore est istadu bloccadu",
+       "blockedtext": "<strong>Custu nùmene impitadore o indiritzu IP est stadu bloccadu.</strong>\n\nSu bloccu est stadu postu dae $1.\nSu motivu de su bloccu est: <em>$2</em>.\n\n* Su bloccu incumentzat: $8\n* Su bloccu scadit: $6\n* Intervallu de bloccu: $7\n\nSi boles, podes tzerriare $1 o un'àteru [[{{MediaWiki:Grouppage-sysop}}|amministradore]] pro faeddare de su bloccu.\nNota ca sa funtzione 'Ispedi un'email a custu impitadore' no est ativa ki no est stadu registradu un'indiritzu email vàlidu in is [[Special:Preferences|preferèntzias]] tuas o ki s'usu de custa funtzione est stadu bloccadu.\nS'indiritzu IP atuale est $3, su nùmeru ID de su bloccu est #$5.\nPro praxere spetzìfica totu is particulares in antis in carche siat pregunta de acrarimentu.",
+       "blockednoreason": "perunu motivu inditadu",
+       "nosuchsectiontitle": "Impossìbile agatare sa setzione",
+       "loginreqtitle": "Identificatzione rechesta",
+       "loginreqlink": "identìfica·ti",
        "loginreqpagetext": "Depes èsser $1 pro bìer àteras pàginas.",
-       "accmailtitle": "Password ispedia.",
+       "accmailtitle": "Password ispedida.",
        "newarticle": "(Nou)",
-       "newarticletext": "Custa pàgina no esistit galu.\nPro creare sa pàgina, scrie in su box inoghe in bàsciu (abbàida sa [$1 pàgina de agiudu] pro àteras informatziones).\nSi ses intradu inoghe pro sbàlliu, carca in su browser tuo su butone '''back/indietro'''.",
-       "anontalkpagetext": "----''Custa est sa pàgina de cuntierra de unu usuàriu anònimu ki no at creadu unu account galu, o ki non dd'usat. Pro custu impreamus su nùmeru de indiritzos IP pro ddu identificare. Is indiritzos IP podent però èsser cundivìdidos dae unos cantos usuàrios. Si ses unu usuàriu anònimu e ritenes ki custos cummentos non sunt diretos a tue, pro praxere [[Special:UserLogin/signup|crea unu account]] o [[Special:UserLogin|identifica·ti (log in)]] pro evitare cunfusione cun àteros usuàrios anònimos.''",
-       "noarticletext": "In custu momentu sa pàgina est bùida.\nPodes [[Special:Search/{{PAGENAME}}|chircare custu tìtulu]] in àteras pàginas, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} chircare in is registros ligados] oppuru [{{fullurl:{{FULLPAGENAME}}|action=edit}} acontzare sa pàgina]</span>.",
-       "userpage-userdoesnotexist": "S'account de s'usuàriu \"<nowiki>$1</nowiki>\" no est stadu registradu.\nPro praxere abbàida si boles creare/acontzare custa pàgina.",
-       "userpage-userdoesnotexist-view": "S'account de s'usuàriu \"$1\" no est stadu registradu.",
-       "updated": "(Agiornadu)",
+       "newarticletext": "Custa pàgina no esistit galu.\nPro creare sa pàgina, iscrie in su box inoghe a suta (càstia sa [[{{MediaWiki:Helppage}}|pàgina de agiudu]] pro àteras informatziones).\nSi ses intradu inoghe pro isbàlliu, carca in su browser tuo su butone '''back/indietro'''.",
+       "anontalkpagetext": "----\n<em>Custa est sa pàgina de cuntierra de unu impitadore anònimu ki no at creadu unu contu galu, o ki non dd'usat.</em>\nPro custu impreamus su nùmeru de indiritzos IP pro ddu identificare. Is indiritzos IP podent perou èsser cundivìdidos dae unos cantos impitadores. Si ses unu impitadore anònimu e ritenes ki custos cummentos non sunt diretos a tue, pro praxere [[Special:UserLogin/signup|crea unu contu]] o [[Special:UserLogin|identifica·ti (log in)]] pro evitare cunfusione cun àteros impitadore anònimos.''",
+       "noarticletext": "In custu momentu sa pàgina est bùida.\nPodes [[Special:Search/{{PAGENAME}}|chircare custu tìtulu]] in àteras pàginas, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} chircare in is registros ligados] o puru [{{fullurl:{{FULLPAGENAME}}|action=edit}} cambiare sa pàgina como]</span>.",
+       "noarticletext-nopermission": "In custu tempu sa pàgina rechesta est bùida.\nPodes [[Special:Search/{{PAGENAME}}|chircare custu tìtulu]] in is àteras pàginas, o <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} chircare in is regìstros ligados]</span>, ma non tenes su permissu de creare custa pàgina.",
+       "userpage-userdoesnotexist": "Su contu de s'impitadore \"<nowiki>$1</nowiki>\" no est stadu registradu.\nPro praxere abbàida si boles a sèriu creare/cambiare custa pàgina.",
+       "userpage-userdoesnotexist-view": "Su contu de s'impitadore \"$1\" no est stadu registradu.",
+       "usercssyoucanpreview": "<strong>Consìgiu:</strong> Imprea su butone \"{{int:showpreview}}\" pro testare su CSS nou in antis de sarvare.",
+       "userjsyoucanpreview": "<strong>Consìgiu:</strong> Imprea su butone \"{{int:showpreview}}\" pro testare su tuo JavaScript nou in antis de sarvare.",
+       "updated": "(Atualizadu)",
        "note": "'''Nota:'''",
-       "previewnote": "'''Regorda·ti ca custa est feti una ANTIPRIMA. Is mudàntzias tuas non sunt galu sarbadas!'''",
+       "previewnote": "<strong>Regorda·ti ca custa est feti una ANTIPRIMA.</strong>\nIs mudàntzias tuas non sunt galu sarbadas!",
+       "continue-editing": "Bae a s'àrea de modìfica",
        "previewconflict": "Custa antiprima rapresentat su testu in s'àrea acontzu testu de susu comente at a pàrrer si dda sarbas.",
-       "editing": "Acontzu de $1",
-       "editingsection": "Acontzende $1 (setzione)",
-       "editingcomment": "Acontzu de $1 (setzione noa)",
+       "editing": "Cambiende $1",
+       "creating": "Creande $1",
+       "editingsection": "Cambiende $1 (setzione)",
+       "editingcomment": "Modìfica de $1 (setzione noa)",
        "editconflict": "Cunflitu de editzione: $1",
        "explainconflict": "Calicunu àteru at acontzadu custa pàgina in su tempus ki dda fias acontzende tue.\nS'àrea de testu de susu cuntènnet su testu de sa pàgina in sa forma atuale.\nIs mudàntzias tuas sunt ammustradas in s'àrea de testu de bàsciu.\nAs a dèper insertare is mudàntzias tuas in su testu atuale, e pro custu a ddas scrìer in s'àrea de susu.\n'''Solu''' su testu in s'àrea de susu at a èsser sarbadu si carcas su butone \"{{int:savearticle}}\".",
        "yourtext": "Su testu tuo",
-       "storedversion": "Revisione in arkìvio",
+       "storedversion": "Revisione in archìviu",
        "editingold": "'''ATENTZIONE: Ses acontzende una revisione non-agiornada de sa pàgina.'''\nSi dda sarbas de aici, totu is acontzos fatos a pustis de custa revisione ant a bènner pèrdidos pro semper.",
        "yourdiff": "Diferèntzias",
-       "copyrightwarning": "Abbàida, pro praxere, ki totu is contributziones a {{SITENAME}} sunt cunsideradas lassadas a suta permissu de tipu $2 (càstia $1 pro nde schire de prus). Si non keris ki su scritu tuo potzat èsser acontzadu e re-distribuidu dae kie si siat sena piedade e sena àteros lìmites, non ddu imbies a {{SITENAME}}.<br />\nCun s'imbiu de custu scritu ses garantende, a responsabilidade tua, si su scritu ddu as cumpostu tue de persona e in originale, o puru si est stadu copiadu dae una fonte de domìniu pùblicu, o una fonte de gasi, o puru si as otentu permissu craru de impreare custu scritu e si ddu podes dimustrare. '''NO IMPREARE MATERIALE COBERTU DAE DERETU DE AUTORE SENA PERMISSU CRARU!'''",
+       "copyrightwarning": "Abbàida, pro praghere, chi totu is contributos a {{SITENAME}} sunt cunsideradas lassadas a suta permissu de tipu $2 (càstia $1 pro nde ischire de prus). Si non boles chi s'iscritu tuo potzat èssere cambiadu e re-distribuidu dae chie si siat sena piedade e sena àteros lìmites, non ddu imbies a {{SITENAME}}.\nCun s'imbiu de custu iscritu ses garantende, a responsabilidade tua, si su iscritu ddu as cumpostu tue de persone e in originale, o puru si est istadu copiadu dae una fonte de domìniu pùblicu, o una fonte de gasi, o puru si as otentu permissu craru de impreare custu iscritu e si ddu podes dimustrare. '''NO IMPREARE MATERIALE COBERTU DAE DERETU DE AUTORE SENA PERMISSU CRARU!'''",
        "templatesused": "{{PLURAL:$1|Template impreadu|Templates impreados}} in custa pàgina:",
        "templatesusedpreview": "{{PLURAL:$1|Template impreadu|Templates impreados}} in custa antiprima:",
        "templatesusedsection": "{{PLURAL:$1|Template impreadu|Templates impreados}} in custa setzione:",
-       "template-protected": "(amparadu)",
-       "template-semiprotected": "(mesu-amparadu)",
+       "template-protected": "(bardadu)",
+       "template-semiprotected": "(mesu-bardadu)",
        "hiddencategories": "Custa pàgina faghet parte de {{PLURAL:$1|1 categoria cuada|$1 categorias cuadas}}:",
        "nocreate-loggedin": "Non tenes su permissu de creare pàginas noas.",
        "permissionserrors": "Faddina de permissos",
        "permissionserrorstext-withaction": "Non tenes su permissu de $2, pro {{PLURAL:$1|custu motivu|custus motivus}}:",
-       "moveddeleted-notice": "Custa pàgina est istada fuliada.\nSu registru de is fuliaduras e moviduras de sa pàgina est ammustradu pro informatzione.",
+       "recreate-moveddeleted-warn": "<strong>Atentzione: Ses torrende a creare una pàgina chi est istada giai burrada.</strong>\n\nSinchera·ti chi siat pretzisu a sighire cambiende custa pàgina.\nSu registru de is burraduras e moviduras pro custa pàgina benit giùghedu inoghe:",
+       "moveddeleted-notice": "Custa pàgina est istada burrada.\nSu registru de is burraduras e moviduras de sa pàgina est ammustradu pro informatzione.",
        "log-fulllog": "Abbista su registru intreu",
        "edit-conflict": "Cunflitu de editzione.",
-       "viewpagelogs": "Càstia sos registros de custa pàgina",
+       "postedit-confirmation-created": "Sa pàgina est stada creada",
+       "postedit-confirmation-restored": "Sa pàgina est stada restaurada",
+       "postedit-confirmation-saved": "Su càmbiu tuo est stadu sarbadu",
+       "defaultmessagetext": "Testu de su messàgiu predeterminadu",
+       "invalid-content-data": "Datos de cuntènnidu invàlidos",
+       "content-model-wikitext": "wikitestu",
+       "content-model-text": "testu normale",
+       "content-model-javascript": "JavaScript",
+       "content-model-css": "CSS",
+       "post-expand-template-inclusion-category": "Pàginas in is cale sa dimensione templates inclùdidos propassat su lìmite cunsentidu",
+       "post-expand-template-argument-category": "Pàginas cuntenentes templates cun argumentos fartados",
+       "cantcreateaccounttitle": "Non si podet creare unu contu",
+       "viewpagelogs": "Càstia is registros de custa pàgina",
        "nohistory": "Non b'est sa stòria de is acontzos pro custa pàgina.",
        "currentrev": "Revisione currente",
        "currentrev-asof": "Versione currente de is $1",
        "revisionasof": "Revisione de is $1",
-       "revision-info": "Revisione de is $1 dae $2",
-       "previousrevision": "← Acontzu in antis",
-       "nextrevision": "Acontzu in fatu →",
-       "currentrevisionlink": "Revisione currente",
+       "revision-info": "Revisione de su $4 a is $5 de {{GENDER:$6|$2}}$7",
+       "previousrevision": "← Versione in segus",
+       "nextrevision": "Versione in antis →",
+       "currentrevisionlink": "Revisione atuale",
        "cur": "curr",
        "next": "in fatu",
-       "last": "ant",
+       "last": "pre",
        "page_first": "prima",
        "page_last": "ùrtima",
-       "histlegend": "Cunfrontu intre versiones: sebera sa casella de sa versione ki boles e carca \"Invio\" o su butone in bàsciu.<br />\nCosas de ammentare: '''({{int:cur}})''' = diferèntzias cun sa versione currente,\n'''({{int:last}})''' = diferèntzias cun sa versione in antis, '''{{int:minoreditletter}}''' = acontzu minore.",
-       "history-fieldset-title": "Sfògia sa stòria",
-       "history-show-deleted": "Petzi borrados",
-       "histfirst": "Prima",
-       "histlast": "Ã\99rtima",
+       "histlegend": "Cunfrontu intre versiones: Marca sa casella de sa versione chi boles e carca \"Invio\" o su butone in bàsciu.<br />\nCosas de ammentare: <strong>({{int:cur}})</strong> = diferèntzias cun sa versione atuale,\n<strong>({{int:last}})</strong> = diferèntzias cun sa versione pretzedente, <strong>{{int:minoreditletter}}</strong> = càmbiu minore.",
+       "history-fieldset-title": "Isfògia s'istòria",
+       "history-show-deleted": "Feti is burrados",
+       "histfirst": "prima",
+       "histlast": "ùrtima",
        "historysize": "({{PLURAL:$1|1 byte|$1 bytes}})",
        "historyempty": "(bùida)",
+       "history-feed-title": "Istòria de is revisiones",
+       "history-feed-description": "Istòria de is revisiones de sa pàgina in custa wiki",
        "history-feed-item-nocomment": "$1 su $2",
+       "rev-deleted-user": "(nùmene impitadore bogadu)",
        "rev-delundel": "ammustra/cua",
        "rev-showdeleted": "ammustra",
+       "revisiondelete": "Burra o reimprea versiones",
+       "revdelete-no-file": "Su documentu ispetzuficadu no esistit",
        "revdelete-show-file-submit": "Eja",
-       "revdelete-radio-set": "Eja",
-       "revdel-restore": "Muda sa visibilidade",
+       "revdelete-selected-text": "{{PLURAL:$1|Versione seletzionada|Versiones seletzionadas}} de [[:$2]]:",
+       "revdelete-selected-file": "{{PLURAL:$1|Versione seletzionada|Versiones seletzionadas}} de su documentu [[:$2]]:",
+       "logdelete-selected": "{{PLURAL:$1|Acadessimentu de su registru seletzionadu|Acadessimentos de su registru seletzionadu}}:",
+       "revdelete-hide-text": "Testu de sa versione",
+       "revdelete-hide-image": "Cua su cuntènnidu de su documentu",
+       "revdelete-hide-comment": "Modìfica s'ogetu",
+       "revdelete-radio-set": "Cua",
+       "revdelete-radio-unset": "Ammustra",
+       "revdelete-log": "Motivu:",
+       "revdel-restore": "càmbia sa visibilidade",
        "pagehist": "Istòria de sa pàgina",
        "deletedhist": "Istòria fuliada",
+       "revdelete-otherreason": "Motivu diversu o agiuntivu:",
        "revdelete-reasonotherlist": "Àteru motivu",
+       "revdelete-edit-reasonlist": "Càmbia su motivu de sa burradura",
+       "revdelete-offender": "Autore de sa versione:",
        "mergehistory-from": "Pàgina de orìgine:",
        "mergehistory-into": "Pàgina de destinatzione:",
        "mergehistory-no-source": "Sa pàgina de orìgine $1 no esistit.",
        "mergehistory-reason": "Motivu:",
-       "revertmerge": "Fùrria s'unione",
-       "history-title": "Istòria de is revisiones de \"$1\"",
+       "revertmerge": "Iscontza s'unione",
+       "history-title": "$1: Istòria de is revisiones",
+       "difference-multipage": "(Diferèntzias intre pàginas)",
        "lineno": "Lìnia $1:",
        "compareselectedversions": "Cumpara versiones scioberadas",
        "editundo": "annudda",
+       "diff-empty": "(Diferèntzia peruna)",
        "searchresults": "Resurtados de sa chirca",
        "searchresults-title": "Resurtados pro sa chirca de \"$1\"",
        "titlematches": "Currispondèntzias in su tìtulu de s'artìculu",
        "textmatches": "Currispondèntzias in su testu de s'artìculu",
        "notextmatches": "Peruna currispondèntzia in su testu de s'artìculu",
-       "prevn": "{{PLURAL:$1|cabudianu|cabudianos $1}}",
+       "prevn": "{{PLURAL:$1|pretzedente|pretzedentes $1}}",
        "nextn": "{{PLURAL:$1|imbeniente|imbenientes $1}}",
+       "prevn-title": "{{PLURAL:$1|Resurtadu pretzedente|$1 resurtados pretzedentes}}",
+       "nextn-title": "{{PLURAL:$1|Resurtadu imbeniente|$1 resurtados imbenientes}}",
        "shown-title": "Ammustra $1 {{PLURAL:$1|resurtadu|resurtados}} pro pàgina",
        "viewprevnext": "Càstia ($1 {{int:pipe-separator}} $2) ($3).",
-       "searchprofile-articles": "Pàginas de càbidu",
+       "searchmenu-exists": "<strong>Ddu est una pàgina tzerriada \"[[:$1]]\" in custa wiki.</strong> {{PLURAL:$2|0=|Càstia puru is àteros resurtados de sa chirca.}}",
+       "searchmenu-new": "<strong>Crea sa pàgina \"[[:$1]]\" in custa wiki!</strong> {{PLURAL:$2|0=|Càstia fintzas sa pàgina agatada cun sa chirca tua|Càstia fintzas is resurtados de sa chirca}}",
+       "searchprofile-articles": "Pàginas de càbidos",
        "searchprofile-images": "Multimèdia",
-       "searchprofile-everything": "Totu",
+       "searchprofile-everything": "Totue",
        "searchprofile-advanced": "Avantzada",
        "searchprofile-articles-tooltip": "Chirca in $1",
        "searchprofile-images-tooltip": "Chirca files",
-       "search-result-size": "$1 ({{PLURAL:$2|1 faeddu|$2 faeddos}})",
-       "search-result-score": "Rilevàntzia: $1%",
-       "search-redirect": "(redirect $1)",
+       "searchprofile-everything-tooltip": "Chirca in totue (inclùdidas is pàginas de cuntierra)",
+       "searchprofile-advanced-tooltip": "Chirca in nùmene-logos personalizados",
+       "search-result-size": "$1 ({{PLURAL:$2|1 paràula|$2 paràulas}})",
+       "search-result-category-size": "{{PLURAL:$1|1 cumponente|$1 cumponentes}} ({{PLURAL:$2|1 subcategoria|$2 subcategorias}}, {{PLURAL:$3|1 file|$3 files}})",
+       "search-redirect": "(reindiritzadu $1)",
        "search-section": "(setzione $1)",
-       "search-suggest": "Fortzis fias chirkende: $1",
+       "search-suggest": "Fortzis fias chirchende: $1",
        "search-interwiki-caption": "Progetos frades",
-       "search-interwiki-default": "$1 resurtados:",
+       "search-interwiki-default": "Resurtados dae $1:",
        "search-interwiki-more": "(àteru)",
        "searchall": "totu",
        "showingresults": "Inoghe sighende {{PLURAL:$1|benit ammustradu '''1''' resurtadu|benint ammustrados '''$1''' resurtados}} incumentzende dae su nùmeru '''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|Resultadu '''$1''' de '''$3'''|Resultadus '''$1 - $2''' de '''$3'''}} pro '''$4'''",
+       "search-nonefound": "Sa chirca no at prodùidu resurtados.",
        "powersearch-legend": "Chirca delantada",
        "powersearch-ns": "Chirca in su nùmene-logu:",
        "powersearch-togglelabel": "Seletziona:",
        "powersearch-toggleall": "Totu",
        "powersearch-togglenone": "Nudda",
        "preferences": "Preferèntzias",
-       "mypreferences": "Preferèntzias meas",
+       "mypreferences": "Preferèntzias mias",
        "prefs-edits": "Nùmeru de acontzos:",
        "prefs-skin": "Bisura",
        "skin-preview": "Antiprima",
+       "datedefault": "Peruna preferèntzia",
+       "prefs-user-pages": "Paginas impitadore",
        "prefs-personal": "Datos personales",
        "prefs-rc": "Ùrtimas mudàntzias",
        "prefs-watchlist": "Watchlist",
+       "prefs-watchlist-days-max": "Màssimu $1 {{PLURAL:$1|die|dies}}",
+       "prefs-watchlist-edits-max": "Cantidade màssima: 1000",
        "prefs-misc": "Àteras preferèntzias",
        "prefs-resetpass": "Càmbia password",
+       "prefs-email": "Sèberos pro sa email",
+       "prefs-rendering": "Aparèntzia",
        "saveprefs": "Sarva preferèntzias",
+       "restoreprefs": "Restàura totu is sèberos predefinidos (in totu is setziones)",
        "prefs-editing": "Box de acontzadura",
        "rows": "Lìnias:",
        "columns": "Colunnas:",
-       "searchresultshead": "Settaggio delle preferenze per la ricerca",
+       "searchresultshead": "Chirca",
        "stub-threshold-disabled": "Disativadu",
+       "recentchangesdays": "Dies de ammustrare in ùrtimas mudàntzias:",
        "recentchangescount": "Nùmeru de acontzos de amostare pro definidura:",
        "savedprefs": "Is preferèntzias tuas sunt stadas sarbadas.",
        "timezonelegend": "Zona de oràriu:",
        "timezoneregion-antarctica": "Antàrtide",
        "timezoneregion-arctic": "Àrtide",
        "timezoneregion-asia": "Àsia",
+       "timezoneregion-atlantic": "Otzèanu Atlànticu",
        "timezoneregion-australia": "Austràlia",
        "timezoneregion-europe": "Europa",
-       "prefs-searchoptions": "Possibilidades a subra de sa chirca",
+       "timezoneregion-indian": "Otzèanu Indianu",
+       "timezoneregion-pacific": "Otzèanu Patzìficu",
+       "prefs-searchoptions": "Chirca",
        "prefs-namespaces": "Nùmene-logos",
+       "default": "predefinidu",
        "prefs-files": "Files",
-       "youremail": "E-mail:",
-       "username": "Nùmene usuàriu:",
+       "prefs-emailconfirm-label": "Cunfirma de sa email:",
+       "youremail": "Email:",
+       "username": "{{GENDER:$1|Nùmene impitadore}}:Nùmene impitadore",
        "prefs-registration": "Ora de registratzione:",
        "yourrealname": "Nùmene beru:",
        "yourlanguage": "Limba:",
        "yournick": "Sa firma tua:",
-       "yourgender": "Natura:",
-       "gender-unknown": "Non spetzificadu",
-       "gender-male": "Mascu",
-       "gender-female": "Fèmina",
+       "yourgender": "Comente preferes a ti descrir?",
+       "gender-unknown": "Preferu a no ddu narrer",
+       "gender-male": "Issu càmbiat pàginas wiki",
+       "gender-female": "Issa càmbiat pàginas wiki",
        "email": "E-mail",
        "prefs-info": "Informatzione bàsica",
        "prefs-signature": "Firma",
        "prefs-dateformat": "Formadu data",
-       "prefs-advancedediting": "Sèberos avantzados",
+       "prefs-advancedediting": "Sèberos generales",
+       "prefs-preview": "Antiprima",
        "prefs-advancedrc": "Sèberos avantzados",
        "prefs-advancedrendering": "Sèberos avantzados",
        "prefs-advancedsearchoptions": "Sèberos avantzados",
        "prefs-advancedwatchlist": "Sèberos avantzados",
+       "prefs-tokenwatchlist": "Token",
        "prefs-diffs": "Diferèntzias",
-       "userrights-user-editname": "Inserta unu nùmene usuàriu:",
-       "editinguser": "Cambiamentu de is deretos usuàriu de s'usuàriu '''[[User:$1|$1]]''' ([[User talk:$1|{{int:talkpagelinktext}}]]{{int:pipe-separator}}[[Special:Contributions/$1|{{int:contribslink}}]])",
+       "userrights-user-editname": "Inserta unu nùmene impitadore:",
+       "editinguser": "Cambiamentu de is deretos impitadore de s'impitadore <strong>[[User:$1|$1]]</strong> $2",
+       "userrights-groupsmember": "Membru de:",
        "userrights-reason": "Motivu:",
        "userrights-irreversible-marker": "$1*",
        "group": "Grupu:",
        "group-bot": "Bots",
        "group-sysop": "Amministradores",
        "group-bureaucrat": "Buròcrates",
+       "group-suppress": "Tzensores",
        "group-all": "(totus)",
-       "group-user-member": "Usuàriu",
-       "group-autoconfirmed-member": "Autocunfirmados usuàrios",
-       "group-bot-member": "Bot",
-       "group-sysop-member": "Amministradore",
-       "group-bureaucrat-member": "burocrate",
+       "group-user-member": "{{GENDER:$1|impitadore}}",
+       "group-autoconfirmed-member": "{{GENDER:$1|usuàrios autocunfirmados}}",
+       "group-bot-member": "{{GENDER:$1|bot}}",
+       "group-sysop-member": "{{GENDER:$1|aministradore}}",
+       "group-bureaucrat-member": "{{GENDER:$1|buròcrate}}",
+       "group-suppress-member": "{{GENDER:$1|tzensore}}",
        "grouppage-user": "{{ns:project}}:Usuàrios",
        "grouppage-autoconfirmed": "{{ns:project}}:Usuàrios autocunfirmadus",
        "grouppage-bot": "{{ns:project}}:Bots",
        "grouppage-sysop": "{{ns:project}}:Amministradores",
        "grouppage-bureaucrat": "{{ns:project}}:Burocrates",
+       "grouppage-suppress": "{{ns:project}}:Tzensore",
        "right-read": "Lègere pàginas",
-       "right-edit": "Acontzare pàginas",
+       "right-edit": "Cambiare pàginas",
+       "right-createpage": "Creare pàginas (chi non siant pàgina de cuntierra)",
+       "right-createtalk": "Creare pàginas de cuntierra",
+       "right-createaccount": "Creare contos de impitadores noos",
+       "right-minoredit": "Marcare su càmbiu che minore",
        "right-move": "Mòver pàginas",
        "right-move-subpages": "Mòvere pàginas cun is suta-pàginas issoru",
        "right-move-rootuserpages": "Mòvere is pàginas base de is usuàrios",
+       "right-move-categorypages": "Mòvere pàginas de categorias",
        "right-movefile": "Mòvere files",
        "right-upload": "Carrigare files",
        "right-reupload": "Subra-iscrìere files esistentes",
        "right-reupload-own": "Subra-iscrìere files esistentes carrigados dae issetotu",
        "right-upload_by_url": "Carrigare files dae unu URL",
-       "right-autoconfirmed": "Acontzare pàginas mesu-amparadas",
+       "right-autoconfirmed": "No tenet lìmite de atziones pro indiritzos IP",
        "right-delete": "Fuliare pàginas",
        "right-browsearchive": "Chircare pàginas fuliadas",
        "right-undelete": "Restaurare una pàgina",
+       "right-suppressionlog": "Càstia is registros privados",
        "right-siteadmin": "Bloccare e sbloccare su database",
-       "newuserlogpage": "Usuàrios nous",
+       "newuserlogpage": "Impitadores nous",
        "rightslog": "Deretos de is usuàrios",
        "action-read": "lègher custa pàgina",
-       "action-edit": "acontzare custa pàgina",
+       "action-edit": "cambiare custa pàgina",
        "action-createpage": "creare pàginas",
        "action-move": "mòvere custa pàgina",
        "action-movefile": "mòvere custu file",
+       "action-upload": "carriga custu archìviu",
        "action-delete": "burrare custa pàgina",
        "action-browsearchive": "chircare pàginas fuliadas",
+       "action-sendemail": "imbiare emails",
+       "action-editmywatchlist": "cambiare sa lista de is pàginas annotadas tua",
+       "action-viewmywatchlist": "castiare sa lista de pàginas annotadas tua",
+       "action-viewmyprivateinfo": "castiare is informatzione privadas tuas",
+       "action-editmyprivateinfo": "cambiare is informatziones privadas tuas",
        "nchanges": "$1 {{PLURAL:$1|mudàntzia|mudàntzias}}",
+       "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|dae s'ùrtima bisita}}",
+       "enhancedrc-history": "istòria",
        "recentchanges": "Ùrtimas mudàntzias",
-       "recentchanges-legend": "Possibilidades subra ùrtimas mudàntzias",
-       "recentchanges-feed-description": "Custu feed riportada is ùrtimas mudàntzias a is cuntènnidos de su giassu.",
-       "recentchanges-label-newpage": "Custu acontzu at creadu una pàgina noa",
-       "recentchanges-label-minor": "Custu est unu acontzu minore",
-       "recentchanges-label-bot": "Custu acontzu est stadu fatu dae unu bot",
-       "recentchanges-legend-newpage": "$1 - pàgina noa",
-       "rcnotefrom": "Sas chi sighint sunt sas mudàntzias dae '''$2''' (fintzas a '''$1''').",
+       "recentchanges-legend": "Optziones subra ùrtimas mudàntzias",
+       "recentchanges-summary": "Sighi is ùrtimas mudàntzias a sa wiki in custa pàgina.",
+       "recentchanges-feed-description": "Sighi is ùrtimas mudàntzias a sa wiki cun custu feed.",
+       "recentchanges-label-newpage": "Custu càmbiu at creadu una pàgina noa",
+       "recentchanges-label-minor": "Custu est unu càmbiu minore",
+       "recentchanges-label-bot": "Custu càmbiu est stadu fatu dae unu bot",
+       "recentchanges-label-unpatrolled": "Custu càmbiu no est istadu cumprobadu",
+       "recentchanges-label-plusminus": "Sa muda de sa mannesa de sa pàgina dae su nùmeru de bytes",
+       "recentchanges-legend-heading": "'''Legenda:'''",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (càstia [[Special:NewPages|is pàginas noas]])",
+       "rcnotefrom": "{{PLURAL:$5|Sa chi sighit est sa mudàntzia|Is chi sighint sunt is mudàntzias}} dae <strong>$3, $4</strong> (ammustradas fintzas a <strong>$1</strong>).",
        "rclistfrom": "Ammustra mudàntzias dae $3 $2",
-       "rcshowhideminor": "$1 acontzos minores",
-       "rcshowhideminor-show": "Amosta",
+       "rcshowhideminor": "$1 is càmbios minores",
+       "rcshowhideminor-show": "Ammustra",
        "rcshowhideminor-hide": "Cua",
-       "rcshowhidebots": "$1 bots",
-       "rcshowhidebots-show": "Amosta",
+       "rcshowhidebots": "$1 is bots",
+       "rcshowhidebots-show": "Ammustra",
        "rcshowhidebots-hide": "Cua",
-       "rcshowhideliu": "$1 usuàrios intraus",
-       "rcshowhideliu-show": "Amosta",
+       "rcshowhideliu": "$1 is impitadores identificados",
+       "rcshowhideliu-show": "Ammustra",
        "rcshowhideliu-hide": "Cua",
-       "rcshowhideanons": "$1 usuàrios anònimos",
-       "rcshowhideanons-show": "Amosta",
+       "rcshowhideanons": "$1 is impitadores anònimos",
+       "rcshowhideanons-show": "Ammustra",
        "rcshowhideanons-hide": "Cua",
-       "rcshowhidepatr-show": "Amosta",
+       "rcshowhidepatr": "$1 càmbios cumprobados",
+       "rcshowhidepatr-show": "Ammustra",
        "rcshowhidepatr-hide": "Cua",
-       "rcshowhidemine": "$1 acontzos meos",
-       "rcshowhidemine-show": "Amosta",
+       "rcshowhidemine": "$1 is càmbios mios",
+       "rcshowhidemine-show": "Ammustra",
        "rcshowhidemine-hide": "Cua",
        "rclinks": "Ammustra is ùrtimas $1 mudàntzias fatas in is ùrtimas $2 dies<br />$3",
        "diff": "dif",
        "rc_categories_any": "Calesisiat",
        "rc-change-size": "$1",
        "newsectionsummary": "/* $1 */ setzione noa",
-       "rc-enhanced-expand": "Ammustra particulares (esigit JavaScript)",
+       "rc-enhanced-expand": "Ammustra particulares",
        "rc-enhanced-hide": "Cua particulares",
        "recentchangeslinked": "Mudàntzias ligadas",
        "recentchangeslinked-feed": "Mudàntzias ligadas",
        "recentchangeslinked-toolbox": "Mudàntzias ligadas",
        "recentchangeslinked-title": "Mudàntzias ligadas a \"$1\"",
-       "recentchangeslinked-summary": "Custa est una lista de is mudàntzias fatas dae pagu a is pàginas ligadas a cussa spetzificada.\nIs pàginas de sa [[Special:Watchlist|watchlist tua]] sunt in '''grassu'''.",
+       "recentchangeslinked-summary": "Custa est una lista de is mudàntzias fatas dae pagu a is pàginas ligadas a cussa spetzificada.\nIs pàginas [[Special:Watchlist|annotadas dae tue]] sunt in <strong>grassu</strong>.",
        "recentchangeslinked-page": "Nùmene pàgina:",
        "recentchangeslinked-to": "Ammustra feti mudàntzias a pàginas ligadas a cussa spetzificada",
        "upload": "Càrriga file",
        "uploadbtn": "Càrriga file",
        "reuploaddesc": "Torra a su mòdulu pro su carrigamentu.",
        "uploadnologin": "Non ses intrau",
-       "uploadnologintext": "Depes èsser [[Special:UserLogin|identificadu (log in)]] pro carrigare files.",
+       "uploadnologintext": "Depes èsser $1 pro carrigare files.",
        "uploaderror": "Faddina de carrigamentu",
        "uploadtext": "Imprea su modulu a suta pro carrigare files nous.\nPro castiare o chircare is files giai carrigaus, bae a sa [[Special:FileList|lista de is files carrigaus]]. Carrigamentos de files e de noas versiones de files sunt registradas in su [[Special:Log/upload|registru de carrigamentu]], is burraduras in su [[Special:Log/delete|registru burraduras]].\n\nPro insertare unu file aintru de una pàgina, tocat a faghere unu cullegamentu tipu custu:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code>''' pro impreare sa versione cumpleta de su file\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|testo alternativo]]</nowiki></code>''' pro impreare una versione lada 200 pixel insertada in d'unu box, allinniada a manca e cun 'testu alternativu' comente didascalia\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' pro ingenerare unu cullegamentu a su file chentza de du biri",
        "uploadlogpage": "Carrigadas",
        "badfilename": "Su nùmene de su file est stadu cunvertidu in \"$1\".",
        "uploadwarning": "Avvisu de carrigamentu",
        "savefile": "Sarva file",
-       "uploadedimage": "carrigadu \"[[$1]]\"",
        "upload-source": "File de orìgine",
        "sourcefilename": "Nùmene de su file de orìgine:",
        "sourceurl": "Diretzione originària:",
        "destfilename": "Nùmene de su file de destinatzione:",
        "upload-description": "Descritzione de su file",
        "upload-success-subj": "Carrigamentu acabau",
+       "upload-failure-subj": "Problema de carrimentu",
        "upload-file-error": "Faddina a intru",
-       "license": "Licèntzia:",
-       "license-header": "Licèntzia",
-       "upload_source_file": " (unu file in su computer tuo)",
+       "img-auth-nofile": "Su File \"$1\" no esistit.",
+       "img-auth-streaming": "Letura currente de \"$1\".",
+       "license": "Litzèntzia:",
+       "license-header": "Litzèntzia",
+       "nolicense": "Nisciuna litzèntzia indicada",
+       "licenses-edit": "Càmbia su sèberu de sa licèntzia",
+       "upload_source_file": "(su file seberadu in su computer tuo)",
+       "listfiles-delete": "Cantzella",
        "imgfile": "file",
        "listfiles": "Lista de is files",
+       "listfiles_thumb": "Miniatura",
        "listfiles_date": "Data",
        "listfiles_name": "Nùmene",
-       "listfiles_user": "Usuàriu",
+       "listfiles_user": "Impitadore",
        "listfiles_size": "Mannesa in byte",
        "listfiles_description": "Descritzione",
        "listfiles_count": "Versiones",
+       "listfiles-latestversion-yes": "Eja",
+       "listfiles-latestversion-no": "No",
        "file-anchor-link": "File",
        "filehist": "Stòria de su file",
        "filehist-help": "Carca unu grupu data/ora pro castiare su file comente si presentada in su tempus indicadu.",
        "filehist-deleteall": "fùlia totu",
        "filehist-deleteone": "cantzella",
        "filehist-revert": "fùrria",
-       "filehist-current": "currente",
+       "filehist-current": "atuale",
        "filehist-datetime": "Data/Ora",
        "filehist-thumb": "Miniatura",
        "filehist-thumbtext": "Miniatura de sa versione de is $1",
        "filehist-nothumb": "Peruna miniatura",
-       "filehist-user": "Usuàriu",
+       "filehist-user": "Impitadore",
        "filehist-dimensions": "Dimensiones",
        "filehist-filesize": "Mannesa de su file",
        "filehist-comment": "Cummentu",
        "imagelinks": "Ligant a custu file",
-       "linkstoimage": "{{PLURAL:$1|Sa pàgina ki sighit ligat|Is $1 pàginas ki sighint ligant}} a custu file:",
+       "linkstoimage": "{{PLURAL:$1|Sa pàgina chi sighit ligat|Is $1 pàginas chi sighint ligant}} a custu file:",
        "nolinkstoimage": "Peruna pàgina ligat a custu file.",
-       "sharedupload": "Custu file benit dae $1 e podet èssere impreau in àteros progetos.",
+       "linkstoimage-redirect": "$1 (reindiritzamentu file) $2",
+       "sharedupload": "Custu file benit dae $1 e podet èssere impreadu in àteros progetos.",
+       "sharedupload-desc-here": "Custu documentu benit dae $1 e podet èssere impreadu in àteros progetos.\nA sighire est ammustrada sa descritzione in sa sua [$2 pàgina de descritzione de su documentu].",
        "uploadnewversion-linktext": "Carriga una versione noa de custu file",
        "shared-repo-from": "dae $1",
        "filerevert-comment": "Motivu:",
        "filedelete": "Cantzella $1",
        "filedelete-legend": "Cantzella su file",
+       "filedelete-comment": "Motivu:",
        "filedelete-submit": "Cantzella",
        "filedelete-success": "Su file '''$1''' est istadu fuliau.",
+       "filedelete-otherreason": "Motivu diversu o agiuntivu:",
        "filedelete-reason-otherlist": "Àteru motivu",
+       "mimesearch": "Chirca MIME",
+       "mimetype": "Genia MIME:",
        "download": "scàrriga",
        "listredirects": "Lista de totu is redirects",
+       "unusedtemplateswlh": "àteros ligòngios",
        "randompage": "Pàgina a sa tzurpa",
+       "randomincategory-category": "Categoria:",
        "statistics": "Statìsticas",
+       "statistics-header-pages": "Statìsticas subra is pàginas",
        "statistics-header-users": "Statìsticas subra is usuàrios",
        "statistics-pages": "Pàginas",
+       "pageswithprop-submit": "Bae",
        "doubleredirects": "Redirects dòpios",
        "doubleredirectstext": "Custa pàgina cuntenet una lista de pàginas ki re-indiritzant a àteras pàginas de re-indiritzamentu.\nOgni lìnia cuntenet ligàmines a su primu e a su de duos re-indiritzamentu, aici comente sa prima lìnia de sa de duos re-indiritzamentos, chi de sòlitu adòbiat s'artìculu \"beru\", a sa cale fintzas su primu re-indiritzamentu dia depet puntare.\nIs re-indiritzamentos <del>cantzellados</del> sunt stados curretos.",
        "brokenredirects": "Redirects isballiaus",
        "brokenredirectstext": "Custus redirects ligant cun pàginas chi no esistint.",
-       "brokenredirects-edit": "acontza",
+       "brokenredirects-edit": "càmbia",
        "brokenredirects-delete": "cantzella",
        "withoutinterwiki-legend": "Prefissu",
        "withoutinterwiki-submit": "Ammustra",
        "nrevisions": "$1 {{PLURAL:$1|revisione|revisiones}}",
        "nviews": "$1 {{PLURAL:$1|bisura|bisuras}}",
        "lonelypages": "Pàginas burdas",
+       "uncategorizedpages": "Pàginas chentza categoria",
+       "uncategorizedcategories": "Categorias chentza categoria",
+       "uncategorizedimages": "Documentos chentza categoria",
+       "uncategorizedtemplates": "Templates chentza categoria",
+       "unusedcategories": "Categorias no impreadas",
        "unusedimages": "Files no impreaus",
        "popularpages": "Pàginas populares",
+       "wantedcategories": "Categorias chircadas",
        "wantedpages": "Artìculos prus chircados",
+       "wantedfiles": "Documentos chircados",
+       "wantedtemplates": "Templates chircados",
+       "mostlinked": "Pàginas su prus ligadas",
+       "mostlinkedcategories": "Categorias su prus ligadas",
+       "mostimages": "Documentos su prus ligados",
        "mostrevisions": "Pàginas cun prus revisiones",
        "prefixindex": "Ìndighe de is pàginas pro initziales",
        "shortpages": "Pàginas crutzas",
        "longpages": "Pàginas longas",
        "deadendpages": "Pàginas chentza bessida",
        "protectedpages": "Pàginas amparadas",
+       "protectedpages-page": "Pàgina",
+       "protectedpages-expiry": "Iscadit",
+       "protectedpages-reason": "Motivu",
+       "protectedpages-unknown-timestamp": "Isconnottu",
        "protectedtitles": "Tìtulus amparadus",
        "listusers": "Lista usuàrios",
        "usereditcount": "$1 {{PLURAL:$1|acontzu|acontzos}}",
-       "usercreated": "Creadu su $1 a is $2",
+       "usercreated": "{{GENDER:$3|Creadu}} su $1 a is $2",
        "newpages": "Pàginas noas",
-       "newpages-username": "Nùmene usuàriu:",
-       "move": "Movi",
+       "newpages-username": "Nùmene impitadore:",
+       "move": "Move",
        "movethispage": "Move custa pàgina (càmbia su tìtulu)",
-       "unusedimagestext": "Is files ki sighint sunt stados carrigados ma non sunt impreados.\nDia podent essere immàgines impreadas dae àteros giassos cun unu ligàmine diretu, e tando podent essere listados inoghe comente usu ativu.",
+       "unusedimagestext": "Is documentos chi sighint sunt istados carrigados ma non sunt impreados.\nDia podent èssere immàgines impreadas dae àteros giassos cun unu ligòngiu diretu, e tando podent èssere listados inoghe comente usu ativu.",
        "notargettitle": "Perunu obietivu",
-       "notargettext": "Non hai specificato una pagina o un Utente in relazione al quale eseguire l'operazione richiesta.",
+       "notargettext": "Non as ispetzificadu una pàgina o unu impitadore pro issucutare custa funtzione.",
        "pager-newer-n": "{{PLURAL:$1|1 prus nou|$1 prus nous}}",
        "pager-older-n": "{{PLURAL:$1|1 prus betzu|$1 prus betzos}}",
        "booksources": "Fontes libràrias",
        "booksources-search-legend": "Chirca fontes libràrias",
        "booksources-isbn": "ISBN:",
        "booksources-go": "Bae",
-       "specialloguserlabel": "Usuàriu:",
-       "speciallogtitlelabel": "Tìtulu:",
+       "specialloguserlabel": "Atzione fata dae:",
+       "speciallogtitlelabel": "Atzione fata subra:",
        "log": "Registros",
        "allpages": "Totu is pàginas",
        "prevpage": "Pàgina in antis ($1)",
        "allpages-bad-ns": "Su nùmene-logu \"$1\" non esistit in {{SITENAME}}.",
        "categories": "Categorias",
        "sp-deletedcontributions-contribs": "contributziones",
-       "linksearch": "Acàpios a foras",
+       "linksearch": "Chirca acàpios de foras",
        "linksearch-ns": "Nùmene-logu:",
        "linksearch-ok": "Chirca",
+       "linksearch-line": "$1 est ligadu in sa pàgina $2",
        "listusers-submit": "Ammustra",
+       "listusers-blocked": "(blocadu)",
        "activeusers-hidebots": "Cua bots",
        "activeusers-hidesysops": "Cua amministradores",
        "listgrouprights-group": "Grupu",
+       "listgrouprights-rights": "Deretos",
        "listgrouprights-members": "(lista de is cumponentes)",
+       "listgrouprights-namespaceprotection-namespace": "Nùmene-logu",
        "mailnologintext": "Depes èsser [[Special:UserLogin|identificadu (login)]] e àer registradu un'indiritzu e-mail vàlidu in is [[Special:Preferences|preferèntzias tuas]] pro imbiare e-mail a àteros usuàrios.",
-       "emailuser": "E-mail a custu usuàriu",
-       "emailpage": "Ispedi una missada a s'usuàriu",
-       "emailpagetext": "Imprea su mòdulu a suta pro ispedire una missada eletrònica a custu usuàriu.\nS'indiritzu chi as insertadu in is [[Special:Preferences|preferèntzias usuàriu tuas]] at a pàrrere comente su chi at ispedidu sa e-mail, pro fàghere sa manera chi su destinatàriu ti respundat deretu.",
-       "defemailsubject": "Missada dae {{SITENAME}}",
+       "emailuser": "Imbia una email a custu impitadore",
+       "emailuser-title-notarget": "Ispedi una email a s'impitadore",
+       "emailpage": "Ispedi una email a s'impitadore",
+       "emailpagetext": "Imprea su mòdulu a suta pro ispedire una email a custu impitadore.\nS'indiritzu chi as insertadu in is [[Special:Preferences|preferèntzias impitadore tuas]] at a pàrrere comente su chi at ispedidu sa e-mail, pro fàghere sa manera chi su destinatàriu ti respundat deretu.",
+       "defemailsubject": "Missada dae \"$1\", impitadore de {{SITENAME}}",
        "noemailtitle": "Perunu indiritzu e-mail",
-       "noemailtext": "Custu usuàriu no at ispetzificadu un indiritzu e-mail vàlidu.",
-       "email-legend": "Imbia una missada e-mail a un àteru usuàriu de {{SITENAME}}",
+       "noemailtext": "Custu impitadore no at ispetzificadu unu indiritzu email vàlidu.",
+       "emailusername": "Nùmene impitadore:",
+       "email-legend": "Imbia una missada e-mail a un àteru impitadore de {{SITENAME}}",
        "emailfrom": "Dae:",
        "emailto": "A:",
        "emailsubject": "Ogetu:",
        "emailsent": "E-mail ispedia",
        "emailsenttext": "Sa e-mail tua est istada imbiada.",
        "usermessage-editor": "Missu de su sistema",
-       "watchlist": "Sa watchlist mea",
+       "watchlist": "Pàginas annotadas",
        "mywatchlist": "Pàginas annotadas",
+       "watchlistfor2": "Pro $1 $2",
        "nowatchlist": "No as indicadu pàginas in sa watchlist tua.",
        "watchnologin": "No intrau (log in)",
-       "addedwatchtext": "Sa pàgina \"[[:$1]]\" est istada aciunta a sa [[Special:Watchlist|watchlist]] tua.\nIs mudàntzias de custa pàgina e de sa pàgina de cuntierras sua ant a bennere elencadas inoe, e su tìtulu at a aparire in '''grassetto''' in sa pàgina de is [[Special:RecentChanges|ùrtimas mudàntzias]] pro du bidere mengius.",
+       "addedwatchtext": "Sa pàgina \"[[:$1]]\" est istada aciunta a sa [[Special:Watchlist|watchlist]] tua.\nIs mudàntzias de custa pàgina e de sa pàgina de cuntierras sua ant a benner elencadas inoe.",
        "removedwatchtext": "Sa pàgina  \"[[:$1]]\" est istada tirada dae sa [[Special:Watchlist|watchlist tua]].",
-       "watch": "Pone in sa watchlist",
+       "watch": "Annota",
        "watchthispage": "Pone ogru a custu artìculu",
-       "unwatch": "Tira dae sa watchlist",
+       "unwatch": "Tira dae is pàginas annotadas",
        "unwatchthispage": "Boga custa pàgina dae sa watchlist tua",
        "notanarticle": "Custa pàgina no est unu artìculu",
-       "watchlist-details": "Sa watchlist tua cuntènnit {{PLURAL:$1|$1 pàgina|$1 pàginas}}, chentza contare is pàginas de cuntierras.",
+       "watchlist-details": "Tenes {{PLURAL:$1|$1 pàgina annotada paris a sa pagina de cuntierra sua|$1 pàginas annotadas paris a is pàginas de cuntierra issoro}}.",
        "wlshowlast": "Ammustra is ùrtimas $1 oras $2 dies $3",
-       "watchlist-options": "Possibilidades subra sa watchlist",
+       "watchlist-options": "Optziones subra sa lista de pàginas annotadas",
        "watching": "Giunghende a sa watchlist...",
        "unwatching": "Boghende dae sa watchlist...",
-       "enotif_impersonal_salutation": "Usuàriu de {{SITENAME}}",
+       "enotif_impersonal_salutation": "Impitadore de {{SITENAME}}",
+       "enotif_anon_editor": "impitadore anònimu $1",
        "created": "creada",
        "deletepage": "Fùlia pàgina",
        "confirm": "Cunfima",
        "rollback": "Annudda is acontzos",
        "rollbacklink": "rollback",
        "rollbackfailed": "Rollback faddidu",
-       "cantrollback": "Non si podet furriare s'acontzu;\ns'ùrtimu contribuidore est s'ùnicu autore de custa pàgina.",
+       "cantrollback": "Non si podet furriare sa modìfica;\ns'ùrtimu contribuidore est s'ùnicu autore de custa pàgina.",
        "revertpage": "Burradas is mudàntzias de [[Special:Contributions/$2|$2]] ([[User talk:$2|cuntierras]]), torrada a sa versione cabudiana de [[User:$1|$1]]",
-       "protectlogpage": "Amparaduras",
-       "protectedarticle": "at amparau \"[[$1]]\"",
+       "protectlogpage": "Bardaduras",
+       "protectedarticle": "at bardadu \"[[$1]]\"",
        "modifiedarticleprotection": "at cambiau su livellu de amparadura pro \"[[$1]]\"",
+       "prot_1movedto2": "[[$1]] est istada mòvida a [[$2]]",
+       "protect-legend": "Cunfirma amparadura",
        "protectcomment": "Motivu:",
        "protectexpiry": "Iscadèntzia:",
        "protect_expiry_invalid": "S'iscadèntzia est imbàlida.",
        "protect_expiry_old": "Iscadentzia giai passada.",
        "protect-text": "Custu modulu serbit pro castiari e cambiari su livellu de amparadura de sa pàgina '''$1'''.",
        "protect-locked-access": "Non tenes su permissu pro cambiare is livellus de amparadura de sa pàgina.\nIs impostatziones atuales pro sa pàgina '''$1''':",
-       "protect-cascadeon": "A su momentu custa pàgina est bloccada pro ite est inclùdia {{PLURAL:$1|in sa pàgina indicada a suta, pro sa cali|in is pàginas indicadas a suta, pro is calis}} est ativa s'amparadura ricorsiva. Est possìbile cambiare su livellu de amparadura de custa pàgina, ma is impostatziones derivadas dae s'amparadura ricorsiva non ant a èssere mudadas.",
+       "protect-cascadeon": "A su momentu custa pàgina est bardada pro ite est inclùdida {{PLURAL:$1|in sa pàgina indicada a suta, pro sa cale|in is pàginas indicadas a suta, pro is cales}} est ativa sa bardadura ricorsiva.\nEst possìbile cambiare su livellu de bardadura de custa pàgina, ma is efetos derivados dae sa bardadura ricorsiva non ant a èssere mudados.",
        "protect-default": "Autoritza totu is usuàrios",
-       "protect-fallback": "Esigit su permissu \"$1\"",
-       "protect-level-autoconfirmed": "Blocca is usuàrios nobos o non registrados",
-       "protect-level-sysop": "Isceti aministradores",
+       "protect-fallback": "Permìtidu feti a is impitadores cun su permissu \"$1\"",
+       "protect-level-autoconfirmed": "Permìtidu feti a is impitadores autocunfimados",
+       "protect-level-sysop": "Permìtidu feti a is amministradores",
        "protect-summary-cascade": "ricorsiva",
        "protect-expiring": "iscadèntzia: $1 (UTC)",
+       "protect-expiring-local": "iscadit su $1",
        "protect-cascade": "Ampara totu is pàginas inclùdias in custa (amparadura ricorsiva)",
-       "protect-cantedit": "Non podes cambiare is livellus de amparadura pro sa pàgina, pro ite non tenes su permissu de acontzare sa pàgina etotu.",
+       "protect-cantedit": "Non podes cambiare is livellus de amparadura pro sa pàgina, pro ite non tenes su permissu de cambiare sa pàgina etotu.",
        "protect-othertime": "Àteru perìodu:",
+       "protect-othertime-op": "àteru perìodu",
+       "protect-otherreason": "Motivu diversu o agiuntivu:",
+       "protect-otherreason-op": "Àteru motivu",
        "protect-expiry-options": "1 ora:1 hour,1 die:1 day,1 chida:1 week,2 chidas:2 weeks,1 mese:1 month,3 meses:3 months,6 meses:6 months,1 annu:1 year,infinidu:infinite",
        "restriction-type": "Permissu:",
        "restriction-level": "Livellu de restritzioni:",
        "undeleterevisions": "$1 {{PLURAL:$1|revisione|revisiones}} in archìviu",
        "undeletehistory": "Restaurende custa pàgina, totu is revisiones ant a torrare in sa istòria sua.\nChi est istada creada una pàgina cun su matessi tìtulu, is revisiones recuperadas ant a insertare in sa istoria in antis.",
        "undeletebtn": "Ripristina",
-       "undeletelink": "càstia/riprìstina",
-       "undeleteviewlink": "abbista",
+       "undeletelink": "càstia/torra che prima",
+       "undeleteviewlink": "ammustra",
        "undeleteinvert": "Fùrria sa seletzione",
        "undeletecomment": "Motivu:",
        "undeletedrevisions": "{{PLURAL:$1|1 revisione restaurada|$1 revisiones restauradas}}",
        "undeletedrevisions-files": "{{PLURAL:$1|1 revisione|$1 revisiones}} e {{PLURAL:$2|1 file|$2 files}} restaurados",
        "undeletedfiles": "{{PLURAL:$1|1 file restauradu|$1 files restaurados}}",
+       "undelete-search-title": "Chirca pàginas burradas",
        "undelete-search-box": "Chirca pàginas fuliadas",
        "undelete-search-prefix": "Ammustra is pàginas ca su tìtulu cumentzat cun:",
        "undelete-search-submit": "Chirca",
        "undelete-show-file-submit": "Eja",
        "namespace": "Nùmene-logu:",
        "invert": "Fùrria sa seletzione",
+       "namespace_association": "Nùmene-logu assotziadu",
        "blanknamespace": "(Printzipale)",
-       "contributions": "Contributziones usuàriu",
+       "contributions": "Contributos {{GENDER:$1|impitadore}}",
        "contributions-title": "Contributziones de $1",
-       "mycontris": "Contributziones meas",
-       "contribsub2": "Pro $1 ($2)",
+       "mycontris": "Contributos mios",
+       "contribsub2": "Pro {{GENDER:$3|$1}} ($2)",
        "nocontribs": "Nessuna modifica trovata conformemente a questi criteri.",
-       "uctop": "(ùrtimu de sa pàgina)",
-       "month": "Dae su mese (e in antis):",
-       "year": "Dae s'annu (e in antis):",
-       "sp-contributions-newbies": "Ammustra feti is contributziones de is accounts noos",
+       "uctop": "(atuale)",
+       "month": "Dae su mese (e in segus):",
+       "year": "Dae s'annu (e in segus):",
+       "sp-contributions-newbies": "Ammustra feti is contributziones de is contos noos",
+       "sp-contributions-newbies-sub": "Pro is contos noos",
        "sp-contributions-blocklog": "registru de is bloccos",
+       "sp-contributions-uploads": "carrigamentos",
+       "sp-contributions-logs": "registros",
        "sp-contributions-talk": "cuntierra",
-       "sp-contributions-search": "Chirca contributziones",
-       "sp-contributions-username": "Indiritzu IP o nùmene usuàriu:",
+       "sp-contributions-search": "Chirca contributos",
+       "sp-contributions-username": "Indiritzu IP o nùmene impitadore:",
+       "sp-contributions-toponly": "Ammustra feti is contributos chi sunt is ùrtimas versiones pro sa pàgina",
+       "sp-contributions-newonly": "Ammustra feti is càmbios chi ant creadu pàginas noas",
        "sp-contributions-submit": "Chirca",
        "whatlinkshere": "Pàginas chi ligant a custa",
        "whatlinkshere-title": "Pàginas chi ligant a \"$1\"",
        "whatlinkshere-page": "Pàgina:",
-       "linkshere": "Sas pàginas chi sighint ligant a '''[[:$1]]''':",
+       "linkshere": "Is pàginas chi sighint ligant a '''[[:$1]]''':",
        "nolinkshere": "Peruna pàgina ligat a '''[[:$1]]'''.",
        "nolinkshere-ns": "Peruna pàgina ligat a '''[[:$1]]''' in su nùmene-logu seberadu.",
-       "isredirect": "redirect",
+       "isredirect": "pàgina de reindiritzamentu",
        "istemplate": "inclusione",
-       "isimage": "acàpiu pintura",
-       "whatlinkshere-prev": "{{PLURAL:$1|cabudianu|cabudianos $1}}",
+       "isimage": "ligòngiu a documentu",
+       "whatlinkshere-prev": "{{PLURAL:$1|pretzedente|pretzedentes $1}}",
        "whatlinkshere-next": "{{PLURAL:$1|imbeniente|imbenientes $1}}",
-       "whatlinkshere-links": "← acàpius",
-       "whatlinkshere-hideredirs": "$1 redirects",
-       "whatlinkshere-hidetrans": "$1 inclusionis",
-       "whatlinkshere-hidelinks": "$1 acàpius",
+       "whatlinkshere-links": "← ligòngios",
+       "whatlinkshere-hideredirs": "$1 is reindiritzamentos",
+       "whatlinkshere-hidetrans": "$1 inclusiones",
+       "whatlinkshere-hidelinks": "$1 ligòngios",
+       "whatlinkshere-hideimages": "$1 is ligòngios a documentu",
        "whatlinkshere-filters": "Filtros",
-       "blockip": "Blocca usuàriu",
-       "blockip-legend": "Blocca usuàriu",
+       "blockip": "Blocca {{GENDER:$1|impitadore}}",
+       "blockip-legend": "Blocca impitadore",
        "blockiptext": "Usa il modulo sottostante per bloccare l'accesso con diritto di scrittura da uno specifico indirizzo IP. Questo blocco deve essere operato SOLO per prevenire atti di vandalismo, ed in stretta osservanza dei principi tutti della [[{{MediaWiki:Policy-url}}|policy di {{SITENAME}}]]. Il blocco non può in nessun caso essere applicato per motivi ideologici.\nScrivi un motivo specifico per il quale questo indirizzo IP dovrebbe a tuo avviso essere bloccato (per esempio, cita i titoli di pagine eventualmente già oggetto di vandalismo editoriale).",
-       "ipaddressorusername": "Indiritzu IP o nùmene usuàriu:",
+       "ipaddressorusername": "Indiritzu IP o nùmene impitadore:",
        "ipbexpiry": "Scadèntzia:",
        "ipbreason": "Motivu:",
-       "ipbsubmit": "Blocca custu usuàriu",
+       "ipbsubmit": "Blocca custu impitadore",
        "ipbother": "Àteru perìodu:",
        "ipboptions": "2 oras:2 hours,1 die:1 day,3 dies:3 days,1 chida:1 week,2 chidas:2 weeks,1 mese:1 month,3 meses:3 months,6 meses:6 months,1 annu:1 year,infinidu:infinite",
        "badipaddress": "S'indiritzu IP indicadu non est currègidu.",
        "blockipsuccesssub": "Bloccu esecutivu",
-       "blockipsuccesstext": "[[Special:Contributions/$1|$1]] è stadu bloccadu. <br />\nAbbàida sa [[Special:BlockList|lista de IP bloccados]] pro bìder sas bloccaduras.",
-       "ipb-edit-dropdown": "Acontza su motivu de su bloccu",
+       "blockipsuccesstext": "[[Special:Contributions/$1|$1]] è stadu bloccadu. <br />\nCàstia sa [[Special:BlockList|lista de bloccados]] pro bìder sas bloccaduras.",
+       "ipb-edit-dropdown": "Càmbia su motivu de su bloccu",
        "ipb-unblock-addr": "Sblocca $1",
-       "ipb-blocklist-contribs": "Contributziones de $1",
-       "unblockip": "Sblocca s'usuàriu",
+       "ipb-blocklist-contribs": "Contributziones de {{GENDER:$1|$1}}",
+       "unblockip": "Sblocca s'impitadore",
        "unblockiptext": "Usa il modulo sottostante per restituire il diritto di scrittura ad un indirizzo IP precedentemente bloccato.",
        "ipusubmit": "Boga custu bloccu",
-       "ipblocklist": "Usuàrios e indiritzos bloccados",
+       "ipblocklist": "Impitadores bloccados",
+       "blocklist-expiry": "Iscadit",
+       "blocklist-reason": "Motivu",
        "ipblocklist-submit": "Chirca",
        "infiniteblock": "infinitu",
        "expiringblock": "scadit su $1 a is $2",
-       "blocklink": "blocca",
+       "blocklink": "arrea",
        "unblocklink": "sblocca",
-       "change-blocklink": "tramuda su bloccu",
-       "contribslink": "contributziones",
-       "blocklogpage": "Bloccos de usuàrios",
+       "change-blocklink": "tramuda s'arreu",
+       "contribslink": "contributos",
+       "emaillink": "imbia email",
+       "blocklogpage": "Bloccos de impitadores",
        "blocklogentry": "bloccau [[$1]] pro unu tempu de $2 $3",
        "unblocklogentry": "at sbloccau $1",
-       "block-log-flags-nocreate": "creatzione account bloccada",
+       "block-log-flags-nocreate": "registrazione bloccada",
        "sorbs": "DNSBL",
        "lockdb": "Blocca su database",
        "unlockdb": "Sblocca su database",
        "databasenotlocked": "Su database no est bloccadu.",
        "move-page": "Movimentu de $1",
        "move-page-legend": "Movimentu pàgina",
-       "movepagetext": "Cun custu mòdellu podes renumenare una pàgina, movende totu sa stòria sua a sa pàgina noa.\nSu tìtulu bèciu at a diventare una pàgina de reindiritzamentu a su tìtulu nou.\nPodes agiornare automaticamente is redirects ca ligant a su tìtulu originàriu.\nSi sèberas de no, assicura·ti de controllare pro [[Special:DoubleRedirects| reindiritzaduras dòpias]] o [[Special:BrokenRedirects|sballiadas]].\nSes responsàbile de t'assigurare ca is cullegamentos sighint a puntare  a ue depent puntare.\n\nAnnota ca sa pàgina '''non''' s'at a mòver si nde esistit giai un'àtera a su tìtulu nou, si no est ki siat bùida o cun sceti unu reindiritzamentu a sa bècia e siat chentza acontzos in antis. In casu de movimentu sballiadu, duncas, si podet torrare a su tìtulu bèciu, ma non podes subrascrìer una pàgina chi giai esistit.\n\n'''ATENTZIONE:'''\nUnu cambiamentu dràsticu podet creare problemas, mescamente a is pàginas prus populares;\npro praxere depes èsser seguru de àer cumpresu is cunsighèntzias prima de sighire a in antis.",
+       "movepagetext": "Cun custu mòdellu podes renumenare una pàgina, movende totu sa stòria sua a sa pàgina noa.\nSu tìtulu bèciu at a diventare una pàgina de reindiritzamentu a su tìtulu nou.\nPodes agiornare automaticamente is redirects ca ligant a su tìtulu originàriu.\nSi sèberas de no, assicura·ti de controllare pro [[Special:DoubleRedirects| reindiritzaduras dòpias]] o [[Special:BrokenRedirects|sballiadas]].\nSes responsàbile de t'assigurare ca is cullegamentos sighint a puntare  a ue depent puntare.\n\nAnnota ca sa pàgina <strong>non</strong> s'at a mòver si nde esistit giai un'àtera a su tìtulu nou, si no est ki siat bùida o cun sceti unu reindiritzamentu a sa bècia e siat chentza acontzos in antis. In casu de movimentu sballiadu, duncas, si podet torrare a su tìtulu bèciu, ma non podes subrascrìer una pàgina chi giai esistit.\n\n<strong>ATENTZIONE!</strong>\nUnu cambiamentu dràsticu podet creare problemas, mescamente a is pàginas prus populares;\npro praxere depes èsser seguru de àer cumpresu is cunsighèntzias prima de sighire a in antis.",
        "movepagetalktext": "Sa pàgina cuntierras asotziada, chi esistit, at a èssere movida automaticamenti impare a sa pàgina base, '''a parte in custos casos''':\n* su movimentu de sa pàgina est intre namespaces diversos;\n* in currispondèntzia de su tìtulu nou esistit giai una pàgina de cuntierras (non bùida);\n* sa casella inoe in bàsciu no est istata sceberada.\n\nIn custos casos, si cheres, depes mòvere a manu su cuntènnidu de sa pàgina.",
        "movearticle": "Move sa pàgina",
-       "movenologintext": "Depes èsser unu usuàriu registradu e [[Special:UserLogin|identificadu]] pro pòder mòver una pàgina",
+       "movenologintext": "Depes èsser unu impitadore registradu e [[Special:UserLogin|identificadu]] pro pòder mòver una pàgina",
        "newtitle": "Tìtulu nou:",
        "move-watch": "Pone ogru a custa pàgina",
        "movepagebtn": "Move sa pàgina",
        "pagemovedsub": "Movimentu andadu bene",
        "movepage-moved": "'''\"$1\" est istada mòvida a \"$2\"'''",
+       "movepage-moved-redirect": "Unu reindiritzamentu est istadu creadu.",
        "articleexists": "Una pàgina cun custu nùmene esistit giai, o su nùmene ki as seberadu no est bàlidu.\nPro praxere sèbera un'àteru nùmene.",
        "movetalk": "Move sa pàgina de cuntierra galu",
        "movelogpage": "Moviduras",
        "immobile-source-page": "Non si podet mòver custa pàgina.",
        "move-leave-redirect": "Lassa unu reindiritzamentu a palas",
        "export": "Esporta pàginas",
+       "export-submit": "Esporta",
+       "export-addcat": "Annanghe",
+       "export-addns": "Annanghe",
        "export-download": "Sarba comente file",
        "allmessagesname": "Nùmene",
+       "allmessagesdefault": "Testu predefinidu",
        "allmessages-filter-legend": "Filtru",
        "allmessages-filter-all": "Totu",
        "allmessages-language": "Limba:",
        "allmessages-filter-submit": "Bae",
        "allmessages-filter-translate": "Tradui",
        "thumbnail-more": "Amannia",
+       "thumbnail_error": "Faddina creande sa miniatura: $1",
+       "import-interwiki-sourcewiki": "Wiki de orìgine:",
+       "import-interwiki-sourcepage": "Pàgina de orìgine:",
+       "import-interwiki-submit": "Importa",
        "import-interwiki-namespace": "Nùmene-logu de destinatzione:",
        "import-upload-filename": "Nùmene file:",
        "import-comment": "Cummentu:",
-       "tooltip-pt-userpage": "Sa pàgina usuàriu tua",
+       "importstart": "Importande is pàginas...",
+       "import-revision-count": "$1 {{PLURAL:$1|revisione|revisiones}}",
+       "importlogpage": "Importatziones",
+       "tooltip-pt-userpage": "Sa pàgina impitadore tua",
        "tooltip-pt-mytalk": "Sa pàgina de is cuntierras tuas",
-       "tooltip-pt-preferences": "Is preferèntzias chi podes scioberai",
-       "tooltip-pt-watchlist": "Sa lista de is pàginas chi tue ses ponende ogru",
-       "tooltip-pt-mycontris": "Sa lista de is contributziones meas",
-       "tooltip-pt-login": "Si cunsìgiat sa registratzione; mancari non siat obligatoria",
-       "tooltip-pt-logout": "Bessida (log out)",
-       "tooltip-ca-talk": "Cuntierras a propositu de su cuntestu de sa pàgina",
-       "tooltip-ca-edit": "Podes acontzare custa pàgina.\nPro praxere, prima de sarbare càstia s'antiprima",
-       "tooltip-ca-addsection": "Incumintza una setzione noa",
-       "tooltip-ca-viewsource": "Sa pàgina est amparada.\nPodes castiare sa mitza sua",
+       "tooltip-pt-preferences": "Is preferèntzias chi podes seberare",
+       "tooltip-pt-watchlist": "Lista de is pàginas annotadas dae tue pro is mudàntzias",
+       "tooltip-pt-mycontris": "Sa lista de is contributos mios",
+       "tooltip-pt-login": "Sa registratzione est cussigiada; mancari chi non siat obligatoria",
+       "tooltip-pt-logout": "Essida (log out)",
+       "tooltip-ca-talk": "Cuntierras a propòsitu de su cuntestu de sa pàgina",
+       "tooltip-ca-edit": "Podes cambiare custa pàgina.\nPro praxere, prima de sarbare càstia s'antiprima",
+       "tooltip-ca-addsection": "Incumentza una setzione noa",
+       "tooltip-ca-viewsource": "Sa pàgina est bardada.\nPodes castiare sa mitza sua",
        "tooltip-ca-history": "Versiones coladas de custa pàgina",
-       "tooltip-ca-protect": "Ampara custa pàgina",
-       "tooltip-ca-delete": "Fùlia custa pàgina",
+       "tooltip-ca-protect": "Barda custa pàgina",
+       "tooltip-ca-delete": "Burra custa pàgina",
        "tooltip-ca-move": "Move custa pàgina (càmbia su tìtulu)",
-       "tooltip-ca-watch": "Giunghe custa pàgina a sa ''watchlist'' tua",
-       "tooltip-ca-unwatch": "Tira custa pàgina da sa watchlist tua",
-       "tooltip-search": "Chirca a intru de {{SITENAME}}",
-       "tooltip-search-go": "Anda a una pàgina cun custu nùmene, si esistit",
-       "tooltip-search-fulltext": "Chirca custu testu in sas pàginas",
+       "tooltip-ca-watch": "Annota custa pàgina pro is mudàntzias",
+       "tooltip-ca-unwatch": "Rimove custa pàgina dae sa lista de pàginas annotadas tua",
+       "tooltip-search": "Chirca in intru de {{SITENAME}}",
+       "tooltip-search-go": "Bae a una pàgina cun su nùmene indicadu, si esistit",
+       "tooltip-search-fulltext": "Chirca custu testu in is pàginas",
        "tooltip-p-logo": "Bìsita sa pàgina base",
        "tooltip-n-mainpage": "Bìsita sa pàgina base",
        "tooltip-n-mainpage-description": "Bìsita sa pàgina base",
        "tooltip-n-portal": "Descritzione de su progetu, ite podes fàgher, a innue agatas is cosas",
-       "tooltip-n-currentevents": "Informatziones subra acuntèssias atuales",
-       "tooltip-n-recentchanges": "Sa lista de is ùrtimas mudàntzias de su giassu",
+       "tooltip-n-currentevents": "Informatziones subra acadessimentos atuales",
+       "tooltip-n-recentchanges": "Lista de is ùrtimas mudàntzias in su giassu",
        "tooltip-n-randompage": "Càrriga una pàgina a sorte",
        "tooltip-n-help": "Pàginas de agiudu",
        "tooltip-t-whatlinkshere": "Lista de totu is pàginas chi ligant a custa",
        "tooltip-t-recentchangeslinked": "Lista de is ùrtimas mudàntzias de is pàginas ki ligant a custa",
        "tooltip-feed-rss": "RSS feed pro custa pàgina",
        "tooltip-feed-atom": "Atom feed pro custa pàgina",
-       "tooltip-t-contributions": "Càstia sa lista de is contributziones de custu usuàriu",
-       "tooltip-t-emailuser": "Ispedi una missada eletronica a custu usuàriu",
+       "tooltip-t-contributions": "Càstia sa lista de is contributos de custu impitadore",
+       "tooltip-t-emailuser": "Ispedi una email a custu impitadore",
        "tooltip-t-upload": "Càrriga file multimediale",
        "tooltip-t-specialpages": "Lista de is pàginas ispetziales",
        "tooltip-t-print": "Versione de custa pàgina pro s'imprenta",
-       "tooltip-t-permalink": "Cullegamentu permanente a custa versione de sa pàgina",
+       "tooltip-t-permalink": "Ligòngiu permanente a custa versione de sa pàgina",
        "tooltip-ca-nstab-main": "Càstia su cuntènnidu de sa pàgina",
-       "tooltip-ca-nstab-user": "Càstia sa pàgina usuàriu",
-       "tooltip-ca-nstab-special": "Custa est una pàgina ispetziale, non dda podes acontzare",
+       "tooltip-ca-nstab-user": "Càstia sa pàgina impitadore",
+       "tooltip-ca-nstab-special": "Custa est una pàgina ispetziale, non dda podes cambiare",
        "tooltip-ca-nstab-project": "Càstia sa pàgina de servìtziu",
        "tooltip-ca-nstab-image": "Càstia sa pàgina de su file",
        "tooltip-ca-nstab-template": "Càstia su template",
        "tooltip-ca-nstab-category": "Càstia sa pàgina de sa categoria",
-       "tooltip-minoredit": "Signa comente acontzu minore",
+       "tooltip-minoredit": "Marca custa muda comente càmbiu minore",
        "tooltip-save": "Sarva is mudàntzias tuas",
-       "tooltip-preview": "Antiprima de is mudàntzias, pro pregeri usa custu prima de sarvari!",
-       "tooltip-diff": "Ammustra is mudàntzias ki as fatu a su testu",
+       "tooltip-preview": "Antiprima de is mudas fatas, pro praghere usa custu prima de sarvare!",
+       "tooltip-diff": "Ammustra is mudàntzias chi as fatu a su testu",
        "tooltip-compareselectedversions": "Càstia is diferèntzias de is duas versiones seberadas de custa pàgina",
-       "tooltip-watch": "Aciungi custa pàgina a sa watchlist tua",
+       "tooltip-watch": "Annota custa pàgina pro is mudàntzias",
        "tooltip-recreate": "Torra a creare sa pàgina mancari siat stada fuliada",
        "tooltip-upload": "Cumentza a carrigare",
-       "tooltip-rollback": "\"Rollback\" annudda is mudàntzias de custa pàgina fatas dae s'ùrtimu contribudori",
-       "tooltip-undo": "\"Annudda\" fùrriat custu acontzu e aberit su mòdulu de acontzu comente antiprima.\nPodes agiùnger unu motivu in s'ogetu de s'acontzu.",
-       "siteuser": "$1, {{GENDER:$1|usuàriu|usuària}} de {{SITENAME}}",
-       "anonuser": " $1, usuàriu anònimu de {{SITENAME}}",
+       "tooltip-rollback": "\"Rollback\" annudda is mudàntzias de custa pàgina fatas dae s'ùrtimu contribudore",
+       "tooltip-undo": "\"Annudda\" fùrriat custu càmbiu e aberit su mòdulu de càmbiu comente antiprima.\nPodes annànghere unu motivu in s'ogetu.",
+       "tooltip-preferences-save": "Sarva preferèntzias",
+       "tooltip-summary": "Inserta unu resumu curtzu",
+       "siteuser": "$1, impitadore de {{SITENAME}}",
+       "anonuser": "$1, impitadore anònimu de {{SITENAME}}",
        "others": "àteros",
        "siteusers": "$1, {{PLURAL:$2|usuàriu|usuàrios}} de {{SITENAME}}",
        "anonusers": "$1, {{PLURAL:$2|usuàriu anònimu|usuàrios anònimos}} de {{SITENAME}}",
        "creditspage": "Autores de sa pàgina",
-       "previousdiff": "← Acontzu in antis",
-       "nextdiff": "Acontzu in fatu →",
+       "pageinfo-header-edits": "Istòria de is mudàntzias",
+       "pageinfo-article-id": "ID pàgina",
+       "pageinfo-contentpage-yes": "Eja",
+       "pageinfo-protect-cascading-yes": "Eja",
+       "previousdiff": "← Càmbiu in segus",
+       "nextdiff": "Càmbiu in antis →",
+       "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|pàgina|pàginas}}",
        "file-info-size": "$1 × $2 pixels, mannesa de su file: $3, tipu de MIME: $4",
        "file-nohires": "Non si tenent risolutziones prus artas.",
        "svg-long-desc": "file in formadu SVG, mannesa nominale $1 × $2 pixel, mannesa de su file: $3",
        "seconds-abbrev": "$1s",
        "minutes-abbrev": "$1m",
        "hours-abbrev": "$1h",
-       "bad_image_list": "Su formau est su chi sighit:\n\nBenint consideraus isceti is listas putadas (lìnias chi incumentzant cun *).\nSu primu cullegamentu depit èssere unu acàpiu a unu file malu (o indesiderau).\nIs acàpius chi sighint in sa matessi lìnia sunt cunsideraus comente eccetziones (ossiat, pàginas innui si podet usare su file).",
+       "bad_image_list": "Su formadu est su chi sighit:\n\nBenint consideradas isceti is listas punnadas (lìnias chi incumentzant cun *).\nSu primu ligòngiu in cada una lìnia depet èssere unu ligòngiu a unu documentu malu (o indesideradu).\nIs ligòngios chi sighint in sa matessi lìnia sunt cunsiderados comente etzetziones (est a nàrrere, pàginas in ue si podet usare su documentu).",
        "metadata": "Metadatos",
-       "metadata-help": "Custu file cuntènnit informatziones aciuntivas, probabilmente aciuntas dae sa fotocamera o dae su scannerizadori impreaus pro ddu creare o ddu digitalizare. Si su file est istadu acontzau, unos particolares podent non currispundere a sa realtade.",
+       "metadata-help": "Custu file cuntènnit informatziones annuntiles, probabilmente annúnghedas dae sa fotocamera o dae su scannerizadore impreadu pro ddu creare o ddu digitalizare. Si su file est istadu mudadu, unos cantos particulares podent non currispòndere a sa realidade.",
        "metadata-expand": "Ammustra particulares",
        "metadata-collapse": "Cua particulares",
-       "metadata-fields": "Is campus de is metadatos EXIF listaus in custu messàgiu ant a èssere amostaus in sa pàgina de s'immàgine candu sa tabella de is metadatos est presentada in forma breve. Pro impostatzione predefinia, is àteros campus ant a èssere cuaus.\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": "Is campus de is metadatos de imàgine listados in custu messàgiu ant a èssere ammustrados in sa pàgina de s'immàgine candu sa tabella de is metadatos est presentada in forma breve. Pro impostatzione predefinida, is àteros campos ant a èssere cuaos.\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-artist": "Autore",
        "exif-exposuretime-format": "$1 s ($2)",
        "exif-fnumber-format": "f/$1",
        "exif-xyresolution-i": "$1 dpi",
        "exif-xyresolution-c": "$1 dpc",
        "exif-colorspace-1": "sRGB",
-       "exif-colorspace-65535": "FFFF.H",
+       "exif-colorspace-65535": "Chentza calibradura",
        "exif-componentsconfiguration-1": "Y",
        "exif-componentsconfiguration-2": "Cb",
        "exif-componentsconfiguration-3": "Cr",
        "word-separator": "&#32;",
        "ellipsis": "…",
        "percent": "$1%",
+       "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← pàgina in antis",
        "imgmultipagenext": "pàgina in fatu →",
        "imgmultigo": "Bae!",
        "imgmultigoto": "Bae a sa pàgina $1",
+       "img-lang-go": "Bae",
        "table_pager_first": "Primu pàgina",
        "table_pager_last": "Ùrtima pàgina",
        "table_pager_limit_submit": "Bae",
        "size-kilobytes": "$1 KB",
        "size-megabytes": "$1 MB",
        "size-gigabytes": "$1 GB",
-       "watchlistedit-normal-title": "Acontza sa watchlist",
+       "watchlistedit-normal-title": "Càmbia sa lista de annotadas",
        "watchlistedit-raw-titles": "Tìtulos:",
+       "watchlistedit-clear-titles": "Tìtulos:",
        "watchlisttools-view": "Càstia mudàntzias de importu",
-       "watchlisttools-edit": "Càstia e acontza sa watchlist",
+       "watchlisttools-edit": "Càstia e càmbia sa lista de pàginas annotadas",
        "watchlisttools-raw": "Acontza sa watchlist dae su testu",
        "timezone-utc": "UTC",
        "version": "Versione",
        "version-specialpages": "Pàginas ispetziales",
        "version-other": "Àteru",
        "version-version": "(Versione $1)",
-       "version-license": "Licèntzia",
+       "version-license": "Licèntzia MediaWiki",
+       "version-ext-license": "Licèntzia",
+       "version-ext-colheader-license": "Licèntzia",
+       "version-poweredby-others": "àteros",
        "version-software-version": "Versione",
+       "version-entrypoints-header-url": "URL",
+       "redirect-submit": "Bae",
+       "redirect-user": "ID impitadore",
+       "redirect-page": "ID pàgina",
        "fileduplicatesearch-submit": "Chirca",
        "specialpages": "Pàginas ispetziales",
+       "specialpages-note-top": "Legenda",
+       "specialpages-group-login": "Intra / crea contu",
        "specialpages-group-pages": "Listas de is pàginas",
-       "tags-edit": "acontza",
+       "tag-filter": "Filtra pro [[Special:Tags|etichetta]]:",
+       "tags-active-yes": "Eja",
+       "tags-active-no": "No",
+       "tags-edit": "càmbia",
+       "compare-page1": "Pàgina 1",
+       "compare-page2": "Pàgina 2",
+       "compare-rev1": "Revisione 1",
+       "compare-rev2": "Revisione 2",
        "htmlform-selectorother-other": "Àteru",
+       "htmlform-no": "No",
+       "htmlform-yes": "Eja",
+       "logentry-upload-upload": "$1 {{GENDER:$2|carrigadu}} $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|carrigadu}} una versione noa de $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|carrigadu}} $3",
        "rightsnone": "(nisciunu)",
+       "feedback-close": "Fatu",
        "searchsuggest-search": "Chirca",
-       "expand_templates_preview": "Antiprima"
+       "expand_templates_ok": "OK",
+       "expand_templates_preview": "Antiprima",
+       "pagelang-name": "Pàgina",
+       "pagelang-select-lang": "Sèbera limba"
 }
index 62f3650..fb8237a 100644 (file)
        "talkpagelinktext": "Discussioni",
        "specialpage": "Pàggina spiciali",
        "personaltools": "Strumenta pirsunali",
-       "postcomment": "Nova sizzioni",
        "articlepage": "artìculu",
        "talk": "discussioni",
        "views": "Vìsiti",
        "externaldberror": "S'havi virificatu n'erruri cû server d'autinticazzioni sternu, oppuru nun si disponi di l'auturizzazzioni nicissari p'aggiurnari lu propiu accessu sternu.",
        "login": "Trasi",
        "nav-login-createaccount": "Riggìstrati o trasi",
-       "loginprompt": "Tu hai a abbilitari li ''cookies'' pi tràsiri ntâ {{SITENAME}}.",
        "userlogin": "Riggìstrati o trasi",
        "userloginnocreate": "Trasi",
        "logout": "Nesci",
        "userlogin-resetlink": "T'ascurdasti li dittagli pâ trasuta?",
        "userlogin-resetpassword-link": "Reinizzializza la tò password",
        "userlogin-helplink2": "Aiutu pâ trasuta",
-       "userlogin-loggedin": "Vossia già trasìu comu {{GENDER:$1|$1}}.\nUsassi lu mòdulu ccassutta pi tràsiri comu autru utenti.",
-       "userlogin-createanother": "Crèa n'autru cuntu",
        "createacct-emailrequired": "Nnirizzu e-mail",
        "createacct-emailoptional": "Nnirizzu e-mail (facurtativu)",
        "createacct-email-ph": "Nzirisci lu tò nnirizzu e-mail",
        "edit-conflict": "Cunflittu di edizzioni.",
        "edit-no-change": "La mudifica fu ignurata pirchì nu foru appurtati canci ntô testu.",
        "postedit-confirmation-saved": "Lu canciamentu fu sarbatu.",
-       "edit-already-exists": "Mpussìbbili criari na nova pàggina.\nEsisti ggià.",
+       "edit-already-exists": "Mpussìbbili criari na pàggina nova.\nEsisti ggià.",
        "expensive-parserfunction-warning": "Accura: Sta pàggina cunteni troppi chiamati ê parser functions.\n\nAvissi a èssiri menu di $2, ô mumentu ci {{PLURAL:$1|nn'è $1|nni sunnu $1}}.",
        "expensive-parserfunction-category": "Pàggini cu troppi chiamati ê parser functions",
        "post-expand-template-inclusion-warning": "Accura: la diminzioni di li template nziriti è troppu granni.\nArcuni template non vènunu nziriti.",
        "searchprofile-advanced-tooltip": "Cerca ntê namespace pirsunalizzati",
        "search-result-size": "$1 ({{PLURAL:$2|na parola|$2 paroli}})",
        "search-result-category-size": "{{PLURAL:$1|1 utenti|$1 utenti}} ({{PLURAL:$2|1 suttacatigurìa|$2 suttacatigurìi}}, {{PLURAL:$3|1 file|$3 files}})",
-       "search-result-score": "Rilivanza: $1%",
        "search-redirect": "(redirect $1)",
        "search-section": "(sizzioni $1)",
        "search-suggest": "Forsi circavutu: $1",
        "recentchanges-label-bot": "Stu canciamentu fu fattu dû bot",
        "recentchanges-label-unpatrolled": "Stu canciamentu nun havi ancora statu virificatu",
        "recentchanges-label-plusminus": "La diminsioni dâ pàggina canciau di stu nùmmuru di bytes",
-       "recentchanges-legend-newpage": "$1 - pàggina nova",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (talìa [[Special:NewPages|li pàggini novi]])",
        "rcnotefrom": "Ccà sutta cci sunnu li canciamenti a pàrtiri dû <b>$2</b> (ammustrati nzinu ô <b>$1</b>).",
        "rclistfrom": "Ammustra li canciamenti novi a pàrtiri di $3 $2",
        "rcshowhideminor": "$1 li canciamenti nichi",
        "uploadwarning": "Avvisu di Upload",
        "uploadwarning-text": "Cancia cà sutta la discrizzioni di lu file e prova arré",
        "savefile": "Sarva file",
-       "uploadedimage": "hà carricatu \"[[$1]]\"",
-       "overwroteimage": "carricata na nova virsioni di \"[[$1]]\"",
        "uploaddisabled": "Semu spiacenti, ma lu carricamentu di file è timpuraniamenti suspisu.",
        "uploaddisabledtext": "Lu carricamentu dî file nun è attivu supra a stu situ.",
        "php-uploaddisabledtext": "Li file PHP non sunnu abbilitati. Pi favuri cuntrolla li mpustazzioni dû file_uploads.",
        "watchlist-details": "La lista dê pàggini taliati cunteni {{PLURAL:$1|na pàggina (cu la rispittiva pàggina di discussioni)|$1 pàggini (cu li rispittivi pàggini di discussioni)}}.",
        "wlheader-enotif": "La nutìfica via e-mail è attivata.",
        "wlheader-showupdated": "Li pàggini ca hannu statu canciati dâ tò ùrtima vìsita sunnu evidinziati 'n '''grassettu'''",
+       "wlnote": "Sutta attrovi l'ùrtim{{PLURAL:$1|u canciamentu|i $1 canciamenti}}, nta l'ùrtim{{PLURAL:$1|a ura|i '''$2''' uri}}.",
        "wlshowlast": "Ammustra l'ùrtimi $1 uri $2 jorna $3",
        "watchlist-options": "Opzioni ussirvati spiciali",
        "watching": "Junta a l'ussirvati spiciali...",
        "import": "Mporta pàggini",
        "importinterwiki": "Mpurtazzioni transwiki",
        "import-interwiki-text": "Silizziunari un pruggettu wiki e lu tìtulu dâ pàggina a mpurtari. Li dati di pubbricazzioni e li noma di l'autura dî vari virsioni sunnu sarvati. Tutti l'opirazzioni di mpurtazzioni trans-wiki sunnu riggistrati ntô [[Special:Log/import|log di mpurtazzioni]].",
-       "import-interwiki-source": "Surgenti wiki/pàggina:",
        "import-interwiki-history": "Copia la ntera cronoluggìa di sta pàggina",
        "import-interwiki-templates": "Includi tutti li template",
        "import-interwiki-submit": "Mporta",
index 5c60e43..caf7d13 100644 (file)
        "print": "Prent",
        "view": "See",
        "edit": "Eedit",
+       "edit-local": "Eedit local description",
        "create": "Ceaut",
        "editthispage": "Eedit this page",
        "create-this-page": "Creaut this page",
        "talkpagelinktext": "Tauk",
        "specialpage": "Byordinar Page",
        "personaltools": "Personal tuils",
-       "postcomment": "New section",
        "articlepage": "Leuk at content page",
        "talk": "Tauk",
        "views": "Views",
        "jumptonavigation": "navigation",
        "jumptosearch": "rake",
        "view-pool-error": "Sarrie, the servers ar owerlaided at the moment.\nOwer monie uisers ar ettlin tae see this page.\nPlease wait ae while afore ye ettle tae access this page again.\n\n$1",
+       "generic-pool-error": "Sorry, the servers are owerloadit at the moment.\nToo mony uisers are tryin tae view this resoorce.\nPlease wait a while afore you try tae access this resoorce again.",
        "pool-timeout": "Timeout waitin fer the lock",
        "pool-queuefull": "Pool line is ful",
        "pool-errorunknown": "Onknawn mistak.",
        "externaldberror": "Aither thaur wis aen external authentication database mistak, or ye'r naw permitit tae update yer external accoont.",
        "login": "Log in",
        "nav-login-createaccount": "Log in / cræft aen accoont",
-       "loginprompt": "Ye maun hae cookies enabled tae log in tae {{SITENAME}}.",
        "userlogin": "Cræft aen accoont or log in",
        "userloginnocreate": "Log in.",
        "logout": "Log oot",
        "currentrev": "Reveesion the nou",
        "currentrev-asof": "Latest reveesion aes o $1",
        "revisionasof": "Reveesion aes o $1",
-       "revision-info": "Reveesion aes o $1 bi $2",
+       "revision-info": "Reveesion aes o $1 bi {{GENDER:$6|$2}}$7",
        "previousrevision": "← Aulder reveesion",
        "nextrevision": "Newer reveesion →",
        "currentrevisionlink": "Latest reveesion",
        "revdelete-text-text": "Delytit reveesions will still kith in the page histerie, bit pairts o thair content will be onaccessible til the publeec.",
        "revdelete-text-file": "Delytit file versions will still kith in the file histerie, bit pairts o thair content will be onaccessible til the publeec.",
        "logdelete-text": "Delytit log events will still kith in the logs, bit pairts o thair content will be onaccessible til the publeec.",
-       "revdelete-text-others": "Ither admeenistraters oan {{SITENAME}} will still be able tae access the skaukt content n can ondelyte it again throoch this same interface, onless addeetional restreections ar set.",
+       "revdelete-text-others": "Ither admeenistraters will still be able tae access the skaukt content n tae ondelyte it, onless addeetional restreections ar set.",
        "revdelete-confirm": "Please confirm that ye'r ettlin tae dae this, that ye unnerstaunn the consequences, n that ye'r daein this in accordance wi [[{{MediaWiki:Policy-url}}|the policie]].",
        "revdelete-suppress-text": "Suppression shid <strong>yinly</strong> be uised fer the follaein cases:\n* poteentiallie libeloos information\n* galus personal information\n*: <em>hame addresses n telephane nummers, national ideentifeecation nummers, etc.</em>",
        "revdelete-legend": "Set visibeelitie restreections",
        "searchprofile-advanced-tooltip": "Rake in custom namespaces",
        "search-result-size": "$1 ({{PLURAL:$2|1 waird|$2 wairds}})",
        "search-result-category-size": "{{PLURAL:$1|1 memmer|$1 memmers}} ({{PLURAL:$2|1 subcategerie|$2 subcategeries}}, {{PLURAL:$3|1 file|$3 files}})",
-       "search-result-score": "Relevanc: $1%",
        "search-redirect": "(reguide $1)",
        "search-section": "(section $1)",
        "search-file-match": "(matches file content.)",
        "powersearch-togglelabel": "Chec':",
        "powersearch-toggleall": "Aw",
        "powersearch-togglenone": "Nane",
+       "powersearch-remember": "Remember selection for futur rakes",
        "search-external": "Eixternal rake",
        "searchdisabled": "Rakin throu {{SITENAME}} is disabled fer performance raisons. Ye can rake bi wa o Google juist nou. Mynd that thair indexes o {{SITENAME}} content micht be oot o date.",
        "search-error": "Ae mistak haes occurred while rakin: $1",
        "right-deletedtext": "See delytit tex n chynges atween delytit reveesions",
        "right-browsearchive": "Rake delytit pages",
        "right-undelete": "Ondelyte ae page",
-       "right-suppressrevision": "Luikower n restore reveesions skaukt fae admeenistraters",
+       "right-suppressrevision": "See, skauk n onskauk speceefic reveesions o pages fae onie uiser",
        "right-suppressionlog": "see preevate logs",
        "right-block": "Block ither uisers fae eeditin",
        "right-blockemail": "Block ae uiser fae sendin wab-mail",
        "recentchanges-label-unpatrolled": "This eedit haes no bin patrolled yet",
        "recentchanges-label-plusminus": "The page size chynged bi this nummer o bytes",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (see [[Special:NewPages|leet o new pages]] n aw)",
-       "rcnotefrom": "Ablo ar the chynges sin <strong>$2</strong> (up til <strong>$1</strong> shawn).",
+       "rcnotefrom": "Ablo {{PLURAL:$5|is the chynge|ar the chynges}} sin <strong>$3, $4</strong> (up tae <strong>$1</strong> shawn).",
        "rclistfrom": "Shaw new chynges stertin fae $3 $2",
        "rcshowhideminor": "$1 smaa eedits",
        "rcshowhideminor-show": "Shaw",
        "largefileserver": "This file is bigger than the server is confeeegurt tae allou.",
        "emptyfile": "The file that ye uplaided seems tae be tuim.\nThis micht be cause o ae typeower in the filename.\nPlease check whether ye reallie want tae uplaid this file.",
        "windows-nonascii-filename": "This wiki disna support filenames wi speecial chairacters.",
-       "fileexists": "Ae file wi this name exeests aareadies, please check <strong>[[:$1]]</strong> gif ye'r no sair that ye want tae chynge it.\n[[$1|thumb]]",
+       "fileexists": "Ae file wi this name awreadie exeests, please check <strong>[[:$1]]</strong> gif {{GENDER:|ye}}'r no siccar gif ye want tae chynge it.\n[[$1|thumb]]",
        "filepageexists": "The descreeption page fer this file haes awreadie been cræftit at <strong>[[:$1]]</strong>, bit nae file wi this name exeests the nou.\nThe ootline that ye enter will na kith oan the descreeption page.\nTae mak yer ootline kith thaur, ye'll need tae manuallie eedit it.\n[[$1|thumb]]",
        "fileexists-extension": "Ae file wi ae siclike name exeests: [[$2|thumb]]\n* Name o the uplaidin file: <strong>[[:$1]]</strong>\n* Name o the exeestin file: <strong>[[:$2]]</strong>\nWid ye lik tae chuise ae mair disteencteeve name?",
        "fileexists-thumbnail-yes": "The file seems tae be aen eemage o reduced size ''(thumbnail)''.\n[[$1|thumb]]\nPlease check the file <strong>[[:$1]]</strong>.\nGif the checked file is the same eemage o oreeginal size it's no necessairie tae uplaid aen extra thumbnail.",
        "uploadwarning": "Uplaid warnishment",
        "uploadwarning-text": "Please modeefie the file descreeption ablo n gie it anither gae.",
        "savefile": "Hain file",
-       "uploadedimage": "uplaidit \"[[$1]]\"",
-       "overwroteimage": "uplaided ae new version o \"[[$1]]\"",
        "uploaddisabled": "Sarrie, uplaidin is disablit.",
        "copyuploaddisabled": "Uplaid bi URL disabled.",
        "uploaddisabledtext": "File uplaids ar disabled.",
        "license": "Licensin:",
        "license-header": "Licensin",
        "nolicense": "Nane selectit",
+       "licenses-edit": "Eedit license options",
        "license-nopreview": "(Luikower naw available)",
        "upload_source_url": "(ae valid, publeeclie accessible URL)",
        "upload_source_file": "(ae file oan yer computer)",
        "wantedtemplates": "Wantit templates",
        "mostlinked": "Maist airtit-tae pages",
        "mostlinkedcategories": "Maist airtit-tae categeries",
-       "mostlinkedtemplates": "Maist linkt-til templates",
+       "mostlinkedtemplates": "Maist transcludit pages",
        "mostcategories": "Airticles wi the maist categeries",
        "mostimages": "Maist uised eemages",
        "mostinterwikis": "Pages wi the maist interwikis",
        "watchlist-details": "{{PLURAL:$1|$1 page|$1 pages}} oan yer watchleet, no coontin tauk pages seperatlie.",
        "wlheader-enotif": "Wab-mail annooncemant is enabled.",
        "wlheader-showupdated": "Pages that hae been chynged sin ye last veesitit thaim ar shawn in '''baud'''.",
-       "wlnote2": "Ablo ar the chynges in the hainmaist {{PLURAL:$1|hoor|<strong>$1</strong> hours}}, aes o $3, $2.",
+       "wlnote": "Ablo {{PLURAL:$1|is the laist chynge|ae the laist '''$1''' chynges}} in the laist {{PLURAL:$2|hoor|'''$2''' hoors}}, aes o $3, $4.",
        "wlshowlast": "Shaw hainmaist $1 hoors $2 days $3",
        "watchlist-options": "Watchleet opties",
        "watching": "Watchin...",
        "import-upload": "Uplaid XML data",
        "import-token-mismatch": "Loss o session data.\nPlease gie it anither gae.",
        "import-invalid-interwiki": "Canna import fae the speceefied wiki.",
-       "import-error-edit": "Page \"$1\" isna importit cause ye'r na permitit tae eedit it.",
-       "import-error-create": "Page \"$1\" is na importit cause ye'r na permitit tae cræft it.",
-       "import-error-interwiki": "Page \"$1\" is na importit cause its name is reserved fer external linkin (interwiki).",
-       "import-error-special": "Page \"$1\" is na importit cause it belangs til ae speecial namespace that disna permit pages.",
-       "import-error-invalid": "Page \"$1\" is na importit cause its name is onvalit.",
+       "import-error-edit": "Page \"$1\" wisna importit cause ye'r na alloued tae eedit it.",
+       "import-error-create": "Page \"$1\" wisna importit cause ye'r no alloued tae creaut it.",
+       "import-error-interwiki": "Page \"$1\" wisna importit cause its name is reserved fer ootby airtinin (interwiki).",
+       "import-error-special": "Page \"$1\" wisna importit cause it belangs til ae byordinair namespace that disna allou pages.",
+       "import-error-invalid": "Page \"$1\" wisna importit cause the name that it wid be importit tae isna valit oan this wiki.",
        "import-error-unserialize": "Reveesion $2 o page \"$1\" coudna be onsereealized. The reveesion wis reported til uiss content model $3 sereealized aes $4.",
        "import-error-bad-location": "Reveesion $2 uisin content model $3 canna be stored oan \"$1\" oan this wiki, syn that model isna supported oan that page.",
        "import-options-wrong": "Wrang {{PLURAL:$2|optie|opties}}: <nowiki>$1</nowiki>",
        "import-rootpage-nosubpage": "Namespace \"$1\" o the ruit page disna permit subpages.",
        "importlogpagetext": "Admeenistrateeve imports o pages wi eedit histerie fae ither wikis.",
        "import-logentry-upload": "imported [[$1]] bi file uplaid",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|reveesion|reveesions}}",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|reveesion|reveesions}} fae $2",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|reveesion|reveesions}} importit",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|reveesion|reveesions}} importit fae $2",
        "javascripttest": "JavaScript testin",
        "javascripttest-title": "Rinnin $1 tests",
        "javascripttest-pagetext-noframework": "This page is reserved fer rinnin JavaScript tests.",
index 9884302..c6d69e9 100644 (file)
@@ -1,7 +1,8 @@
 {
        "@metadata": {
                "authors": [
-                       "Aursani"
+                       "Aursani",
+                       "아라"
                ]
        },
        "tog-showtoolbar": "سنوارپ اوزار دٻي ڏيکاريو (جاوا اسڪرپٽ)",
        "qbmyoptions": "منهنجا صفحا",
        "faq": "ڪپوس",
        "faqpage": "Project:ڪپوس",
-       "vector-action-delete": "ڊاھيو",
-       "vector-action-move": "چوريو",
-       "vector-action-protect": "تحفظيو",
-       "vector-action-unprotect": "اڻتحفظيو",
-       "vector-view-create": "سرجيو",
-       "vector-view-edit": "سنواريو",
-       "vector-view-viewsource": "ڪوڊ ڏسو",
        "errorpagetitle": "چُڪَ",
        "returnto": "$1 ڏانهن وَرو.",
        "tagline": "{{SITENAME}} طرفان",
        "talkpagelinktext": "بحث",
        "specialpage": "خاص صفحو",
        "personaltools": "ذاتي اوزار",
-       "postcomment": "تاثرات درج ڪريو",
        "articlepage": "مسودو ڏسو",
        "talk": "بحث",
        "views": "ڏيٺون",
        "remembermypassword": "هن ڳڻپيوڪر تي مون کي ياد رکو (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "login": "لاگ اِن",
        "nav-login-createaccount": "لاگ اِن ٿيو / کاتو کوليو",
-       "loginprompt": "{{SITENAME}} ۾ لاگ اِن ٿيڻ لاءِ ڪوڪيز جي قبوليت لازمي آهي.",
        "userlogin": "لاگ اِن ٿيو / کاتو کوليو",
        "logout": "لاگ آئوٽ",
        "userlogout": "لاگ آئوٽ",
        "prevn": "پويان {{PLURAL:$1|$1}}",
        "nextn": "اڳيان {{PLURAL:$1|$1}}",
        "viewprevnext": "ڏسو ($1 {{int:pipe-separator}} $2) ($3)",
-       "powersearch-redir": "چورڻن جي فهرست ڏيکاريو",
        "preferences": "ترجيحات",
        "mypreferences": "منهنجون ترجيحات",
        "skin-preview": "پيش نگاهه",
        "recentchanges": "تازيون تبديليون",
        "recentchanges-feed-description": "ۡهن روان رسد ۾ آيل تازيون تبديليون لهو",
        "rcnotefrom": "هيٺ '''$2''' کان ٿيندڙ تبديليون پيش ڪجن ٿيون ('''$1''' تائين ڏيکارجن ٿيون).",
-       "rclistfrom": "$1 کان شروع ٿيندڙ نيون تبديليون",
+       "rclistfrom": "$3 $2 کان شروع ٿيندڙ نيون تبديليون",
        "rcshowhideminor": "$1 معمولي ترميمون",
        "rcshowhidebots": "$1 بوٽس",
        "rcshowhideliu": "$1 لاگ اِن ٿيل يوزرس",
        "upload": "فائيل چاڙهيو",
        "uploadbtn": "فائيل چاڙهيو",
        "uploadlogpage": "چاڙهه لاگ",
-       "uploadedimage": "\"[[$1]]\" چاڙهيو ويو",
        "listfiles": "فائيل فهرست",
        "file-anchor-link": "فائيل",
        "filehist": "فائيل جي سوانح",
        "log": "لاگس",
        "all-logs-page": "سڀئي لاگس",
        "allpages": "سڀ صفحا",
-       "alphaindexline": "$1 کان $2",
        "nextpage": "اڳيون صفحو ($1)",
        "prevpage": "پويون صفحو ($1)",
        "allpagesfrom": "ھتان شروع ٿيندڙ صفحا نمايو",
index a934d02..57e7818 100644 (file)
        "talkpagelinktext": "Dischussioni",
        "specialpage": "Pagina ippiziari",
        "personaltools": "Isthrumenti passunari",
-       "postcomment": "Noba sezzioni",
        "articlepage": "Vedi la bozi",
        "talk": "Dischussioni",
        "views": "Vìsiti",
        "externaldberror": "S'è verifiggaddu un errori cu lu server di autentificazioni esthernu, oppuru nò si diponi di l'autorizazioni nezzessàri pa aggiornà la propria registhrazioni estherna.",
        "login": "Intra",
        "nav-login-createaccount": "Intra / registhrazioni",
-       "loginprompt": "Pa intrà a {{SITENAME}} è nezzessàriu abirità li cookie.",
        "userlogin": "Intra o cria una noba registhrazioni",
        "userloginnocreate": "Intra",
        "logout": "Esci",
        "fileexists-shared-forbidden": "Un file cun chisthu innòmmu isisthi già i l'archìbiu di li risuzzi mùrthimediari cundibisi. Turrà indareddu e mudìfiggà l'innòmmu cu' lu quari carriggà lu file. [[File:$1|thumb|center|$1]]",
        "uploadwarning": "Avvisu di carriggamentu",
        "savefile": "Saivva file",
-       "uploadedimage": "ha carriggaddu \"[[$1]]\"",
-       "overwroteimage": "ha carriggaddu una nóba versioni di \"[[$1]]\"",
        "uploaddisabled": "Semmu dipiazuddi, ma lu carriggamentu di file è timpuraniamenti suippesu.",
        "uploaddisabledtext": "Lu carriggamentu di file nò è attibu i' {{SITENAME}}.",
        "uploadscripted": "Chistu file cunteni còdizi HTML o script, chi pudia assé interpretaddu mari da lu nabiggadori.",
        "watchlist-details": "La listha di l'abbaidaddi ippiziari cunteni {{PLURAL:$1|una pagina (e la rippettiba pagina di dischussioni)|$1 pagini (e li rippettibi pagini di dischussioni)}}.",
        "wlheader-enotif": "La nutìfica via postha erettrònica è attiba.",
        "wlheader-showupdated": "Li pàgini chi so isthaddi mudìfiggaddi daboi l'ulthima vìsita so evidenziaddi in '''grasseddu'''",
+       "wlnote": "Inogghi {{PLURAL:$1|è erencadda la mudìfigga più rizzenti arriggadda|so erencaddi li '''$1''' mudìfigghi più rizzenti arriggaddi}} {{PLURAL:$2|i' la ulthima ora|i' li ulthimi '''$2''' ori}}.",
        "wlshowlast": "Musthra li ulthimi $1 ori $2 dì $3",
        "watchlist-options": "Opzioni abbaidaddi ippiziari",
        "watching": "Aggiunta a l'abbaidaddi ippiziari...",
index d079543..85bf781 100644 (file)
        "talkpagelinktext": "Ságastallan",
        "specialpage": "Sierrasiidu",
        "personaltools": "Persovnnalaš bargoneavvu",
-       "postcomment": "Ođđa sekšuvdna",
        "articlepage": "Geahča sisdoalu",
        "talk": "Ságastallan",
        "views": "Čájáhusat",
        "yourdomainname": "Fierbmenamma",
        "login": "Čálligoađe sisa",
        "nav-login-createaccount": "Daga ođđa geavaheaddjidovddaldaga dahje čálligoađe sisa",
-       "loginprompt": "Sisačállimii dárbbašuvvojit geavssat (cookies).",
        "userlogin": "Logge sisa dahje ráhkat dovddaldaga",
        "logout": "Čálligoađe olggos",
        "userlogout": "Logge olggos",
        "largefileserver": "Dát fiila lea menddo stuoris.",
        "uploadwarning": "Lasihanvaruhus",
        "savefile": "Vurke",
-       "uploadedimage": "vurkii fiilla [[$1]]",
-       "overwroteimage": "vurkii ođđa veršuvnna fiillas «[[$1]]»",
        "uploaddisabled": "{{GRAMMAR:genitive|{{SITENAME}}}} ii sáhte lasihit fiillaid.",
        "uploaddisabledtext": "Fiillaid vurken lea váldojuvvon eret anus.",
        "uploadscripted": "Dát fiila sisdisdoalla HTML-koda dahje skriptaid, maid neahttabláđejeaddji sáhttá vahagis dahkat.",
        "watchlist-details": "Du čuovvunlisttus {{PLURAL:$1|lea $1 siidu|leat $1 siiddu}}. Lohkui eai leat váldojuvvon ságastallansiidduid.",
        "wlheader-enotif": "E-poastaalmmuhusat leat anus.",
        "wlheader-showupdated": "Siiddut, mat leat rievdaduvvon du maŋimus geavahangearddi maŋŋá leat merkojuvvon '''buoiddes teavsttain'''",
+       "wlnote": "Vuolábealde lea '''$1''' {{PLURAL:$1|rievdadus|rievdadusa}} maŋimus {{PLURAL:$2||'''$2'''}} diimma siste.",
        "wlshowlast": "Čájet maŋimus $1 diimmu dahje $2 beaivvi $3",
        "watching": "Lasihuvvo čuovvunlistui...",
        "unwatching": "Sihkojuvvo čuovvunlisttus...",
index 0ff91b7..813f64b 100644 (file)
        "talkpagelinktext": "Czaxö",
        "specialpage": "Páhina extrava",
        "personaltools": "Cui personalui",
-       "postcomment": "Iitom pte queeet",
        "articlepage": "Cohuatlöx contentua páhina",
        "talk": "Czaxö",
        "views": "Cohuatlöxám",
        "externaldberror": "Pos-römjde authenticacionde database extername jöx me necoccebj permiccionde updatan mecaitom externom.",
        "login": "Caápo",
        "nav-login-createaccount": "Caápo / xuatl",
-       "loginprompt": "Henáabliicookám caápo {{SITENAME}}.",
        "userlogin": "Caápo / xuatl",
        "logout": "Cuípo",
        "userlogout": "Cuípo",
        "filetype-missing": "Ciúchan zo necoccebj extencion (pac' \".jpg\").",
        "uploadwarning": "Attencionde uploadan",
        "savefile": "Xuniim ciúchan",
-       "uploadedimage": "uploadöx \"[[$1]]\"",
-       "overwroteimage": "uploadöx hunvercion zode \"[[$1]]\"",
        "uploadvirus": "Jan ciúchan coccebj virusde PC zo! Detailám: $1",
        "sourcefilename": "Sourcenam IDde ciúchan:",
        "destfilename": "Destinacion IDde ciúchan:",
index 6ad3c21..ba7af45 100644 (file)
        "talkpagelinktext": "Aptarėms",
        "specialpage": "Specēlosis poslapis",
        "personaltools": "Persuonalėnē rakondā",
-       "postcomment": "Rašītė kuomentara",
        "articlepage": "Veizietė straipsnė",
        "talk": "Aptarėms",
        "views": "Parveizėtė",
        "yourdomainname": "Tamstas domens:",
        "login": "Prisėjongtė",
        "nav-login-createaccount": "Prėsėjongtė / sokortė paskīra",
-       "loginprompt": "Ijonkėt pakavukus, jēgo nuorėt prisėjongtė pri {{SITENAME}}.",
        "userlogin": "Prėsėjongtė / sokortė paskīra",
        "userloginnocreate": "Prisėjongtė",
        "logout": "Atsėjongtė",
        "searchprofile-advanced-tooltip": "Ėiškoutė skėrtingūsė vardū sėtīsė",
        "search-result-size": "$1 ({{PLURAL:$2|1 žuodis|$2 žuodē|$2 žuodiu}})",
        "search-result-category-size": "{{PLURAL:$1|1 narīs|$1 nariū}} ({{PLURAL:$2|1 subkateguorėjuo|$2 subkateguorėju}}, {{PLURAL:$3|1 fails|$3 failu}})",
-       "search-result-score": "Tėnkamoms: $1%",
        "search-redirect": "(paradresavėms $1)",
        "search-section": "(skīrios $1)",
        "search-suggest": "Mažo nuoriejot $1",
        "file-exists-duplicate": "Tas fails īr {{PLURAL:$1|šėta faila|šėtū failu}} doblėkats:",
        "uploadwarning": "Diemesė",
        "savefile": "Ėšsauguotė faila",
-       "uploadedimage": "ikielė „[[$1]]“",
-       "overwroteimage": "ikruovė nauja „[[$1]]“ versėjė",
        "uploaddisabledtext": "Failu ikielėmā oždraustė īr.",
        "uploadscripted": "Šėts failos tor HTML a programėni kuoda, katros gal būtė klaidėngā soprasts interneta naršīklės.",
        "uploadvirus": "Šėtom faile īr virosas! Ėšsamiau: $1",
        "watchlist-details": "Keravuojama $1 {{PLURAL:$1|poslapis|$1 poslapē|$1 poslapiu}} neskaitlioujant aptarėmu poslapiu.",
        "wlheader-enotif": "El. pašta primėnėmā ijongtė īr.",
        "wlheader-showupdated": "Poslapē, katrėi pakeistė nu Tamstas paskotėnė apsėlonkėma čiesa anūs, īr pažīmietė '''pastuorintā'''",
+       "wlnote": "Ruoduoma '''$1''' paskotėniu pakeitėmu, atlėktū par '''$2''' paskotėniu adīnu.",
        "wlshowlast": "Ruodītė paskotėniu $1 adīnu, $2 dėinū a $3 pakeitėmus",
        "watchlist-options": "Keravuojamu sāroša pasėrinkėmā",
        "watching": "Itraukiama i keravuojamu sāraša...",
index b422598..5f637fd 100644 (file)
@@ -6,7 +6,8 @@
                        "Nemo bis",
                        "OC Ripper",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Milicevic01"
                ]
        },
        "tog-underline": "Podvuci linkove:",
        "talkpagelinktext": "Razgovor",
        "specialpage": "Posebna stranica",
        "personaltools": "Lični alati",
-       "postcomment": "Pošaljite komentar - Пошаљите коментар",
        "articlepage": "Pogledaj stranicu sa sadržajem (članak)",
        "talk": "Razgovor / Разговор",
        "views": "Pregledi",
        "externaldberror": "Došlo je do greške pri vanjskoj autorizaciji baze podataka ili vam nije dopušteno osvježavanje Vašeg vanjskog korisničkog računa.",
        "login": "Prijavi me - Пријави ме",
        "nav-login-createaccount": "Prijavi se / Registruj se",
-       "loginprompt": "Morate imati kolačiće ('''cookies''') omogućene da biste se prijavili na {{SITENAME}}.",
        "userlogin": "Prijavi se / Пријави се",
        "userloginnocreate": "Prijavi se",
        "logout": "Odjavi se / Одјави се",
        "undo-failure": "Izmjene se ne mogu vratiti zbog konflikta sa izmjenama u međuvremenu.",
        "undo-norev": "Izmjena se ne može vratiti jer ne postoji ranija ili je obrisana.",
        "undo-nochange": "Ovo je uređivanje izgleda već bilo poništeno.",
-       "undo-summary": "Poništena izmjena $1 [[Special:Contributions/$2|korisnika $2]] ([[User talk:$2|razgovor]])",
+       "undo-summary": "Poništena izmjena $1 [[Special:Contribs/$2|korisnika $2]] ([[User talk:$2|razgovor]])",
        "undo-summary-username-hidden": "Poništi izmjenu $1 od skrivenog korisnika",
        "cantcreateaccounttitle": "Nije moguće napraviti korisnički račun",
        "cantcreateaccount-text": "Pravljenje korisničkog računa sa ove IP adrese ('''$1''') je blokirano od strane [[User:$3|$3]].\n\nRazlog koji je naveo $3 je ''$2''",
        "searchprofile-advanced-tooltip": "Traži u ostalim imenskim prostorima",
        "search-result-size": "$1 ({{PLURAL:$2|1 riječ|$2 riječi}})",
        "search-result-category-size": "{{PLURAL:$1|1 član|$1 člana|$1 članova}} ({{PLURAL:$2|1 podkategorija|$2 podkategorije|$2 podkategorija}}, {{PLURAL:$3|1 datoteka|$3 datoteke|$3 datoteka}})",
-       "search-result-score": "Relevantnost: $1%",
        "search-redirect": "(preusmjeravanje $1)",
        "search-section": "(sekcija $1)",
        "search-file-match": "(odgovara sadržaju datoteke)",
        "uploadwarning": "Upozorenje pri slanju",
        "uploadwarning-text": "Molimo izmijeniti opis datoteke ispod i pokušajte kasnije.",
        "savefile": "Snimi datoteku",
-       "uploadedimage": "postavljeno \"[[$1]]\"",
-       "overwroteimage": "postavljena nova verzija datoteke \"[[$1]]\"",
        "uploaddisabled": "Slanje fajlova je isključeno",
        "copyuploaddisabled": "Postavljanje putem URL nije omogućeno.",
        "uploaddisabledtext": "Postavljanje datoteka je onemogućeno.",
        "watchlist-details": "{{PLURAL:$1|$1 stranica praćena|$1 stranice praćene|$1 stranica praćeno}} ne računajući stranice za razgovor.",
        "wlheader-enotif": "* Obavještavanje e-poštom je omogućeno.",
        "wlheader-showupdated": "* Stranice koje su izmijenjene od kad ste ih posljednji put posjetili su prikazane '''podebljanim slovima'''",
+       "wlnote": "Ispod {{PLURAL:$1|je posljednja izmjena|su posljednje '''$1''' izmjene|je posljednjih '''$1''' izmjena}} u {{PLURAL:$2|prethodnom satu|prethodna '''$2''' sata|prethodnih '''$2''' sati}}, zaključno sa $3, $4.",
        "wlshowlast": "Prikaži posljednjih $1 sati $2 dana $3",
        "watchlist-options": "Opcije liste praćenja",
        "watching": "Pratim... / Додавање на списак надгледања...",
index d2a285b..6b4ac69 100644 (file)
        "talkpagelinktext": "Sgdl (mdiwil)",
        "specialpage": "Tasna izlin",
        "personaltools": "Imasn inu",
-       "postcomment": "Ayyaw amaynu",
        "articlepage": "Mel mayllan ɣ tasna",
        "talk": "Amsgdal",
        "views": "Ẓr.. (Mel)",
        "externaldberror": "Imma tlla ɣin kra lafut ɣu ukcumnk ulla urak ittuyskar at tsbddelt lkontnk nbrra.",
        "login": "Kcm ɣid",
        "nav-login-createaccount": "kcm / murzm Amidan",
-       "loginprompt": "You must have cookies enabled to log in to {{SITENAME}}.",
        "userlogin": "kchem / qiyd amskhdam amaynu",
        "userloginnocreate": "Kcm ɣid",
        "logout": "Fuɣ",
        "searchprofile-advanced-tooltip": "Cabba ɣ igmmaḍn li tuyzlaynin",
        "search-result-size": "$1 ({{PLURAL:$2|1 taguri|$2 tiguriwin}})",
        "search-result-category-size": "$1 amdan{{PLURAL:$1||i-n}} ($2 ddu talɣa{{PLURAL:$2||i-s}}, $3 asdaw{{PLURAL:$3||i-n}})",
-       "search-result-score": "Tazdayt: $1%",
        "search-redirect": "(Asmmati $1)",
        "search-section": "Ayyaw $1",
        "search-suggest": "Is trit att nnit: $1",
        "filereuploadsummary": "Imbddln n usdaw",
        "filestatus": "Izrfan ḥbanin",
        "filesource": "Aɣbalu",
-       "uploadedimage": "Issrba \"[[$1]]\"",
        "upload-source": "Aɣbalu n usdaw",
        "sourcefilename": "Aɣbalu n ussaɣ n usdaw",
        "license": "Tlla s izrfan",
index 3b582a5..4c41510 100644 (file)
@@ -22,7 +22,9 @@
                        "රොමානිස් සැමුවෙල්",
                        "ශ්වෙත",
                        "සුරනිමල",
-                       "아라"
+                       "아라",
+                       "හරිත",
+                       "Indunil Chamara"
                ]
        },
        "tog-underline": "සබැඳි යටීර කිරීම:",
        "thursday": "බ්‍රහස්පතින්දා",
        "friday": "සිකුරාදා",
        "saturday": "සෙනසුරාදා",
-       "sun": "ඉරිදා",
-       "mon": "සඳුදා",
-       "tue": "අඟ",
-       "wed": "බදාදා",
-       "thu": "බ්‍රහස්",
-       "fri": "සිකු",
-       "sat": "සෙන",
+       "sun": "ඉරි:",
+       "mon": "සඳු:",
+       "tue": "අඟ:",
+       "wed": "බදා:",
+       "thu": "බ්‍රහ:",
+       "fri": "සිකු:",
+       "sat": "සෙන:",
        "january": "ජනවාරි",
        "february": "පෙබරවාරි",
        "march": "මාර්තු",
        "december-gen": "දෙසැම්බර්",
        "jan": "ජන",
        "feb": "පෙබ",
-       "mar": "මාර්තු",
-       "apr": "අප්‍රේල්",
+       "mar": "මාර්",
+       "apr": "අප්‍රේ",
        "may": "මැයි",
        "jun": "ජූනි",
        "jul": "ජූලි",
        "talkpagelinktext": "කතාබහ",
        "specialpage": "විශේෂ පිටුව",
        "personaltools": "පුද්ගලික මෙවලම්",
-       "postcomment": "නව ඡේදයක්",
        "articlepage": "අන්තර්ගත පිටුව නරඹන්න",
        "talk": "සාකච්ඡාව",
        "views": "දෘෂ්ටි",
        "hidetoc": "සඟවන්න",
        "collapsible-collapse": "හකුලන්න",
        "collapsible-expand": "විදහන්න",
+       "confirmable-confirm": "{{GENDER:$1|ඔබට}} විශ්වාස ද?",
+       "confirmable-yes": "ඔව්",
+       "confirmable-no": "නැත",
        "thisisdeleted": "අවශ්‍යතාවය $1 නැරඹීමද නැතහොත් ප්‍රතිෂ්ඨාපනයද?",
        "viewdeleted": "$1 නැරඹීම අවශ්‍යයද?",
        "restorelink": "මකා දමනු ලැබූ {{PLURAL:$1| එක් සංස්කරණයක්| සංස්කරණ $1  ක්}}",
        "externaldberror": "එක්කෝ සත්‍යාවත් දත්ත-ගබඩා දෝෂයක් පැවතුනි නැතිනම් ඔබගේ බාහිර ගිණුම යාවත්කාලීන කිරීමට ඔබ හට අවසර දී නොමැත.",
        "login": "පිවිසෙන්න",
        "nav-login-createaccount": "පිවිසෙන්න / නව ගිණුමක් තනන්න",
-       "loginprompt": "{{SITENAME}} වෙත ප්‍රවිෂ්ට වීම සඳහා ඔබ විසින් කුකීස් සක්‍රීය කොට තිබිය යුතුය.",
        "userlogin": "පිවිසෙන්න / නව ගිණුමක් තනන්න",
        "userloginnocreate": "ප්‍රවිෂ්ට වන්න",
        "logout": "නික්මීම",
        "gotaccountlink": "පිවිසෙන්න",
        "userlogin-resetlink": "ඔබේ පිවිසුම් තොරතුරු අමතකද?",
        "userlogin-resetpassword-link": "ඔබේ මුරපදය නැති වුනාද?",
-       "userlogin-loggedin": "ඔබ දැනටමත් {{GENDER:$1|}} ලෙස පිවිසී ඇත.\nනව පරිශීලකයෙකු ලෙස ඇතුළු වීමට පහත ආකෘතිය පුරවන්න.",
-       "userlogin-createanother": "තවත් ගිණුමක් ආරම්භ කරන්න",
        "createacct-emailrequired": "වි-තැපෑල ලිපිනය",
        "createacct-emailoptional": "වි-තැපෑල ලිපිනය (විකල්ප)",
        "createacct-email-ph": "ඔබගේ වි-තැපෑල ලිපිනය ඇතුළු කරන්න",
        "suspicious-userlogout": "නිෂ්ක්‍රමණය සඳහා ඔබගේ අයැදුම නිෂ්ප්‍රභා කෙරුනේ එය යොමු කොට ඇත්තේ භින්න(කැඩුනු) බ්‍රවුසරයකින් හෝ නිවේෂණය කෙරෙමින් පවතින ප්‍රොක්සියක් වෙතින් යැයි බැලූ බැල්මට පෙනෙන බැවිනි.",
        "createacct-another-realname-tip": "සැබෑ නාමය හෙළි කිරීම වෛකල්පිකයි.\nඔබ විසින් එය හෙළි කල හොත්, ඔබගේ කෘතීන් සඳහා ඔබහට කතෘ-බුහුමන් පිරිනැමීමට එය භාවිතා කරනු ඇත.",
        "pt-login": "පිවිසෙන්න",
+       "pt-login-button": "පිවිසෙන්න",
        "pt-createaccount": "ගිණුමක් තනන්න",
        "pt-userlogout": "නික්මීම",
        "php-mail-error-unknown": "php mail() ශ්‍රිතයේ හඳුනානොගත් ගැටළුවකි",
        "resetpass-temp-password": "තාවකාලික මුර-පදය:",
        "resetpass-abort-generic": "මුරපදය වෙනස් කිරීම විස්තීරණය මඟින් වලකා ඇත.",
        "resetpass-expired": "ඔබගේ මුරපදය කල් ඉකුත්වී ඇත.කරුණාකර නව මුරපදයක් සකස් කරන්න.",
-       "resetpass-expired-soft": "ඔබගේ මුරපදය කල් ඉකුත්වී ඇති අතර එය නැවත සකස් කල යුතුය.කරුණාකර දැන් මුරපදයක් තෝරන්න.නවත්තන්න click කිරීමෙන් එය පසුව සකස් කල හැකිය.",
+       "resetpass-expired-soft": "ඔබගේ මුරපදය කල් ඉකුත් වී ඇති අතර එය නැවත සකස් කල යුතුය. කරුණාකර දැන් නව මුරපදයක් තෝරන්න, නැතහොත් එය පසුව නැවත සැකසීමට \"{{int:resetpass-submit-cancel}}\" ඉටු කරන්න.",
+       "resetpass-validity-soft": "ඔබේ මුරපදය වලංගු නැත: $1\n\nකරුණාකර දැන් නව මුරපදයක් තෝරන්න, නැතහොත් එය පසුව සැකසීමට \"{{int:resetpass-submit-cancel}}\" ඉටු කරන්න.",
        "passwordreset": "මුරපදය වෙනස් කරන්න",
        "passwordreset-text-one": "තාවකාලික මුර-පදයක් විද්‍යුත් තැපෑළ මගින් ලබා ගැනීම සඳහා මෙම පෝරමය සම්පූර්ණ කරන්න.",
        "passwordreset-text-many": "{{PLURAL:$1|තාවකාලික මුරපදයක් ඊ-තැපෑල හරහා ගෙන්වා ගැනීමට එක් ක්ෂේත්‍රයක් පුරවන්න}}",
        "changeemail-submit": "විද්‍යුත් තැපෑල  වෙනස් කරන්න",
        "changeemail-cancel": "අවලංගු කරන්න",
        "changeemail-throttled": "ඔබ විසින් මෑතදී  පමණට වඩා වාර ගණනක් පිවිසීමෙහි උත්සාහයන් දරා ඇත.\nයළි උත්සාහ කිරීමට පෙර $1 වේලාවක් රැඳී සිටින්න.",
+       "resettokens": "සංකේත නැවත සකසන්න",
+       "resettokens-legend": "සංකේත නැවත සකසන්න",
+       "resettokens-tokens": "සංකේත:",
        "bold_sample": "තදකුරු පෙළ",
        "bold_tip": "තදකුරු පෙළ",
        "italic_sample": "ඇලකුරු පෙළ",
        "currentrev": "නවතම සංශෝධනය",
        "currentrev-asof": "$1 වන විට නවතම සංශෝධනය",
        "revisionasof": "$1 තෙක් සංශෝධනය",
-       "revision-info": "$1 වන විට $2 විසින් සිදු කර ඇති සංශෝධන",
+       "revision-info": "$1 වන විට {{GENDER:$6|$2}}$7 විසින් සිදු කර ඇති සංශෝධන",
        "previousrevision": "← පැරණි සංශෝධනය",
        "nextrevision": "නව සංශෝධනය →",
        "currentrevisionlink": "වත්මන් සංශෝධනය",
        "revdelete-confirm": "කරුණාකර ඔබ මෙය කිරීමට අදහස් කරන බවත්,එහි ප්‍රතිඵලය අවබෝධ කර ගන්නා බවත්,මෙය සිදු කරනුයේ [[{{MediaWiki:Policy-url}}| ප්‍රතිපත්තියට]] අනුකූලව බවත් තහවුරු කරන්න.",
        "revdelete-suppress-text": "යටපත්කිරීම පහත අවස්ථාවන්හිදී  '''පමණක්''' භාවිතා කල යුතුය:\n* නුසුදුසු පෞද්ගලික තොරතුරු\n*: ''නිවසෙහි ලිපින හා දුරකතන අංක ආදිය.''",
        "revdelete-legend": "දෘශ්‍ය අවහිරකිරීම් සකසන්න",
-       "revdelete-hide-text": "සංශෝධන පෙළ සඟවන්න",
+       "revdelete-hide-text": "සංශෝධන පෙළ",
        "revdelete-hide-image": "ගොනු අන්තර්ගතය සඟවන්න",
        "revdelete-hide-name": "ක්‍රියාව හා ඉලක්කය සඟවන්න",
        "revdelete-hide-comment": "සංස්කරණ පරිකථනය",
        "searchprofile-advanced-tooltip": "අභිරුචි නාමඅවකාශයන්හි ගවේෂණය කරන්න",
        "search-result-size": "$1 ({{PLURAL:$2|වචන 1 ක්|වචන $2 ක්}})",
        "search-result-category-size": "{{PLURAL:$1|එක් සාමාජීකයෙන්|සාමාජීකයන් $1 ක්}} ({{PLURAL:$2|එක් උප-ප්‍රවර්ගයක්|උප-ප්‍රවර්ග $2 ක්}}, {{PLURAL:$3|එක් ගොනුවක්|ගොනු $3 ක්}})",
-       "search-result-score": "අදාළතාව: $1%",
        "search-redirect": "($1 යළි-යොමු කරන්න)",
        "search-section": "($1 ඡේදය)",
        "search-file-match": "(ගොනු දත්ත සැසදේ)",
        "userrights-no-interwiki": "අනෙකුත් විකියන්හි පරිශීලක හිමිකම් සංස්කරණය කිරීමට ඔබහට අවසර නොමැත.",
        "userrights-nodatabase": "$1 දත්ත-ගබඩාව නොපවතියි හෝ ස්ථානීක නොවෙයි.",
        "userrights-nologin": "පරිශීලක හිමිකම් ප්‍රදානය කරනු වස්, ඔබ පරිපාලක ගිණුමකින්  [[Special:UserLogin|පුවිෂ්ට විය]] යුතුය.",
-       "userrights-notallowed": "පරà·\92à·\81à·\93ලà¶\9a à·\84à·\92මà·\92à¶\9aමà·\8a à¶\91à¶\9aà·\8a à¶\9aà·\92රà·\93මට à·\84à·\9d à¶\89à·\80තà·\8a à¶\9aà·\92රà·\93මට à¶\94බà¶\9cà·\9a à¶\9cà·\92ණà·\94මට à¶\85à·\80à·\83ර à¶±à·\90ත.",
+       "userrights-notallowed": "පරිශීලක හිමිකම් එක් කිරීමට හෝ ඉවත් කිරීමට ඔබට අවසර නැත.",
        "userrights-changeable-col": "ඔබට වෙනස් කල හැකි කණ්ඩායම්",
        "userrights-unchangeable-col": "ඔබට වෙනස් කල නොහැකි කණ්ඩායම්",
        "userrights-irreversible-marker": "$1*",
        "uploadwarning": "උඩුගත කිරීම් අවවාදයකි",
        "uploadwarning-text": "කරුණාකර පහත ගොනු විස්තරය වෙනස් කර නැවත උත්සාහ කරන්න.",
        "savefile": "ගොනුව සුරකින්න",
-       "uploadedimage": "\"[[$1]]\" උඩුගත කරන ලදි",
-       "overwroteimage": " \"[[$1]]\" හි නව අනුවාදයක් උඩුගත කරන ලදි",
        "uploaddisabled": "උඩුගත කිරීම් අක්‍රීය කර ඇත",
        "copyuploaddisabled": "URL මගින් උඩුගත කිරීම අක්‍රීය කොට ඇත.",
        "uploaddisabledtext": " {{SITENAME}} හි ගොනු උඩුගත කිරීම් අක්‍රීය කර ඇත.",
        "randomincategory": "ප්‍රවර්ගයේ අහඹු පිටු",
        "randomincategory-invalidcategory": "\"$1\" වලංගු ප්‍රවර්ග නාමයක් නොවේ.",
        "randomincategory-nopages": " [[:ප්‍රවර්ගය:$1|$1]] ප්‍රවර්ගයේ පිටු නොමැත.",
-       "randomincategory-selectcategory-submit": "යන්න",
+       "randomincategory-legend": "ප්‍රවර්ගයේ අහඹු පිටු",
        "randomredirect": "අහුඹු යළි-යොමුකිරීම",
        "randomredirect-nopages": "\"$1\" නාම-අවකාශයෙහි යළි-යොමුවීම් නොමැත.",
        "statistics": "සංඛ්‍යාන දත්ත",
        "notanarticle": "අන්තර්ගත පිටුවක් නොවේ",
        "notvisiblerev": "සංශෝධනය මකාදමා ඇත",
        "watchlist-details": "සාකච්ඡා පිටු නොගිණුනු කල, ඔබගේ මුර ලැයිස්තුවෙහි {{PLURAL:$1|එක් පිටුවක්|පිටු $1 ක්}} ඇත.",
-       "wlheader-enotif": "විද්‍යුත්-තැපැල් දැනුම්දීම සක්‍රීය කෙරිණි.",
-       "wlheader-showupdated": "ඔබ විසින් ඒවාට අවසන් වරට පිවිසුනු පසුව වෙනස්කෙරුනු පිටු  '''තදකුරු''' වලින් පෙන්වා ඇත",
+       "wlheader-enotif": "විද්‍යුත් තැපැල් දැනුම්දීම සක්‍රීයයි.",
+       "wlheader-showupdated": "ඔබ විසින් ඒවාට අවසන් වරට පිවිසුනු පසුව වෙනස්ව තිබෙන පිටු <strong>තදකුරු</strong> වලින් පෙන්වා ඇත.",
+       "wlnote": "පහත දැක්වෙන්නේ $3, $4 මෙන්, අවසන් {{PLURAL:$2|පැය|පැය '''$2''' }} තුලදී සිදු කෙරී ඇති {{PLURAL:$1|අවසන් වෙනස්වීම්යි |අවසන් වෙනස්වීම්  '''$1''' යි}}.",
        "wlshowlast": "පසුගිය පැය $1 දින $2 $3 පෙන්වන්න",
        "watchlist-options": "තෝරාගතහැකි මුර ලැයිස්තු සැකසුම්",
        "watching": "මුර කරමින්...",
        "import": "පිටු ආයාත කරන්න",
        "importinterwiki": "අන්තර්විකී ආයාතය",
        "import-interwiki-text": "ආයාත කිරීම සඳහා විකියක් හා පිටු ශීර්ෂයක් තෝරාගන්න.\nසංශෝධන දිනයන් හා සංස්කාරකවරුන්ගේ නම් සංරක්‍ෂණය කෙරෙනු ඇත.\nසියළු අන්තර්විකි ආ‍යාත ක්‍රියාවන් [[Special:Log/import|ආයාත ලඝු-සටහනෙහි]] සටහන් වනු ඇත.",
-       "import-interwiki-source": "මූලාශ්‍ර විකිය/පිටුව:",
+       "import-interwiki-sourcepage": "මූලාශ්‍ර පිටුව:",
        "import-interwiki-history": "මෙම පිටුව සඳහා සියළු ඉතිහාස අනුවාදයන් පිටපත් කරන්න",
        "import-interwiki-templates": "සියළු සැකිලි අන්තර්ගත කරන්න",
        "import-interwiki-submit": "ආයාත කරන්න",
        "duplicate-defaultsort": "'''අවවාදයයි:''' \"$2\" පෙරනිමි සුබෙදුම් යතුර විසින් ‍පූර්ව පෙරනිමි සුබෙදුම් යතුර වූ \"$1\" අතික්‍රමණය කරයි.",
        "version": "අනුවාදය",
        "version-extensions": "ස්ථාපිත ප්‍රසර්ජනයන්",
+       "version-skins": "ඡවිය",
        "version-specialpages": "විශේෂ පිටු",
        "version-parserhooks": "ව්‍යාකරණ විග්‍රහක හසුරු",
        "version-variables": "විචල්‍යයන්",
        "version-antispam": "ස්පෑම වැලැක්වුම",
-       "version-skins": "ඡවිය",
        "version-other": "වෙනත්",
        "version-mediahandlers": "මාධ්‍ය හසුරුවනය",
        "version-hooks": "හසුරු",
index a27497b..c581bf6 100644 (file)
@@ -26,7 +26,8 @@
                        "Valasek",
                        "Wizzard",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Matthew Greg"
                ]
        },
        "tog-underline": "Podčiarkovať odkazy:",
        "talkpagelinktext": "Diskusia",
        "specialpage": "Špeciálna stránka",
        "personaltools": "Osobné nástroje",
-       "postcomment": "Nová sekcia",
        "articlepage": "Zobraziť stránku",
        "talk": "Diskusia",
        "views": "Zobrazení",
        "hidetoc": "skryť",
        "collapsible-collapse": "zbaliť",
        "collapsible-expand": "rozbaliť",
+       "confirmable-yes": "Áno",
+       "confirmable-no": "Nie",
        "thisisdeleted": "Zobraziť alebo obnoviť $1?",
        "viewdeleted": "Zobraziť $1?",
        "restorelink": "{{PLURAL:$1|jednu zmazanú úpravu|$1 zmazané úpravy|$1 zmazaných úprav}}",
        "externaldberror": "Buď nastala chyba externej autentifikačnej databázy alebo vám nie je povolené aktualizovať váš externý účet.",
        "login": "Prihlásiť",
        "nav-login-createaccount": "Prihlásenie / vytvorenie účtu",
-       "loginprompt": "Na prihlásenie do {{GRAMMAR:genitív|{{SITENAME}}}} musíte mať zapnuté koláčiky (cookies).",
        "userlogin": "Prihlásenie / vytvorenie účtu",
        "userloginnocreate": "Prihlásiť",
        "logout": "Odhlásiť",
        "userlogin-resetlink": "Zabudli ste svoje prihlasovacie údaje?",
        "userlogin-resetpassword-link": "Zabudli ste heslo?",
        "userlogin-helplink2": "Pomoc s prihlásením",
-       "userlogin-loggedin": "Ste už {{GENDER:$1|prihĺasený|prihlásená}} ako $1.\nPomocou formulára nižšie sa môžete prihlásiť ako iný redaktor.",
-       "userlogin-createanother": "Vytvoriť ďalší účet",
        "createacct-emailrequired": "E-mailová adresa",
        "createacct-emailoptional": "E-mailová adresa (nepovinné)",
        "createacct-email-ph": "Zadajte vašu e-mailovú adresu",
        "resetpass-temp-password": "Dočasné heslo:",
        "resetpass-abort-generic": "Zmena hesla bola zablokovaná rozšírením.",
        "resetpass-expired": "Platnosť vášho hesla vypršala. Pre prihlásenie si nastavte nové heslo.",
+       "resetpass-expired-soft": "Platnosť vášho hesla vypršala, musíte si nastaviť nové. Zvoľte si nové heslo nebo kliknite na „{{int:resetpass-submit-cancel}}“ a nastavte si ho neskôr.",
+       "resetpass-validity-soft": "Vaše heslo je neplatné: $1\n\nVyberte si nové heslo, alebo kliknite na „{{int:resetpass-submit-cancel}}“ a nastavte si ho neskôr.",
        "passwordreset": "Reset hesla",
        "passwordreset-text-one": "Pre získanie nového hesla vyplňte tento formulár.",
        "passwordreset-text-many": "{{PLURAL:$1|Pre získanie nového hesla zadajte jeden z údajov.}}",
        "searchprofile-advanced-tooltip": "Hľadať vo vymenovaných menných priestoroch",
        "search-result-size": "$1 ({{PLURAL:$2|1 slovo|$2 slová|$2 slov}})",
        "search-result-category-size": "{{PLURAL:$1|1 člen|$1 členovia|$1 členov}} ({{PLURAL:$2|1 podkategória|$2 podkategórie|$2 podkategórií}}, {{PLURAL:$3|1 súbor|$3 súbory|$3 súborov}})",
-       "search-result-score": "Relevancia: $1%",
        "search-redirect": "(presmerovanie $1)",
        "search-section": "(sekcia $1)",
        "search-suggest": "Mali ste na mysli „$1“?",
        "searchrelated": "súvisiace",
        "searchall": "všetko",
        "showingresults": "Nižšie {{PLURAL:$1|je zobrazený jeden výsledok|sú zobrazené '''1''' výsledky|je zobrazených '''$1''' výsledkov}}, počnúc od  #<b>$2</b>.",
-       "showingresultsheader": "{{PLURAL:$5|Výsledok '''$1''' z '''$3'''|Výsledky '''$1 - $2''' z '''$3'''}} pre '''$4'''",
        "search-nonefound": "Vyhľadávanie nenašlo žiadne výsledky.",
        "powersearch-legend": "Pokročilé hľadanie",
        "powersearch-ns": "Hľadať v menných priestoroch:",
        "uploadwarning": "Varovanie pri nahrávaní",
        "uploadwarning-text": "Prosím, zmeňte popis súboru nižšie a skúste to znova.",
        "savefile": "Uložiť súbor",
-       "uploadedimage": "nahraný „[[$1]]“",
-       "overwroteimage": "bola nahraná nová verzia „[[$1]]“",
        "uploaddisabled": "Prepáčte, nahrávanie je vypnuté.",
        "copyuploaddisabled": "Nahrávanie prostredníctvom URL nie je povolené.",
        "uploaddisabledtext": "Nahrávanie súborov je vypnuté.",
        "license-nopreview": "(Náhľad nie je dostupný)",
        "upload_source_url": " (platný, verejne prístupný URL)",
        "upload_source_file": " (súbor na vašom počítači)",
+       "listfiles-delete": "zmazať",
        "listfiles-summary": "Táto špeciálna stránka zobrazuje všetky nahrané súbory.",
        "listfiles_search_for": "Hľadať názov súboru:",
        "imgfile": "súbor",
        "randomincategory": "Náhodná stránka v kategórii",
        "randomincategory-invalidcategory": "\"$1\" nie je platný názov kategórie.",
        "randomincategory-nopages": "V [[:Category:$1|kategórii $1]] nie sú žiadne stránky.",
-       "randomincategory-selectcategory": "Získať náhodnú stránku z kategórie: $1 $2",
-       "randomincategory-selectcategory-submit": "Ísť na",
+       "randomincategory-category": "Kategória:",
+       "randomincategory-legend": "Náhodná stránka v kategórii",
        "randomredirect": "Náhodná presmerovacia stránka",
        "randomredirect-nopages": "V mennom „$1“ priestore nie sú žiadne presmerovania.",
        "statistics": "Štatistiky",
        "pageswithprop-prophidden-binary": "hodnota binárnej vlastnosti bola skrytá ($1)",
        "doubleredirects": "Dvojité presmerovania",
        "doubleredirectstext": "Táto stránka obsahuje zoznam stránok, ktoré presmerovávajú na iné presmerovacie stránky.\nKaždý riadok obsahuje odkaz na prvé a druhé presmerovanie a tiež prvý riadok z textu na ktorý odkazuje druhé presmerovanie, ktoré zvyčajne odkazuje na „skutočný“ cieľ, na ktorý má odkazovať prvé presmerovanie.\n<del>Prečiarknuté</del> položky boli vyriešené.",
-       "double-redirect-fixed-move": "Stránka [[$1]] bola presunutá, teraz je presmerovaním na [[$2]]",
+       "double-redirect-fixed-move": "Stránka [[$1]] bola presunutá.\nBola automaticky aktualizovaná a teraz presmerováva na [[$2]]",
        "double-redirect-fixed-maintenance": "Opravuje sa dvojité presmerovanie z [[$1]] na [[$2]].",
        "double-redirect-fixer": "Korektor presmerovaní",
        "brokenredirects": "Pokazené presmerovania",
        "watchlist-details": "{{PLURAL:$1|Jedna sledovaná stránka|$1 sledované stránky|$1 sledovaných stránok}}, nepočítajúc diskusné stránky.",
        "wlheader-enotif": "Upozorňovanie e-mailom je zapnuté.",
        "wlheader-showupdated": "Stránky, ktoré boli zmenené od vašej poslednej návštevy sú zobrazené '''tučne'''.",
+       "wlnote": "Nižšie {{PLURAL:$1|je posledná jedna zmena|sú posledné '''$1''' zmeny|je posledných '''$1''' zmien}} za {{PLURAL:$2|poslednú hodinu|posledné '''$2''' hodiny|posledných '''$2''' hodín}} do $4, $3.",
        "wlshowlast": "Zobraziť posledných $1 hodín $2 dní $3",
        "watchlist-options": "Nastavenia zoznamu sledovaných",
        "watching": "Pridávam do zoznamu sledovaných...",
        "import": "Import stránok",
        "importinterwiki": "Transwiki import",
        "import-interwiki-text": "Zvoľte wiki a názov stránky, ktorá sa má importovať.\nDátumy revízií a mená používateľov budú zachované.\nVšetky transwiki importy sa zaznamenávajú v [[Special:Log/import|Zázname importov]].",
-       "import-interwiki-source": "Zdrojová wiki/stránka:",
        "import-interwiki-history": "Skopírovať všetky historické revízie tejto stránky",
        "import-interwiki-templates": "Vložiť všetky šablóny",
        "import-interwiki-submit": "Importovať",
        "watchlistedit-raw-done": "Váš zoznam sledovaných stránok bol aktualizovaný.",
        "watchlistedit-raw-added": "{{PLURAL:$1|Jedna položka bola pridaná|$1 položky boli pridané|$1 položiek bolo pridaných}}:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|Jedna položka bola odstránená|$1 položky boli odstránené|$1 položiek bolo odstránených}}:",
+       "watchlistedit-clear-titles": "Názvy:",
        "watchlisttools-view": "Zobraziť súvisiace zmeny",
        "watchlisttools-edit": "Zobraziť a upraviť zoznam sledovaných stránok",
        "watchlisttools-raw": "Upraviť nespracovaný zoznam sledovaných stránok",
        "duplicate-defaultsort": "Upozornenie: Štandardný kláves na zoraďovanie „$2“ nahrádza starý kláves „$1“.",
        "version": "Verzia",
        "version-extensions": "Nainštalované rozšírenia",
+       "version-skins": "Témy vzhľadu",
        "version-specialpages": "Špeciálne stránky",
        "version-parserhooks": "Prípojné body syntaktického analyzátora",
        "version-variables": "Premenné",
        "version-antispam": "Ochranu proti spamu",
-       "version-skins": "Témy vzhľadu",
        "version-other": "Iné",
        "version-mediahandlers": "Obsluha multimédií",
        "version-hooks": "Prípojné body",
        "version-license": "Licencia",
        "version-ext-license": "Licencia",
        "version-ext-colheader-name": "Rozšírenie",
+       "version-skin-colheader-name": "Vzhľad",
        "version-ext-colheader-version": "Verzia",
        "version-ext-colheader-license": "Licencia",
        "version-ext-colheader-description": "Popis",
        "htmlform-no": "Nie",
        "htmlform-yes": "Áno",
        "htmlform-chosen-placeholder": "Vyberte možnosť",
+       "htmlform-cloner-create": "Pridať ďalšie",
+       "htmlform-cloner-delete": "Odstrániť",
        "sqlite-has-fts": "$1 s podporou vyhľadávania v plnom texte",
        "sqlite-no-fts": "$1 bez podpory vyhľadávania v plnom texte",
        "logentry-delete-delete": "$1 zmazal stránku $3",
        "expand_templates_remove_comments": "Odstrániť komentáre",
        "expand_templates_remove_nowiki": "Potlačiť značky <nowiki> vo výsledku",
        "expand_templates_generate_xml": "Zobraziť strom XML",
-       "expand_templates_preview": "Náhľad"
+       "expand_templates_preview": "Náhľad",
+       "pagelang-name": "Stránka",
+       "pagelang-language": "Jazyk",
+       "pagelang-use-default": "Použiť predvolený jazyk",
+       "pagelang-select-lang": "Vybrať jazyk",
+       "right-pagelang": "Zmeniť jazyk stránky",
+       "default-skin-not-found": "Uups! Základná tapeta pre Vašu wiki, popísanú v <code dir=\"ltr\">$wgDefaultSkin</code> ako <code>$1</code>, nie je dostupná. \n\nVaša inštalácia pravdepodobne obsahuje nasledovné tapety. Pozri [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Skin configuration] pre viac informácii o ich aktivácii a zvoľte základnú.\n\n$2\n\n; Ak ste MediaWiki len teraz nainštalovali\n; Zrejme ste to nainštalovali z gitu alebo priamo zo zdrojového kódu inou metódou. Je to očakávané. Skúste nainštalovať nejaké tapety z [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's skin directory];\n:*Stiahnutím [https://www.mediawiki.org/wiki/Download tarball installer], ktorý ponúka viacero tapiet a rozšírení. Skopírovať a nalepiť možno priamo z <code>skins/</code>.\n:*Klonovanie jednej zo <code>mediawiki/skins/*</code> schránok cez git do <code dir=\"ltr\">skins/</code> priečinku Vašej Media Wiki inštalácie.\n: S existujúcou git schránkou, ak ste vývojár MediaWiki, by nemal byť konflikt.\n\n: Ak ste upgradeovali MediaWiki\n: MediaWiki 1.24 a novšie už tapety automaticky neaktivujú. (see [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: Skin autodiscovery]). Nasledovný kód môžete skopírovať do <code>LocalSettings.php</code> pre aktivovanie všetkých dostupných tapiet.\n\n<pre dir=\"ltr\">$3</pre>\n\n; Ak ste upravili <code>LocalSettings.php</code>:\n: Skontrolujte chyby."
 }
index 040772c..4e9bb7c 100644 (file)
@@ -26,6 +26,7 @@
        "tog-watchdefault": "Na spisek nadzorov dodaj vse članke in datoteke, ki sem jih spremenil/-a",
        "tog-watchmoves": "Dodaj strani in datoteke, ki jih premaknem, na moj spisek nadzorov",
        "tog-watchdeletion": "Dodaj strani in datoteke, ki jih izbrišem, na moj spisek nadzorov",
+       "tog-watchrollback": "Dodaj strani, na katerih sem izvedel vrnitev, na moj spisek nadzorov",
        "tog-minordefault": "Vsa urejanja označi kot manjša",
        "tog-previewontop": "Prikaži predogled pred urejevalnim poljem",
        "tog-previewonfirst": "Ob začetku urejanja prikaži predogled",
        "talkpagelinktext": "Pogovor",
        "specialpage": "Posebna stran",
        "personaltools": "Osebna orodja",
-       "postcomment": "Nov razdelek",
        "articlepage": "Prikaže članek",
        "talk": "Pogovor",
        "views": "Pogled",
        "otherlanguages": "V drugih jezikih",
        "redirectedfrom": "(Preusmerjeno s strani $1)",
        "redirectpagesub": "Preusmeritvena stran",
+       "redirectto": "Preusmeritev na:",
        "lastmodifiedat": "Čas zadnje spremembe: $2, $1.",
        "viewcount": "Stran je bila naložena {{PLURAL:$1|$1-krat}}.",
        "protectedpage": "Zaščitena stran",
        "hidetoc": "skrij",
        "collapsible-collapse": "Skrči",
        "collapsible-expand": "Razširi",
+       "confirmable-confirm": "{{GENDER:$1|Ste}} prepričani?",
+       "confirmable-yes": "Da",
+       "confirmable-no": "Ne",
        "thisisdeleted": "Prikažem ali vrnem $1?",
        "viewdeleted": "Prikažem $1?",
        "restorelink": "$1 {{PLURAL:$1|izbrisano redakcijo|izbrisani redakciji|izbrisane redakcije|izbrisanih redakcij}}",
        "invalidtitle-knownnamespace": "Neveljaven naslov z imenskim prostorom »$2« in besedilom »$3«",
        "invalidtitle-unknownnamespace": "Neveljaven naslov z neznano številko imenskega prostora $1 in besedilom »$2«",
        "exception-nologin": "Niste prijavljeni",
-       "exception-nologin-text": "Prosimo, [[Special:Userlogin|prijavite se]], da lahko dostopate do strani ali dejanja.",
+       "exception-nologin-text": "Prosimo, prijavite se, da lahko dostopate do strani ali dejanja.",
        "exception-nologin-text-manual": "Da lahko dostopate do strani ali dejanja, se morate $1.",
        "virus-badscanner": "Slaba konfiguracija: neznani virus skener: ''$1''",
        "virus-scanfailed": "pregled ni uspel (koda $1)",
        "externaldberror": "Pri potrjevanju istovetnosti je prišlo do notranje napake ali pa za osveževanje zunanjega računa nimate dovoljenja.",
        "login": "Prijava",
        "nav-login-createaccount": "Prijavite se / registrirajte se",
-       "loginprompt": "Za prijavo v {{GRAMMAR:tožilnik|{{SITENAME}}}} morate imeti omogočene piškotke.",
        "userlogin": "Prijavite se / registrirajte se",
        "userloginnocreate": "Prijava",
        "logout": "Odjava",
        "userlogin-resetlink": "Ste pozabili svoje prijavne podatke?",
        "userlogin-resetpassword-link": "Ste pozabili svoje geslo?",
        "userlogin-helplink2": "Pomoč pri prijavi",
-       "userlogin-loggedin": "Prijavljeni ste že kot {{GENDER:$1|$1}}.\nUporabite spodnji obrazec, da se prijavite kot drug uporabnik.",
-       "userlogin-createanother": "Ustvari drug račun",
        "createacct-emailrequired": "E-poštni naslov",
        "createacct-emailoptional": "E-poštni naslov (izbirno)",
        "createacct-email-ph": "Vnesite svoj e-poštni naslov",
        "createaccount-text": "Nekdo je ustvaril račun $2 na {{GRAMMAR:dajalnik|{{SITENAME}}}} ($4). Geslo za »$2« je »$3«. Priporočljivo je, da se prijavite in spremenite svoje geslo sedaj.\n\nTo sporočilo lahko prezrete, če je bil račun ustvarjen pomotoma.",
        "login-throttled": "Nedavno ste izvedli preveč poskusov prijave.\nProsimo, počakajte $1, preden poskusite znova.",
        "login-abort-generic": "Vaša prijava ni bila uspešna – Prekinjeno",
+       "login-migrated-generic": "Vaš račun smo preselili in vaše uporabniško ime na tem wikiju ne obstaja več.",
        "loginlanguagelabel": "Jezik: $1",
        "suspicious-userlogout": "Vaša zahteva za odjavo je bila zavrnjena, saj kaže, da je bila poslana iz pokvarjenega brskalnika ali proxyja s predpomnilnikom.",
        "createacct-another-realname-tip": "Pravo ime ni obvezno.\nČe se ga odločite navesti, bo uporabljeno za priznavanje uporabnikovega dela.",
        "preview": "Predogled",
        "showpreview": "Prikaži predogled",
        "showdiff": "Prikaži spremembe",
-       "anoneditwarning": "'''Opozorilo''': niste prijavljeni. V zgodovino strani se bo zapisal vaš IP-naslov.",
+       "blankarticle": "<strong>Opozorilo:</strong> Stran, ki jo ustvarjate, je prazna.\nČe ponovno kliknete »{{int:savearticle}}«, bomo stran ustvarili brez kakršne koli vsebine.",
+       "anoneditwarning": "<strong>Opozorilo:</strong> Niste prijavljeni. Vaš IP-naslov bo javno viden, če naredite kakršno koli urejanje. Če se <strong>[$1 prijavite]</strong> ali <strong>[$2 ustvarite račun]</strong>, bodo vaša urejanja pripisana vašemu uporabniškemu imenu skupaj z drugimi prednostmi.",
        "anonpreviewwarning": "Niste prijavljeni. Ob spremembi strani se bo vaš IP-naslov zapisal v zgodovini urejanja te strani.",
        "missingsummary": "'''Opozorilo:''' Niste napisali povzetka urejanja. Ob ponovnem kliku gumba ''Shrani'' se bo vaše urejanje shranilo brez njega.",
        "missingcommenttext": "Prosimo, vpišite v spodnje polje komentar.",
        "parser-template-recursion-depth-warning": "Prekoračena globina rekurzije predlog ($1)",
        "language-converter-depth-warning": "Prekoračena globina pretvorbe jezikov ($1)",
        "node-count-exceeded-category": "Strani s prekoračenim številom vozlišč",
-       "node-count-exceeded-category-desc": "Kategorija s stranmi, na katerih je preseženo število vozlišč.",
+       "node-count-exceeded-category-desc": "Stran presega največje število vozlišč.",
        "node-count-exceeded-warning": "Stran je prekoračila število vozlišč",
        "expansion-depth-exceeded-category": "Strani s prekoračeno globino razširitve",
-       "expansion-depth-exceeded-category-desc": "Kategorija s stranmi, na katerih je prekoračena globina razširitve.",
+       "expansion-depth-exceeded-category-desc": "Stran presega največjo globino razširitve.",
        "expansion-depth-exceeded-warning": "Stran je prekoračila globino razširitve",
        "parser-unstrip-loop-warning": "Zaznal sem odvezano zanko",
        "parser-unstrip-recursion-limit": "Presežena je omejitev odvezane rekurzije ($1)",
        "rev-deleted-event": "(dnevniški vnos je odstranjen)",
        "rev-deleted-user-contribs": "[uporabniško ime ali IP naslov odstranjeni - urajenje skrito v prispevkih]",
        "rev-deleted-text-permission": "Prikazana redakcija je bila '''izbrisana'''.\nPodrobnosti so na razpolago v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} dnevniku brisanja].",
+       "rev-suppressed-text-permission": "Ta redakcija strani je bila <strong>zatrta</strong>.\nPodrobnosti so navedene v [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} dnevniku zatrtij].",
        "rev-deleted-text-unhide": "Ta sprememba je bila '''izbrisana'''.\nPodrobnosti so morda navedene v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} dnevniku brisanja].\nŠe vedno lahko [$1 pogledate to redakcijo], če želite nadaljevati.",
-       "rev-suppressed-text-unhide": "Ta sprememba je bila '''zavrnjena'''.\nPodrobnosti so morda navedene v [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} dnevniku zavračanj].\nŠe vedno lahko [$1 pogledate to redakcijo], če želite nadaljevati.",
+       "rev-suppressed-text-unhide": "Ta sprememba je bila <strong>zatrta</strong>.\nPodrobnosti so morda navedene v [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} dnevniku zatrtij].\nŠe vedno lahko [$1 pogledate to redakcijo], če želite nadaljevati.",
        "rev-deleted-text-view": "Prikazana redakacija strani je bila iz javnih arhivov odstranjena.\nLahko si jo ogledate; podrobnosti so morda navedene v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} dnevniku brisanja].",
-       "rev-suppressed-text-view": "Ta sprememba je bila '''zavrnjena'''.\nLahko si jo ogledate; podrobnosti so morda navedene v [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} dnevniku zavračanj].",
+       "rev-suppressed-text-view": "Ta sprememba je bila <strong>zatrta</strong>.\nLahko si jo ogledate; podrobnosti so morda navedene v [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} dnevniku zatrtij].",
        "rev-deleted-no-diff": "Povzetka sprememb ne morete videti, ker je bil eden od popravkov '''izbrisan'''.\nPodrobnosti so morda navedene v  [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} dnevniku brisanja].",
        "rev-suppressed-no-diff": "Ogled redakcije ni mogoč, ker je bila ena od sprememb '''izbrisana'''.",
        "rev-deleted-unhide-diff": "Ena od sprememb v tej redakciji je bila '''izbrisana'''.\nPodrobnosti so morda navedene v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} dnevniku brisanja].\nŠe vedno lahko [$1 pogledate to redakcijo], če želite nadaljevati.",
-       "rev-suppressed-unhide-diff": "Ena od sprememb v tej redakciji je bila '''zadržana'''.\nPodrobnosti so morda navedene v [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} dnevniku zadržkov].\nŠe vedno lahko [$1 pogledate to redakcijo], če želite nadaljevati.",
+       "rev-suppressed-unhide-diff": "Ena od sprememb v tej redakciji je bila <strong>zatrta</strong>.\nPodrobnosti so morda navedene v [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} dnevniku zatrtij].\nŠe vedno lahko [$1 pogledate to redakcijo], če želite nadaljevati.",
        "rev-deleted-diff-view": "Ena od sprememb v tej redakciji je bila '''izbrisana'''.\nTo redakcijo si lahko ogledate; podrobnosti lahko najdete v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} dnevniku brisanja].",
-       "rev-suppressed-diff-view": "Ena od sprememb v tej redakciji je bila '''zadržana'''.\nTo redakcijo si lahko ogledate; podrobnosti lahko najdete v [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} dnevniku zadržkov].",
+       "rev-suppressed-diff-view": "Ena od sprememb v tej redakciji je bila <strong>zatrta</strong>.\nTo redakcijo si lahko ogledate; podrobnosti lahko najdete v [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} dnevniku zatrtij].",
        "rev-delundel": "pokaži/skrij",
        "rev-showdeleted": "prikaži",
        "revisiondelete": "Izbriši/obnovi redakcije",
        "revdelete-text-text": "Izbrisane redakcije bodo še vedno prikazane v zgodovini strani, vendar bodo deli njihovih vsebin nedostopni javnosti.",
        "revdelete-text-file": "Izbrisane različice datoteke bodo še vedno prikazane v zgodovini datoteke, vendar bodo deli njihovih vsebin nedostopni javnosti.",
        "logdelete-text": "Izbrisani dnevniški vnosi bodo še vedno prikazani v dnevnikih, vendar bodo deli njihovih vsebin nedostopni javnosti.",
-       "revdelete-text-others": "Drugi administratorji na strani {{SITENAME}} bodo še vedno lahko dostopali do skrite vsebine in jo obnovili z enakim vmesnikom, razen če so nastavljene dodatne omejitve.",
-       "revdelete-confirm": "Prosim potrdite da nameravate to storiti, da se zavedate posledic in da to počnete v skladu s [[{{MediaWiki:Policy-url}}|politiko]].",
-       "revdelete-suppress-text": "Zadrževanje naj bi bilo uporabljeno '''le''' v sledečih primerih:\n* Morebitni klevetniški podatki\n* Neprimerni osebni podatki\n*: ''domači naslovi in telefonske številke, narodne številke istovetnosti itn.''",
+       "revdelete-text-others": "Drugi administratorji bodo še vedno lahko dostopali do skrite vsebine in jo obnovili, razen če so nastavljene dodatne omejitve.",
+       "revdelete-confirm": "Prosimo, potrdite, da nameravate to storiti, da se zavedate posledic in da to počnete v skladu s [[{{MediaWiki:Policy-url}}|politiko]].",
+       "revdelete-suppress-text": "Zatrtje naj bi bilo uporabljeno <strong>le</strong> v sledečih primerih:\n* morebitni klevetniški podatki\n* neprimerni osebni podatki\n*: <em>domači naslovi in telefonske številke, narodne številke istovetnosti itn.</em>",
        "revdelete-legend": "Nastavi omejitve vidnosti",
        "revdelete-hide-text": "Besedilo redakcije",
        "revdelete-hide-image": "Skrij vsebino datoteke.",
        "revdelete-radio-same": "(ne spremeni)",
        "revdelete-radio-set": "Skrito",
        "revdelete-radio-unset": "Vidno",
-       "revdelete-suppress": "Zadrži podatke od administratorjev kakor tudi od ostalih",
+       "revdelete-suppress": "Zatri podatke od administratorjev, kakor tudi od ostalih",
        "revdelete-unsuppress": "Odpraviti omejitve na obnovljenih redakcijah.",
        "revdelete-log": "Razlog:",
        "revdelete-submit": "Uporabi za {{PLURAL:$1|izbrano redakcijo|izbrani redakciji|izbrane redakcije}}",
        "searchprofile-advanced-tooltip": "Iskanje v imenskih prostorih po meri",
        "search-result-size": "$1 ({{PLURAL:$2|1 beseda|2 besedi|$2 besede|$2 besed|$2 besed}})",
        "search-result-category-size": "$1 {{PLURAL:$1|član|člana|člani|članov}} ($1 {{PLURAL:$2|podkategorija|podkategoriji|podkategorije|podkategorij}}, $1 {{PLURAL:$3|datoteka|datoteki|datoteke|datotek}})",
-       "search-result-score": "Ustreznost: $1%",
        "search-redirect": "(preusmeritev $1)",
        "search-section": "(razdelek $1)",
        "search-file-match": "(ujema se z vsebino datoteke)",
        "searchall": "vse",
        "showingresults": "Prikazujem do '''$1''' {{PLURAL:$1|zadetek|zadetka|zadetke|zadetkov}}, začenši s št. '''$2'''.",
        "showingresultsinrange": "Spodaj prikazujem {{PLURAL:$1|1=<strong>1</strong> rezultat|<strong>$1</strong> rezultata|<strong>$1</strong> rezultate|<strong>$1</strong> rezultatov}} v razponu od št. <strong>$2</strong> do št. <strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Zadetek '''$1''' od '''$3'''|Zadetki '''$1 - $2''' od skupno '''$3'''}} za povpraševanje '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Rezultat <strong>$1</strong> od <strong>$3</strong>|Rezultati <strong>$1–$2</strong> od <strong>$3</strong>}}",
        "search-nonefound": "Ni bilo zadetkov, ki ustrezajo poizvedbi.",
        "powersearch-legend": "Napredno iskanje",
        "powersearch-ns": "Iskanje v imenskih prostorih:",
        "preferences": "Nastavitve",
        "mypreferences": "Nastavitve",
        "prefs-edits": "Število urejanj:",
-       "prefsnologintext2": "Za nastavljanje uporabniških nastavitev se morate $1.",
+       "prefsnologintext2": "Za spreminjanje svojih nastavitev se morate prijaviti.",
        "prefs-skin": "Koža",
        "skin-preview": "Predogled",
        "datedefault": "Kakor koli",
        "right-deletedtext": "Ogled izbrisanega besedila in primerjava med izbrisanimi redakcijami",
        "right-browsearchive": "Iskanje izbrisanih strani",
        "right-undelete": "Obnavljanje strani",
-       "right-suppressrevision": "Pregled in obnova pred administratorjem skritih redakcij",
+       "right-suppressrevision": "Ogled, skrivanje in obnavljanje določenih redakcij strani katerega koli uporabnika",
+       "right-viewsuppressed": "Ogled redakcij skritih pred vsemi uporabniki",
        "right-suppressionlog": "Ogled zasebnih dnevniških zapisov",
        "right-block": "Preprečitev (blokada) urejanja drugih uporabnikov",
        "right-blockemail": "Drugemu uporabniku lahko prepreči pošiljanje e-pošte",
        "recentchanges-label-plusminus": "uporabnik je velikost strani spremenil za tolikšno število bajtov",
        "recentchanges-legend-heading": "'''Legenda:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (glej tudi [[Special:NewPages|seznam novih strani]])",
-       "rcnotefrom": "Navedene so spremembe od <strong>$2</strong> dalje (prikazujem jih do <strong>$1</strong>).",
+       "rcnotefrom": "{{PLURAL:$5|Navedena je sprememba|Navedeni sta spremembi|Navedene so spremembe}} od <strong>$3 $4</strong> dalje (prikazujem jih do <strong>$1</strong>).",
        "rclistfrom": "Prikaži spremembe od $3 $2 naprej",
        "rcshowhideminor": "$1 manjša urejanja",
        "rcshowhideminor-show": "Prikaži",
        "uploadwarning": "Opozorilo!",
        "uploadwarning-text": "Prosimo, spremenite opis datoteke spodaj in poskusite ponovno.",
        "savefile": "Shrani datoteko",
-       "uploadedimage": "je naložil(-a) datoteko »[[$1]]«",
-       "overwroteimage": "je naložil(-a) novo različico datoteke »[[$1]]«",
        "uploaddisabled": "Nalaganje je onemogočeno",
        "copyuploaddisabled": "Nalaganje preko URL je onemogočeno",
        "uploaddisabledtext": "Nalaganje datotek je onemogočeno.",
        "license": "Licenca:",
        "license-header": "Licenca",
        "nolicense": "Nobeno",
+       "licenses-edit": "Urejanje možnosti dovoljenja",
        "license-nopreview": "(Predogled ni na voljo)",
-       "upload_source_url": " (veljaven, javnosti dostopen URL)",
-       "upload_source_file": " (datoteka na vašem računalniku)",
+       "upload_source_url": "(vaša izbrana datoteka z veljavnega, javnosti dostopnega URL-ja)",
+       "upload_source_file": "(vaša izbrana datoteka z vašega računalnika)",
+       "listfiles-delete": "izbriši",
        "listfiles-summary": "Ta posebna stran prikazuje vse naložene datoteke.",
        "listfiles_search_for": "Išči po imenu datoteke:",
        "imgfile": "dat.",
        "randomincategory": "Naključna stran v kategoriji",
        "randomincategory-invalidcategory": "»$1« ni veljavno ime kategorije.",
        "randomincategory-nopages": "V kategoriji [[:Category:$1]] ni nobene strani.",
-       "randomincategory-selectcategory": "Dobi naključno stran iz kategorije: $1 $2.",
-       "randomincategory-selectcategory-submit": "Pojdi",
+       "randomincategory-category": "Kategorija:",
+       "randomincategory-legend": "Naključna stran v kategoriji",
        "randomredirect": "Naključna preusmeritev",
        "randomredirect-nopages": "V imenskem prostoru »$1« ni preusmeritev.",
        "statistics": "Statistika",
        "wantedpages-badtitle": "Neveljaven naslov v končnem nizu: $1",
        "wantedfiles": "Želene datoteke",
        "wantedfiletext-cat": "Naslednje datoteke so uporabljene, vendar ne obstajajo. Navedene so morda tudi datoteke iz zunanjih hramb, čeprav obstajajo. Vsi takšni lažni pozitivi bodo <del>prečrtani</del>. Poleg tega so strani, ki vključujejo neobstoječe datoteke, navedene na [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Spodnje datoteke so nekje uporabljene, vendar ne obstajajo. Dodatno lahko strani, ki vključujejo neobstoječe datoteke, najdete na [[:$1]].",
        "wantedfiletext-nocat": "Naslednje datoteke so uporabljene, vendar ne obstajajo. Navedene so morda tudi datoteke iz zunanjih hramb, čeprav obstajajo. Vsi takšni lažni pozitivi bodo <del>prečrtani</del>.",
+       "wantedfiletext-nocat-noforeign": "Spodnje datoteke so nekje uporabljene, vendar ne obstajajo.",
        "wantedtemplates": "Želene predloge",
        "mostlinked": "Strani, na katere se največ povezuje",
        "mostlinkedcategories": "Kategorije z največ elementi",
        "trackingcategories-desc": "Merila za vključitev v kategorijo",
        "noindex-category-desc": "Stran vsebuje čarobno besedo <code><nowiki>__NOINDEX__</nowiki></code> (in je v imenskem prostoru, ki dovoljuje to oznako) in posledično je roboti ne indeksirajo.",
        "index-category-desc": "Stran vsebuje čarobno besedo <code><nowiki>__INDEX__</nowiki></code> (in je v imenskem prostoru, ki dovoljuje to oznako) in posledično jo roboti indeksirajo, čeprav je drugače ne bi.",
-       "post-expand-template-inclusion-category-desc": "Po razširitvi vseh predlog je velikost strani več kot <code>$wgMaxArticleSize</code>, zato nekaterih predlog nismo razširili.",
-       "post-expand-template-argument-category-desc": "Po razširitvi argumentov predloge (nekaj v trojnih narekovajih, npr. <code>{{{Foo}}})</code> je stran večja od <code>$wgMaxArticleSize</code>.",
+       "post-expand-template-inclusion-category-desc": "Velikost strani je po razširitvi vseh predlog več kot <code>$wgMaxArticleSize</code>, zato nekaterih predlog nismo razširili.",
+       "post-expand-template-argument-category-desc": "Stran je večja od <code>$wgMaxArticleSize</code> po razširitvi argumentov predloge (nekaj v trojnih narekovajih, npr. <code>{{{Foo}}}</code>).",
        "expensive-parserfunction-category-desc": "Stran vsebuje preveč dragih razčlenitvenih funkcij (npr. <code>#ifexist</code>). Glejte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Kategorijo smo dodali, če stan vsebuje pokvarjeno povezavo na datoteko (povezavo na vključeno datoteko, ki ne obstaja).",
-       "hidden-category-category-desc": "To je kategorija s <code><nowiki>__HIDDENCAT__</nowiki></code>, kar ji preprečuje, da se po privzetem prikazuje v okvirju s povezavami na kategorije strani.",
+       "broken-file-category-desc": "Stran vsebuje pokvarjeno povezavo na datoteko (povezavo na vključeno datoteko, ki ne obstaja).",
+       "hidden-category-category-desc": "Kategorija vsebuje <code><nowiki>__HIDDENCAT__</nowiki></code> v vsebini strani, kar ji preprečuje, da se po privzetem prikazuje v okvirju s povezavami na kategorije strani.",
        "trackingcategories-nodesc": "Opis ni na voljo.",
        "trackingcategories-disabled": "Kategorija je onemogočena",
        "mailnologin": "Manjka naslov pošiljatelja",
        "mywatchlist": "Spisek nadzorov",
        "watchlistfor2": "Za $1 $2",
        "nowatchlist": "Vaš spisek nadzorov je prazen.",
-       "watchlistanontext": "Za pregled ali urejanje vsebine vašega spiska nadzorov se morate $1.",
+       "watchlistanontext": "Za pregled ali urejanje vsebine vašega spiska nadzorov se morate prijaviti.",
        "watchnologin": "Niste prijavljeni",
        "addwatch": "Dodaj na spisek nadzorov",
        "addedwatchtext": "Stran »[[:$1]]« smo dodali na vaš [[Special:Watchlist|spisek nadzorov]].\nTam bodo navedene prihodnje spremembe te strani in pripadajoče pogovorne strani.",
        "watchlist-details": "Na vašem spisku nadzorov je $1 {{PLURAL:$1|stran|strani|strani}}; pogovorne strani niso štete posebej.",
        "wlheader-enotif": "Obveščanje po elektronski pošti je omogočeno.",
        "wlheader-showupdated": "Strani, spremenjene od vašega zadnjega ogleda, so prikazane '''krepko'''.",
-       "wlnote2": "Spodaj so navedene spremembe v {{PLURAL:$1|zadnji uri|zadnjih <strong>$1</strong> urah}}, od $2, $3.",
+       "wlnote": "{{PLURAL:$1|Navedena je zadnja|Navedeni sta zadnji|Navedene so zadnje|Navedenih je zadnjih}} <strong>$1</strong> {{PLURAL:$1|sprememba|spremembi|spremembe|sprememb}} v {{PLURAL:$2|zadnji <strong>$2</strong> uri|zadnjih <strong>$2</strong> urah}}, od $3, $4.",
        "wlshowlast": "Prikaži zadnjih $1 ur; $2 dni; $3;",
        "watchlist-options": "Možnosti spiska nadzorov",
        "watching": "Nadziranje ...",
        "exbeforeblank": "vsebina pred brisanjem: '$1'",
        "delete-confirm": "Brisanje »$1«",
        "delete-legend": "Izbriši",
-       "historywarning": "'''Opozorilo:''' Stran, ki jo želite izbrisati, ima zgodovino s približno $1 {{PLURAL:$1|redakcijo|redakcijama|redakcijami}}:",
+       "historywarning": "<strong>Opozorilo:</strong> Stran, ki jo nameravate izbrisati, ima zgodovino s približno $1 {{PLURAL:$1|redakcijo|redakcijama|redakcijami}}:",
        "confirmdeletetext": "Iz zbirke podatkov boste izbrisali stran ali sliko skupaj z vso njeno zgodovino.\nProsimo, '''potrdite''', da to resnično želite, da razumete posledice dejanja in da se ravnate po [[{{MediaWiki:Policy-url}}|pravilih]].",
        "actioncomplete": "Poseg je končan",
        "actionfailed": "Dejanje spodletelo",
        "delete-edit-reasonlist": "Uredi razloge za brisanje",
        "delete-toobig": "Ta stran ima obsežno zgodovino urejanja, tj. čez $1 {{PLURAL:$1|redakcijo|redakciji|redakcije|redakcij}}.\nIzbris takšnih strani je bil omejen v izogib neželenim motnjam {{GRAMMAR:dative|{{SITENAME}}}}.",
        "delete-warning-toobig": "Ta stran ima obsežno zgodovino urejanja, tj. čez $1 {{PLURAL:$1|redakcijo|redakciji|redakcije|redakcij}}.\nNjeno brisanje lahko zmoti obratovanje zbirke podatkov {{GRAMMAR:dative|{{SITENAME}}}};\nnadaljujte s previdnostjo.",
+       "deleteprotected": "Strani ne morete izbrisati, ker jo je nekdo zaščitil.",
        "deleting-backlinks-warning": "'''Opozorilo:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Druge strani]] se povezujejo na ali vključujejo stran, ki jo nameravate izbrisati.",
        "rollback": "Vrni spremembe",
        "rollback_short": "Vrni",
        "autoblockid": "Samodejna blokada št. $1",
        "block": "Blokiraj uporabnika",
        "unblock": "Odblokiraj uporabnika",
-       "blockip": "Blokiranje IP-naslova ali uporabniškega imena",
+       "blockip": "Blokiraj {{GENDER:$1|uporabnika|uporabnico}}",
        "blockip-legend": "Blokiraj uporabnika",
        "blockiptext": "Naslednji obrazec vam omogoča, da določenemu IP-naslovu ali uporabniškemu imenu preprečite urejanje.\nTo storimo le zaradi zaščite pred nepotrebnim uničevanjem in po [[{{MediaWiki:Policy-url}}|pravilih]].\nVnesite tudi razlog (''na primer'' seznam strani, ki jih je uporabnik po nepotrebnem kvaril).",
        "ipaddressorusername": "IP-naslov ali uporabniško ime",
        "ipb-unblock-addr": "Deblokiraj $1",
        "ipb-unblock": "Odblokirajte uporabniško ime ali IP-naslov",
        "ipb-blocklist": "Ogled obstoječih blokad",
-       "ipb-blocklist-contribs": "Prispevki za $1",
+       "ipb-blocklist-contribs": "Prispevki za {{GENDER:$1|$1}}",
        "unblockip": "Deblokirajte uporabnika",
        "unblockiptext": "Z naslednjim obrazcem obnovite možnost urejanja z blokiranega IP-naslova ali uporabniškega računa.",
        "ipusubmit": "Odstrani blokado",
        "unblocked": "[[User:$1|$1]] je bil odblokiran",
        "unblocked-range": "$1 so odblokirani",
        "unblocked-id": "Blokada $1 je odstranjena",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] smo odblokirali.",
        "blocklist": "Blokirani uporabniki",
        "ipblocklist": "Blokirani uporabniki",
        "ipblocklist-legend": "Poišči blokiranega uporabnika",
        "import": "Uvoz strani",
        "importinterwiki": "Uvoz transwiki",
        "import-interwiki-text": "Izberite wiki in naslov strani za uvoz.\nDatumi in imena urejevalcev redakcij bodo ohranjena.\nVsi uvozi med wikiji so zabeleženi v [[Special:Log/import|dnevniku uvozov]].",
-       "import-interwiki-source": "Izvorni wiki/stran:",
+       "import-interwiki-sourcewiki": "Izvorni wiki:",
+       "import-interwiki-sourcepage": "Izvorna stran:",
        "import-interwiki-history": "Kopiraj vse dosedanje redakcije te strani",
        "import-interwiki-templates": "Vključi vse predloge",
        "import-interwiki-submit": "Uvozi",
        "import-upload": "Naložite podatke XML",
        "import-token-mismatch": "Izguba podatkov o seji.\nProsimo, poskusite znova.",
        "import-invalid-interwiki": "Uvoz iz navedenega wikija ni možen.",
-       "import-error-edit": "Stran »$1« ni uvožena, ker vam ni dovoljeno, da jo urejate.",
-       "import-error-create": "Stran »$1« ni uvožena, ker vam ni dovoljeno, da jo ustvarite.",
+       "import-error-edit": "Strani »$1« nismo uvozili, ker vam ni dovoljeno, da jo urejate.",
+       "import-error-create": "Strani »$1« nismo uvozili, ker vam ni dovoljeno, da jo ustvarite.",
        "import-error-interwiki": "Strani »$1« nismo uvozili, ker je njeno ime rezervirano za zunanje povezovanje (interwiki).",
        "import-error-special": "Strani »$1« nismo uvozili, ker spada k posebnemu imenskemu prostoru, ki ne dovoljuje strani.",
-       "import-error-invalid": "Strani »$1« nismo uvozili, ker njeno ime ni veljavno.",
+       "import-error-invalid": "Strani »$1« nismo uvozili, ker ime, na katerega bi jo uvozili, na tem wikiju ni veljavno.",
        "import-error-unserialize": "Redakcije $2 strani »$1« ni bilo mogoče deserializirati. Redakcija bi naj uporabljala model vsebine $3, serializiran kot $4.",
        "import-error-bad-location": "Redakcije $2, ki uporablja model vsebine $3, na tem wikiju ne morete straniti na »$1«, saj omenjeni model ni podprt na tej strani.",
        "import-options-wrong": "{{PLURAL:$2|Napačna možnost|Napačni možnosti|Napačne možnosti}}: <nowiki>$1</nowiki>",
        "importlogpage": "Dnevnik uvozov",
        "importlogpagetext": "Administrativni uvozi strani z zgodovino urejanja iz drugih wikijev.",
        "import-logentry-upload": "uvozil [[$1]] z nalaganjem datoteke",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|redakcija|redakciji|redakcije|redakcij|redakcij}}",
+       "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": "prenesel $1 med wikiji",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|redakcija|redakciji|redakcije|redakcij}} uporabnika $2",
+       "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-title": "Poganjanje $1 preizkusov",
        "javascripttest-pagetext-noframework": "Stran je rezervirana za poganjanje preizkusov JavaScript.",
        "autosumm-replace": "Zamenjava strani s/z '$1'",
        "autoredircomment": "preusmeritev na [[$1]]",
        "autosumm-new": "Nova stran z vsebino: $1",
+       "autosumm-newblank": "Ustvarjena prazna stran",
        "lag-warn-normal": "Spremembe novejše od $1 {{PLURAL:$1|sekunde|sekund}} morda ne bodo prikazane na seznamu.",
        "lag-warn-high": "Zaradi visoke zasedenosti strežniških podatkovnih baz, spremembe novejše od $1 {{PLURAL:$1|sekunde|sekund}} morda ne bodo prikazane na seznamu.",
        "watchlistedit-normal-title": "Uredi spisek nadzorov",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|pogovor]])",
        "unknown_extension_tag": "Neznana razširitvena etiketa »$1«",
        "duplicate-defaultsort": "'''Opozorilo:''' Privzeti ključ razvrščanja »$2« prepiše prejšnji privzeti ključ razvrščanja »$1«.",
+       "duplicate-displaytitle": "<strong>Opozorilo:</strong> Prikazni naslov »$2« prepiše prejšnji prikazni naslov »$1«.",
        "version": "Različica",
        "version-extensions": "Nameščene razširitve",
        "version-skins": "Nameščene kože",
        "logentry-rights-rights": "$1 je {{GENDER:$2|spremenil|spremenila|spremenil(-a)}} uporabniške pravice uporabnika $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",
+       "logentry-upload-overwrite": "$1 je {{GENDER:$2|naložil|naložila|naložil(-a)}} novo različico $3",
+       "logentry-upload-revert": "$1 je {{GENDER:$2|naložil|naložila|naložil(-a)}} $3",
        "rightsnone": "(nobeno)",
        "feedback-bugornote": "Če ste pripravljeni podrobno opisati tehnično težavo, vložite [$1 poročilo o hrošču].\nV nasprotnem primeru lahko uporabite preprost obrazec spodaj. Vašo pripombo bomo dodali na stran »[$3 $2]«, skupaj z vašim uporabniškim imenom in podatkom o brskalniku, ki ga uporabljate.",
        "feedback-subject": "Zadeva:",
        "action-pagelang": "spreminjanje jezika strani",
        "log-name-pagelang": "Dnevnik spreminjanja jezika",
        "log-description-pagelang": "Dnevnik sprememb jezika strani.",
-       "logentry-pagelang-pagelang": "$1 je {{GENDER:$2|spremenil|spremenila|spremenil(-a)}} jezik strani $3 z jezika $4 na jezik $5."
+       "logentry-pagelang-pagelang": "$1 je {{GENDER:$2|spremenil|spremenila|spremenil(-a)}} jezik strani $3 z jezika $4 na jezik $5.",
+       "default-skin-not-found": "Ups! Privzeta koža vašega wikija, določena v <code dir=\"ltr\">$wgDefaultSkin</code> kot <code>$1</code>, ni na voljo.\n\nKot kaže, vaša namestitev vsebuje kože, navedene spodaj. Oglejte si [https://www.mediawiki.org/wiki/Manual:Skin_configuration Priročnik: Konfiguracija kož] za več informacij, kako jih omogočiti in nastaviti kot privzete.\n\n$2\n\n; Če ste MediaWiki pravkar namestili:\n: Verjetno ste ga namestili z git ali neposredno iz izvorne kode na kakšen drug način. To je pričakovano. Poskusite namestiti nekaj kož z [https://www.mediawiki.org/wiki/Category:All_skins imenika kož mediawiki.org] tako:\n:* Prenesite [https://www.mediawiki.org/wiki/Download namestitveni program tarball], ki vsebuje nekaj kož in razširitev. Iz njega lahko kopirate in prilepite mapo <code>skins/</code>.\n:* Klonirajte enega od repozitorijev <code>mediawiki/skins/*</code> z git v mapo <code dir=\"ltr\">skins/</code> vaše namestitve MediaWiki.\n: Če ste razvijalec MediaWiki, to ne sme poseči v vaš repozitorij git.\n\n; Če ste MediaWiki pravkar posodobili:\n: MediaWiki 1.24 in novejši nameščenih kož več ne omogočijo samodejno (oglejte si [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Priročnik: Samodejno odkrivanje kož]). V <code>LocalSettings.php</code> lahko prilepite naslednje vrstice, da omogočite trenutno nameščene kože:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Če ste pravkar spremenili <code>LocalSettings.php</code>:\n: Ponovno preverite imena kož, če ste se morda zatipkali.",
+       "default-skin-not-found-no-skins": "Ups! Privzeta koža vašega wikija, določena v <code dir=\"ltr\">$wgDefaultSkin</code> kot <code>$1</code>, ni na voljo.\n\nNimate nameščenih kož.\n\n; Če ste MediaWiki pravkar namestili ali posodobili:\n: Verjetno ste ga namestili z git ali neposredno iz izvorne kode na kakšen drug način. To je pričakovano. MediaWiki 1.24 in novejši nimajo vključene nobene kože v glavnem repozitoriju. Poskusite namestiti nekaj kož z [https://www.mediawiki.org/wiki/Category:All_skins imenika kož mediawiki.org] tako:\n:* Prenesite [https://www.mediawiki.org/wiki/Download namestitveni program tarball], ki vsebuje nekaj kož in razširitev. Iz njega lahko kopirate in prilepite mapo <code dir=\"ltr\">skins/</code>.\n:* Klonirajte enega od repozitorijev <code>mediawiki/skins/*</code> z git v mapo <code>skins/</code> vaše namestitve MediaWiki.\n: Če ste razvijalec MediaWiki, to ne sme poseči v vaš repozitorij git. Oglejte si [https://www.mediawiki.org/wiki/Manual:Skin_configuration Priročnik: Konfiguracija kož] za več informacij, kako jih omogočiti in nastaviti kot privzete.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (omogočeno)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''onemogočeno''')"
 }
index 28e64ee..3c0729d 100644 (file)
        "talkpagelinktext": "Dischkur",
        "specialpage": "Spezialseyte",
        "personaltools": "Meine Werkzeuge",
-       "postcomment": "Neuer Obschnitt",
        "articlepage": "Inhaltsseite oazeiga",
        "talk": "Dischkur",
        "views": "Oansichta",
        "externaldberror": "Entweder is leit a Fahler bei der externa Authentifizierung vur, oder du darfst dei externes Benutzerkonto ne aktualisiera.",
        "login": "Oanmelda",
        "nav-login-createaccount": "Oamelda / a Konto oalega",
-       "loginprompt": "Zer Oameldung missa Cookies aktiviert sei.",
        "userlogin": "Oanmelda / Nutzerkonto erstella",
        "logout": "Oabmelda",
        "userlogout": "Oabmelda",
        "file-thumbnail-no": "Dar Dateinoame beginnt miet <strong>$1</strong>. Dies deutet uff a Bild verringerter Griße ''(thumbnail)'' hin.\nBitte priefe, ob du doas Bild ei voller Ufflesung vorliegen host und loade dieses under damm Originalnoama huch.",
        "file-exists-duplicate": "Diese Datei ies a Duplikat dar fulgenda {{PLURAL:$1|Datei|$1 Dateien}}:",
        "file-deleted-duplicate": "Anne identische Datei dieser Datei ([[:$1]]) wurde frieher geläscht. Ieberpriefe doas Läsch-Logbuch, bevor du se huchlädst.",
-       "uploadedimage": "hoot „[[$1]]“ huchgeloada",
-       "overwroteimage": "hoot anne neue Version vu „[[$1]]“ huchgeloada",
        "uploaddisabled": "Huchlada deaktiviert",
        "uploaddisabledtext": "Doas Huchloada vu Dateien ies deaktiviert.",
        "uploadscripted": "Diese Datei enthält HTML- oder Scriptcode, dar irrtiemlich vu a'm Webbrowser ausgefiehrt waan kennte.",
        "watchlist-details": "Du beobachtest {{PLURAL:$1|1 Seite|$1 Seita}}.",
        "wlheader-enotif": "Dar E-Mail-Benoachrichtigungsdienst ies aktiviert.",
        "wlheader-showupdated": "Seyta miet noo ne gesehenen Änderunga waan '''fett''' dargestellt.",
+       "wlnote": "Is {{PLURAL:$1|folgt de letzte Änderung|folga de letzta '''$1''' Änderunga}} dar letzta {{PLURAL:$2|Stunde|'''$2''' Stunda}}.",
        "wlshowlast": "Zeige de Änneronga dar letzta $1 Stonda, $2 Taage oder $3.",
        "watchlist-options": "Oazeegeoptiona",
        "watching": "Beobachta …",
index aaa8f1a..7587cea 100644 (file)
        "talkpagelinktext": "Wadahadal",
        "specialpage": "Bogaga qaaska ah",
        "personaltools": "Qalabkaaga",
-       "postcomment": "Maqaal cusub",
        "articlepage": "Fiiri bogga qoraalka",
        "talk": "Wadahadal",
        "views": "Muuqaalka",
        "password-change-forbidden": "Ma badali kartid Eraysir ee wiki.",
        "login": "Gudaha gal",
        "nav-login-createaccount": "Gudaha gal / sameyso akoon",
-       "loginprompt": "Waa in aad shidaa cookies'ka hadii aad rabto in aad soo gasho {{SITENAME}}.",
        "userlogin": "Gudaha gal / sameyso akoon",
        "userloginnocreate": "Gudaha gal",
        "logout": "Ka bax",
        "large-file": "waxaa loo baahanyahay in ay san file'yada ka weynaan $1;\nfile'kaan waa  $2.",
        "uploadwarning": "Digniin waxa aad soo gelineesid",
        "savefile": "Faylka kaydi",
-       "uploadedimage": "la soo galiyay \"[[$1]]\"",
-       "overwroteimage": "waxaa la soo galiyay nuuc cusub oo ah \"[[$1]]\"",
        "uploaddisabled": "wax soo gelinta waa la xiray.",
        "copyuploaddisabled": "wax soo gelinta dhinaca URL:ka waa la xiray",
        "uploaddisabledtext": "soo gelinta faylyada waa la xiray",
index 7aa4ea6..cda9eba 100644 (file)
@@ -24,7 +24,9 @@
                        "Urhixidur",
                        "Vinie007",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Gertakapllani",
+                       "OrvenBregu"
                ]
        },
        "tog-underline": "Nënvizo lidhjet:",
        "talkpagelinktext": "Diskuto",
        "specialpage": "Faqe speciale",
        "personaltools": "Mjetet e mia",
-       "postcomment": "Seksion i ri",
        "articlepage": "Shiko faqen me përmbajtje",
        "talk": "Diskutimet",
        "views": "Shikime",
        "externaldberror": "Ose kishte një gabim tek regjistri i identifikimit të jashtëm, ose nuk ju lejohet të përtërini llogarinë tuaje të jashtme.",
        "login": "Hyni",
        "nav-login-createaccount": "Hyni ose hapni një llogari",
-       "loginprompt": "Ju duhet të mundësoni lejimin e \"cookies\" për të hyrë brënda në {{SITENAME}}.",
        "userlogin": "Hyni / hapni llogari",
        "userloginnocreate": "Hyni",
        "logout": "Dalje",
        "edit-gone-missing": "Faqja nuk mund t freskohet.\nDuket se është grisur.",
        "edit-conflict": "Konflikt në redaktim.",
        "edit-no-change": "Redaktimi juaj është anashkaluar pasi që asnjë ndryshim nuk u bë në tekst.",
+       "postedit-confirmation-created": "Faqja eshte krijuar",
+       "postedit-confirmation-restored": "Faqja eshte kthyer",
+       "postedit-confirmation-saved": "Redaktimi juaj eshte ruajtur.",
        "edit-already-exists": "Faqja nuk mundej të hapet.\nAjo tanimë ekziston.",
        "defaultmessagetext": "Teksti i porosisë së parazgjedhur",
-       "editwarning-warning": "Lënia e kësaj faqeje mund t'ju shkaktojë humbjen e çdo ndryshimi që keni bërë.\nNëse keni hyrë brenda, ju mund ta hiqni këtë paralajmërim në seksionin \"Redaktimi\" tek preferencat tuaja.",
+       "invalid-content-data": "Të pavlefshme të dhënave e përmbajtjes",
+       "editwarning-warning": "Duke e lënë këtë faqe mund të shkaktojë ju për të humbur të gjitha ndryshimet që keni bërë ju.\nNëse ju jeni regjistruar, ju mund të çaktivizoni këtë paralajmërim në \"{{int:prefs-editing}}\" seksionin e preferencave tuaja.",
        "content-model-text": "tekst i thejshtë",
        "expensive-parserfunction-warning": "Kujdes: Kjo faqe ka shumë kërkesa që kërkojnë analizë gramatikore të kushtueshme për sistemin.\n\nDuhet të ketë më pakë se $2, {{PLURAL:$2|kërkesë|kërkesa}}, kurse tani {{PLURAL:$1|është $1 kërkesë|janë $1 kërkesa}}.",
        "expensive-parserfunction-category": "Faqe me shumë shprehje të kushtueshmë për analizë gramatikore",
        "searchprofile-advanced-tooltip": "Kërkimi në hapësina",
        "search-result-size": "$1 ({{PLURAL:$2|1 fjalë|$2 fjalë}})",
        "search-result-category-size": "{{PLURAL:$1|1 anëtar|$1 anëtarë}} ({{PLURAL:$2|1 nën-kategori|$2 nën-kategori}}, {{PLURAL:$3|1 skedë|$3 skeda}})",
-       "search-result-score": "Përkatësia: $1%",
        "search-redirect": "(përcjellim $1)",
        "search-section": "(seksioni $1)",
        "search-suggest": "Mos kishit në mendje: $1",
        "uploadwarning": "Kujdes dhënie",
        "uploadwarning-text": "Ju lutemi modifikoni përshkrimin e skedës dhe provojen përsëri.",
        "savefile": "Ruaj skedën",
-       "uploadedimage": "dha \"[[$1]]\"",
-       "overwroteimage": "dha dhe zëvendësoi me një version të ri të \"[[$1]]\"",
        "uploaddisabled": "Ndjesë, dhëniet janë bllokuar në këtë shërbyes dhe nuk është gabimi juaj.",
        "copyuploaddisabled": "Ngarkimi nga URL-ja u çaktivizua.",
        "uploaddisabledtext": "Ngarkimi i skedave është i ndaluar.",
        "license-nopreview": "(Nuk ka parapamje)",
        "upload_source_url": " (URL e vlefshme, publikisht e përdorshme)",
        "upload_source_file": " (skeda në kompjuterin tuaj)",
+       "listfiles-delete": "fshije",
        "listfiles-summary": "Kjo faqe speciale tregon tërë skedat e ngarkuara.\nFillimisht skedat e ngarkuara së fundmi jepen më sipër.\nShtypni kolonat e tjera për të ndryshuar radhitjen.",
        "listfiles_search_for": "Kërko për emrin e figurës:",
        "imgfile": "skeda",
        "watchlist-details": "{{PLURAL:$1|$1 faqe|$1 faqe}} nën mbikqyrje duke mos numëruar faqet e diskutimit.",
        "wlheader-enotif": "Njoftimi me email është lejuar.",
        "wlheader-showupdated": "Faqet që kanë ndryshuar nga vizita juaj e fundit do të tregohen të '''trasha'''",
+       "wlnote": "Më poshtë {{PLURAL:$1|është ndryshimi i fundit|janë '''$1''' ndryshimet e fundit}} në {{PLUARAL:$2:orën e fundit|'''$2''' orët e fundit}}, që nga $3, $4.",
        "wlshowlast": "Trego $1 orët $2 ditët $3",
        "watchlist-options": "Mundësitë e listës mbikqyrëse",
        "watching": "Duke mbikqyrur...",
index 980ea1a..66bff6d 100644 (file)
@@ -24,7 +24,8 @@
                        "Милан Јелисавчић",
                        "Михајло Анђелковић",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Подвлачење веза:",
@@ -41,6 +42,7 @@
        "tog-watchdefault": "Додај странице и датотеке које изменим у списак надгледања",
        "tog-watchmoves": "Додај странице и датотеке које преместим у списак надгледања",
        "tog-watchdeletion": "Додај странице и датотеке које обришем у списак надгледања",
+       "tog-watchrollback": "Додај странице на којима сам вратио измене у списак надгледања",
        "tog-minordefault": "Означавај све измене као мање",
        "tog-previewontop": "Прикажи преглед пре оквира за уређивање",
        "tog-previewonfirst": "Прикажи преглед на првој измени",
        "category-empty": "<div style=\"margin:2em 1em 0 1em; padding:0.5em; border:1px solid #AAA; text-align:center;\">''Ова категорија тренутно не садржи странице или датотеке.''</div>",
        "hidden-categories": "{{PLURAL:$1|Сакривена категорија|Сакривене категорије}}",
        "hidden-category-category": "Сакривене категорије",
-       "category-subcat-count": "{{PLURAL:$2|Ова категорија садржи само следећу поткатегорију.|Ова категорија има {{PLURAL:$1|следећу поткатегорију|следеће $1 поткатегорије|следећих $1 поткатегорија}}, од укупно $2.}}",
+       "category-subcat-count": "{{PLURAL:$2|1=Ова категорија садржи само следећу поткатегорију.|Ова категорија има {{PLURAL:$1|1=следећу поткатегорију|следеће $1 поткатегорије|следећих $1 поткатегорија}}, од укупно $2.}}",
        "category-subcat-count-limited": "Ова категорија садржи {{PLURAL:$1|следећу поткатегорију|следеће $1 поткатегорије|следећих $1 поткатегорија}}.",
-       "category-article-count": "{{PLURAL:$2|Ова категорија садржи само следећу страницу.|{{PLURAL:$1|Следећа страница је|Следеће $1 странице су|Следећих $1 страница је}} у овој категорији, од укупно $2.}}",
-       "category-article-count-limited": "{{PLURAL:$1|Следећа страница је|Следеће $1 странице су|Следећих $1 страница је}} у овој категорији.",
-       "category-file-count": "{{PLURAL:$2|Ова категорија садржи само следећу датотеку.|{{PLURAL:$1|Следећа датотека је|Следеће $1 датотеке су|Следећих $1 датотека је}} у овој категорији, од укупно $2.}}",
-       "category-file-count-limited": "{{PLURAL:$1|Следећа датотека је|Следеће $1 датотеке су|Следећих $1 датотека је}} у овој категорији.",
+       "category-article-count": "{{PLURAL:$2|1=Ова категорија садржи само следећу страницу.|{{PLURAL:$1|Следећа страница је|Следеће $1 странице су|Следећих $1 страница је}} у овој категорији, од укупно $2.}}",
+       "category-article-count-limited": "{{PLURAL:$1|1=Следећа страница је|Следеће $1 странице су|Следећих $1 страница је}} у овој категорији.",
+       "category-file-count": "{{PLURAL:$2|1=Ова категорија садржи само следећу датотеку.|{{PLURAL:$1|1=Следећа датотека је|Следеће $1 датотеке су|Следећих $1 датотека је}} у овој категорији, од укупно $2.}}",
+       "category-file-count-limited": "{{PLURAL:$1|1=Следећа датотека је|Следеће $1 датотеке су|Следећих $1 датотека је}} у овој категорији.",
        "listingcontinuesabbrev": "наст.",
        "index-category": "Пописане странице",
        "noindex-category": "Непописане странице",
        "delete": "Обриши",
        "deletethispage": "Обриши ову страницу",
        "undeletethispage": "Врати ову страницу",
-       "undelete_short": "Врати {{PLURAL:$1|једну обрисану измену|$1 обрисане измене|$1 обрисаних измена}}",
+       "undelete_short": "Врати {{PLURAL:$1|1=једну обрисану измену|$1 обрисане измене|$1 обрисаних измена}}",
        "viewdeleted_short": "Погледај {{PLURAL:$1|обрисану измену|$1 обрисане измене|$1 обрисаних измена}}",
        "protect": "Заштити",
        "protect_change": "промени",
        "talkpagelinktext": "разговор",
        "specialpage": "Посебна страница",
        "personaltools": "Личне алатке",
-       "postcomment": "Нови одељак",
        "articlepage": "Погледај страницу са садржајем",
        "talk": "Разговор",
        "views": "Прегледи",
        "otherlanguages": "Други језици",
        "redirectedfrom": "(преусмерено са $1)",
        "redirectpagesub": "Преусмерење",
+       "redirectto": "Преусмерава на:",
        "lastmodifiedat": "Ова страница је последњи пут измењена $1 у $2.",
        "viewcount": "Ова страница је прегледана {{PLURAL:$1|једанпут|$1 пута|$1 пута}}.",
        "protectedpage": "Заштићена страница",
        "hidetoc": "сакриј",
        "collapsible-collapse": "скупи",
        "collapsible-expand": "прошири",
+       "confirmable-confirm": "Да ли {{GENDER:$1|сте}} сигурни?",
+       "confirmable-yes": "Да",
+       "confirmable-no": "Не",
        "thisisdeleted": "Погледати или вратити $1?",
        "viewdeleted": "Погледати $1?",
        "restorelink": "{{PLURAL:$1|обрисану измену|$1 обрисане измене|$1 обрисаних измена}}",
        "viewsourcetext": "Можете читати и копирати садржај ове странице:",
        "viewyourtext": "Можете да погледате и копирате извор '''ваших измена''' на овој страници:",
        "protectedinterface": "Ова страница садржи текст корисничког окружења за софтвер на овом викију и заштићена је ради спречавања злоупотребе.\nДа бисте додали или изменили преводе свих викија, посетите [//translatewiki.net/ Транслејтвики], пројекат за локализацију Медијавикија.",
-       "editinginterface": "'''Упозорење:''' уређујете страницу која се користи за приказивање текста корисничког окружења.\nИзмене на овој страници ће утицати на све кориснике овог викија.\nДа бисте додали или изменили преводе свих викија, посетите [//translatewiki.net/wiki/Main_Page?setlang=sr_ec Транслејтвики], пројекат за локализацију Медијавикија.",
+       "editinginterface": "<strong>Упозорење:</strong> уређујете страницу која се користи за приказивање текста корисничког окружења.\nИзмене на овој страници ће утицати на све кориснике овог викија.\nДа бисте додали или изменили преводе свих викија, посетите [//translatewiki.net/ Транслејтвики], пројекат за локализацију Медијавикија.",
        "cascadeprotected": "Ова страница је закључана јер садржи {{PLURAL:$1|следећу страницу која је заштићена|следеће странице које су заштићене}} „преносивом“ заштитом:\n$2",
        "namespaceprotected": "Немате дозволу да уређујете странице у именском простору '''$1'''.",
        "customcssprotected": "Немате дозволу да мењате ову CSS страницу јер садржи личне поставке другог корисника.",
        "externaldberror": "Дошло је до грешке при препознавању базе података или немате овлашћења да ажурирате свој спољни налог.",
        "login": "Пријави ме",
        "nav-login-createaccount": "Пријава/регистрација",
-       "loginprompt": "Омогућите колачиће да бисте се пријавили на овај вики.",
        "userlogin": "Пријава/регистрација",
        "userloginnocreate": "Пријава",
        "logout": "Одјава",
        "userlogin-resetlink": "Заборавили сте податке за пријаву?",
        "userlogin-resetpassword-link": "Заборавили сте лозинку?",
        "userlogin-helplink2": "Помоћ при пријављивању",
-       "userlogin-loggedin": "Већ сте пријављени као {{GENDER:$1|$1}}.\nКористите доњи образац да бисте се пријавили као други корисник.",
-       "userlogin-createanother": "Отвори још један налог",
        "createacct-emailrequired": "Адреса е-поште",
        "createacct-emailoptional": "Адреса е-поште (опционо)",
        "createacct-email-ph": "Унесите вашу адресу е-поште",
        "createacct-another-submit": "Отвори још један налог",
        "createacct-benefit-heading": "{{SITENAME}} је направљен од стране људи као што сте ви.",
        "createacct-benefit-body1": "{{PLURAL:$1|измена}}",
-       "createacct-benefit-body2": "{{PLURAL:$1|страница}}",
+       "createacct-benefit-body2": "{{PLURAL:$1|страница|странице}}",
        "createacct-benefit-body3": "скорашњих {{PLURAL:$1|доприноса}}",
        "badretype": "Унете лозинке се не поклапају.",
        "userexists": "Корисничко име је заузето. Изаберите друго.",
        "loginerror": "Грешка при пријављивању",
-       "createacct-error": "Ð\94оÑ\88ло Ñ\98е Ð´Ð¾ Ð³Ñ\80еÑ\88ке Ð¿Ñ\80и ÐºÑ\80еирању налога",
+       "createacct-error": "Ð\94оÑ\88ло Ñ\98е Ð´Ð¾ Ð³Ñ\80еÑ\88ке Ð¿Ñ\80и Ð¾Ñ\82варању налога",
        "createaccounterror": "Не могу да отворим налог: $1",
-       "nocookiesnew": "Кориснички налог је отворен, али нисте пријављени.\nОвај вики користи колачиће за пријаву. Вама су колачићи онемогућени.\nОмогућите их, па се онда пријавите са својим корисничким именом и лозинком.",
-       "nocookieslogin": "Овај вики користи колачиће за пријављивање корисника.\nВама су колачићи онемогућени. Омогућите их и покушајте поново.",
+       "nocookiesnew": "Кориснички налог је отворен, али нисте пријављени.\n{{SITENAME}} користи колачиће за пријаву. Вама су колачићи онемогућени.\nОмогућите их, па се онда пријавите са својим корисничким именом и лозинком.",
+       "nocookieslogin": "{{SITENAME}} користи колачиће за пријављивање корисника.\nВама су колачићи онемогућени. Омогућите их и покушајте поново.",
        "nocookiesfornew": "Кориснички налог није отворен јер његов извор није потврђен.\nОмогућите колачиће на прегледачу и поново учитајте страницу.",
        "nocookiesforlogin": "{{int:nocookieslogin}}",
        "noname": "Унели сте неисправно корисничко име.",
        "password-name-match": "Лозинка се мора разликовати од корисничког имена.",
        "password-login-forbidden": "Коришћење овог корисничког имена и лозинке је забрањено.",
        "mailmypassword": "Ресетуј лозинку",
-       "passwordremindertitle": "{{SITENAME}} â\80\93 Ð¿Ð¾Ð´Ñ\81еÑ\82ник Ð·Ð° Ð»Ð¾Ð·Ð¸Ð½ÐºÑ\83",
+       "passwordremindertitle": "{{SITENAME}} â\80\94 Ð¿Ñ\80ивÑ\80емена Ð»Ð¾Ð·Ð¸Ð½ÐºÐ°",
        "passwordremindertext": "Неко, вероватно ви, са ИП адресе $1 је затражио нову лозинку на викију {{SITENAME}} ($4).\nСтворена је привремена лозинка за {{GENDER:$2|корисника|корисницу|корисника}} $2 која гласи $3.\nУколико је ово ваш захтев, сада се пријавите и поставите нову лозинку.\nПривремена лозинка истиче за {{PLURAL:$5|један дан|$5 дана|$5 дана}}.\n\nАко је неко други затражио промену лозинке, или сте се сетили ваше лозинке и не желите да је мењате, занемарите ову поруку.",
-       "noemail": "Не постоји е-адреса за {{GENDER:$1|корисника|корисницу|корисника}} $1.",
+       "noemail": "Не постоји е-адреса за {{GENDER:$1|корисника|корисницу}} $1.",
        "noemailcreate": "Морате навести исправну е-адресу",
        "passwordsent": "Нова лозинка је послата на е-адресу {{GENDER:$1|корисника|кориснице|корисника}} $1.\nПријавите се пошто је примите.",
        "blocked-mailpassword": "Вашој ИП адреси је онемогућено уређивање страница, као и могућност захтевања нове лозинке.",
        "eauthentsent": "На наведену е-адресу је послат потврдни код.\nПре него што пошаљемо даљње поруке, пратите упутства с е-поште да бисте потврдили да сте ви отворили налог.",
        "throttled-mailpassword": "Порука за промену лозинке је послата у {{PLURAL:$1|последњих сат времена|последња $1 сата|последњих $1 сати}}.\nДа бисмо спречили злоупотребу, подсетник шаљемо само једном у року од {{PLURAL:$1|сат времена|$1 сата|$1 сати}}.",
        "mailerror": "Грешка при слању поруке: $1",
-       "acct_creation_throttle_hit": "Посетиоци овог викија који користе вашу ИП адресу су већ отворили {{PLURAL:$1|један налог|$1 налога|$1 налога}} претходни дан, што је највећи дозвољени број у том временском периоду.\nЗбог тога посетиоци с ове ИП адресе тренутно не могу отворити више налога.",
+       "acct_creation_throttle_hit": "Посетиоци овог викија који користе вашу ИП адресу су већ отворили {{PLURAL:$1|1=један налог|$1 налога|$1 налога}} претходни дан, што је највећи дозвољени број у том временском периоду.\nЗбог тога посетиоци с ове ИП адресе тренутно не могу отворити више налога.",
        "emailauthenticated": "Ваша е-адреса је потврђена $2 у $3.",
        "emailnotauthenticated": "Ваша е-адреса још није потврђена.\nПоруке неће бити послате ни у једном од следећих случајева.",
        "noemailprefs": "Унесите е-адресу како би ове могућности радиле.",
        "preview": "Претпреглед",
        "showpreview": "Прикажи претпреглед",
        "showdiff": "Прикажи измене",
-       "anoneditwarning": "'''Упозорење:''' нисте пријављени.\nВаша ИП адреса ће бити забележена у историји ове странице.",
+       "blankarticle": "<strong>Упозорење:</strong> страница коју правите нема никакав садржај.\nАко још једном притиснете „{{int:savearticle}}“ направићете страницу без садржаја.",
+       "anoneditwarning": "<strong>Упозорење:</strong> нисте пријављени. Ваша ИП адреса ће бити јавно видљива у историји ове странице ако начините било какву измену. Ако се <strong>[$1 пријавите]</strong> или <strong>[$2 отворите налог]</strong> ваше измене ће бити приписане вашем корисничком имену.",
        "anonpreviewwarning": "''Нисте пријављени. Ваша ИП адреса ће бити забележена у историји ове странице.''",
        "missingsummary": "'''Напомена:''' нисте унели опис измене.\nАко поново кликнете на „{{int:savearticle}}“, ваша измена ће бити сачувана без описа.",
        "missingcommenttext": "Унесите коментар испод.",
        "subject-preview": "Преглед теме/наслова:",
        "blockedtitle": "Корисник је блокиран",
        "blockedtext": "<strong>Ваше корисничко име или ИП адреса је блокирана.</strong>\n\nБлокирање је {{GENDER:$4|извршио|извршила}} $1.\nРазлог: <em>$2</em>.\n\n* Датум блокирања: $8\n* Блокирање истиче: $6\n* Име корисника: $7\n\nОбратите се {{GENDER:$4|кориснику|корисници}} $1 или [[{{MediaWiki:Grouppage-sysop}}|администратору]] да разјасните ствар.\nНе можете користити могућност „Пошаљи поруку овом кориснику“ ако нисте унели исправну е-адресу у [[Special:Preferences|подешавањима]].\nВаша блокирана ИП адреса је $3, а ID блокирања $5.\nНаведите све податке изнад при стварања било каквих упита.",
-       "autoblockedtext": "Ваша ИП адреса је блокирана јер ју је употребљавао други корисник, кога је {{GENDER:$1|блокирао|блокирала|блокирао}} $1.\nРазлог:\n\n:''$2''\n\n* Датум блокирања: $8\n* Блокирање истиче: $6\n* Име корисника: $7\n\nОбратите се {{GENDER:$1|кориснику|корисници|кориснику}} $1 или [[{{MediaWiki:Grouppage-sysop}}|администратору]] да разјасните ствар.\n\nНе можете користити могућност „Пошаљи поруку овом кориснику“ ако нисте унели исправну е-адресу у [[Special:Preferences|подешавањима]].\n\nВаша блокирана ИП адреса је $3, а ИБ $5.\nНаведите све податке изнад при стварању било каквих упита.",
+       "autoblockedtext": "Ваша ИП адреса је блокирана јер ју је употребљавао други корисник, кога је {{GENDER:$4|блокирао|блокирала}} $1.\nРазлог:\n\n:<em>$2</em>\n\n* Датум блокирања: $8\n* Блокирање истиче: $6\n* Име корисника: $7\n\nОбратите се {{GENDER:$4|кориснику|корисници}} $1 или [[{{MediaWiki:Grouppage-sysop}}|администратору]] да разјасните ствар.\n\nНе можете користити могућност „Пошаљи поруку овом кориснику“ ако нисте унели исправну е-адресу у [[Special:Preferences|подешавањима]].\n\nВаша блокирана ИП адреса је $3, а ID $5.\nНаведите све податке изнад при стварању било каквих упита.",
        "blockednoreason": "разлог није наведен",
        "whitelistedittext": "За уређивање странице је потребно да будете $1.",
        "confirmedittext": "Морате да потврдите своју е-адресу пре уређивања страница.\nПоставите и потврдите адресу преко [[Special:Preferences|подешавања]].",
        "undo-failure": "Ова измена се не може поништити због сукоба измена.",
        "undo-norev": "Не могу да вратим измену јер не постоји или је обрисана.",
        "undo-nochange": "Изгледа да је измена већ поништена.",
-       "undo-summary": "Поништена измена $1 {{GENDER:$2|корисника|кориснице}} [[Special:Contributions/$2|$2]] ([[User talk:$2|разговор]])",
+       "undo-summary": "Поништена измена $1 {{GENDER:$2|корисника|кориснице}} [[Special:Contribs/$2|$2]] ([[User talk:$2|разговор]])",
        "undo-summary-username-hidden": "Поништи измену $1 скривеног корисника",
        "cantcreateaccounttitle": "Не могу да отворим налог",
-       "cantcreateaccount-text": "Отварање налога с ове IP адресе ('''$1''') је {{GENDER:$3|блокирао|блокирала|блокирао}} [[User:$3|$3]].\n\nРазлог који је навео {{GENDER:$3|корисник|корисница|корисник}} $3 је ''$2''",
+       "cantcreateaccount-text": "Отварање налога с ове IP адресе (<strong>$1</strong>) је блокирао/ла [[User:$3|$3]].\n\nРазлог који је навео/ла $3 је <em>$2</em>",
+       "cantcreateaccount-range-text": "Отварање налога са IP адреса у распону '''$1''', који укључује и вашу IP адресу ('''$4''') је блокирао/ла [[User:$3|$3]].\n\nРазлог који је навео/ла $3 је <em>$2</em>",
        "viewpagelogs": "Погледај дневнике ове странице",
        "nohistory": "Не постоји историја измена ове странице.",
        "currentrev": "Текућа измена",
        "revdelete-reasonotherlist": "Други разлог",
        "revdelete-edit-reasonlist": "Уреди разлоге за брисање",
        "revdelete-offender": "Аутор измене:",
-       "suppressionlog": "Ð\98Ñ\81Ñ\82оÑ\80иÑ\98а сакривања",
+       "suppressionlog": "Ð\94невник сакривања",
        "suppressionlogtext": "Испод се налази списак брисања и блокирања који укључује садржај сакривен од администратора. Текуће забране и блокирања можете наћи [[Special:BlockList|овде]].",
        "mergehistory": "Споји историје страница",
        "mergehistory-header": "Ова страница вам омогућава да спојите измене неке изворне странице у нову страницу.\nЗапамтите да ће ова измена оставити непромењен садржај историје странице.",
        "mergehistory-same-destination": "Изворна и одредишна страница не могу бити исте",
        "mergehistory-reason": "Разлог:",
        "mergelog": "Дневник спајања",
-       "pagemerge-logentry": "Ñ\81Ñ\82Ñ\80аниÑ\86а [[$1]] Ñ\98е Ñ\81поÑ\98ена у [[$2]] (све до измене $3)",
+       "pagemerge-logentry": "Ñ\98е Ñ\81поÑ\98ио [[$1]] у [[$2]] (све до измене $3)",
        "revertmerge": "растави",
        "mergelogpagetext": "Испод је списак најскоријих спајања историја двеју страница.",
        "history-title": "Историја измена странице „$1“",
        "searchprofile-advanced-tooltip": "Претражите прилагођене именске просторе",
        "search-result-size": "$1 ({{PLURAL:$2|1 реч|$2 речи|$2 речи}})",
        "search-result-category-size": "{{PLURAL:$1|1 члан|$1 члана|$1 чланова}}, ({{PLURAL:$2|1 поткатегорија|$2 поткатегорије|$2 поткатегорија}}, {{PLURAL:$3|1 датотека|$3 датотеке|$3 датотека}})",
-       "search-result-score": "Релевантност: $1%",
        "search-redirect": "(преусмерење $1)",
        "search-section": "(одељак $1)",
        "search-suggest": "Да ли сте мислили на: $1",
        "searchall": "све",
        "showingresults": "Испод {{PLURAL:$1|је приказан <strong>1</strong> резултат|су приказана <strong>$1</strong> резултата|је приказано <strong>$1</strong> резултата}} почев од броја <strong>$2</strong>.",
        "showingresultsinrange": "Испод {{PLURAL:$1|је приказан <strong>1</strong> резултат|су приказана <strong>$1</strong> резултата|је приказано <strong>$1</strong> резултата}}, у распону од <strong>$2</strong> до <strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Резултат '''$1''' од '''$3'''|Резултата '''$1 – $2''' од '''$3'''}} за '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Резултат <strong>$1</strong> од <strong>$3</strong>|Резултата <strong>$1 – $2</strong> од <strong>$3</strong>}}",
        "search-nonefound": "Нема поклапања.",
        "powersearch-legend": "Напредна претрага",
        "powersearch-ns": "Тражи у следећим именским просторима:",
        "preferences": "Подешавања",
        "mypreferences": "Подешавања",
        "prefs-edits": "Број измена:",
-       "prefsnologintext2": "Морате бити $1 да бисте мењали своја подешавања.",
+       "prefsnologintext2": "Морате бити пријављени да бисте мењали своја подешавања.",
        "prefs-skin": "Тема",
        "skin-preview": "Прегледај",
        "datedefault": "Свеједно",
        "action-createaccount": "отварање овог корисничког налога",
        "action-history": "гледање историје ове странице",
        "action-minoredit": "означавање ове измене као мање",
-       "action-move": "пÑ\80емеÑ\81Ñ\82и Ð¾Ð²Ñ\83 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83",
+       "action-move": "пÑ\80емеÑ\88Ñ\82аÑ\9aе Ð¾Ð²Ðµ Ñ\81Ñ\82Ñ\80аниÑ\86е",
        "action-move-subpages": "премештање ове странице и њених подстраница",
        "action-move-rootuserpages": "премештање основних корисничких страница",
-       "action-movefile": "премести ову датотеку",
+       "action-move-categorypages": "премештање категорија",
+       "action-movefile": "премештање ове датотеке",
        "action-upload": "слање ове датотеке",
        "action-reupload": "замењивање постојеће датотеке",
        "action-reupload-shared": "постављање ове датотеке на заједничко складиште",
        "action-rollback": "брзо враћање измена последњег корисника који је мењао одређену страницу",
        "action-import": "увожење страница из других викија",
        "action-importupload": "увожење страница из отпремљене датотеке",
-       "action-patrol": "означавање туђих измена прегледаним",
-       "action-autopatrol": "самоозначавање измена прегледаним",
+       "action-patrol": "означавање туђих измена патролираним",
+       "action-autopatrol": "означавање сопствених измена патролираним",
        "action-unwatchedpages": "прегледање списка ненадгледаних страница",
        "action-mergehistory": "спајање историје ове странице",
        "action-userrights": "уређивање свих корисничких права",
        "action-userrights-interwiki": "уређивање корисничких права на другим викијима",
        "action-siteadmin": "закључавање или откључавање базе података",
        "action-sendemail": "слање е-порука",
-       "action-editmywatchlist": "измени свој списак надгледања",
+       "action-editmywatchlist": "измену сопственог списак надгледања",
        "action-viewmywatchlist": "преглед вашег списак надгледања",
        "action-viewmyprivateinfo": "прегледање ваших личних података",
        "action-editmyprivateinfo": "уређивање ваших личних података",
        "uploadwarning": "Упозорење при отпремању",
        "uploadwarning-text": "Измените опис датотеке и покушајте поново.",
        "savefile": "Сачувај датотеку",
-       "uploadedimage": "је послао „[[$1]]“",
-       "overwroteimage": "је послао нову верзију датотеке „[[$1]]“",
        "uploaddisabled": "Отпремање је онемогућено.",
        "copyuploaddisabled": "Слање путем URL адресе је онемогућено.",
        "uploaddisabledtext": "Отпремање датотека је онемогућено.",
        "license-header": "Лиценца:",
        "nolicense": "није изабрано",
        "license-nopreview": "(преглед није доступан)",
-       "upload_source_url": " (исправна и јавно доступна адреса)",
+       "upload_source_url": "(исправна и јавно доступна адреса)",
        "upload_source_file": "(датотека на вашем рачунару)",
+       "listfiles-delete": "обриши",
        "listfiles-summary": "Ова посебна страница приказује све послате датотеке.",
        "listfiles_search_for": "Назив датотеке:",
        "imgfile": "датотека",
        "uploadnewversion-linktext": "Пошаљи нову верзију ове датотеке",
        "shared-repo-from": "из $1",
        "shared-repo": "заједничко складиште",
-       "shared-repo-name-wikimediacommons": "{{#SWITCH:{{{1|}}}\n|#default=Викимедијина остава\n|dat=Викимедијиној остави\n}}",
+       "shared-repo-name-wikimediacommons": "Викимедијина остава",
        "filepage.css": "/* CSS који је постављен овде се налази на страницама за опис датотека, као и на страним викијима */",
        "upload-disallowed-here": "Не можете да замените ову датотеку.",
        "filerevert": "Врати $1",
        "randomincategory": "Случајна страница у категорији",
        "randomincategory-invalidcategory": "„$1“ није ваљано име категорије",
        "randomincategory-nopages": "Нема страница у категорији [[:Category:$1|$1]].",
-       "randomincategory-selectcategory-submit": "Иди",
+       "randomincategory-category": "Категорија:",
        "randomredirect": "Случајно преусмерење",
        "randomredirect-nopages": "Нема преусмерења у именском простору „$1”.",
        "statistics": "Статистике",
        "ninterwikis": "$1 {{PLURAL:$1|међувики|међувикија|међувикија}}",
        "nlinks": "$1 {{PLURAL:$1|веза|везе|веза}}",
        "nmembers": "$1 {{PLURAL:$1|члан|члана|чланова}}",
+       "nmemberschanged": "$1 → $2 {{PLURAL:$2|члан|члана|чланова}}",
        "nrevisions": "$1 {{PLURAL:$1|измена|измене|измена}}",
        "nviews": "$1 {{PLURAL:$1|преглед|прегледа|прегледа}}",
        "nimagelinks": "Користи се на $1 {{PLURAL:$1|страници|странице|страница}}",
        "wantedfiles": "Тражене датотеке",
        "wantedfiletext-cat": "Следеће датотеке се користе, али не постоје. Датотеке из других ризница могу бити наведене иако не постоје. Такве датотеке ће бити <del>поништене</del> са списка. Поред тога, странице које садрже непостојеће датотеке се налазе [[:$1|овде]].",
        "wantedfiletext-nocat": "Следеће датотеке се користе, али не постоје. Датотеке из других ризница могу бити наведене иако не постоје. Такве датотеке ће бити <del>поништене</del> са списка.",
+       "wantedfiletext-nocat-noforeign": "Следеће датотеке се користе, али не постоје.",
        "wantedtemplates": "Тражени шаблони",
        "mostlinked": "Странице с највише веза",
        "mostlinkedcategories": "Категорије с највише веза",
        "cachedspecial-viewing-cached-ts": "Гледате кеширану верзију ове странице, која може да се разликује од тренутне.",
        "cachedspecial-refresh-now": "Погледај најновију.",
        "categories": "Категоријe",
-       "categoriespagetext": "{{PLURAL:$1|Следећа категорија садржи|Следеће категорије садрже}} странице или датотеке.\n[[Special:UnusedCategories|Некоришћене категорије]] нису приказане овде.\nПогледајте и [[Special:WantedCategories|тражене категорије]].",
+       "categoriespagetext": "{{PLURAL:$1|1=Следећа категорија садржи|Следеће категорије садрже}} странице или датотеке.\n[[Special:UnusedCategories|Некоришћене категорије]] нису приказане овде.\nПогледајте и [[Special:WantedCategories|тражене категорије]].",
        "categoriesfrom": "Прикажи категорије почев од:",
        "special-categories-sort-count": "поређај по броју",
        "special-categories-sort-abc": "поређај по азбучном реду",
        "listgrouprights-namespaceprotection-namespace": "Именски простор",
        "trackingcategories-name": "Име поруке",
        "trackingcategories-nodesc": "Опис није доступан.",
+       "trackingcategories-disabled": "Категорија је онемогућена",
        "mailnologin": "Нема адресе за слање",
        "mailnologintext": "Морате бити [[Special:UserLogin|пријављени]] и имати исправну е-адресу у [[Special:Preferences|подешавањима]] да бисте слали е-поруке другим корисницима.",
        "emailuser": "Пошаљи е-поруку",
        "emailuser-title-target": "Слање е-поруке {{GENDER:$1|кориснику|корисници|кориснику}}",
        "emailuser-title-notarget": "Слање е-поруке кориснику",
        "emailpage": "Слање е-порука",
-       "emailpagetext": "Можете да користите доњи образац да пошаљете е-поруку {{GENDER:$1|овом кориснику|овој корисници|овом кориснику|}}.\nЕ-адреса коју сте унели у вашим [[Special:Preferences|подешавањима]] ће се приказати у пољу „Од“, тако да ће прималац моћи да вам одговори директно.",
+       "emailpagetext": "Можете да користите доњи образац да пошаљете е-поруку {{GENDER:$1|овом кориснику|овој корисници}}.\nЕ-адреса коју сте унели у вашим [[Special:Preferences|подешавањима]] ће се приказати у пољу „Од“, тако да ће прималац моћи да вам одговори директно.",
        "defemailsubject": "{{SITENAME}} — Е-пошта од {{GENDER:$1|корисника|кориснице}} $1",
        "usermaildisabled": "Корисничка е-пошта је онемогућена",
        "usermaildisabledtext": "Не можете да шаљете е-поруке другим корисницима на овом викију",
        "mywatchlist": "Списак надгледања",
        "watchlistfor2": "За $1 $2",
        "nowatchlist": "Ваш списак надгледања је празан.",
-       "watchlistanontext": "Морате бити $1 да бисте гледали и уређивали ставке на вашем списку надгледања.",
+       "watchlistanontext": "Морате бити пријављени да бисте гледали и уређивали ставке на вашем списку надгледања.",
        "watchnologin": "Нисте пријављени",
        "addwatch": "Додај на списак надгледања",
        "addedwatchtext": "Страница „[[:$1]]“ је додата на ваш [[Special:Watchlist|списак надгледања]].\nБудуће измене ове странице и њене странице за разговор биће наведене тамо.",
        "watchlist-details": "Имате {{PLURAL:$1|$1 страница|$1 странице|$1 страница}} на вашем списку надгледања, не рачунајући странице за разговор.",
        "wlheader-enotif": "Обавештење е-поруком је омогућено.",
        "wlheader-showupdated": "Странице које су измењене откад сте их последњи пут посетили су '''подебљане'''.",
-       "wlnote2": "Испод су приказане измене у {{PLURAL:$1|последњих један сат|последњих <strong>$1</strong> сата}} закључно са $2, $3.",
+       "wlnote": "Испод {{PLURAL:$1|је последња измена|су последње '''$1''' измене|је последњих '''$1''' измена}} у {{PLURAL:$2|претходном сату|претходна '''$2''' сата|претходних '''$2''' сати}}, закључно са $3, $4.",
        "wlshowlast": "Прикажи последњих $1 сати, $2 дана, $3",
        "watchlist-options": "Поставке списка надгледања",
        "watching": "Надгледање…",
        "deletepage": "Обриши страницу",
        "confirm": "Потврди",
        "excontent": "садржај је био: „$1“",
-       "excontentauthor": "садржај је био: „$1“ (а једини уредник је био „[[Special:Contributions/$2|$2]]“)",
+       "excontentauthor": "садржај је био: „$1“ (а једини уредник је био „[[Special:Contribs/$2|$2]]“)",
        "exbeforeblank": "садржај пре брисања је био: „$1“",
        "delete-confirm": "Брисање странице „$1“",
        "delete-legend": "Обриши",
-       "historywarning": "<strong>Упозорење:</strong> страница коју желите да обришете има историју с приближно $1 {{PLURAL:$1|изменом|измене|измена}}:",
+       "historywarning": "<strong>Упозорење:</strong> страница коју желите да обришете има историју са $1 {{PLURAL:$1|изменом|измене|измена}}:",
        "confirmdeletetext": "Управо ћете обрисати страницу, укључујући и њену историју.\nПотврдите своју намеру, да разумете последице и да ово радите у складу с [[{{MediaWiki:Policy-url}}|правилима]].",
        "actioncomplete": "Радња је завршена",
        "actionfailed": "Радња није успела",
        "delete-edit-reasonlist": "Уреди разлоге брисања",
        "delete-toobig": "Ова страница има велику историју, преко $1 {{PLURAL:$1|измене|измене|измена}}.\nБрисање таквих страница је ограничено да би се спречило случајно оптерећење сервера.",
        "delete-warning-toobig": "Ова страница има велику историју, преко $1 {{PLURAL:$1|измене|изменe|измена}}.\nЊено брисање може пореметити базу података, стога поступајте с опрезом.",
-       "deleting-backlinks-warning": "'''Упозорење:''' Бришете страницу која је укључена у друге странице или друге странице воде на њу.",
+       "deleteprotected": "Не можете обрисати ову страницу зато што је заштићена.",
+       "deleting-backlinks-warning": "'''Упозорење:''' бришете страницу која је укључена у [[Special:WhatLinksHere/{{FULLPAGENAME}}|друге странице]] или друге странице воде на њу.",
        "rollback": "Врати измене",
        "rollback_short": "Врати",
        "rollbacklink": "врати",
        "cantrollback": "Не могу да вратим измену.\nПоследњи аутор је уједно и једини.",
        "alreadyrolled": "Враћање последње измене странице [[:$1]] од стране {{GENDER:$2|корисника|кориснице|корисника}} [[User:$2|$2]] ([[User talk:$2|разговор]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]); неко други је већ изменио или вратио страницу.\n\nПоследњу измену је {{GENDER:$3|направио|направила|направио}} [[User:$3|$3]] ([[User talk:$3|разговор]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Опис измене: „''$1''“.",
-       "revertpage": "Враћене измене [[Special:Contributions/$2|$2]] ([[User talk:$2|разговор]]) на последњу измену корисника [[User:$1|$1]]",
+       "revertpage": "Враћене измене [[Special:Contribs/$2|$2]] ([[User talk:$2|разговор]]) на последњу измену корисника [[User:$1|$1]]",
        "revertpage-nouser": "Враћене су измене скривеног корисника на последњу измену {{GENDER:$1|корисника|кориснице}} [[User:$1|$1]]",
        "rollback-success": "Враћене су измене {{GENDER:$1|корисника|кориснице}} $1\nна последњу измену {{GENDER:$2|корисника|кориснице}} $2.",
        "sessionfailure-title": "Сесија је окончана",
        "sp-contributions-search": "Претрага доприноса",
        "sp-contributions-username": "ИП адреса или корисничко име:",
        "sp-contributions-toponly": "Прикажи само најновије измене",
-       "sp-contributions-newonly": "Ð\9fÑ\80икажи Ñ\81амо Ð¸Ð·Ð¼ÐµÐ½Ðµ ÐºÐ¾Ñ\98има Ñ\81Ñ\83 ÐºÑ\80еиÑ\80ане нове странице",
+       "sp-contributions-newonly": "Ð\9fÑ\80икажи Ñ\81амо Ð¸Ð·Ð¼ÐµÐ½Ðµ ÐºÐ¾Ñ\98има Ñ\81Ñ\83 Ð½Ð°Ð¿Ñ\80авÑ\99ене нове странице",
        "sp-contributions-submit": "Претражи",
        "whatlinkshere": "Шта води овде",
        "whatlinkshere-title": "Странице које су повезане са „$1“",
        "autoblockid": "Аутоматско блокирање #$1",
        "block": "Блокирај корисника",
        "unblock": "Деблокирај корисника",
-       "blockip": "Блокирај корисника",
+       "blockip": "Блокирај {{GENDER:$1|корисника|корисницу}}",
        "blockip-legend": "Блокирај корисника",
        "blockiptext": "Користите доњи образац да бисте забранили приступ за писање с одређене ИП адресе или корисничког имена.\nОво би требало да вршите само ради спречавања вандализма, у складу са [[{{MediaWiki:Policy-url}}|смерницама]].\nИзаберите конкретан разлог испод (пример: навођење конкретних страница које су вандализоване).",
        "ipaddressorusername": "ИП адреса или корисничко име:",
        "unblockiptext": "Користите образац испод да бисте вратили право писања блокираној IP адреси или корисничком имену.",
        "ipusubmit": "Уклони ову блокаду",
        "unblocked": "[[User:$1|$1]] је деблокиран",
-       "unblocked-range": "$1 је {{GENDER:$1|деблокиран|деблокирана|деблокиран}}",
+       "unblocked-range": "$1 је деблокиран",
        "unblocked-id": "Блокирање $1 је уклоњено",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] је деблокиран.",
        "blocklist": "Блокирани корисници",
        "ipblocklist": "Блокирани корисници",
        "ipblocklist-legend": "Проналажење блокираног корисника",
        "expiringblock": "истиче $1 у $2",
        "anononlyblock": "само анонимни",
        "noautoblockblock": "аутоматско блокирање је онемогућено",
-       "createaccountblock": "оÑ\82ваÑ\80аÑ\9aе Ð½Ð°Ð»Ð¾Ð³Ð° Ñ\98е Ð±Ð»Ð¾ÐºÐ¸Ñ\80ано",
+       "createaccountblock": "оÑ\82ваÑ\80аÑ\9aе Ð½Ð°Ð»Ð¾Ð³Ð° Ñ\98е Ð¾Ð½ÐµÐ¼Ð¾Ð³Ñ\83Ñ\9bено",
        "emailblock": "е-пошта је блокирана",
        "blocklist-nousertalk": "забрањено уређивање сопствене странице за разговор",
        "ipblocklist-empty": "Списак блокирања је празан.",
        "emaillink": "пошаљи е-поруку",
        "autoblocker": "Аутоматски сте блокирани јер делите ИП адресу с корисником/цом [[User:$1|$1]].\nРазлог блокирања: „$2“",
        "blocklogpage": "Дневник блокирања",
-       "blocklog-showlog": "{{GENDER:$1|Овај корисник је раније блокиран|Ова корисница је раније блокирана|Овај корисник је раније блокиран}}.\nИсторија блокирања се налази испод:",
-       "blocklog-showsuppresslog": "{{GENDER:|Овај корисник је раније блокиран и сакривен|Ова корисница је раније блокирана и сакривена|Овај корисник је раније блокиран и сакривен}}.\nИсторија сакривања се налази испод:",
+       "blocklog-showlog": "{{GENDER:$1|Овај корисник је раније блокиран|Ова корисница је раније блокирана}}.\nИсторија блокирања се налази испод:",
+       "blocklog-showsuppresslog": "{{GENDER:$1|Овај корисник је раније блокиран и сакривен|Ова корисница је раније блокирана и сакривена}}.\nИсторија сакривања се налази испод:",
        "blocklogentry": "је блокирао [[$1]] с роком истицања од $2 $3",
        "reblock-logentry": "{{GENDER:|је променио|је променила|је променио}} подешавања за блокирање {{GENDER:$1|корисника|кориснице|корисника}} [[$1]] с роком истека од $2 ($3)",
        "blocklogtext": "Ово је дневник блокирања и деблокирања корисника.\nАутоматски блокиране ИП адресе нису наведене.\nТекуће забране и блокирања можете наћи [[Special:BlockList|овде]].",
-       "unblocklogentry": "{{GENDER:|је деблокирао|је деблокирала}} $1",
+       "unblocklogentry": "је деблокирао $1",
        "block-log-flags-anononly": "само анонимни корисници",
        "block-log-flags-nocreate": "онемогућено отварање налога",
        "block-log-flags-noautoblock": "аутоматско блокирање је онемогућено",
        "ipb_expiry_invalid": "Време истека је неисправно.",
        "ipb_expiry_temp": "Сакривене блокаде корисника морају бити трајне.",
        "ipb_hide_invalid": "Не могу да потиснем овај налог; има више од {{PLURAL:$1|једне измене|$1 измена}}.",
-       "ipb_already_blocked": "„$1“ је већ блокиран",
+       "ipb_already_blocked": "„$1“ је већ блокиран.",
        "ipb-needreblock": "$1 је већ блокиран. Желите ли да промените подешавања?",
        "ipb-otherblocks-header": "{{PLURAL:$1|Друга блокада|Друге блокаде}}",
        "unblock-hideuser": "Не можете деблокирати овог корисника јер је његово корисничко име сакривено.",
        "movenotallowedfile": "Немате дозволу да премештате датотеке.",
        "cant-move-user-page": "Немате дозволу за премештање основних корисничких страница (осим подстраница).",
        "cant-move-to-user-page": "Немате дозволу за премештање странице на вашу корисничку страницу (осим на корисничку подстраницу).",
+       "cant-move-category-page": "Немате дозволу да премештате странице категорија.",
        "newtitle": "Нови наслов:",
        "move-watch": "Надгледај ову страницу",
        "movepagebtn": "Премести страницу",
        "movepage-page-exists": "Страница $1 већ постоји и не може се заменити.",
        "movepage-page-moved": "Страница $1 је премештена на $2.",
        "movepage-page-unmoved": "Страница $1 не може да се премести на $2.",
-       "movepage-max-pages": "Највише $1 {{PLURAL:$1|страница је премештена|странице су премештене|страница је премештено}}, и више не може да буде аутоматски премештено.",
+       "movepage-max-pages": "Највише $1 {{PLURAL:$1|страница је премештена|странице су премештене|страница је премештено}} и више не може да буде аутоматски премештено.",
        "movelogpage": "Дневник премештања",
        "movelogpagetext": "Испод се налази списак премештања страница.",
        "movesubpage": "{{PLURAL:$1|Подстраница|Подстранице}}",
        "delete_and_move_reason": "Обрисано да се ослободи место за премештање из „[[$1]]“",
        "selfmove": "Изворни и одредишни наслови су истоветни;\nне могу да преместим страницу преко саме себе.",
        "immobile-source-namespace": "Не могу да преместим странице у именском простору „$1“",
-       "immobile-target-namespace": "Ð\9dе Ð¼Ð¾Ð³Ñ\83 Ð´Ð° Ð¿Ñ\80емеÑ\81Ñ\82им Ñ\81Ñ\82Ñ\80аниÑ\86е Ñ\83 Ð¸Ð¼ÐµÐ½Ñ\81ком Ð¿Ñ\80оÑ\81Ñ\82оÑ\80Ñ\83 â\80\9e$1â\80\9d",
+       "immobile-target-namespace": "Ð\9dе Ð¼Ð¾Ð³Ñ\83 Ð´Ð° Ð¿Ñ\80емеÑ\81Ñ\82им Ñ\81Ñ\82Ñ\80аниÑ\86е Ñ\83 Ð¸Ð¼ÐµÐ½Ñ\81ком Ð¿Ñ\80оÑ\81Ñ\82оÑ\80Ñ\83 â\80\9e$1â\80\9c",
        "immobile-target-namespace-iw": "Међувики веза није исправно одредиште за премештање странице.",
        "immobile-source-page": "Ова страница се не може преместити.",
        "immobile-target-page": "Не могу да преместим на жељени наслов.",
        "import": "Увоз страница",
        "importinterwiki": "Међувики увоз",
        "import-interwiki-text": "Изаберите вики и наслов странице за увоз.\nДатуми и имена уредника ће бити сачувани.\nСве радње при увозу с других викија су забележене у [[Special:Log/import|дневнику увоза]].",
-       "import-interwiki-source": "Извор викија/странице:",
-       "import-interwiki-history": "Копирај све старије измене ове странице",
+       "import-interwiki-history": "Копирај све верзије историје за ову страницу",
        "import-interwiki-templates": "Укључи све шаблоне",
        "import-interwiki-submit": "Увези",
        "import-interwiki-namespace": "Одредишни именски простор:",
        "import-rootpage-nosubpage": "Именски простор „$1“ основне странице не дозвољава подстранице.",
        "importlogpage": "Дневник увоза",
        "importlogpagetext": "Административни увози страница с историјама измена с других викија.",
-       "import-logentry-upload": "{{GENDER:|је увезао|је увезла|уведе}} „[[$1]]“ отпремањем датотеке",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|измена|измене|измена}}",
-       "import-logentry-interwiki": "премештено с другог викија: $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|измена|измене|измена}} од $2",
+       "import-logentry-upload": "је увезао [[$1]] отпремањем датотеке",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|измена увезена|измене увезене|измена увезено}}",
+       "import-logentry-interwiki": "је увезао $1 с другог викија",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|измена увезена|измене увезене|измена увезено}} из $2",
        "javascripttest": "Јаваскрипт тест",
        "javascripttest-title": "Извршавање тестова за $1",
        "javascripttest-pagetext-noframework": "Ова страница је резервисана за извршавање јаваскрипт тестова.",
        "tooltip-undo": "Поништава ову измену и отвара образац за уређивање.",
        "tooltip-preferences-save": "Сачувај поставке",
        "tooltip-summary": "Унесите кратак опис",
-       "common.css": "/** CSS постављен овде ће се одразити на све теме */",
+       "common.css": "/* CSS постављен овде ће се одразити на све теме */",
        "print.css": "/* CSS постављен овде ће утицати на издање за штампу */",
        "noscript.css": "/* CSS постављен овде ће утицати на све кориснике којима је онемогућен јаваскрипт */",
        "group-autoconfirmed.css": "/* CSS постављен овде ће утицати на самопотврђене кориснике */",
        "rcpatroldisabled": "Патролирање скорашњих измена је онемогућено",
        "rcpatroldisabledtext": "Патролирање скорашњих измена је онемогућено.",
        "markedaspatrollederror": "Не могу да означим као патролирано",
-       "markedaspatrollederrortext": "Морате изабрати измену да бисте је означили као прегледану.",
+       "markedaspatrollederrortext": "Морате изабрати измену да бисте је означили као патролирану.",
        "markedaspatrollederror-noautopatrol": "Не можете да означите своје измене као патролиране.",
        "markedaspatrollednotify": "Ова измена на страници „$1“ је означена као патролирана.",
        "markedaspatrollederrornotify": "Означавање ове странице патролираном није успело.",
        "exif-isospeedratings": "ISO осетљивост на светло",
        "exif-shutterspeedvalue": "Брзина затварача",
        "exif-aperturevalue": "Отвор бленде",
-       "exif-brightnessvalue": "Осветљеност",
+       "exif-brightnessvalue": "APEX осветљеност",
        "exif-exposurebiasvalue": "Компензација експозиције",
        "exif-maxaperturevalue": "Највећи број отвора бленде",
        "exif-subjectdistance": "Удаљеност до објекта",
        "scarytranscludefailed-httpstatus": "[Не могу да преузмем шаблон $1: HTTP $2]",
        "scarytranscludetoolong": "[URL адреса је предугачка]",
        "deletedwhileediting": "<strong>Упозорење</strong>: ова страница је обрисана након што сте почели с уређивањем!",
-       "confirmrecreate": "[[User:$1|$1]] ([[User talk:$1|разговор]]) {{GENDER:$1|је обрисао|је обрисала|обриса}} ову страницу након што сте почели да је уређујете из следећег разлога:\n: ''$2''\nПотврдите да стварно желите да направите страницу.",
+       "confirmrecreate": "Корисник [[User:$1|$1]] ([[User talk:$1|разговор]]) је обрисао ову страницу након што сте почели да је уређујете из следећег разлога:\n: <em>$2</em>\nПотврдите да стварно желите да направите страницу.",
        "confirmrecreate-noreason": "Корисник [[User:$1|$1]] ([[User talk:$1|разговор]]) је обрисао ову страницу након што сте почели да га уређујете. Потврдите да стварно желите да поново направите ову страницу.",
        "recreate": "Поново направи",
        "unit-pixel": "px",
        "table_pager_limit_submit": "Иди",
        "table_pager_empty": "Нема резултата",
        "autosumm-blank": "Уклоњен целокупан садржај странице",
-       "autosumm-replace": "Замена садржаја странице са „$1“",
+       "autosumm-replace": "Замењен садржај странице са „$1“",
        "autoredircomment": "Преусмерење на [[$1]]",
        "autosumm-new": "Нова страница: $1",
+       "autosumm-newblank": "Направљена празна страница",
        "size-bytes": "$1 B",
        "size-kilobytes": "$1 kB",
        "size-megabytes": "$1 MB",
        "watchlistedit-normal-legend": "Уклањање наслова са списка надгледања",
        "watchlistedit-normal-explain": "Наслови на вашем списку надгледања су приказани испод.\nДа бисте уклонили наслов, означите кућицу до њега и кликните на „{{int:Watchlistedit-normal-submit}}“.\nМожете и да [[Special:EditWatchlist/raw|уредите сиров списак]].",
        "watchlistedit-normal-submit": "Уклони наслове",
-       "watchlistedit-normal-done": "{{PLURAL:$1|Једна страница је уклоњена|$1 странице су уклоњене|$1 страница је уклоњено}} с вашег списка надгледања:",
+       "watchlistedit-normal-done": "{{PLURAL:$1|1=Једна страница је уклоњена|$1 странице су уклоњене|$1 страница је уклоњено}} с вашег списка надгледања:",
        "watchlistedit-raw-title": "Измени сиров списак надгледања",
        "watchlistedit-raw-legend": "Измени сиров списак надгледања",
        "watchlistedit-raw-explain": "Наслови са списка надгледања су приказани испод и могу се уређивати додавањем или уклањањем ставки са списка;\nједан наслов по реду.\nКада завршите, кликните на „{{int:Watchlistedit-raw-submit}}“.\nМожете да [[Special:EditWatchlist|користите и обичан уређивач]].",
        "watchlistedit-raw-titles": "Наслови:",
        "watchlistedit-raw-submit": "Ажурирај списак",
        "watchlistedit-raw-done": "Ваш списак надгледања је ажуриран.",
-       "watchlistedit-raw-added": "{{PLURAL:$1|Додат је један наслов|Додата су $1 наслова|Додато је $1 наслова}}:",
+       "watchlistedit-raw-added": "{{PLURAL:$1|1=Додат је један наслов|Додата су $1 наслова|Додато је $1 наслова}}:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1 наслов је уклоњен|Уклоњена су $1 наслова|Уклоњено је $1 наслова}}:",
        "watchlistedit-clear-title": "Испразни списак надгледања",
        "watchlistedit-clear-legend": "Испразни списак надгледања",
        "watchlistedit-clear-submit": "Испразни списак надгледања (Ово је трајно!)",
        "watchlistedit-clear-done": "Ваш списак надгледања је испражњен.",
        "watchlistedit-clear-removed": "{{PLURAL:$1|1 наслов је уклоњен|$1 наслова је уклоњено}}:",
-       "watchlisttools-clear": "испразни списак ндгледања",
+       "watchlisttools-clear": "иÑ\81пÑ\80азни Ñ\81пиÑ\81ак Ð½Ð°Ð´Ð³Ð»ÐµÐ´Ð°Ñ\9aа",
        "watchlisttools-view": "прикажи сродне измене",
        "watchlisttools-edit": "прикажи и уреди списак надгледања",
        "watchlisttools-raw": "измени сиров списак надгледања",
        "duplicate-defaultsort": "'''Упозорење:''' подразумевани кључ сврставања „$2“ мења некадашњи кључ „$1“.",
        "version": "Верзија",
        "version-extensions": "Инсталирана проширења",
-       "version-skins": "Теме",
+       "version-skins": "Ð\98нÑ\81Ñ\82алиÑ\80ане Ñ\82еме",
        "version-specialpages": "Посебне странице",
        "version-parserhooks": "Куке рашчлањивача",
        "version-variables": "Променљиве",
        "logentry-delete-delete": "$1 је {{GENDER:$2|обрисао|обрисала}} страницу $3",
        "logentry-delete-restore": "$1 је {{GENDER:$2|вратио|вратила}} страницу $3",
        "logentry-delete-event": "$1 је {{GENDER:$2|променио|променила}} видљивост {{PLURAL:$5|догађаја|$5 догађаја}} у дневнику на $3: $4",
-       "logentry-delete-revision": "$1 је {{GENDER:$2|променио|променила}} видљивост {{PLURAL:$5|измене|$5 измена}} на страници $3: $4",
+       "logentry-delete-revision": "$1 је {{GENDER:$2|променио|променила}} видљивост $5 {{PLURAL:$5|1=измене|измене|измена}} на страници $3: $4",
        "logentry-delete-event-legacy": "$1 је {{GENDER:$2|променио|променила}} видљивост догађаја у дневнику на $3",
        "logentry-delete-revision-legacy": "$1 је {{GENDER:$2|променио|променила}} видљивост измена на страници $3",
        "logentry-suppress-delete": "$1 је {{GENDER:$2|потиснуо|потиснула}} страницу $3",
        "logentry-move-move_redir": "$1 је {{GENDER:$2|преместио|преместила}} страницу $3 на $4 преко преусмерења",
        "logentry-move-move_redir-noredirect": "$1 је {{GENDER:$2|преместио|преместила}} страницу $3 на $4 преко преусмерења без остављања преусмерења",
        "logentry-patrol-patrol": "$1 је {{GENDER:$2|означио|означила}} измену $4 странице $3 као патролирану",
-       "logentry-patrol-patrol-auto": "$1 је аутоматски {{GENDER:$2|означио|означила}} измену $4 странице $3 као прегледану",
+       "logentry-patrol-patrol-auto": "$1 је аутоматски {{GENDER:$2|означио|означила}} измену $4 странице $3 као патролирану",
        "logentry-newusers-newusers": "$1 је {{GENDER:$2|отворио|отворила}} кориснички налог",
        "logentry-newusers-create": "$1 је {{GENDER:$2|отворио|отворила}} кориснички налог",
        "logentry-newusers-create2": "$1 је {{GENDER:$2|отворио|отворила}} кориснички налог $3",
        "logentry-rights-rights": "$1 је {{GENDER:$2|променио|променила}} чланство групе за $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",
+       "logentry-upload-overwrite": "$1 је {{GENDER:$2|послао|послала}} нову верзију $3",
+       "logentry-upload-revert": "$1 је {{GENDER:$2|послао|послала}} $3",
        "rightsnone": "(нема)",
        "feedback-bugornote": "Ако сте спремни да детаљно опишете технички проблем, онда [$1 пријавите грешку].\nУ супротном, послужите се једноставним обрасцем испод. Ваш коментар ће стајати на страници „[$3 $2]“, заједно с корисничким именом и прегледачем који користите.",
        "feedback-subject": "Наслов:",
        "pagelang-name": "Страница",
        "pagelang-language": "Језик",
        "pagelang-select-lang": "Изабери језик",
-       "right-pagelang": "пÑ\80омена језика странице",
+       "right-pagelang": "меÑ\9aаÑ\9aе језика странице",
        "action-pagelang": "промену језика странице"
 }
index 799eaea..dadc80d 100644 (file)
@@ -16,7 +16,8 @@
                        "Жељко Тодоровић",
                        "Михајло Анђелковић",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Podvlačenje veza:",
        "tog-watchdefault": "Dodaj stranice i datoteke koje izmenim u spisak nadgledanja",
        "tog-watchmoves": "Dodaj stranice i datoteke koje premestim u spisak nadgledanja",
        "tog-watchdeletion": "Dodaj stranice i datoteke koje obrišem u spisak nadgledanja",
+       "tog-watchrollback": "Dodaj stranice na kojima sam vratio izmene u spisak nadgledanja",
        "tog-minordefault": "Označavaj sve izmene kao manje",
        "tog-previewontop": "Prikaži pregled pre okvira za uređivanje",
        "tog-previewonfirst": "Prikaži pregled na prvoj izmeni",
        "tog-enotifwatchlistpages": "Pošalji mi e-poruku kada se promeni stranica ili datoteka koju nadgledam",
        "tog-enotifusertalkpages": "Pošalji mi e-poruku kada se promeni moja stranica za razgovor",
        "tog-enotifminoredits": "Pošalji mi e-poruku i za manje izmene u stranicama i datotekama",
-       "tog-enotifrevealaddr": "Otkrij moju e-adresu u porukama obaveštenja",
+       "tog-enotifrevealaddr": "Prikaži moju e-adresu u porukama obaveštenja",
        "tog-shownumberswatching": "Prikaži broj korisnika koji nadgledaju",
        "tog-oldsig": "Tekući potpis:",
        "tog-fancysig": "Smatraj potpis kao vikitekst (bez samopovezivanja)",
        "category-empty": "<div style=\"margin:2em 1em 0 1em; padding:0.5em; border:1px solid #AAA; text-align:center;\">''Ova kategorija trenutno ne sadrži stranice ili datoteke.''</div>",
        "hidden-categories": "{{PLURAL:$1|Sakrivena kategorija|Sakrivene kategorije}}",
        "hidden-category-category": "Sakrivene kategorije",
-       "category-subcat-count": "{{PLURAL:$2|Ova kategorija sadrži samo sledeću potkategoriju.|Ova kategorija ima {{PLURAL:$1|sledeću potkategoriju|sledeće $1 potkategorije|sledećih $1 potkategorija}}, od ukupno $2.}}",
+       "category-subcat-count": "{{PLURAL:$2|1=Ova kategorija sadrži samo sledeću potkategoriju.|Ova kategorija ima {{PLURAL:$1|1=sledeću potkategoriju|sledeće $1 potkategorije|sledećih $1 potkategorija}}, od ukupno $2.}}",
        "category-subcat-count-limited": "Ova kategorija sadrži {{PLURAL:$1|sledeću potkategoriju|sledeće $1 potkategorije|sledećih $1 potkategorija}}.",
-       "category-article-count": "{{PLURAL:$2|Ova kategorija sadrži samo sledeću stranicu.|{{PLURAL:$1|Sledeća stranica je|Sledeće $1 stranice su|Sledećih $1 stranica je}} u ovoj kategoriji, od ukupno $2.}}",
-       "category-article-count-limited": "{{PLURAL:$1|Sledeća stranica je|Sledeće $1 stranice su|Sledećih $1 stranica je}} u ovoj kategoriji.",
-       "category-file-count": "{{PLURAL:$2|Ova kategorija sadrži samo sledeću datoteku.|{{PLURAL:$1|Sledeća datoteka je|Sledeće $1 datoteke su|Sledećih $1 datoteka je}} u ovoj kategoriji, od ukupno $2.}}",
-       "category-file-count-limited": "{{PLURAL:$1|Sledeća datoteka je|Sledeće $1 datoteke su|Sledećih $1 datoteka je}} u ovoj kategoriji.",
+       "category-article-count": "{{PLURAL:$2|1=Ova kategorija sadrži samo sledeću stranicu.|{{PLURAL:$1|Sledeća stranica je|Sledeće $1 stranice su|Sledećih $1 stranica je}} u ovoj kategoriji, od ukupno $2.}}",
+       "category-article-count-limited": "{{PLURAL:$1|1=Sledeća stranica je|Sledeće $1 stranice su|Sledećih $1 stranica je}} u ovoj kategoriji.",
+       "category-file-count": "{{PLURAL:$2|1=Ova kategorija sadrži samo sledeću datoteku.|{{PLURAL:$1|1=Sledeća datoteka je|Sledeće $1 datoteke su|Sledećih $1 datoteka je}} u ovoj kategoriji, od ukupno $2.}}",
+       "category-file-count-limited": "{{PLURAL:$1|1=Sledeća datoteka je|Sledeće $1 datoteke su|Sledećih $1 datoteka je}} u ovoj kategoriji.",
        "listingcontinuesabbrev": "nast.",
        "index-category": "Popisane stranice",
        "noindex-category": "Nepopisane stranice",
        "delete": "Obriši",
        "deletethispage": "Obriši ovu stranicu",
        "undeletethispage": "Vrati ovu stranicu",
-       "undelete_short": "Vrati {{PLURAL:$1|jednu obrisanu izmenu|$1 obrisane izmene|$1 obrisanih izmena}}",
+       "undelete_short": "Vrati {{PLURAL:$1|1=jednu obrisanu izmenu|$1 obrisane izmene|$1 obrisanih izmena}}",
        "viewdeleted_short": "Pogledaj {{PLURAL:$1|obrisanu izmenu|$1 obrisane izmene|$1 obrisanih izmena}}",
        "protect": "Zaštiti",
        "protect_change": "promeni",
        "talkpagelinktext": "razgovor",
        "specialpage": "Posebna stranica",
        "personaltools": "Lične alatke",
-       "postcomment": "Novi odeljak",
        "articlepage": "Pogledaj stranicu sa sadržajem",
        "talk": "Razgovor",
        "views": "Pregledi",
        "otherlanguages": "Drugi jezici",
        "redirectedfrom": "(preusmereno sa $1)",
        "redirectpagesub": "Preusmerenje",
+       "redirectto": "Preusmerava na:",
        "lastmodifiedat": "Ova stranica je poslednji put izmenjena $1 u $2.",
        "viewcount": "Ova stranica je pregledana {{PLURAL:$1|jedanput|$1 puta|$1 puta}}.",
        "protectedpage": "Zaštićena stranica",
        "hidetoc": "sakrij",
        "collapsible-collapse": "skupi",
        "collapsible-expand": "proširi",
+       "confirmable-confirm": "Da li {{GENDER:$1|ste}} sigurni?",
+       "confirmable-yes": "Da",
+       "confirmable-no": "Ne",
        "thisisdeleted": "Pogledati ili vratiti $1?",
        "viewdeleted": "Pogledati $1?",
        "restorelink": "{{PLURAL:$1|obrisanu izmenu|$1 obrisane izmene|$1 obrisanih izmena}}",
        "viewsourcetext": "Možete čitati i kopirati sadržaj ove stranice:",
        "viewyourtext": "Možete da pogledate i umnožite izvor '''vaših izmena''' na ovoj stranici:",
        "protectedinterface": "Ova stranica sadrži tekst korisničkog okruženja za softver na ovom vikiju i zaštićena je radi sprečavanja zloupotrebe.\nDa biste dodali ili izmenili prevode svih vikija, posetite [//translatewiki.net/ Translejtviki], projekat za lokalizaciju Medijavikija.",
-       "editinginterface": "'''Upozorenje:''' uređujete stranicu koja se koristi za prikazivanje teksta korisničkog okruženja.\nIzmene na ovoj stranici će uticati na sve korisnike ovog vikija.\nDa biste dodali ili izmenili prevode svih vikija, posetite [//translatewiki.net/wiki/Main_Page?setlang=sr_ec Translejtviki], projekat za lokalizaciju Medijavikija.",
+       "editinginterface": "<strong>Upozorenje:</strong> uređujete stranicu koja se koristi za prikazivanje teksta korisničkog okruženja.\nIzmene na ovoj stranici će uticati na sve korisnike ovog vikija.\nDa biste dodali ili izmenili prevode svih vikija, posetite [//translatewiki.net/ Translejtviki], projekat za lokalizaciju Medijavikija.",
        "cascadeprotected": "Ova stranica je zaključana jer sadrži {{PLURAL:$1|sledeću stranicu koja je zaštićena|sledeće stranice koje su zaštićene}} „prenosivom“ zaštitom:\n$2",
        "namespaceprotected": "Nemate dozvolu da uređujete stranice u imenskom prostoru '''$1'''.",
        "customcssprotected": "Nemate dozvolu da menjate ovu CSS stranicu jer sadrži lične postavke drugog korisnika.",
        "externaldberror": "Došlo je do greške pri prepoznavanju baze podataka ili nemate ovlašćenja da ažurirate svoj spoljni nalog.",
        "login": "Prijavi me",
        "nav-login-createaccount": "Prijava/registracija",
-       "loginprompt": "Omogućite kolačiće da biste se prijavili na ovaj viki.",
        "userlogin": "Prijava/registracija",
        "userloginnocreate": "Prijava",
        "logout": "Odjava",
        "userlogin-resetlink": "Zaboravili ste podatke za prijavu?",
        "userlogin-resetpassword-link": "Zaboravili ste lozinku?",
        "userlogin-helplink2": "Pomoć pri prijavljivanju",
-       "userlogin-loggedin": "Već ste prijavljeni kao {{GENDER:$1|$1}}.\nKoristite donji obrazac da biste se prijavili kao drugi korisnik.",
-       "userlogin-createanother": "Otvori još jedan nalog",
        "createacct-emailrequired": "Adresa e-pošte",
        "createacct-emailoptional": "Adresa e-pošte (opciono)",
        "createacct-email-ph": "Unesite vašu adresu e-pоšte",
        "badretype": "Unete lozinke se ne poklapaju.",
        "userexists": "Korisničko ime je zauzeto. Izaberite drugo.",
        "loginerror": "Greška pri prijavljivanju",
-       "createacct-error": "Došlo je do greške pri kreiranju naloga",
+       "createacct-error": "Došlo je do greške pri otvaranju naloga",
        "createaccounterror": "Ne mogu da otvorim nalog: $1",
-       "nocookiesnew": "Korisnički nalog je otvoren, ali niste prijavljeni.\nOvaj viki koristi kolačiće za prijavu. Vama su kolačići onemogućeni.\nOmogućite ih, pa se onda prijavite sa svojim korisničkim imenom i lozinkom.",
-       "nocookieslogin": "Ovaj viki koristi kolačiće za prijavljivanje korisnika.\nVama su kolačići onemogućeni. Omogućite ih i pokušajte ponovo.",
+       "nocookiesnew": "Korisnički nalog je otvoren, ali niste prijavljeni.\n{{SITENAME}} koristi kolačiće za prijavu. Vama su kolačići onemogućeni.\nOmogućite ih, pa se onda prijavite sa svojim korisničkim imenom i lozinkom.",
+       "nocookieslogin": "{{SITENAME}} koristi kolačiće za prijavljivanje korisnika.\nVama su kolačići onemogućeni. Omogućite ih i pokušajte ponovo.",
        "nocookiesfornew": "Korisnički nalog nije otvoren jer njegov izvor nije potvrđen.\nOmogućite kolačiće na pregledaču i ponovo učitajte stranicu.",
        "nocookiesforlogin": "{{int:nocookieslogin}}",
        "noname": "Uneli ste neispravno korisničko ime.",
        "password-name-match": "Lozinka se mora razlikovati od korisničkog imena.",
        "password-login-forbidden": "Korišćenje ovog korisničkog imena i lozinke je zabranjeno.",
        "mailmypassword": "Resetuj lozinku",
-       "passwordremindertitle": "{{SITENAME}} â\80\93 podsetnik za lozinku",
+       "passwordremindertitle": "{{SITENAME}} â\80\94 privremena lozinka",
        "passwordremindertext": "Neko, verovatno vi, sa IP adrese $1 je zatražio novu lozinku na vikiju {{SITENAME}} ($4).\nStvorena je privremena lozinka za {{GENDER:$2|korisnika|korisnicu|korisnika}} $2 koja glasi $3.\nUkoliko je ovo vaš zahtev, sada se prijavite i postavite novu lozinku.\nPrivremena lozinka ističe za {{PLURAL:$5|jedan dan|$5 dana|$5 dana}}.\n\nAko je neko drugi zatražio promenu lozinke, ili ste se setili vaše lozinke i ne želite da je menjate, zanemarite ovu poruku.",
-       "noemail": "Ne postoji e-adresa za {{GENDER:$1|korisnika|korisnicu|korisnika}} $1.",
+       "noemail": "Ne postoji e-adresa za {{GENDER:$1|korisnika|korisnicu}} $1.",
        "noemailcreate": "Morate navesti ispravnu e-adresu",
        "passwordsent": "Nova lozinka je poslata na e-adresu {{GENDER:$1|korisnika|korisnice|korisnika}} $1.\nPrijavite se pošto je primite.",
        "blocked-mailpassword": "Vašoj IP adresi je onemogućeno uređivanje stranica, kao i mogućnost zahtevanja nove lozinke.",
        "eauthentsent": "Na navedenu e-adresu je poslat potvrdni kod.\nPre nego što pošaljemo daljnje poruke, pratite uputstva s e-pošte da biste potvrdili da ste vi otvorili nalog.",
        "throttled-mailpassword": "Poruka za promenu lozinke je poslata u {{PLURAL:$1|poslednjih sat vremena|poslednja $1 sata|poslednjih $1 sati}}.\nDa bismo sprečili zloupotrebu, podsetnik šaljemo samo jednom u roku od {{PLURAL:$1|sat vremena|$1 sata|$1 sati}}.",
        "mailerror": "Greška pri slanju poruke: $1",
-       "acct_creation_throttle_hit": "Posetioci ovog vikija koji koriste vašu IP adresu su već otvorili {{PLURAL:$1|jedan nalog|$1 naloga|$1 naloga}} prethodni dan, što je najveći dozvoljeni broj u tom vremenskom periodu.\nZbog toga posetioci s ove IP adrese trenutno ne mogu otvoriti više naloga.",
+       "acct_creation_throttle_hit": "Posetioci ovog vikija koji koriste vašu IP adresu su već otvorili {{PLURAL:$1|1=jedan nalog|$1 naloga|$1 naloga}} prethodni dan, što je najveći dozvoljeni broj u tom vremenskom periodu.\nZbog toga posetioci s ove IP adrese trenutno ne mogu otvoriti više naloga.",
        "emailauthenticated": "Vaša e-adresa je potvrđena $2 u $3.",
        "emailnotauthenticated": "Vaša e-adresa još nije potvrđena.\nPoruke neće biti poslate ni u jednom od sledećih slučajeva.",
        "noemailprefs": "Unesite e-adresu kako bi ove mogućnosti radile.",
        "preview": "Pregled",
        "showpreview": "Prikaži pretpregled",
        "showdiff": "Prikaži izmene",
-       "anoneditwarning": "'''Upozorenje:''' niste prijavljeni.\nVaša IP adresa će biti zabeležena u istoriji ove stranice.",
+       "blankarticle": "<strong>Upozorenje:</strong> stranica koju pravite nema nikakav sadržaj.\nAko još jednom pritisnete „{{int:savearticle}}“ napravićete stranicu bez sadržaja.",
+       "anoneditwarning": "<strong>Upozorenje:</strong> niste prijavljeni. Vaša IP adresa će biti javno vidljiva u istoriji ove stranice ako načinite bilo kakvu izmenu. Ako se <strong>[$1 prijavite]</strong> ili <strong>[$2 otvorite nalog]</strong> vaše izmene će biti pripisane vašem korisničkom imenu.",
        "anonpreviewwarning": "''Niste prijavljeni. Vaša IP adresa će biti zabeležena u istoriji ove stranice.''",
        "missingsummary": "'''Napomena:''' niste uneli opis izmene.\nAko ponovo kliknete na „{{int:savearticle}}“, vaša izmena će biti sačuvana bez opisa.",
        "missingcommenttext": "Unesite komentar ispod.",
        "subject-preview": "Pregled teme/naslova:",
        "blockedtitle": "Korisnik je blokiran",
        "blockedtext": "<strong>Vaše korisničko ime ili IP adresa je blokirana.</strong>\n\nBlokiranje je {{GENDER:$4|izvršio|izvršila}} $1.\nRazlog: <em>$2</em>.\n\n* Datum blokiranja: $8\n* Blokiranje ističe: $6\n* Ime korisnika: $7\n\nObratite se {{GENDER:$4|korisniku|korisnici}} $1 ili [[{{MediaWiki:Grouppage-sysop}}|administratoru]] da razjasnite stvar.\nNe možete koristiti mogućnost „Pošalji poruku ovom korisniku“ ako niste uneli ispravnu e-adresu u [[Special:Preferences|podešavanjima]].\nVaša blokirana IP adresa je $3, a ID blokiranja $5.\nNavedite sve podatke iznad pri stvaranja bilo kakvih upita.",
-       "autoblockedtext": "Vaša IP adresa je blokirana jer ju je upotrebljavao drugi korisnik, koga je {{GENDER:$1|blokirao|blokirala|blokirao}} $1.\nRazlog:\n\n:''$2''\n\n* Datum blokiranja: $8\n* Blokiranje ističe: $6\n* Ime korisnika: $7\n\nObratite se {{GENDER:$1|korisniku|korisnici|korisniku}} $1 ili [[{{MediaWiki:Grouppage-sysop}}|administratoru]] da razjasnite stvar.\n\nNe možete koristiti mogućnost „Pošalji poruku ovom korisniku“ ako niste uneli ispravnu e-adresu u [[Special:Preferences|podešavanjima]].\n\nVaša blokirana IP adresa je $3, a IB $5.\nNavedite sve podatke iznad pri stvaranju bilo kakvih upita.",
+       "autoblockedtext": "Vaša IP adresa je blokirana jer ju je upotrebljavao drugi korisnik, koga je {{GENDER:$4|blokirao|blokirala}} $1.\nRazlog:\n\n:<em>$2</em>\n\n* Datum blokiranja: $8\n* Blokiranje ističe: $6\n* Ime korisnika: $7\n\nObratite se {{GENDER:$4|korisniku|korisnici}} $1 ili [[{{MediaWiki:Grouppage-sysop}}|administratoru]] da razjasnite stvar.\n\nNe možete koristiti mogućnost „Pošalji poruku ovom korisniku“ ako niste uneli ispravnu e-adresu u [[Special:Preferences|podešavanjima]].\n\nVaša blokirana IP adresa je $3, a ID $5.\nNavedite sve podatke iznad pri stvaranju bilo kakvih upita.",
        "blockednoreason": "razlog nije naveden",
        "whitelistedittext": "Za uređivanje stranice je potrebno da budete $1.",
        "confirmedittext": "Morate da potvrdite svoju e-adresu pre uređivanja stranica.\nPostavite i potvrdite adresu preko [[Special:Preferences|podešavanja]].",
        "undo-failure": "Ova izmena se ne može poništiti zbog sukoba izmena.",
        "undo-norev": "Ne mogu da vratim izmenu jer ne postoji ili je obrisana.",
        "undo-nochange": "Izgleda da je izmena već poništena.",
-       "undo-summary": "Poništena izmena $1 {{GENDER:$2|korisnika|korisnice}} [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]])",
+       "undo-summary": "Poništena izmena $1 {{GENDER:$2|korisnika|korisnice}} [[Special:Contribs/$2|$2]] ([[User talk:$2|razgovor]])",
        "undo-summary-username-hidden": "Poništi izmenu $1 skrivenog korisnika",
        "cantcreateaccounttitle": "Ne mogu da otvorim nalog",
-       "cantcreateaccount-text": "Otvaranje naloga s ove IP adrese ('''$1''') je {{GENDER:$3|blokirao|blokirala|blokirao}} [[User:$3|$3]].\n\nRazlog koji je naveo {{GENDER:$3|korisnik|korisnica|korisnik}} $3 je ''$2''",
+       "cantcreateaccount-text": "Otvaranje naloga s ove IP adrese (<strong>$1</strong>) je blokirao/la [[User:$3|$3]].\n\nRazlog koji je naveo/la $3 je <em>$2</em>",
+       "cantcreateaccount-range-text": "Otvaranje naloga sa IP adresa u rasponu '''$1''', koji uključuje i vašu IP adresu ('''$4''') je blokirao/la [[User:$3|$3]].\n\nRazlog koji je naveo/la $3 je <em>$2</em>",
        "viewpagelogs": "Pogledaj dnevnike ove stranice",
        "nohistory": "Ne postoji istorija izmena ove stranice.",
        "currentrev": "Tekuća izmena",
        "revdelete-reasonotherlist": "Drugi razlog",
        "revdelete-edit-reasonlist": "Uredi razloge za brisanje",
        "revdelete-offender": "Autor izmene:",
-       "suppressionlog": "Istorija sakrivanja",
+       "suppressionlog": "Dnevnik sakrivanja",
        "suppressionlogtext": "Ispod se nalazi spisak brisanja i blokiranja koji uključuje sadržaj sakriven od administratora. Tekuće zabrane i blokiranja možete naći [[Special:BlockList|ovde]].",
        "mergehistory": "Spoji istorije stranica",
        "mergehistory-header": "Ova stranica vam omogućava da spojite izmene neke izvorne stranice u novu stranicu.\nZapamtite da će ova izmena ostaviti nepromenjen sadržaj istorije stranice.",
        "mergehistory-same-destination": "Izvorna i odredišna stranica ne mogu biti iste",
        "mergehistory-reason": "Razlog:",
        "mergelog": "Dnevnik spajanja",
-       "pagemerge-logentry": "stranica [[$1]] je spojena u [[$2]] (sve do izmene $3)",
+       "pagemerge-logentry": "je spojio [[$1]] u [[$2]] (sve do izmene $3)",
        "revertmerge": "rastavi",
        "mergelogpagetext": "Ispod je spisak najskorijih spajanja istorija dveju stranica.",
        "history-title": "Istorija izmena stranice „$1“",
        "searchprofile-advanced-tooltip": "Pretražite prilagođene imenske prostore",
        "search-result-size": "$1 ({{PLURAL:$2|1 reč|$2 reči|$2 reči}})",
        "search-result-category-size": "{{PLURAL:$1|1 član|$1 člana|$1 članova}}, ({{PLURAL:$2|1 potkategorija|$2 potkategorije|$2 potkategorija}}, {{PLURAL:$3|1 datoteka|$3 datoteke|$3 datoteka}})",
-       "search-result-score": "Relevantnost: $1%",
        "search-redirect": "(preusmerenje $1)",
        "search-section": "(odeljak $1)",
        "search-suggest": "Da li ste mislili na: $1",
        "searchall": "sve",
        "showingresults": "Ispod {{PLURAL:$1|je prikazan <strong>1</strong> rezultat|su prikazana <strong>$1</strong> rezultata|je prikazano <strong>$1</strong> rezultata}} počev od broja <strong>$2</strong>.",
        "showingresultsinrange": "Ispod {{PLURAL:$1|je prikazan <strong>1</strong> rezultat|su prikazana <strong>$1</strong> rezultata|je prikazano <strong>$1</strong> rezultata}}, u rasponu od <strong>$2</strong> do <strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|1=Rezultat '''$1''' od '''$3'''|Rezultata '''$1 – $2''' od '''$3'''}} za '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Rezultat <strong>$1</strong> od <strong>$3</strong>|Rezultata <strong>$1 – $2</strong> od <strong>$3</strong>}}",
        "search-nonefound": "Nema poklapanja.",
        "powersearch-legend": "Napredna pretraga",
        "powersearch-ns": "Traži u sledećim imenskim prostorima:",
        "action-createaccount": "otvaranje ovog korisničkog naloga",
        "action-history": "gledanje istorije ove stranice",
        "action-minoredit": "označavanje ove izmene kao manje",
-       "action-move": "premesti ovu stranicu",
+       "action-move": "premeštanje ove stranice",
        "action-move-subpages": "premeštanje ove stranice i njenih podstranica",
        "action-move-rootuserpages": "premeštanje osnovnih korisničkih stranica",
-       "action-movefile": "premesti ovu datoteku",
+       "action-movefile": "premeštanje ove datoteke",
        "action-upload": "slanje ove datoteke",
        "action-reupload": "zamenjivanje postojeće datoteke",
        "action-reupload-shared": "postavljanje ove datoteke na zajedničko skladište",
        "action-rollback": "brzo vraćanje izmena poslednjeg korisnika koji je menjao određenu stranicu",
        "action-import": "uvoženje stranica iz drugih vikija",
        "action-importupload": "uvoženje stranica iz otpremljene datoteke",
-       "action-patrol": "označavanje tuđih izmena pregledanim",
-       "action-autopatrol": "samooznačavanje izmena pregledanim",
+       "action-patrol": "označavanje tuđih izmena patroliranim",
+       "action-autopatrol": "označavanje sopstvenih izmena patroliranim",
        "action-unwatchedpages": "pregledanje spiska nenadgledanih stranica",
        "action-mergehistory": "spajanje istorije ove stranice",
        "action-userrights": "uređivanje svih korisničkih prava",
        "action-userrights-interwiki": "uređivanje korisničkih prava na drugim vikijima",
        "action-siteadmin": "zaključavanje ili otključavanje baze podataka",
        "action-sendemail": "slanje e-poruka",
-       "action-editmywatchlist": "izmeni svoj spisak nadgledanja",
+       "action-editmywatchlist": "izmenu sopstvenog spisak nadgledanja",
        "action-viewmywatchlist": "pregled vašeg spisak nadgledanja",
        "action-viewmyprivateinfo": "pregledanje vaših ličnih podataka",
        "action-editmyprivateinfo": "uređivanje vaših ličnih podataka",
        "uploadwarning": "Upozorenje pri otpremanju",
        "uploadwarning-text": "Izmenite opis datoteke i pokušajte ponovo.",
        "savefile": "Sačuvaj datoteku",
-       "uploadedimage": "je poslao „[[$1]]“",
-       "overwroteimage": "je poslao novu verziju datoteke „[[$1]]“",
        "uploaddisabled": "Otpremanje je onemogućeno.",
        "copyuploaddisabled": "Slanje putem URL adrese je onemogućeno.",
        "uploaddisabledtext": "Otpremanje datoteka je onemogućeno.",
        "license-header": "Licenca:",
        "nolicense": "nije izabrano",
        "license-nopreview": "(pregled nije dostupan)",
-       "upload_source_url": " (ispravna i javno dostupna adresa)",
+       "upload_source_url": "(ispravna i javno dostupna adresa)",
        "upload_source_file": "(datoteka na vašem računaru)",
        "listfiles-summary": "Ova posebna stranica prikazuje sve poslate datoteke.",
        "listfiles_search_for": "Naziv datoteke:",
        "sharedupload-desc-create": "Ova datoteka se nalazi na $1 i može da se koristi na drugim projektima.\nNjen opis možete da izmenite na [$2 odgovarajućoj stranici].",
        "filepage-nofile": "Ne postoji datoteka s ovim nazivom.",
        "filepage-nofile-link": "Ne postoji datoteka s ovim nazivom, ali je možete [$1 poslati].",
-       "uploadnewversion-linktext": "Pošalji novo izdanje ove datoteke",
+       "uploadnewversion-linktext": "Pošalji novu verziju ove datoteke",
        "shared-repo-from": "iz $1",
        "shared-repo": "zajedničko skladište",
-       "shared-repo-name-wikimediacommons": "{{#SWITCH:{{{1|}}}\n|#default=Vikimedijina ostava\n|dat=Vikimedijinoj ostavi\n}}",
+       "shared-repo-name-wikimediacommons": "Vikimedijina ostava",
        "filepage.css": "/* CSS koji je postavljen ovde se nalazi na stranicama za opis datoteka, kao i na stranim vikijima */",
        "upload-disallowed-here": "Ne možete da zamenite ovu datoteku.",
        "filerevert": "Vrati $1",
        "randomincategory": "Slučajna stranica u kategoriji",
        "randomincategory-invalidcategory": "„$1“ nije valjano ime kategorije",
        "randomincategory-nopages": "Nema stranica u kategoriji [[:Category:$1|$1]].",
-       "randomincategory-selectcategory-submit": "Idi",
        "randomredirect": "Slučajno preusmerenje",
        "randomredirect-nopages": "Nema preusmerenja u imenskom prostoru „$1”.",
        "statistics": "Statistike",
        "ninterwikis": "$1 {{PLURAL:$1|međuviki|međuvikija|međuvikija}}",
        "nlinks": "$1 {{PLURAL:$1|veza|veze|veza}}",
        "nmembers": "$1 {{PLURAL:$1|član|člana|članova}}",
+       "nmemberschanged": "$1 → $2 {{PLURAL:$2|član|člana|članova}}",
        "nrevisions": "$1 {{PLURAL:$1|izmena|izmene|izmena}}",
        "nviews": "$1 {{PLURAL:$1|pregled|pregleda|pregleda}}",
        "nimagelinks": "Koristi se na $1 {{PLURAL:$1|stranici|stranice|stranica}}",
        "cachedspecial-viewing-cached-ts": "Gledate keširanu verziju ove stranice, koja može da se razlikuje od trenutne.",
        "cachedspecial-refresh-now": "Pogledaj najnoviju.",
        "categories": "Kategorije",
-       "categoriespagetext": "{{PLURAL:$1|Sledeća kategorija sadrži|Sledeće kategorije sadrže}} stranice ili datoteke.\n[[Special:UnusedCategories|Nekorišćene kategorije]] nisu prikazane ovde.\nPogledajte i [[Special:WantedCategories|tražene kategorije]].",
+       "categoriespagetext": "{{PLURAL:$1|1=Sledeća kategorija sadrži|Sledeće kategorije sadrže}} stranice ili datoteke.\n[[Special:UnusedCategories|Nekorišćene kategorije]] nisu prikazane ovde.\nPogledajte i [[Special:WantedCategories|tražene kategorije]].",
        "categoriesfrom": "Prikaži kategorije počev od:",
        "special-categories-sort-count": "poređaj po broju",
        "special-categories-sort-abc": "poređaj po azbučnom redu",
        "emailuser-title-target": "Slanje e-poruke {{GENDER:$1|korisniku|korisnici|korisniku}}",
        "emailuser-title-notarget": "Slanje e-poruke korisniku",
        "emailpage": "Slanje e-poruka",
-       "emailpagetext": "Možete da koristite donji obrazac da pošaljete e-poruku {{GENDER:$1|ovom korisniku|ovoj korisnici|ovom korisniku|}}.\nE-adresa koju ste uneli u vašim [[Special:Preferences|podešavanjima]] će se prikazati u polju „Od“, tako da će primalac moći da vam odgovori direktno.",
+       "emailpagetext": "Možete da koristite donji obrazac da pošaljete e-poruku {{GENDER:$1|ovom korisniku|ovoj korisnici}}.\nE-adresa koju ste uneli u vašim [[Special:Preferences|podešavanjima]] će se prikazati u polju „Od“, tako da će primalac moći da vam odgovori direktno.",
        "defemailsubject": "{{SITENAME}} — E-pošta od {{GENDER:$1|korisnika|korisnice}} $1",
        "usermaildisabled": "Korisnička e-pošta je onemogućena",
        "usermaildisabledtext": "Ne možete da šaljete e-poruke drugim korisnicima na ovom vikiju",
        "watchlist-details": "Imate {{PLURAL:$1|$1 stranica|$1 stranice|$1 stranica}} na vašem spisku nadgledanja, ne računajući stranice za razgovor.",
        "wlheader-enotif": "Obaveštenje e-porukom je omogućeno.",
        "wlheader-showupdated": "Stranice koje su izmenjene otkad ste ih poslednji put posetili su '''podebljane'''.",
-       "wlnote2": "Ispod su prikazane izmene u {{PLURAL:$1|poslednjih jedan sat|poslednjih <strong>$1</strong> sata}} zaključno sa $2, $3.",
+       "wlnote": "Ispod {{PLURAL:$1|je poslednja izmena|su poslednje '''$1''' izmene|je poslednjih '''$1''' izmena}} u {{PLURAL:$2|prethodnom satu|prethodna '''$2''' sata|prethodnih '''$2''' sati}}, zaključno sa $3, $4.",
        "wlshowlast": "Prikaži poslednjih $1 sati, $2 dana, $3",
        "watchlist-options": "Postavke spiska nadgledanja",
        "watching": "Nadgledanje…",
        "deletepage": "Obriši stranicu",
        "confirm": "Potvrdi",
        "excontent": "sadržaj je bio: „$1“",
-       "excontentauthor": "sadržaj je bio: „$1“ (a jedini urednik je bio „[[Special:Contributions/$2|$2]]“)",
+       "excontentauthor": "sadržaj je bio: „$1“ (a jedini urednik je bio „[[Special:Contribs/$2|$2]]“)",
        "exbeforeblank": "sadržaj pre brisanja je bio: „$1“",
        "delete-confirm": "Brisanje stranice „$1“",
        "delete-legend": "Obriši",
        "delete-edit-reasonlist": "Uredi razloge brisanja",
        "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.",
-       "deleting-backlinks-warning": "'''Upozorenje:''' Brišete stranicu koja je uključena u druge stranice ili druge stranice vode na nju.",
+       "deleting-backlinks-warning": "'''Upozorenje:''' brišete stranicu koja je uključena u [[Special:WhatLinksHere/{{FULLPAGENAME}}|druge stranice]] ili druge stranice vode na nju.",
        "rollback": "Vrati izmene",
        "rollback_short": "Vrati",
        "rollbacklink": "vrati",
        "cantrollback": "Ne mogu da vratim izmenu.\nPoslednji autor je ujedno i jedini.",
        "alreadyrolled": "Vraćanje poslednje izmene stranice [[:$1]] od strane {{GENDER:$2|korisnika|korisnice|korisnika}} [[User:$2|$2]] ([[User talk:$2|razgovor]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]); neko drugi je već izmenio ili vratio stranicu.\n\nPoslednju izmenu je {{GENDER:$3|napravio|napravila|napravio}} [[User:$3|$3]] ([[User talk:$3|razgovor]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Opis izmene: „''$1''“.",
-       "revertpage": "Vraćene izmene [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]]) na poslednju izmenu korisnika [[User:$1|$1]]",
+       "revertpage": "Vraćene izmene [[Special:Contribs/$2|$2]] ([[User talk:$2|razgovor]]) na poslednju izmenu korisnika [[User:$1|$1]]",
        "revertpage-nouser": "Vraćene su izmene skrivenog korisnika na poslednju izmenu {{GENDER:$1|korisnika|korisnice}} [[User:$1|$1]]",
        "rollback-success": "Vraćene su izmene {{GENDER:$1|korisnika|korisnice}} $1\nna poslednju izmenu {{GENDER:$2|korisnika|korisnice}} $2.",
        "sessionfailure-title": "Sesija je okončana",
        "sp-contributions-search": "Pretraga doprinosa",
        "sp-contributions-username": "IP adresa ili korisničko ime:",
        "sp-contributions-toponly": "Prikaži samo najnovije izmene",
-       "sp-contributions-newonly": "Prikaži samo izmene kojima su kreirane nove stranice",
+       "sp-contributions-newonly": "Prikaži samo izmene kojima su napravljene nove stranice",
        "sp-contributions-submit": "Pretraži",
        "whatlinkshere": "Šta vodi ovde",
        "whatlinkshere-title": "Stranice koje su povezane sa „$1“",
        "unblockiptext": "Koristite obrazac ispod da biste vratili pravo pisanja blokiranoj IP adresi ili korisničkom imenu.",
        "ipusubmit": "Ukloni ovu blokadu",
        "unblocked": "[[User:$1|$1]] je deblokiran",
-       "unblocked-range": "$1 je {{GENDER:$1|deblokiran|deblokirana|deblokiran}}",
+       "unblocked-range": "$1 je deblokiran",
        "unblocked-id": "Blokiranje $1 je uklonjeno",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] je deblokiran.",
        "blocklist": "Blokirani korisnici",
        "ipblocklist": "Blokirani korisnici",
        "ipblocklist-legend": "Pronalaženje blokiranog korisnika",
        "expiringblock": "ističe $1 u $2",
        "anononlyblock": "samo anonimni",
        "noautoblockblock": "automatsko blokiranje je onemogućeno",
-       "createaccountblock": "otvaranje naloga je blokirano",
+       "createaccountblock": "otvaranje naloga je onemogućeno",
        "emailblock": "e-pošta je blokirana",
        "blocklist-nousertalk": "zabranjeno uređivanje sopstvene stranice za razgovor",
        "ipblocklist-empty": "Spisak blokiranja je prazan.",
        "autoblocker": "Automatski ste blokirani jer delite IP adresu s korisnikom/com [[User:$1|$1]].\nRazlog blokiranja: „$2“",
        "blocklogpage": "Dnevnik blokiranja",
        "blocklog-showlog": "{{GENDER:$1|Ovaj korisnik je ranije blokiran|Ova korisnica je ranije blokirana|Ovaj korisnik je ranije blokiran}}.\nIstorija blokiranja se nalazi ispod:",
-       "blocklog-showsuppresslog": "{{GENDER:|Ovaj korisnik je ranije blokiran i sakriven|Ova korisnica je ranije blokirana i sakrivena|Ovaj korisnik je ranije blokiran i sakriven}}.\nIstorija sakrivanja se nalazi ispod:",
+       "blocklog-showsuppresslog": "{{GENDER:$1|Ovaj korisnik je ranije blokiran i sakriven|Ova korisnica je ranije blokirana i sakrivena}}.\nIstorija sakrivanja se nalazi ispod:",
        "blocklogentry": "je blokirao [[$1]] s rokom isticanja od $2 $3",
        "reblock-logentry": "{{GENDER:|je promenio|je promenila|je promenio}} podešavanja za blokiranje {{GENDER:$1|korisnika|korisnice|korisnika}} [[$1]] s rokom isteka od $2 ($3)",
        "blocklogtext": "Ovo je dnevnik blokiranja i deblokiranja korisnika.\nAutomatski blokirane IP adrese nisu navedene.\nTekuće zabrane i blokiranja možete naći [[Special:BlockList|ovde]].",
-       "unblocklogentry": "{{GENDER:|je deblokirao|je deblokirala}} $1",
+       "unblocklogentry": "je deblokirao $1",
        "block-log-flags-anononly": "samo anonimni korisnici",
        "block-log-flags-nocreate": "onemogućeno otvaranje naloga",
        "block-log-flags-noautoblock": "automatsko blokiranje je onemogućeno",
        "ipb_expiry_invalid": "Vreme isteka je neispravno.",
        "ipb_expiry_temp": "Sakrivene blokade korisnika moraju biti trajne.",
        "ipb_hide_invalid": "Ne mogu da potisnem ovaj nalog; ima više od {{PLURAL:$1|jedne izmene|$1 izmena}}.",
-       "ipb_already_blocked": "„$1“ je već blokiran",
+       "ipb_already_blocked": "„$1“ je već blokiran.",
        "ipb-needreblock": "$1 je već blokiran. Želite li da promenite podešavanja?",
        "ipb-otherblocks-header": "{{PLURAL:$1|Druga blokada|Druge blokade}}",
        "unblock-hideuser": "Ne možete deblokirati ovog korisnika jer je njegovo korisničko ime sakriveno.",
        "movenotallowedfile": "Nemate dozvolu da premeštate datoteke.",
        "cant-move-user-page": "Nemate dozvolu za premeštanje osnovnih korisničkih stranica (osim podstranica).",
        "cant-move-to-user-page": "Nemate dozvolu za premeštanje stranice na vašu korisničku stranicu (osim na korisničku podstranicu).",
+       "cant-move-category-page": "Nemate dozvolu da premeštate stranice kategorija.",
        "newtitle": "Novi naslov:",
        "move-watch": "Nadgledaj ovu stranicu",
        "movepagebtn": "Premesti stranicu",
        "movepage-page-exists": "Stranica $1 već postoji i ne može se zameniti.",
        "movepage-page-moved": "Stranica $1 je premeštena na $2.",
        "movepage-page-unmoved": "Stranica $1 ne može da se premesti na $2.",
-       "movepage-max-pages": "Najviše $1 {{PLURAL:$1|stranica je premeštena|stranice su premeštene|stranica je premešteno}}, i više ne može da bude automatski premešteno.",
+       "movepage-max-pages": "Najviše $1 {{PLURAL:$1|stranica je premeštena|stranice su premeštene|stranica je premešteno}} i više ne može da bude automatski premešteno.",
        "movelogpage": "Dnevnik premeštanja",
        "movelogpagetext": "Ispod se nalazi spisak premeštanja stranica.",
        "movesubpage": "{{PLURAL:$1|Podstranica|Podstranice}}",
        "delete_and_move_reason": "Obrisano da se oslobodi mesto za premeštanje iz „[[$1]]“",
        "selfmove": "Izvorni i odredišni naslovi su istovetni;\nne mogu da premestim stranicu preko same sebe.",
        "immobile-source-namespace": "Ne mogu da premestim stranice u imenskom prostoru „$1“",
-       "immobile-target-namespace": "Ne mogu da premestim stranice u imenskom prostoru â\80\9e$1â\80\9d",
+       "immobile-target-namespace": "Ne mogu da premestim stranice u imenskom prostoru â\80\9e$1â\80\9c",
        "immobile-target-namespace-iw": "Međuviki veza nije ispravno odredište za premeštanje stranice.",
        "immobile-source-page": "Ova stranica se ne može premestiti.",
        "immobile-target-page": "Ne mogu da premestim na željeni naslov.",
        "import": "Uvoz stranica",
        "importinterwiki": "Međuviki uvoz",
        "import-interwiki-text": "Izaberite viki i naslov stranice za uvoz.\nDatumi i imena urednika će biti sačuvani.\nSve radnje pri uvozu s drugih vikija su zabeležene u [[Special:Log/import|dnevniku uvoza]].",
-       "import-interwiki-source": "Izvor vikija/stranice:",
-       "import-interwiki-history": "Umnoži sve izmene ove stranice",
+       "import-interwiki-history": "Kopiraj sve verzije istorije za ovu stranicu",
        "import-interwiki-templates": "Uključi sve šablone",
        "import-interwiki-submit": "Uvezi",
        "import-interwiki-namespace": "Odredišni imenski prostor:",
        "import-rootpage-nosubpage": "Imenski prostor „$1“ osnovne stranice ne dozvoljava podstranice.",
        "importlogpage": "Dnevnik uvoza",
        "importlogpagetext": "Administrativni uvozi stranica s istorijama izmena s drugih vikija.",
-       "import-logentry-upload": "{{GENDER:|je uvezao|je uvezla|uvede}} „[[$1]]“ otpremanjem datoteke",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|izmena|izmene|izmena}}",
-       "import-logentry-interwiki": "premešteno s drugog vikija: $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|izmena|izmene|izmena}} od $2",
+       "import-logentry-upload": "je uvezao [[$1]] otpremanjem datoteke",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|izmena uvezena|izmene uvezene|izmena uvezeno}}",
+       "import-logentry-interwiki": "je uvezao $1 s drugog vikija",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|izmena uvezena|izmene uvezene|izmena uvezeno}} iz $2",
        "javascripttest": "Javaskript test",
        "javascripttest-title": "Izvršavanje testova za $1",
        "javascripttest-pagetext-noframework": "Ova stranica je rezervisana za izvršavanje javaskript testova.",
        "tooltip-undo": "Poništava ovu izmenu i otvara obrazac za uređivanje.",
        "tooltip-preferences-save": "Sačuvaj postavke",
        "tooltip-summary": "Unesite kratak opis",
-       "common.css": "/** CSS postavljen ovde će se odraziti na sve teme */",
+       "common.css": "/* CSS postavljen ovde će se odraziti na sve teme */",
        "print.css": "/* CSS postavljen ovde će uticati na izdanje za štampu */",
        "noscript.css": "/* CSS postavljen ovde će uticati na sve korisnike kojima je onemogućen javaskript */",
        "group-autoconfirmed.css": "/* CSS postavljen ovde će uticati na samopotvrđene korisnike */",
        "rcpatroldisabled": "Patroliranje skorašnjih izmena je onemogućeno",
        "rcpatroldisabledtext": "Patroliranje skorašnjih izmena je onemogućeno.",
        "markedaspatrollederror": "Ne mogu da označim kao patrolirano",
-       "markedaspatrollederrortext": "Morate izabrati izmenu da biste je označili kao pregledanu.",
+       "markedaspatrollederrortext": "Morate izabrati izmenu da biste je označili kao patroliranu.",
        "markedaspatrollederror-noautopatrol": "Ne možete da označite svoje izmene kao patrolirane.",
        "markedaspatrollednotify": "Ova izmena na stranici „$1“ je označena kao patrolirana.",
        "markedaspatrollederrornotify": "Označavanje ove stranice patroliranom nije uspelo.",
        "exif-isospeedratings": "ISO osetljivost na svetlo",
        "exif-shutterspeedvalue": "Brzina zatvarača",
        "exif-aperturevalue": "Otvor blende",
-       "exif-brightnessvalue": "Osvetljenost",
+       "exif-brightnessvalue": "APEX osvetljenost",
        "exif-exposurebiasvalue": "Kompenzacija ekspozicije",
        "exif-maxaperturevalue": "Najveći broj otvora blende",
        "exif-subjectdistance": "Udaljenost do objekta",
        "scarytranscludefailed-httpstatus": "[Ne mogu da preuzmem šablon $1: HTTP $2]",
        "scarytranscludetoolong": "[URL adresa je predugačka]",
        "deletedwhileediting": "<strong>Upozorenje</strong>: ova stranica je obrisana nakon što ste počeli s uređivanjem!",
-       "confirmrecreate": "[[User:$1|$1]] ([[User talk:$1|razgovor]]) {{GENDER:$1|je obrisao|je obrisala|je obrisao}} ovu stranicu nakon što ste počeli da je uređujete iz sledećeg razloga:\n: ''$2''\nPotvrdite da stvarno želite da napravite stranicu.",
+       "confirmrecreate": "Korisnik [[User:$1|$1]] ([[User talk:$1|razgovor]]) je obrisao ovu stranicu nakon što ste počeli da je uređujete iz sledećeg razloga:\n: <em>$2</em>\nPotvrdite da stvarno želite da napravite stranicu.",
        "confirmrecreate-noreason": "Korisnik [[User:$1|$1]] ([[User talk:$1|razgovor]]) je obrisao ovu stranicu nakon što ste počeli da ga uređujete. Potvrdite da stvarno želite da ponovo napravite ovu stranicu.",
        "recreate": "Ponovo napravi",
        "unit-pixel": "px",
        "table_pager_limit_submit": "Idi",
        "table_pager_empty": "Nema rezultata",
        "autosumm-blank": "Uklonjen celokupan sadržaj stranice",
-       "autosumm-replace": "Zamena sadržaja stranice sa „$1“",
+       "autosumm-replace": "Zamenjen sadržaj stranice sa „$1“",
        "autoredircomment": "Preusmerenje na [[$1]]",
        "autosumm-new": "Nova stranica: $1",
+       "autosumm-newblank": "Napravljena prazna stranica",
        "size-bytes": "$1 B",
        "size-kilobytes": "$1 kB",
        "size-megabytes": "$1 MB",
        "watchlistedit-normal-legend": "Uklanjanje naslova sa spiska nadgledanja",
        "watchlistedit-normal-explain": "Naslovi na vašem spisku nadgledanja su prikazani ispod.\nDa biste uklonili naslov, označite kućicu do njega i kliknite na „{{int:Watchlistedit-normal-submit}}“.\nMožete i da [[Special:EditWatchlist/raw|uredite sirov spisak]].",
        "watchlistedit-normal-submit": "Ukloni naslove",
-       "watchlistedit-normal-done": "{{PLURAL:$1|Jedna stranica je uklonjena|$1 stranice su uklonjene|$1 stranica je uklonjeno}} s vašeg spiska nadgledanja:",
+       "watchlistedit-normal-done": "{{PLURAL:$1|1=Jedna stranica je uklonjena|$1 stranice su uklonjene|$1 stranica je uklonjeno}} s vašeg spiska nadgledanja:",
        "watchlistedit-raw-title": "Izmeni sirov spisak nadgledanja",
        "watchlistedit-raw-legend": "Izmeni sirov spisak nadgledanja",
        "watchlistedit-raw-explain": "Naslovi sa spiska nadgledanja su prikazani ispod i mogu se uređivati dodavanjem ili uklanjanjem stavki sa spiska;\njedan naslov po redu.\nKada završite, kliknite na „{{int:Watchlistedit-raw-submit}}“.\nMožete da [[Special:EditWatchlist|koristite i običan uređivač]].",
        "watchlistedit-raw-titles": "Naslovi:",
        "watchlistedit-raw-submit": "Ažuriraj spisak",
        "watchlistedit-raw-done": "Vaš spisak nadgledanja je ažuriran.",
-       "watchlistedit-raw-added": "{{PLURAL:$1|Dodat je jedan naslov|Dodata su $1 naslova|Dodato je $1 naslova}}:",
+       "watchlistedit-raw-added": "{{PLURAL:$1|1=Dodat je jedan naslov|Dodata su $1 naslova|Dodato je $1 naslova}}:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1 naslov je uklonjen|Uklonjena su $1 naslova|Uklonjeno je $1 naslova}}:",
        "watchlistedit-clear-title": "Isprazni spisak nadgledanja",
        "watchlistedit-clear-legend": "Isprazni spisak nadgledanja",
        "duplicate-defaultsort": "'''Upozorenje:''' podrazumevani ključ svrstavanja „$2“ menja nekadašnji ključ „$1“.",
        "version": "Verzija",
        "version-extensions": "Instalirana proširenja",
-       "version-skins": "Teme",
+       "version-skins": "Instalirane teme",
        "version-specialpages": "Posebne stranice",
        "version-parserhooks": "Kuke raščlanjivača",
        "version-variables": "Promenljive",
        "logentry-delete-delete": "$1 je {{GENDER:$2|obrisao|obrisala}} stranicu $3",
        "logentry-delete-restore": "$1 je {{GENDER:$2|vratio|vratila}} stranicu $3",
        "logentry-delete-event": "$1 je {{GENDER:$2|promenio|promenila}} vidljivost {{PLURAL:$5|događaja|$5 daogađaja}} u dnevniku na $3: $4",
-       "logentry-delete-revision": "$1 je {{GENDER:$2|promenio|promenila}} vidljivost {{PLURAL:$5|izmene|$5 izmena}} na stranici $3: $4",
+       "logentry-delete-revision": "$1 je {{GENDER:$2|promenio|promenila}} vidljivost $5 {{PLURAL:$5|1=izmene|izmene|izmena}} na stranici $3: $4",
        "logentry-delete-event-legacy": "$1 je {{GENDER:$2|promenio|promenila}} vidljivost događaja u dnevniku na $3",
        "logentry-delete-revision-legacy": "$1 je {{GENDER:$2|promenio|promenila}} vidljivost izmena na stranici $3",
        "logentry-suppress-delete": "$1 je {{GENDER:$2|potisnuo|potisnula}} stranicu $3",
        "logentry-move-move_redir": "$1 je {{GENDER:$2|premestio|premestila}} stranicu $3 na $4 preko preusmerenja",
        "logentry-move-move_redir-noredirect": "$1 je {{GENDER:|premestio|premestila}} stranicu $3 na $4 preko preusmerenja bez ostavljanja preusmerenja",
        "logentry-patrol-patrol": "$1 je {{GENDER:$2|označio|označila}} izmenu $4 stranice $3 kao patroliranu",
-       "logentry-patrol-patrol-auto": "$1 je automatski {{GENDER:$2|označio|označila}} izmenu $4 stranice $3 kao pregledanu",
+       "logentry-patrol-patrol-auto": "$1 je automatski {{GENDER:$2|označio|označila}} izmenu $4 stranice $3 kao patroliranu",
        "logentry-newusers-newusers": "$1 je {{GENDER:$2|otvorio|otvorila}} korisnički nalog",
        "logentry-newusers-create": "$1 je {{GENDER:$2|otvorio|otvorila}} korisnički nalog",
        "logentry-newusers-create2": "$1 je {{GENDER:$2|otvorio|otvorila}} korisnički nalog $3",
        "expand_templates_remove_comments": "Ukloni komentare",
        "expand_templates_remove_nowiki": "Poništava efekat <nowiki> tagova u prikazu članaka",
        "expand_templates_generate_xml": "Prikaži XML stablo",
-       "expand_templates_preview": "Prikaz"
+       "expand_templates_preview": "Prikaz",
+       "right-pagelang": "menjanje jezika stranice"
 }
index 6178e4c..8cc2bbd 100644 (file)
        "talkpagelinktext": "Taki",
        "specialpage": "Spesrutu papira",
        "personaltools": "Mi eigi wrokosani",
-       "postcomment": "Poti wan boskopu",
        "articlepage": "Luku a papira",
        "talk": "Taki",
        "views": "Views",
        "yourdomainname": "Yu domein:",
        "login": "Psa kon",
        "nav-login-createaccount": "Psa kon / meki wan account",
-       "loginprompt": "Yu musu man kisi cookies fu man psa kon na {{SITENAME}}.",
        "userlogin": "Psa kon / meki wan account",
        "logout": "Psa gwe",
        "userlogout": "Psa gwe",
        "fileuploadsummary": "Infrumasi:",
        "uploadwarning": "Atessi fu uploti",
        "savefile": "Gefre oponaki",
-       "uploadedimage": "lai \"[[$1]]\" poti",
-       "overwroteimage": "abi wan nyun si fu \"[[$1]]\" e uploti",
        "watchthisupload": "Disi papira si",
        "license-nopreview": "(No fusi)",
        "listfiles_search_for": "Suku na gefre:",
index d229fba..edfbeb0 100644 (file)
        "talkpagelinktext": "Diskussion",
        "specialpage": "Spezioalsiede",
        "personaltools": "Persöönelke Reewen",
-       "postcomment": "Näi Stuk",
        "articlepage": "Siede",
        "talk": "Diskussion",
        "views": "Anwiesengen",
        "externaldberror": "Äntweeder deer lait n Failer bie ju externe Authentifizierenge foar, of du duurst din extern Benutzerkonto nit aktualisierje.",
        "login": "Anmäldje",
        "nav-login-createaccount": "Anmäldje",
-       "loginprompt": "Uum sik bie {{SITENAME}} anmäldje tou konnen, mouten Cookies aktivierd weese.",
        "userlogin": "Anmäldje / Benutserkonto moakje",
        "userloginnocreate": "Anmäldje",
        "logout": "Oumäldje",
        "searchprofile-advanced-tooltip": "Säik in wiedere Noomensruume",
        "search-result-size": "$1 ({{PLURAL:$2|1 Woud|$2 Woude}})",
        "search-result-category-size": "{{PLURAL:$1|1 Siede|$1 Sieden}} ({{PLURAL:$2|1 Unnerkategorie|$2 Unnerkategorien}}, {{PLURAL:$3|1 Doatäi|$3 Doatäie}})",
-       "search-result-score": "Relevanz: $1 %",
        "search-redirect": "(Wiederlaitenge $1)",
        "search-section": "(Apsnit $1)",
        "search-suggest": "Meendest du $1?",
        "uploadwarning": "Woarskauenge",
        "uploadwarning-text": "Annerje hierunner ju Doatäibeskrieuwenge un fersäik dät nochmoal.",
        "savefile": "Doatäi spiekerje",
-       "uploadedimage": "\"[[$1]]\" hoochleeden",
-       "overwroteimage": "häd ne näie Version fon „[[$1]]“ hoochleeden",
        "uploaddisabled": "Äntskeeldigenge, dät Hoochleeden is apstuuns deaktivierd.",
        "copyuploaddisabled": "Dät Hoochleeden fon URLs is deaktivierd",
        "uploaddisabledtext": "Dät Hoochleeden fon Doatäie is nit muugelk.",
        "watchlist-details": "Jie beooboachtje {{PLURAL:$1|1 Siede|$1 Sieden}} (Diskussionssieden wuuden hier nit meetäld).",
        "wlheader-enotif": "E-Mail-Beskeed is aktivierd.",
        "wlheader-showupdated": "Sieden, do ätter dien lääste Besäik annerd wuuden sunt, wäide '''fat''' deerstoald.",
+       "wlnote": "Hier {{PLURAL:$1|foulget do lääste Annerenge|foulgje do lääste '''$1''' Annerengen}} fon do lääste {{PLURAL:$2|Uur|'''$2''' Uuren}}.",
        "wlshowlast": "Wies do lääste $1 Uuren, $2 Deege, of $3 (in do lääste 30 Deege).",
        "watchlist-options": "Anwiesoptione",
        "watching": "Beooboachtje …",
        "duplicate-defaultsort": "Paas ap: Die Sortierengskoai „$2“ uurskrift dän toufoarne ferwoanden Koai „$1“.",
        "version": "Version",
        "version-extensions": "Installierde Ärwiederengen",
+       "version-skins": "Benutseruurflächen",
        "version-specialpages": "Spezioalsieden",
        "version-parserhooks": "Parser-Hooks",
        "version-variables": "Variablen",
        "version-antispam": "Spamskuts",
-       "version-skins": "Benutseruurflächen",
        "version-other": "Uurswät",
        "version-mediahandlers": "Medien-Handlere",
        "version-hooks": "Snitsteeden ''(Hooks)''",
index 265dfe8..0002de3 100644 (file)
        "talkpagelinktext": "Obrolan",
        "specialpage": "Kaca Husus",
        "personaltools": "Parabot pribadi",
-       "postcomment": "Bagéan anyar",
        "articlepage": "Témbongkeun kaca eusi",
        "talk": "Sawala",
        "views": "Témbongan",
        "externaldberror": "Aya kasalahan dina pangkalan data oténtikasi luar, atawa anjeun mémang teu diwenangkeun pikeun ngaropéa rekening luar anjeun.",
        "login": "Asup log",
        "nav-login-createaccount": "Nyieun akun/asup log",
-       "loginprompt": "Anjeun kudu boga ''cookies'' sangkan bisa asup log ka {{SITENAME}}.",
        "userlogin": "Asup log / jieun akun",
        "userloginnocreate": "Asup log",
        "logout": "Kaluar log",
        "searchprofile-advanced-tooltip": "Paluruh di rohang ngaran anu tangtu",
        "search-result-size": "$1 ({{PLURAL:$2|1 kecap|$2 kecap}})",
        "search-result-category-size": "{{PLURAL:$1|1 anggota|$1 anggota}} ({{PLURAL:$2|1 subkatégori|$2 subkatégori}}, {{PLURAL:$3|1 berkas|$3 berkas}})",
-       "search-result-score": "Kacocogan: $1%",
        "search-redirect": "(alihan $1)",
        "search-section": "(bagean $1)",
        "search-suggest": "Meureun maksud Anjeun nyaéta: $1",
        "uploadwarning": "Pépéling ngamuat",
        "uploadwarning-text": "Ropéa pedaran berkas di handap terus cobaan deui.",
        "savefile": "Simpen koropak",
-       "uploadedimage": "ngunggah \"[[$1]]\"",
-       "overwroteimage": "Muatkeun koropak nu anyar ti \"[[$1]]\"",
        "uploaddisabled": "Punten, ngamuat ayeuna ditumpurkeun.",
        "uploaddisabledtext": "Fungsi ngamuat koropak ditumpurkeun.",
        "uploadscripted": "Koropak ieu ngandung kode HTML atawa skrip nu bisa dibaca ngaco ku panyungsi ramat (''web browser'').",
        "watchlist-details": "Aya {{PLURAL:$1|$1 kaca|$1 kaca}} nu ku anjeun diawaskeun, teu kaasup kaca obrolan/sawala.",
        "wlheader-enotif": "Pangémbar surélék difungsikeun.",
        "wlheader-showupdated": "Kaca nu robah ti panungtungan anjeun sindang ditémbongkeun kalawan '''kandel'''",
+       "wlnote": "Di handap ieu mangrupa $1 {{PLURAL:$1|robahan|robahan}} ahir salila '''$2''' jam.",
        "wlshowlast": "Témbongkeun $1 jam $2 poé $3 ahir",
        "watchlist-options": "Pilihan awaskeuneun",
        "watching": "Ngawaskeun...",
index 6dc5f90..8cdd728 100644 (file)
                        "WikiPhoenix",
                        "לערי ריינהארט",
                        "아라",
-                       "Abbedabb"
+                       "Abbedabb",
+                       "Platinawolf"
                ]
        },
        "tog-underline": "Stryk under länkar:",
-       "tog-hideminor": "Visa inte mindre redigeringar i senaste ändringar",
+       "tog-hideminor": "Dölj mindre redigeringar i senaste ändringar",
        "tog-hidepatrolled": "Dölj patrullerade redigeringar i senaste ändringar",
-       "tog-newpageshidepatrolled": "Göm patrullerade sidor från listan över nya sidor",
+       "tog-newpageshidepatrolled": "Dölj patrullerade sidor från listan över nya sidor",
        "tog-extendwatchlist": "Utöka bevakningslistan till att visa alla ändringar, inte bara den senaste",
        "tog-usenewrc": "Gruppera ändringar efter sida i senaste ändringar och bevakningslistan",
        "tog-numberheadings": "Automatisk numrerade rubriker",
@@ -75,6 +76,7 @@
        "tog-watchdefault": "Lägg till sidor och filer jag redigerar i min bevakningslista",
        "tog-watchmoves": "Lägg till sidor och filer jag flyttar i min bevakningslista",
        "tog-watchdeletion": "Lägg till sidor och filer jag raderar i min bevakningslista",
+       "tog-watchrollback": "Lägg till sidor som jag har utfört en tillbakarullning på i min övervakningslista",
        "tog-minordefault": "Markera automatiskt ändringar som mindre",
        "tog-previewontop": "Visa förhandsgranskningen ovanför redigeringsrutan",
        "tog-previewonfirst": "Visa förhandsgranskning vid första redigeringen",
        "tog-enotifrevealaddr": "Visa min e-postadress i e-postmeddelanden om ändringar som skickas till andra",
        "tog-shownumberswatching": "Visa antalet användare som bevakar",
        "tog-oldsig": "Nuvarande signatur:",
-       "tog-fancysig": " signatur som wikitext (utan en automatisk länk)",
+       "tog-fancysig": "Behandla signatur som wikitext (utan en automatisk länk)",
        "tog-uselivepreview": "Använd direktuppdaterad förhandsgranskning (experimentell)",
        "tog-forceeditsummary": "Påminn mig om jag inte fyller i en redigeringskommentar",
-       "tog-watchlisthideown": "Visa inte mina redigeringar i bevakningslistan",
+       "tog-watchlisthideown": "Dölj mina redigeringar från bevakningslistan",
        "tog-watchlisthidebots": "Visa inte robotredigeringar i bevakningslistan",
-       "tog-watchlisthideminor": "Visa inte mindre ändringar i bevakningslistan",
+       "tog-watchlisthideminor": "Dölj mindre ändringar från bevakningslistan",
        "tog-watchlisthideliu": "Visa inte redigeringar av inloggade användare i bevakningslistan",
-       "tog-watchlisthideanons": "Visa inte redigeringar av anonyma användare i bevakningslistan",
-       "tog-watchlisthidepatrolled": "Göm patrullerade redigeringar från bevakningslistan",
+       "tog-watchlisthideanons": "Dölj redigeringar av anonyma användare från bevakningslistan",
+       "tog-watchlisthidepatrolled": "Dölj patrullerade redigeringar från bevakningslistan",
        "tog-ccmeonemails": "Skicka kopior till mig av e-post jag skickar till andra användare",
        "tog-diffonly": "Visa inte sidinnehåll under diffar",
        "tog-showhiddencats": "Visa dolda kategorier",
        "tog-prefershttps": "Använd alltid en säker anslutning när jag är inloggad",
        "underline-always": "Alltid",
        "underline-never": "Aldrig",
-       "underline-default": "Webbläsarens standardinställning",
+       "underline-default": "Webbläsarens eller utseendets standardinställning",
        "editfont-style": "Typsnitt i redigeringsrutan:",
        "editfont-default": "Webbläsarens standard",
        "editfont-monospace": "Fast bredd",
        "cancel": "Avbryt",
        "moredotdotdot": "Mer...",
        "morenotlisted": "Denna lista är inte fullständig.",
-       "mypage": "Min sida",
+       "mypage": "Sida",
        "mytalk": "Diskussion",
        "anontalk": "Diskussionssida för denna IP-adress",
        "navigation": "Navigering",
        "talkpagelinktext": "Diskussion",
        "specialpage": "Specialsida",
        "personaltools": "Personliga verktyg",
-       "postcomment": "Nytt avsnitt",
        "articlepage": "Visa innehållssida",
        "talk": "Diskussion",
        "views": "Visningar",
        "otherlanguages": "På andra språk",
        "redirectedfrom": "(Omdirigerad från $1)",
        "redirectpagesub": "Omdirigeringssida",
+       "redirectto": "Omdirigering till:",
        "lastmodifiedat": "Sidan ändrades senast den $1 kl. $2.",
        "viewcount": "Den här sidan har visats {{PLURAL:$1|en gång|$1 gånger}}.",
        "protectedpage": "Skrivskyddad sida",
        "editsectionhint": "Redigera avsnitt: $1",
        "toc": "Innehåll",
        "showtoc": "visa",
-       "hidetoc": "göm",
+       "hidetoc": "dölj",
        "collapsible-collapse": "Dölj",
        "collapsible-expand": "Visa",
+       "confirmable-confirm": "Är {{GENDER:$1|du}} säker?",
+       "confirmable-yes": "Ja",
+       "confirmable-no": "Nej",
        "thisisdeleted": "Visa eller återställ $1?",
        "viewdeleted": "Visa $1?",
        "restorelink": "{{PLURAL:$1|en raderad version|$1 raderade versioner}}",
        "invalidtitle-knownnamespace": "Ogiltig titel med namnrymden \"$2\" och texten \"$3\"",
        "invalidtitle-unknownnamespace": "Ogiltig titel med okänt namnrymdsnummer $1 och texten \"$2\"",
        "exception-nologin": "Inte inloggad",
-       "exception-nologin-text": "Var god [[Special:Userlogin|logga in]] för att komma åt denna sida eller åtgärd.",
+       "exception-nologin-text": "Var god logga in för att komma åt denna sida eller åtgärd.",
        "exception-nologin-text-manual": "Var god $1 för att få tillgång till denna sida eller åtgärd.",
        "virus-badscanner": "Dålig konfigurering: okänd virusskanner: ''$1''",
        "virus-scanfailed": "skanning misslyckades (kod $1)",
        "externaldberror": "Antingen inträffade autentiseringsproblem med en extern databas, eller så får du inte uppdatera ditt externa konto.",
        "login": "Logga in",
        "nav-login-createaccount": "Logga in / skapa konto",
-       "loginprompt": "Du måste tillåta kakor för att logga in på {{SITENAME}}.",
        "userlogin": "Logga in / skapa konto",
        "userloginnocreate": "Logga in",
        "logout": "Logga ut",
        "userlogin-resetlink": "Har du glömt dina inloggningsuppgifter?",
        "userlogin-resetpassword-link": "Glömt ditt lösenord?",
        "userlogin-helplink2": "Hjälp med inloggning",
-       "userlogin-loggedin": "Du är redan inloggad som {{GENDER:$1|$1}}.\nAnvänd formuläret nedan för att logga in som en annan användare.",
-       "userlogin-createanother": "Skapa ett annat konto",
        "createacct-emailrequired": "E-postadress",
        "createacct-emailoptional": "E-postadress (valfritt)",
        "createacct-email-ph": "Bekräfta din e-postadress",
        "createaccount-text": "Någon har skapat ett konto åt din e-postadress på {{SITENAME}} ($4) med namnet \"$2\" och lösenordet \"$3\". Du bör nu logga in och ändra ditt lösenord.\n\nDu kan ignorera detta meddelande om kontot skapats av misstag.",
        "login-throttled": "Du har gjort för många misslyckade inloggningsförsök.\nVänta $1 innan du försöker igen.",
        "login-abort-generic": "Din inloggning misslyckades - Avbröts",
+       "login-migrated-generic": "Dit konto har migrerats och ditt användarnamn existerar inte längre på denna wiki.",
        "loginlanguagelabel": "Språk: $1",
        "suspicious-userlogout": "Din begäran om att logga ut nekades eftersom det ser ut som det skickades av en trasig webbläsare eller cachande proxy.",
        "createacct-another-realname-tip": "Riktiga namnet är valfritt.\nOm du väljer att ange det, kommer det användas för att tillskriva användaren för sitt arbete.",
        "preview": "Förhandsgranska",
        "showpreview": "Visa förhandsgranskning",
        "showdiff": "Visa ändringar",
-       "anoneditwarning": "'''Varning:''' Du är inte inloggad.\nDin IP-adress kommer att sparas i historiken för den här sidan.",
+       "blankarticle": "<strong>Varning:</strong> Sidan du skapar är tom.\nOm du klickar på \"{{int:savearticle}}\" igen kommer sidan skapas utan något innehåll.",
+       "anoneditwarning": "<strong>Varning:</strong> Du är inte inloggad. Din IP-adress kommer att vara publikt synlig om du gör några redigeringar. Om du <strong>[$1 loggar in]</strong> eller <strong>[$2 skapar ett konto]</strong> kommer dina redigeringar att tillskrivas ditt användarnamn, tillsammans med andra fördelar.",
        "anonpreviewwarning": "''Du är inte inloggad. Om du sparar kommer din IP-adress registreras på denna sidas redigeringshistorik.''",
        "missingsummary": "'''Påminnelse:''' Du har inte skrivit någon redigeringskommentar.\nOm du klickar på \"{{int:savearticle}}\" igen, kommer din redigering att sparas utan en sådan.",
        "missingcommenttext": "Var god och skriv in en kommentar nedan.",
        "userjspreview": "'''Kom ihåg att du bara testar/förhandsgranskar ditt JavaScript.'''\n'''Det har inte sparats än!'''",
        "sitecsspreview": "'''Kom ihåg att du bara förhandsgranskar detta CSS.''' \n'''Det har ännu inte sparats!'''",
        "sitejspreview": "'''Kom ihåg att du bara förhandsgranskar denna JavaScript-kod.'''\n'''Det har ännu inte sparats!'''",
-       "userinvalidcssjstitle": "'''Varning:''' Skalet \"$1\" finns inte. Kom ihåg att .css- och .js-sidor för enskilda användare börjar på liten bokstav. Exempel: {{ns:user}}:Foo/vector.css i stället för {{ns:user}}:Foo/Vector.css.",
+       "userinvalidcssjstitle": "'''Varning:''' Utseendet \"$1\" finns inte. Kom ihåg att .css- och .js-sidor för enskilda användare börjar på liten bokstav. Exempel: {{ns:user}}:Foo/vector.css i stället för {{ns:user}}:Foo/Vector.css.",
        "updated": "(Uppdaterad)",
        "note": "'''Obs!'''",
        "previewnote": "'''Kom ihåg att detta bara är en förhandsvisning.'''\nDina ändringar har ännu inte sparats!",
        "parser-template-recursion-depth-warning": "Gräns för mallrekursionsdjup överskriden ($1)",
        "language-converter-depth-warning": "Gräns för språkkonverteringsdjup överskriden ($1)",
        "node-count-exceeded-category": "Sidor där antalet noder har överskridits",
-       "node-count-exceeded-category-desc": "En kategori för sidor där nod-räkningen överskrids.",
-       "node-count-exceeded-warning": "Sidan har överskridit antalet nodar",
+       "node-count-exceeded-category-desc": "Sidan överskrider det maximala antalet noder.",
+       "node-count-exceeded-warning": "Sidan har överskridit antalet noder",
        "expansion-depth-exceeded-category": "Sidor där expansionsdjupet överskrids",
-       "expansion-depth-exceeded-category-desc": "Detta är en kategori för sidor där expansionsdjupet överskrids.",
+       "expansion-depth-exceeded-category-desc": "Sidan har överstridit det maximala expansionsdjupet.",
        "expansion-depth-exceeded-warning": "Sidan överskrider expansionsdjupet",
        "parser-unstrip-loop-warning": "Tagavskalningsloop upptäcktes",
        "parser-unstrip-recursion-limit": "Tagavskalningsloop överskred rekursionsgränsen ($1)",
        "rev-deleted-event": "(loggåtgärd borttagen)",
        "rev-deleted-user-contribs": "[användarnamn eller IP-adress har tagits bort - redigeringen visas ej bland bidragen]",
        "rev-deleted-text-permission": "Denna version av sidan har '''raderats'''.\nDet kan finnas mer information i [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} raderingsloggen].",
+       "rev-suppressed-text-permission": "Denna version av sidan har <strong>undanhållits</strong>.\nDetaljer kan hittas i [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} undanhållandeloggen].",
        "rev-deleted-text-unhide": "Den här versionen av sidan har '''raderats'''.\nDet kan finnas mer information i [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} raderingsloggen].\nDu kan fortfarande [$1 se den här versionen] om du önskar att fortsätta.",
        "rev-suppressed-text-unhide": "Den här versionen av sidan har blivit '''undanhållen'''.\nDet kan finnas mer information i [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} undanhållandeloggen].\nDu kan fortfarande [$1 se den här versionen] om du önskar att fortsätta.",
        "rev-deleted-text-view": "Denna version av sidan har '''raderats'''.\nDu kan se den; det kan finnas mer information i [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} raderingsloggen].",
        "rev-suppressed-unhide-diff": "En av versionerna för denna diff har blivit '''undanhållen'''.\nDet kan finnas detaljer i [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} undanhållandeloggen].\nDu kan fortfarande [$1 se denna diff] om du önskar fortsätta.",
        "rev-deleted-diff-view": "En av sidversionerna i denna diff har '''raderats'''.\nDu kan se denna diff; mer information kan finnas i [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} raderingsloggen].",
        "rev-suppressed-diff-view": "En av versionerna för denna diff har blivit '''undanhållen'''.\nDu kan se denna diff; detaljer kan finnas i [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} undanhållandeloggen].",
-       "rev-delundel": "visa/göm",
+       "rev-delundel": "ändra synlighet",
        "rev-showdeleted": "visa",
        "revisiondelete": "Ta bort/återställ versioner",
        "revdelete-nooldid-title": "Ogiltig målversion",
-       "revdelete-nooldid-text": "Antingen har du inte angivit någon sidversion att utföra funktionen på,\neller så finns inte den version du angav,\neller så försöker du gömma den senaste versionen av sidan.",
+       "revdelete-nooldid-text": "Antingen har du inte angivit någon sidversion att utföra funktionen på, eller så finns inte den version du angav,\neller så försöker du dölja den senaste versionen av sidan.",
        "revdelete-no-file": "Den specificerade filen finns inte.",
        "revdelete-show-file-confirm": "Är du säker på att du vill visa en raderad version av filen \"<nowiki>$1</nowiki>\" från den $2 klockan $3?",
        "revdelete-show-file-submit": "Ja",
        "revdelete-text-text": "Raderade sidversioner kommer fortfarande synas i sidans historik, men delar av innehållet kommer inte att bli tillgängligt offentligt.",
        "revdelete-text-file": "Raderade filversioner kommer fortfarande synas i filens historik, men delar av innehållet kommer inte att bli tillgängligt offentligt.",
        "logdelete-text": "Raderade logghändelser kommer fortfarande synas i loggarna, men delar av innehållet kommer inte att bli tillgängligt offentligt.",
-       "revdelete-text-others": "Andra administratörer på {{SITENAME}} kommer fortfarande att kunna komma åt det dolda innehållet och återställa det igen genom samma gränssnitt om inte tilläggande begränsningar används.",
+       "revdelete-text-others": "Andra administratörer kommer fortfarande att kunna komma åt det dolda innehållet och återställa det igen om inte ytterligare begränsningar används.",
        "revdelete-confirm": "Var god bekräfta att du vill göra detta, och att du förstår konsekvenserna, och att du gör så i enlighet med [[{{MediaWiki:Policy-url}}|policyn]].",
        "revdelete-suppress-text": "Undanhållande ska '''bara''' användas i följande fall:\n* Eventuell förolämpande information\n* Opassande personlig information\n*: ''hemadresser och telefonnummer, personnummer, etc.''",
        "revdelete-legend": "Ändra synlighet",
        "searchprofile-advanced-tooltip": "Sök i vissa namnrymder",
        "search-result-size": "$1 ({{PLURAL:$2|1 ord|$2 ord}})",
        "search-result-category-size": "{{PLURAL:$1|1 medlem|$1 medlemmar}} ({{PLURAL:$2|1 underkategori|$2 underkategorier}}, {{PLURAL:$3|1 fil|$3 filer}})",
-       "search-result-score": "Relevans: $1%",
        "search-redirect": "(omdirigering $1)",
        "search-section": "(avsnitt $1)",
        "search-file-match": "(överensstämmer filens innehåll)",
        "searchall": "alla",
        "showingresults": "Nedan visas upp till {{PLURAL:$1|'''1''' post|'''$1''' poster}} från och med nummer '''$2'''.",
        "showingresultsinrange": "Nedan visas upp till {{PLURAL:$3|<strong>1</strong> resultat|<strong>$1</strong> resultat}} mellan nummer <strong>$2</strong> och nummer <strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Resultat '''$1''' av '''$3'''|Resultat '''$1 - $2''' av '''$3'''}} för '''$4'''",
+       "search-showingresults": "{{PLURAL:$4|Resultat <strong>$1</strong> av <strong>$3</strong>|Resultat <strong>$1 – $2</strong> av <strong>$3</strong>}}",
        "search-nonefound": "Inga resultat matchade frågan.",
        "powersearch-legend": "Avancerad sökning",
        "powersearch-ns": "Sök i namnrymderna:",
        "preferences": "Inställningar",
        "mypreferences": "Inställningar",
        "prefs-edits": "Antal redigeringar:",
-       "prefsnologintext2": "Var god $1 för att ändra användarinställningar.",
+       "prefsnologintext2": "Var god logga in för att ändra dina inställningar.",
        "prefs-skin": "Utseende",
        "skin-preview": "Förhandsvisning",
        "datedefault": "Ovidkommande",
        "prefs-files": "Filer",
        "prefs-custom-css": "personlig CSS",
        "prefs-custom-js": "personlig JavaScript",
-       "prefs-common-css-js": "Delad CSS/JS för alla teman:",
+       "prefs-common-css-js": "Delad CSS/JS för alla utseenden:",
        "prefs-reset-intro": "Du kan använda den här sidan till att återställa dina inställningar till webbplatsens standardinställningar.\nDetta kan inte återställas.",
        "prefs-emailconfirm-label": "E-postbekräftelse:",
        "youremail": "E-post:",
        "right-deletedtext": "Visa raderad text och ändringar mellan raderade versioner",
        "right-browsearchive": "Sök efter raderade sidor",
        "right-undelete": "Återställ raderade sidor",
-       "right-suppressrevision": "Se och återställa sidversioner som dolts för administratörer",
+       "right-suppressrevision": "Se, dölj och ta fram specifika sidversioner som dolts för alla användare",
+       "right-viewsuppressed": "Se sidversioner som dolts från alla användare",
        "right-suppressionlog": "Se privata loggar",
        "right-block": "Blockera andra användare från att redigera",
        "right-blockemail": "Blockera användare från att skicka e-post",
-       "right-hideuser": "Blockera användarnamn och dölja det från blockeringsloggen",
+       "right-hideuser": "Blockera ett användarnamn och dölja det från allmänheten",
        "right-ipblock-exempt": "Kan redigera från blockerade IP-adresser",
        "right-proxyunbannable": "Kan redigera från blockerade proxyer",
        "right-unblockself": "Avblockera sig själv",
        "recentchanges-legend-heading": "'''Teckenförklaring:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (se även [[Special:NewPages|listan över nya sidor]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Nedan visas ändringar sedan <strong>$2</strong> (upp till <strong>$1</strong> ändringar visas).",
+       "rcnotefrom": "Nedan visas {{PLURAL:$5|ändringar|ändringen}} sedan <strong>$3, $4</strong> (upp till <strong>$1</strong> ändringar visas).",
        "rclistfrom": "Visa ändringar från och med $3 $2",
        "rcshowhideminor": "$1 mindre ändringar",
        "rcshowhideminor-show": "Visa",
        "rclinks": "Visa senaste $1 ändringar under de senaste $2 dygnen<br />$3",
        "diff": "skillnad",
        "hist": "historik",
-       "hide": "Göm",
+       "hide": "Dölj",
        "show": "Visa",
        "minoreditletter": "m",
        "newpageletter": "N",
        "rc-change-size-new": "$1 {{PLURAL:$1|byte}} efter ändring",
        "newsectionsummary": "/* $1 */ nytt avsnitt",
        "rc-enhanced-expand": "Visa detaljer",
-       "rc-enhanced-hide": "Göm detaljer",
+       "rc-enhanced-hide": "Dölj detaljer",
        "rc-old-title": "skapades ursprungligen som \"$1\"",
        "recentchangeslinked": "Relaterade ändringar",
        "recentchangeslinked-feed": "Relaterade ändringar",
        "uploadwarning": "Uppladdningsvarning",
        "uploadwarning-text": "Var god och ändra filbeskrivningen nedanför och försök igen.",
        "savefile": "Spara fil",
-       "uploadedimage": "laddade upp \"[[$1]]\"",
-       "overwroteimage": "laddade upp ny version av \"[[$1]]\"",
        "uploaddisabled": "Uppladdningsfunktionen är avstängd",
        "copyuploaddisabled": "Uppladdning med URL avstängt.",
        "uploaddisabledtext": "Uppladdning av filer är avstängd.",
        "license": "Licens:",
        "license-header": "Licensiering",
        "nolicense": "Ingen angiven",
+       "licenses-edit": "Redigera licensalternativ",
        "license-nopreview": "(Förhandsvisning är inte tillgänglig)",
-       "upload_source_url": " (en giltig URL som är allmänt åtkomlig)",
-       "upload_source_file": " (en fil på din dator)",
+       "upload_source_url": "(din valda fil från en giltig webbadress som är allmänt åtkomlig)",
+       "upload_source_file": "(din valda fil från din dator)",
+       "listfiles-delete": "radera",
        "listfiles-summary": "Den här specialsidan visar alla filer som laddats upp.",
        "listfiles_search_for": "Sök efter filnamn:",
        "imgfile": "fil",
        "randomincategory": "Slumpsida i kategori",
        "randomincategory-invalidcategory": "\"$1\" är inte ett giltigt kategorinamn.",
        "randomincategory-nopages": "Det finns inga sidor i kategorin [[:Category:$1]].",
-       "randomincategory-selectcategory": "Få slumpsida från kategori: $1 $2.",
-       "randomincategory-selectcategory-submit": "Gå",
+       "randomincategory-category": "Kategori:",
+       "randomincategory-legend": "Slumpsida i kategori",
        "randomredirect": "Slumpmässig omdirigering",
        "randomredirect-nopages": "Det finns inte några omdirigeringar i namnrymden \"$1\".",
        "statistics": "Statistik",
        "wantedpages-badtitle": "Ogiltig titel bland resultaten: $1",
        "wantedfiles": "Önskade filer",
        "wantedfiletext-cat": "Följande filer används men finns inte. Filer från utländska databaser kan vara listade trots att de inte finns. Sådana falska realiteter kommer att <del>tas bort</del>. Sidor som bäddar in filer som inte finns listas upp på [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Följande filer används men finns inte. Sidor som bäddar in filer som inte finns listas i [[:$1]].",
        "wantedfiletext-nocat": "Följande filer används men finns inte. Filer från utländska databaser kan vara listade trots att de inte finns. Sådana falska realiteter kommer att <del>tas bort</del>.",
+       "wantedfiletext-nocat-noforeign": "Följande filer används men finns inte.",
        "wantedtemplates": "Önskade mallar",
        "mostlinked": "Sidor med flest länkar till sig",
        "mostlinkedcategories": "Kategorier med flest länkar till sig",
        "protectedpages-timestamp": "Tidsstämpel",
        "protectedpages-page": "Sida",
        "protectedpages-expiry": "Upphör",
-       "protectedpages-performer": "Skyddar användare",
+       "protectedpages-performer": "Skyddande användare",
        "protectedpages-params": "Skyddsparametrar",
        "protectedpages-reason": "Anledning",
        "protectedpages-unknown-timestamp": "Okänd",
        "allpagesprefix": "Visa sidor med prefixet:",
        "allpagesbadtitle": "Den angivna sidtiteln var ogiltig eller innehöll ett prefix för annan språkversion eller ett interwiki-prefix.\nDen kan innehålla en eller fler tecken som inte är tillåtna i titlar.",
        "allpages-bad-ns": "Namnrymden \"$1\" finns inte på {{SITENAME}}.",
-       "allpages-hide-redirects": "Göm omdirigeringar",
+       "allpages-hide-redirects": "Dölj omdirigeringar",
        "cachedspecial-viewing-cached-ttl": "Du visar en cachad version av denna sida, som kan vara upp till $1 gammal.",
        "cachedspecial-viewing-cached-ts": "Du visar en cachad version av denna sida, som kanske inte är helt aktuell.",
        "cachedspecial-refresh-now": "Visa senaste.",
        "trackingcategories-desc": "Inklusionskriterier för kategori",
        "noindex-category-desc": "Sidan innehåller det magiska ordet <code><nowiki>__NOINDEX__</nowiki></code> (och är i en namnrymd där denna flagga tillåts), och indexeras därför inte av robotar.",
        "index-category-desc": "Denna sidan innehåller ett <code><nowiki>__INDEX__</nowiki></code> (och är i en namnrymd där denna flagga tillåts), och indexeras därför av robotar även där detta normalt inte skulle ske.",
-       "post-expand-template-inclusion-category-desc": "Efter att alla mallar har expanderats är denna sidan större än <code>$wgMaxArticleSize</code>, därför har vissa mallar inte expanderats.",
-       "post-expand-template-argument-category-desc": "Efter att ett mallargument (något inom trippla parenteser, som <code>{{{Foo}}})</code> expanderats är denna sidan större än <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "För många kostsamma parser-funktioner (som <code>#ifexist</code>) har inkluderats på en sida. Se [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit användarhandboken].",
-       "broken-file-category-desc": "Kategori som läggs till om sidan innehåller en bruten fillänk (en länk som bäddar in en fil som inte finns).",
-       "hidden-category-category-desc": "Detta är en kategori som innehåller <code><nowiki>__HIDDENCAT__</nowiki></code> vilket, som standard, förhindrar den från att visas i kategorirutan.",
+       "post-expand-template-inclusion-category-desc": "Sidan är större än <code>$wgMaxArticleSize</code> efter att alla mallar har expanderats, därför har vissa mallar inte expanderats.",
+       "post-expand-template-argument-category-desc": "Sidan är större än <code>$wgMaxArticleSize</code> efter att ett mallargument (någonting inom tre parenteser, som <code>{{{Foo}}}</code>) expanderats.",
+       "expensive-parserfunction-category-desc": "Sidan använder för många kostsamma parser-funktioner (som <code>#ifexist</code>). Se [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit användarhandboken].",
+       "broken-file-category-desc": "Sidan innehåller en trasig fillänk (en länk som bäddar in en fil som inte finns).",
+       "hidden-category-category-desc": "Kategorin innehåller <code><nowiki>__HIDDENCAT__</nowiki></code> i dess kategori, vilket som standard förhindrar den från att visas i kategorirutan.",
        "trackingcategories-nodesc": "Ingen beskrivning tillgänglig.",
        "trackingcategories-disabled": "Kategorin är inaktiverad",
        "mailnologin": "Ingen adress att skicka till",
        "mywatchlist": "Bevakningslista",
        "watchlistfor2": "För $1 $2",
        "nowatchlist": "Du har inga sidor i din bevakningslista.",
-       "watchlistanontext": "Du måste $1 för att se eller redigera din bevakningslista.",
+       "watchlistanontext": "Du måste logga in för att se eller redigera din bevakningslista.",
        "watchnologin": "Inte inloggad",
        "addwatch": "Lägg till i bevakningslistan",
        "addedwatchtext": "Sidan \"[[:$1]]\" har lagts till på din [[Special:Watchlist|bevakningslista]].\nFramtida ändringar av den här sidan och dess diskussionssida kommer att listas där.",
        "watchlist-details": "Du har {{PLURAL:$1|en sida|$1 sidor}} på din bevakningslista (diskussionssidor är inte separat medräknade).",
        "wlheader-enotif": "E-postmeddelanden är aktiverade.",
        "wlheader-showupdated": "Sidor som har ändrats sedan ditt senaste besök visas i '''fetstil.'''",
-       "wlnote2": "Nedan finns ändringarna från {{PLURAL:$1|den senaste timmen|de senaste <strong>$1</strong> timmarna}}, med början den $2 kl. $3.",
+       "wlnote": "Nedan finns {{PLURAL:$1|den senaste ändringen|de senaste <strong>$1</strong> ändringarna}} under {{PLURAL:$2|den senaste timmen|de senaste <strong>$2</strong> timmarna}} från den $3 kl. $4.",
        "wlshowlast": "Visa senaste $1 timmarna $2 dygnen $3",
        "watchlist-options": "Alternativ för bevakningslistan",
        "watching": "Bevakar...",
        "exbeforeblank": "innehåll före tömning var: \"$1\"",
        "delete-confirm": "Radera \"$1\"",
        "delete-legend": "Radera",
-       "historywarning": "'''Varning:''' Sidan du håller på att radera har en historik med ungefär $1 {{PLURAL:$1|version|versioner}}:",
+       "historywarning": "<strong>Varning:</strong> Sidan du håller på att radera har en historik med ungefär $1 {{PLURAL:$1|version|versioner}}:",
        "confirmdeletetext": "Du håller på att ta bort en sida med hela dess historik.\nBekräfta att du förstår vad du håller på med och vilka konsekvenser detta leder till, och att du följer [[{{MediaWiki:Policy-url}}|riktlinjerna]].",
        "actioncomplete": "Genomfört",
        "actionfailed": "Handlingen misslyckades",
        "delete-edit-reasonlist": "Redigera anledningar för radering",
        "delete-toobig": "Denna sida har en lång redigeringshistorik med mer än $1 {{PLURAL:$1|sidversion|sidversioner}}. Borttagning av sådana sidor har begränsats för att förhindra oavsiktliga driftstörningar på {{SITENAME}}.",
        "delete-warning-toobig": "Denna sida har en lång redigeringshistorik med mer än $1 {{PLURAL:$1|sidversion|sidversioner}}. Att radera sidan kan skapa problem med hanteringen av databasen på {{SITENAME}}; var försiktig.",
+       "deleteprotected": "Du kan inte radera denna sida eftersom den är skyddad.",
        "deleting-backlinks-warning": "'''Varning:'''\n[[Special:WhatLinksHere/{{FULLPAGENAME}}|Andra sidor]] länkar till eller inkluderar sidan som du är på väg att radera.",
        "rollback": "Rulla tillbaka ändringar",
        "rollback_short": "Tillbakarullning",
        "autoblockid": "Autoblockera #$1",
        "block": "Blockera användare",
        "unblock": "Upphäv blockering av användare",
-       "blockip": "Blockera användare",
+       "blockip": "Blockera {{GENDER:$1|användare}}",
        "blockip-legend": "Blockera användare",
        "blockiptext": "Använd formuläret nedan för att blockera möjligheten att redigera sidor från en specifik IP-adress eller ett användarnamn.\nDetta bör endast göras för att förhindra vandalisering, och i överensstämmelse med gällande [[{{MediaWiki:Policy-url}}|policy]].\nAnge orsak nedan (exempelvis genom att nämna sidor som blivit vandaliserade).",
        "ipaddressorusername": "IP-adress eller användarnamn:",
        "blockipsuccesssub": "Blockeringen är utförd",
        "blockipsuccesstext": "[[Special:Contributions/$1|$1]] har blockerats.<br />\nFör att se alla aktuella blockeringar, gå till [[Special:BlockList|listan över blockeringar]].",
        "ipb-blockingself": "Du håller på att blockera dig själv! Är du säker på att du vill göra det?",
-       "ipb-confirmhideuser": "Du är på väg att blockera en användare med \"göm användare\" aktiverat. Detta kommer upphäva användarens namn i alla listor och loggar. Är du säker på att du vill göra det?",
+       "ipb-confirmhideuser": "Du är på väg att blockera en användare med \"dölj användare\" aktiverat. Detta kommer upphäva användarens namn i alla listor och loggar. Är du säker på att du vill göra det?",
        "ipb-confirmaction": "Markera fältet \"{{int:ipb-confirm}}\" längst ned om du är säker på att du verkligen vill göra det.",
        "ipb-edit-dropdown": "Redigera blockeringsanledningar",
        "ipb-unblock-addr": "Ta bort blockering av $1",
        "ipb-unblock": "Ta bort blockering av en användare eller IP-adress",
        "ipb-blocklist": "Visa gällande blockeringar",
-       "ipb-blocklist-contribs": "Bidrag från $1",
+       "ipb-blocklist-contribs": "Bidrag från {{GENDER:$1|$1}}",
        "unblockip": "Ta bort blockering av användare/IP-adress",
        "unblockiptext": "Använd formuläret nedan för att ta bort blockeringen av en IP-adress.",
        "ipusubmit": "Upphäv denna blockering",
        "unblocked": "Blockeringen av [[User:$1|$1]] har hävts",
        "unblocked-range": "$1 har avblockerats",
        "unblocked-id": "Blockeringen $1 har hävts",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] har avblockerats.",
        "blocklist": "Blockerade användare",
        "ipblocklist": "Blockerade användare",
        "ipblocklist-legend": "Sök efter en blockerad användare",
-       "blocklist-userblocks": "Göm kontoblockeringar",
+       "blocklist-userblocks": "Dölj kontoblockeringar",
        "blocklist-tempblocks": "Dölj tillfälliga blockeringar",
-       "blocklist-addressblocks": "Göm enskilda IP-blockeringar",
-       "blocklist-rangeblocks": "Göm intervallblockeringar",
+       "blocklist-addressblocks": "Dölj enskilda IP-blockeringar",
+       "blocklist-rangeblocks": "Dölj intervallblockeringar",
        "blocklist-timestamp": "Tidsstämpel",
        "blocklist-target": "Mål",
        "blocklist-expiry": "Upphör",
        "autoblocker": "Automatisk blockerad eftersom din IP-adress nyligen använts av \"[[User:$1|$1]]\".\nMotiveringen som angavs för blockeringen av $1 var: \"$2\".",
        "blocklogpage": "Blockeringslogg",
        "blocklog-showlog": "Denna användare har blivit blockerad tidigare.\nBlockeringsloggen är tillgänglig nedan som referens:",
-       "blocklog-showsuppresslog": "Denna användare har tidigare blivit blockerad och gömd.\nUndanhållandeloggen visas nedan för referens:",
+       "blocklog-showsuppresslog": "Denna användare har tidigare blivit blockerad och dold.\nUndanhållandeloggen visas nedan för referens:",
        "blocklogentry": "blockerade [[$1]] med blockeringstid på $2 $3",
        "reblock-logentry": "ändrade blockeringsinställningar för [[$1]] med en varaktighet på $2 $3",
        "blocklogtext": "Detta är en logg över blockeringar och avblockeringar.\nAutomatiskt blockerade IP-adresser listas ej.\nSe [[Special:BlockList|blockeringslistan]] för en översikt av gällande blockeringar.",
        "block-log-flags-noemail": "e-post blockerad",
        "block-log-flags-nousertalk": "kan inte redigera sin diskussionssida",
        "block-log-flags-angry-autoblock": "utökad automatblockering aktiverad",
-       "block-log-flags-hiddenname": "användarnamn gömt",
+       "block-log-flags-hiddenname": "användarnamn dolt",
        "range_block_disabled": "Möjligheten för administratörer att blockera intervall av IP-adresser har stängts av.",
        "ipb_expiry_invalid": "Ogiltig varaktighetstid.",
        "ipb_expiry_temp": "För att dölja användarnamnet måste blockeringen vara permanent.",
        "sorbsreason": "Din IP-adress är listad som öppen proxy i den DNSBL {{SITENAME}} använder.",
        "sorbs_create_account_reason": "Din IP-adress är listad som en öppen proxy i den DNSBL som används av {{SITENAME}}.\nDu får inte skapa ett användarkonto",
        "xffblockreason": "En IP-adress i sidhuvudet X-Forwarded-For, antingen din adress eller en proxyserver som du använder, har blockerats. Den ursprungliga anledningen till blockeringen var: $1",
-       "cant-see-hidden-user": "Användaren du försöker blockera är redan blockerad och gömd. Eftersom du inte har hideuser-rättigheter, kan du inte se eller redigera användarens blockering.",
+       "cant-see-hidden-user": "Användaren du försöker blockera är redan blockerad och dold. Eftersom du inte har hideuser-rättigheter, kan du inte se eller redigera användarens blockering.",
        "ipbblocked": "Du kan inte blockera eller avblockera andra användare, eftersom du själv är blockerad",
        "ipbnounblockself": "Du har inte tillåtelse att avblockera dig själv",
        "lockdb": "Lås databas",
        "movepagetalktext": "Diskussionssidan kommer att även den automatiskt flyttas '''om inte''':\n*Det redan finns en diskussionssida som inte är tom med det nya namnet, eller\n*Du avmarkerar rutan nedan.\n\nI de fallen måste du flytta eller sammanfoga sidan manuellt, om det önskas.",
        "movearticle": "Flytta sidan:",
        "moveuserpage-warning": "'''Varning:''' Du håller på att flytta en användarsida. Observera att endast sidan kommer att flyttas och att användaren ''inte'' kommer att byta namn.",
-       "movecategorypage-warning": "<strong>Varning:</strong> Du är på väg att flytta ebn kategorisida. Observera att endast sidan kommer att flyttas och eventuella sidor i den gamla kategorin kommer <em>inte</em> att kategoriseras om till den nya kategorin.",
+       "movecategorypage-warning": "<strong>Varning:</strong> Du är på väg att flytta en kategorisida. Observera att endast sidan kommer att flyttas och eventuella sidor i den gamla kategorin kommer <em>inte</em> att kategoriseras om till den nya kategorin.",
        "movenologintext": "För att flytta en sida måste du vara registrerad användare och [[Special:UserLogin|inloggad]].",
        "movenotallowed": "Du har inte behörighet att flytta sidor på den här wikin.",
        "movenotallowedfile": "Du har inte tillåtelse att flytta filer.",
        "import": "Importera sidor",
        "importinterwiki": "Transwiki-import",
        "import-interwiki-text": "Välj en wiki och sidtitel att importera.\nVersionshistorik (datum och redaktörer) kommer att bevaras.\nAll överföring mellan wikier (transwiki) listas i  [[Special:Log/import|importloggen]].",
-       "import-interwiki-source": "Källwiki/sida:",
+       "import-interwiki-sourcewiki": "Källwiki:",
+       "import-interwiki-sourcepage": "Källsida:",
        "import-interwiki-history": "Kopiera hela versionshistoriken för denna sida",
        "import-interwiki-templates": "Inkludera alla mallar",
        "import-interwiki-submit": "Importera",
        "import-upload": "Ladda upp XML-data",
        "import-token-mismatch": "Sessionsdata har förlorats. Var god pröva igen.",
        "import-invalid-interwiki": "Kan inte importera från den angivna wikin.",
-       "import-error-edit": "Sidan \"$1\" importeras inte eftersom du inte har tillåtelse att redigera den.",
-       "import-error-create": "Sidan \"$1\" importerades inte eftersom du inte har tillåtelse att skapa den.",
-       "import-error-interwiki": "Sidan \"$1\" är inte importerad eftersom dess namn är reserverat för externa länkar (interwiki).",
-       "import-error-special": "Sidan \"$1\" är inte importerad eftersom den tillhör en särskild namnrymd som inte tillåter sidor.",
-       "import-error-invalid": "Sidan \"$1\" är inte importerad eftersom dess namn är ogiltigt.",
+       "import-error-edit": "Sidan \"$1\" blev inte importerad eftersom du inte har tillåtelse att redigera den.",
+       "import-error-create": "Sidan \"$1\" blev inte importerad eftersom du inte har tillåtelse att skapa den.",
+       "import-error-interwiki": "Sidan \"$1\" blev inte importerad eftersom dess namn är reserverat för externa länkar (interwiki).",
+       "import-error-special": "Sidan \"$1\" blev inte importerad eftersom den tillhör en särskild namnrymd som inte tillåter sidor.",
+       "import-error-invalid": "Sidan \"$1\" blev inte importerad eftersom namnet den skulle importeras till är ogiltigt på denna wiki.",
        "import-error-unserialize": "Versionen $2 av sidan \"$1\" kunde inte avserialiseras. Versionen rapporterades för att använda innehållsmodellen $3, som serialiserades som $4.",
        "import-error-bad-location": "Sidversionen $2 som använder innehållsmodellen $3 kan inte lagras på \"$1\" i denna wiki eftersom modellen inte stöds på den där sidan.",
        "import-options-wrong": "Fel {{PLURAL:$2|alternativ|alternativ}}: <nowiki>$1</nowiki>",
        "importlogpage": "Importlogg",
        "importlogpagetext": "Administrativa sidimporter med versionshistorik från andra wikier.",
        "import-logentry-upload": "importerade [[$1]] genom filuppladdning",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|version|versioner}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|version|versioner}} importerades",
        "import-logentry-interwiki": "överförde $1 mellan wikier",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|version|versioner}} från $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|version|versioner}} importerades från $2",
        "javascripttest": "JavaScript-testning",
        "javascripttest-title": "Kör $1 tester",
        "javascripttest-pagetext-noframework": "Denna sida är reserverat för att köra JavaScript-tester.",
        "tooltip-preferences-save": "Spara inställningar",
        "tooltip-summary": "Skriv en kort sammanfattning",
        "interlanguage-link-title": "$1 - $2",
-       "common.css": "/* CSS som skrivs här påverkar alla skal */",
+       "common.css": "/* CSS som skrivs här påverkar alla utseenden */",
        "print.css": "/* CSS som skrivs här kommer att påverka utskriftsversionen */",
        "noscript.css": "/* CSS som placeras här kommer att påverka användare med JavaScript inaktiverat */",
        "group-autoconfirmed.css": "/* CSS som placeras här kommer bara att påverka bekräftade användare */",
        "metadata-help": "Den här filen innehåller extrainformation som troligen lades till av en digitalkamera eller skanner när filen skapades. Om filen har modifierats kan det hända att vissa detaljer inte överensstämmer med den modifierade filen.",
        "metadata-expand": "Visa utökade detaljer",
        "metadata-collapse": "Dölj utökade detaljer",
-       "metadata-fields": "Bildens metadata-fält som är listad i detta meddelande kommer att finnas på bildsidan när metadata-tabellen är hopfälld.\nAndra kommer att gömmas som standard\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": "Bildens metadata-fält som är listad i detta meddelande kommer att finnas på bildsidan när metadata-tabellen är hopfälld.\nAndra kommer att döljas som standard\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": "Bredd",
        "exif-imagelength": "Höjd",
        "exif-bitspersample": "Bitar per komponent",
        "autosumm-replace": "Ersätter sidans innehåll med '$1'",
        "autoredircomment": "Omdirigerar till [[$1]]",
        "autosumm-new": "Skapade sidan med '$1'",
+       "autosumm-newblank": "Skapade tom sida",
        "size-bytes": "$1 byte",
        "size-kilobytes": "$1 kbyte",
        "size-megabytes": "$1 Mbyte",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|diskussion]])",
        "unknown_extension_tag": "Okänd tagg \"$1\"",
        "duplicate-defaultsort": "'''Varning:''' Standardsorteringsnyckeln \"$2\" tar över från den tidigare standardsorteringsnyckeln \"$1\".",
+       "duplicate-displaytitle": "<strong>Varning:</strong> Visningstiteln \"$2\" skriver över den tidigare visningstiteln \"$1\".",
        "version": "Version",
        "version-extensions": "Installerade programtillägg",
        "version-skins": "Installerade utseenden",
        "logentry-delete-revision": "$1 {{GENDER:$2|ändrade}} synligheten för {{PLURAL:$5|en version|$5 versioner}} på sidan $3: $4",
        "logentry-delete-event-legacy": "$1 {{GENDER:$2|ändrade}} synligheten för logghändelser på $3",
        "logentry-delete-revision-legacy": "$1 {{GENDER:$2|ändrade}} synligheten för versioner på sidan $3",
-       "logentry-suppress-delete": "$1 {{GENDER:$2|gömde}} sidan $3",
+       "logentry-suppress-delete": "$1 {{GENDER:$2|dolde}} sidan $3",
        "logentry-suppress-event": "$1 {{GENDER:$2|ändrade}} i hemlighet synligheten för {{PLURAL:$5|en logghändelse|$5 logghändelser}} på $3: $4",
        "logentry-suppress-revision": "$1 {{GENDER:$2|ändrade}} synligheten i hemlighet för {{PLURAL:$5|en version|$5 versioner}} på sidan $3: $4",
        "logentry-suppress-event-legacy": "$1 {{GENDER:$2|ändrade}} synligheten i hemlighet för logghändelser på $3",
        "logentry-rights-rights": "$1 {{GENDER:$2|ändrade}} gruppmedlemskapet för $3 från $4 till $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|ändrade}} gruppmedlemskapet för $3",
        "logentry-rights-autopromote": "$1 {{GENDER:$2|befordrades}} automatiskt från $4 till $5",
+       "logentry-upload-upload": "$1 {{GENDER:$2|laddade upp}} $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|laddade upp}} en ny version av $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|laddade upp}} $3",
        "rightsnone": "(inga)",
        "feedback-bugornote": "Om du är redo att beskriva ett tekniskt problem detaljerat, var god [$1 rapporterar en bugg].\nAnnars kan du använda det enkla formuläret nedan. Din kommentar kommer att läggas till på sidan \"[$3 $2]\", tillsammans med ditt användarnamn och vilken webbläsare du använder.",
        "feedback-subject": "Ämne:",
        "action-pagelang": "ändra sidspråket",
        "log-name-pagelang": "Språkändringslogg",
        "log-description-pagelang": "Detta är en logg över ändringar i sidspråken.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|ändrade}} sidspråket för $3 från $4 till $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|ändrade}} sidspråket för $3 från $4 till $5.",
+       "default-skin-not-found": "Ojsan! Standardutseendet för din wiki, definierad i <code dir=\"ltr\">$wgDefaultSkin</code> som <code>$1</code>, är inte tillgängligt.\n\nDin installation verkar innehålla följande utseenden. Se [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manualen: Utseendeinställningar] för information om hur dessa aktiveras och hur standard väljs.\n\n$2\n\n; Om du precis installerat MediaWiki:\n: Du installerade troligen från git, eller direkt från källkoden via någon annan metod. Detta är att förvänta. Försök att installera några utseenden från [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org:s utseendekatalog], genom att:\n:* Ladda ner [https://www.mediawiki.org/wiki/Download tarball-installeraren], som kommer med flera utseenden och tillägg. Du kan klipp-och-klistra in <code>skins/</code>-katalogen från den.\n:* Klona ett av <code>mediawiki/skins/*</code>-centralförvaren in i <code dir=\"ltr\">skins/</code>-katalogen i din MediaWiki-installation.\n: Att göra detta borde inte påverka ditt git-centralförvar om du är en MediaWiki-utvecklare.\n\n; Om du precis har uppgraderat MediaWiki:\n: MediaWiki 1.24 och nyare aktiverar ej längre automatiskt utseenden (se [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: Automatisk identifiering av utseenden]). Du kan klistra in följande rader i <code>LocalSettings.php</code> för att aktivera alla för närvarande installerade utseenden:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Om du precis har ändrat i <code>LocalSettings.php</code>:\n: Dubbelkolla namnen för utseendena för att identifiera stavfel.",
+       "default-skin-not-found-no-skins": "Ojsan! Standardutseendet för din wiki, definierad i <code>$wgDefaultSkin</code> som <code>$1</code>, är inte tillgängligt.\n\nDu har inga installerade utseenden.\n\n; Om du precis installerat eller uppdaterat MediaWiki:\n: Du installerade troligen från git, eller direkt från källkoden via någon annan metod. Detta är att förvänta. MediaWiki 1.24 och nyare inkluderar inte några utseenden i det huvudsakliga centralförvaret. Försök att installera några utseenden från [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org:s utseendekatalog], genom att:\n:* Ladda ner [https://www.mediawiki.org/wiki/Download tarball-installeraren], som kommer med flera utseenden och tillägg. Du kan klipp-och-klistra in <code dir=\"ltr\">skins/</code>-katalogen från den.\n* Klona ett av <code>mediawiki/skins/*</code>-centralförvaren in i <code>skins/</code>-katalogen i din MediaWiki-installation.\n: Att göra detta borde inte påverka ditt git-centralförvar om du är en MediaWiki-utvecklare. Se [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manualen: Utseendeinställningar] för information om hur utseenden aktiveras och hur standardutseendet väljs.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (aktiverad)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''inaktiverad''')"
 }
index 2d064c7..04b8a9b 100644 (file)
@@ -13,7 +13,8 @@
                        "Stephenwanjau",
                        "לערי ריינהארט",
                        "아라",
-                       "Baba Tabita"
+                       "Baba Tabita",
+                       "Rich Farmbrough"
                ]
        },
        "tog-underline": "Wekea mstari viungo:",
        "talkpagelinktext": "Majadiliano",
        "specialpage": "Ukurasa maalumu",
        "personaltools": "Vifaa binafsi",
-       "postcomment": "Fungu jipya",
        "articlepage": "Onyesha kurasa zilizopo",
        "talk": "Majadiliano",
        "views": "Mitazamo",
        "hidetoc": "ficha",
        "collapsible-collapse": "Kunja",
        "collapsible-expand": "Tanua",
+       "confirmable-yes": "Ndio",
+       "confirmable-no": "Habana",
        "thisisdeleted": "Tazama au rudisha $1?",
        "viewdeleted": "Tazama $1?",
        "restorelink": "{{PLURAL:$1|sahihisho lililofutwa moja|masahihisho yaliyofutwa $1}}",
        "externaldberror": "Huenda kulikuwa na hitilafu ya database au labda hauruhusiwi kubadilisha akaunti yako ya nje.",
        "login": "Ingia",
        "nav-login-createaccount": "Ingia/ sajili akaunti",
-       "loginprompt": "Lazima tarakalishi yako ipokee kuki ili uweze kuingia kwenye {{SITENAME}}.",
        "userlogin": "Ingia/ sajili akaunti",
        "userloginnocreate": "Ingia",
        "logout": "Toka",
        "searchprofile-advanced-tooltip": "Tafuta katika maeneo ya wiki utakayoyachagua",
        "search-result-size": "$1 ({{PLURAL:$2|neno 1|maneno $2}})",
        "search-result-category-size": "{{PLURAL:$1|ukurasa 1|kurasa $1}} ({{PLURAL:$2|kijamii 1|vijamii $2}}, {{PLURAL:$3|faili 1|mafaili $3}})",
-       "search-result-score": "Kiwango cha ulinganisho na ulizo: $1%",
        "search-redirect": "(elekezo toka kwa $1)",
        "search-section": "(fungu $1)",
        "search-suggest": "Je, ulitaka kutafuta: $1",
        "uploadwarning": "Ilani kuhusu kupakia",
        "uploadwarning-text": "Tafadhali ubadilishe maelezo ya faili hapo chini, halafu jaribu tena.",
        "savefile": "Hifadhi faili",
-       "uploadedimage": "ameipakia \"[[$1]]\"",
-       "overwroteimage": "alipakia toleo jipya la \"[[$1]]\"",
        "uploaddisabled": "Upakiaji umelemazwa.",
        "copyuploaddisabled": "Kupakia kwa kupitia URL kumelemazwa.",
        "uploaddisabledtext": "Upakiaji wa mafaili umelemazwa.",
        "unusedtemplateswlh": "viungo vingine",
        "randompage": "Ukurasa wa bahati",
        "randompage-nopages": "Hakuna kurasa katika {{PLURAL:$2|eneo la wiki lifuatalo|maeneo ya wiki yafuatayo}}: $1.",
-       "randomincategory-selectcategory-submit": "Nenda",
        "randomredirect": "Elekezo la bahati",
        "randomredirect-nopages": "Hakuna maelekezo katika eneo la wiki la \"$1\".",
        "statistics": "Takwimu",
        "protectedpages-cascade": "Mpangilio wa ulindaji tu",
        "protectedpagesempty": "Hakuna kurasa zinazolindwa kwa sasa kwa vigezo hivi.",
        "protectedpages-page": "Ukurasa",
+       "protectedpages-reason": "Sababu",
        "protectedpages-unknown-timestamp": "Haijulikani",
        "protectedpages-unknown-performer": "Mtumiaji asiyejulikana",
        "protectedtitles": "Majina yanayozuluiwa",
        "watchlist-details": "Unafuatilia {{PLURAL:$1|ukurasa $1|kurasa $1}} bila kuzingatia kurasa za majadiliano.",
        "wlheader-enotif": "Huduma ya kuarifu kwa barua pepe imewezeshwa.",
        "wlheader-showupdated": "Kurasa zilizobadilika tangu ulivyotembelea mara ya mwisho zinaonyeshwa katika hali ya '''kukooza'''",
+       "wlnote": "{{PLURAL:$1|is the last change|Mabadiliko '''$1''' ya}} mwisho katika {{PLURAL:$2|hour|masaa '''$2''' yaliyopita yanaonyeshwa}} chini, ilivyokuwa saa $4, tarehe $3.",
        "wlshowlast": "Onyesha kutoka masaa $1 siku $2 $3",
        "watchlist-options": "Hitiari za maangalizi",
        "watching": "Unafuatilia...",
        "allmessages-prefix": "Zichujwe kwa kiambishi awali:",
        "allmessages-language": "Lugha:",
        "allmessages-filter-submit": "Uende",
+       "allmessages-filter-translate": "Kufasiri",
        "thumbnail-more": "Kuza",
        "filemissing": "Faili halipo",
        "thumbnail_error": "Hitilafu kutengeneza picha ndogo: $1",
        "import": "Kuleta kurasa",
        "importinterwiki": "Kuleta kutoka wiki nyingine",
        "import-interwiki-text": "Chagua wiki na jina la ukurasa unaotaka kuuleta.\nTarehe za mapitio na majina ya wahariri zitaletwa pia.\nVitendo vyote vya kuleta kutoka wiki nyingine vinaandikwa katika [[Special:Log/import|kumbukumbu za kuleta]].",
-       "import-interwiki-source": "Wiki/ukurasa wa chanzo:",
        "import-interwiki-history": "Leta pamoja na mapitio yote ya ukurasa huu",
        "import-interwiki-templates": "Leta pamoja na vigezo vyote",
        "import-interwiki-submit": "Leta",
        "pageinfo-display-title": "Onyesha mada",
        "pageinfo-article-id": "ID ya ukurasa",
        "pageinfo-language": "Lugha ya maudhui ya ukurasa",
+       "pageinfo-robot-index": "Halali",
+       "pageinfo-robot-noindex": "Marufuku",
        "pageinfo-watchers": "Idadi ya wanaofuatilia",
        "pageinfo-edits": "Idadi ya maharirio",
        "pageinfo-toolboxlink": "Maelezo ya ukurasa",
+       "pageinfo-redirectsto-info": "habari",
        "pageinfo-contentpage-yes": "Ndiyo",
        "pageinfo-protect-cascading-yes": "Ndiyo",
        "pageinfo-category-info": "Maelezo ya jamii",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|majadiliano]])",
        "duplicate-defaultsort": "!'''Ilani:''' Neno msingi la kupanga \"$2\" linafunika neno msingi la kupanga la awali \"$1\".",
        "version": "Toleo",
+       "version-skins": "Maumbo",
        "version-specialpages": "Kurasa maalum",
        "version-variables": "Vibadili",
-       "version-skins": "Maumbo",
        "version-other": "Zingine",
        "version-version": "(Toleo $1)",
        "version-license": "Ruhusa",
index df1295c..2a0f494 100644 (file)
        "talkpagelinktext": "dyskusyjo",
        "specialpage": "Szpecyjolno zajta",
        "personaltools": "Perzůnolne",
-       "postcomment": "Skůmyntuj",
        "articlepage": "Zajta artikla",
        "talk": "Dyskusyjo",
        "views": "Widok",
        "externaldberror": "Je jaki feler we zewnyntrznyj baźe autentyfikacyjnyj, abo ńy mosz uprawńyń potrzebnych do aktualizacyji zewnyntrznego kůnta.",
        "login": "Zaloguj śe",
        "nav-login-createaccount": "Logowańy / Tworzyńy kůnta",
-       "loginprompt": "Muśisz mjeć załůnczůne cookies coby můc śe sam zalogować.",
        "userlogin": "Logowańy / Tworzyńy kůnta",
        "userloginnocreate": "Zaloguj śe",
        "logout": "Wyloguj",
        "explainconflict": "Ftoś zdůnżůł wćepać swoja wersyjo artikla ńim żeś naszkryflou sprowjyńy.\nWe polu edycyji na wjyrchu mosz tekst zajty aktuelńy naszkryflany we baźe danych.\nTwoje pomjyńańo sům we polu edycyji půńiżyj.\nBy wćepać swoje pomjyńańo muśisz pomjyńać tekst we polu na wjyrchu.\n'''Ino''' tekst ze pola na wjyrchu bydźe naszkryflany we baźe jak \nwciśńesz knefel \"{{int:savearticle}}\".",
        "yourtext": "Twůj tekst",
        "storedversion": "Naszkryflano wersyjo",
-       "nonunicodebrowser": "'''Pozůr! Twoja přeglůndorka ńy umje poprowńy rozpoznować kodowańo UTF-8 (Unicode). Bestož wšyjske znoki, kerych Twoja přeglůndorka ńy umje rozpoznować, zamjeńůno na jejich kody heksadecymalne.'''",
-       "editingold": "'''Dej pozůr: Sprowjoš inkšo wersyjo zajty kej bježůnco. Jeli jům naškryfloš, wšyjske půźńyjše pomjyńańa bydům wyćepane.'''",
+       "nonunicodebrowser": "'''Pozůr! Twoja przeglůndorka ńy umi poprawńe rozpoznować kodowańo UTF-8 (Unicode). Bestůż wszyjske znoki, kerych Twojo przeglůndorka ńy umi rozpoznować, zamjeńůno na jejich kody heksadecymalne.'''",
+       "editingold": "'''Dej pozůr: Sprowjosz inkszo wersyjo zajty kej bjeżůnco. Jeli jům naszkryflosz, wszyjske půźńyjsze pomjyńańa bydům wyćepane.'''",
        "yourdiff": "Růżńice",
        "copyrightwarning": "Pamjyntej uo tym, aże cołki wkłod do {{SITENAME}} udostympńůmy wedle zasad $2 (dokładńij we $1). Jak ńy chcesz, coby kożdy můg go půmjyńać a dalij rozpowszychńoć, ńy wćepuj uůnygo sam. Szkryflajůnc sam tukej pośwjadczosz tyż, co te pisańy je twoje własne, abo żeś go wźůn(a) ze materjołůw kere sům na ''public domain'', abo kůmpatybilne.<br />\n'''PROSZA ŃY WĆEPYWAĆ SAM MATYRJOŁŮW KERE SŮM CHRŮŃONE AUTORSKIM PRAWYM BEZ DOZWOLEŃO WŁAŚĆIĆELA!'''",
        "copyrightwarning2": "Pamjyntej uo tym, aże cołki wkłod do {{GRAMMAR:MS.lp|{{SITENAME}}}} może być sprowjany, pomjyńany abo wyćepany bez inkszych użytkownikůw. Jak ńy chcysz, coby kożdy můg uůnygo zmjyńać a dalij rozpowszychńoć bez uograniczyń, ńy wćepuj go sam.<br />\nSzkryflajůnc sam tukej pośwjadczosz tyż, co te pisańy je twoje własne, abo żeś go wźůn(a) ze matyrjołůw kere sům na public domain, abo kůmpatybilne (kuknij tyż: $1).\n'''PROSZA ŃY WĆEPYWAĆ SAM MATYRJOŁŮW KERE SŮM CHRŮŃONE PRAWYM AUTORSKIM BEZ DOZWOLEŃO WŁAŚĆIĆELA!'''",
        "template-protected": "(zawrzity uod sprowjańo)",
        "template-semiprotected": "(tajlowo zawarte)",
        "hiddencategories": "Ta zajta je {{PLURAL:$1|we jednyj schrůńunyj katygoryji|we $1 schrůńunych katygoryjach}}:",
-       "nocreatetext": "Na {{GRAMMAR:MS.lp|{{SITENAME}}}} twořyńy nowych zajtůw uograńičůno.\nMožeš sprowjać te co juž sům, abo [[Special:UserLogin|zalogować śe, abo zauožyć konto]].",
+       "nocreatetext": "Na {{GRAMMAR:MS.lp|{{SITENAME}}}} tworzyńy nowych zajtůw uograńiczůno.\nMoges sprowjać te co już sům, abo [[Special:UserLogin|zalogować śe, abo śa zaregisztrować]].",
        "nocreate-loggedin": "Ńy mosz uprowńyń do tworzyńo nowych zajtůw.",
        "sectioneditnotsupported-title": "Sprowjańy tajli ńymogebne",
        "sectioneditnotsupported-text": "Sprowjańy tajli ńymogebne na tyj zajće.",
        "permissionserrors": "Felerne uprawńyńo",
        "permissionserrorstext": "Ńy mosz uprowńyń do takij akcyje {{PLURAL:$1|skuli tego, co:|bestůż, co:}}",
        "permissionserrorstext-withaction": "Ńy mogesz $2, ze {{PLURAL:$1|takigo powodu|takich powodůw}}:",
-       "recreate-moveddeleted-warn": "'''ůostrzeżyńy: Wćepujesz samo zajta, kery bůu poprzedńo wyćepany.'''\n\nZastanůw śe, czy powinno śe go sam wćepywać.\nRejer wyćepań tyj zajty je podany půńiżej, cobyś mioł wygoda:",
+       "recreate-moveddeleted-warn": "'''Uostrzeżyńy: Wćepujesz ta samo zajta, kero bůła poprzedńo wyćepano.'''\n\nZastanůw śe, czy noleżoło by śe go sam wćepywać.\nRejer wyćepań tyj zajty je podany půńiżej, cobyś mjoł wygoda:",
        "moveddeleted-notice": "Ta zajta zostoła wyćepńynto. Rejer wyćepań tyj zajty je pokozany půńiżyj.",
        "log-fulllog": "Ukoż rejer",
-       "edit-hook-aborted": "Sprowjyńy štopńynte skiž hoka.\nŃy je wjadůme pů jakymu.",
+       "edit-hook-aborted": "Sprowjyńy sztopńynte skiż hoka.\nŃy je wjadůme pů jakymu.",
        "edit-gone-missing": "Ńy idźe zaktualizować zajty.\nZdowo śe, co zostoła wyćepano.",
        "edit-conflict": "Kůnflikt sprowjyń.",
        "edit-no-change": "Twoje sprowjyńe uostoło zignorowane pů takymu, aże ńic żeś we tekśće ńy zmjyńůł.",
        "post-expand-template-inclusion-warning": "Dej pozůr: Dokuplowane mustry sům moc wjelge.\nŃykere mustry ńy bydům dokuplowane.",
        "post-expand-template-inclusion-category": "Zajty, na kerych dokuplowane mustry sům moc wjelge",
        "post-expand-template-argument-warning": "Dej pozůr: Ta zajta zawjyro przinojmyńi jedyn argument we mustrze, kery powoduje co je ůun za wjelgi. Te argumynty bydům pomińynte.",
-       "post-expand-template-argument-category": "Zajty na kerych sům šablůny s pomińyntymi argumyntůma.",
+       "post-expand-template-argument-category": "Zajty na kerych sům mustry ze pomińyntymi argumyntůma.",
        "parser-template-loop-warning": "Wykryto muster zapyntlyńo: [[$1]]",
        "parser-template-recursion-depth-warning": "Przekroczůno limit głymbokośći rekurencyji mustru ($1)",
-       "undo-success": "Sprowjyńy zostouo wycůfane. Proša pomjarkować ukozane půnižyj dyferencyje mjyndzy wersyjami, coby zweryfikować jejich poprawność, potym zaś naškryflać pomjyńańo coby zakońčyć uoperacyjo.",
+       "undo-success": "Sprowjyńy zostoło wycofane. Prosza pomjarkować ukozane půniżyj dyferencyje mjyndzy wersyjůma, coby zweryfikować jejich poprawność, potym zaś naszkryflać pomjyńańo coby zakończyć uoperacyjo.",
        "undo-failure": "Sprowjyńo ńy idźe wycofać skuli kůnflikta ze wersyjůma postrzedńimi.",
        "undo-norev": "Sprowjyńo ńy idźe cofnůńć skuli tego, co ńy istńije abo uostoło wyćepane.",
        "undo-summary": "Wycůfańy wersyji $1 naszkryflanej bez [[Special:Contributions/$2|$2]] ([[User talk:$2|godka]])",
        "cantcreateaccounttitle": "Ńy do śe utworzić kůnta",
-       "cantcreateaccount-text": "Tworzyńy kůnta s tygo adresu IP ('''$1''') zostoło zawarte bez użytkowńika [[User:$3|$3]].\n\nSkuli: ''$2''",
-       "viewpagelogs": "Uoboč rejery uoperacyji lo tyj zajty",
+       "cantcreateaccount-text": "Tworzyńy kůnta s tygo adresu IP ('''$1''') uostoło zawarte bez użytkowńika [[User:$3|$3]].\n\nSkuli: ''$2''",
+       "viewpagelogs": "Uobocz rejery uoperacyji lo tyj zajty",
        "nohistory": "Ta zajta ńy mo swojij historyje sprowjyń.",
        "currentrev": "Aktuelno wersyjo",
        "currentrev-asof": "Aktuelno wersyjo na dźyń $1",
        "revdelete-show-file-confirm": "Jeżeś echt pewny co chcesz uobejzdrzeć wyćepano wersyjo plika „<nowiki>$1</nowiki>” s $2 $3?",
        "revdelete-show-file-submit": "Ja",
        "logdelete-selected": "{{PLURAL:$1|Wybrane zdarzyńy ze rejeru|Wybrane zdarzyńa ze rejeru}}:",
-       "revdelete-legend": "Naštaluj uograńičyńo lo wersyji:",
+       "revdelete-legend": "Nasztaluj uograńiczyńo lo wersyji:",
        "revdelete-hide-text": "Schrůń tekst wersyji",
        "revdelete-hide-image": "Schrůń zawartość plika",
        "revdelete-hide-name": "Schrůń akcyjo a cwek",
        "revdelete-radio-same": "(byz pomjyń)",
        "revdelete-radio-set": "Zakryty",
        "revdelete-radio-unset": "Widoczny",
-       "revdelete-suppress": "Schrůń informacyje zarůwno před admińistratorůma jak i před inkšymi",
-       "revdelete-unsuppress": "Usůń uograńičyńo lo wćepanej nazod historyje pomjyńań",
+       "revdelete-suppress": "Schrůń informacyje zarůwno przed admińistratorůma kej i przed inkszymi",
+       "revdelete-unsuppress": "Usůń uograńiczyńo lo wćepanej nazod historyje pomjyńań",
        "revdelete-log": "Czymu:",
        "revdelete-submit": "Zaakceptuj do wybrany{{PLURAL:$1|j wersyji|ch wersyji}}",
        "revdelete-success": "'''Půmyślńy zmjyńůno widoczność wersyji.'''",
        "pagehist": "Historyjo sprowjyń zajty",
        "deletedhist": "Wyćepano gyszichta sprowjyń",
        "revdelete-hide-current": "Feler przi wyćepywańu wersyji $2, $1.",
-       "revdelete-show-no-access": "Feler przy ukozoniu wersyji $2, $1. Ńy mosz uprawńyń lo njygo.",
-       "revdelete-modify-no-access": "Feler przy zmjyńe widoczności wersyji $2, $1. Ńy mosz uprawńeń lo njygo.",
-       "revdelete-modify-missing": "Feler. Ńy mo elementu $1 w bazie.",
+       "revdelete-show-no-access": "Feler przy ukozoniu wersyji $2, $1. Ńy mosz uprawńyń lo ńygo.",
+       "revdelete-modify-no-access": "Feler przy zmjyńe widoczności wersyji $2, $1. Ńy mosz uprawńeń lo ńygo.",
+       "revdelete-modify-missing": "Feler. Ńy mo tajli $1 w baźe.",
        "revdelete-no-change": "''''Dej pozůr''': element $2, $1 mo już ustawjonům widoczność.",
        "revdelete-concurrent-change": "Feler. Pomjyno już element $2, $1. Prosza uoboczyć to w rejerze.",
-       "revdelete-only-restricted": "Ńy możno ukryć elementu $2, $1 przed administracyjom. Wybjer jydnom ze opcyji.",
+       "revdelete-only-restricted": "Ńy do śe ukryć tajli $2, $1 przed administracyjom. Wybjer jydnom ze uopcyji.",
        "revdelete-reason-dropdown": "* Kůmyntorze lo wyćepańa\n** NPA\n** Prywatność",
        "revdelete-otherreason": "Inkszy/dodatkowy powůd:",
        "revdelete-reasonotherlist": "Inkszy powůd",
        "revdelete-offender": "Autor wersyji:",
        "suppressionlog": "Log schrůńyńć",
        "suppressionlogtext": "Půńiżyj je lista nojnowszych wyćepań a zawarć s uwzglyndńyńym treśći schrůńůnej lo admińistratorůw. Coby przejrzeć lista teroźnych banůw a zawarć, uobezdrzij [[Special:BlockList|IP block list]].",
-       "mergehistory": "Pouůnč historyjo půmjyńań zajtůw",
+       "mergehistory": "Połůncz historyjo půmjyńań zajtůw",
        "mergehistory-header": "Ta zajta dozwolo pouůnčyć historyje půmjyńań jydnyj zajty s inkšům, nowšům zajtům. Dej pozůr, coby sprawjyńy douo ćůnguo historyjo půmjyńań zajty w jeji historyji.",
        "mergehistory-box": "Pouůnč historyjo sprowjyń dwůch zajtůw:",
        "mergehistory-from": "Zajta zdřůduowo:",
        "searchprofile-advanced-tooltip": "Sznupańy we uobranych raumach mjan",
        "search-result-size": "$1 ({{PLURAL:$2|1 słowo|$2 słowa|$2 słůw}})",
        "search-result-category-size": "{{PLURAL:$1|1 element|$1 elementy|$1 elementów}} ({{PLURAL:$2|1 kategoryjo|$2 kategoryje|$2 kategoryje}}, {{PLURAL:$3|1 uobrozek|$3 uobrozki|$3 uobrozkow}})",
-       "search-result-score": "Akuratność: $1%",
        "search-redirect": "(půnkńyńćy $1)",
        "search-section": "(tajla $1)",
        "search-suggest": "Myśloł żeś: $1 ?",
        "file-deleted-duplicate": "Identyczny plik jak tyn plik ([[:$1]]) zostoł wyćepany. Sprowdź historyja wyćepań tamtygo plika ńim wćepńesz go nazod.",
        "uploadwarning": "Uostřežyńe uo wćepywańu",
        "savefile": "Spamjyntej plik",
-       "uploadedimage": "wćepano \"[[$1]]\"",
-       "overwroteimage": "wćepano nowszo wersyjo \"[[$1]]\"",
        "uploaddisabled": "Wćepywanie sam plikůw je zawarte",
        "uploaddisabledtext": "Wćepywańe plikůw je zawarte.",
        "uploadscripted": "Tyn plik zawjyro kod HTML abo skrypt kery može zostać felerńe zinterpretowany bez přyglůndarka internetowo.",
        "nolicense": "Ńy wybrano (naškryflej rynčńy!)",
        "license-nopreview": "(Podglůnd ńydostympny)",
        "upload_source_url": " (poprowny, publičńy dostympny URL)",
-       "upload_source_file": " (plik na twojym komputře)",
+       "upload_source_file": "(plik na twojym kůmputrze)",
        "listfiles-summary": "To je ekstra zajta na kery sům pokazywane wšyske pliki wćepane na serwer. Důmyślńy na wiyrchu listy wyśwjetlajům śe pliki wćepane na uostatku. Coby půmjyńić sposůb sortowańo, klikńij na naguůwek kolůmny.",
        "listfiles_search_for": "Šnupej za grafikům uo mjańe:",
        "imgfile": "plik",
        "watchlist-details": "Na pozorliśće {{PLURAL:$1|je 1 artikel|sům $1 artikle|je $1 artikli}} ńy rachujůnc zajtůw godek.",
        "wlheader-enotif": "Wysůuańy powjadůmjyń na adres e-brif je zouůnčůne",
        "wlheader-showupdated": "Zajty, kere bouy sprowjane uod Twoi uostatńi wizyty na ńych zostoy naškryflane '''tuustym'''",
+       "wlnote": "Půńižy pokazano {{PLURAL:$1|ostatńy sprawjyńy dokůnane|ostatńy '''$1''' sprawjyńe dokůnane|ostatńych '''$1''' sprawjyń dokůnanych}} bez {{PLURAL:$2|uostatńo godźina|uostatńich '''$2''' godźin}}.",
        "wlshowlast": "Pokož uostatńy $1 godźin $2 dńi ($3)",
        "watchlist-options": "Uopcyje artikli na kere dowosz pozůr",
        "watching": "Dowom pozor...",
index 512c95a..cc50bc4 100644 (file)
@@ -34,7 +34,8 @@
                        "බිඟුවා",
                        "Thamiziniyan",
                        "아라",
-                       "Kalyanasundar"
+                       "Kalyanasundar",
+                       "தமிழ்த்தம்பி"
                ]
        },
        "tog-underline": "இணைப்புகளுக்கு அடிக்கோடிடு",
        "talkpagelinktext": "பேச்சு",
        "specialpage": "சிறப்புப் பக்கம்",
        "personaltools": "தனிப்பட்ட பயன்பாட்டுக் கருவிகள்",
-       "postcomment": "புதிய பகுதி",
        "articlepage": "உள்ளடக்கப் பக்கத்தைப் பார்",
        "talk": "உரையாடல்",
        "views": "பார்வைகள்",
        "hidetoc": "மறை",
        "collapsible-collapse": "சுருக்கு",
        "collapsible-expand": "விரிவாக்கு",
+       "confirmable-yes": "ஆம்",
+       "confirmable-no": "இல்லை",
        "thisisdeleted": "$1 பார்க்கவா அல்லது மீள்விக்கவா?",
        "viewdeleted": "$1 பார்?",
        "restorelink": "{{PLURAL:$1|ஒரு நீக்கப்பட்ட தொகுப்பை|$1 நீக்கப்பட்ட தொகுப்புகளை}}",
        "invalidtitle-knownnamespace": "பெயரிடைவெளி ' $2 '' மற்றும் உரை '' $3 '' கொன்ட தலைப்பு செல்லாது",
        "invalidtitle-unknownnamespace": "அறியப்படாத பெயரிடைவெளி $1 மற்றும் உரை $2 கொண்ட தலைப்பு செல்லாது",
        "exception-nologin": "புகுபதிகை செய்யப்படவில்லை.",
-       "exception-nologin-text": "à®\87நà¯\8dத à®ªà®\95à¯\8dà®\95à®®à¯\8d / à®\9aà¯\86யà¯\8dà®\95à¯\88 à®\87நà¯\8dத à®µà®¿à®\95à¯\8dà®\95ியிலà¯\8d à®\89à®\99à¯\8dà®\95ளதà¯\81 à®ªà¯\81à®\95à¯\81பதிà®\95à¯\88யà¯\88 à®\8eதிரà¯\8dபாரà¯\8dà®\95à¯\8dà®\95ிறதà¯\81.",
+       "exception-nologin-text": "à®\87நà¯\8dத à®ªà®\95à¯\8dà®\95à®®à¯\8d / à®\9aà¯\86யà¯\8dà®\95à¯\88 à®\9aà¯\86யà¯\8dய à®\85à®°à¯\81ளà¯\8dà®\95à¯\82à®°à¯\8dநà¯\8dதà¯\81 à®ªà¯\81à®\95à¯\81பதிà®\95à¯\88 à®\9aà¯\86யà¯\8dயவà¯\81à®®à¯\8d.",
        "virus-badscanner": "சரியற்ற உள்ளமைவு: அறியப்படாத வைரஸ் வருடி: '' $1 ''",
        "virus-scanfailed": "வருடல் நடைபெறவில்லை (குறியீடு $1)",
        "virus-unknownscanner": "அறியப்படாத வைரசெதிர்ப்பு:",
        "externaldberror": "வெளி உறுதிப்படுத்தலில் ஏற்பட்ட தவறு காரணமாக உங்கள் வெளி கணக்கை இற்றைப்படுத்த முடியாது.",
        "login": "புகுபதிகை",
        "nav-login-createaccount": "புகுபதிகை/பயனர் கணக்கு தொடக்கம்",
-       "loginprompt": "{{SITENAME}} தளத்துக்கு புகுபதிகை செய்ய உங்கள் இணைய உலாவியின் ஞாபகிகளை செயற்படுத்த வேண்டும்.",
        "userlogin": "புகுபதிகை/பயனர் கணக்கு தொடக்கம்",
        "userloginnocreate": "புகுபதிகை",
        "logout": "விடுபதிகை",
        "gotaccountlink": "புகுபதிகை",
        "userlogin-resetlink": "உங்கள் புகுபதிகைக் குறிப்புகளை மறந்துவிட்டீர்களா?",
        "userlogin-resetpassword-link": "உங்கள் கடவுச் சொல்லை மறந்து விட்டீர்களா?",
-       "userlogin-createanother": "மற்றொரு கணக்கு ஒன்றை உருவாக்கவும்",
        "createacct-emailrequired": "மின்னஞ்சல் முகவரி",
        "createacct-emailoptional": "மின்னஞ்சல் முகவரி (விருப்பத்தேர்வு)",
        "createacct-email-ph": "உங்கள் மின்னஞ்சல் முகவரியை உள்ளிடுக",
        "searchprofile-advanced-tooltip": "தனிப்பட்ட பெயர்வெளிகளில் தேடவும்",
        "search-result-size": "$1 ({{PLURAL:$2|1 சொல்|$2 சொற்கள்}})",
        "search-result-category-size": "{{PLURAL:$1|1 உறுப்பினர்|$1 உறுப்பினர்கள்}} ({{PLURAL:$2|1 துணைப்பகுப்பு|$2 துணைப்பகுப்புகள்}}, {{PLURAL:$3|1 கோப்பு|$3 கோப்புகள்}})",
-       "search-result-score": "பொருத்தம்: $1%",
        "search-redirect": "(பக்க வழிமாற்றம் $1)",
        "search-section": "(பிரிவு $1)",
        "search-suggest": "நீங்கள் கருதியது இதையா: $1",
        "right-deletedtext": " நீக்கப்பட்ட உரை மற்றும் நீக்கப்பட்ட பரிசீலனைகளுக்கு இடையேயான மாற்றங்களை காண்.",
        "right-browsearchive": "நீக்கப்பட்ட பக்கங்களை தேடுக",
        "right-undelete": "பக்கமொன்றை மீட்டெடுக்கவும்",
-       "right-suppressrevision": "நிரà¯\8dவாà®\95ிà®\95ளிà®\9fமிரà¯\81நà¯\8dதà¯\81 à®®à®±à¯\88à®\95à¯\8dà®\95பà¯\8dபà®\9fà¯\8dà®\9f à®¤à®¿à®°à¯\81தà¯\8dதà®\99à¯\8dà®\95ளà¯\88 à®\86யà¯\8dவà¯\81 à®\9aà¯\86யà¯\8dதà¯\81 à®®à¯\80à®\9fà¯\8dà®\9fà¯\86à®\9fà¯\81",
+       "right-suppressrevision": "à®\8eநà¯\8dதவà¯\8aà®°à¯\81 à®ªà®¯à®©à®°à®¿à®\9fமிரà¯\81நà¯\8dதà¯\81à®®à¯\8d à®\95à¯\81றிபà¯\8dபிà®\9fà¯\8dà®\9f à®ªà®\95à¯\8dà®\95தà¯\8d à®¤à®¿à®°à¯\81தà¯\8dதà®\99à¯\8dà®\95ளà¯\88 à®ªà®¾à®°à¯\8dவà¯\88யிà®\9fà¯\81à®\95, à®®à®±à¯\88à®\95à¯\8dà®\95வà¯\81à®®à¯\8d, à®µà¯\86ளிà®\95à¯\8dà®\95ாà®\9fà¯\8dà®\9fவà¯\81à®®à¯\8d",
        "right-suppressionlog": "தனிப்பட்ட பதிவுகளை பார்க்க",
        "right-block": "ஏனைய பயனர்கள் தொகுப்பதை தடுக்கவும்",
        "right-blockemail": "பயனர் மின்னஞ்சல் அனுப்புவதை தடுக்கவும்",
        "uploadwarning": "பதிவேற்றல் எச்சரிக்கை",
        "uploadwarning-text": "கீழுள்ள கோப்புச் சுருக்கத்தை மாற்றி விட்டு மீண்டும் சமர்ப்பியுங்கள்",
        "savefile": "கோப்பைச் சேமி",
-       "uploadedimage": "\"[[$1]]\" பதிவேற்றப்பட்டது",
-       "overwroteimage": "\"[[$1]]\" கோப்பின் புதிய பதிப்பை பதிவேற்று",
        "uploaddisabled": "பதிவேற்றம் செயலிழக்கச் செய்யப்பட்டுள்ளது",
        "copyuploaddisabled": "URL வழியாக தகவலேற்றல் முடக்கப்பட்டுள்ளது.",
        "uploaddisabledtext": "கோப்பு பதிவேற்றங்கள் செயலிழக்கச் செய்யப்பட்டுள்ளன.",
        "license-header": "அனுமதி",
        "nolicense": "தெரிவுச் செய்யப்படவில்லை",
        "license-nopreview": "(முன்தோற்றம் கையிலிருப்பில் இல்லை)",
-       "upload_source_url": " (à®\9aà¯\86லà¯\8dலà¯\81பà®\9fியான, à®\87ணà¯\88ய à®®à¯\81à®\95வரி)",
-       "upload_source_file": " (உங்கள் கணணியில் உள்ள கோப்பு)",
+       "upload_source_url": " (நà¯\80à®\99à¯\8dà®\95ளà¯\8d à®¤à¯\86ரிவà¯\81 à®\9aà¯\86யà¯\8dத, à®ªà¯\8aதà¯\81விலà¯\8d à®\85ணà¯\81à®\95à¯\8dà®\95à¯\82à®\9fிய à®\9aà¯\86லà¯\8dலதà¯\8dதà®\95à¯\8dà®\95 à®\87ணà¯\88ய à®®à¯\81à®\95வரியிலà¯\8d à®\89ளà¯\8dள à®\95à¯\8bபà¯\8dபà¯\81)",
+       "upload_source_file": "(தங்களி்ன் கணினியிலிருந்து தங்களால் தேர்ந்தெடுக்கப்பட்ட கோப்பு)",
        "listfiles-summary": "இச்சிறப்புப் பக்கம் பதிவேற்றப்பட்ட கோப்புகளைப் பட்டியலிடுகிறது.",
        "listfiles_search_for": "பின்வரும் பெயருள்ள ஊடகக் கோப்பைத் தேடு:",
        "imgfile": "கோப்பு",
        "mywatchlist": "கவனிப்புப் பட்டியல்",
        "watchlistfor2": "$1 பயனரின் ($2)",
        "nowatchlist": "உங்களுடைய கவனிப்புப் பட்டியலில் ஒரு விடயமும் இல்லை.",
-       "watchlistanontext": "உங்கள் கவனிப்புப் பட்டியலைப் பார்க்க அல்லது தொகுக்க அருள் கூர்ந்து $1 செய்யுங்கள்.",
+       "watchlistanontext": "உங்கள் கவனிப்புப் பட்டியலைப் பார்க்க அல்லது தொகுக்க அருள் கூர்ந்து புகுபதிகை செய்யுங்கள்.",
        "watchnologin": "புகுபதிகை செய்யப்படவில்லை.",
        "addwatch": "கவனிப்புப் பட்டியலில் சேர்",
        "addedwatchtext": "\"[[:$1]]\" பக்கம் உங்கள் [[Special:Watchlist|கவனிப்புப் பக்கத்தில்]] சேர்க்கப்பட்டுள்ளது. இந்தப் பக்கத்துக்கு எதிர்காலத்தில் செய்யப்படவுள்ள மாற்றங்களும், அதனோடிணைந்த பேச்சுப் பக்கமும், அங்கே பட்டியலிடப்படும். அத்துடன் தெரிந்தெடுக்க வசதியாக [[Special:RecentChanges|அண்மைய மாற்றங்களின் பட்டியலில்]] இது தடித்த எழுத்துக்களில் காட்டப்படும். பின்னர், இப் பக்கத்தை உங்கள் கவனிப்புப் பட்டியலிலிருந்து நீக்க விரும்பினால், பக்கச் சட்டத்திலுள்ள ''கவனிப்பு நீக்கு'' என்ற இணைப்பைச் சொடுக்கவும்.",
        "watchlist-details": "பேச்சுப் பக்கங்களைத் தவிர்த்து, {{PLURAL:$1|$1 பக்கம் கவனிக்கப்பட்டது.|$1 பக்கங்கள் கவனிக்கப்பட்டன.}}",
        "wlheader-enotif": "மின்னஞ்சல் அறிவிப்புகள் செயல்படுத்தப்பட்டுள்ளன.",
        "wlheader-showupdated": "உங்கள் கடைசி வருகைக்குப் பின்னர் மாற்றங்கள் செய்யப்பட்ட பக்கங்கள் '''தடித்த எழுத்துக்களில்''' காட்டப்பட்டுள்ளன",
+       "wlnote": "பின்வருவன கடைசி {{PLURAL:$2|மணித்தியாலத்தில்|'''$2''' மணித்தியாலங்களில்}} செய்யப்பட்ட {{PLURAL:$1|கடைசி ஒரு மாற்றமாகும்|கடைசி $1 மாற்றங்களாகும்}}.",
        "wlshowlast": "கடைசி $1 மணித்தியாலங்கள் $2 நாட்களைக் காட்டு $3",
        "watchlist-options": "கவனிப்பு பட்டியலின் விருப்பத் தேர்வுகள்",
        "watching": "கவனிக்கப்படுகிறது...",
        "exbeforeblank": "வெறுமைப்படுத்த முன்னிருந்த உள்ளடக்கம்: '$1'",
        "delete-confirm": "\"$1\" பக்கத்தை நீக்கு",
        "delete-legend": "நீக்கவும்",
-       "historywarning": "'''எச்சரிக்கை:''' தாங்கள் நீக்கவுள்ள பக்கத்திற்கு சுமார் $1 {{PLURAL:$1|திருத்தம்|திருத்தங்களின்}} வரலாறு உண்டு:",
+       "historywarning": "<strong>எச்சரிக்கை:</strong> தாங்கள் நீக்கவுள்ள பக்கத்திற்கு $1 {{PLURAL:$1|திருத்தம்|திருத்தங்களின்}} வரலாறு உண்டு:",
        "confirmdeletetext": "நீங்கள் இப்பக்கத்தை அதன் வரலாற்றுடன் சேர்த்து நீக்க விழைகிறீர்கள்.\nஅருள் கூர்ந்து உங்கள் செய்கையின் விளைவுகளை நீங்கள் விளங்கிக் கொண்டீர்கள் என்பதையும் இது [[{{MediaWiki:Policy-url}}|கொள்கைகளுடன்]] ஒத்துப்போவதையும் உறுதிப் படுத்தவும்.",
        "actioncomplete": "செயற்பாடு நிறைவுற்றது",
        "actionfailed": "செயல் வெற்றியடையவில்லை",
        "autoblockid": "தானியங்கி தடை #$1",
        "block": "பயனரைத் தடைசெய்",
        "unblock": "பயனர் தடையை நீக்கு",
-       "blockip": "பயனரà¯\88தà¯\8d à®¤à®\9fà¯\81",
+       "blockip": "தà®\9fà¯\81à®\95à¯\8dà®\95வà¯\81à®®à¯\8d {{GENDER:$1|பயனரà¯\8d}}",
        "blockip-legend": "பயனரைத் தடு",
        "blockiptext": "ஒரு குறிப்பிட்ட ஐபி முகவரி அல்லது பயனரிடமிருந்து எழுத்து அணுக்கத்தைத் தடுப்பதற்குக் கீழேயுள்ள படிவத்தை உபயோகிக்கவும். இது விசமத்தனத்தைத் தடுப்பதற்கும் [[{{MediaWiki:Policy-url}}|{{SITENAME}} கொள்கை]]க்கு எற்புடைய வகையிலும் மட்டுமே பயன்படுத்தப்பட வேண்டும்.\nகுறிப்பிட்ட காரணமொன்றைக் கீழே நிரப்புக (எடுத்துக்காட்டாக, விசமத்தனம் செய்யப்பட்ட பக்கங்களை எடுத்துக் காட்டவும்).",
        "ipaddressorusername": "ஐ.பி. அல்லது பயனர் பெயர்:",
        "ipb-unblock-addr": "$1 இன் தடையை நீக்கு",
        "ipb-unblock": "ஐ.பி. அல்லது பயனருக்கான தடையை நீக்கு",
        "ipb-blocklist": "தற்போதுள்ள தடுப்புகளைப் பார்",
-       "ipb-blocklist-contribs": "$1 யின் பங்களிப்புகள்",
+       "ipb-blocklist-contribs": "{{GENDER:$1|$1}}க்கு பங்களிப்புகள்",
        "unblockip": "பயனர் தடையை நீக்கு",
        "unblockiptext": "முன்னர் தடுக்கப்பட்ட ஐ.பி. முகவரி அல்லது பயனர்பெயரின் எழுத்து அணுக்கத்தை மீழ்விப்பதற்கு கீழேயுள்ள படிவத்தை பயன்படுத்தவும்.",
        "ipusubmit": "இந்தத் தடையை நீக்கு",
        "import": "பக்கங்களை இறக்கு",
        "importinterwiki": "விக்கியிடை இறக்குமதி",
        "import-interwiki-text": "இறக்குமதிக்கான விக்கியையும் பக்கத்தையும் தெரிவுச் செய்க.\nதிருத்த நாட்கள், தொகுத்தவர்களின் பெயர்கள் என்பன பேனப்படும்.\nஎல்லா விக்கியிடை இறக்குமதிகளும் [[Special:Log/import|இறக்குமதிப் பதிகையில்]] பதியப்படும்.",
-       "import-interwiki-source": "மூல விக்கி/பக்கம்:",
+       "import-interwiki-sourcepage": "மூலப் பக்கம்:",
        "import-interwiki-history": "இப்பக்கத்தின் அனைத்து வரலாற்றுப் பதிப்புகளையும் நகலெடு",
        "import-interwiki-templates": "அனைத்து வார்ப்புருக்களையும் சேர்",
        "import-interwiki-submit": "இறக்கு",
        "import-upload": "XML தரவை பதிவேற்று",
        "import-token-mismatch": "உங்கள் அமர்வின் தரவுகள் அழிந்துவிட்டன. அருள்கூர்ந்து மீண்டும் முயல்க.",
        "import-invalid-interwiki": "குறிப்பிட்ட விக்கியில் இருந்து இறக்குமதி செய்யமுடியாது .",
-       "import-error-edit": "பக்கம் \"$1\" ஆனது இறக்குமதி செய்யப்படவில்லை ,ஏனெனில் அதை நீங்கள் திருத்த அனுமதிக்கப்படவில்லை.",
-       "import-error-create": "பக்கம் \"$1\" ஆனது இறக்குமதி செய்யப்படவில்லை ,ஏனெனில் அதை நீங்கள் உருவாக்க  அனுமதிக்கப்படவில்லை.",
+       "import-error-edit": "பக்கம் \"$1\" ஆனது இறக்குமதி செய்யப்படவில்லைஏனெனில் அதை நீங்கள் திருத்த அனுமதிக்கப்படவில்லை.",
+       "import-error-create": "பக்கம் \"$1\" ஆனது இறக்குமதி செய்யப்படவில்லைஏனெனில் அதை நீங்கள் உருவாக்க  அனுமதிக்கப்படவில்லை.",
        "import-error-invalid": "பக்கம் \"$1\" பதிவிறக்கம் செய்யப்படவில்லை, ஏனெனில் அதன் பெயர் செல்லாது.",
        "import-rootpage-invalid": "கொடுக்கப்பட்ட மூலப்பக்கம் செல்லாத தலைப்பாகும்.",
        "importlogpage": "இறக்குமதி பதிகை",
        "duplicate-defaultsort": "'''எச்சரிக்கை:''' இயல்புநிலை வரிசைப்படுத்து விசை ''$2 \" முன்னால் இயல்புநிலை வரிசைப்படுத்து விசை \"$1\" ஐ மீறுகிறது.",
        "version": "பதிப்பு",
        "version-extensions": "நிறுவப்பட்ட நீட்சிகள்",
+       "version-skins": "தோல்கள்",
        "version-specialpages": "சிறப்புப் பக்கங்கள்",
        "version-parserhooks": "இலக்கணப் பாகுபடுத்தி கொக்கிகள்",
        "version-variables": "மாறிகள்",
        "version-antispam": " குப்பை (spam) தடுப்பு",
-       "version-skins": "தோல்கள்",
        "version-other": "பிறர்",
        "version-mediahandlers": "ஊடக கையாளிகள்",
        "version-hooks": "கொக்கிகள்",
index 9df1372..4b6eb59 100644 (file)
        "talkpagelinktext": "ಪಾತೆರ",
        "specialpage": "ವಿಶೇಷ ಪುಟ",
        "personaltools": "ವೈಯಕ್ತಿಕ ಉಪಕರಣಲು",
-       "postcomment": "ಕಮೆಂಟ್ ಬರೆಲೆ",
        "articlepage": "ಲೇಖನ ಪುಟೊನು ತೂಲೆ",
        "talk": "ಚರ್ಚೆ",
        "views": "ನೋಟಲು",
        "filedesc": "ಸಾರಾಂಶ",
        "filesource": "ಮೂಲ",
        "savefile": "ಕಡತನ್ ಒರಿಪಾಲೆ",
-       "uploadedimage": "\"[[$1]]\" ಅಪ್ಲೋಡ್ ಆಂಡ್",
        "upload-source": "ಮೂಲ ಕಡತ",
        "license-header": "ಲೈಸೆನ್ಸಿಂಗ್",
        "imgfile": "ಫೈಲ್",
index 92528f5..35f166b 100644 (file)
        "talkpagelinktext": "చర్చ",
        "specialpage": "ప్రత్యేక పేజీ",
        "personaltools": "వ్యక్తిగత పనిముట్లు",
-       "postcomment": "కొత్త విభాగం",
        "articlepage": "విషయపు పేజీని చూడండి",
        "talk": "చర్చ",
        "views": "చూపులు",
        "externaldberror": "డేటాబేసు అధీకరణలో లోపం జరిగింది లేదా మీ బయటి ఖాతాను తాజాకరించడానికి మీకు అనుమతి లేదు.",
        "login": "లాగినవండి",
        "nav-login-createaccount": "లాగినవండి / ఖాతాని సృష్టించుకోండి",
-       "loginprompt": "{{SITENAME}}లోకి ప్రవేశించాలంటే మీ విహారిణిలో కూకీలు చేతనమై ఉండాలి.",
        "userlogin": "లాగినవండి / ఖాతాను సృష్టించుకోండి",
        "userloginnocreate": "లాగినవండి",
        "logout": "నిష్క్రమించు",
        "searchprofile-advanced-tooltip": "కస్టం నేంస్పేసులలో వెదుకు",
        "search-result-size": "$1 ({{PLURAL:$2|1 పదం|$2 పదాలు}})",
        "search-result-category-size": "{{PLURAL:$1|1 సభ్యుడు|$1 సభ్యులు}} ({{PLURAL:$2|1 ఉవవర్గం|$2 ఉపవర్గాలు}}, {{PLURAL:$3|1 దస్త్రం|$3 దస్త్రాలు}})",
-       "search-result-score": "సంబంధం: $1%",
        "search-redirect": "(దారిమార్పు $1)",
        "search-section": "(విభాగం $1)",
        "search-file-match": "(ఫైలు విషయంతో సరిపోలుతోంది)",
        "uploadwarning": "ఎక్కింపు హెచ్చరిక",
        "uploadwarning-text": "కింద ఈ ఫైలు వివరణను మార్చి, మళ్ళీ ప్రయత్నించండి.",
        "savefile": "దస్త్రాన్ని భద్రపరచు",
-       "uploadedimage": "\"[[$1]]\"ని ఎక్కించారు",
-       "overwroteimage": "\"[[$1]]\" యొక్క కొత్త కూర్పును ఎక్కించారు",
        "uploaddisabled": "ఎక్కింపులు అచేతనం చెయ్యబడ్డాయి.",
        "copyuploaddisabled": "URL ద్వారా ఎక్కింపుని అశక్తం చేసారు.",
        "uploaddisabledtext": "ఫైళ్ళ ఎక్కింపులను అచేతనం చేసారు.",
        "randomincategory": "వర్గంలోని యాదృచ్చిక పేజీ",
        "randomincategory-invalidcategory": "\"$1\" అనేది సరైన పర్గం పేరు కాదు.",
        "randomincategory-nopages": "[[:Category:$1|$1]] వర్గంలో పేజీలేమీ లేవు.",
-       "randomincategory-selectcategory": "ఈ వర్గం నుంచి ఒక యాదృచ్ఛిక పేజీని చూడండి: $1 $2.",
-       "randomincategory-selectcategory-submit": "వెళ్ళు",
        "randomredirect": "యాదృచ్చిక దారిమార్పు",
        "randomredirect-nopages": "\"$1\" పేరుబరిలో దారిమార్పులేమీ లేవు.",
        "statistics": "గణాంకాలు",
        "watchlist-details": "మీ వీక్షణ జాబితాలో {{PLURAL:$1|ఒక పేజీ ఉంది|$1 పేజీలు ఉన్నాయి}}, చర్చా పేజీలని వదిలేసి.",
        "wlheader-enotif": "ఈ-మెయిలు గమనికలు పంపబడతాయి.",
        "wlheader-showupdated": "మీ గత సందర్శన తరువాత మారిన పేజీలు <strong>బొద్దు</strong>గా చూపించబడ్డాయి.",
-       "wlnote2": "$2, $3 సమయానికి, గత {{PLURAL:$1|గంటలో|<strong>$1</strong> గంటల్లో}}, జరిగిన మార్పులు కింద ఇవ్వబడ్డాయి.",
+       "wlnote": "$3 నాడు $4 సమయానికి, గడచిన {{PLURAL:$2|గంటలో|'''$2''' గంటలలో}} జరిగిన {{PLURAL:$1|ఒక్క మార్పు కింద ఉంది|'''$1''' మార్పులు కింద ఉన్నాయి}}.",
        "wlshowlast": "గత $1 గంటల $2 రోజుల $3 చూపించు",
        "watchlist-options": "వీక్షణ జాబితా ఎంపికలు",
        "watching": "గమనిస్తున్నారు...",
        "import": "పేజీలను దిగుమతి చేసుకోండి",
        "importinterwiki": "ఇంకోవికీ నుండి దిగుమతి",
        "import-interwiki-text": "దిగుమతి చేసుకోవడానికి ఒక వికీని మరియు అందులోని పేజీని ఎంచుకోండి.\nకూర్పుల తేదీలు మరియు మార్పులు చేసిన వారి పేర్లు భద్రపరచబడతాయి.\nఇతర వికీలనుండి చేస్తున్న దిగుమతుల చర్యలన్నీ [[Special:Log/import|దిగుమతుల చిట్టా]]లో నమోదవుతాయి.",
-       "import-interwiki-source": "మూల వికీ/పేజీ:",
        "import-interwiki-history": "ఈ పేజీ యొక్క అన్ని చారిత్రక కూర్పులను కాపీ చెయ్యి",
        "import-interwiki-templates": "అన్ని మూసలను ఉంచు",
        "import-interwiki-submit": "దిగుమతించు",
        "duplicate-defaultsort": "హెచ్చరిక: డిఫాల్టు పేర్చు కీ \"$2\", గత డిఫాల్టు పేర్చు కీ \"$1\" ని అతిక్రమిస్తుంది.",
        "version": "సంచిక",
        "version-extensions": "స్థాపించిన పొడగింతలు",
+       "version-skins": "అలంకారాలు",
        "version-specialpages": "ప్రత్యేక పేజీలు",
        "version-parserhooks": "పార్సరు కొక్కాలు",
        "version-variables": "చరరాశులు",
        "version-antispam": "స్పాము నివారణ",
-       "version-skins": "అలంకారాలు",
        "version-other": "ఇతర",
        "version-mediahandlers": "మీడియాను ఫైళ్లను నడిపించే పొడిగింపులు",
        "version-hooks": "కొక్కాలు",
index 423f1e3..20ab62d 100644 (file)
        "talkpage": "Diskusaun kona-ba pájina ne'e",
        "talkpagelinktext": "Diskusaun",
        "specialpage": "Pájina espesiál",
-       "postcomment": "Seksaun foun",
        "talk": "Diskusaun",
        "toolbox": "Kaixa besi nian",
        "userpage": "Haree pájina uza-na'in",
        "historyempty": "(mamuk)",
        "history-feed-item-nocomment": "$1 iha $2",
        "rev-delundel": "hatudu/subar",
+       "rev-showdeleted": "hatudu",
        "revisiondelete": "Halakon/restaurar versaun",
        "revdelete-show-file-submit": "Sin",
-       "revdelete-hide-user": "Subar naran edita-na'in/IP",
+       "revdelete-hide-text": "Testu versaun nian",
+       "revdelete-hide-user": "Naran edita-na'in/diresaun IP",
        "revdelete-radio-set": "Sin",
        "revdelete-radio-unset": "Lae",
        "revdelete-edit-reasonlist": "Edita lista motivu nian",
        "recentchanges-label-minor": "Ne'e mudansa ki'ik",
        "recentchanges-label-bot": "Edita husi prosesu automátiku (\"bot\")",
        "rcshowhideminor": "$1 muda ki-ki'ik",
+       "rcshowhideminor-show": "Hatudu",
        "rcshowhidebots": "$1 bot sira",
+       "rcshowhidebots-show": "Hatudu",
        "rcshowhideliu": "$1 ema rejista",
+       "rcshowhideliu-show": "Hatudu",
        "rcshowhideanons": "$1 ema anónimu",
+       "rcshowhideanons-show": "Hatudu",
+       "rcshowhideanons-hide": "Subar",
+       "rcshowhidepatr-show": "Hatudu",
        "rcshowhidemine": "$1 ha'u-nia edita",
+       "rcshowhidemine-show": "Hatudu",
        "diff": "diferensa",
        "hist": "istória",
        "hide": "Hamsumik",
index 50eecf7..bb38251 100644 (file)
        "talkpagelinktext": "Баҳс",
        "specialpage": "Саҳифаи вижа",
        "personaltools": "Абзорҳои шахсӣ",
-       "postcomment": "Бахши нав",
        "articlepage": "Намоиши мақола",
        "talk": "Баҳс",
        "views": "Назарот",
        "otherlanguages": "Бо забонҳои дигар",
        "redirectedfrom": "(Тағйири масир аз $1)",
        "redirectpagesub": "Саҳифаи равонакунӣ",
+       "redirectto": "Тағйири масир ба:",
        "lastmodifiedat": "Ин саҳифа бори охир $2, $1 дигаргун карда шудааст.",
        "viewcount": "Ин саҳифа {{PLURAL:$1|бор|$1 бор}} дида шудааст.",
        "protectedpage": "Саҳифаи муҳофизатшуда",
        "jumptonavigation": "гаштан",
        "jumptosearch": "Ҷустуҷӯ",
        "view-pool-error": "Мутаасифона, корсозҳои дар ҳоли ҳозир дучори бори изофӣ ҳастанд.\nТеъдоди зиёди аз корбарон талош мекунанд, ки ин саҳифаро бубинанд.\nЛутфан қабл аз талош дубора барои дидани ин саҳифа муддате сабр кунед.\n\n$1",
+       "generic-pool-error": "Мутаасифона, корсозҳои дар ҳоли ҳозир дучори бори изофӣ ҳастанд.\nТеъдоди зиёди аз корбарон талош мекунанд, ки ин саҳифаро бубинанд.\nЛутфан қабл аз талош дубора барои дидани ин саҳифа муддате сабр кунед.",
+       "pool-timeout": "Замони мунтазирӣ барои қуфл",
+       "pool-queuefull": "Қатори ҳафза пур аст",
        "pool-errorunknown": "Хатогии ношинос",
+       "pool-servererror": "Хидмати ҳисобкунаки ҳафз дастрас нест ($1).",
        "aboutsite": "Дар бораи {{SITENAME}}",
        "aboutpage": "Project:Дар бораи",
        "copyright": "Мӯҳтаво таҳти иҷозатномаи $1 ва ё дигар дастрас аст.",
        "createacct-yourpasswordagain": "Тасдиқи гузарвожа",
        "createacct-yourpasswordagain-ph": "Гузарвожаро бори дигар ворид кунед",
        "remembermypassword": "Вуруди манро дар ин мурургар дар хотир нигоҳ дор (то ҳадди аксар $1 {{PLURAL:$1|рӯз|рӯз}})",
-       "userlogin-remembermypassword": "Вурудшударо манро нигоҳ дор",
+       "userlogin-remembermypassword": "Вурудшуда манро нигоҳ дор",
        "userlogin-signwithsecure": "Истифодаи пайвастшавии амн",
        "yourdomainname": "Домейни Шумо",
        "password-change-forbidden": "Шумо гузарвожаро дар ин вики тағийр дода наметавонед.",
        "externaldberror": "Хатое дар иртибот бо пойгоҳи дода рух дода аст ё ин ки шумо иҷозат ба рӯзрасонии ҳисоби берунии худро надоред.",
        "login": "Вуруд",
        "nav-login-createaccount": "Вуруд / Сохтани ҳисоби ҷадид",
-       "loginprompt": "Барои вуруд ба {{SITENAME}} бояд кукиҳоро фаъол кунед.",
        "userlogin": "Вуруд / Сохтани ҳисоби ҷадид",
        "userloginnocreate": "Вуруд",
        "logout": "Хуруҷ аз систем",
        "userlogin-resetlink": "Ҷузъиёти вурудро фаромӯш кардаед?",
        "userlogin-resetpassword-link": "Гузарвожаро фаромӯш кардед?",
        "userlogin-helplink2": "Роҳнамои вуруд",
-       "userlogin-loggedin": "Шумо дар ҳол чун {{GENDER:$1|$1}} вуруд шудаед.\nБо истифода аз форми зер чун корбари дигар вориди систем шавед.",
-       "userlogin-createanother": "Эҷоди ҳисоби дигар",
        "createacct-emailrequired": "Нишонаи email",
        "createacct-emailoptional": "Нишони email (ихтиёрӣ)",
        "createacct-email-ph": "Нишони email худро ворид кунед",
        "preview": "Пешнамоиш",
        "showpreview": "Пеш намоиш",
        "showdiff": "Намоиши тағйирот",
-       "anoneditwarning": "'''Ð\9eгоҳӣ:''' Ð¨Ñ\83мо Ð²Ñ\83Ñ\80Ñ\83д Ð½Ð°ÐºÐ°Ñ\80даед. Ð¡Ñ\83Ñ\80оÒ\93аи IP Ð¨Ñ\83мо Ð´Ð°Ñ\80 Ð²Ð¸Ñ\80оиÑ\88оÑ\82и Ð¸Ð½ Ñ\81аҳиÑ\84а Ñ\81абÑ\82 хоҳад шуд.",
+       "anoneditwarning": "'''Ð\9eгоҳӣ:''' Ð¨Ñ\83мо Ð²Ñ\83Ñ\80Ñ\83д Ð½Ð°ÐºÐ°Ñ\80даед. Ð\90гаÑ\80 Ñ\8fгон Ð²Ð¸Ñ\80оиÑ\88и ÐºÑ\83нед Ð½Ð¸Ñ\88онаи IP Ð¨Ñ\83мо Ð±Ð° Ò³Ð°Ð¼Ð° Ð½Ð°Ð¼Ð¾Ñ\91н Ñ\85оҳад Ð±Ñ\83д. Ð\90гаÑ\80 Ð¨Ñ\83мо <strong>[$1 Ð²Ð¾Ñ\80ид Ñ\88авед]</strong> Ñ\91 <strong>[$2 Ò³Ð¸Ñ\81обеÑ\80о Ñ\8dҷод ÐºÑ\83нед]</strong>, Ð²Ð¸Ñ\80оиÑ\88оÑ\82и Ð¨Ñ\83мо Ð±Ð° Ð½Ð¾Ð¼Ð¸ ÐºÐ¾Ñ\80баÑ\80иаÑ\82он Ò³Ð°Ð¼Ñ\80оҳ Ð±Ð¾ Ð´Ð¸Ð³Ð°Ñ\80 Ð±Ð°Ñ\80Ñ\82аÑ\80иҳо Ð¼Ñ\83Ñ\82алиÒ\9b хоҳад шуд.",
        "anonpreviewwarning": "<em>Шумо вориди нашудаед. Захиракунӣ IP нишонаи шуморо дар таърихи вироиши ин саҳифа захира хоҳад кард.</em>",
        "missingsummary": "'''Ёдоварӣ:''' Шумо хулосаи вироиш нанавиштаед.\nАгар дубора тугмаи \"Захира\"-ро клик кунед, вироишатон бидуни хулоса захира хоҳад шуд.",
        "missingcommenttext": "Лутфан тавсифе дар зер бинависед.",
        "currentrev": "Вироишоти кунунӣ",
        "currentrev-asof": "Нусхаи кунунӣ то $1",
        "revisionasof": "Нусха $1",
-       "revision-info": "Нусхаи вироиш $2 дар таърихи $1",
+       "revision-info": "Нусхаи вироиш аз $1 тавассути {{GENDER:$6|$2}}$7",
        "previousrevision": "←Нусхаи кӯҳнатар",
        "nextrevision": "Нусхаи навтарин→",
        "currentrevisionlink": "Намоиши нусхаи феълӣ",
        "searchprofile-everything-tooltip": "Ҷустуҷӯи ҳамаи мӯҳтаво (бо ҳисоби саҳифаҳои баҳс)",
        "searchprofile-advanced-tooltip": "Ҷустуҷӯ дар фазоҳои номи дилхоҳ",
        "search-result-size": "$1 ({{PLURAL:$2|1 калима|$2 калимаҳо}})",
-       "search-result-score": "Иртибот: $1%",
        "search-redirect": "(тағйири масир $1)",
        "search-section": "(қисмат $1)",
        "search-suggest": "Оё шумо инро дар назар доред: $1",
        "searchrelated": "алоқаманд",
        "searchall": "ҳама",
        "showingresults": "Намоиши {{PLURAL:$1|'''1''' натиҷа|'''$1''' натоиҷ}} дар зер оғоз аз #'''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|Натиҷаи <strong>$1</strong> <strong>$3</strong>|Натоиҷи <strong>$1 - $2</strong> <strong>$3</strong>}} барои <strong>$4</strong>",
        "search-nonefound": "Натиҷаи муносиб бо дархост пайдо нашуд.",
        "powersearch-legend": "Ҷустуҷӯи пешрафта",
        "powersearch-ns": "Ҷустуҷӯ дар фазоҳои ном:",
        "fileexists-shared-forbidden": "Дар ҳоли ҳозир парванде бо ҳамин ном дар анбори муштараки парвандаҳо вуҷуд дорад; лутфан бар гардед ва парвандаи мавриди назари худро бо номи дигар бо кунед. [[File:$1|thumb|center|$1]]",
        "uploadwarning": "Огоҳии фиристодан",
        "savefile": "Захираи парванда",
-       "uploadedimage": "боршуда \"[[$1]]\"",
-       "overwroteimage": "нусхаи ҷадиди \"[[$1]]\" боргузорӣ шуд",
        "uploaddisabled": "Бор кордан ғайрифаъол аст",
        "copyuploaddisabled": "Боркунӣ тавассути нишонаи интернетӣ ғайрифаъол аст.",
        "uploaddisabledtext": "Боркунии парванда ғайрифаъол аст.",
        "randompage": "Саҳифаи тасодуфӣ",
        "randompage-nopages": "Ҳеҷ саҳифае дар ин фазои ном мавҷуд нест.",
        "randomincategory": "Саҳифаи тасодуфӣ дар гурӯҳ",
-       "randomincategory-selectcategory-submit": "Бирав",
        "randomredirect": "Масири тасодуфӣ",
        "randomredirect-nopages": "Ҳеҷ саҳифаи тағйири масире дар ин фазои ном мавҷуд нест.",
        "statistics": "Омор\\Статистика",
        "watchlist-details": "{{PLURAL:$1|$1 саҳифа|$1 саҳифаҳо}} дар феҳристи пайгириҳои шумо, бидуни ҳисоби саҳифаҳои баҳс.",
        "wlheader-enotif": "Иттилоорасонии тариқи почтаи электронӣ (E-mail) фаъол шудааст.",
        "wlheader-showupdated": "Саҳифаҳое, ки пас аз охирин сар заданатон ба онҳо тағйир кардаанд '''пурранг''' нишон дода шудаанд",
+       "wlnote": "Дар зер {{PLURAL:$1|охирин тағйир|'''$1''' охирин тағйирот}} дар $2 соати охир {{PLURAL:омадааст|омадаанд}}.",
        "wlshowlast": "Намоиши охирин $1 соат $2 рӯзҳо $3",
        "watchlist-options": "Ихтиёроти феҳристи пайгириҳо",
        "watching": "Пайгири...",
index 780bc24..ec2df52 100644 (file)
        "talkpagelinktext": "Bahs",
        "specialpage": "Sahifai viƶa",
        "personaltools": "Abzorhoi şaxsī",
-       "postcomment": "Baxşi nav",
        "articlepage": "Namoişi maqola",
        "talk": "Bahs",
        "views": "Nazarot",
        "externaldberror": "Xatoe dar irtibot bo pojgohi doda rux doda ast jo in ki şumo içozat ba rūzrasoniji hisobi beruniji xudro nadored.",
        "login": "Vurud",
        "nav-login-createaccount": "Vurud / Soxtani hisobi çadid",
-       "loginprompt": "Baroi vurud ba {{SITENAME}} bojad kukihoro fa'ol kuned.",
        "userlogin": "Vurud / Soxtani hisobi çadid",
        "userloginnocreate": "Vurud",
        "logout": "Xuruç az sistem",
        "searchprofile-images-tooltip": "Çustuçūi parvandaho",
        "searchprofile-everything-tooltip": "Çustuçūi hamai mūhtavo (bo hisobi sahifahoi bahs)",
        "search-result-size": "$1 ({{PLURAL:$2|1 kalima|$2 kalimaho}})",
-       "search-result-score": "Irtibot: $1%",
        "search-redirect": "(taƣjiri masir $1)",
        "search-section": "(qismat $1)",
        "search-suggest": "Ojo şumo inro dar nazar dored: $1",
        "fileexists-thumbnail-yes": "Az aks ba nazar merasad, ki aksi andozaaş xurd ''(anguştdona)''. [[$1|thumb]]\nLutan parvandaro <strong>[[:$1]]</strong> barrasī kuned.\nAgar parvandai barrasişuda aksi xurd karda şudai on parvandai aslī ast, nijoze ba borguzoriji aksi xurd nest.",
        "uploadwarning": "Ogohiji firistodan",
        "savefile": "Zaxirai parvanda",
-       "uploadedimage": "borşuda \"[[$1]]\"",
-       "overwroteimage": "nusxai çadidi \"[[$1]]\" borguzorī şud",
        "uploaddisabled": "Bor kordan ƣajrifa'ol ast",
        "uploadscripted": "In parvanda kodi skriptī jo HTML dorad, ki metavonad dar mururgarī veb nodurust namojon şavad.",
        "uploadvirus": "In parvanda virus dorad! Çuz'ijot: $1",
        "watchlist-details": "{{PLURAL:$1|$1 sahifai|$1 sahifahoi}} dar fehristi pajgirihoi şumo, biduni hisobi sahifahoi bahs.",
        "wlheader-enotif": "Ittiloorasoniji tariqi poctai elektronī (E-mail) imkonpazir ast.",
        "wlheader-showupdated": "Sahifahoe, ki pas az oxirin sar zadanaton ba onho taƣjir kardaand '''purrang''' nişon doda şudaand",
+       "wlnote": "Dar zer {{PLURAL:$1|oxirin taƣjir|'''$1''' oxirin taƣjirot}} dar $2 soati oxir {{PLURAL:omadaast|omadaand}}.",
        "wlshowlast": "Namoişi oxirin $1 soat $2 rūzho $3",
        "watchlist-options": "Ixtijoroti fehristi pajgiriho",
        "watching": "Pajgiri...",
index 083efdd..91f6bf2 100644 (file)
@@ -29,7 +29,7 @@
        "tog-newpageshidepatrolled": "ซ่อนหน้าที่ตรวจแล้วจากรายการหน้าใหม่",
        "tog-extendwatchlist": "ขยายรายการเฝ้าดูให้แสดงการเปลี่ยนแปลงทั้งหมด ไม่เพียงการเปลี่ยนแปลงล่าสุด",
        "tog-usenewrc": "จัดกลุ่มการเปลี่ยนแปลงแบ่งตามหน้าในรายการปรับปรุงล่าสุดและรายการเฝ้าดู",
-       "tog-numberheadings": "à¹\83สà¹\88à¹\80ลà¸\82หัวà¸\82à¹\89อà¹\83à¸\99สารà¸\9aัà¸\8dอัตโนมัติ",
+       "tog-numberheadings": "à¹\83สà¹\88à¹\80ลà¸\82หัวà¹\80รืà¹\88อà¸\87อัตโนมัติ",
        "tog-showtoolbar": "แสดงแถบเครื่องมือแก้ไข",
        "tog-editondblclick": "แก้ไขหน้าเมื่อดับเบิลคลิก",
        "tog-editsectiononrightclick": "เปิดใช้งานการแก้ไขเฉพาะส่วนโดยคลิกขวาที่ชื่อเรื่องของส่วนนั้น",
        "tog-watchdefault": "เพิ่มหน้าและไฟล์ที่ฉันแก้ไขเข้ารายการเฝ้าดู",
        "tog-watchmoves": "เพิ่มและไฟล์ที่ฉันเปลี่ยนชื่อเข้ารายการเฝ้าดู",
        "tog-watchdeletion": "เพิ่มหน้าและไฟล์ที่ฉันลบเข้ารายการเฝ้าดู",
+       "tog-watchrollback": "เพิ่มหน้าที่ฉันย้อนกลับฉุกเฉินเข้ารายการเฝ้าดู",
        "tog-minordefault": "กำหนดให้การแก้ไขทุกครั้งเป็นการแก้ไขเล็กน้อยโดยปริยาย",
        "tog-previewontop": "ให้ตัวอย่างการแก้ไขแสดงก่อนกล่องแก้ไข",
-       "tog-previewonfirst": "à¹\81สà¸\94à¸\87à¸\95ัวอยà¹\88าà¸\87à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82สำหรัà¸\9aการแก้ไขครั้งแรก",
-       "tog-enotifwatchlistpages": "อีà¹\80มลหาà¹\80มืà¹\88อหà¸\99à¹\89าหรือà¹\84à¸\9fลà¹\8cà¹\83à¸\99รายà¸\81ารà¹\80à¸\9dà¹\89าà¸\94ูมีà¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87",
-       "tog-enotifusertalkpages": "อีà¹\80มลหาà¹\80มืà¹\88อหà¸\99à¹\89าà¸\84ุยà¸\81ัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\82อà¸\87à¸\89ัà¸\99มีà¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87",
+       "tog-previewonfirst": "à¹\81สà¸\94à¸\87à¸\95ัวอยà¹\88าà¸\87à¹\83à¸\99การแก้ไขครั้งแรก",
+       "tog-enotifwatchlistpages": "อีเมลหาเมื่อหน้าหรือไฟล์ในรายการเฝ้าดูเปลี่ยนแปลง",
+       "tog-enotifusertalkpages": "อีà¹\80มลหาà¹\80มืà¹\88อมีà¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87หà¸\99à¹\89าà¸\84ุยà¸\81ัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\82อà¸\87à¸\89ัà¸\99",
        "tog-enotifminoredits": "อีเมลหาเช่นกันสำหรับการแก้ไขหน้าและไฟล์เล็กน้อย",
        "tog-enotifrevealaddr": "เปิดเผยที่อยู่อีเมลของฉันในอีเมลแจ้งเตือน",
        "tog-shownumberswatching": "แสดงจำนวนผู้ใช้ที่เฝ้าดู",
        "tog-watchlisthideanons": "ซ่อนการแก้ไขโดยผู้ใช้นิรนามจากรายการเฝ้าดู",
        "tog-watchlisthidepatrolled": "ซ่อนการแก้ไขที่ตรวจแล้วจากรายการเฝ้าดู",
        "tog-ccmeonemails": "ส่งสำเนาอีเมลที่ฉันส่งหาผู้อื่นให้ฉัน",
-       "tog-diffonly": "à¹\84มà¹\88à¹\81สà¸\94à¸\87à¹\80à¸\99ืà¹\89อหาà¹\83à¸\95à¹\89สà¹\88วà¸\99à¸\95à¹\88าà¸\87à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82",
+       "tog-diffonly": "à¹\84มà¹\88à¹\81สà¸\94à¸\87à¹\80à¸\99ืà¹\89อหาหà¸\99à¹\89าà¹\83à¸\95à¹\89à¸\9cลà¸\95à¹\88าà¸\87",
        "tog-showhiddencats": "แสดงหมวดหมู่ที่ซ่อนอยู่",
-       "tog-norollbackdiff": "à¹\84มà¹\88à¹\81สà¸\94à¸\87à¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลงหลังดำเนินการย้อนกลับฉุกเฉิน",
+       "tog-norollbackdiff": "à¹\84มà¹\88à¹\81สà¸\94à¸\87à¸\9cลà¸\95à¹\88างหลังดำเนินการย้อนกลับฉุกเฉิน",
        "tog-useeditwarning": "เตือนฉันเมื่อออกหน้าแก้ไขโดยมีการเปลี่ยนแปลงที่ยังไม่บันทึก",
        "tog-prefershttps": "ใช้การเชื่อมต่อปลอดภัยทุกครั้งเมื่อล็อกอิน",
        "underline-always": "ทุกครั้ง",
        "underline-never": "ไม่",
-       "underline-default": "à¸\84à¹\88าà¸\95ัà¹\89à¸\87à¸\95à¹\89à¸\99ของหน้าตาหรือเบราว์เซอร์",
+       "underline-default": "à¸\84à¹\88าà¹\82à¸\94ยà¸\9bริยายของหน้าตาหรือเบราว์เซอร์",
        "editfont-style": "รูปแบบชุดแบบอักษรในพื้นที่แก้ไข:",
-       "editfont-default": "à¸\84à¹\88าà¸\95ัà¹\89à¸\87à¸\95à¹\89à¸\99ของเบราว์เซอร์",
+       "editfont-default": "à¸\84à¹\88าà¹\82à¸\94ยà¸\9bริยายของเบราว์เซอร์",
        "editfont-monospace": "ชุดอักษรแบบความกว้างคงที่",
        "editfont-sansserif": "ชุดอักษรแบบไม่มีเชิง",
        "editfont-serif": "ชุดอักษรแบบมีเชิง",
        "category-subcat-count": "{{PLURAL:$2|หมวดหมู่นี้มีหมวดหมู่ย่อยเพียงหมวดหมู่เดียว|หมวดหมู่นี้มี {{PLURAL:$1|หมวดหมู่ย่อย|$1 หมวดหมู่ย่อย}} จากทั้งหมด $2 หมวดหมู่}}",
        "category-subcat-count-limited": "หมวดหมู่นี้มี $1 หมวดหมู่ย่อย",
        "category-article-count": "{{PLURAL:$2|หมวดหมู่นี้มีอยู่เพียงหน้าเดียว|ในหมวดหมู่นี้มี {{PLURAL:$1|หน้าเดียว|$1 หน้า}} จากทั้งหมด $2 หน้า}}",
-       "category-article-count-limited": "มี $1 หน้าในหมวดหมู่นี้",
-       "category-file-count": "{{PLURAL:$2|หมวà¸\94หมูà¹\88à¸\99ีà¹\89มีà¹\80à¸\9eียà¸\87à¹\84à¸\9fลà¹\8cà¹\80à¸\94ียว|à¹\83à¸\99หมวดหมู่นี้มี $1 ไฟล์ จากทั้งหมด $2 ไฟล์}}",
+       "category-article-count-limited": "$1 หน้าต่อไปนี้อยู่ในหมวดหมู่นี้",
+       "category-file-count": "{{PLURAL:$2|หมวà¸\94หมูà¹\88à¸\99ีà¹\89มีà¹\80à¸\9eียà¸\87à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89|หมวดหมู่นี้มี $1 ไฟล์ จากทั้งหมด $2 ไฟล์}}",
        "category-file-count-limited": "{{PLURAL:$1|ไฟล์|ไฟล์}}ต่อไปนี้อยู่ในหมวดหมู่นี้",
        "listingcontinuesabbrev": "ต่อ",
        "index-category": "หน้าที่มีดัชนี",
        "mypage": "หน้า",
        "mytalk": "พูดคุย",
        "anontalk": "พูดคุยกับเลขที่อยู่ไอพีนี้",
-       "navigation": "à¸\9bà¹\89ายà¸\9aอà¸\81ทาง",
+       "navigation": "à¸\81ารà¸\99ำทาง",
        "and": "&#32;และ",
        "qbfind": "ค้นหา",
        "qbbrowse": "สืบค้น",
        "actions": "ปฏิบัติการ",
        "namespaces": "เนมสเปซ",
        "variants": "สิ่งที่แตกต่าง",
-       "navigation-heading": "รายà¸\81ารà¹\80ลือà¸\81à¸\9bà¹\89ายà¸\9aอà¸\81ทาง",
+       "navigation-heading": "รายà¸\81ารà¹\80ลือà¸\81à¸\81ารà¸\99ำทาง",
        "errorpagetitle": "มีข้อผิดพลาด",
-       "returnto": "กลับไปที่ $1",
+       "returnto": "กลับไป $1",
        "tagline": "จาก {{SITENAME}}",
-       "help": "à¸\84ำอà¸\98ิà¸\9aาย",
+       "help": "วิà¸\98ีà¹\83à¸\8aà¹\89",
        "search": "ค้นหา",
        "searchbutton": "ค้นหา",
        "go": "ไป",
        "history_short": "ประวัติ",
        "updatedmarker": "ถูกปรับตั้งแต่การเข้าชมครั้งล่าสุดของฉัน",
        "printableversion": "รุ่นพร้อมพิมพ์",
-       "permalink": "ลิà¸\87à¸\81à¹\8cถาวร",
+       "permalink": "à¸\81ารà¹\82ยà¸\87ถาวร",
        "print": "พิมพ์",
        "view": "ดู",
        "view-foreign": "ดูบน $1",
        "talkpagelinktext": "พูดคุย",
        "specialpage": "หน้าพิเศษ",
        "personaltools": "เครื่องมือส่วนตัว",
-       "postcomment": "ส่วนใหม่",
        "articlepage": "ดูหน้าเนื้อหา",
        "talk": "อภิปราย",
        "views": "ดู",
        "otherlanguages": "ในภาษาอื่น",
        "redirectedfrom": "(เปลี่ยนทางจาก $1)",
        "redirectpagesub": "หน้าเปลี่ยนทาง",
-       "lastmodifiedat": "หน้านี้แก้ไขล่าสุดเมื่อวันที่ $1 เวลา $2",
-       "viewcount": "หน้านี้มีการเข้าชม $1 ครั้ง",
+       "redirectto": "เปลี่ยนทางไป:",
+       "lastmodifiedat": "ดัดแปรหน้านี้ล่าสุดเมื่อวันที่ $1 เวลา $2",
+       "viewcount": "หน้านี้มีการเข้าถึง $1 ครั้ง",
        "protectedpage": "หน้าถูกล็อก",
        "jumpto": "ข้ามไปยัง:",
-       "jumptonavigation": "นำทาง",
+       "jumptonavigation": "à¸\81ารà¸\99ำà¸\97าà¸\87",
        "jumptosearch": "ค้นหา",
        "view-pool-error": "ขออภัย ขณะนี้เซิร์ฟเวอร์มีภาระเกิน\nผู้ใช้พยายามดูหน้านี้มากเกินไป\nกรุณารอสักครู่ก่อนเข้าหน้านี้อีกครั้ง\n\n$1",
        "generic-pool-error": "ขออภัย ขณะนี้เซิร์ฟเวอร์โหลดเกิน\nมีผู้ใช้พยายามดูทรัพยากรนี้มากเกินไป\nโปรดรอสักครู่ก่อนลองเข้าถึงทรัพยากรนี้อีกครั้ง",
        "portal-url": "Project:ศูนย์รวมชุมชน",
        "privacy": "นโยบายสิทธิส่วนบุคคล",
        "privacypage": "Project:นโยบายสิทธิส่วนบุคคล",
-       "badaccess": "มีข้อผิดพลาดในการใช้สิทธิ",
+       "badaccess": "มีข้อผิดพลาดในการใช้สิทธิ",
        "badaccess-group0": "คุณไม่ได้รับอนุญาตให้ดำเนินการตามที่ขอ",
-       "badaccess-groups": "ปฏิบัติการที่คุณขอนี้สงวนไว้เฉพาะผู้ใช้ใน{{PLURAL:$2|กลุ่ม|กลุ่ม}}: $1",
+       "badaccess-groups": "ปฏิบัติการที่คุณขอนี้สงวนไว้เฉพาะผู้ใช้ใน{{PLURAL:$2|กลุ่ม|กลุ่มเหล่านี้}}: $1",
        "versionrequired": "ต้องการมีเดียวิกิรุ่น $1",
        "versionrequiredtext": "การใช้หน้านี้ต้องการมีเดียวิกิรุ่น $1  ดู[[Special:Version|หน้ารุ่น]]",
        "ok": "ตกลง",
        "hidetoc": "ซ่อน",
        "collapsible-collapse": "ยุบ",
        "collapsible-expand": "ขยาย",
+       "confirmable-confirm": "คุณแน่ใจหรือ",
+       "confirmable-yes": "ใช่",
+       "confirmable-no": "ไม่",
        "thisisdeleted": "ดูหรือกู้คืน $1 หรือไม่",
        "viewdeleted": "ดู $1 หรือไม่",
        "restorelink": "$1 การแก้ไขที่ถูกลบ",
-       "feedlinks": "ฟีด",
+       "feedlinks": "ฟีด:",
        "feed-invalid": "ฟีดที่สมัครไม่ถูกชนิด",
        "feed-unavailable": "ฟีดไม่ถูกเปิดการใช้งาน",
        "site-rss-feed": "ฟีดอาร์เอสเอส $1",
        "nosuchactiontext": "การกระทำที่กำหนดผ่านยูอาร์แอลดังกล่าวไม่สามารถใช้ได้\nคุณอาจกรอกยูอาร์แอลผิด หรือมาตามลิงก์ที่ไม่ถูกต้อง\nหรืออาจเกิดจากข้อผิดพลาดในซอฟต์แวร์ซึ่ง {{SITENAME}} ใช้อยู่",
        "nosuchspecialpage": "ไม่มีหน้าพิเศษดังกล่าว",
        "nospecialpagetext": "<strong>คุณขอหน้าพิเศษไม่ถูกต้อง</strong>\n\nรายการหน้าพิเศษที่ถูกต้องดูได้ที่ [[Special:SpecialPages|รายการหน้าพิเศษ]]",
-       "error": "ผิดพลาด",
-       "databaseerror": "ผิดพลาดที่ฐานข้อมูล",
+       "error": "à¸\82à¹\89อà¸\9cิà¸\94à¸\9eลาà¸\94",
+       "databaseerror": "à¸\82à¹\89อà¸\9cิà¸\94à¸\9eลาà¸\94à¸\97ีà¹\88à¸\90าà¸\99à¸\82à¹\89อมูล",
        "databaseerror-text": "เกิดความผิดพลาดข้อคำถามของฐานข้อมูล\nซึ่งอาจบ่งชี้ว่ามีจุดบกพร่องในซอฟต์แวร์",
        "databaseerror-textcl": "เกิดความผิดพลาดข้อคำถามของฐานข้อมูล",
        "databaseerror-query": "ข้อคำถาม: $1",
        "databaseerror-function": "ฟังก์ชัน: $1",
-       "databaseerror-error": "à¸\84วามผิดพลาด: $1",
-       "laggedslavemode": "'''คำเตือน:''' ข้อมูลในหน้าอาจไม่ใช่ข้อมูลล่าสุด",
+       "databaseerror-error": "à¸\82à¹\89อผิดพลาด: $1",
+       "laggedslavemode": "<strong>คำเตือน:</strong> หน้านี้อาจไม่มีการปรับล่าสุด",
        "readonly": "ฐานข้อมูลถูกล็อก",
        "enterlockreason": "ใส่เหตุแห่งการล็อก ทั้งเวลาที่คาดว่าจะปลดล็อก",
-       "readonlytext": "à¸\82à¸\93ะà¸\99ีà¹\89à¸\90าà¸\99à¸\82à¹\89อมูลà¸\96ูà¸\81ลà¹\87อà¸\81มิà¹\83หà¹\89รัà¸\9aà¸\82à¹\89อมูลà¹\83หมà¹\88à¹\81ละà¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87อื่น อาจเป็นเพราะการบำรุงรักษาฐานข้อมูลรูทีน หลังแล้วเสร็จจะกลับมาใช้งานได้ตามปกติ\n\nผู้ดูแลระบบที่ล็อกได้ให้คำอธิบายดังนี้: $1",
-       "missing-article": "à¸\90าà¸\99à¸\82à¹\89อมูลà¹\84มà¹\88à¸\9eà¸\9aà¹\80à¸\99ืà¹\89อหาà¸\82อà¸\87หà¸\99à¹\89าà¸\97ีà¹\88à¸\84วรà¸\88ะมี à¹\83à¸\99à¸\8aืà¹\88อ \"$1\" $2\n\nสาà¹\80หà¸\95ุมัà¸\81à¹\80à¸\81ิà¸\94à¸\88าà¸\81à¸\81ารà¹\80à¸\9bรียà¸\9aà¹\80à¸\97ียà¸\9aà¸\97ีà¹\88ลà¹\89าสมัย à¸«à¸£à¸·à¸­à¸\81ารà¹\80à¸\8aืà¹\88อมà¹\82ยà¸\87à¸\9bระวัà¸\95ิà¹\84à¸\9bยัà¸\87หà¸\99à¹\89าà¸\99ัà¹\89à¸\99à¹\84à¸\94à¹\89à¸\96ูà¸\81ลà¸\9aà¹\81ลà¹\89ว\n\nหาà¸\81à¹\84มà¹\88à¹\83à¸\8aà¹\88à¸\81รà¸\93ีà¸\94ัà¸\87à¸\81ลà¹\88าว à¸\84ุà¸\93อาà¸\88à¸\9eà¸\9aà¸\9aัà¹\8aà¸\81ในซอฟต์แวร์ กรุณารายงานต่อ[[Special:ListUsers/sysop|ผู้ดูแลระบบ]] พร้อมระบุยูอาร์แอล",
-       "missingarticle-rev": "(รุ่น#: $1)",
+       "readonlytext": "à¸\82à¸\93ะà¸\99ีà¹\89à¸\90าà¸\99à¸\82à¹\89อมูลà¸\96ูà¸\81ลà¹\87อà¸\81มิà¹\83หà¹\89รัà¸\9aà¸\82à¹\89อมูลà¹\83หมà¹\88à¹\81ละà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¹\80à¸\9eิà¹\88มà¹\80à¸\95ิมอื่น อาจเป็นเพราะการบำรุงรักษาฐานข้อมูลรูทีน หลังแล้วเสร็จจะกลับมาใช้งานได้ตามปกติ\n\nผู้ดูแลระบบที่ล็อกได้ให้คำอธิบายดังนี้: $1",
+       "missing-article": "à¸\90าà¸\99à¸\82à¹\89อมูลà¹\84มà¹\88à¸\9eà¸\9aà¸\82à¹\89อà¸\84วามà¸\82อà¸\87หà¸\99à¹\89าà¸\97ีà¹\88à¸\84วรมี à¸\8aืà¹\88อ \"$1\" $2\n\nสาà¹\80หà¸\95ุมัà¸\81à¹\80à¸\81ิà¸\94à¸\88าà¸\81à¸\9cลà¸\95à¹\88าà¸\87à¸\97ีà¹\88ลà¹\89าสมัย à¸«à¸£à¸·à¸­à¸\81ารà¹\80à¸\8aืà¹\88อมà¹\82ยà¸\87à¸\9bระวัà¸\95ิà¹\84à¸\9bยัà¸\87หà¸\99à¹\89าà¸\99ัà¹\89à¸\99à¸\96ูà¸\81ลà¸\9aà¹\81ลà¹\89ว\n\nหาà¸\81à¹\84มà¹\88à¹\83à¸\8aà¹\88à¸\81รà¸\93ีà¸\94ัà¸\87à¸\81ลà¹\88าว à¸\84ุà¸\93อาà¸\88à¸\9eà¸\9aà¸\88ุà¸\94à¸\9aà¸\81à¸\9eรà¹\88อà¸\87ในซอฟต์แวร์ กรุณารายงานต่อ[[Special:ListUsers/sysop|ผู้ดูแลระบบ]] พร้อมระบุยูอาร์แอล",
+       "missingarticle-rev": "(รุ่นปรับปรุง#: $1)",
        "missingarticle-diff": "(ต่าง: $1, $2)",
        "readonly_lag": "ฐานข้อมูลถูกล็อกอัตโนมัติขณะที่เซิร์ฟเวอร์ฐานข้อมูลรองกำลังปรับปรุงตามฐานข้อมูลหลัก",
-       "internalerror": "à¹\80à¸\81ิà¸\94à¸\84วามผิดพลาดภายใน",
-       "internalerror_info": "à¹\80à¸\81ิà¸\94à¸\84วามผิดพลาดภายใน: $1",
+       "internalerror": "à¸\82à¹\89อผิดพลาดภายใน",
+       "internalerror_info": "à¹\80à¸\81ิà¸\94à¸\82à¹\89อผิดพลาดภายใน: $1",
        "filecopyerror": "ไม่สามารถคัดลอกไฟล์ \"$1\" ไปที่ \"$2\"",
        "filerenameerror": "ไม่สามารถเปลี่ยนชื่อไฟล์ \"$1\" เป็น \"$2\"",
        "filedeleteerror": "ไม่สามารถลบไฟล์ \"$1\"",
        "directorycreateerror": "ไม่สามารถสร้างไดเรกทอรี \"$1\"",
        "filenotfound": "ไม่พบไฟล์ \"$1\"",
        "unexpected": "ผลที่ไม่คาดคิด: \"$1\"=\"$2\"",
-       "formerror": "à¸\9cิà¸\94à¸\9eลาà¸\94: à¹\84มà¹\88สามารà¸\96สà¹\88à¸\87à¹\81à¸\9aà¸\9aได้",
-       "badarticleerror": "à¸\81ารà¸\81ระà¸\97ำà¸\99ีà¹\89à¹\84มà¹\88สามารà¸\96à¸\97ำà¹\83à¸\99หà¸\99à¹\89าà¸\99ีà¹\89à¹\84à¸\94้",
+       "formerror": "à¸\82à¹\89อà¸\9cิà¸\94à¸\9eลาà¸\94: à¸ªà¹\88à¸\87à¹\81à¸\9aà¸\9aà¹\84มà¹\88ได้",
+       "badarticleerror": "à¹\84มà¹\88สามารà¸\96à¸\94ำà¹\80à¸\99ิà¸\99à¸\9bà¸\8fิà¸\9aัà¸\95ิà¸\81ารà¸\99ีà¹\89à¹\83à¸\99หà¸\99à¹\89าà¸\99ี้",
        "cannotdelete": "ไม่สามารถลบหน้าหรือไฟล์ \"$1\" \nอาจมีผู้อื่นลบไปแล้ว",
        "cannotdelete-title": "ไม่สามารถลบหน้า ''$1''",
-       "delete-hook-aborted": "à¸\81ารลà¸\9aà¸\96ูà¸\81ฮุà¸\81ยà¸\81à¹\80ลิà¸\81\nà¹\82à¸\94ยà¹\84มà¹\88มีà¸\84ำอà¸\98ิà¸\9aาย",
+       "delete-hook-aborted": "à¸\81ารลà¸\9aà¸\96ูà¸\81ฮุà¸\81ยà¸\81à¹\80ลิà¸\81\nà¹\82à¸\94ยà¹\84มà¹\88มีà¸\84ำà¸\8aีà¹\89à¹\81à¸\88à¸\87",
        "no-null-revision": "ไม่สามารถสร้างรุ่นว่างใหม่ของหน้า \"$1\"",
        "badtitle": "ใช้ชื่อเรื่องนี้ไม่ได้",
        "badtitletext": "ชื่อหน้าที่ขอไม่ถูกต้อง เป็นชื่อว่าง หรือชื่อข้ามภาษาหรือข้ามวิกิที่เชื่อมโยงไม่ถูกต้อง\nอาจมีอักขระที่ไม่สามารถใช้ในชื่อเรื่องได้",
        "perfcached": "ข้อมูลต่อไปนี้ถูกเก็บในแคช และอาจล้าสมัย มีผลการค้นหาสูงสุด $1 รายการในแคช",
        "perfcachedts": "ข้อมูลต่อไปนี้ถูกเก็บในแคช และได้รับการปรับล่าสุดเมื่อ $1 ผลลัพธ์สูงสุด $4 รายการสามารถเก็บในแคชได้",
-       "querypage-no-updates": "à¸\82à¸\93ะà¸\99ีà¹\89à¸\81ารà¸\9bรัà¸\9aà¸\9bรุà¸\87หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81ระà¸\87ัà¸\9a ข้อมูลในที่นี้จะไม่รีเฟรชเป็นปัจจุบัน",
+       "querypage-no-updates": "à¸\82à¸\93ะà¸\99ีà¹\89à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\81ารà¸\9bรัà¸\9aหà¸\99à¹\89าà¸\99ีà¹\89 \nข้อมูลในที่นี้จะไม่รีเฟรชเป็นปัจจุบัน",
        "viewsource": "ดูโค้ด",
        "viewsource-title": "ดูโค้ดสำหรับ $1",
-       "actionthrottled": "à¸\81ารà¸\81ระà¸\97ำà¸\99ีà¹\89à¸\96ูà¸\81ระà¸\87ัà¸\9aà¹\84วà¹\89à¸\8aัà¹\88วà¸\84ราว",
-       "actionthrottledtext": "à¹\80à¸\9eืà¹\88อà¹\80à¸\9bà¹\87à¸\99มาà¸\95รà¸\81ารà¸\9bà¹\89อà¸\87à¸\81ัà¸\99สà¹\81à¸\9bม à¸\84ุà¸\93à¸\88ึà¸\87à¸\96ูà¸\81à¸\88ำà¸\81ัà¸\94มิà¹\83หà¹\89à¸\81ระà¸\97ำสิà¹\88à¸\87à¸\99ีà¹\89à¹\84มà¹\88à¹\83หà¹\89à¸\95ิà¸\94à¸\95à¹\88อà¸\81ัà¸\99หลายà¸\84รัà¹\89à¸\87à¹\80à¸\81ิà¸\99à¹\84à¸\9bà¹\83à¸\99à¸\8aà¹\88วà¸\87ระยะà¹\80วลาสัà¹\89à¸\99 à¹\86 à¸\8bึà¹\88à¸\87à¸\82à¸\93ะà¸\99ีà¹\89à¸\84ุà¸\93à¹\84à¸\94à¹\89à¸\81ระà¸\97ำà¹\80à¸\81ิà¸\99à¸\82ีà¸\94à¸\88ำà¸\81ัà¸\94à¹\81ลà¹\89ว กรุณารอสักครู่แล้วลองอีกครั้ง",
-       "protectedpagetext": "หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81ลà¹\87อà¸\81à¹\80à¸\9eืà¹\88อà¸\9bà¹\89อà¸\87à¸\81ัà¸\99มิà¹\83หà¹\89แก้ไขหรือปฏิบัติการอื่น",
+       "actionthrottled": "à¸\9bà¸\8fิà¸\9aัà¸\95ิà¸\81ารà¸\96ูà¸\81à¸\88ำà¸\81ัà¸\94",
+       "actionthrottledtext": "à¹\80à¸\9eืà¹\88อà¹\80à¸\9bà¹\87à¸\99มาà¸\95รà¸\81ารà¸\9bà¹\89อà¸\87à¸\81ัà¸\99สà¹\81à¸\9bม à¸\84ุà¸\93à¸\88ึà¸\87à¸\96ูà¸\81à¸\88ำà¸\81ัà¸\94มิà¹\83หà¹\89à¸\81ระà¸\97ำสิà¹\88à¸\87à¸\99ีà¹\89à¹\84มà¹\88à¹\83หà¹\89à¸\95ิà¸\94à¸\95à¹\88อà¸\81ัà¸\99หลายà¸\84รัà¹\89à¸\87à¹\80à¸\81ิà¸\99à¹\84à¸\9bà¹\83à¸\99à¸\8aà¹\88วà¸\87ระยะà¹\80วลาสัà¹\89à¸\99 à¹\86 à¸\8bึà¹\88à¸\87à¸\82à¸\93ะà¸\99ีà¹\89à¸\84ุà¸\93à¹\80ลยà¸\82ีà¸\94à¸\88ำà¸\81ัà¸\94à¸\99ีà¹\89à¹\81ลà¹\89ว \nกรุณารอสักครู่แล้วลองอีกครั้ง",
+       "protectedpagetext": "หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81ลà¹\87อà¸\81à¹\80à¸\9eืà¹\88อà¸\9bà¹\89อà¸\87à¸\81ัà¸\99à¸\81ารแก้ไขหรือปฏิบัติการอื่น",
        "viewsourcetext": "คุณสามารถดูและคัดลอกโค้ดของหน้านี้:",
-       "viewyourtext": "คุณสามารถดูและคัดลอกต้นฉบับ'''การแก้ไขของคุณ'''ในหน้านี้ได้",
+       "viewyourtext": "คุณสามารถดูและคัดลอกต้นฉบับ<strong>การแก้ไขของคุณ</strong>มายังหน้านี้ได้:",
        "protectedinterface": "หน้านี้เป็นข้อความอินเตอร์เฟซสำหรับซอฟต์แวร์บนวิกินี้ และถูกป้องกันเพื่อมิให้มีการกระทำผิด\nในการเพิ่มหรือเปลี่ยนแปลงการแปลสำหรับทุกวิกิ โปรดใช้ [//translatewiki.net/ translatewiki.net] โครงการแปลมีเดียวิกิเป็นภาษาถิ่น",
        "editinginterface": "'''คำเตือน:''' คุณกำลังแก้ไขหน้าที่ใช้เพื่อให้ข้อความอินเตอร์เฟซแก่ซอฟต์แวร์\nการเปลี่ยนแปลงหน้านี้จะกระทบต่อลักษณะของอินเตอร์เฟซผู้ใช้แก่ผู้ใช้อื่นบนวิกินี้\nในการเพิ่มหรือเปลี่ยนแปลงคำแปลสำหรับทุกวิกิ โปรดใช้ [//translatewiki.net/wiki/Main_Page?setlang=th translatewiki.net] โครงการแปลมีเดียวิกิเป็นภาษาถิ่น",
-       "cascadeprotected": "หà¸\99à¹\89าà¸\99ีà¹\89à¹\84à¸\94à¹\89รัà¸\9aà¸\81ารà¸\9bà¹\89อà¸\87à¸\81ัà¸\99à¸\88าà¸\81à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82 à¹\80à¸\99ืà¹\88อà¸\87à¸\88าà¸\81หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81à¹\83à¸\8aà¹\89à¹\80à¸\9bà¹\87à¸\99สà¹\88วà¸\99หà¸\99ึà¹\88à¸\87à¹\83à¸\99{{PLURAL:$1|หà¸\99à¹\89า $2 à¸\8bึà¹\88à¸\87à¹\84à¸\94à¹\89รัà¸\9aà¸\81ารà¸\9bà¹\89อà¸\87à¸\81ัà¸\99à¹\81à¸\9aà¸\9a \"à¸\97à¸\9aà¸\97ุà¸\81ลำà¸\94ัà¸\9aà¸\82ัà¹\89à¸\99\"|หà¸\99à¹\89าà¸\8bึà¹\88à¸\87à¹\84à¸\94à¹\89รัà¸\9aà¸\81ารà¸\9bà¹\89อà¸\87à¸\81ัà¸\99à¹\81à¸\9aà¸\9a \"à¸\97à¸\9aà¸\97ุà¸\81ลำà¸\94ัà¸\9aà¸\82ัà¹\89à¸\99\" à¸\94ัà¸\87à¸\95à¹\88อà¹\84à¸\9bà¸\99ีà¹\89: $2}}",
+       "cascadeprotected": "หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81à¸\9bà¹\89อà¸\87à¸\81ัà¸\99มิà¹\83หà¹\89à¹\81à¸\81à¹\89à¹\84à¸\82 à¹\80à¸\9eราะà¸\96ูà¸\81รวมอยูà¹\88à¹\83à¸\99หà¸\99à¹\89าà¸\8bึà¹\88à¸\87à¸\96ูà¸\81ลà¹\87อà¸\81à¹\82à¸\94ยà¹\80à¸\9bิà¸\94à¸\95ัวà¹\80ลือà¸\81 \"à¸\97à¸\9aà¸\97ุà¸\81ลำà¸\94ัà¸\9aà¸\82ัà¹\89à¸\99\":\n$2",
        "namespaceprotected": "คุณไม่มีสิทธิแก้ไขหน้าในเนมสเปซ <strong>$1</strong>",
-       "customcssprotected": "à¸\84ุà¸\93à¹\84มà¹\88มีสิà¸\97à¸\98ิà¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าสà¹\84à¸\95ลà¹\8c CSS à¸\99ีà¹\89 à¹\80à¸\99ืà¹\88อà¸\87à¸\88าà¸\81หà¸\99à¹\89าà¸\99ีà¹\89มีการตั้งค่าส่วนบุคคลของผู้ใช้อื่น",
-       "customjsprotected": "à¸\84ุà¸\93à¹\84มà¹\88มีสิà¸\97à¸\98ิà¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¸\88าวาสà¸\84ริà¸\9bà¸\95à¹\8cà¸\99ีà¹\89 à¹\80à¸\99ืà¹\88อà¸\87à¸\88าà¸\81หน้านี้มีการตั้งค่าส่วนบุคคลของผู้ใช้อื่น",
+       "customcssprotected": "à¸\84ุà¸\93à¹\84มà¹\88มีสิà¸\97à¸\98ิà¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าสà¹\84à¸\95ลà¹\8c CSS à¸\99ีà¹\89 à¹\80à¸\9eราะมีการตั้งค่าส่วนบุคคลของผู้ใช้อื่น",
+       "customjsprotected": "à¸\84ุà¸\93à¹\84มà¹\88มีสิà¸\97à¸\98ิà¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¸\88าวาสà¸\84ริà¸\9bà¸\95à¹\8cà¸\99ีà¹\89 à¹\80à¸\9eราะหน้านี้มีการตั้งค่าส่วนบุคคลของผู้ใช้อื่น",
        "mycustomcssprotected": "คุณไม่ได้รับอนุญาตให้แก้ไขหน้าซีเอสเอสนี้",
        "mycustomjsprotected": "คุณไม่ได้รับอนุญาตให้แก้ไขหน้าจาวาสคริปต์นี้",
        "myprivateinfoprotected": "คุณไม่ได้รับอนุญาตให้แก้ไขข้อมูลส่วนตัวของคุณ",
        "mypreferencesprotected": "คุณไม่ได้รับอนุญาตให้แก้ไขการตั้งค่าของคุณ",
-       "ns-specialprotected": "หà¸\99à¹\89าà¸\9eิà¹\80ศษà¹\84มà¹\88สามารà¸\96à¹\81à¸\81à¹\89à¹\84à¸\82à¹\84à¸\94à¹\89",
-       "titleprotected": "ชื่อเรื่องนี้ถูกป้องกันมิให้สร้างโดย [[User:$1|$1]] \nเหตุผลที่ให้ไว้คือ ''<em>$2</em>''",
-       "filereadonlyerror": "ไม่สามารถแก้ไขไฟล์ \"$1\" เพราะที่เก็บไฟล์ \"$2\" อยู่ในภาวะอ่านอย่างเดียว\nผู้ดูแลระบบที่ล็อกให้คำอธิบายว่า: \"$3\"",
+       "ns-specialprotected": "à¹\84มà¹\88สามารà¸\96à¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¸\9eิà¹\80ศษ",
+       "titleprotected": "ชื่อเรื่องนี้ถูก [[User:$1|$1]] ป้องกันมิให้สร้าง\nเหตุผลที่ให้ไว้คือ ''<em>$2</em>''",
+       "filereadonlyerror": "ไม่สามารถแก้ไขไฟล์ \"$1\" เพราะที่เก็บไฟล์ \"$2\" อยู่ในภาวะอ่านอย่างเดียว\n\nผู้ดูแลระบบที่ล็อกให้คำอธิบายว่า: \"$3\"",
        "invalidtitle-knownnamespace": "ชื่อเรื่องที่มีเนมสเปซ \"$2\" กับข้อความ \"$3\" ไม่ถูกต้อง",
        "invalidtitle-unknownnamespace": "ชื่อเรื่องที่ไม่ทราบเนมสเปซหมายเลข $1 กับข้อความ \"$2\" ไม่ถูกต้อง",
        "exception-nologin": "ไม่ได้ล็อกอิน",
-       "exception-nologin-text": "โปรด[[Special:Userlogin|ล็อกอิน]]เพื่อสามารถเข้าถึงหน้าหรือปฏิบัติการนี้",
+       "exception-nologin-text": "โปรดล็อกอินเพื่อสามารถเข้าถึงหน้าหรือปฏิบัติการนี้",
        "exception-nologin-text-manual": "โปรด$1เพื่อสามารถเข้าถึงหน้าหรือปฏิบัติการนี้",
-       "virus-badscanner": "โครงแบบผิดพลาด: ไม่รู้จักตัวสแกนไวรัส: ''$1''",
+       "virus-badscanner": "โครงแบบผิดพลาด: ไม่รู้จักตัวสแกนไวรัส: <em>$1</em>",
        "virus-scanfailed": "การสแกนล้มเหลว (โค้ด $1)",
        "virus-unknownscanner": "ไม่รู้จักโปรแกรมป้องกันไวรัสตัวนี้:",
-       "logouttext": "'''ขณะนี้คุณได้ล็อกเอาต์แล้ว'''\n\nหมายเหตุว่า บางหน้าอาจยังแสดงผลเสมือนว่าคุณกำลังล็อกอินอยู่ จนกว่าคุณจะล้างแคชเบราว์เซอร์ของคุณ",
+       "logouttext": "<strong>คุณล็อกเอาต์แล้ว</strong>\n\nหมายเหตุว่า บางหน้าอาจยังแสดงผลเสมือนว่าคุณยังล็อกอินอยู่ จนกว่าคุณจะล้างแคชเบราว์เซอร์ของคุณ",
        "welcomeuser": "ยินดีต้อนรับ $1!",
-       "welcomecreation-msg": "à¸\9aัà¸\8dà¸\8aีà¸\82อà¸\87à¸\84ุà¸\93à¸\96ูà¸\81สรà¹\89าà¸\87à¸\82ึà¹\89à¸\99à¹\81ลà¹\89ว\nอยà¹\88าลืมà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87[[Special:Preferences|à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¹\83à¸\99 {{SITENAME}}]] à¸\82อà¸\87à¸\84ุà¸\93",
-       "yourname": "ชื่อผู้ใช้",
+       "welcomecreation-msg": "สรà¹\89าà¸\87à¸\9aัà¸\8dà¸\8aีà¸\82อà¸\87à¸\84ุà¸\93à¹\81ลà¹\89ว\nà¸\84ุà¸\93สามารà¸\96à¹\80à¸\9bลีà¹\88ยà¸\99[[Special:Preferences|à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88า]] {{SITENAME}} à¸\82อà¸\87à¸\84ุà¸\93à¹\84à¸\94à¹\89หาà¸\81à¸\95à¹\89อà¸\87à¸\81าร",
+       "yourname": "ชื่อผู้ใช้:",
        "userlogin-yourname": "ชื่อผู้ใช้",
        "userlogin-yourname-ph": "กรอกชื่อผู้ใช้",
        "createacct-another-username-ph": "กรอกชื่อผู้ใช้",
-       "yourpassword": "รหัสผ่าน",
+       "yourpassword": "รหัสผ่าน:",
        "userlogin-yourpassword": "รหัสผ่าน",
        "userlogin-yourpassword-ph": "กรอกรหัสผ่าน",
        "createacct-yourpassword-ph": "กรอกรหัสผ่าน",
        "userlogin-signwithsecure": "ใช้การเชื่อมต่อที่ปลอดภัย",
        "yourdomainname": "โดเมนของคุณ:",
        "password-change-forbidden": "คุณไม่สามารถเปลี่ยนรหัสผ่านบนวิกินี้",
-       "externaldberror": "มีà¸\82à¹\89อà¸\9cิà¸\94à¸\9eลาà¸\94à¸\82อà¸\87à¸\90าà¸\99à¸\82à¹\89อมูลà¹\83à¸\99à¸\81ารà¸\9eิสูà¸\88à¸\99à¹\8cà¸\95ัวà¸\88ริà¸\87 à¸«à¸£à¸·à¸­à¸\84ุà¸\93à¹\84มà¹\88à¹\84à¸\94à¹\89รัà¸\9aอà¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¸\9bรัà¸\9aà¸\9aัà¸\8dà¸\8aีภายà¸\99อà¸\81à¸\82อà¸\87à¸\84ุà¸\93",
+       "externaldberror": "มีข้อผิดพลาดของฐานข้อมูลการพิสูจน์ตัวจริง หรือคุณไม่ได้รับอนุญาตให้ปรับบัญชีภายนอกของคุณ",
        "login": "ล็อกอิน",
        "nav-login-createaccount": "ล็อกอิน / สร้างบัญชี",
-       "loginprompt": "ต้องเปิดใช้คุกกี้ก่อนจะล็อกอินเข้าสู่ {{SITENAME}}",
        "userlogin": "ล็อกอิน / สร้างบัญชี",
        "userloginnocreate": "ล็อกอิน",
        "logout": "ล็อกเอาต์",
        "userlogin-resetlink": "ลืมรายละเอียดล็อกอินของคุณหรือ",
        "userlogin-resetpassword-link": "ลืมรหัสผ่านหรือ",
        "userlogin-helplink2": "วิธีใช้เรื่องการล็อกอิน",
-       "userlogin-loggedin": "คุณล็อกอินในชื่อ {{GENDER:$1|$1}} แล้ว\nใช้แบบด้านล่างเพื่อล็อกอินเป็นอีกผู้ใช้หนึ่ง",
-       "userlogin-createanother": "สร้างอีกบัญชี",
        "createacct-emailrequired": "ที่อยู่อีเมล",
        "createacct-emailoptional": "ที่อยู่อีเมล (เลือกไม่ใส่ได้)",
        "createacct-email-ph": "กรอกที่อยู่อีเมล",
        "createacct-benefit-body1": "$1 การแก้ไข",
        "createacct-benefit-body2": "$1 หน้า",
        "createacct-benefit-body3": "$1 ผู้ร่วมเขียน",
-       "badretype": "รหัสà¸\9cà¹\88าà¸\99à¸\97ีà¹\88à¹\83สà¹\88ไม่ตรงกัน",
-       "userexists": "à¸\8aืà¹\88อà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88à¸\81รอà¸\81มีà¸\9cูà¹\89อืà¹\88à¸\99à¹\83à¸\8aà¹\89à¹\84à¸\9bà¹\81ลà¹\89ว กรุณาเลือกชื่ออื่น",
+       "badretype": "รหัสà¸\9cà¹\88าà¸\99à¸\97ีà¹\88à¸\84ุà¸\93à¸\81รอà¸\81ไม่ตรงกัน",
+       "userexists": "à¸\8aืà¹\88อà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88à¸\81รอà¸\81มีà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\81ลà¹\89ว \nกรุณาเลือกชื่ออื่น",
        "loginerror": "ล็อกอินผิดพลาด",
        "createacct-error": "การสร้างบัญชีผิดพลาด",
-       "createaccounterror": "ไม่สามารถสร้างบัญชีผู้ใช้: $1",
-       "nocookiesnew": "à¸\8aืà¹\88อà¸\9aัà¸\8dà¸\8aีà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\84à¸\94à¹\89à¸\96ูà¸\81สรà¹\89าà¸\87à¸\82ึà¹\89à¸\99à¹\81ลà¹\89ว à¹\81à¸\95à¹\88ยัà¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89ลà¹\87อà¸\81อิà¸\99à¹\80à¸\82à¹\89าสูà¹\88 {{SITENAME}} à¹\80à¸\99ืà¹\88อà¸\87à¸\88าà¸\81วà¹\88าà¹\84มà¹\88à¹\84à¸\94à¹\89à¹\80à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\84ุà¸\81à¸\81ีà¹\89 à¸\96à¹\89าà¸\95à¹\89อà¸\87à¸\81ารลà¹\87อà¸\81อิà¸\99à¹\83หà¹\89à¹\80à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\84ุà¸\81à¸\81ีà¹\89à¹\81ละà¸\97ำà¸\81ารลà¹\87อà¸\81อิà¸\99à¹\82à¸\94ยà¹\83สà¹\88à¸\8aืà¹\88อà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\9eรà¹\89อมรหัสà¸\9cà¹\88าà¸\99",
-       "nocookieslogin": "{{SITENAME}} à¹\83à¸\8aà¹\89à¸\84ุà¸\81à¸\81ีà¹\89สำหรัà¸\9aà¸\81ารลà¹\87อà¸\81อิà¸\99 à¸\82à¸\93ะà¸\99ีà¹\89à¸\84ุà¸\81à¸\81ีà¹\89à¸\82อà¸\87à¸\84ุà¸\93à¹\84มà¹\88à¹\80à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99 กรุณาเปิดใช้งานและลองอีกครั้ง",
-       "nocookiesfornew": "à¸\9aัà¸\8dà¸\8aีà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\84มà¹\88à¸\96ูà¸\81สรà¹\89าà¸\87 à¹\80à¸\99ืà¹\88อà¸\87à¸\88าà¸\81à¹\80ราà¹\84มà¹\88สามารà¸\96ยืà¸\99ยัà¸\99à¹\81หลà¹\88à¸\87à¸\97ีà¹\88มา\nà¸\81รุà¸\93าà¹\81à¸\99à¹\88à¹\83à¸\88วà¹\88าà¸\84ุà¸\93à¹\84à¸\94à¹\89à¹\80à¸\9bิà¸\94à¹\83à¸\8aà¹\89คุกกี้ โหลดหน้านี้ใหม่และลองอีกครั้ง",
+       "createaccounterror": "ไม่สามารถสร้างบัญชี: $1",
+       "nocookiesnew": "สรà¹\89าà¸\87à¸\9aัà¸\8dà¸\8aีà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\81ลà¹\89ว à¹\81à¸\95à¹\88ยัà¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89ลà¹\87อà¸\81อิà¸\99 \n{{SITENAME}} à¹\83à¸\8aà¹\89à¸\84ุà¸\81à¸\81ีà¹\89à¹\80à¸\9eืà¹\88อลà¹\87อà¸\81อิà¸\99à¸\9cูà¹\89à¹\83à¸\8aà¹\89\nà¸\84ุà¸\93à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\84ุà¸\81à¸\81ีà¹\89\nà¹\82à¸\9bรà¸\94à¹\80à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99 à¹\81ลà¹\89วลà¹\87อà¸\81อิà¸\99à¸\9eรà¹\89อมà¸\8aืà¹\88อà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\81ละรหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\82อà¸\87à¸\84ุà¸\93",
+       "nocookieslogin": "{{SITENAME}} à¹\83à¸\8aà¹\89à¸\84ุà¸\81à¸\81ีà¹\89à¹\80à¸\9eืà¹\88อลà¹\87อà¸\81อิà¸\99à¸\9cูà¹\89à¹\83à¸\8aà¹\89\nà¸\84ุà¸\93à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\84ุà¸\81à¸\81ีà¹\89\nกรุณาเปิดใช้งานและลองอีกครั้ง",
+       "nocookiesfornew": "à¸\9aัà¸\8dà¸\8aีà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\84มà¹\88à¸\96ูà¸\81สรà¹\89าà¸\87 à¹\80à¸\99ืà¹\88อà¸\87à¸\88าà¸\81à¹\80ราà¹\84มà¹\88สามารà¸\96ยืà¸\99ยัà¸\99à¸\95à¹\89à¸\99à¸\97าà¸\87\nà¸\81รุà¸\93าà¸\97ำà¹\83หà¹\89à¹\81à¸\99à¹\88à¹\83à¸\88วà¹\88าà¸\84ุà¸\93à¹\84à¸\94à¹\89à¹\80à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99คุกกี้ โหลดหน้านี้ใหม่และลองอีกครั้ง",
        "noname": "คุณไม่ได้ใส่ชื่อผู้ใช้ที่ถูกต้อง",
        "loginsuccesstitle": "ล็อกอินสำเร็จ",
-       "loginsuccess": "'''ขณะนี้คุณล็อกอินเข้าสู่ {{SITENAME}} ด้วยชื่อ \"$1\"'''",
+       "loginsuccess": "<strong>ขณะนี้คุณล็อกอินเข้าสู่ {{SITENAME}} ด้วยชื่อ \"$1\"</strong>",
        "nosuchuser": "ไม่มีผู้ใช้ชื่อ \"$1\"\nชื่อผู้ใช้นั้นไวต่ออักษรใหญ่เล็ก\nกรุณาตรวจการสะกดอีกครั้ง หรือ[[Special:UserLogin/signup|สร้างบัญชีใหม่]]",
-       "nosuchusershort": "ไม่มีผู้ใช้ชื่อ \"$1\" กรุณาตรวจสอบการสะกด",
+       "nosuchusershort": "ไม่มีผู้ใช้ชื่อ \"$1\" \nกรุณาตรวจสอบการสะกด",
        "nouserspecified": "คุณต้องระบุชื่อผู้ใช้",
        "login-userblocked": "ผู้ใช้นี้ถูกบล็อก ไม่อนุญาตให้ล็อกอิน",
-       "wrongpassword": "รหัสà¸\9cà¹\88าà¸\99à¸\97ีà¹\88à¹\83สà¹\88à¹\84มà¹\88à¸\96ูà¸\81à¸\95à¹\89อà¸\87 โปรดลองอีกครั้ง",
-       "wrongpasswordempty": "ยัà¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89ระà¸\9aุรหัสà¸\9cà¹\88าà¸\99 โปรดลองอีกครั้ง",
-       "passwordtooshort": "รหัสà¸\9cà¹\88าà¸\99à¸\95à¹\89อà¸\87มีà¸\84วามยาวอยà¹\88าà¸\87à¸\99à¹\89อย $1 à¸­à¸±à¸\81à¸\82ระ",
+       "wrongpassword": "รหัสà¸\9cà¹\88าà¸\99à¸\97ีà¹\88à¸\81รอà¸\81à¹\84มà¹\88à¸\96ูà¸\81à¸\95à¹\89อà¸\87 \nโปรดลองอีกครั้ง",
+       "wrongpasswordempty": "รหัสà¸\9cà¹\88าà¸\99à¸\97ีà¹\88à¸\81รอà¸\81วà¹\88าà¸\87\nโปรดลองอีกครั้ง",
+       "passwordtooshort": "รหัสผ่านต้องมีอย่างน้อย $1 อักขระ",
        "password-name-match": "รหัสผ่านต้องต่างจากชื่อผู้ใช้",
        "password-login-forbidden": "ห้ามใช้ชื่อผู้ใช้และรหัสผ่านนี้",
        "mailmypassword": "ตั้งรหัสผ่านใหม่",
        "passwordremindertitle": "รหัสผ่านชั่วคราวใหม่สำหรับ {{SITENAME}}",
-       "passwordremindertext": "à¸\9cูà¹\89à¹\83à¸\94à¸\9cูà¹\89หà¸\99ึà¹\88à¸\87 (à¸\8bึà¹\88à¸\87อาà¸\88à¹\80à¸\9bà¹\87à¸\99à¸\84ุà¸\93 à¸\97ีà¹\88à¹\83à¸\8aà¹\89à¹\80ลà¸\82à¸\97ีà¹\88อยูà¹\88à¹\84อà¸\9eี $1) à¸\82อà¹\83หà¹\89สà¹\88à¸\87รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\82อà¸\87 {{SITENAME}} ($4) à¸£à¸«à¸±à¸ªà¸\9cà¹\88าà¸\99à¸\8aัà¹\88วà¸\84ราวสำหรัà¸\9aà¸\8aืà¹\88อà¸\9cูà¹\89à¹\83à¸\8aà¹\89 \"$2\" à¸\96ูà¸\81สรà¹\89าà¸\87à¸\82ึà¹\89à¸\99 à¹\81ละà¸\81ำหà¸\99à¸\94à¹\80à¸\9bà¹\87à¸\99 \"$3\" à¸«à¸²à¸\81à¸\81ารà¸\82อรหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\99ีà¹\89à¹\80à¸\9bà¹\87à¸\99à¹\80à¸\88à¸\95à¸\99าà¸\82อà¸\87à¸\84ุà¸\93 à¸\84ุà¸\93à¸\88ำà¸\95à¹\89อà¸\87ลà¹\87อà¸\81อิà¸\99à¹\81ละà¹\80ลือà¸\81รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88 à¸\93 à¸\82à¸\93ะà¸\99ีà¹\89 à¸£à¸«à¸±à¸ªà¸\9cà¹\88าà¸\99à¸\8aัà¹\88วà¸\84ราวà¸\82อà¸\87à¸\84ุà¸\93à¸\88ะหมà¸\94อายุà¹\83à¸\99 $5 à¸§à¸±à¸\99\n\nหาà¸\81à¹\80à¸\9bà¹\87à¸\99à¸\9aุà¸\84à¸\84ลอืà¹\88à¸\99à¸\97ีà¹\88à¸\82อรหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88 à¸«à¸£à¸·à¸­à¸«à¸²à¸\81à¸\84ุà¸\93à¸\88ำรหัสà¸\9cà¹\88าà¸\99à¸\82อà¸\87à¸\84ุà¸\93à¹\84à¸\94à¹\89à¹\81ลà¹\89ว à¹\81ละà¹\84มà¹\88à¸\95à¹\89อà¸\87à¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88อีà¸\81à¸\95à¹\88อà¹\84à¸\9b คุณอาจละเลยข้อความนี้และใช้รหัสผ่านเดิมของคุณต่อไป",
-       "noemail": "à¹\84มà¹\88มีà¸\97ีà¹\88อยูà¹\88อีà¹\80มลà¸\9aัà¸\99à¸\97ึà¸\81à¹\84วà¹\89สำหรับผู้ใช้ \"$1\"",
+       "passwordremindertext": "à¸\9cูà¹\89à¹\83à¸\94à¸\9cูà¹\89หà¸\99ึà¹\88à¸\87 (à¸\8bึà¹\88à¸\87อาà¸\88à¹\80à¸\9bà¹\87à¸\99à¸\84ุà¸\93 à¸\97ีà¹\88à¹\83à¸\8aà¹\89à¹\80ลà¸\82à¸\97ีà¹\88อยูà¹\88à¹\84อà¸\9eี $1) à¸\82อà¹\83หà¹\89สà¹\88à¸\87รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\82อà¸\87 {{SITENAME}} ($4) à¸£à¸«à¸±à¸ªà¸\9cà¹\88าà¸\99à¸\8aัà¹\88วà¸\84ราวสำหรัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89 \"$2\" à¸\96ูà¸\81สรà¹\89าà¸\87à¸\82ึà¹\89à¸\99 à¹\81ละà¸\81ำหà¸\99à¸\94à¹\80à¸\9bà¹\87à¸\99 \"$3\" à¸«à¸²à¸\81à¹\80à¸\9bà¹\87à¸\99à¹\80à¸\88à¸\95à¸\99าà¸\82อà¸\87à¸\84ุà¸\93 à¸\84ุà¸\93à¸\88ำà¸\95à¹\89อà¸\87ลà¹\87อà¸\81อิà¸\99à¹\81ละà¹\80ลือà¸\81รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¹\83à¸\99à¸\82à¸\93ะà¸\99ีà¹\89 \nรหัสà¸\9cà¹\88าà¸\99à¸\8aัà¹\88วà¸\84ราวà¸\82อà¸\87à¸\84ุà¸\93à¸\88ะหมà¸\94อายุà¹\83à¸\99 $5 à¸§à¸±à¸\99\n\nหาà¸\81à¹\80à¸\9bà¹\87à¸\99à¸\9aุà¸\84à¸\84ลอืà¹\88à¸\99à¸\97ีà¹\88à¸\82อรหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88 à¸«à¸£à¸·à¸­à¸«à¸²à¸\81à¸\84ุà¸\93à¸\88ำรหัสà¸\9cà¹\88าà¸\99à¸\82อà¸\87à¸\84ุà¸\93à¹\84à¸\94à¹\89à¹\81ลà¹\89ว à¹\81ละà¹\84มà¹\88à¸\95à¹\89อà¸\87à¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88อีà¸\81 คุณอาจละเลยข้อความนี้และใช้รหัสผ่านเดิมของคุณต่อไป",
+       "noemail": "à¹\84มà¹\88มีà¸\81ารà¸\9aัà¸\99à¸\97ึà¸\81à¸\97ีà¹\88อยูà¹\88อีà¹\80มลสำหรับผู้ใช้ \"$1\"",
        "noemailcreate": "คุณจำต้องใส่ที่อยู่อีเมลให้ถูกต้อง",
        "passwordsent": "รหัสผ่านใหม่ถูกส่งไปยังที่อยู่อีเมลที่ลงทะเบียนไว้ของ \"$1\"\nกรุณาล็อกอินอีกครั้งหลังได้รับอีเมล",
-       "blocked-mailpassword": "à¹\80ลà¸\82à¸\97ีà¹\88อยูà¹\88à¹\84อà¸\9eีà¸\82อà¸\87à¸\84ุà¸\93à¸\96ูà¸\81à¸\9aลà¹\87อà¸\81มิà¹\83หà¹\89à¹\81à¸\81à¹\89à¹\84à¸\82 à¸\97ำà¹\83หà¹\89à¹\84มà¹\88สามารà¸\96à¸\97ำà¹\80รืà¹\88อà¸\87à¸\82อรหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¹\84à¸\94à¹\89 เพื่อป้องกันการใช้ในทางที่ผิด",
-       "eauthentsent": "อีà¹\80มลยืà¸\99ยัà¸\99à¹\84à¸\94à¹\89à¸\96ูà¸\81สà¹\88à¸\87à¹\84à¸\9bà¸\97ีà¹\88อยูà¹\88อีà¹\80มลà¸\97ีà¹\88à¹\80สà¸\99อ à¸\81à¹\88อà¸\99à¸\97ีà¹\88อีà¹\80มลà¸\88ะà¸\96ูà¸\81สà¹\88à¸\87à¹\84à¸\9bà¸\97ีà¹\88à¸\8aืà¹\88อà¸\9aัà¸\8dà¸\8aีà¸\99ัà¹\89à¸\99 à¸\84ุà¸\93à¸\95à¹\89อà¸\87à¸\9bà¸\8fิà¸\9aัà¸\95ิà¸\95ามà¸\84ำà¹\81à¸\99ะà¸\99ำในอีเมลเพื่อยืนยันว่าบัญชีนั้นเป็นของคุณจริง ๆ",
-       "throttled-mailpassword": "อีà¹\80มลà¸\95ัà¹\89à¸\87รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\96ูà¸\81สà¹\88à¸\87à¹\84à¸\9bà¹\81ลà¹\89วà¹\83à¸\99 $1 à¸\8aัà¹\88วà¹\82มà¸\87à¸\97ีà¹\88à¸\9cà¹\88าà¸\99มา \nอีà¹\80มลà¸\95ัà¹\89à¸\87รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\88ะสà¹\88à¸\87à¹\84à¸\9bหà¸\99ึà¹\88à¸\87à¸\84รัà¹\89à¸\87à¸\95à¹\88อ $1 à¸\8aัà¹\88วà¹\82มà¸\87à¹\80à¸\97à¹\88าà¸\99ัà¹\89à¸\99 à¹\80à¸\9eืà¹\88อà¸\9bà¹\89อà¸\87à¸\81ัà¸\99à¸\81ารà¸\81ระà¸\97ำà¸\97ีà¹\88à¹\84มà¹\88à¸\96ูà¸\81à¸\95à¹\89อà¸\87",
+       "blocked-mailpassword": "à¹\80ลà¸\82à¸\97ีà¹\88อยูà¹\88à¹\84อà¸\9eีà¸\82อà¸\87à¸\84ุà¸\93à¸\96ูà¸\81à¸\9aลà¹\87อà¸\81มิà¹\83หà¹\89à¹\81à¸\81à¹\89à¹\84à¸\82 à¸\97ำà¹\83หà¹\89à¹\84มà¹\88สามารà¸\96à¹\83à¸\8aà¹\89à¸\9fัà¸\87à¸\81à¹\8cà¸\8aัà¸\99à¸\81ูà¹\89รหัสà¸\9cà¹\88าà¸\99 เพื่อป้องกันการใช้ในทางที่ผิด",
+       "eauthentsent": "อีà¹\80มลยืà¸\99ยัà¸\99à¸\96ูà¸\81สà¹\88à¸\87à¹\84à¸\9bยัà¸\87à¸\97ีà¹\88อยูà¹\88อีà¹\80มลà¸\97ีà¹\88ระà¸\9aุà¹\84วà¹\89à¹\81ลà¹\89ว \nà¸\81à¹\88อà¸\99à¸\97ีà¹\88อีà¹\80มลอืà¹\88à¸\99à¸\88ะà¸\96ูà¸\81สà¹\88à¸\87à¹\84à¸\9bยัà¸\87à¸\9aัà¸\8dà¸\8aีà¸\99ัà¹\89à¸\99 à¸\84ุà¸\93à¸\95à¹\89อà¸\87à¸\9bà¸\8fิà¸\9aัà¸\95ิà¸\95ามà¸\84ำสัà¹\88à¸\87ในอีเมลเพื่อยืนยันว่าบัญชีนั้นเป็นของคุณจริง ๆ",
+       "throttled-mailpassword": "อีà¹\80มลà¸\95ัà¹\89à¸\87รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\96ูà¸\81สà¹\88à¸\87à¹\84à¸\9bà¹\81ลà¹\89วà¹\83à¸\99 $1 à¸\8aัà¹\88วà¹\82มà¸\87à¸\97ีà¹\88à¸\9cà¹\88าà¸\99มา \nอีà¹\80มลà¸\95ัà¹\89à¸\87รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\88ะสà¹\88à¸\87à¹\84à¸\9bหà¸\99ึà¹\88à¸\87à¸\84รัà¹\89à¸\87à¸\95à¹\88อ $1 à¸\8aัà¹\88วà¹\82มà¸\87à¹\80à¸\97à¹\88าà¸\99ัà¹\89à¸\99 à¹\80à¸\9eืà¹\88อà¸\9bà¹\89อà¸\87à¸\81ัà¸\99à¸\81ารà¸\81ระà¸\97ำà¸\9cิà¸\94",
        "mailerror": "ข้อผิดพลาดในการส่งเมล: $1",
-       "acct_creation_throttle_hit": "ผู้เข้าชมวิกินี้ที่ใช้เลขที่อยู่ไอพีของคุณ ได้สร้างบัญชีแล้ว $1 บัญชีในวันที่ผ่านมา ซึ่งเป็นจำนวนสูงสุดที่อนุญาตในช่วงเวลาดังกล่าว\nจึงส่งผลให้ผู้เข้าชมที่ใช้เลขที่อยู่ไอพีนี้ ไม่สามารถสร้างบัญชีได้อีกในขณะนี้",
-       "emailauthenticated": "à¸\97ีà¹\88อยูà¹\88อีà¹\80มลà¸\82อà¸\87à¸\84ุà¸\93à¹\84à¸\94à¹\89รัà¸\9aà¸\81ารยืà¸\99ยัà¸\99เมื่อวันที่ $2 เวลา $3",
+       "acct_creation_throttle_hit": "ผู้เข้าชมวิกินี้ที่ใช้เลขที่อยู่ไอพีของคุณ ได้สร้าง $1 บัญชีแล้วในวันที่ผ่านมา ซึ่งเป็นจำนวนสูงสุดที่อนุญาตในช่วงเวลาดังกล่าว\nจึงส่งผลให้ผู้เข้าชมที่ใช้เลขที่อยู่ไอพีนี้ ไม่สามารถสร้างบัญชีได้อีกในขณะนี้",
+       "emailauthenticated": "ยืà¸\99ยัà¸\99à¸\97ีà¹\88อยูà¹\88อีà¹\80มลà¸\82อà¸\87à¸\84ุà¸\93เมื่อวันที่ $2 เวลา $3",
        "emailnotauthenticated": "ที่อยู่อีเมลของคุณยังไม่ได้รับการยืนยัน \nจะไม่มีการส่งอีเมลสำหรับคุณลักษณะใด ๆ ต่อไปนี้",
        "noemailprefs": "ระบุที่อยู่อีเมลในการตั้งค่าของคุณเพื่อให้คุณลักษณะเหล่านี้ทำงานได้",
        "emailconfirmlink": "ยืนยันที่อยู่อีเมลของคุณ",
        "cannotchangeemail": "ไม่สามารถเปลี่ยนที่อยู่อีเมลบนวิกินี้",
        "emaildisabled": "เว็บไซต์นี้ไม่สามารถส่งอีเมล",
        "accountcreated": "สร้างบัญชีแล้ว",
-       "accountcreatedtext": "à¸\9aัà¸\8dà¸\8aีà¸\9cูà¹\89à¹\83à¸\8aà¹\89สำหรัà¸\9a [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|à¸\9eูà¸\94à¸\84ุย]]) à¹\84à¸\94à¹\89สร้างขึ้นแล้ว",
-       "createaccount-title": "สร้างบัญชีสำหรับ {{SITENAME}}",
-       "createaccount-text": "มีบางคนสร้างบัญชีโดยใช้ที่อยู่อีเมลของคุณบน {{SITENAME}} ($4) โดยใช้ชื่อ \"$2\" และรหัสผ่าน \"$3\" คุณควรล็อกอินเพื่อเปลี่ยนรหัสผ่านทันที\n\nคุณอาจเพิกเฉยข้อความนี้ หากการสร้างบัญชีนี้เกิดจากความผิดพลาด",
+       "accountcreatedtext": "à¸\9aัà¸\8dà¸\8aีà¸\9cูà¹\89à¹\83à¸\8aà¹\89สำหรัà¸\9a [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|à¸\9eูà¸\94à¸\84ุย]]) à¸\96ูà¸\81สร้างขึ้นแล้ว",
+       "createaccount-title": "à¸\81ารสรà¹\89าà¸\87à¸\9aัà¸\8dà¸\8aีสำหรัà¸\9a {{SITENAME}}",
+       "createaccount-text": "มีบางคนสร้างบัญชีโดยใช้ที่อยู่อีเมลของคุณบน {{SITENAME}} ($4) โดยใช้ชื่อ \"$2\" และรหัสผ่าน \"$3\" \nคุณควรล็อกอินและเปลี่ยนรหัสผ่านทันที\n\nคุณอาจเพิกเฉยข้อความนี้ หากการสร้างบัญชีนี้เป็นความผิดพลาด",
        "login-throttled": "ที่ผ่านมาคุณพยายามล็อกอินมากครั้งเกินไป\nกรุณารอ $1 ก่อนลองอีกครั้ง",
-       "login-abort-generic": "à¸\81ารà¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9aà¸\82อà¸\87à¸\84ุà¸\93à¹\84มà¹\88à¸\9bระสà¸\9aà¸\84วามสำเร็จ - ล้มเลิกแล้ว",
+       "login-abort-generic": "à¸\81ารลà¹\87อà¸\81อิà¸\99à¸\82อà¸\87à¸\84ุà¸\93à¹\84มà¹\88สำเร็จ - ล้มเลิกแล้ว",
        "loginlanguagelabel": "ภาษา: $1",
        "suspicious-userlogout": "คำขอล็อกเอาต์ของคุณถูกปฏิเสธเพราะดูเหมือนส่งมาจากเบราว์เซอร์หรือพร็อกซีแคชที่เสีย",
        "createacct-another-realname-tip": "ไม่จำเป็นต้องใส่ชื่อจริง\nหากคุณเลือกใส่ชื่อจริง จะใช้เพื่อแสดงที่มาสำหรับงานของตน",
        "changepassword": "เปลี่ยนรหัสผ่าน",
        "resetpass_announce": "คุณต้องตั้งรหัสผ่านใหม่จึงจะเสร็จสิ้นการล็อกอิน",
        "resetpass_text": "<!-- เพิ่มข้อความที่นี่ -->",
-       "resetpass_header": "เปลี่ยนรหัสผ่าน",
+       "resetpass_header": "เปลี่ยนรหัสผ่านบัญชี",
        "oldpassword": "รหัสผ่านเดิม:",
        "newpassword": "รหัสผ่านใหม่:",
        "retypenew": "พิมพ์รหัสผ่านใหม่อีกครั้ง:",
        "resetpass_submit": "ตั้งรหัสผ่านและล็อกอิน",
-       "changepassword-success": "à¹\80à¸\9bลีà¹\88ยà¸\99รหัสà¸\9cà¹\88าà¸\99à¸\82อà¸\87à¸\84ุà¸\93à¹\80รียà¸\9aรà¹\89อย",
-       "changepassword-throttled": "à¸\84ุà¸\93à¹\84à¸\94à¹\89à¸\9eยายามลà¹\87อà¸\81อิà¸\99มาà¸\81à¸\84รัà¹\89à¸\87à¹\80à¸\81ิà¸\99à¹\84à¸\9b\nà¸\81รุà¸\93ารอ $1 à¸\81à¹\88อà¸\99ลอà¸\87อีà¸\81à¸\84รัà¹\89à¸\87",
+       "changepassword-success": "à¹\80à¸\9bลีà¹\88ยà¸\99รหัสà¸\9cà¹\88าà¸\99à¸\82อà¸\87à¸\84ุà¸\93สำà¹\80รà¹\87à¸\88",
+       "changepassword-throttled": "คุณพยายามล็อกอินมากครั้งเกินไป\nกรุณารอ $1 ก่อนลองอีกครั้ง",
        "resetpass_forbidden": "ไม่สามารถเปลี่ยนรหัสผ่านได้",
        "resetpass-no-info": "คุณต้องล็อกอินเพื่อเข้าถึงหน้านี้โดยตรง",
        "resetpass-submit-loggedin": "เปลี่ยนรหัสผ่าน",
        "resetpass-submit-cancel": "ยกเลิก",
-       "resetpass-wrong-oldpass": "รหัสà¸\9cà¹\88าà¸\99à¸\8aัà¹\88วà¸\84ราวหรือà¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99à¹\84มà¹\88à¸\96ูà¸\81à¸\95à¹\89อà¸\87\nà¸\84ุà¸\93อาà¸\88à¹\80à¸\9bลีà¹\88ยà¸\99รหัสà¸\9cà¹\88าà¸\99à¸\82อà¸\87à¸\84ุà¸\93à¹\84à¸\9bà¹\81ลà¹\89ว à¸«à¸£à¸·à¸­à¸\82อรหัสà¸\9cà¹\88าà¸\99à¸\8aัà¹\88วà¸\84ราวà¹\83หมà¹\88à¹\81ลà¹\89ว",
+       "resetpass-wrong-oldpass": "รหัสผ่านชั่วคราวหรือปัจจุบันไม่ถูกต้อง\nคุณอาจเปลี่ยนรหัสผ่านของคุณแล้ว หรือขอรหัสผ่านชั่วคราวใหม่แล้ว",
        "resetpass-recycled": "โปรดตั้งรหัสผ่านใหม่ให้ต่างจากรหัสผ่านปัจจุบัน",
        "resetpass-temp-emailed": "คุณล็อกอินด้วยรหัสผ่านชั่วคราวที่ส่งทางอีเมล\nคุณต้องตั้งรหัสผ่านใหม่ที่นี่จึงจะเสร็จสิ้นการล็อกอิน:",
        "resetpass-temp-password": "รหัสผ่านชั่วคราว:",
        "passwordreset-text-one": "กรอกแบบนี้เพื่อตั้งรหัสผ่านใหม่",
        "passwordreset-text-many": "{{PLURAL:$1|กรอกเขตข้อมูลหนึ่งเพื่อรับรหัสผ่านชั่วคราวทางอีเมล}}",
        "passwordreset-legend": "เปลี่ยนรหัสผ่าน",
-       "passwordreset-disabled": "à¸\81ารà¸\95ัà¹\89à¸\87รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\9aà¸\99วิà¸\81ิà¸\99ีà¹\89",
-       "passwordreset-emaildisabled": "à¸\84ุà¸\93ลัà¸\81ษà¸\93ะอีà¹\80มลà¸\96ูà¸\81à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\9aà¸\99วิà¸\81ิà¸\99ีà¹\89",
+       "passwordreset-disabled": "วิà¸\81ิà¸\99ีà¹\89à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\81ารà¸\95ัà¹\89à¸\87รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88",
+       "passwordreset-emaildisabled": "วิà¸\81ิà¸\99ีà¹\89à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\84ุà¸\93ลัà¸\81ษà¸\93ะอีà¹\80มล",
        "passwordreset-username": "ชื่อผู้ใช้:",
        "passwordreset-domain": "โดเมน:",
        "passwordreset-capture": "ดูอีเมลที่ได้หรือไม่",
        "bold_tip": "ทำตัวหนา",
        "italic_sample": "ข้อความตัวเอน",
        "italic_tip": "ทำตัวเอน",
-       "link_sample": "ลิà¸\87à¸\81à¹\8cà¹\80à¸\8aืà¹\88อมà¹\82ยง",
+       "link_sample": "à¹\80à¸\8aืà¹\88อมà¹\82ยà¸\87หัวà¹\80รืà¹\88อง",
        "link_tip": "ลิงก์ภายใน",
-       "extlink_sample": "http://www.example.com à¸\8aืà¹\88อà¹\80รืà¹\88อà¸\87à¸\82อà¸\87ลิà¸\87à¸\81à¹\8c",
+       "extlink_sample": "http://www.example.com à¸\8aืà¹\88อà¹\80รืà¹\88อà¸\87à¹\80à¸\8aืà¹\88อมà¹\82ยà¸\87",
        "extlink_tip": "ลิงก์ภายนอก (อย่าลืมใส่ http:// นำหน้าเสมอ)",
        "headline_sample": "ข้อความพาดหัว",
        "headline_tip": "พาดหัวระดับ 2",
        "media_sample": "ตัวอย่าง.ogg",
        "media_tip": "เชื่อมโยงไฟล์",
        "sig_tip": "ลายเซ็นของคุณพร้อมตราเวลา",
-       "hr_tip": "à¹\80สà¹\89à¸\99à¸\99อà¸\99 (à¹\82à¸\9bรà¸\94à¹\83à¸\8aà¹\89อยà¹\88าà¸\87à¸\88ำà¸\81ัà¸\94)",
+       "hr_tip": "เส้นนอน (ใช้อย่างจำกัด)",
        "summary": "คำอธิบายโดยย่อ:",
-       "subject": "หัวข้อ:",
+       "subject": "หัวข้อ/พาดหัว:",
        "minoredit": "เป็นการแก้ไขเล็กน้อย",
        "watchthis": "เฝ้าดูหน้านี้",
        "savearticle": "บันทึก",
        "preview": "ตัวอย่าง",
-       "showpreview": "à¸\94ูตัวอย่าง",
+       "showpreview": "à¹\81สà¸\94à¸\87ตัวอย่าง",
        "showdiff": "แสดงความเปลี่ยนแปลง",
-       "anoneditwarning": "'''คำเตือน:''' คุณมิได้ล็อกอิน เลขที่อยู่ไอพีของคุณจะถูกบันทึกไว้ในประวัติการแก้ไขของหน้านี้",
-       "anonpreviewwarning": "'''คุณมิได้ล็อกอิน การบันทึกจะเก็บเลขที่อยู่ไอพีของคุณในประวัติการแก้ไขของหน้านี้'''",
+       "blankarticle": "<strong>คำเตือน:</strong> หน้าที่คุณกำลังสร้างว่าง หากคุณคลิก \"{{int:savearticle}}\" อีกครั้ง จะสร้างหน้าโดยไม่มีเนื้อหาใด",
+       "anoneditwarning": "<strong>คำเตือน:</strong> คุณมิได้ล็อกอิน สาธารณะจะเห็นเลขที่อยู่ไอพีของคุณหากคุณแก้ไข หากคุณ<strong>[$1 ล็อกอิน]</strong>หรือ<strong>[$2 สร้างบัญชี]</strong> การแก้ไขของคุณจะถือว่าเป็นของชื่อผู้ใช้ของคุณ ร่วมกับประโยชน์อื่น",
+       "anonpreviewwarning": "<em>คุณมิได้ล็อกอิน การบันทึกจะเก็บเลขที่อยู่ไอพีของคุณในประวัติการแก้ไขของหน้านี้</em>",
        "missingsummary": "'''อย่าลืม:''' คุณยังไม่ได้ระบุคำอธิบายการแก้ไข ถ้าคุณกด \"บันทึก\" อีกครั้ง การแก้ไขของคุณจะถูกบันทึกโดยไม่มีคำอธิบายการแก้ไข",
        "missingcommenttext": "กรุณาใส่ความเห็นด้านล่าง",
        "missingcommentheader": "'''ประกาศเตือน:''' คุณยังไม่ได้ใส่หัวข้อ/จ่าหัวสำหรับความเห็นนี้ ถ้าคุณกด \"{{int:savearticle}}\" อีกครั้ง การแก้ไขของคุณจะถูกบันทึกโดยไม่มีหัวข้อ",
        "summary-preview": "ตัวอย่างคำอธิบายการแก้ไข:",
        "subject-preview": "ตัวอย่างหัวข้อ/พาดหัว:",
-       "blockedtitle": "ผู้ใช้ถูกบล็อกอยู่",
+       "blockedtitle": "ผู้ใช้ถูกบล็อก",
        "blockedtext": "<strong>ชื่อผู้ใช้หรือเลขที่อยู่ไอพีของคุณถูกบล็อก</strong>\n\nการบล็อกนี้ดำเนินการโดย $1\nซึ่งให้เหตุผลว่า ''$2''\n\n* เริ่มการบล็อก: $8\n* หมดเขตการบล็อก: $6\n* ผู้ถูกบล็อก: $7\n\nคุณสามารถติดต่อ $1 หรือ[[{{MediaWiki:Grouppage-sysop}}|ผู้ดูแลระบบ]]คนอื่นเพื่ออภิปรายการบล็อกนี้ได้\nคุณไม่สามารถใช้คุณลักษณะ \"ส่งอีเมลหาผู้ใช้รายนี้ได้\" จนกว่าจะระบุที่อยู่อีเมลให้ถูกต้องใน[[Special:Preferences|การตั้งค่าบัญชี]]ของคุณ และคุณมิได้ถูกห้ามใช้ความสามารถนี้\nเลขที่อยู่ไอพีปัจจุบันของคุณคือ $3 และหมายเลขการบล็อกคือ #$5 \nโปรดแสดงรายละเอียดข้างต้นทั้งหมดในการสอบถามใด ๆ",
        "autoblockedtext": "เลขที่อยู่ไอพีของคุณถูกบล็อกอัตโนมัติ เพราะมีผู้ใช้อื่นใช้มาก่อน ซึ่งถูกบล็อกโดย $1\nโดยให้เหตุผลว่า\n\n:<em>$2</em>\n\n* เริ่มการบล็อก: $8\n* สิ้นสุดการบล็อก: $6\n* ผู้ถูกบล็อก: $7\n\nคุณสามารถติดต่อ $1 หรือ[[{{MediaWiki:Grouppage-sysop}}|ผู้ดูแลระบบ]]คนอื่นเพื่อหารือการบล็อกนี้ \nคุณไม่สามารถใช้คุณลักษณะ \"ส่งอีเมลหาผู้ใช้รายนี้ได้\" จนกว่าจะระบุที่อยู่อีเมลที่ถูกต้องใน[[Special:Preferences|การตั้งค่าบัญชี]]ของคุณ และคุณมิได้ถูกห้ามใช้\nเลขที่อยู่ไอพีปัจจุบันของคุณคือ $3 และหมายเลขการบล็อกคือ #$5 \nโปรดรวมรายละเอียดข้างต้นทั้งหมดในการสอบถามใด ๆ",
-       "blockednoreason": "ไม่ได้ให้เหตุผลไว้",
+       "blockednoreason": "ไม่ได้ให้เหตุผล",
        "whitelistedittext": "คุณต้อง$1เพื่อแก้ไขหน้า",
        "confirmedittext": "คุณต้องยืนยันที่อยู่อีเมลของคุณก่อนแก้ไขหน้า โปรดกำหนดที่อยู่อีเมลของคุณและทำให้ถูกต้องผ่าน[[Special:Preferences|การตั้งค่าผู้ใช้]]",
        "nosuchsectiontitle": "ไม่พบส่วน",
        "accmailtext": "รหัสผ่านแบบสุ่มของ [[User talk:$1|$1]] ถูกส่งไปยัง $2 แล้ว สามารถเปลี่ยนรหัสผ่านในหน้า''[[Special:ChangePassword|เปลี่ยนรหัสผ่าน]]'' หลังล็อกอิน",
        "newarticle": "(ใหม่)",
        "newarticletext": "คุณตามลิงก์ไปยังหน้าที่ยังไม่มีในขณะนี้\nในการสร้างหน้า เริ่มพิมพ์ในกล่องด้านล่าง (ดูข้อมูลเพิ่มเติมใน[$1 หน้าคำอธิบาย])\nถ้าคุณเข้ามาหน้านี้โดยผิดพลาด ให้กดปุ่ม'''ถอยหลัง''' (back) ของเบราว์เซอร์",
-       "anontalkpagetext": "----''หน้านี้เป็นหน้าคุยกับผู้ใช้สำหรับผู้ใช้นิรนามซึ่งยังไม่ได้สร้างบัญชีหรือไม่ได้ล็อกอิน\nดังนั้นเราจึงระบุตัวตนโดยใช้เลขที่อยู่ไอพีแทน\nเลขที่อยู่ไอพีนี้อาจมีผู้ใช้ร่วมกันหลายคน\nถ้าคุณเป็นผู้ใช้นิรนาม และรู้สึกว่าความเห็นที่คุณได้รับไม่เกี่ยวข้องกับคุณแต่อย่างใด กรุณา[[Special:UserLogin/signup|สร้างบัญชีผู้ใช้]]หรือ[[Special:UserLogin|ล็อกอิน]] เพื่อป้องกันการสับสนกับผู้ใช้นิรนามรายอื่น''",
-       "noarticletext": "à¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99à¹\84มà¹\88มีà¹\80à¸\99ืà¹\89อหาà¹\83à¸\99หà¸\99à¹\89าà¸\99ีà¹\89\nà¸\84ุà¸\93สามารà¸\96[[Special:Search/{{PAGENAME}}|à¸\84à¹\89à¸\99หาà¸\8aืà¹\88อหà¸\99à¹\89าà¸\99ีà¹\89]]à¹\83à¸\99หà¸\99à¹\89าอืà¹\88à¸\99 à¸«à¸£à¸·à¸­<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ค้นหาปูมที่เกี่ยวข้อง] หรือ[{{fullurl:{{FULLPAGENAME}}|action=edit}} แก้ไขหน้านี้]</span>",
-       "noarticletext-nopermission": "à¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99à¹\84มà¹\88มีà¹\80à¸\99ืà¹\89อหาในหน้านี้\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}}}} ปูมการลบ]",
+       "anontalkpagetext": "----\n<em>หน้านี้เป็นหน้าคุยกับผู้ใช้สำหรับผู้ใช้นิรนามซึ่งยังไม่ได้สร้างบัญชีหรือไม่ได้ใช้</em>\nดังนั้นเราจึงระบุตัวตนโดยใช้เลขที่อยู่ไอพีแทน\nเลขที่อยู่ไอพีนี้อาจมีผู้ใช้ร่วมกันหลายคน\nถ้าคุณเป็นผู้ใช้นิรนาม และรู้สึกว่าคุณได้รับความเห็นที่ไม่เกี่ยวข้องส่งหาคุณ กรุณา[[Special:UserLogin/signup|สร้างบัญชี]]หรือ[[Special:UserLogin|ล็อกอิน]] เพื่อป้องกันการสับสนกับผู้ใช้นิรนามรายอื่นในอนาคต",
+       "noarticletext": "à¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99à¹\84มà¹\88มีà¸\82à¹\89อà¸\84วามà¹\83à¸\99หà¸\99à¹\89าà¸\99ีà¹\89\nà¸\84ุà¸\93สามารà¸\96[[Special:Search/{{PAGENAME}}|à¸\84à¹\89à¸\99หาà¸\8aืà¹\88อหà¸\99à¹\89าà¸\99ีà¹\89]]à¹\83à¸\99หà¸\99à¹\89าอืà¹\88à¸\99 <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ค้นหาปูมที่เกี่ยวข้อง] หรือ[{{fullurl:{{FULLPAGENAME}}|action=edit}} แก้ไขหน้านี้]</span>",
+       "noarticletext-nopermission": "à¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99à¹\84มà¹\88มีà¸\82à¹\89อà¸\84วามในหน้านี้\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": "บัญชีผู้ใช้ \"$1\" มิได้ลงทะเบียน \nกรุณาตรวจสอบหากคุณต้องการสร้าง/แก้ไขหน้านี้",
        "userpage-userdoesnotexist-view": "บัญชีผู้ใช้ \"$1\" มิได้ลงทะเบียน",
-       "blocked-notice-logextract": "à¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99à¹\80ลà¸\82à¸\97ีà¹\88อยูà¹\88à¹\84อà¸\9eีà¸\99ีà¹\89à¸\96ูà¸\81à¸\9aลà¹\87อà¸\81\nหà¸\99à¹\88วยบล็อกล่าสุดแสดงด้านล่างนี้เพื่อการอ้างอิง:",
+       "blocked-notice-logextract": "à¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\99ีà¹\89à¸\96ูà¸\81à¸\9aลà¹\87อà¸\81\nหà¸\99à¹\88วยà¸\9bูมà¸\81ารบล็อกล่าสุดแสดงด้านล่างนี้เพื่อการอ้างอิง:",
        "clearyourcache": "'''หมายเหตุ:''' หลังจากบันทึก คุณอาจต้องล้างแคชเว็บเบราว์เซอร์ของคุณเพื่อดูการเปลี่ยนแปลง\n* '''ไฟร์ฟอกซ์ / ซาฟารี:''' กดปุ่ม ''Shift'' ค้างไว้ขณะคลิก ''Reload'' หรือกด ''Ctrl-F5'' หรือ ''Ctrl-R'' (''⌘-R'' บนแมค)\n* '''กูเกิล โครม:''' กดปุ่ม ''Ctrl-Shift-R'' (''⌘-Shift-R'' บนแมค)\n* '''อินเทอร์เน็ตเอกซ์พลอเรอร์:''' กดปุ่ม ''Ctrl'' ค้างไว้ขณะคลิก ''Refresh'' หรือกด ''Ctrl-F5''\n* '''โอเปร่า:''' ล้างแคชใน ''Tools → Preferences''",
        "usercssyoucanpreview": "'''คำแนะนำ:''' กดปุ่ม \"{{int:showpreview}}\" เพื่อทดสอบ CSS ใหม่ของคุณก่อนบันทึก",
        "userjsyoucanpreview": "'''คำแนะนำ:''' กดปุ่ม \"{{int:showpreview}}\" เพื่อทดสอบจาวาสคริปต์ใหม่ของคุณก่อนบันทึก",
        "edit-gone-missing": "ไม่สามารถอัปเดตหน้าดังกล่าวได้\nเนื่องจากหน้านี้ถูกลบไปแล้ว",
        "edit-conflict": "แก้ชนกัน",
        "edit-no-change": "การแก้ไขของคุณถูกเพิกเฉย เพราะไม่มีการเปลี่ยนแปลงใด ๆ",
-       "postedit-confirmation-created": "หà¸\99à¹\89าà¸\96ูà¸\81สรà¹\89าà¸\87à¸\82ึà¹\89à¸\99",
+       "postedit-confirmation-created": "หà¸\99à¹\89าà¸\96ูà¸\81สรà¹\89าà¸\87à¹\81ลà¹\89ว",
        "postedit-confirmation-restored": "หน้าถูกกู้คืน",
        "postedit-confirmation-saved": "บันทึกการแก้ไขของคุณแล้ว",
        "edit-already-exists": "ไม่สามารถสร้างหน้าใหม่ได้\nเพราะมีหน้านี้แล้ว",
        "revdelete-text-text": "รุ่นที่ถูกลบจะยังปรากฏในประวัติหน้า แต่สาธารณะจะไม่สามารถเข้าถึงเนื้อหาบางส่วนได้",
        "revdelete-text-file": "รุ่นที่ถูกลบจะยังปรากฏในประวัติไฟล์ แต่สาธารณะจะไม่สามารถเข้าถึงเนื้อหาบางส่วนได้",
        "logdelete-text": "รายการปูมที่ถูกลบจะยังปรากฏในปูม แต่สาธารณะจะไม่สามารถเข้าถึงเนื้อหาบางส่วนได้",
-       "revdelete-text-others": "à¸\9cูà¹\89à¸\94ูà¹\81ลระà¸\9aà¸\9aà¸\84à¸\99อืà¹\88à¸\99à¸\9aà¸\99 {{SITENAME}} à¸\88ะยัà¸\87สามารà¸\96à¹\80à¸\82à¹\89าà¸\96ึà¸\87à¹\80à¸\99ืà¹\89อหาà¸\97ีà¹\88à¸\96ูà¸\81à¸\8bà¹\88อà¸\99 à¹\81ละสามารà¸\96à¸\81ูà¹\89à¸\84ืà¸\99à¹\84à¸\94à¹\89อีà¸\81à¸\9cà¹\88าà¸\99อิà¸\99à¹\80à¸\95อรà¹\8cà¹\80à¸\9fà¸\8bà¹\80à¸\94ียวà¸\81ัà¸\99à¸\99ีà¹\89 à¸¢à¸\81à¹\80วà¹\89à¸\99ตั้งข้อจำกัดเพิ่มเติม",
+       "revdelete-text-others": "à¸\9cูà¹\89à¸\94ูà¹\81ลระà¸\9aà¸\9aà¸\84à¸\99อืà¹\88à¸\99à¸\88ะยัà¸\87สามารà¸\96à¹\80à¸\82à¹\89าà¸\96ึà¸\87à¹\80à¸\99ืà¹\89อหาà¸\97ีà¹\88à¸\96ูà¸\81à¸\8bà¹\88อà¸\99 à¹\81ละสามารà¸\96à¸\81ูà¹\89à¸\84ืà¸\99à¹\80à¸\99ืà¹\89อหาà¹\84à¸\94à¹\89 à¸¢à¸\81à¹\80วà¹\89à¸\99มีà¸\81ารตั้งข้อจำกัดเพิ่มเติม",
        "revdelete-confirm": "กรุณายืนยันว่าคุณมีเจตนาลบจริง และเข้าใจผลลัพธ์ และกระทำภายใต้[[{{MediaWiki:Policy-url}}|นโยบาย]]",
        "revdelete-suppress-text": "การระงับควรใช้'''เฉพาะ'''กรณีต่อไปนี้:\n* ข้อมูลที่อาจหมิ่นประมาท\n* ข้อมูลส่วนบุคคลที่ไม่เหมาะสม\n*: ''ที่อยู่บ้านและหมายเลขโทรศัพท์บ้าน, หมายเลขประกันสังคม, ฯลฯ''",
        "revdelete-legend": "ตั้งการจำกัดทัศนวิสัย:",
        "mergehistory-empty": "ไม่มีรุ่นที่สามารถรวมได้",
        "mergehistory-success": "ประวัติ $3 รุ่นของ [[:$1]] ได้ถูกรวมเข้ากับ [[:$2]] แล้ว",
        "mergehistory-fail": "ไม่สามารถรวมประวัติการแก้ไขได้ โปรดตรวจสอบค่าตัวแปรหน้าและเวลาอีกครั้ง",
-       "mergehistory-no-source": "ไม่มีหน้าต้นทาง $1 อยู่ในสารบบ",
-       "mergehistory-no-destination": "ไม่มีหน้าปลายทาง $1 อยู่ในสารบบ",
+       "mergehistory-no-source": "ไม่มีหน้าต้นทาง $1 อยู่",
+       "mergehistory-no-destination": "ไม่มีหน้าปลายทาง $1 อยู่",
        "mergehistory-invalid-source": "ชื่อเรื่องหน้าต้นทางต้องสมเหตุสมผล",
        "mergehistory-invalid-destination": "ชื่อเรื่องหน้าปลายทางต้องสมเหตุสมผล",
        "mergehistory-autocomment": "รวม [[:$1]] เข้ากับ [[:$2]]",
        "searchmenu-exists": "<strong>มีหน้าชื่อ \"[[:$1]]\" บนวิกินี้</strong>\n{{PLURAL:$2|0=|ดูผลการค้นหาอื่นที่พบเพิ่มเติม}}",
        "searchmenu-new": "<strong>สร้างหน้า \"[[:$1]]\" บนวิกินี้!</strong> {{PLURAL:$2|0=|ดูหน้าที่พบด้วยการค้นหาของคุณ|ดูผลการค้นหาที่พบเพิ่มเติม}}",
        "searchprofile-articles": "หน้าเนื้อหา",
-       "searchprofile-images": "มัลà¸\95ิมีà¹\80à¸\94ีย",
+       "searchprofile-images": "สืà¹\88อà¸\9bระสม",
        "searchprofile-everything": "ทุกอย่าง",
        "searchprofile-advanced": "ชั้นสูง",
        "searchprofile-articles-tooltip": "ค้นหาใน $1",
        "searchprofile-advanced-tooltip": "ค้นหาในเนมสเปซที่เลือกเอง",
        "search-result-size": "$1 ($2 คำ)",
        "search-result-category-size": "$1 สมาชิก ($2 หมวดหมู่ย่อย, $3 ไฟล์)",
-       "search-result-score": "ความเกี่ยวข้อง : $1%",
        "search-redirect": "(เปลี่ยนทาง $1)",
        "search-section": "(ส่วน $1)",
        "search-file-match": "(จับคู่เนื้อหาไฟล์)",
        "searchall": "ทั้งหมด",
        "showingresults": "ด้านล่างแสดง <strong>1</strong> ผลลัพธ์ เริ่มตั้งแต่รายการที่ <strong>$2</strong>",
        "showingresultsinrange": "ด้านล่างแสดงมากสุด {{PLURAL:$1|<strong>1</strong>|<strong>$1</strong>}} ผลลัพธ์ ในพิสัย #<strong>$2</strong> ถึง #<strong>$3</strong>",
-       "showingresultsheader": "{{PLURAL:$5|ผลการค้นหา <strong>$1</strong> จาก <strong>$3</strong>|ผลการค้นหา <strong>$1 - $2</strong> จาก <strong>$3</strong>}} สำหรับ <strong>$4</strong>",
+       "search-showingresults": "{{PLURAL:$4|ผลลัพธ์ <strong>$1</strong> จากทั้งหมด <strong>$3</strong>|ผลลัพธ์ <strong>$1 - $2</strong> จากทั้งหมด <strong>$3</strong>}}",
        "search-nonefound": "ไม่มีผลลัพธ์ตรงกับคำค้น",
-       "powersearch-legend": "à¸\84à¹\89à¸\99หาระà¸\94ัà¸\9aสูง",
+       "powersearch-legend": "à¸\84à¹\89à¸\99หาà¸\82ัà¹\89à¸\99สูง",
        "powersearch-ns": "ค้นหาในเนมสเปซ:",
        "powersearch-togglelabel": "เลือก:",
        "powersearch-toggleall": "ทั้งหมด",
        "search-external": "ค้นหาภายนอก",
        "searchdisabled": "การค้นหา {{SITENAME}} ปิดใช้งาน คุณสามารถค้นหาผ่านกูเกิลหรือเซิร์ชเอนจินอื่นในเวลาไม่นาน โปรดทราบว่าดัชนีเนื้อหาของ {{SITENAME}} บนเซิร์ชเอนจินอาจเป็นข้อมูลเก่า",
        "search-error": "เกิดข้อผิดพลาดขณะกำลังค้นหา: $1",
-       "preferences": "à¸\95ัà¹\89à¸\87à¸\84à¹\88าสà¹\88วà¸\99à¸\95ัว",
+       "preferences": "à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88า",
        "mypreferences": "การตั้งค่า",
        "prefs-edits": "จำนวนการแก้ไข:",
-       "prefsnologintext2": "โปรด$1เพื่อเปลี่ยนการตั้งค่าของคุณ",
+       "prefsnologintext2": "โปรดล็อกอินเพื่อเปลี่ยนการตั้งค่าของคุณ",
        "prefs-skin": "หน้าตา",
        "skin-preview": "แสดงตัวอย่าง",
        "datedefault": "ไม่มีการตั้งค่า",
        "rows": "แถว:",
        "columns": "คอลัมน์:",
        "searchresultshead": "ค้นหา",
-       "stub-threshold": "ขีดแบ่งสำหรับ <a href=\"#\" class=\"stub\">ลิงก์โครง</a> (ไบต์):",
+       "stub-threshold": "ขีดแบ่งสำหรับการจัดรูปแบบ <a href=\"#\" class=\"stub\">ลิงก์โครง</a> (ไบต์):",
        "stub-threshold-disabled": "ปิดใช้งาน",
        "recentchangesdays": "จำนวนวันที่แสดงในปรับปรุงล่าสุด:",
        "recentchangesdays-max": "มากสุด $1 วัน",
        "prefs-help-signature": "ความเห็นในหน้าพูดคุยควรลงลายเซ็นด้วย \"<nowiki>~~~~</nowiki>\" ซึ่งจะถูกแปลงเป็นลายเซ็นของคุณและตราเวลา",
        "badsig": "ลายเซ็นดิบไม่ถูกต้อง ให้ตรวจสอบแท็กเอชทีเอ็มแอล",
        "badsiglength": "ลายเซ็นของคุณยาวเกินไป ต้องยาวไม่เกิน $1 ตัวอักษร",
-       "yourgender": "à¹\80à¸\9eศ:",
-       "gender-unknown": "ไม่ระบุ",
+       "yourgender": "à¸\95à¹\89อà¸\87à¸\81ารà¹\83หà¹\89ระà¸\9aุà¹\80à¸\9bà¹\87à¸\99à¹\80à¸\9eศà¹\83à¸\94",
+       "gender-unknown": "à¸\82อà¹\84มà¹\88ระà¸\9aุ",
        "gender-male": "ชาย",
        "gender-female": "หญิง",
        "prefs-help-gender": "เลือกตั้งค่านี้หรือไม่ก็ได้\nซอฟต์แวร์ใช้ค่านี้เพื่อติดต่อคุณและกล่าวถึงคุณโดยใช้เพศทางไวยากรณ์ที่เหมาะสมเมื่อติดต่อผู้อื่น\nข้อมูลนี้เปิดเผยต่อสาธารณะ",
        "editusergroup": "แก้ไขกลุ่มผู้ใช้",
        "editinguser": "กำลังเปลี่ยนสิทธิผู้ใช้ของผู้ใช้ '''[[User:$1|$1]]''' $2",
        "userrights-editusergroup": "แก้ไขกลุ่มผู้ใช้",
-       "saveusergroups": "à¸\95à¸\81ลà¸\87",
-       "userrights-groupsmember": "สมาà¸\8aิà¸\81à¹\83à¸\99à¸\81ลุà¹\88ม:",
+       "saveusergroups": "à¸\9aัà¸\99à¸\97ึà¸\81à¸\81ลุà¹\88มà¸\9cูà¹\89à¹\83à¸\8aà¹\89",
+       "userrights-groupsmember": "สมาà¸\8aิà¸\81à¸\82อà¸\87:",
        "userrights-groupsmember-auto": "สมาชิกโดยปริยายของ:",
        "userrights-groups-help": "คุณสามารถเปลี่ยนแปลงกลุ่มที่ผู้ใช้รายนี้อยู่:\n* กล่องที่มีเครื่องหมายถูก หมายความว่า ผู้ใช้อยู่ในกลุ่มนั้น\n* กล่องที่ไม่มีเครื่องหมายถูก หมายความว่า ผู้ใช้ไม่ได้อยู่ในกลุ่มนั้น\n* เครื่องหมาย * ชี้ว่าคุณไม่สามารถนำกลุ่มนั้นออกได้เมื่อคุณเพิ่มกลุ่มนั้นไปแล้ว หรือกลับกัน",
        "userrights-reason": "เหตุผล:",
        "right-reupload-shared": "เขียนทับไฟล์บนคลังเก็บสื่อส่วนกลาง",
        "right-upload_by_url": "อัปโหลดไฟล์จากยูอาร์แอล",
        "right-purge": "ล้างแคชของเว็บไซต์โดยไม่มีการยืนยัน",
-       "right-autoconfirmed": "à¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¸\97ีà¹\88à¸\96ูà¸\81à¸\81ึà¹\88à¸\87ลà¹\87อà¸\81",
+       "right-autoconfirmed": "à¹\84มà¹\88à¹\84à¸\94à¹\89รัà¸\9aà¸\9cลà¸\88าà¸\81à¸\82ีà¸\94à¸\88ำà¸\81ัà¸\94อัà¸\95รายึà¸\94à¹\80ลà¸\82à¸\97ีà¹\88อยูà¹\88à¹\84อà¸\9eี",
        "right-bot": "กำหนดเป็นกระบวนการอัตโนมัติ",
        "right-nominornewtalk": "ไม่มีการแก้ไขเล็กน้อยในหน้าอภิปรายที่ทำให้การแจ้งข้อความใหม่ปรากฏ",
        "right-apihighlimits": "ใช้ข้อจำกัดที่สูงขึ้นในคำสั่งเอพีไอ",
        "right-writeapi": "ใช้การเขียนเอพีไอ",
        "right-delete": "ลบหน้า",
        "right-bigdelete": "ลบหน้าที่มีประวัติขนาดใหญ่",
-       "right-deletelogentry": "ลà¸\9aà¹\81ละà¸\81ูà¹\89à¸\84ืà¸\99หà¸\99à¹\88วยà¸\9bูมà¸\97ีà¹\88à¹\80à¸\88าะà¸\88à¸\87",
+       "right-deletelogentry": "ลà¸\9aà¹\81ละà¸\81ูà¹\89à¸\84ืà¸\99หà¸\99à¹\88วยà¸\9bูมà¸\88ำà¹\80à¸\9eาะ",
        "right-deleterevision": "ลบและกู้คืนรุ่นจำเพาะของหน้า",
        "right-deletedhistory": "ดูหน่วยประวัติที่ถูกลบ โดยไม่มีข้อความที่เกี่ยวข้อง",
        "right-deletedtext": "ดูข้อความที่ถูกลบและการเปลี่ยนแปลงระหว่างรุ่นที่ถูกลบ",
        "right-browsearchive": "ค้นหาหน้าที่ถูกลบ",
        "right-undelete": "กู้คืนหน้า",
-       "right-suppressrevision": "ดูและกู้คืนรุ่นที่ซ่อนจากผู้ดูแลระบบ",
+       "right-suppressrevision": "ดู ซ่อนและเปิดเผยรุ่นจำเพาะของหน้าจากผู้ใช้ทุกคน",
+       "right-viewsuppressed": "ดูรุ่นที่ถูกซ่อนจากผู้ใช้ทุกคน",
        "right-suppressionlog": "ดูปูมส่วนตัว",
        "right-block": "บล็อกมิให้ผู้ใช้อื่นแก้ไข",
        "right-blockemail": "บล็อกมิให้ผู้ใช้ส่งอีเมล",
        "right-hideuser": "บล็อกชื่อผู้ใช้ ซ่อนไม่ให้สาธารณะเห็น",
-       "right-ipblock-exempt": "อà¹\89อมการบล็อกเลขที่อยู่ไอพี บล็อกอัตโนมัติ และบล็อกช่วง",
+       "right-ipblock-exempt": "à¹\80ลีà¹\88ยà¸\87การบล็อกเลขที่อยู่ไอพี บล็อกอัตโนมัติ และบล็อกช่วง",
        "right-proxyunbannable": "เลี่ยงการบล็อกอัตโนมัติของพร็อกซี",
        "right-unblockself": "ปลดบล็อกตนเอง",
-       "right-protect": "เปลี่ยนระดับการล็อกและแก้ไขหน้าที่ถูกล็อก",
+       "right-protect": "เปลี่ยนระดับการล็อกและแก้ไขหน้าที่ถูกล็อกแบบถ่ายทอด",
        "right-editprotected": "แก้ไขหน้าที่ถูกล็อกซึ่ง \"{{int:protect-level-sysop}}\"",
        "right-editsemiprotected": "แก้ไขหน้าที่ถูกล็อกซึ่ง \"{{int:protect-level-autoconfirmed}}\"",
        "right-editinterface": "แก้ไขอินเตอร์เฟซผู้ใช้",
        "right-editmyprivateinfo": "แก้ไขข้อมูลส่วนตัวของคุณ (เช่น ที่อยู่อีเมล ชื่อจริง)",
        "right-editmyoptions": "แก้ไขการตั้งค่าของคุณ",
        "right-rollback": "ย้อนการแก้ไขของผู้ใช้ล่าสุดที่แก้ไขหน้าเฉพาะอย่างรวดเร็ว",
-       "right-markbotedits": "ทำเครื่องหมายการย้อนว่าเป็นการแก้ไขโดยบอต",
+       "right-markbotedits": "à¸\97ำà¹\80à¸\84รืà¹\88อà¸\87หมายà¸\81ารยà¹\89อà¸\99à¸\81ลัà¸\9aà¸\89ุà¸\81à¹\80à¸\89ิà¸\99วà¹\88าà¹\80à¸\9bà¹\87à¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¹\82à¸\94ยà¸\9aอà¸\95",
        "right-noratelimit": "ไม่ได้รับผลกระทบจากขีดจำกัดอัตรา",
        "right-import": "นำเข้าหน้าจากวิกิอื่น",
        "right-importupload": "นำเข้าหน้าจากไฟล์ที่อัปโหลด",
        "right-patrol": "ทำเครื่องหมายการแก้ไขของผู้อื่นว่าตรวจสอบแล้ว",
        "right-autopatrol": "ให้ทำเครื่องหมายการแก้ไขของตนเองเป็นตรวจสอบแล้วอัตโนมัติ",
-       "right-patrolmarks": "à¸\94ูà¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87ลà¹\88าสุà¸\94à¸\82อà¸\87à¸\81ารà¸\97ำà¹\80à¸\84รืà¹\88อà¸\87หมายà¸\95รวà¸\88สอà¸\9a",
+       "right-patrolmarks": "à¸\94ูà¸\81ารà¸\97ำà¹\80à¸\84รืà¹\88อà¸\87หมายà¸\95รวà¸\88สอà¸\9aà¹\83à¸\99à¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87ลà¹\88าสุà¸\94",
        "right-unwatchedpages": "ดูรายการหน้าที่ไม่มีผู้เฝ้าดู",
        "right-mergehistory": "รวมประวัติหน้า",
        "right-userrights": "แก้ไขสิทธิผู้ใช้ทั้งหมด",
        "action-history": "ดูประวัติของหน้านี้",
        "action-minoredit": "ทำเครื่องหมายการแก้ไขนี้เป็นการแก้ไขเล็กน้อย",
        "action-move": "ย้ายหน้านี้",
-       "action-move-subpages": "ย้ายหน้านี้ รวมทั้งหน้าย่อย",
+       "action-move-subpages": "ย้ายหน้านี้และหน้าย่อย",
        "action-move-rootuserpages": "ย้ายหน้าผู้ใช้หลัก",
        "action-movefile": "ย้ายไฟล์นี้",
        "action-upload": "อัปโหลดไฟล์นี้",
        "action-reupload": "อัปโหลดทับไฟล์ที่มีอยู่แล้วนี้",
        "action-reupload-shared": "เขียนไฟล์นี้ทับบนคลังส่วนกลาง",
-       "action-upload_by_url": "อัà¸\9bà¹\82หลà¸\94à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89à¸\88าà¸\81à¸\97ีà¹\88อยูà¹\88ยูอารà¹\8cà¹\81อล",
+       "action-upload_by_url": "อัปโหลดไฟล์นี้จากยูอาร์แอล",
        "action-writeapi": "ใช้การเขียนเอพีไอ",
        "action-delete": "ลบหน้านี้",
        "action-deleterevision": "ลบรุ่นนี้",
        "enhancedrc-history": "ประวัติ",
        "recentchanges": "ปรับปรุงล่าสุด",
        "recentchanges-legend": "ตัวเลือกการปรับปรุงล่าสุด",
-       "recentchanges-summary": "à¹\83à¸\99หà¸\99à¹\89าà¸\99ีà¹\89à¹\80à¸\9bà¹\87à¸\99รายà¸\81ารà¸\81ารà¸\9bรัà¸\9aà¸\9bรุà¸\87ลà¹\88าสุà¸\94à¸\9aà¸\99วิà¸\81ินี้",
+       "recentchanges-summary": "à¸\95ิà¸\94à¸\95ามà¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87ลà¹\88าสุà¸\94à¸\9aà¸\99วิà¸\81ิà¸\99ีà¹\89à¹\84à¸\94à¹\89à¸\97าà¸\87หà¸\99à¹\89านี้",
        "recentchanges-noresult": "ไม่มีการเปลี่ยนแปลงในช่วงที่กำหนดซึ่งตรงกับเกณฑ์เหล่านี้",
        "recentchanges-feed-description": "ติดตามการปรับปรุงล่าสุดในวิกินี้ในฟีดนี้",
        "recentchanges-label-newpage": "การแก้ไขนี้สร้างหน้าใหม่",
        "recentchanges-label-unpatrolled": "การแก้ไขนี้ยังไม่ได้ตรวจสอบ",
        "recentchanges-label-plusminus": "ขนาดของหน้าเปลี่ยนไปด้วยจำนวนไบต์เท่านี้",
        "recentchanges-legend-heading": "'''คำอธิบายสัญลักษณ์:'''",
-       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (ดูเพิ่มที่[[Special:NewPages|รายชื่อหน้าใหม่]])",
-       "rcnotefrom": "ด้านล่างเป็นการเปลี่ยนแปลงตั้งแต่ <strong>$2</strong> (มากสุด <strong>$1</strong> รายการ)",
-       "rclistfrom": "แสดงการเปลี่ยนแปลงใหม่เริ่มตั้งแต่ $3 $2",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (ดูเพิ่มที่ [[Special:NewPages|รายชื่อหน้าใหม่]])",
+       "rcnotefrom": "ด้านล่างเป็นการเปลี่ยนแปลงตั้งแต่ <strong>$3, $4</strong> (แสดงมากสุด <strong>$1</strong>)",
+       "rclistfrom": "แสดงการเปลี่ยนแปลงใหม่เริ่มตั้งแต่ $2, $3",
        "rcshowhideminor": "$1การแก้ไขเล็กน้อย",
        "rcshowhideminor-show": "แสดง",
        "rcshowhideminor-hide": "ซ่อน",
        "newpageletter": "ม",
        "boteditletter": "บ",
        "unpatrolledletter": "!",
-       "number_of_watching_users_pageview": "[$1 à¸\84à¸\99เฝ้าดู]",
+       "number_of_watching_users_pageview": "[$1 à¸\9cูà¹\89à¹\83à¸\8aà¹\89เฝ้าดู]",
        "rc_categories": "จำกัดเฉพาะหมวดหมู่ (แยกด้วย \"|\")",
        "rc_categories_any": "ใด ๆ",
        "rc-change-size-new": "$1 ไบต์หลังปรับปรุง",
        "reuploaddesc": "ยกเลิกการอัปโหลดและกลับไปยังแบบอัปโหลด",
        "upload-tryagain": "ส่งคำอธิบายไฟล์ที่ดัดแปรแล้ว",
        "uploadnologin": "ไม่ได้ล็อกอิน",
-       "uploadnologintext": "à¸\95à¹\89อà¸\87$1à¸\81à¹\88อà¸\99à¸\88ึà¸\87à¸\88ะอัà¸\9bà¹\82หลà¸\94à¹\84à¸\9fลà¹\8cà¹\84à¸\94à¹\89",
-       "upload_directory_missing": "à¹\84à¸\94à¹\80รà¸\81à¸\97อรีสำหรัà¸\9aอัà¸\9bà¹\82หลà¸\94 ($1) à¸«à¸²à¸¢à¹\84à¸\9b และเว็บเซิร์ฟเวอร์ไม่สามารถสร้างได้",
-       "upload_directory_read_only": "à¹\80วà¹\87à¸\9aà¹\80à¸\8bิรà¹\8cà¸\9fà¹\80วอรà¹\8cà¹\84มà¹\88สามารà¸\96à¹\80à¸\81à¹\87à¸\9aà¸\82à¹\89อมูลà¹\83à¸\99à¹\84à¸\94à¹\80รà¸\81à¸\97อรี ($1)",
+       "uploadnologintext": "à¹\82à¸\9bรà¸\94$1à¹\80à¸\9eืà¹\88ออัà¸\9bà¹\82หลà¸\94à¹\84à¸\9fลà¹\8c",
+       "upload_directory_missing": "สารà¸\9aà¸\9aอัà¸\9bà¹\82หลà¸\94 ($1) à¸«à¸²à¸¢ และเว็บเซิร์ฟเวอร์ไม่สามารถสร้างได้",
+       "upload_directory_read_only": "à¹\80วà¹\87à¸\9aà¹\80à¸\8bิรà¹\8cà¸\9fà¹\80วอรà¹\8cà¹\84มà¹\88สามารà¸\96à¹\80à¸\82ียà¸\99สารà¸\9aà¸\9aอัà¸\9bà¹\82หลà¸\94 ($1)",
        "uploaderror": "การอัปโหลดผิดพลาด",
        "upload-recreate-warning": "'''คำเตือน: ไฟล์ชื่อนั้นถูกลบหรือเปลี่ยนชื่อแล้ว'''\n\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>''' สำหรับการเชื่อมโยงไฟล์โดยตรง โดยไม่ปรากฏไฟล์นั้นออกมา",
        "uploadwarning": "คำเตือนการอัปโหลด",
        "uploadwarning-text": "กรุณาแก้ไขคำอธิบายไฟล์ด้านล่างนี้ แล้วลองใหม่อีกครั้ง",
        "savefile": "บันทึกไฟล์",
-       "uploadedimage": "อัปโหลด \"[[$1]]\"",
-       "overwroteimage": "อัปโหลดรุ่นใหม่ของ \"[[$1]]\"",
        "uploaddisabled": "ปิดใช้งานการอัปโหลด",
        "copyuploaddisabled": "ปิดใช้งานการอัปโหลดโดยยูอาร์แอล",
        "uploaddisabledtext": "ปิดใช้งานการอัปโหลดไฟล์",
        "sourcefilename": "ชื่อไฟล์ต้นทาง:",
        "sourceurl": "ยูอาร์แอลที่มา:",
        "destfilename": "ชื่อไฟล์ปลายทาง:",
-       "upload-maxfilesize": "à¸\82à¸\99าà¸\94à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¹\83หà¸\8dà¹\88à¸\97ีà¹\88สุà¸\94à¸\97ีà¹\88อà¸\99ุà¸\8dาà¸\95: $1",
+       "upload-maxfilesize": "à¸\82à¸\99าà¸\94à¹\84à¸\9fลà¹\8cà¹\83หà¸\8dà¹\88สุà¸\94: $1",
        "upload-description": "คำอธิบายไฟล์",
        "upload-options": "ตัวเลือกอัปโหลด",
        "watchthisupload": "เฝ้าดูไฟล์นี้",
        "upload-proto-error-text": "การอัปโหลดโดยตรงจากเว็บต้องการยูอาร์แอลที่ขึ้นต้นด้วย <code>http://</code> หรือ <code>ftp://</code>",
        "upload-file-error": "เกิดความผิดพลาดภายใน",
        "upload-file-error-text": "เกิดความผิดพลาดภายในขณะพยายามสร้างไฟล์ชั่วคราวบนเซิร์ฟเวอร์ กรุณาติดต่อ[[Special:ListUsers/sysop|ผู้ดูแลระบบ]]",
-       "upload-misc-error": "à¹\80à¸\81ิà¸\94à¸\84วามà¸\9cิà¸\94à¸\9eลาà¸\94à¹\83à¸\99à¸\81ารอัà¸\9bà¹\82หลà¸\94à¹\82à¸\94ยไม่ทราบสาเหตุ",
-       "upload-misc-error-text": "เกิดความผิดพลาดไม่ทราบสาเหตุระหว่างอัปโหลด กรุณาตรวจสอบว่ายูอาร์แอลนั้นถูกต้องและเข้าถึงได้ และลองอีกครั้ง ถ้ายังมีปัญหา ให้ติดต่อ[[Special:ListUsers/sysop|ผู้ดูแลระบบ]]",
-       "upload-too-many-redirects": "ยูอารà¹\8cà¹\81อลà¸\97ีà¹\88ระà¸\9aุมีการเปลี่ยนทางมากเกินไป",
+       "upload-misc-error": "à¹\80à¸\81ิà¸\94à¸\84วามà¸\9cิà¸\94à¸\9eลาà¸\94à¸\81ารอัà¸\9bà¹\82หลà¸\94ไม่ทราบสาเหตุ",
+       "upload-misc-error-text": "เกิดความผิดพลาดไม่ทราบสาเหตุระหว่างอัปโหลด \nกรุณาตรวจสอบว่ายูอาร์แอลนั้นถูกต้องและเข้าถึงได้ และลองอีกครั้ง \nถ้ายังมีปัญหา ให้ติดต่อ[[Special:ListUsers/sysop|ผู้ดูแลระบบ]]",
+       "upload-too-many-redirects": "ยูอารà¹\8cà¹\81อลà¸\99ัà¹\89à¸\99มีการเปลี่ยนทางมากเกินไป",
        "upload-http-error": "เกิดข้อผิดพลาดเอชทีทีพี: $1",
        "upload-copy-upload-invalid-domain": "การอัปโหลดสำเนาไม่สามารถทำได้จากโดเมนนี้",
-       "backend-fail-backup": "à¹\84มà¹\88สามารà¸\96สำรอà¸\87à¸\82à¹\89อมูลà¹\84à¸\9fลà¹\8c $1.",
+       "backend-fail-backup": "à¹\84มà¹\88สามารà¸\96สำรอà¸\87à¹\84à¸\9fลà¹\8c \"$1\"",
        "backend-fail-notexists": "ไม่มีไฟล์ $1",
-       "backend-fail-delete": "ไม่สามารถลบไฟล์ $1 ได้",
+       "backend-fail-delete": "ไม่สามารถลบไฟล์ \"$1\"",
        "backend-fail-alreadyexists": "มีไฟล์ \"$1\" อยู่แล้ว",
        "backend-fail-store": "ไม่สามารถเก็บไฟล์ \"$1\" ที่ \"$2\" ได้",
        "backend-fail-copy": "ไม่สามารถคัดลอกไฟล์ \"$1\" ไปยัง \"$2\" ได้",
        "license": "การอนุญาตใช้สิทธิ:",
        "license-header": "การอนุญาตใช้สิทธิ",
        "nolicense": "ไม่ได้เลือก",
+       "licenses-edit": "แก้ไขตัวเลือกใบอนุญาต",
        "license-nopreview": "(ไม่สามารถแสดงตัวอย่าง)",
-       "upload_source_url": " (ยูอาร์แอลถูกต้องที่สาธารณะสามารถเข้าถึงได้)",
-       "upload_source_file": " (ไฟล์จากคอมพิวเตอร์คุณ)",
+       "upload_source_url": "(ไฟล์ที่คุณเลือกจากยูอาร์แอลที่สมเหตุสมผลและสาธารณะเข้าถึงได้)",
+       "upload_source_file": "(ไฟล์ที่คุณเลือกจากคอมพิวเตอร์ของคุณ)",
+       "listfiles-delete": "ลบ",
        "listfiles-summary": "หน้าพิเศษนี้แสดงไฟล์ทั้งหมดที่อัปโหลด",
        "listfiles_search_for": "ค้นหาชื่อสื่อ:",
        "imgfile": "ไฟล์",
        "randomincategory": "สุ่มหน้าในหมวดหมู่",
        "randomincategory-invalidcategory": "\"$1\" มิใช่ชื่อหมวดหมู่ที่ถูกต้อง",
        "randomincategory-nopages": "ไม่มีหน้าใน[[:Category:$1]]",
-       "randomincategory-selectcategory": "ดึงหน้าแบบสุ่มจากหมวดหมู่: $1 $2",
-       "randomincategory-selectcategory-submit": "ไป",
        "randomredirect": "สุ่มหน้าเปลี่ยนทาง",
        "randomredirect-nopages": "ไม่มีหน้าเปลี่ยนทางในเนมสเปซ \"$1\"",
        "statistics": "สถิติ",
        "wantedpages-badtitle": "ชื่อเรื่องไม่สมเหตุสมผลในเซตผลลัพธ์: $1",
        "wantedfiles": "ไฟล์ที่ต้องการ",
        "wantedfiletext-cat": "ไฟล์ต่อไปนี้มีการเรียกใช้แต่ไม่มีอยู่ ไฟล์จากคลังเก็บภาษาอื่นอาจแสดงรายการแม้จะมีอยู่ ผลบวกลวงใด ๆ จะถูก<del>ขีดฆ่า</del> ยิ่งไปกว่านั้น หน้าที่ฝังตัวไฟล์ที่ไม่มีอยู่จะแสดงรายการใน [[:$1]]",
+       "wantedfiletext-cat-noforeign": "ไฟล์ต่อไปนี้ถูกใช้แต่ไม่มีไฟล์ นอกเหนือจากนี้ หน้าที่ฝังตัวไฟล์ที่ไม่มีอยู่แสดงรายการใน [[:$1]]",
        "wantedfiletext-nocat": "ไฟล์ต่อไปนี้มีการเรียกใช้แต่ไม่มีอยู่ ไฟล์จากคลังเก็บภาษาอื่นอาจแสดงรายการแม้จะมีอยู่ ผลบวกลวงใด ๆ จะถูก<del>ขีดฆ่า</del>",
+       "wantedfiletext-nocat-noforeign": "ไฟล์ต่อไปนี้ถูกใช้แต่ไม่มีไฟล์",
        "wantedtemplates": "แม่แบบที่ต้องการ",
        "mostlinked": "หน้าที่มีการเชื่อมโยงหามากที่สุด",
        "mostlinkedcategories": "หมวดหมู่ที่มีการเชื่อมโยงหามากที่สุด",
        "mywatchlist": "รายการเฝ้าดู",
        "watchlistfor2": "สำหรับ $1 $2",
        "nowatchlist": "ไม่มีรายการในรายการเฝ้าดูของคุณ",
-       "watchlistanontext": "กรุณา$1เพื่อดูหรือแก้ไขรายการในรายการเฝ้าดูของคุณ",
+       "watchlistanontext": "กรุณาล็อกอินเพื่อดูหรือแก้ไขรายการในรายการเฝ้าดูของคุณ",
        "watchnologin": "ยังไม่ได้ล็อกอิน",
        "addwatch": "เพิ่มเข้ารายการเฝ้าดู",
        "addedwatchtext": "หน้า \"[[:$1]]\" ได้เพิ่มลงใน[[Special:Watchlist|รายการเฝ้าดู]]ของคุณแล้ว การเปลี่ยนแปลงในหน้านี้หรือหน้าพูดคุยที่เกี่ยวข้องจะแสดงในรายการดังกล่าว",
        "watchlist-details": "มี $1 หน้าในรายการเฝ้าดูของคุณ ไม่นับแยกหน้าอภิปราย",
        "wlheader-enotif": "การแจ้งเตือนผ่านอีเมลถูกเปิดใช้งาน",
        "wlheader-showupdated": "หน้าที่มีการเปลี่ยนแปลงตั้งแต่คุณเข้าชมล่าสุดแสดงใน'''ตัวหนา'''",
-       "wlnote2": "ด้านล่างเป็นการเปลี่ยนแปลงล่าสุดในช่วง <strong>$1</strong> ชั่วโมงล่าสุด จนถึงวันที่ $2 เวลา $3 น.",
+       "wlnote": "ด้านล่างเป็นการแก้ไข{{PLURAL:$1|ล่าสุด|ล่าสุด <strong>$1</strong> รายการ}} ใน{{PLURAL:$2|ชั่วโมง| <strong>$2</strong> ชั่วโมง}}ที่ผ่านมา จนถึง $3, $4",
        "wlshowlast": "แสดง $1 ชั่วโมง $2 วันล่าสุด $3",
        "watchlist-options": "ตัวเลือกรายการเฝ้าดู",
        "watching": "เฝ้าดู...",
        "protect-title-notallowed": "ดูระดับการล็อกของ \"$1\"",
        "prot_1movedto2": "[[$1]] ถูกเปลี่ยนชื่อเป็น [[$2]]",
        "protect-badnamespace-title": "เนมสเปซล็อกไม่ได้",
-       "protect-badnamespace-text": "หà¸\99à¹\89าà¹\83à¸\99à¹\80à¸\99มสà¹\80à¸\9bà¸\8bà¸\99ีà¹\89à¹\84มà¹\88สามารà¸\96à¸\9bà¹\89อà¸\87à¸\81ัà¸\99ได้",
+       "protect-badnamespace-text": "ลà¹\87อà¸\81หà¸\99à¹\89าà¹\83à¸\99à¹\80à¸\99มสà¹\80à¸\9bà¸\8bà¸\99ีà¹\89à¹\84มà¹\88ได้",
        "protect-norestrictiontypes-text": "หน้านี้ไม่สามารถถูกล็อก เพราะไม่มีประเภทการจำกัดที่ใช้ได้",
        "protect-norestrictiontypes-title": "หน้าที่ล็อกไม่ได้",
        "protect-legend": "ยืนยันการล็อก",
        "sp-contributions-newbies-sub": "สำหรับบัญชีใหม่",
        "sp-contributions-newbies-title": "เรื่องที่เขียนโดยบัญชีใหม่",
        "sp-contributions-blocklog": "ปูมการบล็อก",
-       "sp-contributions-deleted": "การแก้ไขที่ถูกลบ",
+       "sp-contributions-deleted": "à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82อà¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88à¸\96ูà¸\81ลà¸\9a",
        "sp-contributions-uploads": "อัปโหลด",
        "sp-contributions-logs": "ปูม",
        "sp-contributions-talk": "พูดคุย",
        "blockip": "บล็อกผู้ใช้",
        "blockip-legend": "บล็อกผู้ใช้",
        "blockiptext": "ใช้แบบด้านล่างเพื่อบล็อกสิทธิเข้าถึงการเขียนของเลขที่อยู่ไอพีหรือชื่อผู้ใช้โดยเจาะจง การบล็อกนี้ควรดำเนินการเพื่อป้องกันการก่อกวนเท่านั้น และให้สอดคล้องกับ[[{{MediaWiki:Policy-url}}|นโยบาย]]\nกรอกเหตุผลโดยเจาะจงด้านล่าง (เช่น อ้างถึงหน้าที่ถูกก่อกวน)",
-       "ipaddressorusername": "เลขที่อยู่ไอพีหรือชื่อผู้ใช้",
-       "ipbexpiry": "หมดอายุ",
+       "ipaddressorusername": "เลขที่อยู่ไอพีหรือชื่อผู้ใช้:",
+       "ipbexpiry": "หมดอายุ:",
        "ipbreason": "เหตุผล:",
        "ipbreason-dropdown": "*สาเหตุการบล็อกทั่วไป\n** ใส่ข้อมูลเท็จ\n** ลบเนื้อหาในหน้าออก\n** ใส่ลิงก์สแปม\n** ใส่ข้อความไร้สาระ/ขยะเข้ามา\n** พฤติกรรมข่มขู่/รังควาน\n** ใช้หลายบัญชีในทางที่ผิด\n** ชื่อผู้ใช้ที่ไม่อาจยอมรับได้",
        "ipb-hardblock": "ป้องกันไม่ให้ผู้ใช้ล็อกอินแก้ไขจากเลขที่อยู่ไอพีนี้",
        "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",
-       "ipbhidename": "à¸\8bà¹\88อà¸\99à¸\8aืà¹\88อà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\88าà¸\81à¸\9bูมและรายการต่าง ๆ",
-       "ipbwatchuser": "à¹\80à¸\9dà¹\89าà¸\94ูหà¸\99à¹\89าà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\81ละหà¸\99à¹\89าà¸\84ุยà¸\81ัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\82อà¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89รายà¸\99ีà¹\89",
+       "ipbhidename": "à¸\8bà¹\88อà¸\99à¸\8aืà¹\88อà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\88าà¸\81à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82และรายการต่าง ๆ",
+       "ipbwatchuser": "เฝ้าดูหน้าผู้ใช้และหน้าคุยกับผู้ใช้ของผู้ใช้นี้",
        "ipb-disableusertalk": "ป้องกันไม่ให้ผู้ใช้นี้แก้ไขหน้าคุยกับผู้ใช้ของตัวเองขณะถูกบล็อก",
        "ipb-change-block": "บล็อกผู้ใช้อีกครั้งด้วยการตั้งค่าเหล่านี้",
        "ipb-confirm": "ยืนยันการบล็อก",
        "badipaddress": "เลขที่อยู่ไอพีไม่ถูกต้อง",
        "blockipsuccesssub": "บล็อกสำเร็จ",
-       "blockipsuccesstext": "[[Special:Contributions/$1|$1]] à¹\84à¸\94à¹\89à¸\96ูà¸\81à¸\9aลà¹\87อà¸\81à¹\81ลà¹\89ว<br />\nà¸\94ู[[Special:BlockList|รายà¸\81ารà¸\9aลà¹\87อà¸\81]]à¹\80à¸\9eืà¹\88อà¸\97à¸\9aà¸\97วà¸\99à¸\81ารà¸\9aลà¹\87อà¸\81",
+       "blockipsuccesstext": "[[Special:Contributions/$1|$1]] ถูกบล็อกแล้ว<br />\nดู[[Special:BlockList|รายการบล็อก]]เพื่อทบทวนการบล็อก",
        "ipb-blockingself": "คุณกำลังบล็อกตัวเอง! แน่ใจแล้วหรือว่าต้องการทำอย่างนั้น",
        "ipb-confirmhideuser": "คุณกำลังบล็อกผู้ใช้โดยเป็นผู้ใช้ \"ซ่อนผู้ใช้\" ซึ่งจะระงับชื่อผู้ใช้ในรายการและหน่วยปูมทั้งหมด คุณแน่ใจหรือว่าต้องการดำเนินการเช่นนั้น",
-       "ipb-confirmaction": "หากคุณแน่ใจว่าคุณต้องการดำเนินการ โปรดเลือกเขตข้อมูล \"{{int:ipb-confirm}}\"  ที่อยู่ล่างสุด",
+       "ipb-confirmaction": "หากคุณแน่ใจว่าคุณต้องการดำเนินการ โปรดเลือกเขตข้อมูล \"{{int:ipb-confirm}}\" ที่อยู่ล่างสุด",
        "ipb-edit-dropdown": "แก้ไขสาเหตุการบล็อก",
        "ipb-unblock-addr": "ปลดบล็อก $1",
        "ipb-unblock": "ปลดบล็อกผู้ใช้หรือเลขที่อยู่ไอพี",
        "ipb-blocklist": "ดูการบล็อกปัจจุบัน",
        "ipb-blocklist-contribs": "ผลงานเขียนโดย $1",
        "unblockip": "ปลดบล็อกผู้ใช้",
-       "unblockiptext": "à¹\83à¸\8aà¹\89à¹\81à¸\9aà¸\9aà¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¹\80à¸\9eืà¹\88อà¸\84ืà¸\99สิà¸\97à¸\98ิà¸\81ารà¹\80à¸\82à¹\89าà¸\96ึà¸\87à¸\81ารà¹\80à¸\82ียà¸\99à¹\81à¸\81à¹\88à¹\80ลà¸\82à¸\97ีà¹\88อยูà¹\88à¹\84อà¸\9eี à¸«à¸£à¸·à¸­à¸\8aืà¹\88อà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88à¹\80à¸\84ยà¸\96ูà¸\81à¸\9aลà¹\87อà¸\81",
+       "unblockiptext": "ใช้แบบด้านล่างเพื่อคืนการเข้าถึงการเขียนแก่เลขที่อยู่ไอพี หรือชื่อผู้ใช้ที่เคยถูกบล็อก",
        "ipusubmit": "ยกเลิกการบล็อกนี้",
        "unblocked": "[[User:$1|$1]] ถูกปลดบล็อกแล้ว",
        "unblocked-range": "$1 ถูกปลดบล็อกแล้ว",
-       "unblocked-id": "เลิกบล็อก $1",
+       "unblocked-id": "บล็อก $1 ถูกนำออกแล้ว",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] ถูกปลดบล็อก",
        "blocklist": "ผู้ใช้ที่ถูกบล็อก",
        "ipblocklist": "ผู้ใช้ที่ถูกบล็อก",
        "ipblocklist-legend": "ค้นหาผู้ใช้ที่ถูกบล็อก",
-       "blocklist-userblocks": "ซ่อนบล็อกบัญชี",
-       "blocklist-tempblocks": "ซ่อนบล็อกชั่วคราว",
-       "blocklist-addressblocks": "ซ่อนบล็อกไอพีเดียว",
+       "blocklist-userblocks": "à¸\8bà¹\88อà¸\99à¸\81ารà¸\9aลà¹\87อà¸\81à¸\9aัà¸\8dà¸\8aี",
+       "blocklist-tempblocks": "à¸\8bà¹\88อà¸\99à¸\81ารà¸\9aลà¹\87อà¸\81à¸\8aัà¹\88วà¸\84ราว",
+       "blocklist-addressblocks": "à¸\8bà¹\88อà¸\99à¸\81ารà¸\9aลà¹\87อà¸\81à¹\84อà¸\9eีà¹\80à¸\94ียว",
        "blocklist-rangeblocks": "ซ่อนการบล็อกช่วง",
        "blocklist-timestamp": "ตราเวลา",
        "blocklist-target": "เป้าหมาย",
        "expiringblock": "หมดอายุ $1 เวลา $2",
        "anononlyblock": "ไม่ล็อกอินเท่านั้น",
        "noautoblockblock": "ยกเลิกการบล็อกอัตโนมัติ",
-       "createaccountblock": "ปิดใช้งานการสร้างบัญชีผู้ใช้ใหม่",
+       "createaccountblock": "ปิดใช้งานการสร้างบัญชี",
        "emailblock": "ปิดใช้งานอีเมล",
        "blocklist-nousertalk": "ไม่สามารถแก้ไขหน้าคุยกับผู้ใช้ของตนเอง",
        "ipblocklist-empty": "รายการบล็อกว่าง",
        "ipblocklist-no-results": "เลขที่อยู่ไอพีหรือชื่อผู้ใช้ที่ต้องการไม่ได้ถูกบล็อก",
        "blocklink": "บล็อก",
-       "unblocklink": "à¹\80ลิà¸\81บล็อก",
+       "unblocklink": "à¸\9bลà¸\94บล็อก",
        "change-blocklink": "เปลี่ยนการบล็อก",
        "contribslink": "เรื่องที่เขียน",
        "emaillink": "ส่งอีเมล",
        "block-log-flags-angry-autoblock": "การบล็อกอัตโนมัติขั้นสูงเปิดใช้งาน",
        "block-log-flags-hiddenname": "ชื่อผู้ใช้ถูกซ่อน",
        "range_block_disabled": "การบล็อกช่วงไอพีของผู้ดูแลระบบถูกปิดการใช้งาน",
-       "ipb_expiry_invalid": "วัà¸\99หมดอายุไม่ถูกต้อง",
+       "ipb_expiry_invalid": "à¹\80วลาหมดอายุไม่ถูกต้อง",
        "ipb_expiry_temp": "การบล็อกชื่อผู้ใช้ที่ซ่อนต้องเป็นการบล็อกถาวร",
        "ipb_hide_invalid": "ไม่สามารถยับยั้งชื่อผู้ใช้นี้ได้ อาจเพราะมีการแก้ไขมากกว่า $1 การแก้ไข",
-       "ipb_already_blocked": "\"$1\" ถูกบล็อกไปแล้วก่อนหน้านี้",
+       "ipb_already_blocked": "\"$1\" ถูกบล็อกไปแล้ว",
        "ipb-needreblock": "$1 ถูกบล็อกแล้ว คุณต้องการเปลี่ยนการตั้งค่าหรือไม่",
-       "ipb-otherblocks-header": "{{PLURAL:$1|การบล็อก}}อื่น ๆ",
-       "unblock-hideuser": "à¸\84ุà¸\93à¹\84มà¹\88สามารà¸\96ยà¸\81à¹\80ลิà¸\81à¸\81ารà¸\9aลà¹\87อà¸\81à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\87าà¸\99รายนี้ได้ เพราะชื่อผู้ใช้ถูกซ่อนอยู่",
-       "ipb_cant_unblock": "à¸\82à¹\89อà¸\9cิà¸\94à¸\9eลาà¸\94: à¹\84มà¹\88à¸\9eà¸\9aหมายà¹\80ลà¸\82à¸\9aลà¹\87อà¸\81 $1 à¸\81ารà¸\9aลà¹\87อà¸\81à¸\94ัà¸\87à¸\81ลà¹\88าวอาจถูกปลดบล็อกแล้ว",
-       "ipb_blocked_as_range": "à¸\82à¹\89อà¸\9cิà¸\94à¸\9eลาà¸\94: à¹\80ลà¸\82à¸\97ีà¹\88อยูà¹\88à¹\84อà¸\9eี $1 à¸¡à¸´à¹\84à¸\94à¹\89à¸\96ูà¸\81à¸\9aลà¹\87อà¸\81à¹\82à¸\94ยà¸\95รà¸\87à¹\81ละà¹\84มà¹\88สามารà¸\96à¸\9bลà¸\94à¸\9aลà¹\87อà¸\81à¹\84à¸\94à¹\89\nอยà¹\88าà¸\87à¹\84รà¸\81à¹\87à¸\95าม à¹\84อà¸\9eีà¸\99ีà¹\89à¸\96ูà¸\81ระà¸\87ัà¸\9aà¹\83à¸\99à¸\90าà¸\99ะà¸\97ีà¹\88à¹\80à¸\9bà¹\87à¸\99สà¹\88วà¸\99หà¸\99ึà¹\88à¸\87à¸\82อà¸\87à¹\80ลà¸\82à¸\97ีà¹\88อยูà¹\88à¹\84อà¸\9eีà¹\83à¸\99à¸\9eิสัย $2 ซึ่งสามารถปลดบล็อกได้",
+       "ipb-otherblocks-header": "{{PLURAL:$1|การบล็อก}}อื่น",
+       "unblock-hideuser": "à¸\84ุà¸\93à¹\84มà¹\88สามารà¸\96à¸\9bลà¸\94à¸\9aลà¹\87อà¸\81à¸\9cูà¹\89à¹\83à¸\8aà¹\89นี้ได้ เพราะชื่อผู้ใช้ถูกซ่อนอยู่",
+       "ipb_cant_unblock": "à¸\82à¹\89อà¸\9cิà¸\94à¸\9eลาà¸\94: à¹\84มà¹\88à¸\9eà¸\9aà¸\81ารà¸\9aลà¹\87อà¸\81หมายà¹\80ลà¸\82 $1 อาจถูกปลดบล็อกแล้ว",
+       "ipb_blocked_as_range": "à¸\82à¹\89อà¸\9cิà¸\94à¸\9eลาà¸\94: à¹\80ลà¸\82à¸\97ีà¹\88อยูà¹\88à¹\84อà¸\9eี $1 à¸¡à¸´à¹\84à¸\94à¹\89à¸\96ูà¸\81à¸\9aลà¹\87อà¸\81à¹\82à¸\94ยà¸\95รà¸\87à¹\81ละà¹\84มà¹\88สามารà¸\96à¸\9bลà¸\94à¸\9aลà¹\87อà¸\81à¹\84à¸\94à¹\89\nอยà¹\88าà¸\87à¹\84รà¸\81à¹\87à¸\95าม à¹\84อà¸\9eีà¸\99ีà¹\89à¸\96ูà¸\81ระà¸\87ัà¸\9aà¹\82à¸\94ยà¹\80à¸\9bà¹\87à¸\99สà¹\88วà¸\99หà¸\99ึà¹\88à¸\87à¸\82อà¸\87à¸\8aà¹\88วà¸\87 $2 ซึ่งสามารถปลดบล็อกได้",
        "ip_range_invalid": "พิสัยไอพีไม่ถูกต้อง",
        "ip_range_toolarge": "พิสัยบล็อกที่มีขนาดใหญ่กว่า /$1 จะไม่ได้รับอนุญาต",
        "proxyblocker": "ตัวบล็อกพร็อกซี",
        "import": "หน้านำเข้า",
        "importinterwiki": "นำเข้าข้ามวิกิ",
        "import-interwiki-text": "เลือกวิกิและชื่อหัวข้อที่ต้องการนำเข้า วันที่และชื่อผู้เขียนทั้งหมดจะถูกเก็บไว้ โดยการนำเข้าทุกส่วนจะถูกเก็บไว้ใน [[Special:Log/import|ปูมการนำเข้า]]",
-       "import-interwiki-source": "หน้า/วิกิต้นทาง:",
        "import-interwiki-history": "คัดลอกประวัติทั้งหมดในหน้านี้",
        "import-interwiki-templates": "รวมแม่แบบทั้งหมด",
        "import-interwiki-submit": "นำเข้า",
        "autosumm-replace": "แทนที่ข้อความทั้งหมดด้วย '$1'",
        "autoredircomment": "เปลี่ยนทางไปที่ [[$1]]",
        "autosumm-new": "หน้าที่ถูกสร้างด้วย '$1'",
+       "autosumm-newblank": "สร้างหน้าว่าง",
        "size-bytes": "$1 ไบต์",
        "size-kilobytes": "$1 กิโลไบต์",
        "size-megabytes": "$1 เมกะไบต์",
        "watchlistedit-raw-done": "รายการเฝ้าดูของคุณได้ปรับแล้ว",
        "watchlistedit-raw-added": "$1 ชื่อเรื่องได้ถูกเพิ่มเข้าไป:",
        "watchlistedit-raw-removed": "$1 ชื่อเรื่องได้ถูกนำออกไป:",
+       "watchlistedit-clear-title": "ล้างรายการเฝ้าดู",
        "watchlistedit-clear-legend": "ล้างรายการเฝ้าดู",
+       "watchlistedit-clear-explain": "ชื่อเรื่องทั้งหมดจะถูกนำออกจากรายการเฝ้าดูของคุณ",
+       "watchlistedit-clear-titles": "ชื่อเรื่อง:",
+       "watchlistedit-clear-submit": "ล้างรายการเฝ้าดู (เป็นการถาวร!)",
+       "watchlistedit-clear-done": "ล้างรายการเฝ้าดูของคุณแล้ว",
+       "watchlistedit-clear-removed": "$1 ชื่อเรื่องถูกนำออก:",
+       "watchlistedit-too-many": "มีหน้ามากเกินไปที่จะแสดงผลที่นี่",
        "watchlisttools-clear": "ล้างรายการเฝ้าดู",
        "watchlisttools-view": "ดูการเปลี่ยนแปลงที่เกี่ยวข้อง",
        "watchlisttools-edit": "ดูและแก้ไขรายการเฝ้าดู",
        "logentry-rights-rights": "$1 {{GENDER:$2|เปลี่ยน}}กลุ่มสมาชิกของ $3 จาก $4 เป็น $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|เปลี่ยน}}กลุ่มสมาชิกของ $3",
        "logentry-rights-autopromote": "$1 ได้รับการ{{GENDER:$2|เลื่อนกลุ่ม}}จาก $4 เป็น $5 อัตโนมัติ",
+       "logentry-upload-upload": "$1 อัปโหลด $3",
+       "logentry-upload-overwrite": "$1 อัปโหลดรุ่นใหม่ของ $3",
+       "logentry-upload-revert": "$1 อัปโหลด $3",
        "rightsnone": "(ไม่มี)",
        "feedback-bugornote": "หากคุณได้อธิบายปัญหาทางเทคนิคในรายละเอียดแล้ว โปรด[$1 รายงานจุดบกพร่อง]\nมิฉะนั้น คุณสามารถแบบอย่างง่ายด้านล่าง ความเห็นของคุณจะถูกเพิ่มเข้าสู่ \"[$3 $2]\" ร่วมกับชื่อผู้ใช้ของคุณ",
        "feedback-subject": "เรื่อง:",
        "expand_templates_output": "ผลลัพธ์",
        "expand_templates_ok": "ตกลง",
        "expand_templates_remove_comments": "นำส่วนความเห็นออก",
-       "expand_templates_preview": "ตัวอย่างผลแสดง"
+       "expand_templates_preview": "ตัวอย่างผลแสดง",
+       "pagelanguage": "ตัวเลือกภาษาหน้า",
+       "pagelang-name": "หน้า",
+       "pagelang-language": "ภาษา",
+       "pagelang-use-default": "ใช้ภาษาโดยปริยาย",
+       "pagelang-select-lang": "เลือกภาษา",
+       "right-pagelang": "เปลี่ยนภาษาหน้า",
+       "action-pagelang": "เปลี่ยนภาษาหน้า",
+       "log-name-pagelang": "ปูมการเปลี่ยนภาษา",
+       "log-description-pagelang": "นี่คือปูมการเปลี่ยนภาษาหน้า",
+       "logentry-pagelang-pagelang": "$1 เปลี่ยนภาษาของ $3 จาก $4 เป็น $5",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (เปิดใช้งาน)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''ปิดใช้งาน''')"
 }
index c6b21c3..07d5212 100644 (file)
        "talkpagelinktext": "Pikir alyşma",
        "specialpage": "Ýörite Sahypa",
        "personaltools": "Şahsy gurallar",
-       "postcomment": "Täze bölüm",
        "articlepage": "Makalany görkez",
        "talk": "Çekişme",
        "views": "Görnüşler",
        "externaldberror": "Ýa tassyklama maglumat bazasynyň säwligi bar ýa-da öz ulanyjy hasabyňyzy täzelemegiňize rugsat berilmeýär.",
        "login": "Hasaba gir",
        "nav-login-createaccount": "Hasaba gir / Hasap döret",
-       "loginprompt": "{{SITENAME}} saýtynda sessiýa açmak üçin kukileri işletmegiňiz zerurdyr.",
        "userlogin": "Hasaba gir / täze hasap aç",
        "userloginnocreate": "Sessiýa aç",
        "logout": "Hasapdan çyk",
        "searchprofile-advanced-tooltip": "Laýyk at giňişliklerinde gözle",
        "search-result-size": "$1 ({{PLURAL:$2|1 söz|$2 söz}})",
        "search-result-category-size": "{{PLURAL:$1|1 agza|$1 agza}} ({{PLURAL:$2|1 kiçi kategoriýa|$2 kiçi kategoriýa}}, {{PLURAL:$3|1 faýl|$3 faýl}})",
-       "search-result-score": "Kybapdaşlyk: $1%",
        "search-redirect": "(gönükdirme $1)",
        "search-section": "(bölüm $1)",
        "search-suggest": "Şeýle diýjek bolduňyzmy: $1",
        "uploadwarning": "Ýükleme duýduryşy",
        "uploadwarning-text": "Aşakdaky faýl düşündirişini üýtgediň we gaýtadan synanyşyň.",
        "savefile": "Faýly ýazdyr",
-       "uploadedimage": "Ýüklenen: \"[[$1]]\"",
-       "overwroteimage": "\"[[$1]]\" faýlynyň täze wersiýasy ýüklendi",
        "uploaddisabled": "Ýüklemeklik ýapyk",
        "copyuploaddisabled": "URL arkaly ýüklemek ýapyk.",
        "uploaddisabledtext": "Faýl ýüklemeklik ýapyk.",
        "watchlist-details": "Çekişme sahypalaryny hasap etmäniňde, gözegçilik sanawyňyzda {{PLURAL:$1|$1 sahypa|$1 sahypa}} bar.",
        "wlheader-enotif": "E-poçta bilen habar beriş açyk.",
        "wlheader-showupdated": "Soňky gezek baryp görenizden soňra üýtgedilen sahypalar '''goýy şrift''' bilen görkezilýär.",
+       "wlnote": "Aşakda soňky {{PLURAL:$2|bir sagatda|'''$2''' sagatda}} edilen {{PLURAL:$1|soňky üýtgeşme|soňky '''$1''' üýtgeşme}} görkezilýär.",
        "wlshowlast": "Soňky $1 sagady $2 güni görkez $3",
        "watchlist-options": "Gözegçilik sanawynyň opsiýalary",
        "watching": "Gözegçilige alynýar...",
index c589b01..cbb0891 100644 (file)
        "talkpagelinktext": "Usapan",
        "specialpage": "Natatanging pahina",
        "personaltools": "Mga kagamitang pansarili",
-       "postcomment": "Bagong seksiyon",
        "articlepage": "Tingnan ang pahina ng nilalaman",
        "talk": "Usapan",
        "views": "Mga anyo",
        "externaldberror": "Maaaring may kamalian sa pagpapatotoo ng database o kaya hindi ka pinahintulutang isapanahon ng iyong panlabas na account.",
        "login": "Lumagda",
        "nav-login-createaccount": "Lumagda / lumikha ng account",
-       "loginprompt": "Dapat na pinapahintulutan mo ang mga kuki (''cookie'') upang makalagda sa {{SITENAME}}.",
        "userlogin": "Lumagda / lumikha ng account",
        "userloginnocreate": "Lumagda",
        "logout": "Umalis sa pagkaka-login",
        "searchprofile-advanced-tooltip": "Hanapin sa pinasadyang mga espasyo ng pangalan",
        "search-result-size": "$1 ({{PLURAL:$2|1 salita|$2 salita}})",
        "search-result-category-size": "{{PLURAL:$1|isang kasapi|$1 kasapi}} ({{PLURAL:$2|isang subkategorya|$2 subkategorya}}, {{PLURAL:$3|isang talaksan|$3 talaksan}})",
-       "search-result-score": "Kaugnayan: $1%",
        "search-redirect": "(ipanuto/ituro ang $1)",
        "search-section": "(seksyong $1)",
        "search-suggest": "Ito ba ang ibig mong sabihin: $1",
        "uploadwarning": "Babala sa pagkakarga",
        "uploadwarning-text": "Pakibago ang nasa ibabang paglalarawan ng talaksan at subukan muli.",
        "savefile": "Sagipin ang talaksan",
-       "uploadedimage": "ikinarga ang \"[[$1]]\"",
-       "overwroteimage": "nagkarga ng isang bagong bersyon ng \"[[$1]]\"",
        "uploaddisabled": "Hindi pinagana ang mga pagkarga",
        "copyuploaddisabled": "Ikargang paitaas ayon sa hindi pinaganang URL.",
        "uploaddisabledtext": "Hindi pinagana ang mga pagkakarga ng talaksan.",
        "watchlist-details": "{{PLURAL:$1|$1 pahinang|$1 mga pahinang}} nasa iyong talaan ng mga binabantayan, hindi binibilang ang mga pahina ng usapan.",
        "wlheader-enotif": "Umiiral ang pagpapahayag sa pamamagitan ng e-liham.",
        "wlheader-showupdated": "Ipinapakitang may '''makakapal na mga panitik''' ang nabagong/binagong mga pahina mula pa noong huli mong pagdalaw sa kanila",
-       "wlnote2": "Nasa ibaba ang mga pagbabago sa nakaraang <strong>$1</strong> oras, noon pang $2, $3.",
+       "wlnote": "Nasa ibaba ang {{PLURAL:$1|pinakahuling pagbabago|pinakahuling '''$1''' mga pagbabago}} sa loob ng huling {{PLURAL:$2|oras|'''$2''' mga oras}}, magmula noong $3 sa ganap na ika-$4.",
        "wlshowlast": "Ipakita ang huling $1 mga oras $2 mga araw $3",
        "watchlist-options": "Mga pagpipilian para sa talaan ng mga binabantayan",
        "watching": "Isinasama sa mga binabantayan...",
index 2f9d67a..79b7b31 100644 (file)
        "talkpagelinktext": "Mızokirə",
        "specialpage": "Хысусијә сәһифә",
        "personaltools": "Шәхси диләгон",
-       "postcomment": "Нујә ғысм",
        "articlepage": "Мәғолә дијә кардеј",
        "talk": "Mızokirə",
        "views": "Тәмшо кардеј",
        "remembermypassword": "Мыни ым компутерәдә јодәдә огәт (максимум $1 {{PLURAL:$1|руж|руж}})",
        "login": "Ыштәни едаштеј",
        "nav-login-createaccount": "Ыштәни едаштеј / ыштәни ғејд кардовнијеј",
-       "loginprompt": "{{SITENAME}}-әдә ыштәни едәште горнә, шымә бәбе бә «cookies» иҹозә быдән.",
        "userlogin": "Ыштәни едаштеј / ыштәни ғејд кардовнијеј",
        "userloginnocreate": "Ыштәни едаштеј",
        "logout": "Системәдә кој орохнијеј",
        "upload": "Фајли бо жәј",
        "uploadlogpage": "Бо кардә быә чијон журнал",
        "filedesc": "Кыртә тәсвир",
-       "uploadedimage": "бо жәше \"[[$1]]\"",
        "license": "Лисензијә:",
        "license-header": "Лисензијә",
        "imgfile": "фајл",
index 58e73ab..1aed46c 100644 (file)
        "talkpagelinktext": "Alea",
        "specialpage": "Peesi makehe",
        "personaltools": "Puha haʻate meʻangāue",
-       "postcomment": "Fokotuʻu ha fakamatala",
        "articlepage": "Vakai ki he peesi kakano",
        "talk": "Alea",
        "views": "Ngaahi vakai",
        "yourdomainname": "ho ngāueʻanga",
        "login": "Kau ki ai",
        "nav-login-createaccount": "Kau ki ai",
-       "loginprompt": "ʻOku pau te ke fakamafeia ʻa e ngaahi foʻi keke kapau te ke fie kau-ki-ai ki he {{SITENAME}}.",
        "userlogin": "Kau ki ai",
        "logout": "ʻAlu mamaʻo",
        "userlogout": "ʻAlu mamaʻo",
        "fileexists-shared-forbidden": "ʻOku toka ʻi ai ha peesi mo e hingoa ē ʻi he kalasi vahevahe; fakamolemole ʻe foki pea hiki hake ʻa e failé ni mo e ha hingoa foʻou. [[File:$1|thumb|center|$1]]",
        "uploadwarning": "Tokanga hiki hake",
        "savefile": "Haofaki faitaá ni",
-       "uploadedimage": "\"[[$1]]\" ʻosi hiki hake",
        "uploaddisabled": "ʻOku fakataʻeʻaongaʻi ʻa e ngaahi hiki hake",
        "uploaddisabledtext": "ʻOku fakataʻeʻaongaʻi ha ngaahi hiki hake ʻi heni.",
        "uploadvirus": "ʻOku ʻi ai ha vailasi ʻi he failé ni! ʻŪ kiʻi meʻa: $1",
        "watchlist-details": "ʻOku leʻoʻi ʻa e peesi ʻe $1, ʻikai kau ki ai ʻa e ngaahi peesi alea.",
        "wlheader-enotif": "Kuo fakamafeiaʻi tala mei he tohila",
        "wlheader-showupdated": "*Ko e ngaahi peesi kuo liliu talu he taimi hoʻo ʻaʻahi ki ai, ʻoku ʻasi mai fakasinolahi",
+       "wlnote": "ʻOku ʻasi ʻi lalo ʻa e liliu fakamuimui ʻe $1 ʻi he houa fakamuimui ʻe <b>$2</b>.",
        "wlshowlast": "ʻAsi mai houa fakamuimui ʻe $1, ʻaho ʻe $2, $3",
        "watching": "ʻOku leʻo...",
        "unwatching": "ʻOku taʻeleʻo...",
index 347e836..62e90fc 100644 (file)
        "talkpagelinktext": "Toktok",
        "specialpage": "Sipesol pes",
        "personaltools": "Ol pes bilong mi",
-       "postcomment": "Nupela hap bilong pes",
        "talk": "Toktok",
        "views": "Ol lukluk",
        "toolbox": "Sipesol bokis",
index 5b9b74a..0adec18 100644 (file)
@@ -60,7 +60,8 @@
                        "לערי ריינהארט",
                        "아라",
                        "Arystanbek",
-                       "Sayginer"
+                       "Sayginer",
+                       "Sucsuzz"
                ]
        },
        "tog-underline": "Bağlantıların altını çiz:",
        "talkpagelinktext": "Mesaj",
        "specialpage": "Özel sayfa",
        "personaltools": "Kişisel araçlar",
-       "postcomment": "Yeni bölüm",
        "articlepage": "İçerik sayfasını gör",
        "talk": "Tartışma",
        "views": "Görünümler",
        "versionrequiredtext": "Bu sayfayı kullanmak için MediaWiki'nin $1 sürümü gerekmektedir. [[Special:Version|Sürüm sayfasına]] bakınız.",
        "ok": "Tamam",
        "pagetitle-view-mainpage": "{{SITENAME}}",
+       "backlinksubtitle": "←$1",
        "retrievedfrom": "\"$1\" adresinden alındı.",
        "youhavenewmessages": "$1 {{PLURAL:$3|var}} ($2).",
        "youhavenewmessagesfromusers": "{{PLURAL:$3|Başka bir kullanıcıdan|$3 kullanıcıdan}} $1 var ($2).",
        "hidetoc": "gizle",
        "collapsible-collapse": "Daralt",
        "collapsible-expand": "Genişlet",
+       "confirmable-confirm": "Emin misiniz?",
+       "confirmable-yes": "Evet",
+       "confirmable-no": "Hayır",
        "thisisdeleted": "$1 görmek veya geri getirmek istermisiniz?",
        "viewdeleted": "$1 gör?",
        "restorelink": "{{PLURAL:$1|bir silinmiş değişikliği|$1 silinmiş değişikliği}}",
        "externaldberror": "Ya doğrulama veritabanı hatası var ya da kullanıcı hesabınızı güncellemeye yetkiniz yok.",
        "login": "Oturum aç",
        "nav-login-createaccount": "Oturum aç / hesap oluştur",
-       "loginprompt": "{{SITENAME}} sitesinde oturum açabilmek için çerezleri etkinleştirmeniz gerekmektedir.",
        "userlogin": "Oturum aç / hesap oluştur",
        "userloginnocreate": "Giriş yap",
        "logout": "Oturumu kapat",
        "userlogin-resetlink": "Giriş bilgilerinizi mi unuttunuz?",
        "userlogin-resetpassword-link": "Parolanızı mı unuttunuz?",
        "userlogin-helplink2": "Oturum açma konusunda yardım alın",
-       "userlogin-loggedin": "Zaten {{GENDER:$1|$1}} olarak oturum açtınız.\nBaşka bir kullanıcı olarak oturum açmak için aşağıdaki formu kullanın.",
-       "userlogin-createanother": "Başka bir hesap oluşturun",
        "createacct-emailrequired": "E-posta adresi",
        "createacct-emailoptional": "E-posta adresi (isteğe bağlı)",
        "createacct-email-ph": "E-posta adresinizi girin",
        "resetpass-submit-cancel": "İptal",
        "resetpass-wrong-oldpass": "Geçersiz geçici veya güncel şifre.\nŞifrenizi zaten başarıyla değiştirdiniz ya da yeni bir geçici şifre istediniz.",
        "resetpass-recycled": "Lütfen parolanızı eski parolanızdan farklı olarak değiştirin.",
+       "resetpass-temp-emailed": "E-postayla gönderilmiş geçici kodla giriş yaptınız. Oturum açmayı tamamlamak için yeni bir şifre belirlemeniz gerekiyor:",
        "resetpass-temp-password": "Geçici parola:",
        "resetpass-abort-generic": "Parola değişikliği bir uzantı tarafından iptal edildi.",
        "resetpass-expired": "Parolanızın süresi bitti. Lütfen, giriş için yeni bir parola oluşturun.",
        "resetpass-expired-soft": "Parolanızın süresi bitti ve değiştirilmesi gerekiyor. Lütfen, yeni bir parola seçin veya daha sonra oluşturmak için \"{{int:resetpass-submit-cancel}}\" butonuna tıklayın.",
+       "resetpass-validity-soft": "Parolanız geçerli değiş: $1\n\nLütfen yeni bir şifre belirleyin veya daha sonra sıfırlamak için \"{{int:resetpass-submit-cancel}}\" bağlantısını tıklayın.",
        "passwordreset": "Parola sıfırlama",
        "passwordreset-text-one": "Parolanızı sıfırlamak için bu formu doldurun.",
        "passwordreset-text-many": "{{PLURAL:$1|E-posta ile geçici bir parola almak için alanlardan birini doldurun.}}",
        "preview": "Önizleme",
        "showpreview": "Önizlemeyi göster",
        "showdiff": "Değişiklikleri göster",
+       "blankarticle": "<strong>Uyarı:</strong> Oluşturduğunuz sayfa boş.\nEğer \"{{int:savearticle}}\" düğmesine tekrar tıklarsanız, sayfa içerik olmadan oluşturulacaktır.",
        "anoneditwarning": "'''Uyarı:''' Oturum açmadınız.\nIP adresiniz sayfanın değişiklik geçmişine kaydedilecektir.",
        "anonpreviewwarning": "''Giriş yapmadınız. Kaydederseniz, sayfanın değişiklik geçmişine IP adresiniz yazılır.''",
        "missingsummary": "'''Uyarı:''' Herhangi bir özet yazmadın.\nKaydet tuşuna tekrar basarsan sayfa özetsiz kaydedilecek.",
        "edit-conflict": "Değişiklik çakışması.",
        "edit-no-change": "Değişikliğiniz yoksayıldı, çünkü metinde bir değişiklik yapılmadı.",
        "postedit-confirmation-created": "Sayfa oluşturuldu.",
+       "postedit-confirmation-restored": "Sayfa geri yüklendi.",
        "postedit-confirmation-saved": "Değişikliğiniz kaydedildi.",
        "edit-already-exists": "Yeni sayfa oluşturulamıyor.\nSayfa zaten mevcut.",
        "defaultmessagetext": "Varsayılan mesaj metni",
        "parser-template-recursion-depth-warning": "Şablon özyineleme yoğunluğu sınırı aşıldı ($1)",
        "language-converter-depth-warning": "Dil çevirici derinlik sınırı aşıldı ($1)",
        "node-count-exceeded-category": "Düğüm sayısı aşılan sayfalar",
+       "node-count-exceeded-category-desc": "Sayfa azami düğüm sayısını aşıyor.",
        "node-count-exceeded-warning": "Sayfa düğüm sayımı aşıldı",
        "expansion-depth-exceeded-category": "Genişleme derinliği aşılan sayfalar",
+       "expansion-depth-exceeded-category-desc": "Sayfa azami genişleme derinliğini aşıyor.",
        "expansion-depth-exceeded-warning": "Sayfa genişletme derinliği aşıldı",
        "parser-unstrip-loop-warning": "Yineleme döngüsü algılandı",
        "parser-unstrip-recursion-limit": "($1) yineleme sınırı aşıldı",
        "revdelete-no-file": "Belirtilen dosya mevcut değil.",
        "revdelete-show-file-confirm": "\"<nowiki>$1</nowiki>\" dosyasının $2 $3 tarihli silinmiş bir revizyonunu görmek istediğinize emin misiniz?",
        "revdelete-show-file-submit": "Evet",
+       "revdelete-selected-text": "[[:$2]] için {{PLURAL:$1|seçili revizyon|seçili revizyonlar}}:",
+       "revdelete-selected-file": "[[:$2]] için {{PLURAL:$1|seçili dosya revizyonu|seçili dosya revizyonları}}:",
        "logdelete-selected": "{{PLURAL:$1|Seçili kayıt olayı|Seçili kayıt olayları}}:",
+       "revdelete-text-text": "Silinen sürümler sayfa geçmişinde yer almaya devam edecek ancak okuyucular tarafından içeriklerine erişilemeyecektir.",
+       "revdelete-text-file": "Silinen dosya sürümleri dosya geçmişinde yer almaya devam edecek ancak okuyucular tarafından içerik bölümlerine erişilemeyecektir.",
        "revdelete-confirm": "Lütfen, bunu yapmak istediğinizi , sonuçlarını anladığınızı, ve bunu [[{{MediaWiki:Policy-url}}|ilkelere]] göre yapıyor olduğunuzu onaylayın.",
        "revdelete-suppress-text": "Saklama '''sadece''' aşağıdaki durumlarda kullanılmalıdır:\n* Muhtemel iftira niteliğindeki bilgi\n* Uygunsuz kişisel bilgi\n*: ''ev adresleri ve telefon numaraları, sosyal güvenlik numaraları, vs.''",
        "revdelete-legend": "Görünürlük kısıtlamaları ayarla",
        "searchprofile-advanced-tooltip": "Özel ad alanlarında ara",
        "search-result-size": "$1 ({{PLURAL:$2|1 kelime|$2 kelime}})",
        "search-result-category-size": "{{PLURAL:$1|1 üye|$1 üye}} ({{PLURAL:$2|1 altkategori|$2 altkategori}}, {{PLURAL:$3|1 dosya|$3 dosya}})",
-       "search-result-score": "Uygunluk: $1%",
        "search-redirect": "($1 sayfasından yönlendirme)",
        "search-section": "($1 bölümü)",
        "search-file-match": "(dosya içeriğiyle eşleşiyor)",
        "prefs-advancedrendering": "Gelişmiş seçenekler",
        "prefs-advancedsearchoptions": "Gelişmiş seçenekler",
        "prefs-advancedwatchlist": "Gelişmiş seçenekler",
-       "prefs-displayrc": "Görüntü seçenekleri",
+       "prefs-displayrc": "Görüntüleme seçenekleri",
        "prefs-displaywatchlist": "Görüntüleme seçenekleri",
        "prefs-tokenwatchlist": "Anahtar",
        "prefs-diffs": "Farklar",
        "uploadwarning": "Yükleme uyarısı",
        "uploadwarning-text": "Lütfen aşağıdaki dosya açıklamasını değiştirin ve tekrar deneyin.",
        "savefile": "Dosyayı kaydet",
-       "uploadedimage": "Yüklenen: \"[[$1]]\"",
-       "overwroteimage": "\"[[$1]]\" resminin yeni sürümü yüklenmiştir",
        "uploaddisabled": "Geçici olarak şu anda herhangi bir dosya yüklenmez. Biraz sonra bir daha deneyiniz.",
        "copyuploaddisabled": "URL ile yükleme devre dışı.",
        "uploaddisabledtext": "Dosya yüklemeleri devredışı bırakılmıştır.",
        "license-header": "Lisanslama",
        "nolicense": "Hiçbirini seçme",
        "license-nopreview": "(Önizleme etkin değil)",
-       "upload_source_url": " (geçerli, herkesin ulaşabileceği bir URL)",
-       "upload_source_file": " (bilgisayarınızdaki bir dosya)",
+       "upload_source_url": "(geçerli, herkesin ulaşabileceği bir URL'den seçtiğiniz dosya)",
+       "upload_source_file": "(bilgisayarınızdan seçtiğiniz dosya)",
+       "listfiles-delete": "sil",
        "listfiles-summary": "Bu özel sayfa yüklenen tüm dosyaları gösterir.",
        "listfiles_search_for": "Medya adı ara:",
        "imgfile": "dosya",
        "filedelete-maintenance": "Dosyaların silinmesi ve geri getirilmesi bakım süresince geçici olarak devre dışı bırakıldı.",
        "filedelete-maintenance-title": "Dosya silinemiyor",
        "mimesearch": "MIME araması",
-       "mimesearch-summary": "Bu sayfa, MIME türü dosyaların süzülmesini sağlar. Girdi: içeriktürü/alttürü, e.g. <code>resim/jpeg</code>.",
+       "mimesearch-summary": "Bu sayfa, dosyaların MIME türlerine göre filtrelenmesini sağlar. Girdi: içerik_türü/alt_tür veya içerik_türü/*, örn. <code>image/jpeg</code>.",
        "mimetype": "MIME türü:",
        "download": "yükle",
        "unwatchedpages": "İzlenmeyen sayfalar",
        "randomincategory": "Kategoriye göre rastgele sayfa",
        "randomincategory-invalidcategory": "\"$1\" geçerli bir kategori adı değil.",
        "randomincategory-nopages": "[[:Category:$1|$1]] kategorisinde hiç sayfa yok.",
-       "randomincategory-selectcategory": "Rastgele sayfa alınacak kategori: $1 $2.",
-       "randomincategory-selectcategory-submit": "Getir",
+       "randomincategory-category": "Kategori:",
+       "randomincategory-legend": "Kategoriden rastgele sayfa",
        "randomredirect": "Rastgele yönlendirme",
        "randomredirect-nopages": "\"$1\" ad alanında hiç bir yönlendirme yok.",
        "statistics": "İstatistikler",
        "pageswithprop-prophidden-binary": "ikili özellik değeri gizlendi ($1)",
        "doubleredirects": "Çift yönlendirmeler",
        "doubleredirectstext": "Bu sayfa diğer yönlendirme sayfalarına yönlendirme yapan sayfaları listeler.\nHer satırın içerdiği bağlantılar; birinci ve ikinci yönlendirme, ayrıca ikinci yönlendirmenin hedefi, ki bu genelde birinci yönlendirmenin göstermesi gereken \"gerçek\" hedef sayfasıdır.\n<del>Üstü çizili</del> girdiler çözülmüştür.",
-       "double-redirect-fixed-move": "[[$1]] taşındı, artık [[$2]] sayfasına yönlendiriyor",
+       "double-redirect-fixed-move": "[[$1]] taşındı.\nYönlendirme otomatik olarak güncellendi ve [[$2]] sayfasına yönlendirildi.",
        "double-redirect-fixed-maintenance": "[[$1]] - [[$2]] yapılan çift yönlendirme düzeltiliyor.",
        "double-redirect-fixer": "Yönlendirme tamircisi",
        "brokenredirects": "Boş yönlendirmeler",
        "watchlist-details": "Tartışma sayfaları hariç {{PLURAL:$1|$1 sayfa|$1 sayfa}} izleme listenizdedir.",
        "wlheader-enotif": "E-posta bildirimi etkin.",
        "wlheader-showupdated": "Sayfaları son ziyaretinizden beri değişen sayfalar '''kalın''' gösterilmiştir.",
-       "wlnote2": "Aşağıdakiler, son {{PLURAL:$1|bir saat|<strong>$1</strong> saat}} içindeki değişikliklerdir, $2, $3 tarihi itibariyle.",
+       "wlnote": "$3 saat $4 itibariyle son {{PLURAL:$2|bir saatte|'''$2''' saatte}} yapılan {{PLURAL:$1|son değişiklik|son '''$1''' değişiklik}} aşağıdadır.",
        "wlshowlast": "Son $1 saati $2 günü göster $3",
        "watchlist-options": "İzleme listesi seçenekleri",
        "watching": "İzleniyor...",
        "exbeforeblank": "Silinmeden önceki içerik: '$1'",
        "delete-confirm": "\"$1\" sil",
        "delete-legend": "sil",
-       "historywarning": "'''Uyarı:''' Silmek üzere olduğunuz sayfanın yaklaşık olarak $1 {{PLURAL:$1|sürüme|sürüme}} sahip bir geçmişi var:",
+       "historywarning": "<strong>Uyarı:</strong> Silmek üzere olduğunuz sayfanın yaklaşık olarak $1 sürüme sahip bir geçmişi var:",
        "confirmdeletetext": "Bu sayfayı veya dosyayı tüm geçmişi ile birlikte veritabanından kalıcı olarak silmek üzeresiniz.\nBu işlemden kaynaklı doğabilecek sonuçların farkında iseniz ve işlemin [[{{MediaWiki:Policy-url}}|Silme kurallarına]] uygun olduğuna eminseniz, işlemi onaylayın.",
        "actioncomplete": "İşlem tamamlandı",
        "actionfailed": "İşlem başarısız oldu",
        "delete-edit-reasonlist": "Silme nedenlerini değiştir",
        "delete-toobig": "Bu sayfa, $1 {{PLURAL:$1|tane değişiklik|tane değişiklik}} ile çok uzun bir geçmişe sahiptir.\nBöyle sayfaların silinmesi, {{SITENAME}} sitesini bozmamak için sınırlanmaktadır.",
        "delete-warning-toobig": "Bu sayfanın büyük bir değişiklik geçmişi var, $1 {{PLURAL:$1|revizyonun|revizyonun}} üzerinde.\nBunu silmek {{SITENAME}} işlemlerini aksatabilir;\ndikkatle devam edin.",
+       "deleteprotected": "Bu sayfayı silemezsiniz çünkü sayfa korumaya alınmış.",
        "deleting-backlinks-warning": "'''Uyarı:''' Silmek üzere olduğunuz sayfaya [[Özel:SayfayaBağlantılar/{{FULLPAGENAME}}|başka sayfalardan]] bağlantılar var veya sayfanın bazı bölümleri başka sayfalar tarafından alıntı olarak kullanılıyor.",
        "rollback": "değişiklikleri geri al",
        "rollback_short": "geri al",
        "autoblockid": "Otomatik engelleme #$1",
        "block": "Kullanıcıyı engelle",
        "unblock": "Kullanıcının engelini kaldır",
-       "blockip": "Kullanıcıyı engelle",
+       "blockip": "{{GENDER:$1|Kullanıcıyı}} engelle",
        "blockip-legend": "Kullanıcıyı engelle",
        "blockiptext": "Aşağıdaki formu kullanarak belli bir IP'nin veya kayıtlı kullanıcının değişiklik yapmasını engelleyebilirsiniz. Bu sadece vandalizmi engellemek için ve [[{{MediaWiki:Policy-url}}|kurallara]] uygun olarak yapılmalı. Aşağıya mutlaka engelleme ile ilgili bir açıklama yazınız. (örnek: -Şu- sayfalarda vandalizm yapmıştır).",
        "ipaddressorusername": "IP adresi veya kullanıcı adı",
        "ipb-unblock-addr": "$1 için engellemeyi kaldır",
        "ipb-unblock": "Engellemeyi kaldır",
        "ipb-blocklist": "Mevcut olan engellemeleri göster",
-       "ipb-blocklist-contribs": "$1 için katkılar",
+       "ipb-blocklist-contribs": "{{GENDER:$1|$1}} için katkılar",
        "unblockip": "Kullanıcının engellemesini kaldır",
        "unblockiptext": "Daha önceden engellenmiş bir IP adresine ya da kullanıcı adına yazma erişimini geri vermek için aşağıdaki formu kullanın.",
        "ipusubmit": "Bu engellemeyi kaldır",
        "movenotallowedfile": "Sayfaları taşımaya izniniz yok.",
        "cant-move-user-page": "Kullanıcı sayfalarını taşımaya izniniz yok (altsayfalardan başka).",
        "cant-move-to-user-page": "Bir sayfayı, bir kullanıcı sayfasına taşımaya izniniz yok (bir kullanıcı altsayfası dışında).",
+       "cant-move-category-page": "Kategori sayfalarını taşıma yetkiniz yok.",
        "cant-move-to-category-page": "Bir sayfayı, bir kategoriye taşımaya izniniz yok.",
        "newtitle": "Yeni isim",
        "move-watch": "Bu sayfayı izle",
        "import": "Sayfaları aktar",
        "importinterwiki": "Vikilerarası içe aktarım",
        "import-interwiki-text": "İçe aktarmak için bir viki ve sayfa başlığı seçin.\nRevizyon tarihleri ve yazarların isimleri korunacaktır.\nBütün vikilerarası içe aktarım eylemleri [[Special:Log/import|içe aktarım günlüğünde]] kaydedilmektedir.",
-       "import-interwiki-source": "Kaynak viki/sayfa:",
+       "import-interwiki-sourcewiki": "Kaynak viki:",
+       "import-interwiki-sourcepage": "Kaynak sayfa:",
        "import-interwiki-history": "Sayfanın tüm geçmiş sürümlerini kopyala",
        "import-interwiki-templates": "Tüm şablonları içer",
        "import-interwiki-submit": "Import",
        "autosumm-replace": "Sayfa içeriği '$1' ile değiştiriliyor",
        "autoredircomment": "[[$1]] sayfasına yönlendirildi",
        "autosumm-new": "Yeni sayfa: \"$1\"",
+       "autosumm-newblank": "Boş bir sayfa oluşturdu",
        "lag-warn-normal": "$1 {{PLURAL:$1|saniyeden|saniyeden}} yeni değişiklikler bu listede görünmeyebilir.",
        "lag-warn-high": "Veritabanı sunucusundaki aşırı gecikmeden dolayı, $1 {{PLURAL:$1|saniyeden|saniyeden}} yeni değişiklikler bu listede görünmeyebilir.",
        "watchlistedit-normal-title": "İzleme listesini düzenle",
        "watchlistedit-raw-done": "İzleme listeniz güncellendi.",
        "watchlistedit-raw-added": "{{PLURAL:$1|1 başlık|$1 başlık}} eklendi:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1 başlık|$1 başlık}} silindi:",
+       "watchlistedit-clear-title": "İzleme listesi temizlendi",
        "watchlistedit-clear-legend": "İzleme listesini temizle",
        "watchlistedit-clear-explain": "İzleme listenizdeki tüm başlıklar silinecek",
        "watchlistedit-clear-titles": "Başlıklar:",
        "watchlistedit-clear-submit": "İzleme listesini temizle (Geri alınamaz!)",
        "watchlistedit-clear-done": "İzleme listeniz temizlendi.",
        "watchlistedit-clear-removed": "{{PLURAL:$1|1 başlık|$1 başlık}} silindi:",
+       "watchlistedit-too-many": "Görüntülemek için çok fazla sayfa var.",
        "watchlisttools-clear": "İzleme listesini temizle",
        "watchlisttools-view": "İlgili değişiklikleri göster",
        "watchlisttools-edit": "İzleme listesini gör ve düzenle",
        "duplicate-defaultsort": "'''Uyarı:''' Varsayılan \"$2\" sınıflandırma anahtarı, önceki \"$1\" sınıflandırma anahtarını geçersiz kılıyor.",
        "version": "Sürüm",
        "version-extensions": "Yüklü ekler",
-       "version-skins": "Görünümler",
+       "version-skins": "Yüklü görünümler",
        "version-specialpages": "Özel sayfalar",
        "version-parserhooks": "Derleyici çengelleri",
        "version-variables": "Değişkenler",
        "version-hook-name": "Çengel adı",
        "version-hook-subscribedby": "Abone olan",
        "version-version": "($1 sürümü)",
+       "version-no-ext-name": "[isim yok]",
        "version-license": "MediaWiki Lisansı",
        "version-ext-license": "Lisans",
        "version-ext-colheader-name": "Uzantı",
+       "version-skin-colheader-name": "Görünüm",
        "version-ext-colheader-version": "Sürüm",
        "version-ext-colheader-license": "Lisans",
        "version-ext-colheader-description": "Açıklama",
        "htmlform-no": "Hayır",
        "htmlform-yes": "Evet",
        "htmlform-chosen-placeholder": "Bir seçenek seçin",
+       "htmlform-cloner-create": "Daha fazla ekle",
        "htmlform-cloner-delete": "Sil",
        "htmlform-cloner-required": "En az bir değer gereklidir.",
        "sqlite-has-fts": "$1 tam-metin arama desteği ile",
        "logentry-rights-rights": "$1, $3 için grup üyeliğini $4 iken $5 olarak {{GENDER:$2|değiştirdi}}",
        "logentry-rights-rights-legacy": "$1, $3 için grup üyeliğini {{GENDER:$2|değiştirdi}}",
        "logentry-rights-autopromote": "$1, $4 iken $5 olarak otomatik {{GENDER:$2|terfi edildi}}",
+       "logentry-upload-upload": "$1 {{GENDER:$2|yükledi}} $3",
+       "logentry-upload-overwrite": "$1 $3 dosyasının yeni bir sürümünü {{GENDER:$2|yükledi}}",
        "rightsnone": "(hiçbiri)",
        "feedback-bugornote": "Eğer teknik bir problemi detaylarıyla açıklamaya hazırsanız lütfen [$1 bir hata raporlayın]. Diğer taraftan, aşağıdaki kolay formu kullanabilirsiniz. Yorumunuz, kullanıcı adınızla beraber \"[$3 $2]\" sayfasına eklenecektir.",
        "feedback-subject": "Konu:",
        "expand_templates_remove_nowiki": "Sonuçlarda <nowiki> etiketlerini bastır",
        "expand_templates_generate_xml": "XML derleyici ağacını göster",
        "expand_templates_generate_rawhtml": "Ham HTML göster",
-       "expand_templates_preview": "Önizleme"
+       "expand_templates_preview": "Önizleme",
+       "pagelanguage": "Sayfa dili seçicisi",
+       "pagelang-name": "Sayfa",
+       "pagelang-language": "Dil",
+       "pagelang-use-default": "Varsayılan dili kullan",
+       "pagelang-select-lang": "Dil seçin",
+       "right-pagelang": "Sayfa dilini değiştir",
+       "action-pagelang": "sayfa dilini değiştir"
 }
index 77efb97..fbb3d9b 100644 (file)
        "talkpagelinktext": "Mamlo",
        "specialpage": "Faṭo dilonoyto",
        "personaltools": "aMonayḍi",
-       "postcomment": "Fusoqo ḥaṭo",
        "articlepage": "Ḥur baḤbişoṭo",
        "talk": "Droşo",
        "views": "Ḥzayoṭo",
        "remembermypassword": "Dxar uQliḍayḍi buBrowser (buSowudo $1 {{PLURAL:$1|Yawmo|Yawme}})",
        "login": "3bar",
        "nav-login-createaccount": "3bar / Hway Hadomo",
-       "loginprompt": "Glozım maqablat Cookies qanna dqudrat fıtḥat {{SITENAME}}.",
        "userlogin": "3bar / Hway Hadomo",
        "userloginnocreate": "3bar",
        "logout": "Nfoqo",
        "upload": "Mosaq Fayl",
        "uploadlogpage": "Upload log",
        "filedesc": "Sfiquṭo",
-       "uploadedimage": "mosaq \"[[$1]]\"",
        "license": "Fsoso",
        "license-header": "Fsoso",
        "file-anchor-link": "Fayl",
index 1833d18..91da0bb 100644 (file)
        "talkpagelinktext": "Mbulavulo",
        "specialpage": "Tluka ro hlawuleka",
        "personaltools": "Switirhisi swa n'wini",
-       "postcomment": "Xiyenge xintswa",
        "articlepage": "Langutisa tluka ra matsalwa",
        "talk": "Mbulavuriswano",
        "views": "Kulanguteka",
        "remembermypassword": "Tsundzuka ku nghena eka Khompuyuta leyi (kufikela eka $1 {{PLURAL:$1|siku|masiku}})",
        "login": "Pfula u nghena",
        "nav-login-createaccount": "Pfula unghena / Tumbuluxa akhawunti",
-       "loginprompt": "U fanele ku pfumelela swipfuneti leswaku u pfula unghena eka {{SITENAME}}.",
        "userlogin": "Pfula unghena / Tumbuluxa akhawunti",
        "userloginnocreate": "Pfula unghena",
        "logout": "Pfala u famba",
        "upload": "Khandziyisa fayili",
        "uploadlogpage": "Ngula ya nxaxamelo wa swilo leswi hoxiweke",
        "filedesc": "Nkomiso",
-       "uploadedimage": "kuhoxiwe fayili ya \"[[$1]]\"",
        "license": "Nawu wo pfumelela",
        "license-header": "Nawu wo pfumelela",
        "imgfile": "fayili",
index 8cc9001..935ac49 100644 (file)
@@ -20,7 +20,8 @@
                        "Ильнар",
                        "Рашат Якупов",
                        "Умар",
-                       "아라"
+                       "아라",
+                       "Derslek"
                ]
        },
        "tog-underline": "Сылтамаларның астына сызу:",
        "print": "Бастыру",
        "view": "Карау",
        "edit": "Үзгәртү",
+       "edit-local": "Локаль тасвирламаны үзгәртергә",
        "create": "Төзү",
+       "create-local": "Локаль тасвирлама өстәргә",
        "editthispage": "Бу битне үзгәртү",
        "create-this-page": "Бу битне төзү",
        "delete": "Бетерү",
        "deletethispage": "Бу битне бетерү",
        "undeletethispage": "Бу битне кайтарырга",
-       "undelete_short": "$1 {{PLURAL:$1|үзгәртмәне}} торгызу",
-       "viewdeleted_short": "{{PLURAL:$1|1=1 бетерелгән үзгәртүне|$1 бетерелгән үзгәртүне}} карау",
+       "undelete_short": "$1 {{PLURAL:$1|төзәтмәне|$1 төзәтмә}} торгызу",
+       "viewdeleted_short": "{{PLURAL:$1|1=1 бетерелгән үзгәртүне|$1 бетерелгән үзгәртүне}} карау\n{{PLURAL:$1|бетерелгән төзәтмәне|$1 бетерелгән төзәтмәне}} карау",
        "protect": "Яклау",
        "protect_change": "үзгәртү",
        "protectthispage": "Бу битне яклау",
        "talkpagelinktext": "Бәхәс",
        "specialpage": "Махсус бит",
        "personaltools": "Шәхси кораллар",
-       "postcomment": "Яңа бүлек",
        "articlepage": "Мәкаләне карау",
        "talk": "Бәхәс",
        "views": "Караулар",
        "otherlanguages": "Башка телләрдә",
        "redirectedfrom": "($1 битеннән юнәлтелде)",
        "redirectpagesub": "Башка биткә юнәлтү бите",
+       "redirectto": "Шунда юнәлтелә:",
        "lastmodifiedat": "Бу битне соңгы үзгәртү: $2, $1.",
-       "viewcount": "Бу биткә $1 {{PLURAL:$1|тапкыр}} мөрәҗәгать иттеләр.",
+       "viewcount": "Бу биткә $1 {{PLURAL:$1|бер тапкыр|$1 тапкыр}} мөрәҗәгать иттеләр.",
        "protectedpage": "Якланган бит",
        "jumpto": "Моңа күчү:",
        "jumptonavigation": "навигация",
        "externaldberror": "Тышкы мәгълүмат базасы ярдәмендә аутентификация үткәндә хата чыкты, яисә тышкы хисап язмагызга үзгәрешләр кертү хокукыгыз юк.",
        "login": "Керү",
        "nav-login-createaccount": "Керү / теркәлү",
-       "loginprompt": "{{SITENAME}} проектына керү өчен «cookies» рөхсәт ителгән булырга тиеш.",
        "userlogin": "Керү / теркәлү",
        "userloginnocreate": "Керү",
        "logout": "Чыгу",
        "searchprofile-advanced-tooltip": "Бирелгән исемнәр мәйданында эзләү",
        "search-result-size": "$1 ({{PLURAL:$2|$2 сүз}})",
        "search-result-category-size": "{{PLURAL:$1|1=1 әгъза|$1 әгъза}} ({{PLURAL:$2|1=1 асттөркем|$2 асттөркем}}, {{PLURAL:$3|1=1 файл|$3 файл}})",
-       "search-result-score": "Релевантлыгы: $1 %",
        "search-redirect": "(юнәлтү $1)",
        "search-section": "($1 бүлеге)",
        "search-suggest": "Бәлки, сез моны эзлисез: $1",
        "searchrelated": "бәйләнгән",
        "searchall": "барлык",
        "showingresults": "Аста № '''$2''' {{PLURAL:$1|башлап}} '''$1''' {{PLURAL:$1|результат}} күрсәтелгән.",
-       "showingresultsheader": "'''$4''' өчен {{PLURAL:$5|1=Результат '''$1''' сеннән '''$3'''|Результатлар '''$1 — $2''' сеннән  '''$3'''}}",
        "search-nonefound": "Сорауга туры килгән җаваплар табылмады.",
        "powersearch-legend": "Өстәмә эзләү",
        "powersearch-ns": "исемнәрендә эзләү",
        "verification-error": "Бу файл әлегә тикшерү узмаган.",
        "illegal-filename": "Мондый файл исеменә рөхсәт юк",
        "savefile": "Файлны саклау",
-       "uploadedimage": "«[[$1]]» йөкләнгән",
-       "overwroteimage": "«[[$1]]» файлының яңа юрамасы йөкләнелде",
        "uploaddisabled": "Йөкләү тыелган",
        "copyuploaddisabled": "URL адресы буенча йөкләү ябылган.",
        "uploaddisabledtext": "Файлларны йөкләү ябылган.",
        "import": "Битләр кертү",
        "importinterwiki": "Викиара кертү",
        "import-interwiki-text": "Викины һәм кертелүче битнең исемен языгыз.\nҮзгәртүләр вакыты һәм аның авторлары сакланачак.\nБөтен викиара күчерүләр [[Special:Log/import|махсус журналда]] сакланачак.",
-       "import-interwiki-source": "Вики-чыганак/бит:",
        "import-interwiki-history": "Бу битнең барлык үзгәртү тарихын күчермәләү",
        "import-interwiki-templates": "Барлык үрнәкләрне кертү",
        "import-interwiki-submit": "Импортлау",
        "newimages": "Яңа сүрәтләр җыелмасы",
        "newimages-legend": "Фильтр",
        "ilsubmit": "Эзләү",
+       "hours": "{{PLURAL:$1|$1 cәгать|$1 cәгать}}",
+       "hours-ago": "$1 cәгать элек",
+       "minutes-ago": "$1 минут элек",
        "bad_image_list": "Киләчәк рәвеш кирәк:\n\nИсемлек кисәкләре генә (* символыннан башланучы юллар) саналырлар.\nЮлның беренче сылтамасы куйма өчен тыелган рәсемгә сылтама булырга тиеш.\nШул ук юлның киләчәк сылтамалары чыгармалар, рәсемгә тыелмаган битләре, саналырлар.",
        "metadata": "Мета мәгълүматлар",
        "metadata-help": "Бу файлда гадәттә санлы камера яки сканер тарафыннан өстәлгән мәгълүмат бар. Әгәр бу файл төзү вакытыннан соң үзгәртелгән булса, аның кайбер параметрлары дөрес булмаска мөмкин.",
index 95cb788..a7f86ed 100644 (file)
        "talkpagelinktext": "Bäxäs",
        "specialpage": "Maxsus bit",
        "personaltools": "Şäxsi qorallar",
-       "postcomment": "Yaña bülek",
        "articlepage": "Mäqäläne qaraw",
        "talk": "Bäxäs",
        "views": "Qarawlar",
        "externaldberror": "Tışqı mäğlümat bazası yärdämendä awtentifikatsiä ütkändä xata çıqtı, yäisä tışqı xisap yazmağızğa üzgäreşlär kertü xoquqığız yuq.",
        "login": "Kerü",
        "nav-login-createaccount": "Kerü / terkälü",
-       "loginprompt": "{{SITENAME}} proyektına kerü öçen «cookies» röxsät itelgän bulırğa tieş.",
        "userlogin": "Kerü / terkälü",
        "userloginnocreate": "Kerü",
        "logout": "Çığu",
        "searchprofile-everything-tooltip": "Barlıq bitlärdä dä ezläw",
        "searchprofile-advanced-tooltip": "Birelgän isemnär mäydanında ezläw",
        "search-result-size": "$1 ({{PLURAL:$2|$2 süz}})",
-       "search-result-score": "Relevantlığı: $1 %",
        "search-redirect": "(yünältü $1)",
        "search-section": "($1 bülege)",
        "search-suggest": "Bälki, sez monı ezlisez: $1",
        "verification-error": "Bu fayl älegä tikşerü uzmağan.",
        "uploadwarning": "Yökläw kisätmäse",
        "savefile": "Faylnı saqlaw",
-       "uploadedimage": "«[[$1]]» yöklängän",
-       "overwroteimage": "«[[$1]]» faylınıñ yaña yuraması yöklänelde",
        "uploaddisabled": "Yökläw tıyılğan",
        "copyuploaddisabled": "URL adresı buyınça yökläw yabılğan.",
        "uploaddisabledtext": "Fayllarnı yökläw yabılğan.",
index 6d2d010..73e2466 100644 (file)
        "talkpagelinktext": "Чугаа",
        "specialpage": "Тускай арын",
        "personaltools": "Хууда херекселдер",
-       "postcomment": "Чаа салбыр",
        "articlepage": "Допчу арынны көөрү",
        "talk": "Чугаа",
        "views": "Көрүүшкүннери",
        "remembermypassword": "Мени бо компьютерде сактып алыры ($1 {{PLURAL:$1|1=хүн|хүн}}ге чедир)",
        "login": "Кирери",
        "nav-login-createaccount": "Кирери / бүрүткел бижикти чогаадыры",
-       "loginprompt": "{{SITENAME}} сайтче кирерде, баштай «cookies»-ти чөшпээрээр ужурлуг Силер.",
        "userlogin": "Кирери / бүрүткел бижикти чогаадыры",
        "userloginnocreate": "Кирери",
        "logout": "Үнери",
        "accountcreatedtext": "«$1» деп ажыглакчының бүрүткел бижиини бүдүрген.",
        "login-abort-generic": "Системаже таптыг эвес кирип тур силер",
        "loginlanguagelabel": "Дыл: $1",
+       "pt-userlogout": "Үнер",
        "php-mail-error-unknown": "PHP-ниң mail() ажыл-чорудулгазында билбес алдаг бар.",
        "changepassword": "Чажыт сөстү өскертири",
        "resetpass_text": "<!-- Маңаа сөзүглелди немерелээри -->",
        "search-interwiki-more": "(артык)",
        "searchrelated": "холбаалыг",
        "searchall": "шупту",
-       "showingresultsheader": "«'''$4'''» дилээниниң {{PLURAL:$5|1='''$3''' одуругдан '''$1''' түңнели|'''$3''' одуругдан '''$1—$2''' түңнелдери}}",
        "search-nonefound": "Айыткан негелдениң түңнели чок",
        "powersearch-ns": "Аттар делгемнеринден дилээри:",
        "powersearch-toggleall": "Шупту",
        "fileuploadsummary": "Түңнел:",
        "filesource": "Эгези:",
        "savefile": "Файлды шыгжаары",
-       "uploadedimage": "«[[$1]]» деп файлды салган.",
        "upload-maxfilesize": "Файлдың эң улуг хемчээли: $1",
        "watchthisupload": "Бо арынны хайгаараары",
        "upload-file-error": "Иштики алдаг",
index bc5be58..843ceff 100644 (file)
        "talkpagelinktext": "ⴰⵎⵢⴰⵏⵏⴰⵏ",
        "specialpage": "ⵜⴰⵙⵏⴰ ⵉⵥⵍⵉⵏ",
        "personaltools": "ⵉⵎⴰⵙⵙⵏ ⵉⵏⵡ",
-       "postcomment": "ⵜⴰⴷⴰⵍⴰ ⵜⴰⵎⴰⵢⵏⵓⵜ",
        "talk": "ⴰⵎⵢⴰⵏⵏⴰⵏ",
        "views": "ⵥⵕ",
        "toolbox": "ⵉⵎⴰⵙⵙⵏ",
index bfa01d5..a4f87fa 100644 (file)
        "talkpagelinktext": "مۇنازىرە",
        "specialpage": "ئالاھىدە بەت",
        "personaltools": "شەخسىي قوراللار",
-       "postcomment": "يېڭى ئابزاس",
        "articlepage": "مەزمۇن بېتىنى كۆرسەت",
        "talk": "مۇنازىرە",
        "views": "كۆرۈنۈش",
        "externaldberror": "بۇ سانداننى دەلىللەش خاتالىقى ياكى سىرتقى ھېساباتىڭىزنى يېڭىلاشنى چەكلىگەنلىكتىن بولغان بولۇشى مۇمكىن.",
        "login": "تىزىمغا كىر",
        "nav-login-createaccount": "تىزىمغا كىر/ھېسابات قۇر",
-       "loginprompt": "سىز cookies نى قوزغاتقاندىلا ئاندىن   {{SITENAME}} غا كىرەلەيسىز.",
        "userlogin": "تىزىمغا كىر/ھېسابات قۇر",
        "userloginnocreate": "تىزىمغا كىر",
        "logout": "تىزىمدىن چىق",
        "searchprofile-advanced-tooltip": "ئادەتلەنگەن ئات بوشلۇقىدىن ئىزدە",
        "search-result-size": "$1 ({{PLURAL:$2|1 سۆز|$2 سۆز}})",
        "search-result-category-size": "{{PLURAL:$1|1 ئەزا|$1 ئەزا}}({{PLURAL:$2|1 تارماق تۈر|$2 تارماق تۈر}}, {{PLURAL:$3|1 ھۆججەت|$3 ھۆججەت}})",
-       "search-result-score": "باغلىنىشچانلىق: $1%",
        "search-redirect": "($1 قايتا نىشانلا)",
        "search-section": "(ئابزاس $1)",
        "search-file-match": "(ھۆججەت مەزمۇنى ماس كەلگەن)",
        "uploadwarning": "يۈكلەش ئاگاھلاندۇرۇشى",
        "uploadwarning-text": "تۆۋەندىكى ھۆججەت چۈشەندۈرۈشىنى ئۆزگەرتىپ ئاندىن قايتا سىناڭ.",
        "savefile": "ھۆججەت ساقلا",
-       "uploadedimage": "\"[[$1]]\" يۈكلەنگەن",
-       "overwroteimage": " \"[[$1]]\" نىڭ يېڭى نەشرى يۈكلەندى",
        "uploaddisabled": "يۈكلەش چەكلەنگەن",
        "copyuploaddisabled": "URL ئارقىلىق يۈكلەش ئىقتىدارى چەكلەنگەن.",
        "uploaddisabledtext": "ھۆججەت يۈكلەش چەكلەنگەن.",
        "watchlist-details": "كۆزەت تىزىملىكىڭىزدە {{PLURAL:$1|$1 بەت|$1 بەت}}  بار، مۇنازىرە بېتىنى ئۆز ئىچىگە ئالمايدۇ.",
        "wlheader-enotif": "ئېلخەتتە ئەسكەرتىش ئىقتىدارى قوزغىتىلدى.",
        "wlheader-showupdated": "سىز ئالدىنقى قېتىم كۆرگەندىن كېيىن ئۆزگەرتىلگەن بەتلەر '''توم''' كۆرۈنىدۇ",
+       "wlnote": "تۆۋەندىكىسى يېقىنقى {{PLURAL:$2|سائەت}} ئىچىدىكى ئاخىرقى '{{PLURAL:$1| قېتىملىق}}  ئۆزگەرتىش، $3 $4 گىچە.",
        "wlshowlast": "يېقىنقى $1 سائەت $2 كۈن $3 نىڭ ئۆزگەرتىشىنى كۆرسەت",
        "watchlist-options": "كۆزەت تىزىملىك تاللانما",
        "watching": "كۆزەت قىلىۋاتىدۇ…",
        "duplicate-defaultsort": "'''ئاگاھلاندۇرۇش:''' كۆڭۈلدىكى تەرتىپلەش كۇنۇپكىسى \"$2\" ئىلگىرىكى كۆڭۈلدىكى تەرتىپلەش كۇنۇپكىسى \"$1\" نى قاپلىۋېتىدۇ.",
        "version": "نەشرى",
        "version-extensions": "قاچىلانغان كېڭەيتىلمە",
+       "version-skins": "تېرەلەر",
        "version-specialpages": "ئالاھىدە بەتلەر",
        "version-parserhooks": "تەھلىلچى ئىلمىكى",
        "version-variables": "ئۆزگەرگۈچى مىقدار",
        "version-antispam": "ئەخلەتتىن ساقلىنىش",
-       "version-skins": "تېرەلەر",
        "version-other": "باشقا",
        "version-mediahandlers": "ۋاسىتە بىر تەرەپ قىلغۇچ",
        "version-hooks": "ئىلمەك",
index 95d9f26..bfd5b05 100644 (file)
                        "Максим Підліснюк",
                        "Тест",
                        "아라",
-                       "Calak"
+                       "Calak",
+                       "Mykola Swarnyk",
+                       "Milicevic01",
+                       "Lamsec"
                ]
        },
        "tog-underline": "Підкреслювання посилань:",
        "tog-hideminor": "Приховати незначні редагування у списку останніх змін",
        "tog-hidepatrolled": "Приховувати патрульовані редагування у списку нових редагувань",
        "tog-newpageshidepatrolled": "Приховувати патрульовані сторінки у списку нових сторінок",
-       "tog-extendwatchlist": "Розширений список спостереження, що містить усі зміни, а не лише останню",
-       "tog-usenewrc": "Ð\9dа Ñ\81Ñ\82оÑ\80Ñ\96нкаÑ\85 Ð¾Ñ\81Ñ\82аннÑ\96Ñ\85 Ð·Ð¼Ñ\96ни Ñ\82а Ñ\81пиÑ\81кÑ\83 Ñ\81Ñ\82оÑ\81Ñ\82еÑ\80еженнÑ\8f Ð³Ñ\80Ñ\83пÑ\83ваÑ\82и Ñ\80едагÑ\83вання",
+       "tog-extendwatchlist": "Розгорнути список спостереження, щоб показати всі зміни, а не лише останні",
+       "tog-usenewrc": "Ð\93Ñ\80Ñ\83пÑ\83ваÑ\82и Ñ\80едагÑ\83ваннÑ\8f Ð½Ð° Ñ\81Ñ\82оÑ\80Ñ\96нкаÑ\85 Ð¾Ñ\81Ñ\82аннÑ\96Ñ\85 Ð·Ð¼Ñ\96н Ñ\82а Ñ\81пиÑ\81кÑ\83 Ñ\81поÑ\81Ñ\82еÑ\80еження",
        "tog-numberheadings": "Автоматично нумерувати заголовки",
        "tog-showtoolbar": "Показувати панель інструментів",
-       "tog-editondblclick": "РедагÑ\83ваÑ\82и Ñ\81Ñ\82оÑ\80Ñ\96нки Ð¿Ñ\80и Ð¿Ð¾Ð´Ð²Ñ\96йномÑ\83 ÐºÐ»Ð°Ñ\86аннÑ\96 Ð¼Ð¸Ñ\88коÑ\8e",
-       "tog-editsectiononrightclick": "РедагÑ\83ваÑ\82и Ñ\80оздÑ\96ли Ð¿Ñ\80и ÐºÐ»Ð°Ñ\86аннÑ\96 Ð¿Ñ\80авоÑ\8e ÐºÐ½Ð¾Ð¿ÐºÐ¾Ñ\8e Ð¼Ð¸Ñ\88ки Ð½Ð° Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²Ðºу",
+       "tog-editondblclick": "Ð\9fеÑ\80ейÑ\82и Ð² Ñ\80ежим Ñ\80едагÑ\83ваннÑ\8f Ñ\81Ñ\82оÑ\80Ñ\96нки Ð¿Ð¾Ð´Ð²Ñ\96йним ÐºÐ»Ð°Ñ\86аннÑ\8fм Ð¼Ð¸Ñ\88ки",
+       "tog-editsectiononrightclick": "Ð\9fеÑ\80ейÑ\82и Ð² Ñ\80ежим Ñ\80едагÑ\83ваннÑ\8f Ñ\80оздÑ\96лÑ\83 ÐºÐ»Ð°Ñ\86аннÑ\8fм Ð¿Ñ\80авоÑ\8e ÐºÐ½Ð¾Ð¿ÐºÐ¾Ñ\8e Ð¼Ð¸Ñ\88ки Ð½Ð° Ð½Ð°Ð·Ð²Ñ\83 Ñ\80оздÑ\96лу",
        "tog-watchcreations": "Додавати створені мною сторінки і завантажені мною файли до мого списку спостереження",
        "tog-watchdefault": "Додавати змінені мною сторінки та файли до мого списку спостереження",
        "tog-watchmoves": "Додавати перейменовані мною сторінки та файли до мого списку спостереження",
        "tog-watchdeletion": "Додавати вилучені мною сторінки та файли до мого списку спостереження",
+       "tog-watchrollback": "Додавати відкочені мною сторінки до мого списку спостереження",
        "tog-minordefault": "Спочатку позначати всі зміни незначними",
        "tog-previewontop": "Показувати попередній перегляд перед вікном редагування, а не після",
        "tog-previewonfirst": "Показувати попередній перегляд під час першого редагування",
        "tog-enotifwatchlistpages": "Повідомляти електронною поштою про зміну сторінки або файлу з мого списку спостереження",
-       "tog-enotifusertalkpages": "Повідомляти електронною поштою про зміну моєї сторінки обговорення",
+       "tog-enotifusertalkpages": "Повідомляти електронною поштою про зміни на моїй сторінці обговорення",
        "tog-enotifminoredits": "Надсилати мені електронного листа навіть при незначних редагуваннях сторінок та файлів",
        "tog-enotifrevealaddr": "Показувати мою поштову адресу в повідомленнях",
        "tog-shownumberswatching": "Показувати число користувачів, які додали сторінку до свого списку спостереження",
        "tog-oldsig": "Існуючий підпис:",
-       "tog-fancysig": "Ð\92лаÑ\81на Ð²Ñ\96кÑ\96\80озмÑ\96Ñ\82ка Ð¿Ñ\96дпиÑ\81Ñ\83 (без автоматичного посилання)",
+       "tog-fancysig": "СпÑ\80иймаÑ\82и Ð¿Ñ\96дпиÑ\81 Ñ\8fк Ð²Ñ\96кÑ\96\82екÑ\81Ñ\82 (без автоматичного посилання)",
        "tog-uselivepreview": "Використовувати швидкий попередній перегляд (експериментально)",
        "tog-forceeditsummary": "Попереджати, коли не зазначений короткий опис редагування",
        "tog-watchlisthideown": "Приховати мої редагування у списку спостереження",
@@ -81,7 +85,7 @@
        "tog-watchlisthideminor": "Приховати незначні редагування у списку спостереження",
        "tog-watchlisthideliu": "Приховати редагування зареєстрованих дописувачів у списку спостереження",
        "tog-watchlisthideanons": "Приховати редагування анонімних користувачів у списку спостереження",
-       "tog-watchlisthidepatrolled": "Приховувати патрульовані редагування у списку спостереження",
+       "tog-watchlisthidepatrolled": "Приховати відпатрульовані правки у списку спостереження",
        "tog-ccmeonemails": "Надсилати мені копії листів, які я надсилаю іншим користувачам",
        "tog-diffonly": "Не показувати вміст сторінки під різницею версій",
        "tog-showhiddencats": "Показувати приховані категорії",
        "november-date": "$1 листопада",
        "december-date": "$1 грудня",
        "pagecategories": "{{PLURAL:$1|1=Категорія|Категорії|Категорій}}",
-       "category_header": "СÑ\82оÑ\80Ñ\96нки Ð² категорії «$1»",
+       "category_header": "СÑ\82оÑ\80Ñ\96нок Ñ\83 категорії «$1»",
        "subcategories": "Підкатегорії",
        "category-media-header": "Файли в категорії «$1»",
        "category-empty": "''Ця категорія зараз порожня.''",
        "deletethispage": "Вилучити цю сторінку",
        "undeletethispage": "Відновити цю сторінку",
        "undelete_short": "Відновити $1 {{PLURAL:$1|редагування|редагування|редагувань}}",
-       "viewdeleted_short": "Переглянути {{PLURAL:$1|одне вилучене редагування|$1 вилучених редагування|$1 вилучених редагувань}}",
+       "viewdeleted_short": "Переглянути {{PLURAL:$1|одне вилучене редагування|$1 вилучені редагування|$1 вилучених редагувань}}",
        "protect": "Захистити",
        "protect_change": "змінити",
        "protectthispage": "Захистити цю сторінку",
-       "unprotect": "Ð\97мÑ\96на Ð·Ð°Ñ\85иÑ\81Ñ\82Ñ\83",
-       "unprotectthispage": "Ð\97мÑ\96на Ð·Ð°Ñ\85иÑ\81Ñ\82Ñ\83 цієї сторінки",
+       "unprotect": "Ð\97мÑ\96ниÑ\82и Ð·Ð°Ñ\85иÑ\81Ñ\82",
+       "unprotectthispage": "Ð\97мÑ\96ниÑ\82и Ð·Ð°Ñ\85иÑ\81Ñ\82 цієї сторінки",
        "newpage": "Нова сторінка",
        "talkpage": "Обговорити цю сторінку",
        "talkpagelinktext": "обговорення",
        "specialpage": "Спеціальна сторінка",
        "personaltools": "Особисті інструменти",
-       "postcomment": "Новий розділ",
        "articlepage": "Переглянути статтю",
        "talk": "Обговорення",
        "views": "Перегляди",
        "otherlanguages": "Іншими мовами",
        "redirectedfrom": "(Перенаправлено з $1)",
        "redirectpagesub": "Сторінка-перенаправлення",
-       "lastmodifiedat": "Ð\9eÑ\81Ñ\82аннÑ\8f Ð·Ð¼Ñ\96на Ñ\86Ñ\96Ñ\94Ñ\97 Ñ\81Ñ\82оÑ\80Ñ\96нки: $2, $1.",
+       "lastmodifiedat": "ЦÑ\8e Ñ\81Ñ\82оÑ\80Ñ\96нкÑ\83 Ð²Ð¾Ñ\81Ñ\82аннÑ\94 Ð·Ð¼Ñ\96нено: $2, $1.",
        "viewcount": "Цю сторінку переглядали $1 {{PLURAL:$1|раз|рази|разів}}.",
        "protectedpage": "Захищена сторінка",
        "jumpto": "Перейти до:",
        "privacypage": "Project:Політика конфіденційності",
        "badaccess": "Помилка доступу",
        "badaccess-group0": "Вам не дозволено виконувати цю дію.",
-       "badaccess-groups": "Ð\94Ñ\96Ñ\8f, Ñ\8fкÑ\83 Ð\92и хотіли зробити, дозволена лише користувачам із {{PLURAL:$2|1=групи|груп}}: $1.",
+       "badaccess-groups": "Ð\94Ñ\96Ñ\8f, Ñ\8fкÑ\83 Ð²и хотіли зробити, дозволена лише користувачам із {{PLURAL:$2|1=групи|груп}}: $1.",
        "versionrequired": "Потрібна MediaWiki версії $1",
        "versionrequiredtext": "Для роботи з цією сторінкою потрібна MediaWiki версії $1. Див. [[Special:Version|інформацію про версії програмного забезпечення, яке використовується]].",
        "ok": "Гаразд",
        "hidetoc": "сховати",
        "collapsible-collapse": "згорнути",
        "collapsible-expand": "розгорнути",
+       "confirmable-confirm": "{{GENDER:$1|Ви}} впевнені?",
+       "confirmable-yes": "Так",
+       "confirmable-no": "Ні",
        "thisisdeleted": "Переглянути чи відновити $1?",
        "viewdeleted": "Переглянути $1?",
-       "restorelink": "$1 {{PLURAL:$1|вилучене редагування|вилучених редагування|вилучених редагувань}}",
+       "restorelink": "$1 {{PLURAL:$1|вилучене редагування|вилучені редагування|вилучених редагувань}}",
        "feedlinks": "У вигляді:",
        "feed-invalid": "Неправильний тип каналу для підписки.",
        "feed-unavailable": "Стрічки синдикації не доступні",
        "page-atom-feed": "«$1» — Atom-стрічка",
        "feed-atom": "Atom",
        "feed-rss": "RSS",
-       "red-link-title": "$1 (Ñ\82ака Ñ\81Ñ\82оÑ\80Ñ\96нка не існує)",
-       "sort-descending": "Ð\92Ñ\96дÑ\81ортувати за спаданням",
-       "sort-ascending": "Ð\92Ñ\96дÑ\81ортувати за зростанням",
+       "red-link-title": "$1 (Ñ\82акоÑ\97 Ñ\81Ñ\82оÑ\80Ñ\96нки не існує)",
+       "sort-descending": "Сортувати за спаданням",
+       "sort-ascending": "Сортувати за зростанням",
        "nstab-main": "Стаття",
        "nstab-user": "Сторінка користувача",
        "nstab-media": "Медіа-сторінка",
        "nstab-help": "Сторінка довідки",
        "nstab-category": "Категорія",
        "nosuchaction": "Такої дії нема",
-       "nosuchactiontext": "Ð\94Ñ\96Ñ\8f, Ð·Ð°Ð·Ð½Ð°Ñ\87ена Ð² URL, Ð½ÐµÐ¿Ñ\80авилÑ\8cна.\nÐ\92и Ð¼Ð¾Ð³Ð»Ð¸ Ð½ÐµÐ¿Ñ\80авилÑ\8cно Ð½Ð°Ð±Ñ\80аÑ\82и URL Ð°Ð±Ð¾ Ð¿ÐµÑ\80ейÑ\82и Ð¿Ð¾ Ð½ÐµÐºÐ¾Ñ\80екÑ\82номÑ\83 Ð¿Ð¾Ñ\81иланнÑ\8e.\nЦе також може означати помилку в програмному забезпеченні {{GRAMMAR:genitive|{{SITENAME}}}}.",
+       "nosuchactiontext": "Ð\94Ñ\96Ñ\8f, Ð·Ð°Ð·Ð½Ð°Ñ\87ена Ð² URL, Ð½ÐµÐ¿Ñ\80авилÑ\8cна.\nÐ\92и Ð¼Ð¾Ð³Ð»Ð¸ Ð½ÐµÐ¿Ñ\80авилÑ\8cно Ð½Ð°Ð±Ñ\80аÑ\82и URL Ð°Ð±Ð¾ Ð¿ÐµÑ\80ейÑ\82и Ð·Ð° Ð½ÐµÐºÐ¾Ñ\80екÑ\82ним Ð¿Ð¾Ñ\81иланнÑ\8fм.\nЦе також може означати помилку в програмному забезпеченні {{GRAMMAR:genitive|{{SITENAME}}}}.",
        "nosuchspecialpage": "Такої спеціальної сторінки нема",
        "nospecialpagetext": "<strong>Такої спеціальної сторінки не існує.</strong>\n\nДив. [[Special:SpecialPages|список спеціальних сторінок]].",
        "error": "Помилка",
        "laggedslavemode": "Увага: сторінка може не містити останніх редагувань.",
        "readonly": "Запис до бази даних заблокований",
        "enterlockreason": "Зазначте причину і приблизний термін блокування",
-       "readonlytext": "Додавання нових статей та інші зміни бази даних у даний момент заблоковані, ймовірно, через планове сервісне обслуговування бази даних, після закінчення якого буде відновлено нормальний стан.\n\nАдміністратор, що заблокував базу, дав наступне пояснення: $1",
-       "missing-article": "У Ð±Ð°Ð·Ñ\96 Ð´Ð°Ð½Ð¸Ñ\85 Ð½Ðµ Ð·Ð½Ð°Ð¹Ð´ÐµÐ½Ð¾ Ð·Ð°Ð¿Ð¸Ñ\82аний Ñ\82екÑ\81Ñ\82 Ñ\81Ñ\82оÑ\80Ñ\96нки Â«$1» $2.\n\nÐ\9fодÑ\96бна Ñ\81иÑ\82Ñ\83аÑ\86Ñ\96Ñ\8f Ð·Ð°Ð·Ð²Ð¸Ñ\87ай Ð²Ð¸Ð½Ð¸ÐºÐ°Ñ\94 Ð¿Ñ\80и Ñ\81пÑ\80обÑ\96 Ð¿ÐµÑ\80еÑ\85одÑ\83 Ð·Ð° Ð·Ð°Ñ\81Ñ\82аÑ\80Ñ\96лим Ð¿Ð¾Ñ\81иланнÑ\8fм Ð°Ð±Ð¾ Ð½Ð° Ñ\96Ñ\81Ñ\82оÑ\80Ñ\96Ñ\8e Ð·Ð¼Ñ\96н Ñ\81Ñ\82оÑ\80Ñ\96нки, Ñ\8fка Ð±Ñ\83ла Ð²Ð¸Ð»Ñ\83Ñ\87ена.\n\nЯкÑ\89о Ñ\81пÑ\80ава Ð½Ðµ Ð² Ñ\86Ñ\8cомÑ\83, Ñ\82о, Ñ\88видÑ\88е Ð·Ð° Ð²Ñ\81е, Ð²Ð¸ Ð²Ð¸Ñ\8fвили Ð¿Ð¾Ð¼Ð¸Ð»ÐºÑ\83 у програмному забезпеченні.\nБудь ласка, повідомте про це [[Special:ListUsers/sysop|адміністратора]], зазначивши URL.",
+       "readonlytext": "Додавання нових статей та інші зміни бази даних у даний момент заблоковані, ймовірно, через планове сервісне обслуговування бази даних, після закінчення якого буде відновлено нормальний стан.\n\nАдміністратор, що заблокував базу, дав таке пояснення: $1",
+       "missing-article": "У Ð±Ð°Ð·Ñ\96 Ð´Ð°Ð½Ð¸Ñ\85 Ð½Ðµ Ð·Ð½Ð°Ð¹Ð´ÐµÐ½Ð¾ Ð·Ð°Ð¿Ð¸Ñ\82аного Ñ\82екÑ\81Ñ\82Ñ\83 Ñ\81Ñ\82оÑ\80Ñ\96нки Â«$1» $2.\n\nÐ\9fодÑ\96бна Ñ\81иÑ\82Ñ\83аÑ\86Ñ\96Ñ\8f Ð·Ð°Ð·Ð²Ð¸Ñ\87ай Ð²Ð¸Ð½Ð¸ÐºÐ°Ñ\94 Ð¿Ñ\80и Ñ\81пÑ\80обÑ\96 Ð¿ÐµÑ\80еÑ\85одÑ\83 Ð·Ð° Ð·Ð°Ñ\81Ñ\82аÑ\80Ñ\96лим Ð¿Ð¾Ñ\81иланнÑ\8fм Ð°Ð±Ð¾ Ð·Ð° Ñ\96Ñ\81Ñ\82оÑ\80Ñ\96Ñ\94Ñ\8e Ð·Ð¼Ñ\96н Ñ\81Ñ\82оÑ\80Ñ\96нки, Ñ\8fка Ð±Ñ\83ла Ð²Ð¸Ð»Ñ\83Ñ\87ена.\n\nЯкÑ\89о Ñ\81пÑ\80ава Ð½Ðµ Ð² Ñ\86Ñ\8cомÑ\83, Ñ\82о Ð¹Ð¼Ð¾Ð²Ñ\96Ñ\80но, Ð²Ð°Ð¼ Ñ\82Ñ\80апилаÑ\81Ñ\8c Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° у програмному забезпеченні.\nБудь ласка, повідомте про це [[Special:ListUsers/sysop|адміністратора]], зазначивши URL.",
        "missingarticle-rev": "(версія № $1)",
        "missingarticle-diff": "(Різниця: $1, $2)",
-       "readonly_lag": "Ð\91аза Ð´Ð°Ð½Ð¸Ñ\85 Ð°Ð²Ñ\82омаÑ\82иÑ\87но Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð° Ð²Ñ\96д Ð·Ð¼Ñ\96н, Ð´Ð¾ÐºÐ¸ Ð²Ñ\82оÑ\80инний Ñ\81еÑ\80веÑ\80 Ð\91Ð\94 не синхронізується з первинним.",
+       "readonly_lag": "Ð\91аза Ð´Ð°Ð½Ð¸Ñ\85 Ð°Ð²Ñ\82омаÑ\82иÑ\87но Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð° Ð²Ñ\96д Ð·Ð¼Ñ\96н, Ð´Ð¾ÐºÐ¸ Ð²Ñ\82оÑ\80инний Ñ\81еÑ\80веÑ\80 Ð±Ð°Ð·Ð¸ Ð´Ð°Ð½Ð¸Ñ\85 не синхронізується з первинним.",
        "internalerror": "Внутрішня помилка",
        "internalerror_info": "Внутрішня помилка: $1",
-       "filecopyerror": "Неможливо скопіювати файл «$1» в «$2».",
-       "filerenameerror": "Неможливо перейменувати файл «$1» в «$2».",
-       "filedeleteerror": "Неможливо вилучити файл «$1».",
-       "directorycreateerror": "Неможливо створити директорію «$1».",
-       "filenotfound": "Неможливо знайти файл «$1».",
+       "filecopyerror": "Не вдалося скопіювати файл «$1» в «$2».",
+       "filerenameerror": "Не вдалося перейменувати файл «$1» на «$2».",
+       "filedeleteerror": "Не вдалося вилучити файл «$1».",
+       "directorycreateerror": "Не вдалося створити каталог \"$1\".",
+       "filenotfound": "Не вдалося знайти файл «$1».",
        "unexpected": "Неочікуване значення: «$1»=«$2».",
        "formerror": "Помилка: неможливо передати дані форми",
        "badarticleerror": "Ця дія не може бути виконана на цій сторінці.",
-       "cannotdelete": "Ð\9dеможливо Ð²Ð¸Ð»Ñ\83Ñ\87иÑ\82и Ñ\81Ñ\82оÑ\80Ñ\96нкÑ\83 Ð°Ð±Ð¾ Ñ\84айл Â«$1».\nÐ\9cожливо, Ñ\97Ñ\97 (його) Ð²Ð¶Ðµ Ð²Ð¸Ð»Ñ\83Ñ\87ив Ñ\85Ñ\82оÑ\81Ñ\8c Ñ\96нÑ\88ий.",
+       "cannotdelete": "Ð\9dеможливо Ð²Ð¸Ð»Ñ\83Ñ\87иÑ\82и Ñ\81Ñ\82оÑ\80Ñ\96нкÑ\83 Ð°Ð±Ð¾ Ñ\84айл Â«$1».\nÐ\9cожливо, Ñ\86е Ð²Ð¶Ðµ Ð·Ñ\80облено ÐºÐ¸Ð¼Ð¾Ñ\81Ñ\8c Ñ\96нÑ\88им.",
        "cannotdelete-title": "Не вдається видалити сторінку «$1»",
        "delete-hook-aborted": "Вилучення було скасовано процедурою-перехоплювачем. \nНіяких поясненень надано не було.",
        "no-null-revision": "Не вдалося створити нульову версію сторінки «$1»",
        "badtitle": "Неприпустима назва",
-       "badtitletext": "Запитана назва сторінки неправильна, порожня, або неправильно зазначена міжмовна чи міжвікі назва.\nМожливо, в назві використовуються недопустимі символи.",
+       "badtitletext": "Запитана назва сторінки неправильна, порожня, або неправильно зазначена міжмовна назва чи інтервікі.\nМожливо, в назві вжиті недопустимі символи.",
        "perfcached": "Наступні дані взяті з кешу і можуть бути застарілими. В кеші зберігається не більше {{PLURAL:$1|1=одного запису|$1 записів}}.",
        "perfcachedts": "Наступні дані взяті з кешу, востаннє він оновлювався о $1. У кеші зберігається не більше $4 {{PLURAL:$4|1=запису|записів}}.",
-       "querypage-no-updates": "Ð\97мÑ\96ни Ñ\86Ñ\96Ñ\94Ñ\97 Ñ\81Ñ\82оÑ\80Ñ\96нки Ð·Ð°Ñ\80аз Ð·Ð°Ð±Ð¾Ñ\80оненÑ\96. Ð\94анÑ\96 Ñ\82Ñ\83Ñ\82 Ð½Ðµ Ð¼Ð¾Ð¶Ñ\83Ñ\82Ñ\8c Ð±Ñ\83Ñ\82и Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ñ\96 Ð·Ð°Ñ\80аз.",
+       "querypage-no-updates": "Ð\97мÑ\96ни Ñ\86Ñ\96Ñ\94Ñ\97 Ñ\81Ñ\82оÑ\80Ñ\96нки Ð·Ð°Ñ\80аз Ð·Ð°Ð±Ð¾Ñ\80оненÑ\96. Ð\94анÑ\96 Ñ\82Ñ\83Ñ\82 Ð½Ð°Ñ\80азÑ\96 Ð½Ðµ Ð¼Ð¾Ð¶Ñ\83Ñ\82Ñ\8c Ð±Ñ\83Ñ\82и Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ñ\96.",
        "viewsource": "Перегляд",
        "viewsource-title": "Перегляд вихідного коду сторінки $1",
        "actionthrottled": "Обмеження за швидкістю",
-       "actionthrottledtext": "Як Ð·Ð°Ñ\85Ñ\96д Ð±Ð¾Ñ\80оÑ\82Ñ\8cби Ð·Ñ\96 Ñ\81памом, Ñ\83Ñ\81Ñ\82ановлено Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ\8f Ð½Ð° Ð±Ð°Ð³Ð°Ñ\82оÑ\80азове Ð·Ð°Ñ\81Ñ\82оÑ\81Ñ\83ваннÑ\8f Ñ\86Ñ\96Ñ\94Ñ\97 Ð´Ñ\96Ñ\97 Ð¿Ñ\80оÑ\82Ñ\8fгом ÐºÐ¾Ñ\80оÑ\82кого Ð¿Ñ\80омÑ\96жкÑ\83 Ñ\87аÑ\81Ñ\83. Ð\91Ñ\83дÑ\8c Ð»Ð°Ñ\81ка, Ð¿Ð¾Ð²Ñ\82оÑ\80Ñ\96Ñ\82Ñ\8c Ñ\81пÑ\80обÑ\83 Ñ\87еÑ\80ез кілька хвилин.",
+       "actionthrottledtext": "Ð\94лÑ\8f Ð±Ð¾Ñ\80оÑ\82Ñ\8cби Ð·Ñ\96 Ñ\81памом Ð²Ñ\81Ñ\82ановлено Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ\8f Ð½Ð° Ð¿Ð¾Ð²Ñ\82оÑ\80не Ð·Ð°Ñ\81Ñ\82оÑ\81Ñ\83ваннÑ\8f Ñ\86Ñ\96Ñ\94Ñ\97 Ð´Ñ\96Ñ\97 Ð·Ð° ÐºÐ¾Ñ\80оÑ\82кий Ñ\87аÑ\81. Ð\92и Ð¿ÐµÑ\80евиÑ\89или Ñ\86е Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ\8f. Ð\9cожеÑ\82е Ñ\81пÑ\80обÑ\83ваÑ\82и Ð·Ð½Ð¾Ð² Ð·Ð° кілька хвилин.",
        "protectedpagetext": "Ця сторінка захищена від редагування та інших дій.",
        "viewsourcetext": "Ви можете переглянути та скопіювати початковий текст цієї сторінки:",
        "viewyourtext": "Ви можете переглянути та скопіювати текст '''ваших редагувань''' на цій сторінці:",
-       "protectedinterface": "Ця сторінка є частиною інтерфейсу програмного забезпечення цієї вікі і її можуть редагувати лише адміністратори проекту. Щоб додати або змінити переклади для усіх вікі, відвідайте [//translatewiki.net/ translatewiki.net], проект локалізації MediaWiki.",
-       "editinginterface": "'''Увага:''' Ви редагуєте сторінку, що є частиною текстового інтерфейсу. Зміни цієї сторінки спричинять зміну інтерфейсу для інших користувачів. Для перекладу повідомлення використовуйте [//translatewiki.net/wiki/Main_Page?setlang=uk translatewiki.net] — проект, що займається локалізацією MediaWiki.",
-       "cascadeprotected": "Сторінка захищена від змін, оскільки її включено до {{PLURAL:$1|1=сторінки, для якої|наступних сторінок, для яких}} установлено каскадний захист: $2",
+       "protectedinterface": "Ця сторінка містить текст інтерфейсу програмного забезпечення цієї Вікі, захищений від небажаного втручання. Щоб додати або змінити переклади для всіх вікі, перейдіть до [//translatewiki.net/ translatewiki.net], проекту локалізації MediaWiki.",
+       "editinginterface": "'''Увага:''' Ви редагуєте сторінку, що є частиною текстового інтерфейсу програм. \nЗміни цієї сторінки спричинять зміну інтерфейсу для інших користувачів цієї Вікі. \nЩоб додати чи змінити переклади для всіх вікі, використовуйте [//translatewiki.net/wiki/Main_Page?setlang=uk translatewiki.net] — проект локалізації MediaWiki.",
+       "cascadeprotected": "Сторінка захищена від змін, оскільки вона належить до {{PLURAL:$1|1=сторінки, для якої|сторінок, для яких}} установлено каскадний захист: $2",
        "namespaceprotected": "У вас нема дозволу редагувати сторінки в просторі назв «$1».",
-       "customcssprotected": "У Ð²Ð°Ñ\81 Ð½ÐµÐ¼Ð°Ñ\94 Ð¿Ñ\80ав Ð½Ð° Ñ\80едагÑ\83ваннÑ\8f Ñ\86Ñ\96Ñ\94Ñ\97 CSS-Ñ\81Ñ\82оÑ\80Ñ\96нки, Ñ\82ак Ñ\8fк вона містить особисті налаштування іншого користувача.",
-       "customjsprotected": "У вас немає дозволу на редагування цієї JavaScript-сторінки, так як вона містить особисті налаштування іншого користувача.",
-       "mycustomcssprotected": "У Ð\92аÑ\81 Ð½ÐµÐ¼Ð°Ñ\94 Ð¿Ñ\80ав для редагування цієї CSS сторінки.",
+       "customcssprotected": "У Ð²Ð°Ñ\81 Ð½ÐµÐ¼Ð°Ñ\94 Ð´Ð¾Ð·Ð²Ð¾Ð»Ñ\83 Ð½Ð° Ñ\80едагÑ\83ваннÑ\8f Ñ\86Ñ\96Ñ\94Ñ\97 CSS-Ñ\81Ñ\82оÑ\80Ñ\96нки, Ð±Ð¾ вона містить особисті налаштування іншого користувача.",
+       "customjsprotected": "У вас немає дозволу на редагування цієї JavaScript-сторінки, бо вона містить особисті налаштування іншого користувача.",
+       "mycustomcssprotected": "У Ð²Ð°Ñ\81 Ð½ÐµÐ¼Ð°Ñ\94 Ð´Ð¾Ð·Ð²Ð¾Ð»Ñ\83 для редагування цієї CSS сторінки.",
        "mycustomjsprotected": "Ви не маєте дозволу для редагування цієї сторінки JavaScript.",
-       "myprivateinfoprotected": "У Ð\92ас немає дозволу на редагування своєї приватної інформації.",
-       "mypreferencesprotected": "У Ð\92ас немає дозволу на редагування своїх налаштувань.",
+       "myprivateinfoprotected": "У Ð²ас немає дозволу на редагування своєї приватної інформації.",
+       "mypreferencesprotected": "У Ð²ас немає дозволу на редагування своїх налаштувань.",
        "ns-specialprotected": "Спеціальні сторінки не можна редагувати.",
        "titleprotected": "Створення сторінки з такою назвою було заборонене користувачем [[User:$1|$1]].\nЗазначена наступна причина: ''$2''.",
        "filereadonlyerror": "Неможливо змінити файл «$1» тому, що файловий архів «$2» перебуває в режимі «лише для читання».\nАдміністратор, що заблокував його, залишив таке пояснення: «''$3''».",
        "virus-badscanner": "Помилка налаштування: невідомий сканер вірусів: ''$1''",
        "virus-scanfailed": "помилка сканування (код $1)",
        "virus-unknownscanner": "невідомий антивірус:",
-       "logouttext": "'''ТепеÑ\80 Ð²Ð¸ Ð¿Ñ\80аÑ\86Ñ\8eÑ\94Ñ\82е Ð² Ñ\82омÑ\83 Ð¶ Ñ\80ежимÑ\96, Ñ\8fкий Ð±Ñ\83в Ð´Ð¾ Ð²Ð°Ñ\88ого Ð²Ñ\85одÑ\83 Ð´Ð¾ Ñ\81иÑ\81Ñ\82еми.'''\n\nÐ\94еÑ\8fкÑ\96 Ñ\81Ñ\82оÑ\80Ñ\96нки Ð¼Ð¾Ð¶Ñ\83Ñ\82Ñ\8c Ð²Ñ\96добÑ\80ажаÑ\82иÑ\81Ñ\8f, Ð½Ñ\96би Ð²Ð¸ Ñ\89е Ð¿Ñ\80едÑ\81Ñ\82авленÑ\96 Ñ\81иÑ\81Ñ\82емÑ\96 Ð¿Ñ\96д Ñ\96менем, Ñ\89об Ñ\83никнÑ\83Ñ\82и Ñ\86Ñ\8cого, Ð¾Ð½Ð¾Ð²Ñ\96Ñ\82Ñ\8c кеш браузера.",
+       "logouttext": "'''Ð\92и Ð²Ð¸Ð¹Ñ\88ли Ð· Ñ\81иÑ\81Ñ\82еми.'''\n\nÐ\94еÑ\8fкÑ\96 Ñ\81Ñ\82оÑ\80Ñ\96нки Ð¼Ð¾Ð¶Ñ\83Ñ\82Ñ\8c Ð²Ñ\96добÑ\80ажаÑ\82иÑ\81Ñ\8f, Ð½Ñ\96би Ð²Ð¸ Ñ\89е Ð² Ñ\81иÑ\81Ñ\82емÑ\96, Ð°Ð¶ Ð¿Ð¾ÐºÐ¸ Ð²Ð¸ Ð½Ðµ Ð¾Ð½Ð¾Ð²Ð¸Ñ\82е кеш браузера.",
        "welcomeuser": "Вітаємо, $1!",
-       "welcomecreation-msg": "Ð\92аÑ\88 Ð°ÐºÐ°Ñ\83нÑ\82 Ð±Ñ\83ло Ñ\81Ñ\82воÑ\80ено.\nÐ\9dе Ð·Ð°Ð±Ñ\83дÑ\8cÑ\82е Ð·Ð¼Ñ\96ниÑ\82и Ñ\81воÑ\97 [[Special:Preferences|налаштування у {{GRAMMAR:genitive|{{SITENAME}}}}]].",
+       "welcomecreation-msg": "Ð\92аÑ\88 Ð¾Ð±Ð»Ñ\96ковий Ð·Ð°Ð¿Ð¸Ñ\81 Ñ\81Ñ\82воÑ\80ено.\nТепеÑ\80 Ð¼Ð°Ñ\94Ñ\82е Ð·Ð¼Ð¾Ð³Ñ\83 Ð·Ð° Ð±Ð°Ð¶Ð°Ð½Ð½Ñ\8fм Ð·Ð¼Ñ\96нÑ\8eваÑ\82и Ð²Ð°Ñ\88Ñ\96 [[Special:Preferences|налаштування у {{GRAMMAR:genitive|{{SITENAME}}}}]].",
        "yourname": "Ім'я користувача:",
        "userlogin-yourname": "Ім'я користувача",
        "userlogin-yourname-ph": "Введіть ім'я користувача",
        "externaldberror": "Сталася помилка при автентифікації за допомогою зовнішньої бази даних, або у вас недостатньо прав для внесення змін до свого зовнішнього облікового запису.",
        "login": "Вхід до системи",
        "nav-login-createaccount": "Вхід / реєстрація",
-       "loginprompt": "Ви повинні активувати куки (cookies) для входу до {{GRAMMAR:genitive|{{SITENAME}}}}.",
        "userlogin": "Вхід / реєстрація",
        "userloginnocreate": "Увійти",
        "logout": "Вихід із системи",
        "userlogin-noaccount": "Немає облікового запису?",
        "userlogin-joinproject": "Приєднатися до {{GRAMMAR:genitive|{{SITENAME}}}}",
        "nologin": "Ви ще не зареєструвались? $1.",
-       "nologinlink": "Створіть обліковий запис",
+       "nologinlink": "Створити обліковий запис",
        "createaccount": "Зареєструватися",
        "gotaccount": "Ви вже зареєстровані? '''$1'''.",
-       "gotaccountlink": "Увійдіть",
+       "gotaccountlink": "Увійти",
        "userlogin-resetlink": "Забули дані, потрібні для входу?",
        "userlogin-resetpassword-link": "Забули пароль?",
        "userlogin-helplink2": "Допомога з входом у систему",
-       "userlogin-loggedin": "Ви вже увійшли як {{GENDER:$1|$1}}.\nВикористайте нижче форму для входу як інший користувач.",
-       "userlogin-createanother": "Створити інший обліковий запис",
        "createacct-emailrequired": "Адреса електронної пошти",
        "createacct-emailoptional": "Адреса електронної пошти (не обов'язково)",
        "createacct-email-ph": "Введіть Вашу адресу електронної пошти",
        "createacct-realname": "Справжнє ім'я (не обов'язково)",
        "createaccountreason": "Причина:",
        "createacct-reason": "Причина",
-       "createacct-reason-ph": "ЧомÑ\83 Ð\92и створюєте інший обліковий запис",
+       "createacct-reason-ph": "ЧомÑ\83 Ð²и створюєте інший обліковий запис",
        "createacct-captcha": "Перевірка безпеки",
-       "createacct-imgcaptcha-ph": "Ð\92ведÑ\96Ñ\82Ñ\8c Ñ\82екÑ\81Ñ\82, Ñ\89о Ð\92и бачите вище",
-       "createacct-submit": "СÑ\82воÑ\80Ñ\96Ñ\82Ñ\8c Ð\92аш обліковий запис",
+       "createacct-imgcaptcha-ph": "Ð\92ведÑ\96Ñ\82Ñ\8c Ñ\82екÑ\81Ñ\82, Ñ\8fкий Ð²и бачите вище",
+       "createacct-submit": "СÑ\82воÑ\80Ñ\96Ñ\82Ñ\8c Ð²аш обліковий запис",
        "createacct-another-submit": "Створити інший обліковий запис",
-       "createacct-benefit-heading": "{{SITENAME}} створюється такими ж людьми, як і ви.",
+       "createacct-benefit-heading": "{{SITENAME}} створюється такими самими людьми, як і ви.",
        "createacct-benefit-body1": "{{PLURAL:$1|редагування|редагування|редагувань}}",
        "createacct-benefit-body2": "{{PLURAL:$1|сторінка|сторінки|сторінок}}",
        "createacct-benefit-body3": "{{PLURAL:$1|дописувач|дописувачі|дописувачів}} цього місяця",
-       "badretype": "УведенÑ\96 Ð²Ð°Ð¼Ð¸ Ð¿Ð°Ñ\80олÑ\96 Ð½Ðµ Ð·Ð±Ñ\96гаÑ\8eÑ\82Ñ\8cÑ\81Ñ\8f.",
-       "userexists": "Уведене ім'я користувача вже існує.\nБудь ласка оберіть інше ім'я.",
+       "badretype": "Ð\92веденÑ\96 Ð¿Ð°Ñ\80олÑ\96 Ð½Ðµ Ñ\81пÑ\96впадаÑ\8eÑ\82Ñ\8c.",
+       "userexists": "Ð\92ведене ім'я користувача вже існує.\nБудь ласка оберіть інше ім'я.",
        "loginerror": "Помилка при вході до системи",
        "createacct-error": "Помилка створення облікового запису",
        "createaccounterror": "Не в змозі створити обліковий запис: $1",
-       "nocookiesnew": "Ð\9aоÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87 Ð·Ð°Ñ\80еÑ\94Ñ\81Ñ\82Ñ\80Ñ\83вавÑ\81Ñ\8f, Ð°Ð»Ðµ Ð½Ðµ Ð²Ð²Ñ\96йÑ\88ов Ð´Ð¾ Ñ\81иÑ\81Ñ\82еми.\n{{SITENAME}} Ð²Ð¸ÐºÐ¾Ñ\80иÑ\81Ñ\82овÑ\83Ñ\94 ÐºÑ\83ки Ð´Ð»Ñ\8f Ð²Ñ\85одÑ\83 Ð´Ð¾ Ñ\81иÑ\81Ñ\82еми.\nУ Ð²Ð°Ñ\81 ÐºÑ\83ки Ð·Ð°Ð±Ð¾Ñ\80оненÑ\96.\nÐ\91Ñ\83дÑ\8c Ð»Ð°Ñ\81ка, Ð´Ð¾Ð·Ð²Ð¾Ð»Ñ\8cÑ\82е їх, а потім увійдіть з вашим новим іменем користувача і паролем.",
+       "nocookiesnew": "Ð\92и Ð·Ð°Ñ\80еÑ\94Ñ\81Ñ\82Ñ\80ованÑ\96, Ð°Ð»Ðµ Ð½Ðµ Ð²Ð²Ñ\96йÑ\88ли Ð´Ð¾ Ñ\81иÑ\81Ñ\82еми.\n{{SITENAME}} Ð²Ð¸ÐºÐ¾Ñ\80иÑ\81Ñ\82овÑ\83Ñ\94 ÐºÑ\83ки Ð´Ð»Ñ\8f Ð²Ñ\85одÑ\83 Ð´Ð¾ Ñ\81иÑ\81Ñ\82еми.\nУ Ð²Ð°Ñ\81 Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ñ\96 ÐºÑ\83ки.\nÐ\91Ñ\83дÑ\8c Ð»Ð°Ñ\81ка, Ñ\83вÑ\96мкнÑ\96Ñ\82Ñ\8c їх, а потім увійдіть з вашим новим іменем користувача і паролем.",
        "nocookieslogin": "{{SITENAME}} використовує куки (''cookies'') для входу до системи.\nВи їх вимкнули.\nБудь ласка, ввімкніть куки і спробуйте знову.",
-       "nocookiesfornew": "Ð\9eблÑ\96ковий Ð·Ð°Ð¿Ð¸Ñ\81 ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87а Ð½Ðµ Ð±Ñ\83в Ñ\81Ñ\82воÑ\80ений Ñ\87еÑ\80ез Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ñ\96Ñ\81Ñ\82Ñ\8c Ð¿ÐµÑ\80евÑ\96Ñ\80иÑ\82и Ð¹Ð¾Ð³Ð¾ Ð´Ð¶ÐµÑ\80ело.\nÐ\9fеÑ\80еконайÑ\82еÑ\81Ñ\8f, Ñ\89о cookie ввімкнено, оновіть сторінку і спробуйте ще раз.",
+       "nocookiesfornew": "Ð\9eблÑ\96ковий Ð·Ð°Ð¿Ð¸Ñ\81 ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87а Ð½Ðµ Ð±Ñ\83в Ñ\81Ñ\82воÑ\80ений Ñ\87еÑ\80ез Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ñ\96Ñ\81Ñ\82Ñ\8c Ð¿ÐµÑ\80евÑ\96Ñ\80иÑ\82и Ð¿Ð¾Ñ\85одженнÑ\8f Ð´Ð°Ð½Ð¸Ñ\85.\nÐ\9fеÑ\80еконайÑ\82еÑ\81Ñ\8f, Ñ\89о ÐºÑ\83ки ввімкнено, оновіть сторінку і спробуйте ще раз.",
        "nocookiesforlogin": "{{int:nocookieslogin}}",
        "noname": "Ви зазначили неправильне ім'я користувача.",
        "loginsuccesstitle": "Успішний вхід до системи",
-       "loginsuccess": "'''Тепер ви працюєте {{grammar:locative|{{SITENAME}}}} під іменем $1.'''",
-       "nosuchuser": "Користувач з іменем «$1» не існує.\nІмена користувачів регістрозалежні.\nПеревірте правильність написання або скористайтеся формою нижче, щоб [[Special:UserLogin/signup|зареєструвати нового користувача]].",
-       "nosuchusershort": "Користувач з іменем $1 не існує.\nПеревірте правильність написання імені.",
+       "loginsuccess": "'''Тепер ви працюєте в {{grammar:locative|{{SITENAME}}}} під іменем $1.'''",
+       "nosuchuser": "Користувача з іменем «$1» не існує.\nВ іменах користувачів розрізняються великі і малі символи.\nПеревірте правильність написання або скористайтеся формою нижче, щоб [[Special:UserLogin/signup|зареєструвати нового користувача]].",
+       "nosuchusershort": "Користувача з іменем $1 не існує.\nПеревірте правильність написання імені.",
        "nouserspecified": "Ви повинні зазначити ім'я користувача.",
        "login-userblocked": "Цей користувач заблокований. Вхід в систему не дозволений.",
        "wrongpassword": "Ви ввели хибний пароль. Спробуйте ще раз.",
        "wrongpasswordempty": "Ви не ввели пароль. Будь ласка, спробуйте ще раз.",
        "passwordtooshort": "Ваш пароль закороткий, він має містити принаймні $1 {{PLURAL:$1|символ|символи|символів}}.",
-       "password-name-match": "Уведений пароль має відрізнятися від імені користувача.",
+       "password-name-match": "Ð\92аÑ\88 пароль має відрізнятися від імені користувача.",
        "password-login-forbidden": "Використання цього імені користувача і пароля заборонено.",
        "mailmypassword": "Перевстановити пароль",
-       "passwordremindertitle": "Ð\9fам'Ñ\8fÑ\82ка Ð¿Ð°Ñ\80олÑ\8f ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87а {{grammar:genitive|{{SITENAME}}}}",
-       "passwordremindertext": "Хтось (можливо, ви, з IP-адреси $1) зробив запит\nна надсилання вам нового пароля користувача {{grammar:genitive|{{SITENAME}}}} ($4). Для користувача\n«$2» створено новий пароль: <code>$3</code>. Якщо це зробили ви,\nто вам слід увійти до системи, ввівши новий пароль.\nВаш тимчасовий пароль втратить силу через {{PLURAL:$5|$5 день|$5 дні|$5 днів}}.\n\nЯкщо ви не надсилали запиту на зміну пароля або якщо ви вже згадали свій пароль\nі не хочете його змінювати, ви можете ігнорувати це повідомлення і\nпродовжувати використовувати свій старий пароль.",
-       "noemail": "Для користувача \"$1\" не вказано адресу електронної пошти.",
+       "passwordremindertitle": "Ð\9dовий Ñ\82имÑ\87аÑ\81овий Ð¿Ð°Ñ\80олÑ\8c Ð´Ð»Ñ\8f {{grammar:genitive|{{SITENAME}}}}",
+       "passwordremindertext": "Хтось (можливо ви, з IP-адреси $1) зробив запит на новий пароль для {{grammar:genitive|{{SITENAME}}}} ($4). Для користувача «$2» створено новий пароль: <code>$3</code>. Якщо це зробили ви, то вам слід увійти до системи, ввівши новий пароль.\nВаш тимчасовий пароль втратить силу через {{PLURAL:$5|$5 день|$5 дні|$5 днів}}.\n\nЯкщо ви не надсилали запиту на зміну пароля або якщо ви вже згадали свій пароль і не хочете його змінювати, ви можете ігнорувати це повідомлення і продовжувати використовувати свій старий пароль.",
+       "noemail": "Для користувача \"$1\" не вказано адреси електронної пошти.",
        "noemailcreate": "Вам треба вказати правильну адресу електронної пошти",
        "passwordsent": "Новий пароль був надісланий на адресу електронної пошти, зазначену для \"$1\".\nБудь ласка, ввійдіть до системи після отримання пароля.",
-       "blocked-mailpassword": "Редагування з вашої IP-адреси заборонено, заблокована також функція відновлення пароля.",
-       "eauthentsent": "На вказану адресу електронної пошти відправлено лист.\nЩоб отримувати листи надалі, дотримуйтесь викладених там інструкцій для підтвердження того, що ця адреса належить вам.",
-       "throttled-mailpassword": "Ð\86нÑ\81Ñ\82Ñ\80Ñ\83кÑ\86Ñ\96Ñ\8f Ð¿Ð¾ Ð²Ñ\96дновленнÑ\8e Ð¿Ð°Ñ\80олÑ\8e Ð²Ð¶Ðµ Ð±Ñ\83ла Ð²Ð¸Ñ\81лана ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\8e Ð¿Ð¾Ñ\88Ñ\82оÑ\8e Ð¿Ñ\80оÑ\82Ñ\8fгом {{PLURAL:$1|1=оÑ\81Ñ\82аннÑ\8cоÑ\97 Ð³Ð¾Ð´Ð¸Ð½Ð¸|оÑ\81Ñ\82аннÑ\96Ñ\85 $1 Ð³Ð¾Ð´Ð¸Ð½}}.\nÐ\94лÑ\8f Ð¿Ð¾Ð¿ÐµÑ\80едженнÑ\8f Ð·Ð»Ð¾Ð²Ð¶Ð¸Ð²Ð°Ð½Ñ\8c Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½Ð¾ Ð½Ð°Ð´Ñ\81илаÑ\82и Ñ\82Ñ\96лÑ\8cки Ð¾Ð´Ð½Ñ\83 Ñ\96нÑ\81Ñ\82Ñ\80Ñ\83кÑ\86Ñ\96Ñ\8e за {{PLURAL:$1|годину|$1 години|$1 годин}}.",
-       "mailerror": "Ð\9fомилка Ð¿Ñ\80и Ð²Ñ\96дпÑ\80авÑ\86Ñ\96 пошти: $1",
+       "blocked-mailpassword": "Редагування з вашої IP-адреси заборонено, заблокована також функція відновлення пароля, щоб запобігти зловживанням.",
+       "eauthentsent": "На вказану адресу електронної пошти відправлено лист підтвердження.\nЩоб отримувати надалі будь-які повідомлення, необхідно підтвердити, що обліковий рахунок належить справді вам, за процедурою, описаною в листі.",
+       "throttled-mailpassword": "Ð\9bиÑ\81Ñ\82а Ð´Ð»Ñ\8f Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ\8f Ð¿Ð°Ñ\80олÑ\8f Ð²Ð¶Ðµ Ð±Ñ\83ло Ð½Ð°Ð´Ñ\96Ñ\81лано ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\8e Ð¿Ð¾Ñ\88Ñ\82оÑ\8e Ð¿Ñ\80оÑ\82Ñ\8fгом {{PLURAL:$1|1=оÑ\81Ñ\82аннÑ\8cоÑ\97 Ð³Ð¾Ð´Ð¸Ð½Ð¸|оÑ\81Ñ\82аннÑ\96Ñ\85 $1 Ð³Ð¾Ð´Ð¸Ð½}}.\nÐ\94лÑ\8f Ð¿Ð¾Ð¿ÐµÑ\80едженнÑ\8f Ð·Ð»Ð¾Ð²Ð¶Ð¸Ð²Ð°Ð½Ñ\8c Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½Ð¾ Ð½Ð°Ð´Ñ\81илаÑ\82и Ñ\82Ñ\96лÑ\8cки Ð¾Ð´Ð½Ð¾Ð³Ð¾ Ð»Ð¸Ñ\81Ñ\82а Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ\8f Ð¿Ð°Ñ\80олÑ\8f за {{PLURAL:$1|годину|$1 години|$1 годин}}.",
+       "mailerror": "Ð\9fомилка Ð½Ð°Ð´Ñ\81иланнÑ\8f пошти: $1",
        "acct_creation_throttle_hit": "Відвідувачі з вашої IP-адреси вже створили $1 {{PLURAL:$1|обліковий запис|облікових записи|облікових записів}} за останню добу, що є максимумом для цього відрізка часу.\nТаким чином, користувачі з цієї IP-адреси не можуть на цей момент створювати нових облікових записів.",
        "emailauthenticated": "Вашу адресу електронної пошти було підтверджено на  $2  о  $3.",
-       "emailnotauthenticated": "Ð\90дÑ\80еÑ\81Ñ\83 Ð²Ð°Ñ\88оÑ\97 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ñ\89е Ð½Ðµ Ð¿Ñ\96дÑ\82веÑ\80джено. Ð\96одна Ð»Ð¸Ñ\81Ñ\82 Ð½Ðµ Ð±Ñ\83де Ð½Ð°Ð´Ñ\96Ñ\81лано Ð´Ð»Ñ\8f Ð±Ñ\83дÑ\8c\8fкоÑ\97 Ð· Ð½Ð°Ñ\81Ñ\82Ñ\83пниÑ\85 Ñ\84Ñ\83нкцій.",
-       "noemailprefs": "Ð\90дÑ\80еÑ\81Ñ\83 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ð½Ðµ Ð²ÐºÐ°Ð·Ð°Ð½Ð¾, Ñ\84Ñ\83нкÑ\86Ñ\96Ñ\97 Ð²Ñ\96кÑ\96 Ñ\80обоÑ\82и Ð· ÐµÐ». Ð¿Ð¾Ñ\88Ñ\82оÑ\8e Ð²Ñ\96дклÑ\8eÑ\87ені.",
-       "emailconfirmlink": "Підтвердити адресу вашої електронної пошти",
-       "invalidemailaddress": "Уведена Ð°Ð´Ñ\80еÑ\81а Ð½Ðµ Ð¼Ð¾Ð¶Ðµ Ð±Ñ\83Ñ\82и Ð¿Ñ\80ийнÑ\8fÑ\82а, Ð±Ð¾ Ð²Ð¾Ð½Ð° Ð½Ðµ Ð²Ñ\96дповÑ\96даÑ\94 Ñ\84оÑ\80маÑ\82Ñ\83 Ð°Ð´Ñ\80еÑ\81 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и.\nБудь ласка, введіть коректну адресу або залиште поле порожнім.",
-       "cannotchangeemail": "У цій вікі не можна міняти свою адресу ел. пошти.",
-       "emaildisabled": "Цей Ñ\81айÑ\82 Ð½Ðµ Ð¼Ð¾Ð¶Ðµ Ð½Ð°Ð´Ñ\96Ñ\81лати електронні листи.",
+       "emailnotauthenticated": "Ð\90дÑ\80еÑ\81Ñ\83 Ð²Ð°Ñ\88оÑ\97 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ñ\89е Ð½Ðµ Ð¿Ñ\96дÑ\82веÑ\80джено. Ð\9dадÑ\81иланнÑ\8f Ð»Ð¸Ñ\81Ñ\82Ñ\96в Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ðµ Ñ\83 Ð¶Ð¾Ð´Ð½Ñ\96й Ð· Ð½Ð°Ñ\81Ñ\82Ñ\83пниÑ\85 Ð¾Ð¿цій.",
+       "noemailprefs": "Ð\92кажÑ\96Ñ\82Ñ\8c Ð°Ð´Ñ\80еÑ\81Ñ\83 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и, Ñ\89об Ñ\83можливиÑ\82и Ð½Ð°Ñ\81Ñ\82Ñ\83пнÑ\96 Ð¿Ð¾Ñ\88Ñ\82овÑ\96 Ñ\84Ñ\83нкÑ\86Ñ\96Ñ\97 Ð²Ñ\96кі.",
+       "emailconfirmlink": "Підтвердіть адресу вашої електронної пошти",
+       "invalidemailaddress": "Ð\92казана Ð°Ð´Ñ\80еÑ\81а Ð½Ðµ Ð¼Ð¾Ð¶Ðµ Ð±Ñ\83Ñ\82и Ð¿Ñ\80ийнÑ\8fÑ\82а Ñ\87еÑ\80ез Ð½ÐµÐ²Ñ\96дповÑ\96дний Ñ\84оÑ\80маÑ\82.\nБудь ласка, введіть коректну адресу або залиште поле порожнім.",
+       "cannotchangeemail": "У цій вікі не можна міняти адресу електронної пошти, закріплену за обліковим записом.",
+       "emaildisabled": "Ð\97 Ñ\86Ñ\8cого Ñ\81айÑ\82Ñ\83 Ð½Ðµ Ð¼Ð¾Ð¶Ð½Ð° Ð½Ð°Ð´Ñ\81илати електронні листи.",
        "accountcreated": "Обліковий запис створено.",
        "accountcreatedtext": "Обліковий запис користувача для [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|обговорення]]) був створений.",
        "createaccount-title": "Створення облікового запису для {{SITENAME}}",
-       "createaccount-text": "Ð¥Ñ\82оÑ\81Ñ\8c Ñ\81Ñ\82воÑ\80ив Ð¾Ð±Ð»Ñ\96ковий Ð·Ð°Ð¿Ð¸Ñ\81 Â«$2» Ð½Ð° Ñ\81еÑ\80веÑ\80Ñ\96 Ð¿Ñ\80оекÑ\82Ñ\83 {{SITENAME}} ($4) Ð· Ð¿Ð°Ñ\80олем Â«$3», Ð·Ð°Ð·Ð½Ð°Ñ\87ивÑ\88и Ð²Ð°Ñ\88Ñ\83 Ð°Ð´Ñ\80еÑ\81Ñ\83 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и. Ð\92ам Ñ\81лÑ\96д Ð·Ð°Ð¹Ñ\82и Ñ\96 Ð·Ð¼Ñ\96ниÑ\82и Ð¿Ð°Ñ\80олÑ\8c.\n\nÐ\9fÑ\80оÑ\96гноруйте дане повідомлення, якщо обліковий запис було створено помилково.",
+       "createaccount-text": "Ð¥Ñ\82оÑ\81Ñ\8c Ñ\81Ñ\82воÑ\80ив Ð¾Ð±Ð»Ñ\96ковий Ð·Ð°Ð¿Ð¸Ñ\81 Â«$2» Ð½Ð° Ñ\81еÑ\80веÑ\80Ñ\96 Ð¿Ñ\80оекÑ\82Ñ\83 {{SITENAME}} ($4) Ð· Ð¿Ð°Ñ\80олем Â«$3», Ð·Ð°Ð·Ð½Ð°Ñ\87ивÑ\88и Ð²Ð°Ñ\88Ñ\83 Ð°Ð´Ñ\80еÑ\81Ñ\83 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и. Ð\92ам Ñ\81лÑ\96д Ð·Ð°Ð¹Ñ\82и Ñ\96 Ð·Ð¼Ñ\96ниÑ\82и Ð¿Ð°Ñ\80олÑ\8c.\n\nÐ\86гноруйте дане повідомлення, якщо обліковий запис було створено помилково.",
        "login-throttled": "Ви зробили надто багато спроб ввійти до системи.\nБудь ласка, зачекайте $1 перед повторною спробою.",
        "login-abort-generic": "Не вдалося ввійти до системи",
        "loginlanguagelabel": "Мова: $1",
-       "suspicious-userlogout": "Ваш запит на завершення сеанса відхилений, оскільки він схожий на запит, відправлений зіпсованим веб-оглядачем або кешуючим проксі-сервером.",
-       "createacct-another-realname-tip": "Справжнє ім'я є необов'язковим.\nЯкщо ви вирішите надати його, то воно буде використовуватися для присвоєння користувачу авторства до його роботи.",
+       "suspicious-userlogout": "Ваш запит на завершення сеансу відхилений, оскільки він схожий на запит, відправлений зіпсованим веб-оглядачем або кешуючим проксі-сервером.",
+       "createacct-another-realname-tip": "Справжнє ім'я є необов'язковим.\nЯкщо ви вирішите надати його, воно буде використовуватись для позначення редагувань та інших дій користувача.",
        "pt-login": "Увійти",
        "pt-login-button": "Вхід",
        "pt-createaccount": "Створити обліковий запис",
        "pt-userlogout": "Вийти",
        "php-mail-error-unknown": "Невідома помилка в PHP-функції mail()",
-       "user-mail-no-addy": "СпÑ\80оба Ð½Ð°Ð´Ñ\81иланнÑ\8f ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ð±ÐµÐ· Ð·Ð°Ð·Ð½Ð°Ñ\87еноÑ\97 Ð°Ð´Ñ\80еÑ\81и ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и.",
+       "user-mail-no-addy": "СпÑ\80оба Ð½Ð°Ð´Ñ\81иланнÑ\8f ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ð±ÐµÐ· Ð·Ð°Ð·Ð½Ð°Ñ\87еннÑ\8f Ð°Ð´Ñ\80еÑ\81и.",
        "user-mail-no-body": "Спроба надіслати електронного листа з порожнім або надто коротким вмістом.",
        "changepassword": "Змінити пароль",
        "resetpass_announce": "Для завершення входу ви повинні встановити новий пароль.",
        "oldpassword": "Старий пароль:",
        "newpassword": "Новий пароль:",
        "retypenew": "Ще раз введіть новий пароль:",
-       "resetpass_submit": "Установити пароль і ввійти",
+       "resetpass_submit": "Ð\92становити пароль і ввійти",
        "changepassword-success": "Ваш пароль успішно змінено!",
        "changepassword-throttled": "Ви нещодавно зробили надто багато спроб ввійти до системи.\nБудь ласка, зачекайте $1 перед повторною спробою.",
-       "resetpass_forbidden": "Пароль не можна змінювати",
+       "resetpass_forbidden": "Пароль не можна змінити",
        "resetpass-no-info": "Щоб звертатися безпосередньо до цієї сторінки, вам слід увійти до системи.",
        "resetpass-submit-loggedin": "Змінити пароль",
        "resetpass-submit-cancel": "Скасувати",
        "resetpass-expired-soft": "Термін дії вашого пароля закінчився, і тепер він повинен бути змінений. Будь ласка, виберіть новий пароль або натисніть \"{{int:resetpass-submit-cancel}}\", щоб змінити його пізніше.",
        "resetpass-validity-soft": "Ваш пароль є некоректним: $1\n\nБудь ласка, виберіть новий пароль або натисніть «{{int:resetpass-submit-cancel}}», щоб скинути його пізніше.",
        "passwordreset": "Скинути пароль",
-       "passwordreset-text-one": "Заповніть цю форму для відновлення пароля.",
-       "passwordreset-text-many": "{{PLURAL:$1|Ð\97аповнÑ\96Ñ\82Ñ\8c Ð¾Ð´Ð½Ðµ Ð· Ð¿Ð¾Ð»Ñ\96в Ð´Ð»Ñ\8f Ð¾Ñ\82Ñ\80иманнÑ\8f Ñ\82имÑ\87аÑ\81ового Ð¿Ð°Ñ\80олÑ\8e Ñ\87еÑ\80ез ÐµÐ»ÐµÐºÑ\82Ñ\80оннÑ\83 Ð¿Ð¾Ñ\88Ñ\82Ñ\83.}}",
+       "passwordreset-text-one": "Заповніть цю форму, щоб отримати тимчасовий пароль електронною поштою.",
+       "passwordreset-text-many": "{{PLURAL:$1|Ð\97аповнÑ\96Ñ\82Ñ\8c Ð¾Ð´Ð½Ðµ Ð· Ð¿Ð¾Ð»Ñ\96в Ð´Ð»Ñ\8f Ð¾Ñ\82Ñ\80иманнÑ\8f Ñ\82имÑ\87аÑ\81ового Ð¿Ð°Ñ\80олÑ\8f ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\8e Ð¿Ð¾Ñ\88Ñ\82оÑ\8e.}}",
        "passwordreset-legend": "Перевстановити пароль",
        "passwordreset-disabled": "У цій вікі вимкнена можливість скидання пароля.",
-       "passwordreset-emaildisabled": "ФÑ\83нкÑ\86Ñ\96Ñ\97 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ð²Ð¸Ð¼ÐºÐ½Ñ\83Ñ\82о Ð² Ñ\86Ñ\96й Ð²Ñ\96кÑ\96.",
+       "passwordreset-emaildisabled": "Ð\92 Ñ\86Ñ\96й Ð²Ñ\96кÑ\96 Ð²Ð¸Ð¼ÐºÐ½Ñ\83Ñ\82о Ð¤Ñ\83нкÑ\86Ñ\96Ñ\97 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и.",
        "passwordreset-username": "Ім'я користувача:",
        "passwordreset-domain": "Домен:",
        "passwordreset-capture": "Продивитись результуючий електронний лист?",
-       "passwordreset-capture-help": "ЯкÑ\89о Ð\92и Ð²Ñ\81Ñ\82ановиÑ\82е Ð²Ñ\96дмÑ\96Ñ\82кÑ\83, Ð\92ам Ð±Ñ\83де Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ð¸Ð¹ ÐµÐ»ÐµÐºÑ\82Ñ\80онний Ð»Ð¸Ñ\81Ñ\82 (Ñ\96з Ñ\82имÑ\87аÑ\81овим Ð¿Ð°Ñ\80олем), Ñ\8fкий Ð±Ñ\83де Ð²Ñ\96дпÑ\80авлений користувачеві.",
+       "passwordreset-capture-help": "ЯкÑ\89о Ð²Ð¸ Ð·Ñ\80обиÑ\82е Ð¿Ð¾Ð¼Ñ\96Ñ\82кÑ\83 Ñ\83 Ð²Ñ\96конÑ\86Ñ\96, Ð²Ð°Ð¼ Ð±Ñ\83де Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ð¸Ð¹ ÐµÐ»ÐµÐºÑ\82Ñ\80онний Ð»Ð¸Ñ\81Ñ\82 (Ñ\96з Ñ\82имÑ\87аÑ\81овим Ð¿Ð°Ñ\80олем), Ñ\8fкий Ñ\82акож Ð±Ñ\83де Ð½Ð°Ð´Ñ\96Ñ\81ланий користувачеві.",
        "passwordreset-email": "Адреса електронної пошти:",
        "passwordreset-emailtitle": "Деталі облікового запису на {{SITENAME}}",
-       "passwordreset-emailtext-ip": "Ð¥Ñ\82оÑ\81Ñ\8c (Ñ\96мовÑ\96Ñ\80но Ð\92и, Ð· IP-адÑ\80еÑ\81и $1) Ð¿Ð¾Ð¿Ñ\80оÑ\81ив Ð½Ð°Ð³Ð°Ð´Ð°Ñ\82и Ð´ÐµÑ\82алÑ\96 Ð\92аÑ\88ого Ð¾Ð±Ð»Ñ\96кового Ð·Ð°Ð¿Ð¸Ñ\81Ñ\83 Ð´Ð»Ñ\8f {{SITENAME}} ($4). Ð\97 Ð\92аÑ\88оÑ\8e ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\8e Ñ\81кÑ\80инÑ\8cкоÑ\8e Ð¿Ð¾Ð²'Ñ\8fзан{{PLURAL:$3|1=ий Ñ\82акий Ð·Ð°Ð¿Ð¸Ñ\81\96 Ñ\82акÑ\96 Ð·Ð°Ð¿Ð¸Ñ\81и}}:\n\n$2\n\n{{PLURAL:$3|1=Цей Ñ\82имÑ\87аÑ\81овий Ð¿Ð°Ñ\80олÑ\8c Ñ\81Ñ\82ане Ð½ÐµÐ´Ñ\96йÑ\81ним|ЦÑ\96 Ñ\82имÑ\87аÑ\81овÑ\96 Ð¿Ð°Ñ\80олÑ\96 Ñ\81Ñ\82анÑ\83Ñ\82Ñ\8c Ð½ÐµÐ´Ñ\96йÑ\81ними}} Ñ\87еÑ\80ез $5 {{PLURAL:$5|денÑ\8c|днÑ\96|днÑ\96в}}.\nÐ\92и Ð¼Ð°Ñ\94Ñ\82е Ð²Ð²Ñ\96йÑ\82и Ð² Ñ\81иÑ\81Ñ\82емÑ\83 Ñ\96 Ð²Ð¸Ð±Ñ\80аÑ\82и Ð½Ð¾Ð²Ð¸Ð¹ Ð¿Ð°Ñ\80олÑ\8c. Ð¯ÐºÑ\89о Ð¶ Ñ\86ей Ð·Ð°Ð¿Ð¸Ñ\82 Ð·Ñ\80обив Ñ\85Ñ\82оÑ\81Ñ\8c Ñ\96нÑ\88ий, Ð°Ð±Ð¾ Ð\92и Ð¿Ð°Ð¼'Ñ\8fÑ\82аÑ\94Ñ\82е Ñ\81вÑ\96й Ñ\81Ñ\82аÑ\80ий Ð¿Ð°Ñ\80олÑ\8c Ñ\96 Ð½Ðµ Ð±Ð°Ð¶Ð°Ñ\94Ñ\82е Ð¹Ð¾Ð³Ð¾ Ð·Ð¼Ñ\96нÑ\8eваÑ\82и, Ð¼Ð¾Ð¶ÐµÑ\82е Ð¿Ñ\80оÑ\81Ñ\82о Ð¿Ñ\80оігнорувати це повідомлення та продовжувати використовувати старий пароль.",
-       "passwordreset-emailtext-user": "Ð\9aоÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87 $1 Ð· {{SITENAME}} Ð¿Ð¾Ð¿Ñ\80оÑ\81ив Ð½Ð°Ð³Ð°Ð´Ð°Ñ\82и Ð´ÐµÑ\82алÑ\96 Ð\92аÑ\88ого Ð¾Ð±Ð»Ñ\96кового Ð·Ð°Ð¿Ð¸Ñ\81Ñ\83 Ð´Ð»Ñ\8f {{SITENAME}} ($4). Ð\97 Ð\92аÑ\88оÑ\8e ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\8e Ñ\81кÑ\80инÑ\8cкоÑ\8e Ð¿Ð¾Ð²'Ñ\8fзан{{PLURAL:$3|1=ий Ñ\82акий Ð·Ð°Ð¿Ð¸Ñ\81\96 Ñ\82акÑ\96 Ð·Ð°Ð¿Ð¸Ñ\81и}}:\n\n$2\n\n{{PLURAL:$3|1=Цей Ñ\82имÑ\87аÑ\81овий Ð¿Ð°Ñ\80олÑ\8c|ЦÑ\96 Ñ\82имÑ\87аÑ\81овÑ\96 Ð¿Ð°Ñ\80олÑ\96}} Ñ\81Ñ\82анÑ\83Ñ\82Ñ\8c Ð½ÐµÑ\87иннÑ\96 Ñ\87еÑ\80ез {{PLURAL:$5|денÑ\8c|$5 Ð´Ð½Ñ\96|$5 Ð´Ð½Ñ\96в}}.\nÐ\92и Ð¼Ð°Ñ\94Ñ\82е Ð²Ð²Ñ\96йÑ\82и Ð² Ñ\81иÑ\81Ñ\82емÑ\83 Ñ\96 Ð²Ð¸Ð±Ñ\80аÑ\82и Ð½Ð¾Ð²Ð¸Ð¹ Ð¿Ð°Ñ\80олÑ\8c. Ð¯ÐºÑ\89о Ð¶ Ñ\86ей Ð·Ð°Ð¿Ð¸Ñ\82 Ð·Ñ\80обив Ñ\85Ñ\82оÑ\81Ñ\8c Ñ\96нÑ\88ий, Ð°Ð±Ð¾ Ð\92и Ð¿Ð°Ð¼'Ñ\8fÑ\82аÑ\94Ñ\82е Ñ\81вÑ\96й Ñ\81Ñ\82аÑ\80ий Ð¿Ð°Ñ\80олÑ\8c Ñ\96 Ð½Ðµ Ð±Ð°Ð¶Ð°Ñ\94Ñ\82е Ð¹Ð¾Ð³Ð¾ Ð·Ð¼Ñ\96нÑ\8eваÑ\82и, Ð¼Ð¾Ð¶ÐµÑ\82е Ð¿Ñ\80оÑ\81Ñ\82о Ð¿Ñ\80оігнорувати це повідомлення та продовжувати використовувати старий пароль.",
+       "passwordreset-emailtext-ip": "Ð¥Ñ\82оÑ\81Ñ\8c (Ñ\96мовÑ\96Ñ\80но Ð²Ð¸, Ð· IP-адÑ\80еÑ\81и $1) Ð¿Ð¾Ð¿Ñ\80оÑ\81ив Ð½Ð°Ð³Ð°Ð´Ð°Ñ\82и Ð´ÐµÑ\82алÑ\96 Ð²Ð°Ñ\88ого Ð¾Ð±Ð»Ñ\96кового Ð·Ð°Ð¿Ð¸Ñ\81Ñ\83 Ð´Ð»Ñ\8f {{SITENAME}} ($4). Ð\97 Ð²Ð°Ñ\88оÑ\8e ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\8e Ñ\81кÑ\80инÑ\8cкоÑ\8e Ð¿Ð¾Ð²'Ñ\8fзан{{PLURAL:$3|1=ий Ñ\82акий Ð·Ð°Ð¿Ð¸Ñ\81\96 Ñ\82акÑ\96 Ð·Ð°Ð¿Ð¸Ñ\81и}}:\n\n$2\n\n{{PLURAL:$3|1=Цей Ñ\82имÑ\87аÑ\81овий Ð¿Ð°Ñ\80олÑ\8c Ñ\81Ñ\82ане Ð½ÐµÐ´Ñ\96йÑ\81ним|ЦÑ\96 Ñ\82имÑ\87аÑ\81овÑ\96 Ð¿Ð°Ñ\80олÑ\96 Ñ\81Ñ\82анÑ\83Ñ\82Ñ\8c Ð½ÐµÐ´Ñ\96йÑ\81ними}} Ñ\87еÑ\80ез $5 {{PLURAL:$5|денÑ\8c|днÑ\96|днÑ\96в}}.\nÐ\92и Ð¼Ð°Ñ\94Ñ\82е Ð²Ð²Ñ\96йÑ\82и Ð² Ñ\81иÑ\81Ñ\82емÑ\83 Ñ\96 Ð²Ð¸Ð±Ñ\80аÑ\82и Ð½Ð¾Ð²Ð¸Ð¹ Ð¿Ð°Ñ\80олÑ\8c. Ð¯ÐºÑ\89о Ð¶ Ñ\86ей Ð·Ð°Ð¿Ð¸Ñ\82 Ð·Ñ\80обив Ñ\85Ñ\82оÑ\81Ñ\8c Ñ\96нÑ\88ий Ð°Ð±Ð¾ Ð²Ð¸ Ð·Ð³Ð°Ð´Ð°Ð»Ð¸ Ñ\81вÑ\96й Ñ\81Ñ\82аÑ\80ий Ð¿Ð°Ñ\80олÑ\8c Ñ\96 Ð½Ðµ Ð±Ð°Ð¶Ð°Ñ\94Ñ\82е Ð¹Ð¾Ð³Ð¾ Ð·Ð¼Ñ\96нÑ\8eваÑ\82и, Ð¼Ð¾Ð¶ÐµÑ\82е ігнорувати це повідомлення та продовжувати використовувати старий пароль.",
+       "passwordreset-emailtext-user": "Ð\9aоÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87 $1 Ð· {{SITENAME}} Ð¿Ð¾Ð¿Ñ\80оÑ\81ив Ð½Ð°Ð³Ð°Ð´Ð°Ñ\82и Ð´ÐµÑ\82алÑ\96 Ð²Ð°Ñ\88ого Ð¾Ð±Ð»Ñ\96кового Ð·Ð°Ð¿Ð¸Ñ\81Ñ\83 Ð´Ð»Ñ\8f {{SITENAME}} ($4). Ð\97 Ð²Ð°Ñ\88оÑ\8e ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\8e Ñ\81кÑ\80инÑ\8cкоÑ\8e Ð¿Ð¾Ð²'Ñ\8fзан{{PLURAL:$3|1=ий Ñ\82акий Ð·Ð°Ð¿Ð¸Ñ\81\96 Ñ\82акÑ\96 Ð·Ð°Ð¿Ð¸Ñ\81и}}:\n\n$2\n\n{{PLURAL:$3|1=Цей Ñ\82имÑ\87аÑ\81овий Ð¿Ð°Ñ\80олÑ\8c|ЦÑ\96 Ñ\82имÑ\87аÑ\81овÑ\96 Ð¿Ð°Ñ\80олÑ\96}} Ñ\81Ñ\82анÑ\83Ñ\82Ñ\8c Ð½ÐµÑ\87иннÑ\96 Ñ\87еÑ\80ез {{PLURAL:$5|денÑ\8c|$5 Ð´Ð½Ñ\96|$5 Ð´Ð½Ñ\96в}}.\nÐ\92и Ð¼Ð°Ñ\94Ñ\82е Ð²Ð²Ñ\96йÑ\82и Ð² Ñ\81иÑ\81Ñ\82емÑ\83 Ñ\96 Ð²Ð¸Ð±Ñ\80аÑ\82и Ð½Ð¾Ð²Ð¸Ð¹ Ð¿Ð°Ñ\80олÑ\8c. Ð¯ÐºÑ\89о Ð¶ Ñ\86ей Ð·Ð°Ð¿Ð¸Ñ\82 Ð·Ñ\80обив Ñ\85Ñ\82оÑ\81Ñ\8c Ñ\96нÑ\88ий, Ð°Ð±Ð¾ Ð²Ð¸ Ð·Ð³Ð°Ð´Ð°Ð»Ð¸ Ñ\81вÑ\96й Ñ\81Ñ\82аÑ\80ий Ð¿Ð°Ñ\80олÑ\8c Ñ\96 Ð½Ðµ Ð±Ð°Ð¶Ð°Ñ\94Ñ\82е Ð¹Ð¾Ð³Ð¾ Ð·Ð¼Ñ\96нÑ\8eваÑ\82и, Ð¼Ð¾Ð¶ÐµÑ\82е Ð¿Ñ\80оÑ\81Ñ\82о ігнорувати це повідомлення та продовжувати використовувати старий пароль.",
        "passwordreset-emailelement": "Ім'я користувача: $1\nТимчасовий пароль: $2",
-       "passwordreset-emailsent": "Ð\95лекÑ\82Ñ\80онний Ð»Ð¸Ñ\81Ñ\82 Ð´Ð»Ñ\8f Ð²Ñ\96дновленнÑ\8f Ð¿Ð°Ñ\80олÑ\8f Ð²Ñ\96дпÑ\80авлений.",
-       "passwordreset-emailsent-capture": "Ð\95лекÑ\82Ñ\80онний Ð»Ð¸Ñ\81Ñ\82 Ñ\81киданнÑ\8f Ð¿Ð°Ñ\80олÑ\8e було надіслано, як показано нижче.",
+       "passwordreset-emailsent": "Ð\95лекÑ\82Ñ\80онний Ð»Ð¸Ñ\81Ñ\82 Ð´Ð»Ñ\8f Ð²Ñ\96дновленнÑ\8f Ð¿Ð°Ñ\80олÑ\8f Ð½Ð°Ð´Ñ\96Ñ\81ланий.",
+       "passwordreset-emailsent-capture": "Ð\95лекÑ\82Ñ\80онний Ð»Ð¸Ñ\81Ñ\82 Ñ\81киданнÑ\8f Ð¿Ð°Ñ\80олÑ\8f було надіслано, як показано нижче.",
        "passwordreset-emailerror-capture": "Електронний лист для відновлення пароля мав бути надісланий, як показано нижче, але його надсилання {{GENDER:$2|користувачеві|користувачці}} $1 не вдалося.",
        "changeemail": "Змінити адресу електронної пошти",
        "changeemail-header": "Зміна адреси електронної пошти",
        "changeemail-cancel": "Скасувати",
        "changeemail-throttled": "Ви зробили надто багато спроб ввійти до системи.\nБудь ласка, зачекайте $1 перед повторною спробою.",
        "resettokens": "Скидання жетонів",
-       "resettokens-text": "Ð\92и Ð¼Ð¾Ð¶ÐµÑ\82е Ñ\81кинÑ\83Ñ\82и Ð¶ÐµÑ\82они, Ñ\89о Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ\87Ñ\83Ñ\8eÑ\82Ñ\8c Ð´Ð¾Ñ\81Ñ\82Ñ\83п Ð´Ð¾ Ð¿ÐµÐ²Ð½Ð¸Ñ\85 Ð¾Ñ\81обиÑ\81Ñ\82иÑ\85 Ð´Ð°Ð½Ð¸Ñ\85, Ð¿Ð¾Ð²'Ñ\8fзаниÑ\85 Ñ\82Ñ\83Ñ\82 Ñ\96з Ð\92аÑ\88им Ð¾Ð±Ð»Ñ\96ковим Ð·Ð°Ð¿Ð¸Ñ\81ом.\nÐ\92ам Ñ\81лÑ\96д Ñ\86е Ð·Ñ\80обиÑ\82и, Ñ\8fкÑ\89о Ð\92и Ð²Ð¸Ð¿Ð°Ð´ÐºÐ¾Ð²Ð¾ Ð¿Ð¾Ð´Ñ\96лилиÑ\81Ñ\8c Ð¶ÐµÑ\82онами Ð· ÐºÐ¸Ð¼Ð¾Ñ\81Ñ\8c, Ð°Ð±Ð¾ Ñ\8fкÑ\89о Ð\92аш обліковий запис було зламано.",
+       "resettokens-text": "Ð\92и Ð¼Ð¾Ð¶ÐµÑ\82е Ñ\81кинÑ\83Ñ\82и Ð¶ÐµÑ\82они, Ñ\89о Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ\87Ñ\83Ñ\8eÑ\82Ñ\8c Ð´Ð¾Ñ\81Ñ\82Ñ\83п Ð´Ð¾ Ð¿ÐµÐ²Ð½Ð¸Ñ\85 Ð¾Ñ\81обиÑ\81Ñ\82иÑ\85 Ð´Ð°Ð½Ð¸Ñ\85, Ð¿Ð¾Ð²'Ñ\8fзаниÑ\85 Ñ\82Ñ\83Ñ\82 Ñ\96з Ð²Ð°Ñ\88им Ð¾Ð±Ð»Ñ\96ковим Ð·Ð°Ð¿Ð¸Ñ\81ом.\nÐ\92ам Ñ\81лÑ\96д Ñ\86е Ð·Ñ\80обиÑ\82и, Ñ\8fкÑ\89о Ð²Ð¸ Ð²Ð¸Ð¿Ð°Ð´ÐºÐ¾Ð²Ð¾ Ð¿Ð¾Ð´Ñ\96лилиÑ\81Ñ\8c Ð¶ÐµÑ\82онами Ð· ÐºÐ¸Ð¼Ð¾Ñ\81Ñ\8c, Ð°Ð±Ð¾ Ñ\8fкÑ\89о Ð²аш обліковий запис було зламано.",
        "resettokens-no-tokens": "Немає жетонів до скидання.",
        "resettokens-legend": "Скинути жетони",
        "resettokens-tokens": "Жетони:",
        "resettokens-token-label": "$1 (поточне значення: $2)",
-       "resettokens-watchlist-token": "Маркер стрічки новин (Atom/RSS) з [[Special:Watchlist|змін на сторінку у вашому списку спостереження]]",
+       "resettokens-watchlist-token": "Маркер стрічки новин (Atom/RSS) щодо [[Special:Watchlist|зміни на сторінці з вашого списку спостереження]]",
        "resettokens-done": "Жетони скинуто.",
        "resettokens-resetbutton": "Скинути обрані жетони",
        "bold_sample": "Жирний текст",
        "italic_tip": "Курсив",
        "link_sample": "Назва посилання",
        "link_tip": "Внутрішнє посилання",
-       "extlink_sample": "http://www.example.com назва посилання",
+       "extlink_sample": "назва посилання http://www.example.com",
        "extlink_tip": "Зовнішнє посилання (не забудьте про префікс http://)",
        "headline_sample": "Текст заголовка",
        "headline_tip": "Заголовок 2-го рівня",
-       "nowiki_sample": "Ð\92Ñ\81Ñ\82авлÑ\8fйÑ\82е Ñ\81Ñ\8eди Ð½ÐµÐ²Ñ\96дформатований текст.",
+       "nowiki_sample": "Ð\92Ñ\81Ñ\82авиÑ\82и Ñ\81Ñ\8eди Ð½Ðµформатований текст.",
        "nowiki_tip": "Ігнорувати вікі-форматування",
        "image_sample": "Example.jpg",
        "image_tip": "Файл",
        "preview": "Попередній перегляд",
        "showpreview": "Попередній перегляд",
        "showdiff": "Показати зміни",
-       "anoneditwarning": "'''Увага''': Ви не увійшли до системи. Ваша IP-адреса буде записана до історії змін цієї сторінки.",
+       "blankarticle": "'''Попередження:''' Створена вами сторінка порожня.\nЯкщо Ви знову натиснете «{{int:savearticle}}», сторінку буде створено без вмісту.",
+       "anoneditwarning": "'''Увага''': Ви не увійшли до системи. До історії змін цієї сторінки буде записана ваша IP-адреса.",
        "anonpreviewwarning": "''Ви не увійшли в систему. Якщо ви виконаєте збереження, то в історію сторінки буде записана ваша IP-адреса.''",
        "missingsummary": "'''Нагадування''': Ви не дали короткого опису змін.\nНатиснувши кнопку «Зберегти» ще раз, ви збережете зміни без коментаря.",
        "missingcommenttext": "Будь ласка, введіть нижче ваше повідомлення.",
        "subject-preview": "Заголовок буде:",
        "blockedtitle": "Користувача заблоковано",
        "blockedtext": "'''Ваш обліковий запис або IP-адреса заблоковані.'''\n\nБлокування виконане адміністратором $1.\nЗазначена наступна причина: ''$2''.\n\n* Початок блокування: $8\n* Закінчення блокування: $6\n* Блокування виконав: $7\n\nВи можете надіслати листа користувачеві $1 або будь-якому іншому [[{{MediaWiki:Grouppage-sysop}}|адміністратору]], щоб обговорити блокування.\n\nЗверніть увагу, що ви не зможете надіслати листа адміністратору, якщо ви не зареєстровані або не підтвердили свою електронну адресу в [[Special:Preferences|особистих налаштуваннях]], а також якщо вам було заборонено надсилати листи при блокуванні.\n\nВаша поточна IP-адреса — $3, ідентифікатор блокування — #$5. Будь ласка, зазначайте ці дані у своїх запитах.",
-       "autoblockedtext": "Ваша IP-адреса автоматично заблокована у зв'язку з тим, що вона раніше використовувалася кимось із заблокованих користувачів. Адміністратор ($1), що її заблокував, зазначив наступну причину блокування:\n\n:''$2''\n\n* Початок блокування: $8\n* Закінчення блокування: $6\n* Був заблокований: $7\n\nВи можете надіслати листа користувачеві $1 або будь-якому іншому [[{{MediaWiki:Grouppage-sysop}}|адміністратору]], щоб обговорити блокування.\n\nЗверніть увагу, що ви не зможете надіслати листа адміністраторові, якщо ви не зареєстровані у проекті або не підтвердили свою електронну адресу в [[Special:Preferences|особистих налаштуваннях]], а також якщо вам було заборонено надсилати листи при блокуванні.\n\nВаша поточна IP-адреса — $3, ідентифікатор блокування — #$5. Будь ласка, зазначайте його у своїх запитах.",
+       "autoblockedtext": "Ваша IP-адреса автоматично заблокована у зв'язку з тим, що вона раніше використовувалася кимось із заблокованих користувачів. Адміністратор ($1), що її заблокував, зазначив наступну причину блокування:\n\n:''$2''\n\n* Початок блокування: $8\n* Закінчення блокування: $6\n* Блокування виконав: $7\n\nВи можете надіслати листа користувачеві $1 або будь-якому іншому [[{{MediaWiki:Grouppage-sysop}}|адміністратору]], щоб обговорити блокування.\n\nЗверніть увагу, що ви не зможете надіслати листа адміністраторові, якщо ви не зареєстровані у проекті або не підтвердили свою електронну адресу в [[Special:Preferences|особистих налаштуваннях]], а також якщо вам було заборонено надсилати листи при блокуванні.\n\nВаша поточна IP-адреса — $3, ідентифікатор блокування — #$5. Будь ласка, зазначайте його у своїх запитах.",
        "blockednoreason": "не вказано причини",
        "whitelistedittext": "Ви повинні $1 щоб редагувати сторінки.",
-       "confirmedittext": "Ð\92и Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ\96 Ð¿Ñ\96дÑ\82веÑ\80диÑ\82и Ð²Ð°Ñ\88Ñ\83 Ð°Ð´Ñ\80еÑ\81Ñ\83 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ð¿ÐµÑ\80ед Ñ\80едагÑ\83ваннÑ\8fм Ñ\81Ñ\82оÑ\80Ñ\96нок.\nÐ\91Ñ\83дÑ\8c-лаÑ\81ка Ð·Ð°Ð·Ð½Ð°Ñ\87Ñ\82е і підтвердіть вашу електронну адресу на [[Special:Preferences|сторінці налаштувань]].",
+       "confirmedittext": "Ð\92и Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ\96 Ð¿Ñ\96дÑ\82веÑ\80диÑ\82и Ð²Ð°Ñ\88Ñ\83 Ð°Ð´Ñ\80еÑ\81Ñ\83 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ð¿ÐµÑ\80ед Ñ\80едагÑ\83ваннÑ\8fм Ñ\81Ñ\82оÑ\80Ñ\96нок.\nÐ\91Ñ\83дÑ\8c-лаÑ\81ка Ð²ÐºÐ°Ð¶Ñ\96Ñ\82Ñ\8c і підтвердіть вашу електронну адресу на [[Special:Preferences|сторінці налаштувань]].",
        "nosuchsectiontitle": "Не вдається знайти розділ",
        "nosuchsectiontext": "Ви намагаєтесь редагувати розділ, якого не існує.\nМожливо, він був перейменований або вилучений, поки ви переглядали сторінку.",
        "loginreqtitle": "Необхідно ввійти до системи",
        "loginreqlink": "ввійти в систему",
-       "loginreqpagetext": "Ð\92и Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ\96 $1, Ñ\89об Ð¿ÐµÑ\80еглÑ\8fнÑ\83ти інші сторінки.",
+       "loginreqpagetext": "Ð\92и Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ\96 $1, Ñ\89об Ð¿ÐµÑ\80еглÑ\8fдати інші сторінки.",
        "accmailtitle": "Пароль надіслано.",
        "accmailtext": "Пароль для користувача [[User talk:$1|$1]], згенерований випадковим чином, надісланий на адресу $2.\nПісля реєстрації в системі ви зможете ''[[Special:ChangePassword|змінити пароль]]''.",
        "newarticle": "(Нова)",
        "newarticletext": "Ви перейшли на сторінку, яка поки що не існує.\n\nЩоб створити нову сторінку, наберіть текст у вікні нижче (див. [$1 довідкову статтю], щоб отримати більше інформації).\nЯкщо ви опинились тут помилково, просто натисніть кнопку браузера '''назад'''.",
-       "anontalkpagetext": "----''Це сторінка обговорення анонімного користувача, який ще не зареєструвався або не скористався зареєстрованим обліковим записом.\nТому ми вимушені використовувати IP-адресу для його ідентифікації.\nОдна IP-адреса може використовуватися декількома користувачами.\nЯкщо ви — анонімний користувач і вважаєте, що отримали коментарі, адресовані не вам, будь ласка [[Special:UserLogin/signup|зареєструйтесь]] або [[Special:UserLogin|увійдіть до системи]], щоб у майбутньому уникнути можливої плутанини з іншими анонімними користувачами.''",
+       "anontalkpagetext": "----''Це сторінка обговорення анонімного користувача, який ще не зареєструвався або не скористався зареєстрованим обліковим записом.''\nТому ми вимушені використовувати IP-адресу для його ідентифікації.\nОдна IP-адреса може використовуватись кількома користувачами.\nЯкщо ви — анонімний користувач і вважаєте, що отримали коментарі, адресовані не вам, будь ласка [[Special:UserLogin/signup|зареєструйтесь]] або [[Special:UserLogin|увійдіть до системи]], щоб у майбутньому уникнути можливої плутанини з іншими анонімними користувачами.",
        "noarticletext": "Зараз на цій сторінці нема тексту.\nВи можете [[Special:Search/{{PAGENAME}}|пошукати цю назву]] на інших сторінках,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} пошукати в журналах]\nабо [{{fullurl:{{FULLPAGENAME}}|action=edit}} створити сторінку з такою назвою]</span>.",
        "noarticletext-nopermission": "Зараз на цій сторінці немає тексту.\nВи можете [[Special:Search/{{PAGENAME}}|пошукати цю назву]] на інших сторінках,\nабо <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} пошукати пов'язані записи в журналах]</span>, але ви не маєте дозволу на створення такої сторінки.",
        "missing-revision": "Версія #$1 сторінки «{{FULLPAGENAME}}» не існує.\n\nІмовірно, Ви перейшли за застарілим посиланням на вилучену сторінку.\nПодробиці можна дізнатися з [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журналу вилучень].",
        "usercssyoucanpreview": "'''Підказка:''' використовуйте кнопку «{{int:showpreview}}», щоб протестувати ваш новий css-файл перед збереженням.",
        "userjsyoucanpreview": "'''Підказка:''' використовуйте кнопку «{{int:showpreview}}», щоб протестувати ваш новий код JavaScript перед збереженням.",
        "usercsspreview": "'''Пам'ятайте, що це лише попередній перегляд вашого css-файлу.'''\n'''Його ще не збережено!'''",
-       "userjspreview": "'''Ð\9fам'Ñ\8fÑ\82айÑ\82е, Ñ\89о Ñ\86е Ñ\82Ñ\96лÑ\8cки Ð¿Ð¾Ð¿ÐµÑ\80еднÑ\96й Ð¿ÐµÑ\80еглÑ\8fд Ð²Ð°Ñ\88ого JavaScript-Ñ\84айлÑ\83 Ñ\96 Ð¿Ð¾ÐºÐ¸ Ð²Ñ\96н Ñ\89е не збережений!'''",
+       "userjspreview": "'''Ð\9fам'Ñ\8fÑ\82айÑ\82е, Ñ\89о Ñ\86е Ñ\82Ñ\96лÑ\8cки Ð¿Ð¾Ð¿ÐµÑ\80еднÑ\96й Ð¿ÐµÑ\80еглÑ\8fд Ð²Ð°Ñ\88ого JavaScript-Ñ\84айлÑ\83 Ñ\96 Ð²Ñ\96н Ð¿Ð¾ÐºÐ¸-Ñ\89о не збережений!'''",
        "sitecsspreview": "'''Пам'ятайте, що це тільки попередній перегляд цього CSS.'''\n'''Його ще не збережено!'''",
        "sitejspreview": "'''Пам'ятайте, що це лише попередній перегляд вашого JavaScript-коду.'''\n'''Його ще не збережено!'''",
        "userinvalidcssjstitle": "'''Увага:''' тема оформлення «$1» не знайдена.\nПам'ятайте, що користувацькі .css та .js сторінки повинні мати назву, що складається лише з малих літер, наприклад «{{ns:user}}:Хтось/vector.css», а не «{{ns:user}}:Хтось/Vector.css».",
        "note": "'''Зауваження:'''",
        "previewnote": "'''Це лише попередній перегляд.'''\nВаші зміни ще не збережено!",
        "continue-editing": "Продовжити редагування",
-       "previewconflict": "Цей попередній перегляд відображає текст з верхнього вікна редагування так, як він буде виглядіти, якщо ви вирішите зберегти його.",
-       "session_fail_preview": "'''Система не може зберегти ваші редагування, оскільки втрачені дані сеансу. Будь ласка, повторіть вашу спробу.\nЯкщо помилка буде повторюватись, спробуйте [[Special:UserLogout|вийти з системи]] і зайти знову.'''",
-       "session_fail_preview_html": "<strong>Ð\92ибаÑ\87Ñ\82е! Ð\9dеможливо Ð·Ð±ÐµÑ\80егÑ\82и Ð²Ð°Ñ\88Ñ\96 Ð·Ð¼Ñ\96ни Ñ\87еÑ\80ез Ð²Ñ\82Ñ\80аÑ\82Ñ\83 Ð´Ð°Ð½Ð¸Ñ\85 HTML-Ñ\81еÑ\81Ñ\96Ñ\97.</strong>\n\n''Ð\9eÑ\81кÑ\96лÑ\8cки {{SITENAME}} Ð´Ð¾Ð·Ð²Ð¾Ð»Ñ\8fÑ\94 Ð²Ð¸ÐºÐ¾Ñ\80иÑ\81Ñ\82овÑ\83ваÑ\82и Ñ\87иÑ\81Ñ\82ий HTML, Ð¿Ð¾Ð¿ÐµÑ\80еднÑ\96й Ð¿ÐµÑ\80еглÑ\8fд Ð²Ñ\96дклÑ\8eÑ\87ено, Ñ\89об Ð¿Ð¾Ð¿ÐµÑ\80едиÑ\82и JavaScript-аÑ\82аки.''\n\n<strong>ЯкÑ\89о Ñ\86е Ð´Ð¾Ð±Ñ\80оÑ\8fкÑ\96Ñ\81на спроба редагування, будь ласка, спробуйте ще раз. Якщо не вийде знову, - спробуйте [[Special:UserLogout|завершити сеанс роботи]] й ще раз ввійти до системи.</strong>",
-       "token_suffix_mismatch": "'''Ваше редагування було відхилене, оскільки ваша програма не правильно обробляє знаки пунктуації у вікні редагування. Редагування було скасоване для запобігання спотворенню тексту статті.\nПодібні проблеми можуть виникати при використанні анонімізуючих веб-проксі, що містять помилки.'''",
-       "edit_form_incomplete": "'''Частина даних із форми редагування не досягла сервера. Уважно перевірте чи не пошкоджено ваших правок і спробуйте ще раз.'''",
+       "previewconflict": "Цей попередній перегляд відображає текст з верхнього вікна редагування так, як він буде виглядати, якщо ви вирішите зберегти його.",
+       "session_fail_preview": "'''Система не може зберегти ваші редагування, оскільки втрачені дані сеансу. Будь ласка, повторіть вашу спробу.\nЯкщо помилка буде повторюватись, спробуйте [[Special:UserLogout|вийти з системи]] і увійти знову.'''",
+       "session_fail_preview_html": "<strong>Ð\92ибаÑ\87Ñ\82е! Ð\9dеможливо Ð·Ð±ÐµÑ\80егÑ\82и Ð²Ð°Ñ\88Ñ\96 Ð·Ð¼Ñ\96ни Ñ\87еÑ\80ез Ð²Ñ\82Ñ\80аÑ\82Ñ\83 Ð´Ð°Ð½Ð¸Ñ\85 HTML-Ñ\81еÑ\81Ñ\96Ñ\97.</strong>\n\n''Ð\9eÑ\81кÑ\96лÑ\8cки {{SITENAME}} Ð´Ð¾Ð·Ð²Ð¾Ð»Ñ\8fÑ\94 Ð²Ð¸ÐºÐ¾Ñ\80иÑ\81Ñ\82овÑ\83ваÑ\82и Ñ\87иÑ\81Ñ\82ий HTML, Ð¿Ð¾Ð¿ÐµÑ\80еднÑ\96й Ð¿ÐµÑ\80еглÑ\8fд Ð²Ñ\96дклÑ\8eÑ\87ено, Ñ\89об Ð¿Ð¾Ð¿ÐµÑ\80едиÑ\82и JavaScript-аÑ\82аки.''\n\n<strong>ЯкÑ\89о Ñ\86е Ð»ÐµÐ³Ñ\96Ñ\82имна спроба редагування, будь ласка, спробуйте ще раз. Якщо не вийде знову, - спробуйте [[Special:UserLogout|завершити сеанс роботи]] й ще раз ввійти до системи.</strong>",
+       "token_suffix_mismatch": "'''Ваше редагування було відхилене, оскільки ваша програма неправильно обробляє знаки пунктуації у вікні редагування. Редагування було скасоване для запобігання спотворенню тексту статті.\nПодібні проблеми можуть виникати при використанні анонімізуючих веб-проксі, що містять помилки.'''",
+       "edit_form_incomplete": "'''Частина даних із форми редагування не досягла сервера. Уважно перевірте, чи не пошкоджені ваші правки і спробуйте ще раз.'''",
        "editing": "Редагування $1",
        "creating": "Створення $1",
        "editingsection": "Редагування $1 (розділ)",
        "editingcomment": "Редагування $1 (новий розділ)",
        "editconflict": "Конфлікт редагування: $1",
-       "explainconflict": "Ще Ñ\85Ñ\82оÑ\81Ñ\8c Ð·Ð¼Ñ\96нив Ñ\86Ñ\8e Ñ\81Ñ\82оÑ\80Ñ\96нкÑ\83 Ð· Ñ\82ого Ñ\87аÑ\81Ñ\83, Ñ\8fк Ð²Ð¸ Ñ\80озпоÑ\87али Ñ\97Ñ\97 Ð·Ð¼Ñ\96нÑ\8eваÑ\82и.\nУ Ð²ÐµÑ\80Ñ\85нÑ\8cомÑ\83 Ð²Ñ\96кнÑ\96 Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ð¾ Ð¿Ð¾Ñ\82оÑ\87ний Ñ\82екÑ\81Ñ\82 Ñ\81Ñ\82оÑ\80Ñ\96нки.\nÐ\92аÑ\88Ñ\96 Ð·Ð¼Ñ\96ни Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ñ\96 Ð² Ð½Ð¸Ð¶Ð½Ñ\8cомÑ\83 Ð²Ñ\96кнÑ\96.\nÐ\92ам Ð½ÐµÐ¾Ð±Ñ\85Ñ\96дно Ð¿ÐµÑ\80енеÑ\81Ñ\82и Ð²Ð°Ñ\88Ñ\96 Ð·Ð¼Ñ\96ни Ð² Ñ\96Ñ\81нÑ\83Ñ\8eÑ\87ий Ñ\82екÑ\81Ñ\82.\nЯкÑ\89о Ð²Ð¸ Ð½Ð°Ñ\82иÑ\81неÑ\82е Â«{{int:savearticle}}», Ñ\82о Ð±Ñ\83де Ð·Ð±ÐµÑ\80ежено '''Ñ\82Ñ\96лÑ\8cки''' Ñ\82екÑ\81Ñ\82 Ñ\83 Ð²ÐµÑ\80Ñ\85нÑ\8cомÑ\83 Ð²Ñ\96кнÑ\96 редагування.",
+       "explainconflict": "Ще Ñ\85Ñ\82оÑ\81Ñ\8c Ð·Ð¼Ñ\96нив Ñ\86Ñ\8e Ñ\81Ñ\82оÑ\80Ñ\96нкÑ\83 Ð· Ñ\82ого Ñ\87аÑ\81Ñ\83, Ñ\8fк Ð²Ð¸ Ñ\80озпоÑ\87али Ñ\97Ñ\97 Ð¿Ñ\80авиÑ\82и.\nУ Ð²ÐµÑ\80Ñ\85нÑ\8cомÑ\83 Ð²Ñ\96кнÑ\96 Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ð¾ Ð¿Ð¾Ñ\82оÑ\87ний Ñ\82екÑ\81Ñ\82 Ñ\81Ñ\82оÑ\80Ñ\96нки.\nÐ\92аÑ\88Ñ\96 Ð·Ð¼Ñ\96ни Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ñ\96 Ð² Ð½Ð¸Ð¶Ð½Ñ\8cомÑ\83 Ð²Ñ\96кнÑ\96.\nÐ\92ам Ð½ÐµÐ¾Ð±Ñ\85Ñ\96дно Ð¿ÐµÑ\80енеÑ\81Ñ\82и Ð²Ð°Ñ\88Ñ\96 Ð·Ð¼Ñ\96ни Ð² Ñ\96Ñ\81нÑ\83Ñ\8eÑ\87ий Ñ\82екÑ\81Ñ\82.\nЯкÑ\89о Ð²Ð¸ Ð½Ð°Ñ\82иÑ\81неÑ\82е Â«{{int:savearticle}}», Ñ\82о Ð±Ñ\83де Ð·Ð±ÐµÑ\80ежено '''лиÑ\88е''' Ñ\82екÑ\81Ñ\82 Ð· Ð²ÐµÑ\80Ñ\85нÑ\8cого Ð²Ñ\96кна редагування.",
        "yourtext": "Ваш текст",
        "storedversion": "Збережена версія",
-       "nonunicodebrowser": "'''Ð\9fÐ\9eÐ\9fÐ\95РÐ\95Ð\94Ð\96Ð\95Ð\9dÐ\9dЯ: Ð\92аÑ\88 [[бÑ\80аÑ\83зеÑ\80]] Ð½Ðµ Ð¿Ñ\96дÑ\82Ñ\80имÑ\83Ñ\94 [[ЮнÑ\96код]].''' \nЩоб Ð¿Ð¾Ð´Ð¾Ð»Ð°Ñ\82и Ñ\86е Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ\8f Ñ\82а Ð´Ð¾Ð·Ð²Ð¾Ð»Ð¸Ñ\82и Ð\92ам безпечно редагувати сторінки, усі не-ASCII символи буде показано їх шістнадцятковими кодами.",
-       "editingold": "'''Ð\9fÐ\9eÐ\9fÐ\95РÐ\95Ð\94Ð\96Ð\95Ð\9dÐ\9dЯ: Ви редагуєте застарілу версію даної статті.\nЯкщо ви збережете її, будь-які редагування, зроблені між версіями, будуть втрачені.'''",
+       "nonunicodebrowser": "'''Ð\9fопеÑ\80едженнÑ\8f: Ð\92аÑ\88 Ð±Ñ\80аÑ\83зеÑ\80 Ð½Ðµ Ð¿Ñ\96дÑ\82Ñ\80имÑ\83Ñ\94 Ð®Ð½Ñ\96код.''' \nЩоб Ð¿Ð¾Ð´Ð¾Ð»Ð°Ñ\82и Ñ\86е Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ\8f Ñ\82а Ð´Ð¾Ð·Ð²Ð¾Ð»Ð¸Ñ\82и Ð²ам безпечно редагувати сторінки, усі не-ASCII символи буде показано їх шістнадцятковими кодами.",
+       "editingold": "'''Ð\9fопеÑ\80едженнÑ\8f: Ви редагуєте застарілу версію даної статті.\nЯкщо ви збережете її, будь-які редагування, зроблені між версіями, будуть втрачені.'''",
        "yourdiff": "Відмінності",
-       "copyrightwarning": "Ð\97веÑ\80нÑ\96Ñ\82Ñ\8c Ñ\83вагÑ\83, Ñ\89о Ð±Ñ\83дÑ\8c\8fкÑ\96 Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ\8f Ñ\96 Ð·Ð¼Ñ\96ни Ð´Ð¾ {{grammar:genitive|{{SITENAME}}}} Ñ\80озглÑ\8fдаÑ\8eÑ\82Ñ\8cÑ\81Ñ\8f Ñ\8fк Ð²Ð¸Ð¿Ñ\83Ñ\89енÑ\96 Ð½Ð° Ñ\83моваÑ\85 Ð»Ñ\96Ñ\86ензÑ\96Ñ\97 $2 (див. $1).\nЯкÑ\89о Ð²Ð¸ Ð½Ðµ Ð±Ð°Ð¶Ð°Ñ\94Ñ\82е, Ñ\89об Ð½Ð°Ð¿Ð¸Ñ\81ане Ð²Ð°Ð¼Ð¸ Ð±ÐµÐ·Ð¶Ð°Ð»Ñ\96Ñ\81но Ñ\80едагÑ\83валоÑ\81Ñ\8c Ñ\96 Ñ\80озповÑ\81Ñ\8eджÑ\83валоÑ\81Ñ\8f Ð·Ð° Ð±Ð°Ð¶Ð°Ð½Ð½Ñ\8fм Ð±Ñ\83дÑ\8c-кого, Ð½Ðµ Ð¿Ð¸Ñ\88Ñ\96Ñ\82Ñ\8c Ñ\82Ñ\83Ñ\82.<br />\nÐ\92и Ñ\82акож Ð¿Ñ\96дÑ\82веÑ\80джÑ\83Ñ\94Ñ\82е, Ñ\89о Ð½Ð°Ð¿Ð¸Ñ\81ане Ð²Ð°Ð¼Ð¸ Ñ\82Ñ\83Ñ\82 Ð½Ð°Ð»ÐµÐ¶Ð¸Ñ\82Ñ\8c Ð²Ð°Ð¼ Ð°Ð±Ð¾ Ð²Ð·Ñ\8fÑ\82е Ð· Ð´Ð¶ÐµÑ\80ела, Ñ\89о Ñ\94 Ñ\81Ñ\83Ñ\81пÑ\96лÑ\8cним Ð½Ð°Ð´Ð±Ð°Ð½Ð½Ñ\8fм Ñ\87и Ð¿Ð¾Ð´Ñ\96бним Ð²Ñ\96лÑ\8cним Ð´Ð¶ÐµÑ\80елом.\n'''Ð\9dÐ\95 Ð\9fУÐ\91Ð\9bÐ\86Ð\9aУÐ\99ТÐ\95 Ð¢Ð£Ð¢ Ð\91Ð\95Ð\97 Ð\94Ð\9eÐ\97Ð\92Ð\9eÐ\9bУ Ð\9cÐ\90ТÐ\95РÐ\86Ð\90Ð\9bÐ\98, Ð©Ð\9e Ð\9eÐ¥Ð\9eРÐ\9eÐ\9dЯЮТЬСЯ Ð\90Ð\92ТÐ\9eРСЬÐ\9aÐ\98Ð\9c Ð\9fРÐ\90Ð\92Ð\9eÐ\9c!'''",
-       "copyrightwarning2": "Ð\91Ñ\83дÑ\8c Ð»Ð°Ñ\81ка, Ð·Ð²ÐµÑ\80нÑ\96Ñ\82Ñ\8c Ñ\83вагÑ\83, Ñ\89о Ð²Ñ\81Ñ\96 Ð²Ð½ÐµÑ\81енÑ\96 Ð²Ð°Ð¼Ð¸ Ð·Ð¼Ñ\96ни Ð¼Ð¾Ð¶Ñ\83Ñ\82Ñ\8c Ñ\80едагÑ\83ваÑ\82иÑ\81Ñ\8f, Ð´Ð¾Ð¿Ð¾Ð²Ð½Ñ\8eваÑ\82иÑ\81Ñ\8f Ð°Ð±Ð¾ Ð²Ð¸Ð»Ñ\83Ñ\87аÑ\82иÑ\81Ñ\8f Ñ\96нÑ\88ими ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87ами.\nЯкÑ\89о Ð²Ð¸ Ð½Ðµ Ð±Ð°Ð¶Ð°Ñ\94Ñ\82е, Ñ\89об Ð½Ð°Ð¿Ð¸Ñ\81ане Ð²Ð°Ð¼Ð¸ Ð±ÐµÐ·Ð¶Ð°Ð»Ñ\96Ñ\81но Ñ\80едагÑ\83валоÑ\81Ñ\8c â\80\94 Ð½Ðµ Ð¿Ð¸Ñ\88Ñ\96Ñ\82Ñ\8c Ñ\82Ñ\83Ñ\82.<br />\nÐ\92и Ñ\82акож Ð·Ð¾Ð±Ð¾Ð²'Ñ\8fзÑ\83Ñ\94Ñ\82еÑ\81Ñ\8c, Ñ\89о Ð½Ð°Ð¿Ð¸Ñ\81ане Ð²Ð°Ð¼Ð¸ Ñ\82Ñ\83Ñ\82 Ð½Ð°Ð»ÐµÐ¶Ð¸Ñ\82Ñ\8c Ð²Ð°Ð¼ Ð°Ð±Ð¾ Ð²Ð·Ñ\8fÑ\82е Ð· Ð´Ð¶ÐµÑ\80ела, Ñ\89о Ñ\94 Ñ\81Ñ\83Ñ\81пÑ\96лÑ\8cним Ð½Ð°Ð´Ð±Ð°Ð½Ð½Ñ\8fм, Ð°Ð±Ð¾ Ð¿Ð¾Ð´Ñ\96бного Ð²Ñ\96лÑ\8cного Ð´Ð¶ÐµÑ\80ела (див. $1).<br />\n'''Ð\9dÐ\95 Ð\9fУÐ\91Ð\9bÐ\86Ð\9aУÐ\99ТÐ\95 Ð¢Ð£Ð¢ Ð\91Ð\95Ð\97 Ð\94Ð\9eÐ\97Ð\92Ð\9eÐ\9bУ Ð\9cÐ\90ТÐ\95РÐ\86Ð\90Ð\9bÐ\98, Ð©Ð\9e Ð\84 Ð\9eÐ\91\84Ð\9aТÐ\9eÐ\9c Ð\90Ð\92ТÐ\9eРСЬÐ\9aÐ\9eÐ\93Ð\9e Ð\9fРÐ\90Ð\92Ð\90!'''",
-       "longpageerror": "'''Ð\9fомилка: Ð¢ÐµÐºÑ\81Ñ\82, Ñ\89о Ð²Ð¸ Ð½Ð°Ð´Ñ\96Ñ\81лали Ð·Ð°Ð¹Ð¼Ð°Ñ\94 $1 {{PLURAL:$1|кÑ\96лобайÑ\82|кÑ\96лобайÑ\82и|кÑ\96лобайÑ\82Ñ\96в}}, Ñ\89о Ð±Ñ\96лÑ\8cÑ\88е Ð·Ð° Ð²Ñ\81Ñ\82ановленÑ\83 Ð¼ÐµÐ¶Ñ\83 Ñ\83 $2 {{PLURAL:$2|кілобайт|кілобайти|кілобайтів}}.'''\nЙого неможливо зберегти.",
-       "readonlywarning": "'''Ð\9fÐ\9eÐ\9fÐ\95РÐ\95Ð\94Ð\96Ð\95Ð\9dÐ\9dЯ: Ð\91аза Ð´Ð°Ð½Ð¸Ñ\85 Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð° Ð² Ð·Ð²'Ñ\8fзкÑ\83 Ð· Ð¿Ñ\80оÑ\86едÑ\83Ñ\80ами Ð¾Ð±Ñ\81лÑ\83говÑ\83ваннÑ\8f,\nÑ\82омÑ\83, Ð½Ð° Ð´Ð°Ð½Ð¸Ð¹ Ð¼Ð¾Ð¼ÐµÐ½Ñ\82, Ð²Ð¸ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82е Ð·Ð°Ð¿Ð¸Ñ\81аÑ\82и Ð²Ð°Ñ\88Ñ\96 Ð·Ð¼Ñ\96ни.\nÐ\9cожливо, Ð²Ð°Ð¼ Ð²Ð°Ñ\80Ñ\82о Ð·Ð±ÐµÑ\80егÑ\82и Ñ\82екÑ\81Ñ\82 Ð² Ð»Ð¾ÐºÐ°Ð»Ñ\8cний Ñ\84айл (на Ñ\81воÑ\94мÑ\83 Ð´Ð¸Ñ\81кÑ\83) Ð¹ Ð·Ð±ÐµÑ\80егÑ\82и Ð¹Ð¾Ð³Ð¾ пізніше.'''\n\nАдміністратор, що заблокував базу даних, залишив наступне пояснення: $1",
+       "copyrightwarning": "Ð\97веÑ\80нÑ\96Ñ\82Ñ\8c Ñ\83вагÑ\83, Ñ\89о Ð±Ñ\83дÑ\8c\8fкÑ\96 Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ\8f Ñ\96 Ð·Ð¼Ñ\96ни Ð´Ð¾ {{grammar:genitive|{{SITENAME}}}} Ñ\80озглÑ\8fдаÑ\8eÑ\82Ñ\8cÑ\81Ñ\8f Ñ\8fк Ð²Ð¸Ð¿Ñ\83Ñ\89енÑ\96 Ð½Ð° Ñ\83моваÑ\85 Ð»Ñ\96Ñ\86ензÑ\96Ñ\97 $2 (деÑ\82алÑ\8cнÑ\96Ñ\88е Ð´Ð¸Ð². $1).\nЯкÑ\89о Ð²Ð¸ Ð½Ðµ Ð±Ð°Ð¶Ð°Ñ\94Ñ\82е, Ñ\89об Ð½Ð°Ð¿Ð¸Ñ\81ане Ð²Ð°Ð¼Ð¸ Ð±ÐµÐ·Ð¶Ð°Ð»Ñ\8cно Ñ\80едагÑ\83валоÑ\81Ñ\8c Ñ\96 Ñ\80озповÑ\81Ñ\8eджÑ\83валоÑ\81Ñ\8f Ð·Ð° Ð±Ð°Ð¶Ð°Ð½Ð½Ñ\8fм Ð±Ñ\83дÑ\8c-кого, Ð½Ðµ Ð¿Ð¸Ñ\88Ñ\96Ñ\82Ñ\8c Ñ\82Ñ\83Ñ\82.<br />\nÐ\92и Ñ\82акож Ð¿Ñ\96дÑ\82веÑ\80джÑ\83Ñ\94Ñ\82е, Ñ\89о Ð½Ð°Ð¿Ð¸Ñ\81ане Ð²Ð°Ð¼Ð¸ Ñ\82Ñ\83Ñ\82 Ð½Ð°Ð»ÐµÐ¶Ð¸Ñ\82Ñ\8c Ð²Ð°Ð¼ Ð°Ð±Ð¾ Ð²Ð·Ñ\8fÑ\82е Ð· Ð´Ð¶ÐµÑ\80ела, Ñ\89о Ñ\94 Ñ\81Ñ\83Ñ\81пÑ\96лÑ\8cним Ð½Ð°Ð´Ð±Ð°Ð½Ð½Ñ\8fм Ñ\87и Ð¿Ð¾Ð´Ñ\96бного Ð²Ñ\96лÑ\8cного Ð´Ð¶ÐµÑ\80ела.\n'''Ð\9dе Ð¿Ñ\83блÑ\96кÑ\83йÑ\82е Ñ\82Ñ\83Ñ\82 Ð±ÐµÐ· Ð´Ð¾Ð·Ð²Ð¾Ð»Ñ\83 Ð¼Ð°Ñ\82еÑ\80Ñ\96али, Ð·Ð°Ñ\85иÑ\89енÑ\96 Ð°Ð²Ñ\82оÑ\80Ñ\81Ñ\8cким Ð¿Ñ\80авом!'''",
+       "copyrightwarning2": "Ð\91Ñ\83дÑ\8c Ð»Ð°Ñ\81ка, Ð·Ð²ÐµÑ\80нÑ\96Ñ\82Ñ\8c Ñ\83вагÑ\83, Ñ\89о Ð²Ñ\81Ñ\96 Ð·Ð¼Ñ\96ни, Ð²Ð½ÐµÑ\81енÑ\96 Ð²Ð°Ð¼Ð¸ Ð´Ð¾ {{SITENAME}}, Ð¼Ð¾Ð¶Ñ\83Ñ\82Ñ\8c Ñ\80едагÑ\83ваÑ\82иÑ\81Ñ\8f, Ð´Ð¾Ð¿Ð¾Ð²Ð½Ñ\8eваÑ\82иÑ\81Ñ\8f Ð°Ð±Ð¾ Ð²Ð¸Ð»Ñ\83Ñ\87аÑ\82иÑ\81Ñ\8f Ñ\96нÑ\88ими ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87ами.\nЯкÑ\89о Ð²Ð¸ Ð½Ðµ Ð±Ð°Ð¶Ð°Ñ\94Ñ\82е, Ñ\89об Ð½Ð°Ð¿Ð¸Ñ\81ане Ð²Ð°Ð¼Ð¸ Ð±ÐµÐ·Ð¶Ð°Ð»Ñ\8cно Ñ\80едагÑ\83валоÑ\81Ñ\8c â\80\94 Ð½Ðµ Ð¿Ð¸Ñ\88Ñ\96Ñ\82Ñ\8c Ñ\82Ñ\83Ñ\82.<br />\nÐ\92и Ñ\82акож Ð¿Ñ\96дÑ\82веÑ\80джÑ\83Ñ\94Ñ\82е, Ñ\89о Ð½Ð°Ð²ÐµÐ´ÐµÐ½Ðµ Ñ\82Ñ\83Ñ\82 Ð½Ð°Ð¿Ð¸Ñ\81ано Ð²Ð°Ð¼Ð¸ Ð¾Ñ\81обиÑ\81Ñ\82о Ð°Ð±Ð¾ Ð·Ð°Ð¿Ð¾Ð·Ð¸Ñ\87ено Ð· Ð´Ð¶ÐµÑ\80ела, Ñ\8fке Ñ\94 Ñ\81Ñ\83Ñ\81пÑ\96лÑ\8cним Ð½Ð°Ð´Ð±Ð°Ð½Ð½Ñ\8fм, Ð°Ð±Ð¾ Ð¿Ð¾Ð´Ñ\96бного Ð²Ñ\96лÑ\8cного Ð´Ð¶ÐµÑ\80ела (див. $1).<br />\n'''Ð\9dе Ð¿Ñ\83блÑ\96кÑ\83йÑ\82е Ñ\82Ñ\83Ñ\82 Ð±ÐµÐ· Ð´Ð¾Ð·Ð²Ð¾Ð»Ñ\83 Ð¼Ð°Ñ\82еÑ\80Ñ\96али, Ð·Ð°Ñ\85иÑ\89енÑ\96 Ð°Ð²Ñ\82оÑ\80Ñ\81Ñ\8cким Ð¿Ñ\80авом!'''",
+       "longpageerror": "'''Ð\9fомилка: Ð\9fоданий Ð²Ð°Ð¼Ð¸ Ñ\82екÑ\81Ñ\82 Ñ\81Ñ\82ановиÑ\82Ñ\8c $1 {{PLURAL:$1|кÑ\96лобайÑ\82|кÑ\96лобайÑ\82и|кÑ\96лобайÑ\82Ñ\96в}}, Ñ\89о Ð±Ñ\96лÑ\8cÑ\88е Ð·Ð° Ð²Ñ\81Ñ\82ановленÑ\83 Ð¼ÐµÐ¶Ñ\83 Ñ\83 {{PLURAL:$2|кілобайт|кілобайти|кілобайтів}}.'''\nЙого неможливо зберегти.",
+       "readonlywarning": "'''Ð\9fопеÑ\80едженнÑ\8f: Ð\91аза Ð´Ð°Ð½Ð¸Ñ\85 Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð° Ð½Ð° Ð¾Ð±Ñ\81лÑ\83говÑ\83ваннÑ\8f, Ñ\82омÑ\83, Ð½Ð° Ð´Ð°Ð½Ð¸Ð¹ Ð¼Ð¾Ð¼ÐµÐ½Ñ\82, Ð²Ð¸ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82е Ð·Ð°Ð¿Ð¸Ñ\81аÑ\82и Ð²Ð°Ñ\88Ñ\96 Ð·Ð¼Ñ\96ни.\nÐ\9cожливо, Ð²Ð°Ð¼ Ð²Ð°Ñ\80Ñ\82о Ñ\81копÑ\96Ñ\8eваÑ\82и Ñ\82екÑ\81Ñ\82 Ñ\83 Ñ\84айл Ð½Ð° Ð²Ð°Ñ\88омÑ\83 ÐºÐ¾Ð¼Ð¿'Ñ\8eÑ\82еÑ\80Ñ\96 Ð¹ Ð·Ð±ÐµÑ\80егÑ\82и Ð¹Ð¾Ð³Ð¾ Ð½Ð° пізніше.'''\n\nАдміністратор, що заблокував базу даних, залишив наступне пояснення: $1",
        "protectedpagewarning": "'''Попередження: Ця сторінка була захищена від змін так, що тільки користувачі з правами адміністратора можуть її редагувати.'''\nОстанній запис журналу наведений нижче для довідки:",
        "semiprotectedpagewarning": "'''Зауваження:''' Ця сторінка захищена так, що її можуть редагувати тільки зареєстровані користувачі.\nОстанній запис журналу наведений нижче для довідки:",
        "cascadeprotectedwarning": "'''Попередження:''' Цю сторінку можуть редагувати лише користувачі з групи «Адміністратори», оскільки вона включена {{PLURAL:$1|1=до сторінки, для якої|до наступних сторінок, для яких}} активовано каскадний захист:",
        "titleprotectedwarning": "'''Попередження. Ця сторінка була захищена так, що для її створення потрібні [[Special:ListGroupRights|особливі права]].'''\nОстанній запис журналу наведений нижче для довідки:",
        "templatesused": "{{PLURAL:$1|1=Шаблон, використаний|Шаблони, використані}} на цій сторінці:",
        "templatesusedpreview": "{{PLURAL:$1|1=Шаблон, використаний|Шаблони, використані}} у цьому попередньому перегляді:",
-       "templatesusedsection": "{{PLURAL:$1|1=Шаблон, Ð²Ð¸ÐºÐ¾Ñ\80иÑ\81Ñ\82аний|Шаблони, Ð²Ð¸ÐºÐ¾Ñ\80иÑ\81Ñ\82анÑ\96}} Ñ\83 Ñ\86Ñ\96й Ñ\81екÑ\86Ñ\96Ñ\97:",
+       "templatesusedsection": "{{PLURAL:$1|1=Шаблон, Ð²Ð¸ÐºÐ¾Ñ\80иÑ\81Ñ\82аний|Шаблони, Ð²Ð¸ÐºÐ¾Ñ\80иÑ\81Ñ\82анÑ\96}} Ñ\83 Ñ\86Ñ\8cомÑ\83 Ñ\80оздÑ\96лÑ\96:",
        "template-protected": "(захищено)",
        "template-semiprotected": "(частково захищено)",
        "hiddencategories": "Ця сторінка належить до $1 {{PLURAL:$1|прихованої категорії|прихованих категорій|прихованих категорій}}:",
        "edittools": "<!-- Розміщений тут текст буде відображатися під формою редагування і формою завантаження. -->",
        "edittools-upload": "-",
-       "nocreatetext": "Ð\9dа Ñ\86Ñ\8cомÑ\83 Ñ\81айÑ\82Ñ\96 Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð¾ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ\96Ñ\81Ñ\82Ñ\8c Ñ\81Ñ\82воÑ\80еннÑ\8f Ð½Ð¾Ð²Ð¸Ñ\85 Ñ\81Ñ\82оÑ\80Ñ\96нок.\nÐ\92и Ð¼Ð¾Ð¶ÐµÑ\82е Ð¿Ð¾Ð²ÐµÑ\80нÑ\83Ñ\82Ñ\8cÑ\81Ñ\8f Ð½Ð°Ð·Ð°Ð´ Ð¹ змінити існуючу сторінку, [[Special:UserLogin|ввійти в систему, або створити новий обліковий запис]].",
+       "nocreatetext": "Ð\9dа Ñ\81айÑ\82Ñ\96 {{SITENAME}} Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð¾ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ\96Ñ\81Ñ\82Ñ\8c Ñ\81Ñ\82воÑ\80еннÑ\8f Ð½Ð¾Ð²Ð¸Ñ\85 Ñ\81Ñ\82оÑ\80Ñ\96нок.\nÐ\92и Ð¼Ð¾Ð¶ÐµÑ\82е Ð¿Ð¾Ð²ÐµÑ\80нÑ\83Ñ\82Ñ\8cÑ\81Ñ\8c Ð½Ð°Ð·Ð°Ð´ Ñ\96 змінити існуючу сторінку, [[Special:UserLogin|ввійти в систему, або створити новий обліковий запис]].",
        "nocreate-loggedin": "У вас нема дозволу створювати нові сторінки.",
        "sectioneditnotsupported-title": "Редагування окремих розділів не підтримується",
        "sectioneditnotsupported-text": "На цій сторінці не підтримується редагування окремих розділів",
        "permissionserrors": "Помилка доступу",
        "permissionserrorstext": "У вас нема прав на виконання цієї операції з {{PLURAL:$1|1=наступної причини|наступних причин}}:",
        "permissionserrorstext-withaction": "У вас нема дозволу на $2 з {{PLURAL:$1|1=такої причини|таких причин}}:",
-       "recreate-moveddeleted-warn": "'''Попередження: ви намагаєтеся створити сторінку, яка раніше вже була вилучена.'''\n\nПеревірте, чи справді вам потрібно знову створювати цю сторінку.\nНижче наведений журнал вилучень і перейменувань:",
+       "recreate-moveddeleted-warn": "'''Попередження: ви намагаєтеся створити сторінку, яка раніше вже була вилучена.'''\n\nПеревірте, чи справді вам справді потрібно створювати цю сторінку.\nНижче, для зручності, наведений журнал вилучень і перейменувань:",
        "moveddeleted-notice": "Ця сторінка була вилучена.\nДля довідки нижче наведені відповідні записи з журналів вилучень і перейменувань.",
        "log-fulllog": "Переглянути весь журнал",
        "edit-hook-aborted": "Редагування скасоване процедурою-перехоплювачем.\nДодаткові пояснення не наведені.",
        "postedit-confirmation-restored": "Сторінка була відновлена.",
        "postedit-confirmation-saved": "Ваше редагування збережено",
        "edit-already-exists": "Неможливо створити нову сторінку.\nВона вже існує.",
-       "defaultmessagetext": "ТекÑ\81Ñ\82 Â«Ð·Ð° Ð·Ð°Ð¼Ð¾Ð²Ñ\87Ñ\83ваннÑ\8f»",
-       "content-failed-to-parse": "Не вдалось проаналізувати $2 як тип $1: $3",
+       "defaultmessagetext": "СÑ\82андаÑ\80Ñ\82ний Ñ\82екÑ\81Ñ\82 Ð¿Ð¾Ð²Ñ\96домленнÑ\8f",
+       "content-failed-to-parse": "Не вдалось ідентифікувати $2 як тип $1 через: $3",
        "invalid-content-data": "Неприпустимі дані",
        "content-not-allowed-here": "Вміст «$1» недопустимий на сторінці [[$2]]",
        "editwarning-warning": "Перехід на іншу сторінку призведе до втрати ваших змін.\nЯкщо ви ввійшли до системи, то ви можете відключити це попередження в розділі \"{{int:prefs-editing}}\" ваших налаштувань.",
-       "editpage-notsupportedcontentformat-title": "Ð\9dепÑ\96дÑ\82Ñ\80имÑ\83ваний Ñ\84оÑ\80маÑ\82 Ð²Ð¼Ñ\96Ñ\81Ñ\82Ñ\83",
+       "editpage-notsupportedcontentformat-title": "ФоÑ\80маÑ\82 Ð²Ð¼Ñ\96Ñ\81Ñ\82Ñ\83 Ð½Ðµ Ð¿Ñ\96дÑ\82Ñ\80имÑ\83Ñ\94Ñ\82Ñ\8cÑ\81Ñ\8f",
        "editpage-notsupportedcontentformat-text": "Формат вмісту $1 не підтримується моделлю вмісту $2.",
        "content-model-wikitext": "вікітекст",
        "content-model-text": "звичайний текст",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
-       "expensive-parserfunction-warning": "Увага: Ця сторінка містить дуже багато викликів ресурсомістких функцій.\n\nКількість викликів не повинна перевищувати $2, зараз потрібно зробити $1 {{PLURAL:$1|виклик|виклики|викликів}}.",
+       "expensive-parserfunction-warning": "'''Увага:''' Ця сторінка містить дуже багато викликів ресурсомістких функцій.\n\nКількість викликів не повинна перевищувати $2, зараз потрібно зробити $1 {{PLURAL:$1|виклик|виклики|викликів}}.",
        "expensive-parserfunction-category": "Сторінки з дуже великою кількістю викликів ресурсомістких функцій",
-       "post-expand-template-inclusion-warning": "Увага: розмір шаблонів для включення занадто великий.\nДеякі шаблони не буде включено.",
+       "post-expand-template-inclusion-warning": "'''Увага:''' розмір шаблонів для включення занадто великий.\nДеякі шаблони не буде включено.",
        "post-expand-template-inclusion-category": "Сторінки з перевищеним розміром включених шаблонів",
-       "post-expand-template-argument-warning": "'''Увага:''' Ð¦Ñ\8f Ñ\81Ñ\82оÑ\80Ñ\96нка Ð¼Ñ\96Ñ\81Ñ\82иÑ\82Ñ\8c Ð¿Ñ\80инаймнÑ\96 Ð¾Ð´Ð¸Ð½ Ð°Ñ\80гÑ\83менÑ\82 Ñ\88аблонÑ\83, Ñ\8fкий Ð¼Ð°Ñ\94 Ð½Ð°Ð´Ñ\82о Ð²ÐµÐ»Ð¸ÐºÐ¸Ð¹ Ñ\80озмÑ\96Ñ\80 Ð´Ð»Ñ\8f Ñ\80озгоÑ\80Ñ\82аннÑ\8f.\nТакÑ\96 Ð°Ñ\80гÑ\83менÑ\82и Ð±Ñ\83ли Ð¾Ð¿Ñ\83Ñ\89ені.",
+       "post-expand-template-argument-warning": "'''Увага:''' Ð¦Ñ\8f Ñ\81Ñ\82оÑ\80Ñ\96нка Ð¼Ñ\96Ñ\81Ñ\82иÑ\82Ñ\8c Ð¿Ñ\80инаймнÑ\96 Ð¾Ð´Ð¸Ð½ Ð°Ñ\80гÑ\83менÑ\82 Ñ\88аблонÑ\83, Ñ\8fкий Ð¼Ð°Ñ\94 Ð½Ð°Ð´Ñ\82о Ð²ÐµÐ»Ð¸ÐºÐ¸Ð¹ Ñ\80озмÑ\96Ñ\80 Ð´Ð»Ñ\8f Ñ\80озгоÑ\80Ñ\82аннÑ\8f.\nЦÑ\96 Ð°Ñ\80гÑ\83менÑ\82и Ð±Ñ\83ли Ð¿Ñ\80оÑ\96гноÑ\80овані.",
        "post-expand-template-argument-category": "Сторінки, які містять пропущені аргументи шаблонів",
        "parser-template-loop-warning": "Виявлена петля у шаблонах: [[$1]]",
        "parser-template-recursion-depth-warning": "Перевищене обмеження глибини рекурсії шаблону ($1)",
        "language-converter-depth-warning": "Перевищене обмеження глибини мовного конвертора ($1)",
        "node-count-exceeded-category": "Сторінки, на яких перевищено лічильник вузлів",
-       "node-count-exceeded-category-desc": "Ð\9aаÑ\82егоÑ\80Ñ\96Ñ\8f Ð´Ð»Ñ\8f Ñ\81Ñ\82оÑ\80Ñ\96нок, Ð½Ð° Ñ\8fкиÑ\85 Ð¿ÐµÑ\80ебÑ\96лÑ\8cÑ\88ена кількість вузлів.",
+       "node-count-exceeded-category-desc": "Ð\9aаÑ\82егоÑ\80Ñ\96Ñ\8f Ð´Ð»Ñ\8f Ñ\81Ñ\82оÑ\80Ñ\96нок, Ð½Ð° Ñ\8fкиÑ\85 Ð¿ÐµÑ\80евиÑ\89ена кількість вузлів.",
        "node-count-exceeded-warning": "Кількість вузлів препроцесора на сторінці перевищила встановлену межу.",
        "expansion-depth-exceeded-category": "Сторінки, де перевищено глибину розгортання",
        "expansion-depth-exceeded-category-desc": "Це категорія для сторінок з перевищеною глибиною розкриття.",
        "converter-manual-rule-error": "Помилка в ручному правилі перетворення мови",
        "undo-success": "Редагування може бути скасовано.\nБудь ласка, перевірте порівняння нижче, щоб впевнитись, що це те, що ви хочете зробити, а потім збережіть зміни, щоб закінчити скасування редагування.",
        "undo-failure": "Неможливо скасувати редагування через несумісність проміжних змін.",
-       "undo-norev": "РедагÑ\83ваннÑ\8f Ð½Ðµ Ð¼Ð¾Ð¶Ðµ Ð±Ñ\83Ñ\82и Ñ\81каÑ\81оване, Ð±Ð¾ Ð²Ð¾Ð½Ð¾ Ð½Ðµ Ñ\96Ñ\81нÑ\83Ñ\94 Ð°Ð±Ð¾ Ð±Ñ\83ло Ð²Ð¸Ð»Ñ\83Ñ\87ене.",
-       "undo-nochange": "Схоже, редагування уже було скасовано.",
-       "undo-summary": "Скасування редагування № $1 користувача [[Special:Contributions/$2|$2]] ([[User talk:$2|обговорення]])",
-       "undo-summary-username-hidden": "Скасувати перевірку $1 прихованого користувача",
+       "undo-norev": "РедагÑ\83ваннÑ\8f Ð½Ðµ Ð¼Ð¾Ð¶Ðµ Ð±Ñ\83Ñ\82и Ñ\81каÑ\81оване, Ð±Ð¾ Ð¹Ð¾Ð³Ð¾ Ð½Ðµ Ñ\96Ñ\81нÑ\83Ñ\94 Ð°Ð±Ð¾ Ð±Ñ\83ло Ð²Ð¸Ð»Ñ\83Ñ\87ено.",
+       "undo-nochange": "Схоже, редагування вже було скасовано.",
+       "undo-summary": "Скасування редагування № $1 користувача [[Special:Contribs/$2|$2]] ([[User talk:$2|обговорення]])",
+       "undo-summary-username-hidden": "Скасувати правку $1, виконану прихованим користувачем",
        "cantcreateaccounttitle": "Неможливо створити обліковий запис",
        "cantcreateaccount-text": "Створення облікових записів із цієї IP-адреси ('''$1''') було заблоковане [[User:$3|користувачем $3]].\n\n$3 зазначив таку причину: ''$2''",
-       "cantcreateaccount-range-text": "СÑ\82воÑ\80еннÑ\8f Ð¾Ð±Ð»Ñ\96кового Ð·Ð°Ð¿Ð¸Ñ\81Ñ\83 Ñ\96з IP-адÑ\80еÑ\81 Ñ\83 Ð´Ñ\96апазонÑ\96  '''$1''', Ñ\8fкий Ð²ÐºÐ»Ñ\8eÑ\87аÑ\94 Ð²Ð°Ñ\88Ñ\83 IP-адÑ\80еÑ\81Ñ\83 ('''$4'''), Ð²Ð¶Ðµ заблоковано користувачем [[User:$3|$3]].\n\nКористувач $3 вказав як причину ''$2''",
+       "cantcreateaccount-range-text": "СÑ\82воÑ\80еннÑ\8f Ð¾Ð±Ð»Ñ\96кового Ð·Ð°Ð¿Ð¸Ñ\81Ñ\83 Ñ\96з IP-адÑ\80еÑ\81 Ñ\83 Ð´Ñ\96апазонÑ\96  '''$1''', Ñ\8fкий Ð²ÐºÐ»Ñ\8eÑ\87аÑ\94 Ð²Ð°Ñ\88Ñ\83 IP-адÑ\80еÑ\81Ñ\83 ('''$4'''), Ð±Ñ\83ло заблоковано користувачем [[User:$3|$3]].\n\nКористувач $3 вказав як причину ''$2''",
        "viewpagelogs": "Показати журнали для цієї сторінки",
        "nohistory": "Для цієї статті відсутній журнал редагувань.",
        "currentrev": "Поточна версія",
        "currentrevisionlink": "Поточна версія",
        "cur": "поточн.",
        "next": "наст.",
-       "last": "оÑ\81Ñ\82.",
+       "last": "попеÑ\80.",
        "page_first": "перша",
        "page_last": "остання",
-       "histlegend": "Пояснення: (поточн.) = відмінності від поточної версії,\n(ост.) = відмінності від попередньої версії, '''м''' = незначне редагування",
+       "histlegend": "Ð\92ибÑ\96Ñ\80 Ð²ÐµÑ\80Ñ\81Ñ\96Ñ\97: Ð\9fознаÑ\87Ñ\82е Ñ\83 ÐºÑ\80Ñ\83глиÑ\85 Ð²Ñ\96конÑ\86Ñ\8fÑ\85 Ð²ÐµÑ\80Ñ\81Ñ\96Ñ\97 Ð´Ð»Ñ\8f Ð¿Ð¾Ñ\80Ñ\96внÑ\8fннÑ\8f Ñ\96 Ð½Ð°Ñ\82иÑ\81нÑ\96Ñ\82Ñ\8c Â«Enter» Ð°Ð±Ð¾ ÐºÐ½Ð¾Ð¿ÐºÑ\83 Ð²Ð½Ð¸Ð·Ñ\83.\n\nÐ\9fоÑ\8fÑ\81неннÑ\8f: (поÑ\82оÑ\87н.) = Ð²Ñ\96дмÑ\96нноÑ\81Ñ\82Ñ\96 Ð²Ñ\96д Ð¿Ð¾Ñ\82оÑ\87ноÑ\97 Ð²ÐµÑ\80Ñ\81Ñ\96Ñ\97,\n(оÑ\81Ñ\82.) = Ð²Ñ\96дмÑ\96нноÑ\81Ñ\82Ñ\96 Ð²Ñ\96д Ð¿Ð¾Ð¿ÐµÑ\80еднÑ\8cоÑ\97 Ð²ÐµÑ\80Ñ\81Ñ\96Ñ\97, '''м''' = Ð½ÐµÐ·Ð½Ð°Ñ\87не Ñ\80едагÑ\83ваннÑ\8f",
        "history-fieldset-title": "Переглянути історію",
        "history-show-deleted": "Тільки вилучені",
        "histfirst": "найдавніші",
        "histlast": "найновіші",
        "historysize": "($1 {{PLURAL:$1|байт|байти|байтів}})",
-       "historyempty": "(поÑ\80ожнÑ\8cо)",
+       "historyempty": "(поÑ\80ожнÑ\8f)",
        "history-feed-title": "Історія редагувань",
        "history-feed-description": "Історія редагувань цієї сторінки в вікі",
        "history-feed-item-nocomment": "$1 в $2",
        "rev-deleted-comment": "(опис редагування вилучено)",
        "rev-deleted-user": "(ім'я автора стерто)",
        "rev-deleted-event": "(запис журналу вилучений)",
-       "rev-deleted-user-contribs": "[ім'я користувача або IP-адреса вилучені — редагування приховане у внеску]",
+       "rev-deleted-user-contribs": "[ім'я користувача або IP-адреса вилучені — редагування приховане з внеску]",
        "rev-deleted-text-permission": "Ця версія сторінки '''вилучена'''.\nМожливо є пояснення в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журналі вилучень].",
+       "rev-suppressed-text-permission": "Цю версію сторінки було <strong>приховано</strong>.\nДетальніше можна подивитися у [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журналі приховування].",
        "rev-deleted-text-unhide": "Ця версія сторінки була '''вилучена'''.\nПодробиці наведені у [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журналі вилучень].\nВи все ще можете [$1 переглянути цю версію], якщо забажаєте.",
        "rev-suppressed-text-unhide": "Ця версія сторінки була '''прихована'''.\nПодробиці наведені у [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журналі приховань].\nВи все ще можете [$1 переглянути цю версію], якщо забажаєте.",
        "rev-deleted-text-view": "Ця версія сторінки '''вилучена'''.\nВи можете переглянути її; пояснення дивіться в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журналі вилучень].",
        "revdelete-selected-text": "{{PLURAL:$1|Вибрана редакція|Вибрані редакції}} із [[:$2]]:",
        "revdelete-selected-file": "{{PLURAL:$1|Вибрана версія файлу|Вибрані версії файлу}} із [[:$2]]:",
        "logdelete-selected": "{{PLURAL:$1|1=Обраний запис|Обрані записи}} журналу:",
-       "revdelete-text-text": "Видалені версії будуть як і раніше видно в історії сторінки, але їх частини вмісту будуть доступні для учасників.",
+       "revdelete-text-text": "Видалені версії будуть як і раніше, показані в історії сторінки, але частини їх вмісту будуть недоступні для учасників.",
        "revdelete-text-file": "Видалені версії файлу будуть як і раніше видно в історії сторінки, але їх частини вмісту будуть доступні для учасників.",
-       "logdelete-text": "Видалені події в журналі будуть як і раніше видно в журналах, але частини їх вмісту будуть доступні для учасників.",
-       "revdelete-text-others": "Інші адміністратори на {{grammar:genitive|{{SITENAME}}}} як і раніше буде мати можливість доступу до прихованого вмісту і зможуть відновити його знову через цей же інтерфейс, якщо не встановлено додаткові обмеження.",
-       "revdelete-confirm": "Будь ласка, підтвердить, що ви справді бажаєте це здійснити, усвідомлюєте наслідки та робите це згідно з [[{{MediaWiki:Policy-url}}|правилами]].",
+       "logdelete-text": "Ð\92идаленÑ\96 Ð¿Ð¾Ð´Ñ\96Ñ\97 Ð² Ð¶Ñ\83Ñ\80налÑ\96 Ð±Ñ\83дÑ\83Ñ\82Ñ\8c Ñ\8fк Ñ\96 Ñ\80анÑ\96Ñ\88е Ð²Ð¸Ð´Ð½Ð¾ Ð² Ð¶Ñ\83Ñ\80налаÑ\85, Ð°Ð»Ðµ Ñ\87аÑ\81Ñ\82ини Ñ\97Ñ\85 Ð²Ð¼Ñ\96Ñ\81Ñ\82Ñ\83 Ð±Ñ\83дÑ\83Ñ\82Ñ\8c Ð½ÐµÐ´Ð¾Ñ\81Ñ\82Ñ\83пнÑ\96 Ð´Ð»Ñ\8f Ñ\83Ñ\87аÑ\81никÑ\96в.",
+       "revdelete-text-others": "Інші адміністратори, як і раніше, будуть мати можливість доступу до прихованого вмісту і зможуть відновити його, якщо не встановлено додаткові обмеження.",
+       "revdelete-confirm": "Будь ласка, підтвердіть, що ви справді бажаєте це здійснити, що усвідомлюєте наслідки та робите це згідно з [[{{MediaWiki:Policy-url}}|правилами]].",
        "revdelete-suppress-text": "Приховування може відбуватися '''лише''' в таких випадках:\n* Потенційно наклепницькі відомості\n* Недоречна особиста інформація\n*: ''домашні адреси, номери телефонів, номер паспорта тощо.''",
        "revdelete-legend": "Встановити обмеження видимості",
        "revdelete-hide-text": "Текст версії сторінки",
        "logdelete-failure": "'''Не вдалося встановити видимість журналу:'''\n$1",
        "revdel-restore": "Змінити видимість",
        "pagehist": "Історія сторінки",
-       "deletedhist": "Історія вилучень",
+       "deletedhist": "Історія вилучена",
        "revdelete-hide-current": "Помилка приховування запису від $2, $1: це поточна версія.\nЇї не можна приховати.",
        "revdelete-show-no-access": "Помилка показу запису від $2, $1: він позначений як «з обмеженим доступом».\nВи не маєте доступу до нього.",
        "revdelete-modify-no-access": "Помилка редгування запису від $2, $1: його поначено як \"з обмеженим доступом\".\nВи не маєте доступу до нього.",
        "revdelete-no-change": "'''Увага:''' запис від $2, $1 вже має запрошені налаштування видимості.",
        "revdelete-concurrent-change": "Помилка редагування запису від $2, $1: його стан змінений кимось іншим, поки ви робили свої зміни.\nБудь ласка, перевірте журнал.",
        "revdelete-only-restricted": "Помилка приховання запису від $2, $1: ви не можете приховати записи від перегляду адміністраторів без одночасного вибору однієї з інших опцій приховання.",
-       "revdelete-reason-dropdown": "* Типові причини вилучення\n** Порушення авторських прав\n** Недоречна особиста інформація\n** Невідповідне ім'я користувача\n** Потенційно наклепна інформація",
+       "revdelete-reason-dropdown": "* Типові причини вилучення\n** Порушення авторських прав\n** Недоречні коментарі чи особиста інформація\n** Невідповідне ім'я користувача\n** Потенційно наклепницька інформація",
        "revdelete-otherreason": "Інша/додаткова причина:",
        "revdelete-reasonotherlist": "Інша причина",
-       "revdelete-edit-reasonlist": "Редагувати причини вилучень",
+       "revdelete-edit-reasonlist": "Редагувати причини вилучення",
        "revdelete-offender": "Автор версії:",
        "suppressionlog": "Журнал приховувань",
        "suppressionlogtext": "Нижче наведено список вилучень та блокувань, включаючи матеріали, приховані від адміністраторів.\nДивіться [[Special:BlockList|список блокувань]] для перегляду поточних блокувань.",
-       "mergehistory": "Об'єднання історій редагувань",
+       "mergehistory": "Об'єднати історії редагувань",
        "mergehistory-header": "Ця сторінка дозволяє вам об'єднати історії редагувань двох різних сторінок.\nПереконайтеся, що ця зміна збереже цілісність історії сторінки.",
        "mergehistory-box": "Об'єднати історії редагувань двох сторінок:",
        "mergehistory-from": "Вихідна сторінка:",
        "mergehistory-into": "Цільова сторінка:",
        "mergehistory-list": "Історія редагувань, що об'єднується",
-       "mergehistory-merge": "Ð\9dаÑ\81Ñ\82Ñ\83пнÑ\96 Ð²ÐµÑ\80Ñ\81Ñ\96Ñ\97 [[:$1]] Ð¼Ð¾Ð¶Ñ\83Ñ\82Ñ\8c Ð±Ñ\83Ñ\82и Ð¾Ð±'Ñ\94днанÑ\96 Ñ\83 [[:$2]]. Ð\92икоÑ\80иÑ\81Ñ\82айÑ\82е Ð¿ÐµÑ\80емикаÑ\87Ñ\96 Ð´Ð»Ñ\8f Ñ\82ого, Ñ\89об Ð¾Ð±'Ñ\94днаÑ\82и Ñ\82Ñ\96лÑ\8cки Ð²Ð¸Ð±Ñ\80аний Ð´Ñ\96апазон Ñ\80едагÑ\83ванÑ\8cВрахуйте, що при використанні навігаційних посилань дані будуть втрачені.",
+       "mergehistory-merge": "Ð\9dаÑ\81Ñ\82Ñ\83пнÑ\96 Ð²ÐµÑ\80Ñ\81Ñ\96Ñ\97 [[:$1]] Ð¼Ð¾Ð¶Ñ\83Ñ\82Ñ\8c Ð±Ñ\83Ñ\82и Ð¾Ð±'Ñ\94днанÑ\96 Ñ\83 [[:$2]]. Ð\92икоÑ\80иÑ\81Ñ\82айÑ\82е ÐºÑ\80Ñ\83глÑ\96 Ð²Ñ\96конÑ\86Ñ\8f, Ñ\89об Ð¾Ð±'Ñ\94днаÑ\82и Ñ\82Ñ\96лÑ\8cки Ð²Ð¸Ð±Ñ\80аний Ð´Ñ\96апазон Ñ\80едагÑ\83ванÑ\8c. \nВрахуйте, що при використанні навігаційних посилань дані будуть втрачені.",
        "mergehistory-go": "Показати редагування, що об'єднуються",
-       "mergehistory-submit": "Об'єднати редагування",
-       "mergehistory-empty": "Не знайдені редагування для об'єднання.",
+       "mergehistory-submit": "Об'єднати версії",
+       "mergehistory-empty": "Не знайдено версій для об'єднання.",
        "mergehistory-success": "$3 {{PLURAL:$3|редагування|редагування|редагувань}} з [[:$1]] успішно перенесені до [[:$2]].",
        "mergehistory-fail": "Не вдалося здійснити об'єднання історій сторінок, будь ласка, перевірте параметри сторінки й часу.",
        "mergehistory-fail-toobig": "Не вдалося виконати злиття історії оскільки буде перейменовано більше, ніж ліміт у $1 {{PLURAL:$1|версію|версії|версій}}.",
        "mergehistory-no-source": "Вихідна сторінка «$1» не існує.",
        "mergehistory-no-destination": "Цільова сторінка «$1» не існує.",
-       "mergehistory-invalid-source": "Ð\94жеÑ\80ело Ð¿Ð¾Ð²Ð¸Ð½Ð½Ðµ мати правильний заголовок.",
+       "mergehistory-invalid-source": "Ð\92иÑ\85Ñ\96дна Ñ\81Ñ\82оÑ\80Ñ\96нка Ð¿Ð¾Ð²Ð¸Ð½Ð½Ð° мати правильний заголовок.",
        "mergehistory-invalid-destination": "Цільова сторінка повинна мати правильний заголовок.",
        "mergehistory-autocomment": "Редагування з [[:$1]] перенесені до [[:$2]]",
        "mergehistory-comment": "Редагування [[:$1]] перенесені до [[:$2]]: $3",
        "shown-title": "Показувати $1 {{PLURAL:$1|запис|записи|записів}} на сторінці",
        "viewprevnext": "Переглянути ($1 {{int:pipe-separator}} $2) ($3).",
        "searchmenu-exists": "'''У цій вікі є сторінка з назвою «[[:$1]]»'''",
-       "searchmenu-new": "<strong>Створити сторінку «[[:$1]]» у цьому вікі-проекті!</strong>\n{{PLURAL:$2|0=|Див. також сторінку, знайдену по результатами вашого пошуку.|Див. також знайдені результати пошуку.}}",
+       "searchmenu-new": "<strong>Створити сторінку «[[:$1]]» у цьому вікіпроекті!</strong>\n{{PLURAL:$2|0=|Див. також сторінку, знайдену за результатами вашого пошуку.|Див. також знайдені результати пошуку.}}",
        "searchprofile-articles": "Статті",
        "searchprofile-images": "Мультимедіа",
        "searchprofile-everything": "Усюди",
        "searchprofile-advanced-tooltip": "Шукати в заданих просторах назв",
        "search-result-size": "$1 ($2 {{PLURAL:$2|слово|слова|слів}})",
        "search-result-category-size": "{{PLURAL:$1|$1 елемент|$1 елементи|$1 елементів}} ({{PLURAL:$2|$2 підкатегорія|$2 підкатегорії|$2 підкатегорій}}, {{PLURAL:$3|$3 файл|$3 файли|$3 файлів}})",
-       "search-result-score": "Відповідність: $1 %",
        "search-redirect": "(перенаправлення $1)",
        "search-section": "(розділ $1)",
        "search-file-match": "(збігається із вмістом файлу)",
        "searchall": "усі",
        "showingresults": "Нижче {{PLURAL:$1|показане|показані|показані}} '''$1''' {{PLURAL:$1|результат|результати|результатів}}, починаючи з №&nbsp;'''$2'''",
        "showingresultsinrange": "Нижче показано до {{PLURAL:$1|<strong>1</strong> результата|<strong>$1</strong> результатів|<strong>$1</strong> результати}} у діапазоні від #<strong>$2</strong> до #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|1=Результат '''$1''' з '''$3'''|Результати '''$1 — $2''' з '''$3'''}} для '''$4'''",
        "search-nonefound": "Не знайдено результатів, що відповідають запиту.",
        "powersearch-legend": "Розширений пошук",
        "powersearch-ns": "Пошук у просторах назв:",
        "right-deletedtext": "перегляд вилученого тексту та змін між вилученими версіями",
        "right-browsearchive": "Пошук вилучених сторінок",
        "right-undelete": "Відновлення сторінок",
-       "right-suppressrevision": "Перегляд і відновлення версій, прихованих від адміністраторів",
+       "right-suppressrevision": "Перегляд, приховання та відновлення конкретних змін сторінок від будь-якого користувача",
+       "right-viewsuppressed": "Перегляд змін, приховаих від усіх користувачів",
        "right-suppressionlog": "Перегляд приватних журналів",
        "right-block": "Заборона редагувань для інших дописувачів",
        "right-blockemail": "Блокування користувачам надсилання електронної пошти",
        "recentchanges-legend-heading": "'''Легенда:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (див. також [[Special:NewPages|список нових сторінок]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Ð\9dижÑ\87е Ð²Ñ\96добÑ\80аженÑ\96 Ñ\80едагÑ\83ваннÑ\8f Ð· <strong>$2</strong> (до <strong>$1</strong>).",
+       "rcnotefrom": "Ð\9dижÑ\87е Ð·Ð½Ð°Ñ\85одÑ\8fÑ\82Ñ\8cÑ\81Ñ\8f {{PLURAL:$5|Ñ\80едагÑ\83ваннÑ\8f}} Ð· <strong>$3, $4</strong> (вÑ\96добÑ\80ажено до <strong>$1</strong>).",
        "rclistfrom": "Показати редагування починаючи з $3 $2.",
        "rcshowhideminor": "$1 незначні редагування",
        "rcshowhideminor-show": "показати",
        "uploadwarning": "Попередження",
        "uploadwarning-text": "Будь ласка, змініть наданий нижче опис файлу і спробуйте ще раз.",
        "savefile": "Зберегти файл",
-       "uploadedimage": "завантажив «[[$1]]»",
-       "overwroteimage": "завантажив нову версію «[[$1]]»",
        "uploaddisabled": "Завантаження заборонене",
        "copyuploaddisabled": "Завантаження через URL вимкнене.",
        "uploaddisabledtext": "Можливість завантаження файлів відключена.",
        "license": "Ліцензування:",
        "license-header": "Ліцензування",
        "nolicense": "Відсутнє",
+       "licenses-edit": "Редагувати параметри ліцензії",
        "license-nopreview": "(Попередній перегляд недоступний)",
        "upload_source_url": " (вірна, публічно доступна інтернет-адреса)",
        "upload_source_file": " (файл на вашому комп'ютері)",
+       "listfiles-delete": "видалити",
        "listfiles-summary": "Ця спеціальна сторінка показує всі завантажені файли.",
        "listfiles_search_for": "Пошук по назві зображення:",
        "imgfile": "файл",
        "randomincategory": "Випадкова сторінка у категорії",
        "randomincategory-invalidcategory": "\" $1 \" не є дійсним іменем категорії.",
        "randomincategory-nopages": "У [[:Category:$1]] немає сторінок.",
-       "randomincategory-selectcategory": "Перейти на випадкову сторінку з категорії: $1 $2.",
-       "randomincategory-selectcategory-submit": "Перейти",
        "randomredirect": "Випадкове перенаправлення",
        "randomredirect-nopages": "Простір назв «$1» не містить перенаправлень.",
        "statistics": "Статистика",
        "wantedpages-badtitle": "Неправильний заголовок у результатах запиту: $1",
        "wantedfiles": "Необхідні файли",
        "wantedfiletext-cat": "Наступні файли використовують, але вони не існують. У цей список можуть помилково потрапити файли, що знаходяться на зовнішніх сховищах. Такі хибні моменти помічаються <del>перекреслюванням</del>. Крім того, сторінки, що використовують неіснуючі файли, перелічені в [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Наступні файли використовуються, але не існують. Крім того, сторінки, що посилаються на фійли, які не існують, перераховані у [[:$1]].",
        "wantedfiletext-nocat": "Наступні файли використовують, але вони не існують. У цей список можуть помилково потрапити файли, що знаходяться на зовнішніх сховищах. Такі хибні моменти помічаються <del>перекреслюванням</del>.",
+       "wantedfiletext-nocat-noforeign": "Наступні файли використовуються, але не існують.",
        "wantedtemplates": "Необхідні шаблони",
        "mostlinked": "Сторінки, на які найбільше посилань",
        "mostlinkedcategories": "Найбільші категорії",
        "watchlist-details": "У вашому списку спостереження $1 {{PLURAL:$1|сторінка|сторінки|сторінок}} (не враховуючи сторінок обговорення).",
        "wlheader-enotif": "Сповіщення електронною поштою ввімкнено.",
        "wlheader-showupdated": "Сторінки, що змінилися після вашого останнього їх відвідування, виділені '''жирним''' шрифтом.",
-       "wlnote2": "Нижче наведено зміни за {{PLURAL:$1|останню годину|останні <strong>$1</strong> години|останні <strong>$1</strong> годин}} на $2 $3.",
+       "wlnote": "Нижче наведено {{PLURAL:$1|останнє $1 редагування|останні $1 редагування|останні $1 редагувань}} за {{PLURAL:$2|останню|останні|останні}} <strong>$2</strong> {{PLURAL:$2|годину|години|годин}}, на час $3 $4.",
        "wlshowlast": "Показати зміни за останні $1 годин $2 днів $3",
        "watchlist-options": "Налаштування списку спостереження",
        "watching": "Додавання до списку спостереження…",
        "delete-toobig": "У цієї сторінки дуже довга історія редагувань, більше $1 {{PLURAL:$1|версії|версій|версій}}.\nВилучення таких сторінок було заборонене з метою уникнення порушень у роботі сайту {{SITENAME}}.",
        "delete-warning-toobig": "У цієї сторінки дуже довга історія редагувань, більше $1 {{PLURAL:$1|версії|версій|версій}}.\nЇї вилучення може призвести до порушень у роботі бази даних сайту {{SITENAME}};\nдійте обережно.",
        "deleting-backlinks-warning": "'''Попередження:'''  [[Special:WhatLinksHere/{{FULLPAGENAME}}|інші сторінки]] посилаються або містять сторінку, яку ви маєте намір видалити.",
-       "rollback": "Ð\92Ñ\96дкинÑ\83Ñ\82и редагування",
+       "rollback": "Ð\92Ñ\96дкинÑ\83Ñ\82о редагування",
        "rollback_short": "Відкинути",
        "rollbacklink": "відкинути",
        "rollbacklinkcount": "відкинути $1 {{PLURAL:$1|редагування|редагування|редагувань}}",
        "import": "Імпорт статей",
        "importinterwiki": "Міжвікі імпорт",
        "import-interwiki-text": "Вкажіть вікі й назву імпортованої сторінки.\nДати змін й імена авторів буде збережено.\nУсі операції міжвікі-імпорту реєструються в [[Special:Log/import|відповідному протоколі]].",
-       "import-interwiki-source": "Вікі/сторінка-джерело",
        "import-interwiki-history": "Копіювати всю історію змін цієї сторінки",
        "import-interwiki-templates": "Включити всі шаблони",
        "import-interwiki-submit": "Імпортувати",
        "import-upload": "Завантажити XML-дані",
        "import-token-mismatch": "Утрачені дані сеансу. Будь ласка, спробуйте ще раз.",
        "import-invalid-interwiki": "Неможливо імпортувати із зазначеної вікі.",
-       "import-error-edit": "Сторінку \"$1\" не імпортовано, оскільки вам не дозволено її редагувати.",
-       "import-error-create": "Сторінку \"$1\" не імпортовано, оскільки вам не дозволено її створювати.",
-       "import-error-interwiki": "Сторінку \"$1\" не імпортовано, оскільки її назва зарезервована для зовнішніх посилань (interwiki).",
-       "import-error-special": "Сторінку \"$1\" не імпортовано, оскільки вона належить до особливого простору імен, що не дозволяє створення сторінок.",
-       "import-error-invalid": "Сторінку \"$1\" не імпортовано, оскільки його ім'я неприпустиме.",
+       "import-error-edit": "Сторінку «$1» не було імпортовано, оскільки Вам не дозволено її редагувати.",
+       "import-error-create": "Сторінку «$1» не було імпортовано, оскільки Вам не дозволено її створювати.",
+       "import-error-interwiki": "Сторінку «$1» не було імпортовано, оскільки її назва зарезервована для зовнішніх посилань (interwiki).",
+       "import-error-special": "Сторінку «$1» не було імпортовано, оскільки вона належить до особливого простору назв, що не дозволяє створення сторінок.",
+       "import-error-invalid": "Сторінку «$1» не було імпортовано, оскільки назва, у яку вона імпортується, неприпустима у цій вікі.",
        "import-error-unserialize": "Версія $2 сторінки «$1» не може бути деструктурованою (десеріалізованою). Отримано повідомлення, що у цій версії використано модель $3 сериалізована як $4.",
        "import-error-bad-location": "Правка $2, що використовує модель вмісту $3, не може бути збережена у «$1» цієї вікі, тому що ця модель не підтримується на цій сторінці.",
        "import-options-wrong": "{{PLURAL:$2|1=Неправильна опція|Неправильні опції}}: <nowiki>$1</nowiki>",
        "importlogpage": "Журнал імпорту",
        "importlogpagetext": "Імпорт адміністраторами сторінок з історією редагувань з інших вікі.",
        "import-logentry-upload": "«[[$1]]» — імпорт з файлу",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|версія|версії|версій}}",
+       "import-logentry-upload-detail": "Імпортовано $1 {{PLURAL:$1|версія|версії|версій}}",
        "import-logentry-interwiki": "«$1» — міжвікі імпорт",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|версія|версії|версій}} з $2",
+       "import-logentry-interwiki-detail": "Імпортовано $1 {{PLURAL:$1|версія|версії|версій}} з $2",
        "javascripttest": "Тестування JavaScript",
        "javascripttest-title": "Працює  $1  випробувань",
        "javascripttest-pagetext-noframework": "Ця сторінка призначений для тестування JavaScript.",
        "autosumm-replace": "Замінено вміст на «$1»",
        "autoredircomment": "Перенаправлено на [[$1]]",
        "autosumm-new": "Створена сторінка: $1",
+       "autosumm-newblank": "Створити порожню сторінку",
        "size-bytes": "$1 байтів",
        "size-kilobytes": "$1 КБ",
        "size-megabytes": "$1 МБ",
        "timezone-utc": "UTC",
        "unknown_extension_tag": "Невідомий тег доповнення «$1»",
        "duplicate-defaultsort": "Увага. Ключ сортування «$2» перекриває попередній ключ сортування «$1».",
+       "duplicate-displaytitle": "<strong>Увага:</strong> Відображений заголовок \"$2\" заміщує раніше відображений заголовок \"$1\".",
        "version": "Версія MediaWiki",
        "version-extensions": "Установлені розширення",
        "version-skins": "Встановлені теми оформлення",
        "version-version": "($1)",
        "version-no-ext-name": "[без назви]",
        "version-svn-revision": "(r$2)",
-       "version-license": "Ліцензія MediaWik",
+       "version-license": "Ліцензія MediaWiki",
        "version-ext-license": "Ліцензія",
        "version-ext-colheader-name": "Розширення",
        "version-skin-colheader-name": "Тема оформлення",
        "logentry-rights-rights": "$1 {{GENDER:$1|змінив|змінила}} членство в групах для $3 із $4 на $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$1|змінив|змінила}} членство в групах для $3",
        "logentry-rights-autopromote": "$1 було автоматично переведено із $4 в $5",
+       "logentry-upload-upload": "$1 {{GENDER:$2|завантажив|завантажила}} $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|завантажив|завантажила}} нову версію $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|завантажив|завантажила}} $3",
        "rightsnone": "(нема)",
        "feedback-bugornote": "Якщо ви готові описати технічні проблеми в деталях, будь ласка, [$1 повідомте про помилку].\nАбо можете використати форму нижче. Ваш коментар буде додано на сторінку \"[$3  $2]\", разом з іменем користувача.",
        "feedback-subject": "Тема:",
        "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-row-enabled": "* <code>$1</code> / $2 (увімкнено)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''вимкнено''')"
 }
index 8726dc3..3170cbd 100644 (file)
        "talkpagelinktext": "تبادلۂ خیال",
        "specialpage": "خصوصی صفحہ",
        "personaltools": "ذاتی اوزار",
-       "postcomment": "اگلا حصّہ",
        "articlepage": "مندرجاتی صفحہ دیکھیۓ",
        "talk": "تبادلہٴ خیال",
        "views": "خیالات",
        "externaldberror": "یا تو توثیقی ڈیٹابیس میں خطا واقع ہوئی اور یا آپ کو بیرونی کھاتہ بتاریخ کرنے کی اِجازت نہیں ہے.",
        "login": "داخل ہوں",
        "nav-login-createaccount": "کھاتہ کھولیں یا اندراج کریں",
-       "loginprompt": "{{SITENAME}} میں داخلے کیلۓ آپکے پاس قند (کوکیز) مجازہوناچاہیں۔",
        "userlogin": "کھاتہ کھولیں یا اندراج کریں",
        "userloginnocreate": "داخلِ نوشتہ ہوجائیے",
        "logout": "اخراج",
        "searchprofile-advanced-tooltip": "اپنی پسند کے جائے نام میں تلاش",
        "search-result-size": "$1 ({{PLURAL:$2|1 لفظ|$2 الفاظ}})",
        "search-result-category-size": "{{PLURAL:$1|1 رُکن|$1 اراکین}} ({{PLURAL:$2|1 ذیلی زمرہ|$2 ذیلی زمرہ جات}}, {{PLURAL:$3|1 ملف|$3 ملفات}})",
-       "search-result-score": "توافق: $1%",
        "search-redirect": "(رجوع مکرر $1)",
        "search-section": "(حصہ $1)",
        "search-suggest": "کیا آپ کا مطلب تھا: $1",
        "fileexists": "اس نام سے ایک ملف (فائل) پہلے ہی موجود ہے، اگر آپ کو یقین نہ ہو کہ اسے حذف کردیا جانا چاہیۓ تو براہ کرم  <strong>[[:$1]]</strong> کو ایک نظر دیکھ لیجیۓ۔ [[$1|thumb]]",
        "uploadwarning": "انتباہ بہ سلسلۂ زبراثقال",
        "savefile": "فائل محفوظ کریں",
-       "uploadedimage": "زبراثقال (اپ لوڈ) براۓ \"[[$1]]\"",
        "sourcefilename": "اسم ملف (فائل) کا منبع:",
        "destfilename": "تعین شدہ اسم ملف:",
        "watchthisupload": "یہ صفحہ زیر نظر کیجیۓ",
        "watchthispage": "یہ صفحہ زیر نظر کیجیۓ",
        "unwatch": "زیرنظرمنسوخ",
        "watchlist-details": "آپ کی زیرِنظرفہرست پر {{PLURAL:$1|$1 صفحہ ہے|$1 صفحات ہیں}}، اِس میں تبادلۂ خیال صفحات کی تعداد شامل نہیں.",
+       "wlnote": "نیچےآخری $1 تبدیلیاں ہیں جو کے پیچھلے <b>$2</b> گھنٹوں میں کی گئیں۔",
        "wlshowlast": "دکھائیں آخری $1 گھنٹے $2 دن $3",
        "watchlist-options": "اختیارات برائے زیرِنظرفہرست",
        "created": "بنا دیا گیا",
index 25867f7..5c1fd06 100644 (file)
        "talkpagelinktext": "munozara",
        "specialpage": "Maxsus sahifa",
        "personaltools": "Shaxsiy uskunalar",
-       "postcomment": "Yangi boʻlim",
        "articlepage": "Maqolani koʻrib chiqish",
        "talk": "Munozara",
        "views": "Qarashlar",
        "password-change-forbidden": "Siz bu vikida maxfiy soʻzni oʻzgartira olmaysiz.",
        "login": "Kirish",
        "nav-login-createaccount": "Kirish / Hisob yaratish",
-       "loginprompt": "{{SITENAME}}ga kirish uchun kukilar yoqilgan bo'lishi kerak.",
        "userlogin": "Kirish / Hisob yaratish",
        "userloginnocreate": "Kirish",
        "logout": "Chiqish",
        "searchprofile-advanced-tooltip": "Belgilangan nomfazolardan qidirish",
        "search-result-size": "$1 ({{PLURAL:$2|1 ta soʻz|$2 ta soʻz}})",
        "search-result-category-size": "$1 {{PLURAL:$1|a'zo|a'zolar}} ($2 {{PLURAL:$2|ostturkum|ostturkumlar}}, $3 {{PLURAL:$3|fayl|fayllar}}).",
-       "search-result-score": "Relavantlik: $1%.",
        "search-redirect": "(yoʻnaltirish $1)",
        "search-section": "($1 boʻlimi)",
        "search-suggest": "Balki buni nazarda tutgandirsiz: $1",
        "filestatus": "Tarqatish shartlari:",
        "filesource": "Manba:",
        "ignorewarnings": "Ogohlantirishlarga eʼtibor qilma",
-       "uploadedimage": "\"[[$1]]\"ni yukladi",
-       "overwroteimage": "\"[[$1]]\"ning yangi versiyasini yukladi",
        "upload-source": "Yuklanayotgan fayl",
        "sourcefilename": "Fayl nomi:",
        "destfilename": "Fayl nomi:",
        "notanarticle": "Maqola emas",
        "watchlist-details": "Sizning kuzatuv roʻyxatingizda hozirda {{PLURAL:$1|bitta sahifa|$1ta sahifa}} mavjud (munozara sahifalarini hisobga olmaganda).",
        "wlheader-showupdated": "Siz oxirgi marta kirganingizdan keyin oʻzgartirilgan sahifalar '''qalin''' yozuv bilan ajratib koʻrsatilgan.",
+       "wlnote": "Below {{PLURAL:$1|is the last change|are the last '''$1''' changes}} in the last {{PLURAL:$2|hour|'''$2''' hours}}, as of $3, $4.",
        "wlshowlast": "Oxirgi $1 soatdagi $2 kundagi tahrirlarni koʻrsat $3",
        "watchlist-options": "Kuzatuv roʻyxati moslamalari",
        "watching": "Kuzatish...",
index 09c4ce1..1e1c309 100644 (file)
        "talkpagelinktext": "Discussion",
        "specialpage": "Pagina speciale",
        "personaltools": "Strumenti personali",
-       "postcomment": "Nova sesion",
        "articlepage": "Varda ła voxe",
        "talk": "Discussion",
        "views": "Visite",
        "externaldberror": "Se xè verifegà n'erore con el server de autenticasion esterno, opure no se dispone de łe autorizasion nesesarie par ajornare el proprio aceso esterno.",
        "login": "Entra",
        "nav-login-createaccount": "Entra / Regìstrete",
-       "loginprompt": "Par entrar su {{SITENAME}} te ghè da verghe i cookie ativà.",
        "userlogin": "Entra / Regìstrete",
        "userloginnocreate": "Entra",
        "logout": "Và fora",
        "searchprofile-advanced-tooltip": "Serca nei namespace personalixài",
        "search-result-size": "$1 ({{PLURAL:$2|na parola|$2 parole}})",
        "search-result-category-size": "{{PLURAL:$1|1 utente|$1 utenti}} ({{PLURAL:$2|1 sotocategoria|$2 sotocategorie}}, {{PLURAL:$3|1 file|$3 file}})",
-       "search-result-score": "Rilevansa: $1%",
        "search-redirect": "(redirect $1)",
        "search-section": "(sesion $1)",
        "search-suggest": "Sercavito forsi: $1",
        "searchrelated": "ligà",
        "searchall": "tuti",
        "showingresults": "Qua de soto vien mostrà al massimo {{PLURAL:$1|'''1''' risultato|'''$1''' risultati}} a partir dal nùmaro '''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|Risultato '''$1''' de '''$3'''|Risultati '''$1 - $2''' de '''$3'''}} par '''$4'''",
        "search-nonefound": "La riserca no la gà catà gnente.",
        "powersearch-legend": "Riserca avansà",
        "powersearch-ns": "Serca ne i namespace:",
        "recentchanges-label-plusminus": "La dimension de la pagina la xe canbià de sto nùmaro de byte",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (varda anca [[Special:NewPages|l'elenco de le pagine nove]])",
        "rcnotefrom": "Qui di seguito sono elencate le modifiche da '''$2''' (fino a '''$1''').",
-       "rclistfrom": "Fà védar i canbiamenti fati dal $3 $2",
+       "rclistfrom": "Mostra i canbiamenti fati da ƚe $2 del $3",
        "rcshowhideminor": "$1 i canbiamenti picenini",
        "rcshowhidebots": "$1 i bot",
        "rcshowhideliu": "$1 i utenti registrài",
        "uploadwarning": "Avixo de caricamento",
        "uploadwarning-text": "Par piaser, cànbia la descrission del file qua de soto e próa da novo.",
        "savefile": "Salva file",
-       "uploadedimage": "ga cargà \"[[$1]]\"",
-       "overwroteimage": "gà cargà na version nova de \"[[$1]]\"",
        "uploaddisabled": "Semo spiacenti, ma el caricamento de file el xe tenporaneamente sospeso.",
        "copyuploaddisabled": "El caricamento tramite URL el xe disabilità.",
        "uploaddisabledtext": "El caricamento dei file no'l xe mìa ativo.",
        "randomincategory": "Pagina a ocio in te na categoria",
        "randomincategory-invalidcategory": "\"$1\" no'l và mia ben come nome de categoria.",
        "randomincategory-nopages": "No ghe xe mia pagine in [[:Category:$1]].",
-       "randomincategory-selectcategory": "Ciapa na pagina a ocio da la categoria: $1 $2.",
-       "randomincategory-selectcategory-submit": "Và",
        "randomredirect": "Un redirect a caso",
        "randomredirect-nopages": "No ghe xe nissun rimando in tel namespace \"$1\".",
        "statistics": "Statisteghe",
        "watchlist-details": "Te sì drio tegner d'ocio {{PLURAL:$1|una pagina (e la so pagina de discussion)|$1 pagine (e le so pagine de discussion)}}.",
        "wlheader-enotif": "Xe ativà la notifica via e-mail.",
        "wlheader-showupdated": "Le pagine che xe stà canbià da la to ultima visita le xe segnà in '''grosso'''",
+       "wlnote": "Cuà soto te cati {{PLURAL:$1|'l ultimo canbiamento|i ultimi '''$1''' canbiamenti}} inte {{PLURAL:$2|l'ultema ora|łe ultime '''$2''' ore}}; i dati i xe axornai a łe $4 del $3.",
        "wlshowlast": "Mostra le ultime $1 ore $2 zorni $3",
        "watchlist-options": "Inpostassion de le pagine tegnùe d'ocio",
        "watching": "Taco a tegner d'ocio...",
        "import": "Inporta pàxene",
        "importinterwiki": "Inportazion transwiki",
        "import-interwiki-text": "Seleziona un projeto wiki e el titoło de ła pàxena da inportar.\nLe date de publicazion e i nomi de i autori de łe varie version i sarà conservà.\nTute łe operazion de inportazion trans-wiki łe xè notà nel [[Special:Log/import|registro de inportazion]].",
-       "import-interwiki-source": "Sorgente wiki/pàxena:",
        "import-interwiki-history": "Copia l'intiera cronołogia de sta pàxena",
        "import-interwiki-templates": "Tira dentro tuti i modèi",
        "import-interwiki-submit": "Inporta",
        "duplicate-defaultsort": "Ocio: la ciave de ordinamento predefinìa \"$2\" la va in conflito co' quela de prima \"$1\".",
        "version": "Version",
        "version-extensions": "Estension instalè",
+       "version-skins": "Aspeto grafego",
        "version-specialpages": "Pagine speciali",
        "version-parserhooks": "Hook del parser",
        "version-variables": "Variabili",
        "version-antispam": "Prevension del spam",
-       "version-skins": "Aspeto grafego",
        "version-other": "Altro",
        "version-mediahandlers": "Gestori de contenuti multimediài",
        "version-hooks": "Hook",
index 07ba40c..d00ada8 100644 (file)
        "talkpagelinktext": "Lodu",
        "specialpage": "Specialine lehtpol'",
        "personaltools": "Personaližed azeged",
-       "postcomment": "Uz' jaguz",
        "articlepage": "Kacu südäimišton lehtpol'",
        "talk": "Diskussii",
        "views": "Kacundad",
        "externaldberror": "Ozaižihe petuz autentifikacijan, kudamb tehtihe andmusiden irdbazan turbiš, aigan, vai teile ei ulotu oiktusid toižetada ičetoi irdregistracijad.",
        "login": "Kirjutadas sistemha",
        "nav-login-createaccount": "Kirjutadas / Sada registracii",
-       "loginprompt": "Pidab laskta sada \"cookies\", miše kirjutadas {{SITENAME}}he.",
        "userlogin": "Kirjutadas / Sada registracii",
        "userloginnocreate": "Kirjutagatoiš sistemha",
        "logout": "Lähtta",
        "searchprofile-advanced-tooltip": "Ectä märitud nimiavarusiš",
        "search-result-size": "$1 ({{PLURAL:$2|1 sana|$2 sanad}})",
        "search-result-category-size": "{{PLURAL:$1|1 element|$1 elementad}} ({{PLURAL:$2|1 alakategorii|$2 alakategorijad}}, {{PLURAL:$3|1 fail|$3 failad}})",
-       "search-result-score": "Relevantižuz: $1%",
        "search-redirect": "(oigenduz $1)",
        "search-section": "(jaguz $1)",
        "search-suggest": "Tahtoižit-ik löuta: $1",
        "file-exists-duplicate": "Nece fail om {{PLURAL:$1|necen failan|neniden failoiden}} dublikat:",
        "uploadwarning": "Varutuz jügutoitmižes",
        "savefile": "Kirjutada fail",
-       "uploadedimage": "om jügutoitnu \"[[$1]]\"",
-       "overwroteimage": "jügutoiti \"[[$1]]\"-failan uden versijan",
        "uploaddisabled": "Jügutoitand om kel'tud",
        "uploaddisabledtext": "Failoiden jügutoitand om sauptud.",
        "php-uploaddisabledtext": "Failoiden jügutoitand om kel'tud PHP:n järgendusiš. Kodvgat \"file_uploads\"-järgenduz.",
        "duplicate-defaultsort": "'''Varutuz:''' Sortiruindan avadim äugotižjärgendusen mödhe \"$2\" toižetab edeližen avadimen äugotižjärgendusen mödhe \"$1\".",
        "version": "Versii",
        "version-extensions": "Seižutadud ližad",
+       "version-skins": "Nägutemad",
        "version-specialpages": "Specialižed lehtpoled",
        "version-parserhooks": "Sintaksižen analizatoran sabustajad",
        "version-variables": "Vajehtujad lugud",
        "version-antispam": "Antispam",
-       "version-skins": "Nägutemad",
        "version-other": "Toine",
        "version-mediahandlers": "Median radimed",
        "version-hooks": "Sabutajad",
index a262641..6163709 100644 (file)
@@ -42,6 +42,7 @@
        "tog-watchdefault": "Tự động theo dõi các trang và tập tin tôi sửa",
        "tog-watchmoves": "Tự động theo dõi các trang và tập tin tôi di chuyển",
        "tog-watchdeletion": "Tự động theo dõi các trang và tập tin tôi xóa",
+       "tog-watchrollback": "Tự động theo dõi các trang tôi lùi sửa",
        "tog-minordefault": "Mặc định đánh dấu tất cả sửa đổi của tôi là sửa đổi nhỏ",
        "tog-previewontop": "Hiển thị phần xem trước nằm trên hộp sửa đổi",
        "tog-previewonfirst": "Hiện xem trước tại ngay khi bắt đầu sửa đổi",
        "talkpagelinktext": "Thảo luận",
        "specialpage": "Trang đặc biệt",
        "personaltools": "Công cụ cá nhân",
-       "postcomment": "Đề mục mới",
        "articlepage": "Xem trang nội dung",
        "talk": "Thảo luận",
        "views": "Các hiển thị",
        "otherlanguages": "Ngôn ngữ khác",
        "redirectedfrom": "(đổi hướng từ $1)",
        "redirectpagesub": "Trang đổi hướng",
+       "redirectto": "Đổi hướng đến:",
        "lastmodifiedat": "Trang này được sửa đổi lần cuối lúc $2 $1.",
        "viewcount": "Trang này đã được đọc {{PLURAL:$1|một|$1}} lần.",
        "protectedpage": "Trang bị khóa",
        "hidetoc": "ẩn",
        "collapsible-collapse": "Thu gọn",
        "collapsible-expand": "Mở rộng",
+       "confirmable-confirm": "{{GENDER:$1}}Bạn chắc chứ?",
+       "confirmable-yes": "Có",
+       "confirmable-no": "Không",
        "thisisdeleted": "Xem hay phục hồi $1 ?",
        "viewdeleted": "Xem $1?",
        "restorelink": "{{PLURAL:$1|một|$1}} sửa đổi đã xóa",
        "invalidtitle-knownnamespace": "Tựa trang không hợp lệ có không gian tên “$2” và văn bản “$3”",
        "invalidtitle-unknownnamespace": "Tựa trang không hợp lệ có không gian tên số $1 không rõ và văn bản “$2”",
        "exception-nologin": "Chưa đăng nhập",
-       "exception-nologin-text": "Xin vui lòng [[Special:Userlogin|đăng nhập]] để truy cập trang hoặc thực hiện tác vụ này.",
+       "exception-nologin-text": "Xin vui lòng đăng nhập để truy cập trang hoặc thực hiện tác vụ này.",
        "exception-nologin-text-manual": "Xin vui lòng $1 để truy cập trang hoặc tác vụ này.",
        "virus-badscanner": "Cấu hình sau: không nhận ra bộ quét virus: ''$1''",
        "virus-scanfailed": "quét thất bại (mã $1)",
        "externaldberror": "Có lỗi khi xác nhận cơ sở dữ liệu bên ngoài hoặc bạn không được phép cập nhật tài khoản bên ngoài.",
        "login": "Đăng nhập",
        "nav-login-createaccount": "Đăng nhập / Mở tài khoản",
-       "loginprompt": "Bạn cần bật cookie để đăng nhập vào {{SITENAME}}.",
        "userlogin": "Đăng nhập / Mở tài khoản",
        "userloginnocreate": "Đăng nhập",
        "logout": "Đăng xuất",
        "userlogin-resetlink": "Quên mất thông tin đăng nhập?",
        "userlogin-resetpassword-link": "Quên mật khẩu?",
        "userlogin-helplink2": "Trợ giúp đăng nhập",
-       "userlogin-loggedin": "Bạn đã đăng nhập với tên {{GENDER:$1}}$1.\nHãy sử dụng biểu mẫu ở dưới để đăng nhập với tài khoản người dùng khác.",
-       "userlogin-createanother": "Mở thêm tài khoản",
        "createacct-emailrequired": "Địa chỉ thư điện tử",
        "createacct-emailoptional": "Địa chỉ thư điện tử (tùy chọn)",
        "createacct-email-ph": "Nhập địa chỉ thư điện tử của bạn",
        "noemailprefs": "Hãy ghi một địa chỉ thư điện tử trong tùy chọn cá nhân để có thể sử dụng tính năng này.",
        "emailconfirmlink": "Xác nhận địa chỉ thư điện tử",
        "invalidemailaddress": "Địa chỉ thư điện tử không được chấp nhận vì định dạng thư có vẻ sai.\nHãy nhập một địa chỉ có định dạng đúng hoặc bỏ trống ô đó.",
-       "cannotchangeemail": "Không có thể thay đổi địa chỉ thư điện tử của các tài khoản trên wiki này.",
+       "cannotchangeemail": "Không thể thay đổi địa chỉ thư điện tử của các tài khoản trên wiki này.",
        "emaildisabled": "Website này không thể gửi thư điện tử.",
        "accountcreated": "Mở tài khoản thành công",
        "accountcreatedtext": "Tài khoản thành viên cho [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|thảo luận]]) đã được mở.",
        "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-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ư.",
        "createacct-another-realname-tip": "Tên thật là không bắt buộc. \n\nNếu bạn đồng ý cung cấp, nó sẽ dùng để ghi nhận công lao của bạn.",
        "preview": "Xem trước",
        "showpreview": "Xem trước",
        "showdiff": "Xem thay đổi",
-       "anoneditwarning": "'''Cảnh báo:''' Bạn chưa đăng nhập. Địa chỉ IP của bạn sẽ được ghi lại trong lịch sử sửa đổi của trang.",
+       "blankarticle": "<strong>Cảnh báo:</strong> Bạn sẽ tạo ra một trang trống.\nNếu bấm “{{int:savearticle}}” lần nữa, một trang không có nội dung sẽ được tạo ra.",
+       "anoneditwarning": "<strong>Cảnh báo:</strong> Bạn chưa đăng nhập. Địa chỉ IP của bạn sẽ bị hiển thị công khai nếu bạn thực hiện bất kỳ sửa đổi nào. Nếu bạn <strong>[$1 đăng nhập]</strong> hoặc <strong>[$2 mở tài khoản]</strong>, sửa đổi của bạn sẽ được gán bởi tên đăng nhập của bạn, cùng nhiều lợi ích khác.",
        "anonpreviewwarning": "''Bạn chưa đăng nhập. Khi lưu trang này, địa chỉ IP của bạn sẽ được ghi vào lịch sử trang.''",
        "missingsummary": "'''Nhắc nhở:''' Bạn đã không ghi lại tóm lược sửa đổi. Nếu bạn nhấn Lưu trang một lần nữa, sửa đổi của bạn sẽ được lưu mà không có tóm lược.",
        "missingcommenttext": "Xin hãy gõ vào lời bàn luận ở dưới.",
        "parser-template-recursion-depth-warning": "Bản mẫu đã vượt quá giới hạn về độ sâu đệ quy ($1)",
        "language-converter-depth-warning": "Đã vượt quá giới hạn độ sâu của bộ chuyển đổi ngôn ngữ ($1)",
        "node-count-exceeded-category": "Trang có số nốt vượt quá giới hạn cho phép",
-       "node-count-exceeded-category-desc": "Thể loại chứa các trang có số nốt vượt quá giới hạn cho phép.",
-       "node-count-exceeded-warning": "Trang có nhiều nốt quá",
+       "node-count-exceeded-category-desc": "Trang có số nốt vượt quá giới hạn cho phép.",
+       "node-count-exceeded-warning": "Trang có quá nhiều nốt",
        "expansion-depth-exceeded-category": "Trang có độ sâu bung bản mẫu vượt quá giới hạn cho phép",
-       "expansion-depth-exceeded-category-desc": "Thể loại này chứa các trang có độ sâu bung bản mẫu vượt quá giới hạn cho phép.",
+       "expansion-depth-exceeded-category-desc": "Trang có độ sâu bung bản mẫu vượt quá giới hạn cho phép.",
        "expansion-depth-exceeded-warning": "Trang bung bản mẫu sâu quá",
        "parser-unstrip-loop-warning": "Vòng lặp unstrip",
        "parser-unstrip-recursion-limit": "Đã vượt quá giới hạn về độ sâu đệ quy unstrip ($1)",
        "rev-deleted-event": "(tác vụ nhật trình đã bị xóa)",
        "rev-deleted-user-contribs": "[tên người dùng hay địa chỉ IP bị ẩn – sửa đổi được ẩn khỏi danh sách đóng góp]",
        "rev-deleted-text-permission": "Phiên bản này đã bị '''xóa'''.\nCó thể có thêm chi tiết tại [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} nhật trình xóa].",
+       "rev-suppressed-text-permission": "Phiên bản này đã bị '''ẩn'''.\nCó thêm chi tiết tại [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} nhật trình ẩn].",
        "rev-deleted-text-unhide": "Phiên bản này đã bị '''xóa'''.\nCó thể có thêm chi tiết tại [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} nhật trình xóa].\nBạn vẫn có thể [$1 xem phiên bản này] nếu muốn.",
        "rev-suppressed-text-unhide": "Phiên bản này đã bị '''giấu'''.\nCó thể có thêm chi tiết tại [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} nhật trình giấu].\nBạn vẫn có thể [$1 xem phiên bản này] nếu muốn.",
        "rev-deleted-text-view": "Phiên bản này đã bị '''xóa'''.\nBạn vẫn có thể xem nó; có thể có thêm chi tiết tại [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} nhật trình xóa].",
        "revdelete-text-text": "Các phiên bản đã xóa sẽ tiếp tục xuất hiện trong lịch sử trang, nhưng một số phần của nội dung sẽ bị ẩn khỏi công chúng.",
        "revdelete-text-file": "Các phiên bản tập tin đã xóa sẽ tiếp tục xuất hiện trong lịch sử tập tin, nhưng một số phần của nội dung sẽ bị ẩn khỏi công chúng.",
        "logdelete-text": "Các sự kiện đã xóa sẽ tiếp tục xuất hiện trong nhật trình, nhưng một số phần của nội dung sẽ bị ẩn khỏi công chúng.",
-       "revdelete-text-others": "Các bảo quản viên khác trên {{SITENAME}} sẽ vẫn có quyền truy cập nội dung ẩn và có thể phục hồi nó qua cùng giao diện này, trừ khi có hạn chế bổ sung.",
+       "revdelete-text-others": "Các bảo quản viên khác sẽ vẫn có quyền truy cập nội dung ẩn và phục hồi nó qua cùng giao diện này, trừ khi có hạn chế bổ sung.",
        "revdelete-confirm": "Xin hãy xác nhận rằng bạn có ý định xóa, nhận biết tầm quan trọng của việc này, và việc xóa tuân theo [[{{MediaWiki:Policy-url}}|quy định]].",
        "revdelete-suppress-text": "Việc ẩn giấu '''chỉ''' nên dùng trong các trường hợp sau:\n* Thông tin có thể phỉ báng\n* Thông tin cá nhân không thích hợp\n*: ''địa chỉ nhà và số điện thoại, số chứng minh nhân dân, số an sinh xã hội, v.v.''",
        "revdelete-legend": "Thiết lập hạn chế khả kiến",
        "searchprofile-advanced-tooltip": "Tìm trong không gian tên tùy chọn",
        "search-result-size": "$1 ({{PLURAL:$2|1 từ|$2 từ}})",
        "search-result-category-size": "$1 trang thành viên ($2 thể loại con, $3 tập tin)",
-       "search-result-score": "Độ phù hợp: $1%",
        "search-redirect": "(đổi hướng $1)",
        "search-section": "(đề mục $1)",
        "search-file-match": "(khớp nội dung tập tin)",
        "searchall": "tất cả",
        "showingresults": "Dưới đây là {{PLURAL:$1|'''1'''|'''$1'''}} kết quả bắt đầu từ #'''$2'''.",
        "showingresultsinrange": "Dưới đây là cho tới <strong>$1</strong> kết quả từ #<strong>$2</strong> đến #<strong>$3</strong>.",
-       "showingresultsheader": "{{PLURAL:$5|Kết quả thứ '''$1''' trong tổng số '''$3''' kết quả|Các kết quả '''$1–$2''' trong tổng số '''$3''' kết quả}} cho '''$4'''",
        "search-nonefound": "Không có kết quả nào khớp với câu truy vấn.",
        "powersearch-legend": "Tìm kiếm nâng cao",
        "powersearch-ns": "Tìm trong không gian tên:",
        "preferences": "Tùy chọn",
        "mypreferences": "Tùy chọn",
        "prefs-edits": "Số lần sửa đổi:",
-       "prefsnologintext2": "Xin vui lòng $1 để thay đổi tùy chọn.",
+       "prefsnologintext2": "Xin vui lòng đăng nhập để thay đổi tùy chọn.",
        "prefs-skin": "Giao diện",
        "skin-preview": "Xem trước",
        "datedefault": "Không quan tâm",
        "prefs-custom-css": "sửa CSS",
        "prefs-custom-js": "sửa JS",
        "prefs-common-css-js": "CSS/JS chung cho mọi giao diện:",
-       "prefs-reset-intro": "Có thể mặc định lại toàn bộ tùy chọn dùng trang này.\nKhông có thể lùi lại tác động này.",
+       "prefs-reset-intro": "Có thể mặc định lại toàn bộ tùy chọn dùng trang này. Điều này không thể hoàn tác.",
        "prefs-emailconfirm-label": "Xác nhận thư điện tử:",
        "youremail": "Thư điện tử:",
        "username": "{{GENDER:$1}}Tên người dùng:",
        "right-deletedtext": "Xem văn bản đã xóa và các thay đổi giữa phiên bản đã xóa",
        "right-browsearchive": "Tìm kiếm trang đã bị xóa",
        "right-undelete": "Phục hồi trang",
-       "right-suppressrevision": "Xem và phục hồi phiên bản mà bảo quản viên không thấy",
+       "right-suppressrevision": "Xem và hiện/ẩn các phiên bản trang cụ thể đối với mọi người dùng khác",
+       "right-viewsuppressed": "Xem các phiên bản được ẩn mà mọi người khác không thấy được",
        "right-suppressionlog": "Xem nhật trình riêng tư",
        "right-block": "Cấm thành viên khác sửa đổi",
        "right-blockemail": "Cấm người dùng gửi thư điện tử",
        "recentchanges-legend-heading": "'''Chú giải:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (xem thêm [[Special:NewPages|danh sách các trang mới]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Các thay đổi từ <strong>$2</strong> (hiển thị tối đa <strong>$1</strong> thay đổi).",
+       "rcnotefrom": "Dưới đây là {{PLURAL:$5|thay đổi duy nhất|các thay đổi}} từ <strong>$3 $4</strong> (hiển thị tối đa <strong>$1</strong> thay đổi).",
        "rclistfrom": "Xem các thay đổi từ $2 $3 trở về sau",
        "rcshowhideminor": "$1 sửa đổi nhỏ",
        "rcshowhideminor-show": "Hiện",
        "ignorewarnings": "Bỏ qua cảnh báo",
        "minlength1": "Tên tập tin phải có ít nhất một ký tự.",
        "illegalfilename": "Tên tập tin “$1” có chứa ký tự không được phép dùng cho tựa trang. Xin hãy đổi tên và tải lên lại.",
-       "filename-toolong": "Tên tập tin không có thể dài quá 240 byte.",
+       "filename-toolong": "Tên tập tin không thể dài quá 240 byte.",
        "badfilename": "Tên tập tin đã được đổi thành “$1”.",
        "filetype-mime-mismatch": "Phần mở rộng của tập tin (“.$1”) không phù hợp kiểu MIME được nhận ra ($2).",
        "filetype-badmime": "Không thể tải lên các tập tin có kiểu MIME “$1”.",
        "uploadwarning": "Cảnh báo!",
        "uploadwarning-text": "Xin hãy chỉnh sửa miêu tả tập tin ở dưới và thử lại.",
        "savefile": "Lưu tập tin",
-       "uploadedimage": "đã tải “[[$1]]” lên",
-       "overwroteimage": "đã tải lên một phiên bản mới của “[[$1]]”",
        "uploaddisabled": "Chức năng tải lên đã bị khóa.",
        "copyuploaddisabled": "Chức năng tải lên từ địa chỉ URL đã bị tắt.",
        "uploaddisabledtext": "Chức năng tải tập tin đã bị tắt.",
        "license": "Giấy phép:",
        "license-header": "Giấy phép",
        "nolicense": "chưa chọn",
+       "licenses-edit": "Sửa các giấy phép",
        "license-nopreview": "(Không xem trước được)",
-       "upload_source_url": " (địa chỉ URL đúng, có thể truy cập)",
-       "upload_source_file": " (tập tin trên máy của bạn)",
+       "upload_source_url": "(URL hợp lệ của một tập tin ai có thể truy cập)",
+       "upload_source_file": "(tập tin trên máy của bạn)",
+       "listfiles-delete": "xóa",
        "listfiles-summary": "Trang đặc biệt này liệt kê các tập tin được tải lên.",
        "listfiles_search_for": "Tìm kiếm theo tên tập tin:",
        "imgfile": "tập tin",
        "shared-repo-from": "tại $1",
        "shared-repo": "kho lưu trữ dùng chung",
        "filepage.css": "/* Mã CSS tại đây sẽ ảnh hướng đến trang miêu tả tập tin, cũng như các wiki khách bên ngoài dựa trên wiki này */",
-       "upload-disallowed-here": "Bạn không có thể ghi đè lên tập tin này.",
+       "upload-disallowed-here": "Bạn không thể ghi đè lên tập tin này.",
        "filerevert": "Lùi lại phiên bản của $1",
        "filerevert-legend": "Lùi lại tập tin",
        "filerevert-intro": "Bạn đang lùi '''[[Media:$1|$1]]''' về [$4 phiên bản lúc $3, $2].",
        "randomincategory": "Trang ngẫu nhiên trong thể loại",
        "randomincategory-invalidcategory": "“$1” không phải tên thể loại hợp lệ.",
        "randomincategory-nopages": "Không có trang nào trong [[:Category:$1]].",
-       "randomincategory-selectcategory": "Xem trang ngẫu nhiên trong thể loại: $1 $2.",
-       "randomincategory-selectcategory-submit": "Xem",
+       "randomincategory-category": "Thể loại:",
+       "randomincategory-legend": "Trang ngẫu nhiên trong thể loại",
        "randomredirect": "Trang đổi hướng ngẫu nhiên",
        "randomredirect-nopages": "Không có trang đổi hướng nào trong không gian tên “$1”.",
        "statistics": "Thống kê",
        "wantedpages-badtitle": "Tiêu đề không hợp lệ trong tập kết quả: $1",
        "wantedfiles": "Tập tin cần thiết",
        "wantedfiletext-cat": "Các tập tin sau được nhúng nhưng không tồn tại. Các tập tin từ kho dùng chung có thể được liệt kê trong khi tồn tại; các trường hợp này được <del>gạch bỏ</del>. Ngoài ra, các trang nhúng tập tin không tồn tại được liệt kê tại [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Các tập tin bên dưới được sử dụng nhưng không tồn tại. Các trang nhúng những tập tin không tồn tại cũng được xếp trong [[:$1]].",
        "wantedfiletext-nocat": "Các tập tin sau được nhúng nhưng không tồn tại. Các tập tin từ kho dùng chung có thể được liệt kê trong khi tồn tại; các trường hợp này được <del>gạch bỏ</del>.",
+       "wantedfiletext-nocat-noforeign": "Các tập tin bên dưới được sử dụng nhưng không tồn tại.",
        "wantedtemplates": "Bản mẫu cần viết nhất",
        "mostlinked": "Trang được liên kết đến nhiều nhất",
        "mostlinkedcategories": "Thể loại có nhiều trang nhất",
        "trackingcategories-desc": "Tiêu chuẩn xếp thể loại",
        "noindex-category-desc": "Trang này không được các robot đánh chỉ mục vì trang có từ thần chú <code><nowiki>__NOINDEX__</nowiki></code> và nằm trong không gian tên cho phép từ thần chú này.",
        "index-category-desc": "Trang này có từ thần chú <code><nowiki>__INDEX__</nowiki></code> và nằm trong một không gian tên cho phép từ thần chú này, nên được các robot đánh chỉ mục, trong khi bình thường nó không được đánh chỉ mục.",
-       "post-expand-template-inclusion-category-desc": "Nếu bung tất cả các bản mẫu, kích thước trang sẽ vượt quá <code>$wgMaxArticleSize</code>, nên một số bản mẫu không được bung.",
-       "post-expand-template-argument-category-desc": "Nếu bung một tham số bản mẫu (tức định danh có mỗi bên ba dấu ngoặc móc, thí dụ <code>{{{Thí dụ}}}</code>), trang này sẽ vượt quá <code>$wgMaxArticleSize</code>.",
-       "expensive-parserfunction-category-desc": "Trang có quá nhiều hàm cú pháp cần mức độ xử lý cao (chẳng hạn như <code>#ifexist</code>). Xem [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit?uselang=vi Manual:$wgExpensiveParserFunctionLimit].",
-       "broken-file-category-desc": "Trang này muốn nhúng một tập tin không tồn tại.",
-       "hidden-category-category-desc": "Thể loại này có <code><nowiki>__HIDDENCAT__</nowiki></code>, nên, theo mặc định, thể loại không xuất hiện trong hộp thể loại trên các trang được xếp vào thể loại.",
+       "post-expand-template-inclusion-category-desc": "Kích thước trang sẽ vượt quá <code>$wgMaxArticleSize</code> nếu bung hết toàn bộ bản mẫu, nên một số bản mẫu không được bung.",
+       "post-expand-template-argument-category-desc": "Trang này sẽ vượt quá <code>$wgMaxArticleSize</code> nếu bung một tham số bản mẫu (tức định danh có mỗi bên ba dấu ngoặc móc, thí dụ <code>{{{Thí dụ}}}</code>).",
+       "expensive-parserfunction-category-desc": "Trang có quá nhiều hàm cú pháp cần mức độ xử lý cao (chẳng hạn như <code>#ifexist</code>). Xem [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "Trang này có một liên kết tập tin hỏng (liên kết nhúng tập tin không tồn tại).",
+       "hidden-category-category-desc": "Nội dung của trang thể loại này chứa <code><nowiki>__HIDDENCAT__</nowiki></code>, nên theo mặc định thì thể loại không xuất hiện trong thanh thể loại trên các trang được xếp vào thể loại.",
        "trackingcategories-nodesc": "Không có miêu tả.",
        "trackingcategories-disabled": "Thể loại bị tắt",
        "mailnologin": "Không có địa chỉ gửi thư",
        "mywatchlist": "Trang theo dõi",
        "watchlistfor2": "Của $1 $2",
        "nowatchlist": "Danh sách theo dõi của bạn không có gì.",
-       "watchlistanontext": "Xin hãy $1 để xem hay sửa đổi các trang được theo dõi.",
+       "watchlistanontext": "Xin hãy đăng nhập để xem hay sửa đổi các trang trong danh sách theo dõi của bạn.",
        "watchnologin": "Chưa đăng nhập",
        "addwatch": "Thêm vào danh sách theo dõi",
        "addedwatchtext": "Trang “[[:$1]]” đã vào [[Special:Watchlist|danh sách theo dõi]] của bạn.\nNhững sửa đổi đối với trang này và trang thảo luận của nó sẽ được liệt kê ở đấy.",
        "watchlist-details": "Bạn đang theo dõi {{PLURAL:$1}}$1 trang, không kể riêng các trang thảo luận.",
        "wlheader-enotif": "Đã bật thông báo qua thư điện tử.",
        "wlheader-showupdated": "Các trang đã thay đổi kể từ lần cuối bạn xem chúng được in '''đậm'''",
-       "wlnote2": "Bên dưới có các thay đổi vào <strong>$1</strong> giờ qua, vào lúc $3 $2.",
+       "wlnote": "Dưới đây là {{PLURAL:$1|thay đổi duy nhất|<strong>$1</strong> thay đổi gần nhất}} trong {{PLURAL:$2|giờ|<strong>$2</strong> giờ}} qua, tính tới $3 lúc $4.",
        "wlshowlast": "Hiển thị $1 giờ $2 ngày gần đây $3",
        "watchlist-options": "Tùy chọn về danh sách theo dõi",
        "watching": "Đang theo dõi…",
        "exbeforeblank": "nội dung trước khi tẩy trống: “$1”",
        "delete-confirm": "Xóa “$1”",
        "delete-legend": "Xóa",
-       "historywarning": "'''Cảnh báo:''' Trang bạn sắp xóa đã có lịch sử khoảng $1 {{PLURAL:$1|phiên bản|phiên bản}}:",
+       "historywarning": "<strong>Cảnh báo:</strong> Trang bạn sắp xóa đã có lịch sử $1 phiên bản:",
        "confirmdeletetext": "Bạn sắp xóa hẳn một trang cùng với tất cả lịch sử của nó.\nXin xác nhận việc bạn định làm, và hiểu rõ những hệ lụy của nó, và bạn thực hiện nó theo đúng đúng [[{{MediaWiki:Policy-url}}|quy định]].",
        "actioncomplete": "Đã thực hiện xong",
        "actionfailed": "Tác động bị thất bại",
        "delete-edit-reasonlist": "Sửa lý do xóa",
        "delete-toobig": "Trang này có lịch sử sửa đổi lớn, đến hơn {{PLURAL:$1|lần|lần}} sửa đổi.\nViệc xóa các trang như vậy bị hạn chế để ngăn ngừa phá hoại do vô ý cho {{SITENAME}}.",
        "delete-warning-toobig": "Trang này có lịch sử sửa đổi lớn, đến hơn {{PLURAL:$1|lần|lần}} sửa đổi.\nViệc xóa các trang có thể làm tổn hại đến hoạt động của cơ sở dữ liệu {{SITENAME}};\nhãy cẩn trọng khi thực hiện.",
+       "deleteprotected": "Bạn không thể xóa trang này vì nó đã được khóa lại.",
        "deleting-backlinks-warning": "'''Cảnh báo:''' Có [[Special:WhatLinksHere/{{FULLPAGENAME}}|trang khác]] liên kết đến hoặc nhúng trang mà bạn sắp xóa.",
        "rollback": "Lùi tất cả sửa đổi",
        "rollback_short": "Lùi tất cả",
        "autoblockid": "Cấm tự động #$1",
        "block": "Cấm người dùng",
        "unblock": "Bỏ cấm người dùng",
-       "blockip": "Cấm người dùng",
+       "blockip": "Cấm {{GENDER:$1}}người dùng",
        "blockip-legend": "Cấm người dùng",
        "blockiptext": "Dùng mẫu dưới để cấm một địa chỉ IP hoặc thành viên không được viết trang.\nĐiều này chỉ nên làm để tránh phá hoại, và phải theo [[{{MediaWiki:Policy-url}}|quy định]].\nĐiền vào lý do cụ thể ở dưới (ví dụ, chỉ ra trang nào bị phá hoại).",
        "ipaddressorusername": "Địa chỉ IP hay tên thành viên:",
        "import": "Nhập các trang",
        "importinterwiki": "Nhập giữa các wiki",
        "import-interwiki-text": "Chọn tên trang và wiki để nhập trang vào.\nNgày của phiên bản và tên người viết trang sẽ được giữ nguyên.\nTất cả những lần nhập trang từ wiki khác được ghi lại ở [[Special:Log/import|nhật trình nhập trang]].",
-       "import-interwiki-source": "Wiki/trang mã nguồn:",
+       "import-interwiki-sourcewiki": "Wiki nguồn:",
+       "import-interwiki-sourcepage": "Trang nguồn:",
        "import-interwiki-history": "Sao chép tất cả các phiên bản cũ của trang này",
        "import-interwiki-templates": "Gồm tất cả các bản mẫu",
        "import-interwiki-submit": "Nhập",
        "imported-log-entries": "Đã nhập {{PLURAL:$1|mục nhật trình|$1 mục nhật trình}}.",
        "importfailed": "Không nhập được: $1",
        "importunknownsource": "Không hiểu nguồn trang để nhập vào",
-       "importcantopen": "Không có thể mở tập tin để nhập vào",
+       "importcantopen": "Không thể mở tập tin để nhập vào",
        "importbadinterwiki": "Liên kết liên wiki sai",
        "importsuccess": "Nhập thành công!",
        "importnosources": "Không có nguồn nhập giữa wiki và việc nhập lịch sử bị tắt.",
        "import-error-create": "Trang “$1” không được nhập tại vì bạn không được phép tạo ra nó.",
        "import-error-interwiki": "Trang “$1” không được nhập vì tên của nó được dành riêng cho liên kết ngoài (liên wiki).",
        "import-error-special": "Trang “$1” không được nhập vì nó thuộc về không gian tên đặc biệt không cho phép các trang không mặc định.",
-       "import-error-invalid": "Trang “$1” không được nhập vì tên của nó không hợp lệ.",
+       "import-error-invalid": "Trang “$1” không được nhập vì ứng với một tên tập tin không hợp lệ trên wiki này.",
        "import-error-unserialize": "Không thể giải tuần tự hóa phiên bản $2 của trang “$1”. Tập tin kết xuất cho rằng phiên bản có mô hình nội dung $3 được tuần tự hóa theo định dạng $4.",
        "import-error-bad-location": "Không thể lưu giữ phiên bản $2 với mô hình nội dung $3 vào “$1” trên wiki này vì trang này không hỗ trợ mô hình đó.",
        "import-options-wrong": "{{PLURAL:$2|Tùy chọn|Các tùy chọn}} có vấn đề: <nowiki>$1</nowiki>",
        "importlogpage": "Nhật trình nhập trang",
        "importlogpagetext": "Đây là danh sách các trang được quản lý nhập vào đây. Các trang này có lịch sử sửa đổi từ hồi ở wiki khác.",
        "import-logentry-upload": "nhập vào [[$1]] bằng cách tải tập tin",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|phiên bản|phiên bản}}",
+       "import-logentry-upload-detail": "Đã nhập $1 phiên bản",
        "import-logentry-interwiki": "đã nhập vào $1 từ wiki khác",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|phiên bản|phiên bản}} từ $2",
+       "import-logentry-interwiki-detail": "Đã nhập $1 phiên bản từ $2",
        "javascripttest": "Kiểm thử JavaScript",
        "javascripttest-title": "Đang chạy $1 ca kiểm thử",
        "javascripttest-pagetext-noframework": "Trang này dành cho việc chạy các ca kiểm thử JavaScript.",
        "autosumm-replace": "Đã thay thế cả nội dung bằng “$1”",
        "autoredircomment": "Đổi hướng đến [[$1]]",
        "autosumm-new": "Tạo trang mới với nội dung “$1”",
+       "autosumm-newblank": "Đã tạo trang trống",
        "size-kilobytes": "$1 kB",
        "bitrate-bits": "$1 bps",
        "bitrate-kilobits": "$1 kbps",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|thảo luận]])",
        "unknown_extension_tag": "Không hiểu thẻ mở rộng “$1”",
        "duplicate-defaultsort": "Cảnh báo: Từ khóa xếp mặc định “$2” ghi đè từ khóa trước, “$1”.",
+       "duplicate-displaytitle": "<strong>Cảnh báo:</strong> Tên hiển thị “$2” ghi đè tên hiển thị “$1” bên trên.",
        "version": "Phiên bản",
        "version-extensions": "Các phần mở rộng được cài đặt",
        "version-skins": "Giao diện đã cài đặt",
        "logentry-rights-rights": "$1 {{GENDER:$2}}đã đổi các nhóm bao gồm $3 từ $4 đến $5",
        "logentry-rights-rights-legacy": "{{GENDER:$2}}$1 đã đổi các nhóm bao gồm $3",
        "logentry-rights-autopromote": "$1 {{GENDER:$2}}đã được tự động phong cấp từ $4 đến $5",
+       "logentry-upload-upload": "$1 {{GENDER:$2}}đã tải lên $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2}}đã tải lên một phiên bản mới của $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2}}đã tải lên $3",
        "rightsnone": "(không có)",
        "feedback-bugornote": "Nếu bạn đã sẵn sàng để miêu tả các chi tiết của một vấn đề kỹ thuật, xin vui lòng [$1 báo cáo lỗi].\nNếu không thì bạn có thể điền biểu mẫu đơn giản ở dưới. Lời ghi của bạn sẽ được đăng lên trang “[$3 $2]”, cùng với tên người dùng và trình duyệt của bạn.",
        "feedback-subject": "Tiêu đề:",
        "action-pagelang": "thay đổi ngôn ngữ của trang",
        "log-name-pagelang": "Nhật trình thay đổi ngôn ngữ",
        "log-description-pagelang": "Nhật trình này ghi các thay đổi ngôn ngữ của các trang.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2}}đã đổi ngôn ngữ của trang $3 từ $4 thành $5."
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2}}đã đổi ngôn ngữ của trang $3 từ $4 thành $5.",
+       "default-skin-not-found": "Đã xảy ra lỗi! Giao diện mặc định của wiki này được định nghĩa trong <code dir=\"ltr\">$wgDefaultSkin</code> là <code>$1</code> nhưng không tồn tại.\n\nViệc cài đặt của bạn dường như bao gồm những giao diện sau đây. Xin xem [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Skin_configuration Hướng dẫn: Cấu hình giao diện] để biết thông tin về cách kích hoạt hoặc chọn một trong số chúng làm giao diện mặc định.\n\n$2\n\n; Nếu bạn vừa mới cài đặt MediaWiki:\n: Có lẽ bạn đã cài đặt nó từ git, hoặc trực tiếp từ mã nguồn bằng cách sử dụng một số phương thức khác. Điều này đã nằm trong tính toán của chúng tôi. Hãy thử cài đặt một số giao diện từ [https://www.mediawiki.org/wiki/Category:All_skins thư mục giao diện của mediawiki.org] bằng cách:\n:* Tải về [https://www.mediawiki.org/wiki/Special:MyLanguage/Download trình cài đặt dưới dạng gói tar], trong đó có kèm theo một số giao diện và phần mở rộng. Bạn có thể chép nó và dán vào thư mục <code>skins/</code>.\n:*Sao chép một trong những kho <code>mediawiki/skins/*</code> thông qua git vào trong thư mục <code dir=\"ltr\">skins/</code> của cài đặt MediaWiki của bạn.\n: Cách này sẽ không có ảnh hưởng đến kho git của bạn dù bạn là một nhà phát triển MediaWiki.\n\n; Nếu bạn vừa mới nâng cấp MediaWiki:\n: Phiên bản MediaWiki 1.24 trở lên không còn tự động kích hoạt giao diện đã cài đặt (xem [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Hướng dẫn: Tự động dò giao diện]). Bạn có thể dán những dòng lệnh vào <code>LocalSettings.php</code> để kích hoạt tất cả giao diện hiện đã được cài dặt:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Nếu bạn vừa mới chỉnh sửa <code>LocalSettings.php</code>:\n: Kiểm tra lại tên các giao diện xem có lỗi đánh máy nào không.",
+       "default-skin-not-found-no-skins": "Đã xảy ra lỗi! Giao diện mặc định của wiki này được định nghĩa trong <code dir=\"ltr\">$wgDefaultSkin</code> là <code>$1</code> nhưng không tồn tại.\n\nKhông có giao diện nào của bạn được kích hoạt.\n\n; Nếu bạn vừa mới cài đặt MediaWiki:\n: Bạn có thể cài đặt nó từ git, hoặc trực tiếp từ mã nguồn bằng cách sử dụng một số phương thức khác. Điều này nằm trong dự kiến. Hãy thử cài đặt một số giao diện từ [https://www.mediawiki.org/wiki/Category:All_skins thư mục giao diện của mediawiki.org], bằng cách:\n:* Tải về [https://www.mediawiki.org/wiki/Special:MyLanguage/Download trình cài đặt dưới dạng gói tar], trong đó có kèm theo một số giao diện và phần mở rộng. Bạn có thể chép nó và dán vào thư mục <code>skins/</code>.\n:*Sao chép một trong những kho <code>mediawiki/skins/*</code> thông qua git vào trong thư mục <code dir=\"ltr\">skins/</code> của cài đặt MediaWiki của bạn.\n: Cách này sẽ không có ảnh hưởng đến kho git của bạn dù bạn là một nhà phát triển MediaWiki. Xin xem [https://www.mediawiki.org/wiki/Manual:Skin_configuration Hướng dẫn: Cấu hình giao diện] để biết thông tin về cách kích hoạt hoặc chọn một trong số chúng làm giao diện mặc định.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (kích hoạt)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''vô hiệu hóa''')"
 }
index 39099bc..8eefeb6 100644 (file)
        "talkpagelinktext": "Disghusjoon",
        "specialpage": "Schbedsjaal-sajdn",
        "personaltools": "Ajchne werchdsajch",
-       "postcomment": "Najn abschnid",
        "articlepage": "D'inhalds-sajdn dsajchn",
        "talk": "Disghusjoon",
        "views": "Ôôsichdn",
        "remembermypassword": "Miid den Brauser dauerhafd ogmeld bleim (maximal $1 {{PLURAL:$1|Dooch|Dooch}})",
        "login": "Ôômeldn",
        "nav-login-createaccount": "Oomeldn / Ghondoo ooleeng",
-       "loginprompt": "Zum Omelldn mäin Guggies agdivierd sei.",
        "userlogin": "Ôômeldn / Als Bajdräächâr ajschrajm",
        "logout": "Abmeldn",
        "userlogout": "Abmeldn",
        "searchprofile-advanced-tooltip": "Soung in weidere Namensraim",
        "search-result-size": "$1 ({{PLURAL:$2|1 wôrd|$2 wärdâr}})",
        "search-result-category-size": "{{PLURAL:$1|1 Seidn|$1 Seidn}} ({{PLURAL:$2|1 Untergadegorii|$2 Untergadegoriin}}, {{PLURAL:$3|1 Dadei|$3 Dadein}})",
-       "search-result-score": "Âjschleechich: $1 %",
        "search-redirect": "(Wajdalajdung fon „$1“ häa)",
        "search-section": "(Abschnid $1)",
        "search-suggest": "Hasd ajchndlich gmaand „$1“?",
        "upload": "Nauflôôdn",
        "uploadlogpage": "Brodoghol fom dadaj-hoochlôôdn",
        "filedesc": "Bschreibung",
-       "uploadedimage": "had „[[$1]]“ naufglôôdn",
        "license": "Lizenz",
        "license-header": "Lizenz",
        "file-anchor-link": "Daddei",
index b073f11..84c90c1 100644 (file)
        "talkpagelinktext": "Bespik",
        "specialpage": "Pad patik",
        "personaltools": "Stums pösodik",
-       "postcomment": "Diläd nulik",
        "articlepage": "Jonön ninädapadi",
        "talk": "Bespik",
        "views": "Logams",
        "externaldberror": "U ejenon fümükamapöl plödik nünödema, u no dalol atimükön kali plödik ola.",
        "login": "Nunädolös obi",
        "nav-login-createaccount": "Nunädön oki / jafön kali",
-       "loginprompt": "Mutol mögükön „kekilis“ ad kanön nunädön oli in {{SITENAME}}.",
        "userlogin": "Nunädön oki / jafön kali",
        "userloginnocreate": "Nunädön oki",
        "logout": "Senunädön oki",
        "searchprofile-advanced-tooltip": "Sukön in nemaspads patik",
        "search-result-size": "$1 ({{PLURAL:$2|vöd 1|vöds $2}})",
        "search-result-category-size": "{{PLURAL:$1|liman 1|limans $1}} ({{PLURAL:$2|donaklad 1|donaklads $2}}, {{PLURAL:$3|ragiv 1|ragivs $3}})",
-       "search-result-score": "Demäd: $1%",
        "search-redirect": "(lüodüköm: $1)",
        "search-section": "(diläd: $1)",
        "search-suggest": "Ediseinol-li: $1 ?",
        "file-deleted-duplicate": "Ragiv votik, kel leigon ko ragiv at ([[:$1]]), pemoükon büo. Sötol kontrolön moükamajenotemi ragiva et büä odönulöpükol oni.",
        "uploadwarning": "Löpükamanuned",
        "savefile": "Dakipolöd ragivi",
-       "uploadedimage": "\"[[$1]]\" pelöpüköl",
-       "overwroteimage": "fomami nulik ragiva: „[[$1]]“ pelöpükon",
        "uploaddisabled": "Löpükam penemögükon",
        "uploaddisabledtext": "Löpükam ragivas penemögükon.",
        "uploadscripted": "Ragiv at ninükon eli HTML u vödis programapüka, kelis bevüresodanaföm ba opölanätäpreton",
        "watchlist-details": "{{PLURAL:$1|pad $1|pads $1}} su galädalised, plä bespikapads.",
        "wlheader-enotif": "Nunam medü pot leäktronik pemögükon.",
        "wlheader-showupdated": "Pads pos visit lätik ola pevotüköls papenons '''me tonats bigik'''",
+       "wlnote": "Is palisedons votükam{{PLURAL:$1| lätik|s lätik '''$1'''}} dü düp{{PLURAL:$2| lätik|s lätik '''$2'''}}.",
        "wlshowlast": "Jonolöd: düpis lätik $1, delis lätik $2, $3",
        "watchlist-options": "Paramets galädaliseda",
        "watching": "Papladon ini galädalised...",
        "duplicate-defaultsort": "Nüned: Leodükamakik kösömik: „$2“ buon bu leodükamakik kösömik büik: „$1“.",
        "version": "Fomam",
        "version-extensions": "Veitükumams pestitöl",
-       "version-specialpages": "Pads patik",
        "version-skins": "Fomäts",
+       "version-specialpages": "Pads patik",
        "version-other": "Votik",
        "version-hooks": "Huköms",
        "version-hook-name": "Hukömanem",
index 3154416..28d38e7 100644 (file)
        "remembermypassword": "Mäleht minuu (enintään $1 {{PLURAL:$1|päivä|päivää}})",
        "login": "Cirjut süäme",
        "nav-login-createaccount": "Cirjut süäme vai registriiroit cäüttijässi",
-       "loginprompt": "Tüü piättä «cookies» võttamin luvata, štobõ entä sisteema ete esitellä.",
        "userlogin": "Cirjut süäme",
        "userloginnocreate": "Cirjut süäme",
        "logout": "Cirjut uloz",
        "filename": "Failinimi",
        "filedesc": "Turvotuz",
        "fileuploadsummary": "Turvotuz:",
-       "uploadedimage": "\"[[$1]]\" on laajõngoitõttu ülez",
        "license": "Litseenttsija:",
        "license-header": "Litseenttsija",
        "imgfile": "faili",
index b942a82..9461efe 100644 (file)
        "talkpagelinktext": "Arotus",
        "specialpage": "Tallituslehekülg",
        "personaltools": "Erätüüriistaq",
-       "postcomment": "Vahtsõnõ alajago",
        "articlepage": "Artiklilehekülg",
        "talk": "Arotus",
        "views": "Kaemisõq",
        "externaldberror": "Välitsen kimmästegemisteedüskogon om viga vai olõ-i sul lubat umma pruukjanimme muutaq.",
        "login": "Nimega sisseminek",
        "nav-login-createaccount": "Mineq nimega sisse",
-       "loginprompt": "{{SITENAME}} lask nimega sisse õnnõ sis, ku lubatas valmistuisi.",
        "userlogin": "Mineq nimega sisse vai luuq pruukjanimi",
        "userloginnocreate": "Nimega sisseminek",
        "logout": "Nime alt välläminek",
        "fileexists-shared-forbidden": "Sama nimega teedüstü om jo olõman jaetuidõ teedüstüide hulgan. Pästäq teedüstü mõnõ tõõsõ nime ala. Parhillanõ teedüstü: [[File:$1|thumb|center|$1]]",
        "uploadwarning": "Üleslaatmishoiatus",
        "savefile": "Pästäq teedüstü ärq",
-       "uploadedimage": "laadõ üles \"$1\"",
-       "overwroteimage": "üles laadit \"[[$1]]\" vahtsõnõ kujo",
        "uploaddisabled": "Üleslaatminõ lää-s kõrda",
        "uploaddisabledtext": "Teedüstü üleslaatminõ om keelet.",
        "uploadscripted": "Seol teedüstül om HTML-kuud vai skripte, minkast võrgokaeja või võlssi arvo saiaq.",
        "watchlist-details": "Perräkaemisnimekirän om {{PLURAL:$1|$1 leht|$1 lehte}}, rehkendämäldä arotuslehti.",
        "wlheader-enotif": "E-postiga teedäqandmisõq ommaq käügin.",
        "wlheader-showupdated": "Leheq, midä om muudõt päält su viimäst käümist, ommaq '''paksun kirän'''",
+       "wlnote": "Tan om '''$1''' {{PLURAL:$1|muutminõ|muutmist}} viimädse '''$2''' tunni ao seen.",
        "wlshowlast": "Näütäq viimädseq $1 tunni $2 päivä $3",
        "watchlist-options": "Perräkaemisnimekirä säädmine",
        "watching": "Pandas perräkaemisnimekirjä...",
index 6b870e7..a513fb8 100644 (file)
        "talkpagelinktext": "Copiner",
        "specialpage": "Pådje sipeciåle",
        "personaltools": "Usteyes da vosse",
-       "postcomment": "Novele seccion",
        "articlepage": "Vey l' årtike",
        "talk": "Copene",
        "views": "Vuwes",
        "yourdomainname": "Vosse dominne",
        "login": "S' elodjî",
        "nav-login-createaccount": "Ahiver on conte, udon-bén s' elodjî",
-       "loginprompt": "Vos dvoz permete les coûkes po vs elodjî so {{SITENAME}}.",
        "userlogin": "S' elodjî",
        "userloginnocreate": "S' elodjî",
        "logout": "Si dislodjî",
        "searchprofile-advanced-tooltip": "Tchoezixhoz les espåces di lomaedje ki vos vloz rwaitî pol cweraedje",
        "search-result-size": "$1 ($2 mot{{PLURAL:$2||s}})",
        "search-result-category-size": "$1 mimbe{{PLURAL:$1||s}} ($2 dizo-categoreye{{PLURAL:$2||s}}, $3 fitchî{{PLURAL:$3||s}})",
-       "search-result-score": "Pertinance: $1%",
        "search-redirect": "(redjiblé di $1)",
        "search-section": "(seccion $1)",
        "search-suggest": "Sayîz motoit çoula: $1",
        "search-interwiki-more": "(dipus)",
        "searchall": "totafwait",
        "showingresults": "Chal pa dzo {{PLURAL:$1|'''1''' rizultat|'''$1''' rizultats}} a pårti do limero '''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|Rizultat '''$1'''|Rizultats '''$1 - $2'''}} foû di '''$3'' po '''$4'''",
        "search-nonefound": "N' a rén di çou ki vs cweroz après",
        "powersearch-legend": "Pus spepieus rcweraedjes",
        "powersearch-ns": "Cweri ezès espåces di lomaedje:",
        "fileexists-shared-forbidden": "I gn a ddja on fitchî avou ç' no la e ridant des fitchîs pårtaedjîs.\nRivnoz s' i vs plait en erî et s' reberwetez l' fitchî dizo èn ôte no si vos vloz.\n[[File:$1|thumb|center|$1]]",
        "uploadwarning": "Adviertixhmint so l' eberwetaedje",
        "savefile": "Schaper l' fitchî",
-       "uploadedimage": "eberwetaedje di «[[$1]]»",
        "uploaddisabled": "Eberwetaedje di fitchîs dismetou",
        "uploaddisabledtext": "L' eberwetaedje di fitchîs a stî dismetou.",
        "uploadscripted": "Ci fitchî ci a-st å dvins do côde HTML ou on scripe ki pôreut esse må comprin pa on betchteu waibe.",
        "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'''",
+       "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 $3",
        "watchlist-options": "Tchuzes del djivêye des shuvous",
        "enotif_reset": "Mårker totes les pådjes come vizitêyes",
        "pageinfo-watchers": "Nombe di shuveus",
        "pageinfo-edits": "Nombe di candjmints",
        "pageinfo-authors": "Nombe d' oteurs diferins",
-       "markaspatrolleddiff": "Marké come patrouyî",
+       "markaspatrolleddiff": "Marké come ricoridjî",
        "markaspatrolledtext": "Marker cisse pådje ci come dedja patrouyeye",
        "patrol-log-page": "Djournå des patrouyaedjes",
        "patrol-log-header": "Çouchal c' est on djournå des modêyes k' ont stî patrouyeyes.",
        "watchlisttools-edit": "Vey et candjî l' djivêye des shuvous",
        "version": "Modêye des programes",
        "version-extensions": "Rawetes d' astalêyes",
+       "version-skins": "Peas",
        "version-specialpages": "Pådjes sipeciåles",
        "version-variables": "Variåves",
        "version-antispam": "Siconte do spam",
-       "version-skins": "Peas",
        "version-other": "Ôtes",
        "version-license": "Licince",
        "version-software": "Programes astalés",
index 6b032f6..7d6b931 100644 (file)
        "talkpagelinktext": "Hiruhimangraw",
        "specialpage": "Pinaurog nga pakli",
        "personaltools": "Mga pankalugaringon nga garamiton",
-       "postcomment": "Bag-o nga bahin",
        "articlepage": "Kitaa in may sulod nga pakli",
        "talk": "Hiruhimangraw",
        "views": "Mga paglantaw",
        "externaldberror": "Mayda authenticaton database error o diri ka tinutugotan pag-update an imo akwant ha gawas.",
        "login": "Sakob",
        "nav-login-createaccount": "Magpalista nga masakob / paghimo hin bag-o nga akawnt",
-       "loginprompt": "Kinahanglan mo hin mga kuki (''cookie'') para makapag log-in ha {{SITENAME}}.",
        "userlogin": "Magpasabot nga masakob / paghimo hin akawnt",
        "userloginnocreate": "Magpasabot nga masakob",
        "logout": "Gawas",
        "searchprofile-advanced-tooltip": "Pamilnga ha mga nabatasan nga ngaran-lat'ang",
        "search-result-size": "$1 ({{PLURAL:$2|1 nga pulong|$2 nga mga pulong}})",
        "search-result-category-size": "{{PLURAL:$1|1 nga api|$1 nga mga api}} ({{PLURAL:$2|1 nga ubos-nga-kaarangay|$2 nga mga ubos-nga-kaarangay}}, {{PLURAL:$3| 1 nga fayl|$3 nga mga fayl}})",
-       "search-result-score": "Pagkaangay: $1%",
        "search-redirect": "(redirekta $1)",
        "search-section": "(bahin $1)",
        "search-suggest": "Buot sidngon mo ba: $1",
        "windows-nonascii-filename": "Ini nga wiki in diri nakasuportado han mga ngaran-han-paypay nga may-ada pinaurog nga mga karakter.",
        "uploadwarning": "Pahimatngon han pagkarga paigbaw",
        "savefile": "Igtipig an paypay",
-       "uploadedimage": "ginkarga-paigbaw \"[[$1]]\"",
-       "overwroteimage": "Ginkaraga an bag-o nga bersyon han \"[[$1]]\"",
        "uploaddisabled": "Waray ginpagana an pagkarga paigbaw",
        "copyuploaddisabled": "An pagkarga paigbaw pinaagi hin URL in waray ginpagana",
        "uploaddisabledtext": "An mga pagkarga-paigbaw in diri ginpapagana.",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|hiruhimangraw]])",
        "duplicate-defaultsort": "'''Pahimatngon:''' An daan-aada nga paglainlain nga piridlitan nga \"$2\" in igsasapaw an durudaan nga daan-aada nga paglainlain nga piridlitan nga \"$1\".",
        "version": "Bersyon",
+       "version-skins": "Mga panit",
        "version-specialpages": "Mga pinaurog nga pakli",
        "version-parserhooks": "Mga kawil parser",
        "version-variables": "Mga variable",
        "version-antispam": "Pamugong hin spam",
-       "version-skins": "Mga panit",
        "version-other": "iba",
        "version-mediahandlers": "Mga nakapot han medya",
        "version-hooks": "Mga kawil",
index 665f693..e3a99fe 100644 (file)
        "talkpagelinktext": "Diisoo",
        "specialpage": "Xëtu jagleel",
        "personaltools": "Samay jumtukaay",
-       "postcomment": "Xaaj bu bees",
        "articlepage": "Gis jukki bi",
        "talk": "Waxtaan",
        "views": "Xool yo",
        "externaldberror": "Njuumte judd na ci dàttub njoxe bi, walla day ni rekk amuloo sañ-sañu yeesal sa sàqum biti.",
        "login": "xammeeku",
        "nav-login-createaccount": "Dugg / Bindu",
-       "loginprompt": "Faaw nga doxal cookie yi ngir man a dugg ci {{SITENAME}}.",
        "userlogin": "Dugg / Bindu",
        "logout": "Génnu",
        "userlogout": "Génnu",
        "searchprofile-everything-tooltip": "Seet fépp (ba ci xëti waxtaanuwaay yi)",
        "searchprofile-advanced-tooltip": "Seet ci barabi tur yi",
        "search-result-size": "$1 ({{PLURAL:$2|1 baat|$2 baat}})",
-       "search-result-score": "Baaxaay: $1%",
        "search-redirect": "(jubluwaat bu jëm $1)",
        "search-section": "(xaaj $1)",
        "search-suggest": "Xéj-na lii nga doon seet: $1",
        "file-exists-duplicate": "ŋara wi ñaaralub {{PLURAL:$1| ŋara wii di toftal la| ŋara yii di toftal lañu}} :",
        "uploadwarning": "Moytul !",
        "savefile": "Denc dencukaay bi",
-       "uploadedimage": "Yeb na « [[$1]] »",
-       "overwroteimage": "moo yeb sumb bu bees bu « [[$1]] »",
        "uploaddisabled": "Di jéeggalu, yebug dencukaay yi dañ koo doxadilandi.",
        "uploaddisabledtext": "Yebug dencukaay yi dañ koo doxadil.",
        "uploadscripted": "Wii ŋara dafa am yoonug HTML walla ab script bu ab joowukaayub web mana tekke ci anam gu baaxul.",
        "unwatchthispage": "Bul toppati",
        "watchlist-details": "Topp nga $1 {{PLURAL:$1|xët|ciy xët}}, soo waññiwaalewul xëti waxtaanuwaay yi.",
        "wlheader-showupdated": "Xët yi ñu soppiwoon ca sa duggu bu mujj ñoom la ñu fesal ñu <b>xëm</b>",
+       "wlnote": "Fii ci suuf {{PLURAL:$1| ngay gis coppite yu mujj yi|ngay gis $1 coppite yu mujj}} ci {{PLURAL:$2|waxtu gu mujj gi|<b>$2</b> waxtu yu mujj}}.",
        "wlshowlast": "wone $1 waxtu yu mujj, $2 bess yu mujj, walla $3.",
        "watchlist-options": "Tànneefi limu toppte bi",
        "watching": "Topp...",
index 5778823..c140890 100644 (file)
@@ -14,7 +14,9 @@
                        "Mywood",
                        "Cwek",
                        "Duolaimi",
-                       "Impersonator 1"
+                       "Impersonator 1",
+                       "LNDDYL",
+                       "TheChampionMan1234"
                ]
        },
        "tog-underline": "鏈接下橫線:",
@@ -41,7 +43,7 @@
        "tog-shownumberswatching": "顯示關注人數",
        "tog-oldsig": "能界签名先望:",
        "tog-fancysig": "畀簽名當wiki文本(弗自動鏈接)",
-       "tog-uselivepreview": "用当场先望(试验)",
+       "tog-uselivepreview": "用當場先望(試驗)",
        "tog-forceeditsummary": "編要空白到提醒我",
        "tog-watchlisthideown": "關注表裏囥脫我所編",
        "tog-watchlisthidebots": "關注表裏囥脫機器人所編",
        "talkpagelinktext": "討論",
        "specialpage": "特別頁",
        "personaltools": "私人家伙",
-       "postcomment": "新段",
        "articlepage": "望內容頁",
        "talk": "探讨",
        "views": "望",
        "currentevents-url": "Project:箇阶段个事干",
        "disclaimers": "甮追問",
        "disclaimerpage": "Project:甮追問",
-       "edithelp": "ç¼\96å\86\99帮助",
+       "edithelp": "編寫幫助",
        "mainpage": "封面",
        "mainpage-description": "封面",
        "policy-url": "Project:策略",
-       "portal": "社å\8cºå\8f°é\97¨",
-       "portal-url": "Project:社å\8cºå\8f°é\97¨",
+       "portal": "社å\8d\80è\87ºé\96\80",
+       "portal-url": "Project:社å\8d\80è\87ºé\96\80",
        "privacy": "隱私策略",
        "privacypage": "Project:隱私策略",
        "badaccess": "权限",
        "externaldberror": "迭个作兴是由于验证数据库错误或者侬拨禁止更新侬个外部账号。",
        "login": "登进去",
        "nav-login-createaccount": "登进去 / 建账号",
-       "loginprompt": "必须用缓存(cookies)好登进{{SITENAME}}。",
        "userlogin": "登进去 / 建账号",
        "userloginnocreate": "登录",
        "logout": "登出",
        "gotaccountlink": "登录",
        "userlogin-resetlink": "忘记登录细节?",
        "userlogin-resetpassword-link": "转设密码",
-       "userlogin-loggedin": "你侬用{{GENDER:$1|$1}}登进来哉。用下向个表以别样身份登进。",
-       "userlogin-createanother": "建别样账号",
        "createacct-emailrequired": "电子信地址",
        "createacct-emailoptional": "电子信地址(填弗填由你)",
        "createacct-email-ph": "畀你侬个电子信地址打进去",
        "searchprofile-advanced-tooltip": "垃拉自定义名字空间里向搜索",
        "search-result-size": "$1($2字)",
        "search-result-category-size": "$1个成员($2个儿分类,$3个文件)",
-       "search-result-score": "相关度:$1%",
        "search-redirect": "(转戳到 $1)",
        "search-section": "(段落 $1)",
        "search-suggest": "你侬是寻:$1",
        "windows-nonascii-filename": "箇wiki弗支持文件名用特別個字符。",
        "uploadwarning": "上载警告",
        "savefile": "保存文件",
-       "uploadedimage": "上传 \"[[$1]]\"",
        "sourcefilename": "源文件:",
        "destfilename": "目标文件名:",
        "watchthisupload": "關注箇文件",
        "filedelete-maintenance-title": "文件刪弗爻",
        "download": "下载",
        "listredirects": "重定向列表",
-       "unusedtemplateswlh": "å\88¥æ¨£鏈接",
+       "unusedtemplateswlh": "å\85¶ä»\96鏈接",
        "randompage": "随便望望",
        "randomincategory": "分類裏個隨便一頁",
-       "randomincategory-selectcategory-submit": "去",
        "statistics": "统计",
        "statistics-header-users": "用户资料",
        "statistics-users-active": "活跃用户",
index 596b8d7..c952187 100644 (file)
        "talkpagelinktext": "Меткән",
        "specialpage": "Көдлхнә халх",
        "personaltools": "Эврән зер-зев",
-       "postcomment": "Шин хүв",
        "articlepage": "Зүүл үзх",
        "talk": "Меткән",
        "views": "Хәләврүд",
        "yourdomainname": "Тана домен:",
        "login": "Орлһн",
        "nav-login-createaccount": "Харһх / бичгдлһн кех",
-       "loginprompt": "{{SITENAME}} тал орлһна төлә, та «cookies» олзлдг кергтә.",
        "userlogin": "Орх аль бичгдлһиг бүтәх",
        "userloginnocreate": "Харһх",
        "logout": "Һарх",
        "searchprofile-articles-tooltip": "$1 гидг зүүлд хәәх",
        "searchprofile-images-tooltip": "Боомг хәәх",
        "search-result-size": "$1 ({{PLURAL:$2|$2 үг|$2 үгмүд|$2 үгмүд}})",
-       "search-result-score": "Әдлцән: $1 %",
        "search-redirect": "(авч одлһн $1)",
        "search-section": "($1 хүв)",
        "search-suggest": "Та эниг таанат: $1 ?",
        "filedesc": "Учр-утх",
        "fileuploadsummary": "Учр-утх:",
        "savefile": "Хадһлх",
-       "uploadedimage": "«[[$1]]» тәвв",
        "upload-success-subj": "Йовудта тәвллһн",
        "license": "Закан:",
        "license-header": "Закан:",
index c8c247b..c71079f 100644 (file)
        "yourdomainname": "თქვან დომენ",
        "login": "მიშულა",
        "nav-login-createaccount": "მიშულა/ანგარიშიშ გონწყუმა",
-       "loginprompt": "{{SITENAME}}-შა მიშაულარო ოხვილუთ ეკაკილეფიშ (cookies) გოაქტიურაფას.",
        "userlogin": "მიშულა/ანგარიშიშ გონწყუმა",
        "logout": "გიშულა",
        "userlogout": "გიშულა",
        "uploadbtn": "ფაილიშ გეთება",
        "uploadlogpage": "ეხარგუაშ ორეგისტრირებელ ჟურნალ",
        "filedesc": "რეზიუმე",
-       "uploadedimage": "ეხარგელი რე \"[[$1]]\"",
        "license": "ლიცენზირაფა:",
        "license-header": "ლიცენზირაფა",
        "listfiles": "სურათეფიშ ერკებულ",
index 816bf32..f07949a 100644 (file)
@@ -28,6 +28,7 @@
        "tog-watchdefault": "צולייגן בלעטער וואס איך רעדאקטיר צו מיין אכטונג ליסטע",
        "tog-watchmoves": "צולייגן בלעטער וואס איך באוועג און טעקעס וואס איך לאד ארויף צו מיין אכטונג ליסטע",
        "tog-watchdeletion": "צולייגן בלעטער וואס איך מעק אויס צו מיין אויפפאסונג ליסטע",
+       "tog-watchrollback": "צולייגן צו מיין אויפפאסן ליסטע בלעטער אויף וואס איך האב אדורכגעפירט א צוריקשטעלן.",
        "tog-minordefault": "באגרענעצן אלע רעדאַקטירונגען גרונטלעך אלס מינערדיק",
        "tog-previewontop": "צײַג די \"פֿאָרויסיגע װײַזונג\" גלײַך בײַ דער ערשטער באַאַרבעטונג",
        "tog-previewonfirst": "ווייזן פֿאראויסדיגע ווייזונג בײַ דער ערשטער רעדאקטירונג",
        "talkpagelinktext": "שמועס",
        "specialpage": "ספעציעלער בלאט",
        "personaltools": "פערזענלעכע געצייג",
-       "postcomment": "נייע אפטיילונג",
        "articlepage": "זען אינהאַלט בלאַט",
        "talk": "שמועס",
        "views": "קוקן",
        "hidetoc": "באַהאַלטן",
        "collapsible-collapse": "אײַנציען",
        "collapsible-expand": "פֿאַרברייטערן",
+       "confirmable-confirm": "צי זענט {{GENDER:$1|איר}} זיכער?",
+       "confirmable-yes": "יא",
+       "confirmable-no": "ניין",
        "thisisdeleted": "זען אדער צוריקשטעלן $1?",
        "viewdeleted": "זען $1?",
        "restorelink": "{{PLURAL:$1|איין געמעקטע ענדערונג|$1 געמעקטע ענדערונגען}}",
        "invalidtitle-knownnamespace": "אומגילטירער טיטל מיט נאמענטייל \"$2\" און טעקסט \"$3\"",
        "invalidtitle-unknownnamespace": "אומגילטיקער טיטל מיט אומבאוואוסטן נאמענטייל נומער $1 און טעקסט \"$2\"",
        "exception-nologin": "נישט אַרײַנלאגירט",
-       "exception-nologin-text": "×\90×\99ר ×©×\90פר×\98 ×\96×\99×\99×\9f [[Special:Userlogin|×\90ר×\99×\99× ×\9c×\90×\92×\99ר×\98]] to כדי צו קענען צוקומען צו דעם בלאט אדער דער אקציע.",
+       "exception-nologin-text": "×\96ײַ×\98 ×\90×\96×\95×\99 ×\92×\95×\98 ×\90רײַנ×\9c×\90×\92×\99ר×\9f כדי צו קענען צוקומען צו דעם בלאט אדער דער אקציע.",
        "exception-nologin-text-manual": "זייט אזוי גוט $1 כדי צו קענען צוקומען צו דעם בלאט אדער דער אקציע.",
        "virus-badscanner": "שלעכטע קאנפֿיגוראציע: אומבאוואוסטער ווירוס איבערקוקער: ''$1''",
        "virus-scanfailed": "איבערקוקן נישט געראטן (קאד: $1)",
        "externaldberror": "עס איז אדער פארגעקומען אן אויטענטיקאציע דאטנבאזע פעלער אדער איר זענט נישט ערמעגליכט צו דערהיינטיגן אייער דרויסנדיגע קאנטע.",
        "login": "אַרײַנלאָגירן",
        "nav-login-createaccount": "ארײַנלאָגירן / זיך אײַנשרײַבן",
-       "loginprompt": "איר מוסט ערלויבן קיכלעך (\"cookies\") אויף צו אַרײַנלאָגירן אינעם {{SITENAME}}.",
        "userlogin": "ארײַנלאָגירן / זיך אײַנשרײַבן",
        "userloginnocreate": "אַרײַנלאגירן",
        "logout": "אַרױסלאָגירן",
        "userlogin-resetlink": "פארגעסן אײַערע אַרײַנלאָגירן פרטים?",
        "userlogin-resetpassword-link": "פֿאַרגעסן אײַער פאַסווארט?",
        "userlogin-helplink2": "הילף מיט ארײַנלאגירן",
-       "userlogin-loggedin": "איר זענט שוין אריינלאגירט ווי {{GENDER:$1|$1}}.\nניצט די פארעם אונטן כדי אריינלאגירן ווי אן אנדער באניצער.",
-       "userlogin-createanother": "שאפֿן נאך א קאנטע",
        "createacct-emailrequired": "בליצפּאָסט אַדרעס",
        "createacct-emailoptional": "בליצפאסט אדרעס (אפציאנאל)",
        "createacct-email-ph": "קלאַפט ארײַן אײַער בליצפּאָסט אַדרעס",
        "changeemail-cancel": "אַנולירן",
        "changeemail-throttled": "איר האט געפרוווט צופֿיל מאל אריינלאגירן.\nזייט אזוי גוט און וואַרט $1 איידער איר פרוווט נאכאמאל.",
        "resettokens": "צוריקזעצן טאקנס",
+       "resettokens-text": "דא קענט איר צוריקשטעלן טאקנס וואס דערלויבן צוטריט צו געוויסע פריוואטע דאטן שייך צו אײַער קאנטע.\n\nYou should do it if you accidentally shared them with someone or if your account has been compromised.",
        "resettokens-no-tokens": "נישט פאראן קיין טאקנס צוריקצוזעצן.",
        "resettokens-legend": "צוריקזעצן טאקנס",
        "resettokens-tokens": "טאקנס:",
        "preview": "פֿאראויסקוק",
        "showpreview": "ווײַזן פֿאָרױסקוק",
        "showdiff": "ווײַז די ענדערונגען",
-       "anoneditwarning": "'''ווארענונג:''' איר זענט נישט אריינלאגירט אין אייער קאנטע. אייער איי פי אדרעס וועט ווערן דאקומענטירט אין דעם בלאטס היסטאריע פון ענדערונגען. אויב זארגט איר זיך פאר פריוואטקייטן, ביטע טוט זיך אריינלאגירן.",
+       "blankarticle": "<strong>אזהרה:</strong> דער בלאט איר גייט שאפן איז ליידיק.\nטאמער איר וועט דריקן אויף \"{{int:savearticle}}\" נאכאמאל, וועט דער בלאט ווערן געשאפן אן קיין אינהאלט.",
+       "anoneditwarning": "<strong>ווארענונג:</strong> איר זענט נישט אריינלאגירט. אייער איי פי אדרעס וועט ווערן עפנטלעך זעבאר ווען איר פירט דורך  ענדערונגען . אז איר <strong>[$1 לאגירט ארײַן]</strong> אדער <strong>[$2 שאפט א קאנטע]</strong>, וועלן אײַערע רעדאקטירונגען ווערן צוגעשריבן צו אײַער באניצער-נאמען, ווי אויך אנדערע טובות.",
        "anonpreviewwarning": "''איר זענט נישט אַרײַנלאגירט. אויפֿהיטן וועט ארײַנשרײַבן אײַער IP אַדרעס אין דער רעדאַקטירונג היסטאריע פונעם בלאַט.''",
        "missingsummary": "'''דערמאנונג:''' איר האט נישט אויסגעפילט דעם קורץ ווארט אויפקלערונג אויף אייער עדיט. אויב וועט איר דרוקן נאכאמאל אויף  \"היט אפ דעם בלאט\", וועט אייער ענדערונג ווערן געהיטן אן דעם.",
        "missingcommenttext": "ביטע שטעלט אריין א אנמערקונג פון אונטן.",
        "parser-template-recursion-depth-warning": "מוסטער רעקורסיע טיף מאקסימום איבערגעשטיגן ($1)",
        "language-converter-depth-warning": "אַריבער דעם שפּראַך קאַנווערטער טיף לימיט ($1)",
        "node-count-exceeded-category": "בלעטער וואו קנופצאל איז צו פיל",
-       "node-count-exceeded-category-desc": "×\90 ×§×\90×\98×¢×\92×\90ר×\99×¢ ×¤×\90ר ×\91×\9c×¢×\98ער ×\95×\95×\90×\95 ×\93×\99 ×§× ×\95פצ×\90×\9c ×\90×\99×\96 ×¦×\95 ×¤×\99ל.",
-       "node-count-exceeded-warning": "קנ×\95פנצ×\90×\9c ×\90×\95×\99פ×\9f ×\91×\9c×\90×\98 ×¦×\95 ×\94×\95×\99×\9a",
+       "node-count-exceeded-category-desc": "×\93×\99ר ×\91×\9c×\90×\98 ×©×\98×\99×\99×\92×\98 ×\90×\99×\91ער ×\93×\99 ×\9e×\90קס×\99×\9e×\95×\9d ×§× ×\95פצ×\90ל.",
+       "node-count-exceeded-warning": "×\93ער ×\91×\9c×\90×\98 ×\90×\99×\96 ×\90×\99×\91ער×\92עש×\98×\99×\92×\9f ×\93×¢×\9d ×§× ×\95פנצ×\90×\9c",
        "expansion-depth-exceeded-category": "בלעטער וואו מ'האט אריבערגעשטיגן די פארברייטערונג טיף",
-       "expansion-depth-exceeded-category-desc": "×\93×\90ס ×\90×\99×\96 ×\90 ×§×\90×\98×¢×\92×\90ר×\99×¢ ×¤×\90ר ×\91×\9c×¢×\98ער ×\95×\95×\90ס ×©×\98×\99×\92×\9f ×\90×\99×\91ער ×\93ער פארברייטערן־טיף.",
+       "expansion-depth-exceeded-category-desc": "×\93ער ×\91×\9c×\90×\98 ×©×\98×\99×\99×\92×\98 ×\90×\99×\91ער ×\93×\99 פארברייטערן־טיף.",
        "expansion-depth-exceeded-warning": "בלאט גייט אריבער דער פארברייטערונג טיף",
        "parser-unstrip-loop-warning": "פעטליע געטראפֿן",
        "converter-manual-rule-error": "געטראפן א גרײַז אין האנטלעכן שפראך־קאנווערטירן כלל",
        "rev-deleted-event": "(לאגירן אקציע אראפגענומען)",
        "rev-deleted-user-contribs": "[באַניצער נאָמען אָדער IP אַדרעס אראפגענומען - רעדאַקטירונג פֿאַרבאָרגן פֿון בייַשטייַערונגען]",
        "rev-deleted-text-permission": "די בלאט רעוויזיע איז געווארן '''אויסגעמעקט '''.\nעס איז מעגלעך דא נאך פרטים אין דעם\n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} אויסמעקונג לאג].",
+       "rev-suppressed-text-permission": "די בלאט רעוויזיע איז געווארן <strong>אונטערדריקט</strong>. מען קען געפינען נאך פרטים אין דעם [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} אונטערדריקן לאגבוך].",
        "rev-deleted-text-unhide": "די בלאט רעוויזיע איז געווארן '''אויסגעמעקט '''.\nעס איז מעגלעך דא נאך פרטים אין דעם\n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} אויסמעקונג לאג].\nאיר קענט נאך  [$1 באקוקן די רעוויזיע] אויב איר ווילט גיין ווײַטער.",
        "rev-suppressed-text-unhide": "די בלאט רעוויזיע איז געווארן '''באהאלטן'''.\nעס איז מעגלעך דא נאך פרטים אין דעם [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} באהעלטעניש לאג].\nאיר קענט נאך [$1 באקוקן די רעוויזיע] אויב איר ווילט גיין ווײַטער.",
        "rev-deleted-text-view": "די בלאט רעוויזיע איז געווארן '''אויסגעמעקט'''.\nאיר קענט זען זי;\nעס איז מעגלעך דא נאך פרטים אין דעם [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} אויסמעקונג לאג].",
        "revdelete-text-text": "אויסגעמעקטע ווערסיעס וועלן נאך דערשיינען אין דער בלאט־היסטאריע, אבער טייל פון זייער אינהאלט וועט נישט זײַן צוגאנגבאר צום עולם.",
        "revdelete-text-file": "אויסגעמעקטע טעקע ווערסיעס וועלן נאך דערשיינען אין דער בלאט־היסטאריע, אבער טייל פון זייער אינהאלט וועט נישט זײַן צוגאנגבאר צום עולם.",
        "logdelete-text": "אויסגעמעקטע לאגביכער־געשעענישן וועלן נאך דערשיינען אינעם לאגבוך, אבער טייל פון זייער אינהאלט וועט נישט זײַן צוגאנגבאר צום עולם.",
-       "revdelete-text-others": "×\90× ×\93ערע ×¡×\99ס×\90פ×\9f ×\91×\99×\99 {{SITENAME}} ×\95×\95×¢×\9c×\9f × ×\90×\9a ×§×¢× ×¢×\9f ×¦×\95ק×\95×\9e×¢×\9f ×¦×\95×\9d ×\91×\90×\94×\90×\9c×\98×¢× ×¢×\9d ×\90×\99× ×\94×\90×\9c×\98 ×\90×\95×\9f ×§×¢× ×¢×\9f ×\90×\99×\9d ×¦×\95ר×\99קש×\98×¢×\9c×\9f ×\93×\95ר×\9b×\9f ×\96×¢×\9c×\91×\9f ×\90×\99×\99×\91ערפ×\9c×\90×\9a, סײַדן ווען מען שטעלט נאך באשרענקונגען.",
+       "revdelete-text-others": "×\90× ×\93ערע ×¡×\99ס×\90פ×\9f ×\95×\95×¢×\9c×\9f × ×\90×\9a ×§×¢× ×¢×\9f ×¦×\95ק×\95×\9e×¢×\9f ×¦×\95×\9d ×\91×\90×\94×\90×\9c×\98×¢× ×¢×\9d ×\90×\99× ×\94×\90×\9c×\98 ×\90×\95×\9f ×§×¢× ×¢×\9f ×\90×\99×\9d ×¦×\95ר×\99קש×\98×¢×\9c×\9f, סײַדן ווען מען שטעלט נאך באשרענקונגען.",
        "revdelete-confirm": "זייט אזוי גוט און באשטעטיקט אז דאס איז טאקע אייער כוונה, אז איר פארשטייט די קאנסעקווענצן, און אז איר טוט דאס לויט  [[{{MediaWiki:Policy-url}}|דער פאליסי]].",
        "revdelete-suppress-text": "אונטערדרוקן זאל בלויז גענוצט ווערן '''נאר''' אין די פאלגנדע פעלער:\n* אינפארמאציע וואס קען זיין מוציא שם רע\n* אויפדעקונג פון פריוואטקייט אינפארמאציע\n*: ''היים אדרעסן, טעלעפאן נומערן, נאציאנאלע אידענטיפיקאציע נומערן, א.א.וו.''",
        "revdelete-legend": "שטעלט ווייזונג באגרענעצונגען",
        "searchprofile-advanced-tooltip": "זוכן אין צוגעשטעלטע ָנאָמענטיילן",
        "search-result-size": "$1 ({{PLURAL:$2|איין ווארט|$2 ווערטער}})",
        "search-result-category-size": "{{PLURAL:$1|1 מיטגליד|$1 מיטגלידער}} ({{PLURAL:$2|1 אונטער־קאַטעגאריע|$2 אונטער־קאַטעגאריעס}}, {{PLURAL:$3|1 טעקע|$3 טעקעס}})",
-       "search-result-score": "שייכותדיקייט: $1%",
        "search-redirect": "(ווײַטערפֿירן $1)",
        "search-section": "(אפטיילונג $1)",
        "search-file-match": "(פאסט צו טעקע אינהאלט)",
        "preferences": "פרעפֿערענצן",
        "mypreferences": "פּרעפֿערענצן",
        "prefs-edits": "צאָל ענדערונגען:",
-       "prefsnologintext2": "זייט אזוי גוט $1 כדי צו שטעלן באניצער פרעפערענצן.",
+       "prefsnologintext2": "זייט אזוי גוט ארײַנלאגירן כדי צו ענדערן אײַערי באניצער פרעפערענצן.",
        "prefs-skin": "סקין",
        "skin-preview": "פארויסדיגע ווייזונג",
        "datedefault": "נישטא קיין פרעפערענץ",
        "right-deletedtext": "באַקוקן אויסגעמעקטן טעקסט און ענדערונגען צווישן אויסגעמעקטע ווערסיעס",
        "right-browsearchive": "זוכן אויסגעמעקטע בלעטער",
        "right-undelete": "צוריקשטעלן א בלאט",
-       "right-suppressrevision": "קוק-איבער און דריי-צוריק רעוויזיעס באהאלטן פון אדימיניסטראטורן",
+       "right-suppressrevision": "איבערקוקן, באהאלטן און אויפדעקן געוויסע רעוויזיעס פון בלעטער פאר אלע באניצער",
+       "right-viewsuppressed": "באקוקן רעוויזיעס באהאלטן פון אלע באניצער",
        "right-suppressionlog": "זען פריוואַטע לאגביכער",
        "right-block": "בלאקירן אַנדערע באַניצער פֿון רעדאַקטירן",
        "right-blockemail": "בלאקירן א באַניצער פֿון שיקן ע־פאסט",
        "recentchanges-legend-heading": "'''לעגענדע:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (זעט אויך [[Special:NewPages|די רשימה פון נייע בלעטער]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "פֿאלגנד זענען די ענדערונגען זײַט <strong>$2</strong> (ביז <strong>$1</strong>).",
+       "rcnotefrom": "פֿאלגנד {{PLURAL:$5|איז די ענדערונג| זענען די ענדערונגען}} זײַט <strong>$3, $4</strong> (ביז <strong>$1</strong>).",
        "rclistfrom": "װײַזן נײַע ענדערונגען פֿון $3 $2",
        "rcshowhideminor": "$1 מינערדיגע ענדערונגען",
        "rcshowhideminor-show": "ווײַזן",
        "uploadwarning": "אַרויפֿלאָדן וואָרענונג",
        "uploadwarning-text": "זײַט אַזוי גוט מאדיפֿיצירן די טעקע באַשרייבונג און פרובירט נאכאַמאָל.",
        "savefile": "אױפֿהיטן טעקע",
-       "uploadedimage": "אַרױפֿגעלאָדן \"[[$1]]\"",
-       "overwroteimage": "אַרויפֿגעלאָדן א נײַע ווערסיע פון \"[[$1]]\"",
        "uploaddisabled": "אַרויפֿלאָדן טעקעס מבוטל",
        "copyuploaddisabled": "ארויפלאדן דורך URL אומאקטיווירט",
        "uploaddisabledtext": "אַרויפֿלאָדן טעקעס נישט דערמעגלעכט.",
        "upload-options": "אַרויפֿלאָדן ברירה'ס",
        "watchthisupload": "אויפֿפאַסן דעם בלאט",
        "filewasdeleted": "א טעקע מיט דעם נאמען האט מען שוין ארויפגעלאדן און דערנאך אויסגעמעקט.\nאיר זאלט בודק זיין דעם $1 איידער איר הייבט אן ארויפלאדן ווידעראמאל.",
+       "filename-bad-prefix": "דער נאמען פון דער טעקע וואס איר לאדט ארויף הייבט אן מיט  <strong>\"$1\"</strong>, וואס איז אן אלגעמיינער נאמען געשטעלט פון א דיגיטאלישער קאמערע.\nזײַט אזוי גוט קלויבט א נאמען פאר דער טעקע ואס באשרײַבט איר אינהאלט.",
        "upload-success-subj": "דערפֿאלגרייכער ארויפֿלאָד",
        "upload-success-msg": "אײַער אַרויפֿלאָד פֿון [$2] איז געווען דערפֿאלגרייך. עס איז פֿאַראָן דאָ: [[:{{ns:file}}:$1]]",
        "upload-failure-subj": "אַרויפֿלאָדן פראבלעם",
        "license": "ליצענץ:",
        "license-header": "ליצענץ:",
        "nolicense": "גארנישט",
+       "licenses-edit": "רעדאקטירן ליצענץ אפציעס",
        "license-nopreview": "(פֿאראויסקוק נישט פֿאַראַן)",
-       "upload_source_url": " (א גילטיקע , צוגעגנלעכער URL)",
-       "upload_source_file": "(א טעקע אויף אײַער קאמפיוטער)",
+       "upload_source_url": "(אײַער געקליבענע טעקע פון א גילטיקן, צוגעגנלעכן URL)",
+       "upload_source_file": "(אײַער געקליבענע טעקע פון אײַער קאמפיוטער)",
+       "listfiles-delete": "אויסמעקן",
        "listfiles-summary": "דער דאזיקער באזונדערער בלאט ווייזט אלע ארויפגעלאדענע טעקעס.",
        "listfiles_search_for": "זוכן פֿאַר מעדיע נאָמען:",
        "imgfile": "טעקע",
        "unwatchedpages": "בלעטער וואס זענען נישט אויפגעפאסט",
        "listredirects": "ליסטע פון ווײַטערפֿירונגען",
        "listduplicatedfiles": "ליסטע פון טעקעס מיט דופליקאטן",
+       "listduplicatedfiles-summary": "דאס איז א רשימה פון טעקעס וואו די לעצטיקסטע ווערסיע פון דער טעקע איז א דופליקאט פון דער לעצטיקסטע ווערסיע פון אן אנדער טעקע. נאר לאקאלע טעקעס קומען אין באטראכט.",
        "listduplicatedfiles-entry": "[[:טעקע:$1|$1]] האט [[$3|{{PLURAL:$2|א דופליקאט|$2 דופליקאטן}}]].",
        "unusedtemplates": "נישט באניצטע מוסטערן",
        "unusedtemplatestext": "דער בלאט ווײַזט אלע בלעטער אינעם {{ns:template}} נאמענטייל וואס זענען נישט אײַנגעשלאסן אין אן אנדער בלאט. געדענקט צו באקוקן אנדערע בלעטער פאר לינקען צו די מוסטערן איידער איר מעקט זיי אויס.",
        "randomincategory": "צופעליקער בלאט אין קאטעגאריע",
        "randomincategory-invalidcategory": "\"$1\" איז נישט קיין גילטיקער קאטעגאריע נאמען.",
        "randomincategory-nopages": "נישט פאראן קיין בלעטער אין [[:Category:$1]].",
-       "randomincategory-selectcategory": "באקומען צופעליקן בלאט פון קאטעגאריע: $1, $2.",
-       "randomincategory-selectcategory-submit": "גיין",
+       "randomincategory-category": "קאַטעגאריע:",
+       "randomincategory-legend": "צופעליקער בלאט אין קאטעגאריע",
        "randomredirect": "צופֿעליק ווײַטערפֿירן",
        "randomredirect-nopages": "נישטא קיין ווײַטערפֿירונגען אין דעם נאמענטייל $1.",
        "statistics": "סטאַטיסטיק",
        "wantedpages-badtitle": "אומגילטיקער טיטל אין רעזולטאַט: $1",
        "wantedfiles": "געזוכטע טעקעס",
        "wantedfiletext-cat": "די פֿאלגנדע טעקעס ווערן געניצט אבער זיי עקזיסטירן נישט. טעקעס פון פֿרעמדע רעפאזיטאריעס קענען ווערן אריינגערעכנט טראץ זיי עקזיסטירן יא. אזעלכע גרייזן וועלן ווערן <del>אויסגעשריכן </del>. דערצו, בלעטער וואס ניצן אומעקזיסטירנדע טעקעס ווערן אריינגערעכנט אין [[:$1]].",
+       "wantedfiletext-cat-noforeign": "די פאלגנדע טעקעס ווערן געניצט אבער זענען נישט פאראן. Additionally, pages that embed files that do not exist are listed in [[:$1]].",
+       "wantedfiletext-nocat-noforeign": "די פאלגנדע טעקעס ווערן געניצט אבער זענען נישט פאראן.",
        "wantedtemplates": "געזוכטע מוסטערן",
        "mostlinked": "מערסט פֿארבינדענע בלעטער",
        "mostlinkedcategories": "מערסט פֿארבינדענע קאטעגאריעס",
        "allpages-bad-ns": "{{SITENAME}} האט נישט קיין נאָמענטייל \"$1\".",
        "allpages-hide-redirects": "פֿארהיילן ווייטערפֿירונגען",
        "cachedspecial-viewing-cached-ttl": "איר באקוקט א ווערסיע פון דעם בלאט פונעם זאפאס, וואס קען אבער זיין  פֿארעלטערט ביז $1.",
+       "cachedspecial-viewing-cached-ts": "איר זעט א זאפאס־ווערסיע פון דעם בלאט, וואס איז מעגלעך נישט אקטועל.",
        "cachedspecial-refresh-now": "באקוקן די לעצטע.",
        "categories": "קאַטעגאָריעס",
        "categoriespagetext": "די פֿאלגענדע {{PLURAL:$1| קאַטעגאָריע אַנטהאַלט|קאַטעגאָריעס אַנטהאַלטן}} בלעטער אדער מעדיע.\n[[Special:UnusedCategories|אומבאַניצטע קאַטעגאריעס]] זענען נישט געוויזן דא.\nזעט אויך [[Special:WantedCategories|געזוכטע קאַטעגאריעס]].",
        "mywatchlist": "אויפפַּאסונג ליסטע",
        "watchlistfor2": "פֿאַר $1 $2",
        "nowatchlist": "איר האט נישט קיין שום בלעטער אין אייער אויפפַּאסונג ליסטע.",
-       "watchlistanontext": "ביטע $1 כדי צו זען אדער ענדערן בלעטער אין אייער אַכטגעבן ליסטע.",
+       "watchlistanontext": "ביטע לאגירט ארײַן כדי צו זען אדער ענדערן בלעטער אין אייער אַכטגעבן ליסטע.",
        "watchnologin": "איר זענט נישט אַרײַנלאגירט",
        "addwatch": "צולייגן צו דער אויפֿפאַסונג ליסטע",
        "addedwatchtext": "דער בלאט \"[[:$1]]\" איז צוגעלײגט געוואָרן צו אײַער [[Special:Watchlist|אויפֿפאַסונג ליסטע]].\n\nווײַטערע ענדערונגען צו דעם בלאַט און צו זײַן פארבינדענעם רעדן בלאַט וועלן זײַן אויסגערעכנט דארט.",
        "watchlist-details": "{{PLURAL:$1|$1 בלאט|$1 בלעטער}} אין אייער אויפֿפאסן ליסטע, נישט רעכענען  רעדן בלעטער.",
        "wlheader-enotif": "ע-פאסט מעלדונג ערמעגליכט.",
        "wlheader-showupdated": "בלעטער געענדערט זײַט אײַער לעצטן וויזיט זען געוויזן '''דיק'''.",
-       "wlnote2": "אונטן זענען די ענדערונגען אין די לעצטע  {{PLURAL:$1|שעה|<strong>$1</strong> שעה'ן}}, ביז $2, $3.",
+       "wlnote": "אונטן {{PLURAL:$1|איז די לעצטע ענדערונג|זענען די לעצטע <strong>$1</strong> ענדערונגען}} אין {{PLURAL:$2|דער לעצטער שעה|די לעצטע <strong>$2</strong> שעה'ן}} ביז $3, $4.",
        "wlshowlast": "(ווײַזן די לעצטע $1 שעה'ן | $2 טעג | $3)",
        "watchlist-options": "אויפֿפאַסן ליסטע ברירות",
        "watching": "אויפפאסענדונג…",
        "exbeforeblank": "אינהאַלט בעפֿאַרן אויסליידיגן איז געווען: \"$1\"",
        "delete-confirm": "אויסמעקן $1",
        "delete-legend": "אויסמעקן",
-       "historywarning": "אכטונג – איר גייט אויסמעקן א בלאט וואָס האט א היסטאריע מיט $1 {{PLURAL:$1|ווערסיע|ווערסיעס}}:",
+       "historywarning": "<strong>אכטונג:</strong> איר גייט אויסמעקן א בלאט וואָס האט א היסטאריע מיט $1 {{PLURAL:$1|ווערסיע|ווערסיעס}}:",
        "confirmdeletetext": "איר גייט איצט אויסמעקן א בלאט צוזאַמען מיט זײַן גאנצע היסטאריע.\n\nביטע באשטעטיגט אז דאס איז טאקע אייער כוונה, אז איר פארשטייט פולערהייט די קאנסקווענסן פון דעם אַקט, און אז דאס איז אין איינקלאנג מיט [[{{MediaWiki:Policy-url}}|דער פאליסי]].",
        "actioncomplete": "די אַקציע אָט זיך דורכגעפֿירט",
        "actionfailed": "אקציע דורכגעפאלן",
        "delete-edit-reasonlist": "רעדאַקטירן די אויסמעקן סיבות",
        "delete-toobig": "דער בלאַט האט א גרויסע רעדאקטירונג היסטאריע, מער ווי $1 {{PLURAL:$1|רעוויזיע|רעוויזיעס}}. אויסמעקן אזעלכע בלעטער איז באַגרענעצט געווארן בכדי צו פֿאַרמײַדן א צופֿעליגע פֿאַרשטערונג פֿון  {{SITENAME}}.",
        "delete-warning-toobig": "דער בלאַט האט א גרויסע רעדאקטירונג היסטאריע, מער ווי $1 {{PLURAL:$1|רעוויזיע|רעוויזיעס}}. אויסמעקן אים קען פֿאַרשטערן דאַטנבאַזע אפעראַציעס פֿון {{SITENAME}}; זײַט פֿארזיכטיג איידער איר מעקט אויס.",
+       "deleteprotected": "איר קענט נישט אויסמעקן דעם בלאט ווײַל ער איז געשיצט.",
        "deleting-backlinks-warning": "'''ווארענוג:'''\n[[Special:WhatLinksHere/{{FULLPAGENAME}}|אנדערע בלעטער]]  פארבינדן צום בלאט אדער אריבערשליסן דעם בלאט איר האלט ביי אויסמעקן.",
        "rollback": "צוריקדרייען רעדאַקטירונגען",
        "rollback_short": "צוריקדרייען",
        "sp-contributions-search": "זוכן בײַשטײַערונגען",
        "sp-contributions-username": "באניצער נאמען אדער IP אדרעס:",
        "sp-contributions-toponly": "בלויז ווײַזן רעדאַקטירונגען וואָס זענען די לעצטיקע רעוויזיעס",
-       "sp-contributions-newonly": "בלוז ווײַזן רעדאקטירונגען וואס זענען נײַ־געשאפענע בלעטער",
+       "sp-contributions-newonly": "×\91×\9c×\95×\99×\96 ×\95×\95ײַ×\96×\9f ×¨×¢×\93×\90ק×\98×\99ר×\95× ×\92×¢×\9f ×\95×\95×\90ס ×\96×¢× ×¢×\9f × ×²Ö·Ö¾×\92עש×\90פענע ×\91×\9c×¢×\98ער",
        "sp-contributions-submit": "זוכן",
        "whatlinkshere": "װאָס פֿאַרבינדט אַהער",
        "whatlinkshere-title": "בלעטער וואס פֿארבינדן צו $1",
        "autoblockid": "אויטאמאטיש בלאק #$1",
        "block": "בלאקירן באַניצער",
        "unblock": "אויפֿבלאקירן באניצער",
-       "blockip": "בלאקירן באַניצער",
+       "blockip": "בלאקירן {{GENDER:$1|באַניצער}}",
        "blockip-legend": "בלאקירן באַניצער",
        "blockiptext": "באניצט די פארעם דא אונטן כדי צו בלאקירן שרײַבן רעכטן פֿון איינגעשריבענע באניצער אדער סתם ספעציפישע איי פי אדרעסן.\n\nאזאלכע בלאקירונגען מוזן דורכגעפירט ווערן בלויז צו פֿאַרמײַדן וואַנדאַליזם, און לויט די [[{{MediaWiki:Policy-url}}|פארשריפטן און פאליסיס]].\n\nביטע שרײַבט ארויס קלאָר די ספעציפֿישע סיבה (למשל, ציטירן וועלכע בלעטער מ'האט וואַנדאַליזירט).",
        "ipaddressorusername": "IP אדרעס אדער באַניצער נאמען:",
        "ipb-unblock-addr": "אויפֿבלאקירן $1",
        "ipb-unblock": "אויפֿבלאקירן א באַניצער נאמען אדער IP אדרעס",
        "ipb-blocklist": "זעט עקזיסטירנדע בלאקירונגען",
-       "ipb-blocklist-contribs": "בײַשטײַערונגען פֿון $1",
+       "ipb-blocklist-contribs": "בײַשטײַערונגען פֿון {{GENDER:$1|$1}}",
        "unblockip": "אויפֿבלאקירן באניצער",
        "unblockiptext": "מיט דעם פארמולאר קענט איר צוריקשטעלן שרייבן ערלויבניש צו אן IP אדרעס אדער באניצער נאמען וואס איז געווען בלאקירט.",
        "ipusubmit": "אוועקנעמען דעם בלאק",
        "imageinvalidfilename": "דער ציל טעקע נאָמען איז נישט גילטיק.",
        "fix-double-redirects": "דערהײַנטיקן ווײַטערפֿירונגען צום ארגינעלן טיטל",
        "move-leave-redirect": "איבערלאזן א ווײַטערפֿירונג",
+       "protectedpagemovewarning": "'''ווארענונג:  דער בלאט איז געווארן געשיצט אז בלויז באניצערס מיט סיסאפ פריווילעגיעס קענען אים באוועגן.'''\nדי פארגאנגענע לאגבוך באשרײַבונג ווערט געוויזן דא:",
+       "semiprotectedpagemovewarning": "'''באמערקונג:''' דער דאזיגער בלאַט איז געשיצט אז בלויז איינגעשריבענע באניצערס קענען אים באוועגן.\nדי פֿאַרגאַנגענע לאגבוך באשרײַבונג ווערט געוויזן דאָ:",
        "move-over-sharedrepo": "== טעקע עקזיסטירט ==\n[[:$1]] עקזיסטירט אויף א געטיילטן רעפאזיטאריום. ווען מען באוועגט א טעקע צו דעם טיטל וועט דאס איבערשרייבן די געטיילטע טעקע.",
        "file-exists-sharedrepo": "ס'איז שוין פאראן א טעקע מיטן געקליבענעם נאמען אויף א געמיינזאם רעפאזיטאריום.\nזייט אזוי גוט קלייבט אן אנדער נאמען.",
        "export": "עקספארטירן בלעטער",
        "import": "אימפארטירן בלעטער",
        "importinterwiki": "אריבערוויקי אימפארט",
        "import-interwiki-text": "קלויבט אויס א וויקי און אן ארטיקל קעפל צו אימפארטירן.\nדי דאטעס און די נעמען פון די רעדאקטארן וועט ווערן געהיטן.\nאלע צווישנוויקי אימפארט אקציעס ווערן פארשריבן אינעם   [[Special:Log/import|אימפארט לאג]].",
-       "import-interwiki-source": "מקור וויקי/בלאט",
+       "import-interwiki-sourcewiki": "מקור וויקי:",
+       "import-interwiki-sourcepage": "מקור בלאַט:",
        "import-interwiki-history": "קאפירן אלע היסטאריע ווערסיעס פאר דעם בלאט",
        "import-interwiki-templates": "איינשילסן אלע מוסטערן",
        "import-interwiki-submit": "אימפארט",
        "import-token-mismatch": "אָנווער פון סעסיע דאַטן.\n ביטע פרובירט נאכאמאל.",
        "import-invalid-interwiki": "נישט מעגלעך צו אימפארטירן פון ספעציפֿירטער וויקי.",
        "import-error-edit": "דעם בלאט \"$1\" קען מען נישט אימפארטירן ווייל איר האט נישט די רעכט אים צו רעדאקטירן.",
-       "import-error-create": "×\93×¢×\9d  ×\91×\9c×\90×\98 \"$1\" ×§×¢×\9f ×\9e×¢×\9f × ×\99ש×\98 ×\90×\99×\9eפ×\90ר×\98×\99ר×\9f ווייל איר האט נישט די רעכט צו שאפן אים.",
-       "import-error-interwiki": "×\93×¢×\9d ×\91×\9c×\90×\98 \"$1\"  ×§×¢×\9f ×\9e×¢×\9f × ×\99ש×\98 ×\90×\99×\9eפ×\90ר×\98×\99ר×\9f ×\95×\95×\99×\99ל זיין נאמען איז רעזערווירט פאר דרויסנדיקער פארבינדונג (אינטערוויקי).",
-       "import-error-special": "×\93×¢×\9d ×\91×\9c×\90×\98 \"$1\" ×§×¢×\9f ×\9e×¢×\9f × ×\99ש×\98 ×\90×\99×\9eפ×\90ר×\98×\99ר×\9f ווייל ער געהערט צו א באזונדערן נאמענטייל וואס אנטהאלט נישט קיין בלעטער.",
-       "import-error-invalid": "×\93×¢×\9d ×\91×\9c×\90×\98 \"$1\" ×§×¢×\9f ×\9e×¢×\9f × ×\99ש×\98 ×\90×\99×\9eפ×\90ר×\98×\99ר×\9f ×\95×\95×\99×\99×\9c ×\96×\99×\99×\9f × ×\90×\9e×¢×\9f ×\90×\99×\96 ×\90×\95×\9e×\92×\99×\9c×\98×\99ק.",
+       "import-error-create": "×\93×¢×\9d  ×\91×\9c×\90×\98 \"$1\" ×\94×\90×\98 ×\9e×¢×\9f × ×\99ש×\98 ×\90×\99×\9eפ×\90ר×\98×\99ר×\98 ווייל איר האט נישט די רעכט צו שאפן אים.",
+       "import-error-interwiki": "×\93×¢×\9d ×\91×\9c×\90×\98 \"$1\"  ×\94×\90×\98 ×\9e×¢×\9f × ×\99ש×\98 ×\90×\99×\9eפ×\90ר×\98×\99ר×\98 ×\95×\95ײַל זיין נאמען איז רעזערווירט פאר דרויסנדיקער פארבינדונג (אינטערוויקי).",
+       "import-error-special": "×\93×¢×\9d ×\91×\9c×\90×\98 \"$1\" ×\94×\90×\98 ×\9e×¢×\9f × ×\99ש×\98 ×\90×\99×\9eפ×\90ר×\98×\99ר×\98 ווייל ער געהערט צו א באזונדערן נאמענטייל וואס אנטהאלט נישט קיין בלעטער.",
+       "import-error-invalid": "×\93×¢×\9d ×\91×\9c×\90×\98 \"$1\" ×\94×\90×\98 ×\9e×¢×\9f × ×\99ש×\98 ×\90×\99×\9eפ×\90ר×\98×\99ר×\98 ×\95×\95ײַ×\9c ×\93ער × ×\90×\9e×¢×\9f ×¦×\95 ×\95×\95×\90ס ×¢×¨ ×\95×\95×\90×\9c×\98 ×\95×\95ער×\9f ×\90×\99×\9eפ×\90ר×\98×\99ר×\98 ×\90×\99×\96 ×\90×\95×\9e×\92×\99×\9c×\98×\99ק ×\90×\95×\99×£ ×\93ער ×\95×\95×\99ק×\99.",
        "import-options-wrong": "{{PLURAL:$2|פאלשער אויסקלייב|פאלשע אויסקלייבן}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "געגעבענער שטאמבלאט איז אן אומגילטיקער טיטל.",
        "import-rootpage-nosubpage": "נאמענטייל \"$1\" פונעם שטאמבלאט ערלויבט נישט קיין אונטערבלעטער.",
        "importlogpage": "אימפארט לאגבוך",
        "importlogpagetext": "אַדמיניסטראַטיווער אימפארט פון בלעטער מיט רעדאַגירן היסטאריע פֿון ​​אַנדערע וויקיס.",
        "import-logentry-upload": "האט אימפארטירט [[$1]] דורך טעקע אַרויפֿלאָדן",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|רעוויזיע|רעוויזיעס}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|רעוויזיע|רעוויזיעס}} אימפארטירט",
        "import-logentry-interwiki": "אריבערגעוויקיט $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|רעוויזיע|רעוויזיעס}} פֿון $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|רע×\95×\95×\99×\96×\99×¢|רע×\95×\95×\99×\96×\99עס}} ×\90×\99×\9eפ×\90ר×\98×\99ר×\98 ×¤Ö¿×\95×\9f $2",
        "javascripttest": "JavaScript טעסט",
        "javascripttest-title": "דורכפירנדיק $1 בדיקות",
        "javascripttest-pagetext-noframework": " דער בלאט איז רעזערווירט פאר JavaScript. פרואוון.",
        "api-error-badtoken": "אינערלעכער גרײַז: סימן טויג נישט.",
        "api-error-copyuploaddisabled": "אַרויפֿלאָדן דורך URL איז אומאַקטיווירט אויף דעם סערווירער.",
        "api-error-duplicate": "שוין דאָ אין דער וויקי {{PLURAL:$1|[$2 ָאַן אַנדער טעקע]|[$2 אַנדערע טעקעס]}} מיטן זעלבן תוכן.",
-       "api-error-duplicate-archive": "ס'איז שוין געווען {{PLURAL:$1| [ $2 אַן אַנדער טעקע] | געווען [ $2 עטלעכע אַנדערע טעקעס]}} אויף דעם פּלאַץ מיט דעם זעלביקן תוכן, אָבער {{PLURAL:$1| עס איז | זיי זענען}}  געווארן אויסגעמעקט.",
-       "api-error-duplicate-archive-popup-title": "פֿאַרטאפלטע {{PLURAL:$1| טעקע | טעקעס}} וואָס זענען שוין געווארן אויסגעמעקט",
+       "api-error-duplicate-archive": "ס'איז שוין געווען {{PLURAL:$1| [$2 אַן אַנדער טעקע] | [$1 עטלעכע אַנדערע טעקעס]}} אויף דעם פּלאַץ מיט דעם זעלביקן תוכן, אָבער {{PLURAL:$1| עס איז | זיי זענען}}  געווארן אויסגעמעקט.",
+       "api-error-duplicate-archive-popup-title": "פֿאַרטאפלטע {{PLURAL:$1| טעקע וואָס איז| טעקעס וואָס זענען}}  שוין געווארן אויסגעמעקט",
        "api-error-duplicate-popup-title": "פֿאַרטאפלטע {{PLURAL:$1| טעקע | טעקעס}}",
        "api-error-empty-file": "די טעקע וואָס איר האט אײַנגעגעבן איז ליידיג.",
        "api-error-emptypage": "שאפן נייע ליידיקע בלעטער איז נישט ערלויבט.",
index a67e3d9..842cc1d 100644 (file)
@@ -45,6 +45,7 @@
        "tog-showhiddencats": "Ṣ'àfihàn àwọn ẹ̀ka pípamọ́",
        "tog-norollbackdiff": "Fo ìyàtọ̀ lẹ́yín síṣe ìyísẹ́yìn",
        "tog-useeditwarning": "Kìlọ̀ fún mi tí mo bá únkúrò ní ojúewé àtúnṣe láì tíì mupamọ́",
+       "tog-prefershttps": "Lo ìjáwọlé oníàbò ní gbogbo ìgbà",
        "underline-always": "Nígbà gbogbo",
        "underline-never": "Rárá",
        "underline-default": "Ti àwọ tàbí ẹrọ́ ìtọ́kùn",
        "permalink": "Ìjápọ̀ tíkòníyípadà",
        "print": "Ìtẹ̀síìwé",
        "view": "Ìwòran",
+       "view-foreign": "Ìgbéwò lórí $1",
        "edit": "Àtúnṣe",
+       "edit-local": "Àtúnṣe ìjúwe ìhàhín",
        "create": "Ṣèdá",
+       "create-local": "Ìfikún ìjúwe ìhàhín",
        "editthispage": "S'àtúnṣe ojúewé yi",
        "create-this-page": "Ṣè'dá ojúewé yìí",
        "delete": "Ìparẹ́",
        "talkpagelinktext": "Ọ̀rọ̀",
        "specialpage": "Ojúewé Pàtàkì",
        "personaltools": "Àwọn irinṣẹ́ àdáni",
-       "postcomment": "Abala tuntun",
        "articlepage": "Ìfihàn àkóónú ojúewé",
        "talk": "Ìfọ̀rọ̀wérọ̀",
        "views": "Àwọn ìwò",
        "externaldberror": "Bóyá àsìṣe ìfidájú ibùdó dátà ló ṣẹlẹ̀ tàbí ẹ kò jẹ́ gbígbà ní ààyè láti sọ àpamọ́ òde yín di ọ̀tun.",
        "login": "Ìjáwọlé",
        "nav-login-createaccount": "Ìwọlé / Ìforúkọ sílẹ̀",
-       "loginprompt": "Ẹ gbọ́dọ̀ jọ̀wọ́ cookies láti wọlé sí {{SITENAME}}.",
        "userlogin": "Ìwọlé / ìforúkọ sílẹ̀",
        "userloginnocreate": "Ìjáwọlé",
        "logout": "Ìjáde",
        "searchprofile-advanced-tooltip": "Ṣàwáàrí nínú àwọn orúkọàyè pàtó",
        "search-result-size": "$1 ({{PLURAL:$2|ọ̀rọ̀ 1|àwọn ọ̀rọ̀ $2}})",
        "search-result-category-size": "{{PLURAL:$1|ẹlẹgbẹ́ 1|àwọn ẹlẹgbẹ́ $1}} ({{PLURAL:$2|ẹ̀kà abẹ́ 1|àwọn ẹ̀kà abẹ́ $2}}, {{PLURAL:$3|fáìlì 1|àwọn fáìlì $3}})",
-       "search-result-score": "Ìbáramu: $1%",
        "search-redirect": "(àtúnjúwe $1)",
        "search-section": "(abala $1)",
        "search-suggest": "Ṣé ẹ fẹ́: $1",
        "uploadwarning": "Ìkìlọ̀ ìrùsókè",
        "uploadwarning-text": "Ẹ jọ̀wọ́ ẹ tún ìjúwe fáìlì ìsàlẹ̀ náà ṣe kí ẹ tó gbìyànjú lẹ́ẹ̀kan síi.",
        "savefile": "Ìmúpamọ́ fáìlì",
-       "uploadedimage": "\"[[$1]]\" ti jẹ́rírùsókè",
-       "overwroteimage": "ṣe ìrùsókè àtúnyẹ̀wò tuntun \"[[$1]]\"",
        "uploaddisabled": "Dídálẹ́kun àwọn ìrùsókè.",
        "copyuploaddisabled": "Ìdálẹ́kun ìrùsókè pẹ̀lú URL.",
        "uploaddisabledtext": "Dídálẹ́kun àwọn ìrùsókè fáìlì.",
        "watchlist-details": "{{PLURAL:$1|Ojúewé $1|Àwọn ojúewé $1}} ló wà nínú ìmójútó yín, tí a kò bá ka àwọn ojúewé ọ̀rọ̀.",
        "wlheader-enotif": "Ìfitónilétí e-mail wà ní gbígbàláyè.",
        "wlheader-showupdated": "Àwọn ojúewé tí wọn ti yípadà látìgbà tí ẹ ṣàbẹ̀wò wọn gbẹ̀yìn jẹ́ fífihàn ní ''kedere'''",
+       "wlnote": "Lábẹ́ {{PLURAL:$1|ni àtúnṣe tó gbẹ̀yìn|ni àwọn àtúnṣe '''$1''' tí wọn gbẹ̀yìn}} ní {{PLURAL:$2|wákàtí kan|wákàtí '''$2'''}} sẹ́yìn, títí dí ọjọ́ $3, $4.",
        "wlshowlast": "Ìfihàn wákàtí $1 sẹ́yìn ọjọ́ $2 sẹ́yìn $3",
        "watchlist-options": "Àṣàyàn ìmójútọ́",
        "watching": "Ó ún mójútó...",
        "duplicate-defaultsort": "'''Ìkìlọ̀:''' Bọ́tìnì ìtò àkọ́kọ́ṣe \"$2\" dípò Bọ́tìnì ìtò àkọ́kọ́ṣe \"$1\" tẹ́lẹ̀.",
        "version": "Àtẹ̀jáde",
        "version-extensions": "Àwọn ìfàgùn kíkànsínú",
+       "version-skins": "Skin (Àwọ̀)",
        "version-specialpages": "Àwọn ojúewé pàtàkì",
        "version-variables": "Ayàtọ̀",
        "version-antispam": "Ìdínà spam",
-       "version-skins": "Skin (Àwọ̀)",
        "version-other": "Òmíràn",
        "version-hooks": "Àwọn hook",
        "version-hook-name": "Orúkọ hook",
index 821f78c..4b0d976 100644 (file)
@@ -19,7 +19,8 @@
                        "아라",
                        "Ktchankt",
                        "Kc kennylau",
-                       "Mywood"
+                       "Mywood",
+                       "Impersonator 1"
                ]
        },
        "tog-underline": "連結加底線:",
        "talkpagelinktext": "傾偈",
        "specialpage": "特別頁",
        "personaltools": "個人工具",
-       "postcomment": "新小節",
        "articlepage": "睇目錄",
        "talk": "討論",
        "views": "去睇",
        "externaldberror": "驗證資料庫出錯,或者唔允許你更新你嘅外部帳戶。",
        "login": "登入",
        "nav-login-createaccount": "登入/開新戶口",
-       "loginprompt": "你一定要開咗 cookies 先登入到{{SITENAME}}。",
        "userlogin": "登入/開新戶口",
        "userloginnocreate": "登入",
        "logout": "登出",
        "searchprofile-advanced-tooltip": "響自定空間名度搵",
        "search-result-size": "$1 ($2個字)",
        "search-result-category-size": "$1位成員 ($2個細類,$3個檔案)",
-       "search-result-score": "相關度: $1%",
        "search-redirect": "(跳轉 $1)",
        "search-section": "(小節 $1)",
        "search-suggest": "你係唔係搵: $1",
        "uploadwarning": "上載警告",
        "uploadwarning-text": "請修改下面嘅檔案描述再重試。",
        "savefile": "儲存檔案",
-       "uploadedimage": "上載咗\"[[$1]]\"",
-       "overwroteimage": "已經上載咗\"[[$1]]\"嘅新版本",
        "uploaddisabled": "上載已停用。",
        "copyuploaddisabled": "由URL嘅上載已經停用。",
        "uploaddisabledtext": "檔案上載已經停用。",
        "watchlist-details": "唔計討論頁,有 $1 版響你個監視清單度。",
        "wlheader-enotif": "電子郵件通知已經啟用。",
        "wlheader-showupdated": "'''粗體字'''嘅頁響你上次嚟之後被人改過",
+       "wlnote": "以下係最近'''$2'''個鐘之內嘅最新$1次修改。",
        "wlshowlast": "顯示最近 $1 個鐘 $2 日 $3 嘅修改",
        "watchlist-options": "監視清單選項",
        "watching": "監視緊...",
index 29bb0b0..e99e9f2 100644 (file)
        "talkpagelinktext": "Overleg",
        "specialpage": "Speciaole bladzie",
        "personaltools": "Persoônlijke instelliengen",
-       "postcomment": "Nuuw kopje toevoehen",
        "articlepage": "Bekiek 't artikel",
        "talk": "Overleg",
        "views": "Acties",
        "externaldberror": "Der is een fout opetreeën bie 't anmelden bie de database of je ei hin toestemmieng jen externe gebruker bie te werken.",
        "login": "Anmelden",
        "nav-login-createaccount": "Anmelden / Inschrieven",
-       "loginprompt": "Je mò cookies ineschaokeld ène om je te kunn'n anmelden bie {{SITENAME}}.",
        "userlogin": "Anmelden / Inschrieven",
        "logout": "Ofmelden",
        "userlogout": "Ofmelden",
        "searchprofile-advanced-tooltip": "Zoek'n in angegeev'n naemruumtes",
        "search-result-size": "$1 ({{PLURAL:$2|1 woôrd|$2 woôrn}})",
        "search-result-category-size": "{{PLURAL:$1|1 categorielid|$1 categorieleden}} ({{PLURAL:$2|1 ondercategorie|$2 ondercategorieën}}, {{PLURAL:$3|1 bestand|$3 bestanden}})",
-       "search-result-score": "Rillevantie: $1%",
        "search-redirect": "(deurverwiezieng $1)",
        "search-section": "(subkop $1)",
        "search-suggest": "Bedoeln je: $1",
        "ignorewarnings": "Aolle waerschuwiengen neheern",
        "minlength1": "Bestandsnaem'n mott'n minstes eên letter bevatt'n.",
        "badfilename": "Bestandsnaem is veranderd nae \"$1\".",
-       "uploadedimage": "ei \"[[$1]]\" geüpload",
        "watchthisupload": "Volg deêze bladzie",
        "license": "Licentie:",
        "license-header": "Licentie",
index 966331a..5ef199e 100644 (file)
                        "아라",
                        "Mywood",
                        "Impersonator 1",
-                       "Duolaimi"
+                       "Duolaimi",
+                       "TianyinLee",
+                       "NigelSoft",
+                       "Zhuyifei1999"
                ]
        },
        "tog-underline": "链接下划线:",
        "tog-hideminor": "隐藏最近更改中的小编辑",
        "tog-hidepatrolled": "隐藏最近更改中的已巡查编辑",
        "tog-newpageshidepatrolled": "隐藏新页面列表中的已巡查页面",
-       "tog-extendwatchlist": "扩展监视列表以显示所有更改而不仅是最近更改",
+       "tog-extendwatchlist": "扩展监视列表以显示所有更改,而不仅限于最近更改",
        "tog-usenewrc": "按页面合并最近更改和监视列表中的更改",
        "tog-numberheadings": "自动编号标题",
        "tog-showtoolbar": "显示编辑工具栏",
        "tog-editondblclick": "双击编辑页面",
-       "tog-editsectiononrightclick": "启用右击段落标题编辑段落",
-       "tog-watchcreations": "添加我创建的页面和我上传的文件至我的监视列表",
-       "tog-watchdefault": "添加我编辑的页面和文件至我的监视列表",
-       "tog-watchmoves": "添加我移动的页面和文件至我的监视列表",
-       "tog-watchdeletion": "添加我删除的页面和文件至我的监视列表",
-       "tog-minordefault": "默认标记所有编辑为小编辑",
-       "tog-previewontop": "将预览显示在编辑框上方",
+       "tog-editsectiononrightclick": "启用右击小节标题编辑段落",
+       "tog-watchcreations": "将我创建的页面和我上传的文件添加至我的监视列表",
+       "tog-watchdefault": "将我编辑的页面和文件添加至我的监视列表",
+       "tog-watchmoves": "将我移动的页面和文件添加至我的监视列表",
+       "tog-watchdeletion": "将我删除的页面和文件添加至我的监视列表",
+       "tog-watchrollback": "将我回退过的页面添加至我的监视列表",
+       "tog-minordefault": "将所有编辑默认标记为小编辑",
+       "tog-previewontop": "在编辑框上方显示预览",
        "tog-previewonfirst": "首次编辑时显示预览",
        "tog-enotifwatchlistpages": "当我的监视列表中的页面或文件更改时发送电子邮件通知我",
        "tog-enotifusertalkpages": "当我的用户讨论页面更改时发送电子邮件通知我",
        "tog-diffonly": "不在差异下面显示页面内容",
        "tog-showhiddencats": "显示隐藏分类",
        "tog-norollbackdiff": "执行回退后不显示差异",
-       "tog-useeditwarning": "当我离开有未保存更改的编辑页面时提醒我",
+       "tog-useeditwarning": "当我离开编辑页面时,如果有尚未保存的更改,请提醒我",
        "tog-prefershttps": "登录时始终使用安全连接",
        "underline-always": "始终",
        "underline-never": "从不",
        "october-date": "10月$1日",
        "november-date": "11月$1日",
        "december-date": "12月$1日",
-       "pagecategories": "{{PLURAL:$1|分类}}",
+       "pagecategories": "{{PLURAL:$1|分类|$1个分类}}",
        "category_header": "分类“$1”中的页面",
        "subcategories": "子分类",
        "category-media-header": "分类“$1”中的媒体文件",
        "category-empty": "<em>本分类目前没有包含页面或媒体文件。</em>",
-       "hidden-categories": "{{PLURAL:$1|隐藏分类}}",
+       "hidden-categories": "{{PLURAL:$1|隐藏分类|$1个隐藏分类}}",
        "hidden-category-category": "隐藏分类",
        "category-subcat-count": "{{PLURAL:$2|本分类只有以下子分类。|本分类有以下$1个子分类,共有$2个子分类。}}",
        "category-subcat-count-limited": "本分类有以下{{PLURAL:$1|子分类|$1个子分类}}。",
-       "category-article-count": "{{PLURAL:$2|本分类只包含以下页面。|以下{{PLURAL:$1|页面|$1个页面}}属于本分类,共$2个页面。}}",
-       "category-article-count-limited": "以下{{PLURAL:$1|页面|$1个页面}}属于当前分类。",
-       "category-file-count": "{{PLURAL:$2|本分类只包含以下文件。|以下{{PLURAL:$1|文件|$1个文件}}属于本分类,共$2个文件。}}",
-       "category-file-count-limited": "以下{{PLURAL:$1|文件|$1个文件}}属于当前分类。",
+       "category-article-count": "{{PLURAL:$2|本分类只包含以下页面。|本分类中包含以下$1个页面,共$2个页面。}}",
+       "category-article-count-limited": "当前分类包含以下$1个页面。",
+       "category-file-count": "{{PLURAL:$2|本分类只包含以下一个文件。|本分类包含以下$1个文件,共$2个文件。}}",
+       "category-file-count-limited": "当前分类包含以下$1个文件。",
        "listingcontinuesabbrev": "续",
-       "index-category": "å\8f¯索引页面",
+       "index-category": "å·²索引页面",
        "noindex-category": "不可索引页面",
-       "broken-file-category": "有受损文件链接的页面",
+       "broken-file-category": "有受损文件链接的页面",
        "categoryviewer-pagedlinks": "($1)($2)",
        "about": "关于",
        "article": "内容页面",
        "faq": "常见问题",
        "faqpage": "Project:常见问题",
        "actions": "操作",
-       "namespaces": "å\90\8då­\97空间",
+       "namespaces": "å\91½å\90\8d空间",
        "variants": "变种",
        "navigation-heading": "导航菜单",
-       "errorpagetitle": "出错",
+       "errorpagetitle": "错误",
        "returnto": "返回$1。",
        "tagline": "来自{{SITENAME}}",
        "help": "帮助",
        "searcharticle": "前往",
        "history": "页面历史",
        "history_short": "历史",
-       "updatedmarker": "更新于我上次访问后",
+       "updatedmarker": "已于我上次访问之后更新",
        "printableversion": "打印版本",
        "permalink": "固定链接",
        "print": "打印",
        "deletethispage": "删除本页",
        "undeletethispage": "还原本页",
        "undelete_short": "还原$1次编辑",
-       "viewdeleted_short": "查看$1个已删除的编辑",
+       "viewdeleted_short": "查看$1个已删除的编辑",
        "protect": "保护",
        "protect_change": "更改",
        "protectthispage": "保护本页",
        "talkpagelinktext": "讨论",
        "specialpage": "特殊页面",
        "personaltools": "个人工具",
-       "postcomment": "新段落",
        "articlepage": "查看内容页面",
        "talk": "讨论",
-       "views": "查看",
+       "views": "视图",
        "toolbox": "工具",
        "userpage": "查看用户页面",
        "projectpage": "查看项目页面",
        "imagepage": "查看文件页面",
-       "mediawikipage": "查看息页面",
+       "mediawikipage": "查看息页面",
        "templatepage": "查看模板页面",
        "viewhelppage": "查看帮助页面",
        "categorypage": "查看分类页面",
        "otherlanguages": "其他语言",
        "redirectedfrom": "(重定向自$1)",
        "redirectpagesub": "重定向页面",
+       "redirectto": "重定向至:",
        "lastmodifiedat": "本页面最后修改于$1 $2。",
        "viewcount": "本页面已经被访问过$1次。",
        "protectedpage": "受保护页面",
        "mainpage": "首页",
        "mainpage-description": "首页",
        "policy-url": "Project:方针",
-       "portal": "社å\8cºä¸\93页",
+       "portal": "社å\8cºä¸»页",
        "portal-url": "Project:社区专页",
-       "privacy": "é\9a\90ç§\81æ\9d\83æ\94¿ç­\96",
+       "privacy": "隐私政策",
        "privacypage": "Project:隐私权政策",
        "badaccess": "权限错误",
        "badaccess-group0": "你被禁止执行你刚才请求的操作。",
        "hidetoc": "隐藏",
        "collapsible-collapse": "折叠",
        "collapsible-expand": "展开",
+       "confirmable-confirm": "{{GENDER:$1|你}}确定么?",
+       "confirmable-yes": "是",
+       "confirmable-no": "否",
        "thisisdeleted": "查看或还原$1?",
        "viewdeleted": "查看$1?",
        "restorelink": "$1个已被删除的编辑",
        "invalidtitle-knownnamespace": "使用名字空间“$2”和文本“$3”的无效标题",
        "invalidtitle-unknownnamespace": "使用未知名字空间编号$1和文本“$2”的无效标题",
        "exception-nologin": "未登录",
-       "exception-nologin-text": "该页é\9d¢æ\88\96æ\93\8dä½\9cé\9c\80è¦\81ä½ [[Special:Userlogin|ç\99»å½\95]]è\87³æ\9c¬Wiki。",
+       "exception-nologin-text": "请ç\99»å½\95以访é\97®æ­¤é¡µé\9d¢æ\88\96è¿\9bè¡\8cæ\93\8dä½\9c。",
        "exception-nologin-text-manual": "查看该页面或进行此操作需要您$1。",
        "virus-badscanner": "错误的配置:未知的病毒扫描程序:''$1''",
        "virus-scanfailed": "扫描失败(代码 $1)",
        "externaldberror": "验证数据库出错或您被禁止更新您的外部账号。",
        "login": "登录",
        "nav-login-createaccount": "登录/创建账户",
-       "loginprompt": "你必须启用Cookie才能登录{{SITENAME}}。",
        "userlogin": "登录/创建账户",
        "userloginnocreate": "登录",
        "logout": "退出",
        "userlogin-resetlink": "忘记你的登录信息?",
        "userlogin-resetpassword-link": "忘记密码?",
        "userlogin-helplink2": "登录帮助",
-       "userlogin-loggedin": "您已经以{{GENDER:$1|$1}}的身份登录。使用下面的表格以其他用户的身份登录。",
-       "userlogin-createanother": "创建另一个账户",
        "createacct-emailrequired": "电子邮件地址",
        "createacct-emailoptional": "电子邮件地址(可选)",
        "createacct-email-ph": "请输入你的电子邮件地址",
        "createaccount-text": "有人在{{SITENAME}}中利用您的邮箱创建了一个名为 \"$2\" 的新帐户($4),密码是 \"$3\" 。您应该立即登录并更改密码。\n\n如果该账户创建错误的话,您可以忽略此信息。",
        "login-throttled": "你最近尝试登录的次数过多。请等待$1后再试。",
        "login-abort-generic": "登录失败 - 已终止",
+       "login-migrated-generic": "您的账户已被迁移,并且您的用户名在此wiki不再存在。",
        "loginlanguagelabel": "语言:$1",
        "suspicious-userlogout": "注销请求被拒绝,因为它似乎是由有设计缺陷的浏览器或缓存代理发出的。",
        "createacct-another-realname-tip": "真实姓名是选填项目。\n如果你选择提供它,它将会用于贡献署名。",
        "preview": "预览",
        "showpreview": "显示预览",
        "showdiff": "显示更改",
-       "anoneditwarning": "<strong>警告:</strong>您没有登录。您的IP地址将被记录在该页面的编辑历史中。",
-       "anonpreviewwarning": "''你没有登录。保存会记录你的IP地址于该页面的编辑历史中。''",
+       "blankarticle": "<strong>警告</strong>:您创建的页面是空白的。如果您再次点击“{{int:savearticle}}”,您将真的创建没有任何内容的页面。",
+       "anoneditwarning": "<strong>警告:</strong>您没有登录。您做出任何编辑后您的IP地址会公开可见。如果您<strong>[$1 登陆]</strong>或<strong>[$2 注册]</strong>一个账户,您的编辑将归属于您的用户名,以及有其他好处。",
+       "anonpreviewwarning": "<em>你没有登录。保存会记录你的IP地址于该页面的编辑历史中。</em>",
        "missingsummary": "'''提示:'''你没有提供编辑摘要。如果你再次点击“{{int:savearticle}}”,你的编辑将不带编辑摘要保存。",
        "missingcommenttext": "请在下面输入评论。",
        "missingcommentheader": "'''提示:''' 您还没有为此评论提供一个标题。如果您再次点击“{{int:savearticle}}”,您的编辑将不带标题保存。",
        "summary-preview": "摘要预览:",
        "subject-preview": "标题预览:",
        "blockedtitle": "用户被封禁",
-       "blockedtext": "'''你的用户名或IP地址已被封禁。'''\n\n执行封禁的管理员是$1。封禁原因是''$2''。\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n你可以联系$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]讨论该封禁。只有当你在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“电邮联系”功能时,才可以使用它。你当前的IP地址是$3,该封禁ID是#$5。请在你的询问中包含上面的所有信息。",
+       "blockedtext": "<strong>你的用户名或IP地址已被封禁。</strong>\n\n执行封禁的管理员是$1。封禁原因是<em>$2</em>。\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n你可以联系$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]讨论该封禁。只有当你在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“电邮联系”功能时,才可以使用它。你当前的IP地址是$3,该封禁ID是#$5。请在你的询问中包含上面的所有信息。",
        "autoblockedtext": "您的IP地址因曾被一位被$1封禁的用户使用而被自动封禁。封禁原因:\n\n:<em>$2</em>\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您可以联系$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]申诉该封禁。\n\n请注意,只有当您已在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“电邮联系”功能时,才能发送电子邮件联系管理员。\n\n您当前的IP地址为$3,该封禁ID为#$5。\n请您在申诉内容中说明以上所有信息。",
        "blockednoreason": "未给出原因",
        "whitelistedittext": "您必须先$1才可编辑页面。",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
        "expensive-parserfunction-warning": "<strong>警告:</strong>这个页面有太多高昂的语法功能调用。\n\n它应该少过$2次呼叫,现在有$1次呼叫。",
-       "expensive-parserfunction-category": "有过多高开销解析器函数调用的页面",
+       "expensive-parserfunction-category": "页面中有太多耗费的语法功能呼叫",
        "post-expand-template-inclusion-warning": "'''警告:'''包含模板大小过大。\n一些模板将不会包含。",
-       "post-expand-template-inclusion-category": "模板包含大小超限的页面",
-       "post-expand-template-argument-warning": "'''警告:'''本页面包含至少一个模板参数有过大扩展大小。这些参数会被略过。",
+       "post-expand-template-inclusion-category": "模板包含上限已经超过的页面",
+       "post-expand-template-argument-warning": "<strong>警告:</strong>本页面包含至少一个模板参数有过大扩展大小。这些参数会被略过。",
        "post-expand-template-argument-category": "含有略过模板参数的页面",
        "parser-template-loop-warning": "检查到模板循环:[[$1]]",
        "parser-template-recursion-depth-warning": "模板递归深度越限($1)",
        "language-converter-depth-warning": "字词转换器深度越限($1)",
-       "node-count-exceeded-category": "节点数超限的页面",
-       "node-count-exceeded-category-desc": "è\8a\82ç\82¹æ\95°æº¢å\87ºé¡µé\9d¢ç\9a\84å\88\86ç±»。",
+       "node-count-exceeded-category": "页面的节点数超出限制",
+       "node-count-exceeded-category-desc": "è\85å\87ºæ\9c\80é«\98è\8a\82ç\82¹æ\95°ç\9a\84页é\9d¢。",
        "node-count-exceeded-warning": "页面超出了节点数",
-       "expansion-depth-exceeded-category": "展开深度超限的页面",
-       "expansion-depth-exceeded-category-desc": "这是超出拓展深度页面的分类。",
+       "expansion-depth-exceeded-category": "扩展深度超出限制的页面",
+       "expansion-depth-exceeded-category-desc": "页面超出最大扩展深度。",
        "expansion-depth-exceeded-warning": "页面超过了扩展深度",
        "parser-unstrip-loop-warning": "检测到回圈",
        "parser-unstrip-recursion-limit": "递归超过限制 ($1)",
        "rev-deleted-event": "(日志操作被删除)",
        "rev-deleted-user-contribs": "[用户名或IP地址被删除 - 编辑在贡献中隐藏]",
        "rev-deleted-text-permission": "本页面版本已被'''删除'''。详情请见[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 删除日志]。",
+       "rev-suppressed-text-permission": "此页面修订已经被<strong>监督隐藏</strong>。详细信息可在[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 监督日志]中找到。",
        "rev-deleted-text-unhide": "本页面版本已被'''删除'''。详情请见[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 删除日志]。如果你想继续操作,你仍然可以[$1 查看本版本]。",
        "rev-suppressed-text-unhide": "该页面版本已经被'''监督隐藏'''。在[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 监督日志]中可以找到详细的信息。如果您想继续的话,您可以仍然[$1 去查看这次版本]。",
        "rev-deleted-text-view": "本页面版本已被'''删除'''。你可以查看它,详情请见[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 删除日志]。",
        "revdelete-text-text": "已删除版本仍将在页面历史中显示,但涉及部分的内容将对公众不可见。",
        "revdelete-text-file": "已删除文件版本仍将在文件历史中显示,但涉及部分的内容将对公众不可见。",
        "logdelete-text": "已删除日志事件仍将在日志中显示,但涉及部分的内容将对公众不可见。",
-       "revdelete-text-others": "å\9c¨{{SITENAME}}ç\9a\84å\85¶ä»\96管ç\90\86å\91\98ä»\8då°\86å\8f¯ä»¥è®¿é\97®é\9a\90è\97\8få\86\85容ï¼\8c并å\9c¨ä¸\80å®\9aæ\9d¡ä»¶ä¸\8bè\83½å¤\9fé\80\9aè¿\87ç\9b¸å\90\8cç\95\8cé\9d¢å\8f\96æ¶\88å\88 é\99¤,除非附加条件被设定。",
+       "revdelete-text-others": "å\85¶ä»\96管ç\90\86å\91\98ä»\8då°\86å\8f¯ä»¥è®¿é\97®é\9a\90è\97\8få\86\85容并å\88 é\99¤å®\83,除非附加条件被设定。",
        "revdelete-confirm": "请确认该操作,明白其后果,并确保该操作符合[[{{MediaWiki:Policy-url}}|方针]]。",
        "revdelete-suppress-text": "阻止应'''仅'''用于以下情况:\n* 潜在的诽谤信息\n* 不合适的个人信息\n*: ''家庭地址、电话号码和社保号码等。''",
        "revdelete-legend": "设置可见性之限制",
        "searchprofile-advanced-tooltip": "在自定义名字空间中搜索",
        "search-result-size": "$1($2个字)",
        "search-result-category-size": "$1个成员($2个子分类,$3个文件)",
-       "search-result-score": "相关度:$1%",
        "search-redirect": "(重定向自“$1”)",
        "search-section": "(“$1”段落)",
        "search-file-match": "(匹配文件内容)",
        "searchall": "所有",
        "showingresults": "下面显示从第'''$2'''条结果开始的'''$1'''条结果。",
        "showingresultsinrange": "下面显示区间#<strong>$2</strong>至#<strong>$3</strong>的<strong>$1</strong>条结果。",
-       "showingresultsheader": "关于<strong>$4</strong>的{{PLURAL:$5|第<strong>$1</strong>条结果,共<strong>$3</strong>条结果|第<strong>$1 - $2</strong>条结果,共<strong>$3</strong>条结果}}",
+       "search-showingresults": "{{PLURAL:$4|<strong>$3</strong>条结果中的<strong>$1</strong>条|<strong>$3</strong>条结果中的<strong>$1~$2</strong>条}}",
        "search-nonefound": "找不到和查询相匹配的结果。",
        "powersearch-legend": "高级搜索",
        "powersearch-ns": "搜索名字空间:",
        "preferences": "设置",
        "mypreferences": "设置",
        "prefs-edits": "编辑数:",
-       "prefsnologintext2": "è¿\9bè¡\8cç\94¨æ\88·è®¾ç½®é\9c\80è¦\81æ\82¨$1。",
+       "prefsnologintext2": "请ç\99»å½\95以æ\9b´æ\94¹æ\82¨ç\9a\84ç\94¨æ\88·è®¾ç½®。",
        "prefs-skin": "皮肤",
        "skin-preview": "预览",
        "datedefault": "默认格式",
        "group-bot": "机器人",
        "group-sysop": "管理员",
        "group-bureaucrat": "行政员",
-       "group-suppress": "监督",
+       "group-suppress": "监督",
        "group-all": "(所有)",
        "group-user-member": "{{GENDER:$1|用户}}",
        "group-autoconfirmed-member": "自动确认用户",
        "group-bot-member": "机器人",
        "group-sysop-member": "{{GENDER:$1|管理员}}",
        "group-bureaucrat-member": "行政员",
-       "group-suppress-member": "监督员",
+       "group-suppress-member": "{{GENDER:$1|监督员}}",
        "grouppage-user": "{{ns:project}}:用户",
        "grouppage-autoconfirmed": "{{ns:project}}:自动确认用户",
        "grouppage-bot": "{{ns:project}}:机器人",
        "grouppage-sysop": "{{ns:project}}:管理员",
        "grouppage-bureaucrat": "{{ns:project}}:行政员",
-       "grouppage-suppress": "{{ns:project}}:监督",
+       "grouppage-suppress": "{{ns:project}}:监督",
        "right-read": "阅读页面",
        "right-edit": "编辑页面",
        "right-createpage": "创建非讨论页面",
        "right-deletedtext": "查看已被删除的文本及已删除版本间的差异",
        "right-browsearchive": "搜索已被删除的页面",
        "right-undelete": "还原页面",
-       "right-suppressrevision": "复核并还原对管理员隐藏的版本",
+       "right-suppressrevision": "查看、隐藏与取消隐藏任何用户对页面做出的特定版本",
+       "right-viewsuppressed": "查看被隐藏的任何用户的修订",
        "right-suppressionlog": "查看非公开日志",
        "right-block": "阻止其他用户编辑",
        "right-blockemail": "阻止用户发送电子邮件",
        "recentchanges-legend-heading": "'''说明:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}}(见[[Special:NewPages|新页面列表]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "下面是<strong>$2</strong>之后的更改(最多显示<strong>$1</strong>个)。",
+       "rcnotefrom": "下面{{PLURAL:$5|是}}<strong>$3 $4</strong>之后的更改(最多显示<strong>$1</strong>个)。",
        "rclistfrom": "显示$3 $2之后的新更改",
        "rcshowhideminor": "$1小编辑",
        "rcshowhideminor-show": "显示",
        "uploadwarning": "上传警告",
        "uploadwarning-text": "请修改下面的文件说明并重试。",
        "savefile": "保存文件",
-       "uploadedimage": "上传“[[$1]]”",
-       "overwroteimage": "上传“[[$1]]”的新版本",
        "uploaddisabled": "上传己停用。",
        "copyuploaddisabled": "URL上传已停用。",
        "uploaddisabledtext": "文件上传已停用。",
        "watchthisupload": "监视这个文件",
        "filewasdeleted": "之前已经有一个同名文件被上传后又被删除了。在上传此文件之前您需要检查$1。",
        "filename-bad-prefix": "您上传的文件名称是以<strong>“$1”</strong>作为开头,通常这种没有含意的文件名称是由数码相机中自动编排。请在您的文件中重新选择一个更加有意义的文件名称。",
+       "filename-prefix-blacklist": " #<!-- 请将本行保留为原样 --> <pre>\n# 语法如下:\n#  * 任何以“#”开头到结尾的行为注释\n#  * 任何非空行是根据相机自动分配特定文件名的前缀\nCIMG # 卡西欧\nDSC_ # 尼康\nDSCF # 富士\nDSCN # 尼康\nDUW # 部分手机\nIMG # 一般\nJD # 业纳\nMGP # 宾得\nPICT # 其他\n #</pre> <!-- 请将本行保留为原样 -->",
        "upload-success-subj": "上传成功",
        "upload-success-msg": "您在[$2]的上传已经成功,可以在这里找到:[[:{{ns:file}}:$1]]",
        "upload-failure-subj": "上传问题",
        "license": "授权协议:",
        "license-header": "授权协议",
        "nolicense": "未选定",
+       "licenses-edit": "编辑许可选项",
        "license-nopreview": "(无预览可用)",
-       "upload_source_url": "(有效、可以公开访问的URL)",
-       "upload_source_file": "(您计算机上的一个文件)",
+       "upload_source_url": "(您选择的来自有效、可以公开访问的URL的文件)",
+       "upload_source_file": "(来自您计算机上您选择的文件)",
+       "listfiles-delete": "删除",
        "listfiles-summary": "本特殊页面展示所有上传的文件。",
        "listfiles_search_for": "按媒体名称搜索:",
        "imgfile": "文件",
        "shared-repo-from": "来自$1",
        "shared-repo": "一个共享文件库",
        "shared-repo-name-wikimediacommons": "维基共享资源",
+       "filepage.css": "/* 放置于此的CSS会包含在文件描述页上,并包含在其他客户端wiki上 */",
        "upload-disallowed-here": "您不可以覆盖此文件。",
        "filerevert": "恢复$1",
        "filerevert-legend": "恢复文件",
        "randomincategory": "分类中随机页面",
        "randomincategory-invalidcategory": "“$1”不是一个有效的分类名称。",
        "randomincategory-nopages": "[[:Category:$1]]中没有页面。",
-       "randomincategory-selectcategory": "获取随机页面从分类:$1 $2。",
-       "randomincategory-selectcategory-submit": "提交",
+       "randomincategory-category": "分类:",
+       "randomincategory-legend": "分内中随机页面",
        "randomredirect": "随机重定向",
        "randomredirect-nopages": "“$1”名字空间中没有重定向。",
        "statistics": "统计",
        "wantedpages-badtitle": "在结果组上的无效标题:$1",
        "wantedfiles": "需要的文件",
        "wantedfiletext-cat": "以下文件被使用,但并不存在。来自外部库的文件即使存在也可能被列出。任何这类误报会用<del>删除线</del>标记。另外,插入不存在的文件的页面列于[[:$1]]。",
+       "wantedfiletext-cat-noforeign": "以下文件被使用但尚不存在。此外嵌入不存在文件的页面在[[:$1]]列出。",
        "wantedfiletext-nocat": "以下文件被使用,但并不存在。来自外部库的文件即使存在也可能被列出。任何这类误报会用<del>删除线</del>标记。",
+       "wantedfiletext-nocat-noforeign": "以下文件被使用但尚不存在。",
        "wantedtemplates": "需要的模板",
        "mostlinked": "最多链接页面",
        "mostlinkedcategories": "最多链接分类",
        "index-category-desc": "页面中有<code><nowiki>__INDEX__</nowiki></code>魔术字(并且在标记允许的名字空间)且因此被机器人索引但本不应索引的。",
        "post-expand-template-inclusion-category-desc": "在展开了所有模板后,页面大小大于<code>$wgMaxArticleSize</code>,所以一些模板未展开。",
        "post-expand-template-argument-category-desc": "展开了模板参数(三对花括号内,例如<code>{{{Foo}}}</code>)之后,页面大于<code>$wgMaxArticleSize</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>的分类,该魔术字阻止分类默认在页面上的分类链接框中显示。",
+       "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": "无电子邮件地址",
        "mywatchlist": "监视列表",
        "watchlistfor2": "$1的监视列表$2",
        "nowatchlist": "你的监视列表为空。",
-       "watchlistanontext": "请$1以查看或编辑您的监视列表。",
+       "watchlistanontext": "请登录以查看或编辑您的监视列表。",
        "watchnologin": "未登录",
        "addwatch": "添加至监视列表",
        "addedwatchtext": "已将页面“[[:$1]]”加入您的[[Special:Watchlist|监视列表]]。此后本页面及其讨论页的若有更改将在监视列表中显示。",
        "watchlist-details": "不计讨论页,您的监视列表中有$1个页面。",
        "wlheader-enotif": "已启用电子邮件通知。",
        "wlheader-showupdated": "您上次访问后发生更改的页面'''加粗'''显示",
-       "wlnote2": "下面是最近{{PLURAL:$1|<strong>$1</strong>小时}}的更改,截至$2 $3。",
+       "wlnote": "下面是{{PLURAL:$2|过去<strong>$2</strong>小时}}的{{PLURAL:$1|最后<strong>$1</strong>个更改}},截至$3 $4。",
        "wlshowlast": "显示过去$1小时$2天$3",
        "watchlist-options": "监视列表选项",
        "watching": "正在监视...",
        "exbeforeblank": "被清空前的内容为:“$1”",
        "delete-confirm": "删除“$1”",
        "delete-legend": "删除",
-       "historywarning": "警告:您将要删除的页面有约$1个{{PLURAL:$1|版本}}的历史:",
+       "historywarning": "<strong>警告</strong>:您将要删除的页面有约$1次修订的历史:",
        "confirmdeletetext": "您即将删除一个页面或图像以及其历史。\n请确定您要进行此项操作,并且了解其后果,同时您的行为符合[[{{MediaWiki:Policy-url}}]]。",
        "actioncomplete": "操作完成",
        "actionfailed": "操作失败",
        "delete-edit-reasonlist": "编辑删除原因",
        "delete-toobig": "这个页面有一个十分大量的编辑历史,超过$1个版本。删除此类页面的动作已经被限制,以防止在{{SITENAME}}上的意外扰乱。",
        "delete-warning-toobig": "这个页面有一个十分大量的编辑历史,超过$1个版本。删除它可能会扰乱{{SITENAME}}的数据库操作;在继续此动作前请小心。",
+       "deleteprotected": "您不能删除此页面因为它被保护。",
        "deleting-backlinks-warning": "'''警告:'''有[[Special:WhatLinksHere/{{FULLPAGENAME}}|其他页面]]链接至或包含您要删除的页面。",
        "rollback": "回退编辑",
        "rollback_short": "回退",
        "restriction-level-all": "任何级别",
        "undelete": "查看被删除页面",
        "undeletepage": "查看和还原被删除的页面",
-       "undeletepagetitle": "'''以下包含[[:$1]]的已删除之版本'''。",
+       "undeletepagetitle": "'''以下包含[[:$1|$1]]的已删除之版本'''。",
        "viewdeletedpage": "查看被删页面",
        "undeletepagetext": "以下{{PLURAL:$1|页面|$1个页面}}已被删除,但依然在归档中并可以被恢复。归档可能会被定时清理。",
        "undelete-fieldset-title": "还原版本",
        "autoblockid": "自动封禁#$1",
        "block": "封禁用户",
        "unblock": "解封用户",
-       "blockip": "封禁用户",
+       "blockip": "封禁{{GENDER:$1|用户}}",
        "blockip-legend": "封禁用户",
        "blockiptext": "使用下方的表单来禁止来自特定IP地址或用户名的写访问。\n只有在为了防止破坏,并符合[[{{MediaWiki:Policy-url}}|方针]]的情况下才可采取此行动。\n请在下面输入一个具体的理由(例如引述一个被破坏的页面)。",
        "ipaddressorusername": "IP地址或用户名:",
        "ipb-unblock-addr": "解封$1",
        "ipb-unblock": "解封用户名或IP地址",
        "ipb-blocklist": "查看现有封禁",
-       "ipb-blocklist-contribs": "$1的贡献",
+       "ipb-blocklist-contribs": "{{GENDER:$1|$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": "查找被封禁用户",
        "import": "导入页面",
        "importinterwiki": "跨wiki导入",
        "import-interwiki-text": "选择要导入的wiki和页面标题,导入版本的日期和编辑者名称会被保存。所有的跨wiki导入操作都将记录到[[Special:Log/import|导入日志]]。",
-       "import-interwiki-source": "来源wiki/页面:",
+       "import-interwiki-sourcewiki": "来源wiki:",
+       "import-interwiki-sourcepage": "来源页面:",
        "import-interwiki-history": "复制此页的所有历史版本",
        "import-interwiki-templates": "包含所有模板",
        "import-interwiki-submit": "导入",
        "import-upload": "上传XML数据",
        "import-token-mismatch": "会话数据遗失。请重试。",
        "import-invalid-interwiki": "不能从指定的wiki导入。",
-       "import-error-edit": "\"$1\"页面不导入,因为您不准对其进行编辑。",
-       "import-error-create": "\"$1\"页面不导入,因为您不准创建它。",
-       "import-error-interwiki": "页面“$1”未能导入,因为它的名称需要使用外部跨wiki链接。",
-       "import-error-special": "页面“$1”未导入,因为它需要使用一个不能创建页面的特殊名字空间。",
-       "import-error-invalid": "页面“$1”未能导入,因为它的名字无效。",
+       "import-error-edit": "页面“$1”未导入,因为您不被允许编辑它。",
+       "import-error-create": "页面“$1”未导入,因为您不被允许创建它。",
+       "import-error-interwiki": "页面“$1”未导入,因为它的名字被外部链接(跨wiki链接)保留。",
+       "import-error-special": "页面“$1”未导入,因为它属于不允许页面编辑的特殊名字空间。",
+       "import-error-invalid": "页面“$1”未导入,因为在此wiki导入的名字无效。",
        "import-error-unserialize": "页面“$1”的版本$2无法反序列化。此版本使用内容模型$3序列化为$4。",
        "import-error-bad-location": "在此wiki使用了内容模式$3的版本$2不能被保存至“$1”,这是因为此模式在此页面不被支持。",
        "import-options-wrong": "{{PLURAL:$2|选项}}出错:<nowiki>$1</nowiki>",
        "importlogpage": "导入日志",
        "importlogpagetext": "管理性导入在其他wiki上有编辑历史的页面。",
        "import-logentry-upload": "通过文件上传导入[[$1]]",
-       "import-logentry-upload-detail": "$1个版本",
-       "import-logentry-interwiki": "跨wiki$1",
-       "import-logentry-interwiki-detail": "来自$2的$1个{{PLURAL:$1|版本}}",
+       "import-logentry-upload-detail": "已导入$1个{{PLURAL:$1|版本}}",
+       "import-logentry-interwiki": "跨wiki页面$1",
+       "import-logentry-interwiki-detail": "已从$2导入$1个{{PLURAL:$1|版本}}",
        "javascripttest": "JavaScript测试",
        "javascripttest-title": "运行$1测试",
        "javascripttest-pagetext-noframework": "本页面被保留进行JavaScript测试。",
        "print.css": "/* 放置于这里的CSS将影响打印输出 */",
        "noscript.css": "/* 放置于这里的CSS将影响停用JavaScript的用户 */",
        "group-autoconfirmed.css": "/* 放置于这里的CSS将只影响自动确认用户 */",
+       "group-user.css": "/* 放置于此的CSS将只会影响注册用户 */",
        "group-bot.css": "/* 放置于这里的CSS将只影响机器人 */",
        "group-sysop.css": "/* 放置于这里的CSS将只影响管理员 */",
-       "group-bureaucrat.css": "/* 放置于这里的CSS将只影响行政员 */",
+       "group-bureaucrat.css": "/* 放置于这里的CSS将只影响行政员 */",
        "common.js": "/* 这里的任何JavaScript将为所有用户在每次页面载入时加载。 */",
        "group-autoconfirmed.js": "/* 这里的任何JavaScript将只为自动确认用户加载 */",
+       "group-user.js": "/* 放置于此的JavaScript将只为注册用户加载 */",
        "group-bot.js": "/* 这里的任何JavaScript将只为机器人加载 */",
        "group-sysop.js": "/* 这里的任何JavaScript将只为管理员加载 */",
        "group-bureaucrat.js": "/* 这里的任何JavaScript将只为行政员加载 */",
        "autosumm-replace": "以“$1”替换内容",
        "autoredircomment": "重定向页面至[[$1]]",
        "autosumm-new": "创建页面,内容为“$1”",
+       "autosumm-newblank": "创建空白页面",
        "size-bytes": "$1字节",
        "lag-warn-normal": "过去$1秒内的更改未必会在这个列表中显示。",
        "lag-warn-high": "由于数据库的过度延迟,过去$1秒的更改未必会在这个列表中显示。",
        "signature": "[[{{ns:user}}:$1|$2]]([[{{ns:user_talk}}:$1|讨论]])",
        "unknown_extension_tag": "未知扩展标签“$1”",
        "duplicate-defaultsort": "'''警告:'''默认排序关键词“$2”覆盖了之前的默认排序关键词“$1”。",
+       "duplicate-displaytitle": "<strong>警告:</strong>显示的标题“$2”重写了此前显示的标题“$1”。",
        "version": "版本",
        "version-extensions": "安装的扩展程序",
        "version-skins": "已安装皮肤",
        "logentry-rights-rights": "$1{{GENDER:$2|更改}}$3的用户组自$4至$5",
        "logentry-rights-rights-legacy": "$1更改$3的用户组",
        "logentry-rights-autopromote": "$1被自动地{{GENDER:$2|提升}}自$4至$5",
+       "logentry-upload-upload": "$1{{GENDER:$2|上传了}}$3",
+       "logentry-upload-overwrite": "$1{{GENDER:$2|上传了}}$3的新版本",
+       "logentry-upload-revert": "$1{{GENDER:$2|上传了}}$3",
        "rightsnone": "(无)",
        "feedback-bugornote": "如果你准备好详细描述一个技术问题,请[$1 报告bug]。或者你可以使用下面的简单表格。你的评论将被添加至页面“[$3 $2]”,附有你的用户名。",
        "feedback-subject": "主题:",
        "expand_templates_intro": "此特殊页面可以递归地展开所给文本中的模板。\n它同时还可展开诸如<nowiki>{{</nowiki>#language:...}}的解析器函数和诸如<nowiki>{{</nowiki>CURRENTDAY}}的变量。\n实际上,几乎所有在双重花括号中的内容都会被展开。",
        "expand_templates_title": "上下文标题,用于{{FULLPAGENAME}}等:",
        "expand_templates_input": "输入文本:",
-       "expand_templates_output": "结果",
+       "expand_templates_output": "结果",
        "expand_templates_xml_output": "XML输出",
        "expand_templates_html_output": "原始HTML输出",
        "expand_templates_ok": "确定",
        "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 dir=\"ltr\">$wgDefaultSkin</code>定义的wiki默认皮肤<code>$1</code>不可用。您的安装版本看起来需要包含以下皮肤。参见MediaWiki官网手册[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/zh-hans 打包安装器],这会预装一些皮肤和扩展。您可在此处复制粘贴<code>skins/</code>。\n:* 通过git直接克隆<code>mediawiki/skins/*</code>存储库中的一个至您的MediaWiki副本的<code dir=\"ltr\">skins/</code>。\n: 做这些事应该不会打扰您的git存储库如果你是MediaWiki开发人员的话。\n\n; 如果您升级了您的MediaWiki的话:\n: MediaWiki 1.24版本起不再自动启用已安装皮肤(参见[https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery 此手册])。您可复制粘贴以下文本至您wiki的<code>LocalSettings.php</code>以启用安装的皮肤:\n\n<pre dir=\"ltr\">$3</pre>\n\n; 如果您已经修改了<code>LocalSettings.php</code>:\n: 请再次检查皮肤名以确保不存在错误拼写。",
+       "default-skin-not-found-no-skins": "天哪!您在<code>$wgDefaultSkin</code>定义的wiki默认皮肤<code>$1</code>不可用。而且您没有安装任何皮肤。\n\n; 如果您刚刚安装完了MediaWiki的话:\n: 您可能是从git库安装的,或者使用其他方法直接从源代码安装的。希望如此。尝试通过以下方法从[https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org的皮肤存储库]安装一些皮肤:\n:* 下载[https://www.mediawiki.org/wiki/Download/zh-hans 打包安装器],这会预装一些皮肤和扩展。您可在此处复制粘贴<code>skins/</code>。\n:* 通过git直接克隆<code>mediawiki/skins/*</code>存储库中的一个至您的MediaWiki副本的<code dir=\"ltr\">skins/</code>。\n: 做这些事应该不会打扰您的git存储库如果你是MediaWiki开发人员的话。参见MediaWiki官网手册[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('''已禁用''')"
 }
index 2dbb891..5cc05f6 100644 (file)
                        "Mywood",
                        "Cwek",
                        "Impersonator 1",
-                       "LNDDYL"
+                       "LNDDYL",
+                       "Cathypilot0117",
+                       "NigelSoft"
                ]
        },
-       "tog-underline": "連結底線:",
+       "tog-underline": "連結顯示底線:",
        "tog-hideminor": "隱藏最近變更中的小修訂",
-       "tog-hidepatrolled": "隱藏最近更改中巡查過的編輯",
+       "tog-hidepatrolled": "隱藏最近變更中巡查過的編輯",
        "tog-newpageshidepatrolled": "隱藏新頁面清單中巡查過的頁面",
        "tog-extendwatchlist": "展開監視清單顯示包含最近以外的所有變更",
        "tog-usenewrc": "依最近變更與監視清單頁面分類顯示變更",
        "tog-numberheadings": "標題自動編號",
        "tog-showtoolbar": "顯示編輯工具列",
-       "tog-editondblclick": "啟用滑鼠雙擊編輯頁面",
-       "tog-editsectiononrightclick": "啟用滑鼠右鍵點選章節標題編輯",
+       "tog-editondblclick": "開啟滑鼠雙擊編輯頁面",
+       "tog-editsectiononrightclick": "開啟滑鼠右鍵點選章節標題編輯",
        "tog-watchcreations": "將我建立的頁面和上傳的檔案加入監視清單",
        "tog-watchdefault": "將我編輯的頁面和檔案新增至監視清單",
        "tog-watchmoves": "將我移動的頁面和檔案加入監視清單",
        "tog-watchdeletion": "將我刪除的頁面和檔案新增至監視清單",
+       "tog-watchrollback": "將我曾經還原的頁面新增至監視清單",
        "tog-minordefault": "預設標記所有的編輯為小修訂",
        "tog-previewontop": "顯示預覽於編輯框上方",
        "tog-previewonfirst": "第一次編輯時顯示預覽",
@@ -91,7 +94,7 @@
        "tog-watchlisthideanons": "隱藏監視清單中匿名使用者的編輯",
        "tog-watchlisthidepatrolled": "隱藏監視清單中已巡查的編輯",
        "tog-ccmeonemails": "傳送郵件給他人時,也送一份副本到我的電子郵件信箱",
-       "tog-diffonly": "比對版本差異時下面不顯示頁面內容",
+       "tog-diffonly": "比對差異時下方不顯示頁面內容",
        "tog-showhiddencats": "顯示隱藏分類",
        "tog-norollbackdiff": "執行還原後略過差異比對",
        "tog-useeditwarning": "未儲存離開編輯頁面時警告我",
        "october-date": "十月 $1 日",
        "november-date": "十一月 $1 日",
        "december-date": "十二月 $1 日",
-       "pagecategories": "{{PLURAL:$1|分類|分類}}",
+       "pagecategories": "{{PLURAL:$1|分類|$1 個分類}}",
        "category_header": "分類 \"$1\" 中的頁面",
        "subcategories": "子分類",
        "category-media-header": "分類 \"$1\" 中的媒體",
        "listingcontinuesabbrev": "續",
        "index-category": "已列索引的頁面",
        "noindex-category": "未列索引的頁面",
-       "broken-file-category": "含有損壞檔案連結的頁面",
+       "broken-file-category": "檔案連結損壞的頁面",
        "about": "關於",
        "article": "內容頁面",
        "newwindow": "(以新視窗開啟)",
        "history_short": "歷史",
        "updatedmarker": "自我最後一次訪問以後的更新",
        "printableversion": "可列印版",
-       "permalink": "固定連結",
+       "permalink": "靜態連結",
        "print": "列印",
        "view": "檢視",
        "view-foreign": "用 $1 檢視",
        "talkpagelinktext": "對話",
        "specialpage": "特殊頁面",
        "personaltools": "個人工具",
-       "postcomment": "新章節",
        "articlepage": "檢視內容頁面",
        "talk": "討論",
        "views": "檢視",
        "otherlanguages": "其他語言",
        "redirectedfrom": "(已重新導向自 $1)",
        "redirectpagesub": "重新導向頁面",
+       "redirectto": "重新導向至:",
        "lastmodifiedat": "此頁面最後修訂於 $1 $2。",
        "viewcount": "此頁面已被檢視過 $1 次。",
        "protectedpage": "受保護頁面",
        "aboutpage": "Project:About",
        "copyright": "除非額外說明,否則本站內容均使用 $1 授權條款。",
        "copyrightpage": "{{ns:project}}:Copyrights",
-       "currentevents": "æ\96°è\81\9eå\8b\95æ\85\8b",
-       "currentevents-url": "Project:新聞動態",
+       "currentevents": "æ\9c\80æ\96°äº\8b件",
+       "currentevents-url": "Project:Current events",
        "disclaimers": "免責聲明",
        "disclaimerpage": "Project:General disclaimer",
        "edithelp": "編輯説明",
-       "mainpage": "首頁",
-       "mainpage-description": "首頁",
-       "policy-url": "Project:方針",
-       "portal": "社群主頁",
-       "portal-url": "Project:社群專頁",
+       "mainpage": "主頁面",
+       "mainpage-description": "主頁面",
+       "policy-url": "Project:Policy",
+       "portal": "社群入口",
+       "portal-url": "Project:Community portal",
        "privacy": "隱私政策",
        "privacypage": "Project:Privacy policy",
        "badaccess": "權限錯誤",
        "hidetoc": "隱藏",
        "collapsible-collapse": "合併",
        "collapsible-expand": "展開",
+       "confirmable-confirm": "{{GENDER:$1|您}}確定嗎?",
+       "confirmable-yes": "是",
+       "confirmable-no": "否",
        "thisisdeleted": "檢視或還原 $1 ?",
        "viewdeleted": "檢視 $1?",
        "restorelink": "$1 個已刪除的編輯",
        "feedlinks": "訂閱:",
-       "feed-invalid": "無效的訂閱類型。",
+       "feed-invalid": "無效的訂閱 Feed 類型。",
        "feed-unavailable": "目前未提供 RSS 或 Atom",
        "site-rss-feed": "$1 的 RSS feed",
        "site-atom-feed": "$1 的 Atom feed",
        "nstab-project": "專案頁面",
        "nstab-image": "檔案",
        "nstab-mediawiki": "訊息",
-       "nstab-template": "模æ\9d¿",
+       "nstab-template": "樣ç\89\88",
        "nstab-help": "說明頁面",
        "nstab-category": "分類",
        "nosuchaction": "無此動作",
        "readonly": "資料庫已鎖定",
        "enterlockreason": "請輸入鎖定的原因,包括估計重新開放的時間",
        "readonlytext": "資料庫目前已鎖定無法新增或修改資料,\n可能正在進行例行的資料庫維修作業,完成之後即可恢復正常。\n\n鎖定資料庫的管理員說明:$1",
-       "missing-article": "資料庫查無預期的頁面文字,頁面 \"$1\" $2。\n\n通常是因您連結到了已過期(已被刪除)的差異或歷史頁面。\n\n若這不是您所遇到的情況,您可能找到了一個系統的問題。\n請記錄 URL 位址,並向 [[Special:ListUsers/sysop|管理員]] 報告此問題。",
+       "missing-article": "資料庫查無預期的頁面文字,名稱為 \"$1\" $2。\n\n通常是因您連結到了已被刪除的差異或歷史頁面。\n\n若您所遇到的不是這個情況,您可能是發現軟體問題。\n請記錄 URL 位址,並向 [[Special:ListUsers/sysop|管理員]] 回報此問題。",
        "missingarticle-rev": "(修訂#:$1)",
        "missingarticle-diff": "(差異:$1, $2)",
        "readonly_lag": "資料庫已自動鎖定,正在等候次要資料庫同步資料到主要資料庫",
        "invalidtitle-knownnamespace": "無效的標題,命名空間 \"$2\" 與名稱 \"$3\"",
        "invalidtitle-unknownnamespace": "無效的標題,不明的命名空間編號 $1 與名稱 \"$2\"",
        "exception-nologin": "未登入",
-       "exception-nologin-text": "您需要先 [[Special:Userlogin|登入]] 檢視或者編輯此頁面。",
+       "exception-nologin-text": "請先登入以檢視或修改",
        "exception-nologin-text-manual": "請先 $1 以存取此頁面或操作。",
        "virus-badscanner": "錯誤的設定:不明的病毒掃瞄程式:<em>$1</em>",
        "virus-scanfailed": "掃瞄失敗 (代碼 $1)",
        "userlogin-yourpassword": "密碼",
        "userlogin-yourpassword-ph": "輸入您的密碼",
        "createacct-yourpassword-ph": "輸入密碼",
-       "yourpasswordagain": "再次輸入密碼:",
+       "yourpasswordagain": "再輸入密碼一次:",
        "createacct-yourpasswordagain": "確認密碼",
        "createacct-yourpasswordagain-ph": "再次輸入密碼",
        "remembermypassword": "在瀏覽器上記住我的登入資訊 (上限 $1 {{PLURAL:$1|天}})",
        "externaldberror": "這可能是由於資料庫驗證錯誤,或是不允許您更新外部帳號。",
        "login": "登入",
        "nav-login-createaccount": "登入/建立帳號",
-       "loginprompt": "您必須允許瀏覽器紀錄 Cookie 才能成功登入 {{SITENAME}}。",
        "userlogin": "登入/建立帳號",
        "userloginnocreate": "登入",
        "logout": "登出",
        "userlogout": "登出",
-       "notloggedin": "未登入",
+       "notloggedin": "未登入",
        "userlogin-noaccount": "沒有帳號嗎?",
        "userlogin-joinproject": "加入 {{SITENAME}}",
        "nologin": "您還沒有帳號嗎? $1。",
        "userlogin-resetlink": "您忘記了登入的詳細資訊?",
        "userlogin-resetpassword-link": "忘記密碼?",
        "userlogin-helplink2": "登入協助",
-       "userlogin-loggedin": "您目前已登入 {{GENDER:$1|$1}} 使用者,\n請使用下列表單改登入另一位使用者。",
-       "userlogin-createanother": "建立另一個帳號",
        "createacct-emailrequired": "電子郵件位址",
        "createacct-emailoptional": "電子郵件位址 (選填)",
        "createacct-email-ph": "輸入您的電子郵件位址",
        "createacct-another-email-ph": "輸入電子郵件位址",
-       "createaccountmail": "使ç\94¨è\87¨æ\99\82ç\9a\84é\9a¨æ©\9få¯\86碼ï¼\8c並å°\87å®\83å¯\84å\88°æ\8c\87å®\9aç\9a\84é\9b»å­\90é\83µä»¶å\9c°址",
+       "createaccountmail": "使ç\94¨è\87¨æ\99\82ç\9a\84é\9a¨æ©\9få¯\86碼ï¼\8c並å°\87å®\83å\82³é\80\81å\88°æ\8c\87å®\9aç\9a\84é\9b»å­\90é\83µä»¶ä½\8d址",
        "createacct-realname": "真實姓名 (選填)",
        "createaccountreason": "原因:",
        "createacct-reason": "原因",
        "passwordremindertext": "不明人士 (可能是您自己,來自 IP 位址 $1) 要求重設在 {{SITENAME}} ($4) 的密碼。\n給使用者 \"$2\" 的臨時密碼設為 \"$3\"。\n如果這個動作是您做的,您需要立即登入並設定一個新的密碼,\n您的臨時密碼將於{{PLURAL:$5|一|$5}}天內過期。\n\n如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略此訊息並且繼續使用您原本的密碼。",
        "noemail": "使用者 \"$1\" 未登記電子郵件位址。",
        "noemailcreate": "您需要提供一個有效的電子郵件位址。",
-       "passwordsent": "使用者 \"$1\" 的新密碼已寄至當出登記的電子郵件址,\n請稍後收到信件後再登入。",
+       "passwordsent": "使用者 \"$1\" 的新密碼已寄至當出登記的電子郵件址,\n請稍後收到信件後再登入。",
        "blocked-mailpassword": "您的 IP 位址已被封鎖不允許編輯,密碼復原的功能也同樣被禁止使用以防止被濫用。",
        "eauthentsent": "已寄出一封確認信到您所設定的電子郵件位址。\n在未收到其它電子郵件前,您必須先依照信件中的指示,確認這個帳號確實是您本人。",
        "throttled-mailpassword": "密碼重設的電子郵件已經在最近 $1 小時內寄出。\n為防止濫用,$1 小時內只能寄出一次密碼重設信件。",
-       "mailerror": "å¯\84å\87º電子郵件錯誤:$1",
+       "mailerror": "å\82³é\80\81電子郵件錯誤:$1",
        "acct_creation_throttle_hit": "使用您目前的 IP 位址的訪客在最近一天建立了 {{PLURAL:$1|1 個帳號|$1 個帳號}},已超出系統允許的上限。\n因此,目前無法讓使用此 IP 位址的訪客建立帳號。",
        "emailauthenticated": "您的電子郵件位址已確認於 $2 的 $3。",
-       "emailnotauthenticated": "您的電子郵件址尚未確認,\n尚不會寄出以下功能的電子郵件給您。",
-       "noemailprefs": "在您的偏好設定中設定電子郵件址,讓您可以使用這些功能。",
+       "emailnotauthenticated": "您的電子郵件址尚未確認,\n尚不會寄出以下功能的電子郵件給您。",
+       "noemailprefs": "在您的偏好設定中設定電子郵件址,讓您可以使用這些功能。",
        "emailconfirmlink": "確認您的電子郵件位址",
-       "invalidemailaddress": "無法接受格式不正確的電子郵件地址,\n請輸入正確的電子郵件地址格式或略過填寫該欄位。",
+       "invalidemailaddress": "無法接受格式不正確的電子郵件位址,\n請輸入正確的電子郵件位址格式或略過填寫該欄位。",
        "cannotchangeemail": "此 Wiki 不允許更改帳號的電子郵件位址。",
-       "emaildisabled": "此網ç«\99ä¸\8dè\83½å¯\84å\87º電子郵件。",
+       "emaildisabled": "此網ç«\99ä¸\8dè\83½å\82³é\80\81電子郵件。",
        "accountcreated": "已建立帳號",
        "accountcreatedtext": "使用者帳號 [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|對話]]) 已建立。",
        "createaccount-title": "{{SITENAME}} 的帳號建立",
        "pt-createaccount": "建立帳號",
        "pt-userlogout": "登出",
        "php-mail-error-unknown": "PHP 的 mail() 函數發生不明錯誤。",
-       "user-mail-no-addy": "試å\9c\96å¯\84å\87º沒有電子郵件位址的信件。",
-       "user-mail-no-body": "試圖寄出一個空的或異常簡短的電子郵件。",
+       "user-mail-no-addy": "試å\9c\96å\82³é\80\81沒有電子郵件位址的信件。",
+       "user-mail-no-body": "試圖寄出內容為空的或異常簡短的電子郵件。",
        "changepassword": "變更密碼",
        "resetpass_announce": "要完成登入,您必須設定一個新密碼。",
        "resetpass_text": "<!-- 在此處加入文字 -->",
        "passwordreset-emailtext-user": "使用者 $1 要求重設在 {{SITENAME}} ($4) 的密碼,下列是與此電子郵件位址有關的使用者{{PLURAL:$3|帳號}}:\n\n$2\n\n{{PLURAL:$3|這個臨時密碼|這些臨時密碼}}將會在{{PLURAL:$5|一天|$5 天}}內到期,\n您應立即登入並更改新的密碼。如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略此訊息並且繼續使用您原本的密碼。",
        "passwordreset-emailelement": "使用者名稱:$1\n臨時密碼:$2",
        "passwordreset-emailsent": "已寄出重設密碼的電子郵件。",
-       "passwordreset-emailsent-capture": "已寄出重設密碼的電子郵件,並在下面顯示。",
-       "passwordreset-emailerror-capture": "產生的重設密碼的電子郵件如下所示,但傳送給{{GENDER:$2|使用者}}失敗:$1",
+       "passwordreset-emailsent-capture": "已寄出重設密碼的電子郵件,並於下方顯示。",
+       "passwordreset-emailerror-capture": "下列為重設密碼的電子郵件內容,傳送給{{GENDER:$2|使用者}}失敗:$1",
        "changeemail": "變更電子郵件位址",
        "changeemail-header": "變更帳號的電子郵件位址",
-       "changeemail-text": "填寫表格以修æ\94¹æ\82¨ç\9a\84é\9b»å­\90é\83µä»¶ä½\8då\9d\80ã\80\82æ\82¨é\9c\80è¦\81輸å\85¥å¯\86碼以確認此次變更。",
+       "changeemail-text": "å®\8cæ\88\90此表å\96®ä»¥ä¿®æ\94¹æ\82¨ç\9a\84é\9b»å­\90é\83µä»¶ä½\8då\9d\80ï¼\8cæ\82¨é\9c\80è¦\81輸å\85¥æ\82¨ç\9a\84å¯\86碼ä¾\86確認此次變更。",
        "changeemail-no-info": "您必須登入方可直接存取此頁面。",
        "changeemail-oldemail": "目前的電子郵件位址:",
        "changeemail-newemail": "新的電子郵件位址:",
        "preview": "預覽",
        "showpreview": "顯示預覽",
        "showdiff": "顯示變更",
-       "anoneditwarning": "<strong>警告:</strong>您尚未登入。\n您的 IP 位址將記錄在此頁的編輯歷史中。",
+       "blankarticle": "<strong>警告:</strong>您正在建立的頁面是空白的。\n如果您再按一下\"{{int:savearticle}}\",將建立沒有任何內容的頁面。",
+       "anoneditwarning": "<strong>警告:</strong>您尚未登入。 若您進行任何的編輯您的 IP 位置將會被公開。 若您 <strong>[$1 登入]</strong> 或 <strong>[$2 建立帳號]</strong>,您的編輯將會以您的使用者名稱標示,擁有其他優點。",
        "anonpreviewwarning": "<em>您尚未登入。儲存頁面會將您的 IP 位址記錄在此頁面的編輯歷史中。</em>",
        "missingsummary": "<strong>提醒:</strong>您未填寫編輯摘要。\n若您再點選 \"{{int:savearticle}}\" 一次,將略過摘要直接儲存您的編輯。",
        "missingcommenttext": "請在下方輸入評論。",
        "summary-preview": "摘要預覽:",
        "subject-preview": "主旨/標題預覽:",
        "blockedtitle": "使用者已被封鎖",
-       "blockedtext": "<strong>您的使用者名稱或 IP 位址以被封鎖。</strong>\n\n您被 $1 封鎖,\n原因爲 <em>$2</em>。\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 相關封鎖對象:$7\n\n您可以聯繫 $1 或其他的 [[{{MediaWiki:Grouppage-sysop}}|管理員]] 討論封鎖的相關問題。\n若您已在 [[Special:Preferences|偏好設定]] 中設定了一個有效的電子郵件址,且尚未被封鎖郵件功能,則您可透過 \"傳送電子郵件給這位使用者\" 的功能來聯絡相關管理員。\n您目刖的 IP 位址是 $3,此次封鎖的 ID 爲 #$5。\n請您在詢問時附註以上詳細訊息。",
-       "autoblockedtext": "因先前的另一位使用者被 $1 封鎖,您的 IP 位址已被自動封鎖。\n原因是:\n\n:<em>$2</em>\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 相關封鎖對象:$7\n\n您可以聯繫 $1 或其他的 [[{{MediaWiki:Grouppage-sysop}}|管理員]] 討論封鎖的相關問題。\n若您已在 [[Special:Preferences|偏好設定]] 中設定了一個有效的電子郵件址,且尚未被封鎖郵件功能,則您可透過 \"傳送電子郵件給這位使用者\" 的功能來聯絡相關管理員。\n您目刖的 IP 位址是 $3,此次封鎖的 ID 爲 #$5。\n請您在詢問時附註以上詳細訊息。",
+       "blockedtext": "<strong>您的使用者名稱或 IP 位址以被封鎖。</strong>\n\n您被 $1 封鎖,\n原因爲 <em>$2</em>。\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 相關封鎖對象:$7\n\n您可以聯繫 $1 或其他的 [[{{MediaWiki:Grouppage-sysop}}|管理員]] 討論封鎖的相關問題。\n若您已在 [[Special:Preferences|偏好設定]] 中設定了一個有效的電子郵件址,且尚未被封鎖郵件功能,則您可透過 \"傳送電子郵件給這位使用者\" 的功能來聯絡相關管理員。\n您目刖的 IP 位址是 $3,此次封鎖的 ID 爲 #$5。\n請您在詢問時附註以上詳細訊息。",
+       "autoblockedtext": "因先前的另一位使用者被 $1 封鎖,您的 IP 位址已被自動封鎖。\n原因是:\n\n:<em>$2</em>\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 相關封鎖對象:$7\n\n您可以聯繫 $1 或其他的 [[{{MediaWiki:Grouppage-sysop}}|管理員]] 討論封鎖的相關問題。\n若您已在 [[Special:Preferences|偏好設定]] 中設定了一個有效的電子郵件址,且尚未被封鎖郵件功能,則您可透過 \"傳送電子郵件給這位使用者\" 的功能來聯絡相關管理員。\n您目刖的 IP 位址是 $3,此次封鎖的 ID 爲 #$5。\n請您在詢問時附註以上詳細訊息。",
        "blockednoreason": "未說明原因",
        "whitelistedittext": "請先 $1 才可編輯頁面。",
        "confirmedittext": "在編輯此頁之前您必須確認您的電子郵件位址。\n請透過 [[Special:Preferences|偏好設定]] 設定並驗證您的電子郵件位址。",
        "sitejspreview": "<strong>您目前正預覽此 JavaScript,JavaScript 還尚未儲存!</strong>",
        "userinvalidcssjstitle": "<strong>警告:</strong> 無此外觀樣式 \"$1\"。\n自訂的 .css 和 .js 頁面要使用小寫標題,例如:{{ns:user}}:Foo/vector.css 與 {{ns:user}}:Foo/Vector.css 是不同的。",
        "updated": "(已更新)",
-       "note": "</strong>注意:</strong>",
+       "note": "<strong>注意:</strong>",
        "previewnote": "<strong>您目前正在預覽,您的變更還尚未儲存!</strong>",
        "continue-editing": "前往編輯框",
        "previewconflict": "此預覽顯示了您於上方文字編輯框中的內容儲存之後將會顯示的結果。",
        "postedit-confirmation-saved": "您的編輯已儲存。",
        "edit-already-exists": "無法建立新頁面。\n該頁面已存在。",
        "defaultmessagetext": "預設訊息文字",
-       "content-failed-to-parse": "析 $2 格式的 $1 語法內容失敗:$3",
+       "content-failed-to-parse": "析 $2 格式的 $1 語法內容失敗:$3",
        "invalid-content-data": "內容資料無效",
        "content-not-allowed-here": "頁面 [[$2]] 不允許使用 \"$1\" 語法內容",
        "editwarning-warning": "離開此頁面可能會令您遺失之前所作的所有更改。\n若您已經登入,您可在偏好設定的 \"{{int:prefs-editing}}\" 項目關閉此警告。",
        "content-model-text": "純文字",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
-       "expensive-parserfunction-warning": "<strong>警告:</strong>此頁面使用了太多消耗系統資源的析函數。\n\n使用次數應小於 $2 次,但目前使用了 $1 次。",
+       "expensive-parserfunction-warning": "<strong>警告:</strong>此頁面使用了太多消耗系統資源的析函數。\n\n使用次數應小於 $2 次,但目前使用了 $1 次。",
        "expensive-parserfunction-category": "使用了太多消耗系統資源的分析函數的頁面",
        "post-expand-template-inclusion-warning": "<strong>警告:</strong>引用樣板後大小超出限制。\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-category-desc": "超出節點數量限制的頁面。",
        "node-count-exceeded-warning": "頁面超出節點數量限制",
        "expansion-depth-exceeded-category": "展開深度超出限制的頁面",
-       "expansion-depth-exceeded-category-desc": "這是超出展開深度頁面的分類。",
+       "expansion-depth-exceeded-category-desc": "超出展開深度限制的頁面。",
        "expansion-depth-exceeded-warning": "頁面超出展開深度限制",
        "parser-unstrip-loop-warning": "偵測到 Unstrip 迴圈",
        "parser-unstrip-recursion-limit": "Unstrip 遞迴超出限制 ($1)",
        "history-feed-item-nocomment": "$1 於 $2",
        "history-feed-empty": "請求的頁面不存在,\n可能已被刪除或重新命名。\n請嘗試 [[Special:Search|搜尋本站]] 取得其他相關的新頁面。",
        "rev-deleted-comment": "(已移除編輯摘要)",
-       "rev-deleted-user": "(已移除使用者名稱)",
+       "rev-deleted-user": " (已移除使用者名稱)",
        "rev-deleted-event": "(已移除日誌)",
        "rev-deleted-user-contribs": "[使用者名稱或 IP 位址已移除 - 已隱藏貢獻清單中的編輯]",
        "rev-deleted-text-permission": "此頁面修訂已被 <strong>刪除</strong>。\n可至 [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 刪除日誌] 取得詳細資訊。",
+       "rev-suppressed-text-permission": "此頁面修訂已被 <strong>禁止顯示</strong>。\n可至 [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 禁止顯示日誌] 取得詳細資訊。",
        "rev-deleted-text-unhide": "此頁面修訂已被 <strong>刪除</strong>。\n可至 [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 刪除日誌] 取得詳細資訊。\n若您要繼續,您仍可 [$1 檢視此修訂] 。",
        "rev-suppressed-text-unhide": "此頁面修訂已被 <strong>禁止顯示</strong>。\n可至 [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 禁止顯示日誌] 取得詳細資訊。\n若您要繼續,您仍可以 [$1 檢視此修訂]。",
        "rev-deleted-text-view": "此頁面修訂已被 <strong>刪除</strong>。\n您可繼續檢視修訂,可至 [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 刪除日誌] 取得詳細資訊。",
        "revdelete-text-text": "已刪除的修訂仍會出現於頁面歷史中,但內容將不開放存取。",
        "revdelete-text-file": "已刪除的檔案版本仍會出現於檔案歷史中,但內容將不開放存取。",
        "logdelete-text": "已刪除的日誌活動仍會出現於日誌中,但內容將不開放存取。",
-       "revdelete-text-others": "在 {{SITENAME}} 上的其他管理員仍有權限可以存取隱藏的內容,且能夠取消刪除,除非有額外的設定限制。",
+       "revdelete-text-others": "若未有額外的設定限制,其他管理員仍有權限檢視與取消刪除隱藏的內容。",
        "revdelete-confirm": "請確認您是否明白此動作會造成的後果,\n以及您所做的動作是否符合 [[{{MediaWiki:Policy-url}}|政策]] 規範。",
        "revdelete-suppress-text": "禁制顯示應<strong>只有</strong>在下述情形時使用:\n* 潛在誹謗的資訊\n* 不合適個人資料\n*: <em>住家地址、電話號碼、身分證字號等。</em>",
        "revdelete-legend": "設定顯示限制",
        "mergehistory-submit": "合併修訂",
        "mergehistory-empty": "沒有可以合併的修訂",
        "mergehistory-success": "[[:$1]] 中 $3 次修訂已經成功地合併至 [[:$2]]。",
-       "mergehistory-fail": "不可以進行歷史合併,請重新檢查該頁面以及時間參數。",
-       "mergehistory-fail-toobig": "由於超出$1個合併移動版本的上限,故此無法進行歷史合併。",
+       "mergehistory-fail": "無法進行歷史合併,請重新檢查該頁面及時間參數。",
+       "mergehistory-fail-toobig": "超過 $1 個修訂移動的上限,無法進行歷史合併。",
        "mergehistory-no-source": "來源頁面 $1 不存在。",
        "mergehistory-no-destination": "目標頁面 $1 不存在。",
        "mergehistory-invalid-source": "來源頁面必須使用有效的標題。",
        "showhideselectedversions": "更改已選擇修訂的顯示設定",
        "editundo": "還原",
        "diff-empty": "(無差異)",
-       "diff-multi-sameuser": "(未顯示相同使用者於中間所作的 $1 次修訂)",
+       "diff-multi-sameuser": "(未顯示同一使用者於中間所作的 $1 次修訂)",
        "diff-multi-otherusers": "(未顯示由 $2 位使用者於中間所作的 $1 次修訂)",
        "diff-multi-manyusers": "(未顯示由超過 $2 位使用者於中間所作的 $1 次修訂)",
-       "difference-missing-revision": "{{PLURAL:$2|1次修訂|$2 次修訂}}差異($1)不存在。\n\n這通常是因為過時的頁面修訂差異鏈接被刪除。\n詳情請閱[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 刪除日誌]。",
+       "difference-missing-revision": "查無此差異 ($1) 中的{{PLURAL:$2|1 次修訂|$2 次修訂}}。\n\n這通常是因為差異的連結過時,頁面已被刪除。\n詳情資訊請參閱 [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 刪除日誌]。",
        "searchresults": "搜尋結果",
        "searchresults-title": "\"$1\" 的搜尋結果",
        "titlematches": "頁面標題符合",
        "searchprofile-advanced-tooltip": "搜尋自訂命名空間",
        "search-result-size": "$1 ($2 個字)",
        "search-result-category-size": "$1 位成員 ($2 個子分類,$3 個檔案)",
-       "search-result-score": "相關度:$1%",
        "search-redirect": "(重新導向 $1)",
        "search-section": "(章節 $1)",
        "search-file-match": "(符合檔案內容)",
        "search-suggest": "您指的是不是:$1",
        "search-interwiki-caption": "姐妹專案",
        "search-interwiki-default": "來自 $1 的結果:",
-       "search-interwiki-more": "(更多)",
+       "search-interwiki-more": "(更多)",
        "search-relatedarticle": "相關",
        "searchrelated": "相關",
        "searchall": "全部",
        "showingresults": "以下顯示從第 <strong>$2</strong> 筆開始,共 {{PLURAL:$1|<strong>1</strong> 筆結果|<strong>$1</strong> 筆結果}}:",
        "showingresultsinrange": "以下顯示從第 <strong>$2</strong> 筆至第 <strong>$3</strong> 筆中的 {{PLURAL:$1|<strong>1</strong> 筆結果|<strong>$1</strong> 筆結果}}:",
-       "showingresultsheader": "<strong>$4</strong> 的 {{PLURAL:$5|第 <strong>$1</strong> 筆結果,共 <strong>$3</strong> 筆|第 <strong>$1 - $2</strong>,共 <strong>$3</strong> 筆}}",
+       "search-showingresults": "{{PLURAL:$4|<strong>$3</strong> 的 <strong>$1</strong> 筆結果|<strong>$3</strong> 的 <strong>$1 - $2</strong> 筆結果}}",
        "search-nonefound": "無符合查詢條件的結果。",
        "powersearch-legend": "進階搜尋",
        "powersearch-ns": "搜尋以下命名空間:",
        "powersearch-togglelabel": "請選擇:",
        "powersearch-toggleall": "全部",
        "powersearch-togglenone": "無",
-       "powersearch-remember": "記住選項用於以後搜",
+       "powersearch-remember": "記住選項用於以後搜",
        "search-external": "外部搜尋",
        "searchdisabled": "{{SITENAME}} 已停用搜尋功能。\n您可以改透過 Google 搜尋。\n請注意,在 Google 中搜尋到的 {{SITENAME}} 頁面內容可能不是最新的。",
        "search-error": "搜尋時發生錯誤:$1",
        "preferences": "偏好設定",
        "mypreferences": "偏好設定",
        "prefs-edits": "編輯次數:",
-       "prefsnologintext2": "請 $1 以更改您的偏好設定。",
+       "prefsnologintext2": "請登入以更改您的偏好設定。",
        "prefs-skin": "外觀",
        "skin-preview": "預覽",
        "datedefault": "預設值",
        "recentchangesdays-max": "最多 $1 {{PLURAL:$1|天}}",
        "recentchangescount": "預設顯示的編輯數:",
        "prefs-help-recentchangescount": "這包含最近變更、頁面歷史以及日誌。",
-       "prefs-help-watchlist-token2": "訂閱您的監視清單所需的密鑰。\n任何人只要知道密鑰就能夠讀取您的監視列表,所以請勿任意與它人共享。\n若有需要 [[Special:ResetTokens|您可重設密鑰]]。",
-       "savedprefs": "您的偏好設定已儲存。",
+       "prefs-help-watchlist-token2": "訂閱您的監視清單所需的密鑰。\n任何人只要知道密鑰就能夠讀取您的監視清單,所以請勿任意與它人共享。\n若有需要 [[Special:ResetTokens|您可重設密鑰]]。",
+       "savedprefs": "已儲存您的偏好設定。",
        "timezonelegend": "時區:",
        "localtime": "當地時間:",
        "timezoneuseserverdefault": "使用 Wiki 預設值 ($1)",
        "timezoneregion-europe": "歐洲",
        "timezoneregion-indian": "印度洋",
        "timezoneregion-pacific": "太平洋",
-       "allowemail": "啟用來自其他使用者的郵件通知功能",
+       "allowemail": "開啟來自其他使用者的郵件通知功能",
        "prefs-searchoptions": "搜尋",
        "prefs-namespaces": "命名空間",
        "default": "預設",
        "prefs-help-variant": "您希望用於顯示本站內容的語種或拼寫語系。",
        "yournick": "新的簽名:",
        "prefs-help-signature": "在對話頁面上評論時應使用 \"<nowiki>~~~~</nowiki>\" 簽名,\n該符號會轉換成您的簽名與時間。",
-       "badsig": "錯誤的原始簽名。請檢查HTML標籤。",
-       "badsiglength": "您的簽名過長。\n它的長度不可超過$1個字元。",
-       "yourgender": "您希望如何被描述?",
+       "badsig": "錯誤的原始簽名。請檢查 HTML 標籤。",
+       "badsiglength": "您的簽名過長。\n它的長度不可超過 $1 個字元。",
+       "yourgender": "您希望使用何種性別稱呼?",
        "gender-unknown": "我不想說明",
        "gender-male": "他編輯了 Wiki 頁面",
        "gender-female": "她編輯了 Wiki 頁面",
        "prefs-help-gender": "此偏好設定為選填欄位。\n系統會使用您選擇的方式稱呼您,對他人提及您時也會使用適當語法稱呼。\n此項資訊會被公開。",
        "email": "電子郵件",
        "prefs-help-realname": "真實姓名為選填欄位。\n若您提供真實姓名,它會用於使用者貢獻署名。",
-       "prefs-help-email": "電子郵件址為選填欄位。\n但在重設密碼時會使用,而您很有可能會忘記密。",
+       "prefs-help-email": "電子郵件址為選填欄位。\n但在重設密碼時會使用,而您很有可能會忘記密。",
        "prefs-help-email-others": "您亦可以選擇讓其他使用者用電子郵件與您聯繫,透過您的使用者或對話頁面上方的連結。\n您的電子郵件位址不會實際告知給其他要聯絡您的使用者。",
        "prefs-help-email-required": "電子郵件地址是必填項目。",
        "prefs-info": "基本資訊",
        "prefs-tokenwatchlist": "密鑰",
        "prefs-diffs": "差異",
        "prefs-help-prefershttps": "此偏好設定將於您下次登入時生效。",
-       "prefs-tabs-navigation-hint": "提示:您可通過左、右鍵於選項卡之間切換。",
+       "prefs-tabs-navigation-hint": "提示:您可使用左、右方向鍵切換頁籤。",
        "email-address-validity-valid": "電子郵件位址有效",
-       "email-address-validity-invalid": "請提供一個有效的電子郵件位址",
+       "email-address-validity-invalid": "請輸入一個有效的電子郵件位址",
        "userrights": "使用者權限管理",
        "userrights-lookup-user": "管理使用者群組",
-       "userrights-user-editname": "輸入使用者名稱:",
+       "userrights-user-editname": "è«\8b輸å\85¥ä½¿ç\94¨è\80\85å\90\8d稱ï¼\9a",
        "editusergroup": "編輯使用者群組",
-       "editinguser": "變更使用者 '''[[User:$1|$1]]''' 的使用者權限 $2",
+       "editinguser": "變更使用者 <strong>[[User:$1|$1]]</strong> 的使用者權限 $2",
        "userrights-editusergroup": "編輯使用者群組",
        "saveusergroups": "儲存使用者群組",
        "userrights-groupsmember": "所屬群組:",
        "userrights-no-interwiki": "您沒有權限去編輯其它使用者在 Wiki 上的權限。",
        "userrights-nodatabase": "資料庫 $1 不存在或不在本地主機的。",
        "userrights-nologin": "您必須 [[Special:UserLogin|登入]] 管理員帳號以指定使用者權限。",
-       "userrights-notallowed": "你無權加入或刪除使用者權限。",
+       "userrights-notallowed": "您沒有權限加入或刪除使用者權限。",
        "userrights-changeable-col": "您可變更的群組",
        "userrights-unchangeable-col": "您不可變更的群組",
        "userrights-conflict": "使用者權限更改發生衝突!請重新檢視並確認你的更改。",
-       "userrights-removed-self": "æ\82¨å·²æ\88\90å\8a\9f移é\99¤è\87ªå·±ç\9a\84æ¬\8aé\99\90ï¼\8cæ\95\85æ­¤æ\82¨æ²\92æ³\95å\86\8d次訪å\95\8fæ­¤é \81。",
+       "userrights-removed-self": "æ\82¨å·²æ\88\90å\8a\9f移é\99¤è\87ªå·±ç\9a\84æ¬\8aé\99\90ï¼\8cæ\82¨å·²ç\84¡æ³\95å\86\8d次å­\98å\8f\96æ­¤é \81é\9d¢。",
        "group": "群組:",
        "group-user": "使用者",
-       "group-autoconfirmed": "自動確認使用者",
+       "group-autoconfirmed": "自動確認使用者",
        "group-bot": "機器人",
        "group-sysop": "管理員",
        "group-bureaucrat": "行政員",
-       "group-suppress": "監督",
+       "group-suppress": "監督",
        "group-all": "(全部)",
        "group-user-member": "{{GENDER:$1|使用者}}",
        "group-autoconfirmed-member": "自動確認使用者",
        "right-deletedtext": "檢視已刪除修訂中已刪除的文字及變更",
        "right-browsearchive": "搜尋已刪除的頁面",
        "right-undelete": "取消刪除頁面",
-       "right-suppressrevision": "複查與還原由管理員隱藏的修訂",
+       "right-suppressrevision": "檢視、隱藏與取消隱藏任何使用者對頁面的修訂",
+       "right-viewsuppressed": "檢視所有使用者的隱藏修訂",
        "right-suppressionlog": "檢視非公開日誌",
        "right-block": "封鎖其他使用者的編輯權限",
-       "right-blockemail": "封鎖使用者傳送電子郵件的權限",
+       "right-blockemail": "封鎖使用者傳送電子郵件",
        "right-hideuser": "封鎖使用者名稱,避免公開顯示",
        "right-ipblock-exempt": "略過 IP 封鎖、自動封鎖及範圍封鎖檢查",
        "right-proxyunbannable": "略過 Proxy 自動封鎖檢查",
        "right-editmyuserjs": "編輯自己的使用者 JavaScript 檔",
        "right-viewmywatchlist": "檢視自己的監視清單",
        "right-editmywatchlist": "編輯自己的監視清單。注意,即使無此權限,某些操作仍會新增頁面至監視清單。",
-       "right-viewmyprivateinfo": "檢視自己的私隱資料 (如:電子郵件址及真實姓名)",
-       "right-editmyprivateinfo": "編輯自己的私隱資料 (如:電子郵件址及真實姓名)",
+       "right-viewmyprivateinfo": "檢視自己的私隱資料 (如:電子郵件址及真實姓名)",
+       "right-editmyprivateinfo": "編輯自己的私隱資料 (如:電子郵件址及真實姓名)",
        "right-editmyoptions": "編輯自己的偏好設定",
        "right-rollback": "快速還原最後一位使用者對某一頁面的編輯",
        "right-markbotedits": "標示還原編輯為機械人編輯",
        "right-import": "由其他 Wiki 匯入頁面",
        "right-importupload": "由檔案上傳匯入頁面",
        "right-patrol": "標示其他人的編輯爲已巡查",
-       "right-autopatrol": "將自己的編輯自動標示為已巡查",
+       "right-autopatrol": "將自己的編輯自動標示為已巡查",
        "right-patrolmarks": "檢視最近變更的巡查標記",
        "right-unwatchedpages": "檢視未監視的頁面",
        "right-mergehistory": "合併頁面歷史",
        "action-minoredit": "標示此編輯為小修訂",
        "action-move": "移動此頁面",
        "action-move-subpages": "移動此頁面與它的子頁面",
-       "action-move-rootuserpages": "移動使用者根頁面",
+       "action-move-rootuserpages": "移動根使用者頁面",
        "action-move-categorypages": "移動分類頁面",
        "action-movefile": "移動此檔案",
        "action-upload": "上傳此檔案",
        "action-importupload": "由檔案上傳匯入頁面",
        "action-patrol": "標示其它人的編輯為已巡查",
        "action-autopatrol": "標示您的編輯為已巡查",
-       "action-unwatchedpages": "檢視未監視的頁面列表",
+       "action-unwatchedpages": "檢視未監視的頁面清單",
        "action-mergehistory": "合併此頁面的歷史",
        "action-userrights": "編輯所有使用者的權限",
        "action-userrights-interwiki": "編輯在其它 Wiki 上的使用者權限",
-       "action-siteadmin": "鎖定解除鎖定資料庫",
+       "action-siteadmin": "鎖定解除鎖定資料庫",
        "action-sendemail": "傳送電子郵件",
        "action-editmywatchlist": "編輯您的監視清單",
        "action-viewmywatchlist": "檢視您的監視清單",
-       "action-viewmyprivateinfo": "æ\9f¥ç\9c\8bæ\82¨ç\9a\84å\80\8b人è³\87æ\96\99",
-       "action-editmyprivateinfo": "編輯您的個人資",
+       "action-viewmyprivateinfo": "檢è¦\96æ\82¨ç\9a\84å\80\8b人è³\87è¨\8a",
+       "action-editmyprivateinfo": "編輯您的個人資",
        "nchanges": "$1 次變更",
        "enhancedrc-since-last-visit": "自上次訪問已有 $1",
        "enhancedrc-history": "歷史",
        "recentchanges-legend-heading": "'''說明:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (請參考 [[Special:NewPages|最新頁面]])",
        "recentchanges-legend-plusminus": "(<em>±123</em>)",
-       "rcnotefrom": "以下為自 <strong>$2</strong> 以來的變更 (最多顯示 <strong>$1</strong> 筆)。",
+       "rcnotefrom": "以下{{PLURAL:$5|為}}自 <strong>$3 $4</strong> 以來的變更 (最多顯示 <strong>$1</strong> 筆)。",
        "rclistfrom": "顯示自 $3 $2 以來的最近變更",
        "rcshowhideminor": "$1 小修訂",
        "rcshowhideminor-show": "顯示",
        "uploadbtn": "上傳檔案",
        "reuploaddesc": "取消上傳並返回上傳表單",
        "upload-tryagain": "送出修改後的檔案描述",
-       "uploadnologin": "未登入",
+       "uploadnologin": "未登入",
        "uploadnologintext": "您必須先 $1 才能上傳檔案。",
        "upload_directory_missing": "缺少上傳目錄 ($1) 且網頁伺服器沒有權限建立。",
        "upload_directory_read_only": "網頁伺服器沒有上傳目錄 ($1) 的寫入權限。",
        "uploadlogpage": "上傳日誌",
        "uploadlogpagetext": "以下清單為最近上傳的檔案。\n請檢視 [[Special:NewFiles|最新檔案圖庫]] 以視覺化的方式檢視。",
        "filename": "檔案名稱",
-       "filedesc": "æª\94æ¡\88æ\91\98è¦\81",
-       "fileuploadsummary": "æª\94æ¡\88æ\91\98è¦\81ï¼\9a",
+       "filedesc": "摘要",
+       "fileuploadsummary": "摘要:",
        "filereuploadsummary": "檔案變更:",
        "filestatus": "版權狀態:",
        "filesource": "來源:",
        "illegal-filename": "不允許使用的檔案名稱。",
        "overwrite": "不允許覆蓋現有檔案。",
        "unknown-error": "發生不明錯誤。",
-       "tmp-create-error": "無法建立臨時檔案。",
+       "tmp-create-error": "無法建立暫存檔案。",
        "tmp-write-error": "寫入臨時檔案發生錯誤。",
        "large-file": "建議的檔案大小上限為 $1;\n此檔案為 $2。",
        "largefileserver": "此檔案大小超出伺服器設定的允許範圍。",
-       "emptyfile": "您上傳的檔案為空的。\n可能是檔案名輸入錯誤。\n請檢查您是否真的要上傳空檔案。",
+       "emptyfile": "您上傳的檔案為空的。\n可能是檔案名輸入錯誤。\n請檢查您是否真的要上傳空檔案。",
        "windows-nonascii-filename": "本 Wiki 不支援使用特殊符號的檔案名稱。",
        "fileexists": "已存在相同名稱的檔案,若{{GENDER:|您}}不確定是否要變更它,請檢查 <strong>[[:$1]]</strong>。\n[[$1|thumb]]",
        "filepageexists": "此檔案的描述頁面 <strong>[[:$1]]</strong> 已存在,但目前沒有使用此名稱的檔案。\n您在此輸入的摘要不會儲存到該描述頁面,\n您必須手動編輯該描述頁面。\n[[$1|thumb]]",
        "uploadwarning": "上傳警告",
        "uploadwarning-text": "請修改以下的檔案描述並重試。",
        "savefile": "儲存檔案",
-       "uploadedimage": "已上傳 \"[[$1]]\"",
-       "overwroteimage": "已上傳新版本的 \"[[$1]]\"",
        "uploaddisabled": "己停用上傳。",
        "copyuploaddisabled": "己停用使用 URL 上傳。",
        "uploaddisabledtext": "已停用檔案上傳。",
        "watchthisupload": "監視此檔案",
        "filewasdeleted": "先前已有同樣名稱的檔案上傳,後來被刪除。\n您應在上傳此檔案前檢查 $1。",
        "filename-bad-prefix": "您上傳的檔案名稱以 <strong>\"$1\"</strong> 開頭,是不具任何描述意義的名稱,通常由數位相機自動產生。\n請替您的檔案使用一個更具描述意義的名稱。",
-       "upload-success-subj": "上傳成功",
+       "upload-success-subj": "成功上傳",
        "upload-success-msg": "您已成功使用 [$2] 上傳檔案,可於此處取得檔案:[[:{{ns:file}}:$1]]",
        "upload-failure-subj": "上傳問題",
        "upload-failure-msg": "您使用 [$2] 上傳的檔案發生問題:\n\n$1",
        "upload-proto-error": "通訊協定不正確",
        "upload-proto-error-text": "遠端上傳檔案需要使用以 <code>http://</code> 或 <code>ftp://</code> 開頭的 URL。",
        "upload-file-error": "內部錯誤",
-       "upload-file-error-text": "嘗試在伺服器上建立臨時檔案時發生內部錯誤。\n請連絡 [[Special:ListUsers/sysop|管理員]]。",
+       "upload-file-error-text": "嘗試在伺服器上建立暫存檔案時發生內部錯誤。\n請連絡 [[Special:ListUsers/sysop|管理員]]。",
        "upload-misc-error": "不明的上傳錯誤",
        "upload-misc-error-text": "上傳時發生不明錯誤。\n請檢查您的 URL 是否有效且可存取,然後再重試一次。\n如果仍有問題,請聯絡 [[Special:ListUsers/sysop|管理員]]。",
        "upload-too-many-redirects": "該 URL 重新導向至太多其他位址",
        "license": "授權條款:",
        "license-header": "授權條款",
        "nolicense": "尚未選擇",
+       "licenses-edit": "編輯授權條款選項",
        "license-nopreview": "(不可預覽)",
-       "upload_source_url": "(有效,可公開存取的 URL)",
-       "upload_source_file": "(在您電腦上的檔案)",
-       "listfiles-summary": "此特殊頁面顯示所有上傳過的檔案。",
+       "upload_source_url": "(您選擇的檔案來自有效,可公開存取的 URL)",
+       "upload_source_file": "(您在您的電腦上選擇的檔案)",
+       "listfiles-delete": "刪除",
+       "listfiles-summary": "此特殊頁面顯示所有已上傳的檔案。",
        "listfiles_search_for": "搜尋媒體名稱:",
        "imgfile": "檔案",
-       "listfiles": "檔案列表",
+       "listfiles": "檔案清單",
        "listfiles_thumb": "縮圖",
        "listfiles_date": "日期",
        "listfiles_name": "名稱",
        "filehist-user": "使用者",
        "filehist-dimensions": "尺寸",
        "filehist-filesize": "檔案大小",
-       "filehist-comment": "註解",
-       "imagelinks": "檔案使用",
-       "linkstoimage": "下列 $1 個頁面連結到此檔案:",
-       "linkstoimage-more": "超過$1個頁面連接到這個檔案。\n此處只列出首$1個連接到此檔案的頁面。\n您也可以查看[[Special:WhatLinksHere/$2|完整的清單]]。",
-       "nolinkstoimage": "沒有頁面連接到本檔案。",
-       "morelinkstoimage": "檢視連到這個檔案的[[Special:WhatLinksHere/$1|更多連結]]。",
+       "filehist-comment": "備註",
+       "imagelinks": "檔案用途",
+       "linkstoimage": "下列 {{PLURAL:$1|頁面連結|$1 個頁面連結}}到此檔案:",
+       "linkstoimage-more": "超過 $1 個{{PLURAL:$1|頁面連結|頁面連結}}到此檔案。\n下列清單只列出前 {{PLURAL:$1|1 筆連結|$1 筆連結}}到此檔案的頁面。\n您也可以檢視 [[Special:WhatLinksHere/$2|完整清單]]。",
+       "nolinkstoimage": "沒有頁面連結到此檔案。",
+       "morelinkstoimage": "檢視連到這個檔案的[[Special:WhatLinksHere/$1|更多連結]]。",
        "linkstoimage-redirect": "$1 (檔案重新導向) $2",
        "duplicatesoffile": "以下 $1 個檔案與此檔案重覆 ([[Special:FileDuplicateSearch/$2|了解詳細資訊]]):",
        "sharedupload": "此檔案來自 $1 且可能被其他專案所使用。",
        "download": "下載",
        "unwatchedpages": "未監視的頁面",
        "listredirects": "重新導向頁面清單",
-       "listduplicatedfiles": "重複檔案列表",
-       "listduplicatedfiles-summary": "以下列表中某檔案之最新版本與其他檔案之最新版本重複。進包含本地檔案",
+       "listduplicatedfiles": "重複檔案清單",
+       "listduplicatedfiles-summary": "此清單中包含最新版本的檔案與其他檔案重複的清單,本清單只顯示本地檔案。",
        "listduplicatedfiles-entry": "[[:File:$1|$1]] 有[[$3|其他 $2 個重複檔案]]。",
        "unusedtemplates": "未使用的樣版",
        "unusedtemplatestext": "此頁面列出所有於 {{ns:template}} 命名空間下未被其他頁面引用的樣版。\n在刪除前,仍需檢查是否有連結這些樣版的其他頁面。",
        "unusedtemplateswlh": "其他連結",
        "randompage": "隨機頁面",
        "randompage-nopages": "在{{PLURAL:$2|命名空間}}中沒有任何頁面:$1。",
-       "randomincategory": "分類中的隨機頁面",
+       "randomincategory": "隨機分類頁面",
        "randomincategory-invalidcategory": "\"$1\" 不是一個有效的分類名稱。",
-       "randomincategory-nopages": "[[:Category:$1]]中沒有頁面。",
-       "randomincategory-selectcategory": "從分類中獲取隨機頁面:$1 $2",
-       "randomincategory-selectcategory-submit": "執行",
+       "randomincategory-nopages": "[[:Category:$1]] 中沒有任何頁面。",
+       "randomincategory-category": "分類:",
+       "randomincategory-legend": "隨機分類頁面",
        "randomredirect": "隨機重新導向",
        "randomredirect-nopages": "在命名空間 \"$1\" 中沒有任何重新導向頁面。",
        "statistics": "統計",
        "statistics-articles": "內容頁面",
        "statistics-pages": "頁面",
        "statistics-pages-desc": "在 Wiki 上所有的頁面,包括對話頁面、重新導向頁面等。",
-       "statistics-files": "已上傳的檔案",
+       "statistics-files": "已上傳的檔案",
        "statistics-edits": "自 {{SITENAME}} 成立以來的頁面編輯數",
        "statistics-edits-average": "每頁平均編輯數",
        "statistics-views-total": "檢視總數",
-       "statistics-views-total-desc": "ä¸\8då­\98å\9c¨é \81é\9d¢å\92\8cç\89¹æ®\8aé \81é\9d¢ç\9a\84æ\9f¥ç\9c\8bæ\95¸æ\9cªè¨\88å\85¥",
+       "statistics-views-total-desc": "ä¸\8då\8c\85å\90«ä¸\8då­\98å\9c¨é \81é\9d¢è\88\87ç\89¹æ®\8aé \81é\9d¢ç\9a\84檢è¦\96æ\95¸",
        "statistics-views-peredit": "每次編輯檢視數",
        "statistics-users": "已註冊的 [[Special:ListUsers|使用者]]",
        "statistics-users-active": "活動使用者",
        "statistics-users-active-desc": "在最近 $1 天操作過的使用者",
-       "statistics-mostpopular": "被查閱次數最多的頁面",
+       "statistics-mostpopular": "檢視最多次的頁面",
        "pageswithprop": "擁有屬性的頁面",
-       "pageswithprop-legend": "有頁面屬性的頁面",
+       "pageswithprop-legend": "æ\93\81æ\9c\89é \81é\9d¢å±¬æ\80§ç\9a\84é \81é\9d¢",
        "pageswithprop-text": "此頁面用來查詢使用了指定屬性的頁面。",
        "pageswithprop-prop": "屬性名稱:",
        "pageswithprop-submit": "執行",
        "brokenredirectstext": "以下的重新導向頁面連結的頁面不存在:",
        "brokenredirects-edit": "編輯",
        "brokenredirects-delete": "刪除",
-       "withoutinterwiki": "未有語言連結的頁面",
+       "withoutinterwiki": "語言連結的頁面",
        "withoutinterwiki-summary": "下列是沒有連結到其它語言版本的頁面。",
        "withoutinterwiki-legend": "字首",
        "withoutinterwiki-submit": "顯示",
        "specialpage-empty": "此報表無查無任何結果。",
        "lonelypages": "孤立頁面",
        "lonelypagestext": "下列頁面尚未被 {{SITENAME}} 中的其它頁面連結或引用。",
-       "uncategorizedpages": "待分類頁面",
-       "uncategorizedcategories": "待分類類別",
-       "uncategorizedimages": "待分類檔案",
+       "uncategorizedpages": "未分類的頁面",
+       "uncategorizedcategories": "未分類的分類",
+       "uncategorizedimages": "未分類的檔案",
        "uncategorizedtemplates": "待分類樣版",
        "unusedcategories": "未使用的分類",
        "unusedimages": "未使用的檔案",
-       "popularpages": "ç\86±é»\9e頁面",
+       "popularpages": "ç\86±é\96\80頁面",
        "wantedcategories": "需要的分類",
        "wantedpages": "需要的頁面",
-       "wantedpages-badtitle": "在結果組上的無效標題: $1",
+       "wantedpages-badtitle": "結果集合中的標題無效:$1",
        "wantedfiles": "需要的檔案",
-       "wantedfiletext-cat": "以下檔案被使用,但不存在。外部儲存庫的文件儘管現有,但可能會在此列出,任何此類的誤報將被<del>剔除</del>。此外,內嵌了不存在的檔案的網頁將在[[:$1]]列出。",
-       "wantedfiletext-nocat": "以下檔案被使用,但不存在。外部儲存庫的文件儘管現有,但可能會在此列出,任何此類的誤報將被<del>剔除</del>。",
+       "wantedfiletext-cat": "下列檔案被時用,但檔案不存在。 外部儲存庫的檔案儘管存在,但此清單仍會列出。 這類誤報的項目會以 <del>刪除線</del> 標示。 另外,頁面內嵌檔案不存在會於清單 [[:$1]] 中顯示。",
+       "wantedfiletext-cat-noforeign": "下列檔案已被使用但不存在。 除此之外,頁面已內嵌但不存在的檔案列於 [[:$1]]。",
+       "wantedfiletext-nocat": "下列檔案被時用,但檔案不存在。 外部儲存庫的檔案儘管存在,但此清單仍會列出。 這類誤報的項目會以 <del>刪除線</del> 標示。",
+       "wantedfiletext-nocat-noforeign": "下列檔案已被使用但不存在。",
        "wantedtemplates": "需要的樣版",
-       "mostlinked": "最多連結頁面",
-       "mostlinkedcategories": "最多連結分類",
-       "mostlinkedtemplates": "最多被嵌入包含的頁面",
-       "mostcategories": "最多分類頁面",
-       "mostimages": "最多連結檔案",
+       "mostlinked": "被連結最多的頁面",
+       "mostlinkedcategories": "被連結最多的分類",
+       "mostlinkedtemplates": "被引用最多的頁面",
+       "mostcategories": "最多分類頁面",
+       "mostimages": "被連結最多的檔案",
        "mostinterwikis": "最多 Interwiki 連結的頁面",
-       "mostrevisions": "最多修訂頁面",
+       "mostrevisions": "最多修訂頁面",
        "prefixindex": "所有頁面與字首",
        "prefixindex-namespace": "所有含字首的頁面 ($1 命名空間)",
        "prefixindex-strip": "於清單中省略字首",
        "protectedpages-summary": "此頁面列出目前受保護的頁面。 欲查詢受保護標題清單,請參考 [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]]。",
        "protectedpages-cascade": "只顯示連鎖的保護頁面",
        "protectedpages-noredirect": "隱藏重新導向頁面",
-       "protectedpagesempty": "在這些參數下沒有頁面正在保護。",
+       "protectedpagesempty": "目前沒有使用這些參數的受保護頁面。",
        "protectedpages-timestamp": "日期時間",
        "protectedpages-page": "頁面",
        "protectedpages-expiry": "期限",
        "protectedpages-unknown-performer": "不明的使用者",
        "protectedtitles": "受保護標題",
        "protectedtitles-summary": "此頁面列出目前受保護的標題。 欲查詢受保護頁面清單,請參考 [[{{#special:ProtectedPages}}|{{int:protectedpages}}]]。",
-       "protectedtitlesempty": "在這些參數之下並無標題正在保護。",
+       "protectedtitlesempty": "目前沒有使用這些參數的受保護標題。",
        "listusers": "使用者清單",
        "listusers-editsonly": "只顯示有編輯的使用者",
        "listusers-creationsort": "依建立日期排序",
        "newpages-username": "使用者名稱:",
        "ancientpages": "最舊頁面",
        "move": "移動",
-       "movethispage": "移å\8b\95æ\9c¬é \81",
+       "movethispage": "移å\8b\95æ­¤é \81é\9d¢",
        "unusedimagestext": "下列為未被任何頁面使用的檔案。\n請注意,其它網站可能直接透過 URL 連結至檔案,所以這裡列出的檔案仍有可能被使用。",
        "unusedcategoriestext": "下列分類沒有被其它頁面或者分類所使用。",
        "notargettitle": "無目標",
        "notargettext": "您尚未指定目標頁面或使用者以進行此項操作。",
-       "nopagetitle": "目標頁面",
+       "nopagetitle": "沒有此目標頁面",
        "nopagetext": "您所指定的目標頁面並不存在。",
        "pager-newer-n": "較新 $1 筆",
        "pager-older-n": "較舊 $1 筆",
        "suppress": "監督",
-       "querypage-disabled": "æ­¤ç\89¹æ®\8aé \81é\9d¢å\9fºæ\96¼æ\95\88è\83½ç\9a\84å\8e\9få\9b å·²ç¶\93被停用。",
+       "querypage-disabled": "æ­¤ç\89¹æ®\8aé \81é\9d¢å\9b è\80\83é\87\8fæ\95\88è\83½å\95\8fé¡\8cå·²被停用。",
        "booksources": "圖書資源",
        "booksources-search-legend": "尋找圖書資源",
        "booksources-isbn": "國際標準書號:",
        "booksources-go": "執行",
-       "booksources-text": "以ä¸\8bæ\98¯ä¸\80份é\8a·å\94®æ\96°æ\9b¸æ\88\96äº\8cæ\89\8bæ\9b¸ç\9a\84å\88\97表ï¼\8c並å\8f¯è\83½æ\9c\89{{GENDER:|ä½ |妳|ä½ }}æ­£å°\8bæ\89¾ç\9a\84æ\9b¸ç\9a\84é\80²ä¸\80æ­¥è¨\8aæ\81¯:",
-       "booksources-invalid-isbn": "æ\8f\90ä¾\9bç\9a\84ISBNè\99\9f碼並ä¸\8d正確ï¼\8cè«\8b檢æ\9f¥å\8e\9få§\8bè¤\87製ä¾\86æº\90è\99\9f碼是否有誤。",
-       "specialloguserlabel": "操作者:",
+       "booksources-text": "ä¸\8bå\88\97æ¸\85å\96®å\8c\85å\90«å\85¶ä»\96é\8a·å\94®æ\96°æ\9b¸ç±\8dæ\88\96äº\8cæ\89\8bæ\9b¸ç±\8dç\9a\84網ç«\99é\80£çµ\90ï¼\8cå\8f¯æ\9c\83æ\9c\89ä½ æ\83³å°\8bæ\89¾æ\9b¸ç±\8dç\9a\84é\80²ä¸\80é\83¨è³\87è¨\8a:",
+       "booksources-invalid-isbn": "æ\82¨æ\8f\90ä¾\9bç\9a\84 ISBN ä¸\8d正確ï¼\8cè«\8b檢æ\9f¥è¤\87製ç\9a\84ä¾\86æº\90是否有誤。",
+       "specialloguserlabel": "執行者:",
        "speciallogtitlelabel": "目標 (標題或使用者):",
        "log": "日誌",
        "all-logs-page": "所有公開日誌",
        "allpages": "所有頁面",
        "nextpage": "下一頁 ($1)",
        "prevpage": "上一頁 ($1)",
-       "allpagesfrom": "顯示從此處開始的頁面:",
-       "allpagesto": "顯示從此處結束的頁面:",
+       "allpagesfrom": "顯示頁面開始於:",
+       "allpagesto": "顯示頁面結束於:",
        "allarticles": "所有頁面",
        "allinnamespace": "所有頁面 ($1 命名空間)",
        "allpagessubmit": "執行",
        "allpagesbadtitle": "指定的頁面標題無效、包含內部語言或內部 Wiki 的字首。\n它可能包含一個或多個的不能用於標題的字元。",
        "allpages-bad-ns": "{{SITENAME}} 沒有 \"$1\" 命名空間。",
        "allpages-hide-redirects": "隱藏重新導向頁面",
-       "cachedspecial-viewing-cached-ttl": "你正在瀏覽本頁的緩存版本,至多可能存在$1的延遲。",
-       "cachedspecial-viewing-cached-ts": "您正在閱讀此頁的緩存版本,這可能不是完整的版本。",
-       "cachedspecial-refresh-now": "æ\9f¥ç\9c\8bæ\9c\80æ\96°。",
-       "categories": "頁面分類",
+       "cachedspecial-viewing-cached-ttl": "你正在檢視此頁面的快取版本,最多會有 $1 的延遲。",
+       "cachedspecial-viewing-cached-ts": "你正在檢視此頁面的快取版本,可能不完全與實際相同。",
+       "cachedspecial-refresh-now": "檢è¦\96æ\9c\80æ\96°ç\89\88æ\9c¬。",
+       "categories": "分類",
        "categoriespagetext": "下列為包含頁面或媒體的{{PLURAL:$1|分類}}。\n[[Special:UnusedCategories|未使用的分類]] 不會在此顯示。\n請參考 [[Special:WantedCategories|需要的分類]]。",
-       "categoriesfrom": "顯示由此項起之分類:",
-       "special-categories-sort-count": "數量排列",
-       "special-categories-sort-abc": "字母排列",
+       "categoriesfrom": "顯示分類開始於:",
+       "special-categories-sort-count": "數量排列",
+       "special-categories-sort-abc": "字母排列",
        "deletedcontributions": "已刪除的使用者貢獻",
        "deletedcontributions-title": "已刪除的使用者貢獻",
        "sp-deletedcontributions-contribs": "貢獻",
-       "linksearch": "å¤\96é\83¨é\8f\88æ\8e¥æ\90\9cç´¢",
-       "linksearch-pat": "搜尋網址:",
+       "linksearch": "å¤\96é\83¨é\80£çµ\90æ\90\9cå°\8b",
+       "linksearch-pat": "搜尋關鍵字:",
        "linksearch-ns": "命名空間:",
        "linksearch-ok": "搜尋",
        "linksearch-text": "可使用萬用字元如 \"*.wikipedia.org\"。\n萬用字元必須使用在最上層網域,例如 \"*.org\".<br />\n支援的{{PLURAL:$2|通訊協定|通訊協定}}有:<code>$1</code> (若未指定則預設使用 http:// 通訊協定)。",
-       "linksearch-line": "$1 連自 $2",
+       "linksearch-line": "$1 由 $2 所連結",
        "linksearch-error": "萬用字元僅可在主機名稱的開頭使用。",
        "listusersfrom": "顯示使用者開始自:",
        "listusers-submit": "顯示",
        "listgrouprights-key": "說明:\n* <span class=\"listgrouprights-granted\">已授予的權限</span>\n* <span class=\"listgrouprights-revoked\">已撤銷的權限</span>",
        "listgrouprights-group": "群組",
        "listgrouprights-rights": "權限",
-       "listgrouprights-helppage": "Help:群組權限",
+       "listgrouprights-helppage": "Help:Group rights",
        "listgrouprights-members": "(成員清單)",
-       "listgrouprights-addgroup": "加入的{{PLURAL:$2|一個|多個}}群組: $1",
-       "listgrouprights-removegroup": "移除的{{PLURAL:$2|一個|多個}}群組: $1",
+       "listgrouprights-addgroup": "加入{{PLURAL:$2|群組|群組}}:$1",
+       "listgrouprights-removegroup": "移除{{PLURAL:$2|群組|群組}}:$1",
        "listgrouprights-addgroup-all": "加入所有群組",
        "listgrouprights-removegroup-all": "移除所有群組",
        "listgrouprights-addgroup-self": "在自己的帳號中加入的{{PLURAL:$2|一個|多個}}群組: $1",
        "listgrouprights-namespaceprotection-header": "命名空間限制",
        "listgrouprights-namespaceprotection-namespace": "命名空間",
        "listgrouprights-namespaceprotection-restrictedto": "允許使用者編輯的權限",
-       "trackingcategories": "è·\9f蹤分類",
+       "trackingcategories": "追蹤分類",
        "trackingcategories-summary": "此頁面列出由 MediaWiki 系統自動產生用來追蹤頁面的分類,這些分類的名稱可由命名空間 {{ns:8}} 中的相關系統訊息中修改。",
-       "trackingcategories-msg": "è·\9f蹤分類",
+       "trackingcategories-msg": "追蹤分類",
        "trackingcategories-name": "訊息名稱",
-       "trackingcategories-desc": "å\88\86é¡\9eæ\94¶é\8c\84æº\96å\89\87",
+       "trackingcategories-desc": "å\88\86é¡\9eæ\94¶é\8c\84æ¨\99æº\96",
        "noindex-category-desc": "命名空間允許,且含有魔術字 <code><nowiki>__NOINDEX__</nowiki></code> 未被機器人列入索引的頁面。",
        "index-category-desc": "命名空間允許,且含有魔術字 <code><nowiki>__INDEX__</nowiki></code> 被機器人列入索引的頁面。",
-       "post-expand-template-inclusion-category-desc": "展開顯示所有樣版後,頁面大小超出 <code>$wgMaxArticleSize</code> 限制,因此部份樣版將不會顯示。",
-       "post-expand-template-argument-category-desc": "å\9c¨å±\95é\96\8b模樣ç\89\88å\8f\83æ\95¸ä¹\8bå¾\8c (æ\9c\89äº\9bæ\96¼ä¸\89æ\8b¬è\99\9f中ï¼\8cå¦\82 <code>{{{Foo}}}</code>)ï¼\8cé \81é\9d¢å¤§å°\8fè¶\85é\81\8e<code>$wgMaxArticleSize</code> è¨­å®\9aç\9a\84é\99\90å\88。",
-       "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": "å\88\86é¡\9e被ç¦\81ç\94¨",
+       "post-expand-template-inclusion-category-desc": "展開樣版後大小超過 <code>$wgMaxArticleSize</code> 導致部份樣版未正常展開的頁面。",
+       "post-expand-template-argument-category-desc": "å±\95é\96\8b樣ç\89\88å\8f\83æ\95¸å¾\8c大å°\8fè¶\85é\81\8e <code>$wgMaxArticleSize</code> ç\9a\84é \81é\9d¢ (æ\9c\89äº\9bæ\96¼ä¸\89æ\8b¬è\99\9f中ï¼\8cå¦\82 <code>{{{Foo}}}</code>)。",
+       "expensive-parserfunction-category-desc": "頁面使用太多消耗系統資源的解析器函數 (如 <code>#ifexist</code>)。\n請參考 [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": "å·²å\81\9cç\94¨å\88\86é¡\9e",
        "mailnologin": "沒有傳送位址",
-       "mailnologintext": "您必須先 [[Special:UserLogin|登入]]\n並在 [[Special:Preferences|偏好設定]]\n中設定一個有效的電子郵件址才可以傳送信件給其他使用者。",
-       "emailuser": "寄信給此使用者",
-       "emailuser-title-target": "寄信給此{{GENDER:$1|使用者}}",
-       "emailuser-title-notarget": "寄信給使用者",
+       "mailnologintext": "您必須先 [[Special:UserLogin|登入]]\n並在 [[Special:Preferences|偏好設定]]\n中設定一個有效的電子郵件址才可以傳送信件給其他使用者。",
+       "emailuser": "Email 此使用者",
+       "emailuser-title-target": "Email 給此{{GENDER:$1|使用者}}",
+       "emailuser-title-notarget": "E-mail 給使用者",
        "emailpage": "E-mail 給使用者",
-       "emailpagetext": "您可以使用以下表格傳送電子郵件給這位 {{Gender:$1|使用者}}。\n您在 [[Special:Preferences|偏好設定]] 中所輸入的電子郵件址將會作為郵件的 \"寄件人\",因此該使用者可直接回覆您。",
-       "defemailsubject": "來自使用者 \"$1\" 於 {{SITENAME}} 寄來的電子郵件",
+       "emailpagetext": "您可以使用以下表格傳送電子郵件給這位 {{Gender:$1|使用者}}。\n您在 [[Special:Preferences|偏好設定]] 中所輸入的電子郵件址將會作為郵件的 \"寄件人\",因此該使用者可直接回覆您。",
+       "defemailsubject": "{{SITENAME}} 使用者 \"$1\" 寄來的電子郵件",
        "usermaildisabled": "使用者電子郵件已停用",
-       "usermaildisabledtext": "您不傳送信件到這個 Wiki 上的其他使用者",
+       "usermaildisabledtext": "您不傳送信件到這個 Wiki 上的其他使用者",
        "noemailtitle": "沒有電子郵件位址",
        "noemailtext": "此使用者尚未指定一個有效的電子郵件位址。",
        "nowikiemailtext": "此使用者選擇不接收其他使用者的信件。",
        "emailtarget": "輸入收件人使用者名稱",
        "emailusername": "使用者名稱:",
        "emailusernamesubmit": "送出",
-       "email-legend": "傳送電子郵件給另一位 {{SITENAME}} 使用者",
+       "email-legend": "傳送電子郵件給另一位 {{SITENAME}} 使用者",
        "emailfrom": "寄件人:",
        "emailto": "收件人:",
-       "emailsubject": "主:",
+       "emailsubject": "主:",
        "emailmessage": "訊息:",
        "emailsend": "傳送",
-       "emailccme": "傳送一份副本到我的電子郵件信箱。",
+       "emailccme": "傳送一份訊息副本到我的電子郵件信箱。",
        "emailccsubject": "您寄給 $1 的訊息副本:$2",
-       "emailsent": "電子郵件已送出",
-       "emailsenttext": "您的電子郵件訊息已經送出。",
-       "emailuserfooter": "這封電子郵件是由 $1 透過 {{SITENAME}} 的 \"傳送信件給使用者\" 功能寄給 $2。",
+       "emailsent": "已寄出電子郵件",
+       "emailsenttext": "已寄出您的電子郵件訊息。",
+       "emailuserfooter": "這封電子郵件是由 $1 透過 {{SITENAME}} 的 \"Email 給此使用者\" 功能寄給 $2。",
        "usermessage-summary": "留給系統訊息。",
        "usermessage-editor": "系統訊息",
        "watchlist": "監視清單",
        "mywatchlist": "監視清單",
        "watchlistfor2": "$1 的監視清單 $2",
        "nowatchlist": "您的監視清單沒有任何項目。",
-       "watchlistanontext": "請 $1 以檢視或編輯您的監視清單。",
+       "watchlistanontext": "請先登入以檢視或修改在監控表的項目",
        "watchnologin": "尚未登入",
        "addwatch": "新增至監視清單",
        "addedwatchtext": "已於[[Special:Watchlist|您的監視清單]]新增頁面 \"[[:$1]]\"。\n未來對此頁面及其關聯的對話頁面的變更將會在此清單中列出。",
        "watchlist-details": "您的監視清單上共有 $1 個頁面 (不包含對話頁面)。",
        "wlheader-enotif": "已開啟電子郵件通知功能。",
        "wlheader-showupdated": "在您最後一次檢視過後修改的頁面會以 <strong>粗體</strong> 顯示。",
-       "wlnote2": "以下為截至 $2 $3 最近 <strong>$1</strong> 小時的變更。",
+       "wlnote": "以下為自 $3 $4 之後的 <strong>$2</strong> 小時內所做的 <strong>$1</strong> 次變更。",
        "wlshowlast": "顯示最近 $1 小時,$2 天,$3 的修改",
        "watchlist-options": "監視清單選項",
        "watching": "正在監視...",
        "exbeforeblank": "被清空前的內容為:\"$1\"",
        "delete-confirm": "刪除 \"$1\"",
        "delete-legend": "刪除",
-       "historywarning": "<strong>警告:</strong>您正要刪除的頁面內含有約 $1 次{{PLURAL:$1|的修訂}}歷史:",
+       "historywarning": "<strong>警告:</strong>您正要刪除的頁面內含 $1 次{{PLURAL:$1|的修訂}}歷史:",
        "confirmdeletetext": "您正要刪除一個頁面或圖片以及其所有歷史。\n請確定您了解要進行此項操作所造成的後果,同時確認您的行為符合[[{{MediaWiki:Policy-url}}]] 規範。",
        "actioncomplete": "操作完成",
        "actionfailed": "操作失敗",
        "deletedtext": "已刪除 \"$1\"。\n請參考 $2 檢視最近的刪除記錄。",
        "dellogpage": "刪除日誌",
-       "dellogpagetext": "以下為最近刪除記錄的列表。",
+       "dellogpagetext": "以下為最近刪除記錄的清單。",
        "deletionlog": "刪除日誌",
        "reverted": "還原到較早的版本",
        "deletecomment": "原因:",
        "deleteotherreason": "其它/額外的原因:",
-       "deletereasonotherlist": "其它理由",
+       "deletereasonotherlist": "其它原因",
        "deletereason-dropdown": "* 常見的刪除原因\n** 濫發廣告訊息\n** 破壞\n** 侵犯版權\n** 作者請求\n** 損壞的重新導向連結",
-       "delete-edit-reasonlist": "編輯刪除理由",
+       "delete-edit-reasonlist": "編輯刪除原因",
        "delete-toobig": "這個頁面有一個十分大量的編輯歷史,超過$1次修訂。刪除此類頁面的動作已經被限制,以防止在{{SITENAME}}上的意外擾亂。",
        "delete-warning-toobig": "這個頁面有一個十分大量的編輯歷史,超過$1次修訂。刪除它可能會擾亂{{SITENAME}}的資料庫操作;在繼續此動作前請小心。",
+       "deleteprotected": "此頁面已受保護,您無法刪除此頁面。",
        "deleting-backlinks-warning": "<strong>警告:</strong>您正要刪除的頁面有[[Special:WhatLinksHere/{{FULLPAGENAME}}|其他頁面]]連結或引用。",
        "rollback": "還原編輯",
        "rollback_short": "還原",
        "rollbacklink": "還原",
        "rollbacklinkcount": "還原 $1 次編輯",
-       "rollbacklinkcount-morethan": "回退多過 $1 次{{PLURAL:$1|編輯}}",
+       "rollbacklinkcount-morethan": "還原超過 $1 次{{PLURAL:$1|編輯}}",
        "rollbackfailed": "還原失敗",
        "cantrollback": "無法還原編輯;\n此頁面的最後貢獻者是唯一的作者。",
        "alreadyrolled": "無法還原由 [[User:$2|$2]] ([[User talk:$2|對話]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]] 所作的最後一次編輯 [[:$1]],已有其他人編輯或還原了該頁面。\n\n最後一次編輯該頁面的使用者是 [[User:$3|$3]] ([[User talk:$3|對話]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]])。",
-       "editcomment": "編輯摘要\"''$1''\"。",
+       "editcomment": "編輯摘要為:\"''$1''\"。",
        "revertpage": "已還原 [[Special:Contributions/$2|$2]] ([[User talk:$2|對話]]) 的編輯為最後由 [[User:$1|$1]] 所修訂的版本",
        "revertpage-nouser": "已還隱藏使用者的編輯為最後 {{GENDER:$1|[[User:$1|$1]]}} 修訂的版本",
        "rollback-success": "已還原 $1 做的編輯;\n更變回最後由 $2 修訂的版本。",
-       "sessionfailure-title": "登入資訊失敗",
-       "sessionfailure": "似乎您的登會話有問題;\n為了防止會話劫持,這個操作已經被取消。\n請返回先前的頁面,重新載入該頁面,然後重試。",
+       "sessionfailure-title": "連線階段失敗",
+       "sessionfailure": "似乎您的登會話有問題;\n為了防止會話劫持,這個操作已經被取消。\n請返回先前的頁面,重新載入該頁面,然後重試。",
        "protectlogpage": "保護日誌",
-       "protectlogtext": "以下為變更頁面保護的列表。\n請參考 [[Special:ProtectedPages|受保護頁面列表]] 檢視目前受保護頁面。",
+       "protectlogtext": "以下為變更頁面保護的清單。\n請參考 [[Special:ProtectedPages|受保護頁面清單]] 檢視目前受保護頁面。",
        "protectedarticle": "已保護 \"[[$1]]\"",
        "modifiedarticleprotection": "已變更 \"[[$1]]\" 的保護層級",
        "unprotectedarticle": "已解除 \"[[$1]]\" 的保護",
        "protect-expiry-indefinite": "無限期",
        "protect-cascade": "保護本頁中包含的頁面 (連鎖保護)",
        "protect-cantedit": "您沒有編輯權限,無法更改此頁面的保護層級。",
-       "protect-othertime": "其它時間:",
+       "protect-othertime": "其它時間",
        "protect-othertime-op": "其它時間",
        "protect-existing-expiry": "已設定期限:$2 $3",
        "protect-otherreason": "其它/額外的原因:",
-       "protect-otherreason-op": "其它理由",
+       "protect-otherreason-op": "其它原因",
        "protect-dropdown": "*常見的保護原因\n** 過度的破壞\n** 過多垃圾訊息\n** 反生產性的編輯戰\n** 高流量頁面",
        "protect-edit-reasonlist": "編輯保護原因",
-       "protect-expiry-options": "1 小時:1 hour,1 天:1 day,1 週:1 week,2 週:2 weeks,1 個月:1 month,3 個月:3 months,6 個月:6 months,1 年:1 year,限期:infinite",
+       "protect-expiry-options": "1 小時:1 hour,1 天:1 day,1 週:1 week,2 週:2 weeks,1 個月:1 month,3 個月:3 months,6 個月:6 months,1 年:1 year,限期:infinite",
        "restriction-type": "權限:",
        "restriction-level": "限制層級:",
        "minimum-size": "大小下限",
        "restriction-move": "移動",
        "restriction-create": "建立",
        "restriction-upload": "上傳",
-       "restriction-level-sysop": "全保護",
-       "restriction-level-autoconfirmed": "半保護",
-       "restriction-level-all": "任何級別",
+       "restriction-level-sysop": "å\8f\97å\85¨ä¿\9dè­·",
+       "restriction-level-autoconfirmed": "å\8f\97å\8d\8aä¿\9dè­·",
+       "restriction-level-all": "任何層級",
        "undelete": "檢視已刪除的頁面",
        "undeletepage": "檢視與還原已刪除的頁面",
-       "undeletepagetitle": "'''以下包含[[:$1]]的已刪除之修訂版本'''。",
-       "viewdeletedpage": "檢視已刪除頁面",
-       "undeletepagetext": "以ä¸\8bç\9a\84$1å\80\8bé \81é\9d¢å·²ç¶\93被å\88ªé\99¤ï¼\8cä½\86ä¾\9dç\84¶å\9c¨æª\94æ¡\88中並å\8f¯ä»¥è¢«æ\81¢å¾©ã\80\82\næª\94æ¡\88庫å\8f¯è\83½è¢«定時清理。",
+       "undeletepagetitle": "<strong>下列為 [[:$1]] 已刪除的修訂版本</strong>。",
+       "viewdeletedpage": "檢視已刪除頁面",
+       "undeletepagetext": "ä¸\8bå\88\97 {{PLURAL:$1|1 å\80\8bé \81é\9d¢å·²å\88ªé\99¤|$1 å\80\8bé \81é\9d¢å·²å\88ªé\99¤}}ä½\86å°\9aå\9c¨å°\81å­\98ï¼\8cä»\8då\8f¯é\82\84å\8e\9fã\80\82\nå°\81å­\98ç\9a\84æª\94æ¡\88å\8f¯è\83½æ\9c\83定時清理。",
        "undelete-fieldset-title": "還原修訂",
        "undeleteextrahelp": "若要還原所有的頁面歷史,請取消勾選所有核選方塊並點選 <strong><em>{{int:undeletebtn}}</em></strong>。\n若要還原指定的頁面歷史,請勾選要還原的修訂核選方塊並點選 <strong><em>{{int:undeletebtn}}</em></strong>。",
        "undeleterevisions": "已封存 $1 個修訂",
        "undeletedpage": "<strong>已還原 $1</strong>\n\n請參考 [[Special:Log/delete|刪除日誌]] 以查詢最近刪除及還原的記錄。",
        "undelete-header": "請參考 [[Special:Log/delete|刪除日誌]] 查詢最近刪除的頁面。",
        "undelete-search-title": "搜尋已刪除頁面",
-       "undelete-search-box": "搜尋已刪除頁面",
+       "undelete-search-box": "搜尋已刪除頁面",
        "undelete-search-prefix": "顯示頁面開始自:",
        "undelete-search-submit": "搜尋",
        "undelete-no-results": "刪除記錄裡沒有符合的頁面。",
        "mycontris": "我的貢獻",
        "contribsub2": "{{GENDER:$3|$1}} 的貢獻 ($2)",
        "contributions-userdoesnotexist": "使用者帳號 \"$1\" 尚未註冊。",
-       "nocontribs": "沒有找到符合特徵的更改。",
+       "nocontribs": "沒有找到符合條件的變更。",
        "uctop": "(目前)",
        "month": "截止月份:",
        "year": "截止年份:",
        "sp-contributions-userrights": "使用者權限管理",
        "sp-contributions-blocked-notice": "此使用者目前已被封鎖。\n以下為最近的封鎖紀錄以供參考:",
        "sp-contributions-blocked-notice-anon": "此 IP 位址目前已被封鎖。\n以下為最近的封鎖紀錄以供參考:",
-       "sp-contributions-search": "搜尋貢獻記錄",
+       "sp-contributions-search": "搜尋貢獻",
        "sp-contributions-username": "IP 位址或使用者名稱:",
-       "sp-contributions-toponly": "å\8fªé¡¯ç¤ºæ\9c\80æ\96°ä¿®è¨\82ç\89\88æ\9c¬ç\9a\84編輯",
-       "sp-contributions-newonly": "å\83\85顯示建ç«\8bé \81é\9d¢ä¹\8b編輯",
+       "sp-contributions-toponly": "只顯示最新修訂的編輯",
+       "sp-contributions-newonly": "å\8fªé¡¯ç¤ºå»ºç«\8bé \81é\9d¢ç\9a\84編輯",
        "sp-contributions-submit": "搜尋",
        "whatlinkshere": "連入頁面",
        "whatlinkshere-title": "連結到 \"$1\" 的頁面",
        "whatlinkshere-page": "頁面:",
-       "linkshere": "以下頁面連結到[[:$1]]:",
-       "nolinkshere": "沒有頁面連結到[[:$1]]。",
+       "linkshere": "以下頁面連結至 <strong>[[:$1]]</strong>:",
+       "nolinkshere": "沒有頁面連結至 <strong>[[:$1]]</strong>。",
        "nolinkshere-ns": "已選擇的命名空間中沒有頁面連結到 [[:$1]]。",
        "isredirect": "重新導向頁面",
        "istemplate": "引用",
        "isimage": "檔案連結",
        "whatlinkshere-prev": "前 $1 筆",
        "whatlinkshere-next": "後 $1 筆",
-       "whatlinkshere-links": "← 連",
+       "whatlinkshere-links": "← 連",
        "whatlinkshere-hideredirs": "$1 重新導向頁面",
        "whatlinkshere-hidetrans": "$1 引用",
        "whatlinkshere-hidelinks": "$1 連結",
        "whatlinkshere-hideimages": "$1 檔案連結",
        "whatlinkshere-filters": "搜尋",
-       "autoblockid": "自動查封 #$1",
+       "autoblockid": "自動封鎖 #$1",
        "block": "封鎖使用者",
        "unblock": "解除封鎖使用者",
-       "blockip": "封鎖使用者",
+       "blockip": "封鎖{{GENDER:$1|使用者}}",
        "blockip-legend": "封鎖使用者",
-       "blockiptext": "填寫以下單據可封鎖特定 IP 位或使用者名稱的存取權限。\n這個動作應用來避免破壞行為,可根據 [[{{MediaWiki:Policy-url}}|管理政策]]。\n請在下方填寫一個具體的原因 (例如:引述一段破壞頁面的事實)。",
+       "blockiptext": "填寫以下單據可封鎖特定 IP 位或使用者名稱的存取權限。\n這個動作應用來避免破壞行為,可根據 [[{{MediaWiki:Policy-url}}|管理政策]]。\n請在下方填寫一個具體的原因 (例如:引述一段破壞頁面的事實)。",
        "ipaddressorusername": "IP 位址或使用者名稱:",
        "ipbexpiry": "期限:",
        "ipbreason": "原因:",
        "ipbreason-dropdown": "*常見的封鎖原因\n** 填寫不實資訊\n** 刪除頁面內容\n** 散佈外部廣告連結\n** 在頁面填寫無意義文字\n** 無禮的行為、攻擊/騷擾別人\n** 濫用多個帳號\n** 使用不受歡迎的使用者名稱",
-       "ipb-hardblock": "避免使用此 IP 位址登入的使用者編輯",
+       "ipb-hardblock": "禁止使用此 IP 位址登入的使用者編輯",
        "ipbcreateaccount": "禁止建立帳號",
        "ipbemailban": "禁止使用者傳送電子郵件",
        "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",
+       "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",
        "ipbhidename": "在編輯及清單中隱藏使用者名稱",
-       "ipbwatchuser": "監視這位使用者的使用者頁面及其對話頁面",
+       "ipbwatchuser": "監視這位使用者的使用者頁面及其對話頁面",
        "ipb-disableusertalk": "避免在封鎖此使用者的期間編輯自己的對話頁面",
        "ipb-change-block": "使用現有設定重新封鎖使用者",
        "ipb-confirm": "確認封鎖",
        "ipb-unblock-addr": "解除封鎖 $1",
        "ipb-unblock": "解除封鎖使用者名稱或 IP 位址",
        "ipb-blocklist": "檢視目前的封鎖",
-       "ipb-blocklist-contribs": "$1的貢獻",
+       "ipb-blocklist-contribs": "{{GENDER:$1|$1}} 的貢獻",
        "unblockip": "解除封鎖使用者",
        "unblockiptext": "填寫以下單據以取消先前封鎖的 IP 位址或使用者名稱。",
        "ipusubmit": "移除這個封鎖",
        "unblocked": "[[User:$1|$1]] 的封鎖已經解除。",
-       "unblocked-range": "$1已被解封",
+       "unblocked-range": "已解除封鎖 $1。",
        "unblocked-id": "已經移除 $1 的封鎖。",
        "blocklist": "已封鎖的使用者",
        "ipblocklist": "已封鎖的使用者",
        "blocklist-nousertalk": "無法編輯自己的對話頁面",
        "ipblocklist-empty": "封鎖清單無任何資訊。",
        "ipblocklist-no-results": "指定的 IP 位址或使用者名稱尚未被封鎖。",
-       "blocklink": "查封",
+       "blocklink": "封鎖",
        "unblocklink": "解除封鎖",
        "change-blocklink": "變更封鎖",
        "contribslink": "貢獻",
        "emaillink": "傳送電子郵件",
        "autoblocker": "您的 IP 位址因最近被 [[User:$1|$1]] 使用過而被自動封鎖。\n封鎖 $1 的原因為 \"$2\"",
-       "blocklogpage": "查封日誌",
+       "blocklogpage": "封鎖日誌",
        "blocklog-showlog": "此使用者先前被封鎖過。\n以下為封鎖紀錄以供參考:",
        "blocklog-showsuppresslog": "此使用者先前被封鎖並且隱藏過。\n以下為禁止顯示紀錄以供參考:",
        "blocklogentry": "已封鎖 [[$1]] 的期限至 $2 $3",
        "reblock-logentry": "更改 [[$1]] 的封鎖期限至 $2 $3",
-       "blocklogtext": "æ­¤ç\82ºä½¿ç\94¨è\80\85ç\9a\84å°\81é\8e\96å\8f\8aå\8f\96æ¶\88å°\81é\8e\96è¨\98é\8c\84ã\80\82\nä¸\8då\8c\85è\87ªå\8b\95å°\81é\8e\96ç\9a\84 IP ä½\8då\9d\80ã\80\82\nè«\8bå\8f\83è\80\83 [[Special:BlockList|å°\81é\8e\96æ¸\85å\96®]] ä»¥æ\9f¥ç\9c\8b目前的封鎖。",
-       "unblocklogentry": "已解 $1",
+       "blocklogtext": "æ­¤ç\82ºä½¿ç\94¨è\80\85ç\9a\84å°\81é\8e\96å\8f\8aå\8f\96æ¶\88å°\81é\8e\96è¨\98é\8c\84ã\80\82\nä¸\8då\8c\85è\87ªå\8b\95å°\81é\8e\96ç\9a\84 IP ä½\8då\9d\80ã\80\82\nè«\8bå\8f\83è\80\83 [[Special:BlockList|å°\81é\8e\96æ¸\85å\96®]] ä»¥æª¢è¦\96目前的封鎖。",
+       "unblocklogentry": "已解除封鎖 $1",
        "block-log-flags-anononly": "僅限匿名使用者",
        "block-log-flags-nocreate": "停用帳號建立",
        "block-log-flags-noautoblock": "停用自動封鎖",
        "block-log-flags-noemail": "停用電子郵件",
        "block-log-flags-nousertalk": "無法編輯自己的對話頁面",
-       "block-log-flags-angry-autoblock": "加強自動封鎖已啟用",
+       "block-log-flags-angry-autoblock": "加強自動封鎖已開啟",
        "block-log-flags-hiddenname": "隱藏使用者名稱",
        "range_block_disabled": "管理員可建立範圍封鎖的權限以被關閉。",
-       "ipb_expiry_invalid": "無效的終止時間。",
+       "ipb_expiry_invalid": "無效的期限。",
        "ipb_expiry_temp": "隱藏使用者名稱的封鎖不可設定期限。",
        "ipb_hide_invalid": "無法禁止顯示此帳號;它擁有超過 $1 次的編輯。",
        "ipb_already_blocked": "已經封鎖 \"$1\"。",
-       "ipb-needreblock": "$1已經被封鎖。您是否想更改這個設定?",
+       "ipb-needreblock": "$1 已經被封鎖。您是否想更改設定?",
        "ipb-otherblocks-header": "其他{{PLURAL:$1|封鎖}}",
        "unblock-hideuser": "由於此使用者名稱已被設為隱藏,您無法解除封鎖這個使用者。",
        "ipb_cant_unblock": "錯誤:查無封鎖 ID $1,可能已被解除封鎖。",
        "ip_range_invalid": "無效的 IP 範圍。",
        "ip_range_toolarge": "不允許封鎖範圍大於 /$1。",
        "proxyblocker": "代理封鎖器",
-       "proxyblockreason": "因您的 IP 位址是開放代理伺服器,已被封鎖。\n請聯繫您的網服務供應商或您所在組織的技術支援,告知他們此嚴重的安全性問題。",
-       "sorbsreason": "您的IP位址在{{SITENAME}}中被 DNSBL列為屬於開放代理服務器。",
+       "proxyblockreason": "因您的 IP 位址是開放代理伺服器,已被封鎖。\n請聯繫您的網服務供應商或您所在組織的技術支援,告知他們此嚴重的安全性問題。",
+       "sorbsreason": "您的 IP 位址在 {{SITENAME}} 使用的 DNSBL 列為開放代理伺服器。",
        "sorbs_create_account_reason": "您連線到 {{SITENAME}} 的 IP 位址被 DNSBL 列為開放代理伺服器。\n您不能建立帳號。",
        "xffblockreason": "您的 IP 位址使用 X-Forwarded-For 標頭,您或您使用的代理伺服器已被封鎖。\n封鎖的原因為:$1",
        "cant-see-hidden-user": "您欲封鎖的使用者已經被封鎖並且隱藏。\n您沒有隱藏使用者的權限,您無法檢視或編輯該使用者的封鎖狀態。",
        "movenologintext": "您必須是已註冊的使用者並且 [[Special:UserLogin|登入]] 才可移動頁面。",
        "movenotallowed": "您沒有權限移動頁面。",
        "movenotallowedfile": "您沒有權限移動檔案。",
-       "cant-move-user-page": "您沒有權限移動使用者頁面 (除使用者子頁面外)。",
+       "cant-move-user-page": "您沒有權限移動使用者頁面 (子頁面除外)。",
        "cant-move-to-user-page": "您沒有權限移動頁面至使用者頁面 (除使用者子頁面外)。",
        "cant-move-category-page": "您沒有權限移動分類頁面。",
        "cant-move-to-category-page": "您沒有權限移動頁面至分類頁面。",
        "newtitle": "新標題:",
        "move-watch": "監視來源以及目標頁面",
        "movepagebtn": "移動頁面",
-       "pagemovedsub": "移動成功",
+       "pagemovedsub": "已成功移動",
        "movepage-moved": "<strong>已移動 \"$1\" 至 \"$2\"</strong>",
        "movepage-moved-redirect": "已建立重新導向頁面。",
        "movepage-moved-noredirect": "已禁止建立重新導向頁面。",
        "thumbnail_error_remote": "來自 $1 錯誤訊息:\n$2",
        "djvu_page_error": "DjVu 頁面超出範圍",
        "djvu_no_xml": "無法在 DjVu 檔案中擷取 XML",
-       "thumbnail-temp-create": "無法建立臨時縮圖檔案",
+       "thumbnail-temp-create": "無法建立暫存縮圖檔案",
        "thumbnail-dest-create": "無法儲存縮圖至目標",
        "thumbnail_invalid_params": "無效的縮圖參數",
        "thumbnail_dest_directory": "無法建立目標目錄",
        "import": "匯入頁面",
        "importinterwiki": "Transwiki 匯入",
        "import-interwiki-text": "請選擇一個 Wiki 與頁面標題以進行匯入。\n會同時記錄修訂日期和編輯者的名稱。\n所有的 Transwiki 匯入操作會被記錄在 [[Special:Log/import|匯入日誌]]。",
-       "import-interwiki-source": "來源 Wiki/頁面:",
+       "import-interwiki-sourcewiki": "來源 Wiki:",
+       "import-interwiki-sourcepage": "來源頁面:",
        "import-interwiki-history": "複製此頁的所有歷史修訂",
        "import-interwiki-templates": "包含所有樣版",
        "import-interwiki-submit": "匯入",
        "importtext": "請使用 [[Special:Export|匯出工具]] 從來源 Wiki 匯出檔案,\n儲存至您的電腦後再上傳到這裡。",
        "importstart": "正在匯入頁面...",
        "import-revision-count": "$1 個修訂",
-       "importnopages": "沒有匯入的頁面。",
+       "importnopages": "æ²\92æ\9c\89å\8f¯å\8c¯å\85¥ç\9a\84é \81é\9d¢ã\80\82",
        "imported-log-entries": "已匯入 $1 筆日誌項目。",
        "importfailed": "匯入失敗:<nowiki>$1</nowiki>",
        "importunknownsource": "不明的來源匯入類型",
        "importcantopen": "無法開啟匯入檔案",
        "importbadinterwiki": "無效的 Interwiki 連結",
-       "importsuccess": "å\8c¯å\85¥å®\8cæ\88\90!",
+       "importsuccess": "å·²å®\8cæ\88\90å\8c¯å\85¥!",
        "importnosources": "未定義任何 Transwiki 匯入來源且已關閉使用歷史記錄上傳功能。",
        "importnofile": "未上傳匯入檔案。",
-       "importuploaderrorsize": "上匯入檔案失敗。\n檔案大小超過允許上傳大小。",
-       "importuploaderrorpartial": "上匯入檔案失敗。\n僅上傳部份檔案。",
-       "importuploaderrortemp": "上載匯入檔案失敗。\n遺失臨時資料夾。",
-       "import-parse-failure": "XML 匯入析失敗",
+       "importuploaderrorsize": "上匯入檔案失敗。\n檔案大小超過允許上傳大小。",
+       "importuploaderrorpartial": "上匯入檔案失敗。\n僅上傳部份檔案。",
+       "importuploaderrortemp": "上傳匯入檔案失敗。\n遺失暫存資料夾。",
+       "import-parse-failure": "XML 匯入析失敗",
        "import-noarticle": "沒有任何可匯入的頁面!",
        "import-nonewrevisions": "未匯入任何修訂 (修訂已存在,或因錯誤跳過)。",
        "xml-error-string": "$1 於行 $2,欄 $3 ($4 位元組):$5",
        "import-error-create": "您沒有權限建立頁面 \"$1\",無法匯入。",
        "import-error-interwiki": "頁面 \"$1\" 的名稱已保留作為外部連結 (Interwiki) 使用,無法匯入。",
        "import-error-special": "頁面 \"$1\" 屬於不允許頁面的特殊命名空間,無法匯入。",
-       "import-error-invalid": "頁面 \"$1\" 名稱無效,無法匯入。",
+       "import-error-invalid": "é \81é\9d¢ \"$1\" å\8c¯å\85¥æ­¤ Wiki ç\9a\84å\90\8d稱ç\84¡æ\95\88ï¼\8cç\84¡æ³\95å\8c¯å\85¥ã\80\82",
        "import-error-unserialize": "頁面 \"$1\" 的修訂 $2 無法反序列反。 此修訂使用 $3 內容模型以 $4 的方式序列化。",
        "import-error-bad-location": "此 Wiki 的頁面 \"$1\" 不支援使用內容模型 $3,修訂 $2 無法儲存至該頁面 。",
        "import-options-wrong": "{{PLURAL:$2|選項}}錯誤:<nowiki>$1</nowiki>",
        "importlogpage": "匯入日誌",
        "importlogpagetext": "管理性匯入其他 Wiki 的頁面及編輯歷史記錄。",
        "import-logentry-upload": "使用檔案上傳匯入 [[$1]]",
-       "import-logentry-upload-detail": "$1 個修訂",
+       "import-logentry-upload-detail": "已匯入 $1 筆{{PLURAL:$1|修訂}}",
        "import-logentry-interwiki": "Transwiki 頁面 $1",
-       "import-logentry-interwiki-detail": "來自 $2 的 $1 個修訂",
+       "import-logentry-interwiki-detail": "已從 $2 匯入 $1 筆{{PLURAL:$1|修訂}}",
        "javascripttest": "JavaScript 測試",
        "javascripttest-title": "執行 $1 測試。",
        "javascripttest-pagetext-noframework": "此頁面保留用來作為 JavaScript 測試使用。",
        "tooltip-pt-userpage": "您的使用者頁面",
        "tooltip-pt-anonuserpage": "您編輯使用的 IP 位址所對應的使用者頁面",
        "tooltip-pt-mytalk": "您的對話頁面",
-       "tooltip-pt-anontalk": "對於來自此IP地址編輯的對話",
+       "tooltip-pt-anontalk": "對於來自此 IP 位址編輯的對話",
        "tooltip-pt-preferences": "您的偏好設定",
        "tooltip-pt-watchlist": "您監視變更頁面清單",
        "tooltip-pt-mycontris": "您的貢獻清單",
        "tooltip-t-contributions": "此使用者的貢獻清單",
        "tooltip-t-emailuser": "傳送電子郵件給這個使用者",
        "tooltip-t-upload": "上傳檔案",
-       "tooltip-t-specialpages": "全部特殊頁面的列表",
+       "tooltip-t-specialpages": "全部特殊頁面的清單",
        "tooltip-t-print": "此頁面的可列印版本",
-       "tooltip-t-permalink": "此頁面修訂的固定連結",
+       "tooltip-t-permalink": "此頁面修訂的靜態連結",
        "tooltip-ca-nstab-main": "檢視頁面內容",
        "tooltip-ca-nstab-user": "檢視使用者頁面",
        "tooltip-ca-nstab-media": "檢視媒體頁面",
        "tooltip-ca-nstab-special": "此頁面為特殊頁面,無法編輯",
        "tooltip-ca-nstab-project": "檢視專案頁面",
        "tooltip-ca-nstab-image": "檢視檔案頁面",
-       "tooltip-ca-nstab-mediawiki": "檢è¦\96系統è³\87è¨\8a",
+       "tooltip-ca-nstab-mediawiki": "檢è¦\96系統è¨\8aæ\81¯",
        "tooltip-ca-nstab-template": "檢視樣版",
        "tooltip-ca-nstab-help": "檢視說明頁面",
        "tooltip-ca-nstab-category": "檢視分類頁面",
        "noscript.css": "/* 此 CSS 會影響沒有啓用 JavaScript 的使用者 */",
        "group-autoconfirmed.css": "/* 此 CSS 會影響自動確認的使用者 */",
        "group-bot.css": "/* 此 CSS 會影響機器人 */",
-       "group-sysop.css": "/*  CSS 會影響管理員 */",
+       "group-sysop.css": "/* 這裡的 CSS 會影響管理員 */",
        "group-bureaucrat.css": "/* 此 CSS 會影響行政員 */",
        "common.js": "/* 此 JavaScript 會用於使用者載入的每一個頁面。 */",
+       "group-sysop.js": "/* 這裡的 JavaScript 會影響管理員 */",
        "anonymous": "{{SITENAME}} 的匿名{{PLURAL:$1|使用者}}",
        "siteuser": "{{SITENAME}} 使用者 $1",
        "anonuser": "{{SITENAME}} 匿名使用者 $1",
-       "lastmodifiedatby": "此頁由 $3 於 $1 $2 的最後更改。",
+       "lastmodifiedatby": "此頁面由 $3 於 $1 $2 做最後修改。",
        "othercontribs": "此頁面由 $1 所貢獻。",
        "others": "其他",
        "siteusers": "{{SITENAME}} {{PLURAL:$2|使用者}} $1",
        "pageinfo-header-restrictions": "頁面保護",
        "pageinfo-header-properties": "頁面屬性",
        "pageinfo-display-title": "顯示標題",
-       "pageinfo-default-sort": "預設排序:",
+       "pageinfo-default-sort": "預設排序方式:",
        "pageinfo-length": "頁面長度 (位元組)",
-       "pageinfo-article-id": "頁面編號",
+       "pageinfo-article-id": "頁面 ID",
        "pageinfo-language": "頁面內容語言",
        "pageinfo-content-model": "頁面內容模型",
        "pageinfo-robot-policy": "由機器人建立索引",
        "pageinfo-watchers": "頁面監視者數",
        "pageinfo-few-watchers": "少於 $1 名監視者",
        "pageinfo-redirects-name": "指向此頁面的重新導向頁面數量",
-       "pageinfo-subpages-name": "此頁面的子頁面",
+       "pageinfo-subpages-name": "此頁面的子頁面",
        "pageinfo-subpages-value": "$1 ($2 個重新導向頁面; $3 個非重新導向頁面)",
-       "pageinfo-firstuser": "頁面建立者",
-       "pageinfo-firsttime": "é \81é\9d¢å\89µå»º日期",
+       "pageinfo-firstuser": "頁面建立者",
+       "pageinfo-firsttime": "é \81é\9d¢å»ºç«\8b日期",
        "pageinfo-lastuser": "最近編輯者",
-       "pageinfo-lasttime": "最編輯日期",
+       "pageinfo-lasttime": "最編輯日期",
        "pageinfo-edits": "編輯總次數",
        "pageinfo-authors": "作者總數",
        "pageinfo-recent-edits": "最近編輯次數 (過去$1內)",
-       "pageinfo-recent-authors": "最近作者數",
+       "pageinfo-recent-authors": "最近作者數",
        "pageinfo-magic-words": "魔術{{PLURAL:$1|字}} ($1)",
        "pageinfo-hidden-categories": "隱藏{{PLURAL:$1|分類}} ($1)",
-       "pageinfo-templates": "引用樣版 ($1)",
+       "pageinfo-templates": "引用樣版 ($1)",
        "pageinfo-transclusions": "頁面被引用於 ($1)",
        "pageinfo-toolboxlink": "頁面資訊",
        "pageinfo-redirectsto": "重新導向至",
        "pageinfo-category-info": "分類資訊",
        "pageinfo-category-pages": "頁面數量",
        "pageinfo-category-subcats": "子分類數量",
-       "pageinfo-category-files": "編輯數量",
+       "pageinfo-category-files": "檔案數量",
        "markaspatrolleddiff": "標記為已巡查",
        "markaspatrolledtext": "標記此頁面為已巡查",
        "markedaspatrolled": "己標記為已巡查",
        "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-nohires": "無更高解度可提供。",
+       "file-nohires": "無更高解度可提供。",
        "svg-long-desc": "SVG 檔案,表面大小:$1 × $2 像素,檔案大小:$3",
        "svg-long-desc-animated": "SVG 動畫檔案,表面大小:$1 × $2 像素,檔案大小:$3",
        "svg-long-error": "無效的 SVG 檔案:$1",
        "exif-contrast": "對比度",
        "exif-saturation": "飽和度",
        "exif-sharpness": "銳利度",
-       "exif-devicesettingdescription": "設å\82\99設定描述",
+       "exif-devicesettingdescription": "è£\9dç½®設定描述",
        "exif-subjectdistancerange": "主體距離範圍",
        "exif-imageuniqueid": "唯一影像識別碼",
        "exif-gpsversionid": "GPS 標籤版本",
        "exif-gpsaltituderef": "海拔參考值",
        "exif-gpsaltitude": "海拔",
        "exif-gpstimestamp": "GPS 時間 (原子鐘)",
-       "exif-gpssatellites": "測量使用的衛星",
+       "exif-gpssatellites": "測量用的衛星",
        "exif-gpsstatus": "接收器狀態",
        "exif-gpsmeasuremode": "測量模式",
        "exif-gpsdop": "測量精度",
        "exif-pngfilecomment": "PNG 檔案備註",
        "exif-disclaimer": "免責聲明",
        "exif-contentwarning": "內容警告",
-       "exif-giffilecomment": "GIF註釋",
+       "exif-giffilecomment": "GIF 檔案備註",
        "exif-intellectualgenre": "項目類型",
        "exif-subjectnewscode": "主題代碼",
-       "exif-scenecode": "IPTC現場代碼",
+       "exif-scenecode": "IPTC 現場代碼",
        "exif-event": "事件描述",
        "exif-organisationinimage": "組織描述",
        "exif-personinimage": "所描述的人",
-       "exif-originalimageheight": "被è£\81å\89ªå\89\8d高度",
-       "exif-originalimagewidth": "被è£\81å\89ªå\89\8d寬度",
+       "exif-originalimageheight": "è£\81å\88\87å\89\8dç\9a\84高度",
+       "exif-originalimagewidth": "è£\81å\88\87å\89\8dç\9a\84寬度",
        "exif-compression-1": "未壓縮",
-       "exif-compression-2": "CCITT第3組一維修改霍夫曼遊程編碼",
-       "exif-compression-3": "CCITT第3組傳真編碼",
-       "exif-compression-4": "CCITT第4組傳真編碼",
-       "exif-compression-6": "JPEG(舊)",
+       "exif-compression-2": "CCITT 第 3 組一維修改霍夫曼變動長度編碼",
+       "exif-compression-3": "CCITT 第 3 組傳真編碼",
+       "exif-compression-4": "CCITT 第 4 組傳真編碼",
+       "exif-compression-6": "JPEG (舊)",
        "exif-copyrighted-true": "受版權保護",
-       "exif-copyrighted-false": "版權所屬者不明",
-       "exif-unknowndate": "æ\9cªç\9f¥ç\9a\84æ\97¥æ\9c\9f",
+       "exif-copyrighted-false": "版權狀態不明",
+       "exif-unknowndate": "æ\97¥æ\9c\9fä¸\8dæ\98\8e",
        "exif-orientation-1": "標準",
        "exif-orientation-2": "水平翻轉",
        "exif-orientation-3": "旋轉 180°",
        "exif-exposureprogram-7": "人像模式 (用於近距離照片,對焦不在背景)",
        "exif-exposureprogram-8": "風景模式 (用於風景照片,對焦在背景)",
        "exif-subjectdistance-value": "$1 尺",
-       "exif-meteringmode-0": "未知",
+       "exif-meteringmode-0": "不明",
        "exif-meteringmode-1": "平均",
        "exif-meteringmode-2": "中心加權平均",
        "exif-meteringmode-3": "點測",
        "exif-meteringmode-5": "模式",
        "exif-meteringmode-6": "部分",
        "exif-meteringmode-255": "其他",
-       "exif-lightsource-0": "未知",
+       "exif-lightsource-0": "不明",
        "exif-lightsource-1": "日光",
        "exif-lightsource-2": "螢光燈",
        "exif-lightsource-3": "鎢絲燈 (白熾燈)",
        "exif-flash-redeye-1": "防紅眼模式",
        "exif-focalplaneresolutionunit-2": "英寸",
        "exif-sensingmethod-1": "未定義",
-       "exif-sensingmethod-2": "一塊彩色區域傳感器",
-       "exif-sensingmethod-3": "兩塊彩色區域傳感器",
-       "exif-sensingmethod-4": "三塊彩色區域傳感器",
-       "exif-sensingmethod-5": "連續彩色區域傳感器",
-       "exif-sensingmethod-7": "三線傳感器",
-       "exif-sensingmethod-8": "連續彩色線性傳感器",
-       "exif-filesource-3": "數相機",
+       "exif-sensingmethod-2": "單晶片彩色區域感測器",
+       "exif-sensingmethod-3": "雙晶片彩色區域感測器",
+       "exif-sensingmethod-4": "三晶片彩色區域感測器",
+       "exif-sensingmethod-5": "連續彩色區域感測器",
+       "exif-sensingmethod-7": "三線性感測器",
+       "exif-sensingmethod-8": "連續彩色線性感測器",
+       "exif-filesource-3": "數相機",
        "exif-scenetype-1": "直接照像圖片",
        "exif-customrendered-0": "標準處理",
        "exif-customrendered-1": "自定義處理",
        "exif-sharpness-0": "標準",
        "exif-sharpness-1": "低",
        "exif-sharpness-2": "高",
-       "exif-subjectdistancerange-0": "未知",
-       "exif-subjectdistancerange-1": "自動處理程式(宏)",
+       "exif-subjectdistancerange-0": "不明",
+       "exif-subjectdistancerange-1": "巨集",
        "exif-subjectdistancerange-2": "近景",
        "exif-subjectdistancerange-3": "遠景",
        "exif-gpslatitude-n": "北緯",
        "exif-dc-rights": "權利",
        "exif-dc-source": "來源媒體",
        "exif-dc-type": "介質類型",
-       "exif-rating-rejected": "拒絕",
+       "exif-rating-rejected": "拒絕",
        "exif-isospeedratings-overflow": "大於 65535",
        "exif-iimcategory-ace": "藝術、文化與娛樂",
        "exif-iimcategory-clj": "犯罪與法律",
        "watchlistall2": "全部",
        "namespacesall": "全部",
        "monthsall": "全部",
-       "confirmemail": "確èª\8dé\83µç®±位址",
-       "confirmemail_noemail": "您尚未於 [[Special:Preferences|偏好設定]] 輸入一個有效的電子郵件址。",
-       "confirmemail_text": "{{SITENAME}}要求您在使用郵件功能之前驗證您的郵箱位址。\n點擊以下按鈕可向您的郵箱發送一封確認郵件。該郵件包含有一行代碼連結;\n請在您的瀏覽器中加載此連結以確認您的郵箱位址是有效的。",
-       "confirmemail_pending": "確認碼已送至您的電子郵件,\n若您才剛建立好您的帳號,可能需要稍後幾分鐘才能收到。\n若沒有收到,請再重新申請一次確認碼。",
-       "confirmemail_send": "é\83µç\99¼確認代碼",
-       "confirmemail_sent": "確認郵件已發送。",
-       "confirmemail_oncreate": "一個確認代碼已經被送到您的郵箱。該代碼並不要求您進行登入,\n但若您要啟用在此 wiki 上的任何基於電子郵件的功能,您必須先提交此代碼。",
-       "confirmemail_sendfailed": "{{SITENAME}}無法送確認郵件,請檢查郵箱位址是否包含非法字元。\n\n郵件傳送員回應: $1",
+       "confirmemail": "確èª\8dé\9b»å­\90é\83µä»¶位址",
+       "confirmemail_noemail": "您尚未於 [[Special:Preferences|偏好設定]] 輸入一個有效的電子郵件址。",
+       "confirmemail_text": "{{SITENAME}}要求您在使用郵件功能之前驗證您的郵箱位址。\n點選以下按鈕可向您的郵箱傳送一封確認郵件。該郵件包含有一行代碼連結;\n請在您的瀏覽器中載入此連結以確認您的郵箱位址是有效的。",
+       "confirmemail_pending": "確認碼已送至您的電子郵件,\n若您才剛建立好您的帳號,可能需要稍後幾分鐘才能收到。\n若沒有收到,請再重新申請一次確認碼。",
+       "confirmemail_send": "é\9b»å­\90é\83µä»¶å¯\84é\80\81確認代碼",
+       "confirmemail_sent": "已寄出確認電子郵件。",
+       "confirmemail_oncreate": "一個確認代碼已經被送到您的郵箱。該代碼並不要求您進行登入,\n但若您要啟用在此 wiki 上的任何基於電子郵件的功能,您必須先提交此代碼。",
+       "confirmemail_sendfailed": "{{SITENAME}}無法送確認郵件,請檢查郵箱位址是否包含非法字元。\n\n郵件傳送員回應: $1",
        "confirmemail_invalid": "無效的確認碼,該代碼可能已經過期。",
-       "confirmemail_needlogin": "您需要$1以確認您的郵箱位址。",
-       "confirmemail_success": "您的郵箱已經被確認。您現在可以[[Special:UserLogin|登]]並使用此網站了。",
-       "confirmemail_loggedin": "您的郵箱位址現下已被確認。",
-       "confirmemail_subject": "{{SITENAME}}郵箱位址確認",
-       "confirmemail_body": "不明人士 (可能是您自己,來自 IP 位址 $1)  已在 {{SITENAME}} 註冊了一個帳號 \"$2\" 並使用了此電子郵件址。\n\n請確認這個帳號是屬於您的,並使用瀏覽器開啟下方連結以啟用在 {{SITENAME}} 上的電子郵件功能:\n\n$3\n\n若您 *未* 註冊此帳號,\n請開啟下方連結取消電子郵件確認:\n\n$5\n\n此確認代碼會於 $4 過期。",
-       "confirmemail_body_changed": "不明人士 (可能是您自己,來自 IP 位址 $1)  已將在 {{SITENAME}} 帳號 \"$2\" 的電子郵件址更改至此。\n\n請確認這個帳號是屬於您的,並使用瀏覽器開啟下方連結以啟用在 {{SITENAME}} 上的電子郵件功能:\n\n$3\n\n若您 *未* 註冊此帳號,\n請開啟下方連結取消電子郵件確認:\n\n$5\n\n此確認代碼會於 $4 過期。",
-       "confirmemail_body_set": "不明人士 (可能是您自己,來自 IP 位址 $1)  已將在 {{SITENAME}} 帳號 \"$2\" 的電子郵件址設定至此。\n\n請確認這個帳號是屬於您的,並使用瀏覽器開啟下方連結以啟用在 {{SITENAME}} 上的電子郵件功能:\n\n$3\n\n若您 *未* 註冊此帳號,\n請開啟下方連結取消電子郵件確認:\n\n$5\n\n此確認代碼會於 $4 過期。",
-       "confirmemail_invalidated": "電郵地址確認已取消",
-       "invalidateemail": "取消電確認",
+       "confirmemail_needlogin": "請 $1 以確認您的電子郵件地址。",
+       "confirmemail_success": "您的郵箱已經被確認。您現在可以[[Special:UserLogin|登]]並使用此網站了。",
+       "confirmemail_loggedin": "已確認您的電子郵件地址。",
+       "confirmemail_subject": "{{SITENAME}} 電子郵件地址確認",
+       "confirmemail_body": "不明人士 (可能是您自己,來自 IP 位址 $1)  已在 {{SITENAME}} 註冊了一個帳號 \"$2\" 並使用了此電子郵件址。\n\n請確認這個帳號是屬於您的,並使用瀏覽器開啟下方連結以啟用在 {{SITENAME}} 上的電子郵件功能:\n\n$3\n\n若您 *未* 註冊此帳號,\n請開啟下方連結取消電子郵件確認:\n\n$5\n\n此確認代碼會於 $4 過期。",
+       "confirmemail_body_changed": "不明人士 (可能是您自己,來自 IP 位址 $1)  已將在 {{SITENAME}} 帳號 \"$2\" 的電子郵件址更改至此。\n\n請確認這個帳號是屬於您的,並使用瀏覽器開啟下方連結以啟用在 {{SITENAME}} 上的電子郵件功能:\n\n$3\n\n若您 *未* 註冊此帳號,\n請開啟下方連結取消電子郵件確認:\n\n$5\n\n此確認代碼會於 $4 過期。",
+       "confirmemail_body_set": "不明人士 (可能是您自己,來自 IP 位址 $1)  已將在 {{SITENAME}} 帳號 \"$2\" 的電子郵件址設定至此。\n\n請確認這個帳號是屬於您的,並使用瀏覽器開啟下方連結以啟用在 {{SITENAME}} 上的電子郵件功能:\n\n$3\n\n若您 *未* 註冊此帳號,\n請開啟下方連結取消電子郵件確認:\n\n$5\n\n此確認代碼會於 $4 過期。",
+       "confirmemail_invalidated": "已取消電子郵件地址確認",
+       "invalidateemail": "取消電子郵件確認",
        "scarytranscludedisabled": "[Interwiki 轉換代碼不可用]",
        "scarytranscludefailed": "[樣版 $1 讀取失敗]",
        "scarytranscludefailed-httpstatus": "[樣版 $1 讀取失敗:HTTP $2]",
-       "scarytranscludetoolong": "[URL 地址太長]",
+       "scarytranscludetoolong": "[URL 長]",
        "deletedwhileediting": "<strong>警告:</strong>此頁在您開始編輯之後已經被刪除﹗",
        "confirmrecreate": "在您編輯的同時,使用者 [[User:$1|$1]] ([[User talk:$1|對話]]) 刪除了此頁面,原因為:\n: <em>$2</em>\n請確認您是否真的要重新建立此頁面。",
        "confirmrecreate-noreason": "在您編輯的同時,使用者 [[User:$1|$1]] ([[User talk:$1|對話]]) 刪除了此頁面,請確認您是否真的要重新建立此頁面。",
-       "recreate": "重",
+       "recreate": "重新建立",
        "confirm_purge_button": "確定",
-       "confirm-purge-top": "要清除此頁面的快取嗎?",
+       "confirm-purge-top": "要清除此頁面的快取嗎",
        "confirm-purge-bottom": "清理一頁將會清除快取以及強迫顯示最現時之修訂版本。",
        "confirm-watch-button": "確定",
        "confirm-watch-top": "新增此頁面至您的監視清單?",
        "table_pager_limit_label": "每頁筆數︰",
        "table_pager_limit_submit": "送出",
        "table_pager_empty": "沒有結果",
-       "autosumm-blank": "清空頁面",
+       "autosumm-blank": "空白的頁面",
        "autosumm-replace": "使用 \"$1\" 取代內容",
        "autoredircomment": "頁面已重新導向至 [[$1]]",
        "autosumm-new": "已建立頁面,內容為 \"$1\"",
+       "autosumm-newblank": "建立空白頁面",
        "size-bytes": "$1 位元組",
        "lag-warn-normal": "此清單可能不會顯示最近 $1 {{PLURAL:$1|秒}}內的變更。",
        "lag-warn-high": "由於資料庫回應延遲,此清單可能不會顯示最近 $1 {{PLURAL:$1|秒}}內的變更。",
        "watchlistedit-clear-legend": "清空監視清單",
        "watchlistedit-clear-explain": "將會移除您的監視清單中所有的標題",
        "watchlistedit-clear-titles": "標題:",
-       "watchlistedit-clear-submit": "清空監視清單無法還原)",
+       "watchlistedit-clear-submit": "清空監視清單 (無法還原)",
        "watchlistedit-clear-done": "已清空您的監視清單。",
        "watchlistedit-clear-removed": "已移除 $1 個標題:",
        "watchlistedit-too-many": "太多要在此處顯示的頁面。",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|對話]])",
        "unknown_extension_tag": "不明的擴充標籤 \"$1\"",
        "duplicate-defaultsort": "<strong>警告:</strong>預設的排序鍵 \"$2\" 會覆蓋先前預設的排序鍵 \"$1\"。",
+       "duplicate-displaytitle": "<strong>警告:</strong> 顯示標題 \"$2\" 覆蓋之前的顯示標題 \"$1\"。",
        "version": "版本",
        "version-extensions": "已安裝的擴充套件",
-       "version-skins": "已外觀",
+       "version-skins": "已安裝的外觀",
        "version-specialpages": "特殊頁面",
-       "version-parserhooks": "èª\9eæ³\95連結(Hook)",
+       "version-parserhooks": "解æ\9e\90å\99¨連結(Hook)",
        "version-variables": "變數",
        "version-antispam": "垃圾訊息防止",
        "version-other": "其他",
        "version-mediahandlers": "媒體處理器",
        "version-hooks": "連結(Hooks)",
-       "version-parser-extensiontags": "èª\9eæ³\95擴充標籤",
+       "version-parser-extensiontags": "解æ\9e\90å\99¨擴充標籤",
        "version-parser-function-hooks": "語法函數連結",
        "version-hook-name": "連結名稱",
        "version-hook-subscribedby": "署名",
        "version-version": "($1)",
-       "version-no-ext-name": "[名]",
+       "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-description": "描述",
        "version-ext-colheader-credits": "作者",
        "version-license-title": "$1 的授權條款",
        "version-license-not-found": "查無此擴充套件的詳細授權條款資訊。",
        "version-entrypoints": "入口 URL",
        "version-entrypoints-header-entrypoint": "入口",
        "version-entrypoints-header-url": "URL",
-       "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath 條目路徑]",
+       "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath 文章路徑]",
+       "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Script 路徑]",
        "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": "尋找:",
+       "redirect-lookup": "查詢:",
        "redirect-value": "值:",
        "redirect-user": "使用者 ID",
        "redirect-page": "頁面 ID",
        "redirect-revision": "頁面修訂 ID",
        "redirect-file": "檔案名稱",
-       "redirect-not-exists": "æ\89¾ä¸\8då\88°",
+       "redirect-not-exists": "æ\9f¥ç\84¡å\80¼",
        "fileduplicatesearch": "搜尋重覆檔案",
        "fileduplicatesearch-summary": "依據雜湊值(Hash)來搜尋重複的檔案。",
        "fileduplicatesearch-legend": "搜尋重覆",
        "specialpages-note": "* 一般特殊頁面。\n* <span class=\"mw-specialpagerestricted\">受限制的特殊頁面。</span>",
        "specialpages-group-maintenance": "維護報表",
        "specialpages-group-other": "其它特殊頁面",
-       "specialpages-group-login": "登入/建立新帳號",
+       "specialpages-group-login": "登入 / 建立帳號",
        "specialpages-group-changes": "最近變更與日誌",
        "specialpages-group-media": "媒體上傳與報表",
        "specialpages-group-users": "使用者與權限",
        "specialpages-group-spam": "反垃圾訊息工具",
        "blankpage": "空白頁面",
        "intentionallyblankpage": "此頁面被故意設為空白。",
-       "external_image_whitelist": " #留下這行一樣的文字<pre>\n#在下面(//之中間部份)輸入正規表達式\n#這些將會跟外部(已超連結的)圖片配合\n#那些配合到出來的會顯示成圖片,否則就只會顯示成連結\n#有 # 開頭的行會當成註解\n#大小寫並無區分\n\n#在這行上面輸入所有的regex。留下這行一樣的文字</pre>",
+       "external_image_whitelist": " #請勿修改本行文字<pre>\n#請於下方填寫正規表示法 (只需 // 之間的內容)\n#將會檢查外部連結的圖片是否符合這些條件\n#符合條件的連結會以圖片顯示,否則只顯示連結\n#以 # 開頭的行會被做為註解\n#此條件不區分大小寫\n\n#請將所有正規表示法輸入在此行上方,請勿修改本行文字</pre>",
        "tags": "有效變更標籤",
        "tag-filter": "[[Special:Tags|標籤]]搜尋:",
        "tag-filter-submit": "搜尋",
        "tags-tag": "標籤名稱",
        "tags-display-header": "在更改清單中的出現方式",
        "tags-description-header": "完整含意說明",
-       "tags-active-header": "å­\98æª\94?",
+       "tags-active-header": "å\95\9fç\94¨?",
        "tags-hitcount-header": "已加上標籤的更改",
        "tags-active-yes": "是",
        "tags-active-no": "否",
        "compare-invalid-title": "所指定標題無效。",
        "compare-title-not-exists": "所指定的話題不存在。",
        "compare-revision-not-exists": "所指定的修訂不存在。",
-       "dberr-problems": "歉!這個網站出現了一些技術上的問題。",
+       "dberr-problems": "æ\8a±æ­\89ï¼\81é\80\99å\80\8b網ç«\99å\87ºç\8f¾äº\86ä¸\80äº\9bæ\8a\80è¡\93ä¸\8aç\9a\84å\95\8fé¡\8cã\80\82",
        "dberr-again": "嘗試等候數分鐘後,然後再試。",
        "dberr-info": "(無法連線資料庫伺服器:$1)",
        "dberr-info-hidden": "(無法連線資料庫伺服器)",
        "dberr-usegoogle": "在現階段您可以嘗試透過 Google 搜尋。",
        "dberr-outofdate": "留意他們索引出來之內容可能不是最新的。",
        "dberr-cachederror": "這個是所要求出來的快取複本,可能不是最新的。",
-       "htmlform-invalid-input": "您輸入的內容存在問題",
+       "htmlform-invalid-input": "您的輸入的內容有問題。",
        "htmlform-select-badoption": "您所指定的值不是有效的選項。",
        "htmlform-int-invalid": "您所指定的值不是一個整數。",
        "htmlform-float-invalid": "您所指定的值不是一個數字。",
-       "htmlform-int-toolow": "您所指定的值低於最小值$1",
-       "htmlform-int-toohigh": "您所指定的值高於最大值$1",
-       "htmlform-required": "此值是必填項",
-       "htmlform-submit": "提交",
+       "htmlform-int-toolow": "您所指定的值低於最小值 $1。",
+       "htmlform-int-toohigh": "您所指定的值高於最大值 $1。",
+       "htmlform-required": "此值為必填。",
+       "htmlform-submit": "送出",
        "htmlform-reset": "還原更改",
        "htmlform-selectorother-other": "其他",
        "htmlform-no": "否",
        "htmlform-yes": "是",
-       "htmlform-chosen-placeholder": "選項",
+       "htmlform-chosen-placeholder": "謮選擇一個選項",
        "htmlform-cloner-create": "新增更多",
        "htmlform-cloner-delete": "移除",
        "htmlform-cloner-required": "至少必須填寫一筆資料。",
-       "sqlite-has-fts": "帶全文搜尋的版本$1",
-       "sqlite-no-fts": "不帶全文搜尋的版本$1",
+       "sqlite-has-fts": "$1 且支援全文搜索",
+       "sqlite-no-fts": "$1 且不支援全文搜索",
        "logentry-delete-delete": "$1 刪除頁面 $3",
        "logentry-delete-restore": "$1 還原頁面 $3",
        "logentry-delete-event": "$1 {{GENDER:$2|已更改}} $3 中 {{PLURAL:$5|1 筆日誌|$5 筆日誌}}的可見性:$4",
        "logentry-suppress-revision": "$1 {{GENDER:$2|已暗中更改}}頁面 $3 中 {{PLURAL:$5|1 筆修訂|$5 筆修訂}}的可見性:$4",
        "logentry-suppress-event-legacy": "$1 {{GENDER:$2|已暗中更改}} $3 中日誌的可見性",
        "logentry-suppress-revision-legacy": "$1 {{GENDER:$2|已暗中更改}}頁面 $3 中修訂的可見性",
-       "revdelete-content-hid": "隱藏內容",
-       "revdelete-summary-hid": "隱藏編輯摘要",
+       "revdelete-content-hid": "隱藏內容",
+       "revdelete-summary-hid": "己隱藏摘要",
        "revdelete-uname-hid": "隱藏使用者名稱",
        "revdelete-content-unhid": "取消隱藏內容",
        "revdelete-summary-unhid": "取消隱藏編輯摘要",
        "logentry-rights-rights": "$1 {{GENDER:$2|已更改}} $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",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|上傳了}}新版本的 $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|已上傳}} $3",
        "rightsnone": "(無)",
        "feedback-bugornote": "如果您準備要詳細描述一個技術問題,請至 [$1 回報問題]。\n或您可以使用以下的簡易表單回報問題,您的使用者名稱與評論將被新增到頁面 \"[$3 $2]\"。",
        "feedback-subject": "主旨:",
        "feedback-message": "訊息:",
        "feedback-cancel": "取消",
-       "feedback-submit": "提交反饋",
-       "feedback-adding": "正在頁面添加反饋...",
-       "feedback-error1": "錯誤:從API返回無法識別的結果",
+       "feedback-submit": "送出意見回饋",
+       "feedback-adding": "正在新增意見回饋至頁面...",
+       "feedback-error1": "錯誤:無法識別 API 回傳的結果",
        "feedback-error2": "錯誤:編輯失敗",
-       "feedback-error3": "錯誤:API 沒有應",
-       "feedback-thanks": "謝謝!您的反饋已被發布到頁面“[$2 $1]”。",
+       "feedback-error3": "錯誤:API 沒有應",
+       "feedback-thanks": "感謝!您的意見回饋已發佈到頁面 \"[$2 $1]\"。",
        "feedback-close": "完成",
-       "feedback-bugcheck": "請檢查此bug是否為[$1 已知bug]。",
-       "feedback-bugnew": "我已經檢查過。報告一個新的bug",
+       "feedback-bugcheck": "很好! 檢查一下您的意見是不是已經被列為 [$1 已知問題]。",
+       "feedback-bugnew": "我已經檢查。 回報新問題",
        "searchsuggest-search": "搜尋",
        "searchsuggest-containing": "包含...",
        "api-error-badaccess-groups": "您沒有權限在此 Wiki 上傳檔案。",
-       "api-error-badtoken": "內部錯誤:標記無效。",
-       "api-error-copyuploaddisabled": "通過URL上傳的功能已被此伺服器禁用。",
-       "api-error-duplicate": "在網站上已經具有相同內容的{{PLURAL:$1|[$2 另一個文件]|[$2 另一些文件]}}。",
-       "api-error-duplicate-archive": "在網站上曾經具有相同內容的{{PLURAL:$1|[$2 另一個文件]|[$2 另一些文件]}},但已被刪除。",
-       "api-error-duplicate-archive-popup-title": "已被刪除的重複{{PLURAL:$1|文件}}。",
-       "api-error-duplicate-popup-title": "é\87\8dè¤\87ç\9a\84{{PLURAL:$1|æ\96\87件}}。",
-       "api-error-empty-file": "您提交的檔案是空的。",
-       "api-error-emptypage": "不許創建沒有內容的新頁面。",
-       "api-error-fetchfileerror": "內部錯誤:獲取文件時發生錯誤。",
-       "api-error-fileexists-forbidden": "以\" $1 \"命名的檔案已經存在,並且不能被重寫。",
-       "api-error-fileexists-shared-forbidden": "以\" $1 \"命名的檔案已經存在於共用檔案儲存庫上,並且不能被重寫。",
-       "api-error-file-too-large": "您提交的檔案太大了。",
-       "api-error-filename-tooshort": "檔案名過短。",
-       "api-error-filetype-banned": "這種類型的檔案是被禁止的。",
+       "api-error-badtoken": "內部錯誤:密鑰錯誤。",
+       "api-error-copyuploaddisabled": "此伺服器已停用使用 URL 上傳檔案的功能。",
+       "api-error-duplicate": "在網站上已有相同內容的{{PLURAL:$1|[$2 其他檔案]|[$2 其他檔案]}}。",
+       "api-error-duplicate-archive": "在網站上曾有相同內容的{{PLURAL:$1|[$2 其他檔案]|[$2 其他檔案]}},但已被刪除。",
+       "api-error-duplicate-archive-popup-title": "重複的{{PLURAL:$1|檔案}}已經被刪除。",
+       "api-error-duplicate-popup-title": "é\87\8dè¤\87ç\9a\84{{PLURAL:$1|æª\94æ¡\88}}。",
+       "api-error-empty-file": "您送出的檔案是空的。",
+       "api-error-emptypage": "不允許建立空白的頁面。",
+       "api-error-fetchfileerror": "內部錯誤:取得檔案時發生錯誤。",
+       "api-error-fileexists-forbidden": "名稱為 \"$1\" 的檔案已經存在,並且不能被覆寫。",
+       "api-error-fileexists-shared-forbidden": "名稱為 \"$1\" 的檔案已經存在於共用儲存庫,並且不能被覆寫。",
+       "api-error-file-too-large": "您送出的檔案太大了。",
+       "api-error-filename-tooshort": "檔案名過短。",
+       "api-error-filetype-banned": "此檔案類型已禁止使用。",
        "api-error-filetype-banned-type": "$1{{PLURAL:$4|不是允許的檔案類型}}。  允許的{{PLURAL:$3|檔案類型是}} $2。",
-       "api-error-filetype-missing": "æ\9c¬æª\94æ¡\88缺å°\91äº\86副檔名。",
+       "api-error-filetype-missing": "æ­¤æª\94æ¡\88å\90\8d稱缺å°\91副檔名。",
        "api-error-hookaborted": "你試圖進行的修改被一個擴展鉤子終止。",
-       "api-error-http": "內部錯誤:無法連到伺服器。",
-       "api-error-illegal-filename": "æª\94æ¡\88å\90\8dä¸\8då\85\81許ã\80\82",
+       "api-error-http": "內部錯誤:無法連到伺服器。",
+       "api-error-illegal-filename": "ä¸\8då\85\81許使ç\94¨ç\9a\84æª\94æ¡\88å\90\8d稱ã\80\82",
        "api-error-internal-error": "內部錯誤:此 Wiki 在處理你的上傳時發生錯誤。",
-       "api-error-invalid-file-key": "內部錯誤:於臨時儲存庫中查無檔案。",
-       "api-error-missingparam": "內部錯誤:請求缺少參數。",
-       "api-error-missingresult": "內部錯誤:無法確定複製是否成功。",
-       "api-error-mustbeloggedin": "您必須登錄後再上傳文件。",
-       "api-error-mustbeposted": "內部錯誤:請求需 HTTP POST。",
-       "api-error-noimageinfo": "文件成功,但伺服器沒有給我們任何該文件的信息。",
-       "api-error-nomodule": "內部錯誤:缺少上傳模集。",
-       "api-error-ok-but-empty": "內部錯誤:伺服器沒有應。",
-       "api-error-overwrite": "不允許覆蓋現有檔案。",
-       "api-error-stashfailed": "內部錯誤:伺服器保存臨時檔案失敗。",
-       "api-error-publishfailed": "內部錯誤:伺服器發佈臨時檔案失敗。",
-       "api-error-stasherror": "上載檔案存檔時出錯。",
+       "api-error-invalid-file-key": "內部錯誤:於暫存儲存庫中查無檔案。",
+       "api-error-missingparam": "內部錯誤:請求缺少參數。",
+       "api-error-missingresult": "內部錯誤:無法辨識複製是否成功。",
+       "api-error-mustbeloggedin": "您必須登入方可上傳檔案。",
+       "api-error-mustbeposted": "內部錯誤:請求需使用 HTTP POST。",
+       "api-error-noimageinfo": "上傳成功,但伺服器沒有給我們任何該檔案的資訊。",
+       "api-error-nomodule": "內部錯誤:缺少上傳模集。",
+       "api-error-ok-but-empty": "內部錯誤:伺服器沒有應。",
+       "api-error-overwrite": "不允許覆蓋已存在的檔案。",
+       "api-error-stashfailed": "內部錯誤:伺服器儲存暫存檔案失敗。",
+       "api-error-publishfailed": "內部錯誤:伺服器發佈暫存檔案失敗。",
+       "api-error-stasherror": "上傳檔案至儲存庫時發生錯誤。",
        "api-error-timeout": "伺服器沒有在預期的時間內回應。",
-       "api-error-unclassified": "發生未知錯誤。",
-       "api-error-unknown-code": "未知錯誤:$1",
-       "api-error-unknown-error": "å\85§é\83¨é\8c¯èª¤ï¼\9aå\98\97試ä¸\8aå\82³æ\96\87件æ\99\82å\87ºé\8c¯。",
-       "api-error-unknown-warning": "未知的警告:$1",
-       "api-error-unknownerror": "未知錯誤:$1。",
-       "api-error-uploaddisabled": "æ\9c¬wikiç\9a\84ä¸\8aå\82³æª\94æ¡\88功能已停用。",
-       "api-error-verification-error": "æ\9c¬檔案可能已損壞,或副檔名錯誤。",
+       "api-error-unclassified": "發生不明錯誤。",
+       "api-error-unknown-code": "不明錯誤:\"$1\"。",
+       "api-error-unknown-error": "å\85§é\83¨é\8c¯èª¤ï¼\9aå\98\97試ä¸\8aå\82³æ\82¨ç\9a\84æª\94æ¡\88æ\99\82ç\99¼ç\94\9fé\8c¯èª¤。",
+       "api-error-unknown-warning": "不明警告:\"$1\"。",
+       "api-error-unknownerror": "不明錯誤:\"$1\"。",
+       "api-error-uploaddisabled": "æ­¤ Wiki ç\9a\84ä¸\8aå\82³功能已停用。",
+       "api-error-verification-error": "æ­¤檔案可能已損壞,或副檔名錯誤。",
        "duration-seconds": "$1 秒",
        "duration-minutes": "$1 分鐘",
        "duration-hours": "$1 小時",
        "duration-decades": "$1{{PLURAL:$1|0 年|0 年}}",
        "duration-centuries": "$1 世紀",
        "duration-millennia": "$1 千年",
-       "rotate-comment": "順時針旋轉圖像$1{{PLURAL:$1|度}}",
-       "limitreport-title": "析器分析資料:",
+       "rotate-comment": "已順時針旋轉圖片 $1 {{PLURAL:$1|度|度}}",
+       "limitreport-title": "析器分析資料:",
        "limitreport-cputime": "CPU 使用時間",
        "limitreport-cputime-value": "$1 秒",
        "limitreport-walltime": "實際使用時間",
        "limitreport-walltime-value": "$1 秒",
-       "limitreport-ppvisitednodes": "預處理訪問節點次數",
+       "limitreport-ppvisitednodes": "預處理訪問節點次數",
        "limitreport-ppgeneratednodes": "預處理器產生節點次數",
        "limitreport-postexpandincludesize": "展開後的引用大小",
        "limitreport-postexpandincludesize-value": "$1/$2 個{{PLURAL:$2|位元組}}",
        "limitreport-templateargumentsize": "樣版參數大小",
        "limitreport-templateargumentsize-value": "$1/$2 個{{PLURAL:$2|位元組}}",
        "limitreport-expansiondepth": "最高展開深度",
-       "limitreport-expensivefunctioncount": "高分析函數次數",
+       "limitreport-expensivefunctioncount": "高消耗解析器函數次數",
        "expandtemplates": "展開樣版",
-       "expand_templates_intro": "本特殊頁面會將文字中的樣版展開,可以包含支援的分析程式語法,如 <code><nowiki>{{</nowiki>#language:…}}</code> 與變數如 <code><nowiki>{{</nowiki>CURRENTDAY}}</code>。\n實際上,絕大部分在雙括號中的內容都會被展開。",
+       "expand_templates_intro": "本特殊頁面會將文字中的樣版展開,可以包含支援的解析器語法,如 <code><nowiki>{{</nowiki>#language:…}}</code> 與變數如 <code><nowiki>{{</nowiki>CURRENTDAY}}</code>。\n實際上,絕大部分在雙括號中的內容都會被展開。",
        "expand_templates_title": "上下文標題,用於 {{FULLPAGENAME}} 等:",
        "expand_templates_input": "輸入文字:",
-       "expand_templates_output": "結果",
+       "expand_templates_output": "結果",
        "expand_templates_xml_output": "XML 輸出",
        "expand_templates_html_output": "原始 HTML 輸出",
        "expand_templates_ok": "確定",
        "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 dir=\"ltr\">$wgDefaultSkin</code> 設定的 Wiki 預設外觀 <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/Special:MyLanguage/Download tarball 安裝程式],該程式包含數個外觀與擴充套件。 您可以複製並貼上至 <code>skins/</code> 目錄。\n:* 透過 git 複製 <code>mediawiki/skins/*</code> 儲存庫中其中一個外觀到您安裝的 MediaWiki <code dir=\"ltr\">skins/</code> 目錄中。\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 dir=\"ltr\">$3</pre>\n\n; 若您才剛修改 <code>LocalSettings.php</code>:\n: 請再次確認您輸入的外觀名稱是否有誤。",
+       "default-skin-not-found-no-skins": "哎呀!您於 <code>$wgDefaultSkin</code> 設定的 Wiki 預設外觀 <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:* 透過 git 複製 <code>mediawiki/skins/*</code> 儲存庫中其中一個外觀到您安裝的 MediaWiki <code dir=\"ltr\">skins/</code> 目錄中。\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 ('''已停用''')"
 }
index 0fcf660..15c8142 100644 (file)
@@ -8,5 +8,12 @@
  *
  */
 
+$digitTransformTable = array();
+
+$separatorTransformTable = array(
+       '.' => ',',
+       ',' => '.'
+);
+
 $fallback = 'ar';
 
index af37630..1ed78b3 100644 (file)
@@ -45,3 +45,6 @@ $namespaceAliases = array(
        'Kategorie_Diskussion' => NS_CATEGORY_TALK,
 );
 
+// Remove German aliases
+$namespaceGenderAliases = array();
+
index dd19174..b1efa3a 100644 (file)
@@ -173,3 +173,4 @@ $dateFormats = array(
        'hijri both' => '‏H:i، xmjی xmFی xmY',
 );
 
+$linkTrail = "/^([ئابپتجچحخدرڕزژسشعغفڤقکگلڵمنوۆهھەیێ‌]+)(.*)$/sDu";
index 3729a78..1618bdb 100644 (file)
@@ -57,43 +57,43 @@ $namespaceAliases = array(
 $namespaceGenderAliases = array();
 
 $datePreferences = array(
-    'default',
-    'mdy',
-    'dmy',
-    'ymd',
-    'yyyy-mm-dd',
-    'ISO 8601',
+       'default',
+       'mdy',
+       'dmy',
+       'ymd',
+       'yyyy-mm-dd',
+       'ISO 8601',
 );
 
 $defaultDateFormat = 'ymd';
 
 $datePreferenceMigrationMap = array(
-    'default',
-    'mdy',
-    'dmy',
-    'ymd'
+       'default',
+       'mdy',
+       'dmy',
+       'ymd'
 );
 
 $dateFormats = array(
-    'mdy time' => 'H:i',
-    'mdy date' => 'F j Y "с."',
-    'mdy both' => 'H:i, F j Y "с."',
+       'mdy time' => 'H:i',
+       'mdy date' => 'F j Y "с."',
+       'mdy both' => 'H:i, F j Y "с."',
 
-    'dmy time' => 'H:i',
-    'dmy date' => 'j F Y "с."',
-    'dmy both' => 'H:i, j F Y "с."',
+       'dmy time' => 'H:i',
+       'dmy date' => 'j F Y "с."',
+       'dmy both' => 'H:i, j F Y "с."',
 
-    'ymd time' => 'H:i',
-    'ymd date' => 'Y "с." xg j',
-    'ymd both' => 'H:i, Y "с." xg j',
+       'ymd time' => 'H:i',
+       'ymd date' => 'Y "с." xg j',
+       'ymd both' => 'H:i, Y "с." xg j',
 
-    'yyyy-mm-dd time' => 'xnH:xni:xns',
-    'yyyy-mm-dd date' => 'xnY-xnm-xnd',
-    'yyyy-mm-dd both' => 'xnH:xni:xns, xnY-xnm-xnd',
+       'yyyy-mm-dd time' => 'xnH:xni:xns',
+       'yyyy-mm-dd date' => 'xnY-xnm-xnd',
+       'yyyy-mm-dd both' => 'xnH:xni:xns, xnY-xnm-xnd',
 
-    'ISO 8601 time' => 'xnH:xni:xns',
-    'ISO 8601 date' => 'xnY.xnm.xnd',
-    'ISO 8601 both' => 'xnY.xnm.xnd"T"xnH:xni:xns',
+       'ISO 8601 time' => 'xnH:xni:xns',
+       'ISO 8601 date' => 'xnY.xnm.xnd',
+       'ISO 8601 both' => 'xnY.xnm.xnd"T"xnH:xni:xns',
 );
 
 $separatorTransformTable = array( ','  => '.', '.' => ',' );
index 7fb5df0..6b852b7 100644 (file)
@@ -52,43 +52,43 @@ $namespaceAliases = array(
 );
 
 $datePreferences = array(
-    'default',
-    'mdy',
-    'dmy',
-    'ymd',
-    'yyyy-mm-dd',
-    'ISO 8601',
+       'default',
+       'mdy',
+       'dmy',
+       'ymd',
+       'yyyy-mm-dd',
+       'ISO 8601',
 );
 
 $defaultDateFormat = 'ymd';
 
 $datePreferenceMigrationMap = array(
-    'default',
-    'mdy',
-    'dmy',
-    'ymd'
+       'default',
+       'mdy',
+       'dmy',
+       'ymd'
 );
 
 $dateFormats = array(
-    'mdy time' => 'H:i',
-    'mdy date' => 'F j Y "s."',
-    'mdy both' => 'H:i, F j Y "s."',
+       'mdy time' => 'H:i',
+       'mdy date' => 'F j Y "s."',
+       'mdy both' => 'H:i, F j Y "s."',
 
-    'dmy time' => 'H:i',
-    'dmy date' => 'j F Y "s."',
-    'dmy both' => 'H:i, j F Y "s."',
+       'dmy time' => 'H:i',
+       'dmy date' => 'j F Y "s."',
+       'dmy both' => 'H:i, j F Y "s."',
 
-    'ymd time' => 'H:i',
-    'ymd date' => 'Y "s." xg j',
-    'ymd both' => 'H:i, Y "s." xg j',
+       'ymd time' => 'H:i',
+       'ymd date' => 'Y "s." xg j',
+       'ymd both' => 'H:i, Y "s." xg j',
 
-    'yyyy-mm-dd time' => 'xnH:xni:xns',
-    'yyyy-mm-dd date' => 'xnY-xnm-xnd',
-    'yyyy-mm-dd both' => 'xnH:xni:xns, xnY-xnm-xnd',
+       'yyyy-mm-dd time' => 'xnH:xni:xns',
+       'yyyy-mm-dd date' => 'xnY-xnm-xnd',
+       'yyyy-mm-dd both' => 'xnH:xni:xns, xnY-xnm-xnd',
 
-    'ISO 8601 time' => 'xnH:xni:xns',
-    'ISO 8601 date' => 'xnY.xnm.xnd',
-    'ISO 8601 both' => 'xnY.xnm.xnd"T"xnH:xni:xns',
+       'ISO 8601 time' => 'xnH:xni:xns',
+       'ISO 8601 date' => 'xnY.xnm.xnd',
+       'ISO 8601 both' => 'xnY.xnm.xnd"T"xnH:xni:xns',
 );
 
 $separatorTransformTable = array( ',' => '.', '.' => ',' );
index 2718a48..b796aca 100644 (file)
@@ -261,7 +261,7 @@ $magicWords = array(
  * Date formats list for Special:Preferences
  * see $dateFormats for definitions
  */
-$datePreferences =  array(
+$datePreferences = array(
        'ČSN basic dt',
        'ČSN padded dt',
        'ČSN basic td',
index 4cffd2b..d6f268f 100644 (file)
@@ -35,8 +35,8 @@ $namespaceAliases = array(
 );
 
 $namespaceGenderAliases = array(
-        NS_USER => array( 'male' => 'Wužywaŕ', 'female' => 'Wužywarka' ),
-        NS_USER_TALK => array( 'male' => 'Diskusija_wužywarja', 'female' => 'Diskusija_wužywarki' ),
+       NS_USER => array( 'male' => 'Wužywaŕ', 'female' => 'Wužywarka' ),
+       NS_USER_TALK => array( 'male' => 'Diskusija_wužywarja', 'female' => 'Diskusija_wužywarki' ),
 );
 
 $specialPageAliases = array(
index 6900aeb..7541f31 100644 (file)
@@ -103,9 +103,11 @@ $namespaceAliases = array();
  * Array of gender specific. namespace aliases.
  * Mapping NS_xxx to array of GENDERKEY to alias.
  * Example:
-$namespaceGenderAliases = array(
-       NS_USER => array( 'male' => 'Male_user', 'female' => 'Female_user' ),
-);
+ * @code
+ * $namespaceGenderAliases = array(
+ *     NS_USER => array( 'male' => 'Male_user', 'female' => 'Female_user' ),
+ * );
+ * @endcode
  */
 $namespaceGenderAliases = array();
 
@@ -202,173 +204,175 @@ $bookstoreList = array(
  * This array can be modified at runtime with the LanguageGetMagic hook
  */
 $magicWords = array(
-#   ID                                  CASE  SYNONYMS
-       'redirect'                => array( 0,    '#REDIRECT' ),
-       'notoc'                   => array( 0,    '__NOTOC__' ),
-       'nogallery'               => array( 0,    '__NOGALLERY__' ),
-       'forcetoc'                => array( 0,    '__FORCETOC__' ),
-       'toc'                     => array( 0,    '__TOC__' ),
-       'noeditsection'           => array( 0,    '__NOEDITSECTION__' ),
-       '!'                       => array( 1,    '!' ),
-       'currentmonth'            => array( 1,    'CURRENTMONTH', 'CURRENTMONTH2' ),
-       'currentmonth1'           => array( 1,    'CURRENTMONTH1' ),
-       'currentmonthname'        => array( 1,    'CURRENTMONTHNAME' ),
-       'currentmonthnamegen'     => array( 1,    'CURRENTMONTHNAMEGEN' ),
-       'currentmonthabbrev'      => array( 1,    'CURRENTMONTHABBREV' ),
-       'currentday'              => array( 1,    'CURRENTDAY' ),
-       'currentday2'             => array( 1,    'CURRENTDAY2' ),
-       'currentdayname'          => array( 1,    'CURRENTDAYNAME' ),
-       'currentyear'             => array( 1,    'CURRENTYEAR' ),
-       'currenttime'             => array( 1,    'CURRENTTIME' ),
-       'currenthour'             => array( 1,    'CURRENTHOUR' ),
-       'localmonth'              => array( 1,    'LOCALMONTH', 'LOCALMONTH2' ),
-       'localmonth1'             => array( 1,    'LOCALMONTH1' ),
-       'localmonthname'          => array( 1,    'LOCALMONTHNAME' ),
-       'localmonthnamegen'       => array( 1,    'LOCALMONTHNAMEGEN' ),
-       'localmonthabbrev'        => array( 1,    'LOCALMONTHABBREV' ),
-       'localday'                => array( 1,    'LOCALDAY' ),
-       'localday2'               => array( 1,    'LOCALDAY2' ),
-       'localdayname'            => array( 1,    'LOCALDAYNAME' ),
-       'localyear'               => array( 1,    'LOCALYEAR' ),
-       'localtime'               => array( 1,    'LOCALTIME' ),
-       'localhour'               => array( 1,    'LOCALHOUR' ),
-       'numberofpages'           => array( 1,    'NUMBEROFPAGES' ),
-       'numberofarticles'        => array( 1,    'NUMBEROFARTICLES' ),
-       'numberoffiles'           => array( 1,    'NUMBEROFFILES' ),
-       'numberofusers'           => array( 1,    'NUMBEROFUSERS' ),
-       'numberofactiveusers'     => array( 1,    'NUMBEROFACTIVEUSERS' ),
-       'numberofedits'           => array( 1,    'NUMBEROFEDITS' ),
-       'numberofviews'           => array( 1,    'NUMBEROFVIEWS' ),
-       'pagename'                => array( 1,    'PAGENAME' ),
-       'pagenamee'               => array( 1,    'PAGENAMEE' ),
-       'namespace'               => array( 1,    'NAMESPACE' ),
-       'namespacee'              => array( 1,    'NAMESPACEE' ),
-       'namespacenumber'         => array( 1,    'NAMESPACENUMBER' ),
-       'talkspace'               => array( 1,    'TALKSPACE' ),
-       'talkspacee'              => array( 1,    'TALKSPACEE' ),
-       'subjectspace'            => array( 1,    'SUBJECTSPACE', 'ARTICLESPACE' ),
-       'subjectspacee'           => array( 1,    'SUBJECTSPACEE', 'ARTICLESPACEE' ),
-       'fullpagename'            => array( 1,    'FULLPAGENAME' ),
-       'fullpagenamee'           => array( 1,    'FULLPAGENAMEE' ),
-       'subpagename'             => array( 1,    'SUBPAGENAME' ),
-       'subpagenamee'            => array( 1,    'SUBPAGENAMEE' ),
-       'rootpagename'            => array( 1,    'ROOTPAGENAME' ),
-       'rootpagenamee'           => array( 1,    'ROOTPAGENAMEE' ),
-       'basepagename'            => array( 1,    'BASEPAGENAME' ),
-       'basepagenamee'           => array( 1,    'BASEPAGENAMEE' ),
-       'talkpagename'            => array( 1,    'TALKPAGENAME' ),
-       'talkpagenamee'           => array( 1,    'TALKPAGENAMEE' ),
-       'subjectpagename'         => array( 1,    'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
-       'subjectpagenamee'        => array( 1,    'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ),
-       'msg'                     => array( 0,    'MSG:' ),
-       'subst'                   => array( 0,    'SUBST:' ),
-       'safesubst'               => array( 0,    'SAFESUBST:' ),
-       'msgnw'                   => array( 0,    'MSGNW:' ),
-       'img_thumbnail'           => array( 1,    'thumbnail', 'thumb' ),
-       'img_manualthumb'         => array( 1,    'thumbnail=$1', 'thumb=$1' ),
-       'img_right'               => array( 1,    'right' ),
-       'img_left'                => array( 1,    'left' ),
-       'img_none'                => array( 1,    'none' ),
-       'img_width'               => array( 1,    '$1px' ),
-       'img_center'              => array( 1,    'center', 'centre' ),
-       'img_framed'              => array( 1,    'framed', 'enframed', 'frame' ),
-       'img_frameless'           => array( 1,    'frameless' ),
-       'img_lang'                => array( 1,    'lang=$1' ),
-       'img_page'                => array( 1,    'page=$1', 'page $1' ),
-       'img_upright'             => array( 1,    'upright', 'upright=$1', 'upright $1' ),
-       'img_border'              => array( 1,    'border' ),
-       'img_baseline'            => array( 1,    'baseline' ),
-       'img_sub'                 => array( 1,    'sub' ),
-       'img_super'               => array( 1,    'super', 'sup' ),
-       'img_top'                 => array( 1,    'top' ),
-       'img_text_top'            => array( 1,    'text-top' ),
-       'img_middle'              => array( 1,    'middle' ),
-       'img_bottom'              => array( 1,    'bottom' ),
-       'img_text_bottom'         => array( 1,    'text-bottom' ),
-       'img_link'                => array( 1,    'link=$1' ),
-       'img_alt'                 => array( 1,    'alt=$1' ),
-       'img_class'               => array( 1,    'class=$1' ),
-       'int'                     => array( 0,    'INT:' ),
-       'sitename'                => array( 1,    'SITENAME' ),
-       'ns'                      => array( 0,    'NS:' ),
-       'nse'                     => array( 0,    'NSE:' ),
-       'localurl'                => array( 0,    'LOCALURL:' ),
-       'localurle'               => array( 0,    'LOCALURLE:' ),
-       'articlepath'             => array( 0,    'ARTICLEPATH' ),
-       'pageid'                  => array( 0,    'PAGEID' ),
-       'server'                  => array( 0,    'SERVER' ),
-       'servername'              => array( 0,    'SERVERNAME' ),
-       'scriptpath'              => array( 0,    'SCRIPTPATH' ),
-       'stylepath'               => array( 0,    'STYLEPATH' ),
-       'grammar'                 => array( 0,    'GRAMMAR:' ),
-       'gender'                  => array( 0,    'GENDER:' ),
-       'notitleconvert'          => array( 0,    '__NOTITLECONVERT__', '__NOTC__' ),
-       'nocontentconvert'        => array( 0,    '__NOCONTENTCONVERT__', '__NOCC__' ),
-       'currentweek'             => array( 1,    'CURRENTWEEK' ),
-       'currentdow'              => array( 1,    'CURRENTDOW' ),
-       'localweek'               => array( 1,    'LOCALWEEK' ),
-       'localdow'                => array( 1,    'LOCALDOW' ),
-       'revisionid'              => array( 1,    'REVISIONID' ),
-       'revisionday'             => array( 1,    'REVISIONDAY' ),
-       'revisionday2'            => array( 1,    'REVISIONDAY2' ),
-       'revisionmonth'           => array( 1,    'REVISIONMONTH' ),
-       'revisionmonth1'          => array( 1,    'REVISIONMONTH1' ),
-       'revisionyear'            => array( 1,    'REVISIONYEAR' ),
-       'revisiontimestamp'       => array( 1,    'REVISIONTIMESTAMP' ),
-       'revisionuser'            => array( 1,    'REVISIONUSER' ),
-       'revisionsize'            => array( 1,    'REVISIONSIZE' ),
-       'plural'                  => array( 0,    'PLURAL:' ),
-       'fullurl'                 => array( 0,    'FULLURL:' ),
-       'fullurle'                => array( 0,    'FULLURLE:' ),
-       'canonicalurl'            => array( 0,    'CANONICALURL:' ),
-       'canonicalurle'           => array( 0,    'CANONICALURLE:' ),
-       'lcfirst'                 => array( 0,    'LCFIRST:' ),
-       'ucfirst'                 => array( 0,    'UCFIRST:' ),
-       'lc'                      => array( 0,    'LC:' ),
-       'uc'                      => array( 0,    'UC:' ),
-       'raw'                     => array( 0,    'RAW:' ),
-       'displaytitle'            => array( 1,    'DISPLAYTITLE' ),
-       'rawsuffix'               => array( 1,    'R' ),
-       'nocommafysuffix'         => array( 0,    'NOSEP' ),
-       'newsectionlink'          => array( 1,    '__NEWSECTIONLINK__' ),
-       'nonewsectionlink'        => array( 1,    '__NONEWSECTIONLINK__' ),
-       'currentversion'          => array( 1,    'CURRENTVERSION' ),
-       'urlencode'               => array( 0,    'URLENCODE:' ),
-       'anchorencode'            => array( 0,    'ANCHORENCODE' ),
-       'currenttimestamp'        => array( 1,    'CURRENTTIMESTAMP' ),
-       'localtimestamp'          => array( 1,    'LOCALTIMESTAMP' ),
-       'directionmark'           => array( 1,    'DIRECTIONMARK', 'DIRMARK' ),
-       'language'                => array( 0,    '#LANGUAGE:' ),
-       'contentlanguage'         => array( 1,    'CONTENTLANGUAGE', 'CONTENTLANG' ),
-       'pagesinnamespace'        => array( 1,    'PAGESINNAMESPACE:', 'PAGESINNS:' ),
-       'numberofadmins'          => array( 1,    'NUMBEROFADMINS' ),
-       'formatnum'               => array( 0,    'FORMATNUM' ),
-       'padleft'                 => array( 0,    'PADLEFT' ),
-       'padright'                => array( 0,    'PADRIGHT' ),
-       'special'                 => array( 0,    'special' ),
-       'speciale'                => array( 0,    'speciale' ),
-       'defaultsort'             => array( 1,    'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DEFAULTCATEGORYSORT:' ),
-       'filepath'                => array( 0,    'FILEPATH:' ),
-       'tag'                     => array( 0,    'tag' ),
-       'hiddencat'               => array( 1,    '__HIDDENCAT__' ),
-       'pagesincategory'         => array( 1,    'PAGESINCATEGORY', 'PAGESINCAT' ),
-       'pagesize'                => array( 1,    'PAGESIZE' ),
-       'index'                   => array( 1,    '__INDEX__' ),
-       'noindex'                 => array( 1,    '__NOINDEX__' ),
-       'numberingroup'           => array( 1,    'NUMBERINGROUP', 'NUMINGROUP' ),
-       'staticredirect'          => array( 1,    '__STATICREDIRECT__' ),
-       'protectionlevel'         => array( 1,    'PROTECTIONLEVEL' ),
-       'cascadingsources'        => array( 1,    'CASCADINGSOURCES' ),
-       'formatdate'              => array( 0,    'formatdate', 'dateformat' ),
-       'url_path'                => array( 0,    'PATH' ),
-       'url_wiki'                => array( 0,    'WIKI' ),
-       'url_query'               => array( 0,    'QUERY' ),
-       'defaultsort_noerror'     => array( 0,    'noerror' ),
-       'defaultsort_noreplace'   => array( 0,    'noreplace' ),
-       'pagesincategory_all'     => array( 0,    'all' ),
-       'pagesincategory_pages'   => array( 0,    'pages' ),
-       'pagesincategory_subcats' => array( 0,    'subcats' ),
-       'pagesincategory_files'   => array( 0,    'files' ),
+#   ID                               CASE  SYNONYMS
+       'redirect'                => array( 0, '#REDIRECT' ),
+       'notoc'                   => array( 0, '__NOTOC__' ),
+       'nogallery'               => array( 0, '__NOGALLERY__' ),
+       'forcetoc'                => array( 0, '__FORCETOC__' ),
+       'toc'                     => array( 0, '__TOC__' ),
+       'noeditsection'           => array( 0, '__NOEDITSECTION__' ),
+       '!'                       => array( 1, '!' ),
+       'currentmonth'            => array( 1, 'CURRENTMONTH', 'CURRENTMONTH2' ),
+       'currentmonth1'           => array( 1, 'CURRENTMONTH1' ),
+       'currentmonthname'        => array( 1, 'CURRENTMONTHNAME' ),
+       'currentmonthnamegen'     => array( 1, 'CURRENTMONTHNAMEGEN' ),
+       'currentmonthabbrev'      => array( 1, 'CURRENTMONTHABBREV' ),
+       'currentday'              => array( 1, 'CURRENTDAY' ),
+       'currentday2'             => array( 1, 'CURRENTDAY2' ),
+       'currentdayname'          => array( 1, 'CURRENTDAYNAME' ),
+       'currentyear'             => array( 1, 'CURRENTYEAR' ),
+       'currenttime'             => array( 1, 'CURRENTTIME' ),
+       'currenthour'             => array( 1, 'CURRENTHOUR' ),
+       'localmonth'              => array( 1, 'LOCALMONTH', 'LOCALMONTH2' ),
+       'localmonth1'             => array( 1, 'LOCALMONTH1' ),
+       'localmonthname'          => array( 1, 'LOCALMONTHNAME' ),
+       'localmonthnamegen'       => array( 1, 'LOCALMONTHNAMEGEN' ),
+       'localmonthabbrev'        => array( 1, 'LOCALMONTHABBREV' ),
+       'localday'                => array( 1, 'LOCALDAY' ),
+       'localday2'               => array( 1, 'LOCALDAY2' ),
+       'localdayname'            => array( 1, 'LOCALDAYNAME' ),
+       'localyear'               => array( 1, 'LOCALYEAR' ),
+       'localtime'               => array( 1, 'LOCALTIME' ),
+       'localhour'               => array( 1, 'LOCALHOUR' ),
+       'numberofpages'           => array( 1, 'NUMBEROFPAGES' ),
+       'numberofarticles'        => array( 1, 'NUMBEROFARTICLES' ),
+       'numberoffiles'           => array( 1, 'NUMBEROFFILES' ),
+       'numberofusers'           => array( 1, 'NUMBEROFUSERS' ),
+       'numberofactiveusers'     => array( 1, 'NUMBEROFACTIVEUSERS' ),
+       'numberofedits'           => array( 1, 'NUMBEROFEDITS' ),
+       'numberofviews'           => array( 1, 'NUMBEROFVIEWS' ),
+       'pagename'                => array( 1, 'PAGENAME' ),
+       'pagenamee'               => array( 1, 'PAGENAMEE' ),
+       'namespace'               => array( 1, 'NAMESPACE' ),
+       'namespacee'              => array( 1, 'NAMESPACEE' ),
+       'namespacenumber'         => array( 1, 'NAMESPACENUMBER' ),
+       'talkspace'               => array( 1, 'TALKSPACE' ),
+       'talkspacee'              => array( 1, 'TALKSPACEE' ),
+       'subjectspace'            => array( 1, 'SUBJECTSPACE', 'ARTICLESPACE' ),
+       'subjectspacee'           => array( 1, 'SUBJECTSPACEE', 'ARTICLESPACEE' ),
+       'fullpagename'            => array( 1, 'FULLPAGENAME' ),
+       'fullpagenamee'           => array( 1, 'FULLPAGENAMEE' ),
+       'subpagename'             => array( 1, 'SUBPAGENAME' ),
+       'subpagenamee'            => array( 1, 'SUBPAGENAMEE' ),
+       'rootpagename'            => array( 1, 'ROOTPAGENAME' ),
+       'rootpagenamee'           => array( 1, 'ROOTPAGENAMEE' ),
+       'basepagename'            => array( 1, 'BASEPAGENAME' ),
+       'basepagenamee'           => array( 1, 'BASEPAGENAMEE' ),
+       'talkpagename'            => array( 1, 'TALKPAGENAME' ),
+       'talkpagenamee'           => array( 1, 'TALKPAGENAMEE' ),
+       'subjectpagename'         => array( 1, 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
+       'subjectpagenamee'        => array( 1, 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ),
+       'msg'                     => array( 0, 'MSG:' ),
+       'subst'                   => array( 0, 'SUBST:' ),
+       'safesubst'               => array( 0, 'SAFESUBST:' ),
+       'msgnw'                   => array( 0, 'MSGNW:' ),
+       'img_thumbnail'           => array( 1, 'thumbnail', 'thumb' ),
+       'img_manualthumb'         => array( 1, 'thumbnail=$1', 'thumb=$1' ),
+       'img_right'               => array( 1, 'right' ),
+       'img_left'                => array( 1, 'left' ),
+       'img_none'                => array( 1, 'none' ),
+       'img_width'               => array( 1, '$1px' ),
+       'img_center'              => array( 1, 'center', 'centre' ),
+       'img_framed'              => array( 1, 'framed', 'enframed', 'frame' ),
+       'img_frameless'           => array( 1, 'frameless' ),
+       'img_lang'                => array( 1, 'lang=$1' ),
+       'img_page'                => array( 1, 'page=$1', 'page $1' ),
+       'img_upright'             => array( 1, 'upright', 'upright=$1', 'upright $1' ),
+       'img_border'              => array( 1, 'border' ),
+       'img_baseline'            => array( 1, 'baseline' ),
+       'img_sub'                 => array( 1, 'sub' ),
+       'img_super'               => array( 1, 'super', 'sup' ),
+       'img_top'                 => array( 1, 'top' ),
+       'img_text_top'            => array( 1, 'text-top' ),
+       'img_middle'              => array( 1, 'middle' ),
+       'img_bottom'              => array( 1, 'bottom' ),
+       'img_text_bottom'         => array( 1, 'text-bottom' ),
+       'img_link'                => array( 1, 'link=$1' ),
+       'img_alt'                 => array( 1, 'alt=$1' ),
+       'img_class'               => array( 1, 'class=$1' ),
+       'int'                     => array( 0, 'INT:' ),
+       'sitename'                => array( 1, 'SITENAME' ),
+       'ns'                      => array( 0, 'NS:' ),
+       'nse'                     => array( 0, 'NSE:' ),
+       'localurl'                => array( 0, 'LOCALURL:' ),
+       'localurle'               => array( 0, 'LOCALURLE:' ),
+       'articlepath'             => array( 0, 'ARTICLEPATH' ),
+       'pageid'                  => array( 0, 'PAGEID' ),
+       'server'                  => array( 0, 'SERVER' ),
+       'servername'              => array( 0, 'SERVERNAME' ),
+       'scriptpath'              => array( 0, 'SCRIPTPATH' ),
+       'stylepath'               => array( 0, 'STYLEPATH' ),
+       'grammar'                 => array( 0, 'GRAMMAR:' ),
+       'gender'                  => array( 0, 'GENDER:' ),
+       'notitleconvert'          => array( 0, '__NOTITLECONVERT__', '__NOTC__' ),
+       'nocontentconvert'        => array( 0, '__NOCONTENTCONVERT__', '__NOCC__' ),
+       'currentweek'             => array( 1, 'CURRENTWEEK' ),
+       'currentdow'              => array( 1, 'CURRENTDOW' ),
+       'localweek'               => array( 1, 'LOCALWEEK' ),
+       'localdow'                => array( 1, 'LOCALDOW' ),
+       'revisionid'              => array( 1, 'REVISIONID' ),
+       'revisionday'             => array( 1, 'REVISIONDAY' ),
+       'revisionday2'            => array( 1, 'REVISIONDAY2' ),
+       'revisionmonth'           => array( 1, 'REVISIONMONTH' ),
+       'revisionmonth1'          => array( 1, 'REVISIONMONTH1' ),
+       'revisionyear'            => array( 1, 'REVISIONYEAR' ),
+       'revisiontimestamp'       => array( 1, 'REVISIONTIMESTAMP' ),
+       'revisionuser'            => array( 1, 'REVISIONUSER' ),
+       'revisionsize'            => array( 1, 'REVISIONSIZE' ),
+       'plural'                  => array( 0, 'PLURAL:' ),
+       'fullurl'                 => array( 0, 'FULLURL:' ),
+       'fullurle'                => array( 0, 'FULLURLE:' ),
+       'canonicalurl'            => array( 0, 'CANONICALURL:' ),
+       'canonicalurle'           => array( 0, 'CANONICALURLE:' ),
+       'lcfirst'                 => array( 0, 'LCFIRST:' ),
+       'ucfirst'                 => array( 0, 'UCFIRST:' ),
+       'lc'                      => array( 0, 'LC:' ),
+       'uc'                      => array( 0, 'UC:' ),
+       'raw'                     => array( 0, 'RAW:' ),
+       'displaytitle'            => array( 1, 'DISPLAYTITLE' ),
+       'rawsuffix'               => array( 1, 'R' ),
+       'nocommafysuffix'         => array( 0, 'NOSEP' ),
+       'newsectionlink'          => array( 1, '__NEWSECTIONLINK__' ),
+       'nonewsectionlink'        => array( 1, '__NONEWSECTIONLINK__' ),
+       'currentversion'          => array( 1, 'CURRENTVERSION' ),
+       'urlencode'               => array( 0, 'URLENCODE:' ),
+       'anchorencode'            => array( 0, 'ANCHORENCODE' ),
+       'currenttimestamp'        => array( 1, 'CURRENTTIMESTAMP' ),
+       'localtimestamp'          => array( 1, 'LOCALTIMESTAMP' ),
+       'directionmark'           => array( 1, 'DIRECTIONMARK', 'DIRMARK' ),
+       'language'                => array( 0, '#LANGUAGE:' ),
+       'contentlanguage'         => array( 1, 'CONTENTLANGUAGE', 'CONTENTLANG' ),
+       'pagesinnamespace'        => array( 1, 'PAGESINNAMESPACE:', 'PAGESINNS:' ),
+       'numberofadmins'          => array( 1, 'NUMBEROFADMINS' ),
+       'formatnum'               => array( 0, 'FORMATNUM' ),
+       'padleft'                 => array( 0, 'PADLEFT' ),
+       'padright'                => array( 0, 'PADRIGHT' ),
+       'special'                 => array( 0, 'special' ),
+       'speciale'                => array( 0, 'speciale' ),
+       'defaultsort'             => array( 1, 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DEFAULTCATEGORYSORT:' ),
+       'filepath'                => array( 0, 'FILEPATH:' ),
+       'tag'                     => array( 0, 'tag' ),
+       'hiddencat'               => array( 1, '__HIDDENCAT__' ),
+       'pagesincategory'         => array( 1, 'PAGESINCATEGORY', 'PAGESINCAT' ),
+       'pagesize'                => array( 1, 'PAGESIZE' ),
+       'index'                   => array( 1, '__INDEX__' ),
+       'noindex'                 => array( 1, '__NOINDEX__' ),
+       'numberingroup'           => array( 1, 'NUMBERINGROUP', 'NUMINGROUP' ),
+       'staticredirect'          => array( 1, '__STATICREDIRECT__' ),
+       'protectionlevel'         => array( 1, 'PROTECTIONLEVEL' ),
+       'cascadingsources'        => array( 1, 'CASCADINGSOURCES' ),
+       'formatdate'              => array( 0, 'formatdate', 'dateformat' ),
+       'url_path'                => array( 0, 'PATH' ),
+       'url_wiki'                => array( 0, 'WIKI' ),
+       'url_query'               => array( 0, 'QUERY' ),
+       'defaultsort_noerror'     => array( 0, 'noerror' ),
+       'defaultsort_noreplace'   => array( 0, 'noreplace' ),
+       'displaytitle_noerror'    => array( 0, 'noerror' ),
+       'displaytitle_noreplace'  => array( 0, 'noreplace' ),
+       'pagesincategory_all'     => array( 0, 'all' ),
+       'pagesincategory_pages'   => array( 0, 'pages' ),
+       'pagesincategory_subcats' => array( 0, 'subcats' ),
+       'pagesincategory_files'   => array( 0, 'files' ),
 );
 
 /**
@@ -402,7 +406,7 @@ $specialPageAliases = array(
        'Diff'                      => array( 'Diff' ),
        'DoubleRedirects'           => array( 'DoubleRedirects' ),
        'EditWatchlist'             => array( 'EditWatchlist' ),
-       'Emailuser'                 => array( 'EmailUser' ),
+       'Emailuser'                 => array( 'EmailUser', 'Email' ),
        'ExpandTemplates'           => array( 'ExpandTemplates' ),
        'Export'                    => array( 'Export' ),
        'Fewestrevisions'           => array( 'FewestRevisions' ),
@@ -435,6 +439,7 @@ $specialPageAliases = array(
        'Mostrevisions'             => array( 'MostRevisions' ),
        'Movepage'                  => array( 'MovePage' ),
        'Mycontributions'           => array( 'MyContributions' ),
+       'MyLanguage'                => array( 'MyLanguage' ),
        'Mypage'                    => array( 'MyPage' ),
        'Mytalk'                    => array( 'MyTalk' ),
        'Myuploads'                 => array( 'MyUploads', 'MyFiles' ),
@@ -446,7 +451,7 @@ $specialPageAliases = array(
        'PermanentLink'             => array( 'PermanentLink', 'PermaLink' ),
        'Popularpages'              => array( 'PopularPages' ),
        'Preferences'               => array( 'Preferences' ),
-       'Prefixindex'               => array( 'PrefixIndex' ) ,
+       'Prefixindex'               => array( 'PrefixIndex' ),
        'Protectedpages'            => array( 'ProtectedPages' ),
        'Protectedtitles'           => array( 'ProtectedTitles' ),
        'Randompage'                => array( 'Random', 'RandomPage' ),
@@ -507,16 +512,16 @@ $linkPrefixCharset = 'a-zA-Z\\x{80}-\\x{10ffff}';
  * basis if needed.
  */
 $imageFiles = array(
-       'button-bold'     => 'button_bold.png',
-       'button-italic'   => 'button_italic.png',
-       'button-link'     => 'button_link.png',
-       'button-extlink'  => 'button_extlink.png',
-       'button-headline' => 'button_headline.png',
-       'button-image'    => 'button_image.png',
-       'button-media'    => 'button_media.png',
-       'button-nowiki'   => 'button_nowiki.png',
-       'button-sig'      => 'button_sig.png',
-       'button-hr'       => 'button_hr.png',
+       'button-bold'     => 'en/button_bold.png',
+       'button-italic'   => 'en/button_italic.png',
+       'button-link'     => 'en/button_link.png',
+       'button-extlink'  => 'en/button_extlink.png',
+       'button-headline' => 'en/button_headline.png',
+       'button-image'    => 'en/button_image.png',
+       'button-media'    => 'en/button_media.png',
+       'button-nowiki'   => 'en/button_nowiki.png',
+       'button-sig'      => 'en/button_sig.png',
+       'button-hr'       => 'en/button_hr.png',
 );
 
 /**
index 88afbe7..da3eb7a 100644 (file)
@@ -371,7 +371,7 @@ $datePreferenceMigrationMap = array(
  * overridden.
  */
 $dateFormats = array(
-    # Please be cautious not to delete the invisible RLM from the beginning of the strings.
+       # Please be cautious not to delete the invisible RLM from the beginning of the strings.
        'mdy time' => '‏H:i',
        'mdy date' => '‏n/j/Y میلادی',
        'mdy both' => '‏n/j/Y میلادی، ساعت H:i',
index ac16028..8682ab0 100644 (file)
 $fallback = 'fr';
 
 $bookstoreList = array(
-    'Amazon.fr'    => 'http://www.amazon.fr/exec/obidos/ISBN=$1',
-    'alapage.fr'   => 'http://www.alapage.com/mx/?tp=F&type=101&l_isbn=$1&donnee_appel=ALASQ&devise=&',
-    'fnac.com'     => 'http://www3.fnac.com/advanced/book.do?isbn=$1',
-    'chapitre.com' => 'http://www.chapitre.com/frame_rec.asp?isbn=$1',
+       'Amazon.fr'    => 'http://www.amazon.fr/exec/obidos/ISBN=$1',
+       'alapage.fr'   => 'http://www.alapage.com/mx/?tp=F&type=101&l_isbn=$1&donnee_appel=ALASQ&devise=&',
+       'fnac.com'     => 'http://www3.fnac.com/advanced/book.do?isbn=$1',
+       'chapitre.com' => 'http://www.chapitre.com/frame_rec.asp?isbn=$1',
 );
 
 $namespaceNames = array(
@@ -290,17 +290,17 @@ $magicWords = array(
 $linkTrail = '/^([a-zàâçéèêîœôû·’æäåāăëēïīòöōùü‘]+)(.*)$/sDu';
 
 $dateFormats = array(
-    'mdy time' => 'H:i',
-    'mdy date' => 'F j, Y',
-    'mdy both' => 'F j, Y "a" H:i',
+       'mdy time' => 'H:i',
+       'mdy date' => 'F j, Y',
+       'mdy both' => 'F j, Y "a" H:i',
 
-    'dmy time' => 'H:i',
-    'dmy date' => 'j F Y',
-    'dmy both' => 'j F Y "a" H:i',
+       'dmy time' => 'H:i',
+       'dmy date' => 'j F Y',
+       'dmy both' => 'j F Y "a" H:i',
 
-    'ymd time' => 'H:i',
-    'ymd date' => 'Y F j',
-    'ymd both' => 'Y F j "a" H:i',
+       'ymd time' => 'H:i',
+       'ymd date' => 'Y F j',
+       'ymd both' => 'Y F j "a" H:i',
 );
 
 $separatorTransformTable = array( ',' => "\xc2\xa0", '.' => ',' );
index 947e6b1..38e5b0a 100644 (file)
@@ -35,8 +35,8 @@ $namespaceAliases = array(
 );
 
 $namespaceGenderAliases = array(
-        NS_USER => array( 'male' => 'Wužiwar', 'female' => 'Wužiwarka' ),
-        NS_USER_TALK => array( 'male' => 'Diskusija_z_wužiwarjom', 'female' => 'Diskusija_z_wužiwarku' ),
+       NS_USER => array( 'male' => 'Wužiwar', 'female' => 'Wužiwarka' ),
+       NS_USER_TALK => array( 'male' => 'Diskusija_z_wužiwarjom', 'female' => 'Diskusija_z_wužiwarku' ),
 );
 
 $datePreferences = array(
index 3fcc4cc..a33efef 100644 (file)
@@ -106,8 +106,8 @@ $namespaceAliases = array(
 
        # Aliases to renamed kk-arab namespaces
        'مەدياۋيكي'        => NS_MEDIAWIKI,
-       'مەدياۋيكي_تالقىلاۋى'  => NS_MEDIAWIKI_TALK ,
-       'ٷلگٸ'        => NS_TEMPLATE ,
+       'مەدياۋيكي_تالقىلاۋى'  => NS_MEDIAWIKI_TALK,
+       'ٷلگٸ'        => NS_TEMPLATE,
        'ٷلگٸ_تالقىلاۋى'    => NS_TEMPLATE_TALK,
        'ٴۇلگٴى'              => NS_TEMPLATE,
        'ٴۇلگٴى_تالقىلاۋى'    => NS_TEMPLATE_TALK,
index 3e1b7ab..680c2ea 100644 (file)
@@ -77,8 +77,8 @@ $namespaceAliases = array(
 
        # Aliases to renamed kk-arab namespaces
        'مەدياۋيكي'        => NS_MEDIAWIKI,
-       'مەدياۋيكي_تالقىلاۋى'  => NS_MEDIAWIKI_TALK ,
-       'ٷلگٸ'        => NS_TEMPLATE ,
+       'مەدياۋيكي_تالقىلاۋى'  => NS_MEDIAWIKI_TALK,
+       'ٷلگٸ'        => NS_TEMPLATE,
        'ٷلگٸ_تالقىلاۋى'    => NS_TEMPLATE_TALK,
        'ٴۇلگٴى'              => NS_TEMPLATE,
        'ٴۇلگٴى_تالقىلاۋى'    => NS_TEMPLATE_TALK,
index 76aff5b..b7f8c6f 100644 (file)
@@ -72,8 +72,8 @@ $namespaceAliases = array(
 
        # Aliases to renamed kk-arab namespaces
        'مەدياۋيكي'        => NS_MEDIAWIKI,
-       'مەدياۋيكي_تالقىلاۋى'  => NS_MEDIAWIKI_TALK ,
-       'ٷلگٸ'        => NS_TEMPLATE ,
+       'مەدياۋيكي_تالقىلاۋى'  => NS_MEDIAWIKI_TALK,
+       'ٷلگٸ'        => NS_TEMPLATE,
        'ٷلگٸ_تالقىلاۋى'    => NS_TEMPLATE_TALK,
        'ٴۇلگٴى'              => NS_TEMPLATE,
        'ٴۇلگٴى_تالقىلاۋى'    => NS_TEMPLATE_TALK,
index 23cf2ba..e338b42 100644 (file)
@@ -104,6 +104,9 @@ $namespaceAliases = array(
 $separatorTransformTable = array( ',' => "\xc2\xa0", '.' => ',' );
 $linkTrail = '/^([äöüėëijßəğåůæœça-z]+)(.*)$/sDu';
 
+// Remove German aliases
+$namespaceGenderAliases = array();
+
 $specialPageAliases = array(
        'Activeusers'               => array( 'Aktive', 'AktiveMetmaacher', 'Aktive_Metmaacher', 'AktiveMedmaacher', 'Aktive_Medmaacher' ),
        'Allmessages'               => array( 'MediaWiki-Appachtemang' ),
@@ -206,6 +209,6 @@ $magicWords = array(
 );
 
 $imageFiles = array(
-    'button-italic'   => 'ksh/button_S_italic.png',
+       'button-italic'   => 'ksh/button_italic.png',
 );
 
index 4ae749a..8850302 100644 (file)
@@ -48,6 +48,9 @@ $namespaceAliases = array(
        'Bild_Diskussioun' => NS_FILE_TALK,
 );
 
+// Remove German aliases
+$namespaceGenderAliases = array();
+
 $specialPageAliases = array(
        'Activeusers'               => array( 'Aktiv_Benotzer' ),
        'Allmessages'               => array( 'All_Systemmessagen' ),
index d5437da..85c0c26 100644 (file)
@@ -126,9 +126,9 @@ $defaultDateFormat = 'zh';
  * overridden.
  */
 $dateFormats = array(
-        'zh time' => 'H時i分',
-        'zh date' => 'Y年n月j日 (l)',
-        'zh both' => 'Y年n月j日 (D) H時i分',
+       'zh time' => 'H時i分',
+       'zh date' => 'Y年n月j日 (l)',
+       'zh both' => 'Y年n月j日 (D) H時i分',
 );
 
 $digitTransformTable = array(
index 3397894..e66cb02 100644 (file)
@@ -131,6 +131,9 @@ $dateFormats = array(
        'ymd both' => 'H:i, Y M j.',
 );
 
+// Remove German aliases
+$namespaceGenderAliases = array();
+
 $specialPageAliases = array(
        'Allmessages'               => array( 'Systemnarichten' ),
        'Allpages'                  => array( 'Alle Sieden' ),
index fdb33e4..49268f6 100644 (file)
@@ -70,7 +70,7 @@ $dateFormats = array(
 );
 
 $bookstoreList = array(
-        'Koninklijke Bibliotheek' => 'http://opc4.kb.nl/DB=1/SET=5/TTL=1/CMD?ACT=SRCH&IKT=1007&SRT=RLV&TRM=$1'
+       'Koninklijke Bibliotheek' => 'http://opc4.kb.nl/DB=1/SET=5/TTL=1/CMD?ACT=SRCH&IKT=1007&SRT=RLV&TRM=$1'
 );
 
 #!!# Translation <b>HLEERSTE:</b> is used more than once for <a href="#mw-sp-magic-lcfirst">lcfirst</a> and <a href="#mw-sp-magic-ucfirst">ucfirst</a>.
index 5eaccf6..3c65610 100644 (file)
@@ -180,5 +180,5 @@ $magicWords = array(
 );
 
 $linkTrail = '/^((?:[a-z]|а|æ|б|в|г|д|е|ё|ж|з|и|й|к|л|м|н|о|п|р|с|т|у|ф|х|ц|ч|ш|щ|ъ|ы|ь|э|ю|я|“|»)+)(.*)$/sDu';
-$fallback8bitEncoding =  'windows-1251';
+$fallback8bitEncoding = 'windows-1251';
 
index 5c835dc..8b7916f 100644 (file)
@@ -50,6 +50,9 @@ $namespaceAliases = array(
        'Kategorie_Diskussion' => NS_CATEGORY_TALK,
 );
 
+// Remove German aliases
+$namespaceGenderAliases = array();
+
 $specialPageAliases = array(
        'Listadmins'                => array( 'Verwalter', 'Administratoren' ),
        'Listbots'                  => array( 'Waddefresser', 'Bots' ),
index c0832fd..edba76a 100644 (file)
@@ -58,3 +58,6 @@ $namespaceAliases = array(
        'Kadegorie_Dischbediere' => NS_CATEGORY_TALK,
 );
 
+// Remove German aliases
+$namespaceGenderAliases = array();
+
index 9098d85..a96b766 100644 (file)
@@ -433,9 +433,9 @@ $fallback8bitEncoding = 'windows-1251';
 $linkPrefixExtension = false;
 
 $imageFiles = array(
-       'button-bold'   => 'cyrl/button_bold.png',
-       'button-italic' => 'cyrl/button_italic.png',
-       'button-link'   => 'cyrl/button_link.png',
+       'button-bold'   => 'ru/button_bold.png',
+       'button-italic' => 'ru/button_italic.png',
+       'button-link'   => 'ru/button_link.png',
 );
 
 $linkTrail = '/^([a-zабвгдеёжзийклмнопрстуфхцчшщъыьэюя]+)(.*)$/sDu';
index 017b4d0..839a5de 100644 (file)
@@ -51,7 +51,7 @@ $namespaceNames = array(
 );
 
 $namespaceAliases = array(
-        # Aliases for Latin script namespaces
+       # Aliases for Latin script namespaces
        "Medija"                  => NS_MEDIA,
        "Posebno"                 => NS_SPECIAL,
        "Razgovor"                => NS_TALK,
index b359c26..0d64526 100644 (file)
@@ -304,7 +304,7 @@ $magicWords = array(
 );
 
 $linkTrail = '/^([a-zåäöéÅÄÖÉ]+)(.*)$/sDu';
-$separatorTransformTable =  array(
+$separatorTransformTable = array(
        ',' => "\xc2\xa0", // @bug 2749
        '.' => ','
 );
index bc26d31..49a8891 100644 (file)
@@ -34,18 +34,18 @@ $datePreferences = false;
 $defaultDateFormat = 'dmy';
 
 $dateFormats = array(
-        'mdy time' => 'H:i',
-        'mdy date' => 'M j, Y',
-        'mdy both' => 'H:i, M j, Y',
-        'dmy time' => 'H:i',
-        'dmy date' => 'j M Y',
-        'dmy both' => 'j M Y, H:i',
-        'ymd time' => 'H:i',
-        'ymd date' => 'Y M j',
-        'ymd both' => 'H:i, Y M j',
-        'ISO 8601 time' => 'xnH:xni:xns',
-        'ISO 8601 date' => 'xnY-xnm-xnd',
-        'ISO 8601 both' => 'xnY-xnm-xnd"T"xnH:xni:xns',
+       'mdy time' => 'H:i',
+       'mdy date' => 'M j, Y',
+       'mdy both' => 'H:i, M j, Y',
+       'dmy time' => 'H:i',
+       'dmy date' => 'j M Y',
+       'dmy both' => 'j M Y, H:i',
+       'ymd time' => 'H:i',
+       'ymd date' => 'Y M j',
+       'ymd both' => 'H:i, Y M j',
+       'ISO 8601 time' => 'xnH:xni:xns',
+       'ISO 8601 date' => 'xnY-xnm-xnd',
+       'ISO 8601 both' => 'xnY-xnm-xnd"T"xnH:xni:xns',
 );
 
 $namespaceNames = array(
index 09b5590..8846f79 100644 (file)
@@ -45,18 +45,18 @@ $datePreferences = false;
 $defaultDateFormat = 'dmy';
 
 $dateFormats = array(
-        'mdy time' => 'H:i',
-        'mdy date' => 'M j, Y',
-        'mdy both' => 'H:i, M j, Y',
-        'dmy time' => 'H:i',
-        'dmy date' => 'j M Y',
-        'dmy both' => 'j M Y, H:i',
-        'ymd time' => 'H:i',
-        'ymd date' => 'Y M j',
-        'ymd both' => 'H:i, Y M j',
-        'ISO 8601 time' => 'xnH:xni:xns',
-        'ISO 8601 date' => 'xnY-xnm-xnd',
-        'ISO 8601 both' => 'xnY-xnm-xnd"T"xnH:xni:xns',
+       'mdy time' => 'H:i',
+       'mdy date' => 'M j, Y',
+       'mdy both' => 'H:i, M j, Y',
+       'dmy time' => 'H:i',
+       'dmy date' => 'j M Y',
+       'dmy both' => 'j M Y, H:i',
+       'ymd time' => 'H:i',
+       'ymd date' => 'Y M j',
+       'ymd both' => 'H:i, Y M j',
+       'ISO 8601 time' => 'xnH:xni:xns',
+       'ISO 8601 date' => 'xnY-xnm-xnd',
+       'ISO 8601 both' => 'xnY-xnm-xnd"T"xnH:xni:xns',
 );
 
 $magicWords = array(
index 2ec847b..494951f 100644 (file)
@@ -59,3 +59,6 @@ $specialPageAliases = array(
        'Watchlist'                 => array( 'Bäoobôchdungslisdâ' ),
 );
 
+// Remove German aliases
+$namespaceGenderAliases = array();
+
index c9ea0f9..2eabcab 100644 (file)
@@ -102,6 +102,7 @@ class CLDRPluralRuleConverter {
 
        /**
         * Private constructor.
+        * @param string $rule
         */
        protected function __construct( $rule ) {
                $this->rule = $rule;
@@ -313,6 +314,7 @@ class CLDRPluralRuleConverter {
 
        /**
         * Throw an error
+        * @param string $message
         */
        protected function error( $message ) {
                throw new CLDRPluralRuleError( $message );
index 1790f48..655f309 100644 (file)
--- a/load.php
+++ b/load.php
@@ -23,7 +23,7 @@
  */
 
 // Bail if PHP is too low
-if ( !function_exists( 'version_compare' ) || version_compare( phpversion(), '5.3.2' ) < 0 ) {
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
        // We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
        require dirname( __FILE__ ) . '/includes/PHPVersionError.php';
        wfPHPVersionError( 'load.php' );
@@ -39,7 +39,9 @@ if ( !$wgRequest->checkUrlExtension() ) {
 }
 
 // Respond to resource loading request
-$resourceLoader = new ResourceLoader();
+$resourceLoader = new ResourceLoader(
+       ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+);
 $resourceLoader->respond( new ResourceLoaderContext( $resourceLoader, $wgRequest ) );
 
 wfProfileOut( 'load.php' );
index ffb07eb..8d30df4 100644 (file)
@@ -113,6 +113,13 @@ abstract class Maintenance {
         */
        public $fileHandle;
 
+       /**
+        * Accessible via getConfig()
+        *
+        * @var Config
+        */
+       private $config;
+
        /**
         * Default constructor. Children should call this *first* if implementing
         * their own constructors
@@ -457,6 +464,26 @@ abstract class Maintenance {
                $this->mDependantParameters = array_diff_key( $this->mParams, $this->mGenericParameters );
        }
 
+       /**
+        * @since 1.24
+        * @return Config
+        */
+       public function getConfig() {
+               if ( $this->config === null ) {
+                       $this->config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               }
+
+               return $this->config;
+       }
+
+       /**
+        * @since 1.24
+        * @param Config $config
+        */
+       public function setConfig( Config $config ) {
+               $this->config = $config;
+       }
+
        /**
         * Run a child maintenance script. Pass all of the current arguments
         * to it.
index 5cb6f5f..30bb6ad 100644 (file)
@@ -51,7 +51,7 @@ installations.
        edit.php
        Edit a page to change its content
 
-       findhooks.php
+       findHooks.php
        Find hooks that aren't documented in docs/hooks.txt
 
        importDump.php
@@ -60,9 +60,6 @@ installations.
        importImages.php
        Import images into the wiki
 
-       importTextFile.php
-       Import the contents of a text file into a wiki page
-
        moveBatch.php
        Move a batch of pages
 
diff --git a/maintenance/archives/patch-fa_major_mime-chemical.sql b/maintenance/archives/patch-fa_major_mime-chemical.sql
new file mode 100644 (file)
index 0000000..be9b0ff
--- /dev/null
@@ -0,0 +1,3 @@
+ALTER TABLE /*$wgDBprefix*/filearchive
+  CHANGE  fa_major_mime fa_major_mime ENUM('unknown','application','audio','image','text','video','message','model','multipart','chemical');
+
index c87c959..2d698f6 100644 (file)
@@ -6,4 +6,4 @@
 
 CREATE TABLE /*$wgDBprefix*/hitcounter (
   hc_id INTEGER UNSIGNED NOT NULL
-) ENGINE=HEAP MAX_ROWS=25000;
+) ENGINE=MEMORY MAX_ROWS=25000;
diff --git a/maintenance/archives/patch-il_from_namespace.sql b/maintenance/archives/patch-il_from_namespace.sql
new file mode 100644 (file)
index 0000000..4c858f4
--- /dev/null
@@ -0,0 +1,4 @@
+ALTER TABLE /*_*/imagelinks
+  ADD COLUMN il_from_namespace int NOT NULL default 0;
+
+CREATE INDEX /*i*/il_backlinks_namespace ON /*_*/imagelinks (il_to,il_from_namespace,il_from);
\ No newline at end of file
diff --git a/maintenance/archives/patch-img_major_mime-chemical.sql b/maintenance/archives/patch-img_major_mime-chemical.sql
new file mode 100644 (file)
index 0000000..4bde446
--- /dev/null
@@ -0,0 +1,3 @@
+ALTER TABLE /*$wgDBprefix*/image
+  CHANGE  img_major_mime img_major_mime ENUM('unknown','application','audio','image','text','video','message','model','multipart','chemical');
+
index bd348c4..8d9426e 100644 (file)
@@ -1,4 +1,4 @@
--- Add indexes to the mime types in image for use on Special:MIMEsearch,
+-- Add indexes to the MIME types in image for use on Special:MIMEsearch,
 -- changes a query like
 --
 -- SELECT img_name FROM image WHERE img_major_mime = "image" AND img_minor_mime = "svg";
diff --git a/maintenance/archives/patch-oi_major_mime-chemical.sql b/maintenance/archives/patch-oi_major_mime-chemical.sql
new file mode 100644 (file)
index 0000000..e3b4552
--- /dev/null
@@ -0,0 +1,3 @@
+ALTER TABLE /*$wgDBprefix*/oldimage
+  CHANGE  oi_major_mime oi_major_mime ENUM('unknown','application','audio','image','text','video','message','model','multipart','chemical');
+
diff --git a/maintenance/archives/patch-pl_from_namespace.sql b/maintenance/archives/patch-pl_from_namespace.sql
new file mode 100644 (file)
index 0000000..2f7ff04
--- /dev/null
@@ -0,0 +1,4 @@
+ALTER TABLE /*_*/pagelinks
+       ADD COLUMN pl_from_namespace int NOT NULL default 0;
+
+CREATE INDEX /*i*/pl_backlinks_namespace ON /*_*/pagelinks (pl_namespace,pl_title,pl_from_namespace,pl_from);
index 0a0e4e1..6ad1622 100644 (file)
@@ -7,6 +7,6 @@ CREATE TABLE /*_*/profiling (
   pf_memory float NOT NULL default 0,
   pf_name varchar(255) NOT NULL default '',
   pf_server varchar(30) NOT NULL default ''
-) ENGINE=HEAP;
+) ENGINE=MEMORY;
 
 CREATE UNIQUE INDEX /*i*/pf_name_server ON /*_*/profiling (pf_name, pf_server);
\ No newline at end of file
diff --git a/maintenance/archives/patch-restructure.sql b/maintenance/archives/patch-restructure.sql
deleted file mode 100644 (file)
index a5bc3e5..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
--- The Great Restructuring of October 2004
--- Creates 'page', 'revision' tables and transforms the classic
--- cur+old into a separate page+revision+text structure.
---
--- The pre-conversion 'old' table is renamed to 'text' and used
--- without internal restructuring to avoid rebuilding the entire
--- table. (This can be done separately if desired.)
---
--- The pre-conversion 'cur' table is now redundant and can be
--- discarded when done.
-
-CREATE TABLE /*$wgDBprefix*/page (
-  page_id int unsigned NOT NULL auto_increment,
-  page_namespace tinyint NOT NULL,
-  page_title varchar(255) binary NOT NULL,
-  page_restrictions tinyblob NOT NULL,
-  page_counter bigint unsigned NOT NULL default '0',
-  page_is_redirect tinyint unsigned NOT NULL default '0',
-  page_is_new tinyint unsigned NOT NULL default '0',
-  page_random real unsigned NOT NULL,
-  page_touched binary(14) NOT NULL default '',
-  page_latest int unsigned NOT NULL,
-  page_len int unsigned NOT NULL,
-
-  PRIMARY KEY page_id (page_id),
-  UNIQUE INDEX name_title (page_namespace,page_title),
-  INDEX (page_random),
-  INDEX (page_len)
-);
-
-CREATE TABLE /*$wgDBprefix*/revision (
-  rev_id int unsigned NOT NULL auto_increment,
-  rev_page int unsigned NOT NULL,
-  rev_comment tinyblob NOT NULL,
-  rev_user int unsigned NOT NULL default '0',
-  rev_user_text varchar(255) binary NOT NULL default '',
-  rev_timestamp binary(14) NOT NULL default '',
-  rev_minor_edit tinyint unsigned NOT NULL default '0',
-  rev_deleted tinyint unsigned NOT NULL default '0',
-
-  PRIMARY KEY rev_page_id (rev_page, rev_id),
-  UNIQUE INDEX rev_id (rev_id),
-  INDEX rev_timestamp (rev_timestamp),
-  INDEX page_timestamp (rev_page,rev_timestamp),
-  INDEX user_timestamp (rev_user,rev_timestamp),
-  INDEX usertext_timestamp (rev_user_text,rev_timestamp)
-);
-
--- If creating new 'text' table it would look like this:
---
--- CREATE TABLE /*$wgDBprefix*/text (
---   old_id int(8) unsigned NOT NULL auto_increment,
---   old_text mediumtext NOT NULL,
---   old_flags tinyblob NOT NULL,
---
---   PRIMARY KEY old_id (old_id)
--- );
-
-
--- Lock!
-LOCK TABLES /*$wgDBprefix*/page WRITE, /*$wgDBprefix*/revision WRITE, /*$wgDBprefix*/old WRITE, /*$wgDBprefix*/cur WRITE;
-
--- Save the last old_id value for later
-SELECT (@maxold:=MAX(old_id)) FROM /*$wgDBprefix*/old;
-
--- First, copy all current entries into the old table.
-INSERT
-  INTO /*$wgDBprefix*/old
-    (old_namespace,
-    old_title,
-    old_text,
-    old_comment,
-    old_user,
-    old_user_text,
-    old_timestamp,
-    old_minor_edit,
-    old_flags)
-  SELECT
-    cur_namespace,
-    cur_title,
-    cur_text,
-    cur_comment,
-    cur_user,
-    cur_user_text,
-    cur_timestamp,
-    cur_minor_edit,
-    ''
-  FROM /*$wgDBprefix*/cur;
-
--- Now, copy all old data except the text into revisions
-INSERT
-  INTO /*$wgDBprefix*/revision
-    (rev_id,
-    rev_page,
-    rev_comment,
-    rev_user,
-    rev_user_text,
-    rev_timestamp,
-    rev_minor_edit)
-  SELECT
-    old_id,
-    cur_id,
-    old_comment,
-    old_user,
-    old_user_text,
-    old_timestamp,
-    old_minor_edit
-  FROM /*$wgDBprefix*/old,/*$wgDBprefix*/cur
-  WHERE old_namespace=cur_namespace
-    AND old_title=cur_title;
-
--- And, copy the cur data into page
-INSERT
-  INTO /*$wgDBprefix*/page
-    (page_id,
-    page_namespace,
-    page_title,
-    page_restrictions,
-    page_counter,
-    page_is_redirect,
-    page_is_new,
-    page_random,
-    page_touched,
-    page_latest)
-  SELECT
-    cur_id,
-    cur_namespace,
-    cur_title,
-    cur_restrictions,
-    cur_counter,
-    cur_is_redirect,
-    cur_is_new,
-    cur_random,
-    cur_touched,
-    rev_id
-  FROM /*$wgDBprefix*/cur,/*$wgDBprefix*/revision
-  WHERE cur_id=rev_page
-    AND rev_timestamp=cur_timestamp
-    AND rev_id > @maxold;
-
-UNLOCK TABLES;
-
--- Keep the old table around as the text store.
--- Its extra fields will be ignored, but trimming them is slow
--- so we won't bother doing it for now.
-ALTER TABLE /*$wgDBprefix*/old RENAME TO /*$wgDBprefix*/text;
diff --git a/maintenance/archives/patch-tl_from_namespace.sql b/maintenance/archives/patch-tl_from_namespace.sql
new file mode 100644 (file)
index 0000000..8d6c76b
--- /dev/null
@@ -0,0 +1,4 @@
+ALTER TABLE /*_*/templatelinks
+       ADD COLUMN tl_from_namespace int NOT NULL default 0;
+
+CREATE INDEX /*i*/tl_backlinks_namespace ON /*_*/templatelinks (tl_namespace,tl_title,tl_from_namespace,tl_from);
index 9ac204d..aeadc93 100644 (file)
@@ -125,6 +125,8 @@ EOT;
 
        /**
         * Copy all rows from $srcTable to $dstTable
+        * @param string $srcTable
+        * @param string $dstTable
         */
        function sync( $srcTable, $dstTable ) {
                $batchSize = 1000;
index 7fca377..5f77637 100644 (file)
@@ -343,6 +343,7 @@ class TextPassDumper extends BackupDumper {
 
        /**
         * @throws MWException Failure to parse XML input
+        * @param string $input
         * @return bool
         */
        function readDump( $input ) {
index b81f9fd..ce38dad 100644 (file)
@@ -41,7 +41,10 @@ class BenchmarkParse extends Maintenance {
                parent::__construct();
                $this->addDescription( 'Benchmark parse operation' );
                $this->addArg( 'title', 'The name of the page to parse' );
-               $this->addOption( 'cold', 'Don\'t repeat the parse operation to warm the cache' );
+               $this->addOption( 'warmup', 'Repeat the parse operation this number of times to warm the cache',
+                       false, true );
+               $this->addOption( 'loops', 'Number of times to repeat parse operation post-warmup',
+                       false, true );
                $this->addOption( 'page-time',
                        'Use the version of the page which was current at the given time',
                        false, true );
@@ -81,22 +84,30 @@ class BenchmarkParse extends Maintenance {
                        exit( 1 );
                }
 
-               if ( !$this->hasOption( 'cold' ) ) {
+               $warmup = $this->getOption( 'warmup', 1 );
+               for ( $i = 0; $i < $warmup; $i++ ) {
                        $this->runParser( $revision );
                }
 
+               $loops = $this->getOption( 'loops', 1 );
+               if ( $loops < 1 ) {
+                       $this->error( 'Invalid number of loops specified', true );
+               }
                $startUsage = getrusage();
                $startTime = microtime( true );
-               $this->runParser( $revision );
+               for ( $i = 0; $i < $loops; $i++ ) {
+                       $this->runParser( $revision );
+               }
                $endUsage = getrusage();
                $endTime = microtime( true );
 
                printf( "CPU time = %.3f s, wall clock time = %.3f s\n",
                        // CPU time
-                       $endUsage['ru_utime.tv_sec'] + $endUsage['ru_utime.tv_usec'] * 1e-6
-                       - $startUsage['ru_utime.tv_sec'] - $startUsage['ru_utime.tv_usec'] * 1e-6,
+                       $endUsage['ru_utime.tv_sec'] + $endUsage['ru_utime.tv_usec'] * 1e-6
+                       - $startUsage['ru_utime.tv_sec'] - $startUsage['ru_utime.tv_usec'] * 1e-6 ) / $loops,
                        // Wall clock time
-                       $endTime - $startTime );
+                       ( $endTime - $startTime ) / $loops
+               );
        }
 
        /**
index 6ef4909..d1c2edd 100644 (file)
@@ -345,7 +345,6 @@ class CheckSyntax extends Maintenance {
         * or pointless ?> closing tags at the end.
         *
         * @param string $file String Path to a file to check for errors
-        * @return bool
         */
        private function checkForMistakes( $file ) {
                foreach ( $this->mNoStyleCheckPaths as $regex ) {
index cc8b024..e1d0ed6 100644 (file)
@@ -47,7 +47,7 @@ class CleanupRemovedModules extends Maintenance {
 
        public function execute() {
                $dbw = wfGetDB( DB_MASTER );
-               $rl = new ResourceLoader();
+               $rl = new ResourceLoader( ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
                $moduleNames = $rl->getModuleNames();
                $moduleList = implode( ', ', array_map( array( $dbw, 'addQuotes' ), $moduleNames ) );
                $limit = max( 1, intval( $this->getOption( 'batchsize', 500 ) ) );
index 72b6aa5..0df9e7f 100644 (file)
@@ -148,9 +148,15 @@ class TitleCleanup extends TableCleanup {
                                $ns = 0;
                        }
 
+                       # Namespace which no longer exists. Put the page in the main namespace
+                       # since we don't have any idea of the old namespace name. See bug 68501.
+                       if ( !MWNamespace::exists( $ns ) ) {
+                               $ns = 0;
+                       }
+
                        $clean = 'Broken/' . $prior;
                        $verified = Title::makeTitleSafe( $ns, $clean );
-                       if ( $verified->exists() ) {
+                       if ( !$verified || $verified->exists() ) {
                                $blah = "Broken/id:" . $row->page_id;
                                $this->output( "Couldn't legalize; form '$clean' exists; using '$blah'\n" );
                                $verified = Title::makeTitleSafe( $ns, $blah );
index 0d3e643..88776f4 100644 (file)
@@ -43,6 +43,7 @@ class CommandLineInc extends Maintenance {
 
        /**
         * No help, it would just be misleading since it misses custom options
+        * @param bool $force
         */
        protected function maybeHelp( $force = false ) {
                if ( !$force ) {
index 93fe660..98441b6 100644 (file)
@@ -79,7 +79,7 @@ class CompareParserCache extends Maintenance {
 
                                $this->output( "Found cache entry found for '{$title->getPrefixedText()}'..." );
                                $oldHtml = trim( preg_replace( '#<!-- .+-->#Us', '', $parserOutputOld->getText() ) );
-                               $newHtml = trim( preg_replace( '#<!-- .+-->#Us', '',$parserOutputNew->getText() ) );
+                               $newHtml = trim( preg_replace( '#<!-- .+-->#Us', '', $parserOutputNew->getText() ) );
                                $diff = wfDiff( $oldHtml, $newHtml );
                                if ( strlen( $diff ) ) {
                                        $this->output( "differences found:\n\n$diff\n\n" );
index 11a81eb..221ebe3 100644 (file)
@@ -140,7 +140,7 @@ class ConvertLinks extends Maintenance {
                                        $this->logPerformance = false;
                                }
                        }
-                       $baseTime = $startTime = $this->getMicroTime();
+                       $baseTime = $startTime = microtime( true );
                        # Create a title -> cur_id map
                        $this->output( "Loading IDs from $cur table...\n" );
                        $this->performanceLog( $fh, "Reading $numRows rows from cur table...\n" );
@@ -161,7 +161,7 @@ class ConvertLinks extends Maintenance {
                                        if ( ( $curRowsRead % $curReadReportInterval ) == 0 ) {
                                                $this->performanceLog(
                                                        $fh,
-                                                       $curRowsRead . " " . ( $this->getMicroTime() - $baseTime ) . "\n"
+                                                       $curRowsRead . " " . ( microtime( true ) - $baseTime ) . "\n"
                                                );
                                                $this->output( "\t$curRowsRead rows of $cur table read.\n" );
                                        }
@@ -172,7 +172,7 @@ class ConvertLinks extends Maintenance {
                        $this->output( "Finished loading IDs.\n\n" );
                        $this->performanceLog(
                                $fh,
-                               "Took " . ( $this->getMicroTime() - $baseTime ) . " seconds to load IDs.\n\n"
+                               "Took " . ( microtime( true ) - $baseTime ) . " seconds to load IDs.\n\n"
                        );
 
                        # --------------------------------------------------------------------
@@ -181,7 +181,7 @@ class ConvertLinks extends Maintenance {
                        # convert, and write to the new table.
                        $this->createTempTable();
                        $this->performanceLog( $fh, "Resetting timer.\n\n" );
-                       $baseTime = $this->getMicroTime();
+                       $baseTime = microtime( true );
                        $this->output( "Processing $numRows rows from $links table...\n" );
                        $this->performanceLog( $fh, "Processing $numRows rows from $links table...\n" );
                        $this->performanceLog( $fh, "rows inserted vs seconds elapsed:\n" );
@@ -226,7 +226,7 @@ class ConvertLinks extends Maintenance {
                                                $this->output( " done. Total $totalTuplesInserted tuples inserted.\n" );
                                                $this->performanceLog(
                                                        $fh,
-                                                       $totalTuplesInserted . " " . ( $this->getMicroTime() - $baseTime ) . "\n"
+                                                       $totalTuplesInserted . " " . ( microtime( true ) - $baseTime ) . "\n"
                                                );
                                        }
                                }
@@ -239,7 +239,7 @@ class ConvertLinks extends Maintenance {
                        );
                        $this->performanceLog(
                                $fh,
-                               "Total execution time: " . ( $this->getMicroTime() - $startTime ) . " seconds.\n"
+                               "Total execution time: " . ( microtime( true ) - $startTime ) . " seconds.\n"
                        );
                        if ( $this->logPerformance ) {
                                fclose( $fh );
@@ -300,12 +300,6 @@ class ConvertLinks extends Maintenance {
                        fwrite( $fh, $text );
                }
        }
-
-       private function getMicroTime() { # return time in seconds, with microsecond accuracy
-               list( $usec, $sec ) = explode( " ", microtime() );
-
-               return ( (float)$usec + (float)$sec );
-       }
 }
 
 $maintClass = "ConvertLinks";
index a07cbc2..dbe9698 100644 (file)
@@ -30,15 +30,18 @@ require_once __DIR__ . '/Maintenance.php';
 class DeleteEqualMessages extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Deletes all pages in the MediaWiki namespace that are equal to the default message";
+               $this->mDescription = 'Deletes all pages in the MediaWiki namespace that are equal to '
+                       . 'the default message';
                $this->addOption( 'delete', 'Actually delete the pages (default: dry run)' );
                $this->addOption( 'delete-talk', 'Don\'t leave orphaned talk pages behind during deletion' );
-               $this->addOption( 'lang-code', 'Check for subpages of this language code (default: root page against content language). ' .
-                       'Use value "*" to run for all mwfile language code subpages (including the base pages that override content language).', false, true );
+               $this->addOption( 'lang-code', 'Check for subpages of this language code (default: root '
+                       . 'page against content language). Use value "*" to run for all mwfile language code '
+                       . 'subpages (including the base pages that override content language).', false, true );
        }
 
        /**
         * @param string|bool $langCode See --lang-code option.
+        * @param array &$messageInfo
         */
        protected function fetchMessageInfo( $langCode, array &$messageInfo ) {
                global $wgContLang;
@@ -59,7 +62,8 @@ class DeleteEqualMessages extends Maintenance {
                // Normalise message names for NS_MEDIAWIKI page_title
                $messageNames = array_map( array( $wgContLang, 'ucfirst' ), $messageNames );
 
-               $statuses = AllMessagesTablePager::getCustomisedStatuses( $messageNames, $langCode, $nonContLang );
+               $statuses = AllMessagesTablePager::getCustomisedStatuses(
+                       $messageNames, $langCode, $nonContLang );
                // getCustomisedStatuses is stripping the sub page from the page titles, add it back
                $titleSuffix = $nonContLang ? "/$langCode" : '';
 
@@ -134,8 +138,10 @@ class DeleteEqualMessages extends Maintenance {
                        return;
                }
 
-               $this->output( "\n{$messageInfo['relevantPages']} pages in the MediaWiki namespace override messages." );
-               $this->output( "\n{$messageInfo['equalPages']} pages are equal to the default message (+ {$messageInfo['equalPagesTalks']} talk pages).\n" );
+               $this->output( "\n{$messageInfo['relevantPages']} pages in the MediaWiki namespace "
+                       . "override messages." );
+               $this->output( "\n{$messageInfo['equalPages']} pages are equal to the default message "
+                       . "(+ {$messageInfo['equalPagesTalks']} talk pages).\n" );
 
                if ( !$doDelete ) {
                        $list = '';
@@ -182,7 +188,8 @@ class DeleteEqualMessages extends Maintenance {
                                $this->output( "\n* [[$title]]" );
                                $page = WikiPage::factory( $title );
                                $error = ''; // Passed by ref
-                               $page->doDeleteArticle( 'Orphaned talk page of no longer required message', false, 0, false, $error, $user );
+                               $page->doDeleteArticle( 'Orphaned talk page of no longer required message',
+                                       false, 0, false, $error, $user );
                        }
                }
                $this->output( "\n\ndone!\n" );
index 246d6fc..0a65e31 100644 (file)
@@ -80,7 +80,7 @@ if ( !$mime ) {
        }
 }
 if ( $mime ) {
-       # Use custom handling to serve files with a known mime type
+       # Use custom handling to serve files with a known MIME type
        # This way we can serve things like .svg files that the built-in
        # PHP webserver doesn't understand.
        # ;) Nicely enough we just happen to bundle a mime.types file
index f555113..df8a34c 100644 (file)
@@ -1,10 +1,10 @@
-ænglisc
-ævar
 &add
 &amp
 &bar
+&img
 &sim
 &url
+&wap
 ABNF
 API
 Aacute
@@ -366,6 +366,7 @@ abusive
 ac
 acad
 accel
+acceptbilling
 acceptlang
 accessdenied
 accesskey
@@ -430,6 +431,8 @@ ai
 aifc
 aiff
 aiprop
+airtel
+aisort
 ajaxwatch
 al
 alefsym
@@ -441,6 +444,7 @@ allcategories
 alldata
 alle
 allexamples
+allfileusages
 allhidden
 allimages
 allimit
@@ -458,6 +462,8 @@ allpagesbadtitle
 allpagesprefix
 allpagesredirect
 allpagessubmit
+allpartners
+allredirects
 allrev
 alltitles
 alltransclusions
@@ -470,11 +476,13 @@ alreadyexists
 alreadyrolled
 alunique
 am
+analyticsconfig
 anchor
 anchorclose
 anchorencode
 and
 andconvert
+andreescu
 andtitle
 anon
 anoneditwarning
@@ -654,6 +662,7 @@ badversion
 balancer
 balancers
 banjar
+barebone
 barstein
 base
 basefont
@@ -683,6 +692,7 @@ bgcolor
 bgzip
 bidi
 bigdelete
+bingbot
 binhex
 bitdepth
 bitfield
@@ -740,11 +750,13 @@ bmwschema
 bmysql
 bname
 bodycontent
+bogo
 boldening
 bolding
 booksources
 bool
 boolean
+bordercolor
 borderhack
 bot
 botedit
@@ -829,12 +841,14 @@ capitalizeallnouns
 captchaid
 captchas
 captchaword
+carriersnoips
 cascade
 cascadeable
 cascadeon
 cascadeprotected
 cascadeprotectedwarning
 cascading
+cascadinglevels
 cascadingness
 categories
 categories's
@@ -848,6 +862,7 @@ categorypage
 categoryviewer
 catids
 catlinks
+catmsg
 catpage
 catrope
 cattitles
@@ -861,6 +876,7 @@ cedil
 ceebc
 cellpadding
 cellspacing
+cellulant
 central
 centralauth
 centralnotice
@@ -1067,6 +1083,7 @@ danga
 danielc
 darr
 datalen
+datapath
 dataset
 datasets
 datasize
@@ -1107,6 +1124,7 @@ defaultcontentmodel
 defaultmessagetext
 defaultmissing
 defaultns
+defaultoptions
 defaultsort
 defaultval
 deferr
@@ -1167,6 +1185,7 @@ devangari
 devel
 df
 dflt
+dflts
 dhtml
 diams
 didn
@@ -1233,6 +1252,7 @@ domainpart
 domainparts
 domas
 doms
+dont
 dotdotcount
 dotm
 dotsc
@@ -1250,6 +1270,7 @@ dropdown
 dump
 dumpfm
 dupfunc
+dupl
 duplicatefiles
 duplicatesoffile
 dvips
@@ -1317,7 +1338,9 @@ eimissingparam
 eititle
 el
 elapsedreal
+elastica
 elemname
+elems
 elink
 eltitle
 email
@@ -1380,6 +1403,7 @@ epcampus
 epcoordinator
 epinstructor
 eponline
+eqiad
 erevoke
 errno
 error
@@ -1436,6 +1460,7 @@ externaldberror
 externaldiff
 externaledit
 externaleditor
+externalimages
 externallinks
 externalstore
 extet
@@ -1445,6 +1470,7 @@ extlinks
 extracts
 extradata
 extrafields
+extralanglink
 extraq
 extratags
 exturlusage
@@ -1515,6 +1541,7 @@ filepage
 filepath
 filerenameerror
 filerepo
+filerepoinfo
 filerevert
 filerevisions
 files
@@ -1553,6 +1580,7 @@ flagtype
 flatlist
 flds
 float
+flrevs
 fmttime
 fname
 fnof
@@ -1571,6 +1599,7 @@ forcebot
 forceditsummary
 forceeditsummary
 forcelinkupdate
+forcerecursivelinkupdate
 forcetoc
 forcontent
 formaction
@@ -1588,6 +1617,7 @@ found
 founder
 fr
 frac
+frameborder
 frameless
 framesets
 frasl
@@ -1624,12 +1654,15 @@ gadgetcategories
 gadgets
 gaid
 gaifilterredir
+gaifrom
 gallerybox
 gallerycaption
 gallerytext
 gapdir
 gapfilterredir
+gapfrom
 gaplimit
+gapnamespace
 gapprefix
 garber
 gblblock
@@ -1643,8 +1676,10 @@ general
 generatexml
 generator
 geocoordinate
+geodata
 geosearch
 gerrit
+geshi
 getcookie
 getenv
 getheader
@@ -1681,6 +1716,7 @@ globe
 gmail
 gmdate
 goodtitle
+googlebot
 gopher
 graymap
 grayscale
@@ -1777,8 +1813,8 @@ hit
 hitcount
 hitcounter
 hits
+hlist
 hmac
-hmtl
 hobby
 homelink
 hookaborted
@@ -1842,9 +1878,11 @@ ilfrom
 ilto
 im
 image
+imagecolorallocate
 imagegetsize
 imageinfo
 imageinvalidfilename
+imagelimits
 imagelinks
 imagemagick
 imagemaxsize
@@ -1857,6 +1895,7 @@ imagesize
 imagetype
 imagetypemismatch
 imageusage
+imagewhitelistenabled
 imagick
 imgmultigo
 imgmultigoto
@@ -1928,6 +1967,7 @@ interwiki
 interwikimap
 interwikipage
 interwikis
+interwikisearchinfo
 interwikisource
 intnull
 intoken
@@ -1975,6 +2015,8 @@ ipchain
 ipedits
 iphash
 ipinrange
+ipset
+ipsets
 ipusers
 iquest
 irc
@@ -1986,12 +2028,14 @@ isconnected
 iscur
 isin
 isip
+islocal
 ismap
 isminor
 ismodsince
 ismulti
 isnew
 ispermalink
+isroot
 isself
 isset
 istainted
@@ -2019,6 +2063,7 @@ iwltitle
 iwprefix
 iwtitle
 iwurl
+ized
 javascript
 javascripttest
 jbartsh
@@ -2037,6 +2082,7 @@ jslint
 jsmimetype
 jsminplus
 json
+jsonconfig
 jsonfm
 jsparse
 jstext
@@ -2055,6 +2101,7 @@ keyname
 keynames
 keytype
 khash
+kikongo
 kludgy
 knownnamespace
 konqueror
@@ -2070,11 +2117,13 @@ langcode
 langcodes
 langconversion
 langlinks
+langname
 langprop
 langs
 language
 languagelinks
 languages
+languageselection
 languageshtml
 laquo
 large
@@ -2085,6 +2134,7 @@ lastdot
 lastedit
 lasteditor
 lastedittime
+lastfile
 lastlink
 lastmod
 lastmodifiedat
@@ -2135,6 +2185,8 @@ link
 linkarr
 linkcolour
 linkprefix
+linkprefixcharset
+linkpurge
 links
 linkstoimage
 linktbl
@@ -2170,6 +2222,7 @@ localdayname
 localdow
 locale
 localhour
+localinterwiki
 localmonth
 localmonthabbrev
 localmonthname
@@ -2200,6 +2253,7 @@ loginerror
 loginfo
 loginlanguagelinks
 loginlink
+loginout
 loginprompt
 loginreqlink
 loginreqpagetext
@@ -2236,7 +2290,6 @@ ltitle
 ltrimmed
 lurl
 lysator
-möller
 macr
 magicarr
 magicfile
@@ -2255,6 +2308,7 @@ mailtext
 mailto
 mainmodule
 mainpage
+maint
 maintainership
 makesafe
 male
@@ -2290,16 +2344,19 @@ maxwidth
 mazeland
 mbresponse
 mbstring
+mccmnc
 mckey
 mcklmqw
 mcrypt
 mcvalue
 md
 mdash
+mdot
 medialink
 mediaqueries
 mediatype
 mediawarning
+mediawiki
 mediawiki's
 mediawikipage
 megapixels
@@ -2380,6 +2437,7 @@ mkdir
 mms
 mobile
 mobileformat
+mobilelanding
 mobileview
 modified
 modifiedarticleprotection
@@ -2400,6 +2458,7 @@ moodbar
 moredotdotdot
 morelinkstoimage
 morethan
+mouseup
 move
 movedarticleprotection
 moveddeleted
@@ -2437,6 +2496,7 @@ msgsmall
 msgtext
 msie
 msmetafile
+msnbot
 mssql
 msvideo
 msword
@@ -2444,6 +2504,7 @@ mtime
 mtype
 mullane
 multi
+multiactions
 multibyte
 multicast
 multipage
@@ -2481,10 +2542,13 @@ mysqldump
 mytalk
 mytext
 mywatchlist
+möller
 nabla
 name
 namehidden
 nameinlowercase
+namelookup
+namemsg
 names
 namespace
 namespacealiases
@@ -2541,6 +2605,7 @@ newpos
 newquery
 newrevid
 news
+newsectionheaderdefaultlevel
 newsectionlink
 newsectionsummary
 newset
@@ -2567,6 +2632,7 @@ nextredirect
 nextrevision
 nextval
 nfkc
+nfkd
 nginx
 nheight
 niklas
@@ -2780,6 +2846,7 @@ noto
 notoc
 notoggle
 notoken
+notpatrollable
 notransform
 notreviewable
 notrustworthy
@@ -2881,6 +2948,7 @@ oldtitle
 oldtitlemsg
 oline
 oname
+onerror
 onkeyup
 online
 onload
@@ -2891,6 +2959,7 @@ onlyquery
 onsubmit
 onthisday
 ontop
+onuser
 openbasedir
 opendoc
 opendocument
@@ -2899,6 +2968,7 @@ opensearchdescription
 openssl's
 openxml
 openxmlformats
+operamini
 oplus
 oppositedm
 optgroup
@@ -2913,6 +2983,7 @@ ordertype
 ordf
 ordm
 org
+orghttp
 origcategory
 ortime
 oslash
@@ -2984,6 +3055,7 @@ pagetriagetagging
 pagetriagetemplate
 pageurl
 pageview
+pango
 param
 parameters
 paraminfo
@@ -3084,8 +3156,10 @@ pltitles
 plusminus
 plusmn
 pname
+png'd
 pnmtojpeg
 pnmtopng
+pointsize
 poolcounter
 popts
 popularpages
@@ -3110,12 +3184,14 @@ pptm
 pptx
 precaching
 precompiled
+preemptively
 preferences
 preferencestoken
 prefill
 prefilled
 prefix
 prefixindex
+prefixsearch
 prefixsearchdisabled
 prefs
 prefsection
@@ -3131,6 +3207,7 @@ preprocessing
 preprocessors
 presentationml
 presep
+pretransfer
 prevchar
 prevdiff
 previd
@@ -3194,6 +3271,7 @@ protecttoken
 proto
 protocol
 protocols
+protorel
 protos
 proxied
 proxyblocker
@@ -3216,6 +3294,7 @@ purged
 qabardjajəbza
 qbar
 qbsettings
+qlow
 qmoicj
 qp
 quasit
@@ -3234,6 +3313,7 @@ querytype
 question
 queuefull
 quickbar
+quicksorts
 quicktemplate
 quicktime
 qunit
@@ -3329,6 +3409,7 @@ redirectable
 redirectcreated
 redirectedfrom
 redirections
+redirector
 redirectpagesub
 redirectparams
 redirects
@@ -3343,6 +3424,7 @@ redis
 redlink
 redlinks
 redocument
+redux
 reedyboy
 reenables
 reencode
@@ -3380,6 +3462,8 @@ remstudent
 renameuser
 renaming
 renderable
+renderesibanner
+renderwarning
 renormalized
 repeating
 repl
@@ -3565,6 +3649,7 @@ selflink
 selfmove
 semiglobal
 semiprotected
+semiprotectedlevels
 semiprotectedpagewarning
 sendemail
 sendmail
@@ -3683,9 +3768,14 @@ slideshow
 sm
 smaxage
 smil
+smpp
+sms's
+smscontent
+smslogs
 smtp
 snippet
 sodipodi
+softredirect
 softtabstop
 solaris
 somecontent
@@ -3739,6 +3829,7 @@ stabilize
 stable
 stablesettings
 stansvik
+starcode
 start
 startid
 startime
@@ -3746,6 +3837,7 @@ startsortkey
 startsortkeyprefix
 starttime
 starttimestamp
+starttransfer
 stash
 stashfailed
 stashimageinfo
@@ -3762,6 +3854,7 @@ stopwords
 storedversion
 strcasecmp
 strcmp
+strftime
 string
 stripos
 stripslashes
@@ -3878,6 +3971,7 @@ taglist
 tags
 tagset
 tagstack
+tahoma
 tailorings
 talk
 talkable
@@ -3895,8 +3989,8 @@ talkpagetext
 talkspace
 talkspacee
 talkto
-taraškievica
 tarask
+taraškievica
 target
 tb
 tbase
@@ -3923,6 +4017,7 @@ test
 testclean
 testdata
 testmailuser
+teston
 testpass
 testrunner
 testswarm
@@ -3963,6 +4058,7 @@ thumbheight
 thumbhtml
 thumbimage
 thumbinner
+thumblimits
 thumbmime
 thumbnail
 thumbnailing
@@ -4036,6 +4132,7 @@ toparse
 topbar
 toplevel
 toplinks
+topojson
 toponly
 torev
 torevid
@@ -4067,7 +4164,9 @@ transwiki
 troff
 true
 truespeed
+truncatedtext
 trustworthy
+truteq
 truthy
 tsearch
 tsquery
@@ -4090,6 +4189,7 @@ udpprofile
 ufffd
 ugrave
 ui
+uids
 uint
 ulimit
 ulink
@@ -4115,6 +4215,8 @@ undel
 undelete
 undeleted
 undeletion
+undismissable
+undismissible
 undo
 undoafter
 undofailure
@@ -4129,6 +4231,7 @@ unhelpful
 unhidden
 unhide
 unidata
+unidecode
 unindent
 unindexed
 uniq
@@ -4156,6 +4259,7 @@ unprotect
 unprotectedarticle
 unprotection
 unprotectthispage
+unreadcount
 unredacted
 unrequest
 unrequested
@@ -4168,6 +4272,7 @@ unseed
 unserialization
 unserialize
 unserialized
+unserializes
 unserializing
 unsetting
 unstub
@@ -4211,6 +4316,7 @@ uploadscripted
 uploadsource
 uploadstash
 uploadvirus
+uploadwarning
 uppercased
 upsih
 urandom
@@ -4294,6 +4400,9 @@ usertoollinks
 useskin
 useto
 usort
+usrmonth
+ussd
+ussdcontent
 ustar
 ustoken
 utfnormal
@@ -4338,6 +4447,7 @@ viewdeleted
 viewhelppage
 viewmyprivateinfo
 viewmywatchlist
+viewport
 viewprevnext
 viewsource
 viewsourcelink
@@ -4354,6 +4464,7 @@ vorbis
 vpad
 vrml
 vslow
+vumi
 vvcv
 vxml
 wais
@@ -4391,6 +4502,7 @@ wbxml
 wddx
 wddxfm
 weblog
+weblogs
 webm
 webp
 webrequest
@@ -4433,17 +4545,23 @@ wikilove
 wikiloveimagelog
 wikimedia
 wikimediacommons
+wikimediafoundation
+wikinews
 wikipage
 wikipedia
 wikipedian
 wikipedias
+wikiquote
 wikis
+wikisource
 wikisyntax
 wikitable
 wikitables
 wikitech
 wikitext
 wikiuser
+wikiversity
+wikivoyage
 wiktionary
 wincache
 wininet
@@ -4468,6 +4586,7 @@ wmls
 wmlsc
 wmlscript
 wmlscriptc
+wmnet
 wordcount
 wordprocessingml
 wordwg
@@ -4482,6 +4601,7 @@ writerequired
 writerights
 wrongpassword
 x
+xanalytics
 xbitmap
 xcache
 xcancel
@@ -4503,8 +4623,8 @@ xml
 xmldoublequote
 xmlfm
 xmlimport
+xmlmeta
 xmlns
-xmlsafe
 xmlselect
 xor
 xpinstall
@@ -4517,6 +4637,7 @@ xxxxx
 yacute
 yaml
 yamlfm
+yandex
 year
 yes
 youhavenewmessages
@@ -4538,10 +4659,26 @@ yourvariant
 yourwiki
 yuml
 yyyymmddhhiiss
+zcmd
+zerobanner
+zerobar
+zerobutton
+zeroconfig
+zerodontask
+zerodot
+zeroinfo
+zeronet
+zeroportal
+zfile
 zhdaemon
 zhengzhu
 zhtable
 zijdel
+zlang
 zlib
 zoffset
+zrma
 zwnj
+ænglisc
+ævar
+świerkosz
index 47e6a89..46844c9 100644 (file)
@@ -44,6 +44,7 @@ if ( !$maintClass || !class_exists( $maintClass ) ) {
 }
 
 // Get an object to start us off
+/** @var Maintenance $maintenance */
 $maintenance = new $maintClass();
 
 // Basic sanity checks and such
@@ -77,17 +78,6 @@ if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
        # Use a callback function to configure MediaWiki
        call_user_func( MW_CONFIG_CALLBACK );
 } else {
-       if ( file_exists( "$IP/../wmf-config/wikimedia-mode" ) ) {
-               // Load settings, using wikimedia-mode if needed
-               // @todo FIXME: Replace this hack with general farm-friendly code
-               # @todo FIXME: Wikimedia-specific stuff needs to go away to an ext
-               # Maybe a hook?
-               // @codingStandardsIgnoreStart MediaWiki.NamingConventions.ValidGlobalName.wgPrefix
-               global $cluster;
-               $cluster = 'pmtpa';
-               // @codingStandardsIgnoreEnd
-               require "$IP/../wmf-config/wgConf.php";
-       }
        // Require the configuration (probably LocalSettings.php)
        require $maintenance->loadSettings();
 }
@@ -100,6 +90,8 @@ if ( $maintenance->getDbType() === Maintenance::DB_NONE ) {
                $wgLocalisationCacheConf['storeClass'] = 'LCStoreNull';
        }
 }
+
+$maintenance->setConfig( ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
 $maintenance->finalSetup();
 // Some last includes
 require_once "$IP/includes/Setup.php";
index 6bdb15d..75ec12b 100644 (file)
@@ -54,8 +54,6 @@ class EditCLI extends Maintenance {
                $noRC = $this->hasOption( 'no-rc' );
 
                $wgUser = User::newFromName( $userName );
-               $context = RequestContext::getMain();
-               $context->setUser( $wgUser );
                if ( !$wgUser ) {
                        $this->error( "Invalid username", true );
                }
@@ -67,7 +65,6 @@ class EditCLI extends Maintenance {
                if ( !$title ) {
                        $this->error( "Invalid title", true );
                }
-               $context->setTitle( $title );
 
                if ( $this->hasOption( 'nocreate' ) && !$title->exists() ) {
                        $this->error( "Page does not exist", true );
index 1c3f037..94ca604 100644 (file)
@@ -27,7 +27,7 @@ require_once __DIR__ . '/Maintenance.php';
 /**
  * Maintenance script to delete archived (non-current) files from storage.
  *
- * @TODO: Maybe add some simple logging
+ * @todo Maybe add some simple logging
  *
  * @ingroup Maintenance
  * @since 1.22
index 9929cf9..36760d7 100644 (file)
@@ -99,6 +99,7 @@ class FindHooks extends Maintenance {
                        $IP . '/includes/revisiondelete/',
                        $IP . '/includes/search/',
                        $IP . '/includes/site/',
+                       $IP . '/includes/skins/',
                        $IP . '/includes/specialpage/',
                        $IP . '/includes/specials/',
                        $IP . '/includes/upload/',
@@ -109,9 +110,6 @@ class FindHooks extends Maintenance {
                        $IP . '/tests/',
                        $IP . '/tests/parser/',
                        $IP . '/tests/phpunit/suites/',
-                       $IP . '/skins/',
-                       $IP . '/skins/MonoBook/',
-                       $IP . '/skins/Vector/',
                );
 
                foreach ( $pathinc as $dir ) {
@@ -136,7 +134,8 @@ class FindHooks extends Maintenance {
 
        /**
         * Get the hook documentation, either locally or from MediaWiki.org
-        * @return array of documented hooks
+        * @param string $doc
+        * @return array Array of documented hooks
         */
        private function getHooksFromDoc( $doc ) {
                if ( $this->hasOption( 'online' ) ) {
@@ -148,7 +147,7 @@ class FindHooks extends Maintenance {
 
        /**
         * Get hooks from a local file (for example docs/hooks.txt)
-        * @param string $doc filename to look in
+        * @param string $doc Filename to look in
         * @return array Array of documented hooks
         */
        private function getHooksFromLocalDoc( $doc ) {
@@ -161,7 +160,7 @@ class FindHooks extends Maintenance {
 
        /**
         * Get hooks from www.mediawiki.org using the API
-        * @return array of documented hooks
+        * @return array Array of documented hooks
         */
        private function getHooksFromOnlineDoc() {
                // All hooks
@@ -199,7 +198,7 @@ class FindHooks extends Maintenance {
        /**
         * Get hooks from a PHP file
         * @param string $file Full filename to the PHP file.
-        * @return array of hooks found.
+        * @return array Array of hooks found
         */
        private function getHooksFromFile( $file ) {
                $content = file_get_contents( $file );
@@ -216,7 +215,7 @@ class FindHooks extends Maintenance {
        /**
         * Get hooks from the source code.
         * @param string $path Directory where the include files can be found
-        * @return array Array of hooks found.
+        * @return array Array of hooks found
         */
        private function getHooksFromPath( $path ) {
                $hooks = array();
diff --git a/maintenance/findMissingFiles.php b/maintenance/findMissingFiles.php
new file mode 100644 (file)
index 0000000..5f9f643
--- /dev/null
@@ -0,0 +1,115 @@
+<?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
+ */
+
+require_once __DIR__ . '/Maintenance.php';
+
+class FindMissingFiles extends Maintenance {
+       function __construct() {
+               parent::__construct();
+
+               $this->mDescription = 'Find registered files with no corresponding file.';
+               $this->addOption( 'start', 'Starting file name', false, true );
+               $this->addOption( 'mtimeafter', 'Only include files changed since this time', false, true );
+               $this->addOption( 'mtimebefore', 'Only includes files changed before this time', false, true );
+               $this->setBatchSize( 300 );
+       }
+
+       function execute() {
+               $lastName = $this->getOption( 'start', '' );
+
+               $repo = RepoGroup::singleton()->getLocalRepo();
+               $dbr = $repo->getSlaveDB();
+               $be = $repo->getBackend();
+
+               $mtime1 = $dbr->timestampOrNull( $this->getOption( 'mtimeafter', null ) );
+               $mtime2 = $dbr->timestampOrNull( $this->getOption( 'mtimebefore', null ) );
+
+               $joinTables = array( 'image' );
+               $joinConds = array( 'image' => array( 'INNER JOIN', 'img_name = page_title' ) );
+               if ( $mtime1 || $mtime2 ) {
+                       $joinTables[] = 'logging';
+                       $on = array( 'log_page = page_id', 'log_type' => array( 'upload', 'move', 'delete' ) );
+                       if ( $mtime1 ) {
+                               $on[] = "log_timestamp > {$dbr->addQuotes($mtime1)}";
+                       }
+                       if ( $mtime2 ) {
+                               $on[] = "log_timestamp < {$dbr->addQuotes($mtime2)}";
+                       }
+                       $joinConds['logging'] = array( 'INNER JOIN', $on );
+               }
+
+               do {
+                       $res = $dbr->select(
+                               array_merge( array( 'page' ), $joinTables ),
+                               array( 'img_name' => 'DISTINCT(page_title)' ),
+                               array( 'page_namespace' => NS_FILE,
+                                       "page_title >= " . $dbr->addQuotes( $lastName ) ),
+                               __METHOD__,
+                               array( 'ORDER BY' => 'page_title', 'LIMIT' => $this->mBatchSize ),
+                               $joinConds
+                       );
+
+                       // Check if any of these files are missing...
+                       $pathsByName = array();
+                       foreach ( $res as $row ) {
+                               $file = $repo->newFile( $row->img_name );
+                               $pathsByName[$row->img_name] = $file->getPath();
+                               $lastName = $row->img_name;
+                       }
+                       $be->preloadFileStat( array( 'srcs' => $pathsByName ) );
+                       foreach ( $pathsByName as $path ) {
+                               if ( $be->fileExists( array( 'src' => $path ) ) === false ) {
+                                       $this->output( "$path\n" );
+                               }
+                       }
+
+                       // Find all missing old versions of any of the files in this batch...
+                       if ( count( $pathsByName ) ) {
+                               $ores = $dbr->select( 'oldimage',
+                                       array( 'oi_name', 'oi_archive_name' ),
+                                       array( 'oi_name' => array_keys( $pathsByName ) ),
+                                       __METHOD__
+                               );
+
+                               $checkPaths = array();
+                               foreach ( $ores as $row ) {
+                                       if ( !strlen( $row->oi_archive_name ) ) {
+                                               continue; // broken row
+                                       }
+                                       $file = $repo->newFromArchiveName( $row->oi_name, $row->oi_archive_name );
+                                       $checkPaths[] = $file->getPath();
+                               }
+
+                               foreach ( array_chunk( $checkPaths, $this->mBatchSize ) as $paths ) {
+                                       $be->preloadFileStat( array( 'srcs' => $paths ) );
+                                       foreach ( $paths as $path ) {
+                                               if ( $be->fileExists( array( 'src' => $path ) ) === false ) {
+                                                       $this->output( "$path\n" );
+                                               }
+                                       }
+                               }
+                       }
+               } while ( $res->numRows() >= $this->mBatchSize );
+       }
+}
+
+$maintClass = 'FindMissingFiles';
+require_once RUN_MAINTENANCE_IF_MAIN;
index a678a92..9568284 100644 (file)
@@ -96,7 +96,6 @@ class FixDoubleRedirects extends Maintenance {
                foreach ( $res as $row ) {
                        $titleA = Title::makeTitle( $row->pa_namespace, $row->pa_title );
                        $titleB = Title::makeTitle( $row->pb_namespace, $row->pb_title );
-                       RequestContext::getMain()->setTitle( $titleA );
 
                        $processedTitles .= "* [[$titleA]]\n";
 
index 83e731a..22d9940 100644 (file)
@@ -80,7 +80,8 @@ class GenerateJsonI18n extends Maintenance {
                        }
                        $this->output( "Searching for supplementary i18n files...\n" );
                        $dir_iterator = new RecursiveDirectoryIterator( dirname( $phpfile ) );
-                       $iterator = new RecursiveIteratorIterator( $dir_iterator, RecursiveIteratorIterator::LEAVES_ONLY );
+                       $iterator = new RecursiveIteratorIterator(
+                               $dir_iterator, RecursiveIteratorIterator::LEAVES_ONLY );
                        foreach ( $iterator as $path => $fileObject ) {
                                if ( fnmatch( "*.i18n.php", $fileObject->getFilename() ) ) {
                                        $this->output( "Converting $path.\n" );
index 1db53f3..d5f6834 100644 (file)
@@ -87,7 +87,7 @@ class GetConfiguration extends Maintenance {
        public function finalSetup() {
                parent::finalSetup();
 
-               $this->regex = $this->getOption( 'regex' ) ? : $this->getOption( 'iregex' );
+               $this->regex = $this->getOption( 'regex' ) ?: $this->getOption( 'iregex' );
                if ( $this->regex ) {
                        $this->regex = '/' . $this->regex . '/';
                        if ( $this->hasOption( 'iregex' ) ) {
index 1f7cbf5..1f75bcc 100644 (file)
@@ -141,8 +141,7 @@ TEXT;
                } elseif ( $obj instanceof WikiRevision ) {
                        $ns = $obj->title->getNamespace();
                } else {
-                       echo wfBacktrace();
-                       $this->error( "Cannot get namespace of object in " . __METHOD__, true );
+                       throw new MWException( "Cannot get namespace of object in " . __METHOD__ );
                }
 
                return is_array( $this->nsFilter ) && !in_array( $ns, $this->nsFilter );
@@ -182,7 +181,7 @@ TEXT;
        function handleUpload( $revision ) {
                if ( $this->uploads ) {
                        if ( $this->skippedNamespace( $revision ) ) {
-                               return;
+                               return false;
                        }
                        $this->uploadCount++;
                        // $this->report();
@@ -196,6 +195,8 @@ TEXT;
                                return $dbw->deadlockLoop( array( $revision, 'importUpload' ) );
                        }
                }
+
+               return false;
        }
 
        function handleLogItem( $rev ) {
diff --git a/maintenance/importTextFile.php b/maintenance/importTextFile.php
deleted file mode 100644 (file)
index f73dd1c..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-<?php
-/**
- * Create or edit pages using the contents of a text file.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- * @author Rob Church <robchur@gmail.com>
- */
-
-$options = array( 'help', 'nooverwrite', 'norc' );
-$optionsWithArgs = array( 'title', 'user', 'comment' );
-require_once __DIR__ . '/commandLine.inc';
-echo "Import Text File\n\n";
-
-if ( count( $args ) < 1 || isset( $options['help'] ) ) {
-       showHelp();
-} else {
-
-       $filename = $args[0];
-       echo "Using {$filename}...";
-       if ( is_file( $filename ) ) {
-
-               $title = isset( $options['title'] ) ? $options['title'] : titleFromFilename( $filename );
-               $title = Title::newFromText( $title );
-
-               if ( is_object( $title ) ) {
-
-                       echo "\nUsing title '" . $title->getPrefixedText() . "'...";
-                       if ( !$title->exists() || !isset( $options['nooverwrite'] ) ) {
-                               RequestContext::getMain()->setTitle( $title );
-
-                               $text = file_get_contents( $filename );
-                               $user = isset( $options['user'] ) ? $options['user'] : 'Maintenance script';
-                               $user = User::newFromName( $user );
-
-                               if ( is_object( $user ) ) {
-
-                                       echo "\nUsing username '" . $user->getName() . "'...";
-                                       $wgUser =& $user;
-                                       $comment = isset( $options['comment'] ) ? $options['comment'] : 'Importing text file';
-                                       $flags = 0 | ( isset( $options['norc'] ) ? EDIT_SUPPRESS_RC : 0 );
-
-                                       echo "\nPerforming edit...";
-                                       $page = WikiPage::factory( $title );
-                                       $content = ContentHandler::makeContent( $text, $title );
-                                       $page->doEditContent( $content, $comment, $flags, false, $user );
-                                       echo "done.\n";
-                               } else {
-                                       echo "invalid username.\n";
-                               }
-                       } else {
-                               echo "page exists.\n";
-                       }
-               } else {
-                       echo "invalid title.\n";
-               }
-       } else {
-               echo "does not exist.\n";
-       }
-}
-
-function titleFromFilename( $filename ) {
-       $parts = explode( '/', $filename );
-       $parts = explode( '.', $parts[count( $parts ) - 1] );
-
-       return $parts[0];
-}
-
-function showHelp() {
-       print <<<EOF
-USAGE: php importTextFile.php <options> <filename>
-
-<filename> : Path to the file containing page content to import
-
-Options:
-
---title <title>
-       Title for the new page; default is to use the filename as a base
---user <user>
-       User to be associated with the edit
---comment <comment>
-       Edit summary
---nooverwrite
-       Don't overwrite existing content
---norc
-       Don't update recent changes
---help
-       Show this information
-
-EOF;
-}
index fbc5d98..b948b67 100644 (file)
  * @ingroup Maintenance
  */
 
-if ( !function_exists( 'version_compare' ) || ( version_compare( phpversion(), '5.3.2' ) < 0 ) ) {
-       require_once dirname( __FILE__ ) . '/../includes/PHPVersionError.php';
-       wfPHPVersionError( 'cli' );
-}
+// Checking for old versions of PHP is done in Maintenance.php
+// We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
+require_once dirname( __FILE__ ) . '/Maintenance.php';
 
 define( 'MW_CONFIG_CALLBACK', 'Installer::overrideConfig' );
 define( 'MEDIAWIKI_INSTALL', true );
 
-require_once dirname( __DIR__ ) . '/maintenance/Maintenance.php';
-
 /**
  * Maintenance script to install and configure MediaWiki
  *
- * Default values for the options are defined in DefaultSettings.php (see the mapping in CliInstaller.php)
+ * Default values for the options are defined in DefaultSettings.php
+ * (see the mapping in CliInstaller.php)
  * Default for --dbpath (SQLite-specific) is defined in SqliteInstaller::getGlobalDefaults
  *
  * @ingroup Maintenance
@@ -85,9 +83,11 @@ class CommandLineInstaller extends Maintenance {
                        true
                );
                $this->addOption( 'confpath', "Path to write LocalSettings.php to ($IP)", false, true );
-               $this->addOption( 'dbschema', 'The schema for the MediaWiki DB in PostgreSQL/Microsoft SQL Server (mediawiki)', false, true );
+               $this->addOption( 'dbschema', 'The schema for the MediaWiki DB in '
+                       . 'PostgreSQL/Microsoft SQL Server (mediawiki)', false, true );
                /*
-               $this->addOption( 'namespace', 'The project namespace (same as the "name" argument)', false, true );
+               $this->addOption( 'namespace', 'The project namespace (same as the "name" argument)',
+                       false, true );
                */
                $this->addOption( 'env-checks', "Run environment checks only, don't change anything" );
        }
index 8efabef..0660e55 100644 (file)
@@ -45,6 +45,7 @@ rfc|http://www.rfc-editor.org/rfc/rfc$1.txt|0
 s23wiki|http://s23.org/wiki/$1|0
 seattlewireless|http://seattlewireless.net/$1|0
 senseislibrary|http://senseis.xmp.net/?$1|0
+shoutwiki|http://www.shoutwiki.com/wiki/$1|0
 sourceforge|http://sourceforge.net/$1|0
 sourcewatch|http://www.sourcewatch.org/index.php?title=$1|0
 squeak|http://wiki.squeak.org/squeak/$1|0
@@ -54,6 +55,7 @@ tmnet|http://www.technomanifestos.net/?$1|0
 theopedia|http://www.theopedia.com/$1|0
 twiki|http://twiki.org/cgi-bin/view/$1|0
 uea|http://uea.org/vikio/index.php/$1|0
+uncyclopedia|http://en.uncyclopedia.co/wiki/$1|0
 unreal|http://wiki.beyondunreal.com/$1|0
 usemod|http://www.usemod.com/cgi-bin/wiki.pl?$1|0
 webseitzwiki|http://webseitz.fluxent.com/wiki/$1|0
index 53559ef..aad0cc3 100644 (file)
@@ -47,6 +47,7 @@ REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES
 ('s23wiki','http://s23.org/wiki/$1',0),
 ('seattlewireless','http://seattlewireless.net/$1',0),
 ('senseislibrary','http://senseis.xmp.net/?$1',0),
+('shoutwiki','http://www.shoutwiki.com/wiki/$1',0),
 ('sourceforge','http://sourceforge.net/$1',0),
 ('sourcewatch','http://www.sourcewatch.org/index.php?title=$1',0),
 ('squeak','http://wiki.squeak.org/squeak/$1',0),
@@ -56,6 +57,7 @@ REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES
 ('theopedia','http://www.theopedia.com/$1',0),
 ('twiki','http://twiki.org/cgi-bin/view/$1',0),
 ('uea','http://uea.org/vikio/index.php/$1',0),
+('uncyclopedia','http://en.uncyclopedia.co/wiki/$1',0),
 ('unreal','http://wiki.beyondunreal.com/$1',0),
 ('usemod','http://www.usemod.com/cgi-bin/wiki.pl?$1',0),
 ('webseitzwiki','http://webseitz.fluxent.com/wiki/$1',0),
index eed76b6..e97f292 100644 (file)
@@ -26,6 +26,7 @@
                "../../resources/src/jquery/jquery.checkboxShiftClick.js",
                "../../resources/src/jquery/jquery.client.js",
                "../../resources/src/jquery/jquery.colorUtil.js",
+               "../../resources/src/jquery/jquery.confirmable.js",
                "../../resources/src/jquery/jquery.footHovzer.js",
                "../../resources/src/jquery/jquery.getAttrs.js",
                "../../resources/src/jquery/jquery.hidpi.js",
index 2bb5e6b..db6c315 100644 (file)
@@ -365,7 +365,7 @@ class UcdXmlReader {
                $xml = $this->open();
                $this->callback = $callback;
 
-               while ( $xml->name !== 'repertoire' && $xml->next() ) ;
+               while ( $xml->name !== 'repertoire' && $xml->next() );
 
                while ( $xml->read() ) {
                        if ( $xml->nodeType == XMLReader::ELEMENT ) {
@@ -389,7 +389,7 @@ class UcdXmlReader {
                if ( !$this->xml ) {
                        throw new MWException( __METHOD__ . ": unable to open {$this->fileName}" );
                }
-               while ( $this->xml->name !== 'ucd' && $this->xml->read() ) ;
+               while ( $this->xml->name !== 'ucd' && $this->xml->read() );
                $this->xml->read();
 
                return $this->xml;
@@ -450,7 +450,7 @@ class UcdXmlReader {
                }
 
                $xml = $this->open();
-               while ( $xml->name !== 'blocks' && $xml->read() ) ;
+               while ( $xml->name !== 'blocks' && $xml->read() );
 
                while ( $xml->read() ) {
                        if ( $xml->nodeType == XMLReader::ELEMENT ) {
index 9c9b7ff..fb496cb 100644 (file)
@@ -55,7 +55,7 @@ class Languages {
        /** @var array Magic words */
        protected $mMagicWords;
 
-       /** @var  array Special page aliases */
+       /** @var array Special page aliases */
        protected $mSpecialPageAliases;
 
        /**
index da49e55..a97d2e1 100644 (file)
@@ -78,7 +78,7 @@ class McTest extends Maintenance {
                        $set = 0;
                        $incr = 0;
                        $get = 0;
-                       $time_start = $this->microtime_float();
+                       $time_start = microtime( true );
                        for ( $i = 1; $i <= $iterations; $i++ ) {
                                if ( $mcc->set( "test$i", $i ) ) {
                                        $set++;
@@ -95,21 +95,11 @@ class McTest extends Maintenance {
                                        $get++;
                                }
                        }
-                       $exectime = $this->microtime_float() - $time_start;
+                       $exectime = microtime( true ) - $time_start;
 
                        $this->output( " set: $set   incr: $incr   get: $get time: $exectime", $server );
                }
        }
-
-       /**
-        * Return microtime() as a float
-        * @return float
-        */
-       private function microtime_float() {
-               list( $usec, $sec ) = explode( " ", microtime() );
-
-               return ( (float)$usec + (float)$sec );
-       }
 }
 
 $maintClass = "McTest";
diff --git a/maintenance/mssql/archives/patch-fa_major_mime-chemical.sql b/maintenance/mssql/archives/patch-fa_major_mime-chemical.sql
new file mode 100644 (file)
index 0000000..1836808
--- /dev/null
@@ -0,0 +1,4 @@
+ALTER TABLE /*_*/filearchive
+DROP CONSTRAINT fa_major_mime_ckc;
+ALTER TABLE /*_*/filearchive
+WITH NOCHECK ADD CONSTRAINT fa_major_mime_ckc CHECK (fa_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical'));
\ No newline at end of file
diff --git a/maintenance/mssql/archives/patch-img_major_mime-chemical.sql b/maintenance/mssql/archives/patch-img_major_mime-chemical.sql
new file mode 100644 (file)
index 0000000..eed0786
--- /dev/null
@@ -0,0 +1,4 @@
+ALTER TABLE /*_*/image
+DROP CONSTRAINT img_major_mime_ckc;
+ALTER TABLE /*_*/image
+WITH NOCHECK ADD CONSTRAINT img_major_mime_ckc CHECK (img_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical'));
\ No newline at end of file
diff --git a/maintenance/mssql/archives/patch-oi_major_mime-chemical.sql b/maintenance/mssql/archives/patch-oi_major_mime-chemical.sql
new file mode 100644 (file)
index 0000000..35482ed
--- /dev/null
@@ -0,0 +1,4 @@
+ALTER TABLE /*_*/oldimage
+DROP CONSTRAINT oi_major_mime_ckc;
+ALTER TABLE /*_*/oldimage
+WITH NOCHECK ADD CONSTRAINT oi_major_mime_ckc CHECK (oi_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical'));
\ No newline at end of file
index daaa81e..b9cd715 100644 (file)
@@ -594,7 +594,7 @@ CREATE TABLE /*_*/image (
   -- SHA-1 content hash in base-36
   img_sha1 nvarchar(32) NOT NULL default '',
 
-  CONSTRAINT img_major_mime_ckc check (img_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart')),
+  CONSTRAINT img_major_mime_ckc check (img_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical')),
   CONSTRAINT img_media_type_ckc check (img_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'))
 );
 
@@ -639,7 +639,7 @@ CREATE TABLE /*_*/oldimage (
   oi_deleted tinyint NOT NULL default 0,
   oi_sha1 nvarchar(32) NOT NULL default '',
 
-  CONSTRAINT oi_major_mime_ckc check (oi_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart')),
+  CONSTRAINT oi_major_mime_ckc check (oi_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical')),
   CONSTRAINT oi_media_type_ckc check (oi_media_type IN('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'))
 );
 
@@ -700,7 +700,7 @@ CREATE TABLE /*_*/filearchive (
   -- sha1 hash of file content
   fa_sha1 nvarchar(32) NOT NULL default '',
 
-  CONSTRAINT fa_major_mime_ckc check (fa_major_mime in('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart')),
+  CONSTRAINT fa_major_mime_ckc check (fa_major_mime in('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart', 'chemical')),
   CONSTRAINT fa_media_type_ckc check (fa_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'))
 );
 
diff --git a/maintenance/mssql/update-keys.sql b/maintenance/mssql/update-keys.sql
new file mode 100644 (file)
index 0000000..4d2c1c1
--- /dev/null
@@ -0,0 +1,31 @@
+-- Update keys for Microsoft SQL Server
+-- SQL to insert update keys into the initial tables after a
+-- fresh installation of MediaWiki's database.
+-- This is read and executed by the install script; you should
+-- not have to run it by itself unless doing a manual install.
+-- Insert keys here if either the unnecessary would cause heavy
+-- processing or could potentially cause trouble by lowering field
+-- sizes, adding constraints, etc.
+-- When adjusting field sizes, it is recommended removing old
+-- patches but to play safe, update keys should also inserted here.
+
+--
+-- The /*_*/ comments in this and other files are
+-- replaced with the defined table prefix by the installer
+-- and updater scripts. If you are installing or running
+-- updates manually, you will need to manually insert the
+-- table prefix if any when running these scripts.
+--
+
+INSERT INTO /*_*/updatelog
+       SELECT 'filearchive-fa_major_mime-patch-fa_major_mime-chemical.sql' AS ul_key, null as ul_value
+       UNION SELECT 'image-img_major_mime-patch-img_major_mime-chemical.sql', null
+       UNION SELECT 'oldimage-oi_major_mime-patch-oi_major_mime-chemical.sql', null
+       UNION SELECT 'cl_type-category_types-ck', null
+       UNION SELECT 'fa_major_mime-major_mime-ck', null
+       UNION SELECT 'fa_media_type-media_type-ck', null
+       UNION SELECT 'img_major_mime-major_mime-ck', null
+       UNION SELECT 'img_media_type-media_type-ck', null
+       UNION SELECT 'oi_major_mime-major_mime-ck', null
+       UNION SELECT 'oi_media_type-media_type-ck', null
+       UNION SELECT 'us_media_type-media_type-ck', null;
\ No newline at end of file
index ea86e88..cbc389b 100644 (file)
@@ -186,8 +186,8 @@ class NamespaceConflictChecker extends Maintenance {
 
        /**
         * @todo Do this for real
-        * @param int $ns
-        * @param string $name
+        * @param int $key
+        * @param string $prefix
         * @param bool $fix
         * @param string $suffix
         * @return bool
diff --git a/maintenance/nextJobDB.php b/maintenance/nextJobDB.php
deleted file mode 100644 (file)
index d172363..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-<?php
-/**
- * Pick a database that has pending jobs
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- */
-
-require_once __DIR__ . '/Maintenance.php';
-
-/**
- * Maintenance script that picks a database that has pending jobs.
- *
- * @ingroup Maintenance
- */
-class NextJobDB extends Maintenance {
-       public function __construct() {
-               parent::__construct();
-               $this->mDescription = "Pick a database that has pending jobs";
-               $this->addOption( 'type', "Search by job type", false, true );
-               $this->addOption( 'types', "Space separated list of job types to search for", false, true );
-       }
-
-       public function execute() {
-               global $wgJobTypesExcludedFromDefaultQueue;
-
-               // job type required/picked
-               if ( $this->hasOption( 'types' ) ) {
-                       $types = explode( ' ', $this->getOption( 'types' ) );
-               } elseif ( $this->hasOption( 'type' ) ) {
-                       $types = array( $this->getOption( 'type' ) );
-               } else {
-                       $types = false;
-               }
-
-               // Handle any required periodic queue maintenance
-               $this->executeReadyPeriodicTasks();
-
-               // Get all the queues with jobs in them
-               $pendingDBs = JobQueueAggregator::singleton()->getAllReadyWikiQueues();
-               if ( !count( $pendingDBs ) ) {
-                       return; // no DBs with jobs or cache is both empty and locked
-               }
-
-               $candidates = array(); // list of (type, db)
-               // Flatten the tree of candidates into a flat list so that a random
-               // item can be selected, weighing each queue (type/db tuple) equally.
-               foreach ( $pendingDBs as $type => $dbs ) {
-                       if (
-                               ( is_array( $types ) && in_array( $type, $types ) ) ||
-                               ( $types === false && !in_array( $type, $wgJobTypesExcludedFromDefaultQueue ) )
-                       ) {
-                               foreach ( $dbs as $db ) {
-                                       $candidates[] = array( $type, $db );
-                               }
-                       }
-               }
-               if ( !count( $candidates ) ) {
-                       return; // no jobs for this type
-               }
-
-               list( $type, $db ) = $candidates[mt_rand( 0, count( $candidates ) - 1 )];
-
-               if ( $this->hasOption( 'types' ) ) {
-                       $this->output( $db . " " . $type . "\n" );
-               } else {
-                       $this->output( $db . "\n" );
-               }
-       }
-
-       /**
-        * Do all ready periodic jobs for all databases every 5 minutes (and .1% of the time)
-        * @return int
-        */
-       private function executeReadyPeriodicTasks() {
-               global $wgLocalDatabases, $wgMemc;
-
-               $count = 0;
-               $memcKey = 'jobqueue:periodic:lasttime';
-               $timestamp = (int)$wgMemc->get( $memcKey ); // UNIX timestamp or 0
-               if ( ( time() - $timestamp ) > 300 || mt_rand( 0, 999 ) == 0 ) { // 5 minutes
-                       if ( $wgMemc->add( "$memcKey:rebuild", 1, 1800 ) ) { // lock
-                               foreach ( $wgLocalDatabases as $db ) {
-                                       $count += JobQueueGroup::singleton( $db )->executeReadyPeriodicTasks();
-                               }
-                               $wgMemc->set( $memcKey, time() );
-                               $wgMemc->delete( "$memcKey:rebuild" ); // unlock
-                       }
-               }
-
-               return $count;
-       }
-}
-
-$maintClass = "NextJobDb";
-require_once RUN_MAINTENANCE_IF_MAIN;
index 9af57da..638d7c5 100644 (file)
@@ -113,7 +113,7 @@ class CLIParser extends Maintenance {
         * Default title is 'CLIParser', it can be overriden with the option
         * --title <Your:Title>
         *
-        * @return Title object
+        * @return Title
         */
        protected function getTitle() {
                $title = $this->getOption( 'title' )
diff --git a/maintenance/populateBacklinkNamespace.php b/maintenance/populateBacklinkNamespace.php
new file mode 100644 (file)
index 0000000..054f792
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+/**
+ * Optional upgrade script to populate *_from_namespace fields
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once __DIR__ . '/Maintenance.php';
+
+/**
+ * Maintenance script to populate *_from_namespace fields
+ *
+ * @ingroup Maintenance
+ */
+class PopulateBacklinkNamespace extends LoggedUpdateMaintenance {
+       public function __construct() {
+               parent::__construct();
+               $this->mDescription = "Populate the *_from_namespace fields";
+               $this->addOption( 'lastUpdatedId', "Highest page_id with updated links", false, true );
+       }
+
+       protected function getUpdateKey() {
+               return 'populate *_from_namespace';
+       }
+
+       protected function updateSkippedMessage() {
+               return '*_from_namespace column of backlink tables already populated.';
+       }
+
+       public function doDBUpdates() {
+               $force = $this->getOption( 'force' );
+
+               $db = $this->getDB( DB_MASTER );
+
+               $this->output( "Updating *_from_namespace fields in links tables.\n" );
+
+               $start = $this->getOption( 'lastUpdatedId' );
+               if ( !$start ) {
+                       $start = $db->selectField( 'page', 'MIN(page_id)', false, __METHOD__ );
+               }
+               if ( !$start ) {
+                       $this->output( "Nothing to do." );
+                       return false;
+               }
+               $end = $db->selectField( 'page', 'MAX(page_id)', false, __METHOD__ );
+
+               # Do remaining chunk
+               $end += $this->mBatchSize - 1;
+               $blockStart = $start;
+               $blockEnd = $start + $this->mBatchSize - 1;
+               while ( $blockEnd <= $end ) {
+                       $this->output( "...doing page_id from $blockStart to $blockEnd\n" );
+                       $cond = "page_id BETWEEN $blockStart AND $blockEnd";
+                       $res = $db->select( 'page', array( 'page_id', 'page_namespace' ), $cond, __METHOD__ );
+                       foreach ( $res as $row ) {
+                               $db->update( 'pagelinks',
+                                       array( 'pl_from_namespace' => $row->page_namespace ),
+                                       array( 'pl_from' => $row->page_id ),
+                                       __METHOD__
+                               );
+                               $db->update( 'templatelinks',
+                                       array( 'tl_from_namespace' => $row->page_namespace ),
+                                       array( 'tl_from' => $row->page_id ),
+                                       __METHOD__
+                               );
+                               $db->update( 'imagelinks',
+                                       array( 'il_from_namespace' => $row->page_namespace ),
+                                       array( 'il_from' => $row->page_id ),
+                                       __METHOD__
+                               );
+                       }
+                       $blockStart += $this->mBatchSize - 1;
+                       $blockEnd += $this->mBatchSize - 1;
+                       wfWaitForSlaves();
+               }
+               return true;
+       }
+}
+
+$maintClass = "PopulateBacklinkNamespace";
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/populateBloomCache.php b/maintenance/populateBloomCache.php
new file mode 100644 (file)
index 0000000..40ad5fc
--- /dev/null
@@ -0,0 +1,78 @@
+<?php
+/**
+ * Script to populate a bloom filter with a BloomFilter* class
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once __DIR__ . '/Maintenance.php';
+
+/**
+ * Script to populate a bloom filter with a BloomFilter* class
+ *
+ * @ingroup Maintenance
+ */
+class PopulateBloomFilter extends Maintenance {
+       public function __construct() {
+               parent::__construct();
+               $this->addOption( 'cache', 'Bloom cache store name', true, true );
+               $this->addOption( 'filter', 'Bloom filter name', true, true );
+               $this->addOption( 'domain', 'Bloom filter domain', true, true );
+               $this->addOption( 'delay', 'Sleep delay between batches (us)', false, true );
+               $this->mDescription = "Populate the specified bloom filter";
+       }
+
+       public function execute() {
+               $type = $this->getOption( 'filter' );
+               $domain = $this->getOption( 'domain' );
+               $bcache = BloomCache::get( $this->getOption( 'cache' ) );
+               $delay = $this->getOption( 'delay', 1e5 );
+
+               if ( !method_exists( "BloomFilter{$type}", 'merge' ) ) {
+                       $this->error( "No \"BloomFilter{$type}::merge\" method found.", 1 );
+               }
+
+               $virtualKey = "$domain:$type";
+               $status = $bcache->getStatus( $virtualKey );
+               if ( $status == false ) {
+                       $this->error( "Could not query virtual bloom filter '$virtualKey'.", 1 );
+               }
+
+               $startTime = microtime( true );
+               $this->output( "Current timestamp is '$startTime'.\n" );
+               $this->output( "Current filter timestamp is '{$status['asOfTime']}'.\n" );
+
+               do {
+                       $status = call_user_func_array(
+                               array( "BloomFilter{$type}", 'merge' ),
+                               array( $bcache, $domain, $virtualKey, $status )
+                       );
+                       if ( $status == false ) {
+                               $this->error( "Could not query virtual bloom filter '$virtualKey'.", 1 );
+                       }
+                       $this->output( "Filter updated to timestamp '{$status['asOfTime']}'.\n" );
+                       usleep( $delay );
+               } while ( $status['asOfTime'] && $status['asOfTime'] < $startTime );
+
+               $this->output( "Done, filter $type of domain $domain reached time '$startTime'.\n" );
+       }
+}
+
+$maintClass = "PopulateBloomFilter";
+require_once RUN_MAINTENANCE_IF_MAIN;
index cf35fe8..400050e 100644 (file)
@@ -206,6 +206,7 @@ CREATE INDEX redirect_ns_title ON redirect (rd_namespace,rd_title,rd_from);
 
 CREATE TABLE pagelinks (
   pl_from       INTEGER   NOT NULL  REFERENCES page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+  pl_from_namespace INTEGER NOT NULL DEFAULT 0,
   pl_namespace  SMALLINT  NOT NULL,
   pl_title      TEXT      NOT NULL
 );
@@ -214,6 +215,7 @@ CREATE INDEX pagelinks_title ON pagelinks (pl_title);
 
 CREATE TABLE templatelinks (
   tl_from       INTEGER  NOT NULL  REFERENCES page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+  tl_from_namespace INTEGER NOT NULL DEFAULT 0,
   tl_namespace  SMALLINT NOT NULL,
   tl_title      TEXT     NOT NULL
 );
@@ -222,6 +224,7 @@ CREATE INDEX templatelinks_from          ON templatelinks (tl_from);
 
 CREATE TABLE imagelinks (
   il_from  INTEGER  NOT NULL  REFERENCES page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+  il_from_namespace INTEGER NOT NULL DEFAULT 0,
   il_to    TEXT     NOT NULL
 );
 CREATE UNIQUE INDEX il_from ON imagelinks (il_to,il_from);
index 9155623..cb55f0f 100644 (file)
@@ -159,6 +159,7 @@ class PPFuzzTest {
 
        /**
         * @param Title $title
+        * @return array
         */
        function templateHook( $title ) {
                $titleText = $title->getPrefixedDBkey();
index f0b6ec7..6702209 100644 (file)
@@ -160,10 +160,11 @@ class PurgeChangedPages extends Maintenance {
         * If this returns an empty array for a non-empty query result, then all the rows
         * had the same column value and the query should be repeated with a higher LIMIT.
         *
-        * @TODO: move this elsewhere
+        * @todo move this elsewhere
         *
         * @param ResultWrapper $res Query result sorted by $column (ascending)
         * @param string $column
+        * @param int $limit
         * @return array (array of rows, string column value)
         */
        protected function pageableSortedRows( ResultWrapper $res, $column, $limit ) {
index 913e9f0..5093cb3 100644 (file)
@@ -23,6 +23,9 @@
  * @author Rob Church <robchur@gmail.com>
  */
 
+/**
+ * @param bool $delete
+ */
 function PurgeRedundantText( $delete = false ) {
 
        # Data should come off the master, wrapped in a transaction
index 8cb23fd..831118c 100644 (file)
@@ -70,7 +70,7 @@ class RefreshImageMetadata extends Maintenance {
 
                $this->addOption(
                        'mime',
-                       '(Inefficient!) Only refresh files with this mime type. Can accept wild-card image/*',
+                       '(Inefficient!) Only refresh files with this MIME type. Can accept wild-card image/*',
                        false,
                        true
                );
index ca9572f..1b35292 100755 (executable)
@@ -9,12 +9,12 @@ then
        exit 1
 fi
 
-TARGET_REPO=$(cd $(dirname $0)/../..; pwd)
+TARGET_REPO=$(cd "$(dirname $0)/../.."; pwd)
 TARGET_DIR=resources/lib/oojs-ui
 UI_REPO=$1
 
 function oojsuihash() {
-       grep "OOjs UI v" $TARGET_REPO/$TARGET_DIR/oojs-ui.js \
+       grep "OOjs UI v" "$TARGET_REPO/$TARGET_DIR/oojs-ui.js" \
                | head -n 1 \
                | grep -Eo '\([a-z0-9]+\)' \
                | sed 's/^(//' \
@@ -22,19 +22,19 @@ function oojsuihash() {
 }
 
 function oojsuitag() {
-       grep "OOjs UI v" $TARGET_REPO/$TARGET_DIR/oojs-ui.js \
+       grep "OOjs UI v" "$TARGET_REPO/$TARGET_DIR/oojs-ui.js" \
                | head -n 1 \
                | grep -Eo '\bv[0-9a-z.-]+\b'
 }
 
 function oojsuiversion() {
-       grep "OOjs UI v" $TARGET_REPO/$TARGET_DIR/oojs-ui.js \
+       grep "OOjs UI v" "$TARGET_REPO/$TARGET_DIR/oojs-ui.js" \
                | head -n 1 \
                | grep -Eo '\bv[0-9a-z.-]+\b.*$'
 }
 
 # Prepare working tree
-cd $TARGET_REPO &&
+cd "$TARGET_REPO" &&
 git reset $TARGET_DIR && git checkout $TARGET_DIR && git fetch origin &&
 git checkout -B upstream-oojsui origin/master || exit 1
 
@@ -48,10 +48,10 @@ then
 fi
 if [ "$OLDHASH" == "" ]
 then
-       OLDHASH=$(git rev-parse $OLDTAG)
+       OLDHASH=$(git rev-parse "$OLDTAG")
        if [ $? != 0 ]
        then
-               echo Could not find OOjs UI version
+               echo "Could not find OOjs UI version"
                cd -
                exit 1
        fi
@@ -72,13 +72,13 @@ NEWCHANGESDISPLAY=$(git log $OLDHASH.. --oneline --no-merges --reverse --color=a
 
 # Copy files
 # - Exclude the default non-svg stylesheet
-rsync --recursive --delete --force --exclude 'oojs-ui.css' ./dist/ $TARGET_REPO/$TARGET_DIR || exit 1
+rsync --recursive --delete --force --exclude 'oojs-ui.css' --exclude 'oojs-ui*.rtl.css' ./dist/ "$TARGET_REPO/$TARGET_DIR" || exit 1
 
 # Read the new version
 NEWVERSION=$(oojsuiversion)
 
 # Generate commit
-cd $TARGET_REPO
+cd "$TARGET_REPO"
 COMMITMSG=$(cat <<END
 Update OOjs UI to $NEWVERSION
 
index 2c50002..d9e6fb9 100755 (executable)
@@ -7,12 +7,12 @@ then
        exit 1
 fi
 
-REPO_DIR=$(cd $(dirname $0)/../..; pwd) # Root dir of the git repo working tree
-TARGET_DIR=resources/lib/oojs # Destination relative to the root of the repo
-NPM_DIR=`mktemp -d 2>/dev/null || mktemp -d -t 'update-oojs'` # e.g. /tmp/update-oojs.rI0I5Vir
+REPO_DIR=$(cd "$(dirname $0)/../.."; pwd) # Root dir of the git repo working tree
+TARGET_DIR="resources/lib/oojs" # Destination relative to the root of the repo
+NPM_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t 'update-oojs') # e.g. /tmp/update-oojs.rI0I5Vir
 
 # Prepare working tree
-cd $REPO_DIR &&
+cd "$REPO_DIR" &&
 git reset $TARGET_DIR && git checkout $TARGET_DIR && git fetch origin &&
 git checkout -B upstream-oojs origin/master || exit 1
 
@@ -20,7 +20,7 @@ git checkout -B upstream-oojs origin/master || exit 1
 cd $NPM_DIR
 if [ -n "$1" ]
 then
-       npm install oojs@$1 || exit 1
+       npm install "oojs@$1" || exit 1
 else
        npm install oojs || exit 1
 fi
@@ -33,10 +33,10 @@ then
 fi
 
 # Copy file(s)
-rsync --recursive --delete --force ./node_modules/oojs/dist $REPO_DIR/$TARGET_DIR || exit 1
+rsync --force ./node_modules/oojs/dist/oojs.jquery.js "$REPO_DIR/$TARGET_DIR" || exit 1
 
 # Clean up temporary area
-rm -rf $NPM_DIR
+rm -rf "$NPM_DIR"
 
 # Generate commit
 cd $REPO_DIR || exit 1
index 9b86e1b..40605ce 100644 (file)
@@ -37,6 +37,7 @@ class RunJobs extends Maintenance {
                $this->addOption( 'type', 'Type of job to run', false, true );
                $this->addOption( 'procs', 'Number of processes to use', false, true );
                $this->addOption( 'nothrottle', 'Ignore job throttling configuration', false, false );
+               $this->addOption( 'result', 'Set to JSON to print only a JSON response', false, true );
        }
 
        public function memoryLimit() {
@@ -65,215 +66,28 @@ class RunJobs extends Maintenance {
                        }
                }
 
-               $type = $this->getOption( 'type', false );
-               $maxJobs = $this->getOption( 'maxjobs', false );
-               $maxTime = $this->getOption( 'maxtime', false );
-               $noThrottle = $this->hasOption( 'nothrottle' );
-               $startTime = time();
+               $json = ( $this->getOption( 'result' ) === 'json' );
 
-               $group = JobQueueGroup::singleton();
-               // Handle any required periodic queue maintenance
-               $count = $group->executeReadyPeriodicTasks();
-               if ( $count > 0 ) {
-                       $this->runJobsLog( "Executed $count periodic queue task(s)." );
+               $runner = new JobRunner();
+               if ( !$json ) {
+                       $runner->setDebugHandler( array( $this, 'debugInternal' ) );
                }
-
-               $backoffs = $this->loadBackoffs(); // map of (type => UNIX expiry)
-               $startingBackoffs = $backoffs; // avoid unnecessary writes
-               $backoffExpireFunc = function ( $t ) {
-                       return $t > time();
-               };
-
-               $jobsRun = 0; // counter
-               $flags = JobQueueGroup::USE_CACHE;
-               $lastTime = time(); // time since last slave check
-               do {
-                       $backoffs = array_filter( $backoffs, $backoffExpireFunc );
-                       $blacklist = $noThrottle ? array() : array_keys( $backoffs );
-                       if ( $type === false ) {
-                               $job = $group->pop( JobQueueGroup::TYPE_DEFAULT, $flags, $blacklist );
-                       } elseif ( in_array( $type, $blacklist ) ) {
-                               $job = false; // requested queue in backoff state
-                       } else {
-                               $job = $group->pop( $type ); // job from a single queue
-                       }
-                       if ( $job ) { // found a job
-                               ++$jobsRun;
-                               $this->runJobsLog( $job->toString() . " STARTING" );
-
-                               // Set timer to stop the job if too much CPU time is used
-                               set_time_limit( $maxTime ? : 0 );
-                               // Run the job...
-                               wfProfileIn( __METHOD__ . '-' . get_class( $job ) );
-                               $t = microtime( true );
-                               try {
-                                       $status = $job->run();
-                                       $error = $job->getLastError();
-                               } catch ( MWException $e ) {
-                                       MWExceptionHandler::rollbackMasterChangesAndLog( $e );
-                                       $status = false;
-                                       $error = get_class( $e ) . ': ' . $e->getMessage();
-                                       $e->report(); // write error to STDERR and the log
-                               }
-                               $timeMs = intval( ( microtime( true ) - $t ) * 1000 );
-                               wfProfileOut( __METHOD__ . '-' . get_class( $job ) );
-                               // Disable the timer
-                               set_time_limit( 0 );
-
-                               // Mark the job as done on success or when the job cannot be retried
-                               if ( $status !== false || !$job->allowRetries() ) {
-                                       $group->ack( $job ); // done
-                               }
-
-                               if ( $status === false ) {
-                                       $this->runJobsLog( $job->toString() . " t=$timeMs error={$error}" );
-                               } else {
-                                       $this->runJobsLog( $job->toString() . " t=$timeMs good" );
-                               }
-
-                               // Back off of certain jobs for a while
-                               $ttw = $this->getBackoffTimeToWait( $job );
-                               if ( $ttw > 0 ) {
-                                       $jType = $job->getType();
-                                       $backoffs[$jType] = isset( $backoffs[$jType] ) ? $backoffs[$jType] : 0;
-                                       $backoffs[$jType] = max( $backoffs[$jType], time() + $ttw );
-                               }
-
-                               // Break out if we hit the job count or wall time limits...
-                               if ( $maxJobs && $jobsRun >= $maxJobs ) {
-                                       break;
-                               } elseif ( $maxTime && ( time() - $startTime ) > $maxTime ) {
-                                       break;
-                               }
-
-                               // Don't let any of the main DB slaves get backed up
-                               $timePassed = time() - $lastTime;
-                               if ( $timePassed >= 5 || $timePassed < 0 ) {
-                                       wfWaitForSlaves();
-                                       $lastTime = time();
-                               }
-                               // Don't let any queue slaves/backups fall behind
-                               if ( $jobsRun > 0 && ( $jobsRun % 100 ) == 0 ) {
-                                       $group->waitForBackups();
-                               }
-
-                               // Bail if near-OOM instead of in a job
-                               $this->assertMemoryOK();
-                       }
-               } while ( $job ); // stop when there are no jobs
-               // Sync the persistent backoffs for the next runJobs.php pass
-               $backoffs = array_filter( $backoffs, $backoffExpireFunc );
-               if ( $backoffs !== $startingBackoffs ) {
-                       $this->syncBackoffs( $backoffs );
-               }
-       }
-
-       /**
-        * @param Job $job
-        * @return int Seconds for this runner to avoid doing more jobs of this type
-        * @see $wgJobBackoffThrottling
-        */
-       private function getBackoffTimeToWait( Job $job ) {
-               global $wgJobBackoffThrottling;
-
-               if ( !isset( $wgJobBackoffThrottling[$job->getType()] ) ||
-                       $job instanceof DuplicateJob // no work was done
-               ) {
-                       return 0; // not throttled
-               }
-
-               $itemsPerSecond = $wgJobBackoffThrottling[$job->getType()];
-               if ( $itemsPerSecond <= 0 ) {
-                       return 0; // not throttled
-               }
-
-               $seconds = 0;
-               if ( $job->workItemCount() > 0 ) {
-                       $exactSeconds = $job->workItemCount() / $itemsPerSecond;
-                       // use randomized rounding
-                       $seconds = floor( $exactSeconds );
-                       $remainder = $exactSeconds - $seconds;
-                       $seconds += ( mt_rand() / mt_getrandmax() < $remainder ) ? 1 : 0;
-               }
-
-               return (int)$seconds;
-       }
-
-       /**
-        * Get the previous backoff expiries from persistent storage
-        *
-        * @return array Map of (job type => backoff expiry timestamp)
-        */
-       private function loadBackoffs() {
-               $section = new ProfileSection( __METHOD__ );
-
-               $backoffs = array();
-               $file = wfTempDir() . '/mw-runJobs-backoffs.json';
-               if ( is_file( $file ) ) {
-                       $handle = fopen( $file, 'rb' );
-                       flock( $handle, LOCK_SH );
-                       $content = stream_get_contents( $handle );
-                       flock( $handle, LOCK_UN );
-                       fclose( $handle );
-                       $backoffs = json_decode( $content, true ) ? : array();
-               }
-
-               return $backoffs;
-       }
-
-       /**
-        * Merge the current backoff expiries from persistent storage
-        *
-        * @param array $backoffs Map of (job type => backoff expiry timestamp)
-        */
-       private function syncBackoffs( array $backoffs ) {
-               $section = new ProfileSection( __METHOD__ );
-
-               $file = wfTempDir() . '/mw-runJobs-backoffs.json';
-               $handle = fopen( $file, 'wb+' );
-               flock( $handle, LOCK_EX );
-               $content = stream_get_contents( $handle );
-               $cBackoffs = json_decode( $content, true ) ? : array();
-               foreach ( $backoffs as $type => $timestamp ) {
-                       $cBackoffs[$type] = isset( $cBackoffs[$type] ) ? $cBackoffs[$type] : 0;
-                       $cBackoffs[$type] = max( $cBackoffs[$type], $backoffs[$type] );
-               }
-               ftruncate( $handle, 0 );
-               fwrite( $handle, json_encode( $backoffs ) );
-               flock( $handle, LOCK_UN );
-               fclose( $handle );
-       }
-
-       /**
-        * Make sure that this script is not too close to the memory usage limit.
-        * It is better to die in between jobs than OOM right in the middle of one.
-        * @throws MWException
-        */
-       private function assertMemoryOK() {
-               static $maxBytes = null;
-               if ( $maxBytes === null ) {
-                       $m = array();
-                       if ( preg_match( '!^(\d+)(k|m|g|)$!i', ini_get( 'memory_limit' ), $m ) ) {
-                               list( , $num, $unit ) = $m;
-                               $conv = array( 'g' => 1073741824, 'm' => 1048576, 'k' => 1024, '' => 1 );
-                               $maxBytes = $num * $conv[strtolower( $unit )];
-                       } else {
-                               $maxBytes = 0;
-                       }
-               }
-               $usedBytes = memory_get_usage();
-               if ( $maxBytes && $usedBytes >= 0.95 * $maxBytes ) {
-                       throw new MWException( "Detected excessive memory usage ($usedBytes/$maxBytes)." );
+               $response = $runner->run( array(
+                       'type'     => $this->getOption( 'type', false ),
+                       'maxJobs'  => $this->getOption( 'maxjobs', false ),
+                       'maxTime'  => $this->getOption( 'maxtime', false ),
+                       'throttle' => $this->hasOption( 'nothrottle' ) ? false : true,
+               ) );
+               if ( $json ) {
+                       $this->output( FormatJson::encode( $response, true ) );
                }
        }
 
        /**
-        * Log the job message
-        * @param string $msg The message to log
+        * @param string $s
         */
-       private function runJobsLog( $msg ) {
-               $this->output( wfTimestamp( TS_DB ) . " $msg\n" );
-               wfDebugLog( 'runJobs', $msg );
+       public function debugInternal( $s ) {
+               $this->output( $s );
        }
 }
 
index 38f346b..b8dc554 100644 (file)
@@ -64,7 +64,7 @@ class ShowJobs extends Maintenance {
                                $claimed = $queue->getAcquiredCount();
                                $abandoned = $queue->getAbandonedCount();
                                $active = max( 0, $claimed - $abandoned );
-                               if ( ( $pending + $claimed + $delayed ) > 0 ) {
+                               if ( ( $pending + $claimed + $delayed + $abandoned ) > 0 ) {
                                        $this->output(
                                                "{$type}: $pending queued; " .
                                                "$claimed claimed ($active active, $abandoned abandoned); " .
index c947a4c..afa3ef7 100644 (file)
@@ -39,7 +39,7 @@ class MwSql extends Maintenance {
        }
 
        public function execute() {
-               $wiki = $this->getOption( 'wikidb' ) ? : false;
+               $wiki = $this->getOption( 'wikidb' ) ?: false;
                // Get the appropriate load balancer (for this wiki)
                if ( $this->hasOption( 'cluster' ) ) {
                        $lb = wfGetLBFactory()->getExternalLB( $this->getOption( 'cluster' ), $wiki );
@@ -136,7 +136,7 @@ class MwSql extends Maintenance {
        /**
         * Print the results, callback for $db->sourceStream()
         * @param ResultWrapper $res The results object
-        * @param DatabaseBase $db object
+        * @param DatabaseBase $db
         */
        public function sqlPrintResult( $res, $db ) {
                if ( !$res ) {
index 9729a72..5c0fd07 100644 (file)
@@ -42,7 +42,7 @@ class Sqlite {
         * Will throw exceptions on SQL errors
         * @param array|string $files
         * @throws MWException
-        * @return string|bool true if no error or error string in case of errors
+        * @return bool True if no error or error string in case of errors
         */
        public static function checkSqlSyntax( $files ) {
                if ( !Sqlite::isPresent() ) {
index 0f337ec..cfffbbc 100644 (file)
@@ -136,7 +136,11 @@ class CompressOld extends Maintenance {
                }
        }
 
-       /** @todo document */
+       /**
+        * @todo document
+        * @param int $start
+        * @param string $extdb
+        */
        private function compressOldPages( $start = 0, $extdb = '' ) {
                $chunksize = 50;
                $this->output( "Starting from old_id $start...\n" );
index 307d0b0..910f56b 100644 (file)
@@ -289,6 +289,8 @@ class RecompressTracked {
 
        /**
         * Dispatch a command to a specified slave
+        * @param int $slaveId
+        * @param array|string $args
         */
        function dispatchToSlave( $slaveId, $args ) {
                $args = (array)$args;
@@ -352,6 +354,9 @@ class RecompressTracked {
 
        /**
         * Display a progress report
+        * @param string $label
+        * @param int $current
+        * @param int $end
         */
        function report( $label, $current, $end ) {
                $this->numBatches++;
@@ -707,6 +712,8 @@ class CgzCopyTransaction {
 
        /**
         * Create a transaction from a RecompressTracked object
+        * @param RecompressTracked $parent
+        * @param string $blobClass
         */
        function __construct( $parent, $blobClass ) {
                $this->blobClass = $blobClass;
index dff5cb8..290f164 100644 (file)
@@ -65,6 +65,9 @@ function resolveStubs() {
 
 /**
  * Resolve a history stub
+ * @param int $id
+ * @param string $stubText
+ * @param string $flags
  */
 function resolveStub( $id, $stubText, $flags ) {
        $fname = 'resolveStub';
index b9493cd..14a1502 100644 (file)
@@ -280,6 +280,7 @@ class SyncFileBackend extends Maintenance {
         * Substitute the backend name of storage paths with that of a given one
         *
         * @param array|string $paths List of paths or single string path
+        * @param FileBackend $backend
         * @return array|string
         */
        protected function replaceNamePaths( $paths, FileBackend $backend ) {
index 6f200b2..0228684 100644 (file)
@@ -473,6 +473,8 @@ CREATE INDEX /*i*/ar_revid ON /*_*/archive (ar_rev_id);
 CREATE TABLE /*_*/pagelinks (
   -- Key to the page_id of the page containing the link.
   pl_from int unsigned NOT NULL default 0,
+  -- Namespace for this page
+  pl_from_namespace int NOT NULL default 0,
 
   -- Key to page_namespace/page_title of the target page.
   -- The target page may or may not exist, and due to renames
@@ -483,7 +485,8 @@ CREATE TABLE /*_*/pagelinks (
 ) /*$wgDBTableOptions*/;
 
 CREATE UNIQUE INDEX /*i*/pl_from ON /*_*/pagelinks (pl_from,pl_namespace,pl_title);
-CREATE UNIQUE INDEX /*i*/pl_namespace ON /*_*/pagelinks (pl_namespace,pl_title,pl_from);
+CREATE INDEX /*i*/pl_namespace ON /*_*/pagelinks (pl_namespace,pl_title,pl_from);
+CREATE INDEX /*i*/pl_backlinks_namespace ON /*_*/pagelinks (pl_namespace,pl_title,pl_from_namespace,pl_from);
 
 
 --
@@ -492,6 +495,8 @@ CREATE UNIQUE INDEX /*i*/pl_namespace ON /*_*/pagelinks (pl_namespace,pl_title,p
 CREATE TABLE /*_*/templatelinks (
   -- Key to the page_id of the page containing the link.
   tl_from int unsigned NOT NULL default 0,
+  -- Namespace for this page
+  tl_from_namespace int NOT NULL default 0,
 
   -- Key to page_namespace/page_title of the target page.
   -- The target page may or may not exist, and due to renames
@@ -502,7 +507,8 @@ CREATE TABLE /*_*/templatelinks (
 ) /*$wgDBTableOptions*/;
 
 CREATE UNIQUE INDEX /*i*/tl_from ON /*_*/templatelinks (tl_from,tl_namespace,tl_title);
-CREATE UNIQUE INDEX /*i*/tl_namespace ON /*_*/templatelinks (tl_namespace,tl_title,tl_from);
+CREATE INDEX /*i*/tl_namespace ON /*_*/templatelinks (tl_namespace,tl_title,tl_from);
+CREATE INDEX /*i*/tl_backlinks_namespace ON /*_*/templatelinks (tl_namespace,tl_title,tl_from_namespace,tl_from);
 
 
 --
@@ -513,6 +519,8 @@ CREATE UNIQUE INDEX /*i*/tl_namespace ON /*_*/templatelinks (tl_namespace,tl_tit
 CREATE TABLE /*_*/imagelinks (
   -- Key to page_id of the page containing the image / media link.
   il_from int unsigned NOT NULL default 0,
+  -- Namespace for this page
+  il_from_namespace int NOT NULL default 0,
 
   -- Filename of target image.
   -- This is also the page_title of the file's description page;
@@ -521,7 +529,8 @@ CREATE TABLE /*_*/imagelinks (
 ) /*$wgDBTableOptions*/;
 
 CREATE UNIQUE INDEX /*i*/il_from ON /*_*/imagelinks (il_from,il_to);
-CREATE UNIQUE INDEX /*i*/il_to ON /*_*/imagelinks (il_to,il_from);
+CREATE INDEX /*i*/il_to ON /*_*/imagelinks (il_to,il_from);
+CREATE INDEX /*i*/il_backlinks_namespace ON /*_*/imagelinks (il_to,il_from_namespace,il_from);
 
 
 --
@@ -727,7 +736,7 @@ CREATE UNIQUE INDEX /*i*/ss_row_id ON /*_*/site_stats (ss_row_id);
 --
 CREATE TABLE /*_*/hitcounter (
   hc_id int unsigned NOT NULL
-) ENGINE=HEAP MAX_ROWS=25000;
+) ENGINE=MEMORY MAX_ROWS=25000;
 
 
 --
@@ -838,7 +847,8 @@ CREATE TABLE /*_*/image (
 
   -- major part of a MIME media type as defined by IANA
   -- see http://www.iana.org/assignments/media-types/
-  img_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") NOT NULL default "unknown",
+  -- for "chemical" cf. http://dx.doi.org/10.1021/ci9803233 by the ACS
+  img_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical") NOT NULL default "unknown",
 
   -- minor part of a MIME media type as defined by IANA
   -- the minor parts are not required to adher to any standard
@@ -897,7 +907,7 @@ CREATE TABLE /*_*/oldimage (
 
   oi_metadata mediumblob NOT NULL,
   oi_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
-  oi_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") NOT NULL default "unknown",
+  oi_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical") NOT NULL default "unknown",
   oi_minor_mime varbinary(100) NOT NULL default "unknown",
   oi_deleted tinyint unsigned NOT NULL default 0,
   oi_sha1 varbinary(32) NOT NULL default ''
@@ -947,7 +957,7 @@ CREATE TABLE /*_*/filearchive (
   fa_metadata mediumblob,
   fa_bits int default 0,
   fa_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
-  fa_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") default "unknown",
+  fa_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical") default "unknown",
   fa_minor_mime varbinary(100) default "unknown",
   fa_description tinyblob,
   fa_user int unsigned default 0,
index c890c69..adebd27 100644 (file)
@@ -47,7 +47,7 @@ class Undelete extends Maintenance {
                if ( !$wgUser ) {
                        $this->error( "Invalid username", true );
                }
-               $archive = new PageArchive( $title );
+               $archive = new PageArchive( $title, RequestContext::getMain()->getConfig() );
                $this->output( "Undeleting " . $title->getPrefixedDBkey() . '...' );
                $archive->undelete( array(), $reason );
                $this->output( "done\n" );
diff --git a/maintenance/update-keys.sql b/maintenance/update-keys.sql
new file mode 100644 (file)
index 0000000..dfbb67e
--- /dev/null
@@ -0,0 +1,29 @@
+-- SQL to insert update keys into the initial tables after a
+-- fresh installation of MediaWiki's database.
+-- This is read and executed by the install script; you should
+-- not have to run it by itself unless doing a manual install.
+-- Insert keys here if either the unnecessary would cause heavy
+-- processing or could potentially cause trouble by lowering field
+-- sizes, adding constraints, etc.
+-- When adjusting field sizes, it is recommended removing old
+-- patches but to play safe, update keys should also inserted here.
+
+-- This is a shared file used for both MySQL and SQLite installs.
+-- Therefore inserting multiple values is not possible using the
+-- INSERT INTO VALUES syntax.
+--
+--
+-- The /*_*/ comments in this and other files are
+-- replaced with the defined table prefix by the installer
+-- and updater scripts. If you are installing or running
+-- updates manually, you will need to manually insert the
+-- table prefix if any when running these scripts.
+--
+
+INSERT IGNORE INTO /*_*/updatelog
+       SELECT 'filearchive-fa_major_mime-patch-fa_major_mime-chemical.sql' AS ul_key, null as ul_value
+       UNION SELECT 'image-img_major_mime-patch-img_major_mime-chemical.sql', null
+       UNION SELECT 'oldimage-oi_major_mime-patch-oi_major_mime-chemical.sql', null
+       UNION SELECT 'user_groups-ug_group-patch-ug_group-length-increase-255.sql', null
+       UNION SELECT 'user_former_groups-ufg_group-patch-ufg_group-length-increase-255.sql', null
+       UNION SELECT 'user_properties-up_property-patch-up_property.sql', null;
\ No newline at end of file
index a51564a..046d73c 100755 (executable)
@@ -26,7 +26,7 @@
  * @ingroup Maintenance
  */
 
-if ( !function_exists( 'version_compare' ) || ( version_compare( phpversion(), '5.3.2' ) < 0 ) ) {
+if ( !function_exists( 'version_compare' ) || ( version_compare( PHP_VERSION, '5.3.2' ) < 0 ) ) {
        require dirname( __FILE__ ) . '/../includes/PHPVersionError.php';
        wfPHPVersionError( 'cli' );
 }
index 19c1d24..342ffba 100644 (file)
@@ -219,6 +219,9 @@ TEXT;
        /**
         * Return an SQL expression selecting rows which sort above the given row,
         * assuming an ordering of cl_to, cl_type, cl_from
+        * @param stdClass $row
+        * @param DatabaseBase $dbw
+        * @return string
         */
        function getBatchCondition( $row, $dbw ) {
                $fields = array( 'cl_to', 'cl_type', 'cl_from' );
index 9b8714d..99ba3b8 100644 (file)
@@ -40,7 +40,11 @@ class UserOptions {
 
        private $mMode, $mReady;
 
-       /** Constructor. Will show usage and exit if script options are not correct */
+       /**
+        * Constructor. Will show usage and exit if script options are not correct
+        * @param array $opts
+        * @param array $args
+        */
        function __construct( $opts, $args ) {
                if ( !$this->checkOpts( $opts, $args ) ) {
                        UserOptions::showUsageAndExit();
diff --git a/maintenance/wrapOldPasswords.php b/maintenance/wrapOldPasswords.php
new file mode 100644 (file)
index 0000000..37272a0
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Maintenance script to wrap all old-style passwords in a layered type
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+require_once __DIR__ . '/Maintenance.php';
+
+/**
+ * Maintenance script to wrap all passwords of a certain type in a specified layered
+ * type that wraps around the old type.
+ *
+ * @since 1.24
+ * @ingroup Maintenance
+ */
+class WrapOldPasswords extends Maintenance {
+       public function __construct() {
+               parent::__construct();
+               $this->mDescription = "Wrap all passwords of a certain type in a new layered type";
+               $this->addOption( 'type',
+                       'Password type to wrap passwords in (must inherit LayeredParameterizedPassword)', true, true );
+               $this->addOption( 'verbose', 'Enables verbose output', false, false, 'v' );
+               $this->setBatchSize( 100 );
+       }
+
+       public function execute() {
+               global $wgAuth;
+
+               if ( !$wgAuth->allowSetLocalPassword() ) {
+                       $this->error( '$wgAuth does not allow local passwords. Aborting.', true );
+               }
+
+               $passwordFactory = new PasswordFactory();
+               $passwordFactory->init( RequestContext::getMain()->getConfig() );
+
+               $typeInfo = $passwordFactory->getTypes();
+               $layeredType = $this->getOption( 'type' );
+
+               // Check that type exists and is a layered type
+               if ( !isset( $typeInfo[$layeredType] ) ) {
+                       $this->error( 'Undefined password type', true );
+               }
+
+               $passObj = $passwordFactory->newFromType( $layeredType );
+               if ( !$passObj instanceof LayeredParameterizedPassword ) {
+                       $this->error( 'Layered parameterized password type must be used.', true );
+               }
+
+               // Extract the first layer type
+               $typeConfig = $typeInfo[$layeredType];
+               $firstType = $typeConfig['types'][0];
+
+               // Get a list of password types that are applicable
+               $dbw = $this->getDB( DB_MASTER );
+               $typeCond = 'user_password' . $dbw->buildLike( ":$firstType:", $dbw->anyString() );
+
+               $minUserId = 0;
+               do {
+                       $dbw->begin();
+
+                       $res = $dbw->select( 'user',
+                               array( 'user_id', 'user_name', 'user_password' ),
+                               array(
+                                       'user_id > ' . $dbw->addQuotes( $minUserId ),
+                                       $typeCond
+                               ),
+                               __METHOD__,
+                               array(
+                                       'ORDER BY' => 'user_id',
+                                       'LIMIT' => $this->mBatchSize,
+                                       'LOCK IN SHARE MODE',
+                               )
+                       );
+
+                       /** @var User[] $updateUsers */
+                       $updateUsers = array();
+                       foreach ( $res as $row ) {
+                               if ( $this->hasOption( 'verbose' ) ) {
+                                       $this->output( "Updating password for user {$row->user_name} ({$row->user_id}).\n" );
+                               }
+
+                               $user = User::newFromId( $row->user_id );
+                               /** @var ParameterizedPassword $password */
+                               $password = $passwordFactory->newFromCiphertext( $row->user_password );
+                               /** @var LayeredParameterizedPassword $layeredPassword */
+                               $layeredPassword = $passwordFactory->newFromType( $layeredType );
+                               $layeredPassword->partialCrypt( $password );
+
+                               $updateUsers[] = $user;
+                               $dbw->update( 'user',
+                                       array( 'user_password' => $layeredPassword->toString() ),
+                                       array( 'user_id' => $row->user_id ),
+                                       __METHOD__
+                               );
+
+                               $minUserId = $row->user_id;
+                       }
+
+                       $dbw->commit();
+
+                       // Clear memcached so old passwords are wiped out
+                       foreach ( $updateUsers as $user ) {
+                               $user->clearSharedCache();
+                       }
+               } while ( $res->numRows() );
+       }
+}
+
+$maintClass = "WrapOldPasswords";
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/mw-config/config-cc.css b/mw-config/config-cc.css
new file mode 100644 (file)
index 0000000..ecd10fa
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * Copy of CC standard stylesheet, plus tweaks for iframe usage
+ */
+
+body {
+       margin: 0;
+       background: #eee;
+       font-family: Verdana;
+       color: #333;
+}
+
+#main {
+       border: 1px solid #D0D0D0;
+       background: #fff;
+       margin: 0.5em;
+}
+
+/**
+ * Looks like you have to specify the width of #menu
+ * or IE5 Mac stretches it all the way across the div, and
+ * Opera streches it half way.
+ */
+
+#main #menu {
+       border-left: 1px dotted #ccc;
+       float: right;
+       width: 230px;
+       background: white;
+       margin: 0 0 10px 10px;
+}
+
+td, h3, p, h1, pre {
+       margin: 0 20px 20px 20px;
+       font-size: 11px;
+       line-height: 140%;
+}
+
+.header {
+       padding-left: 10px;
+       padding-top: 10px;
+}
+
+.nav {
+       padding-left: 10px;
+       padding-bottom: 10px;
+       font-size: 11px;
+       margin-bottom: 16px;
+}
+
+#menu p {
+       font-size: 11px;
+}
+
+.dent {
+       margin-left: 64px;
+}
diff --git a/mw-config/config.css b/mw-config/config.css
new file mode 100644 (file)
index 0000000..17b2039
--- /dev/null
@@ -0,0 +1,174 @@
+.env-check {
+       font-size: 90%;
+       margin: 1em 0 1em 2.5em;
+}
+
+.config-section {
+       margin-top: 2em;
+}
+
+.config-block {
+       margin-top: 2em;
+       display: block;
+
+}
+
+.config-block-label {
+       display: block;
+       margin-bottom: .2em;
+}
+
+.config-block-label label, .config-label {
+       font-weight: bold;
+       padding-right: .5em;
+       padding-top: .2em;
+}
+
+.config-block-elements {
+       margin-left: 2em;
+}
+
+.config-block-elements li {
+       list-style: none;
+}
+
+.config-input {
+       clear: left;
+       zoom: 100%; /* IE hack */
+}
+
+.config-page-wrapper {
+       padding: 0.5em;
+}
+
+.config-page-list {
+       float: right;
+       width: 12em;
+       border: 1px solid #aaa;
+       background: #fff;
+       padding: 0.5em;
+       /* 3em left margin to leave space between the list and the page-content */
+       margin: 0.5em 0.5em 0.5em 3.5em;
+}
+
+.config-page {
+       padding: 0.5em 0.5em 0.5em 2em;
+       margin: 0.5em 0.5em 0.5em 0.5em;
+       background: #eee;
+}
+
+.config-submit {
+       clear: left;
+       text-align: center;
+       padding: 1em;
+}
+
+.config-submit input {
+       margin-left: 0.5em;
+       margin-right: 0.5em;
+}
+
+.config-page-disabled {
+       color: #aaa;
+}
+
+.config-error-box {
+       border: 2px solid #f00;
+}
+
+.config-page-current {
+       font-weight: bold;
+}
+
+.config-message {
+       display: list-item;
+       line-height: 1.5em;
+       /* @embed */
+       list-style-image: url(images/bullet.gif);
+       list-style-type: square;
+}
+
+.config-input-text {
+       width: 20em;
+       margin-right: 1em;
+}
+
+.config-input-check {
+       margin-left: 10em;
+}
+
+.config-skins-item {
+       /* Clearfix */
+       clear: left;
+       overflow: hidden;
+}
+
+.config-skins-item .config-input-check {
+       margin-left: 10em;
+       width: 20em;
+       float: left;
+}
+
+.config-skins-item .config-skins-use-as-default {
+       float: left;
+}
+
+.error {
+       color: red;
+       background-color: #fff;
+       font-weight: bold;
+       left: 1em;
+       font-size: 100%;
+}
+
+.config-settings-block {
+       list-style-type: none;
+       list-style-image: none;
+       margin: 0;
+       padding: 0;
+}
+
+.btn-install {
+       font-weight: bold;
+       font-size: 110%;
+       padding: .2em .3em;
+}
+
+.success-message {
+       font-weight: bold;
+       font-size: 110%;
+       color: green;
+}
+
+.success-box {
+       font-size: 130%;
+}
+
+.config-cc-wrapper {
+       clear: left;
+       /* If you change this height, also change it in WebInstallerOptions::submitCC() */
+       height: 54em;
+}
+
+.config-plainlink a {
+       background: none !important;
+       padding: 0 !important;
+}
+
+.config-download-link {
+       font-size: 1.8em;
+       margin-left: 2em;
+}
+
+.config-download-link a {
+       background: url(images/download-32.png) no-repeat center left;
+       padding-left: 40px; /* 32 px for the image (above), plus some breathing room */
+       height: 32px; /* provide enough vertical room for the image */
+       display: inline-block; /* allow the height property (above) to work */
+       line-height: 32px; /* center the text vertically */
+}
+
+#config-live-log {
+       overflow: hidden;
+       min-width: 20em;
+}
diff --git a/mw-config/config.js b/mw-config/config.js
new file mode 100644 (file)
index 0000000..cf17aef
--- /dev/null
@@ -0,0 +1,108 @@
+( function ( $ ) {
+       $( function () {
+               var $label, labelText;
+
+               function syncText() {
+                       var value = $(this).val()
+                               .replace( /[\[\]\{\}|#<>%+? ]/g, '_' )
+                               .replace( /&/, '&amp;' )
+                               .replace( /__+/g, '_' )
+                               .replace( /^_+/, '' )
+                               .replace( /_+$/, '' );
+                       value = value.charAt( 0 ).toUpperCase() + value.slice( 1 );
+                       $label.text( labelText.replace( '$1', value ) );
+               }
+
+               // Set up the help system
+               $( '.mw-help-field-data' )
+                       .hide()
+                       .closest( '.mw-help-field-container' )
+                               .find( '.mw-help-field-hint' )
+                                       .show()
+                                       .click( function () {
+                                               $(this)
+                                                       .closest( '.mw-help-field-container' )
+                                                               .find( '.mw-help-field-data' )
+                                                                       .slideToggle( 'fast' );
+                                       } );
+
+               // Show/hide code for DB-specific options
+               // FIXME: Do we want slow, fast, or even non-animated (instantaneous) showing/hiding here?
+               $( '.dbRadio' ).each( function () {
+                       $( document.getElementById( $(this).attr( 'rel' ) ) ).hide();
+               } );
+               $( document.getElementById( $( '.dbRadio:checked' ).attr( 'rel' ) ) ).show();
+               $( '.dbRadio' ).click( function () {
+                       var $checked = $( '.dbRadio:checked' ),
+                               $wrapper = $( document.getElementById( $checked.attr( 'rel' ) ) );
+                       if ( $wrapper.is( ':hidden' ) ) {
+                               $( '.dbWrapper' ).hide( 'slow' );
+                               $wrapper.show( 'slow' );
+                       }
+               } );
+
+               // Scroll to the bottom of upgrade log
+               $( '#config-live-log' ).children( 'textarea' ).each( function () {
+                       this.scrollTop = this.scrollHeight;
+               } );
+
+               // Show/hide Creative Commons thingy
+               $( '.licenseRadio' ).click( function () {
+                       var $wrapper = $( '#config-cc-wrapper' );
+                       if ( $( '#config__LicenseCode_cc-choose' ).is( ':checked' ) ) {
+                               $wrapper.show( 'slow' );
+                       } else {
+                               $wrapper.hide( 'slow' );
+                       }
+               } );
+
+               // Show/hide random stuff (email, upload)
+               $( '.showHideRadio' ).click( function () {
+                       var $wrapper = $( '#' + $(this).attr( 'rel' ) );
+                       if ( $(this).is( ':checked' ) ) {
+                               $wrapper.show( 'slow' );
+                       } else {
+                               $wrapper.hide( 'slow' );
+                       }
+               } );
+               $( '.hideShowRadio' ).click( function () {
+                       var $wrapper = $( '#' + $(this).attr( 'rel' ) );
+                       if ( $(this).is( ':checked' ) ) {
+                               $wrapper.hide( 'slow' );
+                       } else {
+                               $wrapper.show( 'slow' );
+                       }
+               } );
+
+               // Hide "other" textboxes by default
+               // Should not be done in CSS for javascript disabled compatibility
+               $( '.enabledByOther' ).closest( '.config-block' ).hide();
+
+               // Enable/disable "other" textboxes
+               $( '.enableForOther' ).click( function () {
+                       var $textbox = $( document.getElementById( $(this).attr( 'rel' ) ) );
+                       // FIXME: Ugh, this is ugly
+                       if ( $(this).val() === 'other' ) {
+                               $textbox.removeProp( 'readonly' ).closest( '.config-block' ).slideDown( 'fast' );
+                       } else {
+                               $textbox.prop( 'readonly', true ).closest( '.config-block' ).slideUp( 'fast' );
+                       }
+               } );
+
+               // Synchronize radio button label for sitename with textbox
+               $label = $( 'label[for=config__NamespaceType_site-name]' );
+               labelText = $label.text();
+               $label.text( labelText.replace( '$1', '' ) );
+               $( '#config_wgSitename' ).on( 'keyup change', syncText ).each( syncText );
+
+               // Show/Hide memcached servers when needed
+               $( 'input[name$="config_wgMainCacheType"]' ).change( function () {
+                       var $memc = $( '#config-memcachewrapper' );
+                       if ( $( 'input[name$="config_wgMainCacheType"]:checked' ).val() === 'memcached' ) {
+                               $memc.show( 'slow' );
+                       } else {
+                               $memc.hide( 'slow' );
+                       }
+               } );
+       } );
+}( jQuery ) );
diff --git a/mw-config/images/ajax-loader.gif b/mw-config/images/ajax-loader.gif
new file mode 100644 (file)
index 0000000..72203fd
Binary files /dev/null and b/mw-config/images/ajax-loader.gif differ
diff --git a/mw-config/images/bullet.gif b/mw-config/images/bullet.gif
new file mode 100644 (file)
index 0000000..b43de48
Binary files /dev/null and b/mw-config/images/bullet.gif differ
diff --git a/mw-config/images/critical-32.png b/mw-config/images/critical-32.png
new file mode 100644 (file)
index 0000000..9b38e6a
Binary files /dev/null and b/mw-config/images/critical-32.png differ
diff --git a/mw-config/images/download-32.png b/mw-config/images/download-32.png
new file mode 100644 (file)
index 0000000..e5b8318
Binary files /dev/null and b/mw-config/images/download-32.png differ
diff --git a/mw-config/images/info-32.png b/mw-config/images/info-32.png
new file mode 100644 (file)
index 0000000..ab09e1d
Binary files /dev/null and b/mw-config/images/info-32.png differ
diff --git a/mw-config/images/installer-logo.png b/mw-config/images/installer-logo.png
new file mode 100644 (file)
index 0000000..c6bd868
Binary files /dev/null and b/mw-config/images/installer-logo.png differ
diff --git a/mw-config/images/tick-32.png b/mw-config/images/tick-32.png
new file mode 100644 (file)
index 0000000..34cfa9c
Binary files /dev/null and b/mw-config/images/tick-32.png differ
diff --git a/mw-config/images/warning-32.png b/mw-config/images/warning-32.png
new file mode 100644 (file)
index 0000000..0400734
Binary files /dev/null and b/mw-config/images/warning-32.png differ
index 56c1308..a6cebc3 100644 (file)
  * @file
  */
 
+// Bail if PHP is too low
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
+       // We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
+       require dirname( dirname( __FILE__ ) ) . '/includes/PHPVersionError.php';
+       wfPHPVersionError( 'mw-config/index.php' );
+}
+
 define( 'MW_CONFIG_CALLBACK', 'Installer::overrideConfig' );
 define( 'MEDIAWIKI_INSTALL', true );
 
@@ -37,7 +44,7 @@ function wfInstallerMain() {
 
        if ( !$installer->startSession() ) {
 
-               if( $installer->request->getVal( "css" ) ) {
+               if ( $installer->request->getVal( "css" ) ) {
                        // Do not display errors on css pages
                        $installer->outputCss();
                        exit;
index 8120599..762af69 100644 (file)
@@ -163,15 +163,18 @@ if ( isset( $_REQUEST['expand'] ) ) {
        }
 }
 
+// @codingStandardsIgnoreStart
 class profile_point {
-       var $name;
-       var $count;
-       var $time;
-       var $children;
+       // @codingStandardsIgnoreEnd
 
-       static $totaltime, $totalmemory, $totalcount;
+       public $name;
+       public $count;
+       public $time;
+       public $children;
 
-       function __construct( $name, $count, $time, $memory ) {
+       public static $totaltime, $totalmemory, $totalcount;
+
+       public function __construct( $name, $count, $time, $memory ) {
                $this->name = $name;
                $this->count = $count;
                $this->time = $time;
@@ -179,11 +182,11 @@ class profile_point {
                $this->children = array();
        }
 
-       function add_child( $child ) {
+       public function add_child( $child ) {
                $this->children[] = $child;
        }
 
-       function display( $expand, $indent = 0.0 ) {
+       public function display( $expand, $indent = 0.0 ) {
                usort( $this->children, 'compare_point' );
 
                $ex = isset( $expand[$this->name()] );
@@ -214,6 +217,7 @@ class profile_point {
                                <?php echo htmlspecialchars( str_replace( ',', ', ', $this->name() ) ) . $extet ?>
                        </div>
                </th>
+               <?php //@codingStandardsIgnoreStart ?>
                <td class="mw-profileinfo-timep"><?php echo @wfPercent( $this->time() / self::$totaltime * 100 ); ?></td>
                <td class="mw-profileinfo-memoryp"><?php echo @wfPercent( $this->memory() / self::$totalmemory * 100 ); ?></td>
                <td class="mw-profileinfo-count"><?php echo $this->count(); ?></td>
@@ -222,6 +226,7 @@ class profile_point {
                <td class="mw-profileinfo-mpc"><?php echo round( sprintf( '%.2f', $this->memoryPerCall() / 1024 ), 2 ); ?></td>
                <td class="mw-profileinfo-tpr"><?php echo @round( sprintf( '%.2f', $this->time() / self::$totalcount ), 2 ); ?></td>
                <td class="mw-profileinfo-mpr"><?php echo @round( sprintf( '%.2f', $this->memory() / self::$totalcount / 1024 ), 2 ); ?></td>
+               <?php //@codingStandardsIgnoreEnd ?>
        </tr>
                <?php
                if ( $ex ) {
@@ -231,49 +236,61 @@ class profile_point {
                }
        }
 
-       function name() {
+       public function name() {
                return $this->name;
        }
 
-       function count() {
+       public function count() {
                return $this->count;
        }
 
-       function time() {
+       public function time() {
                return $this->time;
        }
 
-       function memory() {
+       public function memory() {
                return $this->memory;
        }
 
-       function timePerCall() {
+       public function timePerCall() {
+               // @codingStandardsIgnoreStart
                return @( $this->time / $this->count );
+               // @codingStandardsIgnoreEnd
        }
 
-       function memoryPerCall() {
+       public function memoryPerCall() {
+               // @codingStandardsIgnoreStart
                return @( $this->memory / $this->count );
+               // @codingStandardsIgnoreEnd
        }
 
-       function callsPerRequest() {
+       public function callsPerRequest() {
+               // @codingStandardsIgnoreStart
                return @( $this->count / self::$totalcount );
+               // @codingStandardsIgnoreEnd
        }
 
-       function timePerRequest() {
+       public function timePerRequest() {
+               // @codingStandardsIgnoreStart
                return @( $this->time / self::$totalcount );
+               // @codingStandardsIgnoreEnd
        }
 
-       function memoryPerRequest() {
+       public function memoryPerRequest() {
+               // @codingStandardsIgnoreStart
                return @( $this->memory / self::$totalcount );
+               // @codingStandardsIgnoreEnd
        }
 
-       function fmttime() {
+       public function fmttime() {
                return sprintf( '%5.02f', $this->time );
        }
 };
 
 function compare_point( profile_point $a, profile_point $b ) {
+       // @codingStandardsIgnoreStart
        global $sort;
+       // @codingStandardsIgnoreEnd
        switch ( $sort ) {
                case 'name':
                        return strcmp( $a->name(), $b->name() );
@@ -342,7 +359,9 @@ if ( isset( $_REQUEST['filter'] ) ) {
        profile_point::$totalmemory = 0.0;
 
        function getEscapedProfileUrl( $_filter = false, $_sort = false, $_expand = false ) {
+               // @codingStandardsIgnoreStart
                global $filter, $sort, $expand;
+               // @codingStandardsIgnoreEnd
 
                if ( $_expand === false ) {
                        $_expand = $expand;
index 4f854fb..9f64da4 100644 (file)
@@ -83,41 +83,40 @@ return array(
         */
        'mediawiki.skinning.elements' => array(
                'styles' => array(
-                       'commonElements.css' => array( 'media' => 'screen' ),
+                       'resources/src/mediawiki.skinning/elements.css' => array( 'media' => 'screen' ),
                ),
-               'remoteSkinPath' => 'common',
-               'localBasePath' => $GLOBALS['wgStyleDirectory'] . '/common',
        ),
        'mediawiki.skinning.content' => array(
                'styles' => array(
-                       'commonElements.css' => array( 'media' => 'screen' ),
-                       'commonContent.css' => array( 'media' => 'screen' ),
+                       'resources/src/mediawiki.skinning/elements.css' => array( 'media' => 'screen' ),
+                       'resources/src/mediawiki.skinning/content.css' => array( 'media' => 'screen' ),
                ),
-               'remoteSkinPath' => 'common',
-               'localBasePath' => $GLOBALS['wgStyleDirectory'] . '/common',
        ),
        'mediawiki.skinning.interface' => array(
                // Used in the web installer. Test it after modifying this definition!
                'styles' => array(
-                       'commonElements.css' => array( 'media' => 'screen' ),
-                       'commonContent.css' => array( 'media' => 'screen' ),
-                       'commonInterface.css' => array( 'media' => 'screen' ),
+                       'resources/src/mediawiki.skinning/elements.css' => array( 'media' => 'screen' ),
+                       'resources/src/mediawiki.skinning/content.css' => array( 'media' => 'screen' ),
+                       'resources/src/mediawiki.skinning/interface.css' => array( 'media' => 'screen' ),
                ),
-               'remoteSkinPath' => 'common',
-               'localBasePath' => $GLOBALS['wgStyleDirectory'] . '/common',
        ),
 
        'mediawiki.skinning.content.parsoid' => array(
                // Style Parsoid HTML+RDFa output consistent with wikitext from PHP parser
-               // with the commonInterface.css styles; skinStyles should be used if your
+               // with the interface.css styles; skinStyles should be used if your
                // skin over-rides common content styling.
                'skinStyles' => array(
                        'default' => 'resources/src/mediawiki.skinning/content.parsoid.less',
-                       'minerva' => array(),
                ),
                'targets' => array( 'desktop', 'mobile' ),
        ),
 
+       'mediawiki.skinning.content.externallinks' => array(
+               'styles' => array(
+                       'resources/src/mediawiki.skinning/content.externallinks.css' => array( 'media' => 'screen' ),
+               ),
+       ),
+
        /* jQuery */
 
        'jquery' => array(
@@ -129,7 +128,7 @@ return array(
                        array(
                                'resources/lib/jquery/jquery.js'
                        ) ),
-               'debugRaw' => false,
+               'raw' => true,
                'targets' => array( 'desktop', 'mobile' ),
        ),
 
@@ -192,6 +191,19 @@ return array(
        'jquery.colorUtil' => array(
                'scripts' => 'resources/src/jquery/jquery.colorUtil.js',
        ),
+       'jquery.confirmable' => array(
+               'scripts' => array(
+                       'resources/src/jquery/jquery.confirmable.js',
+                       'resources/src/jquery/jquery.confirmable.mediawiki.js',
+               ),
+               'messages' => array(
+                       'confirmable-confirm',
+                       'confirmable-yes',
+                       'confirmable-no',
+               ),
+               'styles' => 'resources/src/jquery/jquery.confirmable.css',
+               'dependencies' => 'mediawiki.jqueryMsg',
+       ),
        // Use mediawiki.cookie in new code, rather than jquery.cookie.
        'jquery.cookie' => array(
                'scripts' => 'resources/lib/jquery/jquery.cookie.js',
@@ -329,10 +341,6 @@ return array(
                                'resources/lib/jquery.ui/themes/smoothness/jquery.ui.core.css',
                                'resources/lib/jquery.ui/themes/smoothness/jquery.ui.theme.css',
                        ),
-                       'vector' => array(
-                               'resources/src/jquery.ui-themes/vector/jquery.ui.core.css',
-                               'resources/src/jquery.ui-themes/vector/jquery.ui.theme.css',
-                       ),
                ),
                'group' => 'jquery.ui',
        ),
@@ -344,7 +352,6 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.accordion.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.accordion.css',
                ),
                'group' => 'jquery.ui',
        ),
@@ -358,7 +365,6 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.autocomplete.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.autocomplete.css',
                ),
                'group' => 'jquery.ui',
        ),
@@ -370,7 +376,6 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.button.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.button.css',
                ),
                'group' => 'jquery.ui',
        ),
@@ -379,7 +384,6 @@ return array(
                'dependencies' => 'jquery.ui.core',
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.datepicker.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.datepicker.css',
                ),
                'languageScripts' => array(
                        'af' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-af.js',
@@ -465,7 +469,6 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.dialog.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.dialog.css',
                ),
                'group' => 'jquery.ui',
        ),
@@ -517,7 +520,6 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.progressbar.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.progressbar.css',
                ),
                'group' => 'jquery.ui',
        ),
@@ -530,7 +532,6 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.resizable.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.resizable.css',
                ),
                'group' => 'jquery.ui',
        ),
@@ -543,7 +544,6 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.selectable.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.selectable.css',
                ),
                'group' => 'jquery.ui',
        ),
@@ -556,7 +556,6 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.slider.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.slider.css',
                ),
                'group' => 'jquery.ui',
        ),
@@ -589,7 +588,6 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.tabs.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.tabs.css',
                ),
                'group' => 'jquery.ui',
        ),
@@ -693,78 +691,82 @@ return array(
        'moment' => array(
                'scripts' => 'resources/lib/moment/moment.js',
                'languageScripts' => array(
-                       'ar' => 'resources/lib/moment/lang/ar.js',
-                       'ar-ma' => 'resources/lib/moment/lang/ar-ma.js',
-                       'ar-sa' => 'resources/lib/moment/lang/ar-sa.js',
-                       'az' => 'resources/lib/moment/lang/az.js',
-                       'bg' => 'resources/lib/moment/lang/bg.js',
-                       'bn' => 'resources/lib/moment/lang/bn.js',
-                       'br' => 'resources/lib/moment/lang/br.js',
-                       'bs' => 'resources/lib/moment/lang/bs.js',
-                       'ca' => 'resources/lib/moment/lang/ca.js',
-                       'cs' => 'resources/lib/moment/lang/cs.js',
-                       'cv' => 'resources/lib/moment/lang/cv.js',
-                       'cy' => 'resources/lib/moment/lang/cy.js',
-                       'da' => 'resources/lib/moment/lang/da.js',
-                       'de' => 'resources/lib/moment/lang/de.js',
-                       'de-at' => 'resources/lib/moment/lang/de-at.js',
-                       'el' => 'resources/lib/moment/lang/el.js',
-                       'en-au' => 'resources/lib/moment/lang/en-au.js',
-                       'en-ca' => 'resources/lib/moment/lang/en-ca.js',
-                       'en-gb' => 'resources/lib/moment/lang/en-gb.js',
-                       'eo' => 'resources/lib/moment/lang/eo.js',
-                       'es' => 'resources/lib/moment/lang/es.js',
-                       'et' => 'resources/lib/moment/lang/et.js',
-                       'eu' => 'resources/lib/moment/lang/eu.js',
-                       'fa' => 'resources/lib/moment/lang/fa.js',
-                       'fi' => 'resources/lib/moment/lang/fi.js',
-                       'fo' => 'resources/lib/moment/lang/fo.js',
-                       'fr-ca' => 'resources/lib/moment/lang/fr-ca.js',
-                       'fr' => 'resources/lib/moment/lang/fr.js',
-                       'gl' => 'resources/lib/moment/lang/gl.js',
-                       'he' => 'resources/lib/moment/lang/he.js',
-                       'hi' => 'resources/lib/moment/lang/hi.js',
-                       'hr' => 'resources/lib/moment/lang/hr.js',
-                       'hu' => 'resources/lib/moment/lang/hu.js',
-                       'hy-am' => 'resources/lib/moment/lang/hy-am.js',
-                       'id' => 'resources/lib/moment/lang/id.js',
-                       'is' => 'resources/lib/moment/lang/is.js',
-                       'it' => 'resources/lib/moment/lang/it.js',
-                       'ja' => 'resources/lib/moment/lang/ja.js',
-                       'ka' => 'resources/lib/moment/lang/ka.js',
-                       'ko' => 'resources/lib/moment/lang/ko.js',
-                       'lt' => 'resources/lib/moment/lang/lt.js',
-                       'lv' => 'resources/lib/moment/lang/lv.js',
-                       'mk' => 'resources/lib/moment/lang/mk.js',
-                       'ml' => 'resources/lib/moment/lang/ml.js',
-                       'mr' => 'resources/lib/moment/lang/mr.js',
-                       'ms-my' => 'resources/lib/moment/lang/ms-my.js',
-                       'nb' => 'resources/lib/moment/lang/nb.js',
-                       'ne' => 'resources/lib/moment/lang/ne.js',
-                       'nl' => 'resources/lib/moment/lang/nl.js',
-                       'nn' => 'resources/lib/moment/lang/nn.js',
-                       'pl' => 'resources/lib/moment/lang/pl.js',
-                       'pt-br' => 'resources/lib/moment/lang/pt-br.js',
-                       'pt' => 'resources/lib/moment/lang/pt.js',
-                       'ro' => 'resources/lib/moment/lang/ro.js',
-                       'ru' => 'resources/lib/moment/lang/ru.js',
-                       'sk' => 'resources/lib/moment/lang/sk.js',
-                       'sl' => 'resources/lib/moment/lang/sl.js',
-                       'sq' => 'resources/lib/moment/lang/sq.js',
-                       'sr' => 'resources/lib/moment/lang/sr.js',
-                       'sr-ec' => 'resources/lib/moment/lang/sr-cyrl.js',
-                       'sv' => 'resources/lib/moment/lang/sv.js',
-                       'ta' => 'resources/lib/moment/lang/ta.js',
-                       'th' => 'resources/lib/moment/lang/th.js',
-                       'tl-ph' => 'resources/lib/moment/lang/tl-ph.js',
-                       'tr' => 'resources/lib/moment/lang/tr.js',
-                       'tzm' => 'resources/lib/moment/lang/tzm.js',
-                       'tzm-latn' => 'resources/lib/moment/lang/tzm-latn.js',
-                       'uk' => 'resources/lib/moment/lang/uk.js',
-                       'uz' => 'resources/lib/moment/lang/uz.js',
-                       'vi' => 'resources/lib/moment/lang/vi.js',
-                       'zh-cn' => 'resources/lib/moment/lang/zh-cn.js',
-                       'zh-tw' => 'resources/lib/moment/lang/zh-tw.js',
+                       'af' => 'resources/lib/moment/locale/af.js',
+                       'ar' => 'resources/lib/moment/locale/ar.js',
+                       'ar-ma' => 'resources/lib/moment/locale/ar-ma.js',
+                       'ar-sa' => 'resources/lib/moment/locale/ar-sa.js',
+                       'az' => 'resources/lib/moment/locale/az.js',
+                       'be' => 'resources/lib/moment/locale/be.js',
+                       'bg' => 'resources/lib/moment/locale/bg.js',
+                       'bn' => 'resources/lib/moment/locale/bn.js',
+                       'bo' => 'resources/lib/moment/locale/bo.js',
+                       'br' => 'resources/lib/moment/locale/br.js',
+                       'bs' => 'resources/lib/moment/locale/bs.js',
+                       'ca' => 'resources/lib/moment/locale/ca.js',
+                       'cs' => 'resources/lib/moment/locale/cs.js',
+                       'cv' => 'resources/lib/moment/locale/cv.js',
+                       'cy' => 'resources/lib/moment/locale/cy.js',
+                       'da' => 'resources/lib/moment/locale/da.js',
+                       'de' => 'resources/lib/moment/locale/de.js',
+                       'de-at' => 'resources/lib/moment/locale/de-at.js',
+                       'el' => 'resources/lib/moment/locale/el.js',
+                       'en-au' => 'resources/lib/moment/locale/en-au.js',
+                       'en-ca' => 'resources/lib/moment/locale/en-ca.js',
+                       'en-gb' => 'resources/lib/moment/locale/en-gb.js',
+                       'eo' => 'resources/lib/moment/locale/eo.js',
+                       'es' => 'resources/lib/moment/locale/es.js',
+                       'et' => 'resources/lib/moment/locale/et.js',
+                       'eu' => 'resources/lib/moment/locale/eu.js',
+                       'fa' => 'resources/lib/moment/locale/fa.js',
+                       'fi' => 'resources/lib/moment/locale/fi.js',
+                       'fo' => 'resources/lib/moment/locale/fo.js',
+                       'fr-ca' => 'resources/lib/moment/locale/fr-ca.js',
+                       'fr' => 'resources/lib/moment/locale/fr.js',
+                       'gl' => 'resources/lib/moment/locale/gl.js',
+                       'he' => 'resources/lib/moment/locale/he.js',
+                       'hi' => 'resources/lib/moment/locale/hi.js',
+                       'hr' => 'resources/lib/moment/locale/hr.js',
+                       'hu' => 'resources/lib/moment/locale/hu.js',
+                       'hy-am' => 'resources/lib/moment/locale/hy-am.js',
+                       'id' => 'resources/lib/moment/locale/id.js',
+                       'is' => 'resources/lib/moment/locale/is.js',
+                       'it' => 'resources/lib/moment/locale/it.js',
+                       'ja' => 'resources/lib/moment/locale/ja.js',
+                       'ka' => 'resources/lib/moment/locale/ka.js',
+                       'ko' => 'resources/lib/moment/locale/ko.js',
+                       'lt' => 'resources/lib/moment/locale/lt.js',
+                       'lv' => 'resources/lib/moment/locale/lv.js',
+                       'mk' => 'resources/lib/moment/locale/mk.js',
+                       'ml' => 'resources/lib/moment/locale/ml.js',
+                       'mr' => 'resources/lib/moment/locale/mr.js',
+                       'ms-my' => 'resources/lib/moment/locale/ms-my.js',
+                       'my' => 'resources/lib/moment/locale/my.js',
+                       'nb' => 'resources/lib/moment/locale/nb.js',
+                       'ne' => 'resources/lib/moment/locale/ne.js',
+                       'nl' => 'resources/lib/moment/locale/nl.js',
+                       'nn' => 'resources/lib/moment/locale/nn.js',
+                       'pl' => 'resources/lib/moment/locale/pl.js',
+                       'pt-br' => 'resources/lib/moment/locale/pt-br.js',
+                       'pt' => 'resources/lib/moment/locale/pt.js',
+                       'ro' => 'resources/lib/moment/locale/ro.js',
+                       'ru' => 'resources/lib/moment/locale/ru.js',
+                       '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',
+                       'sv' => 'resources/lib/moment/locale/sv.js',
+                       'ta' => 'resources/lib/moment/locale/ta.js',
+                       'th' => 'resources/lib/moment/locale/th.js',
+                       'tl-ph' => 'resources/lib/moment/locale/tl-ph.js',
+                       'tr' => 'resources/lib/moment/locale/tr.js',
+                       'tzm' => 'resources/lib/moment/locale/tzm.js',
+                       'tzm-latn' => 'resources/lib/moment/locale/tzm-latn.js',
+                       'uk' => 'resources/lib/moment/locale/uk.js',
+                       'uz' => 'resources/lib/moment/locale/uz.js',
+                       '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',
                ),
        ),
 
@@ -773,7 +775,7 @@ return array(
        'mediawiki' => array(
                'scripts' => 'resources/src/mediawiki/mediawiki.js',
                'debugScripts' => 'resources/src/mediawiki/mediawiki.log.js',
-               'debugRaw' => false,
+               'raw' => true,
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.api' => array(
@@ -813,6 +815,9 @@ return array(
                        'user.tokens',
                ),
        ),
+       'mediawiki.content.json' => array(
+               'styles' => 'resources/src/mediawiki/mediawiki.content.json.css',
+       ),
        'mediawiki.debug' => array(
                'scripts' => array(
                        'resources/src/mediawiki/mediawiki.debug.js',
@@ -865,6 +870,7 @@ return array(
                'dependencies' => array(
                        'jquery.hidpi',
                ),
+               'skipFunction' => 'resources/src/mediawiki.hidpi-skip.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.hlist' => array(
@@ -876,6 +882,9 @@ return array(
        ),
        'mediawiki.htmlform' => array(
                'scripts' => 'resources/src/mediawiki/mediawiki.htmlform.js',
+               'dependencies' => array(
+                       'jquery.mwExtension',
+               ),
                'messages' => array( 'htmlform-chosen-placeholder' ),
        ),
        'mediawiki.icon' => array(
@@ -905,6 +914,10 @@ return array(
                'scripts' => 'resources/src/mediawiki/mediawiki.notify.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
+       'mediawiki.pager.tablePager' => array(
+               'styles' => 'resources/src/mediawiki/mediawiki.pager.tablePager.less',
+               'position' => 'top',
+       ),
        'mediawiki.searchSuggest' => array(
                'scripts' => 'resources/src/mediawiki/mediawiki.searchSuggest.js',
                'styles' => 'resources/src/mediawiki/mediawiki.searchSuggest.css',
@@ -937,6 +950,7 @@ return array(
        ),
        'mediawiki.Uri' => array(
                'scripts' => 'resources/src/mediawiki/mediawiki.Uri.js',
+               'dependencies' => 'mediawiki.util',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.user' => array(
@@ -970,8 +984,10 @@ return array(
 
        'mediawiki.action.edit' => array(
                'scripts' => 'resources/src/mediawiki.action/mediawiki.action.edit.js',
+               'styles' => 'resources/src/mediawiki.action/mediawiki.action.edit.css',
                'dependencies' => array(
                        'mediawiki.action.edit.styles',
+                       'mediawiki.action.edit.toolbar',
                        'jquery.textSelection',
                        'jquery.byteLimit',
                ),
@@ -981,6 +997,10 @@ return array(
                'styles' => 'resources/src/mediawiki.action/mediawiki.action.edit.styles.css',
                'position' => 'top',
        ),
+       'mediawiki.action.edit.toolbar' => array(
+               'class' => 'ResourceLoaderEditToolbarModule',
+               'styles' => 'resources/src/mediawiki.action/mediawiki.action.edit.toolbar/mediawiki.action.edit.toolbar.less',
+       ),
        'mediawiki.action.edit.collapsibleFooter' => array(
                'scripts' => 'resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js',
                'styles' => 'resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css',
@@ -1016,6 +1036,7 @@ return array(
                ),
        ),
        'mediawiki.action.view.metadata' => array(
+               'styles' => 'resources/src/mediawiki.action/mediawiki.action.view.metadata.css',
                'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.metadata.js',
                'messages' => array(
                        'metadata-expand',
@@ -1035,19 +1056,29 @@ return array(
                        'postedit-confirmation-saved',
                ),
        ),
-       'mediawiki.action.view.redirectToFragment' => array(
-               'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.redirectToFragment.js',
+       'mediawiki.action.view.redirect' => array(
+               'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.redirect.js',
                'dependencies' => array(
                        'jquery.client',
                ),
                'position' => 'top',
        ),
+       // Deployment hack for compatibility with cached HTML, remove before 1.24 release
+       'mediawiki.action.view.redirectToFragment' => array(
+               'dependencies' => 'mediawiki.action.view.redirect',
+               'position' => 'top',
+       ),
+       'mediawiki.action.view.redirectPage' => array(
+               'styles' => 'resources/src/mediawiki.action/mediawiki.action.view.redirectPage.css',
+               'position' => 'top',
+       ),
        'mediawiki.action.view.rightClickEdit' => array(
                'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.rightClickEdit.js',
        ),
        'mediawiki.action.edit.editWarning' => array(
                'scripts' => 'resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js',
                'dependencies' => array(
+                       'jquery.textSelection',
                        'mediawiki.jqueryMsg'
                ),
                'messages' => array(
@@ -1055,17 +1086,14 @@ return array(
                        'prefs-editing'
                ),
        ),
-       // Alias for backwards compatibility
-       'mediawiki.action.watch.ajax' => array(
-               'dependencies' => 'mediawiki.page.watch.ajax'
-       ),
 
        /* MediaWiki Language */
 
        'mediawiki.language' => array(
                'scripts' => array(
                        'resources/src/mediawiki.language/mediawiki.language.js',
-                       'resources/src/mediawiki.language/mediawiki.language.numbers.js'
+                       'resources/src/mediawiki.language/mediawiki.language.numbers.js',
+                       'resources/src/mediawiki.language/mediawiki.language.fallback.js',
                ),
                'languageScripts' => array(
                        'bs' => 'resources/src/mediawiki.language/languages/bs.js',
@@ -1087,6 +1115,11 @@ return array(
                                'mediawiki.cldr',
                        ),
                'targets' => array( 'desktop', 'mobile' ),
+               'messages' => array(
+                       'and',
+                       'comma-separator',
+                       'word-separator'
+               ),
        ),
 
        'mediawiki.cldr' => array(
@@ -1180,6 +1213,7 @@ return array(
                'dependencies' => array(
                        'mediawiki.api.watch',
                        'mediawiki.notify',
+                       'mediawiki.page.startup',
                        'mediawiki.util',
                        'jquery.accessKeyLabel',
                        'jquery.mwExtension',
@@ -1196,7 +1230,11 @@ return array(
        ),
        'mediawiki.page.image.pagination' => array(
                'scripts' => 'resources/src/mediawiki.page/mediawiki.page.image.pagination.js',
-               'dependencies' => array( 'jquery.spinner' )
+               'dependencies' => array(
+                       'mediawiki.Uri',
+                       'mediawiki.util',
+                       'jquery.spinner',
+               ),
        ),
 
        /* MediaWiki Special pages */
@@ -1204,9 +1242,6 @@ return array(
        'mediawiki.special' => array(
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.js',
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.css',
-               'skinStyles' => array(
-                       'vector' => 'skins/Vector/special.less', // FIXME this should use $wgStyleDirectory
-               ),
        ),
        'mediawiki.special.block' => array(
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.block.js',
@@ -1242,6 +1277,9 @@ return array(
        'mediawiki.special.changeslist.enhanced' => array(
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css',
        ),
+       'mediawiki.special.import' => array(
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.import.js',
+       ),
        'mediawiki.special.movePage' => array(
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.movePage.js',
                'dependencies' => 'jquery.byteLimit',
@@ -1256,9 +1294,6 @@ return array(
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.preferences.js',
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.preferences.css',
                'position' => 'top',
-               'skinStyles' => array(
-                       'vector' => 'skins/Vector/special.preferences.less', // FIXME this should use $wgStyleDirectory
-               ),
                'messages' => array(
                        'prefs-tabs-navigation-hint',
                ),
@@ -1284,7 +1319,6 @@ return array(
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.undelete.js',
        ),
        'mediawiki.special.upload' => array(
-               // @todo merge in remainder of mediawiki.legacy.upload
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.upload.js',
                'messages' => array(
                        'widthheight',
@@ -1295,7 +1329,10 @@ return array(
                        'largefileserver',
                ),
                'dependencies' => array(
+                       'jquery.spinner',
+                       'mediawiki.api',
                        'mediawiki.libs.jpegmeta',
+                       'mediawiki.Title',
                        'mediawiki.util',
                ),
        ),
@@ -1356,7 +1393,8 @@ return array(
                        'mediawiki.api',
                        'mediawiki.api.watch',
                        'mediawiki.notify',
-                       'mediawiki.Title'
+                       'mediawiki.Title',
+                       'mediawiki.util',
                ),
        ),
        'mediawiki.special.javaScriptTest' => array(
@@ -1373,66 +1411,50 @@ return array(
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.version.css',
        ),
 
+       /* MediaWiki Installer */
+
+       'mediawiki.legacy.config' => array(
+               // Used in the web installer. Test it after modifying this definition!
+               // These files are not actually loaded via ResourceLoader, so dependencies etc. won't work.
+               'scripts' => 'mw-config/config.js',
+               'styles' => 'mw-config/config.css',
+       ),
+
        /* MediaWiki Legacy */
 
        'mediawiki.legacy.ajax' => array(
-               'scripts' => 'common/ajax.js',
-               'remoteBasePath' => $GLOBALS['wgStylePath'],
-               'localBasePath' => $GLOBALS['wgStyleDirectory'],
+               'scripts' => 'resources/src/mediawiki.legacy/ajax.js',
                'dependencies' => array(
                        'mediawiki.util',
                        'mediawiki.legacy.wikibits',
                ),
-               'position' => 'top', // Temporary hack for legacy support
+               'position' => 'top',
        ),
        'mediawiki.legacy.commonPrint' => array(
-               'styles' => array( 'common/commonPrint.css' => array( 'media' => 'print' ) ),
-               'remoteBasePath' => $GLOBALS['wgStylePath'],
-               'localBasePath' => $GLOBALS['wgStyleDirectory'],
-       ),
-       'mediawiki.legacy.config' => array(
-               // Used in the web installer. Test it after modifying this definition!
-               'scripts' => 'common/config.js',
-               'styles' => array( 'common/config.css' ),
-               'remoteBasePath' => $GLOBALS['wgStylePath'],
-               'localBasePath' => $GLOBALS['wgStyleDirectory'],
-               'dependencies' => 'mediawiki.legacy.wikibits',
+               'styles' => array(
+                       'resources/src/mediawiki.legacy/commonPrint.css' => array( 'media' => 'print' )
+               ),
        ),
        'mediawiki.legacy.protect' => array(
-               'scripts' => 'common/protect.js',
-               'remoteBasePath' => $GLOBALS['wgStylePath'],
-               'localBasePath' => $GLOBALS['wgStyleDirectory'],
+               'scripts' => 'resources/src/mediawiki.legacy/protect.js',
                'dependencies' => array(
                        'jquery.byteLimit',
                ),
-               'position' => 'top',
+               'messages' => array( 'protect-unchain-permissions' )
        ),
        'mediawiki.legacy.shared' => array(
                // Used in the web installer. Test it after modifying this definition!
-               'styles' => array( 'common/shared.css' => array( 'media' => 'screen' ) ),
-               'remoteBasePath' => $GLOBALS['wgStylePath'],
-               'localBasePath' => $GLOBALS['wgStyleDirectory'],
+               'styles' => array(
+                       'resources/src/mediawiki.legacy/shared.css' => array( 'media' => 'screen' )
+               ),
        ),
        'mediawiki.legacy.oldshared' => array(
-               'styles' => array( 'common/oldshared.css' => array( 'media' => 'screen' ) ),
-               'remoteBasePath' => $GLOBALS['wgStylePath'],
-               'localBasePath' => $GLOBALS['wgStyleDirectory'],
-       ),
-       'mediawiki.legacy.upload' => array(
-               'scripts' => 'common/upload.js',
-               'remoteBasePath' => $GLOBALS['wgStylePath'],
-               'localBasePath' => $GLOBALS['wgStyleDirectory'],
-               'dependencies' => array(
-                       'jquery.spinner',
-                       'mediawiki.api',
-                       'mediawiki.Title',
-                       'mediawiki.util',
+               'styles' => array(
+                       'resources/src/mediawiki.legacy/oldshared.css' => array( 'media' => 'screen' )
                ),
        ),
        'mediawiki.legacy.wikibits' => array(
-               'scripts' => 'common/wikibits.js',
-               'remoteBasePath' => $GLOBALS['wgStylePath'],
-               'localBasePath' => $GLOBALS['wgStyleDirectory'],
+               'scripts' => 'resources/src/mediawiki.legacy/wikibits.js',
                'dependencies' => array(
                        'mediawiki.util',
                ),
@@ -1442,18 +1464,38 @@ return array(
        /* MediaWiki UI */
 
        'mediawiki.ui' => array(
-               'skinStyles' => array(
-                       'default' => 'resources/src/mediawiki.ui/default.less',
-                       'vector' => 'resources/src/mediawiki.ui/vector.less',
+               'styles' => array(
+                       'resources/src/mediawiki.ui/default.less',
+               ),
+               'position' => 'top',
+               'targets' => array( 'desktop', 'mobile' ),
+       ),
+       'mediawiki.ui.checkbox' => array(
+               'styles' => array(
+                       'resources/src/mediawiki.ui/components/checkbox.less',
+               ),
+               'position' => 'top',
+               'targets' => array( 'desktop', 'mobile' ),
+       ),
+       // Lightweight module for anchor styles
+       'mediawiki.ui.anchor' => array(
+               'styles' => array(
+                       'resources/src/mediawiki.ui/components/anchors.less',
                ),
                'position' => 'top',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        // Lightweight module for button styles
        'mediawiki.ui.button' => array(
-               'skinStyles' => array(
-                       'default' => 'resources/src/mediawiki.ui/components/default/buttons.less',
-                       'vector' => 'resources/src/mediawiki.ui/components/vector/buttons.less',
+               'styles' => array(
+                       'resources/src/mediawiki.ui/components/buttons.less',
+               ),
+               'position' => 'top',
+               'targets' => array( 'desktop', 'mobile' ),
+       ),
+       'mediawiki.ui.input' => array(
+               'styles' => array(
+                       'resources/src/mediawiki.ui/components/inputs.less',
                ),
                'position' => 'top',
                'targets' => array( 'desktop', 'mobile' ),
@@ -1463,6 +1505,7 @@ return array(
        'es5-shim' => array(
                'scripts' => array(
                        'resources/lib/es5-shim/es5-shim.js',
+                       'resources/src/polyfill-object-create.js',
                ),
                'targets' => array( 'desktop', 'mobile' ),
                'skipFunction' => 'resources/src/es5-skip.js',
@@ -1471,7 +1514,7 @@ return array(
        /* OOjs */
        'oojs' => array(
                'scripts' => array(
-                       'resources/lib/oojs/oojs.js',
+                       'resources/lib/oojs/oojs.jquery.js',
                ),
                'targets' => array( 'desktop', 'mobile' ),
                'dependencies' => array(
@@ -1492,18 +1535,19 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/oojs-ui/oojs-ui-apex.css',
-                       'minerva' => 'resources/lib/oojs-ui/oojs-ui-agora.css',
+                       // FIXME As of July 2014, this is to be gone "in a couple of months".
+                       'minerva' => 'resources/lib/oojs-ui/oojs-ui-minerva.css',
                ),
                'messages' => array(
-                       'ooui-dialog-action-close',
                        'ooui-outline-control-move-down',
                        'ooui-outline-control-move-up',
                        'ooui-outline-control-remove',
                        'ooui-toolbar-more',
-                       'ooui-dialog-confirm-title',
-                       'ooui-dialog-confirm-default-prompt',
-                       'ooui-dialog-confirm-default-ok',
-                       'ooui-dialog-confirm-default-cancel'
+                       'ooui-dialog-message-accept',
+                       'ooui-dialog-message-reject',
+                       'ooui-dialog-process-dismiss',
+                       'ooui-dialog-process-error',
+                       'ooui-dialog-process-retry',
                ),
                'dependencies' => array(
                        'es5-shim',
index 02048c0..4595994 100644 (file)
@@ -366,7 +366,6 @@ var spliceWorksWithEmptyObject = (function () {
     ArrayPrototype.splice.call(obj, 0, 0, 1);
     return obj.length === 1;
 }());
-var omittingSecondSpliceArgIsNoop = [1].splice(0).length === 0;
 defineProperties(ArrayPrototype, {
     splice: function splice(start, deleteCount) {
         if (arguments.length === 0) { return []; }
@@ -375,14 +374,14 @@ defineProperties(ArrayPrototype, {
         if (arguments.length > 0 && typeof deleteCount !== 'number') {
             args = _Array_slice_.call(arguments);
             if (args.length < 2) {
-                args.push(toInteger(deleteCount));
+                args.push(this.length - start);
             } else {
                 args[1] = toInteger(deleteCount);
             }
         }
         return array_splice.apply(this, args);
     }
-}, !omittingSecondSpliceArgIsNoop || !spliceWorksWithEmptyObject);
+}, !spliceWorksWithEmptyObject);
 
 // ES5 15.4.4.12
 // http://es5.github.com/#x15.4.4.13
@@ -674,7 +673,7 @@ defineProperties(ArrayPrototype, {
 // ES5 15.4.4.14
 // http://es5.github.com/#x15.4.4.14
 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
-var hasFirefox2IndexOfBug = [0, 1].indexOf(1, 2) !== -1;
+var hasFirefox2IndexOfBug = Array.prototype.indexOf && [0, 1].indexOf(1, 2) !== -1;
 defineProperties(ArrayPrototype, {
     indexOf: function indexOf(sought /*, fromIndex */ ) {
         var self = splitString && isString(this) ? this.split('') : toObject(this),
@@ -703,7 +702,7 @@ defineProperties(ArrayPrototype, {
 // ES5 15.4.4.15
 // http://es5.github.com/#x15.4.4.15
 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
-var hasFirefox2LastIndexOfBug = [0, 1].lastIndexOf(0, -3) !== -1;
+var hasFirefox2LastIndexOfBug = Array.prototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;
 defineProperties(ArrayPrototype, {
     lastIndexOf: function lastIndexOf(sought /*, fromIndex */) {
         var self = splitString && isString(this) ? this.split('') : toObject(this),
@@ -1082,7 +1081,7 @@ if (!Date.now) {
 // http://es5.github.com/#x15.7.4.5
 var hasToFixedBugs = NumberPrototype.toFixed && (
   (0.00008).toFixed(3) !== '0.000'
-  || (0.9).toFixed(0) === '0'
+  || (0.9).toFixed(0) !== '1'
   || (1.255).toFixed(2) !== '1.25'
   || (1000000000000000128).toFixed(0) !== "1000000000000000128"
 );
index 6d5974a..3fb201c 100644 (file)
@@ -1,47 +1,90 @@
 /*!
- * jQuery Cookie Plugin
+ * jQuery Cookie Plugin v1.3.1
  * https://github.com/carhartl/jquery-cookie
  *
- * Copyright 2011, Klaus Hartl
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.opensource.org/licenses/GPL-2.0
+ * Copyright 2013 Klaus Hartl
+ * Released under the MIT license
  */
-(function($) {
-    $.cookie = function(key, value, options) {
-
-        // key and at least value given, set cookie...
-        if (arguments.length > 1 && (!/Object/.test(Object.prototype.toString.call(value)) || value === null || value === undefined)) {
-            options = $.extend({}, options);
-
-            if (value === null || value === undefined) {
-                options.expires = -1;
-            }
-
-            if (typeof options.expires === 'number') {
-                var days = options.expires, t = options.expires = new Date();
-                t.setDate(t.getDate() + days);
-            }
-
-            value = String(value);
-
-            return (document.cookie = [
-                encodeURIComponent(key), '=', options.raw ? value : encodeURIComponent(value),
-                options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
-                options.path    ? '; path=' + options.path : '',
-                options.domain  ? '; domain=' + options.domain : '',
-                options.secure  ? '; secure' : ''
-            ].join(''));
-        }
-
-        // key and possibly options given, get cookie...
-        options = value || {};
-        var decode = options.raw ? function(s) { return s; } : decodeURIComponent;
-
-        var pairs = document.cookie.split('; ');
-        for (var i = 0, pair; pair = pairs[i] && pairs[i].split('='); i++) {
-            if (decode(pair[0]) === key) return decode(pair[1] || ''); // IE saves cookies with empty string as "c; ", e.g. without "=" as opposed to EOMB, thus pair[1] may be undefined
-        }
-        return null;
-    };
-})(jQuery);
+(function ($, document, undefined) {
+
+       var pluses = /\+/g;
+
+       function raw(s) {
+               return s;
+       }
+
+       function decoded(s) {
+               return unRfc2068(decodeURIComponent(s.replace(pluses, ' ')));
+       }
+
+       function unRfc2068(value) {
+               if (value.indexOf('"') === 0) {
+                       // This is a quoted cookie as according to RFC2068, unescape
+                       value = value.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
+               }
+               return value;
+       }
+
+       function fromJSON(value) {
+               return config.json ? JSON.parse(value) : value;
+       }
+
+       var config = $.cookie = function (key, value, options) {
+
+               // write
+               if (value !== undefined) {
+                       options = $.extend({}, config.defaults, options);
+
+                       if (value === null) {
+                               options.expires = -1;
+                       }
+
+                       if (typeof options.expires === 'number') {
+                               var days = options.expires, t = options.expires = new Date();
+                               t.setDate(t.getDate() + days);
+                       }
+
+                       value = config.json ? JSON.stringify(value) : String(value);
+
+                       return (document.cookie = [
+                               encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value),
+                               options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+                               options.path    ? '; path=' + options.path : '',
+                               options.domain  ? '; domain=' + options.domain : '',
+                               options.secure  ? '; secure' : ''
+                       ].join(''));
+               }
+
+               // read
+               var decode = config.raw ? raw : decoded;
+               var cookies = document.cookie.split('; ');
+               var result = key ? null : {};
+               for (var i = 0, l = cookies.length; i < l; i++) {
+                       var parts = cookies[i].split('=');
+                       var name = decode(parts.shift());
+                       var cookie = decode(parts.join('='));
+
+                       if (key && key === name) {
+                               result = fromJSON(cookie);
+                               break;
+                       }
+
+                       if (!key) {
+                               result[name] = fromJSON(cookie);
+                       }
+               }
+
+               return result;
+       };
+
+       config.defaults = {};
+
+       $.removeCookie = function (key, options) {
+               if ($.cookie(key) !== null) {
+                       $.cookie(key, null, options);
+                       return true;
+               }
+               return false;
+       };
+
+})(jQuery, document);
diff --git a/resources/lib/moment/lang/ar-ma.js b/resources/lib/moment/lang/ar-ma.js
deleted file mode 100644 (file)
index 1c159f1..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// moment.js language configuration
-// language : Moroccan Arabic (ar-ma)
-// author : ElFadili Yassine : https://github.com/ElFadiliY
-// author : Abdel Said : https://github.com/abdelsaid
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ar-ma', {
-        months : "يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),
-        monthsShort : "يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),
-        weekdays : "الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),
-        weekdaysShort : "احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),
-        weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[اليوم على الساعة] LT",
-            nextDay: '[غدا على الساعة] LT',
-            nextWeek: 'dddd [على الساعة] LT',
-            lastDay: '[أمس على الساعة] LT',
-            lastWeek: 'dddd [على الساعة] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "في %s",
-            past : "منذ %s",
-            s : "ثوان",
-            m : "دقيقة",
-            mm : "%d دقائق",
-            h : "ساعة",
-            hh : "%d ساعات",
-            d : "يوم",
-            dd : "%d أيام",
-            M : "شهر",
-            MM : "%d أشهر",
-            y : "سنة",
-            yy : "%d سنوات"
-        },
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/ar-sa.js b/resources/lib/moment/lang/ar-sa.js
deleted file mode 100644 (file)
index 162d386..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-// moment.js language configuration
-// language : Arabic Saudi Arabia (ar-sa)
-// author : Suhail Alkowaileet : https://github.com/xsoh
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var symbolMap = {
-        '1': '١',
-        '2': '٢',
-        '3': '٣',
-        '4': '٤',
-        '5': '٥',
-        '6': '٦',
-        '7': '٧',
-        '8': '٨',
-        '9': '٩',
-        '0': '٠'
-    }, numberMap = {
-        '١': '1',
-        '٢': '2',
-        '٣': '3',
-        '٤': '4',
-        '٥': '5',
-        '٦': '6',
-        '٧': '7',
-        '٨': '8',
-        '٩': '9',
-        '٠': '0'
-    };
-
-    return moment.lang('ar-sa', {
-        months : "يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),
-        monthsShort : "يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),
-        weekdays : "الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),
-        weekdaysShort : "أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),
-        weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 12) {
-                return "ص";
-            } else {
-                return "م";
-            }
-        },
-        calendar : {
-            sameDay: "[اليوم على الساعة] LT",
-            nextDay: '[غدا على الساعة] LT',
-            nextWeek: 'dddd [على الساعة] LT',
-            lastDay: '[أمس على الساعة] LT',
-            lastWeek: 'dddd [على الساعة] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "في %s",
-            past : "منذ %s",
-            s : "ثوان",
-            m : "دقيقة",
-            mm : "%d دقائق",
-            h : "ساعة",
-            hh : "%d ساعات",
-            d : "يوم",
-            dd : "%d أيام",
-            M : "شهر",
-            MM : "%d أشهر",
-            y : "سنة",
-            yy : "%d سنوات"
-        },
-        preparse: function (string) {
-            return string.replace(/[۰-۹]/g, function (match) {
-                return numberMap[match];
-            }).replace(/،/g, ',');
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            }).replace(/,/g, '،');
-        },
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/ar.js b/resources/lib/moment/lang/ar.js
deleted file mode 100644 (file)
index dd01a42..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-// moment.js language configuration
-// language : Arabic (ar)
-// author : Abdel Said : https://github.com/abdelsaid
-// changes in months, weekdays : Ahmed Elkhatib
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var symbolMap = {
-        '1': '١',
-        '2': '٢',
-        '3': '٣',
-        '4': '٤',
-        '5': '٥',
-        '6': '٦',
-        '7': '٧',
-        '8': '٨',
-        '9': '٩',
-        '0': '٠'
-    }, numberMap = {
-        '١': '1',
-        '٢': '2',
-        '٣': '3',
-        '٤': '4',
-        '٥': '5',
-        '٦': '6',
-        '٧': '7',
-        '٨': '8',
-        '٩': '9',
-        '٠': '0'
-    };
-
-    return moment.lang('ar', {
-        months : "يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"),
-        monthsShort : "يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"),
-        weekdays : "الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),
-        weekdaysShort : "أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),
-        weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 12) {
-                return "ص";
-            } else {
-                return "م";
-            }
-        },
-        calendar : {
-            sameDay: "[اليوم على الساعة] LT",
-            nextDay: '[غدا على الساعة] LT',
-            nextWeek: 'dddd [على الساعة] LT',
-            lastDay: '[أمس على الساعة] LT',
-            lastWeek: 'dddd [على الساعة] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "في %s",
-            past : "منذ %s",
-            s : "ثوان",
-            m : "دقيقة",
-            mm : "%d دقائق",
-            h : "ساعة",
-            hh : "%d ساعات",
-            d : "يوم",
-            dd : "%d أيام",
-            M : "شهر",
-            MM : "%d أشهر",
-            y : "سنة",
-            yy : "%d سنوات"
-        },
-        preparse: function (string) {
-            return string.replace(/[۰-۹]/g, function (match) {
-                return numberMap[match];
-            }).replace(/،/g, ',');
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            }).replace(/,/g, '،');
-        },
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/az.js b/resources/lib/moment/lang/az.js
deleted file mode 100644 (file)
index bee1f9a..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-// moment.js language configuration
-// language : azerbaijani (az)
-// author : topchiyev : https://github.com/topchiyev
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    var suffixes = {
-        1: "-inci",
-        5: "-inci",
-        8: "-inci",
-        70: "-inci",
-        80: "-inci",
-
-        2: "-nci",
-        7: "-nci",
-        20: "-nci",
-        50: "-nci",
-
-        3: "-üncü",
-        4: "-üncü",
-        100: "-üncü",
-
-        6: "-ncı",
-
-        9: "-uncu",
-        10: "-uncu",
-        30: "-uncu",
-
-        60: "-ıncı",
-        90: "-ıncı"
-    };
-    return moment.lang('az', {
-        months : "yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr".split("_"),
-        monthsShort : "yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek".split("_"),
-        weekdays : "Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə".split("_"),
-        weekdaysShort : "Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən".split("_"),
-        weekdaysMin : "Bz_BE_ÇA_Çə_CA_Cü_Şə".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[bugün saat] LT',
-            nextDay : '[sabah saat] LT',
-            nextWeek : '[gələn həftə] dddd [saat] LT',
-            lastDay : '[dünən] LT',
-            lastWeek : '[keçən həftə] dddd [saat] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s sonra",
-            past : "%s əvvəl",
-            s : "birneçə saniyyə",
-            m : "bir dəqiqə",
-            mm : "%d dəqiqə",
-            h : "bir saat",
-            hh : "%d saat",
-            d : "bir gün",
-            dd : "%d gün",
-            M : "bir ay",
-            MM : "%d ay",
-            y : "bir il",
-            yy : "%d il"
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return "gecə";
-            } else if (hour < 12) {
-                return "səhər";
-            } else if (hour < 17) {
-                return "gündüz";
-            } else {
-                return "axşam";
-            }
-        },
-        ordinal : function (number) {
-            if (number === 0) {  // special case for zero
-                return number + "-ıncı";
-            }
-            var a = number % 10,
-                b = number % 100 - a,
-                c = number >= 100 ? 100 : null;
-
-            return number + (suffixes[a] || suffixes[b] || suffixes[c]);
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/bg.js b/resources/lib/moment/lang/bg.js
deleted file mode 100644 (file)
index f47ed65..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-// moment.js language configuration
-// language : bulgarian (bg)
-// author : Krasen Borisov : https://github.com/kraz
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('bg', {
-        months : "януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),
-        monthsShort : "янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),
-        weekdays : "неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),
-        weekdaysShort : "нед_пон_вто_сря_чет_пет_съб".split("_"),
-        weekdaysMin : "нд_пн_вт_ср_чт_пт_сб".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "D.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Днес в] LT',
-            nextDay : '[Утре в] LT',
-            nextWeek : 'dddd [в] LT',
-            lastDay : '[Вчера в] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                case 6:
-                    return '[В изминалата] dddd [в] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[В изминалия] dddd [в] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "след %s",
-            past : "преди %s",
-            s : "няколко секунди",
-            m : "минута",
-            mm : "%d минути",
-            h : "час",
-            hh : "%d часа",
-            d : "ден",
-            dd : "%d дни",
-            M : "месец",
-            MM : "%d месеца",
-            y : "година",
-            yy : "%d години"
-        },
-        ordinal : function (number) {
-            var lastDigit = number % 10,
-                last2Digits = number % 100;
-            if (number === 0) {
-                return number + '-ев';
-            } else if (last2Digits === 0) {
-                return number + '-ен';
-            } else if (last2Digits > 10 && last2Digits < 20) {
-                return number + '-ти';
-            } else if (lastDigit === 1) {
-                return number + '-ви';
-            } else if (lastDigit === 2) {
-                return number + '-ри';
-            } else if (lastDigit === 7 || lastDigit === 8) {
-                return number + '-ми';
-            } else {
-                return number + '-ти';
-            }
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/bn.js b/resources/lib/moment/lang/bn.js
deleted file mode 100644 (file)
index fb23bd0..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-// moment.js language configuration
-// language : Bengali (bn)
-// author : Kaushik Gandhi : https://github.com/kaushikgandhi
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var symbolMap = {
-        '1': '১',
-        '2': '২',
-        '3': '৩',
-        '4': '৪',
-        '5': '৫',
-        '6': '৬',
-        '7': '৭',
-        '8': '৮',
-        '9': '৯',
-        '0': '০'
-    },
-    numberMap = {
-        '১': '1',
-        '২': '2',
-        '৩': '3',
-        '৪': '4',
-        '৫': '5',
-        '৬': '6',
-        '৭': '7',
-        '৮': '8',
-        '৯': '9',
-        '০': '0'
-    };
-
-    return moment.lang('bn', {
-        months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split("_"),
-        monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split("_"),
-        weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রুবার_শনিবার'.split("_"),
-        weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্রু_শনি'.split("_"),
-        weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split("_"),
-        longDateFormat : {
-            LT : "A h:mm সময়",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY, LT",
-            LLLL : "dddd, D MMMM YYYY, LT"
-        },
-        calendar : {
-            sameDay : '[আজ] LT',
-            nextDay : '[আগামীকাল] LT',
-            nextWeek : 'dddd, LT',
-            lastDay : '[গতকাল] LT',
-            lastWeek : '[গত] dddd, LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s পরে",
-            past : "%s আগে",
-            s : "কএক সেকেন্ড",
-            m : "এক মিনিট",
-            mm : "%d মিনিট",
-            h : "এক ঘন্টা",
-            hh : "%d ঘন্টা",
-            d : "এক দিন",
-            dd : "%d দিন",
-            M : "এক মাস",
-            MM : "%d মাস",
-            y : "এক বছর",
-            yy : "%d বছর"
-        },
-        preparse: function (string) {
-            return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) {
-                return numberMap[match];
-            });
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            });
-        },
-        //Bengali is a vast language its spoken 
-        //in different forms in various parts of the world.
-        //I have just generalized with most common one used
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return "রাত";
-            } else if (hour < 10) {
-                return "শকাল";
-            } else if (hour < 17) {
-                return "দুপুর";
-            } else if (hour < 20) {
-                return "বিকেল";
-            } else {
-                return "রাত";
-            }
-        },
-        week : {
-            dow : 0, // Sunday is the first day of the week.
-            doy : 6  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/br.js b/resources/lib/moment/lang/br.js
deleted file mode 100644 (file)
index 39c60df..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// moment.js language configuration
-// language : breton (br)
-// author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function relativeTimeWithMutation(number, withoutSuffix, key) {
-        var format = {
-            'mm': "munutenn",
-            'MM': "miz",
-            'dd': "devezh"
-        };
-        return number + ' ' + mutation(format[key], number);
-    }
-
-    function specialMutationForYears(number) {
-        switch (lastNumber(number)) {
-        case 1:
-        case 3:
-        case 4:
-        case 5:
-        case 9:
-            return number + ' bloaz';
-        default:
-            return number + ' vloaz';
-        }
-    }
-
-    function lastNumber(number) {
-        if (number > 9) {
-            return lastNumber(number % 10);
-        }
-        return number;
-    }
-
-    function mutation(text, number) {
-        if (number === 2) {
-            return softMutation(text);
-        }
-        return text;
-    }
-
-    function softMutation(text) {
-        var mutationTable = {
-            'm': 'v',
-            'b': 'v',
-            'd': 'z'
-        };
-        if (mutationTable[text.charAt(0)] === undefined) {
-            return text;
-        }
-        return mutationTable[text.charAt(0)] + text.substring(1);
-    }
-
-    return moment.lang('br', {
-        months : "Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),
-        monthsShort : "Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),
-        weekdays : "Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"),
-        weekdaysShort : "Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),
-        weekdaysMin : "Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),
-        longDateFormat : {
-            LT : "h[e]mm A",
-            L : "DD/MM/YYYY",
-            LL : "D [a viz] MMMM YYYY",
-            LLL : "D [a viz] MMMM YYYY LT",
-            LLLL : "dddd, D [a viz] MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Hiziv da] LT',
-            nextDay : '[Warc\'hoazh da] LT',
-            nextWeek : 'dddd [da] LT',
-            lastDay : '[Dec\'h da] LT',
-            lastWeek : 'dddd [paset da] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "a-benn %s",
-            past : "%s 'zo",
-            s : "un nebeud segondennoù",
-            m : "ur vunutenn",
-            mm : relativeTimeWithMutation,
-            h : "un eur",
-            hh : "%d eur",
-            d : "un devezh",
-            dd : relativeTimeWithMutation,
-            M : "ur miz",
-            MM : relativeTimeWithMutation,
-            y : "ur bloaz",
-            yy : specialMutationForYears
-        },
-        ordinal : function (number) {
-            var output = (number === 1) ? 'añ' : 'vet';
-            return number + output;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/bs.js b/resources/lib/moment/lang/bs.js
deleted file mode 100644 (file)
index 83a9b4c..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-// moment.js language configuration
-// language : bosnian (bs)
-// author : Nedim Cholich : https://github.com/frontyard
-// based on (hr) translation by Bojan Marković
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    function translate(number, withoutSuffix, key) {
-        var result = number + " ";
-        switch (key) {
-        case 'm':
-            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
-        case 'mm':
-            if (number === 1) {
-                result += 'minuta';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'minute';
-            } else {
-                result += 'minuta';
-            }
-            return result;
-        case 'h':
-            return withoutSuffix ? 'jedan sat' : 'jednog sata';
-        case 'hh':
-            if (number === 1) {
-                result += 'sat';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'sata';
-            } else {
-                result += 'sati';
-            }
-            return result;
-        case 'dd':
-            if (number === 1) {
-                result += 'dan';
-            } else {
-                result += 'dana';
-            }
-            return result;
-        case 'MM':
-            if (number === 1) {
-                result += 'mjesec';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'mjeseca';
-            } else {
-                result += 'mjeseci';
-            }
-            return result;
-        case 'yy':
-            if (number === 1) {
-                result += 'godina';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'godine';
-            } else {
-                result += 'godina';
-            }
-            return result;
-        }
-    }
-
-    return moment.lang('bs', {
-               months : "januar_februar_mart_april_maj_juni_juli_avgust_septembar_oktobar_novembar_decembar".split("_"),
-               monthsShort : "jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),
-        weekdays : "nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),
-        weekdaysShort : "ned._pon._uto._sri._čet._pet._sub.".split("_"),
-        weekdaysMin : "ne_po_ut_sr_če_pe_su".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD. MM. YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd, D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay  : '[danas u] LT',
-            nextDay  : '[sutra u] LT',
-
-            nextWeek : function () {
-                switch (this.day()) {
-                case 0:
-                    return '[u] [nedjelju] [u] LT';
-                case 3:
-                    return '[u] [srijedu] [u] LT';
-                case 6:
-                    return '[u] [subotu] [u] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[u] dddd [u] LT';
-                }
-            },
-            lastDay  : '[jučer u] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                    return '[prošlu] dddd [u] LT';
-                case 6:
-                    return '[prošle] [subote] [u] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[prošli] dddd [u] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "za %s",
-            past   : "prije %s",
-            s      : "par sekundi",
-            m      : translate,
-            mm     : translate,
-            h      : translate,
-            hh     : translate,
-            d      : "dan",
-            dd     : translate,
-            M      : "mjesec",
-            MM     : translate,
-            y      : "godinu",
-            yy     : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/ca.js b/resources/lib/moment/lang/ca.js
deleted file mode 100644 (file)
index cf47113..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// moment.js language configuration
-// language : catalan (ca)
-// author : Juan G. Hurtado : https://github.com/juanghurtado
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ca', {
-        months : "gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),
-        monthsShort : "gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.".split("_"),
-        weekdays : "diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),
-        weekdaysShort : "dg._dl._dt._dc._dj._dv._ds.".split("_"),
-        weekdaysMin : "Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : function () {
-                return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            nextDay : function () {
-                return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            nextWeek : function () {
-                return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            lastDay : function () {
-                return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            lastWeek : function () {
-                return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "en %s",
-            past : "fa %s",
-            s : "uns segons",
-            m : "un minut",
-            mm : "%d minuts",
-            h : "una hora",
-            hh : "%d hores",
-            d : "un dia",
-            dd : "%d dies",
-            M : "un mes",
-            MM : "%d mesos",
-            y : "un any",
-            yy : "%d anys"
-        },
-        ordinal : '%dº',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/cs.js b/resources/lib/moment/lang/cs.js
deleted file mode 100644 (file)
index cb79c9b..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-// moment.js language configuration
-// language : czech (cs)
-// author : petrbela : https://github.com/petrbela
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var months = "leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),
-        monthsShort = "led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_");
-
-    function plural(n) {
-        return (n > 1) && (n < 5) && (~~(n / 10) !== 1);
-    }
-
-    function translate(number, withoutSuffix, key, isFuture) {
-        var result = number + " ";
-        switch (key) {
-        case 's':  // a few seconds / in a few seconds / a few seconds ago
-            return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami';
-        case 'm':  // a minute / in a minute / a minute ago
-            return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou');
-        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'minuty' : 'minut');
-            } else {
-                return result + 'minutami';
-            }
-            break;
-        case 'h':  // an hour / in an hour / an hour ago
-            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
-        case 'hh': // 9 hours / in 9 hours / 9 hours ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'hodiny' : 'hodin');
-            } else {
-                return result + 'hodinami';
-            }
-            break;
-        case 'd':  // a day / in a day / a day ago
-            return (withoutSuffix || isFuture) ? 'den' : 'dnem';
-        case 'dd': // 9 days / in 9 days / 9 days ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'dny' : 'dní');
-            } else {
-                return result + 'dny';
-            }
-            break;
-        case 'M':  // a month / in a month / a month ago
-            return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem';
-        case 'MM': // 9 months / in 9 months / 9 months ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'měsíce' : 'měsíců');
-            } else {
-                return result + 'měsíci';
-            }
-            break;
-        case 'y':  // a year / in a year / a year ago
-            return (withoutSuffix || isFuture) ? 'rok' : 'rokem';
-        case 'yy': // 9 years / in 9 years / 9 years ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'roky' : 'let');
-            } else {
-                return result + 'lety';
-            }
-            break;
-        }
-    }
-
-    return moment.lang('cs', {
-        months : months,
-        monthsShort : monthsShort,
-        monthsParse : (function (months, monthsShort) {
-            var i, _monthsParse = [];
-            for (i = 0; i < 12; i++) {
-                // use custom parser to solve problem with July (červenec)
-                _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
-            }
-            return _monthsParse;
-        }(months, monthsShort)),
-        weekdays : "neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),
-        weekdaysShort : "ne_po_út_st_čt_pá_so".split("_"),
-        weekdaysMin : "ne_po_út_st_čt_pá_so".split("_"),
-        longDateFormat : {
-            LT: "H.mm",
-            L : "DD. MM. YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[dnes v] LT",
-            nextDay: '[zítra v] LT',
-            nextWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[v neděli v] LT';
-                case 1:
-                case 2:
-                    return '[v] dddd [v] LT';
-                case 3:
-                    return '[ve středu v] LT';
-                case 4:
-                    return '[ve čtvrtek v] LT';
-                case 5:
-                    return '[v pátek v] LT';
-                case 6:
-                    return '[v sobotu v] LT';
-                }
-            },
-            lastDay: '[včera v] LT',
-            lastWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[minulou neděli v] LT';
-                case 1:
-                case 2:
-                    return '[minulé] dddd [v] LT';
-                case 3:
-                    return '[minulou středu v] LT';
-                case 4:
-                case 5:
-                    return '[minulý] dddd [v] LT';
-                case 6:
-                    return '[minulou sobotu v] LT';
-                }
-            },
-            sameElse: "L"
-        },
-        relativeTime : {
-            future : "za %s",
-            past : "před %s",
-            s : translate,
-            m : translate,
-            mm : translate,
-            h : translate,
-            hh : translate,
-            d : translate,
-            dd : translate,
-            M : translate,
-            MM : translate,
-            y : translate,
-            yy : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/cv.js b/resources/lib/moment/lang/cv.js
deleted file mode 100644 (file)
index a5812de..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-// moment.js language configuration
-// language : chuvash (cv)
-// author : Anatoly Mironov : https://github.com/mirontoli
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('cv', {
-        months : "кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"),
-        monthsShort : "кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"),
-        weekdays : "вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"),
-        weekdaysShort : "выр_тун_ытл_юн_кĕç_эрн_шăм".split("_"),
-        weekdaysMin : "вр_тн_ыт_юн_кç_эр_шм".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD-MM-YYYY",
-            LL : "YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ]",
-            LLL : "YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT",
-            LLLL : "dddd, YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT"
-        },
-        calendar : {
-            sameDay: '[Паян] LT [сехетре]',
-            nextDay: '[Ыран] LT [сехетре]',
-            lastDay: '[Ĕнер] LT [сехетре]',
-            nextWeek: '[Çитес] dddd LT [сехетре]',
-            lastWeek: '[Иртнĕ] dddd LT [сехетре]',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : function (output) {
-                var affix = /сехет$/i.exec(output) ? "рен" : /çул$/i.exec(output) ? "тан" : "ран";
-                return output + affix;
-            },
-            past : "%s каялла",
-            s : "пĕр-ик çеккунт",
-            m : "пĕр минут",
-            mm : "%d минут",
-            h : "пĕр сехет",
-            hh : "%d сехет",
-            d : "пĕр кун",
-            dd : "%d кун",
-            M : "пĕр уйăх",
-            MM : "%d уйăх",
-            y : "пĕр çул",
-            yy : "%d çул"
-        },
-        ordinal : '%d-мĕш',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/cy.js b/resources/lib/moment/lang/cy.js
deleted file mode 100644 (file)
index 5cd8476..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// moment.js language configuration
-// language : Welsh (cy)
-// author : Robert Allen
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang("cy", {
-        months: "Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr".split("_"),
-        monthsShort: "Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag".split("_"),
-        weekdays: "Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn".split("_"),
-        weekdaysShort: "Sul_Llun_Maw_Mer_Iau_Gwe_Sad".split("_"),
-        weekdaysMin: "Su_Ll_Ma_Me_Ia_Gw_Sa".split("_"),
-        // time formats are the same as en-gb
-        longDateFormat: {
-            LT: "HH:mm",
-            L: "DD/MM/YYYY",
-            LL: "D MMMM YYYY",
-            LLL: "D MMMM YYYY LT",
-            LLLL: "dddd, D MMMM YYYY LT"
-        },
-        calendar: {
-            sameDay: '[Heddiw am] LT',
-            nextDay: '[Yfory am] LT',
-            nextWeek: 'dddd [am] LT',
-            lastDay: '[Ddoe am] LT',
-            lastWeek: 'dddd [diwethaf am] LT',
-            sameElse: 'L'
-        },
-        relativeTime: {
-            future: "mewn %s",
-            past: "%s yn ôl",
-            s: "ychydig eiliadau",
-            m: "munud",
-            mm: "%d munud",
-            h: "awr",
-            hh: "%d awr",
-            d: "diwrnod",
-            dd: "%d diwrnod",
-            M: "mis",
-            MM: "%d mis",
-            y: "blwyddyn",
-            yy: "%d flynedd"
-        },
-        // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
-        ordinal: function (number) {
-            var b = number,
-                output = '',
-                lookup = [
-                    '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
-                    'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed
-                ];
-
-            if (b > 20) {
-                if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) {
-                    output = 'fed'; // not 30ain, 70ain or 90ain
-                } else {
-                    output = 'ain';
-                }
-            } else if (b > 0) {
-                output = lookup[b];
-            }
-
-            return number + output;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/da.js b/resources/lib/moment/lang/da.js
deleted file mode 100644 (file)
index e06f8c3..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// moment.js language configuration
-// language : danish (da)
-// author : Ulrik Nielsen : https://github.com/mrbase
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('da', {
-        months : "januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),
-        monthsShort : "jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),
-        weekdays : "søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),
-        weekdaysShort : "søn_man_tir_ons_tor_fre_lør".split("_"),
-        weekdaysMin : "sø_ma_ti_on_to_fr_lø".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd [d.] D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[I dag kl.] LT',
-            nextDay : '[I morgen kl.] LT',
-            nextWeek : 'dddd [kl.] LT',
-            lastDay : '[I går kl.] LT',
-            lastWeek : '[sidste] dddd [kl] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "om %s",
-            past : "%s siden",
-            s : "få sekunder",
-            m : "et minut",
-            mm : "%d minutter",
-            h : "en time",
-            hh : "%d timer",
-            d : "en dag",
-            dd : "%d dage",
-            M : "en måned",
-            MM : "%d måneder",
-            y : "et år",
-            yy : "%d år"
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/de-at.js b/resources/lib/moment/lang/de-at.js
deleted file mode 100644 (file)
index 565c12b..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// moment.js language configuration
-// language : austrian german (de-at)
-// author : lluchs : https://github.com/lluchs
-// author: Menelion Elensúle: https://github.com/Oire
-// author : Martin Groller : https://github.com/MadMG
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function processRelativeTime(number, withoutSuffix, key, isFuture) {
-        var format = {
-            'm': ['eine Minute', 'einer Minute'],
-            'h': ['eine Stunde', 'einer Stunde'],
-            'd': ['ein Tag', 'einem Tag'],
-            'dd': [number + ' Tage', number + ' Tagen'],
-            'M': ['ein Monat', 'einem Monat'],
-            'MM': [number + ' Monate', number + ' Monaten'],
-            'y': ['ein Jahr', 'einem Jahr'],
-            'yy': [number + ' Jahre', number + ' Jahren']
-        };
-        return withoutSuffix ? format[key][0] : format[key][1];
-    }
-
-    return moment.lang('de-at', {
-        months : "Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),
-        monthsShort : "Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),
-        weekdays : "Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),
-        weekdaysShort : "So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),
-        weekdaysMin : "So_Mo_Di_Mi_Do_Fr_Sa".split("_"),
-        longDateFormat : {
-            LT: "HH:mm [Uhr]",
-            L : "DD.MM.YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd, D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[Heute um] LT",
-            sameElse: "L",
-            nextDay: '[Morgen um] LT',
-            nextWeek: 'dddd [um] LT',
-            lastDay: '[Gestern um] LT',
-            lastWeek: '[letzten] dddd [um] LT'
-        },
-        relativeTime : {
-            future : "in %s",
-            past : "vor %s",
-            s : "ein paar Sekunden",
-            m : processRelativeTime,
-            mm : "%d Minuten",
-            h : processRelativeTime,
-            hh : "%d Stunden",
-            d : processRelativeTime,
-            dd : processRelativeTime,
-            M : processRelativeTime,
-            MM : processRelativeTime,
-            y : processRelativeTime,
-            yy : processRelativeTime
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/de.js b/resources/lib/moment/lang/de.js
deleted file mode 100644 (file)
index 86cd268..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// moment.js language configuration
-// language : german (de)
-// author : lluchs : https://github.com/lluchs
-// author: Menelion Elensúle: https://github.com/Oire
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function processRelativeTime(number, withoutSuffix, key, isFuture) {
-        var format = {
-            'm': ['eine Minute', 'einer Minute'],
-            'h': ['eine Stunde', 'einer Stunde'],
-            'd': ['ein Tag', 'einem Tag'],
-            'dd': [number + ' Tage', number + ' Tagen'],
-            'M': ['ein Monat', 'einem Monat'],
-            'MM': [number + ' Monate', number + ' Monaten'],
-            'y': ['ein Jahr', 'einem Jahr'],
-            'yy': [number + ' Jahre', number + ' Jahren']
-        };
-        return withoutSuffix ? format[key][0] : format[key][1];
-    }
-
-    return moment.lang('de', {
-        months : "Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),
-        monthsShort : "Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),
-        weekdays : "Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),
-        weekdaysShort : "So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),
-        weekdaysMin : "So_Mo_Di_Mi_Do_Fr_Sa".split("_"),
-        longDateFormat : {
-            LT: "HH:mm [Uhr]",
-            L : "DD.MM.YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd, D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[Heute um] LT",
-            sameElse: "L",
-            nextDay: '[Morgen um] LT',
-            nextWeek: 'dddd [um] LT',
-            lastDay: '[Gestern um] LT',
-            lastWeek: '[letzten] dddd [um] LT'
-        },
-        relativeTime : {
-            future : "in %s",
-            past : "vor %s",
-            s : "ein paar Sekunden",
-            m : processRelativeTime,
-            mm : "%d Minuten",
-            h : processRelativeTime,
-            hh : "%d Stunden",
-            d : processRelativeTime,
-            dd : processRelativeTime,
-            M : processRelativeTime,
-            MM : processRelativeTime,
-            y : processRelativeTime,
-            yy : processRelativeTime
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/el.js b/resources/lib/moment/lang/el.js
deleted file mode 100644 (file)
index e2a38cd..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-// moment.js language configuration
-// language : modern greek (el)
-// author : Aggelos Karalias : https://github.com/mehiel
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('el', {
-        monthsNominativeEl : "Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),
-        monthsGenitiveEl : "Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),
-        months : function (momentToFormat, format) {
-            if (/D/.test(format.substring(0, format.indexOf("MMMM")))) { // if there is a day number before 'MMMM'
-                return this._monthsGenitiveEl[momentToFormat.month()];
-            } else {
-                return this._monthsNominativeEl[momentToFormat.month()];
-            }
-        },
-        monthsShort : "Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),
-        weekdays : "Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),
-        weekdaysShort : "Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),
-        weekdaysMin : "Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),
-        meridiem : function (hours, minutes, isLower) {
-            if (hours > 11) {
-                return isLower ? 'μμ' : 'ΜΜ';
-            } else {
-                return isLower ? 'πμ' : 'ΠΜ';
-            }
-        },
-        longDateFormat : {
-            LT : "h:mm A",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendarEl : {
-            sameDay : '[Σήμερα {}] LT',
-            nextDay : '[Αύριο {}] LT',
-            nextWeek : 'dddd [{}] LT',
-            lastDay : '[Χθες {}] LT',
-            lastWeek : function() {
-                switch (this.day()) {
-                    case 6:
-                        return '[το προηγούμενο] dddd [{}] LT';
-                    default:
-                        return '[την προηγούμενη] dddd [{}] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        calendar : function (key, mom) {
-            var output = this._calendarEl[key],
-                hours = mom && mom.hours();
-
-            if (typeof output === 'function') {
-                output = output.apply(mom);
-            }
-
-            return output.replace("{}", (hours % 12 === 1 ? "στη" : "στις"));
-        },
-        relativeTime : {
-            future : "σε %s",
-            past : "%s πριν",
-            s : "δευτερόλεπτα",
-            m : "ένα λεπτό",
-            mm : "%d λεπτά",
-            h : "μία ώρα",
-            hh : "%d ώρες",
-            d : "μία μέρα",
-            dd : "%d μέρες",
-            M : "ένας μήνας",
-            MM : "%d μήνες",
-            y : "ένας χρόνος",
-            yy : "%d χρόνια"
-        },
-        ordinal : function (number) {
-            return number + 'η';
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/en-au.js b/resources/lib/moment/lang/en-au.js
deleted file mode 100644 (file)
index 4d91e25..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-// moment.js language configuration
-// language : australian english (en-au)
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('en-au', {
-        months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
-        monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
-        weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
-        weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
-        weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
-        longDateFormat : {
-            LT : "h:mm A",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Today at] LT',
-            nextDay : '[Tomorrow at] LT',
-            nextWeek : 'dddd [at] LT',
-            lastDay : '[Yesterday at] LT',
-            lastWeek : '[Last] dddd [at] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "in %s",
-            past : "%s ago",
-            s : "a few seconds",
-            m : "a minute",
-            mm : "%d minutes",
-            h : "an hour",
-            hh : "%d hours",
-            d : "a day",
-            dd : "%d days",
-            M : "a month",
-            MM : "%d months",
-            y : "a year",
-            yy : "%d years"
-        },
-        ordinal : function (number) {
-            var b = number % 10,
-                output = (~~ (number % 100 / 10) === 1) ? 'th' :
-                (b === 1) ? 'st' :
-                (b === 2) ? 'nd' :
-                (b === 3) ? 'rd' : 'th';
-            return number + output;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/en-ca.js b/resources/lib/moment/lang/en-ca.js
deleted file mode 100644 (file)
index a97e9f3..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-// moment.js language configuration
-// language : canadian english (en-ca)
-// author : Jonathan Abourbih : https://github.com/jonbca
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('en-ca', {
-        months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
-        monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
-        weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
-        weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
-        weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
-        longDateFormat : {
-            LT : "h:mm A",
-            L : "YYYY-MM-DD",
-            LL : "D MMMM, YYYY",
-            LLL : "D MMMM, YYYY LT",
-            LLLL : "dddd, D MMMM, YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Today at] LT',
-            nextDay : '[Tomorrow at] LT',
-            nextWeek : 'dddd [at] LT',
-            lastDay : '[Yesterday at] LT',
-            lastWeek : '[Last] dddd [at] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "in %s",
-            past : "%s ago",
-            s : "a few seconds",
-            m : "a minute",
-            mm : "%d minutes",
-            h : "an hour",
-            hh : "%d hours",
-            d : "a day",
-            dd : "%d days",
-            M : "a month",
-            MM : "%d months",
-            y : "a year",
-            yy : "%d years"
-        },
-        ordinal : function (number) {
-            var b = number % 10,
-                output = (~~ (number % 100 / 10) === 1) ? 'th' :
-                (b === 1) ? 'st' :
-                (b === 2) ? 'nd' :
-                (b === 3) ? 'rd' : 'th';
-            return number + output;
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/en-gb.js b/resources/lib/moment/lang/en-gb.js
deleted file mode 100644 (file)
index 3a7907b..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// moment.js language configuration
-// language : great britain english (en-gb)
-// author : Chris Gedrim : https://github.com/chrisgedrim
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('en-gb', {
-        months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
-        monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
-        weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
-        weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
-        weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Today at] LT',
-            nextDay : '[Tomorrow at] LT',
-            nextWeek : 'dddd [at] LT',
-            lastDay : '[Yesterday at] LT',
-            lastWeek : '[Last] dddd [at] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "in %s",
-            past : "%s ago",
-            s : "a few seconds",
-            m : "a minute",
-            mm : "%d minutes",
-            h : "an hour",
-            hh : "%d hours",
-            d : "a day",
-            dd : "%d days",
-            M : "a month",
-            MM : "%d months",
-            y : "a year",
-            yy : "%d years"
-        },
-        ordinal : function (number) {
-            var b = number % 10,
-                output = (~~ (number % 100 / 10) === 1) ? 'th' :
-                (b === 1) ? 'st' :
-                (b === 2) ? 'nd' :
-                (b === 3) ? 'rd' : 'th';
-            return number + output;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/eo.js b/resources/lib/moment/lang/eo.js
deleted file mode 100644 (file)
index 03b1abf..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// moment.js language configuration
-// language : esperanto (eo)
-// author : Colin Dean : https://github.com/colindean
-// komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko.
-//          Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni!
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('eo', {
-        months : "januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro".split("_"),
-        monthsShort : "jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec".split("_"),
-        weekdays : "Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato".split("_"),
-        weekdaysShort : "Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab".split("_"),
-        weekdaysMin : "Di_Lu_Ma_Me_Ĵa_Ve_Sa".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "YYYY-MM-DD",
-            LL : "D[-an de] MMMM, YYYY",
-            LLL : "D[-an de] MMMM, YYYY LT",
-            LLLL : "dddd, [la] D[-an de] MMMM, YYYY LT"
-        },
-        meridiem : function (hours, minutes, isLower) {
-            if (hours > 11) {
-                return isLower ? 'p.t.m.' : 'P.T.M.';
-            } else {
-                return isLower ? 'a.t.m.' : 'A.T.M.';
-            }
-        },
-        calendar : {
-            sameDay : '[Hodiaŭ je] LT',
-            nextDay : '[Morgaŭ je] LT',
-            nextWeek : 'dddd [je] LT',
-            lastDay : '[Hieraŭ je] LT',
-            lastWeek : '[pasinta] dddd [je] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "je %s",
-            past : "antaŭ %s",
-            s : "sekundoj",
-            m : "minuto",
-            mm : "%d minutoj",
-            h : "horo",
-            hh : "%d horoj",
-            d : "tago",//ne 'diurno', ĉar estas uzita por proksimumo
-            dd : "%d tagoj",
-            M : "monato",
-            MM : "%d monatoj",
-            y : "jaro",
-            yy : "%d jaroj"
-        },
-        ordinal : "%da",
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/es.js b/resources/lib/moment/lang/es.js
deleted file mode 100644 (file)
index 67432ca..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-// moment.js language configuration
-// language : spanish (es)
-// author : Julio Napurí : https://github.com/julionc
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var monthsShortDot = "ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),
-        monthsShort = "ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_");
-
-    return moment.lang('es', {
-        months : "enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),
-        monthsShort : function (m, format) {
-            if (/-MMM-/.test(format)) {
-                return monthsShort[m.month()];
-            } else {
-                return monthsShortDot[m.month()];
-            }
-        },
-        weekdays : "domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),
-        weekdaysShort : "dom._lun._mar._mié._jue._vie._sáb.".split("_"),
-        weekdaysMin : "Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD/MM/YYYY",
-            LL : "D [de] MMMM [del] YYYY",
-            LLL : "D [de] MMMM [del] YYYY LT",
-            LLLL : "dddd, D [de] MMMM [del] YYYY LT"
-        },
-        calendar : {
-            sameDay : function () {
-                return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
-            },
-            nextDay : function () {
-                return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
-            },
-            nextWeek : function () {
-                return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
-            },
-            lastDay : function () {
-                return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
-            },
-            lastWeek : function () {
-                return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "en %s",
-            past : "hace %s",
-            s : "unos segundos",
-            m : "un minuto",
-            mm : "%d minutos",
-            h : "una hora",
-            hh : "%d horas",
-            d : "un día",
-            dd : "%d días",
-            M : "un mes",
-            MM : "%d meses",
-            y : "un año",
-            yy : "%d años"
-        },
-        ordinal : '%dº',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/et.js b/resources/lib/moment/lang/et.js
deleted file mode 100644 (file)
index fb410ef..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// moment.js language configuration
-// language : estonian (et)
-// author : Henry Kehlmann : https://github.com/madhenry
-// improvements : Illimar Tambek : https://github.com/ragulka
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function processRelativeTime(number, withoutSuffix, key, isFuture) {
-        var format = {
-            's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'],
-            'm' : ['ühe minuti', 'üks minut'],
-            'mm': [number + ' minuti', number + ' minutit'],
-            'h' : ['ühe tunni', 'tund aega', 'üks tund'],
-            'hh': [number + ' tunni', number + ' tundi'],
-            'd' : ['ühe päeva', 'üks päev'],
-            'M' : ['kuu aja', 'kuu aega', 'üks kuu'],
-            'MM': [number + ' kuu', number + ' kuud'],
-            'y' : ['ühe aasta', 'aasta', 'üks aasta'],
-            'yy': [number + ' aasta', number + ' aastat']
-        };
-        if (withoutSuffix) {
-            return format[key][2] ? format[key][2] : format[key][1];
-        }
-        return isFuture ? format[key][0] : format[key][1];
-    }
-
-    return moment.lang('et', {
-        months        : "jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),
-        monthsShort   : "jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),
-        weekdays      : "pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev".split("_"),
-        weekdaysShort : "P_E_T_K_N_R_L".split("_"),
-        weekdaysMin   : "P_E_T_K_N_R_L".split("_"),
-        longDateFormat : {
-            LT   : "H:mm",
-            L    : "DD.MM.YYYY",
-            LL   : "D. MMMM YYYY",
-            LLL  : "D. MMMM YYYY LT",
-            LLLL : "dddd, D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay  : '[Täna,] LT',
-            nextDay  : '[Homme,] LT',
-            nextWeek : '[Järgmine] dddd LT',
-            lastDay  : '[Eile,] LT',
-            lastWeek : '[Eelmine] dddd LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s pärast",
-            past   : "%s tagasi",
-            s      : processRelativeTime,
-            m      : processRelativeTime,
-            mm     : processRelativeTime,
-            h      : processRelativeTime,
-            hh     : processRelativeTime,
-            d      : processRelativeTime,
-            dd     : '%d päeva',
-            M      : processRelativeTime,
-            MM     : processRelativeTime,
-            y      : processRelativeTime,
-            yy     : processRelativeTime
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/eu.js b/resources/lib/moment/lang/eu.js
deleted file mode 100644 (file)
index 659b739..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// moment.js language configuration
-// language : euskara (eu)
-// author : Eneko Illarramendi : https://github.com/eillarra
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('eu', {
-        months : "urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),
-        monthsShort : "urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),
-        weekdays : "igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),
-        weekdaysShort : "ig._al._ar._az._og._ol._lr.".split("_"),
-        weekdaysMin : "ig_al_ar_az_og_ol_lr".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "YYYY-MM-DD",
-            LL : "YYYY[ko] MMMM[ren] D[a]",
-            LLL : "YYYY[ko] MMMM[ren] D[a] LT",
-            LLLL : "dddd, YYYY[ko] MMMM[ren] D[a] LT",
-            l : "YYYY-M-D",
-            ll : "YYYY[ko] MMM D[a]",
-            lll : "YYYY[ko] MMM D[a] LT",
-            llll : "ddd, YYYY[ko] MMM D[a] LT"
-        },
-        calendar : {
-            sameDay : '[gaur] LT[etan]',
-            nextDay : '[bihar] LT[etan]',
-            nextWeek : 'dddd LT[etan]',
-            lastDay : '[atzo] LT[etan]',
-            lastWeek : '[aurreko] dddd LT[etan]',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s barru",
-            past : "duela %s",
-            s : "segundo batzuk",
-            m : "minutu bat",
-            mm : "%d minutu",
-            h : "ordu bat",
-            hh : "%d ordu",
-            d : "egun bat",
-            dd : "%d egun",
-            M : "hilabete bat",
-            MM : "%d hilabete",
-            y : "urte bat",
-            yy : "%d urte"
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/fa.js b/resources/lib/moment/lang/fa.js
deleted file mode 100644 (file)
index 4a690c4..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-// moment.js language configuration
-// language : Persian Language
-// author : Ebrahim Byagowi : https://github.com/ebraminio
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var symbolMap = {
-        '1': '۱',
-        '2': '۲',
-        '3': '۳',
-        '4': '۴',
-        '5': '۵',
-        '6': '۶',
-        '7': '۷',
-        '8': '۸',
-        '9': '۹',
-        '0': '۰'
-    }, numberMap = {
-        '۱': '1',
-        '۲': '2',
-        '۳': '3',
-        '۴': '4',
-        '۵': '5',
-        '۶': '6',
-        '۷': '7',
-        '۸': '8',
-        '۹': '9',
-        '۰': '0'
-    };
-
-    return moment.lang('fa', {
-        months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
-        monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
-        weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
-        weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
-        weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'),
-        longDateFormat : {
-            LT : 'HH:mm',
-            L : 'DD/MM/YYYY',
-            LL : 'D MMMM YYYY',
-            LLL : 'D MMMM YYYY LT',
-            LLLL : 'dddd, D MMMM YYYY LT'
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 12) {
-                return "قبل از ظهر";
-            } else {
-                return "بعد از ظهر";
-            }
-        },
-        calendar : {
-            sameDay : '[امروز ساعت] LT',
-            nextDay : '[فردا ساعت] LT',
-            nextWeek : 'dddd [ساعت] LT',
-            lastDay : '[دیروز ساعت] LT',
-            lastWeek : 'dddd [پیش] [ساعت] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : 'در %s',
-            past : '%s پیش',
-            s : 'چندین ثانیه',
-            m : 'یک دقیقه',
-            mm : '%d دقیقه',
-            h : 'یک ساعت',
-            hh : '%d ساعت',
-            d : 'یک روز',
-            dd : '%d روز',
-            M : 'یک ماه',
-            MM : '%d ماه',
-            y : 'یک سال',
-            yy : '%d سال'
-        },
-        preparse: function (string) {
-            return string.replace(/[۰-۹]/g, function (match) {
-                return numberMap[match];
-            }).replace(/،/g, ',');
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            }).replace(/,/g, '،');
-        },
-        ordinal : '%dم',
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12 // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/fi.js b/resources/lib/moment/lang/fi.js
deleted file mode 100644 (file)
index 49f477c..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-// moment.js language configuration
-// language : finnish (fi)
-// author : Tarmo Aidantausta : https://github.com/bleadof
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '),
-        numbersFuture = ['nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden',
-                          numbersPast[7], numbersPast[8], numbersPast[9]];
-
-    function translate(number, withoutSuffix, key, isFuture) {
-        var result = "";
-        switch (key) {
-        case 's':
-            return isFuture ? 'muutaman sekunnin' : 'muutama sekunti';
-        case 'm':
-            return isFuture ? 'minuutin' : 'minuutti';
-        case 'mm':
-            result = isFuture ? 'minuutin' : 'minuuttia';
-            break;
-        case 'h':
-            return isFuture ? 'tunnin' : 'tunti';
-        case 'hh':
-            result = isFuture ? 'tunnin' : 'tuntia';
-            break;
-        case 'd':
-            return isFuture ? 'päivän' : 'päivä';
-        case 'dd':
-            result = isFuture ? 'päivän' : 'päivää';
-            break;
-        case 'M':
-            return isFuture ? 'kuukauden' : 'kuukausi';
-        case 'MM':
-            result = isFuture ? 'kuukauden' : 'kuukautta';
-            break;
-        case 'y':
-            return isFuture ? 'vuoden' : 'vuosi';
-        case 'yy':
-            result = isFuture ? 'vuoden' : 'vuotta';
-            break;
-        }
-        result = verbalNumber(number, isFuture) + " " + result;
-        return result;
-    }
-
-    function verbalNumber(number, isFuture) {
-        return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number;
-    }
-
-    return moment.lang('fi', {
-        months : "tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),
-        monthsShort : "tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),
-        weekdays : "sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),
-        weekdaysShort : "su_ma_ti_ke_to_pe_la".split("_"),
-        weekdaysMin : "su_ma_ti_ke_to_pe_la".split("_"),
-        longDateFormat : {
-            LT : "HH.mm",
-            L : "DD.MM.YYYY",
-            LL : "Do MMMM[ta] YYYY",
-            LLL : "Do MMMM[ta] YYYY, [klo] LT",
-            LLLL : "dddd, Do MMMM[ta] YYYY, [klo] LT",
-            l : "D.M.YYYY",
-            ll : "Do MMM YYYY",
-            lll : "Do MMM YYYY, [klo] LT",
-            llll : "ddd, Do MMM YYYY, [klo] LT"
-        },
-        calendar : {
-            sameDay : '[tänään] [klo] LT',
-            nextDay : '[huomenna] [klo] LT',
-            nextWeek : 'dddd [klo] LT',
-            lastDay : '[eilen] [klo] LT',
-            lastWeek : '[viime] dddd[na] [klo] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s päästä",
-            past : "%s sitten",
-            s : translate,
-            m : translate,
-            mm : translate,
-            h : translate,
-            hh : translate,
-            d : translate,
-            dd : translate,
-            M : translate,
-            MM : translate,
-            y : translate,
-            yy : translate
-        },
-        ordinal : "%d.",
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/fo.js b/resources/lib/moment/lang/fo.js
deleted file mode 100644 (file)
index 2f1cbb8..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// moment.js language configuration
-// language : faroese (fo)
-// author : Ragnar Johannesen : https://github.com/ragnar123
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('fo', {
-        months : "januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember".split("_"),
-        monthsShort : "jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),
-        weekdays : "sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur".split("_"),
-        weekdaysShort : "sun_mán_týs_mik_hós_frí_ley".split("_"),
-        weekdaysMin : "su_má_tý_mi_hó_fr_le".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D. MMMM, YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Í dag kl.] LT',
-            nextDay : '[Í morgin kl.] LT',
-            nextWeek : 'dddd [kl.] LT',
-            lastDay : '[Í gjár kl.] LT',
-            lastWeek : '[síðstu] dddd [kl] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "um %s",
-            past : "%s síðani",
-            s : "fá sekund",
-            m : "ein minutt",
-            mm : "%d minuttir",
-            h : "ein tími",
-            hh : "%d tímar",
-            d : "ein dagur",
-            dd : "%d dagar",
-            M : "ein mánaði",
-            MM : "%d mánaðir",
-            y : "eitt ár",
-            yy : "%d ár"
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/fr-ca.js b/resources/lib/moment/lang/fr-ca.js
deleted file mode 100644 (file)
index 3280d79..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-// moment.js language configuration
-// language : canadian french (fr-ca)
-// author : Jonathan Abourbih : https://github.com/jonbca
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('fr-ca', {
-        months : "janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),
-        monthsShort : "janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),
-        weekdays : "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),
-        weekdaysShort : "dim._lun._mar._mer._jeu._ven._sam.".split("_"),
-        weekdaysMin : "Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "YYYY-MM-DD",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[Aujourd'hui à] LT",
-            nextDay: '[Demain à] LT',
-            nextWeek: 'dddd [à] LT',
-            lastDay: '[Hier à] LT',
-            lastWeek: 'dddd [dernier à] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "dans %s",
-            past : "il y a %s",
-            s : "quelques secondes",
-            m : "une minute",
-            mm : "%d minutes",
-            h : "une heure",
-            hh : "%d heures",
-            d : "un jour",
-            dd : "%d jours",
-            M : "un mois",
-            MM : "%d mois",
-            y : "un an",
-            yy : "%d ans"
-        },
-        ordinal : function (number) {
-            return number + (number === 1 ? 'er' : '');
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/fr.js b/resources/lib/moment/lang/fr.js
deleted file mode 100644 (file)
index 6b3dc52..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// moment.js language configuration
-// language : french (fr)
-// author : John Fischer : https://github.com/jfroffice
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('fr', {
-        months : "janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),
-        monthsShort : "janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),
-        weekdays : "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),
-        weekdaysShort : "dim._lun._mar._mer._jeu._ven._sam.".split("_"),
-        weekdaysMin : "Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[Aujourd'hui à] LT",
-            nextDay: '[Demain à] LT',
-            nextWeek: 'dddd [à] LT',
-            lastDay: '[Hier à] LT',
-            lastWeek: 'dddd [dernier à] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "dans %s",
-            past : "il y a %s",
-            s : "quelques secondes",
-            m : "une minute",
-            mm : "%d minutes",
-            h : "une heure",
-            hh : "%d heures",
-            d : "un jour",
-            dd : "%d jours",
-            M : "un mois",
-            MM : "%d mois",
-            y : "un an",
-            yy : "%d ans"
-        },
-        ordinal : function (number) {
-            return number + (number === 1 ? 'er' : '');
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/gl.js b/resources/lib/moment/lang/gl.js
deleted file mode 100644 (file)
index 8b14127..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// moment.js language configuration
-// language : galician (gl)
-// author : Juan G. Hurtado : https://github.com/juanghurtado
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('gl', {
-        months : "Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro".split("_"),
-        monthsShort : "Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"),
-        weekdays : "Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"),
-        weekdaysShort : "Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"),
-        weekdaysMin : "Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : function () {
-                return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
-            },
-            nextDay : function () {
-                return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
-            },
-            nextWeek : function () {
-                return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
-            },
-            lastDay : function () {
-                return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT';
-            },
-            lastWeek : function () {
-                return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : function (str) {
-                if (str === "uns segundos") {
-                    return "nuns segundos";
-                }
-                return "en " + str;
-            },
-            past : "hai %s",
-            s : "uns segundos",
-            m : "un minuto",
-            mm : "%d minutos",
-            h : "unha hora",
-            hh : "%d horas",
-            d : "un día",
-            dd : "%d días",
-            M : "un mes",
-            MM : "%d meses",
-            y : "un ano",
-            yy : "%d anos"
-        },
-        ordinal : '%dº',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/he.js b/resources/lib/moment/lang/he.js
deleted file mode 100644 (file)
index b85dbe8..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// moment.js language configuration
-// language : Hebrew (he)
-// author : Tomer Cohen : https://github.com/tomer
-// author : Moshe Simantov : https://github.com/DevelopmentIL
-// author : Tal Ater : https://github.com/TalAter
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('he', {
-        months : "ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"),
-        monthsShort : "ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"),
-        weekdays : "ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"),
-        weekdaysShort : "א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),
-        weekdaysMin : "א_ב_ג_ד_ה_ו_ש".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D [ב]MMMM YYYY",
-            LLL : "D [ב]MMMM YYYY LT",
-            LLLL : "dddd, D [ב]MMMM YYYY LT",
-            l : "D/M/YYYY",
-            ll : "D MMM YYYY",
-            lll : "D MMM YYYY LT",
-            llll : "ddd, D MMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[היום ב־]LT',
-            nextDay : '[מחר ב־]LT',
-            nextWeek : 'dddd [בשעה] LT',
-            lastDay : '[אתמול ב־]LT',
-            lastWeek : '[ביום] dddd [האחרון בשעה] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "בעוד %s",
-            past : "לפני %s",
-            s : "מספר שניות",
-            m : "דקה",
-            mm : "%d דקות",
-            h : "שעה",
-            hh : function (number) {
-                if (number === 2) {
-                    return "שעתיים";
-                }
-                return number + " שעות";
-            },
-            d : "יום",
-            dd : function (number) {
-                if (number === 2) {
-                    return "יומיים";
-                }
-                return number + " ימים";
-            },
-            M : "חודש",
-            MM : function (number) {
-                if (number === 2) {
-                    return "חודשיים";
-                }
-                return number + " חודשים";
-            },
-            y : "שנה",
-            yy : function (number) {
-                if (number === 2) {
-                    return "שנתיים";
-                }
-                return number + " שנים";
-            }
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/hi.js b/resources/lib/moment/lang/hi.js
deleted file mode 100644 (file)
index 8e6e99c..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-// moment.js language configuration
-// language : hindi (hi)
-// author : Mayank Singhal : https://github.com/mayanksinghal
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var symbolMap = {
-        '1': '१',
-        '2': '२',
-        '3': '३',
-        '4': '४',
-        '5': '५',
-        '6': '६',
-        '7': '७',
-        '8': '८',
-        '9': '९',
-        '0': '०'
-    },
-    numberMap = {
-        '१': '1',
-        '२': '2',
-        '३': '3',
-        '४': '4',
-        '५': '5',
-        '६': '6',
-        '७': '7',
-        '८': '8',
-        '९': '9',
-        '०': '0'
-    };
-
-    return moment.lang('hi', {
-        months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split("_"),
-        monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split("_"),
-        weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split("_"),
-        weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split("_"),
-        weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split("_"),
-        longDateFormat : {
-            LT : "A h:mm बजे",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY, LT",
-            LLLL : "dddd, D MMMM YYYY, LT"
-        },
-        calendar : {
-            sameDay : '[आज] LT',
-            nextDay : '[कल] LT',
-            nextWeek : 'dddd, LT',
-            lastDay : '[कल] LT',
-            lastWeek : '[पिछले] dddd, LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s में",
-            past : "%s पहले",
-            s : "कुछ ही क्षण",
-            m : "एक मिनट",
-            mm : "%d मिनट",
-            h : "एक घंटा",
-            hh : "%d घंटे",
-            d : "एक दिन",
-            dd : "%d दिन",
-            M : "एक महीने",
-            MM : "%d महीने",
-            y : "एक वर्ष",
-            yy : "%d वर्ष"
-        },
-        preparse: function (string) {
-            return string.replace(/[१२३४५६७८९०]/g, function (match) {
-                return numberMap[match];
-            });
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            });
-        },
-        // Hindi notation for meridiems are quite fuzzy in practice. While there exists
-        // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi.
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return "रात";
-            } else if (hour < 10) {
-                return "सुबह";
-            } else if (hour < 17) {
-                return "दोपहर";
-            } else if (hour < 20) {
-                return "शाम";
-            } else {
-                return "रात";
-            }
-        },
-        week : {
-            dow : 0, // Sunday is the first day of the week.
-            doy : 6  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/hr.js b/resources/lib/moment/lang/hr.js
deleted file mode 100644 (file)
index 2e3bf11..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-// moment.js language configuration
-// language : hrvatski (hr)
-// author : Bojan Marković : https://github.com/bmarkovic
-
-// based on (sl) translation by Robert Sedovšek
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    function translate(number, withoutSuffix, key) {
-        var result = number + " ";
-        switch (key) {
-        case 'm':
-            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
-        case 'mm':
-            if (number === 1) {
-                result += 'minuta';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'minute';
-            } else {
-                result += 'minuta';
-            }
-            return result;
-        case 'h':
-            return withoutSuffix ? 'jedan sat' : 'jednog sata';
-        case 'hh':
-            if (number === 1) {
-                result += 'sat';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'sata';
-            } else {
-                result += 'sati';
-            }
-            return result;
-        case 'dd':
-            if (number === 1) {
-                result += 'dan';
-            } else {
-                result += 'dana';
-            }
-            return result;
-        case 'MM':
-            if (number === 1) {
-                result += 'mjesec';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'mjeseca';
-            } else {
-                result += 'mjeseci';
-            }
-            return result;
-        case 'yy':
-            if (number === 1) {
-                result += 'godina';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'godine';
-            } else {
-                result += 'godina';
-            }
-            return result;
-        }
-    }
-
-    return moment.lang('hr', {
-        months : "sječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_"),
-        monthsShort : "sje._vel._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),
-        weekdays : "nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),
-        weekdaysShort : "ned._pon._uto._sri._čet._pet._sub.".split("_"),
-        weekdaysMin : "ne_po_ut_sr_če_pe_su".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD. MM. YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd, D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay  : '[danas u] LT',
-            nextDay  : '[sutra u] LT',
-
-            nextWeek : function () {
-                switch (this.day()) {
-                case 0:
-                    return '[u] [nedjelju] [u] LT';
-                case 3:
-                    return '[u] [srijedu] [u] LT';
-                case 6:
-                    return '[u] [subotu] [u] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[u] dddd [u] LT';
-                }
-            },
-            lastDay  : '[jučer u] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                    return '[prošlu] dddd [u] LT';
-                case 6:
-                    return '[prošle] [subote] [u] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[prošli] dddd [u] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "za %s",
-            past   : "prije %s",
-            s      : "par sekundi",
-            m      : translate,
-            mm     : translate,
-            h      : translate,
-            hh     : translate,
-            d      : "dan",
-            dd     : translate,
-            M      : "mjesec",
-            MM     : translate,
-            y      : "godinu",
-            yy     : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/hu.js b/resources/lib/moment/lang/hu.js
deleted file mode 100644 (file)
index 9833024..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-// moment.js language configuration
-// language : hungarian (hu)
-// author : Adam Brunner : https://github.com/adambrunner
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' ');
-
-    function translate(number, withoutSuffix, key, isFuture) {
-        var num = number,
-            suffix;
-
-        switch (key) {
-        case 's':
-            return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce';
-        case 'm':
-            return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce');
-        case 'mm':
-            return num + (isFuture || withoutSuffix ? ' perc' : ' perce');
-        case 'h':
-            return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája');
-        case 'hh':
-            return num + (isFuture || withoutSuffix ? ' óra' : ' órája');
-        case 'd':
-            return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja');
-        case 'dd':
-            return num + (isFuture || withoutSuffix ? ' nap' : ' napja');
-        case 'M':
-            return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
-        case 'MM':
-            return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
-        case 'y':
-            return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve');
-        case 'yy':
-            return num + (isFuture || withoutSuffix ? ' év' : ' éve');
-        }
-
-        return '';
-    }
-
-    function week(isFuture) {
-        return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]';
-    }
-
-    return moment.lang('hu', {
-        months : "január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),
-        monthsShort : "jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),
-        weekdays : "vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),
-        weekdaysShort : "vas_hét_kedd_sze_csüt_pén_szo".split("_"),
-        weekdaysMin : "v_h_k_sze_cs_p_szo".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "YYYY.MM.DD.",
-            LL : "YYYY. MMMM D.",
-            LLL : "YYYY. MMMM D., LT",
-            LLLL : "YYYY. MMMM D., dddd LT"
-        },
-        meridiem : function (hours, minutes, isLower) {
-            if (hours < 12) {
-                return isLower === true ? 'de' : 'DE';
-            } else {
-                return isLower === true ? 'du' : 'DU';
-            }
-        },
-        calendar : {
-            sameDay : '[ma] LT[-kor]',
-            nextDay : '[holnap] LT[-kor]',
-            nextWeek : function () {
-                return week.call(this, true);
-            },
-            lastDay : '[tegnap] LT[-kor]',
-            lastWeek : function () {
-                return week.call(this, false);
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s múlva",
-            past : "%s",
-            s : translate,
-            m : translate,
-            mm : translate,
-            h : translate,
-            hh : translate,
-            d : translate,
-            dd : translate,
-            M : translate,
-            MM : translate,
-            y : translate,
-            yy : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/hy-am.js b/resources/lib/moment/lang/hy-am.js
deleted file mode 100644 (file)
index 951655b..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-// moment.js language configuration
-// language : Armenian (hy-am)
-// author : Armendarabyan : https://github.com/armendarabyan
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    function monthsCaseReplace(m, format) {
-        var months = {
-            'nominative': 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_'),
-            'accusative': 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_')
-        },
-
-        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return months[nounCase][m.month()];
-    }
-
-    function monthsShortCaseReplace(m, format) {
-        var monthsShort = 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_');
-
-        return monthsShort[m.month()];
-    }
-
-    function weekdaysCaseReplace(m, format) {
-        var weekdays = 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_');
-
-        return weekdays[m.day()];
-    }
-
-    return moment.lang('hy-am', {
-        months : monthsCaseReplace,
-        monthsShort : monthsShortCaseReplace,
-        weekdays : weekdaysCaseReplace,
-        weekdaysShort : "կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),
-        weekdaysMin : "կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY թ.",
-            LLL : "D MMMM YYYY թ., LT",
-            LLLL : "dddd, D MMMM YYYY թ., LT"
-        },
-        calendar : {
-            sameDay: '[այսօր] LT',
-            nextDay: '[վաղը] LT',
-            lastDay: '[երեկ] LT',
-            nextWeek: function () {
-                return 'dddd [օրը ժամը] LT';
-            },
-            lastWeek: function () {
-                return '[անցած] dddd [օրը ժամը] LT';
-            },
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "%s հետո",
-            past : "%s առաջ",
-            s : "մի քանի վայրկյան",
-            m : "րոպե",
-            mm : "%d րոպե",
-            h : "ժամ",
-            hh : "%d ժամ",
-            d : "օր",
-            dd : "%d օր",
-            M : "ամիս",
-            MM : "%d ամիս",
-            y : "տարի",
-            yy : "%d տարի"
-        },
-
-        meridiem : function (hour) {
-            if (hour < 4) {
-                return "գիշերվա";
-            } else if (hour < 12) {
-                return "առավոտվա";
-            } else if (hour < 17) {
-                return "ցերեկվա";
-            } else {
-                return "երեկոյան";
-            }
-        },
-
-        ordinal: function (number, period) {
-            switch (period) {
-            case 'DDD':
-            case 'w':
-            case 'W':
-            case 'DDDo':
-                if (number === 1) {
-                    return number + '-ին';
-                }
-                return number + '-րդ';
-            default:
-                return number;
-            }
-        },
-
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/id.js b/resources/lib/moment/lang/id.js
deleted file mode 100644 (file)
index f186280..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-// moment.js language configuration
-// language : Bahasa Indonesia (id)
-// author : Mohammad Satrio Utomo : https://github.com/tyok
-// reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('id', {
-        months : "Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),
-        monthsShort : "Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),
-        weekdays : "Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),
-        weekdaysShort : "Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),
-        weekdaysMin : "Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),
-        longDateFormat : {
-            LT : "HH.mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY [pukul] LT",
-            LLLL : "dddd, D MMMM YYYY [pukul] LT"
-        },
-        meridiem : function (hours, minutes, isLower) {
-            if (hours < 11) {
-                return 'pagi';
-            } else if (hours < 15) {
-                return 'siang';
-            } else if (hours < 19) {
-                return 'sore';
-            } else {
-                return 'malam';
-            }
-        },
-        calendar : {
-            sameDay : '[Hari ini pukul] LT',
-            nextDay : '[Besok pukul] LT',
-            nextWeek : 'dddd [pukul] LT',
-            lastDay : '[Kemarin pukul] LT',
-            lastWeek : 'dddd [lalu pukul] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "dalam %s",
-            past : "%s yang lalu",
-            s : "beberapa detik",
-            m : "semenit",
-            mm : "%d menit",
-            h : "sejam",
-            hh : "%d jam",
-            d : "sehari",
-            dd : "%d hari",
-            M : "sebulan",
-            MM : "%d bulan",
-            y : "setahun",
-            yy : "%d tahun"
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/is.js b/resources/lib/moment/lang/is.js
deleted file mode 100644 (file)
index 5b6b2a8..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-// moment.js language configuration
-// language : icelandic (is)
-// author : Hinrik Örn Sigurðsson : https://github.com/hinrik
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function plural(n) {
-        if (n % 100 === 11) {
-            return true;
-        } else if (n % 10 === 1) {
-            return false;
-        }
-        return true;
-    }
-
-    function translate(number, withoutSuffix, key, isFuture) {
-        var result = number + " ";
-        switch (key) {
-        case 's':
-            return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum';
-        case 'm':
-            return withoutSuffix ? 'mínúta' : 'mínútu';
-        case 'mm':
-            if (plural(number)) {
-                return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum');
-            } else if (withoutSuffix) {
-                return result + 'mínúta';
-            }
-            return result + 'mínútu';
-        case 'hh':
-            if (plural(number)) {
-                return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum');
-            }
-            return result + 'klukkustund';
-        case 'd':
-            if (withoutSuffix) {
-                return 'dagur';
-            }
-            return isFuture ? 'dag' : 'degi';
-        case 'dd':
-            if (plural(number)) {
-                if (withoutSuffix) {
-                    return result + 'dagar';
-                }
-                return result + (isFuture ? 'daga' : 'dögum');
-            } else if (withoutSuffix) {
-                return result + 'dagur';
-            }
-            return result + (isFuture ? 'dag' : 'degi');
-        case 'M':
-            if (withoutSuffix) {
-                return 'mánuður';
-            }
-            return isFuture ? 'mánuð' : 'mánuði';
-        case 'MM':
-            if (plural(number)) {
-                if (withoutSuffix) {
-                    return result + 'mánuðir';
-                }
-                return result + (isFuture ? 'mánuði' : 'mánuðum');
-            } else if (withoutSuffix) {
-                return result + 'mánuður';
-            }
-            return result + (isFuture ? 'mánuð' : 'mánuði');
-        case 'y':
-            return withoutSuffix || isFuture ? 'ár' : 'ári';
-        case 'yy':
-            if (plural(number)) {
-                return result + (withoutSuffix || isFuture ? 'ár' : 'árum');
-            }
-            return result + (withoutSuffix || isFuture ? 'ár' : 'ári');
-        }
-    }
-
-    return moment.lang('is', {
-        months : "janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),
-        monthsShort : "jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),
-        weekdays : "sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),
-        weekdaysShort : "sun_mán_þri_mið_fim_fös_lau".split("_"),
-        weekdaysMin : "Su_Má_Þr_Mi_Fi_Fö_La".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD/MM/YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY [kl.] LT",
-            LLLL : "dddd, D. MMMM YYYY [kl.] LT"
-        },
-        calendar : {
-            sameDay : '[í dag kl.] LT',
-            nextDay : '[á morgun kl.] LT',
-            nextWeek : 'dddd [kl.] LT',
-            lastDay : '[í gær kl.] LT',
-            lastWeek : '[síðasta] dddd [kl.] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "eftir %s",
-            past : "fyrir %s síðan",
-            s : translate,
-            m : translate,
-            mm : translate,
-            h : "klukkustund",
-            hh : translate,
-            d : translate,
-            dd : translate,
-            M : translate,
-            MM : translate,
-            y : translate,
-            yy : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/it.js b/resources/lib/moment/lang/it.js
deleted file mode 100644 (file)
index 9c27f66..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-// moment.js language configuration
-// language : italian (it)
-// author : Lorenzo : https://github.com/aliem
-// author: Mattia Larentis: https://github.com/nostalgiaz
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('it', {
-        months : "gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),
-        monthsShort : "gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),
-        weekdays : "Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),
-        weekdaysShort : "Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),
-        weekdaysMin : "D_L_Ma_Me_G_V_S".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: '[Oggi alle] LT',
-            nextDay: '[Domani alle] LT',
-            nextWeek: 'dddd [alle] LT',
-            lastDay: '[Ieri alle] LT',
-            lastWeek: '[lo scorso] dddd [alle] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : function (s) {
-                return ((/^[0-9].+$/).test(s) ? "tra" : "in") + " " + s;
-            },
-            past : "%s fa",
-            s : "alcuni secondi",
-            m : "un minuto",
-            mm : "%d minuti",
-            h : "un'ora",
-            hh : "%d ore",
-            d : "un giorno",
-            dd : "%d giorni",
-            M : "un mese",
-            MM : "%d mesi",
-            y : "un anno",
-            yy : "%d anni"
-        },
-        ordinal: '%dº',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/ja.js b/resources/lib/moment/lang/ja.js
deleted file mode 100644 (file)
index 9cd7e9e..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// moment.js language configuration
-// language : japanese (ja)
-// author : LI Long : https://github.com/baryon
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ja', {
-        months : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
-        monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
-        weekdays : "日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),
-        weekdaysShort : "日_月_火_水_木_金_土".split("_"),
-        weekdaysMin : "日_月_火_水_木_金_土".split("_"),
-        longDateFormat : {
-            LT : "Ah時m分",
-            L : "YYYY/MM/DD",
-            LL : "YYYY年M月D日",
-            LLL : "YYYY年M月D日LT",
-            LLLL : "YYYY年M月D日LT dddd"
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 12) {
-                return "午前";
-            } else {
-                return "午後";
-            }
-        },
-        calendar : {
-            sameDay : '[今日] LT',
-            nextDay : '[明日] LT',
-            nextWeek : '[来週]dddd LT',
-            lastDay : '[昨日] LT',
-            lastWeek : '[前週]dddd LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s後",
-            past : "%s前",
-            s : "数秒",
-            m : "1分",
-            mm : "%d分",
-            h : "1時間",
-            hh : "%d時間",
-            d : "1日",
-            dd : "%d日",
-            M : "1ヶ月",
-            MM : "%dヶ月",
-            y : "1年",
-            yy : "%d年"
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/ka.js b/resources/lib/moment/lang/ka.js
deleted file mode 100644 (file)
index 0cebdaa..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-// moment.js language configuration
-// language : Georgian (ka)
-// author : Irakli Janiashvili : https://github.com/irakli-janiashvili
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    function monthsCaseReplace(m, format) {
-        var months = {
-            'nominative': 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'),
-            'accusative': 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_')
-        },
-
-        nounCase = (/D[oD] *MMMM?/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return months[nounCase][m.month()];
-    }
-
-    function weekdaysCaseReplace(m, format) {
-        var weekdays = {
-            'nominative': 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'),
-            'accusative': 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_')
-        },
-
-        nounCase = (/(წინა|შემდეგ)/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return weekdays[nounCase][m.day()];
-    }
-
-    return moment.lang('ka', {
-        months : monthsCaseReplace,
-        monthsShort : "იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ".split("_"),
-        weekdays : weekdaysCaseReplace,
-        weekdaysShort : "კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ".split("_"),
-        weekdaysMin : "კვ_ორ_სა_ოთ_ხუ_პა_შა".split("_"),
-        longDateFormat : {
-            LT : "h:mm A",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[დღეს] LT[-ზე]',
-            nextDay : '[ხვალ] LT[-ზე]',
-            lastDay : '[გუშინ] LT[-ზე]',
-            nextWeek : '[შემდეგ] dddd LT[-ზე]',
-            lastWeek : '[წინა] dddd LT-ზე',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : function (s) {
-                return (/(წამი|წუთი|საათი|წელი)/).test(s) ?
-                    s.replace(/ი$/, "ში") :
-                    s + "ში";
-            },
-            past : function (s) {
-                if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) {
-                    return s.replace(/(ი|ე)$/, "ის წინ");
-                }
-                if ((/წელი/).test(s)) {
-                    return s.replace(/წელი$/, "წლის წინ");
-                }
-            },
-            s : "რამდენიმე წამი",
-            m : "წუთი",
-            mm : "%d წუთი",
-            h : "საათი",
-            hh : "%d საათი",
-            d : "დღე",
-            dd : "%d დღე",
-            M : "თვე",
-            MM : "%d თვე",
-            y : "წელი",
-            yy : "%d წელი"
-        },
-        ordinal : function (number) {
-            if (number === 0) {
-                return number;
-            }
-
-            if (number === 1) {
-                return number + "-ლი";
-            }
-
-            if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) {
-                return "მე-" + number;
-            }
-
-            return number + "-ე";
-        },
-        week : {
-            dow : 1,
-            doy : 7
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/km.js b/resources/lib/moment/lang/km.js
deleted file mode 100644 (file)
index 0759c8f..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// moment.js language configuration
-// language : khmer (km)
-// author : Kruy Vanna : https://github.com/kruyvanna
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('km', {
-        months: "មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ".split("_"),
-        monthsShort: "មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ".split("_"),
-        weekdays: "អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍".split("_"),
-        weekdaysShort: "អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍".split("_"),
-        weekdaysMin: "អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍".split("_"),
-        longDateFormat: {
-            LT: "HH:mm",
-            L: "DD/MM/YYYY",
-            LL: "D MMMM YYYY",
-            LLL: "D MMMM YYYY LT",
-            LLLL: "dddd, D MMMM YYYY LT"
-        },
-        calendar: {
-            sameDay: '[ថ្ងៃនៈ ម៉ោង] LT',
-            nextDay: '[ស្អែក ម៉ោង] LT',
-            nextWeek: 'dddd [ម៉ោង] LT',
-            lastDay: '[ម្សិលមិញ ម៉ោង] LT',
-            lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT',
-            sameElse: 'L'
-        },
-        relativeTime: {
-            future: "%sទៀត",
-            past: "%sមុន",
-            s: "ប៉ុន្មានវិនាទី",
-            m: "មួយនាទី",
-            mm: "%d នាទី",
-            h: "មួយម៉ោង",
-            hh: "%d ម៉ោង",
-            d: "មួយថ្ងៃ",
-            dd: "%d ថ្ងៃ",
-            M: "មួយខែ",
-            MM: "%d ខែ",
-            y: "មួយឆ្នាំ",
-            yy: "%d ឆ្នាំ"
-        },
-        week: {
-            dow: 1, // Monday is the first day of the week.
-            doy: 4 // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/ko.js b/resources/lib/moment/lang/ko.js
deleted file mode 100644 (file)
index 3b469df..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// moment.js language configuration
-// language : korean (ko)
-//
-// authors 
-//
-// - Kyungwook, Park : https://github.com/kyungw00k
-// - Jeeeyul Lee <jeeeyul@gmail.com>
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ko', {
-        months : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),
-        monthsShort : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),
-        weekdays : "일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),
-        weekdaysShort : "일_월_화_수_목_금_토".split("_"),
-        weekdaysMin : "일_월_화_수_목_금_토".split("_"),
-        longDateFormat : {
-            LT : "A h시 mm분",
-            L : "YYYY.MM.DD",
-            LL : "YYYY년 MMMM D일",
-            LLL : "YYYY년 MMMM D일 LT",
-            LLLL : "YYYY년 MMMM D일 dddd LT"
-        },
-        meridiem : function (hour, minute, isUpper) {
-            return hour < 12 ? '오전' : '오후';
-        },
-        calendar : {
-            sameDay : '오늘 LT',
-            nextDay : '내일 LT',
-            nextWeek : 'dddd LT',
-            lastDay : '어제 LT',
-            lastWeek : '지난주 dddd LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s 후",
-            past : "%s 전",
-            s : "몇초",
-            ss : "%d초",
-            m : "일분",
-            mm : "%d분",
-            h : "한시간",
-            hh : "%d시간",
-            d : "하루",
-            dd : "%d일",
-            M : "한달",
-            MM : "%d달",
-            y : "일년",
-            yy : "%d년"
-        },
-        ordinal : '%d일',
-        meridiemParse : /(오전|오후)/,
-        isPM : function (token) {
-            return token === "오후";
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/lb.js b/resources/lib/moment/lang/lb.js
deleted file mode 100644 (file)
index 946ba13..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-// moment.js language configuration
-// language : Luxembourgish (lb)
-// author : mweimerskirch : https://github.com/mweimerskirch
-
-// Note: Luxembourgish has a very particular phonological rule ("Eifeler Regel") that causes the
-// deletion of the final "n" in certain contexts. That's what the "eifelerRegelAppliesToWeekday"
-// and "eifelerRegelAppliesToNumber" methods are meant for
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function processRelativeTime(number, withoutSuffix, key, isFuture) {
-        var format = {
-            'm': ['eng Minutt', 'enger Minutt'],
-            'h': ['eng Stonn', 'enger Stonn'],
-            'd': ['een Dag', 'engem Dag'],
-            'dd': [number + ' Deeg', number + ' Deeg'],
-            'M': ['ee Mount', 'engem Mount'],
-            'MM': [number + ' Méint', number + ' Méint'],
-            'y': ['ee Joer', 'engem Joer'],
-            'yy': [number + ' Joer', number + ' Joer']
-        };
-        return withoutSuffix ? format[key][0] : format[key][1];
-    }
-
-    function processFutureTime(string) {
-        var number = string.substr(0, string.indexOf(' '));
-        if (eifelerRegelAppliesToNumber(number)) {
-            return "a " + string;
-        }
-        return "an " + string;
-    }
-
-    function processPastTime(string) {
-        var number = string.substr(0, string.indexOf(' '));
-        if (eifelerRegelAppliesToNumber(number)) {
-            return "viru " + string;
-        }
-        return "virun " + string;
-    }
-
-    function processLastWeek(string1) {
-        var weekday = this.format('d');
-        if (eifelerRegelAppliesToWeekday(weekday)) {
-            return '[Leschte] dddd [um] LT';
-        }
-        return '[Leschten] dddd [um] LT';
-    }
-
-    /**
-     * Returns true if the word before the given week day loses the "-n" ending.
-     * e.g. "Leschten Dënschdeg" but "Leschte Méindeg"
-     *
-     * @param weekday {integer}
-     * @returns {boolean}
-     */
-    function eifelerRegelAppliesToWeekday(weekday) {
-        weekday = parseInt(weekday, 10);
-        switch (weekday) {
-        case 0: // Sonndeg
-        case 1: // Méindeg
-        case 3: // Mëttwoch
-        case 5: // Freideg
-        case 6: // Samschdeg
-            return true;
-        default: // 2 Dënschdeg, 4 Donneschdeg
-            return false;
-        }
-    }
-
-    /**
-     * Returns true if the word before the given number loses the "-n" ending.
-     * e.g. "an 10 Deeg" but "a 5 Deeg"
-     *
-     * @param number {integer}
-     * @returns {boolean}
-     */
-    function eifelerRegelAppliesToNumber(number) {
-        number = parseInt(number, 10);
-        if (isNaN(number)) {
-            return false;
-        }
-        if (number < 0) {
-            // Negative Number --> always true
-            return true;
-        } else if (number < 10) {
-            // Only 1 digit
-            if (4 <= number && number <= 7) {
-                return true;
-            }
-            return false;
-        } else if (number < 100) {
-            // 2 digits
-            var lastDigit = number % 10, firstDigit = number / 10;
-            if (lastDigit === 0) {
-                return eifelerRegelAppliesToNumber(firstDigit);
-            }
-            return eifelerRegelAppliesToNumber(lastDigit);
-        } else if (number < 10000) {
-            // 3 or 4 digits --> recursively check first digit
-            while (number >= 10) {
-                number = number / 10;
-            }
-            return eifelerRegelAppliesToNumber(number);
-        } else {
-            // Anything larger than 4 digits: recursively check first n-3 digits
-            number = number / 1000;
-            return eifelerRegelAppliesToNumber(number);
-        }
-    }
-
-    return moment.lang('lb', {
-        months: "Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),
-        monthsShort: "Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),
-        weekdays: "Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),
-        weekdaysShort: "So._Mé._Dë._Më._Do._Fr._Sa.".split("_"),
-        weekdaysMin: "So_Mé_Dë_Më_Do_Fr_Sa".split("_"),
-        longDateFormat: {
-            LT: "H:mm [Auer]",
-            L: "DD.MM.YYYY",
-            LL: "D. MMMM YYYY",
-            LLL: "D. MMMM YYYY LT",
-            LLLL: "dddd, D. MMMM YYYY LT"
-        },
-        calendar: {
-            sameDay: "[Haut um] LT",
-            sameElse: "L",
-            nextDay: '[Muer um] LT',
-            nextWeek: 'dddd [um] LT',
-            lastDay: '[Gëschter um] LT',
-            lastWeek: processLastWeek
-        },
-        relativeTime: {
-            future: processFutureTime,
-            past: processPastTime,
-            s: "e puer Sekonnen",
-            m: processRelativeTime,
-            mm: "%d Minutten",
-            h: processRelativeTime,
-            hh: "%d Stonnen",
-            d: processRelativeTime,
-            dd: processRelativeTime,
-            M: processRelativeTime,
-            MM: processRelativeTime,
-            y: processRelativeTime,
-            yy: processRelativeTime
-        },
-        ordinal: '%d.',
-        week: {
-            dow: 1, // Monday is the first day of the week.
-            doy: 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/lt.js b/resources/lib/moment/lang/lt.js
deleted file mode 100644 (file)
index 3c11b89..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-// moment.js language configuration
-// language : Lithuanian (lt)
-// author : Mindaugas Mozūras : https://github.com/mmozuras
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var units = {
-        "m" : "minutė_minutės_minutę",
-        "mm": "minutės_minučių_minutes",
-        "h" : "valanda_valandos_valandą",
-        "hh": "valandos_valandų_valandas",
-        "d" : "diena_dienos_dieną",
-        "dd": "dienos_dienų_dienas",
-        "M" : "mėnuo_mėnesio_mėnesį",
-        "MM": "mėnesiai_mėnesių_mėnesius",
-        "y" : "metai_metų_metus",
-        "yy": "metai_metų_metus"
-    },
-    weekDays = "sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis".split("_");
-
-    function translateSeconds(number, withoutSuffix, key, isFuture) {
-        if (withoutSuffix) {
-            return "kelios sekundės";
-        } else {
-            return isFuture ? "kelių sekundžių" : "kelias sekundes";
-        }
-    }
-
-    function translateSingular(number, withoutSuffix, key, isFuture) {
-        return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]);
-    }
-
-    function special(number) {
-        return number % 10 === 0 || (number > 10 && number < 20);
-    }
-
-    function forms(key) {
-        return units[key].split("_");
-    }
-
-    function translate(number, withoutSuffix, key, isFuture) {
-        var result = number + " ";
-        if (number === 1) {
-            return result + translateSingular(number, withoutSuffix, key[0], isFuture);
-        } else if (withoutSuffix) {
-            return result + (special(number) ? forms(key)[1] : forms(key)[0]);
-        } else {
-            if (isFuture) {
-                return result + forms(key)[1];
-            } else {
-                return result + (special(number) ? forms(key)[1] : forms(key)[2]);
-            }
-        }
-    }
-
-    function relativeWeekDay(moment, format) {
-        var nominative = format.indexOf('dddd HH:mm') === -1,
-            weekDay = weekDays[moment.day()];
-
-        return nominative ? weekDay : weekDay.substring(0, weekDay.length - 2) + "į";
-    }
-
-    return moment.lang("lt", {
-        months : "sausio_vasario_kovo_balandžio_gegužės_biržėlio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio".split("_"),
-        monthsShort : "sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),
-        weekdays : relativeWeekDay,
-        weekdaysShort : "Sek_Pir_Ant_Tre_Ket_Pen_Šeš".split("_"),
-        weekdaysMin : "S_P_A_T_K_Pn_Š".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "YYYY-MM-DD",
-            LL : "YYYY [m.] MMMM D [d.]",
-            LLL : "YYYY [m.] MMMM D [d.], LT [val.]",
-            LLLL : "YYYY [m.] MMMM D [d.], dddd, LT [val.]",
-            l : "YYYY-MM-DD",
-            ll : "YYYY [m.] MMMM D [d.]",
-            lll : "YYYY [m.] MMMM D [d.], LT [val.]",
-            llll : "YYYY [m.] MMMM D [d.], ddd, LT [val.]"
-        },
-        calendar : {
-            sameDay : "[Šiandien] LT",
-            nextDay : "[Rytoj] LT",
-            nextWeek : "dddd LT",
-            lastDay : "[Vakar] LT",
-            lastWeek : "[Praėjusį] dddd LT",
-            sameElse : "L"
-        },
-        relativeTime : {
-            future : "po %s",
-            past : "prieš %s",
-            s : translateSeconds,
-            m : translateSingular,
-            mm : translate,
-            h : translateSingular,
-            hh : translate,
-            d : translateSingular,
-            dd : translate,
-            M : translateSingular,
-            MM : translate,
-            y : translateSingular,
-            yy : translate
-        },
-        ordinal : function (number) {
-            return number + '-oji';
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/lv.js b/resources/lib/moment/lang/lv.js
deleted file mode 100644 (file)
index ffe25cf..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// moment.js language configuration
-// language : latvian (lv)
-// author : Kristaps Karlsons : https://github.com/skakri
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var units = {
-        'mm': 'minūti_minūtes_minūte_minūtes',
-        'hh': 'stundu_stundas_stunda_stundas',
-        'dd': 'dienu_dienas_diena_dienas',
-        'MM': 'mēnesi_mēnešus_mēnesis_mēneši',
-        'yy': 'gadu_gadus_gads_gadi'
-    };
-
-    function format(word, number, withoutSuffix) {
-        var forms = word.split('_');
-        if (withoutSuffix) {
-            return number % 10 === 1 && number !== 11 ? forms[2] : forms[3];
-        } else {
-            return number % 10 === 1 && number !== 11 ? forms[0] : forms[1];
-        }
-    }
-
-    function relativeTimeWithPlural(number, withoutSuffix, key) {
-        return number + ' ' + format(units[key], number, withoutSuffix);
-    }
-
-    return moment.lang('lv', {
-        months : "janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"),
-        monthsShort : "jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"),
-        weekdays : "svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"),
-        weekdaysShort : "Sv_P_O_T_C_Pk_S".split("_"),
-        weekdaysMin : "Sv_P_O_T_C_Pk_S".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "YYYY. [gada] D. MMMM",
-            LLL : "YYYY. [gada] D. MMMM, LT",
-            LLLL : "YYYY. [gada] D. MMMM, dddd, LT"
-        },
-        calendar : {
-            sameDay : '[Šodien pulksten] LT',
-            nextDay : '[Rīt pulksten] LT',
-            nextWeek : 'dddd [pulksten] LT',
-            lastDay : '[Vakar pulksten] LT',
-            lastWeek : '[Pagājušā] dddd [pulksten] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s vēlāk",
-            past : "%s agrāk",
-            s : "dažas sekundes",
-            m : "minūti",
-            mm : relativeTimeWithPlural,
-            h : "stundu",
-            hh : relativeTimeWithPlural,
-            d : "dienu",
-            dd : relativeTimeWithPlural,
-            M : "mēnesi",
-            MM : relativeTimeWithPlural,
-            y : "gadu",
-            yy : relativeTimeWithPlural
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/mk.js b/resources/lib/moment/lang/mk.js
deleted file mode 100644 (file)
index 5f272fa..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-// moment.js language configuration
-// language : macedonian (mk)
-// author : Borislav Mickov : https://github.com/B0k0
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('mk', {
-        months : "јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември".split("_"),
-        monthsShort : "јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек".split("_"),
-        weekdays : "недела_понеделник_вторник_среда_четврток_петок_сабота".split("_"),
-        weekdaysShort : "нед_пон_вто_сре_чет_пет_саб".split("_"),
-        weekdaysMin : "нe_пo_вт_ср_че_пе_сa".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "D.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Денес во] LT',
-            nextDay : '[Утре во] LT',
-            nextWeek : 'dddd [во] LT',
-            lastDay : '[Вчера во] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                case 6:
-                    return '[Во изминатата] dddd [во] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[Во изминатиот] dddd [во] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "после %s",
-            past : "пред %s",
-            s : "неколку секунди",
-            m : "минута",
-            mm : "%d минути",
-            h : "час",
-            hh : "%d часа",
-            d : "ден",
-            dd : "%d дена",
-            M : "месец",
-            MM : "%d месеци",
-            y : "година",
-            yy : "%d години"
-        },
-        ordinal : function (number) {
-            var lastDigit = number % 10,
-                last2Digits = number % 100;
-            if (number === 0) {
-                return number + '-ев';
-            } else if (last2Digits === 0) {
-                return number + '-ен';
-            } else if (last2Digits > 10 && last2Digits < 20) {
-                return number + '-ти';
-            } else if (lastDigit === 1) {
-                return number + '-ви';
-            } else if (lastDigit === 2) {
-                return number + '-ри';
-            } else if (lastDigit === 7 || lastDigit === 8) {
-                return number + '-ми';
-            } else {
-                return number + '-ти';
-            }
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/ml.js b/resources/lib/moment/lang/ml.js
deleted file mode 100644 (file)
index cc7db9a..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-// moment.js language configuration
-// language : malayalam (ml)
-// author : Floyd Pink : https://github.com/floydpink
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ml', {
-        months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split("_"),
-        monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split("_"),
-        weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split("_"),
-        weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split("_"),
-        weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split("_"),
-        longDateFormat : {
-            LT : "A h:mm -നു",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY, LT",
-            LLLL : "dddd, D MMMM YYYY, LT"
-        },
-        calendar : {
-            sameDay : '[ഇന്ന്] LT',
-            nextDay : '[നാളെ] LT',
-            nextWeek : 'dddd, LT',
-            lastDay : '[ഇന്നലെ] LT',
-            lastWeek : '[കഴിഞ്ഞ] dddd, LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s കഴിഞ്ഞ്",
-            past : "%s മുൻപ്",
-            s : "അൽപ നിമിഷങ്ങൾ",
-            m : "ഒരു മിനിറ്റ്",
-            mm : "%d മിനിറ്റ്",
-            h : "ഒരു മണിക്കൂർ",
-            hh : "%d മണിക്കൂർ",
-            d : "ഒരു ദിവസം",
-            dd : "%d ദിവസം",
-            M : "ഒരു മാസം",
-            MM : "%d മാസം",
-            y : "ഒരു വർഷം",
-            yy : "%d വർഷം"
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return "രാത്രി";
-            } else if (hour < 12) {
-                return "രാവിലെ";
-            } else if (hour < 17) {
-                return "ഉച്ച കഴിഞ്ഞ്";
-            } else if (hour < 20) {
-                return "വൈകുന്നേരം";
-            } else {
-                return "രാത്രി";
-            }
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/mr.js b/resources/lib/moment/lang/mr.js
deleted file mode 100644 (file)
index 0d1adfd..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-// moment.js language configuration
-// language : Marathi (mr)
-// author : Harshad Kale : https://github.com/kalehv
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var symbolMap = {
-        '1': '१',
-        '2': '२',
-        '3': '३',
-        '4': '४',
-        '5': '५',
-        '6': '६',
-        '7': '७',
-        '8': '८',
-        '9': '९',
-        '0': '०'
-    },
-    numberMap = {
-        '१': '1',
-        '२': '2',
-        '३': '3',
-        '४': '4',
-        '५': '5',
-        '६': '6',
-        '७': '7',
-        '८': '8',
-        '९': '9',
-        '०': '0'
-    };
-
-    return moment.lang('mr', {
-        months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split("_"),
-        monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split("_"),
-        weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split("_"),
-        weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split("_"),
-        weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split("_"),
-        longDateFormat : {
-            LT : "A h:mm वाजता",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY, LT",
-            LLLL : "dddd, D MMMM YYYY, LT"
-        },
-        calendar : {
-            sameDay : '[आज] LT',
-            nextDay : '[उद्या] LT',
-            nextWeek : 'dddd, LT',
-            lastDay : '[काल] LT',
-            lastWeek: '[मागील] dddd, LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s नंतर",
-            past : "%s पूर्वी",
-            s : "सेकंद",
-            m: "एक मिनिट",
-            mm: "%d मिनिटे",
-            h : "एक तास",
-            hh : "%d तास",
-            d : "एक दिवस",
-            dd : "%d दिवस",
-            M : "एक महिना",
-            MM : "%d महिने",
-            y : "एक वर्ष",
-            yy : "%d वर्षे"
-        },
-        preparse: function (string) {
-            return string.replace(/[१२३४५६७८९०]/g, function (match) {
-                return numberMap[match];
-            });
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            });
-        },
-        meridiem: function (hour, minute, isLower)
-        {
-            if (hour < 4) {
-                return "रात्री";
-            } else if (hour < 10) {
-                return "सकाळी";
-            } else if (hour < 17) {
-                return "दुपारी";
-            } else if (hour < 20) {
-                return "सायंकाळी";
-            } else {
-                return "रात्री";
-            }
-        },
-        week : {
-            dow : 0, // Sunday is the first day of the week.
-            doy : 6  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/ms-my.js b/resources/lib/moment/lang/ms-my.js
deleted file mode 100644 (file)
index 501d5aa..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// moment.js language configuration
-// language : Bahasa Malaysia (ms-MY)
-// author : Weldan Jamili : https://github.com/weldan
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ms-my', {
-        months : "Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),
-        monthsShort : "Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),
-        weekdays : "Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),
-        weekdaysShort : "Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),
-        weekdaysMin : "Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),
-        longDateFormat : {
-            LT : "HH.mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY [pukul] LT",
-            LLLL : "dddd, D MMMM YYYY [pukul] LT"
-        },
-        meridiem : function (hours, minutes, isLower) {
-            if (hours < 11) {
-                return 'pagi';
-            } else if (hours < 15) {
-                return 'tengahari';
-            } else if (hours < 19) {
-                return 'petang';
-            } else {
-                return 'malam';
-            }
-        },
-        calendar : {
-            sameDay : '[Hari ini pukul] LT',
-            nextDay : '[Esok pukul] LT',
-            nextWeek : 'dddd [pukul] LT',
-            lastDay : '[Kelmarin pukul] LT',
-            lastWeek : 'dddd [lepas pukul] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "dalam %s",
-            past : "%s yang lepas",
-            s : "beberapa saat",
-            m : "seminit",
-            mm : "%d minit",
-            h : "sejam",
-            hh : "%d jam",
-            d : "sehari",
-            dd : "%d hari",
-            M : "sebulan",
-            MM : "%d bulan",
-            y : "setahun",
-            yy : "%d tahun"
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/nb.js b/resources/lib/moment/lang/nb.js
deleted file mode 100644 (file)
index 2f652ef..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// moment.js language configuration
-// language : norwegian bokmål (nb)
-// authors : Espen Hovlandsdal : https://github.com/rexxars
-//           Sigurd Gartmann : https://github.com/sigurdga
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('nb', {
-        months : "januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),
-        monthsShort : "jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.".split("_"),
-        weekdays : "søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),
-        weekdaysShort : "sø._ma._ti._on._to._fr._lø.".split("_"),
-        weekdaysMin : "sø_ma_ti_on_to_fr_lø".split("_"),
-        longDateFormat : {
-            LT : "H.mm",
-            L : "DD.MM.YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY [kl.] LT",
-            LLLL : "dddd D. MMMM YYYY [kl.] LT"
-        },
-        calendar : {
-            sameDay: '[i dag kl.] LT',
-            nextDay: '[i morgen kl.] LT',
-            nextWeek: 'dddd [kl.] LT',
-            lastDay: '[i går kl.] LT',
-            lastWeek: '[forrige] dddd [kl.] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "om %s",
-            past : "for %s siden",
-            s : "noen sekunder",
-            m : "ett minutt",
-            mm : "%d minutter",
-            h : "en time",
-            hh : "%d timer",
-            d : "en dag",
-            dd : "%d dager",
-            M : "en måned",
-            MM : "%d måneder",
-            y : "ett år",
-            yy : "%d år"
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/ne.js b/resources/lib/moment/lang/ne.js
deleted file mode 100644 (file)
index 1d57b8c..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-// moment.js language configuration
-// language : nepali/nepalese
-// author : suvash : https://github.com/suvash
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var symbolMap = {
-        '1': '१',
-        '2': '२',
-        '3': '३',
-        '4': '४',
-        '5': '५',
-        '6': '६',
-        '7': '७',
-        '8': '८',
-        '9': '९',
-        '0': '०'
-    },
-    numberMap = {
-        '१': '1',
-        '२': '2',
-        '३': '3',
-        '४': '4',
-        '५': '5',
-        '६': '6',
-        '७': '7',
-        '८': '8',
-        '९': '9',
-        '०': '0'
-    };
-
-    return moment.lang('ne', {
-        months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split("_"),
-        monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split("_"),
-        weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split("_"),
-        weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split("_"),
-        weekdaysMin : 'आइ._सो._मङ्_बु._बि._शु._श.'.split("_"),
-        longDateFormat : {
-            LT : "Aको h:mm बजे",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY, LT",
-            LLLL : "dddd, D MMMM YYYY, LT"
-        },
-        preparse: function (string) {
-            return string.replace(/[१२३४५६७८९०]/g, function (match) {
-                return numberMap[match];
-            });
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            });
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 3) {
-                return "राती";
-            } else if (hour < 10) {
-                return "बिहान";
-            } else if (hour < 15) {
-                return "दिउँसो";
-            } else if (hour < 18) {
-                return "बेलुका";
-            } else if (hour < 20) {
-                return "साँझ";
-            } else {
-                return "राती";
-            }
-        },
-        calendar : {
-            sameDay : '[आज] LT',
-            nextDay : '[भोली] LT',
-            nextWeek : '[आउँदो] dddd[,] LT',
-            lastDay : '[हिजो] LT',
-            lastWeek : '[गएको] dddd[,] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%sमा",
-            past : "%s अगाडी",
-            s : "केही समय",
-            m : "एक मिनेट",
-            mm : "%d मिनेट",
-            h : "एक घण्टा",
-            hh : "%d घण्टा",
-            d : "एक दिन",
-            dd : "%d दिन",
-            M : "एक महिना",
-            MM : "%d महिना",
-            y : "एक बर्ष",
-            yy : "%d बर्ष"
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/nl.js b/resources/lib/moment/lang/nl.js
deleted file mode 100644 (file)
index ffd454f..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-// moment.js language configuration
-// language : dutch (nl)
-// author : Joris Röling : https://github.com/jjupiter
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var monthsShortWithDots = "jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),
-        monthsShortWithoutDots = "jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_");
-
-    return moment.lang('nl', {
-        months : "januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),
-        monthsShort : function (m, format) {
-            if (/-MMM-/.test(format)) {
-                return monthsShortWithoutDots[m.month()];
-            } else {
-                return monthsShortWithDots[m.month()];
-            }
-        },
-        weekdays : "zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),
-        weekdaysShort : "zo._ma._di._wo._do._vr._za.".split("_"),
-        weekdaysMin : "Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD-MM-YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: '[vandaag om] LT',
-            nextDay: '[morgen om] LT',
-            nextWeek: 'dddd [om] LT',
-            lastDay: '[gisteren om] LT',
-            lastWeek: '[afgelopen] dddd [om] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "over %s",
-            past : "%s geleden",
-            s : "een paar seconden",
-            m : "één minuut",
-            mm : "%d minuten",
-            h : "één uur",
-            hh : "%d uur",
-            d : "één dag",
-            dd : "%d dagen",
-            M : "één maand",
-            MM : "%d maanden",
-            y : "één jaar",
-            yy : "%d jaar"
-        },
-        ordinal : function (number) {
-            return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/nn.js b/resources/lib/moment/lang/nn.js
deleted file mode 100644 (file)
index 8c15108..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// moment.js language configuration
-// language : norwegian nynorsk (nn)
-// author : https://github.com/mechuwind
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('nn', {
-        months : "januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),
-        monthsShort : "jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),
-        weekdays : "sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),
-        weekdaysShort : "sun_mån_tys_ons_tor_fre_lau".split("_"),
-        weekdaysMin : "su_må_ty_on_to_fr_lø".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: '[I dag klokka] LT',
-            nextDay: '[I morgon klokka] LT',
-            nextWeek: 'dddd [klokka] LT',
-            lastDay: '[I går klokka] LT',
-            lastWeek: '[Føregåande] dddd [klokka] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "om %s",
-            past : "for %s sidan",
-            s : "nokre sekund",
-            m : "eit minutt",
-            mm : "%d minutt",
-            h : "ein time",
-            hh : "%d timar",
-            d : "ein dag",
-            dd : "%d dagar",
-            M : "ein månad",
-            MM : "%d månader",
-            y : "eit år",
-            yy : "%d år"
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/pl.js b/resources/lib/moment/lang/pl.js
deleted file mode 100644 (file)
index 97770d2..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-// moment.js language configuration
-// language : polish (pl)
-// author : Rafal Hirsz : https://github.com/evoL
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var monthsNominative = "styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),
-        monthsSubjective = "stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_");
-
-    function plural(n) {
-        return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1);
-    }
-
-    function translate(number, withoutSuffix, key) {
-        var result = number + " ";
-        switch (key) {
-        case 'm':
-            return withoutSuffix ? 'minuta' : 'minutę';
-        case 'mm':
-            return result + (plural(number) ? 'minuty' : 'minut');
-        case 'h':
-            return withoutSuffix  ? 'godzina'  : 'godzinę';
-        case 'hh':
-            return result + (plural(number) ? 'godziny' : 'godzin');
-        case 'MM':
-            return result + (plural(number) ? 'miesiące' : 'miesięcy');
-        case 'yy':
-            return result + (plural(number) ? 'lata' : 'lat');
-        }
-    }
-
-    return moment.lang('pl', {
-        months : function (momentToFormat, format) {
-            if (/D MMMM/.test(format)) {
-                return monthsSubjective[momentToFormat.month()];
-            } else {
-                return monthsNominative[momentToFormat.month()];
-            }
-        },
-        monthsShort : "sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),
-        weekdays : "niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),
-        weekdaysShort : "nie_pon_wt_śr_czw_pt_sb".split("_"),
-        weekdaysMin : "N_Pn_Wt_Śr_Cz_Pt_So".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: '[Dziś o] LT',
-            nextDay: '[Jutro o] LT',
-            nextWeek: '[W] dddd [o] LT',
-            lastDay: '[Wczoraj o] LT',
-            lastWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[W zeszłą niedzielę o] LT';
-                case 3:
-                    return '[W zeszłą środę o] LT';
-                case 6:
-                    return '[W zeszłą sobotę o] LT';
-                default:
-                    return '[W zeszły] dddd [o] LT';
-                }
-            },
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "za %s",
-            past : "%s temu",
-            s : "kilka sekund",
-            m : translate,
-            mm : translate,
-            h : translate,
-            hh : translate,
-            d : "1 dzień",
-            dd : '%d dni',
-            M : "miesiąc",
-            MM : translate,
-            y : "rok",
-            yy : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/pt-br.js b/resources/lib/moment/lang/pt-br.js
deleted file mode 100644 (file)
index 8f142d1..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// moment.js language configuration
-// language : brazilian portuguese (pt-br)
-// author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('pt-br', {
-        months : "janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro".split("_"),
-        monthsShort : "jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez".split("_"),
-        weekdays : "domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado".split("_"),
-        weekdaysShort : "dom_seg_ter_qua_qui_sex_sáb".split("_"),
-        weekdaysMin : "dom_2ª_3ª_4ª_5ª_6ª_sáb".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D [de] MMMM [de] YYYY",
-            LLL : "D [de] MMMM [de] YYYY [às] LT",
-            LLLL : "dddd, D [de] MMMM [de] YYYY [às] LT"
-        },
-        calendar : {
-            sameDay: '[Hoje às] LT',
-            nextDay: '[Amanhã às] LT',
-            nextWeek: 'dddd [às] LT',
-            lastDay: '[Ontem às] LT',
-            lastWeek: function () {
-                return (this.day() === 0 || this.day() === 6) ?
-                    '[Último] dddd [às] LT' : // Saturday + Sunday
-                    '[Última] dddd [às] LT'; // Monday - Friday
-            },
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "em %s",
-            past : "%s atrás",
-            s : "segundos",
-            m : "um minuto",
-            mm : "%d minutos",
-            h : "uma hora",
-            hh : "%d horas",
-            d : "um dia",
-            dd : "%d dias",
-            M : "um mês",
-            MM : "%d meses",
-            y : "um ano",
-            yy : "%d anos"
-        },
-        ordinal : '%dº'
-    });
-}));
diff --git a/resources/lib/moment/lang/pt.js b/resources/lib/moment/lang/pt.js
deleted file mode 100644 (file)
index 3042844..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// moment.js language configuration
-// language : portuguese (pt)
-// author : Jefferson : https://github.com/jalex79
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('pt', {
-        months : "janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro".split("_"),
-        monthsShort : "jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez".split("_"),
-        weekdays : "domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado".split("_"),
-        weekdaysShort : "dom_seg_ter_qua_qui_sex_sáb".split("_"),
-        weekdaysMin : "dom_2ª_3ª_4ª_5ª_6ª_sáb".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D [de] MMMM [de] YYYY",
-            LLL : "D [de] MMMM [de] YYYY LT",
-            LLLL : "dddd, D [de] MMMM [de] YYYY LT"
-        },
-        calendar : {
-            sameDay: '[Hoje às] LT',
-            nextDay: '[Amanhã às] LT',
-            nextWeek: 'dddd [às] LT',
-            lastDay: '[Ontem às] LT',
-            lastWeek: function () {
-                return (this.day() === 0 || this.day() === 6) ?
-                    '[Último] dddd [às] LT' : // Saturday + Sunday
-                    '[Última] dddd [às] LT'; // Monday - Friday
-            },
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "em %s",
-            past : "há %s",
-            s : "segundos",
-            m : "um minuto",
-            mm : "%d minutos",
-            h : "uma hora",
-            hh : "%d horas",
-            d : "um dia",
-            dd : "%d dias",
-            M : "um mês",
-            MM : "%d meses",
-            y : "um ano",
-            yy : "%d anos"
-        },
-        ordinal : '%dº',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/ro.js b/resources/lib/moment/lang/ro.js
deleted file mode 100644 (file)
index fc27509..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// moment.js language configuration
-// language : romanian (ro)
-// author : Vlad Gurdiga : https://github.com/gurdiga
-// author : Valentin Agachi : https://github.com/avaly
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function relativeTimeWithPlural(number, withoutSuffix, key) {
-        var format = {
-            'mm': 'minute',
-            'hh': 'ore',
-            'dd': 'zile',
-            'MM': 'luni',
-            'yy': 'ani'
-        },
-            separator = ' ';
-        if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) {
-            separator = ' de ';
-        }
-
-        return number + separator + format[key];
-    }
-
-    return moment.lang('ro', {
-        months : "ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),
-        monthsShort : "ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.".split("_"),
-        weekdays : "duminică_luni_marți_miercuri_joi_vineri_sâmbătă".split("_"),
-        weekdaysShort : "Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"),
-        weekdaysMin : "Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY H:mm",
-            LLLL : "dddd, D MMMM YYYY H:mm"
-        },
-        calendar : {
-            sameDay: "[azi la] LT",
-            nextDay: '[mâine la] LT',
-            nextWeek: 'dddd [la] LT',
-            lastDay: '[ieri la] LT',
-            lastWeek: '[fosta] dddd [la] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "peste %s",
-            past : "%s în urmă",
-            s : "câteva secunde",
-            m : "un minut",
-            mm : relativeTimeWithPlural,
-            h : "o oră",
-            hh : relativeTimeWithPlural,
-            d : "o zi",
-            dd : relativeTimeWithPlural,
-            M : "o lună",
-            MM : relativeTimeWithPlural,
-            y : "un an",
-            yy : relativeTimeWithPlural
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/ru.js b/resources/lib/moment/lang/ru.js
deleted file mode 100644 (file)
index dc013a7..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-// moment.js language configuration
-// language : russian (ru)
-// author : Viktorminator : https://github.com/Viktorminator
-// Author : Menelion Elensúle : https://github.com/Oire
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function plural(word, num) {
-        var forms = word.split('_');
-        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
-    }
-
-    function relativeTimeWithPlural(number, withoutSuffix, key) {
-        var format = {
-            'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут',
-            'hh': 'час_часа_часов',
-            'dd': 'день_дня_дней',
-            'MM': 'месяц_месяца_месяцев',
-            'yy': 'год_года_лет'
-        };
-        if (key === 'm') {
-            return withoutSuffix ? 'минута' : 'минуту';
-        }
-        else {
-            return number + ' ' + plural(format[key], +number);
-        }
-    }
-
-    function monthsCaseReplace(m, format) {
-        var months = {
-            'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'),
-            'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_')
-        },
-
-        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return months[nounCase][m.month()];
-    }
-
-    function monthsShortCaseReplace(m, format) {
-        var monthsShort = {
-            'nominative': 'янв_фев_мар_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'),
-            'accusative': 'янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек'.split('_')
-        },
-
-        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return monthsShort[nounCase][m.month()];
-    }
-
-    function weekdaysCaseReplace(m, format) {
-        var weekdays = {
-            'nominative': 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'),
-            'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_')
-        },
-
-        nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую)? ?\] ?dddd/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return weekdays[nounCase][m.day()];
-    }
-
-    return moment.lang('ru', {
-        months : monthsCaseReplace,
-        monthsShort : monthsShortCaseReplace,
-        weekdays : weekdaysCaseReplace,
-        weekdaysShort : "вс_пн_вт_ср_чт_пт_сб".split("_"),
-        weekdaysMin : "вс_пн_вт_ср_чт_пт_сб".split("_"),
-        monthsParse : [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[й|я]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i],
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY г.",
-            LLL : "D MMMM YYYY г., LT",
-            LLLL : "dddd, D MMMM YYYY г., LT"
-        },
-        calendar : {
-            sameDay: '[Сегодня в] LT',
-            nextDay: '[Завтра в] LT',
-            lastDay: '[Вчера в] LT',
-            nextWeek: function () {
-                return this.day() === 2 ? '[Во] dddd [в] LT' : '[В] dddd [в] LT';
-            },
-            lastWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[В прошлое] dddd [в] LT';
-                case 1:
-                case 2:
-                case 4:
-                    return '[В прошлый] dddd [в] LT';
-                case 3:
-                case 5:
-                case 6:
-                    return '[В прошлую] dddd [в] LT';
-                }
-            },
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "через %s",
-            past : "%s назад",
-            s : "несколько секунд",
-            m : relativeTimeWithPlural,
-            mm : relativeTimeWithPlural,
-            h : "час",
-            hh : relativeTimeWithPlural,
-            d : "день",
-            dd : relativeTimeWithPlural,
-            M : "месяц",
-            MM : relativeTimeWithPlural,
-            y : "год",
-            yy : relativeTimeWithPlural
-        },
-
-        meridiemParse: /ночи|утра|дня|вечера/i,
-        isPM : function (input) {
-            return /^(дня|вечера)$/.test(input);
-        },
-
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return "ночи";
-            } else if (hour < 12) {
-                return "утра";
-            } else if (hour < 17) {
-                return "дня";
-            } else {
-                return "вечера";
-            }
-        },
-
-        ordinal: function (number, period) {
-            switch (period) {
-            case 'M':
-            case 'd':
-            case 'DDD':
-                return number + '-й';
-            case 'D':
-                return number + '-го';
-            case 'w':
-            case 'W':
-                return number + '-я';
-            default:
-                return number;
-            }
-        },
-
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/sk.js b/resources/lib/moment/lang/sk.js
deleted file mode 100644 (file)
index ed8a41d..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-// moment.js language configuration
-// language : slovak (sk)
-// author : Martin Minka : https://github.com/k2s
-// based on work of petrbela : https://github.com/petrbela
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var months = "január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_"),
-        monthsShort = "jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_");
-
-    function plural(n) {
-        return (n > 1) && (n < 5);
-    }
-
-    function translate(number, withoutSuffix, key, isFuture) {
-        var result = number + " ";
-        switch (key) {
-        case 's':  // a few seconds / in a few seconds / a few seconds ago
-            return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami';
-        case 'm':  // a minute / in a minute / a minute ago
-            return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou');
-        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'minúty' : 'minút');
-            } else {
-                return result + 'minútami';
-            }
-            break;
-        case 'h':  // an hour / in an hour / an hour ago
-            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
-        case 'hh': // 9 hours / in 9 hours / 9 hours ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'hodiny' : 'hodín');
-            } else {
-                return result + 'hodinami';
-            }
-            break;
-        case 'd':  // a day / in a day / a day ago
-            return (withoutSuffix || isFuture) ? 'deň' : 'dňom';
-        case 'dd': // 9 days / in 9 days / 9 days ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'dni' : 'dní');
-            } else {
-                return result + 'dňami';
-            }
-            break;
-        case 'M':  // a month / in a month / a month ago
-            return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom';
-        case 'MM': // 9 months / in 9 months / 9 months ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'mesiace' : 'mesiacov');
-            } else {
-                return result + 'mesiacmi';
-            }
-            break;
-        case 'y':  // a year / in a year / a year ago
-            return (withoutSuffix || isFuture) ? 'rok' : 'rokom';
-        case 'yy': // 9 years / in 9 years / 9 years ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'roky' : 'rokov');
-            } else {
-                return result + 'rokmi';
-            }
-            break;
-        }
-    }
-
-    return moment.lang('sk', {
-        months : months,
-        monthsShort : monthsShort,
-        monthsParse : (function (months, monthsShort) {
-            var i, _monthsParse = [];
-            for (i = 0; i < 12; i++) {
-                // use custom parser to solve problem with July (červenec)
-                _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
-            }
-            return _monthsParse;
-        }(months, monthsShort)),
-        weekdays : "nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"),
-        weekdaysShort : "ne_po_ut_st_št_pi_so".split("_"),
-        weekdaysMin : "ne_po_ut_st_št_pi_so".split("_"),
-        longDateFormat : {
-            LT: "H:mm",
-            L : "DD.MM.YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[dnes o] LT",
-            nextDay: '[zajtra o] LT',
-            nextWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[v nedeľu o] LT';
-                case 1:
-                case 2:
-                    return '[v] dddd [o] LT';
-                case 3:
-                    return '[v stredu o] LT';
-                case 4:
-                    return '[vo štvrtok o] LT';
-                case 5:
-                    return '[v piatok o] LT';
-                case 6:
-                    return '[v sobotu o] LT';
-                }
-            },
-            lastDay: '[včera o] LT',
-            lastWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[minulú nedeľu o] LT';
-                case 1:
-                case 2:
-                    return '[minulý] dddd [o] LT';
-                case 3:
-                    return '[minulú stredu o] LT';
-                case 4:
-                case 5:
-                    return '[minulý] dddd [o] LT';
-                case 6:
-                    return '[minulú sobotu o] LT';
-                }
-            },
-            sameElse: "L"
-        },
-        relativeTime : {
-            future : "za %s",
-            past : "pred %s",
-            s : translate,
-            m : translate,
-            mm : translate,
-            h : translate,
-            hh : translate,
-            d : translate,
-            dd : translate,
-            M : translate,
-            MM : translate,
-            y : translate,
-            yy : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/sl.js b/resources/lib/moment/lang/sl.js
deleted file mode 100644 (file)
index d260f80..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-// moment.js language configuration
-// language : slovenian (sl)
-// author : Robert Sedovšek : https://github.com/sedovsek
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function translate(number, withoutSuffix, key) {
-        var result = number + " ";
-        switch (key) {
-        case 'm':
-            return withoutSuffix ? 'ena minuta' : 'eno minuto';
-        case 'mm':
-            if (number === 1) {
-                result += 'minuta';
-            } else if (number === 2) {
-                result += 'minuti';
-            } else if (number === 3 || number === 4) {
-                result += 'minute';
-            } else {
-                result += 'minut';
-            }
-            return result;
-        case 'h':
-            return withoutSuffix ? 'ena ura' : 'eno uro';
-        case 'hh':
-            if (number === 1) {
-                result += 'ura';
-            } else if (number === 2) {
-                result += 'uri';
-            } else if (number === 3 || number === 4) {
-                result += 'ure';
-            } else {
-                result += 'ur';
-            }
-            return result;
-        case 'dd':
-            if (number === 1) {
-                result += 'dan';
-            } else {
-                result += 'dni';
-            }
-            return result;
-        case 'MM':
-            if (number === 1) {
-                result += 'mesec';
-            } else if (number === 2) {
-                result += 'meseca';
-            } else if (number === 3 || number === 4) {
-                result += 'mesece';
-            } else {
-                result += 'mesecev';
-            }
-            return result;
-        case 'yy':
-            if (number === 1) {
-                result += 'leto';
-            } else if (number === 2) {
-                result += 'leti';
-            } else if (number === 3 || number === 4) {
-                result += 'leta';
-            } else {
-                result += 'let';
-            }
-            return result;
-        }
-    }
-
-    return moment.lang('sl', {
-        months : "januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),
-        monthsShort : "jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),
-        weekdays : "nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"),
-        weekdaysShort : "ned._pon._tor._sre._čet._pet._sob.".split("_"),
-        weekdaysMin : "ne_po_to_sr_če_pe_so".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD. MM. YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd, D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay  : '[danes ob] LT',
-            nextDay  : '[jutri ob] LT',
-
-            nextWeek : function () {
-                switch (this.day()) {
-                case 0:
-                    return '[v] [nedeljo] [ob] LT';
-                case 3:
-                    return '[v] [sredo] [ob] LT';
-                case 6:
-                    return '[v] [soboto] [ob] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[v] dddd [ob] LT';
-                }
-            },
-            lastDay  : '[včeraj ob] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                case 6:
-                    return '[prejšnja] dddd [ob] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[prejšnji] dddd [ob] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "čez %s",
-            past   : "%s nazaj",
-            s      : "nekaj sekund",
-            m      : translate,
-            mm     : translate,
-            h      : translate,
-            hh     : translate,
-            d      : "en dan",
-            dd     : translate,
-            M      : "en mesec",
-            MM     : translate,
-            y      : "eno leto",
-            yy     : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/sq.js b/resources/lib/moment/lang/sq.js
deleted file mode 100644 (file)
index 0d3cdcf..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-// moment.js language configuration
-// language : Albanian (sq)
-// author : Flakërim Ismani : https://github.com/flakerimi
-// author: Menelion Elensúle: https://github.com/Oire (tests)
-// author : Oerd Cukalla : https://github.com/oerd (fixes)
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('sq', {
-        months : "Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"),
-        monthsShort : "Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"),
-        weekdays : "E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë".split("_"),
-        weekdaysShort : "Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"),
-        weekdaysMin : "D_H_Ma_Më_E_P_Sh".split("_"),
-        meridiem : function (hours, minutes, isLower) {
-            return hours < 12 ? 'PD' : 'MD';
-        },
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Sot në] LT',
-            nextDay : '[Nesër në] LT',
-            nextWeek : 'dddd [në] LT',
-            lastDay : '[Dje në] LT',
-            lastWeek : 'dddd [e kaluar në] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "në %s",
-            past : "%s më parë",
-            s : "disa sekonda",
-            m : "një minutë",
-            mm : "%d minuta",
-            h : "një orë",
-            hh : "%d orë",
-            d : "një ditë",
-            dd : "%d ditë",
-            M : "një muaj",
-            MM : "%d muaj",
-            y : "një vit",
-            yy : "%d vite"
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/sr-cyrl.js b/resources/lib/moment/lang/sr-cyrl.js
deleted file mode 100644 (file)
index ae1754b..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-// moment.js language configuration
-// language : Serbian-cyrillic (sr-cyrl)
-// author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    var translator = {
-        words: { //Different grammatical cases
-            m: ['један минут', 'једне минуте'],
-            mm: ['минут', 'минуте', 'минута'],
-            h: ['један сат', 'једног сата'],
-            hh: ['сат', 'сата', 'сати'],
-            dd: ['дан', 'дана', 'дана'],
-            MM: ['месец', 'месеца', 'месеци'],
-            yy: ['година', 'године', 'година']
-        },
-        correctGrammaticalCase: function (number, wordKey) {
-            return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
-        },
-        translate: function (number, withoutSuffix, key) {
-            var wordKey = translator.words[key];
-            if (key.length === 1) {
-                return withoutSuffix ? wordKey[0] : wordKey[1];
-            } else {
-                return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
-            }
-        }
-    };
-
-    return moment.lang('sr-cyrl', {
-        months: ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'],
-        monthsShort: ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'],
-        weekdays: ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'],
-        weekdaysShort: ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'],
-        weekdaysMin: ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'],
-        longDateFormat: {
-            LT: "H:mm",
-            L: "DD. MM. YYYY",
-            LL: "D. MMMM YYYY",
-            LLL: "D. MMMM YYYY LT",
-            LLLL: "dddd, D. MMMM YYYY LT"
-        },
-        calendar: {
-            sameDay: '[данас у] LT',
-            nextDay: '[сутра у] LT',
-
-            nextWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[у] [недељу] [у] LT';
-                case 3:
-                    return '[у] [среду] [у] LT';
-                case 6:
-                    return '[у] [суботу] [у] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[у] dddd [у] LT';
-                }
-            },
-            lastDay  : '[јуче у] LT',
-            lastWeek : function () {
-                var lastWeekDays = [
-                    '[прошле] [недеље] [у] LT',
-                    '[прошлог] [понедељка] [у] LT',
-                    '[прошлог] [уторка] [у] LT',
-                    '[прошле] [среде] [у] LT',
-                    '[прошлог] [четвртка] [у] LT',
-                    '[прошлог] [петка] [у] LT',
-                    '[прошле] [суботе] [у] LT'
-                ];
-                return lastWeekDays[this.day()];
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "за %s",
-            past   : "пре %s",
-            s      : "неколико секунди",
-            m      : translator.translate,
-            mm     : translator.translate,
-            h      : translator.translate,
-            hh     : translator.translate,
-            d      : "дан",
-            dd     : translator.translate,
-            M      : "месец",
-            MM     : translator.translate,
-            y      : "годину",
-            yy     : translator.translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/sr.js b/resources/lib/moment/lang/sr.js
deleted file mode 100644 (file)
index 54a5f4f..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-// moment.js language configuration
-// language : Serbian-latin (sr)
-// author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    var translator = {
-        words: { //Different grammatical cases
-            m: ['jedan minut', 'jedne minute'],
-            mm: ['minut', 'minute', 'minuta'],
-            h: ['jedan sat', 'jednog sata'],
-            hh: ['sat', 'sata', 'sati'],
-            dd: ['dan', 'dana', 'dana'],
-            MM: ['mesec', 'meseca', 'meseci'],
-            yy: ['godina', 'godine', 'godina']
-        },
-        correctGrammaticalCase: function (number, wordKey) {
-            return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
-        },
-        translate: function (number, withoutSuffix, key) {
-            var wordKey = translator.words[key];
-            if (key.length === 1) {
-                return withoutSuffix ? wordKey[0] : wordKey[1];
-            } else {
-                return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
-            }
-        }
-    };
-
-    return moment.lang('sr', {
-        months: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'],
-        monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'],
-        weekdays: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'],
-        weekdaysShort: ['ned.', 'pon.', 'uto.', 'sre.', 'čet.', 'pet.', 'sub.'],
-        weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
-        longDateFormat: {
-            LT: "H:mm",
-            L: "DD. MM. YYYY",
-            LL: "D. MMMM YYYY",
-            LLL: "D. MMMM YYYY LT",
-            LLLL: "dddd, D. MMMM YYYY LT"
-        },
-        calendar: {
-            sameDay: '[danas u] LT',
-            nextDay: '[sutra u] LT',
-
-            nextWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[u] [nedelju] [u] LT';
-                case 3:
-                    return '[u] [sredu] [u] LT';
-                case 6:
-                    return '[u] [subotu] [u] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[u] dddd [u] LT';
-                }
-            },
-            lastDay  : '[juče u] LT',
-            lastWeek : function () {
-                var lastWeekDays = [
-                    '[prošle] [nedelje] [u] LT',
-                    '[prošlog] [ponedeljka] [u] LT',
-                    '[prošlog] [utorka] [u] LT',
-                    '[prošle] [srede] [u] LT',
-                    '[prošlog] [četvrtka] [u] LT',
-                    '[prošlog] [petka] [u] LT',
-                    '[prošle] [subote] [u] LT'
-                ];
-                return lastWeekDays[this.day()];
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "za %s",
-            past   : "pre %s",
-            s      : "nekoliko sekundi",
-            m      : translator.translate,
-            mm     : translator.translate,
-            h      : translator.translate,
-            hh     : translator.translate,
-            d      : "dan",
-            dd     : translator.translate,
-            M      : "mesec",
-            MM     : translator.translate,
-            y      : "godinu",
-            yy     : translator.translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/sv.js b/resources/lib/moment/lang/sv.js
deleted file mode 100644 (file)
index 0de8c40..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// moment.js language configuration
-// language : swedish (sv)
-// author : Jens Alm : https://github.com/ulmus
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('sv', {
-        months : "januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),
-        monthsShort : "jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),
-        weekdays : "söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),
-        weekdaysShort : "sön_mån_tis_ons_tor_fre_lör".split("_"),
-        weekdaysMin : "sö_må_ti_on_to_fr_lö".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "YYYY-MM-DD",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: '[Idag] LT',
-            nextDay: '[Imorgon] LT',
-            lastDay: '[Igår] LT',
-            nextWeek: 'dddd LT',
-            lastWeek: '[Förra] dddd[en] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "om %s",
-            past : "för %s sedan",
-            s : "några sekunder",
-            m : "en minut",
-            mm : "%d minuter",
-            h : "en timme",
-            hh : "%d timmar",
-            d : "en dag",
-            dd : "%d dagar",
-            M : "en månad",
-            MM : "%d månader",
-            y : "ett år",
-            yy : "%d år"
-        },
-        ordinal : function (number) {
-            var b = number % 10,
-                output = (~~ (number % 100 / 10) === 1) ? 'e' :
-                (b === 1) ? 'a' :
-                (b === 2) ? 'a' :
-                (b === 3) ? 'e' : 'e';
-            return number + output;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/ta.js b/resources/lib/moment/lang/ta.js
deleted file mode 100644 (file)
index cc742c9..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-// moment.js language configuration
-// language : tamil (ta)
-// author : Arjunkumar Krishnamoorthy : https://github.com/tk120404
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    /*var symbolMap = {
-            '1': '௧',
-            '2': '௨',
-            '3': '௩',
-            '4': '௪',
-            '5': '௫',
-            '6': '௬',
-            '7': '௭',
-            '8': '௮',
-            '9': '௯',
-            '0': '௦'
-        },
-        numberMap = {
-            '௧': '1',
-            '௨': '2',
-            '௩': '3',
-            '௪': '4',
-            '௫': '5',
-            '௬': '6',
-            '௭': '7',
-            '௮': '8',
-            '௯': '9',
-            '௦': '0'
-        }; */
-
-    return moment.lang('ta', {
-        months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split("_"),
-        monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split("_"),
-        weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split("_"),
-        weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split("_"),
-        weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY, LT",
-            LLLL : "dddd, D MMMM YYYY, LT"
-        },
-        calendar : {
-            sameDay : '[இன்று] LT',
-            nextDay : '[நாளை] LT',
-            nextWeek : 'dddd, LT',
-            lastDay : '[நேற்று] LT',
-            lastWeek : '[கடந்த வாரம்] dddd, LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s இல்",
-            past : "%s முன்",
-            s : "ஒரு சில விநாடிகள்",
-            m : "ஒரு நிமிடம்",
-            mm : "%d நிமிடங்கள்",
-            h : "ஒரு மணி நேரம்",
-            hh : "%d மணி நேரம்",
-            d : "ஒரு நாள்",
-            dd : "%d நாட்கள்",
-            M : "ஒரு மாதம்",
-            MM : "%d மாதங்கள்",
-            y : "ஒரு வருடம்",
-            yy : "%d ஆண்டுகள்"
-        },
-/*        preparse: function (string) {
-            return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) {
-                return numberMap[match];
-            });
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            });
-        },*/
-        ordinal : function (number) {
-            return number + 'வது';
-        },
-
-
-// refer http://ta.wikipedia.org/s/1er1      
-
-        meridiem : function (hour, minute, isLower) {
-            if (hour >= 6 && hour <= 10) {
-                return " காலை";
-            } else   if (hour >= 10 && hour <= 14) {
-                return " நண்பகல்";
-            } else    if (hour >= 14 && hour <= 18) {
-                return " எற்பாடு";
-            } else   if (hour >= 18 && hour <= 20) {
-                return " மாலை";
-            } else  if (hour >= 20 && hour <= 24) {
-                return " இரவு";
-            } else  if (hour >= 0 && hour <= 6) {
-                return " வைகறை";
-            }
-        },
-        week : {
-            dow : 0, // Sunday is the first day of the week.
-            doy : 6  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/th.js b/resources/lib/moment/lang/th.js
deleted file mode 100644 (file)
index 70336c8..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// moment.js language configuration
-// language : thai (th)
-// author : Kridsada Thanabulpong : https://github.com/sirn
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('th', {
-        months : "มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),
-        monthsShort : "มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา".split("_"),
-        weekdays : "อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),
-        weekdaysShort : "อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"), // yes, three characters difference
-        weekdaysMin : "อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),
-        longDateFormat : {
-            LT : "H นาฬิกา m นาที",
-            L : "YYYY/MM/DD",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY เวลา LT",
-            LLLL : "วันddddที่ D MMMM YYYY เวลา LT"
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 12) {
-                return "ก่อนเที่ยง";
-            } else {
-                return "หลังเที่ยง";
-            }
-        },
-        calendar : {
-            sameDay : '[วันนี้ เวลา] LT',
-            nextDay : '[พรุ่งนี้ เวลา] LT',
-            nextWeek : 'dddd[หน้า เวลา] LT',
-            lastDay : '[เมื่อวานนี้ เวลา] LT',
-            lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "อีก %s",
-            past : "%sที่แล้ว",
-            s : "ไม่กี่วินาที",
-            m : "1 นาที",
-            mm : "%d นาที",
-            h : "1 ชั่วโมง",
-            hh : "%d ชั่วโมง",
-            d : "1 วัน",
-            dd : "%d วัน",
-            M : "1 เดือน",
-            MM : "%d เดือน",
-            y : "1 ปี",
-            yy : "%d ปี"
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/tl-ph.js b/resources/lib/moment/lang/tl-ph.js
deleted file mode 100644 (file)
index 8044483..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// moment.js language configuration
-// language : Tagalog/Filipino (tl-ph)
-// author : Dan Hagman
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('tl-ph', {
-        months : "Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre".split("_"),
-        monthsShort : "Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis".split("_"),
-        weekdays : "Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado".split("_"),
-        weekdaysShort : "Lin_Lun_Mar_Miy_Huw_Biy_Sab".split("_"),
-        weekdaysMin : "Li_Lu_Ma_Mi_Hu_Bi_Sab".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "MM/D/YYYY",
-            LL : "MMMM D, YYYY",
-            LLL : "MMMM D, YYYY LT",
-            LLLL : "dddd, MMMM DD, YYYY LT"
-        },
-        calendar : {
-            sameDay: "[Ngayon sa] LT",
-            nextDay: '[Bukas sa] LT',
-            nextWeek: 'dddd [sa] LT',
-            lastDay: '[Kahapon sa] LT',
-            lastWeek: 'dddd [huling linggo] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "sa loob ng %s",
-            past : "%s ang nakalipas",
-            s : "ilang segundo",
-            m : "isang minuto",
-            mm : "%d minuto",
-            h : "isang oras",
-            hh : "%d oras",
-            d : "isang araw",
-            dd : "%d araw",
-            M : "isang buwan",
-            MM : "%d buwan",
-            y : "isang taon",
-            yy : "%d taon"
-        },
-        ordinal : function (number) {
-            return number;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/tr.js b/resources/lib/moment/lang/tr.js
deleted file mode 100644 (file)
index e90f250..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-// moment.js language configuration
-// language : turkish (tr)
-// authors : Erhan Gundogan : https://github.com/erhangundogan,
-//           Burak Yiğit Kaya: https://github.com/BYK
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    var suffixes = {
-        1: "'inci",
-        5: "'inci",
-        8: "'inci",
-        70: "'inci",
-        80: "'inci",
-
-        2: "'nci",
-        7: "'nci",
-        20: "'nci",
-        50: "'nci",
-
-        3: "'üncü",
-        4: "'üncü",
-        100: "'üncü",
-
-        6: "'ncı",
-
-        9: "'uncu",
-        10: "'uncu",
-        30: "'uncu",
-
-        60: "'ıncı",
-        90: "'ıncı"
-    };
-
-    return moment.lang('tr', {
-        months : "Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),
-        monthsShort : "Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),
-        weekdays : "Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),
-        weekdaysShort : "Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),
-        weekdaysMin : "Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[bugün saat] LT',
-            nextDay : '[yarın saat] LT',
-            nextWeek : '[haftaya] dddd [saat] LT',
-            lastDay : '[dün] LT',
-            lastWeek : '[geçen hafta] dddd [saat] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s sonra",
-            past : "%s önce",
-            s : "birkaç saniye",
-            m : "bir dakika",
-            mm : "%d dakika",
-            h : "bir saat",
-            hh : "%d saat",
-            d : "bir gün",
-            dd : "%d gün",
-            M : "bir ay",
-            MM : "%d ay",
-            y : "bir yıl",
-            yy : "%d yıl"
-        },
-        ordinal : function (number) {
-            if (number === 0) {  // special case for zero
-                return number + "'ıncı";
-            }
-            var a = number % 10,
-                b = number % 100 - a,
-                c = number >= 100 ? 100 : null;
-
-            return number + (suffixes[a] || suffixes[b] || suffixes[c]);
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/tzm-latn.js b/resources/lib/moment/lang/tzm-latn.js
deleted file mode 100644 (file)
index f7e9089..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// moment.js language configuration
-// language : Morocco Central Atlas Tamaziɣt in Latin (tzm-latn)
-// author : Abdel Said : https://github.com/abdelsaid
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('tzm-latn', {
-        months : "innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),
-        monthsShort : "innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),
-        weekdays : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),
-        weekdaysShort : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),
-        weekdaysMin : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[asdkh g] LT",
-            nextDay: '[aska g] LT',
-            nextWeek: 'dddd [g] LT',
-            lastDay: '[assant g] LT',
-            lastWeek: 'dddd [g] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "dadkh s yan %s",
-            past : "yan %s",
-            s : "imik",
-            m : "minuḍ",
-            mm : "%d minuḍ",
-            h : "saɛa",
-            hh : "%d tassaɛin",
-            d : "ass",
-            dd : "%d ossan",
-            M : "ayowr",
-            MM : "%d iyyirn",
-            y : "asgas",
-            yy : "%d isgasn"
-        },
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/tzm.js b/resources/lib/moment/lang/tzm.js
deleted file mode 100644 (file)
index c7c76bd..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// moment.js language configuration
-// language : Morocco Central Atlas Tamaziɣt (tzm)
-// author : Abdel Said : https://github.com/abdelsaid
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('tzm', {
-        months : "ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),
-        monthsShort : "ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),
-        weekdays : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),
-        weekdaysShort : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),
-        weekdaysMin : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[ⴰⵙⴷⵅ ⴴ] LT",
-            nextDay: '[ⴰⵙⴽⴰ ⴴ] LT',
-            nextWeek: 'dddd [ⴴ] LT',
-            lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT',
-            lastWeek: 'dddd [ⴴ] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s",
-            past : "ⵢⴰⵏ %s",
-            s : "ⵉⵎⵉⴽ",
-            m : "ⵎⵉⵏⵓⴺ",
-            mm : "%d ⵎⵉⵏⵓⴺ",
-            h : "ⵙⴰⵄⴰ",
-            hh : "%d ⵜⴰⵙⵙⴰⵄⵉⵏ",
-            d : "ⴰⵙⵙ",
-            dd : "%d oⵙⵙⴰⵏ",
-            M : "ⴰⵢoⵓⵔ",
-            MM : "%d ⵉⵢⵢⵉⵔⵏ",
-            y : "ⴰⵙⴳⴰⵙ",
-            yy : "%d ⵉⵙⴳⴰⵙⵏ"
-        },
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/uk.js b/resources/lib/moment/lang/uk.js
deleted file mode 100644 (file)
index 47056cb..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-// moment.js language configuration
-// language : ukrainian (uk)
-// author : zemlanin : https://github.com/zemlanin
-// Author : Menelion Elensúle : https://github.com/Oire
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function plural(word, num) {
-        var forms = word.split('_');
-        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
-    }
-
-    function relativeTimeWithPlural(number, withoutSuffix, key) {
-        var format = {
-            'mm': 'хвилина_хвилини_хвилин',
-            'hh': 'година_години_годин',
-            'dd': 'день_дні_днів',
-            'MM': 'місяць_місяці_місяців',
-            'yy': 'рік_роки_років'
-        };
-        if (key === 'm') {
-            return withoutSuffix ? 'хвилина' : 'хвилину';
-        }
-        else if (key === 'h') {
-            return withoutSuffix ? 'година' : 'годину';
-        }
-        else {
-            return number + ' ' + plural(format[key], +number);
-        }
-    }
-
-    function monthsCaseReplace(m, format) {
-        var months = {
-            'nominative': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_'),
-            'accusative': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_')
-        },
-
-        nounCase = (/D[oD]? *MMMM?/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return months[nounCase][m.month()];
-    }
-
-    function weekdaysCaseReplace(m, format) {
-        var weekdays = {
-            'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'),
-            'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'),
-            'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_')
-        },
-
-        nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ?
-            'accusative' :
-            ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ?
-                'genitive' :
-                'nominative');
-
-        return weekdays[nounCase][m.day()];
-    }
-
-    function processHoursFunction(str) {
-        return function () {
-            return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT';
-        };
-    }
-
-    return moment.lang('uk', {
-        months : monthsCaseReplace,
-        monthsShort : "січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),
-        weekdays : weekdaysCaseReplace,
-        weekdaysShort : "нд_пн_вт_ср_чт_пт_сб".split("_"),
-        weekdaysMin : "нд_пн_вт_ср_чт_пт_сб".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY р.",
-            LLL : "D MMMM YYYY р., LT",
-            LLLL : "dddd, D MMMM YYYY р., LT"
-        },
-        calendar : {
-            sameDay: processHoursFunction('[Сьогодні '),
-            nextDay: processHoursFunction('[Завтра '),
-            lastDay: processHoursFunction('[Вчора '),
-            nextWeek: processHoursFunction('[У] dddd ['),
-            lastWeek: function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                case 5:
-                case 6:
-                    return processHoursFunction('[Минулої] dddd [').call(this);
-                case 1:
-                case 2:
-                case 4:
-                    return processHoursFunction('[Минулого] dddd [').call(this);
-                }
-            },
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "за %s",
-            past : "%s тому",
-            s : "декілька секунд",
-            m : relativeTimeWithPlural,
-            mm : relativeTimeWithPlural,
-            h : "годину",
-            hh : relativeTimeWithPlural,
-            d : "день",
-            dd : relativeTimeWithPlural,
-            M : "місяць",
-            MM : relativeTimeWithPlural,
-            y : "рік",
-            yy : relativeTimeWithPlural
-        },
-
-        // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
-
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return "ночі";
-            } else if (hour < 12) {
-                return "ранку";
-            } else if (hour < 17) {
-                return "дня";
-            } else {
-                return "вечора";
-            }
-        },
-
-        ordinal: function (number, period) {
-            switch (period) {
-            case 'M':
-            case 'd':
-            case 'DDD':
-            case 'w':
-            case 'W':
-                return number + '-й';
-            case 'D':
-                return number + '-го';
-            default:
-                return number;
-            }
-        },
-
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/uz.js b/resources/lib/moment/lang/uz.js
deleted file mode 100644 (file)
index a5b06fa..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// moment.js language configuration
-// language : uzbek
-// author : Sardor Muminov : https://github.com/muminoff
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('uz', {
-        months : "январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),
-        monthsShort : "янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"),
-        weekdays : "Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба".split("_"),
-        weekdaysShort : "Якш_Душ_Сеш_Чор_Пай_Жум_Шан".split("_"),
-        weekdaysMin : "Як_Ду_Се_Чо_Па_Жу_Ша".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "D MMMM YYYY, dddd LT"
-        },
-        calendar : {
-            sameDay : '[Бугун соат] LT [да]',
-            nextDay : '[Эртага] LT [да]',
-            nextWeek : 'dddd [куни соат] LT [да]',
-            lastDay : '[Кеча соат] LT [да]',
-            lastWeek : '[Утган] dddd [куни соат] LT [да]',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "Якин %s ичида",
-            past : "Бир неча %s олдин",
-            s : "фурсат",
-            m : "бир дакика",
-            mm : "%d дакика",
-            h : "бир соат",
-            hh : "%d соат",
-            d : "бир кун",
-            dd : "%d кун",
-            M : "бир ой",
-            MM : "%d ой",
-            y : "бир йил",
-            yy : "%d йил"
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/vi.js b/resources/lib/moment/lang/vi.js
deleted file mode 100644 (file)
index 94890b0..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-// moment.js language configuration
-// language : vietnamese (vi)
-// author : Bang Nguyen : https://github.com/bangnk
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('vi', {
-        months : "tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12".split("_"),
-        monthsShort : "Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12".split("_"),
-        weekdays : "chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy".split("_"),
-        weekdaysShort : "CN_T2_T3_T4_T5_T6_T7".split("_"),
-        weekdaysMin : "CN_T2_T3_T4_T5_T6_T7".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM [năm] YYYY",
-            LLL : "D MMMM [năm] YYYY LT",
-            LLLL : "dddd, D MMMM [năm] YYYY LT",
-            l : "DD/M/YYYY",
-            ll : "D MMM YYYY",
-            lll : "D MMM YYYY LT",
-            llll : "ddd, D MMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[Hôm nay lúc] LT",
-            nextDay: '[Ngày mai lúc] LT',
-            nextWeek: 'dddd [tuần tới lúc] LT',
-            lastDay: '[Hôm qua lúc] LT',
-            lastWeek: 'dddd [tuần rồi lúc] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "%s tới",
-            past : "%s trước",
-            s : "vài giây",
-            m : "một phút",
-            mm : "%d phút",
-            h : "một giờ",
-            hh : "%d giờ",
-            d : "một ngày",
-            dd : "%d ngày",
-            M : "một tháng",
-            MM : "%d tháng",
-            y : "một năm",
-            yy : "%d năm"
-        },
-        ordinal : function (number) {
-            return number;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/zh-cn.js b/resources/lib/moment/lang/zh-cn.js
deleted file mode 100644 (file)
index 50a3ed9..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-// moment.js language configuration
-// language : chinese
-// author : suupic : https://github.com/suupic
-// author : Zeno Zeng : https://github.com/zenozeng
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('zh-cn', {
-        months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
-        monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
-        weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),
-        weekdaysShort : "周日_周一_周二_周三_周四_周五_周六".split("_"),
-        weekdaysMin : "日_一_二_三_四_五_六".split("_"),
-        longDateFormat : {
-            LT : "Ah点mm",
-            L : "YYYY-MM-DD",
-            LL : "YYYY年MMMD日",
-            LLL : "YYYY年MMMD日LT",
-            LLLL : "YYYY年MMMD日ddddLT",
-            l : "YYYY-MM-DD",
-            ll : "YYYY年MMMD日",
-            lll : "YYYY年MMMD日LT",
-            llll : "YYYY年MMMD日ddddLT"
-        },
-        meridiem : function (hour, minute, isLower) {
-            var hm = hour * 100 + minute;
-            if (hm < 600) {
-                return "凌晨";
-            } else if (hm < 900) {
-                return "早上";
-            } else if (hm < 1130) {
-                return "上午";
-            } else if (hm < 1230) {
-                return "中午";
-            } else if (hm < 1800) {
-                return "下午";
-            } else {
-                return "晚上";
-            }
-        },
-        calendar : {
-            sameDay : function () {
-                return this.minutes() === 0 ? "[今天]Ah[点整]" : "[今天]LT";
-            },
-            nextDay : function () {
-                return this.minutes() === 0 ? "[明天]Ah[点整]" : "[明天]LT";
-            },
-            lastDay : function () {
-                return this.minutes() === 0 ? "[昨天]Ah[点整]" : "[昨天]LT";
-            },
-            nextWeek : function () {
-                var startOfWeek, prefix;
-                startOfWeek = moment().startOf('week');
-                prefix = this.unix() - startOfWeek.unix() >= 7 * 24 * 3600 ? '[下]' : '[本]';
-                return this.minutes() === 0 ? prefix + "dddAh点整" : prefix + "dddAh点mm";
-            },
-            lastWeek : function () {
-                var startOfWeek, prefix;
-                startOfWeek = moment().startOf('week');
-                prefix = this.unix() < startOfWeek.unix()  ? '[上]' : '[本]';
-                return this.minutes() === 0 ? prefix + "dddAh点整" : prefix + "dddAh点mm";
-            },
-            sameElse : 'LL'
-        },
-        ordinal : function (number, period) {
-            switch (period) {
-            case "d":
-            case "D":
-            case "DDD":
-                return number + "日";
-            case "M":
-                return number + "月";
-            case "w":
-            case "W":
-                return number + "周";
-            default:
-                return number;
-            }
-        },
-        relativeTime : {
-            future : "%s内",
-            past : "%s前",
-            s : "几秒",
-            m : "1分钟",
-            mm : "%d分钟",
-            h : "1小时",
-            hh : "%d小时",
-            d : "1天",
-            dd : "%d天",
-            M : "1个月",
-            MM : "%d个月",
-            y : "1年",
-            yy : "%d年"
-        },
-        week : {
-            // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/lib/moment/lang/zh-tw.js b/resources/lib/moment/lang/zh-tw.js
deleted file mode 100644 (file)
index bbb0737..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-// moment.js language configuration
-// language : traditional chinese (zh-tw)
-// author : Ben : https://github.com/ben-lin
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('zh-tw', {
-        months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
-        monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
-        weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),
-        weekdaysShort : "週日_週一_週二_週三_週四_週五_週六".split("_"),
-        weekdaysMin : "日_一_二_三_四_五_六".split("_"),
-        longDateFormat : {
-            LT : "Ah點mm",
-            L : "YYYY年MMMD日",
-            LL : "YYYY年MMMD日",
-            LLL : "YYYY年MMMD日LT",
-            LLLL : "YYYY年MMMD日ddddLT",
-            l : "YYYY年MMMD日",
-            ll : "YYYY年MMMD日",
-            lll : "YYYY年MMMD日LT",
-            llll : "YYYY年MMMD日ddddLT"
-        },
-        meridiem : function (hour, minute, isLower) {
-            var hm = hour * 100 + minute;
-            if (hm < 900) {
-                return "早上";
-            } else if (hm < 1130) {
-                return "上午";
-            } else if (hm < 1230) {
-                return "中午";
-            } else if (hm < 1800) {
-                return "下午";
-            } else {
-                return "晚上";
-            }
-        },
-        calendar : {
-            sameDay : '[今天]LT',
-            nextDay : '[明天]LT',
-            nextWeek : '[下]ddddLT',
-            lastDay : '[昨天]LT',
-            lastWeek : '[上]ddddLT',
-            sameElse : 'L'
-        },
-        ordinal : function (number, period) {
-            switch (period) {
-            case "d" :
-            case "D" :
-            case "DDD" :
-                return number + "日";
-            case "M" :
-                return number + "月";
-            case "w" :
-            case "W" :
-                return number + "週";
-            default :
-                return number;
-            }
-        },
-        relativeTime : {
-            future : "%s內",
-            past : "%s前",
-            s : "幾秒",
-            m : "一分鐘",
-            mm : "%d分鐘",
-            h : "一小時",
-            hh : "%d小時",
-            d : "一天",
-            dd : "%d天",
-            M : "一個月",
-            MM : "%d個月",
-            y : "一年",
-            yy : "%d年"
-        }
-    });
-}));
diff --git a/resources/lib/moment/locale/af.js b/resources/lib/moment/locale/af.js
new file mode 100644 (file)
index 0000000..1b8c520
--- /dev/null
@@ -0,0 +1,65 @@
+// moment.js locale configuration
+// locale : afrikaans (af)
+// author : Werner Mollentze : https://github.com/wernerm
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('af', {
+        months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'),
+        weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'),
+        weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'),
+        weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'),
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 12) {
+                return isLower ? 'vm' : 'VM';
+            } else {
+                return isLower ? 'nm' : 'NM';
+            }
+        },
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : '[Vandag om] LT',
+            nextDay : '[Môre om] LT',
+            nextWeek : 'dddd [om] LT',
+            lastDay : '[Gister om] LT',
+            lastWeek : '[Laas] dddd [om] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'oor %s',
+            past : '%s gelede',
+            s : '\'n paar sekondes',
+            m : '\'n minuut',
+            mm : '%d minute',
+            h : '\'n uur',
+            hh : '%d ure',
+            d : '\'n dag',
+            dd : '%d dae',
+            M : '\'n maand',
+            MM : '%d maande',
+            y : '\'n jaar',
+            yy : '%d jaar'
+        },
+        ordinal : function (number) {
+            return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter
+        },
+        week : {
+            dow : 1, // Maandag is die eerste dag van die week.
+            doy : 4  // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ar-ma.js b/resources/lib/moment/locale/ar-ma.js
new file mode 100644 (file)
index 0000000..5b2095a
--- /dev/null
@@ -0,0 +1,56 @@
+// moment.js locale configuration
+// locale : Moroccan Arabic (ar-ma)
+// author : ElFadili Yassine : https://github.com/ElFadiliY
+// author : Abdel Said : https://github.com/abdelsaid
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('ar-ma', {
+        months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
+        monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
+        weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+        weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
+        weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[اليوم على الساعة] LT',
+            nextDay: '[غدا على الساعة] LT',
+            nextWeek: 'dddd [على الساعة] LT',
+            lastDay: '[أمس على الساعة] LT',
+            lastWeek: 'dddd [على الساعة] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'في %s',
+            past : 'منذ %s',
+            s : 'ثوان',
+            m : 'دقيقة',
+            mm : '%d دقائق',
+            h : 'ساعة',
+            hh : '%d ساعات',
+            d : 'يوم',
+            dd : '%d أيام',
+            M : 'شهر',
+            MM : '%d أشهر',
+            y : 'سنة',
+            yy : '%d سنوات'
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ar-sa.js b/resources/lib/moment/locale/ar-sa.js
new file mode 100644 (file)
index 0000000..f7867ea
--- /dev/null
@@ -0,0 +1,96 @@
+// moment.js locale configuration
+// locale : Arabic Saudi Arabia (ar-sa)
+// author : Suhail Alkowaileet : https://github.com/xsoh
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '١',
+        '2': '٢',
+        '3': '٣',
+        '4': '٤',
+        '5': '٥',
+        '6': '٦',
+        '7': '٧',
+        '8': '٨',
+        '9': '٩',
+        '0': '٠'
+    }, numberMap = {
+        '١': '1',
+        '٢': '2',
+        '٣': '3',
+        '٤': '4',
+        '٥': '5',
+        '٦': '6',
+        '٧': '7',
+        '٨': '8',
+        '٩': '9',
+        '٠': '0'
+    };
+
+    return moment.defineLocale('ar-sa', {
+        months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+        monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+        weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+        weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+        weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D MMMM YYYY LT'
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return 'ص';
+            } else {
+                return 'م';
+            }
+        },
+        calendar : {
+            sameDay: '[اليوم على الساعة] LT',
+            nextDay: '[غدا على الساعة] LT',
+            nextWeek: 'dddd [على الساعة] LT',
+            lastDay: '[أمس على الساعة] LT',
+            lastWeek: 'dddd [على الساعة] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'في %s',
+            past : 'منذ %s',
+            s : 'ثوان',
+            m : 'دقيقة',
+            mm : '%d دقائق',
+            h : 'ساعة',
+            hh : '%d ساعات',
+            d : 'يوم',
+            dd : '%d أيام',
+            M : 'شهر',
+            MM : '%d أشهر',
+            y : 'سنة',
+            yy : '%d سنوات'
+        },
+        preparse: function (string) {
+            return string.replace(/[۰-۹]/g, function (match) {
+                return numberMap[match];
+            }).replace(/،/g, ',');
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            }).replace(/,/g, '،');
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ar.js b/resources/lib/moment/locale/ar.js
new file mode 100644 (file)
index 0000000..1791a6b
--- /dev/null
@@ -0,0 +1,129 @@
+// moment.js locale configuration
+// Locale: Arabic (ar)
+// Author: Abdel Said: https://github.com/abdelsaid
+// Changes in months, weekdays: Ahmed Elkhatib
+// Native plural forms: forabi https://github.com/forabi
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '١',
+        '2': '٢',
+        '3': '٣',
+        '4': '٤',
+        '5': '٥',
+        '6': '٦',
+        '7': '٧',
+        '8': '٨',
+        '9': '٩',
+        '0': '٠'
+    }, numberMap = {
+        '١': '1',
+        '٢': '2',
+        '٣': '3',
+        '٤': '4',
+        '٥': '5',
+        '٦': '6',
+        '٧': '7',
+        '٨': '8',
+        '٩': '9',
+        '٠': '0'
+    }, pluralForm = function (n) {
+        return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
+    }, plurals = {
+        s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
+        m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
+        h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
+        d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
+        M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
+        y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
+    }, pluralize = function (u) {
+        return function (number, withoutSuffix, string, isFuture) {
+            var f = pluralForm(number),
+                str = plurals[u][pluralForm(number)];
+            if (f === 2) {
+                str = str[withoutSuffix ? 0 : 1];
+            }
+            return str.replace(/%d/i, number);
+        };
+    }, months = [
+        'كانون الثاني يناير',
+        'شباط فبراير',
+        'آذار مارس',
+        'نيسان أبريل',
+        'أيار مايو',
+        'حزيران يونيو',
+        'تموز يوليو',
+        'آب أغسطس',
+        'أيلول سبتمبر',
+        'تشرين الأول أكتوبر',
+        'تشرين الثاني نوفمبر',
+        'كانون الأول ديسمبر'
+    ];
+
+    return moment.defineLocale('ar', {
+        months : months,
+        monthsShort : months,
+        weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+        weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+        weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D MMMM YYYY LT'
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return 'ص';
+            } else {
+                return 'م';
+            }
+        },
+        calendar : {
+            sameDay: '[اليوم عند الساعة] LT',
+            nextDay: '[غدًا عند الساعة] LT',
+            nextWeek: 'dddd [عند الساعة] LT',
+            lastDay: '[أمس عند الساعة] LT',
+            lastWeek: 'dddd [عند الساعة] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'بعد %s',
+            past : 'منذ %s',
+            s : pluralize('s'),
+            m : pluralize('m'),
+            mm : pluralize('m'),
+            h : pluralize('h'),
+            hh : pluralize('h'),
+            d : pluralize('d'),
+            dd : pluralize('d'),
+            M : pluralize('M'),
+            MM : pluralize('M'),
+            y : pluralize('y'),
+            yy : pluralize('y')
+        },
+        preparse: function (string) {
+            return string.replace(/[۰-۹]/g, function (match) {
+                return numberMap[match];
+            }).replace(/،/g, ',');
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            }).replace(/,/g, '،');
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/az.js b/resources/lib/moment/locale/az.js
new file mode 100644 (file)
index 0000000..e82f6e1
--- /dev/null
@@ -0,0 +1,101 @@
+// moment.js locale configuration
+// locale : azerbaijani (az)
+// author : topchiyev : https://github.com/topchiyev
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var suffixes = {
+        1: '-inci',
+        5: '-inci',
+        8: '-inci',
+        70: '-inci',
+        80: '-inci',
+
+        2: '-nci',
+        7: '-nci',
+        20: '-nci',
+        50: '-nci',
+
+        3: '-üncü',
+        4: '-üncü',
+        100: '-üncü',
+
+        6: '-ncı',
+
+        9: '-uncu',
+        10: '-uncu',
+        30: '-uncu',
+
+        60: '-ıncı',
+        90: '-ıncı'
+    };
+    return moment.defineLocale('az', {
+        months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'),
+        monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'),
+        weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'),
+        weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'),
+        weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : '[bugün saat] LT',
+            nextDay : '[sabah saat] LT',
+            nextWeek : '[gələn həftə] dddd [saat] LT',
+            lastDay : '[dünən] LT',
+            lastWeek : '[keçən həftə] dddd [saat] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s sonra',
+            past : '%s əvvəl',
+            s : 'birneçə saniyyə',
+            m : 'bir dəqiqə',
+            mm : '%d dəqiqə',
+            h : 'bir saat',
+            hh : '%d saat',
+            d : 'bir gün',
+            dd : '%d gün',
+            M : 'bir ay',
+            MM : '%d ay',
+            y : 'bir il',
+            yy : '%d il'
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'gecə';
+            } else if (hour < 12) {
+                return 'səhər';
+            } else if (hour < 17) {
+                return 'gündüz';
+            } else {
+                return 'axşam';
+            }
+        },
+        ordinal : function (number) {
+            if (number === 0) {  // special case for zero
+                return number + '-ıncı';
+            }
+            var a = number % 10,
+                b = number % 100 - a,
+                c = number >= 100 ? 100 : null;
+
+            return number + (suffixes[a] || suffixes[b] || suffixes[c]);
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/be.js b/resources/lib/moment/locale/be.js
new file mode 100644 (file)
index 0000000..fe3186a
--- /dev/null
@@ -0,0 +1,150 @@
+// moment.js locale configuration
+// locale : belarusian (be)
+// author : Dmitry Demidov : https://github.com/demidov91
+// author: Praleska: http://praleska.pro/
+// Author : Menelion Elensúle : https://github.com/Oire
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function plural(word, num) {
+        var forms = word.split('_');
+        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+    }
+
+    function relativeTimeWithPlural(number, withoutSuffix, key) {
+        var format = {
+            'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін',
+            'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін',
+            'dd': 'дзень_дні_дзён',
+            'MM': 'месяц_месяцы_месяцаў',
+            'yy': 'год_гады_гадоў'
+        };
+        if (key === 'm') {
+            return withoutSuffix ? 'хвіліна' : 'хвіліну';
+        }
+        else if (key === 'h') {
+            return withoutSuffix ? 'гадзіна' : 'гадзіну';
+        }
+        else {
+            return number + ' ' + plural(format[key], +number);
+        }
+    }
+
+    function monthsCaseReplace(m, format) {
+        var months = {
+            'nominative': 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_'),
+            'accusative': 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_')
+        },
+
+        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return months[nounCase][m.month()];
+    }
+
+    function weekdaysCaseReplace(m, format) {
+        var weekdays = {
+            'nominative': 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'),
+            'accusative': 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_')
+        },
+
+        nounCase = (/\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return weekdays[nounCase][m.day()];
+    }
+
+    return moment.defineLocale('be', {
+        months : monthsCaseReplace,
+        monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'),
+        weekdays : weekdaysCaseReplace,
+        weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
+        weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY г.',
+            LLL : 'D MMMM YYYY г., LT',
+            LLLL : 'dddd, D MMMM YYYY г., LT'
+        },
+        calendar : {
+            sameDay: '[Сёння ў] LT',
+            nextDay: '[Заўтра ў] LT',
+            lastDay: '[Учора ў] LT',
+            nextWeek: function () {
+                return '[У] dddd [ў] LT';
+            },
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 5:
+                case 6:
+                    return '[У мінулую] dddd [ў] LT';
+                case 1:
+                case 2:
+                case 4:
+                    return '[У мінулы] dddd [ў] LT';
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'праз %s',
+            past : '%s таму',
+            s : 'некалькі секунд',
+            m : relativeTimeWithPlural,
+            mm : relativeTimeWithPlural,
+            h : relativeTimeWithPlural,
+            hh : relativeTimeWithPlural,
+            d : 'дзень',
+            dd : relativeTimeWithPlural,
+            M : 'месяц',
+            MM : relativeTimeWithPlural,
+            y : 'год',
+            yy : relativeTimeWithPlural
+        },
+
+
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'ночы';
+            } else if (hour < 12) {
+                return 'раніцы';
+            } else if (hour < 17) {
+                return 'дня';
+            } else {
+                return 'вечара';
+            }
+        },
+
+        ordinal: function (number, period) {
+            switch (period) {
+            case 'M':
+            case 'd':
+            case 'DDD':
+            case 'w':
+            case 'W':
+                return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы';
+            case 'D':
+                return number + '-га';
+            default:
+                return number;
+            }
+        },
+
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/bg.js b/resources/lib/moment/locale/bg.js
new file mode 100644 (file)
index 0000000..41b1e3a
--- /dev/null
@@ -0,0 +1,86 @@
+// moment.js locale configuration
+// locale : bulgarian (bg)
+// author : Krasen Borisov : https://github.com/kraz
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('bg', {
+        months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
+        monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
+        weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
+        weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
+        weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            L : 'D.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : '[Днес в] LT',
+            nextDay : '[Утре в] LT',
+            nextWeek : 'dddd [в] LT',
+            lastDay : '[Вчера в] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 6:
+                    return '[В изминалата] dddd [в] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[В изминалия] dddd [в] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'след %s',
+            past : 'преди %s',
+            s : 'няколко секунди',
+            m : 'минута',
+            mm : '%d минути',
+            h : 'час',
+            hh : '%d часа',
+            d : 'ден',
+            dd : '%d дни',
+            M : 'месец',
+            MM : '%d месеца',
+            y : 'година',
+            yy : '%d години'
+        },
+        ordinal : function (number) {
+            var lastDigit = number % 10,
+                last2Digits = number % 100;
+            if (number === 0) {
+                return number + '-ев';
+            } else if (last2Digits === 0) {
+                return number + '-ен';
+            } else if (last2Digits > 10 && last2Digits < 20) {
+                return number + '-ти';
+            } else if (lastDigit === 1) {
+                return number + '-ви';
+            } else if (lastDigit === 2) {
+                return number + '-ри';
+            } else if (lastDigit === 7 || lastDigit === 8) {
+                return number + '-ми';
+            } else {
+                return number + '-ти';
+            }
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/bn.js b/resources/lib/moment/locale/bn.js
new file mode 100644 (file)
index 0000000..7e8ccfd
--- /dev/null
@@ -0,0 +1,106 @@
+// moment.js locale configuration
+// locale : Bengali (bn)
+// author : Kaushik Gandhi : https://github.com/kaushikgandhi
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '১',
+        '2': '২',
+        '3': '৩',
+        '4': '৪',
+        '5': '৫',
+        '6': '৬',
+        '7': '৭',
+        '8': '৮',
+        '9': '৯',
+        '0': '০'
+    },
+    numberMap = {
+        '১': '1',
+        '২': '2',
+        '৩': '3',
+        '৪': '4',
+        '৫': '5',
+        '৬': '6',
+        '৭': '7',
+        '৮': '8',
+        '৯': '9',
+        '০': '0'
+    };
+
+    return moment.defineLocale('bn', {
+        months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'),
+        monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split('_'),
+        weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রুবার_শনিবার'.split('_'),
+        weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্রু_শনি'.split('_'),
+        weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'),
+        longDateFormat : {
+            LT : 'A h:mm সময়',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, LT',
+            LLLL : 'dddd, D MMMM YYYY, LT'
+        },
+        calendar : {
+            sameDay : '[আজ] LT',
+            nextDay : '[আগামীকাল] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[গতকাল] LT',
+            lastWeek : '[গত] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s পরে',
+            past : '%s আগে',
+            s : 'কএক সেকেন্ড',
+            m : 'এক মিনিট',
+            mm : '%d মিনিট',
+            h : 'এক ঘন্টা',
+            hh : '%d ঘন্টা',
+            d : 'এক দিন',
+            dd : '%d দিন',
+            M : 'এক মাস',
+            MM : '%d মাস',
+            y : 'এক বছর',
+            yy : '%d বছর'
+        },
+        preparse: function (string) {
+            return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) {
+                return numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            });
+        },
+        //Bengali is a vast language its spoken
+        //in different forms in various parts of the world.
+        //I have just generalized with most common one used
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'রাত';
+            } else if (hour < 10) {
+                return 'শকাল';
+            } else if (hour < 17) {
+                return 'দুপুর';
+            } else if (hour < 20) {
+                return 'বিকেল';
+            } else {
+                return 'রাত';
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/bo.js b/resources/lib/moment/locale/bo.js
new file mode 100644 (file)
index 0000000..0d44e47
--- /dev/null
@@ -0,0 +1,103 @@
+// moment.js locale configuration
+// locale : tibetan (bo)
+// author : Thupten N. Chakrishar : https://github.com/vajradog
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '༡',
+        '2': '༢',
+        '3': '༣',
+        '4': '༤',
+        '5': '༥',
+        '6': '༦',
+        '7': '༧',
+        '8': '༨',
+        '9': '༩',
+        '0': '༠'
+    },
+    numberMap = {
+        '༡': '1',
+        '༢': '2',
+        '༣': '3',
+        '༤': '4',
+        '༥': '5',
+        '༦': '6',
+        '༧': '7',
+        '༨': '8',
+        '༩': '9',
+        '༠': '0'
+    };
+
+    return moment.defineLocale('bo', {
+        months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
+        monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
+        weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'),
+        weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
+        weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
+        longDateFormat : {
+            LT : 'A h:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, LT',
+            LLLL : 'dddd, D MMMM YYYY, LT'
+        },
+        calendar : {
+            sameDay : '[དི་རིང] LT',
+            nextDay : '[སང་ཉིན] LT',
+            nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT',
+            lastDay : '[ཁ་སང] LT',
+            lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s ལ་',
+            past : '%s སྔན་ལ',
+            s : 'ལམ་སང',
+            m : 'སྐར་མ་གཅིག',
+            mm : '%d སྐར་མ',
+            h : 'ཆུ་ཚོད་གཅིག',
+            hh : '%d ཆུ་ཚོད',
+            d : 'ཉིན་གཅིག',
+            dd : '%d ཉིན་',
+            M : 'ཟླ་བ་གཅིག',
+            MM : '%d ཟླ་བ',
+            y : 'ལོ་གཅིག',
+            yy : '%d ལོ'
+        },
+        preparse: function (string) {
+            return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) {
+                return numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            });
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'མཚན་མོ';
+            } else if (hour < 10) {
+                return 'ཞོགས་ཀས';
+            } else if (hour < 17) {
+                return 'ཉིན་གུང';
+            } else if (hour < 20) {
+                return 'དགོང་དག';
+            } else {
+                return 'མཚན་མོ';
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/br.js b/resources/lib/moment/locale/br.js
new file mode 100644 (file)
index 0000000..a4f1491
--- /dev/null
@@ -0,0 +1,107 @@
+// moment.js locale configuration
+// locale : breton (br)
+// author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function relativeTimeWithMutation(number, withoutSuffix, key) {
+        var format = {
+            'mm': 'munutenn',
+            'MM': 'miz',
+            'dd': 'devezh'
+        };
+        return number + ' ' + mutation(format[key], number);
+    }
+
+    function specialMutationForYears(number) {
+        switch (lastNumber(number)) {
+        case 1:
+        case 3:
+        case 4:
+        case 5:
+        case 9:
+            return number + ' bloaz';
+        default:
+            return number + ' vloaz';
+        }
+    }
+
+    function lastNumber(number) {
+        if (number > 9) {
+            return lastNumber(number % 10);
+        }
+        return number;
+    }
+
+    function mutation(text, number) {
+        if (number === 2) {
+            return softMutation(text);
+        }
+        return text;
+    }
+
+    function softMutation(text) {
+        var mutationTable = {
+            'm': 'v',
+            'b': 'v',
+            'd': 'z'
+        };
+        if (mutationTable[text.charAt(0)] === undefined) {
+            return text;
+        }
+        return mutationTable[text.charAt(0)] + text.substring(1);
+    }
+
+    return moment.defineLocale('br', {
+        months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'),
+        monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'),
+        weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'),
+        weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'),
+        weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'h[e]mm A',
+            L : 'DD/MM/YYYY',
+            LL : 'D [a viz] MMMM YYYY',
+            LLL : 'D [a viz] MMMM YYYY LT',
+            LLLL : 'dddd, D [a viz] MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : '[Hiziv da] LT',
+            nextDay : '[Warc\'hoazh da] LT',
+            nextWeek : 'dddd [da] LT',
+            lastDay : '[Dec\'h da] LT',
+            lastWeek : 'dddd [paset da] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'a-benn %s',
+            past : '%s \'zo',
+            s : 'un nebeud segondennoù',
+            m : 'ur vunutenn',
+            mm : relativeTimeWithMutation,
+            h : 'un eur',
+            hh : '%d eur',
+            d : 'un devezh',
+            dd : relativeTimeWithMutation,
+            M : 'ur miz',
+            MM : relativeTimeWithMutation,
+            y : 'ur bloaz',
+            yy : specialMutationForYears
+        },
+        ordinal : function (number) {
+            var output = (number === 1) ? 'añ' : 'vet';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/bs.js b/resources/lib/moment/locale/bs.js
new file mode 100644 (file)
index 0000000..b9a5851
--- /dev/null
@@ -0,0 +1,138 @@
+// moment.js locale configuration
+// locale : bosnian (bs)
+// author : Nedim Cholich : https://github.com/frontyard
+// based on (hr) translation by Bojan Marković
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function translate(number, withoutSuffix, key) {
+        var result = number + ' ';
+        switch (key) {
+        case 'm':
+            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
+        case 'mm':
+            if (number === 1) {
+                result += 'minuta';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'minute';
+            } else {
+                result += 'minuta';
+            }
+            return result;
+        case 'h':
+            return withoutSuffix ? 'jedan sat' : 'jednog sata';
+        case 'hh':
+            if (number === 1) {
+                result += 'sat';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'sata';
+            } else {
+                result += 'sati';
+            }
+            return result;
+        case 'dd':
+            if (number === 1) {
+                result += 'dan';
+            } else {
+                result += 'dana';
+            }
+            return result;
+        case 'MM':
+            if (number === 1) {
+                result += 'mjesec';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'mjeseca';
+            } else {
+                result += 'mjeseci';
+            }
+            return result;
+        case 'yy':
+            if (number === 1) {
+                result += 'godina';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'godine';
+            } else {
+                result += 'godina';
+            }
+            return result;
+        }
+    }
+
+    return moment.defineLocale('bs', {
+        months : 'januar_februar_mart_april_maj_juni_juli_avgust_septembar_oktobar_novembar_decembar'.split('_'),
+        monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'),
+        weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
+        weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
+        weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            L : 'DD. MM. YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY LT',
+            LLLL : 'dddd, D. MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay  : '[danas u] LT',
+            nextDay  : '[sutra u] LT',
+
+            nextWeek : function () {
+                switch (this.day()) {
+                case 0:
+                    return '[u] [nedjelju] [u] LT';
+                case 3:
+                    return '[u] [srijedu] [u] LT';
+                case 6:
+                    return '[u] [subotu] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[u] dddd [u] LT';
+                }
+            },
+            lastDay  : '[jučer u] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                    return '[prošlu] dddd [u] LT';
+                case 6:
+                    return '[prošle] [subote] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[prošli] dddd [u] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past   : 'prije %s',
+            s      : 'par sekundi',
+            m      : translate,
+            mm     : translate,
+            h      : translate,
+            hh     : translate,
+            d      : 'dan',
+            dd     : translate,
+            M      : 'mjesec',
+            MM     : translate,
+            y      : 'godinu',
+            yy     : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ca.js b/resources/lib/moment/locale/ca.js
new file mode 100644 (file)
index 0000000..fd41ff5
--- /dev/null
@@ -0,0 +1,66 @@
+// moment.js locale configuration
+// locale : catalan (ca)
+// author : Juan G. Hurtado : https://github.com/juanghurtado
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('ca', {
+        months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'),
+        monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'),
+        weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'),
+        weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'),
+        weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : function () {
+                return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            nextDay : function () {
+                return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            nextWeek : function () {
+                return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            lastDay : function () {
+                return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            lastWeek : function () {
+                return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'en %s',
+            past : 'fa %s',
+            s : 'uns segons',
+            m : 'un minut',
+            mm : '%d minuts',
+            h : 'una hora',
+            hh : '%d hores',
+            d : 'un dia',
+            dd : '%d dies',
+            M : 'un mes',
+            MM : '%d mesos',
+            y : 'un any',
+            yy : '%d anys'
+        },
+        ordinal : '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/cs.js b/resources/lib/moment/locale/cs.js
new file mode 100644 (file)
index 0000000..87dec55
--- /dev/null
@@ -0,0 +1,155 @@
+// moment.js locale configuration
+// locale : czech (cs)
+// author : petrbela : https://github.com/petrbela
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'),
+        monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_');
+
+    function plural(n) {
+        return (n > 1) && (n < 5) && (~~(n / 10) !== 1);
+    }
+
+    function translate(number, withoutSuffix, key, isFuture) {
+        var result = number + ' ';
+        switch (key) {
+        case 's':  // a few seconds / in a few seconds / a few seconds ago
+            return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami';
+        case 'm':  // a minute / in a minute / a minute ago
+            return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou');
+        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'minuty' : 'minut');
+            } else {
+                return result + 'minutami';
+            }
+            break;
+        case 'h':  // an hour / in an hour / an hour ago
+            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
+        case 'hh': // 9 hours / in 9 hours / 9 hours ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'hodiny' : 'hodin');
+            } else {
+                return result + 'hodinami';
+            }
+            break;
+        case 'd':  // a day / in a day / a day ago
+            return (withoutSuffix || isFuture) ? 'den' : 'dnem';
+        case 'dd': // 9 days / in 9 days / 9 days ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'dny' : 'dní');
+            } else {
+                return result + 'dny';
+            }
+            break;
+        case 'M':  // a month / in a month / a month ago
+            return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem';
+        case 'MM': // 9 months / in 9 months / 9 months ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'měsíce' : 'měsíců');
+            } else {
+                return result + 'měsíci';
+            }
+            break;
+        case 'y':  // a year / in a year / a year ago
+            return (withoutSuffix || isFuture) ? 'rok' : 'rokem';
+        case 'yy': // 9 years / in 9 years / 9 years ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'roky' : 'let');
+            } else {
+                return result + 'lety';
+            }
+            break;
+        }
+    }
+
+    return moment.defineLocale('cs', {
+        months : months,
+        monthsShort : monthsShort,
+        monthsParse : (function (months, monthsShort) {
+            var i, _monthsParse = [];
+            for (i = 0; i < 12; i++) {
+                // use custom parser to solve problem with July (červenec)
+                _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
+            }
+            return _monthsParse;
+        }(months, monthsShort)),
+        weekdays : 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'),
+        weekdaysShort : 'ne_po_út_st_čt_pá_so'.split('_'),
+        weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'),
+        longDateFormat : {
+            LT: 'H:mm',
+            L : 'DD. MM. YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY LT',
+            LLLL : 'dddd D. MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[dnes v] LT',
+            nextDay: '[zítra v] LT',
+            nextWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[v neděli v] LT';
+                case 1:
+                case 2:
+                    return '[v] dddd [v] LT';
+                case 3:
+                    return '[ve středu v] LT';
+                case 4:
+                    return '[ve čtvrtek v] LT';
+                case 5:
+                    return '[v pátek v] LT';
+                case 6:
+                    return '[v sobotu v] LT';
+                }
+            },
+            lastDay: '[včera v] LT',
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[minulou neděli v] LT';
+                case 1:
+                case 2:
+                    return '[minulé] dddd [v] LT';
+                case 3:
+                    return '[minulou středu v] LT';
+                case 4:
+                case 5:
+                    return '[minulý] dddd [v] LT';
+                case 6:
+                    return '[minulou sobotu v] LT';
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past : 'před %s',
+            s : translate,
+            m : translate,
+            mm : translate,
+            h : translate,
+            hh : translate,
+            d : translate,
+            dd : translate,
+            M : translate,
+            MM : translate,
+            y : translate,
+            yy : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/cv.js b/resources/lib/moment/locale/cv.js
new file mode 100644 (file)
index 0000000..138b6c1
--- /dev/null
@@ -0,0 +1,59 @@
+// moment.js locale configuration
+// locale : chuvash (cv)
+// author : Anatoly Mironov : https://github.com/mirontoli
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('cv', {
+        months : 'кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав'.split('_'),
+        monthsShort : 'кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш'.split('_'),
+        weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун'.split('_'),
+        weekdaysShort : 'выр_тун_ытл_юн_кĕç_эрн_шăм'.split('_'),
+        weekdaysMin : 'вр_тн_ыт_юн_кç_эр_шм'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD-MM-YYYY',
+            LL : 'YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ]',
+            LLL : 'YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT',
+            LLLL : 'dddd, YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT'
+        },
+        calendar : {
+            sameDay: '[Паян] LT [сехетре]',
+            nextDay: '[Ыран] LT [сехетре]',
+            lastDay: '[Ĕнер] LT [сехетре]',
+            nextWeek: '[Çитес] dddd LT [сехетре]',
+            lastWeek: '[Иртнĕ] dddd LT [сехетре]',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : function (output) {
+                var affix = /сехет$/i.exec(output) ? 'рен' : /çул$/i.exec(output) ? 'тан' : 'ран';
+                return output + affix;
+            },
+            past : '%s каялла',
+            s : 'пĕр-ик çеккунт',
+            m : 'пĕр минут',
+            mm : '%d минут',
+            h : 'пĕр сехет',
+            hh : '%d сехет',
+            d : 'пĕр кун',
+            dd : '%d кун',
+            M : 'пĕр уйăх',
+            MM : '%d уйăх',
+            y : 'пĕр çул',
+            yy : '%d çул'
+        },
+        ordinal : '%d-мĕш',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/cy.js b/resources/lib/moment/locale/cy.js
new file mode 100644 (file)
index 0000000..65fb356
--- /dev/null
@@ -0,0 +1,77 @@
+// moment.js locale configuration
+// locale : Welsh (cy)
+// author : Robert Allen
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('cy', {
+        months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'),
+        monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'),
+        weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'),
+        weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'),
+        weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'),
+        // time formats are the same as en-gb
+        longDateFormat: {
+            LT: 'HH:mm',
+            L: 'DD/MM/YYYY',
+            LL: 'D MMMM YYYY',
+            LLL: 'D MMMM YYYY LT',
+            LLLL: 'dddd, D MMMM YYYY LT'
+        },
+        calendar: {
+            sameDay: '[Heddiw am] LT',
+            nextDay: '[Yfory am] LT',
+            nextWeek: 'dddd [am] LT',
+            lastDay: '[Ddoe am] LT',
+            lastWeek: 'dddd [diwethaf am] LT',
+            sameElse: 'L'
+        },
+        relativeTime: {
+            future: 'mewn %s',
+            past: '%s yn ôl',
+            s: 'ychydig eiliadau',
+            m: 'munud',
+            mm: '%d munud',
+            h: 'awr',
+            hh: '%d awr',
+            d: 'diwrnod',
+            dd: '%d diwrnod',
+            M: 'mis',
+            MM: '%d mis',
+            y: 'blwyddyn',
+            yy: '%d flynedd'
+        },
+        // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
+        ordinal: function (number) {
+            var b = number,
+                output = '',
+                lookup = [
+                    '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
+                    'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed
+                ];
+
+            if (b > 20) {
+                if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) {
+                    output = 'fed'; // not 30ain, 70ain or 90ain
+                } else {
+                    output = 'ain';
+                }
+            } else if (b > 0) {
+                output = lookup[b];
+            }
+
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/da.js b/resources/lib/moment/locale/da.js
new file mode 100644 (file)
index 0000000..5e9ef96
--- /dev/null
@@ -0,0 +1,56 @@
+// moment.js locale configuration
+// locale : danish (da)
+// author : Ulrik Nielsen : https://github.com/mrbase
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('da', {
+        months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
+        weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
+        weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'),
+        weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY LT',
+            LLLL : 'dddd [d.] D. MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : '[I dag kl.] LT',
+            nextDay : '[I morgen kl.] LT',
+            nextWeek : 'dddd [kl.] LT',
+            lastDay : '[I går kl.] LT',
+            lastWeek : '[sidste] dddd [kl] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'om %s',
+            past : '%s siden',
+            s : 'få sekunder',
+            m : 'et minut',
+            mm : '%d minutter',
+            h : 'en time',
+            hh : '%d timer',
+            d : 'en dag',
+            dd : '%d dage',
+            M : 'en måned',
+            MM : '%d måneder',
+            y : 'et år',
+            yy : '%d år'
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/de-at.js b/resources/lib/moment/locale/de-at.js
new file mode 100644 (file)
index 0000000..ff715f8
--- /dev/null
@@ -0,0 +1,72 @@
+// moment.js locale configuration
+// locale : austrian german (de-at)
+// author : lluchs : https://github.com/lluchs
+// author: Menelion Elensúle: https://github.com/Oire
+// author : Martin Groller : https://github.com/MadMG
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var format = {
+            'm': ['eine Minute', 'einer Minute'],
+            'h': ['eine Stunde', 'einer Stunde'],
+            'd': ['ein Tag', 'einem Tag'],
+            'dd': [number + ' Tage', number + ' Tagen'],
+            'M': ['ein Monat', 'einem Monat'],
+            'MM': [number + ' Monate', number + ' Monaten'],
+            'y': ['ein Jahr', 'einem Jahr'],
+            'yy': [number + ' Jahre', number + ' Jahren']
+        };
+        return withoutSuffix ? format[key][0] : format[key][1];
+    }
+
+    return moment.defineLocale('de-at', {
+        months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+        monthsShort : 'Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
+        weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
+        weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
+        weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
+        longDateFormat : {
+            LT: 'HH:mm [Uhr]',
+            L : 'DD.MM.YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY LT',
+            LLLL : 'dddd, D. MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[Heute um] LT',
+            sameElse: 'L',
+            nextDay: '[Morgen um] LT',
+            nextWeek: 'dddd [um] LT',
+            lastDay: '[Gestern um] LT',
+            lastWeek: '[letzten] dddd [um] LT'
+        },
+        relativeTime : {
+            future : 'in %s',
+            past : 'vor %s',
+            s : 'ein paar Sekunden',
+            m : processRelativeTime,
+            mm : '%d Minuten',
+            h : processRelativeTime,
+            hh : '%d Stunden',
+            d : processRelativeTime,
+            dd : processRelativeTime,
+            M : processRelativeTime,
+            MM : processRelativeTime,
+            y : processRelativeTime,
+            yy : processRelativeTime
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/de.js b/resources/lib/moment/locale/de.js
new file mode 100644 (file)
index 0000000..11ab9ac
--- /dev/null
@@ -0,0 +1,71 @@
+// moment.js locale configuration
+// locale : german (de)
+// author : lluchs : https://github.com/lluchs
+// author: Menelion Elensúle: https://github.com/Oire
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var format = {
+            'm': ['eine Minute', 'einer Minute'],
+            'h': ['eine Stunde', 'einer Stunde'],
+            'd': ['ein Tag', 'einem Tag'],
+            'dd': [number + ' Tage', number + ' Tagen'],
+            'M': ['ein Monat', 'einem Monat'],
+            'MM': [number + ' Monate', number + ' Monaten'],
+            'y': ['ein Jahr', 'einem Jahr'],
+            'yy': [number + ' Jahre', number + ' Jahren']
+        };
+        return withoutSuffix ? format[key][0] : format[key][1];
+    }
+
+    return moment.defineLocale('de', {
+        months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+        monthsShort : 'Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
+        weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
+        weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
+        weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
+        longDateFormat : {
+            LT: 'HH:mm [Uhr]',
+            L : 'DD.MM.YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY LT',
+            LLLL : 'dddd, D. MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[Heute um] LT',
+            sameElse: 'L',
+            nextDay: '[Morgen um] LT',
+            nextWeek: 'dddd [um] LT',
+            lastDay: '[Gestern um] LT',
+            lastWeek: '[letzten] dddd [um] LT'
+        },
+        relativeTime : {
+            future : 'in %s',
+            past : 'vor %s',
+            s : 'ein paar Sekunden',
+            m : processRelativeTime,
+            mm : '%d Minuten',
+            h : processRelativeTime,
+            hh : '%d Stunden',
+            d : processRelativeTime,
+            dd : processRelativeTime,
+            M : processRelativeTime,
+            MM : processRelativeTime,
+            y : processRelativeTime,
+            yy : processRelativeTime
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/el.js b/resources/lib/moment/locale/el.js
new file mode 100644 (file)
index 0000000..eb8eb1a
--- /dev/null
@@ -0,0 +1,94 @@
+// moment.js locale configuration
+// locale : modern greek (el)
+// author : Aggelos Karalias : https://github.com/mehiel
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('el', {
+        monthsNominativeEl : 'Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος'.split('_'),
+        monthsGenitiveEl : 'Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου'.split('_'),
+        months : function (momentToFormat, format) {
+            if (/D/.test(format.substring(0, format.indexOf('MMMM')))) { // if there is a day number before 'MMMM'
+                return this._monthsGenitiveEl[momentToFormat.month()];
+            } else {
+                return this._monthsNominativeEl[momentToFormat.month()];
+            }
+        },
+        monthsShort : 'Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ'.split('_'),
+        weekdays : 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split('_'),
+        weekdaysShort : 'Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ'.split('_'),
+        weekdaysMin : 'Κυ_Δε_Τρ_Τε_Πε_Πα_Σα'.split('_'),
+        meridiem : function (hours, minutes, isLower) {
+            if (hours > 11) {
+                return isLower ? 'μμ' : 'ΜΜ';
+            } else {
+                return isLower ? 'πμ' : 'ΠΜ';
+            }
+        },
+        isPM : function (input) {
+            return ((input + '').toLowerCase()[0] === 'μ');
+        },
+        meridiemParse : /[ΠΜ]\.?Μ?\.?/i,
+        longDateFormat : {
+            LT : 'h:mm A',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        calendarEl : {
+            sameDay : '[Σήμερα {}] LT',
+            nextDay : '[Αύριο {}] LT',
+            nextWeek : 'dddd [{}] LT',
+            lastDay : '[Χθες {}] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                    case 6:
+                        return '[το προηγούμενο] dddd [{}] LT';
+                    default:
+                        return '[την προηγούμενη] dddd [{}] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        calendar : function (key, mom) {
+            var output = this._calendarEl[key],
+                hours = mom && mom.hours();
+
+            if (typeof output === 'function') {
+                output = output.apply(mom);
+            }
+
+            return output.replace('{}', (hours % 12 === 1 ? 'στη' : 'στις'));
+        },
+        relativeTime : {
+            future : 'σε %s',
+            past : '%s πριν',
+            s : 'δευτερόλεπτα',
+            m : 'ένα λεπτό',
+            mm : '%d λεπτά',
+            h : 'μία ώρα',
+            hh : '%d ώρες',
+            d : 'μία μέρα',
+            dd : '%d μέρες',
+            M : 'ένας μήνας',
+            MM : '%d μήνες',
+            y : 'ένας χρόνος',
+            yy : '%d χρόνια'
+        },
+        ordinal : function (number) {
+            return number + 'η';
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/en-au.js b/resources/lib/moment/locale/en-au.js
new file mode 100644 (file)
index 0000000..75ad34a
--- /dev/null
@@ -0,0 +1,62 @@
+// moment.js locale configuration
+// locale : australian english (en-au)
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('en-au', {
+        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'h:mm A',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[Last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'in %s',
+            past : '%s ago',
+            s : 'a few seconds',
+            m : 'a minute',
+            mm : '%d minutes',
+            h : 'an hour',
+            hh : '%d hours',
+            d : 'a day',
+            dd : '%d days',
+            M : 'a month',
+            MM : '%d months',
+            y : 'a year',
+            yy : '%d years'
+        },
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~(number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/en-ca.js b/resources/lib/moment/locale/en-ca.js
new file mode 100644 (file)
index 0000000..077dc8b
--- /dev/null
@@ -0,0 +1,59 @@
+// moment.js locale configuration
+// locale : canadian english (en-ca)
+// author : Jonathan Abourbih : https://github.com/jonbca
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('en-ca', {
+        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'h:mm A',
+            L : 'YYYY-MM-DD',
+            LL : 'D MMMM, YYYY',
+            LLL : 'D MMMM, YYYY LT',
+            LLLL : 'dddd, D MMMM, YYYY LT'
+        },
+        calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[Last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'in %s',
+            past : '%s ago',
+            s : 'a few seconds',
+            m : 'a minute',
+            mm : '%d minutes',
+            h : 'an hour',
+            hh : '%d hours',
+            d : 'a day',
+            dd : '%d days',
+            M : 'a month',
+            MM : '%d months',
+            y : 'a year',
+            yy : '%d years'
+        },
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~(number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/en-gb.js b/resources/lib/moment/locale/en-gb.js
new file mode 100644 (file)
index 0000000..4491d4a
--- /dev/null
@@ -0,0 +1,63 @@
+// moment.js locale configuration
+// locale : great britain english (en-gb)
+// author : Chris Gedrim : https://github.com/chrisgedrim
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('en-gb', {
+        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[Last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'in %s',
+            past : '%s ago',
+            s : 'a few seconds',
+            m : 'a minute',
+            mm : '%d minutes',
+            h : 'an hour',
+            hh : '%d hours',
+            d : 'a day',
+            dd : '%d days',
+            M : 'a month',
+            MM : '%d months',
+            y : 'a year',
+            yy : '%d years'
+        },
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~(number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/eo.js b/resources/lib/moment/locale/eo.js
new file mode 100644 (file)
index 0000000..735ed8e
--- /dev/null
@@ -0,0 +1,65 @@
+// moment.js locale configuration
+// locale : esperanto (eo)
+// author : Colin Dean : https://github.com/colindean
+// komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko.
+//          Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni!
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('eo', {
+        months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec'.split('_'),
+        weekdays : 'Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato'.split('_'),
+        weekdaysShort : 'Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab'.split('_'),
+        weekdaysMin : 'Di_Lu_Ma_Me_Ĵa_Ve_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'YYYY-MM-DD',
+            LL : 'D[-an de] MMMM, YYYY',
+            LLL : 'D[-an de] MMMM, YYYY LT',
+            LLLL : 'dddd, [la] D[-an de] MMMM, YYYY LT'
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours > 11) {
+                return isLower ? 'p.t.m.' : 'P.T.M.';
+            } else {
+                return isLower ? 'a.t.m.' : 'A.T.M.';
+            }
+        },
+        calendar : {
+            sameDay : '[Hodiaŭ je] LT',
+            nextDay : '[Morgaŭ je] LT',
+            nextWeek : 'dddd [je] LT',
+            lastDay : '[Hieraŭ je] LT',
+            lastWeek : '[pasinta] dddd [je] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'je %s',
+            past : 'antaŭ %s',
+            s : 'sekundoj',
+            m : 'minuto',
+            mm : '%d minutoj',
+            h : 'horo',
+            hh : '%d horoj',
+            d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo
+            dd : '%d tagoj',
+            M : 'monato',
+            MM : '%d monatoj',
+            y : 'jaro',
+            yy : '%d jaroj'
+        },
+        ordinal : '%da',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/es.js b/resources/lib/moment/locale/es.js
new file mode 100644 (file)
index 0000000..04b83a8
--- /dev/null
@@ -0,0 +1,75 @@
+// moment.js locale configuration
+// locale : spanish (es)
+// author : Julio Napurí : https://github.com/julionc
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'),
+        monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');
+
+    return moment.defineLocale('es', {
+        months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'),
+        monthsShort : function (m, format) {
+            if (/-MMM-/.test(format)) {
+                return monthsShort[m.month()];
+            } else {
+                return monthsShortDot[m.month()];
+            }
+        },
+        weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
+        weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
+        weekdaysMin : 'Do_Lu_Ma_Mi_Ju_Vi_Sá'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D [de] MMMM [de] YYYY',
+            LLL : 'D [de] MMMM [de] YYYY LT',
+            LLLL : 'dddd, D [de] MMMM [de] YYYY LT'
+        },
+        calendar : {
+            sameDay : function () {
+                return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            nextDay : function () {
+                return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            nextWeek : function () {
+                return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            lastDay : function () {
+                return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            lastWeek : function () {
+                return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'en %s',
+            past : 'hace %s',
+            s : 'unos segundos',
+            m : 'un minuto',
+            mm : '%d minutos',
+            h : 'una hora',
+            hh : '%d horas',
+            d : 'un día',
+            dd : '%d días',
+            M : 'un mes',
+            MM : '%d meses',
+            y : 'un año',
+            yy : '%d años'
+        },
+        ordinal : '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/et.js b/resources/lib/moment/locale/et.js
new file mode 100644 (file)
index 0000000..242ee16
--- /dev/null
@@ -0,0 +1,76 @@
+// moment.js locale configuration
+// locale : estonian (et)
+// author : Henry Kehlmann : https://github.com/madhenry
+// improvements : Illimar Tambek : https://github.com/ragulka
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var format = {
+            's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'],
+            'm' : ['ühe minuti', 'üks minut'],
+            'mm': [number + ' minuti', number + ' minutit'],
+            'h' : ['ühe tunni', 'tund aega', 'üks tund'],
+            'hh': [number + ' tunni', number + ' tundi'],
+            'd' : ['ühe päeva', 'üks päev'],
+            'M' : ['kuu aja', 'kuu aega', 'üks kuu'],
+            'MM': [number + ' kuu', number + ' kuud'],
+            'y' : ['ühe aasta', 'aasta', 'üks aasta'],
+            'yy': [number + ' aasta', number + ' aastat']
+        };
+        if (withoutSuffix) {
+            return format[key][2] ? format[key][2] : format[key][1];
+        }
+        return isFuture ? format[key][0] : format[key][1];
+    }
+
+    return moment.defineLocale('et', {
+        months        : 'jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember'.split('_'),
+        monthsShort   : 'jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets'.split('_'),
+        weekdays      : 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split('_'),
+        weekdaysShort : 'P_E_T_K_N_R_L'.split('_'),
+        weekdaysMin   : 'P_E_T_K_N_R_L'.split('_'),
+        longDateFormat : {
+            LT   : 'H:mm',
+            L    : 'DD.MM.YYYY',
+            LL   : 'D. MMMM YYYY',
+            LLL  : 'D. MMMM YYYY LT',
+            LLLL : 'dddd, D. MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay  : '[Täna,] LT',
+            nextDay  : '[Homme,] LT',
+            nextWeek : '[Järgmine] dddd LT',
+            lastDay  : '[Eile,] LT',
+            lastWeek : '[Eelmine] dddd LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s pärast',
+            past   : '%s tagasi',
+            s      : processRelativeTime,
+            m      : processRelativeTime,
+            mm     : processRelativeTime,
+            h      : processRelativeTime,
+            hh     : processRelativeTime,
+            d      : processRelativeTime,
+            dd     : '%d päeva',
+            M      : processRelativeTime,
+            MM     : processRelativeTime,
+            y      : processRelativeTime,
+            yy     : processRelativeTime
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/eu.js b/resources/lib/moment/locale/eu.js
new file mode 100644 (file)
index 0000000..8fb89b4
--- /dev/null
@@ -0,0 +1,60 @@
+// moment.js locale configuration
+// locale : euskara (eu)
+// author : Eneko Illarramendi : https://github.com/eillarra
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('eu', {
+        months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'),
+        monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'),
+        weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'),
+        weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'),
+        weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'YYYY-MM-DD',
+            LL : 'YYYY[ko] MMMM[ren] D[a]',
+            LLL : 'YYYY[ko] MMMM[ren] D[a] LT',
+            LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] LT',
+            l : 'YYYY-M-D',
+            ll : 'YYYY[ko] MMM D[a]',
+            lll : 'YYYY[ko] MMM D[a] LT',
+            llll : 'ddd, YYYY[ko] MMM D[a] LT'
+        },
+        calendar : {
+            sameDay : '[gaur] LT[etan]',
+            nextDay : '[bihar] LT[etan]',
+            nextWeek : 'dddd LT[etan]',
+            lastDay : '[atzo] LT[etan]',
+            lastWeek : '[aurreko] dddd LT[etan]',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s barru',
+            past : 'duela %s',
+            s : 'segundo batzuk',
+            m : 'minutu bat',
+            mm : '%d minutu',
+            h : 'ordu bat',
+            hh : '%d ordu',
+            d : 'egun bat',
+            dd : '%d egun',
+            M : 'hilabete bat',
+            MM : '%d hilabete',
+            y : 'urte bat',
+            yy : '%d urte'
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/fa.js b/resources/lib/moment/locale/fa.js
new file mode 100644 (file)
index 0000000..b1151bd
--- /dev/null
@@ -0,0 +1,97 @@
+// moment.js locale configuration
+// locale : Persian (fa)
+// author : Ebrahim Byagowi : https://github.com/ebraminio
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '۱',
+        '2': '۲',
+        '3': '۳',
+        '4': '۴',
+        '5': '۵',
+        '6': '۶',
+        '7': '۷',
+        '8': '۸',
+        '9': '۹',
+        '0': '۰'
+    }, numberMap = {
+        '۱': '1',
+        '۲': '2',
+        '۳': '3',
+        '۴': '4',
+        '۵': '5',
+        '۶': '6',
+        '۷': '7',
+        '۸': '8',
+        '۹': '9',
+        '۰': '0'
+    };
+
+    return moment.defineLocale('fa', {
+        months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
+        monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
+        weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
+        weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
+        weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return 'قبل از ظهر';
+            } else {
+                return 'بعد از ظهر';
+            }
+        },
+        calendar : {
+            sameDay : '[امروز ساعت] LT',
+            nextDay : '[فردا ساعت] LT',
+            nextWeek : 'dddd [ساعت] LT',
+            lastDay : '[دیروز ساعت] LT',
+            lastWeek : 'dddd [پیش] [ساعت] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'در %s',
+            past : '%s پیش',
+            s : 'چندین ثانیه',
+            m : 'یک دقیقه',
+            mm : '%d دقیقه',
+            h : 'یک ساعت',
+            hh : '%d ساعت',
+            d : 'یک روز',
+            dd : '%d روز',
+            M : 'یک ماه',
+            MM : '%d ماه',
+            y : 'یک سال',
+            yy : '%d سال'
+        },
+        preparse: function (string) {
+            return string.replace(/[۰-۹]/g, function (match) {
+                return numberMap[match];
+            }).replace(/،/g, ',');
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            }).replace(/,/g, '،');
+        },
+        ordinal : '%dم',
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12 // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/fi.js b/resources/lib/moment/locale/fi.js
new file mode 100644 (file)
index 0000000..1fedcab
--- /dev/null
@@ -0,0 +1,105 @@
+// moment.js locale configuration
+// locale : finnish (fi)
+// author : Tarmo Aidantausta : https://github.com/bleadof
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '),
+        numbersFuture = [
+            'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden',
+            numbersPast[7], numbersPast[8], numbersPast[9]
+        ];
+
+    function translate(number, withoutSuffix, key, isFuture) {
+        var result = '';
+        switch (key) {
+        case 's':
+            return isFuture ? 'muutaman sekunnin' : 'muutama sekunti';
+        case 'm':
+            return isFuture ? 'minuutin' : 'minuutti';
+        case 'mm':
+            result = isFuture ? 'minuutin' : 'minuuttia';
+            break;
+        case 'h':
+            return isFuture ? 'tunnin' : 'tunti';
+        case 'hh':
+            result = isFuture ? 'tunnin' : 'tuntia';
+            break;
+        case 'd':
+            return isFuture ? 'päivän' : 'päivä';
+        case 'dd':
+            result = isFuture ? 'päivän' : 'päivää';
+            break;
+        case 'M':
+            return isFuture ? 'kuukauden' : 'kuukausi';
+        case 'MM':
+            result = isFuture ? 'kuukauden' : 'kuukautta';
+            break;
+        case 'y':
+            return isFuture ? 'vuoden' : 'vuosi';
+        case 'yy':
+            result = isFuture ? 'vuoden' : 'vuotta';
+            break;
+        }
+        result = verbalNumber(number, isFuture) + ' ' + result;
+        return result;
+    }
+
+    function verbalNumber(number, isFuture) {
+        return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number;
+    }
+
+    return moment.defineLocale('fi', {
+        months : 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'),
+        monthsShort : 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'),
+        weekdays : 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'),
+        weekdaysShort : 'su_ma_ti_ke_to_pe_la'.split('_'),
+        weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'),
+        longDateFormat : {
+            LT : 'HH.mm',
+            L : 'DD.MM.YYYY',
+            LL : 'Do MMMM[ta] YYYY',
+            LLL : 'Do MMMM[ta] YYYY, [klo] LT',
+            LLLL : 'dddd, Do MMMM[ta] YYYY, [klo] LT',
+            l : 'D.M.YYYY',
+            ll : 'Do MMM YYYY',
+            lll : 'Do MMM YYYY, [klo] LT',
+            llll : 'ddd, Do MMM YYYY, [klo] LT'
+        },
+        calendar : {
+            sameDay : '[tänään] [klo] LT',
+            nextDay : '[huomenna] [klo] LT',
+            nextWeek : 'dddd [klo] LT',
+            lastDay : '[eilen] [klo] LT',
+            lastWeek : '[viime] dddd[na] [klo] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s päästä',
+            past : '%s sitten',
+            s : translate,
+            m : translate,
+            mm : translate,
+            h : translate,
+            hh : translate,
+            d : translate,
+            dd : translate,
+            M : translate,
+            MM : translate,
+            y : translate,
+            yy : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/fo.js b/resources/lib/moment/locale/fo.js
new file mode 100644 (file)
index 0000000..a27f9da
--- /dev/null
@@ -0,0 +1,56 @@
+// moment.js locale configuration
+// locale : faroese (fo)
+// author : Ragnar Johannesen : https://github.com/ragnar123
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('fo', {
+        months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
+        weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'),
+        weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'),
+        weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D. MMMM, YYYY LT'
+        },
+        calendar : {
+            sameDay : '[Í dag kl.] LT',
+            nextDay : '[Í morgin kl.] LT',
+            nextWeek : 'dddd [kl.] LT',
+            lastDay : '[Í gjár kl.] LT',
+            lastWeek : '[síðstu] dddd [kl] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'um %s',
+            past : '%s síðani',
+            s : 'fá sekund',
+            m : 'ein minutt',
+            mm : '%d minuttir',
+            h : 'ein tími',
+            hh : '%d tímar',
+            d : 'ein dagur',
+            dd : '%d dagar',
+            M : 'ein mánaði',
+            MM : '%d mánaðir',
+            y : 'eitt ár',
+            yy : '%d ár'
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/fr-ca.js b/resources/lib/moment/locale/fr-ca.js
new file mode 100644 (file)
index 0000000..c0f1bdc
--- /dev/null
@@ -0,0 +1,54 @@
+// moment.js locale configuration
+// locale : canadian french (fr-ca)
+// author : Jonathan Abourbih : https://github.com/jonbca
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('fr-ca', {
+        months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
+        monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
+        weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
+        weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
+        weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'YYYY-MM-DD',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[Aujourd\'hui à] LT',
+            nextDay: '[Demain à] LT',
+            nextWeek: 'dddd [à] LT',
+            lastDay: '[Hier à] LT',
+            lastWeek: 'dddd [dernier à] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'dans %s',
+            past : 'il y a %s',
+            s : 'quelques secondes',
+            m : 'une minute',
+            mm : '%d minutes',
+            h : 'une heure',
+            hh : '%d heures',
+            d : 'un jour',
+            dd : '%d jours',
+            M : 'un mois',
+            MM : '%d mois',
+            y : 'un an',
+            yy : '%d ans'
+        },
+        ordinal : function (number) {
+            return number + (number === 1 ? 'er' : '');
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/fr.js b/resources/lib/moment/locale/fr.js
new file mode 100644 (file)
index 0000000..f217ff1
--- /dev/null
@@ -0,0 +1,58 @@
+// moment.js locale configuration
+// locale : french (fr)
+// author : John Fischer : https://github.com/jfroffice
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('fr', {
+        months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
+        monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
+        weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
+        weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
+        weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[Aujourd\'hui à] LT',
+            nextDay: '[Demain à] LT',
+            nextWeek: 'dddd [à] LT',
+            lastDay: '[Hier à] LT',
+            lastWeek: 'dddd [dernier à] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'dans %s',
+            past : 'il y a %s',
+            s : 'quelques secondes',
+            m : 'une minute',
+            mm : '%d minutes',
+            h : 'une heure',
+            hh : '%d heures',
+            d : 'un jour',
+            dd : '%d jours',
+            M : 'un mois',
+            MM : '%d mois',
+            y : 'un an',
+            yy : '%d ans'
+        },
+        ordinal : function (number) {
+            return number + (number === 1 ? 'er' : '');
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/gl.js b/resources/lib/moment/locale/gl.js
new file mode 100644 (file)
index 0000000..ac63862
--- /dev/null
@@ -0,0 +1,71 @@
+// moment.js locale configuration
+// locale : galician (gl)
+// author : Juan G. Hurtado : https://github.com/juanghurtado
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('gl', {
+        months : 'Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro'.split('_'),
+        monthsShort : 'Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.'.split('_'),
+        weekdays : 'Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado'.split('_'),
+        weekdaysShort : 'Dom._Lun._Mar._Mér._Xov._Ven._Sáb.'.split('_'),
+        weekdaysMin : 'Do_Lu_Ma_Mé_Xo_Ve_Sá'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : function () {
+                return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
+            },
+            nextDay : function () {
+                return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
+            },
+            nextWeek : function () {
+                return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
+            },
+            lastDay : function () {
+                return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT';
+            },
+            lastWeek : function () {
+                return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : function (str) {
+                if (str === 'uns segundos') {
+                    return 'nuns segundos';
+                }
+                return 'en ' + str;
+            },
+            past : 'hai %s',
+            s : 'uns segundos',
+            m : 'un minuto',
+            mm : '%d minutos',
+            h : 'unha hora',
+            hh : '%d horas',
+            d : 'un día',
+            dd : '%d días',
+            M : 'un mes',
+            MM : '%d meses',
+            y : 'un ano',
+            yy : '%d anos'
+        },
+        ordinal : '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/he.js b/resources/lib/moment/locale/he.js
new file mode 100644 (file)
index 0000000..06f954f
--- /dev/null
@@ -0,0 +1,77 @@
+// moment.js locale configuration
+// locale : Hebrew (he)
+// author : Tomer Cohen : https://github.com/tomer
+// author : Moshe Simantov : https://github.com/DevelopmentIL
+// author : Tal Ater : https://github.com/TalAter
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('he', {
+        months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'),
+        monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'),
+        weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'),
+        weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'),
+        weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D [ב]MMMM YYYY',
+            LLL : 'D [ב]MMMM YYYY LT',
+            LLLL : 'dddd, D [ב]MMMM YYYY LT',
+            l : 'D/M/YYYY',
+            ll : 'D MMM YYYY',
+            lll : 'D MMM YYYY LT',
+            llll : 'ddd, D MMM YYYY LT'
+        },
+        calendar : {
+            sameDay : '[היום ב־]LT',
+            nextDay : '[מחר ב־]LT',
+            nextWeek : 'dddd [בשעה] LT',
+            lastDay : '[אתמול ב־]LT',
+            lastWeek : '[ביום] dddd [האחרון בשעה] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'בעוד %s',
+            past : 'לפני %s',
+            s : 'מספר שניות',
+            m : 'דקה',
+            mm : '%d דקות',
+            h : 'שעה',
+            hh : function (number) {
+                if (number === 2) {
+                    return 'שעתיים';
+                }
+                return number + ' שעות';
+            },
+            d : 'יום',
+            dd : function (number) {
+                if (number === 2) {
+                    return 'יומיים';
+                }
+                return number + ' ימים';
+            },
+            M : 'חודש',
+            MM : function (number) {
+                if (number === 2) {
+                    return 'חודשיים';
+                }
+                return number + ' חודשים';
+            },
+            y : 'שנה',
+            yy : function (number) {
+                if (number === 2) {
+                    return 'שנתיים';
+                }
+                return number + ' שנים';
+            }
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/hi.js b/resources/lib/moment/locale/hi.js
new file mode 100644 (file)
index 0000000..4e64560
--- /dev/null
@@ -0,0 +1,105 @@
+// moment.js locale configuration
+// locale : hindi (hi)
+// author : Mayank Singhal : https://github.com/mayanksinghal
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '१',
+        '2': '२',
+        '3': '३',
+        '4': '४',
+        '5': '५',
+        '6': '६',
+        '7': '७',
+        '8': '८',
+        '9': '९',
+        '0': '०'
+    },
+    numberMap = {
+        '१': '1',
+        '२': '2',
+        '३': '3',
+        '४': '4',
+        '५': '5',
+        '६': '6',
+        '७': '7',
+        '८': '8',
+        '९': '9',
+        '०': '0'
+    };
+
+    return moment.defineLocale('hi', {
+        months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'),
+        monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'),
+        weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
+        weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'),
+        weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
+        longDateFormat : {
+            LT : 'A h:mm बजे',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, LT',
+            LLLL : 'dddd, D MMMM YYYY, LT'
+        },
+        calendar : {
+            sameDay : '[आज] LT',
+            nextDay : '[कल] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[कल] LT',
+            lastWeek : '[पिछले] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s में',
+            past : '%s पहले',
+            s : 'कुछ ही क्षण',
+            m : 'एक मिनट',
+            mm : '%d मिनट',
+            h : 'एक घंटा',
+            hh : '%d घंटे',
+            d : 'एक दिन',
+            dd : '%d दिन',
+            M : 'एक महीने',
+            MM : '%d महीने',
+            y : 'एक वर्ष',
+            yy : '%d वर्ष'
+        },
+        preparse: function (string) {
+            return string.replace(/[१२३४५६७८९०]/g, function (match) {
+                return numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            });
+        },
+        // Hindi notation for meridiems are quite fuzzy in practice. While there exists
+        // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi.
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'रात';
+            } else if (hour < 10) {
+                return 'सुबह';
+            } else if (hour < 17) {
+                return 'दोपहर';
+            } else if (hour < 20) {
+                return 'शाम';
+            } else {
+                return 'रात';
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/hr.js b/resources/lib/moment/locale/hr.js
new file mode 100644 (file)
index 0000000..9e3f6fa
--- /dev/null
@@ -0,0 +1,139 @@
+// moment.js locale configuration
+// locale : hrvatski (hr)
+// author : Bojan Marković : https://github.com/bmarkovic
+
+// based on (sl) translation by Robert Sedovšek
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function translate(number, withoutSuffix, key) {
+        var result = number + ' ';
+        switch (key) {
+        case 'm':
+            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
+        case 'mm':
+            if (number === 1) {
+                result += 'minuta';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'minute';
+            } else {
+                result += 'minuta';
+            }
+            return result;
+        case 'h':
+            return withoutSuffix ? 'jedan sat' : 'jednog sata';
+        case 'hh':
+            if (number === 1) {
+                result += 'sat';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'sata';
+            } else {
+                result += 'sati';
+            }
+            return result;
+        case 'dd':
+            if (number === 1) {
+                result += 'dan';
+            } else {
+                result += 'dana';
+            }
+            return result;
+        case 'MM':
+            if (number === 1) {
+                result += 'mjesec';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'mjeseca';
+            } else {
+                result += 'mjeseci';
+            }
+            return result;
+        case 'yy':
+            if (number === 1) {
+                result += 'godina';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'godine';
+            } else {
+                result += 'godina';
+            }
+            return result;
+        }
+    }
+
+    return moment.defineLocale('hr', {
+        months : 'sječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_'),
+        monthsShort : 'sje._vel._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'),
+        weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
+        weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
+        weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            L : 'DD. MM. YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY LT',
+            LLLL : 'dddd, D. MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay  : '[danas u] LT',
+            nextDay  : '[sutra u] LT',
+
+            nextWeek : function () {
+                switch (this.day()) {
+                case 0:
+                    return '[u] [nedjelju] [u] LT';
+                case 3:
+                    return '[u] [srijedu] [u] LT';
+                case 6:
+                    return '[u] [subotu] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[u] dddd [u] LT';
+                }
+            },
+            lastDay  : '[jučer u] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                    return '[prošlu] dddd [u] LT';
+                case 6:
+                    return '[prošle] [subote] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[prošli] dddd [u] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past   : 'prije %s',
+            s      : 'par sekundi',
+            m      : translate,
+            mm     : translate,
+            h      : translate,
+            hh     : translate,
+            d      : 'dan',
+            dd     : translate,
+            M      : 'mjesec',
+            MM     : translate,
+            y      : 'godinu',
+            yy     : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/hu.js b/resources/lib/moment/locale/hu.js
new file mode 100644 (file)
index 0000000..73fdb83
--- /dev/null
@@ -0,0 +1,105 @@
+// moment.js locale configuration
+// locale : hungarian (hu)
+// author : Adam Brunner : https://github.com/adambrunner
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' ');
+
+    function translate(number, withoutSuffix, key, isFuture) {
+        var num = number,
+            suffix;
+
+        switch (key) {
+        case 's':
+            return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce';
+        case 'm':
+            return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce');
+        case 'mm':
+            return num + (isFuture || withoutSuffix ? ' perc' : ' perce');
+        case 'h':
+            return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája');
+        case 'hh':
+            return num + (isFuture || withoutSuffix ? ' óra' : ' órája');
+        case 'd':
+            return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja');
+        case 'dd':
+            return num + (isFuture || withoutSuffix ? ' nap' : ' napja');
+        case 'M':
+            return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
+        case 'MM':
+            return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
+        case 'y':
+            return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve');
+        case 'yy':
+            return num + (isFuture || withoutSuffix ? ' év' : ' éve');
+        }
+
+        return '';
+    }
+
+    function week(isFuture) {
+        return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]';
+    }
+
+    return moment.defineLocale('hu', {
+        months : 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split('_'),
+        monthsShort : 'jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec'.split('_'),
+        weekdays : 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'),
+        weekdaysShort : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'),
+        weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            L : 'YYYY.MM.DD.',
+            LL : 'YYYY. MMMM D.',
+            LLL : 'YYYY. MMMM D., LT',
+            LLLL : 'YYYY. MMMM D., dddd LT'
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 12) {
+                return isLower === true ? 'de' : 'DE';
+            } else {
+                return isLower === true ? 'du' : 'DU';
+            }
+        },
+        calendar : {
+            sameDay : '[ma] LT[-kor]',
+            nextDay : '[holnap] LT[-kor]',
+            nextWeek : function () {
+                return week.call(this, true);
+            },
+            lastDay : '[tegnap] LT[-kor]',
+            lastWeek : function () {
+                return week.call(this, false);
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s múlva',
+            past : '%s',
+            s : translate,
+            m : translate,
+            mm : translate,
+            h : translate,
+            hh : translate,
+            d : translate,
+            dd : translate,
+            M : translate,
+            MM : translate,
+            y : translate,
+            yy : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/hy-am.js b/resources/lib/moment/locale/hy-am.js
new file mode 100644 (file)
index 0000000..affcd7e
--- /dev/null
@@ -0,0 +1,112 @@
+// moment.js locale configuration
+// locale : Armenian (hy-am)
+// author : Armendarabyan : https://github.com/armendarabyan
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function monthsCaseReplace(m, format) {
+        var months = {
+            'nominative': 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_'),
+            'accusative': 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_')
+        },
+
+        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return months[nounCase][m.month()];
+    }
+
+    function monthsShortCaseReplace(m, format) {
+        var monthsShort = 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_');
+
+        return monthsShort[m.month()];
+    }
+
+    function weekdaysCaseReplace(m, format) {
+        var weekdays = 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_');
+
+        return weekdays[m.day()];
+    }
+
+    return moment.defineLocale('hy-am', {
+        months : monthsCaseReplace,
+        monthsShort : monthsShortCaseReplace,
+        weekdays : weekdaysCaseReplace,
+        weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
+        weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY թ.',
+            LLL : 'D MMMM YYYY թ., LT',
+            LLLL : 'dddd, D MMMM YYYY թ., LT'
+        },
+        calendar : {
+            sameDay: '[այսօր] LT',
+            nextDay: '[վաղը] LT',
+            lastDay: '[երեկ] LT',
+            nextWeek: function () {
+                return 'dddd [օրը ժամը] LT';
+            },
+            lastWeek: function () {
+                return '[անցած] dddd [օրը ժամը] LT';
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : '%s հետո',
+            past : '%s առաջ',
+            s : 'մի քանի վայրկյան',
+            m : 'րոպե',
+            mm : '%d րոպե',
+            h : 'ժամ',
+            hh : '%d ժամ',
+            d : 'օր',
+            dd : '%d օր',
+            M : 'ամիս',
+            MM : '%d ամիս',
+            y : 'տարի',
+            yy : '%d տարի'
+        },
+
+        meridiem : function (hour) {
+            if (hour < 4) {
+                return 'գիշերվա';
+            } else if (hour < 12) {
+                return 'առավոտվա';
+            } else if (hour < 17) {
+                return 'ցերեկվա';
+            } else {
+                return 'երեկոյան';
+            }
+        },
+
+        ordinal: function (number, period) {
+            switch (period) {
+            case 'DDD':
+            case 'w':
+            case 'W':
+            case 'DDDo':
+                if (number === 1) {
+                    return number + '-ին';
+                }
+                return number + '-րդ';
+            default:
+                return number;
+            }
+        },
+
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/id.js b/resources/lib/moment/locale/id.js
new file mode 100644 (file)
index 0000000..143426a
--- /dev/null
@@ -0,0 +1,67 @@
+// moment.js locale configuration
+// locale : Bahasa Indonesia (id)
+// author : Mohammad Satrio Utomo : https://github.com/tyok
+// reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('id', {
+        months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des'.split('_'),
+        weekdays : 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'),
+        weekdaysShort : 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'),
+        weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'),
+        longDateFormat : {
+            LT : 'HH.mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY [pukul] LT',
+            LLLL : 'dddd, D MMMM YYYY [pukul] LT'
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 11) {
+                return 'pagi';
+            } else if (hours < 15) {
+                return 'siang';
+            } else if (hours < 19) {
+                return 'sore';
+            } else {
+                return 'malam';
+            }
+        },
+        calendar : {
+            sameDay : '[Hari ini pukul] LT',
+            nextDay : '[Besok pukul] LT',
+            nextWeek : 'dddd [pukul] LT',
+            lastDay : '[Kemarin pukul] LT',
+            lastWeek : 'dddd [lalu pukul] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'dalam %s',
+            past : '%s yang lalu',
+            s : 'beberapa detik',
+            m : 'semenit',
+            mm : '%d menit',
+            h : 'sejam',
+            hh : '%d jam',
+            d : 'sehari',
+            dd : '%d hari',
+            M : 'sebulan',
+            MM : '%d bulan',
+            y : 'setahun',
+            yy : '%d tahun'
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/is.js b/resources/lib/moment/locale/is.js
new file mode 100644 (file)
index 0000000..479f82d
--- /dev/null
@@ -0,0 +1,124 @@
+// moment.js locale configuration
+// locale : icelandic (is)
+// author : Hinrik Örn Sigurðsson : https://github.com/hinrik
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function plural(n) {
+        if (n % 100 === 11) {
+            return true;
+        } else if (n % 10 === 1) {
+            return false;
+        }
+        return true;
+    }
+
+    function translate(number, withoutSuffix, key, isFuture) {
+        var result = number + ' ';
+        switch (key) {
+        case 's':
+            return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum';
+        case 'm':
+            return withoutSuffix ? 'mínúta' : 'mínútu';
+        case 'mm':
+            if (plural(number)) {
+                return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum');
+            } else if (withoutSuffix) {
+                return result + 'mínúta';
+            }
+            return result + 'mínútu';
+        case 'hh':
+            if (plural(number)) {
+                return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum');
+            }
+            return result + 'klukkustund';
+        case 'd':
+            if (withoutSuffix) {
+                return 'dagur';
+            }
+            return isFuture ? 'dag' : 'degi';
+        case 'dd':
+            if (plural(number)) {
+                if (withoutSuffix) {
+                    return result + 'dagar';
+                }
+                return result + (isFuture ? 'daga' : 'dögum');
+            } else if (withoutSuffix) {
+                return result + 'dagur';
+            }
+            return result + (isFuture ? 'dag' : 'degi');
+        case 'M':
+            if (withoutSuffix) {
+                return 'mánuður';
+            }
+            return isFuture ? 'mánuð' : 'mánuði';
+        case 'MM':
+            if (plural(number)) {
+                if (withoutSuffix) {
+                    return result + 'mánuðir';
+                }
+                return result + (isFuture ? 'mánuði' : 'mánuðum');
+            } else if (withoutSuffix) {
+                return result + 'mánuður';
+            }
+            return result + (isFuture ? 'mánuð' : 'mánuði');
+        case 'y':
+            return withoutSuffix || isFuture ? 'ár' : 'ári';
+        case 'yy':
+            if (plural(number)) {
+                return result + (withoutSuffix || isFuture ? 'ár' : 'árum');
+            }
+            return result + (withoutSuffix || isFuture ? 'ár' : 'ári');
+        }
+    }
+
+    return moment.defineLocale('is', {
+        months : 'janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des'.split('_'),
+        weekdays : 'sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur'.split('_'),
+        weekdaysShort : 'sun_mán_þri_mið_fim_fös_lau'.split('_'),
+        weekdaysMin : 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY [kl.] LT',
+            LLLL : 'dddd, D. MMMM YYYY [kl.] LT'
+        },
+        calendar : {
+            sameDay : '[í dag kl.] LT',
+            nextDay : '[á morgun kl.] LT',
+            nextWeek : 'dddd [kl.] LT',
+            lastDay : '[í gær kl.] LT',
+            lastWeek : '[síðasta] dddd [kl.] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'eftir %s',
+            past : 'fyrir %s síðan',
+            s : translate,
+            m : translate,
+            mm : translate,
+            h : 'klukkustund',
+            hh : translate,
+            d : translate,
+            dd : translate,
+            M : translate,
+            MM : translate,
+            y : translate,
+            yy : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/it.js b/resources/lib/moment/locale/it.js
new file mode 100644 (file)
index 0000000..6695390
--- /dev/null
@@ -0,0 +1,59 @@
+// moment.js locale configuration
+// locale : italian (it)
+// author : Lorenzo : https://github.com/aliem
+// author: Mattia Larentis: https://github.com/nostalgiaz
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('it', {
+        months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'),
+        monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'),
+        weekdays : 'Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato'.split('_'),
+        weekdaysShort : 'Dom_Lun_Mar_Mer_Gio_Ven_Sab'.split('_'),
+        weekdaysMin : 'D_L_Ma_Me_G_V_S'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[Oggi alle] LT',
+            nextDay: '[Domani alle] LT',
+            nextWeek: 'dddd [alle] LT',
+            lastDay: '[Ieri alle] LT',
+            lastWeek: '[lo scorso] dddd [alle] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : function (s) {
+                return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s;
+            },
+            past : '%s fa',
+            s : 'alcuni secondi',
+            m : 'un minuto',
+            mm : '%d minuti',
+            h : 'un\'ora',
+            hh : '%d ore',
+            d : 'un giorno',
+            dd : '%d giorni',
+            M : 'un mese',
+            MM : '%d mesi',
+            y : 'un anno',
+            yy : '%d anni'
+        },
+        ordinal: '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ja.js b/resources/lib/moment/locale/ja.js
new file mode 100644 (file)
index 0000000..f14fa4e
--- /dev/null
@@ -0,0 +1,58 @@
+// moment.js locale configuration
+// locale : japanese (ja)
+// author : LI Long : https://github.com/baryon
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('ja', {
+        months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+        monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+        weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'),
+        weekdaysShort : '日_月_火_水_木_金_土'.split('_'),
+        weekdaysMin : '日_月_火_水_木_金_土'.split('_'),
+        longDateFormat : {
+            LT : 'Ah時m分',
+            L : 'YYYY/MM/DD',
+            LL : 'YYYY年M月D日',
+            LLL : 'YYYY年M月D日LT',
+            LLLL : 'YYYY年M月D日LT dddd'
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return '午前';
+            } else {
+                return '午後';
+            }
+        },
+        calendar : {
+            sameDay : '[今日] LT',
+            nextDay : '[明日] LT',
+            nextWeek : '[来週]dddd LT',
+            lastDay : '[昨日] LT',
+            lastWeek : '[前週]dddd LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s後',
+            past : '%s前',
+            s : '数秒',
+            m : '1分',
+            mm : '%d分',
+            h : '1時間',
+            hh : '%d時間',
+            d : '1日',
+            dd : '%d日',
+            M : '1ヶ月',
+            MM : '%dヶ月',
+            y : '1年',
+            yy : '%d年'
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ka.js b/resources/lib/moment/locale/ka.js
new file mode 100644 (file)
index 0000000..73eb9c7
--- /dev/null
@@ -0,0 +1,107 @@
+// moment.js locale configuration
+// locale : Georgian (ka)
+// author : Irakli Janiashvili : https://github.com/irakli-janiashvili
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function monthsCaseReplace(m, format) {
+        var months = {
+            'nominative': 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'),
+            'accusative': 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_')
+        },
+
+        nounCase = (/D[oD] *MMMM?/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return months[nounCase][m.month()];
+    }
+
+    function weekdaysCaseReplace(m, format) {
+        var weekdays = {
+            'nominative': 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'),
+            'accusative': 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_')
+        },
+
+        nounCase = (/(წინა|შემდეგ)/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return weekdays[nounCase][m.day()];
+    }
+
+    return moment.defineLocale('ka', {
+        months : monthsCaseReplace,
+        monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'),
+        weekdays : weekdaysCaseReplace,
+        weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'),
+        weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'),
+        longDateFormat : {
+            LT : 'h:mm A',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : '[დღეს] LT[-ზე]',
+            nextDay : '[ხვალ] LT[-ზე]',
+            lastDay : '[გუშინ] LT[-ზე]',
+            nextWeek : '[შემდეგ] dddd LT[-ზე]',
+            lastWeek : '[წინა] dddd LT-ზე',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : function (s) {
+                return (/(წამი|წუთი|საათი|წელი)/).test(s) ?
+                    s.replace(/ი$/, 'ში') :
+                    s + 'ში';
+            },
+            past : function (s) {
+                if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) {
+                    return s.replace(/(ი|ე)$/, 'ის წინ');
+                }
+                if ((/წელი/).test(s)) {
+                    return s.replace(/წელი$/, 'წლის წინ');
+                }
+            },
+            s : 'რამდენიმე წამი',
+            m : 'წუთი',
+            mm : '%d წუთი',
+            h : 'საათი',
+            hh : '%d საათი',
+            d : 'დღე',
+            dd : '%d დღე',
+            M : 'თვე',
+            MM : '%d თვე',
+            y : 'წელი',
+            yy : '%d წელი'
+        },
+        ordinal : function (number) {
+            if (number === 0) {
+                return number;
+            }
+
+            if (number === 1) {
+                return number + '-ლი';
+            }
+
+            if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) {
+                return 'მე-' + number;
+            }
+
+            return number + '-ე';
+        },
+        week : {
+            dow : 1,
+            doy : 7
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/km.js b/resources/lib/moment/locale/km.js
new file mode 100644 (file)
index 0000000..9ba4888
--- /dev/null
@@ -0,0 +1,55 @@
+// moment.js locale configuration
+// locale : khmer (km)
+// author : Kruy Vanna : https://github.com/kruyvanna
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('km', {
+        months: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'),
+        monthsShort: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'),
+        weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
+        weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
+        weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
+        longDateFormat: {
+            LT: 'HH:mm',
+            L: 'DD/MM/YYYY',
+            LL: 'D MMMM YYYY',
+            LLL: 'D MMMM YYYY LT',
+            LLLL: 'dddd, D MMMM YYYY LT'
+        },
+        calendar: {
+            sameDay: '[ថ្ងៃនៈ ម៉ោង] LT',
+            nextDay: '[ស្អែក ម៉ោង] LT',
+            nextWeek: 'dddd [ម៉ោង] LT',
+            lastDay: '[ម្សិលមិញ ម៉ោង] LT',
+            lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT',
+            sameElse: 'L'
+        },
+        relativeTime: {
+            future: '%sទៀត',
+            past: '%sមុន',
+            s: 'ប៉ុន្មានវិនាទី',
+            m: 'មួយនាទី',
+            mm: '%d នាទី',
+            h: 'មួយម៉ោង',
+            hh: '%d ម៉ោង',
+            d: 'មួយថ្ងៃ',
+            dd: '%d ថ្ងៃ',
+            M: 'មួយខែ',
+            MM: '%d ខែ',
+            y: 'មួយឆ្នាំ',
+            yy: '%d ឆ្នាំ'
+        },
+        week: {
+            dow: 1, // Monday is the first day of the week.
+            doy: 4 // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ko.js b/resources/lib/moment/locale/ko.js
new file mode 100644 (file)
index 0000000..57017f5
--- /dev/null
@@ -0,0 +1,63 @@
+// moment.js locale configuration
+// locale : korean (ko)
+//
+// authors
+//
+// - Kyungwook, Park : https://github.com/kyungw00k
+// - Jeeeyul Lee <jeeeyul@gmail.com>
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('ko', {
+        months : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
+        monthsShort : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
+        weekdays : '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'),
+        weekdaysShort : '일_월_화_수_목_금_토'.split('_'),
+        weekdaysMin : '일_월_화_수_목_금_토'.split('_'),
+        longDateFormat : {
+            LT : 'A h시 m분',
+            L : 'YYYY.MM.DD',
+            LL : 'YYYY년 MMMM D일',
+            LLL : 'YYYY년 MMMM D일 LT',
+            LLLL : 'YYYY년 MMMM D일 dddd LT'
+        },
+        meridiem : function (hour, minute, isUpper) {
+            return hour < 12 ? '오전' : '오후';
+        },
+        calendar : {
+            sameDay : '오늘 LT',
+            nextDay : '내일 LT',
+            nextWeek : 'dddd LT',
+            lastDay : '어제 LT',
+            lastWeek : '지난주 dddd LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s 후',
+            past : '%s 전',
+            s : '몇초',
+            ss : '%d초',
+            m : '일분',
+            mm : '%d분',
+            h : '한시간',
+            hh : '%d시간',
+            d : '하루',
+            dd : '%d일',
+            M : '한달',
+            MM : '%d달',
+            y : '일년',
+            yy : '%d년'
+        },
+        ordinal : '%d일',
+        meridiemParse : /(오전|오후)/,
+        isPM : function (token) {
+            return token === '오후';
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/lb.js b/resources/lib/moment/locale/lb.js
new file mode 100644 (file)
index 0000000..14fab97
--- /dev/null
@@ -0,0 +1,137 @@
+// moment.js locale configuration
+// locale : Luxembourgish (lb)
+// author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz
+
+// Note: Luxembourgish has a very particular phonological rule ('Eifeler Regel') that causes the
+// deletion of the final 'n' in certain contexts. That's what the 'eifelerRegelAppliesToWeekday'
+// and 'eifelerRegelAppliesToNumber' methods are meant for
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var format = {
+            'm': ['eng Minutt', 'enger Minutt'],
+            'h': ['eng Stonn', 'enger Stonn'],
+            'd': ['een Dag', 'engem Dag'],
+            'M': ['ee Mount', 'engem Mount'],
+            'y': ['ee Joer', 'engem Joer']
+        };
+        return withoutSuffix ? format[key][0] : format[key][1];
+    }
+
+    function processFutureTime(string) {
+        var number = string.substr(0, string.indexOf(' '));
+        if (eifelerRegelAppliesToNumber(number)) {
+            return 'a ' + string;
+        }
+        return 'an ' + string;
+    }
+
+    function processPastTime(string) {
+        var number = string.substr(0, string.indexOf(' '));
+        if (eifelerRegelAppliesToNumber(number)) {
+            return 'viru ' + string;
+        }
+        return 'virun ' + string;
+    }
+
+    /**
+     * Returns true if the word before the given number loses the '-n' ending.
+     * e.g. 'an 10 Deeg' but 'a 5 Deeg'
+     *
+     * @param number {integer}
+     * @returns {boolean}
+     */
+    function eifelerRegelAppliesToNumber(number) {
+        number = parseInt(number, 10);
+        if (isNaN(number)) {
+            return false;
+        }
+        if (number < 0) {
+            // Negative Number --> always true
+            return true;
+        } else if (number < 10) {
+            // Only 1 digit
+            if (4 <= number && number <= 7) {
+                return true;
+            }
+            return false;
+        } else if (number < 100) {
+            // 2 digits
+            var lastDigit = number % 10, firstDigit = number / 10;
+            if (lastDigit === 0) {
+                return eifelerRegelAppliesToNumber(firstDigit);
+            }
+            return eifelerRegelAppliesToNumber(lastDigit);
+        } else if (number < 10000) {
+            // 3 or 4 digits --> recursively check first digit
+            while (number >= 10) {
+                number = number / 10;
+            }
+            return eifelerRegelAppliesToNumber(number);
+        } else {
+            // Anything larger than 4 digits: recursively check first n-3 digits
+            number = number / 1000;
+            return eifelerRegelAppliesToNumber(number);
+        }
+    }
+
+    return moment.defineLocale('lb', {
+        months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+        monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
+        weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'),
+        weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'),
+        weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'),
+        longDateFormat: {
+            LT: 'H:mm [Auer]',
+            L: 'DD.MM.YYYY',
+            LL: 'D. MMMM YYYY',
+            LLL: 'D. MMMM YYYY LT',
+            LLLL: 'dddd, D. MMMM YYYY LT'
+        },
+        calendar: {
+            sameDay: '[Haut um] LT',
+            sameElse: 'L',
+            nextDay: '[Muer um] LT',
+            nextWeek: 'dddd [um] LT',
+            lastDay: '[Gëschter um] LT',
+            lastWeek: function () {
+                // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule
+                switch (this.day()) {
+                    case 2:
+                    case 4:
+                        return '[Leschten] dddd [um] LT';
+                    default:
+                        return '[Leschte] dddd [um] LT';
+                }
+            }
+        },
+        relativeTime : {
+            future : processFutureTime,
+            past : processPastTime,
+            s : 'e puer Sekonnen',
+            m : processRelativeTime,
+            mm : '%d Minutten',
+            h : processRelativeTime,
+            hh : '%d Stonnen',
+            d : processRelativeTime,
+            dd : '%d Deeg',
+            M : processRelativeTime,
+            MM : '%d Méint',
+            y : processRelativeTime,
+            yy : '%d Joer'
+        },
+        ordinal: '%d.',
+        week: {
+            dow: 1, // Monday is the first day of the week.
+            doy: 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/lt.js b/resources/lib/moment/locale/lt.js
new file mode 100644 (file)
index 0000000..013f8f1
--- /dev/null
@@ -0,0 +1,118 @@
+// moment.js locale configuration
+// locale : Lithuanian (lt)
+// author : Mindaugas Mozūras : https://github.com/mmozuras
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var units = {
+        'm' : 'minutė_minutės_minutę',
+        'mm': 'minutės_minučių_minutes',
+        'h' : 'valanda_valandos_valandą',
+        'hh': 'valandos_valandų_valandas',
+        'd' : 'diena_dienos_dieną',
+        'dd': 'dienos_dienų_dienas',
+        'M' : 'mėnuo_mėnesio_mėnesį',
+        'MM': 'mėnesiai_mėnesių_mėnesius',
+        'y' : 'metai_metų_metus',
+        'yy': 'metai_metų_metus'
+    },
+    weekDays = 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_');
+
+    function translateSeconds(number, withoutSuffix, key, isFuture) {
+        if (withoutSuffix) {
+            return 'kelios sekundės';
+        } else {
+            return isFuture ? 'kelių sekundžių' : 'kelias sekundes';
+        }
+    }
+
+    function translateSingular(number, withoutSuffix, key, isFuture) {
+        return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]);
+    }
+
+    function special(number) {
+        return number % 10 === 0 || (number > 10 && number < 20);
+    }
+
+    function forms(key) {
+        return units[key].split('_');
+    }
+
+    function translate(number, withoutSuffix, key, isFuture) {
+        var result = number + ' ';
+        if (number === 1) {
+            return result + translateSingular(number, withoutSuffix, key[0], isFuture);
+        } else if (withoutSuffix) {
+            return result + (special(number) ? forms(key)[1] : forms(key)[0]);
+        } else {
+            if (isFuture) {
+                return result + forms(key)[1];
+            } else {
+                return result + (special(number) ? forms(key)[1] : forms(key)[2]);
+            }
+        }
+    }
+
+    function relativeWeekDay(moment, format) {
+        var nominative = format.indexOf('dddd HH:mm') === -1,
+            weekDay = weekDays[moment.day()];
+
+        return nominative ? weekDay : weekDay.substring(0, weekDay.length - 2) + 'į';
+    }
+
+    return moment.defineLocale('lt', {
+        months : 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'),
+        monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'),
+        weekdays : relativeWeekDay,
+        weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'),
+        weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'YYYY-MM-DD',
+            LL : 'YYYY [m.] MMMM D [d.]',
+            LLL : 'YYYY [m.] MMMM D [d.], LT [val.]',
+            LLLL : 'YYYY [m.] MMMM D [d.], dddd, LT [val.]',
+            l : 'YYYY-MM-DD',
+            ll : 'YYYY [m.] MMMM D [d.]',
+            lll : 'YYYY [m.] MMMM D [d.], LT [val.]',
+            llll : 'YYYY [m.] MMMM D [d.], ddd, LT [val.]'
+        },
+        calendar : {
+            sameDay : '[Šiandien] LT',
+            nextDay : '[Rytoj] LT',
+            nextWeek : 'dddd LT',
+            lastDay : '[Vakar] LT',
+            lastWeek : '[Praėjusį] dddd LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'po %s',
+            past : 'prieš %s',
+            s : translateSeconds,
+            m : translateSingular,
+            mm : translate,
+            h : translateSingular,
+            hh : translate,
+            d : translateSingular,
+            dd : translate,
+            M : translateSingular,
+            MM : translate,
+            y : translateSingular,
+            yy : translate
+        },
+        ordinal : function (number) {
+            return number + '-oji';
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/lv.js b/resources/lib/moment/locale/lv.js
new file mode 100644 (file)
index 0000000..7e1892e
--- /dev/null
@@ -0,0 +1,77 @@
+// moment.js locale configuration
+// locale : latvian (lv)
+// author : Kristaps Karlsons : https://github.com/skakri
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var units = {
+        'mm': 'minūti_minūtes_minūte_minūtes',
+        'hh': 'stundu_stundas_stunda_stundas',
+        'dd': 'dienu_dienas_diena_dienas',
+        'MM': 'mēnesi_mēnešus_mēnesis_mēneši',
+        'yy': 'gadu_gadus_gads_gadi'
+    };
+
+    function format(word, number, withoutSuffix) {
+        var forms = word.split('_');
+        if (withoutSuffix) {
+            return number % 10 === 1 && number !== 11 ? forms[2] : forms[3];
+        } else {
+            return number % 10 === 1 && number !== 11 ? forms[0] : forms[1];
+        }
+    }
+
+    function relativeTimeWithPlural(number, withoutSuffix, key) {
+        return number + ' ' + format(units[key], number, withoutSuffix);
+    }
+
+    return moment.defineLocale('lv', {
+        months : 'janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec'.split('_'),
+        weekdays : 'svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena'.split('_'),
+        weekdaysShort : 'Sv_P_O_T_C_Pk_S'.split('_'),
+        weekdaysMin : 'Sv_P_O_T_C_Pk_S'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD.MM.YYYY',
+            LL : 'YYYY. [gada] D. MMMM',
+            LLL : 'YYYY. [gada] D. MMMM, LT',
+            LLLL : 'YYYY. [gada] D. MMMM, dddd, LT'
+        },
+        calendar : {
+            sameDay : '[Šodien pulksten] LT',
+            nextDay : '[Rīt pulksten] LT',
+            nextWeek : 'dddd [pulksten] LT',
+            lastDay : '[Vakar pulksten] LT',
+            lastWeek : '[Pagājušā] dddd [pulksten] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s vēlāk',
+            past : '%s agrāk',
+            s : 'dažas sekundes',
+            m : 'minūti',
+            mm : relativeTimeWithPlural,
+            h : 'stundu',
+            hh : relativeTimeWithPlural,
+            d : 'dienu',
+            dd : relativeTimeWithPlural,
+            M : 'mēnesi',
+            MM : relativeTimeWithPlural,
+            y : 'gadu',
+            yy : relativeTimeWithPlural
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/mk.js b/resources/lib/moment/locale/mk.js
new file mode 100644 (file)
index 0000000..94c7fc1
--- /dev/null
@@ -0,0 +1,86 @@
+// moment.js locale configuration
+// locale : macedonian (mk)
+// author : Borislav Mickov : https://github.com/B0k0
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('mk', {
+        months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'),
+        monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'),
+        weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'),
+        weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'),
+        weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            L : 'D.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : '[Денес во] LT',
+            nextDay : '[Утре во] LT',
+            nextWeek : 'dddd [во] LT',
+            lastDay : '[Вчера во] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 6:
+                    return '[Во изминатата] dddd [во] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[Во изминатиот] dddd [во] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'после %s',
+            past : 'пред %s',
+            s : 'неколку секунди',
+            m : 'минута',
+            mm : '%d минути',
+            h : 'час',
+            hh : '%d часа',
+            d : 'ден',
+            dd : '%d дена',
+            M : 'месец',
+            MM : '%d месеци',
+            y : 'година',
+            yy : '%d години'
+        },
+        ordinal : function (number) {
+            var lastDigit = number % 10,
+                last2Digits = number % 100;
+            if (number === 0) {
+                return number + '-ев';
+            } else if (last2Digits === 0) {
+                return number + '-ен';
+            } else if (last2Digits > 10 && last2Digits < 20) {
+                return number + '-ти';
+            } else if (lastDigit === 1) {
+                return number + '-ви';
+            } else if (lastDigit === 2) {
+                return number + '-ри';
+            } else if (lastDigit === 7 || lastDigit === 8) {
+                return number + '-ми';
+            } else {
+                return number + '-ти';
+            }
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ml.js b/resources/lib/moment/locale/ml.js
new file mode 100644 (file)
index 0000000..ea4d949
--- /dev/null
@@ -0,0 +1,64 @@
+// moment.js locale configuration
+// locale : malayalam (ml)
+// author : Floyd Pink : https://github.com/floydpink
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('ml', {
+        months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'),
+        monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'),
+        weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'),
+        weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'),
+        weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'),
+        longDateFormat : {
+            LT : 'A h:mm -നു',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, LT',
+            LLLL : 'dddd, D MMMM YYYY, LT'
+        },
+        calendar : {
+            sameDay : '[ഇന്ന്] LT',
+            nextDay : '[നാളെ] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[ഇന്നലെ] LT',
+            lastWeek : '[കഴിഞ്ഞ] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s കഴിഞ്ഞ്',
+            past : '%s മുൻപ്',
+            s : 'അൽപ നിമിഷങ്ങൾ',
+            m : 'ഒരു മിനിറ്റ്',
+            mm : '%d മിനിറ്റ്',
+            h : 'ഒരു മണിക്കൂർ',
+            hh : '%d മണിക്കൂർ',
+            d : 'ഒരു ദിവസം',
+            dd : '%d ദിവസം',
+            M : 'ഒരു മാസം',
+            MM : '%d മാസം',
+            y : 'ഒരു വർഷം',
+            yy : '%d വർഷം'
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'രാത്രി';
+            } else if (hour < 12) {
+                return 'രാവിലെ';
+            } else if (hour < 17) {
+                return 'ഉച്ച കഴിഞ്ഞ്';
+            } else if (hour < 20) {
+                return 'വൈകുന്നേരം';
+            } else {
+                return 'രാത്രി';
+            }
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/mr.js b/resources/lib/moment/locale/mr.js
new file mode 100644 (file)
index 0000000..141eaf8
--- /dev/null
@@ -0,0 +1,104 @@
+// moment.js locale configuration
+// locale : Marathi (mr)
+// author : Harshad Kale : https://github.com/kalehv
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '१',
+        '2': '२',
+        '3': '३',
+        '4': '४',
+        '5': '५',
+        '6': '६',
+        '7': '७',
+        '8': '८',
+        '9': '९',
+        '0': '०'
+    },
+    numberMap = {
+        '१': '1',
+        '२': '2',
+        '३': '3',
+        '४': '4',
+        '५': '5',
+        '६': '6',
+        '७': '7',
+        '८': '8',
+        '९': '9',
+        '०': '0'
+    };
+
+    return moment.defineLocale('mr', {
+        months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'),
+        monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'),
+        weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
+        weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'),
+        weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
+        longDateFormat : {
+            LT : 'A h:mm वाजता',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, LT',
+            LLLL : 'dddd, D MMMM YYYY, LT'
+        },
+        calendar : {
+            sameDay : '[आज] LT',
+            nextDay : '[उद्या] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[काल] LT',
+            lastWeek: '[मागील] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s नंतर',
+            past : '%s पूर्वी',
+            s : 'सेकंद',
+            m: 'एक मिनिट',
+            mm: '%d मिनिटे',
+            h : 'एक तास',
+            hh : '%d तास',
+            d : 'एक दिवस',
+            dd : '%d दिवस',
+            M : 'एक महिना',
+            MM : '%d महिने',
+            y : 'एक वर्ष',
+            yy : '%d वर्षे'
+        },
+        preparse: function (string) {
+            return string.replace(/[१२३४५६७८९०]/g, function (match) {
+                return numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            });
+        },
+        meridiem: function (hour, minute, isLower)
+        {
+            if (hour < 4) {
+                return 'रात्री';
+            } else if (hour < 10) {
+                return 'सकाळी';
+            } else if (hour < 17) {
+                return 'दुपारी';
+            } else if (hour < 20) {
+                return 'सायंकाळी';
+            } else {
+                return 'रात्री';
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ms-my.js b/resources/lib/moment/locale/ms-my.js
new file mode 100644 (file)
index 0000000..7efcbaa
--- /dev/null
@@ -0,0 +1,66 @@
+// moment.js locale configuration
+// locale : Bahasa Malaysia (ms-MY)
+// author : Weldan Jamili : https://github.com/weldan
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('ms-my', {
+        months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'),
+        monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
+        weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
+        weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
+        weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
+        longDateFormat : {
+            LT : 'HH.mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY [pukul] LT',
+            LLLL : 'dddd, D MMMM YYYY [pukul] LT'
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 11) {
+                return 'pagi';
+            } else if (hours < 15) {
+                return 'tengahari';
+            } else if (hours < 19) {
+                return 'petang';
+            } else {
+                return 'malam';
+            }
+        },
+        calendar : {
+            sameDay : '[Hari ini pukul] LT',
+            nextDay : '[Esok pukul] LT',
+            nextWeek : 'dddd [pukul] LT',
+            lastDay : '[Kelmarin pukul] LT',
+            lastWeek : 'dddd [lepas pukul] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'dalam %s',
+            past : '%s yang lepas',
+            s : 'beberapa saat',
+            m : 'seminit',
+            mm : '%d minit',
+            h : 'sejam',
+            hh : '%d jam',
+            d : 'sehari',
+            dd : '%d hari',
+            M : 'sebulan',
+            MM : '%d bulan',
+            y : 'setahun',
+            yy : '%d tahun'
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/my.js b/resources/lib/moment/locale/my.js
new file mode 100644 (file)
index 0000000..138d101
--- /dev/null
@@ -0,0 +1,88 @@
+// moment.js locale configuration
+// locale : Burmese (my)
+// author : Squar team, mysquar.com
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '၁',
+        '2': '၂',
+        '3': '၃',
+        '4': '၄',
+        '5': '၅',
+        '6': '၆',
+        '7': '၇',
+        '8': '၈',
+        '9': '၉',
+        '0': '၀'
+    }, numberMap = {
+        '၁': '1',
+        '၂': '2',
+        '၃': '3',
+        '၄': '4',
+        '၅': '5',
+        '၆': '6',
+        '၇': '7',
+        '၈': '8',
+        '၉': '9',
+        '၀': '0'
+    };
+    return moment.defineLocale('my', {
+        months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'),
+        monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'),
+        weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'),
+        weekdaysShort: 'နွေ_လာ_င်္ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
+        weekdaysMin: 'နွေ_လာ_င်္ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
+        longDateFormat: {
+            LT: 'HH:mm',
+            L: 'DD/MM/YYYY',
+            LL: 'D MMMM YYYY',
+            LLL: 'D MMMM YYYY LT',
+            LLLL: 'dddd D MMMM YYYY LT'
+        },
+        calendar: {
+            sameDay: '[ယနေ.] LT [မှာ]',
+            nextDay: '[မနက်ဖြန်] LT [မှာ]',
+            nextWeek: 'dddd LT [မှာ]',
+            lastDay: '[မနေ.က] LT [မှာ]',
+            lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]',
+            sameElse: 'L'
+        },
+        relativeTime: {
+            future: 'လာမည့် %s မှာ',
+            past: 'လွန်ခဲ့သော %s က',
+            s: 'စက္ကန်.အနည်းငယ်',
+            m: 'တစ်မိနစ်',
+            mm: '%d မိနစ်',
+            h: 'တစ်နာရီ',
+            hh: '%d နာရီ',
+            d: 'တစ်ရက်',
+            dd: '%d ရက်',
+            M: 'တစ်လ',
+            MM: '%d လ',
+            y: 'တစ်နှစ်',
+            yy: '%d နှစ်'
+        },
+        preparse: function (string) {
+            return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) {
+                return numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            });
+        },
+        week: {
+            dow: 1, // Monday is the first day of the week.
+            doy: 4 // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/nb.js b/resources/lib/moment/locale/nb.js
new file mode 100644 (file)
index 0000000..533659d
--- /dev/null
@@ -0,0 +1,57 @@
+// moment.js locale configuration
+// locale : norwegian bokmål (nb)
+// authors : Espen Hovlandsdal : https://github.com/rexxars
+//           Sigurd Gartmann : https://github.com/sigurdga
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('nb', {
+        months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
+        weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
+        weekdaysShort : 'søn_man_tirs_ons_tors_fre_lør'.split('_'),
+        weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
+        longDateFormat : {
+            LT : 'H.mm',
+            L : 'DD.MM.YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY [kl.] LT',
+            LLLL : 'dddd D. MMMM YYYY [kl.] LT'
+        },
+        calendar : {
+            sameDay: '[i dag kl.] LT',
+            nextDay: '[i morgen kl.] LT',
+            nextWeek: 'dddd [kl.] LT',
+            lastDay: '[i går kl.] LT',
+            lastWeek: '[forrige] dddd [kl.] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'om %s',
+            past : 'for %s siden',
+            s : 'noen sekunder',
+            m : 'ett minutt',
+            mm : '%d minutter',
+            h : 'en time',
+            hh : '%d timer',
+            d : 'en dag',
+            dd : '%d dager',
+            M : 'en måned',
+            MM : '%d måneder',
+            y : 'ett år',
+            yy : '%d år'
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ne.js b/resources/lib/moment/locale/ne.js
new file mode 100644 (file)
index 0000000..51629eb
--- /dev/null
@@ -0,0 +1,105 @@
+// moment.js locale configuration
+// locale : nepali/nepalese
+// author : suvash : https://github.com/suvash
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '१',
+        '2': '२',
+        '3': '३',
+        '4': '४',
+        '5': '५',
+        '6': '६',
+        '7': '७',
+        '8': '८',
+        '9': '९',
+        '0': '०'
+    },
+    numberMap = {
+        '१': '1',
+        '२': '2',
+        '३': '3',
+        '४': '4',
+        '५': '5',
+        '६': '6',
+        '७': '7',
+        '८': '8',
+        '९': '9',
+        '०': '0'
+    };
+
+    return moment.defineLocale('ne', {
+        months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'),
+        monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'),
+        weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'),
+        weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'),
+        weekdaysMin : 'आइ._सो._मङ्_बु._बि._शु._श.'.split('_'),
+        longDateFormat : {
+            LT : 'Aको h:mm बजे',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, LT',
+            LLLL : 'dddd, D MMMM YYYY, LT'
+        },
+        preparse: function (string) {
+            return string.replace(/[१२३४५६७८९०]/g, function (match) {
+                return numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            });
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 3) {
+                return 'राती';
+            } else if (hour < 10) {
+                return 'बिहान';
+            } else if (hour < 15) {
+                return 'दिउँसो';
+            } else if (hour < 18) {
+                return 'बेलुका';
+            } else if (hour < 20) {
+                return 'साँझ';
+            } else {
+                return 'राती';
+            }
+        },
+        calendar : {
+            sameDay : '[आज] LT',
+            nextDay : '[भोली] LT',
+            nextWeek : '[आउँदो] dddd[,] LT',
+            lastDay : '[हिजो] LT',
+            lastWeek : '[गएको] dddd[,] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%sमा',
+            past : '%s अगाडी',
+            s : 'केही समय',
+            m : 'एक मिनेट',
+            mm : '%d मिनेट',
+            h : 'एक घण्टा',
+            hh : '%d घण्टा',
+            d : 'एक दिन',
+            dd : '%d दिन',
+            M : 'एक महिना',
+            MM : '%d महिना',
+            y : 'एक बर्ष',
+            yy : '%d बर्ष'
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/nl.js b/resources/lib/moment/locale/nl.js
new file mode 100644 (file)
index 0000000..213beeb
--- /dev/null
@@ -0,0 +1,67 @@
+// moment.js locale configuration
+// locale : dutch (nl)
+// author : Joris Röling : https://github.com/jjupiter
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_'),
+        monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_');
+
+    return moment.defineLocale('nl', {
+        months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'),
+        monthsShort : function (m, format) {
+            if (/-MMM-/.test(format)) {
+                return monthsShortWithoutDots[m.month()];
+            } else {
+                return monthsShortWithDots[m.month()];
+            }
+        },
+        weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'),
+        weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'),
+        weekdaysMin : 'Zo_Ma_Di_Wo_Do_Vr_Za'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD-MM-YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[vandaag om] LT',
+            nextDay: '[morgen om] LT',
+            nextWeek: 'dddd [om] LT',
+            lastDay: '[gisteren om] LT',
+            lastWeek: '[afgelopen] dddd [om] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'over %s',
+            past : '%s geleden',
+            s : 'een paar seconden',
+            m : 'één minuut',
+            mm : '%d minuten',
+            h : 'één uur',
+            hh : '%d uur',
+            d : 'één dag',
+            dd : '%d dagen',
+            M : 'één maand',
+            MM : '%d maanden',
+            y : 'één jaar',
+            yy : '%d jaar'
+        },
+        ordinal : function (number) {
+            return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/nn.js b/resources/lib/moment/locale/nn.js
new file mode 100644 (file)
index 0000000..c5b6505
--- /dev/null
@@ -0,0 +1,56 @@
+// moment.js locale configuration
+// locale : norwegian nynorsk (nn)
+// author : https://github.com/mechuwind
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('nn', {
+        months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
+        weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'),
+        weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'),
+        weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[I dag klokka] LT',
+            nextDay: '[I morgon klokka] LT',
+            nextWeek: 'dddd [klokka] LT',
+            lastDay: '[I går klokka] LT',
+            lastWeek: '[Føregåande] dddd [klokka] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'om %s',
+            past : 'for %s sidan',
+            s : 'nokre sekund',
+            m : 'eit minutt',
+            mm : '%d minutt',
+            h : 'ein time',
+            hh : '%d timar',
+            d : 'ein dag',
+            dd : '%d dagar',
+            M : 'ein månad',
+            MM : '%d månader',
+            y : 'eit år',
+            yy : '%d år'
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/pl.js b/resources/lib/moment/locale/pl.js
new file mode 100644 (file)
index 0000000..63a62f1
--- /dev/null
@@ -0,0 +1,98 @@
+// moment.js locale configuration
+// locale : polish (pl)
+// author : Rafal Hirsz : https://github.com/evoL
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_'),
+        monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split('_');
+
+    function plural(n) {
+        return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1);
+    }
+
+    function translate(number, withoutSuffix, key) {
+        var result = number + ' ';
+        switch (key) {
+        case 'm':
+            return withoutSuffix ? 'minuta' : 'minutę';
+        case 'mm':
+            return result + (plural(number) ? 'minuty' : 'minut');
+        case 'h':
+            return withoutSuffix  ? 'godzina'  : 'godzinę';
+        case 'hh':
+            return result + (plural(number) ? 'godziny' : 'godzin');
+        case 'MM':
+            return result + (plural(number) ? 'miesiące' : 'miesięcy');
+        case 'yy':
+            return result + (plural(number) ? 'lata' : 'lat');
+        }
+    }
+
+    return moment.defineLocale('pl', {
+        months : function (momentToFormat, format) {
+            if (/D MMMM/.test(format)) {
+                return monthsSubjective[momentToFormat.month()];
+            } else {
+                return monthsNominative[momentToFormat.month()];
+            }
+        },
+        monthsShort : 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'),
+        weekdays : 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split('_'),
+        weekdaysShort : 'nie_pon_wt_śr_czw_pt_sb'.split('_'),
+        weekdaysMin : 'N_Pn_Wt_Śr_Cz_Pt_So'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[Dziś o] LT',
+            nextDay: '[Jutro o] LT',
+            nextWeek: '[W] dddd [o] LT',
+            lastDay: '[Wczoraj o] LT',
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[W zeszłą niedzielę o] LT';
+                case 3:
+                    return '[W zeszłą środę o] LT';
+                case 6:
+                    return '[W zeszłą sobotę o] LT';
+                default:
+                    return '[W zeszły] dddd [o] LT';
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past : '%s temu',
+            s : 'kilka sekund',
+            m : translate,
+            mm : translate,
+            h : translate,
+            hh : translate,
+            d : '1 dzień',
+            dd : '%d dni',
+            M : 'miesiąc',
+            MM : translate,
+            y : 'rok',
+            yy : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/pt-br.js b/resources/lib/moment/locale/pt-br.js
new file mode 100644 (file)
index 0000000..44eedaf
--- /dev/null
@@ -0,0 +1,56 @@
+// moment.js locale configuration
+// locale : brazilian portuguese (pt-br)
+// author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('pt-br', {
+        months : 'janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro'.split('_'),
+        monthsShort : 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_'),
+        weekdays : 'domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado'.split('_'),
+        weekdaysShort : 'dom_seg_ter_qua_qui_sex_sáb'.split('_'),
+        weekdaysMin : 'dom_2ª_3ª_4ª_5ª_6ª_sáb'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D [de] MMMM [de] YYYY',
+            LLL : 'D [de] MMMM [de] YYYY [às] LT',
+            LLLL : 'dddd, D [de] MMMM [de] YYYY [às] LT'
+        },
+        calendar : {
+            sameDay: '[Hoje às] LT',
+            nextDay: '[Amanhã às] LT',
+            nextWeek: 'dddd [às] LT',
+            lastDay: '[Ontem às] LT',
+            lastWeek: function () {
+                return (this.day() === 0 || this.day() === 6) ?
+                    '[Último] dddd [às] LT' : // Saturday + Sunday
+                    '[Última] dddd [às] LT'; // Monday - Friday
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'em %s',
+            past : '%s atrás',
+            s : 'segundos',
+            m : 'um minuto',
+            mm : '%d minutos',
+            h : 'uma hora',
+            hh : '%d horas',
+            d : 'um dia',
+            dd : '%d dias',
+            M : 'um mês',
+            MM : '%d meses',
+            y : 'um ano',
+            yy : '%d anos'
+        },
+        ordinal : '%dº'
+    });
+}));
diff --git a/resources/lib/moment/locale/pt.js b/resources/lib/moment/locale/pt.js
new file mode 100644 (file)
index 0000000..aced692
--- /dev/null
@@ -0,0 +1,60 @@
+// moment.js locale configuration
+// locale : portuguese (pt)
+// author : Jefferson : https://github.com/jalex79
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('pt', {
+        months : 'janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro'.split('_'),
+        monthsShort : 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_'),
+        weekdays : 'domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado'.split('_'),
+        weekdaysShort : 'dom_seg_ter_qua_qui_sex_sáb'.split('_'),
+        weekdaysMin : 'dom_2ª_3ª_4ª_5ª_6ª_sáb'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D [de] MMMM [de] YYYY',
+            LLL : 'D [de] MMMM [de] YYYY LT',
+            LLLL : 'dddd, D [de] MMMM [de] YYYY LT'
+        },
+        calendar : {
+            sameDay: '[Hoje às] LT',
+            nextDay: '[Amanhã às] LT',
+            nextWeek: 'dddd [às] LT',
+            lastDay: '[Ontem às] LT',
+            lastWeek: function () {
+                return (this.day() === 0 || this.day() === 6) ?
+                    '[Último] dddd [às] LT' : // Saturday + Sunday
+                    '[Última] dddd [às] LT'; // Monday - Friday
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'em %s',
+            past : 'há %s',
+            s : 'segundos',
+            m : 'um minuto',
+            mm : '%d minutos',
+            h : 'uma hora',
+            hh : '%d horas',
+            d : 'um dia',
+            dd : '%d dias',
+            M : 'um mês',
+            MM : '%d meses',
+            y : 'um ano',
+            yy : '%d anos'
+        },
+        ordinal : '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ro.js b/resources/lib/moment/locale/ro.js
new file mode 100644 (file)
index 0000000..dc34d3c
--- /dev/null
@@ -0,0 +1,72 @@
+// moment.js locale configuration
+// locale : romanian (ro)
+// author : Vlad Gurdiga : https://github.com/gurdiga
+// author : Valentin Agachi : https://github.com/avaly
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function relativeTimeWithPlural(number, withoutSuffix, key) {
+        var format = {
+                'mm': 'minute',
+                'hh': 'ore',
+                'dd': 'zile',
+                'MM': 'luni',
+                'yy': 'ani'
+            },
+            separator = ' ';
+        if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) {
+            separator = ' de ';
+        }
+
+        return number + separator + format[key];
+    }
+
+    return moment.defineLocale('ro', {
+        months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'),
+        monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split('_'),
+        weekdays : 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'),
+        weekdaysShort : 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'),
+        weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY H:mm',
+            LLLL : 'dddd, D MMMM YYYY H:mm'
+        },
+        calendar : {
+            sameDay: '[azi la] LT',
+            nextDay: '[mâine la] LT',
+            nextWeek: 'dddd [la] LT',
+            lastDay: '[ieri la] LT',
+            lastWeek: '[fosta] dddd [la] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'peste %s',
+            past : '%s în urmă',
+            s : 'câteva secunde',
+            m : 'un minut',
+            mm : relativeTimeWithPlural,
+            h : 'o oră',
+            hh : relativeTimeWithPlural,
+            d : 'o zi',
+            dd : relativeTimeWithPlural,
+            M : 'o lună',
+            MM : relativeTimeWithPlural,
+            y : 'un an',
+            yy : relativeTimeWithPlural
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ru.js b/resources/lib/moment/locale/ru.js
new file mode 100644 (file)
index 0000000..2f15233
--- /dev/null
@@ -0,0 +1,166 @@
+// moment.js locale configuration
+// locale : russian (ru)
+// author : Viktorminator : https://github.com/Viktorminator
+// Author : Menelion Elensúle : https://github.com/Oire
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function plural(word, num) {
+        var forms = word.split('_');
+        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+    }
+
+    function relativeTimeWithPlural(number, withoutSuffix, key) {
+        var format = {
+            'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут',
+            'hh': 'час_часа_часов',
+            'dd': 'день_дня_дней',
+            'MM': 'месяц_месяца_месяцев',
+            'yy': 'год_года_лет'
+        };
+        if (key === 'm') {
+            return withoutSuffix ? 'минута' : 'минуту';
+        }
+        else {
+            return number + ' ' + plural(format[key], +number);
+        }
+    }
+
+    function monthsCaseReplace(m, format) {
+        var months = {
+            'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'),
+            'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_')
+        },
+
+        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return months[nounCase][m.month()];
+    }
+
+    function monthsShortCaseReplace(m, format) {
+        var monthsShort = {
+            'nominative': 'янв_фев_мар_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'),
+            'accusative': 'янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек'.split('_')
+        },
+
+        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return monthsShort[nounCase][m.month()];
+    }
+
+    function weekdaysCaseReplace(m, format) {
+        var weekdays = {
+            'nominative': 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'),
+            'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_')
+        },
+
+        nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую)? ?\] ?dddd/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return weekdays[nounCase][m.day()];
+    }
+
+    return moment.defineLocale('ru', {
+        months : monthsCaseReplace,
+        monthsShort : monthsShortCaseReplace,
+        weekdays : weekdaysCaseReplace,
+        weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
+        weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
+        monthsParse : [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[й|я]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i],
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY г.',
+            LLL : 'D MMMM YYYY г., LT',
+            LLLL : 'dddd, D MMMM YYYY г., LT'
+        },
+        calendar : {
+            sameDay: '[Сегодня в] LT',
+            nextDay: '[Завтра в] LT',
+            lastDay: '[Вчера в] LT',
+            nextWeek: function () {
+                return this.day() === 2 ? '[Во] dddd [в] LT' : '[В] dddd [в] LT';
+            },
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[В прошлое] dddd [в] LT';
+                case 1:
+                case 2:
+                case 4:
+                    return '[В прошлый] dddd [в] LT';
+                case 3:
+                case 5:
+                case 6:
+                    return '[В прошлую] dddd [в] LT';
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'через %s',
+            past : '%s назад',
+            s : 'несколько секунд',
+            m : relativeTimeWithPlural,
+            mm : relativeTimeWithPlural,
+            h : 'час',
+            hh : relativeTimeWithPlural,
+            d : 'день',
+            dd : relativeTimeWithPlural,
+            M : 'месяц',
+            MM : relativeTimeWithPlural,
+            y : 'год',
+            yy : relativeTimeWithPlural
+        },
+
+        meridiemParse: /ночи|утра|дня|вечера/i,
+        isPM : function (input) {
+            return /^(дня|вечера)$/.test(input);
+        },
+
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'ночи';
+            } else if (hour < 12) {
+                return 'утра';
+            } else if (hour < 17) {
+                return 'дня';
+            } else {
+                return 'вечера';
+            }
+        },
+
+        ordinal: function (number, period) {
+            switch (period) {
+            case 'M':
+            case 'd':
+            case 'DDD':
+                return number + '-й';
+            case 'D':
+                return number + '-го';
+            case 'w':
+            case 'W':
+                return number + '-я';
+            default:
+                return number;
+            }
+        },
+
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/sk.js b/resources/lib/moment/locale/sk.js
new file mode 100644 (file)
index 0000000..991afeb
--- /dev/null
@@ -0,0 +1,156 @@
+// moment.js locale configuration
+// locale : slovak (sk)
+// author : Martin Minka : https://github.com/k2s
+// based on work of petrbela : https://github.com/petrbela
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_'),
+        monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_');
+
+    function plural(n) {
+        return (n > 1) && (n < 5);
+    }
+
+    function translate(number, withoutSuffix, key, isFuture) {
+        var result = number + ' ';
+        switch (key) {
+        case 's':  // a few seconds / in a few seconds / a few seconds ago
+            return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami';
+        case 'm':  // a minute / in a minute / a minute ago
+            return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou');
+        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'minúty' : 'minút');
+            } else {
+                return result + 'minútami';
+            }
+            break;
+        case 'h':  // an hour / in an hour / an hour ago
+            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
+        case 'hh': // 9 hours / in 9 hours / 9 hours ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'hodiny' : 'hodín');
+            } else {
+                return result + 'hodinami';
+            }
+            break;
+        case 'd':  // a day / in a day / a day ago
+            return (withoutSuffix || isFuture) ? 'deň' : 'dňom';
+        case 'dd': // 9 days / in 9 days / 9 days ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'dni' : 'dní');
+            } else {
+                return result + 'dňami';
+            }
+            break;
+        case 'M':  // a month / in a month / a month ago
+            return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom';
+        case 'MM': // 9 months / in 9 months / 9 months ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'mesiace' : 'mesiacov');
+            } else {
+                return result + 'mesiacmi';
+            }
+            break;
+        case 'y':  // a year / in a year / a year ago
+            return (withoutSuffix || isFuture) ? 'rok' : 'rokom';
+        case 'yy': // 9 years / in 9 years / 9 years ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'roky' : 'rokov');
+            } else {
+                return result + 'rokmi';
+            }
+            break;
+        }
+    }
+
+    return moment.defineLocale('sk', {
+        months : months,
+        monthsShort : monthsShort,
+        monthsParse : (function (months, monthsShort) {
+            var i, _monthsParse = [];
+            for (i = 0; i < 12; i++) {
+                // use custom parser to solve problem with July (červenec)
+                _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
+            }
+            return _monthsParse;
+        }(months, monthsShort)),
+        weekdays : 'nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota'.split('_'),
+        weekdaysShort : 'ne_po_ut_st_št_pi_so'.split('_'),
+        weekdaysMin : 'ne_po_ut_st_št_pi_so'.split('_'),
+        longDateFormat : {
+            LT: 'H:mm',
+            L : 'DD.MM.YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY LT',
+            LLLL : 'dddd D. MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[dnes o] LT',
+            nextDay: '[zajtra o] LT',
+            nextWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[v nedeľu o] LT';
+                case 1:
+                case 2:
+                    return '[v] dddd [o] LT';
+                case 3:
+                    return '[v stredu o] LT';
+                case 4:
+                    return '[vo štvrtok o] LT';
+                case 5:
+                    return '[v piatok o] LT';
+                case 6:
+                    return '[v sobotu o] LT';
+                }
+            },
+            lastDay: '[včera o] LT',
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[minulú nedeľu o] LT';
+                case 1:
+                case 2:
+                    return '[minulý] dddd [o] LT';
+                case 3:
+                    return '[minulú stredu o] LT';
+                case 4:
+                case 5:
+                    return '[minulý] dddd [o] LT';
+                case 6:
+                    return '[minulú sobotu o] LT';
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past : 'pred %s',
+            s : translate,
+            m : translate,
+            mm : translate,
+            h : translate,
+            hh : translate,
+            d : translate,
+            dd : translate,
+            M : translate,
+            MM : translate,
+            y : translate,
+            yy : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/sl.js b/resources/lib/moment/locale/sl.js
new file mode 100644 (file)
index 0000000..2bdbf1c
--- /dev/null
@@ -0,0 +1,144 @@
+// moment.js locale configuration
+// locale : slovenian (sl)
+// author : Robert Sedovšek : https://github.com/sedovsek
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function translate(number, withoutSuffix, key) {
+        var result = number + ' ';
+        switch (key) {
+        case 'm':
+            return withoutSuffix ? 'ena minuta' : 'eno minuto';
+        case 'mm':
+            if (number === 1) {
+                result += 'minuta';
+            } else if (number === 2) {
+                result += 'minuti';
+            } else if (number === 3 || number === 4) {
+                result += 'minute';
+            } else {
+                result += 'minut';
+            }
+            return result;
+        case 'h':
+            return withoutSuffix ? 'ena ura' : 'eno uro';
+        case 'hh':
+            if (number === 1) {
+                result += 'ura';
+            } else if (number === 2) {
+                result += 'uri';
+            } else if (number === 3 || number === 4) {
+                result += 'ure';
+            } else {
+                result += 'ur';
+            }
+            return result;
+        case 'dd':
+            if (number === 1) {
+                result += 'dan';
+            } else {
+                result += 'dni';
+            }
+            return result;
+        case 'MM':
+            if (number === 1) {
+                result += 'mesec';
+            } else if (number === 2) {
+                result += 'meseca';
+            } else if (number === 3 || number === 4) {
+                result += 'mesece';
+            } else {
+                result += 'mesecev';
+            }
+            return result;
+        case 'yy':
+            if (number === 1) {
+                result += 'leto';
+            } else if (number === 2) {
+                result += 'leti';
+            } else if (number === 3 || number === 4) {
+                result += 'leta';
+            } else {
+                result += 'let';
+            }
+            return result;
+        }
+    }
+
+    return moment.defineLocale('sl', {
+        months : 'januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december'.split('_'),
+        monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'),
+        weekdays : 'nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota'.split('_'),
+        weekdaysShort : 'ned._pon._tor._sre._čet._pet._sob.'.split('_'),
+        weekdaysMin : 'ne_po_to_sr_če_pe_so'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            L : 'DD. MM. YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY LT',
+            LLLL : 'dddd, D. MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay  : '[danes ob] LT',
+            nextDay  : '[jutri ob] LT',
+
+            nextWeek : function () {
+                switch (this.day()) {
+                case 0:
+                    return '[v] [nedeljo] [ob] LT';
+                case 3:
+                    return '[v] [sredo] [ob] LT';
+                case 6:
+                    return '[v] [soboto] [ob] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[v] dddd [ob] LT';
+                }
+            },
+            lastDay  : '[včeraj ob] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 6:
+                    return '[prejšnja] dddd [ob] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[prejšnji] dddd [ob] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'čez %s',
+            past   : '%s nazaj',
+            s      : 'nekaj sekund',
+            m      : translate,
+            mm     : translate,
+            h      : translate,
+            hh     : translate,
+            d      : 'en dan',
+            dd     : translate,
+            M      : 'en mesec',
+            MM     : translate,
+            y      : 'eno leto',
+            yy     : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/sq.js b/resources/lib/moment/locale/sq.js
new file mode 100644 (file)
index 0000000..6ae4178
--- /dev/null
@@ -0,0 +1,61 @@
+// moment.js locale configuration
+// locale : Albanian (sq)
+// author : Flakërim Ismani : https://github.com/flakerimi
+// author: Menelion Elensúle: https://github.com/Oire (tests)
+// author : Oerd Cukalla : https://github.com/oerd (fixes)
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('sq', {
+        months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'),
+        monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'),
+        weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'),
+        weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'),
+        weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'),
+        meridiem : function (hours, minutes, isLower) {
+            return hours < 12 ? 'PD' : 'MD';
+        },
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : '[Sot në] LT',
+            nextDay : '[Nesër në] LT',
+            nextWeek : 'dddd [në] LT',
+            lastDay : '[Dje në] LT',
+            lastWeek : 'dddd [e kaluar në] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'në %s',
+            past : '%s më parë',
+            s : 'disa sekonda',
+            m : 'një minutë',
+            mm : '%d minuta',
+            h : 'një orë',
+            hh : '%d orë',
+            d : 'një ditë',
+            dd : '%d ditë',
+            M : 'një muaj',
+            MM : '%d muaj',
+            y : 'një vit',
+            yy : '%d vite'
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/sr-cyrl.js b/resources/lib/moment/locale/sr-cyrl.js
new file mode 100644 (file)
index 0000000..7278de6
--- /dev/null
@@ -0,0 +1,105 @@
+// moment.js locale configuration
+// locale : Serbian-cyrillic (sr-cyrl)
+// author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var translator = {
+        words: { //Different grammatical cases
+            m: ['један минут', 'једне минуте'],
+            mm: ['минут', 'минуте', 'минута'],
+            h: ['један сат', 'једног сата'],
+            hh: ['сат', 'сата', 'сати'],
+            dd: ['дан', 'дана', 'дана'],
+            MM: ['месец', 'месеца', 'месеци'],
+            yy: ['година', 'године', 'година']
+        },
+        correctGrammaticalCase: function (number, wordKey) {
+            return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
+        },
+        translate: function (number, withoutSuffix, key) {
+            var wordKey = translator.words[key];
+            if (key.length === 1) {
+                return withoutSuffix ? wordKey[0] : wordKey[1];
+            } else {
+                return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
+            }
+        }
+    };
+
+    return moment.defineLocale('sr-cyrl', {
+        months: ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'],
+        monthsShort: ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'],
+        weekdays: ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'],
+        weekdaysShort: ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'],
+        weekdaysMin: ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'],
+        longDateFormat: {
+            LT: 'H:mm',
+            L: 'DD. MM. YYYY',
+            LL: 'D. MMMM YYYY',
+            LLL: 'D. MMMM YYYY LT',
+            LLLL: 'dddd, D. MMMM YYYY LT'
+        },
+        calendar: {
+            sameDay: '[данас у] LT',
+            nextDay: '[сутра у] LT',
+
+            nextWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[у] [недељу] [у] LT';
+                case 3:
+                    return '[у] [среду] [у] LT';
+                case 6:
+                    return '[у] [суботу] [у] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[у] dddd [у] LT';
+                }
+            },
+            lastDay  : '[јуче у] LT',
+            lastWeek : function () {
+                var lastWeekDays = [
+                    '[прошле] [недеље] [у] LT',
+                    '[прошлог] [понедељка] [у] LT',
+                    '[прошлог] [уторка] [у] LT',
+                    '[прошле] [среде] [у] LT',
+                    '[прошлог] [четвртка] [у] LT',
+                    '[прошлог] [петка] [у] LT',
+                    '[прошле] [суботе] [у] LT'
+                ];
+                return lastWeekDays[this.day()];
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'за %s',
+            past   : 'пре %s',
+            s      : 'неколико секунди',
+            m      : translator.translate,
+            mm     : translator.translate,
+            h      : translator.translate,
+            hh     : translator.translate,
+            d      : 'дан',
+            dd     : translator.translate,
+            M      : 'месец',
+            MM     : translator.translate,
+            y      : 'годину',
+            yy     : translator.translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/sr.js b/resources/lib/moment/locale/sr.js
new file mode 100644 (file)
index 0000000..d008282
--- /dev/null
@@ -0,0 +1,105 @@
+// moment.js locale configuration
+// locale : Serbian-latin (sr)
+// author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var translator = {
+        words: { //Different grammatical cases
+            m: ['jedan minut', 'jedne minute'],
+            mm: ['minut', 'minute', 'minuta'],
+            h: ['jedan sat', 'jednog sata'],
+            hh: ['sat', 'sata', 'sati'],
+            dd: ['dan', 'dana', 'dana'],
+            MM: ['mesec', 'meseca', 'meseci'],
+            yy: ['godina', 'godine', 'godina']
+        },
+        correctGrammaticalCase: function (number, wordKey) {
+            return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
+        },
+        translate: function (number, withoutSuffix, key) {
+            var wordKey = translator.words[key];
+            if (key.length === 1) {
+                return withoutSuffix ? wordKey[0] : wordKey[1];
+            } else {
+                return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
+            }
+        }
+    };
+
+    return moment.defineLocale('sr', {
+        months: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'],
+        monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'],
+        weekdays: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'],
+        weekdaysShort: ['ned.', 'pon.', 'uto.', 'sre.', 'čet.', 'pet.', 'sub.'],
+        weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
+        longDateFormat: {
+            LT: 'H:mm',
+            L: 'DD. MM. YYYY',
+            LL: 'D. MMMM YYYY',
+            LLL: 'D. MMMM YYYY LT',
+            LLLL: 'dddd, D. MMMM YYYY LT'
+        },
+        calendar: {
+            sameDay: '[danas u] LT',
+            nextDay: '[sutra u] LT',
+
+            nextWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[u] [nedelju] [u] LT';
+                case 3:
+                    return '[u] [sredu] [u] LT';
+                case 6:
+                    return '[u] [subotu] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[u] dddd [u] LT';
+                }
+            },
+            lastDay  : '[juče u] LT',
+            lastWeek : function () {
+                var lastWeekDays = [
+                    '[prošle] [nedelje] [u] LT',
+                    '[prošlog] [ponedeljka] [u] LT',
+                    '[prošlog] [utorka] [u] LT',
+                    '[prošle] [srede] [u] LT',
+                    '[prošlog] [četvrtka] [u] LT',
+                    '[prošlog] [petka] [u] LT',
+                    '[prošle] [subote] [u] LT'
+                ];
+                return lastWeekDays[this.day()];
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past   : 'pre %s',
+            s      : 'nekoliko sekundi',
+            m      : translator.translate,
+            mm     : translator.translate,
+            h      : translator.translate,
+            hh     : translator.translate,
+            d      : 'dan',
+            dd     : translator.translate,
+            M      : 'mesec',
+            MM     : translator.translate,
+            y      : 'godinu',
+            yy     : translator.translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/sv.js b/resources/lib/moment/locale/sv.js
new file mode 100644 (file)
index 0000000..634b3cf
--- /dev/null
@@ -0,0 +1,63 @@
+// moment.js locale configuration
+// locale : swedish (sv)
+// author : Jens Alm : https://github.com/ulmus
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('sv', {
+        months : 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
+        weekdays : 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'),
+        weekdaysShort : 'sön_mån_tis_ons_tor_fre_lör'.split('_'),
+        weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'YYYY-MM-DD',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[Idag] LT',
+            nextDay: '[Imorgon] LT',
+            lastDay: '[Igår] LT',
+            nextWeek: 'dddd LT',
+            lastWeek: '[Förra] dddd[en] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'om %s',
+            past : 'för %s sedan',
+            s : 'några sekunder',
+            m : 'en minut',
+            mm : '%d minuter',
+            h : 'en timme',
+            hh : '%d timmar',
+            d : 'en dag',
+            dd : '%d dagar',
+            M : 'en månad',
+            MM : '%d månader',
+            y : 'ett år',
+            yy : '%d år'
+        },
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~(number % 100 / 10) === 1) ? 'e' :
+                (b === 1) ? 'a' :
+                (b === 2) ? 'a' :
+                (b === 3) ? 'e' : 'e';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/ta.js b/resources/lib/moment/locale/ta.js
new file mode 100644 (file)
index 0000000..53bab0d
--- /dev/null
@@ -0,0 +1,112 @@
+// moment.js locale configuration
+// locale : tamil (ta)
+// author : Arjunkumar Krishnamoorthy : https://github.com/tk120404
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    /*var symbolMap = {
+            '1': '௧',
+            '2': '௨',
+            '3': '௩',
+            '4': '௪',
+            '5': '௫',
+            '6': '௬',
+            '7': '௭',
+            '8': '௮',
+            '9': '௯',
+            '0': '௦'
+        },
+        numberMap = {
+            '௧': '1',
+            '௨': '2',
+            '௩': '3',
+            '௪': '4',
+            '௫': '5',
+            '௬': '6',
+            '௭': '7',
+            '௮': '8',
+            '௯': '9',
+            '௦': '0'
+        }; */
+
+    return moment.defineLocale('ta', {
+        months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'),
+        monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'),
+        weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'),
+        weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'),
+        weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, LT',
+            LLLL : 'dddd, D MMMM YYYY, LT'
+        },
+        calendar : {
+            sameDay : '[இன்று] LT',
+            nextDay : '[நாளை] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[நேற்று] LT',
+            lastWeek : '[கடந்த வாரம்] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s இல்',
+            past : '%s முன்',
+            s : 'ஒரு சில விநாடிகள்',
+            m : 'ஒரு நிமிடம்',
+            mm : '%d நிமிடங்கள்',
+            h : 'ஒரு மணி நேரம்',
+            hh : '%d மணி நேரம்',
+            d : 'ஒரு நாள்',
+            dd : '%d நாட்கள்',
+            M : 'ஒரு மாதம்',
+            MM : '%d மாதங்கள்',
+            y : 'ஒரு வருடம்',
+            yy : '%d ஆண்டுகள்'
+        },
+/*        preparse: function (string) {
+            return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) {
+                return numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            });
+        },*/
+        ordinal : function (number) {
+            return number + 'வது';
+        },
+
+
+        // refer http://ta.wikipedia.org/s/1er1
+
+        meridiem : function (hour, minute, isLower) {
+            if (hour >= 6 && hour <= 10) {
+                return ' காலை';
+            } else if (hour >= 10 && hour <= 14) {
+                return ' நண்பகல்';
+            } else if (hour >= 14 && hour <= 18) {
+                return ' எற்பாடு';
+            } else if (hour >= 18 && hour <= 20) {
+                return ' மாலை';
+            } else if (hour >= 20 && hour <= 24) {
+                return ' இரவு';
+            } else if (hour >= 0 && hour <= 6) {
+                return ' வைகறை';
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/th.js b/resources/lib/moment/locale/th.js
new file mode 100644 (file)
index 0000000..fc99701
--- /dev/null
@@ -0,0 +1,58 @@
+// moment.js locale configuration
+// locale : thai (th)
+// author : Kridsada Thanabulpong : https://github.com/sirn
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('th', {
+        months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'),
+        monthsShort : 'มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา'.split('_'),
+        weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'),
+        weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference
+        weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'),
+        longDateFormat : {
+            LT : 'H นาฬิกา m นาที',
+            L : 'YYYY/MM/DD',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY เวลา LT',
+            LLLL : 'วันddddที่ D MMMM YYYY เวลา LT'
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return 'ก่อนเที่ยง';
+            } else {
+                return 'หลังเที่ยง';
+            }
+        },
+        calendar : {
+            sameDay : '[วันนี้ เวลา] LT',
+            nextDay : '[พรุ่งนี้ เวลา] LT',
+            nextWeek : 'dddd[หน้า เวลา] LT',
+            lastDay : '[เมื่อวานนี้ เวลา] LT',
+            lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'อีก %s',
+            past : '%sที่แล้ว',
+            s : 'ไม่กี่วินาที',
+            m : '1 นาที',
+            mm : '%d นาที',
+            h : '1 ชั่วโมง',
+            hh : '%d ชั่วโมง',
+            d : '1 วัน',
+            dd : '%d วัน',
+            M : '1 เดือน',
+            MM : '%d เดือน',
+            y : '1 ปี',
+            yy : '%d ปี'
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/tl-ph.js b/resources/lib/moment/locale/tl-ph.js
new file mode 100644 (file)
index 0000000..c15cc1f
--- /dev/null
@@ -0,0 +1,58 @@
+// moment.js locale configuration
+// locale : Tagalog/Filipino (tl-ph)
+// author : Dan Hagman
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('tl-ph', {
+        months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'),
+        monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'),
+        weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'),
+        weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'),
+        weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'MM/D/YYYY',
+            LL : 'MMMM D, YYYY',
+            LLL : 'MMMM D, YYYY LT',
+            LLLL : 'dddd, MMMM DD, YYYY LT'
+        },
+        calendar : {
+            sameDay: '[Ngayon sa] LT',
+            nextDay: '[Bukas sa] LT',
+            nextWeek: 'dddd [sa] LT',
+            lastDay: '[Kahapon sa] LT',
+            lastWeek: 'dddd [huling linggo] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'sa loob ng %s',
+            past : '%s ang nakalipas',
+            s : 'ilang segundo',
+            m : 'isang minuto',
+            mm : '%d minuto',
+            h : 'isang oras',
+            hh : '%d oras',
+            d : 'isang araw',
+            dd : '%d araw',
+            M : 'isang buwan',
+            MM : '%d buwan',
+            y : 'isang taon',
+            yy : '%d taon'
+        },
+        ordinal : function (number) {
+            return number;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/tr.js b/resources/lib/moment/locale/tr.js
new file mode 100644 (file)
index 0000000..36e8fca
--- /dev/null
@@ -0,0 +1,92 @@
+// moment.js locale configuration
+// locale : turkish (tr)
+// authors : Erhan Gundogan : https://github.com/erhangundogan,
+//           Burak Yiğit Kaya: https://github.com/BYK
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var suffixes = {
+        1: '\'inci',
+        5: '\'inci',
+        8: '\'inci',
+        70: '\'inci',
+        80: '\'inci',
+
+        2: '\'nci',
+        7: '\'nci',
+        20: '\'nci',
+        50: '\'nci',
+
+        3: '\'üncü',
+        4: '\'üncü',
+        100: '\'üncü',
+
+        6: '\'ncı',
+
+        9: '\'uncu',
+        10: '\'uncu',
+        30: '\'uncu',
+
+        60: '\'ıncı',
+        90: '\'ıncı'
+    };
+
+    return moment.defineLocale('tr', {
+        months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'),
+        monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'),
+        weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'),
+        weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'),
+        weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay : '[bugün saat] LT',
+            nextDay : '[yarın saat] LT',
+            nextWeek : '[haftaya] dddd [saat] LT',
+            lastDay : '[dün] LT',
+            lastWeek : '[geçen hafta] dddd [saat] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s sonra',
+            past : '%s önce',
+            s : 'birkaç saniye',
+            m : 'bir dakika',
+            mm : '%d dakika',
+            h : 'bir saat',
+            hh : '%d saat',
+            d : 'bir gün',
+            dd : '%d gün',
+            M : 'bir ay',
+            MM : '%d ay',
+            y : 'bir yıl',
+            yy : '%d yıl'
+        },
+        ordinal : function (number) {
+            if (number === 0) {  // special case for zero
+                return number + '\'ıncı';
+            }
+            var a = number % 10,
+                b = number % 100 - a,
+                c = number >= 100 ? 100 : null;
+
+            return number + (suffixes[a] || suffixes[b] || suffixes[c]);
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/tzm-latn.js b/resources/lib/moment/locale/tzm-latn.js
new file mode 100644 (file)
index 0000000..3189772
--- /dev/null
@@ -0,0 +1,55 @@
+// moment.js locale configuration
+// locale : Morocco Central Atlas Tamaziɣt in Latin (tzm-latn)
+// author : Abdel Said : https://github.com/abdelsaid
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('tzm-latn', {
+        months : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'),
+        monthsShort : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'),
+        weekdays : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
+        weekdaysShort : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
+        weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[asdkh g] LT',
+            nextDay: '[aska g] LT',
+            nextWeek: 'dddd [g] LT',
+            lastDay: '[assant g] LT',
+            lastWeek: 'dddd [g] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'dadkh s yan %s',
+            past : 'yan %s',
+            s : 'imik',
+            m : 'minuḍ',
+            mm : '%d minuḍ',
+            h : 'saɛa',
+            hh : '%d tassaɛin',
+            d : 'ass',
+            dd : '%d ossan',
+            M : 'ayowr',
+            MM : '%d iyyirn',
+            y : 'asgas',
+            yy : '%d isgasn'
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/tzm.js b/resources/lib/moment/locale/tzm.js
new file mode 100644 (file)
index 0000000..0a7f3f1
--- /dev/null
@@ -0,0 +1,55 @@
+// moment.js locale configuration
+// locale : Morocco Central Atlas Tamaziɣt (tzm)
+// author : Abdel Said : https://github.com/abdelsaid
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('tzm', {
+        months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'),
+        monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'),
+        weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
+        weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
+        weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd D MMMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[ⴰⵙⴷⵅ ⴴ] LT',
+            nextDay: '[ⴰⵙⴽⴰ ⴴ] LT',
+            nextWeek: 'dddd [ⴴ] LT',
+            lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT',
+            lastWeek: 'dddd [ⴴ] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s',
+            past : 'ⵢⴰⵏ %s',
+            s : 'ⵉⵎⵉⴽ',
+            m : 'ⵎⵉⵏⵓⴺ',
+            mm : '%d ⵎⵉⵏⵓⴺ',
+            h : 'ⵙⴰⵄⴰ',
+            hh : '%d ⵜⴰⵙⵙⴰⵄⵉⵏ',
+            d : 'ⴰⵙⵙ',
+            dd : '%d oⵙⵙⴰⵏ',
+            M : 'ⴰⵢoⵓⵔ',
+            MM : '%d ⵉⵢⵢⵉⵔⵏ',
+            y : 'ⴰⵙⴳⴰⵙ',
+            yy : '%d ⵉⵙⴳⴰⵙⵏ'
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/uk.js b/resources/lib/moment/locale/uk.js
new file mode 100644 (file)
index 0000000..bc22fff
--- /dev/null
@@ -0,0 +1,157 @@
+// moment.js locale configuration
+// locale : ukrainian (uk)
+// author : zemlanin : https://github.com/zemlanin
+// Author : Menelion Elensúle : https://github.com/Oire
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function plural(word, num) {
+        var forms = word.split('_');
+        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+    }
+
+    function relativeTimeWithPlural(number, withoutSuffix, key) {
+        var format = {
+            'mm': 'хвилина_хвилини_хвилин',
+            'hh': 'година_години_годин',
+            'dd': 'день_дні_днів',
+            'MM': 'місяць_місяці_місяців',
+            'yy': 'рік_роки_років'
+        };
+        if (key === 'm') {
+            return withoutSuffix ? 'хвилина' : 'хвилину';
+        }
+        else if (key === 'h') {
+            return withoutSuffix ? 'година' : 'годину';
+        }
+        else {
+            return number + ' ' + plural(format[key], +number);
+        }
+    }
+
+    function monthsCaseReplace(m, format) {
+        var months = {
+            'nominative': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_'),
+            'accusative': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_')
+        },
+
+        nounCase = (/D[oD]? *MMMM?/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return months[nounCase][m.month()];
+    }
+
+    function weekdaysCaseReplace(m, format) {
+        var weekdays = {
+            'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'),
+            'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'),
+            'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_')
+        },
+
+        nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ?
+            'accusative' :
+            ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ?
+                'genitive' :
+                'nominative');
+
+        return weekdays[nounCase][m.day()];
+    }
+
+    function processHoursFunction(str) {
+        return function () {
+            return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT';
+        };
+    }
+
+    return moment.defineLocale('uk', {
+        months : monthsCaseReplace,
+        monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'),
+        weekdays : weekdaysCaseReplace,
+        weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+        weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY р.',
+            LLL : 'D MMMM YYYY р., LT',
+            LLLL : 'dddd, D MMMM YYYY р., LT'
+        },
+        calendar : {
+            sameDay: processHoursFunction('[Сьогодні '),
+            nextDay: processHoursFunction('[Завтра '),
+            lastDay: processHoursFunction('[Вчора '),
+            nextWeek: processHoursFunction('[У] dddd ['),
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 5:
+                case 6:
+                    return processHoursFunction('[Минулої] dddd [').call(this);
+                case 1:
+                case 2:
+                case 4:
+                    return processHoursFunction('[Минулого] dddd [').call(this);
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'за %s',
+            past : '%s тому',
+            s : 'декілька секунд',
+            m : relativeTimeWithPlural,
+            mm : relativeTimeWithPlural,
+            h : 'годину',
+            hh : relativeTimeWithPlural,
+            d : 'день',
+            dd : relativeTimeWithPlural,
+            M : 'місяць',
+            MM : relativeTimeWithPlural,
+            y : 'рік',
+            yy : relativeTimeWithPlural
+        },
+
+        // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
+
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'ночі';
+            } else if (hour < 12) {
+                return 'ранку';
+            } else if (hour < 17) {
+                return 'дня';
+            } else {
+                return 'вечора';
+            }
+        },
+
+        ordinal: function (number, period) {
+            switch (period) {
+            case 'M':
+            case 'd':
+            case 'DDD':
+            case 'w':
+            case 'W':
+                return number + '-й';
+            case 'D':
+                return number + '-го';
+            default:
+                return number;
+            }
+        },
+
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/uz.js b/resources/lib/moment/locale/uz.js
new file mode 100644 (file)
index 0000000..62fb89e
--- /dev/null
@@ -0,0 +1,55 @@
+// moment.js locale configuration
+// locale : uzbek (uz)
+// author : Sardor Muminov : https://github.com/muminoff
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('uz', {
+        months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'),
+        monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'),
+        weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'),
+        weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'),
+        weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'D MMMM YYYY, dddd LT'
+        },
+        calendar : {
+            sameDay : '[Бугун соат] LT [да]',
+            nextDay : '[Эртага] LT [да]',
+            nextWeek : 'dddd [куни соат] LT [да]',
+            lastDay : '[Кеча соат] LT [да]',
+            lastWeek : '[Утган] dddd [куни соат] LT [да]',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'Якин %s ичида',
+            past : 'Бир неча %s олдин',
+            s : 'фурсат',
+            m : 'бир дакика',
+            mm : '%d дакика',
+            h : 'бир соат',
+            hh : '%d соат',
+            d : 'бир кун',
+            dd : '%d кун',
+            M : 'бир ой',
+            MM : '%d ой',
+            y : 'бир йил',
+            yy : '%d йил'
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/vi.js b/resources/lib/moment/locale/vi.js
new file mode 100644 (file)
index 0000000..20e3ffe
--- /dev/null
@@ -0,0 +1,62 @@
+// moment.js locale configuration
+// locale : vietnamese (vi)
+// author : Bang Nguyen : https://github.com/bangnk
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('vi', {
+        months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'),
+        monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'),
+        weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'),
+        weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
+        weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM [năm] YYYY',
+            LLL : 'D MMMM [năm] YYYY LT',
+            LLLL : 'dddd, D MMMM [năm] YYYY LT',
+            l : 'DD/M/YYYY',
+            ll : 'D MMM YYYY',
+            lll : 'D MMM YYYY LT',
+            llll : 'ddd, D MMM YYYY LT'
+        },
+        calendar : {
+            sameDay: '[Hôm nay lúc] LT',
+            nextDay: '[Ngày mai lúc] LT',
+            nextWeek: 'dddd [tuần tới lúc] LT',
+            lastDay: '[Hôm qua lúc] LT',
+            lastWeek: 'dddd [tuần rồi lúc] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : '%s tới',
+            past : '%s trước',
+            s : 'vài giây',
+            m : 'một phút',
+            mm : '%d phút',
+            h : 'một giờ',
+            hh : '%d giờ',
+            d : 'một ngày',
+            dd : '%d ngày',
+            M : 'một tháng',
+            MM : '%d tháng',
+            y : 'một năm',
+            yy : '%d năm'
+        },
+        ordinal : function (number) {
+            return number;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/zh-cn.js b/resources/lib/moment/locale/zh-cn.js
new file mode 100644 (file)
index 0000000..aff26c5
--- /dev/null
@@ -0,0 +1,108 @@
+// moment.js locale configuration
+// locale : chinese (zh-cn)
+// author : suupic : https://github.com/suupic
+// author : Zeno Zeng : https://github.com/zenozeng
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('zh-cn', {
+        months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
+        monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+        weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
+        weekdaysShort : '周日_周一_周二_周三_周四_周五_周六'.split('_'),
+        weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
+        longDateFormat : {
+            LT : 'Ah点mm',
+            L : 'YYYY-MM-DD',
+            LL : 'YYYY年MMMD日',
+            LLL : 'YYYY年MMMD日LT',
+            LLLL : 'YYYY年MMMD日ddddLT',
+            l : 'YYYY-MM-DD',
+            ll : 'YYYY年MMMD日',
+            lll : 'YYYY年MMMD日LT',
+            llll : 'YYYY年MMMD日ddddLT'
+        },
+        meridiem : function (hour, minute, isLower) {
+            var hm = hour * 100 + minute;
+            if (hm < 600) {
+                return '凌晨';
+            } else if (hm < 900) {
+                return '早上';
+            } else if (hm < 1130) {
+                return '上午';
+            } else if (hm < 1230) {
+                return '中午';
+            } else if (hm < 1800) {
+                return '下午';
+            } else {
+                return '晚上';
+            }
+        },
+        calendar : {
+            sameDay : function () {
+                return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT';
+            },
+            nextDay : function () {
+                return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT';
+            },
+            lastDay : function () {
+                return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT';
+            },
+            nextWeek : function () {
+                var startOfWeek, prefix;
+                startOfWeek = moment().startOf('week');
+                prefix = this.unix() - startOfWeek.unix() >= 7 * 24 * 3600 ? '[下]' : '[本]';
+                return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
+            },
+            lastWeek : function () {
+                var startOfWeek, prefix;
+                startOfWeek = moment().startOf('week');
+                prefix = this.unix() < startOfWeek.unix()  ? '[上]' : '[本]';
+                return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
+            },
+            sameElse : 'LL'
+        },
+        ordinal : function (number, period) {
+            switch (period) {
+            case 'd':
+            case 'D':
+            case 'DDD':
+                return number + '日';
+            case 'M':
+                return number + '月';
+            case 'w':
+            case 'W':
+                return number + '周';
+            default:
+                return number;
+            }
+        },
+        relativeTime : {
+            future : '%s内',
+            past : '%s前',
+            s : '几秒',
+            m : '1分钟',
+            mm : '%d分钟',
+            h : '1小时',
+            hh : '%d小时',
+            d : '1天',
+            dd : '%d天',
+            M : '1个月',
+            MM : '%d个月',
+            y : '1年',
+            yy : '%d年'
+        },
+        week : {
+            // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/locale/zh-tw.js b/resources/lib/moment/locale/zh-tw.js
new file mode 100644 (file)
index 0000000..71f99a2
--- /dev/null
@@ -0,0 +1,84 @@
+// moment.js locale configuration
+// locale : traditional chinese (zh-tw)
+// author : Ben : https://github.com/ben-lin
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.defineLocale('zh-tw', {
+        months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
+        monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+        weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
+        weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'),
+        weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
+        longDateFormat : {
+            LT : 'Ah點mm',
+            L : 'YYYY年MMMD日',
+            LL : 'YYYY年MMMD日',
+            LLL : 'YYYY年MMMD日LT',
+            LLLL : 'YYYY年MMMD日ddddLT',
+            l : 'YYYY年MMMD日',
+            ll : 'YYYY年MMMD日',
+            lll : 'YYYY年MMMD日LT',
+            llll : 'YYYY年MMMD日ddddLT'
+        },
+        meridiem : function (hour, minute, isLower) {
+            var hm = hour * 100 + minute;
+            if (hm < 900) {
+                return '早上';
+            } else if (hm < 1130) {
+                return '上午';
+            } else if (hm < 1230) {
+                return '中午';
+            } else if (hm < 1800) {
+                return '下午';
+            } else {
+                return '晚上';
+            }
+        },
+        calendar : {
+            sameDay : '[今天]LT',
+            nextDay : '[明天]LT',
+            nextWeek : '[下]ddddLT',
+            lastDay : '[昨天]LT',
+            lastWeek : '[上]ddddLT',
+            sameElse : 'L'
+        },
+        ordinal : function (number, period) {
+            switch (period) {
+            case 'd' :
+            case 'D' :
+            case 'DDD' :
+                return number + '日';
+            case 'M' :
+                return number + '月';
+            case 'w' :
+            case 'W' :
+                return number + '週';
+            default :
+                return number;
+            }
+        },
+        relativeTime : {
+            future : '%s內',
+            past : '%s前',
+            s : '幾秒',
+            m : '一分鐘',
+            mm : '%d分鐘',
+            h : '一小時',
+            hh : '%d小時',
+            d : '一天',
+            dd : '%d天',
+            M : '一個月',
+            MM : '%d個月',
+            y : '一年',
+            yy : '%d年'
+        }
+    });
+}));
index 83282c6..d100a9c 100644 (file)
@@ -1,21 +1,21 @@
 //! moment.js
-//! version : 2.7.0
+//! version : 2.8.3
 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
 //! license : MIT
 //! momentjs.com
 
 (function (undefined) {
-
     /************************************
         Constants
     ************************************/
 
     var moment,
-        VERSION = "2.7.0",
+        VERSION = '2.8.3',
         // the global-scope this is NOT the global object in Node.js
         globalScope = typeof global !== 'undefined' ? global : this,
         oldGlobalMoment,
         round = Math.round,
+        hasOwnProperty = Object.prototype.hasOwnProperty,
         i,
 
         YEAR = 0,
         SECOND = 5,
         MILLISECOND = 6,
 
-        // internal storage for language config files
-        languages = {},
+        // internal storage for locale config files
+        locales = {},
 
-        // moment internal properties
-        momentProperties = {
-            _isAMomentObject: null,
-            _i : null,
-            _f : null,
-            _l : null,
-            _strict : null,
-            _tzm : null,
-            _isUTC : null,
-            _offset : null,  // optional. Combine with _isUTC
-            _pf : null,
-            _lang : null  // optional
-        },
+        // extra moment internal properties (plugins register props here)
+        momentProperties = [],
 
         // check for nodeJS
         hasModule = (typeof module !== 'undefined' && module.exports),
             ['HH', /(T| )\d\d/]
         ],
 
-        // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
+        // timezone chunker '+10:00' > ['10', '00'] or '-1530' > ['-15', '30']
         parseTimezoneChunker = /([\+\-]|\d\d)/gi,
 
         // getter and setter names
 
         // default relative time thresholds
         relativeTimeThresholds = {
-          s: 45,   //seconds to minutes
-          m: 45,   //minutes to hours
-          h: 22,   //hours to days
-          dd: 25,  //days to month (month == 1)
-          dm: 45,  //days to months (months > 1)
-          dy: 345  //days to year
+            s: 45,  // seconds to minute
+            m: 45,  // minutes to hour
+            h: 22,  // hours to day
+            d: 26,  // days to month
+            M: 11   // months to year
         },
 
         // tokens to ordinalize and pad
                 return this.month() + 1;
             },
             MMM  : function (format) {
-                return this.lang().monthsShort(this, format);
+                return this.localeData().monthsShort(this, format);
             },
             MMMM : function (format) {
-                return this.lang().months(this, format);
+                return this.localeData().months(this, format);
             },
             D    : function () {
                 return this.date();
                 return this.day();
             },
             dd   : function (format) {
-                return this.lang().weekdaysMin(this, format);
+                return this.localeData().weekdaysMin(this, format);
             },
             ddd  : function (format) {
-                return this.lang().weekdaysShort(this, format);
+                return this.localeData().weekdaysShort(this, format);
             },
             dddd : function (format) {
-                return this.lang().weekdays(this, format);
+                return this.localeData().weekdays(this, format);
             },
             w    : function () {
                 return this.week();
                 return this.isoWeekday();
             },
             a    : function () {
-                return this.lang().meridiem(this.hours(), this.minutes(), true);
+                return this.localeData().meridiem(this.hours(), this.minutes(), true);
             },
             A    : function () {
-                return this.lang().meridiem(this.hours(), this.minutes(), false);
+                return this.localeData().meridiem(this.hours(), this.minutes(), false);
             },
             H    : function () {
                 return this.hours();
             },
             Z    : function () {
                 var a = -this.zone(),
-                    b = "+";
+                    b = '+';
                 if (a < 0) {
                     a = -a;
-                    b = "-";
+                    b = '-';
                 }
-                return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2);
+                return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2);
             },
             ZZ   : function () {
                 var a = -this.zone(),
-                    b = "+";
+                    b = '+';
                 if (a < 0) {
                     a = -a;
-                    b = "-";
+                    b = '-';
                 }
                 return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
             },
             }
         },
 
+        deprecations = {},
+
         lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
 
     // Pick the first defined of two or three arguments. dfl comes from
         switch (arguments.length) {
             case 2: return a != null ? a : b;
             case 3: return a != null ? a : b != null ? b : c;
-            default: throw new Error("Implement me");
+            default: throw new Error('Implement me');
         }
     }
 
+    function hasOwnProp(a, b) {
+        return hasOwnProperty.call(a, b);
+    }
+
     function defaultParsingFlags() {
         // We need to deep clone this object, and es5 standard is not very
         // helpful.
         };
     }
 
+    function printMsg(msg) {
+        if (moment.suppressDeprecationWarnings === false &&
+                typeof console !== 'undefined' && console.warn) {
+            console.warn('Deprecation warning: ' + msg);
+        }
+    }
+
     function deprecate(msg, fn) {
         var firstTime = true;
-        function printMsg() {
-            if (moment.suppressDeprecationWarnings === false &&
-                    typeof console !== 'undefined' && console.warn) {
-                console.warn("Deprecation warning: " + msg);
-            }
-        }
         return extend(function () {
             if (firstTime) {
-                printMsg();
+                printMsg(msg);
                 firstTime = false;
             }
             return fn.apply(this, arguments);
         }, fn);
     }
 
+    function deprecateSimple(name, msg) {
+        if (!deprecations[name]) {
+            printMsg(msg);
+            deprecations[name] = true;
+        }
+    }
+
     function padToken(func, count) {
         return function (a) {
             return leftZeroFill(func.call(this, a), count);
     }
     function ordinalizeToken(func, period) {
         return function (a) {
-            return this.lang().ordinal(func.call(this, a), period);
+            return this.localeData().ordinal(func.call(this, a), period);
         };
     }
 
         Constructors
     ************************************/
 
-    function Language() {
-
+    function Locale() {
     }
 
     // Moment prototype object
-    function Moment(config) {
-        checkOverflow(config);
-        extend(this, config);
+    function Moment(config, skipOverflow) {
+        if (skipOverflow !== false) {
+            checkOverflow(config);
+        }
+        copyConfig(this, config);
+        this._d = new Date(+config._d);
     }
 
     // Duration Constructor
 
         this._data = {};
 
+        this._locale = moment.localeData();
+
         this._bubble();
     }
 
 
     function extend(a, b) {
         for (var i in b) {
-            if (b.hasOwnProperty(i)) {
+            if (hasOwnProp(b, i)) {
                 a[i] = b[i];
             }
         }
 
-        if (b.hasOwnProperty("toString")) {
+        if (hasOwnProp(b, 'toString')) {
             a.toString = b.toString;
         }
 
-        if (b.hasOwnProperty("valueOf")) {
+        if (hasOwnProp(b, 'valueOf')) {
             a.valueOf = b.valueOf;
         }
 
         return a;
     }
 
-    function cloneMoment(m) {
-        var result = {}, i;
-        for (i in m) {
-            if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) {
-                result[i] = m[i];
+    function copyConfig(to, from) {
+        var i, prop, val;
+
+        if (typeof from._isAMomentObject !== 'undefined') {
+            to._isAMomentObject = from._isAMomentObject;
+        }
+        if (typeof from._i !== 'undefined') {
+            to._i = from._i;
+        }
+        if (typeof from._f !== 'undefined') {
+            to._f = from._f;
+        }
+        if (typeof from._l !== 'undefined') {
+            to._l = from._l;
+        }
+        if (typeof from._strict !== 'undefined') {
+            to._strict = from._strict;
+        }
+        if (typeof from._tzm !== 'undefined') {
+            to._tzm = from._tzm;
+        }
+        if (typeof from._isUTC !== 'undefined') {
+            to._isUTC = from._isUTC;
+        }
+        if (typeof from._offset !== 'undefined') {
+            to._offset = from._offset;
+        }
+        if (typeof from._pf !== 'undefined') {
+            to._pf = from._pf;
+        }
+        if (typeof from._locale !== 'undefined') {
+            to._locale = from._locale;
+        }
+
+        if (momentProperties.length > 0) {
+            for (i in momentProperties) {
+                prop = momentProperties[i];
+                val = from[prop];
+                if (typeof val !== 'undefined') {
+                    to[prop] = val;
+                }
             }
         }
 
-        return result;
+        return to;
     }
 
     function absRound(number) {
         return (sign ? (forceSign ? '+' : '') : '-') + output;
     }
 
-    // helper function for _.addTime and _.subtractTime
+    function positiveMomentsDifference(base, other) {
+        var res = {milliseconds: 0, months: 0};
+
+        res.months = other.month() - base.month() +
+            (other.year() - base.year()) * 12;
+        if (base.clone().add(res.months, 'M').isAfter(other)) {
+            --res.months;
+        }
+
+        res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
+
+        return res;
+    }
+
+    function momentsDifference(base, other) {
+        var res;
+        other = makeAs(other, base);
+        if (base.isBefore(other)) {
+            res = positiveMomentsDifference(base, other);
+        } else {
+            res = positiveMomentsDifference(other, base);
+            res.milliseconds = -res.milliseconds;
+            res.months = -res.months;
+        }
+
+        return res;
+    }
+
+    // TODO: remove 'name' arg after deprecation is removed
+    function createAdder(direction, name) {
+        return function (val, period) {
+            var dur, tmp;
+            //invert the arguments, but complain about it
+            if (period !== null && !isNaN(+period)) {
+                deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
+                tmp = val; val = period; period = tmp;
+            }
+
+            val = typeof val === 'string' ? +val : val;
+            dur = moment.duration(val, period);
+            addOrSubtractDurationFromMoment(this, dur, direction);
+            return this;
+        };
+    }
+
     function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) {
         var milliseconds = duration._milliseconds,
             days = duration._days,
     }
 
     function isDate(input) {
-        return  Object.prototype.toString.call(input) === '[object Date]' ||
-                input instanceof Date;
+        return Object.prototype.toString.call(input) === '[object Date]' ||
+            input instanceof Date;
     }
 
     // compare two arrays, return the number of differences
             prop;
 
         for (prop in inputObject) {
-            if (inputObject.hasOwnProperty(prop)) {
+            if (hasOwnProp(inputObject, prop)) {
                 normalizedProp = normalizeUnits(prop);
                 if (normalizedProp) {
                     normalizedInput[normalizedProp] = inputObject[prop];
 
         moment[field] = function (format, index) {
             var i, getter,
-                method = moment.fn._lang[field],
+                method = moment._locale[field],
                 results = [];
 
             if (typeof format === 'number') {
 
             getter = function (i) {
                 var m = moment().utc().set(setter, i);
-                return method.call(moment.fn._lang, m, format || '');
+                return method.call(moment._locale, m, format || '');
             };
 
             if (index != null) {
         return m._isValid;
     }
 
-    function normalizeLanguage(key) {
+    function normalizeLocale(key) {
         return key ? key.toLowerCase().replace('_', '-') : key;
     }
 
+    // pick the locale from the array
+    // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
+    // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
+    function chooseLocale(names) {
+        var i = 0, j, next, locale, split;
+
+        while (i < names.length) {
+            split = normalizeLocale(names[i]).split('-');
+            j = split.length;
+            next = normalizeLocale(names[i + 1]);
+            next = next ? next.split('-') : null;
+            while (j > 0) {
+                locale = loadLocale(split.slice(0, j).join('-'));
+                if (locale) {
+                    return locale;
+                }
+                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
+                    //the next array item is better than a shallower substring of this one
+                    break;
+                }
+                j--;
+            }
+            i++;
+        }
+        return null;
+    }
+
+    function loadLocale(name) {
+        var oldLocale = null;
+        if (!locales[name] && hasModule) {
+            try {
+                oldLocale = moment.locale();
+                require('./locale/' + name);
+                // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales
+                moment.locale(oldLocale);
+            } catch (e) { }
+        }
+        return locales[name];
+    }
+
     // Return a moment from input, that is local/utc/zone equivalent to model.
     function makeAs(input, model) {
         return model._isUTC ? moment(input).zone(model._offset || 0) :
     }
 
     /************************************
-        Languages
+        Locale
     ************************************/
 
 
-    extend(Language.prototype, {
+    extend(Locale.prototype, {
 
         set : function (config) {
             var prop, i;
             }
         },
 
-        _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
+        _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
         months : function (m) {
             return this._months[m.month()];
         },
 
-        _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
+        _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
         monthsShort : function (m) {
             return this._monthsShort[m.month()];
         },
             }
         },
 
-        _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
+        _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
         weekdays : function (m) {
             return this._weekdays[m.day()];
         },
 
-        _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
+        _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
         weekdaysShort : function (m) {
             return this._weekdaysShort[m.day()];
         },
 
-        _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
+        _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
         weekdaysMin : function (m) {
             return this._weekdaysMin[m.day()];
         },
         },
 
         _longDateFormat : {
-            LT : "h:mm A",
-            L : "MM/DD/YYYY",
-            LL : "MMMM D YYYY",
-            LLL : "MMMM D YYYY LT",
-            LLLL : "dddd, MMMM D YYYY LT"
+            LT : 'h:mm A',
+            L : 'MM/DD/YYYY',
+            LL : 'MMMM D, YYYY',
+            LLL : 'MMMM D, YYYY LT',
+            LLLL : 'dddd, MMMM D, YYYY LT'
         },
         longDateFormat : function (key) {
             var output = this._longDateFormat[key];
         },
 
         _relativeTime : {
-            future : "in %s",
-            past : "%s ago",
-            s : "a few seconds",
-            m : "a minute",
-            mm : "%d minutes",
-            h : "an hour",
-            hh : "%d hours",
-            d : "a day",
-            dd : "%d days",
-            M : "a month",
-            MM : "%d months",
-            y : "a year",
-            yy : "%d years"
+            future : 'in %s',
+            past : '%s ago',
+            s : 'a few seconds',
+            m : 'a minute',
+            mm : '%d minutes',
+            h : 'an hour',
+            hh : '%d hours',
+            d : 'a day',
+            dd : '%d days',
+            M : 'a month',
+            MM : '%d months',
+            y : 'a year',
+            yy : '%d years'
         },
+
         relativeTime : function (number, withoutSuffix, string, isFuture) {
             var output = this._relativeTime[string];
             return (typeof output === 'function') ?
                 output(number, withoutSuffix, string, isFuture) :
                 output.replace(/%d/i, number);
         },
+
         pastFuture : function (diff, output) {
             var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
             return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
         },
 
         ordinal : function (number) {
-            return this._ordinal.replace("%d", number);
+            return this._ordinal.replace('%d', number);
         },
-        _ordinal : "%d",
+        _ordinal : '%d',
 
         preparse : function (string) {
             return string;
         }
     });
 
-    // Loads a language definition into the `languages` cache.  The function
-    // takes a key and optionally values.  If not in the browser and no values
-    // are provided, it will load the language file module.  As a convenience,
-    // this function also returns the language values.
-    function loadLang(key, values) {
-        values.abbr = key;
-        if (!languages[key]) {
-            languages[key] = new Language();
-        }
-        languages[key].set(values);
-        return languages[key];
-    }
-
-    // Remove a language from the `languages` cache. Mostly useful in tests.
-    function unloadLang(key) {
-        delete languages[key];
-    }
-
-    // Determines which language definition to use and returns it.
-    //
-    // With no parameters, it will return the global language.  If you
-    // pass in a language key, such as 'en', it will return the
-    // definition for 'en', so long as 'en' has already been loaded using
-    // moment.lang.
-    function getLangDefinition(key) {
-        var i = 0, j, lang, next, split,
-            get = function (k) {
-                if (!languages[k] && hasModule) {
-                    try {
-                        require('./lang/' + k);
-                    } catch (e) { }
-                }
-                return languages[k];
-            };
-
-        if (!key) {
-            return moment.fn._lang;
-        }
-
-        if (!isArray(key)) {
-            //short-circuit everything else
-            lang = get(key);
-            if (lang) {
-                return lang;
-            }
-            key = [key];
-        }
-
-        //pick the language from the array
-        //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
-        //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
-        while (i < key.length) {
-            split = normalizeLanguage(key[i]).split('-');
-            j = split.length;
-            next = normalizeLanguage(key[i + 1]);
-            next = next ? next.split('-') : null;
-            while (j > 0) {
-                lang = get(split.slice(0, j).join('-'));
-                if (lang) {
-                    return lang;
-                }
-                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
-                    //the next array item is better than a shallower substring of this one
-                    break;
-                }
-                j--;
-            }
-            i++;
-        }
-        return moment.fn._lang;
-    }
-
     /************************************
         Formatting
     ************************************/
 
     function removeFormattingTokens(input) {
         if (input.match(/\[[\s\S]/)) {
-            return input.replace(/^\[|\]$/g, "");
+            return input.replace(/^\[|\]$/g, '');
         }
-        return input.replace(/\\/g, "");
+        return input.replace(/\\/g, '');
     }
 
     function makeFormatFunction(format) {
         }
 
         return function (mom) {
-            var output = "";
+            var output = '';
             for (i = 0; i < length; i++) {
                 output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
             }
 
     // format date using native date object
     function formatMoment(m, format) {
-
         if (!m.isValid()) {
-            return m.lang().invalidDate();
+            return m.localeData().invalidDate();
         }
 
-        format = expandFormat(format, m.lang());
+        format = expandFormat(format, m.localeData());
 
         if (!formatFunctions[format]) {
             formatFunctions[format] = makeFormatFunction(format);
         return formatFunctions[format](m);
     }
 
-    function expandFormat(format, lang) {
+    function expandFormat(format, locale) {
         var i = 5;
 
         function replaceLongDateFormatTokens(input) {
-            return lang.longDateFormat(input) || input;
+            return locale.longDateFormat(input) || input;
         }
 
         localFormattingTokens.lastIndex = 0;
         case 'ggggg':
             return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
         case 'S':
-            if (strict) { return parseTokenOneDigit; }
+            if (strict) {
+                return parseTokenOneDigit;
+            }
             /* falls through */
         case 'SS':
-            if (strict) { return parseTokenTwoDigits; }
+            if (strict) {
+                return parseTokenTwoDigits;
+            }
             /* falls through */
         case 'SSS':
-            if (strict) { return parseTokenThreeDigits; }
+            if (strict) {
+                return parseTokenThreeDigits;
+            }
             /* falls through */
         case 'DDD':
             return parseTokenOneToThreeDigits;
             return parseTokenWord;
         case 'a':
         case 'A':
-            return getLangDefinition(config._l)._meridiemParse;
+            return config._locale._meridiemParse;
         case 'X':
             return parseTokenTimestampMs;
         case 'Z':
         case 'Do':
             return parseTokenOrdinal;
         default :
-            a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
+            a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i'));
             return a;
         }
     }
 
     function timezoneMinutesFromString(string) {
-        string = string || "";
+        string = string || '';
         var possibleTzMatches = (string.match(parseTokenTimezone) || []),
             tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
             parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
             break;
         case 'MMM' : // fall through to MMMM
         case 'MMMM' :
-            a = getLangDefinition(config._l).monthsParse(input);
+            a = config._locale.monthsParse(input);
             // if we didn't find a month name, mark the date as invalid.
             if (a != null) {
                 datePartArray[MONTH] = a;
         // AM / PM
         case 'a' : // fall through to A
         case 'A' :
-            config._isPm = getLangDefinition(config._l).isPM(input);
+            config._isPm = config._locale.isPM(input);
             break;
         // 24 HOUR
         case 'H' : // fall through to hh
         case 'dd':
         case 'ddd':
         case 'dddd':
-            a = getLangDefinition(config._l).weekdaysParse(input);
+            a = config._locale.weekdaysParse(input);
             // if we didn't get a weekday name, mark the date as invalid
             if (a != null) {
                 config._w = config._w || {};
     }
 
     function dayOfYearFromWeekInfo(config) {
-        var w, weekYear, week, weekday, dow, doy, temp, lang;
+        var w, weekYear, week, weekday, dow, doy, temp;
 
         w = config._w;
         if (w.GG != null || w.W != null || w.E != null) {
             week = dfl(w.W, 1);
             weekday = dfl(w.E, 1);
         } else {
-            lang = getLangDefinition(config._l);
-            dow = lang._week.dow;
-            doy = lang._week.doy;
+            dow = config._locale._week.dow;
+            doy = config._locale._week.doy;
 
             weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year);
             week = dfl(w.w, 1);
 
     // date from string and format string
     function makeDateFromStringAndFormat(config) {
-
         if (config._f === moment.ISO_8601) {
             parseISO(config);
             return;
         config._pf.empty = true;
 
         // This array is used to make a Date, either with `new Date` or `Date.UTC`
-        var lang = getLangDefinition(config._l),
-            string = '' + config._i,
+        var string = '' + config._i,
             i, parsedInput, tokens, token, skipped,
             stringLength = string.length,
             totalParsedInputLength = 0;
 
-        tokens = expandFormat(config._f, lang).match(formattingTokens) || [];
+        tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
 
         for (i = 0; i < tokens.length; i++) {
             token = tokens[i];
 
         for (i = 0; i < config._f.length; i++) {
             currentScore = 0;
-            tempConfig = extend({}, config);
+            tempConfig = copyConfig({}, config);
+            if (config._useUTC != null) {
+                tempConfig._useUTC = config._useUTC;
+            }
             tempConfig._pf = defaultParsingFlags();
             tempConfig._f = config._f[i];
             makeDateFromStringAndFormat(tempConfig);
             config._pf.iso = true;
             for (i = 0, l = isoDates.length; i < l; i++) {
                 if (isoDates[i][1].exec(string)) {
-                    // match[5] should be "T" or undefined
-                    config._f = isoDates[i][0] + (match[6] || " ");
+                    // match[5] should be 'T' or undefined
+                    config._f = isoDates[i][0] + (match[6] || ' ');
                     break;
                 }
             }
                 }
             }
             if (string.match(parseTokenTimezone)) {
-                config._f += "Z";
+                config._f += 'Z';
             }
             makeDateFromStringAndFormat(config);
         } else {
         }
     }
 
-    function makeDateFromInput(config) {
-        var input = config._i,
-            matched = aspNetJsonRegex.exec(input);
+    function map(arr, fn) {
+        var res = [], i;
+        for (i = 0; i < arr.length; ++i) {
+            res.push(fn(arr[i], i));
+        }
+        return res;
+    }
 
+    function makeDateFromInput(config) {
+        var input = config._i, matched;
         if (input === undefined) {
             config._d = new Date();
-        } else if (matched) {
+        } else if (isDate(input)) {
+            config._d = new Date(+input);
+        } else if ((matched = aspNetJsonRegex.exec(input)) !== null) {
             config._d = new Date(+matched[1]);
         } else if (typeof input === 'string') {
             makeDateFromString(config);
         } else if (isArray(input)) {
-            config._a = input.slice(0);
+            config._a = map(input.slice(0), function (obj) {
+                return parseInt(obj, 10);
+            });
             dateFromConfig(config);
-        } else if (isDate(input)) {
-            config._d = new Date(+input);
         } else if (typeof(input) === 'object') {
             dateFromObject(config);
         } else if (typeof(input) === 'number') {
         return date;
     }
 
-    function parseWeekday(input, language) {
+    function parseWeekday(input, locale) {
         if (typeof input === 'string') {
             if (!isNaN(input)) {
                 input = parseInt(input, 10);
             }
             else {
-                input = language.weekdaysParse(input);
+                input = locale.weekdaysParse(input);
                 if (typeof input !== 'number') {
                     return null;
                 }
 
 
     // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
-    function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
-        return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
+    function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
+        return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
     }
 
-    function relativeTime(milliseconds, withoutSuffix, lang) {
-        var seconds = round(Math.abs(milliseconds) / 1000),
-            minutes = round(seconds / 60),
-            hours = round(minutes / 60),
-            days = round(hours / 24),
-            years = round(days / 365),
-            args = seconds < relativeTimeThresholds.s  && ['s', seconds] ||
+    function relativeTime(posNegDuration, withoutSuffix, locale) {
+        var duration = moment.duration(posNegDuration).abs(),
+            seconds = round(duration.as('s')),
+            minutes = round(duration.as('m')),
+            hours = round(duration.as('h')),
+            days = round(duration.as('d')),
+            months = round(duration.as('M')),
+            years = round(duration.as('y')),
+
+            args = seconds < relativeTimeThresholds.s && ['s', seconds] ||
                 minutes === 1 && ['m'] ||
                 minutes < relativeTimeThresholds.m && ['mm', minutes] ||
                 hours === 1 && ['h'] ||
                 hours < relativeTimeThresholds.h && ['hh', hours] ||
                 days === 1 && ['d'] ||
-                days <= relativeTimeThresholds.dd && ['dd', days] ||
-                days <= relativeTimeThresholds.dm && ['M'] ||
-                days < relativeTimeThresholds.dy && ['MM', round(days / 30)] ||
+                days < relativeTimeThresholds.d && ['dd', days] ||
+                months === 1 && ['M'] ||
+                months < relativeTimeThresholds.M && ['MM', months] ||
                 years === 1 && ['y'] || ['yy', years];
+
         args[2] = withoutSuffix;
-        args[3] = milliseconds > 0;
-        args[4] = lang;
+        args[3] = +posNegDuration > 0;
+        args[4] = locale;
         return substituteTimeAgo.apply({}, args);
     }
 
             daysToDayOfWeek += 7;
         }
 
-        adjustedMoment = moment(mom).add('d', daysToDayOfWeek);
+        adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd');
         return {
             week: Math.ceil(adjustedMoment.dayOfYear() / 7),
             year: adjustedMoment.year()
         var input = config._i,
             format = config._f;
 
+        config._locale = config._locale || moment.localeData(config._l);
+
         if (input === null || (format === undefined && input === '')) {
             return moment.invalid({nullInput: true});
         }
 
         if (typeof input === 'string') {
-            config._i = input = getLangDefinition().preparse(input);
+            config._i = input = config._locale.preparse(input);
         }
 
         if (moment.isMoment(input)) {
-            config = cloneMoment(input);
-
-            config._d = new Date(+input._d);
+            return new Moment(input, true);
         } else if (format) {
             if (isArray(format)) {
                 makeDateFromStringAndArray(config);
         return new Moment(config);
     }
 
-    moment = function (input, format, lang, strict) {
+    moment = function (input, format, locale, strict) {
         var c;
 
-        if (typeof(lang) === "boolean") {
-            strict = lang;
-            lang = undefined;
+        if (typeof(locale) === 'boolean') {
+            strict = locale;
+            locale = undefined;
         }
         // object construction must be done this way.
         // https://github.com/moment/moment/issues/1423
         c._isAMomentObject = true;
         c._i = input;
         c._f = format;
-        c._l = lang;
+        c._l = locale;
         c._strict = strict;
         c._isUTC = false;
         c._pf = defaultParsingFlags();
     moment.suppressDeprecationWarnings = false;
 
     moment.createFromInputFallback = deprecate(
-            "moment construction falls back to js Date. This is " +
-            "discouraged and will be removed in upcoming major " +
-            "release. Please refer to " +
-            "https://github.com/moment/moment/issues/1407 for more info.",
-            function (config) {
-        config._d = new Date(config._i);
-    });
+        'moment construction falls back to js Date. This is ' +
+        'discouraged and will be removed in upcoming major ' +
+        'release. Please refer to ' +
+        'https://github.com/moment/moment/issues/1407 for more info.',
+        function (config) {
+            config._d = new Date(config._i);
+        }
+    );
 
     // Pick a moment m from moments so that m[fn](other) is true for all
     // other. This relies on the function fn to be transitive.
     };
 
     // creating with utc
-    moment.utc = function (input, format, lang, strict) {
+    moment.utc = function (input, format, locale, strict) {
         var c;
 
-        if (typeof(lang) === "boolean") {
-            strict = lang;
-            lang = undefined;
+        if (typeof(locale) === 'boolean') {
+            strict = locale;
+            locale = undefined;
         }
         // object construction must be done this way.
         // https://github.com/moment/moment/issues/1423
         c._isAMomentObject = true;
         c._useUTC = true;
         c._isUTC = true;
-        c._l = lang;
+        c._l = locale;
         c._i = input;
         c._f = format;
         c._strict = strict;
             match = null,
             sign,
             ret,
-            parseIso;
+            parseIso,
+            diffRes;
 
         if (moment.isDuration(input)) {
             duration = {
                 duration.milliseconds = input;
             }
         } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
-            sign = (match[1] === "-") ? -1 : 1;
+            sign = (match[1] === '-') ? -1 : 1;
             duration = {
                 y: 0,
                 d: toInt(match[DATE]) * sign,
                 ms: toInt(match[MILLISECOND]) * sign
             };
         } else if (!!(match = isoDurationRegex.exec(input))) {
-            sign = (match[1] === "-") ? -1 : 1;
+            sign = (match[1] === '-') ? -1 : 1;
             parseIso = function (inp) {
                 // We'd normally use ~~inp for this, but unfortunately it also
                 // converts floats to ints.
                 s: parseIso(match[7]),
                 w: parseIso(match[8])
             };
+        } else if (typeof duration === 'object' &&
+                ('from' in duration || 'to' in duration)) {
+            diffRes = momentsDifference(moment(duration.from), moment(duration.to));
+
+            duration = {};
+            duration.ms = diffRes.milliseconds;
+            duration.M = diffRes.months;
         }
 
         ret = new Duration(duration);
 
-        if (moment.isDuration(input) && input.hasOwnProperty('_lang')) {
-            ret._lang = input._lang;
+        if (moment.isDuration(input) && hasOwnProp(input, '_locale')) {
+            ret._locale = input._locale;
         }
 
         return ret;
     moment.updateOffset = function () {};
 
     // This function allows you to set a threshold for relative time strings
-    moment.relativeTimeThreshold = function(threshold, limit) {
-      if (relativeTimeThresholds[threshold] === undefined) {
-        return false;
-      }
-      relativeTimeThresholds[threshold] = limit;
-      return true;
+    moment.relativeTimeThreshold = function (threshold, limit) {
+        if (relativeTimeThresholds[threshold] === undefined) {
+            return false;
+        }
+        if (limit === undefined) {
+            return relativeTimeThresholds[threshold];
+        }
+        relativeTimeThresholds[threshold] = limit;
+        return true;
     };
 
-    // This function will load languages and then set the global language.  If
+    moment.lang = deprecate(
+        'moment.lang is deprecated. Use moment.locale instead.',
+        function (key, value) {
+            return moment.locale(key, value);
+        }
+    );
+
+    // This function will load locale and then set the global locale.  If
     // no arguments are passed in, it will simply return the current global
-    // language key.
-    moment.lang = function (key, values) {
-        var r;
-        if (!key) {
-            return moment.fn._lang._abbr;
-        }
-        if (values) {
-            loadLang(normalizeLanguage(key), values);
-        } else if (values === null) {
-            unloadLang(key);
-            key = 'en';
-        } else if (!languages[key]) {
-            getLangDefinition(key);
-        }
-        r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
-        return r._abbr;
+    // locale key.
+    moment.locale = function (key, values) {
+        var data;
+        if (key) {
+            if (typeof(values) !== 'undefined') {
+                data = moment.defineLocale(key, values);
+            }
+            else {
+                data = moment.localeData(key);
+            }
+
+            if (data) {
+                moment.duration._locale = moment._locale = data;
+            }
+        }
+
+        return moment._locale._abbr;
+    };
+
+    moment.defineLocale = function (name, values) {
+        if (values !== null) {
+            values.abbr = name;
+            if (!locales[name]) {
+                locales[name] = new Locale();
+            }
+            locales[name].set(values);
+
+            // backwards compat for now: also set the locale
+            moment.locale(name);
+
+            return locales[name];
+        } else {
+            // useful for testing
+            delete locales[name];
+            return null;
+        }
     };
 
-    // returns language data
-    moment.langData = function (key) {
-        if (key && key._lang && key._lang._abbr) {
-            key = key._lang._abbr;
+    moment.langData = deprecate(
+        'moment.langData is deprecated. Use moment.localeData instead.',
+        function (key) {
+            return moment.localeData(key);
+        }
+    );
+
+    // returns locale data
+    moment.localeData = function (key) {
+        var locale;
+
+        if (key && key._locale && key._locale._abbr) {
+            key = key._locale._abbr;
+        }
+
+        if (!key) {
+            return moment._locale;
+        }
+
+        if (!isArray(key)) {
+            //short-circuit everything else
+            locale = loadLocale(key);
+            if (locale) {
+                return locale;
+            }
+            key = [key];
         }
-        return getLangDefinition(key);
+
+        return chooseLocale(key);
     };
 
     // compare moment object
     moment.isMoment = function (obj) {
         return obj instanceof Moment ||
-            (obj != null &&  obj.hasOwnProperty('_isAMomentObject'));
+            (obj != null && hasOwnProp(obj, '_isAMomentObject'));
     };
 
     // for typechecking Duration objects
         },
 
         toString : function () {
-            return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
+            return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
         },
 
         toDate : function () {
         },
 
         isDSTShifted : function () {
-
             if (this._a) {
                 return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
             }
             return this._pf.overflow;
         },
 
-        utc : function () {
-            return this.zone(0);
+        utc : function (keepLocalTime) {
+            return this.zone(0, keepLocalTime);
         },
 
-        local : function () {
-            this.zone(0);
-            this._isUTC = false;
+        local : function (keepLocalTime) {
+            if (this._isUTC) {
+                this.zone(0, keepLocalTime);
+                this._isUTC = false;
+
+                if (keepLocalTime) {
+                    this.add(this._dateTzOffset(), 'm');
+                }
+            }
             return this;
         },
 
         format : function (inputString) {
             var output = formatMoment(this, inputString || moment.defaultFormat);
-            return this.lang().postformat(output);
+            return this.localeData().postformat(output);
         },
 
-        add : function (input, val) {
-            var dur;
-            // switch args to support add('s', 1) and add(1, 's')
-            if (typeof input === 'string' && typeof val === 'string') {
-                dur = moment.duration(isNaN(+val) ? +input : +val, isNaN(+val) ? val : input);
-            } else if (typeof input === 'string') {
-                dur = moment.duration(+val, input);
-            } else {
-                dur = moment.duration(input, val);
-            }
-            addOrSubtractDurationFromMoment(this, dur, 1);
-            return this;
-        },
+        add : createAdder(1, 'add'),
 
-        subtract : function (input, val) {
-            var dur;
-            // switch args to support subtract('s', 1) and subtract(1, 's')
-            if (typeof input === 'string' && typeof val === 'string') {
-                dur = moment.duration(isNaN(+val) ? +input : +val, isNaN(+val) ? val : input);
-            } else if (typeof input === 'string') {
-                dur = moment.duration(+val, input);
-            } else {
-                dur = moment.duration(input, val);
-            }
-            addOrSubtractDurationFromMoment(this, dur, -1);
-            return this;
-        },
+        subtract : createAdder(-1, 'subtract'),
 
         diff : function (input, units, asFloat) {
             var that = makeAs(input, this),
                 zoneDiff = (this.zone() - that.zone()) * 6e4,
-                diff, output;
+                diff, output, daysAdjust;
 
             units = normalizeUnits(units);
 
                 output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
                 // adjust by taking difference in days, average number of days
                 // and dst in the given months.
-                output += ((this - moment(this).startOf('month')) -
-                        (that - moment(that).startOf('month'))) / diff;
+                daysAdjust = (this - moment(this).startOf('month')) -
+                    (that - moment(that).startOf('month'));
                 // same as above but with zones, to negate all dst
-                output -= ((this.zone() - moment(this).startOf('month').zone()) -
-                        (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff;
+                daysAdjust -= ((this.zone() - moment(this).startOf('month').zone()) -
+                        (that.zone() - moment(that).startOf('month').zone())) * 6e4;
+                output += daysAdjust / diff;
                 if (units === 'year') {
                     output = output / 12;
                 }
         },
 
         from : function (time, withoutSuffix) {
-            return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
+            return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
         },
 
         fromNow : function (withoutSuffix) {
                     diff < 1 ? 'sameDay' :
                     diff < 2 ? 'nextDay' :
                     diff < 7 ? 'nextWeek' : 'sameElse';
-            return this.format(this.lang().calendar(format, this));
+            return this.format(this.localeData().calendar(format, this));
         },
 
         isLeapYear : function () {
         day : function (input) {
             var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
             if (input != null) {
-                input = parseWeekday(input, this.lang());
-                return this.add({ d : input - day });
+                input = parseWeekday(input, this.localeData());
+                return this.add(input - day, 'd');
             } else {
                 return day;
             }
 
         month : makeAccessor('Month', true),
 
-        startOf: function (units) {
+        startOf : function (units) {
             units = normalizeUnits(units);
             // the following switch intentionally omits break keywords
             // to utilize falling through the cases.
 
         endOf: function (units) {
             units = normalizeUnits(units);
-            return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1);
+            return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
         },
 
         isAfter: function (input, units) {
-            units = typeof units !== 'undefined' ? units : 'millisecond';
-            return +this.clone().startOf(units) > +moment(input).startOf(units);
+            units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
+            if (units === 'millisecond') {
+                input = moment.isMoment(input) ? input : moment(input);
+                return +this > +input;
+            } else {
+                return +this.clone().startOf(units) > +moment(input).startOf(units);
+            }
         },
 
         isBefore: function (input, units) {
-            units = typeof units !== 'undefined' ? units : 'millisecond';
-            return +this.clone().startOf(units) < +moment(input).startOf(units);
+            units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
+            if (units === 'millisecond') {
+                input = moment.isMoment(input) ? input : moment(input);
+                return +this < +input;
+            } else {
+                return +this.clone().startOf(units) < +moment(input).startOf(units);
+            }
         },
 
         isSame: function (input, units) {
-            units = units || 'ms';
-            return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
+            units = normalizeUnits(units || 'millisecond');
+            if (units === 'millisecond') {
+                input = moment.isMoment(input) ? input : moment(input);
+                return +this === +input;
+            } else {
+                return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
+            }
         },
 
         min: deprecate(
-                 "moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",
+                 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
                  function (other) {
                      other = moment.apply(null, arguments);
                      return other < this ? this : other;
          ),
 
         max: deprecate(
-                "moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",
+                'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
                 function (other) {
                     other = moment.apply(null, arguments);
                     return other > this ? this : other;
                 }
         ),
 
-        // keepTime = true means only change the timezone, without affecting
-        // the local hour. So 5:31:26 +0300 --[zone(2, true)]--> 5:31:26 +0200
-        // It is possible that 5:31:26 doesn't exist int zone +0200, so we
-        // adjust the time as needed, to be valid.
+        // keepLocalTime = true means only change the timezone, without
+        // affecting the local hour. So 5:31:26 +0300 --[zone(2, true)]-->
+        // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist int zone
+        // +0200, so we adjust the time as needed, to be valid.
         //
         // Keeping the time actually adds/subtracts (one hour)
         // from the actual represented time. That is why we call updateOffset
         // a second time. In case it wants us to change the offset again
         // _changeInProgress == true case, then we have to adjust, because
         // there is no such time in the given timezone.
-        zone : function (input, keepTime) {
-            var offset = this._offset || 0;
+        zone : function (input, keepLocalTime) {
+            var offset = this._offset || 0,
+                localAdjust;
             if (input != null) {
-                if (typeof input === "string") {
+                if (typeof input === 'string') {
                     input = timezoneMinutesFromString(input);
                 }
                 if (Math.abs(input) < 16) {
                     input = input * 60;
                 }
+                if (!this._isUTC && keepLocalTime) {
+                    localAdjust = this._dateTzOffset();
+                }
                 this._offset = input;
                 this._isUTC = true;
+                if (localAdjust != null) {
+                    this.subtract(localAdjust, 'm');
+                }
                 if (offset !== input) {
-                    if (!keepTime || this._changeInProgress) {
+                    if (!keepLocalTime || this._changeInProgress) {
                         addOrSubtractDurationFromMoment(this,
                                 moment.duration(offset - input, 'm'), 1, false);
                     } else if (!this._changeInProgress) {
                     }
                 }
             } else {
-                return this._isUTC ? offset : this._d.getTimezoneOffset();
+                return this._isUTC ? offset : this._dateTzOffset();
             }
             return this;
         },
 
         zoneAbbr : function () {
-            return this._isUTC ? "UTC" : "";
+            return this._isUTC ? 'UTC' : '';
         },
 
         zoneName : function () {
-            return this._isUTC ? "Coordinated Universal Time" : "";
+            return this._isUTC ? 'Coordinated Universal Time' : '';
         },
 
         parseZone : function () {
 
         dayOfYear : function (input) {
             var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
-            return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
+            return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
         },
 
         quarter : function (input) {
         },
 
         weekYear : function (input) {
-            var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year;
-            return input == null ? year : this.add("y", (input - year));
+            var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year;
+            return input == null ? year : this.add((input - year), 'y');
         },
 
         isoWeekYear : function (input) {
             var year = weekOfYear(this, 1, 4).year;
-            return input == null ? year : this.add("y", (input - year));
+            return input == null ? year : this.add((input - year), 'y');
         },
 
         week : function (input) {
-            var week = this.lang().week(this);
-            return input == null ? week : this.add("d", (input - week) * 7);
+            var week = this.localeData().week(this);
+            return input == null ? week : this.add((input - week) * 7, 'd');
         },
 
         isoWeek : function (input) {
             var week = weekOfYear(this, 1, 4).week;
-            return input == null ? week : this.add("d", (input - week) * 7);
+            return input == null ? week : this.add((input - week) * 7, 'd');
         },
 
         weekday : function (input) {
-            var weekday = (this.day() + 7 - this.lang()._week.dow) % 7;
-            return input == null ? weekday : this.add("d", input - weekday);
+            var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
+            return input == null ? weekday : this.add(input - weekday, 'd');
         },
 
         isoWeekday : function (input) {
         },
 
         weeksInYear : function () {
-            var weekInfo = this._lang._week;
+            var weekInfo = this.localeData()._week;
             return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
         },
 
             return this;
         },
 
-        // If passed a language key, it will set the language for this
-        // instance.  Otherwise, it will return the language configuration
+        // If passed a locale key, it will set the locale for this
+        // instance.  Otherwise, it will return the locale configuration
         // variables for this instance.
-        lang : function (key) {
+        locale : function (key) {
+            var newLocaleData;
+
             if (key === undefined) {
-                return this._lang;
+                return this._locale._abbr;
             } else {
-                this._lang = getLangDefinition(key);
+                newLocaleData = moment.localeData(key);
+                if (newLocaleData != null) {
+                    this._locale = newLocaleData;
+                }
                 return this;
             }
+        },
+
+        lang : deprecate(
+            'moment().lang() is deprecated. Use moment().localeData() instead.',
+            function (key) {
+                if (key === undefined) {
+                    return this.localeData();
+                } else {
+                    return this.locale(key);
+                }
+            }
+        ),
+
+        localeData : function () {
+            return this._locale;
+        },
+
+        _dateTzOffset : function () {
+            // On Firefox.24 Date#getTimezoneOffset returns a floating point.
+            // https://github.com/moment/moment/pull/1871
+            return Math.round(this._d.getTimezoneOffset() / 15) * 15;
         }
     });
 
 
         // TODO: Move this out of here!
         if (typeof value === 'string') {
-            value = mom.lang().monthsParse(value);
+            value = mom.localeData().monthsParse(value);
             // TODO: Another silent failure?
             if (typeof value !== 'number') {
                 return mom;
     moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true);
     // moment.fn.month is defined separately
     moment.fn.date = makeAccessor('Date', true);
-    moment.fn.dates = deprecate("dates accessor is deprecated. Use date instead.", makeAccessor('Date', true));
+    moment.fn.dates = deprecate('dates accessor is deprecated. Use date instead.', makeAccessor('Date', true));
     moment.fn.year = makeAccessor('FullYear', true);
-    moment.fn.years = deprecate("years accessor is deprecated. Use year instead.", makeAccessor('FullYear', true));
+    moment.fn.years = deprecate('years accessor is deprecated. Use year instead.', makeAccessor('FullYear', true));
 
     // add plural methods
     moment.fn.days = moment.fn.day;
     ************************************/
 
 
+    function daysToYears (days) {
+        // 400 years have 146097 days (taking into account leap year rules)
+        return days * 400 / 146097;
+    }
+
+    function yearsToDays (years) {
+        // years * 365 + absRound(years / 4) -
+        //     absRound(years / 100) + absRound(years / 400);
+        return years * 146097 / 400;
+    }
+
     extend(moment.duration.fn = Duration.prototype, {
 
         _bubble : function () {
                 days = this._days,
                 months = this._months,
                 data = this._data,
-                seconds, minutes, hours, years;
+                seconds, minutes, hours, years = 0;
 
             // The following code bubbles up values, see the tests for
             // examples of what that means.
             data.hours = hours % 24;
 
             days += absRound(hours / 24);
-            data.days = days % 30;
 
+            // Accurately convert days to years, assume start from year 0.
+            years = absRound(daysToYears(days));
+            days -= absRound(yearsToDays(years));
+
+            // 30 days to a month
+            // TODO (iskren): Use anchor date (like 1st Jan) to compute this.
             months += absRound(days / 30);
-            data.months = months % 12;
+            days %= 30;
 
-            years = absRound(months / 12);
+            // 12 months -> 1 year
+            years += absRound(months / 12);
+            months %= 12;
+
+            data.days = days;
+            data.months = months;
             data.years = years;
         },
 
+        abs : function () {
+            this._milliseconds = Math.abs(this._milliseconds);
+            this._days = Math.abs(this._days);
+            this._months = Math.abs(this._months);
+
+            this._data.milliseconds = Math.abs(this._data.milliseconds);
+            this._data.seconds = Math.abs(this._data.seconds);
+            this._data.minutes = Math.abs(this._data.minutes);
+            this._data.hours = Math.abs(this._data.hours);
+            this._data.months = Math.abs(this._data.months);
+            this._data.years = Math.abs(this._data.years);
+
+            return this;
+        },
+
         weeks : function () {
             return absRound(this.days() / 7);
         },
         },
 
         humanize : function (withSuffix) {
-            var difference = +this,
-                output = relativeTime(difference, !withSuffix, this.lang());
+            var output = relativeTime(this, !withSuffix, this.localeData());
 
             if (withSuffix) {
-                output = this.lang().pastFuture(difference, output);
+                output = this.localeData().pastFuture(+this, output);
             }
 
-            return this.lang().postformat(output);
+            return this.localeData().postformat(output);
         },
 
         add : function (input, val) {
         },
 
         as : function (units) {
+            var days, months;
             units = normalizeUnits(units);
-            return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
+
+            if (units === 'month' || units === 'year') {
+                days = this._days + this._milliseconds / 864e5;
+                months = this._months + daysToYears(days) * 12;
+                return units === 'month' ? months : months / 12;
+            } else {
+                // handle milliseconds separately because of floating point math errors (issue #1867)
+                days = this._days + yearsToDays(this._months / 12);
+                switch (units) {
+                    case 'week': return days / 7 + this._milliseconds / 6048e5;
+                    case 'day': return days + this._milliseconds / 864e5;
+                    case 'hour': return days * 24 + this._milliseconds / 36e5;
+                    case 'minute': return days * 24 * 60 + this._milliseconds / 6e4;
+                    case 'second': return days * 24 * 60 * 60 + this._milliseconds / 1000;
+                    // Math.floor prevents floating point math errors here
+                    case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + this._milliseconds;
+                    default: throw new Error('Unknown unit ' + units);
+                }
+            }
         },
 
         lang : moment.fn.lang,
+        locale : moment.fn.locale,
 
-        toIsoString : function () {
+        toIsoString : deprecate(
+            'toIsoString() is deprecated. Please use toISOString() instead ' +
+            '(notice the capitals)',
+            function () {
+                return this.toISOString();
+            }
+        ),
+
+        toISOString : function () {
             // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
             var years = Math.abs(this.years()),
                 months = Math.abs(this.months()),
                 (hours ? hours + 'H' : '') +
                 (minutes ? minutes + 'M' : '') +
                 (seconds ? seconds + 'S' : '');
+        },
+
+        localeData : function () {
+            return this._locale;
         }
     });
 
+    moment.duration.fn.toString = moment.duration.fn.toISOString;
+
     function makeDurationGetter(name) {
         moment.duration.fn[name] = function () {
             return this._data[name];
         };
     }
 
-    function makeDurationAsGetter(name, factor) {
-        moment.duration.fn['as' + name] = function () {
-            return +this / factor;
-        };
-    }
-
     for (i in unitMillisecondFactors) {
-        if (unitMillisecondFactors.hasOwnProperty(i)) {
-            makeDurationAsGetter(i, unitMillisecondFactors[i]);
+        if (hasOwnProp(unitMillisecondFactors, i)) {
             makeDurationGetter(i.toLowerCase());
         }
     }
 
-    makeDurationAsGetter('Weeks', 6048e5);
+    moment.duration.fn.asMilliseconds = function () {
+        return this.as('ms');
+    };
+    moment.duration.fn.asSeconds = function () {
+        return this.as('s');
+    };
+    moment.duration.fn.asMinutes = function () {
+        return this.as('m');
+    };
+    moment.duration.fn.asHours = function () {
+        return this.as('h');
+    };
+    moment.duration.fn.asDays = function () {
+        return this.as('d');
+    };
+    moment.duration.fn.asWeeks = function () {
+        return this.as('weeks');
+    };
     moment.duration.fn.asMonths = function () {
-        return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
+        return this.as('M');
+    };
+    moment.duration.fn.asYears = function () {
+        return this.as('y');
     };
-
 
     /************************************
-        Default Lang
+        Default Locale
     ************************************/
 
 
-    // Set default language, other languages will inherit from English.
-    moment.lang('en', {
+    // Set default locale, other locale will inherit from English.
+    moment.locale('en', {
         ordinal : function (number) {
             var b = number % 10,
                 output = (toInt(number % 100 / 10) === 1) ? 'th' :
         }
     });
 
-    /* EMBED_LANGUAGES */
+    /* EMBED_LOCALES */
 
     /************************************
         Exposing Moment
         oldGlobalMoment = globalScope.moment;
         if (shouldDeprecate) {
             globalScope.moment = deprecate(
-                    "Accessing Moment through the global scope is " +
-                    "deprecated, and will be removed in an upcoming " +
-                    "release.",
+                    'Accessing Moment through the global scope is ' +
+                    'deprecated, and will be removed in an upcoming ' +
+                    'release.',
                     moment);
         } else {
             globalScope.moment = moment;
     // CommonJS module is defined
     if (hasModule) {
         module.exports = moment;
-    } else if (typeof define === "function" && define.amd) {
-        define("moment", function (require, exports, module) {
+    } else if (typeof define === 'function' && define.amd) {
+        define('moment', function (require, exports, module) {
             if (module.config && module.config() && module.config().noGlobal === true) {
                 // release the global variable
                 globalScope.moment = oldGlobalMoment;
index 34f8972..b01e2cd 100644 (file)
@@ -8,11 +8,17 @@
                        "Mido",
                        "OsamaK",
                        "زكريا",
-                       "مشعل الحربي"
+                       "مشعل الحربي",
+                       "ترجمان05"
                ]
        },
-       "ooui-dialog-action-close": "أغلق",
        "ooui-outline-control-move-down": "انقل العنصر للأسفل",
        "ooui-outline-control-move-up": "انقل العنصر للأعلى",
-       "ooui-toolbar-more": "مزيد"
+       "ooui-outline-control-remove": "أزل العنصر",
+       "ooui-toolbar-more": "مزيد",
+       "ooui-dialog-message-accept": "موافق",
+       "ooui-dialog-message-reject": "ألغ",
+       "ooui-dialog-process-error": "حدث خطأ",
+       "ooui-dialog-process-dismiss": "أغلق",
+       "ooui-dialog-process-retry": "حاول مرة أخرى"
 }
diff --git a/resources/lib/oojs-ui/i18n/arq.json b/resources/lib/oojs-ui/i18n/arq.json
new file mode 100644 (file)
index 0000000..8098781
--- /dev/null
@@ -0,0 +1,16 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Bachounda"
+               ]
+       },
+       "ooui-outline-control-move-down": "هبط الشيئ للتحت",
+       "ooui-outline-control-move-up": "طلع الشيئ للفوق",
+       "ooui-outline-control-remove": "أمحي العنصر",
+       "ooui-toolbar-more": "زيادة",
+       "ooui-dialog-message-accept": "مليح",
+       "ooui-dialog-message-reject": "رجَع",
+       "ooui-dialog-process-error": "حاجه ما خدمتش مليح",
+       "ooui-dialog-process-dismiss": "أرفضها",
+       "ooui-dialog-process-retry": "عاود جرب"
+}
index eb39dac..87d7688 100644 (file)
@@ -6,13 +6,13 @@
                        "Xuacu"
                ]
        },
-       "ooui-dialog-action-close": "Zarrar",
        "ooui-outline-control-move-down": "Mover abaxo l'elementu",
        "ooui-outline-control-move-up": "Mover arriba l'elementu",
        "ooui-outline-control-remove": "Desaniciar elementu",
        "ooui-toolbar-more": "Más",
-       "ooui-dialog-confirm-title": "Confirmar",
-       "ooui-dialog-confirm-default-prompt": "¿Tas seguru?",
-       "ooui-dialog-confirm-default-ok": "Aceutar",
-       "ooui-dialog-confirm-default-cancel": "Encaboxar"
+       "ooui-dialog-message-accept": "Aceutar",
+       "ooui-dialog-message-reject": "Encaboxar",
+       "ooui-dialog-process-error": "Daqué funcionó mal",
+       "ooui-dialog-process-dismiss": "Descartar",
+       "ooui-dialog-process-retry": "Vuelvi a intentalo"
 }
index 44247ca..6959191 100644 (file)
@@ -6,9 +6,13 @@
                        "Y-M D"
                ]
        },
-       "ooui-dialog-action-close": "Serriñ",
        "ooui-outline-control-move-down": "Lakaat an elfenn da ziskenn",
        "ooui-outline-control-move-up": "Lakaat an elfenn da bignat",
        "ooui-outline-control-remove": "Tennañ an elfenn",
-       "ooui-toolbar-more": "Muioc'h"
+       "ooui-toolbar-more": "Muioc'h",
+       "ooui-dialog-message-accept": "Mat eo",
+       "ooui-dialog-message-reject": "Nullañ",
+       "ooui-dialog-process-error": "Un dra bennak a-dreuz a zo bet",
+       "ooui-dialog-process-dismiss": "Disteurel",
+       "ooui-dialog-process-retry": "Klask en-dro"
 }
index 3ff9763..c3e80fe 100644 (file)
@@ -7,11 +7,14 @@
                        "Pginer",
                        "QuimGil",
                        "SMP",
-                       "Vriullop"
+                       "Vriullop",
+                       "Toniher",
+                       "Edustus"
                ]
        },
-       "ooui-dialog-action-close": "Tanca",
        "ooui-outline-control-move-down": "Baixa element",
        "ooui-outline-control-move-up": "Puja element",
-       "ooui-toolbar-more": "Més"
+       "ooui-toolbar-more": "Més",
+       "ooui-dialog-process-dismiss": "Descarta",
+       "ooui-dialog-process-retry": "Torneu-ho a provar"
 }
index ca6d5b4..a75cf0b 100644 (file)
                        "ශ්වෙත"
                ]
        },
-       "ooui-dialog-action-close": "Zavřít",
        "ooui-outline-control-move-down": "Přesunout položku dolů",
        "ooui-outline-control-move-up": "Přesunout položku nahoru",
        "ooui-outline-control-remove": "Odstranit položku",
        "ooui-toolbar-more": "Další",
-       "ooui-dialog-confirm-title": "Potvrzení",
-       "ooui-dialog-confirm-default-prompt": "Opravdu?",
-       "ooui-dialog-confirm-default-ok": "OK",
-       "ooui-dialog-confirm-default-cancel": "Storno"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Storno",
+       "ooui-dialog-process-error": "Něco se pokazilo",
+       "ooui-dialog-process-dismiss": "Zavřít",
+       "ooui-dialog-process-retry": "Zkusit znovu"
 }
index 97ed48c..546689b 100644 (file)
                        "Tomabrafix"
                ]
        },
-       "ooui-dialog-action-close": "Schließen",
        "ooui-outline-control-move-down": "Element nach unten verschieben",
        "ooui-outline-control-move-up": "Element nach oben verschieben",
        "ooui-outline-control-remove": "Element entfernen",
        "ooui-toolbar-more": "Mehr",
-       "ooui-dialog-confirm-title": "Bestätigen",
-       "ooui-dialog-confirm-default-prompt": "Bist du sicher?",
-       "ooui-dialog-confirm-default-ok": "Okay",
-       "ooui-dialog-confirm-default-cancel": "Abbrechen"
+       "ooui-dialog-message-accept": "Okay",
+       "ooui-dialog-message-reject": "Abbrechen",
+       "ooui-dialog-process-error": "Etwas ist schief gelaufen",
+       "ooui-dialog-process-dismiss": "Ausblenden",
+       "ooui-dialog-process-retry": "Erneut versuchen"
 }
index fa3089f..cddd46e 100644 (file)
                        "Tifa93"
                ]
        },
-       "ooui-dialog-action-close": "Κλείσιμο",
        "ooui-outline-control-move-down": "Μετακίνηση στοιχείου προς τα κάτω",
        "ooui-outline-control-move-up": "Μετακίνηση στοιχείου προς τα επάνω",
        "ooui-outline-control-remove": "Αφαίρεση στοιχείου",
-       "ooui-toolbar-more": "Περισσότερα"
+       "ooui-toolbar-more": "Περισσότερα",
+       "ooui-dialog-message-accept": "ΟΚ",
+       "ooui-dialog-message-reject": "Ακύρωση",
+       "ooui-dialog-process-error": "Κάτι πήγε στραβά",
+       "ooui-dialog-process-dismiss": "Απόρριψη",
+       "ooui-dialog-process-retry": "Δοκιμάστε ξανά"
 }
index 2498a76..9e99440 100644 (file)
@@ -1,28 +1,28 @@
 {
-    "@metadata": {
-        "authors": [
-            "Trevor Parscal",
-            "Ed Sanders",
-            "James D. Forrester",
-            "Raimond Spekking",
-            "Erik Moeller",
-            "Moriel Schottlender",
-            "Yuki Shira",
-            "Siebrand Mazeland",
-            "Rob Moen",
-            "Timo Tijhof",
-            "Roan Kattouw",
-            "Christian Williams",
-            "Amir E. Aharoni"
-        ]
-    },
-    "ooui-dialog-action-close": "Close",
-    "ooui-outline-control-move-down": "Move item down",
-    "ooui-outline-control-move-up": "Move item up",
-    "ooui-outline-control-remove": "Remove item",
-    "ooui-toolbar-more": "More",
-    "ooui-dialog-confirm-title": "Confirm",
-    "ooui-dialog-confirm-default-prompt": "Are you sure?",
-    "ooui-dialog-confirm-default-ok": "OK",
-    "ooui-dialog-confirm-default-cancel": "Cancel"
+       "@metadata": {
+               "authors": [
+                       "Trevor Parscal",
+                       "Ed Sanders",
+                       "James D. Forrester",
+                       "Raimond Spekking",
+                       "Erik Moeller",
+                       "Moriel Schottlender",
+                       "Yuki Shira",
+                       "Siebrand Mazeland",
+                       "Rob Moen",
+                       "Timo Tijhof",
+                       "Roan Kattouw",
+                       "Christian Williams",
+                       "Amir E. Aharoni"
+               ]
+       },
+       "ooui-outline-control-move-down": "Move item down",
+       "ooui-outline-control-move-up": "Move item up",
+       "ooui-outline-control-remove": "Remove item",
+       "ooui-toolbar-more": "More",
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Cancel",
+       "ooui-dialog-process-error": "Something went wrong",
+       "ooui-dialog-process-dismiss": "Dismiss",
+       "ooui-dialog-process-retry": "Try again"
 }
index 76485ea..7660d4a 100644 (file)
                        "PoLuX124",
                        "Ralgis",
                        "Thehelpfulone",
-                       "Gloria sah"
+                       "Gloria sah",
+                       "Macofe"
                ]
        },
-       "ooui-dialog-action-close": "Cerrar",
        "ooui-outline-control-move-down": "Bajar elemento",
        "ooui-outline-control-move-up": "Subir elemento",
        "ooui-outline-control-remove": "Eliminar elemento",
        "ooui-toolbar-more": "Más",
-       "ooui-dialog-confirm-title": "Confirmar",
-       "ooui-dialog-confirm-default-prompt": "¿Está seguro?",
-       "ooui-dialog-confirm-default-ok": "Aceptar",
-       "ooui-dialog-confirm-default-cancel": "Cancelar"
+       "ooui-dialog-message-accept": "Aceptar",
+       "ooui-dialog-message-reject": "Cancelar",
+       "ooui-dialog-process-error": "Algo salió mal",
+       "ooui-dialog-process-dismiss": "Descartar",
+       "ooui-dialog-process-retry": "Intentar de nuevo"
 }
index 164685c..ac3af74 100644 (file)
@@ -5,13 +5,13 @@
                        "Pikne"
                ]
        },
-       "ooui-dialog-action-close": "Sule",
        "ooui-outline-control-move-down": "Liiguta üksust allapoole",
        "ooui-outline-control-move-up": "Liiguta üksust ülespoole",
        "ooui-outline-control-remove": "Eemalda üksus",
        "ooui-toolbar-more": "Veel",
-       "ooui-dialog-confirm-title": "Kinnitus",
-       "ooui-dialog-confirm-default-prompt": "Kas oled kindel?",
-       "ooui-dialog-confirm-default-ok": "Sobib",
-       "ooui-dialog-confirm-default-cancel": "Loobu"
+       "ooui-dialog-message-accept": "Sobib",
+       "ooui-dialog-message-reject": "Loobu",
+       "ooui-dialog-process-error": "Midagi läks valesti",
+       "ooui-dialog-process-dismiss": "Hülga",
+       "ooui-dialog-process-retry": "Proovi uuesti"
 }
index ec051ac..b0ec803 100644 (file)
                        "Armin1392"
                ]
        },
-       "ooui-dialog-action-close": "بستن",
        "ooui-outline-control-move-down": "انتقال مورد به پایین",
        "ooui-outline-control-move-up": "انتقال مورد به بالا",
        "ooui-outline-control-remove": "حذف مورد",
        "ooui-toolbar-more": "بیشتر",
-       "ooui-dialog-confirm-title": "تأیید",
-       "ooui-dialog-confirm-default-prompt": "آیا مطمئن هستید؟",
-       "ooui-dialog-confirm-default-ok": "تأیید",
-       "ooui-dialog-confirm-default-cancel": "لغو"
+       "ooui-dialog-message-accept": "تأیید",
+       "ooui-dialog-message-reject": "لغو",
+       "ooui-dialog-process-error": "مشکلی وجود دارد",
+       "ooui-dialog-process-dismiss": "نپذیرفتن",
+       "ooui-dialog-process-retry": "دوباره امتحان کن"
 }
index 8e8b81e..efaabed 100644 (file)
                        "VezonThunder"
                ]
        },
-       "ooui-dialog-action-close": "Sulje",
        "ooui-outline-control-move-down": "Siirrä kohdetta alaspäin",
        "ooui-outline-control-move-up": "Siirrä kohdetta ylöspäin",
        "ooui-outline-control-remove": "Poista kohde",
        "ooui-toolbar-more": "Lisää",
-       "ooui-dialog-confirm-title": "Vahvista",
-       "ooui-dialog-confirm-default-prompt": "Oletko varma?",
-       "ooui-dialog-confirm-default-ok": "OK",
-       "ooui-dialog-confirm-default-cancel": "Peruuta"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Peruuta",
+       "ooui-dialog-process-error": "Jokin meni pieleen",
+       "ooui-dialog-process-dismiss": "Hylkää",
+       "ooui-dialog-process-retry": "Yritä uudelleen"
 }
index 6b8871a..8ff5475 100644 (file)
                        "Trizek",
                        "Urhixidur",
                        "Verdy p",
-                       "Wyz"
+                       "Wyz",
+                       "SnowedEarth"
                ]
        },
-       "ooui-dialog-action-close": "Fermer",
        "ooui-outline-control-move-down": "Faire descendre l’élément",
        "ooui-outline-control-move-up": "Faire monter l’élément",
        "ooui-outline-control-remove": "Supprimer l’élément",
        "ooui-toolbar-more": "Plus",
-       "ooui-dialog-confirm-title": "Confirmer",
-       "ooui-dialog-confirm-default-prompt": "Êtes-vous sûr ?",
-       "ooui-dialog-confirm-default-ok": "OK",
-       "ooui-dialog-confirm-default-cancel": "Annuler"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Annuler",
+       "ooui-dialog-process-error": "Quelque chose a mal tourné",
+       "ooui-dialog-process-dismiss": "Rejeter",
+       "ooui-dialog-process-retry": "Réessayez"
 }
diff --git a/resources/lib/oojs-ui/i18n/gd.json b/resources/lib/oojs-ui/i18n/gd.json
new file mode 100644 (file)
index 0000000..6a83c9c
--- /dev/null
@@ -0,0 +1,13 @@
+{
+       "@metadata": {
+               "authors": [
+                       "GunChleoc"
+               ]
+       },
+       "ooui-outline-control-move-down": "Gluais nì sìos",
+       "ooui-outline-control-move-up": "Gluais nì suas",
+       "ooui-outline-control-remove": "Thoir air falbh an nì",
+       "ooui-toolbar-more": "Barrachd",
+       "ooui-dialog-message-accept": "Ceart ma-thà",
+       "ooui-dialog-message-reject": "Sguir dheth"
+}
index a4b6787..eac992f 100644 (file)
@@ -6,13 +6,13 @@
                        "Toliño"
                ]
        },
-       "ooui-dialog-action-close": "Pechar",
        "ooui-outline-control-move-down": "Mover o elemento abaixo",
        "ooui-outline-control-move-up": "Mover o elemento arriba",
        "ooui-outline-control-remove": "Eliminar o elemento",
        "ooui-toolbar-more": "Máis",
-       "ooui-dialog-confirm-title": "Confirmar",
-       "ooui-dialog-confirm-default-prompt": "Está seguro?",
-       "ooui-dialog-confirm-default-ok": "Aceptar",
-       "ooui-dialog-confirm-default-cancel": "Cancelar"
+       "ooui-dialog-message-accept": "Aceptar",
+       "ooui-dialog-message-reject": "Cancelar",
+       "ooui-dialog-process-error": "Algo foi mal",
+       "ooui-dialog-process-dismiss": "Agochar",
+       "ooui-dialog-process-retry": "Inténteo de novo"
 }
index d72b3af..2d8315b 100644 (file)
@@ -6,9 +6,12 @@
                        "The Discoverer"
                ]
        },
-       "ooui-dialog-action-close": "બંધ કરો",
        "ooui-outline-control-move-down": "વસ્તુ નીચે ખસેડો",
        "ooui-outline-control-move-up": "વસ્તુ ઉપર ખસેડો",
        "ooui-outline-control-remove": "વસ્તુ હટાવો",
-       "ooui-toolbar-more": "વધુ"
+       "ooui-toolbar-more": "વધુ",
+       "ooui-dialog-message-accept": "બરાબર",
+       "ooui-dialog-message-reject": "રદ કરો",
+       "ooui-dialog-process-error": "કંઇક ગરબડ થઇ",
+       "ooui-dialog-process-retry": "ફરી પ્રયત્ન કરો"
 }
index 26660f9..bbaf4c1 100644 (file)
                        "קיפודנחש"
                ]
        },
-       "ooui-dialog-action-close": "סגירה",
        "ooui-outline-control-move-down": "להזיז את הפריט מטה",
        "ooui-outline-control-move-up": "להזיז את הפריט מעלה",
        "ooui-outline-control-remove": "להסיר את הפריט",
        "ooui-toolbar-more": "עוד",
-       "ooui-dialog-confirm-title": "אישור",
-       "ooui-dialog-confirm-default-prompt": "באמת?",
-       "ooui-dialog-confirm-default-ok": "אישור",
-       "ooui-dialog-confirm-default-cancel": "ביטול"
+       "ooui-dialog-message-accept": "אישור",
+       "ooui-dialog-message-reject": "ביטול",
+       "ooui-dialog-process-error": "משהו השתבש",
+       "ooui-dialog-process-dismiss": "לוותר",
+       "ooui-dialog-process-retry": "לנסות שוב"
 }
index f16f984..c3724cf 100644 (file)
@@ -3,12 +3,17 @@
                "authors": [
                        "MaGa",
                        "Roberta F.",
-                       "SpeedyGonsales"
+                       "SpeedyGonsales",
+                       "Zeljko.filipin"
                ]
        },
-       "ooui-dialog-action-close": "zatvori",
        "ooui-outline-control-move-down": "Premjesti stavku dolje",
        "ooui-outline-control-move-up": "Premjesti stavku gore",
        "ooui-outline-control-remove": "Ukloni",
-       "ooui-toolbar-more": "Više mogućnosti"
+       "ooui-toolbar-more": "Više",
+       "ooui-dialog-message-accept": "U redu",
+       "ooui-dialog-message-reject": "Odustani",
+       "ooui-dialog-process-error": "Nešto je pošlo po zlu",
+       "ooui-dialog-process-dismiss": "Zatvori",
+       "ooui-dialog-process-retry": "Pokušajte ponovo"
 }
index 0f423b3..9117a05 100644 (file)
@@ -5,15 +5,16 @@
                        "Einstein2",
                        "Misibacsi",
                        "ViDam",
-                       "Tacsipacsi"
+                       "Tacsipacsi",
+                       "Csega"
                ]
        },
-       "ooui-dialog-action-close": "Bezár",
        "ooui-outline-control-move-down": "Elem mozgatása lefelé",
        "ooui-outline-control-move-up": "Elem mozgatása felfelé",
        "ooui-outline-control-remove": "Elem eltávolítása",
        "ooui-toolbar-more": "Tovább...",
-       "ooui-dialog-confirm-title": "Megerősítés",
-       "ooui-dialog-confirm-default-prompt": "Biztos vagy benne?",
-       "ooui-dialog-confirm-default-cancel": "Mégse"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Mégse",
+       "ooui-dialog-process-dismiss": "Elrejt",
+       "ooui-dialog-process-retry": "Próbáld újra"
 }
index f1c9ced..b374b6f 100644 (file)
@@ -4,13 +4,13 @@
                        "McDutchie"
                ]
        },
-       "ooui-dialog-action-close": "Clauder",
        "ooui-outline-control-move-down": "Displaciar elemento in basso",
        "ooui-outline-control-move-up": "Displaciar elemento in alto",
        "ooui-outline-control-remove": "Remover elemento",
        "ooui-toolbar-more": "Plus",
-       "ooui-dialog-confirm-title": "Confirmation",
-       "ooui-dialog-confirm-default-prompt": "Es tu secur?",
-       "ooui-dialog-confirm-default-ok": "OK",
-       "ooui-dialog-confirm-default-cancel": "Cancellar"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Cancellar",
+       "ooui-dialog-process-error": "Qualcosa ha vadite mal",
+       "ooui-dialog-process-dismiss": "Clauder",
+       "ooui-dialog-process-retry": "Reprobar"
 }
index 5d9e3bb..81a91ed 100644 (file)
@@ -4,13 +4,13 @@
                        "Lam-ang"
                ]
        },
-       "ooui-dialog-action-close": "Irekep",
        "ooui-outline-control-move-down": "Ipababa ti banag",
        "ooui-outline-control-move-up": "Ipangato ti banag",
        "ooui-outline-control-remove": "Ikkaten ti banag",
        "ooui-toolbar-more": "Adu pay",
-       "ooui-dialog-confirm-title": "Pasingkedan",
-       "ooui-dialog-confirm-default-prompt": "Siguradoka kadi?",
-       "ooui-dialog-confirm-default-ok": "Sige",
-       "ooui-dialog-confirm-default-cancel": "Ukasen"
+       "ooui-dialog-message-accept": "Sige",
+       "ooui-dialog-message-reject": "Ukasen",
+       "ooui-dialog-process-error": "Adda madi a napasamak",
+       "ooui-dialog-process-dismiss": "Pugsayen",
+       "ooui-dialog-process-retry": "Padasen manen"
 }
index 162fa8c..3d4e049 100644 (file)
                        "Ontsed"
                ]
        },
-       "ooui-dialog-action-close": "Chiudi",
        "ooui-outline-control-move-down": "Sposta in basso",
        "ooui-outline-control-move-up": "Sposta in alto",
        "ooui-outline-control-remove": "Rimuovi elemento",
        "ooui-toolbar-more": "Altro",
-       "ooui-dialog-confirm-title": "Conferma",
-       "ooui-dialog-confirm-default-prompt": "Sei sicuro?",
-       "ooui-dialog-confirm-default-ok": "OK",
-       "ooui-dialog-confirm-default-cancel": "Annulla"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Annulla",
+       "ooui-dialog-process-error": "Qualcosa è andato storto",
+       "ooui-dialog-process-dismiss": "Nascondi",
+       "ooui-dialog-process-retry": "Riprova"
 }
index 70c1e07..2ac8dc1 100644 (file)
@@ -4,16 +4,17 @@
                        "Fryed-peach",
                        "Miya",
                        "Penn Station",
-                       "Shirayuki"
+                       "Shirayuki",
+                       "Takot"
                ]
        },
-       "ooui-dialog-action-close": "閉じる",
        "ooui-outline-control-move-down": "項目を下に移動させる",
        "ooui-outline-control-move-up": "項目を上に移動させる",
        "ooui-outline-control-remove": "項目を除去",
        "ooui-toolbar-more": "その他",
-       "ooui-dialog-confirm-title": "確認",
-       "ooui-dialog-confirm-default-prompt": "本当によろしいですか?",
-       "ooui-dialog-confirm-default-ok": "OK",
-       "ooui-dialog-confirm-default-cancel": "キャンセル"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "キャンセル",
+       "ooui-dialog-process-error": "エラーが発生しました…",
+       "ooui-dialog-process-dismiss": "閉じる",
+       "ooui-dialog-process-retry": "もう一度お試しください"
 }
index 85931f5..0b89e37 100644 (file)
@@ -5,13 +5,13 @@
                        "Nayvik"
                ]
        },
-       "ooui-dialog-action-close": "ಮುಚ್ಚಿ",
        "ooui-outline-control-move-down": "ವಸ್ತು ಕೆಲ್ಗೆ ಸ್ಥಲಾನ್ಥರಿಸು",
        "ooui-outline-control-move-up": "ವಸ್ತು ಮೆಲೆ ಸ್ಥಲಾನ್ಥರಿಸು",
        "ooui-outline-control-remove": "ವಸ್ತು ತೆಗೆ",
        "ooui-toolbar-more": "ಹೆಚ್ಚು",
-       "ooui-dialog-confirm-title": "ಧೃಡಪಡಿಸು",
-       "ooui-dialog-confirm-default-prompt": "ನೀವು ಖ‍ಚಿತವಾಗಿದ್ದೀರಾ?",
-       "ooui-dialog-confirm-default-ok": "ಸರಿ",
-       "ooui-dialog-confirm-default-cancel": "ರದ್ದು"
+       "ooui-dialog-message-accept": "ಸರಿ",
+       "ooui-dialog-message-reject": "ರದ್ದು",
+       "ooui-dialog-process-error": "ಎನೋ ಎಡವಟ್ಟಾಗಿದೆ....",
+       "ooui-dialog-process-dismiss": "ತೆಗೆದುಹಾಕು",
+       "ooui-dialog-process-retry": "ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"
 }
index afd8753..82d91ab 100644 (file)
@@ -6,16 +6,17 @@
                        "Kwj2772",
                        "LFM",
                        "아라",
-                       "고기랑"
+                       "고기랑",
+                       "Ryuch"
                ]
        },
-       "ooui-dialog-action-close": "닫기",
        "ooui-outline-control-move-down": "항목을 아래로 옮기기",
        "ooui-outline-control-move-up": "항목을 위로 옮기기",
        "ooui-outline-control-remove": "항목 지우기",
        "ooui-toolbar-more": "더 보기",
-       "ooui-dialog-confirm-title": "확인",
-       "ooui-dialog-confirm-default-prompt": "확실합니까?",
-       "ooui-dialog-confirm-default-ok": "확인",
-       "ooui-dialog-confirm-default-cancel": "취소"
+       "ooui-dialog-message-accept": "확인",
+       "ooui-dialog-message-reject": "취소",
+       "ooui-dialog-process-error": "무언가가 잘못되었습니다",
+       "ooui-dialog-process-dismiss": "숨기기",
+       "ooui-dialog-process-retry": "다시 시도하세요"
 }
index e2e12ab..1cbcb8a 100644 (file)
                        "Викиней"
                ]
        },
-       "ooui-dialog-action-close": "Zoumaachen",
        "ooui-outline-control-move-down": "Element erof réckelen",
        "ooui-outline-control-move-up": "Element erop réckelen",
        "ooui-outline-control-remove": "Element ewechhuelen",
        "ooui-toolbar-more": "Méi",
-       "ooui-dialog-confirm-title": "Confirméieren",
-       "ooui-dialog-confirm-default-prompt": "Sidd Dir sécher?",
-       "ooui-dialog-confirm-default-ok": "OK",
-       "ooui-dialog-confirm-default-cancel": "Ofbriechen"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Ofbriechen",
+       "ooui-dialog-process-error": "Et ass eppes schif gaang",
+       "ooui-dialog-process-dismiss": "Verwerfen",
+       "ooui-dialog-process-retry": "Nach eng Kéier probéieren"
 }
index 7ad74dc..32fc9fe 100644 (file)
@@ -8,12 +8,10 @@
                        "PeterisP"
                ]
        },
-       "ooui-dialog-action-close": "Aizvērt",
        "ooui-outline-control-move-down": "Pārvietot vienumu uz leju",
        "ooui-outline-control-move-up": "Pārvietot vienumu uz augšu",
        "ooui-toolbar-more": "Vairāk",
-       "ooui-dialog-confirm-title": "Apstiprināt",
-       "ooui-dialog-confirm-default-prompt": "Vai esat pārliecināts?",
-       "ooui-dialog-confirm-default-ok": "Labi",
-       "ooui-dialog-confirm-default-cancel": "Atcelt"
+       "ooui-dialog-message-accept": "Labi",
+       "ooui-dialog-message-reject": "Atcelt",
+       "ooui-dialog-process-retry": "Mēģināt vēlreiz"
 }
index 90685ea..d628034 100644 (file)
@@ -6,13 +6,13 @@
                        "Iwan Novirion"
                ]
        },
-       "ooui-dialog-action-close": "Затвори",
        "ooui-outline-control-move-down": "Помести надолу",
        "ooui-outline-control-move-up": "Помести нагоре",
        "ooui-outline-control-remove": "Отстрани ставка",
        "ooui-toolbar-more": "Повеќе",
-       "ooui-dialog-confirm-title": "Потврди",
-       "ooui-dialog-confirm-default-prompt": "Дали сте сигурни?",
-       "ooui-dialog-confirm-default-ok": "ОК",
-       "ooui-dialog-confirm-default-cancel": "Откажи"
+       "ooui-dialog-message-accept": "ОК",
+       "ooui-dialog-message-reject": "Откажи",
+       "ooui-dialog-process-error": "Нешто не е во ред",
+       "ooui-dialog-process-dismiss": "Тргни",
+       "ooui-dialog-process-retry": "Обиди се пак"
 }
index c2d9bc8..823d493 100644 (file)
@@ -6,12 +6,12 @@
                        "Pizza1016"
                ]
        },
-       "ooui-dialog-action-close": "Tutup",
        "ooui-outline-control-move-down": "Alihkan perkara ke bawah",
        "ooui-outline-control-move-up": "Alihkan perkara ke atas",
        "ooui-outline-control-remove": "Buang perkara",
        "ooui-toolbar-more": "Selebihnya",
-       "ooui-dialog-confirm-title": "Mengesahkan",
-       "ooui-dialog-confirm-default-prompt": "Adakah anda pasti?",
-       "ooui-dialog-confirm-default-cancel": "Batal"
+       "ooui-dialog-message-reject": "Batal",
+       "ooui-dialog-process-error": "Ada masalah",
+       "ooui-dialog-process-dismiss": "Singkir",
+       "ooui-dialog-process-retry": "Cuba lagi"
 }
index 43a64cd..3fe75e3 100644 (file)
@@ -5,12 +5,17 @@
                        "Event",
                        "Jeblad",
                        "Laaknor",
-                       "Njardarlogar"
+                       "Njardarlogar",
+                       "Jdforrester"
                ]
        },
-       "ooui-dialog-action-close": "Lukk",
        "ooui-outline-control-move-down": "Flytt ned",
        "ooui-outline-control-move-up": "Flytt opp",
        "ooui-outline-control-remove": "Fjern element",
-       "ooui-toolbar-more": "Mer"
+       "ooui-toolbar-more": "Mer",
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Avbryt",
+       "ooui-dialog-process-error": "Noe gikk galt",
+       "ooui-dialog-process-dismiss": "Lukk",
+       "ooui-dialog-process-retry": "Prøv igjen"
 }
index dbae538..a7b4c08 100644 (file)
                        "Gloria sah"
                ]
        },
-       "ooui-dialog-action-close": "Sluiten",
        "ooui-outline-control-move-down": "Item omlaag verplaatsen",
        "ooui-outline-control-move-up": "Item omhoog verplaatsen",
        "ooui-outline-control-remove": "Item verwijderen",
        "ooui-toolbar-more": "Meer",
-       "ooui-dialog-confirm-title": "Bevestigen",
-       "ooui-dialog-confirm-default-prompt": "Weet u het zeker?",
-       "ooui-dialog-confirm-default-ok": "Oké",
-       "ooui-dialog-confirm-default-cancel": "Annuleren"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Annuleren",
+       "ooui-dialog-process-error": "Er is iets misgegaan",
+       "ooui-dialog-process-dismiss": "Sluiten",
+       "ooui-dialog-process-retry": "Opnieuw proberen"
 }
index 35e7ee4..c62782e 100644 (file)
@@ -5,9 +5,13 @@
                        "Tumsaa"
                ]
        },
-       "ooui-dialog-action-close": "Cufi",
        "ooui-outline-control-move-down": "Gad buusi",
        "ooui-outline-control-move-up": "Ol baasi",
        "ooui-outline-control-remove": "Balleessi",
-       "ooui-toolbar-more": "Dabalata"
+       "ooui-toolbar-more": "Dabalata",
+       "ooui-dialog-message-accept": "Tole",
+       "ooui-dialog-message-reject": "Dhiisi",
+       "ooui-dialog-process-error": "Dogoggorri wayii ummameera",
+       "ooui-dialog-process-dismiss": "Didi",
+       "ooui-dialog-process-retry": "Itti deebi'ii yaali"
 }
index bea0c3a..7978673 100644 (file)
                        "Andrzej aa"
                ]
        },
-       "ooui-dialog-action-close": "Zamknij",
        "ooui-outline-control-move-down": "Przenieś niżej",
        "ooui-outline-control-move-up": "Przenieś wyżej",
        "ooui-outline-control-remove": "Usuń element",
        "ooui-toolbar-more": "Więcej",
-       "ooui-dialog-confirm-title": "Potwierdź",
-       "ooui-dialog-confirm-default-prompt": "Jesteś pewien?",
-       "ooui-dialog-confirm-default-ok": "OK",
-       "ooui-dialog-confirm-default-cancel": "Anuluj"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Anuluj",
+       "ooui-dialog-process-error": "Coś poszło nie tak",
+       "ooui-dialog-process-dismiss": "Ukryj",
+       "ooui-dialog-process-retry": "Spróbuj ponownie"
 }
index e9ad6de..5cb3e3d 100644 (file)
                        "SandroHc"
                ]
        },
-       "ooui-dialog-action-close": "Fechar",
        "ooui-outline-control-move-down": "Mover item para baixo",
        "ooui-outline-control-move-up": "Mover item para cima",
        "ooui-outline-control-remove": "Remover elemento",
        "ooui-toolbar-more": "Mais",
-       "ooui-dialog-confirm-title": "Confirmar",
-       "ooui-dialog-confirm-default-prompt": "Tem a certeza?",
-       "ooui-dialog-confirm-default-ok": "Aceitar",
-       "ooui-dialog-confirm-default-cancel": "Cancelar"
+       "ooui-dialog-message-accept": "Aceitar",
+       "ooui-dialog-message-reject": "Cancelar",
+       "ooui-dialog-process-error": "Algo correu mal",
+       "ooui-dialog-process-dismiss": "Ignorar",
+       "ooui-dialog-process-retry": "Tentar novamente"
 }
index 87198e5..9b3bb60 100644 (file)
                        "Sayak Sarkar",
                        "Shirayuki",
                        "Siebrand",
-                       "Trevor Parscal"
+                       "Trevor Parscal",
+                       "Liuxinyu970226"
                ]
        },
-       "ooui-dialog-action-close": "Label text for button to exit from dialog.\n\n{{Identical|Close}}",
        "ooui-outline-control-move-down": "Tool tip for a button that moves items in a list down one place",
        "ooui-outline-control-move-up": "Tool tip for a button that moves items in a list up one place",
        "ooui-outline-control-remove": "Tool tip for a button that removes items from a list.\n{{Identical|Remove item}}",
        "ooui-toolbar-more": "Label for the toolbar group that contains a list of all other available tools.\n{{Identical|More}}",
-       "ooui-dialog-confirm-title": "Title of the generic dialog used to confirm things.\n{{Identical|Confirm}}",
-       "ooui-dialog-confirm-default-prompt": "The default prompt of a confirmation dialog.\n{{Identical|Are you sure?}}",
-       "ooui-dialog-confirm-default-ok": "The default OK button text on a confirmation dialog.\n{{Identical|OK}}",
-       "ooui-dialog-confirm-default-cancel": "The default cancel button text on a confirmation dialog.\n{{Identical|Cancel}}"
+       "ooui-dialog-message-accept": "Default label for the accept button of a message dialog\n{{Identical|OK}}",
+       "ooui-dialog-message-reject": "Default label for the reject button of a message dialog\n{{Identical|Cancel}}",
+       "ooui-dialog-process-error": "Title for process dialog error description",
+       "ooui-dialog-process-dismiss": "Label for process dialog dismiss error button, visible when describing errors\n{{Identical|Dismiss}}",
+       "ooui-dialog-process-retry": "Label for process dialog retry action button, visible when describing recoverable errors\n{{Identical|Try again}}"
 }
index 0181514..06e0f1d 100644 (file)
@@ -8,13 +8,13 @@
                        "Gloria sah"
                ]
        },
-       "ooui-dialog-action-close": "Închide",
        "ooui-outline-control-move-down": "Mută elementul mai jos",
        "ooui-outline-control-move-up": "Mută elementul mai sus",
        "ooui-outline-control-remove": "Elimină elementul",
        "ooui-toolbar-more": "Mai mult",
-       "ooui-dialog-confirm-title": "Confirmare",
-       "ooui-dialog-confirm-default-prompt": "Sunteți sigur(ă)?",
-       "ooui-dialog-confirm-default-ok": "OK",
-       "ooui-dialog-confirm-default-cancel": "Revocare"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Revocare",
+       "ooui-dialog-process-error": "Ceva nu a funcționat",
+       "ooui-dialog-process-dismiss": "Renunțare",
+       "ooui-dialog-process-retry": "Reîncearcă"
 }
index 435f20c..efd1062 100644 (file)
                        "Умар"
                ]
        },
-       "ooui-dialog-action-close": "Закрыть",
        "ooui-outline-control-move-down": "Переместить элемент вниз",
        "ooui-outline-control-move-up": "Переместить элемент вверх",
        "ooui-outline-control-remove": "Удалить пункт",
        "ooui-toolbar-more": "Ещё",
-       "ooui-dialog-confirm-title": "Подтвердить",
-       "ooui-dialog-confirm-default-prompt": "Вы уверены?",
-       "ooui-dialog-confirm-default-ok": "ОК",
-       "ooui-dialog-confirm-default-cancel": "Отмена"
+       "ooui-dialog-message-accept": "ОК",
+       "ooui-dialog-message-reject": "Отмена",
+       "ooui-dialog-process-error": "Что-то пошло не так",
+       "ooui-dialog-process-dismiss": "Закрыть",
+       "ooui-dialog-process-retry": "Попробовать ещё раз"
 }
index f0ccce5..5737548 100644 (file)
@@ -7,13 +7,13 @@
                        "Yerpo"
                ]
        },
-       "ooui-dialog-action-close": "Zapri",
        "ooui-outline-control-move-down": "Prestavi predmet nižje",
        "ooui-outline-control-move-up": "Prestavi predmet višje",
        "ooui-outline-control-remove": "Odstrani vnos",
        "ooui-toolbar-more": "Več",
-       "ooui-dialog-confirm-title": "Potrdi",
-       "ooui-dialog-confirm-default-prompt": "Ste prepričani?",
-       "ooui-dialog-confirm-default-ok": "V redu",
-       "ooui-dialog-confirm-default-cancel": "Prekliči"
+       "ooui-dialog-message-accept": "V redu",
+       "ooui-dialog-message-reject": "Prekliči",
+       "ooui-dialog-process-error": "Nekaj je šlo narobe",
+       "ooui-dialog-process-dismiss": "Skrij",
+       "ooui-dialog-process-retry": "Poskusi znova"
 }
index 44dfd60..ec18019 100644 (file)
@@ -4,16 +4,16 @@
                        "Euriditi",
                        "Kushtrim",
                        "Elioqoshi",
-                       "GretaDoci"
+                       "GretaDoci",
+                       "Gertakapllani"
                ]
        },
-       "ooui-dialog-action-close": "Mbylle",
        "ooui-outline-control-move-down": "Zhvendose artikullin më poshtë",
        "ooui-outline-control-move-up": "Zhvendose artikullin më lart",
        "ooui-outline-control-remove": "Hiq artikullin",
        "ooui-toolbar-more": "Më tepër...",
-       "ooui-dialog-confirm-title": "Konfirmo",
-       "ooui-dialog-confirm-default-prompt": "A jeni i sigurt?",
-       "ooui-dialog-confirm-default-ok": "Në rregull",
-       "ooui-dialog-confirm-default-cancel": "Anullo"
+       "ooui-dialog-message-accept": "Në rregull",
+       "ooui-dialog-message-reject": "Anullo",
+       "ooui-dialog-process-error": "Diçka shkoi keq",
+       "ooui-dialog-process-retry": "Provo përsëri"
 }
index 308ed84..d653356 100644 (file)
@@ -6,13 +6,13 @@
                        "Милан Јелисавчић"
                ]
        },
-       "ooui-dialog-action-close": "Затвори",
        "ooui-outline-control-move-down": "Премести ставку на доле",
        "ooui-outline-control-move-up": "Премести ставку на горе",
        "ooui-outline-control-remove": "Уклони ставку",
        "ooui-toolbar-more": "Више",
-       "ooui-dialog-confirm-title": "Потврди",
-       "ooui-dialog-confirm-default-prompt": "Јесте ли сигурни?",
-       "ooui-dialog-confirm-default-ok": "У реду",
-       "ooui-dialog-confirm-default-cancel": "Откажи"
+       "ooui-dialog-message-accept": "У реду",
+       "ooui-dialog-message-reject": "Откажи",
+       "ooui-dialog-process-error": "Нешто је пошло наопако",
+       "ooui-dialog-process-dismiss": "Одбаци",
+       "ooui-dialog-process-retry": "Покушај поново"
 }
index fbd03de..40305d0 100644 (file)
                        "Lokal Profil"
                ]
        },
-       "ooui-dialog-action-close": "Stäng",
        "ooui-outline-control-move-down": "Flytta ned objekt",
        "ooui-outline-control-move-up": "Flytta upp objekt",
        "ooui-outline-control-remove": "Ta bort objekt",
        "ooui-toolbar-more": "Mer",
-       "ooui-dialog-confirm-title": "Bekräfta",
-       "ooui-dialog-confirm-default-prompt": "Är du säker?",
-       "ooui-dialog-confirm-default-ok": "OK",
-       "ooui-dialog-confirm-default-cancel": "Avbryt"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Avbryt",
+       "ooui-dialog-process-error": "Något gick fel",
+       "ooui-dialog-process-dismiss": "Stäng",
+       "ooui-dialog-process-retry": "Försök igen"
 }
index f9c46d7..510e468 100644 (file)
@@ -5,8 +5,11 @@
                        "Muddyb Blast Producer"
                ]
        },
-       "ooui-dialog-action-close": "Funga",
        "ooui-outline-control-move-down": "Sogeza kipengee chini",
        "ooui-outline-control-move-up": "Sogeza kipengee juu",
-       "ooui-toolbar-more": "Zaidi"
+       "ooui-outline-control-remove": "Toa kitu",
+       "ooui-toolbar-more": "Zaidi",
+       "ooui-dialog-message-accept": "Sawa",
+       "ooui-dialog-message-reject": "Batilisha",
+       "ooui-dialog-process-retry": "Jaribu tena"
 }
index 3717cf9..82f7c6c 100644 (file)
@@ -7,11 +7,12 @@
                        "Maidis",
                        "Rapsar",
                        "Talha Samil Cakir",
-                       "TurkishStyles"
+                       "TurkishStyles",
+                       "Sayginer"
                ]
        },
-       "ooui-dialog-action-close": "Kapat",
        "ooui-outline-control-move-down": "Ögeyi aşağı taşı",
        "ooui-outline-control-move-up": "Ögeyi yukarı taşı",
-       "ooui-toolbar-more": "Daha fazla"
+       "ooui-toolbar-more": "Daha fazla",
+       "ooui-dialog-process-retry": "Tekrar dene"
 }
index 2bdac54..d6034f0 100644 (file)
                        "Ата"
                ]
        },
-       "ooui-dialog-action-close": "Закрити",
        "ooui-outline-control-move-down": "Перемістити елемент униз",
        "ooui-outline-control-move-up": "Перемістити елемент вгору",
        "ooui-outline-control-remove": "Видалити елемент",
-       "ooui-toolbar-more": "Більше"
+       "ooui-toolbar-more": "Більше",
+       "ooui-dialog-message-accept": "Готово",
+       "ooui-dialog-message-reject": "Скасувати",
+       "ooui-dialog-process-error": "Щось пішло не так",
+       "ooui-dialog-process-dismiss": "Приховати",
+       "ooui-dialog-process-retry": "Спробуйте ще раз"
 }
index 9cc4543..205cbe8 100644 (file)
@@ -6,13 +6,13 @@
                        "Minh Nguyen"
                ]
        },
-       "ooui-dialog-action-close": "Đóng",
        "ooui-outline-control-move-down": "Chuyển mục xuống",
        "ooui-outline-control-move-up": "Chuyển mục lên",
        "ooui-outline-control-remove": "Xóa khoản",
        "ooui-toolbar-more": "Thêm",
-       "ooui-dialog-confirm-title": "Xác nhận",
-       "ooui-dialog-confirm-default-prompt": "Bạn có chắc chắn?",
-       "ooui-dialog-confirm-default-ok": "OK",
-       "ooui-dialog-confirm-default-cancel": "Hủy bỏ"
+       "ooui-dialog-message-accept": "OK",
+       "ooui-dialog-message-reject": "Hủy bỏ",
+       "ooui-dialog-process-error": "Đã bị trục trặc",
+       "ooui-dialog-process-dismiss": "Bỏ qua",
+       "ooui-dialog-process-retry": "Thử lại"
 }
index 01a22d1..a850fce 100644 (file)
@@ -6,13 +6,13 @@
                        "十弌"
                ]
        },
-       "ooui-dialog-action-close": "שליסן",
        "ooui-outline-control-move-down": "רוקן עלעמענט אראפ",
        "ooui-outline-control-move-up": "רוקן עלעמענט ארויף",
        "ooui-outline-control-remove": "אַראָפנעמען איינס",
        "ooui-toolbar-more": "נאך",
-       "ooui-dialog-confirm-title": "באַשטעטיקן",
-       "ooui-dialog-confirm-default-prompt": "איר זענט זיכער?",
-       "ooui-dialog-confirm-default-ok": "יאָ",
-       "ooui-dialog-confirm-default-cancel": "אַנולירן"
+       "ooui-dialog-message-accept": "יאָ",
+       "ooui-dialog-message-reject": "אַנולירן",
+       "ooui-dialog-process-error": "עפעס איז דורכגעפאלן",
+       "ooui-dialog-process-dismiss": "צומאַכן",
+       "ooui-dialog-process-retry": "פרובירט נאכאמאל"
 }
diff --git a/resources/lib/oojs-ui/i18n/yue.json b/resources/lib/oojs-ui/i18n/yue.json
new file mode 100644 (file)
index 0000000..81ad9a9
--- /dev/null
@@ -0,0 +1,16 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Deryck Chan"
+               ]
+       },
+       "ooui-outline-control-move-down": "向下搬",
+       "ooui-outline-control-move-up": "向上搬",
+       "ooui-outline-control-remove": "拎走",
+       "ooui-toolbar-more": "仲有...",
+       "ooui-dialog-message-accept": "好",
+       "ooui-dialog-message-reject": "取消",
+       "ooui-dialog-process-error": "唔對路",
+       "ooui-dialog-process-dismiss": "閂咗佢",
+       "ooui-dialog-process-retry": "再試過"
+}
index 8d1c09f..02bdafa 100644 (file)
                        "Xiaomingyan",
                        "Yfdyh000",
                        "Zhangjintao",
-                       "乌拉跨氪"
+                       "乌拉跨氪",
+                       "Great Brightstar"
                ]
        },
-       "ooui-dialog-action-close": "关闭",
        "ooui-outline-control-move-down": "下移项",
        "ooui-outline-control-move-up": "上移项",
        "ooui-outline-control-remove": "删除项",
        "ooui-toolbar-more": "更多",
-       "ooui-dialog-confirm-title": "确认",
-       "ooui-dialog-confirm-default-prompt": "您确定吗?",
-       "ooui-dialog-confirm-default-ok": "好",
-       "ooui-dialog-confirm-default-cancel": "取消"
+       "ooui-dialog-message-accept": "确定",
+       "ooui-dialog-message-reject": "取消",
+       "ooui-dialog-process-error": "发生一些错误",
+       "ooui-dialog-process-dismiss": "解除",
+       "ooui-dialog-process-retry": "重试"
 }
index 255658b..05fb20d 100644 (file)
                        "Cwlin0416"
                ]
        },
-       "ooui-dialog-action-close": "關閉",
        "ooui-outline-control-move-down": "項目下移",
        "ooui-outline-control-move-up": "項目上移",
        "ooui-outline-control-remove": "移除項目",
        "ooui-toolbar-more": "更多",
-       "ooui-dialog-confirm-title": "確認",
-       "ooui-dialog-confirm-default-prompt": "您確定嗎?",
-       "ooui-dialog-confirm-default-ok": "確定",
-       "ooui-dialog-confirm-default-cancel": "取消"
+       "ooui-dialog-message-accept": "確定",
+       "ooui-dialog-message-reject": "取消",
+       "ooui-dialog-process-error": "發生不明錯誤",
+       "ooui-dialog-process-dismiss": "放棄",
+       "ooui-dialog-process-retry": "再試一次"
 }
diff --git a/resources/lib/oojs-ui/images/anchor.png b/resources/lib/oojs-ui/images/anchor.png
new file mode 100644 (file)
index 0000000..470a7ac
Binary files /dev/null and b/resources/lib/oojs-ui/images/anchor.png differ
diff --git a/resources/lib/oojs-ui/images/anchor.svg b/resources/lib/oojs-ui/images/anchor.svg
new file mode 100644 (file)
index 0000000..3694391
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="15" height="8" viewBox="0 0 15 8">
+    <g id="anchor">
+        <polygon id="outline" style="fill:#808080;" points="7.609,2.499 2.096,8 13.125,8"/>
+        <polygon id="fill" style="fill:#FFFFFF;" points="7.609,3 2.598,8 12.622,8"/>
+    </g>
+</svg>
index 1075110..76df479 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/accept.png and b/resources/lib/oojs-ui/images/icons/accept.png differ
index ff52c32..b385a74 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="apply" opacity=".75">
-        <path id="check" fill-rule="evenodd" clip-rule="evenodd" d="M19.062 5.139l-1.644-1.139-8.551 12.357-3.454-3.454-1.413 1.413 5.021 5.022z"/>
+    <g id="accept" opacity=".75">
+        <path id="check" d="M19.062 5.139l-1.644-1.139-8.551 12.357-3.454-3.454-1.413 1.413 5.021 5.022z"/>
     </g>
 </svg>
index 5cf353f..a7788c7 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/add-item.png and b/resources/lib/oojs-ui/images/icons/add-item.png differ
index b25d5b7..c42731a 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="apply" opacity=".75">
-        <path d="M13 8h-2v3h-3v2h3v3h2v-3h3v-2h-3z"/>
+    <g id="add-item" opacity=".75">
+        <path id="plus" d="M13 8h-2v3h-3v2h3v3h2v-3h3v-2h-3z"/>
     </g>
 </svg>
index 7f5ada5..7609ec9 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/advanced.png and b/resources/lib/oojs-ui/images/icons/advanced.png differ
index 223b7fc..0f85e44 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="settings" opacity=".75">
-        <path id="gear" d="M20.869 13.476c.079-.482.131-.972.131-1.476s-.052-.994-.131-1.476l-2.463-.259c-.149-.556-.367-1.082-.648-1.57l1.558-1.924c-.576-.806-1.281-1.511-2.087-2.087l-1.924 1.558c-.488-.281-1.015-.499-1.57-.648l-.259-2.463c-.482-.079-.972-.131-1.476-.131s-.994.052-1.476.131l-.259 2.463c-.555.149-1.081.367-1.57.648l-1.924-1.557c-.805.576-1.51 1.281-2.086 2.086l1.558 1.924c-.281.488-.499 1.015-.648 1.57l-2.463.259c-.08.482-.132.972-.132 1.476s.052.994.131 1.476l2.463.259c.149.556.367 1.082.648 1.57l-1.558 1.924c.576.806 1.281 1.511 2.087 2.087l1.924-1.558c.488.281 1.015.499 1.57.648l.259 2.463c.482.079.972.131 1.476.131s.994-.052 1.476-.131l.259-2.463c.556-.149 1.082-.367 1.57-.648l1.924 1.558c.806-.576 1.511-1.281 2.087-2.087l-1.558-1.924c.281-.488.499-1.015.648-1.57l2.463-.259zm-8.869 2.522c-2.209 0-3.998-1.789-3.998-3.998s1.789-3.998 3.998-3.998 3.998 1.789 3.998 3.998-1.789 3.998-3.998 3.998z" fill-rule="evenodd" clip-rule="evenodd"/>
+        <path id="gear" d="M20.869 13.476c.079-.482.131-.972.131-1.476s-.052-.994-.131-1.476l-2.463-.259c-.149-.556-.367-1.082-.648-1.57l1.558-1.924c-.576-.806-1.281-1.511-2.087-2.087l-1.924 1.558c-.488-.281-1.015-.499-1.57-.648l-.259-2.463c-.482-.079-.972-.131-1.476-.131s-.994.052-1.476.131l-.259 2.463c-.555.149-1.081.367-1.57.648l-1.924-1.557c-.805.576-1.51 1.281-2.086 2.086l1.558 1.924c-.281.488-.499 1.015-.648 1.57l-2.463.259c-.08.482-.132.972-.132 1.476s.052.994.131 1.476l2.463.259c.149.556.367 1.082.648 1.57l-1.558 1.924c.576.806 1.281 1.511 2.087 2.087l1.924-1.558c.488.281 1.015.499 1.57.648l.259 2.463c.482.079.972.131 1.476.131s.994-.052 1.476-.131l.259-2.463c.556-.149 1.082-.367 1.57-.648l1.924 1.558c.806-.576 1.511-1.281 2.087-2.087l-1.558-1.924c.281-.488.499-1.015.648-1.57l2.463-.259zm-8.869 2.522c-2.209 0-3.998-1.789-3.998-3.998s1.789-3.998 3.998-3.998 3.998 1.789 3.998 3.998-1.789 3.998-3.998 3.998z"/>
     </g>
 </svg>
index 992ea2a..a45ad31 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/alert.png and b/resources/lib/oojs-ui/images/icons/alert.png differ
index fb25766..819e062 100644 (file)
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="alert" opacity=".75">
-        <path id="point" fill-rule="evenodd" clip-rule="evenodd" d="M11 16h2v2h-2z"/>
-        <path id="stroke" fill-rule="evenodd" clip-rule="evenodd" d="M13.516 10h-3l.484 5h2z"/>
+        <path id="point" d="M11 16h2v2h-2z"/>
+        <path id="stroke" d="M13.516 10h-3l.484 5h2z"/>
         <path id="triangle" d="M12.017 5.974l7.519 13.026h-15.04l7.521-13.026m0-2.474c-.544 0-1.088.357-1.5 1.071l-7.985 13.831c-.825 1.429-.15 2.598 1.5 2.598h15.968c1.65 0 2.325-1.169 1.5-2.599l-7.983-13.829c-.413-.715-.956-1.072-1.5-1.072z"/>
     </g>
 </svg>
index 5db1c4d..c48f55d 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/arched-arrow-ltr.png and b/resources/lib/oojs-ui/images/icons/arched-arrow-ltr.png differ
index 88a6a40..9fd2866 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="arched-arrow-ltr" opacity=".75">
-        <path id="arrow" d="M19.925 14.937l-2.391-6.901-1.48 2.329c-.964-.845-2.699-1.85-5.513-1.823-4.887.046-6.524 4.244-6.524 4.244s2.753-2.639 6.925-1.949c1.729.286 3.007 1.206 3.675 1.791l-1.474 2.319 6.782-.01z" fill-rule="evenodd" clip-rule="evenodd"/>
+        <path id="arrow" d="M19.925 14.937l-2.391-6.901-1.48 2.329c-.964-.845-2.699-1.85-5.513-1.823-4.887.046-6.524 4.244-6.524 4.244s2.753-2.639 6.925-1.949c1.729.286 3.007 1.206 3.675 1.791l-1.474 2.319 6.782-.01z"/>
     </g>
 </svg>
index 7931971..51c8de4 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/arched-arrow-rtl.png and b/resources/lib/oojs-ui/images/icons/arched-arrow-rtl.png differ
index 50541d2..b16c1b4 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="arched-arrow-rtl" opacity=".75">
-        <path id="arrow" d="M13.401 8.542c-2.814-.027-4.549.978-5.513 1.823l-1.48-2.329-2.391 6.901 6.782.009-1.474-2.319c.668-.584 1.945-1.504 3.675-1.791 4.172-.69 6.925 1.949 6.925 1.949s-1.637-4.197-6.524-4.243z" fill-rule="evenodd" clip-rule="evenodd"/>
+        <path id="arrow" d="M13.401 8.542c-2.814-.027-4.549.978-5.513 1.823l-1.48-2.329-2.391 6.901 6.782.009-1.474-2.319c.668-.584 1.945-1.504 3.675-1.791 4.172-.69 6.925 1.949 6.925 1.949s-1.637-4.197-6.524-4.243z"/>
     </g>
 </svg>
index 82c3cb4..9a2c9db 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/check.png and b/resources/lib/oojs-ui/images/icons/check.png differ
index 697dd62..02d6bb3 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/clear.png and b/resources/lib/oojs-ui/images/icons/clear.png differ
index 484a104..8409c67 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="clear" opacity=".75">
-        <path id="circle_with_strike" d="M11.999 5.022c-3.853 0-6.977 3.124-6.977 6.978 0 3.853 3.124 6.978 6.977 6.978 3.854 0 6.979-3.125 6.979-6.978 0-3.854-3.125-6.978-6.979-6.978zm-5.113 6.978c0-1.092.572-3.25.93-2.929l7.113 7.113c.488.525-1.837.931-2.93.931-2.825-.001-5.113-2.291-5.113-5.115zm9.298 2.929l-7.114-7.113c-.445-.483 1.837-.931 2.929-.931 2.827 0 5.115 2.289 5.115 5.114 0 1.093-.364 3.543-.93 2.93z" fill-rule="evenodd" clip-rule="evenodd"/>
+        <path id="circle-with-strike" d="M11.999 5.022c-3.853 0-6.977 3.124-6.977 6.978 0 3.853 3.124 6.978 6.977 6.978 3.854 0 6.979-3.125 6.979-6.978 0-3.854-3.125-6.978-6.979-6.978zm-5.113 6.978c0-1.092.572-3.25.93-2.929l7.113 7.113c.488.525-1.837.931-2.93.931-2.825-.001-5.113-2.291-5.113-5.115zm9.298 2.929l-7.114-7.113c-.445-.483 1.837-.931 2.929-.931 2.827 0 5.115 2.289 5.115 5.114 0 1.093-.364 3.543-.93 2.93z"/>
     </g>
 </svg>
index f7eed9f..06d4921 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/close.png and b/resources/lib/oojs-ui/images/icons/close.png differ
index 15278e9..3c0ab46 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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" opacity=".75">
-        <path id="x" fill-rule="evenodd" clip-rule="evenodd" d="M18.717 6.697l-1.414-1.414-5.303 5.303-5.303-5.303-1.414 1.414 5.303 5.303-5.303 5.303 1.414 1.414 5.303-5.303 5.303 5.303 1.414-1.414-5.303-5.303z"/>
+        <path id="x" d="M18.717 6.697l-1.414-1.414-5.303 5.303-5.303-5.303-1.414 1.414 5.303 5.303-5.303 5.303 1.414 1.414 5.303-5.303 5.303 5.303 1.414-1.414-5.303-5.303z"/>
     </g>
 </svg>
index a5ebdbf..783e1e0 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/code.png and b/resources/lib/oojs-ui/images/icons/code.png differ
index 38b796f..2c4ecee 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/collapse.png and b/resources/lib/oojs-ui/images/icons/collapse.png differ
index 97bdc50..c677e9e 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="collapse" opacity=".75">
-        <path id="arrow" fill-rule="evenodd" clip-rule="evenodd" d="M6.697 15.714l5.303-5.302 5.303 5.302 1.414-1.414-6.717-6.717-6.717 6.717z"/>
+        <path id="arrow" d="M6.697 15.714l5.303-5.302 5.303 5.302 1.414-1.414-6.717-6.717-6.717 6.717z"/>
     </g>
 </svg>
index 9546455..5be2b72 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/comment.png and b/resources/lib/oojs-ui/images/icons/comment.png differ
index ebb038e..0348035 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="comment" opacity=".75">
-        <path id="speech_bubble" d="M15 6h-6c-1.657 0-3 1.344-3 3v4c0 1.656 1.343 3 3 3v3l3-3h3c1.657 0 3-1.344 3-3v-4c0-1.656-1.343-3-3-3z" fill-rule="evenodd" clip-rule="evenodd"/>
+        <path id="speech-bubble" d="M15 6h-6c-1.657 0-3 1.344-3 3v4c0 1.656 1.343 3 3 3v3l3-3h3c1.657 0 3-1.344 3-3v-4c0-1.656-1.343-3-3-3z"/>
     </g>
 </svg>
index e90aca1..3ae27c0 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/expand.png and b/resources/lib/oojs-ui/images/icons/expand.png differ
index 81c2ec0..f41b9f9 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="expand" opacity=".75">
-        <path id="arrow" fill-rule="evenodd" clip-rule="evenodd" d="M17.303 8.283l-5.303 5.303-5.303-5.303-1.414 1.414 6.717 6.717 6.717-6.717z"/>
+        <path id="arrow" d="M17.303 8.283l-5.303 5.303-5.303-5.303-1.414 1.414 6.717 6.717 6.717-6.717z"/>
     </g>
 </svg>
index dca745b..c1190fc 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/help.png and b/resources/lib/oojs-ui/images/icons/help.png differ
index 09117e1..ce129a7 100644 (file)
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="help" opacity=".75" fill-rule="evenodd" clip-rule="evenodd">
+    <g id="help" opacity=".75">
         <path id="circle" d="M12.001 2.085c-5.478 0-9.916 4.438-9.916 9.916 0 5.476 4.438 9.914 9.916 9.914 5.476 0 9.914-4.438 9.914-9.914 0-5.478-4.438-9.916-9.914-9.916zm.001 18c-4.465 0-8.084-3.619-8.084-8.083 0-4.465 3.619-8.084 8.084-8.084 4.464 0 8.083 3.619 8.083 8.084 0 4.464-3.619 8.083-8.083 8.083z"/>
-        <g id="question_mark">
+        <g id="question-mark">
             <path id="top" d="M11.766 6.688c-2.5 0-3.219 2.188-3.219 2.188l1.411.854s.298-.791.901-1.229c.516-.375 1.625-.625 2.219.125.701.885-.17 1.587-1.078 2.719-.953 1.186-1 3.655-1 3.655h1.969s.135-2.318 1.041-3.381c.603-.707 1.443-1.338 1.443-2.494s-1.187-2.437-3.687-2.437z"/>
             <path id="bottom" d="M11 16h2v2h-2z"/>
         </g>
index c049931..8a9862f 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/history.png and b/resources/lib/oojs-ui/images/icons/history.png differ
index a89e257..91e072f 100644 (file)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="history" opacity=".75" fill-rule="evenodd" clip-rule="evenodd">
-        <path id="clock_hands" d="M17.26 15.076s-2.385-1.935-4.005-3.062c.72-2.397 1.702-6.559 1.702-6.559s-4.35 5.363-4.877 6.699c-.463 1.168 1.459 2.209 2.346 1.678 1.9.551 4.834 1.244 4.834 1.244z"/>
+    <g id="history" opacity=".75">
+        <path id="clock-hands" d="M17.26 15.076s-2.385-1.935-4.005-3.062c.72-2.397 1.702-6.559 1.702-6.559s-4.35 5.363-4.877 6.699c-.463 1.168 1.459 2.209 2.346 1.678 1.9.551 4.834 1.244 4.834 1.244z"/>
         <path id="arrow" d="M12.086 2.085c-5.478 0-9.916 4.438-9.916 9.916 0 1.783.476 3.454 1.301 4.898l-2.223 2.04h5.688v-5.219l-2.066 1.896c-.55-1.088-.866-2.312-.866-3.615 0-4.465 3.619-8.084 8.084-8.084 4.464 0 8.083 3.619 8.083 8.084 0 4.464-3.619 8.083-8.083 8.083-1.145 0-2.228-.247-3.213-.678l-.833 1.634c1.235.557 2.602.874 4.045.874 5.476 0 9.914-4.438 9.914-9.914-.001-5.477-4.439-9.915-9.915-9.915z"/>
     </g>
 </svg>
index f43804d..a74fb18 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/info.png and b/resources/lib/oojs-ui/images/icons/info.png differ
index 22ad9be..9ba57d7 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="help" opacity=".75">
-        <path d="M11.499 17c-3.036 0-5.499-2.464-5.499-5.5 0-3.037 2.462-5.5 5.499-5.5 3.037 0 5.501 2.462 5.501 5.5 0 3.036-2.464 5.5-5.501 5.5zm.002-12c-3.591 0-6.501 2.91-6.501 6.5s2.91 6.5 6.501 6.5c3.588 0 6.499-2.911 6.499-6.5s-2.911-6.5-6.499-6.5zM12 10v4h1v1h-3v-1h1v-3h-1v-1zM11 8h1v1h-1z"/>
+    <g id="info" opacity=".75">
+        <path id="circled-i" d="M11.499 17c-3.036 0-5.499-2.464-5.499-5.5 0-3.037 2.462-5.5 5.499-5.5 3.037 0 5.501 2.462 5.501 5.5 0 3.036-2.464 5.5-5.501 5.5zm.002-12c-3.591 0-6.501 2.91-6.501 6.5s2.91 6.5 6.501 6.5c3.588 0 6.499-2.911 6.499-6.5s-2.911-6.5-6.499-6.5zM12 10v4h1v1h-3v-1h1v-3h-1v-1zM11 8h1v1h-1z"/>
     </g>
 </svg>
index 7dfa268..e51657d 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/link.png and b/resources/lib/oojs-ui/images/icons/link.png differ
index 7d8a1ef..fcb06be 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="link" opacity=".75">
         <path id="right" d="M19.188 12.001c0 1.1-.891 2.015-1.988 2.015l-4.195-.015c.538 1.088.963 1.999 1.997 1.999h3c1.656 0 2.998-2.343 2.998-4s-1.342-4-2.998-4h-3c-1.034 0-1.459.911-1.998 1.999l4.195-.015c1.098 0 1.989.917 1.989 2.017z"/>
index b5ac60f..e53aed6 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/menu.png and b/resources/lib/oojs-ui/images/icons/menu.png differ
index 75866f6..2d04789 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="menu" opacity=".75">
         <path id="lines" d="M6 15h12c.553 0 1 .447 1 1v1c0 .553-.447 1-1 1h-12c-.553 0-1-.447-1-1v-1c0-.553.447-1 1-1zm-1-4v1c0 .553.447 1 1 1h12c.553 0 1-.447 1-1v-1c0-.553-.447-1-1-1h-12c-.553 0-1 .447-1 1zm0-5v1c0 .553.447 1 1 1h12c.553 0 1-.447 1-1v-1c0-.553-.447-1-1-1h-12c-.553 0-1 .447-1 1z"/>
index ded5f05..4b9f3bf 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/move-ltr.png and b/resources/lib/oojs-ui/images/icons/move-ltr.png differ
index 3c19c4f..eea75d8 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="move-ltr" opacity=".75">
-        <path id="arrow" fill-rule="evenodd" clip-rule="evenodd" d="M8.935 7.181l5.302 5.302-5.302 5.303 1.414 1.414 6.716-6.717-6.716-6.716z"/>
+        <path id="arrow" d="M8.935 7.181l5.302 5.302-5.302 5.303 1.414 1.414 6.716-6.717-6.716-6.716z"/>
     </g>
 </svg>
index fc6e62d..7cd9cff 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/move-rtl.png and b/resources/lib/oojs-ui/images/icons/move-rtl.png differ
index d9f35c1..2dc5eaf 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="move-rtl" opacity=".75">
-        <path id="arrow_9_" fill-rule="evenodd" clip-rule="evenodd" d="M15.065 17.786l-5.302-5.303 5.302-5.302-1.414-1.414-6.716 6.716 6.716 6.717z"/>
+        <path id="arrow" d="M15.065 17.786l-5.302-5.303 5.302-5.302-1.414-1.414-6.716 6.716 6.716 6.717z"/>
     </g>
 </svg>
index faf8af9..ef9daec 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/picture.png and b/resources/lib/oojs-ui/images/icons/picture.png differ
index cd4c0f7..4862fbc 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="picture" opacity=".75" fill-rule="evenodd" clip-rule="evenodd">
+    <g id="picture" opacity=".75">
         <path id="frame" d="M18 4h-12c-2-.007-3 .993-3 2.993l.014 9.007c-.014 2 .986 2.988 2.986 3h12c2-.012 2.994-1 3-3.006v-9.001c-.006-2-1-3-3-2.993zm1 13h-14v-11h14v11z"/>
         <path id="mountains" d="M6 13.5l3.5-3.5 2.328 2.312-1.312 1.094.875 1.032 4.109-3.438 2.5 2v3h-12z"/>
         <path id="sky" d="M6 12l3.516-4.156 3.046 3.172 2.938-2.016 2.5 2v-4h-12z"/>
index 2f11db3..0d15c3b 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/remove-item.png and b/resources/lib/oojs-ui/images/icons/remove-item.png differ
index 5dd607b..723e70f 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="remove-item">
-        <path d="M8 11h8v2h-8z"/>
+        <path id="minus" d="M8 11h8v2h-8z"/>
     </g>
 </svg>
index d7e116c..8baeee0 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/remove.png and b/resources/lib/oojs-ui/images/icons/remove.png differ
index 06c89d7..61f4d2d 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="remove" opacity=".75">
-        <path id="trash_can" d="M12 10h-1v6h1v-6zm-2 0h-1v6h1v-6zm4 0h-1v6h1v-6zm0-4v-1h-5v1h-3v3h1v7.966l1 1.031v-.074.077h6.984l.016-.018v.015l1-1.031v-7.966h1v-3h-3zm1 11h-7v-8h7v8zm1-9h-9v-1h9v1z" fill-rule="evenodd" clip-rule="evenodd"/>
+        <path id="trash-can" d="M12 10h-1v6h1v-6zm-2 0h-1v6h1v-6zm4 0h-1v6h1v-6zm0-4v-1h-5v1h-3v3h1v7.966l1 1.031v-.074.077h6.984l.016-.018v.015l1-1.031v-7.966h1v-3h-3zm1 11h-7v-8h7v8zm1-9h-9v-1h9v1z"/>
     </g>
 </svg>
index df29792..19bc178 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/search.png and b/resources/lib/oojs-ui/images/icons/search.png differ
index ff7144c..75b38c8 100644 (file)
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="search" opacity=".75">
-        <path id="magnifying_glass" d="M16.021 15.96l-2.374-2.375-.169-.099c.403-.566.643-1.26.643-2.009-.001-1.92-1.558-3.477-3.477-3.477-1.921 0-3.478 1.557-3.478 3.478 0 1.92 1.557 3.477 3.478 3.477.749 0 1.442-.239 2.01-.643l.098.169 2.375 2.374c.19.189.543.143.79-.104s.293-.601.104-.791zm-5.377-2.27c-1.221 0-2.213-.991-2.213-2.213 0-1.221.992-2.213 2.213-2.213 1.222 0 2.213.992 2.213 2.213-.001 1.222-.992 2.213-2.213 2.213z"/>
+        <path id="magnifying-glass" d="M16.021 15.96l-2.374-2.375-.169-.099c.403-.566.643-1.26.643-2.009-.001-1.92-1.558-3.477-3.477-3.477-1.921 0-3.478 1.557-3.478 3.478 0 1.92 1.557 3.477 3.478 3.477.749 0 1.442-.239 2.01-.643l.098.169 2.375 2.374c.19.189.543.143.79-.104s.293-.601.104-.791zm-5.377-2.27c-1.221 0-2.213-.991-2.213-2.213 0-1.221.992-2.213 2.213-2.213 1.222 0 2.213.992 2.213 2.213-.001 1.222-.992 2.213-2.213 2.213z"/>
     </g>
 </svg>
index b1b35e9..0314960 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/settings.png and b/resources/lib/oojs-ui/images/icons/settings.png differ
index cbc4efc..6e45b60 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="settings" opacity=".75">
-        <path d="M3 4h3v2h-3zM12 4h9v2h-9zM8 3h2c.552 0 1 .448 1 1v2c0 .552-.448 1-1 1h-2c-.552 0-1-.448-1-1v-2c0-.552.448-1 1-1zM3 11h9v2h-9zM18 11h3v2h-3zM14 10h2c.552 0 1 .448 1 1v2c0 .552-.448 1-1 1h-2c-.552 0-1-.448-1-1v-2c0-.552.448-1 1-1zM3 18h6v2h-6zM15 18h6v2h-6zM11 17h2c.552 0 1 .448 1 1v2c0 .552-.448 1-1 1h-2c-.552 0-1-.448-1-1v-2c0-.552.448-1 1-1z"/>
+        <path id="gear" d="M3 4h3v2h-3zM12 4h9v2h-9zM8 3h2c.552 0 1 .448 1 1v2c0 .552-.448 1-1 1h-2c-.552 0-1-.448-1-1v-2c0-.552.448-1 1-1zM3 11h9v2h-9zM18 11h3v2h-3zM14 10h2c.552 0 1 .448 1 1v2c0 .552-.448 1-1 1h-2c-.552 0-1-.448-1-1v-2c0-.552.448-1 1-1zM3 18h6v2h-6zM15 18h6v2h-6zM11 17h2c.552 0 1 .448 1 1v2c0 .552-.448 1-1 1h-2c-.552 0-1-.448-1-1v-2c0-.552.448-1 1-1z"/>
     </g>
 </svg>
index 722f4d7..9802856 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/tag.png and b/resources/lib/oojs-ui/images/icons/tag.png differ
index 496e7fc..1d61b81 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="tag" opacity=".75">
         <path d="M18.748 11.717c.389.389.389 1.025 0 1.414l-4.949 4.95c-.389.389-1.025.389-1.414 0l-6.01-6.01c-.389-.389-.707-1.157-.707-1.707l-.001-4.364c0-.55.45-1 1-1h4.364c.55 0 1.318.318 1.707.707l6.01 6.01zm-10.644-4.261c-.579.576-.578 1.514-.001 2.093.578.577 1.516.577 2.095.001.576-.578.576-1.517 0-2.095-.581-.576-1.518-.577-2.094.001z"/>
index 3d48a3c..bee8a3d 100644 (file)
Binary files a/resources/lib/oojs-ui/images/icons/window.png and b/resources/lib/oojs-ui/images/icons/window.png differ
index ad12773..44f7ba7 100644 (file)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?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="window" opacity=".75">
         <path id="title" d="M7 10h10v1h-10z"/>
-        <path id="window" d="M16 19h-8c-2.206 0-4-1.794-4-4v-6c0-2.206 1.794-4 4-4h8c2.206 0 4 1.794 4 4v6c0 2.206-1.794 4-4 4zm-8-12c-1.103 0-2 .897-2 2v6c0 1.103.897 2 2 2h8c1.103 0 2-.897 2-2v-6c0-1.103-.897-2-2-2h-8z"/>
+        <path id="frame" d="M16 19h-8c-2.206 0-4-1.794-4-4v-6c0-2.206 1.794-4 4-4h8c2.206 0 4 1.794 4 4v6c0 2.206-1.794 4-4 4zm-8-12c-1.103 0-2 .897-2 2v6c0 1.103.897 2 2 2h8c1.103 0 2-.897 2-2v-6c0-1.103-.897-2-2-2h-8z"/>
     </g>
 </svg>
index bfc83e7..dc41e49 100644 (file)
Binary files a/resources/lib/oojs-ui/images/indicators/alert.png and b/resources/lib/oojs-ui/images/indicators/alert.png differ
index 7cfde44..e2e49a8 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
-    <g id="deprecated" opacity=".75">
+    <g id="alert" opacity=".75">
         <path d="M6 12c-3.314 0-6-2.686-6-6s2.686-6 6-6 6 2.686 6 6-2.686 6-6 6zm-1-5h2v-5h-2zm0 3h2v-2h-2z"/>
     </g>
 </svg>
index 64e3bac..edbc84f 100644 (file)
Binary files a/resources/lib/oojs-ui/images/indicators/arrow-down.png and b/resources/lib/oojs-ui/images/indicators/arrow-down.png differ
index d345ec0..55670de 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
     <g id="down" opacity=".75">
         <path id="arrow" d="M2 3l3.5 6 3.5-6z"/>
index 4eafd0f..8a85a05 100644 (file)
Binary files a/resources/lib/oojs-ui/images/indicators/arrow-ltr.png and b/resources/lib/oojs-ui/images/indicators/arrow-ltr.png differ
index ce13ba0..07cc888 100644 (file)
Binary files a/resources/lib/oojs-ui/images/indicators/arrow-rtl.png and b/resources/lib/oojs-ui/images/indicators/arrow-rtl.png differ
index 401cde6..f25858d 100644 (file)
Binary files a/resources/lib/oojs-ui/images/indicators/arrow-up.png and b/resources/lib/oojs-ui/images/indicators/arrow-up.png differ
index 78e0115..b9d725e 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
+<?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
     <g id="up" opacity=".75">
         <path id="arrow" d="M5.5 2l-3.5 6h7z"/>
index d10e0d4..bca07c6 100644 (file)
Binary files a/resources/lib/oojs-ui/images/indicators/required.png and b/resources/lib/oojs-ui/images/indicators/required.png differ
diff --git a/resources/lib/oojs-ui/images/tail.svg b/resources/lib/oojs-ui/images/tail.svg
deleted file mode 100644 (file)
index 4df8bb2..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-        width="15px" height="8px" viewBox="0 0 15 8" style="enable-background:new 0 0 15 8;" xml:space="preserve">
-<g id="tail">
-       <polygon id="outline" style="fill-rule:evenodd;clip-rule:evenodd;fill:#808080;" points="7.609,2.499 2.096,8 13.125,8"/>
-       <polygon id="fill" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;" points="7.609,3 2.598,8 12.622,8"/>
-</g>
-</svg>
index b8e36d3..1843f27 100644 (file)
Binary files a/resources/lib/oojs-ui/images/textures/transparency.png and b/resources/lib/oojs-ui/images/textures/transparency.png differ
diff --git a/resources/lib/oojs-ui/images/textures/transparency.svg b/resources/lib/oojs-ui/images/textures/transparency.svg
new file mode 100644 (file)
index 0000000..63a0b57
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="16" height="16" viewBox="0, 0, 16, 16">
+       <g id="transparency">
+               <path d="M0,0 L8,0 L8,8 L0,8 z" fill="#CCCCCC"/>
+               <path d="M8,8 L16,8 L16,16 L8,16 z" fill="#CCCCCC"/>
+               <path d="M8,0 L16,0 L16,8 L8,8 z" fill="#FFFFFF"/>
+               <path d="M0,8 L8,8 L8,16 L0,16 z" fill="#FFFFFF"/>
+       </g>
+</svg>
diff --git a/resources/lib/oojs-ui/oojs-ui-agora.css b/resources/lib/oojs-ui/oojs-ui-agora.css
deleted file mode 100644 (file)
index dc999cd..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*!
- * OOjs UI v0.1.0-pre (85cfc2e735)
- * https://www.mediawiki.org/wiki/OOjs_UI
- *
- * Copyright 2011–2014 OOjs Team and other contributors.
- * Released under the MIT license
- * http://oojs.mit-license.org
- *
- * Date: 2014-07-03T02:33:09Z
- */
-.oo-ui-dialog-content .oo-ui-window-closeButton {
-  position: absolute;
-  top: 0;
-  left: 0;
-}
-
-.oo-ui-dialog-content .oo-ui-window-icon {
-  margin-left: 3.35em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-body {
-  position: absolute;
-  top: 3.35em;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  overflow-y: auto;
-}
-
-.oo-ui-dialog-content .oo-ui-window-foot {
-  position: absolute;
-  top: 0;
-  right: 0;
-  height: 3.35em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-button {
-  height: 100%;
-}
-
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-button .oo-ui-labeledElement-label {
-  display: inline-block;
-  width: 0;
-  text-indent: -9999px;
-}
-
-.oo-ui-dialog-medium .oo-ui-window-frame {
-  top: 0;
-  bottom: 0;
-  background-color: white;
-}
-
-.oo-ui-window-head {
-  height: 3.35em;
-  border-bottom: 1px solid #dddddd;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-window-body {
-  padding: 2em 3.35em;
-}
-
-.oo-ui-window-icon {
-  width: 3.35em;
-  height: 3.35em;
-  background-size: 2em auto;
-  border-left: 1px solid #dddddd;
-}
-
-.oo-ui-window-title {
-  line-height: 3.35em;
-}
-
-.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
-.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  width: 3.35em;
-  height: 3.35em;
-  background-size: 2em auto;
-}
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
-  padding: 0 0 1em;
-}
-
-.oo-ui-optionWidget {
-  padding: 0.8em 1em 0.8em 3.35em;
-  font-weight: bold;
-  border-bottom: 1px solid #dddddd;
-}
-
-.oo-ui-optionWidget.oo-ui-indicatedElement .oo-ui-labeledElement-label {
-  padding-right: 1.5em;
-}
-
-.oo-ui-optionWidget-level-0 {
-  padding-left: 3.5em;
-}
-
-.oo-ui-optionWidget-level-0 .oo-ui-iconedElement-icon {
-  left: 1em;
-}
-
-.oo-ui-optionWidget-level-1 {
-  padding-left: 5em;
-}
-
-.oo-ui-optionWidget-level-1 .oo-ui-iconedElement-icon {
-  left: 2.5em;
-}
-
-.oo-ui-optionWidget-level-2 {
-  padding-left: 6.5em;
-}
-
-.oo-ui-optionWidget-level-2 .oo-ui-iconedElement-icon {
-  left: 4em;
-}
-
-.oo-ui-buttonOptionWidget {
-  padding: 0;
-}
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
-  color: #ffffff;
-  background: #347bff;
-}
-
-.oo-ui-menuSectionItemWidget {
-  font-weight: normal;
-  color: #777777;
-  border: none;
-}
-
-.oo-ui-textInputWidget input,
-.oo-ui-textInputWidget textarea {
-  padding: .8em 1em;
-}
-
-/* Icons */
-
-.oo-ui-icon-check {
-  background: #347bff;
-  background-image: /* @embed */ url(themes/agora/images/icons/check.svg);
-}
\ No newline at end of file
index 7018b52..53e46d6 100644 (file)
 /*!
- * OOjs UI v0.1.0-pre (85cfc2e735)
+ * OOjs UI v0.1.0-pre (49b64bdba7)
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2014 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2014-07-03T02:33:09Z
+ * Date: 2014-09-15T22:18:37Z
  */
-.oo-ui-dialog {
-  background-color: #fff;
-  background-color: rgba(255, 255, 255, 0.5);
-  /* Opening and closing animation */
-
-  opacity: 0;
-}
-
-.oo-ui-dialog > .oo-ui-window-frame {
-  -webkit-transform: scale(0.5);
-     -moz-transform: scale(0.5);
-      -ms-transform: scale(0.5);
-       -o-transform: scale(0.5);
-          transform: scale(0.5);
-}
-
-.oo-ui-dialog.oo-ui-window-setup,
-.oo-ui-dialog.oo-ui-window-setup > .oo-ui-window-frame {
-  -webkit-transition: all 250ms ease-in-out;
-     -moz-transition: all 250ms ease-in-out;
-      -ms-transition: all 250ms ease-in-out;
-       -o-transition: all 250ms ease-in-out;
-          transition: all 250ms ease-in-out;
-}
-
-.oo-ui-dialog.oo-ui-window-ready {
-  opacity: 1;
-}
-
-.oo-ui-dialog.oo-ui-window-ready > .oo-ui-window-frame {
-  -webkit-transform: scale(1);
-     -moz-transform: scale(1);
-      -ms-transform: scale(1);
-       -o-transform: scale(1);
-          transform: scale(1);
-}
-
-.oo-ui-dialog-content .oo-ui-window-head,
-.oo-ui-dialog-content .oo-ui-window-body,
-.oo-ui-dialog-content .oo-ui-window-foot {
-  position: absolute;
-  right: 0;
-  left: 0;
-  overflow: hidden;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-dialog-content .oo-ui-window-head {
-  top: 0;
-  height: 3.8em;
-  padding: 0.5em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-title {
-  line-height: 2.8em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-icon {
-  width: 2.4em;
-  height: 2.8em;
-  line-height: 2.8em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-closeButton {
-  float: right;
-  margin: 0.25em 0.25em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-body {
-  top: 3.8em;
-  bottom: 4.8em;
-}
-
-.oo-ui-dialog-content-footless .oo-ui-window-body {
-  bottom: 0;
-}
-
-.oo-ui-dialog > .oo-ui-window-frame {
-  top: 1em;
-  bottom: 1em;
-  background-color: #fff;
-  border: solid 1px #ccc;
-  border-radius: 0.5em;
-  box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
-}
-
-.oo-ui-dialog-small > .oo-ui-window-frame {
-  width: 400px;
-  max-height: 230px;
-}
-
-.oo-ui-dialog-medium > .oo-ui-window-frame {
-  width: 600px;
-  max-height: 460px;
-}
-
-.oo-ui-dialog-large > .oo-ui-window-frame {
-  width: 800px;
-  max-height: 690px;
-}
-
-.oo-ui-dialog-content .oo-ui-window-head,
-.oo-ui-dialog-content .oo-ui-window-foot {
-  z-index: 1;
-}
-
-.oo-ui-dialog-content .oo-ui-window-body {
-  z-index: 2;
-  box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
-}
-
-.oo-ui-dialog-content .oo-ui-window-foot {
-  bottom: 0;
-  height: 4.8em;
-  padding: 1em;
+/*
+ * Blank theme mixins.
+ *
+ * Base styles invoke these mixins at the end of their definitions. Override these mixins to add
+ * additional rules to the base styles.
+ */
+/*
+ * Base styles.
+ *
+ * Themes should include this file after defining their variables and mixins.
+ */
+/* @noflip */
+.oo-ui-rtl {
+  direction: rtl;
 }
-
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed {
-  margin: 0.125em 0.25em;
+/* @noflip */
+.oo-ui-ltr {
+  direction: ltr;
 }
-
-.oo-ui-dialog-content .oo-ui-window-overlay {
-  z-index: 3;
+.oo-ui-buttonElement > .oo-ui-buttonElement-button {
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: middle;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
 }
-
-.oo-ui-frame-content {
-  font-family: sans-serif;
-  font-size: 0.8em;
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  display: none;
 }
-
-.oo-ui-toolbar-bar {
-  background: #f8fbfd;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #f1f7fb));
-  background-image: -webkit-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
-  background-image: -moz-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
-  background-image: -ms-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
-  background-image: -o-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
-  background-image: linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
-  border-bottom: solid 1px #ccc;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#f1f7fb');
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+  display: none;
 }
-
-.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
-  background: none;
-  border: none;
+.oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+  cursor: default;
 }
-
-.oo-ui-toolbar-shadow {
-  bottom: -9px;
-  height: 9px;
-  background-image: /* @embed */ url(images/toolbar-shadow.png);
-  opacity: 0.125;
-  -webkit-transition: opacity 500ms ease-in-out;
-     -moz-transition: opacity 500ms ease-in-out;
-      -ms-transition: opacity 500ms ease-in-out;
-       -o-transition: opacity 500ms ease-in-out;
-          transition: opacity 500ms ease-in-out;
+.oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
 }
-
-.oo-ui-toolGroup {
-  border: solid 1px transparent;
-  border-radius: 0.25em;
-  -webkit-transition: border-color 300ms ease-in-out;
-     -moz-transition: border-color 300ms ease-in-out;
-      -ms-transition: border-color 300ms ease-in-out;
-       -o-transition: border-color 300ms ease-in-out;
-          transition: border-color 300ms ease-in-out;
+.oo-ui-buttonElement-frameless {
+  display: inline-block;
+  position: relative;
 }
-
-.oo-ui-toolGroup.oo-ui-widget-enabled:hover {
-  border-color: rgba(0, 0, 0, 0.1);
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  display: inline-block;
+  vertical-align: middle;
 }
-
-.oo-ui-toolGroup.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-tool-title {
-  color: #000;
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
+  display: inline-block;
+  vertical-align: top;
+  text-align: center;
 }
-
-.oo-ui-window-body {
-  padding: 0 0.75em;
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  display: inline-block;
+  vertical-align: middle;
 }
-
-.oo-ui-window-icon {
-  width: 2em;
-  height: 2em;
-  margin-right: 0.5em;
-  line-height: 2em;
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+  cursor: default;
 }
-
-.oo-ui-window-title {
-  line-height: 2em;
+.oo-ui-buttonElement > .oo-ui-buttonElement-button {
   color: #333;
 }
-
-.oo-ui-window-overlay {
-  font-family: sans-serif;
-  font-size: 1em;
-  line-height: 1.5em;
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  margin-left: 0;
 }
-
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button {
-  color: #333;
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+  margin-right: -0.75em;
 }
-
-.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
-.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+.oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  opacity: 0.8;
   width: 1.9em;
   height: 1.9em;
-  opacity: 0.8;
 }
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
   /* Don't animate opacities for now, causes wiggling in Chrome (bug 63020) */
-
   /*.oo-ui-transition(opacity 200ms);*/
-
 }
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-iconedElement-icon,
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-iconedElement-icon {
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:hover > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:focus > .oo-ui-iconElement-icon {
   opacity: 1;
 }
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-labeledElement-label,
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-labeledElement-label {
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label,
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:focus > .oo-ui-labelElement-label {
   color: #000;
 }
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
   color: #333;
+  margin-left: 0.25em;
 }
-
-.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  color: #087ecc;
+}
+.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  color: #76ab36;
+}
+.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  color: #d45353;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
   opacity: 0.2;
 }
-
-.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
   color: #ccc;
 }
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-  padding: 0.2em 0.8em;
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
   margin: 0.1em 0;
+  padding: 0.2em 0.8em;
+  border-radius: 0.3em;
   text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
+  border: 1px #c9c9c9 solid;
+  -webkit-transition: border-color 100ms ease-in-out;
+  -moz-transition: border-color 100ms ease-in-out;
+  -ms-transition: border-color 100ms ease-in-out;
+  -o-transition: border-color 100ms ease-in-out;
+  transition: border-color 100ms ease-in-out;
   background: #eeeeee;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#dddddd');
   background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #dddddd));
   background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
   background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
   background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
   background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
   background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  border: 1px #c9c9c9 solid;
-  border-radius: 0.3em;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#dddddd');
-  -webkit-transition: border-color 100ms ease-in-out;
-     -moz-transition: border-color 100ms ease-in-out;
-      -ms-transition: border-color 100ms ease-in-out;
-       -o-transition: border-color 100ms ease-in-out;
-          transition: border-color 100ms ease-in-out;
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:focus {
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button:focus {
   border-color: #aaa;
 }
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  line-height: 1.9em;
+}
+.oo-ui-buttonElement-framed.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+  box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
   color: black;
+  border-color: #c9c9c9;
   background: #eeeeee;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#dddddd', endColorstr='#ffffff');
   background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #dddddd), color-stop(100%, #ffffff));
   background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
   background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
   background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
   background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
   background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  border-color: #c9c9c9;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#dddddd', endColorstr='#ffffff');
-  box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
 }
-
-.oo-ui-buttonedElement-framed.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  margin-right: -0.5em;
+.oo-ui-buttonElement-framed.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
   margin-left: -0.5em;
+  margin-right: -0.5em;
 }
-
-.oo-ui-buttonedElement-framed.oo-ui-iconedElement.oo-ui-labeledElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  margin-right: 0.3em;
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
   margin-left: -0.5em;
+  margin-right: 0.3em;
 }
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button {
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button {
+  border: solid 1px #a6cee1;
   background: #cde7f4;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#eaf4fa', endColorstr='#b0d9ee');
   background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #eaf4fa), color-stop(100%, #b0d9ee));
   background-image: -webkit-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
   background-image: -moz-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
   background-image: -ms-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
   background-image: -o-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
   background-image: linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-  border: solid 1px #a6cee1;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#eaf4fa', endColorstr='#b0d9ee');
 }
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button:focus {
   border-color: #9dc2d4;
 }
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-primary.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-primary.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+  border: solid 1px #a6cee1;
   background: #cde7f4;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#b0d9ee', endColorstr='#eaf4fa');
   background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #b0d9ee), color-stop(100%, #eaf4fa));
   background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
   background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
   background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
   background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
   background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  border: solid 1px #a6cee1;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#b0d9ee', endColorstr='#eaf4fa');
 }
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button {
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button {
+  border: solid 1px #b8d892;
   background: #daf0be;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f0fbe1', endColorstr='#c3e59a');
   background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f0fbe1), color-stop(100%, #c3e59a));
   background-image: -webkit-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
   background-image: -moz-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
   background-image: -ms-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
   background-image: -o-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
   background-image: linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-  border: solid 1px #b8d892;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f0fbe1', endColorstr='#c3e59a');
 }
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
   border-color: #adcb89;
 }
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+  border: solid 1px #b8d892;
   background: #daf0be;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#c3e59a', endColorstr='#f0fbe1');
   background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #c3e59a), color-stop(100%, #f0fbe1));
   background-image: -webkit-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
   background-image: -moz-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
   background-image: -ms-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
   background-image: -o-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
   background-image: linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-  border: solid 1px #b8d892;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#c3e59a', endColorstr='#f0fbe1');
 }
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-destructive .oo-ui-buttonedElement-button {
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
   color: #d45353;
 }
-
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+  opacity: 0.5;
+  box-shadow: none;
   color: #333;
   background: #eee;
   border-color: #ccc;
-  opacity: 0.5;
-  box-shadow: none;
 }
-
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active:hover,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed:hover,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:focus,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active:focus,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button:focus {
   border-color: #ccc;
   box-shadow: none;
 }
-
+.oo-ui-clippableElement-clippable {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-bookletLayout-stackLayout.oo-ui-stackLayout-continuous .oo-ui-panelLayout-scrollable {
+  overflow-y: hidden;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
+  width: 100%;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-scrollable {
+  overflow-y: auto;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-padded {
+  padding: 2em;
+}
+.oo-ui-bookletLayout-outlinePanel-editable .oo-ui-outlineWidget {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 3em;
+  overflow-y: auto;
+}
+.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+}
 .oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
   padding: 1.5em;
 }
-
 .oo-ui-bookletLayout-outlinePanel {
   border-right: solid 1px #ddd;
 }
-
 .oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
   box-shadow: 0 0 0.25em rgba(0, 0, 0, 0.25);
 }
-
-.oo-ui-fieldLayout-disabled .oo-ui-labeledElement-label {
+.oo-ui-fieldLayout {
+  margin-bottom: 1em;
+}
+.oo-ui-fieldLayout:before,
+.oo-ui-fieldLayout:after {
+  content: " ";
+  display: table;
+}
+.oo-ui-fieldLayout:after {
+  clear: both;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labelElement-label {
+  display: block;
+  float: left;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field {
+  display: block;
+  float: left;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labelElement-label {
+  text-align: right;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labelElement-label {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labelElement-label {
+  display: inline-block;
+}
+.oo-ui-fieldLayout > .oo-ui-popupButtonWidget > .oo-ui-popupWidget > .oo-ui-popupWidget-popup {
+  z-index: 1;
+}
+.oo-ui-fieldLayout .oo-ui-fieldLayout-help {
+  float: right;
+}
+.oo-ui-fieldLayout .oo-ui-fieldLayout-help-content {
+  padding: 0.5em 0.75em;
+}
+.oo-ui-fieldLayout:last-child {
+  margin-bottom: 0;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labelElement-label {
+  padding-top: 0.5em;
+  margin-right: 5%;
+  width: 35%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field {
+  width: 60%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labelElement-label {
+  padding: 0.75em 0.5em 0.5em 0.5em;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field {
+  padding: 0.5em 0;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labelElement-label {
+  padding: 0.5em 0;
+}
+.oo-ui-fieldLayout > .oo-ui-popupButtonWidget > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  margin-top: 0.25em;
+}
+.oo-ui-fieldLayout-disabled .oo-ui-labelElement-label {
   color: #ccc;
 }
-
 .oo-ui-fieldsetLayout {
+  position: relative;
+  margin: 0;
+  padding: 0;
   border: none;
 }
-
-.oo-ui-fieldsetLayout > .oo-ui-labeledElement-label {
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-iconElement-icon {
+  display: block;
+  position: absolute;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-fieldsetLayout.oo-ui-labelElement > .oo-ui-labelElement-label {
+  display: inline-block;
+}
+.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout {
+  margin-top: 2em;
+}
+.oo-ui-fieldsetLayout > .oo-ui-labelElement-label {
   font-size: 1.5em;
+  margin-bottom: 0.5em;
+  padding: 0.25em 0;
 }
-
-.oo-ui-panelLayout {
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-labelElement-label {
+  padding-left: 1.75em;
+  line-height: 1.33em;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-iconElement-icon {
+  left: 0;
+  top: 0.25em;
+  width: 2em;
+  height: 2em;
+}
+.oo-ui-gridLayout {
   position: absolute;
   top: 0;
+  left: 0;
   right: 0;
   bottom: 0;
+}
+.oo-ui-panelLayout {
+  position: relative;
+}
+.oo-ui-panelLayout-scrollable {
+  overflow-y: auto;
+}
+.oo-ui-panelLayout-expanded {
+  position: absolute;
+  top: 0;
   left: 0;
+  right: 0;
+  bottom: 0;
 }
-
 .oo-ui-panelLayout-padded {
-  padding: 2em;
+  padding: 1.25em;
+}
+.oo-ui-stackLayout > .oo-ui-panelLayout {
+  display: none;
+}
+.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
+  display: block;
+  position: relative;
+}
+.oo-ui-popupTool .oo-ui-popupWidget-popup,
+.oo-ui-popupTool .oo-ui-popupWidget-anchor {
+  z-index: 4;
+}
+.oo-ui-popupTool .oo-ui-popupWidget {
+  margin-left: 1.25em;
+  font-size: 0.8em;
+}
+.oo-ui-toolGroup {
+  display: inline-block;
+  vertical-align: middle;
+  margin: 0.3em;
+  border-radius: 0.25em;
+  border: solid 1px transparent;
+  -webkit-transition: border-color 300ms ease-in-out;
+  -moz-transition: border-color 300ms ease-in-out;
+  -ms-transition: border-color 300ms ease-in-out;
+  -o-transition: border-color 300ms ease-in-out;
+  transition: border-color 300ms ease-in-out;
+}
+.oo-ui-toolGroup-empty {
+  display: none;
+}
+.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-toolGroup.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-toolGroup.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-tool-title {
+  color: #000;
+}
+.oo-ui-barToolGroup > .oo-ui-iconElement-icon,
+.oo-ui-barToolGroup > .oo-ui-labelElement-label {
+  display: none;
+}
+.oo-ui-barToolGroup .oo-ui-tool {
+  display: inline-block;
+  position: relative;
+  vertical-align: top;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link {
+  display: block;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  display: block;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  display: none;
+}
+.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+.oo-ui-barToolGroup .oo-ui-tool-title,
+.oo-ui-barToolGroup .oo-ui-tool-accel {
+  display: none;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-link {
+  cursor: pointer;
 }
-
 .oo-ui-barToolGroup .oo-ui-tool {
   margin: -1px 0 -1px -1px;
   border: solid 1px transparent;
 }
-
 .oo-ui-barToolGroup .oo-ui-tool:first-child {
-  border-bottom-left-radius: 0.25em;
   border-top-left-radius: 0.25em;
+  border-bottom-left-radius: 0.25em;
 }
-
 .oo-ui-barToolGroup .oo-ui-tool:last-child {
   margin-right: -1px;
   border-top-right-radius: 0.25em;
   border-bottom-right-radius: 0.25em;
 }
-
-.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+.oo-ui-barToolGroup .oo-ui-tool-link {
+  height: 1.5em;
+  padding: 0.25em;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  height: 1.5em;
+  width: 1.5em;
   opacity: 0.8;
 }
-
 .oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled:hover {
   border-color: rgba(0, 0, 0, 0.2);
 }
-
 .oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-active.oo-ui-widget-enabled {
+  border-color: rgba(0, 0, 0, 0.2);
+  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
   background: #f8fbfd;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
   background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
   background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
   background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
   background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
   background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
   background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  border-color: rgba(0, 0, 0, 0.2);
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
-  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
 }
-
 .oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
   border-left-color: rgba(0, 0, 0, 0.1);
 }
-
-.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconElement-icon {
   opacity: 0.2;
 }
-
-.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-iconElement-icon {
   opacity: 0.8;
 }
-
-.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconedElement-icon {
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconElement-icon {
   opacity: 1;
 }
-
-.oo-ui-barToolGroup.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+.oo-ui-barToolGroup.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconElement-icon {
   opacity: 0.2;
 }
-
-.oo-ui-listToolGroup.oo-ui-popupToolGroup-active {
-  border-color: rgba(0, 0, 0, 0.2);
+.oo-ui-popupToolGroup {
+  position: relative;
+  height: 2em;
+  min-width: 2.5em;
 }
-
-.oo-ui-listToolGroup .oo-ui-tool {
-  margin: -1px 0;
-  border: solid 1px transparent;
+.oo-ui-popupToolGroup-handle {
+  display: block;
+  cursor: pointer;
 }
-
-.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled {
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+  position: absolute;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-disabled .oo-ui-popupToolGroup-handle {
+  cursor: default;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+  display: none;
+  position: absolute;
+  z-index: 4;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools .oo-ui-iconElement-icon {
+  background-repeat: no-repeat;
+  background-position: center center;
+}
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled > .oo-ui-toolGroup-tools {
+  display: block;
+}
+.oo-ui-popupToolGroup-left > .oo-ui-toolGroup-tools {
+  left: 0;
+}
+.oo-ui-popupToolGroup-right > .oo-ui-toolGroup-tools {
+  right: 0;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-accel {
+  display: none;
+}
+.oo-ui-popupToolGroup.oo-ui-indicatorElement.oo-ui-iconElement {
+  min-width: 3.5em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+  top: 0;
+  width: 2em;
+  height: 2em;
+  opacity: 0.8;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator {
+  right: 0;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+  left: 0.25em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+  line-height: 2.6em;
+  font-size: 0.8em;
+  margin: 0 1em;
+}
+.oo-ui-popupToolGroup-header {
+  line-height: 2.6em;
+  font-size: 0.8em;
+  margin: 0 0.6em;
+  font-weight: bold;
+}
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled {
+  border-bottom-left-radius: 0;
+  border-bottom-right-radius: 0;
+  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
   background: #f8fbfd;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
   background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
   background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
   background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
   background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
   background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
   background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+}
+.oo-ui-popupToolGroup.oo-ui-iconElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+  margin-left: 3em;
+}
+.oo-ui-popupToolGroup.oo-ui-indicatorElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+  margin-right: 2.25em;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+  top: 2em;
+  margin: 0 -1px;
+  border: solid 1px #ccc;
+  background-color: white;
+  box-shadow: 0 0.25em 1em rgba(0, 0, 0, 0.25);
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  height: 2em;
+  width: 2em;
+  margin-right: 0.25em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  line-height: 2em;
+  font-size: 0.8em;
+}
+.oo-ui-listToolGroup .oo-ui-tool {
+  display: inline-block;
+  width: 100%;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-listToolGroup .oo-ui-tool-link {
+  display: block;
+  cursor: pointer;
+  white-space: nowrap;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+.oo-ui-listToolGroup .oo-ui-toolGroup-tools {
+  padding: 0.25em;
+}
+.oo-ui-listToolGroup.oo-ui-popupToolGroup-active {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-listToolGroup .oo-ui-tool {
+  border: solid 1px transparent;
+  margin: -1px 0;
+}
+.oo-ui-listToolGroup .oo-ui-tool-link {
+  padding-right: 0.5em;
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled {
   border-color: rgba(0, 0, 0, 0.1);
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
   box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+  background: #f8fbfd;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
 }
-
 .oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
   border-top-color: rgba(0, 0, 0, 0.1);
 }
-
 .oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled:hover {
   border-color: rgba(0, 0, 0, 0.2);
 }
-
 .oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
   border-color: rgba(0, 0, 0, 0.2);
 }
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-iconElement-icon {
   opacity: 0.8;
 }
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconedElement-icon {
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconElement-icon {
   opacity: 1;
 }
-
 .oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
   color: #ccc;
 }
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconElement-icon {
   opacity: 0.2;
 }
-
 .oo-ui-listToolGroup.oo-ui-widget-disabled {
   color: #ccc;
 }
-
-.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-indicatedElement-indicator,
-.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-iconedElement-icon {
+.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator,
+.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-iconElement-icon {
   opacity: 0.2;
 }
-
 .oo-ui-menuToolGroup {
   border-color: rgba(0, 0, 0, 0.1);
 }
-
+.oo-ui-menuToolGroup .oo-ui-tool {
+  display: block;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link {
+  display: block;
+  cursor: pointer;
+  white-space: nowrap;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  background-image: none;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconElement-icon {
+  background-image: /* @embed */ url(images/icons/check.svg);
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+  min-width: 8em;
+}
+.oo-ui-menuToolGroup .oo-ui-toolGroup-tools {
+  padding: 0.25em 0 0.25em 0;
+}
 .oo-ui-menuToolGroup.oo-ui-widget-enabled:hover {
   border-color: rgba(0, 0, 0, 0.2);
 }
-
 .oo-ui-menuToolGroup.oo-ui-popupToolGroup-active {
   border-color: rgba(0, 0, 0, 0.25);
 }
-
+.oo-ui-menuToolGroup .oo-ui-tool-link {
+  padding: 0 1em 0 0.25em;
+}
 .oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
   background-color: #e1f3ff;
 }
-
 .oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
   color: #ccc;
 }
-
-.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconElement-icon {
   opacity: 0.2;
 }
-
 .oo-ui-menuToolGroup.oo-ui-widget-disabled {
   color: #ccc;
   border-color: rgba(0, 0, 0, 0.05);
 }
-
-.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-indicatedElement-indicator,
-.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-iconedElement-icon {
+.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator,
+.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-iconElement-icon {
   opacity: 0.2;
 }
-
-.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator,
-.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
-  opacity: 0.8;
+.oo-ui-toolbar {
+  clear: both;
 }
-
-.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
-  background-color: white;
-  border: solid 1px #ccc;
-  box-shadow: 0 0.25em 1em rgba(0, 0, 0, 0.25);
+.oo-ui-toolbar-bar {
+  line-height: 1em;
 }
-
-.oo-ui-popupToolGroup-active.oo-ui-widget-enabled {
+.oo-ui-toolbar-actions {
+  float: right;
+}
+.oo-ui-toolbar-tools {
+  display: inline;
+}
+.oo-ui-toolbar-tools,
+.oo-ui-toolbar-actions,
+.oo-ui-toolbar-shadow {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-toolbar-actions .oo-ui-popupWidget {
+  -webkit-touch-callout: default;
+  -webkit-user-select: all;
+  -moz-user-select: all;
+  -ms-user-select: all;
+  user-select: all;
+}
+.oo-ui-toolbar-shadow {
+  background-position: left top;
+  background-repeat: repeat-x;
+  position: absolute;
+  width: 100%;
+  pointer-events: none;
+}
+.oo-ui-toolbar-bar {
+  border-bottom: solid 1px #ccc;
   background: #f8fbfd;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
-  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  border-bottom-right-radius: 0;
-  border-bottom-left-radius: 0;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
-  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#f1f7fb');
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #f1f7fb));
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: -moz-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: -ms-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: -o-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+}
+.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
+  border: none;
+  background: none;
+}
+.oo-ui-toolbar-shadow {
+  background-image: /* @embed */ url(images/toolbar-shadow.png);
+  bottom: -9px;
+  height: 9px;
+  opacity: 0.125;
+  -webkit-transition: opacity 500ms ease-in-out;
+  -moz-transition: opacity 500ms ease-in-out;
+  -ms-transition: opacity 500ms ease-in-out;
+  -o-transition: opacity 500ms ease-in-out;
+  transition: opacity 500ms ease-in-out;
 }
-
 .oo-ui-optionWidget {
+  position: relative;
+  display: block;
+  cursor: pointer;
   padding: 0.5em 2em 0.5em 3em;
+  border: none;
+}
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+  cursor: default;
+}
+.oo-ui-optionWidget .oo-ui-labelElement-label {
+  display: block;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
 }
-
 .oo-ui-optionWidget-highlighted {
   background-color: #e1f3ff;
 }
-
+.oo-ui-optionWidget .oo-ui-labelElement-label {
+  line-height: 1.5em;
+}
 .oo-ui-selectWidget-depressed .oo-ui-optionWidget-selected {
   background-color: #a7dcff;
 }
-
 .oo-ui-selectWidget-pressed .oo-ui-optionWidget-pressed {
   background-color: #a7dcff;
 }
-
 .oo-ui-optionWidget.oo-ui-widget-disabled {
   color: #ccc;
 }
-
-.oo-ui-menuWidget {
-  margin-top: -1px;
-  background: #fff;
-  border: solid 1px #ccc;
-  border-radius: 0 0 0.25em 0.25em;
-  box-shadow: 0 0.15em 1em 0 rgba(0, 0, 0, 0.2);
-}
-
-.oo-ui-popupWidget-popup {
-  background-color: #fff;
-  border: solid 1px #ccc;
-  border-radius: 0.25em;
-  box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+  position: absolute;
+  background-repeat: no-repeat;
+  background-position: center center;
 }
-
-.oo-ui-popupWidget-tailed .oo-ui-popupWidget-tail {
-  width: 15px;
-  height: 8px;
-  margin-left: -7px;
-  background-image: /* @embed */ url(images/tail.svg);
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+  top: 50%;
+  width: 2em;
+  height: 2em;
+  margin-top: -1em;
 }
-
-.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
-  -webkit-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
-     -moz-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
-      -ms-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
-       -o-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
-          transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon {
+  left: 0.5em;
 }
-
-.oo-ui-popupWidget-body {
-  box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+  right: 0.5em;
 }
-
-.oo-ui-buttonGroupWidget {
+.oo-ui-buttonSelectWidget {
   display: inline-block;
   white-space: nowrap;
-}
-
-.oo-ui-buttonOptionWidget {
-  padding: 0;
-}
-
-.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected,
-.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
-.oo-ui-buttonOptionWidget.oo-ui-optionWidget-highlighted {
-  background-color: transparent;
-}
-
-.oo-ui-buttonSelectWidget {
   border-radius: 0.3em;
 }
-
-.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
-  margin-left: -1px;
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
   border-radius: 0;
+  margin-left: -1px;
 }
-
-.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:first-child .oo-ui-buttonedElement-button {
-  margin-left: 0;
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:first-child .oo-ui-buttonElement-button {
   border-bottom-left-radius: 0.3em;
   border-top-left-radius: 0.3em;
+  margin-left: 0;
 }
-
-.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:last-child .oo-ui-buttonedElement-button {
-  border-top-right-radius: 0.3em;
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:last-child .oo-ui-buttonElement-button {
   border-bottom-right-radius: 0.3em;
+  border-top-right-radius: 0.3em;
 }
-
-.oo-ui-inlineMenuWidget-handle {
-  border: solid 1px rgba(0, 0, 0, 0.1);
-  border-radius: 0.25em;
+.oo-ui-buttonOptionWidget {
+  display: inline-block;
+  padding: 0;
+  background-color: transparent;
 }
-
-.oo-ui-inlineMenuWidget-handle:hover {
-  border-color: rgba(0, 0, 0, 0.2);
+.oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+  position: relative;
 }
-
-.oo-ui-inlineMenuWidget-handle .oo-ui-indicatedElement-indicator,
-.oo-ui-inlineMenuWidget-handle .oo-ui-iconedElement-icon {
-  opacity: 0.8;
+.oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  position: static;
+  display: inline-block;
+  vertical-align: middle;
 }
-
-.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle {
-  color: #ccc;
-  text-shadow: 0 1px 1px #fff;
-  background-color: #f3f3f3;
-  border-color: #ddd;
+.oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+  height: 1.9em;
 }
-
-.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-indicatedElement-indicator {
-  opacity: 0.2;
+.oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  height: 1.9em;
+  margin-top: 0;
 }
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected,
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-highlighted {
   background-color: transparent;
 }
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted,
-.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted.oo-ui-optionWidget-selected {
-  background-color: #e1f3ff;
-}
-
-.oo-ui-menuSectionItemWidget {
-  padding: 0.33em 0.75em;
-  color: #888;
+.oo-ui-labelWidget {
+  display: inline-block;
+  padding: 0.5em 0;
 }
-
-.oo-ui-outlineControlsWidget {
-  background-color: #fff;
+.oo-ui-iconWidget {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+  line-height: 2.5em;
+  height: 1.9em;
+  width: 1.9em;
+  opacity: 0.8;
 }
-
-.oo-ui-outlineControlsWidget > .oo-ui-iconedElement-icon {
+.oo-ui-iconWidget.oo-ui-widget-disabled {
   opacity: 0.2;
 }
-
-.oo-ui-outlineItemWidget {
-  font-size: 1.1em;
-}
-
-.oo-ui-outlineItemWidget.oo-ui-indicatedElement .oo-ui-labeledElement-label {
-  padding-right: 1.5em;
+.oo-ui-indicatorWidget {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+  line-height: 2.5em;
+  height: 1.9em;
+  width: 1.9em;
+  opacity: 0.8;
 }
-
-.oo-ui-outlineItemWidget.oo-ui-indicatedElement .oo-ui-indicatedElement-indicator {
-  opacity: 0.5;
+.oo-ui-indicatorWidget.oo-ui-widget-disabled {
+  opacity: 0.2;
 }
-
-.oo-ui-outlineItemWidget-level-0 {
-  padding-left: 3.5em;
+.oo-ui-buttonWidget {
+  display: inline-block;
+  vertical-align: middle;
 }
-
-.oo-ui-outlineItemWidget-level-0 .oo-ui-iconedElement-icon {
-  left: 1em;
+.oo-ui-buttonGroupWidget {
+  display: inline-block;
+  white-space: nowrap;
+  border-radius: 0.3em;
 }
-
-.oo-ui-outlineItemWidget-level-1 {
-  padding-left: 5em;
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+  border-radius: 0;
+  margin-bottom: -1px;
+  margin-left: -1px;
 }
-
-.oo-ui-outlineItemWidget-level-1 .oo-ui-iconedElement-icon {
-  left: 2.5em;
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:first-child .oo-ui-buttonElement-button {
+  border-bottom-left-radius: 0.3em;
+  border-top-left-radius: 0.3em;
+  margin-left: 0;
 }
-
-.oo-ui-outlineItemWidget-level-2 {
-  padding-left: 6.5em;
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:last-child .oo-ui-buttonElement-button {
+  border-bottom-right-radius: 0.3em;
+  border-top-right-radius: 0.3em;
 }
-
-.oo-ui-outlineItemWidget-level-2 .oo-ui-iconedElement-icon {
-  left: 4em;
+.oo-ui-toggleSwitchWidget {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+  overflow: hidden;
+  cursor: pointer;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+  -webkit-transform: translateZ(0px);
+  -moz-transform: translateZ(0px);
+  -ms-transform: translateZ(0px);
+  -o-transform: translateZ(0px);
+  transform: translateZ(0px);
+  height: 2em;
+  width: 4em;
+  border-radius: 1em;
+  box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
+  border: solid 1px #ccc;
+  background: #eeeeee;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#dddddd', endColorstr='#ffffff');
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #dddddd), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
 }
-
-.oo-ui-selectWidget-depressed .oo-ui-outlineItemWidget.oo-ui-optionWidget-selected {
-  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
-  background-color: #a7dcff;
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+  cursor: default;
 }
-
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-important {
-  font-weight: bold;
+.oo-ui-toggleSwitchWidget-grip {
+  position: absolute;
+  display: block;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
 }
-
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-placeholder {
-  font-style: italic;
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  right: 0;
+  left: 0;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
 }
-
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-iconedElement-icon {
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+  display: none;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
   opacity: 0.5;
 }
-
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-labeledElement-label {
-  color: #777;
+.oo-ui-toggleSwitchWidget-grip {
+  top: 0.25em;
+  left: 0.25em;
+  width: 1.5em;
+  height: 1.5em;
+  margin-top: -1px;
+  border-radius: 1em;
+  box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
+  border: 1px #c9c9c9 solid;
+  -webkit-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+  -moz-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+  -ms-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+  -o-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+  transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+  background: #eeeeee;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#dddddd');
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #dddddd));
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
 }
-
-.oo-ui-searchWidget-query {
-  box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.2);
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover .oo-ui-toggleSwitchWidget-grip {
+  border-color: #aaa;
+}
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+  border-radius: 1em;
+  box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
+  -webkit-transition: opacity 200ms ease-in-out;
+  -moz-transition: opacity 200ms ease-in-out;
+  -ms-transition: opacity 200ms ease-in-out;
+  -o-transition: opacity 200ms ease-in-out;
+  transition: opacity 200ms ease-in-out;
+  background: #cde7f4;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#b0d9ee', endColorstr='#eaf4fa');
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #b0d9ee), color-stop(100%, #eaf4fa));
+  background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+}
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-glow {
+  opacity: 1;
+}
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+  left: 2.25em;
+  margin-left: -2px;
+}
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+  display: block;
+  opacity: 0;
+}
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
+  left: 0.25em;
+  margin-left: 0;
+}
+.oo-ui-actionWidget.oo-ui-pendingElement-pending {
+  background-image: /* @embed */ url(images/textures/pending.gif);
+}
+.oo-ui-popupWidget-popup {
+  position: absolute;
+  overflow: hidden;
+  z-index: 1;
+}
+.oo-ui-popupWidget-anchor {
+  display: none;
+  z-index: 1;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor {
+  display: block;
+  position: absolute;
+  background-repeat: no-repeat;
+}
+.oo-ui-popupWidget-head {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-popupWidget-head .oo-ui-buttonWidget {
+  float: right;
+}
+.oo-ui-popupWidget-head .oo-ui-labelElement-label {
+  float: left;
+  cursor: default;
+}
+.oo-ui-popupWidget-body {
+  clear: both;
+  overflow: hidden;
+}
+.oo-ui-popupWidget-popup {
+  border: solid 1px #ccc;
+  border-radius: 0.25em;
+  background-color: #fff;
+  box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-popup {
+  margin-top: 7px;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor {
+  width: 15px;
+  height: 8px;
+  margin-left: -7px;
+  background-image: /* @embed */ url(images/anchor.svg);
+}
+.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
+  -webkit-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+  -moz-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+  -ms-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+  -o-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+  transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+}
+.oo-ui-popupWidget-head {
+  height: 2.5em;
+}
+.oo-ui-popupWidget-head .oo-ui-buttonWidget {
+  margin: 0.25em;
+}
+.oo-ui-popupWidget-head .oo-ui-labelElement-label {
+  margin: 0.75em 1em;
+}
+.oo-ui-popupWidget-body {
+  box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
+}
+.oo-ui-popupWidget-body-padded {
+  padding: 0 1em;
+}
+.oo-ui-popupButtonWidget {
+  position: relative;
+}
+.oo-ui-popupButtonWidget .oo-ui-popupWidget {
+  position: absolute;
+  left: 1em;
+  cursor: auto;
 }
-
 .oo-ui-textInputWidget {
+  position: relative;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
   width: 20em;
 }
-
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+  display: inline-block;
+  width: 100%;
+  resize: none;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-textInputWidget.oo-ui-pendingElement-pending input,
+.oo-ui-textInputWidget.oo-ui-pendingElement-pending textarea {
+  background-image: /* @embed */ url(images/textures/pending.gif);
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator {
+  position: absolute;
+  top: 0;
+  height: 100%;
+  background-repeat: no-repeat;
+  cursor: pointer;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon {
+  left: 0;
+}
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator {
+  right: 0;
+}
 .oo-ui-textInputWidget input,
 .oo-ui-textInputWidget textarea {
   padding: 0.5em;
-  font-family: sans-serif;
   font-size: 1em;
+  font-family: sans-serif;
   background-color: #fff;
   border: solid 1px #ccc;
-  border-radius: 0.25em;
   box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
+  border-radius: 0.25em;
   -webkit-transition: border-color 200ms, box-shadow 200ms;
-     -moz-transition: border-color 200ms, box-shadow 200ms;
-      -ms-transition: border-color 200ms, box-shadow 200ms;
-       -o-transition: border-color 200ms, box-shadow 200ms;
-          transition: border-color 200ms, box-shadow 200ms;
+  -moz-transition: border-color 200ms, box-shadow 200ms;
+  -ms-transition: border-color 200ms, box-shadow 200ms;
+  -o-transition: border-color 200ms, box-shadow 200ms;
+  transition: border-color 200ms, box-shadow 200ms;
 }
-
 .oo-ui-textInputWidget-decorated input,
 .oo-ui-textInputWidget-decorated textarea {
   padding-left: 2em;
 }
-
 .oo-ui-textInputWidget-icon {
   width: 2em;
 }
-
 .oo-ui-textInputWidget.oo-ui-widget-enabled input:focus,
 .oo-ui-textInputWidget.oo-ui-widget-enabled textarea:focus {
-  border-color: #a7dcff;
   outline: none;
+  border-color: #a7dcff;
   box-shadow: 0 0 0.3em #a7dcff, 0 0 0 white;
 }
-
 .oo-ui-textInputWidget input[readonly],
 .oo-ui-textInputWidget textarea[readonly] {
   color: #777;
   text-shadow: 0 1px 1px #fff;
 }
-
-.oo-ui-textInputWidget-pending input,
-.oo-ui-textInputWidget-pending textarea {
+.oo-ui-textInputWidget.oo-ui-pendingElement-pending input,
+.oo-ui-textInputWidget.oo-ui-pendingElement-pending textarea {
   background-color: transparent;
 }
-
 .oo-ui-textInputWidget.oo-ui-widget-disabled input,
 .oo-ui-textInputWidget.oo-ui-widget-disabled input:focus,
 .oo-ui-textInputWidget.oo-ui-widget-disabled textarea,
 .oo-ui-textInputWidget.oo-ui-widget-disabled textarea:focus {
   color: #ccc;
   text-shadow: 0 1px 1px #fff;
-  background-color: #f3f3f3;
   border-color: #ddd;
+  background-color: #f3f3f3;
 }
-
-.oo-ui-toggleSwitchWidget {
-  background: #eeeeee;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #dddddd), color-stop(100%, #ffffff));
-  background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
+.oo-ui-textInputWidget .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget .oo-ui-indicatorElement-indicator {
+  opacity: 0.8;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement input,
+.oo-ui-textInputWidget.oo-ui-iconElement textarea {
+  padding-left: 2em;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+  width: 2em;
+  background-position: right center;
+}
+.oo-ui-textInputWidget.oo-ui-indicatorElement input,
+.oo-ui-textInputWidget.oo-ui-indicatorElement textarea {
+  padding-right: 1.5em;
+}
+.oo-ui-textInputWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  width: 1.5em;
+  background-position: left center;
+}
+.oo-ui-menuWidget {
+  position: absolute;
+  background: #fff;
+  margin-top: -1px;
   border: solid 1px #ccc;
-  border-radius: 1em;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#dddddd', endColorstr='#ffffff');
-  box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
+  border-radius: 0 0 0.25em 0.25em;
+  box-shadow: 0 0.15em 1em 0 rgba(0, 0, 0, 0.2);
 }
-
-.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+.oo-ui-menuWidget input {
+  position: absolute;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+  opacity: 0;
+}
+.oo-ui-menuItemWidget {
+  position: relative;
+}
+.oo-ui-menuItemWidget .oo-ui-iconElement-icon {
+  display: none;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+  background-color: transparent;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected .oo-ui-iconElement-icon {
+  display: block;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+  background-color: transparent;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted,
+.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted.oo-ui-optionWidget-selected {
+  background-color: #e1f3ff;
+}
+.oo-ui-menuSectionItemWidget {
+  cursor: default;
+  padding: 0.33em 0.75em;
+  color: #888;
+}
+.oo-ui-inlineMenuWidget {
+  position: relative;
+  display: inline-block;
+  margin: 0.25em 0;
+  min-width: 20em;
+}
+.oo-ui-inlineMenuWidget-handle {
+  width: 100%;
+  display: inline-block;
+  cursor: pointer;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon {
+  position: absolute;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-inlineMenuWidget .oo-ui-menuWidget {
+  z-index: 1;
+  width: 100%;
+}
+.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle {
+  cursor: default;
+}
+.oo-ui-inlineMenuWidget-handle {
+  height: 2.5em;
+  border: solid 1px rgba(0, 0, 0, 0.1);
+  border-radius: 0.25em;
+}
+.oo-ui-inlineMenuWidget-handle:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator {
+  right: 0;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon {
+  left: 0.25em;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label {
+  line-height: 2.5em;
+  margin: 0 0.5em;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon {
+  top: 0;
+  width: 2.5em;
+  height: 2.5em;
+  opacity: 0.8;
+}
+.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle {
+  color: #ccc;
+  text-shadow: 0 1px 1px #fff;
+  border-color: #ddd;
+  background-color: #f3f3f3;
+}
+.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+  opacity: 0.2;
+}
+.oo-ui-inlineMenuWidget.oo-ui-iconElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label {
+  margin-left: 3em;
+}
+.oo-ui-inlineMenuWidget.oo-ui-indicatorElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label {
+  margin-right: 2em;
+}
+.oo-ui-outlineItemWidget {
+  position: relative;
+  cursor: pointer;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  font-size: 1.1em;
+  padding: 0.75em;
+}
+.oo-ui-outlineItemWidget.oo-ui-indicatorElement .oo-ui-labelElement-label {
+  padding-right: 1.5em;
+}
+.oo-ui-outlineItemWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
   opacity: 0.5;
 }
-
-.oo-ui-toggleSwitchWidget-grip {
-  background: #eeeeee;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #dddddd));
-  background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  border: 1px #c9c9c9 solid;
-  border-radius: 1em;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#dddddd');
-  box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
+.oo-ui-outlineItemWidget-level-0 {
+  padding-left: 3.5em;
 }
-
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover,
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover .oo-ui-toggleSwitchWidget-grip {
-  border-color: #aaa;
+.oo-ui-outlineItemWidget-level-0 .oo-ui-iconElement-icon {
+  left: 1em;
 }
-
-.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
-  background: #cde7f4;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #b0d9ee), color-stop(100%, #eaf4fa));
-  background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  border-radius: 1em;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#b0d9ee', endColorstr='#eaf4fa');
-  box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
+.oo-ui-outlineItemWidget-level-1 {
+  padding-left: 5em;
 }
-
-.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-glow {
-  opacity: 1;
+.oo-ui-outlineItemWidget-level-1 .oo-ui-iconElement-icon {
+  left: 2.5em;
 }
-
-.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+.oo-ui-outlineItemWidget-level-2 {
+  padding-left: 6.5em;
+}
+.oo-ui-outlineItemWidget-level-2 .oo-ui-iconElement-icon {
+  left: 4em;
+}
+.oo-ui-selectWidget-depressed .oo-ui-outlineItemWidget.oo-ui-optionWidget-selected {
+  background-color: #a7dcff;
+  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
+}
+.oo-ui-outlineItemWidget.oo-ui-flaggedElement-important {
+  font-weight: bold;
+}
+.oo-ui-outlineItemWidget.oo-ui-flaggedElement-placeholder {
+  font-style: italic;
+}
+.oo-ui-outlineItemWidget.oo-ui-flaggedElement-empty .oo-ui-iconElement-icon {
+  opacity: 0.5;
+}
+.oo-ui-outlineItemWidget.oo-ui-flaggedElement-empty .oo-ui-labelElement-label {
+  color: #777;
+}
+.oo-ui-outlineControlsWidget {
+  height: 3em;
+  background-color: #fff;
+}
+.oo-ui-outlineControlsWidget-items,
+.oo-ui-outlineControlsWidget-movers {
+  float: left;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+  float: left;
+  background-position: right center;
+  background-repeat: no-repeat;
+}
+.oo-ui-outlineControlsWidget-items {
+  float: left;
+}
+.oo-ui-outlineControlsWidget-items .oo-ui-buttonWidget {
+  float: left;
+}
+.oo-ui-outlineControlsWidget-movers {
+  float: right;
+}
+.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
+  float: right;
+}
+.oo-ui-outlineControlsWidget-items,
+.oo-ui-outlineControlsWidget-movers {
+  height: 2em;
+  margin: 0.5em;
+  padding: 0;
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+  width: 1.5em;
+  height: 2em;
+  margin: 0.5em 0 0.5em 0.5em;
+  opacity: 0.2;
+}
+.oo-ui-outlineControlsWidget-items {
+  margin-left: 0;
+}
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget {
+  z-index: 1;
+  min-width: 20em;
+}
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget-handle {
+  border: solid 1px rgba(0, 0, 0, 0.1);
+  border-radius: 0.25em;
+}
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget-handle:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget.oo-ui-widget-disabled .oo-ui-textInputWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator,
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget-empty .oo-ui-textInputWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  cursor: default;
+  opacity: 0.2;
+}
+.oo-ui-searchWidget-query {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+  width: 100%;
+}
+.oo-ui-searchWidget-results {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.oo-ui-searchWidget-query {
+  height: 4em;
+  padding: 0 1em;
+  box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.2);
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+  margin: 0.75em 0;
+}
+.oo-ui-searchWidget-results {
+  top: 4em;
+  padding: 1em;
+  line-height: 0;
+}
+.oo-ui-window {
+  line-height: 1em;
+  /* Content div takes focus when opened, so hide outline */
+}
+.oo-ui-window-frame {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-window-frame > iframe {
+  width: 100%;
+  height: 100%;
+  margin: 0;
+  padding: 0;
+}
+.oo-ui-window-content:focus {
+  outline: none;
+}
+.oo-ui-window-head,
+.oo-ui-window-foot {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-window-body {
+  margin: 0;
+  padding: 0;
+  background: none;
+}
+.oo-ui-window-overlay {
+  position: absolute;
+  top: 0;
+  left: 0;
+}
+.oo-ui-window-isolated {
+  background-color: transparent;
+  background-image: none;
+  font-family: sans-serif;
+  font-size: 0.8em;
+}
+.oo-ui-dialog-content > .oo-ui-window-head,
+.oo-ui-dialog-content > .oo-ui-window-body,
+.oo-ui-dialog-content > .oo-ui-window-foot {
+  position: absolute;
+  left: 0;
+  right: 0;
+  overflow: hidden;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-dialog-content > .oo-ui-window-head {
+  z-index: 1;
+  top: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-head.oo-ui-pendingElement-pending {
+  background-image: /* @embed */ url(images/textures/pending.gif);
+}
+.oo-ui-dialog-content > .oo-ui-window-body {
+  z-index: 2;
+  top: 0;
+  bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-foot {
+  z-index: 1;
+  bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-overlay {
+  z-index: 3;
+}
+.oo-ui-dialog-content > .oo-ui-window-body {
+  box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
+}
+.oo-ui-messageDialog-actions-horizontal {
+  display: table;
+  table-layout: fixed;
+  width: 100%;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+  display: table-cell;
+  width: 1%;
+}
+.oo-ui-messageDialog-actions-vertical {
   display: block;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+  display: block;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget {
+  position: relative;
+  text-align: center;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-buttonElement-button {
+  display: block;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-labelElement-label {
+  position: relative;
+  top: auto;
+  bottom: auto;
+  display: inline;
+  white-space: nowrap;
+}
+.oo-ui-messageDialog-content .oo-ui-window-body {
+  box-shadow: 0 0 0.33em rgba(0, 0, 0, 0.33);
+}
+.oo-ui-messageDialog-title,
+.oo-ui-messageDialog-message {
+  display: block;
+  text-align: center;
+  padding-top: 0.5em;
+}
+.oo-ui-messageDialog-title {
+  font-size: 1.5em;
+  line-height: 1em;
+  color: #000;
+}
+.oo-ui-messageDialog-message {
+  font-size: 0.9em;
+  line-height: 1.25em;
+  color: #666;
+}
+.oo-ui-messageDialog-message-verbose {
+  font-size: 1.1em;
+  line-height: 1.5em;
+  text-align: left;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+  border-right: solid 1px #e5e5e5;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget:last-child {
+  border-right-width: 0;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+  border-bottom: solid 1px #e5e5e5;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget:last-child {
+  border-bottom-width: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-labelElement-label {
+  text-align: center;
+  line-height: 3.4em;
+  padding: 0 2em;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:hover {
+  background-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:active {
+  background-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-primary:hover {
+  background-color: rgba(8, 126, 204, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-primary:active {
+  background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-labelElement-label {
+  font-weight: bold;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover {
+  background-color: rgba(118, 171, 54, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active {
+  background-color: rgba(118, 171, 54, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover {
+  background-color: rgba(212, 83, 83, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active {
+  background-color: rgba(212, 83, 83, 0.1);
+}
+.oo-ui-processDialog-location {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.oo-ui-processDialog-title {
+  display: inline;
+  padding: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget {
+  white-space: nowrap;
+}
+.oo-ui-processDialog-actions-safe,
+.oo-ui-processDialog-actions-primary {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+}
+.oo-ui-processDialog-actions-safe {
+  left: 0;
+}
+.oo-ui-processDialog-actions-primary {
+  right: 0;
+}
+.oo-ui-processDialog-errors {
+  display: none;
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 2;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.oo-ui-processDialog-content .oo-ui-window-head {
+  height: 3.4em;
+}
+.oo-ui-processDialog-content .oo-ui-window-body {
+  top: 3.4em;
+  box-shadow: 0 0 0.33em rgba(0, 0, 0, 0.33);
+}
+.oo-ui-processDialog-navigation {
+  position: relative;
+  height: 3.4em;
+  padding: 0 1em;
+}
+.oo-ui-processDialog-location {
+  padding: 0.75em 0;
+  height: 1.9em;
+  cursor: default;
+  text-align: center;
+}
+.oo-ui-processDialog-title {
+  font-weight: bold;
+  line-height: 1.9em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-buttonElement-button {
+  padding-top: 0.75em;
+  padding-bottom: 0.75em;
+  min-width: 1.9em;
+  min-height: 1.9em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-labelElement-label {
+  line-height: 1.9em;
+  padding: 0 1em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-iconElement-icon,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-iconElement-icon,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-iconElement-icon {
+  position: absolute;
+  margin-top: -0.125em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-framed {
+  margin: 0.75em 0 0.75em 0.75em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+  padding: 0;
+  vertical-align: middle;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget:hover {
+  background-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget:active {
+  background-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed {
+  margin: 0.75em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+  /* Adjust for border so text aligns with title */
+  margin: -1px;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-primary:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-primary:hover {
+  background-color: rgba(8, 126, 204, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-primary:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-primary:active {
+  background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-labelElement-label {
+  font-weight: bold;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover {
+  background-color: rgba(118, 171, 54, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active {
+  background-color: rgba(118, 171, 54, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover {
+  background-color: rgba(212, 83, 83, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active {
+  background-color: rgba(212, 83, 83, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+  left: 0.5em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-labelElement-label {
+  padding-left: 2.25em;
+}
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+  right: 0.5em;
+}
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-labelElement-label {
+  padding-right: 2.25em;
+}
+.oo-ui-processDialog > .oo-ui-window-frame {
+  min-height: 5em;
+}
+.oo-ui-processDialog-errors {
+  background-color: rgba(255, 255, 255, 0.9);
+  padding: 3em 3em 1.5em 3em;
+  text-align: center;
+}
+.oo-ui-processDialog-errors .oo-ui-buttonWidget {
+  margin: 2em 1em 2em 1em;
+}
+.oo-ui-processDialog-errors-title {
+  font-size: 1.5em;
+  color: #000;
+  margin-bottom: 2em;
+}
+.oo-ui-processDialog-error {
+  text-align: left;
+  margin: 1em;
+  padding: 1em;
+  border: solid 1px #ff9e9e;
+  background-color: #fff7f7;
+  border-radius: 0.25em;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+  position: fixed;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup {
+  width: auto;
+  height: auto;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 1em;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup > .oo-ui-window-frame {
+  position: absolute;
+  right: 0;
+  left: 0;
+  margin: auto;
+  overflow: hidden;
+  max-width: 100%;
+  max-height: 100%;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup > .oo-ui-window-frame > iframe {
+  width: 100%;
+  height: 100%;
+}
+.oo-ui-windowManager-fullscreen > .oo-ui-dialog > .oo-ui-window-frame {
+  width: 100%;
+  height: 100%;
+  top: 0;
+  bottom: 0;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+  background-color: rgba(255, 255, 255, 0.5);
   opacity: 0;
-}
\ No newline at end of file
+  -webkit-transition: opacity 250ms ease-in-out;
+  -moz-transition: opacity 250ms ease-in-out;
+  -ms-transition: opacity 250ms ease-in-out;
+  -o-transition: opacity 250ms ease-in-out;
+  transition: opacity 250ms ease-in-out;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog > .oo-ui-window-frame {
+  top: 1em;
+  bottom: 1em;
+  background-color: #fff;
+  -webkit-transform: scale(0.5);
+  -moz-transform: scale(0.5);
+  -ms-transform: scale(0.5);
+  -o-transform: scale(0.5);
+  transform: scale(0.5);
+  -webkit-transition: all 250ms ease-in-out;
+  -moz-transition: all 250ms ease-in-out;
+  -ms-transition: all 250ms ease-in-out;
+  -o-transition: all 250ms ease-in-out;
+  transition: all 250ms ease-in-out;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-ready {
+  opacity: 1;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-ready > .oo-ui-window-frame {
+  -webkit-transform: scale(1);
+  -moz-transform: scale(1);
+  -ms-transform: scale(1);
+  -o-transform: scale(1);
+  transform: scale(1);
+}
+.oo-ui-windowManager-modal.oo-ui-windowManager-floating > .oo-ui-dialog > .oo-ui-window-frame {
+  border: solid 1px #ccc;
+  border-radius: 0.5em;
+  box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
+}
diff --git a/resources/lib/oojs-ui/oojs-ui-apex.rtl.css b/resources/lib/oojs-ui/oojs-ui-apex.rtl.css
new file mode 100644 (file)
index 0000000..7dd7b61
--- /dev/null
@@ -0,0 +1,1929 @@
+/*!
+ * OOjs UI v0.1.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2014 OOjs Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2014-09-11T19:39:50Z
+ */
+/*
+ * Blank theme mixins.
+ *
+ * Base styles invoke these mixins at the end of their definitions. Override these mixins to add
+ * additional rules to the base styles.
+ */
+/*
+ * Base styles.
+ *
+ * Themes should include this file after defining their variables and mixins.
+ */
+/* @noflip */
+.oo-ui-rtl {
+  direction: rtl;
+}
+/* @noflip */
+.oo-ui-ltr {
+  direction: ltr;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button {
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: middle;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  display: none;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+  display: none;
+}
+.oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+  cursor: default;
+}
+.oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-buttonElement-frameless {
+  display: inline-block;
+  position: relative;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
+  display: inline-block;
+  vertical-align: top;
+  text-align: center;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+  cursor: default;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button {
+  color: #333;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  margin-right: 0;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+  margin-left: -0.75em;
+}
+.oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  opacity: 0.8;
+  width: 1.9em;
+  height: 1.9em;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  /* Don't animate opacities for now, causes wiggling in Chrome (bug 63020) */
+  /*.oo-ui-transition(opacity 200ms);*/
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:hover > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:focus > .oo-ui-iconElement-icon {
+  opacity: 1;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label,
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:focus > .oo-ui-labelElement-label {
+  color: #000;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  color: #333;
+  margin-right: 0.25em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  color: #087ecc;
+}
+.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  color: #76ab36;
+}
+.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  color: #d45353;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  opacity: 0.2;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  color: #ccc;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
+  margin: 0.1em 0;
+  padding: 0.2em 0.8em;
+  border-radius: 0.3em;
+  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
+  border: 1px #c9c9c9 solid;
+  -webkit-transition: border-color 100ms ease-in-out;
+  -moz-transition: border-color 100ms ease-in-out;
+  -ms-transition: border-color 100ms ease-in-out;
+  -o-transition: border-color 100ms ease-in-out;
+  transition: border-color 100ms ease-in-out;
+  background: #eeeeee;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#dddddd');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #dddddd));
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button:focus {
+  border-color: #aaa;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  line-height: 1.9em;
+}
+.oo-ui-buttonElement-framed.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+  box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
+  color: black;
+  border-color: #c9c9c9;
+  background: #eeeeee;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#dddddd', endColorstr='#ffffff');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #dddddd), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
+}
+.oo-ui-buttonElement-framed.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  margin-right: -0.5em;
+  margin-left: -0.5em;
+}
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  margin-right: -0.5em;
+  margin-left: 0.3em;
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button {
+  border: solid 1px #a6cee1;
+  background: #cde7f4;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#eaf4fa', endColorstr='#b0d9ee');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eaf4fa), color-stop(100%, #b0d9ee));
+  background-image: -webkit-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  background-image: -moz-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  background-image: -ms-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  background-image: -o-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  background-image: linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button:focus {
+  border-color: #9dc2d4;
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-primary.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-primary.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+  border: solid 1px #a6cee1;
+  background: #cde7f4;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#b0d9ee', endColorstr='#eaf4fa');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #b0d9ee), color-stop(100%, #eaf4fa));
+  background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button {
+  border: solid 1px #b8d892;
+  background: #daf0be;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f0fbe1', endColorstr='#c3e59a');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f0fbe1), color-stop(100%, #c3e59a));
+  background-image: -webkit-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  background-image: -moz-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  background-image: -ms-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  background-image: -o-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  background-image: linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
+  border-color: #adcb89;
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+  border: solid 1px #b8d892;
+  background: #daf0be;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#c3e59a', endColorstr='#f0fbe1');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #c3e59a), color-stop(100%, #f0fbe1));
+  background-image: -webkit-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  background-image: -moz-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  background-image: -ms-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  background-image: -o-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  background-image: linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
+  color: #d45353;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+  opacity: 0.5;
+  box-shadow: none;
+  color: #333;
+  background: #eee;
+  border-color: #ccc;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button:focus {
+  border-color: #ccc;
+  box-shadow: none;
+}
+.oo-ui-clippableElement-clippable {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-bookletLayout-stackLayout.oo-ui-stackLayout-continuous .oo-ui-panelLayout-scrollable {
+  overflow-y: hidden;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
+  width: 100%;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-scrollable {
+  overflow-y: auto;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-padded {
+  padding: 2em;
+}
+.oo-ui-bookletLayout-outlinePanel-editable .oo-ui-outlineWidget {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 3em;
+  overflow-y: auto;
+}
+.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  left: 0;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
+  padding: 1.5em;
+}
+.oo-ui-bookletLayout-outlinePanel {
+  border-left: solid 1px #ddd;
+}
+.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
+  box-shadow: 0 0 0.25em rgba(0, 0, 0, 0.25);
+}
+.oo-ui-fieldLayout {
+  margin-bottom: 1em;
+}
+.oo-ui-fieldLayout:before,
+.oo-ui-fieldLayout:after {
+  content: " ";
+  display: table;
+}
+.oo-ui-fieldLayout:after {
+  clear: both;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labelElement-label {
+  display: block;
+  float: right;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field {
+  display: block;
+  float: right;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labelElement-label {
+  text-align: left;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labelElement-label {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labelElement-label {
+  display: inline-block;
+}
+.oo-ui-fieldLayout > .oo-ui-popupButtonWidget > .oo-ui-popupWidget > .oo-ui-popupWidget-popup {
+  z-index: 1;
+}
+.oo-ui-fieldLayout:last-child {
+  margin-bottom: 0;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labelElement-label {
+  padding-top: 0.5em;
+  margin-left: 5%;
+  width: 35%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field {
+  width: 60%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labelElement-label {
+  padding: 0.75em 0.5em 0.5em 0.5em;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field {
+  padding: 0.5em 0;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labelElement-label {
+  padding: 0.5em 0;
+}
+.oo-ui-fieldLayout > .oo-ui-popupButtonWidget > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  margin-top: 0.25em;
+}
+.oo-ui-fieldLayout-disabled .oo-ui-labelElement-label {
+  color: #ccc;
+}
+.oo-ui-fieldsetLayout {
+  position: relative;
+  margin: 0;
+  padding: 0;
+  border: none;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-iconElement-icon {
+  display: block;
+  position: absolute;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-fieldsetLayout.oo-ui-labelElement > .oo-ui-labelElement-label {
+  display: inline-block;
+}
+.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout {
+  margin-top: 2em;
+}
+.oo-ui-fieldsetLayout > .oo-ui-labelElement-label {
+  font-size: 1.5em;
+  margin-bottom: 0.5em;
+  padding: 0.25em 0;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-labelElement-label {
+  padding-right: 1.75em;
+  line-height: 1.33em;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-iconElement-icon {
+  right: 0;
+  top: 0.25em;
+  width: 2em;
+  height: 2em;
+}
+.oo-ui-gridLayout {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+}
+.oo-ui-panelLayout {
+  position: relative;
+}
+.oo-ui-panelLayout-scrollable {
+  overflow-y: auto;
+}
+.oo-ui-panelLayout-expanded {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+}
+.oo-ui-panelLayout-padded {
+  padding: 1.25em;
+}
+.oo-ui-stackLayout > .oo-ui-panelLayout {
+  display: none;
+}
+.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
+  display: block;
+  position: relative;
+}
+.oo-ui-popupTool .oo-ui-popupWidget-popup,
+.oo-ui-popupTool .oo-ui-popupWidget-anchor {
+  z-index: 4;
+}
+.oo-ui-popupTool .oo-ui-popupWidget {
+  margin-right: 1.25em;
+  font-size: 0.8em;
+}
+.oo-ui-toolGroup {
+  display: inline-block;
+  vertical-align: middle;
+  margin: 0.3em;
+  border-radius: 0.25em;
+  border: solid 1px transparent;
+  -webkit-transition: border-color 300ms ease-in-out;
+  -moz-transition: border-color 300ms ease-in-out;
+  -ms-transition: border-color 300ms ease-in-out;
+  -o-transition: border-color 300ms ease-in-out;
+  transition: border-color 300ms ease-in-out;
+}
+.oo-ui-toolGroup-empty {
+  display: none;
+}
+.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-toolGroup.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-toolGroup.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-tool-title {
+  color: #000;
+}
+.oo-ui-barToolGroup > .oo-ui-iconElement-icon,
+.oo-ui-barToolGroup > .oo-ui-labelElement-label {
+  display: none;
+}
+.oo-ui-barToolGroup .oo-ui-tool {
+  display: inline-block;
+  position: relative;
+  vertical-align: top;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link {
+  display: block;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  display: block;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  display: none;
+}
+.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+.oo-ui-barToolGroup .oo-ui-tool-title,
+.oo-ui-barToolGroup .oo-ui-tool-accel {
+  display: none;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-link {
+  cursor: pointer;
+}
+.oo-ui-barToolGroup .oo-ui-tool {
+  margin: -1px -1px -1px 0;
+  border: solid 1px transparent;
+}
+.oo-ui-barToolGroup .oo-ui-tool:first-child {
+  border-top-right-radius: 0.25em;
+  border-bottom-right-radius: 0.25em;
+}
+.oo-ui-barToolGroup .oo-ui-tool:last-child {
+  margin-left: -1px;
+  border-top-left-radius: 0.25em;
+  border-bottom-left-radius: 0.25em;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link {
+  height: 1.5em;
+  padding: 0.25em;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  height: 1.5em;
+  width: 1.5em;
+  opacity: 0.8;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-active.oo-ui-widget-enabled {
+  border-color: rgba(0, 0, 0, 0.2);
+  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+  background: #f8fbfd;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
+  border-right-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconElement-icon {
+  opacity: 0.2;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-iconElement-icon {
+  opacity: 0.8;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconElement-icon {
+  opacity: 1;
+}
+.oo-ui-barToolGroup.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconElement-icon {
+  opacity: 0.2;
+}
+.oo-ui-popupToolGroup {
+  position: relative;
+  height: 2em;
+  min-width: 2.5em;
+}
+.oo-ui-popupToolGroup-handle {
+  display: block;
+  cursor: pointer;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+  position: absolute;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-disabled .oo-ui-popupToolGroup-handle {
+  cursor: default;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+  display: none;
+  position: absolute;
+  z-index: 4;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools .oo-ui-iconElement-icon {
+  background-repeat: no-repeat;
+  background-position: center center;
+}
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled > .oo-ui-toolGroup-tools {
+  display: block;
+}
+.oo-ui-popupToolGroup-left > .oo-ui-toolGroup-tools {
+  right: 0;
+}
+.oo-ui-popupToolGroup-right > .oo-ui-toolGroup-tools {
+  left: 0;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-accel {
+  display: none;
+}
+.oo-ui-popupToolGroup.oo-ui-indicatorElement.oo-ui-iconElement {
+  min-width: 3.5em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+  top: 0;
+  width: 2em;
+  height: 2em;
+  opacity: 0.8;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator {
+  left: 0;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+  right: 0.25em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+  line-height: 2.6em;
+  font-size: 0.8em;
+  margin: 0 1em;
+}
+.oo-ui-popupToolGroup-header {
+  line-height: 2.6em;
+  font-size: 0.8em;
+  margin: 0 0.6em;
+  font-weight: bold;
+}
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+  background: #f8fbfd;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+}
+.oo-ui-popupToolGroup.oo-ui-iconElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+  margin-right: 3em;
+}
+.oo-ui-popupToolGroup.oo-ui-indicatorElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+  margin-left: 2.25em;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+  top: 2em;
+  margin: 0 -1px;
+  border: solid 1px #ccc;
+  background-color: white;
+  box-shadow: 0 0.25em 1em rgba(0, 0, 0, 0.25);
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  height: 2em;
+  width: 2em;
+  margin-left: 0.25em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  line-height: 2em;
+  font-size: 0.8em;
+}
+.oo-ui-listToolGroup .oo-ui-tool {
+  display: inline-block;
+  width: 100%;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-listToolGroup .oo-ui-tool-link {
+  display: block;
+  cursor: pointer;
+  white-space: nowrap;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+.oo-ui-listToolGroup .oo-ui-toolGroup-tools {
+  padding: 0.25em;
+}
+.oo-ui-listToolGroup.oo-ui-popupToolGroup-active {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-listToolGroup .oo-ui-tool {
+  border: solid 1px transparent;
+  margin: -1px 0;
+}
+.oo-ui-listToolGroup .oo-ui-tool-link {
+  padding-left: 0.5em;
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled {
+  border-color: rgba(0, 0, 0, 0.1);
+  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+  background: #f8fbfd;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
+  border-top-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-iconElement-icon {
+  opacity: 0.8;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconElement-icon {
+  opacity: 1;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
+  color: #ccc;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconElement-icon {
+  opacity: 0.2;
+}
+.oo-ui-listToolGroup.oo-ui-widget-disabled {
+  color: #ccc;
+}
+.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator,
+.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-iconElement-icon {
+  opacity: 0.2;
+}
+.oo-ui-menuToolGroup {
+  border-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-menuToolGroup .oo-ui-tool {
+  display: block;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link {
+  display: block;
+  cursor: pointer;
+  white-space: nowrap;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  background-image: none;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconElement-icon {
+  background-image: /* @embed */ url(images/icons/check.svg);
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+  min-width: 8em;
+}
+.oo-ui-menuToolGroup .oo-ui-toolGroup-tools {
+  padding: 0.25em 0 0.25em 0;
+}
+.oo-ui-menuToolGroup.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-menuToolGroup.oo-ui-popupToolGroup-active {
+  border-color: rgba(0, 0, 0, 0.25);
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link {
+  padding: 0 0.25em 0 1em;
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
+  background-color: #e1f3ff;
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
+  color: #ccc;
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconElement-icon {
+  opacity: 0.2;
+}
+.oo-ui-menuToolGroup.oo-ui-widget-disabled {
+  color: #ccc;
+  border-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator,
+.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-iconElement-icon {
+  opacity: 0.2;
+}
+.oo-ui-toolbar {
+  clear: both;
+}
+.oo-ui-toolbar-bar {
+  line-height: 1em;
+}
+.oo-ui-toolbar-actions {
+  float: left;
+}
+.oo-ui-toolbar-tools {
+  display: inline;
+}
+.oo-ui-toolbar-tools,
+.oo-ui-toolbar-actions,
+.oo-ui-toolbar-shadow {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-toolbar-actions .oo-ui-popupWidget {
+  -webkit-touch-callout: default;
+  -webkit-user-select: all;
+  -moz-user-select: all;
+  -ms-user-select: all;
+  user-select: all;
+}
+.oo-ui-toolbar-shadow {
+  background-position: right top;
+  background-repeat: repeat-x;
+  position: absolute;
+  width: 100%;
+  pointer-events: none;
+}
+.oo-ui-toolbar-bar {
+  border-bottom: solid 1px #ccc;
+  background: #f8fbfd;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#f1f7fb');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f1f7fb));
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: -moz-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: -ms-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: -o-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+}
+.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
+  border: none;
+  background: none;
+}
+.oo-ui-toolbar-shadow {
+  background-image: /* @embed */ url(images/toolbar-shadow.png);
+  bottom: -9px;
+  height: 9px;
+  opacity: 0.125;
+  -webkit-transition: opacity 500ms ease-in-out;
+  -moz-transition: opacity 500ms ease-in-out;
+  -ms-transition: opacity 500ms ease-in-out;
+  -o-transition: opacity 500ms ease-in-out;
+  transition: opacity 500ms ease-in-out;
+}
+.oo-ui-optionWidget {
+  position: relative;
+  display: block;
+  cursor: pointer;
+  padding: 0.5em 3em 0.5em 2em;
+  border: none;
+}
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+  cursor: default;
+}
+.oo-ui-optionWidget .oo-ui-labelElement-label {
+  display: block;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
+}
+.oo-ui-optionWidget-highlighted {
+  background-color: #e1f3ff;
+}
+.oo-ui-optionWidget .oo-ui-labelElement-label {
+  line-height: 1.5em;
+}
+.oo-ui-selectWidget-depressed .oo-ui-optionWidget-selected {
+  background-color: #a7dcff;
+}
+.oo-ui-selectWidget-pressed .oo-ui-optionWidget-pressed {
+  background-color: #a7dcff;
+}
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+  color: #ccc;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+  position: absolute;
+  background-repeat: no-repeat;
+  background-position: center center;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+  top: 50%;
+  width: 2em;
+  height: 2em;
+  margin-top: -1em;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon {
+  right: 0.5em;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+  left: 0.5em;
+}
+.oo-ui-buttonSelectWidget {
+  display: inline-block;
+  white-space: nowrap;
+  border-radius: 0.3em;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+  border-radius: 0;
+  margin-right: -1px;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:first-child .oo-ui-buttonElement-button {
+  border-bottom-right-radius: 0.3em;
+  border-top-right-radius: 0.3em;
+  margin-right: 0;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:last-child .oo-ui-buttonElement-button {
+  border-bottom-left-radius: 0.3em;
+  border-top-left-radius: 0.3em;
+}
+.oo-ui-buttonOptionWidget {
+  display: inline-block;
+  padding: 0;
+  background-color: transparent;
+}
+.oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+  position: relative;
+}
+.oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  position: static;
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+  height: 1.9em;
+}
+.oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  height: 1.9em;
+  margin-top: 0;
+}
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected,
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-highlighted {
+  background-color: transparent;
+}
+.oo-ui-labelWidget {
+  display: inline-block;
+  padding: 0.5em 0;
+}
+.oo-ui-iconWidget {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+  line-height: 2.5em;
+  height: 1.9em;
+  width: 1.9em;
+  opacity: 0.8;
+}
+.oo-ui-iconWidget.oo-ui-widget-disabled {
+  opacity: 0.2;
+}
+.oo-ui-indicatorWidget {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+  line-height: 2.5em;
+  height: 1.9em;
+  width: 1.9em;
+  opacity: 0.8;
+}
+.oo-ui-indicatorWidget.oo-ui-widget-disabled {
+  opacity: 0.2;
+}
+.oo-ui-buttonWidget {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-buttonGroupWidget {
+  display: inline-block;
+  white-space: nowrap;
+  border-radius: 0.3em;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+  border-radius: 0;
+  margin-bottom: -1px;
+  margin-right: -1px;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:first-child .oo-ui-buttonElement-button {
+  border-bottom-right-radius: 0.3em;
+  border-top-right-radius: 0.3em;
+  margin-right: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:last-child .oo-ui-buttonElement-button {
+  border-bottom-left-radius: 0.3em;
+  border-top-left-radius: 0.3em;
+}
+.oo-ui-toggleSwitchWidget {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+  overflow: hidden;
+  cursor: pointer;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+  -webkit-transform: translateZ(0px);
+  -moz-transform: translateZ(0px);
+  -ms-transform: translateZ(0px);
+  -o-transform: translateZ(0px);
+  transform: translateZ(0px);
+  height: 2em;
+  width: 4em;
+  border-radius: 1em;
+  box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
+  border: solid 1px #ccc;
+  background: #eeeeee;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#dddddd', endColorstr='#ffffff');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #dddddd), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+  cursor: default;
+}
+.oo-ui-toggleSwitchWidget-grip {
+  position: absolute;
+  display: block;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+  display: none;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+  opacity: 0.5;
+}
+.oo-ui-toggleSwitchWidget-grip {
+  top: 0.25em;
+  right: 0.25em;
+  width: 1.5em;
+  height: 1.5em;
+  margin-top: -1px;
+  border-radius: 1em;
+  box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
+  border: 1px #c9c9c9 solid;
+  -webkit-transition: right 200ms ease-in-out, margin-right 200ms ease-in-out;
+  -moz-transition: right 200ms ease-in-out, margin-right 200ms ease-in-out;
+  -ms-transition: right 200ms ease-in-out, margin-right 200ms ease-in-out;
+  -o-transition: right 200ms ease-in-out, margin-right 200ms ease-in-out;
+  transition: right 200ms ease-in-out, margin-right 200ms ease-in-out;
+  background: #eeeeee;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#dddddd');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #dddddd));
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover .oo-ui-toggleSwitchWidget-grip {
+  border-color: #aaa;
+}
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+  border-radius: 1em;
+  box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
+  -webkit-transition: opacity 200ms ease-in-out;
+  -moz-transition: opacity 200ms ease-in-out;
+  -ms-transition: opacity 200ms ease-in-out;
+  -o-transition: opacity 200ms ease-in-out;
+  transition: opacity 200ms ease-in-out;
+  background: #cde7f4;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#b0d9ee', endColorstr='#eaf4fa');
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #b0d9ee), color-stop(100%, #eaf4fa));
+  background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+}
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-glow {
+  opacity: 1;
+}
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+  right: 2.25em;
+  margin-right: -2px;
+}
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+  display: block;
+  opacity: 0;
+}
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
+  right: 0.25em;
+  margin-right: 0;
+}
+.oo-ui-popupWidget-popup {
+  position: absolute;
+  overflow: hidden;
+  z-index: 1;
+}
+.oo-ui-popupWidget-anchor {
+  display: none;
+  z-index: 1;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor {
+  display: block;
+  position: absolute;
+  background-repeat: no-repeat;
+}
+.oo-ui-popupWidget-head {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-popupWidget-head .oo-ui-buttonWidget {
+  float: left;
+}
+.oo-ui-popupWidget-head .oo-ui-labelElement-label {
+  float: right;
+  cursor: default;
+}
+.oo-ui-popupWidget-body {
+  clear: both;
+  overflow: hidden;
+}
+.oo-ui-popupWidget-popup {
+  border: solid 1px #ccc;
+  border-radius: 0.25em;
+  background-color: #fff;
+  box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-popup {
+  margin-top: 7px;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor {
+  width: 15px;
+  height: 8px;
+  margin-right: -7px;
+  background-image: /* @embed */ url(images/anchor.svg);
+}
+.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
+  -webkit-transition: width 100ms ease-in-out, height 100ms ease-in-out, right 100ms ease-in-out;
+  -moz-transition: width 100ms ease-in-out, height 100ms ease-in-out, right 100ms ease-in-out;
+  -ms-transition: width 100ms ease-in-out, height 100ms ease-in-out, right 100ms ease-in-out;
+  -o-transition: width 100ms ease-in-out, height 100ms ease-in-out, right 100ms ease-in-out;
+  transition: width 100ms ease-in-out, height 100ms ease-in-out, right 100ms ease-in-out;
+}
+.oo-ui-popupWidget-head {
+  height: 2.5em;
+}
+.oo-ui-popupWidget-head .oo-ui-buttonWidget {
+  margin: 0.25em;
+}
+.oo-ui-popupWidget-head .oo-ui-labelElement-label {
+  margin: 0.75em 1em;
+}
+.oo-ui-popupWidget-body {
+  box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
+}
+.oo-ui-popupWidget-body-padded {
+  padding: 0 1em;
+}
+.oo-ui-popupButtonWidget {
+  position: relative;
+}
+.oo-ui-popupButtonWidget .oo-ui-popupWidget {
+  position: absolute;
+  right: 1em;
+  cursor: auto;
+}
+.oo-ui-textInputWidget {
+  position: relative;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+  width: 20em;
+}
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+  display: inline-block;
+  width: 100%;
+  resize: none;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator {
+  position: absolute;
+  top: 0;
+  height: 100%;
+  background-repeat: no-repeat;
+  cursor: pointer;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon {
+  right: 0;
+}
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator {
+  left: 0;
+}
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+  padding: 0.5em;
+  font-size: 1em;
+  font-family: sans-serif;
+  background-color: #fff;
+  border: solid 1px #ccc;
+  box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
+  border-radius: 0.25em;
+  -webkit-transition: border-color 200ms, box-shadow 200ms;
+  -moz-transition: border-color 200ms, box-shadow 200ms;
+  -ms-transition: border-color 200ms, box-shadow 200ms;
+  -o-transition: border-color 200ms, box-shadow 200ms;
+  transition: border-color 200ms, box-shadow 200ms;
+}
+.oo-ui-textInputWidget-decorated input,
+.oo-ui-textInputWidget-decorated textarea {
+  padding-right: 2em;
+}
+.oo-ui-textInputWidget-icon {
+  width: 2em;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input:focus,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea:focus {
+  outline: none;
+  border-color: #a7dcff;
+  box-shadow: 0 0 0.3em #a7dcff, 0 0 0 white;
+}
+.oo-ui-textInputWidget input[readonly],
+.oo-ui-textInputWidget textarea[readonly] {
+  color: #777;
+  text-shadow: 0 1px 1px #fff;
+}
+.oo-ui-textInputWidget-pending input,
+.oo-ui-textInputWidget-pending textarea {
+  background-color: transparent;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled input,
+.oo-ui-textInputWidget.oo-ui-widget-disabled input:focus,
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea,
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea:focus {
+  color: #ccc;
+  text-shadow: 0 1px 1px #fff;
+  border-color: #ddd;
+  background-color: #f3f3f3;
+}
+.oo-ui-textInputWidget .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget .oo-ui-indicatorElement-indicator {
+  opacity: 0.8;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement input,
+.oo-ui-textInputWidget.oo-ui-iconElement textarea {
+  padding-right: 2em;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+  width: 2em;
+  background-position: left center;
+}
+.oo-ui-textInputWidget.oo-ui-indicatorElement input,
+.oo-ui-textInputWidget.oo-ui-indicatorElement textarea {
+  padding-left: 1.5em;
+}
+.oo-ui-textInputWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  width: 1.5em;
+  background-position: right center;
+}
+.oo-ui-menuWidget {
+  position: absolute;
+  background: #fff;
+  margin-top: -1px;
+  border: solid 1px #ccc;
+  border-radius: 0 0 0.25em 0.25em;
+  box-shadow: 0 0.15em 1em 0 rgba(0, 0, 0, 0.2);
+}
+.oo-ui-menuWidget input {
+  position: absolute;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+  opacity: 0;
+}
+.oo-ui-menuItemWidget {
+  position: relative;
+}
+.oo-ui-menuItemWidget .oo-ui-iconElement-icon {
+  display: none;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+  background-color: transparent;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected .oo-ui-iconElement-icon {
+  display: block;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+  background-color: transparent;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted,
+.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted.oo-ui-optionWidget-selected {
+  background-color: #e1f3ff;
+}
+.oo-ui-menuSectionItemWidget {
+  cursor: default;
+  padding: 0.33em 0.75em;
+  color: #888;
+}
+.oo-ui-inlineMenuWidget {
+  position: relative;
+  display: inline-block;
+  margin: 0.25em 0;
+  min-width: 20em;
+}
+.oo-ui-inlineMenuWidget-handle {
+  width: 100%;
+  display: inline-block;
+  cursor: pointer;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon {
+  position: absolute;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-inlineMenuWidget .oo-ui-menuWidget {
+  z-index: 1;
+  width: 100%;
+}
+.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle {
+  cursor: default;
+}
+.oo-ui-inlineMenuWidget-handle {
+  height: 2.5em;
+  border: solid 1px rgba(0, 0, 0, 0.1);
+  border-radius: 0.25em;
+}
+.oo-ui-inlineMenuWidget-handle:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator {
+  left: 0;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon {
+  right: 0.25em;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label {
+  line-height: 2.5em;
+  margin: 0 0.5em;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon {
+  top: 0;
+  width: 2.5em;
+  height: 2.5em;
+  opacity: 0.8;
+}
+.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle {
+  color: #ccc;
+  text-shadow: 0 1px 1px #fff;
+  border-color: #ddd;
+  background-color: #f3f3f3;
+}
+.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+  opacity: 0.2;
+}
+.oo-ui-inlineMenuWidget.oo-ui-iconElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label {
+  margin-right: 3em;
+}
+.oo-ui-inlineMenuWidget.oo-ui-indicatorElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label {
+  margin-left: 2em;
+}
+.oo-ui-outlineItemWidget {
+  position: relative;
+  cursor: pointer;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  font-size: 1.1em;
+  padding: 0.75em;
+}
+.oo-ui-outlineItemWidget.oo-ui-indicatorElement .oo-ui-labelElement-label {
+  padding-left: 1.5em;
+}
+.oo-ui-outlineItemWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  opacity: 0.5;
+}
+.oo-ui-outlineItemWidget-level-0 {
+  padding-right: 3.5em;
+}
+.oo-ui-outlineItemWidget-level-0 .oo-ui-iconElement-icon {
+  right: 1em;
+}
+.oo-ui-outlineItemWidget-level-1 {
+  padding-right: 5em;
+}
+.oo-ui-outlineItemWidget-level-1 .oo-ui-iconElement-icon {
+  right: 2.5em;
+}
+.oo-ui-outlineItemWidget-level-2 {
+  padding-right: 6.5em;
+}
+.oo-ui-outlineItemWidget-level-2 .oo-ui-iconElement-icon {
+  right: 4em;
+}
+.oo-ui-selectWidget-depressed .oo-ui-outlineItemWidget.oo-ui-optionWidget-selected {
+  background-color: #a7dcff;
+  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
+}
+.oo-ui-outlineItemWidget.oo-ui-flaggedElement-important {
+  font-weight: bold;
+}
+.oo-ui-outlineItemWidget.oo-ui-flaggedElement-placeholder {
+  font-style: italic;
+}
+.oo-ui-outlineItemWidget.oo-ui-flaggedElement-empty .oo-ui-iconElement-icon {
+  opacity: 0.5;
+}
+.oo-ui-outlineItemWidget.oo-ui-flaggedElement-empty .oo-ui-labelElement-label {
+  color: #777;
+}
+.oo-ui-outlineControlsWidget {
+  height: 3em;
+  background-color: #fff;
+}
+.oo-ui-outlineControlsWidget-items,
+.oo-ui-outlineControlsWidget-movers {
+  float: right;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+  float: right;
+  background-position: left center;
+  background-repeat: no-repeat;
+}
+.oo-ui-outlineControlsWidget-items {
+  float: right;
+}
+.oo-ui-outlineControlsWidget-items .oo-ui-buttonWidget {
+  float: right;
+}
+.oo-ui-outlineControlsWidget-movers {
+  float: left;
+}
+.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
+  float: left;
+}
+.oo-ui-outlineControlsWidget-items,
+.oo-ui-outlineControlsWidget-movers {
+  height: 2em;
+  margin: 0.5em;
+  padding: 0;
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+  width: 1.5em;
+  height: 2em;
+  margin: 0.5em 0.5em 0.5em 0;
+  opacity: 0.2;
+}
+.oo-ui-outlineControlsWidget-items {
+  margin-right: 0;
+}
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget {
+  z-index: 1;
+  min-width: 20em;
+}
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget-handle {
+  border: solid 1px rgba(0, 0, 0, 0.1);
+  border-radius: 0.25em;
+}
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget-handle:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget.oo-ui-widget-disabled .oo-ui-textInputWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator,
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget-empty .oo-ui-textInputWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  cursor: default;
+  opacity: 0.2;
+}
+.oo-ui-searchWidget-query {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+  width: 100%;
+}
+.oo-ui-searchWidget-results {
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  left: 0;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.oo-ui-searchWidget-query {
+  height: 4em;
+  padding: 0 1em;
+  box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.2);
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+  margin: 0.75em 0;
+}
+.oo-ui-searchWidget-results {
+  top: 4em;
+  padding: 1em;
+  line-height: 0;
+}
+.oo-ui-window {
+  line-height: 1em;
+  /* Content div takes focus when opened, so hide outline */
+}
+.oo-ui-window-frame {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-window-frame > iframe {
+  width: 100%;
+  height: 100%;
+  margin: 0;
+  padding: 0;
+}
+.oo-ui-window-content:focus {
+  outline: none;
+}
+.oo-ui-window-head,
+.oo-ui-window-foot {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-window-body {
+  margin: 0;
+  padding: 0;
+  background: none;
+}
+.oo-ui-window-overlay {
+  position: absolute;
+  top: 0;
+  right: 0;
+}
+.oo-ui-window-isolated {
+  background-color: transparent;
+  background-image: none;
+  font-family: sans-serif;
+  font-size: 0.8em;
+}
+.oo-ui-dialog-content > .oo-ui-window-head,
+.oo-ui-dialog-content > .oo-ui-window-body,
+.oo-ui-dialog-content > .oo-ui-window-foot {
+  position: absolute;
+  right: 0;
+  left: 0;
+  overflow: hidden;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-dialog-content > .oo-ui-window-head {
+  z-index: 1;
+  top: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-body {
+  z-index: 2;
+  top: 0;
+  bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-foot {
+  z-index: 1;
+  bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-overlay {
+  z-index: 3;
+}
+.oo-ui-dialog-content > .oo-ui-window-body {
+  box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
+}
+.oo-ui-messageDialog-actions-horizontal {
+  display: table;
+  table-layout: fixed;
+  width: 100%;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+  display: table-cell;
+  width: 1%;
+}
+.oo-ui-messageDialog-actions-vertical {
+  display: block;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+  display: block;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget {
+  position: relative;
+  text-align: center;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-buttonElement-button {
+  display: block;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-labelElement-label {
+  position: relative;
+  top: auto;
+  bottom: auto;
+  display: inline;
+  white-space: nowrap;
+}
+.oo-ui-messageDialog-content .oo-ui-window-body {
+  box-shadow: 0 0 0.33em rgba(0, 0, 0, 0.33);
+}
+.oo-ui-messageDialog-title,
+.oo-ui-messageDialog-message {
+  display: block;
+  text-align: center;
+  padding-top: 0.5em;
+}
+.oo-ui-messageDialog-title {
+  font-size: 1.5em;
+  line-height: 1em;
+  color: #000;
+}
+.oo-ui-messageDialog-message {
+  font-size: 0.9em;
+  line-height: 1.25em;
+  color: #666;
+}
+.oo-ui-messageDialog-message-verbose {
+  font-size: 1.1em;
+  line-height: 1.5em;
+  text-align: right;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+  border-left: solid 1px #e5e5e5;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget:last-child {
+  border-left-width: 0;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+  border-bottom: solid 1px #e5e5e5;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget:last-child {
+  border-bottom-width: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-labelElement-label {
+  text-align: center;
+  line-height: 3.4em;
+  padding: 0 2em;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:hover {
+  background-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:active {
+  background-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-primary:hover {
+  background-color: rgba(8, 126, 204, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-primary:active {
+  background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-labelElement-label {
+  font-weight: bold;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover {
+  background-color: rgba(118, 171, 54, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active {
+  background-color: rgba(118, 171, 54, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover {
+  background-color: rgba(212, 83, 83, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active {
+  background-color: rgba(212, 83, 83, 0.1);
+}
+.oo-ui-processDialog-location {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.oo-ui-processDialog-title {
+  display: inline;
+  padding: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget {
+  white-space: nowrap;
+}
+.oo-ui-processDialog-actions-safe,
+.oo-ui-processDialog-actions-primary {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+}
+.oo-ui-processDialog-actions-safe {
+  right: 0;
+}
+.oo-ui-processDialog-actions-primary {
+  left: 0;
+}
+.oo-ui-processDialog-errors {
+  display: none;
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+  z-index: 2;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.oo-ui-processDialog-content .oo-ui-window-head {
+  height: 3.4em;
+}
+.oo-ui-processDialog-content .oo-ui-window-body {
+  top: 3.4em;
+  box-shadow: 0 0 0.33em rgba(0, 0, 0, 0.33);
+}
+.oo-ui-processDialog-navigation {
+  position: relative;
+  height: 3.4em;
+  padding: 0 1em;
+}
+.oo-ui-processDialog-location {
+  padding: 0.75em 0;
+  height: 1.9em;
+  cursor: default;
+  text-align: center;
+}
+.oo-ui-processDialog-title {
+  font-weight: bold;
+  line-height: 1.9em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-buttonElement-button {
+  padding-top: 0.75em;
+  padding-bottom: 0.75em;
+  min-width: 1.9em;
+  min-height: 1.9em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-labelElement-label {
+  line-height: 1.9em;
+  padding: 0 1em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-iconElement-icon,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-iconElement-icon,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-iconElement-icon {
+  position: absolute;
+  margin-top: -0.125em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-framed {
+  margin: 0.75em 0.75em 0.75em 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+  padding: 0;
+  vertical-align: middle;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget:hover {
+  background-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget:active {
+  background-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed {
+  margin: 0.75em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+  /* Adjust for border so text aligns with title */
+  margin: -1px;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-primary:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-primary:hover {
+  background-color: rgba(8, 126, 204, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-primary:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-primary:active {
+  background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-labelElement-label {
+  font-weight: bold;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover {
+  background-color: rgba(118, 171, 54, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active {
+  background-color: rgba(118, 171, 54, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover {
+  background-color: rgba(212, 83, 83, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active {
+  background-color: rgba(212, 83, 83, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+  right: 0.5em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-labelElement-label {
+  padding-right: 2.25em;
+}
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+  left: 0.5em;
+}
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-labelElement-label {
+  padding-left: 2.25em;
+}
+.oo-ui-processDialog > .oo-ui-window-frame {
+  min-height: 5em;
+}
+.oo-ui-processDialog-errors {
+  background-color: rgba(255, 255, 255, 0.9);
+  padding: 3em 3em 1.5em 3em;
+  text-align: center;
+}
+.oo-ui-processDialog-errors .oo-ui-buttonWidget {
+  margin: 2em 1em 2em 1em;
+}
+.oo-ui-processDialog-errors-title {
+  font-size: 1.5em;
+  color: #000;
+  margin-bottom: 2em;
+}
+.oo-ui-processDialog-error {
+  text-align: right;
+  margin: 1em;
+  padding: 1em;
+  border: solid 1px #ff9e9e;
+  background-color: #fff7f7;
+  border-radius: 0.25em;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+  position: fixed;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup {
+  width: auto;
+  height: auto;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0;
+  padding: 1em;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup > .oo-ui-window-frame {
+  position: fixed;
+  left: 0;
+  right: 0;
+  margin: auto;
+  overflow: hidden;
+  max-width: 100%;
+  max-height: 100%;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup > .oo-ui-window-frame > iframe {
+  width: 100%;
+  height: 100%;
+}
+.oo-ui-windowManager-fullscreen > .oo-ui-dialog > .oo-ui-window-frame {
+  width: 100%;
+  height: 100%;
+  top: 0;
+  bottom: 0;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+  background-color: rgba(255, 255, 255, 0.5);
+  opacity: 0;
+  -webkit-transition: opacity 250ms ease-in-out;
+  -moz-transition: opacity 250ms ease-in-out;
+  -ms-transition: opacity 250ms ease-in-out;
+  -o-transition: opacity 250ms ease-in-out;
+  transition: opacity 250ms ease-in-out;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog > .oo-ui-window-frame {
+  top: 1em;
+  bottom: 1em;
+  background-color: #fff;
+  -webkit-transform: scale(0.5);
+  -moz-transform: scale(0.5);
+  -ms-transform: scale(0.5);
+  -o-transform: scale(0.5);
+  transform: scale(0.5);
+  -webkit-transition: all 250ms ease-in-out;
+  -moz-transition: all 250ms ease-in-out;
+  -ms-transition: all 250ms ease-in-out;
+  -o-transition: all 250ms ease-in-out;
+  transition: all 250ms ease-in-out;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-ready {
+  opacity: 1;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-ready > .oo-ui-window-frame {
+  -webkit-transform: scale(1);
+  -moz-transform: scale(1);
+  -ms-transform: scale(1);
+  -o-transform: scale(1);
+  transform: scale(1);
+}
+.oo-ui-windowManager-modal.oo-ui-windowManager-floating > .oo-ui-dialog > .oo-ui-window-frame {
+  border: solid 1px #ccc;
+  border-radius: 0.5em;
+  box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
+}
diff --git a/resources/lib/oojs-ui/oojs-ui-minerva.css b/resources/lib/oojs-ui/oojs-ui-minerva.css
new file mode 100644 (file)
index 0000000..e817142
--- /dev/null
@@ -0,0 +1,1397 @@
+/*!
+ * OOjs UI v0.1.0-pre (49b64bdba7)
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2014 OOjs Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2014-09-15T22:18:37Z
+ */
+/*
+ * Blank theme mixins.
+ *
+ * Base styles invoke these mixins at the end of their definitions. Override these mixins to add
+ * additional rules to the base styles.
+ */
+/*
+ * Base styles.
+ *
+ * Themes should include this file after defining their variables and mixins.
+ */
+/* @noflip */
+.oo-ui-rtl {
+  direction: rtl;
+}
+/* @noflip */
+.oo-ui-ltr {
+  direction: ltr;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button {
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: middle;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  display: none;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+  display: none;
+}
+.oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+  cursor: default;
+}
+.oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-buttonElement-frameless {
+  display: inline-block;
+  position: relative;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
+  display: inline-block;
+  vertical-align: top;
+  text-align: center;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+  cursor: default;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  margin-left: 0;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+  margin-right: -0.75em;
+}
+.oo-ui-buttonElement.oo-ui-indicatorElement .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement.oo-ui-iconElement .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  width: 3.35em;
+  height: 3.35em;
+  background-size: 2em auto;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  margin-left: 0.25em;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  line-height: 1.9em;
+}
+.oo-ui-clippableElement-clippable {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-bookletLayout-stackLayout.oo-ui-stackLayout-continuous .oo-ui-panelLayout-scrollable {
+  overflow-y: hidden;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
+  width: 100%;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-scrollable {
+  overflow-y: auto;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-padded {
+  padding: 2em;
+}
+.oo-ui-bookletLayout-outlinePanel-editable .oo-ui-outlineWidget {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 3em;
+  overflow-y: auto;
+}
+.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
+  padding: 0 0 1em;
+}
+.oo-ui-fieldLayout {
+  margin-bottom: 1em;
+}
+.oo-ui-fieldLayout:before,
+.oo-ui-fieldLayout:after {
+  content: " ";
+  display: table;
+}
+.oo-ui-fieldLayout:after {
+  clear: both;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labelElement-label {
+  display: block;
+  float: left;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field {
+  display: block;
+  float: left;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labelElement-label {
+  text-align: right;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labelElement-label {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labelElement-label {
+  display: inline-block;
+}
+.oo-ui-fieldLayout > .oo-ui-popupButtonWidget > .oo-ui-popupWidget > .oo-ui-popupWidget-popup {
+  z-index: 1;
+}
+.oo-ui-fieldLayout .oo-ui-fieldLayout-help {
+  float: right;
+}
+.oo-ui-fieldLayout .oo-ui-fieldLayout-help-content {
+  padding: 0.5em 0.75em;
+}
+.oo-ui-fieldLayout:last-child {
+  margin-bottom: 0;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labelElement-label {
+  padding-top: 0.5em;
+  margin-right: 5%;
+  width: 35%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field {
+  width: 60%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labelElement-label {
+  padding: 0.75em 0.5em 0.5em 0.5em;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field {
+  padding: 0.5em 0;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labelElement-label {
+  padding: 0.5em 0;
+}
+.oo-ui-fieldLayout > .oo-ui-popupButtonWidget > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  margin-top: 0.25em;
+}
+.oo-ui-fieldLayout-disabled .oo-ui-labelElement-label {
+  color: #ccc;
+}
+.oo-ui-fieldsetLayout {
+  position: relative;
+  margin: 0;
+  padding: 0;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-iconElement-icon {
+  display: block;
+  position: absolute;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-fieldsetLayout.oo-ui-labelElement > .oo-ui-labelElement-label {
+  display: inline-block;
+}
+.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout {
+  margin-top: 2em;
+}
+.oo-ui-fieldsetLayout > .oo-ui-labelElement-label {
+  margin-bottom: 0.5em;
+  padding: 0.25em 0;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-labelElement-label {
+  padding-left: 1.75em;
+  line-height: 1.33em;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-iconElement-icon {
+  left: 0;
+  top: 0.25em;
+  width: 2em;
+  height: 2em;
+}
+.oo-ui-gridLayout {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+}
+.oo-ui-panelLayout {
+  position: relative;
+  padding: 1em 3.35em;
+}
+.oo-ui-panelLayout-scrollable {
+  overflow-y: auto;
+}
+.oo-ui-panelLayout-expanded {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+}
+.oo-ui-stackLayout > .oo-ui-panelLayout {
+  display: none;
+}
+.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
+  display: block;
+  position: relative;
+}
+.oo-ui-popupTool .oo-ui-popupWidget-popup,
+.oo-ui-popupTool .oo-ui-popupWidget-anchor {
+  z-index: 4;
+}
+.oo-ui-popupTool .oo-ui-popupWidget {
+  margin-left: 1.25em;
+  font-size: 0.8em;
+}
+.oo-ui-toolGroup {
+  display: inline-block;
+  vertical-align: middle;
+  margin: 0.3em;
+}
+.oo-ui-toolGroup-empty {
+  display: none;
+}
+.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-barToolGroup > .oo-ui-iconElement-icon,
+.oo-ui-barToolGroup > .oo-ui-labelElement-label {
+  display: none;
+}
+.oo-ui-barToolGroup .oo-ui-tool {
+  display: inline-block;
+  position: relative;
+  vertical-align: top;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link {
+  display: block;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  display: block;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  display: none;
+}
+.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+.oo-ui-barToolGroup .oo-ui-tool-title,
+.oo-ui-barToolGroup .oo-ui-tool-accel {
+  display: none;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-link {
+  cursor: pointer;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link {
+  height: 1.5em;
+  padding: 0.25em;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  height: 1.5em;
+  width: 1.5em;
+}
+.oo-ui-popupToolGroup {
+  position: relative;
+  height: 2em;
+  min-width: 2.5em;
+}
+.oo-ui-popupToolGroup-handle {
+  display: block;
+  cursor: pointer;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+  position: absolute;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-disabled .oo-ui-popupToolGroup-handle {
+  cursor: default;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+  display: none;
+  position: absolute;
+  z-index: 4;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools .oo-ui-iconElement-icon {
+  background-repeat: no-repeat;
+  background-position: center center;
+}
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled > .oo-ui-toolGroup-tools {
+  display: block;
+}
+.oo-ui-popupToolGroup-left > .oo-ui-toolGroup-tools {
+  left: 0;
+}
+.oo-ui-popupToolGroup-right > .oo-ui-toolGroup-tools {
+  right: 0;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-accel {
+  display: none;
+}
+.oo-ui-popupToolGroup.oo-ui-indicatorElement.oo-ui-iconElement {
+  min-width: 3.5em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+  top: 0;
+  width: 2em;
+  height: 2em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator {
+  right: 0;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+  left: 0.25em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+  line-height: 2.6em;
+  font-size: 0.8em;
+  margin: 0 1em;
+}
+.oo-ui-popupToolGroup-header {
+  line-height: 2.6em;
+  font-size: 0.8em;
+  margin: 0 0.6em;
+  font-weight: bold;
+}
+.oo-ui-popupToolGroup.oo-ui-iconElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+  margin-left: 3em;
+}
+.oo-ui-popupToolGroup.oo-ui-indicatorElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+  margin-right: 2.25em;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+  top: 2.3em;
+  margin: 0 -1px;
+  border: solid 1px #dddddd;
+  background-color: white;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  height: 2em;
+  width: 2em;
+  margin-right: 0.25em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  line-height: 2em;
+  font-size: 0.8em;
+}
+.oo-ui-listToolGroup .oo-ui-tool {
+  display: inline-block;
+  width: 100%;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-listToolGroup .oo-ui-tool-link {
+  display: block;
+  cursor: pointer;
+  white-space: nowrap;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+.oo-ui-listToolGroup .oo-ui-toolGroup-tools {
+  padding: 0.25em;
+}
+.oo-ui-listToolGroup .oo-ui-tool-link {
+  padding-right: 0.5em;
+}
+.oo-ui-menuToolGroup .oo-ui-tool {
+  display: block;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link {
+  display: block;
+  cursor: pointer;
+  white-space: nowrap;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  background-image: none;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconElement-icon {
+  background-image: /* @embed */ url(images/icons/check.svg);
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+  min-width: 8em;
+}
+.oo-ui-menuToolGroup .oo-ui-toolGroup-tools {
+  padding: 0.25em 0 0.25em 0;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link {
+  padding: 0 1em 0 0.25em;
+}
+.oo-ui-toolbar {
+  clear: both;
+}
+.oo-ui-toolbar-bar {
+  line-height: 1em;
+}
+.oo-ui-toolbar-actions {
+  float: right;
+}
+.oo-ui-toolbar-tools {
+  display: inline;
+}
+.oo-ui-toolbar-tools,
+.oo-ui-toolbar-actions,
+.oo-ui-toolbar-shadow {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-toolbar-actions .oo-ui-popupWidget {
+  -webkit-touch-callout: default;
+  -webkit-user-select: all;
+  -moz-user-select: all;
+  -ms-user-select: all;
+  user-select: all;
+}
+.oo-ui-toolbar-shadow {
+  background-position: left top;
+  background-repeat: repeat-x;
+  position: absolute;
+  width: 100%;
+  pointer-events: none;
+}
+.oo-ui-toolbar-bar {
+  border-bottom: solid 1px #dddddd;
+  background: white;
+}
+.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
+  border: none;
+  background: none;
+}
+.oo-ui-selectWidget {
+  margin: 0;
+  padding: 0;
+}
+.oo-ui-optionWidget {
+  position: relative;
+  display: block;
+  cursor: pointer;
+  padding: 0.8em 1em 0.8em 3.35em;
+  border: none;
+  font-weight: bold;
+}
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+  cursor: default;
+}
+.oo-ui-optionWidget .oo-ui-labelElement-label {
+  display: block;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
+}
+.oo-ui-optionWidget .oo-ui-labelElement-label {
+  line-height: 1.5em;
+}
+.oo-ui-optionWidget.oo-ui-indicatorElement .oo-ui-labelElement-label {
+  padding-right: 1.5em;
+}
+.oo-ui-optionWidget-level-0 {
+  padding-left: 3.5em;
+}
+.oo-ui-optionWidget-level-0 .oo-ui-iconElement-icon {
+  left: 1em;
+}
+.oo-ui-optionWidget-level-1 {
+  padding-left: 5em;
+}
+.oo-ui-optionWidget-level-1 .oo-ui-iconElement-icon {
+  left: 2.5em;
+}
+.oo-ui-optionWidget-level-2 {
+  padding-left: 6.5em;
+}
+.oo-ui-optionWidget-level-2 .oo-ui-iconElement-icon {
+  left: 4em;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+  position: absolute;
+  background-repeat: no-repeat;
+  background-position: center center;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+  top: 50%;
+  width: 2em;
+  height: 2em;
+  margin-top: -1em;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon {
+  left: 0.5em;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+  right: 0.5em;
+}
+.oo-ui-buttonSelectWidget {
+  display: inline-block;
+  white-space: nowrap;
+}
+.oo-ui-buttonOptionWidget {
+  display: inline-block;
+  padding: 0;
+  background-color: transparent;
+}
+.oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+  position: relative;
+}
+.oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  position: static;
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+  height: 1.9em;
+}
+.oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  height: 1.9em;
+  margin-top: 0;
+}
+.oo-ui-labelWidget {
+  display: inline-block;
+  padding: 0.5em 0;
+}
+.oo-ui-iconWidget {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+  line-height: 2.5em;
+  height: 1.9em;
+  width: 1.9em;
+  opacity: 0.8;
+}
+.oo-ui-iconWidget.oo-ui-widget-disabled {
+  opacity: 0.2;
+}
+.oo-ui-indicatorWidget {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+  line-height: 2.5em;
+  height: 1.9em;
+  width: 1.9em;
+  opacity: 0.8;
+}
+.oo-ui-indicatorWidget.oo-ui-widget-disabled {
+  opacity: 0.2;
+}
+.oo-ui-buttonWidget {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-buttonGroupWidget {
+  border-radius: 0.3em;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+  border-radius: 0;
+  margin-bottom: -1px;
+  margin-left: -1px;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:first-child .oo-ui-buttonElement-button {
+  border-bottom-left-radius: 0.3em;
+  border-top-left-radius: 0.3em;
+  margin-left: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:last-child .oo-ui-buttonElement-button {
+  border-bottom-right-radius: 0.3em;
+  border-top-right-radius: 0.3em;
+}
+.oo-ui-toggleSwitchWidget {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+  overflow: hidden;
+  cursor: pointer;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+  -webkit-transform: translateZ(0px);
+  -moz-transform: translateZ(0px);
+  -ms-transform: translateZ(0px);
+  -o-transform: translateZ(0px);
+  transform: translateZ(0px);
+  height: 2em;
+  width: 4em;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+  cursor: default;
+}
+.oo-ui-toggleSwitchWidget-grip {
+  position: absolute;
+  display: block;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  right: 0;
+  left: 0;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+  display: none;
+}
+.oo-ui-toggleSwitchWidget-grip {
+  top: 0.25em;
+  left: 0.25em;
+  width: 1.5em;
+  height: 1.5em;
+  margin-top: -1px;
+  -webkit-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+  -moz-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+  -ms-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+  -o-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+  transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+}
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+  -webkit-transition: opacity 200ms ease-in-out;
+  -moz-transition: opacity 200ms ease-in-out;
+  -ms-transition: opacity 200ms ease-in-out;
+  -o-transition: opacity 200ms ease-in-out;
+  transition: opacity 200ms ease-in-out;
+}
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+  left: 2.25em;
+  margin-left: -2px;
+}
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
+  left: 0.25em;
+  margin-left: 0;
+}
+.oo-ui-actionWidget.oo-ui-pendingElement-pending {
+  background-image: /* @embed */ url(images/textures/pending.gif);
+}
+.oo-ui-popupWidget-popup {
+  position: absolute;
+  overflow: hidden;
+  z-index: 1;
+}
+.oo-ui-popupWidget-anchor {
+  display: none;
+  z-index: 1;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor {
+  display: block;
+  position: absolute;
+  background-repeat: no-repeat;
+}
+.oo-ui-popupWidget-head {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-popupWidget-head .oo-ui-buttonWidget {
+  float: right;
+}
+.oo-ui-popupWidget-head .oo-ui-labelElement-label {
+  float: left;
+  cursor: default;
+}
+.oo-ui-popupWidget-body {
+  clear: both;
+  overflow: hidden;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-popup {
+  margin-top: 7px;
+}
+.oo-ui-popupWidget-head {
+  height: 2.5em;
+}
+.oo-ui-popupWidget-head .oo-ui-buttonWidget {
+  margin: 0.25em;
+}
+.oo-ui-popupWidget-head .oo-ui-labelElement-label {
+  margin: 0.75em 1em;
+}
+.oo-ui-popupWidget-body-padded {
+  padding: 0 1em;
+}
+.oo-ui-popupButtonWidget {
+  position: relative;
+}
+.oo-ui-popupButtonWidget .oo-ui-popupWidget {
+  position: absolute;
+  left: 1em;
+  cursor: auto;
+}
+.oo-ui-lookupInputWidget-menu {
+  background-color: #fff;
+}
+.oo-ui-textInputWidget {
+  position: relative;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+  display: inline-block;
+  width: 100%;
+  resize: none;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-textInputWidget.oo-ui-pendingElement-pending input,
+.oo-ui-textInputWidget.oo-ui-pendingElement-pending textarea {
+  background-image: /* @embed */ url(images/textures/pending.gif);
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator {
+  position: absolute;
+  top: 0;
+  height: 100%;
+  background-repeat: no-repeat;
+  cursor: pointer;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon {
+  left: 0;
+}
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator {
+  right: 0;
+}
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+  padding: .8em 1em;
+}
+.oo-ui-menuWidget {
+  position: absolute;
+  background: white;
+  border: solid 1px #dddddd;
+}
+.oo-ui-menuWidget input {
+  position: absolute;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+  opacity: 0;
+}
+.oo-ui-menuItemWidget {
+  position: relative;
+}
+.oo-ui-menuItemWidget .oo-ui-iconElement-icon {
+  display: none;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+  background-color: transparent;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected .oo-ui-iconElement-icon {
+  display: block;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+  background: #347bff;
+  color: #ffffff;
+}
+.oo-ui-menuItemWidget .oo-ui-iconElement-icon {
+  background-size: 24px auto;
+}
+.oo-ui-menuSectionItemWidget {
+  cursor: default;
+  font-weight: normal;
+  color: #777777;
+  border: none;
+}
+.oo-ui-inlineMenuWidget {
+  position: relative;
+  display: inline-block;
+  margin: 0.25em 0;
+  min-width: 20em;
+}
+.oo-ui-inlineMenuWidget-handle {
+  width: 100%;
+  display: inline-block;
+  cursor: pointer;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon {
+  position: absolute;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-inlineMenuWidget .oo-ui-menuWidget {
+  z-index: 1;
+  width: 100%;
+}
+.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle {
+  cursor: default;
+}
+.oo-ui-inlineMenuWidget-handle {
+  height: 2.5em;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon {
+  top: 0;
+  width: 2.5em;
+  height: 2.5em;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator {
+  right: 0;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon {
+  left: 0.25em;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label {
+  line-height: 2.5em;
+  margin: 0 0.5em;
+}
+.oo-ui-inlineMenuWidget.oo-ui-iconElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label {
+  margin-left: 3em;
+}
+.oo-ui-inlineMenuWidget.oo-ui-indicatorElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label {
+  margin-right: 2em;
+}
+.oo-ui-outlineItemWidget {
+  position: relative;
+  cursor: pointer;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  padding: 0.75em;
+}
+.oo-ui-outlineControlsWidget {
+  height: 3em;
+}
+.oo-ui-outlineControlsWidget-items,
+.oo-ui-outlineControlsWidget-movers {
+  float: left;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+  float: left;
+  background-position: right center;
+  background-repeat: no-repeat;
+}
+.oo-ui-outlineControlsWidget-items {
+  float: left;
+}
+.oo-ui-outlineControlsWidget-items .oo-ui-buttonWidget {
+  float: left;
+}
+.oo-ui-outlineControlsWidget-movers {
+  float: right;
+}
+.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
+  float: right;
+}
+.oo-ui-outlineControlsWidget-items,
+.oo-ui-outlineControlsWidget-movers {
+  height: 2em;
+  margin: 0.5em;
+  padding: 0;
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+  width: 1.5em;
+  height: 2em;
+  margin: 0.5em 0 0.5em 0.5em;
+}
+.oo-ui-outlineControlsWidget-items {
+  margin-left: 0;
+}
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget {
+  z-index: 1;
+}
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget > .oo-ui-selectWidget {
+  min-width: 20em;
+}
+.oo-ui-searchWidget-query {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+  width: 100%;
+}
+.oo-ui-searchWidget-results {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.oo-ui-searchWidget-query {
+  height: 4em;
+  padding: 0 1em;
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+  margin: 0.75em 0;
+}
+.oo-ui-searchWidget-results {
+  top: 4em;
+  padding: 1em;
+  line-height: 0;
+}
+.oo-ui-window {
+  line-height: 1em;
+  /* Content div takes focus when opened, so hide outline */
+}
+.oo-ui-window-frame {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-window-frame > iframe {
+  width: 100%;
+  height: 100%;
+  margin: 0;
+  padding: 0;
+}
+.oo-ui-window-content:focus {
+  outline: none;
+}
+.oo-ui-window-head,
+.oo-ui-window-foot {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-window-body {
+  margin: 0;
+  padding: 0;
+  background: none;
+}
+.oo-ui-window-overlay {
+  position: absolute;
+  top: 0;
+  left: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-head,
+.oo-ui-dialog-content > .oo-ui-window-body,
+.oo-ui-dialog-content > .oo-ui-window-foot {
+  position: absolute;
+  left: 0;
+  right: 0;
+  overflow: hidden;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-dialog-content > .oo-ui-window-head {
+  z-index: 1;
+  top: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-head.oo-ui-pendingElement-pending {
+  background-image: /* @embed */ url(images/textures/pending.gif);
+}
+.oo-ui-dialog-content > .oo-ui-window-body {
+  z-index: 2;
+  top: 0;
+  bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-foot {
+  z-index: 1;
+  bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-overlay {
+  z-index: 3;
+}
+.oo-ui-messageDialog-actions-horizontal {
+  display: table;
+  table-layout: fixed;
+  width: 100%;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+  display: table-cell;
+  width: 1%;
+}
+.oo-ui-messageDialog-actions-vertical {
+  display: block;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+  display: block;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget {
+  position: relative;
+  text-align: center;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-buttonElement-button {
+  display: block;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-labelElement-label {
+  position: relative;
+  top: auto;
+  bottom: auto;
+  display: inline;
+  white-space: nowrap;
+}
+.oo-ui-messageDialog-title,
+.oo-ui-messageDialog-message {
+  display: block;
+  text-align: center;
+  padding-top: 0.5em;
+}
+.oo-ui-messageDialog-title {
+  font-size: 1.5em;
+  line-height: 1em;
+  color: #000;
+}
+.oo-ui-messageDialog-message {
+  font-size: 0.9em;
+  line-height: 1.25em;
+  color: #666;
+}
+.oo-ui-messageDialog-message-verbose {
+  font-size: 1.1em;
+  line-height: 1.5em;
+  text-align: left;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+  border-right: solid 1px #e5e5e5;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget:last-child {
+  border-right-width: 0;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+  border-bottom: solid 1px #e5e5e5;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget:last-child {
+  border-bottom-width: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-labelElement-label {
+  text-align: center;
+  line-height: 3.4em;
+  padding: 0 2em;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:hover {
+  background-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:active {
+  background-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-primary:hover {
+  background-color: rgba(8, 126, 204, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-primary:active {
+  background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-labelElement-label {
+  font-weight: bold;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover {
+  background-color: rgba(118, 171, 54, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active {
+  background-color: rgba(118, 171, 54, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover {
+  background-color: rgba(212, 83, 83, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active {
+  background-color: rgba(212, 83, 83, 0.1);
+}
+.oo-ui-processDialog-location {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.oo-ui-processDialog-title {
+  display: inline;
+  padding: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget {
+  white-space: nowrap;
+}
+.oo-ui-processDialog-actions-safe,
+.oo-ui-processDialog-actions-primary {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+}
+.oo-ui-processDialog-actions-safe {
+  left: 0;
+}
+.oo-ui-processDialog-actions-primary {
+  right: 0;
+}
+.oo-ui-processDialog-errors {
+  display: none;
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 2;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.oo-ui-processDialog-content .oo-ui-window-head {
+  height: 3.35em;
+  border-bottom: 1px solid #dddddd;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-processDialog-content .oo-ui-window-body {
+  top: 3.35em;
+  padding: 2em 0;
+}
+.oo-ui-processDialog-navigation {
+  position: relative;
+  height: 3.35em;
+  padding: 0 1em;
+}
+.oo-ui-processDialog-location {
+  padding: 0.75em 0;
+  height: 1.85em;
+  cursor: default;
+  text-align: center;
+}
+.oo-ui-processDialog-title {
+  font-weight: bold;
+  line-height: 1.85em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-buttonElement-button {
+  padding: 0.35em 0.75em;
+  min-width: 1.85em;
+  min-height: 1.85em;
+  border: 1px solid #dddddd;
+  border-radius: 4px;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-labelElement-label {
+  line-height: 1.85em;
+  padding: 0 1em;
+  font-weight: bold;
+  color: #777777;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-iconElement-icon,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-iconElement-icon,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-iconElement-icon {
+  position: absolute;
+  margin-top: -0.125em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+  vertical-align: middle;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-destructive .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-destructive .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-flaggedElement-destructive .oo-ui-buttonElement-button {
+  border: 1px solid transparent;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-destructive .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-destructive .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-flaggedElement-destructive .oo-ui-labelElement-label {
+  color: #d11d13;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-buttonElement-button {
+  padding: 0.75em 0.35em;
+  border: none;
+  border-radius: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-buttonElement-button {
+  background-color: #347bff;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-labelElement-label {
+  color: #ffffff;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+  left: 0.5em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-labelElement-label {
+  padding-left: 2.25em;
+}
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+  right: 0.5em;
+}
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-labelElement-label {
+  padding-right: 2.25em;
+}
+.oo-ui-processDialog-actions-other {
+  position: absolute;
+  bottom: 1em;
+}
+.oo-ui-processDialog > .oo-ui-window-frame {
+  min-height: 5em;
+}
+.oo-ui-processDialog-errors {
+  background-color: rgba(255, 255, 255, 0.9);
+  padding: 3em 3em 1.5em 3em;
+  text-align: center;
+}
+.oo-ui-processDialog-errors .oo-ui-buttonWidget {
+  margin: 2em 1em 2em 1em;
+}
+.oo-ui-processDialog-errors-title {
+  font-size: 1.5em;
+  color: #000;
+  margin-bottom: 2em;
+}
+.oo-ui-processDialog-error {
+  text-align: left;
+  margin: 1em;
+  padding: 1em;
+  border: solid 1px #ff9e9e;
+  background-color: #fff7f7;
+  border-radius: 0.25em;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+  position: fixed;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup {
+  width: auto;
+  height: auto;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 1em;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup > .oo-ui-window-frame {
+  position: absolute;
+  right: 0;
+  left: 0;
+  margin: auto;
+  overflow: hidden;
+  max-width: 100%;
+  max-height: 100%;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup > .oo-ui-window-frame > iframe {
+  width: 100%;
+  height: 100%;
+}
+.oo-ui-windowManager-fullscreen > .oo-ui-dialog > .oo-ui-window-frame {
+  width: 100%;
+  height: 100%;
+  top: 0;
+  bottom: 0;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+  background-color: rgba(255, 255, 255, 0.5);
+  opacity: 0;
+  -webkit-transition: opacity 250ms ease-in-out;
+  -moz-transition: opacity 250ms ease-in-out;
+  -ms-transition: opacity 250ms ease-in-out;
+  -o-transition: opacity 250ms ease-in-out;
+  transition: opacity 250ms ease-in-out;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog > .oo-ui-window-frame {
+  top: 0;
+  bottom: 0;
+  background-color: #fff;
+  -webkit-transform: translate3d(0, -200%, 0);
+  -moz-transform: translate3d(0, -200%, 0);
+  -ms-transform: translate3d(0, -200%, 0);
+  -o-transform: translate3d(0, -200%, 0);
+  transform: translate3d(0, -200%, 0);
+  -webkit-transition: transform 250ms ease-in-out;
+  -moz-transition: transform 250ms ease-in-out;
+  -ms-transition: transform 250ms ease-in-out;
+  -o-transition: transform 250ms ease-in-out;
+  transition: transform 250ms ease-in-out;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-ready {
+  opacity: 1;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-ready > .oo-ui-window-frame {
+  -webkit-transform: translate3d(0, 0, 0);
+  -moz-transform: translate3d(0, 0, 0);
+  -ms-transform: translate3d(0, 0, 0);
+  -o-transform: translate3d(0, 0, 0);
+  transform: translate3d(0, 0, 0);
+}
+.oo-ui-windowManager-modal.oo-ui-windowManager-floating > .oo-ui-dialog > .oo-ui-window-frame {
+  border: solid 1px #ccc;
+  border-radius: 0.5em;
+  box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
+}
+
+/*
+ * Blank theme mixins.
+ *
+ * Base styles invoke these mixins at the end of their definitions. Override these mixins to add
+ * additional rules to the base styles.
+ */
+.oo-ui-icon-check {
+  background-image: /* @embed */ url(themes/minerva/images/icons/check.png);
+  background: #347bff;
+}
diff --git a/resources/lib/oojs-ui/oojs-ui-minerva.rtl.css b/resources/lib/oojs-ui/oojs-ui-minerva.rtl.css
new file mode 100644 (file)
index 0000000..e452952
--- /dev/null
@@ -0,0 +1,1381 @@
+/*!
+ * OOjs UI v0.1.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2014 OOjs Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2014-09-11T19:39:50Z
+ */
+/*
+ * Blank theme mixins.
+ *
+ * Base styles invoke these mixins at the end of their definitions. Override these mixins to add
+ * additional rules to the base styles.
+ */
+/*
+ * Base styles.
+ *
+ * Themes should include this file after defining their variables and mixins.
+ */
+/* @noflip */
+.oo-ui-rtl {
+  direction: rtl;
+}
+/* @noflip */
+.oo-ui-ltr {
+  direction: ltr;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button {
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: middle;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  display: none;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+  display: none;
+}
+.oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+  cursor: default;
+}
+.oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-buttonElement-frameless {
+  display: inline-block;
+  position: relative;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
+  display: inline-block;
+  vertical-align: top;
+  text-align: center;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+  cursor: default;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  margin-right: 0;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+  margin-left: -0.75em;
+}
+.oo-ui-buttonElement.oo-ui-indicatorElement .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement.oo-ui-iconElement .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  width: 3.35em;
+  height: 3.35em;
+  background-size: 2em auto;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  margin-right: 0.25em;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+  line-height: 1.9em;
+}
+.oo-ui-clippableElement-clippable {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-bookletLayout-stackLayout.oo-ui-stackLayout-continuous .oo-ui-panelLayout-scrollable {
+  overflow-y: hidden;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
+  width: 100%;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-scrollable {
+  overflow-y: auto;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-padded {
+  padding: 2em;
+}
+.oo-ui-bookletLayout-outlinePanel-editable .oo-ui-outlineWidget {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 3em;
+  overflow-y: auto;
+}
+.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  left: 0;
+}
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
+  padding: 0 0 1em;
+}
+.oo-ui-fieldLayout {
+  margin-bottom: 1em;
+}
+.oo-ui-fieldLayout:before,
+.oo-ui-fieldLayout:after {
+  content: " ";
+  display: table;
+}
+.oo-ui-fieldLayout:after {
+  clear: both;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labelElement-label {
+  display: block;
+  float: right;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field {
+  display: block;
+  float: right;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labelElement-label {
+  text-align: left;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labelElement-label {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labelElement-label {
+  display: inline-block;
+}
+.oo-ui-fieldLayout > .oo-ui-popupButtonWidget > .oo-ui-popupWidget > .oo-ui-popupWidget-popup {
+  z-index: 1;
+}
+.oo-ui-fieldLayout:last-child {
+  margin-bottom: 0;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labelElement-label {
+  padding-top: 0.5em;
+  margin-left: 5%;
+  width: 35%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field {
+  width: 60%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labelElement-label {
+  padding: 0.75em 0.5em 0.5em 0.5em;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field {
+  padding: 0.5em 0;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labelElement-label {
+  padding: 0.5em 0;
+}
+.oo-ui-fieldLayout > .oo-ui-popupButtonWidget > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+  margin-top: 0.25em;
+}
+.oo-ui-fieldLayout-disabled .oo-ui-labelElement-label {
+  color: #ccc;
+}
+.oo-ui-fieldsetLayout {
+  position: relative;
+  margin: 0;
+  padding: 0;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-iconElement-icon {
+  display: block;
+  position: absolute;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-fieldsetLayout.oo-ui-labelElement > .oo-ui-labelElement-label {
+  display: inline-block;
+}
+.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout {
+  margin-top: 2em;
+}
+.oo-ui-fieldsetLayout > .oo-ui-labelElement-label {
+  margin-bottom: 0.5em;
+  padding: 0.25em 0;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-labelElement-label {
+  padding-right: 1.75em;
+  line-height: 1.33em;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-iconElement-icon {
+  right: 0;
+  top: 0.25em;
+  width: 2em;
+  height: 2em;
+}
+.oo-ui-gridLayout {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+}
+.oo-ui-panelLayout {
+  position: relative;
+  padding: 1em 3.35em;
+}
+.oo-ui-panelLayout-scrollable {
+  overflow-y: auto;
+}
+.oo-ui-panelLayout-expanded {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+}
+.oo-ui-stackLayout > .oo-ui-panelLayout {
+  display: none;
+}
+.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
+  display: block;
+  position: relative;
+}
+.oo-ui-popupTool .oo-ui-popupWidget-popup,
+.oo-ui-popupTool .oo-ui-popupWidget-anchor {
+  z-index: 4;
+}
+.oo-ui-popupTool .oo-ui-popupWidget {
+  margin-right: 1.25em;
+  font-size: 0.8em;
+}
+.oo-ui-toolGroup {
+  display: inline-block;
+  vertical-align: middle;
+  margin: 0.3em;
+}
+.oo-ui-toolGroup-empty {
+  display: none;
+}
+.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-barToolGroup > .oo-ui-iconElement-icon,
+.oo-ui-barToolGroup > .oo-ui-labelElement-label {
+  display: none;
+}
+.oo-ui-barToolGroup .oo-ui-tool {
+  display: inline-block;
+  position: relative;
+  vertical-align: top;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link {
+  display: block;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  display: block;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  display: none;
+}
+.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+.oo-ui-barToolGroup .oo-ui-tool-title,
+.oo-ui-barToolGroup .oo-ui-tool-accel {
+  display: none;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-link {
+  cursor: pointer;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link {
+  height: 1.5em;
+  padding: 0.25em;
+}
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  height: 1.5em;
+  width: 1.5em;
+}
+.oo-ui-popupToolGroup {
+  position: relative;
+  height: 2em;
+  min-width: 2.5em;
+}
+.oo-ui-popupToolGroup-handle {
+  display: block;
+  cursor: pointer;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+  position: absolute;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-disabled .oo-ui-popupToolGroup-handle {
+  cursor: default;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+  display: none;
+  position: absolute;
+  z-index: 4;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools .oo-ui-iconElement-icon {
+  background-repeat: no-repeat;
+  background-position: center center;
+}
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled > .oo-ui-toolGroup-tools {
+  display: block;
+}
+.oo-ui-popupToolGroup-left > .oo-ui-toolGroup-tools {
+  right: 0;
+}
+.oo-ui-popupToolGroup-right > .oo-ui-toolGroup-tools {
+  left: 0;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-accel {
+  display: none;
+}
+.oo-ui-popupToolGroup.oo-ui-indicatorElement.oo-ui-iconElement {
+  min-width: 3.5em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+  top: 0;
+  width: 2em;
+  height: 2em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator {
+  left: 0;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+  right: 0.25em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+  line-height: 2.6em;
+  font-size: 0.8em;
+  margin: 0 1em;
+}
+.oo-ui-popupToolGroup-header {
+  line-height: 2.6em;
+  font-size: 0.8em;
+  margin: 0 0.6em;
+  font-weight: bold;
+}
+.oo-ui-popupToolGroup.oo-ui-iconElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+  margin-right: 3em;
+}
+.oo-ui-popupToolGroup.oo-ui-indicatorElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+  margin-left: 2.25em;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+  top: 2.3em;
+  margin: 0 -1px;
+  border: solid 1px #dddddd;
+  background-color: white;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  height: 2em;
+  width: 2em;
+  margin-left: 0.25em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  line-height: 2em;
+  font-size: 0.8em;
+}
+.oo-ui-listToolGroup .oo-ui-tool {
+  display: inline-block;
+  width: 100%;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-listToolGroup .oo-ui-tool-link {
+  display: block;
+  cursor: pointer;
+  white-space: nowrap;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+.oo-ui-listToolGroup .oo-ui-toolGroup-tools {
+  padding: 0.25em;
+}
+.oo-ui-listToolGroup .oo-ui-tool-link {
+  padding-left: 0.5em;
+}
+.oo-ui-menuToolGroup .oo-ui-tool {
+  display: block;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link {
+  display: block;
+  cursor: pointer;
+  white-space: nowrap;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+  background-image: none;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconElement-icon {
+  background-image: /* @embed */ url(images/icons/check.svg);
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+  min-width: 8em;
+}
+.oo-ui-menuToolGroup .oo-ui-toolGroup-tools {
+  padding: 0.25em 0 0.25em 0;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link {
+  padding: 0 0.25em 0 1em;
+}
+.oo-ui-toolbar {
+  clear: both;
+}
+.oo-ui-toolbar-bar {
+  line-height: 1em;
+}
+.oo-ui-toolbar-actions {
+  float: left;
+}
+.oo-ui-toolbar-tools {
+  display: inline;
+}
+.oo-ui-toolbar-tools,
+.oo-ui-toolbar-actions,
+.oo-ui-toolbar-shadow {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-toolbar-actions .oo-ui-popupWidget {
+  -webkit-touch-callout: default;
+  -webkit-user-select: all;
+  -moz-user-select: all;
+  -ms-user-select: all;
+  user-select: all;
+}
+.oo-ui-toolbar-shadow {
+  background-position: right top;
+  background-repeat: repeat-x;
+  position: absolute;
+  width: 100%;
+  pointer-events: none;
+}
+.oo-ui-toolbar-bar {
+  border-bottom: solid 1px #dddddd;
+  background: white;
+}
+.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
+  border: none;
+  background: none;
+}
+.oo-ui-selectWidget {
+  margin: 0;
+  padding: 0;
+}
+.oo-ui-optionWidget {
+  position: relative;
+  display: block;
+  cursor: pointer;
+  padding: 0.8em 3.35em 0.8em 1em;
+  border: none;
+  font-weight: bold;
+}
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+  cursor: default;
+}
+.oo-ui-optionWidget .oo-ui-labelElement-label {
+  display: block;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
+}
+.oo-ui-optionWidget .oo-ui-labelElement-label {
+  line-height: 1.5em;
+}
+.oo-ui-optionWidget.oo-ui-indicatorElement .oo-ui-labelElement-label {
+  padding-left: 1.5em;
+}
+.oo-ui-optionWidget-level-0 {
+  padding-right: 3.5em;
+}
+.oo-ui-optionWidget-level-0 .oo-ui-iconElement-icon {
+  right: 1em;
+}
+.oo-ui-optionWidget-level-1 {
+  padding-right: 5em;
+}
+.oo-ui-optionWidget-level-1 .oo-ui-iconElement-icon {
+  right: 2.5em;
+}
+.oo-ui-optionWidget-level-2 {
+  padding-right: 6.5em;
+}
+.oo-ui-optionWidget-level-2 .oo-ui-iconElement-icon {
+  right: 4em;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+  position: absolute;
+  background-repeat: no-repeat;
+  background-position: center center;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+  top: 50%;
+  width: 2em;
+  height: 2em;
+  margin-top: -1em;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon {
+  right: 0.5em;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+  left: 0.5em;
+}
+.oo-ui-buttonSelectWidget {
+  display: inline-block;
+  white-space: nowrap;
+}
+.oo-ui-buttonOptionWidget {
+  display: inline-block;
+  padding: 0;
+  background-color: transparent;
+}
+.oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+  position: relative;
+}
+.oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  position: static;
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+  height: 1.9em;
+}
+.oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+  height: 1.9em;
+  margin-top: 0;
+}
+.oo-ui-labelWidget {
+  display: inline-block;
+  padding: 0.5em 0;
+}
+.oo-ui-iconWidget {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+  line-height: 2.5em;
+  height: 1.9em;
+  width: 1.9em;
+  opacity: 0.8;
+}
+.oo-ui-iconWidget.oo-ui-widget-disabled {
+  opacity: 0.2;
+}
+.oo-ui-indicatorWidget {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+  line-height: 2.5em;
+  height: 1.9em;
+  width: 1.9em;
+  opacity: 0.8;
+}
+.oo-ui-indicatorWidget.oo-ui-widget-disabled {
+  opacity: 0.2;
+}
+.oo-ui-buttonWidget {
+  display: inline-block;
+  vertical-align: middle;
+}
+.oo-ui-buttonGroupWidget {
+  border-radius: 0.3em;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+  border-radius: 0;
+  margin-bottom: -1px;
+  margin-right: -1px;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:first-child .oo-ui-buttonElement-button {
+  border-bottom-right-radius: 0.3em;
+  border-top-right-radius: 0.3em;
+  margin-right: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:last-child .oo-ui-buttonElement-button {
+  border-bottom-left-radius: 0.3em;
+  border-top-left-radius: 0.3em;
+}
+.oo-ui-toggleSwitchWidget {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+  overflow: hidden;
+  cursor: pointer;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+  -webkit-transform: translateZ(0px);
+  -moz-transform: translateZ(0px);
+  -ms-transform: translateZ(0px);
+  -o-transform: translateZ(0px);
+  transform: translateZ(0px);
+  height: 2em;
+  width: 4em;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+  cursor: default;
+}
+.oo-ui-toggleSwitchWidget-grip {
+  position: absolute;
+  display: block;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+  display: none;
+}
+.oo-ui-toggleSwitchWidget-grip {
+  top: 0.25em;
+  right: 0.25em;
+  width: 1.5em;
+  height: 1.5em;
+  margin-top: -1px;
+  -webkit-transition: right 200ms ease-in-out, margin-right 200ms ease-in-out;
+  -moz-transition: right 200ms ease-in-out, margin-right 200ms ease-in-out;
+  -ms-transition: right 200ms ease-in-out, margin-right 200ms ease-in-out;
+  -o-transition: right 200ms ease-in-out, margin-right 200ms ease-in-out;
+  transition: right 200ms ease-in-out, margin-right 200ms ease-in-out;
+}
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+  -webkit-transition: opacity 200ms ease-in-out;
+  -moz-transition: opacity 200ms ease-in-out;
+  -ms-transition: opacity 200ms ease-in-out;
+  -o-transition: opacity 200ms ease-in-out;
+  transition: opacity 200ms ease-in-out;
+}
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+  right: 2.25em;
+  margin-right: -2px;
+}
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
+  right: 0.25em;
+  margin-right: 0;
+}
+.oo-ui-popupWidget-popup {
+  position: absolute;
+  overflow: hidden;
+  z-index: 1;
+}
+.oo-ui-popupWidget-anchor {
+  display: none;
+  z-index: 1;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor {
+  display: block;
+  position: absolute;
+  background-repeat: no-repeat;
+}
+.oo-ui-popupWidget-head {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-popupWidget-head .oo-ui-buttonWidget {
+  float: left;
+}
+.oo-ui-popupWidget-head .oo-ui-labelElement-label {
+  float: right;
+  cursor: default;
+}
+.oo-ui-popupWidget-body {
+  clear: both;
+  overflow: hidden;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-popup {
+  margin-top: 7px;
+}
+.oo-ui-popupWidget-head {
+  height: 2.5em;
+}
+.oo-ui-popupWidget-head .oo-ui-buttonWidget {
+  margin: 0.25em;
+}
+.oo-ui-popupWidget-head .oo-ui-labelElement-label {
+  margin: 0.75em 1em;
+}
+.oo-ui-popupWidget-body-padded {
+  padding: 0 1em;
+}
+.oo-ui-popupButtonWidget {
+  position: relative;
+}
+.oo-ui-popupButtonWidget .oo-ui-popupWidget {
+  position: absolute;
+  right: 1em;
+  cursor: auto;
+}
+.oo-ui-lookupInputWidget-menu {
+  background-color: #fff;
+}
+.oo-ui-textInputWidget {
+  position: relative;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+  display: inline-block;
+  width: 100%;
+  resize: none;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator {
+  position: absolute;
+  top: 0;
+  height: 100%;
+  background-repeat: no-repeat;
+  cursor: pointer;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon {
+  right: 0;
+}
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator {
+  left: 0;
+}
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+  padding: .8em 1em;
+}
+.oo-ui-menuWidget {
+  position: absolute;
+  background: white;
+  border: solid 1px #dddddd;
+}
+.oo-ui-menuWidget input {
+  position: absolute;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+  opacity: 0;
+}
+.oo-ui-menuItemWidget {
+  position: relative;
+}
+.oo-ui-menuItemWidget .oo-ui-iconElement-icon {
+  display: none;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+  background-color: transparent;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected .oo-ui-iconElement-icon {
+  display: block;
+}
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+  background: #347bff;
+  color: #ffffff;
+}
+.oo-ui-menuItemWidget .oo-ui-iconElement-icon {
+  background-size: 24px auto;
+}
+.oo-ui-menuSectionItemWidget {
+  cursor: default;
+  font-weight: normal;
+  color: #777777;
+  border: none;
+}
+.oo-ui-inlineMenuWidget {
+  position: relative;
+  display: inline-block;
+  margin: 0.25em 0;
+  min-width: 20em;
+}
+.oo-ui-inlineMenuWidget-handle {
+  width: 100%;
+  display: inline-block;
+  cursor: pointer;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon {
+  position: absolute;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.oo-ui-inlineMenuWidget .oo-ui-menuWidget {
+  z-index: 1;
+  width: 100%;
+}
+.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle {
+  cursor: default;
+}
+.oo-ui-inlineMenuWidget-handle {
+  height: 2.5em;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon {
+  top: 0;
+  width: 2.5em;
+  height: 2.5em;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator {
+  left: 0;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon {
+  right: 0.25em;
+}
+.oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label {
+  line-height: 2.5em;
+  margin: 0 0.5em;
+}
+.oo-ui-inlineMenuWidget.oo-ui-iconElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label {
+  margin-right: 3em;
+}
+.oo-ui-inlineMenuWidget.oo-ui-indicatorElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label {
+  margin-left: 2em;
+}
+.oo-ui-outlineItemWidget {
+  position: relative;
+  cursor: pointer;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  padding: 0.75em;
+}
+.oo-ui-outlineControlsWidget {
+  height: 3em;
+}
+.oo-ui-outlineControlsWidget-items,
+.oo-ui-outlineControlsWidget-movers {
+  float: right;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+  float: right;
+  background-position: left center;
+  background-repeat: no-repeat;
+}
+.oo-ui-outlineControlsWidget-items {
+  float: right;
+}
+.oo-ui-outlineControlsWidget-items .oo-ui-buttonWidget {
+  float: right;
+}
+.oo-ui-outlineControlsWidget-movers {
+  float: left;
+}
+.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
+  float: left;
+}
+.oo-ui-outlineControlsWidget-items,
+.oo-ui-outlineControlsWidget-movers {
+  height: 2em;
+  margin: 0.5em;
+  padding: 0;
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+  width: 1.5em;
+  height: 2em;
+  margin: 0.5em 0.5em 0.5em 0;
+}
+.oo-ui-outlineControlsWidget-items {
+  margin-right: 0;
+}
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget {
+  z-index: 1;
+}
+.oo-ui-comboBoxWidget > .oo-ui-selectWidget > .oo-ui-selectWidget {
+  min-width: 20em;
+}
+.oo-ui-searchWidget-query {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+  width: 100%;
+}
+.oo-ui-searchWidget-results {
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  left: 0;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.oo-ui-searchWidget-query {
+  height: 4em;
+  padding: 0 1em;
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+  margin: 0.75em 0;
+}
+.oo-ui-searchWidget-results {
+  top: 4em;
+  padding: 1em;
+  line-height: 0;
+}
+.oo-ui-window {
+  line-height: 1em;
+  /* Content div takes focus when opened, so hide outline */
+}
+.oo-ui-window-frame {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-window-frame > iframe {
+  width: 100%;
+  height: 100%;
+  margin: 0;
+  padding: 0;
+}
+.oo-ui-window-content:focus {
+  outline: none;
+}
+.oo-ui-window-head,
+.oo-ui-window-foot {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.oo-ui-window-body {
+  margin: 0;
+  padding: 0;
+  background: none;
+}
+.oo-ui-window-overlay {
+  position: absolute;
+  top: 0;
+  right: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-head,
+.oo-ui-dialog-content > .oo-ui-window-body,
+.oo-ui-dialog-content > .oo-ui-window-foot {
+  position: absolute;
+  right: 0;
+  left: 0;
+  overflow: hidden;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-dialog-content > .oo-ui-window-head {
+  z-index: 1;
+  top: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-body {
+  z-index: 2;
+  top: 0;
+  bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-foot {
+  z-index: 1;
+  bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-overlay {
+  z-index: 3;
+}
+.oo-ui-messageDialog-actions-horizontal {
+  display: table;
+  table-layout: fixed;
+  width: 100%;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+  display: table-cell;
+  width: 1%;
+}
+.oo-ui-messageDialog-actions-vertical {
+  display: block;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+  display: block;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget {
+  position: relative;
+  text-align: center;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-buttonElement-button {
+  display: block;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-labelElement-label {
+  position: relative;
+  top: auto;
+  bottom: auto;
+  display: inline;
+  white-space: nowrap;
+}
+.oo-ui-messageDialog-title,
+.oo-ui-messageDialog-message {
+  display: block;
+  text-align: center;
+  padding-top: 0.5em;
+}
+.oo-ui-messageDialog-title {
+  font-size: 1.5em;
+  line-height: 1em;
+  color: #000;
+}
+.oo-ui-messageDialog-message {
+  font-size: 0.9em;
+  line-height: 1.25em;
+  color: #666;
+}
+.oo-ui-messageDialog-message-verbose {
+  font-size: 1.1em;
+  line-height: 1.5em;
+  text-align: right;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+  border-left: solid 1px #e5e5e5;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget:last-child {
+  border-left-width: 0;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+  border-bottom: solid 1px #e5e5e5;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget:last-child {
+  border-bottom-width: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-labelElement-label {
+  text-align: center;
+  line-height: 3.4em;
+  padding: 0 2em;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:hover {
+  background-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:active {
+  background-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-primary:hover {
+  background-color: rgba(8, 126, 204, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-primary:active {
+  background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-labelElement-label {
+  font-weight: bold;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover {
+  background-color: rgba(118, 171, 54, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active {
+  background-color: rgba(118, 171, 54, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover {
+  background-color: rgba(212, 83, 83, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active {
+  background-color: rgba(212, 83, 83, 0.1);
+}
+.oo-ui-processDialog-location {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.oo-ui-processDialog-title {
+  display: inline;
+  padding: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget {
+  white-space: nowrap;
+}
+.oo-ui-processDialog-actions-safe,
+.oo-ui-processDialog-actions-primary {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+}
+.oo-ui-processDialog-actions-safe {
+  right: 0;
+}
+.oo-ui-processDialog-actions-primary {
+  left: 0;
+}
+.oo-ui-processDialog-errors {
+  display: none;
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+  z-index: 2;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.oo-ui-processDialog-content .oo-ui-window-head {
+  height: 3.35em;
+  border-bottom: 1px solid #dddddd;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.oo-ui-processDialog-content .oo-ui-window-body {
+  top: 3.35em;
+  padding: 2em 0;
+}
+.oo-ui-processDialog-navigation {
+  position: relative;
+  height: 3.35em;
+  padding: 0 1em;
+}
+.oo-ui-processDialog-location {
+  padding: 0.75em 0;
+  height: 1.85em;
+  cursor: default;
+  text-align: center;
+}
+.oo-ui-processDialog-title {
+  font-weight: bold;
+  line-height: 1.85em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-buttonElement-button {
+  padding: 0.35em 0.75em;
+  min-width: 1.85em;
+  min-height: 1.85em;
+  border: 1px solid #dddddd;
+  border-radius: 4px;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-labelElement-label {
+  line-height: 1.85em;
+  padding: 0 1em;
+  font-weight: bold;
+  color: #777777;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-iconElement-icon,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-iconElement-icon,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-iconElement-icon {
+  position: absolute;
+  margin-top: -0.125em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+  vertical-align: middle;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-destructive .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-destructive .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-flaggedElement-destructive .oo-ui-buttonElement-button {
+  border: 1px solid transparent;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-destructive .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-destructive .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-flaggedElement-destructive .oo-ui-labelElement-label {
+  color: #d11d13;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-buttonElement-button {
+  padding: 0.75em 0.35em;
+  border: none;
+  border-radius: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-buttonElement-button {
+  background-color: #347bff;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-primary .oo-ui-labelElement-label {
+  color: #ffffff;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+  right: 0.5em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-labelElement-label {
+  padding-right: 2.25em;
+}
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+  left: 0.5em;
+}
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-labelElement-label {
+  padding-left: 2.25em;
+}
+.oo-ui-processDialog-actions-other {
+  position: absolute;
+  bottom: 1em;
+}
+.oo-ui-processDialog > .oo-ui-window-frame {
+  min-height: 5em;
+}
+.oo-ui-processDialog-errors {
+  background-color: rgba(255, 255, 255, 0.9);
+  padding: 3em 3em 1.5em 3em;
+  text-align: center;
+}
+.oo-ui-processDialog-errors .oo-ui-buttonWidget {
+  margin: 2em 1em 2em 1em;
+}
+.oo-ui-processDialog-errors-title {
+  font-size: 1.5em;
+  color: #000;
+  margin-bottom: 2em;
+}
+.oo-ui-processDialog-error {
+  text-align: right;
+  margin: 1em;
+  padding: 1em;
+  border: solid 1px #ff9e9e;
+  background-color: #fff7f7;
+  border-radius: 0.25em;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+  position: fixed;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup {
+  width: auto;
+  height: auto;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0;
+  padding: 1em;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup > .oo-ui-window-frame {
+  position: fixed;
+  left: 0;
+  right: 0;
+  margin: auto;
+  overflow: hidden;
+  max-width: 100%;
+  max-height: 100%;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup > .oo-ui-window-frame > iframe {
+  width: 100%;
+  height: 100%;
+}
+.oo-ui-windowManager-fullscreen > .oo-ui-dialog > .oo-ui-window-frame {
+  width: 100%;
+  height: 100%;
+  top: 0;
+  bottom: 0;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+  background-color: rgba(255, 255, 255, 0.5);
+  opacity: 0;
+  -webkit-transition: opacity 250ms ease-in-out;
+  -moz-transition: opacity 250ms ease-in-out;
+  -ms-transition: opacity 250ms ease-in-out;
+  -o-transition: opacity 250ms ease-in-out;
+  transition: opacity 250ms ease-in-out;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog > .oo-ui-window-frame {
+  top: 0;
+  bottom: 0;
+  background-color: #fff;
+  -webkit-transform: translate3d(0, -200%, 0);
+  -moz-transform: translate3d(0, -200%, 0);
+  -ms-transform: translate3d(0, -200%, 0);
+  -o-transform: translate3d(0, -200%, 0);
+  transform: translate3d(0, -200%, 0);
+  -webkit-transition: transform 250ms ease-in-out;
+  -moz-transition: transform 250ms ease-in-out;
+  -ms-transition: transform 250ms ease-in-out;
+  -o-transition: transform 250ms ease-in-out;
+  transition: transform 250ms ease-in-out;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-ready {
+  opacity: 1;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-ready > .oo-ui-window-frame {
+  -webkit-transform: translate3d(0, 0, 0);
+  -moz-transform: translate3d(0, 0, 0);
+  -ms-transform: translate3d(0, 0, 0);
+  -o-transform: translate3d(0, 0, 0);
+  transform: translate3d(0, 0, 0);
+}
+.oo-ui-windowManager-modal.oo-ui-windowManager-floating > .oo-ui-dialog > .oo-ui-window-frame {
+  border: solid 1px #ccc;
+  border-radius: 0.5em;
+  box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
+}
+
+/*
+ * Blank theme mixins.
+ *
+ * Base styles invoke these mixins at the end of their definitions. Override these mixins to add
+ * additional rules to the base styles.
+ */
+.oo-ui-icon-check {
+  background-image: /* @embed */ url(themes/minerva/images/icons/check.png);
+  background: #347bff;
+}
index f2e3202..a3e2375 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (85cfc2e735)
+ * OOjs UI v0.1.0-pre (49b64bdba7)
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2014 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2014-07-03T02:33:09Z
+ * Date: 2014-09-15T22:18:37Z
  */
 ( function ( OO ) {
 
@@ -26,22 +26,22 @@ OO.ui.bind = $.proxy;
  * @property {Object}
  */
 OO.ui.Keys = {
-       'UNDEFINED': 0,
-       'BACKSPACE': 8,
-       'DELETE': 46,
-       'LEFT': 37,
-       'RIGHT': 39,
-       'UP': 38,
-       'DOWN': 40,
-       'ENTER': 13,
-       'END': 35,
-       'HOME': 36,
-       'TAB': 9,
-       'PAGEUP': 33,
-       'PAGEDOWN': 34,
-       'ESCAPE': 27,
-       'SHIFT': 16,
-       'SPACE': 32
+       UNDEFINED: 0,
+       BACKSPACE: 8,
+       DELETE: 46,
+       LEFT: 37,
+       RIGHT: 39,
+       UP: 38,
+       DOWN: 40,
+       ENTER: 13,
+       END: 35,
+       HOME: 36,
+       TAB: 9,
+       PAGEUP: 33,
+       PAGEDOWN: 34,
+       ESCAPE: 27,
+       SHIFT: 16,
+       SPACE: 32
 };
 
 /**
@@ -94,7 +94,6 @@ OO.ui.getLocalValue = function ( obj, lang, fallback ) {
 };
 
 ( function () {
-
        /**
         * Message store for the default implementation of OO.ui.msg
         *
@@ -104,8 +103,6 @@ OO.ui.getLocalValue = function ( obj, lang, fallback ) {
         * @private
         */
        var messages = {
-               // Label text for button to exit from dialog
-               'ooui-dialog-action-close': 'Close',
                // Tool tip for a button that moves items in a list down one place
                'ooui-outline-control-move-down': 'Move item down',
                // Tool tip for a button that moves items in a list up one place
@@ -114,15 +111,16 @@ OO.ui.getLocalValue = function ( obj, lang, fallback ) {
                'ooui-outline-control-remove': 'Remove item',
                // Label for the toolbar group that contains a list of all other available tools
                'ooui-toolbar-more': 'More',
-
-               // Label for the generic dialog used to confirm things
-               'ooui-dialog-confirm-title': 'Confirm',
-               // The default prompt of a confirmation dialog
-               'ooui-dialog-confirm-default-prompt': 'Are you sure?',
-               // The default OK button text on a confirmation dialog
-               'ooui-dialog-confirm-default-ok': 'OK',
-               // The default cancel button text on a confirmation dialog
-               'ooui-dialog-confirm-default-cancel': 'Cancel'
+               // Default label for the accept button of a confirmation dialog
+               'ooui-dialog-message-accept': 'OK',
+               // Default label for the reject button of a confirmation dialog
+               'ooui-dialog-message-reject': 'Cancel',
+               // Title for process dialog error description
+               'ooui-dialog-process-error': 'Something went wrong',
+               // Label for process dialog dismiss error button, visible when describing errors
+               'ooui-dialog-process-dismiss': 'Dismiss',
+               // Label for process dialog retry action button, visible when describing recoverable errors
+               'ooui-dialog-process-retry': 'Try again'
        };
 
        /**
@@ -157,14 +155,30 @@ OO.ui.getLocalValue = function ( obj, lang, fallback ) {
                return message;
        };
 
-       /** */
-       OO.ui.deferMsg = function ( key ) {
+       /**
+        * Package a message and arguments for deferred resolution.
+        *
+        * Use this when you are statically specifying a message and the message may not yet be present.
+        *
+        * @param {string} key Message key
+        * @param {Mixed...} [params] Message parameters
+        * @return {Function} Function that returns the resolved message when executed
+        */
+       OO.ui.deferMsg = function () {
+               var args = arguments;
                return function () {
-                       return OO.ui.msg( key );
+                       return OO.ui.msg.apply( OO.ui, args );
                };
        };
 
-       /** */
+       /**
+        * Resolve a message.
+        *
+        * If the message is a function it will be executed, otherwise it will pass through directly.
+        *
+        * @param {Function|string} msg Deferred message, or message text
+        * @return {string} Resolved message
+        */
        OO.ui.resolveMsg = function ( msg ) {
                if ( $.isFunction( msg ) ) {
                        return msg();
@@ -175,643 +189,1832 @@ OO.ui.getLocalValue = function ( obj, lang, fallback ) {
 } )();
 
 /**
- * DOM element abstraction.
+ * Element that can be marked as pending.
  *
  * @abstract
  * @class
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {Function} [$] jQuery for the frame the widget is in
- * @cfg {string[]} [classes] CSS class names
- * @cfg {string} [text] Text to insert
- * @cfg {jQuery} [$content] Content elements to append (after text)
  */
-OO.ui.Element = function OoUiElement( config ) {
-       // Configuration initialization
+OO.ui.PendingElement = function OoUiPendingElement( config ) {
+       // Config initialisation
        config = config || {};
 
        // Properties
-       this.$ = config.$ || OO.ui.Element.getJQuery( document );
-       this.$element = this.$( this.$.context.createElement( this.getTagName() ) );
-       this.elementGroup = null;
+       this.pending = 0;
+       this.$pending = null;
 
-       // Initialization
-       if ( $.isArray( config.classes ) ) {
-               this.$element.addClass( config.classes.join( ' ' ) );
-       }
-       if ( config.text ) {
-               this.$element.text( config.text );
-       }
-       if ( config.$content ) {
-               this.$element.append( config.$content );
-       }
+       // Initialisation
+       this.setPendingElement( config.$pending || this.$element );
 };
 
 /* Setup */
 
-OO.initClass( OO.ui.Element );
+OO.initClass( OO.ui.PendingElement );
 
-/* Static Properties */
+/* Methods */
 
 /**
- * HTML tag name.
- *
- * This may be ignored if getTagName is overridden.
+ * Set the pending element (and clean up any existing one).
  *
- * @static
- * @inheritable
- * @property {string}
+ * @param {jQuery} $pending The element to set to pending.
  */
-OO.ui.Element.static.tagName = 'div';
+OO.ui.PendingElement.prototype.setPendingElement = function ( $pending ) {
+       if ( this.$pending ) {
+               this.$pending.removeClass( 'oo-ui-pendingElement-pending' );
+       }
 
-/* Static Methods */
+       this.$pending = $pending;
+       if ( this.pending > 0 ) {
+               this.$pending.addClass( 'oo-ui-pendingElement-pending' );
+       }
+};
 
 /**
- * Get a jQuery function within a specific document.
+ * Check if input is pending.
  *
- * @static
- * @param {jQuery|HTMLElement|HTMLDocument|Window} context Context to bind the function to
- * @param {OO.ui.Frame} [frame] Frame of the document context
- * @return {Function} Bound jQuery function
+ * @return {boolean}
  */
-OO.ui.Element.getJQuery = function ( context, frame ) {
-       function wrapper( selector ) {
-               return $( selector, wrapper.context );
+OO.ui.PendingElement.prototype.isPending = function () {
+       return !!this.pending;
+};
+
+/**
+ * Increase the pending stack.
+ *
+ * @chainable
+ */
+OO.ui.PendingElement.prototype.pushPending = function () {
+       if ( this.pending === 0 ) {
+               this.$pending.addClass( 'oo-ui-pendingElement-pending' );
        }
+       this.pending++;
 
-       wrapper.context = this.getDocument( context );
+       return this;
+};
 
-       if ( frame ) {
-               wrapper.frame = frame;
+/**
+ * Reduce the pending stack.
+ *
+ * Clamped at zero.
+ *
+ * @chainable
+ */
+OO.ui.PendingElement.prototype.popPending = function () {
+       if ( this.pending === 1 ) {
+               this.$pending.removeClass( 'oo-ui-pendingElement-pending' );
        }
+       this.pending = Math.max( 0, this.pending - 1 );
 
-       return wrapper;
+       return this;
 };
 
 /**
- * Get the document of an element.
+ * List of actions.
  *
- * @static
- * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Object to get the document for
- * @return {HTMLDocument|null} Document object
+ * @abstract
+ * @class
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
  */
-OO.ui.Element.getDocument = function ( obj ) {
-       // jQuery - selections created "offscreen" won't have a context, so .context isn't reliable
-       return ( obj[0] && obj[0].ownerDocument ) ||
-               // Empty jQuery selections might have a context
-               obj.context ||
-               // HTMLElement
-               obj.ownerDocument ||
-               // Window
-               obj.document ||
-               // HTMLDocument
-               ( obj.nodeType === 9 && obj ) ||
-               null;
+OO.ui.ActionSet = function OoUiActionSet( config ) {
+       // Configuration intialization
+       config = config || {};
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Properties
+       this.list = [];
+       this.categories = {
+               actions: 'getAction',
+               flags: 'getFlags',
+               modes: 'getModes'
+       };
+       this.categorized = {};
+       this.special = {};
+       this.others = [];
+       this.organized = false;
+       this.changing = false;
+       this.changed = false;
 };
 
+/* Setup */
+
+OO.mixinClass( OO.ui.ActionSet, OO.EventEmitter );
+
+/* Static Properties */
+
 /**
- * Get the window of an element or document.
+ * Symbolic name of dialog.
  *
+ * @abstract
  * @static
- * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the window for
- * @return {Window} Window object
+ * @inheritable
+ * @property {string}
  */
-OO.ui.Element.getWindow = function ( obj ) {
-       var doc = this.getDocument( obj );
-       return doc.parentWindow || doc.defaultView;
+OO.ui.ActionSet.static.specialFlags = [ 'safe', 'primary' ];
+
+/* Events */
+
+/**
+ * @event click
+ * @param {OO.ui.ActionWidget} action Action that was clicked
+ */
+
+/**
+ * @event resize
+ * @param {OO.ui.ActionWidget} action Action that was resized
+ */
+
+/**
+ * @event add
+ * @param {OO.ui.ActionWidget[]} added Actions added
+ */
+
+/**
+ * @event remove
+ * @param {OO.ui.ActionWidget[]} added Actions removed
+ */
+
+/**
+ * @event change
+ */
+
+/* Methods */
+
+/**
+ * Handle action change events.
+ *
+ * @fires change
+ */
+OO.ui.ActionSet.prototype.onActionChange = function () {
+       this.organized = false;
+       if ( this.changing ) {
+               this.changed = true;
+       } else {
+               this.emit( 'change' );
+       }
 };
 
 /**
- * Get the direction of an element or document.
+ * Check if a action is one of the special actions.
  *
- * @static
- * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the direction for
- * @return {string} Text direction, either `ltr` or `rtl`
+ * @param {OO.ui.ActionWidget} action Action to check
+ * @return {boolean} Action is special
  */
-OO.ui.Element.getDir = function ( obj ) {
-       var isDoc, isWin;
+OO.ui.ActionSet.prototype.isSpecial = function ( action ) {
+       var flag;
 
-       if ( obj instanceof jQuery ) {
-               obj = obj[0];
-       }
-       isDoc = obj.nodeType === 9;
-       isWin = obj.document !== undefined;
-       if ( isDoc || isWin ) {
-               if ( isWin ) {
-                       obj = obj.document;
+       for ( flag in this.special ) {
+               if ( action === this.special[flag] ) {
+                       return true;
                }
-               obj = obj.body;
        }
-       return $( obj ).css( 'direction' );
+
+       return false;
 };
 
 /**
- * Get the offset between two frames.
- *
- * TODO: Make this function not use recursion.
+ * Get actions.
  *
- * @static
- * @param {Window} from Window of the child frame
- * @param {Window} [to=window] Window of the parent frame
- * @param {Object} [offset] Offset to start with, used internally
- * @return {Object} Offset object, containing left and top properties
+ * @param {Object} [filters] Filters to use, omit to get all actions
+ * @param {string|string[]} [filters.actions] Actions that actions must have
+ * @param {string|string[]} [filters.flags] Flags that actions must have
+ * @param {string|string[]} [filters.modes] Modes that actions must have
+ * @param {boolean} [filters.visible] Actions must be visible
+ * @param {boolean} [filters.disabled] Actions must be disabled
+ * @return {OO.ui.ActionWidget[]} Actions matching all criteria
  */
-OO.ui.Element.getFrameOffset = function ( from, to, offset ) {
-       var i, len, frames, frame, rect;
+OO.ui.ActionSet.prototype.get = function ( filters ) {
+       var i, len, list, category, actions, index, match, matches;
 
-       if ( !to ) {
-               to = window;
-       }
-       if ( !offset ) {
-               offset = { 'top': 0, 'left': 0 };
-       }
-       if ( from.parent === from ) {
-               return offset;
-       }
+       if ( filters ) {
+               this.organize();
 
-       // Get iframe element
-       frames = from.parent.document.getElementsByTagName( 'iframe' );
-       for ( i = 0, len = frames.length; i < len; i++ ) {
-               if ( frames[i].contentWindow === from ) {
-                       frame = frames[i];
-                       break;
+               // Collect category candidates
+               matches = [];
+               for ( category in this.categorized ) {
+                       list = filters[category];
+                       if ( list ) {
+                               if ( !Array.isArray( list ) ) {
+                                       list = [ list ];
+                               }
+                               for ( i = 0, len = list.length; i < len; i++ ) {
+                                       actions = this.categorized[category][list[i]];
+                                       if ( Array.isArray( actions ) ) {
+                                               matches.push.apply( matches, actions );
+                                       }
+                               }
+                       }
                }
-       }
-
-       // Recursively accumulate offset values
-       if ( frame ) {
-               rect = frame.getBoundingClientRect();
-               offset.left += rect.left;
-               offset.top += rect.top;
-               if ( from !== to ) {
-                       this.getFrameOffset( from.parent, offset );
+               // Remove by boolean filters
+               for ( i = 0, len = matches.length; i < len; i++ ) {
+                       match = matches[i];
+                       if (
+                               ( filters.visible !== undefined && match.isVisible() !== filters.visible ) ||
+                               ( filters.disabled !== undefined && match.isDisabled() !== filters.disabled )
+                       ) {
+                               matches.splice( i, 1 );
+                               len--;
+                               i--;
+                       }
+               }
+               // Remove duplicates
+               for ( i = 0, len = matches.length; i < len; i++ ) {
+                       match = matches[i];
+                       index = matches.lastIndexOf( match );
+                       while ( index !== i ) {
+                               matches.splice( index, 1 );
+                               len--;
+                               index = matches.lastIndexOf( match );
+                       }
                }
+               return matches;
        }
-       return offset;
+       return this.list.slice();
 };
 
 /**
- * Get the offset between two elements.
+ * Get special actions.
  *
- * @static
- * @param {jQuery} $from
- * @param {jQuery} $to
- * @return {Object} Translated position coordinates, containing top and left properties
+ * Special actions are the first visible actions with special flags, such as 'safe' and 'primary'.
+ * Special flags can be configured by changing #static-specialFlags in a subclass.
+ *
+ * @return {OO.ui.ActionWidget|null} Safe action
  */
-OO.ui.Element.getRelativePosition = function ( $from, $to ) {
-       var from = $from.offset(),
-               to = $to.offset();
-       return { 'top': Math.round( from.top - to.top ), 'left': Math.round( from.left - to.left ) };
+OO.ui.ActionSet.prototype.getSpecial = function () {
+       this.organize();
+       return $.extend( {}, this.special );
 };
 
 /**
- * Get element border sizes.
+ * Get other actions.
  *
- * @static
- * @param {HTMLElement} el Element to measure
- * @return {Object} Dimensions object with `top`, `left`, `bottom` and `right` properties
+ * Other actions include all non-special visible actions.
+ *
+ * @return {OO.ui.ActionWidget[]} Other actions
  */
-OO.ui.Element.getBorders = function ( el ) {
-       var doc = el.ownerDocument,
-               win = doc.parentWindow || doc.defaultView,
-               style = win && win.getComputedStyle ?
-                       win.getComputedStyle( el, null ) :
-                       el.currentStyle,
-               $el = $( el ),
-               top = parseFloat( style ? style.borderTopWidth : $el.css( 'borderTopWidth' ) ) || 0,
-               left = parseFloat( style ? style.borderLeftWidth : $el.css( 'borderLeftWidth' ) ) || 0,
-               bottom = parseFloat( style ? style.borderBottomWidth : $el.css( 'borderBottomWidth' ) ) || 0,
-               right = parseFloat( style ? style.borderRightWidth : $el.css( 'borderRightWidth' ) ) || 0;
-
-       return {
-               'top': Math.round( top ),
-               'left': Math.round( left ),
-               'bottom': Math.round( bottom ),
-               'right': Math.round( right )
-       };
+OO.ui.ActionSet.prototype.getOthers = function () {
+       this.organize();
+       return this.others.slice();
 };
 
 /**
- * Get dimensions of an element or window.
+ * Toggle actions based on their modes.
  *
- * @static
- * @param {HTMLElement|Window} el Element to measure
- * @return {Object} Dimensions object with `borders`, `scroll`, `scrollbar` and `rect` properties
+ * Unlike calling toggle on actions with matching flags, this will enforce mutually exclusive
+ * visibility; matching actions will be shown, non-matching actions will be hidden.
+ *
+ * @param {string} mode Mode actions must have
+ * @chainable
+ * @fires toggle
+ * @fires change
  */
-OO.ui.Element.getDimensions = function ( el ) {
-       var $el, $win,
-               doc = el.ownerDocument || el.document,
-               win = doc.parentWindow || doc.defaultView;
+OO.ui.ActionSet.prototype.setMode = function ( mode ) {
+       var i, len, action;
 
-       if ( win === el || el === doc.documentElement ) {
-               $win = $( win );
-               return {
-                       'borders': { 'top': 0, 'left': 0, 'bottom': 0, 'right': 0 },
-                       'scroll': {
-                               'top': $win.scrollTop(),
-                               'left': $win.scrollLeft()
-                       },
-                       'scrollbar': { 'right': 0, 'bottom': 0 },
-                       'rect': {
-                               'top': 0,
-                               'left': 0,
-                               'bottom': $win.innerHeight(),
-                               'right': $win.innerWidth()
-                       }
-               };
-       } else {
-               $el = $( el );
-               return {
-                       'borders': this.getBorders( el ),
-                       'scroll': {
-                               'top': $el.scrollTop(),
-                               'left': $el.scrollLeft()
-                       },
-                       'scrollbar': {
-                               'right': $el.innerWidth() - el.clientWidth,
-                               'bottom': $el.innerHeight() - el.clientHeight
-                       },
-                       'rect': el.getBoundingClientRect()
-               };
+       this.changing = true;
+       for ( i = 0, len = this.list.length; i < len; i++ ) {
+               action = this.list[i];
+               action.toggle( action.hasMode( mode ) );
        }
+
+       this.organized = false;
+       this.changing = false;
+       this.emit( 'change' );
+
+       return this;
 };
 
 /**
- * Get closest scrollable container.
+ * Change which actions are able to be performed.
  *
- * Traverses up until either a scrollable element or the root is reached, in which case the window
- * will be returned.
+ * Actions with matching actions will be disabled/enabled. Other actions will not be changed.
  *
- * @static
- * @param {HTMLElement} el Element to find scrollable container for
- * @param {string} [dimension] Dimension of scrolling to look for; `x`, `y` or omit for either
- * @return {HTMLElement|Window} Closest scrollable container
+ * @param {Object.<string,boolean>} actions List of abilities, keyed by action name, values
+ *   indicate actions are able to be performed
+ * @chainable
  */
-OO.ui.Element.getClosestScrollableContainer = function ( el, dimension ) {
-       var i, val,
-               props = [ 'overflow' ],
-               $parent = $( el ).parent();
-
-       if ( dimension === 'x' || dimension === 'y' ) {
-               props.push( 'overflow-' + dimension );
-       }
+OO.ui.ActionSet.prototype.setAbilities = function ( actions ) {
+       var i, len, action, item;
 
-       while ( $parent.length ) {
-               if ( $parent[0] === el.ownerDocument.body ) {
-                       return $parent[0];
-               }
-               i = props.length;
-               while ( i-- ) {
-                       val = $parent.css( props[i] );
-                       if ( val === 'auto' || val === 'scroll' ) {
-                               return $parent[0];
-                       }
+       for ( i = 0, len = this.list.length; i < len; i++ ) {
+               item = this.list[i];
+               action = item.getAction();
+               if ( actions[action] !== undefined ) {
+                       item.setDisabled( !actions[action] );
                }
-               $parent = $parent.parent();
        }
-       return this.getDocument( el ).body;
+
+       return this;
 };
 
 /**
- * Scroll element into view.
+ * Executes a function once per action.
  *
- * @static
- * @param {HTMLElement} el Element to scroll into view
- * @param {Object} [config={}] Configuration config
- * @param {string} [config.duration] jQuery animation duration value
- * @param {string} [config.direction] Scroll in only one direction, e.g. 'x' or 'y', omit
- *  to scroll in both directions
- * @param {Function} [config.complete] Function to call when scrolling completes
+ * When making changes to multiple actions, use this method instead of iterating over the actions
+ * manually to defer emitting a change event until after all actions have been changed.
+ *
+ * @param {Object|null} actions Filters to use for which actions to iterate over; see #get
+ * @param {Function} callback Callback to run for each action; callback is invoked with three
+ *   arguments: the action, the action's index, the list of actions being iterated over
+ * @chainable
  */
-OO.ui.Element.scrollIntoView = function ( el, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       var rel, anim = {},
-               callback = typeof config.complete === 'function' && config.complete,
-               sc = this.getClosestScrollableContainer( el, config.direction ),
-               $sc = $( sc ),
-               eld = this.getDimensions( el ),
-               scd = this.getDimensions( sc ),
-               $win = $( this.getWindow( el ) );
-
-       // Compute the distances between the edges of el and the edges of the scroll viewport
-       if ( $sc.is( 'body' ) ) {
-               // If the scrollable container is the <body> this is easy
-               rel = {
-                       'top': eld.rect.top,
-                       'bottom': $win.innerHeight() - eld.rect.bottom,
-                       'left': eld.rect.left,
-                       'right': $win.innerWidth() - eld.rect.right
-               };
-       } else {
-               // Otherwise, we have to subtract el's coordinates from sc's coordinates
-               rel = {
-                       'top': eld.rect.top - ( scd.rect.top + scd.borders.top ),
-                       'bottom': scd.rect.bottom - scd.borders.bottom - scd.scrollbar.bottom - eld.rect.bottom,
-                       'left': eld.rect.left - ( scd.rect.left + scd.borders.left ),
-                       'right': scd.rect.right - scd.borders.right - scd.scrollbar.right - eld.rect.right
-               };
+OO.ui.ActionSet.prototype.forEach = function ( filter, callback ) {
+       this.changed = false;
+       this.changing = true;
+       this.get( filter ).forEach( callback );
+       this.changing = false;
+       if ( this.changed ) {
+               this.emit( 'change' );
        }
 
-       if ( !config.direction || config.direction === 'y' ) {
-               if ( rel.top < 0 ) {
-                       anim.scrollTop = scd.scroll.top + rel.top;
-               } else if ( rel.top > 0 && rel.bottom < 0 ) {
-                       anim.scrollTop = scd.scroll.top + Math.min( rel.top, -rel.bottom );
-               }
-       }
-       if ( !config.direction || config.direction === 'x' ) {
-               if ( rel.left < 0 ) {
-                       anim.scrollLeft = scd.scroll.left + rel.left;
-               } else if ( rel.left > 0 && rel.right < 0 ) {
-                       anim.scrollLeft = scd.scroll.left + Math.min( rel.left, -rel.right );
-               }
-       }
-       if ( !$.isEmptyObject( anim ) ) {
-               $sc.stop( true ).animate( anim, config.duration || 'fast' );
-               if ( callback ) {
-                       $sc.queue( function ( next ) {
-                               callback();
-                               next();
-                       } );
-               }
-       } else {
-               if ( callback ) {
-                       callback();
-               }
-       }
+       return this;
 };
 
-/* Methods */
-
 /**
- * Get the HTML tag name.
- *
- * Override this method to base the result on instance information.
+ * Add actions.
  *
- * @return {string} HTML tag name
+ * @param {OO.ui.ActionWidget[]} actions Actions to add
+ * @chainable
+ * @fires add
+ * @fires change
  */
-OO.ui.Element.prototype.getTagName = function () {
-       return this.constructor.static.tagName;
-};
+OO.ui.ActionSet.prototype.add = function ( actions ) {
+       var i, len, action;
 
-/**
- * Check if the element is attached to the DOM
- * @return {boolean} The element is attached to the DOM
- */
-OO.ui.Element.prototype.isElementAttached = function () {
-       return $.contains( this.getElementDocument(), this.$element[0] );
-};
+       this.changing = true;
+       for ( i = 0, len = actions.length; i < len; i++ ) {
+               action = actions[i];
+               action.connect( this, {
+                       click: [ 'emit', 'click', action ],
+                       resize: [ 'emit', 'resize', action ],
+                       toggle: [ 'onActionChange' ]
+               } );
+               this.list.push( action );
+       }
+       this.organized = false;
+       this.emit( 'add', actions );
+       this.changing = false;
+       this.emit( 'change' );
 
-/**
- * Get the DOM document.
- *
- * @return {HTMLDocument} Document object
- */
-OO.ui.Element.prototype.getElementDocument = function () {
-       return OO.ui.Element.getDocument( this.$element );
+       return this;
 };
 
 /**
- * Get the DOM window.
+ * Remove actions.
  *
- * @return {Window} Window object
+ * @param {OO.ui.ActionWidget[]} actions Actions to remove
+ * @chainable
+ * @fires remove
+ * @fires change
  */
-OO.ui.Element.prototype.getElementWindow = function () {
-       return OO.ui.Element.getWindow( this.$element );
-};
+OO.ui.ActionSet.prototype.remove = function ( actions ) {
+       var i, len, index, action;
 
-/**
- * Get closest scrollable container.
- */
-OO.ui.Element.prototype.getClosestScrollableElementContainer = function () {
-       return OO.ui.Element.getClosestScrollableContainer( this.$element[0] );
+       this.changing = true;
+       for ( i = 0, len = actions.length; i < len; i++ ) {
+               action = actions[i];
+               index = this.list.indexOf( action );
+               if ( index !== -1 ) {
+                       action.disconnect( this );
+                       this.list.splice( index, 1 );
+               }
+       }
+       this.organized = false;
+       this.emit( 'remove', actions );
+       this.changing = false;
+       this.emit( 'change' );
+
+       return this;
 };
 
 /**
- * Get group element is in.
+ * Remove all actions.
  *
- * @return {OO.ui.GroupElement|null} Group element, null if none
+ * @chainable
+ * @fires remove
+ * @fires change
  */
-OO.ui.Element.prototype.getElementGroup = function () {
-       return this.elementGroup;
+OO.ui.ActionSet.prototype.clear = function () {
+       var i, len, action,
+               removed = this.list.slice();
+
+       this.changing = true;
+       for ( i = 0, len = this.list.length; i < len; i++ ) {
+               action = this.list[i];
+               action.disconnect( this );
+       }
+
+       this.list = [];
+
+       this.organized = false;
+       this.emit( 'remove', removed );
+       this.changing = false;
+       this.emit( 'change' );
+
+       return this;
 };
 
 /**
- * Set group element is in.
+ * Organize actions.
  *
- * @param {OO.ui.GroupElement|null} group Group element, null if none
+ * This is called whenver organized information is requested. It will only reorganize the actions
+ * if something has changed since the last time it ran.
+ *
+ * @private
  * @chainable
  */
-OO.ui.Element.prototype.setElementGroup = function ( group ) {
-       this.elementGroup = group;
+OO.ui.ActionSet.prototype.organize = function () {
+       var i, iLen, j, jLen, flag, action, category, list, item, special,
+               specialFlags = this.constructor.static.specialFlags;
+
+       if ( !this.organized ) {
+               this.categorized = {};
+               this.special = {};
+               this.others = [];
+               for ( i = 0, iLen = this.list.length; i < iLen; i++ ) {
+                       action = this.list[i];
+                       if ( action.isVisible() ) {
+                               // Populate catgeories
+                               for ( category in this.categories ) {
+                                       if ( !this.categorized[category] ) {
+                                               this.categorized[category] = {};
+                                       }
+                                       list = action[this.categories[category]]();
+                                       if ( !Array.isArray( list ) ) {
+                                               list = [ list ];
+                                       }
+                                       for ( j = 0, jLen = list.length; j < jLen; j++ ) {
+                                               item = list[j];
+                                               if ( !this.categorized[category][item] ) {
+                                                       this.categorized[category][item] = [];
+                                               }
+                                               this.categorized[category][item].push( action );
+                                       }
+                               }
+                               // Populate special/others
+                               special = false;
+                               for ( j = 0, jLen = specialFlags.length; j < jLen; j++ ) {
+                                       flag = specialFlags[j];
+                                       if ( !this.special[flag] && action.hasFlag( flag ) ) {
+                                               this.special[flag] = action;
+                                               special = true;
+                                               break;
+                                       }
+                               }
+                               if ( !special ) {
+                                       this.others.push( action );
+                               }
+                       }
+               }
+               this.organized = true;
+       }
+
        return this;
 };
 
 /**
- * Scroll element into view.
+ * DOM element abstraction.
  *
- * @param {Object} [config={}]
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Function} [$] jQuery for the frame the widget is in
+ * @cfg {string[]} [classes] CSS class names
+ * @cfg {string} [text] Text to insert
+ * @cfg {jQuery} [$content] Content elements to append (after text)
  */
-OO.ui.Element.prototype.scrollElementIntoView = function ( config ) {
-       return OO.ui.Element.scrollIntoView( this.$element[0], config );
+OO.ui.Element = function OoUiElement( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Properties
+       this.$ = config.$ || OO.ui.Element.getJQuery( document );
+       this.$element = this.$( this.$.context.createElement( this.getTagName() ) );
+       this.elementGroup = null;
+
+       // Initialization
+       if ( $.isArray( config.classes ) ) {
+               this.$element.addClass( config.classes.join( ' ' ) );
+       }
+       if ( config.text ) {
+               this.$element.text( config.text );
+       }
+       if ( config.$content ) {
+               this.$element.append( config.$content );
+       }
 };
 
+/* Setup */
+
+OO.initClass( OO.ui.Element );
+
+/* Static Properties */
+
 /**
- * Bind a handler for an event on this.$element
+ * HTML tag name.
  *
- * @deprecated Use jQuery#on instead.
- * @param {string} event
- * @param {Function} callback
+ * This may be ignored if getTagName is overridden.
+ *
+ * @static
+ * @inheritable
+ * @property {string}
  */
-OO.ui.Element.prototype.onDOMEvent = function ( event, callback ) {
-       OO.ui.Element.onDOMEvent( this.$element, event, callback );
-};
+OO.ui.Element.static.tagName = 'div';
+
+/* Static Methods */
 
 /**
- * Unbind a handler bound with #offDOMEvent
+ * Get a jQuery function within a specific document.
  *
- * @deprecated Use jQuery#off instead.
- * @param {string} event
- * @param {Function} callback
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} context Context to bind the function to
+ * @param {jQuery} [$iframe] HTML iframe element that contains the document, omit if document is
+ *   not in an iframe
+ * @return {Function} Bound jQuery function
  */
-OO.ui.Element.prototype.offDOMEvent = function ( event, callback ) {
-       OO.ui.Element.offDOMEvent( this.$element, event, callback );
+OO.ui.Element.getJQuery = function ( context, $iframe ) {
+       function wrapper( selector ) {
+               return $( selector, wrapper.context );
+       }
+
+       wrapper.context = this.getDocument( context );
+
+       if ( $iframe ) {
+               wrapper.$iframe = $iframe;
+       }
+
+       return wrapper;
 };
 
-( function () {
-       /**
-        * Bind a handler for an event on a DOM element.
-        *
-        * Used to be for working around a jQuery bug (jqbug.com/14180),
-        * but obsolete as of jQuery 1.11.0.
-        *
-        * @static
-        * @deprecated Use jQuery#on instead.
-        * @param {HTMLElement|jQuery} el DOM element
-        * @param {string} event Event to bind
-        * @param {Function} callback Callback to call when the event fires
-        */
-       OO.ui.Element.onDOMEvent = function ( el, event, callback ) {
-               $( el ).on( event, callback );
+/**
+ * Get the document of an element.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Object to get the document for
+ * @return {HTMLDocument|null} Document object
+ */
+OO.ui.Element.getDocument = function ( obj ) {
+       // jQuery - selections created "offscreen" won't have a context, so .context isn't reliable
+       return ( obj[0] && obj[0].ownerDocument ) ||
+               // Empty jQuery selections might have a context
+               obj.context ||
+               // HTMLElement
+               obj.ownerDocument ||
+               // Window
+               obj.document ||
+               // HTMLDocument
+               ( obj.nodeType === 9 && obj ) ||
+               null;
+};
+
+/**
+ * Get the window of an element or document.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the window for
+ * @return {Window} Window object
+ */
+OO.ui.Element.getWindow = function ( obj ) {
+       var doc = this.getDocument( obj );
+       return doc.parentWindow || doc.defaultView;
+};
+
+/**
+ * Get the direction of an element or document.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the direction for
+ * @return {string} Text direction, either `ltr` or `rtl`
+ */
+OO.ui.Element.getDir = function ( obj ) {
+       var isDoc, isWin;
+
+       if ( obj instanceof jQuery ) {
+               obj = obj[0];
+       }
+       isDoc = obj.nodeType === 9;
+       isWin = obj.document !== undefined;
+       if ( isDoc || isWin ) {
+               if ( isWin ) {
+                       obj = obj.document;
+               }
+               obj = obj.body;
+       }
+       return $( obj ).css( 'direction' );
+};
+
+/**
+ * Get the offset between two frames.
+ *
+ * TODO: Make this function not use recursion.
+ *
+ * @static
+ * @param {Window} from Window of the child frame
+ * @param {Window} [to=window] Window of the parent frame
+ * @param {Object} [offset] Offset to start with, used internally
+ * @return {Object} Offset object, containing left and top properties
+ */
+OO.ui.Element.getFrameOffset = function ( from, to, offset ) {
+       var i, len, frames, frame, rect;
+
+       if ( !to ) {
+               to = window;
+       }
+       if ( !offset ) {
+               offset = { top: 0, left: 0 };
+       }
+       if ( from.parent === from ) {
+               return offset;
+       }
+
+       // Get iframe element
+       frames = from.parent.document.getElementsByTagName( 'iframe' );
+       for ( i = 0, len = frames.length; i < len; i++ ) {
+               if ( frames[i].contentWindow === from ) {
+                       frame = frames[i];
+                       break;
+               }
+       }
+
+       // Recursively accumulate offset values
+       if ( frame ) {
+               rect = frame.getBoundingClientRect();
+               offset.left += rect.left;
+               offset.top += rect.top;
+               if ( from !== to ) {
+                       this.getFrameOffset( from.parent, offset );
+               }
+       }
+       return offset;
+};
+
+/**
+ * Get the offset between two elements.
+ *
+ * @static
+ * @param {jQuery} $from
+ * @param {jQuery} $to
+ * @return {Object} Translated position coordinates, containing top and left properties
+ */
+OO.ui.Element.getRelativePosition = function ( $from, $to ) {
+       var from = $from.offset(),
+               to = $to.offset();
+       return { top: Math.round( from.top - to.top ), left: Math.round( from.left - to.left ) };
+};
+
+/**
+ * Get element border sizes.
+ *
+ * @static
+ * @param {HTMLElement} el Element to measure
+ * @return {Object} Dimensions object with `top`, `left`, `bottom` and `right` properties
+ */
+OO.ui.Element.getBorders = function ( el ) {
+       var doc = el.ownerDocument,
+               win = doc.parentWindow || doc.defaultView,
+               style = win && win.getComputedStyle ?
+                       win.getComputedStyle( el, null ) :
+                       el.currentStyle,
+               $el = $( el ),
+               top = parseFloat( style ? style.borderTopWidth : $el.css( 'borderTopWidth' ) ) || 0,
+               left = parseFloat( style ? style.borderLeftWidth : $el.css( 'borderLeftWidth' ) ) || 0,
+               bottom = parseFloat( style ? style.borderBottomWidth : $el.css( 'borderBottomWidth' ) ) || 0,
+               right = parseFloat( style ? style.borderRightWidth : $el.css( 'borderRightWidth' ) ) || 0;
+
+       return {
+               top: Math.round( top ),
+               left: Math.round( left ),
+               bottom: Math.round( bottom ),
+               right: Math.round( right )
        };
+};
+
+/**
+ * Get dimensions of an element or window.
+ *
+ * @static
+ * @param {HTMLElement|Window} el Element to measure
+ * @return {Object} Dimensions object with `borders`, `scroll`, `scrollbar` and `rect` properties
+ */
+OO.ui.Element.getDimensions = function ( el ) {
+       var $el, $win,
+               doc = el.ownerDocument || el.document,
+               win = doc.parentWindow || doc.defaultView;
+
+       if ( win === el || el === doc.documentElement ) {
+               $win = $( win );
+               return {
+                       borders: { top: 0, left: 0, bottom: 0, right: 0 },
+                       scroll: {
+                               top: $win.scrollTop(),
+                               left: $win.scrollLeft()
+                       },
+                       scrollbar: { right: 0, bottom: 0 },
+                       rect: {
+                               top: 0,
+                               left: 0,
+                               bottom: $win.innerHeight(),
+                               right: $win.innerWidth()
+                       }
+               };
+       } else {
+               $el = $( el );
+               return {
+                       borders: this.getBorders( el ),
+                       scroll: {
+                               top: $el.scrollTop(),
+                               left: $el.scrollLeft()
+                       },
+                       scrollbar: {
+                               right: $el.innerWidth() - el.clientWidth,
+                               bottom: $el.innerHeight() - el.clientHeight
+                       },
+                       rect: el.getBoundingClientRect()
+               };
+       }
+};
+
+/**
+ * Get closest scrollable container.
+ *
+ * Traverses up until either a scrollable element or the root is reached, in which case the window
+ * will be returned.
+ *
+ * @static
+ * @param {HTMLElement} el Element to find scrollable container for
+ * @param {string} [dimension] Dimension of scrolling to look for; `x`, `y` or omit for either
+ * @return {HTMLElement} Closest scrollable container
+ */
+OO.ui.Element.getClosestScrollableContainer = function ( el, dimension ) {
+       var i, val,
+               props = [ 'overflow' ],
+               $parent = $( el ).parent();
+
+       if ( dimension === 'x' || dimension === 'y' ) {
+               props.push( 'overflow-' + dimension );
+       }
+
+       while ( $parent.length ) {
+               if ( $parent[0] === el.ownerDocument.body ) {
+                       return $parent[0];
+               }
+               i = props.length;
+               while ( i-- ) {
+                       val = $parent.css( props[i] );
+                       if ( val === 'auto' || val === 'scroll' ) {
+                               return $parent[0];
+                       }
+               }
+               $parent = $parent.parent();
+       }
+       return this.getDocument( el ).body;
+};
+
+/**
+ * Scroll element into view.
+ *
+ * @static
+ * @param {HTMLElement} el Element to scroll into view
+ * @param {Object} [config={}] Configuration config
+ * @param {string} [config.duration] jQuery animation duration value
+ * @param {string} [config.direction] Scroll in only one direction, e.g. 'x' or 'y', omit
+ *  to scroll in both directions
+ * @param {Function} [config.complete] Function to call when scrolling completes
+ */
+OO.ui.Element.scrollIntoView = function ( el, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       var rel, anim = {},
+               callback = typeof config.complete === 'function' && config.complete,
+               sc = this.getClosestScrollableContainer( el, config.direction ),
+               $sc = $( sc ),
+               eld = this.getDimensions( el ),
+               scd = this.getDimensions( sc ),
+               $win = $( this.getWindow( el ) );
+
+       // Compute the distances between the edges of el and the edges of the scroll viewport
+       if ( $sc.is( 'body' ) ) {
+               // If the scrollable container is the <body> this is easy
+               rel = {
+                       top: eld.rect.top,
+                       bottom: $win.innerHeight() - eld.rect.bottom,
+                       left: eld.rect.left,
+                       right: $win.innerWidth() - eld.rect.right
+               };
+       } else {
+               // Otherwise, we have to subtract el's coordinates from sc's coordinates
+               rel = {
+                       top: eld.rect.top - ( scd.rect.top + scd.borders.top ),
+                       bottom: scd.rect.bottom - scd.borders.bottom - scd.scrollbar.bottom - eld.rect.bottom,
+                       left: eld.rect.left - ( scd.rect.left + scd.borders.left ),
+                       right: scd.rect.right - scd.borders.right - scd.scrollbar.right - eld.rect.right
+               };
+       }
+
+       if ( !config.direction || config.direction === 'y' ) {
+               if ( rel.top < 0 ) {
+                       anim.scrollTop = scd.scroll.top + rel.top;
+               } else if ( rel.top > 0 && rel.bottom < 0 ) {
+                       anim.scrollTop = scd.scroll.top + Math.min( rel.top, -rel.bottom );
+               }
+       }
+       if ( !config.direction || config.direction === 'x' ) {
+               if ( rel.left < 0 ) {
+                       anim.scrollLeft = scd.scroll.left + rel.left;
+               } else if ( rel.left > 0 && rel.right < 0 ) {
+                       anim.scrollLeft = scd.scroll.left + Math.min( rel.left, -rel.right );
+               }
+       }
+       if ( !$.isEmptyObject( anim ) ) {
+               $sc.stop( true ).animate( anim, config.duration || 'fast' );
+               if ( callback ) {
+                       $sc.queue( function ( next ) {
+                               callback();
+                               next();
+                       } );
+               }
+       } else {
+               if ( callback ) {
+                       callback();
+               }
+       }
+};
+
+/* Methods */
+
+/**
+ * Get the HTML tag name.
+ *
+ * Override this method to base the result on instance information.
+ *
+ * @return {string} HTML tag name
+ */
+OO.ui.Element.prototype.getTagName = function () {
+       return this.constructor.static.tagName;
+};
+
+/**
+ * Check if the element is attached to the DOM
+ * @return {boolean} The element is attached to the DOM
+ */
+OO.ui.Element.prototype.isElementAttached = function () {
+       return $.contains( this.getElementDocument(), this.$element[0] );
+};
+
+/**
+ * Get the DOM document.
+ *
+ * @return {HTMLDocument} Document object
+ */
+OO.ui.Element.prototype.getElementDocument = function () {
+       return OO.ui.Element.getDocument( this.$element );
+};
+
+/**
+ * Get the DOM window.
+ *
+ * @return {Window} Window object
+ */
+OO.ui.Element.prototype.getElementWindow = function () {
+       return OO.ui.Element.getWindow( this.$element );
+};
+
+/**
+ * Get closest scrollable container.
+ */
+OO.ui.Element.prototype.getClosestScrollableElementContainer = function () {
+       return OO.ui.Element.getClosestScrollableContainer( this.$element[0] );
+};
+
+/**
+ * Get group element is in.
+ *
+ * @return {OO.ui.GroupElement|null} Group element, null if none
+ */
+OO.ui.Element.prototype.getElementGroup = function () {
+       return this.elementGroup;
+};
+
+/**
+ * Set group element is in.
+ *
+ * @param {OO.ui.GroupElement|null} group Group element, null if none
+ * @chainable
+ */
+OO.ui.Element.prototype.setElementGroup = function ( group ) {
+       this.elementGroup = group;
+       return this;
+};
+
+/**
+ * Scroll element into view.
+ *
+ * @param {Object} [config={}]
+ */
+OO.ui.Element.prototype.scrollElementIntoView = function ( config ) {
+       return OO.ui.Element.scrollIntoView( this.$element[0], config );
+};
+
+/**
+ * Bind a handler for an event on this.$element
+ *
+ * @deprecated Use jQuery#on instead.
+ * @param {string} event
+ * @param {Function} callback
+ */
+OO.ui.Element.prototype.onDOMEvent = function ( event, callback ) {
+       OO.ui.Element.onDOMEvent( this.$element, event, callback );
+};
+
+/**
+ * Unbind a handler bound with #offDOMEvent
+ *
+ * @deprecated Use jQuery#off instead.
+ * @param {string} event
+ * @param {Function} callback
+ */
+OO.ui.Element.prototype.offDOMEvent = function ( event, callback ) {
+       OO.ui.Element.offDOMEvent( this.$element, event, callback );
+};
+
+( function () {
+       /**
+        * Bind a handler for an event on a DOM element.
+        *
+        * Used to be for working around a jQuery bug (jqbug.com/14180),
+        * but obsolete as of jQuery 1.11.0.
+        *
+        * @static
+        * @deprecated Use jQuery#on instead.
+        * @param {HTMLElement|jQuery} el DOM element
+        * @param {string} event Event to bind
+        * @param {Function} callback Callback to call when the event fires
+        */
+       OO.ui.Element.onDOMEvent = function ( el, event, callback ) {
+               $( el ).on( event, callback );
+       };
+
+       /**
+        * Unbind a handler bound with #static-method-onDOMEvent.
+        *
+        * @deprecated Use jQuery#off instead.
+        * @static
+        * @param {HTMLElement|jQuery} el DOM element
+        * @param {string} event Event to unbind
+        * @param {Function} [callback] Callback to unbind
+        */
+       OO.ui.Element.offDOMEvent = function ( el, event, callback ) {
+               $( el ).off( event, callback );
+       };
+}() );
+
+/**
+ * Container for elements.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.Layout = function OoUiLayout( config ) {
+       // Initialize config
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Layout.super.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-layout' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Layout, OO.ui.Element );
+OO.mixinClass( OO.ui.Layout, OO.EventEmitter );
+
+/**
+ * User interface control.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [disabled=false] Disable
+ */
+OO.ui.Widget = function OoUiWidget( config ) {
+       // Initialize config
+       config = $.extend( { disabled: false }, config );
+
+       // Parent constructor
+       OO.ui.Widget.super.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Properties
+       this.visible = true;
+       this.disabled = null;
+       this.wasDisabled = null;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-widget' );
+       this.setDisabled( !!config.disabled );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Widget, OO.ui.Element );
+OO.mixinClass( OO.ui.Widget, OO.EventEmitter );
+
+/* Events */
+
+/**
+ * @event disable
+ * @param {boolean} disabled Widget is disabled
+ */
+
+/**
+ * @event toggle
+ * @param {boolean} visible Widget is visible
+ */
+
+/* Methods */
+
+/**
+ * Check if the widget is disabled.
+ *
+ * @param {boolean} Button is disabled
+ */
+OO.ui.Widget.prototype.isDisabled = function () {
+       return this.disabled;
+};
+
+/**
+ * Check if widget is visible.
+ *
+ * @return {boolean} Widget is visible
+ */
+OO.ui.Widget.prototype.isVisible = function () {
+       return this.visible;
+};
+
+/**
+ * Set the disabled state of the widget.
+ *
+ * This should probably change the widgets' appearance and prevent it from being used.
+ *
+ * @param {boolean} disabled Disable widget
+ * @chainable
+ */
+OO.ui.Widget.prototype.setDisabled = function ( disabled ) {
+       var isDisabled;
+
+       this.disabled = !!disabled;
+       isDisabled = this.isDisabled();
+       if ( isDisabled !== this.wasDisabled ) {
+               this.$element.toggleClass( 'oo-ui-widget-disabled', isDisabled );
+               this.$element.toggleClass( 'oo-ui-widget-enabled', !isDisabled );
+               this.emit( 'disable', isDisabled );
+       }
+       this.wasDisabled = isDisabled;
+
+       return this;
+};
+
+/**
+ * Toggle visibility of widget.
+ *
+ * @param {boolean} [show] Make widget visible, omit to toggle visibility
+ * @fires visible
+ * @chainable
+ */
+OO.ui.Widget.prototype.toggle = function ( show ) {
+       show = show === undefined ? !this.visible : !!show;
+
+       if ( show !== this.isVisible() ) {
+               this.visible = show;
+               this.$element.toggle( show );
+               this.emit( 'toggle', show );
+       }
+
+       return this;
+};
+
+/**
+ * Update the disabled state, in case of changes in parent widget.
+ *
+ * @chainable
+ */
+OO.ui.Widget.prototype.updateDisabled = function () {
+       this.setDisabled( this.disabled );
+       return this;
+};
+
+/**
+ * Container for elements in a child frame.
+ *
+ * Use together with OO.ui.WindowManager.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * When a window is opened, the setup and ready processes are executed. Similarly, the hold and
+ * teardown processes are executed when the window is closed.
+ *
+ * - {@link OO.ui.WindowManager#openWindow} or {@link #open} methods are used to start opening
+ * - Window manager begins opening window
+ * - {@link #getSetupProcess} method is called and its result executed
+ * - {@link #getReadyProcess} method is called and its result executed
+ * - Window is now open
+ *
+ * - {@link OO.ui.WindowManager#closeWindow} or {@link #close} methods are used to start closing
+ * - Window manager begins closing window
+ * - {@link #getHoldProcess} method is called and its result executed
+ * - {@link #getTeardownProcess} method is called and its result executed
+ * - Window is now closed
+ *
+ * Each process (setup, ready, hold and teardown) can be extended in subclasses by overriding
+ * {@link #getSetupProcess}, {@link #getReadyProcess}, {@link #getHoldProcess} and
+ * {@link #getTeardownProcess} respectively. Each process is executed in series, so asynchonous
+ * processing can complete. Always assume window processes are executed asychronously. See
+ * OO.ui.Process for more details about how to work with processes. Some events, as well as the
+ * #open and #close methods, provide promises which are resolved when the window enters a new state.
+ *
+ * Sizing of windows is specified using symbolic names which are interpreted by the window manager.
+ * If the requested size is not recognized, the window manager will choose a sensible fallback.
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [size] Symbolic name of dialog size, `small`, `medium`, `large` or `full`; omit to
+ *   use #static-size
+ * @fires initialize
+ */
+OO.ui.Window = function OoUiWindow( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Window.super.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Properties
+       this.manager = null;
+       this.initialized = false;
+       this.visible = false;
+       this.opening = null;
+       this.closing = null;
+       this.opened = null;
+       this.timing = null;
+       this.loading = null;
+       this.size = config.size || this.constructor.static.size;
+       this.$frame = this.$( '<div>' );
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-window' )
+               .append( this.$frame );
+       this.$frame.addClass( 'oo-ui-window-frame' );
+
+       // NOTE: Additional intitialization will occur when #setManager is called
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Window, OO.ui.Element );
+OO.mixinClass( OO.ui.Window, OO.EventEmitter );
+
+/* Events */
+
+/**
+ * @event resize
+ * @param {string} size Symbolic size name, e.g. 'small', 'medium', 'large', 'full'
+ */
+
+/* Static Properties */
+
+/**
+ * Symbolic name of size.
+ *
+ * Size is used if no size is configured during construction.
+ *
+ * @static
+ * @inheritable
+ * @property {string}
+ */
+OO.ui.Window.static.size = 'medium';
+
+/* Static Methods */
+
+/**
+ * Transplant the CSS styles from as parent document to a frame's document.
+ *
+ * This loops over the style sheets in the parent document, and copies their nodes to the
+ * frame's document. It then polls the document to see when all styles have loaded, and once they
+ * have, resolves the promise.
+ *
+ * If the styles still haven't loaded after a long time (5 seconds by default), we give up waiting
+ * and resolve the promise anyway. This protects against cases like a display: none; iframe in
+ * Firefox, where the styles won't load until the iframe becomes visible.
+ *
+ * For details of how we arrived at the strategy used in this function, see #load.
+ *
+ * @static
+ * @inheritable
+ * @param {HTMLDocument} parentDoc Document to transplant styles from
+ * @param {HTMLDocument} frameDoc Document to transplant styles to
+ * @param {number} [timeout=5000] How long to wait before giving up (in ms). If 0, never give up.
+ * @return {jQuery.Promise} Promise resolved when styles have loaded
+ */
+OO.ui.Window.static.transplantStyles = function ( parentDoc, frameDoc, timeout ) {
+       var i, numSheets, styleNode, styleText, newNode, timeoutID, pollNodeId, $pendingPollNodes,
+               $pollNodes = $( [] ),
+               // Fake font-family value
+               fontFamily = 'oo-ui-frame-transplantStyles-loaded',
+               nextIndex = parentDoc.oouiFrameTransplantStylesNextIndex || 0,
+               deferred = $.Deferred();
+
+       for ( i = 0, numSheets = parentDoc.styleSheets.length; i < numSheets; i++ ) {
+               styleNode = parentDoc.styleSheets[i].ownerNode;
+               if ( styleNode.disabled ) {
+                       continue;
+               }
+
+               if ( styleNode.nodeName.toLowerCase() === 'link' ) {
+                       // External stylesheet; use @import
+                       styleText = '@import url(' + styleNode.href + ');';
+               } else {
+                       // Internal stylesheet; just copy the text
+                       // For IE10 we need to fall back to .cssText, BUT that's undefined in
+                       // other browsers, so fall back to '' rather than 'undefined'
+                       styleText = styleNode.textContent || parentDoc.styleSheets[i].cssText || '';
+               }
+
+               // Create a node with a unique ID that we're going to monitor to see when the CSS
+               // has loaded
+               if ( styleNode.oouiFrameTransplantStylesId ) {
+                       // If we're nesting transplantStyles operations and this node already has
+                       // a CSS rule to wait for loading, reuse it
+                       pollNodeId = styleNode.oouiFrameTransplantStylesId;
+               } else {
+                       // Otherwise, create a new ID
+                       pollNodeId = 'oo-ui-frame-transplantStyles-loaded-' + nextIndex;
+                       nextIndex++;
+
+                       // Add #pollNodeId { font-family: ... } to the end of the stylesheet / after the @import
+                       // The font-family rule will only take effect once the @import finishes
+                       styleText += '\n' + '#' + pollNodeId + ' { font-family: ' + fontFamily + '; }';
+               }
+
+               // Create a node with id=pollNodeId
+               $pollNodes = $pollNodes.add( $( '<div>', frameDoc )
+                       .attr( 'id', pollNodeId )
+                       .appendTo( frameDoc.body )
+               );
+
+               // Add our modified CSS as a <style> tag
+               newNode = frameDoc.createElement( 'style' );
+               newNode.textContent = styleText;
+               newNode.oouiFrameTransplantStylesId = pollNodeId;
+               frameDoc.head.appendChild( newNode );
+       }
+       frameDoc.oouiFrameTransplantStylesNextIndex = nextIndex;
+
+       // Poll every 100ms until all external stylesheets have loaded
+       $pendingPollNodes = $pollNodes;
+       timeoutID = setTimeout( function pollExternalStylesheets() {
+               while (
+                       $pendingPollNodes.length > 0 &&
+                       $pendingPollNodes.eq( 0 ).css( 'font-family' ) === fontFamily
+               ) {
+                       $pendingPollNodes = $pendingPollNodes.slice( 1 );
+               }
+
+               if ( $pendingPollNodes.length === 0 ) {
+                       // We're done!
+                       if ( timeoutID !== null ) {
+                               timeoutID = null;
+                               $pollNodes.remove();
+                               deferred.resolve();
+                       }
+               } else {
+                       timeoutID = setTimeout( pollExternalStylesheets, 100 );
+               }
+       }, 100 );
+       // ...but give up after a while
+       if ( timeout !== 0 ) {
+               setTimeout( function () {
+                       if ( timeoutID ) {
+                               clearTimeout( timeoutID );
+                               timeoutID = null;
+                               $pollNodes.remove();
+                               deferred.reject();
+                       }
+               }, timeout || 5000 );
+       }
+
+       return deferred.promise();
+};
+
+/* Methods */
+
+/**
+ * Handle mouse down events.
+ *
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.Window.prototype.onMouseDown = function ( e ) {
+       // Prevent clicking on the click-block from stealing focus
+       if ( e.target === this.$element[0] ) {
+               return false;
+       }
+};
+
+/**
+ * Check if window has been initialized.
+ *
+ * @return {boolean} Window has been initialized
+ */
+OO.ui.Window.prototype.isInitialized = function () {
+       return this.initialized;
+};
+
+/**
+ * Check if window is visible.
+ *
+ * @return {boolean} Window is visible
+ */
+OO.ui.Window.prototype.isVisible = function () {
+       return this.visible;
+};
+
+/**
+ * Check if window is loading.
+ *
+ * @return {boolean} Window is loading
+ */
+OO.ui.Window.prototype.isLoading = function () {
+       return this.loading && this.loading.state() === 'pending';
+};
+
+/**
+ * Check if window is loaded.
+ *
+ * @return {boolean} Window is loaded
+ */
+OO.ui.Window.prototype.isLoaded = function () {
+       return this.loading && this.loading.state() === 'resolved';
+};
+
+/**
+ * Check if window is opening.
+ *
+ * This is a wrapper around OO.ui.WindowManager#isOpening.
+ *
+ * @return {boolean} Window is opening
+ */
+OO.ui.Window.prototype.isOpening = function () {
+       return this.manager.isOpening( this );
+};
+
+/**
+ * Check if window is closing.
+ *
+ * This is a wrapper around OO.ui.WindowManager#isClosing.
+ *
+ * @return {boolean} Window is closing
+ */
+OO.ui.Window.prototype.isClosing = function () {
+       return this.manager.isClosing( this );
+};
 
-       /**
-        * Unbind a handler bound with #static-method-onDOMEvent.
-        *
-        * @deprecated Use jQuery#off instead.
-        * @static
-        * @param {HTMLElement|jQuery} el DOM element
-        * @param {string} event Event to unbind
-        * @param {Function} [callback] Callback to unbind
-        */
-       OO.ui.Element.offDOMEvent = function ( el, event, callback ) {
-               $( el ).off( event, callback );
-       };
-}() );
+/**
+ * Check if window is opened.
+ *
+ * This is a wrapper around OO.ui.WindowManager#isOpened.
+ *
+ * @return {boolean} Window is opened
+ */
+OO.ui.Window.prototype.isOpened = function () {
+       return this.manager.isOpened( this );
+};
 
 /**
- * Embedded iframe with the same styles as its parent.
+ * Get the window manager.
  *
- * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
+ * @return {OO.ui.WindowManager} Manager of window
+ */
+OO.ui.Window.prototype.getManager = function () {
+       return this.manager;
+};
+
+/**
+ * Get the window size.
  *
- * @constructor
- * @param {Object} [config] Configuration options
+ * @return {string} Symbolic size name, e.g. 'small', 'medium', 'large', 'full'
  */
-OO.ui.Frame = function OoUiFrame( config ) {
-       // Parent constructor
-       OO.ui.Frame.super.call( this, config );
+OO.ui.Window.prototype.getSize = function () {
+       return this.size;
+};
 
-       // Mixin constructors
-       OO.EventEmitter.call( this );
+/**
+ * Get the height of the dialog contents.
+ *
+ * @return {number} Content height
+ */
+OO.ui.Window.prototype.getContentHeight = function () {
+       return Math.round(
+               // Add buffer for border
+               ( this.$frame.outerHeight() - this.$frame.innerHeight() ) +
+               // Use combined heights of children
+               ( this.$head.outerHeight( true ) + this.getBodyHeight() + this.$foot.outerHeight( true ) )
+       );
+};
 
-       // Properties
-       this.loading = null;
-       this.config = config;
+/**
+ * Get the height of the dialog contents.
+ *
+ * @return {number} Height of content
+ */
+OO.ui.Window.prototype.getBodyHeight = function () {
+       return this.$body[0].scrollHeight;
+};
 
-       // Initialize
-       this.$element
-               .addClass( 'oo-ui-frame' )
-               .attr( { 'frameborder': 0, 'scrolling': 'no' } );
+/**
+ * Get the directionality of the frame
+ *
+ * @return {string} Directionality, 'ltr' or 'rtl'
+ */
+OO.ui.Window.prototype.getDir = function () {
+       return this.dir;
+};
 
+/**
+ * Get a process for setting up a window for use.
+ *
+ * Each time the window is opened this process will set it up for use in a particular context, based
+ * on the `data` argument.
+ *
+ * When you override this method, you can add additional setup steps to the process the parent
+ * method provides using the 'first' and 'next' methods.
+ *
+ * @abstract
+ * @param {Object} [data] Window opening data
+ * @return {OO.ui.Process} Setup process
+ */
+OO.ui.Window.prototype.getSetupProcess = function () {
+       return new OO.ui.Process();
 };
 
-/* Setup */
+/**
+ * Get a process for readying a window for use.
+ *
+ * Each time the window is open and setup, this process will ready it up for use in a particular
+ * context, based on the `data` argument.
+ *
+ * When you override this method, you can add additional setup steps to the process the parent
+ * method provides using the 'first' and 'next' methods.
+ *
+ * @abstract
+ * @param {Object} [data] Window opening data
+ * @return {OO.ui.Process} Setup process
+ */
+OO.ui.Window.prototype.getReadyProcess = function () {
+       return new OO.ui.Process();
+};
 
-OO.inheritClass( OO.ui.Frame, OO.ui.Element );
-OO.mixinClass( OO.ui.Frame, OO.EventEmitter );
+/**
+ * Get a process for holding a window from use.
+ *
+ * Each time the window is closed, this process will hold it from use in a particular context, based
+ * on the `data` argument.
+ *
+ * When you override this method, you can add additional setup steps to the process the parent
+ * method provides using the 'first' and 'next' methods.
+ *
+ * @abstract
+ * @param {Object} [data] Window closing data
+ * @return {OO.ui.Process} Hold process
+ */
+OO.ui.Window.prototype.getHoldProcess = function () {
+       return new OO.ui.Process();
+};
 
-/* Static Properties */
+/**
+ * Get a process for tearing down a window after use.
+ *
+ * Each time the window is closed this process will tear it down and do something with the user's
+ * interactions within the window, based on the `data` argument.
+ *
+ * When you override this method, you can add additional teardown steps to the process the parent
+ * method provides using the 'first' and 'next' methods.
+ *
+ * @abstract
+ * @param {Object} [data] Window closing data
+ * @return {OO.ui.Process} Teardown process
+ */
+OO.ui.Window.prototype.getTeardownProcess = function () {
+       return new OO.ui.Process();
+};
 
 /**
- * @static
- * @inheritdoc
+ * Toggle visibility of window.
+ *
+ * If the window is isolated and hasn't fully loaded yet, the visiblity property will be used
+ * instead of display.
+ *
+ * @param {boolean} [show] Make window visible, omit to toggle visibility
+ * @fires visible
+ * @chainable
  */
-OO.ui.Frame.static.tagName = 'iframe';
+OO.ui.Window.prototype.toggle = function ( show ) {
+       show = show === undefined ? !this.visible : !!show;
 
-/* Events */
+       if ( show !== this.isVisible() ) {
+               this.visible = show;
+
+               if ( this.isolated && !this.isLoaded() ) {
+                       // Hide the window using visibility instead of display until loading is complete
+                       // Can't use display: none; because that prevents the iframe from loading in Firefox
+                       this.$element.css( 'visibility', show ? 'visible' : 'hidden' );
+               } else {
+                       this.$element.toggle( show ).css( 'visibility', '' );
+               }
+               this.emit( 'toggle', show );
+       }
+
+       return this;
+};
+
+/**
+ * Set the window manager.
+ *
+ * This must be called before initialize. Calling it more than once will cause an error.
+ *
+ * @param {OO.ui.WindowManager} manager Manager for this window
+ * @throws {Error} If called more than once
+ * @chainable
+ */
+OO.ui.Window.prototype.setManager = function ( manager ) {
+       if ( this.manager ) {
+               throw new Error( 'Cannot set window manager, window already has a manager' );
+       }
+
+       // Properties
+       this.manager = manager;
+       this.isolated = manager.shouldIsolate();
+
+       // Initialization
+       if ( this.isolated ) {
+               this.$iframe = this.$( '<iframe>' );
+               this.$iframe.attr( { frameborder: 0, scrolling: 'no' } );
+               this.$frame.append( this.$iframe );
+               this.$ = function () {
+                       throw new Error( 'this.$() cannot be used until the frame has been initialized.' );
+               };
+               // WARNING: Do not use this.$ again until #initialize is called
+       } else {
+               this.$content = this.$( '<div>' );
+               this.$document = $( this.getElementDocument() );
+               this.$content.addClass( 'oo-ui-window-content' );
+               this.$frame.append( this.$content );
+       }
+       this.toggle( false );
+
+       // Figure out directionality:
+       this.dir = OO.ui.Element.getDir( this.$iframe || this.$content ) || 'ltr';
+
+       return this;
+};
 
 /**
- * @event load
+ * Set the window size.
+ *
+ * @param {string} size Symbolic size name, e.g. 'small', 'medium', 'large', 'full'
+ * @chainable
  */
+OO.ui.Window.prototype.setSize = function ( size ) {
+       this.size = size;
+       this.manager.updateWindowSize( this );
+       return this;
+};
 
-/* Static Methods */
+/**
+ * Set window dimensions.
+ *
+ * Properties are applied to the frame container.
+ *
+ * @param {Object} dim CSS dimension properties
+ * @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
+ * @chainable
+ */
+OO.ui.Window.prototype.setDimensions = function ( dim ) {
+       // Apply width before height so height is not based on wrapping content using the wrong width
+       this.$frame.css( {
+               width: dim.width || '',
+               minWidth: dim.minWidth || '',
+               maxWidth: dim.maxWidth || ''
+       } );
+       this.$frame.css( {
+               height: ( dim.height !== undefined ? dim.height : this.getContentHeight() ) || '',
+               minHeight: dim.minHeight || '',
+               maxHeight: dim.maxHeight || ''
+       } );
+       return this;
+};
 
 /**
- * Transplant the CSS styles from as parent document to a frame's document.
+ * Initialize window contents.
  *
- * This loops over the style sheets in the parent document, and copies their nodes to the
- * frame's document. It then polls the document to see when all styles have loaded, and once they
- * have, resolves the promise.
+ * The first time the window is opened, #initialize is called when it's safe to begin populating
+ * its contents. See #getSetupProcess for a way to make changes each time the window opens.
  *
- * If the styles still haven't loaded after a long time (5 seconds by default), we give up waiting
- * and resolve the promise anyway. This protects against cases like a display: none; iframe in
- * Firefox, where the styles won't load until the iframe becomes visible.
+ * Once this method is called, this.$ can be used to create elements within the frame.
  *
- * For details of how we arrived at the strategy used in this function, see #load.
+ * @throws {Error} If not attached to a manager
+ * @chainable
+ */
+OO.ui.Window.prototype.initialize = function () {
+       if ( !this.manager ) {
+               throw new Error( 'Cannot initialize window, must be attached to a manager' );
+       }
+
+       // Properties
+       this.$head = this.$( '<div>' );
+       this.$body = this.$( '<div>' );
+       this.$foot = this.$( '<div>' );
+       this.$overlay = this.$( '<div>' );
+
+       // Events
+       this.$element.on( 'mousedown', OO.ui.bind( this.onMouseDown, this ) );
+
+       // Initialization
+       this.$head.addClass( 'oo-ui-window-head' );
+       this.$body.addClass( 'oo-ui-window-body' );
+       this.$foot.addClass( 'oo-ui-window-foot' );
+       this.$overlay.addClass( 'oo-ui-window-overlay' );
+       this.$content.append( this.$head, this.$body, this.$foot, this.$overlay );
+
+       return this;
+};
+
+/**
+ * Open window.
  *
- * @static
- * @inheritable
- * @param {HTMLDocument} parentDoc Document to transplant styles from
- * @param {HTMLDocument} frameDoc Document to transplant styles to
- * @param {number} [timeout=5000] How long to wait before giving up (in ms). If 0, never give up.
- * @return {jQuery.Promise} Promise resolved when styles have loaded
+ * This is a wrapper around calling {@link OO.ui.WindowManager#openWindow} on the window manager.
+ * To do something each time the window opens, use #getSetupProcess or #getReadyProcess.
+ *
+ * @param {Object} [data] Window opening data
+ * @return {jQuery.Promise} Promise resolved when window is opened; when the promise is resolved the
+ *   first argument will be a promise which will be resolved when the window begins closing
  */
-OO.ui.Frame.static.transplantStyles = function ( parentDoc, frameDoc, timeout ) {
-       var i, numSheets, styleNode, newNode, timeoutID, pollNodeId, $pendingPollNodes,
-               $pollNodes = $( [] ),
-               // Fake font-family value
-               fontFamily = 'oo-ui-frame-transplantStyles-loaded',
+OO.ui.Window.prototype.open = function ( data ) {
+       return this.manager.openWindow( this, data );
+};
+
+/**
+ * Close window.
+ *
+ * This is a wrapper around calling OO.ui.WindowManager#closeWindow on the window manager.
+ * To do something each time the window closes, use #getHoldProcess or #getTeardownProcess.
+ *
+ * @param {Object} [data] Window closing data
+ * @return {jQuery.Promise} Promise resolved when window is closed
+ */
+OO.ui.Window.prototype.close = function ( data ) {
+       return this.manager.closeWindow( this, data );
+};
+
+/**
+ * Setup window.
+ *
+ * This is called by OO.ui.WindowManager durring window opening, and should not be called directly
+ * by other systems.
+ *
+ * @param {Object} [data] Window opening data
+ * @return {jQuery.Promise} Promise resolved when window is setup
+ */
+OO.ui.Window.prototype.setup = function ( data ) {
+       var win = this,
                deferred = $.Deferred();
 
-       for ( i = 0, numSheets = parentDoc.styleSheets.length; i < numSheets; i++ ) {
-               styleNode = parentDoc.styleSheets[i].ownerNode;
-               if ( styleNode.disabled ) {
-                       continue;
-               }
-               if ( styleNode.nodeName.toLowerCase() === 'link' ) {
-                       // External stylesheet
-                       // Create a node with a unique ID that we're going to monitor to see when the CSS
-                       // has loaded
-                       pollNodeId = 'oo-ui-frame-transplantStyles-loaded-' + i;
-                       $pollNodes = $pollNodes.add( $( '<div>', frameDoc )
-                               .attr( 'id', pollNodeId )
-                               .appendTo( frameDoc.body )
-                       );
+       this.$element.show();
+       this.visible = true;
+       this.getSetupProcess( data ).execute().done( function () {
+               // Force redraw by asking the browser to measure the elements' widths
+               win.$element.addClass( 'oo-ui-window-setup' ).width();
+               win.$content.addClass( 'oo-ui-window-content-setup' ).width();
+               deferred.resolve();
+       } );
 
-                       // Add <style>@import url(...); #pollNodeId { font-family: ... }</style>
-                       // The font-family rule will only take effect once the @import finishes
-                       newNode = frameDoc.createElement( 'style' );
-                       newNode.textContent = '@import url(' + styleNode.href + ');\n' +
-                               '#' + pollNodeId + ' { font-family: ' + fontFamily + '; }';
-               } else {
-                       // Not an external stylesheet, or no polling required; just copy the node over
-                       newNode = frameDoc.importNode( styleNode, true );
-               }
-               frameDoc.head.appendChild( newNode );
-       }
+       return deferred.promise();
+};
 
-       // Poll every 100ms until all external stylesheets have loaded
-       $pendingPollNodes = $pollNodes;
-       timeoutID = setTimeout( function pollExternalStylesheets() {
-               while (
-                       $pendingPollNodes.length > 0 &&
-                       $pendingPollNodes.eq( 0 ).css( 'font-family' ) === fontFamily
-               ) {
-                       $pendingPollNodes = $pendingPollNodes.slice( 1 );
-               }
+/**
+ * Ready window.
+ *
+ * This is called by OO.ui.WindowManager durring window opening, and should not be called directly
+ * by other systems.
+ *
+ * @param {Object} [data] Window opening data
+ * @return {jQuery.Promise} Promise resolved when window is ready
+ */
+OO.ui.Window.prototype.ready = function ( data ) {
+       var win = this,
+               deferred = $.Deferred();
+
+       this.$content.focus();
+       this.getReadyProcess( data ).execute().done( function () {
+               // Force redraw by asking the browser to measure the elements' widths
+               win.$element.addClass( 'oo-ui-window-ready' ).width();
+               win.$content.addClass( 'oo-ui-window-content-ready' ).width();
+               deferred.resolve();
+       } );
+
+       return deferred.promise();
+};
+
+/**
+ * Hold window.
+ *
+ * This is called by OO.ui.WindowManager durring window closing, and should not be called directly
+ * by other systems.
+ *
+ * @param {Object} [data] Window closing data
+ * @return {jQuery.Promise} Promise resolved when window is held
+ */
+OO.ui.Window.prototype.hold = function ( data ) {
+       var win = this,
+               deferred = $.Deferred();
 
-               if ( $pendingPollNodes.length === 0 ) {
-                       // We're done!
-                       if ( timeoutID !== null ) {
-                               timeoutID = null;
-                               $pollNodes.remove();
-                               deferred.resolve();
-                       }
-               } else {
-                       timeoutID = setTimeout( pollExternalStylesheets, 100 );
+       this.getHoldProcess( data ).execute().done( function () {
+               // Get the focused element within the window's content
+               var $focus = win.$content.find( OO.ui.Element.getDocument( win.$content ).activeElement );
+
+               // Blur the focused element
+               if ( $focus.length ) {
+                       $focus[0].blur();
                }
-       }, 100 );
-       // ...but give up after a while
-       if ( timeout !== 0 ) {
-               setTimeout( function () {
-                       if ( timeoutID ) {
-                               clearTimeout( timeoutID );
-                               timeoutID = null;
-                               $pollNodes.remove();
-                               deferred.reject();
-                       }
-               }, timeout || 5000 );
-       }
+
+               // Force redraw by asking the browser to measure the elements' widths
+               win.$element.removeClass( 'oo-ui-window-ready' ).width();
+               win.$content.removeClass( 'oo-ui-window-content-ready' ).width();
+               deferred.resolve();
+       } );
 
        return deferred.promise();
 };
 
-/* Methods */
+/**
+ * Teardown window.
+ *
+ * This is called by OO.ui.WindowManager durring window closing, and should not be called directly
+ * by other systems.
+ *
+ * @param {Object} [data] Window closing data
+ * @return {jQuery.Promise} Promise resolved when window is torn down
+ */
+OO.ui.Window.prototype.teardown = function ( data ) {
+       var win = this,
+               deferred = $.Deferred();
+
+       this.getTeardownProcess( data ).execute().done( function () {
+               // Force redraw by asking the browser to measure the elements' widths
+               win.$element.removeClass( 'oo-ui-window-setup' ).width();
+               win.$content.removeClass( 'oo-ui-window-content-setup' ).width();
+               win.$element.hide();
+               win.visible = false;
+               deferred.resolve();
+       } );
+
+       return deferred.promise();
+};
 
 /**
  * Load the frame contents.
@@ -833,25 +2036,35 @@ OO.ui.Frame.static.transplantStyles = function ( parentDoc, frameDoc, timeout )
  * loaded is to attempt to access .cssRules and wait for that to stop throwing an exception. But
  * cross-domain stylesheets never allow .cssRules to be accessed even after they have loaded.
  *
- * The workaround is to change all `<link href="...">` tags to `<style>@import url(...)</style>` tags.
- * Because `@import` is blocking, Chrome won't add the stylesheet to document.styleSheets until
- * the `@import` has finished, and Firefox won't allow .cssRules to be accessed until the `@import`
- * has finished. And because the contents of the `<style>` tag are from the same origin, accessing
- * .cssRules is allowed.
+ * The workaround is to change all `<link href="...">` tags to `<style>@import url(...)</style>`
+ * tags. Because `@import` is blocking, Chrome won't add the stylesheet to document.styleSheets
+ * until the `@import` has finished, and Firefox won't allow .cssRules to be accessed until the
+ * `@import` has finished. And because the contents of the `<style>` tag are from the same origin,
+ * accessing .cssRules is allowed.
  *
  * However, now that we control the styles we're injecting, we might as well do away with
  * browser-specific polling hacks like document.styleSheets and .cssRules, and instead inject
  * `<style>@import url(...); #foo { font-family: someValue; }</style>`, then create `<div id="foo">`
- * and wait for its font-family to change to someValue. Because `@import` is blocking, the font-family
- * rule is not applied until after the `@import` finishes.
+ * and wait for its font-family to change to someValue. Because `@import` is blocking, the
+ * font-family rule is not applied until after the `@import` finishes.
  *
  * All this stylesheet injection and polling magic is in #transplantStyles.
  *
  * @return {jQuery.Promise} Promise resolved when loading is complete
  * @fires load
  */
-OO.ui.Frame.prototype.load = function () {
-       var win, doc;
+OO.ui.Window.prototype.load = function () {
+       var sub, doc, loading,
+               win = this;
+
+       // Non-isolated windows are already "loaded"
+       if ( !this.loading && !this.isolated ) {
+               this.loading = $.Deferred().resolve();
+               this.initialize();
+               // Set initialized state after so sub-classes aren't confused by it being set by calling
+               // their parent initialize method
+               this.initialized = true;
+       }
 
        // Return existing promise if already loading or loaded
        if ( this.loading ) {
@@ -859,1032 +2072,1058 @@ OO.ui.Frame.prototype.load = function () {
        }
 
        // Load the frame
-       this.loading = $.Deferred();
-
-       win = this.$element.prop( 'contentWindow' );
-       doc = win.document;
-
-       // Figure out directionality:
-       this.dir = OO.ui.Element.getDir( this.$element ) || 'ltr';
+       loading = this.loading = $.Deferred();
+       sub = this.$iframe.prop( 'contentWindow' );
+       doc = sub.document;
 
        // Initialize contents
        doc.open();
        doc.write(
                '<!doctype html>' +
                '<html>' +
-                       '<body class="oo-ui-frame-body oo-ui-' + this.dir + '" style="direction:' + this.dir + ';" dir="' + this.dir + '">' +
-                               '<div class="oo-ui-frame-content"></div>' +
+                       '<body class="oo-ui-window-isolated oo-ui-' + this.dir + '"' +
+                               ' style="direction:' + this.dir + ';" dir="' + this.dir + '">' +
+                               '<div class="oo-ui-window-content"></div>' +
                        '</body>' +
                '</html>'
        );
        doc.close();
 
        // Properties
-       this.$ = OO.ui.Element.getJQuery( doc, this );
-       this.$content = this.$( '.oo-ui-frame-content' ).attr( 'tabIndex', 0 );
+       this.$ = OO.ui.Element.getJQuery( doc, this.$element );
+       this.$content = this.$( '.oo-ui-window-content' ).attr( 'tabIndex', 0 );
        this.$document = this.$( doc );
 
        // Initialization
        this.constructor.static.transplantStyles( this.getElementDocument(), this.$document[0] )
-               .always( OO.ui.bind( function () {
-                       this.emit( 'load' );
-                       this.loading.resolve();
-               }, this ) );
+               .always( function () {
+                       // Initialize isolated windows
+                       win.initialize();
+                       // Set initialized state after so sub-classes aren't confused by it being set by calling
+                       // their parent initialize method
+                       win.initialized = true;
+                       // Undo the visibility: hidden; hack and apply display: none;
+                       // We can do this safely now that the iframe has initialized
+                       // (don't do this from within #initialize because it has to happen
+                       // after the all subclasses have been handled as well).
+                       win.toggle( win.isVisible() );
 
-       return this.loading.promise();
-};
+                       loading.resolve();
+               } );
 
-/**
- * Set the size of the frame.
- *
- * @param {number} width Frame width in pixels
- * @param {number} height Frame height in pixels
- * @chainable
- */
-OO.ui.Frame.prototype.setSize = function ( width, height ) {
-       this.$element.css( { 'width': width, 'height': height } );
-       return this;
+       return loading.promise();
 };
 
 /**
- * Container for elements in a child frame.
+ * Base class for all dialogs.
+ *
+ * Logic:
+ * - Manage the window (open and close, etc.).
+ * - Store the internal name and display title.
+ * - A stack to track one or more pending actions.
+ * - Manage a set of actions that can be performed.
+ * - Configure and create action widgets.
+ *
+ * User interface:
+ * - Close the dialog with Escape key.
+ * - Visually lock the dialog while an action is in
+ *   progress (aka "pending").
  *
- * There are two ways to specify a title: set the static `title` property or provide a `title`
- * property in the configuration options. The latter will override the former.
+ * Subclass responsibilities:
+ * - Display the title somewhere.
+ * - Add content to the dialog.
+ * - Provide a UI to close the dialog.
+ * - Display the action widgets somewhere.
  *
  * @abstract
  * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
+ * @extends OO.ui.Window
+ * @mixins OO.ui.PendingElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {string|Function} [title] Title string or function that returns a string
- * @cfg {string} [icon] Symbolic name of icon
- * @fires initialize
  */
-OO.ui.Window = function OoUiWindow( config ) {
-       var element = this;
+OO.ui.Dialog = function OoUiDialog( config ) {
        // Parent constructor
-       OO.ui.Window.super.call( this, config );
+       OO.ui.Dialog.super.call( this, config );
 
        // Mixin constructors
-       OO.EventEmitter.call( this );
+       OO.ui.PendingElement.call( this );
 
        // Properties
-       this.visible = false;
-       this.opening = null;
-       this.closing = null;
-       this.opened = null;
-       this.title = OO.ui.resolveMsg( config.title || this.constructor.static.title );
-       this.icon = config.icon || this.constructor.static.icon;
-       this.frame = new OO.ui.Frame( { '$': this.$ } );
-       this.$frame = this.$( '<div>' );
-       this.$ = function () {
-               throw new Error( 'this.$() cannot be used until the frame has been initialized.' );
-       };
-
-       // Initialization
-       this.$element
-               .addClass( 'oo-ui-window' )
-               // Hide the window using visibility: hidden; while the iframe is still loading
-               // Can't use display: none; because that prevents the iframe from loading in Firefox
-               .css( 'visibility', 'hidden' )
-               .append( this.$frame );
-       this.$frame
-               .addClass( 'oo-ui-window-frame' )
-               .append( this.frame.$element );
+       this.actions = new OO.ui.ActionSet();
+       this.attachedActions = [];
+       this.currentAction = null;
 
        // Events
-       this.frame.on( 'load', function () {
-               element.initialize();
-               // Undo the visibility: hidden; hack and apply display: none;
-               // We can do this safely now that the iframe has initialized
-               // (don't do this from within #initialize because it has to happen
-               // after the all subclasses have been handled as well).
-               element.$element.hide().css( 'visibility', '' );
+       this.actions.connect( this, {
+               click: 'onActionClick',
+               resize: 'onActionResize',
+               change: 'onActionsChange'
        } );
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-dialog' )
+               .attr( 'role', 'dialog' );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.Window, OO.ui.Element );
-OO.mixinClass( OO.ui.Window, OO.EventEmitter );
-
-/* Events */
-
-/**
- * Window is setup.
- *
- * Fired after the setup process has been executed.
- *
- * @event setup
- * @param {Object} data Window opening data
- */
-
-/**
- * Window is ready.
- *
- * Fired after the ready process has been executed.
- *
- * @event ready
- * @param {Object} data Window opening data
- */
-
-/**
- * Window is torn down
- *
- * Fired after the teardown process has been executed.
- *
- * @event teardown
- * @param {Object} data Window closing data
- */
+OO.inheritClass( OO.ui.Dialog, OO.ui.Window );
+OO.mixinClass( OO.ui.Dialog, OO.ui.PendingElement );
 
 /* Static Properties */
 
 /**
- * Symbolic name of icon.
+ * Symbolic name of dialog.
  *
+ * @abstract
  * @static
  * @inheritable
  * @property {string}
  */
-OO.ui.Window.static.icon = 'window';
+OO.ui.Dialog.static.name = '';
 
 /**
- * Window title.
- *
- * Subclasses must implement this property before instantiating the window.
- * Alternatively, override #getTitle with an alternative implementation.
+ * Dialog title.
  *
- * @static
  * @abstract
+ * @static
  * @inheritable
- * @property {string|Function} Title string or function that returns a string
- */
-OO.ui.Window.static.title = null;
-
-/* Methods */
-
-/**
- * Check if window is visible.
- *
- * @return {boolean} Window is visible
- */
-OO.ui.Window.prototype.isVisible = function () {
-       return this.visible;
-};
-
-/**
- * Check if window is opening.
- *
- * @return {boolean} Window is opening
- */
-OO.ui.Window.prototype.isOpening = function () {
-       return !!this.opening && this.opening.state() === 'pending';
-};
-
-/**
- * Check if window is closing.
- *
- * @return {boolean} Window is closing
- */
-OO.ui.Window.prototype.isClosing = function () {
-       return !!this.closing && this.closing.state() === 'pending';
-};
-
-/**
- * Check if window is opened.
- *
- * @return {boolean} Window is opened
+ * @property {jQuery|string|Function} Label nodes, text or a function that returns nodes or text
  */
-OO.ui.Window.prototype.isOpened = function () {
-       return !!this.opened && this.opened.state() === 'pending';
-};
+OO.ui.Dialog.static.title = '';
 
 /**
- * Get the window frame.
+ * List of OO.ui.ActionWidget configuration options.
  *
- * @return {OO.ui.Frame} Frame of window
+ * @static
+ * inheritable
+ * @property {Object[]}
  */
-OO.ui.Window.prototype.getFrame = function () {
-       return this.frame;
-};
+OO.ui.Dialog.static.actions = [];
 
 /**
- * Get the title of the window.
+ * Close dialog when the escape key is pressed.
  *
- * @return {string} Title text
+ * @static
+ * @abstract
+ * @inheritable
+ * @property {boolean}
  */
-OO.ui.Window.prototype.getTitle = function () {
-       return this.title;
-};
+OO.ui.Dialog.static.escapable = true;
 
-/**
- * Get the window icon.
- *
- * @return {string} Symbolic name of icon
- */
-OO.ui.Window.prototype.getIcon = function () {
-       return this.icon;
-};
+/* Methods */
 
 /**
- * Set the size of window frame.
+ * Handle frame document key down events.
  *
- * @param {number} [width=auto] Custom width
- * @param {number} [height=auto] Custom height
- * @chainable
+ * @param {jQuery.Event} e Key down event
  */
-OO.ui.Window.prototype.setSize = function ( width, height ) {
-       if ( !this.frame.$content ) {
-               return;
+OO.ui.Dialog.prototype.onDocumentKeyDown = function ( e ) {
+       if ( e.which === OO.ui.Keys.ESCAPE ) {
+               this.close();
+               return false;
        }
-
-       this.frame.$element.css( {
-               'width': width === undefined ? 'auto' : width,
-               'height': height === undefined ? 'auto' : height
-       } );
-
-       return this;
 };
 
 /**
- * Set the title of the window.
+ * Handle action resized events.
  *
- * @param {string|Function} title Title text or a function that returns text
- * @chainable
+ * @param {OO.ui.ActionWidget} action Action that was resized
  */
-OO.ui.Window.prototype.setTitle = function ( title ) {
-       this.title = OO.ui.resolveMsg( title );
-       if ( this.$title ) {
-               this.$title.text( title );
-       }
-       return this;
+OO.ui.Dialog.prototype.onActionResize = function () {
+       // Override in subclass
 };
 
 /**
- * Set the icon of the window.
+ * Handle action click events.
  *
- * @param {string} icon Symbolic name of icon
- * @chainable
+ * @param {OO.ui.ActionWidget} action Action that was clicked
  */
-OO.ui.Window.prototype.setIcon = function ( icon ) {
-       if ( this.$icon ) {
-               this.$icon.removeClass( 'oo-ui-icon-' + this.icon );
+OO.ui.Dialog.prototype.onActionClick = function ( action ) {
+       if ( !this.isPending() ) {
+               this.currentAction = action;
+               this.executeAction( action.getAction() );
        }
-       this.icon = icon;
-       if ( this.$icon ) {
-               this.$icon.addClass( 'oo-ui-icon-' + this.icon );
-       }
-
-       return this;
-};
-
-/**
- * Set the position of window to fit with contents.
- *
- * @param {string} left Left offset
- * @param {string} top Top offset
- * @chainable
- */
-OO.ui.Window.prototype.setPosition = function ( left, top ) {
-       this.$element.css( { 'left': left, 'top': top } );
-       return this;
-};
-
-/**
- * Set the height of window to fit with contents.
- *
- * @param {number} [min=0] Min height
- * @param {number} [max] Max height (defaults to content's outer height)
- * @chainable
- */
-OO.ui.Window.prototype.fitHeightToContents = function ( min, max ) {
-       var height = this.frame.$content.outerHeight();
-
-       this.frame.$element.css(
-               'height', Math.max( min || 0, max === undefined ? height : Math.min( max, height ) )
-       );
-
-       return this;
 };
 
 /**
- * Set the width of window to fit with contents.
- *
- * @param {number} [min=0] Min height
- * @param {number} [max] Max height (defaults to content's outer width)
- * @chainable
+ * Handle actions change event.
  */
-OO.ui.Window.prototype.fitWidthToContents = function ( min, max ) {
-       var width = this.frame.$content.outerWidth();
-
-       this.frame.$element.css(
-               'width', Math.max( min || 0, max === undefined ? width : Math.min( max, width ) )
-       );
-
-       return this;
+OO.ui.Dialog.prototype.onActionsChange = function () {
+       this.detachActions();
+       if ( !this.isClosing() ) {
+               this.attachActions();
+       }
 };
 
 /**
- * Initialize window contents.
- *
- * The first time the window is opened, #initialize is called when it's safe to begin populating
- * its contents. See #setup for a way to make changes each time the window opens.
- *
- * Once this method is called, this.$$ can be used to create elements within the frame.
+ * Get set of actions.
  *
- * @chainable
+ * @return {OO.ui.ActionSet}
  */
-OO.ui.Window.prototype.initialize = function () {
-       // Properties
-       this.$ = this.frame.$;
-       this.$title = this.$( '<div class="oo-ui-window-title"></div>' )
-               .text( this.title );
-       this.$icon = this.$( '<div class="oo-ui-window-icon"></div>' )
-               .addClass( 'oo-ui-icon-' + this.icon );
-       this.$head = this.$( '<div class="oo-ui-window-head"></div>' );
-       this.$body = this.$( '<div class="oo-ui-window-body"></div>' );
-       this.$foot = this.$( '<div class="oo-ui-window-foot"></div>' );
-       this.$overlay = this.$( '<div class="oo-ui-window-overlay"></div>' );
-
-       // Initialization
-       this.frame.$content.append(
-               this.$head.append( this.$icon, this.$title ),
-               this.$body,
-               this.$foot,
-               this.$overlay
-       );
-
-       return this;
+OO.ui.Dialog.prototype.getActions = function () {
+       return this.actions;
 };
 
 /**
- * Get a process for setting up a window for use.
- *
- * Each time the window is opened this process will set it up for use in a particular context, based
- * on the `data` argument.
+ * Get a process for taking action.
  *
- * When you override this method, you can add additional setup steps to the process the parent
+ * When you override this method, you can add additional accept steps to the process the parent
  * method provides using the 'first' and 'next' methods.
  *
  * @abstract
- * @param {Object} [data] Window opening data
- * @return {OO.ui.Process} Setup process
+ * @param {string} [action] Symbolic name of action
+ * @return {OO.ui.Process} Action process
  */
-OO.ui.Window.prototype.getSetupProcess = function () {
-       return new OO.ui.Process();
+OO.ui.Dialog.prototype.getActionProcess = function ( action ) {
+       return new OO.ui.Process()
+               .next( function () {
+                       if ( !action ) {
+                               // An empty action always closes the dialog without data, which should always be
+                               // safe and make no changes
+                               this.close();
+                       }
+               }, this );
 };
 
 /**
- * Get a process for readying a window for use.
- *
- * Each time the window is open and setup, this process will ready it up for use in a particular
- * context, based on the `data` argument.
- *
- * When you override this method, you can add additional setup steps to the process the parent
- * method provides using the 'first' and 'next' methods.
+ * @inheritdoc
  *
- * @abstract
- * @param {Object} [data] Window opening data
- * @return {OO.ui.Process} Setup process
+ * @param {Object} [data] Dialog opening data
+ * @param {jQuery|string|Function|null} [data.label] Dialog label, omit to use #static-label
+ * @param {Object[]} [data.actions] List of OO.ui.ActionWidget configuration options for each
+ *   action item, omit to use #static-actions
  */
-OO.ui.Window.prototype.getReadyProcess = function () {
-       return new OO.ui.Process();
-};
+OO.ui.Dialog.prototype.getSetupProcess = function ( data ) {
+       data = data || {};
 
-/**
- * Get a process for tearing down a window after use.
- *
- * Each time the window is closed this process will tear it down and do something with the user's
- * interactions within the window, based on the `data` argument.
- *
- * When you override this method, you can add additional teardown steps to the process the parent
- * method provides using the 'first' and 'next' methods.
- *
- * @abstract
- * @param {Object} [data] Window closing data
- * @return {OO.ui.Process} Teardown process
+       // Parent method
+       return OO.ui.Dialog.super.prototype.getSetupProcess.call( this, data )
+               .next( function () {
+                       var i, len,
+                               items = [],
+                               config = this.constructor.static,
+                               actions = data.actions !== undefined ? data.actions : config.actions;
+
+                       this.title.setLabel(
+                               data.title !== undefined ? data.title : this.constructor.static.title
+                       );
+                       for ( i = 0, len = actions.length; i < len; i++ ) {
+                               items.push(
+                                       new OO.ui.ActionWidget( $.extend( { $: this.$ }, actions[i] ) )
+                               );
+                       }
+                       this.actions.add( items );
+               }, this );
+};
+
+/**
+ * @inheritdoc
  */
-OO.ui.Window.prototype.getTeardownProcess = function () {
-       return new OO.ui.Process();
+OO.ui.Dialog.prototype.getTeardownProcess = function ( data ) {
+       // Parent method
+       return OO.ui.Dialog.super.prototype.getTeardownProcess.call( this, data )
+               .first( function () {
+                       this.actions.clear();
+                       this.currentAction = null;
+               }, this );
 };
 
 /**
- * Open window.
- *
- * Do not override this method. Use #getSetupProcess to do something each time the window closes.
- *
- * @param {Object} [data] Window opening data
- * @fires initialize
- * @fires opening
- * @fires open
- * @fires ready
- * @return {jQuery.Promise} Promise resolved when window is opened; when the promise is resolved the
- *   first argument will be a promise which will be resolved when the window begins closing
+ * @inheritdoc
  */
-OO.ui.Window.prototype.open = function ( data ) {
-       // Return existing promise if already opening or open
-       if ( this.opening ) {
-               return this.opening.promise();
-       }
+OO.ui.Dialog.prototype.initialize = function () {
+       // Parent method
+       OO.ui.Dialog.super.prototype.initialize.call( this );
 
-       // Open the window
-       this.opening = $.Deferred();
+       // Properties
+       this.title = new OO.ui.LabelWidget( { $: this.$ } );
 
-       this.$ariaHidden = $( 'body' ).children().not( this.$element.parentsUntil( 'body' ).last() )
-               .attr( 'aria-hidden', '' );
+       // Events
+       if ( this.constructor.static.escapable ) {
+               this.$document.on( 'keydown', OO.ui.bind( this.onDocumentKeyDown, this ) );
+       }
 
-       this.frame.load().done( OO.ui.bind( function () {
-               this.$element.show();
-               this.visible = true;
-               this.getSetupProcess( data ).execute().done( OO.ui.bind( function () {
-                       this.$element.addClass( 'oo-ui-window-setup' );
-                       this.emit( 'setup', data );
-                       setTimeout( OO.ui.bind( function () {
-                               this.frame.$content.focus();
-                               this.getReadyProcess( data ).execute().done( OO.ui.bind( function () {
-                                       this.$element.addClass( 'oo-ui-window-ready' );
-                                       this.emit( 'ready', data );
-                                       this.opened = $.Deferred();
-                                       // Now that we are totally done opening, it's safe to allow closing
-                                       this.closing = null;
-                                       this.opening.resolve( this.opened.promise() );
-                               }, this ) );
-                       }, this ) );
-               }, this ) );
-       }, this ) );
+       // Initialization
+       this.$content.addClass( 'oo-ui-dialog-content' );
+       this.setPendingElement( this.$head );
+};
 
-       return this.opening.promise();
+/**
+ * Attach action actions.
+ */
+OO.ui.Dialog.prototype.attachActions = function () {
+       // Remember the list of potentially attached actions
+       this.attachedActions = this.actions.get();
 };
 
 /**
- * Close window.
- *
- * Do not override this method. Use #getTeardownProcess to do something each time the window closes.
+ * Detach action actions.
  *
- * @param {Object} [data] Window closing data
- * @fires closing
- * @fires close
- * @return {jQuery.Promise} Promise resolved when window is closed
+ * @chainable
  */
-OO.ui.Window.prototype.close = function ( data ) {
-       var close;
+OO.ui.Dialog.prototype.detachActions = function () {
+       var i, len;
 
-       // Return existing promise if already closing or closed
-       if ( this.closing ) {
-               return this.closing.promise();
+       // Detach all actions that may have been previously attached
+       for ( i = 0, len = this.attachedActions.length; i < len; i++ ) {
+               this.attachedActions[i].$element.detach();
        }
+       this.attachedActions = [];
+};
 
-       // Close after opening is done if opening is in progress
-       if ( this.opening && this.opening.state() === 'pending' ) {
-               close = OO.ui.bind( function () {
-                       return this.close( data );
-               }, this );
-               return this.opening.then( close, close );
-       }
-
-       // Close the window
-       // This.closing needs to exist before we emit the closing event so that handlers can call
-       // window.close() and trigger the safety check above
-       this.closing = $.Deferred();
-       this.frame.$content.find( ':focus' ).blur();
-       this.$element.removeClass( 'oo-ui-window-ready' );
-       this.getTeardownProcess( data ).execute().done( OO.ui.bind( function () {
-               this.$element.removeClass( 'oo-ui-window-setup' );
-               this.emit( 'teardown', data );
-               // To do something different with #opened, resolve/reject #opened in the teardown process
-               if ( this.opened && this.opened.state() === 'pending' ) {
-                       this.opened.resolve();
-               }
-               this.$element.hide();
-               if ( this.$ariaHidden ) {
-                       this.$ariaHidden.removeAttr( 'aria-hidden' );
-                       this.$ariaHidden = undefined;
-               }
-               this.visible = false;
-               this.closing.resolve();
-               // Now that we are totally done closing, it's safe to allow opening
-               this.opening = null;
-       }, this ) );
-
-       return this.closing.promise();
+/**
+ * Execute an action.
+ *
+ * @param {string} action Symbolic name of action to execute
+ * @return {jQuery.Promise} Promise resolved when action completes, rejected if it fails
+ */
+OO.ui.Dialog.prototype.executeAction = function ( action ) {
+       this.pushPending();
+       return this.getActionProcess( action ).execute()
+               .always( OO.ui.bind( this.popPending, this ) );
 };
 
 /**
- * Set of mutually exclusive windows.
+ * Collection of windows.
  *
  * @class
  * @extends OO.ui.Element
  * @mixins OO.EventEmitter
  *
+ * Managed windows are mutually exclusive. If a window is opened while there is a current window
+ * already opening or opened, the current window will be closed without data. Empty closing data
+ * should always result in the window being closed without causing constructive or destructive
+ * action.
+ *
+ * As a window is opened and closed, it passes through several stages and the manager emits several
+ * corresponding events.
+ *
+ * - {@link #openWindow} or {@link OO.ui.Window#open} methods are used to start opening
+ * - {@link #event-opening} is emitted with `opening` promise
+ * - {@link #getSetupDelay} is called the returned value is used to time a pause in execution
+ * - {@link OO.ui.Window#getSetupProcess} method is called on the window and its result executed
+ * - `setup` progress notification is emitted from opening promise
+ * - {@link #getReadyDelay} is called the returned value is used to time a pause in execution
+ * - {@link OO.ui.Window#getReadyProcess} method is called on the window and its result executed
+ * - `ready` progress notification is emitted from opening promise
+ * - `opening` promise is resolved with `opened` promise
+ * - Window is now open
+ *
+ * - {@link #closeWindow} or {@link OO.ui.Window#close} methods are used to start closing
+ * - `opened` promise is resolved with `closing` promise
+ * - {@link #event-closing} is emitted with `closing` promise
+ * - {@link #getHoldDelay} is called the returned value is used to time a pause in execution
+ * - {@link OO.ui.Window#getHoldProcess} method is called on the window and its result executed
+ * - `hold` progress notification is emitted from opening promise
+ * - {@link #getTeardownDelay} is called the returned value is used to time a pause in execution
+ * - {@link OO.ui.Window#getTeardownProcess} method is called on the window and its result executed
+ * - `teardown` progress notification is emitted from opening promise
+ * - Closing promise is resolved
+ * - Window is now closed
+ *
  * @constructor
- * @param {OO.Factory} factory Window factory
  * @param {Object} [config] Configuration options
+ * @cfg {boolean} [isolate] Configure managed windows to isolate their content using inline frames
+ * @cfg {OO.Factory} [factory] Window factory to use for automatic instantiation
+ * @cfg {boolean} [modal=true] Prevent interaction outside the dialog
  */
-OO.ui.WindowSet = function OoUiWindowSet( factory, config ) {
+OO.ui.WindowManager = function OoUiWindowManager( config ) {
+       // Configuration initialization
+       config = config || {};
+
        // Parent constructor
-       OO.ui.WindowSet.super.call( this, config );
+       OO.ui.WindowManager.super.call( this, config );
 
        // Mixin constructors
        OO.EventEmitter.call( this );
 
        // Properties
-       this.factory = factory;
-
-       /**
-        * List of all windows associated with this window set.
-        *
-        * @property {OO.ui.Window[]}
-        */
-       this.windowList = [];
-
-       /**
-        * Mapping of OO.ui.Window objects created by name from the #factory.
-        *
-        * @property {Object}
-        */
+       this.factory = config.factory;
+       this.modal = config.modal === undefined || !!config.modal;
+       this.isolate = !!config.isolate;
        this.windows = {};
+       this.opening = null;
+       this.opened = null;
+       this.closing = null;
+       this.preparingToOpen = null;
+       this.preparingToClose = null;
+       this.size = null;
        this.currentWindow = null;
+       this.$ariaHidden = null;
+       this.requestedSize = null;
+       this.onWindowResizeTimeout = null;
+       this.onWindowResizeHandler = OO.ui.bind( this.onWindowResize, this );
+       this.afterWindowResizeHandler = OO.ui.bind( this.afterWindowResize, this );
+       this.onWindowMouseWheelHandler = OO.ui.bind( this.onWindowMouseWheel, this );
+       this.onDocumentKeyDownHandler = OO.ui.bind( this.onDocumentKeyDown, this );
 
        // Initialization
-       this.$element.addClass( 'oo-ui-windowSet' );
+       this.$element
+               .addClass( 'oo-ui-windowManager' )
+               .toggleClass( 'oo-ui-windowManager-modal', this.modal );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.WindowSet, OO.ui.Element );
-OO.mixinClass( OO.ui.WindowSet, OO.EventEmitter );
+OO.inheritClass( OO.ui.WindowManager, OO.ui.Element );
+OO.mixinClass( OO.ui.WindowManager, OO.EventEmitter );
 
 /* Events */
 
 /**
- * @event setup
- * @param {OO.ui.Window} win Window that's been setup
- * @param {Object} config Window opening information
+ * Window is opening.
+ *
+ * Fired when the window begins to be opened.
+ *
+ * @event opening
+ * @param {OO.ui.Window} win Window that's being opened
+ * @param {jQuery.Promise} opening Promise resolved when window is opened; when the promise is
+ *   resolved the first argument will be a promise which will be resolved when the window begins
+ *   closing, the second argument will be the opening data; progress notifications will be fired on
+ *   the promise for `setup` and `ready` when those processes are completed respectively.
+ * @param {Object} data Window opening data
+ */
+
+/**
+ * Window is closing.
+ *
+ * Fired when the window begins to be closed.
+ *
+ * @event closing
+ * @param {OO.ui.Window} win Window that's being closed
+ * @param {jQuery.Promise} opening Promise resolved when window is closed; when the promise
+ *   is resolved the first argument will be a the closing data; progress notifications will be fired
+ *   on the promise for `hold` and `teardown` when those processes are completed respectively.
+ * @param {Object} data Window closing data
  */
 
+/* Static Properties */
+
 /**
- * @event ready
- * @param {OO.ui.Window} win Window that's ready
- * @param {Object} config Window opening information
+ * Map of symbolic size names and CSS properties.
+ *
+ * @static
+ * @inheritable
+ * @property {Object}
  */
+OO.ui.WindowManager.static.sizes = {
+       small: {
+               width: 300
+       },
+       medium: {
+               width: 500
+       },
+       large: {
+               width: 700
+       },
+       full: {
+               // These can be non-numeric because they are never used in calculations
+               width: '100%',
+               height: '100%'
+       }
+};
 
 /**
- * @event teardown
- * @param {OO.ui.Window} win Window that's been torn down
- * @param {Object} config Window closing information
+ * Symbolic name of default size.
+ *
+ * Default size is used if the window's requested size is not recognized.
+ *
+ * @static
+ * @inheritable
+ * @property {string}
  */
+OO.ui.WindowManager.static.defaultSize = 'medium';
 
 /* Methods */
 
 /**
- * Handle a window setup event.
+ * Handle window resize events.
  *
- * @param {OO.ui.Window} win Window that's been setup
- * @param {Object} [config] Window opening information
- * @fires setup
+ * @param {jQuery.Event} e Window resize event
  */
-OO.ui.WindowSet.prototype.onWindowSetup = function ( win, config ) {
-       if ( this.currentWindow && this.currentWindow !== win ) {
-               this.currentWindow.close();
-       }
-       this.currentWindow = win;
-       this.emit( 'setup', win, config );
+OO.ui.WindowManager.prototype.onWindowResize = function () {
+       clearTimeout( this.onWindowResizeTimeout );
+       this.onWindowResizeTimeout = setTimeout( this.afterWindowResizeHandler, 200 );
 };
 
 /**
- * Handle a window ready event.
+ * Handle window resize events.
  *
- * @param {OO.ui.Window} win Window that's ready
- * @param {Object} [config] Window opening information
- * @fires ready
+ * @param {jQuery.Event} e Window resize event
  */
-OO.ui.WindowSet.prototype.onWindowReady = function ( win, config ) {
-       this.emit( 'ready', win, config );
+OO.ui.WindowManager.prototype.afterWindowResize = function () {
+       if ( this.currentWindow ) {
+               this.updateWindowSize( this.currentWindow );
+       }
 };
 
 /**
- * Handle a window teardown event.
+ * Handle window mouse wheel events.
  *
- * @param {OO.ui.Window} win Window that's been torn down
- * @param {Object} [config] Window closing information
- * @fires teardown
+ * @param {jQuery.Event} e Mouse wheel event
  */
-OO.ui.WindowSet.prototype.onWindowTeardown = function ( win, config ) {
-       this.currentWindow = null;
-       this.emit( 'teardown', win, config );
+OO.ui.WindowManager.prototype.onWindowMouseWheel = function () {
+       return false;
 };
 
 /**
- * Get the current window.
+ * Handle document key down events.
  *
- * @return {OO.ui.Window|null} Current window or null if none open
+ * @param {jQuery.Event} e Key down event
  */
-OO.ui.WindowSet.prototype.getCurrentWindow = function () {
-       return this.currentWindow;
+OO.ui.WindowManager.prototype.onDocumentKeyDown = function ( e ) {
+       switch ( e.which ) {
+               case OO.ui.Keys.PAGEUP:
+               case OO.ui.Keys.PAGEDOWN:
+               case OO.ui.Keys.END:
+               case OO.ui.Keys.HOME:
+               case OO.ui.Keys.LEFT:
+               case OO.ui.Keys.UP:
+               case OO.ui.Keys.RIGHT:
+               case OO.ui.Keys.DOWN:
+                       // Prevent any key events that might cause scrolling
+                       return false;
+       }
 };
 
 /**
- * Return a given window.
+ * Check if window is opening.
  *
- * @param {string} name Symbolic name of window
- * @return {OO.ui.Window} Window with specified name
+ * @return {boolean} Window is opening
  */
-OO.ui.WindowSet.prototype.getWindow = function ( name ) {
-       var win;
-
-       if ( !this.factory.lookup( name ) ) {
-               throw new Error( 'Unknown window: ' + name );
-       }
-       if ( !( name in this.windows ) ) {
-               win = this.windows[name] = this.createWindow( name );
-               this.addWindow( win );
-       }
-       return this.windows[name];
+OO.ui.WindowManager.prototype.isOpening = function ( win ) {
+       return win === this.currentWindow && !!this.opening && this.opening.state() === 'pending';
 };
 
 /**
- * Create a window for use in this window set.
+ * Check if window is closing.
  *
- * @param {string} name Symbolic name of window
- * @return {OO.ui.Window} Window with specified name
+ * @return {boolean} Window is closing
  */
-OO.ui.WindowSet.prototype.createWindow = function ( name ) {
-       return this.factory.create( name, { '$': this.$ } );
+OO.ui.WindowManager.prototype.isClosing = function ( win ) {
+       return win === this.currentWindow && !!this.closing && this.closing.state() === 'pending';
 };
 
 /**
- * Add a given window to this window set.
- *
- * Connects event handlers and attaches it to the DOM. Calling
- * OO.ui.Window#open will not work until the window is added to the set.
+ * Check if window is opened.
  *
- * @param {OO.ui.Window} win Window to add
+ * @return {boolean} Window is opened
  */
-OO.ui.WindowSet.prototype.addWindow = function ( win ) {
-       if ( this.windowList.indexOf( win ) !== -1 ) {
-               // Already set up
-               return;
-       }
-       this.windowList.push( win );
-
-       win.connect( this, {
-               'setup': [ 'onWindowSetup', win ],
-               'ready': [ 'onWindowReady', win ],
-               'teardown': [ 'onWindowTeardown', win ]
-       } );
-       this.$element.append( win.$element );
+OO.ui.WindowManager.prototype.isOpened = function ( win ) {
+       return win === this.currentWindow && !!this.opened && this.opened.state() === 'pending';
 };
 
 /**
- * Modal dialog window.
+ * Check if window contents should be isolated.
  *
- * @abstract
- * @class
- * @extends OO.ui.Window
+ * Window content isolation is done using inline frames.
  *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [footless] Hide foot
- * @cfg {string} [size='large'] Symbolic name of dialog size, `small`, `medium` or `large`
+ * @return {boolean} Window contents should be isolated
  */
-OO.ui.Dialog = function OoUiDialog( config ) {
-       // Configuration initialization
-       config = $.extend( { 'size': 'large' }, config );
-
-       // Parent constructor
-       OO.ui.Dialog.super.call( this, config );
-
-       // Properties
-       this.visible = false;
-       this.footless = !!config.footless;
-       this.size = null;
-       this.pending = 0;
-       this.onWindowMouseWheelHandler = OO.ui.bind( this.onWindowMouseWheel, this );
-       this.onDocumentKeyDownHandler = OO.ui.bind( this.onDocumentKeyDown, this );
-
-       // Events
-       this.$element.on( 'mousedown', false );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-dialog' ).attr( 'role', 'dialog' );
-       this.setSize( config.size );
+OO.ui.WindowManager.prototype.shouldIsolate = function () {
+       return this.isolate;
 };
 
-/* Setup */
+/**
+ * Check if a window is being managed.
+ *
+ * @param {OO.ui.Window} win Window to check
+ * @return {boolean} Window is being managed
+ */
+OO.ui.WindowManager.prototype.hasWindow = function ( win ) {
+       var name;
 
-OO.inheritClass( OO.ui.Dialog, OO.ui.Window );
+       for ( name in this.windows ) {
+               if ( this.windows[name] === win ) {
+                       return true;
+               }
+       }
 
-/* Static Properties */
+       return false;
+};
 
 /**
- * Symbolic name of dialog.
+ * Get the number of milliseconds to wait between beginning opening and executing setup process.
  *
- * @abstract
- * @static
- * @inheritable
- * @property {string}
+ * @param {OO.ui.Window} win Window being opened
+ * @param {Object} [data] Window opening data
+ * @return {number} Milliseconds to wait
  */
-OO.ui.Dialog.static.name = '';
+OO.ui.WindowManager.prototype.getSetupDelay = function () {
+       return 0;
+};
 
 /**
- * Map of symbolic size names and CSS classes.
+ * Get the number of milliseconds to wait between finishing setup and executing ready process.
  *
- * @static
- * @inheritable
- * @property {Object}
+ * @param {OO.ui.Window} win Window being opened
+ * @param {Object} [data] Window opening data
+ * @return {number} Milliseconds to wait
  */
-OO.ui.Dialog.static.sizeCssClasses = {
-       'small': 'oo-ui-dialog-small',
-       'medium': 'oo-ui-dialog-medium',
-       'large': 'oo-ui-dialog-large'
+OO.ui.WindowManager.prototype.getReadyDelay = function () {
+       return 0;
 };
 
-/* Methods */
-
 /**
- * Handle close button click events.
+ * Get the number of milliseconds to wait between beginning closing and executing hold process.
+ *
+ * @param {OO.ui.Window} win Window being closed
+ * @param {Object} [data] Window closing data
+ * @return {number} Milliseconds to wait
  */
-OO.ui.Dialog.prototype.onCloseButtonClick = function () {
-       this.close( { 'action': 'cancel' } );
+OO.ui.WindowManager.prototype.getHoldDelay = function () {
+       return 0;
 };
 
 /**
- * Handle window mouse wheel events.
+ * Get the number of milliseconds to wait between finishing hold and executing teardown process.
  *
- * @param {jQuery.Event} e Mouse wheel event
+ * @param {OO.ui.Window} win Window being closed
+ * @param {Object} [data] Window closing data
+ * @return {number} Milliseconds to wait
  */
-OO.ui.Dialog.prototype.onWindowMouseWheel = function () {
-       return false;
+OO.ui.WindowManager.prototype.getTeardownDelay = function () {
+       return this.modal ? 250 : 0;
 };
 
 /**
- * Handle document key down events.
+ * Get managed window by symbolic name.
  *
- * @param {jQuery.Event} e Key down event
+ * If window is not yet instantiated, it will be instantiated and added automatically.
+ *
+ * @param {string} name Symbolic window name
+ * @return {jQuery.Promise} Promise resolved with matching window, or rejected with an OO.ui.Error
+ * @throws {Error} If the symbolic name is unrecognized by the factory
+ * @throws {Error} If the symbolic name unrecognized as a managed window
  */
-OO.ui.Dialog.prototype.onDocumentKeyDown = function ( e ) {
-       switch ( e.which ) {
-               case OO.ui.Keys.PAGEUP:
-               case OO.ui.Keys.PAGEDOWN:
-               case OO.ui.Keys.END:
-               case OO.ui.Keys.HOME:
-               case OO.ui.Keys.LEFT:
-               case OO.ui.Keys.UP:
-               case OO.ui.Keys.RIGHT:
-               case OO.ui.Keys.DOWN:
-                       // Prevent any key events that might cause scrolling
-                       return false;
+OO.ui.WindowManager.prototype.getWindow = function ( name ) {
+       var deferred = $.Deferred(),
+               win = this.windows[name];
+
+       if ( !( win instanceof OO.ui.Window ) ) {
+               if ( this.factory ) {
+                       if ( !this.factory.lookup( name ) ) {
+                               deferred.reject( new OO.ui.Error(
+                                       'Cannot auto-instantiate window: symbolic name is unrecognized by the factory'
+                               ) );
+                       } else {
+                               win = this.factory.create( name, this, { $: this.$ } );
+                               this.addWindows( [ win ] );
+                               deferred.resolve( win );
+                       }
+               } else {
+                       deferred.reject( new OO.ui.Error(
+                               'Cannot get unmanaged window: symbolic name unrecognized as a managed window'
+                       ) );
+               }
+       } else {
+               deferred.resolve( win );
        }
+
+       return deferred.promise();
 };
 
 /**
- * Handle frame document key down events.
+ * Get current window.
  *
- * @param {jQuery.Event} e Key down event
+ * @return {OO.ui.Window|null} Currently opening/opened/closing window
  */
-OO.ui.Dialog.prototype.onFrameDocumentKeyDown = function ( e ) {
-       if ( e.which === OO.ui.Keys.ESCAPE ) {
-               this.close( { 'action': 'cancel' } );
-               return false;
-       }
+OO.ui.WindowManager.prototype.getCurrentWindow = function () {
+       return this.currentWindow;
 };
 
 /**
- * Set dialog size.
+ * Open a window.
  *
- * @param {string} [size='large'] Symbolic name of dialog size, `small`, `medium` or `large`
+ * @param {OO.ui.Window|string} win Window object or symbolic name of window to open
+ * @param {Object} [data] Window opening data
+ * @return {jQuery.Promise} Promise resolved when window is done opening; see {@link #event-opening}
+ *   for more details about the `opening` promise
+ * @fires opening
  */
-OO.ui.Dialog.prototype.setSize = function ( size ) {
-       var name, state, cssClass,
-               sizeCssClasses = OO.ui.Dialog.static.sizeCssClasses;
+OO.ui.WindowManager.prototype.openWindow = function ( win, data ) {
+       var manager = this,
+               preparing = [],
+               opening = $.Deferred();
+
+       // Argument handling
+       if ( typeof win === 'string' ) {
+               return this.getWindow( win ).then( function ( win ) {
+                       return manager.openWindow( win, data );
+               } );
+       }
+
+       // Error handling
+       if ( !this.hasWindow( win ) ) {
+               opening.reject( new OO.ui.Error(
+                       'Cannot open window: window is not attached to manager'
+               ) );
+       } else if ( this.preparingToOpen || this.opening || this.opened ) {
+               opening.reject( new OO.ui.Error(
+                       'Cannot open window: another window is opening or open'
+               ) );
+       }
+
+       // Window opening
+       if ( opening.state() !== 'rejected' ) {
+               // Begin loading the window if it's not loading or loaded already - may take noticable time
+               // and we want to do this in paralell with any other preparatory actions
+               if ( !win.isLoading() && !win.isLoaded() ) {
+                       // Finish initializing the window (must be done after manager is attached to DOM)
+                       win.setManager( this );
+                       preparing.push( win.load() );
+               }
 
-       if ( !sizeCssClasses[size] ) {
-               size = 'large';
-       }
-       this.size = size;
-       for ( name in sizeCssClasses ) {
-               state = name === size;
-               cssClass = sizeCssClasses[name];
-               this.$element.toggleClass( cssClass, state );
+               if ( this.closing ) {
+                       // If a window is currently closing, wait for it to complete
+                       preparing.push( this.closing );
+               }
+
+               this.preparingToOpen = $.when.apply( $, preparing );
+               // Ensure handlers get called after preparingToOpen is set
+               this.preparingToOpen.done( function () {
+                       if ( manager.modal ) {
+                               manager.toggleGlobalEvents( true );
+                               manager.toggleAriaIsolation( true );
+                       }
+                       manager.currentWindow = win;
+                       manager.opening = opening;
+                       manager.preparingToOpen = null;
+                       manager.emit( 'opening', win, opening, data );
+                       setTimeout( function () {
+                               win.setup( data ).then( function () {
+                                       manager.updateWindowSize( win );
+                                       manager.opening.notify( { state: 'setup' } );
+                                       setTimeout( function () {
+                                               win.ready( data ).then( function () {
+                                                       manager.updateWindowSize( win );
+                                                       manager.opening.notify( { state: 'ready' } );
+                                                       manager.opening = null;
+                                                       manager.opened = $.Deferred();
+                                                       opening.resolve( manager.opened.promise(), data );
+                                               } );
+                                       }, manager.getReadyDelay() );
+                               } );
+                       }, manager.getSetupDelay() );
+               } );
        }
+
+       return opening.promise();
 };
 
 /**
- * @inheritdoc
+ * Close a window.
+ *
+ * @param {OO.ui.Window|string} win Window object or symbolic name of window to close
+ * @param {Object} [data] Window closing data
+ * @return {jQuery.Promise} Promise resolved when window is done closing; see {@link #event-closing}
+ *   for more details about the `closing` promise
+ * @throws {Error} If no window by that name is being managed
+ * @fires closing
  */
-OO.ui.Dialog.prototype.initialize = function () {
-       // Parent method
-       OO.ui.Dialog.super.prototype.initialize.call( this );
-
-       // Properties
-       this.closeButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'close',
-               'title': OO.ui.msg( 'ooui-dialog-action-close' )
-       } );
-
-       // Events
-       this.closeButton.connect( this, { 'click': 'onCloseButtonClick' } );
-       this.frame.$document.on( 'keydown', OO.ui.bind( this.onFrameDocumentKeyDown, this ) );
+OO.ui.WindowManager.prototype.closeWindow = function ( win, data ) {
+       var manager = this,
+               preparing = [],
+               closing = $.Deferred(),
+               opened = this.opened;
+
+       // Argument handling
+       if ( typeof win === 'string' ) {
+               win = this.windows[win];
+       } else if ( !this.hasWindow( win ) ) {
+               win = null;
+       }
+
+       // Error handling
+       if ( !win ) {
+               closing.reject( new OO.ui.Error(
+                       'Cannot close window: window is not attached to manager'
+               ) );
+       } else if ( win !== this.currentWindow ) {
+               closing.reject( new OO.ui.Error(
+                       'Cannot close window: window already closed with different data'
+               ) );
+       } else if ( this.preparingToClose || this.closing ) {
+               closing.reject( new OO.ui.Error(
+                       'Cannot close window: window already closing with different data'
+               ) );
+       }
+
+       // Window closing
+       if ( closing.state() !== 'rejected' ) {
+               if ( this.opening ) {
+                       // If the window is currently opening, close it when it's done
+                       preparing.push( this.opening );
+               }
 
-       // Initialization
-       this.frame.$content.addClass( 'oo-ui-dialog-content' );
-       if ( this.footless ) {
-               this.frame.$content.addClass( 'oo-ui-dialog-content-footless' );
+               this.preparingToClose = $.when.apply( $, preparing );
+               // Ensure handlers get called after preparingToClose is set
+               this.preparingToClose.done( function () {
+                       manager.closing = closing;
+                       manager.preparingToClose = null;
+                       manager.emit( 'closing', win, closing, data );
+                       manager.opened = null;
+                       opened.resolve( closing.promise(), data );
+                       setTimeout( function () {
+                               win.hold( data ).then( function () {
+                                       closing.notify( { state: 'hold' } );
+                                       setTimeout( function () {
+                                               win.teardown( data ).then( function () {
+                                                       closing.notify( { state: 'teardown' } );
+                                                       if ( manager.modal ) {
+                                                               manager.toggleGlobalEvents( false );
+                                                               manager.toggleAriaIsolation( false );
+                                                       }
+                                                       manager.closing = null;
+                                                       manager.currentWindow = null;
+                                                       closing.resolve( data );
+                                               } );
+                                       }, manager.getTeardownDelay() );
+                               } );
+                       }, manager.getHoldDelay() );
+               } );
        }
-       this.closeButton.$element.addClass( 'oo-ui-window-closeButton' );
-       this.$head.append( this.closeButton.$element );
+
+       return closing.promise();
 };
 
 /**
- * @inheritdoc
+ * Add windows.
+ *
+ * @param {Object.<string,OO.ui.Window>|OO.ui.Window[]} windows Windows to add
+ * @throws {Error} If one of the windows being added without an explicit symbolic name does not have
+ *   a statically configured symbolic name
  */
-OO.ui.Dialog.prototype.getSetupProcess = function ( data ) {
-       return OO.ui.Dialog.super.prototype.getSetupProcess.call( this, data )
-               .next( function () {
-                       // Prevent scrolling in top-level window
-                       this.$( window ).on( 'mousewheel', this.onWindowMouseWheelHandler );
-                       this.$( document ).on( 'keydown', this.onDocumentKeyDownHandler );
-               }, this );
+OO.ui.WindowManager.prototype.addWindows = function ( windows ) {
+       var i, len, win, name, list;
+
+       if ( $.isArray( windows ) ) {
+               // Convert to map of windows by looking up symbolic names from static configuration
+               list = {};
+               for ( i = 0, len = windows.length; i < len; i++ ) {
+                       name = windows[i].constructor.static.name;
+                       if ( typeof name !== 'string' ) {
+                               throw new Error( 'Cannot add window' );
+                       }
+                       list[name] = windows[i];
+               }
+       } else if ( $.isPlainObject( windows ) ) {
+               list = windows;
+       }
+
+       // Add windows
+       for ( name in list ) {
+               win = list[name];
+               this.windows[name] = win;
+               this.$element.append( win.$element );
+       }
 };
 
 /**
- * @inheritdoc
+ * Remove windows.
+ *
+ * Windows will be closed before they are removed.
+ *
+ * @param {string} name Symbolic name of window to remove
+ * @return {jQuery.Promise} Promise resolved when window is closed and removed
+ * @throws {Error} If windows being removed are not being managed
  */
-OO.ui.Dialog.prototype.getTeardownProcess = function ( data ) {
-       return OO.ui.Dialog.super.prototype.getTeardownProcess.call( this, data )
-               .first( function () {
-                       // Wait for closing transition
-                       return OO.ui.Process.static.delay( 250 );
-               }, this )
-               .next( function () {
-                       // Allow scrolling in top-level window
-                       this.$( window ).off( 'mousewheel', this.onWindowMouseWheelHandler );
-                       this.$( document ).off( 'keydown', this.onDocumentKeyDownHandler );
-               }, this );
+OO.ui.WindowManager.prototype.removeWindows = function ( names ) {
+       var i, len, win, name,
+               manager = this,
+               promises = [],
+               cleanup = function ( name, win ) {
+                       delete manager.windows[name];
+                       win.$element.detach();
+               };
+
+       for ( i = 0, len = names.length; i < len; i++ ) {
+               name = names[i];
+               win = this.windows[name];
+               if ( !win ) {
+                       throw new Error( 'Cannot remove window' );
+               }
+               promises.push( this.closeWindow( name ).then( OO.ui.bind( cleanup, null, name, win ) ) );
+       }
+
+       return $.when.apply( $, promises );
 };
 
 /**
- * Check if input is pending.
+ * Remove all windows.
  *
- * @return {boolean}
+ * Windows will be closed before they are removed.
+ *
+ * @return {jQuery.Promise} Promise resolved when all windows are closed and removed
  */
-OO.ui.Dialog.prototype.isPending = function () {
-       return !!this.pending;
+OO.ui.WindowManager.prototype.clearWindows = function () {
+       return this.removeWindows( Object.keys( this.windows ) );
 };
 
 /**
- * Increase the pending stack.
+ * Set dialog size.
+ *
+ * Fullscreen mode will be used if the dialog is too wide to fit in the screen.
  *
  * @chainable
  */
-OO.ui.Dialog.prototype.pushPending = function () {
-       if ( this.pending === 0 ) {
-               this.frame.$content.addClass( 'oo-ui-dialog-pending' );
-               this.$head.addClass( 'oo-ui-texture-pending' );
-               this.$foot.addClass( 'oo-ui-texture-pending' );
+OO.ui.WindowManager.prototype.updateWindowSize = function ( win ) {
+       // Bypass for non-current, and thus invisible, windows
+       if ( win !== this.currentWindow ) {
+               return;
        }
-       this.pending++;
+
+       var viewport = OO.ui.Element.getDimensions( win.getElementWindow() ),
+               sizes = this.constructor.static.sizes,
+               size = win.getSize();
+
+       if ( !sizes[size] ) {
+               size = this.constructor.static.defaultSize;
+       }
+       if ( size !== 'full' && viewport.rect.right - viewport.rect.left < sizes[size].width ) {
+               size = 'full';
+       }
+
+       this.$element.toggleClass( 'oo-ui-windowManager-fullscreen', size === 'full' );
+       this.$element.toggleClass( 'oo-ui-windowManager-floating', size !== 'full' );
+       win.setDimensions( sizes[size] );
 
        return this;
 };
 
 /**
- * Reduce the pending stack.
- *
- * Clamped at zero.
+ * Bind or unbind global events for scrolling.
  *
+ * @param {boolean} [on] Bind global events
  * @chainable
  */
-OO.ui.Dialog.prototype.popPending = function () {
-       if ( this.pending === 1 ) {
-               this.frame.$content.removeClass( 'oo-ui-dialog-pending' );
-               this.$head.removeClass( 'oo-ui-texture-pending' );
-               this.$foot.removeClass( 'oo-ui-texture-pending' );
+OO.ui.WindowManager.prototype.toggleGlobalEvents = function ( on ) {
+       on = on === undefined ? !!this.globalEvents : !!on;
+
+       if ( on ) {
+               if ( !this.globalEvents ) {
+                       this.$( this.getElementDocument() ).on( {
+                               // Prevent scrolling by keys in top-level window
+                               keydown: this.onDocumentKeyDownHandler
+                       } );
+                       this.$( this.getElementWindow() ).on( {
+                               // Prevent scrolling by wheel in top-level window
+                               mousewheel: this.onWindowMouseWheelHandler,
+                               // Start listening for top-level window dimension changes
+                               'orientationchange resize': this.onWindowResizeHandler
+                       } );
+                       this.globalEvents = true;
+               }
+       } else if ( this.globalEvents ) {
+               // Unbind global events
+               this.$( this.getElementDocument() ).off( {
+                       // Allow scrolling by keys in top-level window
+                       keydown: this.onDocumentKeyDownHandler
+               } );
+               this.$( this.getElementWindow() ).off( {
+                       // Allow scrolling by wheel in top-level window
+                       mousewheel: this.onWindowMouseWheelHandler,
+                       // Stop listening for top-level window dimension changes
+                       'orientationchange resize': this.onWindowResizeHandler
+               } );
+               this.globalEvents = false;
        }
-       this.pending = Math.max( 0, this.pending - 1 );
 
        return this;
 };
 
 /**
- * Container for elements.
- *
- * @abstract
- * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
+ * Toggle screen reader visibility of content other than the window manager.
  *
- * @constructor
- * @param {Object} [config] Configuration options
+ * @param {boolean} [isolate] Make only the window manager visible to screen readers
+ * @chainable
  */
-OO.ui.Layout = function OoUiLayout( config ) {
-       // Initialize config
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Layout.super.call( this, config );
+OO.ui.WindowManager.prototype.toggleAriaIsolation = function ( isolate ) {
+       isolate = isolate === undefined ? !this.$ariaHidden : !!isolate;
 
-       // Mixin constructors
-       OO.EventEmitter.call( this );
+       if ( isolate ) {
+               if ( !this.$ariaHidden ) {
+                       // Hide everything other than the window manager from screen readers
+                       this.$ariaHidden = $( 'body' )
+                               .children()
+                               .not( this.$element.parentsUntil( 'body' ).last() )
+                               .attr( 'aria-hidden', '' );
+               }
+       } else if ( this.$ariaHidden ) {
+               // Restore screen reader visiblity
+               this.$ariaHidden.removeAttr( 'aria-hidden' );
+               this.$ariaHidden = null;
+       }
 
-       // Initialization
-       this.$element.addClass( 'oo-ui-layout' );
+       return this;
 };
 
-/* Setup */
-
-OO.inheritClass( OO.ui.Layout, OO.ui.Element );
-OO.mixinClass( OO.ui.Layout, OO.EventEmitter );
-
 /**
- * User interface control.
+ * Destroy window manager.
  *
+ * Windows will not be closed, only removed from the DOM.
+ */
+OO.ui.WindowManager.prototype.destroy = function () {
+       this.toggleGlobalEvents( false );
+       this.toggleAriaIsolation( false );
+       this.$element.remove();
+};
+
+/**
  * @abstract
  * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
  *
  * @constructor
+ * @param {string|jQuery} message Description of error
  * @param {Object} [config] Configuration options
- * @cfg {boolean} [disabled=false] Disable
+ * @cfg {boolean} [recoverable=true] Error is recoverable
  */
-OO.ui.Widget = function OoUiWidget( config ) {
-       // Initialize config
-       config = $.extend( { 'disabled': false }, config );
-
-       // Parent constructor
-       OO.ui.Widget.super.call( this, config );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
+OO.ui.Error = function OoUiElement( message, config ) {
+       // Configuration initialization
+       config = config || {};
 
        // Properties
-       this.disabled = null;
-       this.wasDisabled = null;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-widget' );
-       this.setDisabled( !!config.disabled );
+       this.message = message instanceof jQuery ? message : String( message );
+       this.recoverable = config.recoverable === undefined || !!config.recoverable;
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.Widget, OO.ui.Element );
-OO.mixinClass( OO.ui.Widget, OO.EventEmitter );
-
-/* Events */
-
-/**
- * @event disable
- * @param {boolean} disabled Widget is disabled
- */
+OO.initClass( OO.ui.Error );
 
 /* Methods */
 
 /**
- * Check if the widget is disabled.
+ * Check if error can be recovered from.
  *
- * @param {boolean} Button is disabled
+ * @return {boolean} Error is recoverable
  */
-OO.ui.Widget.prototype.isDisabled = function () {
-       return this.disabled;
+OO.ui.Error.prototype.isRecoverable = function () {
+       return this.recoverable;
 };
 
 /**
- * Update the disabled state, in case of changes in parent widget.
+ * Get error message as DOM nodes.
  *
- * @chainable
+ * @return {jQuery} Error message in DOM nodes
  */
-OO.ui.Widget.prototype.updateDisabled = function () {
-       this.setDisabled( this.disabled );
-       return this;
+OO.ui.Error.prototype.getMessage = function () {
+       return this.message instanceof jQuery ?
+               this.message.clone() :
+               $( '<div>' ).text( this.message ).contents();
 };
 
 /**
- * Set the disabled state of the widget.
- *
- * This should probably change the widgets' appearance and prevent it from being used.
+ * Get error message as text.
  *
- * @param {boolean} disabled Disable widget
- * @chainable
+ * @return {string} Error message
  */
-OO.ui.Widget.prototype.setDisabled = function ( disabled ) {
-       var isDisabled;
-
-       this.disabled = !!disabled;
-       isDisabled = this.isDisabled();
-       if ( isDisabled !== this.wasDisabled ) {
-               this.$element.toggleClass( 'oo-ui-widget-disabled', isDisabled );
-               this.$element.toggleClass( 'oo-ui-widget-enabled', !isDisabled );
-               this.emit( 'disable', isDisabled );
-       }
-       this.wasDisabled = isDisabled;
-       return this;
+OO.ui.Error.prototype.getMessageText = function () {
+       return this.message instanceof jQuery ? this.message.text() : this.message;
 };
 
 /**
@@ -1897,34 +3136,26 @@ OO.ui.Widget.prototype.setDisabled = function ( disabled ) {
  * @class
  *
  * @constructor
+ * @param {number|jQuery.Promise|Function} step Time to wait, promise to wait for or function to
+ *   call, see #createStep for more information
+ * @param {Object} [context=null] Context to call the step function in, ignored if step is a number
+ *   or a promise
+ * @return {Object} Step object, with `callback` and `context` properties
  */
-OO.ui.Process = function () {
+OO.ui.Process = function ( step, context ) {
        // Properties
        this.steps = [];
+
+       // Initialization
+       if ( step !== undefined ) {
+               this.next( step, context );
+       }
 };
 
 /* Setup */
 
 OO.initClass( OO.ui.Process );
 
-/* Static Methods */
-
-/**
- * Generate a promise which is resolved after a set amount of time.
- *
- * @param {number} length Number of milliseconds before resolving the promise
- * @return {jQuery.Promise} Promise that will be resolved after a set amount of time
- */
-OO.ui.Process.static.delay = function ( length ) {
-       var deferred = $.Deferred();
-
-       setTimeout( function () {
-               deferred.resolve();
-       }, length );
-
-       return deferred.promise();
-};
-
 /* Methods */
 
 /**
@@ -1947,11 +3178,29 @@ OO.ui.Process.prototype.execute = function () {
        function proceed( step ) {
                return function () {
                        // Execute step in the correct context
-                       var result = step[0].call( step[1] );
+                       var deferred,
+                               result = step.callback.call( step.context );
 
                        if ( result === false ) {
                                // Use rejected promise for boolean false results
-                               return $.Deferred().reject().promise();
+                               return $.Deferred().reject( [] ).promise();
+                       }
+                       if ( typeof result === 'number' ) {
+                               if ( result < 0 ) {
+                                       throw new Error( 'Cannot go back in time: flux capacitor is out of service' );
+                               }
+                               // Use a delayed promise for numbers, expecting them to be in milliseconds
+                               deferred = $.Deferred();
+                               setTimeout( deferred.resolve, result );
+                               return deferred.promise();
+                       }
+                       if ( result instanceof OO.ui.Error ) {
+                               // Use rejected promise for error
+                               return $.Deferred().reject( [ result ] ).promise();
+                       }
+                       if ( $.isArray( result ) && result.length && result[0] instanceof OO.ui.Error ) {
+                               // Use rejected promise for list of errors
+                               return $.Deferred().reject( result ).promise();
                        }
                        // Duck-type the object to see if it can produce a promise
                        if ( result && $.isFunction( result.promise ) ) {
@@ -1976,185 +3225,258 @@ OO.ui.Process.prototype.execute = function () {
        return promise;
 };
 
+/**
+ * Create a process step.
+ *
+ * @private
+ * @param {number|jQuery.Promise|Function} step
+ *
+ * - Number of milliseconds to wait; or
+ * - Promise to wait to be resolved; or
+ * - Function to execute
+ *   - If it returns boolean false the process will stop
+ *   - If it returns an object with a `promise` method the process will use the promise to either
+ *     continue to the next step when the promise is resolved or stop when the promise is rejected
+ *   - If it returns a number, the process will wait for that number of milliseconds before
+ *     proceeding
+ * @param {Object} [context=null] Context to call the step function in, ignored if step is a number
+ *   or a promise
+ * @return {Object} Step object, with `callback` and `context` properties
+ */
+OO.ui.Process.prototype.createStep = function ( step, context ) {
+       if ( typeof step === 'number' || $.isFunction( step.promise ) ) {
+               return {
+                       callback: function () {
+                               return step;
+                       },
+                       context: null
+               };
+       }
+       if ( $.isFunction( step ) ) {
+               return {
+                       callback: step,
+                       context: context
+               };
+       }
+       throw new Error( 'Cannot create process step: number, promise or function expected' );
+};
+
 /**
  * Add step to the beginning of the process.
  *
- * @param {Function} step Function to execute; if it returns boolean false the process will stop; if
- *   it returns an object with a `promise` method the process will use the promise to either
- *   continue to the next step when the promise is resolved or stop when the promise is rejected
- * @param {Object} [context=null] Context to call the step function in
+ * @inheritdoc #createStep
+ * @return {OO.ui.Process} this
  * @chainable
  */
 OO.ui.Process.prototype.first = function ( step, context ) {
-       this.steps.unshift( [ step, context || null ] );
+       this.steps.unshift( this.createStep( step, context ) );
        return this;
 };
 
 /**
  * Add step to the end of the process.
  *
- * @param {Function} step Function to execute; if it returns boolean false the process will stop; if
- *   it returns an object with a `promise` method the process will use the promise to either
- *   continue to the next step when the promise is resolved or stop when the promise is rejected
- * @param {Object} [context=null] Context to call the step function in
+ * @inheritdoc #createStep
+ * @return {OO.ui.Process} this
  * @chainable
  */
 OO.ui.Process.prototype.next = function ( step, context ) {
-       this.steps.push( [ step, context || null ] );
+       this.steps.push( this.createStep( step, context ) );
        return this;
 };
 
 /**
- * Dialog for showing a confirmation/warning message.
+ * Factory for tools.
  *
  * @class
- * @extends OO.ui.Dialog
- *
+ * @extends OO.Factory
  * @constructor
- * @param {Object} [config] Configuration options
  */
-OO.ui.ConfirmationDialog = function OoUiConfirmationDialog( config ) {
-       // Configuration initialization
-       config = $.extend( { 'size': 'small' }, config );
-
+OO.ui.ToolFactory = function OoUiToolFactory() {
        // Parent constructor
-       OO.ui.Dialog.call( this, config );
+       OO.ui.ToolFactory.super.call( this );
 };
 
-/* Inheritance */
+/* Setup */
 
-OO.inheritClass( OO.ui.ConfirmationDialog, OO.ui.Dialog );
+OO.inheritClass( OO.ui.ToolFactory, OO.Factory );
 
-/* Static Properties */
+/* Methods */
+
+/** */
+OO.ui.ToolFactory.prototype.getTools = function ( include, exclude, promote, demote ) {
+       var i, len, included, promoted, demoted,
+               auto = [],
+               used = {};
+
+       // Collect included and not excluded tools
+       included = OO.simpleArrayDifference( this.extract( include ), this.extract( exclude ) );
 
-OO.ui.ConfirmationDialog.static.name = 'confirm';
+       // Promotion
+       promoted = this.extract( promote, used );
+       demoted = this.extract( demote, used );
 
-OO.ui.ConfirmationDialog.static.icon = 'help';
+       // Auto
+       for ( i = 0, len = included.length; i < len; i++ ) {
+               if ( !used[included[i]] ) {
+                       auto.push( included[i] );
+               }
+       }
 
-OO.ui.ConfirmationDialog.static.title = OO.ui.deferMsg( 'ooui-dialog-confirm-title' );
+       return promoted.concat( auto ).concat( demoted );
+};
 
-/* Methods */
+/**
+ * Get a flat list of names from a list of names or groups.
+ *
+ * Tools can be specified in the following ways:
+ *
+ * - A specific tool: `{ name: 'tool-name' }` or `'tool-name'`
+ * - All tools in a group: `{ group: 'group-name' }`
+ * - All tools: `'*'`
+ *
+ * @private
+ * @param {Array|string} collection List of tools
+ * @param {Object} [used] Object with names that should be skipped as properties; extracted
+ *  names will be added as properties
+ * @return {string[]} List of extracted names
+ */
+OO.ui.ToolFactory.prototype.extract = function ( collection, used ) {
+       var i, len, item, name, tool,
+               names = [];
+
+       if ( collection === '*' ) {
+               for ( name in this.registry ) {
+                       tool = this.registry[name];
+                       if (
+                               // Only add tools by group name when auto-add is enabled
+                               tool.static.autoAddToCatchall &&
+                               // Exclude already used tools
+                               ( !used || !used[name] )
+                       ) {
+                               names.push( name );
+                               if ( used ) {
+                                       used[name] = true;
+                               }
+                       }
+               }
+       } else if ( $.isArray( collection ) ) {
+               for ( i = 0, len = collection.length; i < len; i++ ) {
+                       item = collection[i];
+                       // Allow plain strings as shorthand for named tools
+                       if ( typeof item === 'string' ) {
+                               item = { name: item };
+                       }
+                       if ( OO.isPlainObject( item ) ) {
+                               if ( item.group ) {
+                                       for ( name in this.registry ) {
+                                               tool = this.registry[name];
+                                               if (
+                                                       // Include tools with matching group
+                                                       tool.static.group === item.group &&
+                                                       // Only add tools by group name when auto-add is enabled
+                                                       tool.static.autoAddToGroup &&
+                                                       // Exclude already used tools
+                                                       ( !used || !used[name] )
+                                               ) {
+                                                       names.push( name );
+                                                       if ( used ) {
+                                                               used[name] = true;
+                                                       }
+                                               }
+                                       }
+                               // Include tools with matching name and exclude already used tools
+                               } else if ( item.name && ( !used || !used[item.name] ) ) {
+                                       names.push( item.name );
+                                       if ( used ) {
+                                               used[item.name] = true;
+                                       }
+                               }
+                       }
+               }
+       }
+       return names;
+};
 
 /**
- * @inheritdoc
+ * Factory for tool groups.
+ *
+ * @class
+ * @extends OO.Factory
+ * @constructor
  */
-OO.ui.ConfirmationDialog.prototype.initialize = function () {
-       // Parent method
-       OO.ui.Dialog.prototype.initialize.call( this );
-
-       // Set up the layout
-       var contentLayout = new OO.ui.PanelLayout( {
-               '$': this.$,
-               'padded': true
-       } );
-
-       this.$promptContainer = this.$( '<div>' ).addClass( 'oo-ui-dialog-confirm-promptContainer' );
-
-       this.cancelButton = new OO.ui.ButtonWidget();
-       this.cancelButton.connect( this, { 'click': [ 'close', 'cancel' ] } );
-
-       this.okButton = new OO.ui.ButtonWidget();
-       this.okButton.connect( this, { 'click': [ 'close', 'ok' ] } );
+OO.ui.ToolGroupFactory = function OoUiToolGroupFactory() {
+       // Parent constructor
+       OO.Factory.call( this );
 
-       // Make the buttons
-       contentLayout.$element.append( this.$promptContainer );
-       this.$body.append( contentLayout.$element );
+       var i, l,
+               defaultClasses = this.constructor.static.getDefaultClasses();
 
-       this.$foot.append(
-               this.okButton.$element,
-               this.cancelButton.$element
-       );
+       // Register default toolgroups
+       for ( i = 0, l = defaultClasses.length; i < l; i++ ) {
+               this.register( defaultClasses[i] );
+       }
 };
 
-/*
- * Setup a confirmation dialog.
- *
- * @param {Object} [data] Window opening data including text of the dialog and text for the buttons
- * @param {jQuery|string} [data.prompt] Text to display or list of nodes to use as content of the dialog.
- * @param {jQuery|string|Function|null} [data.okLabel] Label of the OK button
- * @param {jQuery|string|Function|null} [data.cancelLabel] Label of the cancel button
- * @param {string|string[]} [data.okFlags="constructive"] Flags for the OK button
- * @param {string|string[]} [data.cancelFlags="destructive"] Flags for the cancel button
- * @return {OO.ui.Process} Setup process
- */
-OO.ui.ConfirmationDialog.prototype.getSetupProcess = function ( data ) {
-       // Parent method
-       return OO.ui.ConfirmationDialog.super.prototype.getSetupProcess.call( this, data )
-               .next( function () {
-                       var prompt = data.prompt || OO.ui.deferMsg( 'ooui-dialog-confirm-default-prompt' ),
-                               okLabel = data.okLabel || OO.ui.deferMsg( 'ooui-dialog-confirm-default-ok' ),
-                               cancelLabel = data.cancelLabel || OO.ui.deferMsg( 'ooui-dialog-confirm-default-cancel' ),
-                               okFlags = data.okFlags || 'constructive',
-                               cancelFlags = data.cancelFlags || 'destructive';
-
-                       if ( typeof prompt === 'string' ) {
-                               this.$promptContainer.text( prompt );
-                       } else {
-                               this.$promptContainer.empty().append( prompt );
-                       }
+/* Setup */
 
-                       this.okButton.setLabel( okLabel ).clearFlags().setFlags( okFlags );
-                       this.cancelButton.setLabel( cancelLabel ).clearFlags().setFlags( cancelFlags );
-               }, this );
-};
+OO.inheritClass( OO.ui.ToolGroupFactory, OO.Factory );
+
+/* Static Methods */
 
 /**
- * @inheritdoc
+ * Get a default set of classes to be registered on construction
+ *
+ * @return {Function[]} Default classes
  */
-OO.ui.ConfirmationDialog.prototype.getTeardownProcess = function ( data ) {
-       // Parent method
-       return OO.ui.ConfirmationDialog.super.prototype.getTeardownProcess.call( this, data )
-               .first( function () {
-                       if ( data === 'ok' ) {
-                               this.opened.resolve();
-                       } else { // data === 'cancel', or no data
-                               this.opened.reject();
-                       }
-               }, this );
+OO.ui.ToolGroupFactory.static.getDefaultClasses = function () {
+       return [
+               OO.ui.BarToolGroup,
+               OO.ui.ListToolGroup,
+               OO.ui.MenuToolGroup
+       ];
 };
 
 /**
  * Element with a button.
  *
+ * Buttons are used for controls which can be clicked. They can be configured to use tab indexing
+ * and access keys for accessibility purposes.
+ *
  * @abstract
  * @class
  *
  * @constructor
- * @param {jQuery} $button Button node, assigned to #$button
  * @param {Object} [config] Configuration options
- * @cfg {boolean} [frameless] Render button without a frame
- * @cfg {number} [tabIndex=0] Button's tab index, use -1 to prevent tab focusing
+ * @cfg {jQuery} [$button] Button node, assigned to #$button, omit to use a generated `<a>`
+ * @cfg {boolean} [framed=true] Render button with a frame
+ * @cfg {number} [tabIndex=0] Button's tab index, use null to have no tabIndex
+ * @cfg {string} [accessKey] Button's access key
  */
-OO.ui.ButtonedElement = function OoUiButtonedElement( $button, config ) {
+OO.ui.ButtonElement = function OoUiButtonElement( config ) {
        // Configuration initialization
        config = config || {};
 
        // Properties
-       this.$button = $button;
+       this.$button = null;
+       this.framed = null;
        this.tabIndex = null;
+       this.accessKey = null;
        this.active = false;
        this.onMouseUpHandler = OO.ui.bind( this.onMouseUp, this );
-
-       // Events
-       this.$button.on( 'mousedown', OO.ui.bind( this.onMouseDown, this ) );
+       this.onMouseDownHandler = OO.ui.bind( this.onMouseDown, this );
 
        // Initialization
-       this.$element
-               .addClass( 'oo-ui-buttonedElement' )
-               .prop( 'tabIndex', config.tabIndex || 0 );
-       this.$button
-               .addClass( 'oo-ui-buttonedElement-button' )
-               .attr( 'role', 'button' );
-       if ( config.frameless ) {
-               this.$element.addClass( 'oo-ui-buttonedElement-frameless' );
-       } else {
-               this.$element.addClass( 'oo-ui-buttonedElement-framed' );
-       }
+       this.$element.addClass( 'oo-ui-buttonElement' );
+       this.toggleFramed( config.framed === undefined || config.framed );
+       this.setTabIndex( config.tabIndex || 0 );
+       this.setAccessKey( config.accessKey );
+       this.setButtonElement( config.$button || this.$( '<a>' ) );
 };
 
 /* Setup */
 
-OO.initClass( OO.ui.ButtonedElement );
+OO.initClass( OO.ui.ButtonElement );
 
 /* Static Properties */
 
@@ -2165,26 +3487,43 @@ OO.initClass( OO.ui.ButtonedElement );
  * @inheritable
  * @property {boolean}
  */
-OO.ui.ButtonedElement.static.cancelButtonMouseDownEvents = true;
+OO.ui.ButtonElement.static.cancelButtonMouseDownEvents = true;
 
 /* Methods */
 
+/**
+ * Set the button element.
+ *
+ * If an element is already set, it will be cleaned up before setting up the new element.
+ *
+ * @param {jQuery} $button Element to use as button
+ */
+OO.ui.ButtonElement.prototype.setButtonElement = function ( $button ) {
+       if ( this.$button ) {
+               this.$button
+                       .removeClass( 'oo-ui-buttonElement-button' )
+                       .removeAttr( 'role accesskey tabindex' )
+                       .off( this.onMouseDownHandler );
+       }
+
+       this.$button = $button
+               .addClass( 'oo-ui-buttonElement-button' )
+               .attr( { role: 'button', accesskey: this.accessKey, tabindex: this.tabIndex } )
+               .on( 'mousedown', this.onMouseDownHandler );
+};
+
 /**
  * Handles mouse down events.
  *
  * @param {jQuery.Event} e Mouse down event
  */
-OO.ui.ButtonedElement.prototype.onMouseDown = function ( e ) {
+OO.ui.ButtonElement.prototype.onMouseDown = function ( e ) {
        if ( this.isDisabled() || e.which !== 1 ) {
                return false;
        }
-       // tabIndex should generally be interacted with via the property, but it's not possible to
-       // reliably unset a tabIndex via a property so we use the (lowercase) "tabindex" attribute
-       this.tabIndex = this.$button.attr( 'tabindex' );
-       this.$button
-               // Remove the tab-index while the button is down to prevent the button from stealing focus
-               .removeAttr( 'tabindex' )
-               .addClass( 'oo-ui-buttonedElement-pressed' );
+       // Remove the tab-index while the button is down to prevent the button from stealing focus
+       this.$button.removeAttr( 'tabindex' );
+       this.$element.addClass( 'oo-ui-buttonElement-pressed' );
        // Run the mouseup handler no matter where the mouse is when the button is let go, so we can
        // reliably reapply the tabindex and remove the pressed class
        this.getElementDocument().addEventListener( 'mouseup', this.onMouseUpHandler, true );
@@ -2199,295 +3538,142 @@ OO.ui.ButtonedElement.prototype.onMouseDown = function ( e ) {
  *
  * @param {jQuery.Event} e Mouse up event
  */
-OO.ui.ButtonedElement.prototype.onMouseUp = function ( e ) {
+OO.ui.ButtonElement.prototype.onMouseUp = function ( e ) {
        if ( this.isDisabled() || e.which !== 1 ) {
                return false;
        }
-       this.$button
-               // Restore the tab-index after the button is up to restore the button's accesssibility
-               .attr( 'tabindex', this.tabIndex )
-               .removeClass( 'oo-ui-buttonedElement-pressed' );
+       // Restore the tab-index after the button is up to restore the button's accesssibility
+       this.$button.attr( 'tabindex', this.tabIndex );
+       this.$element.removeClass( 'oo-ui-buttonElement-pressed' );
        // Stop listening for mouseup, since we only needed this once
        this.getElementDocument().removeEventListener( 'mouseup', this.onMouseUpHandler, true );
 };
 
 /**
- * Set active state.
+ * Toggle frame.
  *
- * @param {boolean} [value] Make button active
+ * @param {boolean} [framed] Make button framed, omit to toggle
  * @chainable
  */
-OO.ui.ButtonedElement.prototype.setActive = function ( value ) {
-       this.$button.toggleClass( 'oo-ui-buttonedElement-active', !!value );
-       return this;
-};
-
-/**
- * Element that can be automatically clipped to visible boundaies.
- *
- * @abstract
- * @class
- *
- * @constructor
- * @param {jQuery} $clippable Nodes to clip, assigned to #$clippable
- * @param {Object} [config] Configuration options
- */
-OO.ui.ClippableElement = function OoUiClippableElement( $clippable, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Properties
-       this.$clippable = $clippable;
-       this.clipping = false;
-       this.clipped = false;
-       this.$clippableContainer = null;
-       this.$clippableScroller = null;
-       this.$clippableWindow = null;
-       this.idealWidth = null;
-       this.idealHeight = null;
-       this.onClippableContainerScrollHandler = OO.ui.bind( this.clip, this );
-       this.onClippableWindowResizeHandler = OO.ui.bind( this.clip, this );
+OO.ui.ButtonElement.prototype.toggleFramed = function ( framed ) {
+       framed = framed === undefined ? !this.framed : !!framed;
+       if ( framed !== this.framed ) {
+               this.framed = framed;
+               this.$element
+                       .toggleClass( 'oo-ui-buttonElement-frameless', !framed )
+                       .toggleClass( 'oo-ui-buttonElement-framed', framed );
+       }
 
-       // Initialization
-       this.$clippable.addClass( 'oo-ui-clippableElement-clippable' );
+       return this;
 };
 
-/* Methods */
-
 /**
- * Set clipping.
+ * Set tab index.
  *
- * @param {boolean} value Enable clipping
+ * @param {number|null} tabIndex Button's tab index, use null to remove
  * @chainable
  */
-OO.ui.ClippableElement.prototype.setClipping = function ( value ) {
-       value = !!value;
+OO.ui.ButtonElement.prototype.setTabIndex = function ( tabIndex ) {
+       tabIndex = typeof tabIndex === 'number' && tabIndex >= 0 ? tabIndex : null;
 
-       if ( this.clipping !== value ) {
-               this.clipping = value;
-               if ( this.clipping ) {
-                       this.$clippableContainer = this.$( this.getClosestScrollableElementContainer() );
-                       // If the clippable container is the body, we have to listen to scroll events and check
-                       // jQuery.scrollTop on the window because of browser inconsistencies
-                       this.$clippableScroller = this.$clippableContainer.is( 'body' ) ?
-                               this.$( OO.ui.Element.getWindow( this.$clippableContainer ) ) :
-                               this.$clippableContainer;
-                       this.$clippableScroller.on( 'scroll', this.onClippableContainerScrollHandler );
-                       this.$clippableWindow = this.$( this.getElementWindow() )
-                               .on( 'resize', this.onClippableWindowResizeHandler );
-                       // Initial clip after visible
-                       setTimeout( OO.ui.bind( this.clip, this ) );
-               } else {
-                       this.$clippableContainer = null;
-                       this.$clippableScroller.off( 'scroll', this.onClippableContainerScrollHandler );
-                       this.$clippableScroller = null;
-                       this.$clippableWindow.off( 'resize', this.onClippableWindowResizeHandler );
-                       this.$clippableWindow = null;
+       if ( this.tabIndex !== tabIndex ) {
+               if ( this.$button ) {
+                       if ( tabIndex !== null ) {
+                               this.$button.attr( 'tabindex', tabIndex );
+                       } else {
+                               this.$button.removeAttr( 'tabindex' );
+                       }
                }
+               this.tabIndex = tabIndex;
        }
 
        return this;
 };
 
 /**
- * Check if the element will be clipped to fit the visible area of the nearest scrollable container.
+ * Set access key.
  *
- * @return {boolean} Element will be clipped to the visible area
+ * @param {string} accessKey Button's access key, use empty string to remove
+ * @chainable
  */
-OO.ui.ClippableElement.prototype.isClipping = function () {
-       return this.clipping;
-};
+OO.ui.ButtonElement.prototype.setAccessKey = function ( accessKey ) {
+       accessKey = typeof accessKey === 'string' && accessKey.length ? accessKey : null;
 
-/**
- * Check if the bottom or right of the element is being clipped by the nearest scrollable container.
- *
- * @return {boolean} Part of the element is being clipped
- */
-OO.ui.ClippableElement.prototype.isClipped = function () {
-       return this.clipped;
-};
+       if ( this.accessKey !== accessKey ) {
+               if ( this.$button ) {
+                       if ( accessKey !== null ) {
+                               this.$button.attr( 'accesskey', accessKey );
+                       } else {
+                               this.$button.removeAttr( 'accesskey' );
+                       }
+               }
+               this.accessKey = accessKey;
+       }
 
-/**
- * Set the ideal size.
- *
- * @param {number|string} [width] Width as a number of pixels or CSS string with unit suffix
- * @param {number|string} [height] Height as a number of pixels or CSS string with unit suffix
- */
-OO.ui.ClippableElement.prototype.setIdealSize = function ( width, height ) {
-       this.idealWidth = width;
-       this.idealHeight = height;
+       return this;
 };
 
 /**
- * Clip element to visible boundaries and allow scrolling when needed.
- *
- * Element will be clipped the bottom or right of the element is within 10px of the edge of, or
- * overlapped by, the visible area of the nearest scrollable container.
+ * Set active state.
  *
+ * @param {boolean} [value] Make button active
  * @chainable
  */
-OO.ui.ClippableElement.prototype.clip = function () {
-       if ( !this.clipping ) {
-               // this.$clippableContainer and this.$clippableWindow are null, so the below will fail
-               return this;
-       }
-
-       var buffer = 10,
-               cOffset = this.$clippable.offset(),
-               ccOffset = this.$clippableContainer.offset() || { 'top': 0, 'left': 0 },
-               ccHeight = this.$clippableContainer.innerHeight() - buffer,
-               ccWidth = this.$clippableContainer.innerWidth() - buffer,
-               scrollTop = this.$clippableScroller.scrollTop(),
-               scrollLeft = this.$clippableScroller.scrollLeft(),
-               desiredWidth = ( ccOffset.left + scrollLeft + ccWidth ) - cOffset.left,
-               desiredHeight = ( ccOffset.top + scrollTop + ccHeight ) - cOffset.top,
-               naturalWidth = this.$clippable.prop( 'scrollWidth' ),
-               naturalHeight = this.$clippable.prop( 'scrollHeight' ),
-               clipWidth = desiredWidth < naturalWidth,
-               clipHeight = desiredHeight < naturalHeight;
-
-       if ( clipWidth ) {
-               this.$clippable.css( { 'overflow-x': 'auto', 'width': desiredWidth } );
-       } else {
-               this.$clippable.css( 'width', this.idealWidth || '' );
-               this.$clippable.width(); // Force reflow for https://code.google.com/p/chromium/issues/detail?id=387290
-               this.$clippable.css( 'overflow-x', '' );
-       }
-       if ( clipHeight ) {
-               this.$clippable.css( { 'overflow-y': 'auto', 'height': desiredHeight } );
-       } else {
-               this.$clippable.css( 'height', this.idealHeight || '' );
-               this.$clippable.height(); // Force reflow for https://code.google.com/p/chromium/issues/detail?id=387290
-               this.$clippable.css( 'overflow-y', '' );
-       }
-
-       this.clipped = clipWidth || clipHeight;
-
+OO.ui.ButtonElement.prototype.setActive = function ( value ) {
+       this.$element.toggleClass( 'oo-ui-buttonElement-active', !!value );
        return this;
 };
 
 /**
- * Element with named flags that can be added, removed, listed and checked.
- *
- * A flag, when set, adds a CSS class on the `$element` by combing `oo-ui-flaggableElement-` with
- * the flag name. Flags are primarily useful for styling.
+ * Element containing a sequence of child elements.
  *
  * @abstract
  * @class
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {string[]} [flags=[]] Styling flags, e.g. 'primary', 'destructive' or 'constructive'
+ * @cfg {jQuery} [$group] Container node, assigned to #$group, omit to use a generated `<div>`
  */
-OO.ui.FlaggableElement = function OoUiFlaggableElement( config ) {
-       // Config initialization
+OO.ui.GroupElement = function OoUiGroupElement( config ) {
+       // Configuration
        config = config || {};
 
        // Properties
-       this.flags = {};
+       this.$group = null;
+       this.items = [];
+       this.aggregateItemEvents = {};
 
        // Initialization
-       this.setFlags( config.flags );
+       this.setGroupElement( config.$group || this.$( '<div>' ) );
 };
 
 /* Methods */
 
 /**
- * Check if a flag is set.
- *
- * @param {string} flag Name of flag
- * @return {boolean} Has flag
- */
-OO.ui.FlaggableElement.prototype.hasFlag = function ( flag ) {
-       return flag in this.flags;
-};
-
-/**
- * Get the names of all flags set.
- *
- * @return {string[]} flags Flag names
- */
-OO.ui.FlaggableElement.prototype.getFlags = function () {
-       return Object.keys( this.flags );
-};
-
-/**
- * Clear all flags.
+ * Set the group element.
  *
- * @chainable
- */
-OO.ui.FlaggableElement.prototype.clearFlags = function () {
-       var flag,
-               classPrefix = 'oo-ui-flaggableElement-';
-
-       for ( flag in this.flags ) {
-               delete this.flags[flag];
-               this.$element.removeClass( classPrefix + flag );
-       }
-
-       return this;
-};
-
-/**
- * Add one or more flags.
+ * If an element is already set, items will be moved to the new element.
  *
- * @param {string|string[]|Object.<string, boolean>} flags One or more flags to add, or an object
- *  keyed by flag name containing boolean set/remove instructions.
- * @chainable
+ * @param {jQuery} $group Element to use as group
  */
-OO.ui.FlaggableElement.prototype.setFlags = function ( flags ) {
-       var i, len, flag,
-               classPrefix = 'oo-ui-flaggableElement-';
+OO.ui.GroupElement.prototype.setGroupElement = function ( $group ) {
+       var i, len;
 
-       if ( typeof flags === 'string' ) {
-               // Set
-               this.flags[flags] = true;
-               this.$element.addClass( classPrefix + flags );
-       } else if ( $.isArray( flags ) ) {
-               for ( i = 0, len = flags.length; i < len; i++ ) {
-                       flag = flags[i];
-                       // Set
-                       this.flags[flag] = true;
-                       this.$element.addClass( classPrefix + flag );
-               }
-       } else if ( OO.isPlainObject( flags ) ) {
-               for ( flag in flags ) {
-                       if ( flags[flag] ) {
-                               // Set
-                               this.flags[flag] = true;
-                               this.$element.addClass( classPrefix + flag );
-                       } else {
-                               // Remove
-                               delete this.flags[flag];
-                               this.$element.removeClass( classPrefix + flag );
-                       }
-               }
+       this.$group = $group;
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               this.$group.append( this.items[i].$element );
        }
-       return this;
 };
 
 /**
- * Element containing a sequence of child elements.
- *
- * @abstract
- * @class
- *
- * @constructor
- * @param {jQuery} $group Container node, assigned to #$group
- * @param {Object} [config] Configuration options
- */
-OO.ui.GroupElement = function OoUiGroupElement( $group, config ) {
-       // Configuration
-       config = config || {};
-
-       // Properties
-       this.$group = $group;
-       this.items = [];
-       this.aggregateItemEvents = {};
+ * Check if there are no items.
+ *
+ * @return {boolean} Group is empty
+ */
+OO.ui.GroupElement.prototype.isEmpty = function () {
+       return !this.items.length;
 };
 
-/* Methods */
-
 /**
  * Get items.
  *
@@ -2553,6 +3739,8 @@ OO.ui.GroupElement.prototype.aggregate = function ( events ) {
 /**
  * Add items.
  *
+ * Adding an existing item (by value) will move it.
+ *
  * @param {OO.ui.Element[]} items Item
  * @param {number} [index] Index to insert items at
  * @chainable
@@ -2668,32 +3856,40 @@ OO.ui.GroupElement.prototype.clearItems = function () {
 /**
  * Element containing an icon.
  *
+ * Icons are graphics, about the size of normal text. They can be used to aid the user in locating
+ * a control or convey information in a more space efficient way. Icons should rarely be used
+ * without labels; such as in a toolbar where space is at a premium or within a context where the
+ * meaning is very clear to the user.
+ *
  * @abstract
  * @class
  *
  * @constructor
- * @param {jQuery} $icon Icon node, assigned to #$icon
  * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$icon] Icon node, assigned to #$icon, omit to use a generated `<span>`
  * @cfg {Object|string} [icon=''] Symbolic icon name, or map of icon names keyed by language ID;
  *  use the 'default' key to specify the icon to be used when there is no icon in the user's
  *  language
+ * @cfg {string} [iconTitle] Icon title text or a function that returns text
  */
-OO.ui.IconedElement = function OoUiIconedElement( $icon, config ) {
+OO.ui.IconElement = function OoUiIconElement( config ) {
        // Config intialization
        config = config || {};
 
        // Properties
-       this.$icon = $icon;
+       this.$icon = null;
        this.icon = null;
+       this.iconTitle = null;
 
        // Initialization
-       this.$icon.addClass( 'oo-ui-iconedElement-icon' );
        this.setIcon( config.icon || this.constructor.static.icon );
+       this.setIconTitle( config.iconTitle || this.constructor.static.iconTitle );
+       this.setIconElement( config.$icon || this.$( '<span>' ) );
 };
 
 /* Setup */
 
-OO.initClass( OO.ui.IconedElement );
+OO.initClass( OO.ui.IconElement );
 
 /* Static Properties */
 
@@ -2706,7 +3902,7 @@ OO.initClass( OO.ui.IconedElement );
  * additional icon names keyed by language code.
  *
  * Example of i18n icon definition:
- *     { 'default': 'bold-a', 'en': 'bold-b', 'de': 'bold-f' }
+ *     { default: 'bold-a', en: 'bold-b', de: 'bold-f' }
  *
  * @static
  * @inheritable
@@ -2714,374 +3910,881 @@ OO.initClass( OO.ui.IconedElement );
  *  use the 'default' key to specify the icon to be used when there is no icon in the user's
  *  language
  */
-OO.ui.IconedElement.static.icon = null;
+OO.ui.IconElement.static.icon = null;
+
+/**
+ * Icon title.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null} Icon title text, a function that returns text or null for no
+ *  icon title
+ */
+OO.ui.IconElement.static.iconTitle = null;
 
 /* Methods */
 
+/**
+ * Set the icon element.
+ *
+ * If an element is already set, it will be cleaned up before setting up the new element.
+ *
+ * @param {jQuery} $icon Element to use as icon
+ */
+OO.ui.IconElement.prototype.setIconElement = function ( $icon ) {
+       if ( this.$icon ) {
+               this.$icon
+                       .removeClass( 'oo-ui-iconElement-icon oo-ui-icon-' + this.icon )
+                       .removeAttr( 'title' );
+       }
+
+       this.$icon = $icon
+               .addClass( 'oo-ui-iconElement-icon' )
+               .toggleClass( 'oo-ui-icon-' + this.icon, !!this.icon );
+       if ( this.iconTitle !== null ) {
+               this.$icon.attr( 'title', this.iconTitle );
+       }
+};
+
 /**
  * Set icon.
  *
- * @param {Object|string} icon Symbolic icon name, or map of icon names keyed by language ID;
+ * @param {Object|string|null} icon Symbolic icon name, or map of icon names keyed by language ID;
  *  use the 'default' key to specify the icon to be used when there is no icon in the user's
- *  language
+ *  language, use null to remove icon
  * @chainable
  */
-OO.ui.IconedElement.prototype.setIcon = function ( icon ) {
+OO.ui.IconElement.prototype.setIcon = function ( icon ) {
        icon = OO.isPlainObject( icon ) ? OO.ui.getLocalValue( icon, null, 'default' ) : icon;
+       icon = typeof icon === 'string' && icon.trim().length ? icon.trim() : null;
+
+       if ( this.icon !== icon ) {
+               if ( this.$icon ) {
+                       if ( this.icon !== null ) {
+                               this.$icon.removeClass( 'oo-ui-icon-' + this.icon );
+                       }
+                       if ( icon !== null ) {
+                               this.$icon.addClass( 'oo-ui-icon-' + icon );
+                       }
+               }
+               this.icon = icon;
+       }
+
+       this.$element.toggleClass( 'oo-ui-iconElement', !!this.icon );
+
+       return this;
+};
+
+/**
+ * Set icon title.
+ *
+ * @param {string|Function|null} icon Icon title text, a function that returns text or null
+ *  for no icon title
+ * @chainable
+ */
+OO.ui.IconElement.prototype.setIconTitle = function ( iconTitle ) {
+       iconTitle = typeof iconTitle === 'function' ||
+               ( typeof iconTitle === 'string' && iconTitle.length ) ?
+                       OO.ui.resolveMsg( iconTitle ) : null;
+
+       if ( this.iconTitle !== iconTitle ) {
+               this.iconTitle = iconTitle;
+               if ( this.$icon ) {
+                       if ( this.iconTitle !== null ) {
+                               this.$icon.attr( 'title', iconTitle );
+                       } else {
+                               this.$icon.removeAttr( 'title' );
+                       }
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Get icon.
+ *
+ * @return {string} Icon
+ */
+OO.ui.IconElement.prototype.getIcon = function () {
+       return this.icon;
+};
+
+/**
+ * Element containing an indicator.
+ *
+ * Indicators are graphics, smaller than normal text. They can be used to describe unique status or
+ * behavior. Indicators should only be used in exceptional cases; such as a button that opens a menu
+ * instead of performing an action directly, or an item in a list which has errors that need to be
+ * resolved.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$indicator] Indicator node, assigned to #$indicator, omit to use a generated
+ *   `<span>`
+ * @cfg {string} [indicator] Symbolic indicator name
+ * @cfg {string} [indicatorTitle] Indicator title text or a function that returns text
+ */
+OO.ui.IndicatorElement = function OoUiIndicatorElement( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.$indicator = null;
+       this.indicator = null;
+       this.indicatorTitle = null;
+
+       // Initialization
+       this.setIndicator( config.indicator || this.constructor.static.indicator );
+       this.setIndicatorTitle( config.indicatorTitle || this.constructor.static.indicatorTitle );
+       this.setIndicatorElement( config.$indicator || this.$( '<span>' ) );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.IndicatorElement );
+
+/* Static Properties */
+
+/**
+ * indicator.
+ *
+ * @static
+ * @inheritable
+ * @property {string|null} Symbolic indicator name or null for no indicator
+ */
+OO.ui.IndicatorElement.static.indicator = null;
+
+/**
+ * Indicator title.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null} Indicator title text, a function that returns text or null for no
+ *  indicator title
+ */
+OO.ui.IndicatorElement.static.indicatorTitle = null;
+
+/* Methods */
+
+/**
+ * Set the indicator element.
+ *
+ * If an element is already set, it will be cleaned up before setting up the new element.
+ *
+ * @param {jQuery} $indicator Element to use as indicator
+ */
+OO.ui.IndicatorElement.prototype.setIndicatorElement = function ( $indicator ) {
+       if ( this.$indicator ) {
+               this.$indicator
+                       .removeClass( 'oo-ui-indicatorElement-indicator oo-ui-indicator-' + this.indicator )
+                       .removeAttr( 'title' );
+       }
+
+       this.$indicator = $indicator
+               .addClass( 'oo-ui-indicatorElement-indicator' )
+               .toggleClass( 'oo-ui-indicator-' + this.indicator, !!this.indicator );
+       if ( this.indicatorTitle !== null ) {
+               this.$indicatorTitle.attr( 'title', this.indicatorTitle );
+       }
+};
+
+/**
+ * Set indicator.
+ *
+ * @param {string|null} indicator Symbolic name of indicator to use or null for no indicator
+ * @chainable
+ */
+OO.ui.IndicatorElement.prototype.setIndicator = function ( indicator ) {
+       indicator = typeof indicator === 'string' && indicator.length ? indicator.trim() : null;
+
+       if ( this.indicator !== indicator ) {
+               if ( this.$indicator ) {
+                       if ( this.indicator !== null ) {
+                               this.$indicator.removeClass( 'oo-ui-indicator-' + this.indicator );
+                       }
+                       if ( indicator !== null ) {
+                               this.$indicator.addClass( 'oo-ui-indicator-' + indicator );
+                       }
+               }
+               this.indicator = indicator;
+       }
+
+       this.$element.toggleClass( 'oo-ui-indicatorElement', !!this.indicator );
+
+       return this;
+};
+
+/**
+ * Set indicator title.
+ *
+ * @param {string|Function|null} indicator Indicator title text, a function that returns text or
+ *   null for no indicator title
+ * @chainable
+ */
+OO.ui.IndicatorElement.prototype.setIndicatorTitle = function ( indicatorTitle ) {
+       indicatorTitle = typeof indicatorTitle === 'function' ||
+               ( typeof indicatorTitle === 'string' && indicatorTitle.length ) ?
+                       OO.ui.resolveMsg( indicatorTitle ) : null;
+
+       if ( this.indicatorTitle !== indicatorTitle ) {
+               this.indicatorTitle = indicatorTitle;
+               if ( this.$indicator ) {
+                       if ( this.indicatorTitle !== null ) {
+                               this.$indicator.attr( 'title', indicatorTitle );
+                       } else {
+                               this.$indicator.removeAttr( 'title' );
+                       }
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Get indicator.
+ *
+ * @return {string} title Symbolic name of indicator
+ */
+OO.ui.IndicatorElement.prototype.getIndicator = function () {
+       return this.indicator;
+};
+
+/**
+ * Get indicator title.
+ *
+ * @return {string} Indicator title text
+ */
+OO.ui.IndicatorElement.prototype.getIndicatorTitle = function () {
+       return this.indicatorTitle;
+};
+
+/**
+ * Element containing a label.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$label] Label node, assigned to #$label, omit to use a generated `<span>`
+ * @cfg {jQuery|string|Function} [label] Label nodes, text or a function that returns nodes or text
+ * @cfg {boolean} [autoFitLabel=true] Whether to fit the label or not.
+ */
+OO.ui.LabelElement = function OoUiLabelElement( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.$label = null;
+       this.label = null;
+       this.autoFitLabel = config.autoFitLabel === undefined || !!config.autoFitLabel;
+
+       // Initialization
+       this.setLabel( config.label || this.constructor.static.label );
+       this.setLabelElement( config.$label || this.$( '<span>' ) );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.LabelElement );
+
+/* Static Properties */
+
+/**
+ * Label.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null} Label text; a function that returns nodes or text; or null for
+ *  no label
+ */
+OO.ui.LabelElement.static.label = null;
+
+/* Methods */
+
+/**
+ * Set the label element.
+ *
+ * If an element is already set, it will be cleaned up before setting up the new element.
+ *
+ * @param {jQuery} $label Element to use as label
+ */
+OO.ui.LabelElement.prototype.setLabelElement = function ( $label ) {
+       if ( this.$label ) {
+               this.$label.removeClass( 'oo-ui-labelElement-label' ).empty();
+       }
+
+       this.$label = $label.addClass( 'oo-ui-labelElement-label' );
+       this.setLabelContent( this.label );
+};
+
+/**
+ * Set the label.
+ *
+ * An empty string will result in the label being hidden. A string containing only whitespace will
+ * be converted to a single &nbsp;
+ *
+ * @param {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
+ *  text; or null for no label
+ * @chainable
+ */
+OO.ui.LabelElement.prototype.setLabel = function ( label ) {
+       label = typeof label === 'function' ? OO.ui.resolveMsg( label ) : label;
+       label = ( typeof label === 'string' && label.length ) || label instanceof jQuery ? label : null;
+
+       if ( this.label !== label ) {
+               if ( this.$label ) {
+                       this.setLabelContent( label );
+               }
+               this.label = label;
+       }
+
+       this.$element.toggleClass( 'oo-ui-labelElement', !!this.label );
+
+       return this;
+};
+
+/**
+ * Get the label.
+ *
+ * @return {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
+ *  text; or null for no label
+ */
+OO.ui.LabelElement.prototype.getLabel = function () {
+       return this.label;
+};
 
-       if ( this.icon ) {
-               this.$icon.removeClass( 'oo-ui-icon-' + this.icon );
+/**
+ * Fit the label.
+ *
+ * @chainable
+ */
+OO.ui.LabelElement.prototype.fitLabel = function () {
+       if ( this.$label && this.$label.autoEllipsis && this.autoFitLabel ) {
+               this.$label.autoEllipsis( { hasSpan: false, tooltip: true } );
        }
-       if ( typeof icon === 'string' ) {
-               icon = icon.trim();
-               if ( icon.length ) {
-                       this.$icon.addClass( 'oo-ui-icon-' + icon );
-                       this.icon = icon;
+
+       return this;
+};
+
+/**
+ * Set the content of the label.
+ *
+ * Do not call this method until after the label element has been set by #setLabelElement.
+ *
+ * @private
+ * @param {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
+ *  text; or null for no label
+ */
+OO.ui.LabelElement.prototype.setLabelContent = function ( label ) {
+       if ( typeof label === 'string' ) {
+               if ( label.match( /^\s*$/ ) ) {
+                       // Convert whitespace only string to a single non-breaking space
+                       this.$label.html( '&nbsp;' );
+               } else {
+                       this.$label.text( label );
                }
+       } else if ( label instanceof jQuery ) {
+               this.$label.empty().append( label );
+       } else {
+               this.$label.empty();
        }
-       this.$element.toggleClass( 'oo-ui-iconedElement', !!this.icon );
+       this.$label.css( 'display', !label ? 'none' : '' );
+};
+
+/**
+ * Element containing an OO.ui.PopupWidget object.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} [popup] Configuration to pass to popup
+ * @cfg {boolean} [autoClose=true] Popup auto-closes when it loses focus
+ */
+OO.ui.PopupElement = function OoUiPopupElement( config ) {
+       // Configuration initialization
+       config = config || {};
 
-       return this;
+       // Properties
+       this.popup = new OO.ui.PopupWidget( $.extend(
+               { autoClose: true },
+               config.popup,
+               { $: this.$, $autoCloseIgnore: this.$element }
+       ) );
 };
 
+/* Methods */
+
 /**
- * Get icon.
+ * Get popup.
  *
- * @return {string} Icon
+ * @return {OO.ui.PopupWidget} Popup widget
  */
-OO.ui.IconedElement.prototype.getIcon = function () {
-       return this.icon;
+OO.ui.PopupElement.prototype.getPopup = function () {
+       return this.popup;
 };
 
 /**
- * Element containing an indicator.
+ * Element with named flags that can be added, removed, listed and checked.
+ *
+ * A flag, when set, adds a CSS class on the `$element` by combining `oo-ui-flaggedElement-` with
+ * the flag name. Flags are primarily useful for styling.
  *
  * @abstract
  * @class
  *
  * @constructor
- * @param {jQuery} $indicator Indicator node, assigned to #$indicator
  * @param {Object} [config] Configuration options
- * @cfg {string} [indicator] Symbolic indicator name
- * @cfg {string} [indicatorTitle] Indicator title text or a function that return text
+ * @cfg {string[]} [flags=[]] Styling flags, e.g. 'primary', 'destructive' or 'constructive'
+ * @cfg {jQuery} [$flagged] Flagged node, assigned to #$flagged, omit to use #$element
  */
-OO.ui.IndicatedElement = function OoUiIndicatedElement( $indicator, config ) {
-       // Config intialization
+OO.ui.FlaggedElement = function OoUiFlaggedElement( config ) {
+       // Config initialization
        config = config || {};
 
        // Properties
-       this.$indicator = $indicator;
-       this.indicator = null;
-       this.indicatorLabel = null;
+       this.flags = {};
+       this.$flagged = null;
 
        // Initialization
-       this.$indicator.addClass( 'oo-ui-indicatedElement-indicator' );
-       this.setIndicator( config.indicator || this.constructor.static.indicator );
-       this.setIndicatorTitle( config.indicatorTitle  || this.constructor.static.indicatorTitle );
+       this.setFlags( config.flags );
+       this.setFlaggedElement( config.$flagged || this.$element );
 };
 
-/* Setup */
+/* Events */
 
-OO.initClass( OO.ui.IndicatedElement );
+/**
+ * @event flag
+ * @param {Object.<string,boolean>} changes Object keyed by flag name containing boolean
+ *   added/removed properties
+ */
 
-/* Static Properties */
+/* Methods */
 
 /**
- * indicator.
+ * Set the flagged element.
  *
- * @static
- * @inheritable
- * @property {string|null} Symbolic indicator name or null for no indicator
+ * If an element is already set, it will be cleaned up before setting up the new element.
+ *
+ * @param {jQuery} $flagged Element to add flags to
  */
-OO.ui.IndicatedElement.static.indicator = null;
+OO.ui.FlaggedElement.prototype.setFlaggedElement = function ( $flagged ) {
+       var classNames = Object.keys( this.flags ).map( function ( flag ) {
+               return 'oo-ui-flaggedElement-' + flag;
+       } ).join( ' ' );
+
+       if ( this.$flagged ) {
+               this.$flagged.removeClass( classNames );
+       }
+
+       this.$flagged = $flagged.addClass( classNames );
+};
 
 /**
- * Indicator title.
+ * Check if a flag is set.
  *
- * @static
- * @inheritable
- * @property {string|Function|null} Indicator title text, a function that return text or null for no
- *  indicator title
+ * @param {string} flag Name of flag
+ * @return {boolean} Has flag
  */
-OO.ui.IndicatedElement.static.indicatorTitle = null;
+OO.ui.FlaggedElement.prototype.hasFlag = function ( flag ) {
+       return flag in this.flags;
+};
 
-/* Methods */
+/**
+ * Get the names of all flags set.
+ *
+ * @return {string[]} flags Flag names
+ */
+OO.ui.FlaggedElement.prototype.getFlags = function () {
+       return Object.keys( this.flags );
+};
 
 /**
- * Set indicator.
+ * Clear all flags.
  *
- * @param {string|null} indicator Symbolic name of indicator to use or null for no indicator
  * @chainable
+ * @fires flag
  */
-OO.ui.IndicatedElement.prototype.setIndicator = function ( indicator ) {
-       if ( this.indicator ) {
-               this.$indicator.removeClass( 'oo-ui-indicator-' + this.indicator );
-               this.indicator = null;
+OO.ui.FlaggedElement.prototype.clearFlags = function () {
+       var flag, className,
+               changes = {},
+               remove = [],
+               classPrefix = 'oo-ui-flaggedElement-';
+
+       for ( flag in this.flags ) {
+               className = classPrefix + flag;
+               changes[flag] = false;
+               delete this.flags[flag];
+               remove.push( className );
        }
-       if ( typeof indicator === 'string' ) {
-               indicator = indicator.trim();
-               if ( indicator.length ) {
-                       this.$indicator.addClass( 'oo-ui-indicator-' + indicator );
-                       this.indicator = indicator;
-               }
+
+       if ( this.$flagged ) {
+               this.$flagged.removeClass( remove.join( ' ' ) );
        }
-       this.$element.toggleClass( 'oo-ui-indicatedElement', !!this.indicator );
+
+       this.emit( 'flag', changes );
 
        return this;
 };
 
 /**
- * Set indicator label.
+ * Add one or more flags.
  *
- * @param {string|Function|null} indicator Indicator title text, a function that return text or null
- *  for no indicator title
+ * @param {string|string[]|Object.<string, boolean>} flags One or more flags to add, or an object
+ *  keyed by flag name containing boolean set/remove instructions.
  * @chainable
+ * @fires flag
  */
-OO.ui.IndicatedElement.prototype.setIndicatorTitle = function ( indicatorTitle ) {
-       this.indicatorTitle = indicatorTitle = OO.ui.resolveMsg( indicatorTitle );
+OO.ui.FlaggedElement.prototype.setFlags = function ( flags ) {
+       var i, len, flag, className,
+               changes = {},
+               add = [],
+               remove = [],
+               classPrefix = 'oo-ui-flaggedElement-';
 
-       if ( typeof indicatorTitle === 'string' && indicatorTitle.length ) {
-               this.$indicator.attr( 'title', indicatorTitle );
-       } else {
-               this.$indicator.removeAttr( 'title' );
+       if ( typeof flags === 'string' ) {
+               className = classPrefix + flags;
+               // Set
+               if ( !this.flags[flags] ) {
+                       this.flags[flags] = true;
+                       add.push( className );
+               }
+       } else if ( $.isArray( flags ) ) {
+               for ( i = 0, len = flags.length; i < len; i++ ) {
+                       flag = flags[i];
+                       className = classPrefix + flag;
+                       // Set
+                       if ( !this.flags[flag] ) {
+                               changes[flag] = true;
+                               this.flags[flag] = true;
+                               add.push( className );
+                       }
+               }
+       } else if ( OO.isPlainObject( flags ) ) {
+               for ( flag in flags ) {
+                       className = classPrefix + flag;
+                       if ( flags[flag] ) {
+                               // Set
+                               if ( !this.flags[flag] ) {
+                                       changes[flag] = true;
+                                       this.flags[flag] = true;
+                                       add.push( className );
+                               }
+                       } else {
+                               // Remove
+                               if ( this.flags[flag] ) {
+                                       changes[flag] = false;
+                                       delete this.flags[flag];
+                                       remove.push( className );
+                               }
+                       }
+               }
        }
 
-       return this;
-};
+       if ( this.$flagged ) {
+               this.$flagged
+                       .addClass( add.join( ' ' ) )
+                       .removeClass( remove.join( ' ' ) );
+       }
 
-/**
- * Get indicator.
- *
- * @return {string} title Symbolic name of indicator
- */
-OO.ui.IndicatedElement.prototype.getIndicator = function () {
-       return this.indicator;
-};
+       this.emit( 'flag', changes );
 
-/**
- * Get indicator title.
- *
- * @return {string} Indicator title text
- */
-OO.ui.IndicatedElement.prototype.getIndicatorTitle = function () {
-       return this.indicatorTitle;
+       return this;
 };
 
 /**
- * Element containing a label.
+ * Element with a title.
+ *
+ * Titles are rendered by the browser and are made visible when hovering the element. Titles are
+ * not visible on touch devices.
  *
  * @abstract
  * @class
  *
  * @constructor
- * @param {jQuery} $label Label node, assigned to #$label
  * @param {Object} [config] Configuration options
- * @cfg {jQuery|string|Function} [label] Label nodes, text or a function that returns nodes or text
- * @cfg {boolean} [autoFitLabel=true] Whether to fit the label or not.
+ * @cfg {jQuery} [$titled] Titled node, assigned to #$titled, omit to use #$element
+ * @cfg {string|Function} [title] Title text or a function that returns text
  */
-OO.ui.LabeledElement = function OoUiLabeledElement( $label, config ) {
+OO.ui.TitledElement = function OoUiTitledElement( config ) {
        // Config intialization
        config = config || {};
 
        // Properties
-       this.$label = $label;
-       this.label = null;
+       this.$titled = null;
+       this.title = null;
 
        // Initialization
-       this.$label.addClass( 'oo-ui-labeledElement-label' );
-       this.setLabel( config.label || this.constructor.static.label );
-       this.autoFitLabel = config.autoFitLabel === undefined || !!config.autoFitLabel;
+       this.setTitle( config.title || this.constructor.static.title );
+       this.setTitledElement( config.$titled || this.$element );
 };
 
 /* Setup */
 
-OO.initClass( OO.ui.LabeledElement );
+OO.initClass( OO.ui.TitledElement );
 
 /* Static Properties */
 
 /**
- * Label.
+ * Title.
  *
  * @static
  * @inheritable
- * @property {string|Function|null} Label text; a function that returns a nodes or text; or null for
- *  no label
+ * @property {string|Function} Title text or a function that returns text
  */
-OO.ui.LabeledElement.static.label = null;
+OO.ui.TitledElement.static.title = null;
 
 /* Methods */
 
 /**
- * Set the label.
+ * Set the titled element.
  *
- * An empty string will result in the label being hidden. A string containing only whitespace will
- * be converted to a single &nbsp;
+ * If an element is already set, it will be cleaned up before setting up the new element.
  *
- * @param {jQuery|string|Function|null} label Label nodes; text; a function that retuns nodes or
- *  text; or null for no label
- * @chainable
+ * @param {jQuery} $titled Element to set title on
  */
-OO.ui.LabeledElement.prototype.setLabel = function ( label ) {
-       var empty = false;
-
-       this.label = label = OO.ui.resolveMsg( label ) || null;
-       if ( typeof label === 'string' && label.length ) {
-               if ( label.match( /^\s*$/ ) ) {
-                       // Convert whitespace only string to a single non-breaking space
-                       this.$label.html( '&nbsp;' );
-               } else {
-                       this.$label.text( label );
-               }
-       } else if ( label instanceof jQuery ) {
-               this.$label.empty().append( label );
-       } else {
-               this.$label.empty();
-               empty = true;
+OO.ui.TitledElement.prototype.setTitledElement = function ( $titled ) {
+       if ( this.$titled ) {
+               this.$titled.removeAttr( 'title' );
        }
-       this.$element.toggleClass( 'oo-ui-labeledElement', !empty );
-       this.$label.css( 'display', empty ? 'none' : '' );
 
-       return this;
+       this.$titled = $titled;
+       if ( this.title ) {
+               this.$titled.attr( 'title', this.title );
+       }
 };
 
 /**
- * Get the label.
+ * Set title.
  *
- * @return {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
- *  text; or null for no label
+ * @param {string|Function|null} title Title text, a function that returns text or null for no title
+ * @chainable
  */
-OO.ui.LabeledElement.prototype.getLabel = function () {
-       return this.label;
+OO.ui.TitledElement.prototype.setTitle = function ( title ) {
+       title = typeof title === 'string' ? OO.ui.resolveMsg( title ) : null;
+
+       if ( this.title !== title ) {
+               if ( this.$titled ) {
+                       if ( title !== null ) {
+                               this.$titled.attr( 'title', title );
+                       } else {
+                               this.$titled.removeAttr( 'title' );
+                       }
+               }
+               this.title = title;
+       }
+
+       return this;
 };
 
 /**
- * Fit the label.
+ * Get title.
  *
- * @chainable
+ * @return {string} Title string
  */
-OO.ui.LabeledElement.prototype.fitLabel = function () {
-       if ( this.$label.autoEllipsis && this.autoFitLabel ) {
-               this.$label.autoEllipsis( { 'hasSpan': false, 'tooltip': true } );
-       }
-       return this;
+OO.ui.TitledElement.prototype.getTitle = function () {
+       return this.title;
 };
 
 /**
- * Popuppable element.
+ * Element that can be automatically clipped to visible boundaries.
+ *
+ * Whenever the element's natural height changes, you have to call
+ * #clip to make sure it's still clipping correctly.
  *
  * @abstract
  * @class
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {number} [popupWidth=320] Width of popup
- * @cfg {number} [popupHeight] Height of popup
- * @cfg {Object} [popup] Configuration to pass to popup
+ * @cfg {jQuery} [$clippable] Nodes to clip, assigned to #$clippable, omit to use #$element
  */
-OO.ui.PopuppableElement = function OoUiPopuppableElement( config ) {
+OO.ui.ClippableElement = function OoUiClippableElement( config ) {
        // Configuration initialization
-       config = $.extend( { 'popupWidth': 320 }, config );
+       config = config || {};
 
        // Properties
-       this.popup = new OO.ui.PopupWidget( $.extend(
-               { 'align': 'center', 'autoClose': true },
-               config.popup,
-               { '$': this.$, '$autoCloseIgnore': this.$element }
-       ) );
-       this.popupWidth = config.popupWidth;
-       this.popupHeight = config.popupHeight;
+       this.$clippable = null;
+       this.clipping = false;
+       this.clippedHorizontally = false;
+       this.clippedVertically = false;
+       this.$clippableContainer = null;
+       this.$clippableScroller = null;
+       this.$clippableWindow = null;
+       this.idealWidth = null;
+       this.idealHeight = null;
+       this.onClippableContainerScrollHandler = OO.ui.bind( this.clip, this );
+       this.onClippableWindowResizeHandler = OO.ui.bind( this.clip, this );
+
+       // Initialization
+       this.setClippableElement( config.$clippable || this.$element );
 };
 
 /* Methods */
 
 /**
- * Get popup.
+ * Set clippable element.
  *
- * @return {OO.ui.PopupWidget} Popup widget
+ * If an element is already set, it will be cleaned up before setting up the new element.
+ *
+ * @param {jQuery} $clippable Element to make clippable
  */
-OO.ui.PopuppableElement.prototype.getPopup = function () {
-       return this.popup;
+OO.ui.ClippableElement.prototype.setClippableElement = function ( $clippable ) {
+       if ( this.$clippable ) {
+               this.$clippable.removeClass( 'oo-ui-clippableElement-clippable' );
+               this.$clippable.css( { width: '', height: '' } );
+               this.$clippable.width(); // Force reflow for https://code.google.com/p/chromium/issues/detail?id=387290
+               this.$clippable.css( { overflowX: '', overflowY: '' } );
+       }
+
+       this.$clippable = $clippable.addClass( 'oo-ui-clippableElement-clippable' );
+       this.clip();
 };
 
 /**
- * Show popup.
+ * Toggle clipping.
+ *
+ * Do not turn clipping on until after the element is attached to the DOM and visible.
+ *
+ * @param {boolean} [clipping] Enable clipping, omit to toggle
+ * @chainable
  */
-OO.ui.PopuppableElement.prototype.showPopup = function () {
-       this.popup.show().display( this.popupWidth, this.popupHeight );
+OO.ui.ClippableElement.prototype.toggleClipping = function ( clipping ) {
+       clipping = clipping === undefined ? !this.clipping : !!clipping;
+
+       if ( this.clipping !== clipping ) {
+               this.clipping = clipping;
+               if ( clipping ) {
+                       this.$clippableContainer = this.$( this.getClosestScrollableElementContainer() );
+                       // If the clippable container is the body, we have to listen to scroll events and check
+                       // jQuery.scrollTop on the window because of browser inconsistencies
+                       this.$clippableScroller = this.$clippableContainer.is( 'body' ) ?
+                               this.$( OO.ui.Element.getWindow( this.$clippableContainer ) ) :
+                               this.$clippableContainer;
+                       this.$clippableScroller.on( 'scroll', this.onClippableContainerScrollHandler );
+                       this.$clippableWindow = this.$( this.getElementWindow() )
+                               .on( 'resize', this.onClippableWindowResizeHandler );
+                       // Initial clip after visible
+                       this.clip();
+               } else {
+                       this.$clippable.css( { width: '', height: '' } );
+                       this.$clippable.width(); // Force reflow for https://code.google.com/p/chromium/issues/detail?id=387290
+                       this.$clippable.css( { overflowX: '', overflowY: '' } );
+
+                       this.$clippableContainer = null;
+                       this.$clippableScroller.off( 'scroll', this.onClippableContainerScrollHandler );
+                       this.$clippableScroller = null;
+                       this.$clippableWindow.off( 'resize', this.onClippableWindowResizeHandler );
+                       this.$clippableWindow = null;
+               }
+       }
+
+       return this;
 };
 
 /**
- * Hide popup.
+ * Check if the element will be clipped to fit the visible area of the nearest scrollable container.
+ *
+ * @return {boolean} Element will be clipped to the visible area
  */
-OO.ui.PopuppableElement.prototype.hidePopup = function () {
-       this.popup.hide();
+OO.ui.ClippableElement.prototype.isClipping = function () {
+       return this.clipping;
 };
 
 /**
- * Element with a title.
- *
- * @abstract
- * @class
+ * Check if the bottom or right of the element is being clipped by the nearest scrollable container.
  *
- * @constructor
- * @param {jQuery} $label Titled node, assigned to #$titled
- * @param {Object} [config] Configuration options
- * @cfg {string|Function} [title] Title text or a function that returns text
+ * @return {boolean} Part of the element is being clipped
  */
-OO.ui.TitledElement = function OoUiTitledElement( $titled, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Properties
-       this.$titled = $titled;
-       this.title = null;
-
-       // Initialization
-       this.setTitle( config.title || this.constructor.static.title );
+OO.ui.ClippableElement.prototype.isClipped = function () {
+       return this.clippedHorizontally || this.clippedVertically;
 };
 
-/* Setup */
-
-OO.initClass( OO.ui.TitledElement );
-
-/* Static Properties */
+/**
+ * Check if the right of the element is being clipped by the nearest scrollable container.
+ *
+ * @return {boolean} Part of the element is being clipped
+ */
+OO.ui.ClippableElement.prototype.isClippedHorizontally = function () {
+       return this.clippedHorizontally;
+};
 
 /**
- * Title.
+ * Check if the bottom of the element is being clipped by the nearest scrollable container.
  *
- * @static
- * @inheritable
- * @property {string|Function} Title text or a function that returns text
+ * @return {boolean} Part of the element is being clipped
  */
-OO.ui.TitledElement.static.title = null;
+OO.ui.ClippableElement.prototype.isClippedVertically = function () {
+       return this.clippedVertically;
+};
 
-/* Methods */
+/**
+ * Set the ideal size.
+ *
+ * @param {number|string} [width] Width as a number of pixels or CSS string with unit suffix
+ * @param {number|string} [height] Height as a number of pixels or CSS string with unit suffix
+ */
+OO.ui.ClippableElement.prototype.setIdealSize = function ( width, height ) {
+       this.idealWidth = width;
+       this.idealHeight = height;
+};
 
 /**
- * Set title.
+ * Clip element to visible boundaries and allow scrolling when needed. Call this method when
+ * the element's natural height changes.
+ *
+ * Element will be clipped the bottom or right of the element is within 10px of the edge of, or
+ * overlapped by, the visible area of the nearest scrollable container.
  *
- * @param {string|Function|null} title Title text, a function that returns text or null for no title
  * @chainable
  */
-OO.ui.TitledElement.prototype.setTitle = function ( title ) {
-       this.title = title = OO.ui.resolveMsg( title ) || null;
+OO.ui.ClippableElement.prototype.clip = function () {
+       if ( !this.clipping ) {
+               // this.$clippableContainer and this.$clippableWindow are null, so the below will fail
+               return this;
+       }
+
+       var buffer = 10,
+               cOffset = this.$clippable.offset(),
+               $container = this.$clippableContainer.is( 'body' ) ?
+                       this.$clippableWindow : this.$clippableContainer,
+               ccOffset = $container.offset() || { top: 0, left: 0 },
+               ccHeight = $container.innerHeight() - buffer,
+               ccWidth = $container.innerWidth() - buffer,
+               scrollTop = this.$clippableScroller.scrollTop(),
+               scrollLeft = this.$clippableScroller.scrollLeft(),
+               desiredWidth = ( ccOffset.left + scrollLeft + ccWidth ) - cOffset.left,
+               desiredHeight = ( ccOffset.top + scrollTop + ccHeight ) - cOffset.top,
+               naturalWidth = this.$clippable.prop( 'scrollWidth' ),
+               naturalHeight = this.$clippable.prop( 'scrollHeight' ),
+               clipWidth = desiredWidth < naturalWidth,
+               clipHeight = desiredHeight < naturalHeight;
 
-       if ( typeof title === 'string' && title.length ) {
-               this.$titled.attr( 'title', title );
+       if ( clipWidth ) {
+               this.$clippable.css( { overflowX: 'auto', width: desiredWidth } );
        } else {
-               this.$titled.removeAttr( 'title' );
+               this.$clippable.css( 'width', this.idealWidth || '' );
+               this.$clippable.width(); // Force reflow for https://code.google.com/p/chromium/issues/detail?id=387290
+               this.$clippable.css( 'overflowX', '' );
+       }
+       if ( clipHeight ) {
+               this.$clippable.css( { overflowY: 'auto', height: desiredHeight } );
+       } else {
+               this.$clippable.css( 'height', this.idealHeight || '' );
+               this.$clippable.height(); // Force reflow for https://code.google.com/p/chromium/issues/detail?id=387290
+               this.$clippable.css( 'overflowY', '' );
        }
 
-       return this;
-};
+       this.clippedHorizontally = clipWidth;
+       this.clippedVertically = clipHeight;
 
-/**
- * Get title.
- *
- * @return {string} Title string
- */
-OO.ui.TitledElement.prototype.getTitle = function () {
-       return this.title;
+       return this;
 };
 
 /**
@@ -3090,7 +4793,7 @@ OO.ui.TitledElement.prototype.getTitle = function () {
  * @abstract
  * @class
  * @extends OO.ui.Widget
- * @mixins OO.ui.IconedElement
+ * @mixins OO.ui.IconElement
  *
  * @constructor
  * @param {OO.ui.ToolGroup} toolGroup
@@ -3105,7 +4808,7 @@ OO.ui.Tool = function OoUiTool( toolGroup, config ) {
        OO.ui.Tool.super.call( this, config );
 
        // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.IconElement.call( this, config );
 
        // Properties
        this.toolGroup = toolGroup;
@@ -3116,7 +4819,7 @@ OO.ui.Tool = function OoUiTool( toolGroup, config ) {
        this.title = null;
 
        // Events
-       this.toolbar.connect( this, { 'updateState': 'onUpdateState' } );
+       this.toolbar.connect( this, { updateState: 'onUpdateState' } );
 
        // Initialization
        this.$title.addClass( 'oo-ui-tool-title' );
@@ -3138,7 +4841,7 @@ OO.ui.Tool = function OoUiTool( toolGroup, config ) {
 /* Setup */
 
 OO.inheritClass( OO.ui.Tool, OO.ui.Widget );
-OO.mixinClass( OO.ui.Tool, OO.ui.IconedElement );
+OO.mixinClass( OO.ui.Tool, OO.ui.IconElement );
 
 /* Events */
 
@@ -3362,7 +5065,7 @@ OO.ui.Toolbar = function OoUiToolbar( toolFactory, toolGroupFactory, config ) {
 
        // Mixin constructors
        OO.EventEmitter.call( this );
-       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
+       OO.ui.GroupElement.call( this, config );
 
        // Properties
        this.toolFactory = toolFactory;
@@ -3376,7 +5079,7 @@ OO.ui.Toolbar = function OoUiToolbar( toolFactory, toolGroupFactory, config ) {
        // Events
        this.$element
                .add( this.$bar ).add( this.$group ).add( this.$actions )
-               .on( 'mousedown', OO.ui.bind( this.onMouseDown, this ) );
+               .on( 'mousedown touchstart', OO.ui.bind( this.onPointerDown, this ) );
 
        // Initialization
        this.$group.addClass( 'oo-ui-toolbar-tools' );
@@ -3423,7 +5126,7 @@ OO.ui.Toolbar.prototype.getToolGroupFactory = function () {
  *
  * @param {jQuery.Event} e Mouse down event
  */
-OO.ui.Toolbar.prototype.onMouseDown = function ( e ) {
+OO.ui.Toolbar.prototype.onPointerDown = function ( e ) {
        var $closestWidgetToEvent = this.$( e.target ).closest( '.oo-ui-widget' ),
                $closestWidgetToToolbar = this.$element.closest( '.oo-ui-widget' );
        if ( !$closestWidgetToEvent.length || $closestWidgetToEvent[0] === $closestWidgetToToolbar[0] ) {
@@ -3444,8 +5147,8 @@ OO.ui.Toolbar.prototype.initialize = function () {
  *
  * Tools can be specified in the following ways:
  *
- * - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
- * - All tools in a group: `{ 'group': 'group-name' }`
+ * - A specific tool: `{ name: 'tool-name' }` or `'tool-name'`
+ * - All tools in a group: `{ group: 'group-name' }`
  * - All tools: `'*'` - Using this will make the group a list with a "More" label by default
  *
  * @param {Object.<string,Array>} groups List of tool group configurations
@@ -3477,7 +5180,7 @@ OO.ui.Toolbar.prototype.setup = function ( groups ) {
                // Check type has been registered
                type = this.getToolGroupFactory().lookup( group.type ) ? group.type : defaultType;
                items.push(
-                       this.getToolGroupFactory().create( type, this, $.extend( { '$': this.$ }, group ) )
+                       this.getToolGroupFactory().create( type, this, $.extend( { $: this.$ }, group ) )
                );
        }
        this.addItems( items );
@@ -3547,126 +5250,13 @@ OO.ui.Toolbar.prototype.getToolAccelerator = function () {
        return undefined;
 };
 
-/**
- * Factory for tools.
- *
- * @class
- * @extends OO.Factory
- * @constructor
- */
-OO.ui.ToolFactory = function OoUiToolFactory() {
-       // Parent constructor
-       OO.ui.ToolFactory.super.call( this );
-};
-
-/* Setup */
-
-OO.inheritClass( OO.ui.ToolFactory, OO.Factory );
-
-/* Methods */
-
-/** */
-OO.ui.ToolFactory.prototype.getTools = function ( include, exclude, promote, demote ) {
-       var i, len, included, promoted, demoted,
-               auto = [],
-               used = {};
-
-       // Collect included and not excluded tools
-       included = OO.simpleArrayDifference( this.extract( include ), this.extract( exclude ) );
-
-       // Promotion
-       promoted = this.extract( promote, used );
-       demoted = this.extract( demote, used );
-
-       // Auto
-       for ( i = 0, len = included.length; i < len; i++ ) {
-               if ( !used[included[i]] ) {
-                       auto.push( included[i] );
-               }
-       }
-
-       return promoted.concat( auto ).concat( demoted );
-};
-
-/**
- * Get a flat list of names from a list of names or groups.
- *
- * Tools can be specified in the following ways:
- *
- * - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
- * - All tools in a group: `{ 'group': 'group-name' }`
- * - All tools: `'*'`
- *
- * @private
- * @param {Array|string} collection List of tools
- * @param {Object} [used] Object with names that should be skipped as properties; extracted
- *  names will be added as properties
- * @return {string[]} List of extracted names
- */
-OO.ui.ToolFactory.prototype.extract = function ( collection, used ) {
-       var i, len, item, name, tool,
-               names = [];
-
-       if ( collection === '*' ) {
-               for ( name in this.registry ) {
-                       tool = this.registry[name];
-                       if (
-                               // Only add tools by group name when auto-add is enabled
-                               tool.static.autoAddToCatchall &&
-                               // Exclude already used tools
-                               ( !used || !used[name] )
-                       ) {
-                               names.push( name );
-                               if ( used ) {
-                                       used[name] = true;
-                               }
-                       }
-               }
-       } else if ( $.isArray( collection ) ) {
-               for ( i = 0, len = collection.length; i < len; i++ ) {
-                       item = collection[i];
-                       // Allow plain strings as shorthand for named tools
-                       if ( typeof item === 'string' ) {
-                               item = { 'name': item };
-                       }
-                       if ( OO.isPlainObject( item ) ) {
-                               if ( item.group ) {
-                                       for ( name in this.registry ) {
-                                               tool = this.registry[name];
-                                               if (
-                                                       // Include tools with matching group
-                                                       tool.static.group === item.group &&
-                                                       // Only add tools by group name when auto-add is enabled
-                                                       tool.static.autoAddToGroup &&
-                                                       // Exclude already used tools
-                                                       ( !used || !used[name] )
-                                               ) {
-                                                       names.push( name );
-                                                       if ( used ) {
-                                                               used[name] = true;
-                                                       }
-                                               }
-                                       }
-                               // Include tools with matching name and exclude already used tools
-                               } else if ( item.name && ( !used || !used[item.name] ) ) {
-                                       names.push( item.name );
-                                       if ( used ) {
-                                               used[item.name] = true;
-                                       }
-                               }
-                       }
-               }
-       }
-       return names;
-};
-
 /**
  * Collection of tools.
  *
  * Tools can be specified in the following ways:
  *
- * - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
- * - All tools in a group: `{ 'group': 'group-name' }`
+ * - A specific tool: `{ name: 'tool-name' }` or `'tool-name'`
+ * - All tools in a group: `{ group: 'group-name' }`
  * - All tools: `'*'`
  *
  * @abstract
@@ -3690,7 +5280,7 @@ OO.ui.ToolGroup = function OoUiToolGroup( toolbar, config ) {
        OO.ui.ToolGroup.super.call( this, config );
 
        // Mixin constructors
-       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
+       OO.ui.GroupElement.call( this, config );
 
        // Properties
        this.toolbar = toolbar;
@@ -3705,14 +5295,14 @@ OO.ui.ToolGroup = function OoUiToolGroup( toolbar, config ) {
 
        // Events
        this.$element.on( {
-               'mousedown': OO.ui.bind( this.onMouseDown, this ),
-               'mouseup': OO.ui.bind( this.onMouseUp, this ),
-               'mouseover': OO.ui.bind( this.onMouseOver, this ),
-               'mouseout': OO.ui.bind( this.onMouseOut, this )
+               'mousedown touchstart': OO.ui.bind( this.onPointerDown, this ),
+               'mouseup touchend': OO.ui.bind( this.onPointerUp, this ),
+               mouseover: OO.ui.bind( this.onMouseOver, this ),
+               mouseout: OO.ui.bind( this.onMouseOut, this )
        } );
-       this.toolbar.getToolFactory().connect( this, { 'register': 'onToolFactoryRegister' } );
-       this.aggregate( { 'disable': 'itemDisable' } );
-       this.connect( this, { 'itemDisable': 'updateDisabled' } );
+       this.toolbar.getToolFactory().connect( this, { register: 'onToolFactoryRegister' } );
+       this.aggregate( { disable: 'itemDisable' } );
+       this.connect( this, { itemDisable: 'updateDisabled' } );
 
        // Initialization
        this.$group.addClass( 'oo-ui-toolGroup-tools' );
@@ -3795,17 +5385,18 @@ OO.ui.ToolGroup.prototype.updateDisabled = function () {
  *
  * @param {jQuery.Event} e Mouse down event
  */
-OO.ui.ToolGroup.prototype.onMouseDown = function ( e ) {
-       if ( !this.isDisabled() && e.which === 1 ) {
+OO.ui.ToolGroup.prototype.onPointerDown = function ( e ) {
+       // e.which is 0 for touch events, 1 for left mouse button
+       if ( !this.isDisabled() && e.which <= 1 ) {
                this.pressed = this.getTargetTool( e );
                if ( this.pressed ) {
                        this.pressed.setActive( true );
                        this.getElementDocument().addEventListener(
                                'mouseup', this.onCapturedMouseUpHandler, true
                        );
-                       return false;
                }
        }
+       return false;
 };
 
 /**
@@ -3815,9 +5406,9 @@ OO.ui.ToolGroup.prototype.onMouseDown = function ( e ) {
  */
 OO.ui.ToolGroup.prototype.onCapturedMouseUp = function ( e ) {
        this.getElementDocument().removeEventListener( 'mouseup', this.onCapturedMouseUpHandler, true );
-       // onMouseUp may be called a second time, depending on where the mouse is when the button is
+       // onPointerUp may be called a second time, depending on where the mouse is when the button is
        // released, but since `this.pressed` will no longer be true, the second call will be ignored.
-       this.onMouseUp( e );
+       this.onPointerUp( e );
 };
 
 /**
@@ -3825,10 +5416,11 @@ OO.ui.ToolGroup.prototype.onCapturedMouseUp = function ( e ) {
  *
  * @param {jQuery.Event} e Mouse up event
  */
-OO.ui.ToolGroup.prototype.onMouseUp = function ( e ) {
+OO.ui.ToolGroup.prototype.onPointerUp = function ( e ) {
        var tool = this.getTargetTool( e );
 
-       if ( !this.isDisabled() && e.which === 1 && this.pressed && this.pressed === tool ) {
+       // e.which is 0 for touch events, 1 for left mouse button
+       if ( !this.isDisabled() && e.which <= 1 && this.pressed && this.pressed === tool ) {
                this.pressed.onSelect();
        }
 
@@ -3980,367 +5572,440 @@ OO.ui.ToolGroup.prototype.destroy = function () {
 };
 
 /**
- * Factory for tool groups.
- *
- * @class
- * @extends OO.Factory
- * @constructor
- */
-OO.ui.ToolGroupFactory = function OoUiToolGroupFactory() {
-       // Parent constructor
-       OO.Factory.call( this );
-
-       var i, l,
-               defaultClasses = this.constructor.static.getDefaultClasses();
-
-       // Register default toolgroups
-       for ( i = 0, l = defaultClasses.length; i < l; i++ ) {
-               this.register( defaultClasses[i] );
-       }
-};
-
-/* Setup */
-
-OO.inheritClass( OO.ui.ToolGroupFactory, OO.Factory );
-
-/* Static Methods */
-
-/**
- * Get a default set of classes to be registered on construction
- *
- * @return {Function[]} Default classes
- */
-OO.ui.ToolGroupFactory.static.getDefaultClasses = function () {
-       return [
-               OO.ui.BarToolGroup,
-               OO.ui.ListToolGroup,
-               OO.ui.MenuToolGroup
-       ];
-};
-
-/**
- * Layout made of a fieldset and optional legend.
- *
- * Just add OO.ui.FieldLayout items.
- *
- * @class
- * @extends OO.ui.Layout
- * @mixins OO.ui.LabeledElement
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.GroupElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string} [icon] Symbolic icon name
- * @cfg {OO.ui.FieldLayout[]} [items] Items to add
- */
-OO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) {
-       // Config initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.FieldsetLayout.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$( '<div>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<div>' ), config );
-       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
-
-       // Initialization
-       this.$element
-               .addClass( 'oo-ui-fieldsetLayout' )
-               .prepend( this.$icon, this.$label, this.$group );
-       if ( $.isArray( config.items ) ) {
-               this.addItems( config.items );
-       }
-};
-
-/* Setup */
-
-OO.inheritClass( OO.ui.FieldsetLayout, OO.ui.Layout );
-OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.LabeledElement );
-OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.GroupElement );
-
-/* Static Properties */
-
-OO.ui.FieldsetLayout.static.tagName = 'div';
-
-/**
- * Layout made of a field and optional label.
+ * Dialog for showing a message.
  *
- * @class
- * @extends OO.ui.Layout
- * @mixins OO.ui.LabeledElement
+ * User interface:
+ * - Registers two actions by default (safe and primary).
+ * - Renders action widgets in the footer.
  *
- * Available label alignment modes include:
- *  - 'left': Label is before the field and aligned away from it, best for when the user will be
- *    scanning for a specific label in a form with many fields
- *  - 'right': Label is before the field and aligned toward it, best for forms the user is very
- *    familiar with and will tab through field checking quickly to verify which field they are in
- *  - 'top': Label is before the field and above it, best for when the use will need to fill out all
- *    fields from top to bottom in a form with few fields
- *  - 'inline': Label is after the field and aligned toward it, best for small boolean fields like
- *    checkboxes or radio buttons
+ * @class
+ * @extends OO.ui.Dialog
  *
  * @constructor
- * @param {OO.ui.Widget} field Field widget
  * @param {Object} [config] Configuration options
- * @cfg {string} [align='left'] Alignment mode, either 'left', 'right', 'top' or 'inline'
  */
-OO.ui.FieldLayout = function OoUiFieldLayout( field, config ) {
-       // Config initialization
-       config = $.extend( { 'align': 'left' }, config );
-
+OO.ui.MessageDialog = function OoUiMessageDialog( config ) {
        // Parent constructor
-       OO.ui.FieldLayout.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.LabeledElement.call( this, this.$( '<label>' ), config );
+       OO.ui.MessageDialog.super.call( this, config );
 
        // Properties
-       this.$field = this.$( '<div>' );
-       this.field = field;
-       this.align = null;
-
-       // Events
-       if ( this.field instanceof OO.ui.InputWidget ) {
-               this.$label.on( 'click', OO.ui.bind( this.onLabelClick, this ) );
-       }
-       this.field.connect( this, { 'disable': 'onFieldDisable' } );
+       this.verticalActionLayout = null;
 
        // Initialization
-       this.$element.addClass( 'oo-ui-fieldLayout' );
-       this.$field
-               .addClass( 'oo-ui-fieldLayout-field' )
-               .toggleClass( 'oo-ui-fieldLayout-disable', this.field.isDisabled() )
-               .append( this.field.$element );
-       this.setAlignment( config.align );
+       this.$element.addClass( 'oo-ui-messageDialog' );
 };
 
-/* Setup */
+/* Inheritance */
 
-OO.inheritClass( OO.ui.FieldLayout, OO.ui.Layout );
-OO.mixinClass( OO.ui.FieldLayout, OO.ui.LabeledElement );
+OO.inheritClass( OO.ui.MessageDialog, OO.ui.Dialog );
 
-/* Methods */
+/* Static Properties */
+
+OO.ui.MessageDialog.static.name = 'message';
+
+OO.ui.MessageDialog.static.size = 'small';
+
+OO.ui.MessageDialog.static.verbose = false;
 
 /**
- * Handle field disable events.
+ * Dialog title.
  *
- * @param {boolean} value Field is disabled
+ * A confirmation dialog's title should describe what the progressive action will do. An alert
+ * dialog's title should describe what event occured.
+ *
+ * @static
+ * inheritable
+ * @property {jQuery|string|Function|null}
  */
-OO.ui.FieldLayout.prototype.onFieldDisable = function ( value ) {
-       this.$element.toggleClass( 'oo-ui-fieldLayout-disabled', value );
-};
+OO.ui.MessageDialog.static.title = null;
 
 /**
- * Handle label mouse click events.
+ * A confirmation dialog's message should describe the consequences of the progressive action. An
+ * alert dialog's message should describe why the event occured.
  *
- * @param {jQuery.Event} e Mouse click event
+ * @static
+ * inheritable
+ * @property {jQuery|string|Function|null}
  */
-OO.ui.FieldLayout.prototype.onLabelClick = function () {
-       this.field.simulateLabelClick();
-       return false;
-};
+OO.ui.MessageDialog.static.message = null;
+
+OO.ui.MessageDialog.static.actions = [
+       { action: 'accept', label: OO.ui.deferMsg( 'ooui-dialog-message-accept' ), flags: 'primary' },
+       { action: 'reject', label: OO.ui.deferMsg( 'ooui-dialog-message-reject' ), flags: 'safe' }
+];
+
+/* Methods */
 
 /**
- * Get the field.
- *
- * @return {OO.ui.Widget} Field widget
+ * @inheritdoc
  */
-OO.ui.FieldLayout.prototype.getField = function () {
-       return this.field;
+OO.ui.MessageDialog.prototype.onActionResize = function ( action ) {
+       this.fitActions();
+       return OO.ui.ProcessDialog.super.prototype.onActionResize.call( this, action );
 };
 
 /**
- * Set the field alignment mode.
+ * Toggle action layout between vertical and horizontal.
  *
- * @param {string} value Alignment mode, either 'left', 'right', 'top' or 'inline'
+ * @param {boolean} [value] Layout actions vertically, omit to toggle
  * @chainable
  */
-OO.ui.FieldLayout.prototype.setAlignment = function ( value ) {
-       if ( value !== this.align ) {
-               // Default to 'left'
-               if ( [ 'left', 'right', 'top', 'inline' ].indexOf( value ) === -1 ) {
-                       value = 'left';
-               }
-               // Reorder elements
-               if ( value === 'inline' ) {
-                       this.$element.append( this.$field, this.$label );
-               } else {
-                       this.$element.append( this.$label, this.$field );
-               }
-               // Set classes
-               if ( this.align ) {
-                       this.$element.removeClass( 'oo-ui-fieldLayout-align-' + this.align );
-               }
-               this.align = value;
-               this.$element.addClass( 'oo-ui-fieldLayout-align-' + this.align );
+OO.ui.MessageDialog.prototype.toggleVerticalActionLayout = function ( value ) {
+       value = value === undefined ? !this.verticalActionLayout : !!value;
+
+       if ( value !== this.verticalActionLayout ) {
+               this.verticalActionLayout = value;
+               this.$actions
+                       .toggleClass( 'oo-ui-messageDialog-actions-vertical', value )
+                       .toggleClass( 'oo-ui-messageDialog-actions-horizontal', !value );
        }
 
        return this;
 };
 
 /**
- * Layout made of proportionally sized columns and rows.
- *
- * @class
- * @extends OO.ui.Layout
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.prototype.getActionProcess = function ( action ) {
+       if ( action ) {
+               return new OO.ui.Process( function () {
+                       this.close( { action: action } );
+               }, this );
+       }
+       return OO.ui.MessageDialog.super.prototype.getActionProcess.call( this, action );
+};
+
+/**
+ * @inheritdoc
  *
- * @constructor
- * @param {OO.ui.PanelLayout[]} panels Panels in the grid
- * @param {Object} [config] Configuration options
- * @cfg {number[]} [widths] Widths of columns as ratios
- * @cfg {number[]} [heights] Heights of columns as ratios
+ * @param {Object} [data] Dialog opening data
+ * @param {jQuery|string|Function|null} [data.title] Description of the action being confirmed
+ * @param {jQuery|string|Function|null} [data.message] Description of the action's consequence
+ * @param {boolean} [data.verbose] Message is verbose and should be styled as a long message
+ * @param {Object[]} [data.actions] List of OO.ui.ActionOptionWidget configuration options for each
+ *   action item
  */
-OO.ui.GridLayout = function OoUiGridLayout( panels, config ) {
-       var i, len, widths;
+OO.ui.MessageDialog.prototype.getSetupProcess = function ( data ) {
+       data = data || {};
 
-       // Config initialization
-       config = config || {};
+       // Parent method
+       return OO.ui.MessageDialog.super.prototype.getSetupProcess.call( this, data )
+               .next( function () {
+                       this.title.setLabel(
+                               data.title !== undefined ? data.title : this.constructor.static.title
+                       );
+                       this.message.setLabel(
+                               data.message !== undefined ? data.message : this.constructor.static.message
+                       );
+                       this.message.$element.toggleClass(
+                               'oo-ui-messageDialog-message-verbose',
+                               data.verbose !== undefined ? data.verbose : this.constructor.static.verbose
+                       );
+               }, this );
+};
 
-       // Parent constructor
-       OO.ui.GridLayout.super.call( this, config );
+/**
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.prototype.getBodyHeight = function () {
+       return Math.round( this.text.$element.outerHeight( true ) );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.prototype.initialize = function () {
+       // Parent method
+       OO.ui.MessageDialog.super.prototype.initialize.call( this );
 
        // Properties
-       this.panels = [];
-       this.widths = [];
-       this.heights = [];
+       this.$actions = this.$( '<div>' );
+       this.container = new OO.ui.PanelLayout( {
+               $: this.$, scrollable: true, classes: [ 'oo-ui-messageDialog-container' ]
+       } );
+       this.text = new OO.ui.PanelLayout( {
+               $: this.$, padded: true, expanded: false, classes: [ 'oo-ui-messageDialog-text' ]
+       } );
+       this.message = new OO.ui.LabelWidget( {
+               $: this.$, classes: [ 'oo-ui-messageDialog-message' ]
+       } );
 
        // Initialization
-       this.$element.addClass( 'oo-ui-gridLayout' );
-       for ( i = 0, len = panels.length; i < len; i++ ) {
-               this.panels.push( panels[i] );
-               this.$element.append( panels[i].$element );
-       }
-       if ( config.widths || config.heights ) {
-               this.layout( config.widths || [ 1 ], config.heights || [ 1 ] );
-       } else {
-               // Arrange in columns by default
-               widths = [];
-               for ( i = 0, len = this.panels.length; i < len; i++ ) {
-                       widths[i] = 1;
-               }
-               this.layout( widths, [ 1 ] );
-       }
+       this.title.$element.addClass( 'oo-ui-messageDialog-title' );
+       this.$content.addClass( 'oo-ui-messageDialog-content' );
+       this.container.$element.append( this.text.$element );
+       this.text.$element.append( this.title.$element, this.message.$element );
+       this.$body.append( this.container.$element );
+       this.$actions.addClass( 'oo-ui-messageDialog-actions' );
+       this.$foot.append( this.$actions );
 };
 
-/* Setup */
+/**
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.prototype.attachActions = function () {
+       var i, len, other, special, others;
 
-OO.inheritClass( OO.ui.GridLayout, OO.ui.Layout );
+       // Parent method
+       OO.ui.MessageDialog.super.prototype.attachActions.call( this );
+
+       special = this.actions.getSpecial();
+       others = this.actions.getOthers();
+       if ( special.safe ) {
+               this.$actions.append( special.safe.$element );
+               special.safe.toggleFramed( false );
+       }
+       if ( others.length ) {
+               for ( i = 0, len = others.length; i < len; i++ ) {
+                       other = others[i];
+                       this.$actions.append( other.$element );
+                       other.toggleFramed( false );
+               }
+       }
+       if ( special.primary ) {
+               this.$actions.append( special.primary.$element );
+               special.primary.toggleFramed( false );
+       }
 
-/* Events */
+       this.fitActions();
+       if ( !this.isOpening() ) {
+               this.manager.updateWindowSize( this );
+       }
+       this.$body.css( 'bottom', this.$foot.outerHeight( true ) );
+};
 
 /**
- * @event layout
+ * Fit action actions into columns or rows.
+ *
+ * Columns will be used if all labels can fit without overflow, otherwise rows will be used.
  */
+OO.ui.MessageDialog.prototype.fitActions = function () {
+       var i, len, action,
+               actions = this.actions.get();
+
+       // Detect clipping
+       this.toggleVerticalActionLayout( false );
+       for ( i = 0, len = actions.length; i < len; i++ ) {
+               action = actions[i];
+               if ( action.$element.innerWidth() < action.$label.outerWidth( true ) ) {
+                       this.toggleVerticalActionLayout( true );
+                       break;
+               }
+       }
+};
 
 /**
- * @event update
+ * Navigation dialog window.
+ *
+ * Logic:
+ * - Show and hide errors.
+ * - Retry an action.
+ *
+ * User interface:
+ * - Renders header with dialog title and one action widget on either side
+ *   (a 'safe' button on the left, and a 'primary' button on the right, both of
+ *   which close the dialog).
+ * - Displays any action widgets in the footer (none by default).
+ * - Ability to dismiss errors.
+ *
+ * Subclass responsibilities:
+ * - Register a 'safe' action.
+ * - Register a 'primary' action.
+ * - Add content to the dialog.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Dialog
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
  */
+OO.ui.ProcessDialog = function OoUiProcessDialog( config ) {
+       // Parent constructor
+       OO.ui.ProcessDialog.super.call( this, config );
 
-/* Static Properties */
+       // Initialization
+       this.$element.addClass( 'oo-ui-processDialog' );
+};
 
-OO.ui.GridLayout.static.tagName = 'div';
+/* Setup */
+
+OO.inheritClass( OO.ui.ProcessDialog, OO.ui.Dialog );
 
 /* Methods */
 
 /**
- * Set grid dimensions.
+ * Handle dismiss button click events.
  *
- * @param {number[]} widths Widths of columns as ratios
- * @param {number[]} heights Heights of rows as ratios
- * @fires layout
- * @throws {Error} If grid is not large enough to fit all panels
+ * Hides errors.
  */
-OO.ui.GridLayout.prototype.layout = function ( widths, heights ) {
-       var x, y,
-               xd = 0,
-               yd = 0,
-               cols = widths.length,
-               rows = heights.length;
+OO.ui.ProcessDialog.prototype.onDismissErrorButtonClick = function () {
+       this.hideErrors();
+};
 
-       // Verify grid is big enough to fit panels
-       if ( cols * rows < this.panels.length ) {
-               throw new Error( 'Grid is not large enough to fit ' + this.panels.length + 'panels' );
-       }
+/**
+ * Handle retry button click events.
+ *
+ * Hides errors and then tries again.
+ */
+OO.ui.ProcessDialog.prototype.onRetryButtonClick = function () {
+       this.hideErrors();
+       this.executeAction( this.currentAction.getAction() );
+};
 
-       // Sum up denominators
-       for ( x = 0; x < cols; x++ ) {
-               xd += widths[x];
-       }
-       for ( y = 0; y < rows; y++ ) {
-               yd += heights[y];
-       }
-       // Store factors
-       this.widths = [];
-       this.heights = [];
-       for ( x = 0; x < cols; x++ ) {
-               this.widths[x] = widths[x] / xd;
-       }
-       for ( y = 0; y < rows; y++ ) {
-               this.heights[y] = heights[y] / yd;
+/**
+ * @inheritdoc
+ */
+OO.ui.ProcessDialog.prototype.onActionResize = function ( action ) {
+       if ( this.actions.isSpecial( action ) ) {
+               this.fitLabel();
        }
-       // Synchronize view
-       this.update();
-       this.emit( 'layout' );
+       return OO.ui.ProcessDialog.super.prototype.onActionResize.call( this, action );
 };
 
 /**
- * Update panel positions and sizes.
- *
- * @fires update
+ * @inheritdoc
  */
-OO.ui.GridLayout.prototype.update = function () {
-       var x, y, panel,
-               i = 0,
-               left = 0,
-               top = 0,
-               dimensions,
-               width = 0,
-               height = 0,
-               cols = this.widths.length,
-               rows = this.heights.length;
+OO.ui.ProcessDialog.prototype.initialize = function () {
+       // Parent method
+       OO.ui.ProcessDialog.super.prototype.initialize.call( this );
 
-       for ( y = 0; y < rows; y++ ) {
-               for ( x = 0; x < cols; x++ ) {
-                       panel = this.panels[i];
-                       width = this.widths[x];
-                       height = this.heights[y];
-                       dimensions = {
-                               'width': Math.round( width * 100 ) + '%',
-                               'height': Math.round( height * 100 ) + '%',
-                               'top': Math.round( top * 100 ) + '%'
-                       };
-                       // If RTL, reverse:
-                       if ( OO.ui.Element.getDir( this.$.context ) === 'rtl' ) {
-                               dimensions.right = Math.round( left * 100 ) + '%';
-                       } else {
-                               dimensions.left = Math.round( left * 100 ) + '%';
-                       }
-                       panel.$element.css( dimensions );
-                       i++;
-                       left += width;
+       // Properties
+       this.$navigation = this.$( '<div>' );
+       this.$location = this.$( '<div>' );
+       this.$safeActions = this.$( '<div>' );
+       this.$primaryActions = this.$( '<div>' );
+       this.$otherActions = this.$( '<div>' );
+       this.dismissButton = new OO.ui.ButtonWidget( {
+               $: this.$,
+               label: OO.ui.msg( 'ooui-dialog-process-dismiss' )
+       } );
+       this.retryButton = new OO.ui.ButtonWidget( {
+               $: this.$,
+               label: OO.ui.msg( 'ooui-dialog-process-retry' )
+       } );
+       this.$errors = this.$( '<div>' );
+       this.$errorsTitle = this.$( '<div>' );
+
+       // Events
+       this.dismissButton.connect( this, { click: 'onDismissErrorButtonClick' } );
+       this.retryButton.connect( this, { click: 'onRetryButtonClick' } );
+
+       // Initialization
+       this.title.$element.addClass( 'oo-ui-processDialog-title' );
+       this.$location
+               .append( this.title.$element )
+               .addClass( 'oo-ui-processDialog-location' );
+       this.$safeActions.addClass( 'oo-ui-processDialog-actions-safe' );
+       this.$primaryActions.addClass( 'oo-ui-processDialog-actions-primary' );
+       this.$otherActions.addClass( 'oo-ui-processDialog-actions-other' );
+       this.$errorsTitle
+               .addClass( 'oo-ui-processDialog-errors-title' )
+               .text( OO.ui.msg( 'ooui-dialog-process-error' ) );
+       this.$errors
+               .addClass( 'oo-ui-processDialog-errors' )
+               .append( this.$errorsTitle, this.dismissButton.$element, this.retryButton.$element );
+       this.$content
+               .addClass( 'oo-ui-processDialog-content' )
+               .append( this.$errors );
+       this.$navigation
+               .addClass( 'oo-ui-processDialog-navigation' )
+               .append( this.$safeActions, this.$location, this.$primaryActions );
+       this.$head.append( this.$navigation );
+       this.$foot.append( this.$otherActions );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ProcessDialog.prototype.attachActions = function () {
+       var i, len, other, special, others;
+
+       // Parent method
+       OO.ui.ProcessDialog.super.prototype.attachActions.call( this );
+
+       special = this.actions.getSpecial();
+       others = this.actions.getOthers();
+       if ( special.primary ) {
+               this.$primaryActions.append( special.primary.$element );
+               special.primary.toggleFramed( true );
+       }
+       if ( others.length ) {
+               for ( i = 0, len = others.length; i < len; i++ ) {
+                       other = others[i];
+                       this.$otherActions.append( other.$element );
+                       other.toggleFramed( true );
                }
-               top += height;
-               left = 0;
+       }
+       if ( special.safe ) {
+               this.$safeActions.append( special.safe.$element );
+               special.safe.toggleFramed( true );
        }
 
-       this.emit( 'update' );
+       this.fitLabel();
+       this.$body.css( 'bottom', this.$foot.outerHeight( true ) );
 };
 
 /**
- * Get a panel at a given position.
+ * @inheritdoc
+ */
+OO.ui.ProcessDialog.prototype.executeAction = function ( action ) {
+       OO.ui.ProcessDialog.super.prototype.executeAction.call( this, action )
+               .fail( OO.ui.bind( this.showErrors, this ) );
+};
+
+/**
+ * Fit label between actions.
  *
- * The x and y position is affected by the current grid layout.
+ * @chainable
+ */
+OO.ui.ProcessDialog.prototype.fitLabel = function () {
+       var width = Math.max(
+               this.$safeActions.is( ':visible' ) ? this.$safeActions.width() : 0,
+               this.$primaryActions.is( ':visible' ) ? this.$primaryActions.width() : 0
+       );
+       this.$location.css( { paddingLeft: width, paddingRight: width } );
+
+       return this;
+};
+
+/**
+ * Handle errors that occured durring accept or reject processes.
  *
- * @param {number} x Horizontal position
- * @param {number} y Vertical position
- * @return {OO.ui.PanelLayout} The panel at the given postion
+ * @param {OO.ui.Error[]} errors Errors to be handled
  */
-OO.ui.GridLayout.prototype.getPanel = function ( x, y ) {
-       return this.panels[( x * this.widths.length ) + y];
+OO.ui.ProcessDialog.prototype.showErrors = function ( errors ) {
+       var i, len, $item,
+               items = [],
+               recoverable = true;
+
+       for ( i = 0, len = errors.length; i < len; i++ ) {
+               if ( !errors[i].isRecoverable() ) {
+                       recoverable = false;
+               }
+               $item = this.$( '<div>' )
+                       .addClass( 'oo-ui-processDialog-error' )
+                       .append( errors[i].getMessage() );
+               items.push( $item[0] );
+       }
+       this.$errorItems = this.$( items );
+       if ( recoverable ) {
+               this.retryButton.clearFlags().setFlags( this.currentAction.getFlags() );
+       } else {
+               this.currentAction.setDisabled( true );
+       }
+       this.retryButton.toggle( recoverable );
+       this.$errorsTitle.after( this.$errorItems );
+       this.$errors.show().scrollTop( 0 );
+};
+
+/**
+ * Hide errors.
+ */
+OO.ui.ProcessDialog.prototype.hideErrors = function () {
+       this.$errors.hide();
+       this.$errorItems.remove();
+       this.$errorItems = null;
 };
 
 /**
@@ -4367,31 +6032,31 @@ OO.ui.BookletLayout = function OoUiBookletLayout( config ) {
        this.currentPageName = null;
        this.pages = {};
        this.ignoreFocus = false;
-       this.stackLayout = new OO.ui.StackLayout( { '$': this.$, 'continuous': !!config.continuous } );
-       this.autoFocus = config.autoFocus === undefined ? true : !!config.autoFocus;
+       this.stackLayout = new OO.ui.StackLayout( { $: this.$, continuous: !!config.continuous } );
+       this.autoFocus = config.autoFocus === undefined || !!config.autoFocus;
        this.outlineVisible = false;
        this.outlined = !!config.outlined;
        if ( this.outlined ) {
                this.editable = !!config.editable;
                this.outlineControlsWidget = null;
-               this.outlineWidget = new OO.ui.OutlineWidget( { '$': this.$ } );
-               this.outlinePanel = new OO.ui.PanelLayout( { '$': this.$, 'scrollable': true } );
+               this.outlineWidget = new OO.ui.OutlineWidget( { $: this.$ } );
+               this.outlinePanel = new OO.ui.PanelLayout( { $: this.$, scrollable: true } );
                this.gridLayout = new OO.ui.GridLayout(
                        [ this.outlinePanel, this.stackLayout ],
-                       { '$': this.$, 'widths': [ 1, 2 ] }
+                       { $: this.$, widths: [ 1, 2 ] }
                );
                this.outlineVisible = true;
                if ( this.editable ) {
                        this.outlineControlsWidget = new OO.ui.OutlineControlsWidget(
-                               this.outlineWidget, { '$': this.$ }
+                               this.outlineWidget, { $: this.$ }
                        );
                }
        }
 
        // Events
-       this.stackLayout.connect( this, { 'set': 'onStackLayoutSet' } );
+       this.stackLayout.connect( this, { set: 'onStackLayoutSet' } );
        if ( this.outlined ) {
-               this.outlineWidget.connect( this, { 'select': 'onOutlineWidgetSelect' } );
+               this.outlineWidget.connect( this, { select: 'onOutlineWidgetSelect' } );
        }
        if ( this.autoFocus ) {
                // Event 'focus' does not bubble, but 'focusin' does
@@ -4410,356 +6075,764 @@ OO.ui.BookletLayout = function OoUiBookletLayout( config ) {
                                .addClass( 'oo-ui-bookletLayout-outlinePanel-editable' )
                                .append( this.outlineControlsWidget.$element );
                }
-               this.$element.append( this.gridLayout.$element );
-       } else {
-               this.$element.append( this.stackLayout.$element );
+               this.$element.append( this.gridLayout.$element );
+       } else {
+               this.$element.append( this.stackLayout.$element );
+       }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.BookletLayout, OO.ui.Layout );
+
+/* Events */
+
+/**
+ * @event set
+ * @param {OO.ui.PageLayout} page Current page
+ */
+
+/**
+ * @event add
+ * @param {OO.ui.PageLayout[]} page Added pages
+ * @param {number} index Index pages were added at
+ */
+
+/**
+ * @event remove
+ * @param {OO.ui.PageLayout[]} pages Removed pages
+ */
+
+/* Methods */
+
+/**
+ * Handle stack layout focus.
+ *
+ * @param {jQuery.Event} e Focusin event
+ */
+OO.ui.BookletLayout.prototype.onStackLayoutFocus = function ( e ) {
+       var name, $target;
+
+       // Find the page that an element was focused within
+       $target = $( e.target ).closest( '.oo-ui-pageLayout' );
+       for ( name in this.pages ) {
+               // Check for page match, exclude current page to find only page changes
+               if ( this.pages[name].$element[0] === $target[0] && name !== this.currentPageName ) {
+                       this.setPage( name );
+                       break;
+               }
+       }
+};
+
+/**
+ * Handle stack layout set events.
+ *
+ * @param {OO.ui.PanelLayout|null} page The page panel that is now the current panel
+ */
+OO.ui.BookletLayout.prototype.onStackLayoutSet = function ( page ) {
+       var $input, layout = this;
+       if ( page ) {
+               page.scrollElementIntoView( { complete: function () {
+                       if ( layout.autoFocus ) {
+                               // Set focus to the first input if nothing on the page is focused yet
+                               if ( !page.$element.find( ':focus' ).length ) {
+                                       $input = page.$element.find( ':input:first' );
+                                       if ( $input.length ) {
+                                               $input[0].focus();
+                                       }
+                               }
+                       }
+               } } );
+       }
+};
+
+/**
+ * Handle outline widget select events.
+ *
+ * @param {OO.ui.OptionWidget|null} item Selected item
+ */
+OO.ui.BookletLayout.prototype.onOutlineWidgetSelect = function ( item ) {
+       if ( item ) {
+               this.setPage( item.getData() );
+       }
+};
+
+/**
+ * Check if booklet has an outline.
+ *
+ * @return {boolean}
+ */
+OO.ui.BookletLayout.prototype.isOutlined = function () {
+       return this.outlined;
+};
+
+/**
+ * Check if booklet has editing controls.
+ *
+ * @return {boolean}
+ */
+OO.ui.BookletLayout.prototype.isEditable = function () {
+       return this.editable;
+};
+
+/**
+ * Check if booklet has a visible outline.
+ *
+ * @return {boolean}
+ */
+OO.ui.BookletLayout.prototype.isOutlineVisible = function () {
+       return this.outlined && this.outlineVisible;
+};
+
+/**
+ * Hide or show the outline.
+ *
+ * @param {boolean} [show] Show outline, omit to invert current state
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.toggleOutline = function ( show ) {
+       if ( this.outlined ) {
+               show = show === undefined ? !this.outlineVisible : !!show;
+               this.outlineVisible = show;
+               this.gridLayout.layout( show ? [ 1, 2 ] : [ 0, 1 ], [ 1 ] );
+       }
+
+       return this;
+};
+
+/**
+ * Get the outline widget.
+ *
+ * @param {OO.ui.PageLayout} page Page to be selected
+ * @return {OO.ui.PageLayout|null} Closest page to another
+ */
+OO.ui.BookletLayout.prototype.getClosestPage = function ( page ) {
+       var next, prev, level,
+               pages = this.stackLayout.getItems(),
+               index = $.inArray( page, pages );
+
+       if ( index !== -1 ) {
+               next = pages[index + 1];
+               prev = pages[index - 1];
+               // Prefer adjacent pages at the same level
+               if ( this.outlined ) {
+                       level = this.outlineWidget.getItemFromData( page.getName() ).getLevel();
+                       if (
+                               prev &&
+                               level === this.outlineWidget.getItemFromData( prev.getName() ).getLevel()
+                       ) {
+                               return prev;
+                       }
+                       if (
+                               next &&
+                               level === this.outlineWidget.getItemFromData( next.getName() ).getLevel()
+                       ) {
+                               return next;
+                       }
+               }
+       }
+       return prev || next || null;
+};
+
+/**
+ * Get the outline widget.
+ *
+ * @return {OO.ui.OutlineWidget|null} Outline widget, or null if boolet has no outline
+ */
+OO.ui.BookletLayout.prototype.getOutline = function () {
+       return this.outlineWidget;
+};
+
+/**
+ * Get the outline controls widget. If the outline is not editable, null is returned.
+ *
+ * @return {OO.ui.OutlineControlsWidget|null} The outline controls widget.
+ */
+OO.ui.BookletLayout.prototype.getOutlineControls = function () {
+       return this.outlineControlsWidget;
+};
+
+/**
+ * Get a page by name.
+ *
+ * @param {string} name Symbolic name of page
+ * @return {OO.ui.PageLayout|undefined} Page, if found
+ */
+OO.ui.BookletLayout.prototype.getPage = function ( name ) {
+       return this.pages[name];
+};
+
+/**
+ * Get the current page name.
+ *
+ * @return {string|null} Current page name
+ */
+OO.ui.BookletLayout.prototype.getPageName = function () {
+       return this.currentPageName;
+};
+
+/**
+ * Add a page to the layout.
+ *
+ * When pages are added with the same names as existing pages, the existing pages will be
+ * automatically removed before the new pages are added.
+ *
+ * @param {OO.ui.PageLayout[]} pages Pages to add
+ * @param {number} index Index to insert pages after
+ * @fires add
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.addPages = function ( pages, index ) {
+       var i, len, name, page, item, currentIndex,
+               stackLayoutPages = this.stackLayout.getItems(),
+               remove = [],
+               items = [];
+
+       // Remove pages with same names
+       for ( i = 0, len = pages.length; i < len; i++ ) {
+               page = pages[i];
+               name = page.getName();
+
+               if ( Object.prototype.hasOwnProperty.call( this.pages, name ) ) {
+                       // Correct the insertion index
+                       currentIndex = $.inArray( this.pages[name], stackLayoutPages );
+                       if ( currentIndex !== -1 && currentIndex + 1 < index ) {
+                               index--;
+                       }
+                       remove.push( this.pages[name] );
+               }
+       }
+       if ( remove.length ) {
+               this.removePages( remove );
        }
-};
-
-/* Setup */
 
-OO.inheritClass( OO.ui.BookletLayout, OO.ui.Layout );
+       // Add new pages
+       for ( i = 0, len = pages.length; i < len; i++ ) {
+               page = pages[i];
+               name = page.getName();
+               this.pages[page.getName()] = page;
+               if ( this.outlined ) {
+                       item = new OO.ui.OutlineItemWidget( name, page, { $: this.$ } );
+                       page.setOutlineItem( item );
+                       items.push( item );
+               }
+       }
 
-/* Events */
+       if ( this.outlined && items.length ) {
+               this.outlineWidget.addItems( items, index );
+               this.updateOutlineWidget();
+       }
+       this.stackLayout.addItems( pages, index );
+       this.emit( 'add', pages, index );
 
-/**
- * @event set
- * @param {OO.ui.PageLayout} page Current page
- */
+       return this;
+};
 
 /**
- * @event add
- * @param {OO.ui.PageLayout[]} page Added pages
- * @param {number} index Index pages were added at
+ * Remove a page from the layout.
+ *
+ * @fires remove
+ * @chainable
  */
+OO.ui.BookletLayout.prototype.removePages = function ( pages ) {
+       var i, len, name, page,
+               items = [];
 
-/**
- * @event remove
- * @param {OO.ui.PageLayout[]} pages Removed pages
- */
+       for ( i = 0, len = pages.length; i < len; i++ ) {
+               page = pages[i];
+               name = page.getName();
+               delete this.pages[name];
+               if ( this.outlined ) {
+                       items.push( this.outlineWidget.getItemFromData( name ) );
+                       page.setOutlineItem( null );
+               }
+       }
+       if ( this.outlined && items.length ) {
+               this.outlineWidget.removeItems( items );
+               this.updateOutlineWidget();
+       }
+       this.stackLayout.removeItems( pages );
+       this.emit( 'remove', pages );
 
-/* Methods */
+       return this;
+};
 
 /**
- * Handle stack layout focus.
+ * Clear all pages from the layout.
  *
- * @param {jQuery.Event} e Focusin event
+ * @fires remove
+ * @chainable
  */
-OO.ui.BookletLayout.prototype.onStackLayoutFocus = function ( e ) {
-       var name, $target;
+OO.ui.BookletLayout.prototype.clearPages = function () {
+       var i, len,
+               pages = this.stackLayout.getItems();
 
-       // Find the page that an element was focused within
-       $target = $( e.target ).closest( '.oo-ui-pageLayout' );
-       for ( name in this.pages ) {
-               // Check for page match, exclude current page to find only page changes
-               if ( this.pages[name].$element[0] === $target[0] && name !== this.currentPageName ) {
-                       this.setPage( name );
-                       break;
+       this.pages = {};
+       this.currentPageName = null;
+       if ( this.outlined ) {
+               this.outlineWidget.clearItems();
+               for ( i = 0, len = pages.length; i < len; i++ ) {
+                       pages[i].setOutlineItem( null );
                }
        }
+       this.stackLayout.clearItems();
+
+       this.emit( 'remove', pages );
+
+       return this;
 };
 
 /**
- * Handle stack layout set events.
+ * Set the current page by name.
  *
- * @param {OO.ui.PanelLayout|null} page The page panel that is now the current panel
+ * @fires set
+ * @param {string} name Symbolic name of page
  */
-OO.ui.BookletLayout.prototype.onStackLayoutSet = function ( page ) {
-       if ( page ) {
-               page.scrollElementIntoView( { 'complete': OO.ui.bind( function () {
-                       if ( this.autoFocus ) {
-                               // Set focus to the first input if nothing on the page is focused yet
-                               if ( !page.$element.find( ':focus' ).length ) {
-                                       page.$element.find( ':input:first' ).focus();
+OO.ui.BookletLayout.prototype.setPage = function ( name ) {
+       var selectedItem,
+               $focused,
+               page = this.pages[name];
+
+       if ( name !== this.currentPageName ) {
+               if ( this.outlined ) {
+                       selectedItem = this.outlineWidget.getSelectedItem();
+                       if ( selectedItem && selectedItem.getData() !== name ) {
+                               this.outlineWidget.selectItem( this.outlineWidget.getItemFromData( name ) );
+                       }
+               }
+               if ( page ) {
+                       if ( this.currentPageName && this.pages[this.currentPageName] ) {
+                               this.pages[this.currentPageName].setActive( false );
+                               // Blur anything focused if the next page doesn't have anything focusable - this
+                               // is not needed if the next page has something focusable because once it is focused
+                               // this blur happens automatically
+                               if ( this.autoFocus && !page.$element.find( ':input' ).length ) {
+                                       $focused = this.pages[this.currentPageName].$element.find( ':focus' );
+                                       if ( $focused.length ) {
+                                               $focused[0].blur();
+                                       }
                                }
                        }
-               }, this ) } );
+                       this.currentPageName = name;
+                       this.stackLayout.setItem( page );
+                       page.setActive( true );
+                       this.emit( 'set', page );
+               }
        }
 };
 
 /**
- * Handle outline widget select events.
+ * Call this after adding or removing items from the OutlineWidget.
  *
- * @param {OO.ui.OptionWidget|null} item Selected item
+ * @chainable
  */
-OO.ui.BookletLayout.prototype.onOutlineWidgetSelect = function ( item ) {
-       if ( item ) {
-               this.setPage( item.getData() );
+OO.ui.BookletLayout.prototype.updateOutlineWidget = function () {
+       // Auto-select first item when nothing is selected anymore
+       if ( !this.outlineWidget.getSelectedItem() ) {
+               this.outlineWidget.selectItem( this.outlineWidget.getFirstSelectableItem() );
        }
+
+       return this;
 };
 
 /**
- * Check if booklet has an outline.
+ * Layout made of a field and optional label.
  *
- * @return {boolean}
+ * @class
+ * @extends OO.ui.Layout
+ * @mixins OO.ui.LabelElement
+ *
+ * Available label alignment modes include:
+ *  - left: Label is before the field and aligned away from it, best for when the user will be
+ *    scanning for a specific label in a form with many fields
+ *  - right: Label is before the field and aligned toward it, best for forms the user is very
+ *    familiar with and will tab through field checking quickly to verify which field they are in
+ *  - top: Label is before the field and above it, best for when the use will need to fill out all
+ *    fields from top to bottom in a form with few fields
+ *  - inline: Label is after the field and aligned toward it, best for small boolean fields like
+ *    checkboxes or radio buttons
+ *
+ * @constructor
+ * @param {OO.ui.Widget} field Field widget
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [align='left'] Alignment mode, either 'left', 'right', 'top' or 'inline'
+ * @cfg {string} [help] Explanatory text shown as a '?' icon.
  */
-OO.ui.BookletLayout.prototype.isOutlined = function () {
-       return this.outlined;
+OO.ui.FieldLayout = function OoUiFieldLayout( field, config ) {
+       // Config initialization
+       config = $.extend( { align: 'left' }, config );
+
+       // Parent constructor
+       OO.ui.FieldLayout.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.LabelElement.call( this, config );
+
+       // Properties
+       this.$field = this.$( '<div>' );
+       this.field = field;
+       this.align = null;
+       if ( config.help ) {
+               this.popupButtonWidget = new OO.ui.PopupButtonWidget( {
+                       $: this.$,
+                       classes: [ 'oo-ui-fieldLayout-help' ],
+                       framed: false,
+                       icon: 'info'
+               } );
+
+               this.popupButtonWidget.getPopup().$body.append(
+                       this.$( '<div>' )
+                               .text( config.help )
+                               .addClass( 'oo-ui-fieldLayout-help-content' )
+               );
+               this.$help = this.popupButtonWidget.$element;
+       } else {
+               this.$help = this.$( [] );
+       }
+
+       // Events
+       if ( this.field instanceof OO.ui.InputWidget ) {
+               this.$label.on( 'click', OO.ui.bind( this.onLabelClick, this ) );
+       }
+       this.field.connect( this, { disable: 'onFieldDisable' } );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-fieldLayout' );
+       this.$field
+               .addClass( 'oo-ui-fieldLayout-field' )
+               .toggleClass( 'oo-ui-fieldLayout-disable', this.field.isDisabled() )
+               .append( this.field.$element );
+       this.setAlignment( config.align );
 };
 
+/* Setup */
+
+OO.inheritClass( OO.ui.FieldLayout, OO.ui.Layout );
+OO.mixinClass( OO.ui.FieldLayout, OO.ui.LabelElement );
+
+/* Methods */
+
 /**
- * Check if booklet has editing controls.
+ * Handle field disable events.
  *
- * @return {boolean}
+ * @param {boolean} value Field is disabled
  */
-OO.ui.BookletLayout.prototype.isEditable = function () {
-       return this.editable;
+OO.ui.FieldLayout.prototype.onFieldDisable = function ( value ) {
+       this.$element.toggleClass( 'oo-ui-fieldLayout-disabled', value );
 };
 
 /**
- * Check if booklet has a visible outline.
+ * Handle label mouse click events.
  *
- * @return {boolean}
+ * @param {jQuery.Event} e Mouse click event
  */
-OO.ui.BookletLayout.prototype.isOutlineVisible = function () {
-       return this.outlined && this.outlineVisible;
+OO.ui.FieldLayout.prototype.onLabelClick = function () {
+       this.field.simulateLabelClick();
+       return false;
 };
 
 /**
- * Hide or show the outline.
+ * Get the field.
  *
- * @param {boolean} [show] Show outline, omit to invert current state
- * @chainable
+ * @return {OO.ui.Widget} Field widget
  */
-OO.ui.BookletLayout.prototype.toggleOutline = function ( show ) {
-       if ( this.outlined ) {
-               show = show === undefined ? !this.outlineVisible : !!show;
-               this.outlineVisible = show;
-               this.gridLayout.layout( show ? [ 1, 2 ] : [ 0, 1 ], [ 1 ] );
-       }
-
-       return this;
+OO.ui.FieldLayout.prototype.getField = function () {
+       return this.field;
 };
 
 /**
- * Get the outline widget.
+ * Set the field alignment mode.
  *
- * @param {OO.ui.PageLayout} page Page to be selected
- * @return {OO.ui.PageLayout|null} Closest page to another
+ * @param {string} value Alignment mode, either 'left', 'right', 'top' or 'inline'
+ * @chainable
  */
-OO.ui.BookletLayout.prototype.getClosestPage = function ( page ) {
-       var next, prev, level,
-               pages = this.stackLayout.getItems(),
-               index = $.inArray( page, pages );
-
-       if ( index !== -1 ) {
-               next = pages[index + 1];
-               prev = pages[index - 1];
-               // Prefer adjacent pages at the same level
-               if ( this.outlined ) {
-                       level = this.outlineWidget.getItemFromData( page.getName() ).getLevel();
-                       if (
-                               prev &&
-                               level === this.outlineWidget.getItemFromData( prev.getName() ).getLevel()
-                       ) {
-                               return prev;
-                       }
-                       if (
-                               next &&
-                               level === this.outlineWidget.getItemFromData( next.getName() ).getLevel()
-                       ) {
-                               return next;
-                       }
+OO.ui.FieldLayout.prototype.setAlignment = function ( value ) {
+       if ( value !== this.align ) {
+               // Default to 'left'
+               if ( [ 'left', 'right', 'top', 'inline' ].indexOf( value ) === -1 ) {
+                       value = 'left';
+               }
+               // Reorder elements
+               if ( value === 'inline' ) {
+                       this.$element.append( this.$field, this.$label, this.$help );
+               } else {
+                       this.$element.append( this.$help, this.$label, this.$field );
+               }
+               // Set classes
+               if ( this.align ) {
+                       this.$element.removeClass( 'oo-ui-fieldLayout-align-' + this.align );
                }
+               this.align = value;
+               // The following classes can be used here:
+               // oo-ui-fieldLayout-align-left
+               // oo-ui-fieldLayout-align-right
+               // oo-ui-fieldLayout-align-top
+               // oo-ui-fieldLayout-align-inline
+               this.$element.addClass( 'oo-ui-fieldLayout-align-' + this.align );
        }
-       return prev || next || null;
+
+       return this;
 };
 
 /**
- * Get the outline widget.
+ * Layout made of a fieldset and optional legend.
  *
- * @return {OO.ui.OutlineWidget|null} Outline widget, or null if boolet has no outline
+ * Just add OO.ui.FieldLayout items.
+ *
+ * @class
+ * @extends OO.ui.Layout
+ * @mixins OO.ui.LabelElement
+ * @mixins OO.ui.IconElement
+ * @mixins OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [icon] Symbolic icon name
+ * @cfg {OO.ui.FieldLayout[]} [items] Items to add
  */
-OO.ui.BookletLayout.prototype.getOutline = function () {
-       return this.outlineWidget;
+OO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) {
+       // Config initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.FieldsetLayout.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.IconElement.call( this, config );
+       OO.ui.LabelElement.call( this, config );
+       OO.ui.GroupElement.call( this, config );
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-fieldsetLayout' )
+               .prepend( this.$icon, this.$label, this.$group );
+       if ( $.isArray( config.items ) ) {
+               this.addItems( config.items );
+       }
 };
 
+/* Setup */
+
+OO.inheritClass( OO.ui.FieldsetLayout, OO.ui.Layout );
+OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.IconElement );
+OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.LabelElement );
+OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.GroupElement );
+
+/* Static Properties */
+
+OO.ui.FieldsetLayout.static.tagName = 'div';
+
 /**
- * Get the outline controls widget. If the outline is not editable, null is returned.
+ * Layout with an HTML form.
  *
- * @return {OO.ui.OutlineControlsWidget|null} The outline controls widget.
+ * @class
+ * @extends OO.ui.Layout
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
  */
-OO.ui.BookletLayout.prototype.getOutlineControls = function () {
-       return this.outlineControlsWidget;
+OO.ui.FormLayout = function OoUiFormLayout( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.FormLayout.super.call( this, config );
+
+       // Events
+       this.$element.on( 'submit', OO.ui.bind( this.onFormSubmit, this ) );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-formLayout' );
 };
 
+/* Setup */
+
+OO.inheritClass( OO.ui.FormLayout, OO.ui.Layout );
+
+/* Events */
+
 /**
- * Get a page by name.
- *
- * @param {string} name Symbolic name of page
- * @return {OO.ui.PageLayout|undefined} Page, if found
+ * @event submit
  */
-OO.ui.BookletLayout.prototype.getPage = function ( name ) {
-       return this.pages[name];
-};
+
+/* Static Properties */
+
+OO.ui.FormLayout.static.tagName = 'form';
+
+/* Methods */
 
 /**
- * Get the current page name.
+ * Handle form submit events.
  *
- * @return {string|null} Current page name
+ * @param {jQuery.Event} e Submit event
+ * @fires submit
  */
-OO.ui.BookletLayout.prototype.getPageName = function () {
-       return this.currentPageName;
+OO.ui.FormLayout.prototype.onFormSubmit = function () {
+       this.emit( 'submit' );
+       return false;
 };
 
 /**
- * Add a page to the layout.
+ * Layout made of proportionally sized columns and rows.
  *
- * When pages are added with the same names as existing pages, the existing pages will be
- * automatically removed before the new pages are added.
+ * @class
+ * @extends OO.ui.Layout
  *
- * @param {OO.ui.PageLayout[]} pages Pages to add
- * @param {number} index Index to insert pages after
- * @fires add
- * @chainable
+ * @constructor
+ * @param {OO.ui.PanelLayout[]} panels Panels in the grid
+ * @param {Object} [config] Configuration options
+ * @cfg {number[]} [widths] Widths of columns as ratios
+ * @cfg {number[]} [heights] Heights of columns as ratios
  */
-OO.ui.BookletLayout.prototype.addPages = function ( pages, index ) {
-       var i, len, name, page, item, currentIndex,
-               stackLayoutPages = this.stackLayout.getItems(),
-               remove = [],
-               items = [];
+OO.ui.GridLayout = function OoUiGridLayout( panels, config ) {
+       var i, len, widths;
 
-       // Remove pages with same names
-       for ( i = 0, len = pages.length; i < len; i++ ) {
-               page = pages[i];
-               name = page.getName();
+       // Config initialization
+       config = config || {};
 
-               if ( Object.prototype.hasOwnProperty.call( this.pages, name ) ) {
-                       // Correct the insertion index
-                       currentIndex = $.inArray( this.pages[name], stackLayoutPages );
-                       if ( currentIndex !== -1 && currentIndex + 1 < index ) {
-                               index--;
-                       }
-                       remove.push( this.pages[name] );
-               }
-       }
-       if ( remove.length ) {
-               this.removePages( remove );
-       }
+       // Parent constructor
+       OO.ui.GridLayout.super.call( this, config );
 
-       // Add new pages
-       for ( i = 0, len = pages.length; i < len; i++ ) {
-               page = pages[i];
-               name = page.getName();
-               this.pages[page.getName()] = page;
-               if ( this.outlined ) {
-                       item = new OO.ui.OutlineItemWidget( name, page, { '$': this.$ } );
-                       page.setOutlineItem( item );
-                       items.push( item );
+       // Properties
+       this.panels = [];
+       this.widths = [];
+       this.heights = [];
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-gridLayout' );
+       for ( i = 0, len = panels.length; i < len; i++ ) {
+               this.panels.push( panels[i] );
+               this.$element.append( panels[i].$element );
+       }
+       if ( config.widths || config.heights ) {
+               this.layout( config.widths || [ 1 ], config.heights || [ 1 ] );
+       } else {
+               // Arrange in columns by default
+               widths = [];
+               for ( i = 0, len = this.panels.length; i < len; i++ ) {
+                       widths[i] = 1;
                }
+               this.layout( widths, [ 1 ] );
        }
+};
 
-       if ( this.outlined && items.length ) {
-               this.outlineWidget.addItems( items, index );
-               this.updateOutlineWidget();
-       }
-       this.stackLayout.addItems( pages, index );
-       this.emit( 'add', pages, index );
+/* Setup */
 
-       return this;
-};
+OO.inheritClass( OO.ui.GridLayout, OO.ui.Layout );
+
+/* Events */
 
 /**
- * Remove a page from the layout.
- *
- * @fires remove
- * @chainable
+ * @event layout
  */
-OO.ui.BookletLayout.prototype.removePages = function ( pages ) {
-       var i, len, name, page,
-               items = [];
 
-       for ( i = 0, len = pages.length; i < len; i++ ) {
-               page = pages[i];
-               name = page.getName();
-               delete this.pages[name];
-               if ( this.outlined ) {
-                       items.push( this.outlineWidget.getItemFromData( name ) );
-                       page.setOutlineItem( null );
-               }
-       }
-       if ( this.outlined && items.length ) {
-               this.outlineWidget.removeItems( items );
-               this.updateOutlineWidget();
-       }
-       this.stackLayout.removeItems( pages );
-       this.emit( 'remove', pages );
+/**
+ * @event update
+ */
 
-       return this;
-};
+/* Static Properties */
+
+OO.ui.GridLayout.static.tagName = 'div';
+
+/* Methods */
 
 /**
- * Clear all pages from the layout.
+ * Set grid dimensions.
  *
- * @fires remove
- * @chainable
+ * @param {number[]} widths Widths of columns as ratios
+ * @param {number[]} heights Heights of rows as ratios
+ * @fires layout
+ * @throws {Error} If grid is not large enough to fit all panels
  */
-OO.ui.BookletLayout.prototype.clearPages = function () {
-       var i, len,
-               pages = this.stackLayout.getItems();
+OO.ui.GridLayout.prototype.layout = function ( widths, heights ) {
+       var x, y,
+               xd = 0,
+               yd = 0,
+               cols = widths.length,
+               rows = heights.length;
 
-       this.pages = {};
-       this.currentPageName = null;
-       if ( this.outlined ) {
-               this.outlineWidget.clearItems();
-               for ( i = 0, len = pages.length; i < len; i++ ) {
-                       pages[i].setOutlineItem( null );
-               }
+       // Verify grid is big enough to fit panels
+       if ( cols * rows < this.panels.length ) {
+               throw new Error( 'Grid is not large enough to fit ' + this.panels.length + 'panels' );
        }
-       this.stackLayout.clearItems();
-
-       this.emit( 'remove', pages );
 
-       return this;
+       // Sum up denominators
+       for ( x = 0; x < cols; x++ ) {
+               xd += widths[x];
+       }
+       for ( y = 0; y < rows; y++ ) {
+               yd += heights[y];
+       }
+       // Store factors
+       this.widths = [];
+       this.heights = [];
+       for ( x = 0; x < cols; x++ ) {
+               this.widths[x] = widths[x] / xd;
+       }
+       for ( y = 0; y < rows; y++ ) {
+               this.heights[y] = heights[y] / yd;
+       }
+       // Synchronize view
+       this.update();
+       this.emit( 'layout' );
 };
 
 /**
- * Set the current page by name.
+ * Update panel positions and sizes.
  *
- * @fires set
- * @param {string} name Symbolic name of page
+ * @fires update
  */
-OO.ui.BookletLayout.prototype.setPage = function ( name ) {
-       var selectedItem,
-               page = this.pages[name];
+OO.ui.GridLayout.prototype.update = function () {
+       var x, y, panel,
+               i = 0,
+               left = 0,
+               top = 0,
+               dimensions,
+               width = 0,
+               height = 0,
+               cols = this.widths.length,
+               rows = this.heights.length;
 
-       if ( name !== this.currentPageName ) {
-               if ( this.outlined ) {
-                       selectedItem = this.outlineWidget.getSelectedItem();
-                       if ( selectedItem && selectedItem.getData() !== name ) {
-                               this.outlineWidget.selectItem( this.outlineWidget.getItemFromData( name ) );
-                       }
-               }
-               if ( page ) {
-                       if ( this.currentPageName && this.pages[this.currentPageName] ) {
-                               this.pages[this.currentPageName].setActive( false );
-                               // Blur anything focused if the next page doesn't have anything focusable - this
-                               // is not needed if the next page has something focusable because once it is focused
-                               // this blur happens automatically
-                               if ( this.autoFocus && !page.$element.find( ':input' ).length ) {
-                                       this.pages[this.currentPageName].$element.find( ':focus' ).blur();
-                               }
+       for ( y = 0; y < rows; y++ ) {
+               height = this.heights[y];
+               for ( x = 0; x < cols; x++ ) {
+                       panel = this.panels[i];
+                       width = this.widths[x];
+                       dimensions = {
+                               width: Math.round( width * 100 ) + '%',
+                               height: Math.round( height * 100 ) + '%',
+                               top: Math.round( top * 100 ) + '%',
+                               // HACK: Work around IE bug by setting visibility: hidden; if width or height is zero
+                               visibility: width === 0 || height === 0 ? 'hidden' : ''
+                       };
+                       // If RTL, reverse:
+                       if ( OO.ui.Element.getDir( this.$.context ) === 'rtl' ) {
+                               dimensions.right = Math.round( left * 100 ) + '%';
+                       } else {
+                               dimensions.left = Math.round( left * 100 ) + '%';
                        }
-                       this.currentPageName = name;
-                       this.stackLayout.setItem( page );
-                       page.setActive( true );
-                       this.emit( 'set', page );
+                       panel.$element.css( dimensions );
+                       i++;
+                       left += width;
                }
+               top += height;
+               left = 0;
        }
+
+       this.emit( 'update' );
 };
 
 /**
- * Call this after adding or removing items from the OutlineWidget.
+ * Get a panel at a given position.
  *
- * @chainable
+ * The x and y position is affected by the current grid layout.
+ *
+ * @param {number} x Horizontal position
+ * @param {number} y Vertical position
+ * @return {OO.ui.PanelLayout} The panel at the given postion
  */
-OO.ui.BookletLayout.prototype.updateOutlineWidget = function () {
-       // Auto-select first item when nothing is selected anymore
-       if ( !this.outlineWidget.getSelectedItem() ) {
-               this.outlineWidget.selectItem( this.outlineWidget.getFirstSelectableItem() );
-       }
-
-       return this;
+OO.ui.GridLayout.prototype.getPanel = function ( x, y ) {
+       return this.panels[( x * this.widths.length ) + y];
 };
 
 /**
@@ -4770,8 +6843,9 @@ OO.ui.BookletLayout.prototype.updateOutlineWidget = function () {
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {boolean} [scrollable] Allow vertical scrolling
- * @cfg {boolean} [padded] Pad the content from the edges
+ * @cfg {boolean} [scrollable=false] Allow vertical scrolling
+ * @cfg {boolean} [padded=false] Pad the content from the edges
+ * @cfg {boolean} [expanded=true] Expand size to fill the entire parent element
  */
 OO.ui.PanelLayout = function OoUiPanelLayout( config ) {
        // Config initialization
@@ -4789,6 +6863,10 @@ OO.ui.PanelLayout = function OoUiPanelLayout( config ) {
        if ( config.padded ) {
                this.$element.addClass( 'oo-ui-panelLayout-padded' );
        }
+
+       if ( config.expanded === undefined || config.expanded ) {
+               this.$element.addClass( 'oo-ui-panelLayout-expanded' );
+       }
 };
 
 /* Setup */
@@ -4808,7 +6886,7 @@ OO.inheritClass( OO.ui.PanelLayout, OO.ui.Layout );
  */
 OO.ui.PageLayout = function OoUiPageLayout( name, config ) {
        // Configuration initialization
-       config = $.extend( { 'scrollable': true }, config );
+       config = $.extend( { scrollable: true }, config );
 
        // Parent constructor
        OO.ui.PageLayout.super.call( this, config );
@@ -4863,13 +6941,33 @@ OO.ui.PageLayout.prototype.getOutlineItem = function () {
 };
 
 /**
- * Get outline item.
+ * Set outline item.
+ *
+ * @localdoc Subclasses should override #setupOutlineItem instead of this method to adjust the
+ *   outline item as desired; this method is called for setting (with an object) and unsetting
+ *   (with null) and overriding methods would have to check the value of `outlineItem` to avoid
+ *   operating on null instead of an OO.ui.OutlineItemWidget object.
  *
  * @param {OO.ui.OutlineItemWidget|null} outlineItem Outline item widget, null to clear
  * @chainable
  */
 OO.ui.PageLayout.prototype.setOutlineItem = function ( outlineItem ) {
-       this.outlineItem = outlineItem;
+       this.outlineItem = outlineItem || null;
+       if ( outlineItem ) {
+               this.setupOutlineItem();
+       }
+       return this;
+};
+
+/**
+ * Setup outline item.
+ *
+ * @localdoc Subclasses should override this method to adjust the outline item as desired.
+ *
+ * @param {OO.ui.OutlineItemWidget} outlineItem Outline item widget to setup
+ * @chainable
+ */
+OO.ui.PageLayout.prototype.setupOutlineItem = function () {
        return this;
 };
 
@@ -4904,13 +7002,13 @@ OO.ui.PageLayout.prototype.setActive = function ( active ) {
  */
 OO.ui.StackLayout = function OoUiStackLayout( config ) {
        // Config initialization
-       config = $.extend( { 'scrollable': true }, config );
+       config = $.extend( { scrollable: true }, config );
 
        // Parent constructor
        OO.ui.StackLayout.super.call( this, config );
 
        // Mixin constructors
-       OO.ui.GroupElement.call( this, this.$element, config );
+       OO.ui.GroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );
 
        // Properties
        this.currentItem = null;
@@ -4999,7 +7097,7 @@ OO.ui.StackLayout.prototype.removeItems = function ( items ) {
        // Mixin method
        OO.ui.GroupElement.prototype.removeItems.call( this, items );
 
-       if ( $.inArray( this.currentItem, items  ) !== -1 ) {
+       if ( $.inArray( this.currentItem, items ) !== -1 ) {
                if ( this.items.length ) {
                        this.setItem( this.items[0] );
                } else {
@@ -5096,9 +7194,9 @@ OO.ui.BarToolGroup.static.name = 'bar';
  * @abstract
  * @class
  * @extends OO.ui.ToolGroup
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.IndicatedElement
- * @mixins OO.ui.LabeledElement
+ * @mixins OO.ui.IconElement
+ * @mixins OO.ui.IndicatorElement
+ * @mixins OO.ui.LabelElement
  * @mixins OO.ui.TitledElement
  * @mixins OO.ui.ClippableElement
  *
@@ -5115,11 +7213,11 @@ OO.ui.PopupToolGroup = function OoUiPopupToolGroup( toolbar, config ) {
        OO.ui.PopupToolGroup.super.call( this, toolbar, config );
 
        // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
-       OO.ui.TitledElement.call( this, this.$element, config );
-       OO.ui.ClippableElement.call( this, this.$group, config );
+       OO.ui.IconElement.call( this, config );
+       OO.ui.IndicatorElement.call( this, config );
+       OO.ui.LabelElement.call( this, config );
+       OO.ui.TitledElement.call( this, config );
+       OO.ui.ClippableElement.call( this, $.extend( {}, config, { $clippable: this.$group } ) );
 
        // Properties
        this.active = false;
@@ -5129,8 +7227,8 @@ OO.ui.PopupToolGroup = function OoUiPopupToolGroup( toolbar, config ) {
 
        // Events
        this.$handle.on( {
-               'mousedown': OO.ui.bind( this.onHandleMouseDown, this ),
-               'mouseup': OO.ui.bind( this.onHandleMouseUp, this )
+               'mousedown touchstart': OO.ui.bind( this.onHandlePointerDown, this ),
+               'mouseup touchend': OO.ui.bind( this.onHandlePointerUp, this )
        } );
 
        // Initialization
@@ -5155,9 +7253,9 @@ OO.ui.PopupToolGroup = function OoUiPopupToolGroup( toolbar, config ) {
 /* Setup */
 
 OO.inheritClass( OO.ui.PopupToolGroup, OO.ui.ToolGroup );
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.IndicatedElement );
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.LabeledElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.IconElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.IndicatorElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.LabelElement );
 OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.TitledElement );
 OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.ClippableElement );
 
@@ -5194,11 +7292,12 @@ OO.ui.PopupToolGroup.prototype.onBlur = function ( e ) {
 /**
  * @inheritdoc
  */
-OO.ui.PopupToolGroup.prototype.onMouseUp = function ( e ) {
-       if ( !this.isDisabled() && e.which === 1 ) {
+OO.ui.PopupToolGroup.prototype.onPointerUp = function ( e ) {
+       // e.which is 0 for touch events, 1 for left mouse button
+       if ( !this.isDisabled() && e.which <= 1 ) {
                this.setActive( false );
        }
-       return OO.ui.PopupToolGroup.super.prototype.onMouseUp.call( this, e );
+       return OO.ui.PopupToolGroup.super.prototype.onPointerUp.call( this, e );
 };
 
 /**
@@ -5206,7 +7305,7 @@ OO.ui.PopupToolGroup.prototype.onMouseUp = function ( e ) {
  *
  * @param {jQuery.Event} e Mouse up event
  */
-OO.ui.PopupToolGroup.prototype.onHandleMouseUp = function () {
+OO.ui.PopupToolGroup.prototype.onHandlePointerUp = function () {
        return false;
 };
 
@@ -5215,8 +7314,9 @@ OO.ui.PopupToolGroup.prototype.onHandleMouseUp = function () {
  *
  * @param {jQuery.Event} e Mouse down event
  */
-OO.ui.PopupToolGroup.prototype.onHandleMouseDown = function ( e ) {
-       if ( !this.isDisabled() && e.which === 1 ) {
+OO.ui.PopupToolGroup.prototype.onHandlePointerDown = function ( e ) {
+       // e.which is 0 for touch events, 1 for left mouse button
+       if ( !this.isDisabled() && e.which <= 1 ) {
                this.setActive( !this.active );
        }
        return false;
@@ -5232,13 +7332,25 @@ OO.ui.PopupToolGroup.prototype.setActive = function ( value ) {
        if ( this.active !== value ) {
                this.active = value;
                if ( value ) {
-                       this.setClipping( true );
-                       this.$element.addClass( 'oo-ui-popupToolGroup-active' );
                        this.getElementDocument().addEventListener( 'mouseup', this.onBlurHandler, true );
+
+                       // Try anchoring the popup to the left first
+                       this.$element.addClass( 'oo-ui-popupToolGroup-active oo-ui-popupToolGroup-left' );
+                       this.toggleClipping( true );
+                       if ( this.isClippedHorizontally() ) {
+                               // Anchoring to the left caused the popup to clip, so anchor it to the right instead
+                               this.toggleClipping( false );
+                               this.$element
+                                       .removeClass( 'oo-ui-popupToolGroup-left' )
+                                       .addClass( 'oo-ui-popupToolGroup-right' );
+                               this.toggleClipping( true );
+                       }
                } else {
-                       this.setClipping( false );
-                       this.$element.removeClass( 'oo-ui-popupToolGroup-active' );
                        this.getElementDocument().removeEventListener( 'mouseup', this.onBlurHandler, true );
+                       this.$element.removeClass(
+                               'oo-ui-popupToolGroup-active oo-ui-popupToolGroup-left  oo-ui-popupToolGroup-right'
+                       );
+                       this.toggleClipping( false );
                }
        }
 };
@@ -5289,7 +7401,7 @@ OO.ui.MenuToolGroup = function OoUiMenuToolGroup( toolbar, config ) {
        OO.ui.MenuToolGroup.super.call( this, toolbar, config );
 
        // Events
-       this.toolbar.connect( this, { 'updateState': 'onUpdateState' } );
+       this.toolbar.connect( this, { updateState: 'onUpdateState' } );
 
        // Initialization
        this.$element.addClass( 'oo-ui-menuToolGroup' );
@@ -5332,7 +7444,7 @@ OO.ui.MenuToolGroup.prototype.onUpdateState = function () {
  * @abstract
  * @class
  * @extends OO.ui.Tool
- * @mixins OO.ui.PopuppableElement
+ * @mixins OO.ui.PopupElement
  *
  * @constructor
  * @param {OO.ui.Toolbar} toolbar
@@ -5343,7 +7455,7 @@ OO.ui.PopupTool = function OoUiPopupTool( toolbar, config ) {
        OO.ui.PopupTool.super.call( this, toolbar, config );
 
        // Mixin constructors
-       OO.ui.PopuppableElement.call( this, config );
+       OO.ui.PopupElement.call( this, config );
 
        // Initialization
        this.$element
@@ -5354,206 +7466,541 @@ OO.ui.PopupTool = function OoUiPopupTool( toolbar, config ) {
 /* Setup */
 
 OO.inheritClass( OO.ui.PopupTool, OO.ui.Tool );
-OO.mixinClass( OO.ui.PopupTool, OO.ui.PopuppableElement );
+OO.mixinClass( OO.ui.PopupTool, OO.ui.PopupElement );
+
+/* Methods */
+
+/**
+ * Handle the tool being selected.
+ *
+ * @inheritdoc
+ */
+OO.ui.PopupTool.prototype.onSelect = function () {
+       if ( !this.isDisabled() ) {
+               this.popup.toggle();
+       }
+       this.setActive( false );
+       return false;
+};
+
+/**
+ * Handle the toolbar state being updated.
+ *
+ * @inheritdoc
+ */
+OO.ui.PopupTool.prototype.onUpdateState = function () {
+       this.setActive( false );
+};
+
+/**
+ * Mixin for OO.ui.Widget subclasses to provide OO.ui.GroupElement.
+ *
+ * Use together with OO.ui.ItemWidget to make disabled state inheritable.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.GroupWidget = function OoUiGroupWidget( config ) {
+       // Parent constructor
+       OO.ui.GroupWidget.super.call( this, config );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.GroupWidget, OO.ui.GroupElement );
+
+/* Methods */
+
+/**
+ * Set the disabled state of the widget.
+ *
+ * This will also update the disabled state of child widgets.
+ *
+ * @param {boolean} disabled Disable widget
+ * @chainable
+ */
+OO.ui.GroupWidget.prototype.setDisabled = function ( disabled ) {
+       var i, len;
+
+       // Parent method
+       // Note: Calling #setDisabled this way assumes this is mixed into an OO.ui.Widget
+       OO.ui.Widget.prototype.setDisabled.call( this, disabled );
+
+       // During construction, #setDisabled is called before the OO.ui.GroupElement constructor
+       if ( this.items ) {
+               for ( i = 0, len = this.items.length; i < len; i++ ) {
+                       this.items[i].updateDisabled();
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Mixin for widgets used as items in widgets that inherit OO.ui.GroupWidget.
+ *
+ * Item widgets have a reference to a OO.ui.GroupWidget while they are attached to the group. This
+ * allows bidrectional communication.
+ *
+ * Use together with OO.ui.GroupWidget to make disabled state inheritable.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ */
+OO.ui.ItemWidget = function OoUiItemWidget() {
+       //
+};
+
+/* Methods */
+
+/**
+ * Check if widget is disabled.
+ *
+ * Checks parent if present, making disabled state inheritable.
+ *
+ * @return {boolean} Widget is disabled
+ */
+OO.ui.ItemWidget.prototype.isDisabled = function () {
+       return this.disabled ||
+               ( this.elementGroup instanceof OO.ui.Widget && this.elementGroup.isDisabled() );
+};
+
+/**
+ * Set group element is in.
+ *
+ * @param {OO.ui.GroupElement|null} group Group element, null if none
+ * @chainable
+ */
+OO.ui.ItemWidget.prototype.setElementGroup = function ( group ) {
+       // Parent method
+       // Note: Calling #setElementGroup this way assumes this is mixed into an OO.ui.Element
+       OO.ui.Element.prototype.setElementGroup.call( this, group );
+
+       // Initialize item disabled states
+       this.updateDisabled();
+
+       return this;
+};
+
+/**
+ * Mixin that adds a menu showing suggested values for a text input.
+ *
+ * Subclasses must handle `select` and `choose` events on #lookupMenu to make use of selections.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {OO.ui.TextInputWidget} input Input widget
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$overlay=this.$( 'body' )] Overlay layer
+ */
+OO.ui.LookupInputWidget = function OoUiLookupInputWidget( input, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.lookupInput = input;
+       this.$overlay = config.$overlay || this.$( 'body,.oo-ui-window-overlay' ).last();
+       this.lookupMenu = new OO.ui.TextInputMenuWidget( this, {
+               $: OO.ui.Element.getJQuery( this.$overlay ),
+               input: this.lookupInput,
+               $container: config.$container
+       } );
+       this.lookupCache = {};
+       this.lookupQuery = null;
+       this.lookupRequest = null;
+       this.populating = false;
+
+       // Events
+       this.$overlay.append( this.lookupMenu.$element );
+
+       this.lookupInput.$input.on( {
+               focus: OO.ui.bind( this.onLookupInputFocus, this ),
+               blur: OO.ui.bind( this.onLookupInputBlur, this ),
+               mousedown: OO.ui.bind( this.onLookupInputMouseDown, this )
+       } );
+       this.lookupInput.connect( this, { change: 'onLookupInputChange' } );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-lookupWidget' );
+       this.lookupMenu.$element.addClass( 'oo-ui-lookupWidget-menu' );
+};
 
 /* Methods */
 
 /**
- * Handle the tool being selected.
+ * Handle input focus event.
+ *
+ * @param {jQuery.Event} e Input focus event
+ */
+OO.ui.LookupInputWidget.prototype.onLookupInputFocus = function () {
+       this.openLookupMenu();
+};
+
+/**
+ * Handle input blur event.
+ *
+ * @param {jQuery.Event} e Input blur event
+ */
+OO.ui.LookupInputWidget.prototype.onLookupInputBlur = function () {
+       this.lookupMenu.toggle( false );
+};
+
+/**
+ * Handle input mouse down event.
  *
- * @inheritdoc
+ * @param {jQuery.Event} e Input mouse down event
  */
-OO.ui.PopupTool.prototype.onSelect = function () {
-       if ( !this.isDisabled() ) {
-               if ( this.popup.isVisible() ) {
-                       this.hidePopup();
-               } else {
-                       this.showPopup();
-               }
-       }
-       this.setActive( false );
-       return false;
+OO.ui.LookupInputWidget.prototype.onLookupInputMouseDown = function () {
+       this.openLookupMenu();
 };
 
 /**
- * Handle the toolbar state being updated.
+ * Handle input change event.
  *
- * @inheritdoc
+ * @param {string} value New input value
  */
-OO.ui.PopupTool.prototype.onUpdateState = function () {
-       this.setActive( false );
+OO.ui.LookupInputWidget.prototype.onLookupInputChange = function () {
+       this.openLookupMenu();
 };
 
 /**
- * Group widget.
- *
- * Mixin for OO.ui.Widget subclasses.
- *
- * Use together with OO.ui.ItemWidget to make disabled state inheritable.
- *
- * @abstract
- * @class
- * @extends OO.ui.GroupElement
+ * Get lookup menu.
  *
- * @constructor
- * @param {jQuery} $group Container node, assigned to #$group
- * @param {Object} [config] Configuration options
+ * @return {OO.ui.TextInputMenuWidget}
  */
-OO.ui.GroupWidget = function OoUiGroupWidget( $element, config ) {
-       // Parent constructor
-       OO.ui.GroupWidget.super.call( this, $element, config );
+OO.ui.LookupInputWidget.prototype.getLookupMenu = function () {
+       return this.lookupMenu;
 };
 
-/* Setup */
+/**
+ * Open the menu.
+ *
+ * @chainable
+ */
+OO.ui.LookupInputWidget.prototype.openLookupMenu = function () {
+       var value = this.lookupInput.getValue();
 
-OO.inheritClass( OO.ui.GroupWidget, OO.ui.GroupElement );
+       if ( this.lookupMenu.$input.is( ':focus' ) && $.trim( value ) !== '' ) {
+               this.populateLookupMenu();
+               this.lookupMenu.toggle( true );
+       } else {
+               this.lookupMenu
+                       .clearItems()
+                       .toggle( false );
+       }
 
-/* Methods */
+       return this;
+};
 
 /**
- * Set the disabled state of the widget.
- *
- * This will also update the disabled state of child widgets.
+ * Populate lookup menu with current information.
  *
- * @param {boolean} disabled Disable widget
  * @chainable
  */
-OO.ui.GroupWidget.prototype.setDisabled = function ( disabled ) {
-       var i, len;
-
-       // Parent method
-       // Note: Calling #setDisabled this way assumes this is mixed into an OO.ui.Widget
-       OO.ui.Widget.prototype.setDisabled.call( this, disabled );
+OO.ui.LookupInputWidget.prototype.populateLookupMenu = function () {
+       var widget = this;
 
-       // During construction, #setDisabled is called before the OO.ui.GroupElement constructor
-       if ( this.items ) {
-               for ( i = 0, len = this.items.length; i < len; i++ ) {
-                       this.items[i].updateDisabled();
-               }
+       if ( !this.populating ) {
+               this.populating = true;
+               this.getLookupMenuItems()
+                       .done( function ( items ) {
+                               widget.lookupMenu.clearItems();
+                               if ( items.length ) {
+                                       widget.lookupMenu
+                                               .addItems( items )
+                                               .toggle( true );
+                                       widget.initializeLookupMenuSelection();
+                                       widget.openLookupMenu();
+                               } else {
+                                       widget.lookupMenu.toggle( true );
+                               }
+                               widget.populating = false;
+                       } )
+                       .fail( function () {
+                               widget.lookupMenu.clearItems();
+                               widget.populating = false;
+                       } );
        }
 
        return this;
 };
 
 /**
- * Item widget.
- *
- * Use together with OO.ui.GroupWidget to make disabled state inheritable.
+ * Set selection in the lookup menu with current information.
  *
- * @abstract
- * @class
+ * @chainable
+ */
+OO.ui.LookupInputWidget.prototype.initializeLookupMenuSelection = function () {
+       if ( !this.lookupMenu.getSelectedItem() ) {
+               this.lookupMenu.selectItem( this.lookupMenu.getFirstSelectableItem() );
+       }
+       this.lookupMenu.highlightItem( this.lookupMenu.getSelectedItem() );
+};
+
+/**
+ * Get lookup menu items for the current query.
  *
- * @constructor
+ * @return {jQuery.Promise} Promise object which will be passed menu items as the first argument
+ * of the done event
  */
-OO.ui.ItemWidget = function OoUiItemWidget() {
-       //
+OO.ui.LookupInputWidget.prototype.getLookupMenuItems = function () {
+       var widget = this,
+               value = this.lookupInput.getValue(),
+               deferred = $.Deferred();
+
+       if ( value && value !== this.lookupQuery ) {
+               // Abort current request if query has changed
+               if ( this.lookupRequest ) {
+                       this.lookupRequest.abort();
+                       this.lookupQuery = null;
+                       this.lookupRequest = null;
+               }
+               if ( value in this.lookupCache ) {
+                       deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) );
+               } else {
+                       this.lookupQuery = value;
+                       this.lookupRequest = this.getLookupRequest()
+                               .always( function () {
+                                       widget.lookupQuery = null;
+                                       widget.lookupRequest = null;
+                               } )
+                               .done( function ( data ) {
+                                       widget.lookupCache[value] = widget.getLookupCacheItemFromData( data );
+                                       deferred.resolve( widget.getLookupMenuItemsFromData( widget.lookupCache[value] ) );
+                               } )
+                               .fail( function () {
+                                       deferred.reject();
+                               } );
+                       this.pushPending();
+                       this.lookupRequest.always( function () {
+                               widget.popPending();
+                       } );
+               }
+       }
+       return deferred.promise();
 };
 
-/* Methods */
+/**
+ * Get a new request object of the current lookup query value.
+ *
+ * @abstract
+ * @return {jqXHR} jQuery AJAX object, or promise object with an .abort() method
+ */
+OO.ui.LookupInputWidget.prototype.getLookupRequest = function () {
+       // Stub, implemented in subclass
+       return null;
+};
 
 /**
- * Check if widget is disabled.
+ * Handle successful lookup request.
  *
- * Checks parent if present, making disabled state inheritable.
+ * Overriding methods should call #populateLookupMenu when results are available and cache results
+ * for future lookups in #lookupCache as an array of #OO.ui.MenuItemWidget objects.
  *
- * @return {boolean} Widget is disabled
+ * @abstract
+ * @param {Mixed} data Response from server
  */
-OO.ui.ItemWidget.prototype.isDisabled = function () {
-       return this.disabled ||
-               ( this.elementGroup instanceof OO.ui.Widget && this.elementGroup.isDisabled() );
+OO.ui.LookupInputWidget.prototype.onLookupRequestDone = function () {
+       // Stub, implemented in subclass
 };
 
 /**
- * Set group element is in.
+ * Get a list of menu item widgets from the data stored by the lookup request's done handler.
  *
- * @param {OO.ui.GroupElement|null} group Group element, null if none
- * @chainable
+ * @abstract
+ * @param {Mixed} data Cached result data, usually an array
+ * @return {OO.ui.MenuItemWidget[]} Menu items
  */
-OO.ui.ItemWidget.prototype.setElementGroup = function ( group ) {
-       // Parent method
-       // Note: Calling #setElementGroup this way assumes this is mixed into an OO.ui.Element
-       OO.ui.Element.prototype.setElementGroup.call( this, group );
-
-       // Initialize item disabled states
-       this.updateDisabled();
-
-       return this;
+OO.ui.LookupInputWidget.prototype.getLookupMenuItemsFromData = function () {
+       // Stub, implemented in subclass
+       return [];
 };
 
 /**
- * Icon widget.
+ * Set of controls for an OO.ui.OutlineWidget.
+ *
+ * Controls include moving items up and down, removing items, and adding different kinds of items.
  *
  * @class
  * @extends OO.ui.Widget
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.TitledElement
+ * @mixins OO.ui.GroupElement
+ * @mixins OO.ui.IconElement
  *
  * @constructor
+ * @param {OO.ui.OutlineWidget} outline Outline to control
  * @param {Object} [config] Configuration options
  */
-OO.ui.IconWidget = function OoUiIconWidget( config ) {
-       // Config intialization
-       config = config || {};
+OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) {
+       // Configuration initialization
+       config = $.extend( { icon: 'add-item' }, config );
 
        // Parent constructor
-       OO.ui.IconWidget.super.call( this, config );
+       OO.ui.OutlineControlsWidget.super.call( this, config );
 
        // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$element, config );
-       OO.ui.TitledElement.call( this, this.$element, config );
+       OO.ui.GroupElement.call( this, config );
+       OO.ui.IconElement.call( this, config );
+
+       // Properties
+       this.outline = outline;
+       this.$movers = this.$( '<div>' );
+       this.upButton = new OO.ui.ButtonWidget( {
+               $: this.$,
+               framed: false,
+               icon: 'collapse',
+               title: OO.ui.msg( 'ooui-outline-control-move-up' )
+       } );
+       this.downButton = new OO.ui.ButtonWidget( {
+               $: this.$,
+               framed: false,
+               icon: 'expand',
+               title: OO.ui.msg( 'ooui-outline-control-move-down' )
+       } );
+       this.removeButton = new OO.ui.ButtonWidget( {
+               $: this.$,
+               framed: false,
+               icon: 'remove',
+               title: OO.ui.msg( 'ooui-outline-control-remove' )
+       } );
+
+       // Events
+       outline.connect( this, {
+               select: 'onOutlineChange',
+               add: 'onOutlineChange',
+               remove: 'onOutlineChange'
+       } );
+       this.upButton.connect( this, { click: [ 'emit', 'move', -1 ] } );
+       this.downButton.connect( this, { click: [ 'emit', 'move', 1 ] } );
+       this.removeButton.connect( this, { click: [ 'emit', 'remove' ] } );
 
        // Initialization
-       this.$element.addClass( 'oo-ui-iconWidget' );
+       this.$element.addClass( 'oo-ui-outlineControlsWidget' );
+       this.$group.addClass( 'oo-ui-outlineControlsWidget-items' );
+       this.$movers
+               .addClass( 'oo-ui-outlineControlsWidget-movers' )
+               .append( this.removeButton.$element, this.upButton.$element, this.downButton.$element );
+       this.$element.append( this.$icon, this.$group, this.$movers );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.IconWidget, OO.ui.Widget );
-OO.mixinClass( OO.ui.IconWidget, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.IconWidget, OO.ui.TitledElement );
+OO.inheritClass( OO.ui.OutlineControlsWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.GroupElement );
+OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.IconElement );
 
-/* Static Properties */
+/* Events */
 
-OO.ui.IconWidget.static.tagName = 'span';
+/**
+ * @event move
+ * @param {number} places Number of places to move
+ */
 
 /**
- * Indicator widget.
+ * @event remove
+ */
+
+/* Methods */
+
+/**
+ * Handle outline change events.
+ */
+OO.ui.OutlineControlsWidget.prototype.onOutlineChange = function () {
+       var i, len, firstMovable, lastMovable,
+               items = this.outline.getItems(),
+               selectedItem = this.outline.getSelectedItem(),
+               movable = selectedItem && selectedItem.isMovable(),
+               removable = selectedItem && selectedItem.isRemovable();
+
+       if ( movable ) {
+               i = -1;
+               len = items.length;
+               while ( ++i < len ) {
+                       if ( items[i].isMovable() ) {
+                               firstMovable = items[i];
+                               break;
+                       }
+               }
+               i = len;
+               while ( i-- ) {
+                       if ( items[i].isMovable() ) {
+                               lastMovable = items[i];
+                               break;
+                       }
+               }
+       }
+       this.upButton.setDisabled( !movable || selectedItem === firstMovable );
+       this.downButton.setDisabled( !movable || selectedItem === lastMovable );
+       this.removeButton.setDisabled( !removable );
+};
+
+/**
+ * Mixin for widgets with a boolean on/off state.
  *
+ * @abstract
  * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.IndicatedElement
- * @mixins OO.ui.TitledElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
- */
-OO.ui.IndicatorWidget = function OoUiIndicatorWidget( config ) {
-       // Config intialization
+ * @cfg {boolean} [value=false] Initial value
+ */
+OO.ui.ToggleWidget = function OoUiToggleWidget( config ) {
+       // Configuration initialization
        config = config || {};
 
-       // Parent constructor
-       OO.ui.IndicatorWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.IndicatedElement.call( this, this.$element, config );
-       OO.ui.TitledElement.call( this, this.$element, config );
+       // Properties
+       this.value = null;
 
        // Initialization
-       this.$element.addClass( 'oo-ui-indicatorWidget' );
+       this.$element.addClass( 'oo-ui-toggleWidget' );
+       this.setValue( !!config.value );
 };
 
-/* Setup */
+/* Events */
 
-OO.inheritClass( OO.ui.IndicatorWidget, OO.ui.Widget );
-OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.IndicatedElement );
-OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.TitledElement );
+/**
+ * @event change
+ * @param {boolean} value Changed value
+ */
 
-/* Static Properties */
+/* Methods */
 
-OO.ui.IndicatorWidget.static.tagName = 'span';
+/**
+ * Get the value of the toggle.
+ *
+ * @return {boolean}
+ */
+OO.ui.ToggleWidget.prototype.getValue = function () {
+       return this.value;
+};
+
+/**
+ * Set the value of the toggle.
+ *
+ * @param {boolean} value New value
+ * @fires change
+ * @chainable
+ */
+OO.ui.ToggleWidget.prototype.setValue = function ( value ) {
+       value = !!value;
+       if ( this.value !== value ) {
+               this.value = value;
+               this.emit( 'change', value );
+               this.$element.toggleClass( 'oo-ui-toggleWidget-on', value );
+               this.$element.toggleClass( 'oo-ui-toggleWidget-off', !value );
+       }
+       return this;
+};
 
 /**
- * Container for multiple related buttons.
+ * Group widget for multiple related buttons.
  *
  * Use together with OO.ui.ButtonWidget.
  *
@@ -5570,7 +8017,7 @@ OO.ui.ButtonGroupWidget = function OoUiButtonGroupWidget( config ) {
        OO.ui.ButtonGroupWidget.super.call( this, config );
 
        // Mixin constructors
-       OO.ui.GroupElement.call( this, this.$element, config );
+       OO.ui.GroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );
 
        // Initialization
        this.$element.addClass( 'oo-ui-buttonGroupWidget' );
@@ -5585,65 +8032,66 @@ OO.inheritClass( OO.ui.ButtonGroupWidget, OO.ui.Widget );
 OO.mixinClass( OO.ui.ButtonGroupWidget, OO.ui.GroupElement );
 
 /**
- * Button widget.
+ * Generic widget for buttons.
  *
  * @class
  * @extends OO.ui.Widget
- * @mixins OO.ui.ButtonedElement
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.IndicatedElement
- * @mixins OO.ui.LabeledElement
+ * @mixins OO.ui.ButtonElement
+ * @mixins OO.ui.IconElement
+ * @mixins OO.ui.IndicatorElement
+ * @mixins OO.ui.LabelElement
  * @mixins OO.ui.TitledElement
- * @mixins OO.ui.FlaggableElement
+ * @mixins OO.ui.FlaggedElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {string} [title=''] Title text
  * @cfg {string} [href] Hyperlink to visit when clicked
  * @cfg {string} [target] Target to open hyperlink in
  */
 OO.ui.ButtonWidget = function OoUiButtonWidget( config ) {
        // Configuration initialization
-       config = $.extend( { 'target': '_blank' }, config );
+       config = $.extend( { target: '_blank' }, config );
 
        // Parent constructor
        OO.ui.ButtonWidget.super.call( this, config );
 
        // Mixin constructors
-       OO.ui.ButtonedElement.call( this, this.$( '<a>' ), config );
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
-       OO.ui.TitledElement.call( this, this.$button, config );
-       OO.ui.FlaggableElement.call( this, config );
+       OO.ui.ButtonElement.call( this, config );
+       OO.ui.IconElement.call( this, config );
+       OO.ui.IndicatorElement.call( this, config );
+       OO.ui.LabelElement.call( this, config );
+       OO.ui.TitledElement.call( this, config, $.extend( {}, config, { $titled: this.$button } ) );
+       OO.ui.FlaggedElement.call( this, config );
 
        // Properties
-       this.isHyperlink = typeof config.href === 'string';
+       this.href = null;
+       this.target = null;
+       this.isHyperlink = false;
 
        // Events
        this.$button.on( {
-               'click': OO.ui.bind( this.onClick, this ),
-               'keypress': OO.ui.bind( this.onKeyPress, this )
+               click: OO.ui.bind( this.onClick, this ),
+               keypress: OO.ui.bind( this.onKeyPress, this )
        } );
 
        // Initialization
-       this.$button
-               .append( this.$icon, this.$label, this.$indicator )
-               .attr( { 'href': config.href, 'target': config.target } );
+       this.$button.append( this.$icon, this.$label, this.$indicator );
        this.$element
                .addClass( 'oo-ui-buttonWidget' )
                .append( this.$button );
+       this.setHref( config.href );
+       this.setTarget( config.target );
 };
 
 /* Setup */
 
 OO.inheritClass( OO.ui.ButtonWidget, OO.ui.Widget );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.ButtonedElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IndicatedElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.LabeledElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.ButtonElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IconElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IndicatorElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.LabelElement );
 OO.mixinClass( OO.ui.ButtonWidget, OO.ui.TitledElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.FlaggableElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.FlaggedElement );
 
 /* Events */
 
@@ -5665,1706 +8113,1529 @@ OO.ui.ButtonWidget.prototype.onClick = function () {
                if ( this.isHyperlink ) {
                        return true;
                }
-       }
-       return false;
-};
-
-/**
- * Handles keypress events.
- *
- * @param {jQuery.Event} e Keypress event
- * @fires click
- */
-OO.ui.ButtonWidget.prototype.onKeyPress = function ( e ) {
-       if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) {
-               this.onClick();
-               if ( this.isHyperlink ) {
-                       return true;
-               }
-       }
-       return false;
-};
-
-/**
- * Input widget.
- *
- * @abstract
- * @class
- * @extends OO.ui.Widget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string} [name=''] HTML input name
- * @cfg {string} [value=''] Input value
- * @cfg {boolean} [readOnly=false] Prevent changes
- * @cfg {Function} [inputFilter] Filter function to apply to the input. Takes a string argument and returns a string.
- */
-OO.ui.InputWidget = function OoUiInputWidget( config ) {
-       // Config intialization
-       config = $.extend( { 'readOnly': false }, config );
-
-       // Parent constructor
-       OO.ui.InputWidget.super.call( this, config );
-
-       // Properties
-       this.$input = this.getInputElement( config );
-       this.value = '';
-       this.readOnly = false;
-       this.inputFilter = config.inputFilter;
-
-       // Events
-       this.$input.on( 'keydown mouseup cut paste change input select', OO.ui.bind( this.onEdit, this ) );
-
-       // Initialization
-       this.$input
-               .attr( 'name', config.name )
-               .prop( 'disabled', this.isDisabled() );
-       this.setReadOnly( config.readOnly );
-       this.$element.addClass( 'oo-ui-inputWidget' ).append( this.$input );
-       this.setValue( config.value );
-};
-
-/* Setup */
-
-OO.inheritClass( OO.ui.InputWidget, OO.ui.Widget );
-
-/* Events */
-
-/**
- * @event change
- * @param value
- */
-
-/* Methods */
-
-/**
- * Get input element.
- *
- * @param {Object} [config] Configuration options
- * @return {jQuery} Input element
- */
-OO.ui.InputWidget.prototype.getInputElement = function () {
-       return this.$( '<input>' );
-};
-
-/**
- * Handle potentially value-changing events.
- *
- * @param {jQuery.Event} e Key down, mouse up, cut, paste, change, input, or select event
- */
-OO.ui.InputWidget.prototype.onEdit = function () {
-       if ( !this.isDisabled() ) {
-               // Allow the stack to clear so the value will be updated
-               setTimeout( OO.ui.bind( function () {
-                       this.setValue( this.$input.val() );
-               }, this ) );
-       }
-};
-
-/**
- * Get the value of the input.
- *
- * @return {string} Input value
- */
-OO.ui.InputWidget.prototype.getValue = function () {
-       return this.value;
-};
-
-/**
- * Sets the direction of the current input, either RTL or LTR
- *
- * @param {boolean} isRTL
- */
-OO.ui.InputWidget.prototype.setRTL = function ( isRTL ) {
-       if ( isRTL ) {
-               this.$input.removeClass( 'oo-ui-ltr' );
-               this.$input.addClass( 'oo-ui-rtl' );
-       } else {
-               this.$input.removeClass( 'oo-ui-rtl' );
-               this.$input.addClass( 'oo-ui-ltr' );
-       }
-};
-
-/**
- * Set the value of the input.
- *
- * @param {string} value New value
- * @fires change
- * @chainable
- */
-OO.ui.InputWidget.prototype.setValue = function ( value ) {
-       value = this.sanitizeValue( value );
-       if ( this.value !== value ) {
-               this.value = value;
-               this.emit( 'change', this.value );
-       }
-       // Update the DOM if it has changed. Note that with sanitizeValue, it
-       // is possible for the DOM value to change without this.value changing.
-       if ( this.$input.val() !== this.value ) {
-               this.$input.val( this.value );
-       }
-       return this;
-};
-
-/**
- * Sanitize incoming value.
- *
- * Ensures value is a string, and converts undefined and null to empty strings.
- *
- * @param {string} value Original value
- * @return {string} Sanitized value
- */
-OO.ui.InputWidget.prototype.sanitizeValue = function ( value ) {
-       if ( value === undefined || value === null ) {
-               return '';
-       } else if ( this.inputFilter ) {
-               return this.inputFilter( String( value ) );
-       } else {
-               return String( value );
-       }
-};
-
-/**
- * Simulate the behavior of clicking on a label bound to this input.
- */
-OO.ui.InputWidget.prototype.simulateLabelClick = function () {
-       if ( !this.isDisabled() ) {
-               if ( this.$input.is( ':checkbox,:radio' ) ) {
-                       this.$input.click();
-               } else if ( this.$input.is( ':input' ) ) {
-                       this.$input.focus();
-               }
-       }
-};
-
-/**
- * Check if the widget is read-only.
- *
- * @return {boolean}
- */
-OO.ui.InputWidget.prototype.isReadOnly = function () {
-       return this.readOnly;
-};
-
-/**
- * Set the read-only state of the widget.
- *
- * This should probably change the widgets's appearance and prevent it from being used.
- *
- * @param {boolean} state Make input read-only
- * @chainable
- */
-OO.ui.InputWidget.prototype.setReadOnly = function ( state ) {
-       this.readOnly = !!state;
-       this.$input.prop( 'readOnly', this.readOnly );
-       return this;
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.InputWidget.prototype.setDisabled = function ( state ) {
-       OO.ui.InputWidget.super.prototype.setDisabled.call( this, state );
-       if ( this.$input ) {
-               this.$input.prop( 'disabled', this.isDisabled() );
-       }
-       return this;
-};
-
-/**
- * Focus the input.
- *
- * @chainable
- */
-OO.ui.InputWidget.prototype.focus = function () {
-       this.$input.focus();
-       return this;
+       }
+       return false;
 };
 
 /**
- * Checkbox widget.
- *
- * @class
- * @extends OO.ui.InputWidget
+ * Handles keypress events.
  *
- * @constructor
- * @param {Object} [config] Configuration options
+ * @param {jQuery.Event} e Keypress event
+ * @fires click
  */
-OO.ui.CheckboxInputWidget = function OoUiCheckboxInputWidget( config ) {
-       // Parent constructor
-       OO.ui.CheckboxInputWidget.super.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-checkboxInputWidget' );
+OO.ui.ButtonWidget.prototype.onKeyPress = function ( e ) {
+       if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) {
+               this.onClick();
+               if ( this.isHyperlink ) {
+                       return true;
+               }
+       }
+       return false;
 };
 
-/* Setup */
-
-OO.inheritClass( OO.ui.CheckboxInputWidget, OO.ui.InputWidget );
-
-/* Events */
-
-/* Methods */
-
 /**
- * Get input element.
+ * Get hyperlink location.
  *
- * @return {jQuery} Input element
+ * @return {string} Hyperlink location
  */
-OO.ui.CheckboxInputWidget.prototype.getInputElement = function () {
-       return this.$( '<input type="checkbox" />' );
+OO.ui.ButtonWidget.prototype.getHref = function () {
+       return this.href;
 };
 
 /**
- * Get checked state of the checkbox
+ * Get hyperlink target.
  *
- * @return {boolean} If the checkbox is checked
+ * @return {string} Hyperlink target
  */
-OO.ui.CheckboxInputWidget.prototype.getValue = function () {
-       return this.value;
+OO.ui.ButtonWidget.prototype.getTarget = function () {
+       return this.target;
 };
 
 /**
- * Set value
+ * Set hyperlink location.
+ *
+ * @param {string|null} href Hyperlink location, null to remove
  */
-OO.ui.CheckboxInputWidget.prototype.setValue = function ( value ) {
-       value = !!value;
-       if ( this.value !== value ) {
-               this.value = value;
-               this.$input.prop( 'checked', this.value );
-               this.emit( 'change', this.value );
+OO.ui.ButtonWidget.prototype.setHref = function ( href ) {
+       href = typeof href === 'string' ? href : null;
+
+       if ( href !== this.href ) {
+               this.href = href;
+               if ( href !== null ) {
+                       this.$button.attr( 'href', href );
+                       this.isHyperlink = true;
+               } else {
+                       this.$button.removeAttr( 'href' );
+                       this.isHyperlink = false;
+               }
        }
+
+       return this;
 };
 
 /**
- * @inheritdoc
+ * Set hyperlink target.
+ *
+ * @param {string|null} target Hyperlink target, null to remove
  */
-OO.ui.CheckboxInputWidget.prototype.onEdit = function () {
-       if ( !this.isDisabled() ) {
-               // Allow the stack to clear so the value will be updated
-               setTimeout( OO.ui.bind( function () {
-                       this.setValue( this.$input.prop( 'checked' ) );
-               }, this ) );
+OO.ui.ButtonWidget.prototype.setTarget = function ( target ) {
+       target = typeof target === 'string' ? target : null;
+
+       if ( target !== this.target ) {
+               this.target = target;
+               if ( target !== null ) {
+                       this.$button.attr( 'target', target );
+               } else {
+                       this.$button.removeAttr( 'target' );
+               }
        }
+
+       return this;
 };
 
 /**
- * Label widget.
+ * Button widget that executes an action and is managed by an OO.ui.ActionSet.
  *
  * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.LabeledElement
+ * @extends OO.ui.ButtonWidget
+ * @mixins OO.ui.PendingElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
+ * @cfg {string} [action] Symbolic action name
+ * @cfg {string[]} [modes] Symbolic mode names
  */
-OO.ui.LabelWidget = function OoUiLabelWidget( config ) {
+OO.ui.ActionWidget = function OoUiActionWidget( config ) {
        // Config intialization
-       config = config || {};
+       config = $.extend( { framed: false }, config );
 
        // Parent constructor
-       OO.ui.LabelWidget.super.call( this, config );
+       OO.ui.ActionWidget.super.call( this, config );
 
        // Mixin constructors
-       OO.ui.LabeledElement.call( this, this.$element, config );
+       OO.ui.PendingElement.call( this, config );
 
        // Properties
-       this.input = config.input;
-
-       // Events
-       if ( this.input instanceof OO.ui.InputWidget ) {
-               this.$element.on( 'click', OO.ui.bind( this.onClick, this ) );
-       }
+       this.action = config.action || '';
+       this.modes = config.modes || [];
+       this.width = 0;
+       this.height = 0;
 
        // Initialization
-       this.$element.addClass( 'oo-ui-labelWidget' );
+       this.$element.addClass( 'oo-ui-actionWidget' );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.LabelWidget, OO.ui.Widget );
-OO.mixinClass( OO.ui.LabelWidget, OO.ui.LabeledElement );
+OO.inheritClass( OO.ui.ActionWidget, OO.ui.ButtonWidget );
+OO.mixinClass( OO.ui.ActionWidget, OO.ui.PendingElement );
 
-/* Static Properties */
+/* Events */
 
-OO.ui.LabelWidget.static.tagName = 'label';
+/**
+ * @event resize
+ */
 
 /* Methods */
 
 /**
- * Handles label mouse click events.
+ * Check if action is available in a certain mode.
  *
- * @param {jQuery.Event} e Mouse click event
+ * @param {string} mode Name of mode
+ * @return {boolean} Has mode
  */
-OO.ui.LabelWidget.prototype.onClick = function () {
-       this.input.simulateLabelClick();
-       return false;
+OO.ui.ActionWidget.prototype.hasMode = function ( mode ) {
+       return this.modes.indexOf( mode ) !== -1;
 };
 
 /**
- * Lookup input widget.
- *
- * Mixin that adds a menu showing suggested values to a text input. Subclasses must handle `select`
- * and `choose` events on #lookupMenu to make use of selections.
- *
- * @class
- * @abstract
+ * Get symbolic action name.
  *
- * @constructor
- * @param {OO.ui.TextInputWidget} input Input widget
- * @param {Object} [config] Configuration options
- * @cfg {jQuery} [$overlay=this.$( 'body' )] Overlay layer
+ * @return {string}
  */
-OO.ui.LookupInputWidget = function OoUiLookupInputWidget( input, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Properties
-       this.lookupInput = input;
-       this.$overlay = config.$overlay || this.$( 'body,.oo-ui-window-overlay' ).last();
-       this.lookupMenu = new OO.ui.TextInputMenuWidget( this, {
-               '$': OO.ui.Element.getJQuery( this.$overlay ),
-               'input': this.lookupInput,
-               '$container': config.$container
-       } );
-       this.lookupCache = {};
-       this.lookupQuery = null;
-       this.lookupRequest = null;
-       this.populating = false;
-
-       // Events
-       this.$overlay.append( this.lookupMenu.$element );
-
-       this.lookupInput.$input.on( {
-               'focus': OO.ui.bind( this.onLookupInputFocus, this ),
-               'blur': OO.ui.bind( this.onLookupInputBlur, this ),
-               'mousedown': OO.ui.bind( this.onLookupInputMouseDown, this )
-       } );
-       this.lookupInput.connect( this, { 'change': 'onLookupInputChange' } );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-lookupWidget' );
-       this.lookupMenu.$element.addClass( 'oo-ui-lookupWidget-menu' );
+OO.ui.ActionWidget.prototype.getAction = function () {
+       return this.action;
 };
 
-/* Methods */
-
 /**
- * Handle input focus event.
+ * Get symbolic action name.
  *
- * @param {jQuery.Event} e Input focus event
+ * @return {string}
  */
-OO.ui.LookupInputWidget.prototype.onLookupInputFocus = function () {
-       this.openLookupMenu();
+OO.ui.ActionWidget.prototype.getModes = function () {
+       return this.modes.slice();
 };
 
 /**
- * Handle input blur event.
+ * Emit a resize event if the size has changed.
  *
- * @param {jQuery.Event} e Input blur event
+ * @chainable
  */
-OO.ui.LookupInputWidget.prototype.onLookupInputBlur = function () {
-       this.lookupMenu.hide();
+OO.ui.ActionWidget.prototype.propagateResize = function () {
+       var width, height;
+
+       if ( this.isElementAttached() ) {
+               width = this.$element.width();
+               height = this.$element.height();
+
+               if ( width !== this.width || height !== this.height ) {
+                       this.width = width;
+                       this.height = height;
+                       this.emit( 'resize' );
+               }
+       }
+
+       return this;
 };
 
 /**
- * Handle input mouse down event.
- *
- * @param {jQuery.Event} e Input mouse down event
+ * @inheritdoc
  */
-OO.ui.LookupInputWidget.prototype.onLookupInputMouseDown = function () {
-       this.openLookupMenu();
+OO.ui.ActionWidget.prototype.setIcon = function () {
+       // Mixin method
+       OO.ui.IconElement.prototype.setIcon.apply( this, arguments );
+       this.propagateResize();
+
+       return this;
 };
 
 /**
- * Handle input change event.
- *
- * @param {string} value New input value
+ * @inheritdoc
  */
-OO.ui.LookupInputWidget.prototype.onLookupInputChange = function () {
-       this.openLookupMenu();
+OO.ui.ActionWidget.prototype.setLabel = function () {
+       // Mixin method
+       OO.ui.LabelElement.prototype.setLabel.apply( this, arguments );
+       this.propagateResize();
+
+       return this;
 };
 
 /**
- * Get lookup menu.
- *
- * @return {OO.ui.TextInputMenuWidget}
+ * @inheritdoc
  */
-OO.ui.LookupInputWidget.prototype.getLookupMenu = function () {
-       return this.lookupMenu;
+OO.ui.ActionWidget.prototype.setFlags = function () {
+       // Mixin method
+       OO.ui.FlaggedElement.prototype.setFlags.apply( this, arguments );
+       this.propagateResize();
+
+       return this;
 };
 
 /**
- * Open the menu.
- *
- * @chainable
+ * @inheritdoc
  */
-OO.ui.LookupInputWidget.prototype.openLookupMenu = function () {
-       var value = this.lookupInput.getValue();
-
-       if ( this.lookupMenu.$input.is( ':focus' ) && $.trim( value ) !== '' ) {
-               this.populateLookupMenu();
-               if ( !this.lookupMenu.isVisible() ) {
-                       this.lookupMenu.show();
-               }
-       } else {
-               this.lookupMenu.clearItems();
-               this.lookupMenu.hide();
-       }
+OO.ui.ActionWidget.prototype.clearFlags = function () {
+       // Mixin method
+       OO.ui.FlaggedElement.prototype.clearFlags.apply( this, arguments );
+       this.propagateResize();
 
        return this;
 };
 
 /**
- * Populate lookup menu with current information.
+ * Toggle visibility of button.
  *
+ * @param {boolean} [show] Show button, omit to toggle visibility
  * @chainable
  */
-OO.ui.LookupInputWidget.prototype.populateLookupMenu = function () {
-       if ( !this.populating ) {
-               this.populating = true;
-               this.getLookupMenuItems()
-                       .done( OO.ui.bind( function ( items ) {
-                               this.lookupMenu.clearItems();
-                               if ( items.length ) {
-                                       this.lookupMenu.show();
-                                       this.lookupMenu.addItems( items );
-                                       this.initializeLookupMenuSelection();
-                                       this.openLookupMenu();
-                               } else {
-                                       this.lookupMenu.hide();
-                               }
-                               this.populating = false;
-                       }, this ) )
-                       .fail( OO.ui.bind( function () {
-                               this.lookupMenu.clearItems();
-                               this.populating = false;
-                       }, this ) );
-       }
+OO.ui.ActionWidget.prototype.toggle = function () {
+       // Parent method
+       OO.ui.ActionWidget.super.prototype.toggle.apply( this, arguments );
+       this.propagateResize();
 
        return this;
 };
 
 /**
- * Set selection in the lookup menu with current information.
+ * Button that shows and hides a popup.
  *
- * @chainable
+ * @class
+ * @extends OO.ui.ButtonWidget
+ * @mixins OO.ui.PopupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
  */
-OO.ui.LookupInputWidget.prototype.initializeLookupMenuSelection = function () {
-       if ( !this.lookupMenu.getSelectedItem() ) {
-               this.lookupMenu.selectItem( this.lookupMenu.getFirstSelectableItem() );
-       }
-       this.lookupMenu.highlightItem( this.lookupMenu.getSelectedItem() );
+OO.ui.PopupButtonWidget = function OoUiPopupButtonWidget( config ) {
+       // Parent constructor
+       OO.ui.PopupButtonWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.PopupElement.call( this, config );
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-popupButtonWidget' )
+               .append( this.popup.$element );
 };
 
+/* Setup */
+
+OO.inheritClass( OO.ui.PopupButtonWidget, OO.ui.ButtonWidget );
+OO.mixinClass( OO.ui.PopupButtonWidget, OO.ui.PopupElement );
+
+/* Methods */
+
 /**
- * Get lookup menu items for the current query.
+ * Handles mouse click events.
  *
- * @return {jQuery.Promise} Promise object which will be passed menu items as the first argument
- * of the done event
+ * @param {jQuery.Event} e Mouse click event
  */
-OO.ui.LookupInputWidget.prototype.getLookupMenuItems = function () {
-       var value = this.lookupInput.getValue(),
-               deferred = $.Deferred();
+OO.ui.PopupButtonWidget.prototype.onClick = function ( e ) {
+       // Skip clicks within the popup
+       if ( $.contains( this.popup.$element[0], e.target ) ) {
+               return;
+       }
 
-       if ( value && value !== this.lookupQuery ) {
-               // Abort current request if query has changed
-               if ( this.lookupRequest ) {
-                       this.lookupRequest.abort();
-                       this.lookupQuery = null;
-                       this.lookupRequest = null;
-               }
-               if ( value in this.lookupCache ) {
-                       deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) );
-               } else {
-                       this.lookupQuery = value;
-                       this.lookupRequest = this.getLookupRequest()
-                               .always( OO.ui.bind( function () {
-                                       this.lookupQuery = null;
-                                       this.lookupRequest = null;
-                               }, this ) )
-                               .done( OO.ui.bind( function ( data ) {
-                                       this.lookupCache[value] = this.getLookupCacheItemFromData( data );
-                                       deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) );
-                               }, this ) )
-                               .fail( function () {
-                                       deferred.reject();
-                               } );
-                       this.pushPending();
-                       this.lookupRequest.always( OO.ui.bind( function () {
-                               this.popPending();
-                       }, this ) );
-               }
+       if ( !this.isDisabled() ) {
+               this.popup.toggle();
+               // Parent method
+               OO.ui.PopupButtonWidget.super.prototype.onClick.call( this );
        }
-       return deferred.promise();
+       return false;
 };
 
 /**
- * Get a new request object of the current lookup query value.
+ * Button that toggles on and off.
  *
- * @abstract
- * @return {jqXHR} jQuery AJAX object, or promise object with an .abort() method
+ * @class
+ * @extends OO.ui.ButtonWidget
+ * @mixins OO.ui.ToggleWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [value=false] Initial value
  */
-OO.ui.LookupInputWidget.prototype.getLookupRequest = function () {
-       // Stub, implemented in subclass
-       return null;
+OO.ui.ToggleButtonWidget = function OoUiToggleButtonWidget( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.ToggleButtonWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.ToggleWidget.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-toggleButtonWidget' );
 };
 
+/* Setup */
+
+OO.inheritClass( OO.ui.ToggleButtonWidget, OO.ui.ButtonWidget );
+OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.ToggleWidget );
+
+/* Methods */
+
 /**
- * Handle successful lookup request.
- *
- * Overriding methods should call #populateLookupMenu when results are available and cache results
- * for future lookups in #lookupCache as an array of #OO.ui.MenuItemWidget objects.
- *
- * @abstract
- * @param {Mixed} data Response from server
+ * @inheritdoc
  */
-OO.ui.LookupInputWidget.prototype.onLookupRequestDone = function () {
-       // Stub, implemented in subclass
+OO.ui.ToggleButtonWidget.prototype.onClick = function () {
+       if ( !this.isDisabled() ) {
+               this.setValue( !this.value );
+       }
+
+       // Parent method
+       return OO.ui.ToggleButtonWidget.super.prototype.onClick.call( this );
 };
 
 /**
- * Get a list of menu item widgets from the data stored by the lookup request's done handler.
- *
- * @abstract
- * @param {Mixed} data Cached result data, usually an array
- * @return {OO.ui.MenuItemWidget[]} Menu items
+ * @inheritdoc
  */
-OO.ui.LookupInputWidget.prototype.getLookupMenuItemsFromData = function () {
-       // Stub, implemented in subclass
-       return [];
+OO.ui.ToggleButtonWidget.prototype.setValue = function ( value ) {
+       value = !!value;
+       if ( value !== this.value ) {
+               this.setActive( value );
+       }
+
+       // Parent method (from mixin)
+       OO.ui.ToggleWidget.prototype.setValue.call( this, value );
+
+       return this;
 };
 
 /**
- * Option widget.
+ * Icon widget.
  *
- * Use with OO.ui.SelectWidget.
+ * See OO.ui.IconElement for more information.
  *
  * @class
  * @extends OO.ui.Widget
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.LabeledElement
- * @mixins OO.ui.IndicatedElement
- * @mixins OO.ui.FlaggableElement
+ * @mixins OO.ui.IconElement
+ * @mixins OO.ui.TitledElement
  *
  * @constructor
- * @param {Mixed} data Option data
  * @param {Object} [config] Configuration options
- * @cfg {string} [rel] Value for `rel` attribute in DOM, allowing per-option styling
  */
-OO.ui.OptionWidget = function OoUiOptionWidget( data, config ) {
+OO.ui.IconWidget = function OoUiIconWidget( config ) {
        // Config intialization
        config = config || {};
 
        // Parent constructor
-       OO.ui.OptionWidget.super.call( this, config );
+       OO.ui.IconWidget.super.call( this, config );
 
        // Mixin constructors
-       OO.ui.ItemWidget.call( this );
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
-       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.FlaggableElement.call( this, config );
-
-       // Properties
-       this.data = data;
-       this.selected = false;
-       this.highlighted = false;
-       this.pressed = false;
+       OO.ui.IconElement.call( this, $.extend( {}, config, { $icon: this.$element } ) );
+       OO.ui.TitledElement.call( this, $.extend( {}, config, { $titled: this.$element } ) );
 
        // Initialization
-       this.$element
-               .data( 'oo-ui-optionWidget', this )
-               .attr( 'rel', config.rel )
-               .addClass( 'oo-ui-optionWidget' )
-               .append( this.$label );
-       this.$element
-               .prepend( this.$icon )
-               .append( this.$indicator );
+       this.$element.addClass( 'oo-ui-iconWidget' );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.OptionWidget, OO.ui.Widget );
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.ItemWidget );
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.LabeledElement );
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.IndicatedElement );
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.FlaggableElement );
+OO.inheritClass( OO.ui.IconWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.IconWidget, OO.ui.IconElement );
+OO.mixinClass( OO.ui.IconWidget, OO.ui.TitledElement );
 
 /* Static Properties */
 
-OO.ui.OptionWidget.static.tagName = 'li';
+OO.ui.IconWidget.static.tagName = 'span';
 
-OO.ui.OptionWidget.static.selectable = true;
+/**
+ * Indicator widget.
+ *
+ * See OO.ui.IndicatorElement for more information.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.IndicatorElement
+ * @mixins OO.ui.TitledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.IndicatorWidget = function OoUiIndicatorWidget( config ) {
+       // Config intialization
+       config = config || {};
 
-OO.ui.OptionWidget.static.highlightable = true;
+       // Parent constructor
+       OO.ui.IndicatorWidget.super.call( this, config );
 
-OO.ui.OptionWidget.static.pressable = true;
+       // Mixin constructors
+       OO.ui.IndicatorElement.call( this, $.extend( {}, config, { $indicator: this.$element } ) );
+       OO.ui.TitledElement.call( this, $.extend( {}, config, { $titled: this.$element } ) );
 
-OO.ui.OptionWidget.static.scrollIntoViewOnSelect = false;
+       // Initialization
+       this.$element.addClass( 'oo-ui-indicatorWidget' );
+};
 
-/* Methods */
+/* Setup */
 
-/**
- * Check if option can be selected.
- *
- * @return {boolean} Item is selectable
- */
-OO.ui.OptionWidget.prototype.isSelectable = function () {
-       return this.constructor.static.selectable && !this.isDisabled();
-};
+OO.inheritClass( OO.ui.IndicatorWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.IndicatorElement );
+OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.TitledElement );
 
-/**
- * Check if option can be highlighted.
- *
- * @return {boolean} Item is highlightable
- */
-OO.ui.OptionWidget.prototype.isHighlightable = function () {
-       return this.constructor.static.highlightable && !this.isDisabled();
-};
+/* Static Properties */
 
-/**
- * Check if option can be pressed.
- *
- * @return {boolean} Item is pressable
- */
-OO.ui.OptionWidget.prototype.isPressable = function () {
-       return this.constructor.static.pressable && !this.isDisabled();
-};
+OO.ui.IndicatorWidget.static.tagName = 'span';
 
 /**
- * Check if option is selected.
+ * Inline menu of options.
  *
- * @return {boolean} Item is selected
- */
-OO.ui.OptionWidget.prototype.isSelected = function () {
-       return this.selected;
-};
-
-/**
- * Check if option is highlighted.
+ * Inline menus provide a control for accessing a menu and compose a menu within the widget, which
+ * can be accessed using the #getMenu method.
  *
- * @return {boolean} Item is highlighted
- */
-OO.ui.OptionWidget.prototype.isHighlighted = function () {
-       return this.highlighted;
-};
-
-/**
- * Check if option is pressed.
+ * Use with OO.ui.MenuOptionWidget.
  *
- * @return {boolean} Item is pressed
- */
-OO.ui.OptionWidget.prototype.isPressed = function () {
-       return this.pressed;
-};
-
-/**
- * Set selected state.
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.IconElement
+ * @mixins OO.ui.IndicatorElement
+ * @mixins OO.ui.LabelElement
+ * @mixins OO.ui.TitledElement
  *
- * @param {boolean} [state=false] Select option
- * @chainable
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} [menu] Configuration options to pass to menu widget
  */
-OO.ui.OptionWidget.prototype.setSelected = function ( state ) {
-       if ( this.constructor.static.selectable ) {
-               this.selected = !!state;
-               if ( this.selected ) {
-                       this.$element.addClass( 'oo-ui-optionWidget-selected' );
-                       if ( this.constructor.static.scrollIntoViewOnSelect ) {
-                               this.scrollElementIntoView();
-                       }
-               } else {
-                       this.$element.removeClass( 'oo-ui-optionWidget-selected' );
-               }
-       }
-       return this;
-};
+OO.ui.InlineMenuWidget = function OoUiInlineMenuWidget( config ) {
+       // Configuration initialization
+       config = $.extend( { indicator: 'down' }, config );
 
-/**
- * Set highlighted state.
- *
- * @param {boolean} [state=false] Highlight option
- * @chainable
- */
-OO.ui.OptionWidget.prototype.setHighlighted = function ( state ) {
-       if ( this.constructor.static.highlightable ) {
-               this.highlighted = !!state;
-               if ( this.highlighted ) {
-                       this.$element.addClass( 'oo-ui-optionWidget-highlighted' );
-               } else {
-                       this.$element.removeClass( 'oo-ui-optionWidget-highlighted' );
-               }
-       }
-       return this;
+       // Parent constructor
+       OO.ui.InlineMenuWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.IconElement.call( this, config );
+       OO.ui.IndicatorElement.call( this, config );
+       OO.ui.LabelElement.call( this, config );
+       OO.ui.TitledElement.call( this, $.extend( {}, config, { $titled: this.$label } ) );
+
+       // Properties
+       this.menu = new OO.ui.MenuWidget( $.extend( { $: this.$, widget: this }, config.menu ) );
+       this.$handle = this.$( '<span>' );
+
+       // Events
+       this.$element.on( { click: OO.ui.bind( this.onClick, this ) } );
+       this.menu.connect( this, { select: 'onMenuSelect' } );
+
+       // Initialization
+       this.$handle
+               .addClass( 'oo-ui-inlineMenuWidget-handle' )
+               .append( this.$icon, this.$label, this.$indicator );
+       this.$element
+               .addClass( 'oo-ui-inlineMenuWidget' )
+               .append( this.$handle, this.menu.$element );
 };
 
+/* Setup */
+
+OO.inheritClass( OO.ui.InlineMenuWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.IconElement );
+OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.IndicatorElement );
+OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.LabelElement );
+OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.TitledElement );
+
+/* Methods */
+
 /**
- * Set pressed state.
+ * Get the menu.
  *
- * @param {boolean} [state=false] Press option
- * @chainable
+ * @return {OO.ui.MenuWidget} Menu of widget
  */
-OO.ui.OptionWidget.prototype.setPressed = function ( state ) {
-       if ( this.constructor.static.pressable ) {
-               this.pressed = !!state;
-               if ( this.pressed ) {
-                       this.$element.addClass( 'oo-ui-optionWidget-pressed' );
-               } else {
-                       this.$element.removeClass( 'oo-ui-optionWidget-pressed' );
-               }
-       }
-       return this;
+OO.ui.InlineMenuWidget.prototype.getMenu = function () {
+       return this.menu;
 };
 
 /**
- * Make the option's highlight flash.
- *
- * While flashing, the visual style of the pressed state is removed if present.
+ * Handles menu select events.
  *
- * @return {jQuery.Promise} Promise resolved when flashing is done
+ * @param {OO.ui.MenuItemWidget} item Selected menu item
  */
-OO.ui.OptionWidget.prototype.flash = function () {
-       var $this = this.$element,
-               deferred = $.Deferred();
+OO.ui.InlineMenuWidget.prototype.onMenuSelect = function ( item ) {
+       var selectedLabel;
 
-       if ( !this.isDisabled() && this.constructor.static.pressable ) {
-               $this.removeClass( 'oo-ui-optionWidget-highlighted oo-ui-optionWidget-pressed' );
-               setTimeout( OO.ui.bind( function () {
-                       // Restore original classes
-                       $this
-                               .toggleClass( 'oo-ui-optionWidget-highlighted', this.highlighted )
-                               .toggleClass( 'oo-ui-optionWidget-pressed', this.pressed );
-                       setTimeout( function () {
-                               deferred.resolve();
-                       }, 100 );
-               }, this ), 100 );
+       if ( !item ) {
+               return;
        }
 
-       return deferred.promise();
+       selectedLabel = item.getLabel();
+
+       // If the label is a DOM element, clone it, because setLabel will append() it
+       if ( selectedLabel instanceof jQuery ) {
+               selectedLabel = selectedLabel.clone();
+       }
+
+       this.setLabel( selectedLabel );
 };
 
 /**
- * Get option data.
+ * Handles mouse click events.
  *
- * @return {Mixed} Option data
+ * @param {jQuery.Event} e Mouse click event
  */
-OO.ui.OptionWidget.prototype.getData = function () {
-       return this.data;
+OO.ui.InlineMenuWidget.prototype.onClick = function ( e ) {
+       // Skip clicks within the menu
+       if ( $.contains( this.menu.$element[0], e.target ) ) {
+               return;
+       }
+
+       if ( !this.isDisabled() ) {
+               if ( this.menu.isVisible() ) {
+                       this.menu.toggle( false );
+               } else {
+                       this.menu.toggle( true );
+               }
+       }
+       return false;
 };
 
 /**
- * Selection of options.
- *
- * Use together with OO.ui.OptionWidget.
+ * Base class for input widgets.
  *
+ * @abstract
  * @class
  * @extends OO.ui.Widget
- * @mixins OO.ui.GroupElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {OO.ui.OptionWidget[]} [items] Options to add
+ * @cfg {string} [name=''] HTML input name
+ * @cfg {string} [value=''] Input value
+ * @cfg {boolean} [readOnly=false] Prevent changes
+ * @cfg {Function} [inputFilter] Filter function to apply to the input. Takes a string argument and returns a string.
  */
-OO.ui.SelectWidget = function OoUiSelectWidget( config ) {
+OO.ui.InputWidget = function OoUiInputWidget( config ) {
        // Config intialization
-       config = config || {};
+       config = $.extend( { readOnly: false }, config );
 
        // Parent constructor
-       OO.ui.SelectWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.GroupWidget.call( this, this.$element, config );
+       OO.ui.InputWidget.super.call( this, config );
 
        // Properties
-       this.pressed = false;
-       this.selecting = null;
-       this.hashes = {};
-       this.onMouseUpHandler = OO.ui.bind( this.onMouseUp, this );
-       this.onMouseMoveHandler = OO.ui.bind( this.onMouseMove, this );
+       this.$input = this.getInputElement( config );
+       this.value = '';
+       this.readOnly = false;
+       this.inputFilter = config.inputFilter;
 
        // Events
-       this.$element.on( {
-               'mousedown': OO.ui.bind( this.onMouseDown, this ),
-               'mouseover': OO.ui.bind( this.onMouseOver, this ),
-               'mouseleave': OO.ui.bind( this.onMouseLeave, this )
-       } );
+       this.$input.on( 'keydown mouseup cut paste change input select', OO.ui.bind( this.onEdit, this ) );
 
        // Initialization
-       this.$element.addClass( 'oo-ui-selectWidget oo-ui-selectWidget-depressed' );
-       if ( $.isArray( config.items ) ) {
-               this.addItems( config.items );
-       }
+       this.$input
+               .attr( 'name', config.name )
+               .prop( 'disabled', this.isDisabled() );
+       this.setReadOnly( config.readOnly );
+       this.$element.addClass( 'oo-ui-inputWidget' ).append( this.$input );
+       this.setValue( config.value );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.SelectWidget, OO.ui.Widget );
-
-// Need to mixin base class as well
-OO.mixinClass( OO.ui.SelectWidget, OO.ui.GroupElement );
-OO.mixinClass( OO.ui.SelectWidget, OO.ui.GroupWidget );
+OO.inheritClass( OO.ui.InputWidget, OO.ui.Widget );
 
 /* Events */
 
 /**
- * @event highlight
- * @param {OO.ui.OptionWidget|null} item Highlighted item
+ * @event change
+ * @param value
  */
 
+/* Methods */
+
 /**
- * @event press
- * @param {OO.ui.OptionWidget|null} item Pressed item
+ * Get input element.
+ *
+ * @param {Object} [config] Configuration options
+ * @return {jQuery} Input element
  */
+OO.ui.InputWidget.prototype.getInputElement = function () {
+       return this.$( '<input>' );
+};
 
 /**
- * @event select
- * @param {OO.ui.OptionWidget|null} item Selected item
+ * Handle potentially value-changing events.
+ *
+ * @param {jQuery.Event} e Key down, mouse up, cut, paste, change, input, or select event
  */
+OO.ui.InputWidget.prototype.onEdit = function () {
+       var widget = this;
+       if ( !this.isDisabled() ) {
+               // Allow the stack to clear so the value will be updated
+               setTimeout( function () {
+                       widget.setValue( widget.$input.val() );
+               } );
+       }
+};
 
 /**
- * @event choose
- * @param {OO.ui.OptionWidget|null} item Chosen item
+ * Get the value of the input.
+ *
+ * @return {string} Input value
  */
+OO.ui.InputWidget.prototype.getValue = function () {
+       return this.value;
+};
 
 /**
- * @event add
- * @param {OO.ui.OptionWidget[]} items Added items
- * @param {number} index Index items were added at
+ * Sets the direction of the current input, either RTL or LTR
+ *
+ * @param {boolean} isRTL
  */
+OO.ui.InputWidget.prototype.setRTL = function ( isRTL ) {
+       if ( isRTL ) {
+               this.$input.removeClass( 'oo-ui-ltr' );
+               this.$input.addClass( 'oo-ui-rtl' );
+       } else {
+               this.$input.removeClass( 'oo-ui-rtl' );
+               this.$input.addClass( 'oo-ui-ltr' );
+       }
+};
 
 /**
- * @event remove
- * @param {OO.ui.OptionWidget[]} items Removed items
+ * Set the value of the input.
+ *
+ * @param {string} value New value
+ * @fires change
+ * @chainable
  */
+OO.ui.InputWidget.prototype.setValue = function ( value ) {
+       value = this.sanitizeValue( value );
+       if ( this.value !== value ) {
+               this.value = value;
+               this.emit( 'change', this.value );
+       }
+       // Update the DOM if it has changed. Note that with sanitizeValue, it
+       // is possible for the DOM value to change without this.value changing.
+       if ( this.$input.val() !== this.value ) {
+               this.$input.val( this.value );
+       }
+       return this;
+};
 
-/* Static Properties */
+/**
+ * Sanitize incoming value.
+ *
+ * Ensures value is a string, and converts undefined and null to empty strings.
+ *
+ * @param {string} value Original value
+ * @return {string} Sanitized value
+ */
+OO.ui.InputWidget.prototype.sanitizeValue = function ( value ) {
+       if ( value === undefined || value === null ) {
+               return '';
+       } else if ( this.inputFilter ) {
+               return this.inputFilter( String( value ) );
+       } else {
+               return String( value );
+       }
+};
 
-OO.ui.SelectWidget.static.tagName = 'ul';
+/**
+ * Simulate the behavior of clicking on a label bound to this input.
+ */
+OO.ui.InputWidget.prototype.simulateLabelClick = function () {
+       if ( !this.isDisabled() ) {
+               if ( this.$input.is( ':checkbox,:radio' ) ) {
+                       this.$input.click();
+               } else if ( this.$input.is( ':input' ) ) {
+                       this.$input[0].focus();
+               }
+       }
+};
 
-/* Methods */
+/**
+ * Check if the widget is read-only.
+ *
+ * @return {boolean}
+ */
+OO.ui.InputWidget.prototype.isReadOnly = function () {
+       return this.readOnly;
+};
 
 /**
- * Handle mouse down events.
+ * Set the read-only state of the widget.
  *
- * @private
- * @param {jQuery.Event} e Mouse down event
+ * This should probably change the widgets's appearance and prevent it from being used.
+ *
+ * @param {boolean} state Make input read-only
+ * @chainable
  */
-OO.ui.SelectWidget.prototype.onMouseDown = function ( e ) {
-       var item;
+OO.ui.InputWidget.prototype.setReadOnly = function ( state ) {
+       this.readOnly = !!state;
+       this.$input.prop( 'readOnly', this.readOnly );
+       return this;
+};
 
-       if ( !this.isDisabled() && e.which === 1 ) {
-               this.togglePressed( true );
-               item = this.getTargetItem( e );
-               if ( item && item.isSelectable() ) {
-                       this.pressItem( item );
-                       this.selecting = item;
-                       this.getElementDocument().addEventListener(
-                               'mouseup', this.onMouseUpHandler, true
-                       );
-                       this.getElementDocument().addEventListener(
-                               'mousemove', this.onMouseMoveHandler, true
-                       );
-               }
+/**
+ * @inheritdoc
+ */
+OO.ui.InputWidget.prototype.setDisabled = function ( state ) {
+       OO.ui.InputWidget.super.prototype.setDisabled.call( this, state );
+       if ( this.$input ) {
+               this.$input.prop( 'disabled', this.isDisabled() );
        }
-       return false;
+       return this;
 };
 
 /**
- * Handle mouse up events.
+ * Focus the input.
  *
- * @private
- * @param {jQuery.Event} e Mouse up event
+ * @chainable
  */
-OO.ui.SelectWidget.prototype.onMouseUp = function ( e ) {
-       var item;
+OO.ui.InputWidget.prototype.focus = function () {
+       this.$input[0].focus();
+       return this;
+};
 
-       this.togglePressed( false );
-       if ( !this.selecting ) {
-               item = this.getTargetItem( e );
-               if ( item && item.isSelectable() ) {
-                       this.selecting = item;
-               }
-       }
-       if ( !this.isDisabled() && e.which === 1 && this.selecting ) {
-               this.pressItem( null );
-               this.chooseItem( this.selecting );
-               this.selecting = null;
-       }
+/**
+ * Blur the input.
+ *
+ * @chainable
+ */
+OO.ui.InputWidget.prototype.blur = function () {
+       this.$input[0].blur();
+       return this;
+};
 
-       this.getElementDocument().removeEventListener(
-               'mouseup', this.onMouseUpHandler, true
-       );
-       this.getElementDocument().removeEventListener(
-               'mousemove', this.onMouseMoveHandler, true
-       );
+/**
+ * Checkbox input widget.
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.CheckboxInputWidget = function OoUiCheckboxInputWidget( config ) {
+       // Parent constructor
+       OO.ui.CheckboxInputWidget.super.call( this, config );
 
-       return false;
+       // Initialization
+       this.$element.addClass( 'oo-ui-checkboxInputWidget' );
 };
 
+/* Setup */
+
+OO.inheritClass( OO.ui.CheckboxInputWidget, OO.ui.InputWidget );
+
+/* Events */
+
+/* Methods */
+
 /**
- * Handle mouse move events.
+ * Get input element.
  *
- * @private
- * @param {jQuery.Event} e Mouse move event
+ * @return {jQuery} Input element
  */
-OO.ui.SelectWidget.prototype.onMouseMove = function ( e ) {
-       var item;
-
-       if ( !this.isDisabled() && this.pressed ) {
-               item = this.getTargetItem( e );
-               if ( item && item !== this.selecting && item.isSelectable() ) {
-                       this.pressItem( item );
-                       this.selecting = item;
-               }
-       }
-       return false;
+OO.ui.CheckboxInputWidget.prototype.getInputElement = function () {
+       return this.$( '<input type="checkbox" />' );
 };
 
 /**
- * Handle mouse over events.
+ * Get checked state of the checkbox
  *
- * @private
- * @param {jQuery.Event} e Mouse over event
+ * @return {boolean} If the checkbox is checked
  */
-OO.ui.SelectWidget.prototype.onMouseOver = function ( e ) {
-       var item;
+OO.ui.CheckboxInputWidget.prototype.getValue = function () {
+       return this.value;
+};
 
-       if ( !this.isDisabled() ) {
-               item = this.getTargetItem( e );
-               this.highlightItem( item && item.isHighlightable() ? item : null );
+/**
+ * Set value
+ */
+OO.ui.CheckboxInputWidget.prototype.setValue = function ( value ) {
+       value = !!value;
+       if ( this.value !== value ) {
+               this.value = value;
+               this.$input.prop( 'checked', this.value );
+               this.emit( 'change', this.value );
        }
-       return false;
 };
 
 /**
- * Handle mouse leave events.
- *
- * @private
- * @param {jQuery.Event} e Mouse over event
+ * @inheritdoc
  */
-OO.ui.SelectWidget.prototype.onMouseLeave = function () {
+OO.ui.CheckboxInputWidget.prototype.onEdit = function () {
+       var widget = this;
        if ( !this.isDisabled() ) {
-               this.highlightItem( null );
+               // Allow the stack to clear so the value will be updated
+               setTimeout( function () {
+                       widget.setValue( widget.$input.prop( 'checked' ) );
+               } );
        }
-       return false;
 };
 
 /**
- * Get the closest item to a jQuery.Event.
+ * Input widget with a text field.
  *
- * @private
- * @param {jQuery.Event} e
- * @return {OO.ui.OptionWidget|null} Outline item widget, `null` if none was found
+ * @class
+ * @extends OO.ui.InputWidget
+ * @mixins OO.ui.IconElement
+ * @mixins OO.ui.IndicatorElement
+ * @mixins OO.ui.PendingElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [placeholder] Placeholder text
+ * @cfg {boolean} [multiline=false] Allow multiple lines of text
+ * @cfg {boolean} [autosize=false] Automatically resize to fit content
+ * @cfg {boolean} [maxRows=10] Maximum number of rows to make visible when autosizing
  */
-OO.ui.SelectWidget.prototype.getTargetItem = function ( e ) {
-       var $item = this.$( e.target ).closest( '.oo-ui-optionWidget' );
-       if ( $item.length ) {
-               return $item.data( 'oo-ui-optionWidget' );
+OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.TextInputWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.IconElement.call( this, config );
+       OO.ui.IndicatorElement.call( this, config );
+       OO.ui.PendingElement.call( this, config );
+
+       // Properties
+       this.multiline = !!config.multiline;
+       this.autosize = !!config.autosize;
+       this.maxRows = config.maxRows !== undefined ? config.maxRows : 10;
+
+       // Events
+       this.$input.on( 'keypress', OO.ui.bind( this.onKeyPress, this ) );
+       this.$element.on( 'DOMNodeInsertedIntoDocument', OO.ui.bind( this.onElementAttach, this ) );
+       this.$icon.on( 'mousedown', OO.ui.bind( this.onIconMouseDown, this ) );
+       this.$indicator.on( 'mousedown', OO.ui.bind( this.onIndicatorMouseDown, this ) );
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-textInputWidget' )
+               .append( this.$icon, this.$indicator );
+       if ( config.placeholder ) {
+               this.$input.attr( 'placeholder', config.placeholder );
        }
-       return null;
+       this.$element.attr( 'role', 'textbox' );
 };
 
+/* Setup */
+
+OO.inheritClass( OO.ui.TextInputWidget, OO.ui.InputWidget );
+OO.mixinClass( OO.ui.TextInputWidget, OO.ui.IconElement );
+OO.mixinClass( OO.ui.TextInputWidget, OO.ui.IndicatorElement );
+OO.mixinClass( OO.ui.TextInputWidget, OO.ui.PendingElement );
+
+/* Events */
+
 /**
- * Get selected item.
+ * User presses enter inside the text box.
  *
- * @return {OO.ui.OptionWidget|null} Selected item, `null` if no item is selected
+ * Not called if input is multiline.
+ *
+ * @event enter
  */
-OO.ui.SelectWidget.prototype.getSelectedItem = function () {
-       var i, len;
 
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               if ( this.items[i].isSelected() ) {
-                       return this.items[i];
-               }
-       }
-       return null;
-};
+/**
+ * User clicks the icon.
+ *
+ * @event icon
+ */
 
 /**
- * Get highlighted item.
+ * User clicks the indicator.
  *
- * @return {OO.ui.OptionWidget|null} Highlighted item, `null` if no item is highlighted
+ * @event indicator
  */
-OO.ui.SelectWidget.prototype.getHighlightedItem = function () {
-       var i, len;
 
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               if ( this.items[i].isHighlighted() ) {
-                       return this.items[i];
-               }
+/* Methods */
+
+/**
+ * Handle icon mouse down events.
+ *
+ * @param {jQuery.Event} e Mouse down event
+ * @fires icon
+ */
+OO.ui.TextInputWidget.prototype.onIconMouseDown = function ( e ) {
+       if ( e.which === 1 ) {
+               this.$input[0].focus();
+               this.emit( 'icon' );
+               return false;
        }
-       return null;
 };
 
 /**
- * Get an existing item with equivilant data.
+ * Handle indicator mouse down events.
  *
- * @param {Object} data Item data to search for
- * @return {OO.ui.OptionWidget|null} Item with equivilent value, `null` if none exists
+ * @param {jQuery.Event} e Mouse down event
+ * @fires indicator
  */
-OO.ui.SelectWidget.prototype.getItemFromData = function ( data ) {
-       var hash = OO.getHash( data );
-
-       if ( hash in this.hashes ) {
-               return this.hashes[hash];
+OO.ui.TextInputWidget.prototype.onIndicatorMouseDown = function ( e ) {
+       if ( e.which === 1 ) {
+               this.$input[0].focus();
+               this.emit( 'indicator' );
+               return false;
        }
-
-       return null;
 };
 
 /**
- * Toggle pressed state.
+ * Handle key press events.
  *
- * @param {boolean} pressed An option is being pressed
+ * @param {jQuery.Event} e Key press event
+ * @fires enter If enter key is pressed and input is not multiline
  */
-OO.ui.SelectWidget.prototype.togglePressed = function ( pressed ) {
-       if ( pressed === undefined ) {
-               pressed = !this.pressed;
-       }
-       if ( pressed !== this.pressed ) {
-               this.$element.toggleClass( 'oo-ui-selectWidget-pressed', pressed );
-               this.$element.toggleClass( 'oo-ui-selectWidget-depressed', !pressed );
-               this.pressed = pressed;
+OO.ui.TextInputWidget.prototype.onKeyPress = function ( e ) {
+       if ( e.which === OO.ui.Keys.ENTER && !this.multiline ) {
+               this.emit( 'enter' );
        }
 };
 
 /**
- * Highlight an item.
- *
- * Highlighting is mutually exclusive.
+ * Handle element attach events.
  *
- * @param {OO.ui.OptionWidget} [item] Item to highlight, omit to deselect all
- * @fires highlight
- * @chainable
+ * @param {jQuery.Event} e Element attach event
  */
-OO.ui.SelectWidget.prototype.highlightItem = function ( item ) {
-       var i, len, highlighted,
-               changed = false;
+OO.ui.TextInputWidget.prototype.onElementAttach = function () {
+       this.adjustSize();
+};
 
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               highlighted = this.items[i] === item;
-               if ( this.items[i].isHighlighted() !== highlighted ) {
-                       this.items[i].setHighlighted( highlighted );
-                       changed = true;
-               }
-       }
-       if ( changed ) {
-               this.emit( 'highlight', item );
-       }
+/**
+ * @inheritdoc
+ */
+OO.ui.TextInputWidget.prototype.onEdit = function () {
+       this.adjustSize();
 
-       return this;
+       // Parent method
+       return OO.ui.TextInputWidget.super.prototype.onEdit.call( this );
 };
 
 /**
- * Select an item.
- *
- * @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all
- * @fires select
- * @chainable
+ * @inheritdoc
  */
-OO.ui.SelectWidget.prototype.selectItem = function ( item ) {
-       var i, len, selected,
-               changed = false;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               selected = this.items[i] === item;
-               if ( this.items[i].isSelected() !== selected ) {
-                       this.items[i].setSelected( selected );
-                       changed = true;
-               }
-       }
-       if ( changed ) {
-               this.emit( 'select', item );
-       }
+OO.ui.TextInputWidget.prototype.setValue = function ( value ) {
+       // Parent method
+       OO.ui.TextInputWidget.super.prototype.setValue.call( this, value );
 
+       this.adjustSize();
        return this;
 };
 
 /**
- * Press an item.
+ * Automatically adjust the size of the text input.
+ *
+ * This only affects multi-line inputs that are auto-sized.
  *
- * @param {OO.ui.OptionWidget} [item] Item to press, omit to depress all
- * @fires press
  * @chainable
  */
-OO.ui.SelectWidget.prototype.pressItem = function ( item ) {
-       var i, len, pressed,
-               changed = false;
+OO.ui.TextInputWidget.prototype.adjustSize = function () {
+       var $clone, scrollHeight, innerHeight, outerHeight, maxInnerHeight, idealHeight;
 
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               pressed = this.items[i] === item;
-               if ( this.items[i].isPressed() !== pressed ) {
-                       this.items[i].setPressed( pressed );
-                       changed = true;
-               }
-       }
-       if ( changed ) {
-               this.emit( 'press', item );
+       if ( this.multiline && this.autosize ) {
+               $clone = this.$input.clone()
+                       .val( this.$input.val() )
+                       .css( { height: 0 } )
+                       .insertAfter( this.$input );
+               // Set inline height property to 0 to measure scroll height
+               scrollHeight = $clone[0].scrollHeight;
+               // Remove inline height property to measure natural heights
+               $clone.css( 'height', '' );
+               innerHeight = $clone.innerHeight();
+               outerHeight = $clone.outerHeight();
+               // Measure max rows height
+               $clone.attr( 'rows', this.maxRows ).css( 'height', 'auto' );
+               maxInnerHeight = $clone.innerHeight();
+               $clone.removeAttr( 'rows' ).css( 'height', '' );
+               $clone.remove();
+               idealHeight = Math.min( maxInnerHeight, scrollHeight );
+               // Only apply inline height when expansion beyond natural height is needed
+               this.$input.css(
+                       'height',
+                       // Use the difference between the inner and outer height as a buffer
+                       idealHeight > outerHeight ? idealHeight + ( outerHeight - innerHeight ) : ''
+               );
        }
-
        return this;
 };
 
 /**
- * Choose an item.
- *
- * Identical to #selectItem, but may vary in subclasses that want to take additional action when
- * an item is selected using the keyboard or mouse.
+ * Get input element.
  *
- * @param {OO.ui.OptionWidget} item Item to choose
- * @fires choose
- * @chainable
+ * @param {Object} [config] Configuration options
+ * @return {jQuery} Input element
  */
-OO.ui.SelectWidget.prototype.chooseItem = function ( item ) {
-       this.selectItem( item );
-       this.emit( 'choose', item );
-
-       return this;
+OO.ui.TextInputWidget.prototype.getInputElement = function ( config ) {
+       return config.multiline ? this.$( '<textarea>' ) : this.$( '<input type="text" />' );
 };
 
+/* Methods */
+
 /**
- * Get an item relative to another one.
+ * Check if input supports multiple lines.
  *
- * @param {OO.ui.OptionWidget} item Item to start at
- * @param {number} direction Direction to move in
- * @return {OO.ui.OptionWidget|null} Item at position, `null` if there are no items in the menu
+ * @return {boolean}
  */
-OO.ui.SelectWidget.prototype.getRelativeSelectableItem = function ( item, direction ) {
-       var inc = direction > 0 ? 1 : -1,
-               len = this.items.length,
-               index = item instanceof OO.ui.OptionWidget ?
-                       $.inArray( item, this.items ) : ( inc > 0 ? -1 : 0 ),
-               stopAt = Math.max( Math.min( index, len - 1 ), 0 ),
-               i = inc > 0 ?
-                       // Default to 0 instead of -1, if nothing is selected let's start at the beginning
-                       Math.max( index, -1 ) :
-                       // Default to n-1 instead of -1, if nothing is selected let's start at the end
-                       Math.min( index, len );
-
-       while ( true ) {
-               i = ( i + inc + len ) % len;
-               item = this.items[i];
-               if ( item instanceof OO.ui.OptionWidget && item.isSelectable() ) {
-                       return item;
-               }
-               // Stop iterating when we've looped all the way around
-               if ( i === stopAt ) {
-                       break;
-               }
-       }
-       return null;
+OO.ui.TextInputWidget.prototype.isMultiline = function () {
+       return !!this.multiline;
 };
 
 /**
- * Get the next selectable item.
+ * Check if input automatically adjusts its size.
  *
- * @return {OO.ui.OptionWidget|null} Item, `null` if ther aren't any selectable items
+ * @return {boolean}
  */
-OO.ui.SelectWidget.prototype.getFirstSelectableItem = function () {
-       var i, len, item;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               item = this.items[i];
-               if ( item instanceof OO.ui.OptionWidget && item.isSelectable() ) {
-                       return item;
-               }
-       }
+OO.ui.TextInputWidget.prototype.isAutosizing = function () {
+       return !!this.autosize;
+};
 
-       return null;
+/**
+ * Select the contents of the input.
+ *
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.select = function () {
+       this.$input.select();
+       return this;
 };
 
 /**
- * Add items.
+ * Text input with a menu of optional values.
  *
- * When items are added with the same values as existing items, the existing items will be
- * automatically removed before the new items are added.
+ * @class
+ * @extends OO.ui.Widget
  *
- * @param {OO.ui.OptionWidget[]} items Items to add
- * @param {number} [index] Index to insert items after
- * @fires add
- * @chainable
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} [menu] Configuration options to pass to menu widget
+ * @cfg {Object} [input] Configuration options to pass to input widget
  */
-OO.ui.SelectWidget.prototype.addItems = function ( items, index ) {
-       var i, len, item, hash,
-               remove = [];
+OO.ui.ComboBoxWidget = function OoUiComboBoxWidget( config ) {
+       // Configuration initialization
+       config = config || {};
 
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-               hash = OO.getHash( item.getData() );
-               if ( hash in this.hashes ) {
-                       // Remove item with same value
-                       remove.push( this.hashes[hash] );
-               }
-               this.hashes[hash] = item;
-       }
-       if ( remove.length ) {
-               this.removeItems( remove );
-       }
+       // Parent constructor
+       OO.ui.ComboBoxWidget.super.call( this, config );
 
-       // Mixin method
-       OO.ui.GroupWidget.prototype.addItems.call( this, items, index );
+       // Properties
+       this.input = new OO.ui.TextInputWidget( $.extend(
+               { $: this.$, indicator: 'down', disabled: this.isDisabled() },
+               config.input
+       ) );
+       this.menu = new OO.ui.MenuWidget( $.extend(
+               { $: this.$, widget: this, input: this.input, disabled: this.isDisabled() },
+               config.menu
+       ) );
 
-       // Always provide an index, even if it was omitted
-       this.emit( 'add', items, index === undefined ? this.items.length - items.length - 1 : index );
+       // Events
+       this.input.connect( this, {
+               change: 'onInputChange',
+               indicator: 'onInputIndicator',
+               enter: 'onInputEnter'
+       } );
+       this.menu.connect( this, {
+               choose: 'onMenuChoose',
+               add: 'onMenuItemsChange',
+               remove: 'onMenuItemsChange'
+       } );
 
-       return this;
+       // Initialization
+       this.$element.addClass( 'oo-ui-comboBoxWidget' ).append(
+               this.input.$element,
+               this.menu.$element
+       );
+       this.onMenuItemsChange();
 };
 
+/* Setup */
+
+OO.inheritClass( OO.ui.ComboBoxWidget, OO.ui.Widget );
+
+/* Methods */
+
 /**
- * Remove items.
- *
- * Items will be detached, not removed, so they can be used later.
+ * Handle input change events.
  *
- * @param {OO.ui.OptionWidget[]} items Items to remove
- * @fires remove
- * @chainable
+ * @param {string} value New value
  */
-OO.ui.SelectWidget.prototype.removeItems = function ( items ) {
-       var i, len, item, hash;
+OO.ui.ComboBoxWidget.prototype.onInputChange = function ( value ) {
+       var match = this.menu.getItemFromData( value );
 
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-               hash = OO.getHash( item.getData() );
-               if ( hash in this.hashes ) {
-                       // Remove existing item
-                       delete this.hashes[hash];
-               }
-               if ( item.isSelected() ) {
-                       this.selectItem( null );
-               }
-       }
+       this.menu.selectItem( match );
 
-       // Mixin method
-       OO.ui.GroupWidget.prototype.removeItems.call( this, items );
+       if ( !this.isDisabled() ) {
+               this.menu.toggle( true );
+       }
+};
 
-       this.emit( 'remove', items );
+/**
+ * Handle input indicator events.
+ */
+OO.ui.ComboBoxWidget.prototype.onInputIndicator = function () {
+       if ( !this.isDisabled() ) {
+               this.menu.toggle();
+       }
+};
 
-       return this;
+/**
+ * Handle input enter events.
+ */
+OO.ui.ComboBoxWidget.prototype.onInputEnter = function () {
+       if ( !this.isDisabled() ) {
+               this.menu.toggle( false );
+       }
 };
 
 /**
- * Clear all items.
- *
- * Items will be detached, not removed, so they can be used later.
+ * Handle menu choose events.
  *
- * @fires remove
- * @chainable
+ * @param {OO.ui.OptionWidget} item Chosen item
  */
-OO.ui.SelectWidget.prototype.clearItems = function () {
-       var items = this.items.slice();
+OO.ui.ComboBoxWidget.prototype.onMenuChoose = function ( item ) {
+       if ( item ) {
+               this.input.setValue( item.getData() );
+       }
+};
 
-       // Clear all items
-       this.hashes = {};
-       // Mixin method
-       OO.ui.GroupWidget.prototype.clearItems.call( this );
-       this.selectItem( null );
+/**
+ * Handle menu item change events.
+ */
+OO.ui.ComboBoxWidget.prototype.onMenuItemsChange = function () {
+       this.$element.toggleClass( 'oo-ui-comboBoxWidget-empty', this.menu.isEmpty() );
+};
 
-       this.emit( 'remove', items );
+/**
+ * @inheritdoc
+ */
+OO.ui.ComboBoxWidget.prototype.setDisabled = function ( disabled ) {
+       // Parent method
+       OO.ui.ComboBoxWidget.super.prototype.setDisabled.call( this, disabled );
+
+       if ( this.input ) {
+               this.input.setDisabled( this.isDisabled() );
+       }
+       if ( this.menu ) {
+               this.menu.setDisabled( this.isDisabled() );
+       }
 
        return this;
 };
 
 /**
- * Menu item widget.
- *
- * Use with OO.ui.MenuWidget.
+ * Label widget.
  *
  * @class
- * @extends OO.ui.OptionWidget
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.LabelElement
  *
  * @constructor
- * @param {Mixed} data Item data
  * @param {Object} [config] Configuration options
  */
-OO.ui.MenuItemWidget = function OoUiMenuItemWidget( data, config ) {
-       // Configuration initialization
-       config = $.extend( { 'icon': 'check' }, config );
+OO.ui.LabelWidget = function OoUiLabelWidget( config ) {
+       // Config intialization
+       config = config || {};
 
        // Parent constructor
-       OO.ui.MenuItemWidget.super.call( this, data, config );
+       OO.ui.LabelWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.LabelElement.call( this, $.extend( {}, config, { $label: this.$element } ) );
+
+       // Properties
+       this.input = config.input;
+
+       // Events
+       if ( this.input instanceof OO.ui.InputWidget ) {
+               this.$element.on( 'click', OO.ui.bind( this.onClick, this ) );
+       }
 
        // Initialization
-       this.$element.addClass( 'oo-ui-menuItemWidget' );
+       this.$element.addClass( 'oo-ui-labelWidget' );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.MenuItemWidget, OO.ui.OptionWidget );
+OO.inheritClass( OO.ui.LabelWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.LabelWidget, OO.ui.LabelElement );
+
+/* Static Properties */
+
+OO.ui.LabelWidget.static.tagName = 'span';
+
+/* Methods */
 
 /**
- * Menu widget.
+ * Handles label mouse click events.
  *
- * Use together with OO.ui.MenuItemWidget.
+ * @param {jQuery.Event} e Mouse click event
+ */
+OO.ui.LabelWidget.prototype.onClick = function () {
+       this.input.simulateLabelClick();
+       return false;
+};
+
+/**
+ * Generic option widget for use with OO.ui.SelectWidget.
  *
  * @class
- * @extends OO.ui.SelectWidget
- * @mixins OO.ui.ClippableElement
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.LabelElement
+ * @mixins OO.ui.FlaggedElement
  *
  * @constructor
+ * @param {Mixed} data Option data
  * @param {Object} [config] Configuration options
- * @cfg {OO.ui.InputWidget} [input] Input to bind keyboard handlers to
- * @cfg {boolean} [autoHide=true] Hide the menu when the mouse is pressed outside the menu
+ * @cfg {string} [rel] Value for `rel` attribute in DOM, allowing per-option styling
  */
-OO.ui.MenuWidget = function OoUiMenuWidget( config ) {
+OO.ui.OptionWidget = function OoUiOptionWidget( data, config ) {
        // Config intialization
        config = config || {};
 
        // Parent constructor
-       OO.ui.MenuWidget.super.call( this, config );
+       OO.ui.OptionWidget.super.call( this, config );
 
        // Mixin constructors
-       OO.ui.ClippableElement.call( this, this.$group, config );
+       OO.ui.ItemWidget.call( this );
+       OO.ui.LabelElement.call( this, config );
+       OO.ui.FlaggedElement.call( this, config );
 
        // Properties
-       this.autoHide = config.autoHide === undefined || !!config.autoHide;
-       this.newItems = null;
-       this.$input = config.input ? config.input.$input : null;
-       this.$previousFocus = null;
-       this.isolated = !config.input;
-       this.visible = false;
-       this.flashing = false;
-       this.onKeyDownHandler = OO.ui.bind( this.onKeyDown, this );
-       this.onDocumentMouseDownHandler = OO.ui.bind( this.onDocumentMouseDown, this );
+       this.data = data;
+       this.selected = false;
+       this.highlighted = false;
+       this.pressed = false;
 
        // Initialization
-       this.$element.hide().addClass( 'oo-ui-menuWidget' );
+       this.$element
+               .data( 'oo-ui-optionWidget', this )
+               .attr( 'rel', config.rel )
+               .attr( 'role', 'option' )
+               .addClass( 'oo-ui-optionWidget' )
+               .append( this.$label );
+       this.$element
+               .prepend( this.$icon )
+               .append( this.$indicator );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.MenuWidget, OO.ui.SelectWidget );
-OO.mixinClass( OO.ui.MenuWidget, OO.ui.ClippableElement );
+OO.inheritClass( OO.ui.OptionWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.ItemWidget );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.LabelElement );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.FlaggedElement );
+
+/* Static Properties */
+
+OO.ui.OptionWidget.static.selectable = true;
+
+OO.ui.OptionWidget.static.highlightable = true;
+
+OO.ui.OptionWidget.static.pressable = true;
+
+OO.ui.OptionWidget.static.scrollIntoViewOnSelect = false;
 
 /* Methods */
 
 /**
- * Handles document mouse down events.
+ * Check if option can be selected.
  *
- * @param {jQuery.Event} e Key down event
+ * @return {boolean} Item is selectable
  */
-OO.ui.MenuWidget.prototype.onDocumentMouseDown = function ( e ) {
-       if ( !$.contains( this.$element[0], e.target ) ) {
-               this.hide();
-       }
+OO.ui.OptionWidget.prototype.isSelectable = function () {
+       return this.constructor.static.selectable && !this.isDisabled();
 };
 
 /**
- * Handles key down events.
+ * Check if option can be highlighted.
  *
- * @param {jQuery.Event} e Key down event
+ * @return {boolean} Item is highlightable
  */
-OO.ui.MenuWidget.prototype.onKeyDown = function ( e ) {
-       var nextItem,
-               handled = false,
-               highlightItem = this.getHighlightedItem();
-
-       if ( !this.isDisabled() && this.visible ) {
-               if ( !highlightItem ) {
-                       highlightItem = this.getSelectedItem();
-               }
-               switch ( e.keyCode ) {
-                       case OO.ui.Keys.ENTER:
-                               this.chooseItem( highlightItem );
-                               handled = true;
-                               break;
-                       case OO.ui.Keys.UP:
-                               nextItem = this.getRelativeSelectableItem( highlightItem, -1 );
-                               handled = true;
-                               break;
-                       case OO.ui.Keys.DOWN:
-                               nextItem = this.getRelativeSelectableItem( highlightItem, 1 );
-                               handled = true;
-                               break;
-                       case OO.ui.Keys.ESCAPE:
-                               if ( highlightItem ) {
-                                       highlightItem.setHighlighted( false );
-                               }
-                               this.hide();
-                               handled = true;
-                               break;
-               }
-
-               if ( nextItem ) {
-                       this.highlightItem( nextItem );
-                       nextItem.scrollElementIntoView();
-               }
-
-               if ( handled ) {
-                       e.preventDefault();
-                       e.stopPropagation();
-                       return false;
-               }
-       }
+OO.ui.OptionWidget.prototype.isHighlightable = function () {
+       return this.constructor.static.highlightable && !this.isDisabled();
 };
 
 /**
- * Check if the menu is visible.
+ * Check if option can be pressed.
  *
- * @return {boolean} Menu is visible
+ * @return {boolean} Item is pressable
  */
-OO.ui.MenuWidget.prototype.isVisible = function () {
-       return this.visible;
+OO.ui.OptionWidget.prototype.isPressable = function () {
+       return this.constructor.static.pressable && !this.isDisabled();
 };
 
 /**
- * Bind key down listener.
+ * Check if option is selected.
+ *
+ * @return {boolean} Item is selected
  */
-OO.ui.MenuWidget.prototype.bindKeyDownListener = function () {
-       if ( this.$input ) {
-               this.$input.on( 'keydown', this.onKeyDownHandler );
-       } else {
-               // Capture menu navigation keys
-               this.getElementWindow().addEventListener( 'keydown', this.onKeyDownHandler, true );
-       }
+OO.ui.OptionWidget.prototype.isSelected = function () {
+       return this.selected;
 };
 
 /**
- * Unbind key down listener.
+ * Check if option is highlighted.
+ *
+ * @return {boolean} Item is highlighted
  */
-OO.ui.MenuWidget.prototype.unbindKeyDownListener = function () {
-       if ( this.$input ) {
-               this.$input.off( 'keydown' );
-       } else {
-               this.getElementWindow().removeEventListener( 'keydown', this.onKeyDownHandler, true );
-       }
+OO.ui.OptionWidget.prototype.isHighlighted = function () {
+       return this.highlighted;
 };
 
 /**
- * Choose an item.
+ * Check if option is pressed.
  *
- * This will close the menu when done, unlike selectItem which only changes selection.
+ * @return {boolean} Item is pressed
+ */
+OO.ui.OptionWidget.prototype.isPressed = function () {
+       return this.pressed;
+};
+
+/**
+ * Set selected state.
  *
- * @param {OO.ui.OptionWidget} item Item to choose
+ * @param {boolean} [state=false] Select option
  * @chainable
  */
-OO.ui.MenuWidget.prototype.chooseItem = function ( item ) {
-       // Parent method
-       OO.ui.MenuWidget.super.prototype.chooseItem.call( this, item );
-
-       if ( item && !this.flashing ) {
-               this.flashing = true;
-               item.flash().done( OO.ui.bind( function () {
-                       this.hide();
-                       this.flashing = false;
-               }, this ) );
-       } else {
-               this.hide();
+OO.ui.OptionWidget.prototype.setSelected = function ( state ) {
+       if ( this.constructor.static.selectable ) {
+               this.selected = !!state;
+               this.$element.toggleClass( 'oo-ui-optionWidget-selected', state );
+               if ( state && this.constructor.static.scrollIntoViewOnSelect ) {
+                       this.scrollElementIntoView();
+               }
        }
-
        return this;
 };
 
 /**
- * Add items.
- *
- * Adding an existing item (by value) will move it.
+ * Set highlighted state.
  *
- * @param {OO.ui.MenuItemWidget[]} items Items to add
- * @param {number} [index] Index to insert items after
+ * @param {boolean} [state=false] Highlight option
  * @chainable
  */
-OO.ui.MenuWidget.prototype.addItems = function ( items, index ) {
-       var i, len, item;
-
-       // Parent method
-       OO.ui.MenuWidget.super.prototype.addItems.call( this, items, index );
-
-       // Auto-initialize
-       if ( !this.newItems ) {
-               this.newItems = [];
-       }
-
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-               if ( this.visible ) {
-                       // Defer fitting label until
-                       item.fitLabel();
-               } else {
-                       this.newItems.push( item );
-               }
+OO.ui.OptionWidget.prototype.setHighlighted = function ( state ) {
+       if ( this.constructor.static.highlightable ) {
+               this.highlighted = !!state;
+               this.$element.toggleClass( 'oo-ui-optionWidget-highlighted', state );
        }
-
        return this;
 };
 
 /**
- * Show the menu.
+ * Set pressed state.
  *
+ * @param {boolean} [state=false] Press option
  * @chainable
  */
-OO.ui.MenuWidget.prototype.show = function () {
-       var i, len;
+OO.ui.OptionWidget.prototype.setPressed = function ( state ) {
+       if ( this.constructor.static.pressable ) {
+               this.pressed = !!state;
+               this.$element.toggleClass( 'oo-ui-optionWidget-pressed', state );
+       }
+       return this;
+};
 
-       if ( this.items.length ) {
-               this.$element.show();
-               this.visible = true;
-               this.bindKeyDownListener();
+/**
+ * Make the option's highlight flash.
+ *
+ * While flashing, the visual style of the pressed state is removed if present.
+ *
+ * @return {jQuery.Promise} Promise resolved when flashing is done
+ */
+OO.ui.OptionWidget.prototype.flash = function () {
+       var widget = this,
+               $element = this.$element,
+               deferred = $.Deferred();
 
-               // Change focus to enable keyboard navigation
-               if ( this.isolated && this.$input && !this.$input.is( ':focus' ) ) {
-                       this.$previousFocus = this.$( ':focus' );
-                       this.$input.focus();
-               }
-               if ( this.newItems && this.newItems.length ) {
-                       for ( i = 0, len = this.newItems.length; i < len; i++ ) {
-                               this.newItems[i].fitLabel();
-                       }
-                       this.newItems = null;
-               }
+       if ( !this.isDisabled() && this.constructor.static.pressable ) {
+               $element.removeClass( 'oo-ui-optionWidget-highlighted oo-ui-optionWidget-pressed' );
+               setTimeout( function () {
+                       // Restore original classes
+                       $element
+                               .toggleClass( 'oo-ui-optionWidget-highlighted', widget.highlighted )
+                               .toggleClass( 'oo-ui-optionWidget-pressed', widget.pressed );
 
-               this.setClipping( true );
+                       setTimeout( function () {
+                               deferred.resolve();
+                       }, 100 );
 
-               // Auto-hide
-               if ( this.autoHide ) {
-                       this.getElementDocument().addEventListener(
-                               'mousedown', this.onDocumentMouseDownHandler, true
-                       );
-               }
+               }, 100 );
        }
 
-       return this;
+       return deferred.promise();
 };
 
 /**
- * Hide the menu.
+ * Get option data.
  *
- * @chainable
+ * @return {Mixed} Option data
  */
-OO.ui.MenuWidget.prototype.hide = function () {
-       this.$element.hide();
-       this.visible = false;
-       this.unbindKeyDownListener();
-
-       if ( this.isolated && this.$previousFocus ) {
-               this.$previousFocus.focus();
-               this.$previousFocus = null;
-       }
+OO.ui.OptionWidget.prototype.getData = function () {
+       return this.data;
+};
 
-       this.getElementDocument().removeEventListener(
-               'mousedown', this.onDocumentMouseDownHandler, true
-       );
+/**
+ * Option widget with an option icon and indicator.
+ *
+ * Use together with OO.ui.SelectWidget.
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ * @mixins OO.ui.IconElement
+ * @mixins OO.ui.IndicatorElement
+ *
+ * @constructor
+ * @param {Mixed} data Option data
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.DecoratedOptionWidget = function OoUiDecoratedOptionWidget( data, config ) {
+       // Parent constructor
+       OO.ui.DecoratedOptionWidget.super.call( this, data, config );
 
-       this.setClipping( false );
+       // Mixin constructors
+       OO.ui.IconElement.call( this, config );
+       OO.ui.IndicatorElement.call( this, config );
 
-       return this;
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-decoratedOptionWidget' )
+               .prepend( this.$icon )
+               .append( this.$indicator );
 };
 
+/* Setup */
+
+OO.inheritClass( OO.ui.DecoratedOptionWidget, OO.ui.OptionWidget );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.IconElement );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.IndicatorElement );
+
 /**
- * Inline menu of options.
+ * Option widget that looks like a button.
  *
- * Use with OO.ui.MenuOptionWidget.
+ * Use together with OO.ui.ButtonSelectWidget.
  *
  * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.IndicatedElement
- * @mixins OO.ui.LabeledElement
- * @mixins OO.ui.TitledElement
+ * @extends OO.ui.DecoratedOptionWidget
+ * @mixins OO.ui.ButtonElement
  *
  * @constructor
+ * @param {Mixed} data Option data
  * @param {Object} [config] Configuration options
- * @cfg {Object} [menu] Configuration options to pass to menu widget
  */
-OO.ui.InlineMenuWidget = function OoUiInlineMenuWidget( config ) {
-       // Configuration initialization
-       config = $.extend( { 'indicator': 'down' }, config );
-
+OO.ui.ButtonOptionWidget = function OoUiButtonOptionWidget( data, config ) {
        // Parent constructor
-       OO.ui.InlineMenuWidget.super.call( this, config );
+       OO.ui.ButtonOptionWidget.super.call( this, data, config );
 
        // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
-       OO.ui.TitledElement.call( this, this.$label, config );
-
-       // Properties
-       this.menu = new OO.ui.MenuWidget( $.extend( { '$': this.$ }, config.menu ) );
-       this.$handle = this.$( '<span>' );
-
-       // Events
-       this.$element.on( { 'click': OO.ui.bind( this.onClick, this ) } );
-       this.menu.connect( this, { 'select': 'onMenuSelect' } );
+       OO.ui.ButtonElement.call( this, config );
 
        // Initialization
-       this.$handle
-               .addClass( 'oo-ui-inlineMenuWidget-handle' )
-               .append( this.$icon, this.$label, this.$indicator );
-       this.$element
-               .addClass( 'oo-ui-inlineMenuWidget' )
-               .append( this.$handle, this.menu.$element );
+       this.$element.addClass( 'oo-ui-buttonOptionWidget' );
+       this.$button.append( this.$element.contents() );
+       this.$element.append( this.$button );
 };
 
-/* Setup */
+/* Setup */
+
+OO.inheritClass( OO.ui.ButtonOptionWidget, OO.ui.DecoratedOptionWidget );
+OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.ButtonElement );
+
+/* Static Properties */
 
-OO.inheritClass( OO.ui.InlineMenuWidget, OO.ui.Widget );
-OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.IndicatedElement );
-OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.LabeledElement );
-OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.TitledElement );
+// Allow button mouse down events to pass through so they can be handled by the parent select widget
+OO.ui.ButtonOptionWidget.static.cancelButtonMouseDownEvents = false;
 
 /* Methods */
 
 /**
- * Get the menu.
- *
- * @return {OO.ui.MenuWidget} Menu of widget
- */
-OO.ui.InlineMenuWidget.prototype.getMenu = function () {
-       return this.menu;
-};
-
-/**
- * Handles menu select events.
- *
- * @param {OO.ui.MenuItemWidget} item Selected menu item
+ * @inheritdoc
  */
-OO.ui.InlineMenuWidget.prototype.onMenuSelect = function ( item ) {
-       var selectedLabel;
-
-       if ( !item ) {
-               return;
-       }
-
-       selectedLabel = item.getLabel();
+OO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {
+       OO.ui.ButtonOptionWidget.super.prototype.setSelected.call( this, state );
 
-       // If the label is a DOM element, clone it, because setLabel will append() it
-       if ( selectedLabel instanceof jQuery ) {
-               selectedLabel = selectedLabel.clone();
+       if ( this.constructor.static.selectable ) {
+               this.setActive( state );
        }
 
-       this.setLabel( selectedLabel );
+       return this;
 };
 
 /**
- * Handles mouse click events.
+ * Item of an OO.ui.MenuWidget.
  *
- * @param {jQuery.Event} e Mouse click event
+ * @class
+ * @extends OO.ui.DecoratedOptionWidget
+ *
+ * @constructor
+ * @param {Mixed} data Item data
+ * @param {Object} [config] Configuration options
  */
-OO.ui.InlineMenuWidget.prototype.onClick = function ( e ) {
-       // Skip clicks within the menu
-       if ( $.contains( this.menu.$element[0], e.target ) ) {
-               return;
-       }
+OO.ui.MenuItemWidget = function OoUiMenuItemWidget( data, config ) {
+       // Configuration initialization
+       config = $.extend( { icon: 'check' }, config );
 
-       if ( !this.isDisabled() ) {
-               if ( this.menu.isVisible() ) {
-                       this.menu.hide();
-               } else {
-                       this.menu.show();
-               }
-       }
-       return false;
+       // Parent constructor
+       OO.ui.MenuItemWidget.super.call( this, data, config );
+
+       // Initialization
+       this.$element
+               .attr( 'role', 'menuitem' )
+               .addClass( 'oo-ui-menuItemWidget' );
 };
 
+/* Setup */
+
+OO.inheritClass( OO.ui.MenuItemWidget, OO.ui.DecoratedOptionWidget );
+
 /**
- * Menu section item widget.
- *
- * Use with OO.ui.MenuWidget.
+ * Section to group one or more items in a OO.ui.MenuWidget.
  *
  * @class
- * @extends OO.ui.OptionWidget
+ * @extends OO.ui.DecoratedOptionWidget
  *
  * @constructor
  * @param {Mixed} data Item data
@@ -7380,7 +9651,7 @@ OO.ui.MenuSectionItemWidget = function OoUiMenuSectionItemWidget( data, config )
 
 /* Setup */
 
-OO.inheritClass( OO.ui.MenuSectionItemWidget, OO.ui.OptionWidget );
+OO.inheritClass( OO.ui.MenuSectionItemWidget, OO.ui.DecoratedOptionWidget );
 
 /* Static Properties */
 
@@ -7389,1017 +9660,1393 @@ OO.ui.MenuSectionItemWidget.static.selectable = false;
 OO.ui.MenuSectionItemWidget.static.highlightable = false;
 
 /**
- * Create an OO.ui.OutlineWidget object.
- *
- * Use with OO.ui.OutlineItemWidget.
+ * Items for an OO.ui.OutlineWidget.
  *
  * @class
- * @extends OO.ui.SelectWidget
+ * @extends OO.ui.DecoratedOptionWidget
  *
  * @constructor
+ * @param {Mixed} data Item data
  * @param {Object} [config] Configuration options
+ * @cfg {number} [level] Indentation level
+ * @cfg {boolean} [movable] Allow modification from outline controls
  */
-OO.ui.OutlineWidget = function OoUiOutlineWidget( config ) {
+OO.ui.OutlineItemWidget = function OoUiOutlineItemWidget( data, config ) {
        // Config intialization
        config = config || {};
 
        // Parent constructor
-       OO.ui.OutlineWidget.super.call( this, config );
+       OO.ui.OutlineItemWidget.super.call( this, data, config );
+
+       // Properties
+       this.level = 0;
+       this.movable = !!config.movable;
+       this.removable = !!config.removable;
 
        // Initialization
-       this.$element.addClass( 'oo-ui-outlineWidget' );
+       this.$element.addClass( 'oo-ui-outlineItemWidget' );
+       this.setLevel( config.level );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.OutlineWidget, OO.ui.SelectWidget );
-
-/**
- * Creates an OO.ui.OutlineControlsWidget object.
- *
- * Use together with OO.ui.OutlineWidget.js
- *
- * @class
- *
- * @constructor
- * @param {OO.ui.OutlineWidget} outline Outline to control
- * @param {Object} [config] Configuration options
- */
-OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) {
-       // Configuration initialization
-       config = $.extend( { 'icon': 'add-item' }, config );
+OO.inheritClass( OO.ui.OutlineItemWidget, OO.ui.DecoratedOptionWidget );
 
-       // Parent constructor
-       OO.ui.OutlineControlsWidget.super.call( this, config );
+/* Static Properties */
 
-       // Mixin constructors
-       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
-       OO.ui.IconedElement.call( this, this.$( '<div>' ), config );
+OO.ui.OutlineItemWidget.static.highlightable = false;
 
-       // Properties
-       this.outline = outline;
-       this.$movers = this.$( '<div>' );
-       this.upButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'collapse',
-               'title': OO.ui.msg( 'ooui-outline-control-move-up' )
-       } );
-       this.downButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'expand',
-               'title': OO.ui.msg( 'ooui-outline-control-move-down' )
-       } );
-       this.removeButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'remove',
-               'title': OO.ui.msg( 'ooui-outline-control-remove' )
-       } );
+OO.ui.OutlineItemWidget.static.scrollIntoViewOnSelect = true;
 
-       // Events
-       outline.connect( this, {
-               'select': 'onOutlineChange',
-               'add': 'onOutlineChange',
-               'remove': 'onOutlineChange'
-       } );
-       this.upButton.connect( this, { 'click': [ 'emit', 'move', -1 ] } );
-       this.downButton.connect( this, { 'click': [ 'emit', 'move', 1 ] } );
-       this.removeButton.connect( this, { 'click': [ 'emit', 'remove' ] } );
+OO.ui.OutlineItemWidget.static.levelClass = 'oo-ui-outlineItemWidget-level-';
 
-       // Initialization
-       this.$element.addClass( 'oo-ui-outlineControlsWidget' );
-       this.$group.addClass( 'oo-ui-outlineControlsWidget-items' );
-       this.$movers
-               .addClass( 'oo-ui-outlineControlsWidget-movers' )
-               .append( this.removeButton.$element, this.upButton.$element, this.downButton.$element );
-       this.$element.append( this.$icon, this.$group, this.$movers );
-};
+OO.ui.OutlineItemWidget.static.levels = 3;
 
-/* Setup */
+/* Methods */
 
-OO.inheritClass( OO.ui.OutlineControlsWidget, OO.ui.Widget );
-OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.GroupElement );
-OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.IconedElement );
+/**
+ * Check if item is movable.
+ *
+ * Movablilty is used by outline controls.
+ *
+ * @return {boolean} Item is movable
+ */
+OO.ui.OutlineItemWidget.prototype.isMovable = function () {
+       return this.movable;
+};
 
-/* Events */
+/**
+ * Check if item is removable.
+ *
+ * Removablilty is used by outline controls.
+ *
+ * @return {boolean} Item is removable
+ */
+OO.ui.OutlineItemWidget.prototype.isRemovable = function () {
+       return this.removable;
+};
 
 /**
- * @event move
- * @param {number} places Number of places to move
+ * Get indentation level.
+ *
+ * @return {number} Indentation level
  */
+OO.ui.OutlineItemWidget.prototype.getLevel = function () {
+       return this.level;
+};
 
 /**
- * @event remove
+ * Set movability.
+ *
+ * Movablilty is used by outline controls.
+ *
+ * @param {boolean} movable Item is movable
+ * @chainable
  */
+OO.ui.OutlineItemWidget.prototype.setMovable = function ( movable ) {
+       this.movable = !!movable;
+       return this;
+};
 
-/* Methods */
+/**
+ * Set removability.
+ *
+ * Removablilty is used by outline controls.
+ *
+ * @param {boolean} movable Item is removable
+ * @chainable
+ */
+OO.ui.OutlineItemWidget.prototype.setRemovable = function ( removable ) {
+       this.removable = !!removable;
+       return this;
+};
 
 /**
- * Handle outline change events.
+ * Set indentation level.
+ *
+ * @param {number} [level=0] Indentation level, in the range of [0,#maxLevel]
+ * @chainable
  */
-OO.ui.OutlineControlsWidget.prototype.onOutlineChange = function () {
-       var i, len, firstMovable, lastMovable,
-               items = this.outline.getItems(),
-               selectedItem = this.outline.getSelectedItem(),
-               movable = selectedItem && selectedItem.isMovable(),
-               removable = selectedItem && selectedItem.isRemovable();
+OO.ui.OutlineItemWidget.prototype.setLevel = function ( level ) {
+       var levels = this.constructor.static.levels,
+               levelClass = this.constructor.static.levelClass,
+               i = levels;
 
-       if ( movable ) {
-               i = -1;
-               len = items.length;
-               while ( ++i < len ) {
-                       if ( items[i].isMovable() ) {
-                               firstMovable = items[i];
-                               break;
-                       }
-               }
-               i = len;
-               while ( i-- ) {
-                       if ( items[i].isMovable() ) {
-                               lastMovable = items[i];
-                               break;
-                       }
+       this.level = level ? Math.max( 0, Math.min( levels - 1, level ) ) : 0;
+       while ( i-- ) {
+               if ( this.level === i ) {
+                       this.$element.addClass( levelClass + i );
+               } else {
+                       this.$element.removeClass( levelClass + i );
                }
        }
-       this.upButton.setDisabled( !movable || selectedItem === firstMovable );
-       this.downButton.setDisabled( !movable || selectedItem === lastMovable );
-       this.removeButton.setDisabled( !removable );
+
+       return this;
 };
 
 /**
- * Creates an OO.ui.OutlineItemWidget object.
- *
- * Use with OO.ui.OutlineWidget.
+ * Container for content that is overlaid and positioned absolutely.
  *
  * @class
- * @extends OO.ui.OptionWidget
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.LabelElement
  *
  * @constructor
- * @param {Mixed} data Item data
  * @param {Object} [config] Configuration options
- * @cfg {number} [level] Indentation level
- * @cfg {boolean} [movable] Allow modification from outline controls
+ * @cfg {number} [width=320] Width of popup in pixels
+ * @cfg {number} [height] Height of popup, omit to use automatic height
+ * @cfg {boolean} [anchor=true] Show anchor pointing to origin of popup
+ * @cfg {string} [align='center'] Alignment of popup to origin
+ * @cfg {jQuery} [$container] Container to prevent popup from rendering outside of
+ * @cfg {jQuery} [$content] Content to append to the popup's body
+ * @cfg {boolean} [autoClose=false] Popup auto-closes when it loses focus
+ * @cfg {jQuery} [$autoCloseIgnore] Elements to not auto close when clicked
+ * @cfg {boolean} [head] Show label and close button at the top
+ * @cfg {boolean} [padded] Add padding to the body
  */
-OO.ui.OutlineItemWidget = function OoUiOutlineItemWidget( data, config ) {
+OO.ui.PopupWidget = function OoUiPopupWidget( config ) {
        // Config intialization
        config = config || {};
 
        // Parent constructor
-       OO.ui.OutlineItemWidget.super.call( this, data, config );
+       OO.ui.PopupWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.LabelElement.call( this, config );
+       OO.ui.ClippableElement.call( this, config );
 
        // Properties
-       this.level = 0;
-       this.movable = !!config.movable;
-       this.removable = !!config.removable;
+       this.visible = false;
+       this.$popup = this.$( '<div>' );
+       this.$head = this.$( '<div>' );
+       this.$body = this.$( '<div>' );
+       this.$anchor = this.$( '<div>' );
+       this.$container = config.$container; // If undefined, will be computed lazily in updateDimensions()
+       this.autoClose = !!config.autoClose;
+       this.$autoCloseIgnore = config.$autoCloseIgnore;
+       this.transitionTimeout = null;
+       this.anchor = null;
+       this.width = config.width !== undefined ? config.width : 320;
+       this.height = config.height !== undefined ? config.height : null;
+       this.align = config.align || 'center';
+       this.closeButton = new OO.ui.ButtonWidget( { $: this.$, framed: false, icon: 'close' } );
+       this.onMouseDownHandler = OO.ui.bind( this.onMouseDown, this );
+
+       // Events
+       this.closeButton.connect( this, { click: 'onCloseButtonClick' } );
 
        // Initialization
-       this.$element.addClass( 'oo-ui-outlineItemWidget' );
-       this.setLevel( config.level );
+       this.toggleAnchor( config.anchor === undefined || config.anchor );
+       this.$body.addClass( 'oo-ui-popupWidget-body' );
+       this.$anchor.addClass( 'oo-ui-popupWidget-anchor' );
+       this.$head
+               .addClass( 'oo-ui-popupWidget-head' )
+               .append( this.$label, this.closeButton.$element );
+       if ( !config.head ) {
+               this.$head.hide();
+       }
+       this.$popup
+               .addClass( 'oo-ui-popupWidget-popup' )
+               .append( this.$head, this.$body );
+       this.$element
+               .hide()
+               .addClass( 'oo-ui-popupWidget' )
+               .append( this.$popup, this.$anchor );
+       // Move content, which was added to #$element by OO.ui.Widget, to the body
+       if ( config.$content instanceof jQuery ) {
+               this.$body.append( config.$content );
+       }
+       if ( config.padded ) {
+               this.$body.addClass( 'oo-ui-popupWidget-body-padded' );
+       }
+       this.setClippableElement( this.$body );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.OutlineItemWidget, OO.ui.OptionWidget );
-
-/* Static Properties */
-
-OO.ui.OutlineItemWidget.static.highlightable = false;
+OO.inheritClass( OO.ui.PopupWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.PopupWidget, OO.ui.LabelElement );
+OO.mixinClass( OO.ui.PopupWidget, OO.ui.ClippableElement );
 
-OO.ui.OutlineItemWidget.static.scrollIntoViewOnSelect = true;
+/* Events */
 
-OO.ui.OutlineItemWidget.static.levelClass = 'oo-ui-outlineItemWidget-level-';
+/**
+ * @event hide
+ */
 
-OO.ui.OutlineItemWidget.static.levels = 3;
+/**
+ * @event show
+ */
 
 /* Methods */
 
 /**
- * Check if item is movable.
- *
- * Movablilty is used by outline controls.
+ * Handles mouse down events.
  *
- * @return {boolean} Item is movable
+ * @param {jQuery.Event} e Mouse down event
  */
-OO.ui.OutlineItemWidget.prototype.isMovable = function () {
-       return this.movable;
+OO.ui.PopupWidget.prototype.onMouseDown = function ( e ) {
+       if (
+               this.isVisible() &&
+               !$.contains( this.$element[0], e.target ) &&
+               ( !this.$autoCloseIgnore || !this.$autoCloseIgnore.has( e.target ).length )
+       ) {
+               this.toggle( false );
+       }
 };
 
 /**
- * Check if item is removable.
- *
- * Removablilty is used by outline controls.
- *
- * @return {boolean} Item is removable
+ * Bind mouse down listener.
  */
-OO.ui.OutlineItemWidget.prototype.isRemovable = function () {
-       return this.removable;
+OO.ui.PopupWidget.prototype.bindMouseDownListener = function () {
+       // Capture clicks outside popup
+       this.getElementWindow().addEventListener( 'mousedown', this.onMouseDownHandler, true );
 };
 
 /**
- * Get indentation level.
- *
- * @return {number} Indentation level
+ * Handles close button click events.
  */
-OO.ui.OutlineItemWidget.prototype.getLevel = function () {
-       return this.level;
+OO.ui.PopupWidget.prototype.onCloseButtonClick = function () {
+       if ( this.isVisible() ) {
+               this.toggle( false );
+       }
 };
 
 /**
- * Set movability.
+ * Unbind mouse down listener.
+ */
+OO.ui.PopupWidget.prototype.unbindMouseDownListener = function () {
+       this.getElementWindow().removeEventListener( 'mousedown', this.onMouseDownHandler, true );
+};
+
+/**
+ * Set whether to show a anchor.
  *
- * Movablilty is used by outline controls.
+ * @param {boolean} [show] Show anchor, omit to toggle
+ */
+OO.ui.PopupWidget.prototype.toggleAnchor = function ( show ) {
+       show = show === undefined ? !this.anchored : !!show;
+
+       if ( this.anchored !== show ) {
+               if ( show ) {
+                       this.$element.addClass( 'oo-ui-popupWidget-anchored' );
+               } else {
+                       this.$element.removeClass( 'oo-ui-popupWidget-anchored' );
+               }
+               this.anchored = show;
+       }
+};
+
+/**
+ * Check if showing a anchor.
  *
- * @param {boolean} movable Item is movable
- * @chainable
+ * @return {boolean} anchor is visible
  */
-OO.ui.OutlineItemWidget.prototype.setMovable = function ( movable ) {
-       this.movable = !!movable;
+OO.ui.PopupWidget.prototype.hasAnchor = function () {
+       return this.anchor;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.PopupWidget.prototype.toggle = function ( show ) {
+       show = show === undefined ? !this.isVisible() : !!show;
+
+       var change = show !== this.isVisible();
+
+       // Parent method
+       OO.ui.PopupWidget.super.prototype.toggle.call( this, show );
+
+       if ( change ) {
+               if ( show ) {
+                       if ( this.autoClose ) {
+                               this.bindMouseDownListener();
+                       }
+                       this.updateDimensions();
+                       this.toggleClipping( true );
+               } else {
+                       this.toggleClipping( false );
+                       if ( this.autoClose ) {
+                               this.unbindMouseDownListener();
+                       }
+               }
+       }
+
        return this;
 };
 
 /**
- * Set removability.
+ * Set the size of the popup.
  *
- * Removablilty is used by outline controls.
+ * Changing the size may also change the popup's position depending on the alignment.
  *
- * @param {boolean} movable Item is removable
+ * @param {number} width Width
+ * @param {number} height Height
+ * @param {boolean} [transition=false] Use a smooth transition
  * @chainable
  */
-OO.ui.OutlineItemWidget.prototype.setRemovable = function ( removable ) {
-       this.removable = !!removable;
-       return this;
+OO.ui.PopupWidget.prototype.setSize = function ( width, height, transition ) {
+       this.width = width;
+       this.height = height !== undefined ? height : null;
+       if ( this.isVisible() ) {
+               this.updateDimensions( transition );
+       }
 };
 
 /**
- * Set indentation level.
+ * Update the size and position.
  *
- * @param {number} [level=0] Indentation level, in the range of [0,#maxLevel]
+ * Only use this to keep the popup properly anchored. Use #setSize to change the size, and this will
+ * be called automatically.
+ *
+ * @param {boolean} [transition=false] Use a smooth transition
  * @chainable
  */
-OO.ui.OutlineItemWidget.prototype.setLevel = function ( level ) {
-       var levels = this.constructor.static.levels,
-               levelClass = this.constructor.static.levelClass,
-               i = levels;
+OO.ui.PopupWidget.prototype.updateDimensions = function ( transition ) {
+       var popupOffset, originOffset, containerLeft, containerWidth, containerRight,
+               popupLeft, popupRight, overlapLeft, overlapRight, anchorWidth,
+               widget = this,
+               padding = 10;
 
-       this.level = level ? Math.max( 0, Math.min( levels - 1, level ) ) : 0;
-       while ( i-- ) {
-               if ( this.level === i ) {
-                       this.$element.addClass( levelClass + i );
-               } else {
-                       this.$element.removeClass( levelClass + i );
-               }
+       if ( !this.$container ) {
+               // Lazy-initialize $container if not specified in constructor
+               this.$container = this.$( this.getClosestScrollableElementContainer() );
+       }
+
+       // Set height and width before measuring things, since it might cause our measurements
+       // to change (e.g. due to scrollbars appearing or disappearing)
+       this.$popup.css( {
+               width: this.width,
+               height: this.height !== null ? this.height : 'auto'
+       } );
+
+       // Compute initial popupOffset based on alignment
+       popupOffset = this.width * ( { left: 0, center: -0.5, right: -1 } )[this.align];
+
+       // Figure out if this will cause the popup to go beyond the edge of the container
+       originOffset = Math.round( this.$element.offset().left );
+       containerLeft = Math.round( this.$container.offset().left );
+       containerWidth = this.$container.innerWidth();
+       containerRight = containerLeft + containerWidth;
+       popupLeft = popupOffset - padding;
+       popupRight = popupOffset + padding + this.width + padding;
+       overlapLeft = ( originOffset + popupLeft ) - containerLeft;
+       overlapRight = containerRight - ( originOffset + popupRight );
+
+       // Adjust offset to make the popup not go beyond the edge, if needed
+       if ( overlapRight < 0 ) {
+               popupOffset += overlapRight;
+       } else if ( overlapLeft < 0 ) {
+               popupOffset -= overlapLeft;
+       }
+
+       // Adjust offset to avoid anchor being rendered too close to the edge
+       anchorWidth = this.$anchor.width();
+       if ( this.align === 'right' ) {
+               popupOffset += anchorWidth;
+       } else if ( this.align === 'left' ) {
+               popupOffset -= anchorWidth;
+       }
+
+       // Prevent transition from being interrupted
+       clearTimeout( this.transitionTimeout );
+       if ( transition ) {
+               // Enable transition
+               this.$element.addClass( 'oo-ui-popupWidget-transitioning' );
+       }
+
+       // Position body relative to anchor
+       this.$popup.css( 'left', popupOffset );
+
+       if ( transition ) {
+               // Prevent transitioning after transition is complete
+               this.transitionTimeout = setTimeout( function () {
+                       widget.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
+               }, 200 );
+       } else {
+               // Prevent transitioning immediately
+               this.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
        }
 
        return this;
 };
 
 /**
- * Option widget that looks like a button.
+ * Search widget.
  *
- * Use together with OO.ui.ButtonSelectWidget.
+ * Search widgets combine a query input, placed above, and a results selection widget, placed below.
+ * Results are cleared and populated each time the query is changed.
  *
  * @class
- * @extends OO.ui.OptionWidget
- * @mixins OO.ui.ButtonedElement
- * @mixins OO.ui.FlaggableElement
+ * @extends OO.ui.Widget
  *
  * @constructor
- * @param {Mixed} data Option data
  * @param {Object} [config] Configuration options
+ * @cfg {string|jQuery} [placeholder] Placeholder text for query input
+ * @cfg {string} [value] Initial query value
  */
-OO.ui.ButtonOptionWidget = function OoUiButtonOptionWidget( data, config ) {
+OO.ui.SearchWidget = function OoUiSearchWidget( config ) {
+       // Configuration intialization
+       config = config || {};
+
        // Parent constructor
-       OO.ui.ButtonOptionWidget.super.call( this, data, config );
+       OO.ui.SearchWidget.super.call( this, config );
 
-       // Mixin constructors
-       OO.ui.ButtonedElement.call( this, this.$( '<a>' ), config );
-       OO.ui.FlaggableElement.call( this, config );
+       // Properties
+       this.query = new OO.ui.TextInputWidget( {
+               $: this.$,
+               icon: 'search',
+               placeholder: config.placeholder,
+               value: config.value
+       } );
+       this.results = new OO.ui.SelectWidget( { $: this.$ } );
+       this.$query = this.$( '<div>' );
+       this.$results = this.$( '<div>' );
+
+       // Events
+       this.query.connect( this, {
+               change: 'onQueryChange',
+               enter: 'onQueryEnter'
+       } );
+       this.results.connect( this, {
+               highlight: 'onResultsHighlight',
+               select: 'onResultsSelect'
+       } );
+       this.query.$input.on( 'keydown', OO.ui.bind( this.onQueryKeydown, this ) );
 
        // Initialization
-       this.$element.addClass( 'oo-ui-buttonOptionWidget' );
-       this.$button.append( this.$element.contents() );
-       this.$element.append( this.$button );
+       this.$query
+               .addClass( 'oo-ui-searchWidget-query' )
+               .append( this.query.$element );
+       this.$results
+               .addClass( 'oo-ui-searchWidget-results' )
+               .append( this.results.$element );
+       this.$element
+               .addClass( 'oo-ui-searchWidget' )
+               .append( this.$results, this.$query );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.ButtonOptionWidget, OO.ui.OptionWidget );
-OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.ButtonedElement );
-OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.FlaggableElement );
+OO.inheritClass( OO.ui.SearchWidget, OO.ui.Widget );
 
-/* Static Properties */
+/* Events */
 
-// Allow button mouse down events to pass through so they can be handled by the parent select widget
-OO.ui.ButtonOptionWidget.static.cancelButtonMouseDownEvents = false;
+/**
+ * @event highlight
+ * @param {Object|null} item Item data or null if no item is highlighted
+ */
+
+/**
+ * @event select
+ * @param {Object|null} item Item data or null if no item is selected
+ */
 
 /* Methods */
 
 /**
- * @inheritdoc
+ * Handle query key down events.
+ *
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.SearchWidget.prototype.onQueryKeydown = function ( e ) {
+       var highlightedItem, nextItem,
+               dir = e.which === OO.ui.Keys.DOWN ? 1 : ( e.which === OO.ui.Keys.UP ? -1 : 0 );
+
+       if ( dir ) {
+               highlightedItem = this.results.getHighlightedItem();
+               if ( !highlightedItem ) {
+                       highlightedItem = this.results.getSelectedItem();
+               }
+               nextItem = this.results.getRelativeSelectableItem( highlightedItem, dir );
+               this.results.highlightItem( nextItem );
+               nextItem.scrollElementIntoView();
+       }
+};
+
+/**
+ * Handle select widget select events.
+ *
+ * Clears existing results. Subclasses should repopulate items according to new query.
+ *
+ * @param {string} value New value
+ */
+OO.ui.SearchWidget.prototype.onQueryChange = function () {
+       // Reset
+       this.results.clearItems();
+};
+
+/**
+ * Handle select widget enter key events.
+ *
+ * Selects highlighted item.
+ *
+ * @param {string} value New value
+ */
+OO.ui.SearchWidget.prototype.onQueryEnter = function () {
+       // Reset
+       this.results.selectItem( this.results.getHighlightedItem() );
+};
+
+/**
+ * Handle select widget highlight events.
+ *
+ * @param {OO.ui.OptionWidget} item Highlighted item
+ * @fires highlight
+ */
+OO.ui.SearchWidget.prototype.onResultsHighlight = function ( item ) {
+       this.emit( 'highlight', item ? item.getData() : null );
+};
+
+/**
+ * Handle select widget select events.
+ *
+ * @param {OO.ui.OptionWidget} item Selected item
+ * @fires select
  */
-OO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {
-       OO.ui.ButtonOptionWidget.super.prototype.setSelected.call( this, state );
-
-       if ( this.constructor.static.selectable ) {
-               this.setActive( state );
-       }
-
-       return this;
+OO.ui.SearchWidget.prototype.onResultsSelect = function ( item ) {
+       this.emit( 'select', item ? item.getData() : null );
 };
 
 /**
- * Select widget containing button options.
- *
- * Use together with OO.ui.ButtonOptionWidget.
- *
- * @class
- * @extends OO.ui.SelectWidget
+ * Get the query input.
  *
- * @constructor
- * @param {Object} [config] Configuration options
+ * @return {OO.ui.TextInputWidget} Query input
  */
-OO.ui.ButtonSelectWidget = function OoUiButtonSelectWidget( config ) {
-       // Parent constructor
-       OO.ui.ButtonSelectWidget.super.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-buttonSelectWidget' );
+OO.ui.SearchWidget.prototype.getQuery = function () {
+       return this.query;
 };
 
-/* Setup */
-
-OO.inheritClass( OO.ui.ButtonSelectWidget, OO.ui.SelectWidget );
+/**
+ * Get the results list.
+ *
+ * @return {OO.ui.SelectWidget} Select list
+ */
+OO.ui.SearchWidget.prototype.getResults = function () {
+       return this.results;
+};
 
 /**
- * Container for content that is overlaid and positioned absolutely.
+ * Generic selection of options.
+ *
+ * Items can contain any rendering, and are uniquely identified by a has of thier data. Any widget
+ * that provides options, from which the user must choose one, should be built on this class.
+ *
+ * Use together with OO.ui.OptionWidget.
  *
  * @class
  * @extends OO.ui.Widget
- * @mixins OO.ui.LabeledElement
+ * @mixins OO.ui.GroupElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {boolean} [tail=true] Show tail pointing to origin of popup
- * @cfg {string} [align='center'] Alignment of popup to origin
- * @cfg {jQuery} [$container] Container to prevent popup from rendering outside of
- * @cfg {boolean} [autoClose=false] Popup auto-closes when it loses focus
- * @cfg {jQuery} [$autoCloseIgnore] Elements to not auto close when clicked
- * @cfg {boolean} [head] Show label and close button at the top
+ * @cfg {OO.ui.OptionWidget[]} [items] Options to add
  */
-OO.ui.PopupWidget = function OoUiPopupWidget( config ) {
+OO.ui.SelectWidget = function OoUiSelectWidget( config ) {
        // Config intialization
        config = config || {};
 
        // Parent constructor
-       OO.ui.PopupWidget.super.call( this, config );
+       OO.ui.SelectWidget.super.call( this, config );
 
        // Mixin constructors
-       OO.ui.LabeledElement.call( this, this.$( '<div>' ), config );
-       OO.ui.ClippableElement.call( this, this.$( '<div>' ), config );
+       OO.ui.GroupWidget.call( this, $.extend( {}, config, { $group: this.$element } ) );
 
        // Properties
-       this.visible = false;
-       this.$popup = this.$( '<div>' );
-       this.$head = this.$( '<div>' );
-       this.$body = this.$clippable;
-       this.$tail = this.$( '<div>' );
-       this.$container = config.$container || this.$( 'body' );
-       this.autoClose = !!config.autoClose;
-       this.$autoCloseIgnore = config.$autoCloseIgnore;
-       this.transitionTimeout = null;
-       this.tail = false;
-       this.align = config.align || 'center';
-       this.closeButton = new OO.ui.ButtonWidget( { '$': this.$, 'frameless': true, 'icon': 'close' } );
-       this.onMouseDownHandler = OO.ui.bind( this.onMouseDown, this );
+       this.pressed = false;
+       this.selecting = null;
+       this.hashes = {};
+       this.onMouseUpHandler = OO.ui.bind( this.onMouseUp, this );
+       this.onMouseMoveHandler = OO.ui.bind( this.onMouseMove, this );
 
        // Events
-       this.closeButton.connect( this, { 'click': 'onCloseButtonClick' } );
+       this.$element.on( {
+               mousedown: OO.ui.bind( this.onMouseDown, this ),
+               mouseover: OO.ui.bind( this.onMouseOver, this ),
+               mouseleave: OO.ui.bind( this.onMouseLeave, this )
+       } );
 
        // Initialization
-       this.useTail( config.tail !== undefined ? !!config.tail : true );
-       this.$body.addClass( 'oo-ui-popupWidget-body' );
-       this.$tail.addClass( 'oo-ui-popupWidget-tail' );
-       this.$head
-               .addClass( 'oo-ui-popupWidget-head' )
-               .append( this.$label, this.closeButton.$element );
-       if ( !config.head ) {
-               this.$head.hide();
+       this.$element.addClass( 'oo-ui-selectWidget oo-ui-selectWidget-depressed' );
+       if ( $.isArray( config.items ) ) {
+               this.addItems( config.items );
        }
-       this.$popup
-               .addClass( 'oo-ui-popupWidget-popup' )
-               .append( this.$head, this.$body );
-       this.$element.hide()
-               .addClass( 'oo-ui-popupWidget' )
-               .append( this.$popup, this.$tail );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.PopupWidget, OO.ui.Widget );
-OO.mixinClass( OO.ui.PopupWidget, OO.ui.LabeledElement );
-OO.mixinClass( OO.ui.PopupWidget, OO.ui.ClippableElement );
+OO.inheritClass( OO.ui.SelectWidget, OO.ui.Widget );
+
+// Need to mixin base class as well
+OO.mixinClass( OO.ui.SelectWidget, OO.ui.GroupElement );
+OO.mixinClass( OO.ui.SelectWidget, OO.ui.GroupWidget );
 
 /* Events */
 
 /**
- * @event hide
+ * @event highlight
+ * @param {OO.ui.OptionWidget|null} item Highlighted item
  */
 
 /**
- * @event show
+ * @event press
+ * @param {OO.ui.OptionWidget|null} item Pressed item
+ */
+
+/**
+ * @event select
+ * @param {OO.ui.OptionWidget|null} item Selected item
+ */
+
+/**
+ * @event choose
+ * @param {OO.ui.OptionWidget|null} item Chosen item
+ */
+
+/**
+ * @event add
+ * @param {OO.ui.OptionWidget[]} items Added items
+ * @param {number} index Index items were added at
+ */
+
+/**
+ * @event remove
+ * @param {OO.ui.OptionWidget[]} items Removed items
  */
 
 /* Methods */
 
 /**
- * Handles mouse down events.
+ * Handle mouse down events.
  *
+ * @private
  * @param {jQuery.Event} e Mouse down event
  */
-OO.ui.PopupWidget.prototype.onMouseDown = function ( e ) {
-       if (
-               this.visible &&
-               !$.contains( this.$element[0], e.target ) &&
-               ( !this.$autoCloseIgnore || !this.$autoCloseIgnore.has( e.target ).length )
-       ) {
-               this.hide();
+OO.ui.SelectWidget.prototype.onMouseDown = function ( e ) {
+       var item;
+
+       if ( !this.isDisabled() && e.which === 1 ) {
+               this.togglePressed( true );
+               item = this.getTargetItem( e );
+               if ( item && item.isSelectable() ) {
+                       this.pressItem( item );
+                       this.selecting = item;
+                       this.getElementDocument().addEventListener(
+                               'mouseup',
+                               this.onMouseUpHandler,
+                               true
+                       );
+                       this.getElementDocument().addEventListener(
+                               'mousemove',
+                               this.onMouseMoveHandler,
+                               true
+                       );
+               }
        }
+       return false;
 };
 
 /**
- * Bind mouse down listener.
+ * Handle mouse up events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse up event
  */
-OO.ui.PopupWidget.prototype.bindMouseDownListener = function () {
-       // Capture clicks outside popup
-       this.getElementWindow().addEventListener( 'mousedown', this.onMouseDownHandler, true );
+OO.ui.SelectWidget.prototype.onMouseUp = function ( e ) {
+       var item;
+
+       this.togglePressed( false );
+       if ( !this.selecting ) {
+               item = this.getTargetItem( e );
+               if ( item && item.isSelectable() ) {
+                       this.selecting = item;
+               }
+       }
+       if ( !this.isDisabled() && e.which === 1 && this.selecting ) {
+               this.pressItem( null );
+               this.chooseItem( this.selecting );
+               this.selecting = null;
+       }
+
+       this.getElementDocument().removeEventListener(
+               'mouseup',
+               this.onMouseUpHandler,
+               true
+       );
+       this.getElementDocument().removeEventListener(
+               'mousemove',
+               this.onMouseMoveHandler,
+               true
+       );
+
+       return false;
 };
 
 /**
- * Handles close button click events.
+ * Handle mouse move events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse move event
  */
-OO.ui.PopupWidget.prototype.onCloseButtonClick = function () {
-       if ( this.visible ) {
-               this.hide();
+OO.ui.SelectWidget.prototype.onMouseMove = function ( e ) {
+       var item;
+
+       if ( !this.isDisabled() && this.pressed ) {
+               item = this.getTargetItem( e );
+               if ( item && item !== this.selecting && item.isSelectable() ) {
+                       this.pressItem( item );
+                       this.selecting = item;
+               }
        }
+       return false;
 };
 
 /**
- * Unbind mouse down listener.
+ * Handle mouse over events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse over event
  */
-OO.ui.PopupWidget.prototype.unbindMouseDownListener = function () {
-       this.getElementWindow().removeEventListener( 'mousedown', this.onMouseDownHandler, true );
+OO.ui.SelectWidget.prototype.onMouseOver = function ( e ) {
+       var item;
+
+       if ( !this.isDisabled() ) {
+               item = this.getTargetItem( e );
+               this.highlightItem( item && item.isHighlightable() ? item : null );
+       }
+       return false;
+};
+
+/**
+ * Handle mouse leave events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse over event
+ */
+OO.ui.SelectWidget.prototype.onMouseLeave = function () {
+       if ( !this.isDisabled() ) {
+               this.highlightItem( null );
+       }
+       return false;
+};
+
+/**
+ * Get the closest item to a jQuery.Event.
+ *
+ * @private
+ * @param {jQuery.Event} e
+ * @return {OO.ui.OptionWidget|null} Outline item widget, `null` if none was found
+ */
+OO.ui.SelectWidget.prototype.getTargetItem = function ( e ) {
+       var $item = this.$( e.target ).closest( '.oo-ui-optionWidget' );
+       if ( $item.length ) {
+               return $item.data( 'oo-ui-optionWidget' );
+       }
+       return null;
+};
+
+/**
+ * Get selected item.
+ *
+ * @return {OO.ui.OptionWidget|null} Selected item, `null` if no item is selected
+ */
+OO.ui.SelectWidget.prototype.getSelectedItem = function () {
+       var i, len;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               if ( this.items[i].isSelected() ) {
+                       return this.items[i];
+               }
+       }
+       return null;
 };
 
 /**
- * Check if the popup is visible.
+ * Get highlighted item.
  *
- * @return {boolean} Popup is visible
+ * @return {OO.ui.OptionWidget|null} Highlighted item, `null` if no item is highlighted
  */
-OO.ui.PopupWidget.prototype.isVisible = function () {
-       return this.visible;
+OO.ui.SelectWidget.prototype.getHighlightedItem = function () {
+       var i, len;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               if ( this.items[i].isHighlighted() ) {
+                       return this.items[i];
+               }
+       }
+       return null;
 };
 
 /**
- * Set whether to show a tail.
+ * Get an existing item with equivilant data.
  *
- * @return {boolean} Make tail visible
+ * @param {Object} data Item data to search for
+ * @return {OO.ui.OptionWidget|null} Item with equivilent value, `null` if none exists
  */
-OO.ui.PopupWidget.prototype.useTail = function ( value ) {
-       value = !!value;
-       if ( this.tail !== value ) {
-               this.tail = value;
-               if ( value ) {
-                       this.$element.addClass( 'oo-ui-popupWidget-tailed' );
-               } else {
-                       this.$element.removeClass( 'oo-ui-popupWidget-tailed' );
-               }
+OO.ui.SelectWidget.prototype.getItemFromData = function ( data ) {
+       var hash = OO.getHash( data );
+
+       if ( hash in this.hashes ) {
+               return this.hashes[hash];
        }
+
+       return null;
 };
 
 /**
- * Check if showing a tail.
+ * Toggle pressed state.
  *
- * @return {boolean} tail is visible
+ * @param {boolean} pressed An option is being pressed
  */
-OO.ui.PopupWidget.prototype.hasTail = function () {
-       return this.tail;
+OO.ui.SelectWidget.prototype.togglePressed = function ( pressed ) {
+       if ( pressed === undefined ) {
+               pressed = !this.pressed;
+       }
+       if ( pressed !== this.pressed ) {
+               this.$element
+                       .toggleClass( 'oo-ui-selectWidget-pressed', pressed )
+                       .toggleClass( 'oo-ui-selectWidget-depressed', !pressed );
+               this.pressed = pressed;
+       }
 };
 
 /**
- * Show the context.
+ * Highlight an item.
+ *
+ * Highlighting is mutually exclusive.
  *
- * @fires show
+ * @param {OO.ui.OptionWidget} [item] Item to highlight, omit to deselect all
+ * @fires highlight
  * @chainable
  */
-OO.ui.PopupWidget.prototype.show = function () {
-       if ( !this.visible ) {
-               this.setClipping( true );
-               this.$element.show();
-               this.visible = true;
-               this.emit( 'show' );
-               if ( this.autoClose ) {
-                       this.bindMouseDownListener();
+OO.ui.SelectWidget.prototype.highlightItem = function ( item ) {
+       var i, len, highlighted,
+               changed = false;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               highlighted = this.items[i] === item;
+               if ( this.items[i].isHighlighted() !== highlighted ) {
+                       this.items[i].setHighlighted( highlighted );
+                       changed = true;
                }
        }
+       if ( changed ) {
+               this.emit( 'highlight', item );
+       }
+
        return this;
 };
 
 /**
- * Hide the context.
+ * Select an item.
  *
- * @fires hide
+ * @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all
+ * @fires select
  * @chainable
  */
-OO.ui.PopupWidget.prototype.hide = function () {
-       if ( this.visible ) {
-               this.setClipping( false );
-               this.$element.hide();
-               this.visible = false;
-               this.emit( 'hide' );
-               if ( this.autoClose ) {
-                       this.unbindMouseDownListener();
+OO.ui.SelectWidget.prototype.selectItem = function ( item ) {
+       var i, len, selected,
+               changed = false;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               selected = this.items[i] === item;
+               if ( this.items[i].isSelected() !== selected ) {
+                       this.items[i].setSelected( selected );
+                       changed = true;
                }
        }
+       if ( changed ) {
+               this.emit( 'select', item );
+       }
+
        return this;
 };
 
 /**
- * Updates the position and size.
+ * Press an item.
  *
- * @param {number} width Width
- * @param {number} height Height
- * @param {boolean} [transition=false] Use a smooth transition
+ * @param {OO.ui.OptionWidget} [item] Item to press, omit to depress all
+ * @fires press
  * @chainable
  */
-OO.ui.PopupWidget.prototype.display = function ( width, height, transition ) {
-       var padding = 10,
-               originOffset = Math.round( this.$element.offset().left ),
-               containerLeft = Math.round( this.$container.offset().left ),
-               containerWidth = this.$container.innerWidth(),
-               containerRight = containerLeft + containerWidth,
-               popupOffset = width * ( { 'left': 0, 'center': -0.5, 'right': -1 } )[this.align],
-               popupLeft = popupOffset - padding,
-               popupRight = popupOffset + padding + width + padding,
-               overlapLeft = ( originOffset + popupLeft ) - containerLeft,
-               overlapRight = containerRight - ( originOffset + popupRight );
-
-       // Prevent transition from being interrupted
-       clearTimeout( this.transitionTimeout );
-       if ( transition ) {
-               // Enable transition
-               this.$element.addClass( 'oo-ui-popupWidget-transitioning' );
-       }
+OO.ui.SelectWidget.prototype.pressItem = function ( item ) {
+       var i, len, pressed,
+               changed = false;
 
-       if ( overlapRight < 0 ) {
-               popupOffset += overlapRight;
-       } else if ( overlapLeft < 0 ) {
-               popupOffset -= overlapLeft;
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               pressed = this.items[i] === item;
+               if ( this.items[i].isPressed() !== pressed ) {
+                       this.items[i].setPressed( pressed );
+                       changed = true;
+               }
        }
-
-       // Position body relative to anchor and resize
-       this.$popup.css( {
-               'left': popupOffset,
-               'width': width,
-               'height': height === undefined ? 'auto' : height
-       } );
-
-       if ( transition ) {
-               // Prevent transitioning after transition is complete
-               this.transitionTimeout = setTimeout( OO.ui.bind( function () {
-                       this.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
-               }, this ), 200 );
-       } else {
-               // Prevent transitioning immediately
-               this.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
+       if ( changed ) {
+               this.emit( 'press', item );
        }
 
        return this;
 };
 
 /**
- * Button that shows and hides a popup.
+ * Choose an item.
  *
- * @class
- * @extends OO.ui.ButtonWidget
- * @mixins OO.ui.PopuppableElement
+ * Identical to #selectItem, but may vary in subclasses that want to take additional action when
+ * an item is selected using the keyboard or mouse.
  *
- * @constructor
- * @param {Object} [config] Configuration options
+ * @param {OO.ui.OptionWidget} item Item to choose
+ * @fires choose
+ * @chainable
  */
-OO.ui.PopupButtonWidget = function OoUiPopupButtonWidget( config ) {
-       // Parent constructor
-       OO.ui.PopupButtonWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.PopuppableElement.call( this, config );
+OO.ui.SelectWidget.prototype.chooseItem = function ( item ) {
+       this.selectItem( item );
+       this.emit( 'choose', item );
 
-       // Initialization
-       this.$element
-               .addClass( 'oo-ui-popupButtonWidget' )
-               .append( this.popup.$element );
+       return this;
 };
 
-/* Setup */
-
-OO.inheritClass( OO.ui.PopupButtonWidget, OO.ui.ButtonWidget );
-OO.mixinClass( OO.ui.PopupButtonWidget, OO.ui.PopuppableElement );
-
-/* Methods */
-
 /**
- * Handles mouse click events.
+ * Get an item relative to another one.
  *
- * @param {jQuery.Event} e Mouse click event
+ * @param {OO.ui.OptionWidget} item Item to start at
+ * @param {number} direction Direction to move in
+ * @return {OO.ui.OptionWidget|null} Item at position, `null` if there are no items in the menu
  */
-OO.ui.PopupButtonWidget.prototype.onClick = function ( e ) {
-       // Skip clicks within the popup
-       if ( $.contains( this.popup.$element[0], e.target ) ) {
-               return;
-       }
+OO.ui.SelectWidget.prototype.getRelativeSelectableItem = function ( item, direction ) {
+       var inc = direction > 0 ? 1 : -1,
+               len = this.items.length,
+               index = item instanceof OO.ui.OptionWidget ?
+                       $.inArray( item, this.items ) : ( inc > 0 ? -1 : 0 ),
+               stopAt = Math.max( Math.min( index, len - 1 ), 0 ),
+               i = inc > 0 ?
+                       // Default to 0 instead of -1, if nothing is selected let's start at the beginning
+                       Math.max( index, -1 ) :
+                       // Default to n-1 instead of -1, if nothing is selected let's start at the end
+                       Math.min( index, len );
 
-       if ( !this.isDisabled() ) {
-               if ( this.popup.isVisible() ) {
-                       this.hidePopup();
-               } else {
-                       this.showPopup();
+       while ( true ) {
+               i = ( i + inc + len ) % len;
+               item = this.items[i];
+               if ( item instanceof OO.ui.OptionWidget && item.isSelectable() ) {
+                       return item;
+               }
+               // Stop iterating when we've looped all the way around
+               if ( i === stopAt ) {
+                       break;
                }
-               OO.ui.PopupButtonWidget.super.prototype.onClick.call( this );
        }
-       return false;
+       return null;
 };
 
 /**
- * Search widget.
- *
- * Combines query and results selection widgets.
- *
- * @class
- * @extends OO.ui.Widget
+ * Get the next selectable item.
  *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string|jQuery} [placeholder] Placeholder text for query input
- * @cfg {string} [value] Initial query value
+ * @return {OO.ui.OptionWidget|null} Item, `null` if ther aren't any selectable items
  */
-OO.ui.SearchWidget = function OoUiSearchWidget( config ) {
-       // Configuration intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.SearchWidget.super.call( this, config );
-
-       // Properties
-       this.query = new OO.ui.TextInputWidget( {
-               '$': this.$,
-               'icon': 'search',
-               'placeholder': config.placeholder,
-               'value': config.value
-       } );
-       this.results = new OO.ui.SelectWidget( { '$': this.$ } );
-       this.$query = this.$( '<div>' );
-       this.$results = this.$( '<div>' );
+OO.ui.SelectWidget.prototype.getFirstSelectableItem = function () {
+       var i, len, item;
 
-       // Events
-       this.query.connect( this, {
-               'change': 'onQueryChange',
-               'enter': 'onQueryEnter'
-       } );
-       this.results.connect( this, {
-               'highlight': 'onResultsHighlight',
-               'select': 'onResultsSelect'
-       } );
-       this.query.$input.on( 'keydown', OO.ui.bind( this.onQueryKeydown, this ) );
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               item = this.items[i];
+               if ( item instanceof OO.ui.OptionWidget && item.isSelectable() ) {
+                       return item;
+               }
+       }
 
-       // Initialization
-       this.$query
-               .addClass( 'oo-ui-searchWidget-query' )
-               .append( this.query.$element );
-       this.$results
-               .addClass( 'oo-ui-searchWidget-results' )
-               .append( this.results.$element );
-       this.$element
-               .addClass( 'oo-ui-searchWidget' )
-               .append( this.$results, this.$query );
+       return null;
 };
 
-/* Setup */
-
-OO.inheritClass( OO.ui.SearchWidget, OO.ui.Widget );
-
-/* Events */
-
 /**
- * @event highlight
- * @param {Object|null} item Item data or null if no item is highlighted
+ * Add items.
+ *
+ * When items are added with the same values as existing items, the existing items will be
+ * automatically removed before the new items are added.
+ *
+ * @param {OO.ui.OptionWidget[]} items Items to add
+ * @param {number} [index] Index to insert items after
+ * @fires add
+ * @chainable
  */
+OO.ui.SelectWidget.prototype.addItems = function ( items, index ) {
+       var i, len, item, hash,
+               remove = [];
 
-/**
- * @event select
- * @param {Object|null} item Item data or null if no item is selected
- */
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+               hash = OO.getHash( item.getData() );
+               if ( hash in this.hashes ) {
+                       // Remove item with same value
+                       remove.push( this.hashes[hash] );
+               }
+               this.hashes[hash] = item;
+       }
+       if ( remove.length ) {
+               this.removeItems( remove );
+       }
+
+       // Mixin method
+       OO.ui.GroupWidget.prototype.addItems.call( this, items, index );
 
-/* Methods */
+       // Always provide an index, even if it was omitted
+       this.emit( 'add', items, index === undefined ? this.items.length - items.length - 1 : index );
+
+       return this;
+};
 
 /**
- * Handle query key down events.
+ * Remove items.
  *
- * @param {jQuery.Event} e Key down event
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @param {OO.ui.OptionWidget[]} items Items to remove
+ * @fires remove
+ * @chainable
  */
-OO.ui.SearchWidget.prototype.onQueryKeydown = function ( e ) {
-       var highlightedItem, nextItem,
-               dir = e.which === OO.ui.Keys.DOWN ? 1 : ( e.which === OO.ui.Keys.UP ? -1 : 0 );
+OO.ui.SelectWidget.prototype.removeItems = function ( items ) {
+       var i, len, item, hash;
 
-       if ( dir ) {
-               highlightedItem = this.results.getHighlightedItem();
-               if ( !highlightedItem ) {
-                       highlightedItem = this.results.getSelectedItem();
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+               hash = OO.getHash( item.getData() );
+               if ( hash in this.hashes ) {
+                       // Remove existing item
+                       delete this.hashes[hash];
+               }
+               if ( item.isSelected() ) {
+                       this.selectItem( null );
                }
-               nextItem = this.results.getRelativeSelectableItem( highlightedItem, dir );
-               this.results.highlightItem( nextItem );
-               nextItem.scrollElementIntoView();
        }
+
+       // Mixin method
+       OO.ui.GroupWidget.prototype.removeItems.call( this, items );
+
+       this.emit( 'remove', items );
+
+       return this;
 };
 
 /**
- * Handle select widget select events.
+ * Clear all items.
  *
- * Clears existing results. Subclasses should repopulate items according to new query.
+ * Items will be detached, not removed, so they can be used later.
  *
- * @param {string} value New value
+ * @fires remove
+ * @chainable
  */
-OO.ui.SearchWidget.prototype.onQueryChange = function () {
-       // Reset
-       this.results.clearItems();
+OO.ui.SelectWidget.prototype.clearItems = function () {
+       var items = this.items.slice();
+
+       // Clear all items
+       this.hashes = {};
+       // Mixin method
+       OO.ui.GroupWidget.prototype.clearItems.call( this );
+       this.selectItem( null );
+
+       this.emit( 'remove', items );
+
+       return this;
 };
 
 /**
- * Handle select widget enter key events.
+ * Select widget containing button options.
  *
- * Selects highlighted item.
+ * Use together with OO.ui.ButtonOptionWidget.
  *
- * @param {string} value New value
- */
-OO.ui.SearchWidget.prototype.onQueryEnter = function () {
-       // Reset
-       this.results.selectItem( this.results.getHighlightedItem() );
-};
-
-/**
- * Handle select widget highlight events.
+ * @class
+ * @extends OO.ui.SelectWidget
  *
- * @param {OO.ui.OptionWidget} item Highlighted item
- * @fires highlight
+ * @constructor
+ * @param {Object} [config] Configuration options
  */
-OO.ui.SearchWidget.prototype.onResultsHighlight = function ( item ) {
-       this.emit( 'highlight', item ? item.getData() : null );
-};
+OO.ui.ButtonSelectWidget = function OoUiButtonSelectWidget( config ) {
+       // Parent constructor
+       OO.ui.ButtonSelectWidget.super.call( this, config );
 
-/**
- * Handle select widget select events.
- *
- * @param {OO.ui.OptionWidget} item Selected item
- * @fires select
- */
-OO.ui.SearchWidget.prototype.onResultsSelect = function ( item ) {
-       this.emit( 'select', item ? item.getData() : null );
+       // Initialization
+       this.$element.addClass( 'oo-ui-buttonSelectWidget' );
 };
 
-/**
- * Get the query input.
- *
- * @return {OO.ui.TextInputWidget} Query input
- */
-OO.ui.SearchWidget.prototype.getQuery = function () {
-       return this.query;
-};
+/* Setup */
 
-/**
- * Get the results list.
- *
- * @return {OO.ui.SelectWidget} Select list
- */
-OO.ui.SearchWidget.prototype.getResults = function () {
-       return this.results;
-};
+OO.inheritClass( OO.ui.ButtonSelectWidget, OO.ui.SelectWidget );
 
 /**
- * Text input widget.
+ * Overlaid menu of options.
+ *
+ * Menus are clipped to the visible viewport. They do not provide a control for opening or closing
+ * the menu.
+ *
+ * Use together with OO.ui.MenuItemWidget.
  *
  * @class
- * @extends OO.ui.InputWidget
+ * @extends OO.ui.SelectWidget
+ * @mixins OO.ui.ClippableElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {string} [placeholder] Placeholder text
- * @cfg {string} [icon] Symbolic name of icon
- * @cfg {boolean} [multiline=false] Allow multiple lines of text
- * @cfg {boolean} [autosize=false] Automatically resize to fit content
- * @cfg {boolean} [maxRows=10] Maximum number of rows to make visible when autosizing
+ * @cfg {OO.ui.InputWidget} [input] Input to bind keyboard handlers to
+ * @cfg {OO.ui.Widget} [widget] Widget to bind mouse handlers to
+ * @cfg {boolean} [autoHide=true] Hide the menu when the mouse is pressed outside the menu
  */
-OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
-       config = $.extend( { 'maxRows': 10 }, config );
+OO.ui.MenuWidget = function OoUiMenuWidget( config ) {
+       // Config intialization
+       config = config || {};
 
        // Parent constructor
-       OO.ui.TextInputWidget.super.call( this, config );
+       OO.ui.MenuWidget.super.call( this, config );
 
-       // Properties
-       this.pending = 0;
-       this.multiline = !!config.multiline;
-       this.autosize = !!config.autosize;
-       this.maxRows = config.maxRows;
+       // Mixin constructors
+       OO.ui.ClippableElement.call( this, $.extend( {}, config, { $clippable: this.$group } ) );
 
-       // Events
-       this.$input.on( 'keypress', OO.ui.bind( this.onKeyPress, this ) );
-       this.$element.on( 'DOMNodeInsertedIntoDocument', OO.ui.bind( this.onElementAttach, this ) );
+       // Properties
+       this.flashing = false;
+       this.visible = false;
+       this.newItems = null;
+       this.autoHide = config.autoHide === undefined || !!config.autoHide;
+       this.$input = config.input ? config.input.$input : null;
+       this.$widget = config.widget ? config.widget.$element : null;
+       this.$previousFocus = null;
+       this.isolated = !config.input;
+       this.onKeyDownHandler = OO.ui.bind( this.onKeyDown, this );
+       this.onDocumentMouseDownHandler = OO.ui.bind( this.onDocumentMouseDown, this );
 
        // Initialization
-       this.$element.addClass( 'oo-ui-textInputWidget' );
-       if ( config.icon ) {
-               this.$element.addClass( 'oo-ui-textInputWidget-decorated' );
-               this.$element.append(
-                       this.$( '<span>' )
-                               .addClass( 'oo-ui-textInputWidget-icon oo-ui-icon-' + config.icon )
-                               .mousedown( OO.ui.bind( function () {
-                                       this.$input.focus();
-                                       return false;
-                               }, this ) )
-               );
-       }
-       if ( config.placeholder ) {
-               this.$input.attr( 'placeholder', config.placeholder );
-       }
+       this.$element
+               .hide()
+               .attr( 'role', 'menu' )
+               .addClass( 'oo-ui-menuWidget' );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.TextInputWidget, OO.ui.InputWidget );
-
-/* Events */
-
-/**
- * User presses enter inside the text box.
- *
- * Not called if input is multiline.
- *
- * @event enter
- */
+OO.inheritClass( OO.ui.MenuWidget, OO.ui.SelectWidget );
+OO.mixinClass( OO.ui.MenuWidget, OO.ui.ClippableElement );
 
 /* Methods */
 
 /**
- * Handle key press events.
+ * Handles document mouse down events.
  *
- * @param {jQuery.Event} e Key press event
- * @fires enter If enter key is pressed and input is not multiline
+ * @param {jQuery.Event} e Key down event
  */
-OO.ui.TextInputWidget.prototype.onKeyPress = function ( e ) {
-       if ( e.which === OO.ui.Keys.ENTER && !this.multiline ) {
-               this.emit( 'enter' );
+OO.ui.MenuWidget.prototype.onDocumentMouseDown = function ( e ) {
+       if ( !$.contains( this.$element[0], e.target ) && ( !this.$widget || !$.contains( this.$widget[0], e.target ) ) ) {
+               this.toggle( false );
        }
 };
 
 /**
- * Handle element attach events.
- *
- * @param {jQuery.Event} e Element attach event
- */
-OO.ui.TextInputWidget.prototype.onElementAttach = function () {
-       this.adjustSize();
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.TextInputWidget.prototype.onEdit = function () {
-       this.adjustSize();
-
-       // Parent method
-       return OO.ui.TextInputWidget.super.prototype.onEdit.call( this );
-};
-
-/**
- * Automatically adjust the size of the text input.
- *
- * This only affects multi-line inputs that are auto-sized.
+ * Handles key down events.
  *
- * @chainable
+ * @param {jQuery.Event} e Key down event
  */
-OO.ui.TextInputWidget.prototype.adjustSize = function () {
-       var $clone, scrollHeight, innerHeight, outerHeight, maxInnerHeight, idealHeight;
+OO.ui.MenuWidget.prototype.onKeyDown = function ( e ) {
+       var nextItem,
+               handled = false,
+               highlightItem = this.getHighlightedItem();
 
-       if ( this.multiline && this.autosize ) {
-               $clone = this.$input.clone()
-                       .val( this.$input.val() )
-                       .css( { 'height': 0 } )
-                       .insertAfter( this.$input );
-               // Set inline height property to 0 to measure scroll height
-               scrollHeight = $clone[0].scrollHeight;
-               // Remove inline height property to measure natural heights
-               $clone.css( 'height', '' );
-               innerHeight = $clone.innerHeight();
-               outerHeight = $clone.outerHeight();
-               // Measure max rows height
-               $clone.attr( 'rows', this.maxRows ).css( 'height', 'auto' );
-               maxInnerHeight = $clone.innerHeight();
-               $clone.removeAttr( 'rows' ).css( 'height', '' );
-               $clone.remove();
-               idealHeight = Math.min( maxInnerHeight, scrollHeight );
-               // Only apply inline height when expansion beyond natural height is needed
-               this.$input.css(
-                       'height',
-                       // Use the difference between the inner and outer height as a buffer
-                       idealHeight > outerHeight ? idealHeight + ( outerHeight - innerHeight ) : ''
-               );
+       if ( !this.isDisabled() && this.isVisible() ) {
+               if ( !highlightItem ) {
+                       highlightItem = this.getSelectedItem();
+               }
+               switch ( e.keyCode ) {
+                       case OO.ui.Keys.ENTER:
+                               this.chooseItem( highlightItem );
+                               handled = true;
+                               break;
+                       case OO.ui.Keys.UP:
+                               nextItem = this.getRelativeSelectableItem( highlightItem, -1 );
+                               handled = true;
+                               break;
+                       case OO.ui.Keys.DOWN:
+                               nextItem = this.getRelativeSelectableItem( highlightItem, 1 );
+                               handled = true;
+                               break;
+                       case OO.ui.Keys.ESCAPE:
+                               if ( highlightItem ) {
+                                       highlightItem.setHighlighted( false );
+                               }
+                               this.toggle( false );
+                               handled = true;
+                               break;
+               }
+
+               if ( nextItem ) {
+                       this.highlightItem( nextItem );
+                       nextItem.scrollElementIntoView();
+               }
+
+               if ( handled ) {
+                       e.preventDefault();
+                       e.stopPropagation();
+                       return false;
+               }
        }
-       return this;
 };
 
 /**
- * Get input element.
- *
- * @param {Object} [config] Configuration options
- * @return {jQuery} Input element
+ * Bind key down listener.
  */
-OO.ui.TextInputWidget.prototype.getInputElement = function ( config ) {
-       return config.multiline ? this.$( '<textarea>' ) : this.$( '<input type="text" />' );
+OO.ui.MenuWidget.prototype.bindKeyDownListener = function () {
+       if ( this.$input ) {
+               this.$input.on( 'keydown', this.onKeyDownHandler );
+       } else {
+               // Capture menu navigation keys
+               this.getElementWindow().addEventListener( 'keydown', this.onKeyDownHandler, true );
+       }
 };
 
-/* Methods */
-
 /**
- * Check if input supports multiple lines.
- *
- * @return {boolean}
+ * Unbind key down listener.
  */
-OO.ui.TextInputWidget.prototype.isMultiline = function () {
-       return !!this.multiline;
+OO.ui.MenuWidget.prototype.unbindKeyDownListener = function () {
+       if ( this.$input ) {
+               this.$input.off( 'keydown' );
+       } else {
+               this.getElementWindow().removeEventListener( 'keydown', this.onKeyDownHandler, true );
+       }
 };
 
 /**
- * Check if input automatically adjusts its size.
+ * Choose an item.
  *
- * @return {boolean}
+ * This will close the menu when done, unlike selectItem which only changes selection.
+ *
+ * @param {OO.ui.OptionWidget} item Item to choose
+ * @chainable
  */
-OO.ui.TextInputWidget.prototype.isAutosizing = function () {
-       return !!this.autosize;
+OO.ui.MenuWidget.prototype.chooseItem = function ( item ) {
+       var widget = this;
+
+       // Parent method
+       OO.ui.MenuWidget.super.prototype.chooseItem.call( this, item );
+
+       if ( item && !this.flashing ) {
+               this.flashing = true;
+               item.flash().done( function () {
+                       widget.toggle( false );
+                       widget.flashing = false;
+               } );
+       } else {
+               this.toggle( false );
+       }
+
+       return this;
 };
 
 /**
- * Check if input is pending.
- *
- * @return {boolean}
+ * @inheritdoc
  */
-OO.ui.TextInputWidget.prototype.isPending = function () {
-       return !!this.pending;
+OO.ui.MenuWidget.prototype.addItems = function ( items, index ) {
+       var i, len, item;
+
+       // Parent method
+       OO.ui.MenuWidget.super.prototype.addItems.call( this, items, index );
+
+       // Auto-initialize
+       if ( !this.newItems ) {
+               this.newItems = [];
+       }
+
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+               if ( this.isVisible() ) {
+                       // Defer fitting label until item has been attached
+                       item.fitLabel();
+               } else {
+                       this.newItems.push( item );
+               }
+       }
+
+       // Reevaluate clipping
+       this.clip();
+
+       return this;
 };
 
 /**
- * Increase the pending stack.
- *
- * @chainable
+ * @inheritdoc
  */
-OO.ui.TextInputWidget.prototype.pushPending = function () {
-       if ( this.pending === 0 ) {
-               this.$element.addClass( 'oo-ui-textInputWidget-pending' );
-               this.$input.addClass( 'oo-ui-texture-pending' );
-       }
-       this.pending++;
+OO.ui.MenuWidget.prototype.removeItems = function ( items ) {
+       // Parent method
+       OO.ui.MenuWidget.super.prototype.removeItems.call( this, items );
+
+       // Reevaluate clipping
+       this.clip();
 
        return this;
 };
 
 /**
- * Reduce the pending stack.
- *
- * Clamped at zero.
- *
- * @chainable
+ * @inheritdoc
  */
-OO.ui.TextInputWidget.prototype.popPending = function () {
-       if ( this.pending === 1 ) {
-               this.$element.removeClass( 'oo-ui-textInputWidget-pending' );
-               this.$input.removeClass( 'oo-ui-texture-pending' );
-       }
-       this.pending = Math.max( 0, this.pending - 1 );
+OO.ui.MenuWidget.prototype.clearItems = function () {
+       // Parent method
+       OO.ui.MenuWidget.super.prototype.clearItems.call( this );
+
+       // Reevaluate clipping
+       this.clip();
 
        return this;
 };
 
 /**
- * Select the contents of the input.
- *
- * @chainable
+ * @inheritdoc
  */
-OO.ui.TextInputWidget.prototype.select = function () {
-       this.$input.select();
+OO.ui.MenuWidget.prototype.toggle = function ( visible ) {
+       visible = ( visible === undefined ? !this.visible : !!visible ) && !!this.items.length;
+
+       var i, len,
+               change = visible !== this.isVisible();
+
+       // Parent method
+       OO.ui.MenuWidget.super.prototype.toggle.call( this, visible );
+
+       if ( change ) {
+               if ( visible ) {
+                       this.bindKeyDownListener();
+
+                       // Change focus to enable keyboard navigation
+                       if ( this.isolated && this.$input && !this.$input.is( ':focus' ) ) {
+                               this.$previousFocus = this.$( ':focus' );
+                               this.$input[0].focus();
+                       }
+                       if ( this.newItems && this.newItems.length ) {
+                               for ( i = 0, len = this.newItems.length; i < len; i++ ) {
+                                       this.newItems[i].fitLabel();
+                               }
+                               this.newItems = null;
+                       }
+                       this.toggleClipping( true );
+
+                       // Auto-hide
+                       if ( this.autoHide ) {
+                               this.getElementDocument().addEventListener(
+                                       'mousedown', this.onDocumentMouseDownHandler, true
+                               );
+                       }
+               } else {
+                       this.unbindKeyDownListener();
+                       if ( this.isolated && this.$previousFocus ) {
+                               this.$previousFocus[0].focus();
+                               this.$previousFocus = null;
+                       }
+                       this.getElementDocument().removeEventListener(
+                               'mousedown', this.onDocumentMouseDownHandler, true
+                       );
+                       this.toggleClipping( false );
+               }
+       }
+
        return this;
 };
 
 /**
  * Menu for a text input widget.
  *
+ * This menu is specially designed to be positioned beneath the text input widget. Even if the input
+ * is in a different frame, the menu's position is automatically calulated and maintained when the
+ * menu is toggled or the window is resized.
+ *
  * @class
  * @extends OO.ui.MenuWidget
  *
@@ -8437,29 +11084,24 @@ OO.ui.TextInputMenuWidget.prototype.onWindowResize = function () {
 };
 
 /**
- * Show the menu.
- *
- * @chainable
+ * @inheritdoc
  */
-OO.ui.TextInputMenuWidget.prototype.show = function () {
-       // Parent method
-       OO.ui.TextInputMenuWidget.super.prototype.show.call( this );
+OO.ui.TextInputMenuWidget.prototype.toggle = function ( visible ) {
+       visible = !!visible;
 
-       this.position();
-       this.$( this.getElementWindow() ).on( 'resize', this.onWindowResizeHandler );
-       return this;
-};
+       var change = visible !== this.isVisible();
 
-/**
- * Hide the menu.
- *
- * @chainable
- */
-OO.ui.TextInputMenuWidget.prototype.hide = function () {
        // Parent method
-       OO.ui.TextInputMenuWidget.super.prototype.hide.call( this );
+       OO.ui.TextInputMenuWidget.super.prototype.toggle.call( this, visible );
 
-       this.$( this.getElementWindow() ).off( 'resize', this.onWindowResizeHandler );
+       if ( change ) {
+               if ( this.isVisible() ) {
+                       this.position();
+                       this.$( this.getElementWindow() ).on( 'resize', this.onWindowResizeHandler );
+               } else {
+                       this.$( this.getElementWindow() ).off( 'resize', this.onWindowResizeHandler );
+               }
+       }
        return this;
 };
 
@@ -8477,9 +11119,9 @@ OO.ui.TextInputMenuWidget.prototype.position = function () {
        dimensions.top += $container.height();
 
        // Compensate for frame position if in a differnt frame
-       if ( this.input.$.frame && this.input.$.context !== this.$element[0].ownerDocument ) {
+       if ( this.input.$.$iframe && this.input.$.context !== this.$element[0].ownerDocument ) {
                frameOffset = OO.ui.Element.getRelativePosition(
-                       this.input.$.frame.$element, this.$element.offsetParent()
+                       this.input.$.$iframe, this.$element.offsetParent()
                );
                dimensions.left += frameOffset.left;
                dimensions.top += frameOffset.top;
@@ -8492,130 +11134,37 @@ OO.ui.TextInputMenuWidget.prototype.position = function () {
                        delete dimensions.left;
                }
        }
-
        this.$element.css( dimensions );
        this.setIdealSize( $container.width() );
-       return this;
-};
-
-/**
- * Width with on and off states.
- *
- * Mixin for widgets with a boolean state.
- *
- * @abstract
- * @class
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [value=false] Initial value
- */
-OO.ui.ToggleWidget = function OoUiToggleWidget( config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Properties
-       this.value = null;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-toggleWidget' );
-       this.setValue( !!config.value );
-};
-
-/* Events */
-
-/**
- * @event change
- * @param {boolean} value Changed value
- */
-
-/* Methods */
-
-/**
- * Get the value of the toggle.
- *
- * @return {boolean}
- */
-OO.ui.ToggleWidget.prototype.getValue = function () {
-       return this.value;
-};
 
-/**
- * Set the value of the toggle.
- *
- * @param {boolean} value New value
- * @fires change
- * @chainable
- */
-OO.ui.ToggleWidget.prototype.setValue = function ( value ) {
-       value = !!value;
-       if ( this.value !== value ) {
-               this.value = value;
-               this.emit( 'change', value );
-               this.$element.toggleClass( 'oo-ui-toggleWidget-on', value );
-               this.$element.toggleClass( 'oo-ui-toggleWidget-off', !value );
-       }
        return this;
 };
 
 /**
- * Button that toggles on and off.
+ * Structured list of items.
+ *
+ * Use with OO.ui.OutlineItemWidget.
  *
  * @class
- * @extends OO.ui.ButtonWidget
- * @mixins OO.ui.ToggleWidget
+ * @extends OO.ui.SelectWidget
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {boolean} [value=false] Initial value
  */
-OO.ui.ToggleButtonWidget = function OoUiToggleButtonWidget( config ) {
-       // Configuration initialization
+OO.ui.OutlineWidget = function OoUiOutlineWidget( config ) {
+       // Config intialization
        config = config || {};
 
        // Parent constructor
-       OO.ui.ToggleButtonWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.ToggleWidget.call( this, config );
+       OO.ui.OutlineWidget.super.call( this, config );
 
        // Initialization
-       this.$element.addClass( 'oo-ui-toggleButtonWidget' );
+       this.$element.addClass( 'oo-ui-outlineWidget' );
 };
 
 /* Setup */
 
-OO.inheritClass( OO.ui.ToggleButtonWidget, OO.ui.ButtonWidget );
-OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.ToggleWidget );
-
-/* Methods */
-
-/**
- * @inheritdoc
- */
-OO.ui.ToggleButtonWidget.prototype.onClick = function () {
-       if ( !this.isDisabled() ) {
-               this.setValue( !this.value );
-       }
-
-       // Parent method
-       return OO.ui.ToggleButtonWidget.super.prototype.onClick.call( this );
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.ToggleButtonWidget.prototype.setValue = function ( value ) {
-       value = !!value;
-       if ( value !== this.value ) {
-               this.setActive( value );
-       }
-
-       // Parent method (from mixin)
-       OO.ui.ToggleWidget.prototype.setValue.call( this, value );
-
-       return this;
-};
+OO.inheritClass( OO.ui.OutlineWidget, OO.ui.SelectWidget );
 
 /**
  * Switch that slides on and off.
diff --git a/resources/lib/oojs-ui/oojs-ui.rtl.css b/resources/lib/oojs-ui/oojs-ui.rtl.css
new file mode 100644 (file)
index 0000000..7f1fa34
--- /dev/null
@@ -0,0 +1,112 @@
+/*!
+ * OOjs UI v0.1.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2014 OOjs Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2014-09-11T19:39:50Z
+ */
+/*
+ * Blank theme mixins.
+ *
+ * Base styles invoke these mixins at the end of their definitions. Override these mixins to add
+ * additional rules to the base styles.
+ */
+.oo-ui-icon-add-item {
+  background-image: /* @embed */ url(images/icons/add-item.png);
+}
+.oo-ui-icon-advanced {
+  background-image: /* @embed */ url(images/icons/advanced.png);
+}
+.oo-ui-icon-alert {
+  background-image: /* @embed */ url(images/icons/alert.png);
+}
+.oo-ui-icon-check {
+  background-image: /* @embed */ url(images/icons/check.png);
+}
+.oo-ui-icon-clear {
+  background-image: /* @embed */ url(images/icons/clear.png);
+}
+.oo-ui-icon-close {
+  background-image: /* @embed */ url(images/icons/close.png);
+}
+.oo-ui-icon-code {
+  background-image: /* @embed */ url(images/icons/code.png);
+}
+.oo-ui-icon-collapse {
+  background-image: /* @embed */ url(images/icons/collapse.png);
+}
+.oo-ui-icon-comment {
+  background-image: /* @embed */ url(images/icons/comment.png);
+}
+.oo-ui-icon-expand {
+  background-image: /* @embed */ url(images/icons/expand.png);
+}
+.oo-ui-icon-help {
+  background-image: /* @embed */ url(images/icons/help.png);
+}
+.oo-ui-icon-info {
+  background-image: /* @embed */ url(images/icons/info.png);
+}
+.oo-ui-icon-link {
+  background-image: /* @embed */ url(images/icons/link.png);
+}
+.oo-ui-icon-menu {
+  background-image: /* @embed */ url(images/icons/menu.png);
+}
+.oo-ui-icon-next {
+  background-image: /* @embed */ url(images/icons/move-rtl.png);
+}
+.oo-ui-icon-picture {
+  background-image: /* @embed */ url(images/icons/picture.png);
+}
+.oo-ui-icon-previous {
+  background-image: /* @embed */ url(images/icons/move-ltr.png);
+}
+.oo-ui-icon-redo {
+  background-image: /* @embed */ url(images/icons/arched-arrow-rtl.png);
+}
+.oo-ui-icon-remove {
+  background-image: /* @embed */ url(images/icons/remove.png);
+}
+.oo-ui-icon-search {
+  background-image: /* @embed */ url(images/icons/search.png);
+}
+.oo-ui-icon-settings {
+  background-image: /* @embed */ url(images/icons/settings.png);
+}
+.oo-ui-icon-tag {
+  background-image: /* @embed */ url(images/icons/tag.png);
+}
+.oo-ui-icon-undo {
+  background-image: /* @embed */ url(images/icons/arched-arrow-ltr.png);
+}
+.oo-ui-icon-window {
+  background-image: /* @embed */ url(images/icons/window.png);
+}
+.oo-ui-indicator-alert {
+  background-image: /* @embed */ url(images/indicators/alert.png);
+}
+.oo-ui-indicator-down {
+  background-image: /* @embed */ url(images/indicators/arrow-down.png);
+}
+.oo-ui-indicator-next {
+  background-image: /* @embed */ url(images/indicators/arrow-rtl.png);
+}
+.oo-ui-indicator-previous {
+  background-image: /* @embed */ url(images/indicators/arrow-ltr.png);
+}
+.oo-ui-indicator-required {
+  background-image: /* @embed */ url(images/indicators/required.png);
+}
+.oo-ui-indicator-up {
+  background-image: /* @embed */ url(images/indicators/arrow-up.png);
+}
+.oo-ui-texture-pending {
+  background-image: /* @embed */ url(images/textures/pending.gif);
+}
+.oo-ui-texture-transparency {
+  background-image: /* @embed */ url(images/textures/transparency.png);
+}
index a249314..913d5fd 100644 (file)
 /*!
- * OOjs UI v0.1.0-pre (85cfc2e735)
+ * OOjs UI v0.1.0-pre (49b64bdba7)
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2014 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2014-07-03T02:33:09Z
+ * Date: 2014-09-15T22:18:37Z
+ */
+/*
+ * Blank theme mixins.
+ *
+ * Base styles invoke these mixins at the end of their definitions. Override these mixins to add
+ * additional rules to the base styles.
  */
-/* Textures */
-
-.oo-ui-texture-pending {
-  background-image: /* @embed */ url(images/textures/pending.gif);
-}
-
-.oo-ui-texture-transparency {
-  background-image: /* @embed */ url(images/textures/transparency.png);
-}
-
-/* RTL Definitions */
-
-/* @noflip */
-
-.oo-ui-rtl {
-  direction: rtl;
-}
-
-/* @noflip */
-
-.oo-ui-ltr {
-  direction: ltr;
-}
-
-.oo-ui-dialog {
-  position: fixed;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  padding: 1em;
-  line-height: 1em;
-  /* Fix for strange opacity-related rendering issues.
-          CAUTION: -webkit-backface-visibility: hidden; is EXTREMELY DANGEROUS.
-          If applied to a VE surface directly, it will break selection of
-          FocusableNodes, and in the past it's caused transparent PNGs to
-          render as opaque black images. For some reason applying it to the dialog
-          wrapper in the main document fixes opacity-related behavior in the iframe
-          document, but doesn't break the surface inside the iframe. */
-
-  -webkit-backface-visibility: hidden;
-          backface-visibility: hidden;
-}
-
-.oo-ui-dialog > .oo-ui-window-frame {
-  position: fixed;
-  right: 0;
-  left: 0;
-  min-height: 12em;
-  margin: auto;
-  overflow: hidden;
-}
-
-.oo-ui-dialog > .oo-ui-window-frame .oo-ui-frame {
-  width: 100%;
-  height: 100%;
-}
-
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed {
-  float: left;
-}
-
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-flaggableElement-primary,
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-flaggableElement-constructive,
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-flaggableElement-destructive {
-  float: right;
-}
-
-.oo-ui-dialog-content-footless .oo-ui-window-foot {
-  display: none;
-}
-
-.oo-ui-frame {
-  padding: 0;
-  margin: 0;
-}
-
-.oo-ui-frame-body {
-  padding: 0;
-  margin: 0;
-  background: none;
-}
-
-.oo-ui-frame-content:focus {
-  outline: none;
-}
-
-.oo-ui-toolbar {
-  clear: both;
-}
-
-.oo-ui-toolbar-bar {
-  line-height: 1em;
-}
-
-.oo-ui-toolbar-bottom .oo-ui-toolbar-bar {
-  position: absolute;
-}
-
-.oo-ui-toolbar-actions {
-  float: right;
-}
-
-.oo-ui-toolbar-tools {
-  float: left;
-}
-
-.oo-ui-toolbar-tools,
-.oo-ui-toolbar-actions,
-.oo-ui-toolbar-shadow {
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-toolbar-actions .oo-ui-popupWidget {
-  -webkit-user-select: all;
-     -moz-user-select: all;
-      -ms-user-select: all;
-          user-select: all;
-  -webkit-touch-callout: default;
-}
-
-.oo-ui-toolbar-shadow {
-  position: absolute;
-  width: 100%;
-  pointer-events: none;
-  background-position: left top;
-  background-repeat: repeat-x;
-}
-
-.oo-ui-toolGroup {
-  display: inline-block;
-  margin: 0.3em;
-  vertical-align: middle;
-}
-
-.oo-ui-toolGroup-empty {
-  display: none;
-}
-
-.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-window-head {
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-window-icon {
-  float: left;
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-window-title {
-  float: left;
-  white-space: nowrap;
-  cursor: default;
-}
-
-.oo-ui-window-overlay {
-  position: absolute;
-  top: 0;
-  left: 0;
-}
-
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button {
-  display: inline-block;
-  vertical-align: middle;
-  cursor: pointer;
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  display: none;
-  margin-left: 0;
-}
-
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator {
-  display: none;
-  margin-right: -0.75em;
-}
-
-.oo-ui-buttonedElement.oo-ui-widget-disabled .oo-ui-buttonedElement-button {
-  cursor: default;
-}
-
-.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
-.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  display: inline-block;
-  vertical-align: middle;
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-buttonedElement-frameless {
-  position: relative;
-  display: inline-block;
-}
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
-  display: inline-block;
-  margin-left: 0.25em;
-  vertical-align: middle;
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-  display: inline-block;
-  text-align: center;
-  vertical-align: top;
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
-  display: inline-block;
-  line-height: 1.9em;
-  vertical-align: middle;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
-  cursor: default;
-}
-
-.oo-ui-clippableElement-clippable {
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-bookletLayout-stackLayout.oo-ui-stackLayout-continuous .oo-ui-panelLayout-scrollable {
-  overflow-y: hidden;
-}
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
-  width: 100%;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-scrollable {
-  overflow-y: auto;
-}
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-padded {
-  padding: 2em;
-}
-
-.oo-ui-bookletLayout-outlinePanel-editable .oo-ui-outlineWidget {
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 3em;
-  left: 0;
-  overflow-y: auto;
-}
-
-.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
-  position: absolute;
-  right: 0;
-  bottom: 0;
-  left: 0;
-}
-
-.oo-ui-fieldLayout {
-  margin-bottom: 1em;
-}
-
-.oo-ui-fieldLayout:last-child {
-  margin-bottom: 0;
-}
-
-.oo-ui-fieldLayout:before,
-.oo-ui-fieldLayout:after {
-  display: table;
-  content: " ";
-}
-
-.oo-ui-fieldLayout:after {
-  clear: both;
-}
-
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labeledElement-label,
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labeledElement-label {
-  display: block;
-  float: left;
-  width: 35%;
-  padding-top: 0.5em;
-  margin-right: 5%;
-}
-
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field,
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field {
-  display: block;
-  float: left;
-  width: 60%;
-}
-
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labeledElement-label {
-  text-align: right;
-}
-
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labeledElement-label {
-  display: inline-block;
-  padding: 0.75em 0.5em 0.5em 0.5em;
-  vertical-align: middle;
-}
-
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field {
-  display: inline-block;
-  padding: 0.5em 0;
-  vertical-align: middle;
-}
-
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labeledElement-label {
-  padding: 0.5em 0;
-}
-
-.oo-ui-fieldsetLayout {
-  position: relative;
-  padding: 0;
-  margin: 0;
-}
-
-.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout {
-  margin-top: 2em;
-}
-
-.oo-ui-fieldsetLayout-labeled {
-  margin-top: -0.75em;
-}
-
-.oo-ui-fieldsetLayout > .oo-ui-labeledElement-label {
-  padding: 0.25em 0;
-  margin-bottom: 0.5em;
-}
-
-.oo-ui-fieldsetLayout.oo-ui-iconedElement > .oo-ui-labeledElement-label {
-  padding-left: 1.75em;
-  line-height: 1.33em;
-}
-
-.oo-ui-fieldsetLayout.oo-ui-iconedElement > .oo-ui-iconedElement-icon {
-  position: absolute;
-  top: 0.25em;
-  left: 0;
-  display: block;
-  width: 2em;
-  height: 2em;
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-gridLayout {
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-}
-
-.oo-ui-labelWidget {
-  padding: 0.5em 0;
-}
-
-.oo-ui-panelLayout-scrollable {
-  overflow-y: auto;
-}
-
-.oo-ui-stackLayout > .oo-ui-panelLayout {
-  display: none;
-}
-
-.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
-  position: relative;
-  display: block;
-}
-
-.oo-ui-barToolGroup > .oo-ui-iconedElement-icon,
-.oo-ui-barToolGroup > .oo-ui-labeledElement-label {
-  display: none;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool {
-  position: relative;
-  display: inline-block;
-  vertical-align: top;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-link {
-  display: block;
-  height: 1.5em;
-  padding: 0.25em;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  display: block;
-  width: 1.5em;
-  height: 1.5em;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-tool-title {
-  display: none;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
-  cursor: default;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-title,
-.oo-ui-barToolGroup .oo-ui-tool-accel {
-  display: none;
-}
-
-.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-link {
-  cursor: pointer;
-}
-
-.oo-ui-listToolGroup .oo-ui-toolGroup-tools {
-  padding: 0.25em;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool {
-  display: inline-block;
-  width: 100%;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool-link {
-  display: block;
-  padding-right: 0.5em;
-  white-space: nowrap;
-  cursor: pointer;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
-  cursor: default;
-}
-
-.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
-  min-width: 8em;
-}
-
-.oo-ui-menuToolGroup .oo-ui-toolGroup-tools {
-  padding: 0.25em 0 0.25em 0;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool {
-  display: block;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool-link {
-  display: block;
-  padding: 0 1em 0 0.25em;
-  white-space: nowrap;
-  cursor: pointer;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  background-image: none;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  background-image: /* @embed */ url(images/icons/check.png);
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
-  cursor: default;
-}
-
-.oo-ui-popupToolGroup {
-  position: relative;
-  height: 2em;
-  min-width: 2.5em;
-}
-
-.oo-ui-popupToolGroup.oo-ui-indicatedElement.oo-ui-iconedElement {
-  min-width: 3.5em;
-}
-
-.oo-ui-popupToolGroup-handle {
-  display: block;
-  cursor: pointer;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator,
-.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
-  position: absolute;
-  top: 0;
-  width: 2em;
-  height: 2em;
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator {
-  right: 0;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
-  left: 0.25em;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
-  margin: 0 1em;
-  font-size: 0.8em;
-  line-height: 2.6em;
-}
-
-.oo-ui-popupToolGroup-header {
-  margin: 0 0.6em;
-  font-size: 0.8em;
-  font-weight: bold;
-  line-height: 2.6em;
-}
-
-.oo-ui-popupToolGroup.oo-ui-widget-disabled .oo-ui-popupToolGroup-handle {
-  cursor: default;
-}
-
-.oo-ui-popupToolGroup.oo-ui-iconedElement .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
-  margin-left: 3em;
-}
-
-.oo-ui-popupToolGroup.oo-ui-indicatedElement .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
-  margin-right: 2.25em;
-}
-
-.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
-  position: absolute;
-  top: 2em;
-  left: -1px;
-  z-index: 4;
-  display: none;
-}
-
-.oo-ui-popupToolGroup .oo-ui-toolGroup-tools .oo-ui-iconedElement-icon {
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-popupToolGroup-active.oo-ui-widget-enabled > .oo-ui-toolGroup-tools {
-  display: block;
-}
-
-.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  display: inline-block;
-  width: 2em;
-  height: 2em;
-  margin-right: 0.25em;
-  vertical-align: middle;
-}
-
-.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
-  display: inline-block;
-  font-size: 0.8em;
-  line-height: 2em;
-  vertical-align: middle;
-}
-
-.oo-ui-popupToolGroup .oo-ui-tool-accel {
-  display: none;
-}
-
-.oo-ui-popupTool .oo-ui-popupWidget {
-  margin-left: 1.25em;
-  font-size: 0.8em;
-}
-
-.oo-ui-popupTool .oo-ui-popupWidget-popup,
-.oo-ui-popupTool .oo-ui-popupWidget-tail {
-  z-index: 4;
-}
-
-.oo-ui-iconWidget {
-  display: inline-block;
-  width: 1.9em;
-  height: 1.9em;
-  line-height: 2.5em;
-  vertical-align: middle;
-  background-position: center center;
-  background-repeat: no-repeat;
-  opacity: 0.8;
-}
-
-.oo-ui-iconWidget.oo-ui-widget-disabled {
-  opacity: 0.2;
-}
-
-.oo-ui-indicatorWidget {
-  display: inline-block;
-  width: 1.9em;
-  height: 1.9em;
-  line-height: 2.5em;
-  vertical-align: middle;
-  background-position: center center;
-  background-repeat: no-repeat;
-  opacity: 0.8;
-}
-
-.oo-ui-indicatorWidget.oo-ui-widget-disabled {
-  opacity: 0.2;
-}
-
-.oo-ui-selectWidget {
-  padding: 0;
-  margin: 0;
-  list-style: none;
-}
-
-.oo-ui-optionWidget {
-  position: relative;
-  display: block;
-  margin: 0;
-  list-style: none;
-  cursor: pointer;
-  border: none;
-}
-
-.oo-ui-optionWidget.oo-ui-widget-disabled {
-  cursor: default;
-}
-
-.oo-ui-optionWidget .oo-ui-labeledElement-label {
-  display: block;
-  overflow: hidden;
-  line-height: 1.5em;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.oo-ui-optionWidget .oo-ui-iconedElement-icon,
-.oo-ui-optionWidget .oo-ui-indicatedElement-indicator {
-  position: absolute;
-  top: 50%;
-  width: 2em;
-  height: 2em;
-  margin-top: -1em;
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-optionWidget .oo-ui-iconedElement-icon {
-  left: 0.5em;
-}
-
-.oo-ui-optionWidget .oo-ui-indicatedElement-indicator {
-  right: 0.5em;
-}
-
-.oo-ui-menuWidget {
-  position: absolute;
-}
-
-.oo-ui-menuWidget input {
-  position: absolute;
-  width: 0;
-  height: 0;
-  overflow: hidden;
-  opacity: 0;
-}
-
-.oo-ui-popupWidget-popup {
-  position: absolute;
-  overflow: hidden;
-}
-
-.oo-ui-popupWidget-tail {
-  display: none;
-}
-
-.oo-ui-popupWidget-tailed .oo-ui-popupWidget-popup {
-  margin-top: 7px;
-}
-
-.oo-ui-popupWidget-tailed .oo-ui-popupWidget-tail {
-  position: absolute;
-  display: block;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-popupWidget-head {
-  height: 2.5em;
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-popupWidget-head .oo-ui-buttonWidget {
-  float: right;
-  margin: 0.25em;
-}
-
-.oo-ui-popupWidget-head .oo-ui-labeledElement-label {
-  float: left;
-  margin: 0.75em 1em;
-  cursor: default;
-}
-
-.oo-ui-popupWidget-body {
-  clear: both;
-}
-
-.oo-ui-buttonGroupWidget {
-  border-radius: 0.3em;
-}
-
-.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-  margin-bottom: -1px;
-  margin-left: -1px;
-  border-radius: 0;
-}
-
-.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:first-child .oo-ui-buttonedElement-button {
-  margin-left: 0;
-  border-bottom-left-radius: 0.3em;
-  border-top-left-radius: 0.3em;
-}
-
-.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:last-child .oo-ui-buttonedElement-button {
-  border-top-right-radius: 0.3em;
-  border-bottom-right-radius: 0.3em;
-}
-
-.oo-ui-buttonOptionWidget {
-  display: inline-block;
-  background-color: transparent;
-}
-
-.oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
-  position: relative;
-  height: 1.9em;
-}
-
-.oo-ui-buttonOptionWidget.oo-ui-iconedElement .oo-ui-iconedElement-icon,
-.oo-ui-buttonOptionWidget.oo-ui-indicatedElement .oo-ui-indicatedElement-indicator {
-  position: static;
-  display: inline-block;
-  height: 1.9em;
-  margin-top: 0;
-  vertical-align: middle;
-}
-
-.oo-ui-buttonSelectWidget {
-  display: inline-block;
-  white-space: nowrap;
-}
-
-.oo-ui-buttonWidget {
-  display: inline-block;
-  vertical-align: middle;
-}
-
-.oo-ui-inlineMenuWidget {
-  position: relative;
-  display: inline-block;
-  min-width: 20em;
-  margin: 0.25em 0;
-}
-
-.oo-ui-inlineMenuWidget-handle {
-  display: inline-block;
-  width: 100%;
-  height: 2.5em;
-  cursor: pointer;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-inlineMenuWidget-handle .oo-ui-indicatedElement-indicator,
-.oo-ui-inlineMenuWidget-handle .oo-ui-iconedElement-icon {
-  position: absolute;
-  top: 0;
-  width: 2.5em;
-  height: 2.5em;
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-inlineMenuWidget-handle .oo-ui-indicatedElement-indicator {
-  right: 0;
-}
-
-.oo-ui-inlineMenuWidget-handle .oo-ui-iconedElement-icon {
-  left: 0.25em;
-}
-
-.oo-ui-inlineMenuWidget-handle .oo-ui-labeledElement-label {
-  margin: 0 0.5em;
-  line-height: 2.5em;
-}
-
-.oo-ui-inlineMenuWidget.oo-ui-iconedElement .oo-ui-inlineMenuWidget-handle .oo-ui-labeledElement-label {
-  margin-left: 3em;
-}
-
-.oo-ui-inlineMenuWidget.oo-ui-indicatedElement .oo-ui-inlineMenuWidget-handle .oo-ui-labeledElement-label {
-  margin-right: 2em;
-}
-
-.oo-ui-inlineMenuWidget .oo-ui-menuWidget {
-  z-index: 1;
-  width: 100%;
-}
-
-.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle {
-  cursor: default;
-}
-
-.oo-ui-menuItemWidget {
-  position: relative;
-}
-
-.oo-ui-menuItemWidget .oo-ui-iconedElement-icon {
-  display: none;
-}
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
-  background-color: transparent;
-}
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-selected .oo-ui-iconedElement-icon {
-  display: block;
-}
-
-.oo-ui-menuSectionItemWidget {
-  cursor: default;
-}
-
-.oo-ui-outlineControlsWidget {
-  height: 3em;
-}
-
-.oo-ui-outlineControlsWidget-items,
-.oo-ui-outlineControlsWidget-movers {
-  float: left;
-  height: 2em;
-  padding: 0;
-  margin: 0.5em;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-outlineControlsWidget > .oo-ui-iconedElement-icon {
-  float: left;
-  width: 1.5em;
-  height: 2em;
-  margin: 0.5em 0 0.5em 0.5em;
-  background-position: right center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-outlineControlsWidget-items {
-  float: left;
-  margin-left: 0;
-}
-
-.oo-ui-outlineControlsWidget-items .oo-ui-buttonWidget {
-  float: left;
-}
-
-.oo-ui-outlineControlsWidget-movers {
-  float: right;
-}
-
-.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
-  float: right;
-}
-
-.oo-ui-outlineItemWidget {
-  position: relative;
-  padding: 0.75em;
-  cursor: pointer;
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-popupButtonWidget {
-  position: relative;
-}
-
-.oo-ui-popupButtonWidget .oo-ui-popupWidget {
-  position: absolute;
-  left: 1em;
-  cursor: auto;
-}
-
-.oo-ui-searchWidget-query {
-  position: absolute;
-  top: 0;
-  right: 0;
-  left: 0;
-  height: 4em;
-  padding: 0 1em;
-}
-
-.oo-ui-searchWidget-query .oo-ui-textInputWidget {
-  width: 100%;
-  margin: 0.75em 0;
-}
-
-.oo-ui-searchWidget-results {
-  position: absolute;
-  top: 4em;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  padding: 1em;
-  overflow-x: hidden;
-  overflow-y: auto;
-  line-height: 0;
-}
-
-.oo-ui-textInputWidget {
-  position: relative;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-textInputWidget input,
-.oo-ui-textInputWidget textarea {
-  display: inline-block;
-  width: 100%;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-  resize: none;
-}
-
-.oo-ui-textInputWidget-icon {
-  position: absolute;
-  top: 0;
-  left: 0;
-  height: 100%;
-  background-position: right center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-toggleSwitchWidget {
-  position: relative;
-  display: inline-block;
-  width: 4em;
-  height: 2em;
-  overflow: hidden;
-  vertical-align: middle;
-  cursor: pointer;
-  -webkit-transform: translateZ(0);
-     -moz-transform: translateZ(0);
-      -ms-transform: translateZ(0);
-       -o-transform: translateZ(0);
-          transform: translateZ(0);
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
-  cursor: default;
-}
-
-.oo-ui-toggleSwitchWidget-grip {
-  position: absolute;
-  top: 0.25em;
-  left: 0.25em;
-  display: block;
-  width: 1.5em;
-  height: 1.5em;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-  -webkit-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-     -moz-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-      -ms-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-       -o-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-          transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-}
-
-.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  -webkit-transition: opacity 200ms ease-in-out;
-     -moz-transition: opacity 200ms ease-in-out;
-      -ms-transition: opacity 200ms ease-in-out;
-       -o-transition: opacity 200ms ease-in-out;
-          transition: opacity 200ms ease-in-out;
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
-  left: 2.25em;
-  margin-left: -2px;
-}
-
-.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
-  left: 0.25em;
-  margin-left: 0;
-}
-
-.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
-  display: none;
-}
-
-/* Icons */
-
 .oo-ui-icon-add-item {
   background-image: /* @embed */ url(images/icons/add-item.svg);
 }
-
 .oo-ui-icon-advanced {
   background-image: /* @embed */ url(images/icons/advanced.svg);
 }
-
 .oo-ui-icon-alert {
   background-image: /* @embed */ url(images/icons/alert.svg);
 }
-
 .oo-ui-icon-check {
   background-image: /* @embed */ url(images/icons/check.svg);
 }
-
 .oo-ui-icon-clear {
   background-image: /* @embed */ url(images/icons/clear.svg);
 }
-
 .oo-ui-icon-close {
   background-image: /* @embed */ url(images/icons/close.svg);
 }
-
 .oo-ui-icon-code {
   background-image: /* @embed */ url(images/icons/code.svg);
 }
-
 .oo-ui-icon-collapse {
   background-image: /* @embed */ url(images/icons/collapse.svg);
 }
-
 .oo-ui-icon-comment {
   background-image: /* @embed */ url(images/icons/comment.svg);
 }
-
 .oo-ui-icon-expand {
   background-image: /* @embed */ url(images/icons/expand.svg);
 }
-
 .oo-ui-icon-help {
   background-image: /* @embed */ url(images/icons/help.svg);
 }
-
 .oo-ui-icon-info {
   background-image: /* @embed */ url(images/icons/info.svg);
 }
-
 .oo-ui-icon-link {
   background-image: /* @embed */ url(images/icons/link.svg);
 }
-
 .oo-ui-icon-menu {
   background-image: /* @embed */ url(images/icons/menu.svg);
 }
-
 .oo-ui-icon-next {
   background-image: /* @embed */ url(images/icons/move-ltr.svg);
 }
-
 .oo-ui-icon-picture {
   background-image: /* @embed */ url(images/icons/picture.svg);
 }
-
 .oo-ui-icon-previous {
   background-image: /* @embed */ url(images/icons/move-rtl.svg);
 }
-
 .oo-ui-icon-redo {
   background-image: /* @embed */ url(images/icons/arched-arrow-ltr.svg);
 }
-
 .oo-ui-icon-remove {
   background-image: /* @embed */ url(images/icons/remove.svg);
 }
-
 .oo-ui-icon-search {
   background-image: /* @embed */ url(images/icons/search.svg);
 }
-
 .oo-ui-icon-settings {
   background-image: /* @embed */ url(images/icons/settings.svg);
 }
-
 .oo-ui-icon-tag {
   background-image: /* @embed */ url(images/icons/tag.svg);
 }
-
 .oo-ui-icon-undo {
   background-image: /* @embed */ url(images/icons/arched-arrow-rtl.svg);
 }
-
 .oo-ui-icon-window {
   background-image: /* @embed */ url(images/icons/window.svg);
 }
-
-/* Indicators */
-
 .oo-ui-indicator-alert {
   background-image: /* @embed */ url(images/indicators/alert.svg);
 }
-
 .oo-ui-indicator-down {
   background-image: /* @embed */ url(images/indicators/arrow-down.svg);
 }
-
 .oo-ui-indicator-next {
   background-image: /* @embed */ url(images/indicators/arrow-ltr.svg);
 }
-
 .oo-ui-indicator-previous {
   background-image: /* @embed */ url(images/indicators/arrow-rtl.svg);
 }
-
 .oo-ui-indicator-required {
   background-image: /* @embed */ url(images/indicators/required.svg);
 }
-
 .oo-ui-indicator-up {
   background-image: /* @embed */ url(images/indicators/arrow-up.svg);
-}
\ No newline at end of file
+}
+.oo-ui-texture-pending {
+  background-image: /* @embed */ url(images/textures/pending.gif);
+}
+.oo-ui-texture-transparency {
+  background-image: /* @embed */ url(images/textures/transparency.svg);
+}
diff --git a/resources/lib/oojs-ui/oojs-ui.svg.rtl.css b/resources/lib/oojs-ui/oojs-ui.svg.rtl.css
new file mode 100644 (file)
index 0000000..5a78d6b
--- /dev/null
@@ -0,0 +1,112 @@
+/*!
+ * OOjs UI v0.1.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2014 OOjs Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2014-09-11T19:39:50Z
+ */
+/*
+ * Blank theme mixins.
+ *
+ * Base styles invoke these mixins at the end of their definitions. Override these mixins to add
+ * additional rules to the base styles.
+ */
+.oo-ui-icon-add-item {
+  background-image: /* @embed */ url(images/icons/add-item.svg);
+}
+.oo-ui-icon-advanced {
+  background-image: /* @embed */ url(images/icons/advanced.svg);
+}
+.oo-ui-icon-alert {
+  background-image: /* @embed */ url(images/icons/alert.svg);
+}
+.oo-ui-icon-check {
+  background-image: /* @embed */ url(images/icons/check.svg);
+}
+.oo-ui-icon-clear {
+  background-image: /* @embed */ url(images/icons/clear.svg);
+}
+.oo-ui-icon-close {
+  background-image: /* @embed */ url(images/icons/close.svg);
+}
+.oo-ui-icon-code {
+  background-image: /* @embed */ url(images/icons/code.svg);
+}
+.oo-ui-icon-collapse {
+  background-image: /* @embed */ url(images/icons/collapse.svg);
+}
+.oo-ui-icon-comment {
+  background-image: /* @embed */ url(images/icons/comment.svg);
+}
+.oo-ui-icon-expand {
+  background-image: /* @embed */ url(images/icons/expand.svg);
+}
+.oo-ui-icon-help {
+  background-image: /* @embed */ url(images/icons/help.svg);
+}
+.oo-ui-icon-info {
+  background-image: /* @embed */ url(images/icons/info.svg);
+}
+.oo-ui-icon-link {
+  background-image: /* @embed */ url(images/icons/link.svg);
+}
+.oo-ui-icon-menu {
+  background-image: /* @embed */ url(images/icons/menu.svg);
+}
+.oo-ui-icon-next {
+  background-image: /* @embed */ url(images/icons/move-rtl.svg);
+}
+.oo-ui-icon-picture {
+  background-image: /* @embed */ url(images/icons/picture.svg);
+}
+.oo-ui-icon-previous {
+  background-image: /* @embed */ url(images/icons/move-ltr.svg);
+}
+.oo-ui-icon-redo {
+  background-image: /* @embed */ url(images/icons/arched-arrow-rtl.svg);
+}
+.oo-ui-icon-remove {
+  background-image: /* @embed */ url(images/icons/remove.svg);
+}
+.oo-ui-icon-search {
+  background-image: /* @embed */ url(images/icons/search.svg);
+}
+.oo-ui-icon-settings {
+  background-image: /* @embed */ url(images/icons/settings.svg);
+}
+.oo-ui-icon-tag {
+  background-image: /* @embed */ url(images/icons/tag.svg);
+}
+.oo-ui-icon-undo {
+  background-image: /* @embed */ url(images/icons/arched-arrow-ltr.svg);
+}
+.oo-ui-icon-window {
+  background-image: /* @embed */ url(images/icons/window.svg);
+}
+.oo-ui-indicator-alert {
+  background-image: /* @embed */ url(images/indicators/alert.svg);
+}
+.oo-ui-indicator-down {
+  background-image: /* @embed */ url(images/indicators/arrow-down.svg);
+}
+.oo-ui-indicator-next {
+  background-image: /* @embed */ url(images/indicators/arrow-rtl.svg);
+}
+.oo-ui-indicator-previous {
+  background-image: /* @embed */ url(images/indicators/arrow-ltr.svg);
+}
+.oo-ui-indicator-required {
+  background-image: /* @embed */ url(images/indicators/required.svg);
+}
+.oo-ui-indicator-up {
+  background-image: /* @embed */ url(images/indicators/arrow-up.svg);
+}
+.oo-ui-texture-pending {
+  background-image: /* @embed */ url(images/textures/pending.gif);
+}
+.oo-ui-texture-transparency {
+  background-image: /* @embed */ url(images/textures/transparency.svg);
+}
diff --git a/resources/lib/oojs-ui/themes/agora/images/icons/check.svg b/resources/lib/oojs-ui/themes/agora/images/icons/check.svg
deleted file mode 100644 (file)
index 6a91939..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->\r
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\r
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"\r
-        width="44.075px" height="44.076px" viewBox="0 0 44.075 44.076" enable-background="new 0 0 44.075 44.076" xml:space="preserve">\r
-<polygon fill="#FFFFFF" points="41.673,12.657 15.385,37.159 15.201,36.961 10.037,31.424 2.402,23.239 8.057,17.962 15.693,26.157 \r
-       36.319,6.917 "/>\r
-</svg>\r
diff --git a/resources/lib/oojs-ui/themes/minerva/images/icons/check.png b/resources/lib/oojs-ui/themes/minerva/images/icons/check.png
new file mode 100644 (file)
index 0000000..65026a0
Binary files /dev/null and b/resources/lib/oojs-ui/themes/minerva/images/icons/check.png differ
diff --git a/resources/lib/oojs-ui/themes/minerva/images/icons/check.svg b/resources/lib/oojs-ui/themes/minerva/images/icons/check.svg
new file mode 100644 (file)
index 0000000..6a91939
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\r
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"\r
+        width="44.075px" height="44.076px" viewBox="0 0 44.075 44.076" enable-background="new 0 0 44.075 44.076" xml:space="preserve">\r
+<polygon fill="#FFFFFF" points="41.673,12.657 15.385,37.159 15.201,36.961 10.037,31.424 2.402,23.239 8.057,17.962 15.693,26.157 \r
+       36.319,6.917 "/>\r
+</svg>\r
diff --git a/resources/lib/oojs/oojs.jquery.js b/resources/lib/oojs/oojs.jquery.js
new file mode 100644 (file)
index 0000000..c62df22
--- /dev/null
@@ -0,0 +1,879 @@
+/*!
+ * OOjs v1.1.1 optimised for jQuery
+ * https://www.mediawiki.org/wiki/OOjs
+ *
+ * Copyright 2011-2014 OOjs Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2014-09-11T00:40:09Z
+ */
+( function ( global ) {
+
+'use strict';
+
+/*exported toString */
+var
+       /**
+        * Namespace for all classes, static methods and static properties.
+        * @class OO
+        * @singleton
+        */
+       oo = {},
+       hasOwn = oo.hasOwnProperty,
+       toString = oo.toString;
+
+/* Class Methods */
+
+/**
+ * Utility to initialize a class for OO inheritance.
+ *
+ * Currently this just initializes an empty static object.
+ *
+ * @param {Function} fn
+ */
+oo.initClass = function ( fn ) {
+       fn.static = fn.static || {};
+};
+
+/**
+ * Inherit from prototype to another using Object#create.
+ *
+ * Beware: This redefines the prototype, call before setting your prototypes.
+ *
+ * Beware: This redefines the prototype, can only be called once on a function.
+ * If called multiple times on the same function, the previous prototype is lost.
+ * This is how prototypal inheritance works, it can only be one straight chain
+ * (just like classical inheritance in PHP for example). If you need to work with
+ * multiple constructors consider storing an instance of the other constructor in a
+ * property instead, or perhaps use a mixin (see OO.mixinClass).
+ *
+ *     function Thing() {}
+ *     Thing.prototype.exists = function () {};
+ *
+ *     function Person() {
+ *         Person.super.apply( this, arguments );
+ *     }
+ *     OO.inheritClass( Person, Thing );
+ *     Person.static.defaultEyeCount = 2;
+ *     Person.prototype.walk = function () {};
+ *
+ *     function Jumper() {
+ *         Jumper.super.apply( this, arguments );
+ *     }
+ *     OO.inheritClass( Jumper, Person );
+ *     Jumper.prototype.jump = function () {};
+ *
+ *     Jumper.static.defaultEyeCount === 2;
+ *     var x = new Jumper();
+ *     x.jump();
+ *     x.walk();
+ *     x instanceof Thing && x instanceof Person && x instanceof Jumper;
+ *
+ * @param {Function} targetFn
+ * @param {Function} originFn
+ * @throws {Error} If target already inherits from origin
+ */
+oo.inheritClass = function ( targetFn, originFn ) {
+       if ( targetFn.prototype instanceof originFn ) {
+               throw new Error( 'Target already inherits from origin' );
+       }
+
+       var targetConstructor = targetFn.prototype.constructor;
+
+       // Using ['super'] instead of .super because 'super' is not supported
+       // by IE 8 and below (bug 63303).
+       // Provide .parent as alias for code supporting older browsers which
+       // allows people to comply with their style guide.
+       targetFn['super'] = targetFn.parent = originFn;
+
+       targetFn.prototype = Object.create( originFn.prototype, {
+               // Restore constructor property of targetFn
+               constructor: {
+                       value: targetConstructor,
+                       enumerable: false,
+                       writable: true,
+                       configurable: true
+               }
+       } );
+
+       // Extend static properties - always initialize both sides
+       oo.initClass( originFn );
+       targetFn.static = Object.create( originFn.static );
+};
+
+/**
+ * Copy over *own* prototype properties of a mixin.
+ *
+ * The 'constructor' (whether implicit or explicit) is not copied over.
+ *
+ * This does not create inheritance to the origin. If inheritance is needed
+ * use oo.inheritClass instead.
+ *
+ * Beware: This can redefine a prototype property, call before setting your prototypes.
+ *
+ * Beware: Don't call before oo.inheritClass.
+ *
+ *     function Foo() {}
+ *     function Context() {}
+ *
+ *     // Avoid repeating this code
+ *     function ContextLazyLoad() {}
+ *     ContextLazyLoad.prototype.getContext = function () {
+ *         if ( !this.context ) {
+ *             this.context = new Context();
+ *         }
+ *         return this.context;
+ *     };
+ *
+ *     function FooBar() {}
+ *     OO.inheritClass( FooBar, Foo );
+ *     OO.mixinClass( FooBar, ContextLazyLoad );
+ *
+ * @param {Function} targetFn
+ * @param {Function} originFn
+ */
+oo.mixinClass = function ( targetFn, originFn ) {
+       var key;
+
+       // Copy prototype properties
+       for ( key in originFn.prototype ) {
+               if ( key !== 'constructor' && hasOwn.call( originFn.prototype, key ) ) {
+                       targetFn.prototype[key] = originFn.prototype[key];
+               }
+       }
+
+       // Copy static properties - always initialize both sides
+       oo.initClass( targetFn );
+       if ( originFn.static ) {
+               for ( key in originFn.static ) {
+                       if ( hasOwn.call( originFn.static, key ) ) {
+                               targetFn.static[key] = originFn.static[key];
+                       }
+               }
+       } else {
+               oo.initClass( originFn );
+       }
+};
+
+/* Object Methods */
+
+/**
+ * Create a new object that is an instance of the same
+ * constructor as the input, inherits from the same object
+ * and contains the same own properties.
+ *
+ * This makes a shallow non-recursive copy of own properties.
+ * To create a recursive copy of plain objects, use #copy.
+ *
+ *     var foo = new Person( mom, dad );
+ *     foo.setAge( 21 );
+ *     var foo2 = OO.cloneObject( foo );
+ *     foo.setAge( 22 );
+ *
+ *     // Then
+ *     foo2 !== foo; // true
+ *     foo2 instanceof Person; // true
+ *     foo2.getAge(); // 21
+ *     foo.getAge(); // 22
+ *
+ * @param {Object} origin
+ * @return {Object} Clone of origin
+ */
+oo.cloneObject = function ( origin ) {
+       var key, r;
+
+       r = Object.create( origin.constructor.prototype );
+
+       for ( key in origin ) {
+               if ( hasOwn.call( origin, key ) ) {
+                       r[key] = origin[key];
+               }
+       }
+
+       return r;
+};
+
+/**
+ * Get an array of all property values in an object.
+ *
+ * @param {Object} Object to get values from
+ * @return {Array} List of object values
+ */
+oo.getObjectValues = function ( obj ) {
+       var key, values;
+
+       if ( obj !== Object( obj ) ) {
+               throw new TypeError( 'Called on non-object' );
+       }
+
+       values = [];
+       for ( key in obj ) {
+               if ( hasOwn.call( obj, key ) ) {
+                       values[values.length] = obj[key];
+               }
+       }
+
+       return values;
+};
+
+/**
+ * Recursively compare properties between two objects.
+ *
+ * A false result may be caused by property inequality or by properties in one object missing from
+ * the other. An asymmetrical test may also be performed, which checks only that properties in the
+ * first object are present in the second object, but not the inverse.
+ *
+ * If either a or b is null or undefined it will be treated as an empty object.
+ *
+ * @param {Object|undefined|null} a First object to compare
+ * @param {Object|undefined|null} b Second object to compare
+ * @param {boolean} [asymmetrical] Whether to check only that b contains values from a
+ * @return {boolean} If the objects contain the same values as each other
+ */
+oo.compare = function ( a, b, asymmetrical ) {
+       var aValue, bValue, aType, bType, k;
+
+       if ( a === b ) {
+               return true;
+       }
+
+       a = a || {};
+       b = b || {};
+
+       for ( k in a ) {
+               if ( !hasOwn.call( a, k ) ) {
+                       // Support es3-shim: Without this filter, comparing [] to {} will be false in ES3
+                       // because the shimmed "forEach" is enumerable and shows up in Array but not Object.
+                       continue;
+               }
+
+               aValue = a[k];
+               bValue = b[k];
+               aType = typeof aValue;
+               bType = typeof bValue;
+               if ( aType !== bType ||
+                       (
+                               ( aType === 'string' || aType === 'number' || aType === 'boolean' ) &&
+                               aValue !== bValue
+                       ) ||
+                       ( aValue === Object( aValue ) && !oo.compare( aValue, bValue, asymmetrical ) ) ) {
+                       return false;
+               }
+       }
+       // If the check is not asymmetrical, recursing with the arguments swapped will verify our result
+       return asymmetrical ? true : oo.compare( b, a, true );
+};
+
+/**
+ * Create a plain deep copy of any kind of object.
+ *
+ * Copies are deep, and will either be an object or an array depending on `source`.
+ *
+ * @param {Object} source Object to copy
+ * @param {Function} [leafCallback] Applied to leaf values after they are cloned but before they are added to the clone
+ * @param {Function} [nodeCallback] Applied to all values before they are cloned.  If the nodeCallback returns a value other than undefined, the returned value is used instead of attempting to clone.
+ * @return {Object} Copy of source object
+ */
+oo.copy = function ( source, leafCallback, nodeCallback ) {
+       var key, destination;
+
+       if ( nodeCallback ) {
+               // Extensibility: check before attempting to clone source.
+               destination = nodeCallback( source );
+               if ( destination !== undefined ) {
+                       return destination;
+               }
+       }
+
+       if ( Array.isArray( source ) ) {
+               // Array (fall through)
+               destination = new Array( source.length );
+       } else if ( source && typeof source.clone === 'function' ) {
+               // Duck type object with custom clone method
+               return leafCallback ? leafCallback( source.clone() ) : source.clone();
+       } else if ( source && typeof source.cloneNode === 'function' ) {
+               // DOM Node
+               return leafCallback ?
+                       leafCallback( source.cloneNode( true ) ) :
+                       source.cloneNode( true );
+       } else if ( oo.isPlainObject( source ) ) {
+               // Plain objects (fall through)
+               destination = {};
+       } else {
+               // Non-plain objects (incl. functions) and primitive values
+               return leafCallback ? leafCallback( source ) : source;
+       }
+
+       // source is an array or a plain object
+       for ( key in source ) {
+               destination[key] = oo.copy( source[key], leafCallback, nodeCallback );
+       }
+
+       // This is an internal node, so we don't apply the leafCallback.
+       return destination;
+};
+
+/**
+ * Generate a hash of an object based on its name and data.
+ *
+ * Performance optimization: <http://jsperf.com/ve-gethash-201208#/toJson_fnReplacerIfAoForElse>
+ *
+ * To avoid two objects with the same values generating different hashes, we utilize the replacer
+ * argument of JSON.stringify and sort the object by key as it's being serialized. This may or may
+ * not be the fastest way to do this; we should investigate this further.
+ *
+ * Objects and arrays are hashed recursively. When hashing an object that has a .getHash()
+ * function, we call that function and use its return value rather than hashing the object
+ * ourselves. This allows classes to define custom hashing.
+ *
+ * @param {Object} val Object to generate hash for
+ * @return {string} Hash of object
+ */
+oo.getHash = function ( val ) {
+       return JSON.stringify( val, oo.getHash.keySortReplacer );
+};
+
+/**
+ * Sort objects by key (helper function for OO.getHash).
+ *
+ * This is a callback passed into JSON.stringify.
+ *
+ * @method getHash_keySortReplacer
+ * @param {string} key Property name of value being replaced
+ * @param {Mixed} val Property value to replace
+ * @return {Mixed} Replacement value
+ */
+oo.getHash.keySortReplacer = function ( key, val ) {
+       var normalized, keys, i, len;
+       if ( val && typeof val.getHashObject === 'function' ) {
+               // This object has its own custom hash function, use it
+               val = val.getHashObject();
+       }
+       if ( !Array.isArray( val ) && Object( val ) === val ) {
+               // Only normalize objects when the key-order is ambiguous
+               // (e.g. any object not an array).
+               normalized = {};
+               keys = Object.keys( val ).sort();
+               i = 0;
+               len = keys.length;
+               for ( ; i < len; i += 1 ) {
+                       normalized[keys[i]] = val[keys[i]];
+               }
+               return normalized;
+
+       // Primitive values and arrays get stable hashes
+       // by default. Lets those be stringified as-is.
+       } else {
+               return val;
+       }
+};
+
+/**
+ * Compute the union (duplicate-free merge) of a set of arrays.
+ *
+ * Arrays values must be convertable to object keys (strings).
+ *
+ * By building an object (with the values for keys) in parallel with
+ * the array, a new item's existence in the union can be computed faster.
+ *
+ * @param {Array...} arrays Arrays to union
+ * @return {Array} Union of the arrays
+ */
+oo.simpleArrayUnion = function () {
+       var i, ilen, arr, j, jlen,
+               obj = {},
+               result = [];
+
+       for ( i = 0, ilen = arguments.length; i < ilen; i++ ) {
+               arr = arguments[i];
+               for ( j = 0, jlen = arr.length; j < jlen; j++ ) {
+                       if ( !obj[ arr[j] ] ) {
+                               obj[ arr[j] ] = true;
+                               result.push( arr[j] );
+                       }
+               }
+       }
+
+       return result;
+};
+
+/**
+ * Combine arrays (intersection or difference).
+ *
+ * An intersection checks the item exists in 'b' while difference checks it doesn't.
+ *
+ * Arrays values must be convertable to object keys (strings).
+ *
+ * By building an object (with the values for keys) of 'b' we can
+ * compute the result faster.
+ *
+ * @private
+ * @param {Array} a First array
+ * @param {Array} b Second array
+ * @param {boolean} includeB Whether to items in 'b'
+ * @return {Array} Combination (intersection or difference) of arrays
+ */
+function simpleArrayCombine( a, b, includeB ) {
+       var i, ilen, isInB,
+               bObj = {},
+               result = [];
+
+       for ( i = 0, ilen = b.length; i < ilen; i++ ) {
+               bObj[ b[i] ] = true;
+       }
+
+       for ( i = 0, ilen = a.length; i < ilen; i++ ) {
+               isInB = !!bObj[ a[i] ];
+               if ( isInB === includeB ) {
+                       result.push( a[i] );
+               }
+       }
+
+       return result;
+}
+
+/**
+ * Compute the intersection of two arrays (items in both arrays).
+ *
+ * Arrays values must be convertable to object keys (strings).
+ *
+ * @param {Array} a First array
+ * @param {Array} b Second array
+ * @return {Array} Intersection of arrays
+ */
+oo.simpleArrayIntersection = function ( a, b ) {
+       return simpleArrayCombine( a, b, true );
+};
+
+/**
+ * Compute the difference of two arrays (items in 'a' but not 'b').
+ *
+ * Arrays values must be convertable to object keys (strings).
+ *
+ * @param {Array} a First array
+ * @param {Array} b Second array
+ * @return {Array} Intersection of arrays
+ */
+oo.simpleArrayDifference = function ( a, b ) {
+       return simpleArrayCombine( a, b, false );
+};
+
+/*global $ */
+
+oo.isPlainObject = $.isPlainObject;
+
+/*global hasOwn */
+
+( function () {
+
+       /**
+        * @class OO.EventEmitter
+        *
+        * @constructor
+        */
+       oo.EventEmitter = function OoEventEmitter() {
+               // Properties
+
+               /**
+                * Storage of bound event handlers by event name.
+                *
+                * @property
+                */
+               this.bindings = {};
+       };
+
+       oo.initClass( oo.EventEmitter );
+
+       /* Private helper functions */
+
+       /**
+        * Validate a function or method call in a context
+        *
+        * For a method name, check that it names a function in the context object
+        *
+        * @private
+        * @param {Function|string} method Function or method name
+        * @param {Mixed} context The context of the call
+        * @throws {Error} A method name is given but there is no context
+        * @throws {Error} In the context object, no property exists with the given name
+        * @throws {Error} In the context object, the named property is not a function
+        */
+       function validateMethod( method, context ) {
+               // Validate method and context
+               if ( typeof method === 'string' ) {
+                       // Validate method
+                       if ( context === undefined || context === null ) {
+                               throw new Error( 'Method name "' + method + '" has no context.' );
+                       }
+                       if ( !( method in context ) ) {
+                               // Technically the method does not need to exist yet: it could be
+                               // added before call time. But this probably signals a typo.
+                               throw new Error( 'Method not found: "' + method + '"' );
+                       }
+                       if ( typeof context[method] !== 'function' ) {
+                               // Technically the property could be replaced by a function before
+                               // call time. But this probably signals a typo.
+                               throw new Error( 'Property "' + method + '" is not a function' );
+                       }
+               } else if ( typeof method !== 'function' ) {
+                       throw new Error( 'Invalid callback. Function or method name expected.' );
+               }
+       }
+
+       /* Methods */
+
+       /**
+        * Add a listener to events of a specific event.
+        *
+        * The listener can be a function or the string name of a method; if the latter, then the
+        * name lookup happens at the time the listener is called.
+        *
+        * @param {string} event Type of event to listen to
+        * @param {Function|string} method Function or method name to call when event occurs
+        * @param {Array} [args] Arguments to pass to listener, will be prepended to emitted arguments
+        * @param {Object} [context=null] Context object for function or method call
+        * @throws {Error} Listener argument is not a function or a valid method name
+        * @chainable
+        */
+       oo.EventEmitter.prototype.on = function ( event, method, args, context ) {
+               var bindings;
+
+               validateMethod( method, context );
+
+               if ( hasOwn.call( this.bindings, event ) ) {
+                       bindings = this.bindings[event];
+               } else {
+                       // Auto-initialize bindings list
+                       bindings = this.bindings[event] = [];
+               }
+               // Add binding
+               bindings.push( {
+                       method: method,
+                       args: args,
+                       context: ( arguments.length < 4 ) ? null : context
+               } );
+               return this;
+       };
+
+       /**
+        * Add a one-time listener to a specific event.
+        *
+        * @param {string} event Type of event to listen to
+        * @param {Function} listener Listener to call when event occurs
+        * @chainable
+        */
+       oo.EventEmitter.prototype.once = function ( event, listener ) {
+               var eventEmitter = this,
+                       listenerWrapper = function () {
+                               eventEmitter.off( event, listenerWrapper );
+                               listener.apply( eventEmitter, Array.prototype.slice.call( arguments, 0 ) );
+                       };
+               return this.on( event, listenerWrapper );
+       };
+
+       /**
+        * Remove a specific listener from a specific event.
+        *
+        * @param {string} event Type of event to remove listener from
+        * @param {Function|string} [method] Listener to remove. Must be in the same form as was passed
+        * to "on". Omit to remove all listeners.
+        * @param {Object} [context=null] Context object function or method call
+        * @chainable
+        * @throws {Error} Listener argument is not a function or a valid method name
+        */
+       oo.EventEmitter.prototype.off = function ( event, method, context ) {
+               var i, bindings;
+
+               if ( arguments.length === 1 ) {
+                       // Remove all bindings for event
+                       delete this.bindings[event];
+                       return this;
+               }
+
+               validateMethod( method, context );
+
+               if ( !( event in this.bindings ) || !this.bindings[event].length ) {
+                       // No matching bindings
+                       return this;
+               }
+
+               // Default to null context
+               if ( arguments.length < 3 ) {
+                       context = null;
+               }
+
+               // Remove matching handlers
+               bindings = this.bindings[event];
+               i = bindings.length;
+               while ( i-- ) {
+                       if ( bindings[i].method === method && bindings[i].context === context ) {
+                               bindings.splice( i, 1 );
+                       }
+               }
+
+               // Cleanup if now empty
+               if ( bindings.length === 0 ) {
+                       delete this.bindings[event];
+               }
+               return this;
+       };
+
+       /**
+        * Emit an event.
+        *
+        * TODO: Should this be chainable? What is the usefulness of the boolean
+        * return value here?
+        *
+        * @param {string} event Type of event
+        * @param {Mixed} args First in a list of variadic arguments passed to event handler (optional)
+        * @return {boolean} If event was handled by at least one listener
+        */
+       oo.EventEmitter.prototype.emit = function ( event ) {
+               var i, len, binding, bindings, args, method;
+
+               if ( event in this.bindings ) {
+                       // Slicing ensures that we don't get tripped up by event handlers that add/remove bindings
+                       bindings = this.bindings[event].slice();
+                       args = Array.prototype.slice.call( arguments, 1 );
+                       for ( i = 0, len = bindings.length; i < len; i++ ) {
+                               binding = bindings[i];
+                               if ( typeof binding.method === 'string' ) {
+                                       // Lookup method by name (late binding)
+                                       method = binding.context[ binding.method ];
+                               } else {
+                                       method = binding.method;
+                               }
+                               method.apply(
+                                       binding.context,
+                                       binding.args ? binding.args.concat( args ) : args
+                               );
+                       }
+                       return true;
+               }
+               return false;
+       };
+
+       /**
+        * Connect event handlers to an object.
+        *
+        * @param {Object} context Object to call methods on when events occur
+        * @param {Object.<string,string>|Object.<string,Function>|Object.<string,Array>} methods List of
+        *  event bindings keyed by event name containing either method names, functions or arrays containing
+        *  method name or function followed by a list of arguments to be passed to callback before emitted
+        *  arguments
+        * @chainable
+        */
+       oo.EventEmitter.prototype.connect = function ( context, methods ) {
+               var method, args, event;
+
+               for ( event in methods ) {
+                       method = methods[event];
+                       // Allow providing additional args
+                       if ( Array.isArray( method ) ) {
+                               args = method.slice( 1 );
+                               method = method[0];
+                       } else {
+                               args = [];
+                       }
+                       // Add binding
+                       this.on( event, method, args, context );
+               }
+               return this;
+       };
+
+       /**
+        * Disconnect event handlers from an object.
+        *
+        * @param {Object} context Object to disconnect methods from
+        * @param {Object.<string,string>|Object.<string,Function>|Object.<string,Array>} [methods] List of
+        * event bindings keyed by event name. Values can be either method names or functions, but must be
+        * consistent with those used in the corresponding call to "connect".
+        * @chainable
+        */
+       oo.EventEmitter.prototype.disconnect = function ( context, methods ) {
+               var i, event, bindings;
+
+               if ( methods ) {
+                       // Remove specific connections to the context
+                       for ( event in methods ) {
+                               this.off( event, methods[event], context );
+                       }
+               } else {
+                       // Remove all connections to the context
+                       for ( event in this.bindings ) {
+                               bindings = this.bindings[event];
+                               i = bindings.length;
+                               while ( i-- ) {
+                                       // bindings[i] may have been removed by the previous step's
+                                       // this.off so check it still exists
+                                       if ( bindings[i] && bindings[i].context === context ) {
+                                               this.off( event, bindings[i].method, context );
+                                       }
+                               }
+                       }
+               }
+
+               return this;
+       };
+
+}() );
+
+/*global hasOwn */
+
+/**
+ * @class OO.Registry
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ */
+oo.Registry = function OoRegistry() {
+       // Mixin constructors
+       oo.EventEmitter.call( this );
+
+       // Properties
+       this.registry = {};
+};
+
+/* Inheritance */
+
+oo.mixinClass( oo.Registry, oo.EventEmitter );
+
+/* Events */
+
+/**
+ * @event register
+ * @param {string} name
+ * @param {Mixed} data
+ */
+
+/* Methods */
+
+/**
+ * Associate one or more symbolic names with some data.
+ *
+ * Only the base name will be registered, overriding any existing entry with the same base name.
+ *
+ * @param {string|string[]} name Symbolic name or list of symbolic names
+ * @param {Mixed} data Data to associate with symbolic name
+ * @fires register
+ * @throws {Error} Name argument must be a string or array
+ */
+oo.Registry.prototype.register = function ( name, data ) {
+       var i, len;
+       if ( typeof name === 'string' ) {
+               this.registry[name] = data;
+               this.emit( 'register', name, data );
+       } else if ( Array.isArray( name ) ) {
+               for ( i = 0, len = name.length; i < len; i++ ) {
+                       this.register( name[i], data );
+               }
+       } else {
+               throw new Error( 'Name must be a string or array, cannot be a ' + typeof name );
+       }
+};
+
+/**
+ * Get data for a given symbolic name.
+ *
+ * Lookups are done using the base name.
+ *
+ * @param {string} name Symbolic name
+ * @return {Mixed|undefined} Data associated with symbolic name
+ */
+oo.Registry.prototype.lookup = function ( name ) {
+       if ( hasOwn.call( this.registry, name ) ) {
+               return this.registry[name];
+       }
+};
+
+/**
+ * @class OO.Factory
+ * @extends OO.Registry
+ *
+ * @constructor
+ */
+oo.Factory = function OoFactory() {
+       oo.Factory.parent.call( this );
+
+       // Properties
+       this.entries = [];
+};
+
+/* Inheritance */
+
+oo.inheritClass( oo.Factory, oo.Registry );
+
+/* Methods */
+
+/**
+ * Register a constructor with the factory.
+ *
+ * Classes must have a static `name` property to be registered.
+ *
+ *     function MyClass() {};
+ *     OO.initClass( MyClass );
+ *     // Adds a static property to the class defining a symbolic name
+ *     MyClass.static.name = 'mine';
+ *     // Registers class with factory, available via symbolic name 'mine'
+ *     factory.register( MyClass );
+ *
+ * @param {Function} constructor Constructor to use when creating object
+ * @throws {Error} Name must be a string and must not be empty
+ * @throws {Error} Constructor must be a function
+ */
+oo.Factory.prototype.register = function ( constructor ) {
+       var name;
+
+       if ( typeof constructor !== 'function' ) {
+               throw new Error( 'constructor must be a function, cannot be a ' + typeof constructor );
+       }
+       name = constructor.static && constructor.static.name;
+       if ( typeof name !== 'string' || name === '' ) {
+               throw new Error( 'Name must be a string and must not be empty' );
+       }
+       this.entries.push( name );
+
+       oo.Factory.parent.prototype.register.call( this, name, constructor );
+};
+
+/**
+ * Create an object based on a name.
+ *
+ * Name is used to look up the constructor to use, while all additional arguments are passed to the
+ * constructor directly, so leaving one out will pass an undefined to the constructor.
+ *
+ * @param {string} name Object name
+ * @param {Mixed...} [args] Arguments to pass to the constructor
+ * @return {Object} The new object
+ * @throws {Error} Unknown object name
+ */
+oo.Factory.prototype.create = function ( name ) {
+       var args, obj,
+               constructor = this.lookup( name );
+
+       if ( !constructor ) {
+               throw new Error( 'No class registered by that name: ' + name );
+       }
+
+       // Convert arguments to array and shift the first argument (name) off
+       args = Array.prototype.slice.call( arguments, 1 );
+
+       // We can't use the "new" operator with .apply directly because apply needs a
+       // context. So instead just do what "new" does: create an object that inherits from
+       // the constructor's prototype (which also makes it an "instanceof" the constructor),
+       // then invoke the constructor with the object as context, and return it (ignoring
+       // the constructor's return value).
+       obj = Object.create( constructor.prototype );
+       constructor.apply( obj, args );
+       return obj;
+};
+
+/*jshint node:true */
+if ( typeof module !== 'undefined' && module.exports ) {
+       module.exports = oo;
+} else {
+       global.OO = oo;
+}
+
+}( this ) );
diff --git a/resources/lib/oojs/oojs.js b/resources/lib/oojs/oojs.js
deleted file mode 100644 (file)
index 8ccd50a..0000000
+++ /dev/null
@@ -1,862 +0,0 @@
-/*!
- * OOjs v1.0.10
- * https://www.mediawiki.org/wiki/OOjs
- *
- * Copyright 2011-2014 OOjs Team and other contributors.
- * Released under the MIT license
- * http://oojs.mit-license.org
- *
- * Date: Wed Jun 18 2014 20:03:40 GMT-0700 (PDT)
- */
-( function ( global ) {
-
-'use strict';
-/*exported toString */
-var
-       /**
-        * Namespace for all classes, static methods and static properties.
-        * @class OO
-        * @singleton
-        */
-       oo = {},
-       hasOwn = oo.hasOwnProperty,
-       toString = oo.toString;
-
-/* Class Methods */
-
-/**
- * Utility to initialize a class for OO inheritance.
- *
- * Currently this just initializes an empty static object.
- *
- * @param {Function} fn
- */
-oo.initClass = function ( fn ) {
-       fn.static = fn.static || {};
-};
-
-/**
- * Utility for common usage of Object#create for inheriting from one
- * prototype to another.
- *
- * Beware: This redefines the prototype, call before setting your prototypes.
- * Beware: This redefines the prototype, can only be called once on a function.
- *  If called multiple times on the same function, the previous prototype is lost.
- *  This is how prototypal inheritance works, it can only be one straight chain
- *  (just like classical inheritance in PHP for example). If you need to work with
- *  multiple constructors consider storing an instance of the other constructor in a
- *  property instead, or perhaps use a mixin (see OO.mixinClass).
- *
- *     function Thing() {}
- *     Thing.prototype.exists = function () {};
- *
- *     function Person() {
- *         Person.super.apply( this, arguments );
- *     }
- *     OO.inheritClass( Person, Thing );
- *     Person.static.defaultEyeCount = 2;
- *     Person.prototype.walk = function () {};
- *
- *     function Jumper() {
- *         Jumper.super.apply( this, arguments );
- *     }
- *     OO.inheritClass( Jumper, Person );
- *     Jumper.prototype.jump = function () {};
- *
- *     Jumper.static.defaultEyeCount === 2;
- *     var x = new Jumper();
- *     x.jump();
- *     x.walk();
- *     x instanceof Thing && x instanceof Person && x instanceof Jumper;
- *
- * @param {Function} targetFn
- * @param {Function} originFn
- * @throws {Error} If target already inherits from origin
- */
-oo.inheritClass = function ( targetFn, originFn ) {
-       if ( targetFn.prototype instanceof originFn ) {
-               throw new Error( 'Target already inherits from origin' );
-       }
-
-       var targetConstructor = targetFn.prototype.constructor;
-
-       // Using ['super'] instead of .super because 'super' is not supported
-       // by IE 8 and below (bug 63303).
-       // Provide .parent as alias for code supporting older browsers which
-       // allows people to comply with their style guide.
-       targetFn['super'] = targetFn.parent = originFn;
-
-       targetFn.prototype = Object.create( originFn.prototype, {
-               // Restore constructor property of targetFn
-               constructor: {
-                       value: targetConstructor,
-                       enumerable: false,
-                       writable: true,
-                       configurable: true
-               }
-       } );
-
-       // Extend static properties - always initialize both sides
-       oo.initClass( originFn );
-       targetFn.static = Object.create( originFn.static );
-};
-
-/**
- * Utility to copy over *own* prototype properties of a mixin.
- * The 'constructor' (whether implicit or explicit) is not copied over.
- *
- * This does not create inheritance to the origin. If inheritance is needed
- * use oo.inheritClass instead.
- *
- * Beware: This can redefine a prototype property, call before setting your prototypes.
- * Beware: Don't call before oo.inheritClass.
- *
- *     function Foo() {}
- *     function Context() {}
- *
- *     // Avoid repeating this code
- *     function ContextLazyLoad() {}
- *     ContextLazyLoad.prototype.getContext = function () {
- *         if ( !this.context ) {
- *             this.context = new Context();
- *         }
- *         return this.context;
- *     };
- *
- *     function FooBar() {}
- *     OO.inheritClass( FooBar, Foo );
- *     OO.mixinClass( FooBar, ContextLazyLoad );
- *
- * @param {Function} targetFn
- * @param {Function} originFn
- */
-oo.mixinClass = function ( targetFn, originFn ) {
-       var key;
-
-       // Copy prototype properties
-       for ( key in originFn.prototype ) {
-               if ( key !== 'constructor' && hasOwn.call( originFn.prototype, key ) ) {
-                       targetFn.prototype[key] = originFn.prototype[key];
-               }
-       }
-
-       // Copy static properties - always initialize both sides
-       oo.initClass( targetFn );
-       if ( originFn.static ) {
-               for ( key in originFn.static ) {
-                       if ( hasOwn.call( originFn.static, key ) ) {
-                               targetFn.static[key] = originFn.static[key];
-                       }
-               }
-       } else {
-               oo.initClass( originFn );
-       }
-};
-
-/* Object Methods */
-
-/**
- * Create a new object that is an instance of the same
- * constructor as the input, inherits from the same object
- * and contains the same own properties.
- *
- * This makes a shallow non-recursive copy of own properties.
- * To create a recursive copy of plain objects, use #copy.
- *
- *     var foo = new Person( mom, dad );
- *     foo.setAge( 21 );
- *     var foo2 = OO.cloneObject( foo );
- *     foo.setAge( 22 );
- *
- *     // Then
- *     foo2 !== foo; // true
- *     foo2 instanceof Person; // true
- *     foo2.getAge(); // 21
- *     foo.getAge(); // 22
- *
- * @param {Object} origin
- * @return {Object} Clone of origin
- */
-oo.cloneObject = function ( origin ) {
-       var key, r;
-
-       r = Object.create( origin.constructor.prototype );
-
-       for ( key in origin ) {
-               if ( hasOwn.call( origin, key ) ) {
-                       r[key] = origin[key];
-               }
-       }
-
-       return r;
-};
-
-/**
- * Get an array of all property values in an object.
- *
- * @param {Object} Object to get values from
- * @return {Array} List of object values
- */
-oo.getObjectValues = function ( obj ) {
-       var key, values;
-
-       if ( obj !== Object( obj ) ) {
-               throw new TypeError( 'Called on non-object' );
-       }
-
-       values = [];
-       for ( key in obj ) {
-               if ( hasOwn.call( obj, key ) ) {
-                       values[values.length] = obj[key];
-               }
-       }
-
-       return values;
-};
-
-/**
- * Recursively compares properties between two objects.
- *
- * A false result may be caused by property inequality or by properties in one object missing from
- * the other. An asymmetrical test may also be performed, which checks only that properties in the
- * first object are present in the second object, but not the inverse.
- *
- * @param {Object} a First object to compare
- * @param {Object} b Second object to compare
- * @param {boolean} [asymmetrical] Whether to check only that b contains values from a
- * @return {boolean} If the objects contain the same values as each other
- */
-oo.compare = function ( a, b, asymmetrical ) {
-       var aValue, bValue, aType, bType, k;
-
-       if ( a === b ) {
-               return true;
-       }
-
-       for ( k in a ) {
-               if ( !hasOwn.call( a, k ) ) {
-                       // Support es3-shim: Without this filter, comparing [] to {} will be false in ES3
-                       // because the shimmed "forEach" is enumerable and shows up in Array but not Object.
-                       continue;
-               }
-
-               aValue = a[k];
-               bValue = b[k];
-               aType = typeof aValue;
-               bType = typeof bValue;
-               if ( aType !== bType ||
-                       ( ( aType === 'string' || aType === 'number' ) && aValue !== bValue ) ||
-                       ( aValue === Object( aValue ) && !oo.compare( aValue, bValue, asymmetrical ) ) ) {
-                       return false;
-               }
-       }
-       // If the check is not asymmetrical, recursing with the arguments swapped will verify our result
-       return asymmetrical ? true : oo.compare( b, a, true );
-};
-
-/**
- * Create a plain deep copy of any kind of object.
- *
- * Copies are deep, and will either be an object or an array depending on `source`.
- *
- * @param {Object} source Object to copy
- * @param {Function} [callback] Applied to leaf values before they added to the clone
- * @return {Object} Copy of source object
- */
-oo.copy = function ( source, callback ) {
-       var key, sourceValue, sourceType, destination;
-
-       if ( typeof source.clone === 'function' ) {
-               return source.clone();
-       }
-
-       destination = Array.isArray( source ) ? new Array( source.length ) : {};
-
-       for ( key in source ) {
-               sourceValue = source[key];
-               sourceType = typeof sourceValue;
-               if ( Array.isArray( sourceValue ) ) {
-                       // Array
-                       destination[key] = oo.copy( sourceValue, callback );
-               } else if ( sourceValue && typeof sourceValue.clone === 'function' ) {
-                       // Duck type object with custom clone method
-                       destination[key] = callback ?
-                               callback( sourceValue.clone() ) : sourceValue.clone();
-               } else if ( sourceValue && typeof sourceValue.cloneNode === 'function' ) {
-                       // DOM Node
-                       destination[key] = callback ?
-                               callback( sourceValue.cloneNode( true ) ) : sourceValue.cloneNode( true );
-               } else if ( oo.isPlainObject( sourceValue ) ) {
-                       // Plain objects
-                       destination[key] = oo.copy( sourceValue, callback );
-               } else {
-                       // Non-plain objects (incl. functions) and primitive values
-                       destination[key] = callback ? callback( sourceValue ) : sourceValue;
-               }
-       }
-
-       return destination;
-};
-
-/**
- * Generate a hash of an object based on its name and data.
- *
- * Performance optimization: <http://jsperf.com/ve-gethash-201208#/toJson_fnReplacerIfAoForElse>
- *
- * To avoid two objects with the same values generating different hashes, we utilize the replacer
- * argument of JSON.stringify and sort the object by key as it's being serialized. This may or may
- * not be the fastest way to do this; we should investigate this further.
- *
- * Objects and arrays are hashed recursively. When hashing an object that has a .getHash()
- * function, we call that function and use its return value rather than hashing the object
- * ourselves. This allows classes to define custom hashing.
- *
- * @param {Object} val Object to generate hash for
- * @return {string} Hash of object
- */
-oo.getHash = function ( val ) {
-       return JSON.stringify( val, oo.getHash.keySortReplacer );
-};
-
-/**
- * Helper function for OO.getHash which sorts objects by key.
- *
- * This is a callback passed into JSON.stringify.
- *
- * @method getHash_keySortReplacer
- * @param {string} key Property name of value being replaced
- * @param {Mixed} val Property value to replace
- * @return {Mixed} Replacement value
- */
-oo.getHash.keySortReplacer = function ( key, val ) {
-       var normalized, keys, i, len;
-       if ( val && typeof val.getHashObject === 'function' ) {
-               // This object has its own custom hash function, use it
-               val = val.getHashObject();
-       }
-       if ( !Array.isArray( val ) && Object( val ) === val ) {
-               // Only normalize objects when the key-order is ambiguous
-               // (e.g. any object not an array).
-               normalized = {};
-               keys = Object.keys( val ).sort();
-               i = 0;
-               len = keys.length;
-               for ( ; i < len; i += 1 ) {
-                       normalized[keys[i]] = val[keys[i]];
-               }
-               return normalized;
-
-       // Primitive values and arrays get stable hashes
-       // by default. Lets those be stringified as-is.
-       } else {
-               return val;
-       }
-};
-
-/**
- * Compute the union (duplicate-free merge) of a set of arrays.
- *
- * Arrays values must be convertable to object keys (strings).
- *
- * By building an object (with the values for keys) in parallel with
- * the array, a new item's existence in the union can be computed faster.
- *
- * @param {Array...} arrays Arrays to union
- * @return {Array} Union of the arrays
- */
-oo.simpleArrayUnion = function () {
-       var i, ilen, arr, j, jlen,
-               obj = {},
-               result = [];
-
-       for ( i = 0, ilen = arguments.length; i < ilen; i++ ) {
-               arr = arguments[i];
-               for ( j = 0, jlen = arr.length; j < jlen; j++ ) {
-                       if ( !obj[ arr[j] ] ) {
-                               obj[ arr[j] ] = true;
-                               result.push( arr[j] );
-                       }
-               }
-       }
-
-       return result;
-};
-
-/**
- * Combine arrays (intersection or difference).
- *
- * An intersection checks the item exists in 'b' while difference checks it doesn't.
- *
- * Arrays values must be convertable to object keys (strings).
- *
- * By building an object (with the values for keys) of 'b' we can
- * compute the result faster.
- *
- * @private
- * @param {Array} a First array
- * @param {Array} b Second array
- * @param {boolean} includeB Whether to items in 'b'
- * @return {Array} Combination (intersection or difference) of arrays
- */
-function simpleArrayCombine( a, b, includeB ) {
-       var i, ilen, isInB,
-               bObj = {},
-               result = [];
-
-       for ( i = 0, ilen = b.length; i < ilen; i++ ) {
-               bObj[ b[i] ] = true;
-       }
-
-       for ( i = 0, ilen = a.length; i < ilen; i++ ) {
-               isInB = !!bObj[ a[i] ];
-               if ( isInB === includeB ) {
-                       result.push( a[i] );
-               }
-       }
-
-       return result;
-}
-
-/**
- * Compute the intersection of two arrays (items in both arrays).
- *
- * Arrays values must be convertable to object keys (strings).
- *
- * @param {Array} a First array
- * @param {Array} b Second array
- * @return {Array} Intersection of arrays
- */
-oo.simpleArrayIntersection = function ( a, b ) {
-       return simpleArrayCombine( a, b, true );
-};
-
-/**
- * Compute the difference of two arrays (items in 'a' but not 'b').
- *
- * Arrays values must be convertable to object keys (strings).
- *
- * @param {Array} a First array
- * @param {Array} b Second array
- * @return {Array} Intersection of arrays
- */
-oo.simpleArrayDifference = function ( a, b ) {
-       return simpleArrayCombine( a, b, false );
-};
-/*global hasOwn, toString */
-
-/**
- * Assert whether a value is a plain object or not.
- *
- * @param {Mixed} obj
- * @return {boolean}
- */
-oo.isPlainObject = function ( obj ) {
-       /*jshint eqnull:true, eqeqeq:false */
-
-       // Any object or value whose internal [[Class]] property is not "[object Object]"
-       // Support IE8: Explicitly filter out DOM nodes
-       // Support IE8: Explicitly filter out Window object (needs loose comparison)
-       if ( !obj || toString.call( obj ) !== '[object Object]' || obj.nodeType || ( obj != null && obj == obj.window ) ) {
-               return false;
-       }
-
-       // The try/catch suppresses exceptions thrown when attempting to access
-       // the "constructor" property of certain host objects suich as window.location
-       // in Firefox < 20 (https://bugzilla.mozilla.org/814622)
-       try {
-               if ( obj.constructor &&
-                               !hasOwn.call( obj.constructor.prototype, 'isPrototypeOf' ) ) {
-                       return false;
-               }
-       } catch ( e ) {
-               return false;
-       }
-
-       return true;
-};
-/**
- * @class OO.EventEmitter
- *
- * @constructor
- */
-oo.EventEmitter = function OoEventEmitter() {
-       // Properties
-
-       /**
-        * Storage of bound event handlers by event name.
-        *
-        * @property
-        */
-       this.bindings = {};
-};
-
-/* Methods */
-
-/**
- * Add a listener to events of a specific event.
- *
- * If the callback/context are already bound to the event, they will not be bound again.
- *
- * @param {string} event Type of event to listen to
- * @param {Function} callback Function to call when event occurs
- * @param {Array} [args] Arguments to pass to listener, will be prepended to emitted arguments
- * @param {Object} [context=null] Object to use as context for callback function or call method on
- * @throws {Error} Listener argument is not a function or method name
- * @chainable
- */
-oo.EventEmitter.prototype.on = function ( event, callback, args, context ) {
-       var i, bindings, binding;
-
-       // Validate callback
-       if ( typeof callback !== 'function' ) {
-               throw new Error( 'Invalid callback. Function or method name expected.' );
-       }
-       // Fallback to null context
-       if ( arguments.length < 4 ) {
-               context = null;
-       }
-       if ( this.bindings.hasOwnProperty( event ) ) {
-               // Check for duplicate callback and context for this event
-               bindings = this.bindings[event];
-               i = bindings.length;
-               while ( i-- ) {
-                       binding = bindings[i];
-                       if ( bindings.callback === callback && bindings.context === context ) {
-                               return this;
-                       }
-               }
-       } else {
-               // Auto-initialize bindings list
-               bindings = this.bindings[event] = [];
-       }
-       // Add binding
-       bindings.push( {
-               callback: callback,
-               args: args,
-               context: context
-       } );
-       return this;
-};
-
-/**
- * Adds a one-time listener to a specific event.
- *
- * @param {string} event Type of event to listen to
- * @param {Function} listener Listener to call when event occurs
- * @chainable
- */
-oo.EventEmitter.prototype.once = function ( event, listener ) {
-       var eventEmitter = this,
-               listenerWrapper = function () {
-                       eventEmitter.off( event, listenerWrapper );
-                       listener.apply( eventEmitter, Array.prototype.slice.call( arguments, 0 ) );
-               };
-       return this.on( event, listenerWrapper );
-};
-
-/**
- * Remove a specific listener from a specific event.
- *
- * @param {string} event Type of event to remove listener from
- * @param {Function} [callback] Listener to remove, omit to remove all
- * @param {Object} [context=null] Object used context for callback function or method
- * @chainable
- * @throws {Error} Listener argument is not a function
- */
-oo.EventEmitter.prototype.off = function ( event, callback, context ) {
-       var i, bindings;
-
-       if ( arguments.length === 1 ) {
-               // Remove all bindings for event
-               if ( event in this.bindings ) {
-                       delete this.bindings[event];
-               }
-       } else {
-               if ( typeof callback !== 'function' ) {
-                       throw new Error( 'Invalid callback. Function expected.' );
-               }
-               if ( !( event in this.bindings ) || !this.bindings[event].length ) {
-                       // No matching bindings
-                       return this;
-               }
-               // Fallback to null context
-               if ( arguments.length < 3 ) {
-                       context = null;
-               }
-               // Remove matching handlers
-               bindings = this.bindings[event];
-               i = bindings.length;
-               while ( i-- ) {
-                       if ( bindings[i].callback === callback && bindings[i].context === context ) {
-                               bindings.splice( i, 1 );
-                       }
-               }
-               // Cleanup if now empty
-               if ( bindings.length === 0 ) {
-                       delete this.bindings[event];
-               }
-       }
-       return this;
-};
-
-/**
- * Emit an event.
- *
- * TODO: Should this be chainable? What is the usefulness of the boolean
- * return value here?
- *
- * @param {string} event Type of event
- * @param {Mixed} args First in a list of variadic arguments passed to event handler (optional)
- * @return {boolean} If event was handled by at least one listener
- */
-oo.EventEmitter.prototype.emit = function ( event ) {
-       var i, len, binding, bindings, args;
-
-       if ( event in this.bindings ) {
-               // Slicing ensures that we don't get tripped up by event handlers that add/remove bindings
-               bindings = this.bindings[event].slice();
-               args = Array.prototype.slice.call( arguments, 1 );
-               for ( i = 0, len = bindings.length; i < len; i++ ) {
-                       binding = bindings[i];
-                       binding.callback.apply(
-                               binding.context,
-                               binding.args ? binding.args.concat( args ) : args
-                       );
-               }
-               return true;
-       }
-       return false;
-};
-
-/**
- * Connect event handlers to an object.
- *
- * @param {Object} context Object to call methods on when events occur
- * @param {Object.<string,string>|Object.<string,Function>|Object.<string,Array>} methods List of
- *  event bindings keyed by event name containing either method names, functions or arrays containing
- *  method name or function followed by a list of arguments to be passed to callback before emitted
- *  arguments
- * @chainable
- */
-oo.EventEmitter.prototype.connect = function ( context, methods ) {
-       var method, callback, args, event;
-
-       for ( event in methods ) {
-               method = methods[event];
-               // Allow providing additional args
-               if ( Array.isArray( method ) ) {
-                       args = method.slice( 1 );
-                       method = method[0];
-               } else {
-                       args = [];
-               }
-               // Allow callback to be a method name
-               if ( typeof method === 'string' ) {
-                       // Validate method
-                       if ( !context[method] || typeof context[method] !== 'function' ) {
-                               throw new Error( 'Method not found: ' + method );
-                       }
-                       // Resolve to function
-                       callback = context[method];
-               } else {
-                       callback = method;
-               }
-               // Add binding
-               this.on.apply( this, [ event, callback, args, context ] );
-       }
-       return this;
-};
-
-/**
- * Disconnect event handlers from an object.
- *
- * @param {Object} context Object to disconnect methods from
- * @param {Object.<string,string>|Object.<string,Function>|Object.<string,Array>} [methods] List of
- * event bindings keyed by event name containing either method names or functions
- * @chainable
- */
-oo.EventEmitter.prototype.disconnect = function ( context, methods ) {
-       var i, method, callback, event, bindings;
-
-       if ( methods ) {
-               // Remove specific connections to the context
-               for ( event in methods ) {
-                       method = methods[event];
-                       if ( typeof method === 'string' ) {
-                               // Validate method
-                               if ( !context[method] || typeof context[method] !== 'function' ) {
-                                       throw new Error( 'Method not found: ' + method );
-                               }
-                               // Resolve to function
-                               callback = context[method];
-                       } else {
-                               callback = method;
-                       }
-                       this.off( event, callback, context );
-               }
-       } else {
-               // Remove all connections to the context
-               for ( event in this.bindings ) {
-                       bindings = this.bindings[event];
-                       i = bindings.length;
-                       while ( i-- ) {
-                               if ( bindings[i].context === context ) {
-                                       this.off( event, bindings[i].callback, context );
-                               }
-                       }
-               }
-       }
-
-       return this;
-};
-/**
- * @class OO.Registry
- * @mixins OO.EventEmitter
- *
- * @constructor
- */
-oo.Registry = function OoRegistry() {
-       // Mixin constructors
-       oo.EventEmitter.call( this );
-
-       // Properties
-       this.registry = {};
-};
-
-/* Inheritance */
-
-oo.mixinClass( oo.Registry, oo.EventEmitter );
-
-/* Events */
-
-/**
- * @event register
- * @param {string} name
- * @param {Mixed} data
- */
-
-/* Methods */
-
-/**
- * Associate one or more symbolic names with some data.
- *
- * Only the base name will be registered, overriding any existing entry with the same base name.
- *
- * @param {string|string[]} name Symbolic name or list of symbolic names
- * @param {Mixed} data Data to associate with symbolic name
- * @fires register
- * @throws {Error} Name argument must be a string or array
- */
-oo.Registry.prototype.register = function ( name, data ) {
-       var i, len;
-       if ( typeof name === 'string' ) {
-               this.registry[name] = data;
-               this.emit( 'register', name, data );
-       } else if ( Array.isArray( name ) ) {
-               for ( i = 0, len = name.length; i < len; i++ ) {
-                       this.register( name[i], data );
-               }
-       } else {
-               throw new Error( 'Name must be a string or array, cannot be a ' + typeof name );
-       }
-};
-
-/**
- * Get data for a given symbolic name.
- *
- * Lookups are done using the base name.
- *
- * @param {string} name Symbolic name
- * @return {Mixed|undefined} Data associated with symbolic name
- */
-oo.Registry.prototype.lookup = function ( name ) {
-       return this.registry[name];
-};
-/**
- * @class OO.Factory
- * @extends OO.Registry
- *
- * @constructor
- */
-oo.Factory = function OoFactory() {
-       oo.Factory.parent.call( this );
-
-       // Properties
-       this.entries = [];
-};
-
-/* Inheritance */
-
-oo.inheritClass( oo.Factory, oo.Registry );
-
-/* Methods */
-
-/**
- * Register a constructor with the factory.
- *
- * Classes must have a static `name` property to be registered.
- *
- *     function MyClass() {};
- *     OO.initClass( MyClass );
- *     // Adds a static property to the class defining a symbolic name
- *     MyClass.static.name = 'mine';
- *     // Registers class with factory, available via symbolic name 'mine'
- *     factory.register( MyClass );
- *
- * @param {Function} constructor Constructor to use when creating object
- * @throws {Error} Name must be a string and must not be empty
- * @throws {Error} Constructor must be a function
- */
-oo.Factory.prototype.register = function ( constructor ) {
-       var name;
-
-       if ( typeof constructor !== 'function' ) {
-               throw new Error( 'constructor must be a function, cannot be a ' + typeof constructor );
-       }
-       name = constructor.static && constructor.static.name;
-       if ( typeof name !== 'string' || name === '' ) {
-               throw new Error( 'Name must be a string and must not be empty' );
-       }
-       this.entries.push( name );
-
-       oo.Factory.parent.prototype.register.call( this, name, constructor );
-};
-
-/**
- * Create an object based on a name.
- *
- * Name is used to look up the constructor to use, while all additional arguments are passed to the
- * constructor directly, so leaving one out will pass an undefined to the constructor.
- *
- * @param {string} name Object name
- * @param {Mixed...} [args] Arguments to pass to the constructor
- * @return {Object} The new object
- * @throws {Error} Unknown object name
- */
-oo.Factory.prototype.create = function ( name ) {
-       var args, obj, constructor;
-
-       if ( !this.registry.hasOwnProperty( name ) ) {
-               throw new Error( 'No class registered by that name: ' + name );
-       }
-       constructor = this.registry[name];
-
-       // Convert arguments to array and shift the first argument (name) off
-       args = Array.prototype.slice.call( arguments, 1 );
-
-       // We can't use the "new" operator with .apply directly because apply needs a
-       // context. So instead just do what "new" does: create an object that inherits from
-       // the constructor's prototype (which also makes it an "instanceof" the constructor),
-       // then invoke the constructor with the object as context, and return it (ignoring
-       // the constructor's return value).
-       obj = Object.create( constructor.prototype );
-       constructor.apply( obj, args );
-       return obj;
-};
-/*jshint node:true */
-if ( typeof module !== 'undefined' && module.exports ) {
-       module.exports = oo;
-} else {
-       global.OO = oo;
-}
-}( this ) );
diff --git a/resources/lib/sinonjs/sinon-1.10.3.js b/resources/lib/sinonjs/sinon-1.10.3.js
new file mode 100644 (file)
index 0000000..703414d
--- /dev/null
@@ -0,0 +1,5073 @@
+/**
+ * Sinon.JS 1.10.3, 2014/07/11
+ *
+ * @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.
+ */
+
+this.sinon = (function () {
+var samsam, formatio;
+function define(mod, deps, fn) { if (mod == "samsam") { samsam = 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 (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 (getClass(object) === "Array" && getClass(matcher) === "Array") {
+            return arrayContains(object, matcher);
+        }
+
+        if (matcher && typeof matcher === "object") {
+            var prop;
+            for (prop in matcher) {
+                if (!match(object[prop], 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
+    };
+
+    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 i, l, pieces = [];
+        for (i = 0, l = array.length; i < l; ++i) {
+            pieces.push(ascii(this, array[i], processed));
+        }
+        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, l;
+
+        for (i = 0, l = properties.length; 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, l = indent; i < l; ++i) { is += " "; }
+
+        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;
+});
+/*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
+/*global module, require, __dirname, document*/
+/**
+ * Sinon core utilities. For internal use only.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+var sinon = (function (formatio) {
+    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;
+    }
+
+    var sinon = {
+        wrapMethod: function wrapMethod(object, property, method) {
+            if (!object) {
+                throw new TypeError("Should wrap property of object");
+            }
+
+            if (typeof method != "function") {
+                throw new TypeError("Method wrapper should be function");
+            }
+
+            var wrappedMethod = object[property],
+                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._stack) {
+                    error.stack += '\n--------------\n' + wrappedMethod._stack;
+                }
+                throw error;
+            }
+
+            // 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);
+            object[property] = method;
+            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._stack = (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) {
+                    delete object[property];
+                }
+                if (object[property] === method) {
+                    object[property] = wrappedMethod;
+                }
+            };
+
+            method.restore.sinon = true;
+            mirrorProperties(method, wrappedMethod);
+
+            return method;
+        },
+
+        extend: function extend(target) {
+            for (var i = 1, l = arguments.length; i < l; i += 1) {
+                for (var prop in arguments[i]) {
+                    if (arguments[i].hasOwnProperty(prop)) {
+                        target[prop] = arguments[i][prop];
+                    }
+
+                    // DONT ENUM bug, only care about toString
+                    if (arguments[i].hasOwnProperty("toString") &&
+                        arguments[i].toString != target.toString) {
+                        target.toString = arguments[i].toString;
+                    }
+                }
+            }
+
+            return target;
+        },
+
+        create: function create(proto) {
+            var F = function () {};
+            F.prototype = proto;
+            return new F();
+        },
+
+        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;
+        },
+
+        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;
+        },
+
+        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";
+        },
+
+        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;
+        },
+
+        format: function (val) {
+            return "" + val;
+        },
+
+        defaultConfig: {
+            injectIntoThis: true,
+            injectInto: null,
+            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
+            useFakeTimers: true,
+            useFakeServer: true
+        },
+
+        timesInWords: function timesInWords(count) {
+            return count == 1 && "once" ||
+                count == 2 && "twice" ||
+                count == 3 && "thrice" ||
+                (count || 0) + " times";
+        },
+
+        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;
+        },
+
+        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;
+            });
+        },
+
+        log: function () {},
+
+        logError: function (label, err) {
+            var msg = label + " threw exception: ";
+            sinon.log(msg + "[" + err.name + "] " + err.message);
+            if (err.stack) { sinon.log(err.stack); }
+
+            setTimeout(function () {
+                err.message = msg + err.message;
+                throw err;
+            }, 0);
+        },
+
+        typeOf: function (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();
+        },
+
+        createStubInstance: function (constructor) {
+            if (typeof constructor !== "function") {
+                throw new TypeError("The constructor should be a function.");
+            }
+            return sinon.stub(sinon.create(constructor.prototype));
+        },
+
+        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();
+            }
+        }
+    };
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
+    var isAMD = typeof define === 'function' && typeof define.amd === 'object' && define.amd;
+
+    function makePublicAPI(require, exports, module) {
+        module.exports = sinon;
+        sinon.spy = require("./sinon/spy");
+        sinon.spyCall = require("./sinon/call");
+        sinon.behavior = require("./sinon/behavior");
+        sinon.stub = require("./sinon/stub");
+        sinon.mock = require("./sinon/mock");
+        sinon.collection = require("./sinon/collection");
+        sinon.assert = require("./sinon/assert");
+        sinon.sandbox = require("./sinon/sandbox");
+        sinon.test = require("./sinon/test");
+        sinon.testCase = require("./sinon/test_case");
+        sinon.match = require("./sinon/match");
+    }
+
+    if (isAMD) {
+        define(makePublicAPI);
+    } else if (isNode) {
+        try {
+            formatio = require("formatio");
+        } catch (e) {}
+        makePublicAPI(require, exports, module);
+    }
+
+    if (formatio) {
+        var formatter = formatio.configure({ quoteStrings: false });
+        sinon.format = function () {
+            return formatter.ascii.apply(formatter, arguments);
+        };
+    } else if (isNode) {
+        try {
+            var util = require("util");
+            sinon.format = function (value) {
+                return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
+            };
+        } catch (e) {
+            /* Node, but no util module - would be very old, but better safe than
+             sorry */
+        }
+    }
+
+    return sinon;
+}(typeof formatio == "object" && formatio));
+
+/* @depend ../sinon.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) {
+    var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    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;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = match; });
+    } else if (commonJSModule) {
+        module.exports = match;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+  * @depend ../sinon.js
+  * @depend match.js
+  */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+  * 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) {
+    var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    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() {
+            for (var i = 0, l = arguments.length; i < l; i += 1) {
+                if (!sinon.deepEqual(arguments[i], this.args[i])) {
+                    return false;
+                }
+            }
+
+            return true;
+        },
+
+        calledWithMatch: function calledWithMatch() {
+            for (var i = 0, l = arguments.length; 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;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = createSpyCall; });
+    } else if (commonJSModule) {
+        module.exports = createSpyCall;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+
+/**
+  * @depend ../sinon.js
+  * @depend call.js
+  */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+  * Spy functions
+  *
+  * @author Christian Johansen (christian@cjohansen.no)
+  * @license BSD
+  *
+  * Copyright (c) 2010-2013 Christian Johansen
+  */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
+    var push = Array.prototype.push;
+    var slice = Array.prototype.slice;
+    var callId = 0;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function spy(object, property) {
+        if (!property && typeof object == "function") {
+            return spy.create(object);
+        }
+
+        if (!object && !property) {
+            return spy.create(function () { });
+        }
+
+        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) {
+        // Retain the function length:
+        var p;
+        if (func.length) {
+            eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) +
+                ") { return p.invoke(func, this, slice.call(arguments)); });");
+        }
+        else {
+            p = function proxy() {
+                return p.invoke(func, this, slice.call(arguments));
+            };
+        }
+        return p;
+    }
+
+    var uuid = 0;
+
+    // Public API
+    var spyApi = {
+        reset: function () {
+            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();
+                }
+            }
+        },
+
+        create: function create(func) {
+            var name;
+
+            if (typeof func != "function") {
+                func = function () { };
+            } else {
+                name = sinon.functionName(func);
+            }
+
+            var proxy = createProxy(func);
+
+            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._create = 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 {
+                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;
+            }
+
+            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._create();
+            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;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = spy; });
+    } else if (commonJSModule) {
+        module.exports = spy;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ */
+/*jslint eqeqeq: false, onevar: false*/
+/*global module, require, sinon, process, setImmediate, setTimeout*/
+/**
+ * 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 commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    var slice = Array.prototype.slice;
+    var join = Array.prototype.join;
+    var proto;
+
+    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) {
+            var callArgProp = behavior.callArgProp;
+
+            for (var i = 0, l = args.length; i < l; ++i) {
+                if (!callArgProp && typeof args[i] == "function") {
+                    return args[i];
+                }
+
+                if (callArgProp && args[i] &&
+                    typeof args[i][callArgProp] == "function") {
+                    return args[i][callArgProp];
+                }
+            }
+
+            return null;
+        }
+
+        return args[callArgAt];
+    }
+
+    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);
+            }
+        }
+    }
+
+    proto = {
+        create: function(stub) {
+            var behavior = sinon.extend({}, sinon.behavior);
+            delete behavior.create;
+            behavior.stub = stub;
+
+            return behavior;
+        },
+
+        isPresent: function() {
+            return (typeof this.callArgAt == 'number' ||
+                    this.exception ||
+                    typeof this.returnArgAt == 'number' ||
+                    this.returnThis ||
+                    this.returnValueDefined);
+        },
+
+        invoke: function(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(index) {
+            return this.stub.onCall(index);
+        },
+
+        onFirstCall: function() {
+            return this.stub.onFirstCall();
+        },
+
+        onSecondCall: function() {
+            return this.stub.onSecondCall();
+        },
+
+        onThirdCall: function() {
+            return this.stub.onThirdCall();
+        },
+
+        withArgs: function(/* 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 = -1;
+            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 = -1;
+            this.callbackArguments = slice.call(arguments, 1);
+            this.callbackContext = context;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        yieldsTo: function (prop) {
+            this.callArgAt = -1;
+            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 = -1;
+            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;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = proto; });
+    } else if (commonJSModule) {
+        module.exports = proto;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend spy.js
+ * @depend behavior.js
+ */
+/*jslint eqeqeq: false, onevar: false*/
+/*global module, require, sinon*/
+/**
+ * Stub functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function stub(object, property, func) {
+        if (!!func && typeof func != "function") {
+            throw new TypeError("Custom stub should be function");
+        }
+
+        var wrapper;
+
+        if (func) {
+            wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
+        } else {
+            wrapper = stub.create();
+        }
+
+        if (!object && typeof property === "undefined") {
+            return sinon.stub.create();
+        }
+
+        if (typeof property === "undefined" && typeof object == "object") {
+            for (var prop in object) {
+                if (typeof object[prop] === "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;
+
+    sinon.extend(stub, (function () {
+        var proto = {
+            create: function create() {
+                var functionStub = function () {
+                    return getCurrentBehavior(functionStub).invoke(this, arguments);
+                };
+
+                functionStub.id = "stub#" + uuid++;
+                var orig = functionStub;
+                functionStub = sinon.spy.create(functionStub);
+                functionStub.func = orig;
+
+                sinon.extend(functionStub, stub);
+                functionStub._create = 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(index) {
+                if (!this.behaviors[index]) {
+                    this.behaviors[index] = sinon.behavior.create(this);
+                }
+
+                return this.behaviors[index];
+            },
+
+            onFirstCall: function() {
+                return this.onCall(0);
+            },
+
+            onSecondCall: function() {
+                return this.onCall(1);
+            },
+
+            onThirdCall: function() {
+                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));
+            }
+        }
+
+        return proto;
+    }()));
+
+    sinon.stub = stub;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = stub; });
+    } else if (commonJSModule) {
+        module.exports = stub;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend stub.js
+ */
+/*jslint eqeqeq: false, onevar: false, nomen: false*/
+/*global module, require, sinon*/
+/**
+ * Mock functions.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
+    var push = [].push;
+    var match;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    match = sinon.match;
+
+    if (!match && commonJSModule) {
+        match = require("./match");
+    }
+
+    function mock(object) {
+        if (!object) {
+            return sinon.expectation.create("Anonymous mock");
+        }
+
+        return mock.create(object);
+    }
+
+    sinon.mock = mock;
+
+    sinon.extend(mock, (function () {
+        function each(collection, callback) {
+            if (!collection) {
+                return;
+            }
+
+            for (var i = 0, l = collection.length; i < l; i += 1) {
+                callback(collection[i]);
+            }
+        }
+
+        return {
+            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 {
+                    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;
+
+    sinon.expectation = (function () {
+        var slice = Array.prototype.slice;
+        var _invoke = sinon.spy.invoke;
+
+        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;
+            }
+        }
+
+        return {
+            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 _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(message) {
+              sinon.assert.pass(message);
+            },
+            fail: function (message) {
+                var exception = new Error(message);
+                exception.name = "ExpectationError";
+
+                throw exception;
+            }
+        };
+    }());
+
+    sinon.mock = mock;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = mock; });
+    } else if (commonJSModule) {
+        module.exports = mock;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend stub.js
+ * @depend mock.js
+ */
+/*jslint eqeqeq: false, onevar: false, forin: true*/
+/*global module, require, sinon*/
+/**
+ * Collections of stubs, spies and mocks.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
+    var push = [].push;
+    var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    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);
+        }
+    }
+
+    var collection = {
+        verify: function resolve() {
+            each(this, "verify");
+        },
+
+        restore: function restore() {
+            each(this, "restore");
+            compact(this);
+        },
+
+        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;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = collection; });
+    } else if (commonJSModule) {
+        module.exports = collection;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
+/*global module, require, window*/
+/**
+ * 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) {
+    // 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 id = 1;
+
+    function addTimer(args, recurring) {
+        if (args.length === 0) {
+            throw new Error("Function requires at least 1 parameter");
+        }
+
+        if (typeof args[0] === "undefined") {
+            throw new Error("Callback must be provided to timer calls");
+        }
+
+        var toId = id++;
+        var delay = args[1] || 0;
+
+        if (!this.timeouts) {
+            this.timeouts = {};
+        }
+
+        this.timeouts[toId] = {
+            id: toId,
+            func: args[0],
+            callAt: this.now + delay,
+            invokeArgs: Array.prototype.slice.call(args, 2)
+        };
+
+        if (recurring === true) {
+            this.timeouts[toId].interval = delay;
+        }
+
+        if (addTimerReturnsObject) {
+            return {
+                id: toId,
+                ref: function() {},
+                unref: function() {}
+            };
+        }
+        else {
+            return toId;
+        }
+    }
+
+    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;
+    }
+
+    function createObject(object) {
+        var newObject;
+
+        if (Object.create) {
+            newObject = Object.create(object);
+        } else {
+            var F = function () {};
+            F.prototype = object;
+            newObject = new F();
+        }
+
+        newObject.Date.clock = newObject;
+        return newObject;
+    }
+
+    sinon.clock = {
+        now: 0,
+
+        create: function create(now) {
+            var clock = createObject(this);
+
+            if (typeof now == "number") {
+                clock.now = now;
+            }
+
+            if (!!now && typeof now == "object") {
+                throw new TypeError("now should be milliseconds since UNIX epoch");
+            }
+
+            return clock;
+        },
+
+        setTimeout: function setTimeout(callback, timeout) {
+            return addTimer.call(this, arguments, false);
+        },
+
+        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 (!this.timeouts) {
+                this.timeouts = [];
+            }
+            // 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 this.timeouts) {
+                delete this.timeouts[timerId];
+            }
+        },
+
+        setInterval: function setInterval(callback, timeout) {
+            return addTimer.call(this, arguments, true);
+        },
+
+        clearInterval: function clearInterval(timerId) {
+            this.clearTimeout(timerId);
+        },
+
+        setImmediate: function setImmediate(callback) {
+            var passThruArgs = Array.prototype.slice.call(arguments, 1);
+
+            return addTimer.call(this, [callback, 0].concat(passThruArgs), false);
+        },
+
+        clearImmediate: function clearImmediate(timerId) {
+            this.clearTimeout(timerId);
+        },
+
+        tick: function tick(ms) {
+            ms = typeof ms == "number" ? ms : parseTime(ms);
+            var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
+            var timer = this.firstTimerInRange(tickFrom, tickTo);
+
+            var firstException;
+            while (timer && tickFrom <= tickTo) {
+                if (this.timeouts[timer.id]) {
+                    tickFrom = this.now = timer.callAt;
+                    try {
+                      this.callTimer(timer);
+                    } catch (e) {
+                      firstException = firstException || e;
+                    }
+                }
+
+                timer = this.firstTimerInRange(previous, tickTo);
+                previous = tickFrom;
+            }
+
+            this.now = tickTo;
+
+            if (firstException) {
+              throw firstException;
+            }
+
+            return this.now;
+        },
+
+        firstTimerInRange: function (from, to) {
+            var timer, smallest = null, originalTimer;
+
+            for (var id in this.timeouts) {
+                if (this.timeouts.hasOwnProperty(id)) {
+                    if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
+                        continue;
+                    }
+
+                    if (smallest === null || this.timeouts[id].callAt < smallest) {
+                        originalTimer = this.timeouts[id];
+                        smallest = this.timeouts[id].callAt;
+
+                        timer = {
+                            func: this.timeouts[id].func,
+                            callAt: this.timeouts[id].callAt,
+                            interval: this.timeouts[id].interval,
+                            id: this.timeouts[id].id,
+                            invokeArgs: this.timeouts[id].invokeArgs
+                        };
+                    }
+                }
+            }
+
+            return timer || null;
+        },
+
+        callTimer: function (timer) {
+            if (typeof timer.interval == "number") {
+                this.timeouts[timer.id].callAt += timer.interval;
+            } else {
+                delete this.timeouts[timer.id];
+            }
+
+            try {
+                if (typeof timer.func == "function") {
+                    timer.func.apply(null, timer.invokeArgs);
+                } else {
+                    eval(timer.func);
+                }
+            } catch (e) {
+              var exception = e;
+            }
+
+            if (!this.timeouts[timer.id]) {
+                if (exception) {
+                  throw exception;
+                }
+                return;
+            }
+
+            if (exception) {
+              throw exception;
+            }
+        },
+
+        reset: function reset() {
+            this.timeouts = {};
+        },
+
+        Date: (function () {
+            var NativeDate = Date;
+
+            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 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;
+    }
+
+    var methods = ["Date", "setTimeout", "setInterval",
+                   "clearTimeout", "clearInterval"];
+
+    if (typeof global.setImmediate !== "undefined") {
+        methods.push("setImmediate");
+    }
+
+    if (typeof global.clearImmediate !== "undefined") {
+        methods.push("clearImmediate");
+    }
+
+    function restore() {
+        var method;
+
+        for (var i = 0, l = this.methods.length; i < l; i++) {
+            method = this.methods[i];
+
+            if (global[method].hadOwnProperty) {
+                global[method] = this["_" + method];
+            } else {
+                try {
+                    delete global[method];
+                } catch (e) {}
+            }
+        }
+
+        // Prevent multiple executions which will completely remove these props
+        this.methods = [];
+    }
+
+    function stubGlobal(method, clock) {
+        clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(global, method);
+        clock["_" + method] = global[method];
+
+        if (method == "Date") {
+            var date = mirrorDateProperties(clock[method], global[method]);
+            global[method] = date;
+        } else {
+            global[method] = function () {
+                return clock[method].apply(clock, arguments);
+            };
+
+            for (var prop in clock[method]) {
+                if (clock[method].hasOwnProperty(prop)) {
+                    global[method][prop] = clock[method][prop];
+                }
+            }
+        }
+
+        global[method].clock = clock;
+    }
+
+    sinon.useFakeTimers = function useFakeTimers(now) {
+        var clock = sinon.clock.create(now);
+        clock.restore = restore;
+        clock.methods = Array.prototype.slice.call(arguments,
+                                                   typeof now == "number" ? 1 : 0);
+
+        if (clock.methods.length === 0) {
+            clock.methods = methods;
+        }
+
+        for (var i = 0, l = clock.methods.length; i < l; i++) {
+            stubGlobal(clock.methods[i], clock);
+        }
+
+        return clock;
+    };
+}(typeof global != "undefined" && typeof global !== "function" ? global : this));
+
+sinon.timers = {
+    setTimeout: setTimeout,
+    clearTimeout: clearTimeout,
+    setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
+    clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
+    setInterval: setInterval,
+    clearInterval: clearInterval,
+    Date: Date
+};
+
+if (typeof module !== 'undefined' && module.exports) {
+    module.exports = sinon;
+}
+
+/*jslint eqeqeq: false, onevar: false*/
+/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
+/**
+ * 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;
+
+    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;
+    };
+
+    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;
+        }
+    };
+}());
+
+/**
+ * @depend ../../sinon.js
+ * @depend event.js
+ */
+/*jslint eqeqeq: false, onevar: false*/
+/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
+/**
+ * Fake XMLHttpRequest object
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+// wrapper for global
+(function(global) {
+    if (typeof sinon === "undefined") {
+        global.sinon = {};
+    }
+
+    var supportsProgress = typeof ProgressEvent !== "undefined";
+    var supportsCustomEvent = typeof CustomEvent !== "undefined";
+    sinon.xhr = { XMLHttpRequest: global.XMLHttpRequest };
+    var xhr = sinon.xhr;
+    xhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
+    xhr.GlobalActiveXObject = global.ActiveXObject;
+    xhr.supportsActiveX = typeof xhr.GlobalActiveXObject != "undefined";
+    xhr.supportsXHR = typeof xhr.GlobalXMLHttpRequest != "undefined";
+    xhr.workingXHR = xhr.supportsXHR ? xhr.GlobalXMLHttpRequest : xhr.supportsActiveX
+                                     ? function() { return new xhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false;
+    xhr.supportsCORS = xhr.supportsXHR && 'withCredentials' in (new sinon.xhr.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*/
+
+    function FakeXMLHttpRequest() {
+        this.readyState = FakeXMLHttpRequest.UNSENT;
+        this.requestHeaders = {};
+        this.requestBody = null;
+        this.status = 0;
+        this.statusText = "";
+        this.upload = new UploadProgress();
+        if (sinon.xhr.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(event, listener) {
+        this.eventListeners[event].push(listener);
+    };
+
+    UploadProgress.prototype.removeEventListener = function(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(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");
+        }
+    }
+
+    // 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(fn) {
+        this.filters.push(fn)
+    };
+    var IE6Re = /MSIE 6/;
+    FakeXMLHttpRequest.defake = function(fakeXhr,xhrArgs) {
+        var xhr = new sinon.xhr.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() {
+            fakeXhr.readyState = xhr.readyState;
+            if(xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
+                copyAttrs(["status","statusText"]);
+            }
+            if(xhr.readyState >= FakeXMLHttpRequest.LOADING) {
+                copyAttrs(["responseText"]);
+            }
+            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;
+        }
+    }
+
+    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.responseXML = null;
+            this.requestHeaders = {};
+            this.sendFlag = false;
+            if(sinon.FakeXMLHttpRequest.useFilters === true) {
+                var xhrArgs = arguments;
+                var defake = some(FakeXMLHttpRequest.filters,function(filter) {
+                    return filter.apply(this,xhrArgs)
+                });
+                if (defake) {
+                  return sinon.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);
+                }
+            }
+
+            this.dispatchEvent(new sinon.Event("readystatechange"));
+
+            switch (this.readyState) {
+                case FakeXMLHttpRequest.DONE:
+                    this.dispatchEvent(new sinon.Event("load", false, false, this));
+                    this.dispatchEvent(new sinon.Event("loadend", false, false, this));
+                    this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
+                    if (supportsProgress) {
+                        this.upload.dispatchEvent(new sinon.ProgressEvent('progress', {loaded: 100, total: 100}));
+                    }
+                    break;
+            }
+        },
+
+        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)) {
+                if (this.requestHeaders["Content-Type"]) {
+                    var value = this.requestHeaders["Content-Type"].split(";");
+                    this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8";
+                } else {
+                    this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
+                }
+
+                this.requestBody = data;
+            }
+
+            this.errorFlag = false;
+            this.sendFlag = this.async;
+            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.errorFlag = true;
+            this.requestHeaders = {};
+
+            if (this.readyState > sinon.FakeXMLHttpRequest.UNSENT && this.sendFlag) {
+                this.readyStateChange(sinon.FakeXMLHttpRequest.DONE);
+                this.sendFlag = false;
+            }
+
+            this.readyState = sinon.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 = header.toLowerCase();
+
+            for (var h in this.responseHeaders) {
+                if (h.toLowerCase() == header) {
+                    return this.responseHeaders[h];
+                }
+            }
+
+            return 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
+                }
+            }
+
+            if (this.async) {
+                this.readyStateChange(FakeXMLHttpRequest.DONE);
+            } else {
+                this.readyState = 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));
+            }
+        },
+
+        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
+    });
+
+    // Borrowed from JSpec
+    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",
+        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"
+    };
+
+    sinon.useFakeXMLHttpRequest = function () {
+        sinon.FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
+            if (xhr.supportsXHR) {
+                global.XMLHttpRequest = xhr.GlobalXMLHttpRequest;
+            }
+
+            if (xhr.supportsActiveX) {
+                global.ActiveXObject = xhr.GlobalActiveXObject;
+            }
+
+            delete sinon.FakeXMLHttpRequest.restore;
+
+            if (keepOnCreate !== true) {
+                delete sinon.FakeXMLHttpRequest.onCreate;
+            }
+        };
+        if (xhr.supportsXHR) {
+            global.XMLHttpRequest = sinon.FakeXMLHttpRequest;
+        }
+
+        if (xhr.supportsActiveX) {
+            global.ActiveXObject = function ActiveXObject(objId) {
+                if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
+
+                    return new sinon.FakeXMLHttpRequest();
+                }
+
+                return new xhr.GlobalActiveXObject(objId);
+            };
+        }
+
+        return sinon.FakeXMLHttpRequest;
+    };
+
+    sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
+
+})((function(){ return typeof global === "object" ? global : this; })());
+
+if (typeof module !== 'undefined' && module.exports) {
+    module.exports = sinon;
+}
+
+/**
+ * @depend fake_xml_http_request.js
+ */
+/*jslint eqeqeq: false, onevar: false, regexp: false, plusplus: false*/
+/*global module, require, window*/
+/**
+ * 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 = {};
+}
+
+sinon.fakeServer = (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;
+    }
+
+    return {
+        create: function () {
+            var server = create(this);
+            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.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(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) {
+                    sinon.fakeServer.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);
+        }
+    };
+}());
+
+if (typeof module !== 'undefined' && module.exports) {
+    module.exports = sinon;
+}
+
+/**
+ * @depend fake_server.js
+ * @depend fake_timers.js
+ */
+/*jslint browser: true, eqeqeq: false, onevar: false*/
+/*global sinon*/
+/**
+ * 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 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);
+    };
+}());
+
+/**
+ * @depend ../sinon.js
+ * @depend collection.js
+ * @depend util/fake_timers.js
+ * @depend util/fake_server_with_clock.js
+ */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global require, module*/
+/**
+ * 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
+ */
+
+if (typeof module !== "undefined" && module.exports && typeof require == "function") {
+    var sinon = require("../sinon");
+    sinon.extend(sinon, require("./util/fake_timers"));
+}
+
+(function () {
+    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;
+            }
+
+            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;
+        }
+    });
+
+    sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = sinon.sandbox; });
+    } else if (typeof module !== 'undefined' && module.exports) {
+        module.exports = sinon.sandbox;
+    }
+}());
+
+/**
+ * @depend ../sinon.js
+ * @depend stub.js
+ * @depend mock.js
+ * @depend sandbox.js
+ */
+/*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/
+/*global module, require, sinon*/
+/**
+ * Test function, sandboxes fakes
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    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 exception, result;
+            var args = Array.prototype.slice.call(arguments).concat(sandbox.args);
+
+            try {
+                result = callback.apply(this, args);
+            } catch (e) {
+                exception = e;
+            }
+
+            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;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = test; });
+    } else if (commonJSModule) {
+        module.exports = test;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend test.js
+ */
+/*jslint eqeqeq: false, onevar: false, eqeqeq: false*/
+/*global module, require, sinon*/
+/**
+ * Test case, sandboxes all test functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon || !Object.prototype.hasOwnProperty) {
+        return;
+    }
+
+    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 testCase(tests, prefix) {
+        /*jsl:ignore*/
+        if (!tests || typeof tests != "object") {
+            throw new TypeError("sinon.testCase needs an object with test functions");
+        }
+        /*jsl:end*/
+
+        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)) {
+                property = tests[testName];
+
+                if (/^(setUp|tearDown)$/.test(testName)) {
+                    continue;
+                }
+
+                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;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = testCase; });
+    } else if (commonJSModule) {
+        module.exports = testCase;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend stub.js
+ */
+/*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+ * 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 commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
+    var slice = Array.prototype.slice;
+    var assert;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    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 (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.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 != "export" && (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;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = assert; });
+    } else if (commonJSModule) {
+        module.exports = assert;
+    }
+}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
+
+/**
+ * @depend ../../sinon.js
+ * @depend event.js
+ */
+/*jslint eqeqeq: false, onevar: false*/
+/*global sinon, module, require, XDomainRequest*/
+/**
+ * Fake XDomainRequest object
+ */
+
+if (typeof sinon == "undefined") {
+    this.sinon = {};
+}
+sinon.xdr = { XDomainRequest: this.XDomainRequest };
+
+// wrapper for global
+(function (global) {
+    var xdr = sinon.xdr;
+    xdr.GlobalXDomainRequest = global.XDomainRequest;
+    xdr.supportsXDR = typeof xdr.GlobalXDomainRequest != "undefined";
+    xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest :  false;
+
+    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(){
+            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 () {
+        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;
+})(this);
+
+if (typeof module == "object" && typeof require == "function") {
+    module.exports = sinon;
+}
+
+return sinon;}.call(typeof window != 'undefined' && window || {}));
diff --git a/resources/lib/sinonjs/sinon-1.9.0.js b/resources/lib/sinonjs/sinon-1.9.0.js
deleted file mode 100644 (file)
index 428b729..0000000
+++ /dev/null
@@ -1,4794 +0,0 @@
-/**
- * Sinon.JS 1.9.0, 2014/03/05
- *
- * @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.
- */
-
-this.sinon = (function () {
-var samsam, formatio;
-function define(mod, deps, fn) { if (mod == "samsam") { samsam = deps(); } else { formatio = fn(samsam); } }
-define.amd = true;
-((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 (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 (getClass(object) === "Array" && getClass(matcher) === "Array") {
-            return arrayContains(object, matcher);
-        }
-
-        if (matcher && typeof matcher === "object") {
-            var prop;
-            for (prop in matcher) {
-                if (!match(object[prop], 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
-    };
-
-    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 i, l, pieces = [];
-        for (i = 0, l = array.length; i < l; ++i) {
-            pieces.push(ascii(this, array[i], processed));
-        }
-        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, l;
-
-        for (i = 0, l = properties.length; 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, l = indent; i < l; ++i) { is += " "; }
-
-        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;
-});
-/*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
-/*global module, require, __dirname, document*/
-/**
- * Sinon core utilities. For internal use only.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-var sinon = (function (formatio) {
-    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 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;
-    }
-
-    var sinon = {
-        wrapMethod: function wrapMethod(object, property, method) {
-            if (!object) {
-                throw new TypeError("Should wrap property of object");
-            }
-
-            if (typeof method != "function") {
-                throw new TypeError("Method wrapper should be function");
-            }
-
-            var wrappedMethod = object[property],
-                error;
-
-            if (!isFunction(wrappedMethod)) {
-                error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
-                                    property + " as function");
-            }
-
-            if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
-                error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
-            }
-
-            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._stack) {
-                    error.stack += '\n--------------\n' + wrappedMethod._stack;
-                }
-                throw error;
-            }
-
-            // 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);
-            object[property] = method;
-            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._stack = (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) {
-                    delete object[property];
-                }
-                if (object[property] === method) {
-                    object[property] = wrappedMethod;
-                }
-            };
-
-            method.restore.sinon = true;
-            mirrorProperties(method, wrappedMethod);
-
-            return method;
-        },
-
-        extend: function extend(target) {
-            for (var i = 1, l = arguments.length; i < l; i += 1) {
-                for (var prop in arguments[i]) {
-                    if (arguments[i].hasOwnProperty(prop)) {
-                        target[prop] = arguments[i][prop];
-                    }
-
-                    // DONT ENUM bug, only care about toString
-                    if (arguments[i].hasOwnProperty("toString") &&
-                        arguments[i].toString != target.toString) {
-                        target.toString = arguments[i].toString;
-                    }
-                }
-            }
-
-            return target;
-        },
-
-        create: function create(proto) {
-            var F = function () {};
-            F.prototype = proto;
-            return new F();
-        },
-
-        deepEqual: function deepEqual(a, b) {
-            if (sinon.match && sinon.match.isMatcher(a)) {
-                return a.test(b);
-            }
-            if (typeof a != "object" || typeof b != "object") {
-                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 (!deepEqual(a[prop], b[prop])) {
-                    return false;
-                }
-            }
-
-            for (prop in b) {
-                bLength += 1;
-            }
-
-            return aLength == bLength;
-        },
-
-        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;
-        },
-
-        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";
-        },
-
-        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;
-        },
-
-        format: function (val) {
-            return "" + val;
-        },
-
-        defaultConfig: {
-            injectIntoThis: true,
-            injectInto: null,
-            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
-            useFakeTimers: true,
-            useFakeServer: true
-        },
-
-        timesInWords: function timesInWords(count) {
-            return count == 1 && "once" ||
-                count == 2 && "twice" ||
-                count == 3 && "thrice" ||
-                (count || 0) + " times";
-        },
-
-        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;
-        },
-
-        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;
-            });
-        },
-
-        log: function () {},
-
-        logError: function (label, err) {
-            var msg = label + " threw exception: ";
-            sinon.log(msg + "[" + err.name + "] " + err.message);
-            if (err.stack) { sinon.log(err.stack); }
-
-            setTimeout(function () {
-                err.message = msg + err.message;
-                throw err;
-            }, 0);
-        },
-
-        typeOf: function (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();
-        },
-
-        createStubInstance: function (constructor) {
-            if (typeof constructor !== "function") {
-                throw new TypeError("The constructor should be a function.");
-            }
-            return sinon.stub(sinon.create(constructor.prototype));
-        },
-
-        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();
-            }
-        }
-    };
-
-    var isNode = typeof module !== "undefined" && module.exports;
-    var isAMD = typeof define === 'function' && typeof define.amd === 'object' && define.amd;
-
-    if (isAMD) {
-        define(function(){
-            return sinon;
-        });
-    } else if (isNode) {
-        try {
-            formatio = require("formatio");
-        } catch (e) {}
-        module.exports = sinon;
-        module.exports.spy = require("./sinon/spy");
-        module.exports.spyCall = require("./sinon/call");
-        module.exports.behavior = require("./sinon/behavior");
-        module.exports.stub = require("./sinon/stub");
-        module.exports.mock = require("./sinon/mock");
-        module.exports.collection = require("./sinon/collection");
-        module.exports.assert = require("./sinon/assert");
-        module.exports.sandbox = require("./sinon/sandbox");
-        module.exports.test = require("./sinon/test");
-        module.exports.testCase = require("./sinon/test_case");
-        module.exports.assert = require("./sinon/assert");
-        module.exports.match = require("./sinon/match");
-    }
-
-    if (formatio) {
-        var formatter = formatio.configure({ quoteStrings: false });
-        sinon.format = function () {
-            return formatter.ascii.apply(formatter, arguments);
-        };
-    } else if (isNode) {
-        try {
-            var util = require("util");
-            sinon.format = function (value) {
-                return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
-            };
-        } catch (e) {
-            /* Node, but no util module - would be very old, but better safe than
-             sorry */
-        }
-    }
-
-    return sinon;
-}(typeof formatio == "object" && formatio));
-
-/* @depend ../sinon.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) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    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");
-
-    if (commonJSModule) {
-        module.exports = match;
-    } else {
-        sinon.match = match;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
-  * @depend ../sinon.js
-  * @depend match.js
-  */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
-  * 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) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    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() {
-            for (var i = 0, l = arguments.length; i < l; i += 1) {
-                if (!sinon.deepEqual(arguments[i], this.args[i])) {
-                    return false;
-                }
-            }
-
-            return true;
-        },
-
-        calledWithMatch: function calledWithMatch() {
-            for (var i = 0, l = arguments.length; 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
-
-    if (commonJSModule) {
-        module.exports = createSpyCall;
-    } else {
-        sinon.spyCall = createSpyCall;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-
-/**
-  * @depend ../sinon.js
-  * @depend call.js
-  */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
-  * Spy functions
-  *
-  * @author Christian Johansen (christian@cjohansen.no)
-  * @license BSD
-  *
-  * Copyright (c) 2010-2013 Christian Johansen
-  */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-    var push = Array.prototype.push;
-    var slice = Array.prototype.slice;
-    var callId = 0;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function spy(object, property) {
-        if (!property && typeof object == "function") {
-            return spy.create(object);
-        }
-
-        if (!object && !property) {
-            return spy.create(function () { });
-        }
-
-        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) {
-        // Retain the function length:
-        var p;
-        if (func.length) {
-            eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) +
-                ") { return p.invoke(func, this, slice.call(arguments)); });");
-        }
-        else {
-            p = function proxy() {
-                return p.invoke(func, this, slice.call(arguments));
-            };
-        }
-        return p;
-    }
-
-    var uuid = 0;
-
-    // Public API
-    var spyApi = {
-        reset: function () {
-            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();
-                }
-            }
-        },
-
-        create: function create(func) {
-            var name;
-
-            if (typeof func != "function") {
-                func = function () { };
-            } else {
-                name = sinon.functionName(func);
-            }
-
-            var proxy = createProxy(func);
-
-            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._create = 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++);
-
-            try {
-                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;
-            }
-
-            push.call(this.exceptions, exception);
-            push.call(this.returnValues, returnValue);
-
-            createCallProperties.call(this);
-
-            if (exception !== undefined) {
-                throw exception;
-            }
-
-            return returnValue;
-        },
-
-        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._create();
-            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;
-
-    if (commonJSModule) {
-        module.exports = spy;
-    } else {
-        sinon.spy = spy;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global module, require, sinon, process, setImmediate, setTimeout*/
-/**
- * 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 commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    var slice = Array.prototype.slice;
-    var join = Array.prototype.join;
-    var proto;
-
-    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) {
-            var callArgProp = behavior.callArgProp;
-
-            for (var i = 0, l = args.length; i < l; ++i) {
-                if (!callArgProp && typeof args[i] == "function") {
-                    return args[i];
-                }
-
-                if (callArgProp && args[i] &&
-                    typeof args[i][callArgProp] == "function") {
-                    return args[i][callArgProp];
-                }
-            }
-
-            return null;
-        }
-
-        return args[callArgAt];
-    }
-
-    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);
-            }
-        }
-    }
-
-    proto = {
-        create: function(stub) {
-            var behavior = sinon.extend({}, sinon.behavior);
-            delete behavior.create;
-            behavior.stub = stub;
-
-            return behavior;
-        },
-
-        isPresent: function() {
-            return (typeof this.callArgAt == 'number' ||
-                    this.exception ||
-                    typeof this.returnArgAt == 'number' ||
-                    this.returnThis ||
-                    this.returnValueDefined);
-        },
-
-        invoke: function(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(index) {
-            return this.stub.onCall(index);
-        },
-
-        onFirstCall: function() {
-            return this.stub.onFirstCall();
-        },
-
-        onSecondCall: function() {
-            return this.stub.onSecondCall();
-        },
-
-        onThirdCall: function() {
-            return this.stub.onThirdCall();
-        },
-
-        withArgs: function(/* 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 = -1;
-            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 = -1;
-            this.callbackArguments = slice.call(arguments, 1);
-            this.callbackContext = context;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        yieldsTo: function (prop) {
-            this.callArgAt = -1;
-            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 = -1;
-            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);
-        }
-    }
-
-    if (commonJSModule) {
-        module.exports = proto;
-    } else {
-        sinon.behavior = proto;
-    }
-}(typeof sinon == "object" && sinon || null));
-/**
- * @depend ../sinon.js
- * @depend spy.js
- * @depend behavior.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global module, require, sinon*/
-/**
- * Stub functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function stub(object, property, func) {
-        if (!!func && typeof func != "function") {
-            throw new TypeError("Custom stub should be function");
-        }
-
-        var wrapper;
-
-        if (func) {
-            wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
-        } else {
-            wrapper = stub.create();
-        }
-
-        if (!object && typeof property === "undefined") {
-            return sinon.stub.create();
-        }
-
-        if (typeof property === "undefined" && typeof object == "object") {
-            for (var prop in object) {
-                if (typeof object[prop] === "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;
-
-    sinon.extend(stub, (function () {
-        var proto = {
-            create: function create() {
-                var functionStub = function () {
-                    return getCurrentBehavior(functionStub).invoke(this, arguments);
-                };
-
-                functionStub.id = "stub#" + uuid++;
-                var orig = functionStub;
-                functionStub = sinon.spy.create(functionStub);
-                functionStub.func = orig;
-
-                sinon.extend(functionStub, stub);
-                functionStub._create = 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(index) {
-                if (!this.behaviors[index]) {
-                    this.behaviors[index] = sinon.behavior.create(this);
-                }
-
-                return this.behaviors[index];
-            },
-
-            onFirstCall: function() {
-                return this.onCall(0);
-            },
-
-            onSecondCall: function() {
-                return this.onCall(1);
-            },
-
-            onThirdCall: function() {
-                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));
-            }
-        }
-
-        return proto;
-    }()));
-
-    if (commonJSModule) {
-        module.exports = stub;
-    } else {
-        sinon.stub = stub;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- */
-/*jslint eqeqeq: false, onevar: false, nomen: false*/
-/*global module, require, sinon*/
-/**
- * Mock functions.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-    var push = [].push;
-    var match;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    match = sinon.match;
-
-    if (!match && commonJSModule) {
-        match = require("./match");
-    }
-
-    function mock(object) {
-        if (!object) {
-            return sinon.expectation.create("Anonymous mock");
-        }
-
-        return mock.create(object);
-    }
-
-    sinon.mock = mock;
-
-    sinon.extend(mock, (function () {
-        function each(collection, callback) {
-            if (!collection) {
-                return;
-            }
-
-            for (var i = 0, l = collection.length; i < l; i += 1) {
-                callback(collection[i]);
-            }
-        }
-
-        return {
-            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 {
-                    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;
-
-    sinon.expectation = (function () {
-        var slice = Array.prototype.slice;
-        var _invoke = sinon.spy.invoke;
-
-        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;
-            }
-        }
-
-        return {
-            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 _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(message) {
-              sinon.assert.pass(message);
-            },
-            fail: function (message) {
-                var exception = new Error(message);
-                exception.name = "ExpectationError";
-
-                throw exception;
-            }
-        };
-    }());
-
-    if (commonJSModule) {
-        module.exports = mock;
-    } else {
-        sinon.mock = mock;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- * @depend mock.js
- */
-/*jslint eqeqeq: false, onevar: false, forin: true*/
-/*global module, require, sinon*/
-/**
- * Collections of stubs, spies and mocks.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-    var push = [].push;
-    var hasOwnProperty = Object.prototype.hasOwnProperty;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    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);
-        }
-    }
-
-    var collection = {
-        verify: function resolve() {
-            each(this, "verify");
-        },
-
-        restore: function restore() {
-            each(this, "restore");
-            compact(this);
-        },
-
-        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;
-        }
-    };
-
-    if (commonJSModule) {
-        module.exports = collection;
-    } else {
-        sinon.collection = collection;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
-/*global module, require, window*/
-/**
- * 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) {
-    var id = 1;
-
-    function addTimer(args, recurring) {
-        if (args.length === 0) {
-            throw new Error("Function requires at least 1 parameter");
-        }
-
-        if (typeof args[0] === "undefined") {
-            throw new Error("Callback must be provided to timer calls");
-        }
-
-        var toId = id++;
-        var delay = args[1] || 0;
-
-        if (!this.timeouts) {
-            this.timeouts = {};
-        }
-
-        this.timeouts[toId] = {
-            id: toId,
-            func: args[0],
-            callAt: this.now + delay,
-            invokeArgs: Array.prototype.slice.call(args, 2)
-        };
-
-        if (recurring === true) {
-            this.timeouts[toId].interval = delay;
-        }
-
-        return toId;
-    }
-
-    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;
-    }
-
-    function createObject(object) {
-        var newObject;
-
-        if (Object.create) {
-            newObject = Object.create(object);
-        } else {
-            var F = function () {};
-            F.prototype = object;
-            newObject = new F();
-        }
-
-        newObject.Date.clock = newObject;
-        return newObject;
-    }
-
-    sinon.clock = {
-        now: 0,
-
-        create: function create(now) {
-            var clock = createObject(this);
-
-            if (typeof now == "number") {
-                clock.now = now;
-            }
-
-            if (!!now && typeof now == "object") {
-                throw new TypeError("now should be milliseconds since UNIX epoch");
-            }
-
-            return clock;
-        },
-
-        setTimeout: function setTimeout(callback, timeout) {
-            return addTimer.call(this, arguments, false);
-        },
-
-        clearTimeout: function clearTimeout(timerId) {
-            if (!this.timeouts) {
-                this.timeouts = [];
-            }
-
-            if (timerId in this.timeouts) {
-                delete this.timeouts[timerId];
-            }
-        },
-
-        setInterval: function setInterval(callback, timeout) {
-            return addTimer.call(this, arguments, true);
-        },
-
-        clearInterval: function clearInterval(timerId) {
-            this.clearTimeout(timerId);
-        },
-
-        setImmediate: function setImmediate(callback) {
-            var passThruArgs = Array.prototype.slice.call(arguments, 1);
-
-            return addTimer.call(this, [callback, 0].concat(passThruArgs), false);
-        },
-
-        clearImmediate: function clearImmediate(timerId) {
-            this.clearTimeout(timerId);
-        },
-
-        tick: function tick(ms) {
-            ms = typeof ms == "number" ? ms : parseTime(ms);
-            var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
-            var timer = this.firstTimerInRange(tickFrom, tickTo);
-
-            var firstException;
-            while (timer && tickFrom <= tickTo) {
-                if (this.timeouts[timer.id]) {
-                    tickFrom = this.now = timer.callAt;
-                    try {
-                      this.callTimer(timer);
-                    } catch (e) {
-                      firstException = firstException || e;
-                    }
-                }
-
-                timer = this.firstTimerInRange(previous, tickTo);
-                previous = tickFrom;
-            }
-
-            this.now = tickTo;
-
-            if (firstException) {
-              throw firstException;
-            }
-
-            return this.now;
-        },
-
-        firstTimerInRange: function (from, to) {
-            var timer, smallest = null, originalTimer;
-
-            for (var id in this.timeouts) {
-                if (this.timeouts.hasOwnProperty(id)) {
-                    if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
-                        continue;
-                    }
-
-                    if (smallest === null || this.timeouts[id].callAt < smallest) {
-                        originalTimer = this.timeouts[id];
-                        smallest = this.timeouts[id].callAt;
-
-                        timer = {
-                            func: this.timeouts[id].func,
-                            callAt: this.timeouts[id].callAt,
-                            interval: this.timeouts[id].interval,
-                            id: this.timeouts[id].id,
-                            invokeArgs: this.timeouts[id].invokeArgs
-                        };
-                    }
-                }
-            }
-
-            return timer || null;
-        },
-
-        callTimer: function (timer) {
-            if (typeof timer.interval == "number") {
-                this.timeouts[timer.id].callAt += timer.interval;
-            } else {
-                delete this.timeouts[timer.id];
-            }
-
-            try {
-                if (typeof timer.func == "function") {
-                    timer.func.apply(null, timer.invokeArgs);
-                } else {
-                    eval(timer.func);
-                }
-            } catch (e) {
-              var exception = e;
-            }
-
-            if (!this.timeouts[timer.id]) {
-                if (exception) {
-                  throw exception;
-                }
-                return;
-            }
-
-            if (exception) {
-              throw exception;
-            }
-        },
-
-        reset: function reset() {
-            this.timeouts = {};
-        },
-
-        Date: (function () {
-            var NativeDate = Date;
-
-            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 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;
-    }
-
-    var methods = ["Date", "setTimeout", "setInterval",
-                   "clearTimeout", "clearInterval"];
-
-    if (typeof global.setImmediate !== "undefined") {
-        methods.push("setImmediate");
-    }
-
-    if (typeof global.clearImmediate !== "undefined") {
-        methods.push("clearImmediate");
-    }
-
-    function restore() {
-        var method;
-
-        for (var i = 0, l = this.methods.length; i < l; i++) {
-            method = this.methods[i];
-
-            if (global[method].hadOwnProperty) {
-                global[method] = this["_" + method];
-            } else {
-                try {
-                    delete global[method];
-                } catch (e) {}
-            }
-        }
-
-        // Prevent multiple executions which will completely remove these props
-        this.methods = [];
-    }
-
-    function stubGlobal(method, clock) {
-        clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(global, method);
-        clock["_" + method] = global[method];
-
-        if (method == "Date") {
-            var date = mirrorDateProperties(clock[method], global[method]);
-            global[method] = date;
-        } else {
-            global[method] = function () {
-                return clock[method].apply(clock, arguments);
-            };
-
-            for (var prop in clock[method]) {
-                if (clock[method].hasOwnProperty(prop)) {
-                    global[method][prop] = clock[method][prop];
-                }
-            }
-        }
-
-        global[method].clock = clock;
-    }
-
-    sinon.useFakeTimers = function useFakeTimers(now) {
-        var clock = sinon.clock.create(now);
-        clock.restore = restore;
-        clock.methods = Array.prototype.slice.call(arguments,
-                                                   typeof now == "number" ? 1 : 0);
-
-        if (clock.methods.length === 0) {
-            clock.methods = methods;
-        }
-
-        for (var i = 0, l = clock.methods.length; i < l; i++) {
-            stubGlobal(clock.methods[i], clock);
-        }
-
-        return clock;
-    };
-}(typeof global != "undefined" && typeof global !== "function" ? global : this));
-
-sinon.timers = {
-    setTimeout: setTimeout,
-    clearTimeout: clearTimeout,
-    setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
-    clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
-    setInterval: setInterval,
-    clearInterval: clearInterval,
-    Date: Date
-};
-
-if (typeof module !== 'undefined' && module.exports) {
-    module.exports = sinon;
-}
-
-/*jslint eqeqeq: false, onevar: false*/
-/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
-/**
- * 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;
-
-    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;
-    };
-
-    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;
-        }
-    };
-}());
-
-/**
- * @depend ../../sinon.js
- * @depend event.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
-/**
- * Fake XMLHttpRequest object
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-// wrapper for global
-(function(global) {
-    if (typeof sinon === "undefined") {
-        global.sinon = {};
-    }
-
-    var supportsProgress = typeof ProgressEvent !== "undefined";
-    var supportsCustomEvent = typeof CustomEvent !== "undefined";
-    sinon.xhr = { XMLHttpRequest: global.XMLHttpRequest };
-    var xhr = sinon.xhr;
-    xhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
-    xhr.GlobalActiveXObject = global.ActiveXObject;
-    xhr.supportsActiveX = typeof xhr.GlobalActiveXObject != "undefined";
-    xhr.supportsXHR = typeof xhr.GlobalXMLHttpRequest != "undefined";
-    xhr.workingXHR = xhr.supportsXHR ? xhr.GlobalXMLHttpRequest : xhr.supportsActiveX
-                                     ? function() { return new xhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false;
-    xhr.supportsCORS = 'withCredentials' in (new sinon.xhr.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*/
-
-    function FakeXMLHttpRequest() {
-        this.readyState = FakeXMLHttpRequest.UNSENT;
-        this.requestHeaders = {};
-        this.requestBody = null;
-        this.status = 0;
-        this.statusText = "";
-        this.upload = new UploadProgress();
-        if (sinon.xhr.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(event, listener) {
-        this.eventListeners[event].push(listener);
-    };
-
-    UploadProgress.prototype.removeEventListener = function(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(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");
-        }
-    }
-
-    // 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(fn) {
-        this.filters.push(fn)
-    };
-    var IE6Re = /MSIE 6/;
-    FakeXMLHttpRequest.defake = function(fakeXhr,xhrArgs) {
-        var xhr = new sinon.xhr.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() {
-            fakeXhr.readyState = xhr.readyState;
-            if(xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                copyAttrs(["status","statusText"]);
-            }
-            if(xhr.readyState >= FakeXMLHttpRequest.LOADING) {
-                copyAttrs(["responseText"]);
-            }
-            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;
-        }
-    }
-
-    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.responseXML = null;
-            this.requestHeaders = {};
-            this.sendFlag = false;
-            if(sinon.FakeXMLHttpRequest.useFilters === true) {
-                var xhrArgs = arguments;
-                var defake = some(FakeXMLHttpRequest.filters,function(filter) {
-                    return filter.apply(this,xhrArgs)
-                });
-                if (defake) {
-                  return sinon.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);
-                }
-            }
-
-            this.dispatchEvent(new sinon.Event("readystatechange"));
-
-            switch (this.readyState) {
-                case FakeXMLHttpRequest.DONE:
-                    this.dispatchEvent(new sinon.Event("load", false, false, this));
-                    this.dispatchEvent(new sinon.Event("loadend", false, false, this));
-                    this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
-                    if (supportsProgress) {
-                        this.upload.dispatchEvent(new sinon.ProgressEvent('progress', {loaded: 100, total: 100}));
-                    }
-                    break;
-            }
-        },
-
-        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)) {
-                if (this.requestHeaders["Content-Type"]) {
-                    var value = this.requestHeaders["Content-Type"].split(";");
-                    this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8";
-                } else {
-                    this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
-                }
-
-                this.requestBody = data;
-            }
-
-            this.errorFlag = false;
-            this.sendFlag = this.async;
-            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.errorFlag = true;
-            this.requestHeaders = {};
-
-            if (this.readyState > sinon.FakeXMLHttpRequest.UNSENT && this.sendFlag) {
-                this.readyStateChange(sinon.FakeXMLHttpRequest.DONE);
-                this.sendFlag = false;
-            }
-
-            this.readyState = sinon.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 = header.toLowerCase();
-
-            for (var h in this.responseHeaders) {
-                if (h.toLowerCase() == header) {
-                    return this.responseHeaders[h];
-                }
-            }
-
-            return 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
-                }
-            }
-
-            if (this.async) {
-                this.readyStateChange(FakeXMLHttpRequest.DONE);
-            } else {
-                this.readyState = 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));
-            }
-        },
-
-        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
-    });
-
-    // Borrowed from JSpec
-    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",
-        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"
-    };
-
-    sinon.useFakeXMLHttpRequest = function () {
-        sinon.FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
-            if (xhr.supportsXHR) {
-                global.XMLHttpRequest = xhr.GlobalXMLHttpRequest;
-            }
-
-            if (xhr.supportsActiveX) {
-                global.ActiveXObject = xhr.GlobalActiveXObject;
-            }
-
-            delete sinon.FakeXMLHttpRequest.restore;
-
-            if (keepOnCreate !== true) {
-                delete sinon.FakeXMLHttpRequest.onCreate;
-            }
-        };
-        if (xhr.supportsXHR) {
-            global.XMLHttpRequest = sinon.FakeXMLHttpRequest;
-        }
-
-        if (xhr.supportsActiveX) {
-            global.ActiveXObject = function ActiveXObject(objId) {
-                if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
-
-                    return new sinon.FakeXMLHttpRequest();
-                }
-
-                return new xhr.GlobalActiveXObject(objId);
-            };
-        }
-
-        return sinon.FakeXMLHttpRequest;
-    };
-
-    sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
-
-})(typeof global === "object" ? global : this);
-
-if (typeof module !== 'undefined' && module.exports) {
-    module.exports = sinon;
-}
-
-/**
- * @depend fake_xml_http_request.js
- */
-/*jslint eqeqeq: false, onevar: false, regexp: false, plusplus: false*/
-/*global module, require, window*/
-/**
- * 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 = {};
-}
-
-sinon.fakeServer = (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 log(response, request) {
-        var str;
-
-        str =  "Request:\n"  + sinon.format(request)  + "\n\n";
-        str += "Response:\n" + sinon.format(response) + "\n\n";
-
-        sinon.log(str);
-    }
-
-    return {
-        create: function () {
-            var server = create(this);
-            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.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);
-            }
-        },
-
-        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);
-            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) {
-                    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);
-        }
-    };
-}());
-
-if (typeof module !== 'undefined' && module.exports) {
-    module.exports = sinon;
-}
-
-/**
- * @depend fake_server.js
- * @depend fake_timers.js
- */
-/*jslint browser: true, eqeqeq: false, onevar: false*/
-/*global sinon*/
-/**
- * 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 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);
-    };
-}());
-
-/**
- * @depend ../sinon.js
- * @depend collection.js
- * @depend util/fake_timers.js
- * @depend util/fake_server_with_clock.js
- */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global require, module*/
-/**
- * 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
- */
-
-if (typeof module !== 'undefined' && module.exports) {
-    var sinon = require("../sinon");
-    sinon.extend(sinon, require("./util/fake_timers"));
-}
-
-(function () {
-    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;
-            }
-
-            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;
-        }
-    });
-
-    sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
-
-    if (typeof module !== 'undefined' && module.exports) {
-        module.exports = sinon.sandbox;
-    }
-}());
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- * @depend mock.js
- * @depend sandbox.js
- */
-/*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Test function, sandboxes fakes
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function test(callback) {
-        var type = typeof callback;
-
-        if (type != "function") {
-            throw new TypeError("sinon.test needs to wrap a test function, got " + type);
-        }
-
-        return function () {
-            var config = sinon.getConfig(sinon.config);
-            config.injectInto = config.injectIntoThis && this || config.injectInto;
-            var sandbox = sinon.sandbox.create(config);
-            var exception, result;
-            var args = Array.prototype.slice.call(arguments).concat(sandbox.args);
-
-            try {
-                result = callback.apply(this, args);
-            } catch (e) {
-                exception = e;
-            }
-
-            if (typeof exception !== "undefined") {
-                sandbox.restore();
-                throw exception;
-            }
-            else {
-                sandbox.verifyAndRestore();
-            }
-
-            return result;
-        };
-    }
-
-    test.config = {
-        injectIntoThis: true,
-        injectInto: null,
-        properties: ["spy", "stub", "mock", "clock", "server", "requests"],
-        useFakeTimers: true,
-        useFakeServer: true
-    };
-
-    if (commonJSModule) {
-        module.exports = test;
-    } else {
-        sinon.test = test;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend test.js
- */
-/*jslint eqeqeq: false, onevar: false, eqeqeq: false*/
-/*global module, require, sinon*/
-/**
- * Test case, sandboxes all test functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon || !Object.prototype.hasOwnProperty) {
-        return;
-    }
-
-    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 testCase(tests, prefix) {
-        /*jsl:ignore*/
-        if (!tests || typeof tests != "object") {
-            throw new TypeError("sinon.testCase needs an object with test functions");
-        }
-        /*jsl:end*/
-
-        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)) {
-                property = tests[testName];
-
-                if (/^(setUp|tearDown)$/.test(testName)) {
-                    continue;
-                }
-
-                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;
-    }
-
-    if (commonJSModule) {
-        module.exports = testCase;
-    } else {
-        sinon.testCase = testCase;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- */
-/*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * 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 commonJSModule = typeof module !== "undefined" && module.exports;
-    var slice = Array.prototype.slice;
-    var assert;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    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 (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.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 != "export" && (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");
-
-    if (commonJSModule) {
-        module.exports = assert;
-    } else {
-        sinon.assert = assert;
-    }
-}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
-
-return sinon;}.call(typeof window != 'undefined' && window || {}));
diff --git a/resources/lib/sinonjs/sinon-ie-1.10.3.js b/resources/lib/sinonjs/sinon-ie-1.10.3.js
new file mode 100644 (file)
index 0000000..de8c23d
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+ * Sinon.JS 1.10.3, 2014/07/11
+ *
+ * @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.
+ */
+
+/*global sinon, setTimeout, setInterval, clearTimeout, clearInterval, Date*/
+/**
+ * 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
+ */
+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;
+
+/*global sinon*/
+/**
+ * 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
+ */
+function XMLHttpRequest() {}
+
+// Reassign the original function. Now its writable attribute
+// should be true. Hackish, I know, but it works.
+XMLHttpRequest = sinon.xhr.XMLHttpRequest || undefined;
+/*global sinon*/
+/**
+ * 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.
+ */
+function XDomainRequest() {}
+
+// Reassign the original function. Now its writable attribute
+// should be true. Hackish, I know, but it works.
+XDomainRequest = sinon.xdr.XDomainRequest || undefined;
diff --git a/resources/lib/sinonjs/sinon-ie-1.9.0.js b/resources/lib/sinonjs/sinon-ie-1.9.0.js
deleted file mode 100644 (file)
index c9fbd9d..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Sinon.JS 1.9.0, 2014/03/05
- *
- * @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.
- */
-
-/*global sinon, setTimeout, setInterval, clearTimeout, clearInterval, Date*/
-/**
- * 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
- */
-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;
-
-/*global sinon*/
-/**
- * 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
- */
-function XMLHttpRequest() {}
-
-// Reassign the original function. Now its writable attribute
-// should be true. Hackish, I know, but it works.
-XMLHttpRequest = sinon.xhr.XMLHttpRequest || undefined;
index d14c64b..a4039d8 100644 (file)
@@ -2,14 +2,17 @@
  * Skip function for es5-shim module.
  *
  * Test for strict mode as a proxy for full ES5 function support (but not syntax)
- * Per http://kangax.github.io/compat-table/es5/ this is a reasonable short-cut
- * that still allows this to be as short as possible (there are no function "No"s
- * for non-"obsolete" real browsers where strict support is available).
+ * Per http://kangax.github.io/compat-table/es5/ this is a reasonable shortcut
+ * that still allows this to be as short as possible (there are no browsers we
+ * support that have strict mode, but lack other features).
  *
- * Note that this will cause IE9 users to get the shim (which should be close to
- * a no-op but will increase page payload).
+ * Do explicitly test for Function#bind because of PhantomJS (which implements
+ * strict mode, but lacks Function#bind).
+ *
+ * IE9 supports all features except strict mode, so loading es5-shim should be close to
+ * a no-op but does increase page payload).
  */
 return ( function () {
        'use strict';
-       return !this;
+       return !this && !!Function.prototype.bind;
 }() );
index 915cd85..f38decd 100644 (file)
@@ -1,4 +1,6 @@
 ( function ( mw, $ ) {
+       // @deprecated since 1.24.  The 'jquery.json' module will be removed in MW 1.25.  Use the 'json' module.
+
        mw.log.deprecate( $, 'toJSON', $.toJSON, 'Use JSON.stringify instead (module "json" for polyfill).' );
        mw.log.deprecate( $, 'evalJSON', $.evalJSON, 'Use JSON.parse instead (module "json" for polyfill).' );
        mw.log.deprecate( $, 'secureEvalJSON', $.secureEvalJSON, 'Use JSON.parse instead (module "json" for polyfill).' );
diff --git a/resources/src/jquery.ui-themes/vector/images/close.png b/resources/src/jquery.ui-themes/vector/images/close.png
deleted file mode 100644 (file)
index ef0dd9e..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/close.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/titlebar-fade.png b/resources/src/jquery.ui-themes/vector/images/titlebar-fade.png
deleted file mode 100644 (file)
index 12a80c8..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/titlebar-fade.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-anim_basic_16x16.gif b/resources/src/jquery.ui-themes/vector/images/ui-anim_basic_16x16.gif
deleted file mode 100644 (file)
index 085ccae..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-anim_basic_16x16.gif and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png
deleted file mode 100644 (file)
index 09de537..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_flat_70_000000_40x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_flat_70_000000_40x100.png
deleted file mode 100644 (file)
index c06dd56..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-bg_flat_70_000000_40x100.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png
deleted file mode 100644 (file)
index 5308b46..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png
deleted file mode 100644 (file)
index 0c8997f..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png
deleted file mode 100644 (file)
index 3149255..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png
deleted file mode 100644 (file)
index 09b2376..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png
deleted file mode 100644 (file)
index 66627c1..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png
deleted file mode 100644 (file)
index ccb6dc0..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-icons_2694e8_256x240.png b/resources/src/jquery.ui-themes/vector/images/ui-icons_2694e8_256x240.png
deleted file mode 100644 (file)
index 998ac3b..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-icons_2694e8_256x240.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-icons_2e83ff_256x240.png b/resources/src/jquery.ui-themes/vector/images/ui-icons_2e83ff_256x240.png
deleted file mode 100644 (file)
index 34e38d1..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-icons_2e83ff_256x240.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-icons_3d80b3_256x240.png b/resources/src/jquery.ui-themes/vector/images/ui-icons_3d80b3_256x240.png
deleted file mode 100644 (file)
index ec129a8..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-icons_3d80b3_256x240.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-icons_666666_256x240.png b/resources/src/jquery.ui-themes/vector/images/ui-icons_666666_256x240.png
deleted file mode 100644 (file)
index a32c57d..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-icons_666666_256x240.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-icons_72a7cf_256x240.png b/resources/src/jquery.ui-themes/vector/images/ui-icons_72a7cf_256x240.png
deleted file mode 100644 (file)
index 88fad1a..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-icons_72a7cf_256x240.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-icons_ffffff_256x240.png b/resources/src/jquery.ui-themes/vector/images/ui-icons_ffffff_256x240.png
deleted file mode 100644 (file)
index 29ba7d2..0000000
Binary files a/resources/src/jquery.ui-themes/vector/images/ui-icons_ffffff_256x240.png and /dev/null differ
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.accordion.css b/resources/src/jquery.ui-themes/vector/jquery.ui.accordion.css
deleted file mode 100644 (file)
index 8d8a1a6..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* Accordion
-----------------------------------*/
-.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
-.ui-accordion .ui-accordion-li-fix { display: inline; }
-.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
-.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
-/* IE7-/Win - Fix extra vertical space in lists */
-.ui-accordion a { zoom: 1; }
-.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
-.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
-.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
-.ui-accordion .ui-accordion-content-active { display: block; }
\ No newline at end of file
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.autocomplete.css b/resources/src/jquery.ui-themes/vector/jquery.ui.autocomplete.css
deleted file mode 100644 (file)
index da6de45..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Autocomplete
-----------------------------------*/
-.ui-autocomplete { position: absolute; cursor: default; }
-.ui-autocomplete-loading { /* @embed */ background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; }
-
-/* workarounds */
-* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
-
-/* Menu
-----------------------------------*/
-.ui-menu {
-       list-style:none;
-       padding: 2px;
-       margin: 0;
-       display:block;
-       float: left;
-}
-.ui-menu .ui-menu {
-       margin-top: -3px;
-}
-.ui-menu .ui-menu-item {
-       margin:0;
-       padding: 0;
-       zoom: 1;
-       float: left;
-       clear: left;
-       width: 100%;
-}
-.ui-menu .ui-menu-item a {
-       text-decoration:none;
-       display:block;
-       padding:.2em .4em;
-       line-height:1.5;
-       zoom:1;
-}
-.ui-menu .ui-menu-item a.ui-state-hover,
-.ui-menu .ui-menu-item a.ui-state-active {
-       font-weight: normal;
-       margin: -1px;
-}
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.button.css b/resources/src/jquery.ui-themes/vector/jquery.ui.button.css
deleted file mode 100644 (file)
index 8c2286d..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-/* Button
-----------------------------------*/
-
-.ui-button {
-       display: inline-block;
-       position: relative;
-       padding: 0;
-       margin-right: .1em;
-       text-decoration: none !important;
-       cursor: pointer;
-       text-align: center;
-       zoom: 1;
-       overflow: visible; /* the overflow property removes extra width in IE */
-}
-
-/*button text element */
-.ui-button .ui-button-text {
-       display: block;
-       line-height: 1.4;
-       text-shadow: 0 1px 1px #fff;
-}
-.ui-button-text-only .ui-button-text {
-       padding: 0.3em 1em 0.25em 1em;
-}
-.ui-button-icon-only .ui-button-text,
-.ui-button-icons-only .ui-button-text {
-       padding: 0.3em;
-       text-indent: -9999999px;
-}
-.ui-button-text-icon-primary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
-       padding: 0.3em 1em 0.25em 2.1em;
-}
-.ui-button-text-icon-secondary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
-       padding: 0.3em 2.1em 0.25em 1em;
-}
-.ui-button-text-icons .ui-button-text {
-       padding-left: 2.1em;
-       padding-right: 2.1em;
-}
-
-/* no icon support for input elements, provide padding by default */
-input.ui-button {
-       padding: 0.3em 1em;
-}
-
-/*button icon element(s) */
-.ui-button-icon-only .ui-icon,
-.ui-button-text-icon-primary .ui-icon,
-.ui-button-text-icon-secondary .ui-icon,
-.ui-button-text-icons .ui-icon,
-.ui-button-text-icon .ui-icon,
-.ui-button-icons-only .ui-icon {
-       position: absolute;
-       top: 50%;
-       margin-top: -9px;
-}
-.ui-button-icon-only .ui-icon {
-       left: 50%;
-       margin-left: -8px;
-}
-.ui-button-text-icon-primary .ui-button-icon-primary,
-.ui-button-text-icon .ui-button-icon-primary,
-.ui-button-text-icons .ui-button-icon-primary,
-.ui-button-icons-only .ui-button-icon-primary {
-       left: 0.5em;
-}
-.ui-button-text-icon-secondary .ui-button-icon-secondary,
-.ui-button-text-icon .ui-button-icon-secondary,
-.ui-button-text-icons .ui-button-icon-secondary,
-.ui-button-icons-only .ui-button-icon-secondary {
-       right: 0.5em;
-}
-
-/*button sets*/
-.ui-buttonset {
-       margin-right: 7px;
-}
-.ui-buttonset .ui-button {
-       margin-left: 0;
-       margin-right: -.4em;
-}
-
-/* workarounds */
-button.ui-button::-moz-focus-inner {
-       border: 0;
-       padding: 0; /* reset extra padding in Firefox */
-}
-/* Disables the annoying dashed border Firefox puts on active buttons */
-body button.ui-button::-moz-focus-inner {
-       border: 0;
-}
-/* Give large buttons some extra padding */
-body .ui-button-large {
-       padding: 5px;
-}
-/* Use white icons for colored buttons */
-.ui-button-green .ui-icon,
-.ui-button-blue .ui-icon,
-.ui-button-red .ui-icon,
-.ui-button-orange .ui-icon {
-       /* @embed */
-       background-image: url(images/ui-icons_ffffff_256x240.png) !important;
-}
-
-/* Corner radius */
-/* This is normally handled in jquery.ui.theme.css, but in our case, the corner
-   styling of our buttons doesn't match our default widget corner styling */
-.ui-button.ui-corner-all,
-.ui-button.ui-corner-top,
-.ui-button.ui-corner-left,
-.ui-button.ui-corner-tl {
-       border-top-left-radius: 4px;
-}
-.ui-button.ui-corner-all,
-.ui-button.ui-corner-top,
-
-.ui-button.ui-corner-right,
-.ui-button.ui-corner-tr {
-       border-top-right-radius: 4px;
-}
-.ui-button.ui-corner-all,
-.ui-button.ui-corner-bottom,
-.ui-button.ui-corner-left,
-.ui-button.ui-corner-bl {
-       border-bottom-left-radius: 4px;
-}
-.ui-button.ui-corner-all,
-.ui-button.ui-corner-bottom,
-.ui-button.ui-corner-right,
-.ui-button.ui-corner-br {
-       border-bottom-right-radius: 4px;
-}
-
-body .ui-button {
-       color: #2779aa;
-       margin: 0.5em 0 0.5em 0.4em;
-       border: 1px solid #aaa !important;
-       background: #f0f0f0 !important;
-       background: -moz-linear-gradient(top, #fff 0%, #ddd 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #fff 0%, #ddd 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #fff 0%, #ddd 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #fff 0%, #ddd 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #fff 0%, #ddd 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#dddddd', GradientType=0); /* IE6-8 */
-       cursor: pointer;
-       font-size: 1em;
-       line-height: 1.4em;
-       width: auto;
-       overflow: visible;
-       box-shadow: 0 1px 3px rgba(0,0,0,.2);
-}
-
-body .ui-button-icon-only {
-       width: 2.2em;
-}
-
-body .ui-button-icons-only {
-       width: 3.4em;
-}
-
-body .ui-button:hover {
-       color: #2779aa;
-       border-color: #bbb !important;
-       background: #fff !important;
-       background: -moz-linear-gradient(top, #fff 0%, #eee 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #fff 0%, #eee 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #fff 0%, #eee 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #fff 0%, #eee 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #fff 0%, #eee 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); /* IE6-8 */
-       box-shadow: 0 1px 3px rgba(0,0,0,.1);
-}
-body .ui-button:active,
-body .ui-button:focus {
-       border-color: #8ad !important;
-       box-shadow: 0 0 1px 1px rgba(167,215,249,.5);
-}
-body .ui-button:active {
-       background: #e0e0e0 !important;
-       background: -moz-linear-gradient(top, #f0f0f0 0%, #d0d0d0 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #f0f0f0 0%, #d0d0d0 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #f0f0f0 0%, #d0d0d0 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #f0f0f0 0%, #d0d0d0 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #f0f0f0 0%, #d0d0d0 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f0f0f0', endColorstr='#d0d0d0', GradientType=0); /* IE6-8 */
-}
-
-/* Green buttons */
-body .ui-button-green,
-body .ui-button-green .ui-button-text {
-       color: white;
-       text-shadow: 0 -1px 1px #072;
-}
-body .ui-button.ui-button-green {
-       border-color: #294 !important;
-       background: #295 !important;
-       background: -moz-linear-gradient(top, #3c8 0%, #295 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #3c8 0%, #295 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #3c8 0%, #295 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #3c8 0%, #295 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #3c8 0%, #295 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#33cc88', endColorstr='#229955', GradientType=0); /* IE6-8 */
-       box-shadow: 0 1px 3px rgba(0,0,0,.3);
-}
-body .ui-button.ui-button-green:hover {
-       background: #33a055 !important;
-       background: -moz-linear-gradient(top, #44d388 0%, #33a055 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #44d388 0%, #33a055 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #44d388 0%, #33a055 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #44d388 0%, #33a055 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #44d388 0%, #33a055 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#44d388', endColorstr='#33a055', GradientType=0); /* IE6-8 */
-       box-shadow: 0 1px 3px rgba(0,0,0,.25);
-}
-body .ui-button.ui-button-green:active,
-body .ui-button.ui-button-green:focus {
-       border-color: #172 !important;
-       box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
-}
-body .ui-button.ui-button-green:active {
-       background: #338855 !important;
-       background: -moz-linear-gradient(top, #30c080 0%, #338855 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #30c080 0%, #338855 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #30c080 0%, #338855 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #30c080 0%, #338855 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #30c080 0%, #338855 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#30c080', endColorstr='#338855', GradientType=0); /* IE6-8 */
-}
-
-/* Blue buttons */
-body .ui-button-blue,
-body .ui-button-blue .ui-button-text {
-       color: white;
-       text-shadow: 0 -1px 1px #037;
-}
-body .ui-button.ui-button-blue {
-       border-color: #468 !important;
-       background: #36b !important;
-       background: -moz-linear-gradient(top, #48e 0%, #36b 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #48e 0%, #36b 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #48e 0%, #36b 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #48e 0%, #36b 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #48e 0%, #36b 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4488ee', endColorstr='#3366bb', GradientType=0); /* IE6-8 */
-       box-shadow: 0 1px 3px rgba(0,0,0,.35);
-}
-body .ui-button.ui-button-blue:hover {
-       background: #36c !important;
-       background: -moz-linear-gradient(top, #59e 0%, #36c 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #59e 0%, #36c 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #59e 0%, #36c 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #59e 0%, #36c 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #59e 0%, #36c 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5599ee', endColorstr='#3366cc', GradientType=0); /* IE6-8 */
-}
-body .ui-button.ui-button-blue:active,
-body .ui-button.ui-button-blue:focus {
-       border-color: #357 !important;
-       box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
-}
-body .ui-button.ui-button-blue:active {
-       background: #3060a0 !important;
-       background: -moz-linear-gradient(top, #4080e0 0%, #3060a0 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #4080e0 0%, #3060a0 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #4080e0 0%, #3060a0 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #4080e0 0%, #3060a0 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #4080e0 0%, #3060a0 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4080e0', endColorstr='#3060a0', GradientType=0); /* IE6-8 */
-}
-
-/* Red buttons */
-body .ui-button-red,
-body .ui-button-red .ui-button-text {
-       color: white;
-       text-shadow: 0 -1px 1px #700;
-}
-body .ui-button.ui-button-red {
-       border-color: #944 !important;
-       background: #a22 !important;
-       background: -moz-linear-gradient(top, #d44 0%, #a22 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #d44 0%, #a22 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #d44 0%, #a22 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #d44 0%, #a22 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #d44 0%, #a22 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dd4444', endColorstr='#aa2222', GradientType=0); /* IE6-8 */
-       box-shadow: 0 1px 3px rgba(0,0,0,.35);
-}
-body .ui-button.ui-button-red:hover {
-       border-color: #a44 !important;
-       background: #b03333 !important;
-       background: -moz-linear-gradient(top, #ee4646 0%, #b03333 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #ee4646 0%, #b03333 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #ee4646 0%, #b03333 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #ee4646 0%, #b03333 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #ee4646 0%, #b03333 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee4646', endColorstr='#b03333', GradientType=0); /* IE6-8 */
-       box-shadow: 0 1px 3px rgba(0,0,0,.3);
-}
-body .ui-button.ui-button-red:active,
-body .ui-button.ui-button-red:focus {
-       border-color: #747 !important;
-       box-shadow: 0 0 2px 2px rgba(167,215,249,.7);
-}
-body .ui-button.ui-button-red:active {
-       background: #952020 !important;
-       background: -moz-linear-gradient(top, #d04545 0%, #952020 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #d04545 0%, #952020 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #d04545 0%, #952020 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #d04545 0%, #952020 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #d04545 0%, #952020 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#d04545', endColorstr='#952020', GradientType=0); /* IE6-8 */
-}
-
-/* Disabled buttons */
-body .ui-button-green.disabled,
-body .ui-button-green.disabled:hover,
-body .ui-button-green.disabled:active,
-body .ui-button-green.disabled:focus,
-body .ui-button-blue.disabled,
-body .ui-button-blue.disabled:hover,
-body .ui-button-blue.disabled:active,
-body .ui-button-blue.disabled:focus,
-body .ui-button-red.disabled,
-body .ui-button-red.disabled:hover,
-body .ui-button-red.disabled:active,
-body .ui-button-red.disabled:focus,
-body .ui-button.disabled,
-body .ui-button.disabled:hover {
-       color: #aaa;
-       border-color: #ccc !important;
-       background: #eee !important;
-       background: -moz-linear-gradient(top, #f6f6f6 0%, #eee 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #f6f6f6 0%, #eee 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #f6f6f6 0%, #eee 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #f6f6f6 0%, #eee 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #f6f6f6 0%, #eee 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6f6f6', endColorstr='#eeeeee', GradientType=0); /* IE6-8 */
-       box-shadow: 0 1px 3px rgba(0,0,0,0);
-}
-body .ui-button-green.disabled .ui-button-text,
-body .ui-button-blue.disabled .ui-button-text,
-body .ui-button-red.disabled .ui-button-text {
-       color: #aaa;
-       text-shadow: 0 1px 1px #fff;
-}
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.core.css b/resources/src/jquery.ui-themes/vector/jquery.ui.core.css
deleted file mode 100644 (file)
index 1931aad..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-* jQuery UI CSS Framework
-* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
-* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
-*/
-
-/* Layout helpers
-----------------------------------*/
-.ui-helper-hidden { display: none; }
-.ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
-.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
-.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
-.ui-helper-clearfix { display: inline-block; }
-/* required comment for clearfix to work in Opera \*/
-* html .ui-helper-clearfix { height:1%; }
-.ui-helper-clearfix { display:block; }
-/* end clearfix */
-.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
-
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-disabled { cursor: default !important; }
-
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Overlays */
-.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.datepicker.css b/resources/src/jquery.ui-themes/vector/jquery.ui.datepicker.css
deleted file mode 100644 (file)
index 871bf69..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Datepicker
-----------------------------------*/
-.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
-.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
-.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
-.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
-.ui-datepicker .ui-datepicker-prev { left:2px; }
-.ui-datepicker .ui-datepicker-next { right:2px; }
-.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
-.ui-datepicker .ui-datepicker-next-hover { right:1px; }
-.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
-.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
-.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; padding:1px 0; }
-.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
-.ui-datepicker select.ui-datepicker-month, 
-.ui-datepicker select.ui-datepicker-year { width: 49%;}
-.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
-.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
-.ui-datepicker td { border: 0; padding: 1px; }
-.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
-.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .2em 0 0 0; padding: 0 .2em; border-top: 1px solid #DDDDDD; border-left: 0; border-right: 0; border-bottom: 0; }
-.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi { width:auto; }
-.ui-datepicker-multi .ui-datepicker-group { float:left; }
-.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
-.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
-.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
-.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
-.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
-.ui-datepicker-row-break { clear:both; width:100%; }
-
-/* RTL support */
-/* @noflip */ .ui-datepicker-rtl { direction: rtl; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-group { float:right; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
-
-/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
-.ui-datepicker-cover {
-    display: none; /*sorry for IE5*/
-    display/**/: block; /*sorry for IE5*/
-    position: absolute; /*must have*/
-    z-index: -1; /*must have*/
-    filter: mask(); /*must have*/
-    top: -4px; /*must have*/
-    left: -4px; /*must have*/
-    width: 200px; /*must have*/
-    height: 200px; /*must have*/
-}
\ No newline at end of file
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.dialog.css b/resources/src/jquery.ui-themes/vector/jquery.ui.dialog.css
deleted file mode 100644 (file)
index cd85f14..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Dialog
-----------------------------------*/
-.ui-dialog { position: absolute; padding: 0; width: 300px; }
-.ui-dialog .ui-dialog-titlebar { padding: .75em; position: relative;  }
-.ui-dialog .ui-dialog-title { float: left; margin: 0; } 
-.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .75em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
-.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
-.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
-.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
-.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
-.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
-.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
-.ui-draggable .ui-dialog-titlebar { cursor: move; }
-/* Customizations */
-body .ui-dialog .ui-dialog-titlebar-close:hover {
-       text-decoration: none;
-}
-body .ui-dialog .ui-dialog-content .status-invalid input {
-       border: 2px solid red;
-       padding: 2px 1px;
-}
-body .ui-dialog .ui-dialog-titlebar {
-       padding: 0.9em 1.4em 0.6em !important;
-}
-body .ui-dialog .ui-widget-header {
-       /* @embed */
-       background: #f0f0f0 url(images/titlebar-fade.png) repeat-x scroll 50% 100% !important;
-}
-/* FIXME: Should just update the icon sprite if we're keeping this X */
-body .ui-dialog .ui-icon-closethick {
-       /* @embed */
-       background: url(images/close.png) no-repeat 50% 50% !important;
-}
-body .ui-dialog .ui-dialog-buttonpane {
-       margin-top: 0 !important;
-       padding:0.3em 1.4em 0.5em 1.4em !important;
-}
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.progressbar.css b/resources/src/jquery.ui-themes/vector/jquery.ui.progressbar.css
deleted file mode 100644 (file)
index bc0939e..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Progressbar
-----------------------------------*/
-.ui-progressbar { height:2em; text-align: left; }
-.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.resizable.css b/resources/src/jquery.ui-themes/vector/jquery.ui.resizable.css
deleted file mode 100644 (file)
index f1bd7c5..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Resizable
-----------------------------------*/
-.ui-resizable { position: relative;}
-.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
-.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
-.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
-.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
-/* @noflip */
-.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
-/* @noflip */
-.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
-/* @noflip */
-.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
-/* @noflip */
-.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
-/* @noflip */
-.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
-/* @noflip */
-.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
\ No newline at end of file
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.selectable.css b/resources/src/jquery.ui-themes/vector/jquery.ui.selectable.css
deleted file mode 100644 (file)
index c5d46ce..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-/* Selectable
-----------------------------------*/
-.ui-selectable-helper { border:1px dotted black }
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.slider.css b/resources/src/jquery.ui-themes/vector/jquery.ui.slider.css
deleted file mode 100644 (file)
index 07c6f4e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Slider
-----------------------------------*/
-.ui-slider { position: relative; text-align: left; }
-.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
-.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
-
-.ui-slider-horizontal { height: .8em; }
-.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
-.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
-.ui-slider-horizontal .ui-slider-range-min { left: 0; }
-.ui-slider-horizontal .ui-slider-range-max { right: 0; }
-
-.ui-slider-vertical { width: .8em; height: 100px; }
-.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
-.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
-.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
-.ui-slider-vertical .ui-slider-range-max { top: 0; }
\ No newline at end of file
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.tabs.css b/resources/src/jquery.ui-themes/vector/jquery.ui.tabs.css
deleted file mode 100644 (file)
index 99e16db..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Tabs
-----------------------------------*/
-.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
-.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
-.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
-.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
-.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
-.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
-.ui-tabs .ui-tabs-hide { display: none !important; }
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.theme.css b/resources/src/jquery.ui-themes/vector/jquery.ui.theme.css
deleted file mode 100644 (file)
index 8f46645..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-
-
-/*
-* jQuery UI CSS Framework
-* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
-* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=sans-serif&fwDefault=normal&fsDefault=1.0em&cornerRadius=3px&bgColorHeader=ffffff&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=100&borderColorHeader=aed0ea&fcHeader=222222&iconColorHeader=72a7cf&bgColorContent=f2f5f7&bgTextureContent=04_highlight_hard.png&bgImgOpacityContent=100&borderColorContent=cccccc&fcContent=362b36&iconColorContent=72a7cf&bgColorDefault=d7ebf9&bgTextureDefault=04_highlight_hard.png&bgImgOpacityDefault=80&borderColorDefault=aed0ea&fcDefault=2779aa&iconColorDefault=3d80b3&bgColorHover=e4f1fb&bgTextureHover=03_highlight_soft.png&bgImgOpacityHover=100&borderColorHover=74b2e2&fcHover=0070a3&iconColorHover=2694e8&bgColorActive=f0f0f0&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=cccccc&fcActive=000000&iconColorActive=666666&bgColorHighlight=ffef8f&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=25&borderColorHighlight=f9dd34&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=cd0a0a&bgTextureError=01_flat.png&bgImgOpacityError=15&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffffff&bgColorOverlay=000000&bgTextureOverlay=21_glow_ball.png&bgImgOpacityOverlay=100&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=70&opacityShadow=20&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px
-*/
-
-
-/* Component containers
-----------------------------------*/
-.ui-widget { font-family: sans-serif; font-size: 0.8em; }
-.ui-widget .ui-widget { font-size: 1em; }
-.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: sans-serif; font-size: 1em; }
-.ui-widget-content { border: 1px solid #cccccc; /* @embed */ background: #f2f5f7 url(images/ui-bg_highlight-hard_100_f2f5f7_1x100.png) 50% top repeat-x; color: #362b36; }
-.ui-widget-content a { color: #362b36; }
-.ui-widget-header { border-bottom: 1px solid #bbbbbb; line-height: 1em; /* @embed */ background: #ffffff url(images/ui-bg_highlight-soft_100_ffffff_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
-.ui-widget-header a { color: #222222; }
-
-/* Interaction states
-----------------------------------*/
-.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #aed0ea; /* @embed */ background: #d7ebf9 url(images/ui-bg_highlight-hard_80_d7ebf9_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #2779aa; }
-.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2779aa; text-decoration: none; }
-.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #74b2e2; /* @embed */ background: #e4f1fb url(images/ui-bg_highlight-soft_100_e4f1fb_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #0070a3; }
-.ui-state-hover a, .ui-state-hover a:hover { color: #0070a3; text-decoration: none; }
-.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #cccccc; background: #f0f0f0 /* @embed */ url(images/ui-bg_inset-hard_100_f0f0f0_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #000000; }
-.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #000000; text-decoration: none; }
-.ui-widget :active { outline: none; }
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #f9dd34; background: #ffef8f /* @embed */ url(images/ui-bg_highlight-soft_25_ffef8f_1x100.png) 50% top repeat-x; color: #363636; }
-.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
-.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #cd0a0a /* @embed */ url(images/ui-bg_flat_15_cd0a0a_40x100.png) 50% 50% repeat-x; color: #ffffff; }
-.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
-.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
-.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
-.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
-.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon { width: 16px; height: 16px; }
-.ui-icon, .ui-widget-content .ui-icon, .ui-widget-header .ui-icon { /* @embed */ background-image: url(images/ui-icons_72a7cf_256x240.png); }
-.ui-state-default .ui-icon { /* @embed */ background-image: url(images/ui-icons_3d80b3_256x240.png); }
-.ui-state-hover .ui-icon, .ui-state-focus .ui-icon { /* @embed */ background-image: url(images/ui-icons_2694e8_256x240.png); }
-.ui-state-active .ui-icon { /* @embed */ background-image: url(images/ui-icons_666666_256x240.png); }
-.ui-state-highlight .ui-icon { /* @embed */ background-image: url(images/ui-icons_2e83ff_256x240.png); }
-.ui-state-error .ui-icon, .ui-state-error-text .ui-icon { /* @embed */ background-image: url(images/ui-icons_ffffff_256x240.png); }
-
-/* positioning */
-.ui-icon-carat-1-n { background-position: 0 0; }
-.ui-icon-carat-1-ne { background-position: -16px 0; }
-.ui-icon-carat-1-e { background-position: -32px 0; }
-.ui-icon-carat-1-se { background-position: -48px 0; }
-.ui-icon-carat-1-s { background-position: -64px 0; }
-.ui-icon-carat-1-sw { background-position: -80px 0; }
-.ui-icon-carat-1-w { background-position: -96px 0; }
-.ui-icon-carat-1-nw { background-position: -112px 0; }
-.ui-icon-carat-2-n-s { background-position: -128px 0; }
-.ui-icon-carat-2-e-w { background-position: -144px 0; }
-.ui-icon-triangle-1-n { background-position: 0 -16px; }
-.ui-icon-triangle-1-ne { background-position: -16px -16px; }
-.ui-icon-triangle-1-e { background-position: -32px -16px; }
-.ui-icon-triangle-1-se { background-position: -48px -16px; }
-.ui-icon-triangle-1-s { background-position: -64px -16px; }
-.ui-icon-triangle-1-sw { background-position: -80px -16px; }
-.ui-icon-triangle-1-w { background-position: -96px -16px; }
-.ui-icon-triangle-1-nw { background-position: -112px -16px; }
-.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
-.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
-.ui-icon-arrow-1-n { background-position: 0 -32px; }
-.ui-icon-arrow-1-ne { background-position: -16px -32px; }
-.ui-icon-arrow-1-e { background-position: -32px -32px; }
-.ui-icon-arrow-1-se { background-position: -48px -32px; }
-.ui-icon-arrow-1-s { background-position: -64px -32px; }
-.ui-icon-arrow-1-sw { background-position: -80px -32px; }
-.ui-icon-arrow-1-w { background-position: -96px -32px; }
-.ui-icon-arrow-1-nw { background-position: -112px -32px; }
-.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
-.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
-.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
-.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
-.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
-.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
-.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
-.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
-.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
-.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
-.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
-.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
-.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
-.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
-.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
-.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
-.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
-.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
-.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
-.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
-.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
-.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
-.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
-.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
-.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
-.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
-.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
-.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
-.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
-.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
-.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
-.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
-.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
-.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
-.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
-.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
-.ui-icon-arrow-4 { background-position: 0 -80px; }
-.ui-icon-arrow-4-diag { background-position: -16px -80px; }
-.ui-icon-extlink { background-position: -32px -80px; }
-.ui-icon-newwin { background-position: -48px -80px; }
-.ui-icon-refresh { background-position: -64px -80px; }
-.ui-icon-shuffle { background-position: -80px -80px; }
-.ui-icon-transfer-e-w { background-position: -96px -80px; }
-.ui-icon-transferthick-e-w { background-position: -112px -80px; }
-.ui-icon-folder-collapsed { background-position: 0 -96px; }
-.ui-icon-folder-open { background-position: -16px -96px; }
-.ui-icon-document { background-position: -32px -96px; }
-.ui-icon-document-b { background-position: -48px -96px; }
-.ui-icon-note { background-position: -64px -96px; }
-.ui-icon-mail-closed { background-position: -80px -96px; }
-.ui-icon-mail-open { background-position: -96px -96px; }
-.ui-icon-suitcase { background-position: -112px -96px; }
-.ui-icon-comment { background-position: -128px -96px; }
-.ui-icon-person { background-position: -144px -96px; }
-.ui-icon-print { background-position: -160px -96px; }
-.ui-icon-trash { background-position: -176px -96px; }
-.ui-icon-locked { background-position: -192px -96px; }
-.ui-icon-unlocked { background-position: -208px -96px; }
-.ui-icon-bookmark { background-position: -224px -96px; }
-.ui-icon-tag { background-position: -240px -96px; }
-.ui-icon-home { background-position: 0 -112px; }
-.ui-icon-flag { background-position: -16px -112px; }
-.ui-icon-calendar { background-position: -32px -112px; }
-.ui-icon-cart { background-position: -48px -112px; }
-.ui-icon-pencil { background-position: -64px -112px; }
-.ui-icon-clock { background-position: -80px -112px; }
-.ui-icon-disk { background-position: -96px -112px; }
-.ui-icon-calculator { background-position: -112px -112px; }
-.ui-icon-zoomin { background-position: -128px -112px; }
-.ui-icon-zoomout { background-position: -144px -112px; }
-.ui-icon-search { background-position: -160px -112px; }
-.ui-icon-wrench { background-position: -176px -112px; }
-.ui-icon-gear { background-position: -192px -112px; }
-.ui-icon-heart { background-position: -208px -112px; }
-.ui-icon-star { background-position: -224px -112px; }
-.ui-icon-link { background-position: -240px -112px; }
-.ui-icon-cancel { background-position: 0 -128px; }
-.ui-icon-plus { background-position: -16px -128px; }
-.ui-icon-plusthick { background-position: -32px -128px; }
-.ui-icon-minus { background-position: -48px -128px; }
-.ui-icon-minusthick { background-position: -64px -128px; }
-.ui-icon-close { background-position: -80px -128px; }
-.ui-icon-closethick { background-position: -96px -128px; }
-.ui-icon-key { background-position: -112px -128px; }
-.ui-icon-lightbulb { background-position: -128px -128px; }
-.ui-icon-scissors { background-position: -144px -128px; }
-.ui-icon-clipboard { background-position: -160px -128px; }
-.ui-icon-copy { background-position: -176px -128px; }
-.ui-icon-contact { background-position: -192px -128px; }
-.ui-icon-image { background-position: -208px -128px; }
-.ui-icon-video { background-position: -224px -128px; }
-.ui-icon-script { background-position: -240px -128px; }
-.ui-icon-alert { background-position: 0 -144px; }
-.ui-icon-info { background-position: -16px -144px; }
-.ui-icon-notice { background-position: -32px -144px; }
-.ui-icon-help { background-position: -48px -144px; }
-.ui-icon-check { background-position: -64px -144px; }
-.ui-icon-bullet { background-position: -80px -144px; }
-.ui-icon-radio-off { background-position: -96px -144px; }
-.ui-icon-radio-on { background-position: -112px -144px; }
-.ui-icon-pin-w { background-position: -128px -144px; }
-.ui-icon-pin-s { background-position: -144px -144px; }
-.ui-icon-play { background-position: 0 -160px; }
-.ui-icon-pause { background-position: -16px -160px; }
-.ui-icon-seek-next { background-position: -32px -160px; }
-.ui-icon-seek-prev { background-position: -48px -160px; }
-.ui-icon-seek-end { background-position: -64px -160px; }
-.ui-icon-seek-start { background-position: -80px -160px; }
-/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
-.ui-icon-seek-first { background-position: -80px -160px; }
-.ui-icon-stop { background-position: -96px -160px; }
-.ui-icon-eject { background-position: -112px -160px; }
-.ui-icon-volume-off { background-position: -128px -160px; }
-.ui-icon-volume-on { background-position: -144px -160px; }
-.ui-icon-power { background-position: 0 -176px; }
-.ui-icon-signal-diag { background-position: -16px -176px; }
-.ui-icon-signal { background-position: -32px -176px; }
-.ui-icon-battery-0 { background-position: -48px -176px; }
-.ui-icon-battery-1 { background-position: -64px -176px; }
-.ui-icon-battery-2 { background-position: -80px -176px; }
-.ui-icon-battery-3 { background-position: -96px -176px; }
-.ui-icon-circle-plus { background-position: 0 -192px; }
-.ui-icon-circle-minus { background-position: -16px -192px; }
-.ui-icon-circle-close { background-position: -32px -192px; }
-.ui-icon-circle-triangle-e { background-position: -48px -192px; }
-.ui-icon-circle-triangle-s { background-position: -64px -192px; }
-.ui-icon-circle-triangle-w { background-position: -80px -192px; }
-.ui-icon-circle-triangle-n { background-position: -96px -192px; }
-.ui-icon-circle-arrow-e { background-position: -112px -192px; }
-.ui-icon-circle-arrow-s { background-position: -128px -192px; }
-.ui-icon-circle-arrow-w { background-position: -144px -192px; }
-.ui-icon-circle-arrow-n { background-position: -160px -192px; }
-.ui-icon-circle-zoomin { background-position: -176px -192px; }
-.ui-icon-circle-zoomout { background-position: -192px -192px; }
-.ui-icon-circle-check { background-position: -208px -192px; }
-.ui-icon-circlesmall-plus { background-position: 0 -208px; }
-.ui-icon-circlesmall-minus { background-position: -16px -208px; }
-.ui-icon-circlesmall-close { background-position: -32px -208px; }
-.ui-icon-squaresmall-plus { background-position: -48px -208px; }
-.ui-icon-squaresmall-minus { background-position: -64px -208px; }
-.ui-icon-squaresmall-close { background-position: -80px -208px; }
-.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
-.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
-.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
-.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
-.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
-.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Corner radius */
-.ui-corner-tl { border-top-left-radius: 0; }
-.ui-corner-tr { border-top-right-radius: 0; }
-.ui-corner-bl { border-bottom-left-radius: 0; }
-.ui-corner-br { border-bottom-right-radius: 0; }
-.ui-corner-top { border-top-left-radius: 0; border-top-right-radius: 0; }
-.ui-corner-bottom { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
-.ui-corner-right {  border-top-right-radius: 0; border-bottom-right-radius: 0; }
-.ui-corner-left { border-top-left-radius: 0; border-bottom-left-radius: 0; }
-.ui-corner-all { border-radius: 0; }
-
-/* Overlays */
-.ui-widget-overlay { background: #000000; opacity: .75;filter:Alpha(Opacity=75); }
-.ui-widget-shadow { margin: -7px 0 0 -7px; padding: 7px; /* @embed */ background: #000000 url(images/ui-bg_flat_70_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); border-radius: 8px; }
index 80b8303..7b49cb2 100644 (file)
@@ -154,7 +154,7 @@ function updateTooltip( element ) {
                        }
                }
 
-               // Search it as parent, because the form control can also inside the label element itself
+               // Search it as parent, because the form control can also be inside the label element itself
                $labelParent = $element.parents( 'label' );
                if ( $labelParent.length === 1 ) {
                        updateTooltipOnElement( element, $labelParent[0] );
index 66a3c56..f8641e1 100644 (file)
         * @chainable
         */
        $.fn.arrowSteps = function () {
-               var $steps, width, arrowWidth,
+               var $steps, width, arrowWidth, $stepDiv,
+                       $el = this,
                        paddingSide = $( 'body' ).hasClass( 'rtl' ) ? 'padding-left' : 'padding-right';
 
-               this.addClass( 'arrowSteps' );
-               $steps = this.find( 'li' );
+               $el.addClass( 'arrowSteps' );
+               $steps = $el.find( 'li' );
 
                width = parseInt( 100 / $steps.length, 10 );
                $steps.css( 'width', width + '%' );
                // Every step except the last one has an arrow pointing forward:
                // at the right hand side in LTR languages, and at the left hand side in RTL.
                // Also add in the padding for the calculated arrow width.
-               arrowWidth = parseInt( this.outerHeight(), 10 );
-               $steps.filter( ':not(:last-child)' ).addClass( 'arrow' )
-                       .find( 'div' ).css( paddingSide, arrowWidth.toString() + 'px' );
+               $stepDiv = $steps.filter( ':not(:last-child)' ).addClass( 'arrow' ).find( 'div' );
+
+               // Execute when complete page is fully loaded, including all frames, objects and images
+               $( window ).load( function () {
+                       arrowWidth = parseInt( $el.outerHeight(), 10 );
+                       $stepDiv.css( paddingSide, arrowWidth.toString() + 'px' );
+               } );
+
+               $el.data( 'arrowSteps', $steps );
 
-               this.data( 'arrowSteps', $steps );
                return this;
        };
 
index 061f5d6..9a196b5 100644 (file)
@@ -108,7 +108,7 @@ $.fn.autoEllipsis = function ( options ) {
                                        r = trimmableText.length;
                                        do {
                                                m = Math.ceil( ( l + r ) / 2 );
-                                               $trimmableText.text( trimmableText.substr( 0, m ) + '...' );
+                                               $trimmableText.text( trimmableText.slice( 0, m ) + '...' );
                                                if ( $trimmableText.width() + pw > w ) {
                                                        // Text is too long
                                                        r = m - 1;
@@ -116,7 +116,7 @@ $.fn.autoEllipsis = function ( options ) {
                                                        l = m;
                                                }
                                        } while ( l < r );
-                                       $trimmableText.text( trimmableText.substr( 0, l ) + '...' );
+                                       $trimmableText.text( trimmableText.slice( 0, l ) + '...' );
                                        break;
                                case 'center':
                                        // TODO: Use binary search like for 'right'
@@ -124,7 +124,7 @@ $.fn.autoEllipsis = function ( options ) {
                                        // Begin with making the end shorter
                                        side = 1;
                                        while ( $trimmableText.outerWidth() + pw > w && i[0] > 0 ) {
-                                               $trimmableText.text( trimmableText.substr( 0, i[0] ) + '...' + trimmableText.substr( i[1] ) );
+                                               $trimmableText.text( trimmableText.slice( 0, i[0] ) + '...' + trimmableText.slice( i[1] ) );
                                                // Alternate between trimming the end and begining
                                                if ( side === 0 ) {
                                                        // Make the begining shorter
@@ -141,7 +141,7 @@ $.fn.autoEllipsis = function ( options ) {
                                        // TODO: Use binary search like for 'right'
                                        r = 0;
                                        while ( $trimmableText.outerWidth() + pw > w && r < trimmableText.length ) {
-                                               $trimmableText.text( '...' + trimmableText.substr( r ) );
+                                               $trimmableText.text( '...' + trimmableText.slice( r ) );
                                                r++;
                                        }
                                        break;
index de05fdf..5551232 100644 (file)
 
                inpParts = [
                        // Same start
-                       newVal.substring( 0, startMatches ),
+                       newVal.slice( 0, startMatches ),
                        // Inserted content
-                       newVal.substring( startMatches, newVal.length - endMatches ),
+                       newVal.slice( startMatches, newVal.length - endMatches ),
                        // Same end
-                       newVal.substring( newVal.length - endMatches )
+                       newVal.slice( newVal.length - endMatches )
                ];
 
                // Chop off characters from the end of the "inserted content" string
index be770a9..a6ff8bc 100644 (file)
 
                        // Look for rgb(num,num,num)
                        if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) {
-                               return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
+                               return [
+                                       parseInt( result[1], 10 ),
+                                       parseInt( result[2], 10 ),
+                                       parseInt( result[3], 10 )
+                               ];
                        }
 
                        // Look for rgb(num%,num%,num%)
                        if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) {
-                               return [parseFloat(result[1],10) * 2.55, parseFloat(result[2],10) * 2.55, parseFloat(result[3]) * 2.55];
+                               return [
+                                       parseFloat( result[1] ) * 2.55,
+                                       parseFloat( result[2] ) * 2.55,
+                                       parseFloat( result[3] ) * 2.55
+                               ];
                        }
 
                        // Look for #a0b1c2
                        if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) {
-                               return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
+                               return [
+                                       parseInt( result[1], 16 ),
+                                       parseInt( result[2], 16 ),
+                                       parseInt( result[3], 16 )
+                               ];
                        }
 
                        // Look for #fff
                        if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) {
-                               return [parseInt(result[1] + result[1],16), parseInt(result[2] + result[2],16), parseInt(result[3] + result[3],16)];
+                               return [
+                                       parseInt( result[1] + result[1], 16 ),
+                                       parseInt( result[2] + result[2], 16 ),
+                                       parseInt( result[3] + result[3], 16)
+                               ];
                        }
 
                        // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
                 * @property {Object}
                 */
                colors: {
-                       aqua: [0,255,255],
-                       azure: [240,255,255],
-                       beige: [245,245,220],
-                       black: [0,0,0],
-                       blue: [0,0,255],
-                       brown: [165,42,42],
-                       cyan: [0,255,255],
-                       darkblue: [0,0,139],
-                       darkcyan: [0,139,139],
-                       darkgrey: [169,169,169],
-                       darkgreen: [0,100,0],
-                       darkkhaki: [189,183,107],
-                       darkmagenta: [139,0,139],
-                       darkolivegreen: [85,107,47],
-                       darkorange: [255,140,0],
-                       darkorchid: [153,50,204],
-                       darkred: [139,0,0],
-                       darksalmon: [233,150,122],
-                       darkviolet: [148,0,211],
-                       fuchsia: [255,0,255],
-                       gold: [255,215,0],
-                       green: [0,128,0],
-                       indigo: [75,0,130],
-                       khaki: [240,230,140],
-                       lightblue: [173,216,230],
-                       lightcyan: [224,255,255],
-                       lightgreen: [144,238,144],
-                       lightgrey: [211,211,211],
-                       lightpink: [255,182,193],
-                       lightyellow: [255,255,224],
-                       lime: [0,255,0],
-                       magenta: [255,0,255],
-                       maroon: [128,0,0],
-                       navy: [0,0,128],
-                       olive: [128,128,0],
-                       orange: [255,165,0],
-                       pink: [255,192,203],
-                       purple: [128,0,128],
-                       violet: [128,0,128],
-                       red: [255,0,0],
-                       silver: [192,192,192],
-                       white: [255,255,255],
-                       yellow: [255,255,0],
-                       transparent: [255,255,255]
+                       aqua: [0, 255, 255],
+                       azure: [240, 255, 255],
+                       beige: [245, 245, 220],
+                       black: [0, 0, 0],
+                       blue: [0, 0, 255],
+                       brown: [165, 42, 42],
+                       cyan: [0, 255, 255],
+                       darkblue: [0, 0, 139],
+                       darkcyan: [0, 139, 139],
+                       darkgrey: [169, 169, 169],
+                       darkgreen: [0, 100, 0],
+                       darkkhaki: [189, 183, 107],
+                       darkmagenta: [139, 0, 139],
+                       darkolivegreen: [85, 107, 47],
+                       darkorange: [255, 140, 0],
+                       darkorchid: [153, 50, 204],
+                       darkred: [139, 0, 0],
+                       darksalmon: [233, 150, 122],
+                       darkviolet: [148, 0, 211],
+                       fuchsia: [255, 0, 255],
+                       gold: [255, 215, 0],
+                       green: [0, 128, 0],
+                       indigo: [75, 0, 130],
+                       khaki: [240, 230, 140],
+                       lightblue: [173, 216, 230],
+                       lightcyan: [224, 255, 255],
+                       lightgreen: [144, 238, 144],
+                       lightgrey: [211, 211, 211],
+                       lightpink: [255, 182, 193],
+                       lightyellow: [255, 255, 224],
+                       lime: [0, 255, 0],
+                       magenta: [255, 0, 255],
+                       maroon: [128, 0, 0],
+                       navy: [0, 0, 128],
+                       olive: [128, 128, 0],
+                       orange: [255, 165, 0],
+                       pink: [255, 192, 203],
+                       purple: [128, 0, 128],
+                       violet: [128, 0, 128],
+                       red: [255, 0, 0],
+                       silver: [192, 192, 192],
+                       white: [255, 255, 255],
+                       yellow: [255, 255, 0],
+                       transparent: [255, 255, 255]
                },
 
                /**
diff --git a/resources/src/jquery/jquery.confirmable.css b/resources/src/jquery/jquery.confirmable.css
new file mode 100644 (file)
index 0000000..de69072
--- /dev/null
@@ -0,0 +1,28 @@
+.jquery-confirmable-button {
+       /* Automatically flipped */
+       margin-left: 1ex;
+}
+
+.jquery-confirmable-wrapper {
+       /* Line breaks within the interface text are unpleasant */
+       white-space: nowrap;
+       /* Hiding the original text when it slides to the left */
+       overflow: hidden;
+}
+
+.jquery-confirmable-wrapper,
+.jquery-confirmable-element,
+.jquery-confirmable-interface {
+       /* We need inline-block to be able to size the elements and calculate their dimensions */
+       display: inline-block;
+       /* inline-block elements in this context align to baseline by default */
+       vertical-align: bottom;
+}
+
+.jquery-confirmable-element {
+       transition: margin 250ms cubic-bezier(0.2, 0.8, 0.2, 0.8);
+}
+
+.jquery-confirmable-interface {
+       transition: width 250ms cubic-bezier(0.2, 0.8, 0.2, 0.8);
+}
diff --git a/resources/src/jquery/jquery.confirmable.js b/resources/src/jquery/jquery.confirmable.js
new file mode 100644 (file)
index 0000000..4b80d95
--- /dev/null
@@ -0,0 +1,168 @@
+/**
+ * jQuery confirmable plugin
+ *
+ * Released under the MIT License.
+ *
+ * @author Bartosz Dziewoński
+ *
+ * @class jQuery.plugin.confirmable
+ */
+( function ( $ ) {
+       var identity = function ( data ) {
+               return data;
+       };
+
+       /**
+        * Enable inline confirmation for given clickable element (like `<a />` or `<button />`).
+        *
+        * An additional inline confirmation step being shown before the default action is carried out on
+        * click.
+        *
+        * Calling `.confirmable( { handler: function () { … } } )` will fire the handler only after the
+        * confirmation step.
+        *
+        * The element will have the `jquery-confirmable-element` class added to it when it's clicked for
+        * the first time, which has `white-space: nowrap;` and `display: inline-block;` defined in CSS.
+        * If the computed values for the element are different when you make it confirmable, you might
+        * encounter unexpected behavior.
+        *
+        * @param {Object} [options]
+        * @param {string} [options.events='click'] Events to hook to.
+        * @param {Function} [options.wrapperCallback] Callback to fire when preparing confirmable
+        *     interface. Receives the interface jQuery object as the only parameter.
+        * @param {Function} [options.buttonCallback] Callback to fire when preparing confirmable buttons.
+        *     It is fired separately for the 'Yes' and 'No' button. Receives the button jQuery object as
+        *     the first parameter and 'yes' or 'no' as the second.
+        * @param {Function} [options.handler] Callback to fire when the action is confirmed (user clicks
+        *     the 'Yes' button).
+        * @param {string} [options.i18n] Text to use for interface elements.
+        * @param {string} [options.i18n.confirm] Text to use for the confirmation question.
+        * @param {string} [options.i18n.yes] Text to use for the 'Yes' button.
+        * @param {string} [options.i18n.no] Text to use for the 'No' button.
+        *
+        * @chainable
+        */
+       $.fn.confirmable = function ( options ) {
+               options = $.extend( true, {}, $.fn.confirmable.defaultOptions, options || {} );
+
+               return this.on( options.events, function ( e ) {
+                       var $element, $text, $buttonYes, $buttonNo, $wrapper, $interface, $elementClone,
+                               interfaceWidth, elementWidth, rtl, positionOffscreen, positionRestore, sideMargin;
+
+                       $element = $( this );
+
+                       if ( $element.data( 'jquery-confirmable-button' ) ) {
+                               // We're running on a clone of this element that represents the 'Yes' or 'No' button.
+                               // (This should never happen for the 'No' case unless calling code does bad things.)
+                               return;
+                       }
+
+                       // Only prevent native event handling. Stopping other JavaScript event handlers
+                       // is impossible because they might have already run (we have no control over the order).
+                       e.preventDefault();
+
+                       rtl = $element.css( 'direction' ) === 'rtl';
+                       if ( rtl ) {
+                               positionOffscreen = { position: 'absolute', right: '-9999px' };
+                               positionRestore = { position: '', right: '' };
+                               sideMargin = 'marginRight';
+                       } else {
+                               positionOffscreen = { position: 'absolute', left: '-9999px' };
+                               positionRestore = { position: '', left: '' };
+                               sideMargin = 'marginLeft';
+                       }
+
+                       if ( $element.hasClass( 'jquery-confirmable-element' ) ) {
+                               $wrapper = $element.closest( '.jquery-confirmable-wrapper' );
+                               $interface = $wrapper.find( '.jquery-confirmable-interface' );
+                               $text = $interface.find( '.jquery-confirmable-text' );
+                               $buttonYes = $interface.find( '.jquery-confirmable-button-yes' );
+                               $buttonNo = $interface.find( '.jquery-confirmable-button-no' );
+
+                               interfaceWidth = $interface.data( 'jquery-confirmable-width' );
+                               elementWidth = $element.data( 'jquery-confirmable-width' );
+                       } else {
+                               $elementClone = $element.clone( true );
+                               $element.addClass( 'jquery-confirmable-element' );
+
+                               elementWidth = $element.width();
+                               $element.data( 'jquery-confirmable-width', elementWidth );
+
+                               $wrapper = $( '<span>' )
+                                       .addClass( 'jquery-confirmable-wrapper' );
+                               $element.wrap( $wrapper );
+
+                               // Build the mini-dialog
+                               $text = $( '<span>' )
+                                       .addClass( 'jquery-confirmable-text' )
+                                       .text( options.i18n.confirm );
+
+                               // Clone original element along with event handlers to easily replicate its behavior.
+                               // We could fiddle with .trigger() etc., but that is troublesome especially since
+                               // Safari doesn't implement .click() on <a> links and jQuery follows suit.
+                               $buttonYes = $elementClone.clone( true )
+                                       .addClass( 'jquery-confirmable-button jquery-confirmable-button-yes' )
+                                       .data( 'jquery-confirmable-button', true )
+                                       .text( options.i18n.yes );
+                               if ( options.handler ) {
+                                       $buttonYes.on( options.events, options.handler );
+                               }
+                               $buttonYes = options.buttonCallback( $buttonYes, 'yes' );
+
+                               // Clone it without any events and prevent default action to represent the 'No' button.
+                               $buttonNo = $elementClone.clone( false )
+                                       .addClass( 'jquery-confirmable-button jquery-confirmable-button-no' )
+                                       .data( 'jquery-confirmable-button', true )
+                                       .text( options.i18n.no )
+                                       .on( options.events, function ( e ) {
+                                               $element.css( sideMargin, 0 );
+                                               $interface.css( 'width', 0 );
+                                               e.preventDefault();
+                                       } );
+                               $buttonNo = options.buttonCallback( $buttonNo, 'no' );
+
+                               // Prevent memory leaks
+                               $elementClone.remove();
+
+                               $interface = $( '<span>' )
+                                       .addClass( 'jquery-confirmable-interface' )
+                                       .append( $text, $buttonYes, $buttonNo );
+                               $interface = options.wrapperCallback( $interface );
+
+                               // Render offscreen to measure real width
+                               $interface.css( positionOffscreen );
+                               // Insert it in the correct place while we're at it
+                               $element.after( $interface );
+                               interfaceWidth = $interface.width();
+                               $interface.data( 'jquery-confirmable-width', interfaceWidth );
+                               $interface.css( positionRestore );
+
+                               // Hide to animate the transition later
+                               $interface.css( 'width', 0 );
+                       }
+
+                       // Hide element, show interface. This triggers both transitions.
+                       // In a timeout to trigger the 'width' transition.
+                       setTimeout( function () {
+                               $element.css( sideMargin, -elementWidth );
+                               $interface.css( 'width', interfaceWidth );
+                       }, 1 );
+               } );
+       };
+
+       /**
+        * Default options. Overridable primarily for internationalisation handling.
+        * @property {Object} defaultOptions
+        */
+       $.fn.confirmable.defaultOptions = {
+               events: 'click',
+               wrapperCallback: identity,
+               buttonCallback: identity,
+               handler: null,
+               i18n: {
+                       confirm: 'Are you sure?',
+                       yes: 'Yes',
+                       no: 'No'
+               }
+       };
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.confirmable.mediawiki.js b/resources/src/jquery/jquery.confirmable.mediawiki.js
new file mode 100644 (file)
index 0000000..7ac04f4
--- /dev/null
@@ -0,0 +1,13 @@
+/*!
+ * jQuery confirmable plugin customization for MediaWiki
+ *
+ * This file serves to inject our localised messages into it.
+ */
+
+( function ( mw, $ ) {
+       $.fn.confirmable.defaultOptions.i18n = {
+               confirm: mw.message( 'confirmable-confirm', mw.user ).text(),
+               yes: mw.message( 'confirmable-yes' ).text(),
+               no: mw.message( 'confirmable-no' ).text()
+       };
+}( mediaWiki, jQuery ) );
index 1881085..d7024cc 100644 (file)
@@ -51,7 +51,7 @@ jQuery._farbtastic = function (container, callback) {
                $('*', e).each(function () {
                        if (this.currentStyle.backgroundImage != 'none') {
                                var image = this.currentStyle.backgroundImage;
-                               image = this.currentStyle.backgroundImage.substring(5, image.length - 2);
+                               image = this.currentStyle.backgroundImage.slice(5, image.length - 2);
                                $(this).css({
                                        'backgroundImage': 'none',
                                        'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
index 71b083b..4ecfeb8 100644 (file)
@@ -110,7 +110,7 @@ $.matchSrcSet = function ( devicePixelRatio, srcset ) {
                bits = candidate.split( / +/ );
                src = bits[0];
                if ( bits.length > 1 && bits[1].charAt( bits[1].length - 1 ) === 'x' ) {
-                       ratioStr = bits[1].substr( 0, bits[1].length - 1 );
+                       ratioStr = bits[1].slice( 0, -1 );
                        ratio = parseFloat( ratioStr );
                        if ( ratio <= devicePixelRatio && ratio > selectedRatio ) {
                                selectedRatio = ratio;
index 05745f8..c4e2520 100644 (file)
                                        .text( collapseText )
                                        .wrap( '<span class="mw-collapsible-toggle"></span>' )
                                                .parent()
-                                               .prepend( '&nbsp;[' )
-                                               .append( ']&nbsp;' )
+                                               .prepend( '<span class="mw-collapsible-bracket">[</span>' )
+                                               .append( '<span class="mw-collapsible-bracket">]</span>' )
                                                .on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
                        };
 
                        } else {
                                collapsibleId = $collapsible.attr( 'id' ) || '';
                                if ( collapsibleId.indexOf( 'mw-customcollapsible-' ) === 0 ) {
-                                       $customTogglers = $( '.' + collapsibleId.replace( 'mw-customcollapsible', 'mw-customtoggle' ) );
-                                       $customTogglers.addClass( 'mw-customtoggle' );
+                                       $customTogglers = $( '.' + collapsibleId.replace( 'mw-customcollapsible', 'mw-customtoggle' ) )
+                                               .addClass( 'mw-customtoggle' );
                                }
                        }
 
                                        togglingHandler( $( this ), $collapsible, e, opts );
                                };
 
-                               $toggleLink = $customTogglers;
-                               $toggleLink.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                               $toggleLink = $customTogglers
+                                       .on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+                                       .prop( 'tabIndex', 0 );
 
                        } else {
                                // If this is not a custom case, do the default: wrap the
                                                        $toggleLink = buildDefaultToggleLink().appendTo( $caption );
                                                } else {
                                                        actionHandler = premadeToggleHandler;
-                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+                                                               .prop( 'tabIndex', 0 );
                                                }
                                        } else {
                                                // The toggle-link will be in one the the cells (td or th) of the first row
                                                        $toggleLink = buildDefaultToggleLink().prependTo( $firstItem.eq( -1 ) );
                                                } else {
                                                        actionHandler = premadeToggleHandler;
-                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+                                                               .prop( 'tabIndex', 0 );
                                                }
                                        }
 
                                                $toggleLink.wrap( '<li class="mw-collapsible-toggle-li"></li>' ).parent().prependTo( $collapsible );
                                        } else {
                                                actionHandler = premadeToggleHandler;
-                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+                                                       .prop( 'tabIndex', 0 );
                                        }
 
                                } else { // <div>, <p> etc.
                                                $toggleLink = buildDefaultToggleLink().prependTo( $collapsible );
                                        } else {
                                                actionHandler = premadeToggleHandler;
-                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+                                                       .prop( 'tabIndex', 0 );
                                        }
                                }
                        }
 
-                       // Attributes for accessibility. This isn't necessary when the toggler is already
-                       // an <a> or a <button> etc., but it doesn't hurt either, and it's consistent.
-                       $toggleLink.prop( 'tabIndex', 0 );
-
                        // Initial state
                        if ( options.collapsed || $collapsible.hasClass( 'mw-collapsed' ) ) {
                                // One toggler can hook to multiple elements, and one element can have
index cdcb8fb..dc7aaa4 100644 (file)
@@ -12,7 +12,7 @@
                                        '' : str.toString().replace( /\s+$/, '' );
                },
                ucFirst: function ( str ) {
-                       return str.charAt( 0 ).toUpperCase() + str.substr( 1 );
+                       return str.charAt( 0 ).toUpperCase() + str.slice( 1 );
                },
                escapeRE: function ( str ) {
                        return str.replace ( /([\\{}()|.?*+\-\^$\[\]])/g, '\\$1' );
index ea65946..15cd926 100644 (file)
@@ -9,11 +9,6 @@
        border: none;
        z-index: 1099;
        padding: 0;
-       margin: -1px -1px 0 0;
-}
-
-/* IGNORED BY IE6 */
-html > body .suggestions {
        margin: -1px 0 0 0;
 }
 
index 08ed5d9..3369cde 100644 (file)
@@ -225,7 +225,7 @@ $.suggestions = {
                                                                } else {
                                                                        regionWidth = $region.outerWidth();
                                                                        docWidth = $( document ).width();
-                                                                       if ( ( regionWidth / docWidth  ) > 0.85 ) {
+                                                                       if ( regionWidth > ( 0.85 * docWidth ) ) {
                                                                                // If the input size takes up more than 85% of the document horizontally
                                                                                // expand the suggestions to the writing direction's native end.
                                                                                expandFrom = 'start';
@@ -233,7 +233,7 @@ $.suggestions = {
                                                                                // Calculate the center points of the input and document
                                                                                regionCenter = $region.offset().left + regionWidth / 2;
                                                                                docCenter = docWidth / 2;
-                                                                               if ( Math.abs( regionCenter - docCenter ) / docCenter < 0.10 ) {
+                                                                               if ( Math.abs( regionCenter - docCenter ) < ( 0.10 * docCenter ) ) {
                                                                                        // If the input's center is within 10% of the document center
                                                                                        // use the writing direction's native end.
                                                                                        expandFrom = 'start';
index 5b1e2a7..ea2c5f9 100644 (file)
                        colspan,
                        headerCount,
                        longestTR,
-                       matrixRowIndex,
-                       matrixColumnIndex,
                        exploded,
                        $tableHeaders = $( [] ),
                        $tableRows = $( 'thead:eq(0) > tr', table );
                        // Loop through all the dom cells of the thead
                        $tableRows.each( function ( rowIndex, row ) {
                                $.each( row.cells, function ( columnIndex, cell ) {
+                                       var matrixRowIndex,
+                                               matrixColumnIndex;
+
                                        rowspan = Number( cell.rowSpan );
                                        colspan = Number( cell.colSpan );
 
                        } );
                        // We want to find the row that has the most columns (ignoring colspan)
                        $.each( exploded, function ( index, cellArray ) {
-                               headerCount = $.unique( $( cellArray ) ).length;
+                               headerCount = $( uniqueElements( cellArray ) ).filter( 'th' ).length;
                                if ( headerCount >= maxSeen ) {
                                        maxSeen = headerCount;
                                        longestTR = index;
                                }
                        } );
                        // We cannot use $.unique() here because it sorts into dom order, which is undesirable
-                       $tableHeaders = $( uniqueElements( exploded[longestTR] ) );
+                       $tableHeaders = $( uniqueElements( exploded[longestTR] ) ).filter( 'th' );
                }
 
                // as each header can span over multiple columns (using colspan=N),
index 042db91..8d440fd 100644 (file)
@@ -25,7 +25,7 @@
        $.fn.textSelection = function ( command, options ) {
                var fn,
                        context,
-                       hasIframe,
+                       hasWikiEditorSurface, // The alt edit surface needs to implement the WikiEditor API
                        needSave,
                        retval;
 
                        getContents: function () {
                                return this.val();
                        },
+                       /**
+                        * Set the contents of the textarea, replacing anything that was there before
+                        */
+                       setContents: function ( content ) {
+                               this.val( content );
+                       },
                        /**
                         * Get the currently selected text in this textarea. Will focus the textarea
                         * in some browsers (IE/Opera)
                                                } else {
                                                        while ( selText.charAt( selText.length - 1 ) === ' ' ) {
                                                                // Exclude ending space char
-                                                               selText = selText.substring( 0, selText.length - 1 );
+                                                               selText = selText.slice( 0, -1 );
                                                                post += ' ';
                                                        }
                                                        while ( selText.charAt( 0 ) === ' ' ) {
                                                                // Exclude prepending space char
-                                                               selText = selText.substring( 1, selText.length );
+                                                               selText = selText.slice( 1 );
                                                                pre = ' ' + pre;
                                                        }
                                                }
                                                                        post += '\n';
                                                                }
                                                        }
-                                                       this.value = this.value.substring( 0, startPos ) + insertText +
-                                                               this.value.substring( endPos, this.value.length );
+                                                       this.value = this.value.slice( 0, startPos ) + insertText +
+                                                               this.value.slice( endPos );
                                                        // Setting this.value scrolls the textarea to the top, restore the scroll position
                                                        this.scrollTop = scrollTop;
                                                        if ( window.opera ) {
                                        // Position to start selection at
                                        start: undefined,
                                        // Position to end selection at. Defaults to start
-                                       end: undefined,
-                                       // Element to start selection in (iframe only)
-                                       startContainer: undefined,
-                                       // Element to end selection in (iframe only). Defaults to startContainer
-                                       endContainer: undefined
+                                       end: undefined
                                }, options );
 
                                if ( options.end === undefined ) {
                                        options.end = options.start;
                                }
-                               if ( options.endContainer === undefined ) {
-                                       options.endContainer = options.startContainer;
-                               }
                                // FIXME: We may not need character position-based functions if we insert markers in the right places
                                break;
                        case 'scrollToCaretPosition':
                }
 
                context = $( this ).data( 'wikiEditor-context' );
-               hasIframe = context !== undefined && context && context.$iframe !== undefined;
+               hasWikiEditorSurface = ( context !== undefined && context.$iframe !== undefined );
 
                // IE selection restore voodoo
                needSave = false;
-               if ( hasIframe && context.savedSelection !== null ) {
+               if ( hasWikiEditorSurface && context.savedSelection !== null ) {
                        context.fn.restoreSelection();
                        needSave = true;
                }
-               retval = ( hasIframe ? context.fn : fn )[command].call( this, options );
-               if ( hasIframe && needSave ) {
+               retval = ( hasWikiEditorSurface && context.fn[command] !== undefined ? context.fn : fn )[command].call( this, options );
+               if ( hasWikiEditorSurface && needSave ) {
                        context.fn.saveSelection();
                }
 
diff --git a/resources/src/mediawiki.action/images/nextredirect-ltr.png b/resources/src/mediawiki.action/images/nextredirect-ltr.png
new file mode 100644 (file)
index 0000000..cd657c3
Binary files /dev/null and b/resources/src/mediawiki.action/images/nextredirect-ltr.png differ
diff --git a/resources/src/mediawiki.action/images/nextredirect-rtl.png b/resources/src/mediawiki.action/images/nextredirect-rtl.png
new file mode 100644 (file)
index 0000000..b788f33
Binary files /dev/null and b/resources/src/mediawiki.action/images/nextredirect-rtl.png differ
diff --git a/resources/src/mediawiki.action/images/redirect-ltr.png b/resources/src/mediawiki.action/images/redirect-ltr.png
new file mode 100644 (file)
index 0000000..695f2a1
Binary files /dev/null and b/resources/src/mediawiki.action/images/redirect-ltr.png differ
diff --git a/resources/src/mediawiki.action/images/redirect-rtl.png b/resources/src/mediawiki.action/images/redirect-rtl.png
new file mode 100644 (file)
index 0000000..c954a2a
Binary files /dev/null and b/resources/src/mediawiki.action/images/redirect-rtl.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.css b/resources/src/mediawiki.action/mediawiki.action.edit.css
new file mode 100644 (file)
index 0000000..45ba543
--- /dev/null
@@ -0,0 +1,18 @@
+/*!
+ * Styles for elements of the editing form, loaded only when JavaScript is enabled.
+ */
+
+.mw-toolbar-editbutton {
+       width: 23px;
+       height: 22px;
+       cursor: pointer;
+       vertical-align: middle;
+       /* Cross-browser inline-block */
+       /* Firefox 2 */
+       display: -moz-inline-block;
+       /* Modern browsers */
+       display: inline-block;
+       /* IE7 */
+       zoom: 1;
+       *display: inline;
+}
index dcd2b0b..b565440 100644 (file)
@@ -24,8 +24,8 @@
                                // the original values
                                if (
                                        mw.config.get( 'wgAction' ) === 'submit' ||
-                                               $wpTextbox1.data( 'origtext' ) !== $wpTextbox1.val() ||
-                                               $wpSummary.data( 'origtext' ) !== $wpSummary.val()
+                                               $wpTextbox1.data( 'origtext' ) !== $wpTextbox1.textSelection( 'getContents' ) ||
+                                               $wpSummary.data( 'origtext' ) !== $wpSummary.textSelection( 'getContents' )
                                ) {
                                        // Return our message
                                        retval = mw.msg( 'editwarning-warning' );
index 0481b6a..4519b04 100644 (file)
@@ -15,6 +15,8 @@
         * @private
         */
        function insertButton( b, speedTip, tagOpen, tagClose, sampleText, imageId ) {
+               var $button;
+
                // Backwards compatibility
                if ( typeof b !== 'object' ) {
                        b = {
                                imageId: imageId
                        };
                }
-               var $image = $( '<img>' ).attr( {
-                       width: 23,
-                       height: 22,
+
+               if ( b.imageFile ) {
+                       $button = $( '<img>' ).attr( {
                        src: b.imageFile,
                        alt: b.speedTip,
                        title: b.speedTip,
                        id: b.imageId || undefined,
                        'class': 'mw-toolbar-editbutton'
-               } ).click( function () {
-                       toolbar.insertTags( b.tagOpen, b.tagClose, b.sampleText );
+                       } );
+               } else {
+                       $button = $( '<div>' ).attr( {
+                               title: b.speedTip,
+                               id: b.imageId || undefined,
+                               'class': 'mw-toolbar-editbutton'
+                       } );
+               }
+
+               $button.click( function ( e ) {
+                       if ( b.onClick !== undefined ) {
+                               b.onClick( e );
+                       } else {
+                               toolbar.insertTags( b.tagOpen, b.tagClose, b.sampleText );
+                       }
+
                        return false;
                } );
 
-               $toolbar.append( $image );
+               $toolbar.append( $button );
        }
 
        isReady = false;
        $toolbar = false;
+
        /**
         * @private
         * @property {Array}
                 * by placing buttons in a queue if this method is called before
                 * the toolbar is created.
                 *
-                * For compatiblity, passing the properties listed below as separate arguments
-                * (in the listed order) is also supported.
+                * For backwards-compatibility, passing `imageFile`, `speedTip`, `tagOpen`, `tagClose`,
+                * `sampleText` and `imageId` as separate arguments (in this order) is also supported.
                 *
-                * @param {Object} button Object with the following properties:
-                * @param {string} button.imageFile
-                * @param {string} button.speedTip
-                * @param {string} button.tagOpen
-                * @param {string} button.tagClose
-                * @param {string} button.sampleText
-                * @param {string} [button.imageId]
+                * @param {Object} button Object with the following properties.
+                *  You are required to provide *either* the `onClick` parameter, or the three parameters
+                *  `tagOpen`, `tagClose` and `sampleText`, but not both (they're mutually exclusive).
+                * @param {string} [button.imageFile] Image to use for the button.
+                * @param {string} button.speedTip Tooltip displayed when user mouses over the button.
+                * @param {Function} [button.onClick] Function to be executed when the button is clicked.
+                * @param {string} [button.tagOpen]
+                * @param {string} [button.tagClose]
+                * @param {string} [button.sampleText] Alternative to `onClick`. `tagOpen`, `tagClose` and
+                *  `sampleText` together provide the markup that should be inserted into page text at
+                *  current cursor position.
+                * @param {string} [button.imageId] `id` attribute of the button HTML element. Can be
+         *  used to define the image with CSS if it's not provided as `imageFile`.
                 */
                addButton: function () {
                        if ( isReady ) {
                        }
                },
                /**
+                * Add multiple buttons to the toolbar (see also #addButton).
+                *
                 * Example usage:
+                *
                 *     addButtons( [ { .. }, { .. }, { .. } ] );
                 *     addButtons( { .. }, { .. } );
                 *
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_bold.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_bold.png
new file mode 100644 (file)
index 0000000..e524f6c
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_bold.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_headline.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_headline.png
new file mode 100644 (file)
index 0000000..398e561
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_headline.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_italic.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_italic.png
new file mode 100644 (file)
index 0000000..6ec73e9
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_italic.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_link.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_link.png
new file mode 100644 (file)
index 0000000..c9c63f6
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_link.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_nowiki.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_nowiki.png
new file mode 100644 (file)
index 0000000..743ea61
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ar/button_nowiki.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/be-tarask/button_bold.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/be-tarask/button_bold.png
new file mode 100644 (file)
index 0000000..5c10cfe
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/be-tarask/button_bold.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/be-tarask/button_italic.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/be-tarask/button_italic.png
new file mode 100644 (file)
index 0000000..72209d7
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/be-tarask/button_italic.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/be-tarask/button_link.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/be-tarask/button_link.png
new file mode 100644 (file)
index 0000000..09c86fb
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/be-tarask/button_link.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/de/button_bold.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/de/button_bold.png
new file mode 100644 (file)
index 0000000..367d5bc
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/de/button_bold.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/de/button_italic.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/de/button_italic.png
new file mode 100644 (file)
index 0000000..fdd8c9f
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/de/button_italic.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_bold.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_bold.png
new file mode 100644 (file)
index 0000000..75c3f10
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_bold.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_extlink.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_extlink.png
new file mode 100644 (file)
index 0000000..458943c
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_extlink.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_headline.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_headline.png
new file mode 100644 (file)
index 0000000..9cf751d
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_headline.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_hr.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_hr.png
new file mode 100644 (file)
index 0000000..47e1ca4
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_hr.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_image.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_image.png
new file mode 100644 (file)
index 0000000..6919296
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_image.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_italic.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_italic.png
new file mode 100644 (file)
index 0000000..527fbd1
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_italic.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_link.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_link.png
new file mode 100644 (file)
index 0000000..eb5634b
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_link.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_media.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_media.png
new file mode 100644 (file)
index 0000000..4194ec1
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_media.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_nowiki.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_nowiki.png
new file mode 100644 (file)
index 0000000..2ba818d
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_nowiki.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_sig.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_sig.png
new file mode 100644 (file)
index 0000000..fe34b3f
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/en/button_sig.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_bold.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_bold.png
new file mode 100644 (file)
index 0000000..c54d094
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_bold.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_headline.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_headline.png
new file mode 100644 (file)
index 0000000..9890d15
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_headline.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_italic.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_italic.png
new file mode 100644 (file)
index 0000000..33f91ed
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_italic.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_link.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_link.png
new file mode 100644 (file)
index 0000000..76b939e
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_link.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_nowiki.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_nowiki.png
new file mode 100644 (file)
index 0000000..743ea61
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/fa/button_nowiki.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ksh/LICENSE b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ksh/LICENSE
new file mode 100644 (file)
index 0000000..47ecfe4
--- /dev/null
@@ -0,0 +1,7 @@
+
+button_italic.png
+-------------------
+Source : http://commons.wikimedia.org/wiki/Image:Button_S_italic.png
+License: Public domain
+Author : Purodha Blissenbach, http://ksh.wikipedia.org/wiki/User:Purodha
+
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ksh/button_italic.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ksh/button_italic.png
new file mode 100644 (file)
index 0000000..15496c0
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ksh/button_italic.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/LICENSE b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/LICENSE
new file mode 100644 (file)
index 0000000..bedcec6
--- /dev/null
@@ -0,0 +1,17 @@
+button_bold.png
+---------------
+Source : http://commons.wikimedia.org/wiki/Image:Button_bold_ukr.png
+License: Public domain
+Author : Alexey Belomoev
+
+button_italic.png
+------------------------
+Source : http://commons.wikimedia.org/wiki/Image:Button_italic_ukr.png
+License: Public domain
+Author : Alexey Belomoev
+
+button_link.png
+-----------------
+Source : http://commons.wikimedia.org/wiki/Image:Button_internal_link_ukr.png
+License: GPL
+Author : Saproj, Erik Möller
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/button_bold.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/button_bold.png
new file mode 100644 (file)
index 0000000..eae30d9
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/button_bold.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/button_italic.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/button_italic.png
new file mode 100644 (file)
index 0000000..b958d22
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/button_italic.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/button_link.png b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/button_link.png
new file mode 100644 (file)
index 0000000..12ad373
Binary files /dev/null and b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/images/ru/button_link.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/mediawiki.action.edit.toolbar.less b/resources/src/mediawiki.action/mediawiki.action.edit.toolbar/mediawiki.action.edit.toolbar.less
new file mode 100644 (file)
index 0000000..d65b284
--- /dev/null
@@ -0,0 +1,42 @@
+@import "mediawiki.mixins";
+
+#mw-editbutton-bold {
+       .background-image("images/@{button-bold}");
+}
+
+#mw-editbutton-italic {
+       .background-image("images/@{button-italic}");
+}
+
+#mw-editbutton-link {
+       .background-image("images/@{button-link}");
+}
+
+#mw-editbutton-extlink {
+       .background-image("images/@{button-extlink}");
+}
+
+#mw-editbutton-headline {
+       .background-image("images/@{button-headline}");
+}
+
+#mw-editbutton-image {
+       .background-image("images/@{button-image}");
+}
+
+#mw-editbutton-media {
+       .background-image("images/@{button-media}");
+}
+
+#mw-editbutton-nowiki {
+       .background-image("images/@{button-nowiki}");
+}
+
+// Who decided to make only this single one different than the name of the data item?
+#mw-editbutton-signature {
+       .background-image("images/@{button-sig}");
+}
+
+#mw-editbutton-hr {
+       .background-image("images/@{button-hr}");
+}
diff --git a/resources/src/mediawiki.action/mediawiki.action.view.metadata.css b/resources/src/mediawiki.action/mediawiki.action.view.metadata.css
new file mode 100644 (file)
index 0000000..2c8d2e6
--- /dev/null
@@ -0,0 +1,6 @@
+/*!
+ * Hide collapsable rows in a collapsed table.
+ */
+table.collapsed tr.collapsable {
+       display: none;
+}
index 712cf29..25b5acc 100644 (file)
@@ -4,9 +4,7 @@
  * Add an expand/collapse link and collapse by default if set to
  * (with JS disabled, user will see all items)
  *
- * See also:
- * - ImagePage.php#makeMetadataTable (creates the HTML)
- * - skins/common/shared.css (hides tr.collapsable inside table.collapsed)
+ * See also ImagePage.php#makeMetadataTable (creates the HTML)
  */
 ( function ( mw, $ ) {
        $( function () {
diff --git a/resources/src/mediawiki.action/mediawiki.action.view.redirect.js b/resources/src/mediawiki.action/mediawiki.action.view.redirect.js
new file mode 100644 (file)
index 0000000..b9aa137
--- /dev/null
@@ -0,0 +1,70 @@
+/*!
+ * JavaScript to update page URL when a redirect is viewed, ensuring that the
+ * page is scrolled to the id when it's a redirect with fragment.
+ *
+ * This is loaded in the top queue, so avoid unnecessary dependencies
+ * like mediawiki.Title or mediawiki.Uri.
+ */
+( function ( mw, $ ) {
+       var profile = $.client.profile(),
+               canonical = mw.config.get( 'wgInternalRedirectTargetUrl' ),
+               fragment = null,
+               shouldChangeFragment, index;
+
+       // Clear internal mw.config entries, so that no one tries to depend on them
+       mw.config.set( 'wgInternalRedirectTargetUrl', null );
+
+       // Deployment hack for compatibility with cached HTML, remove before 1.24 release
+       if ( !canonical ) {
+               canonical = mw.config.get( 'wgRedirectToFragment' );
+       }
+
+       index = canonical.indexOf( '#' );
+       if ( index !== -1 ) {
+               fragment = canonical.slice( index );
+       }
+
+       // Never override the fragment if the user intended to look at a different section
+       shouldChangeFragment = fragment && !location.hash;
+
+       // Replace the whole URL if possible, otherwise just change the fragment
+       if ( canonical && history.replaceState ) {
+               if ( !shouldChangeFragment ) {
+                       // If the current page view has a fragment already, don't override it
+                       canonical = canonical.replace( /#.*$/, '' );
+                       canonical += location.hash;
+               }
+
+               // This will also cause the browser to scroll to given fragment
+               history.replaceState( /*data=*/ history.state, /*title=*/ document.title, /*url=*/ canonical );
+
+               // …except for IE 10 and 11. Prod it with a location.hash change.
+               if ( shouldChangeFragment && profile.name === 'msie' && profile.versionNumber >= 10 ) {
+                       location.hash = fragment;
+               }
+
+       } else if ( shouldChangeFragment ) {
+               if ( profile.layout === 'webkit' && profile.layoutVersion < 420 ) {
+                       // Released Safari w/ WebKit 418.9.1 messes up horribly
+                       // Nightlies of 420+ are ok
+                       return;
+               }
+
+               location.hash = fragment;
+       }
+
+       if ( shouldChangeFragment && profile.layout === 'gecko' ) {
+               // Mozilla needs to wait until after load, otherwise the window doesn't
+               // scroll.  See <https://bugzilla.mozilla.org/show_bug.cgi?id=516293>.
+               // There's no obvious way to detect this programmatically, so we use
+               // version-testing.  If Firefox fixes the bug, they'll jump twice, but
+               // better twice than not at all, so make the fix hit future versions as
+               // well.
+               $( function () {
+                       if ( location.hash === fragment ) {
+                               location.hash = fragment;
+                       }
+               } );
+       }
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.action/mediawiki.action.view.redirectPage.css b/resources/src/mediawiki.action/mediawiki.action.view.redirectPage.css
new file mode 100644 (file)
index 0000000..8feca4a
--- /dev/null
@@ -0,0 +1,53 @@
+/*!
+ * Display neat icons on redirect pages.
+ */
+
+/* Hide, but keep accessible for screen-readers. */
+.redirectTo {
+       overflow: hidden;
+       height: 0;
+       zoom: 1;
+}
+
+.redirectText {
+       list-style: none none;
+       display: inline;
+       /* shared.css has some very weird directionality-specific rules for 'ul' we need to override,
+          search for "Correct directionality when page dir is different from site/user dir" */
+       margin: 0 !important;
+       padding: 0 !important;
+}
+
+/* @noflip */
+.mw-content-ltr .redirectText li {
+       display: inline;
+       margin: 0;
+       padding: 0;
+       padding-left: 42px;
+       /* @embed */
+       background: url(images/nextredirect-ltr.png) bottom left no-repeat;
+}
+
+/* @noflip */
+.mw-content-ltr .redirectText li:first-child {
+       padding-left: 47px;
+       /* @embed */
+       background: url(images/redirect-ltr.png) bottom left no-repeat;
+}
+
+/* @noflip */
+.mw-content-rtl .redirectText li {
+       display: inline;
+       margin: 0;
+       padding: 0;
+       padding-right: 42px;
+       /* @embed */
+       background: url(images/nextredirect-rtl.png) bottom right no-repeat;
+}
+
+/* @noflip */
+.mw-content-rtl .redirectText li:first-child {
+       padding-right: 47px;
+       /* @embed */
+       background: url(images/redirect-rtl.png) bottom right no-repeat;
+}
diff --git a/resources/src/mediawiki.action/mediawiki.action.view.redirectToFragment.js b/resources/src/mediawiki.action/mediawiki.action.view.redirectToFragment.js
deleted file mode 100644 (file)
index cbfd7b5..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*!
- * JavaScript to scroll the page to an id, when a redirect with fragment is viewed.
- */
-( function ( mw, $ ) {
-       var profile = $.client.profile(),
-               fragment = mw.config.get( 'wgRedirectToFragment' );
-
-       if ( fragment === null ) {
-               // nothing to do
-               return;
-       }
-
-       if ( profile.layout === 'webkit' && profile.layoutVersion < 420 ) {
-               // Released Safari w/ WebKit 418.9.1 messes up horribly
-               // Nightlies of 420+ are ok
-               return;
-       }
-       if ( !window.location.hash ) {
-               window.location.hash = fragment;
-
-               // Mozilla needs to wait until after load, otherwise the window doesn't
-               // scroll.  See <https://bugzilla.mozilla.org/show_bug.cgi?id=516293>.
-               // There's no obvious way to detect this programmatically, so we use
-               // version-testing.  If Firefox fixes the bug, they'll jump twice, but
-               // better twice than not at all, so make the fix hit future versions as
-               // well.
-               if ( profile.layout === 'gecko' ) {
-                       $( function () {
-                               if ( window.location.hash === fragment ) {
-                                       window.location.hash = fragment;
-                               }
-                       } );
-               }
-       }
-}( mediaWiki, jQuery ) );
index edfb34a..e88ae5e 100644 (file)
                                mw.track( 'mw.deprecate', 'api.cbParam' );
                                mw.log.warn( msg );
                        }
+
                        return this.postWithToken( 'edit', params ).done( ok ).fail( err );
                },
 
                /**
-                * Api helper to grab an edit token.
+                * API helper to grab an edit token.
                 *
                 * @param {Function} [ok] Success callback (deprecated)
                 * @param {Function} [err] Error callback (deprecated)
                                mw.track( 'mw.deprecate', 'api.cbParam' );
                                mw.log.warn( msg );
                        }
+
                        return this.getToken( 'edit' ).done( ok ).fail( err );
                },
 
                /**
-                * Create a new section of the page.
+                * Post a new section to the page.
                 * @see #postWithEditToken
                 * @param {mw.Title|String} title Target page
                 * @param {string} header
                 * @param {string} message wikitext message
+                * @param {Object} [additionalParams] Additional API parameters, e.g. `{ redirect: true }`
                 * @param {Function} [ok] Success handler (deprecated)
                 * @param {Function} [err] Error handler (deprecated)
                 * @return {jQuery.Promise}
                 */
-               newSection: function ( title, header, message, ok, err ) {
+               newSection: function ( title, header, message, additionalParams, ok, err ) {
+                       // Until we remove 'ok' and 'err' parameters, we have to support code that passes them,
+                       // but not additionalParams...
+                       if ( $.isFunction( additionalParams ) ) {
+                               err = ok;
+                               ok = additionalParams;
+                               additionalParams = undefined;
+                       }
+
                        if ( ok || err ) {
                                mw.track( 'mw.deprecate', 'api.cbParam' );
                                mw.log.warn( msg );
                        }
-                       return this.postWithEditToken( {
+
+                       return this.postWithEditToken( $.extend( {
                                action: 'edit',
                                section: 'new',
                                format: 'json',
                                title: String( title ),
                                summary: header,
                                text: message
-                       } ).done( ok ).fail( err );
+                       }, additionalParams ) ).done( ok ).fail( err );
                }
        } );
 
index f8dc836..51b3238 100644 (file)
 
                        // Return the Promise
                        return apiDeferred.promise( { abort: xhr.abort } ).fail( function ( code, details ) {
-                               if ( code !== 'abort' ) {
+                               if ( !( code === 'http' && details && details.textStatus === 'abort' ) ) {
                                        mw.log( 'mw.Api error: ', code, details );
                                }
                        } );
diff --git a/resources/src/mediawiki.hidpi-skip.js b/resources/src/mediawiki.hidpi-skip.js
new file mode 100644 (file)
index 0000000..26b63c7
--- /dev/null
@@ -0,0 +1,4 @@
+/*!
+ * Skip function for mediawiki.hdpi.js.
+ */
+return 'srcset' in new Image();
index 2382aae..453a675 100644 (file)
@@ -34,7 +34,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
                        break;
                case 'illative':
                        // Double the last letter and add 'n'
-                       word += word.substr(  word.length - 1 ) + 'n';
+                       word += word.slice( -1 ) + 'n';
                        break;
                case 'inessive':
                        word += ( aou ? 'ssa' : 'ssä' );
index 48351bc..d1eba43 100644 (file)
@@ -11,17 +11,17 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
                case 'prefixed':
                case 'תחילית': // the same word in Hebrew
                        // Duplicate prefixed "Waw", but only if it's not already double
-                       if ( word.substr( 0, 1 ) === 'ו' && word.substr( 0, 2 ) !== 'וו' ) {
+                       if ( word.slice( 0, 1 ) === 'ו' && word.slice( 0, 2 ) !== 'וו' ) {
                                word = 'ו' + word;
                        }
 
                        // Remove the "He" if prefixed
-                       if ( word.substr( 0, 1 ) === 'ה' ) {
-                               word = word.substr( 1, word.length );
+                       if ( word.slice( 0, 1 ) === 'ה' ) {
+                               word = word.slice( 1 );
                        }
 
                        // Add a hyphen (maqaf) before numbers and non-Hebrew letters
-                       if ( word.substr( 0, 1 ) < 'א' ||  word.substr( 0, 1 ) > 'ת' ) {
+                       if ( word.slice( 0, 1 ) < 'א' ||  word.slice( 0, 1 ) > 'ת' ) {
                                word = '־' + word;
                        }
        }
index ae16f24..9cae360 100644 (file)
@@ -14,12 +14,12 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
 
        switch ( form ) {
                case 'genitive': // սեռական հոլով
-                       if ( word.substr( -1 ) === 'ա' ) {
-                               word = word.substr( 0, word.length - 1 ) + 'այի';
-                       } else if ( word.substr( -1 ) === 'ո' ) {
-                               word = word.substr( 0, word.length - 1 ) + 'ոյի';
-                       } else if ( word.substr( -4 ) === 'գիրք' ) {
-                               word = word.substr( 0, word.length - 4 ) + 'գրքի';
+                       if ( word.slice( -1 ) === 'ա' ) {
+                               word = word.slice( 0, -1 ) + 'այի';
+                       } else if ( word.slice( -1 ) === 'ո' ) {
+                               word = word.slice( 0, -1 ) + 'ոյի';
+                       } else if ( word.slice( -4 ) === 'գիրք' ) {
+                               word = word.slice( 0, -4 ) + 'գրքի';
                        } else {
                                word = word + 'ի';
                        }
index 04b7d0a..52e8dd4 100644 (file)
@@ -14,9 +14,9 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
                        word = word.replace( /u[ms]$/i, 'i' ); // 2nd declension singular
                        word = word.replace( /ommunia$/i, 'ommunium' ); // 3rd declension neuter plural (partly)
                        word = word.replace( /a$/i, 'ae' ); // 1st declension singular
-                       word = word.replace( /libri$/i,'librorum' ); // 2nd declension plural (partly)
+                       word = word.replace( /libri$/i, 'librorum' ); // 2nd declension plural (partly)
                        word = word.replace( /nuntii$/i, 'nuntiorum' ); // 2nd declension plural (partly)
-                       word = word.replace( /tio$/i,'tionis' ); // 3rd declension singular (partly)
+                       word = word.replace( /tio$/i, 'tionis' ); // 3rd declension singular (partly)
                        word = word.replace( /ns$/i, 'ntis' );
                        word = word.replace( /as$/i, 'atis' );
                        word = word.replace( /es$/i, 'ei' ); // 5th declension singular
@@ -26,9 +26,9 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
                        word = word.replace( /u[ms]$/i, 'um' ); // 2nd declension singular
                        word = word.replace( /ommunia$/i, 'am' ); // 3rd declension neuter plural (partly)
                        word = word.replace( /a$/i, 'ommunia' ); // 1st declension singular
-                       word = word.replace( /libri$/i,'libros' ); // 2nd declension plural (partly)
+                       word = word.replace( /libri$/i, 'libros' ); // 2nd declension plural (partly)
                        word = word.replace( /nuntii$/i, 'nuntios' );// 2nd declension plural (partly)
-                       word = word.replace( /tio$/i,'tionem' ); // 3rd declension singular (partly)
+                       word = word.replace( /tio$/i, 'tionem' ); // 3rd declension singular (partly)
                        word = word.replace( /ns$/i, 'ntem' );
                        word = word.replace( /as$/i, 'atem');
                        word = word.replace( /es$/i, 'em' ); // 5th declension singular
@@ -38,9 +38,9 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
                        word = word.replace( /u[ms]$/i, 'o' ); // 2nd declension singular
                        word = word.replace( /ommunia$/i, 'ommunibus' ); // 3rd declension neuter plural (partly)
                        word = word.replace( /a$/i, 'a' ); // 1st declension singular
-                       word = word.replace( /libri$/i,'libris' ); // 2nd declension plural (partly)
+                       word = word.replace( /libri$/i, 'libris' ); // 2nd declension plural (partly)
                        word = word.replace( /nuntii$/i, 'nuntiis' ); // 2nd declension plural (partly)
-                       word = word.replace( /tio$/i,'tione' ); // 3rd declension singular (partly)
+                       word = word.replace( /tio$/i, 'tione' ); // 3rd declension singular (partly)
                        word = word.replace( /ns$/i, 'nte' );
                        word = word.replace( /as$/i, 'ate');
                        word = word.replace( /es$/i, 'e' ); // 5th declension singular
index bdf59be..787be36 100644 (file)
@@ -19,7 +19,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
        }
        // Checking if the $word is in plural form
        if ( word.match( /тæ$/i ) ) {
-               word = word.substring( 0, word.length - 1 );
+               word = word.slice( 0, -1 );
                endAllative = 'æм';
        }
        // Works if word is in singular form.
@@ -30,7 +30,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
        // Checking if word ends on 'у'. 'У' can be either consonant 'W' or vowel 'U' in cyrillic Ossetic.
        // Examples: {{grammar:genitive|аунеу}} = аунеуы, {{grammar:genitive|лæппу}} = лæппуйы.
        else if ( word.match( /у$/i ) ) {
-               if ( !word.substring( word.length - 2, word.length - 1 ).match( /[аæеёиоыэюя]$/i ) ) {
+               if ( !word.slice( -2, -1 ).match( /[аæеёиоыэюя]$/i ) ) {
                        jot = 'й';
                }
        } else if ( !word.match( /[бвгджзйклмнопрстфхцчшщьъ]$/i ) ) {
index b6ba59f..2077b6b 100644 (file)
@@ -15,41 +15,41 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
        }
        switch ( form ) {
                case 'genitive': // родительный падеж
-                       if ( word.substr( word.length - 1 ) === 'ь' ) {
-                               word = word.substr(0, word.length - 1 ) + 'я';
-                       } else if ( word.substr( word.length - 2 ) === 'ия' ) {
-                               word = word.substr(0, word.length - 2 ) + 'ии';
-                       } else if ( word.substr( word.length - 2 ) === 'ка' ) {
-                               word = word.substr(0, word.length - 2 ) + 'ки';
-                       } else if ( word.substr( word.length - 2 )  === 'ти' ) {
-                               word = word.substr(0, word.length - 2 ) + 'тей';
-                       } else if ( word.substr( word.length - 2 ) === 'ды' ) {
-                               word = word.substr(0, word.length - 2 ) + 'дов';
-                       } else if ( word.substr( word.length - 1 ) === 'д' ) {
-                               word = word.substr(0, word.length - 1 ) + 'да';
-                       } else if ( word.substr( word.length - 3 ) === 'ные' ) {
-                               word = word.substr(0, word.length - 3 ) + 'ных';
-                       } else if ( word.substr( word.length - 3 ) === 'ник' ) {
-                               word = word.substr(0, word.length - 3 ) + 'ника';
+                       if ( word.slice( -1 ) === 'ь' ) {
+                               word = word.slice( 0, -1 ) + 'я';
+                       } else if ( word.slice( -2 ) === 'ия' ) {
+                               word = word.slice( 0, -2 ) + 'ии';
+                       } else if ( word.slice( -2 ) === 'ка' ) {
+                               word = word.slice( 0, -2 ) + 'ки';
+                       } else if ( word.slice( -2 ) === 'ти' ) {
+                               word = word.slice( 0, -2 ) + 'тей';
+                       } else if ( word.slice( -2 ) === 'ды' ) {
+                               word = word.slice( 0, -2 ) + 'дов';
+                       } else if ( word.slice( -1 ) === 'д' ) {
+                               word = word.slice( 0, -1 ) + 'да';
+                       } else if ( word.slice( -3 ) === 'ные' ) {
+                               word = word.slice( 0, -3 ) + 'ных';
+                       } else if ( word.slice( -3 ) === 'ник' ) {
+                               word = word.slice( 0, -3 ) + 'ника';
                        }
                        break;
                case 'prepositional': // предложный падеж
-                       if ( word.substr( word.length - 1 ) === 'ь' ) {
-                               word = word.substr(0, word.length - 1 ) + 'е';
-                       } else if ( word.substr( word.length - 2 ) === 'ия' ) {
-                               word = word.substr(0, word.length - 2 ) + 'ии';
-                       } else if ( word.substr( word.length - 2 ) === 'ка' ) {
-                               word = word.substr(0, word.length - 2 ) + 'ке';
-                       } else if ( word.substr( word.length - 2 )  === 'ти' ) {
-                               word = word.substr(0, word.length - 2 ) + 'тях';
-                       } else if ( word.substr( word.length - 2 ) === 'ды' ) {
-                               word = word.substr(0, word.length - 2 ) + 'дах';
-                       } else if ( word.substr( word.length - 1 ) === 'д' ) {
-                               word = word.substr(0, word.length - 1 ) + 'де';
-                       } else if ( word.substr( word.length - 3 ) === 'ные' ) {
-                               word = word.substr(0, word.length - 3 ) + 'ных';
-                       } else if ( word.substr( word.length - 3 ) === 'ник' ) {
-                               word = word.substr(0, word.length - 3 ) + 'нике';
+                       if ( word.slice( -1 ) === 'ь' ) {
+                               word = word.slice( 0, -1 ) + 'е';
+                       } else if ( word.slice( -2 ) === 'ия' ) {
+                               word = word.slice( 0, -2 ) + 'ии';
+                       } else if ( word.slice( -2 ) === 'ка' ) {
+                               word = word.slice( 0, -2 ) + 'ке';
+                       } else if ( word.slice( -2 ) === 'ти' ) {
+                               word = word.slice( 0, -2 ) + 'тях';
+                       } else if ( word.slice( -2 ) === 'ды' ) {
+                               word = word.slice( 0, -2 ) + 'дах';
+                       } else if ( word.slice( -1 ) === 'д' ) {
+                               word = word.slice( 0, -1 ) + 'де';
+                       } else if ( word.slice( -3 ) === 'ные' ) {
+                               word = word.slice( 0, -3 ) + 'ных';
+                       } else if ( word.slice( -3 ) === 'ник' ) {
+                               word = word.slice( 0, -3 ) + 'нике';
                        }
                        break;
        }
index 69f7ec5..550a388 100644 (file)
@@ -9,26 +9,26 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
        }
        switch ( form ) {
                case 'genitive': // родовий відмінок
-                       if ( word.substr( word.length - 4 ) !== 'вікі' && word.substr( word.length - 4 ) !== 'Вікі' ) {
-                               if ( word.substr( word.length - 1 ) === 'ь' ) {
-                                       word = word.substr(0, word.length - 1 ) + 'я';
-                               } else if ( word.substr( word.length - 2 ) === 'ія' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'ії';
-                               } else if ( word.substr( word.length - 2 ) === 'ка' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'ки';
-                               } else if ( word.substr( word.length - 2 ) === 'ти' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'тей';
-                               } else if ( word.substr( word.length - 2 ) === 'ды' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'дов';
-                               } else if ( word.substr( word.length - 3 ) === 'ник' ) {
-                                       word = word.substr(0, word.length - 3 ) + 'ника';
+                       if ( word.slice( -4 ) !== 'вікі' && word.slice( -4 ) !== 'Вікі' ) {
+                               if ( word.slice( -1 ) === 'ь' ) {
+                                       word = word.slice(0, -1 ) + 'я';
+                               } else if ( word.slice( -2 ) === 'ія' ) {
+                                       word = word.slice(0, -2 ) + 'ії';
+                               } else if ( word.slice( -2 ) === 'ка' ) {
+                                       word = word.slice(0, -2 ) + 'ки';
+                               } else if ( word.slice( -2 ) === 'ти' ) {
+                                       word = word.slice(0, -2 ) + 'тей';
+                               } else if ( word.slice( -2 ) === 'ды' ) {
+                                       word = word.slice(0, -2 ) + 'дов';
+                               } else if ( word.slice( -3 ) === 'ник' ) {
+                                       word = word.slice(0, -3 ) + 'ника';
                                }
                        }
                        break;
                case 'accusative': // знахідний відмінок
-                       if ( word.substr( word.length - 4 ) !== 'вікі' && word.substr( word.length - 4 ) !== 'Вікі' ) {
-                               if ( word.substr( word.length - 2 ) === 'ія' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'ію';
+                       if ( word.slice( -4 ) !== 'вікі' && word.slice( -4 ) !== 'Вікі' ) {
+                               if ( word.slice( -2 ) === 'ія' ) {
+                                       word = word.slice(0, -2 ) + 'ію';
                                }
                        }
                        break;
diff --git a/resources/src/mediawiki.language/mediawiki.language.fallback.js b/resources/src/mediawiki.language/mediawiki.language.fallback.js
new file mode 100644 (file)
index 0000000..b1bab02
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Language-fallback-chain-related utilities for mediawiki.language.
+ */
+( function ( mw, $ ) {
+       /**
+        * @class mw.language
+        */
+
+       $.extend( mw.language, {
+
+               /**
+                * Get the language fallback chain for current UI language (not including the language itself).
+                *
+                * @return {string[]} List of language keys, e.g. `['de', 'en']`
+                */
+               getFallbackLanguages: function () {
+                       return mw.language.getData(
+                               mw.config.get( 'wgUserLanguage' ),
+                               'fallbackLanguages'
+                       ) || [];
+               },
+
+               /**
+                * Get the language fallback chain for current UI language, including the language itself.
+                *
+                * @return {string[]} List of language keys, e.g. `['pfl', de', 'en']`
+                */
+               getFallbackLanguageChain: function () {
+                       return [ mw.config.get( 'wgUserLanguage' ) ]
+                               .concat( mw.language.getFallbackLanguages() );
+               }
+
+       } );
+
+}( mediaWiki, jQuery ) );
index 5b9afcf..df95d75 100644 (file)
@@ -35,6 +35,7 @@
                 *  - `grammarForms`
                 *  - `pluralRules`
                 *  - `digitGroupingPattern`
+                *  - `fallbackLanguages`
                 *
                 * @property
                 */
index a0b5569..d4f3c69 100644 (file)
@@ -59,9 +59,9 @@ $.extend( mw.language, {
                        form = forms[index];
                        if ( /^\d+=/.test( form ) ) {
                                equalsPosition = form.indexOf( '=' );
-                               formCount = parseInt( form.substring( 0, equalsPosition ), 10 );
+                               formCount = parseInt( form.slice( 0, equalsPosition ), 10 );
                                if ( formCount === count ) {
-                                       return form.substr( equalsPosition + 1 );
+                                       return form.slice( equalsPosition + 1 );
                                }
                                forms[index] = undefined;
                        }
@@ -144,8 +144,28 @@ $.extend( mw.language, {
                        return grammarForms[form][word] || word;
                }
                return word;
-       }
+       },
 
+       /**
+        * Turn a list of string into a simple list using commas and 'and'.
+        *
+        * See Language::listToText in languages/Language.php
+        *
+        * @param {string[]} list
+        * @return {string}
+        */
+       listToText: function ( list ) {
+               var text = '', i = 0;
+               for ( ; i < list.length; i++ ) {
+                       text += list[i];
+                       if ( list.length - 2 === i ) {
+                               text += mw.msg( 'and' ) + mw.msg( 'word-separator' );
+                       } else if ( list.length - 1 !== i ) {
+                               text += mw.msg( 'comma-separator' );
+                       }
+               }
+               return text;
+       }
 } );
 
 }( mediaWiki, jQuery ) );
index 56fa0da..a0b8141 100644 (file)
@@ -34,7 +34,7 @@
        }
 
        /**
-        * Efficiently replicate a string `n` times.
+        * Replicate a string 'n' times.
         *
         * @private
         * @param {string} str The string to replicate
@@ -47,9 +47,8 @@
                }
 
                var buf = [];
-               while (num) {
+               while ( num-- ) {
                        buf.push( str );
-                       str += str;
                }
                return buf.join( '' );
        }
 
                        // Truncate fractional
                        if ( maxPlaces < fractional.length ) {
-                               valueParts[1] = fractional.substr( 0, maxPlaces );
+                               valueParts[1] = fractional.slice( 0, maxPlaces );
                        }
                } else {
                        if ( valueParts[1] ) {
 
                        // Truncate whole
                        if ( patternDigits.indexOf( '#' ) === -1 ) {
-                               valueParts[0] = valueParts[0].substr( valueParts[0].length - padLength );
+                               valueParts[0] = valueParts[0].slice( valueParts[0].length - padLength );
                        }
                }
 
 
                if ( index !== -1 ) {
                        groupSize = patternParts[0].length - index - 1;
-                       remainder = patternParts[0].substr( 0, index );
+                       remainder = patternParts[0].slice( 0, index );
                        index = remainder.lastIndexOf( ',' );
                        if ( index !== -1 ) {
                                groupSize2 = remainder.length - index - 1;
                }
 
                for ( whole = valueParts[0]; whole; ) {
-                       off = whole.length - groupSize;
-
-                       pieces.push( ( off > 0 ) ? whole.substr( off ) : whole );
+                       off = groupSize ? whole.length - groupSize : 0;
+                       pieces.push( ( off > 0 ) ? whole.slice( off ) : whole );
                        whole = ( off > 0 ) ? whole.slice( 0, off ) : '';
 
                        if ( groupSize2 ) {
                                groupSize = groupSize2;
+                               groupSize2 = null;
                        }
                }
                valueParts[0] = pieces.reverse().join( options.group );
diff --git a/resources/src/mediawiki.legacy/ajax.js b/resources/src/mediawiki.legacy/ajax.js
new file mode 100644 (file)
index 0000000..6b9464a
--- /dev/null
@@ -0,0 +1,194 @@
+/**
+ * Remote Scripting Library
+ * Copyright 2005 modernmethod, inc
+ * Under the open source BSD license
+ * http://www.modernmethod.com/sajax/
+ */
+
+/*jshint camelcase:false */
+/*global alert */
+( function ( mw ) {
+
+/**
+ * if sajax_debug_mode is true, this function outputs given the message into
+ * the element with id = sajax_debug; if no such element exists in the document,
+ * it is injected.
+ */
+function debug( text ) {
+       if ( !window.sajax_debug_mode ) {
+               return false;
+       }
+
+       var b, m,
+               e = document.getElementById( 'sajax_debug' );
+
+       if ( !e ) {
+               e = document.createElement( 'p' );
+               e.className = 'sajax_debug';
+               e.id = 'sajax_debug';
+
+               b = document.getElementsByTagName( 'body' )[0];
+
+               if ( b.firstChild ) {
+                       b.insertBefore( e, b.firstChild );
+               } else {
+                       b.appendChild( e );
+               }
+       }
+
+       m = document.createElement( 'div' );
+       m.appendChild( document.createTextNode( text ) );
+
+       e.appendChild( m );
+
+       return true;
+}
+
+/**
+ * Compatibility wrapper for creating a new XMLHttpRequest object.
+ */
+function createXhr() {
+       debug( 'sajax_init_object() called..' );
+       var a;
+       try {
+               // Try the new style before ActiveX so we don't
+               // unnecessarily trigger warnings in IE 7 when
+               // set to prompt about ActiveX usage
+               a = new XMLHttpRequest();
+       } catch ( xhrE ) {
+               try {
+                       a = new window.ActiveXObject( 'Msxml2.XMLHTTP' );
+               } catch ( msXmlE ) {
+                       try {
+                               a = new window.ActiveXObject( 'Microsoft.XMLHTTP' );
+                       } catch ( msXhrE ) {
+                               a = null;
+                       }
+               }
+       }
+       if ( !a ) {
+               debug( 'Could not create connection object.' );
+       }
+
+       return a;
+}
+
+/**
+ * Perform an AJAX call to MediaWiki. Calls are handled by AjaxDispatcher.php
+ *   func_name - the name of the function to call. Must be registered in $wgAjaxExportList
+ *   args - an array of arguments to that function
+ *   target - the target that will handle the result of the call. If this is a function,
+ *            if will be called with the XMLHttpRequest as a parameter; if it's an input
+ *            element, its value will be set to the resultText; if it's another type of
+ *            element, its innerHTML will be set to the resultText.
+ *
+ * Example:
+ *    sajax_do_call( 'doFoo', [1, 2, 3], document.getElementById( 'showFoo' ) );
+ *
+ * This will call the doFoo function via MediaWiki's AjaxDispatcher, with
+ * (1, 2, 3) as the parameter list, and will show the result in the element
+ * with id = showFoo
+ */
+function doAjaxRequest( func_name, args, target ) {
+       var i, x, uri, post_data;
+       uri = mw.util.wikiScript() + '?action=ajax';
+       if ( window.sajax_request_type === 'GET' ) {
+               if ( uri.indexOf( '?' ) === -1 ) {
+                       uri = uri + '?rs=' + encodeURIComponent( func_name );
+               } else {
+                       uri = uri + '&rs=' + encodeURIComponent( func_name );
+               }
+               for ( i = 0; i < args.length; i++ ) {
+                       uri = uri + '&rsargs[]=' + encodeURIComponent( args[i] );
+               }
+               //uri = uri + '&rsrnd=' + new Date().getTime();
+               post_data = null;
+       } else {
+               post_data = 'rs=' + encodeURIComponent( func_name );
+               for ( i = 0; i < args.length; i++ ) {
+                       post_data = post_data + '&rsargs[]=' + encodeURIComponent( args[i] );
+               }
+       }
+       x = createXhr();
+       if ( !x ) {
+               alert( 'AJAX not supported' );
+               return false;
+       }
+
+       try {
+               x.open( window.sajax_request_type, uri, true );
+       } catch ( e ) {
+               if ( location.hostname === 'localhost' ) {
+                       alert( 'Your browser blocks XMLHttpRequest to "localhost", try using a real hostname for development/testing.' );
+               }
+               throw e;
+       }
+       if ( window.sajax_request_type === 'POST' ) {
+               x.setRequestHeader( 'Method', 'POST ' + uri + ' HTTP/1.1' );
+               x.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
+       }
+       x.setRequestHeader( 'Pragma', 'cache=yes' );
+       x.setRequestHeader( 'Cache-Control', 'no-transform' );
+       x.onreadystatechange = function () {
+               if ( x.readyState !== 4 ) {
+                       return;
+               }
+
+               debug( 'received (' + x.status + ' ' + x.statusText + ') ' + x.responseText );
+
+               //if ( x.status != 200 )
+               //      alert( 'Error: ' + x.status + ' ' + x.statusText + ': ' + x.responseText );
+               //else
+
+               if ( typeof target === 'function' ) {
+                       target( x );
+               } else if ( typeof target === 'object' ) {
+                       if ( target.tagName === 'INPUT' ) {
+                               if ( x.status === 200 ) {
+                                       target.value = x.responseText;
+                               }
+                               //else alert( 'Error: ' + x.status + ' ' + x.statusText + ' (' + x.responseText + ')' );
+                       } else {
+                               if ( x.status === 200 ) {
+                                       target.innerHTML = x.responseText;
+                               } else {
+                                       target.innerHTML = '<div class="error">Error: ' + x.status +
+                                               ' ' + x.statusText + ' (' + x.responseText + ')</div>';
+                               }
+                       }
+               } else {
+                       alert( 'Bad target for sajax_do_call: not a function or object: ' + target );
+               }
+       };
+
+       debug( func_name + ' uri = ' + uri + ' / post = ' + post_data );
+       x.send( post_data );
+       debug( func_name + ' waiting..' );
+
+       return true;
+}
+
+/**
+ * @return {boolean} Whether the browser supports AJAX
+ */
+function wfSupportsAjax() {
+       var request = createXhr(),
+               supportsAjax = request ? true : false;
+
+       request = undefined;
+       return supportsAjax;
+}
+
+// Expose + Mark as deprecated
+var deprecationNotice = 'Sajax is deprecated, use jQuery.ajax or mediawiki.api instead.';
+
+// Variables
+mw.log.deprecate( window, 'sajax_debug_mode', false, deprecationNotice );
+mw.log.deprecate( window, 'sajax_request_type', 'GET', deprecationNotice );
+// Methods
+mw.log.deprecate( window, 'sajax_debug', debug, deprecationNotice );
+mw.log.deprecate( window, 'sajax_init_object', createXhr, deprecationNotice );
+mw.log.deprecate( window, 'sajax_do_call', doAjaxRequest, deprecationNotice );
+mw.log.deprecate( window, 'wfSupportsAjax', wfSupportsAjax, deprecationNotice );
+
+}( mediaWiki ) );
diff --git a/resources/src/mediawiki.legacy/commonPrint.css b/resources/src/mediawiki.legacy/commonPrint.css
new file mode 100644 (file)
index 0000000..830b02f
--- /dev/null
@@ -0,0 +1,435 @@
+/**
+ * MediaWiki Print style sheet for CSS2-capable browsers.
+ * Copyright Gabriel Wicke, http://www.aulinx.de/
+ *
+ * Derived from the plone (http://plone.org/) styles
+ * Copyright Alexander Limi
+ */
+
+/* Thanks to A List Apart (http://alistapart.com/) for useful extras */
+
+/**
+ * Hide all the elements irrelevant for printing
+ */
+.noprint,
+div#jump-to-nav,
+.mw-jump,
+div.top,
+div#column-one,
+#colophon,
+.mw-editsection,
+.mw-editsection-like,
+.toctoggle,
+#toc.tochidden,
+div#f-poweredbyico,
+div#f-copyrightico,
+li#viewcount,
+li#about,
+li#disclaimer,
+li#mobileview,
+li#privacy,
+#footer-places,
+.mw-hidden-catlinks,
+tr.mw-metadata-show-hide-extended,
+span.mw-filepage-other-resolutions,
+#filetoc,
+.usermessage,
+.patrollink,
+#mw-navigation,
+#siteNotice {
+       display: none;
+}
+
+/**
+ * Pagination
+ */
+.wikitable, .thumb, img {
+       page-break-inside: avoid;
+}
+
+h2, h3, h4, h5, h6 {
+       page-break-after: avoid;
+}
+
+p {
+       widows: 3;
+       orphans: 3;
+}
+
+/**
+ * Generic HTML elements
+ */
+body {
+       background: white;
+       color: black;
+       margin: 0;
+       padding: 0;
+}
+
+ul {
+       list-style-type: square;
+}
+
+h1, h2, h3, h4, h5, h6 {
+       font-weight: bold;
+}
+
+dt {
+       font-weight: bold;
+}
+
+p {
+       margin: 1em 0;
+       line-height: 1.2em;
+}
+
+pre, .mw-code {
+       border: 1pt dashed black;
+       white-space: pre;
+       font-size: 8pt;
+       overflow: auto;
+       padding: 1em 0;
+       background: white;
+       color: black;
+}
+
+/**
+ * MediaWiki-specific elements
+ */
+#globalWrapper {
+       width: 100% !important;
+       min-width: 0 !important;
+}
+
+.mw-body {
+       background: white;
+       border: none !important;
+       padding: 0 !important;
+       margin: 0 !important;
+       direction: ltr;
+       color: black;
+}
+
+#column-content {
+       margin: 0 !important;
+}
+
+#column-content .mw-body {
+       padding: 1em;
+       margin: 0 !important;
+}
+
+#toc {
+       border: 1px solid #aaaaaa;
+       background-color: #f9f9f9;
+       padding: 5px;
+       display: -moz-inline-block;
+       display: inline-block;
+       display: table;
+       /* IE7 and earlier */
+       zoom: 1;
+       *display: inline;
+}
+
+#footer {
+       background: white;
+       color: black;
+       margin-top: 1em;
+       border-top: 1px solid #AAA;
+       direction: ltr;
+}
+
+img {
+       border: none;
+       vertical-align: middle;
+}
+
+/* math */
+span.texhtml {
+       font-family: serif;
+}
+
+/**
+ * Links
+ */
+a.stub,
+a.new {
+       color: #ba0000;
+       text-decoration: none;
+}
+
+a {
+       color: black !important;
+       background: none !important;
+       padding: 0 !important;
+}
+
+a:link, a:visited {
+       color: #520;
+       background: transparent;
+       text-decoration: underline;
+}
+
+/* Expand URLs for printing */
+.mw-body a.external.text:after,
+.mw-body a.external.autonumber:after {
+       content: " (" attr(href) ")";
+}
+
+/* Expand protocol-relative URLs for printing */
+.mw-body a.external.text[href^='//']:after,
+.mw-body a.external.autonumber[href^='//']:after {
+       content: " (https:" attr(href) ")";
+}
+
+/* MSIE/Win doesn't understand 'inherit' */
+a,
+a.external,
+a.new,
+a.stub {
+       color: black !important;
+       text-decoration: none !important;
+}
+
+/* Continue ... */
+a,
+a.external,
+a.new,
+a.stub {
+       color: inherit !important;
+       text-decoration: inherit !important;
+}
+
+/**
+ * Floating divs
+ */
+div.floatright {
+       float: right;
+       clear: right;
+       position: relative;
+       margin: 0.5em 0 0.8em 1.4em;
+}
+
+div.floatright p {
+       font-style: italic;
+}
+
+div.floatleft {
+       float: left;
+       clear: left;
+       position: relative;
+       margin: 0.5em 1.4em 0.8em 0;
+}
+
+div.floatleft p {
+       font-style: italic;
+}
+
+div.center {
+       text-align: center;
+}
+
+/**
+ * Thumbnails
+ */
+div.thumb {
+       border: none;
+       width: auto;
+       margin-top: 0.5em;
+       margin-bottom: 0.8em;
+       background-color: transparent;
+}
+
+div.thumbinner {
+       border: 1px solid #cccccc;
+       padding: 3px !important;
+       background-color: White;
+       font-size: 94%;
+       text-align: center;
+       overflow: hidden;
+}
+
+html .thumbimage {
+       border: 1px solid #cccccc;
+}
+
+html .thumbcaption {
+       border: none;
+       text-align: left;
+       line-height: 1.4em;
+       padding: 3px !important;
+       font-size: 94%;
+}
+
+div.magnify {
+       display: none;
+}
+
+/* @noflip */
+div.tright {
+       float: right;
+       clear: right;
+       margin: 0.5em 0 0.8em 1.4em;
+}
+
+/* @noflip */
+div.tleft {
+       float: left;
+       clear: left;
+       margin: 0.5em 1.4em 0.8em 0;
+}
+
+img.thumbborder {
+       border: 1px solid #dddddd;
+}
+
+/**
+ * Galleries (see shared.css for more info)
+ */
+li.gallerybox {
+       vertical-align: top;
+       display: inline-block;
+}
+
+ul.gallery, li.gallerybox {
+       zoom: 1;
+       *display: inline;
+}
+
+ul.gallery {
+       margin: 2px;
+       padding: 2px;
+       display: block;
+}
+
+li.gallerycaption {
+       font-weight: bold;
+       text-align: center;
+       display: block;
+       word-wrap: break-word;
+}
+
+li.gallerybox div.thumb {
+       text-align: center;
+       border: 1px solid #ccc;
+       margin: 2px;
+}
+
+div.gallerytext {
+       overflow: hidden;
+       font-size: 94%;
+       padding: 2px 4px;
+       word-wrap: break-word;
+}
+
+/**
+ * Diff rendering
+ */
+table.diff {
+       background: white;
+}
+
+td.diff-otitle {
+       background: #ffffff;
+}
+
+td.diff-ntitle {
+       background: #ffffff;
+}
+
+td.diff-addedline {
+       background: #ccffcc;
+       font-size: smaller;
+       border: solid 2px black;
+}
+
+td.diff-deletedline {
+       background: #ffffaa;
+       font-size: smaller;
+       border: dotted 2px black;
+}
+
+td.diff-context {
+       background: #eeeeee;
+       font-size: smaller;
+}
+
+.diffchange {
+       color: silver;
+       font-weight: bold;
+       text-decoration: underline;
+}
+
+/**
+ * Table rendering
+ * As on shared.css but with white background.
+ */
+table.wikitable,
+table.mw_metadata {
+       margin: 1em 0;
+       border: 1px #aaa solid;
+       background: white;
+       border-collapse: collapse;
+}
+
+table.wikitable > tr > th, table.wikitable > tr > td,
+table.wikitable > * > tr > th, table.wikitable > * > tr > td,
+.mw_metadata th, .mw_metadata td {
+       border: 1px #aaa solid;
+       padding: 0.2em;
+}
+
+table.wikitable > tr > th,
+table.wikitable > * > tr > th,
+.mw_metadata th {
+       text-align: center;
+       background: white;
+       font-weight: bold;
+}
+
+table.wikitable > caption,
+.mw_metadata caption {
+       font-weight: bold;
+}
+
+table.listing,
+table.listing td {
+       border: 1pt solid black;
+       border-collapse: collapse;
+}
+
+a.sortheader {
+       margin: 0 0.3em;
+}
+
+/**
+ * Categories
+ */
+.catlinks ul {
+       display: inline;
+       margin: 0;
+       padding: 0;
+       list-style: none;
+       list-style-type: none;
+       list-style-image: none;
+       vertical-align: middle !ie;
+}
+
+.catlinks li {
+       display: inline-block;
+       line-height: 1.15em;
+       padding: 0 .4em;
+       border-left: 1px solid #AAA;
+       margin: 0.1em 0;
+       zoom: 1;
+       display: inline !ie;
+}
+
+.catlinks li:first-child {
+       padding-left: .2em;
+       border-left: none;
+}
+
+.printfooter {
+       padding: 1em 0 1em 0;
+}
diff --git a/resources/src/mediawiki.legacy/images/ajax-loader.gif b/resources/src/mediawiki.legacy/images/ajax-loader.gif
new file mode 100644 (file)
index 0000000..72203fd
Binary files /dev/null and b/resources/src/mediawiki.legacy/images/ajax-loader.gif differ
diff --git a/resources/src/mediawiki.legacy/images/checker.png b/resources/src/mediawiki.legacy/images/checker.png
new file mode 100644 (file)
index 0000000..3e9e3d0
Binary files /dev/null and b/resources/src/mediawiki.legacy/images/checker.png differ
diff --git a/resources/src/mediawiki.legacy/images/feed-icon.png b/resources/src/mediawiki.legacy/images/feed-icon.png
new file mode 100644 (file)
index 0000000..00f49f6
Binary files /dev/null and b/resources/src/mediawiki.legacy/images/feed-icon.png differ
diff --git a/resources/src/mediawiki.legacy/images/feed-icon.svg b/resources/src/mediawiki.legacy/images/feed-icon.svg
new file mode 100644 (file)
index 0000000..6e5f570
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 256 256"><defs><linearGradient x1=".085" y1=".085" x2=".915" y2=".915" id="a"><stop offset="0" stop-color="#E3702D"/><stop offset=".107" stop-color="#EA7D31"/><stop offset=".35" stop-color="#F69537"/><stop offset=".5" stop-color="#FB9E3A"/><stop offset=".702" stop-color="#EA7C31"/><stop offset=".887" stop-color="#DE642B"/><stop offset="1" stop-color="#D95B29"/></linearGradient></defs><rect width="256" height="256" rx="55" ry="55" fill="#CC5D15"/><rect width="246" height="246" rx="50" ry="50" x="5" y="5" fill="#F49C52"/><rect width="236" height="236" rx="47" ry="47" x="10" y="10" fill="url(#a)"/><circle cx="68" cy="189" r="24" fill="#FFF"/><path d="M160 213h-34a82 82 0 0 0-82-82v-34a116 116 0 0 1 116 116zM184 213a140 140 0 0 0-140-140v-35a175 175 0 0 1 175 175z" fill="#FFF"/></svg>
\ No newline at end of file
diff --git a/resources/src/mediawiki.legacy/images/help-question-hover.gif b/resources/src/mediawiki.legacy/images/help-question-hover.gif
new file mode 100644 (file)
index 0000000..515138d
Binary files /dev/null and b/resources/src/mediawiki.legacy/images/help-question-hover.gif differ
diff --git a/resources/src/mediawiki.legacy/images/help-question.gif b/resources/src/mediawiki.legacy/images/help-question.gif
new file mode 100644 (file)
index 0000000..b4fc9c5
Binary files /dev/null and b/resources/src/mediawiki.legacy/images/help-question.gif differ
diff --git a/resources/src/mediawiki.legacy/images/question.png b/resources/src/mediawiki.legacy/images/question.png
new file mode 100644 (file)
index 0000000..f7405d2
Binary files /dev/null and b/resources/src/mediawiki.legacy/images/question.png differ
diff --git a/resources/src/mediawiki.legacy/images/question.svg b/resources/src/mediawiki.legacy/images/question.svg
new file mode 100644 (file)
index 0000000..98fbe8d
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="21.059" height="21.06"><path fill="#575757" d="M10.529 0c-5.814 0-10.529 4.714-10.529 10.529s4.715 10.53 10.529 10.53c5.816 0 10.529-4.715 10.529-10.53s-4.712-10.529-10.529-10.529zm-.002 16.767c-.861 0-1.498-.688-1.498-1.516 0-.862.637-1.534 1.498-1.534.828 0 1.5.672 1.5 1.534 0 .827-.672 1.516-1.5 1.516zm2.137-6.512c-.723.568-1 .931-1 1.739v.5h-2.205v-.603c0-1.517.449-2.136 1.154-2.688.707-.552 1.139-.845 1.139-1.637 0-.672-.414-1.051-1.24-1.051-.707 0-1.328.189-1.982.638l-1.051-1.807c.861-.604 1.93-1.034 3.342-1.034 1.912 0 3.516 1.051 3.516 3.066-.001 1.43-.794 2.188-1.673 2.877z"/></svg>
\ No newline at end of file
diff --git a/resources/src/mediawiki.legacy/images/spinner.gif b/resources/src/mediawiki.legacy/images/spinner.gif
new file mode 100644 (file)
index 0000000..6146be4
Binary files /dev/null and b/resources/src/mediawiki.legacy/images/spinner.gif differ
diff --git a/resources/src/mediawiki.legacy/oldshared.css b/resources/src/mediawiki.legacy/oldshared.css
new file mode 100644 (file)
index 0000000..4424fbd
--- /dev/null
@@ -0,0 +1,494 @@
+/**
+ * oldshared.css
+ * This file contains CSS settings common to Wikistandard, Nostalgia and
+ * CologneBlue, the old pre-Monobook skins
+ */
+
+/* For clarity, explicitly state some recommendations from
+ * http://www.w3.org/TR/CSS21/sample.html to make sure the editsection links scale right
+ */
+
+h1 {
+       font-size: 2em;
+}
+
+h2 {
+       font-size: 1.5em;
+}
+
+h3 {
+       font-size: 1.17em;
+}
+
+h4 {
+       font-size: 1.11em;
+}
+
+h5 {
+       font-size: 1.05em;
+}
+
+h6 {
+       font-size: 1em;
+}
+
+h1, h2, h3, h4, h5, h6 {
+       font-weight: bolder;
+}
+
+/* Now the custom parts */
+
+#footer {
+       clear: both;
+}
+
+/* images */
+/* @noflip */
+div.floatright {
+       float: right;
+       clear: right;
+       margin: 0 0 1em 1em;
+}
+
+/* @noflip */
+div.floatright p {
+       font-style: italic;
+}
+
+/* @noflip */
+div.floatleft {
+       float: left;
+       clear: left;
+       margin: 0.3em 0.5em 0.5em 0;
+}
+
+/* @noflip */
+div.floatleft p {
+       font-style: italic;
+}
+
+/* table standards */
+table.rimage {
+       float: right;
+       margin-left: 1em;
+       margin-bottom: 1em;
+       text-align: center;
+       font-size: smaller;
+}
+
+/* thumbnails */
+div.thumb {
+       margin-bottom: .5em;
+       border-style: solid;
+       border-color: white;
+       width: auto;
+}
+
+div.thumbinner {
+       border: 1px solid #ccc;
+       padding: 3px;
+       background-color: #f9f9f9;
+       font-size: 94%;
+       text-align: center;
+       overflow: hidden;
+}
+
+html .thumbimage {
+       border: 1px solid #ccc;
+}
+
+html .thumbcaption {
+       border: none;
+       line-height: 1.4em;
+       padding: 3px;
+       font-size: 94%;
+       text-align: left;
+}
+
+div.magnify {
+       float: right;
+       margin-left: 3px;
+}
+
+div.magnify a {
+       display: block;
+       /* Hide the text… */
+       text-indent: 15px;
+       white-space: nowrap;
+       overflow: hidden;
+       /* …and replace it with the image */
+       width: 15px;
+       height: 11px;
+       /* @embed */
+       background: url(images/magnify-clip-ltr.png) center center no-repeat;
+       /* Don't annoy people who copy-paste everything too much */
+       -moz-user-select: none;
+       -webkit-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+
+/* Temporary WMF deployment hack, to be removed before 1.24 release */
+div.magnify img {
+       display: none;
+}
+
+/* @noflip */
+div.tright {
+       clear: right;
+       float: right;
+       border-width: .5em 0 .8em 1.4em;
+}
+
+/* @noflip */
+div.tleft {
+       float: left;
+       clear: left;
+       margin-right: .5em;
+       border-width: .5em 1.4em .8em 0;
+}
+
+img.thumbborder {
+       border: 1px solid #dddddd;
+}
+
+/* Page history styling */
+/* the auto-generated edit comments */
+.autocomment {
+       color: #4b4b4b;
+}
+
+img {
+       border: none;
+}
+
+#toc,
+.toc {
+       border: 1px solid #bba;
+       background-color: #f7f8ff;
+       padding: 5px;
+       font-size: 95%;
+       text-align: center;
+       display: -moz-inline-block;
+       display: inline-block;
+       display: table;
+
+       /* IE7 and earlier */
+       zoom: 1;
+       *display: inline;
+
+       padding: 7px;
+}
+
+/* CSS for backwards-compatibility with cached page renders and creative uses in wikitext */
+table#toc,
+table.toc {
+       border-collapse: collapse;
+}
+
+/* Remove additional paddings inside table-cells that are not present in <div>s */
+table#toc td,
+table.toc td {
+       padding: 0;
+}
+
+#toc h2,
+.toc h2 {
+       display: inline;
+       border: none;
+       padding: 0;
+       font-size: 100%;
+       font-weight: bold;
+}
+
+#toc ul,
+.toc ul {
+       list-style-type: none;
+       list-style-image: none;
+       padding: 0;
+       text-align: left;
+}
+
+#toc ul ul,
+.toc ul ul {
+       margin: 0 0 0 2em;
+}
+
+#toc .toctoggle,
+.toc .toctoggle {
+       font-size: 94%;
+}
+
+.error {
+       color: red;
+       font-size: larger;
+}
+
+/* preference page with js-genrated toc */
+#preftoc {
+       float: left;
+       margin: 1em 1em 1em 1em;
+       width: 13em;
+}
+
+#preftoc li {
+       border: 1px solid White;
+}
+
+#preftoc li.selected {
+       background-color: #f9f9f9;
+       border: 1px dashed #aaaaaa;
+}
+
+#preftoc a,
+#preftoc a:active {
+       display: block;
+       color: #005189;
+}
+
+.mw-prefs-buttons {
+       clear: left;
+       float: left;
+       margin-top: 1em;
+}
+
+div.htmlform-tip {
+       font-size: 94%;
+       margin-top: 0.4em;
+       color: #666;
+}
+
+fieldset.prefsection {
+       margin-top: 1em;
+}
+
+fieldset.operaprefsection {
+       margin-left: 15em;
+}
+
+/* emulate center */
+.center {
+       width: 100%;
+       text-align: center;
+}
+
+*.center * {
+       margin-left: auto;
+       margin-right: auto;
+}
+
+/* small for tables and similar */
+.small {
+       font-size: 94%;
+}
+
+table.small {
+       font-size: 100%;
+}
+
+/* use this instead of #toc for page content */
+.toccolours {
+       border: 1px solid #aaaaaa;
+       background-color: #f9f9f9;
+       padding: 5px;
+       font-size: 95%;
+}
+
+#siteNotice {
+       border: 1px solid #aaaaaa;
+       padding-left: 0.5em;
+       padding-right: 0.5em;
+}
+
+.sharedUploadNotice {
+       font-style: italic;
+}
+
+span.unpatrolled {
+       font-weight: bold;
+       color: red;
+}
+
+span.updatedmarker {
+       color: black;
+       background-color: #00FF00;
+}
+
+div.gallerybox {
+       width: 150px;
+}
+
+span.comment {
+       font-style: italic;
+}
+
+span.changedby {
+       font-size: 95%;
+}
+
+.previewnote {
+       text-align: center;
+       color: #cc0000;
+}
+
+.editExternally {
+       border-style: solid;
+       border-width: 1px;
+       border-color: gray;
+       background: #ffffff;
+       padding: 3px;
+       margin-top: 0.5em;
+       float: left;
+       font-size: small;
+       text-align: center;
+}
+
+.editExternallyHelp {
+       font-style: italic;
+       color: gray;
+}
+
+li span.deleted {
+       text-decoration: line-through;
+       color: #888;
+       font-style: italic;
+}
+
+/* Classes for Exif data display */
+table.mw_metadata {
+       margin-left: 0.5em;
+}
+
+table.mw_metadata caption {
+       font-weight: bold;
+}
+
+table.mw_metadata th {
+       font-weight: normal;
+}
+
+table.mw_metadata td {
+       padding: 0.1em;
+}
+
+table.mw_metadata {
+       border: none;
+       border-collapse: collapse;
+}
+
+table.mw_metadata td,
+table.mw_metadata th {
+       border: 1px solid #aaaaaa;
+       padding-left: 4px;
+       padding-right: 4px;
+}
+
+table.mw_metadata th {
+       background-color: #f9f9f9;
+}
+
+table.mw_metadata td {
+       background-color: #fcfcfc;
+}
+
+table.mw_metadata td.spacer {
+       background: inherit;
+       border-top: none;
+       border-bottom: none;
+}
+
+.visualClear {
+       clear: both;
+}
+
+/* Allmessages table */
+#allmessagestable th {
+       background-color: #b2b2ff;
+}
+
+#allmessagestable tr.orig {
+       background-color: #ffe2e2;
+}
+
+#allmessagestable tr.new {
+       background-color: #e2ffe2;
+}
+
+#allmessagestable tr.def {
+       background-color: #f0f0ff;
+}
+
+#jump-to-nav {
+       display: none;
+}
+
+div.multipageimagenavbox {
+       border: solid 1px silver;
+       padding: 4px;
+       margin: 1em;
+       background: #f0f0f0;
+}
+
+div.multipageimagenavbox div.thumb {
+       border: none;
+       margin-left: 2em;
+       margin-right: 2em;
+}
+
+div.multipageimagenavbox hr {
+       margin: 6px;
+}
+
+table.multipageimage td {
+       text-align: center;
+}
+
+.templatesUsed {
+       margin-top: 1em;
+}
+
+.MediaTransformError {
+       border: thin solid #777;
+       background-color: #ccc;
+       padding: 0.1em;
+}
+
+.MediaTransformError td {
+       text-align: center;
+       vertical-align: middle;
+       font-size: 90%;
+}
+
+form#specialpages {
+       display: inline;
+}
+
+body {
+       direction: ltr;
+       unicode-bidi: embed;
+       background-color: #ffffec;
+}
+
+body.ns-0 {
+       background-color: white;
+}
+
+/** RTL specific CSS starts here **/
+
+/**
+ * Lists:
+ * The following lines don't have a visible effect on non-Gecko browsers
+ * They fix a problem with Gecko browsers rendering lists to the right of
+ * left-floated objects in an RTL layout.
+ */
+/* @noflip */
+html > body.rtl div#article ul {
+       display: table;
+}
+
+/* @noflip */
+html > body.rtl .mw-body ul#filetoc {
+       display: block;
+}
+
+/* RTL specific CSS ends here **/
diff --git a/resources/src/mediawiki.legacy/protect.js b/resources/src/mediawiki.legacy/protect.js
new file mode 100644 (file)
index 0000000..f9069b6
--- /dev/null
@@ -0,0 +1,240 @@
+( function ( mw, $ ) {
+
+var ProtectionForm = window.ProtectionForm = {
+       /**
+        * Set up the protection chaining interface (i.e. "unlock move permissions" checkbox)
+        * on the protection form
+        */
+       init: function () {
+               var $cell = $( '<td>' ), $row = $( '<tr>' ).append( $cell );
+
+               if ( !$( '#mwProtectSet' ).length ) {
+                       return false;
+               }
+
+               if ( mw.config.get( 'wgCascadeableLevels' ) !== undefined ) {
+                       $( 'form#mw-Protect-Form' ).submit( this.toggleUnchainedInputs.bind( ProtectionForm, true ) );
+               }
+               this.getExpirySelectors().each( function () {
+                       $( this ).change( ProtectionForm.updateExpiryList.bind( ProtectionForm, this ) );
+               } );
+               this.getExpiryInputs().each( function () {
+                       $( this ).on( 'keyup change', ProtectionForm.updateExpiry.bind( ProtectionForm, this ) );
+               } );
+               this.getLevelSelectors().each( function () {
+                       $( this ).change( ProtectionForm.updateLevels.bind( ProtectionForm, this ) );
+               } );
+
+               $( '#mwProtectSet > tbody > tr:first' ).after( $row );
+
+               // If there is only one protection type, there is nothing to chain
+               if ( $( '[id ^= mw-protect-table-]' ).length > 1 ) {
+                       $cell.append(
+                               $( '<input>' )
+                                       .attr( { id: 'mwProtectUnchained', type: 'checkbox' } )
+                                       .click( this.onChainClick.bind( this ) )
+                                       .prop( 'checked', !this.areAllTypesMatching() ),
+                               document.createTextNode( ' ' ),
+                               $( '<label>' )
+                                       .attr( 'for', 'mwProtectUnchained' )
+                                       .text( mw.msg( 'protect-unchain-permissions' ) )
+                       );
+
+                       this.toggleUnchainedInputs( !this.areAllTypesMatching() );
+               }
+
+               $( '#mwProtect-reason' ).byteLimit( 180 );
+
+               this.updateCascadeCheckbox();
+       },
+
+       /**
+        * Sets the disabled attribute on the cascade checkbox depending on the current selected levels
+        */
+       updateCascadeCheckbox: function () {
+               this.getLevelSelectors().each( function () {
+                       if ( !ProtectionForm.isCascadeableLevel( $( this ).val() ) ) {
+                               $( '#mwProtect-cascade' ).prop( { checked: false, disabled: true } );
+                               return false;
+                       } else {
+                               $( '#mwProtect-cascade' ).prop( 'disabled', false );
+                       }
+               } );
+       },
+
+       /**
+        * Checks if a cerain protection level is cascadeable.
+        *
+        * @param {string} level
+        * @return {boolean}
+        */
+       isCascadeableLevel: function ( level ) {
+               return $.inArray( level, mw.config.get( 'wgCascadeableLevels' ) ) !== -1;
+       },
+
+       /**
+        * When protection levels are locked together, update the rest
+        * when one action's level changes
+        *
+        * @param {Element} source Level selector that changed
+        */
+       updateLevels: function ( source ) {
+               if ( !this.isUnchained() ) {
+                       this.setAllSelectors( source.selectedIndex );
+               }
+               this.updateCascadeCheckbox();
+       },
+
+       /**
+        * When protection levels are locked together, update the
+        * expiries when one changes
+        *
+        * @param {Element} source expiry input that changed
+        */
+
+       updateExpiry: function ( source ) {
+               if ( !this.isUnchained() ) {
+                       this.getExpiryInputs().each( function () {
+                               this.value = source.value;
+                       } );
+               }
+               if ( this.isUnchained() ) {
+                       $( '#' + source.id.replace( /^mwProtect-(\w+)-expires$/, 'mwProtectExpirySelection-$1' ) ).val( 'othertime' );
+               } else {
+                       this.getExpirySelectors().each( function () {
+                               this.value = 'othertime';
+                       } );
+               }
+       },
+
+       /**
+        * When protection levels are locked together, update the
+        * expiry lists when one changes and clear the custom inputs
+        *
+        * @param {Element} source Expiry selector that changed
+        */
+       updateExpiryList: function ( source ) {
+               if ( !this.isUnchained() ) {
+                       this.getExpirySelectors().each( function () {
+                               this.value = source.value;
+                       } );
+                       this.getExpiryInputs().each( function () {
+                               this.value = '';
+                       } );
+               }
+       },
+
+       /**
+        * Update chain status and enable/disable various bits of the UI
+        * when the user changes the "unlock move permissions" checkbox
+        */
+       onChainClick: function () {
+               this.toggleUnchainedInputs( this.isUnchained() );
+               if ( !this.isUnchained() ) {
+                       this.setAllSelectors( this.getMaxLevel() );
+               }
+               this.updateCascadeCheckbox();
+       },
+
+       /**
+        * Returns true if the named attribute in all objects in the given array are matching
+        *
+        * @param {Object[]} objects
+        * @param {string} attrName
+        * @return {boolean}
+        */
+       matchAttribute: function ( objects, attrName ) {
+               return $.map( objects, function ( object ) {
+                       return object[attrName];
+               } ).filter( function ( item, index, a ) {
+                       return index === a.indexOf( item );
+               } ).length === 1;
+       },
+
+       /**
+        * Are all actions protected at the same level, with the same expiry time?
+        *
+        * @return {boolean}
+        */
+       areAllTypesMatching: function () {
+               return this.matchAttribute( this.getLevelSelectors(), 'selectedIndex' )
+                       && this.matchAttribute( this.getExpirySelectors(), 'selectedIndex' )
+                       && this.matchAttribute( this.getExpiryInputs(), 'value' );
+       },
+
+       /**
+        * Is protection chaining off?
+        *
+        * @return {boolean}
+        */
+       isUnchained: function () {
+               var element = document.getElementById( 'mwProtectUnchained' );
+               return element
+                       ? element.checked
+                       : true; // No control, so we need to let the user set both levels
+       },
+
+       /**
+        * Find the highest protection level in any selector
+        * @return {number}
+        */
+       getMaxLevel: function () {
+               return Math.max.apply( Math, this.getLevelSelectors().map( function () {
+                       return this.selectedIndex;
+               } ) );
+       },
+
+       /**
+        * Protect all actions at the specified level
+        *
+        * @param {number} index Protection level
+        */
+       setAllSelectors: function ( index ) {
+               this.getLevelSelectors().each( function () {
+                       this.selectedIndex = index;
+               } );
+       },
+
+       /**
+        * Get a list of all protection selectors on the page
+        *
+        * @return {jQuery}
+        */
+       getLevelSelectors: function () {
+               return $( 'select[id ^= mwProtect-level-]' );
+       },
+
+       /**
+        * Get a list of all expiry inputs on the page
+        *
+        * @return {jQuery}
+        */
+       getExpiryInputs: function () {
+               return $( 'input[id ^= mwProtect-][id $= -expires]' );
+       },
+
+       /**
+        * Get a list of all expiry selector lists on the page
+        *
+        * @return {jQuery}
+        */
+       getExpirySelectors: function () {
+               return $( 'select[id ^= mwProtectExpirySelection-]' );
+       },
+
+       /**
+        * Enable/disable protection selectors and expiry inputs
+        *
+        * @param {boolean} val Enable?
+        */
+       toggleUnchainedInputs: function ( val ) {
+               var setDisabled = function () { this.disabled = !val; };
+               this.getLevelSelectors().slice( 1 ).each( setDisabled );
+               this.getExpiryInputs().slice( 1 ).each( setDisabled );
+               this.getExpirySelectors().slice( 1 ).each( setDisabled );
+       }
+};
+
+$( ProtectionForm.init.bind( ProtectionForm ) );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.legacy/shared.css b/resources/src/mediawiki.legacy/shared.css
new file mode 100644 (file)
index 0000000..0604773
--- /dev/null
@@ -0,0 +1,1167 @@
+/**
+ * CSS in this file is used by *all* skins (that have any CSS at all). Be
+ * careful what you put in here, since what looks good in one skin may not in
+ * another, but don't ignore the poor pre-Monobook users either.
+ */
+
+/* GENERAL CLASSES FOR DIRECTIONALITY SUPPORT */
+
+/**
+ * These classes should be used for text depending on the content direction.
+ * Content stuff like editsection, ul/ol and TOC depend on this.
+ */
+.mw-content-ltr {
+       /* @noflip */
+       direction: ltr;
+}
+
+.mw-content-rtl {
+       /* @noflip */
+       direction: rtl;
+}
+
+/* Most input fields should be in site direction */
+.sitedir-ltr textarea,
+.sitedir-ltr input {
+       /* @noflip */
+       direction: ltr;
+}
+
+.sitedir-rtl textarea,
+.sitedir-rtl input {
+       /* @noflip */
+       direction: rtl;
+}
+
+.mw-userlink {
+       unicode-bidi: embed;
+}
+
+/* User-Agent styles for new HTML5 elements */
+mark {
+       background-color: yellow;
+       color: black;
+}
+
+/* Helper for wbr element on IE 8+; in HTML5, but not supported by default as of IE 11. */
+/* Note canonical HTML5 styles recommend "content: \u200B", but this doesn't work as of IE 11. */
+wbr {
+       display: inline-block;
+}
+
+/* Input types that should follow user direction, like buttons */
+/* TODO: What about buttons in wikipage content ? */
+input[type="submit"],
+input[type="button"],
+input[type="reset"],
+input[type="file"] {
+       direction: ltr;
+}
+
+/* Override default values */
+textarea[dir="ltr"],
+input[dir="ltr"] {
+       /* @noflip */
+       direction: ltr;
+}
+
+textarea[dir="rtl"],
+input[dir="rtl"] {
+       /* @noflip */
+       direction: rtl;
+}
+
+/* Default style for semantic tags */
+abbr[title],
+.explain[title] {
+       border-bottom: 1px dotted;
+       cursor: help;
+}
+
+/* Colored watchlist and recent changes numbers */
+.mw-plusminus-pos {
+       color: #006400; /* dark green */
+}
+
+.mw-plusminus-neg {
+       color: #8b0000; /* dark red */
+}
+
+.mw-plusminus-null {
+       color: #aaa; /* gray */
+}
+
+/**
+ * Links to redirects appear italicized on [[Special:AllPages]], [[Special:PrefixIndex]],
+ * [[Special:Watchlist/edit]] and in category listings.
+ */
+.allpagesredirect,
+.redirect-in-category,
+.watchlistredir {
+       font-style: italic;
+}
+
+/* Comment and username portions of RC entries */
+span.comment {
+       font-style: italic;
+}
+
+span.changedby {
+       font-size: 95%;
+}
+
+/* Math */
+.texvc {
+       direction: ltr;
+       unicode-bidi: embed;
+}
+
+img.tex {
+       vertical-align: middle;
+}
+
+span.texhtml {
+       font-family: serif;
+}
+
+/**
+ * Add a bit of margin space between the preview and the toolbar.
+ * This replaces the ugly <p><br /></p> we used to insert into the page source
+ */
+#wikiPreview.ontop {
+       margin-bottom: 1em;
+}
+
+/* Stop floats from intruding into edit area in previews */
+#editform,
+#toolbar,
+#wpTextbox1 {
+       clear: both;
+}
+
+/**
+ * File description page
+ */
+
+div.mw-filepage-resolutioninfo {
+       font-size: smaller;
+}
+
+/**
+ * File histories
+ */
+h2#filehistory {
+       clear: both;
+}
+
+table.filehistory th,
+table.filehistory td {
+       vertical-align: top;
+}
+
+table.filehistory th {
+       text-align: left;
+}
+
+table.filehistory td.mw-imagepage-filesize,
+table.filehistory th.mw-imagepage-filesize {
+       white-space: nowrap;
+}
+
+table.filehistory td.filehistory-selected {
+       font-weight: bold;
+}
+
+/**
+ * Add a checkered background image on hover for file
+ * description pages. (bug 26470)
+ */
+.filehistory a img,
+#file img:hover {
+       /* @embed */
+       background: white url(images/checker.png) repeat;
+}
+
+/**
+ * rev_deleted stuff
+ */
+li span.deleted,
+span.history-deleted {
+       text-decoration: line-through;
+       color: #888;
+       font-style: italic;
+}
+
+/**
+ * Patrol stuff
+ */
+.not-patrolled {
+       background-color: #ffa;
+}
+
+.unpatrolled {
+       font-weight: bold;
+       color: red;
+}
+
+div.patrollink {
+       font-size: 75%;
+       text-align: right;
+}
+
+/**
+ * Forms
+ */
+td.mw-label {
+       text-align: right;
+}
+
+td.mw-input {
+       text-align: left;
+}
+
+td.mw-submit {
+       text-align: left;
+}
+
+td.mw-label {
+       vertical-align: top;
+}
+
+.prefsection td.mw-label {
+       width: 20%;
+}
+
+.prefsection table {
+       width: 100%;
+}
+
+.prefsection table.mw-htmlform-matrix {
+       width: auto;
+}
+
+.mw-icon-question {
+       /* SVG support using a transparent gradient to guarantee cross-browser
+        * compatibility (browsers able to understand gradient syntax support also SVG).
+        * http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique */
+       background-image: url(images/question.png);
+       /* @embed */
+       background-image: -webkit-linear-gradient(transparent, transparent), url(images/question.svg);
+       /* @embed */
+       background-image: linear-gradient(transparent, transparent), url(images/question.svg);
+       background-repeat: no-repeat;
+       background-size: 13px 13px;
+       display: inline-block;
+       height: 13px;
+       width: 13px;
+       margin-left: 4px;
+}
+
+.mw-icon-question:lang(ar),
+.mw-icon-question:lang(fa),
+.mw-icon-question:lang(ur) {
+       -webkit-transform: scaleX(-1);
+       -ms-transform: scaleX(-1);
+       transform: scaleX(-1);
+}
+
+td.mw-submit {
+       white-space: nowrap;
+}
+
+table.mw-htmlform-nolabel td.mw-label {
+       width: 1px;
+}
+
+tr.mw-htmlform-vertical-label td.mw-label {
+       text-align: left !important;
+}
+
+.mw-htmlform-invalid-input td.mw-input input {
+       border-color: red;
+}
+
+.mw-htmlform-flatlist div.mw-htmlform-flatlist-item {
+       display: inline;
+       margin-right: 1em;
+       white-space: nowrap;
+}
+
+.mw-htmlform-matrix td {
+       padding-left: 0.5em;
+       padding-right: 0.5em;
+}
+
+input#wpSummary {
+       width: 80%;
+       margin-bottom: 1em;
+}
+
+/**
+ * Image captions.
+ *
+ * This is only meant to provide the most basic of styles, visual settings shouldn't be added here.
+ */
+
+/* @noflip */
+.mw-content-ltr .thumbcaption {
+       text-align: left;
+}
+
+/* @noflip */
+.mw-content-ltr .magnify {
+       float: right;
+}
+
+/* @noflip */
+.mw-content-rtl .thumbcaption {
+       text-align: right;
+}
+
+/* @noflip */
+.mw-content-rtl .magnify {
+       float: left;
+}
+
+/**
+ * Categories
+ */
+#catlinks {
+       /**
+        * Overrides text justification (user preference)
+        * See bug 31990
+        */
+       text-align: left;
+}
+
+.catlinks ul {
+       display: inline;
+       margin: 0;
+       padding: 0;
+       list-style: none;
+       list-style-type: none;
+       list-style-image: none;
+       vertical-align: middle !ie;
+}
+
+.catlinks li {
+       display: inline-block;
+       line-height: 1.25em;
+       border-left: 1px solid #AAA;
+       margin: 0.125em 0;
+       padding: 0 0.5em;
+       zoom: 1;
+       display: inline !ie;
+}
+
+.catlinks li:first-child {
+       padding-left: 0.25em;
+       border-left: none;
+}
+
+/* (bug 5346) make category redirects italic */
+.catlinks li a.mw-redirect {
+       font-style: italic;
+}
+
+/**
+ * Hidden categories
+ */
+.mw-hidden-cats-hidden {
+       display: none;
+}
+
+.catlinks-allhidden {
+       display: none;
+}
+
+/**
+ * Convenience links to edit block, delete and protect reasons
+ * and upload licenses
+ */
+p.mw-ipb-conveniencelinks,
+p.mw-protect-editreasons,
+p.mw-filedelete-editreasons,
+p.mw-delete-editreasons,
+p.mw-revdel-editreasons,
+p.mw-upload-editlicenses {
+       font-size: 90%;
+       text-align: right;
+}
+
+/* Page history styling */
+
+/* The auto-generated edit comments */
+.autocomment {
+       color: gray;
+}
+
+#pagehistory .history-user {
+       margin-left: 0.4em;
+       margin-right: 0.2em;
+}
+
+#pagehistory span.minor {
+       font-weight: bold;
+}
+
+#pagehistory li {
+       border: 1px solid white;
+}
+
+#pagehistory li.selected {
+       background-color: #f9f9f9;
+       border: 1px dashed #aaa;
+}
+
+.mw-history-revisiondelete-button, #mw-fileduplicatesearch-icon {
+       float: right;
+}
+
+/** Generic minor/bot/newpage styling (recent changes) */
+.newpage,
+.minoredit,
+.botedit {
+       font-weight: bold;
+}
+
+#shared-image-dup,
+#shared-image-conflict {
+       font-style: italic;
+}
+
+/**
+ * Recreating deleted page warning
+ * Reupload file warning
+ * Page protection warning
+ * incl. log entries for these warnings
+ */
+div.mw-warning-with-logexcerpt {
+       padding: 3px;
+       margin-bottom: 3px;
+       border: 2px solid #2F6FAB;
+       clear: both;
+}
+
+div.mw-warning-with-logexcerpt ul li {
+       font-size: 90%;
+}
+
+/* (show/hide) revision deletion links */
+span.mw-revdelundel-link,
+strong.mw-revdelundel-link {
+       font-size: 90%;
+}
+
+span.mw-revdelundel-hidden,
+input.mw-revdelundel-hidden {
+       visibility: hidden;
+}
+
+td.mw-revdel-checkbox,
+th.mw-revdel-checkbox {
+       padding-right: 10px;
+       text-align: center;
+}
+
+/* red links; see bug 36276 */
+a.new {
+       color: #BA0000;
+}
+
+/* feed links */
+a.feedlink {
+       /* SVG support using a transparent gradient to guarantee cross-browser
+        * compatibility (browsers able to understand gradient syntax support also SVG).
+        * http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique */
+       background-image: url(images/feed-icon.png);
+       /* @embed */
+       background-image: -webkit-linear-gradient(transparent, transparent), url(images/feed-icon.svg);
+       /* @embed */
+       background-image: linear-gradient(transparent, transparent), url(images/feed-icon.svg);
+       background-position: center left;
+       background-repeat: no-repeat;
+       background-size: 12px 12px;
+       padding-left: 16px;
+}
+
+/* Plainlinks - this can be used to switch
+ * off special external link styling */
+.plainlinks a.external {
+       background: none !important;
+       padding: 0 !important;
+}
+
+/* External URLs should always be treated as LTR (bug 4330) */
+/* @noflip */ .rtl a.external.free,
+.rtl a.external.autonumber {
+       direction: ltr;
+       unicode-bidi: embed;
+}
+
+/**
+ * wikitable class for skinning normal tables
+ * keep in sync with commonPrint.css
+ */
+table.wikitable {
+       margin: 1em 0;
+       background-color: #f9f9f9;
+       border: 1px #aaa solid;
+       border-collapse: collapse;
+       color: black;
+}
+
+table.wikitable > tr > th,
+table.wikitable > tr > td,
+table.wikitable > * > tr > th,
+table.wikitable > * > tr > td {
+       border: 1px #aaa solid;
+       padding: 0.2em;
+}
+
+table.wikitable > tr > th,
+table.wikitable > * > tr > th {
+       background-color: #f2f2f2;
+       text-align: center;
+}
+
+table.wikitable > caption {
+       font-weight: bold;
+}
+
+/* success and error messages */
+.error,
+.warning,
+.success {
+       font-size: larger;
+}
+
+.error {
+       color: #cc0000;
+}
+
+.warning {
+       color: #705000;
+}
+
+.success {
+       color: #009000;
+}
+
+.errorbox,
+.warningbox,
+.successbox {
+       border: 1px solid;
+       padding: .5em 1em;
+       margin-bottom: 1em;
+       display: -moz-inline-block;
+       display: inline-block;
+       zoom: 1;
+       *display: inline;
+}
+
+.errorbox h2,
+.warningbox h2,
+.successbox h2 {
+       font-size: 1em;
+       color: inherit;
+       font-weight: bold;
+       display: inline;
+       margin: 0 .5em 0 0;
+       border: none;
+}
+
+.errorbox {
+       color: #cc0000;
+       border-color: #fac5c5;
+       background-color: #fae3e3;
+}
+
+.warningbox {
+       color: #705000;
+       border-color: #fde29b;
+       background-color: #fdf1d1;
+}
+
+.successbox {
+       color: #009000;
+       border-color: #b7fdb5;
+       background-color: #e1fddf;
+}
+
+/* general info/warning box for SP */
+.mw-infobox {
+       border: 2px solid #ff7f00;
+       margin: 0.5em;
+       clear: left;
+       overflow: hidden;
+}
+
+.mw-infobox-left {
+       margin: 7px;
+       float: left;
+       width: 35px;
+}
+
+.mw-infobox-right {
+       margin: 0.5em 0.5em 0.5em 49px;
+}
+
+/* Note on preview page */
+.previewnote {
+       color: #c00;
+       margin-bottom: 1em;
+}
+
+.previewnote p {
+       text-indent: 3em;
+       margin: 0.8em 0;
+}
+
+.visualClear {
+       clear: both;
+}
+
+/**
+ * Data table style
+ *
+ * Transparent table with suddle borders
+ * and blue row-highlighting.
+ */
+.mw-datatable {
+       border-collapse: collapse;
+}
+
+.mw-datatable,
+.mw-datatable td,
+.mw-datatable th {
+       border: 1px solid #aaaaaa;
+       padding: 0 0.15em 0 0.15em;
+}
+
+.mw-datatable th {
+       background-color: #ddddff;
+}
+
+.mw-datatable td {
+       background-color: #ffffff;
+}
+
+.mw-datatable tr:hover td {
+       background-color: #eeeeff;
+}
+
+/* filetoc */
+ul#filetoc {
+       text-align: center;
+       border: 1px solid #aaaaaa;
+       background-color: #f9f9f9;
+       padding: 5px;
+       font-size: 95%;
+       margin-bottom: 0.5em;
+       margin-left: 0;
+       margin-right: 0;
+}
+
+#filetoc li {
+       display: inline;
+       list-style-type: none;
+       padding-right: 2em;
+}
+
+/* Classes for Exif data display */
+table.mw_metadata {
+       font-size: 0.8em;
+       margin-left: 0.5em;
+       margin-bottom: 0.5em;
+       width: 400px;
+}
+
+table.mw_metadata caption {
+       font-weight: bold;
+}
+
+table.mw_metadata th {
+       font-weight: normal;
+}
+
+table.mw_metadata td {
+       padding: 0.1em;
+}
+
+table.mw_metadata {
+       border: none;
+       border-collapse: collapse;
+}
+
+table.mw_metadata td,
+table.mw_metadata th {
+       text-align: center;
+       border: 1px solid #aaaaaa;
+       padding-left: 5px;
+       padding-right: 5px;
+}
+
+table.mw_metadata th {
+       background-color: #f9f9f9;
+}
+
+table.mw_metadata td {
+       background-color: #fcfcfc;
+}
+
+table.mw_metadata ul.metadata-langlist {
+       list-style-type: none;
+       list-style-image: none;
+       padding-right: 5px;
+       padding-left: 5px;
+       margin: 0;
+}
+
+/* Correct directionality when page dir is different from site/user dir */
+.mw-content-ltr ul,
+.mw-content-rtl .mw-content-ltr ul {
+       /* @noflip */
+       margin: 0.3em 0 0 1.6em;
+       padding: 0;
+}
+
+.mw-content-rtl ul,
+.mw-content-ltr .mw-content-rtl ul {
+       /* @noflip */
+       margin: 0.3em 1.6em 0 0;
+       padding: 0;
+}
+
+.mw-content-ltr ol,
+.mw-content-rtl .mw-content-ltr ol {
+       /* @noflip */
+       margin: 0.3em 0 0 3.2em;
+       padding: 0;
+}
+
+.mw-content-rtl ol,
+.mw-content-ltr .mw-content-rtl ol {
+       /* @noflip */
+       margin: 0.3em 3.2em 0 0;
+       padding: 0;
+}
+
+/* @noflip */
+.mw-content-ltr dd,
+.mw-content-rtl .mw-content-ltr dd {
+       margin-left: 1.6em;
+       margin-right: 0;
+}
+
+/* @noflip */
+.mw-content-rtl dd,
+.mw-content-ltr .mw-content-rtl dd {
+       margin-right: 1.6em;
+       margin-left: 0;
+}
+
+/* Galleries */
+/* These display attributes look nonsensical, but are needed to support IE and FF2 */
+/* Don't forget to update commonPrint.css */
+li.gallerybox {
+       vertical-align: top;
+       display: -moz-inline-box;
+       display: inline-block;
+}
+
+ul.gallery,
+li.gallerybox {
+       zoom: 1;
+       *display: inline;
+}
+
+ul.gallery {
+       margin: 2px;
+       padding: 2px;
+       display: block;
+}
+
+li.gallerycaption {
+       font-weight: bold;
+       text-align: center;
+       display: block;
+       word-wrap: break-word;
+}
+
+li.gallerybox div.thumb {
+       text-align: center;
+       border: 1px solid #ccc;
+       background-color: #f9f9f9;
+       margin: 2px;
+}
+
+li.gallerybox div.thumb img {
+       display: block;
+       margin: 0 auto;
+}
+
+div.gallerytext {
+       overflow: hidden;
+       font-size: 94%;
+       padding: 2px 4px;
+       word-wrap: break-word;
+}
+
+/* new gallery stuff */
+ul.mw-gallery-nolines li.gallerybox div.thumb {
+       background-color: transparent;
+       border: none;
+}
+
+ul.mw-gallery-nolines li.gallerybox div.gallerytext {
+       text-align: center;
+}
+
+/* height constrained gallery */
+
+ul.mw-gallery-packed li.gallerybox div.thumb,
+ul.mw-gallery-packed-overlay li.gallerybox div.thumb,
+ul.mw-gallery-packed-hover li.gallerybox div.thumb {
+       background-color: transparent;
+       border: none;
+}
+
+ul.mw-gallery-packed li.gallerybox div.thumb img,
+ul.mw-gallery-packed-overlay li.gallerybox div.thumb img,
+ul.mw-gallery-packed-hover li.gallerybox div.thumb img {
+       margin: 0 auto;
+}
+
+ul.mw-gallery-packed-hover li.gallerybox,
+ul.mw-gallery-packed-overlay li.gallerybox {
+       position: relative;
+}
+
+ul.mw-gallery-packed-hover div.gallerytextwrapper {
+       overflow: hidden;
+       height: 0;
+}
+
+ul.mw-gallery-packed-hover li.gallerybox:hover div.gallerytextwrapper,
+ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper,
+ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper {
+       position: absolute;
+       background: white;
+       background: rgba(255, 255, 255, 0.8);
+       padding: 5px 10px;
+       bottom: 0;
+       left: 0; /* Needed for IE */
+       height: auto;
+       font-weight: bold;
+       margin: 2px; /* correspond to style on div.thumb */
+}
+
+ul.mw-gallery-packed-hover,
+ul.mw-gallery-packed-overlay,
+ul.mw-gallery-packed {
+       text-align: center;
+}
+
+.mw-ajax-loader {
+       /* @embed */
+       background-image: url(images/ajax-loader.gif);
+       background-position: center center;
+       background-repeat: no-repeat;
+       padding: 16px;
+       position: relative;
+       top: -16px;
+}
+
+.mw-small-spinner {
+       padding: 10px !important;
+       margin-right: 0.6em;
+       /* @embed */
+       background-image: url(images/spinner.gif);
+       background-position: center center;
+       background-repeat: no-repeat;
+}
+
+/* Language specific height correction for titles. Ref Bug 29405 and Bug 30809 */
+/* Languages like hi or ml require slightly more vertical space to show diacritics properly */
+h1:lang(anp),
+h1:lang(as),
+h1:lang(bh), /* Macrolanguage, used on bh.wikipedia.org, should be removed one day */
+h1:lang(bho),
+h1:lang(bn),
+h1:lang(gu),
+h1:lang(hi),
+h1:lang(kn),
+h1:lang(ks),
+h1:lang(ml),
+h1:lang(mr),
+h1:lang(my),
+h1:lang(mai),
+h1:lang(ne),
+h1:lang(new),
+h1:lang(or),
+h1:lang(pa),
+h1:lang(pi),
+h1:lang(sa),
+h1:lang(ta),
+h1:lang(te) {
+       line-height: 1.6em !important;
+}
+
+h2:lang(anp), h3:lang(anp), h4:lang(anp), h5:lang(anp), h6:lang(anp),
+h2:lang(as), h3:lang(as), h4:lang(as), h5:lang(as), h6:lang(as),
+h2:lang(bho), h3:lang(bho), h4:lang(bho), h5:lang(bho), h6:lang(bho),
+h2:lang(bh), h3:lang(bh), h4:lang(bh), h5:lang(bh), h6:lang(bh),
+h2:lang(bn), h3:lang(bn), h4:lang(bn), h5:lang(bn), h6:lang(bn),
+h2:lang(gu), h3:lang(gu), h4:lang(gu), h5:lang(gu), h6:lang(gu),
+h2:lang(hi), h3:lang(hi), h4:lang(hi), h5:lang(hi), h6:lang(hi),
+h2:lang(kn), h3:lang(kn), h4:lang(kn), h5:lang(kn), h6:lang(kn),
+h2:lang(ks), h3:lang(ks), h4:lang(ks), h5:lang(ks), h6:lang(ks),
+h2:lang(ml), h3:lang(ml), h4:lang(ml), h5:lang(ml), h6:lang(ml),
+h2:lang(mr), h3:lang(mr), h4:lang(mr), h5:lang(mr), h6:lang(mr),
+h2:lang(my), h3:lang(my), h4:lang(my), h5:lang(my), h6:lang(my),
+h2:lang(mai), h3:lang(mai), h4:lang(mai), h5:lang(mai), h6:lang(mai),
+h2:lang(ne), h3:lang(ne), h4:lang(ne), h5:lang(ne), h6:lang(ne),
+h2:lang(new), h3:lang(new), h4:lang(new), h5:lang(new), h6:lang(new),
+h2:lang(or), h3:lang(or), h4:lang(or), h5:lang(or), h6:lang(or),
+h2:lang(pa), h3:lang(pa), h4:lang(pa), h5:lang(pa), h6:lang(pa),
+h2:lang(pi), h3:lang(pi), h4:lang(pi), h5:lang(pi), h6:lang(pi),
+h2:lang(sa), h3:lang(sa), h4:lang(sa), h5:lang(sa), h6:lang(sa),
+h2:lang(ta), h3:lang(ta), h4:lang(ta), h5:lang(ta), h6:lang(ta),
+h2:lang(te), h3:lang(te), h4:lang(te), h5:lang(te), h6:lang(te) {
+       line-height: 1.2em;
+}
+
+/* Localised ordered list numbering for some languages */
+ol:lang(bcc) li,
+ol:lang(bqi) li,
+ol:lang(fa) li,
+ol:lang(glk) li,
+ol:lang(kk-arab) li,
+ol:lang(mzn) li {
+       list-style-type: -moz-persian;
+       list-style-type: persian;
+}
+
+ol:lang(ckb) li {
+       list-style-type: -moz-arabic-indic;
+       list-style-type: arabic-indic;
+}
+
+ol:lang(hi) li,
+ol:lang(mr) li {
+       list-style-type: -moz-devanagari;
+       list-style-type: devanagari;
+}
+
+ol:lang(as) li,
+ol:lang(bn) li {
+       list-style-type: -moz-bengali;
+       list-style-type: bengali;
+}
+
+ol:lang(or) li {
+       list-style-type: -moz-oriya;
+       list-style-type: oriya;
+}
+
+#toc ul, .toc ul {
+       margin: .3em 0;
+}
+
+/* Correct directionality when page dir is different from site/user dir */
+/* @noflip */ .mw-content-ltr .toc ul,
+.mw-content-ltr #toc ul,
+.mw-content-rtl .mw-content-ltr .toc ul,
+.mw-content-rtl .mw-content-ltr #toc ul {
+       text-align: left;
+}
+
+/* @noflip */ .mw-content-rtl .toc ul,
+.mw-content-rtl #toc ul,
+.mw-content-ltr .mw-content-rtl .toc ul,
+.mw-content-ltr .mw-content-rtl #toc ul {
+       text-align: right;
+}
+
+/* @noflip */ .mw-content-ltr .toc ul ul,
+.mw-content-ltr #toc ul ul,
+.mw-content-rtl .mw-content-ltr .toc ul ul,
+.mw-content-rtl .mw-content-ltr #toc ul ul {
+       margin: 0 0 0 2em;
+}
+
+/* @noflip */ .mw-content-rtl .toc ul ul,
+.mw-content-rtl #toc ul ul,
+.mw-content-ltr .mw-content-rtl .toc ul ul,
+.mw-content-ltr .mw-content-rtl #toc ul ul {
+       margin: 0 2em 0 0;
+}
+
+#toc #toctitle,
+.toc #toctitle,
+#toc .toctitle,
+.toc .toctitle {
+       direction: ltr;
+}
+
+/* tooltip styles */
+.mw-help-field-hint {
+       display: none;
+       margin-left: 2px;
+       margin-bottom: -8px;
+       padding: 0 0 0 15px;
+       /* @embed */
+       background-image: url(images/help-question.gif);
+       background-position: left center;
+       background-repeat: no-repeat;
+       cursor: pointer;
+       font-size: .8em;
+       text-decoration: underline;
+       color: #0645ad;
+}
+
+.mw-help-field-hint:hover {
+       /* @embed */
+       background-image: url(images/help-question-hover.gif);
+}
+
+.mw-help-field-data {
+       display: block;
+       background-color: #d6f3ff;
+       padding: 5px 8px 4px 8px;
+       border: 1px solid #5dc9f4;
+       margin-left: 20px;
+}
+
+#mw-clearyourcache,
+#mw-sitecsspreview,
+#mw-sitejspreview,
+#mw-usercsspreview,
+#mw-userjspreview {
+       direction: ltr;
+       unicode-bidi: embed;
+}
+
+/* Correct user & content directionality when viewing a diff */
+.diff-currentversion-title,
+.diff {
+       direction: ltr;
+       unicode-bidi: embed;
+}
+
+/* @noflip */ .diff-contentalign-right td {
+       direction: rtl;
+       unicode-bidi: embed;
+}
+
+/* @noflip */ .diff-contentalign-left td {
+       direction: ltr;
+       unicode-bidi: embed;
+}
+
+.diff-multi,
+.diff-otitle,
+.diff-ntitle,
+.diff-lineno {
+       direction: ltr !important;
+       unicode-bidi: embed;
+}
+
+#mw-revision-info,
+#mw-revision-info-current,
+#mw-revision-nav {
+       direction: ltr;
+       display: inline;
+}
+
+/* Images */
+
+/* @noflip */ div.tright,
+div.floatright,
+table.floatright {
+       clear: right;
+       float: right;
+}
+
+/* @noflip */ div.tleft,
+div.floatleft,
+table.floatleft {
+       float: left;
+       clear: left;
+}
+
+div.floatright,
+table.floatright,
+div.floatleft,
+table.floatleft {
+       position: relative;
+}
+
+/* bug 12205 */
+#mw-credits a {
+       unicode-bidi: embed;
+}
+
+/* Accessibility */
+.mw-jump,
+#jump-to-nav {
+       overflow: hidden;
+       height: 0;
+       zoom: 1; /* http://webaim.org/techniques/skipnav/#iequirk */
+}
+
+/* Print footer should be hidden by default in screen. */
+.printfooter {
+       display: none;
+}
+
+/* For developers */
+.xdebug-error {
+       position: absolute;
+       z-index: 99;
+}
+
+.mw-editsection,
+.toctoggle,
+#jump-to-nav {
+       -moz-user-select: none;
+       -webkit-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+
+/* Display editsection links smaller and next to headings */
+.mw-editsection,
+.mw-editsection-like {
+       font-size: small;
+       font-weight: normal;
+       margin-left: 1em;
+       vertical-align: baseline;
+       /* Reset line-height; headings tend to have it set to larger values */
+       line-height: 1em;
+       /* As .mw-editsection is a <span> (inline element), it is treated as part */
+       /* of the heading content when selecting text by multiple clicks and thus */
+       /* selected together with heading content, despite the user-select: none; */
+       /* rule set above. This enforces non-selection without changing the look. */
+       display: inline-block;
+}
+
+/* Correct directionality when page dir is different from site/user dir */
+/* @noflip */
+.mw-content-ltr .mw-editsection,
+.mw-content-rtl .mw-content-ltr .mw-editsection {
+       margin-left: 1em;
+}
+
+/* @noflip */
+.mw-content-rtl .mw-editsection,
+.mw-content-ltr .mw-content-rtl .mw-editsection {
+       margin-right: 1em;
+}
+
+/* Prevent citations and subscripts from interfering with the line-height */
+sup,
+sub {
+       line-height: 1;
+}
diff --git a/resources/src/mediawiki.legacy/wikibits.js b/resources/src/mediawiki.legacy/wikibits.js
new file mode 100644 (file)
index 0000000..5c6e63b
--- /dev/null
@@ -0,0 +1,201 @@
+/**
+ * MediaWiki legacy wikibits
+ */
+( function ( mw, $ ) {
+       var msg,
+               win = window,
+               ua = navigator.userAgent.toLowerCase(),
+               onloadFuncts = [];
+
+/**
+ * User-agent sniffing.
+ *
+ * @deprecated since 1.17 Use jquery.client instead
+ */
+
+msg = 'Use feature detection or module jquery.client instead.';
+
+mw.log.deprecate( win, 'clientPC', ua, msg );
+
+// Ignored dummy values
+mw.log.deprecate( win, 'is_gecko', false, msg );
+mw.log.deprecate( win, 'is_chrome_mac', false, msg );
+mw.log.deprecate( win, 'is_chrome', false, msg );
+mw.log.deprecate( win, 'webkit_version', false, msg );
+mw.log.deprecate( win, 'is_safari_win', false, msg );
+mw.log.deprecate( win, 'is_safari', false, msg );
+mw.log.deprecate( win, 'webkit_match', false, msg );
+mw.log.deprecate( win, 'is_ff2', false, msg );
+mw.log.deprecate( win, 'ff2_bugs', false, msg );
+mw.log.deprecate( win, 'is_ff2_win', false, msg );
+mw.log.deprecate( win, 'is_ff2_x11', false, msg );
+mw.log.deprecate( win, 'opera95_bugs', false, msg );
+mw.log.deprecate( win, 'opera7_bugs', false, msg );
+mw.log.deprecate( win, 'opera6_bugs', false, msg );
+mw.log.deprecate( win, 'is_opera_95', false, msg );
+mw.log.deprecate( win, 'is_opera_preseven', false, msg );
+mw.log.deprecate( win, 'is_opera', false, msg );
+mw.log.deprecate( win, 'ie6_bugs', false, msg );
+
+/**
+ * DOM utilities for handling of events, text nodes and selecting elements
+ *
+ * @deprecated since 1.17 Use jQuery instead
+ */
+msg = 'Use jQuery instead.';
+
+// Ignored dummy values
+mw.log.deprecate( win, 'doneOnloadHook', undefined, msg );
+mw.log.deprecate( win, 'onloadFuncts', [], msg );
+mw.log.deprecate( win, 'runOnloadHook', $.noop, msg );
+mw.log.deprecate( win, 'changeText', $.noop, msg );
+mw.log.deprecate( win, 'killEvt', $.noop, msg );
+mw.log.deprecate( win, 'addHandler', $.noop, msg );
+mw.log.deprecate( win, 'hookEvent', $.noop, msg );
+mw.log.deprecate( win, 'addClickHandler', $.noop, msg );
+mw.log.deprecate( win, 'removeHandler', $.noop, msg );
+mw.log.deprecate( win, 'getElementsByClassName', function () { return []; }, msg );
+mw.log.deprecate( win, 'getInnerText', function () { return ''; }, msg );
+
+// Run a function after the window onload event is fired
+mw.log.deprecate( win, 'addOnloadHook', function ( hookFunct ) {
+       if ( onloadFuncts ) {
+               onloadFuncts.push(hookFunct);
+       } else {
+               // If func queue is gone the event has happened already,
+               // run immediately instead of queueing.
+               hookFunct();
+       }
+}, msg );
+
+$( win ).on( 'load', function () {
+       var i, functs;
+
+       // Don't run twice
+       if ( !onloadFuncts ) {
+               return;
+       }
+
+       // Deference and clear onloadFuncts before running any
+       // hooks to make sure we don't miss any addOnloadHook
+       // calls.
+       functs = onloadFuncts.slice();
+       onloadFuncts = undefined;
+
+       // Execute the queued functions
+       for ( i = 0; i < functs.length; i++ ) {
+               functs[i]();
+       }
+} );
+
+/**
+ * Toggle checkboxes with shift selection
+ *
+ * @deprecated since 1.17 Use jquery.checkboxShiftClick instead
+ */
+msg = 'Use jquery.checkboxShiftClick instead.';
+mw.log.deprecate( win, 'checkboxes', [], msg );
+mw.log.deprecate( win, 'lastCheckbox', null, msg );
+mw.log.deprecate( win, 'setupCheckboxShiftClick', $.noop, msg );
+mw.log.deprecate( win, 'addCheckboxClickHandlers', $.noop, msg );
+mw.log.deprecate( win, 'checkboxClickHandler', $.noop, msg );
+
+/**
+ * Add a button to the default editor toolbar
+ *
+ * @deprecated since 1.17 Use mw.toolbar instead
+ */
+mw.log.deprecate( win, 'mwEditButtons', [], 'Use mw.toolbar instead.' );
+mw.log.deprecate( win, 'mwCustomEditButtons', [], 'Use mw.toolbar instead.' );
+
+/**
+ * Spinner creation, injection and removal
+ *
+ * @deprecated since 1.18 Use jquery.spinner instead
+ */
+mw.log.deprecate( win, 'injectSpinner', $.noop, 'Use jquery.spinner instead.' );
+mw.log.deprecate( win, 'removeSpinner', $.noop, 'Use jquery.spinner instead.' );
+
+/**
+ * Escape utilities
+ *
+ * @deprecated since 1.18 Use mw.html instead
+ */
+mw.log.deprecate( win, 'escapeQuotes', $.noop, 'Use mw.html instead.' );
+mw.log.deprecate( win, 'escapeQuotesHTML', $.noop, 'Use mw.html instead.' );
+
+/**
+ * Display a message to the user
+ *
+ * @deprecated since 1.17 Use mediawiki.notify instead
+ * @param {string|HTMLElement} message To be put inside the message box
+ */
+mw.log.deprecate( win, 'jsMsg', function ( message ) {
+       if ( !arguments.length || message === '' || message === null ) {
+               return true;
+       }
+       if ( typeof message !== 'object' ) {
+               message = $.parseHTML( message );
+       }
+       mw.notify( message, { autoHide: true, tag: 'legacy' } );
+       return true;
+}, 'Use mediawiki.notify instead.' );
+
+/**
+ * Misc. utilities
+ *
+ * @deprecated since 1.17 Use mediawiki.util instead
+ */
+msg = 'Use mediawiki.util instead.';
+mw.log.deprecate( win, 'updateTooltipAccessKeys', mw.util.updateTooltipAccessKeys, msg );
+mw.log.deprecate( win, 'addPortletLink', mw.util.addPortletLink, msg );
+mw.log.deprecate( win, 'appendCSS', mw.util.addCSS, msg );
+msg = 'Use jquery.accessKeyLabel instead.';
+mw.log.deprecate( win, 'tooltipAccessKeyPrefix', 'alt-', msg );
+mw.log.deprecate( win, 'tooltipAccessKeyRegexp', /\[(alt-)?(.)\]$/, msg );
+
+/**
+ * Wikipage import methods
+ */
+
+// included-scripts tracker
+win.loadedScripts = {};
+
+win.importScript = function ( page ) {
+       var uri = mw.config.get( 'wgScript' ) + '?title=' +
+               mw.util.wikiUrlencode( page ) +
+               '&action=raw&ctype=text/javascript';
+       return win.importScriptURI( uri );
+};
+
+win.importScriptURI = function ( url ) {
+       if ( win.loadedScripts[url] ) {
+               return null;
+       }
+       win.loadedScripts[url] = true;
+       var s = document.createElement( 'script' );
+       s.setAttribute( 'src', url );
+       s.setAttribute( 'type', 'text/javascript' );
+       document.getElementsByTagName( 'head' )[0].appendChild( s );
+       return s;
+};
+
+win.importStylesheet = function ( page ) {
+       var uri = mw.config.get( 'wgScript' ) + '?title=' +
+               mw.util.wikiUrlencode( page ) +
+               '&action=raw&ctype=text/css';
+       return win.importStylesheetURI( uri );
+};
+
+win.importStylesheetURI = function ( url, media ) {
+       var l = document.createElement( 'link' );
+       l.rel = 'stylesheet';
+       l.href = url;
+       if ( media ) {
+               l.media = media;
+       }
+       document.getElementsByTagName('head')[0].appendChild( l );
+       return l;
+};
+
+}( mediaWiki, jQuery ) );
index b65a62b..8c28884 100644 (file)
 }
 
 .transition(@value) {
-       -webkit-transition: @value;
-       -moz-transition: @value;
-       -o-transition: @value;
-       transition: @value;
+       -webkit-transition: @value; // Safari 3.1-6.0, iOS 3.2-6.1, Android 2.1-4.3
+       -moz-transition: @value; // Firefox 4-15
+       -o-transition: @value; // Opera 10.5-12.0
+       transition: @value; // Chrome 26+, Firefox 16+, IE 10+, Safari 6.1+, Opera 12.1+, iOS 7+, Android 4.4+
 }
 
 .box-sizing(@value) {
-       -webkit-box-sizing: @value;
-       -moz-box-sizing: @value;
-       box-sizing: @value;
+       -webkit-box-sizing: @value; // Safari 3.1-5.0, iOS 3.2-4.3, Android 2.1-3.0
+       -moz-box-sizing: @value; // Firefox 4-28,
+       box-sizing: @value; // Chrome 10+, Firefox 29+, IE 8+, Safari 5.1+, Opera 10+, iOS 5+, Android 4+
 }
 
 .box-shadow(@value) {
-       -webkit-box-shadow: @value; // Android 2.3+, iOS 4.0.2-4.2, Safari 3-4
-       box-shadow: @value; // Chrome 6+, Firefox 4+, IE 9+, iOS 5+, Opera 10.50+
+       -webkit-box-shadow: @value; // Safari 3.1-5.0, iOS 3.2-4.3, Android 2.1-3.0
+       box-shadow: @value; // Chrome 10+, Firefox 4+, IE 9+, Safari 5.1+, Opera 11+, iOS 5+, Android 4+
 }
diff --git a/resources/src/mediawiki.less/mediawiki.ui/mixins.less b/resources/src/mediawiki.less/mediawiki.ui/mixins.less
new file mode 100644 (file)
index 0000000..ec9888f
--- /dev/null
@@ -0,0 +1,122 @@
+// ----------------------------------------------------------------------------
+// Form styling mixins
+// ----------------------------------------------------------------------------
+.agora-label-styling() {
+       font-size: 0.9em;
+       color: @colorText;
+
+       * {
+               font-weight: normal;
+       }
+}
+
+.agora-inline-label-styling() {
+       margin-bottom: 0.5em;
+       cursor: pointer;
+       vertical-align: bottom;
+       line-height: normal;
+
+       font-weight: normal;
+
+       & > input[type="checkbox"],
+       & > input[type="radio"] {
+               width: auto;
+               height: auto;
+               margin: 0 0.1em 0 0;
+               padding: 0;
+               border: 1px solid @colorFieldBorder;
+               cursor: pointer;
+       }
+}
+
+// ----------------------------------------------------------------------------
+// Button styling
+// ----------------------------------------------------------------------------
+
+.button-colors(@bgColor) {
+       background: @bgColor;
+
+       &:hover,
+       &:focus {
+               // The inner bottom bevel should match the active background color.
+               box-shadow: 0 1px rgba(0, 0, 0, 10%), inset 0 -3px rgba(0, 0, 0, 20%);
+               border-bottom-color: mix(#000, @bgColor, 20%);
+               outline: none;
+               // remove outline in Firefox
+               &::-moz-focus-inner {
+                       border-color: transparent;
+               }
+       }
+
+       &:active,
+       &.mw-ui-checked {
+               // lessphp doesn't implement shade (https://github.com/leafo/lessphp/issues/528);
+               // it passes it through, then ResourceLoader drops it.
+               // background: shade(@bgColor, 20%);
+               background: mix(#000, @bgColor, 20%);
+               box-shadow: none;
+       }
+}
+
+.button-colors(@bgColor) when (lightness(@bgColor) >= 70%) {
+       color: @colorButtonText;
+       border: 1px solid @colorGray12;
+
+       &:disabled {
+               color: @colorDisabledText;
+
+               // make sure disabled buttons don't have hover and active states
+               &:hover,
+               &:active {
+                       background: @bgColor;
+                       box-shadow: none;
+               }
+       }
+}
+
+.button-colors(@bgColor) when (lightness(@bgColor) < 70%) {
+       color: #fff;
+       // border of the same color as background so that light background and
+       // dark background buttons are the same height (only top and bottom to
+       // make box shadow on hover cover the corners too)
+       border: 1px solid @bgColor;
+       border-left: none;
+       border-right: none;
+       text-shadow: 0 1px rgba(0, 0, 0, .1);
+
+       &:disabled {
+               background: @colorGray12;
+               border-color: @colorGray12;
+
+               // make sure disabled buttons don't have hover and active states
+               &:hover,
+               &:active,
+               &.mw-ui-checked {
+                       box-shadow: none;
+               }
+       }
+}
+
+.button-colors-quiet(@textColor) {
+       // Quiet buttons all start gray, and reveal
+       // constructive/progressive/destructive color on hover and active.
+       color: @colorButtonText;
+
+       &:hover,
+       &:focus {
+               // lessphp doesn't implement tint, see above
+               // color: tint(@textColor, 20%);
+               color: mix(#fff, @textColor, 20%);
+       }
+
+       &:active,
+       &.mw-ui-checked {
+               // lessphp doesn't implement shade, see above
+               // color: shade(@textColor, 20%);
+               color: mix(#000, @textColor, 20%);
+       }
+
+       &:disabled {
+               color: @colorDisabledText;
+       }
+}
diff --git a/resources/src/mediawiki.less/mediawiki.ui/variables.less b/resources/src/mediawiki.less/mediawiki.ui/variables.less
new file mode 100644 (file)
index 0000000..17bf683
--- /dev/null
@@ -0,0 +1,59 @@
+// Colors for use in mediawiki.ui and elsewhere
+
+// Although this defines many shades, be parsimonious in your own use of grays. Prefer
+// colors already in use in MediaWiki. Prefer semantic color names such as "@colorText".
+@colorGray1: #111; // darkest
+@colorGray2: #222;
+@colorGray3: #333;
+@colorGray4: #444;
+@colorGray5: #555;
+@colorGray6: #666;
+@colorGray7: #777;
+@colorGray8: #888;
+@colorGray9: #999;
+@colorGray10: #AAA;
+@colorGray11: #BBB;
+@colorGray12: #CCC;
+@colorGray13: #DDD;
+@colorGray14: #EEE;
+@colorGray15: #F9F9F9; // lightest
+
+// Semantic background colors
+// Blue; for contextual use of a continuing action
+@colorProgressive: #347bff;
+// Green; for contextual use of a positive finalizing action
+@colorConstructive: #00af89;
+// Orange; for contextual use of returning to a past action
+@colorRegressive: #FF5D00;
+// Red; for contextual use of a negative action of high severity
+@colorDestructive: #d11d13;
+// Orange; for contextual use of a potentially negative action of medium severity
+@colorMediumSevere: #FF5D00;
+// Yellow; for contextual use of a potentially negative action of low severity
+@colorLowSevere: #FFB50D;
+
+// Used in mixins to darken contextual colors by the same amount (eg. focus)
+@colorDarkenPercentage: 13.5%;
+// Used in mixins to lighten contextual colors by the same amount (eg. hover)
+@colorLightenPercentage: 13.5%;
+
+// Text colors
+@colorText: @colorGray2;
+@colorTextLight: @colorGray6;
+@colorButtonText: @colorGray5;
+@colorDisabledText: @colorGray12;
+@colorErrorText: #CC0000;
+
+// UI colors
+@colorFieldBorder: @colorGray12;
+@colorShadow: @colorGray14;
+@colorPlaceholder: @colorGray10;
+@colorNeutral: @colorGray7;
+
+// The following rules are deprecated
+@colorWhite: #fff;
+@colorOffWhite: #fafafa;
+@colorGrayDark: #898989;
+@colorGrayLight: #ccc;
+@colorGrayLighter: #ddd;
+@colorGrayLightest: #eee;
index 931e312..622e818 100644 (file)
 
        function bindPageNavigation( $container ) {
                $container.find( '.multipageimagenavbox' ).one( 'click', 'a', function ( e ) {
-                       loadPage( this.href );
+                       var page, uri;
+
+                       // 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();
+
+                       loadPage( uri );
                        e.preventDefault();
                } );
 
index ccddb3e..a05a054 100644 (file)
@@ -1,6 +1,16 @@
 ( function ( mw, $ ) {
        var supportsPlaceholder = 'placeholder' in document.createElement( 'input' );
 
+       // Break out of framesets
+       if ( mw.config.get( 'wgBreakFrames' ) ) {
+               // Note: In IE < 9 strict comparison to window is non-standard (the standard didn't exist yet)
+               // it works only comparing to window.self or window.window (http://stackoverflow.com/q/4850978/319266)
+               if ( window.top !== window.self ) {
+                       // Un-trap us from framesets
+                       window.top.location = window.location;
+               }
+       }
+
        mw.hook( 'wikipage.content' ).add( function ( $content ) {
                var $sortableTables;
 
index 15e9aba..d252f0e 100644 (file)
@@ -6,7 +6,7 @@
  */
 ( function ( mw, $ ) {
        // The name of the page to watch or unwatch
-       var title = mw.config.get( 'wgRelevantPageName', mw.config.get( 'wgPageName' ) );
+       var title = mw.config.get( 'wgRelevantPageName' );
 
        /**
         * Update the link text, link href attribute and (if applicable)
diff --git a/resources/src/mediawiki.skinning/content.css b/resources/src/mediawiki.skinning/content.css
new file mode 100644 (file)
index 0000000..622afe6
--- /dev/null
@@ -0,0 +1,232 @@
+/**
+ * MediaWiki style sheet for general styles on complex content
+ *
+ * Styles for complex things which are a standard part of page content
+ * (ie: the CSS classing built into the system), like the TOC.
+ */
+
+/* Table of Contents */
+#toc,
+.toc,
+.mw-warning {
+       border: 1px solid #aaa;
+       background-color: #f9f9f9;
+       padding: 5px;
+       font-size: 95%;
+}
+
+/**
+ * We want to display the ToC element with intrinsic width in block mode. The fit-content
+ * value for width is however not supported by large groups of browsers.
+ *
+ * We use display:table. Even though it should only contain other table-* display
+ * elements, there are no known problems with using this.
+ *
+ * Because IE < 8, FF 2 and other older browsers don't support display:table, we fallback to
+ * using inline-block mode, which features at least intrinsic width, but won't clear preceding
+ * inline elements. In practice inline elements surrounding the TOC are uncommon enough that
+ * this is an acceptable sacrifice.
+ */
+#toc,
+.toc {
+       display: -moz-inline-block;
+       display: inline-block;
+       display: table;
+
+       /* IE7 and earlier */
+       zoom: 1;
+       *display: inline;
+
+       padding: 7px;
+}
+
+/* CSS for backwards-compatibility with cached page renders and creative uses in wikitext */
+table#toc,
+table.toc {
+       border-collapse: collapse;
+}
+
+/* Remove additional paddings inside table-cells that are not present in <div>s */
+table#toc td,
+table.toc td {
+       padding: 0;
+}
+
+#toc h2,
+.toc h2 {
+       display: inline;
+       border: none;
+       padding: 0;
+       font-size: 100%;
+       font-weight: bold;
+}
+
+#toc #toctitle,
+.toc #toctitle,
+#toc .toctitle,
+.toc .toctitle {
+       text-align: center;
+}
+
+#toc ul,
+.toc ul {
+       list-style-type: none;
+       list-style-image: none;
+       margin-left: 0;
+       padding: 0;
+       text-align: left;
+}
+
+#toc ul ul,
+.toc ul ul {
+       margin: 0 0 0 2em;
+}
+
+#toc .toctoggle,
+.toc .toctoggle {
+       font-size: 94%;
+}
+
+.toccolours {
+       border: 1px solid #aaa;
+       background-color: #f9f9f9;
+       padding: 5px;
+       font-size: 95%;
+}
+
+/* Warning */
+.mw-warning {
+       margin-left: 50px;
+       margin-right: 50px;
+       text-align: center;
+}
+
+/* Images */
+/* @noflip */div.floatright, table.floatright {
+       margin: 0 0 .5em .5em;
+       border: 0;
+}
+
+div.floatright p {
+       font-style: italic;
+}
+
+/* @noflip */div.floatleft, table.floatleft {
+       margin: 0 .5em .5em 0;
+       border: 0;
+}
+
+div.floatleft p {
+       font-style: italic;
+}
+
+/* Thumbnails */
+div.thumb {
+       margin-bottom: .5em;
+       width: auto;
+       background-color: transparent;
+}
+
+div.thumbinner {
+       border: 1px solid #ccc;
+       padding: 3px;
+       background-color: #f9f9f9;
+       font-size: 94%;
+       text-align: center;
+       overflow: hidden;
+}
+
+html .thumbimage {
+       border: 1px solid #ccc;
+}
+
+html .thumbcaption {
+       border: none;
+       line-height: 1.4em;
+       padding: 3px;
+       font-size: 94%;
+       /* Default styles when there's no .mw-content-ltr or .mw-content-rtl, overridden below */
+       text-align: left;
+}
+
+div.magnify {
+       /* Default styles when there's no .mw-content-ltr or .mw-content-rtl, overridden below */
+       float: right;
+       margin-left: 3px;
+}
+
+div.magnify a {
+       display: block;
+       /* Hide the text… */
+       text-indent: 15px;
+       white-space: nowrap;
+       overflow: hidden;
+       /* …and replace it with the image */
+       width: 15px;
+       height: 11px;
+       /* Default styles when there's no .mw-content-ltr or .mw-content-rtl, overridden below */
+       /* @embed */
+       background: url(images/magnify-clip-ltr.png) center center no-repeat;
+       /* Don't annoy people who copy-paste everything too much */
+       -moz-user-select: none;
+       -webkit-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+
+/* Temporary WMF deployment hack, to be removed before 1.24 release */
+div.magnify img {
+       display: none;
+}
+
+img.thumbborder {
+       border: 1px solid #dddddd;
+}
+
+/* Directionality-specific styles for thumbnails - their positioning depends on content language */
+
+/* @noflip */
+.mw-content-ltr .thumbcaption {
+       text-align: left;
+}
+
+/* @noflip */
+.mw-content-ltr .magnify {
+       float: right;
+       margin-left: 3px;
+       margin-right: 0;
+}
+
+/* @noflip */
+.mw-content-ltr div.magnify a {
+       /* @embed */
+       background-image: url(images/magnify-clip-ltr.png);
+}
+
+/* @noflip */
+.mw-content-rtl .thumbcaption {
+       text-align: right;
+}
+
+/* @noflip */
+.mw-content-rtl .magnify {
+       float: left;
+       margin-left: 0;
+       margin-right: 3px;
+}
+
+/* @noflip */
+.mw-content-rtl div.magnify a {
+       /* @embed */
+       background-image: url(images/magnify-clip-rtl.png);
+}
+
+/* @noflip */
+div.tright {
+       margin: .5em 0 1.3em 1.4em;
+}
+
+/* @noflip */
+div.tleft {
+       margin: .5em 1.4em 1.3em 0;
+}
diff --git a/resources/src/mediawiki.skinning/content.externallinks.css b/resources/src/mediawiki.skinning/content.externallinks.css
new file mode 100755 (executable)
index 0000000..d23540d
--- /dev/null
@@ -0,0 +1,102 @@
+/*!
+ * Icons and colors for external links.
+ */
+
+/* Bug 66091 is blocking is from converting this file to LESS
+ * and using the .background-image-svg mixin. */
+
+/* SVG support using a transparent gradient to guarantee cross-browser
+ * compatibility (browsers able to understand gradient syntax support also SVG).
+ * http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique */
+
+.mw-body a.external,
+.link-https {
+       background: url(images/external-ltr.png) center right no-repeat;
+       /* @embed */
+       background-image: -webkit-linear-gradient(transparent, transparent), url(images/external-ltr.svg);
+       /* @embed */
+       background-image: linear-gradient(transparent, transparent), url(images/external-ltr.svg);
+       padding-right: 15px;
+}
+
+.mw-body a.external[href^="mailto:"],
+.link-mailto {
+       background: url(images/mail.png) center right no-repeat;
+       /* @embed */
+       background-image: -webkit-linear-gradient(transparent, transparent), url(images/mail.svg);
+       /* @embed */
+       background-image: linear-gradient(transparent, transparent), url(images/mail.svg);
+       padding-right: 15px;
+}
+
+.mw-body a.external[href^="ftp://"],
+.link-ftp {
+       background: url(images/ftp-ltr.png) center right no-repeat;
+       /* @embed */
+       background-image: -webkit-linear-gradient(transparent, transparent), url(images/ftp-ltr.svg);
+       /* @embed */
+       background-image: linear-gradient(transparent, transparent), url(images/ftp-ltr.svg);
+       padding-right: 15px;
+}
+
+.mw-body a.external[href^="irc://"],
+.mw-body a.external[href^="ircs://"],
+.link-irc {
+       background: url(images/chat-ltr.png) center right no-repeat;
+       /* @embed */
+       background-image: -webkit-linear-gradient(transparent, transparent), url(images/chat-ltr.svg);
+       /* @embed */
+       background-image: linear-gradient(transparent, transparent), url(images/chat-ltr.svg);
+       padding-right: 15px;
+}
+
+.mw-body a.external[href$=".ogg"], .mw-body a.external[href$=".OGG"],
+.mw-body a.external[href$=".mid"], .mw-body a.external[href$=".MID"],
+.mw-body a.external[href$=".midi"], .mw-body a.external[href$=".MIDI"],
+.mw-body a.external[href$=".mp3"], .mw-body a.external[href$=".MP3"],
+.mw-body a.external[href$=".wav"], .mw-body a.external[href$=".WAV"],
+.mw-body a.external[href$=".wma"], .mw-body a.external[href$=".WMA"],
+.link-audio {
+       background: url(images/audio-ltr.png) center right no-repeat;
+       /* @embed */
+       background-image: -webkit-linear-gradient(transparent, transparent), url(images/audio-ltr.svg);
+       /* @embed */
+       background-image: linear-gradient(transparent, transparent), url(images/audio-ltr.svg);
+       padding-right: 15px;
+}
+
+.mw-body a.external[href$=".ogm"], .mw-body a.external[href$=".OGM"],
+.mw-body a.external[href$=".avi"], .mw-body a.external[href$=".AVI"],
+.mw-body a.external[href$=".mpeg"], .mw-body a.external[href$=".MPEG"],
+.mw-body a.external[href$=".mpg"], .mw-body a.external[href$=".MPG"],
+.link-video {
+       background: url(images/video.png) center right no-repeat;
+       /* @embed */
+       background-image: -webkit-linear-gradient(transparent, transparent), url(images/video.svg);
+       /* @embed */
+       background-image: linear-gradient(transparent, transparent), url(images/video.svg);
+       padding-right: 15px;
+}
+
+.mw-body a.external[href$=".pdf"], .mw-body a.external[href$=".PDF"],
+.mw-body a.external[href*=".pdf#"], .mw-body a.external[href*=".PDF#"],
+.mw-body a.external[href*=".pdf?"], .mw-body a.external[href*=".PDF?"],
+.link-document {
+       background: url(images/document-ltr.png) center right no-repeat;
+       /* @embed */
+       background-image: -webkit-linear-gradient(transparent, transparent), url(images/document-ltr.svg);
+       /* @embed */
+       background-image: linear-gradient(transparent, transparent), url(images/document-ltr.svg);
+       padding-right: 15px;
+}
+
+/* Interwiki styling */
+.mw-body a.extiw,
+.mw-body a.extiw:active {
+       color: #36b;
+}
+
+/* External link color */
+.mw-body a.external {
+       color: #36b;
+}
index aeed611..3211dea 100644 (file)
@@ -34,6 +34,9 @@ span.reference {
        font-size: smaller;
        line-height: 1;
        vertical-align: super;
+       unicode-bidi: -moz-isolate;
+       unicode-bidi: -webkit-isolate;
+       unicode-bidi: isolate;
 }
 
 sup, sub {
@@ -69,11 +72,8 @@ figure[typeof*='mw:Image'] {
        }
 
        &.mw-halign-none {
-               /* @noflip */
                margin: 0;
-               /* @noflip */
                clear: none;
-               /* @noflip */
                float: none;
        }
 
@@ -129,13 +129,3 @@ figure[typeof~='mw:Image/Frame'] > *:first-child > img,
 /* Hide the caption for frameless and plain floated images */
 figure[typeof~="mw:Image/Frameless"] > figcaption,
 figure[typeof~="mw:Image"] > figcaption { display: none }
-
-/*
- * Finally, some basic styling for Parsoid render testing.
- * Only Parsoid directly sets .mw-body-content directly on the body, so this
- * shouldn't affect anything else.
- */
-body.mw-body-content {
-       background-color: #fff;
-       padding: 0.8em;
-}
diff --git a/resources/src/mediawiki.skinning/elements.css b/resources/src/mediawiki.skinning/elements.css
new file mode 100644 (file)
index 0000000..392a2a6
--- /dev/null
@@ -0,0 +1,273 @@
+/**
+ * MediaWiki style sheet for general styles on basic content elements
+ *
+ * Styles for basic elements: links, lists, etc...
+ *
+ * This style sheet is used by the Monobook and Vector skins.
+ */
+
+/* Links */
+a {
+       text-decoration: none;
+       color: #0645ad;
+       background: none;
+}
+
+a:visited {
+       color: #0b0080;
+}
+
+a:active {
+       color: #faa700;
+}
+
+a:hover, a:focus {
+       text-decoration: underline;
+}
+
+a.stub {
+       color: #772233;
+}
+
+a.new, #p-personal a.new {
+       color: #ba0000;
+}
+
+a.new:visited, #p-personal a.new:visited {
+       color: #a55858;
+}
+
+/* Interwiki Styling */
+.mw-body a.extiw,
+.mw-body a.extiw:active {
+       color: #36b;
+}
+
+.mw-body a.extiw:visited {
+       color: #636;
+}
+
+.mw-body a.extiw:active {
+       color: #b63;
+}
+
+/* External links */
+.mw-body a.external {
+       color: #36b;
+}
+
+.mw-body a.external:visited {
+       color: #636; /* bug 3112 */
+}
+
+.mw-body a.external:active {
+       color: #b63;
+}
+
+/* Inline Elements */
+img {
+       border: none;
+       vertical-align: middle;
+}
+
+hr {
+       height: 1px;
+       color: #aaa;
+       background-color: #aaa;
+       border: 0;
+       margin: .2em 0;
+}
+
+/* Structural Elements */
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+       color: black;
+       background: none;
+       font-weight: normal;
+       margin: 0;
+       overflow: hidden;
+       padding-top: .5em;
+       padding-bottom: .17em;
+       border-bottom: 1px solid #aaa;
+}
+
+h1 {
+       font-size: 188%;
+}
+
+h2 {
+       font-size: 150%;
+}
+
+h3,
+h4,
+h5,
+h6 {
+       border-bottom: none;
+       font-weight: bold;
+}
+
+h3 {
+       font-size: 132%;
+}
+
+h4 {
+       font-size: 116%;
+}
+
+h5 {
+       font-size: 108%;
+}
+
+h6 {
+       font-size: 100%;
+}
+
+/* Some space under the headers in the content area */
+h1,
+h2 {
+       margin-bottom: .6em;
+}
+
+h3,
+h4,
+h5 {
+       margin-bottom: .3em;
+}
+
+p {
+       margin: .4em 0 .5em 0;
+       line-height: 1.5em;
+}
+
+p img {
+       margin: 0;
+}
+
+ul {
+       line-height: 1.5em;
+       list-style-type: square;
+       margin: .3em 0 0 1.6em;
+       padding: 0;
+}
+
+ol {
+       line-height: 1.5em;
+       margin: .3em 0 0 3.2em;
+       padding: 0;
+       list-style-image: none;
+}
+
+li {
+       margin-bottom: .1em;
+}
+
+dt {
+       font-weight: bold;
+       margin-bottom: .1em;
+}
+
+dl {
+       margin-top: .2em;
+       margin-bottom: .5em;
+}
+
+dd {
+       line-height: 1.5em;
+       margin-left: 1.6em;
+       margin-bottom: .1em;
+}
+
+/* IE 6 and 7 lack support for quotes aroud the <q> element ('::before' and '::after'
+   pseudoelements, 'quotes' property). Let's italicize it instead (using the star hack). */
+q {
+       *font-style: italic;
+}
+
+pre, code, tt, kbd, samp, .mw-code {
+       /*
+        * Some browsers will render the monospace text too small, namely Firefox, Chrome and Safari.
+        * Specifying any valid, second value will trigger correct behavior without forcing a different font.
+        */
+       font-family: monospace, Courier;
+}
+
+code {
+       color: black;
+       background-color: #f9f9f9;
+       border: 1px solid #ddd;
+       border-radius: 2px;
+       padding: 1px 4px;
+}
+
+pre, .mw-code {
+       color: black;
+       background-color: #f9f9f9;
+       border: 1px solid #ddd;
+       padding: 1em;
+}
+
+/* Tables */
+table {
+       font-size: 100%;
+}
+
+/* Forms */
+fieldset {
+       border: 1px solid #2f6fab;
+       margin: 1em 0 1em 0;
+       padding: 0 1em 1em;
+       line-height: 1.5em;
+}
+
+fieldset.nested {
+       margin: 0 0 0.5em 0;
+       padding: 0 0.5em 0.5em;
+}
+
+legend {
+       padding: .5em;
+       font-size: 95%;
+}
+
+form {
+       border: none;
+       margin: 0;
+}
+
+textarea {
+       width: 100%;
+       padding: .1em;
+       display: block;
+       -moz-box-sizing: border-box;
+       -webkit-box-sizing: border-box;
+       box-sizing: border-box;
+}
+
+select {
+       vertical-align: top;
+}
+
+/* Emulate Center */
+.center {
+       width: 100%;
+       text-align: center;
+}
+
+*.center * {
+       margin-left: auto;
+       margin-right: auto;
+}
+
+/* Small for tables and similar */
+.small {
+       font-size: 94%;
+}
+
+table.small {
+       font-size: 100%;
+}
diff --git a/resources/src/mediawiki.skinning/images/audio-ltr.png b/resources/src/mediawiki.skinning/images/audio-ltr.png
new file mode 100644 (file)
index 0000000..8efc4f2
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/audio-ltr.png differ
diff --git a/resources/src/mediawiki.skinning/images/audio-ltr.svg b/resources/src/mediawiki.skinning/images/audio-ltr.svg
new file mode 100644 (file)
index 0000000..e27a5f5
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.467808,-258.39005)">
+<path style="opacity:1;fill:#3366bb;" d="m43.47,259.4-3,3-3,0,0,4,3,0,3,3zm-1,2.5,0,5-1.5-1.5-2.5,0,0-2,2.5,0z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m43.9,262.5c0-0.6213,0.6213-1.243,1.243-0.6213,0,0,0.6213,0.6213,0.6213,2.485s-0.6213,2.485-0.6213,2.485c-0.6213,0.6213-1.243,0-1.243-0.6213,0,0,0.6213-0.6213,0.6213-1.864s-0.6213-1.864-0.6213-1.864z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m45.76,261.2c0-0.6213,0.6213-1.243,1.243-0.6213,0,0,1.243,1.243,1.243,3.728s-1.243,3.728-1.243,3.728c-0.6213,0.6213-1.243,0-1.243-0.6213,0,0,1.243-1.243,1.243-3.107s-1.243-3.107-1.243-3.107z"/>
+</g>
+</svg>
diff --git a/resources/src/mediawiki.skinning/images/audio-rtl.png b/resources/src/mediawiki.skinning/images/audio-rtl.png
new file mode 100644 (file)
index 0000000..1afdf40
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/audio-rtl.png differ
diff --git a/resources/src/mediawiki.skinning/images/audio-rtl.svg b/resources/src/mediawiki.skinning/images/audio-rtl.svg
new file mode 100644 (file)
index 0000000..683bbcd
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.467808,-258.39005)">
+<path style="opacity:1;fill:#3366bb;" d="m42.47,259.4,3,3,3,0,0,4-3,0-3,3zm1,2.5,0,5,1.5-1.5,2.5,0,0-2-2.5,0z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m42.04,262.5c0-0.6213-0.6213-1.243-1.243-0.6213,0,0-0.6213,0.6213-0.6213,2.485s0.6213,2.485,0.6213,2.485c0.6213,0.6213,1.243,0,1.243-0.6213,0,0-0.6213-0.6213-0.6213-1.864s0.6213-1.864,0.6213-1.864z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m40.17,261.2c0-0.6213-0.6213-1.243-1.243-0.6213,0,0-1.243,1.243-1.243,3.728s1.243,3.728,1.243,3.728c0.6213,0.6213,1.243,0,1.243-0.6213,0,0-1.243-1.243-1.243-3.107s1.243-3.107,1.243-3.107z"/>
+</g>
+</svg>
diff --git a/resources/src/mediawiki.skinning/images/chat-ltr.png b/resources/src/mediawiki.skinning/images/chat-ltr.png
new file mode 100644 (file)
index 0000000..624ecec
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/chat-ltr.png differ
diff --git a/resources/src/mediawiki.skinning/images/chat-ltr.svg b/resources/src/mediawiki.skinning/images/chat-ltr.svg
new file mode 100644 (file)
index 0000000..bd5329e
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.467808,-258.39005)">
+<path style="opacity:1;fill:#3366bb;" d="m38.09,260.4-0.6213,0.6213,0,5.757,0.6213,0.6213,1.689,0-0.6213,2.728,4.311-2.728,4.379,0,0.6213-0.6213,0-5.757-0.6213-0.6213zm0.3787,1,9,0,0,5-4,0-2.902,1.897,0.9021-1.897-3,0z"/>
+</g>
+</svg>
diff --git a/resources/src/mediawiki.skinning/images/chat-rtl.png b/resources/src/mediawiki.skinning/images/chat-rtl.png
new file mode 100644 (file)
index 0000000..f90fa33
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/chat-rtl.png differ
diff --git a/resources/src/mediawiki.skinning/images/chat-rtl.svg b/resources/src/mediawiki.skinning/images/chat-rtl.svg
new file mode 100644 (file)
index 0000000..b86218f
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.467808,-258.39005)">
+<path style="opacity:1;fill:#3366bb;" d="m47.85,260.4,0.6213,0.6213,0,5.757-0.6213,0.6213-1.689,0,0.6213,2.728-4.311-2.728-4.379,0-0.6213-0.6213,0-5.757,0.6213-0.6213zm-0.3787,1-9,0,0,5,4,0,2.902,1.897-0.9021-1.897,3,0z"/>
+</g>
+</svg>
diff --git a/resources/src/mediawiki.skinning/images/document-ltr.png b/resources/src/mediawiki.skinning/images/document-ltr.png
new file mode 100644 (file)
index 0000000..4ea9373
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/document-ltr.png differ
diff --git a/resources/src/mediawiki.skinning/images/document-ltr.svg b/resources/src/mediawiki.skinning/images/document-ltr.svg
new file mode 100644 (file)
index 0000000..4396098
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<path style="opacity:1;fill:#15a5ea;" d="m7.5,2,0,3,2.5,0,1-1-2.5,0,0-3z"/>
+<path style="opacity:1;fill:#3366bb;" d="m3,1,0,10,8,0,0-7-2.5-3zm1,1,4,0,2,2.5,0,5.5-6,0z"/>
+</svg>
diff --git a/resources/src/mediawiki.skinning/images/document-rtl.png b/resources/src/mediawiki.skinning/images/document-rtl.png
new file mode 100644 (file)
index 0000000..c281677
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/document-rtl.png differ
diff --git a/resources/src/mediawiki.skinning/images/document-rtl.svg b/resources/src/mediawiki.skinning/images/document-rtl.svg
new file mode 100644 (file)
index 0000000..c37dadc
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<path style="opacity:1;fill:#15a5ea;" d="m5.5,2,0,3-2.5,0-1-1,2.5,0,0-3z"/>
+<path style="opacity:1;fill:#3366bb;" d="m10,1,0,10-8,0,0-7,2.5-3zm-1,1-4,0-2,2.5,0,5.5,6,0z"/>
+</svg>
diff --git a/resources/src/mediawiki.skinning/images/external link icons.svg b/resources/src/mediawiki.skinning/images/external link icons.svg
new file mode 100644 (file)
index 0000000..6a67993
--- /dev/null
@@ -0,0 +1,697 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="13"
+   height="110"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="external link icons.svg">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="15.999999"
+     inkscape:cx="10.40536"
+     inkscape:cy="65.686256"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer5"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1283"
+     inkscape:window-height="711"
+     inkscape:window-x="1790"
+     inkscape:window-y="-6"
+     inkscape:window-maximized="0">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3246"
+       empspacing="4"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       originx="0px"
+       originy="-27.999997px" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="base"
+     style="display:none"
+     transform="translate(-505,-869.36218)">
+    <rect
+       style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4646"
+       width="13"
+       height="12.999996"
+       x="505"
+       y="885.36218" />
+    <rect
+       style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4646-4"
+       width="13"
+       height="12.999998"
+       x="505"
+       y="901.36218" />
+    <rect
+       style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4646-4-6"
+       width="13"
+       height="12.999996"
+       x="505"
+       y="917.36218"
+       inkscape:export-filename="/home/rahah/elvidishu/steak/unreal/dev/skins/external link icons/mail.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90" />
+    <rect
+       style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4646-4-6-9"
+       width="13"
+       height="12.999996"
+       x="505"
+       y="933.36218" />
+    <rect
+       style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4646-4-6-6"
+       width="13"
+       height="12.999996"
+       x="505"
+       y="950.36218" />
+    <rect
+       style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4646-4-6-2"
+       width="13"
+       height="12.999998"
+       x="505"
+       y="966.36218" />
+    <rect
+       style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+       id="rect4646-44"
+       width="13"
+       height="12.999996"
+       x="505"
+       y="869.36218" />
+  </g>
+  <g
+     inkscape:label="sketch 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-505,-869.36218)"
+     style="display:none"
+     sodipodi:insensitive="true">
+    <path
+       style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 507,870.36218 0,5 3,0 4,4 0,-13 -4,4 z"
+       id="path3194"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccc" />
+    <path
+       style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 517,869.36218 c 1,2 1,5 0,7"
+       id="path3196"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 520,867.36218 c 2,2 2,9 0,11"
+       id="path3198"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 507.93861,989.90562 0,15.99988 13,0 0,-10.99988 -5,-5 z"
+       id="path3200"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccc" />
+    <path
+       style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 506.93861,918.90546 0,11.5 15,0 0,-11.5 z"
+       id="path3202"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 506.93861,918.90546 7.5,6 7.5,-6"
+       id="path3204"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccc" />
+    <path
+       style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 507.93861,890.90546 3,0"
+       id="path3212"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 507.93861,893.90546 3,0"
+       id="path3214"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 507.93861,899.90546 3,0"
+       id="path3218"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 507.93861,902.90546 3,0"
+       id="path3220"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 517.93861,890.90546 3,0"
+       id="path3222"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 507.93861,896.90546 13,0"
+       id="path3224"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 517.93861,893.90546 3,0"
+       id="path3226"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 517.93861,899.90546 3,0"
+       id="path3230"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 517.93861,902.90546 3,0"
+       id="path3232"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 510.93861,890.90546 0,12 7,0 0,-12 z"
+       id="path3206"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 507.93861,888.90546 0,16"
+       id="path3208"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 520.93861,888.90546 0,16"
+       id="path3210"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 515.93861,989.90562 0,5 5,0"
+       id="path3234"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccc" />
+    <path
+       style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 513.93861,969.40546 c -2,0 -5,0 -7,0 l 0,10.99995 11,5e-5 c 0,-2.33332 0,-4.66668 0,-7"
+       id="path3236"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none"
+       d="m 513.93861,976.40546 5,-4 3,3 0,-10 -10,0 3,3 -4,5"
+       id="path3242"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccc" />
+    <path
+       style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 506.93861,940.40546 15,0 0,10 -6,0 -6,4 1,-4 -4,0 z"
+       id="path3244"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccc" />
+    <path
+       style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 509.93861,972.40546 c 2,1 4,3 5,5"
+       id="path4641"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="sketch 2"
+     style="display:none"
+     transform="translate(0,-6.0000106)">
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 8.4921988,1.0623917 -4.0641234,4.064123 -3.2512987,0 0,5.6897733 3.2512987,0 4.0641234,4.064124 z m -1.6256494,4.064124 0,5.6897733 -1.6256493,-1.6256493 -2.438474,-1e-6 0,-2.438474 2.438474,1e-6 z"
+       id="path4755-9"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="m 9.3050235,5.1265157 c 0,-0.812824 0.8128245,-1.625649 1.6256495,-0.812824 0,0 0.812825,0.812824 0.812825,3.251298 0,2.4384743 -0.812825,3.2512993 -0.812825,3.2512993 -0.812825,0.812825 -1.6256495,0 -1.6256495,-0.812825 0,0 0.8128245,-0.8128243 0.8128245,-2.4384743 0,-1.625649 -0.8128245,-2.438474 -0.8128245,-2.438474 z"
+       id="path4760-1"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccsccsc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="m 11.743498,3.5008667 c 0,-0.812825 0.812824,-1.625649 1.625649,-0.812825 0,0 1.625649,1.62565 1.625649,4.876948 0,3.2512993 -1.625649,4.8769483 -1.625649,4.8769483 -0.812825,0.812825 -1.625649,0 -1.625649,-0.812824 0,0 1.625649,-1.62565 1.625649,-4.0641243 0,-2.438474 -1.625649,-4.064123 -1.625649,-4.064123 z"
+       id="path4762-8"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccsccsc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 2.8024261,23.008658 0,0.812825 10.5667209,0 0,-0.812825 z"
+       id="path4772"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 2.8024261,33.575379 10.5667209,0 0,-0.812825 -10.5667209,0 z"
+       id="path4774"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 2.8024261,25.447132 0,0.812824 2.438474,0 0,-0.812824 z m 8.1282469,0 0,0.812824 2.438474,0 0,-0.812824 z"
+       id="path4782"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 2.8024261,30.32408 0,0.812824 2.438474,0 0,-0.812824 z m 8.1282469,0 0,0.812824 2.438474,0 0,-0.812824 z"
+       id="path4778"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 2.8024261,28.698431 10.5667209,0 0,-0.812825 -10.5667209,0 z"
+       id="path4780"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="m 5.2409001,27.479194 0,1.625649 5.6897729,0 0,-1.625649 z"
+       id="path4793"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 4.4280754,23.008658 0,10.56672 7.3154226,0 0,-10.56672 z m 1.6256494,1.625649 4.0641232,0 0,7.315422 -4.0641232,0 z"
+       id="path4768"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 1.9896014,21.383009 1.6256493,0 0,13.818019 -1.6256493,0 z"
+       id="path4764"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 12.556322,21.383009 1.62565,0 0,13.818019 -1.62565,0 z"
+       id="path4766"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="m 1.9896014,44.954923 6.096185,5.689773 6.0961856,-5.689773 -0.812825,-0.812825 -1.625649,0.813196 -3.6577116,3.251298 -3.657711,-3.251298 -1.6256493,-0.813196 z"
+       id="path4800-4"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 1.1767767,43.329273 0,11.379545 13.8180193,0 0,-11.379545 z m 1.6256494,1.625649 10.5667209,0 0,8.128247 -10.5667209,0 z"
+       id="path4795-8"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 1.9896014,62.024243 -0.8128247,0.812824 0,8.128247 0.8128247,0.812825 2.438474,0 -0.8128247,3.251297 5.6897728,-3.251297 4.8769485,0 0.812824,-0.812825 0,-8.128247 -0.812824,-0.812824 z m 0.8128247,1.625649 10.5667209,0 0,6.502598 -4.0641235,0 -3.5815088,2.133664 0.9144278,-2.133664 -3.8355164,0 z"
+       id="path4802-8"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccccccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 4.4280754,82.344856 10.5667206,0 0,10.56672 -3.251298,-3.25129 -3.2512992,2.43847 -0.8128247,-0.81282 4.0641239,-3.2513 1.625649,1.62565 0,-5.68978 -5.6897729,0 1.6256494,1.62565 -3.2512987,4.06413 -0.8128247,-0.81283 2.438474,-3.2513 z"
+       id="path4807-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 8.4921988,85.596156 -7.3154221,0 0,10.56672 10.5667213,0 0,-7.31542 -1.62565,0.81283 0,4.87694 -7.3154219,0 0,-7.31542 4.876948,0 z"
+       id="path4809-7"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="m 8.4921988,103.47831 0,4.87694 4.8769482,0 0,-1.62565 -3.251299,0 0,-3.25129 z"
+       id="path4818-67"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 1.9896014,102.66548 0,13.81802 12.1923706,0 0,-10.13799 -3.657711,-3.68003 z m 1.6256493,1.62565 6.5025973,0 2.438474,2.43847 0,8.12825 -8.9410713,0 z"
+       id="path4813-2"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="m 3.6152507,88.847456 c 0,-0.81282 0.8128247,-0.81282 0.8128247,-0.81282 2.438474,0.81282 4.0641234,2.43847 4.8769481,4.87694 0,0 0,0.81283 -0.8128247,0.81283 -1.6256494,-2.43847 -2.438474,-3.2513 -4.8769481,-4.87695 z"
+       id="path4822-8"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer"
+     style="display:none"
+     transform="translate(-10,-26.000007)">
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none"
+       d="m 19,20.999995 -4,4 -3,0 0,6 3,0 4,4 z m -1,2.5 0,9 -2.6,-2.5 -2.4,0 0,-4 2.5,0 z"
+       id="path4755"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none"
+       d="m 19.75,24.999995 c 0,-1 0.75,-1 0.75,-1 0,0 1.5,1.029412 1.5,3.5 0,2.470588 -1.5,3.5 -1.5,3.5 0,0 -0.75,0 -0.75,-1 0,0 1,-0.852941 1,-2.5 0,-1.647059 -1,-2.5 -1,-2.5 z"
+       id="path4760"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccsccsc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none"
+       d="m 22.25,23.999995 c 0,-1 0.75,-1 0.75,-1 0,0 2,1.205882 2,4.5 0,3.294118 -2,4.5 -2,4.5 0,0 -0.75,0 -0.75,-1 0,0 1.5,-1.029412 1.5,-3.5 0,-2.470588 -1.5,-3.5 -1.5,-3.5 z"
+       id="path4762"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccsccsc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none"
+       d="m 31.4375,79.875 -1,1 0,10 1,1 3,0 -1,4 7,-4 6,0 1,-1 0,-10 -1,-1 z m 1,2 13,0 0,8 -5,0 -4.40625,2.625 1.125,-2.625 -4.71875,0 z"
+       id="path4802"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccccccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none"
+       d="m 35.125,98.8125 13,0 0,13 -4,-4 -4,3 -1,-1 5,-4 2,2 0,-7 -7,0 2,2 -4,5 -1,-1 3,-4 z"
+       id="path4807"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none"
+       d="m 40.125,102.8125 -9,0 0,13 13,0 0,-9 -2,1 0,6 -9,0 0,-9 6,0 z"
+       id="path4809"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none"
+       d="m 34.125,106.8125 c 0,-1 1,-1 1,-1 3,1 5,3 6,6 0,0 0,1 -1,1 -2,-3 -3,-4 -6,-6 z"
+       id="path4822"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       d="m 12,50.499995 0,1 3,0 0,-1 -3,0 z m 9,0 0,1 3,0 0,-1 -3,0 z"
+       id="rect4841"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       d="m 12,44.499995 0,1 3,0 0,-1 -3,0 z m 9,0 0,1 3,0 0,-1 -3,0 z"
+       id="rect4843"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+       d="m 12,52.999995 0,1 3,0 0,-1 z m 9,0 0,1 3,0 0,-1 z"
+       id="rect4843-1"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+       d="m 12,41.999995 0,1 3,0 0,-1 z m 9,0 0,1 3,0 0,-1 z"
+       id="rect4843-17"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+       d="m 12,47.499995 0,1 3,0 0,-1 z m 9,0 0,1 3,0 0,-1 z"
+       id="rect4841-9"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccc" />
+    <rect
+       style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4835"
+       width="7"
+       height="2"
+       x="4"
+       y="27"
+       transform="translate(10,19.999995)" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none"
+       d="m 2,21 1,0 0,14 -1,0 z"
+       id="path4826"
+       inkscape:connector-curvature="0"
+       transform="translate(10,19.999995)"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none"
+       d="m 13,21 1,0 0,14 -1,0 z"
+       id="path4828"
+       inkscape:connector-curvature="0"
+       transform="translate(10,19.999995)"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none"
+       d="m 4,22 0,12 8,0 0,-12 z m 1,1 6,0 0,10 -6,0 z"
+       transform="translate(10,19.999995)"
+       id="path4830"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccc" />
+    <rect
+       style="fill:#3366bb;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4837"
+       width="8"
+       height="1"
+       x="4"
+       y="22"
+       transform="translate(10,19.999995)" />
+    <rect
+       style="fill:#3366bb;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4839"
+       width="8"
+       height="1"
+       x="4"
+       y="33"
+       transform="translate(10,19.999995)" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none"
+       d="m 12,64.999995 6,5 6,-5 0.53033,-1.45299 -1.28033,0.45299 -5.25,4.5 -5.25,-4.5 -1.236136,-0.53033 z"
+       id="path4910"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none"
+       d="m 11,62.999995 0,10 14,0 0,-10 z m 1,1 12,0 0,8 -12,0 z"
+       id="path4905"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="m 19,121 0,5 5,0 -1,-1 -3,0 0,-3 z"
+       id="path4818-6"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 12,121 0,14 12,0 0,-10 -4,-4 z m 1,1 6.5,0 3.5,3.5 0,8.5 -10,0 z"
+       id="path4813-3"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccc" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer5"
+     inkscape:label="Layer#1"
+     style="opacity:0.98999999"
+     transform="translate(0,-6.0000106)">
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 7,23.000004 -3,3 -3,0 0,4 3,0 3,3 z m -1,2.500001 0,5 -1.5,-1.500001 -2.5,0 0,-2 2.5,0 z"
+       id="path4755-9-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="m 7.4319858,26.075368 c 0,-0.621323 0.6213237,-1.242647 1.2426477,-0.621323 0,0 0.6213228,0.621323 0.6213228,2.485294 0,1.863971 -0.6213228,2.485294 -0.6213228,2.485294 -0.621324,0.621324 -1.2426477,0 -1.2426477,-0.621323 0,0 0.6213237,-0.621324 0.6213237,-1.863971 0,-1.242648 -0.6213237,-1.863971 -0.6213237,-1.863971 z"
+       id="path4760-1-7"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccsccsc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="m 9.2959563,24.832721 c 0,-0.621324 0.6213228,-1.242647 1.2426477,-0.621324 0,0 1.242646,1.242648 1.242646,3.727942 0,2.485294 -1.242646,3.727941 -1.242646,3.727941 -0.6213249,0.621324 -1.2426477,0 -1.2426477,-0.621323 0,0 1.2426477,-1.242647 1.2426477,-3.106618 0,-1.863971 -1.2426477,-3.106618 -1.2426477,-3.106618 z"
+       id="path4762-8-3"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccsccsc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+       d="m 2.4916056,40.000004 0,0.621323 8.0979164,0 0,-0.621323 z"
+       id="path4772-4"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+       d="m 2.4916056,48.000004 8.0979164,0 0,-0.621324 -8.0979164,0 z"
+       id="path4774-6"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+       d="m 2.4916056,41.919118 0,0.621323 1.8687499,0 0,-0.621323 z m 6.2291665,0 0,0.621323 1.8687499,0 0,-0.621323 z"
+       id="path4782-3"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+       d="m 2.4916056,45.589344 0,0.621322 1.8687499,0 0,-0.621322 z m 6.2291665,0 0,0.621322 1.8687499,0 0,-0.621322 z"
+       id="path4778-9"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+       d="m 2.4916056,44.404412 8.0979164,0 0,-0.621323 -8.0979164,0 z"
+       id="path4780-0"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="m 4.3603555,43.472427 0,1.242647 4.3604166,0 0,-1.242647 z"
+       id="path4793-0"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 4,40.000004 0,8 5,0 0,-8 z m 1,1 3,0 0,6 -3,0 z"
+       id="path4768-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 2,39.000004 1,0 0,10 -1,0 z"
+       id="path4764-1"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 10,39.000004 1,0 0,10 -1,0 z"
+       id="path4766-6"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="M 1.8400738,58.055766 6.5000005,62.405031 11.159927,58.055766 10.538604,57.434442 9.2959563,58.056049 6.5000005,60.541343 3.7040445,58.056049 2.4613977,57.434442 z"
+       id="path4800-4-9"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccc"
+       inkscape:export-filename="/home/rahah/elvidishu/steak/unreal/dev/skins/external link icons/mail.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 1,57.000008 0,8 11,0 0,-8 z m 1,1 9,0 0,6 -9,0 z"
+       id="path4795-8-2"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccc"
+       inkscape:export-filename="/home/rahah/elvidishu/steak/unreal/dev/skins/external link icons/mail.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="M 1.6213238,72.000004 1,72.621328 l 0,5.757352 0.6213238,0.621324 1.6894529,0 L 2.6894528,81.727943 7,79.000004 l 4.378677,0 L 12,78.37868 12,72.621328 11.378677,72.000004 z m 0.3786762,1 9,0 0,5 -4,0 L 4.0978858,79.896603 5,78.000004 l -3,0 z"
+       id="path4802-8-9"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccccccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 5,88.000004 7,0 0,7 -2,-2 -3,2 0,-1 3,-2.249999 1,1 0,-3.750001 -3.75,0 1,1 -2.25,3 -1,0 2,-3 z"
+       id="path4807-5-6"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 7,90.000004 -5,0 0,8 8,0 0,-5 -1,0 0,4 -6,0 0,-6 4,0 z"
+       id="path4809-7-3"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="m 7.5,105.00001 0,3 2.5,0 1,-1 -2.5,0 0,-3 z"
+       id="path4818-67-7"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccc" />
+    <path
+       style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+       d="m 3,104 0,10 8,1e-5 0,-7 -2.5,-3 z m 1,1 4,1e-5 2,2.50001 0,5.49999 -6,0 z"
+       id="path4813-2-2"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccc" />
+    <path
+       style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+       d="m 4.0827206,92.533089 c 0,-0.621319 0.6213239,-0.621319 0.6213239,-0.621319 1.8639706,0.621319 3.1066175,1.863968 3.7279413,3.727935 0,0 0,0.621328 -0.6213238,0.621328 C 6.5680151,94.397065 5.9466913,93.775738 4.0827206,92.533089 z"
+       id="path4822-8-2"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#3465ba;fill-opacity:1;stroke:none;display:inline"
+       d="m 1,8.500006 0,7.5001 1,-0.9872 0,-6.0129 2,0 2,1 4,-2e-4 0,2.0002 1,0 0,-2.5 -0.5,-0.5002 -4.5,2e-4 -2,-1 -2.5,0 z"
+       id="path3209"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccccccccc" />
+    <path
+       style="fill:#16a4e8;fill-opacity:1;stroke:none;display:inline"
+       d="m 6,11.000106 -1,-10e-5 -2.5,0 -0.5,0.5 -1,4.5001 10,-10e-5 0,-4.4998 -0.5,-0.5 z m 0,1 4,-10e-5 0,3 -7.75,-1e-4 0.75,-3.0001 2,0 z"
+       id="path3215"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccccccc" />
+    <path
+       style="fill:#3465ba;fill-opacity:1;stroke:none;display:inline"
+       d="m 2,17.000006 0,1 8,0 0,-1 z"
+       id="path3247"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#3465ba;fill-opacity:1;stroke:none;display:inline"
+       d="m 5,15.500006 0,2 2,0 0,-2 c 0,-0.5 -2,-0.5 -2,0 z"
+       id="path3249"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+  </g>
+</svg>
diff --git a/resources/src/mediawiki.skinning/images/external-ltr.png b/resources/src/mediawiki.skinning/images/external-ltr.png
new file mode 100644 (file)
index 0000000..75750ef
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/external-ltr.png differ
diff --git a/resources/src/mediawiki.skinning/images/external-ltr.svg b/resources/src/mediawiki.skinning/images/external-ltr.svg
new file mode 100644 (file)
index 0000000..e914b7d
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.467808,-258.39005)">
+<path style="opacity:1;fill:#3366bb;" d="m41.47,259.4,7,0,0,7-2-2-3,2,0-1,3-2.25,1,1,0-3.75-3.75,0,1,1-2.25,3-1,0,2-3z"/>
+<path style="opacity:1;fill:#3366bb;" d="m43.47,261.4-5,0,0,8,8,0,0-5-1,0,0,4-6,0,0-6,4,0z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m40.55,263.9c0-0.6213,0.6213-0.6213,0.6213-0.6213,1.864,0.6213,3.107,1.864,3.728,3.728,0,0,0,0.6213-0.6213,0.6213-1.243-1.864-1.864-2.485-3.728-3.728z"/>
+</g>
+</svg>
diff --git a/resources/src/mediawiki.skinning/images/external-rtl.png b/resources/src/mediawiki.skinning/images/external-rtl.png
new file mode 100644 (file)
index 0000000..7b56aaa
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/external-rtl.png differ
diff --git a/resources/src/mediawiki.skinning/images/external-rtl.svg b/resources/src/mediawiki.skinning/images/external-rtl.svg
new file mode 100644 (file)
index 0000000..698c616
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.467808,-258.39005)">
+<path style="opacity:1;fill:#3366bb;" d="m44.47,259.4-7,0,0,7,2-2,3,2,0-1-3-2.25-1,1,0-3.75,3.75,0-1,1,2.25,3,1,0-2-3z"/>
+<path style="opacity:1;fill:#3366bb;" d="m42.47,261.4,5,0,0,8-8,0,0-5,1,0,0,4,6,0,0-6-4,0z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m45.39,263.9c0-0.6213-0.6213-0.6213-0.6213-0.6213-1.864,0.6213-3.107,1.864-3.728,3.728l0.6213,0.6213c1.243-1.864,1.864-2.485,3.728-3.728z"/>
+</g>
+</svg>
diff --git a/resources/src/mediawiki.skinning/images/ftp-ltr.png b/resources/src/mediawiki.skinning/images/ftp-ltr.png
new file mode 100644 (file)
index 0000000..f940b06
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/ftp-ltr.png differ
diff --git a/resources/src/mediawiki.skinning/images/ftp-ltr.svg b/resources/src/mediawiki.skinning/images/ftp-ltr.svg
new file mode 100644 (file)
index 0000000..3a90c31
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-136.35715,-374.43362)">
+<path style="opacity:1;fill:#3465ba;" d="m137.4,376.9,0,7.5,1-0.9872,0-6.013,2,0,2,1,4-0.0002,0,2,1,0,0-2.5-0.5-0.5002-4.5,0.0002-2-1-2.5,0z"/>
+<path style="opacity:1;fill:#16a4e8;" d="m142.4,379.4-1-0.0001-2.5,0-0.5,0.5-1,4.5,10-0.0001,0-4.5-0.5-0.5zm0,1,4-0.0001,0,3-7.75-0.0001,0.75-3,2,0z"/>
+<path style="opacity:1;fill:#3465ba;" d="m138.4,385.4,0,1,8,0,0-1z"/>
+<path style="opacity:1;fill:#3465ba;" d="m141.4,383.9,0,2,2,0,0-2c0-0.5-2-0.5-2,0z"/>
+</g>
+</svg>
diff --git a/resources/src/mediawiki.skinning/images/ftp-rtl.png b/resources/src/mediawiki.skinning/images/ftp-rtl.png
new file mode 100644 (file)
index 0000000..ff76304
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/ftp-rtl.png differ
diff --git a/resources/src/mediawiki.skinning/images/ftp-rtl.svg b/resources/src/mediawiki.skinning/images/ftp-rtl.svg
new file mode 100644 (file)
index 0000000..29e4b44
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-136.35715,-374.43362)">
+<path style="opacity:1;fill:#3465ba;" d="m148.4,376.9,0,7.5-1-0.9872,0-6.013-2,0-2,1-4-0.0002,0,2-1,0,0-2.5,0.5-0.5002,4.5,0.0002,2-1,2.5,0z"/>
+<path style="opacity:1;fill:#16a4e8;" d="m143.4,379.4,1-0.0001,2.5,0,0.5,0.5,1,4.5-10-0.0001,0-4.5,0.5-0.5zm0,1-4-0.0001,0,3,7.75-0.0001-0.75-3-2,0z"/>
+<path style="opacity:1;fill:#3465ba;" d="m147.4,385.4,0,1-8,0,0-1z"/>
+<path style="opacity:1;fill:#3465ba;" d="m144.4,383.9,0,2-2,0,0-2c0-0.5,2-0.5,2,0z"/>
+</g>
+</svg>
diff --git a/resources/src/mediawiki.skinning/images/magnify-clip-ltr.png b/resources/src/mediawiki.skinning/images/magnify-clip-ltr.png
new file mode 100644 (file)
index 0000000..00a9cee
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/magnify-clip-ltr.png differ
diff --git a/resources/src/mediawiki.skinning/images/magnify-clip-rtl.png b/resources/src/mediawiki.skinning/images/magnify-clip-rtl.png
new file mode 100644 (file)
index 0000000..ff85c07
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/magnify-clip-rtl.png differ
diff --git a/resources/src/mediawiki.skinning/images/mail.png b/resources/src/mediawiki.skinning/images/mail.png
new file mode 100644 (file)
index 0000000..5085611
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/mail.png differ
diff --git a/resources/src/mediawiki.skinning/images/mail.svg b/resources/src/mediawiki.skinning/images/mail.svg
new file mode 100644 (file)
index 0000000..5e534fe
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.47,-257.4)">
+<path style="fill:#15a5ea;" d="m38.31,261.4,4.66,4.349,4.66-4.349-0.6213-0.6213-1.243,0.6216-2.796,2.485-2.796-2.485-1.243-0.6216z"/>
+<path style="fill:#3366bb;" d="m37.47,260.4,0,8,11,0,0-8zm1,1,9,0,0,6-9,0z"/>
+</g>
+</svg>
diff --git a/resources/src/mediawiki.skinning/images/video.png b/resources/src/mediawiki.skinning/images/video.png
new file mode 100644 (file)
index 0000000..12f6545
Binary files /dev/null and b/resources/src/mediawiki.skinning/images/video.png differ
diff --git a/resources/src/mediawiki.skinning/images/video.svg b/resources/src/mediawiki.skinning/images/video.svg
new file mode 100644 (file)
index 0000000..d52d0db
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.4678,-258.39)">
+<path style="opacity:1;fill-opacity:1;fill:#15a5ea;" d="m38.96,260.4,0,0.6213,8.098,0,0-0.6213z"/>
+<path style="opacity:1;fill-opacity:1;fill:#15a5ea;" d="m38.96,268.4,8.098,0,0-0.6213-8.098,0z"/>
+<path style="opacity:1;fill-opacity:1;fill:#15a5ea;" d="m38.96,262.3,0,0.6213,1.869,0,0-0.6213zm6.229,0,0,0.6213,1.869,0,0-0.6213z"/>
+<path style="opacity:1;fill-opacity:1;fill:#15a5ea;" d="m38.96,266,0,0.6213,1.869,0,0-0.6213zm6.229,0,0,0.6213,1.869,0,0-0.6213z"/>
+<path style="opacity:1;fill-opacity:1;fill:#15a5ea;" d="m38.96,264.8,8.098,0,0-0.6213-8.098,0z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m40.83,263.9,0,1.243,4.36,0,0-1.243z"/>
+<path style="opacity:1;fill:#3366bb;" d="m40.47,260.4,0,8,5,0,0-8zm1,1,3,0,0,6-3,0z"/>
+<path style="opacity:1;fill:#3366bb;" d="m38.47,259.4,1,0,0,10-1,0z"/>
+<path style="opacity:1;fill:#3366bb;" d="m46.47,259.4,1,0,0,10-1,0z"/>
+</g>
+</svg>
diff --git a/resources/src/mediawiki.skinning/interface.css b/resources/src/mediawiki.skinning/interface.css
new file mode 100644 (file)
index 0000000..398a132
--- /dev/null
@@ -0,0 +1,68 @@
+/**
+ * MediaWiki style sheet for common core styles on interfaces
+ *
+ * Styles for the Monobook/Vector pattern of laying out common interfaces.
+ * These ids/classes are not built into the system,
+ * they are outputted by the actual MonoBook/Vector code by convention.
+ */
+
+/* Categories */
+.catlinks {
+       border: 1px solid #aaa;
+       background-color: #f9f9f9;
+       padding: 5px;
+       margin-top: 1em;
+       clear: both;
+}
+
+.usermessage {
+       background-color: #ffce7b;
+       border: 1px solid #ffa500;
+       color: black;
+       font-weight: bold;
+       margin: 2em 0 1em;
+       padding: .5em 1em;
+       vertical-align: middle;
+}
+
+#siteNotice {
+       position: relative;
+       text-align: center;
+       margin: 0;
+}
+
+#localNotice {
+       margin-bottom: 0.9em;
+}
+
+.firstHeading {
+       margin-bottom: .1em;
+       /* These two rules hack around bug 2013 (fix for more limited bug 11325).
+        * When bug 2013 is fixed properly, they should be removed. */
+       line-height: 1.2em;
+       padding-bottom: 0;
+}
+
+/* Sub-navigation */
+#siteSub {
+       display: none;
+}
+
+#jump-to-nav {
+       /* Negate #contentSub's margin and replicate it so that the jump to links don't affect the spacing */
+       margin-top: -1.4em;
+       margin-bottom: 1.4em;
+}
+
+#contentSub,
+#contentSub2 {
+       font-size: 84%;
+       line-height: 1.2em;
+       margin: 0 0 1.4em 1em;
+       color: #545454;
+       width: auto;
+}
+
+span.subpages {
+       display: block;
+}
index 7ac8154..0356fc7 100644 (file)
 }
 
 /* Special:Allpages */
-table.mw-allpages-table-form, table.mw-allpages-table-chunk {
+table.mw-allpages-table-form {
        width: 100%;
 }
+table.mw-allpages-table-form tr {
+       vertical-align: top;
+}
 .mw-allpages-nav {
        text-align: right;
        margin-bottom: 1em;
 }
-table.mw-allpages-table-form tr {
+
+ul.mw-allpages-chunk {
+       margin: 0;
+       padding: 0;
+}
+ul.mw-allpages-chunk li {
+       border-top: 1px solid #ccc;
+       display: inline-block;
+       margin: 0 1% 0 0;
+       padding: .2em 0;
        vertical-align: top;
+       width: 31%;
 }
 
 /* Special:BlockList */
diff --git a/resources/src/mediawiki.special/mediawiki.special.import.js b/resources/src/mediawiki.special/mediawiki.special.import.js
new file mode 100644 (file)
index 0000000..a9a985e
--- /dev/null
@@ -0,0 +1,35 @@
+/*!
+ * JavaScript for Special:Import
+ */
+( function ( $ ) {
+       function updateImportSubprojectList() {
+               var $projectField = $( '#mw-import-table-interwiki #interwiki' ),
+                       $subprojectField = $projectField.parent().find( '#subproject' ),
+                       $selected = $projectField.find( ':selected' ),
+                       oldValue = $subprojectField.val(),
+                       option, options;
+
+               if ( $selected.attr( 'data-subprojects' ) ) {
+                       options = $.map( $selected.attr( 'data-subprojects' ).split( ' ' ), function ( el ) {
+                               option = document.createElement( 'option' );
+                               option.appendChild( document.createTextNode( el ) );
+                               option.setAttribute( 'value', el );
+                               if ( oldValue === el ) {
+                                       option.setAttribute( 'selected', 'selected' );
+                               }
+                               return option;
+                       } );
+                       $subprojectField.show().empty().append( options );
+               } else {
+                       $subprojectField.hide();
+               }
+       }
+
+       $( function () {
+               var $projectField = $( '#mw-import-table-interwiki #interwiki' );
+               if ( $projectField.length ) {
+                       $projectField.change( updateImportSubprojectList );
+                       updateImportSubprojectList();
+               }
+       } );
+}( jQuery ) );
index afb0905..e27e34a 100644 (file)
@@ -12,7 +12,7 @@
 
 /*
  * Hide, but keep accessible for screen-readers.
- * Like .mw-jump, #jump-to-nav from skins/common/shared.css
+ * Like .mw-jump, #jump-to-nav from shared.css
  */
 .mw-navigation-hint {
        overflow: hidden;
index 60cf46a..b27fe34 100644 (file)
@@ -39,8 +39,8 @@
                                var parts = $( this ).attr( 'href' ).split( 'search=' ),
                                        lastpart = '',
                                        prefix = 'search=';
-                               if ( parts.length > 1 && parts[1].indexOf( '&' ) >= 0 ) {
-                                       lastpart = parts[1].substring( parts[1].indexOf( '&' ) );
+                               if ( parts.length > 1 && parts[1].indexOf( '&' ) !== -1 ) {
+                                       lastpart = parts[1].slice( parts[1].indexOf( '&' ) );
                                } else {
                                        prefix = '&search=';
                                }
                        } );
                } ).trigger( 'change' );
 
+               // When saving settings, use the proper request method (POST instead of GET).
+               $( '#mw-search-powersearch-remember' ).change( function () {
+                       this.form.method = this.checked ? 'post' : 'get';
+               } ).trigger( 'change' );
+
        } );
 
 }( mediaWiki, jQuery ) );
index 3c7ad52..286befc 100644 (file)
 /**
  * JavaScript for Special:Upload
  *
- * Note that additional code still lives in skins/common/upload.js
- *
  * @private
  * @class mw.special.upload
  * @singleton
  */
 ( function ( mw, $ ) {
+       var ajaxUploadDestCheck = mw.config.get( 'wgAjaxUploadDestCheck' ),
+               $license = $( '#wpLicense' ), uploadWarning, uploadLicense;
+
+       window.wgUploadWarningObj = uploadWarning = {
+               responseCache: { '': '&nbsp;' },
+               nameToCheck: '',
+               typing: false,
+               delay: 500, // ms
+               timeoutID: false,
+
+               keypress: function () {
+                       if ( !ajaxUploadDestCheck ) {
+                               return;
+                       }
+
+                       // Find file to upload
+                       if ( !$( '#wpDestFile' ).length || !$( '#wpDestFile-warning' ).length ) {
+                               return;
+                       }
+
+                       this.nameToCheck = $( '#wpDestFile' ).val();
+
+                       // Clear timer
+                       if ( this.timeoutID ) {
+                               clearTimeout( this.timeoutID );
+                       }
+                       // Check response cache
+                       if ( this.responseCache.hasOwnProperty( this.nameToCheck ) ) {
+                               this.setWarning( this.responseCache[this.nameToCheck] );
+                               return;
+                       }
+
+                       this.timeoutID = setTimeout( function () {
+                               uploadWarning.timeout();
+                       }, this.delay );
+               },
+
+               checkNow: function ( fname ) {
+                       if ( !ajaxUploadDestCheck ) {
+                               return;
+                       }
+                       if ( this.timeoutID ) {
+                               clearTimeout( this.timeoutID );
+                       }
+                       this.nameToCheck = fname;
+                       this.timeout();
+               },
+
+               timeout: function () {
+                       var $spinnerDestCheck;
+                       if ( !ajaxUploadDestCheck || this.nameToCheck === '' ) {
+                               return;
+                       }
+                       $spinnerDestCheck = $.createSpinner().insertAfter( '#wpDestFile' );
+
+                       ( new mw.Api() ).get( {
+                               action: 'query',
+                               titles: ( new mw.Title( this.nameToCheck, mw.config.get( 'wgNamespaceIds' ).file ) ).getPrefixedText(),
+                               prop: 'imageinfo',
+                               iiprop: 'uploadwarning',
+                               indexpageids: ''
+                       } ).done( function ( result ) {
+                               var resultOut = '';
+                               if ( result.query ) {
+                                       resultOut = result.query.pages[result.query.pageids[0]].imageinfo[0];
+                               }
+                               $spinnerDestCheck.remove();
+                               uploadWarning.processResult( resultOut, uploadWarning.nameToCheck );
+                       } );
+               },
+
+               processResult: function ( result, fileName ) {
+                       this.setWarning( result.html );
+                       this.responseCache[fileName] = result.html;
+               },
+
+               setWarning: function ( warning ) {
+                       $( '#wpDestFile-warning' ).html( warning );
+
+                       // Set a value in the form indicating that the warning is acknowledged and
+                       // doesn't need to be redisplayed post-upload
+                       if ( !warning ) {
+                               $( '#wpDestFileWarningAck' ).val( '' );
+                       } else {
+                               $( '#wpDestFileWarningAck' ).val( '1' );
+                       }
+
+               }
+       };
+
+       uploadLicense = {
+
+               responseCache: { '': '' },
+
+               fetchPreview: function ( license ) {
+                       var $spinnerLicense;
+                       if ( !mw.config.get( 'wgAjaxLicensePreview' ) ) {
+                               return;
+                       }
+                       if ( this.responseCache.hasOwnProperty( license ) ) {
+                               this.showPreview( this.responseCache[license] );
+                               return;
+                       }
+
+                       $spinnerLicense = $.createSpinner().insertAfter( '#wpLicense' );
+
+                       ( new mw.Api() ).get( {
+                               action: 'parse',
+                               text: '{{' + license + '}}',
+                               title: $( '#wpDestFile' ).val() || 'File:Sample.jpg',
+                               prop: 'text',
+                               pst: ''
+                       } ).done( function ( result ) {
+                               $spinnerLicense.remove();
+                               uploadLicense.processResult( result, license );
+                       } );
+               },
+
+               processResult: function ( result, license ) {
+                       this.responseCache[license] = result.parse.text['*'];
+                       this.showPreview( this.responseCache[license] );
+               },
+
+               showPreview: function ( preview ) {
+                       $( '#mw-license-preview' ).html( preview );
+               }
+
+       };
+
+       $( function () {
+               // Disable URL box if the URL copy upload source type is not selected
+               if ( !$( '#wpSourceTypeurl' ).prop( 'checked' ) ) {
+                       $( '#wpUploadFileURL' ).prop( 'disabled', true );
+               }
+
+               // AJAX wpDestFile warnings
+               if ( ajaxUploadDestCheck ) {
+                       // Insert an event handler that fetches upload warnings when wpDestFile
+                       // has been changed
+                       $( '#wpDestFile' ).change( function () {
+                               uploadWarning.checkNow( $( this ).val() );
+                       } );
+                       // Insert a row where the warnings will be displayed just below the
+                       // wpDestFile row
+                       $( '#mw-htmlform-description tbody' ).append(
+                               $( '<tr>' ).append(
+                                       $( '<td>' )
+                                               .attr( 'id', 'wpDestFile-warning' )
+                                               .attr( 'colspan', 2 )
+                               )
+                       );
+               }
+
+               if ( mw.config.get( 'wgAjaxLicensePreview' ) && $license.length ) {
+                       // License selector check
+                       $license.change( function () {
+                               // We might show a preview
+                               uploadLicense.fetchPreview( $license.val() );
+                       } );
+
+                       // License selector table row
+                       $license.closest( 'tr' ).after(
+                               $( '<tr>' ).append(
+                                       $( '<td>' ),
+                                       $( '<td>' ).attr( 'id', 'mw-license-preview' )
+                               )
+                       );
+               }
+
+               // fillDestFile setup
+               $.each( mw.config.get( 'wgUploadSourceIds' ), function ( index, sourceId ) {
+                       $( '#' + sourceId ).change( function () {
+                               var path, slash, backslash, fname;
+                               if ( !mw.config.get( 'wgUploadAutoFill' ) ) {
+                                       return;
+                               }
+                               // Remove any previously flagged errors
+                               $( '#mw-upload-permitted' ).attr( 'class', '' );
+                               $( '#mw-upload-prohibited' ).attr( 'class', '' );
+
+                               path = $( this ).val();
+                               // Find trailing part
+                               slash = path.lastIndexOf( '/' );
+                               backslash = path.lastIndexOf( '\\' );
+                               if ( slash === -1 && backslash === -1 ) {
+                                       fname = path;
+                               } else if ( slash > backslash ) {
+                                       fname = path.slice( slash + 1 );
+                               } else {
+                                       fname = path.slice( backslash + 1 );
+                               }
+
+                               // Clear the filename if it does not have a valid extension.
+                               // URLs are less likely to have a useful extension, so don't include them in the
+                               // extension check.
+                               if (
+                                       mw.config.get( 'wgStrictFileExtensions' ) &&
+                                       mw.config.get( 'wgFileExtensions' ) &&
+                                       $( this ).attr( 'id' ) !== 'wpUploadFileURL'
+                               ) {
+                                       if (
+                                               fname.lastIndexOf( '.' ) === -1 ||
+                                               $.inArray(
+                                                       fname.slice( fname.lastIndexOf( '.' ) + 1 ).toLowerCase(),
+                                                       $.map( mw.config.get( 'wgFileExtensions' ), function ( element ) {
+                                                               return element.toLowerCase();
+                                                       } )
+                                               ) === -1
+                                       ) {
+                                               // Not a valid extension
+                                               // Clear the upload and set mw-upload-permitted to error
+                                               $( this ).val( '' );
+                                               $( '#mw-upload-permitted' ).attr( 'class', 'error' );
+                                               $( '#mw-upload-prohibited' ).attr( 'class', 'error' );
+                                               // Clear wpDestFile as well
+                                               $( '#wpDestFile' ).val( '' );
+
+                                               return false;
+                                       }
+                               }
+
+                               // Replace spaces by underscores
+                               fname = fname.replace( / /g, '_' );
+                               // Capitalise first letter if needed
+                               if ( mw.config.get( 'wgCapitalizeUploads' ) ) {
+                                       fname = fname.charAt( 0 ).toUpperCase().concat( fname.slice( 1 ) );
+                               }
+
+                               // Output result
+                               if ( $( '#wpDestFile' ).length ) {
+                                       // Call decodeURIComponent function to remove possible URL-encoded characters
+                                       // from the file name (bug 30390). Especially likely with upload-form-url.
+                                       // decodeURIComponent can throw an exception if input is invalid utf-8
+                                       try {
+                                               $( '#wpDestFile' ).val( decodeURIComponent( fname ) );
+                                       } catch ( err ) {
+                                               $( '#wpDestFile' ).val( fname );
+                                       }
+                                       uploadWarning.checkNow( fname );
+                               }
+                       } );
+               } );
+       } );
+
        // Add a preview to the upload form
        $( function () {
                /**
index b66f20e..28b1446 100644 (file)
@@ -43,6 +43,7 @@ section.mw-form-header {
        border: 1px solid #c9c9c9;
        padding: 10px;
        text-align: center;
+       margin-bottom: 15px;
 }
 
 .mw-createacct-captcha-assisted {
index 2a4449e..247f814 100644 (file)
@@ -43,7 +43,7 @@
                                        '<label for="wpCaptchaWord">' + mw.message( 'createacct-captcha' ).escaped() + '</label>',
                                        '<div class="mw-createacct-captcha-container">',
                                                '<div class="mw-createacct-captcha-and-reload" />',
-                                               '<input id="wpCaptchaWord" name="wpCaptchaWord" type="text" placeholder="' +
+                                               '<input id="wpCaptchaWord" class="mw-ui-input" name="wpCaptchaWord" type="text" placeholder="' +
                                                        mw.message( 'createacct-imgcaptcha-ph' ).escaped() +
                                                        '" tabindex="' + tabIndex + '" autocapitalize="off" autocorrect="off">',
                                                        helpHtml,
index dc44c84..ee6a57c 100644 (file)
@@ -6,10 +6,6 @@
        background: url(images/glyph-people-large.png) no-repeat 50%;
        margin: 0 auto;
        padding-top: 4em;
-}
-
-#mw-createaccount-cta,
-#mw-createaccount-another {
        font-size: 0.9em;
        font-weight: normal;
        text-align: center;
@@ -17,8 +13,6 @@
 
 #mw-createaccount-join {
        margin-left: 0.75em;
-       /* Separate from background image */
-       box-shadow: 4px 4px 4px 4px rgba(255, 255, 255, 1);
        width: auto;
        display: inline-block;
 }
diff --git a/resources/src/mediawiki.ui/components/anchors.less b/resources/src/mediawiki.ui/components/anchors.less
new file mode 100644 (file)
index 0000000..e1b258d
--- /dev/null
@@ -0,0 +1,77 @@
+@import "mediawiki.mixins";
+@import "mediawiki.ui/variables";
+@import "mediawiki.ui/mixins";
+
+// Helpers
+.mw-ui-anchor( @mainColor ) {
+       // Make all context classes take the main color in IE6
+       .select-ie6-only& {
+               &:link, &:visited, &:hover, &:focus, &:active {
+                       color: @mainColor;
+               }
+       }
+
+       // Hover state
+       &:hover {
+               color: lighten( @mainColor, @colorLightenPercentage );
+       }
+       // Focus and active states
+       &:focus, &:active {
+               color: darken( @mainColor, @colorDarkenPercentage );
+               outline: none; // outline fix
+       }
+
+       color: @mainColor;
+
+       // Quiet mode is gray at first
+       &.mw-ui-quiet {
+               .mw-ui-anchor-quiet( @mainColor );
+       }
+}
+
+.mw-ui-anchor-quiet( @mainColor ) {
+       color: @colorTextLight;
+       text-decoration: none;
+
+       &:hover {
+               color: @mainColor;
+       }
+       &:focus, &:active {
+               color: darken( @mainColor, @colorDarkenPercentage );
+       }
+}
+
+/*
+Text & Anchors
+
+Allows you to give text a context as to the type of action it is indicating.
+
+Styleguide 6.
+*/
+
+/*
+Guidelines
+
+This context should only applied on elements without special behavior (DIV, SPAN, etc.), including A elements. These classes cannot be applied for styling purposes on other elements (such as form elements), except when used in combination with .mw-ui-button to alter a button context.
+
+Markup:
+<a href=# class="mw-ui-progressive {$modifiers}">Progressive</a>
+<a href=# class="mw-ui-constructive {$modifiers}">Constructive</a>
+<a href=# class="mw-ui-destructive {$modifiers}">Destructive</a>
+
+.mw-ui-quiet - Quiet until interaction.
+
+Styleguide 6.1.
+*/
+.mw-ui-progressive {
+       .mw-ui-anchor( @colorProgressive );
+}
+.mw-ui-constructive {
+       .mw-ui-anchor( @colorConstructive );
+}
+.mw-ui-destructive {
+       .mw-ui-anchor( @colorDestructive );
+}
+.mw-ui-quiet {
+       .mw-ui-anchor-quiet( @colorTextLight );
+}
diff --git a/resources/src/mediawiki.ui/components/buttons.less b/resources/src/mediawiki.ui/components/buttons.less
new file mode 100644 (file)
index 0000000..7142d4d
--- /dev/null
@@ -0,0 +1,230 @@
+@import "mediawiki.mixins";
+@import "mediawiki.ui/variables";
+@import "mediawiki.ui/mixins";
+
+// Buttons
+//
+// All buttons start with mw-ui-button class, modified by other classes.
+// It can be any element.  Due to a lack of a CSS reset, the exact styling of
+// the button depends on what type of element is used.
+// There are two kinds of buttons, the default is a "Call to Action" with an obvious border
+// and there is a quiet kind without a border.
+//
+// Styleguide 2.
+
+@buttonBorderRadius: 3px;
+@transitionDuration: .1s;
+@transitionFunction: ease-in-out;
+
+// Neutral button styling
+//
+// Markup:
+// <button class="mw-ui-button">.mw-ui-button</button>
+// <button class="mw-ui-button" disabled>.mw-ui-button</button>
+//
+// Styleguide 2.1.
+.mw-ui-button {
+       // Inherit the font rather than apply user agent stylesheet (bug 70072)
+       font-family: inherit;
+       font-size: 1em;
+       // Container layout
+       display: inline-block;
+       padding: .5em 1em;
+       margin: 0;
+       .box-sizing(border-box);
+
+       // Disable weird iOS styling
+       -webkit-appearance: none;
+
+       // IE6/IE7 hack
+       // http://stackoverflow.com/a/5838575/365238
+       *display: inline;
+       zoom: 1;
+
+       // Container styling
+       .button-colors(#FFF);
+       border-radius: @buttonBorderRadius;
+
+       // Ensure that buttons and inputs are nicely aligned when they have differing heights
+       vertical-align: middle;
+
+       // Content styling
+       text-align: center;
+       font-weight: bold;
+
+       // Interaction styling
+       cursor: pointer;
+
+       &:disabled {
+               text-shadow: none;
+               cursor: default;
+       }
+
+       .transition(background @transitionDuration @transitionFunction, color @transitionDuration @transitionFunction, box-shadow @transitionDuration @transitionFunction;);
+
+       // Styling for specific button types
+       // -----------------------------------------
+
+       // Big buttons
+       //
+       // Not all buttons are equal. You can emphasise certain actions over others
+       // using the mw-ui-big class.
+       //
+       // Markup:
+       // <button class="mw-ui-button mw-ui-big">.mw-ui-button</button>
+       // <button class="mw-ui-button mw-ui-progressive mw-ui-big">.mw-ui-progressive</button>
+       // <button class="mw-ui-button mw-ui-constructive mw-ui-big">.mw-ui-constructive</button>
+       // <button class="mw-ui-button mw-ui-destructive mw-ui-big">.mw-ui-destructive</button>
+       //
+       // Styleguide 2.1.6.
+       &.mw-ui-big {
+               font-size: 1.3em;
+       }
+
+       // Block buttons
+       //
+       // Some buttons might need to be stacked.
+       //
+       // Markup:
+       // <button class="mw-ui-button mw-ui-block">.mw-ui-button</button>
+       // <button class="mw-ui-button mw-ui-progressive mw-ui-block">.mw-ui-progressive</button>
+       // <button class="mw-ui-button mw-ui-constructive mw-ui-block">.mw-ui-constructive</button>
+       // <button class="mw-ui-button mw-ui-destructive mw-ui-block">.mw-ui-destructive</button>
+       //
+       // Styleguide 2.1.5.
+       &.mw-ui-block {
+               display: block;
+               width: 100%;
+       }
+
+       // Progressive buttons
+       //
+       // Use progressive buttons for actions which lead to a next step in the process.
+       // .mw-ui-primary is deprecated, kept for compatibility.
+       //
+       // Markup:
+       // <button class="mw-ui-button mw-ui-progressive">.mw-ui-progressive</button>
+       // <button class="mw-ui-button mw-ui-progressive" disabled>.mw-ui-progressive</button>
+       //
+       // Styleguide 2.1.1.
+       &.mw-ui-progressive,
+       &.mw-ui-primary {
+               .button-colors(@colorProgressive);
+
+               &.mw-ui-quiet {
+                       .button-colors-quiet(@colorProgressive);
+               }
+       }
+
+       // Constructive buttons
+       //
+       // Use constructive buttons for actions which result in a final action in the process that results
+       // in a change of state.
+       // e.g. save changes button
+       //
+       // Markup:
+       // <button class="mw-ui-button mw-ui-constructive">.mw-ui-constructive</button>
+       // <button class="mw-ui-button mw-ui-constructive" disabled>.mw-ui-constructive</button>
+       //
+       // Styleguide 2.1.2.
+       &.mw-ui-constructive {
+               .button-colors(@colorConstructive);
+
+               &.mw-ui-quiet {
+                       .button-colors-quiet(@colorConstructive);
+               }
+       }
+
+       // Destructive buttons
+       //
+       // Use destructive buttons for actions which result in the destruction of data.
+       // e.g. deleting a page.
+       // This should not be used for cancel buttons.
+       //
+       // Markup:
+       // <button class="mw-ui-button mw-ui-destructive">.mw-ui-destructive</button>
+       // <button class="mw-ui-button mw-ui-destructive" disabled>.mw-ui-destructive</button>
+       //
+       // Styleguide 2.1.3.
+       &.mw-ui-destructive {
+               .button-colors(@colorDestructive);
+
+               &.mw-ui-quiet {
+                       .button-colors-quiet(@colorDestructive);
+               }
+       }
+
+       // Quiet buttons
+       //
+       // Use quiet buttons when they are less important and alongisde other progressive/destructive/progressive buttons.
+       //
+       // Markup:
+       // <button class="mw-ui-button mw-ui-quiet">.mw-ui-button</button>
+       // <button class="mw-ui-button mw-ui-constructive mw-ui-quiet">.mw-ui-constructive</button>
+       // <button class="mw-ui-button mw-ui-constructive mw-ui-quiet" disabled>.mw-ui-constructive</button>
+       // <button class="mw-ui-button mw-ui-destructive mw-ui-quiet">.mw-ui-destructive</button>
+       // <button class="mw-ui-button mw-ui-destructive mw-ui-quiet" disabled>.mw-ui-destructive</button>
+       // <button class="mw-ui-button mw-ui-progressive mw-ui-quiet">.mw-ui-progressive</button>
+       // <button class="mw-ui-button mw-ui-progressive mw-ui-quiet" disabled>.mw-ui-progressive</button>
+       //
+       // Styleguide 2.1.4.
+       &.mw-ui-quiet {
+               background: transparent;
+               border: none;
+               text-shadow: none;
+               .button-colors-quiet(@colorButtonText);
+
+               &:hover,
+               &:focus {
+                       box-shadow: none;
+               }
+
+               &:active,
+               &:disabled {
+                       background: transparent;
+               }
+       }
+}
+
+a.mw-ui-button {
+       text-decoration: none;
+
+       // This overrides an underline declaration on a:hover and a:focus in
+       // commonElements.css, which the class alone isn't specific enough to do.
+       &:hover,
+       &:focus {
+               text-decoration: none;
+       }
+}
+
+// Button groups
+//
+// Group of buttons. Make sure you clear the floating after using a mw-ui-button-group.
+//
+// Markup:
+// <div class="mw-ui-button-group">
+//   <div class="mw-ui-button">A</div>
+//   <div class="mw-ui-button">B</div>
+//   <div class="mw-ui-button">C</div>
+//   <div class="mw-ui-button">D</div>
+// </div><div style="clear:both"></div>
+//
+// Styleguide 2.2.
+.mw-ui-button-group > * {
+       border-radius: 0;
+       float: left;
+
+       &:first-child {
+               border-top-left-radius: @buttonBorderRadius;
+               border-bottom-left-radius: @buttonBorderRadius;
+       }
+
+       &:not(:first-child) {
+               border-left: none;
+       }
+
+       &:last-child{
+               border-top-right-radius: @buttonBorderRadius;
+               border-bottom-right-radius: @buttonBorderRadius;
+       }
+}
diff --git a/resources/src/mediawiki.ui/components/checkbox.less b/resources/src/mediawiki.ui/components/checkbox.less
new file mode 100644 (file)
index 0000000..6d6fdde
--- /dev/null
@@ -0,0 +1,94 @@
+@import "mediawiki.mixins";
+
+// Checkbox
+//
+// Styling checkboxes in a way that works cross browser is a tricky problem to solve.
+// In MediaWiki UI put a checkbox and label inside a mw-ui-checkbox div.
+// This renders in all browsers except IE6-8 which do not support the :checked selector;
+// these are kept backwards-compatible using the :not(#noop) selector.
+// You should give the checkbox and label matching "id" and "for" attributes, respectively.
+//
+// Markup:
+// <div class="mw-ui-checkbox">
+//   <input type="checkbox" id="kss-example-5"><label for="kss-example-5">Standard checkbox</label>
+// </div>
+// <div class="mw-ui-checkbox">
+//   <input type="checkbox" id="kss-example-5-2" disabled><label for="kss-example-5-2">Disabled checkbox</label>
+// </div>
+//
+// Styleguide 5.
+.mw-ui-checkbox {
+       display: inline-block;
+       vertical-align: middle;
+}
+
+@checkboxSize: 24px;
+
+// We use the not selector to cancel out styling on IE 8 and below
+.mw-ui-checkbox:not(#noop) {
+       // Position relatively so we can make use of absolute pseudo elements
+       position: relative;
+       line-height: @checkboxSize;
+
+       * {
+               vertical-align: middle;
+       }
+
+       input[type="checkbox"] {
+               // we hide the input element as instead we will style the label that follows
+               // we use opacity so that VoiceOver software can still identify it
+               opacity: 0;
+               // ensure the invisible checkbox takes up the required width
+               width: @checkboxSize;
+               height: @checkboxSize;
+
+               // the pseudo before element of the label after the checkbox now looks like a checkbox
+               & + label {
+                       &::before {
+                                               content: '';
+                                               position: absolute;
+                                               left: 0;
+                                               display: inline-block;
+                                               border-radius: 2px;
+                                               margin-right: 18px;
+                                               width: @checkboxSize;
+                                               height: @checkboxSize;
+                                               background-color: #fff;
+                                               cursor: pointer;
+                                               border: 1px solid grey;
+                                       }
+               }
+
+               // when the input is checked, style the label pseudo before element that followed as a checked checkbox
+               &:checked {
+                       + label {
+                               &::before {
+                                       .background-image-svg('images/checked.svg', 'images/checked.png');
+                                       background-repeat: no-repeat;
+                                       background-position: center top;
+                               }
+                       }
+               }
+
+               @focusBottomBorderSize: 3px;
+               &:active,
+               &:focus {
+                       + label {
+                               &::after {
+                                       content: '';
+                                       position: absolute;
+                                       width: @checkboxSize;
+                                       height: @checkboxSize - @focusBottomBorderSize + 1; // offset by bottom border
+                                       // offset from the checkbox by 1px to account for left border
+                                       left: 1px;
+                                       border-bottom: solid @focusBottomBorderSize lightgrey;
+                               }
+                       }
+               }
+
+               // disabled checked boxes have a gray background
+               &:disabled + label::before {
+                       background-color: lightgrey;
+               }
+       }
+}
diff --git a/resources/src/mediawiki.ui/components/default/buttons.less b/resources/src/mediawiki.ui/components/default/buttons.less
deleted file mode 100644 (file)
index dce4cd0..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-@import "mediawiki.mixins";
-@import "../../settings/typography";
-@import "../../mixins/effects";
-@import "../../mixins/utilities";
-
-// Buttons
-//
-// All buttons start with mw-ui-button class, modified by other classes.
-// It can be any element.  Due to a lack of a CSS reset, the exact styling of
-// the button depends on what type of element is used.
-// There are two kinds of buttons, the default is a "Call to Action" with an obvious border
-// and there is a quiet kind without a border.
-//
-// Styleguide 2.
-
-@buttonBorderRadius: 3px;
-@transitionDuration: .1s;
-@transitionFunction: ease-in-out;
-
-// Neutral button styling
-//
-// Markup:
-// <button class="mw-ui-button">.mw-ui-button</button>
-// <button class="mw-ui-button" disabled>.mw-ui-button</button>
-//
-// Styleguide 2.1.
-.mw-ui-button {
-       // Container layout
-       display: inline-block;
-       padding: .5em 1em;
-       margin: 0;
-       .box-sizing(border-box);
-
-       // Disable weird iOS styling
-       -webkit-appearance: none;
-
-       // IE6/IE7 hack
-       // http://stackoverflow.com/a/5838575/365238
-       *display: inline;
-       zoom: 1;
-
-       // Container styling
-       .button-colors(@colorWhite);
-       border-radius: @buttonBorderRadius;
-
-       // Ensure that buttons and inputs are nicely aligned when they have differing heights
-       vertical-align: middle;
-
-       // Content styling
-       text-align: center;
-       font-weight: bold;
-
-       // Interaction styling
-       cursor: pointer;
-
-       &:disabled {
-               text-shadow: none;
-               cursor: default;
-       }
-
-       .transition(background @transitionDuration @transitionFunction, color @transitionDuration @transitionFunction, box-shadow @transitionDuration @transitionFunction;);
-
-       // Styling for specific button types
-       // -----------------------------------------
-
-       // Big buttons
-       //
-       // Not all buttons are equal. You can emphasise certain actions over others
-       // using the mw-ui-big class.
-       //
-       // Markup:
-       // <button class="mw-ui-button mw-ui-big">.mw-ui-button</button>
-       // <button class="mw-ui-button mw-ui-progressive mw-ui-big">.mw-ui-progressive</button>
-       // <button class="mw-ui-button mw-ui-constructive mw-ui-big">.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-destructive mw-ui-big">.mw-ui-destructive</button>
-       //
-       // Styleguide 2.1.6.
-       &.mw-ui-big {
-               font-size: @baseFontSize * 1.3;
-       }
-
-       // Block buttons
-       //
-       // Some buttons might need to be stacked.
-       //
-       // Markup:
-       // <button class="mw-ui-button mw-ui-block">.mw-ui-button</button>
-       // <button class="mw-ui-button mw-ui-progressive mw-ui-block">.mw-ui-progressive</button>
-       // <button class="mw-ui-button mw-ui-constructive mw-ui-block">.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-destructive mw-ui-block">.mw-ui-destructive</button>
-       //
-       // Styleguide 2.1.5.
-       &.mw-ui-block {
-               display: block;
-               width: 100%;
-       }
-
-       // Progressive buttons
-       //
-       // Use progressive buttons for actions which lead to a next step in the process.
-       // .mw-ui-primary is deprecated, kept for compatibility.
-       //
-       // Markup:
-       // <button class="mw-ui-button mw-ui-progressive">.mw-ui-progressive</button>
-       // <button class="mw-ui-button mw-ui-progressive" disabled>.mw-ui-progressive</button>
-       //
-       // Styleguide 2.1.1.
-       &.mw-ui-progressive,
-       &.mw-ui-primary {
-               .button-colors(@colorProgressive);
-
-               &.mw-ui-quiet {
-                       .button-colors-quiet(@colorProgressive);
-               }
-       }
-
-       // Constructive buttons
-       //
-       // Use constructive buttons for actions which result in a final action in the process that results
-       // in a change of state.
-       // e.g. save changes button
-       //
-       // Markup:
-       // <button class="mw-ui-button mw-ui-constructive">.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-constructive" disabled>.mw-ui-constructive</button>
-       //
-       // Styleguide 2.1.2.
-       &.mw-ui-constructive {
-               .button-colors(@colorConstructive);
-
-               &.mw-ui-quiet {
-                       .button-colors-quiet(@colorConstructive);
-               }
-       }
-
-       // Destructive buttons
-       //
-       // Use destructive buttons for actions which result in the destruction of data.
-       // e.g. deleting a page.
-       // This should not be used for cancel buttons.
-       //
-       // Markup:
-       // <button class="mw-ui-button mw-ui-destructive">.mw-ui-destructive</button>
-       // <button class="mw-ui-button mw-ui-destructive" disabled>.mw-ui-destructive</button>
-       //
-       // Styleguide 2.1.3.
-       &.mw-ui-destructive {
-               .button-colors(@colorDestructive);
-
-               &.mw-ui-quiet {
-                       .button-colors-quiet(@colorDestructive);
-               }
-       }
-
-       // Quiet buttons
-       //
-       // Use quiet buttons when they are less important and alongisde other progressive/destructive/progressive buttons.
-       //
-       // Markup:
-       // <button class="mw-ui-button mw-ui-quiet">.mw-ui-button</button>
-       // <button class="mw-ui-button mw-ui-constructive mw-ui-quiet">.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-constructive mw-ui-quiet" disabled>.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-destructive mw-ui-quiet">.mw-ui-destructive</button>
-       // <button class="mw-ui-button mw-ui-destructive mw-ui-quiet" disabled>.mw-ui-destructive</button>
-       // <button class="mw-ui-button mw-ui-progressive mw-ui-quiet">.mw-ui-progressive</button>
-       // <button class="mw-ui-button mw-ui-progressive mw-ui-quiet" disabled>.mw-ui-progressive</button>
-       //
-       // Styleguide 2.1.4.
-       &.mw-ui-quiet {
-               background: transparent;
-               border: none;
-               text-shadow: none;
-               .button-colors-quiet(@colorGrayDark);
-
-               &:hover,
-               &:focus {
-                       box-shadow: none;
-               }
-
-               &:active,
-               &:disabled {
-                       background: transparent;
-               }
-       }
-}
-
-a.mw-ui-button {
-       text-decoration: none;
-
-       // This overrides an underline declaration on a:hover and a:focus in
-       // commonElements.css, which the class alone isn't specific enough to do.
-       &:hover,
-       &:focus {
-               text-decoration: none;
-       }
-}
-
-// Button groups
-//
-// Group of buttons. Make sure you clear the floating after using a mw-ui-button-group.
-//
-// Markup:
-// <div class="mw-ui-button-group">
-//   <div class="mw-ui-button">A</div>
-//   <div class="mw-ui-button">B</div>
-//   <div class="mw-ui-button">C</div>
-//   <div class="mw-ui-button">D</div>
-// </div><div style="clear:both"></div>
-//
-// Styleguide 2.2.
-.mw-ui-button-group > * {
-       border-radius: 0;
-       float: left;
-
-       &:first-child {
-               border-top-left-radius: @buttonBorderRadius;
-               border-bottom-left-radius: @buttonBorderRadius;
-       }
-
-       &:not(:first-child) {
-               border-left: none;
-       }
-
-       &:last-child{
-               border-top-right-radius: @buttonBorderRadius;
-               border-bottom-right-radius: @buttonBorderRadius;
-       }
-}
diff --git a/resources/src/mediawiki.ui/components/default/forms.less b/resources/src/mediawiki.ui/components/default/forms.less
deleted file mode 100644 (file)
index 6c40c26..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-// Form elements and layouts
-
-@import "mediawiki.mixins";
-@import "../../mixins/utilities";
-@import "../../mixins/forms";
-
-// --------------------------------------------------------------------------
-// Layouts
-// --------------------------------------------------------------------------
-
-// The FancyCaptcha image CAPTCHA used on WMF wikis drives the width of the
-// 'VForm' design, the form can't be narrower than this.
-@captchaContainerWidth: 290px;
-@defaultFormWidth: @captchaContainerWidth;
-
-// Forms
-//
-// Styleguide 3.
-
-// VForm
-//
-// Style a compact vertical stacked form ("VForm") and the elements in divs
-// within it. See button section on guidance of how and when to use mw-ui-constructive.
-//
-// Markup:
-// <form class="mw-ui-vform">
-//   <div class="mw-ui-vform-field">This is a form example.</div>
-//   <div class="mw-ui-vform-field">
-//     <label>Username </label>
-//     <input value="input">
-//   </div>
-//   <div class="mw-ui-vform-field">
-//     <button class="mw-ui-button mw-ui-constructive">Button in vform</button>
-//   </div>
-// </form>
-//
-// Styleguide 3.1.
-.mw-ui-vform {
-       .box-sizing(border-box);
-
-       width: @defaultFormWidth;
-
-       // MW currently doesn't use the type attribute everywhere on inputs.
-       input,
-       select,
-       .mw-ui-button {
-               display: block;
-               .box-sizing(border-box);
-               margin: 0;
-               width: 100%;
-       }
-
-       // We exclude buttons because they'll generally use mw-ui-button.
-       // Otherwise, we'll unintentionally override that.
-       input:not([type=button]):not([type=submit]):not([type=file]) {
-               .agora-field-styling(); // mixins/forms.less
-       }
-
-       // Give dropdown lists the same spacing as input fields for consistency.
-       // Values taken from .agora-field-styling() in mixins/form.less
-       select {
-               padding: 0.35em 0.5em 0.35em 0.5em;
-               vertical-align: middle;
-       }
-
-       label {
-               display: block;
-               .box-sizing(border-box);
-               .agora-label-styling();
-               width: auto;
-               margin: 0 0 0.2em;
-               padding: 0;
-       }
-
-       // Override input styling just for checkboxes and radio inputs.
-       input[type="checkbox"],
-       input[type="radio"] {
-               display: inline;
-               .box-sizing(content-box);
-               width: auto;
-       }
-
-
-       // Styles for information boxes
-       //
-       // Regular HTMLForm uses .error class, some special pages like
-       // SpecialUserlogin (login and create account) use .errorbox.
-       //
-       // Markup:
-       // <form class="mw-ui-vform">
-       //   <div class="errorbox">An error occurred</div>
-       //   <div class="warningbox">A warning to be noted</div>
-       //   <div class="successbox">Action successful!</div>
-       //   <div class="error">A different kind of error</div>
-       //   <div class="error">
-       //     <ul><li>There are problems with some of your input.</li></ul>
-       //   </div>
-       //   <div class="mw-ui-vform-field">
-       //     <input type="text" value="input" class="mw-ui-input">
-       //   </div>
-       //   <div class="mw-ui-vform-field">
-       //     <select>
-       //       <option value="1">Option 1</option>
-       //       <option value="2">Option 2</option>
-       //     </select>
-       //     <span class="error">The value you specified is not a valid option.</span>
-       //   </div>
-       //   <div class="mw-ui-vform-field">
-       //     <button class="mw-ui-button">Button in vform</button>
-       //   </div>
-       // </form>
-       //
-       // Styleguide 3.1.
-       .error,
-       .errorbox,
-       .warningbox,
-       .successbox {
-               .box-sizing(border-box);
-               font-size: 0.9em;
-               margin: 0 0 1em 0;
-               padding: 0.5em;
-               word-wrap: break-word;
-       }
-
-       // Colours taken from those for .errorbox in skins/common/shared.css
-       .error {
-               color: #cc0000;
-               border: 1px solid #fac5c5;
-               background-color: #fae3e3;
-               text-shadow: 0 1px #fae3e3;
-       }
-
-       // This specifies styling for individual field validation error messages.
-       // Show them below the fields to prevent line break glitches, and leave
-       // some space between the field and the error message box.
-       .mw-ui-vform-div .error, /* for backwards-compatibility, remove before 1.24 */
-       .mw-ui-vform-field .error {
-               display: block;
-               margin-top: 5px;
-       }
-
-}
-
-// --------------------------------------------------------------------------
-// Elements
-// --------------------------------------------------------------------------
-
-// A wrapper for a single form field: the <input> / <select> / <button> element,
-// help text, labels, associated error/warning/success messages, and so on.
-// Elements with this class are generated by HTMLFormField in core MediaWiki.
-//
-// (We use a broad definition of 'field' here: a purely textual information
-// block is also a "field".)
-.mw-ui-vform-div, /* for backwards-compatibility, remove before 1.24 */
-.mw-ui-vform-field {
-       display: block;
-       margin: 0 0 15px;
-       padding: 0;
-       width: 100%;
-}
-
-// Apply mw-ui-input to individual input fields to style them.
-// You generally don't need to use this class if <input> is within an Agora
-// form container such as mw-ui-vform
-.mw-ui-input {
-       .agora-field-styling(); // mixins/forms.less
-}
-
-// Apply mw-ui-label to individual elements to style them.
-// You generally don't need to use this class if <label> is within an Agora
-// form container such as mw-ui-vform
-.mw-ui-label {
-       .agora-label-styling(); // mixins/forms.less
-}
-
-// Nesting an input checkbox or radio button inside a label with this class
-// improves alignment, e.g.
-//     <label class="mw-ui-checkbox-label">
-//             <input type="checkbox">The label text
-//     </label>
-.mw-ui-checkbox-label, .mw-ui-radio-label {
-       .agora-inline-label-styling();
-}
diff --git a/resources/src/mediawiki.ui/components/forms.less b/resources/src/mediawiki.ui/components/forms.less
new file mode 100644 (file)
index 0000000..592a309
--- /dev/null
@@ -0,0 +1,166 @@
+// Form elements and layouts
+
+@import "mediawiki.mixins";
+@import "mediawiki.ui/variables";
+@import "mediawiki.ui/mixins";
+
+// --------------------------------------------------------------------------
+// Layouts
+// --------------------------------------------------------------------------
+
+// The FancyCaptcha image CAPTCHA used on WMF wikis drives the width of the
+// 'VForm' design, the form can't be narrower than this.
+@captchaContainerWidth: 290px;
+@defaultFormWidth: @captchaContainerWidth;
+
+// Forms
+//
+// Styleguide 3.
+
+// VForm
+//
+// Style a compact vertical stacked form ("VForm") and the elements in divs
+// within it. See button and inputs section on guidance of how and when to use them.
+//
+// Markup:
+// <form class="mw-ui-vform">
+//   <div class="mw-ui-vform-field">This is a form example.</div>
+//   <div class="mw-ui-vform-field">
+//     <label>Username </label>
+//     <input class="mw-ui-input" value="input">
+//   </div>
+//   <div class="mw-ui-vform-field">
+//     <button class="mw-ui-button mw-ui-constructive">Button in vform</button>
+//   </div>
+// </form>
+//
+// Styleguide 3.1.
+.mw-ui-vform {
+       .box-sizing(border-box);
+
+       width: @defaultFormWidth;
+
+       // MW currently doesn't use the type attribute everywhere on inputs.
+       select,
+       .mw-ui-button {
+               display: block;
+               .box-sizing(border-box);
+               margin: 0;
+               width: 100%;
+       }
+
+       // Give dropdown lists the same spacing as input fields for consistency.
+       // Values taken from .agora-field-styling() in mixins/form.less
+       select {
+               padding: 0.35em 0.5em 0.35em 0.5em;
+               vertical-align: middle;
+       }
+
+       > label {
+               display: block;
+               .box-sizing(border-box);
+               .agora-label-styling();
+               width: auto;
+               margin: 0 0 0.2em;
+               padding: 0;
+       }
+
+       // Override input styling just for checkboxes and radio inputs.
+       input[type="radio"] {
+               display: inline;
+               .box-sizing(content-box);
+               width: auto;
+       }
+
+
+       // Styles for information boxes
+       //
+       // Regular HTMLForm uses .error class, some special pages like
+       // SpecialUserlogin (login and create account) use .errorbox.
+       //
+       // Markup:
+       // <form class="mw-ui-vform">
+       //   <div class="errorbox">An error occurred</div>
+       //   <div class="warningbox">A warning to be noted</div>
+       //   <div class="successbox">Action successful!</div>
+       //   <div class="error">A different kind of error</div>
+       //   <div class="error">
+       //     <ul><li>There are problems with some of your input.</li></ul>
+       //   </div>
+       //   <div class="mw-ui-vform-field">
+       //     <input type="text" value="input" class="mw-ui-input">
+       //   </div>
+       //   <div class="mw-ui-vform-field">
+       //     <select>
+       //       <option value="1">Option 1</option>
+       //       <option value="2">Option 2</option>
+       //     </select>
+       //     <span class="error">The value you specified is not a valid option.</span>
+       //   </div>
+       //   <div class="mw-ui-vform-field">
+       //     <button class="mw-ui-button">Button in vform</button>
+       //   </div>
+       // </form>
+       //
+       // Styleguide 3.2.
+       .error,
+       .errorbox,
+       .warningbox,
+       .successbox {
+               .box-sizing(border-box);
+               font-size: 0.9em;
+               margin: 0 0 1em 0;
+               padding: 0.5em;
+               word-wrap: break-word;
+       }
+
+       // Colours taken from those for .errorbox in shared.css
+       .error {
+               color: #cc0000;
+               border: 1px solid #fac5c5;
+               background-color: #fae3e3;
+               text-shadow: 0 1px #fae3e3;
+       }
+
+       // This specifies styling for individual field validation error messages.
+       // Show them below the fields to prevent line break glitches, and leave
+       // some space between the field and the error message box.
+       .mw-ui-vform-field .error {
+               display: block;
+               margin-top: 5px;
+       }
+
+}
+
+// --------------------------------------------------------------------------
+// Elements
+// --------------------------------------------------------------------------
+
+// A wrapper for a single form field: the <input> / <select> / <button> element,
+// help text, labels, associated error/warning/success messages, and so on.
+// Elements with this class are generated by HTMLFormField in core MediaWiki.
+//
+// (We use a broad definition of 'field' here: a purely textual information
+// block is also a "field".)
+.mw-ui-vform-field {
+       display: block;
+       margin: 0 0 15px;
+       padding: 0;
+       width: 100%;
+}
+
+// Apply mw-ui-label to individual elements to style them.
+// You generally don't need to use this class if <label> is within an Agora
+// form container such as mw-ui-vform
+.mw-ui-label {
+       .agora-label-styling(); // mixins/forms.less
+}
+
+// Nesting an input  inside a label with this class
+// improves alignment, e.g.
+//     <label class="mw-ui-radio-label">
+//             <input type="radio">The label text
+//     </label>
+.mw-ui-radio-label {
+       .agora-inline-label-styling();
+}
diff --git a/resources/src/mediawiki.ui/components/images/checked.png b/resources/src/mediawiki.ui/components/images/checked.png
new file mode 100644 (file)
index 0000000..ce4e6b9
Binary files /dev/null and b/resources/src/mediawiki.ui/components/images/checked.png differ
diff --git a/resources/src/mediawiki.ui/components/images/checked.svg b/resources/src/mediawiki.ui/components/images/checked.svg
new file mode 100644 (file)
index 0000000..aea69db
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M4 12l5 5 11-12" stroke="#00B78C" stroke-width="3" fill="none"/></svg>
\ No newline at end of file
diff --git a/resources/src/mediawiki.ui/components/inputs.less b/resources/src/mediawiki.ui/components/inputs.less
new file mode 100644 (file)
index 0000000..7108fae
--- /dev/null
@@ -0,0 +1,124 @@
+// Inputs
+
+@import "mediawiki.mixins";
+@import "mediawiki.ui/variables";
+@import "mediawiki.ui/mixins";
+
+// Placeholder text styling helper
+.field-placeholder-styling() {
+       font-style: italic;
+       font-weight: normal;
+}
+// Inputs
+//
+// Apply the mw-ui-input class to input and textarea fields.
+//
+// Styleguide 1.
+
+// mw-ui-input
+//
+// Style an input using MediaWiki UI.
+// Currently in draft status and subject to change.
+// When focused a progressive highlight appears to the left of the field.
+//
+// Markup:
+// <input class="mw-ui-input" placeholder="Enter your name">
+// <textarea class="mw-ui-input">Text here</textarea>
+//
+// Styleguide 1.1.
+.mw-ui-input {
+       // turn off default input styling for input[type="search"] fields
+       -webkit-appearance: none;
+       border: 1px solid @colorFieldBorder;
+       .box-sizing(border-box);
+       width: 100%;
+       padding: .3em .3em .3em .6em;
+       display: block;
+       vertical-align: middle;
+       // Override user agent stylesheet properties. Instead use parent element.
+       color: inherit;
+       font-family: inherit;
+       font-size: inherit;
+       line-height: inherit;
+       .transition(~"border linear .2s, box-shadow linear .2s");
+
+       // Placeholder text styling must be set individually for each browser @winter
+       &::-webkit-input-placeholder { // webkit
+               .field-placeholder-styling;
+       }
+       &::-moz-placeholder { // FF 4-18
+               .field-placeholder-styling;
+       }
+       &:-moz-placeholder { // FF >= 19
+               .field-placeholder-styling;
+       }
+       &:-ms-input-placeholder { // IE >= 10
+               .field-placeholder-styling;
+       }
+
+       // Remove red outline from inputs which have required field and invalid content.
+       // This is a Firefox only issue
+       // See https://developer.mozilla.org/en-US/docs/Web/CSS/:invalid
+       // This should be above :focus so focus behaviour takes preference
+       &:invalid {
+               box-shadow: none;
+       }
+
+       &:focus {
+               box-shadow: inset .45em 0 0 @colorProgressive;
+               border-color: @colorGrayDark;
+               // Remove focus glow on input[type="search"]
+               outline: 0;
+       }
+}
+
+textarea.mw-ui-input {
+       min-height: 8em;
+}
+
+// mw-ui-input-inline
+//
+// Use mw-ui-input-inline with mw-ui-input in cases where you want a button to line up with the input.
+//
+// Markup:
+// <input class="mw-ui-input mw-ui-input-inline">
+// <button class="mw-ui-button mw-ui-constructive">go</button>
+//
+// Styleguide 1.2.
+.mw-ui-input-inline {
+       display: inline-block;
+       width: auto;
+}
+
+// mw-ui-input-large
+//
+// Use mw-ui-input-large with mw-ui-input in cases where there are multiple inputs on a screen and you
+// want to draw attention to one instance. For example, replying with a subject line and more text.
+// Currently in draft status and subject to change. When used on an input field, the text is styled
+// in a large font. When used alongside another mw-ui-input large they are pushed together to form one
+// contiguous block.
+//
+// Markup:
+// <input value="input" class="mw-ui-input mw-ui-input-large" value="input" placeholder="Enter subject">
+// <textarea class="mw-ui-input mw-ui-input-large" placeholder="Provide additional details"></textarea>
+//
+// Styleguide 1.3.
+.mw-ui-input-large {
+       margin-top: 0;
+       margin-bottom: 0;
+
+       // When two large inputs are together, we make them flush by hiding one of the borders
+       & + .mw-ui-input-large {
+               margin-top: -1px;
+       }
+       // When focusing, make the input relative to raise it above any attached inputs to unhide its borders
+       &:focus {
+               position: relative;
+       }
+}
+
+input.mw-ui-input-large {
+       font-size: 1.75em;
+       font-weight: bold;
+       line-height: 1.25em;
+}
index 9aea429..0bbb440 100644 (file)
@@ -1,19 +1,47 @@
-// Generic helper classes that could be used in many elements/layouts
-
-// --------------------------------------------------------------------------
-// Positioning
-// --------------------------------------------------------------------------
-
-@import "../mixins/utilities";
+// Utilities
+//
+// Other things which effect the behaviour of components
 
+// Flush left
+//
+// Used when you want to push an element to the left of its containing element
+//
+// Markup:
+// <div class="mw-ui-vform-field">
+//   <label>Username <a href="#" class="mw-ui-flush-left">?</a></label>
+//   <input>
+// </div>
 .mw-ui-flush-left {
-       .agora-flush-left();
+       float: left;
+       margin-left: 0;
+       padding-left: 0;
 }
 
+// Flush right
+//
+// Used when you want to push an element to the right of its containing element
+//
+// Markup:
+// <div class="mw-ui-vform-field">
+//   <label>Username <a href="#" class="mw-ui-flush-right">?</a></label>
+//   <input>
+// </div>
 .mw-ui-flush-right {
-       .agora-flush-right();
+       float: right;
+       padding-right: 0;
+       margin-right: 0;
 }
 
+// Center block
+//
+// Centers the element in its containing element
+//
+// Markup:
+// <div>
+//   <button class="mw-ui-center-block">click me</button>
+// </div>
 .mw-ui-center-block {
-       .agora-center-block();
+       display: block;
+       margin-left: auto;
+       margin-right: auto;
 }
diff --git a/resources/src/mediawiki.ui/components/vector/buttons.less b/resources/src/mediawiki.ui/components/vector/buttons.less
deleted file mode 100644 (file)
index 1536338..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-@import "../default/buttons"; // Layer Vector on top of the default settings.
-@import "../../mixins/type";
-
-.mw-ui-button {
-       .vector-type();
-}
diff --git a/resources/src/mediawiki.ui/components/vector/containers.less b/resources/src/mediawiki.ui/components/vector/containers.less
deleted file mode 100644 (file)
index 1e9ec05..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// No default settings for containers yet.
-@import "../../mixins/type";
-
-.mw-ui-container {
-       .vector-type();
-}
diff --git a/resources/src/mediawiki.ui/components/vector/forms.less b/resources/src/mediawiki.ui/components/vector/forms.less
deleted file mode 100644 (file)
index 2bbd8f0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-@import "../default/forms"; // Layer Vector on top of the default settings.
-@import "../../mixins/type";
-
-.mw-ui-vform,
-.mw-ui-vform input,
-.mw-ui-input {
-       .vector-type();
-}
index e576937..c9d6208 100644 (file)
@@ -1,7 +1,5 @@
 /**
- * Provide Agora appearance for mw-ui-* classes when using a skin other than
- * Vector.
+ * Provide Agora appearance for mw-ui-* classes.
  */
-
+@import "components/forms";
 @import "components/utilities";
-@import "components/default/forms";
diff --git a/resources/src/mediawiki.ui/mixins/effects.less b/resources/src/mediawiki.ui/mixins/effects.less
deleted file mode 100644 (file)
index 9759f63..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-@import "../settings/colors";
-// ----------------------------------------------------------------------------
-// Button styling
-// ----------------------------------------------------------------------------
-
-.button-colors(@bgColor) {
-       background: @bgColor;
-
-       &:hover,
-       &:focus {
-               // The inner bottom bevel should match the active background color.
-               box-shadow: 0 1px rgba(0, 0, 0, 10%), inset 0 -3px rgba(0, 0, 0, 20%);
-               border-bottom-color: mix(#000, @bgColor, 20%);
-               outline: none;
-               // remove outline in Firefox
-               &::-moz-focus-inner {
-                       border-color: transparent;
-               }
-       }
-
-       &:active,
-       &.mw-ui-checked {
-               // lessphp doesn't implement shade (https://github.com/leafo/lessphp/issues/528);
-               // it passes it through, then ResourceLoader drops it.
-               // background: shade(@bgColor, 20%);
-               background: mix(#000, @bgColor, 20%);
-               box-shadow: none;
-       }
-}
-
-.button-colors(@bgColor) when (lightness(@bgColor) >= 70%) {
-       color: @colorGrayDark;
-       border: 1px solid @colorGrayLight;
-
-       &:disabled {
-               color: @colorGrayLight;
-
-               // make sure disabled buttons don't have hover and active states
-               &:hover,
-               &:active {
-                       background: @bgColor;
-                       box-shadow: none;
-               }
-       }
-}
-
-.button-colors(@bgColor) when (lightness(@bgColor) < 70%) {
-       color: @colorWhite;
-       // border of the same color as background so that light background and
-       // dark background buttons are the same height (only top and bottom to
-       // make box shadow on hover cover the corners too)
-       border: 1px solid @bgColor;
-       border-left: none;
-       border-right: none;
-       text-shadow: 0 1px rgba(0, 0, 0, .1);
-
-       &:disabled {
-               background: @colorGrayLight;
-               border-color: @colorGrayLight;
-
-               // make sure disabled buttons don't have hover and active states
-               &:hover,
-               &:active,
-               &.mw-ui-checked {
-                       box-shadow: none;
-               }
-       }
-}
-
-.button-colors-quiet(@textColor) {
-       // Quiet buttons all start gray, and reveal
-       // constructive/progressive/destructive color on hover and active.
-       color: @colorGrayDark;
-
-       &:hover,
-       &:focus {
-               // lessphp doesn't implement tint, see above
-               // color: tint(@textColor, 20%);
-               color: mix(#fff, @textColor, 20%);
-       }
-
-       &:active,
-       &.mw-ui-checked {
-               // lessphp doesn't implement shade, see above
-               // color: shade(@textColor, 20%);
-               color: mix(#000, @textColor, 20%);
-       }
-
-       &:disabled {
-               color: @colorGrayLight;
-       }
-}
diff --git a/resources/src/mediawiki.ui/mixins/forms.less b/resources/src/mediawiki.ui/mixins/forms.less
deleted file mode 100644 (file)
index 20f42a0..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-@import "../settings/colors";
-
-// Font is not included.
-// For Vector, that should be layered on top with vector-type
-.agora-field-styling() {
-
-       border: 1px solid @colorGrayLight;
-
-       &:focus {
-               // Styling focus of native checkboxes etc on Mac is almost impossible.
-               &:not([type=checkbox]):not([type=radio]) {
-                       outline: 0; // Removes OS field focus
-               }
-
-               box-shadow: @colorProgressiveShadow 0 0 5px;
-
-               border-color: @colorProgressiveShadow;
-       }
-
-       color: @colorText;
-       padding: 0.35em 0.5em 0.35em 0.5em;
-
-       // Ensure that buttons and inputs are nicely aligned when they have differing heights
-       vertical-align: middle;
-}
-
-.agora-label-styling() {
-       //font-weight: bold;
-       font-size: 0.9em;
-       color: darken(@colorGrayLight, 50%);
-
-       * {
-               font-weight: normal;
-       }
-}
-
-.agora-inline-label-styling() {
-       margin-bottom: 0.5em;
-       cursor: pointer;
-       vertical-align: bottom;
-       line-height: normal;
-
-       font-weight: normal;
-
-       & > input[type="checkbox"],
-       & > input[type="radio"] {
-               width: auto;
-               height: auto;
-               margin: 0 0.1em 0 0;
-               padding: 0;
-               border: 1px solid @colorGrayLight;
-               cursor: pointer;
-       }
-}
diff --git a/resources/src/mediawiki.ui/mixins/type.less b/resources/src/mediawiki.ui/mixins/type.less
deleted file mode 100644 (file)
index 4a01168..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-@import "../settings/typography";
-
-.vector-type() {
-       font-size: @baseFontSize;
-       line-height: @baseLineHeight;
-}
diff --git a/resources/src/mediawiki.ui/mixins/utilities.less b/resources/src/mediawiki.ui/mixins/utilities.less
deleted file mode 100644 (file)
index 3d7b732..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-.agora-flush-left() {
-       float: left;
-       margin-left: 0;
-       padding-left: 0;
-}
-
-.agora-flush-right() {
-       float: right;
-       margin-right: 0;
-       padding-right: 0;
-}
-
-.agora-center-block() {
-       display: block;
-       margin-left: auto;
-       margin-right: auto;
-}
diff --git a/resources/src/mediawiki.ui/settings/colors.less b/resources/src/mediawiki.ui/settings/colors.less
deleted file mode 100644 (file)
index d456f86..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// FIXME: remove @colorProgressiveShadow (shadows should be generated
-// in LESS by dimming the original colors)
-@colorProgressiveShadow: #4091ed;
-
-// White; for background use, and text use on dark backgrounds
-@colorWhite: #fff;
-// Off-white; for background use on white backgrounds
-@colorOffWhite: #fafafa;
-// Dark gray; for non-text use
-@colorGrayDark: #898989;
-// Light gray; for non-text use
-@colorGrayLight: #ccc;
-// Very light gray; for non-text use
-@colorGrayLighter: #ddd;
-// Lightest gray; for non-text use
-@colorGrayLightest: #eee;
-
-// Dark gray; for body text
-@colorText: #252525;
-// Light gray; for less important body text and links
-@colorTextLight: #696969;
-
-// Blue; for contextual use of a continuing action
-@colorProgressive: #347bff;
-// Orange; for contextual use of returning to a past action
-@colorRegressive: #ff7e1e;
-// Green; for contextual use of a positive finalizing action
-@colorConstructive: #00af89;
-// Red; for contextual use of a negative finalizing action
-@colorDestructive: #d11d13;
-
-// Used in mixins to darken contextual colors by the same amount (eg. focus)
-@colorDarkenPercentage: 13.5%;
-// Used in mixins to lighten contextual colors by the same amount (eg. hover)
-@colorLightenPercentage: 13.5%;
\ No newline at end of file
diff --git a/resources/src/mediawiki.ui/settings/typography.less b/resources/src/mediawiki.ui/settings/typography.less
deleted file mode 100644 (file)
index 83651ed..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-@baseFontSize: 1em;
-@baseLineHeight: 1.4 * @baseFontSize;
-@baseFontColor: @colorText;
-
-@smallFontSize: 0.75em;
diff --git a/resources/src/mediawiki.ui/vector.less b/resources/src/mediawiki.ui/vector.less
deleted file mode 100644 (file)
index 04e88e8..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * Provide Agora appearance for mw-ui-* classes when using the Vector skin.
- */
-
-// Typography
-//
-// We prefer the usage of Georgia Bold for all headings. Georgia Regular is used to place emphasis on pull-out or short quotations. This latter usage should be used sparingly. 
-//
-// We prefer the use of Helvetica Neue Regular for body copy. Helvetiva Neue Bold for sub-headers. Pull-out quotes within the body copy should use Helvetica Neue Bold. Helvetica Neue is an not open-source font. Hence, below is a list of preferred alternate choices.
-//
-// Second choice: Helvetica
-//
-// Third choice: Arial
-//
-// Wiki content is often predominantly text; hence, visual hierarchy must be clear. Use these recommended type sizes to inform and establish information hierarchy and organization.
-//
-// Unless if you plan to put extra attention and manually adjust spacing, avoid justifying texts and paragraphs as they are harder to read and create unnecessary visual distractions. Along with centered text, they convey a formal and less friendly environment. 
-//
-// It will be important to talk about other languages, scripts and writing direction - with the same level as importance, not as an afterthought.
-//
-// Styleguide 1.
-
-@import "mediawiki.mixins";
-@import "components/utilities";
-@import "components/vector/forms";
-@import "components/vector/containers";
diff --git a/resources/src/mediawiki/images/arrow-sort-ascending.png b/resources/src/mediawiki/images/arrow-sort-ascending.png
new file mode 100644 (file)
index 0000000..f2d339d
Binary files /dev/null and b/resources/src/mediawiki/images/arrow-sort-ascending.png differ
diff --git a/resources/src/mediawiki/images/arrow-sort-ascending.svg b/resources/src/mediawiki/images/arrow-sort-ascending.svg
new file mode 100644 (file)
index 0000000..1e7a094
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path d="M1 10h10l-5-8.658z" fill="#00a"/></svg>
\ No newline at end of file
diff --git a/resources/src/mediawiki/images/arrow-sort-descending.png b/resources/src/mediawiki/images/arrow-sort-descending.png
new file mode 100644 (file)
index 0000000..8afbca9
Binary files /dev/null and b/resources/src/mediawiki/images/arrow-sort-descending.png differ
diff --git a/resources/src/mediawiki/images/arrow-sort-descending.svg b/resources/src/mediawiki/images/arrow-sort-descending.svg
new file mode 100644 (file)
index 0000000..cf11adb
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path d="M1 2h10l-5 8.658z" fill="#00a"/></svg>
\ No newline at end of file
diff --git a/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-ltr.png b/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-ltr.png
new file mode 100644 (file)
index 0000000..2a64fd0
Binary files /dev/null and b/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-ltr.png differ
diff --git a/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-rtl.png b/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-rtl.png
new file mode 100644 (file)
index 0000000..78a493e
Binary files /dev/null and b/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-rtl.png differ
diff --git a/resources/src/mediawiki/images/pager-arrow-disabled-forward-ltr.png b/resources/src/mediawiki/images/pager-arrow-disabled-forward-ltr.png
new file mode 100644 (file)
index 0000000..aa4fbf8
Binary files /dev/null and b/resources/src/mediawiki/images/pager-arrow-disabled-forward-ltr.png differ
diff --git a/resources/src/mediawiki/images/pager-arrow-disabled-forward-rtl.png b/resources/src/mediawiki/images/pager-arrow-disabled-forward-rtl.png
new file mode 100644 (file)
index 0000000..83df068
Binary files /dev/null and b/resources/src/mediawiki/images/pager-arrow-disabled-forward-rtl.png differ
diff --git a/resources/src/mediawiki/images/pager-arrow-fastforward-ltr.png b/resources/src/mediawiki/images/pager-arrow-fastforward-ltr.png
new file mode 100644 (file)
index 0000000..caf5033
Binary files /dev/null and b/resources/src/mediawiki/images/pager-arrow-fastforward-ltr.png differ
diff --git a/resources/src/mediawiki/images/pager-arrow-fastforward-rtl.png b/resources/src/mediawiki/images/pager-arrow-fastforward-rtl.png
new file mode 100644 (file)
index 0000000..52b32a5
Binary files /dev/null and b/resources/src/mediawiki/images/pager-arrow-fastforward-rtl.png differ
diff --git a/resources/src/mediawiki/images/pager-arrow-forward-ltr.png b/resources/src/mediawiki/images/pager-arrow-forward-ltr.png
new file mode 100644 (file)
index 0000000..3f8fee3
Binary files /dev/null and b/resources/src/mediawiki/images/pager-arrow-forward-ltr.png differ
diff --git a/resources/src/mediawiki/images/pager-arrow-forward-rtl.png b/resources/src/mediawiki/images/pager-arrow-forward-rtl.png
new file mode 100644 (file)
index 0000000..f363bf6
Binary files /dev/null and b/resources/src/mediawiki/images/pager-arrow-forward-rtl.png differ
index 4387608..fc8e7e9 100644 (file)
                        namespace = NS_MAIN;
                        title = title
                                // Strip colon
-                               .substr( 1 )
+                               .slice( 1 )
                                // Trim underscores
                                .replace( rUnderscoreTrim, '' );
                }
                } else {
                        fragment = title
                                // Get segment starting after the hash
-                               .substr( i + 1 )
+                               .slice( i + 1 )
                                // Convert to text
                                // NB: Must not be trimmed ("Example#_foo" is not the same as "Example#foo")
                                .replace( /_/g, ' ' );
 
                        title = title
                                // Strip hash
-                               .substr( 0, i )
+                               .slice( 0, i )
                                // Trim underscores, again (strips "_" from "bar" in "Foo_bar_#quux")
                                .replace( rUnderscoreTrim, '' );
                }
                                title.indexOf( '../' ) === 0 ||
                                title.indexOf( '/./' ) !== -1 ||
                                title.indexOf( '/../' ) !== -1 ||
-                               title.substr( title.length - 2 ) === '/.' ||
-                               title.substr( title.length - 3 ) === '/..'
+                               title.slice( -2 ) === '/.' ||
+                               title.slice( -3 ) === '/..'
                        )
                ) {
                        return false;
                        // Extensions are the non-empty segment after the last dot
                        ext = null;
                } else {
-                       ext = title.substr( i + 1 );
-                       title = title.substr( 0, i );
+                       ext = title.slice( i + 1 );
+                       title = title.slice( 0, i );
                }
 
                return {
diff --git a/resources/src/mediawiki/mediawiki.content.json.css b/resources/src/mediawiki/mediawiki.content.json.css
new file mode 100644 (file)
index 0000000..d93e291
--- /dev/null
@@ -0,0 +1,53 @@
+/*!
+ * CSS for styling HTML-formatted JSON Schema objects
+ *
+ * @file
+ * @author Munaf Assaf <massaf@wikimedia.org>
+ */
+
+.mw-json {
+       border-collapse: collapse;
+       border-spacing: 0;
+       font-style: normal;
+}
+
+.mw-json th,
+.mw-json td {
+       border: 1px solid gray;
+       font-size: 16px;
+       padding: 0.5em 1em;
+}
+
+.mw-json td {
+       background-color: #eee;
+       font-style: italic;
+}
+
+.mw-json .value {
+       background-color: #dcfae3;
+       font-family: monospace, monospace;
+       white-space: pre-wrap;
+}
+
+.mw-json tr {
+       margin-bottom: 0.5em;
+}
+
+.mw-json th {
+       background-color: #fff;
+       font-weight: normal;
+}
+
+.mw-json caption {
+       /* For stylistic reasons, suppress the caption of the outermost table */
+       display: none;
+}
+
+.mw-json table caption {
+       color: gray;
+       display: inline-block;
+       font-size: 10px;
+       font-style: italic;
+       margin-bottom: 0.5em;
+       text-align: left;
+}
index f56f0d9..4935984 100644 (file)
@@ -61,7 +61,7 @@
                 */
                switchPane: function ( e ) {
                        var currentPaneId = debug.$container.data( 'currentPane' ),
-                               requestedPaneId = $( this ).prop( 'id' ).substr( 9 ),
+                               requestedPaneId = $( this ).prop( 'id' ).slice( 9 ),
                                $currentPane = $( '#mw-debug-pane-' + currentPaneId ),
                                $requestedPane = $( '#mw-debug-pane-' + requestedPaneId ),
                                hovDone = false;
 
                        gitInfo = '';
                        if ( this.data.gitRevision !== false ) {
-                               gitInfo = '(' + this.data.gitRevision.substring( 0, 7 ) + ')';
+                               gitInfo = '(' + this.data.gitRevision.slice( 0, 7 ) + ')';
                                if ( this.data.gitViewUrl !== false ) {
                                        gitInfo = $( '<a>' )
                                                .attr( 'href', this.data.gitViewUrl )
                        }
 
                        bitDiv( 'phpversion' )
-                               .append( $( '<a href="//www.php.net/"></a>' ).text( 'PHP' ) )
+                               .append( $( this.data.phpEngine === 'HHVM'
+                                       ? '<a href="http://hhvm.com/">HHVM</a>'
+                                       : '<a href="https://php.net/">PHP</a>'
+                               ) )
                                .append( ': ' + this.data.phpVersion );
 
                        bitDiv( 'time' )
index 64ec6c3..04f7acd 100644 (file)
                        // only drop events if requested
                        dropThresholdPx = dropThresholdPx || 0;
 
-                       if ( !Array.prototype.map || !Array.prototype.reduce || !Array.prototype.filter ) {
-                               profile.container = profile.buildRequiresES5();
+                       if (
+                               !Array.prototype.map ||
+                               !Array.prototype.reduce ||
+                               !Array.prototype.filter ||
+                               !document.createElementNS ||
+                               !document.createElementNS.bind
+                       ) {
+                               profile.container = profile.buildRequiresBrowserFeatures();
                        } else if ( data.length === 0 ) {
                                profile.container = profile.buildNoData();
                        } else {
+                               // Initialize createSvgElement (now that we know we have
+                               // document.createElementNS and bind)
+                               this.createSvgElement = document.createElementNS.bind( document, 'http://www.w3.org/2000/svg' );
+
                                // generate a flyout
                                profile.data = new ProfileData( data, profile.width, mergeThresholdPx, dropThresholdPx );
                                // draw it
@@ -52,9 +62,9 @@
                        return profile.container;
                },
 
-               buildRequiresES5: function () {
+               buildRequiresBrowserFeatures: function () {
                        return $( '<div>' )
-                               .text( 'An ES5 compatible javascript engine is required for the profile visualization.' )
+                               .text( 'Certain browser features, including parts of ECMAScript 5 and document.createElementNS, are required for the profile visualization.' )
                                .get( 0 );
                },
 
 
                /**
                 * Creates DOM nodes appropriately namespaced for SVG.
+                * Initialized in init after checking support
                 *
                 * @param string tag to create
                 * @return DOMElement
                 */
-               createSvgElement: document.createElementNS
-                       ? document.createElementNS.bind( document, 'http://www.w3.org/2000/svg' )
-                       // throw a error for browsers which does not support document.createElementNS (IE<8)
-                       : function () { throw new Error( 'document.createElementNS not supported' ); },
+               createSvgElement: null,
 
                /**
                 * @param DOMElement|undefined
        ProfileData.groupOf = function ( label ) {
                var pos, prefix = 'Profile section ended by close(): ';
                if ( label.indexOf( prefix ) === 0 ) {
-                       label = label.substring( prefix.length );
+                       label = label.slice( prefix.length );
                }
 
                pos = [ '::', ':', '-' ].reduce( function ( result, separator ) {
                if ( pos === -1 ) {
                        return label;
                } else {
-                       return label.substring( 0, pos );
+                       return label.slice( 0, pos );
                }
        };
 
index 6533db1..1c0d833 100644 (file)
         * dialog box. Submitting that dialog box appends its contents to a
         * wiki page that you specify, as a new section.
         *
-        * Not compatible with LiquidThreads.
+        * This feature works with classic MediaWiki pages
+        * and is not compatible with LiquidThreads or Flow.
         *
-        * Minimal example in how to use it:
+        * Minimal usage example:
         *
         *     var feedback = new mw.Feedback();
         *     $( '#myButton' ).click( function () { feedback.launch(); } );
                                                                $feedbackPageLink.clone()
                                                        )
                                                ),
-                                               $( '<div style="margin-top: 1em;"></div>' ).append(
-                                                       mw.msg( 'feedback-subject' ),
+                                               $( '<div style="margin-top: 1em;"></div>' )
+                                               .msg( 'feedback-subject' )
+                                               .append(
                                                        $( '<br>' ),
                                                        $( '<input type="text" class="feedback-subject" name="subject" maxlength="60" style="width: 100%; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;"/>' )
                                                ),
-                                               $( '<div style="margin-top: 0.4em;"></div>' ).append(
-                                                       mw.msg( 'feedback-message' ),
+                                               $( '<div style="margin-top: 0.4em;"></div>' )
+                                               .msg( 'feedback-message' )
+                                               .append(
                                                        $( '<br>' ),
                                                        $( '<textarea name="message" class="feedback-message" rows="5" cols="60"></textarea>' )
                                                )
                                        $( '<div class="feedback-mode feedback-bugs"></div>' ).append(
                                                $( '<p>' ).msg( 'feedback-bugcheck', $bugsListLink )
                                        ),
-                                       $( '<div class="feedback-mode feedback-submitting" style="text-align: center; margin: 3em 0;"></div>' ).append(
-                                               mw.msg( 'feedback-adding' ),
+                                       $( '<div class="feedback-mode feedback-submitting" style="text-align: center; margin: 3em 0;"></div>' )
+                                       .msg( 'feedback-adding' )
+                                       .append(
                                                $( '<br>' ),
                                                $( '<span class="feedback-spinner"></span>' )
                                        ),
                                        )
                                );
 
-                               // undo some damage from dialog css
-                               this.$dialog.find( 'a' ).css( {
-                                       color: '#0645ad'
-                               } );
-
-                               this.$dialog.dialog( {
-                                       width: 500,
-                                       autoOpen: false,
-                                       title: mw.msg( this.dialogTitleMessageKey ),
-                                       modal: true,
-                                       buttons: fb.buttons
-                               } );
+                       this.$dialog.dialog( {
+                               width: 500,
+                               autoOpen: false,
+                               title: mw.message( this.dialogTitleMessageKey ).escaped(),
+                               modal: true,
+                               buttons: fb.buttons
+                       } );
 
                        this.subjectInput = this.$dialog.find( 'input.feedback-subject' ).get( 0 );
                        this.messageInput = this.$dialog.find( 'textarea.feedback-message' ).get( 0 );
-
                },
 
                /**
                displayBugs: function () {
                        var fb = this,
                                bugsButtons = {};
+
                        this.display( 'bugs' );
                        bugsButtons[ mw.msg( 'feedback-bugnew' ) ] = function () {
                                window.open( fb.bugsLink, '_blank' );
                displayThanks: function () {
                        var fb = this,
                                closeButton = {};
+
                        this.display( 'thanks' );
                        closeButton[ mw.msg( 'feedback-close' ) ] = function () {
                                fb.$dialog.dialog( 'close' );
                displayForm: function ( contents ) {
                        var fb = this,
                                formButtons = {};
+
                        this.subjectInput.value = ( contents && contents.subject ) ? contents.subject : '';
                        this.messageInput.value = ( contents && contents.message ) ? contents.message : '';
 
                displayError: function ( message ) {
                        var fb = this,
                                closeButton = {};
+
                        this.display( 'error' );
                        this.$dialog.find( '.feedback-error-msg' ).msg( message );
                        closeButton[ mw.msg( 'feedback-close' ) ] = function () {
                        var subject, message,
                                fb = this;
 
-                       function ok( result ) {
+                       // Get the values to submit.
+                       subject = this.subjectInput.value;
+
+                       // We used to include "mw.html.escape( navigator.userAgent )" but there are legal issues
+                       // with posting this without their explicit consent
+                       message = this.messageInput.value;
+                       if ( message.indexOf( '~~~' ) === -1 ) {
+                               message += ' ~~~~';
+                       }
+
+                       this.displaySubmitting();
+
+                       // Post the message, resolving redirects
+                       this.api.newSection(
+                               this.title,
+                               subject,
+                               message,
+                               { redirect: true }
+                       )
+                       .done( function ( result ) {
                                if ( result.edit !== undefined ) {
                                        if ( result.edit.result === 'Success' ) {
                                                fb.displayThanks();
                                        // edit failed
                                        fb.displayError( 'feedback-error2' );
                                }
-                       }
-
-                       function err() {
+                       } )
+                       .fail( function () {
                                // ajax request failed
                                fb.displayError( 'feedback-error3' );
-                       }
-
-                       // Get the values to submit.
-                       subject = this.subjectInput.value;
-
-                       // We used to include "mw.html.escape( navigator.userAgent )" but there are legal issues
-                       // with posting this without their explicit consent
-                       message = this.messageInput.value;
-                       if ( message.indexOf( '~~~' ) === -1 ) {
-                               message += ' ~~~~';
-                       }
-
-                       this.displaySubmitting();
-
-                       this.api.newSection( this.title, subject, message ).done( ok ).fail( err );
+                       } );
                },
 
                /**
                        this.$dialog.dialog( 'open' );
                        this.subjectInput.focus();
                }
-
        };
-
 }( mediaWiki, jQuery ) );
index 8be1321..594800e 100644 (file)
@@ -15,6 +15,7 @@
         * ending in array keys matching the given name (e.g. "baz" matches
         * "foo[bar][baz]").
         *
+        * @private
         * @param {jQuery} element
         * @param {string} name
         * @return {jQuery|null}
         * Helper function for hide-if to return a test function and list of
         * dependent fields for a hide-if specification.
         *
+        * @private
         * @param {jQuery} element
         * @param {Array} hide-if spec
-        * @return {Array} 2 elements: jQuery of dependent fields, and test function
+        * @return {Array}
+        * @return {jQuery} return.0 Dependent fields
+        * @return {Function} return.1 Test function
         */
        function hideIfParse( $el, spec ) {
                var op, i, l, v, $field, $fields, fields, func, funcs, getVal;
@@ -63,7 +67,7 @@
                                                throw new Error( op + ' parameters must be arrays' );
                                        }
                                        v = hideIfParse( $el, spec[i] );
-                                       fields.push( v[0] );
+                                       fields = fields.concat( v[0].toArray() );
                                        funcs.push( v[1] );
                                }
                                $fields = $( fields );
        } );
 
        function enhance( $root ) {
+               var $matrixTooltips, $autocomplete;
 
                /**
                 * @ignore
                        } );
                }
 
-               var $matrixTooltips = $root.find( '.mw-htmlform-matrix .mw-htmlform-tooltip' );
+               $matrixTooltips = $root.find( '.mw-htmlform-matrix .mw-htmlform-tooltip' );
                if ( $matrixTooltips.length ) {
                        mw.loader.using( 'jquery.tipsy', function () {
                                $matrixTooltips.tipsy( { gravity: 's' } );
                        } );
                }
 
+               // Set up autocomplete fields
+               $autocomplete = $root.find( '.mw-htmlform-autocomplete' );
+               if ( $autocomplete.length ) {
+                       mw.loader.using( 'jquery.suggestions', function () {
+                               $autocomplete.suggestions( {
+                                       fetch: function ( val ) {
+                                               var $el = $( this );
+                                               $el.suggestions( 'suggestions',
+                                                       $.grep( $el.data( 'autocomplete' ), function ( v ) {
+                                                               return v.indexOf( val ) === 0;
+                                                       } )
+                                               );
+                                       }
+                               } );
+                       } );
+               }
+
                // Add/remove cloner clones without having to resubmit the form
                $root.find( '.mw-htmlform-cloner-delete-button' ).click( function ( ev ) {
                        ev.preventDefault();
                        $ul = $( this ).prev( 'ul.mw-htmlform-cloner-ul' );
 
                        html = $ul.data( 'template' ).replace(
-                               $ul.data( 'uniqueId' ), 'clone' + ( ++cloneCounter ), 'g'
+                               new RegExp( $.escapeRE( $ul.data( 'uniqueId' ) ), 'g' ),
+                               'clone' + ( ++cloneCounter )
                        );
 
                        $li = $( '<li>' )
index eda7689..8e9fc89 100644 (file)
                },
 
                /**
-                * Perform a substring search across the JavaScript and CSS source code
+                * Perform a string search across the JavaScript and CSS source code
                 * of all loaded modules and return an array of the names of the
                 * modules that matched.
                 *
index 9d34d62..ad71b08 100644 (file)
                         */
                        function makeRegexParser( regex ) {
                                return function () {
-                                       var matches = input.substr( pos ).match( regex );
+                                       var matches = input.slice( pos ).match( regex );
                                        if ( matches === null ) {
                                                return null;
                                        }
 
                                if ( parsedCloseTagResult === null ) {
                                        // Closing tag failed.  Return the start tag and contents.
-                                       return [ 'CONCAT', input.substring( startOpenTagPos, endOpenTagPos ) ]
+                                       return [ 'CONCAT', input.slice( startOpenTagPos, endOpenTagPos ) ]
                                                .concat( parsedHtmlContents );
                                }
 
                                        // parsed HTML link.
                                        //
                                        // Concatenate everything from the tag, flattening the contents.
-                                       result = [ 'CONCAT', input.substring( startOpenTagPos, endOpenTagPos ) ]
-                                               .concat( parsedHtmlContents, input.substring( startCloseTagPos, endCloseTagPos ) );
+                                       result = [ 'CONCAT', input.slice( startOpenTagPos, endOpenTagPos ) ]
+                                               .concat( parsedHtmlContents, input.slice( startCloseTagPos, endCloseTagPos ) );
                                }
 
                                return result;
                        } else {
                                $el = $( '<a>' );
                                if ( typeof arg === 'function' ) {
-                                       $el.click( arg ).attr( 'href', '#' );
+                                       $el.attr( 'href', '#' )
+                                       .click( function ( e ) {
+                                               e.preventDefault();
+                                       } )
+                                       .click( arg );
                                } else {
                                        $el.attr( 'href', arg.toString() );
                                }
                 * @return {string} selected pluralized form according to current language
                 */
                plural: function ( nodes ) {
-                       var forms, count;
+                       var forms, formIndex, node, count;
                        count = parseFloat( this.language.convertNumber( nodes[0], true ) );
                        forms = nodes.slice( 1 );
+                       for ( formIndex = 0; formIndex < forms.length; formIndex++ ) {
+                               node = forms[formIndex];
+                               if ( node.jquery && node.hasClass( 'mediaWiki_htmlEmitter' )  ) {
+                                       // This is a nested node, already expanded.
+                                       forms[formIndex] = forms[formIndex].html();
+                               }
+                       }
                        return forms.length ? this.language.convertPlural( count, forms ) : '';
                },
 
index 12888bd..e29c734 100644 (file)
                         * Format:
                         *     {
                         *         'moduleName': {
+                        *             // At registry
                         *             'version': ############## (unix timestamp),
                         *             'dependencies': ['required.foo', 'bar.also', ...], (or) function () {}
                         *             'group': 'somegroup', (or) null,
                         *             'source': 'local', 'someforeignwiki', (or) null
                         *             'state': 'registered', 'loaded', 'loading', 'ready', 'error' or 'missing'
+                        *             'skip': 'return !!window.Example', (or) null
+                        *
+                        *             // Added during implementation
+                        *             'skipped': true,
                         *             'script': ...,
                         *             'style': ...,
                         *             'messages': { 'key': 'value' },
                         */
                        var registry = {},
                                //
-                               // Mapping of sources, keyed by source-id, values are objects.
+                               // Mapping of sources, keyed by source-id, values are strings.
                                // Format:
                                //      {
-                               //              'sourceId': {
-                               //                      'loadScript': 'http://foo.bar/w/load.php'
-                               //              }
+                               //              'sourceId': 'http://foo.bar/w/load.php'
                                //      }
                                //
                                sources = {},
                        /* Private methods */
 
                        function getMarker() {
-                               // Cached ?
-                               if ( $marker ) {
-                                       return $marker;
-                               }
-
-                               $marker = $( 'meta[name="ResourceLoaderDynamicStyles"]' );
-                               if ( $marker.length ) {
-                                       return $marker;
+                               // Cached
+                               if ( !$marker ) {
+                                       $marker = $( 'meta[name="ResourceLoaderDynamicStyles"]' );
+                                       if ( !$marker.length ) {
+                                               mw.log( 'No <meta name="ResourceLoaderDynamicStyles"> found, inserting dynamically' );
+                                               $marker = $( '<meta>' ).attr( 'name', 'ResourceLoaderDynamicStyles' ).appendTo( 'head' );
+                                       }
                                }
-                               mw.log( 'getMarker> No <meta name="ResourceLoaderDynamicStyles"> found, inserting dynamically.' );
-                               $marker = $( '<meta>' ).attr( 'name', 'ResourceLoaderDynamicStyles' ).appendTo( 'head' );
-
                                return $marker;
                        }
 
                                        skip = new Function( registry[module].skip );
                                        registry[module].skip = null;
                                        if ( skip() ) {
+                                               registry[module].skipped = true;
                                                registry[module].dependencies = [];
                                                registry[module].state = 'ready';
                                                handlePending( module );
                                                crossDomain: true,
                                                cache: true,
                                                async: true
-                                       } ).always( function () {
-                                               if ( callback  ) {
-                                                       callback();
-                                               }
-                                       } );
+                                       } ).always( callback );
                                } else {
                                        /*jshint evil:true */
                                        document.write( mw.html.element( 'script', { 'src': src }, '' ) );
 
                                        for ( source in splits ) {
 
-                                               sourceLoadScript = sources[source].loadScript;
+                                               sourceLoadScript = sources[source];
 
                                                for ( group in splits[source] ) {
 
                                                        for ( i = 0; i < modules.length; i += 1 ) {
                                                                // Determine how many bytes this module would add to the query string
                                                                lastDotIndex = modules[i].lastIndexOf( '.' );
-                                                               // Note that these substr() calls work even if lastDotIndex == -1
+
+                                                               // If lastDotIndex is -1, substr() returns an empty string
                                                                prefix = modules[i].substr( 0, lastDotIndex );
-                                                               suffix = modules[i].substr( lastDotIndex + 1 );
+                                                               suffix = modules[i].slice( lastDotIndex + 1 );
+
                                                                bytesAdded = moduleMap[prefix] !== undefined
                                                                        ? suffix.length + 3 // '%2C'.length == 3
                                                                        : modules[i].length + 3; // '%7C'.length == 3
                                 *
                                 * The #work method will use this information to split up requests by source.
                                 *
-                                *     mw.loader.addSource( 'mediawikiwiki', { loadScript: '//www.mediawiki.org/w/load.php' } );
+                                *     mw.loader.addSource( 'mediawikiwiki', '//www.mediawiki.org/w/load.php' );
                                 *
                                 * @param {string} id Short string representing a source wiki, used internally for
                                 *  registered modules to indicate where they should be loaded from (usually lowercase a-z).
-                                * @param {Object} props
-                                * @param {string} props.loadScript Url to the load.php entry point of the source wiki.
+                                * @param {Object|string} loadUrl load.php url, may be an object for backwards-compatibility
                                 * @return {boolean}
                                 */
-                               addSource: function ( id, props ) {
+                               addSource: function ( id, loadUrl ) {
                                        var source;
                                        // Allow multiple additions
                                        if ( typeof id === 'object' ) {
                                                throw new Error( 'source already registered: ' + id );
                                        }
 
-                                       sources[id] = props;
+                                       if ( typeof loadUrl === 'object' ) {
+                                               loadUrl = loadUrl.loadScript;
+                                       }
+
+                                       sources[id] = loadUrl;
 
                                        return true;
                                },
                                 *
                                 * @param {string|Array} modules Either the name of a module, array of modules,
                                 *  or a URL of an external script or style
-                                * @param {string} [type='text/javascript'] mime-type to use if calling with a URL of an
+                                * @param {string} [type='text/javascript'] MIME type to use if calling with a URL of an
                                 *  external script or style; acceptable values are "text/css" and
                                 *  "text/javascript"; if no type is provided, text/javascript is assumed.
                                 * @param {boolean} [async] Whether to load modules asynchronously.
                                                }
 
                                                for ( key in mw.loader.store.items ) {
-                                                       module = key.substring( 0, key.indexOf( '@' ) );
+                                                       module = key.slice( 0, key.indexOf( '@' ) );
                                                        if ( mw.loader.store.getModuleKey( module ) !== key ) {
                                                                mw.loader.store.stats.expired++;
                                                                delete mw.loader.store.items[key];
index 0c8152e..ae399ce 100644 (file)
        position: fixed;
 }
 
-* html .mw-notification-area-floating {
-       /* Make it at least 'absolute' in IE6 since 'fixed' is not supported */
-       position: absolute;
-}
-
 .mw-notification {
        padding: 0.25em 1em;
        margin-bottom: 0.5em;
index b5fd69c..1968aa9 100644 (file)
                        // on links from hiding a notification.
                        .on( 'click', 'a', function ( e ) {
                                e.stopPropagation();
-                       } );
+                       } )
+                       .hide();
 
                // Prepend the notification area to the content area and save it's object.
                mw.util.$content.prepend( $area );
                /**
                 * Display a notification message to the user.
                 *
-                * @param {HTMLElement|jQuery|mw.Message|string} message
+                * @param {HTMLElement|HTMLElement[]|jQuery|mw.Message|string} message
                 * @param {Object} options The options to use for the notification.
                 *  See #defaults for details.
                 * @return {mw.Notification} Notification object
index 743d651..c1e1dab 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * @class mw.plugin.notify
  */
-( function ( mw, $ ) {
+( function ( mw ) {
        'use strict';
 
        /**
         * @return {jQuery.Promise}
         */
        mw.notify = function ( message, options ) {
-               var d = $.Deferred();
                // Don't bother loading the whole notification system if we never use it.
-               mw.loader.using( 'mediawiki.notification', function () {
-                       // Call notify with the notification the user requested of us.
-                       d.resolve( mw.notification.notify( message, options ) );
-               }, d.reject );
-               return d.promise();
+               return mw.loader.using( 'mediawiki.notification' )
+                       .then( function () {
+                               // Call notify with the notification the user requested of us.
+                               return mw.notification.notify( message, options );
+                       } );
        };
 
        /**
@@ -25,4 +24,4 @@
         * @mixins mw.plugin.notify
         */
 
-}( mediaWiki, jQuery ) );
+}( mediaWiki ) );
diff --git a/resources/src/mediawiki/mediawiki.pager.tablePager.less b/resources/src/mediawiki/mediawiki.pager.tablePager.less
new file mode 100644 (file)
index 0000000..d37aec5
--- /dev/null
@@ -0,0 +1,84 @@
+/*!
+ * Structures generated by the TablePager PHP class
+ * in MediaWiki (used e.g. on Special:ListFiles).
+ */
+
+@import "mediawiki.mixins";
+
+.TablePager {
+       min-width: 80%;
+}
+
+.TablePager .TablePager_sort-ascending a {
+       padding-left: 15px;
+       background: none left center no-repeat;
+       .background-image-svg('images/arrow-sort-ascending.svg', 'images/arrow-sort-ascending.png');
+}
+
+.TablePager .TablePager_sort-descending a {
+       padding-left: 15px;
+       background: none left center no-repeat;
+       .background-image-svg('images/arrow-sort-descending.svg', 'images/arrow-sort-descending.png');
+}
+
+.TablePager_nav {
+       margin: 0 auto;
+}
+
+.TablePager_nav td {
+       padding: 3px;
+       text-align: center;
+       vertical-align: center;
+}
+
+.TablePager_nav a {
+       text-decoration: none;
+}
+
+.TablePager_nav td.TablePager_nav-first .TablePager_nav-disabled {
+       padding-top: 25px;
+       /* @embed */
+       background: url(images/pager-arrow-disabled-fastforward-rtl.png) center top no-repeat;
+}
+
+.TablePager_nav td.TablePager_nav-prev .TablePager_nav-disabled {
+       padding-top: 25px;
+       /* @embed */
+       background: url(images/pager-arrow-disabled-forward-rtl.png) center top no-repeat;
+}
+
+.TablePager_nav td.TablePager_nav-next .TablePager_nav-disabled {
+       padding-top: 25px;
+       /* @embed */
+       background: url(images/pager-arrow-disabled-forward-ltr.png) center top no-repeat;
+}
+
+.TablePager_nav td.TablePager_nav-last .TablePager_nav-disabled {
+       padding-top: 25px;
+       /* @embed */
+       background: url(images/pager-arrow-disabled-fastforward-ltr.png) center top no-repeat;
+}
+
+.TablePager_nav td.TablePager_nav-first .TablePager_nav-enabled {
+       padding-top: 25px;
+       /* @embed */
+       background: url(images/pager-arrow-fastforward-rtl.png) center top no-repeat;
+}
+
+.TablePager_nav td.TablePager_nav-prev .TablePager_nav-enabled {
+       padding-top: 25px;
+       /* @embed */
+       background: url(images/pager-arrow-forward-rtl.png) center top no-repeat;
+}
+
+.TablePager_nav td.TablePager_nav-next .TablePager_nav-enabled {
+       padding-top: 25px;
+       /* @embed */
+       background: url(images/pager-arrow-forward-ltr.png) center top no-repeat;
+}
+
+.TablePager_nav td.TablePager_nav-last .TablePager_nav-enabled {
+       padding-top: 25px;
+       /* @embed */
+       background: url(images/pager-arrow-fastforward-ltr.png) center top no-repeat;
+}
index e8dd473..45338ea 100644 (file)
@@ -35,7 +35,7 @@
                if ( $toc.length && $tocTitle.length && $tocList.length && !$tocToggleLink.length ) {
                        hideToc = $.cookie( 'mw_hidetoc' ) === '1';
 
-                       $tocToggleLink = $( '<a href="#" class="internal" id="togglelink"></a>' )
+                       $tocToggleLink = $( '<a href="#" id="togglelink"></a>' )
                                .text( hideToc ? mw.msg( 'showtoc' ) : mw.msg( 'hidetoc' ) )
                                .click( function ( e ) {
                                        e.preventDefault();
index c5694b7..e93707e 100644 (file)
         *
         * @private
         * @param {string} info One of 'groups' or 'rights'
-        * @param {Function} [callback]
         * @return {jQuery.Promise}
         */
-       function getUserInfo( info, callback ) {
+       function getUserInfo( info ) {
                var api;
                if ( !deferreds[info] ) {
 
@@ -42,7 +41,7 @@
 
                }
 
-               return deferreds[info].done( callback ).promise();
+               return deferreds[info].promise();
        }
 
        mw.user = user = {
@@ -63,7 +62,7 @@
                                seed = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
                        for ( i = 0; i < 32; i++ ) {
                                r = Math.floor( Math.random() * seed.length );
-                               id += seed.substring( r, r + 1 );
+                               id += seed.charAt( r );
                        }
                        return id;
                },
                 * @return {jQuery.Promise}
                 */
                getGroups: function ( callback ) {
-                       return getUserInfo( 'groups', callback );
+                       return getUserInfo( 'groups' ).done( callback );
                },
 
                /**
                 * @return {jQuery.Promise}
                 */
                getRights: function ( callback ) {
-                       return getUserInfo( 'rights', callback );
+                       return getUserInfo( 'rights' ).done( callback );
                }
        };
 
diff --git a/resources/src/polyfill-object-create.js b/resources/src/polyfill-object-create.js
new file mode 100644 (file)
index 0000000..607faf6
--- /dev/null
@@ -0,0 +1,62 @@
+/**
+ * Simplified version of es5-sham#Object-create that also works around a bug
+ * in the actual es5-sham: https://github.com/es-shims/es5-shim/issues/252
+ *
+ * Does not:
+ * - Support empty inheritance via `Object.create(null)`.
+ * - Support getter and setter accessors via `Object.create( .., properties )`.
+ * - Support custom property descriptor (e.g. writable, configurtable, enumerable).
+ * - Leave behind an enumerable "__proto__" all over the place.
+ *
+ * @author Timo Tijhof, 2014
+ */
+
+// ES5 15.2.3.5
+// http://es5.github.com/#x15.2.3.5
+if ( !Object.create ) {
+       ( function () {
+               var hasOwn = Object.hasOwnProperty,
+                       // https://developer.mozilla.org/en-US/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
+                       // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
+                       isEnumBug = !{ valueOf: 0 }.propertyIsEnumerable( 'valueOf' );
+
+               // Reusable constructor function for Object.create
+               function Empty() {}
+
+               function defineProperty( object, key, property ) {
+                       if ( hasOwn.call( property, 'value' ) ) {
+                               object[ key ] = property.value;
+                       } else {
+                               object[ key ] = property;
+                       }
+               }
+
+               Object.create = function create( prototype, properties ) {
+                       var object, key;
+
+                       if ( prototype !== Object( prototype ) ) {
+                               throw new TypeError( 'Called on non-object' );
+                       }
+
+                       Empty.prototype = prototype;
+                       object = new Empty();
+
+                       if ( properties !== undefined ) {
+                               if ( !isEnumBug ) {
+                                       for ( key in properties ) {
+                                               if ( hasOwn.call( properties, key ) ) {
+                                                       defineProperty( object, key, properties[ key ] );
+                                               }
+                                       }
+                               } else {
+                                       Object.keys( properties ).forEach( function ( key ) {
+                                               defineProperty( object, key, properties[ key ] );
+                                       } );
+                               }
+                       }
+
+                       return object;
+               };
+
+       }() );
+}
index cd21ecc..a62cc9d 100644 (file)
@@ -7,15 +7,14 @@
 var mediaWikiLoadStart = ( new Date() ).getTime();
 
 /**
- * Returns false when run in a black-listed browser
+ * Returns false for Grade C supported browsers.
  *
- * This function will be deleted after it's used, so do not expand it to be
- * generally useful beyond startup.
+ * This function should only be used by the Startup module, do not expand it to
+ * be generally useful beyond startup.
  *
  * See also:
- * - https://www.mediawiki.org/wiki/Compatibility#Browser
- * - http://jquerymobile.com/gbs/
- * - http://jquery.com/browser-support/
+ * - https://www.mediawiki.org/wiki/Compatibility#Browsers
+ * - https://jquery.com/browser-support/
  */
 
 /*jshint unused: false */
@@ -24,12 +23,21 @@ function isCompatible( ua ) {
                ua = navigator.userAgent;
        }
 
-       // MediaWiki JS or jQuery is known to have issues with:
+       // Browsers with outdated or limited JavaScript engines get the no-JS experience
        return !(
-               // Internet Explorer < 6
-               ( ua.indexOf( 'MSIE' ) !== -1 && parseFloat( ua.split( 'MSIE' )[1] ) < 6 ) ||
+               // Internet Explorer < 8
+               ( ua.indexOf( 'MSIE' ) !== -1 && parseFloat( ua.split( 'MSIE' )[1] ) < 8 ) ||
                // Firefox < 3
                ( ua.indexOf( 'Firefox/' ) !== -1 && parseFloat( ua.split( 'Firefox/' )[1] ) < 3 ) ||
+               // Opera < 12
+               ( ua.indexOf( 'Opera/' ) !== -1 && ( ua.indexOf( 'Version/' ) === -1 ?
+                       // "Opera/x.y"
+                       parseFloat( ua.split( 'Opera/' )[1] ) < 10 :
+                       // "Opera/9.80 ... Version/x.y"
+                       parseFloat( ua.split( 'Version/' )[1] ) < 12
+               ) ) ||
+               // "Mozilla/0.0 ... Opera x.y"
+               ( ua.indexOf( 'Opera ' ) !== -1 && parseFloat( ua.split( ' Opera ' )[1] ) < 10 ) ||
                // BlackBerry < 6
                ua.match( /BlackBerry[^\/]*\/[1-5]\./ ) ||
                // Open WebOS < 1.5
index 1a9569f..6719bdd 100644 (file)
@@ -1,5 +1,3 @@
 /*
 !/common/
-!/MonoBook/
-!/Vector/
 !/.gitignore
diff --git a/skins/MonoBook/COPYING b/skins/MonoBook/COPYING
deleted file mode 100644 (file)
index 019694a..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-== GNU GENERAL PUBLIC LICENSE ==
-
-Version 2, June 1991
-
-Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
-Everyone is permitted to copy and distribute verbatim copies
-of this license document, but changing it is not allowed.
-
-=== Preamble ===
-
-The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-The precise terms and conditions for copying, distribution and
-modification follow.
-
-== TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ==
-
-'''0.''' This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-'''1.''' You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-'''2.''' You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-       '''a)''' You must cause the modified files to carry prominent notices
-       stating that you changed the files and the date of any change.
-
-       '''b)''' You must cause any work that you distribute or publish, that in
-       whole or in part contains or is derived from the Program or any
-       part thereof, to be licensed as a whole at no charge to all third
-       parties under the terms of this License.
-
-       '''c)''' If the modified program normally reads commands interactively
-       when run, you must cause it, when started running for such
-       interactive use in the most ordinary way, to print or display an
-       announcement including an appropriate copyright notice and a
-       notice that there is no warranty (or else, saying that you provide
-       a warranty) and that users may redistribute the program under
-       these conditions, and telling the user how to view a copy of this
-       License.  (Exception: if the Program itself is interactive but
-       does not normally print such an announcement, your work based on
-       the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-'''3.''' You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-       '''a)''' Accompany it with the complete corresponding machine-readable
-       source code, which must be distributed under the terms of Sections
-       1 and 2 above on a medium customarily used for software interchange; or,
-
-       '''b)''' Accompany it with a written offer, valid for at least three
-       years, to give any third party, for a charge no more than your
-       cost of physically performing source distribution, a complete
-       machine-readable copy of the corresponding source code, to be
-       distributed under the terms of Sections 1 and 2 above on a medium
-       customarily used for software interchange; or,
-
-       '''c)''' Accompany it with the information you received as to the offer
-       to distribute corresponding source code.  (This alternative is
-       allowed only for noncommercial distribution and only if you
-       received the program in object code or executable form with such
-       an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-'''4.''' You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-'''5.''' You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-'''6.''' Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-'''7.''' If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-'''8.''' If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-'''9.''' The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-'''10.''' If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-=== NO WARRANTY ===
-
-'''11.''' BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-'''12.''' IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-       '''END OF TERMS AND CONDITIONS'''
-
-== How to Apply These Terms to Your New Programs ==
-
-If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-       <one line to give the program's name and a brief idea of what it does.>
-
-       Copyright (C) <year>  <name of author>
-
-       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
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-       Gnomovision version 69, Copyright (C) year name of author
-       Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-       This is free software, and you are welcome to redistribute it
-       under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-       Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-       `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-       <signature of Ty Coon>, 1 April 1989
-
-       Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/skins/MonoBook/IE60Fixes.css b/skins/MonoBook/IE60Fixes.css
deleted file mode 100644 (file)
index cd9399f..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/* 6.0 - only fixes */
-/* content area */
-/* workaround for various ie float bugs */
-div#column-content {
-       float: none;
-       margin-left: 0;
-       height: 1%;
-}
-
-div#column-content div#content {
-       margin-left: 12.2em;
-       margin-top: 3em;
-       height: 1%;
-}
-
-.rtl div#column-content div#content {
-       margin-right: 12.2em;
-       margin-left: 0;
-}
-
-div#column-one {
-       position: absolute;
-       top: 0;
-       left: 0;
-       z-index: 4;
-}
-
-.rtl div#column-one {
-       left: auto;
-       right: 0;
-}
-
-div#footer {
-       margin-left: 13.6em;
-       border-left: 1px solid #fabd23;
-}
-
-.rtl div#footer {
-       margin-left: 0;
-       margin-right: 13.6em;
-       border-left: none;
-       border-right: 1px solid #fabd23;
-}
-
-/* float/negative margin brokenness */
-* html div#footer {
-       margin-top: 0;
-}
-
-* html div#column-content {
-       display: inline;
-       margin-bottom: 0;
-}
-
-/* the tabs */
-
-#p-cactions {
-       z-index: 3;
-}
-
-#p-cactions li {
-       padding-bottom: 0 !important;
-       border: none;
-       background-color: transparent;
-       cursor: default;
-       float: none !important;
-}
-
-#p-cactions li a {
-       display: inline-block !important;
-       vertical-align: top;
-       padding-bottom: 0;
-       border: solid #aaa;
-       border-width: 1px 1px 0;
-}
-
-#p-cactions li.selected a {
-       border-color: #fabd23;
-       padding-bottom: 0.17em;
-}
-
-#p-cactions li a:hover {
-       padding-bottom: 0.17em;
-}
-
-#p-navigation a {
-       display: inline-block;
-       width: 100%;
-}
-
-#portal-personaltools {
-       padding-bottom: 0.1em;
-}
-
-.rtl a.feedlink {
-       background-position: right;
-       padding-right: 0;
-       padding-left: 16px;
-}
-
-/* show the hand */
-#p-logo a,
-#p-logo a:hover {
-       cursor: pointer;
-}
-
-div.visualClear {
-       width: 100%;
-       line-height: 0;
-}
-
-textarea {
-       width: 96%;
-}
-
-#catlinks,
-div.tright,
-div.tleft {
-       position: relative;
-}
-
-/* bug 12846 */
-body.rtl #preftoc a, body.rtl #preftoc a:active {
-       float: left;
-}
diff --git a/skins/MonoBook/IE70Fixes.css b/skins/MonoBook/IE70Fixes.css
deleted file mode 100644 (file)
index 42f9ce6..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* 7.0 - only fixes */
-/* content area */
-/* workaround for various ie float bugs */
-
-/* This bit is needed to make links clickable... WTF */
-div#column-content div#content {
-       margin-left: 12.2em;
-       margin-top: 3em;
-       height: 1%;
-}
-
-.rtl div#column-content div#content {
-       margin-right: 12.2em;
-       margin-left: 0;
-}
-
-.rtl div#column-one {
-       /* For some reason it tries to inherit the padding-top into every div,
-        * and I can't figure out how to get it back off.
-        * Margin works correctly for this use, though.
-        */
-       padding-top: 0;
-       margin-top: 160px;
-}
-
-/* These elements also have padding-left: 20px; in main.css, but in RTL mode this is flipped.
- * That's good in normal browsers, but in IE7 it needs to not be flipped for some daft reason.
- * Also clear the right margin (originally margin-left: 1em)
- */
-li#pt-userpage, li#pt-anonuserpage, li#pt-login {
-       padding-left: 20px;
-       margin-right: 0;
-}
-
-.rtl a.feedlink {
-       background-position: right;
-       padding-right: 0;
-       padding-left: 16px;
-}
-
-/* the tabs */
-
-#p-cactions {
-       z-index: 3;
-}
-
-#p-cactions li {
-       padding-bottom: 0 !important;
-       border: none;
-       background-color: transparent;
-       cursor: default;
-       float: none !important;
-}
-
-#p-cactions li a {
-       display: inline-block !important;
-       vertical-align: top;
-       padding-bottom: 0;
-       border: solid #aaa;
-       border-width: 1px 1px 0;
-}
-
-#p-cactions li.selected a {
-       border-color: #fabd23;
-       padding-bottom: 0.17em;
-}
-
-#p-cactions li a:hover {
-       padding-bottom: 0.17em;
-}
-
-#p-navigation a {
-       display: inline-block;
-       width: 100%;
-}
-
-#portal-personaltools {
-       padding-bottom: 0.1em;
-}
-
-textarea {
-       width: 96%;
-}
-
-/*
-#catlinks,
-div.tright,
-div.tleft {
-       position: relative;
-}
-*/
-
-div#footer li {
-       /* Work around bug with inline <li> tags with right margins and nowrap */
-       margin-right: 0;
-}
diff --git a/skins/MonoBook/MonoBook.php b/skins/MonoBook/MonoBook.php
deleted file mode 100644 (file)
index 97c0cd8..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-/**
- * MonoBook nouveau.
- *
- * Translated from gwicke's previous TAL template version to remove
- * dependency on PHPTAL.
- *
- * 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 Skins
- */
-
-$wgExtensionCredits['skin'][] = array(
-       'path' => __FILE__,
-       'name' => 'MonoBook',
-       'namemsg' => 'skinname-monobook',
-       'descriptionmsg' => 'monobook-desc',
-       'url' => 'https://www.mediawiki.org/wiki/Skin:MonoBook',
-       'author' => array( 'Gabriel Wicke', '...' ),
-       'license-name' => 'GPLv2+',
-);
-
-// Register files
-$wgAutoloadClasses['SkinMonoBook'] = __DIR__ . '/SkinMonoBook.php';
-$wgAutoloadClasses['MonoBookTemplate'] = __DIR__ . '/MonoBookTemplate.php';
-$wgMessagesDirs['MonoBook'] = __DIR__ . '/i18n';
-
-// Register skin
-$wgValidSkinNames['monobook'] = 'MonoBook';
-
-// Register modules
-$wgResourceModules['skins.monobook.styles'] = array(
-       'styles' => array(
-               'main.css' => array( 'media' => 'screen' ),
-       ),
-       'remoteSkinPath' => 'MonoBook',
-       'localBasePath' => __DIR__,
-);
diff --git a/skins/MonoBook/MonoBookTemplate.php b/skins/MonoBook/MonoBookTemplate.php
deleted file mode 100644 (file)
index 373c004..0000000
+++ /dev/null
@@ -1,380 +0,0 @@
-<?php
-/**
- * MonoBook nouveau.
- *
- * Translated from gwicke's previous TAL template version to remove
- * dependency on PHPTAL.
- *
- * 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 Skins
- */
-
-/**
- * @ingroup Skins
- */
-class MonoBookTemplate extends BaseTemplate {
-
-       /**
-        * Template filter callback for MonoBook skin.
-        * Takes an associative array of data set from a SkinTemplate-based
-        * class, and a wrapper for MediaWiki's localization database, and
-        * outputs a formatted page.
-        *
-        * @access private
-        */
-       function execute() {
-               // Suppress warnings to prevent notices about missing indexes in $this->data
-               wfSuppressWarnings();
-
-               $this->html( 'headelement' );
-               ?><div id="globalWrapper">
-               <div id="column-content">
-                       <div id="content" class="mw-body-primary" role="main">
-                               <a id="top"></a>
-                               <?php
-                               if ( $this->data['sitenotice'] ) {
-                                       ?>
-                                       <div id="siteNotice"><?php
-                                       $this->html( 'sitenotice' )
-                                       ?></div><?php
-                               }
-                               ?>
-
-                               <h1 id="firstHeading" class="firstHeading" lang="<?php
-                               $this->data['pageLanguage'] =
-                                       $this->getSkin()->getTitle()->getPageViewLanguage()->getHtmlCode();
-                               $this->text( 'pageLanguage' );
-                               ?>"><span dir="auto"><?php $this->html( 'title' ) ?></span></h1>
-
-                               <div id="bodyContent" class="mw-body">
-                                       <div id="siteSub"><?php $this->msg( 'tagline' ) ?></div>
-                                       <div id="contentSub"<?php
-                                       $this->html( 'userlangattributes' ) ?>><?php $this->html( 'subtitle' )
-                                               ?></div>
-                                       <?php if ( $this->data['undelete'] ) { ?>
-                                               <div id="contentSub2"><?php $this->html( 'undelete' ) ?></div>
-                                       <?php
-}
-                                       ?><?php
-                                       if ( $this->data['newtalk'] ) {
-                                               ?>
-                                               <div class="usermessage"><?php $this->html( 'newtalk' ) ?></div>
-                                       <?php
-                                       }
-                                       ?>
-                                       <div id="jump-to-nav" class="mw-jump"><?php
-                                               $this->msg( 'jumpto' )
-                                               ?> <a href="#column-one"><?php
-                                                       $this->msg( 'jumptonavigation' )
-                                                       ?></a><?php
-                                               $this->msg( 'comma-separator' )
-                                               ?><a href="#searchInput"><?php
-                                                       $this->msg( 'jumptosearch' )
-                                                       ?></a></div>
-
-                                       <!-- start content -->
-                                       <?php $this->html( 'bodytext' ) ?>
-                                       <?php
-                                       if ( $this->data['catlinks'] ) {
-                                               $this->html( 'catlinks' );
-                                       }
-                                       ?>
-                                       <!-- end content -->
-                                       <?php
-                                       if ( $this->data['dataAfterContent'] ) {
-                                               $this->html( 'dataAfterContent'
-                                               );
-                                       }
-                                       ?>
-                                       <div class="visualClear"></div>
-                               </div>
-                       </div>
-               </div>
-               <div id="column-one"<?php $this->html( 'userlangattributes' ) ?>>
-                       <h2><?php $this->msg( 'navigation-heading' ) ?></h2>
-                       <?php $this->cactions(); ?>
-                       <div class="portlet" id="p-personal" role="navigation">
-                               <h3><?php $this->msg( 'personaltools' ) ?></h3>
-
-                               <div class="pBody">
-                                       <ul<?php $this->html( 'userlangattributes' ) ?>>
-                                               <?php foreach ( $this->getPersonalTools() as $key => $item ) { ?>
-                                                       <?php echo $this->makeListItem( $key, $item ); ?>
-
-                                               <?php
-}
-                                               ?>
-                                       </ul>
-                               </div>
-                       </div>
-                       <div class="portlet" id="p-logo" role="banner">
-                               <?php
-                               echo Html::element( 'a', array(
-                                               'href' => $this->data['nav_urls']['mainpage']['href'],
-                                               'style' => "background-image: url({$this->data['logopath']});" )
-                                       + Linker::tooltipAndAccesskeyAttribs( 'p-logo' ) ); ?>
-
-                       </div>
-                       <?php
-                       $this->renderPortals( $this->data['sidebar'] );
-                       ?>
-               </div><!-- end of the left (by default at least) column -->
-               <div class="visualClear"></div>
-               <?php
-               $validFooterIcons = $this->getFooterIcons( "icononly" );
-               $validFooterLinks = $this->getFooterLinks( "flat" ); // Additional footer links
-
-               if ( count( $validFooterIcons ) + count( $validFooterLinks ) > 0 ) {
-                       ?>
-                       <div id="footer" role="contentinfo"<?php $this->html( 'userlangattributes' ) ?>>
-                       <?php
-                       $footerEnd = '</div>';
-               } else {
-                       $footerEnd = '';
-               }
-
-               foreach ( $validFooterIcons as $blockName => $footerIcons ) {
-                       ?>
-                       <div id="f-<?php echo htmlspecialchars( $blockName ); ?>ico">
-                               <?php foreach ( $footerIcons as $icon ) { ?>
-                                       <?php echo $this->getSkin()->makeFooterIcon( $icon ); ?>
-
-                               <?php
-}
-                               ?>
-                       </div>
-               <?php
-               }
-
-               if ( count( $validFooterLinks ) > 0 ) {
-                       ?>
-                       <ul id="f-list">
-                               <?php
-                               foreach ( $validFooterLinks as $aLink ) {
-                                       ?>
-                                       <li id="<?php echo $aLink ?>"><?php $this->html( $aLink ) ?></li>
-                               <?php
-                               }
-                               ?>
-                       </ul>
-               <?php
-               }
-
-               echo $footerEnd;
-               ?>
-
-               </div>
-               <?php
-               $this->printTrail();
-               echo Html::closeElement( 'body' );
-               echo Html::closeElement( 'html' );
-               wfRestoreWarnings();
-       } // end of execute() method
-
-       /*************************************************************************************************/
-
-       /**
-        * @param array $sidebar
-        */
-       protected function renderPortals( $sidebar ) {
-               if ( !isset( $sidebar['SEARCH'] ) ) {
-                       $sidebar['SEARCH'] = true;
-               }
-               if ( !isset( $sidebar['TOOLBOX'] ) ) {
-                       $sidebar['TOOLBOX'] = true;
-               }
-               if ( !isset( $sidebar['LANGUAGES'] ) ) {
-                       $sidebar['LANGUAGES'] = true;
-               }
-
-               foreach ( $sidebar as $boxName => $content ) {
-                       if ( $content === false ) {
-                               continue;
-                       }
-
-                       if ( $boxName == 'SEARCH' ) {
-                               $this->searchBox();
-                       } elseif ( $boxName == 'TOOLBOX' ) {
-                               $this->toolbox();
-                       } elseif ( $boxName == 'LANGUAGES' ) {
-                               $this->languageBox();
-                       } else {
-                               $this->customBox( $boxName, $content );
-                       }
-               }
-       }
-
-       function searchBox() {
-               global $wgUseTwoButtonsSearchForm;
-               ?>
-               <div id="p-search" class="portlet" role="search">
-                       <h3><label for="searchInput"><?php $this->msg( 'search' ) ?></label></h3>
-
-                       <div id="searchBody" class="pBody">
-                               <form action="<?php $this->text( 'wgScript' ) ?>" id="searchform">
-                                       <input type='hidden' name="title" value="<?php $this->text( 'searchtitle' ) ?>"/>
-                                       <?php echo $this->makeSearchInput( array( "id" => "searchInput" ) ); ?>
-
-                                       <?php
-                                       echo $this->makeSearchButton(
-                                               "go",
-                                               array( "id" => "searchGoButton", "class" => "searchButton" )
-                                       );
-
-                                       if ( $wgUseTwoButtonsSearchForm ) {
-                                               ?>&#160;
-                                               <?php echo $this->makeSearchButton(
-                                                       "fulltext",
-                                                       array( "id" => "mw-searchButton", "class" => "searchButton" )
-                                               );
-                                       } else {
-                                               ?>
-
-                                               <div><a href="<?php
-                                               $this->text( 'searchaction' )
-                                               ?>" rel="search"><?php $this->msg( 'powersearch-legend' ) ?></a></div><?php
-                                       } ?>
-
-                               </form>
-
-                               <?php $this->renderAfterPortlet( 'search' ); ?>
-                       </div>
-               </div>
-       <?php
-       }
-
-       /**
-        * Prints the cactions bar.
-        * Shared between MonoBook and Modern
-        */
-       function cactions() {
-               ?>
-               <div id="p-cactions" class="portlet" role="navigation">
-                       <h3><?php $this->msg( 'views' ) ?></h3>
-
-                       <div class="pBody">
-                               <ul><?php
-                                       foreach ( $this->data['content_actions'] as $key => $tab ) {
-                                               echo '
-                               ' . $this->makeListItem( $key, $tab );
-                                       } ?>
-
-                               </ul>
-                               <?php $this->renderAfterPortlet( 'cactions' ); ?>
-                       </div>
-               </div>
-       <?php
-       }
-
-       /*************************************************************************************************/
-       function toolbox() {
-               ?>
-               <div class="portlet" id="p-tb" role="navigation">
-                       <h3><?php $this->msg( 'toolbox' ) ?></h3>
-
-                       <div class="pBody">
-                               <ul>
-                                       <?php
-                                       foreach ( $this->getToolbox() as $key => $tbitem ) {
-                                               ?>
-                                               <?php echo $this->makeListItem( $key, $tbitem ); ?>
-
-                                       <?php
-                                       }
-                                       wfRunHooks( 'MonoBookTemplateToolboxEnd', array( &$this ) );
-                                       wfRunHooks( 'SkinTemplateToolboxEnd', array( &$this, true ) );
-                                       ?>
-                               </ul>
-                               <?php $this->renderAfterPortlet( 'tb' ); ?>
-                       </div>
-               </div>
-       <?php
-       }
-
-       /*************************************************************************************************/
-       function languageBox() {
-               if ( $this->data['language_urls'] !== false ) {
-                       ?>
-                       <div id="p-lang" class="portlet" role="navigation">
-                               <h3<?php $this->html( 'userlangattributes' ) ?>><?php $this->msg( 'otherlanguages' ) ?></h3>
-
-                               <div class="pBody">
-                                       <ul>
-                                               <?php foreach ( $this->data['language_urls'] as $key => $langlink ) { ?>
-                                                       <?php echo $this->makeListItem( $key, $langlink ); ?>
-
-                                               <?php
-}
-                                               ?>
-                                       </ul>
-
-                                       <?php $this->renderAfterPortlet( 'lang' ); ?>
-                               </div>
-                       </div>
-               <?php
-               }
-       }
-
-       /*************************************************************************************************/
-       /**
-        * @param string $bar
-        * @param array|string $cont
-        */
-       function customBox( $bar, $cont ) {
-               $portletAttribs = array(
-                       'class' => 'generated-sidebar portlet',
-                       'id' => Sanitizer::escapeId( "p-$bar" ),
-                       'role' => 'navigation'
-               );
-
-               $tooltip = Linker::titleAttrib( "p-$bar" );
-               if ( $tooltip !== false ) {
-                       $portletAttribs['title'] = $tooltip;
-               }
-               echo '  ' . Html::openElement( 'div', $portletAttribs );
-               $msgObj = wfMessage( $bar );
-               ?>
-
-               <h3><?php echo htmlspecialchars( $msgObj->exists() ? $msgObj->text() : $bar ); ?></h3>
-               <div class='pBody'>
-                       <?php
-                       if ( is_array( $cont ) ) {
-                               ?>
-                               <ul>
-                                       <?php
-                                       foreach ( $cont as $key => $val ) {
-                                               ?>
-                                               <?php echo $this->makeListItem( $key, $val ); ?>
-
-                                       <?php
-                                       }
-                                       ?>
-                               </ul>
-                       <?php
-                       } else {
-                               # allow raw HTML block to be defined by extensions
-                               print $cont;
-                       }
-
-                       $this->renderAfterPortlet( $bar );
-                       ?>
-               </div>
-               </div>
-       <?php
-       }
-} // end of class
diff --git a/skins/MonoBook/SkinMonoBook.php b/skins/MonoBook/SkinMonoBook.php
deleted file mode 100644 (file)
index 16fbd00..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-/**
- * MonoBook nouveau.
- *
- * Translated from gwicke's previous TAL template version to remove
- * dependency on PHPTAL.
- *
- * 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 Skins
- */
-
-/**
- * Inherit main code from SkinTemplate, set the CSS and template filter.
- * @ingroup Skins
- */
-class SkinMonoBook extends SkinTemplate {
-       /** Using MonoBook. */
-       public $skinname = 'monobook';
-       public $stylename = 'MonoBook';
-       public $template = 'MonoBookTemplate';
-
-       /**
-        * @param OutputPage $out
-        */
-       function setupSkinUserCss( OutputPage $out ) {
-               parent::setupSkinUserCss( $out );
-
-               $out->addModuleStyles( array( 'mediawiki.skinning.interface', 'skins.monobook.styles' ) );
-
-               // TODO: Migrate all of these
-               $out->addStyle( $this->stylename . '/IE60Fixes.css', 'screen', 'IE 6' );
-               $out->addStyle( $this->stylename . '/IE70Fixes.css', 'screen', 'IE 7' );
-       }
-}
diff --git a/skins/MonoBook/audio.png b/skins/MonoBook/audio.png
deleted file mode 100644 (file)
index 68c8768..0000000
Binary files a/skins/MonoBook/audio.png and /dev/null differ
diff --git a/skins/MonoBook/bullet.gif b/skins/MonoBook/bullet.gif
deleted file mode 100644 (file)
index b43de48..0000000
Binary files a/skins/MonoBook/bullet.gif and /dev/null differ
diff --git a/skins/MonoBook/discussionitem_icon.gif b/skins/MonoBook/discussionitem_icon.gif
deleted file mode 100644 (file)
index e3ca6d9..0000000
Binary files a/skins/MonoBook/discussionitem_icon.gif and /dev/null differ
diff --git a/skins/MonoBook/document.png b/skins/MonoBook/document.png
deleted file mode 100644 (file)
index ee46a50..0000000
Binary files a/skins/MonoBook/document.png and /dev/null differ
diff --git a/skins/MonoBook/external-ltr.png b/skins/MonoBook/external-ltr.png
deleted file mode 100644 (file)
index 6308383..0000000
Binary files a/skins/MonoBook/external-ltr.png and /dev/null differ
diff --git a/skins/MonoBook/external-rtl.png b/skins/MonoBook/external-rtl.png
deleted file mode 100644 (file)
index 5313234..0000000
Binary files a/skins/MonoBook/external-rtl.png and /dev/null differ
diff --git a/skins/MonoBook/file_icon.gif b/skins/MonoBook/file_icon.gif
deleted file mode 100644 (file)
index 69dbeaf..0000000
Binary files a/skins/MonoBook/file_icon.gif and /dev/null differ
diff --git a/skins/MonoBook/headbg.jpg b/skins/MonoBook/headbg.jpg
deleted file mode 100644 (file)
index 5491c6e..0000000
Binary files a/skins/MonoBook/headbg.jpg and /dev/null differ
diff --git a/skins/MonoBook/i18n/aln.json b/skins/MonoBook/i18n/aln.json
deleted file mode 100644 (file)
index b853dde..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Bresta"
-               ]
-       },
-       "monobook.css": "/* CSS i vednosun këtu ka me i prekë shfrytëzuesit e dukjes Monobook */",
-       "monobook.js": "/* Çdo JavaScript këtu ka me u ngarkue për shfrytëzuesit që përdorin dukjen MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/an.json b/skins/MonoBook/i18n/an.json
deleted file mode 100644 (file)
index f635897..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Juanpabl"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* Os estilos CSS colocaus aquí s'aplicarán ta totz os usuarios que faigan servir l'apariencia Monobook */",
-       "monobook.js": "/* O codigo Javascript que se meta aquí será cargau por os usuarios faigan servir l'apariencia MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/ar.json b/skins/MonoBook/i18n/ar.json
deleted file mode 100644 (file)
index 05cad21..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Meno25"
-               ]
-       },
-       "skinname-monobook": "مونوبوك",
-       "monobook.css": "/* الأنماط المتراصة CSS المعروضة هنا ستؤثر على مستخدمي واجهة مونوبوك */",
-       "monobook.js": "/* أي جافاسكريبت هنا سيتم تحميلها للمستخدمين الذين يستعملون واجهة مونوبوك */"
-}
diff --git a/skins/MonoBook/i18n/arz.json b/skins/MonoBook/i18n/arz.json
deleted file mode 100644 (file)
index a49f003..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Meno25"
-               ]
-       },
-       "skinname-monobook": "مونوبوك",
-       "monobook.css": "/* الأنماط المتراصة CSS المعروضة هنا ستؤثر على مستخدمى واجهة مونوبوك */",
-       "monobook.js": "/* أى جافاسكريبت هنا ح تتحمل لليوزرز اللى بيستعملو واجهة مونوبوك */"
-}
diff --git a/skins/MonoBook/i18n/ast.json b/skins/MonoBook/i18n/ast.json
deleted file mode 100644 (file)
index d007deb..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Xuacu"
-               ]
-       },
-       "monobook.css": "/* Los CSS allugaos equí afeutarán a los usuarios del aspeutu Monobook */",
-       "monobook.js": "/* Cualesquier JavaScript que tea equí se cargará pa los usuarios del aspeutu MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/az.json b/skins/MonoBook/i18n/az.json
deleted file mode 100644 (file)
index 55b33d8..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Vago",
-                       "Vugar 1981"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* Burada yerləşən CSS Monobook skin istifadəçilərinə tətbiq olunur */",
-       "monobook.js": "/* Burada MonoBook skin istifadəçiləri üçün istənilən JavaScript yüklənəcək */"
-}
diff --git a/skins/MonoBook/i18n/bcc.json b/skins/MonoBook/i18n/bcc.json
deleted file mode 100644 (file)
index 9732382..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mostafadaneshvar"
-               ]
-       },
-       "skinname-monobook": "منوبوک",
-       "monobook.css": "/* CSS که اداننت کابران پوست مونوبوک تاثیر کننت */",
-       "monobook.js": "/* جاوا اسکریپت ادان فقط په کابرانی که چه پوست منوبوک استفاده کننت بار بیت. */"
-}
diff --git a/skins/MonoBook/i18n/bcl.json b/skins/MonoBook/i18n/bcl.json
deleted file mode 100644 (file)
index 1ef08f2..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Filipinayzd"
-               ]
-       },
-       "monobook.css": "/* an CSS na pigbugtak digdi makakaapektar sa mga parágamit kan Monobook skin */",
-       "monobook.js": "/* Deprecado; gamiton an [[MediaWiki:common.js]] */"
-}
diff --git a/skins/MonoBook/i18n/be-tarask.json b/skins/MonoBook/i18n/be-tarask.json
deleted file mode 100644 (file)
index 7704a41..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "skinname-monobook": "Монакніга"
-}
diff --git a/skins/MonoBook/i18n/be.json b/skins/MonoBook/i18n/be.json
deleted file mode 100644 (file)
index a3a20e5..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Yury Tarasievich"
-               ]
-       },
-       "skinname-monobook": "Манабук",
-       "monobook.css": "/* CSS, упісаны сюды, будзе дзейнічаць на браўзер кожнага чытача з актыўнай світай Monobook */",
-       "monobook.js": "/* Any JavaScript here will be loaded for users using the MonoBook skin */"
-}
diff --git a/skins/MonoBook/i18n/bg.json b/skins/MonoBook/i18n/bg.json
deleted file mode 100644 (file)
index f3e91dd..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-       "skinname-monobook": "Монобук",
-       "monobook.css": "/* Чрез редактиране на този файл можете да промените облика Монобук */",
-       "monobook.js": "/* Остаряла страница; използвайте [[MediaWiki:Common.js]] */"
-}
diff --git a/skins/MonoBook/i18n/bn.json b/skins/MonoBook/i18n/bn.json
deleted file mode 100644 (file)
index d6a4112..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Aftab1995"
-               ]
-       },
-       "skinname-monobook": "মনোবুক"
-}
diff --git a/skins/MonoBook/i18n/br.json b/skins/MonoBook/i18n/br.json
deleted file mode 100644 (file)
index 2ba630f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Fulup"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* Talvezout a raio ar CSS lakaet amañ evit implijerien ar gwiskadur Monobook */",
-       "monobook.js": "/* Kement JavaScript amañ a vo karget evit an implijerien a ra gant ar gwiskadur MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/bs.json b/skins/MonoBook/i18n/bs.json
deleted file mode 100644 (file)
index ddecc4c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "CERminator",
-                       "Kal-El"
-               ]
-       },
-       "skinname-monobook": "MonoKnjiga",
-       "monobook.css": "/* CSS umetnut ovdje uticat će na korisnike koji koriste Monobook skin */",
-       "monobook.js": "/* Bilo koja JavaScript će biti učitana za sve korisnike koji koriste MonoBook skin */"
-}
diff --git a/skins/MonoBook/i18n/ca.json b/skins/MonoBook/i18n/ca.json
deleted file mode 100644 (file)
index 8674693..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Martorell"
-               ]
-       },
-       "monobook.css": "/* Editeu aquest fitxer per personalitzar l'aparença del monobook per a tot el lloc sencer */"
-}
diff --git a/skins/MonoBook/i18n/ce.json b/skins/MonoBook/i18n/ce.json
deleted file mode 100644 (file)
index 61515a8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Умар"
-               ]
-       },
-       "monobook.css": "/* Чуйиллина йолу кхузе CSS хир ю лелош масхьа Monobook чохь */",
-       "monobook.js": "/* Кхузе чу язийна йолу JavaScript код, чу ера ю, массо MonoBook хатl лелош болу декъашхошна */"
-}
diff --git a/skins/MonoBook/i18n/ckb.json b/skins/MonoBook/i18n/ckb.json
deleted file mode 100644 (file)
index 2c42db2..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "skinname-monobook": "مۆنۆ"
-}
diff --git a/skins/MonoBook/i18n/crh-cyrl.json b/skins/MonoBook/i18n/crh-cyrl.json
deleted file mode 100644 (file)
index b11125e..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* monobook темасынынъ аярларыны (настройкаларыны) денъиштирмек ичюн бу ерини денъиштиринъиз. Бутюн сайтта тесирли олур. */"
-}
diff --git a/skins/MonoBook/i18n/crh-latn.json b/skins/MonoBook/i18n/crh-latn.json
deleted file mode 100644 (file)
index c8f2540..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* monobook temasınıñ ayarlarını (nastroykalarını) deñiştirmek içün bu yerini deñiştiriñiz. Bütün saytta tesirli olur. */"
-}
diff --git a/skins/MonoBook/i18n/cs.json b/skins/MonoBook/i18n/cs.json
deleted file mode 100644 (file)
index 62fcddd..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Danny B.",
-                       "Li-sung",
-                       "Mormegil"
-               ]
-       },
-       "monobook-desc": "Klasický vzhled MediaWiki od roku 2004, pojmenovaný po černobílé fotografii knihy v pozadí stránky",
-       "monobook.css": "/* Zde uvedené CSS bude ovlivňovat pouze styl „Monobook“ */",
-       "monobook.js": "/* JavaScript pro uživatele používající vzhled MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/da.json b/skins/MonoBook/i18n/da.json
deleted file mode 100644 (file)
index e20dbb6..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Peter Alberti"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/** CSS inkluderet her vil være aktivt for brugere af Monobook-temaet . */",
-       "monobook.js": "/* JavaScript i denne fil vil indlæses for brugere af udseendet MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/de.json b/skins/MonoBook/i18n/de.json
deleted file mode 100644 (file)
index 047b91d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Geitost",
-                       "Metalhead64"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook-desc": "Ergänzt die klassische MediaWiki-Benutzeroberfläche seit 2004, benannt nach dem Schwarzweißfoto eines Buches im Seitenhintergrund",
-       "monobook.css": "/* Das folgende CSS wird für Benutzer der MonoBook-Benutzeroberfläche geladen */",
-       "monobook.js": "/* Das folgende JavaScript wird für Benutzer der Monobook-Benutzeroberfläche geladen. */"
-}
diff --git a/skins/MonoBook/i18n/diq.json b/skins/MonoBook/i18n/diq.json
deleted file mode 100644 (file)
index ca9696d..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Erdemaslancan"
-               ]
-       },
-       "skinname-monobook": "MonoBook"
-}
diff --git a/skins/MonoBook/i18n/dsb.json b/skins/MonoBook/i18n/dsb.json
deleted file mode 100644 (file)
index 6731b7b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Michawiki",
-                       "Nepl1"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* How zaměstnjony CSS wustatkujo se na wužywarje monobook-šata */",
-       "monobook.js": "/* Slědujucy JavaScript zacytajo se za wužywarjow, kótarež skin MonoBook wužywaju */"
-}
diff --git a/skins/MonoBook/i18n/el.json b/skins/MonoBook/i18n/el.json
deleted file mode 100644 (file)
index 1e7f7b8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Dead3y3"
-               ]
-       },
-       "monobook.css": "/* Το τοποθετημένο εδώ CSS θα επηρεάσει χρήστες του Monobook skin */",
-       "monobook.js": "/* Οποιοσδήποτε κώδικας JavaScript εδώ θα φορτωθεί για χρήστες που χρησιμοποιούν το MonoBook skin */"
-}
diff --git a/skins/MonoBook/i18n/en.json b/skins/MonoBook/i18n/en.json
deleted file mode 100644 (file)
index 0b27e6b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": []
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook-desc": "The classic MediaWiki skin since 2004, named after the black-and-white photo of a book in the page background",
-       "monobook.css": "/* CSS placed here will affect users of the MonoBook skin */",
-       "monobook.js": "/* Any JavaScript here will be loaded for users using the MonoBook skin */"
-}
diff --git a/skins/MonoBook/i18n/eo.json b/skins/MonoBook/i18n/eo.json
deleted file mode 100644 (file)
index 170286a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Objectivesea"
-               ]
-       },
-       "skinname-monobook": "Librejo",
-       "monobook.css": "/* La jena CSS influos la paĝaspekton por uzantoj de la Libreja temo. */",
-       "monobook.js": "/* La jena Ĝavaskripto ŝargiĝos por uzantoj de la Libreja temo. */"
-}
diff --git a/skins/MonoBook/i18n/es.json b/skins/MonoBook/i18n/es.json
deleted file mode 100644 (file)
index 48d424c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Sanbec",
-                       "Vivaelcelta",
-                       "Fitoschido"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook-desc": "El tema clásico de MediaWiki desde 2004, cuyo nombre viene de la foto en blanco y negro de un libro en el fondo",
-       "monobook.css": "/* El CSS colocado en esta página afectará a los usuarios que usen la apariencia \"MonoBook\" */",
-       "monobook.js": "/* El código JavaScript que se ponga aquí será cargado por los usuarios de la apariencia MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/et.json b/skins/MonoBook/i18n/et.json
deleted file mode 100644 (file)
index 591acff..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "skinname-monobook": "MonoBook"
-}
diff --git a/skins/MonoBook/i18n/eu.json b/skins/MonoBook/i18n/eu.json
deleted file mode 100644 (file)
index a5f8c39..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "monobook.css": "/* Hemen idatzitako CSS kodeak Monobook itxuran bakarrik izango du eragina */"
-}
diff --git a/skins/MonoBook/i18n/ext.json b/skins/MonoBook/i18n/ext.json
deleted file mode 100644 (file)
index 70d9567..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "monobook.js": "/* Antigu; gasta [[MediaWiki:common.js]] */"
-}
diff --git a/skins/MonoBook/i18n/fa.json b/skins/MonoBook/i18n/fa.json
deleted file mode 100644 (file)
index 02a0185..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Reza1615"
-               ]
-       },
-       "skinname-monobook": "مونوبوک",
-       "monobook-desc": "پوسته کلاسیک مدیاویکی از سال ۲۰۰۴ از عکس سیاه و سفید در زمینه صفحه  کتاب نام گرفت",
-       "monobook.css": "/* دستورات این بخش کاربرانی را که از پوستهٔ مونوبوک استفاده کنند تحت تاثیر قرار می‌دهند. */"
-}
diff --git a/skins/MonoBook/i18n/fi.json b/skins/MonoBook/i18n/fi.json
deleted file mode 100644 (file)
index f516bdd..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Crt"
-               ]
-       },
-       "skinname-monobook": "Monobook",
-       "monobook.css": "/* Tämä sivu sisältää Monobook-ulkoasua muuttavia tyylejä. */",
-       "monobook.js": "/* Tämän sivun JavaScript-koodi liitetään Monobook-tyyliin */"
-}
diff --git a/skins/MonoBook/i18n/fr.json b/skins/MonoBook/i18n/fr.json
deleted file mode 100644 (file)
index cedbebb..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Gomoko",
-                       "Verdy p"
-               ]
-       },
-       "skinname-monobook": "Monobook",
-       "monobook-desc": "L’habillage classique de MédiaWiki depuis 2004, nommé d’après la photo en noir et blanc d’un livre dans l’arrière-plan de la page",
-       "monobook.css": "/* Le CSS placé ici affectera les utilisateurs de l’habillage Monobook. */",
-       "monobook.js": "/* Tout JavaScript ici sera chargé avec les pages accédées par les utilisateurs de l’habillage MonoBook uniquement. */"
-}
diff --git a/skins/MonoBook/i18n/frp.json b/skins/MonoBook/i18n/frp.json
deleted file mode 100644 (file)
index 06a705a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "ChrisPtDe"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* Lo code CSS betâ ique afècterat los usanciérs de l’habelyâjo « MonoBook ». */",
-       "monobook.js": "/* Tot code JavaScript betâ ique serat chargiê per los usanciérs de l’habelyâjo « MonoBook ». */"
-}
diff --git a/skins/MonoBook/i18n/fur.json b/skins/MonoBook/i18n/fur.json
deleted file mode 100644 (file)
index 87c1f2c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "monobook.css": "/* modifiche chest file par personalizâ la skin monobook par dut il sît */"
-}
diff --git a/skins/MonoBook/i18n/ga.json b/skins/MonoBook/i18n/ga.json
deleted file mode 100644 (file)
index 695a952..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* athraigh an comhad seo chun an craiceann MonoBook a athrú don suíomh ar fad */"
-}
diff --git a/skins/MonoBook/i18n/gan-hans.json b/skins/MonoBook/i18n/gan-hans.json
deleted file mode 100644 (file)
index bed9f08..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-       "monobook.css": "/* 个首𠮶 CSS 会碍到正用Monobook皮肤𠮶用户 */",
-       "monobook.js": "/* 伓再使用;请用[[MediaWiki:common.js]] */"
-}
diff --git a/skins/MonoBook/i18n/gan-hant.json b/skins/MonoBook/i18n/gan-hant.json
deleted file mode 100644 (file)
index 4c98663..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-       "monobook.css": "/* 箇首嗰 CSS 會礙到正用Monobook皮膚嗰用戶 */",
-       "monobook.js": "/* 伓再使用;請用[[MediaWiki:common.js]] */"
-}
diff --git a/skins/MonoBook/i18n/gd.json b/skins/MonoBook/i18n/gd.json
deleted file mode 100644 (file)
index f5bd154..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "GunChleoc"
-               ]
-       },
-       "monobook-desc": "Craiceann MediaWiki clasaigeach o 2004 a chaidh ainmeachadh a-rèir dealbh de leabhar ann an dubh 's geal air cùlaibh nan duilleagan"
-}
diff --git a/skins/MonoBook/i18n/gl.json b/skins/MonoBook/i18n/gl.json
deleted file mode 100644 (file)
index 2e61ad3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Toliño",
-                       "Xosé"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* O CSS que se coloque aquí afectará a quen use a aparencia Monobook */",
-       "monobook.js": "/* Calquera JavaScript que haxa aquí será cargado para os usuarios que usen a aparencia MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/hak.json b/skins/MonoBook/i18n/hak.json
deleted file mode 100644 (file)
index 3253509..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Hakka"
-               ]
-       },
-       "monobook.css": "/* Chhṳ́-chhu ke CSS chiông-voi yáng-hióng sṳ́-yung Monobook mien-pán ke yung-fu */",
-       "monobook.js": "/* Yí-kîn put-chai sṳ́-yung; chhiáng-yung [[MediaWiki:common.js]] */"
-}
diff --git a/skins/MonoBook/i18n/he.json b/skins/MonoBook/i18n/he.json
deleted file mode 100644 (file)
index 89bfb40..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Rotemliss"
-               ]
-       },
-       "skinname-monobook": "מונובוק",
-       "monobook.css": "/* הסגנונות הנכתבים כאן ישפיעו על העיצוב MonoBook בלבד */",
-       "monobook.js": "/* כל סקריפט JavaScript שנכתב כאן ירוץ רק עבור המשתמשים בעיצוב Monobook */"
-}
diff --git a/skins/MonoBook/i18n/hi.json b/skins/MonoBook/i18n/hi.json
deleted file mode 100644 (file)
index 33e527b..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kaustubh",
-                       "Siddhartha Ghai"
-               ]
-       },
-       "monobook.css": "/* यहां रखी गई css मोनोबुक त्वचा का इस्तेमाल करने वाले सभी सदस्योंपर असर करेगी */",
-       "monobook.js": "/* यहाँ पर दी गई जावास्क्रिप्ट मोनोबुक त्वचा का प्रयोग कर रहे सदस्यों के लिए लोड होगी */"
-}
diff --git a/skins/MonoBook/i18n/hr.json b/skins/MonoBook/i18n/hr.json
deleted file mode 100644 (file)
index a56acbd..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/** Ovdje idu izmjene monobook stylesheeta */",
-       "monobook.js": "/* Ne rabi se više; molimo rabite [[MediaWiki:common.js]] */"
-}
diff --git a/skins/MonoBook/i18n/hsb.json b/skins/MonoBook/i18n/hsb.json
deleted file mode 100644 (file)
index 2ac24c7..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Michawiki"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* CSS wobdźěłać, zo by so skin „monobook” za wšěčh wužiwarjow tutoho skina priměrił */",
-       "monobook.js": "/* Slědowacy JavaScript začita so za wužiwarjow, kotřiž šat MonoBook wužiwaja */"
-}
diff --git a/skins/MonoBook/i18n/hu.json b/skins/MonoBook/i18n/hu.json
deleted file mode 100644 (file)
index 07e3a10..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Dani"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* Az ide elhelyezett CSS hatással lesz a Monobook felület használóira */",
-       "monobook.js": "/* A Monobook felületet használó szerkesztők számára betöltendő JavaScriptek */"
-}
diff --git a/skins/MonoBook/i18n/hy.json b/skins/MonoBook/i18n/hy.json
deleted file mode 100644 (file)
index db1d72e..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Teak"
-               ]
-       },
-       "skinname-monobook": "ՄիաԳիրք",
-       "monobook.css": "/* Այստեղ տեղադրված CSS կոդը կկիրառվի Monobook տեսքի վրա*/",
-       "monobook.js": "/* Հնացած է. օգտագործեք [[MediaWiki:common.js]] */"
-}
diff --git a/skins/MonoBook/i18n/ia.json b/skins/MonoBook/i18n/ia.json
deleted file mode 100644 (file)
index 39a703c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "McDutchie"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook-desc": "Le apparentia classic de MediaWiki depost 2004, nominate assi pro le imagine in nigro e blanco (\"mono\") de un libro (\"book\") in le fundo del pagina.",
-       "monobook.css": "/* Le CSS placiate hic afficera le usatores del apparentia MonoBook */",
-       "monobook.js": "/* Omne JavaScript hic se executara pro le usatores del apparentia MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/id.json b/skins/MonoBook/i18n/id.json
deleted file mode 100644 (file)
index 83ce352..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Iwan Novirion",
-                       "Rex"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* CSS yang ada di sini akan diterapkan pada kulit Monobook. */",
-       "monobook.js": "/* Semua JavaScript di sini akan dimuatkan untuk para pengguna yang menggunakan kulit MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/is.json b/skins/MonoBook/i18n/is.json
deleted file mode 100644 (file)
index 1539ae1..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "לערי ריינהארט"
-               ]
-       },
-       "skinname-monobook": "EinBók",
-       "monobook.css": "/* Það sem sett er hingað er bætt við Monobook stilsniðið fyrir allan vefinn */"
-}
diff --git a/skins/MonoBook/i18n/it.json b/skins/MonoBook/i18n/it.json
deleted file mode 100644 (file)
index ba87cd9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Beta16",
-                       "Darth Kule"
-               ]
-       },
-       "monobook-desc": "La skin classica di MediaWiki dal 2004, prende il nome dall'immagine in bianco e nero del libro usata come sfondo della pagina",
-       "monobook.css": "/* Gli stili CSS inseriti qui si applicano agli utenti che usano la skin Monobook */",
-       "monobook.js": "/* Il codice JavaScript inserito qui viene caricato dagli utenti che usano la skin MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/ja.json b/skins/MonoBook/i18n/ja.json
deleted file mode 100644 (file)
index dddc9f8..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Fryed-peach",
-                       "青子守歌"
-               ]
-       },
-       "skinname-monobook": "モノブック",
-       "monobook.css": "/* ここに記述したCSSはモノブック外装の利用者に影響します */",
-       "monobook.js": "/* ここにあるすべてのJavaScriptは、モノブック外装を使用している利用者に対して読み込まれます */"
-}
diff --git a/skins/MonoBook/i18n/ka.json b/skins/MonoBook/i18n/ka.json
deleted file mode 100644 (file)
index 0b16b54..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Alsandro",
-                       "David1010"
-               ]
-       },
-       "skinname-monobook": "მონობუკი",
-       "monobook.css": "/* აქ ჩასმული CSS გავლენას იქონიებს Monobook ინტერფეისის მომხმარებლებზე */"
-}
diff --git a/skins/MonoBook/i18n/kk-arab.json b/skins/MonoBook/i18n/kk-arab.json
deleted file mode 100644 (file)
index d37e014..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-       "skinname-monobook": "دارا كىتاپ (monobook)",
-       "monobook.css": "/* مىندا ورنالاستىرىلعان CSS تەك «دارا كىتاپ» (monobook) مانەرىن پايدالانۋشىلارىنا ىقپال ەتەدى */",
-       "monobook.js": "/* مىنداعى JavaScript تەك «دارا كىتاپ» (monobook) مانەرىن پايدالانۋشىلار ٴۇشىن جەگىلەدى */"
-}
diff --git a/skins/MonoBook/i18n/kk-cyrl.json b/skins/MonoBook/i18n/kk-cyrl.json
deleted file mode 100644 (file)
index c964423..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Arystanbek"
-               ]
-       },
-       "skinname-monobook": "Жеке кітап (monobook)",
-       "monobook.css": "/* Мында орналастырылған CSS тек «Дара кітап» (monobook) мәнерін пайдаланушыларына ықпал етеді */",
-       "monobook.js": "/* Мындағы JavaScript тек «Дара кітап» (monobook) мәнерін пайдаланушылар үшін жегіледі */"
-}
diff --git a/skins/MonoBook/i18n/kk-latn.json b/skins/MonoBook/i18n/kk-latn.json
deleted file mode 100644 (file)
index 1bc6f64..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-       "skinname-monobook": "Dara kitap (monobook)",
-       "monobook.css": "/* Mında ornalastırılğan CSS tek «Dara kitap» (monobook) mänerin paýdalanwşılarına ıqpal etedi */",
-       "monobook.js": "/* Mındağı JavaScript tek «Dara kitap» (monobook) mänerin paýdalanwşılar üşin jegiledi */"
-}
diff --git a/skins/MonoBook/i18n/km.json b/skins/MonoBook/i18n/km.json
deleted file mode 100644 (file)
index 162e5a8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "វ័ណថារិទ្ធ"
-               ]
-       },
-       "skinname-monobook": "សៀវភៅឯក",
-       "monobook.css": "/* CSS បានដាក់ទីនេះនឹងមានអនុភាពលើអ្នកប្រើប្រាស់នៃសំបក Monobook */"
-}
diff --git a/skins/MonoBook/i18n/ko.json b/skins/MonoBook/i18n/ko.json
deleted file mode 100644 (file)
index 08886f4..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "아라"
-               ]
-       },
-       "skinname-monobook": "모노북",
-       "monobook-desc": "문서 배경에서 책의 흑백 사진을 이른, 2004년 이후의 고전 미디어위키 스킨",
-       "monobook.css": "/* 이 CSS 설정은 모노북 스킨을 사용하는 사용자에게 적용됩니다 */",
-       "monobook.js": "/* 이 자바스크립트 설정은 모노북 스킨을 사용하는 사용자에게 적용됩니다 */"
-}
diff --git a/skins/MonoBook/i18n/krc.json b/skins/MonoBook/i18n/krc.json
deleted file mode 100644 (file)
index 2ec1410..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Къарачайлы"
-               ]
-       },
-       "skinname-monobook": "Моно-китаб"
-}
diff --git a/skins/MonoBook/i18n/ksh.json b/skins/MonoBook/i18n/ksh.json
deleted file mode 100644 (file)
index 6c8c810..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Purodha"
-               ]
-       },
-       "skinname-monobook": "MonoBoch",
-       "monobook.css": "/* CSS heh aan dä Stell wirrek nur op de Ovverflääsch „Monobooch“ */",
-       "monobook.js": "/* De JavaSkrippte fun hee krijje alle Sigge met de Ovverflääsch \"Monnobooch\" jescheck */"
-}
diff --git a/skins/MonoBook/i18n/ku-latn.json b/skins/MonoBook/i18n/ku-latn.json
deleted file mode 100644 (file)
index 7fb824a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Krinkle"
-               ]
-       },
-       "monobook.css": "/* CSS placed here will affect users of the Monobook skin */"
-}
diff --git a/skins/MonoBook/i18n/lb.json b/skins/MonoBook/i18n/lb.json
deleted file mode 100644 (file)
index 95ba71a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Robby"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook-desc": "De klassesche Look vu MediaWiki zanter 2004, benannt no der Schwaarzwäissfoto vun engem Buch am Hannergrond vun der Säit",
-       "monobook.css": "/* Dës CSS huet nëmmen Afloss op de Skin ''Monobook''  */"
-}
diff --git a/skins/MonoBook/i18n/lt.json b/skins/MonoBook/i18n/lt.json
deleted file mode 100644 (file)
index 82ba416..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Garas"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* Čia įdėtas CSS bus rodomas Monobook išvaizdos naudotojams */",
-       "monobook.js": "/* Šis JavaScript bus įkeltas tik „MonoBook“ išvaizdos naudotojams. */"
-}
diff --git a/skins/MonoBook/i18n/lzh.json b/skins/MonoBook/i18n/lzh.json
deleted file mode 100644 (file)
index fd50ed7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-       "skinname-monobook": "單書",
-       "monobook.css": "/* 此之 CSS 用於單書面之簿也 */",
-       "monobook.js": "/* 此之JavaScript將載於用單書面之簿 */"
-}
diff --git a/skins/MonoBook/i18n/mg.json b/skins/MonoBook/i18n/mg.json
deleted file mode 100644 (file)
index ed7db66..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "monobook.css": "/* Ovay ity rakitra ity raha hampiasa takilan'angaly (stylesheet) anao manokana amin'ny wiki iray manontolo */"
-}
diff --git a/skins/MonoBook/i18n/min.json b/skins/MonoBook/i18n/min.json
deleted file mode 100644 (file)
index 2eb9001..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Iwan Novirion"
-               ]
-       },
-       "skinname-monobook": "MonoBook"
-}
diff --git a/skins/MonoBook/i18n/mk.json b/skins/MonoBook/i18n/mk.json
deleted file mode 100644 (file)
index be8e280..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Bjankuloski06"
-               ]
-       },
-       "skinname-monobook": "Монобук",
-       "monobook-desc": "Класичното руво на МедијаВики од 2004 г., наречена по црнобелата слика на книга во позадината",
-       "monobook.css": "/* Тука поставениот CSS ќе се применува врз корисниците на рувото „Монобук“ */",
-       "monobook.js": "/* Тука поставениот JavaScript  ќе им се вчитува на корисниците што го користат рувото „Монобук“ */"
-}
diff --git a/skins/MonoBook/i18n/ml.json b/skins/MonoBook/i18n/ml.json
deleted file mode 100644 (file)
index 606cf6c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Praveenp"
-               ]
-       },
-       "skinname-monobook": "മോണോബുക്ക്",
-       "monobook.css": "/* ഇവിടെ നൽകുന്ന സി.എസ്.എസ്. മോണോബുക്ക് ദൃശ്യരൂപം ഉപയോഗിക്കുന്നവർക്ക് ബാധകമായിരിക്കും */",
-       "monobook.js": "/* ഇവിടെ നൽകുന്ന ജാവാസ്ക്രിപ്റ്റ് മോണോബുക്ക് ദൃശ്യരൂപം ഉപയോഗിക്കുന്നവർക്ക് ബാധകമായിരിക്കും */"
-}
diff --git a/skins/MonoBook/i18n/mr.json b/skins/MonoBook/i18n/mr.json
deleted file mode 100644 (file)
index 0700112..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "skinname-monobook": "मोनोबुक"
-}
diff --git a/skins/MonoBook/i18n/ms.json b/skins/MonoBook/i18n/ms.json
deleted file mode 100644 (file)
index fa975fe..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Anakmalaysia"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* CSS yang terletak di sini akan mempengaruhi pengguna kulit Monobook */"
-}
diff --git a/skins/MonoBook/i18n/mt.json b/skins/MonoBook/i18n/mt.json
deleted file mode 100644 (file)
index 3d4a9b0..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Giangian15"
-               ]
-       },
-       "skinname-monobook": "Monobook",
-       "monobook.css": "/* CSS li tpoġġa hawnhekk se jaffetwa dawk l-utenti li jagħmlu użu mill-iskin ''Monobook'' */",
-       "monobook.js": "/* Kull ''JavaScript'' hawnhekk jiġi mniżżel għal dawk l-utenti li qegħdin jagħmlu użu mill-iskin ''Monobook'' */"
-}
diff --git a/skins/MonoBook/i18n/mwl.json b/skins/MonoBook/i18n/mwl.json
deleted file mode 100644 (file)
index 533e78a..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "skinname-monobook": "Lhibro"
-}
diff --git a/skins/MonoBook/i18n/nb.json b/skins/MonoBook/i18n/nb.json
deleted file mode 100644 (file)
index 0318b17..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-       "skinname-monobook": "Monobook",
-       "monobook.css": "/* CSS i denne fila vil gjelde alle som bruker drakta Monobook */",
-       "monobook.js": "/* Javascript i denne fila vil gjelde for brukere av drakta Monobook */"
-}
diff --git a/skins/MonoBook/i18n/nds-nl.json b/skins/MonoBook/i18n/nds-nl.json
deleted file mode 100644 (file)
index 38e52ec..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Servien"
-               ]
-       },
-       "skinname-monobook": "Monobook"
-}
diff --git a/skins/MonoBook/i18n/nds.json b/skins/MonoBook/i18n/nds.json
deleted file mode 100644 (file)
index dddb393..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "monobook.css": "/* disse Datei ännern üm de Monobook-Stilvörlaag för de ganze Siet antopassen */"
-}
diff --git a/skins/MonoBook/i18n/ne.json b/skins/MonoBook/i18n/ne.json
deleted file mode 100644 (file)
index 04516dd..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "सरोज कुमार ढकाल"
-               ]
-       },
-       "skinname-monobook": "मोनोबुक",
-       "monobook.css": "/* यहाँ राखिएको CSS ले मोनोबुक स्किनको प्रयोगकर्ताहरुलाई प्रभावित गर्ने छ  */"
-}
diff --git a/skins/MonoBook/i18n/new.json b/skins/MonoBook/i18n/new.json
deleted file mode 100644 (file)
index a16deba..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Eukesh"
-               ]
-       },
-       "monobook.css": "/* थन तःगु CSS नं मोनोबुक स्किनया छ्य्‌लामितेत असर याइ */"
-}
diff --git a/skins/MonoBook/i18n/nl.json b/skins/MonoBook/i18n/nl.json
deleted file mode 100644 (file)
index b08e117..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Siebrand",
-                       "Sjoerddebruin"
-               ]
-       },
-       "skinname-monobook": "Monobook",
-       "monobook-desc": "De klassieke MediaWiki-vormgeving sinds 2004, genoemd naar de zwart-witfoto van een boek op de achtergrond van de pagina",
-       "monobook.css": "/* CSS die hier wordt geplaatst heeft alleen invloed op de skin Monobook */",
-       "monobook.js": "/* JavaScript die hier wordt geplaatst heeft alleen invloed op gebruikers die de skin Monobook gebruiken */"
-}
diff --git a/skins/MonoBook/i18n/nn.json b/skins/MonoBook/i18n/nn.json
deleted file mode 100644 (file)
index 2655c70..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Eirik",
-                       "Frokor",
-                       "Njardarlogar"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* CSS-tekst som vert plassert her, endrar utsjånaden til sidedrakta Monobook */",
-       "monobook.js": "/* Javascript i denne fila vil gjelde for brukarar av drakta Monobook */"
-}
diff --git a/skins/MonoBook/i18n/nv.json b/skins/MonoBook/i18n/nv.json
deleted file mode 100644 (file)
index ede8a6d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "skinname-monobook": "NaaltsoosŁáa'ígíí"
-}
diff --git a/skins/MonoBook/i18n/oc.json b/skins/MonoBook/i18n/oc.json
deleted file mode 100644 (file)
index 7c1e1f8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Cedric31"
-               ]
-       },
-       "skinname-monobook": "Monobook",
-       "monobook.css": "/* Lo CSS plaçat aicí afectarà los utilizaires del skin Monobook */",
-       "monobook.js": "/* Tot JavaScript aicí serà cargat amb las paginas accedidas pels utilizaires de l’abilhatge MonoBook unicament. */"
-}
diff --git a/skins/MonoBook/i18n/os.json b/skins/MonoBook/i18n/os.json
deleted file mode 100644 (file)
index 86efc7f..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "skinname-monobook": "Моно-чиныг"
-}
diff --git a/skins/MonoBook/i18n/pa.json b/skins/MonoBook/i18n/pa.json
deleted file mode 100644 (file)
index f9e0833..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "skinname-monobook": "ਮੋਨੋਬੁੱਕ"
-}
diff --git a/skins/MonoBook/i18n/pam.json b/skins/MonoBook/i18n/pam.json
deleted file mode 100644 (file)
index 8b31a7b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "monobook.css": "/* CSS a mikabit keni miapectuan la reng gagamit king Monobook a pabalat */"
-}
diff --git a/skins/MonoBook/i18n/pdt.json b/skins/MonoBook/i18n/pdt.json
deleted file mode 100644 (file)
index 428d91c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Wikipeeta"
-               ]
-       },
-       "monobook.css": "/* CSS opp dise Sted wirtjt opp daut Monobook-Skin */",
-       "monobook.js": "/* Daut neachste JavaScript woat fe Brucka mett Monobook-Skin jelode */"
-}
diff --git a/skins/MonoBook/i18n/pl.json b/skins/MonoBook/i18n/pl.json
deleted file mode 100644 (file)
index 4c7031a..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Sp5uhe",
-                       "Matma Rex"
-               ]
-       },
-       "skinname-monobook": "Książka",
-       "monobook-desc": "Klasyczna skórka MediaWiki, stworzona w 2004 roku, nazwana od czarno-białego zdjęcia książki w tle strony",
-       "monobook.css": "/* Umieszczony tutaj kod CSS wpłynie na wygląd skórki Książka */",
-       "monobook.js": "/* Umieszczony tutaj kod JavaScript zostanie załadowany wyłącznie przez użytkowników korzystających ze skórki Książka */"
-}
diff --git a/skins/MonoBook/i18n/pms.json b/skins/MonoBook/i18n/pms.json
deleted file mode 100644 (file)
index 8910d4c..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-       "monobook.css": "/* cangé st'archivi-sì për modifiché la formatassion dël sit antregh */",
-       "monobook.js": "/* Ës messagi-sì as dovrìa pa pì dovrelo; a sò pòst ch'a dòvra [[MediaWiki:common.js]] */"
-}
diff --git a/skins/MonoBook/i18n/ps.json b/skins/MonoBook/i18n/ps.json
deleted file mode 100644 (file)
index d7ee132..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "skinname-monobook": "مونوبوک"
-}
diff --git a/skins/MonoBook/i18n/pt-br.json b/skins/MonoBook/i18n/pt-br.json
deleted file mode 100644 (file)
index b8f05f4..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* o código CSS colocado aqui terá efeito nos usuários do tema Monobook */",
-       "monobook.js": "/* Qualquer JavaScript aqui colocado afetará os usuários do skin MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/pt.json b/skins/MonoBook/i18n/pt.json
deleted file mode 100644 (file)
index 0425b83..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Hamilton Abreu",
-                       "Fúlvio"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook-desc": "A clássica skin do MediaWiki desde 2004, tendo este nome devido a uma imagem em preto-e-branco de um livro no plano de fundo da página",
-       "monobook.css": "/* Código CSS colocado aqui afectará os utilizadores do tema Monobook */",
-       "monobook.js": "/* Código Javascript colocado aqui será carregado para utilizadores do tema Monobook */"
-}
diff --git a/skins/MonoBook/i18n/qqq.json b/skins/MonoBook/i18n/qqq.json
deleted file mode 100644 (file)
index 5056ddb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Meno25",
-                       "Umherirrender",
-                       "Matma Rex"
-               ]
-       },
-       "skinname-monobook": "{{optional}}",
-       "monobook-desc": "{{desc|what=skin|name=MonoBook|url=https://www.mediawiki.org/wiki/Skin:MonoBook}}",
-       "monobook.css": "{{optional}}\nCSS applied to users using MonoBook skin.",
-       "monobook.js": "{{optional}}\nJS for users using MonoBook skin."
-}
diff --git a/skins/MonoBook/i18n/qu.json b/skins/MonoBook/i18n/qu.json
deleted file mode 100644 (file)
index 2fdb43c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "AlimanRuna"
-               ]
-       },
-       "monobook.css": "/* Kayman churasqa CSS nisqaqa Monobook qaratam hukchanqa tukuy internet tiyanapaq */",
-       "monobook.js": "/* Ima kaypi qillqamusqa JavaScript nisqa wakichi qillqapas MonoBook nisqata llamk'achiq ruraqkunapaq chaqnasqa kanqa */"
-}
diff --git a/skins/MonoBook/i18n/rm.json b/skins/MonoBook/i18n/rm.json
deleted file mode 100644 (file)
index 7eb17f7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Gion-andri"
-               ]
-       },
-       "monobook.css": "/* editescha quest file per adattar il skin momobook per l'entira pagina */",
-       "monobook.js": ""
-}
diff --git a/skins/MonoBook/i18n/ro.json b/skins/MonoBook/i18n/ro.json
deleted file mode 100644 (file)
index 2232372..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Firilacroco"
-               ]
-       },
-       "skinname-monobook": "Monobook",
-       "monobook.css": "/* modificați acest fișier pentru a adapta înfățișarea monobook-ului pentru tot situl*/"
-}
diff --git a/skins/MonoBook/i18n/roa-tara.json b/skins/MonoBook/i18n/roa-tara.json
deleted file mode 100644 (file)
index d7b52b0..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Joetaras"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* 'U CSS ca se iacchie aqquà 'u 'ndrucane le utinde d'a masckere Monobook */",
-       "monobook.js": "/* Ogne JavaScript aqquà avène carecate pe le utinde ca ausane 'a masckere MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/ru.json b/skins/MonoBook/i18n/ru.json
deleted file mode 100644 (file)
index c3b1d46..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "AlexSm",
-                       "Kaganer",
-                       "Okras"
-               ]
-       },
-       "monobook-desc": "Классическая тема оформления MediaWiki, созданная в 2004 году и названая в честь чёрно-белой фотографии книги с фонового изображения страницы",
-       "monobook.css": "/* Размещённый здесь CSS будет применяться к теме оформления Monobook */",
-       "monobook.js": "/* Размещённый здесь код JavaScript будет загружаться пользователям, использующим тему оформления MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/sa.json b/skins/MonoBook/i18n/sa.json
deleted file mode 100644 (file)
index 5f3f966..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "skinname-monobook": "पुस्तक"
-}
diff --git a/skins/MonoBook/i18n/sah.json b/skins/MonoBook/i18n/sah.json
deleted file mode 100644 (file)
index 5f3cbfc..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "HalanTul"
-               ]
-       },
-       "monobook.css": "/* Манна оҥоһуллубут CSS Monobook диэн скиҥҥа туһаныллыа */",
-       "monobook.js": "/* Эргэрбит; маны туһан:[[MediaWiki:common.js]] */"
-}
diff --git a/skins/MonoBook/i18n/scn.json b/skins/MonoBook/i18n/scn.json
deleted file mode 100644 (file)
index cba6acf..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Santu",
-                       "Sarvaturi",
-                       "Tonyfroio"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* Li stili CSS nziriti ccà s'àpplicanu a l'utenti chi usanu la skin Monobook */",
-       "monobook.js": "/* Lu còdici JavaScript nzirutu ccà veni carricatu di l'utenti c'ùsanu la skin MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/si.json b/skins/MonoBook/i18n/si.json
deleted file mode 100644 (file)
index 89a6028..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "නන්දිමිතුරු"
-               ]
-       },
-       "monobook.css": "/* මෙහි CSS  බහාලීම ඒකායන ඡවිය භාවිතා කරන පරිශීලකයන් හට බලපෑම් සිදු කල හැක */",
-       "monobook.js": "/* මෙහි ඕනෑම ජාවාස්ක්‍රිප්ට් එකක් ඒකායන ඡවිය භාවිතා කරන පරිශීලකයන්හට ප්‍රවේශනය කෙරේ */"
-}
diff --git a/skins/MonoBook/i18n/sk.json b/skins/MonoBook/i18n/sk.json
deleted file mode 100644 (file)
index 8865e10..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Helix84",
-                       "Rudko"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* Tu umiestnené CSS bude ovplyvňovať používateľov štýlu Monobook */",
-       "monobook.js": "/* Tu sa nachádzajúci JavaScript sa načíta používateľom vzhľadu Monobook */"
-}
diff --git a/skins/MonoBook/i18n/sq.json b/skins/MonoBook/i18n/sq.json
deleted file mode 100644 (file)
index 2a74455..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Dori"
-               ]
-       },
-       "monobook.css": "/* redaktoni këtë faqe për të përshtatur pamjen Monobook për tëra faqet tuaja */"
-}
diff --git a/skins/MonoBook/i18n/sr-ec.json b/skins/MonoBook/i18n/sr-ec.json
deleted file mode 100644 (file)
index 0304c03..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Rancher"
-               ]
-       },
-       "skinname-monobook": "Монобук",
-       "monobook.css": "/* CSS постављен овде ће утицати на све кориснике теме „Монобук“ */",
-       "monobook.js": "/* Јаваскрипт постављен овде ће се учитати за све оне који користе тему „Монобук“ */"
-}
diff --git a/skins/MonoBook/i18n/sr-el.json b/skins/MonoBook/i18n/sr-el.json
deleted file mode 100644 (file)
index 35398b5..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Rancher"
-               ]
-       },
-       "skinname-monobook": "Monobuk",
-       "monobook.css": "/* CSS postavljen ovde će uticati na sve korisnike teme „Monobuk“ */",
-       "monobook.js": "/* Javaskript postavljen ovde će se učitati za sve one koji koriste temu „Monobuk“ */"
-}
diff --git a/skins/MonoBook/i18n/stq.json b/skins/MonoBook/i18n/stq.json
deleted file mode 100644 (file)
index d21f86d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Maartenvdbent"
-               ]
-       },
-       "monobook.css": "/* Littikschrieuwen nit twinge */",
-       "monobook.js": "/* Ferallerd; benutsje insteede deerfon [[MediaWiki:common.js]] */"
-}
diff --git a/skins/MonoBook/i18n/su.json b/skins/MonoBook/i18n/su.json
deleted file mode 100644 (file)
index 627a97b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "monobook.css": "/* édit koropak ieu pikeun nyaluyukeun kulit ''monobook'' pikeun sakabéh situs */"
-}
diff --git a/skins/MonoBook/i18n/sv.json b/skins/MonoBook/i18n/sv.json
deleted file mode 100644 (file)
index 4c08fd8..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Lejonel",
-                       "Lokal Profil",
-                       "Skalman"
-               ]
-       },
-       "skinname-monobook": "Monobook",
-       "monobook-desc": "Det klassiska MediaWiki-utseendet sedan 2004, uppkallad efter det svart-vita foto på en bok som syns i bakgrunden på sidan.",
-       "monobook.css": "/* CSS som skrivs här kommer att påverka alla användare av skalet Monobook */",
-       "monobook.js": "/* JavaScript här kommer att laddas för dem som använder skalet Monobook */"
-}
diff --git a/skins/MonoBook/i18n/te.json b/skins/MonoBook/i18n/te.json
deleted file mode 100644 (file)
index 71b3dbe..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Veeven"
-               ]
-       },
-       "skinname-monobook": "మోనోబుక్"
-}
diff --git a/skins/MonoBook/i18n/th.json b/skins/MonoBook/i18n/th.json
deleted file mode 100644 (file)
index 38be3f9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Manop",
-                       "Octahedron80"
-               ]
-       },
-       "skinname-monobook": "โมโนบุ๊ก",
-       "monobook.css": "/* สไตล์ชีตในหน้านี้จะส่งผลแก่ผู้ใช้ที่ใช้สกินโมโนบุ๊ก */",
-       "monobook.js": "/* จาวาสคริปต์ใด ๆ ในหน้านี้จะถูกโหลดให้แก่ผู้ใช้ที่ใช้สกินโมโนบุ๊ก */"
-}
diff --git a/skins/MonoBook/i18n/tl.json b/skins/MonoBook/i18n/tl.json
deleted file mode 100644 (file)
index 5d10527..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "AnakngAraw",
-                       "Sky Harbor"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* Ang CSS na inilagay dito ay makakaapekto sa mga tagagamit ng pabalat na Monobook */",
-       "monobook.js": "/* Ang anumang JavaScript dito ay ikakarga para sa mga tagagamit na gumagamit ng pabalat na MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/tr.json b/skins/MonoBook/i18n/tr.json
deleted file mode 100644 (file)
index bdb96c8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Dbl2010"
-               ]
-       },
-       "monobook.css": "/* Buraya konulacak CSS kodu tüm Monobook teması kullanan tüm kullanıcılarda etkin olur */"
-}
diff --git a/skins/MonoBook/i18n/tt-cyrl.json b/skins/MonoBook/i18n/tt-cyrl.json
deleted file mode 100644 (file)
index 8f84daf..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ильнар"
-               ]
-       },
-       "skinname-monobook": "Китап"
-}
diff --git a/skins/MonoBook/i18n/tt-latn.json b/skins/MonoBook/i18n/tt-latn.json
deleted file mode 100644 (file)
index 53dfaa0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Don Alessandro"
-               ]
-       },
-       "skinname-monobook": "Kitap"
-}
diff --git a/skins/MonoBook/i18n/tyv.json b/skins/MonoBook/i18n/tyv.json
deleted file mode 100644 (file)
index 26936cf..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Sborsody"
-               ]
-       },
-       "skinname-monobook": "МоноБук"
-}
diff --git a/skins/MonoBook/i18n/ug-arab.json b/skins/MonoBook/i18n/ug-arab.json
deleted file mode 100644 (file)
index 73e0776..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Arlin"
-               ]
-       },
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* CSS placed here will affect users of the Monobook skin */",
-       "monobook.js": "/* Any JavaScript here will be loaded for users using the MonoBook skin */"
-}
diff --git a/skins/MonoBook/i18n/uk.json b/skins/MonoBook/i18n/uk.json
deleted file mode 100644 (file)
index 289f50e..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Dim Grits",
-                       "Matma Rex",
-                       "Ата"
-               ]
-       },
-       "skinname-monobook": "Моно-книга",
-       "monobook-desc": "Класична тема оформлення MediaWiki з 2004 року, названа за чорно-білим фото книги на фоні сторінки",
-       "monobook.css": "/* Розміщений тут CSS буде застосовуватися до всіх тем оформлення Monobook */",
-       "monobook.js": "/* Розміщений тут код JavaScript буде завантажений для всіх користувачів, що використовують тему оформлення Моно-книга */"
-}
diff --git a/skins/MonoBook/i18n/vep.json b/skins/MonoBook/i18n/vep.json
deleted file mode 100644 (file)
index 2213e16..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Игорь Бродский"
-               ]
-       },
-       "skinname-monobook": "MonoBook"
-}
diff --git a/skins/MonoBook/i18n/vi.json b/skins/MonoBook/i18n/vi.json
deleted file mode 100644 (file)
index 67566f6..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Minh Nguyen"
-               ]
-       },
-       "monobook-desc": "Giao diện MediaWiki cổ điển năm 2004, được đặt tên theo bức hình nền cuốn sách đen trắng",
-       "monobook.css": "/* Mã CSS đặt ở đây sẽ ảnh hưởng đến thành viên sử dụng giao diện MonoBook */",
-       "monobook.js": "/* Mã JavaScript tại đây sẽ được tải khi người dùng sử dụng giao diện MonoBook */"
-}
diff --git a/skins/MonoBook/i18n/vmf.json b/skins/MonoBook/i18n/vmf.json
deleted file mode 100644 (file)
index 9b3453b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Silvicola"
-               ]
-       },
-       "monobook.css": "/* CSS hiir beâjflusd nôr dii Monobook-schelfn. Wen'd ale uf ôômôôl beâjflusn wilsch, muâsch an MediaWiki:Common.css was ändârn. */"
-}
diff --git a/skins/MonoBook/i18n/vo.json b/skins/MonoBook/i18n/vo.json
deleted file mode 100644 (file)
index 9e4d0f4..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "monobook.css": "/* El CSS isio pepladöl otefon gebanis padafomäta: Monobook */"
-}
diff --git a/skins/MonoBook/i18n/vro.json b/skins/MonoBook/i18n/vro.json
deleted file mode 100644 (file)
index 9bc1039..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Võrok"
-               ]
-       },
-       "monobook.css": "/* Taa lehe pääl om Monobook-vällänägemist muutvit kujonduisi. */",
-       "monobook.js": "/* Olõi soovitõt; pruugiq [[MediaWiki:common.js]] */"
-}
diff --git a/skins/MonoBook/i18n/wa.json b/skins/MonoBook/i18n/wa.json
deleted file mode 100644 (file)
index 8ffba09..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Srtxg"
-               ]
-       },
-       "monobook.css": "/* li côde CSS metou chal serè eployî pa tos les uzeus eployant l' pea «monobook» */"
-}
diff --git a/skins/MonoBook/i18n/wo.json b/skins/MonoBook/i18n/wo.json
deleted file mode 100644 (file)
index a01b87e..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ibou"
-               ]
-       },
-       "monobook.css": "/* CSS yiñ def fii dañuy am ay njeexit ci jëfandikukatu col gu Monobook. */",
-       "monobook.js": "/*Bépp JavaScript buñ fi duggal jëfandikukat yiy jëfandikoo col gu Monobook keppa koy yeb. */"
-}
diff --git a/skins/MonoBook/i18n/yi.json b/skins/MonoBook/i18n/yi.json
deleted file mode 100644 (file)
index 5a7d3e1..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "פוילישער"
-               ]
-       },
-       "skinname-monobook": "מאנאבוק",
-       "monobook.css": "/* סטייל דא געלייגט וועט באאיינפלוסן דעם Monobook סקין */"
-}
diff --git a/skins/MonoBook/i18n/yue.json b/skins/MonoBook/i18n/yue.json
deleted file mode 100644 (file)
index b450970..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-       "skinname-monobook": "MonoBook",
-       "monobook.css": "/* 響呢度放 CSS 碼去改用戶用嘅 Monobook 畫面 */",
-       "monobook.js": "/* 響每一次個頁面載入時,用 Monobook 畫面嘅用戶都會載入呢度任何嘅JavaScript */"
-}
diff --git a/skins/MonoBook/i18n/zh-hans.json b/skins/MonoBook/i18n/zh-hans.json
deleted file mode 100644 (file)
index fc3f368..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Xiaomingyan",
-                       "Cwek",
-                       "Liuxinyu970226"
-               ]
-       },
-       "monobook-desc": "自2004年就出现的经典MediaWiki皮肤,命名依据一本书中某页面的黑白照片背景",
-       "monobook.css": "/* 放置于这里的CSS将影响使用MonoBook皮肤的用户 */",
-       "monobook.js": "/* 这里的任何JavaScript将为使用MonoBook皮肤的用户加载 */"
-}
diff --git a/skins/MonoBook/i18n/zh-hant.json b/skins/MonoBook/i18n/zh-hant.json
deleted file mode 100644 (file)
index 7813cc1..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Cwlin0416"
-               ]
-       },
-       "monobook.css": "/* 此 CSS 會影響使用 Monobook 介面外觀的使用者 */",
-       "monobook.js": "/* 此 JavaScript 會用於使用 Monobook 介面外觀使用者 */"
-}
diff --git a/skins/MonoBook/link_icon.gif b/skins/MonoBook/link_icon.gif
deleted file mode 100644 (file)
index 168c1a2..0000000
Binary files a/skins/MonoBook/link_icon.gif and /dev/null differ
diff --git a/skins/MonoBook/lock_icon.gif b/skins/MonoBook/lock_icon.gif
deleted file mode 100644 (file)
index f71cd9b..0000000
Binary files a/skins/MonoBook/lock_icon.gif and /dev/null differ
diff --git a/skins/MonoBook/magnify-clip.png b/skins/MonoBook/magnify-clip.png
deleted file mode 100644 (file)
index ffd7637..0000000
Binary files a/skins/MonoBook/magnify-clip.png and /dev/null differ
diff --git a/skins/MonoBook/mail_icon.gif b/skins/MonoBook/mail_icon.gif
deleted file mode 100644 (file)
index cf5680d..0000000
Binary files a/skins/MonoBook/mail_icon.gif and /dev/null differ
diff --git a/skins/MonoBook/main.css b/skins/MonoBook/main.css
deleted file mode 100644 (file)
index cb76ae3..0000000
+++ /dev/null
@@ -1,913 +0,0 @@
-/*
-** MediaWiki 'monobook' style sheet for CSS2-capable browsers.
-** Copyright Gabriel Wicke - http://wikidev.net/
-** License: GPL (http://www.gnu.org/copyleft/gpl.html)
-**
-** Loosely based on http://www.positioniseverything.net/ordered-floats.html by Big John
-** and the Plone 2.0 styles, see http://plone.org/ (Alexander Limi,Joe Geldart & Tom Croucher,
-** Michael Zeltner and Geir Bækholt)
-** All you guys rock :)
-*/
-
-div#column-content {
-       width: 100%;
-       float: right;
-       margin: 0 0 .6em -12.2em;
-       padding: 0;
-}
-
-div#content {
-       margin: 2.8em 0 0 12.2em;
-       padding: 1em;
-       position: relative;
-       z-index: 2;
-}
-
-div#column-one {
-       padding-top: 160px;
-}
-
-/* Hide, but keep accessible for screen-readers */
-#column-one h2 {
-       position: absolute;
-       top: -9999px;
-}
-
-div#content {
-       background: white;
-       color: black;
-       border: 1px solid #aaa;
-       border-right: none;
-       line-height: 1.5em;
-}
-
-/* the left column width is specified in class .portlet */
-
-/* Font size:
-** We take advantage of keyword scaling- browsers won't go below 9px
-** More at http://www.w3.org/2003/07/30-font-size
-** http://style.cleverchimp.com/font_size_intervals/altintervals.html
-*/
-
-body {
-       font: x-small sans-serif;
-       /* @embed */
-       background: #f9f9f9 url(headbg.jpg) 0 0 no-repeat;
-       color: black;
-       margin: 0;
-       padding: 0;
-       direction: ltr; /* Needed for RTL flipping */
-       unicode-bidi: embed;
-}
-
-/* scale back up to a sane default */
-div#globalWrapper {
-       font-size: 127%;
-       width: 100%;
-       margin: 0;
-       padding: 0;
-}
-
-/* general styles */
-a {
-       color: #002bb8;
-}
-
-a:visited {
-       color: #5a3696;
-}
-
-a.new,
-#p-personal a.new {
-       color: #cc2200;
-}
-
-ul {
-       list-style-type: square;
-       /* @embed */
-       list-style-image: url(bullet.gif);
-}
-
-input.historysubmit {
-       padding: 0 .3em .3em .3em !important;
-       font-size: 94%;
-       cursor: pointer;
-       height: 1.7em !important;
-       margin-left: 1.6em;
-}
-
-pre, .mw-code {
-       line-height: 1.1em;
-}
-
-#firstHeading {
-       padding-top: 0;
-}
-
-/*
-** the main content area
-*/
-
-#siteNotice {
-       font-size: 95%;
-       padding: 0 0.9em;
-}
-
-#localNotice {
-       margin: 0;
-}
-
-#siteNotice p {
-       margin: 0;
-       padding: 0;
-}
-
-/*
-** classes for special content elements like town boxes
-** intended to be referenced directly from the wiki src
-*/
-
-/*
-** User styles
-*/
-/* table standards */
-table.rimage {
-       float: right;
-       position: relative;
-       margin-left: 1em;
-       margin-bottom: 1em;
-       text-align: center;
-}
-
-/*
-** edit views etc
-*/
-.special li {
-       line-height: 1.4em;
-       margin: 0;
-       padding: 0;
-}
-
-/*
-** keep the whitespace in front of the ^=, hides rule from konqueror
-** this is css3, the validator doesn't like it when validating as css2
-*/
-#bodyContent a.external {
-       /* @embed */
-       background: url(external-ltr.png) center right no-repeat;
-       padding-right: 13px;
-}
-
-#bodyContent a.external[href ^="https://"],
-.link-https {
-       /* @embed */
-       background: url(lock_icon.gif) center right no-repeat;
-       padding-right: 16px;
-}
-
-#bodyContent a.external[href ^="mailto:"],
-.link-mailto {
-       /* @embed */
-       background: url(mail_icon.gif) center right no-repeat;
-       padding-right: 18px;
-}
-
-#bodyContent a.external[href ^="news:"] {
-       /* @embed */
-       background: url(news_icon.png) center right no-repeat;
-       padding-right: 18px;
-}
-
-#bodyContent a.external[href ^="ftp://"],
-.link-ftp {
-       /* @embed */
-       background: url(file_icon.gif) center right no-repeat;
-       padding-right: 18px;
-}
-
-#bodyContent a.external[href ^="irc://"],
-#bodyContent a.external[href ^="ircs://"],
-.link-irc {
-       /* @embed */
-       background: url(discussionitem_icon.gif) center right no-repeat;
-       padding-right: 18px;
-}
-
-#bodyContent a.external[href $=".ogg"], #bodyContent a.external[href $=".OGG"],
-#bodyContent a.external[href $=".mid"], #bodyContent a.external[href $=".MID"],
-#bodyContent a.external[href $=".midi"], #bodyContent a.external[href $=".MIDI"],
-#bodyContent a.external[href $=".mp3"], #bodyContent a.external[href $=".MP3"],
-#bodyContent a.external[href $=".wav"], #bodyContent a.external[href $=".WAV"],
-#bodyContent a.external[href $=".wma"], #bodyContent a.external[href $=".WMA"],
-.link-audio {
-       /* @embed */
-       background: url(audio.png) center right no-repeat;
-       padding-right: 13px;
-}
-
-#bodyContent a.external[href $=".ogm"], #bodyContent a.external[href $=".OGM"],
-#bodyContent a.external[href $=".avi"], #bodyContent a.external[href $=".AVI"],
-#bodyContent a.external[href $=".mpeg"], #bodyContent a.external[href $=".MPEG"],
-#bodyContent a.external[href $=".mpg"], #bodyContent a.external[href $=".MPG"],
-.link-video {
-       /* @embed */
-       background: url(video.png) center right no-repeat;
-       padding-right: 13px;
-}
-
-#bodyContent a.external[href $=".pdf"], #bodyContent a.external[href $=".PDF"],
-#bodyContent a.external[href *=".pdf#"], #bodyContent a.external[href *=".PDF#"],
-#bodyContent a.external[href *=".pdf?"], #bodyContent a.external[href *=".PDF?"],
-.link-document {
-       /* @embed */
-       background: url(document.png) center right no-repeat;
-       padding-right: 12px;
-}
-
-/* Interwiki Styling */
-#bodyContent a.extiw,
-#bodyContent a.extiw:active {
-       color: #36b;
-}
-
-/* External links */
-#bodyContent a.external {
-       color: #36b;
-}
-
-/*
-** Structural Elements
-*/
-
-/*
-** general portlet styles (elements in the quickbar)
-*/
-.portlet {
-       border: none;
-       margin: 0 0 .5em;
-       padding: 0;
-       float: none;
-       width: 11.6em;
-       overflow: hidden;
-}
-
-.portlet h3 {
-       background: transparent;
-       padding: 0 1em 0 .5em;
-       display: inline;
-       height: 1em;
-       text-transform: lowercase;
-       font-size: 91%;
-       font-weight: normal;
-       white-space: nowrap;
-}
-
-.pBody {
-       font-size: 95%;
-       background-color: white;
-       color: black;
-       border-collapse: collapse;
-       border: 1px solid #aaa;
-       padding: 0 .8em .3em .5em;
-}
-
-/* allows .pBody styles to wrap around content added via BaseTemplateAfterPortlet hook */
-.pBody:after {
-       content: '';
-       clear: both;
-       display: block;
-}
-
-.portlet ul {
-       line-height: 1.5em;
-       font-size: 95%;
-}
-
-.portlet li {
-       padding: 0;
-       margin: 0;
-}
-
-/*
-** Logo properties
-*/
-
-#p-logo {
-       top: 0;
-       left: 0;
-       position: absolute; /*needed to use z-index */
-       z-index: 3;
-       height: 155px;
-       width: 12em;
-       overflow: visible;
-}
-
-#p-logo h3 {
-       display: none;
-}
-
-#p-logo a,
-#p-logo a:hover {
-       display: block;
-       height: 155px;
-       width: 12.2em;
-       background-repeat: no-repeat;
-       background-position: 35% 50% !important;
-       text-decoration: none;
-}
-
-/*
-** Search portlet
-*/
-#p-search {
-       position: relative;
-       z-index: 3;
-}
-
-input.searchButton {
-       margin-top: 1px;
-       font-size: 95%;
-}
-
-#searchGoButton {
-       padding-left: .5em;
-       padding-right: .5em;
-       font-weight: bold;
-}
-
-#searchInput {
-       width: 10.9em;
-       margin: 0;
-       font-size: 95%;
-}
-
-#p-search .pBody {
-       padding: .5em .4em .4em .4em;
-       text-align: center;
-}
-
-#p-search #searchform div div {
-       margin-top: .4em;
-       font-size: 95%;
-}
-
-/*
-** the personal toolbar
-*/
-#p-personal {
-       position: absolute;
-       left: 0;
-       top: 0;
-       z-index: 3;
-}
-
-#p-personal {
-       width: 100%;
-       white-space: nowrap;
-       padding: 0;
-       margin: 0;
-       border: none;
-       background: none;
-       overflow: visible;
-       line-height: 1.2em;
-}
-
-#p-personal h3 {
-       display: none;
-}
-
-#p-personal .portlet,
-#p-personal .pBody {
-       z-index: 0;
-       padding: 0;
-       margin: 0;
-       border: none;
-       overflow: visible;
-       background: none;
-}
-
-/* this is the ul contained in the portlet */
-#p-personal ul {
-       border: none;
-       line-height: 1.4em;
-       color: #2f6fab;
-       padding: 0 2em 0 3em;
-       margin: 0;
-       text-align: right;
-       list-style-type: none;
-       list-style-image: none;
-       z-index: 0;
-       background: none;
-       cursor: default;
-}
-
-#p-personal li {
-       z-index: 0;
-       border: none;
-       padding: 0;
-       display: inline;
-       color: #2f6fab;
-       margin-left: 1em;
-       line-height: 1.2em;
-       background: none;
-}
-
-#p-personal li a {
-       text-decoration: none;
-       color: #005896;
-       padding-bottom: .2em;
-       background: none;
-}
-
-#p-personal li a:hover {
-       background-color: white;
-       padding-bottom: .2em;
-       text-decoration: none;
-}
-
-#p-personal li.active a:hover {
-       background-color: transparent;
-}
-
-/* The icon in front of the username / login link */
-li#pt-userpage,
-li#pt-anonuserpage,
-li#pt-login {
-       /* @embed */
-       background: url(user.gif) top left no-repeat;
-       padding-left: 20px;
-}
-
-#p-personal ul {
-       text-transform: lowercase;
-}
-
-/* Don't lowercase username or IP addresses (IPv6) */
-li#pt-userpage,
-li#pt-anonuserpage {
-       text-transform: none;
-}
-
-#p-personal li.active {
-       font-weight: bold;
-}
-
-/*
-** the page-related actions- page/talk, edit etc
-*/
-#p-cactions {
-       position: absolute;
-       top: 1.3em;
-       left: 11.5em;
-       margin: 0;
-       white-space: nowrap;
-       width: 76%;
-       line-height: 1.1em;
-       overflow: visible;
-       background: none;
-       border-collapse: collapse;
-       padding-left: 1em;
-       font-size: 95%;
-}
-
-#p-cactions ul {
-       list-style-type: none;
-       list-style-image: none;
-}
-
-#p-cactions li {
-       display: inline;
-       border: 1px solid #aaa;
-       border-bottom: none;
-       padding: 0 0 1em 0;
-       margin: 0 .3em 0 0;
-       overflow: visible;
-       background: white;
-}
-
-#p-cactions li.selected {
-       border-color: #fabd23;
-       font-weight: bold;
-}
-
-#p-cactions li a {
-       background-color: #fbfbfb;
-       color: #002bb8;
-       border: none;
-       padding: 0 .8em .3em;
-       position: relative;
-       z-index: 0;
-       margin: 0;
-       text-decoration: none;
-}
-
-#p-cactions li.selected a {
-       z-index: 3;
-       background-color: white;
-}
-
-#p-cactions .new a {
-       color: #ba0000;
-}
-
-#p-cactions li a:hover {
-       z-index: 3;
-       text-decoration: none;
-       background-color: white;
-}
-
-#p-cactions h3 {
-       display: none;
-}
-
-#p-cactions li.istalk {
-       margin-right: 0;
-}
-
-#p-cactions li.istalk a {
-       padding-right: .5em;
-}
-
-#p-cactions #ca-addsection a {
-       padding-left: .4em;
-       padding-right: .4em;
-}
-
-/* offsets to distinguish the tab groups */
-li#ca-talk {
-       margin-right: 1.6em;
-}
-
-li#ca-watch,
-li#ca-unwatch,
-li#ca-varlang-0,
-li#ca-print {
-       margin-left: 1.6em;
-}
-
-#p-cactions .pBody {
-       font-size: 1em;
-       background-color: transparent;
-       color: inherit;
-       border-collapse: inherit;
-       border: 0;
-       padding: 0;
-}
-
-#p-cactions li a {
-       text-transform: lowercase;
-}
-
-#p-lang {
-       position: relative;
-       z-index: 3;
-}
-
-/* Override text-transform on languages where capitalization is significant */
-.capitalize-all-nouns .portlet h3,
-.capitalize-all-nouns #p-personal ul,
-.capitalize-all-nouns #p-cactions ul li a {
-       text-transform: none;
-}
-
-/* TODO: #t-iscite is only used by the Cite extension, come up with some
- * system which allows extensions to add to this file on the fly
- */
-#t-ispermalink, #t-iscite {
-       color: #999;
-}
-
-/*
-** footer
-*/
-div#footer {
-       background-color: white;
-       border-top: 1px solid #fabd23;
-       border-bottom: 1px solid #fabd23;
-       margin: .6em 0 1em 0;
-       overflow: hidden;
-       padding: .4em 0 .3em 0;
-       text-align: center;
-       font-size: 90%;
-}
-
-div#footer li {
-       display: inline;
-       margin: 0 1.3em;
-}
-
-#f-poweredbyico, #f-copyrightico {
-       margin: 0 8px;
-       position: relative;
-       top: -2px; /* Bump it up just a tad */
-}
-
-#f-poweredbyico {
-       float: right;
-       height: 1%;
-}
-
-#f-copyrightico {
-       float: left;
-       height: 1%;
-}
-
-.mw-htmlform-submit {
-       font-weight: bold;
-       padding-left: .3em;
-       padding-right: .3em;
-       margin-right: 2em;
-}
-
-/* js pref toc */
-#preftoc {
-       margin: 0;
-       padding: 0;
-       width: 100%;
-       clear: both;
-}
-
-#preftoc li {
-       background-color: #f0f0f0;
-       color: #000;
-}
-
-#preftoc li {
-       margin: 1px -2px 1px 2px;
-       float: left;
-       padding: 2px 0 3px 0;
-       border: 1px solid #fff;
-       border-right-color: #716f64;
-       border-bottom: 0;
-       position: relative;
-       white-space: nowrap;
-       list-style-type: none;
-       list-style-image: none;
-       z-index: 3;
-}
-
-#preftoc li.selected {
-       font-weight: bold;
-       background-color: #f9f9f9;
-       border: 1px solid #aaa;
-       border-bottom: none;
-       cursor: default;
-       top: 1px;
-       padding-top: 2px;
-       margin-right: -3px;
-}
-
-#preftoc > li.selected {
-       top: 2px;
-}
-
-#preftoc a,
-#preftoc a:active {
-       display: block;
-       color: #000;
-       padding: 0 .7em;
-       position: relative;
-       text-decoration: none;
-}
-
-#preftoc li.selected a {
-       cursor: default;
-       text-decoration: none;
-}
-
-#preferences {
-       margin: 0;
-       border: 1px solid #aaa;
-       clear: both;
-       padding: 1.5em;
-       background-color: #F9F9F9;
-}
-
-.prefsection {
-       border: none;
-       padding: 0;
-       margin: 0;
-}
-
-.prefsection legend {
-       font-weight: bold;
-}
-
-.prefsection table, .prefsection legend {
-       background-color: #F9F9F9;
-}
-
-.mainLegend {
-       display: none;
-}
-
-td.htmlform-tip {
-       font-size: x-small;
-       padding: .2em 2em;
-       color: #666;
-}
-
-.preferences-login {
-       clear: both;
-       margin-bottom: 1.5em;
-}
-
-.prefcache {
-       font-size: 90%;
-       margin-top: 2em;
-}
-
-#userloginprompt, #languagelinks {
-       font-size: 85%;
-}
-
-#login-sectiontip {
-       font-size: 85%;
-       line-height: 1.2;
-       padding-top: 2em;
-}
-
-#userloginlink a, #wpLoginattempt, #wpCreateaccount {
-       font-weight: bold;
-}
-
-/**
- * This was originally added by Gabriel Wicke in r3681 (committed on 25 May 2004)
- * with the commit message "tweaks to page history".
- * Unlike the other IE/Mac fixes that used to be present here, this seems to get
- * applied on more modern browsers, so let's keep it here until someone has the
- * time to properly test it out.
- */
-#pagehistory li.selected {
-       position: relative;
-}
-
-.redirectText {
-       font-size: 150%;
-       margin: 5px;
-}
-
-div.patrollink {
-       clear: both;
-}
-
-.sharedUploadNotice {
-       font-style: italic;
-}
-
-span.updatedmarker {
-       color: black;
-       background-color: #0f0;
-}
-
-.editExternally {
-       border: 1px solid gray;
-       background-color: #ffffff;
-       padding: 3px;
-       margin-top: 0.5em;
-       float: left;
-       font-size: small;
-       text-align: center;
-}
-
-.editExternallyHelp {
-       font-style: italic;
-       color: gray;
-}
-
-.toggle {
-       margin-left: 2em;
-       text-indent: -2em;
-}
-
-/* @bug 1714 */
-input#wpSave,
-input#wpDiff {
-       margin-right: 0.33em;
-}
-
-#wpSave {
-       font-weight: bold;
-}
-
-/* noarticletext */
-div.noarticletext {
-       border: 1px solid #ccc;
-       background: #fff;
-       padding: .2em 1em;
-       color: #000;
-}
-
-div#searchTargetContainer {
-       left: 10px;
-       top: 10px;
-       width: 90%;
-       background: white;
-}
-
-div#searchTarget {
-       padding: 3px;
-       margin: 5px;
-       background: #F0F0F0;
-       border: solid 1px blue;
-}
-
-div#searchTarget ul li {
-       list-style-type: none;
-       list-style-image: none;
-}
-
-div#searchTarget ul li:before {
-       color: orange;
-       content: "\00BB \0020";
-}
-
-div#searchTargetHide {
-       float: right;
-       border: solid 1px black;
-       background: #DCDCDC;
-       padding: 2px;
-}
-
-#powersearch p {
-       margin-top: 0;
-}
-
-div.multipageimagenavbox {
-       border: solid 1px silver;
-       padding: 4px;
-       margin: 1em;
-       background: #f0f0f0;
-}
-
-div.multipageimagenavbox div.thumb {
-       border: none;
-       margin-left: 2em;
-       margin-right: 2em;
-}
-
-div.multipageimagenavbox hr {
-       margin: 6px;
-}
-
-table.multipageimage td {
-       text-align: center;
-}
-
-.templatesUsed {
-       margin-top: 1.5em;
-}
-
-.mw-summary-preview {
-       margin: 0.1em 0;
-}
-
-/* Friendlier slave lag warnings */
-div.mw-lag-warn-normal,
-div.mw-lag-warn-high {
-       padding: 3px;
-       text-align: center;
-       margin: 3px auto;
-}
-
-div.mw-lag-warn-normal {
-       border: 1px solid #FFCC66;
-       background-color: #FFFFCC;
-}
-
-div.mw-lag-warn-high {
-       font-weight: bold;
-       border: 2px solid #FF0033;
-       background-color: #FFCCCC;
-}
-
-.MediaTransformError {
-       background-color: #ccc;
-       padding: 0.1em;
-}
-
-.MediaTransformError td {
-       text-align: center;
-       vertical-align: middle;
-       font-size: 90%;
-}
-
-/* God-damned hack for the crappy layout */
-.os-suggest {
-       font-size: 127%;
-}
-
-/* Sometimes people don't want personal tools to be lowercase! */
-.no-text-transform {
-       text-transform: none;
-}
-
-/* Tooltips are outside of the normal body code, so this helps make the size of the text sensible */
-.tipsy {
-       font-size: 127%;
-}
-
-/* mediawiki.notification */
-.skin-monobook .mw-notification {
-       box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.125);
-}
diff --git a/skins/MonoBook/news_icon.png b/skins/MonoBook/news_icon.png
deleted file mode 100644 (file)
index 4d3cb47..0000000
Binary files a/skins/MonoBook/news_icon.png and /dev/null differ
diff --git a/skins/MonoBook/required.gif b/skins/MonoBook/required.gif
deleted file mode 100644 (file)
index bd71976..0000000
Binary files a/skins/MonoBook/required.gif and /dev/null differ
diff --git a/skins/MonoBook/user.gif b/skins/MonoBook/user.gif
deleted file mode 100644 (file)
index 34b4839..0000000
Binary files a/skins/MonoBook/user.gif and /dev/null differ
diff --git a/skins/MonoBook/video.png b/skins/MonoBook/video.png
deleted file mode 100644 (file)
index d86dbe0..0000000
Binary files a/skins/MonoBook/video.png and /dev/null differ
diff --git a/skins/MonoBook/wiki-indexed.png b/skins/MonoBook/wiki-indexed.png
deleted file mode 100644 (file)
index 799ebac..0000000
Binary files a/skins/MonoBook/wiki-indexed.png and /dev/null differ
diff --git a/skins/MonoBook/wiki.png b/skins/MonoBook/wiki.png
deleted file mode 100644 (file)
index 8c42118..0000000
Binary files a/skins/MonoBook/wiki.png and /dev/null differ
diff --git a/skins/README b/skins/README
new file mode 100644 (file)
index 0000000..4145b35
--- /dev/null
@@ -0,0 +1,29 @@
+Skins, such as the default skin Vector, are distributed separately. Drop them
+into this directory and enable as per the skin's installation instructions.
+
+You can find a list of available skins at
+<https://www.mediawiki.org/wiki/Category:All_skins>,
+and more information about installing and configuring skins at
+<https://www.mediawiki.org/wiki/Manual:Skin_configuration>.
+
+If you are a developer, you might want to fetch the skin tree in another
+directory and make a symbolic link:
+
+ mediawiki/skins$ ln -s ../../skins-trunk/FooBar
+
+Most skins are available through Git:
+    https://gerrit.wikimedia.org/r/#/admin/projects/?filter=mediawiki%252Fskins%252F
+    https://git.wikimedia.org/project/mediawiki
+
+
+Please note that under POSIX systems (Linux...), parent of a symbolic path
+refers to the link source, NOT to the target! You should check the env
+variable MW_INSTALL_PATH in case the extension is not in the default location.
+
+The following code snippet lets you override the default path:
+
+ $IP = getenv( 'MW_INSTALL_PATH' );
+ if( $IP === false ) {
+       $IP = __DIR__ . '/../..';
+ }
+ require_once "$IP/maintenance/Maintenance.php"; // a MediaWiki core file
diff --git a/skins/Vector/COPYING b/skins/Vector/COPYING
deleted file mode 100644 (file)
index 019694a..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-== GNU GENERAL PUBLIC LICENSE ==
-
-Version 2, June 1991
-
-Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
-Everyone is permitted to copy and distribute verbatim copies
-of this license document, but changing it is not allowed.
-
-=== Preamble ===
-
-The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-The precise terms and conditions for copying, distribution and
-modification follow.
-
-== TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ==
-
-'''0.''' This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-'''1.''' You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-'''2.''' You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-       '''a)''' You must cause the modified files to carry prominent notices
-       stating that you changed the files and the date of any change.
-
-       '''b)''' You must cause any work that you distribute or publish, that in
-       whole or in part contains or is derived from the Program or any
-       part thereof, to be licensed as a whole at no charge to all third
-       parties under the terms of this License.
-
-       '''c)''' If the modified program normally reads commands interactively
-       when run, you must cause it, when started running for such
-       interactive use in the most ordinary way, to print or display an
-       announcement including an appropriate copyright notice and a
-       notice that there is no warranty (or else, saying that you provide
-       a warranty) and that users may redistribute the program under
-       these conditions, and telling the user how to view a copy of this
-       License.  (Exception: if the Program itself is interactive but
-       does not normally print such an announcement, your work based on
-       the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-'''3.''' You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-       '''a)''' Accompany it with the complete corresponding machine-readable
-       source code, which must be distributed under the terms of Sections
-       1 and 2 above on a medium customarily used for software interchange; or,
-
-       '''b)''' Accompany it with a written offer, valid for at least three
-       years, to give any third party, for a charge no more than your
-       cost of physically performing source distribution, a complete
-       machine-readable copy of the corresponding source code, to be
-       distributed under the terms of Sections 1 and 2 above on a medium
-       customarily used for software interchange; or,
-
-       '''c)''' Accompany it with the information you received as to the offer
-       to distribute corresponding source code.  (This alternative is
-       allowed only for noncommercial distribution and only if you
-       received the program in object code or executable form with such
-       an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-'''4.''' You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-'''5.''' You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-'''6.''' Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-'''7.''' If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-'''8.''' If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-'''9.''' The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-'''10.''' If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-=== NO WARRANTY ===
-
-'''11.''' BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-'''12.''' IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-       '''END OF TERMS AND CONDITIONS'''
-
-== How to Apply These Terms to Your New Programs ==
-
-If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-       <one line to give the program's name and a brief idea of what it does.>
-
-       Copyright (C) <year>  <name of author>
-
-       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
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-       Gnomovision version 69, Copyright (C) year name of author
-       Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-       This is free software, and you are welcome to redistribute it
-       under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-       Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-       `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-       <signature of Ty Coon>, 1 April 1989
-
-       Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/skins/Vector/SkinVector.php b/skins/Vector/SkinVector.php
deleted file mode 100644 (file)
index 237a241..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-/**
- * Vector - Modern version of MonoBook with fresh look and many usability
- * improvements.
- *
- * 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 Skins
- */
-
-/**
- * SkinTemplate class for Vector skin
- * @ingroup Skins
- */
-class SkinVector extends SkinTemplate {
-       public $skinname = 'vector';
-       public $stylename = 'Vector';
-       public $template = 'VectorTemplate';
-
-       protected static $bodyClasses = array( 'vector-animateLayout' );
-
-       /**
-        * Initializes output page and sets up skin-specific parameters
-        * @param OutputPage $out Object to initialize
-        */
-       public function initPage( OutputPage $out ) {
-               global $wgLocalStylePath;
-
-               parent::initPage( $out );
-
-               // Append CSS which includes IE only behavior fixes for hover support -
-               // this is better than including this in a CSS file since it doesn't
-               // wait for the CSS file to load before fetching the HTC file.
-               $min = $this->getRequest()->getFuzzyBool( 'debug' ) ? '' : '.min';
-               $out->addHeadItem( 'csshover',
-                       '<!--[if lt IE 7]><style type="text/css">body{behavior:url("' .
-                               htmlspecialchars( $wgLocalStylePath ) .
-                               "/{$this->stylename}/csshover{$min}.htc\")}</style><![endif]-->"
-               );
-
-               $out->addModules( array( 'skins.vector.js' ) );
-       }
-
-       /**
-        * Loads skin and user CSS files.
-        * @param OutputPage $out
-        */
-       function setupSkinUserCss( OutputPage $out ) {
-               parent::setupSkinUserCss( $out );
-
-               $styles = array( 'mediawiki.skinning.interface', 'skins.vector.styles' );
-               wfRunHooks( 'SkinVectorStyleModules', array( $this, &$styles ) );
-               $out->addModuleStyles( $styles );
-       }
-
-       /**
-        * Adds classes to the body element.
-        *
-        * @param OutputPage $out
-        * @param array &$bodyAttrs Array of attributes that will be set on the body element
-        */
-       function addToBodyAttributes( $out, &$bodyAttrs ) {
-               if ( isset( $bodyAttrs['class'] ) && strlen( $bodyAttrs['class'] ) > 0 ) {
-                       $bodyAttrs['class'] .= ' ' . implode( ' ', static::$bodyClasses );
-               } else {
-                       $bodyAttrs['class'] = implode( ' ', static::$bodyClasses );
-               }
-       }
-}
diff --git a/skins/Vector/Vector.php b/skins/Vector/Vector.php
deleted file mode 100644 (file)
index be8719a..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-/**
- * Vector - Modern version of MonoBook with fresh look and many usability
- * improvements.
- *
- * 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 Skins
- */
-
-$wgExtensionCredits['skin'][] = array(
-       'path' => __FILE__,
-       'name' => 'Vector',
-       'namemsg' => 'skinname-vector',
-       'descriptionmsg' => 'vector-skin-desc',
-       'url' => 'https://www.mediawiki.org/wiki/Skin:Vector',
-       'author' => array( 'Trevor Parscal', 'Roan Kattouw', '...' ),
-       'license-name' => 'GPLv2+',
-);
-
-// Register files
-$wgAutoloadClasses['SkinVector'] = __DIR__ . '/SkinVector.php';
-$wgAutoloadClasses['VectorTemplate'] = __DIR__ . '/VectorTemplate.php';
-$wgMessagesDirs['Vector'] = __DIR__ . '/i18n';
-
-// Register skin
-$wgValidSkinNames['vector'] = 'Vector';
-
-// Register modules
-$wgResourceModules['skins.vector.styles'] = array(
-       'styles' => array(
-               'screen.less' => array( 'media' => 'screen' ),
-               'screen-hd.less' => array( 'media' => 'screen and (min-width: 982px)' ),
-       ),
-       'remoteSkinPath' => 'Vector',
-       'localBasePath' => __DIR__,
-);
-$wgResourceModules['skins.vector.js'] = array(
-       'scripts' => array(
-               'collapsibleTabs.js',
-               'vector.js',
-       ),
-       'position' => 'top',
-       'dependencies' => array(
-               'jquery.throttle-debounce',
-               'jquery.tabIndex',
-       ),
-       'remoteSkinPath' => 'Vector',
-       'localBasePath' => __DIR__,
-);
diff --git a/skins/Vector/VectorTemplate.php b/skins/Vector/VectorTemplate.php
deleted file mode 100644 (file)
index 7dc376a..0000000
+++ /dev/null
@@ -1,596 +0,0 @@
-<?php
-/**
- * Vector - Modern version of MonoBook with fresh look and many usability
- * improvements.
- *
- * 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 Skins
- */
-
-/**
- * QuickTemplate class for Vector skin
- * @ingroup Skins
- */
-class VectorTemplate extends BaseTemplate {
-       /* Functions */
-
-       /**
-        * Outputs the entire contents of the (X)HTML page
-        */
-       public function execute() {
-               global $wgVectorUseIconWatch;
-
-               // Build additional attributes for navigation urls
-               $nav = $this->data['content_navigation'];
-
-               if ( $wgVectorUseIconWatch ) {
-                       $mode = $this->getSkin()->getUser()->isWatched( $this->getSkin()->getRelevantTitle() )
-                               ? 'unwatch'
-                               : 'watch';
-
-                       if ( isset( $nav['actions'][$mode] ) ) {
-                               $nav['views'][$mode] = $nav['actions'][$mode];
-                               $nav['views'][$mode]['class'] = rtrim( 'icon ' . $nav['views'][$mode]['class'], ' ' );
-                               $nav['views'][$mode]['primary'] = true;
-                               unset( $nav['actions'][$mode] );
-                       }
-               }
-
-               $xmlID = '';
-               foreach ( $nav as $section => $links ) {
-                       foreach ( $links as $key => $link ) {
-                               if ( $section == 'views' && !( isset( $link['primary'] ) && $link['primary'] ) ) {
-                                       $link['class'] = rtrim( 'collapsible ' . $link['class'], ' ' );
-                               }
-
-                               $xmlID = isset( $link['id'] ) ? $link['id'] : 'ca-' . $xmlID;
-                               $nav[$section][$key]['attributes'] =
-                                       ' id="' . Sanitizer::escapeId( $xmlID ) . '"';
-                               if ( $link['class'] ) {
-                                       $nav[$section][$key]['attributes'] .=
-                                               ' class="' . htmlspecialchars( $link['class'] ) . '"';
-                                       unset( $nav[$section][$key]['class'] );
-                               }
-                               if ( isset( $link['tooltiponly'] ) && $link['tooltiponly'] ) {
-                                       $nav[$section][$key]['key'] =
-                                               Linker::tooltip( $xmlID );
-                               } else {
-                                       $nav[$section][$key]['key'] =
-                                               Xml::expandAttributes( Linker::tooltipAndAccesskeyAttribs( $xmlID ) );
-                               }
-                       }
-               }
-               $this->data['namespace_urls'] = $nav['namespaces'];
-               $this->data['view_urls'] = $nav['views'];
-               $this->data['action_urls'] = $nav['actions'];
-               $this->data['variant_urls'] = $nav['variants'];
-
-               // Reverse horizontally rendered navigation elements
-               if ( $this->data['rtl'] ) {
-                       $this->data['view_urls'] =
-                               array_reverse( $this->data['view_urls'] );
-                       $this->data['namespace_urls'] =
-                               array_reverse( $this->data['namespace_urls'] );
-                       $this->data['personal_urls'] =
-                               array_reverse( $this->data['personal_urls'] );
-               }
-               // Output HTML Page
-               $this->html( 'headelement' );
-               ?>
-               <div id="mw-page-base" class="noprint"></div>
-               <div id="mw-head-base" class="noprint"></div>
-               <div id="content" class="mw-body" role="main">
-                       <a id="top"></a>
-
-                       <div id="mw-js-message" style="display:none;"<?php $this->html( 'userlangattributes' ) ?>></div>
-                       <?php
-                       if ( $this->data['sitenotice'] ) {
-                               ?>
-                               <div id="siteNotice"><?php $this->html( 'sitenotice' ) ?></div>
-                       <?php
-                       }
-                       ?>
-                       <h1 id="firstHeading" class="firstHeading" lang="<?php
-                       $this->data['pageLanguage'] =
-                               $this->getSkin()->getTitle()->getPageViewLanguage()->getHtmlCode();
-                       $this->text( 'pageLanguage' );
-                       ?>"><span dir="auto"><?php $this->html( 'title' ) ?></span></h1>
-                       <?php $this->html( 'prebodyhtml' ) ?>
-                       <div id="bodyContent" class="mw-body-content">
-                               <?php
-                               if ( $this->data['isarticle'] ) {
-                                       ?>
-                                       <div id="siteSub"><?php $this->msg( 'tagline' ) ?></div>
-                               <?php
-                               }
-                               ?>
-                               <div id="contentSub"<?php
-                               $this->html( 'userlangattributes' )
-                               ?>><?php $this->html( 'subtitle' ) ?></div>
-                               <?php
-                               if ( $this->data['undelete'] ) {
-                                       ?>
-                                       <div id="contentSub2"><?php $this->html( 'undelete' ) ?></div>
-                               <?php
-                               }
-                               ?>
-                               <?php
-                               if ( $this->data['newtalk'] ) {
-                                       ?>
-                                       <div class="usermessage"><?php $this->html( 'newtalk' ) ?></div>
-                               <?php
-                               }
-                               ?>
-                               <div id="jump-to-nav" class="mw-jump">
-                                       <?php $this->msg( 'jumpto' ) ?>
-                                       <a href="#mw-navigation"><?php
-                                               $this->msg( 'jumptonavigation' )
-                                               ?></a><?php
-                                       $this->msg( 'comma-separator' )
-                                       ?>
-                                       <a href="#p-search"><?php $this->msg( 'jumptosearch' ) ?></a>
-                               </div>
-                               <?php $this->html( 'bodycontent' ) ?>
-                               <?php
-                               if ( $this->data['printfooter'] ) {
-                                       ?>
-                                       <div class="printfooter">
-                                               <?php $this->html( 'printfooter' ); ?>
-                                       </div>
-                               <?php
-                               }
-                               ?>
-                               <?php
-                               if ( $this->data['catlinks'] ) {
-                                       ?>
-                                       <?php
-                                       $this->html( 'catlinks' );
-                                       ?>
-                               <?php
-                               }
-                               ?>
-                               <?php
-                               if ( $this->data['dataAfterContent'] ) {
-                                       ?>
-                                       <?php
-                                       $this->html( 'dataAfterContent' );
-                                       ?>
-                               <?php
-                               }
-                               ?>
-                               <div class="visualClear"></div>
-                               <?php $this->html( 'debughtml' ); ?>
-                       </div>
-               </div>
-               <div id="mw-navigation">
-                       <h2><?php $this->msg( 'navigation-heading' ) ?></h2>
-
-                       <div id="mw-head">
-                               <?php $this->renderNavigation( 'PERSONAL' ); ?>
-                               <div id="left-navigation">
-                                       <?php $this->renderNavigation( array( 'NAMESPACES', 'VARIANTS' ) ); ?>
-                               </div>
-                               <div id="right-navigation">
-                                       <?php $this->renderNavigation( array( 'VIEWS', 'ACTIONS', 'SEARCH' ) ); ?>
-                               </div>
-                       </div>
-                       <div id="mw-panel">
-                               <div id="p-logo" role="banner"><a style="background-image: url(<?php
-                                       $this->text( 'logopath' )
-                                       ?>);" href="<?php
-                                       echo htmlspecialchars( $this->data['nav_urls']['mainpage']['href'] )
-                                       ?>" <?php
-                                       echo Xml::expandAttributes( Linker::tooltipAndAccesskeyAttribs( 'p-logo' ) )
-                                       ?>></a></div>
-                               <?php $this->renderPortals( $this->data['sidebar'] ); ?>
-                       </div>
-               </div>
-               <div id="footer" role="contentinfo"<?php $this->html( 'userlangattributes' ) ?>>
-                       <?php
-                       foreach ( $this->getFooterLinks() as $category => $links ) {
-                               ?>
-                               <ul id="footer-<?php
-                               echo $category
-                               ?>">
-                                       <?php
-                                       foreach ( $links as $link ) {
-                                               ?>
-                                               <li id="footer-<?php
-                                               echo $category
-                                               ?>-<?php
-                                               echo $link
-                                               ?>"><?php
-                                                       $this->html( $link )
-                                                       ?></li>
-                                       <?php
-                                       }
-                                       ?>
-                               </ul>
-                       <?php
-                       }
-                       ?>
-                       <?php $footericons = $this->getFooterIcons( "icononly" );
-                       if ( count( $footericons ) > 0 ) {
-                               ?>
-                               <ul id="footer-icons" class="noprint">
-                                       <?php
-                                       foreach ( $footericons as $blockName => $footerIcons ) {
-                                               ?>
-                                               <li id="footer-<?php
-                                               echo htmlspecialchars( $blockName ); ?>ico">
-                                                       <?php
-                                                       foreach ( $footerIcons as $icon ) {
-                                                               ?>
-                                                               <?php
-                                                               echo $this->getSkin()->makeFooterIcon( $icon );
-                                                               ?>
-
-                                                       <?php
-                                                       }
-                                                       ?>
-                                               </li>
-                                       <?php
-                                       }
-                                       ?>
-                               </ul>
-                       <?php
-                       }
-                       ?>
-                       <div style="clear:both"></div>
-               </div>
-               <?php $this->printTrail(); ?>
-
-       </body>
-</html>
-       <?php
-       }
-
-       /**
-        * Render a series of portals
-        *
-        * @param array $portals
-        */
-       protected function renderPortals( $portals ) {
-               // Force the rendering of the following portals
-               if ( !isset( $portals['SEARCH'] ) ) {
-                       $portals['SEARCH'] = true;
-               }
-               if ( !isset( $portals['TOOLBOX'] ) ) {
-                       $portals['TOOLBOX'] = true;
-               }
-               if ( !isset( $portals['LANGUAGES'] ) ) {
-                       $portals['LANGUAGES'] = true;
-               }
-               // Render portals
-               foreach ( $portals as $name => $content ) {
-                       if ( $content === false ) {
-                               continue;
-                       }
-
-                       switch ( $name ) {
-                               case 'SEARCH':
-                                       break;
-                               case 'TOOLBOX':
-                                       $this->renderPortal( 'tb', $this->getToolbox(), 'toolbox', 'SkinTemplateToolboxEnd' );
-                                       break;
-                               case 'LANGUAGES':
-                                       if ( $this->data['language_urls'] !== false ) {
-                                               $this->renderPortal( 'lang', $this->data['language_urls'], 'otherlanguages' );
-                                       }
-                                       break;
-                               default:
-                                       $this->renderPortal( $name, $content );
-                                       break;
-                       }
-               }
-       }
-
-       /**
-        * @param string $name
-        * @param array $content
-        * @param null|string $msg
-        * @param null|string|array $hook
-        */
-       protected function renderPortal( $name, $content, $msg = null, $hook = null ) {
-               if ( $msg === null ) {
-                       $msg = $name;
-               }
-               $msgObj = wfMessage( $msg );
-               ?>
-               <div class="portal" role="navigation" id='<?php
-               echo Sanitizer::escapeId( "p-$name" )
-               ?>'<?php
-               echo Linker::tooltip( 'p-' . $name )
-               ?> aria-labelledby='<?php echo Sanitizer::escapeId( "p-$name-label" ) ?>'>
-                       <h3<?php
-                       $this->html( 'userlangattributes' )
-                       ?> id='<?php
-                       echo Sanitizer::escapeId( "p-$name-label" )
-                       ?>'><?php
-                               echo htmlspecialchars( $msgObj->exists() ? $msgObj->text() : $msg );
-                               ?></h3>
-
-                       <div class="body">
-                               <?php
-                               if ( is_array( $content ) ) {
-                                       ?>
-                                       <ul>
-                                               <?php
-                                               foreach ( $content as $key => $val ) {
-                                                       ?>
-                                                       <?php echo $this->makeListItem( $key, $val ); ?>
-
-                                               <?php
-                                               }
-                                               if ( $hook !== null ) {
-                                                       wfRunHooks( $hook, array( &$this, true ) );
-                                               }
-                                               ?>
-                                       </ul>
-                               <?php
-                               } else {
-                                       ?>
-                                       <?php
-                                       echo $content; /* Allow raw HTML block to be defined by extensions */
-                               }
-
-                               $this->renderAfterPortlet( $name );
-                               ?>
-                       </div>
-               </div>
-       <?php
-       }
-
-       /**
-        * Render one or more navigations elements by name, automatically reveresed
-        * when UI is in RTL mode
-        *
-        * @param array $elements
-        */
-       protected function renderNavigation( $elements ) {
-               global $wgVectorUseSimpleSearch;
-
-               // If only one element was given, wrap it in an array, allowing more
-               // flexible arguments
-               if ( !is_array( $elements ) ) {
-                       $elements = array( $elements );
-                       // If there's a series of elements, reverse them when in RTL mode
-               } elseif ( $this->data['rtl'] ) {
-                       $elements = array_reverse( $elements );
-               }
-               // Render elements
-               foreach ( $elements as $name => $element ) {
-                       switch ( $element ) {
-                               case 'NAMESPACES':
-                                       ?>
-                                       <div id="p-namespaces" role="navigation" class="vectorTabs<?php
-                                       if ( count( $this->data['namespace_urls'] ) == 0 ) {
-                                               echo ' emptyPortlet';
-                                       }
-                                       ?>" aria-labelledby="p-namespaces-label">
-                                               <h3 id="p-namespaces-label"><?php $this->msg( 'namespaces' ) ?></h3>
-                                               <ul<?php $this->html( 'userlangattributes' ) ?>>
-                                                       <?php
-                                                       foreach ( $this->data['namespace_urls'] as $link ) {
-                                                               ?>
-                                                               <li <?php
-                                                               echo $link['attributes']
-                                                               ?>><span><a href="<?php
-                                                                               echo htmlspecialchars( $link['href'] )
-                                                                               ?>" <?php
-                                                                               echo $link['key']
-                                                                               ?>><?php
-                                                                                       echo htmlspecialchars( $link['text'] )
-                                                                                       ?></a></span></li>
-                                                       <?php
-                                                       }
-                                                       ?>
-                                               </ul>
-                                       </div>
-                                       <?php
-                                       break;
-                               case 'VARIANTS':
-                                       ?>
-                                       <div id="p-variants" role="navigation" class="vectorMenu<?php
-                                       if ( count( $this->data['variant_urls'] ) == 0 ) {
-                                               echo ' emptyPortlet';
-                                       }
-                                       ?>" aria-labelledby="p-variants-label">
-                                               <h3 id="mw-vector-current-variant">
-                                                       <?php
-                                                       foreach ( $this->data['variant_urls'] as $link ) {
-                                                               ?>
-                                                               <?php
-                                                               if ( stripos( $link['attributes'], 'selected' ) !== false ) {
-                                                                       ?>
-                                                                       <?php
-                                                                       echo htmlspecialchars( $link['text'] )
-                                                                       ?>
-                                                               <?php
-                                                               }
-                                                               ?>
-                                                       <?php
-                                                       }
-                                                       ?>
-                                               </h3>
-
-                                               <h3 id="p-variants-label"><span><?php $this->msg( 'variants' ) ?></span><a href="#"></a></h3>
-
-                                               <div class="menu">
-                                                       <ul>
-                                                               <?php
-                                                               foreach ( $this->data['variant_urls'] as $link ) {
-                                                                       ?>
-                                                                       <li<?php
-                                                                       echo $link['attributes']
-                                                                       ?>><a href="<?php
-                                                                               echo htmlspecialchars( $link['href'] )
-                                                                               ?>" lang="<?php
-                                                                               echo htmlspecialchars( $link['lang'] )
-                                                                               ?>" hreflang="<?php
-                                                                               echo htmlspecialchars( $link['hreflang'] )
-                                                                               ?>" <?php
-                                                                               echo $link['key']
-                                                                               ?>><?php
-                                                                                       echo htmlspecialchars( $link['text'] )
-                                                                                       ?></a></li>
-                                                               <?php
-                                                               }
-                                                               ?>
-                                                       </ul>
-                                               </div>
-                                       </div>
-                                       <?php
-                                       break;
-                               case 'VIEWS':
-                                       ?>
-                                       <div id="p-views" role="navigation" class="vectorTabs<?php
-                                       if ( count( $this->data['view_urls'] ) == 0 ) {
-                                               echo ' emptyPortlet';
-                                       }
-                                       ?>" aria-labelledby="p-views-label">
-                                               <h3 id="p-views-label"><?php $this->msg( 'views' ) ?></h3>
-                                               <ul<?php
-                                               $this->html( 'userlangattributes' )
-                                               ?>>
-                                                       <?php
-                                                       foreach ( $this->data['view_urls'] as $link ) {
-                                                               ?>
-                                                               <li<?php
-                                                               echo $link['attributes']
-                                                               ?>><span><a href="<?php
-                                                                               echo htmlspecialchars( $link['href'] )
-                                                                               ?>" <?php
-                                                                               echo $link['key']
-                                                                               ?>><?php
-                                                                                       // $link['text'] can be undefined - bug 27764
-                                                                                       if ( array_key_exists( 'text', $link ) ) {
-                                                                                               echo array_key_exists( 'img', $link )
-                                                                                                       ? '<img src="' . $link['img'] . '" alt="' . $link['text'] . '" />'
-                                                                                                       : htmlspecialchars( $link['text'] );
-                                                                                       }
-                                                                                       ?></a></span></li>
-                                                       <?php
-                                                       }
-                                                       ?>
-                                               </ul>
-                                       </div>
-                                       <?php
-                                       break;
-                               case 'ACTIONS':
-                                       ?>
-                                       <div id="p-cactions" role="navigation" class="vectorMenu<?php
-                                       if ( count( $this->data['action_urls'] ) == 0 ) {
-                                               echo ' emptyPortlet';
-                                       }
-                                       ?>" aria-labelledby="p-cactions-label">
-                                               <h3 id="p-cactions-label"><span><?php $this->msg( 'vector-more-actions' ) ?></span><a href="#"></a></h3>
-
-                                               <div class="menu">
-                                                       <ul<?php $this->html( 'userlangattributes' ) ?>>
-                                                               <?php
-                                                               foreach ( $this->data['action_urls'] as $link ) {
-                                                                       ?>
-                                                                       <li<?php
-                                                                       echo $link['attributes']
-                                                                       ?>>
-                                                                               <a href="<?php
-                                                                               echo htmlspecialchars( $link['href'] )
-                                                                               ?>" <?php
-                                                                               echo $link['key'] ?>><?php echo htmlspecialchars( $link['text'] )
-                                                                                       ?></a>
-                                                                       </li>
-                                                               <?php
-                                                               }
-                                                               ?>
-                                                       </ul>
-                                               </div>
-                                       </div>
-                                       <?php
-                                       break;
-                               case 'PERSONAL':
-                                       ?>
-                                       <div id="p-personal" role="navigation" class="<?php
-                                       if ( count( $this->data['personal_urls'] ) == 0 ) {
-                                               echo ' emptyPortlet';
-                                       }
-                                       ?>" aria-labelledby="p-personal-label">
-                                               <h3 id="p-personal-label"><?php $this->msg( 'personaltools' ) ?></h3>
-                                               <ul<?php $this->html( 'userlangattributes' ) ?>>
-                                                       <?php
-                                                       $personalTools = $this->getPersonalTools();
-                                                       foreach ( $personalTools as $key => $item ) {
-                                                               echo $this->makeListItem( $key, $item );
-                                                       }
-                                                       ?>
-                                               </ul>
-                                       </div>
-                                       <?php
-                                       break;
-                               case 'SEARCH':
-                                       ?>
-                                       <div id="p-search" role="search">
-                                               <h3<?php $this->html( 'userlangattributes' ) ?>>
-                                                       <label for="searchInput"><?php $this->msg( 'search' ) ?></label>
-                                               </h3>
-
-                                               <form action="<?php $this->text( 'wgScript' ) ?>" id="searchform">
-                                                       <?php
-                                                       if ($wgVectorUseSimpleSearch) {
-                                                       ?>
-                                                       <div id="simpleSearch">
-                                                               <?php
-                                                       } else {
-                                                       ?>
-                                                               <div>
-                                                                       <?php
-                                                       }
-                                                       ?>
-                                                       <?php
-                                                       echo $this->makeSearchInput( array( 'id' => 'searchInput' ) );
-                                                       echo Html::hidden( 'title', $this->get( 'searchtitle' ) );
-                                                       // We construct two buttons (for 'go' and 'fulltext' search modes),
-                                                       // but only one will be visible and actionable at a time (they are
-                                                       // overlaid on top of each other in CSS).
-                                                       // * Browsers will use the 'fulltext' one by default (as it's the
-                                                       //   first in tree-order), which is desirable when they are unable
-                                                       //   to show search suggestions (either due to being broken or
-                                                       //   having JavaScript turned off).
-                                                       // * The mediawiki.searchSuggest module, after doing tests for the
-                                                       //   broken browsers, removes the 'fulltext' button and handles
-                                                       //   'fulltext' search itself; this will reveal the 'go' button and
-                                                       //   cause it to be used.
-                                                       echo $this->makeSearchButton(
-                                                               'fulltext',
-                                                               array( 'id' => 'mw-searchButton', 'class' => 'searchButton mw-fallbackSearchButton' )
-                                                       );
-                                                       echo $this->makeSearchButton(
-                                                               'go',
-                                                               array( 'id' => 'searchButton', 'class' => 'searchButton' )
-                                                       );
-                                                       ?>
-                                                               </div>
-                                               </form>
-                                       </div>
-                                       <?php
-
-                                       break;
-                       }
-               }
-       }
-}
diff --git a/skins/Vector/collapsibleTabs.js b/skins/Vector/collapsibleTabs.js
deleted file mode 100644 (file)
index e24bea9..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/**
- * Collapsible tabs jQuery Plugin
- */
-( function ( $ ) {
-       var rtl = $( 'html' ).attr( 'dir' ) === 'rtl';
-       $.fn.collapsibleTabs = function ( options ) {
-               // return if the function is called on an empty jquery object
-               if ( !this.length ) {
-                       return this;
-               }
-               // Merge options into the defaults
-               var settings = $.extend( {}, $.collapsibleTabs.defaults, options );
-
-               this.each( function () {
-                       var $el = $( this );
-                       // add the element to our array of collapsible managers
-                       $.collapsibleTabs.instances = ( $.collapsibleTabs.instances.length === 0 ?
-                               $el : $.collapsibleTabs.instances.add( $el ) );
-                       // attach the settings to the elements
-                       $el.data( 'collapsibleTabsSettings', settings );
-                       // attach data to our collapsible elements
-                       $el.children( settings.collapsible ).each( function () {
-                               $.collapsibleTabs.addData( $( this ) );
-                       } );
-               } );
-
-               // if we haven't already bound our resize handler, bind it now
-               if ( !$.collapsibleTabs.boundEvent ) {
-                       $( window ).on( 'resize', $.debounce( 500, function () {
-                               $.collapsibleTabs.handleResize();
-                       } ) );
-                       $.collapsibleTabs.boundEvent = true;
-               }
-
-               // call our resize handler to setup the page
-               $.collapsibleTabs.handleResize();
-               return this;
-       };
-       $.collapsibleTabs = {
-               instances: [],
-               boundEvent: null,
-               defaults: {
-                       expandedContainer: '#p-views ul',
-                       collapsedContainer: '#p-cactions ul',
-                       collapsible: 'li.collapsible',
-                       shifting: false,
-                       expandCondition: function ( eleWidth ) {
-                               // If there are at least eleWidth + 1 pixels of free space, expand.
-                               // We add 1 because .width() will truncate fractional values but .offset() will not.
-                               return $.collapsibleTabs.calculateTabDistance() >= eleWidth + 1;
-                       },
-                       collapseCondition: function () {
-                               // If there's an overlap, collapse.
-                               return $.collapsibleTabs.calculateTabDistance() < 0;
-                       }
-               },
-               addData: function ( $collapsible ) {
-                       var settings = $collapsible.parent().data( 'collapsibleTabsSettings' );
-                       if ( settings ) {
-                               $collapsible.data( 'collapsibleTabsSettings', {
-                                       expandedContainer: settings.expandedContainer,
-                                       collapsedContainer: settings.collapsedContainer,
-                                       expandedWidth: $collapsible.width(),
-                                       prevElement: $collapsible.prev()
-                               } );
-                       }
-               },
-               getSettings: function ( $collapsible ) {
-                       var settings = $collapsible.data( 'collapsibleTabsSettings' );
-                       if ( !settings ) {
-                               $.collapsibleTabs.addData( $collapsible );
-                               settings = $collapsible.data( 'collapsibleTabsSettings' );
-                       }
-                       return settings;
-               },
-               handleResize: function () {
-                       $.collapsibleTabs.instances.each( function () {
-                               var $el = $( this ),
-                                       data = $.collapsibleTabs.getSettings( $el );
-
-                               if ( data.shifting ) {
-                                       return;
-                               }
-
-                               // if the two navigations are colliding
-                               if ( $el.children( data.collapsible ).length > 0 && data.collapseCondition() ) {
-
-                                       $el.trigger( 'beforeTabCollapse' );
-                                       // move the element to the dropdown menu
-                                       $.collapsibleTabs.moveToCollapsed( $el.children( data.collapsible + ':last' ) );
-                               }
-
-                               // if there are still moveable items in the dropdown menu,
-                               // and there is sufficient space to place them in the tab container
-                               if ( $( data.collapsedContainer + ' ' + data.collapsible ).length > 0 &&
-                                               data.expandCondition( $.collapsibleTabs.getSettings( $( data.collapsedContainer ).children(
-                                                               data.collapsible + ':first' ) ).expandedWidth ) ) {
-                                       //move the element from the dropdown to the tab
-                                       $el.trigger( 'beforeTabExpand' );
-                                       $.collapsibleTabs
-                                               .moveToExpanded( data.collapsedContainer + ' ' + data.collapsible + ':first' );
-                               }
-                       } );
-               },
-               moveToCollapsed: function ( ele ) {
-                       var outerData, expContainerSettings, target,
-                               $moving = $( ele );
-
-                       outerData = $.collapsibleTabs.getSettings( $moving );
-                       if ( !outerData ) {
-                               return;
-                       }
-                       expContainerSettings = $.collapsibleTabs.getSettings( $( outerData.expandedContainer ) );
-                       if ( !expContainerSettings ) {
-                               return;
-                       }
-                       expContainerSettings.shifting = true;
-
-                       // Remove the element from where it's at and put it in the dropdown menu
-                       target = outerData.collapsedContainer;
-                       $moving.css( 'position', 'relative' )
-                               .css( ( rtl ? 'left' : 'right' ), 0 )
-                               .animate( { width: '1px' }, 'normal', function () {
-                                       var data, expContainerSettings;
-                                       $( this ).hide();
-                                       // add the placeholder
-                                       $( '<span class="placeholder" style="display: none;"></span>' ).insertAfter( this );
-                                       $( this ).detach().prependTo( target ).data( 'collapsibleTabsSettings', outerData );
-                                       $( this ).attr( 'style', 'display: list-item;' );
-                                       data = $.collapsibleTabs.getSettings( $( ele ) );
-                                       if ( data ) {
-                                               expContainerSettings = $.collapsibleTabs.getSettings( $( data.expandedContainer ) );
-                                               if ( expContainerSettings ) {
-                                                       expContainerSettings.shifting = false;
-                                                       $.collapsibleTabs.handleResize();
-                                               }
-                                       }
-                               } );
-               },
-               moveToExpanded: function ( ele ) {
-                       var data, expContainerSettings, $target, expandedWidth,
-                               $moving = $( ele );
-
-                       data = $.collapsibleTabs.getSettings( $moving );
-                       if ( !data ) {
-                               return;
-                       }
-                       expContainerSettings = $.collapsibleTabs.getSettings( $( data.expandedContainer ) );
-                       if ( !expContainerSettings ) {
-                               return;
-                       }
-                       expContainerSettings.shifting = true;
-
-                       // grab the next appearing placeholder so we can use it for replacing
-                       $target = $( data.expandedContainer ).find( 'span.placeholder:first' );
-                       expandedWidth = data.expandedWidth;
-                       $moving.css( 'position', 'relative' ).css( ( rtl ? 'right' : 'left' ), 0 ).css( 'width', '1px' );
-                       $target.replaceWith(
-                               $moving
-                               .detach()
-                               .css( 'width', '1px' )
-                               .data( 'collapsibleTabsSettings', data )
-                               .animate( { width: expandedWidth + 'px' }, 'normal', function () {
-                                       $( this ).attr( 'style', 'display: block;' );
-                                       var data, expContainerSettings;
-                                       data = $.collapsibleTabs.getSettings( $( this ) );
-                                       if ( data ) {
-                                               expContainerSettings = $.collapsibleTabs.getSettings( $( data.expandedContainer ) );
-                                               if ( expContainerSettings ) {
-                                                       expContainerSettings.shifting = false;
-                                                       $.collapsibleTabs.handleResize();
-                                               }
-                                       }
-                               } )
-                       );
-               },
-               /**
-                * Returns the amount of horizontal distance between the two tabs groups
-                * (#left-navigation and #right-navigation), in pixels. If negative, this
-                * means that the tabs overlap, and the value is the width of overlapping
-                * parts.
-                *
-                * Used in default expandCondition and collapseCondition.
-                *
-                * @return {Numeric} distance/overlap in pixels
-                */
-               calculateTabDistance: function () {
-                       var $leftTab, $rightTab, leftEnd, rightStart;
-
-                       // In RTL, #right-navigation is actually on the left and vice versa.
-                       // Hooray for descriptive naming.
-                       if ( !rtl ) {
-                               $leftTab = $( '#left-navigation' );
-                               $rightTab = $( '#right-navigation' );
-                       } else {
-                               $leftTab = $( '#right-navigation' );
-                               $rightTab = $( '#left-navigation' );
-                       }
-
-                       leftEnd = $leftTab.offset().left + $leftTab.width();
-                       rightStart = $rightTab.offset().left;
-
-                       return rightStart - leftEnd;
-               }
-       };
-
-}( jQuery ) );
diff --git a/skins/Vector/components/animations.less b/skins/Vector/components/animations.less
deleted file mode 100644 (file)
index 9163779..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Animate between standard and high definition layouts */
-body.vector-animateLayout {
-       div#content,
-       div#footer,
-       #left-navigation {
-               .transition(margin-left 250ms, padding 250ms;);
-       }
-
-       #p-logo {
-               .transition(left 250ms);
-       }
-
-       #mw-panel {
-               .transition(padding-right 250ms);
-       }
-
-       #p-search {
-               .transition(margin-right 250ms);
-       }
-
-       #p-personal {
-               .transition(right 250ms);
-       }
-
-       #mw-head-base {
-               .transition(margin-left 250ms);
-       }
-}
diff --git a/skins/Vector/components/common.less b/skins/Vector/components/common.less
deleted file mode 100644 (file)
index 33cd230..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Any rules which should not be flipped automatically in right-to-left situations should be
- * prepended with @noflip in a comment block.
- *
- * This stylesheet employs a few CSS trick to accomplish compatibility with a wide range of web
- * browsers. The most common trick is to use some styles in IE6 only. This is accomplished by using
- * a rule that makes things work in IE6, and then following it with a rule that begins with
- * "html > body" or use a child selector ">", which is ignored by IE6 because it does not support
- * the child selector. You can spot this by looking for the "OVERRIDDEN BY COMPLIANT BROWSERS" and
- * "IGNORED BY IE6" comments.
- */
-@import "mediawiki.mixins";
-
-/* Framework */
-html {
-       font-size: @html-font-size;
-}
-html,
-body {
-       height: 100%;
-       margin: 0;
-       padding: 0;
-       font-family: @content-font-family;
-}
-body {
-       background-color: @menu-background-color;
-}
-
-/* Content */
-div#content {
-       margin-left: 10em;
-       padding: @content-padding;
-       /* Border on top, left, and bottom side */
-       border: 1px solid @content-border-color;
-       border-right-width: 0;
-       /* Merge the border with tabs' one (in their background image) */
-       margin-top: -1px;
-       background-color: @body-background-color;
-       color: @content-font-color;
-       direction: ltr;
-
-       .mw-editsection,
-       .mw-editsection-like {
-               font-family: @content-font-family;
-       }
-
-       p {
-               line-height: inherit;
-               margin: 0.5em 0;
-       }
-
-       h1,
-       h2,
-       #firstHeading {
-               font-family: @content-heading-font-family;
-               line-height: @heading-line-height;
-               margin-bottom: 0.25em;
-               padding: 0;
-       }
-
-       h1,
-       #firstHeading {
-               font-size: @content-heading-font-size;
-       }
-
-       h2 {
-               font-size: 1.5em;
-               margin-top: 1em;
-       }
-
-       h3,
-       h4,
-       h5,
-       h6 {
-               line-height: @content-line-height;
-               margin-top: 0.3em;
-               margin-bottom: 0;
-               padding-bottom: 0;
-       }
-
-       h3 {
-               font-size: 1.17em;
-       }
-
-       h3,
-       h4 {
-               font-weight: bold;
-       }
-
-       h4,
-       h5,
-       h6 {
-               font-size: 100%; /* (reset) */
-       }
-
-       #toc h2,
-       .toc h2 {
-               font-size: 100%; /* (reset) */
-               font-family: @content-font-family;
-       }
-}
-
-/* Hide empty portlets */
-div.emptyPortlet {
-               display: none;
-}
-
-ul {
-       list-style-type: disc;
-       .list-style-image('images/bullet-icon.png');
-}
-
-pre, .mw-code {
-       line-height: 1.3em;
-}
-
-/* Site Notice (includes notices from CentralNotice extension) */
-#siteNotice {
-       font-size: 0.8em;
-}
-
-.redirectText {
-       font-size: 140%;
-}
-
-.redirectMsg img {
-       vertical-align: text-bottom;
-}
-
-.mw-body-content {
-       position: relative;
-       line-height: @content-line-height;
-       font-size: @content-font-size;
-}
-
-/* Tooltips are outside of the normal body code, so this helps make the size of the text sensible */
-// FIXME: Should be part of jquery.tipsy.css
-.tipsy {
-       font-size: 0.8em;
-}
diff --git a/skins/Vector/components/externalLinks.less b/skins/Vector/components/externalLinks.less
deleted file mode 100644 (file)
index 91388c6..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-@import "mediawiki.mixins.less";
-// External links
-#content {
-       .external {
-               background-position: center right;
-               background-repeat: no-repeat;
-               .background-image-svg('images/external-link-ltr-icon.svg', 'images/external-link-ltr-icon.png');
-               padding-right: 13px;
-       }
-}
diff --git a/skins/Vector/components/footer.less b/skins/Vector/components/footer.less
deleted file mode 100644 (file)
index 3d61b66..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Footer */
-div#footer {
-       margin-left: 10em;
-       margin-top: 0;
-       padding: 0.75em;
-       direction: ltr;
-
-       ul {
-               list-style-type: none;
-               list-style-image: none;
-               margin: 0;
-               padding: 0;
-
-               li {
-                       margin: 0;
-                       padding: 0;
-                       padding-top: 0.5em;
-                       padding-bottom: 0.5em;
-                       color: #333;
-                       font-size: 0.7em;
-               }
-       }
-
-       #footer-icons {
-               float: right;
-
-               li {
-                       float: left;
-                       margin-left: 0.5em;
-                       line-height: 2em;
-                       text-align: right;
-               }
-       }
-
-       #footer-info {
-               li {
-                       line-height: 1.4em;
-               }
-       }
-
-       #footer-places {
-               li {
-                       float: left;
-                       margin-right: 1em;
-                       line-height: 2em;
-               }
-       }
-}
-
-body.ltr {
-       div#footer {
-               #footer-places {
-                       /* @noflip */
-                       float: left;
-               }
-       }
-}
diff --git a/skins/Vector/components/navigation.less b/skins/Vector/components/navigation.less
deleted file mode 100644 (file)
index 8b384ac..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-@import "mediawiki.mixins";
-@import "personalMenu";
-@import "search";
-@import "tabs";
-
-/* Hide, but keep accessible for screen-readers */
-#mw-navigation h2 {
-       position: absolute;
-       top: -9999px;
-}
-
-/* Head */
-#mw-page-base {
-       height: 5em;
-       background-position: bottom left;
-       background-repeat: repeat-x;
-       /* This image is only a fallback (for IE 6-9), so we do not @embed it. */
-       background-image: url('images/page-fade.png');
-       .vertical-gradient(@body-background-color, @menu-background-color, 50%, 100%);
-       background-color: @body-background-color;
-}
-
-#mw-head-base {
-       margin-top: -5em;
-       margin-left: 10em;
-       height: 5em;
-}
-
-div#mw-head {
-       position: absolute;
-       top: 0;
-       right: 0;
-       width: 100%;
-
-       h3 {
-               margin: 0;
-               padding: 0;
-       }
-}
-
-/* Navigation Containers */
-#left-navigation {
-       float: left;
-       margin-left: 10em;
-       margin-top: 2.5em;
-       /* When right nav would overlap left nav, it's placed below it
-          (normal CSS floats behavior). This rule ensures that no empty space
-          is shown between them due to right nav's margin-top. Page layout
-          is still broken, but at least the nav overlaps only the page title
-          instead of half the content. */
-       margin-bottom: -2.5em;
-       /* IE 6 double-margin bug fix */
-       display: inline;
-}
-
-#right-navigation {
-       float: right;
-       margin-top: 2.5em;
-}
-
-/* Logo */
-#p-logo {
-       position: absolute;
-       top: -160px;
-       left: 0;
-       width: 10em;
-       height: 160px;
-
-       a {
-               display: block;
-               width: 10em;
-               height: 160px;
-               background-repeat: no-repeat;
-               background-position: center center;
-               text-decoration: none;
-       }
-}
-
-/* Panel */
-div#mw-panel {
-       font-size: @menu-main-font-size;
-       position: absolute;
-       top: 160px;
-       padding-top: 1em;
-       width: 10em;
-       left: 0;
-
-       div.portal {
-               margin: 0 0.6em 0 0.7em;
-               padding: 0.25em 0;
-               direction: ltr;
-               background-position: top left;
-               background-repeat: no-repeat;
-               .background-image('images/portal-break.png');
-
-               h3 {
-                       font-size: @menu-main-heading-font-size;
-                       color: @menu-main-heading-color;
-                       font-weight: normal;
-                       margin: 0;
-                       padding: @menu-main-heading-padding;
-                       cursor: default;
-                       border: none;
-               }
-
-               div.body {
-                       margin: @menu-main-body-margin;
-                       padding-top: 0;
-
-                       ul {
-                               list-style-type: none;
-                               list-style-image: none;
-                               margin: 0;
-                               padding: @menu-main-body-padding;
-
-                               li {
-                                       line-height: 1.125em;
-                                       margin: 0;
-                                       padding: 0.25em 0;
-                                       font-size: @menu-main-body-font-size;
-                                       word-wrap: break-word;
-
-                                       a {
-                                               color: @menu-main-body-link-color;
-                                               &:visited {
-                                                       color: @menu-main-body-link-visited-color;
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               &.first {
-                       background-image: none;
-                       margin-top: 0;
-                       h3 {
-                               display: none;
-                       }
-                       div.body {
-                               margin-left: 0.5em;
-                       }
-               }
-       }
-}
diff --git a/skins/Vector/components/notifications.less b/skins/Vector/components/notifications.less
deleted file mode 100644 (file)
index 05a1e61..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/* mediawiki.notification */
-.skin-vector {
-       .mw-notification-area {
-               font-size: 0.8em;
-       }
-
-       .mw-notification-area-layout {
-               top: 7em;
-       }
-
-       .mw-notification {
-               background-color: #fff;
-               background-color: rgba(255, 255, 255, 0.93);
-               padding: 0.75em 1.5em;
-               border: solid 1px @content-border-color;
-               border-radius: 0.75em;
-               box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.125);
-       }
-}
diff --git a/skins/Vector/components/personalMenu.less b/skins/Vector/components/personalMenu.less
deleted file mode 100644 (file)
index 7256929..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Personal */
-#p-personal {
-       position: absolute;
-       top: 0.33em;
-       right: 0.75em;
-       /* Display on top of page tabs - bugs 37158, 48078 */
-       z-index: 100;
-
-       h3 {
-               display: none;
-       }
-
-       ul {
-               list-style-type: none;
-               list-style-image: none;
-               margin: 0;
-               padding-left: 10em; /* Keep from overlapping logo */
-       }
-
-       li {
-               line-height: 1.125em;
-               /* @noflip */
-               float: left;
-               margin-left: 0.75em;
-               margin-top: 0.5em;
-               font-size: @menu-personal-font-size;
-               white-space: nowrap;
-       }
-}
-
-/* Icon for Usernames */
-#pt-userpage,
-#pt-anonuserpage,
-#pt-login {
-       background-position: left top;
-       background-repeat: no-repeat;
-       /* SVG support using a transparent gradient to guarantee cross-browser
-        * compatibility (browsers able to understand gradient syntax support also SVG) */
-       .background-image-svg('images/user-icon.svg', 'images/user-icon.png');
-       padding-left: 15px !important;
-}
diff --git a/skins/Vector/components/search.less b/skins/Vector/components/search.less
deleted file mode 100644 (file)
index 46c3030..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Search */
-#p-search {
-       /* @noflip */
-       float: left;
-       margin-right: 0.5em;
-       margin-left: 0.5em;
-
-       h3 {
-               display: none;
-       }
-
-       form,
-       input {
-               margin: 0;
-               margin-top: 0.4em;
-       }
-}
-
-div#simpleSearch {
-       display: block;
-       width: 14em;
-       height: 1.4em;
-       margin-top: 0.65em;
-       position: relative;
-       min-height: 1px; /* Gotta trigger hasLayout for IE7 */
-       border: solid 1px #aaa;
-       color: black;
-       background-color: white;
-       .background-image('images/search-fade.png');
-       background-position: top left;
-       background-repeat: repeat-x;
-
-       // Styles for both the search input and the button
-       input {
-               position: absolute;
-               margin: 0;
-               padding: 0;
-               border: 0;
-               background-color: transparent;
-               color: black;
-       }
-
-       // The search input
-       #searchInput {
-               top: 0;
-               left: 0;
-               width: 90%;
-               padding: 0.2em 0 0.2em 0.2em;
-               font-size: 13px;
-               direction: ltr;
-
-               &:focus {
-                       outline: none;
-               }
-
-               // These rules MAY NOT be merged because of how CSS requires browsers
-               // to parse unrecognized selectors!
-               // Note these rules ensure that placeholder text can be distinguished from
-               // standard text. In browsers which make this distinction clear these rules
-               // are not necessary.
-               // For inputs that use jquery.placeholder.js e.g. IE9-
-               &.placeholder {
-                       color: #999;
-               }
-               // Distinguish placeholder text in IE10+
-               &:-ms-input-placeholder {
-                       color: #999;
-               }
-               // Distinguish placeholder text in Firefox 18-
-               &:-moz-placeholder {
-                       color: #999;
-               }
-
-               // Undo the styles Webkit browsers apply to type=search fields,
-               // we provide our own
-               -webkit-appearance: textfield;
-
-               &::-webkit-search-decoration,
-               &::-webkit-search-cancel-button,
-               &::-webkit-search-results-button,
-               &::-webkit-search-results-decoration {
-                       -webkit-appearance: textfield;
-               }
-       }
-
-       // The buttons. They are displayed in the same position, and if both are
-       // present the fulltext search one obscures the 'Go' one.
-       #searchButton,
-       #mw-searchButton {
-               top: 0;
-               right: 0;
-               width: 10%;
-               height: 100%;
-               cursor: pointer;
-               /* Hide button text and replace it with the image. */
-               /* This would be 100% if not for Firefox shenanigans (bug 60900). */
-               text-indent: 200%;
-               /* Needed to make IE6 respect the text-indent. */
-               line-height: 1;
-               /* Opera 12 on RTL flips the text in a funny way without this. */
-               /* @noflip */
-               direction: ltr;
-               white-space: nowrap;
-               overflow: hidden;
-               .background-image-svg('images/search-ltr.svg', 'images/search-ltr.png');
-               background-position: center center;
-               background-repeat: no-repeat;
-       }
-
-       #mw-searchButton {
-               z-index: 1;
-       }
-}
diff --git a/skins/Vector/components/tabs.less b/skins/Vector/components/tabs.less
deleted file mode 100644 (file)
index 9e39fbb..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
-Styling for namespace tabs (page, discussion) and views (read, edit, view history, watch and other actions)
-*/
-
-/* Navigation Labels */
-div.vectorTabs h3 {
-       display: none;
-}
-
-/* Namespaces and Views */
-div.vectorTabs {
-       /* @noflip */
-       float: left;
-       height: 2.5em;
-       .background-image('images/tab-break.png');
-       background-position: bottom left;
-       background-repeat: no-repeat;
-       padding-left: 1px;
-
-       ul {
-               /* @noflip */
-               float: left;
-               height: 100%;
-               list-style-type: none;
-               list-style-image: none;
-               margin: 0;
-               padding: 0;
-               .background-image('images/tab-break.png');
-               background-position: right bottom;
-               background-repeat: no-repeat;
-
-               li {
-                       /* @noflip */
-                       float: left;
-                       line-height: 1.125em;
-                       /* For IE6, overridden later to display:block by modern browsers */
-                       display: inline-block;
-                       height: 100%;
-                       margin: 0;
-                       padding: 0;
-                       background-color: #f3f3f3;
-                       .background-image('images/tab-normal-fade.png');
-                       background-position: bottom left;
-                       background-repeat: repeat-x;
-                       white-space: nowrap;
-               }
-
-               /* IGNORED BY IE6 which doesn't support child selector */
-               > li {
-                       display: block;
-               }
-       }
-
-       li {
-               &.new {
-                       a,
-                       a:visited{
-                               color: #a55858;
-                       }
-               }
-
-               &.selected {
-                       .background-image('images/tab-current-fade.png');
-                       a,
-                       a:visited{
-                               color: #333;
-                               text-decoration: none;
-                       }
-               }
-
-               &.icon {
-                       a {
-                               background-position: bottom right;
-                               background-repeat: no-repeat;
-                       }
-               }
-
-               a {
-                       /* For IE6, overridden later to display:block by modern browsers */
-                       display: inline-block;
-                       height: 1.9em;
-                       padding-left: 0.5em;
-                       padding-right: 0.5em;
-                       color: @menu-link-color;
-                       cursor: pointer;
-                       font-size: 0.8em;
-               }
-
-               /* Ignored by IE6 which doesn't support child selector */
-               > a {
-                       display: block;
-               }
-       }
-
-       span {
-               display: inline-block;
-               .background-image('images/tab-break.png');
-               background-position: bottom right;
-               background-repeat: no-repeat;
-
-               a  {
-                       /* For IE6, overridden later to display:block by modern browsers */
-                       display: inline-block;
-                       padding-top: 1.25em;
-               }
-
-               /* Ignored by IE6 which doesn't support child selector */
-               > a {
-                       /* @noflip */
-                       float: left;
-                       display: block;
-               }
-       }
-}
-
-/* Variants and Actions */
-div.vectorMenu {
-       /* @noflip */
-       direction: ltr;
-       /* @noflip */
-       float: left;
-       cursor: pointer;
-       position: relative;
-}
-
-body.rtl div.vectorMenu {
-       /* @noflip */
-       direction: rtl;
-}
-
-div#mw-head div.vectorMenu h3 {
-       /* @noflip */
-       float: left;
-       .background-image('images/tab-break.png');
-       background-repeat: no-repeat;
-       background-position: bottom right;
-       margin-left: -1px;
-       font-size: 1em;
-       height: 2.5em;
-       // This effectively moves the "background border" outside of the element to act like a real
-       // border. It is necessary for the dropdown (div.vectorMenu div.menu) to align well.
-       padding-right: 1px;
-       margin-right: -1px;
-}
-
-// The "Variants" menu has a really funny structure
-div#mw-head div.vectorMenu#p-variants {
-       #p-variants-label span {
-               display: none;
-       }
-
-       #mw-vector-current-variant {
-               display: inline-block;
-               float: left;
-               padding-right: 20px;
-               font-size: 0.8em;
-               padding-left: 0.5em;
-               padding-top: 1.375em;
-               font-weight: normal;
-               border: none;
-               background-image: none;
-       }
-}
-
-div.vectorMenu h3 span {
-       display: block;
-       font-size: 0.8em;
-       padding-left: 0.7em;
-       padding-top: 1.375em;
-       margin-right: 20px;
-       font-weight: normal;
-       color: @menu-main-heading-color;
-}
-
-div.vectorMenu h3 a {
-       position: absolute;
-       top: 0;
-       right: 0;
-       width: 20px;
-       height: 2.5em;
-       .background-image-svg('images/arrow-down-icon.svg', 'images/arrow-down-icon.png');
-       background-position: 100% 70%;
-       background-repeat: no-repeat;
-       .transition(background-position 250ms);
-}
-
-div.vectorMenu.menuForceShow h3 a {
-       background-position: 100% 100%;
-}
-
-div.vectorMenuFocus h3 a {
-       .background-image-svg('images/arrow-down-focus-icon.svg', 'images/arrow-down-focus-icon.png');
-}
-
-div.vectorMenu div.menu {
-       // Match the width of the dropdown "heading" (the tab)
-       min-width: 100%;
-       position: absolute;
-       top: 2.5em;
-       left: -1px;
-       background-color: white;
-       border: solid 1px silver;
-       border-top-width: 0;
-       clear: both;
-       text-align: left;
-       display: none;
-}
-
-/* Enable forcing showing of the menu for accessibility */
-div.vectorMenu:hover div.menu,
-div.vectorMenu.menuForceShow div.menu {
-       display: block;
-}
-
-div.vectorMenu ul {
-       list-style-type: none;
-       list-style-image: none;
-       padding: 0;
-       margin: 0;
-       text-align: left;
-}
-
-/* Fixes old versions of FireFox */
-div.vectorMenu ul,
-x:-moz-any-link {
-       min-width: 5em;
-}
-
-/* Returns things back to normal in modern versions of FireFox */
-div.vectorMenu ul,
-x:-moz-any-link,
-x:default {
-       min-width: 0;
-}
-
-div.vectorMenu li {
-       padding: 0;
-       margin: 0;
-       text-align: left;
-       line-height: 1em;
-}
-
-/* OVERRIDDEN BY COMPLIANT BROWSERS */
-div.vectorMenu li a {
-       display: inline-block;
-       padding: 0.5em;
-       white-space: nowrap;
-       color: @menu-link-color;
-       cursor: pointer;
-       font-size: 0.8em;
-}
-
-/* IGNORED BY IE6 */
-div.vectorMenu li > a {
-       display: block;
-}
-
-div.vectorMenu li.selected a,
-div.vectorMenu li.selected a:visited {
-       color: #333;
-       text-decoration: none;
-}
-
-@import 'watchstar.less';
diff --git a/skins/Vector/components/watchstar.less b/skins/Vector/components/watchstar.less
deleted file mode 100644 (file)
index a389ed6..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-@import "mediawiki.mixins.rotation"
-
-/* Watch/Unwatch Icon Styling */
-#ca-unwatch.icon a,
-#ca-watch.icon a {
-       margin: 0;
-       padding: 0;
-       display: block;
-       width: 26px;
-       /* This hides the text but shows the background image */
-       padding-top: 3.1em;
-       margin-top: 0;
-       /* Only applied in IE6 */
-       margin-top: -0.8em !ie;
-       height: 0;
-       overflow: hidden;
-       background-position: 5px 60%;
-}
-#ca-unwatch.icon a {
-       .background-image-svg('images/unwatch-icon.svg', 'images/unwatch-icon.png');
-}
-#ca-watch.icon a {
-       .background-image-svg('images/watch-icon.svg', 'images/watch-icon.png');
-}
-#ca-unwatch.icon a:hover,
-#ca-unwatch.icon a:focus {
-       .background-image-svg('images/unwatch-icon-hl.svg', 'images/unwatch-icon-hl.png');
-}
-#ca-watch.icon a:hover,
-#ca-watch.icon a:focus {
-       .background-image-svg('images/watch-icon-hl.svg', 'images/watch-icon-hl.png');
-}
-#ca-unwatch.icon a.loading,
-#ca-watch.icon a.loading {
-       .background-image-svg('images/watch-icon-loading.svg', 'images/watch-icon-loading.png');
-       .rotation(700ms);
-       /* Suppress the hilarious rotating focus outline on Firefox */
-       outline: none;
-       cursor: default;
-       pointer-events: none;
-       background-position: 50% 60%;
-       -webkit-transform-origin: 50% 57%;
-       transform-origin: 50% 57%;
-}
-#ca-unwatch.icon a span,
-#ca-watch.icon a span {
-       display: none;
-}
diff --git a/skins/Vector/csshover.htc b/skins/Vector/csshover.htc
deleted file mode 100644 (file)
index a13ea68..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-<public:attach event="ondocumentready" onevent="CSSHover()" />
-<script>
-/**
- *     Whatever:hover - V3.11
- *     ------------------------------------------------------------
- *     Author  - Peter Nederlof, http://www.xs4all.nl/~peterned
- *     License - http://creativecommons.org/licenses/LGPL/2.1
- *
- *     Special thanks to Sergiu Dumitriu, http://purl.org/net/sergiu,
- *     for fixing the expression loop.
- *
- *     Whatever:hover is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU Lesser General Public
- *     License as published by the Free Software Foundation; either
- *     version 2.1 of the License, or (at your option) any later version.
- *
- *     Whatever:hover 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
- *     Lesser General Public License for more details.
- *
- *     howto: body { behavior:url("csshover3.htc"); }
- *     ------------------------------------------------------------
- */
-
-window.CSSHover = (function(){
-
-       // regular expressions, used and explained later on.
-       var REG_INTERACTIVE = /(^|\s)((([^a]([^ ]+)?)|(a([^#.][^ ]+)+)):(hover|active|focus))/i;
-       var REG_AFFECTED = /(.*?)\:(hover|active|focus)/i;
-       var REG_PSEUDO = /[^:]+:([a-z\-]+).*/i;
-       var REG_SELECT = /(\.([a-z0-9_\-]+):[a-z]+)|(:[a-z]+)/gi;
-       var REG_CLASS = /\.([a-z0-9_\-]*on(hover|active|focus))/i;
-       var REG_MSIE = /msie (5|6|7)/i;
-       var REG_COMPAT = /backcompat/i;
-
-       // property mapping, real css properties must be used in order to clear expressions later on...
-       // Uses obscure css properties that no-one is likely to use. The properties are borrowed to
-       // set an expression, and are then restored to the most likely correct value.
-       var Properties = {
-               index: 0,
-               list: ['text-kashida', 'text-kashida-space', 'text-justify'],
-               get: function() {
-                       return this.list[(this.index++)%this.list.length];
-               }
-       };
-
-       // camelize is used to convert css properties from (eg) text-kashida to textKashida
-       var camelize = function(str) {
-               return str.replace(/-(.)/mg, function(result, match){
-                       return match.toUpperCase();
-               });
-       };
-       
-       /**
-        *      Local CSSHover object
-        *      --------------------------
-        */
-       
-       var CSSHover = {
-               
-               // array of CSSHoverElements, used to unload created events
-               elements: [], 
-               
-               // buffer used for checking on duplicate expressions
-               callbacks: {}, 
-               
-               // init, called once ondomcontentready via the exposed window.CSSHover function
-               init:function() {
-                       // don't run in IE8 standards; expressions don't work in standards mode anyway, 
-                       // and the stuff we're trying to fix should already work properly
-                       if(!REG_MSIE.test(navigator.userAgent) && !REG_COMPAT.test(window.document.compatMode)) {
-                               return;
-                       }
-
-                       // start parsing the existing stylesheets
-                       var sheets = window.document.styleSheets, l = sheets.length;
-                       for(var i=0; i<l; i++) {
-                               this.parseStylesheet(sheets[i]);
-                       }
-               },
-
-               // called from init, parses individual stylesheets
-               parseStylesheet:function(sheet) {
-                       // check sheet imports and parse those recursively
-                       if(sheet.imports) {
-                               try {
-                                       var imports = sheet.imports;
-                                       var l = imports.length;
-                                       for(var i=0; i<l; i++) {
-                                               this.parseStylesheet(sheet.imports[i]);
-                                       }
-                               } catch(securityException){
-                                       // trycatch for various possible errors
-                               }
-                       }
-                       
-                       // interate the sheet's rules and send them to the parser
-                       try {
-                               var rules = sheet.rules;
-                               var r = rules.length;
-                               for(var j=0; j<r; j++) {
-                                       this.parseCSSRule(rules[j], sheet);
-                               }
-                       } catch(someException){
-                               // trycatch for various errors, most likely accessing the sheet's rules.
-                       }
-               },
-
-               // magic starts here ...
-               parseCSSRule:function(rule, sheet) {
-                       
-                       // The sheet is used to insert new rules into, this must be the same sheet the rule 
-                       // came from, to ensure that relative paths keep pointing to the right location.
-
-                       // only parse a rule if it contains an interactive pseudo.
-                       var select = rule.selectorText;
-                       if(REG_INTERACTIVE.test(select)) {
-                               var style = rule.style.cssText;
-                                       
-                               // affected elements are found by truncating the selector after the interactive pseudo,
-                               // eg: "div li:hover" >>  "div li"
-                               var affected = REG_AFFECTED.exec(select)[1];
-                                       
-                               // that pseudo is needed for a classname, and defines the type of interaction (focus, hover, active)
-                               // eg: "li:hover" >> "onhover"
-                               var pseudo = select.replace(REG_PSEUDO, 'on$1');
-                                       
-                               // the new selector is going to use that classname in a new css rule,
-                               // since IE6 doesn't support multiple classnames, this is merged into one classname
-                               // eg: "li:hover" >> "li.onhover",  "li.folder:hover" >> "li.folderonhover"
-                               var newSelect = select.replace(REG_SELECT, '.$2' + pseudo);
-                                       
-                               // the classname is needed for the events that are going to be set on affected nodes
-                               // eg: "li.folder:hover" >> "folderonhover"
-                               var className = REG_CLASS.exec(newSelect)[1];
-
-                               // no need to set the same callback more than once when the same selector uses the same classname
-                               var hash = affected + className;
-                               if(!this.callbacks[hash]) {
-                                       
-                                       // affected elements are given an expression under a borrowed css property, because fake properties
-                                       // can't have their expressions cleared. Different properties are used per pseudo, to avoid
-                                       // expressions from overwriting eachother. The expression does a callback to CSSHover.patch, 
-                                       // rerouted via the exposed window.CSSHover function.
-                                       var property = Properties.get();
-                                       var atRuntime = camelize(property);
-
-                                       // because the expression is added to the stylesheet, and styles are always applied to html that is
-                                       // dynamically added to the dom, the expression will also trigger for those new elements (provided
-                                       // they are selected by the affected selector). 
-                                       sheet.addRule(affected, property + ':expression(CSSHover(this, "'+pseudo+'", "'+className+'", "'+atRuntime+'"))');
-                                       
-                                       // hash it, so an identical selector/class combo does not duplicate the expression
-                                       this.callbacks[hash] = true;
-                               }
-                               
-                               // duplicate expressions need not be set, but the style could differ
-                               sheet.addRule(newSelect, style);
-                       }
-               },
-
-               // called via the expression, patches individual nodes
-               patch:function(node, type, className, property) {
-
-                       // restores the borrowed css property to the value of its immediate parent, clearing
-                       // the expression so that it's not repeatedly called. 
-                       try {
-                               var value = node.parentNode.currentStyle[property];
-                               node.style[property] = value;   
-                       } catch(e) {
-                               // the above reset should never fail, but just in case, clear the runtimeStyle if it does.
-                               // this will also stop the expression.
-                               node.runtimeStyle[property] = '';
-                       }                       
-               
-                       // just to make sure, also keep track of patched classnames locally on the node
-                       if(!node.csshover) {
-                               node.csshover = [];
-                       }
-
-                       // and check for it to prevent duplicate events with the same classname from being set
-                       if(!node.csshover[className]) {
-                               node.csshover[className] = true;
-
-                               // create an instance for the given type and class
-                               var element = new CSSHoverElement(node, type, className);
-                               
-                               // and store that instance for unloading later on
-                               this.elements.push(element);
-                       }
-
-                       // returns a dummy value to the expression
-                       return type;
-               },
-
-               // unload stuff onbeforeunload
-               unload:function() {
-                       try {
-                               
-                               // remove events
-                               var l = this.elements.length;
-                               for(var i=0; i<l; i++) {
-                                       this.elements[i].unload();
-                               }
-
-                               // and set properties to null 
-                               this.elements = [];
-                               this.callbacks = {};
-
-                       } catch (e) {
-                       }
-               }
-       };
-
-       /**
-        *      CSSHoverElement
-        *      --------------------------
-        */
-
-       // the event types associated with the interactive pseudos
-       var CSSEvents = {
-               onhover:  { activator: 'onmouseenter', deactivator: 'onmouseleave' },
-               onactive: { activator: 'onmousedown',  deactivator: 'onmouseup' },
-               onfocus:  { activator: 'onfocus',      deactivator: 'onblur' }
-       };
-       
-       // CSSHoverElement constructor, called via CSSHover.patch
-       function CSSHoverElement(node, type, className) {
-
-               // the CSSHoverElement patches individual nodes by manually applying the events that should 
-               // have fired by the css pseudoclasses, eg mouseenter and mouseleave for :hover. 
-
-               this.node = node;
-               this.type = type;
-               var replacer = new RegExp('(^|\\s)'+className+'(\\s|$)', 'g');
-
-               // store event handlers for removal onunload
-               this.activator =   function(){ node.className += ' ' + className; };
-               this.deactivator = function(){ node.className = node.className.replace(replacer, ' '); };
-               
-               // add the events
-               node.attachEvent(CSSEvents[type].activator, this.activator);
-               node.attachEvent(CSSEvents[type].deactivator, this.deactivator);
-       }
-       
-       CSSHoverElement.prototype = {
-               // onbeforeunload, called via CSSHover.unload
-               unload:function() {
-
-                       // remove events 
-                       this.node.detachEvent(CSSEvents[this.type].activator, this.activator);
-                       this.node.detachEvent(CSSEvents[this.type].deactivator, this.deactivator);
-
-                       // and set properties to null 
-                       this.activator = null;
-                       this.deactivator = null;
-                       this.node = null;
-                       this.type = null;
-               }
-       };
-
-       // add the unload to the onbeforeunload event
-       window.attachEvent('onbeforeunload', function(){
-               CSSHover.unload();
-       });
-
-       /**
-        *      Public hook
-        *      --------------------------
-        */
-       
-       return function(node, type, className, property) {
-               if(node) {
-                       // called via the css expression; patches individual nodes
-                       return CSSHover.patch(node, type, className, property);
-               } else {
-                       // called ondomcontentready via the public:attach node
-                       CSSHover.init();
-               }
-       };
-
-})();
-</script>
\ No newline at end of file
diff --git a/skins/Vector/csshover.min.htc b/skins/Vector/csshover.min.htc
deleted file mode 100644 (file)
index 7e5c57b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<public:attach event="ondocumentready" onevent="CSSHover()" />
-<script>
-/**
- * Whatever:hover - V3.11
- * http://www.xs4all.nl/~peterned/
- *     
- * Copyright (c) 2009 Peter Nederlof
- * Licensed under the LGPL license
- * http://creativecommons.org/licenses/LGPL/2.1
- */
-window.CSSHover=(function(){var m=/(^|\s)((([^a]([^ ]+)?)|(a([^#.][^ ]+)+)):(hover|active|focus))/i;var n=/(.*?)\:(hover|active|focus)/i;var o=/[^:]+:([a-z\-]+).*/i;var p=/(\.([a-z0-9_\-]+):[a-z]+)|(:[a-z]+)/gi;var q=/\.([a-z0-9_\-]*on(hover|active|focus))/i;var s=/msie (5|6|7)/i;var t=/backcompat/i;var u={index:0,list:['text-kashida','text-kashida-space','text-justify'],get:function(){return this.list[(this.index++)%this.list.length]}};var v=function(c){return c.replace(/-(.)/mg,function(a,b){return b.toUpperCase()})};var w={elements:[],callbacks:{},init:function(){if(!s.test(navigator.userAgent)&&!t.test(window.document.compatMode)){return}var a=window.document.styleSheets,l=a.length;for(var i=0;i<l;i++){this.parseStylesheet(a[i])}},parseStylesheet:function(a){if(a.imports){try{var b=a.imports;var l=b.length;for(var i=0;i<l;i++){this.parseStylesheet(a.imports[i])}}catch(securityException){}}try{var c=a.rules;var r=c.length;for(var j=0;j<r;j++){this.parseCSSRule(c[j],a)}}catch(someException){}},parseCSSRule:function(a,b){var c=a.selectorText;if(m.test(c)){var d=a.style.cssText;var e=n.exec(c)[1];var f=c.replace(o,'on$1');var g=c.replace(p,'.$2'+f);var h=q.exec(g)[1];var i=e+h;if(!this.callbacks[i]){var j=u.get();var k=v(j);b.addRule(e,j+':expression(CSSHover(this, "'+f+'", "'+h+'", "'+k+'"))');this.callbacks[i]=true}b.addRule(g,d)}},patch:function(a,b,c,d){try{var f=a.parentNode.currentStyle[d];a.style[d]=f}catch(e){a.runtimeStyle[d]=''}if(!a.csshover){a.csshover=[]}if(!a.csshover[c]){a.csshover[c]=true;var g=new CSSHoverElement(a,b,c);this.elements.push(g)}return b},unload:function(){try{var l=this.elements.length;for(var i=0;i<l;i++){this.elements[i].unload()}this.elements=[];this.callbacks={}}catch(e){}}};var x={onhover:{activator:'onmouseenter',deactivator:'onmouseleave'},onactive:{activator:'onmousedown',deactivator:'onmouseup'},onfocus:{activator:'onfocus',deactivator:'onblur'}};function CSSHoverElement(a,b,c){this.node=a;this.type=b;var d=new RegExp('(^|\\s)'+c+'(\\s|$)','g');this.activator=function(){a.className+=' '+c};this.deactivator=function(){a.className=a.className.replace(d,' ')};a.attachEvent(x[b].activator,this.activator);a.attachEvent(x[b].deactivator,this.deactivator)}CSSHoverElement.prototype={unload:function(){this.node.detachEvent(x[this.type].activator,this.activator);this.node.detachEvent(x[this.type].deactivator,this.deactivator);this.activator=null;this.deactivator=null;this.node=null;this.type=null}};window.attachEvent('onbeforeunload',function(){w.unload()});return function(a,b,c,d){if(a){return w.patch(a,b,c,d)}else{w.init()}}})();
-</script>
diff --git a/skins/Vector/i18n/ab.json b/skins/Vector/i18n/ab.json
deleted file mode 100644 (file)
index d52ed10..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Temuri rajavi"
-               ]
-       },
-       "vector-action-move": "Ахьӡ аҧсахра",
-       "vector-view-create": "Арҿиара",
-       "vector-view-edit": "Ариашамҭа",
-       "vector-view-history": "Аҭоурых",
-       "vector-view-view": "Аҧхьара",
-       "vector-view-viewsource": "Ахәаҧшра"
-}
diff --git a/skins/Vector/i18n/ace.json b/skins/Vector/i18n/ace.json
deleted file mode 100644 (file)
index befc427..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Fadli Idris",
-                       "Si Gam Acèh"
-               ]
-       },
-       "vector-action-addsection": "Tamah bhaih",
-       "vector-action-delete": "Sampôh",
-       "vector-action-move": "Pupinah",
-       "vector-action-protect": "Peulindông",
-       "vector-action-undelete": "Bateuë sampôh",
-       "vector-action-unprotect": "Gantoe neulindông",
-       "vector-view-create": "Peugöt",
-       "vector-view-edit": "Andam",
-       "vector-view-history": "Eu riwayat",
-       "vector-view-view": "Beuët",
-       "vector-view-viewsource": "Eu nè"
-}
diff --git a/skins/Vector/i18n/ady-cyrl.json b/skins/Vector/i18n/ady-cyrl.json
deleted file mode 100644 (file)
index 77ea233..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Adamsa123",
-                       "Amire80",
-                       "Celekan",
-                       "Siklawy"
-               ]
-       },
-       "vector-action-addsection": "1офтхьабз",
-       "vector-action-delete": "ЛъэкӀ",
-       "vector-action-move": "Хьы",
-       "vector-action-protect": "Иухъумэ",
-       "vector-action-undelete": "Умылъэк1",
-       "vector-action-unprotect": "Умыухъумэ",
-       "vector-view-create": "Игъэхъу",
-       "vector-view-edit": "Гъэтэрэзыжь",
-       "vector-view-history": "Тарихъым eплъ",
-       "vector-view-view": "Едж",
-       "vector-view-viewsource": "Еплъ лъапсэм"
-}
diff --git a/skins/Vector/i18n/aeb.json b/skins/Vector/i18n/aeb.json
deleted file mode 100644 (file)
index b3c71f9..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Csisc",
-                       "Malekbr"
-               ]
-       },
-       "vector-action-addsection": "أضف موضوعا",
-       "vector-action-delete": "احذف",
-       "vector-action-move": "انقل",
-       "vector-action-protect": "احم",
-       "vector-action-undelete": "استرجع الحذف",
-       "vector-action-unprotect": "غير الحماية",
-       "vector-view-create": "أنشئ",
-       "vector-view-edit": "Baddel",
-       "vector-view-history": "Warri l'historique",
-       "vector-view-view": "Aqra",
-       "vector-view-viewsource": "اعرض المصدر"
-}
diff --git a/skins/Vector/i18n/af.json b/skins/Vector/i18n/af.json
deleted file mode 100644 (file)
index 8bd949e..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Byeboer",
-                       "Naudefj"
-               ]
-       },
-       "vector-action-addsection": "Nuwe onderwerp",
-       "vector-action-delete": "Skrap",
-       "vector-action-move": "Skuif",
-       "vector-action-protect": "Beskerm",
-       "vector-action-undelete": "Ontskrap",
-       "vector-action-unprotect": "Wysig beskerming",
-       "vector-view-create": "Skep",
-       "vector-view-edit": "Wysig",
-       "vector-view-history": "Wys geskiedenis",
-       "vector-view-view": "Lees",
-       "vector-view-viewsource": "Wys bronteks",
-       "vector-more-actions": "Meer"
-}
diff --git a/skins/Vector/i18n/aln.json b/skins/Vector/i18n/aln.json
deleted file mode 100644 (file)
index a5cc022..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Bresta"
-               ]
-       },
-       "vector.css": "/* CSSi i vednosun këtu ka me i prekë shfrytëzuesit e dukjes Vector */",
-       "vector.js": "/* Çdo JavaScript këtu ka me u ngarkue për shfrytëzuesit që përdorin dukjen Vector */",
-       "vector-action-addsection": "Shto temë",
-       "vector-action-delete": "Fshij",
-       "vector-action-move": "Zhvendos",
-       "vector-action-protect": "Mbroj",
-       "vector-action-undelete": "Kthe fshimjen mbrapsht",
-       "vector-action-unprotect": "Hiq mbrojtjen",
-       "vector-view-create": "Krijo",
-       "vector-view-edit": "Redakto",
-       "vector-view-history": "Shih historinë",
-       "vector-view-view": "Lexo",
-       "vector-view-viewsource": "Shih kodin"
-}
diff --git a/skins/Vector/i18n/am.json b/skins/Vector/i18n/am.json
deleted file mode 100644 (file)
index 55655bb..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Codex Sinaiticus",
-                       "Elfalem",
-                       "Hinstein",
-                       "Teferra"
-               ]
-       },
-       "vector-action-addsection": "ርዕስ ጨምር",
-       "vector-action-delete": "አጥፋ",
-       "vector-action-move": "ለማዛወር",
-       "vector-action-protect": "ለመቆለፍ",
-       "vector-action-undelete": "አታጥፋ",
-       "vector-action-unprotect": "አለመቆለፍ",
-       "vector-view-create": "አዲስ ፍጠር",
-       "vector-view-edit": "አርም",
-       "vector-view-history": "ታሪኩን አሳይ",
-       "vector-view-view": "ለማንበብ",
-       "vector-view-viewsource": "ጥሬ ኮድ ለመመልከት",
-       "vector-more-actions": "ተጨማሪ"
-}
diff --git a/skins/Vector/i18n/an.json b/skins/Vector/i18n/an.json
deleted file mode 100644 (file)
index a4b5f0c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Juanpabl"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector.css": "/* Os estilos CSS colocaus aquí s'aplicarán ta totz os usuarios que faigan servir l'apariencia Vector */",
-       "vector.js": "/* Qualsiquier codigo Javascript escrito aquí se cargará ta totz os usuarios que usen a piel Vector */",
-       "vector-action-addsection": "Adhibir nueva sección",
-       "vector-action-delete": "Borrar",
-       "vector-action-move": "Tresladar",
-       "vector-action-protect": "Protecher",
-       "vector-action-undelete": "Restaurar",
-       "vector-action-unprotect": "Cambiar protección",
-       "vector-view-create": "Creyar",
-       "vector-view-edit": "Editar",
-       "vector-view-history": "Amostrar l'historial",
-       "vector-view-view": "Leyer",
-       "vector-view-viewsource": "Veyer o codigo fuent"
-}
diff --git a/skins/Vector/i18n/ang.json b/skins/Vector/i18n/ang.json
deleted file mode 100644 (file)
index 56321dc..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Gott wisst"
-               ]
-       },
-       "vector-action-addsection": "Besettan mearcunge",
-       "vector-action-delete": "Forlēosan",
-       "vector-action-move": "Wegan",
-       "vector-action-protect": "Beorgan",
-       "vector-action-undelete": "Scieppan tramet eft",
-       "vector-action-unprotect": "Andwendan beorgunge",
-       "vector-view-create": "Scieppan",
-       "vector-view-edit": "Adihtan",
-       "vector-view-history": "Stǣr",
-       "vector-view-view": "Rǣdan",
-       "vector-view-viewsource": "Sēon fruman"
-}
diff --git a/skins/Vector/i18n/ar.json b/skins/Vector/i18n/ar.json
deleted file mode 100644 (file)
index 9c07d9b..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Abanima",
-                       "Calak",
-                       "Meno25",
-                       "Mido",
-                       "OsamaK",
-                       "أحمد",
-                       "زكريا"
-               ]
-       },
-       "skinname-vector": "فكتور",
-       "vector.css": "/* الأنماط المتراصة CSS المعروضة هنا ستؤثر على مستخدمي واجهة فكتور */",
-       "vector.js": "/* أي جافاسكريبت هنا سيتم تحميلها للمستخدمين الذين يستعملون واجهة فكتور */",
-       "vector-action-addsection": "أضف موضوعا",
-       "vector-action-delete": "احذف",
-       "vector-action-move": "انقل",
-       "vector-action-protect": "احم",
-       "vector-action-undelete": "ألغ الحذف",
-       "vector-action-unprotect": "غير الحماية",
-       "vector-view-create": "أنشئ",
-       "vector-view-edit": "عدل",
-       "vector-view-history": "اعرض التاريخ",
-       "vector-view-view": "اقرأ",
-       "vector-view-viewsource": "اعرض المصدر",
-       "vector-more-actions": "مزيد"
-}
diff --git a/skins/Vector/i18n/arc.json b/skins/Vector/i18n/arc.json
deleted file mode 100644 (file)
index 7bb2372..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "334a",
-                       "Basharh",
-                       "Michaelovic"
-               ]
-       },
-       "vector-action-addsection": "ܐܘܣܦ ܡܠܘܐܐ",
-       "vector-action-delete": "ܫܘܦ",
-       "vector-action-move": "ܫܢܝ",
-       "vector-action-protect": "ܛܪ",
-       "vector-action-undelete": "ܠܐ ܫܘܦ",
-       "vector-action-unprotect": "ܫܚܠܦ ܢܛܝܪܘܬܐ",
-       "vector-view-create": "ܒܪܝ",
-       "vector-view-edit": "ܫܚܠܦ",
-       "vector-view-history": "ܚܙܝ ܬܫܥܝܬܐ",
-       "vector-view-view": "ܩܪܝ",
-       "vector-view-viewsource": "ܚܙܝ ܡܒܘܥܐ"
-}
diff --git a/skins/Vector/i18n/arn.json b/skins/Vector/i18n/arn.json
deleted file mode 100644 (file)
index 9ff9636..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Clerc",
-                       "Fiestoforo"
-               ]
-       },
-       "vector-action-addsection": "Püñamtun dungu",
-       "vector-action-delete": "Liftun",
-       "vector-action-move": "Wiñamün",
-       "vector-action-protect": "Nürüfkünun",
-       "vector-action-undelete": "Wüñoñamümün",
-       "vector-action-unprotect": "Kalekünun Nürüfkünun",
-       "vector-view-create": "Dewman",
-       "vector-view-edit": "Kümeelün",
-       "vector-view-history": "Pengelün rupañmael",
-       "vector-view-view": "Chillkatun",
-       "vector-view-viewsource": "Kimam chew küpan chi wirin"
-}
diff --git a/skins/Vector/i18n/aro.json b/skins/Vector/i18n/aro.json
deleted file mode 100644 (file)
index 77dc6c4..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ooswesthoesbes"
-               ]
-       },
-       "vector-view-edit": "Imeakie"
-}
diff --git a/skins/Vector/i18n/arq.json b/skins/Vector/i18n/arq.json
deleted file mode 100644 (file)
index 740ab9b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Bachounda",
-                       "Oldstoneage"
-               ]
-       },
-       "vector-action-addsection": "زيد موضوع",
-       "vector-action-delete": "امحي",
-       "vector-action-move": "حول",
-       "vector-action-protect": "بروجي",
-       "vector-action-undelete": "ردّ كيما كان",
-       "vector-action-unprotect": "بدّل الـحماية",
-       "vector-view-create": "أصنع",
-       "vector-view-edit": "بدل",
-       "vector-view-history": "روح للتاريخي",
-       "vector-view-view": "أقرى",
-       "vector-view-viewsource": "شوف المصدر"
-}
diff --git a/skins/Vector/i18n/ary.json b/skins/Vector/i18n/ary.json
deleted file mode 100644 (file)
index db687ea..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Enzoreg",
-                       "Zanatos"
-               ]
-       },
-       "vector-action-addsection": "Zid topic",
-       "vector-action-delete": "Suprimi",
-       "vector-action-move": "Neqel",
-       "vector-action-protect": "Ḫami",
-       "vector-action-undelete": "rja lhadf",
-       "vector-action-unprotect": "Ḫiyed l-ḫimaya",
-       "vector-view-create": "Ĥṫareĝ",
-       "vector-view-edit": "Ĝedel",
-       "vector-view-history": "Ṫariĥ l-fiċyé",
-       "vector-view-view": "Qra",
-       "vector-view-viewsource": "Ċof l-masdar"
-}
diff --git a/skins/Vector/i18n/arz.json b/skins/Vector/i18n/arz.json
deleted file mode 100644 (file)
index 3541b15..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ghaly",
-                       "Meno25",
-                       "Ramsis II"
-               ]
-       },
-       "vector.css": "/* CSS اللى هنا حتأثر على اليوزرز اللى بيستخدموا واجهة فكتور */",
-       "vector.js": "/* اى جافاسكريبت هنا حتتحمل لكل يوزر بيستخدم واجهة فكتور */",
-       "vector-action-addsection": "ضيف موضوع",
-       "vector-action-delete": "مسح",
-       "vector-action-move": "نقل",
-       "vector-action-protect": "حمايه",
-       "vector-action-undelete": "الغى المسح",
-       "vector-action-unprotect": "غير الحمايه",
-       "vector-view-create": "اعمل",
-       "vector-view-edit": "تعديل",
-       "vector-view-history": "استعراض التاريخ",
-       "vector-view-view": "قرايه",
-       "vector-view-viewsource": "استعراض المصدر"
-}
diff --git a/skins/Vector/i18n/as.json b/skins/Vector/i18n/as.json
deleted file mode 100644 (file)
index 92efe9f..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Bishnu Saikia",
-                       "Chaipau",
-                       "Gitartha.bordoloi"
-               ]
-       },
-       "vector-action-addsection": "বিষয় যোগ",
-       "vector-action-delete": "বিলোপ কৰক",
-       "vector-action-move": "স্থানান্তৰ কৰক",
-       "vector-action-protect": "সুৰক্ষিত কৰক",
-       "vector-action-undelete": "পুনৰুদ্ধাৰ কৰক",
-       "vector-action-unprotect": "সুৰক্ষা সলনি কৰক",
-       "vector-view-create": "সৃষ্টি কৰক",
-       "vector-view-edit": "সম্পাদনা",
-       "vector-view-history": "ইতিহাস চাওক",
-       "vector-view-view": "পঢ়ক",
-       "vector-view-viewsource": "উৎস চাওক",
-       "vector-more-actions": "অধিক"
-}
diff --git a/skins/Vector/i18n/ase.json b/skins/Vector/i18n/ase.json
deleted file mode 100644 (file)
index 97a3500..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Icemandeaf"
-               ]
-       },
-       "skinname-vector": "M509x575S10e20494x425S14a20493x459S16d20492x478S1fb20494x502S17620493x525S11a20493x545",
-       "vector-skin-desc": "M535x520S19a00507x481S19a08465x481S22f14465x506S22f04509x506 M515x598S18d20494x403S17620499x432S11920493x452S17620499x482S14720500x502S17620499x528S17620499x548S14020485x568 M521x508S1f748479x493S1f740501x493 M532x517S15a16505x505S2880f468x484S20e00491x495S1821d503x492 M534x547S2ff00482x483S10001513x517S2e305488x487 S38700463x496 M535x536S20300516x521S20308470x521S26500516x502S26510470x502S14c30511x465S14c38465x465 M526x522S15a56499x510S11520503x479S20e00489x496S26a02474x489 M520x540S37606481x460S15a40508x513S28801499x491S20500488x492",
-       "vector.css": "/* M509x529S16d20492x471S20320493x495S20320493x514 M535x523S14c50508x492S14c58469x492S22520503x477S22520465x477 M525x525S10004510x475S22a04511x510S1000c476x475S22a14477x510 M534x518S2ff00482x483S15a10522x486S2b700514x458 M521x532S10609498x496S10621487x512S21100500x483S2df20479x468 M526x522S15a56499x510S11520503x479S20e00489x496S26a02474x489 M521x508S1f748479x493S1f740501x493 M509x575S10e20494x425S14a20493x459S16d20492x478S1fb20494x502S17620493x525S11a20493x545 M517x524S15a02484x477S15a20489x484S21100504x492S22a04504x509 */",
-       "vector.js": "/* M520x523S1f540480x477S2a204497x495 M519x527S19220498x489S2a20c482x473S20320498x512 M525x525S10004510x475S22a04511x510S1000c476x475S22a14477x510 M534x518S2ff00482x483S15a10522x486S2b700514x458 M524x539S14402493x485S1440a486x461S22b00508x509S22b10476x483 M536x521S2ff00482x483S10011515x491S28108515x461 M526x522S15a56499x510S11520503x479S20e00489x496S26a02474x489 M509x575S10e20494x425S14a20493x459S16d20492x478S1fb20494x502S17620493x525S11a20493x545 M517x524S15a02484x477S15a20489x484S21100504x492S22a04504x509 */",
-       "vector-action-addsection": "M532x517S15a16505x505S2880f468x484S20e00491x495S1821d503x492 M522x522S15a37478x479S10041485x492S20600500x492",
-       "vector-action-delete": "M527x532S1ea40473x511S1f540512x478S22a07497x504S2f700512x468",
-       "vector-action-move": "M552x509S18520488x494S18528449x494S26626522x492",
-       "vector-action-protect": "M512x519S15a19488x482S15a11489x482S20600488x508",
-       "vector-action-undelete": "M515x538S15a0a486x463S10050500x467S2330b485x516S20e00491x501 M527x532S1ea40473x511S1f540512x478S22a07497x504S2f700512x468",
-       "vector-action-unprotect": "M521x532S10609498x496S10621487x512S21100500x483S2df20479x468 M512x519S15a19488x482S15a11489x482S20600488x508",
-       "vector-view-create": "M532x519S20302493x485S2030a489x502S21100509x504S26900516x482S26910468x501",
-       "vector-view-edit": "M521x532S10609498x496S10621487x512S21100500x483S2df20479x468",
-       "vector-view-history": "M525x524S2ff00482x483S10e00507x494S26500511x474 M514x523S11541487x478S22f04489x509",
-       "vector-view-view": "M513x540S15a06486x459S10e50494x474S22b04493x510",
-       "vector-view-viewsource": "M525x524S2ff00482x483S10e00507x494S26500511x474 M509x545S16d20492x456S17620493x480S10120493x497S14a20494x530",
-       "vector-more-actions": "M526x508S18510501x493S18518475x493"
-}
diff --git a/skins/Vector/i18n/ast.json b/skins/Vector/i18n/ast.json
deleted file mode 100644 (file)
index bd3703f..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Esbardu",
-                       "Xuacu"
-               ]
-       },
-       "vector.css": "/* Los CSS allugaos equí afeutarán a los usuarios del aspeutu Vector */",
-       "vector.js": "/* Cualesquier JavaScript que tea equí se cargará pa los usuarios del aspeutu Vector */",
-       "vector-action-addsection": "Amestar seición",
-       "vector-action-delete": "Desaniciar",
-       "vector-action-move": "Treslladar",
-       "vector-action-protect": "Protexer",
-       "vector-action-undelete": "Restaurar",
-       "vector-action-unprotect": "Camudar la proteición",
-       "vector-view-create": "Crear",
-       "vector-view-edit": "Editar",
-       "vector-view-history": "Ver historial",
-       "vector-view-view": "Lleer",
-       "vector-view-viewsource": "Ver fonte"
-}
diff --git a/skins/Vector/i18n/av.json b/skins/Vector/i18n/av.json
deleted file mode 100644 (file)
index e7a6452..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Умар"
-               ]
-       },
-       "vector-view-edit": "Хисизабизе"
-}
diff --git a/skins/Vector/i18n/avk.json b/skins/Vector/i18n/avk.json
deleted file mode 100644 (file)
index a0585bd..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Wikimistusik"
-               ]
-       },
-       "vector-action-addsection": "Loplekura va detce",
-       "vector-action-delete": "Sulara",
-       "vector-action-move": "Arrundara",
-       "vector-action-protect": "Nendara",
-       "vector-view-create": "Redura",
-       "vector-view-edit": "Betara",
-       "vector-view-history": "Wira va izvot",
-       "vector-view-view": "Belira",
-       "vector-view-viewsource": "klitawira"
-}
diff --git a/skins/Vector/i18n/az.json b/skins/Vector/i18n/az.json
deleted file mode 100644 (file)
index 48d42e5..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "AZISS",
-                       "Arystanbek",
-                       "Gulmammad",
-                       "Sortilegus",
-                       "Vago",
-                       "Vugar 1981",
-                       "Wertuose"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector.css": "/* Burada yerləşən CSS Vector istifadəçilərinə tətbiq olunur */",
-       "vector.js": "/* Burada Vector skin istifadəçiləri üçün istənilən JavaScript yüklənəcək */",
-       "vector-action-addsection": "Mövzu əlavə et",
-       "vector-action-delete": "Sil",
-       "vector-action-move": "Adını dəyişdir",
-       "vector-action-protect": "Mühafizə et",
-       "vector-action-undelete": "Bərpa et",
-       "vector-action-unprotect": "Mühafizəni kənarlaşdır",
-       "vector-view-create": "Yarat",
-       "vector-view-edit": "Redaktə",
-       "vector-view-history": "Tarixçəyə bax",
-       "vector-view-view": "Oxu",
-       "vector-view-viewsource": "Mənbəyə bax",
-       "vector-more-actions": "Daha"
-}
diff --git a/skins/Vector/i18n/azb.json b/skins/Vector/i18n/azb.json
deleted file mode 100644 (file)
index ae46e1c..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "E THP",
-                       "Ebrahimi-amir",
-                       "Mousa"
-               ]
-       },
-       "vector-action-addsection": "قوْنو آرتیر",
-       "vector-action-delete": "سیل",
-       "vector-action-move": "داشی",
-       "vector-action-protect": "قوْرو",
-       "vector-action-undelete": "سیلمگی قایتار",
-       "vector-action-unprotect": "قوْروماغی دَییشدیر",
-       "vector-view-create": "یارات",
-       "vector-view-edit": "دَییشدیر",
-       "vector-view-history": "گئچمیشه باخ",
-       "vector-view-view": "اوْخو",
-       "vector-view-viewsource": "قایناغا باخ"
-}
diff --git a/skins/Vector/i18n/ba.json b/skins/Vector/i18n/ba.json
deleted file mode 100644 (file)
index 30969f7..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Assele",
-                       "Haqmar"
-               ]
-       },
-       "skinname-vector": "Векторлы",
-       "vector-action-addsection": "Тема өҫтәргә",
-       "vector-action-delete": "Юйырға",
-       "vector-action-move": "Исемен үҙгәртергә",
-       "vector-action-protect": "Һаҡларға",
-       "vector-action-undelete": "Тергеҙергә",
-       "vector-action-unprotect": "Һаҡлауҙы үҙгәртергә",
-       "vector-view-create": "Яһау",
-       "vector-view-edit": "Үҙгәртергә",
-       "vector-view-history": "Тарихты ҡарау",
-       "vector-view-view": "Уҡыу",
-       "vector-view-viewsource": "Сығанаҡты ҡарарға"
-}
diff --git a/skins/Vector/i18n/ban.json b/skins/Vector/i18n/ban.json
deleted file mode 100644 (file)
index 4641011..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Adi Mayndra",
-                       "BASAbali"
-               ]
-       },
-       "vector-action-addsection": "imbuhin indik wacana",
-       "vector-action-delete": "ngapus",
-       "vector-action-move": "kisidang",
-       "vector-action-protect": "nyaga",
-       "vector-view-create": "ngawe",
-       "vector-view-edit": "mecikang",
-       "vector-view-history": "indik sane lintang",
-       "vector-view-view": "Waca",
-       "vector-view-viewsource": "cingak witnyane"
-}
diff --git a/skins/Vector/i18n/bar.json b/skins/Vector/i18n/bar.json
deleted file mode 100644 (file)
index 0c085b1..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Bua333",
-                       "Mucalexx"
-               ]
-       },
-       "vector-action-addsection": "An Obschnitt dazua doa",
-       "vector-action-delete": "Leschn",
-       "vector-action-move": "Vaschiabm",
-       "vector-action-protect": "Schitzn",
-       "vector-action-undelete": "Wiederherstön",
-       "vector-action-unprotect": "freigeem",
-       "vector-view-create": "Aufbaun",
-       "vector-view-edit": "Werkln",
-       "vector-view-history": "Gschicht oschaugn",
-       "vector-view-view": "Lesn",
-       "vector-view-viewsource": "Quejtext ozoagn"
-}
diff --git a/skins/Vector/i18n/bbc-latn.json b/skins/Vector/i18n/bbc-latn.json
deleted file mode 100644 (file)
index fe9a284..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Daniel Harahap",
-                       "WBT003Bugari",
-                       "WBT006Hendra",
-                       "WBT009Anju"
-               ]
-       },
-       "vector-action-addsection": "Bagian na imbaru",
-       "vector-action-delete": "Sesa",
-       "vector-action-move": "Pahusor",
-       "vector-action-protect": "Ramoti",
-       "vector-action-undelete": "unang sesa",
-       "vector-action-unprotect": "Uba parlindungan",
-       "vector-view-create": "Tompa",
-       "vector-view-edit": "Paubah",
-       "vector-view-history": "Patudu andorang na",
-       "vector-view-view": "Jaha",
-       "vector-view-viewsource": "Ida haroanna"
-}
diff --git a/skins/Vector/i18n/bcc.json b/skins/Vector/i18n/bcc.json
deleted file mode 100644 (file)
index f6c3c4d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mostafadaneshvar",
-                       "RigiMahnoor"
-               ]
-       },
-       "vector-action-addsection": "هور کتن عنوان",
-       "vector-action-delete": "زورگ",
-       "vector-action-move": "جاه په جاه",
-       "vector-action-protect": "حفاظت",
-       "vector-action-undelete": "ترینگ",
-       "vector-action-unprotect": "پروتکشنء ٹگل بدئ",
-       "vector-view-create": "شرکتن",
-       "vector-view-edit": "اصلاح",
-       "vector-view-history": "چارتن تاریح",
-       "vector-view-view": "وانتن",
-       "vector-view-viewsource": "پیشدارگ بن جاه",
-       "vector-more-actions": "گیشتر"
-}
diff --git a/skins/Vector/i18n/bcl.json b/skins/Vector/i18n/bcl.json
deleted file mode 100644 (file)
index 7e2d73a..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Filipinayzd",
-                       "Geopoet"
-               ]
-       },
-       "vector-action-addsection": "Idagdag an topic",
-       "vector-action-delete": "puráon",
-       "vector-action-move": "Ibalyó",
-       "vector-action-protect": "Protektaran",
-       "vector-action-undelete": "Bawion sa pagkapara",
-       "vector-action-unprotect": "Ribayan an proteksyon",
-       "vector-view-create": "Magmukna",
-       "vector-view-edit": "Liwatón",
-       "vector-view-history": "Tanawon sa historiya",
-       "vector-view-view": "Basáha",
-       "vector-view-viewsource": "Hilingón an ginikánan"
-}
diff --git a/skins/Vector/i18n/be-tarask.json b/skins/Vector/i18n/be-tarask.json
deleted file mode 100644 (file)
index 4bbef69..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "EugeneZelenko",
-                       "Red Winged Duck",
-                       "Wizardist"
-               ]
-       },
-       "skinname-vector": "Вэктар",
-       "vector-action-addsection": "Дадаць тэму",
-       "vector-action-delete": "Выдаліць",
-       "vector-action-move": "Перанесьці",
-       "vector-action-protect": "Абараніць",
-       "vector-action-undelete": "Аднавіць",
-       "vector-action-unprotect": "Зьмяніць абарону",
-       "vector-view-create": "Стварыць",
-       "vector-view-edit": "Рэдагаваць",
-       "vector-view-history": "Паказаць гісторыю",
-       "vector-view-view": "Чытаць",
-       "vector-view-viewsource": "Паказаць крыніцу",
-       "vector-more-actions": "Болей"
-}
diff --git a/skins/Vector/i18n/be.json b/skins/Vector/i18n/be.json
deleted file mode 100644 (file)
index b84c18f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mikalai Udodau",
-                       "Yury Tarasievich",
-                       "Дзяніс Тутэйшы",
-                       "Хомелка"
-               ]
-       },
-       "vector-action-addsection": "Дадаць тэму",
-       "vector-action-delete": "Сцерці",
-       "vector-action-move": "Перанесці",
-       "vector-action-protect": "Ахова",
-       "vector-action-undelete": "Аднавіць",
-       "vector-action-unprotect": "Змяніць ахову",
-       "vector-view-create": "Стварыць",
-       "vector-view-edit": "Правіць",
-       "vector-view-history": "Паказаць гісторыю",
-       "vector-view-view": "Чытаць",
-       "vector-view-viewsource": "Паказаць зыходны тэкст",
-       "vector-more-actions": "Яшчэ"
-}
diff --git a/skins/Vector/i18n/bew.json b/skins/Vector/i18n/bew.json
deleted file mode 100644 (file)
index ab009b4..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Naval Scene"
-               ]
-       },
-       "vector-action-delete": "Ngapus",
-       "vector-action-move": "Pindahin",
-       "vector-action-undelete": "Balikin nyang keapus",
-       "vector-view-create": "Bikin"
-}
diff --git a/skins/Vector/i18n/bg.json b/skins/Vector/i18n/bg.json
deleted file mode 100644 (file)
index 9a2858c..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Borislav",
-                       "DCLXVI",
-                       "Spiritia"
-               ]
-       },
-       "vector-action-addsection": "Добавяне на тема",
-       "vector-action-delete": "Изтриване",
-       "vector-action-move": "Преместване",
-       "vector-action-protect": "Защита",
-       "vector-action-undelete": "Възстановяване",
-       "vector-action-unprotect": "Промяна на защитата",
-       "vector-view-create": "Създаване",
-       "vector-view-edit": "Редактиране",
-       "vector-view-history": "История",
-       "vector-view-view": "Преглед",
-       "vector-view-viewsource": "Преглед на кода"
-}
diff --git a/skins/Vector/i18n/bho.json b/skins/Vector/i18n/bho.json
deleted file mode 100644 (file)
index e41f332..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ganesh",
-                       "Nepaboy"
-               ]
-       },
-       "vector-action-addsection": "विषय जोड़ीं",
-       "vector-action-delete": "मिटाईं",
-       "vector-action-move": "स्थांतरण",
-       "vector-action-protect": "संरक्षित करीं",
-       "vector-action-undelete": "मत मिटाईं",
-       "vector-action-unprotect": "सुरक्षा बदलीं",
-       "vector-view-create": "बनाईं",
-       "vector-view-edit": "सम्पादन",
-       "vector-view-history": "इतिहास देखीं",
-       "vector-view-view": "पढ़ीं",
-       "vector-view-viewsource": "स्त्रोत देखीं"
-}
diff --git a/skins/Vector/i18n/bi.json b/skins/Vector/i18n/bi.json
deleted file mode 100644 (file)
index a30c41b..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Sotiale"
-               ]
-       },
-       "vector-action-move": "Muv",
-       "vector-view-history": "Lukluk histri",
-       "vector-view-view": "Rid"
-}
diff --git a/skins/Vector/i18n/bjn.json b/skins/Vector/i18n/bjn.json
deleted file mode 100644 (file)
index 61cb74e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ezagren",
-                       "J Subhi"
-               ]
-       },
-       "vector-action-addsection": "Tambahi tupik",
-       "vector-action-delete": "Hapus",
-       "vector-action-move": "Pindahakan",
-       "vector-action-protect": "Lindungi",
-       "vector-action-undelete": "Pawalangan pahapusan",
-       "vector-action-unprotect": "Palindungan",
-       "vector-view-create": "Ulah",
-       "vector-view-edit": "Babak",
-       "vector-view-history": "Tiringi halam",
-       "vector-view-view": "Baca",
-       "vector-view-viewsource": "Tiringi asal mula"
-}
diff --git a/skins/Vector/i18n/bm.json b/skins/Vector/i18n/bm.json
deleted file mode 100644 (file)
index 9164ec8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Amadouyoro.thiam"
-               ]
-       },
-       "vector-view-view": "Kalan"
-}
diff --git a/skins/Vector/i18n/bn.json b/skins/Vector/i18n/bn.json
deleted file mode 100644 (file)
index a2c37b3..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Aftab1995",
-                       "Bellayet",
-                       "Leemon2010",
-                       "Nasir8891",
-                       "Tauhid16",
-                       "Wikitanvir"
-               ]
-       },
-       "skinname-vector": "ভেক্টর",
-       "vector-action-addsection": "বিষয় যোগ",
-       "vector-action-delete": "অপসারণ",
-       "vector-action-move": "স্থানান্তর",
-       "vector-action-protect": "সুরক্ষা",
-       "vector-action-undelete": "পুনরুদ্ধার",
-       "vector-action-unprotect": "সুরক্ষা পরিবর্তন",
-       "vector-view-create": "তৈরি",
-       "vector-view-edit": "সম্পাদনা",
-       "vector-view-history": "ইতিহাস",
-       "vector-view-view": "পড়ুন",
-       "vector-view-viewsource": "উৎস দেখুন",
-       "vector-more-actions": "আরও"
-}
diff --git a/skins/Vector/i18n/bo.json b/skins/Vector/i18n/bo.json
deleted file mode 100644 (file)
index defe396..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Freeyak",
-                       "Phurbutsering"
-               ]
-       },
-       "vector-action-addsection": "བརྗོད་གཞི་ཁ་སྣོན།",
-       "vector-action-delete": "སུབས།",
-       "vector-action-move": "སྤོར་བ།",
-       "vector-action-protect": "འགོག་སྲུང།",
-       "vector-action-undelete": "མི་བསུབས་",
-       "vector-action-unprotect": "སྲུང་སྐྱོབ་གློད་པ།",
-       "vector-view-create": "གསར་བཟོ།",
-       "vector-view-edit": "རྩོམ་སྒྲིག",
-       "vector-view-history": "ལོ་རྒྱུས་ལ་ལྟ་བ།",
-       "vector-view-view": "ཀློག་པ།",
-       "vector-view-viewsource": "ཁུངས་ལ་ལྟ་བ།"
-}
diff --git a/skins/Vector/i18n/bpy.json b/skins/Vector/i18n/bpy.json
deleted file mode 100644 (file)
index 3124363..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Usingha"
-               ]
-       },
-       "vector-action-addsection": "বিষয় তিলকর",
-       "vector-action-delete": "পুসে বেলা",
-       "vector-action-move": "থেইকর",
-       "vector-action-protect": "লুকর",
-       "vector-action-undelete": "নাপুসি",
-       "vector-action-unprotect": "লুকরানিহান সিলকর",
-       "vector-view-create": "হঙকরিক",
-       "vector-view-edit": "পতানি",
-       "vector-view-history": "ইতিহাস চেইক",
-       "vector-view-view": "পাকরিক",
-       "vector-view-viewsource": "সোর্স চেইক"
-}
diff --git a/skins/Vector/i18n/br.json b/skins/Vector/i18n/br.json
deleted file mode 100644 (file)
index 9cf579b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Fulup",
-                       "Y-M D"
-               ]
-       },
-       "skinname-vector": "Vektor",
-       "vector.css": "/* Talvezout a raio ar CSS lakaet amañ evit implijerien ar gwiskadur Vektor */",
-       "vector.js": "/* Kement JavaScript amañ a vo karget evit an implijerien a ra gant ar gwiskadur Vektor */",
-       "vector-action-addsection": "Rannbennad nevez",
-       "vector-action-delete": "Diverkañ",
-       "vector-action-move": "Adenvel",
-       "vector-action-protect": "Gwareziñ",
-       "vector-action-undelete": "Diziverkañ",
-       "vector-action-unprotect": "Cheñch gwarez",
-       "vector-view-create": "Krouiñ",
-       "vector-view-edit": "Kemmañ",
-       "vector-view-history": "Gwelet an istor",
-       "vector-view-view": "Lenn",
-       "vector-view-viewsource": "Sellet ouzh tarzh an destenn",
-       "vector-more-actions": "Muioc'h"
-}
diff --git a/skins/Vector/i18n/brh.json b/skins/Vector/i18n/brh.json
deleted file mode 100644 (file)
index ee435e6..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Imdadb"
-               ]
-       },
-       "vector-action-addsection": "Púskun sarhál",
-       "vector-action-delete": "Mesa",
-       "vector-action-move": "Surif",
-       "vector-action-protect": "Rakk",
-       "vector-view-create": "Biná",
-       "vector-view-edit": "Radbadal",
-       "vector-view-history": "Lekav e ur",
-       "vector-view-view": "Xuán",
-       "vector-view-viewsource": "Bumpad e ur"
-}
diff --git a/skins/Vector/i18n/bs.json b/skins/Vector/i18n/bs.json
deleted file mode 100644 (file)
index f94be4c..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "CERminator",
-                       "DzWiki",
-                       "KWiki"
-               ]
-       },
-       "vector-action-addsection": "Dodaj temu",
-       "vector-action-delete": "Izbriši",
-       "vector-action-move": "Preusmjeri",
-       "vector-action-protect": "Zaštiti",
-       "vector-action-undelete": "Vrati obrisano",
-       "vector-action-unprotect": "Promijeni zaštitu",
-       "vector-view-create": "Napravi",
-       "vector-view-edit": "Uredi",
-       "vector-view-history": "Pregled historije",
-       "vector-view-view": "Čitanje",
-       "vector-view-viewsource": "Pogledaj izvor"
-}
diff --git a/skins/Vector/i18n/bug.json b/skins/Vector/i18n/bug.json
deleted file mode 100644 (file)
index b1b0f9e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kurniasan"
-               ]
-       },
-       "vector-action-move": "Paléccé'",
-       "vector-view-create": "Ebbu",
-       "vector-view-edit": "Padéccéng",
-       "vector-view-view": "Baca",
-       "vector-view-viewsource": "Ita sumber"
-}
diff --git a/skins/Vector/i18n/bxr.json b/skins/Vector/i18n/bxr.json
deleted file mode 100644 (file)
index 64ff413..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Bjargal",
-                       "Elvonudinium"
-               ]
-       },
-       "vector-action-addsection": "Һэдэб нэмэхэ",
-       "vector-action-delete": "Усадхаха",
-       "vector-action-move": "Зөөхэ",
-       "vector-view-create": "Үүдхэхэ",
-       "vector-view-edit": "Заһабарилха",
-       "vector-view-history": "Түүхые хараха",
-       "vector-view-view": "Уншаха",
-       "vector-view-viewsource": "эшэ үндэһэндэнь хандаха"
-}
diff --git a/skins/Vector/i18n/ca.json b/skins/Vector/i18n/ca.json
deleted file mode 100644 (file)
index a371374..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Aleator",
-                       "Anskar",
-                       "Calak",
-                       "Paucabot",
-                       "Ssola",
-                       "Vriullop"
-               ]
-       },
-       "vector-action-addsection": "Nova secció",
-       "vector-action-delete": "Esborra",
-       "vector-action-move": "Reanomena",
-       "vector-action-protect": "Protegeix",
-       "vector-action-undelete": "Restaura",
-       "vector-action-unprotect": "Desprotegeix",
-       "vector-view-create": "Crea",
-       "vector-view-edit": "Modifica",
-       "vector-view-history": "Mostra l'historial",
-       "vector-view-view": "Mostra",
-       "vector-view-viewsource": "Mostra el codi",
-       "vector-more-actions": "Més"
-}
diff --git a/skins/Vector/i18n/cdo.json b/skins/Vector/i18n/cdo.json
deleted file mode 100644 (file)
index 2bdcb9f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Yejianfei"
-               ]
-       },
-       "vector-action-addsection": "加話題",
-       "vector-action-delete": "刪掉咯",
-       "vector-action-move": "移動",
-       "vector-action-protect": "保護",
-       "vector-action-undelete": "取消刪除",
-       "vector-action-unprotect": "改變保護",
-       "vector-view-create": "創建",
-       "vector-view-edit": "修改",
-       "vector-view-history": "看歷史",
-       "vector-view-view": "讀",
-       "vector-view-viewsource": "看源代碼"
-}
diff --git a/skins/Vector/i18n/ce.json b/skins/Vector/i18n/ce.json
deleted file mode 100644 (file)
index 75053d7..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Sasan700",
-                       "Умар"
-               ]
-       },
-       "skinname-vector": "Векторан",
-       "vector-action-addsection": "ТӀетоха хьедар",
-       "vector-action-delete": "ДӀаяккха",
-       "vector-action-move": "ЦӀе хийца",
-       "vector-action-protect": "Гlаролла дé",
-       "vector-action-undelete": "МеттахӀоттае",
-       "vector-action-unprotect": "ГӀароллех къаста",
-       "vector-view-create": "Кхоллар",
-       "vector-view-edit": "Нисъе",
-       "vector-view-history": "АгӀона хийцамаш",
-       "vector-view-view": "Éшар",
-       "vector-view-viewsource": "Билглонашка хьажа",
-       "vector-more-actions": "Кхин"
-}
diff --git a/skins/Vector/i18n/ceb.json b/skins/Vector/i18n/ceb.json
deleted file mode 100644 (file)
index e2c631f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Jordz"
-               ]
-       },
-       "vector-action-addsection": "Pagdugang og topiko",
-       "vector-action-delete": "Papasa",
-       "vector-action-move": "Ibalhin",
-       "vector-action-protect": "Protektahi",
-       "vector-action-undelete": "Ayaw papasa",
-       "vector-action-unprotect": "Ayaw protektahi",
-       "vector-view-create": "Himoa",
-       "vector-view-edit": "Usba",
-       "vector-view-history": "Tan-awa ang kaagi",
-       "vector-view-view": "Basaha",
-       "vector-view-viewsource": "Tan-awa ang ginikanan"
-}
diff --git a/skins/Vector/i18n/ckb.json b/skins/Vector/i18n/ckb.json
deleted file mode 100644 (file)
index 0db4670..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Asoxor",
-                       "Calak"
-               ]
-       },
-       "skinname-vector": "ڤێکتۆر",
-       "vector-action-addsection": "بابەت دابنێ",
-       "vector-action-delete": "بیسڕەوە",
-       "vector-action-move": "بیگوازەوە",
-       "vector-action-protect": "بیپارێزە",
-       "vector-action-undelete": "سڕینەوە بگەڕێنەوە",
-       "vector-action-unprotect": "پاراستن بگۆڕە",
-       "vector-view-create": "دروستکردن",
-       "vector-view-edit": "دەستکاریی بکە",
-       "vector-view-history": "مێژووەکەی ببینە",
-       "vector-view-view": "بیخوێنەوە",
-       "vector-view-viewsource": "سەرچاوەکەی ببینە",
-       "vector-more-actions": "زیاتر"
-}
diff --git a/skins/Vector/i18n/co.json b/skins/Vector/i18n/co.json
deleted file mode 100644 (file)
index ad84420..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Paulu"
-               ]
-       },
-       "vector-action-addsection": "Aghjunghje discussione",
-       "vector-action-delete": "Supprimà",
-       "vector-action-move": "Cullucà",
-       "vector-action-protect": "Pruteghje",
-       "vector-action-unprotect": "Cambià a prutezzione",
-       "vector-view-create": "Creà",
-       "vector-view-edit": "Mudificà",
-       "vector-view-history": "Vede a cronolugia",
-       "vector-view-view": "Leghje",
-       "vector-view-viewsource": "Vede a surghjente"
-}
diff --git a/skins/Vector/i18n/cps.json b/skins/Vector/i18n/cps.json
deleted file mode 100644 (file)
index 5c40641..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Capisano",
-                       "Oxyzen"
-               ]
-       },
-       "vector-action-addsection": "Magdugang sang topiko",
-       "vector-action-delete": "Panason",
-       "vector-action-move": "Isdogon",
-       "vector-action-protect": "Protektahan",
-       "vector-action-undelete": "Indi pag panason",
-       "vector-action-unprotect": "Islan ang proteksyon",
-       "vector-view-create": "Ubrahon",
-       "vector-view-edit": "Bag-uhon",
-       "vector-view-history": "Ipakita ang kasaysayan",
-       "vector-view-view": "Basahon",
-       "vector-view-viewsource": "Lantawon ang ginhalinan"
-}
diff --git a/skins/Vector/i18n/crh-cyrl.json b/skins/Vector/i18n/crh-cyrl.json
deleted file mode 100644 (file)
index b49a884..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Don Alessandro"
-               ]
-       },
-       "vector-action-addsection": "Мевзу къош",
-       "vector-action-delete": "Ёкъ эт",
-       "vector-action-move": "Адыны денъиштир",
-       "vector-action-protect": "Къорчала",
-       "vector-action-undelete": "Янъыдан ярат",
-       "vector-action-unprotect": "Къорчалавны денъиштир",
-       "vector-view-create": "Ярат",
-       "vector-view-edit": "Денъиштир",
-       "vector-view-history": "Кечмишини косьтер",
-       "vector-view-view": "Окъу",
-       "vector-view-viewsource": "Менба кодуны косьтер"
-}
diff --git a/skins/Vector/i18n/crh-latn.json b/skins/Vector/i18n/crh-latn.json
deleted file mode 100644 (file)
index ad8d58a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Don Alessandro"
-               ]
-       },
-       "vector-action-addsection": "Mevzu qoş",
-       "vector-action-delete": "Yoq et",
-       "vector-action-move": "Adını deñiştir",
-       "vector-action-protect": "Qorçala",
-       "vector-action-undelete": "Yañıdan yarat",
-       "vector-action-unprotect": "Qorçalavnı deñiştir",
-       "vector-view-create": "Yarat",
-       "vector-view-edit": "Deñiştir",
-       "vector-view-history": "Keçmişini köster",
-       "vector-view-view": "Oqu",
-       "vector-view-viewsource": "Menba kodunı köster"
-}
diff --git a/skins/Vector/i18n/cs.json b/skins/Vector/i18n/cs.json
deleted file mode 100644 (file)
index 081783b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mormegil"
-               ]
-       },
-       "skinname-vector": "Vektor",
-       "vector-skin-desc": "Moderní verze MonoBooku s novějším vzhledem a vylepšenou použitelností",
-       "vector.css": "/* Zde uvedené CSS bude ovlivňovat pouze styl „Vektor“ */",
-       "vector.js": "/* JavaScript pro uživatele používající vzhled „Vektor“ */",
-       "vector-action-addsection": "Přidat téma",
-       "vector-action-delete": "Smazat",
-       "vector-action-move": "Přesunout",
-       "vector-action-protect": "Zamknout",
-       "vector-action-undelete": "Obnovit",
-       "vector-action-unprotect": "Změnit zámek",
-       "vector-view-create": "Založit",
-       "vector-view-edit": "Editovat",
-       "vector-view-history": "Zobrazit historii",
-       "vector-view-view": "Číst",
-       "vector-view-viewsource": "Zobrazit zdrojový kód",
-       "vector-more-actions": "Další"
-}
diff --git a/skins/Vector/i18n/csb.json b/skins/Vector/i18n/csb.json
deleted file mode 100644 (file)
index 56d0930..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kaszeba",
-                       "Kuvaly"
-               ]
-       },
-       "vector-action-addsection": "Dodôj témã",
-       "vector-action-delete": "Rëmôj",
-       "vector-action-move": "Przeniesë",
-       "vector-action-protect": "Zazychrëjë",
-       "vector-action-undelete": "Doprowôdzë nazôd",
-       "vector-action-unprotect": "Òdzychrëjë",
-       "vector-view-create": "Ùsôdzë",
-       "vector-view-edit": "Edicëjô",
-       "vector-view-history": "Historëjô lopka",
-       "vector-view-view": "Czëtôj",
-       "vector-view-viewsource": "Zdrojowi tekst"
-}
diff --git a/skins/Vector/i18n/cu.json b/skins/Vector/i18n/cu.json
deleted file mode 100644 (file)
index caad73c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "ОйЛ"
-               ]
-       },
-       "vector-action-addsection": "новꙑ бєсѣдꙑ чѧсти сътворѥниѥ",
-       "vector-action-delete": "поничьжєниѥ",
-       "vector-action-move": "прѣимєнованиѥ",
-       "vector-action-protect": "ꙁабранѥниѥ",
-       "vector-action-unprotect": "иꙁмѣни ꙁабранѥниꙗ обраꙁъ",
-       "vector-view-create": "сътворѥниѥ",
-       "vector-view-edit": "исправи",
-       "vector-view-history": "їсторїꙗ",
-       "vector-view-view": "чьтѥниѥ",
-       "vector-view-viewsource": "страницѧ источьнъ обраꙁъ",
-       "vector-more-actions": "вѧщє"
-}
diff --git a/skins/Vector/i18n/cv.json b/skins/Vector/i18n/cv.json
deleted file mode 100644 (file)
index 6206af8..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Chavash",
-                       "FLAGELLVM DEI"
-               ]
-       },
-       "vector-action-addsection": "Тема хуш",
-       "vector-action-delete": "Кăларса пăрах",
-       "vector-action-move": "Ятне улăштар",
-       "vector-action-protect": "Хӳтĕле",
-       "vector-view-create": "Çĕннине ту",
-       "vector-view-edit": "Тӳрлет",
-       "vector-view-history": "Кун-çул",
-       "vector-view-view": "Вула",
-       "vector-view-viewsource": "пуçламăш текста пăх"
-}
diff --git a/skins/Vector/i18n/cy.json b/skins/Vector/i18n/cy.json
deleted file mode 100644 (file)
index 99d4dc3..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Lloffiwr"
-               ]
-       },
-       "vector-action-addsection": "Ychwanegu adran",
-       "vector-action-delete": "Dileu",
-       "vector-action-move": "Symud",
-       "vector-action-protect": "Diogelu",
-       "vector-action-undelete": "Adfer",
-       "vector-action-unprotect": "Newid y diogelwch",
-       "vector-view-create": "Dechrau",
-       "vector-view-edit": "Golygu",
-       "vector-view-history": "Gweld yr hanes",
-       "vector-view-view": "Darllen",
-       "vector-view-viewsource": "Dangos côd y dudalen",
-       "vector-more-actions": "Rhagor"
-}
diff --git a/skins/Vector/i18n/da.json b/skins/Vector/i18n/da.json
deleted file mode 100644 (file)
index ad56101..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Byrial",
-                       "Christian List",
-                       "Peter Alberti"
-               ]
-       },
-       "vector-action-addsection": "Nyt emne",
-       "vector-action-delete": "Slet",
-       "vector-action-move": "Flyt",
-       "vector-action-protect": "Beskyt",
-       "vector-action-undelete": "Gendan",
-       "vector-action-unprotect": "Ændr beskyttelse",
-       "vector-view-create": "Opret",
-       "vector-view-edit": "Redigér",
-       "vector-view-history": "Se historik",
-       "vector-view-view": "Læs",
-       "vector-view-viewsource": "Se kilden"
-}
diff --git a/skins/Vector/i18n/de.json b/skins/Vector/i18n/de.json
deleted file mode 100644 (file)
index eefc7ab..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kghbln",
-                       "Metalhead64",
-                       "The Evil IP address",
-                       "Umherirrender"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector-skin-desc": "Moderne Version von Monobook mit frischem Aussehen und vielen Verbesserungen an der Benutzerfreundlichkeit",
-       "vector.css": "/* Das folgende CSS wird für Benutzer der Vector-Benutzeroberfläche geladen. Für allgemeingültige Benutzeroberflächen-Anpassungen bitte [[MediaWiki:Common.css]] bearbeiten. */",
-       "vector.js": "/* Das folgende JavaScript wird für Benutzer der Vector-Benutzeroberfläche geladen. Allgemeingültiges JavaScript bitte in [[MediaWiki:Common.js]] eintragen. */",
-       "vector-action-addsection": "Abschnitt hinzufügen",
-       "vector-action-delete": "Löschen",
-       "vector-action-move": "Verschieben",
-       "vector-action-protect": "Schützen",
-       "vector-action-undelete": "Wiederherstellen",
-       "vector-action-unprotect": "Seitenschutz ändern",
-       "vector-view-create": "Erstellen",
-       "vector-view-edit": "Bearbeiten",
-       "vector-view-history": "Versionsgeschichte",
-       "vector-view-view": "Lesen",
-       "vector-view-viewsource": "Quelltext anzeigen",
-       "vector-more-actions": "Mehr"
-}
diff --git a/skins/Vector/i18n/diq.json b/skins/Vector/i18n/diq.json
deleted file mode 100644 (file)
index 5ba4455..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Asmen",
-                       "Calak",
-                       "Erdemaslancan",
-                       "Mirzali"
-               ]
-       },
-       "skinname-vector": "Vektor",
-       "vector-action-addsection": "Mewzu vıraze",
-       "vector-action-delete": "Bestere",
-       "vector-action-move": "Bere",
-       "vector-action-protect": "Bışevekne",
-       "vector-action-undelete": "Esterıtışi peyser bıgê",
-       "vector-action-unprotect": "Starkerdışi bıvurne",
-       "vector-view-create": "Vıraze",
-       "vector-view-edit": "Bıvurne",
-       "vector-view-history": "Tarixê pele bıvêne",
-       "vector-view-view": "Bıwane",
-       "vector-view-viewsource": "Çımey bıvêne",
-       "vector-more-actions": "Zêde"
-}
diff --git a/skins/Vector/i18n/dsb.json b/skins/Vector/i18n/dsb.json
deleted file mode 100644 (file)
index 7220f36..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Michawiki"
-               ]
-       },
-       "vector-action-addsection": "Temu pśidaś",
-       "vector-action-delete": "Wulašowaś",
-       "vector-action-move": "Pśesunuś",
-       "vector-action-protect": "Šćitaś",
-       "vector-action-undelete": "Wótnowiś",
-       "vector-action-unprotect": "Šćit změniś",
-       "vector-view-create": "Napóraś",
-       "vector-view-edit": "Wobźěłaś",
-       "vector-view-history": "Wersije a awtory",
-       "vector-view-view": "Cytaś",
-       "vector-view-viewsource": "Žrědło se woglědaś"
-}
diff --git a/skins/Vector/i18n/dtp.json b/skins/Vector/i18n/dtp.json
deleted file mode 100644 (file)
index a337040..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "FRANCIS5091",
-                       "FRANELYA"
-               ]
-       },
-       "vector-action-addsection": "Ruhangai piboboroson",
-       "vector-action-delete": "Pugaso",
-       "vector-action-move": "Poundoliho",
-       "vector-action-protect": "Tingoligai",
-       "vector-action-undelete": "Kada pugaso",
-       "vector-action-unprotect": "Alanai tingolig",
-       "vector-view-create": "Pomonsoi",
-       "vector-view-edit": "Idito",
-       "vector-view-history": "Intaai susuyan",
-       "vector-view-view": "Basao",
-       "vector-view-viewsource": "Intaai wowonod"
-}
diff --git a/skins/Vector/i18n/dv.json b/skins/Vector/i18n/dv.json
deleted file mode 100644 (file)
index 9e53056..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ushau97"
-               ]
-       },
-       "vector-action-addsection": "ޚިޔާލެއް އިތުރުކުރައްވާ",
-       "vector-action-delete": "ފޮހެލައްވާ",
-       "vector-action-move": "ތަން ބަދަލުކުރައްވާ",
-       "vector-action-protect": "ދިފާޢުކުރައްވާ",
-       "vector-action-unprotect": "ދިފާޢުކުރުން ބަދަލުކުރައްވާ",
-       "vector-view-create": "ފަށްޓަވާ",
-       "vector-view-edit": "އުނިއިތުރު ގެންނަވާ",
-       "vector-view-history": "ޞަފްޙާގެ ތާރީޚް",
-       "vector-view-view": "ކިޔުއްވާ",
-       "vector-view-viewsource": "މަސްދަރު ބައްލަވާ"
-}
diff --git a/skins/Vector/i18n/ee.json b/skins/Vector/i18n/ee.json
deleted file mode 100644 (file)
index 2214755..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Natsubee"
-               ]
-       },
-       "vector-action-delete": "Tutui",
-       "vector-action-move": "Ɖɔli eƒe nɔƒe",
-       "vector-view-create": "Dze egɔme",
-       "vector-view-edit": "Trɔ asi le eŋu",
-       "vector-view-history": "Kpɔ xoxoawo",
-       "vector-view-view": "Xlẽ",
-       "vector-view-viewsource": "Kpɔ alesi woŋlɔe"
-}
diff --git a/skins/Vector/i18n/egl.json b/skins/Vector/i18n/egl.json
deleted file mode 100644 (file)
index a819ab0..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Lévi"
-               ]
-       },
-       "vector-action-addsection": "Zûnta discusiòun",
-       "vector-action-delete": "Scanşèla",
-       "vector-action-move": "Spôsta",
-       "vector-action-protect": "Prutēz",
-       "vector-action-undelete": "Fà al recóper",
-       "vector-action-unprotect": "Câmbia la prutesiòun",
-       "vector-view-create": "Invèinta",
-       "vector-view-edit": "Mudéfica",
-       "vector-view-history": "Guêrda la stôria",
-       "vector-view-view": "Lēş",
-       "vector-view-viewsource": "Guêrda la surzéia",
-       "vector-more-actions": "Êter"
-}
diff --git a/skins/Vector/i18n/el.json b/skins/Vector/i18n/el.json
deleted file mode 100644 (file)
index 06fa36b..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Calak",
-                       "Crazymadlover",
-                       "Evropi",
-                       "Omnipaedista",
-                       "Protnet",
-                       "ZaDiak"
-               ]
-       },
-       "vector.css": "/* Το τοποθετημένο εδώ CSS θα επηρεάσει χρήστες του Vector skin */",
-       "vector.js": "/* Οποιοσδήποτε κώδικας JavaScript εδώ θα φορτωθεί για χρήστες που χρησιμοποιούν το Vector skin */",
-       "vector-action-addsection": "Προσθήκη θέματος",
-       "vector-action-delete": "Διαγραφή",
-       "vector-action-move": "Μετακίνηση",
-       "vector-action-protect": "Προστασία",
-       "vector-action-undelete": "Επαναφορά",
-       "vector-action-unprotect": "Αλλαγή προστασίας",
-       "vector-view-create": "Δημιουργία",
-       "vector-view-edit": "Επεξεργασία",
-       "vector-view-history": "Προβολή ιστορικού",
-       "vector-view-view": "Ανάγνωση",
-       "vector-view-viewsource": "Προβολή κώδικα",
-       "vector-more-actions": "Περισσότερα"
-}
diff --git a/skins/Vector/i18n/en.json b/skins/Vector/i18n/en.json
deleted file mode 100644 (file)
index 949218e..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": []
-       },
-       "skinname-vector": "Vector",
-       "vector-skin-desc": "Modern version of MonoBook with fresh look and many usability improvements",
-       "vector.css": "/* CSS placed here will affect users of the Vector skin */",
-       "vector.js": "/* Any JavaScript here will be loaded for users using the Vector skin */",
-       "vector-action-addsection": "Add topic",
-       "vector-action-delete": "Delete",
-       "vector-action-move": "Move",
-       "vector-action-protect": "Protect",
-       "vector-action-undelete": "Undelete",
-       "vector-action-unprotect": "Change protection",
-       "vector-view-create": "Create",
-       "vector-view-edit": "Edit",
-       "vector-view-history": "View history",
-       "vector-view-view": "Read",
-       "vector-view-viewsource": "View source",
-       "vector-more-actions": "More"
-}
diff --git a/skins/Vector/i18n/eo.json b/skins/Vector/i18n/eo.json
deleted file mode 100644 (file)
index 5f92fe8..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "KuboF",
-                       "Objectivesea",
-                       "Yekrats"
-               ]
-       },
-       "skinname-vector": "Vektoro",
-       "vector.css": "/* La jena CSS influos la paĝaspekton por uzantoj de la Vektora temo. */",
-       "vector.js": "/* La jena Ĝavaskripto ŝargiĝos por uzantoj de la Vektora temo. */",
-       "vector-action-addsection": "Aldoni temon",
-       "vector-action-delete": "Forigi",
-       "vector-action-move": "Alinomigi",
-       "vector-action-protect": "Protekti",
-       "vector-action-undelete": "Malforigi",
-       "vector-action-unprotect": "Ŝanĝi protektadon",
-       "vector-view-create": "Krei",
-       "vector-view-edit": "Redakti",
-       "vector-view-history": "Vidi historion",
-       "vector-view-view": "Legi",
-       "vector-view-viewsource": "Vidi fonton",
-       "vector-more-actions": "Pli"
-}
diff --git a/skins/Vector/i18n/es-formal.json b/skins/Vector/i18n/es-formal.json
deleted file mode 100644 (file)
index a666c05..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "XanaG"
-               ]
-       },
-       "vector-view-edit": "Editar",
-       "vector-view-history": "Ver historial",
-       "vector-view-view": "Leer"
-}
diff --git a/skins/Vector/i18n/es.json b/skins/Vector/i18n/es.json
deleted file mode 100644 (file)
index 75352a5..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Armando-Martin",
-                       "Crazymadlover",
-                       "Dalton2",
-                       "Fitoschido",
-                       "Locos epraix",
-                       "Manuelt15",
-                       "MarcoAurelio",
-                       "Miguel2706",
-                       "Platonides",
-                       "Vivaelcelta"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector-skin-desc": "Versión moderna de MonoBook, con un aspecto actualizado y muchas mejoras de usabilidad",
-       "vector.css": "/* El CSS colocado en esta página afectará a los usuarios que usen la apariencia \"Vector\" */",
-       "vector.js": "/* Cualquier código JavaScript escrito aquí se cargará para todos los usuarios que usen la apariencia Vector */",
-       "vector-action-addsection": "Sección nueva",
-       "vector-action-delete": "Borrar",
-       "vector-action-move": "Trasladar",
-       "vector-action-protect": "Proteger",
-       "vector-action-undelete": "Restaurar",
-       "vector-action-unprotect": "Cambiar protección",
-       "vector-view-create": "Crear",
-       "vector-view-edit": "Editar",
-       "vector-view-history": "Ver historial",
-       "vector-view-view": "Leer",
-       "vector-view-viewsource": "Ver código",
-       "vector-more-actions": "Más"
-}
diff --git a/skins/Vector/i18n/esu.json b/skins/Vector/i18n/esu.json
deleted file mode 100644 (file)
index b32ac1d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "82-145"
-               ]
-       },
-       "vector-action-move": "Atra cimirtuq",
-       "vector-view-view": "Naaqe"
-}
diff --git a/skins/Vector/i18n/et.json b/skins/Vector/i18n/et.json
deleted file mode 100644 (file)
index 718b93c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ker",
-                       "Pikne",
-                       "WikedKentaur"
-               ]
-       },
-       "skinname-vector": "Vektor",
-       "vector-action-addsection": "Lisa teema",
-       "vector-action-delete": "Kustuta",
-       "vector-action-move": "Teisalda",
-       "vector-action-protect": "Kaitse",
-       "vector-action-undelete": "Taasta",
-       "vector-action-unprotect": "Muuda kaitset",
-       "vector-view-create": "Loo",
-       "vector-view-edit": "Muuda",
-       "vector-view-history": "Näita ajalugu",
-       "vector-view-view": "Vaata",
-       "vector-view-viewsource": "Vaata lähteteksti",
-       "vector-more-actions": "Veel"
-}
diff --git a/skins/Vector/i18n/eu.json b/skins/Vector/i18n/eu.json
deleted file mode 100644 (file)
index 856742c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Unai Fdz. de Betoño",
-                       "Xabier Armendaritz",
-                       "Fitoschido"
-               ]
-       },
-       "vector-action-addsection": "Gehitu atala",
-       "vector-action-delete": "Ezabatu",
-       "vector-action-move": "Mugitu",
-       "vector-action-protect": "Babestu",
-       "vector-action-undelete": "Berreskuratu",
-       "vector-action-unprotect": "Babesa aldatu",
-       "vector-view-create": "Sortu",
-       "vector-view-edit": "Aldatu",
-       "vector-view-history": "Ikusi historia",
-       "vector-view-view": "Irakurri",
-       "vector-view-viewsource": "Kodea ikusia",
-       "vector-more-actions": "Gehiago"
-}
diff --git a/skins/Vector/i18n/ext.json b/skins/Vector/i18n/ext.json
deleted file mode 100644 (file)
index 1cf9a4f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Better"
-               ]
-       },
-       "vector-action-addsection": "Añiil tema",
-       "vector-action-delete": "Esborral",
-       "vector-action-move": "Mual",
-       "vector-action-protect": "Protegel",
-       "vector-action-undelete": "Esborral",
-       "vector-action-unprotect": "Esprotegel",
-       "vector-view-create": "Crial",
-       "vector-view-edit": "Eital",
-       "vector-view-history": "Guipal estorial",
-       "vector-view-view": "Leyel",
-       "vector-view-viewsource": "Guipal cóigu"
-}
diff --git a/skins/Vector/i18n/fa.json b/skins/Vector/i18n/fa.json
deleted file mode 100644 (file)
index 1d329ff..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Calak",
-                       "Ebraminio",
-                       "Huji",
-                       "Reza1615",
-                       "Zack90"
-               ]
-       },
-       "skinname-vector": "برداری",
-       "vector-skin-desc": "نسخه مدرن منوبوک با نگاه تازه و بهبود قابلیت استفاده",
-       "vector-action-addsection": "افزودن بخش",
-       "vector-action-delete": "حذف",
-       "vector-action-move": "انتقال",
-       "vector-action-protect": "محافظت",
-       "vector-action-undelete": "احیا",
-       "vector-action-unprotect": "تغییر سطح حفاظت",
-       "vector-view-create": "ایجاد",
-       "vector-view-edit": "ویرایش",
-       "vector-view-history": "نمایش تاریخچه",
-       "vector-view-view": "خواندن",
-       "vector-view-viewsource": "نمایش مبدأ",
-       "vector-more-actions": "بیشتر"
-}
diff --git a/skins/Vector/i18n/ff.json b/skins/Vector/i18n/ff.json
deleted file mode 100644 (file)
index ac3ee5b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ibrahima"
-               ]
-       },
-       "vector-action-addsection": "Ɓeydi toɓɓere",
-       "vector-action-move": "Dirtin",
-       "vector-view-create": "Sos",
-       "vector-view-edit": "Taƴto",
-       "vector-view-history": "Yiyto aslol",
-       "vector-view-view": "Tar",
-       "vector-view-viewsource": "Yiyto ɗaɗol"
-}
diff --git a/skins/Vector/i18n/fi.json b/skins/Vector/i18n/fi.json
deleted file mode 100644 (file)
index 7533689..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Crt",
-                       "Nedergard",
-                       "Nike",
-                       "Pxos"
-               ]
-       },
-       "vector.css": "/* Tämä sivu sisältää Vector-ulkoasua muuttavia tyylejä. */",
-       "vector.js": "/* Tämän sivun JavaScript-koodi liitetään Vector-tyyliin */",
-       "vector-action-addsection": "Lisää aihe",
-       "vector-action-delete": "Poista",
-       "vector-action-move": "Siirrä",
-       "vector-action-protect": "Suojaa",
-       "vector-action-undelete": "Palauta",
-       "vector-action-unprotect": "Muuta suojausta",
-       "vector-view-create": "Luo",
-       "vector-view-edit": "Muokkaa",
-       "vector-view-history": "Näytä historia",
-       "vector-view-view": "Lue",
-       "vector-view-viewsource": "Näytä lähdekoodi",
-       "vector-more-actions": "Muut"
-}
diff --git a/skins/Vector/i18n/fit.json b/skins/Vector/i18n/fit.json
deleted file mode 100644 (file)
index 46089ae..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mestos"
-               ]
-       },
-       "vector-action-addsection": "Lissää aine",
-       "vector-action-delete": "Ota poies",
-       "vector-action-move": "Siirä",
-       "vector-action-protect": "Suojaa",
-       "vector-action-undelete": "Pane takashiin",
-       "vector-action-unprotect": "Muuta suojaa",
-       "vector-view-create": "Luo",
-       "vector-view-edit": "Mookkaa",
-       "vector-view-history": "Näytä histuuria",
-       "vector-view-view": "Lue",
-       "vector-view-viewsource": "Näytä lähekooti"
-}
diff --git a/skins/Vector/i18n/fo.json b/skins/Vector/i18n/fo.json
deleted file mode 100644 (file)
index 46f272c..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Diupwijk",
-                       "EileenSanda"
-               ]
-       },
-       "vector-action-addsection": "Nýtt evni",
-       "vector-action-delete": "Strika",
-       "vector-action-move": "Flyt",
-       "vector-action-protect": "Friða",
-       "vector-action-undelete": "Endurstovna",
-       "vector-action-unprotect": "Broyt verju",
-       "vector-view-create": "Stovna",
-       "vector-view-edit": "Rætta",
-       "vector-view-history": "Vís søgu",
-       "vector-view-view": "Les",
-       "vector-view-viewsource": "Vís keldu",
-       "vector-more-actions": "Meira"
-}
diff --git a/skins/Vector/i18n/fr.json b/skins/Vector/i18n/fr.json
deleted file mode 100644 (file)
index 623fda8..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Akeron",
-                       "Crochet.david",
-                       "DavidL",
-                       "Gomoko",
-                       "Jean-Frédéric",
-                       "Od1n"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector-skin-desc": "Version moderne de MonoBook avec un aspect rajeuni et beaucoup d’améliorations ergonomiques",
-       "vector.css": "/* Le CSS placé ici affectera les utilisateurs de l’habillage Vector. */",
-       "vector.js": "/* Tout code JavaScript placé ici sera chargé pour les utilisateurs de l’habillage Vector */",
-       "vector-action-addsection": "Ajouter un sujet",
-       "vector-action-delete": "Supprimer",
-       "vector-action-move": "Renommer",
-       "vector-action-protect": "Protéger",
-       "vector-action-undelete": "Rétablir",
-       "vector-action-unprotect": "Changer la protection",
-       "vector-view-create": "Créer",
-       "vector-view-edit": "Modifier",
-       "vector-view-history": "Historique",
-       "vector-view-view": "Lire",
-       "vector-view-viewsource": "Voir la source",
-       "vector-more-actions": "Plus"
-}
diff --git a/skins/Vector/i18n/frc.json b/skins/Vector/i18n/frc.json
deleted file mode 100644 (file)
index f13d8ce..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ebe123"
-               ]
-       },
-       "vector-action-delete": "Supprimer",
-       "vector-action-protect": "Protéger"
-}
diff --git a/skins/Vector/i18n/frp.json b/skins/Vector/i18n/frp.json
deleted file mode 100644 (file)
index 4f0c3bc..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "ChrisPtDe"
-               ]
-       },
-       "skinname-vector": "Vèctor",
-       "vector.css": "/* Lo code CSS betâ ique afècterat los usanciérs de l’habelyâjo « Vèctor ». */",
-       "vector.js": "/* Tot code JavaScript betâ ique serat chargiê per los usanciérs de l’habelyâjo « Vèctor ». */",
-       "vector-action-addsection": "Apondre na chousa",
-       "vector-action-delete": "Suprimar",
-       "vector-action-move": "Dèplaciér",
-       "vector-action-protect": "Protègiér",
-       "vector-action-undelete": "Refâre",
-       "vector-action-unprotect": "Changiér la protèccion",
-       "vector-view-create": "Fâre",
-       "vector-view-edit": "Changiér",
-       "vector-view-history": "Vêre l’historico",
-       "vector-view-view": "Liére",
-       "vector-view-viewsource": "Vêre lo tèxto sôrsa"
-}
diff --git a/skins/Vector/i18n/frr.json b/skins/Vector/i18n/frr.json
deleted file mode 100644 (file)
index f9ff0a3..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Murma174",
-                       "Pyt"
-               ]
-       },
-       "vector-skin-desc": "Modern werjuun faan Monobook mä frisk skak an föl muar mögelkhaiden",
-       "vector-action-addsection": "Nei kirew began",
-       "vector-action-delete": "Strik",
-       "vector-action-move": "Fersküüw",
-       "vector-action-protect": "Seekre",
-       "vector-action-undelete": "Weder iinstel",
-       "vector-action-unprotect": "Sidjenseekerhaid",
-       "vector-view-create": "Maage",
-       "vector-view-edit": "Bewerke",
-       "vector-view-history": "Ferluup uunluke",
-       "vector-view-view": "Lees",
-       "vector-view-viewsource": "Kweltekst uunluke",
-       "vector-more-actions": "Muar"
-}
diff --git a/skins/Vector/i18n/fur.json b/skins/Vector/i18n/fur.json
deleted file mode 100644 (file)
index 9df1846..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Klenje",
-                       "Tocaibon"
-               ]
-       },
-       "vector-action-addsection": "Gnove sezion",
-       "vector-action-delete": "Elimine",
-       "vector-action-move": "Môf",
-       "vector-action-protect": "Protêç",
-       "vector-action-undelete": "Recupere",
-       "vector-action-unprotect": "Gambie la protezion",
-       "vector-view-create": "Cree",
-       "vector-view-edit": "Cambie",
-       "vector-view-history": "Cjale il storic",
-       "vector-view-view": "Lei",
-       "vector-view-viewsource": "Cjale risultive"
-}
diff --git a/skins/Vector/i18n/fy.json b/skins/Vector/i18n/fy.json
deleted file mode 100644 (file)
index 328193d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kening Aldgilles",
-                       "SK-luuut"
-               ]
-       },
-       "vector-action-delete": "Fuortsmite",
-       "vector-action-move": "Werneam",
-       "vector-action-protect": "Beskermje",
-       "vector-action-undelete": "Tebeksette",
-       "vector-action-unprotect": "Beskerming fuorthelje",
-       "vector-view-create": "Oanmeitsje",
-       "vector-view-edit": "Wizigje",
-       "vector-view-history": "Skiednis sjen litte",
-       "vector-view-view": "Lês",
-       "vector-view-viewsource": "Besjoch de boarne"
-}
diff --git a/skins/Vector/i18n/ga.json b/skins/Vector/i18n/ga.json
deleted file mode 100644 (file)
index 81f4caa..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kscanne",
-                       "Kwekubo",
-                       "Moydow"
-               ]
-       },
-       "skinname-vector": "Veicteoir",
-       "vector-action-addsection": "Cuir topaic leis",
-       "vector-action-delete": "Scrios",
-       "vector-action-move": "Athainmnigh",
-       "vector-action-protect": "Glasáil",
-       "vector-action-undelete": "Díscrios",
-       "vector-action-unprotect": "Díghlasáil",
-       "vector-view-create": "Cruthaigh",
-       "vector-view-edit": "Athraigh an lch seo",
-       "vector-view-history": "Féach ar stair",
-       "vector-view-view": "Léigh",
-       "vector-view-viewsource": "Féach ar fhoinse"
-}
diff --git a/skins/Vector/i18n/gag.json b/skins/Vector/i18n/gag.json
deleted file mode 100644 (file)
index 4f45473..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Cuman",
-                       "Emperyan"
-               ]
-       },
-       "vector-view-edit": "Diiştir",
-       "vector-view-view": "Oku"
-}
diff --git a/skins/Vector/i18n/gan-hans.json b/skins/Vector/i18n/gan-hans.json
deleted file mode 100644 (file)
index 5c0db67..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Liangent",
-                       "Xiaomingyan"
-               ]
-       },
-       "vector-action-addsection": "添主题",
-       "vector-action-delete": "删吥",
-       "vector-action-move": "移吥",
-       "vector-action-protect": "护到",
-       "vector-action-undelete": "望下删吥𠮶页面",
-       "vector-action-unprotect": "更改保护",
-       "vector-view-create": "创建",
-       "vector-view-edit": "编辑",
-       "vector-view-history": "望下历史",
-       "vector-view-view": "读",
-       "vector-view-viewsource": "望下原始码"
-}
diff --git a/skins/Vector/i18n/gan-hant.json b/skins/Vector/i18n/gan-hant.json
deleted file mode 100644 (file)
index ceb23b5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Symane"
-               ]
-       },
-       "vector-action-addsection": "添主題",
-       "vector-action-delete": "刪吥",
-       "vector-action-move": "移吥",
-       "vector-action-protect": "護到",
-       "vector-action-undelete": "望下刪吥嗰頁面",
-       "vector-action-unprotect": "解除保護",
-       "vector-view-create": "創建",
-       "vector-view-edit": "編輯",
-       "vector-view-history": "望下歷史",
-       "vector-view-view": "讀",
-       "vector-view-viewsource": "望下原始碼"
-}
diff --git a/skins/Vector/i18n/gd.json b/skins/Vector/i18n/gd.json
deleted file mode 100644 (file)
index 04fa42b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Akerbeltz",
-                       "GunChleoc"
-               ]
-       },
-       "vector-skin-desc": "Tionndadh ùr-nodha de MonoBook le dreach ùr air 's iomadh leasachadh air a sho-chleachdachd",
-       "vector-action-addsection": "Cuir ris cuspair",
-       "vector-action-delete": "Sguab às",
-       "vector-action-move": "Gluais",
-       "vector-action-protect": "Dìon",
-       "vector-action-undelete": "Neo-dhèan an sguabadh às",
-       "vector-action-unprotect": "Atharraich an dìon",
-       "vector-view-create": "Cruthaich",
-       "vector-view-edit": "Deasaich",
-       "vector-view-history": "Seall an eachdraidh",
-       "vector-view-view": "Leugh",
-       "vector-view-viewsource": "Seall an tùs",
-       "vector-more-actions": "Barrachd"
-}
diff --git a/skins/Vector/i18n/gl.json b/skins/Vector/i18n/gl.json
deleted file mode 100644 (file)
index de19c39..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Elisardojm",
-                       "Toliño",
-                       "Vivaelcelta"
-               ]
-       },
-       "vector.css": "/* O CSS que se coloque aquí afectará a quen use a aparencia Vector */",
-       "vector.js": "/* Calquera JavaScript que haxa aquí será cargado para os usuarios que usen a aparencia Vector */",
-       "vector-action-addsection": "Nova sección",
-       "vector-action-delete": "Borrar",
-       "vector-action-move": "Mover",
-       "vector-action-protect": "Protexer",
-       "vector-action-undelete": "Restaurar",
-       "vector-action-unprotect": "Cambiar a protección",
-       "vector-view-create": "Crear",
-       "vector-view-edit": "Editar",
-       "vector-view-history": "Ver o historial",
-       "vector-view-view": "Ler",
-       "vector-view-viewsource": "Ver o código fonte",
-       "vector-more-actions": "Máis"
-}
diff --git a/skins/Vector/i18n/gom-deva.json b/skins/Vector/i18n/gom-deva.json
deleted file mode 100644 (file)
index 044d43c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Darshan kandolkar",
-                       "Pooja tople",
-                       "Sanket.prabhu26",
-                       "Supriya kankumbikar"
-               ]
-       },
-       "vector-action-addsection": "माथाळो दियात",
-       "vector-action-delete": "काडून उडयात",
-       "vector-action-move": "दुसरेकडे व्हरात",
-       "vector-action-protect": "राख",
-       "vector-view-create": "निर्माण कर",
-       "vector-view-edit": "बदल",
-       "vector-view-history": "इतिहास पळेयात",
-       "vector-view-view": "वाचचें",
-       "vector-view-viewsource": "उगम पळेयात"
-}
diff --git a/skins/Vector/i18n/gom-latn.json b/skins/Vector/i18n/gom-latn.json
deleted file mode 100644 (file)
index 37a3117..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Isidore Dantas",
-                       "The Discoverer"
-               ]
-       },
-       "vector-action-addsection": "Vixoi zodd",
-       "vector-action-delete": "Kadd",
-       "vector-action-move": "Zago bodol",
-       "vector-action-protect": "Rakh",
-       "vector-view-create": "Roch",
-       "vector-view-edit": "Sudar",
-       "vector-view-history": "Itihas polloi",
-       "vector-view-view": "Vach",
-       "vector-view-viewsource": "Mull polloi",
-       "vector-more-actions": "Anik"
-}
diff --git a/skins/Vector/i18n/grc.json b/skins/Vector/i18n/grc.json
deleted file mode 100644 (file)
index c22ebf1..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Crazymadlover",
-                       "Omnipaedista"
-               ]
-       },
-       "vector-action-addsection": "Θέμα προστιθέναι",
-       "vector-action-delete": "Σβεννύναι",
-       "vector-action-move": "Κινεῖν",
-       "vector-action-protect": "Φυλάττειν",
-       "vector-action-undelete": "Ἀποκαθιστάναι",
-       "vector-action-unprotect": "Ἄλλαξον τὴν φύλαξιν",
-       "vector-view-create": "Ποιεῖν",
-       "vector-view-edit": "Μεταγράφειν",
-       "vector-view-history": "Ἱστορίαν ὁρᾶν",
-       "vector-view-view": "Ἀναγνῶναι",
-       "vector-view-viewsource": "Ὁρᾶν τὴν πηγήν"
-}
diff --git a/skins/Vector/i18n/gsw.json b/skins/Vector/i18n/gsw.json
deleted file mode 100644 (file)
index 90b3e73..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Als-Holder"
-               ]
-       },
-       "vector-action-addsection": "Abschnitt zuefiege",
-       "vector-action-delete": "Lesche",
-       "vector-action-move": "Verschiebe",
-       "vector-action-protect": "Schitze",
-       "vector-action-undelete": "Widerhärstelle",
-       "vector-action-unprotect": "Syteschutz ändere",
-       "vector-view-create": "Aalege",
-       "vector-view-edit": "Bearbeite",
-       "vector-view-history": "Versionsgschicht",
-       "vector-view-view": "Läse",
-       "vector-view-viewsource": "Quälltext aaluege"
-}
diff --git a/skins/Vector/i18n/gu.json b/skins/Vector/i18n/gu.json
deleted file mode 100644 (file)
index 6d7dc1d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Aritra",
-                       "Ashok modhvadia",
-                       "Dsvyas"
-               ]
-       },
-       "vector-action-addsection": "નવી ચર્ચા",
-       "vector-action-delete": "રદ કરો",
-       "vector-action-move": "ખસેડો",
-       "vector-action-protect": "સુરક્ષિત કરો",
-       "vector-action-undelete": "રદ કરેલું પાછું વાળો",
-       "vector-action-unprotect": "સુરક્ષા બદલો",
-       "vector-view-create": "બનાવો",
-       "vector-view-edit": "ફેરફાર કરો",
-       "vector-view-history": "ઇતિહાસ જુઓ",
-       "vector-view-view": "વાંચો",
-       "vector-view-viewsource": "સ્રોત જુઓ"
-}
diff --git a/skins/Vector/i18n/guc.json b/skins/Vector/i18n/guc.json
deleted file mode 100644 (file)
index e69fac5..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Maor X"
-               ]
-       },
-       "vector-action-delete": "Ojuichajaa",
-       "vector-action-move": "Ansülaa",
-       "vector-action-protect": "Eisalajaa",
-       "vector-view-create": "Akumajaa",
-       "vector-view-edit": "Anaataa",
-       "vector-view-history": "Achikii a'wanajaayamaajatü",
-       "vector-view-view": "Aashaje'eraa",
-       "vector-view-viewsource": "Anüliaa eejeetülee"
-}
diff --git a/skins/Vector/i18n/gv.json b/skins/Vector/i18n/gv.json
deleted file mode 100644 (file)
index 9be429f..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "MacTire02",
-                       "Shimmin Beg"
-               ]
-       },
-       "vector-action-addsection": "Cur cooish noa rish",
-       "vector-action-delete": "Scryss",
-       "vector-action-move": "Scugh",
-       "vector-action-protect": "Coadee",
-       "vector-action-undelete": "Jee-scryss",
-       "vector-action-unprotect": "Caghlaa coadey",
-       "vector-view-create": "Croo",
-       "vector-view-edit": "Reagh",
-       "vector-view-history": "Jeeagh er shennaghys",
-       "vector-view-view": "Lhaih",
-       "vector-view-viewsource": "Jeeagh er bun"
-}
diff --git a/skins/Vector/i18n/ha.json b/skins/Vector/i18n/ha.json
deleted file mode 100644 (file)
index 77e4975..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-       "vector-action-delete": "Soke",
-       "vector-action-move": "Gusarwa",
-       "vector-action-protect": "A kare",
-       "vector-view-create": "Ƙirƙira"
-}
diff --git a/skins/Vector/i18n/hak.json b/skins/Vector/i18n/hak.json
deleted file mode 100644 (file)
index ed0c0cb..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Anson2812",
-                       "Jetlag"
-               ]
-       },
-       "vector-action-addsection": "加入話題",
-       "vector-action-delete": "刪除",
-       "vector-action-move": "移動",
-       "vector-action-protect": "保護",
-       "vector-action-undelete": "恢復",
-       "vector-action-unprotect": "更改保護",
-       "vector-view-create": "建立",
-       "vector-view-edit": "編寫",
-       "vector-view-history": "查看歷史",
-       "vector-view-view": "閱讀",
-       "vector-view-viewsource": "查看源碼"
-}
diff --git a/skins/Vector/i18n/haw.json b/skins/Vector/i18n/haw.json
deleted file mode 100644 (file)
index 98e2919..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kolonahe"
-               ]
-       },
-       "vector-action-addsection": "Hoʻohui kumuhana",
-       "vector-action-delete": "Holoi",
-       "vector-action-move": "E hoʻoneʻe",
-       "vector-action-protect": "E hoʻomalu",
-       "vector-action-undelete": "Holoiʻole",
-       "vector-action-unprotect": "E hoʻololi i ka hoʻomalu",
-       "vector-view-create": "Haku",
-       "vector-view-edit": "Hoʻololi",
-       "vector-view-history": "Nānā i ka mōʻaukala",
-       "vector-view-view": "Heluhelu",
-       "vector-view-viewsource": "Nānā i ke kumu"
-}
diff --git a/skins/Vector/i18n/he.json b/skins/Vector/i18n/he.json
deleted file mode 100644 (file)
index 08a9023..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Amire80",
-                       "Rotemliss"
-               ]
-       },
-       "skinname-vector": "וקטור",
-       "vector.css": "/* הסגנונות הנכתבים כאן ישפיעו על העיצוב Vector בלבד */",
-       "vector.js": "/* כל סקריפט JavaScript שנכתב כאן ירוץ רק עבור המשתמשים בעיצוב Vector */",
-       "vector-action-addsection": "הוספת נושא",
-       "vector-action-delete": "מחיקה",
-       "vector-action-move": "העברה",
-       "vector-action-protect": "הגנה",
-       "vector-action-undelete": "ביטול מחיקה",
-       "vector-action-unprotect": "שינוי הגנה",
-       "vector-view-create": "יצירה",
-       "vector-view-edit": "עריכה",
-       "vector-view-history": "הצגת היסטוריה",
-       "vector-view-view": "קריאה",
-       "vector-view-viewsource": "הצגת מקור",
-       "vector-more-actions": "עוד"
-}
diff --git a/skins/Vector/i18n/hi.json b/skins/Vector/i18n/hi.json
deleted file mode 100644 (file)
index 5b5f56b..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Siddhartha Ghai",
-                       "आलोक",
-                       "रोहित रावत"
-               ]
-       },
-       "vector-action-addsection": "विषय जोड़ें",
-       "vector-action-delete": "हटाएँ",
-       "vector-action-move": "स्थानांतरण करें",
-       "vector-action-protect": "सुरक्षित करें",
-       "vector-action-undelete": "हटाना वापस लें",
-       "vector-action-unprotect": "सुरक्षा बदलें",
-       "vector-view-create": "बनाएँ",
-       "vector-view-edit": "सम्पादन",
-       "vector-view-history": "इतिहास देखें",
-       "vector-view-view": "पढ़ें",
-       "vector-view-viewsource": "स्रोत देखें"
-}
diff --git a/skins/Vector/i18n/hif-latn.json b/skins/Vector/i18n/hif-latn.json
deleted file mode 100644 (file)
index df37b3e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Girmitya",
-                       "Thakurji"
-               ]
-       },
-       "vector-action-addsection": "Topic jorro",
-       "vector-action-delete": "Mitao",
-       "vector-action-move": "Naam badlo",
-       "vector-action-protect": "Bachao",
-       "vector-action-undelete": "Pahile jaise karo",
-       "vector-action-unprotect": "Surakchha ke badlo",
-       "vector-view-create": "Banao",
-       "vector-view-edit": "Badlo",
-       "vector-view-history": "Itihaas dekho",
-       "vector-view-view": "Parrho",
-       "vector-view-viewsource": "Source dekho"
-}
diff --git a/skins/Vector/i18n/hil.json b/skins/Vector/i18n/hil.json
deleted file mode 100644 (file)
index 304f8ac..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Anjoeli9806"
-               ]
-       },
-       "vector-action-addsection": "Magdugang sang topiko",
-       "vector-action-delete": "Panason",
-       "vector-action-move": "Saylohon",
-       "vector-action-protect": "Pangapinan",
-       "vector-action-undelete": "Dulaon ang pagpanas",
-       "vector-action-unprotect": "Ilisan ang pagpangapin",
-       "vector-view-create": "Himuon",
-       "vector-view-edit": "Ilisan",
-       "vector-view-history": "Lantawon ang kasaysayan",
-       "vector-view-view": "Magbasa",
-       "vector-view-viewsource": "Lantawon ang ginhalinan"
-}
diff --git a/skins/Vector/i18n/hr.json b/skins/Vector/i18n/hr.json
deleted file mode 100644 (file)
index 1887ee5..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ex13",
-                       "Tivek"
-               ]
-       },
-       "vector-action-addsection": "Dodaj temu",
-       "vector-action-delete": "Izbriši",
-       "vector-action-move": "Premjesti",
-       "vector-action-protect": "Zaštiti",
-       "vector-action-undelete": "Vrati",
-       "vector-action-unprotect": "Promijeni zaštitu",
-       "vector-view-create": "Započni",
-       "vector-view-edit": "Uredi",
-       "vector-view-history": "Vidi stare izmjene",
-       "vector-view-view": "Čitaj",
-       "vector-view-viewsource": "Vidi izvor"
-}
diff --git a/skins/Vector/i18n/hrx.json b/skins/Vector/i18n/hrx.json
deleted file mode 100644 (file)
index 0a45056..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Paul Beppler"
-               ]
-       },
-       "vector-action-addsection": "Abschnitt hinzufüche",
-       "vector-action-delete": "Lösche",
-       "vector-action-move": "Verschiebe",
-       "vector-action-protect": "Schütz",
-       "vector-action-undelete": "Wiederherstelle",
-       "vector-action-unprotect": "Seiteschutz ännre",
-       "vector-view-create": "Erstell",
-       "vector-view-edit": "Beoorbeite",
-       "vector-view-history": "Versionsgeschicht",
-       "vector-view-view": "Lese",
-       "vector-view-viewsource": "Quelltext oonzeiche"
-}
diff --git a/skins/Vector/i18n/hsb.json b/skins/Vector/i18n/hsb.json
deleted file mode 100644 (file)
index a46105c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Michawiki"
-               ]
-       },
-       "vector-action-addsection": "Temu přidać",
-       "vector-action-delete": "wušmórnyć",
-       "vector-action-move": "přesunyć",
-       "vector-action-protect": "škitać",
-       "vector-action-undelete": "Wobnowić",
-       "vector-action-unprotect": "Škit wotstronić",
-       "vector-view-create": "Wutworić",
-       "vector-view-edit": "Wobdźěłać",
-       "vector-view-history": "Stawizny",
-       "vector-view-view": "Čitać",
-       "vector-view-viewsource": "Žórło sej wobhladać",
-       "vector-more-actions": "Wjace"
-}
diff --git a/skins/Vector/i18n/hsn.json b/skins/Vector/i18n/hsn.json
deleted file mode 100644 (file)
index 99d8dec..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "YulouCN"
-               ]
-       },
-       "vector-view-edit": "增改",
-       "vector-view-history": "履歷",
-       "vector-view-view": "讀"
-}
diff --git a/skins/Vector/i18n/ht.json b/skins/Vector/i18n/ht.json
deleted file mode 100644 (file)
index f71167a..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Boukman",
-                       "Internoob",
-                       "Masterches"
-               ]
-       },
-       "vector-action-addsection": "Ajoute yon sijè",
-       "vector-action-delete": "Efase",
-       "vector-action-move": "Chanje non",
-       "vector-action-protect": "Pwoteje",
-       "vector-action-undelete": "Retabli",
-       "vector-action-unprotect": "Pa pwoteje",
-       "vector-view-create": "Kreye",
-       "vector-view-edit": "Modifye",
-       "vector-view-history": "Gade istorik",
-       "vector-view-view": "Li",
-       "vector-view-viewsource": "Wè kòd tèks sa a"
-}
diff --git a/skins/Vector/i18n/hu-formal.json b/skins/Vector/i18n/hu-formal.json
deleted file mode 100644 (file)
index 4c9fcad..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Tacsipacsi"
-               ]
-       },
-       "vector-action-addsection": "Új téma nyitása",
-       "vector-action-delete": "Törlés",
-       "vector-action-move": "Átnevezés",
-       "vector-action-protect": "Lapvédelem",
-       "vector-action-undelete": "Visszaállítás",
-       "vector-action-unprotect": "Védelem módosítása",
-       "vector-view-create": "Létrehozás",
-       "vector-view-edit": "Szerkesztés",
-       "vector-view-history": "Laptörténet",
-       "vector-view-view": "Olvasás",
-       "vector-view-viewsource": "A lap forrása"
-}
diff --git a/skins/Vector/i18n/hu.json b/skins/Vector/i18n/hu.json
deleted file mode 100644 (file)
index a144ece..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Bdamokos",
-                       "Dani",
-                       "Dj",
-                       "Misibacsi",
-                       "Tacsipacsi",
-                       "Tgr"
-               ]
-       },
-       "vector.css": "/* Az ide elhelyezett CSS hatással lesz a Vector felület használóira */",
-       "vector.js": "/* A Vector felületet használó szerkesztők számára betöltendő JavaScriptek */",
-       "vector-action-addsection": "Új téma nyitása",
-       "vector-action-delete": "Törlés",
-       "vector-action-move": "Átnevezés",
-       "vector-action-protect": "Lapvédelem",
-       "vector-action-undelete": "Visszaállítás",
-       "vector-action-unprotect": "Védelem módosítása",
-       "vector-view-create": "Létrehozás",
-       "vector-view-edit": "Szerkesztés",
-       "vector-view-history": "Laptörténet",
-       "vector-view-view": "Olvasás",
-       "vector-view-viewsource": "A lap forrása",
-       "vector-more-actions": "Több"
-}
diff --git a/skins/Vector/i18n/hy.json b/skins/Vector/i18n/hy.json
deleted file mode 100644 (file)
index f8b322d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Teak",
-                       "Vadgt",
-                       "Xelgen"
-               ]
-       },
-       "skinname-vector": "Սովորական",
-       "vector-action-addsection": "Ավելացնել քննարկում",
-       "vector-action-delete": "Ջնջել",
-       "vector-action-move": "Տեղափոխել այս էջը",
-       "vector-action-protect": "Պաշտպանել",
-       "vector-action-undelete": "Վերականգնել",
-       "vector-action-unprotect": "Փոխել պաշտպանումը",
-       "vector-view-create": "Ստեղծել",
-       "vector-view-edit": "Խմբագրել",
-       "vector-view-history": "Դիտել պատմությունը",
-       "vector-view-view": "Կարդալ",
-       "vector-view-viewsource": "Դիտել ելատեքստը"
-}
diff --git a/skins/Vector/i18n/ia.json b/skins/Vector/i18n/ia.json
deleted file mode 100644 (file)
index c1281fc..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "McDutchie"
-               ]
-       },
-       "vector-skin-desc": "Version moderne de MonoBook con aspecto rejuvenescite e multe meliorationes de usabilitate.",
-       "vector.css": "/* Le CSS placiate hic afficera le usatores del apparentia Vector */",
-       "vector.js": "/* Omne JavaScript hic se executara pro le usatores del apparentia Vector */",
-       "vector-action-addsection": "Adder topico",
-       "vector-action-delete": "Deler",
-       "vector-action-move": "Renominar",
-       "vector-action-protect": "Proteger",
-       "vector-action-undelete": "Restaurar",
-       "vector-action-unprotect": "Cambiar protection",
-       "vector-view-create": "Crear",
-       "vector-view-edit": "Modificar",
-       "vector-view-history": "Vider historia",
-       "vector-view-view": "Leger",
-       "vector-view-viewsource": "Vider texto fonte",
-       "vector-more-actions": "Plus"
-}
diff --git a/skins/Vector/i18n/id.json b/skins/Vector/i18n/id.json
deleted file mode 100644 (file)
index 3116632..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Arifin.wijaya",
-                       "Bennylin",
-                       "Farras",
-                       "Iwan Novirion",
-                       "Rex"
-               ]
-       },
-       "skinname-vector": "Vektor",
-       "vector.css": "/* CSS nan ado di siko diterapkan pado kulik Vektor. */",
-       "vector.js": "/* Semua JavaScript di sini akan dimuatkan untuk para pengguna yang menggunakan kulit Vector */",
-       "vector-action-addsection": "Bagian baru",
-       "vector-action-delete": "Hapus",
-       "vector-action-move": "Pindahkan",
-       "vector-action-protect": "Lindungi",
-       "vector-action-undelete": "Pembatalan penghapusan",
-       "vector-action-unprotect": "Ubah perlindungan",
-       "vector-view-create": "Buat",
-       "vector-view-edit": "Sunting",
-       "vector-view-history": "Versi terdahulu",
-       "vector-view-view": "Baca",
-       "vector-view-viewsource": "Lihat sumber",
-       "vector-more-actions": "Lainnya"
-}
diff --git a/skins/Vector/i18n/ie.json b/skins/Vector/i18n/ie.json
deleted file mode 100644 (file)
index 259b88b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Makuba",
-                       "Renan"
-               ]
-       },
-       "vector.css": "/* CSS colocat ci va afectar usatores de pelle Vector */",
-       "vector.js": "/* Alquel JavaScript ci va esser cargat por usatores que usa li pelle Vector */",
-       "vector-action-addsection": "Adjunter tema",
-       "vector-action-delete": "Deleter",
-       "vector-action-move": "Mover",
-       "vector-action-protect": "Gardar",
-       "vector-action-undelete": "Restituer",
-       "vector-action-unprotect": "Desgardar",
-       "vector-view-create": "Crear",
-       "vector-view-edit": "Redacter",
-       "vector-view-history": "Historie de versiones",
-       "vector-view-view": "Leer",
-       "vector-view-viewsource": "Vider fonte"
-}
diff --git a/skins/Vector/i18n/ig.json b/skins/Vector/i18n/ig.json
deleted file mode 100644 (file)
index 66e93cc..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ukabia"
-               ]
-       },
-       "vector-action-addsection": "Tinyé Okwu",
-       "vector-action-delete": "Kàcha",
-       "vector-action-move": "Páfụ",
-       "vector-action-protect": "Cẹdolu",
-       "vector-action-undelete": "Á gbàkashikwà",
-       "vector-action-unprotect": "Nchẹdo mgbanwe",
-       "vector-view-create": "Ké",
-       "vector-view-edit": "Mèzi",
-       "vector-view-history": "Zí ịta",
-       "vector-view-view": "Gụ́",
-       "vector-view-viewsource": "Zi mkpurụ"
-}
diff --git a/skins/Vector/i18n/ike-latn.json b/skins/Vector/i18n/ike-latn.json
deleted file mode 100644 (file)
index ab22a4a..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "vector-view-edit": "Suqusiqpaa"
-}
diff --git a/skins/Vector/i18n/ilo.json b/skins/Vector/i18n/ilo.json
deleted file mode 100644 (file)
index 817c75f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Lam-ang",
-                       "Saluyot"
-               ]
-       },
-       "vector-action-addsection": "Agnayon ti topiko",
-       "vector-action-delete": "Ikkaten",
-       "vector-action-move": "Iyalis",
-       "vector-action-protect": "Salakniban",
-       "vector-action-undelete": "Isubli ti inikkat",
-       "vector-action-unprotect": "Sukatan ti salaknib",
-       "vector-view-create": "Agaramid",
-       "vector-view-edit": "Urnosen",
-       "vector-view-history": "Kitaen ti pakasaritaan",
-       "vector-view-view": "Basaen",
-       "vector-view-viewsource": "Kitaen ti taudan",
-       "vector-more-actions": "Adu pay"
-}
diff --git a/skins/Vector/i18n/inh.json b/skins/Vector/i18n/inh.json
deleted file mode 100644 (file)
index e50a3ec..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Amire80",
-                       "Sapral Mikail"
-               ]
-       },
-       "vector-action-addsection": "БӀагал тӀатоха",
-       "vector-action-delete": "ДӀадаккха",
-       "vector-action-move": "ЦӀи хувца",
-       "vector-action-protect": "Лораде",
-       "vector-action-undelete": "Юхаоттаде",
-       "vector-action-unprotect": "Лорам хувца",
-       "vector-view-create": "Кхолларле",
-       "vector-view-edit": "Хувцам",
-       "vector-view-history": "Искар",
-       "vector-view-view": "Дешар",
-       "vector-view-viewsource": "Зембакхама бӀаргтассам"
-}
diff --git a/skins/Vector/i18n/io.json b/skins/Vector/i18n/io.json
deleted file mode 100644 (file)
index 3bfec4d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Malafaya"
-               ]
-       },
-       "vector-action-addsection": "Adjuntar topiko",
-       "vector-action-delete": "Efacar",
-       "vector-action-move": "Movar",
-       "vector-action-protect": "Protektar",
-       "vector-action-undelete": "Rekuperar",
-       "vector-action-unprotect": "Desprotektar",
-       "vector-view-create": "Krear",
-       "vector-view-edit": "Redaktar",
-       "vector-view-history": "Vidar versionaro",
-       "vector-view-view": "Lektar",
-       "vector-view-viewsource": "Vidar fonto"
-}
diff --git a/skins/Vector/i18n/is.json b/skins/Vector/i18n/is.json
deleted file mode 100644 (file)
index dc54f1b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Friðrik Bragi Dýrfjörð",
-                       "Maxí",
-                       "Snævar",
-                       "Ævar Arnfjörð Bjarmason"
-               ]
-       },
-       "vector-action-addsection": "Bæta við umræðu",
-       "vector-action-delete": "Eyða",
-       "vector-action-move": "Færa",
-       "vector-action-protect": "Vernda",
-       "vector-action-undelete": "Hætta við eyðingu",
-       "vector-action-unprotect": "Breyta verndunarstigi",
-       "vector-view-create": "Skapa",
-       "vector-view-edit": "Breyta",
-       "vector-view-history": "Breytingaskrá",
-       "vector-view-view": "Lesa",
-       "vector-view-viewsource": "Sýna frumkóða"
-}
diff --git a/skins/Vector/i18n/it.json b/skins/Vector/i18n/it.json
deleted file mode 100644 (file)
index 1598efe..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Beta16",
-                       "Darth Kule",
-                       "Gianfranco",
-                       "Melos",
-                       "Pietrodn"
-               ]
-       },
-       "vector-skin-desc": "Versione moderna del MonoBook con un'aspetto nuovo e molti miglioramenti dell'usabilità",
-       "vector.css": "/* Gli stili CSS inseriti qui si applicano agli utenti che usano la skin Vector */",
-       "vector.js": "/* Il codice JavaScript inserito qui viene caricato dagli utenti che usano la skin Vector */",
-       "vector-action-addsection": "Aggiungi discussione",
-       "vector-action-delete": "Cancella",
-       "vector-action-move": "Sposta",
-       "vector-action-protect": "Proteggi",
-       "vector-action-undelete": "Ripristina",
-       "vector-action-unprotect": "Cambia la protezione",
-       "vector-view-create": "Crea",
-       "vector-view-edit": "Modifica",
-       "vector-view-history": "Cronologia",
-       "vector-view-view": "Leggi",
-       "vector-view-viewsource": "Visualizza sorgente",
-       "vector-more-actions": "Altro"
-}
diff --git a/skins/Vector/i18n/izh.json b/skins/Vector/i18n/izh.json
deleted file mode 100644 (file)
index ab41111..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Aig mest ei varasta"
-               ]
-       },
-       "vector-view-view": "Lukkiia"
-}
diff --git a/skins/Vector/i18n/ja.json b/skins/Vector/i18n/ja.json
deleted file mode 100644 (file)
index 7bfa57e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Fryed-peach",
-                       "Marine-Blue",
-                       "Penn Station",
-                       "Shirayuki",
-                       "Whym",
-                       "青子守歌"
-               ]
-       },
-       "skinname-vector": "ベクター",
-       "vector.css": "/* ここに記述したCSSはベクター外装の利用者に影響します */",
-       "vector.js": "/* ここにあるすべてのJavaScriptは、ベクター外装を使用している利用者に対して読み込まれます */",
-       "vector-action-addsection": "話題追加",
-       "vector-action-delete": "削除",
-       "vector-action-move": "移動",
-       "vector-action-protect": "保護",
-       "vector-action-undelete": "復元",
-       "vector-action-unprotect": "保護再設定",
-       "vector-view-create": "作成",
-       "vector-view-edit": "編集",
-       "vector-view-history": "履歴表示",
-       "vector-view-view": "閲覧",
-       "vector-view-viewsource": "ソースを閲覧",
-       "vector-more-actions": "その他"
-}
diff --git a/skins/Vector/i18n/jam.json b/skins/Vector/i18n/jam.json
deleted file mode 100644 (file)
index cf84305..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Hazard-SJ",
-                       "Yocahuna"
-               ]
-       },
-       "vector-action-addsection": "Ad tapik",
-       "vector-action-delete": "Diliit",
-       "vector-action-move": "Muuv",
-       "vector-action-protect": "Protek",
-       "vector-action-undelete": "Andiliit",
-       "vector-action-unprotect": "Neu protektian",
-       "vector-view-create": "Kriet",
-       "vector-view-edit": "Hedit",
-       "vector-view-history": "Vyuu ischri",
-       "vector-view-view": "Riid",
-       "vector-view-viewsource": "Vyuu Suos"
-}
diff --git a/skins/Vector/i18n/jbo.json b/skins/Vector/i18n/jbo.json
deleted file mode 100644 (file)
index bc1f172..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Gleki"
-               ]
-       },
-       "vector-action-addsection": "jmina la'e se casnu",
-       "vector-action-delete": "vimcu",
-       "vector-action-move": "stika lo cmene",
-       "vector-action-protect": "bandu",
-       "vector-view-create": "zbasu",
-       "vector-view-edit": "stika",
-       "vector-view-history": "lo ckupau citri",
-       "vector-view-view": "tcidu",
-       "vector-view-viewsource": "cpacu lo krasi",
-       "vector-more-actions": "ji'a"
-}
diff --git a/skins/Vector/i18n/jv.json b/skins/Vector/i18n/jv.json
deleted file mode 100644 (file)
index 7af6b95..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Pras"
-               ]
-       },
-       "vector-action-addsection": "Tambah topik",
-       "vector-action-delete": "Busak",
-       "vector-action-move": "Pindhahna",
-       "vector-action-protect": "Reksa",
-       "vector-action-undelete": "Batalna pambusakan",
-       "vector-action-unprotect": "Owahi pangreksan",
-       "vector-view-create": "Gawé",
-       "vector-view-edit": "Sunting",
-       "vector-view-history": "Sajarah kaca",
-       "vector-view-view": "Waca",
-       "vector-view-viewsource": "Pirsani sumber"
-}
diff --git a/skins/Vector/i18n/ka.json b/skins/Vector/i18n/ka.json
deleted file mode 100644 (file)
index a08fe71..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Alsandro",
-                       "David1010",
-                       "გიორგიმელა"
-               ]
-       },
-       "skinname-vector": "ვექტორული",
-       "vector.css": "/* აქ ჩასმული CSS გამოყენებული იქნება ვექტორული გაფორმების თემაში */",
-       "vector-action-addsection": "თემის ჩამატება",
-       "vector-action-delete": "წაშლა",
-       "vector-action-move": "გადატანა",
-       "vector-action-protect": "დაცვა",
-       "vector-action-undelete": "აღდგენა",
-       "vector-action-unprotect": "დაცვის შეცვლა",
-       "vector-view-create": "შექმნა",
-       "vector-view-edit": "რედაქტირება",
-       "vector-view-history": "ისტორია",
-       "vector-view-view": "შემოწმებული სტატია",
-       "vector-view-viewsource": "წყაროს ხილვა",
-       "vector-more-actions": "მეტი"
-}
diff --git a/skins/Vector/i18n/kaa.json b/skins/Vector/i18n/kaa.json
deleted file mode 100644 (file)
index 1518526..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Atabek"
-               ]
-       },
-       "vector-action-addsection": "Tema qosıw",
-       "vector-action-delete": "O'shiriw",
-       "vector-action-move": "Ko'shiriw",
-       "vector-action-protect": "Qorg'aw",
-       "vector-action-undelete": "Qayta tiklew",
-       "vector-action-unprotect": "Qorg'awdı o'zgertiw",
-       "vector-view-create": "Jaratıw",
-       "vector-view-edit": "O'zgertiw",
-       "vector-view-history": "Tariyxın ko'riw",
-       "vector-view-view": "Oqıw",
-       "vector-view-viewsource": "Deregin ko'riw"
-}
diff --git a/skins/Vector/i18n/kab.json b/skins/Vector/i18n/kab.json
deleted file mode 100644 (file)
index f233083..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mmistmurt"
-               ]
-       },
-       "vector-action-addsection": "Rnud ameggay",
-       "vector-action-delete": "Mḥu",
-       "vector-action-move": "Smimeḍ",
-       "vector-action-protect": "Mmesten",
-       "vector-action-undelete": "Uɣaled",
-       "vector-action-unprotect": "Beddel amesten",
-       "vector-view-create": "Snulfu",
-       "vector-view-edit": "Ẓẓiẓreg",
-       "vector-view-history": "Ẓeṛ amazray",
-       "vector-view-view": "Ɣer",
-       "vector-view-viewsource": "Ẓer aɣbalu"
-}
diff --git a/skins/Vector/i18n/kbd-cyrl.json b/skins/Vector/i18n/kbd-cyrl.json
deleted file mode 100644 (file)
index efd893e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Bogups",
-                       "Тамэ Балъкъэрхэ"
-               ]
-       },
-       "vector-action-addsection": "Теухугъуэ щӀэуэ щӀэдзэн",
-       "vector-action-delete": "Ихын",
-       "vector-action-move": "ЦӀэр хъуэжын",
-       "vector-action-protect": "Хъумэн",
-       "vector-action-undelete": "ЗыфӀэгъэувэжын",
-       "vector-action-unprotect": "Хъумэныр техыжын",
-       "vector-view-create": "ЩӀын",
-       "vector-view-edit": "Гъэтэрэзын",
-       "vector-view-history": "Тхыдэм еплъын",
-       "vector-view-view": "Еджэн",
-       "vector-view-viewsource": "КъызхэкӀам еплъын"
-}
diff --git a/skins/Vector/i18n/kg.json b/skins/Vector/i18n/kg.json
deleted file mode 100644 (file)
index f88430a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Rkupsala"
-               ]
-       },
-       "vector-action-delete": "Kufwa",
-       "vector-action-move": "Nata",
-       "vector-action-protect": "Keba",
-       "vector-view-create": "Tunga",
-       "vector-view-edit": "Soba",
-       "vector-view-history": "Tala bansoba",
-       "vector-view-view": "Tânga"
-}
diff --git a/skins/Vector/i18n/khw.json b/skins/Vector/i18n/khw.json
deleted file mode 100644 (file)
index a0ceaca..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Rachitrali"
-               ]
-       },
-       "vector-action-addsection": "نوغ موضوع",
-       "vector-action-delete": "بوغاوے",
-       "vector-action-move": "منتقل کورے",
-       "vector-action-protect": "محفوظ کورے",
-       "vector-action-undelete": "اچی انگیے",
-       "vector-action-unprotect": "غیر محفوظ",
-       "vector-view-create": "ساوزاوے",
-       "vector-view-edit": "ایڈٹ کورے",
-       "vector-view-history": "تاریخچہ",
-       "vector-view-view": "راوے",
-       "vector-view-viewsource": "مسودہ"
-}
diff --git a/skins/Vector/i18n/ki.json b/skins/Vector/i18n/ki.json
deleted file mode 100644 (file)
index 30f6a5f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Stephenwanjau"
-               ]
-       },
-       "vector-action-delete": "Futa"
-}
diff --git a/skins/Vector/i18n/kiu.json b/skins/Vector/i18n/kiu.json
deleted file mode 100644 (file)
index 3d2c3cc..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mirzali"
-               ]
-       },
-       "vector-action-addsection": "Mewzu ilawe ke",
-       "vector-action-delete": "Bestere",
-       "vector-action-move": "Bere",
-       "vector-action-protect": "Bısevekne",
-       "vector-action-undelete": "Esterıtene peyser bıcê",
-       "vector-action-unprotect": "Rake",
-       "vector-view-create": "Vıraze",
-       "vector-view-edit": "Bıvurne",
-       "vector-view-history": "Tarixi basne",
-       "vector-view-view": "Bıwane",
-       "vector-view-viewsource": "Çımey bıvêne"
-}
diff --git a/skins/Vector/i18n/kk-cyrl.json b/skins/Vector/i18n/kk-cyrl.json
deleted file mode 100644 (file)
index 3593350..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Arystanbek",
-                       "Daniyar",
-                       "GaiJin",
-                       "Kaztrans"
-               ]
-       },
-       "vector-action-addsection": "Тақырып қосу",
-       "vector-action-delete": "Жою",
-       "vector-action-move": "Атауын өзгерту",
-       "vector-action-protect": "Қорғау",
-       "vector-action-undelete": "Жоймау",
-       "vector-action-unprotect": "Қорғанысын өзгерту",
-       "vector-view-create": "Бастау",
-       "vector-view-edit": "Өңдеу",
-       "vector-view-history": "Өңделу тарихы",
-       "vector-view-view": "Оқу",
-       "vector-view-viewsource": "Қайнарын қарау",
-       "vector-more-actions": "Тағы"
-}
diff --git a/skins/Vector/i18n/kl.json b/skins/Vector/i18n/kl.json
deleted file mode 100644 (file)
index 6a3d7b1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Iketsi",
-                       "Qaqqalik"
-               ]
-       },
-       "vector-action-addsection": "Imm. nutaaq",
-       "vector-action-move": "Nuuguk",
-       "vector-view-create": "Pilersiguk",
-       "vector-view-edit": "Aaqqissoruk",
-       "vector-view-history": "Oqalutt.",
-       "vector-view-view": "Takuuk",
-       "vector-view-viewsource": "Toqqavia takuuk"
-}
diff --git a/skins/Vector/i18n/km.json b/skins/Vector/i18n/km.json
deleted file mode 100644 (file)
index 6827117..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "គីមស៊្រុន",
-                       "វ័ណថារិទ្ធ"
-               ]
-       },
-       "skinname-vector": "វ៉ិចទ័រ​​",
-       "vector.css": "/* CSS បានដាក់ទីនេះនឹងមានអនុភាពលើអ្នកប្រើប្រាស់នៃសំបក Vector */",
-       "vector-action-addsection": "បន្ថែម​ប្រធានបទ​",
-       "vector-action-delete": "លុបចោល",
-       "vector-action-move": "ប្តូរទីតាំង",
-       "vector-action-protect": "ការពារ",
-       "vector-action-undelete": "ឈប់លុបចោល",
-       "vector-action-unprotect": "ប្ដូរការការពារ",
-       "vector-view-create": "បង្កើត​",
-       "vector-view-edit": "កែប្រែ​",
-       "vector-view-history": "មើល​ប្រវត្តិ​",
-       "vector-view-view": "អាន",
-       "vector-view-viewsource": "មើល​កូដ"
-}
diff --git a/skins/Vector/i18n/kn.json b/skins/Vector/i18n/kn.json
deleted file mode 100644 (file)
index aae7272..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ktkaushik",
-                       "Nayvik",
-                       "VASANTH S.N."
-               ]
-       },
-       "vector-action-addsection": "ವಿಷಯ ಸೇರಿಸಿ",
-       "vector-action-delete": "ಅಳಿಸು",
-       "vector-action-move": "ಸ್ಥಳಾಂತರಿಸಿ",
-       "vector-action-protect": "ಸಂರಕ್ಷಿಸು",
-       "vector-action-undelete": "ಅಳಿಸಬೇಡ",
-       "vector-action-unprotect": "ರಕ್ಷಣೆಯನ್ನು ಬದಲಾವಣೆ",
-       "vector-view-create": "ಸೃಷ್ಟಿಸು",
-       "vector-view-edit": "ಸಂಪಾದಿಸಿ",
-       "vector-view-history": "ಇತಿಹಾಸವನ್ನು ನೋಡಿ",
-       "vector-view-view": "ಓದು",
-       "vector-view-viewsource": "ಆಕರ ವೀಕ್ಷಿಸು"
-}
diff --git a/skins/Vector/i18n/ko.json b/skins/Vector/i18n/ko.json
deleted file mode 100644 (file)
index 038f342..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "ITurtle",
-                       "Kwj2772",
-                       "아라"
-               ]
-       },
-       "skinname-vector": "벡터",
-       "vector-skin-desc": "모노북 스킨을 사용할 때 사용자 인터페이스를 향상합니다",
-       "vector.css": "/* 이 CSS 설정은 벡터 스킨을 사용하는 사용자에게 적용됩니다 */",
-       "vector.js": "/* 이 자바스크립트 설정은 벡터 스킨을 사용하는 사용자에게 적용됩니다 */",
-       "vector-action-addsection": "새 주제",
-       "vector-action-delete": "삭제",
-       "vector-action-move": "옮기기",
-       "vector-action-protect": "보호",
-       "vector-action-undelete": "삭제 취소",
-       "vector-action-unprotect": "보호 설정 바꾸기",
-       "vector-view-create": "만들기",
-       "vector-view-edit": "편집",
-       "vector-view-history": "역사 보기",
-       "vector-view-view": "읽기",
-       "vector-view-viewsource": "원본 보기",
-       "vector-more-actions": "더 보기"
-}
diff --git a/skins/Vector/i18n/koi.json b/skins/Vector/i18n/koi.json
deleted file mode 100644 (file)
index 1753f44..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Enye Lav"
-               ]
-       },
-       "vector-action-delete": "Чышкыны",
-       "vector-view-view": "Лыддьöтны"
-}
diff --git a/skins/Vector/i18n/krc.json b/skins/Vector/i18n/krc.json
deleted file mode 100644 (file)
index cdb2f55..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Iltever",
-                       "Къарачайлы"
-               ]
-       },
-       "skinname-vector": "Вектор",
-       "vector-action-addsection": "Джангы тема къош",
-       "vector-action-delete": "Кетер",
-       "vector-action-move": "Атын ауушдур",
-       "vector-action-protect": "Джакъла",
-       "vector-action-undelete": "Къайтар",
-       "vector-action-unprotect": "Джакълауну тюрлендир",
-       "vector-view-create": "Къура",
-       "vector-view-edit": "Тюрлендир",
-       "vector-view-history": "Тарихи",
-       "vector-view-view": "Окъу",
-       "vector-view-viewsource": "Кодха къара",
-       "vector-more-actions": "Энтда"
-}
diff --git a/skins/Vector/i18n/kri.json b/skins/Vector/i18n/kri.json
deleted file mode 100644 (file)
index 056a9e5..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Protostar"
-               ]
-       },
-       "vector-action-addsection": "Add tòpik",
-       "vector-action-delete": "Delet",
-       "vector-action-move": "Muf",
-       "vector-action-protect": "Protèkt",
-       "vector-view-create": "Kreat",
-       "vector-view-edit": "Chenj",
-       "vector-view-history": "Luk historia",
-       "vector-view-view": "Rid",
-       "vector-view-viewsource": "Luk dhi sòrs"
-}
diff --git a/skins/Vector/i18n/ks-arab.json b/skins/Vector/i18n/ks-arab.json
deleted file mode 100644 (file)
index 68c34ad..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-       "vector-view-edit": "تَرتیٖب دِیُن",
-       "vector-view-view": "پَرُن"
-}
diff --git a/skins/Vector/i18n/ksh.json b/skins/Vector/i18n/ksh.json
deleted file mode 100644 (file)
index 7d91fae..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Purodha"
-               ]
-       },
-       "skinname-vector": "Vektor",
-       "vector.css": "/* CSS heh aan dä Stell wirrek nur op de Ovverflääsch „Vector“ */",
-       "vector.js": "/* De JavaSkrippte fun hee krijje alle Sigge met de Ovverflääsch \"Vector\" jescheck */",
-       "vector-action-addsection": "Ne neue Afschnet onge draan!",
-       "vector-action-delete": "Fottschmiiße!",
-       "vector-action-move": "Ömnänne!",
-       "vector-action-protect": "Schöze!",
-       "vector-action-undelete": "Zerökholle!",
-       "vector-action-unprotect": "Schoz ändere!",
-       "vector-view-create": "Neu Schriive!",
-       "vector-view-edit": "Ändere!",
-       "vector-view-history": "Versione zeije!",
-       "vector-view-view": "Lesse!",
-       "vector-view-viewsource": "Wikitex aanlooere!"
-}
diff --git a/skins/Vector/i18n/ku-latn.json b/skins/Vector/i18n/ku-latn.json
deleted file mode 100644 (file)
index 90e0706..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ferhengvan",
-                       "Gomada"
-               ]
-       },
-       "vector-action-addsection": "Mijarekê lê zêde bike",
-       "vector-action-delete": "Jê bibe",
-       "vector-action-move": "Nav biguherîne",
-       "vector-action-protect": "Biparêze",
-       "vector-action-undelete": "Jê nebe",
-       "vector-action-unprotect": "Parastinê rake",
-       "vector-view-create": "Çêke",
-       "vector-view-edit": "Biguherîne",
-       "vector-view-history": "Dîrokê bibîne",
-       "vector-view-view": "Bixwîne",
-       "vector-view-viewsource": "Çavkaniyan bibîne"
-}
diff --git a/skins/Vector/i18n/kv.json b/skins/Vector/i18n/kv.json
deleted file mode 100644 (file)
index d3df069..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Comp1089"
-               ]
-       },
-       "vector-action-move": "Ним вежны",
-       "vector-view-edit": "Вежны",
-       "vector-view-view": "Лыддьыны"
-}
diff --git a/skins/Vector/i18n/kw.json b/skins/Vector/i18n/kw.json
deleted file mode 100644 (file)
index 4a2975c..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kernoweger",
-                       "Kw-Moon",
-                       "Nrowe"
-               ]
-       },
-       "vector-action-addsection": "Keworra testen",
-       "vector-action-delete": "Dilea",
-       "vector-action-move": "Gwaya",
-       "vector-action-protect": "Difres",
-       "vector-action-undelete": "Disdhilea",
-       "vector-action-unprotect": "Chanjya difresans",
-       "vector-view-create": "Gwruthyl",
-       "vector-view-edit": "Chanjya",
-       "vector-view-history": "Gweles an istori",
-       "vector-view-view": "Redya",
-       "vector-view-viewsource": "Gweles an bennfenten"
-}
diff --git a/skins/Vector/i18n/ky.json b/skins/Vector/i18n/ky.json
deleted file mode 100644 (file)
index e536d9b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Chorobek",
-                       "Growingup",
-                       "Ztimur",
-                       "Викиней"
-               ]
-       },
-       "vector-action-addsection": "Тема кошуу",
-       "vector-action-delete": "Өчүрүү",
-       "vector-action-move": "Аталышын өзгөртүү",
-       "vector-action-protect": "Коргоо",
-       "vector-action-undelete": "Калыбына келтирүү",
-       "vector-action-unprotect": "Коргоону өзгөртүү",
-       "vector-view-create": "Түзүү",
-       "vector-view-edit": "Оңдоо",
-       "vector-view-history": "Тарыхын кароо",
-       "vector-view-view": "Окуу",
-       "vector-view-viewsource": "Кайнарын кароо"
-}
diff --git a/skins/Vector/i18n/la.json b/skins/Vector/i18n/la.json
deleted file mode 100644 (file)
index 2cc4ad2..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "UV"
-               ]
-       },
-       "vector-action-addsection": "Partem novam addere",
-       "vector-action-delete": "Delere",
-       "vector-action-move": "Movere",
-       "vector-action-protect": "Protegere",
-       "vector-action-undelete": "Restituere",
-       "vector-action-unprotect": "Protectionem mutare",
-       "vector-view-create": "Creare",
-       "vector-view-edit": "Recensere",
-       "vector-view-history": "Historiam inspicere",
-       "vector-view-view": "Legere",
-       "vector-view-viewsource": "Fontem inspicere",
-       "vector-more-actions": "Plus"
-}
diff --git a/skins/Vector/i18n/lad.json b/skins/Vector/i18n/lad.json
deleted file mode 100644 (file)
index 729ec48..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Universal Life"
-               ]
-       },
-       "vector-action-addsection": "Ajustar sujeto",
-       "vector-action-delete": "Efassar",
-       "vector-action-move": "Taşirear",
-       "vector-action-protect": "Guadrar",
-       "vector-action-undelete": "Traer atrás",
-       "vector-action-unprotect": "Trocar proteksyon",
-       "vector-view-create": "Criar",
-       "vector-view-edit": "Trocar",
-       "vector-view-history": "Ver la istoria",
-       "vector-view-view": "Meldar",
-       "vector-view-viewsource": "Ver su manadero"
-}
diff --git a/skins/Vector/i18n/lb.json b/skins/Vector/i18n/lb.json
deleted file mode 100644 (file)
index cb26439..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Robby"
-               ]
-       },
-       "vector-skin-desc": "Modern Versioun vu Monobook mat frëschem Look a ville Verbesserunge vun der Benotzerfrëndlechkeet",
-       "vector-action-addsection": "Sujet derbäisetzen",
-       "vector-action-delete": "Läschen",
-       "vector-action-move": "Réckelen",
-       "vector-action-protect": "Spären",
-       "vector-action-undelete": "Restauréieren",
-       "vector-action-unprotect": "Spär änneren",
-       "vector-view-create": "Uleeën",
-       "vector-view-edit": "Änneren",
-       "vector-view-history": "Versioune weisen",
-       "vector-view-view": "Liesen",
-       "vector-view-viewsource": "Quellcode weisen",
-       "vector-more-actions": "Méi"
-}
diff --git a/skins/Vector/i18n/lez.json b/skins/Vector/i18n/lez.json
deleted file mode 100644 (file)
index d132626..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Lezgia",
-                       "Migraghvi",
-                       "Namik",
-                       "Soul Train"
-               ]
-       },
-       "vector-action-addsection": "Тема алава авун",
-       "vector-action-delete": "Алудун",
-       "vector-action-move": "ТӀвар эхцигун",
-       "vector-action-protect": "Хуьн",
-       "vector-action-undelete": "ТуькӀуьр хъувун",
-       "vector-action-unprotect": "Хуьн дегишарун",
-       "vector-view-create": "ТуькӀуьрун",
-       "vector-view-edit": "Дуьзарин",
-       "vector-view-history": "Тарихдиз килигун",
-       "vector-view-view": "КӀелун",
-       "vector-view-viewsource": "Чешме къалурун"
-}
diff --git a/skins/Vector/i18n/lg.json b/skins/Vector/i18n/lg.json
deleted file mode 100644 (file)
index 4282900..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kizito"
-               ]
-       },
-       "vector-action-addsection": "Tandikawo emboozi endala",
-       "vector-action-delete": "Gyawo olupapula luno",
-       "vector-action-move": "Simbuliza",
-       "vector-action-protect": "Ssiba",
-       "vector-action-undelete": "Zawo",
-       "vector-action-unprotect": "Kyusa ebikugizo",
-       "vector-view-create": "Lukolewo",
-       "vector-view-edit": "Kyusa",
-       "vector-view-history": "Ennanda ya fayiro eno",
-       "vector-view-view": "Soma",
-       "vector-view-viewsource": "Kebera obulambike obw'ennono obw'olupapula luno"
-}
diff --git a/skins/Vector/i18n/li.json b/skins/Vector/i18n/li.json
deleted file mode 100644 (file)
index 8fe7e26..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ooswesthoesbes"
-               ]
-       },
-       "vector-action-addsection": "Voog köpke toe",
-       "vector-action-delete": "Ewegsjaffe",
-       "vector-action-move": "Verplaats",
-       "vector-action-protect": "Besjirm",
-       "vector-action-undelete": "Plaats trök",
-       "vector-action-unprotect": "Anger beveiliging",
-       "vector-view-create": "Maak aan",
-       "vector-view-edit": "Bewirk",
-       "vector-view-history": "Bekiek de gesjiedenis",
-       "vector-view-view": "Laes",
-       "vector-view-viewsource": "Bekiek bróntèks"
-}
diff --git a/skins/Vector/i18n/lij.json b/skins/Vector/i18n/lij.json
deleted file mode 100644 (file)
index e73547c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Gastaz",
-                       "Giromin Cangiaxo"
-               ]
-       },
-       "vector-action-addsection": "Azónzi discusción",
-       "vector-action-delete": "Scancella",
-       "vector-action-move": "Mescia",
-       "vector-action-protect": "Protezi",
-       "vector-action-undelete": "Recuppera",
-       "vector-action-unprotect": "Cangia a proteçion",
-       "vector-view-create": "Crea",
-       "vector-view-edit": "Càngia",
-       "vector-view-history": "Fanni védde a Stöia",
-       "vector-view-view": "Lêzi",
-       "vector-view-viewsource": "Veddi a sorgénte"
-}
diff --git a/skins/Vector/i18n/liv.json b/skins/Vector/i18n/liv.json
deleted file mode 100644 (file)
index 68518e5..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Warbola"
-               ]
-       },
-       "vector-action-addsection": "Pangid jūrõ tēma",
-       "vector-action-delete": "Kištāntõgid jarā",
-       "vector-action-move": "Vīž jarā",
-       "vector-action-protect": "Kaitsõmi",
-       "vector-view-create": "Lūo",
-       "vector-view-edit": "Redigīer",
-       "vector-view-history": "Nägţ istōrijõ",
-       "vector-view-view": "Vaņ",
-       "vector-view-viewsource": "Vaņ ovāt tekstõ"
-}
diff --git a/skins/Vector/i18n/lmo.json b/skins/Vector/i18n/lmo.json
deleted file mode 100644 (file)
index a5c8624..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Insübrich",
-                       "Ninonino"
-               ]
-       },
-       "vector-action-addsection": "Giunta argument",
-       "vector-action-delete": "Scancela",
-       "vector-action-move": "Sposta",
-       "vector-action-protect": "Prutegg",
-       "vector-action-undelete": "Recüpera",
-       "vector-action-unprotect": "Càmbia la protesiù",
-       "vector-view-create": "Crea",
-       "vector-view-edit": "Mudifega",
-       "vector-view-history": "Varda la storia",
-       "vector-view-view": "Legg",
-       "vector-view-viewsource": "Varda el codes",
-       "vector-more-actions": "Amò"
-}
diff --git a/skins/Vector/i18n/ln.json b/skins/Vector/i18n/ln.json
deleted file mode 100644 (file)
index 5fb4011..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Eruedin",
-                       "Moyogo"
-               ]
-       },
-       "vector-action-addsection": "Kobakisa mpɔ̂",
-       "vector-action-delete": "Kolímwisa",
-       "vector-action-move": "Kobóngola nkómbó",
-       "vector-action-protect": "Kobátela",
-       "vector-action-undelete": "Kolímwisa tɛ̂",
-       "vector-action-unprotect": " Kobátela tɛ̂",
-       "vector-view-create": "Kokela",
-       "vector-view-edit": "Kobɔngisa",
-       "vector-view-history": "Komɔ́nisa mokóló",
-       "vector-view-view": "Kotánga",
-       "vector-view-viewsource": "Komɔ́nisa mosólo"
-}
diff --git a/skins/Vector/i18n/lrc.json b/skins/Vector/i18n/lrc.json
deleted file mode 100644 (file)
index 8f6f09a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mogoeilor"
-               ]
-       },
-       "vector-action-addsection": "موضوع اضاف بكيد",
-       "vector-action-delete": "حذف بكيد",
-       "vector-action-move": "جاوه جا بوئيت",
-       "vector-action-protect": "حمايت بكيد",
-       "vector-action-undelete": "حذف نبيئني",
-       "vector-action-unprotect": "حمايت آلشت بكيد",
-       "vector-view-create": "راس كردن",
-       "vector-view-edit": "ويرايشت",
-       "vector-view-history": "ديئن ويرگار",
-       "vector-view-view": "حنن",
-       "vector-view-viewsource": "سرچشمه نه بوينيت"
-}
diff --git a/skins/Vector/i18n/lt.json b/skins/Vector/i18n/lt.json
deleted file mode 100644 (file)
index 40886a8..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Garas",
-                       "Homo",
-                       "Matasg",
-                       "Perkunas"
-               ]
-       },
-       "skinname-vector": "Vektorinė",
-       "vector-action-addsection": "Pridėti temą",
-       "vector-action-delete": "Ištrinti",
-       "vector-action-move": "Pervardyti",
-       "vector-action-protect": "Užrakinti",
-       "vector-action-undelete": "Atkurti",
-       "vector-action-unprotect": "Keisti apsaugą",
-       "vector-view-create": "Kurti",
-       "vector-view-edit": "Redaguoti",
-       "vector-view-history": "Istorija",
-       "vector-view-view": "Skaityti",
-       "vector-view-viewsource": "Žiūrėti kodą"
-}
diff --git a/skins/Vector/i18n/ltg.json b/skins/Vector/i18n/ltg.json
deleted file mode 100644 (file)
index d89d6df..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Dark Eagle"
-               ]
-       },
-       "vector-action-addsection": "Dalikt padaļu",
-       "vector-action-delete": "Iztreit",
-       "vector-action-move": "Puorceļt",
-       "vector-action-protect": "Apsorguot",
-       "vector-action-unprotect": "Puormeit apsardzeibu",
-       "vector-view-edit": "Pataiseit",
-       "vector-view-history": "Viesture",
-       "vector-view-view": "Vērtīs"
-}
diff --git a/skins/Vector/i18n/lus.json b/skins/Vector/i18n/lus.json
deleted file mode 100644 (file)
index 4f270de..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "RMizo"
-               ]
-       },
-       "vector-action-addsection": "Thupui belhna",
-       "vector-action-delete": "Paihna",
-       "vector-action-move": "Sawnna",
-       "vector-action-protect": "Venhimna",
-       "vector-action-undelete": "Lak kir lehna",
-       "vector-action-unprotect": "Venhimna dinhmun tidanglam rawh",
-       "vector-view-create": "Siamna",
-       "vector-view-edit": "Siamţhatna",
-       "vector-view-history": "Hunhlui-chanchin",
-       "vector-view-view": "Chhiarna",
-       "vector-view-viewsource": "A hnar enna"
-}
diff --git a/skins/Vector/i18n/luz.json b/skins/Vector/i18n/luz.json
deleted file mode 100644 (file)
index 0670bfd..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "علی ساکی لرستانی"
-               ]
-       },
-       "vector-view-history": "دیئن تاریخچه",
-       "vector-view-view": "هوندن"
-}
diff --git a/skins/Vector/i18n/lv.json b/skins/Vector/i18n/lv.json
deleted file mode 100644 (file)
index 697d1eb..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Marozols",
-                       "Papuass"
-               ]
-       },
-       "vector-action-addsection": "Jauna sadaļa",
-       "vector-action-delete": "Dzēst",
-       "vector-action-move": "Pārvietot",
-       "vector-action-protect": "Aizsargāt",
-       "vector-action-undelete": "Atjaunot",
-       "vector-action-unprotect": "Mainīt aizsardzību",
-       "vector-view-create": "Izveidot",
-       "vector-view-edit": "Labot",
-       "vector-view-history": "Hronoloģija",
-       "vector-view-view": "Skatīt",
-       "vector-view-viewsource": "Aplūkot kodu"
-}
diff --git a/skins/Vector/i18n/lzh.json b/skins/Vector/i18n/lzh.json
deleted file mode 100644 (file)
index 6b6ae38..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Justincheng12345"
-               ]
-       },
-       "skinname-vector": "動力",
-       "vector.css": "/* 此之 CSS 用於動力面之簿也 */",
-       "vector.js": "/* 此之JavaScript將載於用動力面之簿 */",
-       "vector-action-addsection": "入題",
-       "vector-action-delete": "刪",
-       "vector-action-move": "遷",
-       "vector-action-protect": "緘",
-       "vector-action-undelete": "覽刪",
-       "vector-action-unprotect": "啟",
-       "vector-view-create": "立",
-       "vector-view-edit": "纂",
-       "vector-view-history": "覽史",
-       "vector-view-view": "閱",
-       "vector-view-viewsource": "覽源"
-}
diff --git a/skins/Vector/i18n/lzz.json b/skins/Vector/i18n/lzz.json
deleted file mode 100644 (file)
index 3563816..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Bombola",
-                       "Ceas08",
-                       "Erdemaslancan"
-               ]
-       },
-       "vector-action-delete": "Jili",
-       "vector-action-move": "Tori",
-       "vector-action-protect": "İçvi",
-       "vector-view-create": "dokʼidi",
-       "vector-view-edit": "Doktiri",
-       "vector-view-view": "İǩitxi"
-}
diff --git a/skins/Vector/i18n/mai.json b/skins/Vector/i18n/mai.json
deleted file mode 100644 (file)
index 068e67d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ggajendra",
-                       "Umeshberma"
-               ]
-       },
-       "skinname-vector": "सदिश",
-       "vector-action-addsection": "विचार-बिन्दु जोड़ू",
-       "vector-action-delete": "मेटाउ",
-       "vector-action-move": "घसकाउ",
-       "vector-action-protect": "रक्षण करू",
-       "vector-action-undelete": "आपस लाउ",
-       "vector-action-unprotect": "सुरक्षा बदलू",
-       "vector-view-create": "बनाउ",
-       "vector-view-edit": "सम्पादन करू",
-       "vector-view-history": "इतिहास देखू",
-       "vector-view-view": "पढ़ू",
-       "vector-view-viewsource": "जड़ि देखू"
-}
diff --git a/skins/Vector/i18n/map-bms.json b/skins/Vector/i18n/map-bms.json
deleted file mode 100644 (file)
index 1a08582..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "StefanusRA"
-               ]
-       },
-       "vector-action-addsection": "Nambah topik",
-       "vector-action-delete": "Busek",
-       "vector-action-move": "Pindah",
-       "vector-action-protect": "Reksa",
-       "vector-action-undelete": "Batalna pambusakan",
-       "vector-action-unprotect": "Owahi pangreksan",
-       "vector-view-create": "Gawe",
-       "vector-view-edit": "Sunting",
-       "vector-view-history": "Sajarah kaca",
-       "vector-view-view": "Waca",
-       "vector-view-viewsource": "Deleng sumbere"
-}
diff --git a/skins/Vector/i18n/mdf.json b/skins/Vector/i18n/mdf.json
deleted file mode 100644 (file)
index 91787fc..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Numulunj pilgae"
-               ]
-       },
-       "vector-action-addsection": "Поладомс мезень колга корхтамс",
-       "vector-action-delete": "Нардамс",
-       "vector-action-move": "Шашфтомс",
-       "vector-action-protect": "Араламс",
-       "vector-action-undelete": "Мърдафтомс",
-       "vector-action-unprotect": "Араламать полафтомс",
-       "vector-view-create": "Тиемс",
-       "vector-view-edit": "Петнемс",
-       "vector-view-history": "История няфтемс",
-       "vector-view-view": "Морафтомс",
-       "vector-view-viewsource": "Лисьма няфтемс"
-}
diff --git a/skins/Vector/i18n/mg.json b/skins/Vector/i18n/mg.json
deleted file mode 100644 (file)
index 5c51602..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Jagwar"
-               ]
-       },
-       "vector-action-addsection": "Hanampy lohahevitra",
-       "vector-action-delete": "Fafana",
-       "vector-action-move": "Hanolo anarana",
-       "vector-action-protect": "Arovy",
-       "vector-action-undelete": "Avereno",
-       "vector-action-unprotect": "Hanala ny fiarovana",
-       "vector-view-create": "Foronona",
-       "vector-view-edit": "Hanova",
-       "vector-view-history": "Hijery ny tantara",
-       "vector-view-view": "Hamaky",
-       "vector-view-viewsource": "Hijery fango"
-}
diff --git a/skins/Vector/i18n/mhr.json b/skins/Vector/i18n/mhr.json
deleted file mode 100644 (file)
index efe9d4b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Azim",
-                       "Sergey Ivanov",
-                       "Сай",
-                       "Санюн Вадик"
-               ]
-       },
-       "vector-action-addsection": "У ӱжашым тӱҥалаш",
-       "vector-action-delete": "Шӧраш",
-       "vector-action-move": "Лӱмым вашталташ",
-       "vector-action-protect": "Тӧрлатымаш деч аралаш",
-       "vector-action-undelete": "Шӧрымым пӧртылаш",
-       "vector-action-unprotect": "Оролым вашталташ",
-       "vector-view-create": "Ышташ",
-       "vector-view-edit": "Тӧрлаташ",
-       "vector-view-history": "Эртымгорным ончалаш",
-       "vector-view-view": "Лудаш",
-       "vector-view-viewsource": "Тӱҥалтыш текстым ончалаш"
-}
diff --git a/skins/Vector/i18n/mi.json b/skins/Vector/i18n/mi.json
deleted file mode 100644 (file)
index 0a59489..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Piwaiwaka"
-               ]
-       },
-       "vector-view-view": "Tirohia"
-}
diff --git a/skins/Vector/i18n/mic.json b/skins/Vector/i18n/mic.json
deleted file mode 100644 (file)
index 3079089..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Amqui"
-               ]
-       },
-       "vector-action-move": "Ejigliwsit",
-       "vector-view-create": "Etlitoq",
-       "vector-view-view": "Egiljet"
-}
diff --git a/skins/Vector/i18n/min.json b/skins/Vector/i18n/min.json
deleted file mode 100644 (file)
index bf5a735..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Iwan Novirion",
-                       "Luthfi94",
-                       "VoteITP"
-               ]
-       },
-       "skinname-vector": "Vektor",
-       "vector-action-addsection": "Bagian baru",
-       "vector-action-delete": "Hapuih",
-       "vector-action-move": "Pindahkan",
-       "vector-action-protect": "Linduangkan",
-       "vector-action-undelete": "Pambatalan pangapuihan",
-       "vector-action-unprotect": "Tuka palinduangan",
-       "vector-view-create": "Buek",
-       "vector-view-edit": "Suntiang",
-       "vector-view-history": "Riwayaik",
-       "vector-view-view": "Baco",
-       "vector-view-viewsource": "Caliak sumber"
-}
diff --git a/skins/Vector/i18n/mk.json b/skins/Vector/i18n/mk.json
deleted file mode 100644 (file)
index 1f883ae..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Bjankuloski06",
-                       "Brest"
-               ]
-       },
-       "skinname-vector": "Векторско",
-       "vector-skin-desc": "Современа верзија на рувото МоноБук со свеж изглед и многу подобрувања на употребливоста",
-       "vector.css": "/* Тука поставениот CSS се однесува на корисниците на рувото „Векторско“ */",
-       "vector.js": "/* Тука поставениот JavaScript  ќе им се вчитува на корисниците што го користат рувото „Векторско“ */",
-       "vector-action-addsection": "Додај тема",
-       "vector-action-delete": "Избриши",
-       "vector-action-move": "Премести",
-       "vector-action-protect": "Заштити",
-       "vector-action-undelete": "Врати",
-       "vector-action-unprotect": "Измени заштита",
-       "vector-view-create": "Создај",
-       "vector-view-edit": "Уреди",
-       "vector-view-history": "Историја",
-       "vector-view-view": "Читај",
-       "vector-view-viewsource": "Извор",
-       "vector-more-actions": "Повеќе"
-}
diff --git a/skins/Vector/i18n/ml.json b/skins/Vector/i18n/ml.json
deleted file mode 100644 (file)
index 6ca34a1..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Anoopan",
-                       "Praveenp"
-               ]
-       },
-       "skinname-vector": "വെക്റ്റർ",
-       "vector.css": "/* ഇവിടെ നൽകുന്ന സി.എസ്.എസ്. വെക്റ്റർ ദൃശ്യരൂപത്തിനു ബാധകമായിരിക്കും*/",
-       "vector.js": "/*ഇവിടെ നൽകുന്ന ജാവാസ്ക്രിപ്റ്റ് വെക്റ്റർ ദൃശ്യരൂപം ഉപയോഗിക്കുന്ന ഉപയോക്താക്കൾക്ക് ബാധകമായിരിക്കും*/",
-       "vector-action-addsection": "വിഷയം ചേർക്കുക",
-       "vector-action-delete": "മായ്ക്കുക",
-       "vector-action-move": "തലക്കെട്ട് മാറ്റുക",
-       "vector-action-protect": "സം‌രക്ഷിക്കുക",
-       "vector-action-undelete": "മായ്ക്കപ്പെട്ടത് പുനഃസ്ഥാപിക്കുക",
-       "vector-action-unprotect": "സംരക്ഷണത്തിൽ മാറ്റംവരുത്തുക",
-       "vector-view-create": "സൃഷ്ടിക്കുക",
-       "vector-view-edit": "തിരുത്തുക",
-       "vector-view-history": "നാൾവഴി കാണുക",
-       "vector-view-view": "വായിക്കുക",
-       "vector-view-viewsource": "മൂലരൂപം കാണുക",
-       "vector-more-actions": "കൂടുതൽ"
-}
diff --git a/skins/Vector/i18n/mn.json b/skins/Vector/i18n/mn.json
deleted file mode 100644 (file)
index ceeafaf..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Chinneeb",
-                       "MongolWiki",
-                       "Wisdom"
-               ]
-       },
-       "vector-action-addsection": "Сэдэв нэмэх",
-       "vector-action-delete": "Устгах",
-       "vector-action-move": "Зөөх",
-       "vector-action-protect": "Хамгаалах",
-       "vector-action-undelete": "Үл устгах",
-       "vector-action-unprotect": "Хамгаалалтаа солих",
-       "vector-view-create": "Үүсгэх",
-       "vector-view-edit": "Засварлах",
-       "vector-view-history": "Түүх",
-       "vector-view-view": "Унших",
-       "vector-view-viewsource": "Кодыг харах"
-}
diff --git a/skins/Vector/i18n/mnc.json b/skins/Vector/i18n/mnc.json
deleted file mode 100644 (file)
index 60434d5..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Minggantu"
-               ]
-       },
-       "vector-action-delete": "Dabgire",
-       "vector-action-move": "Guribure",
-       "vector-action-protect": "Karmara",
-       "vector-view-create": "Ilibure",
-       "vector-view-edit": "banjibume arara",
-       "vector-view-history": "ere šu wen i suduri be baicara",
-       "vector-view-view": "hūlara",
-       "vector-view-viewsource": "da šu wen be baicara"
-}
diff --git a/skins/Vector/i18n/mr.json b/skins/Vector/i18n/mr.json
deleted file mode 100644 (file)
index ab7e322..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kaajawa",
-                       "V.narsikar"
-               ]
-       },
-       "skinname-vector": "सदिश",
-       "vector-action-addsection": "विषय जोडा",
-       "vector-action-delete": "वगळा",
-       "vector-action-move": "स्थानांतरण",
-       "vector-action-protect": "सुरक्षित करा",
-       "vector-action-undelete": "वगळलेले पुनर्स्थापित करा",
-       "vector-action-unprotect": "सुरक्षितता बदला",
-       "vector-view-create": "तयार करा",
-       "vector-view-edit": "संपादन",
-       "vector-view-history": "इतिहास पहा",
-       "vector-view-view": "वाचा",
-       "vector-view-viewsource": "स्रोत पहा",
-       "vector-more-actions": "अधिक"
-}
diff --git a/skins/Vector/i18n/mrj.json b/skins/Vector/i18n/mrj.json
deleted file mode 100644 (file)
index 72b93b4..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Amdf"
-               ]
-       },
-       "vector-action-delete": "Карангдаш",
-       "vector-action-move": "Лӹмӹм вашталташ",
-       "vector-action-protect": "Ӹшӹклӓш",
-       "vector-view-create": "Ӹштӓш",
-       "vector-view-edit": "Тӧрлӹмӓш",
-       "vector-view-history": "Историм анжымаш",
-       "vector-view-view": "Лыдмаш",
-       "vector-view-viewsource": "Сек пӹтӓриш кодым анжалаш"
-}
diff --git a/skins/Vector/i18n/ms.json b/skins/Vector/i18n/ms.json
deleted file mode 100644 (file)
index 2795e44..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Anakmalaysia",
-                       "Aurora",
-                       "Pizza1016"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector.css": "/* CSS yang terletak di sini akan mempengaruhi pengguna kulit Vector */",
-       "vector-action-addsection": "Buka topik",
-       "vector-action-delete": "Hapus",
-       "vector-action-move": "Pindah",
-       "vector-action-protect": "Lindung",
-       "vector-action-undelete": "Nyahhapus",
-       "vector-action-unprotect": "Ubah perlindungan",
-       "vector-view-create": "Cipta",
-       "vector-view-edit": "Sunting",
-       "vector-view-history": "Lihat sejarah",
-       "vector-view-view": "Baca",
-       "vector-view-viewsource": "Lihat sumber"
-}
diff --git a/skins/Vector/i18n/mt.json b/skins/Vector/i18n/mt.json
deleted file mode 100644 (file)
index 32c9f1a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Chrisportelli"
-               ]
-       },
-       "vector-action-addsection": "Żid diskussjoni",
-       "vector-action-delete": "Ħassar",
-       "vector-action-move": "Mexxi",
-       "vector-action-protect": "Ipproteġi",
-       "vector-action-undelete": "Irkupra",
-       "vector-action-unprotect": "Biddel il-protezzjoni",
-       "vector-view-create": "Oħloq",
-       "vector-view-edit": "Editja",
-       "vector-view-history": "Ara l-kronoloġija",
-       "vector-view-view": "Aqra",
-       "vector-view-viewsource": "Ara s-sors"
-}
diff --git a/skins/Vector/i18n/mui.json b/skins/Vector/i18n/mui.json
deleted file mode 100644 (file)
index 173eda0..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mahali syarifuddin"
-               ]
-       },
-       "vector-view-view": "Baco",
-       "vector-view-viewsource": "Jingok sumber"
-}
diff --git a/skins/Vector/i18n/my.json b/skins/Vector/i18n/my.json
deleted file mode 100644 (file)
index 5cc7802..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Lionslayer",
-                       "Myanmars"
-               ]
-       },
-       "vector-action-addsection": "အကြောင်းအရာအသစ် ထပ်ထည့်ရန်",
-       "vector-action-delete": "ဖျက်​ပါ​",
-       "vector-action-move": "ရွှေ့ပါ",
-       "vector-action-protect": "ထိမ်း​သိမ်း​ပါ​",
-       "vector-action-undelete": "မဖျက်တော့ရန်",
-       "vector-action-unprotect": "ကာကွယ်ခြင်းကို ပြောင်းလဲရန်",
-       "vector-view-create": "စတင်ရေးသားရန်",
-       "vector-view-edit": "ပြင်ရန်",
-       "vector-view-history": "ရာဇဝင်ကြည့်ရန်",
-       "vector-view-view": "ဖတ်ရန်",
-       "vector-view-viewsource": "ရင်းမြစ်ကို ကြည့်ရန်"
-}
diff --git a/skins/Vector/i18n/myv.json b/skins/Vector/i18n/myv.json
deleted file mode 100644 (file)
index 723d5dd..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Botuzhaleny-sodamo"
-               ]
-       },
-       "vector-action-addsection": "Поладомс мезде кортамс",
-       "vector-action-delete": "Нардамс",
-       "vector-action-move": "Печтевтемс",
-       "vector-action-protect": "Аравтомс ванстомас",
-       "vector-action-undelete": "Вельмевтемс нардазенть",
-       "vector-action-unprotect": "Полавтомс ванстоманзо",
-       "vector-view-create": "Теемс-Шкамс",
-       "vector-view-edit": "Витнемс-петнемс",
-       "vector-view-history": "Ваномс юронзо-путовксонзо",
-       "vector-view-view": "Ловномс",
-       "vector-view-viewsource": "Ваномс косто саезь"
-}
diff --git a/skins/Vector/i18n/mzn.json b/skins/Vector/i18n/mzn.json
deleted file mode 100644 (file)
index cf18634..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mjbmr",
-                       "محک"
-               ]
-       },
-       "vector-action-addsection": "ترنه گپ بزوئن",
-       "vector-action-delete": "پاک هاکردن",
-       "vector-action-move": "دکش هاکردن",
-       "vector-action-protect": "زلفن بزوئن",
-       "vector-action-undelete": "دباره بنویشته بیّن",
-       "vector-action-unprotect": "زلفن عوض هاکردن",
-       "vector-view-create": "بساتن",
-       "vector-view-edit": "دچی‌ین",
-       "vector-view-history": "تاریخچه ره بَدی‌ین",
-       "vector-view-view": "بخوندستن",
-       "vector-view-viewsource": "ونه منبع ره هارشائن"
-}
diff --git a/skins/Vector/i18n/nah.json b/skins/Vector/i18n/nah.json
deleted file mode 100644 (file)
index adf8c21..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ricardo gs"
-               ]
-       },
-       "vector-action-delete": "Ticpolōz",
-       "vector-action-move": "Ticzacāz",
-       "vector-action-protect": "Ticquīxtīz",
-       "vector-view-create": "Ticchīhuāz",
-       "vector-view-edit": "Ticpatlāz",
-       "vector-view-history": "Tlahcuilōlli tlahcuilōlloh",
-       "vector-view-view": "Tāmapōhuaz",
-       "vector-view-viewsource": "Tiquittāz in mēyalli"
-}
diff --git a/skins/Vector/i18n/nan.json b/skins/Vector/i18n/nan.json
deleted file mode 100644 (file)
index f1b9045..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ianbu"
-               ]
-       },
-       "vector-action-addsection": "Ke chi̍t-ê toān-lo̍h",
-       "vector-action-delete": "Thâi",
-       "vector-action-move": "Sóa khì",
-       "vector-action-protect": "Pó-hō·",
-       "vector-action-undelete": "chhú-siau thâi tiàu",
-       "vector-action-unprotect": "kái pó-hō·",
-       "vector-view-create": "Khai-sí siá",
-       "vector-view-edit": "Siu-kái",
-       "vector-view-history": "khoàⁿ le̍k-sú",
-       "vector-view-view": "Tha̍k",
-       "vector-view-viewsource": "Khoàⁿ goân-sú lōe-iông",
-       "vector-more-actions": "閣看"
-}
diff --git a/skins/Vector/i18n/nap.json b/skins/Vector/i18n/nap.json
deleted file mode 100644 (file)
index 862f197..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Chelin"
-               ]
-       },
-       "vector-action-addsection": "Aggiunge chiacchierata",
-       "vector-action-delete": "Scancèlla",
-       "vector-action-move": "Spusta",
-       "vector-action-protect": "Prutegge",
-       "vector-action-undelete": "Ripristina",
-       "vector-action-unprotect": "Càgna prutezzione",
-       "vector-view-create": "Cria",
-       "vector-view-edit": "Càgna",
-       "vector-view-history": "Vere cronologgia",
-       "vector-view-view": "Legge",
-       "vector-view-viewsource": "Vere sorgente"
-}
diff --git a/skins/Vector/i18n/nb.json b/skins/Vector/i18n/nb.json
deleted file mode 100644 (file)
index bae61b5..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Danmichaelo",
-                       "Event",
-                       "Nghtwlkr"
-               ]
-       },
-       "vector-action-addsection": "Nytt emne",
-       "vector-action-delete": "Slett",
-       "vector-action-move": "Flytt",
-       "vector-action-protect": "Beskytt",
-       "vector-action-undelete": "Gjenopprett",
-       "vector-action-unprotect": "Endre beskyttelse",
-       "vector-view-create": "Opprett",
-       "vector-view-edit": "Rediger",
-       "vector-view-history": "Vis historikk",
-       "vector-view-view": "Les",
-       "vector-view-viewsource": "Vis kilden",
-       "vector-more-actions": "Mer"
-}
diff --git a/skins/Vector/i18n/nds-nl.json b/skins/Vector/i18n/nds-nl.json
deleted file mode 100644 (file)
index be846db..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Servien"
-               ]
-       },
-       "vector-action-addsection": "Niej onderwarp",
-       "vector-action-delete": "Vortdoon",
-       "vector-action-move": "Herneumen",
-       "vector-action-protect": "Beveiligen",
-       "vector-action-undelete": "Weerummeplaotsen",
-       "vector-action-unprotect": "Beveiliging wiezigen",
-       "vector-view-create": "Anmaken",
-       "vector-view-edit": "Bewarken",
-       "vector-view-history": "Geschiedenisse bekieken",
-       "vector-view-view": "Lezen",
-       "vector-view-viewsource": "Brontekste bekieken",
-       "vector-more-actions": "Meer"
-}
diff --git a/skins/Vector/i18n/nds.json b/skins/Vector/i18n/nds.json
deleted file mode 100644 (file)
index 99145b0..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Slomox",
-                       "Zylbath"
-               ]
-       },
-       "vector-action-addsection": "Thema tofögen",
-       "vector-action-delete": "Wegdoon",
-       "vector-action-move": "Schuven",
-       "vector-action-protect": "Schulen",
-       "vector-action-undelete": "Wedderhalen",
-       "vector-action-unprotect": "Siedenschuul ännern",
-       "vector-view-create": "Opstellen",
-       "vector-view-edit": "Ännern",
-       "vector-view-history": "Historie bekieken",
-       "vector-view-view": "Lesen",
-       "vector-view-viewsource": "Borntext bekieken"
-}
diff --git a/skins/Vector/i18n/ne.json b/skins/Vector/i18n/ne.json
deleted file mode 100644 (file)
index 443becb..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Bhawani Gautam",
-                       "RajeshPandey",
-                       "सरोज कुमार ढकाल"
-               ]
-       },
-       "skinname-vector": "भेक्टर",
-       "vector.css": "/* यहाँ राखिएको CSS ले भेक्टर स्किनको प्रयोगकर्ताहरुलाई प्रभावित गर्ने छ  */",
-       "vector-action-addsection": "विषय थप्नुहोस",
-       "vector-action-delete": "हटाउने",
-       "vector-action-move": "सार्ने",
-       "vector-action-protect": "सुरक्षित गर्ने",
-       "vector-action-undelete": "हटाएको रद्द गर्ने",
-       "vector-action-unprotect": "सुरक्षा परिवर्तन गर्ने",
-       "vector-view-create": "सृजना गर्ने",
-       "vector-view-edit": "सम्पादन",
-       "vector-view-history": "इतिहास हेर्ने",
-       "vector-view-view": "पढ्ने",
-       "vector-view-viewsource": "स्रोत हेर्ने"
-}
diff --git a/skins/Vector/i18n/new.json b/skins/Vector/i18n/new.json
deleted file mode 100644 (file)
index f972066..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Eukesh"
-               ]
-       },
-       "vector-action-move": "संकादिसँ",
-       "vector-view-create": "दयेकादिसँ",
-       "vector-view-edit": "सम्पादन",
-       "vector-view-history": "इतिहास स्वयादिसँ",
-       "vector-view-view": "ब्वनादिसँ"
-}
diff --git a/skins/Vector/i18n/nl.json b/skins/Vector/i18n/nl.json
deleted file mode 100644 (file)
index 07c18d9..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Calak",
-                       "Romaine",
-                       "SPQRobin",
-                       "Siebrand",
-                       "Troefkaart",
-                       "Sjoerddebruin"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector-skin-desc": "Moderne versie van MonoBook met een fris uiterlijk en verbeteringen op het gebied van gebruiksvriendelijkheid",
-       "vector.css": "/* CSS die hier wordt geplaatst heeft alleen invloed op de skin Vector */",
-       "vector.js": "/* JavaScript die hier wordt geplaatst heeft alleen invloed op gebruikers die de skin Vector gebruiken */",
-       "vector-action-addsection": "Kopje toevoegen",
-       "vector-action-delete": "Verwijderen",
-       "vector-action-move": "Hernoemen",
-       "vector-action-protect": "Beveiligen",
-       "vector-action-undelete": "Terugplaatsen",
-       "vector-action-unprotect": "Beveiliging wijzigen",
-       "vector-view-create": "Aanmaken",
-       "vector-view-edit": "Bewerken",
-       "vector-view-history": "Geschiedenis weergeven",
-       "vector-view-view": "Lezen",
-       "vector-view-viewsource": "Brontekst bekijken",
-       "vector-more-actions": "Meer"
-}
diff --git a/skins/Vector/i18n/nn.json b/skins/Vector/i18n/nn.json
deleted file mode 100644 (file)
index 6fd99f1..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Gunnernett",
-                       "Njardarlogar"
-               ]
-       },
-       "vector-action-addsection": "Nytt emne",
-       "vector-action-delete": "Slett",
-       "vector-action-move": "Flytt",
-       "vector-action-protect": "Vern",
-       "vector-action-undelete": "Gjenopprett",
-       "vector-action-unprotect": "Endra vern",
-       "vector-view-create": "Opprett",
-       "vector-view-edit": "Endre",
-       "vector-view-history": "Sjå historikken",
-       "vector-view-view": "Les",
-       "vector-view-viewsource": "Sjå kjelda",
-       "vector-more-actions": "Meir"
-}
diff --git a/skins/Vector/i18n/nov.json b/skins/Vector/i18n/nov.json
deleted file mode 100644 (file)
index 66ad923..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Malafaya"
-               ]
-       },
-       "vector-action-delete": "Ekarta",
-       "vector-view-edit": "Modifika",
-       "vector-view-view": "Lekte"
-}
diff --git a/skins/Vector/i18n/nrm.json b/skins/Vector/i18n/nrm.json
deleted file mode 100644 (file)
index 4c332f2..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "WikiEoFrEn"
-               ]
-       },
-       "vector-view-create": "Criyaer",
-       "vector-view-edit": "Amendaer",
-       "vector-view-view": "Luure"
-}
diff --git a/skins/Vector/i18n/nso.json b/skins/Vector/i18n/nso.json
deleted file mode 100644 (file)
index ea729e7..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mohau"
-               ]
-       },
-       "vector-action-addsection": "Lokela sererwa",
-       "vector-action-delete": "Phumula",
-       "vector-action-move": "Huduša",
-       "vector-action-protect": "Lota",
-       "vector-view-create": "Hlola",
-       "vector-view-edit": "Fetola",
-       "vector-view-history": "Laetša histori",
-       "vector-view-view": "Bala",
-       "vector-view-viewsource": "Lebelela mothopo"
-}
diff --git a/skins/Vector/i18n/oc.json b/skins/Vector/i18n/oc.json
deleted file mode 100644 (file)
index 2aa517e..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Boulaur",
-                       "Cedric31"
-               ]
-       },
-       "vector.css": "/* Lo CSS plaçat aicí afectarà los utilizaires de l’abilhatge Vector */",
-       "vector.js": "/* Tot JavaScript aicí serà cargat amb las paginas accedidas pels utilizaires de l’abilhatge Vector unicament. */",
-       "vector-action-addsection": "Apondre un subjècte",
-       "vector-action-delete": "Suprimir",
-       "vector-action-move": "Tornar nomenar",
-       "vector-action-protect": "Protegir",
-       "vector-action-undelete": "Restablir",
-       "vector-action-unprotect": "Suprimir la proteccion",
-       "vector-view-create": "Crear",
-       "vector-view-edit": "Modificar",
-       "vector-view-history": "Veire l'istoric",
-       "vector-view-view": "Legir",
-       "vector-view-viewsource": "Veire la font"
-}
diff --git a/skins/Vector/i18n/or.json b/skins/Vector/i18n/or.json
deleted file mode 100644 (file)
index 289cc3c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Jnanaranjan Sahu",
-                       "Psubhashish"
-               ]
-       },
-       "vector-action-addsection": "ନୂଆ ଯୋଡ଼ନ୍ତୁ",
-       "vector-action-delete": "ଲିଭାଇବେ",
-       "vector-action-move": "ଘୁଞ୍ଚାଇବେ",
-       "vector-action-protect": "କିଳିବେ",
-       "vector-action-undelete": "ଲିଭାଇବେ ନାହିଁ",
-       "vector-action-unprotect": "କିଳିବେ ନାହିଁ",
-       "vector-view-create": "ତିଆରି କରନ୍ତୁ",
-       "vector-view-edit": "ସମ୍ପାଦନା (Edit)",
-       "vector-view-history": "ଇତିହାସ",
-       "vector-view-view": "ପଢ଼ନ୍ତୁ",
-       "vector-view-viewsource": "ସୋର୍ସ ଦେଖନ୍ତୁ"
-}
diff --git a/skins/Vector/i18n/os.json b/skins/Vector/i18n/os.json
deleted file mode 100644 (file)
index a178289..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Amikeco",
-                       "Bouron"
-               ]
-       },
-       "vector-action-addsection": "Нæуæг ныхас бакæнын",
-       "vector-action-delete": "Схафын",
-       "vector-action-move": "Ном ивын",
-       "vector-action-protect": "Сæхгæнын",
-       "vector-action-undelete": "Рацаразын",
-       "vector-action-unprotect": "Ивын хъахъхъæд",
-       "vector-view-create": "Скæнын",
-       "vector-view-edit": "Ивын",
-       "vector-view-history": "Истори",
-       "vector-view-view": "Кæсын",
-       "vector-view-viewsource": "Код кæсын"
-}
diff --git a/skins/Vector/i18n/pa.json b/skins/Vector/i18n/pa.json
deleted file mode 100644 (file)
index 5f15399..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Aalam",
-                       "Babanwalia",
-                       "Raj Singh",
-                       "TariButtar"
-               ]
-       },
-       "vector-action-addsection": "ਵਿਸ਼ਾ ਜੋੜੋ",
-       "vector-action-delete": "ਹਟਾਓ",
-       "vector-action-move": "ਭੇਜੋ",
-       "vector-action-protect": "ਸੁਰੱਖਿਆ",
-       "vector-action-undelete": "ਹਟਾਉਣਾ-ਵਾਪਸ",
-       "vector-action-unprotect": "ਸੁਰੱਖਿਆ ਬਦਲੋ",
-       "vector-view-create": "ਬਣਾਓ",
-       "vector-view-edit": "ਸੋਧੋ",
-       "vector-view-history": "ਅਤੀਤ ਵੇਖੋ",
-       "vector-view-view": "ਪੜ੍ਹੋ",
-       "vector-view-viewsource": "ਸਰੋਤ ਵੇਖੋ"
-}
diff --git a/skins/Vector/i18n/pam.json b/skins/Vector/i18n/pam.json
deleted file mode 100644 (file)
index 09afda5..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Katimawan2005",
-                       "Val2397"
-               ]
-       },
-       "vector-action-addsection": "Dagdagan ing pisasabian",
-       "vector-action-delete": "Buran",
-       "vector-action-move": "Iyalis",
-       "vector-action-protect": "Protectan/kambilan",
-       "vector-action-undelete": "Isubli/iurung ya pangabura",
-       "vector-action-unprotect": "Idayu ya panga-protecta",
-       "vector-view-create": "Maglalang",
-       "vector-view-edit": "Alilan",
-       "vector-view-history": "Lawen ya ing amlat",
-       "vector-view-view": "Basan",
-       "vector-view-viewsource": "Lawen ya ing pikuanan"
-}
diff --git a/skins/Vector/i18n/pbb.json b/skins/Vector/i18n/pbb.json
deleted file mode 100644 (file)
index 9ddeada..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Sahaquiel9102"
-               ]
-       },
-       "vector-action-delete": "Cjũcj",
-       "vector-action-move": "Quẽese'j",
-       "vector-action-protect": "Pjupj",
-       "vector-view-edit": "Yu'ptjej",
-       "vector-view-view": "Lẽeĩ"
-}
diff --git a/skins/Vector/i18n/pcd.json b/skins/Vector/i18n/pcd.json
deleted file mode 100644 (file)
index 57af67e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Geoleplubo"
-               ]
-       },
-       "vector-action-addsection": "Rajouter un sujeut",
-       "vector-action-delete": "Défacer",
-       "vector-action-move": "Canger ch'nom",
-       "vector-action-protect": "Garantir",
-       "vector-action-undelete": "N'poin défacher",
-       "vector-action-unprotect": "Canger l'garantie",
-       "vector-view-create": "Créer",
-       "vector-view-edit": "Éditer",
-       "vector-view-history": "Vir l'histoère",
-       "vector-view-view": "Lire",
-       "vector-view-viewsource": "Vir l'source"
-}
diff --git a/skins/Vector/i18n/pdc.json b/skins/Vector/i18n/pdc.json
deleted file mode 100644 (file)
index a3903b2..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Xqt"
-               ]
-       },
-       "vector-action-delete": "Verwische",
-       "vector-action-move": "Ziehe",
-       "vector-action-protect": "Schitze",
-       "vector-view-create": "Schtaerte",
-       "vector-view-edit": "Ennere",
-       "vector-view-history": "Gschicht zeige",
-       "vector-view-view": "Lese"
-}
diff --git a/skins/Vector/i18n/pfl.json b/skins/Vector/i18n/pfl.json
deleted file mode 100644 (file)
index 419eb4e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Manuae"
-               ]
-       },
-       "vector-action-addsection": "Abschnidd dzufiesche",
-       "vector-action-delete": "Lesche",
-       "vector-action-move": "Vaschiewe",
-       "vector-action-protect": "Schidze",
-       "vector-action-undelete": "Zriggbringe",
-       "vector-view-create": "Õleesche",
-       "vector-view-edit": "Drõ schaffe",
-       "vector-view-history": "Dadaigschischd",
-       "vector-view-view": "Lese",
-       "vector-view-viewsource": "Gwelltegschd zaische"
-}
diff --git a/skins/Vector/i18n/pi.json b/skins/Vector/i18n/pi.json
deleted file mode 100644 (file)
index cc57f67..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Hemant wikikosh1"
-               ]
-       },
-       "vector-view-create": "रचेतु"
-}
diff --git a/skins/Vector/i18n/pih.json b/skins/Vector/i18n/pih.json
deleted file mode 100644 (file)
index 81fb2fc..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "AmaryllisGardener"
-               ]
-       },
-       "vector-view-history": "View histrei"
-}
diff --git a/skins/Vector/i18n/pl.json b/skins/Vector/i18n/pl.json
deleted file mode 100644 (file)
index 5cf2082..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Matma Rex",
-                       "Sp5uhe"
-               ]
-       },
-       "skinname-vector": "Wektor",
-       "vector-skin-desc": "Odświeżona wersja skórki Książka, z nowym wyglądem i usprawnieniami",
-       "vector.css": "/* Umieszczony tutaj kod CSS wpłynie na wygląd skórki Wektor */",
-       "vector.js": "/* Umieszczony tutaj kod JavaScript zostanie załadowany wyłącznie przez użytkowników korzystających ze skórki Wektor */",
-       "vector-action-addsection": "Dodaj temat",
-       "vector-action-delete": "Usuń",
-       "vector-action-move": "Przenieś",
-       "vector-action-protect": "Zabezpiecz",
-       "vector-action-undelete": "Odtwórz",
-       "vector-action-unprotect": "Zmień zabezpieczenie",
-       "vector-view-create": "Utwórz",
-       "vector-view-edit": "Edytuj",
-       "vector-view-history": "Wyświetl historię",
-       "vector-view-view": "Czytaj",
-       "vector-view-viewsource": "Tekst źródłowy",
-       "vector-more-actions": "Więcej"
-}
diff --git a/skins/Vector/i18n/pms.json b/skins/Vector/i18n/pms.json
deleted file mode 100644 (file)
index 79627b0..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Borichèt"
-               ]
-       },
-       "vector-action-addsection": "Gionté n'argoment",
-       "vector-action-delete": "Scancelé",
-       "vector-action-move": "Tramudé",
-       "vector-action-protect": "Protege",
-       "vector-action-undelete": "Arcuperé",
-       "vector-action-unprotect": "Cangé la protession",
-       "vector-view-create": "Creé",
-       "vector-view-edit": "Modifiché",
-       "vector-view-history": "Smon-e la stòria",
-       "vector-view-view": "Lese",
-       "vector-view-viewsource": "Vëdde la sorgiss"
-}
diff --git a/skins/Vector/i18n/pnb.json b/skins/Vector/i18n/pnb.json
deleted file mode 100644 (file)
index 601f513..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Arslan",
-                       "Khalid Mahmood"
-               ]
-       },
-       "vector-action-addsection": "مضمون پاؤ",
-       "vector-action-delete": "مکاؤ",
-       "vector-action-move": "ٹرو",
-       "vector-action-protect": "بچاؤ",
-       "vector-action-undelete": "واپس لیاؤ",
-       "vector-action-unprotect": "تبدیلی بچاؤ",
-       "vector-view-create": "بناؤ",
-       "vector-view-edit": "لکھو",
-       "vector-view-history": "تریخ وکھاؤ",
-       "vector-view-view": "پڑھو",
-       "vector-view-viewsource": "ویکھو"
-}
diff --git a/skins/Vector/i18n/pnt.json b/skins/Vector/i18n/pnt.json
deleted file mode 100644 (file)
index 1e5ecad..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Omnipaedista",
-                       "Sinopeus",
-                       "ZaDiak"
-               ]
-       },
-       "vector-action-delete": "Σβήσον",
-       "vector-action-move": "Ετεροχλάεμαν",
-       "vector-action-protect": "Ασπάλιγμαν",
-       "vector-action-undelete": "Κλώσιμον",
-       "vector-action-unprotect": "Άνοιγμαν",
-       "vector-view-create": "Ποίσον",
-       "vector-view-edit": "Άλλαξον",
-       "vector-view-history": "Τερέστεν ιστορίαν",
-       "vector-view-view": "Δεάβασον",
-       "vector-view-viewsource": "Τερέστεν κωδικόν"
-}
diff --git a/skins/Vector/i18n/ppl.json b/skins/Vector/i18n/ppl.json
deleted file mode 100644 (file)
index 1c80fd8..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "A R King"
-               ]
-       },
-       "vector-action-addsection": "Yankwik temaj",
-       "vector-action-delete": "Shikishti",
-       "vector-action-move": "Shikijkwani",
-       "vector-action-undelete": "Shalkwepa",
-       "vector-view-create": "Shikchiwa",
-       "vector-view-edit": "Shikpata",
-       "vector-view-history": "Ken mupatak",
-       "vector-view-view": "Shiamatachia",
-       "vector-view-viewsource": "Shikita ne codigoj"
-}
diff --git a/skins/Vector/i18n/prg.json b/skins/Vector/i18n/prg.json
deleted file mode 100644 (file)
index dfd71db..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Nertiks",
-                       "Peteris"
-               ]
-       },
-       "vector-action-delete": "Āupausinais",
-       "vector-action-move": "Prapīdais",
-       "vector-action-protect": "Kūnsteis",
-       "vector-action-unprotect": "Etkūnteis",
-       "vector-view-create": "Teīkeis",
-       "vector-view-edit": "Redigīs",
-       "vector-view-history": "Enwaidinnais istōrijan",
-       "vector-view-view": "Skaitāis",
-       "vector-view-viewsource": "Enwaidinnais appun"
-}
diff --git a/skins/Vector/i18n/ps.json b/skins/Vector/i18n/ps.json
deleted file mode 100644 (file)
index 2ccb265..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ahmed-Najib-Biabani-Ibrahimkhel"
-               ]
-       },
-       "skinname-vector": "وېکټور",
-       "vector.css": "/* د CSS هره بڼه چې دلته ځای پر ځای کېږي هغه به د وېکټور د پوښ ټولو کارنانو لپاره کار کوي */",
-       "vector.js": "/* د جاوا هر يو سکرېپټ چې دلته ځای پر ځای کېږي هغه به د وېکټور د پوښ ټولو کارنانو لپاره کار کوي */",
-       "vector-action-addsection": "سرليکونه ورگډول",
-       "vector-action-delete": "ړنگول",
-       "vector-action-move": "لېږدول",
-       "vector-action-protect": "ژغورل",
-       "vector-action-undelete": "ناړنگول",
-       "vector-action-unprotect": "ژغورنه بدلول",
-       "vector-view-create": "جوړول",
-       "vector-view-edit": "سمول",
-       "vector-view-history": "پېښليک کتل",
-       "vector-view-view": "لوستل",
-       "vector-view-viewsource": "سرچينه کتل"
-}
diff --git a/skins/Vector/i18n/pt-br.json b/skins/Vector/i18n/pt-br.json
deleted file mode 100644 (file)
index db47675..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Cainamarques",
-                       "Diego Queiroz",
-                       "Giro720",
-                       "Helder.wiki",
-                       555
-               ]
-       },
-       "vector.js": "/* Qualquer JavaScript aqui colocado afetará os usuários do skin Vector */",
-       "vector-action-addsection": "Adicionar tópico",
-       "vector-action-delete": "Eliminar",
-       "vector-action-move": "Mover",
-       "vector-action-protect": "Proteger",
-       "vector-action-undelete": "Restaurar",
-       "vector-action-unprotect": "Alterar a proteção",
-       "vector-view-create": "Criar",
-       "vector-view-edit": "Editar",
-       "vector-view-history": "Ver histórico",
-       "vector-view-view": "Ler",
-       "vector-view-viewsource": "Ver código-fonte",
-       "vector-more-actions": "Mais"
-}
diff --git a/skins/Vector/i18n/pt.json b/skins/Vector/i18n/pt.json
deleted file mode 100644 (file)
index 9882289..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Crazymadlover",
-                       "Giro720",
-                       "Hamilton Abreu",
-                       "Malafaya",
-                       "Vitorvicentevalente",
-                       "Waldir"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector-skin-desc": "Versão moderna do MonoBook com um visual fresco e várias melhorias de usabilidade",
-       "vector.css": "/* Código CSS colocado aqui afectará os utilizadores do tema Vector */",
-       "vector.js": "/* Código Javascript colocado aqui será carregado para utilizadores do tema Vector */",
-       "vector-action-addsection": "Adicionar&nbsp;tópico",
-       "vector-action-delete": "Eliminar",
-       "vector-action-move": "Mover",
-       "vector-action-protect": "Proteger",
-       "vector-action-undelete": "Restaurar",
-       "vector-action-unprotect": "Alterar protecção",
-       "vector-view-create": "Criar",
-       "vector-view-edit": "Editar",
-       "vector-view-history": "Ver histórico",
-       "vector-view-view": "Ler",
-       "vector-view-viewsource": "Ver fonte",
-       "vector-more-actions": "Mais"
-}
diff --git a/skins/Vector/i18n/qqq.json b/skins/Vector/i18n/qqq.json
deleted file mode 100644 (file)
index fea395b..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Darth Kule",
-                       "EugeneZelenko",
-                       "Lloffiwr",
-                       "Shirayuki",
-                       "Umherirrender",
-                       "Matma Rex"
-               ]
-       },
-       "skinname-vector": "{{optional}}",
-       "vector-skin-desc": "{{desc|what=skin|name=Vector|url=https://www.mediawiki.org/wiki/Skin:Vector}}",
-       "vector.css": "{{optional}}",
-       "vector.js": "{{optional}}",
-       "vector-action-addsection": "Used in the Vector skin. See for example {{canonicalurl:Talk:Main_Page|useskin=vector}}",
-       "vector-action-delete": "Used in the Vector skin, as the name of a tab at the top of the page. See for example {{canonicalurl:Main_Page|useskin=vector}}\n\n{{Identical|Delete}}",
-       "vector-action-move": "Used in the Vector skin, on the tabs at the top of the page. See for example {{canonicalurl:Talk:Main_Page|useskin=vector}}\n\n{{Identical|Move}}",
-       "vector-action-protect": "Tab at top of page, in vector skin\n\n{{Identical|Protect}}",
-       "vector-action-undelete": "Tab at top of page, in vector skin.\n{{Identical|Undelete}}",
-       "vector-action-unprotect": "Tab at top of page, in vector skin.\n{{Identical|Change protection}}",
-       "vector-view-create": "Tab label in the Vector skin. See for example {{canonicalurl:Foo|useskin=vector}}\n{{Identical|Create}}",
-       "vector-view-edit": "Tab label in the Vector skin. See for example {{canonicalurl:Main_Page|useskin=vector}}\n{{Identical|Edit}}",
-       "vector-view-history": "Tab label in the Vector skin. See for example {{canonicalurl:Main_Page|useskin=vector}}\n{{Identical|View history}}",
-       "vector-view-view": "Tab label in the Vector skin (verb). See for example {{canonicalurl:Main_Page|useskin=vector}}.\n{{Identical|Read}}",
-       "vector-view-viewsource": "Tab label in the Vector skin.\n{{Identical|View source}}",
-       "vector-more-actions": "Label in the Vector skin's menu for the less-important or rarer actions which are not shown as tabs (like moving the page, or for sysops deleting or protecting the page), as well as (for users with a narrow viewing window in their browser) the less-important tab actions which the user's browser is unable to fit in. {{Identical|More}}"
-}
diff --git a/skins/Vector/i18n/qu.json b/skins/Vector/i18n/qu.json
deleted file mode 100644 (file)
index 789fd27..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "AlimanRuna"
-               ]
-       },
-       "vector-action-addsection": "Allwiyta yapay",
-       "vector-action-delete": "Qulluy",
-       "vector-action-move": "Astay",
-       "vector-action-protect": "Amachay",
-       "vector-action-undelete": "Qullusqata paqarichiy",
-       "vector-action-unprotect": "Amachayta wakinchay",
-       "vector-view-create": "Kamariy",
-       "vector-view-edit": "Llamk'apuy",
-       "vector-view-history": "Wiñay kawsayta qhaway",
-       "vector-view-view": "Ñawiriy",
-       "vector-view-viewsource": "Pukyu qillqata qhaway",
-       "vector-more-actions": "Aswan"
-}
diff --git a/skins/Vector/i18n/qug.json b/skins/Vector/i18n/qug.json
deleted file mode 100644 (file)
index 306f4ae..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Sylvain2803"
-               ]
-       },
-       "vector-action-addsection": "Shuk mushuk rimanakuyta kallarina",
-       "vector-action-delete": "Pichana",
-       "vector-action-move": "Apakuna",
-       "vector-action-protect": "Harkana",
-       "vector-action-undelete": "Kutin wacharichina",
-       "vector-action-unprotect": "Harkayta shukchina",
-       "vector-view-create": "Kamarina",
-       "vector-view-edit": "Killkana",
-       "vector-view-history": "Wiñay kawsayta rikuna",
-       "vector-view-view": "Killkakatina",
-       "vector-view-viewsource": "Pukyu killkata rikuna"
-}
diff --git a/skins/Vector/i18n/rap.json b/skins/Vector/i18n/rap.json
deleted file mode 100644 (file)
index b1f644c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Clerc",
-                       "MJohnsson"
-               ]
-       },
-       "vector-action-delete": "horo'i",
-       "vector-view-edit": "Haka titika"
-}
diff --git a/skins/Vector/i18n/rgn.json b/skins/Vector/i18n/rgn.json
deleted file mode 100644 (file)
index 784b8c5..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "vector-action-addsection": "Zonta una cjacarèda",
-       "vector-action-delete": "Scanzèla",
-       "vector-action-move": "Chèmbia nòm",
-       "vector-action-protect": "Metti-j una pruteziò",
-       "vector-action-undelete": "Armett a post",
-       "vector-action-unprotect": "Sbloca"
-}
diff --git a/skins/Vector/i18n/rif.json b/skins/Vector/i18n/rif.json
deleted file mode 100644 (file)
index 44de1de..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "MoubarikBelkasim"
-               ]
-       },
-       "vector-action-move": "Smuṭṭi",
-       "vector-view-create": "Seɣnu",
-       "vector-view-edit": "Ẓṛeg",
-       "vector-view-history": "Ẓeṛ amezruy",
-       "vector-view-view": "Ɣeṛ"
-}
diff --git a/skins/Vector/i18n/rm.json b/skins/Vector/i18n/rm.json
deleted file mode 100644 (file)
index 83ce427..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Gion-andri"
-               ]
-       },
-       "vector-action-addsection": "Agiuntar chapitel",
-       "vector-action-delete": "Stizzar",
-       "vector-action-move": "Spustar",
-       "vector-action-protect": "Bloccar",
-       "vector-action-undelete": "Restituir",
-       "vector-action-unprotect": "Midar la protecziun",
-       "vector-view-create": "Crear",
-       "vector-view-edit": "Modifitgar",
-       "vector-view-history": "Cronologia",
-       "vector-view-view": "Leger",
-       "vector-view-viewsource": "Mussar il code"
-}
diff --git a/skins/Vector/i18n/rmf.json b/skins/Vector/i18n/rmf.json
deleted file mode 100644 (file)
index 9865a50..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Szonja"
-               ]
-       },
-       "vector-action-addsection": "Tilja topikos",
-       "vector-action-delete": "Tšuu nikki",
-       "vector-action-undelete": "Tšuu paale",
-       "vector-view-create": "Luona",
-       "vector-view-edit": "Muoka",
-       "vector-view-history": "Sik histores",
-       "vector-view-view": "Draba",
-       "vector-view-viewsource": "Sik navasiinako koodos"
-}
diff --git a/skins/Vector/i18n/ro.json b/skins/Vector/i18n/ro.json
deleted file mode 100644 (file)
index 96725c0..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "AdiJapan",
-                       "Danutz",
-                       "Firilacroco",
-                       "Minisarm",
-                       "Strainu"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector.css": "/* CSS plasate aici vor afecta utilizatorii stilului Vector */",
-       "vector-action-addsection": "Mesaj nou",
-       "vector-action-delete": "Ștergere",
-       "vector-action-move": "Redenumire",
-       "vector-action-protect": "Protejare",
-       "vector-action-undelete": "Recuperare",
-       "vector-action-unprotect": "Modificare protecție",
-       "vector-view-create": "Creare",
-       "vector-view-edit": "Modificare",
-       "vector-view-history": "Istoric",
-       "vector-view-view": "Lectură",
-       "vector-view-viewsource": "Sursă pagină",
-       "vector-more-actions": "Mai mult"
-}
diff --git a/skins/Vector/i18n/roa-tara.json b/skins/Vector/i18n/roa-tara.json
deleted file mode 100644 (file)
index c5721e7..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Joetaras"
-               ]
-       },
-       "skinname-vector": "Vettore",
-       "vector.css": "/* 'U CSS ca se iacchie aqquà 'u 'ndrucane le utinde d'a masckere Vettore */",
-       "vector.js": "/* Ogne JavaScript aqquà avène carecate pe le utinde ca ausane 'a masckere Vettore */",
-       "vector-action-addsection": "Aggiunge 'na discussiona",
-       "vector-action-delete": "Scangille",
-       "vector-action-move": "Spuèste",
-       "vector-action-protect": "Protegge",
-       "vector-action-undelete": "Repristine",
-       "vector-action-unprotect": "Cange 'a protezione",
-       "vector-view-create": "Ccreje",
-       "vector-view-edit": "Cange",
-       "vector-view-history": "Vide 'u cunde",
-       "vector-view-view": "Ligge",
-       "vector-view-viewsource": "Vide 'u sorgende"
-}
diff --git a/skins/Vector/i18n/ru.json b/skins/Vector/i18n/ru.json
deleted file mode 100644 (file)
index cd344b9..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ignatus",
-                       "JenVan",
-                       "Kaganer",
-                       "Nemo bis",
-                       "Okras",
-                       "Александр Сигачёв"
-               ]
-       },
-       "skinname-vector": "Векторное",
-       "vector-skin-desc": "Современная версия MonoBook с обновлённым оформлением и многими улучшениями в юзабилити",
-       "vector.css": "/* Размещённый здесь CSS будет применяться к векторной теме оформления  */",
-       "vector.js": "/* Размещённый здесь код JavaScript будет загружаться пользователям, использующим тему оформления Vector */",
-       "vector-action-addsection": "Добавить тему",
-       "vector-action-delete": "Удалить",
-       "vector-action-move": "Переименовать",
-       "vector-action-protect": "Защитить",
-       "vector-action-undelete": "Восстановить",
-       "vector-action-unprotect": "Изменить защиту",
-       "vector-view-create": "Создание",
-       "vector-view-edit": "Править",
-       "vector-view-history": "История",
-       "vector-view-view": "Читать",
-       "vector-view-viewsource": "Просмотр разметки",
-       "vector-more-actions": "Ещё"
-}
diff --git a/skins/Vector/i18n/rue.json b/skins/Vector/i18n/rue.json
deleted file mode 100644 (file)
index 2147f80..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Gazeb"
-               ]
-       },
-       "vector-action-addsection": "Придати тему",
-       "vector-action-delete": "Вымазати",
-       "vector-action-move": "Переменовати",
-       "vector-action-protect": "Всокотити",
-       "vector-action-undelete": "Обновити",
-       "vector-action-unprotect": "Змінити замок",
-       "vector-view-create": "Створити",
-       "vector-view-edit": "Едітовати",
-       "vector-view-history": "Видїти історію",
-       "vector-view-view": "Чітати",
-       "vector-view-viewsource": "Видїти код"
-}
diff --git a/skins/Vector/i18n/rup.json b/skins/Vector/i18n/rup.json
deleted file mode 100644 (file)
index 3b0ba68..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "D'AroemenenZullenNiVergaan"
-               ]
-       },
-       "vector-action-addsection": "Dimândari nauâ",
-       "vector-view-history": "Veḑ istoricu"
-}
diff --git a/skins/Vector/i18n/rw.json b/skins/Vector/i18n/rw.json
deleted file mode 100644 (file)
index d151c2d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Vogone"
-               ]
-       },
-       "vector-action-move": "Imura",
-       "vector-view-edit": "Hindura",
-       "vector-view-history": "Reba amateka",
-       "vector-view-view": "Soma"
-}
diff --git a/skins/Vector/i18n/ryu.json b/skins/Vector/i18n/ryu.json
deleted file mode 100644 (file)
index ee1d2c1..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kyoww"
-               ]
-       },
-       "vector-view-edit": "直すん",
-       "vector-view-view": "読むん"
-}
diff --git a/skins/Vector/i18n/sa.json b/skins/Vector/i18n/sa.json
deleted file mode 100644 (file)
index 610ba3e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "NehalDaveND",
-                       "Shubha"
-               ]
-       },
-       "vector-action-addsection": "विषयः योज्यताम्",
-       "vector-action-delete": "अपाक्रियताम्",
-       "vector-action-move": "शीर्षकं परिवर्त्यताम्",
-       "vector-action-protect": "संरक्ष्यताम्",
-       "vector-action-undelete": "नापाकृतं",
-       "vector-action-unprotect": "संरक्षणं परिवर्तयतु",
-       "vector-view-create": "सृज्यताम्",
-       "vector-view-edit": "सम्पाद्यताम्",
-       "vector-view-history": "इतिहासः दृश्यताम्",
-       "vector-view-view": "पठ्यताम्",
-       "vector-view-viewsource": "स्रोतः दृश्यताम्"
-}
diff --git a/skins/Vector/i18n/sah.json b/skins/Vector/i18n/sah.json
deleted file mode 100644 (file)
index 9d44db5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "HalanTul"
-               ]
-       },
-       "vector-action-addsection": "Тиэмэ эбии",
-       "vector-action-delete": "Сот",
-       "vector-action-move": "Аатын уларыт",
-       "vector-action-protect": "Уларыйбат гын",
-       "vector-action-undelete": "Төннөр",
-       "vector-action-unprotect": "Көмүскэлин уларыт",
-       "vector-view-create": "Ай",
-       "vector-view-edit": "Уларыт",
-       "vector-view-history": "Устуоруйатын көрүү",
-       "vector-view-view": "Ааҕыы",
-       "vector-view-viewsource": "Бэлиэлэрин көрүү"
-}
diff --git a/skins/Vector/i18n/sat.json b/skins/Vector/i18n/sat.json
deleted file mode 100644 (file)
index d079721..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Albinus",
-                       "Samar88",
-                       "Srabony90"
-               ]
-       },
-       "vector-action-addsection": "Asol katha joṛaome",
-       "vector-action-delete": "Giḍi",
-       "vector-action-move": "Ocoḱ́me",
-       "vector-action-protect": "Bańcao",
-       "vector-action-undelete": "Bań getgiḍi",
-       "vector-action-unprotect": "Bodol rukhiyạ",
-       "vector-view-create": "Tearme",
-       "vector-view-edit": "So̠mpado̠n",
-       "vector-view-history": "Jạṛ ńelme",
-       "vector-view-view": "Paṛhaḱme",
-       "vector-view-viewsource": "Ńamoḱaḱ ńelme"
-}
diff --git a/skins/Vector/i18n/saz.json b/skins/Vector/i18n/saz.json
deleted file mode 100644 (file)
index a3a6ded..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "MooRePrabu"
-               ]
-       },
-       "vector-view-view": "ꢗꢾꢮ꣄ꢣꢶ"
-}
diff --git a/skins/Vector/i18n/sc.json b/skins/Vector/i18n/sc.json
deleted file mode 100644 (file)
index e7876a6..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Andria",
-                       "Marzedu",
-                       "Via maxima"
-               ]
-       },
-       "vector-action-addsection": "Giunghe cuntierra",
-       "vector-action-delete": "Cantzella",
-       "vector-action-move": "Move",
-       "vector-action-protect": "Ampara",
-       "vector-action-undelete": "Recùpera",
-       "vector-view-create": "Crea",
-       "vector-view-edit": "Acontza",
-       "vector-view-history": "Càstia istòria",
-       "vector-view-view": "Leghe",
-       "vector-view-viewsource": "Càstia mitza",
-       "vector-more-actions": "Prus"
-}
diff --git a/skins/Vector/i18n/scn.json b/skins/Vector/i18n/scn.json
deleted file mode 100644 (file)
index a9483c4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Gmelfi",
-                       "Melos"
-               ]
-       },
-       "vector-action-addsection": "Agghiunci argumentu",
-       "vector-action-delete": "Elìmina",
-       "vector-action-move": "Sposta",
-       "vector-action-protect": "Pruteggi",
-       "vector-action-undelete": "Riprìstina",
-       "vector-action-unprotect": "Cancia la prutizzioni",
-       "vector-view-create": "Crea",
-       "vector-view-edit": "Cancia",
-       "vector-view-history": "Talìa a storia",
-       "vector-view-view": "Leggi",
-       "vector-view-viewsource": "Talìa la fonti",
-       "vector-more-actions": "Àutri cosi"
-}
diff --git a/skins/Vector/i18n/sco.json b/skins/Vector/i18n/sco.json
deleted file mode 100644 (file)
index acf5387..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Avicennasis",
-                       "John Reid",
-                       "Omnipaedista"
-               ]
-       },
-       "vector-action-addsection": "Eik topic",
-       "vector-action-delete": "Delyte",
-       "vector-action-move": "Muiv",
-       "vector-action-protect": "Fend",
-       "vector-action-undelete": "Ondelyte",
-       "vector-action-unprotect": "Chynge protection",
-       "vector-view-create": "Ceaut",
-       "vector-view-edit": "Eedit",
-       "vector-view-history": "See histerie",
-       "vector-view-view": "Read",
-       "vector-view-viewsource": "See Soorce"
-}
diff --git a/skins/Vector/i18n/sd.json b/skins/Vector/i18n/sd.json
deleted file mode 100644 (file)
index 04a5370..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-       "vector-action-delete": "ڊاھيو",
-       "vector-action-move": "چوريو",
-       "vector-action-protect": "تحفظيو",
-       "vector-action-unprotect": "اڻتحفظيو",
-       "vector-view-create": "سرجيو",
-       "vector-view-edit": "سنواريو",
-       "vector-view-viewsource": "ڪوڊ ڏسو"
-}
diff --git a/skins/Vector/i18n/sdc.json b/skins/Vector/i18n/sdc.json
deleted file mode 100644 (file)
index c843931..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Felis",
-                       "Jun Misugi"
-               ]
-       },
-       "vector-action-addsection": "Aggiungì oggettu",
-       "vector-action-delete": "Canzella",
-       "vector-action-move": "Ippustha",
-       "vector-action-protect": "Pruteggì",
-       "vector-view-create": "Cria",
-       "vector-view-edit": "Mudifigga",
-       "vector-view-history": "Vèdi isthòria",
-       "vector-view-view": "Leggi",
-       "vector-view-viewsource": "Vèdi fonti"
-}
diff --git a/skins/Vector/i18n/sdh.json b/skins/Vector/i18n/sdh.json
deleted file mode 100644 (file)
index 2f4523f..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Paraw2"
-               ]
-       },
-       "vector-action-addsection": "بابەت تازە بدە سەری",
-       "vector-action-delete": "بسڕەوە",
-       "vector-action-move": "جیوەجی بکە",
-       "vector-action-protect": "بپیەرێزەێ",
-       "vector-view-create": "درسکردن",
-       "vector-view-edit": "وێراشتەێ بکە",
-       "vector-view-history": "دیرۆکەگەی بۊن",
-       "vector-view-view": "بخوەنە",
-       "vector-view-viewsource": "سەرچاوەگەێ بۊن"
-}
diff --git a/skins/Vector/i18n/se.json b/skins/Vector/i18n/se.json
deleted file mode 100644 (file)
index bb0a900..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Gálaniitoluodda",
-                       "Jeblad",
-                       "Trondtr"
-               ]
-       },
-       "vector-action-addsection": "Lasit fáttá",
-       "vector-action-delete": "Sihko",
-       "vector-action-move": "Sirdde",
-       "vector-action-protect": "Suodjal",
-       "vector-action-undelete": "Máhcat",
-       "vector-action-unprotect": "Rievdat suodjaleami",
-       "vector-view-create": "Álggat",
-       "vector-view-edit": "Rievdat",
-       "vector-view-history": "Geahča historjjá",
-       "vector-view-view": "Loga",
-       "vector-view-viewsource": "Geahča gáldokoda"
-}
diff --git a/skins/Vector/i18n/sg.json b/skins/Vector/i18n/sg.json
deleted file mode 100644 (file)
index 2f65834..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mdkidiri"
-               ]
-       },
-       "vector-action-addsection": "Zîa mbênî lilö daä",
-       "vector-action-delete": "Lungûla",
-       "vector-action-move": "Sanzêe ïrï",
-       "vector-action-protect": "Funga",
-       "vector-action-undelete": "Kîri na nî",
-       "vector-action-unprotect": "Sanzêe fungä",
-       "vector-view-create": "Seka",
-       "vector-view-edit": "Sepe",
-       "vector-view-history": "Tanda mbai nî",
-       "vector-view-view": "Dîko",
-       "vector-view-viewsource": "Fa ligbî nî"
-}
diff --git a/skins/Vector/i18n/sgs.json b/skins/Vector/i18n/sgs.json
deleted file mode 100644 (file)
index 7b2591c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Hugo.arg"
-               ]
-       },
-       "vector-action-addsection": "Pridietė tema",
-       "vector-action-delete": "Trintė",
-       "vector-action-move": "Parvadintė",
-       "vector-action-protect": "Ožrakintė",
-       "vector-action-undelete": "Atkortė",
-       "vector-action-unprotect": "Keistė apsauga",
-       "vector-view-create": "Sokortė",
-       "vector-view-edit": "Taisītė",
-       "vector-view-history": "Veizietė istuorėjė",
-       "vector-view-view": "Skaitītė",
-       "vector-view-viewsource": "Veizietė kuoda"
-}
diff --git a/skins/Vector/i18n/sh.json b/skins/Vector/i18n/sh.json
deleted file mode 100644 (file)
index 21e6153..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "OC Ripper"
-               ]
-       },
-       "vector-action-addsection": "Dodaj temu",
-       "vector-action-delete": "Brisanje",
-       "vector-action-move": "Preusmjeri",
-       "vector-action-protect": "Zaštiti",
-       "vector-action-undelete": "Vrati obrisano",
-       "vector-action-unprotect": "Promijeni zaštitu",
-       "vector-view-create": "Napravi",
-       "vector-view-edit": "Uredi",
-       "vector-view-history": "Pregled historije",
-       "vector-view-view": "Čitaj",
-       "vector-view-viewsource": "Vidi izvor (source)"
-}
diff --git a/skins/Vector/i18n/shi.json b/skins/Vector/i18n/shi.json
deleted file mode 100644 (file)
index 10f48d8..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Dalinanir"
-               ]
-       },
-       "vector-action-addsection": "Zayd amli",
-       "vector-action-delete": "Ḥiyd",
-       "vector-action-move": "Smmatti",
-       "vector-action-protect": "Ḥbu",
-       "vector-action-undelete": "Rard may mayḥiydn",
-       "vector-action-unprotect": "Ḥiyd aḥbu",
-       "vector-view-create": "Skert",
-       "vector-view-edit": "Ara",
-       "vector-view-history": "Mel amzruy",
-       "vector-view-view": "ɣr",
-       "vector-view-viewsource": "Ẓr asagm"
-}
diff --git a/skins/Vector/i18n/shn.json b/skins/Vector/i18n/shn.json
deleted file mode 100644 (file)
index c2cea6a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Saiddzone"
-               ]
-       },
-       "vector-action-protect": "ႁေႉၵင်ႈ",
-       "vector-view-create": "သၢင်ႈ",
-       "vector-view-edit": "မူၼ်ႉမႄး",
-       "vector-view-history": "တူၺ်းပိုၼ်း",
-       "vector-view-view": "လူတူၺ်း",
-       "vector-view-viewsource": "တူၺ်း ငဝ်ႈငႃႇ"
-}
diff --git a/skins/Vector/i18n/si.json b/skins/Vector/i18n/si.json
deleted file mode 100644 (file)
index 640874f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Thushara",
-                       "දසනැබළයෝ",
-                       "පසිඳු කාවින්ද",
-                       "සුරනිමල"
-               ]
-       },
-       "vector-action-addsection": "මාතෘකාව එක්කරන්න",
-       "vector-action-delete": "මකන්න",
-       "vector-action-move": "ගෙනයන්න",
-       "vector-action-protect": "ආරක්‍ෂණය",
-       "vector-action-undelete": "මකාදැමීම අවලංගු කරන්න",
-       "vector-action-unprotect": "ආරක්ෂණ තත්වය වෙනස් කරන්න",
-       "vector-view-create": "තනන්න",
-       "vector-view-edit": "සංස්කරණය",
-       "vector-view-history": "ඉතිහාසය නරඹන්න",
-       "vector-view-view": "කියවන්න",
-       "vector-view-viewsource": "මූලාශ්‍රය නරඹන්න",
-       "vector-more-actions": "තවත්"
-}
diff --git a/skins/Vector/i18n/sk.json b/skins/Vector/i18n/sk.json
deleted file mode 100644 (file)
index 06bf290..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Helix84",
-                       "Rudko",
-                       "Sudo77(new)"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector.css": "/* Tu umiestnené CSS bude ovplyvňovať používateľov štýlu Vector */",
-       "vector.js": "/* Tu sa nachádzajúci JavaScript sa načíta používateľom vzhľadu Vector */",
-       "vector-action-addsection": "Pridať tému",
-       "vector-action-delete": "Zmazať",
-       "vector-action-move": "Presunúť",
-       "vector-action-protect": "Zamknúť",
-       "vector-action-undelete": "Obnoviť",
-       "vector-action-unprotect": "Zmeniť stav ochrany",
-       "vector-view-create": "Vytvoriť",
-       "vector-view-edit": "Upraviť",
-       "vector-view-history": "Zobraziť históriu",
-       "vector-view-view": "Čítať",
-       "vector-view-viewsource": "Zobraziť zdroj",
-       "vector-more-actions": "Viac"
-}
diff --git a/skins/Vector/i18n/sl.json b/skins/Vector/i18n/sl.json
deleted file mode 100644 (file)
index 85e8574..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Dbc334",
-                       "Smihael",
-                       "Yerpo"
-               ]
-       },
-       "vector-action-addsection": "Dodaj temo",
-       "vector-action-delete": "Izbriši",
-       "vector-action-move": "Prestavi",
-       "vector-action-protect": "Zaščiti",
-       "vector-action-undelete": "Vrni",
-       "vector-action-unprotect": "Spremeni zaščito",
-       "vector-view-create": "Ustvari",
-       "vector-view-edit": "Uredi",
-       "vector-view-history": "Zgodovina",
-       "vector-view-view": "Preberi",
-       "vector-view-viewsource": "Izvorno besedilo",
-       "vector-more-actions": "Več"
-}
diff --git a/skins/Vector/i18n/sli.json b/skins/Vector/i18n/sli.json
deleted file mode 100644 (file)
index e394c5e..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Przemub",
-                       "Schläsinger",
-                       "Timpul",
-                       "Äberlausitzer"
-               ]
-       },
-       "vector-action-addsection": "Obschnitt hinzufiega",
-       "vector-action-delete": "Läscha",
-       "vector-action-move": "Verschieba",
-       "vector-action-protect": "Schützen",
-       "vector-action-undelete": "Wiederherstella",
-       "vector-action-unprotect": "Freigahn",
-       "vector-view-create": "Erstella",
-       "vector-view-edit": "Bearbeita",
-       "vector-view-history": "Versionsgeschichte",
-       "vector-view-view": "Lessa",
-       "vector-view-viewsource": "Quelltext siehn"
-}
diff --git a/skins/Vector/i18n/sly.json b/skins/Vector/i18n/sly.json
deleted file mode 100644 (file)
index deb6741..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "ZQheert"
-               ]
-       },
-       "vector-action-delete": "Lelei",
-       "vector-action-move": "Palettei",
-       "vector-view-create": "Bua'",
-       "vector-view-edit": "edi'",
-       "vector-view-view": "Bacai",
-       "vector-view-viewsource": "Tilingi assala'na"
-}
diff --git a/skins/Vector/i18n/so.json b/skins/Vector/i18n/so.json
deleted file mode 100644 (file)
index 1362fd8..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Maax"
-               ]
-       },
-       "vector-action-addsection": "Hadal ku dar",
-       "vector-action-delete": "Tirtir",
-       "vector-action-move": "Wareeji",
-       "vector-action-protect": "Difaac",
-       "vector-action-undelete": "Ha tirtirin",
-       "vector-action-unprotect": "Bedel difaacida",
-       "vector-view-create": "Sameey",
-       "vector-view-edit": "Wax ka bedel",
-       "vector-view-history": "Itusi taariikhda",
-       "vector-view-view": "Akhri",
-       "vector-view-viewsource": "Itusi xogta"
-}
diff --git a/skins/Vector/i18n/sq.json b/skins/Vector/i18n/sq.json
deleted file mode 100644 (file)
index fcc3434..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Dasius",
-                       "GretaDoci",
-                       "MicroBoy",
-                       "Mikullovci11",
-                       "Olsi"
-               ]
-       },
-       "vector-action-addsection": "Shto një temë",
-       "vector-action-delete": "Grise",
-       "vector-action-move": "Zhvendose",
-       "vector-action-protect": "Mbroje",
-       "vector-action-undelete": "Anullo fshirjen",
-       "vector-action-unprotect": "Ndrysho mbrojtjen",
-       "vector-view-create": "Krijo",
-       "vector-view-edit": "Redakto",
-       "vector-view-history": "Shiko historikun",
-       "vector-view-view": "Lexo",
-       "vector-view-viewsource": "Shiko tekstin",
-       "vector-more-actions": "Më tepër..."
-}
diff --git a/skins/Vector/i18n/sr-ec.json b/skins/Vector/i18n/sr-ec.json
deleted file mode 100644 (file)
index e33b69c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Milicevic01",
-                       "Rancher",
-                       "Жељко Тодоровић",
-                       "Михајло Анђелковић"
-               ]
-       },
-       "skinname-vector": "Векторско",
-       "vector.css": "/* CSS постављен овде ће утицати на све кориснике теме „Векторско“ */",
-       "vector.js": "/* Јаваскрипт постављен овде ће се учитати за све оне који користе тему „Векторско“ */",
-       "vector-action-addsection": "Додај тему",
-       "vector-action-delete": "Обриши",
-       "vector-action-move": "Премести",
-       "vector-action-protect": "Заштити",
-       "vector-action-undelete": "Врати",
-       "vector-action-unprotect": "Промени заштиту",
-       "vector-view-create": "Направи",
-       "vector-view-edit": "Уреди",
-       "vector-view-history": "Историја",
-       "vector-view-view": "Читај",
-       "vector-view-viewsource": "Изворни код",
-       "vector-more-actions": "Више"
-}
diff --git a/skins/Vector/i18n/sr-el.json b/skins/Vector/i18n/sr-el.json
deleted file mode 100644 (file)
index 38f17ad..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Michaello",
-                       "Milicevic01",
-                       "Rancher",
-                       "Жељко Тодоровић"
-               ]
-       },
-       "skinname-vector": "Vektorsko",
-       "vector.css": "/* CSS postavljen ovde će uticati na sve korisnike teme „Vektorsko“ */",
-       "vector.js": "/* Javaskript postavljen ovde će se učitati za sve one koji koriste temu „Vektorsko“ */",
-       "vector-action-addsection": "Dodaj temu",
-       "vector-action-delete": "Obriši",
-       "vector-action-move": "Premesti",
-       "vector-action-protect": "Zaštiti",
-       "vector-action-undelete": "Vrati",
-       "vector-action-unprotect": "Promeni zaštitu",
-       "vector-view-create": "Napravi",
-       "vector-view-edit": "Uredi",
-       "vector-view-history": "Istorija",
-       "vector-view-view": "Čitaj",
-       "vector-view-viewsource": "Izvorni kod",
-       "vector-more-actions": "Više"
-}
diff --git a/skins/Vector/i18n/ss.json b/skins/Vector/i18n/ss.json
deleted file mode 100644 (file)
index 44a5edf..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Sibande"
-               ]
-       },
-       "vector-action-addsection": "Ngeta sihloko",
-       "vector-action-move": "Khweshisa",
-       "vector-view-create": "Create",
-       "vector-view-edit": "Hlela",
-       "vector-view-history": "Bona umlandvo",
-       "vector-view-view": "Fundza"
-}
diff --git a/skins/Vector/i18n/stq.json b/skins/Vector/i18n/stq.json
deleted file mode 100644 (file)
index 1e2da5a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Pyt"
-               ]
-       },
-       "vector-action-addsection": "Ousnit bietouföigje",
-       "vector-action-delete": "Läskje",
-       "vector-action-move": "Ferskuuwe",
-       "vector-action-protect": "Skutsje",
-       "vector-action-undelete": "Wierhäärstaale",
-       "vector-action-unprotect": "Siedenskuts annerje",
-       "vector-view-create": "Moakje",
-       "vector-view-edit": "Beoarbaidje",
-       "vector-view-history": "Versionsgeskichte",
-       "vector-view-view": "Leese",
-       "vector-view-viewsource": "Wältext bekiekje"
-}
diff --git a/skins/Vector/i18n/su.json b/skins/Vector/i18n/su.json
deleted file mode 100644 (file)
index d8a780a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kandar"
-               ]
-       },
-       "vector-action-addsection": "Jieun jejer anyar",
-       "vector-action-delete": "Hapus",
-       "vector-action-move": "Pindahkeun",
-       "vector-action-protect": "Konci",
-       "vector-action-undelete": "Bolaykeun ngahapus",
-       "vector-action-unprotect": "Robah protéksi",
-       "vector-view-create": "Jieun",
-       "vector-view-edit": "Édit",
-       "vector-view-history": "Témbongkeun jujutan",
-       "vector-view-view": "Baca",
-       "vector-view-viewsource": "Témbongkeun sumber"
-}
diff --git a/skins/Vector/i18n/sv.json b/skins/Vector/i18n/sv.json
deleted file mode 100644 (file)
index 930bbce..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Martinwiss",
-                       "Najami",
-                       "Skalman",
-                       "WikiPhoenix",
-                       "Lokal Profil"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector-skin-desc": "Modern version av MonoBook med ett nytt utseende och flera användarvänlighetsförbättringar",
-       "vector.css": "/* CSS som skrivs här kommer att påverka alla användare av skalet Vector */",
-       "vector.js": "/* JavaScript här kommer att laddas för dem som använder skalet Vector */",
-       "vector-action-addsection": "Nytt ämne",
-       "vector-action-delete": "Radera",
-       "vector-action-move": "Flytta",
-       "vector-action-protect": "Skrivskydda",
-       "vector-action-undelete": "Återställ",
-       "vector-action-unprotect": "Ändra skydd",
-       "vector-view-create": "Skapa",
-       "vector-view-edit": "Redigera",
-       "vector-view-history": "Visa historik",
-       "vector-view-view": "Visa",
-       "vector-view-viewsource": "Visa källa",
-       "vector-more-actions": "Mer"
-}
diff --git a/skins/Vector/i18n/sw.json b/skins/Vector/i18n/sw.json
deleted file mode 100644 (file)
index cb511ba..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Lloffiwr",
-                       "Muddyb Blast Producer"
-               ]
-       },
-       "vector-action-addsection": "Weka mada",
-       "vector-action-delete": "Futa",
-       "vector-action-move": "Hamisha",
-       "vector-action-protect": "Linda",
-       "vector-action-undelete": "Rudisha",
-       "vector-action-unprotect": "Badilisha ulinzi",
-       "vector-view-create": "Anzisha",
-       "vector-view-edit": "Hariri",
-       "vector-view-history": "Fungua historia",
-       "vector-view-view": "Soma",
-       "vector-view-viewsource": "Tazama msimbo"
-}
diff --git a/skins/Vector/i18n/szl.json b/skins/Vector/i18n/szl.json
deleted file mode 100644 (file)
index 9e8c106..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Britscher",
-                       "Gaj777",
-                       "Przemub"
-               ]
-       },
-       "vector-action-addsection": "Nowo tajla",
-       "vector-action-delete": "Wyćepej",
-       "vector-action-move": "Przećep",
-       "vector-action-protect": "Zawrzij",
-       "vector-action-undelete": "Wćep",
-       "vector-action-unprotect": "Uodymkńij",
-       "vector-view-create": "Stwůrz",
-       "vector-view-edit": "Sprowjej",
-       "vector-view-history": "Uobocz gyszichta",
-       "vector-view-view": "Czytej",
-       "vector-view-viewsource": "Zdrzůdłowy tekst"
-}
diff --git a/skins/Vector/i18n/ta.json b/skins/Vector/i18n/ta.json
deleted file mode 100644 (file)
index 21f8501..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Mayooranathan",
-                       "Shanmugamp7",
-                       "Surya Prakash.S.A.",
-                       "TRYPPN"
-               ]
-       },
-       "vector-action-addsection": "தலைப்பைச் சேர்",
-       "vector-action-delete": "நீக்குக",
-       "vector-action-move": "நகர்த்தவும்",
-       "vector-action-protect": "காக்கவும்",
-       "vector-action-undelete": "நீக்கத்தை நிறுத்து",
-       "vector-action-unprotect": "காப்பை மாற்று",
-       "vector-view-create": "உருவாக்கவும்",
-       "vector-view-edit": "தொகு",
-       "vector-view-history": "வரலாற்றைக் காட்டவும்",
-       "vector-view-view": "படிக்கவும்",
-       "vector-view-viewsource": "மூலத்தைக் காட்டவும்"
-}
diff --git a/skins/Vector/i18n/tcy.json b/skins/Vector/i18n/tcy.json
deleted file mode 100644 (file)
index 0001fe5..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "NamwikiTL",
-                       "VASANTH S.N."
-               ]
-       },
-       "vector-action-addsection": "ವಿಷಯ ಸೇರಾಲೆ",
-       "vector-action-delete": "ದೆತ್ತ್ ಪಾಡ್ಲೆ",
-       "vector-action-move": "ಸ್ಥಳಾಂತರ ಮಲ್ಪುಲೆ",
-       "vector-action-protect": "ಸ೦ರಕ್ಷಿಸಾಲೆ",
-       "vector-action-undelete": "ಮಾಜಾವಡೆ",
-       "vector-action-unprotect": "ಬದಲಾವಣೆನ್ ರಕ್ಷಿಸಾಲೆ",
-       "vector-view-create": " ಸುರು ಮಲ್ಪುಲೆ",
-       "vector-view-edit": "ಸಂಪಾದನೆ ಮಲ್ಪುಲೆ",
-       "vector-view-history": "ಇತಿಹಾಸೊನು ತೂಲೆ",
-       "vector-view-view": "ಓದ್ಲೇ",
-       "vector-view-viewsource": "ಮೂಲೊನು ತೂಲೆ"
-}
diff --git a/skins/Vector/i18n/te.json b/skins/Vector/i18n/te.json
deleted file mode 100644 (file)
index f32d90e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Chaduvari",
-                       "Kiranmayee",
-                       "Praveen Illa",
-                       "Ravichandra",
-                       "Veeven"
-               ]
-       },
-       "skinname-vector": "వెక్టర్",
-       "vector-action-addsection": "విషయాన్ని చేర్చు",
-       "vector-action-delete": "తొలగించు",
-       "vector-action-move": "తరలించు",
-       "vector-action-protect": "సంరక్షించు",
-       "vector-action-undelete": "తొలగింపును రద్దుచెయ్యి",
-       "vector-action-unprotect": "సంరక్షణను మార్చు",
-       "vector-view-create": "సృష్టించు",
-       "vector-view-edit": "సవరించు",
-       "vector-view-history": "చరిత్రను చూడండి",
-       "vector-view-view": "చదువు",
-       "vector-view-viewsource": "మూలాన్ని చూపించు",
-       "vector-more-actions": "మరిన్ని"
-}
diff --git a/skins/Vector/i18n/tet.json b/skins/Vector/i18n/tet.json
deleted file mode 100644 (file)
index 0cc9b82..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "MF-Warburg"
-               ]
-       },
-       "vector-action-protect": "Proteje",
-       "vector-view-create": "Kria",
-       "vector-view-edit": "Edita",
-       "vector-view-history": "Haree istória",
-       "vector-view-view": "Lee"
-}
diff --git a/skins/Vector/i18n/tg-cyrl.json b/skins/Vector/i18n/tg-cyrl.json
deleted file mode 100644 (file)
index ede0347..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ibrahim"
-               ]
-       },
-       "vector-action-addsection": "Иловаи унвон",
-       "vector-action-delete": "Ҳазф",
-       "vector-action-move": "Кӯчонидан",
-       "vector-action-protect": "Муҳофизат",
-       "vector-action-undelete": "Эҳё",
-       "vector-action-unprotect": "Тағйири муҳофизат",
-       "vector-view-create": "Эҷод",
-       "vector-view-edit": "Вироиш",
-       "vector-view-history": "Намоиши таърих",
-       "vector-view-view": "Хондан",
-       "vector-view-viewsource": "Намоиши манбаъ"
-}
diff --git a/skins/Vector/i18n/tg-latn.json b/skins/Vector/i18n/tg-latn.json
deleted file mode 100644 (file)
index 1ecb038..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Liangent"
-               ]
-       },
-       "vector-action-addsection": "Ilovai unvon",
-       "vector-action-delete": "Hazf",
-       "vector-action-move": "Kūconidan",
-       "vector-action-protect": "Muhofizat",
-       "vector-action-undelete": "Ehjo",
-       "vector-action-unprotect": "Ba dar ovardan az muhofizat",
-       "vector-view-create": "Eçod",
-       "vector-view-edit": "Viroiş",
-       "vector-view-history": "Namoişi ta'rix",
-       "vector-view-view": "Xondan",
-       "vector-view-viewsource": "Namoişi manba'"
-}
diff --git a/skins/Vector/i18n/th.json b/skins/Vector/i18n/th.json
deleted file mode 100644 (file)
index ae4b838..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Horus",
-                       "Octahedron80",
-                       "Woraponboonkerd"
-               ]
-       },
-       "skinname-vector": "เวกเตอร์",
-       "vector.css": "/* สไตล์ชีตในหน้านี้จะส่งผลแก่ผู้ใช้ที่ใช้สกินเวกเตอร์ */",
-       "vector.js": "/* จาวาสคริปต์ใด ๆ ในหน้านี้จะถูกโหลดให้แก่ผู้ใช้ที่ใช้สกินเวกเตอร์ */",
-       "vector-action-addsection": "เพิ่มหัวข้อ",
-       "vector-action-delete": "ลบ",
-       "vector-action-move": "เปลี่ยนชื่อ",
-       "vector-action-protect": "ล็อก",
-       "vector-action-undelete": "กู้คืน",
-       "vector-action-unprotect": "เปลี่ยนการล็อก",
-       "vector-view-create": "สร้าง",
-       "vector-view-edit": "แก้ไข",
-       "vector-view-history": "ดูประวัติ",
-       "vector-view-view": "อ่าน",
-       "vector-view-viewsource": "ดูโค้ด",
-       "vector-more-actions": "เพิ่มเติม"
-}
diff --git a/skins/Vector/i18n/tk.json b/skins/Vector/i18n/tk.json
deleted file mode 100644 (file)
index f11da23..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Hanberke"
-               ]
-       },
-       "vector-action-addsection": "Tema goş",
-       "vector-action-delete": "Öçür",
-       "vector-action-move": "Adyny üýtget",
-       "vector-action-protect": "Goraga al",
-       "vector-action-undelete": "Öçürmäni yzyna al",
-       "vector-action-unprotect": "Goragy üýtget",
-       "vector-view-create": "Döret",
-       "vector-view-edit": "Üýtget",
-       "vector-view-history": "Taryhy gör",
-       "vector-view-view": "Oka",
-       "vector-view-viewsource": "Çeşmäni gör"
-}
diff --git a/skins/Vector/i18n/tl.json b/skins/Vector/i18n/tl.json
deleted file mode 100644 (file)
index 2a0495d..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "AnakngAraw",
-                       "Sky Harbor"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector.css": "/* Ang inilagay na CSS dito ay makakaapekto sa mga tagagamit ng pabalat na Vector */",
-       "vector.js": "/* Ang anumang JavaScript dito ay ikakarga para sa mga tagagamit na gumagamit ng pabalat na Vector */",
-       "vector-action-addsection": "Magdagdag ng paksa",
-       "vector-action-delete": "Burahin",
-       "vector-action-move": "Ilipat",
-       "vector-action-protect": "Ipagsanggalang",
-       "vector-action-undelete": "Alisin ang pagbubura",
-       "vector-action-unprotect": "Baguhin ang pagsasanggalang",
-       "vector-view-create": "Likhain",
-       "vector-view-edit": "Baguhin",
-       "vector-view-history": "Tingnan ang kasaysayan",
-       "vector-view-view": "Basahin",
-       "vector-view-viewsource": "Tingnan ang pinagmulan"
-}
diff --git a/skins/Vector/i18n/tly.json b/skins/Vector/i18n/tly.json
deleted file mode 100644 (file)
index a809d5e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Гусейн"
-               ]
-       },
-       "vector-action-addsection": "Мывзу зијод кардеј",
-       "vector-action-delete": "Рәдд кардеј",
-       "vector-action-move": "Номи дәгиш кардеј",
-       "vector-action-protect": "Мыдофијә кардеј",
-       "vector-action-undelete": "Бәрпо кардеј",
-       "vector-action-unprotect": "Мыдофијә дәгиш кардеј",
-       "vector-view-create": "Офәјеј",
-       "vector-view-edit": "Сәрост кардеј",
-       "vector-view-history": "Тарых",
-       "vector-view-view": "Һандемон",
-       "vector-view-viewsource": "Дијә кардеј"
-}
diff --git a/skins/Vector/i18n/tpi.json b/skins/Vector/i18n/tpi.json
deleted file mode 100644 (file)
index 182aa9a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Iketsi",
-                       "Wantok"
-               ]
-       },
-       "vector-action-delete": "Rausim",
-       "vector-action-move": "Surikim",
-       "vector-action-protect": "Tambuim",
-       "vector-view-create": "Kirapim",
-       "vector-view-edit": "Senisim",
-       "vector-view-history": "Ol senis",
-       "vector-view-view": "Rit",
-       "vector-view-viewsource": "Lukim as tok"
-}
diff --git a/skins/Vector/i18n/tr.json b/skins/Vector/i18n/tr.json
deleted file mode 100644 (file)
index da041a9..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Arystanbek",
-                       "Emperyan",
-                       "Joseph",
-                       "Stultiwikia",
-                       "Vito Genovese"
-               ]
-       },
-       "vector-action-addsection": "Konu ekle",
-       "vector-action-delete": "Sil",
-       "vector-action-move": "Taşı",
-       "vector-action-protect": "Koru",
-       "vector-action-undelete": "Silinmeyi geri al",
-       "vector-action-unprotect": "Korumayı değiştir",
-       "vector-view-create": "Oluştur",
-       "vector-view-edit": "Düzenle",
-       "vector-view-history": "Geçmişi gör",
-       "vector-view-view": "Oku",
-       "vector-view-viewsource": "Kaynağı gör",
-       "vector-more-actions": "Diğer"
-}
diff --git a/skins/Vector/i18n/tru.json b/skins/Vector/i18n/tru.json
deleted file mode 100644 (file)
index 1949f25..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ariyo"
-               ]
-       },
-       "vector-action-addsection": "Maḥat Fusoqo ḥaṭo",
-       "vector-action-delete": "Slag",
-       "vector-action-move": "Mtaxar",
-       "vector-action-protect": "Mastar",
-       "vector-view-create": "Xlaq",
-       "vector-view-edit": "Mşaḥlaf",
-       "vector-view-history": "Maktabzabno",
-       "vector-view-view": "Qray",
-       "vector-view-viewsource": "Maḥway li aMabu³e."
-}
diff --git a/skins/Vector/i18n/ts.json b/skins/Vector/i18n/ts.json
deleted file mode 100644 (file)
index c00b029..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Thuvack"
-               ]
-       },
-       "vector-action-addsection": "Veka nholoko ya mhaka",
-       "vector-action-delete": "Sula",
-       "vector-action-move": "Yi sa kunwana",
-       "vector-action-protect": "Sirhelela",
-       "vector-action-undelete": "Cinca kusula",
-       "vector-action-unprotect": "Cinca kusirhelela",
-       "vector-view-create": "Tumbuluxa",
-       "vector-view-edit": "Lulamisa",
-       "vector-view-history": "Languta matimu",
-       "vector-view-view": "Hlaya",
-       "vector-view-viewsource": "Languta xihlovo"
-}
diff --git a/skins/Vector/i18n/tt-cyrl.json b/skins/Vector/i18n/tt-cyrl.json
deleted file mode 100644 (file)
index 606fbe3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Don Alessandro",
-                       "Rinatus",
-                       "Ильнар",
-                       "Рашат Якупов"
-               ]
-       },
-       "skinname-vector": "Сызымлы",
-       "vector-action-addsection": "Яңа тема өстәү",
-       "vector-action-delete": "Бетерү",
-       "vector-action-move": "Күчерү",
-       "vector-action-protect": "Яклау",
-       "vector-action-undelete": "Кайтару",
-       "vector-action-unprotect": "Яклауны үзгәртү",
-       "vector-view-create": "Төзү",
-       "vector-view-edit": "Үзгәртү",
-       "vector-view-history": "Тарихын карау",
-       "vector-view-view": "Уку",
-       "vector-view-viewsource": "Чыганагын карау"
-}
diff --git a/skins/Vector/i18n/tt-latn.json b/skins/Vector/i18n/tt-latn.json
deleted file mode 100644 (file)
index 140768b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Don Alessandro"
-               ]
-       },
-       "skinname-vector": "Sızımlı",
-       "vector-action-addsection": "Yaña tema östäw",
-       "vector-action-delete": "Beterü",
-       "vector-action-move": "Küçerü",
-       "vector-action-protect": "Yaqlaw",
-       "vector-action-undelete": "Qaytaru",
-       "vector-action-unprotect": "Yaqlawnı beterü",
-       "vector-view-create": "Tözü",
-       "vector-view-edit": "Üzgärtü",
-       "vector-view-history": "Tarixın qaraw",
-       "vector-view-view": "Uqu",
-       "vector-view-viewsource": "Çığanağın qaraw"
-}
diff --git a/skins/Vector/i18n/tyv.json b/skins/Vector/i18n/tyv.json
deleted file mode 100644 (file)
index fbfb8e9..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Agilight",
-                       "Sborsody"
-               ]
-       },
-       "skinname-vector": "Вектор",
-       "vector-action-addsection": "Кол сөстү немелээри",
-       "vector-action-delete": "Ырадыры",
-       "vector-action-move": "Шимчээри",
-       "vector-action-protect": "Камгалаары",
-       "vector-action-undelete": "Эгидер",
-       "vector-action-unprotect": "Камгалалды өскертири",
-       "vector-view-create": "Чаяары",
-       "vector-view-edit": "Эдер",
-       "vector-view-history": "Төөгүнү көөрү",
-       "vector-view-view": "Номчуур",
-       "vector-view-viewsource": "Дөзү бижиин көөрү"
-}
diff --git a/skins/Vector/i18n/tzm.json b/skins/Vector/i18n/tzm.json
deleted file mode 100644 (file)
index ed7ef13..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Moha",
-                       "Tifinaghes"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector-action-addsection": "ⵔⵏⵓ ⴰⵙⵏⵜⵍ",
-       "vector-action-delete": "ⵓⴽⵓⵙ",
-       "vector-action-move": "ⵙⵎⵓⵜⵜⵉ",
-       "vector-action-undelete": "ⵙⵙⵓⵖⴰⵍ ⵓⴽⵓⵙ",
-       "vector-action-unprotect": "ⴱⴷⴷⴻⵍ ⵜⴰⵙⵜⴰⵏⵜ",
-       "vector-view-create": "ⴰⵔⴰ",
-       "vector-view-edit": "ⴱⴷⴷⴻⵍ",
-       "vector-view-history": "ⵥⵕ ⴰⵎⵣⵔⵓⵢ",
-       "vector-view-view": "ⵖⵔ",
-       "vector-view-viewsource": "ⵥⵕ ⴰⵖⴱⴰⵍⵓ"
-}
diff --git a/skins/Vector/i18n/udm.json b/skins/Vector/i18n/udm.json
deleted file mode 100644 (file)
index a126329..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Andrewboltachev"
-               ]
-       },
-       "vector-action-addsection": "Выль темаез ватсано",
-       "vector-action-delete": "Быдтоно",
-       "vector-action-move": "Мукет интые выжтыны",
-       "vector-action-protect": "Утьыны",
-       "vector-view-create": "Кылдытоно",
-       "vector-view-edit": "Тупатоно",
-       "vector-view-history": "История",
-       "vector-view-view": "Лыдӟоно",
-       "vector-view-viewsource": "Кодзэ учкыны"
-}
diff --git a/skins/Vector/i18n/ug-arab.json b/skins/Vector/i18n/ug-arab.json
deleted file mode 100644 (file)
index 00bf7df..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Arlin",
-                       "Sahran",
-                       "Tel'et"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector.css": "/* CSS placed here will affect users of the Vector skin */",
-       "vector.js": "/* Any JavaScript here will be loaded for users using the Vector skin */",
-       "vector-action-addsection": "يېڭى تېما قوش",
-       "vector-action-delete": "ئۆچۈر",
-       "vector-action-move": "يۆتكە",
-       "vector-action-protect": "قوغدا",
-       "vector-action-undelete": "ئەسلىگە قايتۇر",
-       "vector-action-unprotect": "قوغداش ئۆزگەرت",
-       "vector-view-create": "قۇر",
-       "vector-view-edit": "تەھرىر",
-       "vector-view-history": "تارىخ كۆرسەت",
-       "vector-view-view": "ئوقۇ",
-       "vector-view-viewsource": "مەنبەنى كۆرسەت"
-}
diff --git a/skins/Vector/i18n/uk.json b/skins/Vector/i18n/uk.json
deleted file mode 100644 (file)
index 2bf1407..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "AS",
-                       "Ahonc",
-                       "Base",
-                       "Calak",
-                       "Dim Grits",
-                       "NickK",
-                       "Prima klasy4na",
-                       "Тест",
-                       "Ата"
-               ]
-       },
-       "skinname-vector": "Векторне",
-       "vector-skin-desc": "Сучасна версія MonoBook зі свіжим виглядом і багатьма зручними покращеннями",
-       "vector.css": "/* Розміщений тут CSS-код буде використаний в темі оформлення Векторне */",
-       "vector.js": "/* Розміщений тут код JavaScript буде завантажений для всіх користувачів, що використовують векторну тему оформлення */",
-       "vector-action-addsection": "Додати тему",
-       "vector-action-delete": "Вилучити",
-       "vector-action-move": "Перейменувати",
-       "vector-action-protect": "Захистити",
-       "vector-action-undelete": "Відновити",
-       "vector-action-unprotect": "Зміна захисту",
-       "vector-view-create": "Створити",
-       "vector-view-edit": "Редагувати",
-       "vector-view-history": "Переглянути історію",
-       "vector-view-view": "Читати",
-       "vector-view-viewsource": "Переглянути код",
-       "vector-more-actions": "Більше"
-}
diff --git a/skins/Vector/i18n/ur.json b/skins/Vector/i18n/ur.json
deleted file mode 100644 (file)
index 595477e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Calak",
-                       "Istabani",
-                       "Noor2020",
-                       "Tahir mq",
-                       "محبوب عالم"
-               ]
-       },
-       "vector-action-addsection": "نیا موضوع",
-       "vector-action-delete": "حذف کرو",
-       "vector-action-move": "منتقل کرو",
-       "vector-action-protect": "محفوظ کرو",
-       "vector-action-undelete": "بحال",
-       "vector-action-unprotect": "تحفظ میں تبدیلی",
-       "vector-view-create": "تخلیق",
-       "vector-view-edit": "ترمیم",
-       "vector-view-history": "تاریخ",
-       "vector-view-view": "مطالعہ",
-       "vector-view-viewsource": "مسودہ",
-       "vector-more-actions": "زیادہ"
-}
diff --git a/skins/Vector/i18n/uz.json b/skins/Vector/i18n/uz.json
deleted file mode 100644 (file)
index ee75d39..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Abdulla",
-                       "Arystanbek",
-                       "Casual",
-                       "CoderSI",
-                       "Sociologist"
-               ]
-       },
-       "skinname-vector": "Vektor",
-       "vector-action-addsection": "Mavzu qoʻshish",
-       "vector-action-delete": "O‘chirish",
-       "vector-action-move": "Ko‘chirish",
-       "vector-action-protect": "Himoyalash",
-       "vector-action-undelete": "Tiklash",
-       "vector-action-unprotect": "Himoyalashni oʻzgartirish",
-       "vector-view-create": "Yaratish",
-       "vector-view-edit": "Tahrirlash",
-       "vector-view-history": "Tarix",
-       "vector-view-view": "Mutolaa",
-       "vector-view-viewsource": "Manbasini koʻrish",
-       "vector-more-actions": "Yana"
-}
diff --git a/skins/Vector/i18n/vec.json b/skins/Vector/i18n/vec.json
deleted file mode 100644 (file)
index 9622828..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Alunardon90",
-                       "Candalua",
-                       "Frigotoni",
-                       "GatoSelvadego",
-                       "Vajotwo"
-               ]
-       },
-       "vector-action-addsection": "Zonta discusion",
-       "vector-action-delete": "Scanseła",
-       "vector-action-move": "Sposta",
-       "vector-action-protect": "Protezi",
-       "vector-action-undelete": "Recupera",
-       "vector-action-unprotect": "Canbia ła protesion",
-       "vector-view-create": "Crea",
-       "vector-view-edit": "Canbia",
-       "vector-view-history": "Varda ła storia",
-       "vector-view-view": "Lezi",
-       "vector-view-viewsource": "Varda el testo"
-}
diff --git a/skins/Vector/i18n/vep.json b/skins/Vector/i18n/vep.json
deleted file mode 100644 (file)
index 00f876c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Игорь Бродский"
-               ]
-       },
-       "vector-action-addsection": "Ližada tem",
-       "vector-action-delete": "Čuta poiš",
-       "vector-action-move": "Udesnimitada",
-       "vector-action-protect": "Kaita",
-       "vector-action-undelete": "Pördutada",
-       "vector-action-unprotect": "Toižetada kaičend",
-       "vector-view-create": "Säta",
-       "vector-view-edit": "Redaktiruida",
-       "vector-view-history": "Kacta istorii",
-       "vector-view-view": "Lugeda",
-       "vector-view-viewsource": "Kacta purtkehe"
-}
diff --git a/skins/Vector/i18n/vi.json b/skins/Vector/i18n/vi.json
deleted file mode 100644 (file)
index a59d9b4..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Minh Nguyen",
-                       "Vinhtantran",
-                       "Withoutaname"
-               ]
-       },
-       "skinname-vector": "Vectơ",
-       "vector-skin-desc": "Giao diện làm lại từ MonoBook có màu tươi và khả dụng hơn",
-       "vector.css": "/* Mã CSS đặt ở đây sẽ ảnh hưởng đến thành viên sử dụng giao diện Vectơ */",
-       "vector.js": "/* Mã JavaScript tại đây sẽ được tải khi người dùng sử dụng giao diện Vectơ */",
-       "vector-action-addsection": "Thêm chủ đề",
-       "vector-action-delete": "Xóa",
-       "vector-action-move": "Di chuyển",
-       "vector-action-protect": "Khóa",
-       "vector-action-undelete": "Phục hồi",
-       "vector-action-unprotect": "Đổi mức khóa",
-       "vector-view-create": "Tạo",
-       "vector-view-edit": "Sửa đổi",
-       "vector-view-history": "Xem lịch sử",
-       "vector-view-view": "Đọc",
-       "vector-view-viewsource": "Xem mã nguồn",
-       "vector-more-actions": "Khác"
-}
diff --git a/skins/Vector/i18n/vls.json b/skins/Vector/i18n/vls.json
deleted file mode 100644 (file)
index c2b841c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "DasRakel"
-               ]
-       },
-       "vector-action-delete": "Wegdoen",
-       "vector-action-move": "Ernoemn",
-       "vector-view-create": "Anmoakn",
-       "vector-view-edit": "Bewerkn",
-       "vector-view-history": "Geschiedenisse bekykn",
-       "vector-view-view": "Leezn",
-       "vector-view-viewsource": "Brontekst bekykn"
-}
diff --git a/skins/Vector/i18n/vmf.json b/skins/Vector/i18n/vmf.json
deleted file mode 100644 (file)
index 439e93a..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Silvicola"
-               ]
-       },
-       "vector.css": "/* CSS hiir beâjflusd nôr dii Vector-schelfn. Wen'd ale uf ôômôôl beâjflusn wilsch, muâsch an MediaWiki:Common.css was ändârn. */",
-       "vector-action-addsection": "Ân najn abschnid ôôfangn",
-       "vector-action-delete": "Leschn",
-       "vector-action-move": "Umdaafn",
-       "vector-action-protect": "Schidsn",
-       "vector-action-undelete": "Leschn riggängich machn",
-       "vector-action-unprotect": "Schuds ufgeebn",
-       "vector-view-create": "Ôôleechn",
-       "vector-view-edit": "Bearbajdn",
-       "vector-view-history": "Wärsjoonsfolche",
-       "vector-view-view": "Leesn",
-       "vector-view-viewsource": "Gwäl-dhägsd ôôgugn"
-}
diff --git a/skins/Vector/i18n/vo.json b/skins/Vector/i18n/vo.json
deleted file mode 100644 (file)
index 1bd3042..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Malafaya"
-               ]
-       },
-       "vector-action-addsection": "Lüükön yegädi",
-       "vector-action-delete": "Moükön",
-       "vector-action-move": "Topätükön",
-       "vector-action-protect": "Jelön",
-       "vector-action-undelete": "Sämoükön",
-       "vector-action-unprotect": "Votükön jeli",
-       "vector-view-create": "Jafön",
-       "vector-view-edit": "Redakön",
-       "vector-view-history": "Logön jenotemi",
-       "vector-view-view": "Reidön",
-       "vector-view-viewsource": "Logön fonäti"
-}
diff --git a/skins/Vector/i18n/vot.json b/skins/Vector/i18n/vot.json
deleted file mode 100644 (file)
index 7bdc92d..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Paivud"
-               ]
-       },
-       "vector-action-addsection": "Vassõn teema",
-       "vector-action-delete": "Pühi",
-       "vector-action-move": "Liikut",
-       "vector-action-protect": "Varjaa",
-       "vector-view-create": "Loo cülci",
-       "vector-view-edit": "Muuttaa",
-       "vector-view-history": "Istori",
-       "vector-view-view": "Lukõa",
-       "vector-view-viewsource": "Lähtekoodi"
-}
diff --git a/skins/Vector/i18n/vro.json b/skins/Vector/i18n/vro.json
deleted file mode 100644 (file)
index a6c3c06..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Võrok"
-               ]
-       },
-       "vector-action-addsection": "Vahtsõ teema ülespandminõ",
-       "vector-action-delete": "Kistudaq ärq",
-       "vector-action-move": "Nõstaq ümbre",
-       "vector-action-protect": "Kaidsaq",
-       "vector-action-undelete": "Tiiq tagasi",
-       "vector-action-unprotect": "Muudaq kaidsõt",
-       "vector-view-create": "Luuq",
-       "vector-view-edit": "Toimõndaq",
-       "vector-view-history": "Näütäq aoluku",
-       "vector-view-view": "Loeq",
-       "vector-view-viewsource": "Kaeq lätteteksti"
-}
diff --git a/skins/Vector/i18n/wa.json b/skins/Vector/i18n/wa.json
deleted file mode 100644 (file)
index 0401884..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Srtxg"
-               ]
-       },
-       "vector-action-addsection": "Radjouter on sudjet",
-       "vector-action-delete": "Disfacer",
-       "vector-action-move": "Displaecî",
-       "vector-action-protect": "Protedjî",
-       "vector-action-undelete": "Rapexhî",
-       "vector-action-unprotect": "Candjî l' protedjaedje",
-       "vector-view-create": "Ahiver",
-       "vector-view-edit": "Candjî",
-       "vector-view-history": "Vey l' istwere",
-       "vector-view-view": "Lére",
-       "vector-view-viewsource": "Vey côde sourdant"
-}
diff --git a/skins/Vector/i18n/war.json b/skins/Vector/i18n/war.json
deleted file mode 100644 (file)
index 8b2f958..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Harvzsf",
-                       "JinJian"
-               ]
-       },
-       "vector-action-addsection": "Igdugang hin himangrawon",
-       "vector-action-delete": "Para-a",
-       "vector-action-move": "Balhina",
-       "vector-action-protect": "Panalipda",
-       "vector-action-undelete": "Igbalik an ginpara",
-       "vector-action-unprotect": "Liwani an panalipod",
-       "vector-view-create": "Himo-a",
-       "vector-view-edit": "Igliwat",
-       "vector-view-history": "Kitaa an kaagi",
-       "vector-view-view": "Basaha",
-       "vector-view-viewsource": "Kitaa an ginkuhaan",
-       "vector-more-actions": "Damo pa"
-}
diff --git a/skins/Vector/i18n/wo.json b/skins/Vector/i18n/wo.json
deleted file mode 100644 (file)
index 5d248d1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ibou"
-               ]
-       },
-       "vector-action-addsection": "Yokkuw tëriit",
-       "vector-action-delete": "Far",
-       "vector-action-move": "Tuddewaat",
-       "vector-action-protect": "Aar",
-       "vector-action-undelete": "Delloowaat",
-       "vector-action-unprotect": "Aaradi",
-       "vector-view-create": "Sos",
-       "vector-view-edit": "Soppi",
-       "vector-view-history": "Wone jaar-jaaram",
-       "vector-view-view": "Jàng",
-       "vector-view-viewsource": "Wone gongikuwaayam"
-}
diff --git a/skins/Vector/i18n/wuu.json b/skins/Vector/i18n/wuu.json
deleted file mode 100644 (file)
index dade0ff..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Benojan"
-               ]
-       },
-       "vector-action-addsection": "加話題",
-       "vector-action-delete": "刪",
-       "vector-action-move": "移",
-       "vector-action-protect": "保",
-       "vector-action-undelete": "弗刪",
-       "vector-action-unprotect": "换保护状态",
-       "vector-view-create": "建",
-       "vector-view-edit": "编",
-       "vector-view-history": "望页史",
-       "vector-view-view": "读",
-       "vector-view-viewsource": "望源码"
-}
diff --git a/skins/Vector/i18n/xal.json b/skins/Vector/i18n/xal.json
deleted file mode 100644 (file)
index b57aad7..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Huuchin"
-               ]
-       },
-       "vector-action-addsection": "Төриг немх",
-       "vector-action-delete": "Һарһх",
-       "vector-action-move": "Көндәх",
-       "vector-action-protect": "Харсх",
-       "vector-action-undelete": "Һарһх биш",
-       "vector-action-unprotect": "Харсх биш",
-       "vector-view-create": "Бүтәх",
-       "vector-view-edit": "Чиклх",
-       "vector-view-history": "Тууҗин хәләвр",
-       "vector-view-view": "Умшлһн",
-       "vector-view-viewsource": "Темдгллһнә хәләвр"
-}
diff --git a/skins/Vector/i18n/xh.json b/skins/Vector/i18n/xh.json
deleted file mode 100644 (file)
index 8cea054..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "vector-view-edit": "Tshintsha"
-}
diff --git a/skins/Vector/i18n/xmf.json b/skins/Vector/i18n/xmf.json
deleted file mode 100644 (file)
index 47cee05..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Kilavagora",
-                       "Lika2672",
-                       "Machirkholi"
-               ]
-       },
-       "vector-action-addsection": "თემაშ მიშაძინა",
-       "vector-action-delete": "ლასუა",
-       "vector-action-move": "გინოღალა",
-       "vector-action-protect": "თხილუა",
-       "vector-view-create": "დორსხუაფა",
-       "vector-view-edit": "რედაქტირაფა",
-       "vector-view-history": "ისტორიაშ ძირაფა",
-       "vector-view-view": "კითხირი",
-       "vector-view-viewsource": "ქიძირე წყუ"
-}
diff --git a/skins/Vector/i18n/yi.json b/skins/Vector/i18n/yi.json
deleted file mode 100644 (file)
index 16907ad..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Joystick",
-                       "פוילישער"
-               ]
-       },
-       "skinname-vector": "וועקטאר",
-       "vector-skin-desc": "מאדערנע ווערסיע פון מאנאבוק מיט פרישן אויסזען און א סך באניצער־פריינדלעכקייט פארבעסערונגען",
-       "vector.css": "/* CSS געשטעלט דא ווירקט נאר אויפן וועקטאר סקין */",
-       "vector-action-addsection": "צושטעלן טעמע",
-       "vector-action-delete": "אויסמעקן",
-       "vector-action-move": "באַוועגן",
-       "vector-action-protect": "שיצן",
-       "vector-action-undelete": "מבטל זיין אויסמעקן",
-       "vector-action-unprotect": "ענדערונג באַשיצונג",
-       "vector-view-create": "שאַפֿן",
-       "vector-view-edit": "רעדאַקטירן",
-       "vector-view-history": "ווײַזן היסטאָריע",
-       "vector-view-view": "לייענען",
-       "vector-view-viewsource": "ווײַזן מקור",
-       "vector-more-actions": "נאך"
-}
diff --git a/skins/Vector/i18n/yo.json b/skins/Vector/i18n/yo.json
deleted file mode 100644 (file)
index e26e68b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Demmy"
-               ]
-       },
-       "vector-action-addsection": "Àfikún orí-ọ̀rọ̀",
-       "vector-action-delete": "Ìparẹ́",
-       "vector-action-move": "Ìyípòdà",
-       "vector-action-protect": "Àbò",
-       "vector-action-undelete": "Ìmúkúrò ìparẹ́",
-       "vector-action-unprotect": "Ìyípadà àbò",
-       "vector-view-create": "Ṣ'èdá",
-       "vector-view-edit": "Àtúnṣe",
-       "vector-view-history": "Wo ìtàn",
-       "vector-view-view": "Àwòkà",
-       "vector-view-viewsource": "Wo àmìọ̀rọ̀"
-}
diff --git a/skins/Vector/i18n/yue.json b/skins/Vector/i18n/yue.json
deleted file mode 100644 (file)
index 3aa2309..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ktchankt",
-                       "Waihorace"
-               ]
-       },
-       "skinname-vector": "Vector",
-       "vector.css": "/* 響呢度放 CSS 碼去改用戶用嘅域達畫面 */",
-       "vector.js": "/* 響每一次個頁面載入時,用域達畫面嘅用戶都會載入呢度任何嘅JavaScript */",
-       "vector-action-addsection": "加主題",
-       "vector-action-delete": "剷走",
-       "vector-action-move": "搬",
-       "vector-action-protect": "保護",
-       "vector-action-undelete": "取消剷走",
-       "vector-action-unprotect": "改保護",
-       "vector-view-create": "開",
-       "vector-view-edit": "改",
-       "vector-view-history": "睇吓歷史",
-       "vector-view-view": "閱",
-       "vector-view-viewsource": "睇吓原始碼",
-       "vector-more-actions": "更多"
-}
diff --git a/skins/Vector/i18n/za.json b/skins/Vector/i18n/za.json
deleted file mode 100644 (file)
index 72bd20d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Biŋhai"
-               ]
-       },
-       "vector-action-delete": "Ca",
-       "vector-action-move": "Daen",
-       "vector-action-protect": "Bauj",
-       "vector-view-create": "Laeb",
-       "vector-view-edit": "gaij",
-       "vector-view-history": "Cazyawj lizsij"
-}
diff --git a/skins/Vector/i18n/zea.json b/skins/Vector/i18n/zea.json
deleted file mode 100644 (file)
index d0f9aab..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Ooswesthoesbes"
-               ]
-       },
-       "vector-action-addsection": "Voeg kopje toe",
-       "vector-action-delete": "Wissen",
-       "vector-action-move": "Verschuuf",
-       "vector-action-protect": "Bescherm",
-       "vector-action-undelete": "Plaets truhhe",
-       "vector-action-unprotect": "Beveiligienge anpass'n",
-       "vector-view-create": "Anmaeken",
-       "vector-view-edit": "Bewerk",
-       "vector-view-history": "Geschiedenisse bekiek'n",
-       "vector-view-view": "Lezen",
-       "vector-view-viewsource": "Brontekst bekieken"
-}
diff --git a/skins/Vector/i18n/zh-hans.json b/skins/Vector/i18n/zh-hans.json
deleted file mode 100644 (file)
index 8e3536f..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Hydra",
-                       "Liangent",
-                       "Liuxinyu970226",
-                       "Xiaomingyan",
-                       "Cwek"
-               ]
-       },
-       "vector-skin-desc": "提供清新的外观和许多可用性改进的现代版MonoBook",
-       "vector.css": "/* 放置于这里的CSS将影响使用Vector皮肤的用户 */",
-       "vector.js": "/* 这里的任何JavaScript将为使用Vector皮肤的用户加载 */",
-       "vector-action-addsection": "添加话题",
-       "vector-action-delete": "删除",
-       "vector-action-move": "移动",
-       "vector-action-protect": "保护",
-       "vector-action-undelete": "还原",
-       "vector-action-unprotect": "更改保护",
-       "vector-view-create": "创建",
-       "vector-view-edit": "编辑",
-       "vector-view-history": "查看历史",
-       "vector-view-view": "阅读",
-       "vector-view-viewsource": "查看源代码",
-       "vector-more-actions": "更多"
-}
diff --git a/skins/Vector/i18n/zh-hant.json b/skins/Vector/i18n/zh-hant.json
deleted file mode 100644 (file)
index 3e67c21..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-       "@metadata": {
-               "authors": [
-                       "Cwlin0416",
-                       "Justincheng12345",
-                       "Liuxinyu970226",
-                       "Mark85296341"
-               ]
-       },
-       "vector.css": "/* 此 CSS 會影響使用 Vector 介面外觀的使用者 */",
-       "vector.js": "/* 此 JavaScript 會用於使用 Vector 介面外觀使用者 */",
-       "vector-action-addsection": "加入主題",
-       "vector-action-delete": "刪除",
-       "vector-action-move": "移動",
-       "vector-action-protect": "保護",
-       "vector-action-undelete": "取消刪除",
-       "vector-action-unprotect": "變更保護",
-       "vector-view-create": "建立",
-       "vector-view-edit": "編輯",
-       "vector-view-history": "檢視歷史",
-       "vector-view-view": "閱讀",
-       "vector-view-viewsource": "檢視原始碼",
-       "vector-more-actions": "更多"
-}
diff --git a/skins/Vector/images/arrow-collapsed-ltr.png b/skins/Vector/images/arrow-collapsed-ltr.png
deleted file mode 100644 (file)
index 063ac6f..0000000
Binary files a/skins/Vector/images/arrow-collapsed-ltr.png and /dev/null differ
diff --git a/skins/Vector/images/arrow-collapsed-ltr.svg b/skins/Vector/images/arrow-collapsed-ltr.svg
deleted file mode 100644 (file)
index b943caa..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M6.001 2.998l5.001 5-5.001 5z" fill="#797979"/></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/arrow-collapsed-rtl.png b/skins/Vector/images/arrow-collapsed-rtl.png
deleted file mode 100644 (file)
index c346218..0000000
Binary files a/skins/Vector/images/arrow-collapsed-rtl.png and /dev/null differ
diff --git a/skins/Vector/images/arrow-collapsed-rtl.svg b/skins/Vector/images/arrow-collapsed-rtl.svg
deleted file mode 100644 (file)
index 5faf356..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M9.999 13.002l-5.001-5 5.001-5z" fill="#797979"/></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/arrow-down-focus-icon.png b/skins/Vector/images/arrow-down-focus-icon.png
deleted file mode 100644 (file)
index 7640bd1..0000000
Binary files a/skins/Vector/images/arrow-down-focus-icon.png and /dev/null differ
diff --git a/skins/Vector/images/arrow-down-focus-icon.svg b/skins/Vector/images/arrow-down-focus-icon.svg
deleted file mode 100644 (file)
index 826c280..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="22" height="16"><path d="M15.502 6.001l-5 5.001-5-5.001z" fill="#929292"/></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/arrow-down-icon.png b/skins/Vector/images/arrow-down-icon.png
deleted file mode 100644 (file)
index 12e3b93..0000000
Binary files a/skins/Vector/images/arrow-down-icon.png and /dev/null differ
diff --git a/skins/Vector/images/arrow-down-icon.svg b/skins/Vector/images/arrow-down-icon.svg
deleted file mode 100644 (file)
index 8e31b2f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="22" height="16"><path d="M15.502 6.001l-5 5.001-5-5.001z" fill="#797979"/></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/arrow-expanded.png b/skins/Vector/images/arrow-expanded.png
deleted file mode 100644 (file)
index 0221028..0000000
Binary files a/skins/Vector/images/arrow-expanded.png and /dev/null differ
diff --git a/skins/Vector/images/arrow-expanded.svg b/skins/Vector/images/arrow-expanded.svg
deleted file mode 100644 (file)
index e744ec3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13.002 6.001l-5 5.001-5-5.001z" fill="#797979"/></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/bullet-icon.png b/skins/Vector/images/bullet-icon.png
deleted file mode 100644 (file)
index 7bae98f..0000000
Binary files a/skins/Vector/images/bullet-icon.png and /dev/null differ
diff --git a/skins/Vector/images/external-link-ltr-icon.png b/skins/Vector/images/external-link-ltr-icon.png
deleted file mode 100644 (file)
index 6308383..0000000
Binary files a/skins/Vector/images/external-link-ltr-icon.png and /dev/null differ
diff --git a/skins/Vector/images/external-link-ltr-icon.svg b/skins/Vector/images/external-link-ltr-icon.svg
deleted file mode 100644 (file)
index 5969d03..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"><g transform="translate(-826.429 -698.791)"><rect width="5.982" height="5.982" x="826.929" y="702.309" fill="#fff" stroke="#06c"/><g><path d="M831.194 698.791h5.234v5.391l-1.571 1.545-1.31-1.31-2.725 2.725-2.689-2.689 2.808-2.808-1.311-1.311z" fill="#06f"/><path d="M835.424 699.795l.022 4.885-1.817-1.817-2.881 2.881-1.228-1.228 2.881-2.881-1.851-1.851z" fill="#fff"/></g></g></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/external-link-rtl-icon.png b/skins/Vector/images/external-link-rtl-icon.png
deleted file mode 100644 (file)
index 5313234..0000000
Binary files a/skins/Vector/images/external-link-rtl-icon.png and /dev/null differ
diff --git a/skins/Vector/images/external-link-rtl-icon.svg b/skins/Vector/images/external-link-rtl-icon.svg
deleted file mode 100644 (file)
index 75a7025..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"><g transform="translate(-826.429 -698.791)"><rect width="5.982" height="5.982" x="-835.929" y="702.309" transform="scale(-1 1)" fill="#fff" stroke="#06c"/><g><path d="M831.663 698.791h-5.234v5.391l1.571 1.545 1.31-1.31 2.725 2.725 2.689-2.689-2.808-2.808 1.311-1.311z" fill="#06f"/><path d="M827.433 699.795l-.022 4.885 1.817-1.817 2.881 2.881 1.228-1.228-2.881-2.881 1.851-1.851z" fill="#fff"/></g></g></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/link-icon.png b/skins/Vector/images/link-icon.png
deleted file mode 100644 (file)
index b70efaa..0000000
Binary files a/skins/Vector/images/link-icon.png and /dev/null differ
diff --git a/skins/Vector/images/magnify-clip.png b/skins/Vector/images/magnify-clip.png
deleted file mode 100644 (file)
index 00a9cee..0000000
Binary files a/skins/Vector/images/magnify-clip.png and /dev/null differ
diff --git a/skins/Vector/images/page-fade.png b/skins/Vector/images/page-fade.png
deleted file mode 100644 (file)
index b4a6034..0000000
Binary files a/skins/Vector/images/page-fade.png and /dev/null differ
diff --git a/skins/Vector/images/portal-break-ltr.png b/skins/Vector/images/portal-break-ltr.png
deleted file mode 100644 (file)
index 20bf366..0000000
Binary files a/skins/Vector/images/portal-break-ltr.png and /dev/null differ
diff --git a/skins/Vector/images/portal-break-rtl.png b/skins/Vector/images/portal-break-rtl.png
deleted file mode 100644 (file)
index e5f6223..0000000
Binary files a/skins/Vector/images/portal-break-rtl.png and /dev/null differ
diff --git a/skins/Vector/images/portal-break.png b/skins/Vector/images/portal-break.png
deleted file mode 100644 (file)
index 90c3918..0000000
Binary files a/skins/Vector/images/portal-break.png and /dev/null differ
diff --git a/skins/Vector/images/preferences/break.png b/skins/Vector/images/preferences/break.png
deleted file mode 100644 (file)
index b529308..0000000
Binary files a/skins/Vector/images/preferences/break.png and /dev/null differ
diff --git a/skins/Vector/images/preferences/fade.png b/skins/Vector/images/preferences/fade.png
deleted file mode 100644 (file)
index 638084d..0000000
Binary files a/skins/Vector/images/preferences/fade.png and /dev/null differ
diff --git a/skins/Vector/images/search-fade.png b/skins/Vector/images/search-fade.png
deleted file mode 100644 (file)
index 6cb7d28..0000000
Binary files a/skins/Vector/images/search-fade.png and /dev/null differ
diff --git a/skins/Vector/images/search-ltr.png b/skins/Vector/images/search-ltr.png
deleted file mode 100644 (file)
index 1db2eb2..0000000
Binary files a/skins/Vector/images/search-ltr.png and /dev/null differ
diff --git a/skins/Vector/images/search-ltr.svg b/skins/Vector/images/search-ltr.svg
deleted file mode 100644 (file)
index 0720f20..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#6c6c6c" fill="none"><path d="M11.29 11.71l-4-4"/><circle cx="5" cy="5" r="4"/></g></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/search-rtl.png b/skins/Vector/images/search-rtl.png
deleted file mode 100644 (file)
index c26c8d0..0000000
Binary files a/skins/Vector/images/search-rtl.png and /dev/null differ
diff --git a/skins/Vector/images/search-rtl.svg b/skins/Vector/images/search-rtl.svg
deleted file mode 100644 (file)
index 622d5f9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#6c6c6c" fill="none"><path d="M.71 11.71l4-4"/><circle cx="7" cy="5" r="4"/></g></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/tab-break.png b/skins/Vector/images/tab-break.png
deleted file mode 100644 (file)
index 6d37af5..0000000
Binary files a/skins/Vector/images/tab-break.png and /dev/null differ
diff --git a/skins/Vector/images/tab-current-fade.png b/skins/Vector/images/tab-current-fade.png
deleted file mode 100644 (file)
index b8f772f..0000000
Binary files a/skins/Vector/images/tab-current-fade.png and /dev/null differ
diff --git a/skins/Vector/images/tab-normal-fade.png b/skins/Vector/images/tab-normal-fade.png
deleted file mode 100644 (file)
index f719a88..0000000
Binary files a/skins/Vector/images/tab-normal-fade.png and /dev/null differ
diff --git a/skins/Vector/images/unwatch-icon-hl.png b/skins/Vector/images/unwatch-icon-hl.png
deleted file mode 100644 (file)
index 6b2b502..0000000
Binary files a/skins/Vector/images/unwatch-icon-hl.png and /dev/null differ
diff --git a/skins/Vector/images/unwatch-icon-hl.svg b/skins/Vector/images/unwatch-icon-hl.svg
deleted file mode 100644 (file)
index d52d547..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><defs><linearGradient id="a"><stop offset="0" stop-color="#c2edff"/><stop offset=".5" stop-color="#68bdff"/><stop offset="1" stop-color="#fff"/></linearGradient><linearGradient x1="13.47" y1="14.363" x2="4.596" y2="3.397" id="b" xlink:href="#a" gradientUnits="userSpaceOnUse"/></defs><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" fill="url(#b)" stroke="#c8b250" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/unwatch-icon.png b/skins/Vector/images/unwatch-icon.png
deleted file mode 100644 (file)
index 9fd9436..0000000
Binary files a/skins/Vector/images/unwatch-icon.png and /dev/null differ
diff --git a/skins/Vector/images/unwatch-icon.svg b/skins/Vector/images/unwatch-icon.svg
deleted file mode 100644 (file)
index cde7bc5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><defs><linearGradient id="a"><stop offset="0" stop-color="#c2edff"/><stop offset=".5" stop-color="#68bdff"/><stop offset="1" stop-color="#fff"/></linearGradient><linearGradient x1="13.47" y1="14.363" x2="4.596" y2="3.397" id="b" xlink:href="#a" gradientUnits="userSpaceOnUse"/></defs><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" fill="url(#b)" stroke="#7cb5d1" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/user-icon.png b/skins/Vector/images/user-icon.png
deleted file mode 100644 (file)
index 57f9f8d..0000000
Binary files a/skins/Vector/images/user-icon.png and /dev/null differ
diff --git a/skins/Vector/images/user-icon.svg b/skins/Vector/images/user-icon.svg
deleted file mode 100644 (file)
index 4335bcf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="13.837"><defs><linearGradient id="e"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#3b74bc"/><stop offset="1" stop-color="#2d5990"/></linearGradient><linearGradient id="c"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#c9c9c9"/></linearGradient><linearGradient id="a"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="d"><stop offset="0" stop-color="#f4d9b1"/><stop offset="1" stop-color="#df9725"/></linearGradient><radialGradient cx="31.113" cy="19.009" r="8.662" fx="31.113" fy="19.009" id="f" xlink:href="#a" gradientUnits="userSpaceOnUse"/><radialGradient cx="28.09" cy="27.203" r="13.565" fx="28.09" fy="27.203" id="g" xlink:href="#b" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.298 0 0 .885 -8.359 4.94)"/><linearGradient x1="30.936" y1="29.553" x2="30.936" y2="35.803" id="h" xlink:href="#c" gradientUnits="userSpaceOnUse"/><radialGradient cx="31.113" cy="19.009" r="8.662" fx="31.113" fy="19.009" id="i" xlink:href="#a" gradientUnits="userSpaceOnUse"/><radialGradient cx="29.345" cy="17.064" r="9.162" fx="29.345" fy="17.064" id="j" xlink:href="#d" gradientUnits="userSpaceOnUse" gradientTransform="matrix(.788 0 0 .788 6.221 3.618)"/><linearGradient x1="20.662" y1="35.818" x2="22.627" y2="36.218" id="k" xlink:href="#e" gradientUnits="userSpaceOnUse" gradientTransform="matrix(.983 .182 -.182 .983 6.232 -2.651)"/><linearGradient x1="22.687" y1="36.39" x2="21.408" y2="35.74" id="l" xlink:href="#e" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-.978 .21 .21 .978 55.11 -3.945)"/></defs><g color="#000"><path d="M39.775 19.009a8.662 8.662 0 1 1-17.324 0 8.662 8.662 0 1 1 17.324 0z" transform="matrix(.693 0 0 .374 -15.548 3.481)" fill="url(#f)" fill-rule="evenodd" overflow="visible"/><path d="M4.046 12.398h4.137c1.172 0 2.332-.43 2.758-1.655.404-1.163.069-3.378-2.551-5.171h-4.895c-2.62 1.655-2.947 3.917-2.344 5.24.614 1.347 1.655 1.586 2.896 1.586z" fill="url(#g)" fill-rule="evenodd" stroke="#204a87" stroke-linecap="round" stroke-linejoin="round" overflow="visible" stroke-width="0.39"/><path d="M4.321 6.193c1.241 1.103 1.793 5.102 1.793 5.102s.552-3.999 1.517-5.171l-3.309.069z" fill="url(#h)" fill-rule="evenodd" overflow="visible"/><path d="M5.21 6.607s-.839.648-.767 1.428c-.796-.702-.819-2.048-.819-2.048l1.586.62z" fill="#729fcf" fill-rule="evenodd" overflow="visible"/><path d="M4.018 11.992l4.092-.009c1.029 0 2.049-.377 2.422-1.453.355-1.022-.037-2.967-2.338-4.542l-4.495-.095c-2.301 1.453-2.747 3.441-2.208 4.697.538 1.256 1.324 1.393 2.526 1.401z" opacity=".215" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" overflow="visible" fill="none" stroke-width="0.39"/><path d="M6.941 6.607s.839.648.767 1.428c.796-.702.819-2.048.819-2.048l-1.586.62z" fill="#729fcf" fill-rule="evenodd" overflow="visible"/><path d="M39.775 19.009a8.662 8.662 0 1 1-17.324 0 8.662 8.662 0 1 1 17.324 0z" transform="matrix(.39 0 0 .39 -6.138 -2.475)" fill="url(#i)" fill-rule="evenodd" overflow="visible"/><path d="M39.775 19.009a8.662 8.662 0 1 1-17.324 0 8.662 8.662 0 1 1 17.324 0z" fill="url(#j)" fill-rule="evenodd" stroke="#c17d11" stroke-linecap="round" stroke-linejoin="round" overflow="visible" transform="matrix(.39 0 0 .39 -6.089 -3.84)"/><path d="M39.775 19.009a8.662 8.662 0 1 1-17.324 0 8.662 8.662 0 1 1 17.324 0z" transform="matrix(.342 0 0 .342 -4.598 -2.929)" opacity=".196" stroke="#fff" stroke-width="1.14" stroke-linecap="round" stroke-linejoin="round" overflow="visible" fill="none"/><path d="M2.433 12.062c-.487-.213-.704-.725-.704-.725.328-1.587 1.451-2.748 1.451-2.748s-.889 2.5-.746 3.473z" opacity=".228" fill="url(#k)" fill-rule="evenodd" overflow="visible"/><path d="M9.806 11.728c.48-.227.704-.781.704-.781-.374-1.577-1.551-2.669-1.551-2.669s.961 2.474.847 3.45z" opacity=".228" fill="url(#l)" fill-rule="evenodd" overflow="visible"/></g></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/watch-icon-hl.png b/skins/Vector/images/watch-icon-hl.png
deleted file mode 100644 (file)
index 4cb87cd..0000000
Binary files a/skins/Vector/images/watch-icon-hl.png and /dev/null differ
diff --git a/skins/Vector/images/watch-icon-hl.svg b/skins/Vector/images/watch-icon-hl.svg
deleted file mode 100644 (file)
index 664c671..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" fill="#fff" stroke="#c8b250" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/watch-icon-loading.png b/skins/Vector/images/watch-icon-loading.png
deleted file mode 100644 (file)
index 5f0c490..0000000
Binary files a/skins/Vector/images/watch-icon-loading.png and /dev/null differ
diff --git a/skins/Vector/images/watch-icon-loading.svg b/skins/Vector/images/watch-icon-loading.svg
deleted file mode 100644 (file)
index 751eb14..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" fill="#fff" stroke="#d1d1d1" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
diff --git a/skins/Vector/images/watch-icon.png b/skins/Vector/images/watch-icon.png
deleted file mode 100644 (file)
index 39daff2..0000000
Binary files a/skins/Vector/images/watch-icon.png and /dev/null differ
diff --git a/skins/Vector/images/watch-icon.svg b/skins/Vector/images/watch-icon.svg
deleted file mode 100644 (file)
index 907b05b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" fill="#fff" stroke="#7cb5d1" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
diff --git a/skins/Vector/screen-hd.less b/skins/Vector/screen-hd.less
deleted file mode 100644 (file)
index 8b286f4..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Vector screen styles for high definition displays */
-
-@import "variables.less";
-
-div#content {
-       margin-left: 11em;
-       padding: 1.25em 1.5em 1.5em 1.5em;
-}
-#p-logo {
-       left: @menu-main-logo-left;
-}
-div#footer {
-       margin-left: 11em;
-       padding: 1.25em;
-}
-#mw-panel {
-       padding-left: 0.5em;
-}
-#p-search {
-       margin-right: 1em;
-}
-#left-navigation {
-       margin-left: 11em;
-}
-#p-personal {
-       right: 1em;
-}
-#mw-head-base {
-       margin-left: 11em;
-}
diff --git a/skins/Vector/screen.less b/skins/Vector/screen.less
deleted file mode 100644 (file)
index f7b374f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/* Vector screen styles */
-
-@import "variables.less";
-
-@import "components/common.less";
-@import "components/animations.less";
-@import "components/navigation.less";
-@import "components/footer.less";
-@import 'components/notifications.less';
-@import "components/externalLinks.less";
diff --git a/skins/Vector/special.less b/skins/Vector/special.less
deleted file mode 100644 (file)
index 6af4b1e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * Adjusts for decreased margin-bottom for h2 elements inside #content div
- * introduced in March / April 2014 typography update.
- */
-table.mw-specialpages-table {
-       margin-top: 0;
-}
diff --git a/skins/Vector/special.preferences.less b/skins/Vector/special.preferences.less
deleted file mode 100644 (file)
index a9b1006..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-@import "mediawiki.mixins";
-@import "variables";
-
-/**
- * The following code is highly modified from monobook. It would be nice if the
- * preftoc id was more human readable like preferences-toc for instance,
- * howerver this would require backporting the other skins.
- */
-
-#preftoc {
-       /* Tabs */
-       width: 100%;
-       float: left;
-       clear: both;
-       margin: 0 !important;
-       padding: 0 !important;
-       .background-image('images/preferences/break.png');
-       background-position: bottom left;
-       background-repeat: no-repeat;
-
-       li {
-               /* Tab */
-               float: left;
-               margin: 0;
-               padding: 0;
-               padding-right: 1px;
-               height: 2.25em;
-               white-space: nowrap;
-               list-style-type: none;
-               list-style-image: none;
-               .background-image('images/preferences/break.png');
-               background-position: bottom right;
-               background-repeat: no-repeat;
-
-               /* Sadly, IE6 won't understand this */
-               &:first-child {
-                       margin-left: 1px;
-               }
-
-               &.selected {
-                       a {
-                               .background-image('images/preferences/fade.png');
-                               background-position: bottom;
-                               background-repeat: repeat-x;
-                               color: #333;
-                               text-decoration: none;
-                       }
-               }
-       }
-
-       a,
-       a:active {
-               display: inline-block;
-               position: relative;
-               color: @menu-link-color;
-               padding: 0.5em;
-               text-decoration: none;
-               background-image: none;
-               font-size: 0.9em;
-       }
-
-       a:hover,
-       a:focus {
-               text-decoration: underline;
-       }
-}
-
-#preferences {
-       float: left;
-       width: 100%;
-       margin: 0;
-       margin-top: -2px;
-       clear: both;
-       border: solid 1px #ccc;
-       background-color: #fafafa;
-
-       fieldset {
-               border: none;
-               border-top: solid 1px #ccc;
-
-               &.prefsection {
-                       border: none;
-                       padding: 0;
-                       margin: 1em;
-
-                       legend.mainLegend {
-                               display: none;
-                       }
-               }
-       }
-
-       legend {
-               color: #666;
-       }
-
-       td {
-               padding-left: 0.5em;
-               padding-right: 0.5em;
-       }
-
-       div.mw-prefs-buttons {
-               padding: 1em;
-
-               input {
-                       margin-right: 0.25em;
-               }
-       }
-}
-
-.htmlform-tip {
-       font-size: x-small;
-       padding: .2em 2em;
-       color: #666;
-}
diff --git a/skins/Vector/variables.less b/skins/Vector/variables.less
deleted file mode 100644 (file)
index b17d15c..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-@html-font-size: 100%;
-
-// Page content
-// FIXME: Use global variable since Echo and CentralNotice use this variable
-@content-border-color: #a7d7f9;
-// FIXME: Find an open font that works with this stack and is readable by Windows users
-@content-font-family: sans-serif;
-@content-font-color: #252525;
-@content-font-size: 0.875em;
-@content-line-height: 1.6;
-@content-padding: 1em;
-@content-heading-font-size: 1.8em;
-@content-heading-font-family: "Linux Libertine", Georgia, Times, serif;
-@body-background-color: #fff;
-@heading-line-height: 1.3;
-
-// Navigation
-@menu-background-color: #f6f6f6;
-
-// Common menu
-@menu-link-color: #0645ad;
-
-// Main menu
-@menu-main-font-size: inherit;
-
-@menu-main-heading-font-size: 0.75em;
-@menu-main-heading-padding: 0.25em 0 0.25em 0.25em;
-@menu-main-heading-color: #4d4d4d;
-
-@menu-main-body-font-size: 0.75em;
-@menu-main-body-link-color: #0645ad;
-@menu-main-body-link-visited-color: #0b0080;
-@menu-main-body-margin: 0 0 0 1.25em;
-@menu-main-body-padding: 0;
-
-@menu-main-logo-left: 0.5em;
-
-// Personal menu
-@menu-personal-font-size: 0.75em;
diff --git a/skins/Vector/vector.js b/skins/Vector/vector.js
deleted file mode 100644 (file)
index 7be3535..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * Vector-specific scripts
- */
-jQuery( function ( $ ) {
-       /**
-        * Focus search input at the very end
-        */
-       $( '#searchInput' ).attr( 'tabindex', $( document ).lastTabIndex() + 1 );
-
-       /**
-        * Dropdown menu accessibility
-        */
-       $( 'div.vectorMenu' ).each( function () {
-               var $el = $( this );
-               $el.find( '> h3 > a' ).parent()
-                       .attr( 'tabindex', '0' )
-                       // For accessibility, show the menu when the h3 is clicked (bug 24298/46486)
-                       .on( 'click keypress', function ( e ) {
-                               if ( e.type === 'click' || e.which === 13 ) {
-                                       $el.toggleClass( 'menuForceShow' );
-                                       e.preventDefault();
-                               }
-                       } )
-                       // When the heading has focus, also set a class that will change the arrow icon
-                       .focus( function () {
-                               $el.find( '> a' ).addClass( 'vectorMenuFocus' );
-                       } )
-                       .blur( function () {
-                               $el.find( '> a' ).removeClass( 'vectorMenuFocus' );
-                       } )
-                       .find( '> a:first' )
-                       // As the h3 can already be focused there's no need for the link to be focusable
-                       .attr( 'tabindex', '-1' );
-       } );
-
-       /**
-        * Sidebar
-        */
-       $( '#mw-panel > .portal:first' ).addClass( 'first' );
-
-       /**
-        * Collapsible tabs
-        */
-       var $cactions = $( '#p-cactions' ),
-               $tabContainer = $( '#p-views ul' ),
-               originalDropdownWidth = $cactions.width();
-
-       // Bind callback functions to animate our drop down menu in and out
-       // and then call the collapsibleTabs function on the menu
-       $tabContainer
-               .bind( 'beforeTabCollapse', function () {
-                       // If the dropdown was hidden, show it
-                       if ( $cactions.hasClass( 'emptyPortlet' ) ) {
-                               $cactions
-                                       .removeClass( 'emptyPortlet' )
-                                       .find( 'h3' )
-                                               .css( 'width', '1px' ).animate( { 'width': originalDropdownWidth }, 'normal' );
-                       }
-               } )
-               .bind( 'beforeTabExpand', function () {
-                       // If we're removing the last child node right now, hide the dropdown
-                       if ( $cactions.find( 'li' ).length === 1 ) {
-                               $cactions.find( 'h3' ).animate( { 'width': '1px' }, 'normal', function () {
-                                       $( this ).attr( 'style', '' )
-                                               .parent().addClass( 'emptyPortlet' );
-                               });
-                       }
-               } )
-               .collapsibleTabs( {
-                       expandCondition: function ( eleWidth ) {
-                               // (This looks a bit awkward because we're doing expensive queries as late as possible.)
-
-                               var distance = $.collapsibleTabs.calculateTabDistance();
-                               // If there are at least eleWidth + 1 pixels of free space, expand.
-                               // We add 1 because .width() will truncate fractional values but .offset() will not.
-                               if ( distance >= eleWidth + 1 ) {
-                                       return true;
-                               } else {
-                                       // Maybe we can still expand? Account for the width of the "Actions" dropdown if the
-                                       // expansion would hide it.
-                                       if ( $cactions.find( 'li' ).length === 1 ) {
-                                               return distance >= eleWidth + 1 - originalDropdownWidth;
-                                       } else {
-                                               return false;
-                                       }
-                               }
-                       },
-                       collapseCondition: function () {
-                               // (This looks a bit awkward because we're doing expensive queries as late as possible.)
-                               // TODO The dropdown itself should probably "fold" to just the down-arrow (hiding the text)
-                               // if it can't fit on the line?
-
-                               // If there's an overlap, collapse.
-                               if ( $.collapsibleTabs.calculateTabDistance() < 0 ) {
-                                       // But only if the width of the tab to collapse is smaller than the width of the dropdown
-                                       // we would have to insert. An example language where this happens is Lithuanian (lt).
-                                       if ( $cactions.hasClass( 'emptyPortlet' ) ) {
-                                               return $tabContainer.children( 'li.collapsible:last' ).width() > originalDropdownWidth;
-                                       } else {
-                                               return true;
-                                       }
-                               } else {
-                                       return false;
-                               }
-                       }
-               } );
-} );
diff --git a/skins/common/IEFixes.js b/skins/common/IEFixes.js
deleted file mode 100644 (file)
index 545acad..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * IE fixes javascript loaded by wikibits.js for IE <= 6.0
- */
-/*global isMSIE55:true, doneIETransform:true, doneIEAlphaFix:true */
-/*global hookit:true, fixalpha:true */
-( function ( mw, $ ) {
-
-var expandedURLs, hasClass;
-
-// Also returns true for IE6, 7, 8, 9 and 10. createPopup is removed in IE11.
-// Good thing this is only loaded for IE <= 6 by wikibits.
-// Might as well set it to true.
-isMSIE55 = ( window.showModalDialog && window.clipboardData && window.createPopup );
-doneIETransform = false;
-doneIEAlphaFix = false;
-
-hookit = function () {
-       if ( !doneIETransform && document.getElementById && document.getElementById( 'bodyContent' ) ) {
-               doneIETransform = true;
-               fixalpha();
-       }
-};
-
-if ( document.attachEvent ) {
-       document.attachEvent( 'onreadystatechange', hookit );
-}
-
-// png alpha transparency fixes
-fixalpha = function ( logoId ) {
-       // bg
-       if ( isMSIE55 && !doneIEAlphaFix ) {
-               var bg, imageUrl, linkFix, logoa, logospan, plogo;
-               plogo = document.getElementById( logoId || 'p-logo' );
-               if ( !plogo ) {
-                       return;
-               }
-
-               logoa = plogo.getElementsByTagName('a')[0];
-               if ( !logoa ) {
-                       return;
-               }
-
-               bg = logoa.currentStyle.backgroundImage;
-               imageUrl = bg.substring( 5, bg.length - 2 );
-
-               doneIEAlphaFix = true;
-
-               if ( imageUrl.substr( imageUrl.length - 4 ).toLowerCase() === '.png' ) {
-                       logospan = logoa.appendChild( document.createElement( 'span' ) );
-
-                       logoa.style.backgroundImage = 'none';
-                       logospan.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + imageUrl + ')';
-                       logospan.style.height = '100%';
-                       logospan.style.position = 'absolute';
-                       logospan.style.width = logoa.currentStyle.width;
-                       logospan.style.cursor = 'hand';
-                       // Center image with hack for IE5.5
-                       if ( document.documentElement.dir === 'rtl' ) {
-                               logospan.style.right = '50%';
-                               logospan.style.setExpression( 'marginRight', '"-" + (this.offsetWidth / 2) + "px"' );
-                       } else {
-                               logospan.style.left = '50%';
-                               logospan.style.setExpression( 'marginLeft', '"-" + (this.offsetWidth / 2) + "px"' );
-                       }
-                       logospan.style.top = '50%';
-                       logospan.style.setExpression( 'marginTop', '"-" + (this.offsetHeight / 2) + "px"' );
-
-                       linkFix = logoa.appendChild( logoa.cloneNode() );
-                       linkFix.style.position = 'absolute';
-                       linkFix.style.height = '100%';
-                       linkFix.style.width = '100%';
-               }
-       }
-};
-
-if ( isMSIE55 ) {
-       // ondomready
-       $( fixalpha );
-}
-
-// Expand links for printing
-hasClass = function ( classText, classWanted ) {
-       var i = 0, classArr = classText.split(/\s/);
-       for ( i = 0; i < classArr.length; i++ ) {
-               if ( classArr[i].toLowerCase() === classWanted.toLowerCase() ) {
-                       return true;
-               }
-       }
-       return false;
-};
-
-window.onbeforeprint = function () {
-       var allLinks, contentEl, expandedLink, expandedText, i;
-
-       expandedURLs = [];
-       contentEl = document.getElementById( 'content' );
-
-       if ( contentEl ) {
-               allLinks = contentEl.getElementsByTagName( 'a' );
-
-               for ( i = 0; i < allLinks.length; i++ ) {
-                       if ( hasClass( allLinks[i].className, 'external' ) && !hasClass( allLinks[i].className, 'free' ) ) {
-                               expandedLink = document.createElement( 'span' );
-                               expandedText = document.createTextNode( ' (' + allLinks[i].href + ')' );
-                               expandedLink.appendChild( expandedText );
-                               allLinks[i].parentNode.insertBefore( expandedLink, allLinks[i].nextSibling );
-                               expandedURLs[i] = expandedLink;
-                       }
-               }
-       }
-};
-
-window.onafterprint = function () {
-       for ( var i = 0; i < expandedURLs.length; i++ ) {
-               if ( expandedURLs[i] ) {
-                       expandedURLs[i].removeNode( true );
-               }
-       }
-};
-
-}( mediaWiki, jQuery ) );
deleted file mode 100644 (file)
index 6b9464a914398344a7ddcbd239be61441fa68fea..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/**
- * Remote Scripting Library
- * Copyright 2005 modernmethod, inc
- * Under the open source BSD license
- * http://www.modernmethod.com/sajax/
- */
-
-/*jshint camelcase:false */
-/*global alert */
-( function ( mw ) {
-
-/**
- * if sajax_debug_mode is true, this function outputs given the message into
- * the element with id = sajax_debug; if no such element exists in the document,
- * it is injected.
- */
-function debug( text ) {
-       if ( !window.sajax_debug_mode ) {
-               return false;
-       }
-
-       var b, m,
-               e = document.getElementById( 'sajax_debug' );
-
-       if ( !e ) {
-               e = document.createElement( 'p' );
-               e.className = 'sajax_debug';
-               e.id = 'sajax_debug';
-
-               b = document.getElementsByTagName( 'body' )[0];
-
-               if ( b.firstChild ) {
-                       b.insertBefore( e, b.firstChild );
-               } else {
-                       b.appendChild( e );
-               }
-       }
-
-       m = document.createElement( 'div' );
-       m.appendChild( document.createTextNode( text ) );
-
-       e.appendChild( m );
-
-       return true;
-}
-
-/**
- * Compatibility wrapper for creating a new XMLHttpRequest object.
- */
-function createXhr() {
-       debug( 'sajax_init_object() called..' );
-       var a;
-       try {
-               // Try the new style before ActiveX so we don't
-               // unnecessarily trigger warnings in IE 7 when
-               // set to prompt about ActiveX usage
-               a = new XMLHttpRequest();
-       } catch ( xhrE ) {
-               try {
-                       a = new window.ActiveXObject( 'Msxml2.XMLHTTP' );
-               } catch ( msXmlE ) {
-                       try {
-                               a = new window.ActiveXObject( 'Microsoft.XMLHTTP' );
-                       } catch ( msXhrE ) {
-                               a = null;
-                       }
-               }
-       }
-       if ( !a ) {
-               debug( 'Could not create connection object.' );
-       }
-
-       return a;
-}
-
-/**
- * Perform an AJAX call to MediaWiki. Calls are handled by AjaxDispatcher.php
- *   func_name - the name of the function to call. Must be registered in $wgAjaxExportList
- *   args - an array of arguments to that function
- *   target - the target that will handle the result of the call. If this is a function,
- *            if will be called with the XMLHttpRequest as a parameter; if it's an input
- *            element, its value will be set to the resultText; if it's another type of
- *            element, its innerHTML will be set to the resultText.
- *
- * Example:
- *    sajax_do_call( 'doFoo', [1, 2, 3], document.getElementById( 'showFoo' ) );
- *
- * This will call the doFoo function via MediaWiki's AjaxDispatcher, with
- * (1, 2, 3) as the parameter list, and will show the result in the element
- * with id = showFoo
- */
-function doAjaxRequest( func_name, args, target ) {
-       var i, x, uri, post_data;
-       uri = mw.util.wikiScript() + '?action=ajax';
-       if ( window.sajax_request_type === 'GET' ) {
-               if ( uri.indexOf( '?' ) === -1 ) {
-                       uri = uri + '?rs=' + encodeURIComponent( func_name );
-               } else {
-                       uri = uri + '&rs=' + encodeURIComponent( func_name );
-               }
-               for ( i = 0; i < args.length; i++ ) {
-                       uri = uri + '&rsargs[]=' + encodeURIComponent( args[i] );
-               }
-               //uri = uri + '&rsrnd=' + new Date().getTime();
-               post_data = null;
-       } else {
-               post_data = 'rs=' + encodeURIComponent( func_name );
-               for ( i = 0; i < args.length; i++ ) {
-                       post_data = post_data + '&rsargs[]=' + encodeURIComponent( args[i] );
-               }
-       }
-       x = createXhr();
-       if ( !x ) {
-               alert( 'AJAX not supported' );
-               return false;
-       }
-
-       try {
-               x.open( window.sajax_request_type, uri, true );
-       } catch ( e ) {
-               if ( location.hostname === 'localhost' ) {
-                       alert( 'Your browser blocks XMLHttpRequest to "localhost", try using a real hostname for development/testing.' );
-               }
-               throw e;
-       }
-       if ( window.sajax_request_type === 'POST' ) {
-               x.setRequestHeader( 'Method', 'POST ' + uri + ' HTTP/1.1' );
-               x.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
-       }
-       x.setRequestHeader( 'Pragma', 'cache=yes' );
-       x.setRequestHeader( 'Cache-Control', 'no-transform' );
-       x.onreadystatechange = function () {
-               if ( x.readyState !== 4 ) {
-                       return;
-               }
-
-               debug( 'received (' + x.status + ' ' + x.statusText + ') ' + x.responseText );
-
-               //if ( x.status != 200 )
-               //      alert( 'Error: ' + x.status + ' ' + x.statusText + ': ' + x.responseText );
-               //else
-
-               if ( typeof target === 'function' ) {
-                       target( x );
-               } else if ( typeof target === 'object' ) {
-                       if ( target.tagName === 'INPUT' ) {
-                               if ( x.status === 200 ) {
-                                       target.value = x.responseText;
-                               }
-                               //else alert( 'Error: ' + x.status + ' ' + x.statusText + ' (' + x.responseText + ')' );
-                       } else {
-                               if ( x.status === 200 ) {
-                                       target.innerHTML = x.responseText;
-                               } else {
-                                       target.innerHTML = '<div class="error">Error: ' + x.status +
-                                               ' ' + x.statusText + ' (' + x.responseText + ')</div>';
-                               }
-                       }
-               } else {
-                       alert( 'Bad target for sajax_do_call: not a function or object: ' + target );
-               }
-       };
-
-       debug( func_name + ' uri = ' + uri + ' / post = ' + post_data );
-       x.send( post_data );
-       debug( func_name + ' waiting..' );
-
-       return true;
-}
-
-/**
- * @return {boolean} Whether the browser supports AJAX
- */
-function wfSupportsAjax() {
-       var request = createXhr(),
-               supportsAjax = request ? true : false;
-
-       request = undefined;
-       return supportsAjax;
-}
-
-// Expose + Mark as deprecated
-var deprecationNotice = 'Sajax is deprecated, use jQuery.ajax or mediawiki.api instead.';
-
-// Variables
-mw.log.deprecate( window, 'sajax_debug_mode', false, deprecationNotice );
-mw.log.deprecate( window, 'sajax_request_type', 'GET', deprecationNotice );
-// Methods
-mw.log.deprecate( window, 'sajax_debug', debug, deprecationNotice );
-mw.log.deprecate( window, 'sajax_init_object', createXhr, deprecationNotice );
-mw.log.deprecate( window, 'sajax_do_call', doAjaxRequest, deprecationNotice );
-mw.log.deprecate( window, 'wfSupportsAjax', wfSupportsAjax, deprecationNotice );
-
-}( mediaWiki ) );
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..6cf8d718503709f208b5fbecec35ab55ea3d9f13
--- /dev/null
@@ -0,0 +1 @@
+../../resources/src/mediawiki.legacy/ajax.js
\ No newline at end of file
diff --git a/skins/common/commonContent.css b/skins/common/commonContent.css
deleted file mode 100644 (file)
index 4157b55..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/**
- * MediaWiki style sheet for general styles on complex content
- *
- * Styles for complex things which are a standard part of page content
- * (ie: the CSS classing built into the system), like the TOC.
- */
-
-/* Table of Contents */
-#toc,
-.toc,
-.mw-warning {
-       border: 1px solid #aaa;
-       background-color: #f9f9f9;
-       padding: 5px;
-       font-size: 95%;
-}
-
-/**
- * We want to display the ToC element with intrinsic width in block mode. The fit-content
- * value for width is however not supported by large groups of browsers.
- *
- * We use display:table. Even though it should only contain other table-* display
- * elements, there are no known problems with using this.
- *
- * Because IE < 8, FF 2 and other older browsers don't support display:table, we fallback to
- * using inline-block mode, which features at least intrinsic width, but won't clear preceding
- * inline elements. In practice inline elements surrounding the TOC are uncommon enough that
- * this is an acceptable sacrifice.
- */
-#toc,
-.toc {
-       display: -moz-inline-block;
-       display: inline-block;
-       display: table;
-
-       /* IE7 and earlier */
-       zoom: 1;
-       *display: inline;
-
-       padding: 7px;
-}
-
-/* CSS for backwards-compatibility with cached page renders and creative uses in wikitext */
-table#toc,
-table.toc {
-       border-collapse: collapse;
-}
-
-/* Remove additional paddings inside table-cells that are not present in <div>s */
-table#toc td,
-table.toc td {
-       padding: 0;
-}
-
-#toc h2,
-.toc h2 {
-       display: inline;
-       border: none;
-       padding: 0;
-       font-size: 100%;
-       font-weight: bold;
-}
-
-#toc #toctitle,
-.toc #toctitle,
-#toc .toctitle,
-.toc .toctitle {
-       text-align: center;
-}
-
-#toc ul,
-.toc ul {
-       list-style-type: none;
-       list-style-image: none;
-       margin-left: 0;
-       padding: 0;
-       text-align: left;
-}
-
-#toc ul ul,
-.toc ul ul {
-       margin: 0 0 0 2em;
-}
-
-#toc .toctoggle,
-.toc .toctoggle {
-       font-size: 94%;
-}
-
-.toccolours {
-       border: 1px solid #aaa;
-       background-color: #f9f9f9;
-       padding: 5px;
-       font-size: 95%;
-}
-
-/* Warning */
-.mw-warning {
-       margin-left: 50px;
-       margin-right: 50px;
-       text-align: center;
-}
-
-/* Images */
-/* @noflip */div.floatright, table.floatright {
-       margin: 0 0 .5em .5em;
-       border: 0;
-}
-
-div.floatright p {
-       font-style: italic;
-}
-
-/* @noflip */div.floatleft, table.floatleft {
-       margin: 0 .5em .5em 0;
-       border: 0;
-}
-
-div.floatleft p {
-       font-style: italic;
-}
-
-/* Thumbnails */
-div.thumb {
-       margin-bottom: .5em;
-       width: auto;
-       background-color: transparent;
-}
-
-div.thumbinner {
-       border: 1px solid #ccc;
-       padding: 3px !important;
-       background-color: #f9f9f9;
-       font-size: 94%;
-       text-align: center;
-       overflow: hidden;
-}
-
-html .thumbimage {
-       border: 1px solid #ccc;
-}
-
-html .thumbcaption {
-       border: none;
-       line-height: 1.4em;
-       padding: 3px !important;
-       font-size: 94%;
-}
-
-div.magnify {
-       border: none !important;
-       background: none !important;
-       margin-left: 3px;
-}
-
-div.magnify a, div.magnify img {
-       display: block;
-       border: none !important;
-       background: none !important;
-}
-
-/* @noflip */div.tright {
-       margin: .5em 0 1.3em 1.4em;
-}
-
-/* @noflip */div.tleft {
-       margin: .5em 1.4em 1.3em 0;
-}
-
-img.thumbborder {
-       border: 1px solid #dddddd;
-}
diff --git a/skins/common/commonElements.css b/skins/common/commonElements.css
deleted file mode 100644 (file)
index 7b2cc40..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/**
- * MediaWiki style sheet for general styles on basic content elements
- *
- * Styles for basic elements: links, lists, etc...
- *
- * This style sheet is used by the Monobook and Vector skins.
- */
-
-/* Links */
-a {
-       text-decoration: none;
-       color: #0645ad;
-       background: none;
-}
-
-a:visited {
-       color: #0b0080;
-}
-
-a:active {
-       color: #faa700;
-}
-
-a:hover, a:focus {
-       text-decoration: underline;
-}
-
-a.stub {
-       color: #772233;
-}
-
-a.new, #p-personal a.new {
-       color: #ba0000;
-}
-
-a.new:visited, #p-personal a.new:visited {
-       color: #a55858;
-}
-
-/* Interwiki Styling */
-.mw-body a.extiw,
-.mw-body a.extiw:active {
-       color: #36b;
-}
-
-.mw-body a.extiw:visited {
-       color: #636;
-}
-
-.mw-body a.extiw:active {
-       color: #b63;
-}
-
-/* External links */
-.mw-body a.external {
-       color: #36b;
-}
-
-.mw-body a.external:visited {
-       color: #636; /* bug 3112 */
-}
-
-.mw-body a.external:active {
-       color: #b63;
-}
-
-/* Inline Elements */
-img {
-       border: none;
-       vertical-align: middle;
-}
-
-hr {
-       height: 1px;
-       color: #aaa;
-       background-color: #aaa;
-       border: 0;
-       margin: .2em 0;
-}
-
-/* Structural Elements */
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
-       color: black;
-       background: none;
-       font-weight: normal;
-       margin: 0;
-       overflow: hidden;
-       padding-top: .5em;
-       padding-bottom: .17em;
-       border-bottom: 1px solid #aaa;
-}
-
-h1 {
-       font-size: 188%;
-}
-
-h2 {
-       font-size: 150%;
-}
-
-h3,
-h4,
-h5,
-h6 {
-       border-bottom: none;
-       font-weight: bold;
-}
-
-h3 {
-       font-size: 132%;
-}
-
-h4 {
-       font-size: 116%;
-}
-
-h5 {
-       font-size: 108%;
-}
-
-h6 {
-       font-size: 100%;
-}
-
-/* Some space under the headers in the content area */
-h1,
-h2 {
-       margin-bottom: .6em;
-}
-
-h3,
-h4,
-h5 {
-       margin-bottom: .3em;
-}
-
-p {
-       margin: .4em 0 .5em 0;
-       line-height: 1.5em;
-}
-
-p img {
-       margin: 0;
-}
-
-ul {
-       line-height: 1.5em;
-       list-style-type: square;
-       margin: .3em 0 0 1.6em;
-       padding: 0;
-}
-
-ol {
-       line-height: 1.5em;
-       margin: .3em 0 0 3.2em;
-       padding: 0;
-       list-style-image: none;
-}
-
-li {
-       margin-bottom: .1em;
-}
-
-dt {
-       font-weight: bold;
-       margin-bottom: .1em;
-}
-
-dl {
-       margin-top: .2em;
-       margin-bottom: .5em;
-}
-
-dd {
-       line-height: 1.5em;
-       margin-left: 1.6em;
-       margin-bottom: .1em;
-}
-
-/* IE 6 and 7 lack support for quotes aroud the <q> element ('::before' and '::after'
-   pseudoelements, 'quotes' property). Let's italicize it instead (using the star hack). */
-q {
-       *font-style: italic;
-}
-
-pre, code, tt, kbd, samp, .mw-code {
-       /*
-        * Some browsers will render the monospace text too small, namely Firefox, Chrome and Safari.
-        * Specifying any valid, second value will trigger correct behavior without forcing a different font.
-        */
-       font-family: monospace, Courier;
-}
-
-code {
-       background-color: #f9f9f9;
-}
-
-pre, .mw-code {
-       padding: 1em;
-       border: 1px solid #ddd;
-       color: black;
-       background-color: #f9f9f9;
-}
-
-/* Tables */
-table {
-       font-size: 100%;
-}
-
-/* Forms */
-fieldset {
-       border: 1px solid #2f6fab;
-       margin: 1em 0 1em 0;
-       padding: 0 1em 1em;
-       line-height: 1.5em;
-}
-
-fieldset.nested {
-       margin: 0 0 0.5em 0;
-       padding: 0 0.5em 0.5em;
-}
-
-legend {
-       padding: .5em;
-       font-size: 95%;
-}
-
-form {
-       border: none;
-       margin: 0;
-}
-
-textarea {
-       width: 100%;
-       padding: .1em;
-       display: block;
-       -moz-box-sizing: border-box;
-       -webkit-box-sizing: border-box;
-       box-sizing: border-box;
-}
-
-select {
-       vertical-align: top;
-}
-
-/* Emulate Center */
-.center {
-       width: 100%;
-       text-align: center;
-}
-
-*.center * {
-       margin-left: auto;
-       margin-right: auto;
-}
-
-/* Small for tables and similar */
-.small {
-       font-size: 94%;
-}
-
-table.small {
-       font-size: 100%;
-}
diff --git a/skins/common/commonInterface.css b/skins/common/commonInterface.css
deleted file mode 100644 (file)
index 733fd11..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * MediaWiki style sheet for common core styles on interfaces
- *
- * Styles for the Monobook/Vector pattern of laying out common interfaces.
- * These ids/classes are not built into the system,
- * they are outputted by the actual MonoBook/Vector code by convention.
- */
-
-/* Categories */
-.catlinks {
-       border: 1px solid #aaa;
-       background-color: #f9f9f9;
-       padding: 5px;
-       margin-top: 1em;
-       clear: both;
-}
-
-/* User Message */
-.usermessage {
-       background-color: #ffce7b;
-       border: 1px solid #ffa500;
-       color: black;
-       font-weight: bold;
-       margin: 2em 0 1em;
-       padding: .5em 1em;
-       vertical-align: middle;
-}
-
-/* Site Notice (includes notices from CentralNotice extension) */
-#siteNotice {
-       position: relative;
-       text-align: center;
-       margin: 0;
-}
-
-#localNotice {
-       margin-bottom: 0.9em;
-}
-
-/* First h1 */
-.firstHeading,
-#firstHeading {
-       margin-bottom: .1em;
-       /* These two rules hack around bug 2013 (fix for more limited bug 11325).
-        * When bug 2013 is fixed properly, they should be removed. */
-       line-height: 1.2em;
-       padding-bottom: 0;
-}
-
-/* Sub-navigation */
-#siteSub {
-       display: none;
-}
-
-#jump-to-nav {
-       /* Negate #contentSub's margin and replicate it so that the jump to links don't affect the spacing */
-       margin-top: -1.4em;
-       margin-bottom: 1.4em;
-}
-
-#contentSub, #contentSub2 {
-       font-size: 84%;
-       line-height: 1.2em;
-       margin: 0 0 1.4em 1em;
-       color: #545454;
-       width: auto;
-}
-
-span.subpages {
-       display: block;
-}
diff --git a/skins/common/commonPrint.css b/skins/common/commonPrint.css
deleted file mode 100644 (file)
index dda17fb..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-/**
- * MediaWiki Print style sheet for CSS2-capable browsers.
- * Copyright Gabriel Wicke, http://www.aulinx.de/
- *
- * Derived from the plone (http://plone.org/) styles
- * Copyright Alexander Limi
- */
-
-/* Thanks to A List Apart (http://alistapart.com/) for useful extras */
-
-/**
- * Hide all the elements irrelevant for printing
- */
-.noprint,
-div#jump-to-nav,
-.mw-jump,
-div.top,
-div#column-one,
-#colophon,
-.mw-editsection,
-.mw-editsection-like,
-.toctoggle,
-#toc.tochidden,
-div#f-poweredbyico,
-div#f-copyrightico,
-li#viewcount,
-li#about,
-li#disclaimer,
-li#mobileview,
-li#privacy,
-#footer-places,
-.mw-hidden-catlinks,
-tr.mw-metadata-show-hide-extended,
-span.mw-filepage-other-resolutions,
-#filetoc,
-.usermessage,
-.patrollink,
-#mw-navigation,
-#siteNotice {
-       display: none;
-}
-
-/**
- * Pagination
- */
-.wikitable, .thumb, img {
-       page-break-inside: avoid;
-}
-
-h2, h3, h4, h5, h6 {
-       page-break-after: avoid;
-}
-
-p {
-       widows: 3;
-       orphans: 3;
-}
-
-/**
- * Generic HTML elements
- */
-body {
-       background: white;
-       color: black;
-       margin: 0;
-       padding: 0;
-}
-
-ul {
-       list-style-type: square;
-}
-
-h1, h2, h3, h4, h5, h6 {
-       font-weight: bold;
-}
-
-dt {
-       font-weight: bold;
-}
-
-p {
-       margin: 1em 0;
-       line-height: 1.2em;
-}
-
-pre, .mw-code {
-       border: 1pt dashed black;
-       white-space: pre;
-       font-size: 8pt;
-       overflow: auto;
-       padding: 1em 0;
-       background: white;
-       color: black;
-}
-
-/**
- * MediaWiki-specific elements
- */
-#globalWrapper {
-       width: 100% !important;
-       min-width: 0 !important;
-}
-
-#content {
-       background: white;
-       border: none !important;
-       padding: 0 !important;
-       margin: 0 !important;
-       direction: ltr;
-       color: black;
-}
-
-#column-content {
-       margin: 0 !important;
-}
-
-#column-content #content {
-       padding: 1em;
-       margin: 0 !important;
-}
-
-#toc {
-       border: 1px solid #aaaaaa;
-       background-color: #f9f9f9;
-       padding: 5px;
-       display: -moz-inline-block;
-       display: inline-block;
-       display: table;
-       /* IE7 and earlier */
-       zoom: 1;
-       *display: inline;
-}
-
-#footer {
-       background: white;
-       color: black;
-       margin-top: 1em;
-       border-top: 1px solid #AAA;
-       direction: ltr;
-}
-
-img {
-       border: none;
-       vertical-align: middle;
-}
-
-/* math */
-span.texhtml {
-       font-family: serif;
-}
-
-/**
- * Links
- */
-a.stub,
-a.new {
-       color: #ba0000;
-       text-decoration: none;
-}
-
-a {
-       color: black !important;
-       background: none !important;
-       padding: 0 !important;
-}
-
-a:link, a:visited {
-       color: #520;
-       background: transparent;
-       text-decoration: underline;
-}
-
-/* Expand URLs for printing */
-#content a.external.text:after,
-#content a.external.autonumber:after {
-       content: " (" attr(href) ")";
-}
-
-/* Expand protocol-relative URLs for printing */
-#content a.external.text[href^='//']:after,
-#content a.external.autonumber[href^='//']:after {
-       content: " (https:" attr(href) ")";
-}
-
-/* MSIE/Win doesn't understand 'inherit' */
-a,
-a.external,
-a.new,
-a.stub {
-       color: black !important;
-       text-decoration: none !important;
-}
-
-/* Continue ... */
-a,
-a.external,
-a.new,
-a.stub {
-       color: inherit !important;
-       text-decoration: inherit !important;
-}
-
-/**
- * Floating divs
- */
-div.floatright {
-       float: right;
-       clear: right;
-       position: relative;
-       margin: 0.5em 0 0.8em 1.4em;
-}
-
-div.floatright p {
-       font-style: italic;
-}
-
-div.floatleft {
-       float: left;
-       clear: left;
-       position: relative;
-       margin: 0.5em 1.4em 0.8em 0;
-}
-
-div.floatleft p {
-       font-style: italic;
-}
-
-div.center {
-       text-align: center;
-}
-
-/**
- * Thumbnails
- */
-div.thumb {
-       border: none;
-       width: auto;
-       margin-top: 0.5em;
-       margin-bottom: 0.8em;
-       background-color: transparent;
-}
-
-div.thumbinner {
-       border: 1px solid #cccccc;
-       padding: 3px !important;
-       background-color: White;
-       font-size: 94%;
-       text-align: center;
-       overflow: hidden;
-}
-
-html .thumbimage {
-       border: 1px solid #cccccc;
-}
-
-html .thumbcaption {
-       border: none;
-       text-align: left;
-       line-height: 1.4em;
-       padding: 3px !important;
-       font-size: 94%;
-}
-
-div.magnify {
-       display: none;
-}
-
-/* @noflip */
-div.tright {
-       float: right;
-       clear: right;
-       margin: 0.5em 0 0.8em 1.4em;
-}
-
-/* @noflip */
-div.tleft {
-       float: left;
-       clear: left;
-       margin: 0.5em 1.4em 0.8em 0;
-}
-
-img.thumbborder {
-       border: 1px solid #dddddd;
-}
-
-/**
- * Galleries (see shared.css for more info)
- */
-li.gallerybox {
-       vertical-align: top;
-       display: inline-block;
-}
-
-ul.gallery, li.gallerybox {
-       zoom: 1;
-       *display: inline;
-}
-
-ul.gallery {
-       margin: 2px;
-       padding: 2px;
-       display: block;
-}
-
-li.gallerycaption {
-       font-weight: bold;
-       text-align: center;
-       display: block;
-       word-wrap: break-word;
-}
-
-li.gallerybox div.thumb {
-       text-align: center;
-       border: 1px solid #ccc;
-       margin: 2px;
-}
-
-div.gallerytext {
-       overflow: hidden;
-       font-size: 94%;
-       padding: 2px 4px;
-       word-wrap: break-word;
-}
-
-/**
- * Diff rendering
- */
-table.diff {
-       background: white;
-}
-
-td.diff-otitle {
-       background: #ffffff;
-}
-
-td.diff-ntitle {
-       background: #ffffff;
-}
-
-td.diff-addedline {
-       background: #ccffcc;
-       font-size: smaller;
-       border: solid 2px black;
-}
-
-td.diff-deletedline {
-       background: #ffffaa;
-       font-size: smaller;
-       border: dotted 2px black;
-}
-
-td.diff-context {
-       background: #eeeeee;
-       font-size: smaller;
-}
-
-.diffchange {
-       color: silver;
-       font-weight: bold;
-       text-decoration: underline;
-}
-
-/**
- * Table rendering
- * As on shared.css but with white background.
- */
-table.wikitable,
-table.mw_metadata {
-       margin: 1em 0;
-       border: 1px #aaa solid;
-       background: white;
-       border-collapse: collapse;
-}
-
-table.wikitable > tr > th, table.wikitable > tr > td,
-table.wikitable > * > tr > th, table.wikitable > * > tr > td,
-.mw_metadata th, .mw_metadata td {
-       border: 1px #aaa solid;
-       padding: 0.2em;
-}
-
-table.wikitable > tr > th,
-table.wikitable > * > tr > th,
-.mw_metadata th {
-       text-align: center;
-       background: white;
-       font-weight: bold;
-}
-
-table.wikitable > caption,
-.mw_metadata caption {
-       font-weight: bold;
-}
-
-table.listing,
-table.listing td {
-       border: 1pt solid black;
-       border-collapse: collapse;
-}
-
-a.sortheader {
-       margin: 0 0.3em;
-}
-
-/**
- * Categories
- */
-.catlinks ul {
-       display: inline;
-       margin: 0;
-       padding: 0;
-       list-style: none;
-       list-style-type: none;
-       list-style-image: none;
-       vertical-align: middle !ie;
-}
-
-.catlinks li {
-       display: inline-block;
-       line-height: 1.15em;
-       padding: 0 .4em;
-       border-left: 1px solid #AAA;
-       margin: 0.1em 0;
-       zoom: 1;
-       display: inline !ie;
-}
-
-.catlinks li:first-child {
-       padding-left: .2em;
-       border-left: none;
-}
diff --git a/skins/common/config-cc.css b/skins/common/config-cc.css
deleted file mode 100644 (file)
index ecd10fa..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Copy of CC standard stylesheet, plus tweaks for iframe usage
- */
-
-body {
-       margin: 0;
-       background: #eee;
-       font-family: Verdana;
-       color: #333;
-}
-
-#main {
-       border: 1px solid #D0D0D0;
-       background: #fff;
-       margin: 0.5em;
-}
-
-/**
- * Looks like you have to specify the width of #menu
- * or IE5 Mac stretches it all the way across the div, and
- * Opera streches it half way.
- */
-
-#main #menu {
-       border-left: 1px dotted #ccc;
-       float: right;
-       width: 230px;
-       background: white;
-       margin: 0 0 10px 10px;
-}
-
-td, h3, p, h1, pre {
-       margin: 0 20px 20px 20px;
-       font-size: 11px;
-       line-height: 140%;
-}
-
-.header {
-       padding-left: 10px;
-       padding-top: 10px;
-}
-
-.nav {
-       padding-left: 10px;
-       padding-bottom: 10px;
-       font-size: 11px;
-       margin-bottom: 16px;
-}
-
-#menu p {
-       font-size: 11px;
-}
-
-.dent {
-       margin-left: 64px;
-}
diff --git a/skins/common/config.css b/skins/common/config.css
deleted file mode 100644 (file)
index aedb6a9..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-.env-check {
-       font-size: 90%;
-       margin: 1em 0 1em 2.5em;
-}
-
-.config-section {
-       margin-top: 2em;
-}
-
-.config-block {
-       margin-top: 2em;
-       display: block;
-
-}
-
-.config-block-label {
-       display: block;
-       margin-bottom: .2em;
-}
-
-.config-block-label label, .config-label {
-       font-weight: bold;
-       padding-right: .5em;
-       padding-top: .2em;
-}
-
-.config-block-elements {
-       margin-left: 2em;
-}
-
-.config-block-elements li {
-       list-style: none;
-}
-
-.config-input {
-       clear: left;
-       zoom: 100%; /* IE hack */
-}
-
-.config-page-wrapper {
-       padding: 0.5em;
-}
-
-.config-page-list {
-       float: right;
-       width: 12em;
-       border: 1px solid #aaa;
-       background: #fff;
-       padding: 0.5em;
-       /* 3em left margin to leave space between the list and the page-content */
-       margin: 0.5em 0.5em 0.5em 3.5em;
-}
-
-.config-page {
-       padding: 0.5em 0.5em 0.5em 2em;
-       margin: 0.5em 0.5em 0.5em 0.5em;
-       background: #eee;
-}
-
-.config-submit {
-       clear: left;
-       text-align: center;
-       padding: 1em;
-}
-
-.config-submit input {
-       margin-left: 0.5em;
-       margin-right: 0.5em;
-}
-
-.config-page-disabled {
-       color: #aaa;
-}
-
-.config-error-box {
-       border: 2px solid #f00;
-}
-
-.config-page-current {
-       font-weight: bold;
-}
-
-.config-message {
-       display: list-item;
-       line-height: 1.5em;
-       /* @embed */
-       list-style-image: url(images/bullet.gif);
-       list-style-type: square;
-}
-
-.config-input-text {
-       width: 20em;
-       margin-right: 1em;
-}
-
-.config-input-check {
-       margin-left: 10em;
-}
-
-.error {
-       color: red;
-       background-color: #fff;
-       font-weight: bold;
-       left: 1em;
-       font-size: 100%;
-}
-
-.config-settings-block {
-       list-style-type: none;
-       list-style-image: none;
-       margin: 0;
-       padding: 0;
-}
-
-.btn-install {
-       font-weight: bold;
-       font-size: 110%;
-       padding: .2em .3em;
-}
-
-.success-message {
-       font-weight: bold;
-       font-size: 110%;
-       color: green;
-}
-
-.success-box {
-       font-size: 130%;
-}
-
-.config-cc-wrapper {
-       clear: left;
-       /* If you change this height, also change it in WebInstallerOptions::submitCC() */
-       height: 54em;
-}
-
-.config-plainlink a {
-       background: none !important;
-       padding: 0 !important;
-}
-
-.config-download-link {
-       font-size: 1.8em;
-       margin-left: 2em;
-}
-
-.config-download-link a {
-       background: url(images/download-32.png) no-repeat center left;
-       padding-left: 40px; /* 32 px for the image (above), plus some breathing room */
-       height: 32px; /* provide enough vertical room for the image */
-       display: inline-block; /* allow the height property (above) to work */
-       line-height: 32px; /* center the text vertically */
-}
-
-#config-live-log {
-       overflow: hidden;
-       min-width: 20em;
-}
diff --git a/skins/common/config.js b/skins/common/config.js
deleted file mode 100644 (file)
index 2886e08..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-( function ( $ ) {
-       $( function () {
-               var $label, labelText;
-
-               function syncText() {
-                       var value = $(this).val()
-                               .replace( /[\[\]\{\}|#<>%+? ]/g, '_' )
-                               .replace( /&/, '&amp;' )
-                               .replace( /__+/g, '_' )
-                               .replace( /^_+/, '' )
-                               .replace( /_+$/, '' );
-                       value = value.substr( 0, 1 ).toUpperCase() + value.substr( 1 );
-                       $label.text( labelText.replace( '$1', value ) );
-               }
-
-               // Set up the help system
-               $( '.mw-help-field-data' )
-                       .hide()
-                       .closest( '.mw-help-field-container' )
-                               .find( '.mw-help-field-hint' )
-                                       .show()
-                                       .click( function () {
-                                               $(this)
-                                                       .closest( '.mw-help-field-container' )
-                                                               .find( '.mw-help-field-data' )
-                                                                       .slideToggle( 'fast' );
-                                       } );
-
-               // Show/hide code for DB-specific options
-               // FIXME: Do we want slow, fast, or even non-animated (instantaneous) showing/hiding here?
-               $( '.dbRadio' ).each( function () {
-                       $( document.getElementById( $(this).attr( 'rel' ) ) ).hide();
-               } );
-               $( document.getElementById( $( '.dbRadio:checked' ).attr( 'rel' ) ) ).show();
-               $( '.dbRadio' ).click( function () {
-                       var $checked = $( '.dbRadio:checked' ),
-                               $wrapper = $( document.getElementById( $checked.attr( 'rel' ) ) );
-                       if ( $wrapper.is( ':hidden' ) ) {
-                               $( '.dbWrapper' ).hide( 'slow' );
-                               $wrapper.show( 'slow' );
-                       }
-               } );
-
-               // Scroll to the bottom of upgrade log
-               $( '#config-live-log' ).children( 'textarea' ).each( function () {
-                       this.scrollTop = this.scrollHeight;
-               } );
-
-               // Show/hide Creative Commons thingy
-               $( '.licenseRadio' ).click( function () {
-                       var $wrapper = $( '#config-cc-wrapper' );
-                       if ( $( '#config__LicenseCode_cc-choose' ).is( ':checked' ) ) {
-                               $wrapper.show( 'slow' );
-                       } else {
-                               $wrapper.hide( 'slow' );
-                       }
-               } );
-
-               // Show/hide random stuff (email, upload)
-               $( '.showHideRadio' ).click( function () {
-                       var $wrapper = $( '#' + $(this).attr( 'rel' ) );
-                       if ( $(this).is( ':checked' ) ) {
-                               $wrapper.show( 'slow' );
-                       } else {
-                               $wrapper.hide( 'slow' );
-                       }
-               } );
-               $( '.hideShowRadio' ).click( function () {
-                       var $wrapper = $( '#' + $(this).attr( 'rel' ) );
-                       if ( $(this).is( ':checked' ) ) {
-                               $wrapper.hide( 'slow' );
-                       } else {
-                               $wrapper.show( 'slow' );
-                       }
-               } );
-
-               // Hide "other" textboxes by default
-               // Should not be done in CSS for javascript disabled compatibility
-               $( '.enabledByOther' ).closest( '.config-block' ).hide();
-
-               // Enable/disable "other" textboxes
-               $( '.enableForOther' ).click( function () {
-                       var $textbox = $( document.getElementById( $(this).attr( 'rel' ) ) );
-                       // FIXME: Ugh, this is ugly
-                       if ( $(this).val() === 'other' ) {
-                               $textbox.removeProp( 'readonly' ).closest( '.config-block' ).slideDown( 'fast' );
-                       } else {
-                               $textbox.prop( 'readonly', true ).closest( '.config-block' ).slideUp( 'fast' );
-                       }
-               } );
-
-               // Synchronize radio button label for sitename with textbox
-               $label = $( 'label[for=config__NamespaceType_site-name]' );
-               labelText = $label.text();
-               $label.text( labelText.replace( '$1', '' ) );
-               $( '#config_wgSitename' ).on( 'keyup change', syncText ).each( syncText );
-
-               // Show/Hide memcached servers when needed
-               $( 'input[name$="config_wgMainCacheType"]' ).change( function () {
-                       var $memc = $( '#config-memcachewrapper' );
-                       if ( $( 'input[name$="config_wgMainCacheType"]:checked' ).val() === 'memcached' ) {
-                               $memc.show( 'slow' );
-                       } else {
-                               $memc.hide( 'slow' );
-                       }
-               } );
-       } );
-}( jQuery ) );
diff --git a/skins/common/feed.css b/skins/common/feed.css
deleted file mode 100644 (file)
index dc0453d..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
-Make RSS and Atom feeds at least semi-legible to folk who accidentally
-load them in a browser...
-
-Compatibility:
-* Mozilla is fine.
-* Safari 1.2: the RSS <link> text isn't shown
-* Opera 7.5 uses the style sheet instead of its native RSS mode.
-* IE/Mac 5.2: none of the :before content works; doesn't get the charset right and displays garbage for non-ASCII.
-* IE/Win 6.0: No background color, borders, font size, font weight, or :before content.
-
-*/
-
-/* RSS: */ rss, channel, title, link, description, language, generator, lastBuildDate, item, pubDate, author, comments, creator,
-/* Atom: */ feed, id, modified, tagline, entry, issued, created, updated, summary, comment {
-       display: block;
-}
-
-rss, feed {
-       background: white;
-       color: black;
-       margin: 1em;
-       font-family: "Verdana", "Tahoma", "Arial", "Helvetica", sans-serif;
-       line-height: 1.5em;
-       font-size: 76%;
-}
-
-rss:before {
-       content: "This RSS feed is meant to be read in a syndicated news reader, and isn't ideal for a web browser.";
-}
-
-feed:before {
-       content: "This Atom feed is meant to be read in a syndicated news reader, and isn't ideal for a web browser.";
-}
-
-rss:before, feed:before {
-       color: red;
-       text-align: center;
-       line-height: 2em;
-}
-
-channel > title,
-item > title,
-feed > title,
-entry > title {
-       font-weight: bold;
-       border-bottom: solid 1px #aaa;
-       margin-left: -0.5em;
-}
-
-channel > title, feed > title {
-       font-size: larger;
-}
-
-item > title, entry > title {
-       font-size: large;
-}
-
-item, entry {
-       margin-top: 1em;
-       margin-left: 2em;
-}
-
-item > description, entry > summary {
-       white-space: pre;
-       overflow: auto;
-       background: #f8f8ff;
-}
-
-pubDate:before {
-       content: "Date: ";
-}
-
-link:before {
-       content: "Link: ";
-}
-
-author:before, creator:before {
-       content: "Author: ";
-}
-
-description:before {
-       content: "Description: ";
-}
-
-id:before {
-       content: "Id: ";
-}
-
-generator:before {
-       content: "Generator: ";
-}
-
-language:before {
-       content: "Language: ";
-}
-
-lastBuildDate:before {
-       content: "Updated: ";
-}
-
-comments:before {
-       content: "Comments page: ";
-}
-
-tagline:before {
-       content: "Tagline: ";
-}
-
-issued:before {
-       content: "Issued: ";
-}
-
-created:before {
-       content: "Created: ";
-}
-
-modified:before {
-       content: "Modified: ";
-}
-
-updated:before {
-       content: "Updated: ";
-}
-
-summary:before {
-       content: "Summary: ";
-}
-
-comment:before {
-       content: "Comment: ";
-}
-
-pubDate:before, link:before, author:before, description:before,
-language:before, generator:before, lastBuildDate:before, comments:before,
-tagline:before, issued:before, created:before, modified:before,
-summary:before, comment:before, creator:before, id:before, updated:before {
-       color: #224;
-       font-weight: bold;
-}
-
-feed link:after {
-       content: attr(href);
-}
diff --git a/skins/common/images/Arr_.png b/skins/common/images/Arr_.png
deleted file mode 100644 (file)
index bc67a4b..0000000
Binary files a/skins/common/images/Arr_.png and /dev/null differ
diff --git a/skins/common/images/Arr_d.png b/skins/common/images/Arr_d.png
deleted file mode 100644 (file)
index 58a9fc6..0000000
Binary files a/skins/common/images/Arr_d.png and /dev/null differ
diff --git a/skins/common/images/Arr_l.png b/skins/common/images/Arr_l.png
deleted file mode 100644 (file)
index 2246254..0000000
Binary files a/skins/common/images/Arr_l.png and /dev/null differ
diff --git a/skins/common/images/Arr_r.png b/skins/common/images/Arr_r.png
deleted file mode 100644 (file)
index 467a555..0000000
Binary files a/skins/common/images/Arr_r.png and /dev/null differ
diff --git a/skins/common/images/Arr_u.png b/skins/common/images/Arr_u.png
deleted file mode 100644 (file)
index 1aa543a..0000000
Binary files a/skins/common/images/Arr_u.png and /dev/null differ
diff --git a/skins/common/images/Checker-16x16.png b/skins/common/images/Checker-16x16.png
deleted file mode 100644 (file)
index 3e9e3d0..0000000
Binary files a/skins/common/images/Checker-16x16.png and /dev/null differ
diff --git a/skins/common/images/Zoom_sans.gif b/skins/common/images/Zoom_sans.gif
deleted file mode 100644 (file)
index 56a49de..0000000
Binary files a/skins/common/images/Zoom_sans.gif and /dev/null differ
diff --git a/skins/common/images/add.png b/skins/common/images/add.png
deleted file mode 100644 (file)
index 3497423..0000000
Binary files a/skins/common/images/add.png and /dev/null differ
diff --git a/skins/common/images/ajax-loader.gif b/skins/common/images/ajax-loader.gif
deleted file mode 100644 (file)
index 72203fd..0000000
Binary files a/skins/common/images/ajax-loader.gif and /dev/null differ
diff --git a/skins/common/images/ar/button_bold.png b/skins/common/images/ar/button_bold.png
deleted file mode 100644 (file)
index e524f6c..0000000
Binary files a/skins/common/images/ar/button_bold.png and /dev/null differ
diff --git a/skins/common/images/ar/button_headline.png b/skins/common/images/ar/button_headline.png
deleted file mode 100644 (file)
index 398e561..0000000
Binary files a/skins/common/images/ar/button_headline.png and /dev/null differ
diff --git a/skins/common/images/ar/button_italic.png b/skins/common/images/ar/button_italic.png
deleted file mode 100644 (file)
index 6ec73e9..0000000
Binary files a/skins/common/images/ar/button_italic.png and /dev/null differ
diff --git a/skins/common/images/ar/button_link.png b/skins/common/images/ar/button_link.png
deleted file mode 100644 (file)
index c9c63f6..0000000
Binary files a/skins/common/images/ar/button_link.png and /dev/null differ
diff --git a/skins/common/images/ar/button_nowiki.png b/skins/common/images/ar/button_nowiki.png
deleted file mode 100644 (file)
index 743ea61..0000000
Binary files a/skins/common/images/ar/button_nowiki.png and /dev/null differ
diff --git a/skins/common/images/arrow_disabled_first_25.png b/skins/common/images/arrow_disabled_first_25.png
deleted file mode 100644 (file)
index 78a493e..0000000
Binary files a/skins/common/images/arrow_disabled_first_25.png and /dev/null differ
diff --git a/skins/common/images/arrow_disabled_last_25.png b/skins/common/images/arrow_disabled_last_25.png
deleted file mode 100644 (file)
index 2a64fd0..0000000
Binary files a/skins/common/images/arrow_disabled_last_25.png and /dev/null differ
diff --git a/skins/common/images/arrow_disabled_left_25.png b/skins/common/images/arrow_disabled_left_25.png
deleted file mode 100644 (file)
index 83df068..0000000
Binary files a/skins/common/images/arrow_disabled_left_25.png and /dev/null differ
diff --git a/skins/common/images/arrow_disabled_right_25.png b/skins/common/images/arrow_disabled_right_25.png
deleted file mode 100644 (file)
index aa4fbf8..0000000
Binary files a/skins/common/images/arrow_disabled_right_25.png and /dev/null differ
diff --git a/skins/common/images/arrow_first_25.png b/skins/common/images/arrow_first_25.png
deleted file mode 100644 (file)
index 52b32a5..0000000
Binary files a/skins/common/images/arrow_first_25.png and /dev/null differ
diff --git a/skins/common/images/arrow_last_25.png b/skins/common/images/arrow_last_25.png
deleted file mode 100644 (file)
index caf5033..0000000
Binary files a/skins/common/images/arrow_last_25.png and /dev/null differ
diff --git a/skins/common/images/arrow_left_25.png b/skins/common/images/arrow_left_25.png
deleted file mode 100644 (file)
index f363bf6..0000000
Binary files a/skins/common/images/arrow_left_25.png and /dev/null differ
diff --git a/skins/common/images/arrow_right_25.png b/skins/common/images/arrow_right_25.png
deleted file mode 100644 (file)
index 3f8fee3..0000000
Binary files a/skins/common/images/arrow_right_25.png and /dev/null differ
diff --git a/skins/common/images/be-tarask/button_bold.png b/skins/common/images/be-tarask/button_bold.png
deleted file mode 100644 (file)
index 5c10cfe..0000000
Binary files a/skins/common/images/be-tarask/button_bold.png and /dev/null differ
diff --git a/skins/common/images/be-tarask/button_italic.png b/skins/common/images/be-tarask/button_italic.png
deleted file mode 100644 (file)
index 72209d7..0000000
Binary files a/skins/common/images/be-tarask/button_italic.png and /dev/null differ
diff --git a/skins/common/images/be-tarask/button_link.png b/skins/common/images/be-tarask/button_link.png
deleted file mode 100644 (file)
index 09c86fb..0000000
Binary files a/skins/common/images/be-tarask/button_link.png and /dev/null differ
diff --git a/skins/common/images/button_bold.png b/skins/common/images/button_bold.png
deleted file mode 100644 (file)
index 75c3f10..0000000
Binary files a/skins/common/images/button_bold.png and /dev/null differ
diff --git a/skins/common/images/button_extlink.png b/skins/common/images/button_extlink.png
deleted file mode 100644 (file)
index 458943c..0000000
Binary files a/skins/common/images/button_extlink.png and /dev/null differ
diff --git a/skins/common/images/button_headline.png b/skins/common/images/button_headline.png
deleted file mode 100644 (file)
index 9cf751d..0000000
Binary files a/skins/common/images/button_headline.png and /dev/null differ
diff --git a/skins/common/images/button_hr.png b/skins/common/images/button_hr.png
deleted file mode 100644 (file)
index 47e1ca4..0000000
Binary files a/skins/common/images/button_hr.png and /dev/null differ
diff --git a/skins/common/images/button_image.png b/skins/common/images/button_image.png
deleted file mode 100644 (file)
index 6919296..0000000
Binary files a/skins/common/images/button_image.png and /dev/null differ
diff --git a/skins/common/images/button_italic.png b/skins/common/images/button_italic.png
deleted file mode 100644 (file)
index 527fbd1..0000000
Binary files a/skins/common/images/button_italic.png and /dev/null differ
diff --git a/skins/common/images/button_link.png b/skins/common/images/button_link.png
deleted file mode 100644 (file)
index eb5634b..0000000
Binary files a/skins/common/images/button_link.png and /dev/null differ
diff --git a/skins/common/images/button_media.png b/skins/common/images/button_media.png
deleted file mode 100644 (file)
index 4194ec1..0000000
Binary files a/skins/common/images/button_media.png and /dev/null differ
diff --git a/skins/common/images/button_nowiki.png b/skins/common/images/button_nowiki.png
deleted file mode 100644 (file)
index 2ba818d..0000000
Binary files a/skins/common/images/button_nowiki.png and /dev/null differ
diff --git a/skins/common/images/button_sig.png b/skins/common/images/button_sig.png
deleted file mode 100644 (file)
index fe34b3f..0000000
Binary files a/skins/common/images/button_sig.png and /dev/null differ
diff --git a/skins/common/images/button_template.png b/skins/common/images/button_template.png
deleted file mode 100644 (file)
index 94d9d0b..0000000
Binary files a/skins/common/images/button_template.png and /dev/null differ
diff --git a/skins/common/images/cc-0.png b/skins/common/images/cc-0.png
deleted file mode 100644 (file)
index 9d3fe5f..0000000
Binary files a/skins/common/images/cc-0.png and /dev/null differ
diff --git a/skins/common/images/cc-by-nc-sa.png b/skins/common/images/cc-by-nc-sa.png
deleted file mode 100644 (file)
index 0d24a71..0000000
Binary files a/skins/common/images/cc-by-nc-sa.png and /dev/null differ
diff --git a/skins/common/images/cc-by-sa.png b/skins/common/images/cc-by-sa.png
deleted file mode 100644 (file)
index 518fb64..0000000
Binary files a/skins/common/images/cc-by-sa.png and /dev/null differ
diff --git a/skins/common/images/cc-by.png b/skins/common/images/cc-by.png
deleted file mode 100644 (file)
index 9cca2f9..0000000
Binary files a/skins/common/images/cc-by.png and /dev/null differ
diff --git a/skins/common/images/closewindow.png b/skins/common/images/closewindow.png
deleted file mode 100644 (file)
index 990702e..0000000
Binary files a/skins/common/images/closewindow.png and /dev/null differ
diff --git a/skins/common/images/closewindow19x19.png b/skins/common/images/closewindow19x19.png
deleted file mode 100644 (file)
index c96d9ff..0000000
Binary files a/skins/common/images/closewindow19x19.png and /dev/null differ
diff --git a/skins/common/images/critical-32.png b/skins/common/images/critical-32.png
deleted file mode 100644 (file)
index 9b38e6a..0000000
Binary files a/skins/common/images/critical-32.png and /dev/null differ
diff --git a/skins/common/images/cyrl/LICENSE b/skins/common/images/cyrl/LICENSE
deleted file mode 100644 (file)
index bedcec6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-button_bold.png
----------------
-Source : http://commons.wikimedia.org/wiki/Image:Button_bold_ukr.png
-License: Public domain
-Author : Alexey Belomoev
-
-button_italic.png
-------------------------
-Source : http://commons.wikimedia.org/wiki/Image:Button_italic_ukr.png
-License: Public domain
-Author : Alexey Belomoev
-
-button_link.png
------------------
-Source : http://commons.wikimedia.org/wiki/Image:Button_internal_link_ukr.png
-License: GPL
-Author : Saproj, Erik Möller
diff --git a/skins/common/images/cyrl/button_bold.png b/skins/common/images/cyrl/button_bold.png
deleted file mode 100644 (file)
index eae30d9..0000000
Binary files a/skins/common/images/cyrl/button_bold.png and /dev/null differ
diff --git a/skins/common/images/cyrl/button_italic.png b/skins/common/images/cyrl/button_italic.png
deleted file mode 100644 (file)
index b958d22..0000000
Binary files a/skins/common/images/cyrl/button_italic.png and /dev/null differ
diff --git a/skins/common/images/cyrl/button_link.png b/skins/common/images/cyrl/button_link.png
deleted file mode 100644 (file)
index 12ad373..0000000
Binary files a/skins/common/images/cyrl/button_link.png and /dev/null differ
diff --git a/skins/common/images/de/button_bold.png b/skins/common/images/de/button_bold.png
deleted file mode 100644 (file)
index 367d5bc..0000000
Binary files a/skins/common/images/de/button_bold.png and /dev/null differ
diff --git a/skins/common/images/de/button_italic.png b/skins/common/images/de/button_italic.png
deleted file mode 100644 (file)
index fdd8c9f..0000000
Binary files a/skins/common/images/de/button_italic.png and /dev/null differ
diff --git a/skins/common/images/diffunderline.gif b/skins/common/images/diffunderline.gif
deleted file mode 100644 (file)
index e062c56..0000000
Binary files a/skins/common/images/diffunderline.gif and /dev/null differ
diff --git a/skins/common/images/download-32.png b/skins/common/images/download-32.png
deleted file mode 100644 (file)
index e5b8318..0000000
Binary files a/skins/common/images/download-32.png and /dev/null differ
diff --git a/skins/common/images/fa/button_bold.png b/skins/common/images/fa/button_bold.png
deleted file mode 100644 (file)
index c54d094..0000000
Binary files a/skins/common/images/fa/button_bold.png and /dev/null differ
diff --git a/skins/common/images/fa/button_headline.png b/skins/common/images/fa/button_headline.png
deleted file mode 100644 (file)
index 9890d15..0000000
Binary files a/skins/common/images/fa/button_headline.png and /dev/null differ
diff --git a/skins/common/images/fa/button_italic.png b/skins/common/images/fa/button_italic.png
deleted file mode 100644 (file)
index 33f91ed..0000000
Binary files a/skins/common/images/fa/button_italic.png and /dev/null differ
diff --git a/skins/common/images/fa/button_link.png b/skins/common/images/fa/button_link.png
deleted file mode 100644 (file)
index 76b939e..0000000
Binary files a/skins/common/images/fa/button_link.png and /dev/null differ
diff --git a/skins/common/images/fa/button_nowiki.png b/skins/common/images/fa/button_nowiki.png
deleted file mode 100644 (file)
index 743ea61..0000000
Binary files a/skins/common/images/fa/button_nowiki.png and /dev/null differ
diff --git a/skins/common/images/feed-icon.png b/skins/common/images/feed-icon.png
deleted file mode 100644 (file)
index 00f49f6..0000000
Binary files a/skins/common/images/feed-icon.png and /dev/null differ
diff --git a/skins/common/images/feed-icon.svg b/skins/common/images/feed-icon.svg
deleted file mode 100644 (file)
index 6e5f570..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 256 256"><defs><linearGradient x1=".085" y1=".085" x2=".915" y2=".915" id="a"><stop offset="0" stop-color="#E3702D"/><stop offset=".107" stop-color="#EA7D31"/><stop offset=".35" stop-color="#F69537"/><stop offset=".5" stop-color="#FB9E3A"/><stop offset=".702" stop-color="#EA7C31"/><stop offset=".887" stop-color="#DE642B"/><stop offset="1" stop-color="#D95B29"/></linearGradient></defs><rect width="256" height="256" rx="55" ry="55" fill="#CC5D15"/><rect width="246" height="246" rx="50" ry="50" x="5" y="5" fill="#F49C52"/><rect width="236" height="236" rx="47" ry="47" x="10" y="10" fill="url(#a)"/><circle cx="68" cy="189" r="24" fill="#FFF"/><path d="M160 213h-34a82 82 0 0 0-82-82v-34a116 116 0 0 1 116 116zM184 213a140 140 0 0 0-140-140v-35a175 175 0 0 1 175 175z" fill="#FFF"/></svg>
\ No newline at end of file
diff --git a/skins/common/images/gnu-fdl.png b/skins/common/images/gnu-fdl.png
deleted file mode 100644 (file)
index 3feaf57..0000000
Binary files a/skins/common/images/gnu-fdl.png and /dev/null differ
diff --git a/skins/common/images/help-question-hover.gif b/skins/common/images/help-question-hover.gif
deleted file mode 100644 (file)
index 515138d..0000000
Binary files a/skins/common/images/help-question-hover.gif and /dev/null differ
diff --git a/skins/common/images/help-question.gif b/skins/common/images/help-question.gif
deleted file mode 100644 (file)
index b4fc9c5..0000000
Binary files a/skins/common/images/help-question.gif and /dev/null differ
diff --git a/skins/common/images/icons/COPYING b/skins/common/images/icons/COPYING
deleted file mode 100644 (file)
index 136530a..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-The icons used here are derived from the crystalsvg icons in the the
-pics/crystalsvg/ directory of kdelibs-3.4.0 they were modified on 2005-05-15
-by Ævar Arnfjörð Bjarmason for use in MediaWiki.
-
-What follows is the contents of the LICENSE.crystalsvg file found in the pics/
-subdirectory of kdelibs-3.4.0:
-
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-This copyright and license notice covers all CrystalSVG images.
-Note the license notice contains an add-on.
-********************************************************************************
-KDE Crystal theme icons.
-Copyright (C) 2002 and following years KDE Artists
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation,
-version 2.1 of the License.
-This library 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
-Lesser General Public License for more details.
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-    **** NOTE THIS ADD-ON ****
-The GNU Lesser General Public License or LGPL is written for software libraries
-in the first place. We expressly want the LGPL to be valid for this artwork
-library too.
-KDE Crystal theme icons is a special kind of software library, it is an
-artwork library, it's elements can be used in a Graphical User Interface, or
-GUI.
-Source code, for this library means:
- - for vectors svg;
- - for pixels, if applicable, the multi-layered formats xcf or psd, or
-otherwise png.
-The LGPL in some sections obliges you to make the files carry
-notices. With images this is in some cases impossible or hardly useful.
-With this library a notice is placed at a prominent place in the directory
-containing the elements. You may follow this practice.
-The exception in section 6 of the GNU Lesser General Public License covers
-the use of elements of this art library in a GUI.
-kde-artists [at] kde.org
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/skins/common/images/icons/fileicon-c.png b/skins/common/images/icons/fileicon-c.png
deleted file mode 100644 (file)
index 0d603b7..0000000
Binary files a/skins/common/images/icons/fileicon-c.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-cpp.png b/skins/common/images/icons/fileicon-cpp.png
deleted file mode 100644 (file)
index 123688f..0000000
Binary files a/skins/common/images/icons/fileicon-cpp.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-deb.png b/skins/common/images/icons/fileicon-deb.png
deleted file mode 100644 (file)
index 87ca3fa..0000000
Binary files a/skins/common/images/icons/fileicon-deb.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-djvu.png b/skins/common/images/icons/fileicon-djvu.png
deleted file mode 100644 (file)
index 1da2276..0000000
Binary files a/skins/common/images/icons/fileicon-djvu.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-djvu.xcf b/skins/common/images/icons/fileicon-djvu.xcf
deleted file mode 100644 (file)
index 8043dcd..0000000
Binary files a/skins/common/images/icons/fileicon-djvu.xcf and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-dvi.png b/skins/common/images/icons/fileicon-dvi.png
deleted file mode 100644 (file)
index f37878d..0000000
Binary files a/skins/common/images/icons/fileicon-dvi.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-exe.png b/skins/common/images/icons/fileicon-exe.png
deleted file mode 100644 (file)
index dc020eb..0000000
Binary files a/skins/common/images/icons/fileicon-exe.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-h.png b/skins/common/images/icons/fileicon-h.png
deleted file mode 100644 (file)
index 339bf02..0000000
Binary files a/skins/common/images/icons/fileicon-h.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-html.png b/skins/common/images/icons/fileicon-html.png
deleted file mode 100644 (file)
index f28f8a2..0000000
Binary files a/skins/common/images/icons/fileicon-html.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-iso.png b/skins/common/images/icons/fileicon-iso.png
deleted file mode 100644 (file)
index c73d229..0000000
Binary files a/skins/common/images/icons/fileicon-iso.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-java.png b/skins/common/images/icons/fileicon-java.png
deleted file mode 100644 (file)
index a1b4f22..0000000
Binary files a/skins/common/images/icons/fileicon-java.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-mid.png b/skins/common/images/icons/fileicon-mid.png
deleted file mode 100644 (file)
index ce2bebb..0000000
Binary files a/skins/common/images/icons/fileicon-mid.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-mov.png b/skins/common/images/icons/fileicon-mov.png
deleted file mode 100644 (file)
index 952de1f..0000000
Binary files a/skins/common/images/icons/fileicon-mov.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-o.png b/skins/common/images/icons/fileicon-o.png
deleted file mode 100644 (file)
index f3523d9..0000000
Binary files a/skins/common/images/icons/fileicon-o.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-ogg.png b/skins/common/images/icons/fileicon-ogg.png
deleted file mode 100644 (file)
index ef4d801..0000000
Binary files a/skins/common/images/icons/fileicon-ogg.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-ogg.xcf b/skins/common/images/icons/fileicon-ogg.xcf
deleted file mode 100644 (file)
index a91024b..0000000
Binary files a/skins/common/images/icons/fileicon-ogg.xcf and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-pdf.png b/skins/common/images/icons/fileicon-pdf.png
deleted file mode 100644 (file)
index 8c8da92..0000000
Binary files a/skins/common/images/icons/fileicon-pdf.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-ps.png b/skins/common/images/icons/fileicon-ps.png
deleted file mode 100644 (file)
index e872833..0000000
Binary files a/skins/common/images/icons/fileicon-ps.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-psd.png b/skins/common/images/icons/fileicon-psd.png
deleted file mode 100644 (file)
index 598f190..0000000
Binary files a/skins/common/images/icons/fileicon-psd.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-rm.png b/skins/common/images/icons/fileicon-rm.png
deleted file mode 100644 (file)
index 81dbe0b..0000000
Binary files a/skins/common/images/icons/fileicon-rm.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-rpm.png b/skins/common/images/icons/fileicon-rpm.png
deleted file mode 100644 (file)
index 1903aac..0000000
Binary files a/skins/common/images/icons/fileicon-rpm.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-svg.png b/skins/common/images/icons/fileicon-svg.png
deleted file mode 100644 (file)
index b782113..0000000
Binary files a/skins/common/images/icons/fileicon-svg.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-tar.png b/skins/common/images/icons/fileicon-tar.png
deleted file mode 100644 (file)
index e5fd1b7..0000000
Binary files a/skins/common/images/icons/fileicon-tar.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-tex.png b/skins/common/images/icons/fileicon-tex.png
deleted file mode 100644 (file)
index a437284..0000000
Binary files a/skins/common/images/icons/fileicon-tex.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-ttf.png b/skins/common/images/icons/fileicon-ttf.png
deleted file mode 100644 (file)
index 1ed4e74..0000000
Binary files a/skins/common/images/icons/fileicon-ttf.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-txt.png b/skins/common/images/icons/fileicon-txt.png
deleted file mode 100644 (file)
index 9e988e7..0000000
Binary files a/skins/common/images/icons/fileicon-txt.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon-xcf.png b/skins/common/images/icons/fileicon-xcf.png
deleted file mode 100644 (file)
index 1037b50..0000000
Binary files a/skins/common/images/icons/fileicon-xcf.png and /dev/null differ
diff --git a/skins/common/images/icons/fileicon.png b/skins/common/images/icons/fileicon.png
deleted file mode 100644 (file)
index 59696a3..0000000
Binary files a/skins/common/images/icons/fileicon.png and /dev/null differ
diff --git a/skins/common/images/info-32.png b/skins/common/images/info-32.png
deleted file mode 100644 (file)
index ab09e1d..0000000
Binary files a/skins/common/images/info-32.png and /dev/null differ
diff --git a/skins/common/images/ksh/LICENSE b/skins/common/images/ksh/LICENSE
deleted file mode 100644 (file)
index ba56f97..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-
-button_S_italic.png
--------------------
-Source : http://commons.wikimedia.org/wiki/Image:Button_S_italic.png
-License: Public domain
-Author : Purodha Blissenbach, http://ksh.wikipedia.org/wiki/User:Purodha
-
diff --git a/skins/common/images/ksh/button_S_italic.png b/skins/common/images/ksh/button_S_italic.png
deleted file mode 100644 (file)
index 15496c0..0000000
Binary files a/skins/common/images/ksh/button_S_italic.png and /dev/null differ
diff --git a/skins/common/images/link_icon.gif b/skins/common/images/link_icon.gif
deleted file mode 100644 (file)
index 168c1a2..0000000
Binary files a/skins/common/images/link_icon.gif and /dev/null differ
diff --git a/skins/common/images/mediawiki.png b/skins/common/images/mediawiki.png
deleted file mode 100644 (file)
index 8c42118..0000000
Binary files a/skins/common/images/mediawiki.png and /dev/null differ
diff --git a/skins/common/images/nextredirectltr.png b/skins/common/images/nextredirectltr.png
deleted file mode 100644 (file)
index cd657c3..0000000
Binary files a/skins/common/images/nextredirectltr.png and /dev/null differ
diff --git a/skins/common/images/nextredirectrtl.png b/skins/common/images/nextredirectrtl.png
deleted file mode 100644 (file)
index b788f33..0000000
Binary files a/skins/common/images/nextredirectrtl.png and /dev/null differ
diff --git a/skins/common/images/poweredby_mediawiki_88x31.png b/skins/common/images/poweredby_mediawiki_88x31.png
deleted file mode 100644 (file)
index 30e1d2e..0000000
Binary files a/skins/common/images/poweredby_mediawiki_88x31.png and /dev/null differ
diff --git a/skins/common/images/public-domain.png b/skins/common/images/public-domain.png
deleted file mode 100644 (file)
index ebf0107..0000000
Binary files a/skins/common/images/public-domain.png and /dev/null differ
diff --git a/skins/common/images/question-small.png b/skins/common/images/question-small.png
deleted file mode 100644 (file)
index f7405d2..0000000
Binary files a/skins/common/images/question-small.png and /dev/null differ
diff --git a/skins/common/images/question.svg b/skins/common/images/question.svg
deleted file mode 100644 (file)
index 98fbe8d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="21.059" height="21.06"><path fill="#575757" d="M10.529 0c-5.814 0-10.529 4.714-10.529 10.529s4.715 10.53 10.529 10.53c5.816 0 10.529-4.715 10.529-10.53s-4.712-10.529-10.529-10.529zm-.002 16.767c-.861 0-1.498-.688-1.498-1.516 0-.862.637-1.534 1.498-1.534.828 0 1.5.672 1.5 1.534 0 .827-.672 1.516-1.5 1.516zm2.137-6.512c-.723.568-1 .931-1 1.739v.5h-2.205v-.603c0-1.517.449-2.136 1.154-2.688.707-.552 1.139-.845 1.139-1.637 0-.672-.414-1.051-1.24-1.051-.707 0-1.328.189-1.982.638l-1.051-1.807c.861-.604 1.93-1.034 3.342-1.034 1.912 0 3.516 1.051 3.516 3.066-.001 1.43-.794 2.188-1.673 2.877z"/></svg>
\ No newline at end of file
diff --git a/skins/common/images/remove.png b/skins/common/images/remove.png
deleted file mode 100644 (file)
index cd03d6d..0000000
Binary files a/skins/common/images/remove.png and /dev/null differ
diff --git a/skins/common/images/spinner.gif b/skins/common/images/spinner.gif
deleted file mode 100644 (file)
index 6146be4..0000000
Binary files a/skins/common/images/spinner.gif and /dev/null differ
diff --git a/skins/common/images/tick-32.png b/skins/common/images/tick-32.png
deleted file mode 100644 (file)
index 34cfa9c..0000000
Binary files a/skins/common/images/tick-32.png and /dev/null differ
diff --git a/skins/common/images/tipsy-arrow.gif b/skins/common/images/tipsy-arrow.gif
deleted file mode 100644 (file)
index 9f1a15b..0000000
Binary files a/skins/common/images/tipsy-arrow.gif and /dev/null differ
diff --git a/skins/common/images/tooltip_icon.png b/skins/common/images/tooltip_icon.png
deleted file mode 100644 (file)
index ba5718a..0000000
Binary files a/skins/common/images/tooltip_icon.png and /dev/null differ
diff --git a/skins/common/images/warning-32.png b/skins/common/images/warning-32.png
deleted file mode 100644 (file)
index 0400734..0000000
Binary files a/skins/common/images/warning-32.png and /dev/null differ
diff --git a/skins/common/oldshared.css b/skins/common/oldshared.css
deleted file mode 100644 (file)
index 250f15c..0000000
+++ /dev/null
@@ -1,541 +0,0 @@
-/**
- * oldshared.css
- * This file contains CSS settings common to Wikistandard, Nostalgia and
- * CologneBlue, the old pre-Monobook skins
- */
-
-/* For clarity, explicitly state some recommendations from
- * http://www.w3.org/TR/CSS21/sample.html to make sure the editsection links scale right
- */
-
-h1 {
-       font-size: 2em;
-}
-
-h2 {
-       font-size: 1.5em;
-}
-
-h3 {
-       font-size: 1.17em;
-}
-
-h4 {
-       font-size: 1.11em;
-}
-
-h5 {
-       font-size: 1.05em;
-}
-
-h6 {
-       font-size: 1em;
-}
-
-h1, h2, h3, h4, h5, h6 {
-       font-weight: bolder;
-}
-
-/* Now the custom parts */
-
-#footer {
-       clear: both;
-}
-
-/* images */
-/* @noflip */
-div.floatright {
-       float: right;
-       clear: right;
-       margin: 0 0 1em 1em;
-}
-
-/* @noflip */
-div.floatright p {
-       font-style: italic;
-}
-
-/* @noflip */
-div.floatleft {
-       float: left;
-       clear: left;
-       margin: 0.3em 0.5em 0.5em 0;
-}
-
-/* @noflip */
-div.floatleft p {
-       font-style: italic;
-}
-
-/* table standards */
-table.rimage {
-       float: right;
-       margin-left: 1em;
-       margin-bottom: 1em;
-       text-align: center;
-       font-size: smaller;
-}
-
-/* thumbnails */
-div.thumb {
-       margin-bottom: .5em;
-       border-style: solid;
-       border-color: white;
-       width: auto;
-}
-
-div.thumbinner {
-       border: 1px solid #ccc;
-       padding: 3px !important;
-       background-color: #f9f9f9;
-       font-size: 94%;
-       text-align: center;
-       overflow: hidden;
-}
-
-html .thumbimage {
-       border: 1px solid #ccc;
-}
-
-html .thumbcaption {
-       border: none;
-       text-align: left;
-       line-height: 1.4em;
-       padding: 3px !important;
-       font-size: 94%;
-}
-
-div.magnify {
-       float: right;
-       border: none !important;
-       background: none !important;
-       margin-left: 3px;
-}
-
-div.magnify a,
-div.magnify img {
-       display: block;
-       border: none !important;
-       background: none !important;
-}
-
-/* @noflip */
-div.tright {
-       clear: right;
-       float: right;
-       border-width: .5em 0 .8em 1.4em;
-}
-
-/* @noflip */
-div.tleft {
-       float: left;
-       clear: left;
-       margin-right: .5em;
-       border-width: .5em 1.4em .8em 0;
-}
-
-img.thumbborder {
-       border: 1px solid #dddddd;
-}
-
-/* Page history styling */
-/* the auto-generated edit comments */
-.autocomment {
-       color: #4b4b4b;
-}
-
-img {
-       border: none;
-}
-
-#toc,
-.toc {
-       border: 1px solid #bba;
-       background-color: #f7f8ff;
-       padding: 5px;
-       font-size: 95%;
-       text-align: center;
-       display: -moz-inline-block;
-       display: inline-block;
-       display: table;
-
-       /* IE7 and earlier */
-       zoom: 1;
-       *display: inline;
-
-       padding: 7px;
-}
-
-/* CSS for backwards-compatibility with cached page renders and creative uses in wikitext */
-table#toc,
-table.toc {
-       border-collapse: collapse;
-}
-
-/* Remove additional paddings inside table-cells that are not present in <div>s */
-table#toc td,
-table.toc td {
-       padding: 0;
-}
-
-#toc h2,
-.toc h2 {
-       display: inline;
-       border: none;
-       padding: 0;
-       font-size: 100%;
-       font-weight: bold;
-}
-
-#toc ul,
-.toc ul {
-       list-style-type: none;
-       list-style-image: none;
-       padding: 0;
-       text-align: left;
-}
-
-#toc ul ul,
-.toc ul ul {
-       margin: 0 0 0 2em;
-}
-
-#toc .toctoggle,
-.toc .toctoggle {
-       font-size: 94%;
-}
-
-.error {
-       color: red;
-       font-size: larger;
-}
-
-/* preference page with js-genrated toc */
-#preftoc {
-       float: left;
-       margin: 1em 1em 1em 1em;
-       width: 13em;
-}
-
-#preftoc li {
-       border: 1px solid White;
-}
-
-#preftoc li.selected {
-       background-color: #f9f9f9;
-       border: 1px dashed #aaaaaa;
-}
-
-#preftoc a,
-#preftoc a:active {
-       display: block;
-       color: #005189;
-}
-
-.mw-prefs-buttons {
-       clear: left;
-       float: left;
-       margin-top: 1em;
-}
-
-div.htmlform-tip {
-       font-size: 94%;
-       margin-top: 0.4em;
-       color: #666;
-}
-
-fieldset.prefsection {
-       margin-top: 1em;
-}
-
-fieldset.operaprefsection {
-       margin-left: 15em;
-}
-
-/* emulate center */
-.center {
-       width: 100%;
-       text-align: center;
-}
-
-*.center * {
-       margin-left: auto;
-       margin-right: auto;
-}
-
-/* small for tables and similar */
-.small {
-       font-size: 94%;
-}
-
-table.small {
-       font-size: 100%;
-}
-
-/* use this instead of #toc for page content */
-.toccolours {
-       border: 1px solid #aaaaaa;
-       background-color: #f9f9f9;
-       padding: 5px;
-       font-size: 95%;
-}
-
-#siteNotice {
-       border: 1px solid #aaaaaa;
-       padding-left: 0.5em;
-       padding-right: 0.5em;
-}
-
-.redirectText {
-       font-size: 150%;
-       margin: 5px;
-}
-
-.sharedUploadNotice {
-       font-style: italic;
-}
-
-span.unpatrolled {
-       font-weight: bold;
-       color: red;
-}
-
-span.updatedmarker {
-       color: black;
-       background-color: #00FF00;
-}
-
-div.gallerybox {
-       width: 150px;
-}
-
-span.comment {
-       font-style: italic;
-}
-
-span.changedby {
-       font-size: 95%;
-}
-
-.previewnote {
-       text-align: center;
-       color: #cc0000;
-}
-
-.editExternally {
-       border-style: solid;
-       border-width: 1px;
-       border-color: gray;
-       background: #ffffff;
-       padding: 3px;
-       margin-top: 0.5em;
-       float: left;
-       font-size: small;
-       text-align: center;
-}
-
-.editExternallyHelp {
-       font-style: italic;
-       color: gray;
-}
-
-li span.deleted {
-       text-decoration: line-through;
-       color: #888;
-       font-style: italic;
-}
-
-/* Classes for Exif data display */
-table.mw_metadata {
-       margin-left: 0.5em;
-}
-
-table.mw_metadata caption {
-       font-weight: bold;
-}
-
-table.mw_metadata th {
-       font-weight: normal;
-}
-
-table.mw_metadata td {
-       padding: 0.1em;
-}
-
-table.mw_metadata {
-       border: none;
-       border-collapse: collapse;
-}
-
-table.mw_metadata td,
-table.mw_metadata th {
-       border: 1px solid #aaaaaa;
-       padding-left: 4px;
-       padding-right: 4px;
-}
-
-table.mw_metadata th {
-       background-color: #f9f9f9;
-}
-
-table.mw_metadata td {
-       background-color: #fcfcfc;
-}
-
-table.mw_metadata td.spacer {
-       background: inherit;
-       border-top: none;
-       border-bottom: none;
-}
-
-table.collapsed tr.collapsable {
-       display: none;
-}
-
-.visualClear {
-       clear: both;
-}
-
-/* Allmessages table */
-#allmessagestable th {
-       background-color: #b2b2ff;
-}
-
-#allmessagestable tr.orig {
-       background-color: #ffe2e2;
-}
-
-#allmessagestable tr.new {
-       background-color: #e2ffe2;
-}
-
-#allmessagestable tr.def {
-       background-color: #f0f0ff;
-}
-
-#jump-to-nav {
-       display: none;
-}
-
-div.multipageimagenavbox {
-       border: solid 1px silver;
-       padding: 4px;
-       margin: 1em;
-       background: #f0f0f0;
-}
-
-div.multipageimagenavbox div.thumb {
-       border: none;
-       margin-left: 2em;
-       margin-right: 2em;
-}
-
-div.multipageimagenavbox hr {
-       margin: 6px;
-}
-
-table.multipageimage td {
-       text-align: center;
-}
-
-/*
-  Table pager (e.g. Special:Imagelist)
-  - remove underlines from the navigation link
-  - collapse borders
-  - set the borders to outsets (similar to Special:Allmessages)
-  - remove line wrapping for all td and th, set background color
-  - restore line wrapping for the last two table cells (description and size)
-*/
-.TablePager_nav a {
-       text-decoration: none;
-}
-
-.TablePager {
-       border-collapse: collapse;
-}
-
-.TablePager,
-.TablePager td,
-.TablePager th {
-       border: 0.15em solid #777777;
-       padding: 0 0.15em 0 0.15em;
-}
-
-.TablePager th {
-       background-color: #eeeeff;
-}
-
-.TablePager td {
-       background-color: #ffffff;
-}
-
-.TablePager tr:hover td {
-       background-color: #eeeeff;
-}
-
-.imagelist td,
-.imagelist th {
-       white-space: nowrap;
-}
-
-.imagelist .TablePager_col_links {
-       background-color: #eeeeff;
-}
-
-.imagelist .TablePager_col_img_description {
-       white-space: normal;
-}
-
-.imagelist th.TablePager_sort {
-       background-color: #ccccff;
-}
-
-.templatesUsed {
-       margin-top: 1em;
-}
-
-.MediaTransformError {
-       border: thin solid #777;
-       background-color: #ccc;
-       padding: 0.1em;
-}
-
-.MediaTransformError td {
-       text-align: center;
-       vertical-align: middle;
-       font-size: 90%;
-}
-
-form#specialpages {
-       display: inline;
-}
-
-body {
-       direction: ltr;
-       unicode-bidi: embed;
-       background-color: #ffffec;
-}
-
-body.ns-0 {
-       background-color: white;
-}
-
-/** RTL specific CSS starts here **/
-
-/**
- * Lists:
- * The following lines don't have a visible effect on non-Gecko browsers
- * They fix a problem with Gecko browsers rendering lists to the right of
- * left-floated objects in an RTL layout.
- */
-/* @noflip */
-html > body.rtl div#article ul {
-       display: table;
-}
-
-/* @noflip */
-html > body.rtl div#bodyContent ul#filetoc {
-       display: block;
-}
-
-/* RTL specific CSS ends here **/
diff --git a/skins/common/protect.js b/skins/common/protect.js
deleted file mode 100644 (file)
index dc142ca..0000000
+++ /dev/null
@@ -1,387 +0,0 @@
-( function ( mw, $ ) {
-
-var ProtectionForm = window.ProtectionForm = {
-       existingMatch: false,
-
-       /**
-        * Set up the protection chaining interface (i.e. "unlock move permissions" checkbox)
-        * on the protection form
-        *
-        * @param opts Object : parameters with members:
-        *     tableId              Identifier of the table containing UI bits
-        *     labelText            Text to use for the checkbox label
-        *     numTypes             The number of protection types
-        *     existingMatch        True if all the existing expiry times match
-        */
-       init: function ( opts ) {
-               var box, boxbody, row, cell, check, label;
-
-               if ( !( document.createTextNode && document.getElementById && document.getElementsByTagName ) ) {
-                       return false;
-               }
-
-               box = document.getElementById( opts.tableId );
-               if ( !box ) {
-                       return false;
-               }
-
-               boxbody = box.getElementsByTagName( 'tbody' )[0];
-               row = document.createElement( 'tr' );
-               boxbody.insertBefore( row, boxbody.firstChild.nextSibling );
-
-               this.existingMatch = opts.existingMatch;
-
-               cell = document.createElement( 'td' );
-               row.appendChild( cell );
-               // If there is only one protection type, there is nothing to chain
-               if ( opts.numTypes > 1 ) {
-                       check = document.createElement( 'input' );
-                       check.id = 'mwProtectUnchained';
-                       check.type = 'checkbox';
-                       $( check ).click( function () {
-                               ProtectionForm.onChainClick();
-                       } );
-
-                       label = document.createElement( 'label' );
-                       label.htmlFor = 'mwProtectUnchained';
-                       label.appendChild( document.createTextNode( opts.labelText ) );
-
-                       cell.appendChild( check );
-                       cell.appendChild( document.createTextNode( ' ' ) );
-                       cell.appendChild( label );
-
-                       check.checked = !this.areAllTypesMatching();
-                       this.enableUnchainedInputs( check.checked );
-               }
-
-               $( '#mwProtect-reason' ).byteLimit( 180 );
-
-               this.updateCascadeCheckbox();
-
-               return true;
-       },
-
-       /**
-        * Sets the disabled attribute on the cascade checkbox depending on the current selected levels
-        */
-       updateCascadeCheckbox: function () {
-               var i, lists, items, selected;
-
-               // For non-existent titles, there is no cascade option
-               if ( !document.getElementById( 'mwProtect-cascade' ) ) {
-                       return;
-               }
-               lists = this.getLevelSelectors();
-               for ( i = 0; i < lists.length; i++ ) {
-                       if ( lists[i].selectedIndex > -1 ) {
-                               items = lists[i].getElementsByTagName( 'option' );
-                               selected = items[ lists[i].selectedIndex ].value;
-                               if ( !this.isCascadeableLevel( selected ) ) {
-                                       document.getElementById( 'mwProtect-cascade' ).checked = false;
-                                       document.getElementById( 'mwProtect-cascade' ).disabled = true;
-                                       return;
-                               }
-                       }
-               }
-               document.getElementById( 'mwProtect-cascade' ).disabled = false;
-       },
-
-       /**
-        * Checks if a cerain protection level is cascadeable.
-        * @param level {String}
-        * @return {Boolean}
-        */
-       isCascadeableLevel: function (  level ) {
-               var cascadeLevels, len, i;
-
-               cascadeLevels = mw.config.get( 'wgCascadeableLevels' );
-               // cascadeLevels isn't defined on all pages
-               if ( cascadeLevels ) {
-                       for ( i = 0, len = cascadeLevels.length; i < len; i += 1 ) {
-                               if ( cascadeLevels[i] === level ) {
-                                       return true;
-                               }
-                       }
-               }
-               return false;
-       },
-
-       /**
-        * When protection levels are locked together, update the rest
-        * when one action's level changes
-        *
-        * @param source Element Level selector that changed
-        */
-       updateLevels: function ( source ) {
-               if ( !this.isUnchained() ) {
-                       this.setAllSelectors( source.selectedIndex );
-               }
-               this.updateCascadeCheckbox();
-       },
-
-       /**
-        * When protection levels are locked together, update the
-        * expiries when one changes
-        *
-        * @param source Element expiry input that changed
-        */
-
-       updateExpiry: function ( source ) {
-               var expiry, listId, list;
-
-               if ( !this.isUnchained() ) {
-                       expiry = source.value;
-                       this.forEachExpiryInput( function ( element ) {
-                               element.value = expiry;
-                       } );
-               }
-               listId = source.id.replace( /^mwProtect-(\w+)-expires$/, 'mwProtectExpirySelection-$1' );
-               list = document.getElementById( listId );
-               if ( list && list.value !== 'othertime' ) {
-                       if ( this.isUnchained() ) {
-                               list.value = 'othertime';
-                       } else {
-                               this.forEachExpirySelector( function ( element ) {
-                                       element.value = 'othertime';
-                               } );
-                       }
-               }
-       },
-
-       /**
-        * When protection levels are locked together, update the
-        * expiry lists when one changes and clear the custom inputs
-        *
-        * @param source Element expiry selector that changed
-        */
-       updateExpiryList: function ( source ) {
-               var expiry;
-               if ( !this.isUnchained() ) {
-                       expiry = source.value;
-                       this.forEachExpirySelector( function ( element ) {
-                               element.value = expiry;
-                       } );
-                       this.forEachExpiryInput( function ( element ) {
-                               element.value = '';
-                       } );
-               }
-       },
-
-       /**
-        * Update chain status and enable/disable various bits of the UI
-        * when the user changes the "unlock move permissions" checkbox
-        */
-       onChainClick: function () {
-               if ( this.isUnchained() ) {
-                       this.enableUnchainedInputs( true );
-               } else {
-                       this.setAllSelectors( this.getMaxLevel() );
-                       this.enableUnchainedInputs( false );
-               }
-               this.updateCascadeCheckbox();
-       },
-
-       /**
-        * Returns true if the named attribute in all objects in the given array are matching
-        */
-       matchAttribute: function ( objects, attrName ) {
-               var i, element, value;
-
-               // Check levels
-               value = null;
-               for ( i = 0; i < objects.length; i++ ) {
-                       element = objects[i];
-                       if ( value === null ) {
-                               value = element[attrName];
-                       } else {
-                               if ( value !== element[attrName] ) {
-                                       return false;
-                               }
-                       }
-               }
-               return true;
-       },
-
-       /**
-        * Are all actions protected at the same level, with the same expiry time?
-        *
-        * @return boolean
-        */
-       areAllTypesMatching: function () {
-               return this.existingMatch
-                       && this.matchAttribute( this.getLevelSelectors(), 'selectedIndex' )
-                       && this.matchAttribute( this.getExpirySelectors(), 'selectedIndex' )
-                       && this.matchAttribute( this.getExpiryInputs(), 'value' );
-       },
-
-       /**
-        * Is protection chaining off?
-        *
-        * @return bool
-        */
-       isUnchained: function () {
-               var element = document.getElementById( 'mwProtectUnchained' );
-               return element
-                       ? element.checked
-                       : true; // No control, so we need to let the user set both levels
-       },
-
-       /**
-        * Find the highest protection level in any selector
-        */
-       getMaxLevel: function () {
-               var maxIndex = -1;
-               this.forEachLevelSelector( function ( element ) {
-                       if ( element.selectedIndex > maxIndex ) {
-                               maxIndex = element.selectedIndex;
-                       }
-               } );
-               return maxIndex;
-       },
-
-       /**
-        * Protect all actions at the specified level
-        *
-        * @param index int Protection level
-        */
-       setAllSelectors: function ( index ) {
-               this.forEachLevelSelector( function ( element ) {
-                       if ( element.selectedIndex !== index ) {
-                               element.selectedIndex = index;
-                       }
-               } );
-       },
-
-       /**
-        * Apply a callback to each protection selector
-        *
-        * @param func callable Callback function
-        */
-       forEachLevelSelector: function ( func ) {
-               var i, selectors;
-
-               selectors = this.getLevelSelectors();
-               for ( i = 0; i < selectors.length; i++ ) {
-                       func( selectors[i] );
-               }
-       },
-
-       /**
-        * Get a list of all protection selectors on the page
-        *
-        * @return Array
-        */
-       getLevelSelectors: function () {
-               var i, ours, all, element;
-
-               all = document.getElementsByTagName( 'select' );
-               ours = [];
-               for ( i = 0; i < all.length; i++ ) {
-                       element = all[i];
-                       if ( element.id.match( /^mwProtect-level-/ ) ) {
-                               ours[ours.length] = element;
-                       }
-               }
-               return ours;
-       },
-
-       /**
-        * Apply a callback to each expiry input
-        *
-        * @param func callable Callback function
-        */
-       forEachExpiryInput: function ( func ) {
-               var i, inputs;
-
-               inputs = this.getExpiryInputs();
-               for ( i = 0; i < inputs.length; i++ ) {
-                       func( inputs[i] );
-               }
-       },
-
-       /**
-        * Get a list of all expiry inputs on the page
-        *
-        * @return Array
-        */
-       getExpiryInputs: function () {
-               var i, all, element, ours;
-
-               all = document.getElementsByTagName( 'input' );
-               ours = [];
-               for ( i = 0; i < all.length; i++ ) {
-                       element = all[i];
-                       if ( element.name.match( /^mwProtect-expiry-/ ) ) {
-                               ours[ours.length] = element;
-                       }
-               }
-               return ours;
-       },
-
-       /**
-        * Apply a callback to each expiry selector list
-        * @param func callable Callback function
-        */
-       forEachExpirySelector: function ( func ) {
-               var i, inputs;
-
-               inputs = this.getExpirySelectors();
-               for ( i = 0; i < inputs.length; i++ ) {
-                       func( inputs[i] );
-               }
-       },
-
-       /**
-        * Get a list of all expiry selector lists on the page
-        *
-        * @return Array
-        */
-       getExpirySelectors: function () {
-               var i, all, ours, element;
-
-               all = document.getElementsByTagName( 'select' );
-               ours = [];
-               for ( i = 0; i < all.length; i++ ) {
-                       element = all[i];
-                       if ( element.id.match( /^mwProtectExpirySelection-/ ) ) {
-                               ours[ours.length] = element;
-                       }
-               }
-               return ours;
-       },
-
-       /**
-        * Enable/disable protection selectors and expiry inputs
-        *
-        * @param val boolean Enable?
-        */
-       enableUnchainedInputs: function ( val ) {
-               var first = true;
-
-               this.forEachLevelSelector( function ( element ) {
-                       if ( first ) {
-                               first = false;
-                       } else {
-                               element.disabled = !val;
-                       }
-               } );
-               first = true;
-               this.forEachExpiryInput( function ( element ) {
-                       if ( first ) {
-                               first = false;
-                       } else {
-                               element.disabled = !val;
-                       }
-               } );
-               first = true;
-               this.forEachExpirySelector( function ( element ) {
-                       if ( first ) {
-                               first = false;
-                       } else {
-                               element.disabled = !val;
-                       }
-               } );
-       }
-};
-
-}( mediaWiki, jQuery ) );
diff --git a/skins/common/shared.css b/skins/common/shared.css
deleted file mode 100644 (file)
index a5612e2..0000000
+++ /dev/null
@@ -1,1292 +0,0 @@
-/**
- * CSS in this file is used by *all* skins (that have any CSS at all). Be
- * careful what you put in here, since what looks good in one skin may not in
- * another, but don't ignore the poor pre-Monobook users either.
- */
-
-/* GENERAL CLASSES FOR DIRECTIONALITY SUPPORT */
-
-/**
- * These classes should be used for text depending on the content direction.
- * Content stuff like editsection, ul/ol and TOC depend on this.
- */
-.mw-content-ltr {
-       /* @noflip */
-       direction: ltr;
-}
-
-.mw-content-rtl {
-       /* @noflip */
-       direction: rtl;
-}
-
-/* Most input fields should be in site direction */
-.sitedir-ltr textarea,
-.sitedir-ltr input {
-       /* @noflip */
-       direction: ltr;
-}
-
-.sitedir-rtl textarea,
-.sitedir-rtl input {
-       /* @noflip */
-       direction: rtl;
-}
-
-/* User-Agent styles for new HTML5 elements */
-mark {
-       background-color: yellow;
-       color: black;
-}
-
-/* Helper for wbr element on IE 8+; in HTML5, but not supported by default as of IE 11. */
-/* Note canonical HTML5 styles recommend "content: \u200B", but this doesn't work as of IE 11. */
-wbr {
-       display: inline-block;
-}
-
-/* Input types that should follow user direction, like buttons */
-/* TODO: What about buttons in wikipage content ? */
-input[type="submit"],
-input[type="button"],
-input[type="reset"],
-input[type="file"] {
-       direction: ltr;
-}
-
-/* Override default values */
-textarea[dir="ltr"],
-input[dir="ltr"] {
-       /* @noflip */
-       direction: ltr;
-}
-
-textarea[dir="rtl"],
-input[dir="rtl"] {
-       /* @noflip */
-       direction: rtl;
-}
-
-/* Default style for semantic tags */
-abbr[title],
-.explain[title] {
-       border-bottom: 1px dotted;
-       cursor: help;
-}
-
-/* Colored watchlist and recent changes numbers */
-.mw-plusminus-pos {
-       color: #006400; /* dark green */
-}
-
-.mw-plusminus-neg {
-       color: #8b0000; /* dark red */
-}
-
-.mw-plusminus-null {
-       color: #aaa; /* gray */
-}
-
-/**
- * Links to redirects appear italicized on [[Special:AllPages]], [[Special:PrefixIndex]],
- * [[Special:Watchlist/edit]] and in category listings.
- */
-.allpagesredirect,
-.redirect-in-category,
-.watchlistredir {
-       font-style: italic;
-}
-
-/* Comment and username portions of RC entries */
-span.comment {
-       font-style: italic;
-}
-
-span.changedby {
-       font-size: 95%;
-}
-
-/* Math */
-.texvc {
-       direction: ltr;
-       unicode-bidi: embed;
-}
-
-img.tex {
-       vertical-align: middle;
-}
-
-span.texhtml {
-       font-family: serif;
-}
-
-/**
- * Add a bit of margin space between the preview and the toolbar.
- * This replaces the ugly <p><br /></p> we used to insert into the page source
- */
-#wikiPreview.ontop {
-       margin-bottom: 1em;
-}
-
-/* Stop floats from intruding into edit area in previews */
-#editform,
-#toolbar,
-#wpTextbox1 {
-       clear: both;
-}
-
-#toolbar img {
-       cursor: pointer;
-}
-
-/**
- * File description page
- */
-
-div.mw-filepage-resolutioninfo {
-       font-size: smaller;
-}
-
-/**
- * File histories
- */
-h2#filehistory {
-       clear: both;
-}
-
-table.filehistory th,
-table.filehistory td {
-       vertical-align: top;
-}
-
-table.filehistory th {
-       text-align: left;
-}
-
-table.filehistory td.mw-imagepage-filesize,
-table.filehistory th.mw-imagepage-filesize {
-       white-space: nowrap;
-}
-
-table.filehistory td.filehistory-selected {
-       font-weight: bold;
-}
-
-/**
- * Add a checkered background image on hover for file
- * description pages. (bug 26470)
- */
-.filehistory a img,
-#file img:hover {
-       /* @embed */
-       background: white url(images/Checker-16x16.png) repeat;
-}
-
-/**
- * rev_deleted stuff
- */
-li span.deleted,
-span.history-deleted {
-       text-decoration: line-through;
-       color: #888;
-       font-style: italic;
-}
-
-/**
- * Patrol stuff
- */
-.not-patrolled {
-       background-color: #ffa;
-}
-
-.unpatrolled {
-       font-weight: bold;
-       color: red;
-}
-
-div.patrollink {
-       font-size: 75%;
-       text-align: right;
-}
-
-/**
- * Forms
- */
-td.mw-label {
-       text-align: right;
-}
-
-td.mw-input {
-       text-align: left;
-}
-
-td.mw-submit {
-       text-align: left;
-}
-
-td.mw-label {
-       vertical-align: top;
-}
-
-.prefsection td.mw-label {
-       width: 20%;
-}
-
-.prefsection table {
-       width: 100%;
-}
-
-.prefsection table.mw-htmlform-matrix {
-       width: auto;
-}
-
-.mw-icon-question {
-       /* SVG support using a transparent gradient to guarantee cross-browser
-        * compatibility (browsers able to understand gradient syntax support also SVG).
-        * http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique */
-       background-image: url(images/question-small.png);
-       /* @embed */
-       background-image: -webkit-linear-gradient(transparent, transparent), url(images/question.svg);
-       /* @embed */
-       background-image: linear-gradient(transparent, transparent), url(images/question.svg);
-       background-repeat: no-repeat;
-       background-size: 13px 13px;
-       display: inline-block;
-       height: 13px;
-       width: 13px;
-       margin-left: 4px;
-}
-
-.mw-icon-question:lang(ar),
-.mw-icon-question:lang(fa),
-.mw-icon-question:lang(ur) {
-       -webkit-transform: scaleX(-1);
-       -ms-transform: scaleX(-1);
-       transform: scaleX(-1);
-}
-
-td.mw-submit {
-       white-space: nowrap;
-}
-
-table.mw-htmlform-nolabel td.mw-label {
-       width: 1px;
-}
-
-tr.mw-htmlform-vertical-label td.mw-label {
-       text-align: left !important;
-}
-
-.mw-htmlform-invalid-input td.mw-input input {
-       border-color: red;
-}
-
-.mw-htmlform-flatlist div.mw-htmlform-flatlist-item {
-       display: inline;
-       margin-right: 1em;
-       white-space: nowrap;
-}
-
-.mw-htmlform-matrix td {
-       padding-left: 0.5em;
-       padding-right: 0.5em;
-}
-
-input#wpSummary {
-       width: 80%;
-       margin-bottom: 1em;
-}
-
-/**
- * Image captions
- */
-/* @noflip */
-.mw-content-ltr .thumbcaption {
-       text-align: left;
-}
-
-/* @noflip */
-.mw-content-rtl .thumbcaption {
-       text-align: right;
-}
-
-/* @noflip */
-.mw-content-ltr .magnify {
-       float: right;
-}
-
-/* @noflip */
-.mw-content-rtl .magnify {
-       float: left;
-}
-
-/**
- * Categories
- */
-#catlinks {
-       /**
-        * Overrides text justification (user preference)
-        * See bug 31990
-        */
-       text-align: left;
-}
-
-.catlinks ul {
-       display: inline;
-       margin: 0;
-       padding: 0;
-       list-style: none;
-       list-style-type: none;
-       list-style-image: none;
-       vertical-align: middle !ie;
-}
-
-.catlinks li {
-       display: inline-block;
-       line-height: 1.25em;
-       border-left: 1px solid #AAA;
-       margin: 0.125em 0;
-       padding: 0 0.5em;
-       zoom: 1;
-       display: inline !ie;
-}
-
-.catlinks li:first-child {
-       padding-left: 0.25em;
-       border-left: none;
-}
-
-/* (bug 5346) make category redirects italic */
-.catlinks li a.mw-redirect {
-       font-style: italic;
-}
-
-/**
- * Hidden categories
- */
-.mw-hidden-cats-hidden {
-       display: none;
-}
-
-.catlinks-allhidden {
-       display: none;
-}
-
-/* Convenience links to edit block, delete and protect reasons */
-p.mw-ipb-conveniencelinks,
-p.mw-protect-editreasons,
-p.mw-filedelete-editreasons,
-p.mw-delete-editreasons,
-p.mw-revdel-editreasons {
-       font-size: 90%;
-       text-align: right;
-}
-
-/**
- * OpenSearch ajax suggestions
- */
-.os-suggest {
-       overflow: auto;
-       overflow-x: hidden;
-       position: absolute;
-       top: 0;
-       left: 0;
-       width: 0;
-       background-color: white;
-       border-style: solid;
-       border-color: #AAAAAA;
-       border-width: 1px;
-       z-index: 99;
-       font-size: 95%;
-}
-
-table.os-suggest-results {
-       font-size: 95%;
-       cursor: pointer;
-       border: 0;
-       border-collapse: collapse;
-       width: 100%;
-}
-
-.os-suggest-result,
-.os-suggest-result-hl {
-       white-space: nowrap;
-       background-color: white;
-       color: black;
-       padding: 2px;
-}
-
-.os-suggest-result-hl,
-.os-suggest-result-hl-webkit {
-       background-color: #4C59A6;
-       color: white;
-}
-
-.os-suggest-toggle {
-       position: relative;
-       left: 1ex;
-       font-size: 65%;
-}
-
-.os-suggest-toggle-def {
-       position: absolute;
-       top: 0;
-       left: 0;
-       font-size: 65%;
-       visibility: hidden;
-}
-
-/* Page history styling */
-
-/* The auto-generated edit comments */
-.autocomment {
-       color: gray;
-}
-
-#pagehistory .history-user {
-       margin-left: 0.4em;
-       margin-right: 0.2em;
-}
-
-#pagehistory span.minor {
-       font-weight: bold;
-}
-
-#pagehistory li {
-       border: 1px solid white;
-}
-
-#pagehistory li.selected {
-       background-color: #f9f9f9;
-       border: 1px dashed #aaa;
-}
-
-.mw-history-revisiondelete-button, #mw-fileduplicatesearch-icon {
-       float: right;
-}
-
-/** Generic minor/bot/newpage styling (recent changes) */
-.newpage,
-.minoredit,
-.botedit {
-       font-weight: bold;
-}
-
-#shared-image-dup,
-#shared-image-conflict {
-       font-style: italic;
-}
-
-/**
- * Recreating deleted page warning
- * Reupload file warning
- * Page protection warning
- * incl. log entries for these warnings
- */
-div.mw-warning-with-logexcerpt {
-       padding: 3px;
-       margin-bottom: 3px;
-       border: 2px solid #2F6FAB;
-       clear: both;
-}
-
-div.mw-warning-with-logexcerpt ul li {
-       font-size: 90%;
-}
-
-/* (show/hide) revision deletion links */
-span.mw-revdelundel-link,
-strong.mw-revdelundel-link {
-       font-size: 90%;
-}
-
-span.mw-revdelundel-hidden,
-input.mw-revdelundel-hidden {
-       visibility: hidden;
-}
-
-td.mw-revdel-checkbox,
-th.mw-revdel-checkbox {
-       padding-right: 10px;
-       text-align: center;
-}
-
-/* red links; see bug 36276 */
-a.new {
-       color: #BA0000;
-}
-
-/* feed links */
-a.feedlink {
-       /* SVG support using a transparent gradient to guarantee cross-browser
-        * compatibility (browsers able to understand gradient syntax support also SVG).
-        * http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique */
-       background-image: url(images/feed-icon.png);
-       /* @embed */
-       background-image: -webkit-linear-gradient(transparent, transparent), url(images/feed-icon.svg);
-       /* @embed */
-       background-image: linear-gradient(transparent, transparent), url(images/feed-icon.svg);
-       background-position: center left;
-       background-repeat: no-repeat;
-       background-size: 12px 12px;
-       padding-left: 16px;
-}
-
-/* Plainlinks - this can be used to switch
- * off special external link styling */
-.plainlinks a {
-       background: none !important;
-       padding: 0 !important;
-}
-
-/* External URLs should always be treated as LTR (bug 4330) */
-/* @noflip */ .rtl a.external.free,
-.rtl a.external.autonumber {
-       direction: ltr;
-       unicode-bidi: embed;
-}
-
-/**
- * wikitable class for skinning normal tables
- * keep in sync with commonPrint.css
- */
-table.wikitable {
-       margin: 1em 0;
-       background-color: #f9f9f9;
-       border: 1px #aaa solid;
-       border-collapse: collapse;
-       color: black;
-}
-
-table.wikitable > tr > th,
-table.wikitable > tr > td,
-table.wikitable > * > tr > th,
-table.wikitable > * > tr > td {
-       border: 1px #aaa solid;
-       padding: 0.2em;
-}
-
-table.wikitable > tr > th,
-table.wikitable > * > tr > th {
-       background-color: #f2f2f2;
-       text-align: center;
-}
-
-table.wikitable > caption {
-       font-weight: bold;
-}
-
-/**
- * Hide collapsable rows in a collapsed table.
- *
- * Used by ImagePage and the mediawiki.action.view.metadata module.
- */
-table.collapsed tr.collapsable {
-       display: none;
-}
-
-/* success and error messages */
-.error,
-.warning,
-.success {
-       font-size: larger;
-}
-
-.error {
-       color: #cc0000;
-}
-
-.warning {
-       color: #705000;
-}
-
-.success {
-       color: #009000;
-}
-
-.errorbox,
-.warningbox,
-.successbox {
-       border: 1px solid;
-       padding: .5em 1em;
-       margin-bottom: 1em;
-       display: -moz-inline-block;
-       display: inline-block;
-       zoom: 1;
-       *display: inline;
-}
-
-.errorbox h2,
-.warningbox h2,
-.successbox h2 {
-       font-size: 1em;
-       color: inherit;
-       font-weight: bold;
-       display: inline;
-       margin: 0 .5em 0 0;
-       border: none;
-}
-
-.errorbox {
-       color: #cc0000;
-       border-color: #fac5c5;
-       background-color: #fae3e3;
-}
-
-.warningbox {
-       color: #705000;
-       border-color: #fde29b;
-       background-color: #fdf1d1;
-}
-
-.successbox {
-       color: #009000;
-       border-color: #b7fdb5;
-       background-color: #e1fddf;
-}
-
-/* general info/warning box for SP */
-.mw-infobox {
-       border: 2px solid #ff7f00;
-       margin: 0.5em;
-       clear: left;
-       overflow: hidden;
-}
-
-.mw-infobox-left {
-       margin: 7px;
-       float: left;
-       width: 35px;
-}
-
-.mw-infobox-right {
-       margin: 0.5em 0.5em 0.5em 49px;
-}
-
-/* Note on preview page */
-.previewnote {
-       color: #c00;
-       margin-bottom: 1em;
-}
-
-.previewnote p {
-       text-indent: 3em;
-       margin: 0.8em 0;
-}
-
-.visualClear {
-       clear: both;
-}
-
-/**
- * Data table style
- *
- * Transparent table with suddle borders
- * and blue row-highlighting.
- */
-.mw-datatable {
-       border-collapse: collapse;
-}
-
-.mw-datatable,
-.mw-datatable td,
-.mw-datatable th {
-       border: 1px solid #aaaaaa;
-       padding: 0 0.15em 0 0.15em;
-}
-
-.mw-datatable th {
-       background-color: #ddddff;
-}
-
-.mw-datatable td {
-       background-color: #ffffff;
-}
-
-.mw-datatable tr:hover td {
-       background-color: #eeeeff;
-}
-
-/**
- * TablePager tables generated by the TablePager PHP class
- * in MediaWiki (e.g. Special:ListFiles).
- */
-.TablePager {
-       min-width: 80%;
-}
-
-.TablePager_nav {
-       margin: 0 auto;
-}
-
-.TablePager_nav td {
-       padding: 3px;
-       text-align: center;
-}
-
-.TablePager_nav a {
-       text-decoration: none;
-}
-
-.imagelist td,
-.imagelist th {
-       white-space: nowrap;
-}
-
-.imagelist .TablePager_col_links {
-       background-color: #eeeeff;
-}
-
-.imagelist .TablePager_col_img_description {
-       white-space: normal;
-}
-
-.imagelist th.TablePager_sort {
-       background-color: #ccccff;
-}
-
-/* filetoc */
-ul#filetoc {
-       text-align: center;
-       border: 1px solid #aaaaaa;
-       background-color: #f9f9f9;
-       padding: 5px;
-       font-size: 95%;
-       margin-bottom: 0.5em;
-       margin-left: 0;
-       margin-right: 0;
-}
-
-#filetoc li {
-       display: inline;
-       list-style-type: none;
-       padding-right: 2em;
-}
-
-/* Classes for Exif data display */
-table.mw_metadata {
-       font-size: 0.8em;
-       margin-left: 0.5em;
-       margin-bottom: 0.5em;
-       width: 400px;
-}
-
-table.mw_metadata caption {
-       font-weight: bold;
-}
-
-table.mw_metadata th {
-       font-weight: normal;
-}
-
-table.mw_metadata td {
-       padding: 0.1em;
-}
-
-table.mw_metadata {
-       border: none;
-       border-collapse: collapse;
-}
-
-table.mw_metadata td,
-table.mw_metadata th {
-       text-align: center;
-       border: 1px solid #aaaaaa;
-       padding-left: 5px;
-       padding-right: 5px;
-}
-
-table.mw_metadata th {
-       background-color: #f9f9f9;
-}
-
-table.mw_metadata td {
-       background-color: #fcfcfc;
-}
-
-table.mw_metadata ul.metadata-langlist {
-       list-style-type: none;
-       list-style-image: none;
-       padding-right: 5px;
-       padding-left: 5px;
-       margin: 0;
-}
-
-/* Correct directionality when page dir is different from site/user dir */
-.mw-content-ltr ul,
-.mw-content-rtl .mw-content-ltr ul {
-       /* @noflip */
-       margin: 0.3em 0 0 1.6em;
-       padding: 0;
-}
-
-.mw-content-rtl ul,
-.mw-content-ltr .mw-content-rtl ul {
-       /* @noflip */
-       margin: 0.3em 1.6em 0 0;
-       padding: 0;
-}
-
-.mw-content-ltr ol,
-.mw-content-rtl .mw-content-ltr ol {
-       /* @noflip */
-       margin: 0.3em 0 0 3.2em;
-       padding: 0;
-}
-
-.mw-content-rtl ol,
-.mw-content-ltr .mw-content-rtl ol {
-       /* @noflip */
-       margin: 0.3em 3.2em 0 0;
-       padding: 0;
-}
-
-/* @noflip */
-.mw-content-ltr dd,
-.mw-content-rtl .mw-content-ltr dd {
-       margin-left: 1.6em;
-       margin-right: 0;
-}
-
-/* @noflip */
-.mw-content-rtl dd,
-.mw-content-ltr .mw-content-rtl dd {
-       margin-right: 1.6em;
-       margin-left: 0;
-}
-
-/* Galleries */
-/* These display attributes look nonsensical, but are needed to support IE and FF2 */
-/* Don't forget to update commonPrint.css */
-li.gallerybox {
-       vertical-align: top;
-       display: -moz-inline-box;
-       display: inline-block;
-}
-
-ul.gallery,
-li.gallerybox {
-       zoom: 1;
-       *display: inline;
-}
-
-ul.gallery {
-       margin: 2px;
-       padding: 2px;
-       display: block;
-}
-
-li.gallerycaption {
-       font-weight: bold;
-       text-align: center;
-       display: block;
-       word-wrap: break-word;
-}
-
-li.gallerybox div.thumb {
-       text-align: center;
-       border: 1px solid #ccc;
-       background-color: #f9f9f9;
-       margin: 2px;
-}
-
-li.gallerybox div.thumb img {
-       display: block;
-       margin: 0 auto;
-}
-
-div.gallerytext {
-       overflow: hidden;
-       font-size: 94%;
-       padding: 2px 4px;
-       word-wrap: break-word;
-}
-
-/* new gallery stuff */
-ul.mw-gallery-nolines li.gallerybox div.thumb {
-       background-color: transparent;
-       border: none;
-}
-
-ul.mw-gallery-nolines li.gallerybox div.gallerytext {
-       text-align: center;
-}
-
-/* height constrained gallery */
-
-ul.mw-gallery-packed li.gallerybox div.thumb,
-ul.mw-gallery-packed-overlay li.gallerybox div.thumb,
-ul.mw-gallery-packed-hover li.gallerybox div.thumb {
-       background-color: transparent;
-       border: none;
-}
-
-ul.mw-gallery-packed li.gallerybox div.thumb img,
-ul.mw-gallery-packed-overlay li.gallerybox div.thumb img,
-ul.mw-gallery-packed-hover li.gallerybox div.thumb img {
-       margin: 0 auto;
-}
-
-ul.mw-gallery-packed-hover li.gallerybox,
-ul.mw-gallery-packed-overlay li.gallerybox {
-       position: relative;
-}
-
-ul.mw-gallery-packed-hover div.gallerytextwrapper {
-       overflow: hidden;
-       height: 0;
-}
-
-ul.mw-gallery-packed-hover li.gallerybox:hover div.gallerytextwrapper,
-ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper,
-ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper {
-       position: absolute;
-       background: white;
-       background: rgba(255, 255, 255, 0.8);
-       padding: 5px 10px;
-       bottom: 0;
-       left: 0; /* Needed for IE */
-       height: auto;
-       font-weight: bold;
-       margin: 2px; /* correspond to style on div.thumb */
-}
-
-ul.mw-gallery-packed-hover,
-ul.mw-gallery-packed-overlay,
-ul.mw-gallery-packed {
-       text-align: center;
-}
-
-.mw-ajax-loader {
-       /* @embed */
-       background-image: url(images/ajax-loader.gif);
-       background-position: center center;
-       background-repeat: no-repeat;
-       padding: 16px;
-       position: relative;
-       top: -16px;
-}
-
-.mw-small-spinner {
-       padding: 10px !important;
-       margin-right: 0.6em;
-       /* @embed */
-       background-image: url(images/spinner.gif);
-       background-position: center center;
-       background-repeat: no-repeat;
-}
-
-/* Language specific height correction for titles. Ref Bug 29405 and Bug 30809 */
-/* Languages like hi or ml require slightly more vertical space to show diacritics properly */
-h1:lang(anp),
-h1:lang(as),
-h1:lang(bh), /* Macrolanguage, used on bh.wikipedia.org, should be removed one day */
-h1:lang(bho),
-h1:lang(bn),
-h1:lang(gu),
-h1:lang(hi),
-h1:lang(kn),
-h1:lang(ks),
-h1:lang(ml),
-h1:lang(mr),
-h1:lang(my),
-h1:lang(mai),
-h1:lang(ne),
-h1:lang(new),
-h1:lang(or),
-h1:lang(pa),
-h1:lang(pi),
-h1:lang(sa),
-h1:lang(ta),
-h1:lang(te) {
-       line-height: 1.6em !important;
-}
-
-h2:lang(anp), h3:lang(anp), h4:lang(anp), h5:lang(anp), h6:lang(anp),
-h2:lang(as), h3:lang(as), h4:lang(as), h5:lang(as), h6:lang(as),
-h2:lang(bho), h3:lang(bho), h4:lang(bho), h5:lang(bho), h6:lang(bho),
-h2:lang(bh), h3:lang(bh), h4:lang(bh), h5:lang(bh), h6:lang(bh),
-h2:lang(bn), h3:lang(bn), h4:lang(bn), h5:lang(bn), h6:lang(bn),
-h2:lang(gu), h3:lang(gu), h4:lang(gu), h5:lang(gu), h6:lang(gu),
-h2:lang(hi), h3:lang(hi), h4:lang(hi), h5:lang(hi), h6:lang(hi),
-h2:lang(kn), h3:lang(kn), h4:lang(kn), h5:lang(kn), h6:lang(kn),
-h2:lang(ks), h3:lang(ks), h4:lang(ks), h5:lang(ks), h6:lang(ks),
-h2:lang(ml), h3:lang(ml), h4:lang(ml), h5:lang(ml), h6:lang(ml),
-h2:lang(mr), h3:lang(mr), h4:lang(mr), h5:lang(mr), h6:lang(mr),
-h2:lang(my), h3:lang(my), h4:lang(my), h5:lang(my), h6:lang(my),
-h2:lang(mai), h3:lang(mai), h4:lang(mai), h5:lang(mai), h6:lang(mai),
-h2:lang(ne), h3:lang(ne), h4:lang(ne), h5:lang(ne), h6:lang(ne),
-h2:lang(new), h3:lang(new), h4:lang(new), h5:lang(new), h6:lang(new),
-h2:lang(or), h3:lang(or), h4:lang(or), h5:lang(or), h6:lang(or),
-h2:lang(pa), h3:lang(pa), h4:lang(pa), h5:lang(pa), h6:lang(pa),
-h2:lang(pi), h3:lang(pi), h4:lang(pi), h5:lang(pi), h6:lang(pi),
-h2:lang(sa), h3:lang(sa), h4:lang(sa), h5:lang(sa), h6:lang(sa),
-h2:lang(ta), h3:lang(ta), h4:lang(ta), h5:lang(ta), h6:lang(ta),
-h2:lang(te), h3:lang(te), h4:lang(te), h5:lang(te), h6:lang(te) {
-       line-height: 1.2em;
-}
-
-/* Localised ordered list numbering for some languages */
-ol:lang(bcc) li,
-ol:lang(bqi) li,
-ol:lang(fa) li,
-ol:lang(glk) li,
-ol:lang(kk-arab) li,
-ol:lang(mzn) li {
-       list-style-type: -moz-persian;
-       list-style-type: persian;
-}
-
-ol:lang(ckb) li {
-       list-style-type: -moz-arabic-indic;
-       list-style-type: arabic-indic;
-}
-
-ol:lang(hi) li,
-ol:lang(mr) li {
-       list-style-type: -moz-devanagari;
-       list-style-type: devanagari;
-}
-
-ol:lang(as) li,
-ol:lang(bn) li {
-       list-style-type: -moz-bengali;
-       list-style-type: bengali;
-}
-
-ol:lang(or) li {
-       list-style-type: -moz-oriya;
-       list-style-type: oriya;
-}
-
-#toc ul, .toc ul {
-       margin: .3em 0;
-}
-
-/* Correct directionality when page dir is different from site/user dir */
-/* @noflip */ .mw-content-ltr .toc ul,
-.mw-content-ltr #toc ul,
-.mw-content-rtl .mw-content-ltr .toc ul,
-.mw-content-rtl .mw-content-ltr #toc ul {
-       text-align: left;
-}
-
-/* @noflip */ .mw-content-rtl .toc ul,
-.mw-content-rtl #toc ul,
-.mw-content-ltr .mw-content-rtl .toc ul,
-.mw-content-ltr .mw-content-rtl #toc ul {
-       text-align: right;
-}
-
-/* @noflip */ .mw-content-ltr .toc ul ul,
-.mw-content-ltr #toc ul ul,
-.mw-content-rtl .mw-content-ltr .toc ul ul,
-.mw-content-rtl .mw-content-ltr #toc ul ul {
-       margin: 0 0 0 2em;
-}
-
-/* @noflip */ .mw-content-rtl .toc ul ul,
-.mw-content-rtl #toc ul ul,
-.mw-content-ltr .mw-content-rtl .toc ul ul,
-.mw-content-ltr .mw-content-rtl #toc ul ul {
-       margin: 0 2em 0 0;
-}
-
-#toc #toctitle,
-.toc #toctitle,
-#toc .toctitle,
-.toc .toctitle {
-       direction: ltr;
-}
-
-/* tooltip styles */
-.mw-help-field-hint {
-       display: none;
-       margin-left: 2px;
-       margin-bottom: -8px;
-       padding: 0 0 0 15px;
-       /* @embed */
-       background-image: url(images/help-question.gif);
-       background-position: left center;
-       background-repeat: no-repeat;
-       cursor: pointer;
-       font-size: .8em;
-       text-decoration: underline;
-       color: #0645ad;
-}
-
-.mw-help-field-hint:hover {
-       /* @embed */
-       background-image: url(images/help-question-hover.gif);
-}
-
-.mw-help-field-data {
-       display: block;
-       background-color: #d6f3ff;
-       padding: 5px 8px 4px 8px;
-       border: 1px solid #5dc9f4;
-       margin-left: 20px;
-}
-
-.tipsy {
-       padding: 5px 5px 10px;
-       font-size: 12px;
-       position: absolute;
-       z-index: 100000;
-       overflow: visible;
-}
-
-.tipsy-inner {
-       padding: 5px 8px 4px 8px;
-       background-color: #d6f3ff;
-       color: black;
-       border: 1px solid #5dc9f4;
-       max-width: 300px;
-       text-align: left;
-}
-
-.tipsy-arrow {
-       position: absolute;
-       /* @embed */
-       background: url(images/tipsy-arrow.gif) no-repeat top left;
-       width: 13px;
-       height: 13px;
-}
-
-.tipsy-se .tipsy-arrow {
-       bottom: -2px;
-       right: 10px;
-       background-position: 0% 100%;
-}
-
-#mw-clearyourcache,
-#mw-sitecsspreview,
-#mw-sitejspreview,
-#mw-usercsspreview,
-#mw-userjspreview {
-       direction: ltr;
-       unicode-bidi: embed;
-}
-
-/* Correct user & content directionality when viewing a diff */
-.diff-currentversion-title,
-.diff {
-       direction: ltr;
-       unicode-bidi: embed;
-}
-
-/* @noflip */ .diff-contentalign-right td {
-       direction: rtl;
-       unicode-bidi: embed;
-}
-
-/* @noflip */ .diff-contentalign-left td {
-       direction: ltr;
-       unicode-bidi: embed;
-}
-
-.diff-multi,
-.diff-otitle,
-.diff-ntitle,
-.diff-lineno {
-       direction: ltr !important;
-       unicode-bidi: embed;
-}
-
-#mw-revision-info,
-#mw-revision-info-current,
-#mw-revision-nav {
-       direction: ltr;
-       display: inline;
-}
-
-/* Images */
-
-/* @noflip */ div.tright,
-div.floatright,
-table.floatright {
-       clear: right;
-       float: right;
-}
-
-/* @noflip */ div.tleft,
-div.floatleft,
-table.floatleft {
-       float: left;
-       clear: left;
-}
-
-div.floatright,
-table.floatright,
-div.floatleft,
-table.floatleft {
-       position: relative;
-}
-
-/* bug 12205 */
-#mw-credits a {
-       unicode-bidi: embed;
-}
-
-/* Accessibility */
-.mw-jump,
-#jump-to-nav {
-       overflow: hidden;
-       height: 0;
-       zoom: 1; /* http://webaim.org/techniques/skipnav/#iequirk */
-}
-
-/* Print footer should be hidden by default in screen. */
-.printfooter {
-       display: none;
-}
-
-/* For developers */
-.xdebug-error {
-       position: absolute;
-       z-index: 99;
-}
-
-.mw-editsection,
-.toctoggle,
-#jump-to-nav {
-       -moz-user-select: none;
-       -webkit-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
-}
-
-/* Display editsection links smaller and next to headings */
-.mw-editsection,
-.mw-editsection-like {
-       font-size: small;
-       font-weight: normal;
-       margin-left: 1em;
-       vertical-align: baseline;
-       /* Reset line-height; headings tend to have it set to larger values */
-       line-height: 1em;
-       /* As .mw-editsection is a <span> (inline element), it is treated as part */
-       /* of the heading content when selecting text by multiple clicks and thus */
-       /* selected together with heading content, despite the user-select: none; */
-       /* rule set above. This enforces non-selection without changing the look. */
-       display: inline-block;
-}
-
-/* Correct directionality when page dir is different from site/user dir */
-/* @noflip */
-.mw-content-ltr .mw-editsection,
-.mw-content-rtl .mw-content-ltr .mw-editsection {
-       margin-left: 1em;
-}
-
-/* @noflip */
-.mw-content-rtl .mw-editsection,
-.mw-content-ltr .mw-content-rtl .mw-editsection {
-       margin-right: 1em;
-}
-
-/* Prevent citations and subscripts from interfering with the line-height */
-sup,
-sub {
-       line-height: 1;
-}
diff --git a/skins/common/upload.js b/skins/common/upload.js
deleted file mode 100644 (file)
index 7933caf..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-/*jshint camelcase:false */
-( function ( mw, $ ) {
-var    licenseSelectorCheck, wgUploadWarningObj, wgUploadLicenseObj, fillDestFilename,
-       ajaxUploadDestCheck = mw.config.get( 'wgAjaxUploadDestCheck' ),
-       fileExtensions = mw.config.get( 'wgFileExtensions' ),
-       $spinnerDestCheck, $spinnerLicense;
-
-licenseSelectorCheck = window.licenseSelectorCheck = function () {
-       var selector = document.getElementById( 'wpLicense' ),
-               selection = selector.options[selector.selectedIndex].value;
-       if ( selector.selectedIndex > 0 ) {
-               if ( !selection ) {
-                       // Option disabled, but browser is broken and doesn't respect this
-                       selector.selectedIndex = 0;
-               }
-       }
-       // We might show a preview
-       wgUploadLicenseObj.fetchPreview( selection );
-};
-
-function uploadSetup() {
-       // Disable URL box if the URL copy upload source type is not selected
-       var ein,
-               selector, ua, isMacIe, i,
-               optionsTable, row, td,
-               wpLicense, wpLicenseRow, wpLicenseTbody,
-               uploadSourceIds, len, onchange,
-               e = document.getElementById( 'wpSourceTypeurl' );
-       if ( e ) {
-               if ( !e.checked ) {
-                       ein = document.getElementById( 'wpUploadFileURL' );
-                       if ( ein ) {
-                               ein.disabled = true;
-                       }
-               }
-       }
-
-       // For MSIE/Mac: non-breaking spaces cause the <option> not to render.
-       // But for some reason, setting the text to itself works
-       selector = document.getElementById( 'wpLicense' );
-       if ( selector ) {
-               ua = navigator.userAgent;
-               isMacIe = ua.indexOf( 'MSIE' ) !== -1 && ua.indexOf( 'Mac' ) !== -1;
-               if ( isMacIe ) {
-                       for ( i = 0; i < selector.options.length; i++ ) {
-                               selector.options[i].text = selector.options[i].text;
-                       }
-               }
-       }
-
-       // AJAX wpDestFile warnings
-       if ( ajaxUploadDestCheck ) {
-               // Insert an event handler that fetches upload warnings when wpDestFile
-               // has been changed
-               document.getElementById( 'wpDestFile' ).onchange = function () {
-                       wgUploadWarningObj.checkNow( this.value );
-               };
-               // Insert a row where the warnings will be displayed just below the
-               // wpDestFile row
-               optionsTable = document.getElementById( 'mw-htmlform-description' ).tBodies[0];
-               row = optionsTable.insertRow( 1 );
-               td = document.createElement( 'td' );
-               td.id = 'wpDestFile-warning';
-               td.colSpan = 2;
-
-               row.appendChild( td );
-       }
-
-       wpLicense = document.getElementById( 'wpLicense' );
-       if ( mw.config.get( 'wgAjaxLicensePreview' ) && wpLicense ) {
-               // License selector check
-               wpLicense.onchange = licenseSelectorCheck;
-
-               // License selector table row
-               wpLicenseRow = wpLicense.parentNode.parentNode;
-               wpLicenseTbody = wpLicenseRow.parentNode;
-
-               row = document.createElement( 'tr' );
-               td = document.createElement( 'td' );
-               row.appendChild( td );
-               td = document.createElement( 'td' );
-               td.id = 'mw-license-preview';
-               row.appendChild( td );
-
-               wpLicenseTbody.insertBefore( row, wpLicenseRow.nextSibling );
-       }
-
-       // fillDestFile setup
-       uploadSourceIds = mw.config.get( 'wgUploadSourceIds' );
-       len = uploadSourceIds.length;
-       onchange = function () {
-               fillDestFilename( this.id );
-       };
-       for ( i = 0; i < len; i += 1 ) {
-               document.getElementById( uploadSourceIds[i] ).onchange = onchange;
-       }
-}
-
-wgUploadWarningObj = window.wgUploadWarningObj = {
-       responseCache: { '': '&nbsp;' },
-       nameToCheck: '',
-       typing: false,
-       delay: 500, // ms
-       timeoutID: false,
-
-       keypress: function () {
-               var cached, destFile, warningElt;
-
-               if ( !ajaxUploadDestCheck ) {
-                       return;
-               }
-
-               // Find file to upload
-               destFile = document.getElementById( 'wpDestFile' );
-               warningElt = document.getElementById( 'wpDestFile-warning' );
-               if ( !destFile || !warningElt ) {
-                       return;
-               }
-
-               this.nameToCheck = destFile.value;
-
-               // Clear timer
-               if ( this.timeoutID ) {
-                       clearTimeout( this.timeoutID );
-               }
-               // Check response cache
-               for ( cached in this.responseCache ) {
-                       if ( this.nameToCheck === cached ) {
-                               this.setWarning(this.responseCache[this.nameToCheck]);
-                               return;
-                       }
-               }
-
-               this.timeoutID = setTimeout( function () {
-                       wgUploadWarningObj.timeout();
-               }, this.delay );
-       },
-
-       checkNow: function ( fname ) {
-               if ( !ajaxUploadDestCheck ) {
-                       return;
-               }
-               if ( this.timeoutID ) {
-                       clearTimeout( this.timeoutID );
-               }
-               this.nameToCheck = fname;
-               this.timeout();
-       },
-
-       timeout: function () {
-               if ( !ajaxUploadDestCheck || this.nameToCheck === '' ) {
-                       return;
-               }
-               $spinnerDestCheck = $.createSpinner().insertAfter( '#wpDestFile' );
-
-               var uploadWarningObj = this;
-               ( new mw.Api() ).get( {
-                       action: 'query',
-                       titles: ( new mw.Title( this.nameToCheck, mw.config.get( 'wgNamespaceIds' ).file ) ).getPrefixedText(),
-                       prop: 'imageinfo',
-                       iiprop: 'uploadwarning',
-                       indexpageids: ''
-               } ).done( function ( result ) {
-                       var resultOut = '';
-                       if ( result.query ) {
-                               resultOut = result.query.pages[result.query.pageids[0]].imageinfo[0];
-                       }
-                       uploadWarningObj.processResult( resultOut, uploadWarningObj.nameToCheck );
-               } );
-       },
-
-       processResult: function ( result, fileName ) {
-               $spinnerDestCheck.remove();
-               $spinnerDestCheck = undefined;
-               this.setWarning( result.html );
-               this.responseCache[fileName] = result.html;
-       },
-
-       setWarning: function ( warning ) {
-               var warningElt = document.getElementById( 'wpDestFile-warning' ),
-                       ackElt = document.getElementsByName( 'wpDestFileWarningAck' );
-
-               this.setInnerHTML( warningElt, warning );
-
-               // Set a value in the form indicating that the warning is acknowledged and
-               // doesn't need to be redisplayed post-upload
-               if ( !warning ) {
-                       ackElt[0].value = '';
-               } else {
-                       ackElt[0].value = '1';
-               }
-
-       },
-       setInnerHTML: function ( element, text ) {
-               // Check for no change to avoid flicker in IE 7
-               if ( element.innerHTML !== text ) {
-                       element.innerHTML = text;
-               }
-       }
-};
-
-fillDestFilename = window.fillDestFilename = function ( id ) {
-       var e, path, slash, backslash, fname,
-               found, ext, i,
-               destFile;
-       if ( !mw.config.get( 'wgUploadAutoFill' ) ) {
-               return;
-       }
-       if ( !document.getElementById ) {
-               return;
-       }
-       // Remove any previously flagged errors
-       e = document.getElementById( 'mw-upload-permitted' );
-       if ( e ) {
-               e.className = '';
-       }
-
-       e = document.getElementById( 'mw-upload-prohibited' );
-       if ( e ) {
-               e.className = '';
-       }
-
-       path = document.getElementById( id ).value;
-       // Find trailing part
-       slash = path.lastIndexOf( '/' );
-       backslash = path.lastIndexOf( '\\' );
-       if ( slash === -1 && backslash === -1 ) {
-               fname = path;
-       } else if ( slash > backslash ) {
-               fname = path.substring( slash + 1, 10000 );
-       } else {
-               fname = path.substring( backslash + 1, 10000 );
-       }
-
-       // Clear the filename if it does not have a valid extension.
-       // URLs are less likely to have a useful extension, so don't include them in the
-       // extension check.
-       if ( mw.config.get( 'wgStrictFileExtensions' ) && fileExtensions && id !== 'wpUploadFileURL' ) {
-               found = false;
-               if ( fname.lastIndexOf( '.' ) !== -1 ) {
-                       ext = fname.substr( fname.lastIndexOf( '.' ) + 1 );
-                       for ( i = 0; i < fileExtensions.length; i += 1 ) {
-                               if ( fileExtensions[i].toLowerCase() === ext.toLowerCase() ) {
-                                       found = true;
-                                       break;
-                               }
-                       }
-               }
-               if ( !found ) {
-                       // Not a valid extension
-                       // Clear the upload and set mw-upload-permitted to error
-                       document.getElementById( id ).value = '';
-                       e = document.getElementById( 'mw-upload-permitted' );
-                       if ( e ) {
-                               e.className = 'error';
-                       }
-
-                       e = document.getElementById( 'mw-upload-prohibited' );
-                       if ( e ) {
-                               e.className = 'error';
-                       }
-
-                       // Clear wpDestFile as well
-                       e = document.getElementById( 'wpDestFile' );
-                       if ( e ) {
-                               e.value = '';
-                       }
-
-                       return false;
-               }
-       }
-
-       // Replace spaces by underscores
-       fname = fname.replace( / /g, '_' );
-       // Capitalise first letter if needed
-       if ( mw.config.get( 'wgCapitalizeUploads' ) ) {
-               fname = fname.charAt( 0 ).toUpperCase().concat( fname.substring( 1, 10000 ) );
-       }
-
-       // Output result
-       destFile = document.getElementById( 'wpDestFile' );
-       if ( destFile ) {
-               // Call decodeURIComponent function to remove possible URL-encoded characters
-               // from the file name (bug 30390). Especially likely with upload-form-url.
-               // decodeURIComponent can throw an exception in input is invalid utf-8
-               try {
-                       destFile.value = decodeURIComponent( fname );
-               } catch ( err ) {
-                       destFile.value = fname;
-               }
-               wgUploadWarningObj.checkNow( fname );
-       }
-};
-
-window.toggleFilenameFiller = function () {
-       if ( !document.getElementById ) {
-               return;
-       }
-       var destName = document.getElementById( 'wpDestFile' ).value;
-       mw.config.set( 'wgUploadAutoFill', !destName );
-};
-
-wgUploadLicenseObj = window.wgUploadLicenseObj = {
-
-       responseCache: { '': '' },
-
-       fetchPreview: function ( license ) {
-               var cached, title;
-               if ( !mw.config.get( 'wgAjaxLicensePreview' ) ) {
-                       return;
-               }
-               for ( cached in this.responseCache ) {
-                       if ( cached === license ) {
-                               this.showPreview( this.responseCache[license] );
-                               return;
-                       }
-               }
-
-               $spinnerLicense = $.createSpinner().insertAfter( '#wpLicense' );
-
-               title = document.getElementById( 'wpDestFile' ).value;
-               if ( !title ) {
-                       title = 'File:Sample.jpg';
-               }
-
-               ( new mw.Api() ).get( {
-                       action: 'parse',
-                       text: '{{' + license + '}}',
-                       title: title,
-                       prop: 'text',
-                       pst: ''
-               } ).done( function ( result ) {
-                       wgUploadLicenseObj.processResult( result, license );
-               } );
-       },
-
-       processResult: function ( result, license ) {
-               $spinnerLicense.remove();
-               $spinnerLicense = undefined;
-               this.responseCache[license] = result.parse.text['*'];
-               this.showPreview( this.responseCache[license] );
-       },
-
-       showPreview: function ( preview ) {
-               var previewPanel = document.getElementById( 'mw-license-preview' );
-               if ( previewPanel.innerHTML !== preview ) {
-                       previewPanel.innerHTML = preview;
-               }
-       }
-
-};
-
-$( uploadSetup );
-
-}( mediaWiki, jQuery ) );
deleted file mode 100644 (file)
index fdfca0afe3118138a63b500cc6289e9f1ab514f7..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- * MediaWiki legacy wikibits
- */
-( function ( mw, $ ) {
-       var msg,
-               win = window,
-               ua = navigator.userAgent.toLowerCase(),
-               isIE6 = ( /msie ([0-9]{1,}[\.0-9]{0,})/.exec( ua ) && parseFloat( RegExp.$1 ) <= 6.0 ),
-               onloadFuncts = [];
-
-if ( mw.config.get( 'wgBreakFrames' ) ) {
-       // Note: In IE < 9 strict comparison to window is non-standard (the standard didn't exist yet)
-       // it works only comparing to window.self or window.window (http://stackoverflow.com/q/4850978/319266)
-       if ( win.top !== win.self ) {
-               // Un-trap us from framesets
-               win.top.location = win.location;
-       }
-}
-
-/**
- * User-agent sniffing.
- *
- * @deprecated since 1.17 Use jquery.client instead
- */
-
-msg = 'Use feature detection or module jquery.client instead.';
-
-mw.log.deprecate( win, 'clientPC', ua, msg );
-
-// Ignored dummy values
-mw.log.deprecate( win, 'is_gecko', false, msg );
-mw.log.deprecate( win, 'is_chrome_mac', false, msg );
-mw.log.deprecate( win, 'is_chrome', false, msg );
-mw.log.deprecate( win, 'webkit_version', false, msg );
-mw.log.deprecate( win, 'is_safari_win', false, msg );
-mw.log.deprecate( win, 'is_safari', false, msg );
-mw.log.deprecate( win, 'webkit_match', false, msg );
-mw.log.deprecate( win, 'is_ff2', false, msg );
-mw.log.deprecate( win, 'ff2_bugs', false, msg );
-mw.log.deprecate( win, 'is_ff2_win', false, msg );
-mw.log.deprecate( win, 'is_ff2_x11', false, msg );
-mw.log.deprecate( win, 'opera95_bugs', false, msg );
-mw.log.deprecate( win, 'opera7_bugs', false, msg );
-mw.log.deprecate( win, 'opera6_bugs', false, msg );
-mw.log.deprecate( win, 'is_opera_95', false, msg );
-mw.log.deprecate( win, 'is_opera_preseven', false, msg );
-mw.log.deprecate( win, 'is_opera', false, msg );
-mw.log.deprecate( win, 'ie6_bugs', false, msg );
-
-/**
- * DOM utilities for handling of events, text nodes and selecting elements
- *
- * @deprecated since 1.17 Use jQuery instead
- */
-msg = 'Use jQuery instead.';
-
-// Ignored dummy values
-mw.log.deprecate( win, 'doneOnloadHook', undefined, msg );
-mw.log.deprecate( win, 'onloadFuncts', [], msg );
-mw.log.deprecate( win, 'runOnloadHook', $.noop, msg );
-mw.log.deprecate( win, 'changeText', $.noop, msg );
-mw.log.deprecate( win, 'killEvt', $.noop, msg );
-mw.log.deprecate( win, 'addHandler', $.noop, msg );
-mw.log.deprecate( win, 'hookEvent', $.noop, msg );
-mw.log.deprecate( win, 'addClickHandler', $.noop, msg );
-mw.log.deprecate( win, 'removeHandler', $.noop, msg );
-mw.log.deprecate( win, 'getElementsByClassName', function () { return []; }, msg );
-mw.log.deprecate( win, 'getInnerText', function () { return ''; }, msg );
-
-// Run a function after the window onload event is fired
-mw.log.deprecate( win, 'addOnloadHook', function ( hookFunct ) {
-       if ( onloadFuncts ) {
-               onloadFuncts.push(hookFunct);
-       } else {
-               // If func queue is gone the event has happened already,
-               // run immediately instead of queueing.
-               hookFunct();
-       }
-}, msg );
-
-$( win ).on( 'load', function () {
-       var i, functs;
-
-       // Don't run twice
-       if ( !onloadFuncts ) {
-               return;
-       }
-
-       // Deference and clear onloadFuncts before running any
-       // hooks to make sure we don't miss any addOnloadHook
-       // calls.
-       functs = onloadFuncts.slice();
-       onloadFuncts = undefined;
-
-       // Execute the queued functions
-       for ( i = 0; i < functs.length; i++ ) {
-               functs[i]();
-       }
-} );
-
-/**
- * Toggle checkboxes with shift selection
- *
- * @deprecated since 1.17 Use jquery.checkboxShiftClick instead
- */
-msg = 'Use jquery.checkboxShiftClick instead.';
-mw.log.deprecate( win, 'checkboxes', [], msg );
-mw.log.deprecate( win, 'lastCheckbox', null, msg );
-mw.log.deprecate( win, 'setupCheckboxShiftClick', $.noop, msg );
-mw.log.deprecate( win, 'addCheckboxClickHandlers', $.noop, msg );
-mw.log.deprecate( win, 'checkboxClickHandler', $.noop, msg );
-
-/**
- * Add a button to the default editor toolbar
- *
- * @deprecated since 1.17 Use mw.toolbar instead
- */
-mw.log.deprecate( win, 'mwEditButtons', [], 'Use mw.toolbar instead.' );
-mw.log.deprecate( win, 'mwCustomEditButtons', [], 'Use mw.toolbar instead.' );
-
-/**
- * Spinner creation, injection and removal
- *
- * @deprecated since 1.18 Use jquery.spinner instead
- */
-mw.log.deprecate( win, 'injectSpinner', $.noop, 'Use jquery.spinner instead.' );
-mw.log.deprecate( win, 'removeSpinner', $.noop, 'Use jquery.spinner instead.' );
-
-/**
- * Escape utilities
- *
- * @deprecated since 1.18 Use mw.html instead
- */
-mw.log.deprecate( win, 'escapeQuotes', $.noop, 'Use mw.html instead.' );
-mw.log.deprecate( win, 'escapeQuotesHTML', $.noop, 'Use mw.html instead.' );
-
-/**
- * Display a message to the user
- *
- * @deprecated since 1.17 Use mediawiki.notify instead
- * @param {string|HTMLElement} message To be put inside the message box
- */
-mw.log.deprecate( win, 'jsMsg', function ( message ) {
-       if ( !arguments.length || message === '' || message === null ) {
-               return true;
-       }
-       if ( typeof message !== 'object' ) {
-               message = $.parseHTML( message );
-       }
-       mw.notify( message, { autoHide: true, tag: 'legacy' } );
-       return true;
-}, 'Use mediawiki.notify instead.' );
-
-/**
- * Misc. utilities
- *
- * @deprecated since 1.17 Use mediawiki.util instead
- */
-msg = 'Use mediawiki.util instead.';
-mw.log.deprecate( win, 'updateTooltipAccessKeys', mw.util.updateTooltipAccessKeys, msg );
-mw.log.deprecate( win, 'addPortletLink', mw.util.addPortletLink, msg );
-mw.log.deprecate( win, 'appendCSS', mw.util.addCSS, msg );
-msg = 'Use jquery.accessKeyLabel instead.';
-mw.log.deprecate( win, 'tooltipAccessKeyPrefix', 'alt-', msg );
-mw.log.deprecate( win, 'tooltipAccessKeyRegexp', /\[(alt-)?(.)\]$/, msg );
-
-/**
- * Wikipage import methods
- */
-
-// included-scripts tracker
-win.loadedScripts = {};
-
-win.importScript = function ( page ) {
-       var uri = mw.config.get( 'wgScript' ) + '?title=' +
-               mw.util.wikiUrlencode( page ) +
-               '&action=raw&ctype=text/javascript';
-       return win.importScriptURI( uri );
-};
-
-win.importScriptURI = function ( url ) {
-       if ( win.loadedScripts[url] ) {
-               return null;
-       }
-       win.loadedScripts[url] = true;
-       var s = document.createElement( 'script' );
-       s.setAttribute( 'src', url );
-       s.setAttribute( 'type', 'text/javascript' );
-       document.getElementsByTagName( 'head' )[0].appendChild( s );
-       return s;
-};
-
-win.importStylesheet = function ( page ) {
-       var uri = mw.config.get( 'wgScript' ) + '?title=' +
-               mw.util.wikiUrlencode( page ) +
-               '&action=raw&ctype=text/css';
-       return win.importStylesheetURI( uri );
-};
-
-win.importStylesheetURI = function ( url, media ) {
-       var l = document.createElement( 'link' );
-       l.rel = 'stylesheet';
-       l.href = url;
-       if ( media ) {
-               l.media = media;
-       }
-       document.getElementsByTagName('head')[0].appendChild( l );
-       return l;
-};
-
-if ( isIE6 ) {
-       win.importScriptURI( mw.config.get( 'stylepath' ) + '/common/IEFixes.js' );
-}
-
-}( mediaWiki, jQuery ) );
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..c86af5b4cafc2d01d733615599ae1d66fe042639
--- /dev/null
@@ -0,0 +1 @@
+../../resources/src/mediawiki.legacy/wikibits.js
\ No newline at end of file
index 37cf68f..2e8fed4 100644 (file)
@@ -35,15 +35,16 @@ $wgAutoloadClasses += array(
        'TestRecorder' => "$testDir/testHelpers.inc",
        'ITestRecorder' => "$testDir/testHelpers.inc",
        'DjVuSupport' => "$testDir/testHelpers.inc",
+       'TidySupport' => "$testDir/testHelpers.inc",
 
        # tests/phpunit
        'MediaWikiTestCase' => "$testDir/phpunit/MediaWikiTestCase.php",
-       'MediaWikiPHPUnitCommand' => "$testDir/phpunit/MediaWikiPHPUnitCommand.php",
        'MediaWikiPHPUnitTestListener' => "$testDir/phpunit/MediaWikiPHPUnitTestListener.php",
        'MediaWikiLangTestCase' => "$testDir/phpunit/MediaWikiLangTestCase.php",
        'ResourceLoaderTestCase' => "$testDir/phpunit/ResourceLoaderTestCase.php",
        'ResourceLoaderTestModule' => "$testDir/phpunit/ResourceLoaderTestCase.php",
        'ResourceLoaderFileModuleTestModule' => "$testDir/phpunit/ResourceLoaderTestCase.php",
+       'ResourceLoaderWikiModuleTestModule' => "$testDir/phpunit/ResourceLoaderTestCase.php",
        'TestUser' => "$testDir/phpunit/includes/TestUser.php",
        'LessFileCompilationTest' => "$testDir/phpunit/LessFileCompilationTest.php",
 
@@ -61,6 +62,9 @@ $wgAutoloadClasses += array(
        'UserWrapper' => "$testDir/phpunit/includes/api/UserWrapper.php",
        'RandomImageGenerator' => "$testDir/phpunit/includes/api/RandomImageGenerator.php",
 
+       # tests/phpunit/includes/changes
+       'TestRecentChangesHelper' => "$testDir/phpunit/includes/changes/TestRecentChangesHelper.php",
+
        # tests/phpunit/includes/content
        'DummyContentHandlerForTesting' => "$testDir/phpunit/includes/content/ContentHandlerTest.php",
        'DummyContentForTesting' => "$testDir/phpunit/includes/content/ContentHandlerTest.php",
@@ -75,6 +79,9 @@ $wgAutoloadClasses += array(
        'PageORMTableForTesting' => "$testDir/phpunit/includes/db/ORMTableTest.php",
        'DatabaseTestHelper' => "$testDir/phpunit/includes/db/DatabaseTestHelper.php",
 
+       # tests/phpunit/includes/passwords
+       'PasswordTestCase' => "$testDir/phpunit/includes/password/PasswordTestCase.php",
+
        # tests/phpunit/languages
        'LanguageClassesTestCase' => "$testDir/phpunit/languages/LanguageClassesTestCase.php",
 
index 92784bf..1ea4eb5 100644 (file)
@@ -4,7 +4,7 @@ GEM
     builder (3.2.2)
     childprocess (0.5.3)
       ffi (~> 1.0, >= 1.0.11)
-    cucumber (1.3.15)
+    cucumber (1.3.16)
       builder (>= 2.1.2)
       diff-lcs (>= 1.1.3)
       gherkin (~> 2.12)
@@ -14,9 +14,9 @@ GEM
       faker (>= 1.1.2)
       yml_reader (>= 0.3)
     diff-lcs (1.2.5)
-    domain_name (0.5.19)
+    domain_name (0.5.20)
       unf (>= 0.0.5, < 1.0.0)
-    faker (1.3.0)
+    faker (1.4.3)
       i18n (~> 0.5)
     faraday (0.9.0)
       multipart-post (>= 1.2, < 3)
@@ -29,15 +29,16 @@ GEM
     headless (1.0.2)
     http-cookie (1.0.2)
       domain_name (~> 0.5)
-    i18n (0.6.9)
+    i18n (0.6.11)
     json (1.8.1)
-    mediawiki_api (0.1.3)
+    mediawiki_api (0.2.1)
       faraday (~> 0.9, >= 0.9.0)
       faraday-cookie_jar (~> 0.0, >= 0.0.6)
-    mediawiki_selenium (0.2.25)
+    mediawiki_selenium (0.3.2)
       cucumber (~> 1.3, >= 1.3.10)
       headless (~> 1.0, >= 1.0.1)
       json (~> 1.8, >= 1.8.1)
+      mediawiki_api (~> 0.2, >= 0.2.1)
       page-object (~> 1.0)
       rest-client (~> 1.6, >= 1.6.7)
       rspec-expectations (~> 2.14, >= 2.14.4)
@@ -46,17 +47,19 @@ GEM
     multi_json (1.10.1)
     multi_test (0.1.1)
     multipart-post (2.0.0)
-    page-object (1.0)
+    netrc (0.7.7)
+    page-object (1.0.2)
       page_navigation (>= 0.9)
       selenium-webdriver (>= 2.42.0)
       watir-webdriver (>= 0.6.9)
     page_navigation (0.9)
       data_magic (>= 0.14)
-    rest-client (1.6.7)
-      mime-types (>= 1.16)
-    rspec-expectations (2.99.1)
+    rest-client (1.7.2)
+      mime-types (>= 1.16, < 3.0)
+      netrc (~> 0.7)
+    rspec-expectations (2.99.2)
       diff-lcs (>= 1.1.3, < 2.0)
-    rubyzip (1.1.5)
+    rubyzip (1.1.6)
     selenium-webdriver (2.42.0)
       childprocess (>= 0.5.0)
       multi_json (~> 1.0)
index 8921fb6..2265762 100644 (file)
@@ -13,11 +13,11 @@ Install:
 
 Ruby 1.9.3 or higher is required
 Firefox browser is required
-
-cd /tests/browser
-gem update --system
-gem install bundler
-bundle install
+::
+ cd /tests/browser
+ gem update --system
+ gem install bundler
+ bundle install
 
 Run the tests:
 
index e7b64cd..c24e386 100644 (file)
@@ -16,7 +16,6 @@ class PreferencesAppearancePage
   page_url URL.url("Special:Preferences#mw-prefsection-rendering")
 
   checkbox(:auto_number_check, id: "mw-input-wpnumberheadings")
-  checkbox(:collapse_sidebar_vector_check, id: "mw-input-wpvector-collapsiblenav")
   radio_button(:cologne_blue, id: "mw-input-wpskin-cologneblue")
   radio_button(:day_mo_year_radio, id: "mw-input-wpdate-dmy")
   checkbox(:dont_show_aft_check, id: "mw-input-wparticlefeedback-disable")
index 69fda8d..59c18a8 100644 (file)
@@ -7,7 +7,7 @@ module.exports = function ( grunt ) {
        grunt.loadNpmTasks( 'grunt-contrib-jshint' );
        grunt.loadNpmTasks( 'grunt-contrib-watch' );
        grunt.loadNpmTasks( 'grunt-banana-checker' );
-       grunt.loadNpmTasks( 'grunt-jscs-checker' );
+       grunt.loadNpmTasks( 'grunt-jscs' );
        grunt.loadNpmTasks( 'grunt-jsonlint' );
 
        grunt.file.setBase(  __dirname + '/../..' );
index a398596..7913363 100644 (file)
@@ -8,8 +8,8 @@
     "grunt": "0.4.2",
     "grunt-contrib-jshint": "0.10.0",
     "grunt-contrib-watch": "0.6.1",
-    "grunt-banana-checker": "0.1.0",
-    "grunt-jscs-checker": "0.4.4",
+    "grunt-banana-checker": "0.2.0",
+    "grunt-jscs": "0.6.1",
     "grunt-jsonlint": "1.0.4"
   }
 }
index 6c8a401..a9df683 100644 (file)
@@ -70,9 +70,9 @@ class ParserTest {
        private $djVuSupport;
 
        /**
-        * @var string $oldTablePrefix Original table prefix
+        * @var TidySupport
         */
-       private $oldTablePrefix;
+       private $tidySupport;
 
        private $maxFuzzTestLength = 300;
        private $fuzzSeed = 0;
@@ -142,6 +142,10 @@ class ParserTest {
                $this->runParsoid = isset( $options['run-parsoid'] );
 
                $this->djVuSupport = new DjVuSupport();
+               $this->tidySupport = new TidySupport();
+               if ( !$this->tidySupport->isEnabled() ) {
+                       echo "Warning: tidy is not installed, skipping some tests\n";
+               }
 
                $this->hooks = array();
                $this->functionHooks = array();
@@ -153,7 +157,7 @@ class ParserTest {
                global $wgParser, $wgParserConf, $IP, $messageMemc, $wgMemc,
                        $wgUser, $wgLang, $wgOut, $wgRequest, $wgStyleDirectory, $wgEnableParserCache,
                        $wgExtraNamespaces, $wgNamespaceAliases, $wgNamespaceProtection, $wgLocalFileRepo,
-                       $wgExtraInterlanguageLinkPrefixes,
+                       $wgExtraInterlanguageLinkPrefixes, $wgLocalInterwikis,
                        $parserMemc, $wgThumbnailScriptPath, $wgScriptPath,
                        $wgArticlePath, $wgScript, $wgStylePath, $wgExtensionAssetsPath,
                        $wgMainCacheType, $wgMessageCacheType, $wgParserCacheType, $wgLockManagers;
@@ -213,7 +217,6 @@ class ParserTest {
                $messageMemc = wfGetMessageCacheStorage();
                $parserMemc = wfGetParserCacheStorage();
 
-               // $wgContLang = new StubContLang;
                $wgUser = new User;
                $context = new RequestContext;
                $wgLang = $context->getLanguage();
@@ -224,11 +227,12 @@ class ParserTest {
                if ( $wgStyleDirectory === false ) {
                        $wgStyleDirectory = "$IP/skins";
                }
+
+               self::setupInterwikis();
+               $wgLocalInterwikis = array( 'local', 'mi' );
                // "extra language links"
                // see https://gerrit.wikimedia.org/r/111390
                array_push( $wgExtraInterlanguageLinkPrefixes, 'mul' );
-
-               self::setupInterwikis();
        }
 
        /**
@@ -245,6 +249,11 @@ class ParserTest {
                # for testing inter-language links
                Hooks::register( 'InterwikiLoadPrefix', function ( $prefix, &$iwData ) {
                        static $testInterwikis = array(
+                               'local' => array(
+                                       'iw_url' => 'http://doesnt.matter.org/$1',
+                                       'iw_api' => '',
+                                       'iw_wikiid' => '',
+                                       'iw_local' => 0 ),
                                'wikipedia' => array(
                                        'iw_url' => 'http://en.wikipedia.org/wiki/$1',
                                        'iw_api' => '',
@@ -280,6 +289,11 @@ class ParserTest {
                                        'iw_api' => '',
                                        'iw_wikiid' => '',
                                        'iw_local' => 1 ),
+                               'mi' => array(
+                                       'iw_url' => 'http://mi.wikipedia.org/wiki/$1',
+                                       'iw_api' => '',
+                                       'iw_wikiid' => '',
+                                       'iw_local' => 1 ),
                                'mul' => array(
                                        'iw_url' => 'http://wikisource.org/wiki/$1',
                                        'iw_api' => '',
@@ -318,6 +332,7 @@ class ParserTest {
         * Remove last character if it is a newline
         * @group utility
         * @param string $s
+        * @return string
         */
        public static function chomp( $s ) {
                if ( substr( $s, -1 ) === "\n" ) {
@@ -402,6 +417,7 @@ class ParserTest {
        /**
         * Get an input dictionary from a set of parser test files
         * @param array $filenames
+        * @return string
         */
        function getFuzzInput( $filenames ) {
                $dict = '';
@@ -424,6 +440,7 @@ class ParserTest {
 
        /**
         * Get a memory usage breakdown
+        * @return array
         */
        function getMemoryBreakdown() {
                $memStats = array();
@@ -606,6 +623,13 @@ class ParserTest {
                        $output = $parser->parse( $input, $title, $options, true, true, 1337 );
                        $output->setTOCEnabled( !isset( $opts['notoc'] ) );
                        $out = $output->getText();
+                       if ( isset( $opts['tidy'] ) ) {
+                               if ( !$this->tidySupport->isEnabled() ) {
+                                       return $this->showSkipped();
+                               }
+                               $out = MWTidy::tidy( $out );
+                               $out = preg_replace( '/\s+$/', '', $out );
+                       }
 
                        if ( isset( $opts['showtitle'] ) ) {
                                if ( $output->getTitleText() ) {
@@ -616,20 +640,18 @@ class ParserTest {
                        }
 
                        if ( isset( $opts['ill'] ) ) {
-                               $out = $this->tidy( implode( ' ', $output->getLanguageLinks() ) );
+                               $out = implode( ' ', $output->getLanguageLinks() );
                        } elseif ( isset( $opts['cat'] ) ) {
                                $outputPage = $context->getOutput();
                                $outputPage->addCategoryLinks( $output->getCategories() );
                                $cats = $outputPage->getCategoryLinks();
 
                                if ( isset( $cats['normal'] ) ) {
-                                       $out = $this->tidy( implode( ' ', $cats['normal'] ) );
+                                       $out = implode( ' ', $cats['normal'] );
                                } else {
                                        $out = '';
                                }
                        }
-
-                       $result = $this->tidy( $result );
                }
 
                $this->teardownGlobals();
@@ -644,6 +666,7 @@ class ParserTest {
        /**
         * Refactored in 1.22 to use ParserTestResult
         * @param ParserTestResult $testResult
+        * @return bool
         */
        function showTestResult( ParserTestResult $testResult ) {
                if ( $testResult->isSuccess() ) {
@@ -660,6 +683,7 @@ class ParserTest {
         * @param string $key Name of option val to retrieve
         * @param array $opts Options array to look in
         * @param mixed $default Default value returned if not found
+        * @return mixed
         */
        private static function getOptionValue( $key, $opts, $default ) {
                $key = strtolower( $key );
@@ -728,11 +752,11 @@ class ParserTest {
 
                if ( preg_match_all( $regex, $instring, $matches, PREG_SET_ORDER ) ) {
                        foreach ( $matches as $bits ) {
-                               $key = strtolower( $bits[ 'k' ] );
-                               if ( !isset( $bits[ 'v' ] ) ) {
+                               $key = strtolower( $bits['k'] );
+                               if ( !isset( $bits['v'] ) ) {
                                        $opts[$key] = true;
                                } else {
-                                       preg_match_all( $valueregex, $bits[ 'v' ], $vmatches );
+                                       preg_match_all( $valueregex, $bits['v'], $vmatches );
                                        $opts[$key] = array_map( array( $this, 'cleanupOption' ), $vmatches[0] );
                                        if ( count( $opts[$key] ) == 1 ) {
                                                $opts[$key] = $opts[$key][0];
@@ -763,8 +787,11 @@ class ParserTest {
         * Ideally this should replace the global configuration entirely.
         * @param string $opts
         * @param string $config
+        * @return RequestContext
         */
        private function setupGlobals( $opts = '', $config = '' ) {
+               global $IP;
+
                # Find out values for some special options.
                $lang =
                        self::getOptionValue( 'language', $opts, 'en' );
@@ -808,6 +835,7 @@ class ParserTest {
                                ) )
                        ),
                        'wgEnableUploads' => self::getOptionValue( 'wgEnableUploads', $opts, true ),
+                       'wgUploadNavigationUrl' => false,
                        'wgStylePath' => '/skins',
                        'wgSitename' => 'MediaWiki',
                        'wgLanguageCode' => $lang,
@@ -827,7 +855,6 @@ class ParserTest {
                        'wgLocaltimezone' => 'UTC',
                        'wgAllowExternalImages' => self::getOptionValue( 'wgAllowExternalImages', $opts, true ),
                        'wgThumbLimits' => array( self::getOptionValue( 'thumbsize', $opts, 180 ) ),
-                       'wgUseTidy' => false,
                        'wgDefaultLanguageVariant' => $variant,
                        'wgVariantArticlePath' => false,
                        'wgGroupPermissions' => array( '*' => array(
@@ -843,13 +870,22 @@ class ParserTest {
                        'wgLinkHolderBatchSize' => $linkHolderBatchSize,
                        'wgExperimentalHtmlIds' => false,
                        'wgExternalLinkTarget' => false,
-                       'wgAlwaysUseTidy' => false,
                        'wgHtml5' => true,
                        'wgWellFormedXml' => true,
                        'wgAllowMicrodataAttributes' => true,
                        'wgAdaptiveMessageCache' => true,
                        'wgDisableLangConversion' => false,
                        'wgDisableTitleConversion' => false,
+                       // Tidy options.
+                       // We always set 'wgUseTidy' to false when parsing, but certain
+                       // test-running modes still use tidy if available, so ensure
+                       // that the tidy-related options are all set to their defaults.
+                       'wgUseTidy' => false,
+                       'wgAlwaysUseTidy' => false,
+                       'wgDebugTidy' => false,
+                       'wgTidyConf' => $IP . '/includes/tidy.conf',
+                       'wgTidyOpts' => '',
+                       'wgTidyInternal' => $this->tidySupport->isInternal(),
                );
 
                if ( $config ) {
@@ -899,6 +935,7 @@ class ParserTest {
        /**
         * List of temporary tables to create, without prefix.
         * Some of these probably aren't necessary.
+        * @return array
         */
        private function listTables() {
                $tables = array( 'user', 'user_properties', 'user_former_groups', 'page', 'page_restrictions',
@@ -942,7 +979,6 @@ class ParserTest {
                }
 
                $this->databaseSetupDone = true;
-               $this->oldTablePrefix = $wgDBprefix;
 
                # SqlBagOStuff broke when using temporary tables on r40209 (bug 15892).
                # It seems to have been fixed since (r55079?), but regressed at some point before r85701.
@@ -1366,7 +1402,7 @@ class ParserTest {
        /**
         * Print a skipped message.
         *
-        * @return boolean
+        * @return bool
         */
        protected function showSkipped() {
                if ( $this->showProgress ) {
@@ -1560,23 +1596,6 @@ class ParserTest {
                return true;
        }
 
-       /**
-        * Run the "tidy" command on text if the $wgUseTidy
-        * global is true
-        *
-        * @param string $text The text to tidy
-        * @return string
-        */
-       private function tidy( $text ) {
-               global $wgUseTidy;
-
-               if ( $wgUseTidy ) {
-                       $text = MWTidy::tidy( $text );
-               }
-
-               return $text;
-       }
-
        private function wellFormed( $text ) {
                $html =
                        Sanitizer::hackDocType() .
index 6097370..c90c4f6 100644 (file)
@@ -46,6 +46,12 @@ Main Page
 blah blah
 !! endarticle
 
+!!article
+Foo
+!!text
+FOO
+!!endarticle
+
 !!article
 Template:Foo
 !!text
@@ -401,6 +407,13 @@ http://fr.wikipedia.org/wiki/🍺
 </p>
 !! end
 
+# Note that the html+tidy output removes the spaces after the <li>,
+# which is a bug (http://sourceforge.net/p/tidy/bugs/945/, etc).
+# This is an issue for all tests with lists.  We intentionally do
+# *not* add html+tidy clauses for these, as we don't want to
+# document/test the broken behavior.  (Parsoid matches the non-tidy
+# output in these cases.)
+
 !! test
 Simple list
 !! wikitext
@@ -757,7 +770,7 @@ Italics and bold: 5-quote opening sequence: (5,2+3)
 parsoid=wt2wt,html2wt
 !! wikitext
 '''''foo'''''
-!! html/*
+!! html
 <p><b><i>foo</i></b>
 </p>
 !! end
@@ -1037,7 +1050,16 @@ parsoid=wt2html,wt2wt
 !''a!!''b
 |''a||''b
 |}
-!! html
+!! html/php+tidy
+<table>
+<tr>
+<th><i>a</i></th>
+<th><i>b</i></th>
+<td><i>a</i></td>
+<td><i>b</i></td>
+</tr>
+</table>
+!! html/parsoid
 <table>
 <tbody><tr><th><i>a</i></th><th><i>b</i></th>
 <td><i>a</i></td><td><i>b</i></td></tr>
@@ -1155,11 +1177,10 @@ Ruby markup (W3C-style)
 : <ruby>東<rb>京</rb><rp>(</rp><rt>とう</rt><rt>きょう</rt><rp>)</rp></ruby>
 ; Double-sided ruby
 : <ruby><rb>旧</rb><rb>金</rb><rb>山</rb><rt>jiù</rt><rt>jīn</rt><rt>shān</rt><rtc>San Francisco</rtc></ruby>
-
 <ruby>
-<rb>♥</rb><rtc><rt>Heart</rt></rtc><rtc lang=fr><rt>Cœur</rt></rtc>
-<rb>☘</rb><rtc><rt>Shamrock</rt></rtc><rtc lang=fr><rt>Trèfle</rt></rtc>
-<rb>✶</rb><rtc><rt>Star</rt></rtc><rtc lang=fr><rt>Étoile</rt></rtc>
+<rb>♥</rb><rtc><rt>Heart</rt></rtc><rtc lang="fr"><rt>Cœur</rt></rtc>
+<rb>☘</rb><rtc><rt>Shamrock</rt></rtc><rtc lang="fr"><rt>Trèfle</rt></rtc>
+<rb>✶</rb><rtc><rt>Star</rt></rtc><rtc lang="fr"><rt>Étoile</rt></rtc>
 </ruby>
 !! html
 <dl><dt> Mono-ruby for individual base characters</dt>
@@ -1180,6 +1201,7 @@ Ruby markup (W3C-style)
 </p>
 !! end
 
+# There is a tidy bug here: http://sourceforge.net/p/tidy/bugs/946/
 !! test
 Non-word characters don't terminate tag names (bug 17663, 40670, 52022)
 !! wikitext
@@ -1540,6 +1562,10 @@ b
 a <div>foo</div>
 <p>b
 </p>
+!! html+tidy
+<p>a</p>
+<div>foo</div>
+<p>b</p>
 !! end
 
 !! test
@@ -1552,6 +1578,12 @@ b
 a <blockquote>foo</blockquote>
 <p>b
 </p>
+!! html+tidy
+<p>a</p>
+<blockquote>
+<p>foo</p>
+</blockquote>
+<p>b</p>
 !! end
 
 !! test
@@ -1564,6 +1596,11 @@ b <div>foo</div>
 a <div>foo</div>
 b <div>foo</div>
 
+!! html+tidy
+<p>a</p>
+<div>foo</div>
+<p>b</p>
+<div>foo</div>
 !! end
 
 !! test
@@ -1576,6 +1613,15 @@ b <blockquote>foo</blockquote>
 a <blockquote>foo</blockquote>
 b <blockquote>foo</blockquote>
 
+!! html+tidy
+<p>a</p>
+<blockquote>
+<p>foo</p>
+</blockquote>
+<p>b</p>
+<blockquote>
+<p>foo</p>
+</blockquote>
 !! end
 
 !! test
@@ -1594,6 +1640,13 @@ d e
 </p>
 x <div>foo</div> z
 
+!! html+tidy
+<div>foo</div>
+<p>a</p>
+<p>b c d e</p>
+<p>x</p>
+<div>foo</div>
+<p>z</p>
 !! end
 
 !! test
@@ -1624,9 +1677,20 @@ b
 </p>
 <div>e</div>
 
+!! html+tidy
+<p><br /></p>
+<p>a</p>
+<p>b</p>
+<div>a</div>
+<p>b</p>
+<div>b</div>
+<p>d</p>
+<p><br /></p>
+<div>e</div>
 !! end
 
 ## PHP parser emits output which is broken
+## XXX The parsoid output doesn't match the tidy output.
 !! test
 Unclosed HTML p-tags should be handled properly
 !! wikitext
@@ -1634,6 +1698,11 @@ Unclosed HTML p-tags should be handled properly
 a
 
 b
+!! html/php+tidy
+<div>
+<p>foo&lt;/div&gt;</p>
+<p>a</p>
+b</div>
 !! html/parsoid
 <div data-parsoid='{"stx":"html"}'><p data-parsoid='{"stx":"html", "autoInsertedEnd":true}'>foo</p></div>
 <p>a</p>
@@ -1785,6 +1854,10 @@ Bug 15491: <ins>/<del> in blockquote (2)
 <blockquote>Foo <del>bar</del> <ins>baz</ins> quux
 </blockquote>
 
+!! html+tidy
+<blockquote>
+<p>Foo</p>
+<del>bar</del> <ins>baz</ins> quux</blockquote>
 !! end
 
 !! test
@@ -1910,6 +1983,12 @@ foo
 </pre></div>
 <pre></pre>
 
+!! html+tidy
+<p>a</p>
+<div>
+<pre>
+foo
+</pre></div>
 !! end
 
 !! test
  a
  | b
  | c
-!! html/parsoid
+!! html/php
 <pre>a
 | b
-| c</pre>
+| c
+</pre>
 !!end
 
 !!test
@@ -2507,6 +2587,12 @@ c
 a
  | b
  | c
+!! html/php
+<p>a
+</p>
+<pre>| b
+| c
+</pre>
 !! html/parsoid
 <p>a</p>
 <pre>
@@ -2527,7 +2613,19 @@ a
  c <blockquote> foo </blockquote>
 <pre><span> foo </span>
 </pre>
-!!end
+!! html+tidy
+<p>a</p>
+<p>foo</p>
+<p>b</p>
+<div>foo</div>
+<p>c</p>
+<blockquote>
+<p>foo</p>
+</blockquote>
+<pre>
+<span> foo </span>
+</pre>
+!! end
 
 !!test
 3b. Indent-Pre and block tags (multi-line html)
@@ -2539,6 +2637,12 @@ a
 </pre>
  b <div> foo </div>
 
+!! html+tidy
+<pre>
+a <span>foo</span>
+</pre>
+<p>b</p>
+<div>foo</div>
 !!end
 
 !!test
@@ -2620,44 +2724,43 @@ File:foobar.jpg
                </div></li>
 </ul>
 
+!! html+tidy
+<p>a</p>
+<ul class="gallery mw-gallery-traditional">
+<li class="gallerybox" style="width: 155px">
+<div style="width: 155px">
+<div class="thumb" style="width: 150px;">
+<div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div>
+</div>
+<div class="gallerytext"></div>
+</div>
+</li>
+</ul>
 !!end
 
 !! test
-Leading pipes outside of tables
-!! options
-parsoid
-!! wikitext
-| foo
-!! html
-<p>| foo</p>
-!! end
-
-!! test
-Leading pipes outside of tables 2
-!! options
-parsoid
-!! wikitext
-a
-| foo
-b
-!! html
-<p>a
-| foo
-b</p>
-!! end
-
-!! test
-Leading pipes outside of tables 3
-!! options
-parsoid
+Table wikitext syntax outside wiki-tables
 !! wikitext
 a
+! not a table heading
+|- not a table row
+| not a table cell
 | class="foo bar" | baz
 b
+|}
+|-
+c
 !! html
 <p>a
+! not a table heading
+|- not a table row
+| not a table cell
 | class="foo bar" | baz
-b</p>
+b
+|}
+|-
+c
+</p>
 !! end
 
 !!test
@@ -3404,6 +3507,9 @@ Definition Lists: Nesting: Test 4
 ## The Parsoid team believes the following three test exposes a
 ## bug in the PHP parser.  (Parsoid team thinks the PHP parser is
 ## wrong to close the <dl> after the <dt> containing the <ul>.)
+## It also exposes a "misfeature" in tidy, which doesn't like
+## <dl> tags with a single <dt> child; it converts the <dt> into
+## a <dd> in that case.  (Parsoid leaves the <dt> alone!)
 !! test
 Definition Lists: Mixed Lists: Test 1
 !! wikitext
@@ -3415,6 +3521,22 @@ Definition Lists: Mixed Lists: Test 1
 <li> bar</li></ul></dt></dl>
 <dl><dt> baz</dt></dl></dd></dl>
 
+!! html/php+tidy
+<dl>
+<dd>
+<dl>
+<dd>
+<ul>
+<li>foo</li>
+<li>bar</li>
+</ul>
+</dd>
+</dl>
+<dl>
+<dt>baz</dt>
+</dl>
+</dd>
+</dl>
 !! html/parsoid
 <dl>
 <dd><dl>
@@ -3542,6 +3664,7 @@ Definition Lists: Mixed Lists: Test 10
 # rules regarding dd/dt on the next two tests.  Parsoid is more
 # consistent, and recognizes the shared nesting and keeps the
 # still-open tags around until the nesting is complete.
+# (And tidy again converts <dt> to <dd> before 'bar'.)
 
 !! test
 Definition Lists: Mixed Lists: Test 11
@@ -3554,6 +3677,43 @@ Definition Lists: Mixed Lists: Test 11
 <dl><dt>boo&#160;</dt>
 <dd>baz</dd></dl></li></ol></li></ul></li></ol></li></ul>
 
+!! html/php+tidy
+<ul>
+<li>
+<ol>
+<li>
+<ul>
+<li>
+<ol>
+<li>
+<dl>
+<dt>foo&#160;</dt>
+<dd>
+<ul>
+<li>
+<dl>
+<dd>
+<dl>
+<dt>bar</dt>
+</dl>
+</dd>
+</dl>
+</li>
+</ul>
+</dd>
+</dl>
+<dl>
+<dt>boo&#160;</dt>
+<dd>baz</dd>
+</dl>
+</li>
+</ol>
+</li>
+</ul>
+</li>
+</ol>
+</li>
+</ul>
 !! html/parsoid
 <ul>
 <li>
@@ -3585,6 +3745,7 @@ Definition Lists: Mixed Lists: Test 11
 !! end
 
 
+# Another case where tidy converts a <dt> to a <dd> (but Parsoid doesn't).
 !! test
 Definition Lists: Weird Ones: Test 1
 !! wikitext
@@ -3593,6 +3754,39 @@ Definition Lists: Weird Ones: Test 1
 <ul><li><ol><li><dl><dt> foo&#160;</dt>
 <dd><ul><li><dl><dd><dl><dd><dl><dt><dl><dt> bar (who uses this?)</dt></dl></dd></dl></dd></dl></dd></dl></li></ul></dd></dl></li></ol></li></ul>
 
+!! html/php+tidy
+<ul>
+<li>
+<ol>
+<li>
+<dl>
+<dt>foo&#160;</dt>
+<dd>
+<ul>
+<li>
+<dl>
+<dd>
+<dl>
+<dd>
+<dl>
+<dd>
+<dl>
+<dt>bar (who uses this?)</dt>
+</dl>
+</dd>
+</dl>
+</dd>
+</dl>
+</dd>
+</dl>
+</li>
+</ul>
+</dd>
+</dl>
+</li>
+</ol>
+</li>
+</ul>
 !! html/parsoid
 <ul>
 <li>
@@ -3803,6 +3997,11 @@ External links: with no contents
 [[wikipedia:Foo|Bar]]
 
 [[wikipedia:Foo|<span>Bar</span>]]
+!! html/php
+<p><a rel="nofollow" class="external autonumber" href="http://en.wikipedia.org/wiki/Foo">[1]</a>
+</p><p><a href="http://en.wikipedia.org/wiki/Foo" class="extiw" title="wikipedia:Foo">Bar</a>
+</p><p><a href="http://en.wikipedia.org/wiki/Foo" class="extiw" title="wikipedia:Foo"><span>Bar</span></a>
+</p>
 !! html/parsoid
 <p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo"></a></p>
 <p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo">Bar</a></p>
@@ -4158,7 +4357,7 @@ External links: wiki links within external link (Bug 3695)
 <p><a rel="nofollow" class="external text" href="http://example.com"></a><a href="/index.php?title=Wikilink&amp;action=edit&amp;redlink=1" class="new" title="Wikilink (page does not exist)">wikilink</a><a rel="nofollow" class="external text" href="http://example.com"> embedded in ext link</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:ExtLink" href="http://example.com"></a><a rel="mw:WikiLink" href="./Wikilink">wikilink</a><span> embedded in ext link</span></p>
+<p><a rel="mw:ExtLink" href="http://example.com"></a><a rel="mw:WikiLink" href="./Wikilink" title="Wikilink">wikilink</a><span> embedded in ext link</span></p>
 !! end
 
 !! test
@@ -4388,8 +4587,10 @@ External link containing double-single-quotes with no space separating the url f
 !! html/php
 <p><a rel="nofollow" class="external text" href="http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm"><i>La muerte de Casagemas</i> (1901) en el sitio de <a href="/index.php?title=Museo_Picasso_(Par%C3%ADs)&amp;action=edit&amp;redlink=1" class="new" title="Museo Picasso (París) (page does not exist)">Museo Picasso</a>.</a>
 </p>
+!! html/php+tidy
+<p><a rel="nofollow" class="external text" href="http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm"><i>La muerte de Casagemas</i> (1901) en el sitio de</a> <a href="/index.php?title=Museo_Picasso_(Par%C3%ADs)&amp;action=edit&amp;redlink=1" class="new" title="Museo Picasso (París) (page does not exist)">Museo Picasso</a>.</p>
 !! html/parsoid
-<p><a rel="mw:ExtLink" href="http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm"><i>La muerte de Casagemas</i> (1901) en el sitio de </a><a rel="mw:WikiLink" href="./Museo_Picasso_(París)">Museo Picasso</a><span>.</span></p>
+<p><a rel="mw:ExtLink" href="http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm"><i>La muerte de Casagemas</i> (1901) en el sitio de </a><a rel="mw:WikiLink" href="./Museo_Picasso_(París)" title="Museo Picasso (París)">Museo Picasso</a><span>.</span></p>
 !! end
 
 !! test
@@ -4920,6 +5121,13 @@ Accept "!!" in table data
 {|
 | Foo!! ||
 |}
+!! html
+<table>
+<tr>
+<td> Foo!! </td>
+<td>
+</td></tr></table>
+
 !! html/parsoid
 <table data-parsoid='{}'>
 <tbody data-parsoid='{}'><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td data-parsoid='{"autoInsertedEnd":true}'> Foo!! </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'></td></tr>
@@ -5300,6 +5508,14 @@ Table-cell after a comment-only-empty-line
 <!--c1-->
 <!--c2-->| b
 |}
+!! html
+<table>
+<tr>
+<td>a
+</td>
+<td> b
+</td></tr></table>
+
 !! html/parsoid
 <table>
 <tbody><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td data-parsoid='{"autoInsertedEnd":true}'>a</td>
@@ -5309,6 +5525,29 @@ Table-cell after a comment-only-empty-line
 
 !! end
 
+!! test
+Build table with {{!}}
+!! wikitext
+{{{!}} class="wikitable"
+! header
+! second header
+{{!}}- style="color:red;"
+{{!}} data {{!}}{{!}} style="color:red;" {{!}} second data
+{{!}}}
+!! html
+<table class="wikitable">
+<tr>
+<th> header
+</th>
+<th> second header
+</th></tr>
+<tr style="color:red;">
+<td> data </td>
+<td style="color:red;"> second data
+</td></tr></table>
+
+!! end
+
 # The expected HTML structure in this test is debatable. The PHP parser does
 # not parse this kind of table at all. The main focus for Parsoid is on
 # round-tripping, so this output is ok for now. TODO: revisit!
@@ -5326,9 +5565,14 @@ Wikitext table with html-syntax row
 <td>foo</td></tr></tbody></table>
 !! end
 
+## Note that Parsoid output differs from PHP and PHP+tidy here.
+## The lack of <tr> tags in the PHP output is arguably a bug in the
+## PHP parser, which tidy then compounds by fostering the content
+## entirely out of the table.  Parsoid recognizes the table context
+## and generates <tr> and <td> wrappers as needed.  Hopefully nobody
+## depends on PHP's treatment of broken table markup!
 !! test
 Implicit <td> after a |-
-(PHP parser relies on Tidy to add the missing <td> tags)
 !! options
 parsoid=wt2html,wt2wt
 !! wikitext
@@ -5336,15 +5580,23 @@ parsoid=wt2html,wt2wt
 |-
 a
 |}
-!! html
+!! html/php
+<table>
+
+a
+</table>
+
+!! html/php+tidy
+<p>a</p>
+!! html/parsoid
 <table>
 <tr><td>a</td></tr>
 </table>
 !! end
 
+# Again, Parsoid adds implicit <td>s here, PHP and Tidy strip the b out.
 !! test
-Pres should be recognized in an explicit <td> context, but not in an implicit <td> context
-(PHP parser relies on Tidy to add the missing <td> tags)
+<pre> tags should be recognized in an explicit <td> context, but not in an implicit <td> context
 !! options
 parsoid=wt2html,wt2wt
 !! wikitext
@@ -5355,7 +5607,28 @@ parsoid=wt2html,wt2wt
 |-
  b
 |}
-!! html
+!! html/php
+<table>
+
+<tr>
+<td>
+<pre>a
+</pre>
+</td></tr>
+ b
+</table>
+
+!! html/php+tidy
+<p>b</p>
+<table>
+<tr>
+<td>
+<pre>
+a
+</pre></td>
+</tr>
+</table>
+!! html/parsoid
 <table>
 <tbody>
 <tr><td><pre>a</pre></td></tr>
@@ -5364,9 +5637,9 @@ parsoid=wt2html,wt2wt
 </table>
 !! end
 
+# PHP + Tidy strips the list out of the table; Parsoid wraps it.
 !! test
 Lists should be recognized in an implicit <td> context
-(PHP parser relies on Tidy to add the missing <td> tags)
 !! options
 parsoid=wt2html,wt2wt
 !! wikitext
@@ -5374,7 +5647,17 @@ parsoid=wt2html,wt2wt
 |-
 *a
 |}
-!! html
+!! html/php
+<table>
+
+<ul><li>a</li></ul>
+</table>
+
+!! html/php+tidy
+<ul>
+<li>a</li>
+</ul>
+!! html/parsoid
 <table>
 <tr>
 <td><ul>
@@ -5447,15 +5730,26 @@ parsoid=wt2html,wt2wt
 ! foo || bar
 <!-- foo -->  || baz || quux
 |}
+!! html/php
+<table>
+<tr>
+<th> foo </th>
+<th> bar
+</th>
+<td> baz </td>
+<td> quux
+</td></tr></table>
+
 !! html/parsoid
 <table>
-<tbody>
-<tr><th>foo </th><th>bar  </th>
-<td>baz </td>
-<td>quux</td></tr></tbody></table>
+<tbody><tr><th> foo </th><th> bar
+<!-- foo -->  </th><td> baz </td><td> quux</td></tr>
+</tbody></table>
 !! end
 
 
+# PHP throws away the (semi-broken) "foo" class here; Parsoid
+# preserves it.
 !!test
 Parsoid: Recover better from broken table attributes
 !!options
@@ -5465,6 +5759,14 @@ parsoid=wt2html
 | class="bar" |
 foo
 |}
+!!html/php+tidy
+<table>
+<tr>
+<td class="bar">
+<p>foo</p>
+</td>
+</tr>
+</table>
 !!html/parsoid
 <table class="foo">
 <tr>
@@ -5568,7 +5870,7 @@ Piped link with multiple pipe characters in link text
 <p><a href="/wiki/Main_Page" title="Main Page">|The|Main|Page|</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="Main_Page">|The|Main|Page|</a></p>
+<p><a rel="mw:WikiLink" href="Main_Page" title="Main Page">|The|Main|Page|</a></p>
 !! end
 
 !! test
@@ -5713,7 +6015,7 @@ Anchor containing a #. (bug 63430)
 <p><a href="/wiki/Main_Page#And.23Link" title="Main Page">Main Page#And#Link</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Main_Page#And%23Link">Main Page#And#Link</a></p>
+<p><a rel="mw:WikiLink" href="./Main_Page#And%23Link" title="Main Page">Main Page#And#Link</a></p>
 !! end
 
 !! test
@@ -5759,7 +6061,7 @@ parsoid=html2wt,html2html
 !! wikitext
 [[MemoryAlpha:AlphaTest]]
 !! html
-<p><a rel="mw:WikiLink" href="./MemoryAlpha:AlphaTest">MemoryAlpha:AlphaTest</a>
+<p><a rel="mw:WikiLink" href="./MemoryAlpha:AlphaTest" title="MemoryAlpha:AlphaTest">MemoryAlpha:AlphaTest</a>
 </p>
 !! end
 
@@ -5795,7 +6097,7 @@ Link containing % (not as a hex sequence)
 <p><a href="/wiki/7%25_Solution" title="7% Solution">7% Solution</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./7%25_Solution">7% Solution</a></p>
+<p><a rel="mw:WikiLink" href="./7%25_Solution" title="7% Solution">7% Solution</a></p>
 !! end
 
 # note that the parsoid HTML is identical to the previous test output,
@@ -5811,7 +6113,7 @@ parsoid=wt2wt,wt2html,html2html
 <p><a href="/wiki/7%25_Solution" title="7% Solution">7% Solution</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./7%25_Solution">7% Solution</a></p>
+<p><a rel="mw:WikiLink" href="./7%25_Solution" title="7% Solution">7% Solution</a></p>
 !!end
 
 !! test
@@ -5834,7 +6136,7 @@ Example for such a section: == < ==
 <p><a href="#.3C">#&lt;</a><a href="#.3E">#&gt;</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Main%20Page#%3C">#&lt;</a><a rel="mw:WikiLink" href="./Main%20Page#%3E">#></a></p>
+<p><a rel="mw:WikiLink" href="./Main%20Page#%3C" title="Main Page">#&lt;</a><a rel="mw:WikiLink" href="./Main%20Page#%3E" title="Main Page">#></a></p>
 !! end
 
 !! test
@@ -5854,7 +6156,7 @@ Link containing an equals sign
 <p><a href="/wiki/Special:BookSources/isbn%3D4-00-026157-6" title="Special:BookSources/isbn=4-00-026157-6">Special:BookSources/isbn=4-00-026157-6</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Special:BookSources/isbn=4-00-026157-6">Special:BookSources/isbn=4-00-026157-6</a></p>
+<p><a rel="mw:WikiLink" href="./Special:BookSources/isbn=4-00-026157-6" title="Special:BookSources/isbn=4-00-026157-6">Special:BookSources/isbn=4-00-026157-6</a></p>
 !! end
 
 !! article
@@ -5874,7 +6176,7 @@ Link containing a tilde
 <p><a href="/wiki/Foo%7Ebar" title="Foo~bar">Foo~bar</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Foo~bar">Foo~bar</a></p>
+<p><a rel="mw:WikiLink" href="./Foo~bar" title="Foo~bar">Foo~bar</a></p>
 !! end
 
 !! test
@@ -5885,7 +6187,7 @@ Link containing double-single-quotes '' (bug 4598)
 <p><a href="/index.php?title=Lista_d%27%27e_paise_d%27%27o_munno&amp;action=edit&amp;redlink=1" class="new" title="Lista d''e paise d''o munno (page does not exist)">Lista d''e paise d''o munno</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Lista_d''e_paise_d''o_munno">Lista d''e paise d''o munno</a></p>
+<p><a rel="mw:WikiLink" href="./Lista_d''e_paise_d''o_munno" title="Lista d''e paise d''o munno">Lista d''e paise d''o munno</a></p>
 !! end
 
 !! test
@@ -5896,7 +6198,7 @@ Some [[Link|pretty ''italics'' and stuff]]!
 <p>Some <a href="/index.php?title=Link&amp;action=edit&amp;redlink=1" class="new" title="Link (page does not exist)">pretty <i>italics</i> and stuff</a>!
 </p>
 !! html/parsoid
-<p>Some <a rel="mw:WikiLink" href="Link">pretty <i>italics</i> and stuff</a>!</p>
+<p>Some <a rel="mw:WikiLink" href="Link" title="Link">pretty <i>italics</i> and stuff</a>!</p>
 !! end
 
 !! test
@@ -5926,9 +6228,9 @@ Link with double quotes in title part (literal) and alternate part (interpreted)
 </p>
 !! html/parsoid
 <meta typeof="mw:Placeholder"/>
-<p><a rel="mw:WikiLink" href="''Pentecoste''">''Pentecoste''</a></p>
-<p><a rel="mw:WikiLink" href="''Pentecoste''">Pentecoste</a></p>
-<p><a rel="mw:WikiLink" href="''Pentecoste''"><i>Pentecoste</i></a></p>
+<p><a rel="mw:WikiLink" href="''Pentecoste''" title="''Pentecoste''">''Pentecoste''</a></p>
+<p><a rel="mw:WikiLink" href="''Pentecoste''" title="''Pentecoste''">Pentecoste</a></p>
+<p><a rel="mw:WikiLink" href="''Pentecoste''" title="''Pentecoste''"><i>Pentecoste</i></a></p>
 !! end
 
 !! test
@@ -6029,7 +6331,7 @@ BUG 2: [[page|http://url/]] should link to page, not http://url/
 <p><a href="/wiki/Main_Page" title="Main Page">http://url/</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Main_Page">http://url/</a></p>
+<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page">http://url/</a></p>
 !! end
 
 # Parsoid does not mark self-links, by design.
@@ -6042,8 +6344,10 @@ title=[[Bug462]]
 !! html/php
 <p><strong class="selflink">Bu&#103;462</strong> <strong class="selflink">Bug462</strong>
 </p>
+!! html/php+tidy
+<p><strong class="selflink">Bug462</strong> <strong class="selflink">Bug462</strong></p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Bug462">Bug462</a> <a rel="mw:WikiLink" href="./Bug462">Bug462</a></p>
+<p><a rel="mw:WikiLink" href="./Bug462" title="Bug462">Bug462</a> <a rel="mw:WikiLink" href="./Bug462" title="Bug462">Bug462</a></p>
 !! end
 
 !! test
@@ -6166,7 +6470,20 @@ Link with multiple ":" in a subpage-supporting namespace (bug 63636)
 <p><a href="/index.php?title=User:Foo/Test/63636:Bar&amp;action=edit&amp;redlink=1" class="new" title="User:Foo/Test/63636:Bar (page does not exist)">Test</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./User:Foo/Test/63636:Bar">Test</a></p>
+<p><a rel="mw:WikiLink" href="./User:Foo/Test/63636:Bar" title="User:Foo/Test/63636:Bar">Test</a></p>
+!! end
+
+!! test
+Purely hash wikilink
+!! options
+title=[[User:test/123]]
+!! wikitext
+[[#a|b]]
+!! html/php
+<p><a href="#a">b</a>
+</p>
+!! html/parsoid
+<p data-parsoid='{}'><a rel="mw:WikiLink" href="../User:Test/123#a" data-parsoid='{"stx":"piped","a":{"href":"../User:Test/123#a"},"sa":{"href":"#a"}}'>b</a></p>
 !! end
 
 !! test
@@ -6176,7 +6493,7 @@ parsoid
 !! wikitext
 {{echo|[[Foo]]}}l
 !! html
-<p><a rel="mw:WikiLink" href="Foo" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"[[Foo]]"}},"i":0}},"l"]}'>Fool</a></p>
+<p><a rel="mw:WikiLink" href="Foo" title="Foo" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"[[Foo]]"}},"i":0}},"l"]}'>Fool</a></p>
 !! end
 
 !! test
@@ -6186,7 +6503,7 @@ parsoid
 !! wikitext
 {{echo|Some [[Fool]]}}s
 !! html
-<p data-parsoid='{}'><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]"}},"i":0}},"s"]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>Some </span><a rel="mw:WikiLink" href="./Fool" about="#mwt1" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a></p>
+<p data-parsoid='{}'><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]"}},"i":0}},"s"]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>Some </span><a rel="mw:WikiLink" href="./Fool" title="Fool" about="#mwt1" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a></p>
 !! end
 
 !! test
@@ -6196,7 +6513,7 @@ parsoid
 !! wikitext
 {{echo|Some [[Fool]]s are '''bold and foolish'''}}
 !! html
-<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]s are &#39;&#39;&#39;bold and foolish&#39;&#39;&#39;"}},"i":0}}]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>Some <a rel="mw:WikiLink" href="./Fool" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a> are <b data-parsoid="{}">bold and foolish</b></p>
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]s are &#39;&#39;&#39;bold and foolish&#39;&#39;&#39;"}},"i":0}}]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>Some <a rel="mw:WikiLink" href="./Fool" title="Fool" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a> are <b data-parsoid="{}">bold and foolish</b></p>
 !! end
 
 !! article
@@ -6248,7 +6565,7 @@ parsoid=html2wt,html2html
 !! wikitext
 [[apple]]<nowiki/>s
 !! html
-<p><a rel="mw:WikiLink" href="Apple">apple</a>s</p>
+<p><a rel="mw:WikiLink" href="Apple" title="Apple">apple</a>s</p>
 !! end
 
 !! test
@@ -6259,7 +6576,7 @@ parsoid=html2wt,html2html
 !! wikitext
 Aðrir mótmælenda<nowiki/>[[söfnuður]]
 !! html
-<p>Aðrir mótmælenda<a rel="mw:WikiLink" href="Söfnuður">söfnuður</a></p>
+<p>Aðrir mótmælenda<a rel="mw:WikiLink" href="Söfnuður" title="Söfnuður">söfnuður</a></p>
 !! end
 
 !! test
@@ -6273,8 +6590,8 @@ Parsoid-centric test: Whitespace in ext- and wiki-links should be preserved
 
 [http://wp.org   ''foo'']
 !! html
-<p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">  bar</a>
-</p><p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">  <i>bar</i></a>
+<p><a href="/wiki/Foo" title="Foo">  bar</a>
+</p><p><a href="/wiki/Foo" title="Foo">  <i>bar</i></a>
 </p><p><a rel="nofollow" class="external text" href="http://wp.org">foo</a>
 </p><p><a rel="nofollow" class="external text" href="http://wp.org"><i>foo</i></a>
 </p>
@@ -6287,15 +6604,18 @@ parsoid
 !! wikitext
 [[Foo|{{echo|a}} b {{echo|c}}]]
 !! html
-<p><a rel="mw:WikiLink" href="Foo"><span about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a"}},"i":0}}]}'>a</span> b <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"c"}},"i":0}}]}'>c</span></a></p>
+<p><a rel="mw:WikiLink" href="Foo" title="Foo"><span about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a"}},"i":0}}]}'>a</span> b <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"c"}},"i":0}}]}'>c</span></a></p>
 !! end
 
 !! test
 Link with angle bracket after anchor
 !! wikitext
 [[Foo#<bar>]]
+!! html/php
+<p><a href="/wiki/Foo#.3Cbar.3E" title="Foo">Foo#&lt;bar&gt;</a>
+</p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Foo#%3Cbar%3E" data-parsoid='{"stx":"simple","a":{"href":"./Foo#%3Cbar%3E"},"sa":{"href":"Foo#&lt;bar>"}}'>Foo#&lt;bar></a></p>
+<p><a rel="mw:WikiLink" href="./Foo#%3Cbar%3E" title="Foo" data-parsoid='{"stx":"simple","a":{"href":"./Foo#%3Cbar%3E"},"sa":{"href":"Foo#&lt;bar>"}}'>Foo#&lt;bar></a></p>
 !! end
 
 ###
@@ -6329,6 +6649,11 @@ Interwiki link encoding conversion (bug 1636)
 <ul><li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class="extiw" title="wikipedia:ro:Olteniţa">Wikipedia:ro:Olteni&#355;a</a></li>
 <li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class="extiw" title="wikipedia:ro:Olteniţa">Wikipedia:ro:Olteni&#355;a</a></li></ul>
 
+!! html+tidy
+<ul>
+<li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class="extiw" title="wikipedia:ro:Olteniţa">Wikipedia:ro:Olteniţa</a></li>
+<li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class="extiw" title="wikipedia:ro:Olteniţa">Wikipedia:ro:Olteniţa</a></li>
+</ul>
 !! end
 
 !! test
@@ -6355,6 +6680,8 @@ Different interwiki prefixes mapping to the same URL
 [[wikipedia:en:Foo]]
 
 [[:wikipedia:en:Foo]]
+
+[[  wikiPEdia :Foo]]
 !! html/parsoid
 <p><a rel="mw:ExtLink" href="//en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"//en.wikipedia.org/wiki/Foo"},"sa":{"href":":en:Foo"},"isIW":true}'>en:Foo</a></p>
 
@@ -6367,6 +6694,8 @@ Different interwiki prefixes mapping to the same URL
 <p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/en:Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/en:Foo"},"sa":{"href":"wikipedia:en:Foo"},"isIW":true}'>wikipedia:en:Foo</a></p>
 
 <p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/en:Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/en:Foo"},"sa":{"href":":wikipedia:en:Foo"},"isIW":true}'>wikipedia:en:Foo</a></p>
+
+<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":"  wikiPEdia :Foo"},"isIW":true}'>  wikiPEdia :Foo</a></p>
 !! end
 
 !! test
@@ -6396,6 +6725,44 @@ parsoid
 <p data-parsoid='{}'><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"piped","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":"wikipedia:Foo"},"isIW":true,"tail":"r"}'>Bar</a></p>
 !! end
 
+!! test
+Local interwiki link
+!! wikitext
+[[local:Template:Foo]]
+!! html
+<p><a href="/wiki/Template:Foo" title="Template:Foo">local:Template:Foo</a>
+</p>
+!! end
+
+!! test
+Local interwiki link: self-link to current page
+!! options
+title=[[Main Page]]
+!! wikitext
+[[local:Main Page]]
+!! html
+<p><strong class="selflink">local:Main Page</strong>
+</p>
+!! end
+
+!! test
+Local interwiki link: prefix only (bug 64167)
+!! wikitext
+[[local:]]
+!! html
+<p><a href="/wiki/Main_Page" title="Main Page">local:</a>
+</p>
+!! end
+
+!! test
+Local interwiki link: with additional interwiki prefix (bug 61357)
+!! wikitext
+[[local:meatball:Hello]]
+!! html
+<p><a href="http://www.usemod.com/cgi-bin/mb.pl?Hello" class="extiw" title="meatball:Hello">local:meatball:Hello</a>
+</p>
+!! end
+
 ###
 ### Interlanguage links
 ### Language links (so that searching for '### language' matches..)
@@ -6406,9 +6773,25 @@ Interlanguage link
 !! wikitext
 Blah blah blah
 [[zh:Chinese]]
-!! html
+!! html/php
+<p>Blah blah blah
+</p>
+!! html/parsoid
+<p>Blah blah blah
+<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
+!! end
+
+!! test
+Interlanguage link with spacing
+!! wikitext
+Blah blah blah
+[[   zh  :    Chinese     ]]
+!! html/php
 <p>Blah blah blah
 </p>
+!! html/parsoid
+<p>Blah blah blah
+<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
 !! end
 
 !! test
@@ -6417,9 +6800,28 @@ Double interlanguage link
 Blah blah blah
 [[es:Spanish]]
 [[zh:Chinese]]
-!! html
+!! html/php
 <p>Blah blah blah
 </p>
+!! html/parsoid
+<p>Blah blah blah
+<link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/Spanish"/>
+<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
+!! end
+
+!! test
+Interlanguage link variations
+!! wikitext
+Blah blah blah
+[[   es :Spanish]]
+[[ ZH :Chinese]]
+!! html/php
+<p>Blah blah blah
+</p>
+!! html/parsoid
+<p>Blah blah blah
+<link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/Spanish" data-parsoid='{"stx":"simple","a":{"href":"//es.wikipedia.org/wiki/Spanish"},"sa":{"href":"   es :Spanish"}}'/>
+<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese" data-parsoid='{"stx":"simple","a":{"href":"//zh.wikipedia.org/wiki/Chinese"},"sa":{"href":" ZH :Chinese"}}'/>
 !! end
 
 !! test
@@ -6429,9 +6831,12 @@ language=ln
 !! wikitext
 Blah blah blah
 [[zh:Chinese]]
-!! html
+!! html/php
 <p>Blah blah blah
 </p>
+!! html/parsoid
+<p>Blah blah blah
+<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
 !! end
 
 !! test
@@ -6442,19 +6847,26 @@ language=ln
 Blah blah blah
 [[es:Spanish]]
 [[zh:Chinese]]
-!! html
+!! html/php
 <p>Blah blah blah
 </p>
+!! html/parsoid
+<p>Blah blah blah
+<link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/Spanish"/>
+<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
 !! end
 
 !! test
 "Extra" interlanguage links (bug 32189 / gerrit 111390)
 !! wikitext
 Blah blah blah
-[[mul:Multilingual]]
-!! html
+[[mul:Article]]
+!! html/php
 <p>Blah blah blah
 </p>
+!! html/parsoid
+<p>Blah blah blah
+<link rel="mw:PageProp/Language" title="Multilingual" href="//wikisource.org/wiki/Article"/></p>
 !! end
 
 !! test
@@ -6490,9 +6902,9 @@ parsoid
 
 [[constructor:foo]]
 !! html
-<p><a rel="mw:WikiLink" href="./Constructor" data-parsoid="{&quot;stx&quot;:&quot;simple&quot;,&quot;a&quot;:{&quot;href&quot;:&quot;./Constructor&quot;},&quot;sa&quot;:{&quot;href&quot;:&quot;constructor&quot;}}">constructor</a></p>
+<p><a rel="mw:WikiLink" href="./Constructor" title="Constructor" data-parsoid="{&quot;stx&quot;:&quot;simple&quot;,&quot;a&quot;:{&quot;href&quot;:&quot;./Constructor&quot;},&quot;sa&quot;:{&quot;href&quot;:&quot;constructor&quot;}}">constructor</a></p>
 
-<p><a rel="mw:WikiLink" href="./Foo" data-parsoid="{&quot;stx&quot;:&quot;simple&quot;,&quot;a&quot;:{&quot;href&quot;:&quot;./Foo&quot;},&quot;sa&quot;:{&quot;href&quot;:&quot;constructor:foo&quot;}}">constructor:foo</a></p>
+<p><a rel="mw:WikiLink" href="./Foo" title="Foo" data-parsoid="{&quot;stx&quot;:&quot;simple&quot;,&quot;a&quot;:{&quot;href&quot;:&quot;./Foo&quot;},&quot;sa&quot;:{&quot;href&quot;:&quot;constructor:foo&quot;}}">constructor:foo</a></p>
 !! end
 
 !! test
@@ -6522,7 +6934,29 @@ parsoid
 !! wikitext
 [[en:Foo]]
 !! html
-<p><a rel="mw:WikiLink" href="./Foo" data-parsoid='{"stx":"simple","a":{"href":"./Foo"},"sa":{"href":"en:Foo"}}'>Foo</a></p>
+<p><a rel="mw:WikiLink" href="./Foo" title="Foo" data-parsoid='{"stx":"simple","a":{"href":"./Foo"},"sa":{"href":"en:Foo"}}'>Foo</a></p>
+!! end
+
+!! test
+Interlanguage link with preceding local interwiki link (bug 68085)
+!! wikitext
+Blah blah blah
+[[local:es:Spanish]]
+!! html
+<p>Blah blah blah
+<a href="http://es.wikipedia.org/wiki/Spanish" class="extiw" title="es:Spanish">local:es:Spanish</a>
+</p>
+!! end
+
+!! test
+Looks like an interlanguage link, but is actually a local interwiki
+!! wikitext
+Blah blah blah
+[[mi:Template:Foo]]
+!! html
+<p>Blah blah blah
+<a href="/wiki/Template:Foo" title="Template:Foo">mi:Template:Foo</a>
+</p>
 !! end
 
 ###
@@ -6629,7 +7063,7 @@ parsoid=wt2html,html2html
 !! wikitext
 #REDIRECT [[:Category:Foo]]
 !! html
-<p><a rel="mw:WikiLink" href="Category:Foo">Category:Foo</a></p>
+<p><a rel="mw:WikiLink" href="Category:Foo" title="Category:Foo">Category:Foo</a></p>
 !! end
 
 !! test
@@ -6717,6 +7151,9 @@ Broken br tag sanitization
 !! end
 
 # TODO: Fix html2html mode (bug 51055)!
+# This </br> handling was added as part of bug 50831; but it
+# differs from how PHP+tidy handles this.  We should investigate
+# this.
 !! test
 Parsoid: Broken br tag recognition
 !! options
@@ -6725,6 +7162,9 @@ parsoid=wt2html
 </br>
 
 <br/ >
+!! html/php+tidy
+<p>&lt;/br&gt;</p>
+<p><br /></p>
 !! html/parsoid
 <p><br></p>
 <p><br/></p>
@@ -6783,7 +7223,7 @@ Handling html with a br self-closing tag
 <br title=bar />
 <br title=bar/>
 <br title=bar/ >
-!! html
+!! html/php
 <p><br title="title" />
 <br title="title" />
 <br />
@@ -6791,6 +7231,14 @@ Handling html with a br self-closing tag
 <br title="bar" />
 <br title="bar/" />
 </p>
+!! html/parsoid
+<p><br title="" />
+<br title="" />
+<br />
+<br title="bar" />
+<br title="bar" />
+<br title="bar/" />
+</p>
 !! end
 
 !! test
@@ -6852,6 +7300,9 @@ Horizontal ruler -- Supports content following dashes on same line
 !! html
 <hr /> Foo
 
+!! html+tidy
+<hr />
+<p>Foo</p>
 !! end
 
 ###
@@ -7103,6 +7554,12 @@ Multiple list tags generated by templates
 </li>
 </li>
 
+!! html+tidy
+<ul>
+<li>a</li>
+<li>b</li>
+<li>c</li>
+</ul>
 !!end
 
 !!test
@@ -7144,7 +7601,7 @@ Replacing whitespace with tabs still doesn't break the list (gerrit 78327)
 
 !!test
 Test the li-hack
-(Cannot test this with PHP parser since it relies on Tidy for the hack)
+(The PHP parser relies on Tidy for the hack)
 !!options
 parsoid=wt2html,wt2wt
 !! wikitext
@@ -7157,19 +7614,15 @@ parsoid=wt2html,wt2wt
 <li><li>not a li-hack
 </li>
 </ul>
-!! html
+!! html+tidy
 <ul>
-<li> foo</li>
+<li>foo</li>
 <li>li-hack</li>
-<li about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<li>templated li-hack"}}}}]}'>templated li-hack</li>
-<li> <!--foo--> </li>
-<li> li-hack with preceding comments</li>
+<li>templated li-hack</li>
+<li>unsupported li-hack with preceding comments</li>
 </ul>
-
 <ul>
-<li></li>
-<li>not a li-hack
-</li>
+<li>not a li-hack</li>
 </ul>
 !!end
 
@@ -7219,47 +7672,60 @@ parsoid
 
 !! test
 Unbalanced closing block tags break a list
-(Parsoid-only since php parser generates broken html -- relies on Tidy to fix up)
+(php parser relies on Tidy to fix up)
 !! wikitext
 <div>
 *a</div><div>
 *b</div>
-!! html/parsoid
+!! html+tidy
 <div>
 <ul>
-<li>a
-</li>
-</ul></div><div>
+<li>a</li>
+</ul>
+</div>
+<div>
 <ul>
-<li>b
-</li>
-</ul></div>
+<li>b</li>
+</ul>
+</div>
 !! end
 
+# Parsoid fails this test, but it might be tricky to support properly.
+# See bug 68395.
 !! test
 Unbalanced closing non-block tags don't break a list
-(Parsoid-only since php parser generates broken html -- relies on Tidy to fix up)
+(php parser relies on Tidy to fix up)
 !! wikitext
 <span>
 *a</span><span>
 *b</span>
+!! html/php+tidy
+<ul>
+<li><span>a</span></li>
+<li><span>b</span></li>
+</ul>
 !! html/parsoid
-<p><span></span>
-</p>
+<span>
 <ul>
 <li>a<span></span>
 </li>
 <li>b
 </li>
 </ul>
+</span>
 !! end
 
 !! test
 Unclosed formatting tags that straddle lists are closed and reopened
-(Parsoid-only since php parser generates broken html -- relies on Tidy to fix up)
+(php parser relies on Tidy to fix up)
 !! wikitext
 # <s> a
 # b </s>
+!! html/php+tidy
+<ol>
+<li><s>a</s></li>
+<li><s>b</s></li>
+</ol>
 !! html/parsoid
 <ol>
 <li> <s> a </s>
@@ -7269,23 +7735,31 @@ Unclosed formatting tags that straddle lists are closed and reopened
 </ol>
 !! end
 
+# Parsoid fails this test, but it might be tricky to support properly.
+# See bug 68395.
 !!test
 List embedded in a non-block tag
-(Ugly Parsoid output -- worth fixing; Disabled for PHP parser since it relies on Tidy)
+(Ugly Parsoid output -- worth fixing; PHP parser relies on Tidy)
 !! wikitext
 <small>
 * foo
 </small>
+!! html/php+tidy
+<ul>
+<li><small>foo</small></li>
+</ul>
 !! html/parsoid
-<p><small></small></p>
 <small>
 <ul>
 <li> foo</li>
 </ul>
 </small>
-<p><small></small></p>
 !!end
 
+# This is a bug in the PHP parser + tidy combination.
+# (The </tr> tag gets parsed as text and html-escaped by PHP,
+# and then fostered out of the table by tidy.)
+# We believe the Parsoid output to be correct.
 !! test
 Table with missing opening <tr> tag
 !! options
@@ -7295,6 +7769,13 @@ parsoid=wt2html,wt2wt
 <td>foo</td>
 </tr>
 </table>
+!! html/php+tidy
+<p>&lt;/tr&gt;</p>
+<table>
+<tr>
+<td>foo</td>
+</tr>
+</table>
 !! html/parsoid
 <table>
 <tr>
@@ -7751,9 +8232,11 @@ Magic Word: {{PAGENAME}} with metacharacters
 title=[['foo & bar = baz']]
 !! wikitext
 ''{{PAGENAME}}''
-!! html
+!! html/php
 <p><i>&#39;foo &#38; bar &#61; baz&#39;</i>
 </p>
+!! html+tidy
+<p><i>'foo &amp; bar = baz'</i></p>
 !! end
 
 !! test
@@ -7762,9 +8245,11 @@ Magic Word: {{PAGENAME}} with metacharacters (bug 26781)
 title=[[*RFC 1234 http://example.com/]]
 !! wikitext
 {{PAGENAME}}
-!! html
+!! html/php
 <p>&#42;RFC&#32;1234 http&#58;//example.com/
 </p>
+!! html+tidy
+<p>*RFC 1234 http://example.com/</p>
 !! end
 
 !! test
@@ -7784,9 +8269,11 @@ Magic Word: {{PAGENAMEE}} with metacharacters (bug 26781)
 title=[[*RFC 1234 http://example.com/]]
 !! wikitext
 {{PAGENAMEE}}
-!! html
+!! html/php
 <p>&#42;RFC_1234_http&#58;//example.com/
 </p>
+!! html+tidy
+<p>*RFC_1234_http://example.com/</p>
 !! end
 
 !! test
@@ -8113,6 +8600,14 @@ Template with invalid target containing wikilink
 <p><span typeof="mw:Transclusion" about="#mwt1" data-mw='{"parts":[{"template":{"target":{"wt":"[[Main Page]]"},"params":{},"i":0}}]}'>{{</span><a rel="mw:WikiLink" href="./Main_Page" about="#mwt1">Main Page</a><span about="#mwt1">}}</span></p>
 !! end
 
+!! test
+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>
+!! end
+
 !! article
 Template:test
 !! text
@@ -8290,9 +8785,16 @@ Template with thumb image (with link in description)
 !! wikitext
 {{paramtest|
   param =[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]}}
-!! html
+!! html/php
 This is a test template with parameter <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Noimage.png" class="new" title="File:Noimage.png">File:Noimage.png</a>  <div class="thumbcaption"><a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">link</a> <a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">caption</a></div></div></div>
 
+!! html+tidy
+<p>This is a test template with parameter</p>
+<div class="thumb tright">
+<div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Noimage.png" class="new" title="File:Noimage.png">File:Noimage.png</a>
+<div class="thumbcaption"><a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">link</a> <a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">caption</a></div>
+</div>
+</div>
 !! end
 
 !! article
@@ -8494,8 +8996,8 @@ Template with targets containing wikilinks
 
 {{{{echo|[[foo}}]]}}
 !! html
-<p>{{<a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">foo</a>}}
-</p><p>{{<a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">foo</a>}}
+<p>{{<a href="/wiki/Foo" title="Foo">foo</a>}}
+</p><p>{{<a href="/wiki/Foo" title="Foo">foo</a>}}
 </p><p>{{[[foo}}]]
 </p>
 !! end
@@ -8714,6 +9216,42 @@ Un-closed <includeonly>
 !! html
 !! end
 
+!! test
+Includes and comments at SOL
+!! wikitext
+<!-- comment --><noinclude><!-- comment --></noinclude><!-- comment -->== hu ==
+
+<noinclude>
+some
+</noinclude>* stuff
+* here
+
+<includeonly>can have stuff</includeonly>=== here ===
+
+!! html/php
+<h2><span class="mw-headline" id="hu">hu</span></h2>
+<p>some
+</p>
+<ul><li> stuff</li>
+<li> here</li></ul>
+<h3><span class="mw-headline" id="here">here</span></h3>
+
+!! html/parsoid
+<!-- comment --><meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"&lt;noinclude>"}'/><!-- comment --><meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"&lt;/noinclude>"}'/><!-- comment -->
+<h2 data-parsoid='{}'> hu </h2>
+
+<meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"&lt;noinclude>"}'/>
+
+<p data-parsoid='{}'>some</p>
+<meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"&lt;/noinclude>"}'/>
+<ul data-parsoid='{}'>
+<li data-parsoid='{}'> stuff</li>
+
+<li data-parsoid='{}'> here</li></ul>
+
+<h3 data-parsoid='{}'> here </h3>
+!! end
+
 # TODO: test with DOM fragment reuse!
 !! test
 Parsoid: DOM fragment reuse
@@ -8883,9 +9421,10 @@ parsoid=wt2html,wt2wt
 |c
 |}
 !!html/parsoid
-<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"&lt;includeonly>a&lt;/includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":"&lt;/includeonly>"}'/><span data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true}'>{{{b}}}</span><table about="#mwt1" typeof="mw:Param" data-parsoid='{"a":{" ":null},"sa":{" ":""},"src":"{| {{{b}}}\n|c\n|}"}'>
+<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"&lt;includeonly>a&lt;/includeonly>"'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><table about="#mwt2" typeof="mw:ExpandedAttrs" data-mw='{"attribs":[[{"txt":"{{{b}}}","html":"&lt;span about=\"#mwt1\" typeof=\"mw:Param\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[31,38,null,null],&amp;quot;src&amp;quot;:&amp;quot;{{{b}}}&amp;quot;}\">{{{b}}}&lt;/span>"},{"html":""}]]}' data-parsoid='{"a":{"{{{b}}}":null},"sa":{"{{{b}}}":""}}'>
 <tbody><tr><td>c</td></tr>
 </tbody></table>
+
 !!end
 
 ###
@@ -8948,6 +9487,11 @@ Templates: 2. Inside a block tag
 <div>Foo</div>
 <blockquote>Foo</blockquote>
 
+!! html+tidy
+<div>Foo</div>
+<blockquote>
+<p>Foo</p>
+</blockquote>
 !!end
 
 !!test
@@ -8985,7 +9529,11 @@ Templates: P-wrapping: 1c. Templates on consecutive lines
 </p>
 bar <div>baz</div>
 
-!!end
+!! html+tidy
+<p>Foo</p>
+<p>bar</p>
+<div>baz</div>
+!! end
 
 !!test
 Templates: P-wrapping: 1d. Template preceded by comment-only line
@@ -9036,12 +9584,23 @@ Templates: Block Tags: 2. Back-to-back template uses
 
 !!end
 
+# This is an edge case relating to paragraph wrapping.
+!!test
+Templates: Correctly encapsulate templates producing </p> tag without a corresponding <p> tag
+!! wikitext
+{{echo|a
+b</p>}}
+!! html/parsoid
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\nb&lt;/p>"}},"i":0}}]}'>a
+b</p><p></p>
+!!end
+
 !!test
 Templates: Links: 1. Simple example
 !! wikitext
 {{echo|[[Foo|bar]]}}
 !! html
-<p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">bar</a>
+<p><a href="/wiki/Foo" title="Foo">bar</a>
 </p>
 !!end
 
@@ -9050,7 +9609,7 @@ Templates: Links: 2. Generation of link href
 !! wikitext
 [[{{echo|Foo}}|bar]]
 !! html
-<p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">bar</a>
+<p><a href="/wiki/Foo" title="Foo">bar</a>
 </p>
 !!end
 
@@ -9069,7 +9628,7 @@ Templates: Links: 3. Generation of part of a link href
 
 [[:Foo{{echo|bar}}|bar]]
 !! html
-<p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">bar</a>
+<p><a href="/wiki/Foo" title="Foo">bar</a>
 </p><p><a href="/index.php?title=Foobar&amp;action=edit&amp;redlink=1" class="new" title="Foobar (page does not exist)">Foobar</a>
 </p><p><a href="/index.php?title=Foobarbaz&amp;action=edit&amp;redlink=1" class="new" title="Foobarbaz (page does not exist)">Foobarbaz</a>
 </p><p><a href="/index.php?title=Foobar&amp;action=edit&amp;redlink=1" class="new" title="Foobar (page does not exist)">bar</a>
@@ -9092,7 +9651,7 @@ Templates: Links: 5. Generation of link text
 !! wikitext
 [[Foo|{{echo|bar}}]]
 !! html
-<p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">bar</a>
+<p><a href="/wiki/Foo" title="Foo">bar</a>
 </p>
 !!end
 
@@ -9101,7 +9660,7 @@ Templates: Links: 5. Nested templates (only outermost template should be marked)
 !! wikitext
 {{echo|[[{{echo|Foo}}|bar]]}}
 !! html
-<p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">bar</a>
+<p><a href="/wiki/Foo" title="Foo">bar</a>
 </p>
 !!end
 
@@ -9283,7 +9842,14 @@ Templates: Wiki Tables: 1a. Fostering of entire template content
 a
 <tr><td></td></tr></table>
 
-!!end
+!! html+tidy
+<p>a</p>
+<table>
+<tr>
+<td></td>
+</tr>
+</table>
+!! end
 
 !!test
 Templates: Wiki Tables: 1b. Fostering of entire template content
@@ -9301,7 +9867,16 @@ foo
 </div>
 <tr><td></td></tr></table>
 
-!!end
+!! html+tidy
+<div>
+<p>foo</p>
+</div>
+<table>
+<tr>
+<td></td>
+</tr>
+</table>
+!! end
 
 !!test
 Templates: Wiki Tables: 2. Fostering of partial template content
@@ -9316,7 +9891,15 @@ a
 <div>b</div>
 <tr><td></td></tr></table>
 
-!!end
+!! html+tidy
+<p>a</p>
+<div>b</div>
+<table>
+<tr>
+<td></td>
+</tr>
+</table>
+!! end
 
 !!test
 Templates: Wiki Tables: 3. td-content via multiple templates
@@ -9422,7 +10005,11 @@ a<div>b{{echo|c</div>d}}e
 !! html
 a<div>bc</div>de
 
-!!end
+!! html+tidy
+<p>a</p>
+<div>bc</div>
+<p>de</p>
+!! end
 
 !!test
 Templates: Ugly templates: 1. Navbox template parses badly leading to table misnesting
@@ -10335,12 +10922,12 @@ thumbsize=220
 [[Link2]]
 ]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Caption <a href="/index.php?title=Link1&amp;action=edit&amp;redlink=1" class="new" title="Link1 (page does not exist)">Link1</a> [[]] <a href="/index.php?title=Link2&amp;action=edit&amp;redlink=1" class="new" title="Link2 (page does not exist)">Link2</a></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Caption <a href="/index.php?title=Link1&amp;action=edit&amp;redlink=1" class="new" title="Link1 (page does not exist)">Link1</a> [[]] <a href="/index.php?title=Link2&amp;action=edit&amp;redlink=1" class="new" title="Link2 (page does not exist)">Link2</a></div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"Caption [[Link1]]\n[[]]\n[[Link2]]\n"}],"dsr":[0,59,2,2]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"dsr":[2,null,null,null]}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption data-parsoid='{"dsr":[null,57,null,null]}'>Caption <a rel="mw:WikiLink" href="./Link1" data-parsoid='{"stx":"simple","a":{"href":"./Link1"},"sa":{"href":"Link1"},"dsr":[32,41,2,2]}'>Link1</a>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"Caption [[Link1]]\n[[]]\n[[Link2]]\n"}],"dsr":[0,59,2,2]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"dsr":[2,null,null,null]}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption data-parsoid='{"dsr":[null,57,null,null]}'>Caption <a rel="mw:WikiLink" href="./Link1" title="Link1" data-parsoid='{"stx":"simple","a":{"href":"./Link1"},"sa":{"href":"Link1"},"dsr":[32,41,2,2]}'>Link1</a>
 [[]]
-<a rel="mw:WikiLink" href="./Link2" data-parsoid='{"stx":"simple","a":{"href":"./Link2"},"sa":{"href":"Link2"},"dsr":[47,56,2,2]}'>Link2</a>
+<a rel="mw:WikiLink" href="./Link2" title="Link2" data-parsoid='{"stx":"simple","a":{"href":"./Link2"},"sa":{"href":"Link2"},"dsr":[47,56,2,2]}'>Link2</a>
 </figcaption></figure>
 !! end
 
@@ -10371,7 +10958,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.jpg|thumb|{{echo|137px}}|This is a caption]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:139px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/137px-Foobar.jpg" width="137" height="16" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/206px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/274px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is a caption</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:139px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/137px-Foobar.jpg" width="137" height="16" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/206px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/274px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is a caption</div></div></div>
 
 !! html/parsoid
 <figure typeof="mw:Image/Thumb mw:ExpandedAttrs" data-mw='{"attribs":[["thumbnail",{"html":"thumb"}],["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[24,38,null,null]}\">137px&lt;/span>"}]]}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
@@ -10382,7 +10969,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.jpg|{{echo|thumb}}|{{echo|137px}}|This is a caption]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:139px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/137px-Foobar.jpg" width="137" height="16" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/206px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/274px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is a caption</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:139px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/137px-Foobar.jpg" width="137" height="16" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/206px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/274px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is a caption</div></div></div>
 
 !! html/parsoid
 <figure typeof="mw:Image/Thumb mw:ExpandedAttrs" data-mw='{"attribs":[["thumbnail",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;thumb&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[18,32,null,null]}\">thumb&lt;/span>"}],["width",{"html":"&lt;span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[33,47,null,null]}\">137px&lt;/span>"}]]}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
@@ -10412,6 +10999,7 @@ Image with multiple attributes from the same template
 <figure class="mw-default-size mw-halign-right" typeof="mw:Image mw:Placeholder"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption text</figcaption></figure>
 !! end
 
+# Parsoid's output here is broken (incorrect p-wrapping); see bug 64901.
 !! test
 Image with link tails
 !! options
@@ -10424,8 +11012,21 @@ thumbsize=220
 <p>123<a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>456
 </p>
 123<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>456
-123<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div></div></div></div>456
+123<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div></div></div></div>456
 
+!! html/php+tidy
+<p>123<a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>456</p>
+<p>123</p>
+<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
+<p>456 123</p>
+<div class="thumb tright">
+<div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>
+<div class="thumbcaption">
+<div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>
+</div>
+</div>
+</div>
+<p>456</p>
 !! html/parsoid
 <p>123<span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span>456</p>
 123<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></figure>456
@@ -10463,7 +11064,7 @@ thumbsize=220
 
 [[File:Foobar.jpg|middle|text-top|caption]]
 !! html/php
-<div class="thumb tleft"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
+<div class="thumb tleft"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" style="vertical-align: middle" /></a>
 </p>
 !! html/parsoid
@@ -10624,7 +11225,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.jpg|thumb|link=http://example.com/|Title]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="http://example.com/"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="http://example.com/"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>Title</figcaption></figure>
@@ -10637,7 +11238,7 @@ thumbsize=220
 !! wikitext
 [[File:Foobar.jpg|thumb=Thumb.png|Title]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/File:Foobar.jpg"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/File:Foobar.jpg"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
@@ -10651,7 +11252,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.jpg|thumb=Thumb.png|link=Main_Page|Title]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/Main_Page" title="Main Page"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/Main_Page" title="Main Page"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
@@ -10665,7 +11266,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.jpg|thumb=Thumb.png|link=http://example.com|Title]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="http://example.com"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="http://example.com"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="http://example.com"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
@@ -10679,7 +11280,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.jpg|thumb=Thumb.png|link=|Title]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:137px;"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" />  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:137px;"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" />  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><span><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></span><figcaption>Title</figcaption></figure>
@@ -10693,7 +11294,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.jpg|thumb=Thumb.png|link=Main_Page|alt=alttext|Title]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/Main_Page" title="Main Page"><img alt="alttext" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/Main_Page" title="Main Page"><img alt="alttext" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="Main_Page"><img alt="alttext" resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
@@ -10709,7 +11310,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tleft"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption">This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page">Main Page</a></figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page" title="Main Page">Main Page</a></figcaption></figure>
 !! end
 
 !! test
@@ -10722,7 +11323,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tleft"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Altitude" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption">This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img alt="Altitude" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page">Main Page</a></figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img alt="Altitude" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page" title="Main Page">Main Page</a></figcaption></figure>
 !! end
 
 !! test
@@ -10794,9 +11395,9 @@ parsoid=wt2html,wt2wt,html2html
 [[File:Foobar.jpg|thumb|frameless|caption]]
 [[File:Foobar.jpg|thumb|frame|caption]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
@@ -10854,7 +11455,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.jpg|thumb|50px]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:52px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" width="50" height="6" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/75px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/100px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:52px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" width="50" height="6" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/75px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/100px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div></div></div></div>
 
 !! html/parsoid
 <figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="6" width="50"/></a></figure>
@@ -10869,8 +11470,8 @@ parsoid=wt2html,wt2wt,html2html
 
 [[File:Foobar.svg|thumb|2000px]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div></div></div></div>
-<div class="thumb tright"><div class="thumbinner" style="width:2002px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="Foobar.svg" src="http://example.com/images/thumb/f/ff/Foobar.svg/2000px-Foobar.svg.png" width="2000" height="1500" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/3000px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/4000px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:2002px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="Foobar.svg" src="http://example.com/images/thumb/f/ff/Foobar.svg/2000px-Foobar.svg.png" width="2000" height="1500" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/3000px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/4000px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"></a></div></div></div></div>
 
 !! html/parsoid
 <figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure>
@@ -10969,7 +11570,7 @@ thumbsize=220
 !! wikitext
 [[File:Foobar.jpg|thumb|http://example.com]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></figcaption></figure>
@@ -10983,7 +11584,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.jpg|thumb|http://example.com|alt=Alteration]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Alteration" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Alteration" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img alt="Alteration" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></figcaption></figure>
@@ -10995,7 +11596,7 @@ SVG thumbnails with no language set
 !! wikitext
 [[File:Foobar.svg|thumb|caption]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/180px-Foobar.svg.png" width="180" height="135" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/360px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/180px-Foobar.svg.png" width="180" height="135" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/360px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" height="165" width="220"/></a><figcaption>caption</figcaption></figure>
@@ -11008,7 +11609,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.svg|thumb|caption|lang=de]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=File:Foobar.svg&amp;lang=de" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/langde-180px-Foobar.svg.png" width="180" height="135" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/langde-270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/langde-360px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=File:Foobar.svg&amp;lang=de" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/langde-180px-Foobar.svg.png" width="180" height="135" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/langde-270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/langde-360px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" lang="de" height="165" width="220"/></a><figcaption>caption</figcaption></figure>
@@ -11021,7 +11622,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.svg|thumb|caption|lang=invalid.language.code]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/180px-Foobar.svg.png" width="180" height="135" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/360px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>lang=invalid.language.code</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/180px-Foobar.svg.png" width="180" height="135" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/360px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"></a></div>lang=invalid.language.code</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" height="165" width="220"/></a><figcaption>lang=invalid.language.code</figcaption></figure>
@@ -11032,7 +11633,7 @@ BUG 1887: A ISBN with a thumbnail
 !! wikitext
 [[File:Foobar.jpg|thumb|ISBN 1235467890]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a href="/wiki/Special:BookSources/1235467890" class="internal mw-magiclink-isbn">ISBN 1235467890</a></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div><a href="/wiki/Special:BookSources/1235467890" class="internal mw-magiclink-isbn">ISBN 1235467890</a></div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption><a href="Special:BookSources/1235467890" rel="mw:ExtLink">ISBN 1235467890</a></figcaption></figure>
@@ -11043,7 +11644,7 @@ BUG 1887: A RFC with a thumbnail
 !! wikitext
 [[File:Foobar.jpg|thumb|This is RFC 12354]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is <a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc12354">RFC 12354</a></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is <a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc12354">RFC 12354</a></div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>This is <a href="//tools.ietf.org/html/rfc12354" rel="mw:ExtLink">RFC 12354</a></figcaption></figure>
@@ -11054,7 +11655,7 @@ BUG 1887: A mailto link with a thumbnail
 !! wikitext
 [[File:Foobar.jpg|thumb|Please mailto:nobody@example.com]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Please <a rel="nofollow" class="external free" href="mailto:nobody@example.com">mailto:nobody@example.com</a></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Please <a rel="nofollow" class="external free" href="mailto:nobody@example.com">mailto:nobody@example.com</a></div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>Please <a rel="mw:ExtLink" href="mailto:nobody@example.com">mailto:nobody@example.com</a></figcaption></figure>
@@ -11137,7 +11738,7 @@ parsoid=wt2html,wt2wt,html2html
 <p>[[Image:Foobar.jpg|thumb|This is a broken caption. But <a href="/wiki/Main_Page" title="Main Page">this</a> is just an ordinary link.
 </p>
 !! html/parsoid
-<p>[[Image:Foobar.jpg|thumb|This is a broken caption. But <a rel="mw:WikiLink" href="Main_Page">this</a> is just an ordinary link.</p>
+<p>[[Image:Foobar.jpg|thumb|This is a broken caption. But <a rel="mw:WikiLink" href="Main_Page" title="Main Page">this</a> is just an ordinary link.</p>
 !! end
 
 !! test
@@ -11145,7 +11746,7 @@ Image caption containing another image
 !! wikitext
 [[File:Foobar.jpg|thumb|This is a caption with another [[File:Thumb.png|image]] inside it!]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is a caption with another <a href="/wiki/File:Thumb.png" class="image" title="image"><img alt="image" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" /></a> inside it!</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is a caption with another <a href="/wiki/File:Thumb.png" class="image" title="image"><img alt="image" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" /></a> inside it!</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>This is a caption with another <span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"image"}'><a href="File:Thumb.png"><img resource="./File:Thumb.png" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a></span> inside it!</figcaption></figure>
@@ -11169,7 +11770,7 @@ Image: caption containing leading space
 !! wikitext
 [[File:Foobar.jpg|thumb| bar]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>bar</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>bar</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption> bar</figcaption></figure>
@@ -11188,7 +11789,7 @@ parsoid=wt2html,wt2wt,html2html
 |}
 and some more text.]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is an example image thumbnail caption with a table <table> <tr> <th> Foo </th> <th> Bar </th></tr> <tr> <td> Foo1 </td> <td> Bar1 </td></tr></table> and some more text.</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is an example image thumbnail caption with a table <table> <tr> <th> Foo </th> <th> Bar </th></tr> <tr> <td> Foo1 </td> <td> Bar1 </td></tr></table> and some more text.</div></div></div>
 
 !! html/parsoid
 <figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"/></a><figcaption>This is an example image thumbnail caption with a table
@@ -11205,7 +11806,7 @@ Bug 3090: External links other than http: in image captions
 !! wikitext
 [[File:Foobar.jpg|thumb|200x200px|This caption has [irc://example.net irc] and [https://example.com Secure] ext links in it.]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This caption has <a rel="nofollow" class="external text" href="irc://example.net">irc</a> and <a rel="nofollow" class="external text" href="https://example.com">Secure</a> ext links in it.</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This caption has <a rel="nofollow" class="external text" href="irc://example.net">irc</a> and <a rel="nofollow" class="external text" href="https://example.com">Secure</a> ext links in it.</div></div></div>
 
 !! html/parsoid
 <figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"/></a><figcaption>This caption has <a rel="mw:ExtLink" href="irc://example.net">irc</a> and <a rel="mw:ExtLink" href="https://example.com">Secure</a> ext links in it.</figcaption></figure>
@@ -11247,7 +11848,7 @@ language=es
 !! wikitext
 [[Archivo:Foobar.jpg|miniatura|izquierda|enlace=foo|caption]]
 !! html/php
-<div class="thumb tleft"><div class="thumbinner" style="width:222px;"><a href="/wiki/Foo" title="Foo"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/Archivo:Foobar.jpg" class="internal" title="Aumentar"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
+<div class="thumb tleft"><div class="thumbinner" style="width:222px;"><a href="/wiki/Foo" title="Foo"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/Archivo:Foobar.jpg" class="internal" title="Aumentar"></a></div>caption</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./Foo"><img resource="./Archivo:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
@@ -11280,9 +11881,9 @@ parsoid=wt2html,wt2wt,html2html
 
 [[File:Foobar.jpg|bogus1|thumb|bogus2|left|bogus3|caption]]
 !! html/php
-<div class="thumb tleft"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
-<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
-<div class="thumb tleft"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
+<div class="thumb tleft"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
+<div class="thumb tleft"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
@@ -11599,8 +12200,8 @@ subpage title=[[Subpage test/1/2/3/4]]
 
 [[../../subpage]]
 !! html
-<p><a rel="mw:WikiLink" href="Subpage_test/1/2/subpage/">subpage</a></p>
-<p><a rel="mw:WikiLink" href="Subpage_test/1/2/subpage">Subpage_test/1/2/subpage</a></p>
+<p><a rel="mw:WikiLink" href="Subpage_test/1/2/subpage/" title="Subpage test/1/2/subpage/">subpage</a></p>
+<p><a rel="mw:WikiLink" href="Subpage_test/1/2/subpage" title="Subpage test/1/2/subpage">Subpage_test/1/2/subpage</a></p>
 !! end
 
 !! test
@@ -11869,8 +12470,8 @@ parsoid
 [[:Category:Foo|Bar]]
 !! html
 <p>
-<a rel="mw:WikiLink" href="Category:Foo">Category:Foo</a>
-<a rel="mw:WikiLink" href="Category:Foo">Bar</a>
+<a rel="mw:WikiLink" href="Category:Foo" title="Category:Foo">Category:Foo</a>
+<a rel="mw:WikiLink" href="Category:Foo" title="Category:Foo">Bar</a>
 </p>
 !! end
 
@@ -11895,8 +12496,8 @@ parsoid
 [[:File:Foo.png|Bar]]
 !! html
 <p>
-<a rel="mw:WikiLink" href="File:Foo.png">File:Foo.png</a>
-<a rel="mw:WikiLink" href="File:Foo.png">Bar</a>
+<a rel="mw:WikiLink" href="File:Foo.png" title="File:Foo.png">File:Foo.png</a>
+<a rel="mw:WikiLink" href="File:Foo.png" title="File:Foo.png">Bar</a>
 </p>
 !! end
 
@@ -11926,15 +12527,19 @@ parsoid
 ### Inter-language links
 ###
 !! test
-Inter-language links
+Interlanguage links
 !! options
 ill
 !! wikitext
 [[es:Alimento]]
 [[fr:Nourriture]]
-[[zh:&#39135;&#21697;]]
-!! html
+[[zh:食品]]
+!! html/php
 es:Alimento fr:Nourriture zh:食品
+!! html/parsoid
+<p><link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/Alimento"/>
+<link rel="mw:PageProp/Language" href="//fr.wikipedia.org/wiki/Nourriture"/>
+<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/食品"/></p>
 !! end
 
 !! test
@@ -11946,8 +12551,13 @@ ill
 [[es:2]]
 [[fr:1]]
 [[fr:2]]
-!! html
+!! html/php
 es:1 fr:1
+!! html/parsoid
+<p><link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/1"/>
+<link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/2"/>
+<link rel="mw:PageProp/Language" href="//fr.wikipedia.org/wiki/1"/>
+<link rel="mw:PageProp/Language" href="//fr.wikipedia.org/wiki/2"/></p>
 !! end
 
 ###
@@ -12351,6 +12961,75 @@ section 5
 </p>
 !! end
 
+!! test
+Header with space, plus and underscore as entity
+!! wikitext
+Id should not contain + for spaces
+
+== Space between Text ==
+section 1
+
+== Space-Entity&#32;between&#32;Text ==
+section 2
+
+== Plus+between+Text ==
+section 3
+
+== Plus-Entity&#43;between&#43;Text ==
+section 4
+
+== Underscore_between_Text ==
+section 5
+
+== Underscore-Entity&#95;between&#95;Text ==
+section 6
+
+[[#Space between Text]]
+[[#Space-Entity&#32;between&#32;Text]]
+[[#Plus+between+Text]]
+[[#Plus-Entity&#43;between&#43;Text]]
+[[#Underscore_between_Text]]
+[[#Underscore-Entity&#95;between&#95;Text]]
+!! html
+<p>Id should not contain + for spaces
+</p>
+<div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#Space_between_Text"><span class="tocnumber">1</span> <span class="toctext">Space between Text</span></a></li>
+<li class="toclevel-1 tocsection-2"><a href="#Space-Entity_between_Text"><span class="tocnumber">2</span> <span class="toctext">Space-Entity&#32;between&#32;Text</span></a></li>
+<li class="toclevel-1 tocsection-3"><a href="#Plus.2Bbetween.2BText"><span class="tocnumber">3</span> <span class="toctext">Plus+between+Text</span></a></li>
+<li class="toclevel-1 tocsection-4"><a href="#Plus-Entity.2Bbetween.2BText"><span class="tocnumber">4</span> <span class="toctext">Plus-Entity&#43;between&#43;Text</span></a></li>
+<li class="toclevel-1 tocsection-5"><a href="#Underscore_between_Text"><span class="tocnumber">5</span> <span class="toctext">Underscore_between_Text</span></a></li>
+<li class="toclevel-1 tocsection-6"><a href="#Underscore-Entity_between_Text"><span class="tocnumber">6</span> <span class="toctext">Underscore-Entity&#95;between&#95;Text</span></a></li>
+</ul>
+</div>
+
+<h2><span class="mw-headline" id="Space_between_Text">Space between Text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Space between Text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<p>section 1
+</p>
+<h2><span class="mw-headline" id="Space-Entity_between_Text">Space-Entity&#32;between&#32;Text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Space-Entity between Text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<p>section 2
+</p>
+<h2><span class="mw-headline" id="Plus.2Bbetween.2BText">Plus+between+Text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Plus+between+Text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<p>section 3
+</p>
+<h2><span class="mw-headline" id="Plus-Entity.2Bbetween.2BText">Plus-Entity&#43;between&#43;Text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=4" title="Edit section: Plus-Entity+between+Text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<p>section 4
+</p>
+<h2><span class="mw-headline" id="Underscore_between_Text">Underscore_between_Text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=5" title="Edit section: Underscore between Text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<p>section 5
+</p>
+<h2><span class="mw-headline" id="Underscore-Entity_between_Text">Underscore-Entity&#95;between&#95;Text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=6" title="Edit section: Underscore-Entity_between_Text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<p>section 6
+</p><p><a href="#Space_between_Text">#Space between Text</a>
+<a href="#Space-Entity_between_Text">#Space-Entity&#32;between&#32;Text</a>
+<a href="#Plus.2Bbetween.2BText">#Plus+between+Text</a>
+<a href="#Plus-Entity.2Bbetween.2BText">#Plus-Entity&#43;between&#43;Text</a>
+<a href="#Underscore_between_Text">#Underscore_between_Text</a>
+<a href="#Underscore-Entity_between_Text">#Underscore-Entity&#95;between&#95;Text</a>
+</p>
+!! end
+
 !! test
 Headers with excess '=' characters
 (Are similar tests necessary beyond the 1st level?)
@@ -12533,6 +13212,31 @@ parsoid
 
 !! end
 
+!! test
+div with multiple empty attribute values
+!! options
+parsoid
+!! wikitext
+<div id= title=>HTML rocks</div>
+!! html
+<div id="" title="">HTML rocks</div>
+
+!! end
+
+!! test
+table with multiple empty attribute values
+!! options
+parsoid
+!! wikitext
+{| title= id=
+| hi
+|}
+!! html
+<table title="" id="">
+<tbody><tr><td> hi</td></tr>
+</tbody></table>
+!! end
+
 # The PHP parser escapes the opening brace to &#123; for some reason, so
 # disabled this test for it.
 !! test
@@ -12629,6 +13333,8 @@ I always thought &eacute; was a cute letter.
 !! html
 <p>I always thought &#233; was a cute letter.
 </p>
+!! html+tidy
+<p>I always thought é was a cute letter.</p>
 !! end
 
 !! test
@@ -12690,6 +13396,7 @@ Ensure that HTML adoption agency algorithm is properly implemented.
 !! end
 
 # This was bug 41545 in the PHP parser.
+# Note that tidy doesn't handle this correctly.
 !! test
 Nesting of <kbd>
 !! wikitext
@@ -12702,6 +13409,8 @@ Nesting of <kbd>
 # The following cases were bug 51081 in the PHP parser.
 # Note that there are some other nestable tags (b, i, etc) which are
 # not covered; see bug 51081 for discussion.
+
+# Note that tidy doesn't handle this correctly.
 !! test
 Nesting of <em>
 !! wikitext
@@ -12711,6 +13420,7 @@ Nesting of <em>
 </p>
 !! end
 
+# Note that tidy doesn't handle this correctly.
 !! test
 Nesting of <strong>
 !! wikitext
@@ -12724,11 +13434,11 @@ Nesting of <strong>
 Nesting of <q>
 !! wikitext
 <q>X<q>Y</q>Z</q>
-!! html
-<p><q>X<q>Y</q>Z</q>
-</p>
+!! html+tidy
+<p><q>X<q>Y</q>Z</q></p>
 !! end
 
+# Note that tidy doesn't handle this correctly.
 !! test
 Nesting of <ruby>
 !! wikitext
@@ -12738,6 +13448,7 @@ Nesting of <ruby>
 </p>
 !! end
 
+# Note that tidy doesn't handle this correctly.
 !! test
 Nesting of <bdo>
 !! wikitext
@@ -12779,6 +13490,8 @@ fixme: doBlockLevels won't wrap this in a paragraph because it contains a div
 !! html
 <a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">Safe Link&lt;div style="display:none"&gt;" onmouseover="alert(document.cookie)" onfoo="&lt;/div&gt;</a>
 
+!! html+tidy
+<p><a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">Safe Link&lt;div style="display:none"&gt;" onmouseover="alert(document.cookie)" onfoo="&lt;/div&gt;</a></p>
 !! end
 
 !! test
@@ -12906,7 +13619,7 @@ Bug 2095: link with three closing brackets
 <p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>]
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Main_Page">Main Page</a>]</p>
+<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page">Main Page</a>]</p>
 !! end
 
 !! test
@@ -12917,7 +13630,7 @@ Bug 2095: link with pipe and three closing brackets
 <p><a href="/wiki/Main_Page" title="Main Page">link</a>]
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Main_Page">link</a>]</p>
+<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page">link</a>]</p>
 !! end
 
 !! test
@@ -12928,7 +13641,7 @@ Bug 2095: link with pipe and three closing brackets, version 2
 <p><a href="/wiki/Main_Page" title="Main Page">[http://example.com/]</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Main_Page">[http://example.com/]</a></p>
+<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page">[http://example.com/]</a></p>
 !! end
 
 
@@ -12963,13 +13676,16 @@ Bug 2304: HTML attribute safety (safe template; regression bug 2309)
 
 !! end
 
+# Parsoid has enough context to handle this case
 !! test
 Bug 2304: HTML attribute safety (dangerous template; 2309)
 !! wikitext
 <div title="{{dangerous attribute}}"></div>
-!! html
+!! html/php
 <div title=""></div>
 
+!! html/parsoid
+<div title='" onmouseover="alert(document.cookie)' about="#mwt2" typeof="mw:ExpandedAttrs" data-mw='{"attribs":[[{"txt":"title"},{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;dangerous attribute&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Dangerous_attribute&amp;quot;},&amp;quot;params&amp;quot;:{},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[]],&amp;quot;dsr&amp;quot;:[12,35,null,null]}\">\" onmouseover=\"alert(document.cookie)&lt;/span>"}]]}' data-parsoid='{"stx":"html","a":{"title":"\" onmouseover=\"alert(document.cookie)"},"sa":{"title":"{{dangerous attribute}}"}}'></div>
 !! end
 
 !! test
@@ -13303,6 +14019,14 @@ Expansion of multi-line templates in attribute values (bug 6255 sanity check 2)
 
 !! end
 
+!! test
+evil <math>-wiki-tags without Extension:Math enabled
+!! wikitext
+<math><img src="some evil external link"><script>some_evil_javascript();</script></math>
+!! html+tidy
+<p>&lt;math&gt;&lt;img src="some evil external link"&gt;&lt;script&gt;some_evil_javascript();&lt;/script&gt;&lt;/math&gt;</p>
+!! end
+
 ###
 ### Parser hooks (see tests/parser/parserTestsParserHook.php for the <tag> extension)
 ###
@@ -13924,6 +14648,17 @@ http://<div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 </div>
 
 
+!! html+tidy
+<h2><span class="mw-headline" id="onmouseover.3D">onmouseover=</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: onmouseover=">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<p>http://</p>
+<div id="toc" class="toc">
+<div id="toctitle">
+<h2>Contents</h2>
+</div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#onmouseover.3D"><span class="tocnumber">1</span> <span class="toctext">onmouseover=</span></a></li>
+</ul>
+</div>
 !! end
 
 !! test
@@ -13937,6 +14672,13 @@ Fuzz testing: Parser14-table
 <tr><td></td></tr>
 </table>
 
+!! html+tidy
+<h2><span class="mw-headline" id="a">a</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: a">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<table style="__TOC__">
+<tr>
+<td></td>
+</tr>
+</table>
 !! end
 
 # Known to produce bogus xml (extra </td>)
@@ -13958,6 +14700,15 @@ noxml
 </tr>
 </table>
 
+!! html+tidy
+<table>
+<tr>
+<th>https://</th>
+<th></th>
+<th></th>
+<th></th>
+</tr>
+</table>
 !! end
 
 !! test
@@ -14045,7 +14796,6 @@ Fuzz testing: Parser25 (bug 6055)
 
 !!test
 Fuzz testing: URL adjacent extension (with space, clean)
-!! options
 !! wikitext
 http://example.com <nowiki>junk</nowiki>
 !! html
@@ -14055,7 +14805,6 @@ http://example.com <nowiki>junk</nowiki>
 
 !!test
 Fuzz testing: URL adjacent extension (no space, dirty; nowiki)
-!! options
 !! wikitext
 http://example.com<nowiki>junk</nowiki>
 !! html
@@ -14065,12 +14814,16 @@ http://example.com<nowiki>junk</nowiki>
 
 !!test
 Fuzz testing: URL adjacent extension (no space, dirty; pre)
-!! options
 !! wikitext
 http://example.com<pre>junk</pre>
 !! html
 <a rel="nofollow" class="external free" href="http://example.com">http://example.com</a><pre>junk</pre>
 
+!! html+tidy
+<p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></p>
+<pre>
+junk
+</pre>
 !!end
 
 !!test
@@ -15463,6 +16216,8 @@ parsoid=wt2html,wt2wt,html2html
 !! html/php
 <p>&#x4a;&#x61;&#x76;&#x61;&#x53;&#x63;&#114;&#x69;&#112;&#x74;
 </p>
+!! html/php+tidy
+<p>JavaScript</p>
 !! html/parsoid
 <p><span typeof="mw:Entity">J</span><span typeof="mw:Entity">a</span><span typeof="mw:Entity">v</span><span typeof="mw:Entity">a</span><span typeof="mw:Entity">S</span><span typeof="mw:Entity">c</span><span typeof="mw:Entity">r</span><span typeof="mw:Entity">i</span><span typeof="mw:Entity">p</span><span typeof="mw:Entity">t</span></p>
 !! end
@@ -15487,6 +16242,8 @@ parsoid=wt2html,wt2wt,html2html
 !! html/php
 <p>&#xee;&#xee;
 </p>
+!! html/php+tidy
+<p>îî</p>
 !! html/parsoid
 <p><span typeof="mw:Entity">î</span><span typeof="mw:Entity">î</span></p>
 !! end
@@ -15508,6 +16265,8 @@ ISBN  978-0-1234-56&#x20;789
 !! html
 <p><a href="/wiki/Special:BookSources/9780123456" class="internal mw-magiclink-isbn">ISBN 978-0-1234-56</a>&#x20;789
 </p>
+!! html+tidy
+<p><a href="/wiki/Special:BookSources/9780123456" class="internal mw-magiclink-isbn">ISBN 978-0-1234-56</a> 789</p>
 !! end
 
 !! test
@@ -15579,6 +16338,8 @@ RFC   983&#x20;987
 !! html
 <p><a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc983">RFC 983</a>&#x20;987
 </p>
+!! html+tidy
+<p><a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc983">RFC 983</a> 987</p>
 !! end
 
 !! test
@@ -15694,7 +16455,7 @@ Images with the "|" character in the comment
 !! wikitext
 [[File:Foobar.jpg|thumb|An [http://test/?param1=|left|&param2=|x external] URL]]
 !! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>An <a rel="nofollow" class="external text" href="http://test/?param1=%7Cleft%7C&amp;param2=%7Cx">external</a> URL</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>An <a rel="nofollow" class="external text" href="http://test/?param1=%7Cleft%7C&amp;param2=%7Cx">external</a> URL</div></div></div>
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>An <a rel="mw:ExtLink" href="http://test/?param1=|left|&amp;param2=|x">external</a> URL</figcaption></figure>
@@ -16796,6 +17557,10 @@ Line two</blockquote>
 <blockquote>Line one
 Line two</blockquote>
 
+!! html+tidy
+<blockquote>
+<p>Line one Line two</p>
+</blockquote>
 !! end
 
 !! test
@@ -16811,6 +17576,10 @@ Line two</blockquote>
 </p>
 Line two</blockquote>
 
+!! html+tidy
+<blockquote>
+<p>Line one</p>
+Line two</blockquote>
 !! end
 
 !! test
@@ -16826,6 +17595,11 @@ Line two
 </p>
 </blockquote>
 
+!! html+tidy
+<blockquote>
+<p>Line one</p>
+<p>Line two</p>
+</blockquote>
 !! end
 
 !! test
@@ -16843,6 +17617,11 @@ Line two
 </p>
 </blockquote>
 
+!! html+tidy
+<blockquote>
+<p>Line one</p>
+<p>Line two</p>
+</blockquote>
 !! end
 
 !! test
@@ -16924,7 +17703,7 @@ Free external link invading image caption
 !! wikitext
 [[Image:Foobar.jpg|thumb|http://x|hello]]
 !! html
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>hello</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>hello</div></div></div>
 
 !! end
 
@@ -17603,6 +18382,20 @@ __TOC__
 
 <h2><span class="mw-headline" id="Quote"><blockquote>Quote</blockquote></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Main_Page&amp;action=edit&amp;section=1" title="Edit section: Quote">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
+!! html+tidy
+<div id="toc" class="toc">
+<div id="toctitle">
+<h2>Contents</h2>
+</div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#Quote"><span class="tocnumber">1</span> <span class="toctext">Quote</span></a></li>
+</ul>
+</div>
+<h2><span class="mw-headline" id="Quote"></span></h2>
+<blockquote>
+<p><span class="mw-headline" id="Quote">Quote</span></p>
+</blockquote>
+<p><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Main_Page&amp;action=edit&amp;section=1" title="Edit section: Quote">edit</a><span class="mw-editsection-bracket">]</span></span></p>
 !! end
 
 !! test
@@ -17645,6 +18438,22 @@ __TOC__
 <h2><span class="mw-headline" id="Foo_Bar"><i>Foo</i> <b>Bar</b></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Foo Bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h2><span class="mw-headline" id="Foo_Bar_2"><i>Foo</i> <blockquote>Bar</blockquote></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Foo Bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
+!! html+tidy
+<div id="toc" class="toc">
+<div id="toctitle">
+<h2>Contents</h2>
+</div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#Foo_Bar"><span class="tocnumber">1</span> <span class="toctext"><i>Foo</i> <b>Bar</b></span></a></li>
+<li class="toclevel-1 tocsection-2"><a href="#Foo_Bar_2"><span class="tocnumber">2</span> <span class="toctext"><i>Foo</i> Bar</span></a></li>
+</ul>
+</div>
+<h2><span class="mw-headline" id="Foo_Bar"><i>Foo</i> <b>Bar</b></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Foo Bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="Foo_Bar_2"><i>Foo</i></span></h2>
+<blockquote>
+<p><span class="mw-headline" id="Foo_Bar_2">Bar</span></p>
+</blockquote>
+<p><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Foo Bar">edit</a><span class="mw-editsection-bracket">]</span></span></p>
 !! end
 
 !! test
@@ -17827,7 +18636,7 @@ nowiki inside link inside heading (bug 18295)
 !! wikitext
 ==[[foo|x<nowiki>y</nowiki>z]]==
 !! html
-<h2><span class="mw-headline" id="xyz"><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">xyz</a></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: xyz">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="xyz"><a href="/wiki/Foo" title="Foo">xyz</a></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: xyz">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
 !! end
 
@@ -18142,10 +18951,10 @@ A <ref>
 
 <references />
 !! html
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"This is a &lt;b data-parsoid=&#39;{\"dsr\":[19,40,3,3]}&#39;>&lt;a rel=\"mw:WikiLink\" href=\"./Bolded_link\" data-parsoid=&#39;{\"stx\":\"simple\",\"a\":{\"href\":\"./Bolded_link\"},\"sa\":{\"href\":\"bolded link\"},\"dsr\":[22,37,2,2]}&#39;>bolded link&lt;/a>&lt;/b> and this is a &lt;span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-mw=&#39;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"transclusion\"}},\"i\":0}}]}&#39; data-parsoid=&#39;{\"pi\":[[{\"k\":\"1\",\"spc\":[\"\",\"\",\"\",\"\"]}]],\"dsr\":[55,76,null,null]}&#39;>transclusion&lt;/span>\n"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"This is a &lt;b data-parsoid=&#39;{\"dsr\":[19,40,3,3]}&#39;>&lt;a rel=\"mw:WikiLink\" href=\"./Bolded_link\" title=\"Bolded link\" data-parsoid=&#39;{\"stx\":\"simple\",\"a\":{\"href\":\"./Bolded_link\"},\"sa\":{\"href\":\"bolded link\"},\"dsr\":[22,37,2,2]}&#39;>bolded link&lt;/a>&lt;/b> and this is a &lt;span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-mw=&#39;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"transclusion\"}},\"i\":0}}]}&#39; data-parsoid=&#39;{\"pi\":[[{\"k\":\"1\",\"spc\":[\"\",\"\",\"\",\"\"]}]],\"dsr\":[55,76,null,null]}&#39;>transclusion&lt;/span>\n"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
 
 <ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> This is a <b><a rel="mw:WikiLink" href="./Bolded_link">bolded link</a></b> and this is a <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"transclusion"}},"i":0}}]}'>transclusion</span>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> This is a <b><a rel="mw:WikiLink" href="./Bolded_link" title="Bolded link">bolded link</a></b> and this is a <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"transclusion"}},"i":0}}]}'>transclusion</span>
 </li>
 </ol>
 !!end
@@ -18476,12 +19285,12 @@ B <ref group="X" name="b" />
 <ref name="b">foo</ref>
 </references>
 !! html
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo bar for a"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo bar for a&lt;/ref>"}'><a href="#cite_note-2" data-parsoid="{}">[2]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"group":"X","name":"b"}}' id="cite_ref-b-3-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"b\" group=\"X\" />"}'><a href="#cite_note-b-3" data-parsoid="{}">[X 1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo bar for a"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo bar for a&lt;/ref>"}'><a href="#cite_note-1" data-parsoid="{}">[1]</a></span>
+B <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"group":"X","name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref group=\"X\" name=\"b\" />"}'><a href="#cite_note-b-2" data-parsoid="{}">[X 1]</a></span></p>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references />"}' data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-b-1" id="cite_note-b-1" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}">↑</span> foo</li><li about="#cite_note-2" id="cite_note-2" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-2-0" data-parsoid="{}">↑</a></span> foo bar for a</li></ol>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references />"}' data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-1-0" data-parsoid="{}">↑</a></span> foo bar for a</li></ol>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-parsoid='{"src":"&lt;references group=\"X\">\n&lt;ref name=\"b\">foo&lt;/ref>\n&lt;/references>","group":"X"}' data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"b\">foo&lt;/ref>","html":"\n&lt;span about=\"#mwt10\" class=\"reference\" data-mw=&#39;{\"name\":\"ref\",\"body\":{\"html\":\"foo\"},\"attrs\":{\"name\":\"b\"}}&#39; rel=\"dc:references\" typeof=\"mw:Extension/ref\">&lt;a href=\"#cite_note-b-1\">[1]&lt;/a>&lt;/span>\n"},"attrs":{"group":"X"}}'><li about="#cite_note-b-3" id="cite_note-b-3" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-b-3-0" data-parsoid="{}">↑</a></span> </li></ol>
+<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-parsoid='{"src":"&lt;references group=\"X\">\n&lt;ref name=\"b\">foo&lt;/ref>\n&lt;/references>","group":"X"}' data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"b\">foo&lt;/ref>","html":"\n&lt;span about=\"#mwt10\" class=\"reference\" data-mw=&#39;{\"name\":\"ref\",\"body\":{\"html\":\"foo\"},\"attrs\":{\"name\":\"b\"}}&#39; rel=\"dc:references\" typeof=\"mw:Extension/ref\">&lt;a href=\"#cite_note-b-2\">[X 1]&lt;/a>&lt;/span>\n"},"attrs":{"group":"X"}}'><li about="#cite_note-b-2" id="cite_note-b-2" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-b-2-0" data-parsoid="{}">↑</a></span> foo</li></ol>
 !! end
 
 !! test
@@ -18891,11 +19700,11 @@ parsoid
 </li>
 </ul>
 <ul>
-<li><a rel="mw:WikiLink" href="Foo">Foo</a>: bar
+<li><a rel="mw:WikiLink" href="Foo" title="Foo">Foo</a>: bar
 </li>
 </ul>
 <ul>
-<li><a rel="mw:WikiLink" href="Foo">Foo</a>*bar
+<li><a rel="mw:WikiLink" href="Foo" title="Foo">Foo</a>*bar
 </li>
 </ul>
 !!end
@@ -19186,7 +19995,7 @@ parsoid
 |}
 !! html
 <table>
-<tbody><tr><td><a rel="mw:WikiLink" href="./Foo">Foo</a>-bar</td>
+<tbody><tr><td><a rel="mw:WikiLink" href="./Foo" title="Foo">Foo</a>-bar</td>
 <td data-parsoid='{"startTagSrc":"|","attrSepSrc":"|"}'>+1</td>
 <td data-parsoid='{"startTagSrc":"|","attrSepSrc":"|"}'>-2</td></tr>
 </tbody></table>
@@ -19622,6 +20431,16 @@ parsoid
  <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
 !! end
 
+!! test
+5. Nowiki escaping should account for indent-pres
+!! options
+parsoid=html2wt
+!! html
+<pre>==foo==</pre>
+!! wikitext
+ ==foo==
+!! end
+
 #### --------------- Behavior Switches --------------------
 !! test
 1. Valid behavior switches should be escaped
@@ -19785,9 +20604,12 @@ HTML tag with 'unnecessary' entity encoding in attributes
 HTML tag with broken attribute value quoting
 !! wikitext
 <span title="Hello world>Foo</span>
-!! html
+!! html/php
 <p><span>Foo</span>
 </p>
+!! html/parsoid
+<p><span title="Hello world">Foo</span>
+</p>
 !! end
 
 !! test
@@ -19807,12 +20629,18 @@ Table with broken attribute value quoting
 {|
 | title="Hello world|Foo
 |}
-!! html
+!! html/php
 <table>
 <tr>
 <td>Foo
 </td></tr></table>
 
+!! html/parsoid
+<table>
+<tr>
+<td title="Hello world">Foo
+</td></tr></table>
+
 !! end
 
 !! test
@@ -20017,6 +20845,13 @@ Indented block & table
  {|
  |foo
  |}
+!! html/php
+ <div>foo</div>
+<table>
+<tr>
+<td>foo
+</td></tr></table>
+
 !! html/parsoid
  <div data-parsoid='{"stx":"html"}'>foo</div>
  <table><tbody>
@@ -20031,6 +20866,13 @@ Indent and comment before table row
  <!--hi-->|-
  | there
 |}
+!! html/php
+<table>
+
+<tr>
+<td> there
+</td></tr></table>
+
 !! html/parsoid
 <table data-parsoid='{}'>
  <!--hi--><tbody data-parsoid='{}'><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
@@ -20414,6 +21256,17 @@ parsoid=html2wt
 # All these tests are marked Parsoid html2wt and html2html only
 # ----------------------------------------------------------------
 
+!! test
+Serialize interwiki links pointing to the current wiki as plain wiki links (bug 65869)
+!! options
+parsoid=html2wt
+language=es
+!! wikitext
+[[Foo]]
+!! html
+<p><a rel="mw:ExtLink" href="http://es.wikipedia.org/wiki/Foo">Foo</a></p>
+!! end
+
 !! test
 Image: Modifying size of an image (1)
 !! options
index d7e8b86..9965c43 100644 (file)
@@ -24,7 +24,8 @@
  * @ingroup Testing
  */
 
-$otions = array( 'quick', 'color', 'quiet', 'help', 'show-output', 'record', 'run-disabled', 'run-parsoid' );
+$otions = array( 'quick', 'color', 'quiet', 'help', 'show-output',
+       'record', 'run-disabled', 'run-parsoid' );
 $optionsWithArgs = array( 'regex', 'filter', 'seed', 'setversion' );
 
 require_once __DIR__ . '/../maintenance/commandLine.inc';
index f67fe02..71e0f4b 100644 (file)
@@ -6,7 +6,7 @@
  * @see https://github.com/sebastianbergmann/phpunit/blob/master/src/Extensions/PhptTestCase.php
  * @author Sam Smith <samsmith@wikimedia.org>
  */
-class LessFileCompilationTest extends MediaWikiTestCase {
+class LessFileCompilationTest extends ResourceLoaderTestCase {
 
        /**
         * @var string $file
@@ -23,14 +23,8 @@ class LessFileCompilationTest extends MediaWikiTestCase {
         * @param string $file
         * @param ResourceLoaderModule $module The ResourceLoader module that
         *   contains the file
-        * @throws PHPUnit_Framework_Exception When the file parameter isn't a
-        *   string or readable file
         */
        public function __construct( $file, ResourceLoaderModule $module ) {
-               if ( !is_string( $file ) || !is_file( $file ) || !is_readable( $file ) ) {
-                       throw PHPUnit_Util_InvalidArgumentHelper::factory( 1, 'readable file' );
-               }
-
                parent::__construct( 'testLessFileCompilation' );
 
                $this->file = $file;
@@ -38,7 +32,19 @@ class LessFileCompilationTest extends MediaWikiTestCase {
        }
 
        public function testLessFileCompilation() {
-               $compiler = ResourceLoader::getLessCompiler();
+               $thisString = $this->toString();
+               $this->assertTrue(
+                       is_string( $this->file ) && is_file( $this->file ) && is_readable( $this->file ),
+                       "$thisString must refer to a readable file"
+               );
+
+               $rlContext = static::getResourceLoaderContext();
+
+               // Bleh
+               $method = new ReflectionMethod( $this->module, 'getLessCompiler' );
+               $method->setAccessible( true );
+               $compiler = $method->invoke( $this->module, $rlContext );
+
                $this->assertNotNull( $compiler->compileFile( $this->file ) );
        }
 
diff --git a/tests/phpunit/MediaWikiPHPUnitCommand.php b/tests/phpunit/MediaWikiPHPUnitCommand.php
deleted file mode 100644 (file)
index fa863fc..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-
-class MediaWikiPHPUnitCommand extends PHPUnit_TextUI_Command {
-
-       public static $additionalOptions = array(
-               'regex=' => false,
-               'file=' => false,
-               'use-filebackend=' => false,
-               'use-bagostuff=' => false,
-               'use-jobqueue=' => false,
-               'keep-uploads' => false,
-               'use-normal-tables' => false,
-               'reuse-db' => false,
-               'wiki=' => false,
-               'debug-tests' => false,
-       );
-
-       public function __construct() {
-               foreach ( self::$additionalOptions as $option => $default ) {
-                       $this->longOptions[$option] = $option . 'Handler';
-               }
-       }
-
-       protected function handleArguments( array $argv ) {
-               parent::handleArguments( $argv );
-
-               if ( !isset( $this->arguments['listeners'] ) ) {
-                       $this->arguments['listeners'] = array();
-               }
-
-               foreach ( $this->options[0] as $option ) {
-                       switch ( $option[0] ) {
-                               case '--debug-tests':
-                                       $this->arguments['listeners'][] = new MediaWikiPHPUnitTestListener( 'PHPUnitCommand' );
-                                       break;
-                       }
-               }
-       }
-
-       public static function main( $exit = true ) {
-               $command = new self;
-               $command->run( $_SERVER['argv'], $exit );
-       }
-
-       public function __call( $func, $args ) {
-
-               if ( substr( $func, -7 ) == 'Handler' ) {
-                       if ( is_null( $args[0] ) ) {
-                               $args[0] = true;
-                       } //Booleans
-                       self::$additionalOptions[substr( $func, 0, -7 )] = $args[0];
-               }
-       }
-
-       public function showHelp() {
-               parent::showHelp();
-
-               print <<<EOT
-
-ParserTest-specific options:
-  --regex="<regex>"        Only run parser tests that match the given regex
-  --file="<filename>"      File describing parser tests
-  --keep-uploads           Re-use the same upload directory for each test, don't delete it
-
-Database options:
-  --use-normal-tables      Use normal DB tables.
-  --reuse-db               Init DB only if tables are missing and keep after finish.
-
-Debugging options:
-  --debug-tests            Log testing activity to the PHPUnitCommand log channel.
-
-EOT;
-       }
-}
index 9eeb251..08463f1 100644 (file)
@@ -1,14 +1,11 @@
 <?php
 
-class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
+class MediaWikiPHPUnitTestListener extends PHPUnit_TextUI_ResultPrinter implements PHPUnit_Framework_TestListener {
+
        /**
         * @var string
         */
-       protected $logChannel;
-
-       public function __construct( $logChannel ) {
-               $this->logChannel = $logChannel;
-       }
+       protected $logChannel = 'PHPUnitCommand';
 
        protected function getTestName( PHPUnit_Framework_Test $test ) {
                $name = get_class( $test );
@@ -35,6 +32,7 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
         * @param float $time
         */
        public function addError( PHPUnit_Framework_Test $test, Exception $e, $time ) {
+               parent::addError( $test, $e, $time );
                wfDebugLog(
                        $this->logChannel,
                        'ERROR in ' . $this->getTestName( $test ) . ': ' . $this->getErrorName( $e )
@@ -51,6 +49,7 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
        public function addFailure( PHPUnit_Framework_Test $test,
                PHPUnit_Framework_AssertionFailedError $e, $time
        ) {
+               parent::addFailure( $test, $e, $time );
                wfDebugLog(
                        $this->logChannel,
                        'FAILURE in ' . $this->getTestName( $test ) . ': ' . $this->getErrorName( $e )
@@ -65,6 +64,7 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
         * @param float $time
         */
        public function addIncompleteTest( PHPUnit_Framework_Test $test, Exception $e, $time ) {
+               parent::addIncompleteTest( $test, $e, $time );
                wfDebugLog(
                        $this->logChannel,
                        'Incomplete test ' . $this->getTestName( $test ) . ': ' . $this->getErrorName( $e )
@@ -77,10 +77,9 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
         * @param PHPUnit_Framework_Test $test
         * @param Exception $e
         * @param float $time
-        *
-        * @since Method available since Release 3.0.0
         */
        public function addSkippedTest( PHPUnit_Framework_Test $test, Exception $e, $time ) {
+               parent::addSkippedTest( $test, $e, $time );
                wfDebugLog(
                        $this->logChannel,
                        'Skipped test ' . $this->getTestName( $test ) . ': ' . $this->getErrorName( $e )
@@ -91,9 +90,9 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
         * A test suite started.
         *
         * @param PHPUnit_Framework_TestSuite $suite
-        * @since Method available since Release 2.2.0
         */
        public function startTestSuite( PHPUnit_Framework_TestSuite $suite ) {
+               parent::startTestSuite( $suite );
                wfDebugLog( $this->logChannel, 'START suite ' . $suite->getName() );
        }
 
@@ -101,9 +100,9 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
         * A test suite ended.
         *
         * @param PHPUnit_Framework_TestSuite $suite
-        * @since Method available since Release 2.2.0
         */
        public function endTestSuite( PHPUnit_Framework_TestSuite $suite ) {
+               parent::endTestSuite( $suite );
                wfDebugLog( $this->logChannel, 'END suite ' . $suite->getName() );
        }
 
@@ -113,6 +112,7 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
         * @param PHPUnit_Framework_Test $test
         */
        public function startTest( PHPUnit_Framework_Test $test ) {
+               parent::startTest( $test );
                wfDebugLog( $this->logChannel, 'Start test ' . $this->getTestName( $test ) );
        }
 
@@ -123,6 +123,7 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
         * @param float $time
         */
        public function endTest( PHPUnit_Framework_Test $test, $time ) {
+               parent::endTest( $test, $time );
                wfDebugLog( $this->logChannel, 'End test ' . $this->getTestName( $test ) );
        }
 }
index c9184e8..995853e 100644 (file)
@@ -88,6 +88,14 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                $this->backupStaticAttributes = false;
        }
 
+       public function __destruct() {
+               // Complain if self::setUp() was called, but not self::tearDown()
+               // $this->called['setUp'] will be checked by self::testMediaWikiTestCaseParentSetupCalled()
+               if ( isset( $this->called['setUp'] ) && !isset( $this->called['tearDown'] ) ) {
+                       throw new MWException( get_called_class() . "::tearDown() must call parent::tearDown()" );
+               }
+       }
+
        public function run( PHPUnit_Framework_TestResult $result = null ) {
                /* Some functions require some kind of caching, and will end up using the db,
                 * which we can't allow, as that would open a new connection for mysql.
@@ -192,7 +200,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        protected function setUp() {
                wfProfileIn( __METHOD__ );
                parent::setUp();
-               $this->called['setUp'] = 1;
+               $this->called['setUp'] = true;
 
                $this->phpErrorLevel = intval( ini_get( 'error_reporting' ) );
 
@@ -221,6 +229,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        protected function tearDown() {
                wfProfileIn( __METHOD__ );
 
+               $this->called['tearDown'] = true;
                // Cleaning up temporary files
                foreach ( $this->tmpFiles as $fileName ) {
                        if ( is_file( $fileName ) || ( is_link( $fileName ) ) ) {
@@ -246,6 +255,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                }
                $this->mwGlobals = array();
                RequestContext::resetMain();
+               MediaHandler::resetCache();
 
                $phpErrorLevel = intval( ini_get( 'error_reporting' ) );
 
@@ -330,7 +340,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         *
         * @param array|string $globalKeys Key to the global variable, or an array of keys.
         *
-        * @throws Exception when trying to stash an unset global
+        * @throws Exception When trying to stash an unset global
         * @since 1.23
         */
        protected function stashMwGlobals( $globalKeys ) {
@@ -369,7 +379,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         * @param string $name The name of the global, as in wgFooBar
         * @param array $values The array containing the entries to set in that global
         *
-        * @throws MWException if the designated global is not an array.
+        * @throws MWException If the designated global is not an array.
         *
         * @since 1.21
         */
@@ -506,16 +516,16 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         *
         * @since 1.21
         *
-        * @note: the original table prefix is stored in self::$oldTablePrefix. This is used
+        * @note the original table prefix is stored in self::$oldTablePrefix. This is used
         * by teardownTestDB() to return the wiki to using the original table set.
         *
-        * @note: this method only works when first called. Subsequent calls have no effect,
+        * @note this method only works when first called. Subsequent calls have no effect,
         * even if using different parameters.
         *
         * @param DatabaseBase $db The database connection
         * @param string $prefix The prefix to use for the new table set (aka schema).
         *
-        * @throws MWException if the database table prefix is already $prefix
+        * @throws MWException If the database table prefix is already $prefix
         */
        public static function setupTestDB( DatabaseBase $db, $prefix ) {
                global $wgDBprefix;
@@ -667,8 +677,8 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         * @return mixed
         */
        public function getCliArg( $offset ) {
-               if ( isset( MediaWikiPHPUnitCommand::$additionalOptions[$offset] ) ) {
-                       return MediaWikiPHPUnitCommand::$additionalOptions[$offset];
+               if ( isset( PHPUnitMaintClass::$additionalOptions[$offset] ) ) {
+                       return PHPUnitMaintClass::$additionalOptions[$offset];
                }
        }
 
@@ -678,7 +688,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         * @param mixed $value
         */
        public function setCliArg( $offset, $value ) {
-               MediaWikiPHPUnitCommand::$additionalOptions[$offset] = $value;
+               PHPUnitMaintClass::$additionalOptions[$offset] = $value;
        }
 
        /**
@@ -1108,4 +1118,24 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
 
                $this->assertEmpty( $errors, implode( "\n", $errors ) );
        }
+
+       /**
+        * Note: we are overriding this method to remove the deprecated error
+        * @see https://bugzilla.wikimedia.org/show_bug.cgi?id=69505
+        * @see https://github.com/sebastianbergmann/phpunit/issues/1292
+        *
+        * @param array $matcher
+        * @param string $actual
+        * @param string $message
+        * @param bool $isHtml
+        */
+       public static function assertTag( $matcher, $actual, $message = '', $isHtml = true ) {
+               //trigger_error(__METHOD__ . ' is deprecated', E_USER_DEPRECATED);
+
+               $dom = PHPUnit_Util_XML::load( $actual, $isHtml );
+               $tags = PHPUnit_Util_XML::findNodes( $dom, $matcher, $isHtml );
+               $matched = count( $tags ) > 0 && $tags[0] instanceof DOMNode;
+
+               self::assertTrue( $matched, $message );
+       }
 }
index f316f56..f5f302e 100644 (file)
@@ -1,10 +1,10 @@
 <?php
 
 abstract class ResourceLoaderTestCase extends MediaWikiTestCase {
-       protected static function getResourceLoaderContext() {
+       protected static function getResourceLoaderContext( $lang = 'en' ) {
                $resourceLoader = new ResourceLoader();
                $request = new FauxRequest( array(
-                               'lang' => 'en',
+                               'lang' => $lang,
                                'modules' => 'startup',
                                'only' => 'scripts',
                                'skin' => 'vector',
@@ -46,6 +46,7 @@ class ResourceLoaderTestModule extends ResourceLoaderModule {
        protected $script = '';
        protected $styles = '';
        protected $skipFunction = null;
+       protected $isRaw = false;
        protected $targets = array( 'test' );
 
        public function __construct( $options = array() ) {
@@ -77,7 +78,18 @@ class ResourceLoaderTestModule extends ResourceLoaderModule {
        public function getSkipFunction() {
                return $this->skipFunction;
        }
+
+       public function isRaw() {
+               return $this->isRaw;
+       }
 }
 
 class ResourceLoaderFileModuleTestModule extends ResourceLoaderFileModule {
 }
+
+class ResourceLoaderWikiModuleTestModule extends ResourceLoaderWikiModule {
+       // Override expected via PHPUnit mocks and stubs
+       protected function getPages( ResourceLoaderContext $context ) {
+               return array();
+       }
+}
diff --git a/tests/phpunit/data/css/expected.css b/tests/phpunit/data/css/expected.css
new file mode 100644 (file)
index 0000000..03addcb
--- /dev/null
@@ -0,0 +1,11 @@
+/* All of the combinations should result in the same output in LTR and RTL mode. */
+
+.selector { /*@embed*/ background-image: url(simple-ltr.gif); }
+
+.selector { /*@embed*/ background-image: url(simple-ltr.gif); }
+
+.selector { /*@embed*/ background-image: url(simple-ltr.gif); }
+
+.selector { /*@embed*/ background-image: url(simple-ltr.gif); }
+
+.selector { /*@embed*/ background-image: url(simple-ltr.gif); }
diff --git a/tests/phpunit/data/css/simple-ltr.gif b/tests/phpunit/data/css/simple-ltr.gif
new file mode 100644 (file)
index 0000000..13c43e9
Binary files /dev/null and b/tests/phpunit/data/css/simple-ltr.gif differ
diff --git a/tests/phpunit/data/css/simple-rtl.gif b/tests/phpunit/data/css/simple-rtl.gif
new file mode 100644 (file)
index 0000000..f9e7531
Binary files /dev/null and b/tests/phpunit/data/css/simple-rtl.gif differ
diff --git a/tests/phpunit/data/css/test.css b/tests/phpunit/data/css/test.css
new file mode 100644 (file)
index 0000000..8d0d670
--- /dev/null
@@ -0,0 +1,11 @@
+/* All of the combinations should result in the same output in LTR and RTL mode. */
+
+/*@noflip*/ .selector { /*@embed*/ background-image: url(simple-ltr.gif); }
+
+/*@noflip*/ .selector { background-image: /*@embed*/ url(simple-ltr.gif); }
+
+.selector { /*@noflip*/ /*@embed*/ background-image: url(simple-ltr.gif); }
+
+.selector { /*@embed*/ /*@noflip*/ background-image: url(simple-ltr.gif); }
+
+.selector { /*@noflip*/ background-image: /*@embed*/ url(simple-ltr.gif); }
index b78780a..e7454af 100644 (file)
@@ -1,4 +1,3 @@
-/* @noflip */
 .unit-tests {
   color: green;
   border: 2px solid #eeeeee;
diff --git a/tests/phpunit/data/localisationcache/en.json b/tests/phpunit/data/localisationcache/en.json
new file mode 100644 (file)
index 0000000..27600cd
--- /dev/null
@@ -0,0 +1,5 @@
+{
+       "present-uk": "en",
+       "present-ru": "en",
+       "present-en": "en"
+}
diff --git a/tests/phpunit/data/localisationcache/ru.json b/tests/phpunit/data/localisationcache/ru.json
new file mode 100644 (file)
index 0000000..79e1444
--- /dev/null
@@ -0,0 +1,4 @@
+{
+       "present-uk": "ru",
+       "present-ru": "ru"
+}
diff --git a/tests/phpunit/data/localisationcache/uk.json b/tests/phpunit/data/localisationcache/uk.json
new file mode 100644 (file)
index 0000000..f63ce5d
--- /dev/null
@@ -0,0 +1,3 @@
+{
+       "present-uk": "uk"
+}
index 3e5ebb7..7bdb1ca 100644 (file)
@@ -24,14 +24,14 @@ class ArrayUtilsTest extends MediaWikiTestCase {
 
        function provideFindLowerBound() {
                $self = $this;
-               $indexValueCallback = function( $size ) use ( $self ) {
-                       return function( $val ) use ( $self, $size ) {
+               $indexValueCallback = function ( $size ) use ( $self ) {
+                       return function ( $val ) use ( $self, $size ) {
                                $self->assertTrue( $val >= 0 );
                                $self->assertTrue( $val < $size );
                                return $val;
                        };
                };
-               $comparisonCallback = function( $a, $b ) {
+               $comparisonCallback = function ( $a, $b ) {
                        return $a - $b;
                };
 
index 8e78da3..9f2b7a0 100644 (file)
@@ -4,13 +4,15 @@
  * @group Database
  */
 class ArticleTablesTest extends MediaWikiLangTestCase {
-
        /**
+        * Make sure that bug 14404 doesn't strike again. We don't want
+        * templatelinks based on the user language when {{int:}} is used, only the
+        * content language.
+        *
         * @covers Title::getTemplateLinksFrom
         * @covers Title::getLinksFrom
-        * @todo give this test a real name explaining what is being tested here
         */
-       public function testbug14404() {
+       public function testTemplatelinksUsesContentLanguage() {
                $title = Title::newFromText( 'Bug 14404' );
                $page = WikiPage::factory( $title );
                $user = new User();
index 3c653b4..185ffa4 100644 (file)
@@ -59,6 +59,9 @@ class EditPageTest extends MediaWikiLangTestCase {
         * User input text is passed to rtrim() by edit page. This is a simple
         * wrapper around assertEquals() which calls rrtrim() to normalize the
         * expected and actual texts.
+        * @param string $expected
+        * @param string $actual
+        * @param string $msg
         */
        protected function assertEditedTextEquals( $expected, $actual, $msg = '' ) {
                return $this->assertEquals( rtrim( $expected ), rtrim( $actual ), $msg );
@@ -82,7 +85,7 @@ class EditPageTest extends MediaWikiLangTestCase {
         *              * wpMinorEdit: mark as minor edit
         *              * wpWatchthis: whether to watch the page
         * @param int|null $expectedCode The expected result code (EditPage::AS_XXX constants).
-        *                  Set to null to skip the check. Defaults to EditPage::AS_OK.
+        *                  Set to null to skip the check.
         * @param string|null $expectedText The text expected to be on the page after the edit.
         *                  Set to null to skip the check.
         * @param string|null $message An optional message to show along with any error message.
@@ -90,12 +93,13 @@ class EditPageTest extends MediaWikiLangTestCase {
         * @return WikiPage The page that was just edited, useful for getting the edit's rev_id, etc.
         */
        protected function assertEdit( $title, $baseText, $user = null, array $edit,
-               $expectedCode = EditPage::AS_OK, $expectedText = null, $message = null
+               $expectedCode = null, $expectedText = null, $message = null
        ) {
                if ( is_string( $title ) ) {
                        $ns = $this->getDefaultWikitextNS();
                        $title = Title::newFromText( $title, $ns );
                }
+               $this->assertNotNull( $title );
 
                if ( is_string( $user ) ) {
                        $user = User::newFromName( $user );
@@ -141,7 +145,9 @@ class EditPageTest extends MediaWikiLangTestCase {
 
                $req = new FauxRequest( $edit, true ); // session ??
 
-               $ep = new EditPage( new Article( $title ) );
+               $article = new Article( $title );
+               $article->getContext()->setTitle( $title );
+               $ep = new EditPage( $article );
                $ep->setContextTitle( $title );
                $ep->importFormData( $req );
 
@@ -174,96 +180,85 @@ class EditPageTest extends MediaWikiLangTestCase {
                return $page;
        }
 
-       /**
-        * @todo split into a dataprovider and test method
-        * @covers EditPage
-        */
-       public function testCreatePage() {
-               $this->assertEdit(
-                       'EditPageTest_testCreatePage',
-                       null,
-                       null,
-                       array(
-                               'wpTextbox1' => "Hello World!",
+       public function provideCreatePages() {
+               return array(
+                       array( 'expected article being created',
+                               'EditPageTest_testCreatePage',
+                               null,
+                               'Hello World!',
+                               EditPage::AS_SUCCESS_NEW_ARTICLE,
+                               'Hello World!'
                        ),
-                       EditPage::AS_SUCCESS_NEW_ARTICLE,
-                       "Hello World!",
-                       "expected article being created"
-               )->doDeleteArticleReal( 'EditPageTest_testCreatePage' );
-
-               $this->assertEdit(
-                       'EditPageTest_testCreatePage',
-                       null,
-                       null,
-                       array(
-                               'wpTextbox1' => "",
+                       array( 'expected article not being created if empty',
+                               'EditPageTest_testCreatePage',
+                               null,
+                               '',
+                               EditPage::AS_BLANK_ARTICLE,
+                               null
                        ),
-                       EditPage::AS_BLANK_ARTICLE,
-                       null,
-                       "expected article not being created if empty"
-               );
-
-               $this->assertEdit(
-                       'MediaWiki:January',
-                       null,
-                       'UTSysop',
-                       array(
-                               'wpTextbox1' => "Not January",
+                       array( 'expected MediaWiki: page being created',
+                               'MediaWiki:January',
+                               'UTSysop',
+                               'Not January',
+                               EditPage::AS_SUCCESS_NEW_ARTICLE,
+                               'Not January'
                        ),
-                       EditPage::AS_SUCCESS_NEW_ARTICLE,
-                       "Not January",
-                       "expected MediaWiki: page being created"
-               )->doDeleteArticleReal( 'EditPageTest_testCreatePage' );
-
-               $this->assertEdit(
-                       'MediaWiki:EditPageTest_testCreatePage',
-                       null,
-                       'UTSysop',
-                       array(
-                               'wpTextbox1' => "",
+                       array( 'expected not-registered MediaWiki: page not being created if empty',
+                               'MediaWiki:EditPageTest_testCreatePage',
+                               'UTSysop',
+                               '',
+                               EditPage::AS_BLANK_ARTICLE,
+                               null
                        ),
-                       EditPage::AS_BLANK_ARTICLE,
-                       null,
-                       "expected not-registered MediaWiki: page not being created if empty"
-               );
-
-               $this->assertEdit(
-                       'MediaWiki:January',
-                       null,
-                       'UTSysop',
-                       array(
-                               'wpTextbox1' => "",
+                       array( 'expected registered MediaWiki: page being created even if empty',
+                               'MediaWiki:January',
+                               'UTSysop',
+                               '',
+                               EditPage::AS_SUCCESS_NEW_ARTICLE,
+                               ''
                        ),
-                       EditPage::AS_SUCCESS_NEW_ARTICLE,
-                       "",
-                       "expected registered MediaWiki: page being created even if empty"
-               )->doDeleteArticleReal( 'EditPageTest_testCreatePage' );
-
-               $this->assertEdit(
-                       'MediaWiki:Ipb-default-expiry',
-                       null,
-                       'UTSysop',
-                       array(
-                               'wpTextbox1' => "",
+                       array( 'expected registered MediaWiki: page whose default content is empty not being created if empty',
+                               'MediaWiki:Ipb-default-expiry',
+                               'UTSysop',
+                               '',
+                               EditPage::AS_BLANK_ARTICLE,
+                               ''
                        ),
-                       EditPage::AS_BLANK_ARTICLE,
-                       "",
-                       "expected registered MediaWiki: page whose default content is empty not being created if empty"
-               );
-
-               $this->assertEdit(
-                       'MediaWiki:January',
-                       null,
-                       'UTSysop',
-                       array(
-                               'wpTextbox1' => "January",
+                       array( 'expected MediaWiki: page not being created if text equals default message',
+                               'MediaWiki:January',
+                               'UTSysop',
+                               'January',
+                               EditPage::AS_BLANK_ARTICLE,
+                               null
+                       ),
+                       array( 'expected empty article being created',
+                               'EditPageTest_testCreatePage',
+                               null,
+                               '',
+                               EditPage::AS_SUCCESS_NEW_ARTICLE,
+                               '',
+                               true
                        ),
-                       EditPage::AS_BLANK_ARTICLE,
-                       null,
-                       "expected MediaWiki: page not being created if text equals default message"
                );
        }
 
+       /**
+        * @dataProvider provideCreatePages
+        * @covers EditPage
+        */
+       public function testCreatePage( $desc, $pageTitle, $user, $editText, $expectedCode, $expectedText, $ignoreBlank = false ) {
+               $edit = array( 'wpTextbox1' => $editText );
+               if ( $ignoreBlank ) {
+                       $edit['wpIgnoreBlankArticle'] = 1;
+               }
+
+               $page = $this->assertEdit( $pageTitle, null, $user, $edit, $expectedCode, $expectedText, $desc );
+
+               if ( $expectedCode != EditPage::AS_BLANK_ARTICLE ) {
+                       $page->doDeleteArticleReal( $pageTitle );
+               }
+       }
+
        public function testUpdatePage() {
                $text = "one";
                $edit = array(
index 06b512d..3acc48e 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+/**
+ * @group GlobalFunctions
+ */
 class GlobalTest extends MediaWikiTestCase {
        protected function setUp() {
                parent::setUp();
@@ -56,13 +59,33 @@ class GlobalTest extends MediaWikiTestCase {
                );
        }
 
+       /*
+        * Test cases for random functions could hypothetically fail,
+        * even though they shouldn't.
+        */
+
        /**
         * @covers ::wfRandom
         */
        public function testRandom() {
-               # This could hypothetically fail, but it shouldn't ;)
                $this->assertFalse(
-                       wfRandom() == wfRandom() );
+                       wfRandom() == wfRandom()
+               );
+       }
+
+       /**
+        * @covers ::wfRandomString
+        */
+       public function testRandomString() {
+               $this->assertFalse(
+                       wfRandomString() == wfRandomString()
+               );
+               $this->assertEquals(
+                       strlen( wfRandomString( 10 ) ), 10
+               );
+               $this->assertTrue(
+                       preg_match( '/^[0-9a-f]+$/i', wfRandomString() ) === 1
+               );
        }
 
        /**
@@ -369,6 +392,8 @@ class GlobalTest extends MediaWikiTestCase {
         * @covers ::swap
         */
        public function testSwapVarsTest() {
+               $this->hideDeprecated( 'swap' );
+
                $var1 = 1;
                $var2 = 2;
 
@@ -716,5 +741,5 @@ class GlobalTest extends MediaWikiTestCase {
                        ),
                );
        }
-       /* @TODO many more! */
+       /* @todo many more! */
 }
index cf891e7..9588ffd 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 
 /**
+ * @group GlobalFunctions
  * @group Database
  */
 class GlobalWithDBTest extends MediaWikiTestCase {
index 9bb7487..13f49f7 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 /**
+ * @group GlobalFunctions
  * @covers ::wfAssembleUrl
  */
 class WfAssembleUrlTest extends MediaWikiTestCase {
index a01c0d4..166d641 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 /**
+ * @group GlobalFunctions
  * @covers ::wfBCP47
  */
 class WfBCP47Test extends MediaWikiTestCase {
@@ -96,7 +97,7 @@ class WfBCP47Test extends MediaWikiTestCase {
                         *  az-Arab-x-AZE-derbend
                         * AZE being private, it should be lower case, hence the test above
                         * should probably be:
-                       #array( 'az-arab-x-aze-derbend', 'az-Arab-x-AZE-derbend' ),
+                        *  array( 'az-arab-x-aze-derbend', 'az-Arab-x-AZE-derbend' ),
                         */
 
                        # Private use registry values:
index 79dd91d..9d55e85 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 /**
+ * @group GlobalFunctions
  * @covers ::wfBaseConvert
  */
 class WfBaseConvertTest extends MediaWikiTestCase {
@@ -185,4 +186,10 @@ class WfBaseConvertTest extends MediaWikiTestCase {
                        strlen( wfBaseConvert( $number, 2, 2, strlen( $number ) - 5 ) )
                );
        }
+
+       public function testLeadingZero() {
+               $this->assertSame( '24', wfBaseConvert( '010', 36, 16 ) );
+               $this->assertSame( '37d4', wfBaseConvert( '0b10', 36, 16 ) );
+               $this->assertSame( 'a734', wfBaseConvert( '0x10', 36, 16 ) );
+       }
 }
index 516c1b9..705730a 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 /**
+ * @group GlobalFunctions
  * @covers ::wfBaseName
  */
 class WfBaseNameTest extends MediaWikiTestCase {
index 9effc30..a69defb 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 /**
+ * @group GlobalFunctions
  * @covers ::wfExpandUrl
  */
 class WfExpandUrlTest extends MediaWikiTestCase {
index bdb3044..bb2b33f 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 
 /**
+ * @group GlobalFunctions
  * @covers ::wfGetCaller
  */
 class WfGetCallerTest extends MediaWikiTestCase {
index af834f8..232fa92 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 /**
+ * @group GlobalFunctions
  * @covers ::wfParseUrl
  */
 class WfParseUrlTest extends MediaWikiTestCase {
index 238a2c9..1faad52 100644 (file)
@@ -1,6 +1,8 @@
 <?php
+
 /**
- *@covers ::wfRemoveDotSegments
+ * @group GlobalFunctions
+ * @covers ::wfRemoveDotSegments
  */
 class WfRemoveDotSegmentsTest extends MediaWikiTestCase {
        /**
diff --git a/tests/phpunit/includes/GlobalFunctions/wfShellExecTest.php b/tests/phpunit/includes/GlobalFunctions/wfShellExecTest.php
new file mode 100644 (file)
index 0000000..fcd26f5
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @group GlobalFunctions
+ * @covers ::wfShellExec
+ */
+class WfShellExecTest extends MediaWikiTestCase {
+       public function testBug67870() {
+               $command = wfIsWindows()
+                       // 333 = 331 + CRLF
+                       ? ( 'for /l %i in (1, 1, 1001) do @echo ' . str_repeat( '*', 331 ) )
+                       : 'printf "%-333333s" "*"';
+
+               // Test several times because it involves a race condition that may randomly succeed or fail
+               for ( $i = 0; $i < 10; $i++ ) {
+                       $output = wfShellExec( $command );
+                       $this->assertEquals( 333333, strlen( $output ) );
+               }
+       }
+}
index aadec87..67284d2 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 
 /**
+ * @group GlobalFunctions
  * @covers ::wfShorthandToInteger
  */
 class WfShorthandToIntegerTest extends MediaWikiTestCase {
index fac9b88..bea496c 100644 (file)
@@ -1,5 +1,7 @@
 <?php
-/*
+
+/**
+ * @group GlobalFunctions
  * @covers ::wfTimestamp
  */
 class WfTimestampTest extends MediaWikiTestCase {
@@ -92,7 +94,7 @@ class WfTimestampTest extends MediaWikiTestCase {
                if ( substr( $output, 0, 1 ) === '/' ) {
                        // Bug 64946: Day of the week calculations for very old
                        // timestamps varies from system to system.
-                       $this->assertRegExp(  $output, $timestamp, $message );
+                       $this->assertRegExp( $output, $timestamp, $message );
                } else {
                        $this->assertEquals( $output, $timestamp, $message );
                }
index 783b985..d11668b 100644 (file)
@@ -1,6 +1,9 @@
 <?php
+
 /**
  * The function only need a string parameter and might react to IIS7.0
+ *
+ * @group GlobalFunctions
  * @covers ::wfUrlencode
  */
 class WfUrlencodeTest extends MediaWikiTestCase {
index c1b637b..9dbfa45 100644 (file)
@@ -8,7 +8,7 @@ class HtmlFormatterTest extends MediaWikiTestCase {
         * @dataProvider getHtmlData
         *
         * @param string $input
-        * @param $expectedText
+        * @param string $expectedText
         * @param array $expectedRemoved
         * @param callable|bool $callback
         */
@@ -40,16 +40,16 @@ class HtmlFormatterTest extends MediaWikiTestCase {
        }
 
        public function getHtmlData() {
-               $removeImages = function( HtmlFormatter $f ) {
+               $removeImages = function ( HtmlFormatter $f ) {
                        $f->setRemoveMedia();
                };
-               $removeTags = function( HtmlFormatter $f ) {
+               $removeTags = function ( HtmlFormatter $f ) {
                        $f->remove( array( 'table', '.foo', '#bar', 'div.baz' ) );
                };
-               $flattenSomeStuff = function( HtmlFormatter $f ) {
+               $flattenSomeStuff = function ( HtmlFormatter $f ) {
                        $f->flatten( array( 's', 'div' ) );
                };
-               $flattenEverything = function( HtmlFormatter $f ) {
+               $flattenEverything = function ( HtmlFormatter $f ) {
                        $f->flattenAllTags();
                };
                return array(
index e934965..a8829cd 100644 (file)
@@ -112,7 +112,8 @@ class HtmlTest extends MediaWikiTestCase {
                        Html::expandAttributes( array( 'foo' => false ) ),
                        'skip keys with false value'
                );
-               $this->assertNotEmpty(
+               $this->assertEquals(
+                       ' foo=""',
                        Html::expandAttributes( array( 'foo' => '' ) ),
                        'keep keys with an empty string'
                );
@@ -153,6 +154,33 @@ class HtmlTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @covers HTML::expandAttributes
+        */
+       public function testExpandAttributesForNumbers() {
+               $this->assertEquals(
+                       ' value=1',
+                       Html::expandAttributes( array( 'value' => 1 ) ),
+                       'Integer value is cast to a string'
+               );
+               $this->assertEquals(
+                       ' value=1.1',
+                       Html::expandAttributes( array( 'value' => 1.1 ) ),
+                       'Float value is cast to a string'
+               );
+       }
+
+       /**
+        * @covers HTML::expandAttributes
+        */
+       public function testExpandAttributesForObjects() {
+               $this->assertEquals(
+                       ' value=stringValue',
+                       Html::expandAttributes( array( 'value' => new HtmlTestValue() ) ),
+                       'Object value is converted to a string'
+               );
+       }
+
        /**
         * Test for Html::expandAttributes()
         * Please note it output a string prefixed with a space!
@@ -299,6 +327,21 @@ class HtmlTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @covers Html::expandAttributes
+        * @expectedException MWException
+        */
+       public function testExpandAttributes_ArrayOnNonListValueAttribute_ThrowsException() {
+               // Real-life test case found in the Popups extension (see Gerrit cf0fd64),
+               // when used with an outdated BetaFeatures extension (see Gerrit deda1e7)
+               Html::expandAttributes( array(
+                       'src' => array(
+                               'ltr' => 'ltr.svg',
+                               'rtl' => 'rtl.svg'
+                       )
+               ) );
+       }
+
        /**
         * @covers Html::namespaceSelector
         */
@@ -664,4 +707,67 @@ class HtmlTest extends MediaWikiTestCase {
                        )
                );
        }
+
+       public function testWrapperInput() {
+               $this->assertEquals(
+                       '<input type=radio value=testval name=testname>',
+                       Html::input( 'testname', 'testval', 'radio' ),
+                       'Input wrapper with type and value.'
+               );
+               $this->assertEquals(
+                       '<input name=testname class=mw-ui-input>',
+                       Html::input( 'testname' ),
+                       'Input wrapper with all default values.'
+               );
+       }
+
+       public function testWrapperCheck() {
+               $this->assertEquals(
+                       '<input type=checkbox value=1 name=testname>',
+                       Html::check( 'testname' ),
+                       'Checkbox wrapper unchecked.'
+               );
+               $this->assertEquals(
+                       '<input checked type=checkbox value=1 name=testname>',
+                       Html::check( 'testname', true ),
+                       'Checkbox wrapper checked.'
+               );
+               $this->assertEquals(
+                       '<input type=checkbox value=testval name=testname>',
+                       Html::check( 'testname', false, array( 'value' => 'testval' ) ),
+                       'Checkbox wrapper with a value override.'
+               );
+       }
+
+       public function testWrapperRadio() {
+               $this->assertEquals(
+                       '<input type=radio value=1 name=testname>',
+                       Html::radio( 'testname' ),
+                       'Radio wrapper unchecked.'
+               );
+               $this->assertEquals(
+                       '<input checked type=radio value=1 name=testname>',
+                       Html::radio( 'testname', true ),
+                       'Radio wrapper checked.'
+               );
+               $this->assertEquals(
+                       '<input type=radio value=testval name=testname>',
+                       Html::radio( 'testname', false, array( 'value' => 'testval' ) ),
+                       'Radio wrapper with a value override.'
+               );
+       }
+
+       public function testWrapperLabel() {
+               $this->assertEquals(
+                       '<label for=testid>testlabel</label>',
+                       Html::label( 'testlabel', 'testid' ),
+                       'Label wrapper'
+               );
+       }
+}
+
+class HtmlTestValue {
+       function __toString() {
+               return 'stringValue';
+       }
 }
index 3660456..197a2b3 100644 (file)
@@ -29,8 +29,8 @@ class ImagePage404Test extends MediaWikiMediaTestCase {
 
        /**
         * @dataProvider providerGetThumbSizes
-        * @param $filename String
-        * @param $expectedNumberThumbs integer How many thumbnails to show
+        * @param string $filename
+        * @param int $expectedNumberThumbs How many thumbnails to show
         */
        function testGetThumbSizes( $filename, $expectedNumberThumbs ) {
                $iPage = $this->getImagePage( $filename );
index d5ecb95..3c255b5 100644 (file)
@@ -22,8 +22,8 @@ class ImagePageTest extends MediaWikiMediaTestCase {
 
        /**
         * @dataProvider providerGetDisplayWidthHeight
-        * @param $dimensions Array [maxWidth, maxHeight, width, height]
-        * @param $expected Array [width, height] The width and height we expect to display at
+        * @param array $dim Array [maxWidth, maxHeight, width, height]
+        * @param array $expected Array [width, height] The width and height we expect to display at
         */
        function testGetDisplayWidthHeight( $dim, $expected ) {
                $iPage = $this->getImagePage( 'animated.gif' );
@@ -66,8 +66,8 @@ class ImagePageTest extends MediaWikiMediaTestCase {
 
        /**
         * @dataProvider providerGetThumbSizes
-        * @param $filename String
-        * @param $expectedNumberThumbs integer How many thumbnails to show
+        * @param string $filename
+        * @param int $expectedNumberThumbs How many thumbnails to show
         */
        function testGetThumbSizes( $filename, $expectedNumberThumbs ) {
                $iPage = $this->getImagePage( $filename );
index 8895403..2fce6bf 100644 (file)
@@ -22,12 +22,13 @@ class ImportTest extends MediaWikiLangTestCase {
         * @covers WikiImporter::handlePage
         * @dataProvider getRedirectXML
         * @param string $xml
+        * @param string|null $redirectTitle
         */
        public function testHandlePageContainsRedirect( $xml, $redirectTitle ) {
                $source = $this->getInputStreamSource( $xml );
 
-               $redirect = NULL;
-               $callback = function( $title, $origTitle, $revCount, $sRevCount, $pageInfo ) use ( &$redirect ) {
+               $redirect = null;
+               $callback = function ( $title, $origTitle, $revCount, $sRevCount, $pageInfo ) use ( &$redirect ) {
                        if ( array_key_exists( 'redirect', $pageInfo ) ) {
                                $redirect = $pageInfo['redirect'];
                        }
@@ -92,7 +93,7 @@ EOF
 </mediawiki>
 EOF
                        ,
-                               NULL
+                               null
                        ),
                );
        }
index a5dac8d..02f6b2a 100644 (file)
@@ -215,8 +215,8 @@ class LinksUpdateTest extends MediaWikiTestCase {
                $po->setProperty( "bool", true );
                $expected[] = array( "bool", true );
 
-               $po->setProperty( "float", 4.0 + 1.0/4.0 );
-               $expected[] = array( "float", 4.0 + 1.0/4.0 );
+               $po->setProperty( "float", 4.0 + 1.0 / 4.0 );
+               $expected[] = array( "float", 4.0 + 1.0 / 4.0 );
 
                $po->setProperty( "int", -7 );
                $expected[] = array( "int", -7 );
diff --git a/tests/phpunit/includes/LocalisationCacheTest.php b/tests/phpunit/includes/LocalisationCacheTest.php
deleted file mode 100644 (file)
index f98410a..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-/**
- * @covers LocalisationCache
- */
-class LocalisationCacheTest extends MediaWikiTestCase {
-       public function testPuralRulesFallback() {
-               $cache = Language::getLocalisationCache();
-
-               $this->assertEquals(
-                       $cache->getItem( 'ar', 'pluralRules' ),
-                       $cache->getItem( 'arz', 'pluralRules' ),
-                       'arz plural rules (undefined) fallback to ar (defined)'
-               );
-
-               $this->assertEquals(
-                       $cache->getItem( 'ar', 'compiledPluralRules' ),
-                       $cache->getItem( 'arz', 'compiledPluralRules' ),
-                       'arz compiled plural rules (undefined) fallback to ar (defined)'
-               );
-
-               $this->assertNotEquals(
-                       $cache->getItem( 'ksh', 'pluralRules' ),
-                       $cache->getItem( 'de', 'pluralRules' ),
-                       'ksh plural rules (defined) dont fallback to de (defined)'
-               );
-
-               $this->assertNotEquals(
-                       $cache->getItem( 'ksh', 'compiledPluralRules' ),
-                       $cache->getItem( 'de', 'compiledPluralRules' ),
-                       'ksh compiled plural rules (defined) dont fallback to de (defined)'
-               );
-       }
-}
index 350e83f..311350b 100644 (file)
@@ -9,7 +9,7 @@
  * Test class for MWNamespace.
  * Generated by PHPUnit on 2011-02-20 at 21:01:55.
  * @todo covers tags
- * @FIXME this test file is a mess
+ * @todo FIXME: this test file is a mess
  *
  */
 class MWNamespaceTest extends MediaWikiTestCase {
index 7db985b..c2acec0 100644 (file)
@@ -119,7 +119,8 @@ class MessageTest extends MediaWikiLangTestCase {
         */
        public function testInLanguage() {
                $this->assertEquals( 'Main Page', wfMessage( 'mainpage' )->inLanguage( 'en' )->text() );
-               $this->assertEquals( 'Заглавная страница', wfMessage( 'mainpage' )->inLanguage( 'ru' )->text() );
+               $this->assertEquals( 'Заглавная страница',
+                       wfMessage( 'mainpage' )->inLanguage( 'ru' )->text() );
 
                // NOTE: make sure internal caching of the message text is reset appropriately
                $msg = wfMessage( 'mainpage' );
@@ -316,4 +317,52 @@ class MessageTest extends MediaWikiLangTestCase {
        public function testInLanguageThrows() {
                wfMessage( 'foo' )->inLanguage( 123 );
        }
+
+       public function keyProvider() {
+               return array(
+                       'string' => array(
+                               'key' => 'mainpage',
+                               'expected' => array( 'mainpage' ),
+                       ),
+                       'single' => array(
+                               'key' => array( 'mainpage' ),
+                               'expected' => array( 'mainpage' ),
+                       ),
+                       'multi' => array(
+                               'key' => array( 'mainpage-foo', 'mainpage-bar', 'mainpage' ),
+                               'expected' => array( 'mainpage-foo', 'mainpage-bar', 'mainpage' ),
+                       ),
+                       'empty' => array(
+                               'key' => array(),
+                               'expected' => null,
+                               'exception' => 'InvalidArgumentException',
+                       ),
+                       'null' => array(
+                               'key' => null,
+                               'expected' => null,
+                               'exception' => 'InvalidArgumentException',
+                       ),
+                       'bad type' => array(
+                               'key' => 17,
+                               'expected' => null,
+                               'exception' => 'InvalidArgumentException',
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider keyProvider()
+        *
+        * @covers Message::getKey
+        */
+       public function testGetKey( $key, $expected, $exception = null ) {
+               if ( $exception ) {
+                       $this->setExpectedException( $exception );
+               }
+
+               $msg = new Message( $key );
+               $this->assertEquals( $expected, $msg->getKeysToTry() );
+               $this->assertEquals( count( $expected ) > 1, $msg->isMultiKey() );
+               $this->assertContains( $msg->getKey(), $expected );
+       }
 }
index a164ff9..742d382 100644 (file)
@@ -11,9 +11,9 @@ class MimeMagicTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider providerImproveTypeFromExtension
-        * @param $ext String File extension (no leading dot)
-        * @param $oldMime String Initially detected mime
-        * @param $expectedMime String Mime type after taking extension into account
+        * @param string $ext File extension (no leading dot)
+        * @param string $oldMime Initially detected MIME
+        * @param string $expectedMime MIME type after taking extension into account
         */
        function testImproveTypeFromExtension( $ext, $oldMime, $expectedMime ) {
                $actualMime = $this->mimeMagic->improveTypeFromExtension( $oldMime, $ext );
@@ -30,7 +30,8 @@ class MimeMagicTest extends MediaWikiTestCase {
                        array( 'tsv', 'text/plain', 'text/tab-separated-values' ),
                        array( 'json', 'text/plain', 'application/json' ),
                        array( 'foo', 'application/x-opc+zip', 'application/zip' ),
-                       array( 'docx', 'application/x-opc+zip', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ),
+                       array( 'docx', 'application/x-opc+zip',
+                               'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ),
                        array( 'djvu', 'image/x-djvu', 'image/vnd.djvu' ),
                        array( 'wav', 'audio/wav', 'audio/wav' ),
                );
index 542b3d6..d7e8cd3 100644 (file)
@@ -25,7 +25,7 @@ class OutputPageTest extends MediaWikiTestCase {
         * options['expectedReturn'] - expected return value
         * options['message'] - PHPUnit message for assertion
         *
-        * @param array $args key-value array of arguments as shown above
+        * @param array $args Key-value array of arguments as shown above
         */
        protected function assertTransformCssMediaCase( $args ) {
                $queryData = array();
@@ -38,7 +38,7 @@ class OutputPageTest extends MediaWikiTestCase {
                }
 
                $fauxRequest = new FauxRequest( $queryData, false );
-               $this->setMWGlobals( array(
+               $this->setMwGlobals( array(
                        'wgRequest' => $fauxRequest,
                ) );
 
@@ -141,82 +141,133 @@ class OutputPageTest extends MediaWikiTestCase {
                        // Load module script only
                        array(
                                array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS ),
-                               '<script src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=scripts&amp;skin=vector&amp;*"></script>
+                               '<script>if(window.mw){
+document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.foo\u0026amp;only=scripts\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");
+}</script>
+'
+                       ),
+                       array(
+                               // Don't condition wrap raw modules (like the startup module)
+                               array( 'test.raw', ResourceLoaderModule::TYPE_SCRIPTS ),
+                               '<script 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&amp;*"></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 ),
-                               '<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=vector&amp;*">
+                               '<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&amp;*">
+'
+                       ),
+                       // Load private module (only=scripts)
+                       array(
+                               array( 'test.quux', ResourceLoaderModule::TYPE_SCRIPTS ),
+                               '<script>if(window.mw){
+mw.test.baz({token:123});mw.loader.state({"test.quux":"ready"});
+
+}</script>
 '
                        ),
                        // Load private module (combined)
                        array(
                                array( 'test.quux', ResourceLoaderModule::TYPE_COMBINED ),
                                '<script>if(window.mw){
-mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"css":[".mw-icon{transition:none}\n/* cache key: wiki:resourceloader:filter:minify-css:7:fd8ea20b3336b2bfb230c789d430067a */"]},{});
-/* cache key: wiki:resourceloader:filter:minify-js:7:274ccee17be73cd5f4dda5dc2a819188 */
+mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"css":[".mw-icon{transition:none}\n"]},{});
+
 }</script>
 '
                        ),
                        // Load module script with with ESI
                        array(
                                array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS, true ),
-                               '<script><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=scripts&amp;skin=vector&amp;*" /></script>
+                               '<script><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=scripts&amp;skin=fallback&amp;*" /></script>
 '
                        ),
                        // Load module styles with with ESI
                        array(
                                array( 'test.foo', ResourceLoaderModule::TYPE_STYLES, true ),
-                               '<style><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=styles&amp;skin=vector&amp;*" /></style>
+                               '<style><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=styles&amp;skin=fallback&amp;*" /></style>
+',
+                       ),
+                       // Load no modules
+                       array(
+                               array( array(), ResourceLoaderModule::TYPE_COMBINED ),
+                               '',
+                       ),
+                       // noscript group
+                       array(
+                               array( '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&amp;*"></noscript>
+'
+                       ),
+                       // Load two modules in separate groups
+                       array(
+                               array( array( 'test.group.foo', 'test.group.bar' ), ResourceLoaderModule::TYPE_COMBINED ),
+                               '<script src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.group.bar&amp;skin=fallback&amp;*"></script>
+<script src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.group.foo&amp;skin=fallback&amp;*"></script>
 ',
                        ),
                );
        }
 
-
        /**
         * @dataProvider provideMakeResourceLoaderLink
         * @covers OutputPage::makeResourceLoaderLink
         */
-       public function testMakeResourceLoaderLink( $args, $expectedHtml) {
+       public function testMakeResourceLoaderLink( $args, $expectedHtml ) {
                $this->setMwGlobals( array(
+                       'wgResourceLoaderDebug' => false,
                        'wgResourceLoaderUseESI' => true,
                        'wgLoadScript' => 'http://127.0.0.1:8080/w/load.php',
                        // Affects whether CDATA is inserted
                        'wgWellFormedXml' => false,
-                       // Cache key is based on database name, and affects output;
-                       // this test should not touch the database anyways.
-                       'wgDBname' => 'wiki',
-                       'wgDBprefix' => '',
                ) );
                $class = new ReflectionClass( 'OutputPage' );
                $method = $class->getMethod( 'makeResourceLoaderLink' );
                $method->setAccessible( true );
                $ctx = new RequestContext();
+               $ctx->setSkin( SkinFactory::getDefaultInstance()->makeSkin( 'fallback' ) );
+               $ctx->setLanguage( 'en' );
                $out = new OutputPage( $ctx );
                $rl = $out->getResourceLoader();
                $rl->register( array(
-                       'test.foo' => new ResourceLoaderTestModule(array(
+                       'test.foo' => new ResourceLoaderTestModule( array(
                                'script' => 'mw.test.foo( { a: true } );',
                                'styles' => '.mw-test-foo { content: "style"; }',
                        )),
-                       'test.bar' => new ResourceLoaderTestModule(array(
+                       'test.bar' => new ResourceLoaderTestModule( array(
                                'script' => 'mw.test.bar( { a: true } );',
                                'styles' => '.mw-test-bar { content: "style"; }',
                        )),
-                       'test.baz' => new ResourceLoaderTestModule(array(
+                       'test.baz' => new ResourceLoaderTestModule( array(
                                'script' => 'mw.test.baz( { a: true } );',
                                'styles' => '.mw-test-baz { content: "style"; }',
                        )),
-                       'test.quux' => new ResourceLoaderTestModule(array(
+                       'test.quux' => new ResourceLoaderTestModule( array(
                                'script' => 'mw.test.baz( { token: 123 } );',
                                'styles' => '/* pref-animate=off */ .mw-icon { transition: none; }',
                                'group' => 'private',
                        )),
+                       'test.raw' => new ResourceLoaderTestModule( array(
+                               'script' => 'mw.test.baz( { token: 123 } );',
+                               'isRaw' => true,
+                       )),
+                       'test.noscript' => new ResourceLoaderTestModule( array(
+                               'styles' => '.mw-test-noscript { content: "style"; }',
+                               'group' => 'noscript',
+                       )),
+                       'test.group.bar' => new ResourceLoaderTestModule( array(
+                               'styles' => '.mw-group-bar { content: "style"; }',
+                               'group' => 'bar',
+                       )),
+                       'test.group.foo' => new ResourceLoaderTestModule( array(
+                               'styles' => '.mw-group-foo { content: "style"; }',
+                               'group' => 'foo',
+                       )),
                ) );
                $links = $method->invokeArgs( $out, $args );
-               $this->assertEquals( $expectedHtml, $links['html'] );
+               // Strip comments to avoid variation due to wgDBname in WikiID and cache key
+               $actualHtml = preg_replace( '#/\*[^*]+\*/#', '', $links['html'] );
+               $this->assertEquals( $expectedHtml, $actualHtml );
        }
 }
diff --git a/tests/phpunit/includes/PasswordTest.php b/tests/phpunit/includes/PasswordTest.php
new file mode 100644 (file)
index 0000000..ceb794b
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Testing framework for the Password infrastructure
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+class PasswordTest extends MediaWikiTestCase {
+       /**
+        * @covers InvalidPassword::equals
+        */
+       public function testInvalidUnequalInvalid() {
+               $invalid1 = User::getPasswordFactory()->newFromCiphertext( null );
+               $invalid2 = User::getPasswordFactory()->newFromCiphertext( null );
+
+               $this->assertFalse( $invalid1->equals( $invalid2 ) );
+       }
+}
index 6fdc239..86e8e8b 100644 (file)
@@ -57,12 +57,12 @@ class TestSample extends MediaWikiLangTestCase {
                );
        }
 
-       // @codingStandardsIgnoreStart Ignore long line warning
        /**
         * @dataProvider provideTitles
+        * @codingStandardsIgnoreStart Ignore long line warning
         * See http://phpunit.de/manual/3.7/en/appendixes.annotations.html#appendixes.annotations.dataProvider
+        * @codingStandardsIgnoreEnd
         */
-       // @codingStandardsIgnoreEnd
        public function testCreateBasicListOfTitles( $titleName, $ns, $text ) {
                $title = Title::newFromText( $titleName, $ns );
                $this->assertEquals( $text, "$title", "see if '$titleName' matches '$text'" );
index f13e838..14911f0 100644 (file)
@@ -2,7 +2,7 @@
 
 /**
  * @covers Sanitizer::validateEmail
- * @TODO all test methods in this class should be refactored and...
+ * @todo all test methods in this class should be refactored and...
  *    use a single test method and a single data provider...
  */
 class SanitizerValidateEmailTest extends MediaWikiTestCase {
diff --git a/tests/phpunit/includes/SkinTemplateTest.php b/tests/phpunit/includes/SkinTemplateTest.php
deleted file mode 100644 (file)
index baa995d..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-
-/**
- * @covers SkinTemplate
- *
- * @group Output
- *
- * @licence GNU GPL v2+
- * @author Bene* < benestar.wikimedia@gmail.com >
- */
-
-class SkinTemplateTest extends MediaWikiTestCase {
-       /**
-        * @dataProvider makeListItemProvider
-        */
-       public function testMakeListItem( $expected, $key, $item, $options, $message ) {
-               $template = $this->getMockForAbstractClass( 'BaseTemplate' );
-
-               $this->assertEquals(
-                       $expected,
-                       $template->makeListItem( $key, $item, $options ),
-                       $message
-               );
-       }
-
-       public function makeListItemProvider() {
-               return array(
-                       array(
-                               '<li class="class" title="itemtitle"><a href="url" title="title">text</a></li>',
-                               '',
-                               array(
-                                       'class' => 'class',
-                                       'itemtitle' => 'itemtitle',
-                                       'href' => 'url',
-                                       'title' => 'title',
-                                       'text' => 'text'
-                               ),
-                               array(),
-                               'Test makteListItem with normal values'
-                       )
-               );
-       }
-}
index 0ee335a..245cdff 100644 (file)
@@ -70,32 +70,23 @@ class SpecialPageTest extends MediaWikiTestCase {
 
                $this->setExpectedException( 'UserNotLoggedIn', $expected );
 
-               if ( $reason === 'blank' && $title === 'blank' ) {
-                       $specialPage->requireLogin();
-               } else {
-                       $specialPage->requireLogin( $reason, $title );
-               }
+               // $specialPage->requireLogin( [ $reason [, $title ] ] )
+               call_user_func_array(
+                       array( $specialPage, 'requireLogin' ),
+                       array_filter( array( $reason, $title ) )
+               );
        }
 
        public function requireLoginAnonProvider() {
                $lang = 'en';
 
-               $msg = wfMessage( 'loginreqlink' )->inLanguage( $lang )->escaped();
-               $loginLink = '<a href="/index.php?title=Special:UserLogin&amp;returnto=Special%3AWatchlist"'
-                       . ' title="Special:UserLogin">' . $msg . '</a>';
-
-               $expected1 = wfMessage( 'exception-nologin-text-manual' )
-                       ->params( $loginLink )->inLanguage( $lang )->text();
-
+               $expected1 = wfMessage( 'exception-nologin-text' )->inLanguage( $lang )->text();
                $expected2 = wfMessage( 'about' )->inLanguage( $lang )->text();
 
                return array(
                        array( $expected1, null, null ),
                        array( $expected2, 'about', null ),
-                       array( $expected2, wfMessage( 'about' ), null ),
                        array( $expected2, 'about', 'about' ),
-                       array( $expected2, 'about', wfMessage( 'about' ) ),
-                       array( $expected1, 'blank', 'blank' )
                );
        }
 
index 3829f90..628c59b 100644 (file)
@@ -203,7 +203,7 @@ class StatusTest extends MediaWikiLangTestCase {
        }
 
        /**
-        * @param array $messageDetails eg. array( 'KEY' => array(/PARAMS/) )
+        * @param array $messageDetails E.g. array( 'KEY' => array(/PARAMS/) )
         * @return Message[]
         */
        protected function getMockMessages( $messageDetails ) {
@@ -286,7 +286,7 @@ class StatusTest extends MediaWikiLangTestCase {
        }
 
        public static function provideCleanParams() {
-               $cleanCallback = function( $value ) {
+               $cleanCallback = function ( $value ) {
                        return '-' . $value . '-';
                };
 
@@ -320,14 +320,14 @@ class StatusTest extends MediaWikiLangTestCase {
        }
 
        /**
-        * @return array of arrays with values;
+        * @return array Array of arrays with values;
         *    0 => status object
         *    1 => expected string (with no context)
         */
        public static function provideGetWikiTextAndHtml() {
                $testCases = array();
 
-               $testCases[ 'GoodStatus' ] = array(
+               $testCases['GoodStatus'] = array(
                        new Status(),
                        "Internal error: Status::getWikiText called for a good result, this is incorrect\n",
                        "<p>Internal error: Status::getWikiText called for a good result, this is incorrect\n</p>",
@@ -335,7 +335,7 @@ class StatusTest extends MediaWikiLangTestCase {
 
                $status = new Status();
                $status->ok = false;
-               $testCases[ 'GoodButNoError' ] = array(
+               $testCases['GoodButNoError'] = array(
                        $status,
                        "Internal error: Status::getWikiText: Invalid result object: no error text but not OK\n",
                        "<p>Internal error: Status::getWikiText: Invalid result object: no error text but not OK\n</p>",
@@ -343,7 +343,7 @@ class StatusTest extends MediaWikiLangTestCase {
 
                $status = new Status();
                $status->warning( 'fooBar!' );
-               $testCases[ '1StringWarning' ] = array(
+               $testCases['1StringWarning'] = array(
                        $status,
                        "<fooBar!>",
                        "<p>&lt;fooBar!&gt;\n</p>",
@@ -352,7 +352,7 @@ class StatusTest extends MediaWikiLangTestCase {
                $status = new Status();
                $status->warning( 'fooBar!' );
                $status->warning( 'fooBar2!' );
-               $testCases[ '2StringWarnings' ] = array(
+               $testCases['2StringWarnings'] = array(
                        $status,
                        "* <fooBar!>\n* <fooBar2!>\n",
                        "<ul><li> &lt;fooBar!&gt;</li>\n<li> &lt;fooBar2!&gt;</li></ul>\n",
@@ -360,7 +360,7 @@ class StatusTest extends MediaWikiLangTestCase {
 
                $status = new Status();
                $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' )  ) );
-               $testCases[ '1MessageWarning' ] = array(
+               $testCases['1MessageWarning'] = array(
                        $status,
                        "<fooBar!>",
                        "<p>&lt;fooBar!&gt;\n</p>",
@@ -369,7 +369,7 @@ class StatusTest extends MediaWikiLangTestCase {
                $status = new Status();
                $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' ) ) );
                $status->warning( new Message( 'fooBar2!' ) );
-               $testCases[ '2MessageWarnings' ] = array(
+               $testCases['2MessageWarnings'] = array(
                        $status,
                        "* <fooBar!>\n* <fooBar2!>\n",
                        "<ul><li> &lt;fooBar!&gt;</li>\n<li> &lt;fooBar2!&gt;</li></ul>\n",
@@ -391,7 +391,7 @@ class StatusTest extends MediaWikiLangTestCase {
        }
 
        /**
-        * @return array of arrays with values;
+        * @return array Array of arrays with values;
         *    0 => status object
         *    1 => expected Message parameters (with no context)
         *    2 => expected Message key
@@ -399,7 +399,7 @@ class StatusTest extends MediaWikiLangTestCase {
        public static function provideGetMessage() {
                $testCases = array();
 
-               $testCases[ 'GoodStatus' ] = array(
+               $testCases['GoodStatus'] = array(
                        new Status(),
                        array( "Status::getMessage called for a good result, this is incorrect\n" ),
                        'internalerror_info'
@@ -407,7 +407,7 @@ class StatusTest extends MediaWikiLangTestCase {
 
                $status = new Status();
                $status->ok = false;
-               $testCases[ 'GoodButNoError' ] = array(
+               $testCases['GoodButNoError'] = array(
                        $status,
                        array( "Status::getMessage: Invalid result object: no error text but not OK\n" ),
                        'internalerror_info'
@@ -415,7 +415,7 @@ class StatusTest extends MediaWikiLangTestCase {
 
                $status = new Status();
                $status->warning( 'fooBar!' );
-               $testCases[ '1StringWarning' ] = array(
+               $testCases['1StringWarning'] = array(
                        $status,
                        array(),
                        'fooBar!'
@@ -437,7 +437,7 @@ class StatusTest extends MediaWikiLangTestCase {
 
                $status = new Status();
                $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' )  ) );
-               $testCases[ '1MessageWarning' ] = array(
+               $testCases['1MessageWarning'] = array(
                        $status,
                        array( 'foo', 'bar' ),
                        'fooBar!'
@@ -446,7 +446,7 @@ class StatusTest extends MediaWikiLangTestCase {
                $status = new Status();
                $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' ) ) );
                $status->warning( new Message( 'fooBar2!' ) );
-               $testCases[ '2MessageWarnings' ] = array(
+               $testCases['2MessageWarnings'] = array(
                        $status,
                        array( new Message( 'fooBar!', array( 'foo', 'bar' ) ), new Message( 'fooBar2!' ) ),
                        "* \$1\n* \$2"
@@ -538,7 +538,7 @@ class StatusTest extends MediaWikiLangTestCase {
         */
        public function testWakeUpSanitizesCallback() {
                $status = new Status();
-               $status->cleanCallback = function( $value ) {
+               $status->cleanCallback = function ( $value ) {
                        return '-' . $value . '-';
                };
                $status->__wakeup();
index f0d4c4d..ae82bc4 100644 (file)
@@ -26,7 +26,7 @@ class TimeAdjustTest extends MediaWikiLangTestCase {
                return array(
                        array( '20061231235959', 0, '20061231235959' ),
                        array( '20061231235959', 5, '20070101000459' ),
-                       array( '20061231235959', 15,'20070101001459' ),
+                       array( '20061231235959', 15, '20070101001459' ),
                        array( '20061231235959', 60, '20070101005959' ),
                        array( '20061231235959', 90, '20070101012959' ),
                        array( '20061231235959', 120, '20070101015959' ),
index 55a17ac..5904fac 100644 (file)
@@ -4,8 +4,8 @@
  * @group ContentHandler
  * @group Database
  *
- * @note: We don't make assumptions about the main namespace.
- *        But we do expect the Help namespace to contain Wikitext.
+ * @note We don't make assumptions about the main namespace.
+ *       But we do expect the Help namespace to contain Wikitext.
  */
 class TitleMethodsTest extends MediaWikiTestCase {
 
index ac80a9a..d2400b3 100644 (file)
@@ -41,6 +41,9 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
                                NS_MEDIAWIKI => 'editinterface',
                        ),
                ) );
+               // Without this testUserBlock will use a non-English context on non-English MediaWiki
+               // installations (because of how Title::checkUserBlock is implemented) and fail.
+               RequestContext::resetMain();
 
                $this->userName = 'Useruser';
                $this->altUserName = 'Altuseruser';
@@ -400,17 +403,17 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
 
                $this->setTitle( NS_USER );
                $this->setUserPerm( '' );
-               $this->assertEquals( array( array( 'badaccess-group0' ), array( 'namespaceprotected', 'User' ) ),
+               $this->assertEquals( array( array( 'badaccess-group0' ), array( 'namespaceprotected', 'User', 'bogus' ) ),
                        $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
 
                $this->setTitle( NS_MEDIAWIKI );
                $this->setUserPerm( 'bogus' );
-               $this->assertEquals( array( array( 'protectedinterface' ) ),
+               $this->assertEquals( array( array( 'protectedinterface', 'bogus' ) ),
                        $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
 
                $this->setTitle( NS_MEDIAWIKI );
                $this->setUserPerm( 'bogus' );
-               $this->assertEquals( array( array( 'protectedinterface' ) ),
+               $this->assertEquals( array( array( 'protectedinterface', 'bogus' ) ),
                        $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
 
                $wgNamespaceProtection = null;
@@ -437,38 +440,38 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
 
                $this->setTitle( NS_USER, $this->userName . '/test.js' );
                $this->runCSSandJSPermissions(
-                       array( array( 'badaccess-group0' ), array( 'mycustomjsprotected' ) ),
-                       array( array( 'badaccess-group0' ), array( 'mycustomjsprotected' ) ),
+                       array( array( 'badaccess-group0' ), array( 'mycustomjsprotected', 'bogus' ) ),
+                       array( array( 'badaccess-group0' ), array( 'mycustomjsprotected', 'bogus' ) ),
                        array( array( 'badaccess-group0' ) ),
-                       array( array( 'badaccess-group0' ), array( 'mycustomjsprotected' ) ),
+                       array( array( 'badaccess-group0' ), array( 'mycustomjsprotected', 'bogus' ) ),
                        array( array( 'badaccess-group0' ) )
                );
 
                $this->setTitle( NS_USER, $this->userName . '/test.css' );
                $this->runCSSandJSPermissions(
-                       array( array( 'badaccess-group0' ), array( 'mycustomcssprotected' ) ),
+                       array( array( 'badaccess-group0' ), array( 'mycustomcssprotected', 'bogus' ) ),
                        array( array( 'badaccess-group0' ) ),
-                       array( array( 'badaccess-group0' ), array( 'mycustomcssprotected' ) ),
+                       array( array( 'badaccess-group0' ), array( 'mycustomcssprotected', 'bogus' ) ),
                        array( array( 'badaccess-group0' ) ),
-                       array( array( 'badaccess-group0' ), array( 'mycustomcssprotected' ) )
+                       array( array( 'badaccess-group0' ), array( 'mycustomcssprotected', 'bogus' ) )
                );
 
                $this->setTitle( NS_USER, $this->altUserName . '/test.js' );
                $this->runCSSandJSPermissions(
-                       array( array( 'badaccess-group0' ), array( 'customjsprotected' ) ),
-                       array( array( 'badaccess-group0' ), array( 'customjsprotected' ) ),
-                       array( array( 'badaccess-group0' ), array( 'customjsprotected' ) ),
-                       array( array( 'badaccess-group0' ), array( 'customjsprotected' ) ),
+                       array( array( 'badaccess-group0' ), array( 'customjsprotected', 'bogus' ) ),
+                       array( array( 'badaccess-group0' ), array( 'customjsprotected', 'bogus' ) ),
+                       array( array( 'badaccess-group0' ), array( 'customjsprotected', 'bogus' ) ),
+                       array( array( 'badaccess-group0' ), array( 'customjsprotected', 'bogus' ) ),
                        array( array( 'badaccess-group0' ) )
                );
 
                $this->setTitle( NS_USER, $this->altUserName . '/test.css' );
                $this->runCSSandJSPermissions(
-                       array( array( 'badaccess-group0' ), array( 'customcssprotected' ) ),
-                       array( array( 'badaccess-group0' ), array( 'customcssprotected' ) ),
-                       array( array( 'badaccess-group0' ), array( 'customcssprotected' ) ),
+                       array( array( 'badaccess-group0' ), array( 'customcssprotected', 'bogus' ) ),
+                       array( array( 'badaccess-group0' ), array( 'customcssprotected', 'bogus' ) ),
+                       array( array( 'badaccess-group0' ), array( 'customcssprotected', 'bogus' ) ),
                        array( array( 'badaccess-group0' ) ),
-                       array( array( 'badaccess-group0' ), array( 'customcssprotected' ) )
+                       array( array( 'badaccess-group0' ), array( 'customcssprotected', 'bogus' ) )
                );
 
                $this->setTitle( NS_USER, $this->altUserName . '/tempo' );
@@ -542,38 +545,38 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
                        "bogus" => array( 'bogus', "sysop", "protect", "" ) );
 
                $this->assertEquals( array( array( 'badaccess-group0' ),
-                               array( 'protectedpagetext', 'bogus' ),
-                               array( 'protectedpagetext', 'editprotected' ),
-                               array( 'protectedpagetext', 'protect' ) ),
+                               array( 'protectedpagetext', 'bogus', 'bogus' ),
+                               array( 'protectedpagetext', 'editprotected', 'bogus' ),
+                               array( 'protectedpagetext', 'protect', 'bogus' ) ),
                        $this->title->getUserPermissionsErrors( 'bogus',
                                $this->user ) );
-               $this->assertEquals( array( array( 'protectedpagetext', 'bogus' ),
-                               array( 'protectedpagetext', 'editprotected' ),
-                               array( 'protectedpagetext', 'protect' ) ),
+               $this->assertEquals( array( array( 'protectedpagetext', 'bogus', 'edit' ),
+                               array( 'protectedpagetext', 'editprotected', 'edit' ),
+                               array( 'protectedpagetext', 'protect', 'edit' ) ),
                        $this->title->getUserPermissionsErrors( 'edit',
                                $this->user ) );
                $this->setUserPerm( "" );
                $this->assertEquals( array( array( 'badaccess-group0' ),
-                               array( 'protectedpagetext', 'bogus' ),
-                               array( 'protectedpagetext', 'editprotected' ),
-                               array( 'protectedpagetext', 'protect' ) ),
+                               array( 'protectedpagetext', 'bogus', 'bogus' ),
+                               array( 'protectedpagetext', 'editprotected', 'bogus' ),
+                               array( 'protectedpagetext', 'protect', 'bogus' ) ),
                        $this->title->getUserPermissionsErrors( 'bogus',
                                $this->user ) );
                $this->assertEquals( array( array( 'badaccess-groups', "*, [[$prefix:Users|Users]]", 2 ),
-                               array( 'protectedpagetext', 'bogus' ),
-                               array( 'protectedpagetext', 'editprotected' ),
-                               array( 'protectedpagetext', 'protect' ) ),
+                               array( 'protectedpagetext', 'bogus', 'edit' ),
+                               array( 'protectedpagetext', 'editprotected', 'edit' ),
+                               array( 'protectedpagetext', 'protect', 'edit' ) ),
                        $this->title->getUserPermissionsErrors( 'edit',
                                $this->user ) );
                $this->setUserPerm( array( "edit", "editprotected" ) );
                $this->assertEquals( array( array( 'badaccess-group0' ),
-                               array( 'protectedpagetext', 'bogus' ),
-                               array( 'protectedpagetext', 'protect' ) ),
+                               array( 'protectedpagetext', 'bogus', 'bogus' ),
+                               array( 'protectedpagetext', 'protect', 'bogus' ) ),
                        $this->title->getUserPermissionsErrors( 'bogus',
                                $this->user ) );
                $this->assertEquals( array(
-                               array( 'protectedpagetext', 'bogus' ),
-                               array( 'protectedpagetext', 'protect' ) ),
+                               array( 'protectedpagetext', 'bogus', 'edit' ),
+                               array( 'protectedpagetext', 'protect', 'edit' ) ),
                        $this->title->getUserPermissionsErrors( 'edit',
                                $this->user ) );
 
@@ -584,14 +587,14 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
                $this->assertEquals( false,
                        $this->title->quickUserCan( 'edit', $this->user ) );
                $this->assertEquals( array( array( 'badaccess-group0' ),
-                               array( 'protectedpagetext', 'bogus' ),
-                               array( 'protectedpagetext', 'editprotected' ),
-                               array( 'protectedpagetext', 'protect' ) ),
+                               array( 'protectedpagetext', 'bogus', 'bogus' ),
+                               array( 'protectedpagetext', 'editprotected', 'bogus' ),
+                               array( 'protectedpagetext', 'protect', 'bogus' ) ),
                        $this->title->getUserPermissionsErrors( 'bogus',
                                $this->user ) );
-               $this->assertEquals( array( array( 'protectedpagetext', 'bogus' ),
-                               array( 'protectedpagetext', 'editprotected' ),
-                               array( 'protectedpagetext', 'protect' ) ),
+               $this->assertEquals( array( array( 'protectedpagetext', 'bogus', 'edit' ),
+                               array( 'protectedpagetext', 'editprotected', 'edit' ),
+                               array( 'protectedpagetext', 'protect', 'edit' ) ),
                        $this->title->getUserPermissionsErrors( 'edit',
                                $this->user ) );
 
@@ -601,14 +604,14 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
                $this->assertEquals( false,
                        $this->title->quickUserCan( 'edit', $this->user ) );
                $this->assertEquals( array( array( 'badaccess-group0' ),
-                               array( 'protectedpagetext', 'bogus' ),
-                               array( 'protectedpagetext', 'protect' ),
-                               array( 'protectedpagetext', 'protect' ) ),
+                               array( 'protectedpagetext', 'bogus', 'bogus' ),
+                               array( 'protectedpagetext', 'protect', 'bogus' ),
+                               array( 'protectedpagetext', 'protect', 'bogus' ) ),
                        $this->title->getUserPermissionsErrors( 'bogus',
                                $this->user ) );
-               $this->assertEquals( array( array( 'protectedpagetext', 'bogus' ),
-                               array( 'protectedpagetext', 'protect' ),
-                               array( 'protectedpagetext', 'protect' ) ),
+               $this->assertEquals( array( array( 'protectedpagetext', 'bogus', 'edit' ),
+                               array( 'protectedpagetext', 'protect', 'edit' ),
+                               array( 'protectedpagetext', 'protect', 'edit' ) ),
                        $this->title->getUserPermissionsErrors( 'edit',
                                $this->user ) );
        }
@@ -627,9 +630,9 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
 
                $this->assertEquals( false,
                        $this->title->userCan( 'bogus', $this->user ) );
-               $this->assertEquals( array( array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n" ),
-                               array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n" ),
-                               array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n" ) ),
+               $this->assertEquals( array( array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ),
+                               array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ),
+                               array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ) ),
                        $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
 
                $this->assertEquals( true,
index 6871582..97f6146 100644 (file)
@@ -1,9 +1,6 @@
 <?php
 
 /**
- * @group Database
- *        ^--- needed for language cache stuff
- *
  * @group Title
  */
 class TitleTest extends MediaWikiTestCase {
@@ -42,84 +39,61 @@ class TitleTest extends MediaWikiTestCase {
                }
        }
 
-       /**
-        * See also mediawiki.Title.test.js
-        * @covers Title::secureAndSplit
-        * @todo This method should be split into 2 separate tests each with a provider
-        * @note: This mainly tests MediaWikiTitleCodec::parseTitle().
-        */
-       public function testSecureAndSplit() {
-               $this->setMwGlobals( array(
-                       'wgLocalInterwikis' => array( 'localtestiw' ),
-                       'wgHooks' => array(
-                               'InterwikiLoadPrefix' => array(
-                                       function ( $prefix, &$data ) {
-                                               if ( $prefix === 'localtestiw' ) {
-                                                       $data = array( 'iw_url' => 'localtestiw' );
-                                               } elseif ( $prefix === 'remotetestiw' ) {
-                                                       $data = array( 'iw_url' => 'remotetestiw' );
-                                               }
-                                               return false;
-                                       }
-                               )
-                       )
-               ));
-               // Valid
-               foreach ( array(
-                       'Sandbox',
-                       'A "B"',
-                       'A \'B\'',
-                       '.com',
-                       '~',
-                       '#',
-                       '"',
-                       '\'',
-                       'Talk:Sandbox',
-                       'Talk:Foo:Sandbox',
-                       'File:Example.svg',
-                       'File_talk:Example.svg',
-                       'Foo/.../Sandbox',
-                       'Sandbox/...',
-                       'A~~',
-                       ':A',
+       public function provideValidSecureAndSplit() {
+               return array(
+                       array( 'Sandbox' ),
+                       array( 'A "B"' ),
+                       array( 'A \'B\'' ),
+                       array( '.com' ),
+                       array( '~' ),
+                       array( '#' ),
+                       array( '"' ),
+                       array( '\'' ),
+                       array( 'Talk:Sandbox' ),
+                       array( 'Talk:Foo:Sandbox' ),
+                       array( 'File:Example.svg' ),
+                       array( 'File_talk:Example.svg' ),
+                       array( 'Foo/.../Sandbox' ),
+                       array( 'Sandbox/...' ),
+                       array( 'A~~' ),
+                       array( ':A' ),
                        // Length is 256 total, but only title part matters
-                       'Category:' . str_repeat( 'x', 248 ),
-                       str_repeat( 'x', 252 ),
+                       array( 'Category:' . str_repeat( 'x', 248 ) ),
+                       array( str_repeat( 'x', 252 ) ),
                        // interwiki prefix
-                       'localtestiw: #anchor',
-                       'localtestiw:',
-                       'localtestiw:foo',
-                       'localtestiw: foo # anchor',
-                       'localtestiw: Talk: Sandbox # anchor',
-                       'remotetestiw:',
-                       'remotetestiw: Talk: # anchor',
-                       'remotetestiw: #bar',
-                       'remotetestiw: Talk:',
-                       'remotetestiw: Talk: Foo',
-                       'localtestiw:remotetestiw:',
-                       'localtestiw:remotetestiw:foo'
-               ) as $text ) {
-                       $this->assertInstanceOf( 'Title', Title::newFromText( $text ), "Valid: $text" );
-               }
+                       array( 'localtestiw: #anchor' ),
+                       array( 'localtestiw:' ),
+                       array( 'localtestiw:foo' ),
+                       array( 'localtestiw: foo # anchor' ),
+                       array( 'localtestiw: Talk: Sandbox # anchor' ),
+                       array( 'remotetestiw:' ),
+                       array( 'remotetestiw: Talk: # anchor' ),
+                       array( 'remotetestiw: #bar' ),
+                       array( 'remotetestiw: Talk:' ),
+                       array( 'remotetestiw: Talk: Foo' ),
+                       array( 'localtestiw:remotetestiw:' ),
+                       array( 'localtestiw:remotetestiw:foo' )
+               );
+       }
 
-               // Invalid
-               foreach ( array(
-                       '',
-                       ':',
-                       '__  __',
-                       '  __  ',
+       public function provideInvalidSecureAndSplit() {
+               return array(
+                       array( '' ),
+                       array( ':' ),
+                       array( '__  __' ),
+                       array( '  __  ' ),
                        // Bad characters forbidden regardless of wgLegalTitleChars
-                       'A [ B',
-                       'A ] B',
-                       'A { B',
-                       'A } B',
-                       'A < B',
-                       'A > B',
-                       'A | B',
+                       array( 'A [ B' ),
+                       array( 'A ] B' ),
+                       array( 'A { B' ),
+                       array( 'A } B' ),
+                       array( 'A < B' ),
+                       array( 'A > B' ),
+                       array( 'A | B' ),
                        // URL encoding
-                       'A%20B',
-                       'A%23B',
-                       'A%2523B',
+                       array( 'A%20B' ),
+                       array( 'A%23B' ),
+                       array( 'A%2523B' ),
                        // XML/HTML character entity references
                        // Note: Commented out because they are not marked invalid by the PHP test as
                        // Title::newFromText runs Sanitizer::decodeCharReferencesAndNormalize first.
@@ -127,32 +101,70 @@ class TitleTest extends MediaWikiTestCase {
                        //'A &#233; B',
                        //'A &#x00E9; B',
                        // Subject of NS_TALK does not roundtrip to NS_MAIN
-                       'Talk:File:Example.svg',
+                       array( 'Talk:File:Example.svg' ),
                        // Directory navigation
-                       '.',
-                       '..',
-                       './Sandbox',
-                       '../Sandbox',
-                       'Foo/./Sandbox',
-                       'Foo/../Sandbox',
-                       'Sandbox/.',
-                       'Sandbox/..',
+                       array( '.' ),
+                       array( '..' ),
+                       array( './Sandbox' ),
+                       array( '../Sandbox' ),
+                       array( 'Foo/./Sandbox' ),
+                       array( 'Foo/../Sandbox' ),
+                       array( 'Sandbox/.' ),
+                       array( 'Sandbox/..' ),
                        // Tilde
-                       'A ~~~ Name',
-                       'A ~~~~ Signature',
-                       'A ~~~~~ Timestamp',
-                       str_repeat( 'x', 256 ),
+                       array( 'A ~~~ Name' ),
+                       array( 'A ~~~~ Signature' ),
+                       array( 'A ~~~~~ Timestamp' ),
+                       array( str_repeat( 'x', 256 ) ),
                        // Namespace prefix without actual title
-                       'Talk:',
-                       'Talk:#',
-                       'Category: ',
-                       'Category: #bar',
+                       array( 'Talk:' ),
+                       array( 'Talk:#' ),
+                       array( 'Category: ' ),
+                       array( 'Category: #bar' ),
                        // interwiki prefix
-                       'localtestiw: Talk: # anchor',
-                       'localtestiw: Talk:'
-               ) as $text ) {
-                       $this->assertNull( Title::newFromText( $text ), "Invalid: $text" );
-               }
+                       array( 'localtestiw: Talk: # anchor' ),
+                       array( 'localtestiw: Talk:' )
+               );
+       }
+
+       private function secureAndSplitGlobals() {
+               $this->setMwGlobals( array(
+                       'wgLocalInterwikis' => array( 'localtestiw' ),
+                       'wgHooks' => array(
+                               'InterwikiLoadPrefix' => array(
+                                       function ( $prefix, &$data ) {
+                                               if ( $prefix === 'localtestiw' ) {
+                                                       $data = array( 'iw_url' => 'localtestiw' );
+                                               } elseif ( $prefix === 'remotetestiw' ) {
+                                                       $data = array( 'iw_url' => 'remotetestiw' );
+                                               }
+                                               return false;
+                                       }
+                               )
+                       )
+               ));
+       }
+
+       /**
+        * See also mediawiki.Title.test.js
+        * @covers Title::secureAndSplit
+        * @dataProvider provideValidSecureAndSplit
+        * @note This mainly tests MediaWikiTitleCodec::parseTitle().
+        */
+       public function testSecureAndSplitValid( $text ) {
+               $this->secureAndSplitGlobals();
+               $this->assertInstanceOf( 'Title', Title::newFromText( $text ), "Valid: $text" );
+       }
+
+       /**
+        * See also mediawiki.Title.test.js
+        * @covers Title::secureAndSplit
+        * @dataProvider provideInvalidSecureAndSplit
+        * @note This mainly tests MediaWikiTitleCodec::parseTitle().
+        */
+       public function testSecureAndSplitInvalid( $text ) {
+               $this->secureAndSplitGlobals();
+               $this->assertNull( Title::newFromText( $text ), "Invalid: $text" );
        }
 
        public static function provideConvertByteClassToUnicodeClass() {
@@ -225,11 +237,10 @@ class TitleTest extends MediaWikiTestCase {
        }
 
        /**
-        * @dataProvider provideBug31100
+        * @dataProvider provideSpecialNamesWithAndWithoutParameter
         * @covers Title::fixSpecialName
-        * @todo give this test a real name explaining what is being tested here
         */
-       public function testBug31100FixSpecialName( $text, $expectedParam ) {
+       public function testFixSpecialNameRetainsParameter( $text, $expectedParam ) {
                $title = Title::newFromText( $text );
                $fixed = $title->fixSpecialName();
                $stuff = explode( '/', $fixed->getDBkey(), 2 );
@@ -245,7 +256,7 @@ class TitleTest extends MediaWikiTestCase {
                );
        }
 
-       public static function provideBug31100() {
+       public static function provideSpecialNamesWithAndWithoutParameter() {
                return array(
                        array( 'Special:Version', null ),
                        array( 'Special:Version/', '' ),
@@ -606,4 +617,35 @@ class TitleTest extends MediaWikiTestCase {
                $title = Title::newFromText( $full );
                $this->assertEquals( $fragment, $title->getFragment() );
        }
+
+       /**
+        * @covers Title::isAlwaysKnown
+        * @dataProvider provideIsAlwaysKnown
+        * @param string $page
+        * @param bool $isKnown
+        */
+       public function testIsAlwaysKnown( $page, $isKnown ) {
+               $title = Title::newFromText( $page );
+               $this->assertEquals( $isKnown, $title->isAlwaysKnown() );
+       }
+
+       public function provideIsAlwaysKnown() {
+               return array(
+                       array( 'Some nonexistent page', false ),
+                       array( 'UTPage', false ),
+                       array( '#test', true ),
+                       array( 'Special:BlankPage', true ),
+                       array( 'Special:SomeNonexistentSpecialPage', false ),
+                       array( 'MediaWiki:Parentheses', true ),
+                       array( 'MediaWiki:Some nonexistent message', false ),
+               );
+       }
+
+       /**
+        * @covers Title::isAlwaysKnown
+        */
+       public function testIsAlwaysKnownOnInterwiki() {
+               $title = Title::makeTitle( NS_MAIN, 'Interwiki link', '', 'externalwiki' );
+               $this->assertTrue( $title->isAlwaysKnown() );
+       }
 }
diff --git a/tests/phpunit/includes/UserMailerTest.php b/tests/phpunit/includes/UserMailerTest.php
deleted file mode 100644 (file)
index dca8aeb..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-
-class UserMailerTest extends MediaWikiLangTestCase {
-
-       /**
-        * @covers UserMailer::quotedPrintable
-        */
-       public function testQuotedPrintable() {
-               $this->assertEquals(
-                       "=?UTF-8?Q?=C4=88u=20legebla=3F?=",
-                       UserMailer::quotedPrintable( "\xc4\x88u legebla?", "UTF-8" ) );
-       }
-
-}
index 36de114..cabbf10 100644 (file)
@@ -323,4 +323,35 @@ class UserTest extends MediaWikiTestCase {
                $this->assertFalse( $user->checkPasswordValidity( 'Passpass' )->isGood() );
                $this->assertEquals( 'password-login-forbidden', $user->getPasswordValidity( 'Passpass' ) );
        }
+
+       /**
+        * @covers User::getCanonicalName()
+        * @dataProvider provideGetCanonicalName
+        */
+       public function testGetCanonicalName( $name, $expectedArray, $msg ) {
+               foreach ( $expectedArray as $validate => $expected ) {
+                       $this->assertEquals(
+                               User::getCanonicalName( $name, $validate === 'false' ? false : $validate ),
+                               $expected,
+                               $msg . ' (' . $validate . ')'
+                       );
+               }
+       }
+
+       public function provideGetCanonicalName() {
+               return array(
+                       array( ' trailing space ', array( 'creatable' => 'Trailing space' ), 'Trailing spaces' ),
+                       // @todo FIXME: Maybe the createable name should be 'Talk:Username' or false to reject?
+                       array( 'Talk:Username', array( 'creatable' => 'Username', 'usable' => 'Username',
+                               'valid' => 'Username', 'false' => 'Talk:Username' ), 'Namespace prefix' ),
+                       array( ' name with # hash', array( 'creatable' => false, 'usable' => false ), 'With hash' ),
+                       array( 'Multi  spaces', array( 'creatable' => 'Multi spaces',
+                               'usable' => 'Multi spaces' ), 'Multi spaces' ),
+                       array( 'lowercase', array( 'creatable' => 'Lowercase' ), 'Lowercase' ),
+                       array( 'in[]valid', array( 'creatable' => false, 'usable' => false, 'valid' => false,
+                               'false' => 'In[]valid' ), 'Invalid' ),
+                       array( 'with / slash', array( 'creatable' => false, 'usable' => false, 'valid' => false,
+                               'false' => 'With / slash' ), 'With slash' ),
+               );
+       }
 }
index 7b12a4a..12d7d2a 100644 (file)
@@ -115,7 +115,7 @@ class WebRequestTest extends MediaWikiTestCase {
                        'wgUsePrivateIPs' => $private,
                        'wgHooks' => array(
                                'IsTrustedProxy' => array(
-                                       function( &$ip, &$trusted ) use ( $xffList ) {
+                                       function ( &$ip, &$trusted ) use ( $xffList ) {
                                                $trusted = $trusted || in_array( $ip, $xffList );
                                                return true;
                                        }
index 382e3d8..e655881 100644 (file)
@@ -81,7 +81,7 @@ class XmlTest extends MediaWikiTestCase {
         */
        public function testElementInputCanHaveAValueOfZero() {
                $this->assertEquals(
-                       '<input name="name" value="0" />',
+                       '<input name="name" value="0" class="mw-ui-input" />',
                        Xml::input( 'name', false, 0 ),
                        'Input with a value of 0 (bug 23797)'
                );
@@ -152,7 +152,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" class="mw-ui-input" /> ' .
                                '<label for="month">From month (and earlier):</label> ' .
                                '<select id="month" name="month" class="mw-month-selector">' .
                                '<option value="-1">all</option>' . "\n" .
@@ -173,7 +173,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" class="mw-ui-input" /> ' .
                                '<label for="month">From month (and earlier):</label> ' .
                                '<select id="month" name="month" class="mw-month-selector">' .
                                '<option value="-1">all</option>' . "\n" .
@@ -207,7 +207,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" class="mw-ui-input" /> ' .
                                '<label for="month">From month (and earlier):</label> ' .
                                '<select id="month" name="month" class="mw-month-selector">' .
                                '<option value="-1">all</option>' . "\n" .
@@ -233,7 +233,7 @@ class XmlTest extends MediaWikiTestCase {
         */
        public function testTextareaNoContent() {
                $this->assertEquals(
-                       '<textarea name="name" id="name" cols="40" rows="5"></textarea>',
+                       '<textarea name="name" id="name" cols="40" rows="5" class="mw-ui-input"></textarea>',
                        Xml::textarea( 'name', '' ),
                        'textarea() with not content'
                );
@@ -244,7 +244,7 @@ class XmlTest extends MediaWikiTestCase {
         */
        public function testTextareaAttribs() {
                $this->assertEquals(
-                       '<textarea name="name" id="name" cols="20" rows="10">&lt;txt&gt;</textarea>',
+                       '<textarea name="name" id="name" cols="20" rows="10" class="mw-ui-input">&lt;txt&gt;</textarea>',
                        Xml::textarea( 'name', '<txt>', 20, 10 ),
                        'textarea() with custom attribs'
                );
diff --git a/tests/phpunit/includes/actions/ActionTest.php b/tests/phpunit/includes/actions/ActionTest.php
new file mode 100644 (file)
index 0000000..eb370d9
--- /dev/null
@@ -0,0 +1,198 @@
+<?php
+
+/**
+ * @covers Action
+ *
+ * @licence GNU GPL v2+
+ * @author Thiemo Mättig
+ *
+ * @group Action
+ */
+class ActionTest extends MediaWikiTestCase {
+
+       protected function setUp() {
+               parent::setUp();
+
+               $context = $this->getContext();
+               $this->setMwGlobals( 'wgActions', array(
+                       'null' => null,
+                       'disabled' => false,
+                       'view' => true,
+                       'edit' => true,
+                       'revisiondelete' => true,
+                       'dummy' => true,
+                       'string' => 'NamedDummyAction',
+                       'declared' => 'NonExistingClassName',
+                       'callable' => array( $this, 'dummyActionCallback' ),
+                       'object' => new InstantiatedDummyAction( $context->getWikiPage(), $context ),
+               ) );
+       }
+
+       private function getPage() {
+               return WikiPage::factory( Title::makeTitle( 0, 'Title' ) );
+       }
+
+       private function getContext( $requestedAction = null ) {
+               $request = new FauxRequest( array( 'action' => $requestedAction ) );
+
+               $context = new DerivativeContext( RequestContext::getMain() );
+               $context->setRequest( $request );
+               $context->setWikiPage( $this->getPage() );
+
+               return $context;
+       }
+
+       public function actionProvider() {
+               return array(
+                       array( 'dummy', 'DummyAction' ),
+                       array( 'string', 'NamedDummyAction' ),
+                       array( 'callable', 'CalledDummyAction' ),
+                       array( 'object', 'InstantiatedDummyAction' ),
+
+                       // Capitalization is ignored
+                       array( 'DUMMY', 'DummyAction' ),
+                       array( 'STRING', 'NamedDummyAction' ),
+
+                       // Null and non-existing values
+                       array( 'null', null ),
+                       array( 'undeclared', null ),
+                       array( '', null ),
+                       array( false, null ),
+               );
+       }
+
+       /**
+        * @dataProvider actionProvider
+        * @param string $requestedAction
+        * @param string|null $expected
+        */
+       public function testActionExists( $requestedAction, $expected ) {
+               $exists = Action::exists( $requestedAction );
+
+               $this->assertSame( $expected !== null, $exists );
+       }
+
+       public function testActionExists_doesNotRequireInstantiation() {
+               // The method is not supposed to check if the action can be instantiated.
+               $exists = Action::exists( 'declared' );
+
+               $this->assertTrue( $exists );
+       }
+
+       /**
+        * @dataProvider actionProvider
+        * @param string $requestedAction
+        * @param string|null $expected
+        */
+       public function testGetActionName( $requestedAction, $expected ) {
+               $context = $this->getContext( $requestedAction );
+               $actionName = Action::getActionName( $context );
+
+               $this->assertEquals( $expected ?: 'nosuchaction', $actionName );
+       }
+
+       public function testGetActionName_editredlinkWorkaround() {
+               // See https://bugzilla.wikimedia.org/show_bug.cgi?id=20966
+               $context = $this->getContext( 'editredlink' );
+               $actionName = Action::getActionName( $context );
+
+               $this->assertEquals( 'edit', $actionName );
+       }
+
+       public function testGetActionName_historysubmitWorkaround() {
+               // See https://bugzilla.wikimedia.org/show_bug.cgi?id=20966
+               $context = $this->getContext( 'historysubmit' );
+               $actionName = Action::getActionName( $context );
+
+               $this->assertEquals( 'view', $actionName );
+       }
+
+       public function testGetActionName_revisiondeleteWorkaround() {
+               // See https://bugzilla.wikimedia.org/show_bug.cgi?id=20966
+               $context = $this->getContext( 'historysubmit' );
+               $context->getRequest()->setVal( 'revisiondelete', true );
+               $actionName = Action::getActionName( $context );
+
+               $this->assertEquals( 'revisiondelete', $actionName );
+       }
+
+       /**
+        * @dataProvider actionProvider
+        * @param string $requestedAction
+        * @param string|null $expected
+        */
+       public function testActionFactory( $requestedAction, $expected ) {
+               $context = $this->getContext();
+               $action = Action::factory( $requestedAction, $context->getWikiPage(), $context );
+
+               $this->assertType( $expected ?: 'null', $action );
+       }
+
+       public function testNull_doesNotExist() {
+               $exists = Action::exists( null );
+
+               $this->assertFalse( $exists );
+       }
+
+       public function testNull_defaultsToView() {
+               $context = $this->getContext( null );
+               $actionName = Action::getActionName( $context );
+
+               $this->assertEquals( 'view', $actionName );
+       }
+
+       public function testNull_canNotBeInstantiated() {
+               $page = $this->getPage();
+               $action = Action::factory( null, $page );
+
+               $this->assertNull( $action );
+       }
+
+       public function testDisabledAction_exists() {
+               $exists = Action::exists( 'disabled' );
+
+               $this->assertTrue( $exists );
+       }
+
+       public function testDisabledAction_isNotResolved() {
+               $context = $this->getContext( 'disabled' );
+               $actionName = Action::getActionName( $context );
+
+               $this->assertEquals( 'nosuchaction', $actionName );
+       }
+
+       public function testDisabledAction_factoryReturnsFalse() {
+               $page = $this->getPage();
+               $action = Action::factory( 'disabled', $page );
+
+               $this->assertFalse( $action );
+       }
+
+       public function dummyActionCallback() {
+               $context = $this->getContext();
+               return new CalledDummyAction( $context->getWikiPage(), $context );
+       }
+
+}
+
+class DummyAction extends Action {
+
+       public function getName() {
+               return get_called_class();
+       }
+
+       public function show() {
+       }
+
+       public function execute() {
+       }
+}
+
+class NamedDummyAction extends DummyAction {
+}
+
+class CalledDummyAction extends DummyAction {
+}
+
+class InstantiatedDummyAction extends DummyAction {
+}
index 9f8c139..3179a45 100644 (file)
@@ -161,14 +161,6 @@ class ApiEditPageTest extends ApiTestCase {
 
                // -- create page (or not) -----------------------------------------
                if ( $text !== null ) {
-                       if ( $text === '' ) {
-                               // can't create an empty page, so create it with some content
-                               $this->doApiRequestWithToken( array(
-                                       'action' => 'edit',
-                                       'title' => $name,
-                                       'text' => '(dummy)', ) );
-                       }
-
                        list( $re ) = $this->doApiRequestWithToken( array(
                                'action' => 'edit',
                                'title' => $name,
index 8c5f540..780cf9e 100644 (file)
@@ -55,7 +55,7 @@ class ApiMainTest extends ApiTestCase {
         * @dataProvider provideAssert
         * @param User $user
         * @param string $assert
-        * @param string|bool $error false if no error expected
+        * @param string|bool $error False if no error expected
         */
        public function testAssert( $user, $assert, $error ) {
                try {
diff --git a/tests/phpunit/includes/api/ApiModuleManagerTest.php b/tests/phpunit/includes/api/ApiModuleManagerTest.php
new file mode 100644 (file)
index 0000000..dab81e1
--- /dev/null
@@ -0,0 +1,318 @@
+<?php
+
+/**
+ * @covers ApiModuleManager
+ *
+ * @group API
+ * @group Database
+ * @group medium
+ */
+class ApiModuleManagerTest extends MediaWikiTestCase {
+
+       private function getModuleManager() {
+               $request = new FauxRequest();
+               $main = new ApiMain( $request );
+               return new ApiModuleManager( $main );
+       }
+
+       public function newApiLogin( $main, $action ) {
+               return new ApiLogin( $main, $action );
+       }
+
+       public function addModuleProvider() {
+               return array(
+                       'plain class' => array(
+                               'login',
+                               'action',
+                               'ApiLogin',
+                               null,
+                       ),
+
+                       'with factory' => array(
+                               'login',
+                               'action',
+                               'ApiLogin',
+                               array( $this, 'newApiLogin' ),
+                       ),
+
+                       'with closure' => array(
+                               'logout',
+                               'action',
+                               'ApiLogout',
+                               function ( ApiMain $main, $action ) {
+                                       return new ApiLogout( $main, $action );
+                               },
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider addModuleProvider
+        */
+       public function testAddModule( $name, $group, $class, $factory = null ) {
+               $moduleManager = $this->getModuleManager();
+               $moduleManager->addModule( $name, $group, $class, $factory );
+
+               $this->assertTrue( $moduleManager->isDefined( $name, $group ), 'isDefined' );
+               $this->assertNotNull( $moduleManager->getModule( $name, $group, true ), 'getModule' );
+       }
+
+       public function addModulesProvider() {
+               return array(
+                       'empty' => array(
+                               array(),
+                               'action',
+                       ),
+
+                       'simple' => array(
+                               array(
+                                       'login' => 'ApiLogin',
+                                       'logout' => 'ApiLogout',
+                               ),
+                               'action',
+                       ),
+
+                       'with factories' => array(
+                               array(
+                                       'login' => array(
+                                               'class' => 'ApiLogin',
+                                               'factory' => array( $this, 'newApiLogin' ),
+                                       ),
+                                       'logout' => array(
+                                               'class' => 'ApiLogout',
+                                               'factory' => function ( ApiMain $main, $action ) {
+                                                       return new ApiLogout( $main, $action );
+                                               },
+                                       ),
+                               ),
+                               'action',
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider addModulesProvider
+        */
+       public function testAddModules( array $modules, $group ) {
+               $moduleManager = $this->getModuleManager();
+               $moduleManager->addModules( $modules, $group );
+
+               foreach ( array_keys( $modules ) as $name ) {
+                       $this->assertTrue( $moduleManager->isDefined( $name, $group ), 'isDefined' );
+                       $this->assertNotNull( $moduleManager->getModule( $name, $group, true ), 'getModule' );
+               }
+
+               $this->assertTrue( true ); // Don't mark the test as risky if $modules is empty
+       }
+
+       public function getModuleProvider() {
+               $modules = array(
+                       'feedrecentchanges' => 'ApiFeedRecentChanges',
+                       'feedcontributions' => array( 'class' => 'ApiFeedContributions' ),
+                       'login' => array(
+                               'class' => 'ApiLogin',
+                               'factory' => array( $this, 'newApiLogin' ),
+                       ),
+                       'logout' => array(
+                               'class' => 'ApiLogout',
+                               'factory' => function ( ApiMain $main, $action ) {
+                                       return new ApiLogout( $main, $action );
+                               },
+                       ),
+               );
+
+               return array(
+                       'legacy entry' => array(
+                               $modules,
+                               'feedrecentchanges',
+                               'ApiFeedRecentChanges',
+                       ),
+
+                       'just a class' => array(
+                               $modules,
+                               'feedcontributions',
+                               'ApiFeedContributions',
+                       ),
+
+                       'with factory' => array(
+                               $modules,
+                               'login',
+                               'ApiLogin',
+                       ),
+
+                       'with closure' => array(
+                               $modules,
+                               'logout',
+                               'ApiLogout',
+                       ),
+               );
+       }
+
+       /**
+        * @covers ApiModuleManager::getModule
+        * @dataProvider getModuleProvider
+        */
+       public function testGetModule( $modules, $name, $expectedClass ) {
+               $moduleManager = $this->getModuleManager();
+               $moduleManager->addModules( $modules, 'test' );
+
+               // should return the right module
+               $module1 = $moduleManager->getModule( $name, null, false );
+               $this->assertInstanceOf( $expectedClass, $module1 );
+
+               // should pass group check (with caching disabled)
+               $module2 = $moduleManager->getModule( $name, 'test', true );
+               $this->assertNotNull( $module2 );
+
+               // should use cached instance
+               $module3 = $moduleManager->getModule( $name, null, false );
+               $this->assertSame( $module1, $module3 );
+
+               // should not use cached instance if caching is disabled
+               $module4 = $moduleManager->getModule( $name, null, true );
+               $this->assertNotSame( $module1, $module4 );
+       }
+
+       /**
+        * @covers ApiModuleManager::getModule
+        */
+       public function testGetModule_null() {
+               $modules = array(
+                       'login' => 'ApiLogin',
+                       'logout' => 'ApiLogout',
+               );
+
+               $moduleManager = $this->getModuleManager();
+               $moduleManager->addModules( $modules, 'test' );
+
+               $this->assertNull( $moduleManager->getModule( 'quux' ), 'unknown name' );
+               $this->assertNull( $moduleManager->getModule( 'login', 'bla' ), 'wrong group' );
+       }
+
+       /**
+        * @covers ApiModuleManager::getNames
+        */
+       public function testGetNames() {
+               $fooModules = array(
+                       'login' => 'ApiLogin',
+                       'logout' => 'ApiLogout',
+               );
+
+               $barModules = array(
+                       'feedcontributions' => array( 'class' => 'ApiFeedContributions' ),
+                       'feedrecentchanges' => array( 'class' => 'ApiFeedRecentChanges' ),
+               );
+
+               $moduleManager = $this->getModuleManager();
+               $moduleManager->addModules( $fooModules, 'foo' );
+               $moduleManager->addModules( $barModules, 'bar' );
+
+               $fooNames = $moduleManager->getNames( 'foo' );
+               $this->assertArrayEquals( array_keys( $fooModules ), $fooNames );
+
+               $allNames = $moduleManager->getNames();
+               $allModules = array_merge( $fooModules, $barModules );
+               $this->assertArrayEquals( array_keys( $allModules ), $allNames );
+       }
+
+       /**
+        * @covers ApiModuleManager::getNamesWithClasses
+        */
+       public function testGetNamesWithClasses() {
+               $fooModules = array(
+                       'login' => 'ApiLogin',
+                       'logout' => 'ApiLogout',
+               );
+
+               $barModules = array(
+                       'feedcontributions' => array( 'class' => 'ApiFeedContributions' ),
+                       'feedrecentchanges' => array( 'class' => 'ApiFeedRecentChanges' ),
+               );
+
+               $moduleManager = $this->getModuleManager();
+               $moduleManager->addModules( $fooModules, 'foo' );
+               $moduleManager->addModules( $barModules, 'bar' );
+
+               $fooNamesWithClasses = $moduleManager->getNamesWithClasses( 'foo' );
+               $this->assertArrayEquals( $fooModules, $fooNamesWithClasses );
+
+               $allNamesWithClasses = $moduleManager->getNamesWithClasses();
+               $allModules = array_merge( $fooModules, array(
+                       'feedcontributions' => 'ApiFeedContributions',
+                       'feedrecentchanges' => 'ApiFeedRecentChanges',
+               ) );
+               $this->assertArrayEquals( $allModules, $allNamesWithClasses );
+       }
+
+       /**
+        * @covers ApiModuleManager::getModuleGroup
+        */
+       public function testGetModuleGroup() {
+               $fooModules = array(
+                       'login' => 'ApiLogin',
+                       'logout' => 'ApiLogout',
+               );
+
+               $barModules = array(
+                       'feedcontributions' => array( 'class' => 'ApiFeedContributions' ),
+                       'feedrecentchanges' => array( 'class' => 'ApiFeedRecentChanges' ),
+               );
+
+               $moduleManager = $this->getModuleManager();
+               $moduleManager->addModules( $fooModules, 'foo' );
+               $moduleManager->addModules( $barModules, 'bar' );
+
+               $this->assertEquals( 'foo', $moduleManager->getModuleGroup( 'login' ) );
+               $this->assertEquals( 'bar', $moduleManager->getModuleGroup( 'feedrecentchanges' ) );
+               $this->assertNull( $moduleManager->getModuleGroup( 'quux' ) );
+       }
+
+       /**
+        * @covers ApiModuleManager::getGroups
+        */
+       public function testGetGroups() {
+               $fooModules = array(
+                       'login' => 'ApiLogin',
+                       'logout' => 'ApiLogout',
+               );
+
+               $barModules = array(
+                       'feedcontributions' => array( 'class' => 'ApiFeedContributions' ),
+                       'feedrecentchanges' => array( 'class' => 'ApiFeedRecentChanges' ),
+               );
+
+               $moduleManager = $this->getModuleManager();
+               $moduleManager->addModules( $fooModules, 'foo' );
+               $moduleManager->addModules( $barModules, 'bar' );
+
+               $groups = $moduleManager->getGroups();
+               $this->assertArrayEquals( array( 'foo', 'bar' ), $groups );
+       }
+
+       /**
+        * @covers ApiModuleManager::getClassName
+        */
+       public function testGetClassName() {
+               $fooModules = array(
+                       'login' => 'ApiLogin',
+                       'logout' => 'ApiLogout',
+               );
+
+               $barModules = array(
+                       'feedcontributions' => array( 'class' => 'ApiFeedContributions' ),
+                       'feedrecentchanges' => array( 'class' => 'ApiFeedRecentChanges' ),
+               );
+
+               $moduleManager = $this->getModuleManager();
+               $moduleManager->addModules( $fooModules, 'foo' );
+               $moduleManager->addModules( $barModules, 'bar' );
+
+               $this->assertEquals( 'ApiLogin', $moduleManager->getClassName( 'login' ) );
+               $this->assertEquals( 'ApiLogout', $moduleManager->getClassName( 'logout' ) );
+               $this->assertEquals( 'ApiFeedContributions', $moduleManager->getClassName( 'feedcontributions' ) );
+               $this->assertEquals( 'ApiFeedRecentChanges', $moduleManager->getClassName( 'feedrecentchanges' ) );
+               $this->assertFalse( $moduleManager->getClassName( 'nonexistentmodule' ) );
+       }
+
+
+}
diff --git a/tests/phpunit/includes/api/ApiRevisionDeleteTest.php b/tests/phpunit/includes/api/ApiRevisionDeleteTest.php
new file mode 100644 (file)
index 0000000..b03836e
--- /dev/null
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * Tests for action=revisiondelete
+ * @covers APIRevisionDelete
+ * @group API
+ * @group medium
+ * @group Database
+ */
+class ApiRevisionDeleteTest extends ApiTestCase {
+
+       public static $page = 'Help:ApiRevDel_test';
+       public $revs = array();
+
+       protected function setUp() {
+               // Needs to be before setup since this gets cached
+               $this->mergeMwGlobalArrayValue( 'wgGroupPermissions', array( 'sysop' => array( 'deleterevision' => true ) ) );
+               parent::setUp();
+               // Make a few edits for us to play with
+               for ( $i = 1; $i <= 5; $i++ ) {
+                       self::editPage( self::$page, MWCryptRand::generateHex( 10 ), 'summary' );
+                       $this->revs[] = Title::newFromText( self::$page )->getLatestRevID( Title::GAID_FOR_UPDATE );
+               }
+
+       }
+
+       public function testHidingRevisions() {
+               $user = self::$users['sysop']->user;
+               $revid = array_shift( $this->revs );
+               $out = $this->doApiRequest( array(
+                       'action' => 'revisiondelete',
+                       'type' => 'revision',
+                       'target' => self::$page,
+                       'ids' => $revid,
+                       'hide' => 'content|user|comment',
+                       'token' => $user->getEditToken(),
+               ) );
+               // Check the output
+               $out = $out[0]['revisiondelete'];
+               $this->assertEquals( $out['status'], 'Success' );
+               $this->assertArrayHasKey( 'items', $out );
+               $item = $out['items'][0];
+               $this->assertArrayHasKey( 'userhidden', $item );
+               $this->assertArrayHasKey( 'commenthidden', $item );
+               $this->assertArrayHasKey( 'texthidden', $item );
+               $this->assertEquals( $item['id'], $revid );
+
+               // Now check that that revision was actually hidden
+               $rev = Revision::newFromId( $revid );
+               $this->assertEquals( $rev->getContent( Revision::FOR_PUBLIC ), null );
+               $this->assertEquals( $rev->getComment( Revision::FOR_PUBLIC ), '' );
+               $this->assertEquals( $rev->getUser( Revision::FOR_PUBLIC ), 0 );
+
+               // Now test unhiding!
+               $out2 = $this->doApiRequest( array(
+                       'action' => 'revisiondelete',
+                       'type' => 'revision',
+                       'target' => self::$page,
+                       'ids' => $revid,
+                       'show' => 'content|user|comment',
+                       'token' => $user->getEditToken(),
+               ) );
+
+               // Check the output
+               $out2 = $out2[0]['revisiondelete'];
+               $this->assertEquals( $out2['status'], 'Success' );
+               $this->assertArrayHasKey( 'items', $out2 );
+               $item = $out2['items'][0];
+
+               $this->assertArrayNotHasKey( 'userhidden', $item );
+               $this->assertArrayNotHasKey( 'commenthidden', $item );
+               $this->assertArrayNotHasKey( 'texthidden', $item );
+
+               $this->assertEquals( $item['id'], $revid );
+
+               $rev = Revision::newFromId( $revid );
+               $this->assertNotEquals( $rev->getContent( Revision::FOR_PUBLIC ), null );
+               $this->assertNotEquals( $rev->getComment( Revision::FOR_PUBLIC ), '' );
+               $this->assertNotEquals( $rev->getUser( Revision::FOR_PUBLIC ), 0 );
+       }
+
+       public function testUnhidingOutput() {
+               $user = self::$users['sysop']->user;
+               $revid = array_shift( $this->revs );
+               // Hide revisions
+               $this->doApiRequest( array(
+                       'action' => 'revisiondelete',
+                       'type' => 'revision',
+                       'target' => self::$page,
+                       'ids' => $revid,
+                       'hide' => 'content|user|comment',
+                       'token' => $user->getEditToken(),
+               ) );
+
+               $out = $this->doApiRequest( array(
+                       'action' => 'revisiondelete',
+                       'type' => 'revision',
+                       'target' => self::$page,
+                       'ids' => $revid,
+                       'show' => 'comment',
+                       'token' => $user->getEditToken(),
+               ) );
+               $out = $out[0]['revisiondelete'];
+               $this->assertEquals( $out['status'], 'Success' );
+               $this->assertArrayHasKey( 'items', $out );
+               $item = $out['items'][0];
+               // Check it has userhidden & texthidden keys
+               // but no commenthidden key
+               $this->assertArrayHasKey( 'userhidden', $item );
+               $this->assertArrayNotHasKey( 'commenthidden', $item );
+               $this->assertArrayHasKey( 'texthidden', $item );
+               $this->assertEquals( $item['id'], $revid );
+       }
+}
index 87ad2cd..cd14194 100644 (file)
@@ -43,10 +43,10 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
 
        /**
         * Edits or creates a page/revision
-        * @param string $pageName page title
-        * @param string $text content of the page
-        * @param string $summary optional summary string for the revision
-        * @param int $defaultNs optional namespace id
+        * @param string $pageName Page title
+        * @param string $text Content of the page
+        * @param string $summary Optional summary string for the revision
+        * @param int $defaultNs Optional namespace id
         * @return array Array as returned by WikiPage::doEditContent()
         */
        protected function editPage( $pageName, $text, $summary = '', $defaultNs = NS_MAIN ) {
@@ -119,10 +119,10 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
         * requesting a "real" edit token.
         *
         * @param array $params Key-value API params
-        * @param array|null $session session array
+        * @param array|null $session Session array
         * @param User|null $user A User object for the context
-        * @return mixed Result of the API call
-        * @throws Exception in case wsToken is not set in the session
+        * @return array Result of the API call
+        * @throws Exception In case wsToken is not set in the session
         */
        protected function doApiRequestWithToken( array $params, array $session = null,
                User $user = null
@@ -133,7 +133,7 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
                        $session = $wgRequest->getSessionArray();
                }
 
-               if ( $session['wsToken'] ) {
+               if ( isset( $session['wsToken'] ) && $session['wsToken'] ) {
                        // add edit token to fake session
                        $session['wsEditToken'] = $session['wsToken'];
                        // add token to request parameters
@@ -141,7 +141,7 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
 
                        return $this->doApiRequest( $params, $session, false, $user );
                } else {
-                       throw new Exception( "request data not in right format" );
+                       throw new Exception( "Session token not available" );
                }
        }
 
@@ -152,8 +152,8 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
 
                $data = $this->doApiRequest( array(
                        'action' => 'login',
-                       'lgname' => self::$users[ $user ]->username,
-                       'lgpassword' => self::$users[ $user ]->password ) );
+                       'lgname' => self::$users[$user]->username,
+                       'lgpassword' => self::$users[$user]->password ) );
 
                $token = $data[0]['login']['token'];
 
@@ -161,8 +161,8 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
                        array(
                                'action' => 'login',
                                'lgtoken' => $token,
-                               'lgname' => self::$users[ $user ]->username,
-                               'lgpassword' => self::$users[ $user ]->password,
+                               'lgname' => self::$users[$user]->username,
+                               'lgpassword' => self::$users[$user]->password,
                        ),
                        $data[2]
                );
index 40407dc..7e51339 100644 (file)
@@ -30,7 +30,7 @@ abstract class ApiTestCaseUpload extends ApiTestCase {
        /**
         * Helper function -- remove files and associated articles by Title
         *
-        * @param Title $title title to be removed
+        * @param Title $title Title to be removed
         *
         * @return bool
         */
@@ -65,7 +65,7 @@ abstract class ApiTestCaseUpload extends ApiTestCase {
        /**
         * Helper function -- remove files and associated articles with a particular filename
         *
-        * @param string $fileName filename to be removed
+        * @param string $fileName Filename to be removed
         *
         * @return bool
         */
@@ -77,7 +77,7 @@ abstract class ApiTestCaseUpload extends ApiTestCase {
         * Helper function -- given a file on the filesystem, find matching
         * content in the db (and associated articles) and remove them.
         *
-        * @param string $filePath path to file on the filesystem
+        * @param string $filePath Path to file on the filesystem
         *
         * @return bool
         */
@@ -96,10 +96,10 @@ abstract class ApiTestCaseUpload extends ApiTestCase {
         * Fake an upload by dumping the file into temp space, and adding info to $_FILES.
         * (This is what PHP would normally do).
         *
-        * @param string $fieldName name this would have in the upload form
-        * @param string $fileName name to title this
-        * @param string $type mime type
-        * @param string $filePath path where to find file contents
+        * @param string $fieldName Name this would have in the upload form
+        * @param string $fileName Name to title this
+        * @param string $type MIME type
+        * @param string $filePath Path where to find file contents
         *
         * @throws Exception
         * @return bool
index 38beb87..13da33c 100644 (file)
@@ -10,12 +10,15 @@ class PrefixUniquenessTest extends MediaWikiTestCase {
        public function testPrefixes() {
                $main = new ApiMain( new FauxRequest() );
                $query = new ApiQuery( $main, 'foo', 'bar' );
-               $modules = $query->getModuleManager()->getNamesWithClasses();
+               $moduleManager = $query->getModuleManager();
+
+               $modules = $moduleManager->getNames();
                $prefixes = array();
 
-               foreach ( $modules as $name => $class ) {
-                       /** @var ApiQueryBase $module */
-                       $module = new $class( $query, $name );
+               foreach ( $modules as $name ) {
+                       $module = $moduleManager->getModule( $name );
+                       $class = get_class( $module );
+
                        $prefix = $module->getModulePrefix();
                        if ( isset( $prefixes[$prefix] ) ) {
                                $this->fail( "Module prefix '{$prefix}' is shared between {$class} and {$prefixes[$prefix]}" );
index e3eea4c..6374cfa 100644 (file)
@@ -328,7 +328,7 @@ class RandomImageGenerator {
         * This is used when simulating a rotated image capture with Exif orientation
         * @param array $spec Returned by getImageSpec
         * @param array $matrix 2x2 transformation matrix
-        * @return array transformed Spec
+        * @return array Transformed Spec
         */
        private static function rotateImageSpec( &$spec, $matrix ) {
                $tSpec = array();
@@ -365,8 +365,8 @@ class RandomImageGenerator {
        /**
         * Given a matrix and a pair of images, return new position
         * @param array $matrix 2x2 rotation matrix
-        * @param int $x x-coordinate number
-        * @param int $y y-coordinate number
+        * @param int $x The x-coordinate number
+        * @param int $y The y-coordinate number
         * @return array Transformed with properties x, y
         */
        private static function matrixMultiply2x2( $matrix, $x, $y ) {
@@ -432,7 +432,7 @@ class RandomImageGenerator {
         * array( array( 'foo', 'bar' ), array( 'quux', 'baz' ) );
         *
         * @param int $number Number of pairs
-        * @return array two-element arrays
+        * @return array Two-element arrays
         */
        private function getRandomWordPairs( $number ) {
                $lines = $this->getRandomLines( $number * 2 );
@@ -451,7 +451,7 @@ class RandomImageGenerator {
         *
         * Will throw exception if the file could not be read or if it had fewer lines than requested.
         *
-        * @param int $number_desired number of lines desired
+        * @param int $number_desired Number of lines desired
         *
         * @throws Exception
         * @return array Array of exactly n elements, drawn randomly from lines the file
index c71faec..fc1f902 100644 (file)
@@ -14,4 +14,9 @@ class ApiFormatJsonTest extends ApiFormatTestBase {
                $this->assertInternalType( 'array', json_decode( $data, true ) );
                $this->assertGreaterThan( 0, count( (array)$data ) );
        }
+
+       public function testJsonpInjection( ) {
+               $data = $this->apiRequest( 'json', array( 'action' => 'query', 'meta' => 'siteinfo', 'callback' => 'myCallback' ) );
+               $this->assertEquals( '/**/myCallback(', substr( $data, 0, 15 ) );
+       }
 }
diff --git a/tests/phpunit/includes/api/format/ApiFormatNoneTest.php b/tests/phpunit/includes/api/format/ApiFormatNoneTest.php
new file mode 100644 (file)
index 0000000..cabd750
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @group API
+ * @group Database
+ * @group medium
+ * @covers ApiFormatNone
+ */
+class ApiFormatNoneTest extends ApiFormatTestBase {
+
+       public function testValidSyntax( ) {
+               $data = $this->apiRequest( 'none', array( 'action' => 'query', 'meta' => 'siteinfo' ) );
+
+               $this->assertEquals( '', $data ); // No output!
+       }
+}
index d8765ee..bce6268 100644 (file)
@@ -37,8 +37,8 @@ abstract class ApiQueryContinueTestBase extends ApiQueryTestBase {
         * @param array $params Api parameters
         * @param int $expectedCount Max number of iterations
         * @param string $id Unit test id
-        * @param bool $useContinue true to use smart continue
-        * @return mixed Merged results data array
+        * @param bool $continue True to use smart continue
+        * @return array Merged results data array
         */
        protected function checkC( $expected, $params, $expectedCount, $id, $continue = true ) {
                $result = $this->query( $params, $expectedCount, $id, $continue );
@@ -50,8 +50,8 @@ abstract class ApiQueryContinueTestBase extends ApiQueryTestBase {
         * @param array $params Api parameters
         * @param int $expectedCount Max number of iterations
         * @param string $id Unit test id
-        * @param bool $useContinue true to use smart continue
-        * @return mixed Merged results data array
+        * @param bool $useContinue True to use smart continue
+        * @return array Merged results data array
         * @throws Exception
         */
        protected function query( $params, $expectedCount, $id, $useContinue = true ) {
@@ -104,10 +104,7 @@ abstract class ApiQueryContinueTestBase extends ApiQueryTestBase {
                        $this->mergeResult( $result, $data );
                        $count++;
                        if ( empty( $continue ) ) {
-                               // $this->assertEquals( $expectedCount, $count, "$id finished early" );
-                               if ( $expectedCount > $count ) {
-                                       print "***** $id Finished early in $count turns. $expectedCount was expected\n";
-                               }
+                               $this->assertEquals( $expectedCount, $count, "$id finished early" );
 
                                return $result;
                        } elseif ( !$useContinue ) {
index 7b686a3..bba22c7 100644 (file)
@@ -96,7 +96,7 @@ class ApiQueryTest extends ApiTestCase {
         * @param string $titlePart
         * @param int $namespace
         * @param string $expected
-        * @param string $description
+        * @param string $expectException
         * @dataProvider provideTestTitlePartToKey
         */
        function testTitlePartToKey( $titlePart, $namespace, $expected, $expectException ) {
index 1b9c1ce..56c15b2 100644 (file)
@@ -34,7 +34,7 @@ STR;
 
        /**
         * Merges all requests parameter + expected values into one
-        * @param ... list of arrays, each of which contains exactly two
+        * @param array $v,... List of arrays, each of which contains exactly two
         * @return array
         */
        protected function merge( /*...*/ ) {
@@ -52,6 +52,8 @@ STR;
        /**
         * Check that the parameter is a valid two element array,
         * with the first element being API request and the second - expected result
+        * @param array $v
+        * @return array
         */
        private function validateRequestExpectedPair( $v ) {
                $this->assertType( 'array', $v, self::PARAM_ASSERT );
@@ -66,6 +68,8 @@ STR;
 
        /**
         * Recursively merges the expected values in the $item into the $all
+        * @param array &$all
+        * @param array $item
         */
        private function mergeExpected( &$all, $item ) {
                foreach ( $item as $k => $v ) {
diff --git a/tests/phpunit/includes/cache/LocalisationCacheTest.php b/tests/phpunit/includes/cache/LocalisationCacheTest.php
new file mode 100644 (file)
index 0000000..fc06a50
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/**
+ * @group Database
+ * @group Cache
+ * @covers LocalisationCache
+ * @author Niklas Laxström
+ */
+class LocalisationCacheTest extends MediaWikiTestCase {
+       protected function setUp() {
+               global $IP;
+
+               parent::setUp();
+               $this->setMwGlobals( array(
+                       'wgMessagesDirs' => array( "$IP/tests/phpunit/data/localisationcache" ),
+                       'wgExtensionMessagesFiles' => array(),
+                       'wgHooks' => array(),
+               ) );
+       }
+
+       public function testPuralRulesFallback() {
+               $cache = new LocalisationCache( array( 'store' => 'detect' ) );
+
+               $this->assertEquals(
+                       $cache->getItem( 'ar', 'pluralRules' ),
+                       $cache->getItem( 'arz', 'pluralRules' ),
+                       'arz plural rules (undefined) fallback to ar (defined)'
+               );
+
+               $this->assertEquals(
+                       $cache->getItem( 'ar', 'compiledPluralRules' ),
+                       $cache->getItem( 'arz', 'compiledPluralRules' ),
+                       'arz compiled plural rules (undefined) fallback to ar (defined)'
+               );
+
+               $this->assertNotEquals(
+                       $cache->getItem( 'ksh', 'pluralRules' ),
+                       $cache->getItem( 'de', 'pluralRules' ),
+                       'ksh plural rules (defined) dont fallback to de (defined)'
+               );
+
+               $this->assertNotEquals(
+                       $cache->getItem( 'ksh', 'compiledPluralRules' ),
+                       $cache->getItem( 'de', 'compiledPluralRules' ),
+                       'ksh compiled plural rules (defined) dont fallback to de (defined)'
+               );
+       }
+
+       public function testRecacheFallbacks() {
+               $lc = new LocalisationCache( array( 'store' => 'detect' ) );
+               $lc->recache( 'uk' );
+               $this->assertEquals(
+                       array(
+                               'present-uk' => 'uk',
+                               'present-ru' => 'ru',
+                               'present-en' => 'en',
+                       ),
+                       $lc->getItem( 'uk', 'messages' ),
+                       'Fallbacks are only used to fill missing data'
+               );
+       }
+
+       public function testRecacheFallbacksWithHooks() {
+               global $wgHooks;
+
+               // Use hook to provide updates for messages. This is what the
+               // LocalisationUpdate extension does. See bug 68781.
+               $wgHooks['LocalisationCacheRecacheFallback'][] = function (
+                       LocalisationCache $lc,
+                       $code,
+                       array &$cache
+               ) {
+                       if ( $code === 'ru' ) {
+                               $cache['messages']['present-uk'] = 'ru-override';
+                               $cache['messages']['present-ru'] = 'ru-override';
+                               $cache['messages']['present-en'] = 'ru-override';
+                       }
+               };
+
+               $lc = new LocalisationCache( array( 'store' => 'detect' ) );
+               $lc->recache( 'uk' );
+               $this->assertEquals(
+                       array(
+                               'present-uk' => 'uk',
+                               'present-ru' => 'ru-override',
+                               'present-en' => 'ru-override',
+                       ),
+                       $lc->getItem( 'uk', 'messages' ),
+                       'Updates provided by hooks follow the normal fallback order.'
+               );
+       }
+}
index 803acf7..442e9f9 100644 (file)
@@ -59,7 +59,7 @@ class MessageCacheTest extends MediaWikiLangTestCase {
         * Helper function for addDBData -- adds a simple page to the database
         *
         * @param string $title Title of page to be created
-        * @param string $lang  Language and content of the created page
+        * @param string $lang Language and content of the created page
         * @param string|null $content Content of the created page, or null for a generic string
         * @param bool $createSubPage Set to false if a root page should be created
         */
diff --git a/tests/phpunit/includes/cache/RedisBloomCacheTest.php b/tests/phpunit/includes/cache/RedisBloomCacheTest.php
new file mode 100644 (file)
index 0000000..3d491e9
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * Test for BloomCacheRedis class.
+ *
+ * @TODO: some generic base "redis test server conf" for all testing?
+ *
+ * @covers BloomCacheRedis
+ * @group Cache
+ */
+class BloomCacheRedisTest extends MediaWikiTestCase {
+       private static $suffix;
+
+       protected function setUp() {
+               parent::setUp();
+
+               self::$suffix = self::$suffix ? : mt_rand();
+
+               $fcache = BloomCache::get( 'main' );
+               if ( $fcache instanceof BloomCacheRedis ) {
+                       $fcache->delete( "unit-testing-" . self::$suffix );
+               } else {
+                       $this->markTestSkipped( 'The main bloom cache is not redis.' );
+               }
+       }
+
+       public function testBloomCache() {
+               $key = "unit-testing-" . self::$suffix;
+               $fcache = BloomCache::get( 'main' );
+               $count = 1500;
+
+               $this->assertTrue( $fcache->delete( $key ), "OK delete of filter '$key'." );
+               $this->assertTrue( $fcache->init( $key, $count, .001 ), "OK init of filter '$key'." );
+
+               $members = array();
+               for ( $i = 0; $i < $count; ++$i ) {
+                       $members[] = "$i-value-$i";
+               }
+               $this->assertTrue( $fcache->add( $key, $members ), "Addition of members to '$key' OK." );
+
+               for ( $i = 0; $i < $count; ++$i ) {
+                       $this->assertTrue( $fcache->isHit( $key, "$i-value-$i" ), "Hit on member '$i-value-$i'." );
+               }
+
+               $falsePositives = array();
+               for ( $i = $count; $i < 2 * $count; ++$i ) {
+                       if ( $fcache->isHit( $key, "value$i" ) ) {
+                               $falsePositives[] = "value$i";
+                       }
+               }
+
+               $eFalsePositives = array(
+                       'value1763',
+                       'value2245',
+                       'value2353',
+                       'value2791',
+                       'value2898',
+                       'value2975'
+               );
+               $this->assertEquals( $eFalsePositives, $falsePositives, "Correct number of false positives found." );
+       }
+
+       protected function tearDown() {
+               parent::tearDown();
+
+               $fcache = BloomCache::get( 'main' );
+               if ( $fcache instanceof BloomCacheRedis ) {
+                       $fcache->delete( "unit-testing-" . self::$suffix );
+               }
+       }
+}
diff --git a/tests/phpunit/includes/changes/EnhancedChangesListTest.php b/tests/phpunit/includes/changes/EnhancedChangesListTest.php
new file mode 100644 (file)
index 0000000..40a11d2
--- /dev/null
@@ -0,0 +1,132 @@
+<?php
+
+/**
+ * @covers EnhancedChangesList
+ *
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class EnhancedChangesListTest extends MediaWikiLangTestCase {
+
+       /**
+        * @var TestRecentChangesHelper
+        */
+       private $testRecentChangesHelper;
+
+       public function __construct( $name = null, array $data = array(), $dataName = '' ) {
+               parent::__construct( $name, $data, $dataName );
+
+               $this->testRecentChangesHelper = new TestRecentChangesHelper();
+       }
+
+       public function testBeginRecentChangesList_styleModules() {
+               $enhancedChangesList = $this->newEnhancedChangesList();
+               $enhancedChangesList->beginRecentChangesList();
+
+               $styleModules = $enhancedChangesList->getOutput()->getModuleStyles();
+
+               $this->assertContains(
+                       'mediawiki.special.changeslist',
+                       $styleModules,
+                       'has mediawiki.special.changeslist'
+                );
+
+               $this->assertContains(
+                       'mediawiki.special.changeslist.enhanced',
+                       $styleModules,
+                       'has mediawiki.special.changeslist.enhanced'
+               );
+       }
+
+       public function testBeginRecentChangesList_jsModules() {
+               $enhancedChangesList = $this->newEnhancedChangesList();
+               $enhancedChangesList->beginRecentChangesList();
+
+               $modules = $enhancedChangesList->getOutput()->getModules();
+
+               $this->assertContains( 'jquery.makeCollapsible', $modules, 'has jquery.makeCollapsible' );
+               $this->assertContains( 'mediawiki.icon', $modules, 'has mediawiki.icon' );
+       }
+
+       public function testBeginRecentChangesList_html() {
+               $enhancedChangesList = $this->newEnhancedChangesList();
+               $html = $enhancedChangesList->beginRecentChangesList();
+
+               $this->assertEquals( '<div class="mw-changeslist">', $html );
+       }
+
+       /**
+        * @todo more tests
+        */
+       public function testRecentChangesLine() {
+               $enhancedChangesList = $this->newEnhancedChangesList();
+               $enhancedChangesList->beginRecentChangesList();
+
+               $recentChange = $this->getEditChange( '20131103092153' );
+               $html = $enhancedChangesList->recentChangesLine( $recentChange, false );
+
+               $this->assertInternalType( 'string', $html );
+
+               $recentChange2 = $this->getEditChange( '20131103092253' );
+               $html = $enhancedChangesList->recentChangesLine( $recentChange2, false );
+
+               $this->assertEquals( '', $html );
+       }
+
+         /**
+          * @todo more tests for actual formatting, this is more of a smoke test
+          */
+         public function testEndRecentChangesList() {
+               $enhancedChangesList = $this->newEnhancedChangesList();
+               $enhancedChangesList->beginRecentChangesList();
+
+               $recentChange = $this->getEditChange( '20131103092153' );
+               $enhancedChangesList->recentChangesLine( $recentChange, false );
+
+               $recentChange2 = $this->getEditChange( '20131103092253' );
+               $enhancedChangesList->recentChangesLine( $recentChange2, false );
+
+               $html = $enhancedChangesList->endRecentChangesList();
+
+               preg_match_all( '/td class="mw-enhanced-rc-nested"/', $html, $matches );
+               $this->assertCount( 2, $matches[0] );
+         }
+
+       /**
+        * @return EnhancedChangesList
+        */
+       private function newEnhancedChangesList() {
+               $user = User::newFromId( 0 );
+               $context = $this->testRecentChangesHelper->getTestContext( $user );
+
+               return new EnhancedChangesList( $context );
+       }
+
+       /**
+        * @return RecentChange
+        */
+       private function getEditChange( $timestamp ) {
+               $user = $this->getTestUser();
+               $recentChange = $this->testRecentChangesHelper->makeEditRecentChange(
+                       $user, 'Cat', $timestamp, 5, 191, 190, 0, 0
+               );
+
+               return $recentChange;
+       }
+
+       /**
+        * @return User
+        */
+       private function getTestUser() {
+               $user = User::newFromName( 'TestRecentChangesUser' );
+
+               if ( !$user->getId() ) {
+                       $user->addToDatabase();
+               }
+
+               return $user;
+       }
+
+}
diff --git a/tests/phpunit/includes/changes/OldChangesListTest.php b/tests/phpunit/includes/changes/OldChangesListTest.php
new file mode 100644 (file)
index 0000000..3a36b9f
--- /dev/null
@@ -0,0 +1,191 @@
+<?php
+
+/**
+ * @covers OldChangesList
+ *
+ * @todo add tests to cover article link, timestamp, character difference,
+ *       log entry, user tool links, direction marks, tags, rollback,
+ *       watching users, and date header.
+ *
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class OldChangesListTest extends MediaWikiLangTestCase {
+
+       /**
+        * @var TestRecentChangesHelper
+        */
+       private $testRecentChangesHelper;
+
+       public function __construct( $name = null, array $data = array(), $dataName = '' ) {
+               parent::__construct( $name, $data, $dataName );
+
+               $this->testRecentChangesHelper = new TestRecentChangesHelper();
+       }
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       'wgArticlePath' => '/wiki/$1'
+               ) );
+       }
+
+       /**
+        * @dataProvider recentChangesLine_CssForLineNumberProvider
+        */
+       public function testRecentChangesLine_CssForLineNumber( $expected, $linenumber, $message ) {
+               $oldChangesList = $this->getOldChangesList();
+               $recentChange = $this->getEditChange();
+
+               $line = $oldChangesList->recentChangesLine( $recentChange, false, $linenumber );
+
+               $this->assertRegExp( $expected, $line, $message );
+       }
+
+       public function recentChangesLine_CssForLineNumberProvider() {
+               return array(
+                       array( '/mw-line-odd/', 1, 'odd line number' ),
+                       array( '/mw-line-even/', 2, 'even line number' )
+               );
+       }
+
+       public function testRecentChangesLine_NotWatchedCssClass() {
+               $oldChangesList = $this->getOldChangesList();
+               $recentChange = $this->getEditChange();
+
+               $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
+
+               $this->assertRegExp( '/mw-changeslist-line-not-watched/', $line );
+       }
+
+       public function testRecentChangesLine_WatchedCssClass() {
+               $oldChangesList = $this->getOldChangesList();
+               $recentChange = $this->getEditChange();
+
+               $line = $oldChangesList->recentChangesLine( $recentChange, true, 1 );
+
+               $this->assertRegExp( '/mw-changeslist-line-watched/', $line );
+       }
+
+       public function testRecentChangesLine_LogTitle() {
+               $oldChangesList = $this->getOldChangesList();
+               $recentChange = $this->getLogChange( 'delete', 'delete' );
+
+               $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
+
+               $message = new Message( 'dellogpage' );
+               $expectedLinkText = $message->inLanguage( 'en' )->text();
+
+               $this->assertRegExp( '/href="\/wiki\/Special:Log\/delete/', $line, 'link has href attribute' );
+               $this->assertRegExp( '/title="Special:Log\/delete/', $line, 'link has title attribute' );
+               $this->assertRegExp( "/$expectedLinkText/", $line, 'link text' );
+       }
+
+       public function testRecentChangesLine_DiffHistLinks() {
+               $oldChangesList = $this->getOldChangesList();
+               $recentChange = $this->getEditChange();
+
+               $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
+
+               $this->assertRegExp(
+                       '/title=Cat&amp;curid=20131103212153&amp;diff=5&amp;oldid=191/',
+                       $line,
+                       'assert diff link'
+               );
+
+               $this->assertRegExp( '/tabindex="0"/', $line, 'assert tab index' );
+               $this->assertRegExp(
+                       '/title=Cat&amp;curid=20131103212153&amp;action=history"/',
+                       $line,
+                       'assert history link'
+               );
+       }
+
+       public function testRecentChangesLine_Flags() {
+               $oldChangesList = $this->getOldChangesList();
+               $recentChange = $this->getNewBotEditChange();
+
+               $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
+
+               $this->assertRegExp(
+                       "/<abbr class='newpage' title='This edit created a new page'>N<\/abbr>/",
+                       $line,
+                       'new page flag'
+               );
+
+               $this->assertRegExp(
+                       "/<abbr class='botedit' title='This edit was performed by a bot'>b<\/abbr>/",
+                       $line,
+                       'bot flag'
+               );
+       }
+
+       public function testRecentChangesLine_Tags() {
+               $recentChange = $this->getEditChange();
+               $recentChange->mAttribs['ts_tags'] = 'vandalism,newbie';
+
+               $oldChangesList = $this->getOldChangesList();
+               $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
+
+               $this->assertRegExp( '/<li class="[\w\s-]*mw-tag-vandalism[\w\s-]*">/', $line );
+               $this->assertRegExp( '/<li class="[\w\s-]*mw-tag-newbie[\w\s-]*">/', $line );
+       }
+
+       private function getNewBotEditChange() {
+               $user = $this->getTestUser();
+
+               $recentChange = $this->testRecentChangesHelper->makeNewBotEditRecentChange(
+                       $user, 'Abc', '20131103212153', 5, 191, 190, 0, 0
+               );
+
+               return $recentChange;
+       }
+
+       private function getLogChange( $logType, $logAction ) {
+               $user = $this->getTestUser();
+
+               $recentChange = $this->testRecentChangesHelper->makeLogRecentChange(
+                       $logType, $logAction, $user, 'Abc', '20131103212153', 0, 0
+               );
+
+               return $recentChange;
+       }
+
+       private function getEditChange() {
+               $user = $this->getTestUser();
+               $recentChange = $this->testRecentChangesHelper->makeEditRecentChange(
+                       $user, 'Cat', '20131103212153', 5, 191, 190, 0, 0
+               );
+
+               return $recentChange;
+       }
+
+       private function getOldChangesList() {
+               $context = $this->getContext();
+               return new OldChangesList( $context );
+       }
+
+       private function getTestUser() {
+               $user = User::newFromName( 'TestRecentChangesUser' );
+
+               if ( !$user->getId() ) {
+                       $user->addToDatabase();
+               }
+
+               return $user;
+       }
+
+       private function getContext() {
+               $user = $this->getTestUser();
+               $context = $this->testRecentChangesHelper->getTestContext( $user );
+
+               $title = Title::newFromText( 'RecentChanges', NS_SPECIAL );
+               $context->setTitle( $title );
+
+               return $context;
+       }
+
+}
index d47cafe..ee1a4d0 100644 (file)
@@ -9,6 +9,18 @@
  * @author Katie Filbert < aude.wiki@gmail.com >
  */
 class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
+
+       /**
+        * @var TestRecentChangesHelper
+        */
+       private $testRecentChangesHelper;
+
+       public function __construct( $name = null, array $data = array(), $dataName = '' ) {
+               parent::__construct( $name, $data, $dataName );
+
+               $this->testRecentChangesHelper = new TestRecentChangesHelper();
+       }
+
        protected function setUp() {
                parent::setUp();
 
@@ -36,7 +48,7 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
                );
                $this->assertEquals( $expected['unpatrolled'], $cacheEntry->unpatrolled, 'unpatrolled' );
 
-               $this->assertUserLinks( 'Mary', $cacheEntry );
+               $this->assertUserLinks( 'TestRecentChangesUser', $cacheEntry );
                $this->assertTitleLink( 'Xyz', $cacheEntry );
 
                $this->assertQueryLink( 'cur', $expected['cur'], $cacheEntry->curlink, 'cur link' );
@@ -49,7 +61,7 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
                        array(
                                array(
                                        'title' => 'Xyz',
-                                       'user' => 'Mary',
+                                       'user' => 'TestRecentChangesUser',
                                        'diff' => array( 'curid' => 5, 'diff' => 191, 'oldid' => 190 ),
                                        'cur' => array( 'curid' => 5, 'diff' => 0, 'oldid' => 191 ),
                                        'timestamp' => '21:21',
@@ -58,9 +70,9 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
                                ),
                                $this->getContext(),
                                $this->getMessages(),
-                               $this->makeEditRecentChange(
-                                       'Xyz',
+                               $this->testRecentChangesHelper->makeEditRecentChange(
                                        $this->getTestUser(),
+                                       'Xyz',
                                        5, // curid
                                        191, // thisid
                                        190, // lastid
@@ -68,28 +80,9 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
                                        0, // counter
                                        0 // number of watching users
                                ),
-                               false,
-                               'edit'
-                       )
-               );
-       }
-
-       private function makeEditRecentChange( $title, $user, $curid, $thisid, $lastid,
-               $timestamp, $counter, $watchingUsers
-       ) {
-
-               $attribs = array_merge(
-                       $this->getDefaultAttributes( $title, $timestamp ),
-                       array(
-                               'rc_user' => $user->getId(),
-                               'rc_user_text' => $user->getName(),
-                               'rc_this_oldid' => $thisid,
-                               'rc_last_oldid' => $lastid,
-                               'rc_cur_id' => $curid
+                               false
                        )
                );
-
-               return $this->makeRecentChange( $attribs, $counter, $watchingUsers );
        }
 
        /**
@@ -110,7 +103,7 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
                $this->assertEquals( $expected['unpatrolled'], $cacheEntry->unpatrolled, 'unpatrolled' );
 
                $this->assertDeleteLogLink( $cacheEntry );
-               $this->assertUserLinks( 'Mary', $cacheEntry );
+               $this->assertUserLinks( 'TestRecentChangesUser', $cacheEntry );
 
                $this->assertEquals( 'cur', $cacheEntry->curlink, 'cur link for delete log or rev' );
                $this->assertEquals( 'diff', $cacheEntry->difflink, 'diff link for delete log or rev' );
@@ -122,45 +115,25 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
                        array(
                                array(
                                        'title' => 'Abc',
-                                       'user' => 'Mary',
+                                       'user' => 'TestRecentChangesUser',
                                        'timestamp' => '21:21',
                                        'numberofWatchingusers' => 0,
                                        'unpatrolled' => false
                                ),
                                $this->getContext(),
                                $this->getMessages(),
-                               $this->makeLogRecentChange(
-                                       'Abc',
+                               $this->testRecentChangesHelper->makeLogRecentChange(
+                                       'delete',
+                                       'delete',
                                        $this->getTestUser(),
+                                       'Abc',
                                        '20131103212153',
                                        0, // counter
                                        0 // number of watching users
                                ),
-                               false,
-                               'delete'
-                       )
-               );
-       }
-
-       private function makeLogRecentChange( $title, $user, $timestamp, $counter, $watchingUsers ) {
-               $attribs = array_merge(
-                       $this->getDefaultAttributes( $title, $timestamp ),
-                       array(
-                               'rc_cur_id' => 0,
-                               'rc_user' => $user->getId(),
-                               'rc_user_text' => $user->getName(),
-                               'rc_this_oldid' => 0,
-                               'rc_last_oldid' => 0,
-                               'rc_old_len' => null,
-                               'rc_new_len' => null,
-                               'rc_type' => 3,
-                               'rc_logid' => 25,
-                               'rc_log_type' => 'delete',
-                               'rc_log_action' => 'delete'
+                               false
                        )
                );
-
-               return $this->makeRecentChange( $attribs, $counter, $watchingUsers );
        }
 
        /**
@@ -195,7 +168,7 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
                        array(
                                array(
                                        'title' => 'Zzz',
-                                       'user' => 'Mary',
+                                       'user' => 'TestRecentChangesUser',
                                        'diff' => '',
                                        'cur' => '',
                                        'timestamp' => '21:21',
@@ -204,9 +177,9 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
                                ),
                                $this->getContext(),
                                $this->getMessages(),
-                               $this->makeDeletedEditRecentChange(
-                                       'Zzz',
+                               $this->testRecentChangesHelper->makeDeletedEditRecentChange(
                                        $this->getTestUser(),
+                                       'Zzz',
                                        '20131103212153',
                                        191, // thisid
                                        190, // lastid
@@ -214,28 +187,9 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
                                        0, // counter
                                        0 // number of watching users
                                ),
-                               false,
-                               'deletedrevuser'
-                       )
-               );
-       }
-
-       private function makeDeletedEditRecentChange( $title, $user, $timestamp, $curid, $thisid,
-               $lastid, $counter, $watchingUsers
-       ) {
-               $attribs = array_merge(
-                       $this->getDefaultAttributes( $title, $timestamp ),
-                       array(
-                               'rc_user' => $user->getId(),
-                               'rc_user_text' => $user->getName(),
-                               'rc_deleted' => 5,
-                               'rc_cur_id' => $curid,
-                               'rc_this_oldid' => $thisid,
-                               'rc_last_oldid' => $lastid
+                               false
                        )
                );
-
-               return $this->makeRecentChange( $attribs, $counter, $watchingUsers );
        }
 
        private function assertUserLinks( $user, $cacheEntry ) {
@@ -341,50 +295,6 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
                }
        }
 
-       private function makeRecentChange( $attribs, $counter, $watchingUsers ) {
-               $change = new RecentChange();
-               $change->setAttribs( $attribs );
-               $change->counter = $counter;
-               $change->numberofWatchingusers = $watchingUsers;
-
-               return $change;
-       }
-
-       private function getDefaultAttributes( $title, $timestamp ) {
-               return array(
-                       'rc_id' => 545,
-                       'rc_user' => 0,
-                       'rc_user_text' => '127.0.0.1',
-                       'rc_ip' => '127.0.0.1',
-                       'rc_title' => $title,
-                       'rc_namespace' => 0,
-                       'rc_timestamp' => $timestamp,
-                       'rc_old_len' => 212,
-                       'rc_new_len' => 188,
-                       'rc_comment' => '',
-                       'rc_minor' => 0,
-                       'rc_bot' => 0,
-                       'rc_type' => 0,
-                       'rc_patrolled' => 1,
-                       'rc_deleted' => 0,
-                       'rc_logid' => 0,
-                       'rc_log_type' => null,
-                       'rc_log_action' => '',
-                       'rc_params' => '',
-                       'rc_source' => 'mw.edit'
-               );
-       }
-
-       private function getTestUser() {
-               $user = User::newFromName( 'Mary' );
-
-               if ( !$user->getId() ) {
-                       $user->addToDatabase();
-               }
-
-               return $user;
-       }
-
        private function getMessages() {
                return array(
                        'cur' => 'cur',
@@ -399,15 +309,22 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
                );
        }
 
-       private function getContext() {
-               $title = Title::newFromText( 'RecentChanges', NS_SPECIAL );
+       private function getTestUser() {
+               $user = User::newFromName( 'TestRecentChangesUser' );
 
-               $context = new RequestContext();
-               $context->setTitle( $title );
-               $context->setLanguage( Language::factory( 'en' ) );
+               if ( !$user->getId() ) {
+                       $user->addToDatabase();
+               }
+
+               return $user;
+       }
 
+       private function getContext() {
                $user = $this->getTestUser();
-               $context->setUser( $user );
+               $context = $this->testRecentChangesHelper->getTestContext( $user );
+
+               $title = Title::newFromText( 'RecentChanges', NS_SPECIAL );
+               $context->setTitle( $title );
 
                return $context;
        }
diff --git a/tests/phpunit/includes/changes/TestRecentChangesHelper.php b/tests/phpunit/includes/changes/TestRecentChangesHelper.php
new file mode 100644 (file)
index 0000000..0da0775
--- /dev/null
@@ -0,0 +1,134 @@
+<?php
+
+/**
+ * Helper for generating test recent changes entries.
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class TestRecentChangesHelper {
+
+       public function makeEditRecentChange( User $user, $titleText, $curid, $thisid, $lastid,
+               $timestamp, $counter, $watchingUsers
+       ) {
+
+               $attribs = array_merge(
+                       $this->getDefaultAttributes( $titleText, $timestamp ),
+                       array(
+                               'rc_user' => $user->getId(),
+                               'rc_user_text' => $user->getName(),
+                               'rc_this_oldid' => $thisid,
+                               'rc_last_oldid' => $lastid,
+                               'rc_cur_id' => $curid
+                       )
+               );
+
+               return $this->makeRecentChange( $attribs, $counter, $watchingUsers );
+       }
+
+       public function makeLogRecentChange( $logType, $logAction, User $user, $titleText, $timestamp, $counter,
+               $watchingUsers
+       ) {
+               $attribs = array_merge(
+                       $this->getDefaultAttributes( $titleText, $timestamp ),
+                       array(
+                               'rc_cur_id' => 0,
+                               'rc_user' => $user->getId(),
+                               'rc_user_text' => $user->getName(),
+                               'rc_this_oldid' => 0,
+                               'rc_last_oldid' => 0,
+                               'rc_old_len' => null,
+                               'rc_new_len' => null,
+                               'rc_type' => 3,
+                               'rc_logid' => 25,
+                               'rc_log_type' => $logType,
+                               'rc_log_action' => $logAction,
+                               'rc_source' => 'mw.log'
+                       )
+               );
+
+               return $this->makeRecentChange( $attribs, $counter, $watchingUsers );
+       }
+
+       public function makeDeletedEditRecentChange( User $user, $titleText, $timestamp, $curid,
+               $thisid, $lastid, $counter, $watchingUsers
+       ) {
+               $attribs = array_merge(
+                       $this->getDefaultAttributes( $titleText, $timestamp ),
+                       array(
+                               'rc_user' => $user->getId(),
+                               'rc_user_text' => $user->getName(),
+                               'rc_deleted' => 5,
+                               'rc_cur_id' => $curid,
+                               'rc_this_oldid' => $thisid,
+                               'rc_last_oldid' => $lastid
+                       )
+               );
+
+               return $this->makeRecentChange( $attribs, $counter, $watchingUsers );
+       }
+
+       public function makeNewBotEditRecentChange( User $user, $titleText, $curid, $thisid, $lastid,
+               $timestamp, $counter, $watchingUsers
+       ) {
+
+               $attribs = array_merge(
+                       $this->getDefaultAttributes( $titleText, $timestamp ),
+                       array(
+                               'rc_user' => $user->getId(),
+                               'rc_user_text' => $user->getName(),
+                               'rc_this_oldid' => $thisid,
+                               'rc_last_oldid' => $lastid,
+                               'rc_cur_id' => $curid,
+                               'rc_type' => 1,
+                               'rc_bot' => 1,
+                               'rc_source' => 'mw.new'
+                       )
+               );
+
+               return $this->makeRecentChange( $attribs, $counter, $watchingUsers );
+       }
+
+       private function makeRecentChange( $attribs, $counter, $watchingUsers ) {
+               $change = new RecentChange();
+               $change->setAttribs( $attribs );
+               $change->counter = $counter;
+               $change->numberofWatchingusers = $watchingUsers;
+
+               return $change;
+       }
+
+       private function getDefaultAttributes( $titleText, $timestamp ) {
+               return array(
+                       'rc_id' => 545,
+                       'rc_user' => 0,
+                       'rc_user_text' => '127.0.0.1',
+                       'rc_ip' => '127.0.0.1',
+                       'rc_title' => $titleText,
+                       'rc_namespace' => 0,
+                       'rc_timestamp' => $timestamp,
+                       'rc_old_len' => 212,
+                       'rc_new_len' => 188,
+                       'rc_comment' => '',
+                       'rc_minor' => 0,
+                       'rc_bot' => 0,
+                       'rc_type' => 0,
+                       'rc_patrolled' => 1,
+                       'rc_deleted' => 0,
+                       'rc_logid' => 0,
+                       'rc_log_type' => null,
+                       'rc_log_action' => '',
+                       'rc_params' => '',
+                       'rc_source' => 'mw.edit'
+               );
+       }
+
+       public function getTestContext( User $user ) {
+               $context = new RequestContext();
+               $context->setLanguage( Language::factory( 'en' ) );
+
+               $context->setUser( $user );
+
+               return $context;
+       }
+}
index 0a6bf72..3902858 100644 (file)
@@ -2,13 +2,19 @@
 
 class ConfigFactoryTest extends MediaWikiTestCase {
 
+       public function tearDown() {
+               // Reset this since we mess with it a bit
+               ConfigFactory::destroyDefaultInstance();
+               parent::tearDown();
+       }
+
        /**
         * @covers ConfigFactory::register
         */
        public function testRegister() {
                $factory = new ConfigFactory();
                $factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
-               $this->assertTrue( True ); // No exception thrown
+               $this->assertTrue( true ); // No exception thrown
                $this->setExpectedException( 'InvalidArgumentException' );
                $factory->register( 'invalid', 'Invalid callback' );
        }
@@ -37,10 +43,28 @@ class ConfigFactoryTest extends MediaWikiTestCase {
         */
        public function testMakeConfigWithInvalidCallback() {
                $factory = new ConfigFactory();
-               $factory->register( 'unittest', function() {
+               $factory->register( 'unittest', function () {
                        return true; // Not a Config object
-               });
+               } );
                $this->setExpectedException( 'UnexpectedValueException' );
                $factory->makeConfig( 'unittest' );
        }
+
+       /**
+        * @covers ConfigFactory::getDefaultInstance
+        */
+       public function testGetDefaultInstance() {
+               // Set $wgConfigRegistry, and check the default
+               // instance read from it
+               $this->setMwGlobals( 'wgConfigRegistry', array(
+                       'conf1' => 'GlobalVarConfig::newInstance',
+                       'conf2' => 'GlobalVarConfig::newInstance',
+               ) );
+               ConfigFactory::destroyDefaultInstance();
+               $factory = ConfigFactory::getDefaultInstance();
+               $this->assertInstanceOf( 'Config', $factory->makeConfig( 'conf1' ) );
+               $this->assertInstanceOf( 'Config', $factory->makeConfig( 'conf2' ) );
+               $this->setExpectedException( 'ConfigException' );
+               $factory->makeConfig( 'conf3' );
+       }
 }
index 7080b02..b15ffa7 100644 (file)
@@ -2,6 +2,42 @@
 
 class GlobalVarConfigTest extends MediaWikiTestCase {
 
+       /**
+        * @covers GlobalVarConfig::newInstance
+        */
+       public function testNewInstance() {
+               $config = GlobalVarConfig::newInstance();
+               $this->assertInstanceOf( 'GlobalVarConfig', $config );
+               $this->maybeStashGlobal( 'wgBaz' );
+               $GLOBALS['wgBaz'] = 'somevalue';
+               // Check prefix is set to 'wg'
+               $this->assertEquals( 'somevalue', $config->get( 'Baz' ) );
+       }
+
+       /**
+        * @covers GlobalVarConfig::__construct
+        * @dataProvider provideConstructor
+        */
+       public function testConstructor( $prefix ) {
+               $var = $prefix . 'GlobalVarConfigTest';
+               $rand = wfRandomString();
+               $this->maybeStashGlobal( $var );
+               $GLOBALS[$var] = $rand;
+               $config = new GlobalVarConfig( $prefix );
+               $this->assertInstanceOf( 'GlobalVarConfig', $config );
+               $this->assertEquals( $rand, $config->get( 'GlobalVarConfigTest' ) );
+       }
+
+       public static function provideConstructor() {
+               return array(
+                       array( 'wg' ),
+                       array( 'ef' ),
+                       array( 'smw' ),
+                       array( 'blahblahblahblah' ),
+                       array( '' ),
+               );
+       }
+
        public function provideGet() {
                $set = array(
                        'wgSomething' => 'default1',
@@ -19,6 +55,7 @@ class GlobalVarConfigTest extends MediaWikiTestCase {
                        array( 'Foo', 'wg', 'default2' ),
                        array( 'Variable', 'ef', 'default3' ),
                        array( 'BAR', '', 'default4' ),
+                       array( 'ThisGlobalWasNotSetAbove', 'wg', false )
                );
        }
 
@@ -28,9 +65,44 @@ class GlobalVarConfigTest extends MediaWikiTestCase {
         * @param string $expected
         * @dataProvider provideGet
         * @covers GlobalVarConfig::get
+        * @covers GlobalVarConfig::getWithPrefix
         */
        public function testGet( $name, $prefix, $expected ) {
                $config = new GlobalVarConfig( $prefix );
+               if ( $expected === false ) {
+                       $this->setExpectedException( 'ConfigException', 'GlobalVarConfig::getWithPrefix: undefined variable:' );
+               }
                $this->assertEquals( $config->get( $name ), $expected );
        }
+
+       public static function provideSet() {
+               return array(
+                       array( 'Foo', 'wg', 'wgFoo' ),
+                       array( 'SomethingRandom', 'wg', 'wgSomethingRandom' ),
+                       array( 'FromAnExtension', 'eg', 'egFromAnExtension' ),
+                       array( 'NoPrefixHere', '', 'NoPrefixHere' ),
+               );
+       }
+
+       private function maybeStashGlobal( $var ) {
+               if ( array_key_exists( $var, $GLOBALS ) ) {
+                       // Will be reset after this test is over
+                       $this->stashMwGlobals( $var );
+               }
+       }
+
+       /**
+        * @dataProvider provideSet
+        * @covers GlobalVarConfig::set
+        * @covers GlobalVarConfig::setWithPrefix
+        */
+       public function testSet( $name, $prefix, $var ) {
+               $this->hideDeprecated( 'GlobalVarConfig::set' );
+               $this->maybeStashGlobal( $var );
+               $config = new GlobalVarConfig( $prefix );
+               $random = wfRandomString();
+               $config->set( $name, $random );
+               $this->assertArrayHasKey( $var, $GLOBALS );
+               $this->assertEquals( $random, $GLOBALS[$var] );
+       }
 }
index 2add9f2..f744973 100644 (file)
@@ -312,6 +312,23 @@ class ContentHandlerTest extends MediaWikiTestCase {
                }
        }
 
+       /*
+        * Test if we become a "Created blank page" summary from getAutoSummary if no Content added to
+        * page.
+        */
+       public function testGetAutosummary() {
+               $content = new DummyContentHandlerForTesting( CONTENT_MODEL_WIKITEXT );
+               $title = Title::newFromText( 'Help:Test' );
+               // Create a new content object with no content
+               $newContent = ContentHandler::makeContent( '', $title, null, null, CONTENT_MODEL_WIKITEXT );
+               // first check, if we become a blank page created summary with the right bitmask
+               $autoSummary = $content->getAutosummary( null, $newContent, 97 );
+               $this->assertEquals( $autoSummary, 'Created blank page' );
+               // now check, what we become with another bitmask
+               $autoSummary = $content->getAutosummary( null, $newContent, 92 );
+               $this->assertEquals( $autoSummary, '' );
+       }
+
        /*
        public function testSupportsSections() {
                $this->markTestIncomplete( "not yet implemented" );
@@ -431,7 +448,7 @@ class DummyContentForTesting extends AbstractContent {
         * Returns native represenation of the data. Interpretation depends on the data model used,
         * as given by getDataModel().
         *
-        * @return mixed the native representation of the content. Could be a string, a nested array
+        * @return mixed The native representation of the content. Could be a string, a nested array
         *  structure, an object, a binary blob... anything, really.
         */
        public function getNativeData() {
@@ -459,7 +476,7 @@ class DummyContentForTesting extends AbstractContent {
         * return $this. That is,  $copy === $original may be true, but only for imutable content
         * objects.
         *
-        * @return Content. A copy of this object.
+        * @return Content A copy of this object
         */
        public function copy() {
                return $this;
@@ -469,7 +486,7 @@ class DummyContentForTesting extends AbstractContent {
         * Returns true if this content is countable as a "real" wiki page, provided
         * that it's also in a countable location (e.g. a current revision in the main namespace).
         *
-        * @param bool $hasLinks if it is known whether this content contains links,
+        * @param bool $hasLinks If it is known whether this content contains links,
         * provide this information here, to avoid redundant parsing to find out.
         * @return bool
         */
@@ -481,7 +498,7 @@ class DummyContentForTesting extends AbstractContent {
         * @param Title $title
         * @param int $revId Unused.
         * @param null|ParserOptions $options
-        * @param bool $generateHtml whether to generate Html (default: true). If false, the result
+        * @param bool $generateHtml Whether to generate Html (default: true). If false, the result
         *  of calling getText() on the ParserOutput object returned by this method is undefined.
         *
         * @return ParserOutput
@@ -497,7 +514,7 @@ class DummyContentForTesting extends AbstractContent {
         *
         * @param Title $title Context title for parsing
         * @param int|null $revId Revision ID (for {{REVISIONID}})
-        * @param ParserOptions|null $options Parser options
+        * @param ParserOptions $options Parser options
         * @param bool $generateHtml Whether or not to generate HTML
         * @param ParserOutput &$output The output object to fill (reference).
         */
diff --git a/tests/phpunit/includes/content/JsonContentTest.php b/tests/phpunit/includes/content/JsonContentTest.php
new file mode 100644 (file)
index 0000000..6c77d1a
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * @author Adam Shorland
+ * @covers JsonContent
+ */
+class JsonContentTest extends MediaWikiLangTestCase {
+
+       /**
+        * @dataProvider provideValidConstruction
+        */
+       public function testValidConstruct( $text, $modelId, $isValid, $expected ) {
+               $obj = new JsonContent( $text, $modelId );
+               $this->assertEquals( $isValid, $obj->isValid() );
+               $this->assertEquals( $expected, $obj->getJsonData() );
+       }
+
+       public function provideValidConstruction() {
+               return array(
+                       array( 'foo', CONTENT_MODEL_JSON, false, null ),
+                       array( FormatJson::encode( array() ), CONTENT_MODEL_JSON, true, array() ),
+                       array( FormatJson::encode( array( 'foo' ) ), CONTENT_MODEL_JSON, true, array( 'foo' ) ),
+               );
+       }
+
+       /**
+        * @dataProvider provideDataToEncode
+        */
+       public function testBeautifyUsesFormatJson( $data ) {
+               $obj = new JsonContent( FormatJson::encode( $data ) );
+               $this->assertEquals( FormatJson::encode( $data, true ), $obj->beautifyJSON() );
+       }
+
+       public function provideDataToEncode() {
+               return array(
+                       array( array() ),
+                       array( array( 'foo' ) ),
+                       array( array( 'foo', 'bar' ) ),
+                       array( array( 'baz' => 'foo', 'bar' ) ),
+                       array( array( 'baz' => 1000, 'bar' ) ),
+               );
+       }
+
+       /**
+        * @dataProvider provideDataToEncode
+        */
+       public function testPreSaveTransform( $data ) {
+               $obj = new JsonContent( FormatJson::encode( $data ) );
+               $newObj = $obj->preSaveTransform( $this->getMockTitle(), $this->getMockUser(), $this->getMockParserOptions() );
+               $this->assertTrue( $newObj->equals( new JsonContent( FormatJson::encode( $data, true ) ) ) );
+       }
+
+       private function getMockTitle() {
+               return $this->getMockBuilder( 'Title' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+       }
+
+       private function getMockUser() {
+               return $this->getMockBuilder( 'User' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+       }
+       private function getMockParserOptions() {
+               return $this->getMockBuilder( 'ParserOptions' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+       }
+
+       /**
+        * @dataProvider provideDataAndParserText
+        */
+       public function testFillParserOutput( $data, $expected ) {
+               $obj = new JsonContent( FormatJson::encode( $data ) );
+               $parserOutput = $obj->getParserOutput( $this->getMockTitle(), null, null, true );
+               $this->assertInstanceOf( 'ParserOutput', $parserOutput );
+//             var_dump( $parserOutput->getText(), "\n" );
+               $this->assertEquals( $expected, $parserOutput->getText() );
+       }
+
+       public function provideDataAndParserText() {
+               return array(
+                       array(
+                               array(),
+                               '<table class="mw-json"><tbody></tbody></table>'
+                       ),
+                       array(
+                               array( 'foo' ),
+                               '<table class="mw-json"><tbody><tr><th>0</th><td class="value">&quot;foo&quot;</td></tr></tbody></table>'
+                       ),
+                       array(
+                               array( 'foo', 'bar' ),
+                               '<table class="mw-json"><tbody><tr><th>0</th><td class="value">&quot;foo&quot;</td></tr>' .
+                               "\n" .
+                               '<tr><th>1</th><td class="value">&quot;bar&quot;</td></tr></tbody></table>'
+                       ),
+                       array(
+                               array( 'baz' => 'foo', 'bar' ),
+                               '<table class="mw-json"><tbody><tr><th>baz</th><td class="value">&quot;foo&quot;</td></tr>' .
+                               "\n" .
+                               '<tr><th>0</th><td class="value">&quot;bar&quot;</td></tr></tbody></table>'
+                       ),
+                       array(
+                               array( 'baz' => 1000, 'bar' ),
+                               '<table class="mw-json"><tbody><tr><th>baz</th><td class="value">1000</td></tr>' .
+                               "\n" .
+                               '<tr><th>0</th><td class="value">&quot;bar&quot;</td></tr></tbody></table>'
+                       ),
+                       array(
+                               array( '<script>alert("evil!")</script>'),
+                               '<table class="mw-json"><tbody><tr><th>0</th><td class="value">&quot;&lt;script&gt;alert(&quot;evil!&quot;)&lt;/script&gt;&quot;</td></tr></tbody></table>',
+                       ),
+               );
+       }
+}
index 88bf7d9..98b4ca0 100644 (file)
@@ -162,6 +162,9 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
                $this->assertEquals( "DROP INDEX foo -- dropping index",
                        $this->replaceVars( "DROP INDEX /*i*/foo ON /*_*/bar -- dropping index" )
                );
+               $this->assertEquals( "INSERT OR IGNORE INTO foo VALUES ('bar')",
+                       $this->replaceVars( "INSERT OR IGNORE INTO foo VALUES ('bar')" )
+               );
        }
 
        /**
@@ -440,12 +443,12 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
 
                $databaseCreation = $db->query( 'CREATE TABLE a ( a_1 )', __METHOD__ );
                $this->assertInstanceOf( 'ResultWrapper', $databaseCreation, "Failed to create table a" );
-               $res = $db->select( 'a' , '*');
-               $this->assertEquals( 0,  $db->numFields($res), "expects to get 0 fields for an empty table" );
+               $res = $db->select( 'a', '*' );
+               $this->assertEquals( 0, $db->numFields( $res ), "expects to get 0 fields for an empty table" );
                $insertion = $db->insert( 'a', array( 'a_1' => 10 ), __METHOD__ );
                $this->assertTrue( $insertion, "Insertion failed" );
-               $res = $db->select( 'a' , '*');
-               $this->assertEquals( 1,  $db->numFields($res), "wrong number of fields" );
+               $res = $db->select( 'a', '*' );
+               $this->assertEquals( 1, $db->numFields( $res ), "wrong number of fields" );
 
                $this->assertTrue( $db->close(), "closing database" );
        }
index 39c311f..0c0b390 100644 (file)
@@ -136,7 +136,7 @@ class DatabaseTestHelper extends DatabaseBase {
                return false;
        }
 
-       function indexInfo( $table, $index, $fname = 'Database::indexInfo' ) {
+       function indexInfo( $table, $index, $fname = 'DatabaseBase::indexInfo' ) {
                return false;
        }
 
index 4ff6165..447bf21 100644 (file)
@@ -115,7 +115,7 @@ abstract class ORMRowTest extends \MediaWikiTestCase {
 
        /**
         * @since 1.20
-        * @return array of IORMRow
+        * @return array Array of IORMRow
         */
        public function instanceProvider() {
                $instances = array();
index e642177..6e41de7 100644 (file)
@@ -103,11 +103,11 @@ class MWDebugTest extends MediaWikiTestCase {
                $this->assertInstanceOf( 'ApiResult', $result );
                $data = $result->getData();
 
-               $expectedKeys = array( 'mwVersion', 'phpVersion', 'gitRevision', 'gitBranch',
+               $expectedKeys = array( 'mwVersion', 'phpEngine', 'phpVersion', 'gitRevision', 'gitBranch',
                        'gitViewUrl', 'time', 'log', 'debugLog', 'queries', 'request', 'memory',
                        'memoryPeak', 'includes', 'profile', '_element' );
 
-               foreach( $expectedKeys as $expectedKey ) {
+               foreach ( $expectedKeys as $expectedKey ) {
                        $this->assertArrayHasKey( $expectedKey, $data['debuginfo'], "debuginfo has $expectedKey" );
                }
 
diff --git a/tests/phpunit/includes/deferred/DeferredUpdatesTest.php b/tests/phpunit/includes/deferred/DeferredUpdatesTest.php
new file mode 100644 (file)
index 0000000..5348c85
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+class DeferredUpdatesTest extends MediaWikiTestCase {
+
+       public function testDoUpdates() {
+               $updates = array(
+                       '1' => 'deferred update 1',
+                       '2' => 'deferred update 2',
+                       '3' => 'deferred update 3',
+                       '2-1' => 'deferred update 1 within deferred update 2',
+               );
+               DeferredUpdates::addCallableUpdate(
+                       function () use ( $updates ) {
+                               echo $updates['1'];
+                       }
+               );
+               DeferredUpdates::addCallableUpdate(
+                       function () use ( $updates ) {
+                               echo $updates['2'];
+                               DeferredUpdates::addCallableUpdate(
+                                       function () use ( $updates ) {
+                                               echo $updates['2-1'];
+                                       }
+                               );
+                       }
+               );
+               DeferredUpdates::addCallableUpdate(
+                       function () use ( $updates ) {
+                               echo $updates[3];
+                       }
+               );
+
+               $this->expectOutputString( implode( '', $updates ) );
+
+               DeferredUpdates::doUpdates();
+       }
+
+}
index e914c72..188ad3f 100644 (file)
@@ -44,7 +44,7 @@ class ArrayDiffFormatterTest extends MediaWikiTestCase {
                        $diffOp->expects( $this->any() )
                                ->method( 'getClosing' )
                                ->with( $this->isType( 'integer' ) )
-                               ->will( $this->returnCallback( function() {
+                               ->will( $this->returnCallback( function () {
                                        return 'mockLine';
                                } ) );
                } else {
index e1a69e3..5474b96 100644 (file)
@@ -39,7 +39,7 @@ class DifferenceEngineTest extends MediaWikiTestCase {
        }
 
        /**
-        * @return int[] revision ids
+        * @return int[] Revision ids
         */
        protected function doEdits() {
                $title = $this->getTitle();
index 2eb1c46..dc5dc6a 100644 (file)
@@ -27,7 +27,7 @@ class MWExceptionHandlerTest extends MediaWikiTestCase {
                $hasObject = false;
                $hasArray = false;
                foreach ( $trace as $frame ) {
-                       if ( ! isset( $frame['args'] ) ) {
+                       if ( !isset( $frame['args'] ) ) {
                                continue;
                        }
                        foreach ( $frame['args'] as $arg ) {
@@ -49,7 +49,7 @@ class MWExceptionHandlerTest extends MediaWikiTestCase {
                $redacted = MWExceptionHandler::getRedactedTrace( $e );
 
                foreach ( $redacted as $frame ) {
-                       if ( ! isset( $frame['args'] ) ) {
+                       if ( !isset( $frame['args'] ) ) {
                                continue;
                        }
                        foreach ( $frame['args'] as $arg ) {
index a7bfbfe..9558cc7 100644 (file)
@@ -21,11 +21,11 @@ class FileBackendTest extends MediaWikiTestCase {
                parent::setUp();
                $uniqueId = time() . '-' . mt_rand();
                $tmpPrefix = wfTempDir() . '/filebackend-unittest-' . $uniqueId;
-               if ( $this->getCliArg( 'use-filebackend=' ) ) {
+               if ( $this->getCliArg( 'use-filebackend' ) ) {
                        if ( self::$backendToUse ) {
                                $this->singleBackend = self::$backendToUse;
                        } else {
-                               $name = $this->getCliArg( 'use-filebackend=' );
+                               $name = $this->getCliArg( 'use-filebackend' );
                                $useConfig = array();
                                foreach ( $wgFileBackends as $conf ) {
                                        if ( $conf['name'] == $name ) {
index 2c52338..5bdb7e7 100644 (file)
@@ -2,7 +2,7 @@
 class RepoGroupTest extends MediaWikiTestCase {
 
        function testHasForeignRepoNegative() {
-               $this->setMWGlobals( 'wgForeignFileRepos', array() );
+               $this->setMwGlobals( 'wgForeignFileRepos', array() );
                RepoGroup::destroySingleton();
                FileBackendGroup::destroySingleton();
                $this->assertFalse( RepoGroup::singleton()->hasForeignRepos() );
@@ -17,21 +17,23 @@ class RepoGroupTest extends MediaWikiTestCase {
                $this->setUpForeignRepo();
                $fakeCallback = $this->getMock( 'RepoGroupTestHelper' );
                $fakeCallback->expects( $this->once() )->method( 'callback' );
-               RepoGroup::singleton()->forEachForeignRepo( array( $fakeCallback, 'callback' ), array( array() ) );
+               RepoGroup::singleton()->forEachForeignRepo(
+                       array( $fakeCallback, 'callback' ), array( array() ) );
        }
 
        function testForEachForeignRepoNone() {
-               $this->setMWGlobals( 'wgForeignFileRepos', array() );
+               $this->setMwGlobals( 'wgForeignFileRepos', array() );
                RepoGroup::destroySingleton();
                FileBackendGroup::destroySingleton();
                $fakeCallback = $this->getMock( 'RepoGroupTestHelper' );
                $fakeCallback->expects( $this->never() )->method( 'callback' );
-               RepoGroup::singleton()->forEachForeignRepo( array( $fakeCallback, 'callback' ), array( array() ) );
+               RepoGroup::singleton()->forEachForeignRepo(
+                       array( $fakeCallback, 'callback' ), array( array() ) );
        }
 
        private function setUpForeignRepo() {
                global $wgUploadDirectory;
-               $this->setMWGlobals( 'wgForeignFileRepos', array( array(
+               $this->setMwGlobals( 'wgForeignFileRepos', array( array(
                        'class' => 'ForeignAPIRepo',
                        'name' => 'wikimediacommons',
                        'backend' => 'wikimediacommons-backend',
index a79866e..9cc2efb 100644 (file)
@@ -17,8 +17,8 @@ class StoreBatchTest extends MediaWikiTestCase {
 
                # Forge a FSRepo object to not have to rely on local wiki settings
                $tmpPrefix = wfTempDir() . '/storebatch-test-' . time() . '-' . mt_rand();
-               if ( $this->getCliArg( 'use-filebackend=' ) ) {
-                       $name = $this->getCliArg( 'use-filebackend=' );
+               if ( $this->getCliArg( 'use-filebackend' ) ) {
+                       $name = $this->getCliArg( 'use-filebackend' );
                        $useConfig = array();
                        foreach ( $wgFileBackends as $conf ) {
                                if ( $conf['name'] == $name ) {
index 9232ce4..8e8b8a9 100644 (file)
@@ -1,6 +1,34 @@
 <?php
 
-class FileRepoFileTest extends MediaWikiMediaTestCase {
+class FileTest extends MediaWikiMediaTestCase {
+
+       /**
+        * @param string $filename
+        * @param bool $expected
+        * @dataProvider providerCanAnimate
+        */
+       function testCanAnimateThumbIfAppropriate( $filename, $expected ) {
+               $this->setMwGlobals( 'wgMaxAnimatedGifArea', 9000 );
+               $file = $this->dataFile( $filename );
+               $this->assertEquals( $file->canAnimateThumbIfAppropriate(), $expected );
+       }
+
+       function providerCanAnimate() {
+               return array(
+                       array( 'nonanimated.gif', true ),
+                       array( 'jpeg-comment-utf.jpg', true ),
+                       array( 'test.tiff', true ),
+                       array( 'Animated_PNG_example_bouncing_beach_ball.png', false ),
+                       array( 'greyscale-png.png', true ),
+                       array( 'Toll_Texas_1.svg', true ),
+                       array( 'LoremIpsum.djvu', true ),
+                       array( '80x60-2layers.xcf', true ),
+                       array( 'Soccer_ball_animated.svg', false ),
+                       array( 'Bishzilla_blink.gif', false ),
+                       array( 'animated.gif', true ),
+               );
+       }
+
        /**
         * @dataProvider getThumbnailBucketProvider
         * @covers File::getThumbnailBucket
@@ -14,8 +42,9 @@ class FileRepoFileTest extends MediaWikiMediaTestCase {
                        ->setMethods( array( 'getWidth' ) )
                        ->getMockForAbstractClass();
 
-               $fileMock->expects( $this->any() )->method( 'getWidth' )->will(
-                       $this->returnValue( $data['width'] ) );
+               $fileMock->expects( $this->any() )
+                       ->method( 'getWidth' )
+                       ->will( $this->returnValue( $data['width'] ) );
 
                $this->assertEquals(
                        $data['expectedBucket'],
@@ -118,29 +147,35 @@ class FileRepoFileTest extends MediaWikiMediaTestCase {
 
                $fsFile = new FSFile( 'fsFilePath' );
 
-               $repoMock->expects( $this->any() )->method( 'fileExists' )->will(
-                       $this->returnValue( true ) );
+               $repoMock->expects( $this->any() )
+                       ->method( 'fileExists' )
+                       ->will( $this->returnValue( true ) );
 
-               $repoMock->expects( $this->any() )->method( 'getLocalReference' )->will(
-                       $this->returnValue( $fsFile ) );
+               $repoMock->expects( $this->any() )
+                       ->method( 'getLocalReference' )
+                       ->will( $this->returnValue( $fsFile ) );
 
                $handlerMock = $this->getMock( 'BitmapHandler', array( 'supportsBucketing' ) );
-               $handlerMock->expects( $this->any() )->method( 'supportsBucketing' )->will(
-                       $this->returnValue( $data['supportsBucketing'] ) );
+               $handlerMock->expects( $this->any() )
+                       ->method( 'supportsBucketing' )
+                       ->will( $this->returnValue( $data['supportsBucketing'] ) );
 
                $fileMock = $this->getMockBuilder( 'File' )
                        ->setConstructorArgs( array( 'fileMock', $repoMock ) )
                        ->setMethods( array( 'getThumbnailBucket', 'getLocalRefPath', 'getHandler' ) )
                        ->getMockForAbstractClass();
 
-               $fileMock->expects( $this->any() )->method( 'getThumbnailBucket' )->will(
-                       $this->returnValue( $data['thumbnailBucket'] ) );
+               $fileMock->expects( $this->any() )
+                       ->method( 'getThumbnailBucket' )
+                       ->will( $this->returnValue( $data['thumbnailBucket'] ) );
 
-               $fileMock->expects( $this->any() )->method( 'getLocalRefPath' )->will(
-                       $this->returnValue( 'localRefPath' ) );
+               $fileMock->expects( $this->any() )
+                       ->method( 'getLocalRefPath' )
+                       ->will( $this->returnValue( 'localRefPath' ) );
 
-               $fileMock->expects( $this->any() )->method( 'getHandler' )->will(
-                       $this->returnValue( $handlerMock ) );
+               $fileMock->expects( $this->any() )
+                       ->method( 'getHandler' )
+                       ->will( $this->returnValue( $handlerMock ) );
 
                $reflection = new ReflectionClass( $fileMock );
                $reflection_property = $reflection->getProperty( 'handler' );
@@ -222,15 +257,18 @@ class FileRepoFileTest extends MediaWikiMediaTestCase {
 
                $fileMock = $this->getMockBuilder( 'File' )
                        ->setConstructorArgs( array( 'fileMock', $repoMock ) )
-                       ->setMethods( array( 'getWidth', 'getBucketThumbPath', 'makeTransformTmpFile', 'generateAndSaveThumb', 'getHandler' ) )
+                       ->setMethods( array( 'getWidth', 'getBucketThumbPath', 'makeTransformTmpFile',
+                               'generateAndSaveThumb', 'getHandler' ) )
                        ->getMockForAbstractClass();
 
                $handlerMock = $this->getMock( 'JpegHandler', array( 'supportsBucketing' ) );
-               $handlerMock->expects( $this->any() )->method( 'supportsBucketing' )->will(
-                       $this->returnValue( true ) );
+               $handlerMock->expects( $this->any() )
+                       ->method( 'supportsBucketing' )
+                       ->will( $this->returnValue( true ) );
 
-               $fileMock->expects( $this->any() )->method( 'getHandler' )->will(
-                       $this->returnValue( $handlerMock ) );
+               $fileMock->expects( $this->any() )
+                       ->method( 'getHandler' )
+                       ->will( $this->returnValue( $handlerMock ) );
 
                $reflectionMethod = new ReflectionMethod( 'File', 'generateBucketsIfNeeded' );
                $reflectionMethod->setAccessible( true );
diff --git a/tests/phpunit/includes/filerepo/files/FileTest.php b/tests/phpunit/includes/filerepo/files/FileTest.php
deleted file mode 100644 (file)
index 36b95ea..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-class FileTest extends MediaWikiMediaTestCase {
-
-       function setUp() {
-               $this->setMWGlobals( 'wgMaxAnimatedGifArea', 9000 );
-               parent::setUp();
-       }
-
-       /**
-        * @param $filename String
-        * @param $expected boolean
-        * @dataProvider providerCanAnimate
-        */
-       function testCanAnimateThumbIfAppropriate( $filename, $expected ) {
-               $file = $this->dataFile( $filename );
-               $this->assertEquals( $file->canAnimateThumbIfAppropriate(), $expected );
-       }
-
-       function providerCanAnimate() {
-               return array(
-                       array( 'nonanimated.gif', true ),
-                       array( 'jpeg-comment-utf.jpg', true ),
-                       array( 'test.tiff', true ),
-                       array( 'Animated_PNG_example_bouncing_beach_ball.png', false ),
-                       array( 'greyscale-png.png', true ),
-                       array( 'Toll_Texas_1.svg', true ),
-                       array( 'LoremIpsum.djvu', true ),
-                       array( '80x60-2layers.xcf', true ),
-                       array( 'Soccer_ball_animated.svg', false ),
-                       array( 'Bishzilla_blink.gif', false ),
-                       array( 'animated.gif', true ),
-               );
-       }
-}
diff --git a/tests/phpunit/includes/htmlform/HTMLAutoCompleteSelectFieldTest.php b/tests/phpunit/includes/htmlform/HTMLAutoCompleteSelectFieldTest.php
new file mode 100644 (file)
index 0000000..2c7f50c
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Unit tests for HTMLAutoCompleteSelectField
+ *
+ * @covers HTMLAutoCompleteSelectField
+ */
+class HtmlAutoCompleteSelectFieldTest extends MediaWikiTestCase {
+
+       var $options = array(
+               'Bulgaria'     => 'BGR',
+               'Burkina Faso' => 'BFA',
+               'Burundi'      => 'BDI',
+       );
+
+       /**
+        * Verify that attempting to instantiate an HTMLAutoCompleteSelectField
+        * without providing any autocomplete options causes an exception to be
+        * thrown.
+        *
+        * @expectedException        MWException
+        * @expectedExceptionMessage called without any autocompletions
+        */
+       function testMissingAutocompletions() {
+               new HTMLAutoCompleteSelectField( array( 'fieldname' => 'Test' ) );
+       }
+
+       /**
+        * Verify that the autocomplete options are correctly encoded as
+        * the 'data-autocomplete' attribute of the field.
+        *
+        * @covers HTMLAutoCompleteSelectField::getAttributes
+        */
+       function testGetAttributes() {
+               $field = new HTMLAutoCompleteSelectField( array(
+                       'fieldname'    => 'Test',
+                       'autocomplete' => $this->options,
+               ) );
+
+               $attributes = $field->getAttributes( array() );
+               $this->assertEquals( array_keys( $this->options ),
+                       FormatJson::decode( $attributes['data-autocomplete'] ),
+                       "The 'data-autocomplete' attribute encodes autocomplete option keys as a JSON array."
+               );
+       }
+
+       /**
+        * Test that the optional select dropdown is included or excluded based on
+        * the presence or absence of the 'options' parameter.
+        */
+       function testOptionalSelectElement() {
+               $params = array(
+                       'fieldname'    => 'Test',
+                       'autocomplete' => $this->options,
+                       'options'      => $this->options,
+               );
+
+               $field = new HTMLAutoCompleteSelectField( $params );
+               $html = $field->getInputHTML( false );
+               $this->assertRegExp( '/select/', $html,
+                       "When the 'options' parameter is set, the HTML includes a <select>" );
+
+               unset( $params['options'] );
+               $field = new HTMLAutoCompleteSelectField( $params );
+               $html = $field->getInputHTML( false );
+               $this->assertNotRegExp( '/select/', $html,
+                       "When the 'options' parameter is not set, the HTML does not include a <select>" );
+       }
+}
index 70374dc..69e4006 100644 (file)
@@ -21,8 +21,8 @@ class JobQueueTest extends MediaWikiTestCase {
 
                $this->setMwGlobals( 'wgMemc', new HashBagOStuff() );
 
-               if ( $this->getCliArg( 'use-jobqueue=' ) ) {
-                       $name = $this->getCliArg( 'use-jobqueue=' );
+               if ( $this->getCliArg( 'use-jobqueue' ) ) {
+                       $name = $this->getCliArg( 'use-jobqueue' );
                        if ( !isset( $wgJobTypeConf[$name] ) ) {
                                throw new MWException( "No \$wgJobTypeConf entry for '$name'." );
                        }
index c8b20d2..e4283b0 100644 (file)
@@ -15,15 +15,27 @@ class CSSJanusTest extends MediaWikiTestCase {
 
                if ( $cssB ) {
                        $transformedA = CSSJanus::transform( $cssA );
-                       $this->assertEquals( $transformedA, $cssB, 'Test A-B transformation' );
+                       $this->assertEquals(
+                               $transformedA,
+                               str_replace( '/* @noflip */ ', '', $cssB ),
+                               'Test A-B transformation'
+                       );
 
                        $transformedB = CSSJanus::transform( $cssB );
-                       $this->assertEquals( $transformedB, $cssA, 'Test B-A transformation' );
+                       $this->assertEquals(
+                               $transformedB,
+                               str_replace( '/* @noflip */ ', '', $cssA ),
+                               'Test B-A transformation'
+                       );
                } else {
                        // If no B version is provided, it means
-                       // the output should equal the input.
+                       // the output should equal the input (modulo @noflip annotations).
                        $transformedA = CSSJanus::transform( $cssA );
-                       $this->assertEquals( $transformedA, $cssA, 'Nothing was flipped' );
+                       $this->assertEquals(
+                               $transformedA,
+                               str_replace( '/* @noflip */ ', '', $cssA ),
+                               'Nothing was flipped'
+                       );
                }
        }
 
@@ -221,6 +233,11 @@ class CSSJanusTest extends MediaWikiTestCase {
                                // Don't mangle zeroes
                                '.foo { text-shadow: orange 0 2px; }'
                        ),
+                       array(
+                               // Make sure floats are not considered zero
+                               '.foo { box-shadow: inset .5em 0 0 white; }',
+                               '.foo { box-shadow: inset -.5em 0 0 white; }',
+                       ),
 
                        // Direction
                        // Note: This differs from the Python implementation,
index b99ef86..334d5b5 100644 (file)
@@ -14,7 +14,7 @@ class MWMessagePackTest extends MediaWikiTestCase {
         * serialization function.
         */
        public function provider() {
-               return array(
+               $tests = array(
                        array( 'nil', null, 'c0' ),
                        array( 'bool', true, 'c3' ),
                        array( 'bool', false, 'c2' ),
@@ -25,16 +25,12 @@ class MWMessagePackTest extends MediaWikiTestCase {
                        array( 'uint 8', 128, 'cc80' ),
                        array( 'uint 16', 1000, 'cd03e8' ),
                        array( 'uint 32', 100000, 'ce000186a0' ),
-                       array( 'uint 64', 10000000000, 'cf00000002540be400' ),
                        array( 'negative fixnum', -1, 'ff' ),
                        array( 'negative fixnum', -2, 'fe' ),
                        array( 'int 8', -128, 'd080' ),
                        array( 'int 8', -35, 'd0dd' ),
                        array( 'int 16', -1000, 'd1fc18' ),
                        array( 'int 32', -100000, 'd2fffe7960' ),
-                       array( 'int 64', -10000000000, 'd3fffffffdabf41c00' ),
-                       array( 'int 64', -223372036854775807, 'd3fce66c50e2840001' ),
-                       array( 'int 64', -9223372036854775807, 'd38000000000000001' ),
                        array( 'double', 0.1, 'cb3fb999999999999a' ),
                        array( 'double', 1.1, 'cb3ff199999999999a' ),
                        array( 'double', 123.456, 'cb405edd2f1a9fbe77' ),
@@ -56,6 +52,15 @@ class MWMessagePackTest extends MediaWikiTestCase {
                                '82a36f6e6501a374776f02'
                        ),
                );
+
+               if ( PHP_INT_SIZE > 4 ) {
+                       $tests[] = array( 'uint 64', 10000000000, 'cf00000002540be400' );
+                       $tests[] = array( 'int 64', -10000000000, 'd3fffffffdabf41c00' );
+                       $tests[] = array( 'int 64', -223372036854775807, 'd3fce66c50e2840001' );
+                       $tests[] = array( 'int 64', -9223372036854775807, 'd38000000000000001' );
+               }
+
+               return $tests;
        }
 
        /**
@@ -65,6 +70,6 @@ class MWMessagePackTest extends MediaWikiTestCase {
         */
        public function testPack( $type, $value, $expected ) {
                $actual = bin2hex( MWMessagePack::pack( $value ) );
-               $this->assertEquals( $actual, $expected, $type );
+               $this->assertEquals( $expected, $actual, $type );
        }
 }
diff --git a/tests/phpunit/includes/mail/MailAddressTest.php b/tests/phpunit/includes/mail/MailAddressTest.php
new file mode 100644 (file)
index 0000000..2d07812
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+
+class MailAddressTest extends MediaWikiTestCase {
+
+       /**
+        * @covers MailAddress::__construct
+        */
+       public function testConstructor() {
+               $ma = new MailAddress( 'foo@bar.baz', 'UserName', 'Real name' );
+               $this->assertInstanceOf( 'MailAddress', $ma );
+       }
+
+       /**
+        * @covers MailAddress::newFromUser
+        */
+       public function testNewFromUser() {
+               $user = $this->getMock( 'User' );
+               $user->expects( $this->any() )->method( 'getName' )->will( $this->returnValue( 'UserName' ) );
+               $user->expects( $this->any() )->method( 'getEmail' )->will( $this->returnValue( 'foo@bar.baz' ) );
+               $user->expects( $this->any() )->method( 'getRealName' )->will( $this->returnValue( 'Real name' ) );
+
+               $ma = MailAddress::newFromUser( $user );
+               $this->assertInstanceOf( 'MailAddress', $ma );
+               $this->setMwGlobals( 'wgEnotifUseRealName', true );
+               $this->assertEquals( 'Real name <foo@bar.baz>', $ma->toString() );
+               $this->setMwGlobals( 'wgEnotifUseRealName', false );
+               $this->assertEquals( 'UserName <foo@bar.baz>', $ma->toString() );
+       }
+
+       /**
+        * @covers MailAddress::toString
+        * @dataProvider provideToString
+        */
+       public function testToString( $useRealName, $address, $name, $realName, $expected ) {
+               if ( wfIsWindows() ) {
+                       $this->markTestSkipped( 'This test only works on non-Windows platforms' );
+               }
+               $this->setMwGlobals( 'wgEnotifUseRealName', $useRealName );
+               $ma = new MailAddress( $address, $name, $realName );
+               $this->assertEquals( $expected, $ma->toString() );
+       }
+
+       public static function provideToString() {
+               return array(
+                       array( true, 'foo@bar.baz', 'FooBar', 'Foo Bar', 'Foo Bar <foo@bar.baz>' ),
+                       array( true, 'foo@bar.baz', 'UserName', null, 'UserName <foo@bar.baz>' ),
+                       array( true, 'foo@bar.baz', 'AUser', 'My real name', 'My real name <foo@bar.baz>' ),
+                       array( true, 'foo@bar.baz', 'A.user.name', 'my@real.name', '"my@real.name" <foo@bar.baz>' ),
+                       array( false, 'foo@bar.baz', 'AUserName', 'Some real name', 'AUserName <foo@bar.baz>' ),
+                       array( false, 'foo@bar.baz', '', '', 'foo@bar.baz' ),
+                       array( true, 'foo@bar.baz', '', '', 'foo@bar.baz' ),
+               );
+       }
+
+       /**
+        * @covers MailAddress::__toString
+        */
+       public function test__ToString() {
+               $ma = new MailAddress( 'some@email.com', 'UserName', 'A real name' );
+               $this->assertEquals( $ma->toString(), (string)$ma );
+       }
+
+}
\ No newline at end of file
diff --git a/tests/phpunit/includes/mail/UserMailerTest.php b/tests/phpunit/includes/mail/UserMailerTest.php
new file mode 100644 (file)
index 0000000..dca8aeb
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+
+class UserMailerTest extends MediaWikiLangTestCase {
+
+       /**
+        * @covers UserMailer::quotedPrintable
+        */
+       public function testQuotedPrintable() {
+               $this->assertEquals(
+                       "=?UTF-8?Q?=C4=88u=20legebla=3F?=",
+                       UserMailer::quotedPrintable( "\xc4\x88u legebla?", "UTF-8" ) );
+       }
+
+}
index 8402522..c720d7b 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+
+/**
+ * @group Media
+ */
 class BitmapMetadataHandlerTest extends MediaWikiTestCase {
 
        protected function setUp() {
index 9395b66..1972c96 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+/**
+ * @group Media
+ */
 class BitmapScalingTest extends MediaWikiTestCase {
 
        protected function setUp() {
index 76cefe5..c0871f1 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 /**
+ * @group Media
  * @covers DjVuHandler
  */
 class DjVuTest extends MediaWikiMediaTestCase {
@@ -34,8 +35,8 @@ class DjVuTest extends MediaWikiMediaTestCase {
        public function testInvalidFile() {
                $this->assertEquals(
                        'a:1:{s:5:"error";s:25:"Error extracting metadata";}',
-                       $this->handler->getMetadata( null, $this->filePath . '/README' ),
-                       'Getting Metadata for an inexistent file should returns false'
+                       $this->handler->getMetadata( null, $this->filePath . '/some-nonexistent-file' ),
+                       'Getting metadata for an inexistent file should return false'
                );
        }
 
@@ -61,7 +62,7 @@ class DjVuTest extends MediaWikiMediaTestCase {
                $file = $this->dataFile( 'LoremIpsum.djvu', 'image/x.djvu' );
                $this->assertEquals(
                        "Lorem ipsum \n1 \n",
-                       (string) $this->handler->getPageText( $file, 1 ),
+                       (string)$this->handler->getPageText( $file, 1 ),
                        "Text layer of page 1 of file LoremIpsum.djvu should be 'Lorem ipsum \n1 \n'"
                );
        }
index 44b2070..41330f4 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+/**
+ * @group Media
+ */
 class ExifBitmapTest extends MediaWikiTestCase {
 
        /**
index 6a1e422..f0bd42a 100644 (file)
@@ -2,6 +2,7 @@
 /**
  * Tests related to auto rotation.
  *
+ * @group Media
  * @group medium
  *
  * @todo covers tags
@@ -31,7 +32,7 @@ class ExifRotationTest extends MediaWikiMediaTestCase {
         * @dataProvider provideFiles
         */
        public function testMetadata( $name, $type, $info ) {
-               if ( !BitmapHandler::canRotate() ) {
+               if ( !$this->handler->canRotate() ) {
                        $this->markTestSkipped( "This test needs a rasterizer that can auto-rotate." );
                }
                $file = $this->dataFile( $name, $type );
@@ -39,12 +40,29 @@ class ExifRotationTest extends MediaWikiMediaTestCase {
                $this->assertEquals( $info['height'], $file->getHeight(), "$name: height check" );
        }
 
+       /**
+        * Same as before, but with auto-rotation set to auto.
+        *
+        * This sets scaler to image magick, which we should detect as
+        * supporting rotation.
+        * @dataProvider provideFiles
+        */
+       public function testMetadataAutoRotate( $name, $type, $info ) {
+               $this->setMwGlobals( 'wgEnableAutoRotation', null );
+               $this->setMwGlobals( 'wgUseImageMagick', true );
+               $this->setMwGlobals( 'wgUseImageResize', true );
+
+               $file = $this->dataFile( $name, $type );
+               $this->assertEquals( $info['width'], $file->getWidth(), "$name: width check" );
+               $this->assertEquals( $info['height'], $file->getHeight(), "$name: height check" );
+       }
+
        /**
         *
         * @dataProvider provideFiles
         */
        public function testRotationRendering( $name, $type, $info, $thumbs ) {
-               if ( !BitmapHandler::canRotate() ) {
+               if ( !$this->handler->canRotate() ) {
                        $this->markTestSkipped( "This test needs a rasterizer that can auto-rotate." );
                }
                foreach ( $thumbs as $size => $out ) {
@@ -132,6 +150,19 @@ class ExifRotationTest extends MediaWikiMediaTestCase {
                $this->assertEquals( $info['height'], $file->getHeight(), "$name: height check" );
        }
 
+       /**
+        * Same as before, but with auto-rotation set to auto and an image scaler that doesn't support it.
+        * @dataProvider provideFilesNoAutoRotate
+        */
+       public function testMetadataAutoRotateUnsupported( $name, $type, $info ) {
+               $this->setMwGlobals( 'wgEnableAutoRotation', null );
+               $this->setMwGlobals( 'wgUseImageResize', false );
+
+               $file = $this->dataFile( $name, $type );
+               $this->assertEquals( $info['width'], $file->getWidth(), "$name: width check" );
+               $this->assertEquals( $info['height'], $file->getHeight(), "$name: height check" );
+       }
+
        /**
         *
         * @dataProvider provideFilesNoAutoRotate
index 735663c..f3c05fb 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 
 /**
+ * @group Media
  * @covers Exif
  */
 class ExifTest extends MediaWikiTestCase {
index 7bc785e..4b8f213 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+/**
+ * @group Media
+ */
 class FakeDimensionFile extends File {
        public $mustRender = false;
 
index daaefc0..002e2cb 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+/**
+ * @group Media
+ */
 class FormatMetadataTest extends MediaWikiMediaTestCase {
 
        protected function setUp() {
index 3491112..6aecd8b 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+
+/**
+ * @group Media
+ */
 class GIFMetadataExtractorTest extends MediaWikiTestCase {
 
        protected function setUp() {
index 17b2964..52a51cc 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+
+/**
+ * @group Media
+ */
 class GIFHandlerTest extends MediaWikiMediaTestCase {
 
        /** @var GIFHandler */
index b556a75..06542cf 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+/**
+ * @group Media
+ */
 class IPTCTest extends MediaWikiTestCase {
 
        /**
index b10f55c..7c977d5 100644 (file)
@@ -6,6 +6,7 @@
  * but it costs money). The implementation of it currently in MediaWiki is based
  * solely on reading the standard, without any real world test files.
  *
+ * @group Media
  * @covers JpegMetadataExtractor
  */
 class JpegMetadataExtractorTest extends MediaWikiTestCase {
@@ -22,7 +23,7 @@ class JpegMetadataExtractorTest extends MediaWikiTestCase {
         * We also use this test to test padding bytes don't
         * screw stuff up
         *
-        * @param string $file filename
+        * @param string $file Filename
         *
         * @dataProvider provideUtf8Comment
         */
index c856b1c..2436e7d 100644 (file)
@@ -1,5 +1,7 @@
 <?php
+
 /**
+ * @group Media
  * @covers JpegHandler
  */
 class JpegTest extends MediaWikiMediaTestCase {
index c28898b..d8cfcc4 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+/**
+ * @group Media
+ */
 class MediaHandlerTest extends MediaWikiTestCase {
 
        /**
index 7b64dfd..8f28158 100644 (file)
@@ -33,7 +33,7 @@ abstract class MediaWikiMediaTestCase extends MediaWikiTestCase {
        }
 
        /**
-        * @return Array Argument for FSRepo constructor
+        * @return array Argument for FSRepo constructor
         */
        protected function getRepoOptions() {
                return array(
@@ -47,7 +47,7 @@ abstract class MediaWikiMediaTestCase extends MediaWikiTestCase {
         * The result of this method will set the file path to use,
         * as well as the protected member $filePath
         *
-        * @return String path where files are
+        * @return string Path where files are
         */
        protected function getFilePath() {
                return __DIR__ . '/../../data/media/';
@@ -59,7 +59,7 @@ abstract class MediaWikiMediaTestCase extends MediaWikiTestCase {
         *
         * Override this method if your test case creates thumbnails
         *
-        * @return boolean
+        * @return bool
         */
        protected function createsThumbnails() {
                return false;
@@ -69,8 +69,8 @@ abstract class MediaWikiMediaTestCase extends MediaWikiTestCase {
         * Utility function: Get a new file object for a file on disk but not actually in db.
         *
         * File must be in the path returned by getFilePath()
-        * @param $name String File name
-        * @param $type String MIME type [optional]
+        * @param string $name File name
+        * @param string $type MIME type [optional]
         * @return UnregisteredLocalFile
         */
        protected function dataFile( $name, $type = null ) {
@@ -78,7 +78,7 @@ abstract class MediaWikiMediaTestCase extends MediaWikiTestCase {
                        // Autodetect by file extension for the lazy.
                        $magic = MimeMagic::singleton();
                        $parts = explode( $name, '.' );
-                       $type = $magic->guessTypesForExtension( $parts[count( $parts ) - 1]  );
+                       $type = $magic->guessTypesForExtension( $parts[count( $parts ) - 1] );
                }
                return new UnregisteredLocalFile( false, $this->repo,
                        "mwstore://localtesting/data/$name", $type );
index 84deb1b..a9eaa9e 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 
 /**
+ * @group Media
  * @covers PNGMetadataExtractor
  */
 class PNGMetadataExtractorTest extends MediaWikiTestCase {
index 14e4d57..092be89 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+
+/**
+ * @group Media
+ */
 class PNGHandlerTest extends MediaWikiMediaTestCase {
 
        /** @var PNGHandler */
@@ -18,7 +22,7 @@ class PNGHandlerTest extends MediaWikiMediaTestCase {
        }
 
        /**
-        * @param string $filename basename of the file to check
+        * @param string $filename Basename of the file to check
         * @param bool $expected Expected result.
         * @dataProvider provideIsAnimated
         * @covers PNGHandler::isAnimatedImage
index f06bd6f..ab33d1c 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 
 /**
+ * @group Media
  * @covers SVGMetadataExtractor
  */
 class SVGMetadataExtractorTest extends MediaWikiTestCase {
index e3bb05e..1361a92 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+/**
+ * @group Media
+ */
 class SvgTest extends MediaWikiMediaTestCase {
 
        protected function setUp() {
index 26d7204..d114820 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+
+/**
+ * @group Media
+ */
 class TiffTest extends MediaWikiTestCase {
 
        /** @var TiffHandler */
index ae4fa8b..5b2de15 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+
+/**
+ * @group Media
+ */
 class XCFHandlerTest extends MediaWikiMediaTestCase {
 
        /** @var XCFHandler */
@@ -12,8 +16,8 @@ class XCFHandlerTest extends MediaWikiMediaTestCase {
 
        /**
         * @param string $filename
-        * @param int $expectedWidth width
-        * @param int $expectedHeigh height
+        * @param int $expectedWidth Width
+        * @param int $expectedHeight Height
         * @dataProvider provideGetImageSize
         * @covers XCFHandler::getImageSize
         */
index 25ae1e6..798e492 100644 (file)
@@ -1,7 +1,8 @@
 <?php
 
 /**
- * @todo covers tags
+ * @group Media
+ * @covers XMPReader
  */
 class XMPTest extends MediaWikiTestCase {
 
index 96bf5e4..ebec8f6 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+
+/**
+ * @group Media
+ */
 class XMPValidateTest extends MediaWikiTestCase {
 
        /**
index 1972bb5..987b6e6 100644 (file)
@@ -11,8 +11,8 @@ class BagOStuffTest extends MediaWikiTestCase {
                parent::setUp();
 
                // type defined through parameter
-               if ( $this->getCliArg( 'use-bagostuff=' ) ) {
-                       $name = $this->getCliArg( 'use-bagostuff=' );
+               if ( $this->getCliArg( 'use-bagostuff' ) ) {
+                       $name = $this->getCliArg( 'use-bagostuff' );
 
                        $this->cache = ObjectCache::newFromId( $name );
                } else {
@@ -23,9 +23,6 @@ class BagOStuffTest extends MediaWikiTestCase {
                $this->cache->delete( wfMemcKey( 'test' ) );
        }
 
-       protected function tearDown() {
-       }
-
        public function testMerge() {
                $key = wfMemcKey( 'test' );
 
@@ -67,7 +64,7 @@ class BagOStuffTest extends MediaWikiTestCase {
                 * - pcntl_fork is supported by the system
                 * - cache type will correctly support calls over forks
                 */
-               $fork = (bool)$this->getCliArg( 'use-bagostuff=' );
+               $fork = (bool)$this->getCliArg( 'use-bagostuff' );
                $fork &= function_exists( 'pcntl_fork' );
                $fork &= !$this->cache instanceof HashBagOStuff;
                $fork &= !$this->cache instanceof EmptyBagOStuff;
index d36697e..1722611 100644 (file)
@@ -171,7 +171,7 @@ class MagicVariableTest extends MediaWikiTestCase {
         * Main assertion helper for magic variables padding
         * @param string $magic Magic variable name
         * @param mixed $value Month or day
-        * @param string $format sprintf format for $value
+        * @param string $format Sprintf format for $value
         */
        private function assertMagicPadding( $magic, $value, $format ) {
                # Initialize parser timestamp as year 2010 at 12h34 56s.
index a506c86..a450972 100644 (file)
@@ -45,7 +45,7 @@ class MediaWikiParserTest {
         * MediaWikiParserTest::suite( MediaWikiParserTest::WITH_ALL );
         * @endcode
         *
-        * @param int $flags bitwise flag to filter out the $wgParserTestFiles that
+        * @param int $flags Bitwise flag to filter out the $wgParserTestFiles that
         * will be included.  Default: MediaWikiParserTest::CORE_ONLY
         *
         * @return PHPUnit_Framework_TestSuite
index 4c72d1c..0df52f5 100644 (file)
@@ -36,6 +36,10 @@ class NewParserTest extends MediaWikiTestCase {
         * @var DjVuSupport
         */
        private $djVuSupport;
+       /**
+        * @var TidySupport
+        */
+       private $tidySupport;
 
        protected $file = false;
 
@@ -51,8 +55,8 @@ class NewParserTest extends MediaWikiTestCase {
                parent::setUp();
 
                //Setup CLI arguments
-               if ( $this->getCliArg( 'regex=' ) ) {
-                       $this->regex = $this->getCliArg( 'regex=' );
+               if ( $this->getCliArg( 'regex' ) ) {
+                       $this->regex = $this->getCliArg( 'regex' );
                } else {
                        # Matches anything
                        $this->regex = '';
@@ -75,6 +79,7 @@ class NewParserTest extends MediaWikiTestCase {
                $tmpGlobals['wgExtensionAssetsPath'] = '/extensions';
                $tmpGlobals['wgStylePath'] = '/skins';
                $tmpGlobals['wgEnableUploads'] = true;
+               $tmpGlobals['wgUploadNavigationUrl'] = false;
                $tmpGlobals['wgThumbnailScriptPath'] = false;
                $tmpGlobals['wgLocalFileRepo'] = array(
                        'class' => 'LocalRepo',
@@ -95,8 +100,6 @@ class NewParserTest extends MediaWikiTestCase {
                $tmpGlobals['wgUseImageResize'] = true;
                $tmpGlobals['wgAllowExternalImages'] = true;
                $tmpGlobals['wgRawHtml'] = false;
-               $tmpGlobals['wgUseTidy'] = false;
-               $tmpGlobals['wgAlwaysUseTidy'] = false;
                $tmpGlobals['wgWellFormedXml'] = true;
                $tmpGlobals['wgAllowMicrodataAttributes'] = true;
                $tmpGlobals['wgExperimentalHtmlIds'] = false;
@@ -148,12 +151,24 @@ class NewParserTest extends MediaWikiTestCase {
                # proper precedence when resolving links. (bug 51680)
                $tmpGlobals['wgExtraNamespaces'] = array( 100 => 'MemoryAlpha' );
 
+               $tmpGlobals['wgLocalInterwikis'] = array( 'local', 'mi' );
                # "extra language links"
                # see https://gerrit.wikimedia.org/r/111390
                $tmpGlobals['wgExtraInterlanguageLinkPrefixes'] = array( 'mul' );
 
-               //DjVu support
+               // DjVu support
                $this->djVuSupport = new DjVuSupport();
+               // Tidy support
+               $this->tidySupport = new TidySupport();
+               // We always set 'wgUseTidy' to false when parsing, but certain
+               // test-running modes still use tidy if available, so ensure
+               // that the tidy-related options are all set to their defaults.
+               $tmpGlobals['wgUseTidy'] = false;
+               $tmpGlobals['wgAlwaysUseTidy'] = false;
+               $tmpGlobals['wgDebugTidy'] = false;
+               $tmpGlobals['wgTidyConf'] = $IP . '/includes/tidy.conf';
+               $tmpGlobals['wgTidyOpts'] = '';
+               $tmpGlobals['wgTidyInternal'] = $this->tidySupport->isInternal();
 
                $this->setMwGlobals( $tmpGlobals );
 
@@ -338,6 +353,9 @@ class NewParserTest extends MediaWikiTestCase {
        /**
         * Set up the global variables for a consistent environment for each test.
         * Ideally this should replace the global configuration entirely.
+        * @param array $opts
+        * @param string $config
+        * @return RequestContext
         */
        protected function setupGlobals( $opts = array(), $config = '' ) {
                global $wgFileBackends;
@@ -352,11 +370,11 @@ class NewParserTest extends MediaWikiTestCase {
                        self::getOptionValue( 'wgLinkHolderBatchSize', $opts, 1000 );
 
                $uploadDir = $this->getUploadDir();
-               if ( $this->getCliArg( 'use-filebackend=' ) ) {
+               if ( $this->getCliArg( 'use-filebackend' ) ) {
                        if ( self::$backendToUse ) {
                                $backend = self::$backendToUse;
                        } else {
-                               $name = $this->getCliArg( 'use-filebackend=' );
+                               $name = $this->getCliArg( 'use-filebackend' );
                                $useConfig = array();
                                foreach ( $wgFileBackends as $conf ) {
                                        if ( $conf['name'] == $name ) {
@@ -494,19 +512,23 @@ class NewParserTest extends MediaWikiTestCase {
                $backend = RepoGroup::singleton()->getLocalRepo()->getBackend();
                $backend->prepare( array( 'dir' => "$base/local-public/3/3a" ) );
                $backend->store( array(
-                       'src' => "$IP/tests/phpunit/data/parser/headbg.jpg", 'dst' => "$base/local-public/3/3a/Foobar.jpg"
+                       'src' => "$IP/tests/phpunit/data/parser/headbg.jpg",
+                       'dst' => "$base/local-public/3/3a/Foobar.jpg"
                ) );
                $backend->prepare( array( 'dir' => "$base/local-public/e/ea" ) );
                $backend->store( array(
-                       'src' => "$IP/tests/phpunit/data/parser/wiki.png", 'dst' => "$base/local-public/e/ea/Thumb.png"
+                       'src' => "$IP/tests/phpunit/data/parser/wiki.png",
+                       'dst' => "$base/local-public/e/ea/Thumb.png"
                ) );
                $backend->prepare( array( 'dir' => "$base/local-public/0/09" ) );
                $backend->store( array(
-                       'src' => "$IP/tests/phpunit/data/parser/headbg.jpg", 'dst' => "$base/local-public/0/09/Bad.jpg"
+                       'src' => "$IP/tests/phpunit/data/parser/headbg.jpg",
+                       'dst' => "$base/local-public/0/09/Bad.jpg"
                ) );
                $backend->prepare( array( 'dir' => "$base/local-public/5/5f" ) );
                $backend->store( array(
-                       'src' => "$IP/tests/phpunit/data/parser/LoremIpsum.djvu", 'dst' => "$base/local-public/5/5f/LoremIpsum.djvu"
+                       'src' => "$IP/tests/phpunit/data/parser/LoremIpsum.djvu",
+                       'dst' => "$base/local-public/5/5f/LoremIpsum.djvu"
                ) );
 
                // No helpful SVG file to copy, so make one ourselves
@@ -730,6 +752,14 @@ class NewParserTest extends MediaWikiTestCase {
                        $output = $parser->parse( $input, $title, $options, true, true, 1337 );
                        $output->setTOCEnabled( !isset( $opts['notoc'] ) );
                        $out = $output->getText();
+                       if ( isset( $opts['tidy'] ) ) {
+                               if ( !$this->tidySupport->isEnabled() ) {
+                                       $this->markTestSkipped( "SKIPPED: tidy extension is not installed.\n" );
+                               } else {
+                                       $out = MWTidy::tidy( $out );
+                                       $out = preg_replace( '/\s+$/', '', $out );
+                               }
+                       }
 
                        if ( isset( $opts['showtitle'] ) ) {
                                if ( $output->getTitleText() ) {
@@ -740,21 +770,19 @@ class NewParserTest extends MediaWikiTestCase {
                        }
 
                        if ( isset( $opts['ill'] ) ) {
-                               $out = $this->tidy( implode( ' ', $output->getLanguageLinks() ) );
+                               $out = implode( ' ', $output->getLanguageLinks() );
                        } elseif ( isset( $opts['cat'] ) ) {
                                $outputPage = $context->getOutput();
                                $outputPage->addCategoryLinks( $output->getCategories() );
                                $cats = $outputPage->getCategoryLinks();
 
                                if ( isset( $cats['normal'] ) ) {
-                                       $out = $this->tidy( implode( ' ', $cats['normal'] ) );
+                                       $out = implode( ' ', $cats['normal'] );
                                } else {
                                        $out = '';
                                }
                        }
                        $parser->mPreprocessor = null;
-
-                       $result = $this->tidy( $result );
                }
 
                $this->teardownGlobals();
@@ -775,8 +803,8 @@ class NewParserTest extends MediaWikiTestCase {
 
                $files = $wgParserTestFiles;
 
-               if ( $this->getCliArg( 'file=' ) ) {
-                       $files = array( $this->getCliArg( 'file=' ) );
+               if ( $this->getCliArg( 'file' ) ) {
+                       $files = array( $this->getCliArg( 'file' ) );
                }
 
                $dict = $this->getFuzzInput( $files );
@@ -847,6 +875,7 @@ class NewParserTest extends MediaWikiTestCase {
        /**
         * Get an input dictionary from a set of parser test files
         * @param array $filenames
+        * @return string
         */
        function getFuzzInput( $filenames ) {
                $dict = '';
@@ -865,6 +894,7 @@ class NewParserTest extends MediaWikiTestCase {
 
        /**
         * Get a memory usage breakdown
+        * @return array
         */
        function getMemoryBreakdown() {
                $memStats = array();
@@ -901,6 +931,7 @@ class NewParserTest extends MediaWikiTestCase {
        /**
         * Get a Parser object
         * @param Preprocessor $preprocessor
+        * @return Parser
         */
        function getParser( $preprocessor = null ) {
                global $wgParserConf;
@@ -958,26 +989,10 @@ class NewParserTest extends MediaWikiTestCase {
 
        //Various "cleanup" functions
 
-       /**
-        * Run the "tidy" command on text if the $wgUseTidy
-        * global is true
-        *
-        * @param string $text The text to tidy
-        * @return string
-        */
-       protected function tidy( $text ) {
-               global $wgUseTidy;
-
-               if ( $wgUseTidy ) {
-                       $text = MWTidy::tidy( $text );
-               }
-
-               return $text;
-       }
-
        /**
         * Remove last character if it is a newline
         * @param string $s
+        * @return string
         */
        public function removeEndingNewline( $s ) {
                if ( substr( $s, -1 ) === "\n" ) {
@@ -1062,6 +1077,7 @@ class NewParserTest extends MediaWikiTestCase {
         * @param string $key Name of option val to retrieve
         * @param array $opts Options array to look in
         * @param mixed $default Default value returned if not found
+        * @return mixed
         */
        protected static function getOptionValue( $key, $opts, $default ) {
                $key = strtolower( $key );
index 29af2c2..cbf4803 100644 (file)
@@ -78,7 +78,7 @@ class ParserMethodsTest extends MediaWikiLangTestCase {
                $wgParser->parse( '<recursivecallparser>baz</recursivecallparser>', $title, $po );
        }
 
-       public function helperParserFunc( $input, $args, $parser) {
+       public function helperParserFunc( $input, $args, $parser ) {
                $title = Title::newFromText( 'foo' );
                $po = new ParserOptions;
                $parser->parse( $input, $title, $po );
index 12aac69..c869258 100644 (file)
@@ -26,6 +26,24 @@ class TidyTest extends MediaWikiTestCase {
        }
 
        public function provideTestWrapping() {
+               $testMathML = <<<'MathML'
+<math xmlns="http://www.w3.org/1998/Math/MathML">
+    <mrow>
+      <mi>a</mi>
+      <mo>&InvisibleTimes;</mo>
+      <msup>
+        <mi>x</mi>
+        <mn>2</mn>
+      </msup>
+      <mo>+</mo>
+      <mi>b</mi>
+      <mo>&InvisibleTimes; </mo>
+      <mi>x</mi>
+      <mo>+</mo>
+      <mi>c</mi>
+    </mrow>
+  </math>
+MathML;
                return array(
                        array(
                                '<mw:editsection page="foo" section="bar">foo</mw:editsection>',
@@ -40,6 +58,7 @@ class TidyTest extends MediaWikiTestCase {
                        array( '<mw:toc>foo</mw:toc>', '<mw:toc>foo</mw:toc>', '<mw:toc> should survive tidy' ),
                        array( "<link foo=\"bar\" />\nfoo", '<link foo="bar"/>foo', '<link> should survive tidy' ),
                        array( "<meta foo=\"bar\" />\nfoo", '<meta foo="bar"/>foo', '<meta> should survive tidy' ),
+                       array( $testMathML, $testMathML, '<math> should survive tidy' ),
                );
        }
 }
diff --git a/tests/phpunit/includes/password/BcryptPasswordTest.php b/tests/phpunit/includes/password/BcryptPasswordTest.php
new file mode 100644 (file)
index 0000000..4d5c78a
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @group large
+ */
+class BcryptPasswordTestCase extends PasswordTestCase {
+       protected function getTypeConfigs() {
+               return array( 'bcrypt' => array(
+                       'class' => 'BcryptPassword',
+                       'cost' => 9,
+               ) );
+       }
+
+       public function providePasswordTests() {
+               /** @codingStandardsIgnoreStart Generic.Files.LineLength.TooLong */
+               return array(
+                       // 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', "" ),
+                       // One or two false sanity tests
+                       array( false, ':bcrypt:5$CCCCCCCCCCCCCCCCCCCCC.$E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW', "UXU" ),
+                       array( false, ':bcrypt:5$CCCCCCCCCCCCCCCCCCCCC.$E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW', "" ),
+               );
+               /** @codingStandardsIgnoreEnd */
+       }
+}
diff --git a/tests/phpunit/includes/password/LayeredParameterizedPasswordTest.php b/tests/phpunit/includes/password/LayeredParameterizedPasswordTest.php
new file mode 100644 (file)
index 0000000..03a742b
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+
+class LayeredParameterizedPasswordTest extends PasswordTestCase {
+       protected function getTypeConfigs() {
+               return array(
+                       'testLargeLayeredTop' => array(
+                               'class' => 'LayeredParameterizedPassword',
+                               'types' => array(
+                                       'testLargeLayeredBottom',
+                                       'testLargeLayeredBottom',
+                                       'testLargeLayeredBottom',
+                                       'testLargeLayeredBottom',
+                                       'testLargeLayeredFinal',
+                               ),
+                       ),
+                       'testLargeLayeredBottom' => array(
+                               'class' => 'Pbkdf2Password',
+                               'algo' => 'sha512',
+                               'cost' => 1024,
+                               'length' => 512,
+                       ),
+                       'testLargeLayeredFinal' => array(
+                               'class' => 'BcryptPassword',
+                               'cost' => 5,
+                       )
+               );
+       }
+
+       public 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' ),
+               );
+               /** @codingStandardsIgnoreEnd */
+       }
+
+       /**
+        * @covers LayeredParameterizedPassword::partialCrypt
+        */
+       public function testLargeLayeredPartialUpdate() {
+               /** @var ParameterizedPassword $partialPassword */
+               $partialPassword = $this->passwordFactory->newFromType( 'testLargeLayeredBottom' );
+               $partialPassword->crypt( 'testPassword123' );
+
+               /** @var LayeredParameterizedPassword $totalPassword */
+               $totalPassword = $this->passwordFactory->newFromType( 'testLargeLayeredTop' );
+               $totalPassword->partialCrypt( $partialPassword );
+
+               $this->assertTrue( $totalPassword->equals( 'testPassword123' ) );
+       }
+}
diff --git a/tests/phpunit/includes/password/PasswordTestCase.php b/tests/phpunit/includes/password/PasswordTestCase.php
new file mode 100644 (file)
index 0000000..7820d53
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Testing framework for the password hashes
+ *
+ * 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.24
+ */
+abstract class PasswordTestCase extends MediaWikiTestCase {
+       /**
+        * @var PasswordFactory
+        */
+       protected $passwordFactory;
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->passwordFactory = new PasswordFactory();
+               foreach ( $this->getTypeConfigs() as $type => $config ) {
+                       $this->passwordFactory->register( $type, $config );
+               }
+       }
+
+       /**
+        * Return an array of configs to be used for this class's password type.
+        *
+        * @return array[]
+        */
+       abstract protected function getTypeConfigs();
+
+       /**
+        * An array of tests in the form of (bool, string, string), where the first
+        * element is whether the second parameter (a password hash) and the third
+        * parameter (a password) should match.
+        *
+        * @return array
+        */
+       abstract public function providePasswordTests();
+
+       /**
+        * @dataProvider providePasswordTests
+        */
+       public function testHashing( $shouldMatch, $hash, $password ) {
+               $hash = $this->passwordFactory->newFromCiphertext( $hash );
+               $password = $this->passwordFactory->newFromPlaintext( $password, $hash );
+               $this->assertSame( $shouldMatch, $hash->equals( $password ) );
+       }
+
+       /**
+        * @dataProvider providePasswordTests
+        */
+       public function testStringSerialization( $shouldMatch, $hash, $password ) {
+               $hashObj = $this->passwordFactory->newFromCiphertext( $hash );
+               $serialized = $hashObj->toString();
+               $unserialized = $this->passwordFactory->newFromCiphertext( $serialized );
+               $this->assertTrue( $hashObj->equals( $unserialized ) );
+       }
+
+       /**
+        * @dataProvider providePasswordTests
+        * @covers InvalidPassword::equals
+        * @covers InvalidPassword::toString
+        */
+       public function testInvalidUnequalNormal( $shouldMatch, $hash, $password ) {
+               $invalid = $this->passwordFactory->newFromCiphertext( null );
+               $normal = $this->passwordFactory->newFromCiphertext( $hash );
+
+               $this->assertFalse( $invalid->equals( $normal ) );
+               $this->assertFalse( $normal->equals( $invalid ) );
+       }
+}
diff --git a/tests/phpunit/includes/password/Pbkdf2PasswordTest.php b/tests/phpunit/includes/password/Pbkdf2PasswordTest.php
new file mode 100644 (file)
index 0000000..ae47120
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @group large
+ */
+class Pbkdf2PasswordTest extends PasswordTestCase {
+       protected function getTypeConfigs() {
+               return array( 'pbkdf2' => array(
+                       'class' => 'Pbkdf2Password',
+                       'algo' => 'sha256',
+                       'cost' => '10000',
+                       'length' => '128',
+               ) );
+       }
+
+       public function providePasswordTests() {
+               return array(
+                       array( true, ":pbkdf2:sha1:1:20:c2FsdA==:DGDID5YfDnHzqbUkr2ASBi/gN6Y=", 'password' ),
+                       array( true, ":pbkdf2:sha1:2:20:c2FsdA==:6mwBTcctb4zNHtkqzh1B8NjeiVc=", 'password' ),
+                       array( true, ":pbkdf2:sha1:4096:20:c2FsdA==:SwB5AbdlSJq+rUnZJvch0GWkKcE=", 'password' ),
+                       array( true, ":pbkdf2:sha1:4096:16:c2EAbHQ=:Vvpqp1VICZ3MN9fwNCXgww==", "pass\x00word" ),
+               );
+       }
+}
index 2d31d08..019e532 100644 (file)
@@ -1,7 +1,8 @@
 <?php
 
-// We will use this class with getMockForAbstractClass to create a concrete mock class. That call will die if the
-// contructor is not public, unless we use disableOriginalConstructor(), in which case we could not test the constructor.
+// We will use this class with getMockForAbstractClass to create a concrete mock class.
+// That call will die if the contructor is not public, unless we use disableOriginalConstructor(),
+// in which case we could not test the constructor.
 abstract class PoolCounterAbstractMock extends PoolCounter {
        public function __construct() {
                call_user_func_array( 'parent::__construct', func_get_args() );
@@ -19,8 +20,8 @@ class PoolCounterTest extends MediaWikiTestCase {
 
                $poolCounter = $this->getMockBuilder( 'PoolCounterAbstractMock' )
                        ->setConstructorArgs( array( $poolCounterConfig, 'testCounter', 'someKey' ) )
-                       // don't mock anything - the proper syntax would be setMethods(null), but due to a PHPUnit bug that
-                       // does not work with getMockForAbstractClass()
+                       // don't mock anything - the proper syntax would be setMethods(null), but due
+                       // to a PHPUnit bug that does not work with getMockForAbstractClass()
                        ->setMethods( array( 'idontexist' ) )
                        ->getMockForAbstractClass();
                $this->assertInstanceOf( 'PoolCounter', $poolCounter );
@@ -44,16 +45,15 @@ class PoolCounterTest extends MediaWikiTestCase {
 
        public function testHashKeyIntoSlots() {
                $poolCounter = $this->getMockBuilder( 'PoolCounterAbstractMock' )
-                       // don't mock anything - the proper syntax would be setMethods(null), but due to a PHPUnit bug that
-                       // does not work with getMockForAbstractClass()
+                       // don't mock anything - the proper syntax would be setMethods(null), but due
+                       // to a PHPUnit bug that does not work with getMockForAbstractClass()
                        ->setMethods( array( 'idontexist' ) )
                        ->disableOriginalConstructor()
                        ->getMockForAbstractClass();
 
-               $hashKeyIntoSlots = new ReflectionMethod($poolCounter, 'hashKeyIntoSlots' );
+               $hashKeyIntoSlots = new ReflectionMethod( $poolCounter, 'hashKeyIntoSlots' );
                $hashKeyIntoSlots->setAccessible( true );
 
-
                $keysWithTwoSlots = $keysWithFiveSlots = array();
                foreach ( range( 1, 100 ) as $i ) {
                        $keysWithTwoSlots[] = $hashKeyIntoSlots->invoke( $poolCounter, 'key ' . $i, 2 );
index 75e54d3..a3d73e5 100644 (file)
@@ -22,7 +22,8 @@ class ResourceLoaderLESSTest extends MediaWikiTestCase {
 
                $expect = file_get_contents( $cssFile );
                $content = file_get_contents( $lessFile );
-               $result = ResourceLoader::getLessCompiler()->compile( $content, $lessFile );
+               $result = ResourceLoader::getLessCompiler( RequestContext::getMain()->getConfig() )
+                       ->compile( $content, $lessFile );
                $this->assertEquals( $expect, $result );
        }
 }
index fa22d34..b0edaaf 100644 (file)
@@ -2,6 +2,19 @@
 
 class ResourceLoaderModuleTest extends ResourceLoaderTestCase {
 
+       protected function setUp() {
+               parent::setUp();
+
+               // The return value of the closure shouldn't matter since this test should
+               // never call it
+               SkinFactory::getDefaultInstance()->register(
+                       'fakeskin',
+                       'FakeSkin',
+                       function () {
+                       }
+               );
+       }
+
        /**
         * @covers ResourceLoaderFileModule::getAllSkinStyleFiles
         */
@@ -21,7 +34,7 @@ class ResourceLoaderModuleTest extends ResourceLoaderTestCase {
                        ),
                        'skinStyles' => array(
                                'default' => 'quux-fallback.less',
-                               'vector' => array(
+                               'fakeskin' => array(
                                        'baz-vector.css',
                                        'quux-vector.less',
                                ),
index df08972..a189387 100644 (file)
@@ -9,10 +9,7 @@ class ResourceLoaderStartupModuleTest extends ResourceLoaderTestCase {
                                'modules' => array(),
                                'out' => '
 mw.loader.addSource( {
-    "local": {
-        "loadScript": "/w/load.php",
-        "apiScript": "/w/api.php"
-    }
+    "local": "/w/load.php"
 } );mw.loader.register( [] );'
                        ) ),
                        array( array(
@@ -22,10 +19,7 @@ mw.loader.addSource( {
                                ),
                                'out' => '
 mw.loader.addSource( {
-    "local": {
-        "loadScript": "/w/load.php",
-        "apiScript": "/w/api.php"
-    }
+    "local": "/w/load.php"
 } );mw.loader.register( [
     [
         "test.blank",
@@ -42,10 +36,7 @@ mw.loader.addSource( {
                                ),
                                'out' => '
 mw.loader.addSource( {
-    "local": {
-        "loadScript": "/w/load.php",
-        "apiScript": "/w/api.php"
-    }
+    "local": "/w/load.php"
 } );mw.loader.register( [
     [
         "test.blank",
@@ -73,10 +64,7 @@ mw.loader.addSource( {
                                ),
                                'out' => '
 mw.loader.addSource( {
-    "local": {
-        "loadScript": "/w/load.php",
-        "apiScript": "/w/api.php"
-    }
+    "local": "/w/load.php"
 } );mw.loader.register( [
     [
         "test.blank",
@@ -97,14 +85,8 @@ mw.loader.addSource( {
                                ),
                                'out' => '
 mw.loader.addSource( {
-    "local": {
-        "loadScript": "/w/load.php",
-        "apiScript": "/w/api.php"
-    },
-    "example": {
-        "loadScript": "http://example.org/w/load.php",
-        "apiScript": "http://example.org/w/api.php"
-    }
+    "local": "/w/load.php",
+    "example": "http://example.org/w/load.php"
 } );mw.loader.register( [
     [
         "test.blank",
@@ -140,10 +122,7 @@ mw.loader.addSource( {
                                ),
                                'out' => '
 mw.loader.addSource( {
-    "local": {
-        "loadScript": "/w/load.php",
-        "apiScript": "/w/api.php"
-    }
+    "local": "/w/load.php"
 } );mw.loader.register( [
     [
         "test.x.core",
@@ -238,14 +217,8 @@ mw.loader.addSource( {
                                ),
                                'out' => '
 mw.loader.addSource( {
-    "local": {
-        "loadScript": "/w/load.php",
-        "apiScript": "/w/api.php"
-    },
-    "example": {
-        "loadScript": "http://example.org/w/load.php",
-        "apiScript": "http://example.org/w/api.php"
-    }
+    "local": "/w/load.php",
+    "example": "http://example.org/w/load.php"
 } );mw.loader.register( [
     [
         "test.blank",
@@ -332,9 +305,10 @@ mw.loader.addSource( {
 
                $rl->register( $case['modules'] );
 
+               $module = new ResourceLoaderStartUpModule();
                $this->assertEquals(
                        ltrim( $case['out'], "\n" ),
-                       ResourceLoaderStartUpModule::getModuleRegistrations( $context ),
+                       $module->getModuleRegistrations( $context ),
                        $case['msg']
                );
        }
@@ -366,14 +340,15 @@ mw.loader.addSource( {
                $context = self::getResourceLoaderContext();
                $rl = $context->getResourceLoader();
                $rl->register( $modules );
+               $module = new ResourceLoaderStartUpModule();
                $this->assertEquals(
-'mw.loader.addSource({"local":{"loadScript":"/w/load.php","apiScript":"/w/api.php"}});'
+'mw.loader.addSource({"local":"/w/load.php"});'
 . 'mw.loader.register(['
 . '["test.blank","1388534400"],'
 . '["test.min","1388534400",["test.blank"],null,"local",'
 . '"return!!(window.JSON\u0026\u0026JSON.parse\u0026\u0026JSON.stringify);"'
 . ']]);',
-                       ResourceLoaderStartUpModule::getModuleRegistrations( $context ),
+                       $module->getModuleRegistrations( $context ),
                        'Minified output'
                );
        }
@@ -385,12 +360,10 @@ mw.loader.addSource( {
                $context = self::getResourceLoaderContext();
                $rl = $context->getResourceLoader();
                $rl->register( $modules );
+               $module = new ResourceLoaderStartUpModule();
                $this->assertEquals(
 'mw.loader.addSource( {
-    "local": {
-        "loadScript": "/w/load.php",
-        "apiScript": "/w/api.php"
-    }
+    "local": "/w/load.php"
 } );mw.loader.register( [
     [
         "test.blank",
@@ -407,7 +380,7 @@ mw.loader.addSource( {
         "return !!(    window.JSON \u0026\u0026    JSON.parse \u0026\u0026    JSON.stringify);"
     ]
 ] );',
-                       ResourceLoaderStartUpModule::getModuleRegistrations( $context ),
+                       $module->getModuleRegistrations( $context ),
                        'Unminified output'
                );
        }
index d3736f5..d2e118c 100644 (file)
@@ -90,6 +90,36 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
                $this->assertStringEqualsFile( $basePath . '/styles.css', $styles['all'] );
        }
 
+       /**
+        * What happens when you mix @embed and @noflip?
+        * This really is an integration test, but oh well.
+        */
+       public function testMixedCssAnnotations(  ) {
+               $basePath = __DIR__ . '/../../data/css';
+               $testModule = new ResourceLoaderFileModule( array(
+                       'localBasePath' => $basePath,
+                       'styles' => array( 'test.css' ),
+               ) );
+               $expectedModule = new ResourceLoaderFileModule( array(
+                       'localBasePath' => $basePath,
+                       'styles' => array( 'expected.css' ),
+               ) );
+
+               $contextLtr = self::getResourceLoaderContext( 'en' );
+               $contextRtl = self::getResourceLoaderContext( 'he' );
+
+               $this->assertEquals(
+                       $expectedModule->getStyles( $contextLtr ),
+                       $testModule->getStyles( $contextLtr ),
+                       "/*@noflip*/ with /*@embed*/ gives correct results in LTR mode"
+               );
+               $this->assertEquals(
+                       $expectedModule->getStyles( $contextLtr ),
+                       $testModule->getStyles( $contextRtl ),
+                       "/*@noflip*/ with /*@embed*/ gives correct results in RTL mode"
+               );
+       }
+
        /**
         * @dataProvider providePackedModules
         * @covers ResourceLoader::makePackedModulesString
@@ -130,6 +160,76 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
                        ),
                );
        }
+
+       public static function provideAddSource() {
+               return array(
+                       array( 'examplewiki', '//example.org/w/load.php', 'examplewiki' ),
+                       array( 'example2wiki', array( 'loadScript' => '//example.com/w/load.php' ), 'example2wiki' ),
+                       array(
+                               array( 'foowiki' => '//foo.org/w/load.php', 'bazwiki' => '//baz.org/w/load.php' ),
+                               null,
+                               array( 'foowiki', 'bazwiki' )
+                       ),
+                       array(
+                               array( 'foowiki' => '//foo.org/w/load.php' ),
+                               null,
+                               false,
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider provideAddSource
+        * @covers ResourceLoader::addSource
+        */
+       public function testAddSource( $name, $info, $expected ) {
+               $rl = new ResourceLoader;
+               if ( $expected === false ) {
+                       $this->setExpectedException( 'MWException', 'ResourceLoader duplicate source addition error' );
+                       $rl->addSource( $name, $info );
+               }
+               $rl->addSource( $name, $info );
+               if ( is_array( $expected ) ) {
+                       foreach ( $expected as $source ) {
+                               $this->assertArrayHasKey( $source, $rl->getSources() );
+                       }
+               } else {
+                       $this->assertArrayHasKey( $expected, $rl->getSources() );
+               }
+       }
+
+       public static function fakeSources() {
+               return array(
+                       'examplewiki' => array(
+                               'loadScript' => '//example.org/w/load.php',
+                               'apiScript' => '//example.org/w/api.php',
+                       ),
+                       'example2wiki' => array(
+                               'loadScript' => '//example.com/w/load.php',
+                               'apiScript' => '//example.com/w/api.php',
+                       ),
+               );
+       }
+
+       /**
+        * @covers ResourceLoader::getLoadScript
+        */
+       public function testGetLoadScript() {
+               $this->setMwGlobals( 'wgResourceLoaderSources', array() );
+               $rl = new ResourceLoader();
+               $sources = self::fakeSources();
+               $rl->addSource( $sources );
+               foreach ( array( 'examplewiki', 'example2wiki' ) as $name ) {
+                       $this->assertEquals( $rl->getLoadScript( $name ), $sources[$name]['loadScript'] );
+               }
+
+               try {
+                       $rl->getLoadScript( 'thiswasneverreigstered' );
+                       $this->assertTrue( false, 'ResourceLoader::getLoadScript should have thrown an exception' );
+               } catch ( MWException $e ) {
+                       $this->assertTrue( true );
+               }
+       }
 }
 
 /* Hooks */
diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderWikiModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderWikiModuleTest.php
new file mode 100644 (file)
index 0000000..50f88c8
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+
+class ResourceLoaderWikiModuleTest extends ResourceLoaderTestCase {
+
+       /**
+        * @covers ResourceLoaderWikiModule::isKnownEmpty
+        * @dataProvider provideIsKnownEmpty
+        */
+       public function testIsKnownEmpty( $titleInfo, $group, $expected ) {
+               $module = $this->getMockBuilder( 'ResourceLoaderWikiModuleTestModule' )
+                       ->setMethods( array( 'getTitleInfo', 'getGroup' ) )
+                       ->getMock();
+               $module->expects( $this->any() )
+                       ->method( 'getTitleInfo' )
+                       ->will( $this->returnValue( $titleInfo ) );
+               $module->expects( $this->any() )
+                       ->method( 'getGroup' )
+                       ->will( $this->returnValue( $group ) );
+               $context = $this->getMockBuilder( 'ResourceLoaderContext' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $this->assertEquals( $expected, $module->isKnownEmpty( $context ) );
+       }
+
+       public function provideIsKnownEmpty() {
+               return array(
+                       // No valid pages
+                       array( array(), 'test1', true ),
+                       // 'site' module with a non-empty page
+                       array(
+                               array(
+                                       'MediaWiki:Common.js' => array(
+                                               'timestamp' => 123456789,
+                                               'length' => 1234
+                                       )
+                               ), 'site', false,
+                       ),
+                       // 'site' module with an empty page
+                       array(
+                               array(
+                                       'MediaWiki:Monobook.js' => array(
+                                               'timestamp' => 987654321,
+                                               'length' => 0,
+                                       ),
+                               ), 'site', false,
+                       ),
+                       // 'user' module with a non-empty page
+                       array(
+                               array(
+                                       'User:FooBar/common.js' => array(
+                                               'timestamp' => 246813579,
+                                               'length' => 25,
+                                       ),
+                               ), 'user', false,
+                       ),
+                       // 'user' module with an empty page
+                       array(
+                               array(
+                                       'User:FooBar/monobook.js' => array(
+                                               'timestamp' => 1357924680,
+                                               'length' => 0,
+                                       ),
+                               ), 'user', true,
+                       ),
+               );
+       }
+}
index f224b7d..af314ba 100644 (file)
@@ -72,7 +72,22 @@ class TestSites {
                $site->setLinkPath( "http://spamzz.test/testing/" );
                $sites[] = $site;
 
-               foreach ( array( 'en', 'de', 'nl', 'sv', 'sr', 'no', 'nn' ) as $langCode ) {
+               /**
+                * Add at least one right-to-left language (current RTL languages in MediaWiki core are:
+                * aeb, ar, arc, arz, azb, bcc, bqi, ckb, dv, en_rtl, fa, glk, he, khw, kk_arab, kk_cn,
+                * ks_arab, ku_arab, lrc, mzn, pnb, ps, sd, ug_arab, ur, yi).
+                */
+               $languageCodes = array(
+                       'de',
+                       'en',
+                       'fa', //right-to-left
+                       'nl',
+                       'nn',
+                       'no',
+                       'sr',
+                       'sv',
+               );
+               foreach ( $languageCodes as $langCode ) {
                        $site = new MediaWikiSite();
                        $site->setGlobalId( $langCode . 'wiki' );
                        $site->setGroup( 'wikipedia' );
diff --git a/tests/phpunit/includes/skins/SkinFactoryTest.php b/tests/phpunit/includes/skins/SkinFactoryTest.php
new file mode 100644 (file)
index 0000000..d3663c8
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+
+class SkinFactoryTest extends MediaWikiTestCase {
+
+       /**
+        * @covers SkinFactory::register
+        */
+       public function testRegister() {
+               $factory = new SkinFactory();
+               $factory->register( 'fallback', 'Fallback', function () {
+                       return new SkinFallback();
+               } );
+               $this->assertTrue( true ); // No exception thrown
+               $this->setExpectedException( 'InvalidArgumentException' );
+               $factory->register( 'invalid', 'Invalid', 'Invalid callback' );
+       }
+
+       /**
+        * @covers SkinFactory::makeSkin
+        */
+       public function testMakeSkinWithNoBuilders() {
+               $factory = new SkinFactory();
+               $this->setExpectedException( 'SkinException' );
+               $factory->makeSkin( 'nobuilderregistered' );
+       }
+
+       /**
+        * @covers SkinFactory::makeSkin
+        */
+       public function testMakeSkinWithInvalidCallback() {
+               $factory = new SkinFactory();
+               $factory->register( 'unittest', 'Unittest', function () {
+                       return true; // Not a Skin object
+               } );
+               $this->setExpectedException( 'UnexpectedValueException' );
+               $factory->makeSkin( 'unittest' );
+       }
+
+       /**
+        * @covers SkinFactory::makeSkin
+        */
+       public function testMakeSkinWithValidCallback() {
+               $factory = new SkinFactory();
+               $factory->register( 'testfallback', 'TestFallback', function () {
+                       return new SkinFallback();
+               } );
+
+               $skin = $factory->makeSkin( 'testfallback' );
+               $this->assertInstanceOf( 'Skin', $skin );
+               $this->assertInstanceOf( 'SkinFallback', $skin );
+       }
+
+       /**
+        * @covers SkinFactory::getSkinNames
+        */
+       public function testGetSkinNames() {
+               $factory = new SkinFactory();
+               // A fake callback we can use that will never be called
+               $callback = function () {
+                       // NOP
+               };
+               $factory->register( 'skin1', 'Skin1', $callback );
+               $factory->register( 'skin2', 'Skin2', $callback );
+               $names = $factory->getSkinNames();
+               $this->assertArrayHasKey( 'skin1', $names );
+               $this->assertArrayHasKey( 'skin2', $names );
+               $this->assertEquals( 'Skin1', $names['skin1'] );
+               $this->assertEquals( 'Skin2', $names['skin2'] );
+       }
+}
diff --git a/tests/phpunit/includes/skins/SkinTemplateTest.php b/tests/phpunit/includes/skins/SkinTemplateTest.php
new file mode 100644 (file)
index 0000000..baa995d
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @covers SkinTemplate
+ *
+ * @group Output
+ *
+ * @licence GNU GPL v2+
+ * @author Bene* < benestar.wikimedia@gmail.com >
+ */
+
+class SkinTemplateTest extends MediaWikiTestCase {
+       /**
+        * @dataProvider makeListItemProvider
+        */
+       public function testMakeListItem( $expected, $key, $item, $options, $message ) {
+               $template = $this->getMockForAbstractClass( 'BaseTemplate' );
+
+               $this->assertEquals(
+                       $expected,
+                       $template->makeListItem( $key, $item, $options ),
+                       $message
+               );
+       }
+
+       public function makeListItemProvider() {
+               return array(
+                       array(
+                               '<li class="class" title="itemtitle"><a href="url" title="title">text</a></li>',
+                               '',
+                               array(
+                                       'class' => 'class',
+                                       'itemtitle' => 'itemtitle',
+                                       'href' => 'url',
+                                       'title' => 'title',
+                                       'text' => 'text'
+                               ),
+                               array(),
+                               'Test makteListItem with normal values'
+                       )
+               );
+       }
+}
diff --git a/tests/phpunit/includes/specials/ImageListPagerTest.php b/tests/phpunit/includes/specials/ImageListPagerTest.php
new file mode 100644 (file)
index 0000000..8a0ac97
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Test class for ImageListPagerTest class.
+ *
+ * Copyright © 2013, Antoine Musso
+ * Copyright © 2013, Siebrand Mazeland
+ * Copyright © 2013, Wikimedia Foundation Inc.
+ *
+ */
+
+class ImageListPagerTest extends MediaWikiTestCase {
+       /**
+        * @expectedException MWException
+        * @expectedExceptionMessage invalid_field
+        * @covers ImageListPager::formatValue
+        */
+       public function testFormatValuesThrowException() {
+               $page = new ImageListPager( RequestContext::getMain() );
+               $page->formatValue( 'invalid_field', 'invalid_value' );
+       }
+}
diff --git a/tests/phpunit/includes/specials/SpecialListFilesTest.php b/tests/phpunit/includes/specials/SpecialListFilesTest.php
deleted file mode 100644 (file)
index 2689236..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-/**
- * Test class for SpecialListFiles class.
- *
- * Copyright © 2013, Antoine Musso
- * Copyright © 2013, Siebrand Mazeland
- * Copyright © 2013, Wikimedia Foundation Inc.
- *
- */
-
-class SpecialListFilesTest extends MediaWikiTestCase {
-       /**
-        * @expectedException MWException
-        * @expectedExceptionMesage invalid_field
-        * @covers ImageListPager::formatValue
-        */
-       public function testFormatValuesThrowException() {
-               $page = new ImageListPager( RequestContext::getMain() );
-               $page->formatValue( 'invalid_field', 'invalid_value' );
-       }
-}
index e7bb35c..bd95281 100644 (file)
@@ -16,9 +16,9 @@ class SpecialMIMESearchTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider providerMimeFiltering
-        * @param $par String subpage for special page
-        * @param $major String Major mime type we expect to look for
-        * @param $minor String Minor mime type we expect to look for
+        * @param string $par Subpage for special page
+        * @param string $major Major MIME type we expect to look for
+        * @param string $minor Minor MIME type we expect to look for
         */
        function testMimeFiltering( $par, $major, $minor ) {
                $this->page->run( $par );
diff --git a/tests/phpunit/includes/specials/SpecialMyLanguageTest.php b/tests/phpunit/includes/specials/SpecialMyLanguageTest.php
new file mode 100644 (file)
index 0000000..fd09043
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * @group Database
+ * @covers SpecialMyLanguage
+ */
+class SpecialMyLanguageTest extends MediaWikiTestCase {
+       public function addDBData() {
+               $titles = array(
+                       'Page/Another',
+                       'Page/Another/ru',
+               );
+               foreach ( $titles as $title ) {
+                       $page = WikiPage::factory( Title::newFromText( $title ) );
+                       if ( $page->getId() == 0 ) {
+                               $page->doEditContent(
+                                       new WikitextContent( 'UTContent' ),
+                                       'UTPageSummary',
+                                       EDIT_NEW,
+                                       false,
+                                       User::newFromName( 'UTSysop' ) );
+                       }
+               }
+       }
+
+       /**
+        * @covers SpecialMyLanguage::findTitle
+        * @dataProvider provideFindTitle
+        * @param string $expected
+        * @param string $subpage
+        * @param string $langCode
+        * @param string $userLang
+        */
+       public function testFindTitle( $expected, $subpage, $langCode, $userLang ) {
+               $this->setMwGlobals( 'wgLanguageCode', $langCode );
+               $special = new SpecialMyLanguage();
+               $special->getContext()->setLanguage( $userLang );
+               // Test with subpages both enabled and disabled
+               $this->mergeMwGlobalArrayValue( 'wgNamespacesWithSubpages', array( NS_MAIN => true ) );
+               $this->assertTitle( $expected, $special->findTitle( $subpage ) );
+               $this->mergeMwGlobalArrayValue( 'wgNamespacesWithSubpages', array( NS_MAIN => false ) );
+               $this->assertTitle( $expected, $special->findTitle( $subpage ) );
+       }
+
+       /**
+        * @param string $expected
+        * @param Title|null $title
+        */
+       private function assertTitle( $expected, $title ) {
+               if ( $title ) {
+                       $title = $title->getPrefixedText();
+               }
+               $this->assertEquals( $expected, $title );
+       }
+
+       public function provideFindTitle() {
+               return array(
+                       array( null, '::Fail', 'en', 'en' ),
+                       array( 'Page/Another', 'Page/Another/en', 'en', 'en' ),
+                       array( 'Page/Another', 'Page/Another', 'en', 'en' ),
+                       array( 'Page/Another/ru', 'Page/Another', 'en', 'ru' ),
+                       array( 'Page/Another', 'Page/Another', 'en', 'es' ),
+               );
+       }
+}
index dbebeb7..83489c6 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 class SpecialSearchTest extends MediaWikiTestCase {
-       private $search;
 
        /**
         * @covers SpecialSearch::load
@@ -18,7 +17,8 @@ class SpecialSearchTest extends MediaWikiTestCase {
         * @param array $userOptions User options to test with. For example:
         *   array('searchNs5' => 1 );. Null to use default options.
         * @param string $expectedProfile An expected search profile name
-        * @param array $expectedNs Expected namespaces
+        * @param array $expectedNS Expected namespaces
+        * @param string $message
         */
        public function testProfileAndNamespaceLoading( $requested, $userOptions,
                $expectedProfile, $expectedNS, $message = 'Profile name and namespaces mismatches!'
@@ -96,6 +96,7 @@ class SpecialSearchTest extends MediaWikiTestCase {
        /**
         * Helper to create a new User object with given options
         * User remains anonymous though
+        * @param array|null $opt
         */
        function newUserWithSearchNS( $opt = null ) {
                $u = User::newFromId( 0 );
@@ -114,6 +115,9 @@ class SpecialSearchTest extends MediaWikiTestCase {
         * https://gerrit.wikimedia.org/r/4841
         */
        public function testSearchTermIsNotExpanded() {
+               $this->setMwGlobals( array(
+                       'wgSearchType' => null,
+               ) );
 
                # Initialize [[Special::Search]]
                $search = new SpecialSearch();
index 73d7ff9..b13df89 100644 (file)
@@ -9,7 +9,7 @@
  * 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.
  */
 class MediaWikiPageLinkRendererTest extends MediaWikiTestCase {
 
+       protected function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       'wgContLang' => Language::factory( 'en' ),
+               ) );
+       }
+
        /**
         * Returns a mock GenderCache that will return "female" always.
         *
@@ -147,7 +155,7 @@ class MediaWikiPageLinkRendererTest extends MediaWikiTestCase {
                $formatter->expects( $this->any() )
                        ->method( 'getFullText' )
                        ->will( $this->returnCallback(
-                               function( TitleValue $title ) {
+                               function ( TitleValue $title ) {
                                        return str_replace( '_', ' ', "$title" );
                                }
                        ));
index 2cf8663..bf06e3b 100644 (file)
@@ -72,7 +72,7 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
 
                $genderCache->expects( $this->any() )
                        ->method( 'getGenderOf' )
-                       ->will( $this->returnCallback( function( $userName ) {
+                       ->will( $this->returnCallback( function ( $userName ) {
                                return preg_match( '/^[^- _]+a( |_|$)/u', $userName ) ? 'female' : 'male';
                        } ) );
 
index 7125247..ec56b63 100644 (file)
@@ -110,7 +110,7 @@ class UploadFromUrlTest extends ApiTestCase {
                $this->user->addGroup( 'sysop' );
                $data = $this->doApiRequest( array(
                        'action' => 'upload',
-                       'url' => 'http://bits.wikimedia.org/skins-1.5/common/images/poweredby_mediawiki_88x31.png',
+                       'url' => 'http://upload.wikimedia.org/wikipedia/mediawiki/b/bc/Wiki.png',
                        'asyncdownload' => 1,
                        'filename' => 'UploadFromUrlTest.png',
                        'token' => $token,
@@ -182,7 +182,7 @@ class UploadFromUrlTest extends ApiTestCase {
                $data = $this->doApiRequest( array(
                        'action' => 'upload',
                        'filename' => 'UploadFromUrlTest.png',
-                       'url' => 'http://bits.wikimedia.org/skins-1.5/common/images/poweredby_mediawiki_88x31.png',
+                       'url' => 'http://upload.wikimedia.org/wikipedia/mediawiki/b/bc/Wiki.png',
                        'ignorewarnings' => true,
                        'token' => $token,
                ), $data );
@@ -213,7 +213,7 @@ class UploadFromUrlTest extends ApiTestCase {
                $this->doApiRequest( array(
                        'action' => 'upload',
                        'filename' => 'UploadFromUrlTest.png',
-                       'url' => 'http://bits.wikimedia.org/skins-1.5/common/images/poweredby_mediawiki_88x31.png',
+                       'url' => 'http://upload.wikimedia.org/wikipedia/mediawiki/b/bc/Wiki.png',
                        'asyncdownload' => 1,
                        'token' => $token,
                        'leavemessage' => 1,
@@ -234,7 +234,7 @@ class UploadFromUrlTest extends ApiTestCase {
                        $this->doApiRequest( array(
                                'action' => 'upload',
                                'filename' => 'UploadFromUrlTest.png',
-                               'url' => 'http://bits.wikimedia.org/skins-1.5/common/images/poweredby_mediawiki_88x31.png',
+                               'url' => 'http://upload.wikimedia.org/wikipedia/mediawiki/b/bc/Wiki.png',
                                'asyncdownload' => 1,
                                'token' => $token,
                                'leavemessage' => 1,
@@ -270,13 +270,16 @@ class UploadFromUrlTest extends ApiTestCase {
         * Helper function to perform an async upload, execute the job and fetch
         * the status
         *
+        * @param string $token
+        * @param bool $ignoreWarnings
+        * @param bool $leaveMessage
         * @return array The result of action=upload&statuskey=key
         */
        private function doAsyncUpload( $token, $ignoreWarnings = false, $leaveMessage = false ) {
                $params = array(
                        'action' => 'upload',
                        'filename' => 'UploadFromUrlTest.png',
-                       'url' => 'http://bits.wikimedia.org/skins-1.5/common/images/poweredby_mediawiki_88x31.png',
+                       'url' => 'http://upload.wikimedia.org/wikipedia/mediawiki/b/bc/Wiki.png',
                        'asyncdownload' => 1,
                        'token' => $token,
                );
index 89759e5..0fdb8e1 100644 (file)
@@ -35,7 +35,9 @@ class StringUtilsTest extends MediaWikiTestCase {
        }
 
        /**
-        * Print high range characters as an hexadecimal
+        * Print high range characters as a hexadecimal
+        * @param string $string
+        * @return string
         */
        function escaped( $string ) {
                $escaped = '';
diff --git a/tests/phpunit/languages/LanguageArqTest.php b/tests/phpunit/languages/LanguageArqTest.php
new file mode 100644 (file)
index 0000000..3fa56d7
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Based on LanguageMlTest
+ * @author Joel Sahleen
+ * @copyright Copyright © 2014, Joel Sahleen
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageArq.php */
+class LanguageArqTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider provideNumber
+        * @covers Language::formatNum
+        */
+       public function testFormatNum( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->formatNum( $value ) );
+       }
+
+       public static function provideNumber() {
+               return array(
+                       array( '1.234.567', '1234567'),
+                       array( '-12,89', -12.89 ),
+                       );
+       }
+
+}
index ef670df..cff2e8f 100644 (file)
@@ -276,7 +276,7 @@ class LanguageTest extends LanguageClassesTestCase {
        }
 
        /**
-        * @return array format is ($len, $ellipsis, $input, $expected)
+        * @return array Format is ($len, $ellipsis, $input, $expected)
         */
        public static function provideHTMLTruncateData() {
                return array(
@@ -457,32 +457,22 @@ class LanguageTest extends LanguageClassesTestCase {
         * @dataProvider provideLanguageCodes
         * @covers Language::isValidBuiltInCode
         */
-       public function testBuiltInCodeValidation( $code, $message = '' ) {
-               $this->assertTrue(
+       public function testBuiltInCodeValidation( $code, $expected, $message = '' ) {
+               $this->assertEquals( $expected,
                        (bool)Language::isValidBuiltInCode( $code ),
                        "validating code $code $message"
                );
        }
 
-       /**
-        * @covers Language::isValidBuiltInCode
-        */
-       public function testBuiltInCodeValidationRejectUnderscore() {
-               $this->assertFalse(
-                       (bool)Language::isValidBuiltInCode( 'be_tarask' ),
-                       "reject underscore in language code"
-               );
-       }
-
        public static function provideLanguageCodes() {
                return array(
-                       array( 'fr', 'Two letters, minor case' ),
-                       array( 'EN', 'Two letters, upper case' ),
-                       array( 'tyv', 'Three letters' ),
-                       array( 'tokipona', 'long language code' ),
-                       array( 'be-tarask', 'With dash' ),
-                       array( 'Zh-classical', 'Begin with upper case, dash' ),
-                       array( 'Be-x-old', 'With extension (two dashes)' ),
+                       array( 'fr', true, 'Two letters, minor case' ),
+                       array( 'EN', false, 'Two letters, upper case' ),
+                       array( 'tyv', true, 'Three letters' ),
+                       array( 'tokipona', true, 'long language code' ),
+                       array( 'be-tarask', true, 'With dash' ),
+                       array( 'be-x-old', true, 'With extension (two dashes)' ),
+                       array( 'be_tarask', false, 'Reject underscores' ),
                );
        }
 
index 4f0d24f..8b6aef5 100644 (file)
@@ -30,9 +30,9 @@ abstract class DumpTestCase extends MediaWikiLangTestCase {
         *
         * @param Page $page Page to add the revision to
         * @param string $text Revisions text
-        * @param string $text Revisions summare
-        *
-        * @throws MWExcepion
+        * @param string $summary Revisions summare
+        * @return array
+        * @throws MWException
         */
        protected function addRevision( Page $page, $text, $summary ) {
                $status = $page->doEditContent(
@@ -181,7 +181,7 @@ abstract class DumpTestCase extends MediaWikiLangTestCase {
         * Asserts that the xml reader is at the final closing tag of an xml file and
         * closes the reader.
         *
-        * @param string $tag (optional) the name of the final tag
+        * @param string $name (optional) the name of the final tag
         *   (e.g.: "mediawiki" for </mediawiki>)
         */
        protected function assertDumpEnd( $name = "mediawiki" ) {
@@ -304,9 +304,9 @@ abstract class DumpTestCase extends MediaWikiLangTestCase {
         * @param string $text_sha1 The base36 SHA-1 of the revision's text
         * @param string|bool $text (optional) The revision's string, or false to check for a
         *            revision stub
+        * @param int|bool $parentid (optional) id of the parent revision
         * @param string $model The expected content model id (default: CONTENT_MODEL_WIKITEXT)
         * @param string $format The expected format model id (default: CONTENT_FORMAT_WIKITEXT)
-        * @param int|bool $parentid (optional) id of the parent revision
         */
        protected function assertRevision( $id, $summary, $text_id, $text_bytes,
                $text_sha1, $text = false, $parentid = false,
index 42d1d0b..e2fc824 100644 (file)
@@ -81,7 +81,7 @@ class MaintenanceFixup extends Maintenance {
                        return;
                }
 
-               return call_user_func_array( array( "parent", __FUNCTION__ ), func_get_args() );
+               call_user_func_array( array( "parent", __FUNCTION__ ), func_get_args() );
        }
 
        /**
@@ -810,4 +810,21 @@ class MaintenanceTest extends MediaWikiTestCase {
                $m2->simulateShutdown();
                $this->assertOutputPrePostShutdown( "foobar\n\n", false );
        }
+
+       /**
+        * @covers Maintenance::getConfig
+        */
+       public function testGetConfig() {
+               $this->assertInstanceOf( 'Config', $this->m->getConfig() );
+               $this->assertSame( ConfigFactory::getDefaultInstance()->makeConfig( 'main' ), $this->m->getConfig() );
+       }
+
+       /**
+        * @covers Maintenance::setConfig
+        */
+       public function testSetConfig() {
+               $conf = $this->getMock( 'Config' );
+               $this->m->setConfig( $conf );
+               $this->assertSame( $conf, $this->m->getConfig() );
+       }
 }
index 744cf61..5e0fe89 100644 (file)
@@ -11,7 +11,7 @@ require_once __DIR__ . "/../../../maintenance/backupPrefetch.inc";
 class BaseDumpTest extends MediaWikiTestCase {
 
        /**
-        * @var BaseDump the BaseDump instance used within a test.
+        * @var BaseDump The BaseDump instance used within a test.
         *
         * If set, this BaseDump gets automatically closed in tearDown.
         */
index 016b7e0..a37a97c 100644 (file)
@@ -434,7 +434,7 @@ class TextPassDumperTest extends DumpTestCase {
         *   revision id increase further and further, while the text
         *   id of the first iteration is reused. The pages and revision
         *   of iteration > 1 have no corresponding representation in the database.
-        * @return string absolute filename of the stub
+        * @return string Absolute filename of the stub
         */
        private function setUpStub( $fname = null, $iterations = 1 ) {
                if ( $fname === null ) {
index 8c40ffe..4e38418 100644 (file)
@@ -91,7 +91,7 @@ class FetchTextTest extends MediaWikiTestCase {
        private $exceptionFromAddDBData;
 
        /**
-        * @var FetchText the (mocked) FetchText that is to test
+        * @var FetchText The (mocked) FetchText that is to test
         */
        private $fetchText;
 
@@ -100,9 +100,9 @@ class FetchTextTest extends MediaWikiTestCase {
         *
         * @param WikiPage $page The page to add the revision to
         * @param string $text The revisions text
-        * @param string $text The revisions summare
-        *
-        * @throws MWExcepion
+        * @param string $summary The revisions summare
+        * @return int
+        * @throws MWException
         */
        private function addRevision( $page, $text, $summary ) {
                $status = $page->doEditContent(
diff --git a/tests/phpunit/maintenance/getSlaveServerTest.php b/tests/phpunit/maintenance/getSlaveServerTest.php
deleted file mode 100644 (file)
index 165dc55..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-<?php
-
-require_once __DIR__ . "/../../../maintenance/getSlaveServer.php";
-
-/**
- * Tests for getSlaveServer
- *
- * @group Database
- * @covers GetSlaveServer
- */
-class GetSlaveServerTest extends MediaWikiTestCase {
-
-       /**
-        * Yields a regular expression that matches a good DB server name
-        *
-        * It matches IPs or hostnames, both optionally followed by a
-        * port specification
-        *
-        * @return string The regular expression
-        */
-       private function getServerRE() {
-               if ( $this->db->getType() === 'sqlite' ) {
-                       // for SQLite, only the empty string is a good server name
-                       return '';
-               }
-
-               $octet = '([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])';
-               $ip = "(($octet\.){3}$octet)";
-
-               $label = '([a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)';
-               $hostname = "($label(\.$label)*)";
-
-               return "($ip|$hostname)(:[0-9]{1,5})?";
-       }
-
-       function testPlain() {
-               $gss = new GetSlaveServer();
-               $gss->execute();
-
-               $this->expectOutputRegex( "/^" . self::getServerRE() . "\n$/D" );
-       }
-
-       function testXmlDumpsBackupUseCase() {
-               global $wgDBprefix;
-
-               global $argv;
-               $argv = array( null, "--globals" );
-
-               $gss = new GetSlaveServer();
-               $gss->loadParamsAndArgs();
-               $gss->execute();
-               $gss->globals();
-
-               // The main answer
-               $output = $this->getActualOutput();
-               $firstLineEndPos = strpos( $output, "\n" );
-               if ( $firstLineEndPos === false ) {
-                       $this->fail( "Could not find end of first line of output" );
-               }
-               $firstLine = substr( $output, 0, $firstLineEndPos );
-               $this->assertRegExp( "/^" . self::getServerRE() . "$/D",
-                       $firstLine, "DB Server" );
-
-               // xmldumps-backup relies on the wgDBprefix in the output.
-               $this->expectOutputRegex( "/^[[:space:]]*\[wgDBprefix\][[:space:]]*=> "
-                       . $wgDBprefix . "$/m" );
-       }
-}
index b2f7fac..e0a72fd 100644 (file)
@@ -35,6 +35,13 @@ class MockImageHandler {
         * a thumbnail at all. That is merely returning a ThumbnailImage that
         * will be consumed by the unit test.  There is no need to create a real
         * thumbnail on the filesystem.
+        * @param ImageHandler $that
+        * @param File $image
+        * @param string $dstPath
+        * @param string $dstUrl
+        * @param array $params
+        * @param int $flags
+        * @return ThumbnailImage
         */
        static function doFakeTransform( $that, $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
                # Example of what we receive:
index d2a4132..1125504 100755 (executable)
@@ -15,6 +15,18 @@ require_once dirname( dirname( __DIR__ ) ) . "/maintenance/Maintenance.php";
 
 class PHPUnitMaintClass extends Maintenance {
 
+       public static $additionalOptions = array(
+               'regex' => false,
+               'file' => false,
+               'use-filebackend' => false,
+               'use-bagostuff' => false,
+               'use-jobqueue' => false,
+               'keep-uploads' => false,
+               'use-normal-tables' => false,
+               'reuse-db' => false,
+               'wiki' => false,
+       );
+
        public function __construct() {
                parent::__construct();
                $this->addOption(
@@ -24,6 +36,20 @@ class PHPUnitMaintClass extends Maintenance {
                        false, # not required
                        true # need arg
                );
+               $this->addOption(
+                       'debug-tests',
+                       'Log testing activity to the PHPUnitCommand log channel.',
+                       false, # not required
+                       false # no arg needed
+               );
+               $this->addOption( 'regex', 'Only run parser tests that match the given regex.', false, true );
+               $this->addOption( 'file', 'File describing parser tests.', false, true );
+               $this->addOption( 'use-filebackend', 'Use filebackend', false, true );
+               $this->addOption( 'use-bagostuff', 'Use bagostuff', false, true );
+               $this->addOption( 'use-jobqueue', 'Use jobqueue', false, true );
+               $this->addOption( 'keep-uploads', 'Re-use the same upload directory for each test, don\'t delete it.', false, false );
+               $this->addOption( 'use-normal-tables', 'Use normal DB tables.', false, false );
+               $this->addOption( 'reuse-db', 'Init DB only if tables are missing and keep after finish.', false, false );
        }
 
        public function finalSetup() {
@@ -67,6 +93,8 @@ class PHPUnitMaintClass extends Maintenance {
        public function execute() {
                global $IP;
 
+               $this->forceFormatServerArgv();
+
                # Make sure we have --configuration or PHPUnit might complain
                if ( !in_array( '--configuration', $_SERVER['argv'] ) ) {
                        //Hack to eliminate the need to use the Makefile (which sucks ATM)
@@ -75,17 +103,12 @@ class PHPUnitMaintClass extends Maintenance {
                }
 
                # --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' );
-                       # Sanity checks
-                       if ( !is_dir( $phpunitDir ) ) {
-                               $this->error( "--with-phpunitdir should be set to an existing directory", 1 );
-                       }
-                       if ( !is_readable( $phpunitDir . "/PHPUnit/Runner/Version.php" ) ) {
-                               $this->error( "No usable PHPUnit installation in $phpunitDir.\nAborting.\n", 1 );
-                       }
 
-                       # Now prepends provided PHPUnit directory
+                       # prepends provided PHPUnit directory or phar
                        $this->output( "Will attempt loading PHPUnit from `$phpunitDir`\n" );
                        set_include_path( $phpunitDir . PATH_SEPARATOR . get_include_path() );
 
@@ -105,7 +128,7 @@ class PHPUnitMaintClass extends Maintenance {
                        # The below code injects a parameter just like if the user called
                        # Probably fix bug 29226
                        $key = array_search( '--colors', $_SERVER['argv'] );
-                       if( $key === false ) {
+                       if ( $key === false ) {
                                array_splice( $_SERVER['argv'], 1, 0, '--colors' );
                        }
                }
@@ -115,7 +138,7 @@ class PHPUnitMaintClass extends Maintenance {
                # PHPUnit uses stream_resolve_include_path() internally
                # See bug 32022
                $key = array_search( '--include-path', $_SERVER['argv'] );
-               if( $key === false ) {
+               if ( $key === false ) {
                        array_splice( $_SERVER['argv'], 1, 0,
                                __DIR__
                                . PATH_SEPARATOR
@@ -123,38 +146,88 @@ class PHPUnitMaintClass extends Maintenance {
                        );
                        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] );
+                       array_splice( $_SERVER['argv'], 1, 0, 'MediaWikiPHPUnitTestListener' );
+                       array_splice( $_SERVER['argv'], 1, 0, '--printer' );
+               }
+
+               foreach ( self::$additionalOptions as $option => $default ) {
+                       $key = array_search( '--' . $option, $_SERVER['argv'] );
+                       if ( $key !== false ) {
+                               unset( $_SERVER['argv'][$key] );
+                               if ( $this->mParams[$option]['withArg'] ) {
+                                       self::$additionalOptions[$option] = $_SERVER['argv'][$key + 1];
+                                       unset( $_SERVER['argv'][$key + 1] );
+                               } else {
+                                       self::$additionalOptions[$option] = true;
+                               }
+                       }
+               }
+
        }
 
        public function getDbType() {
                return Maintenance::DB_ADMIN;
        }
+
+       /**
+        * Force the format of elements in $_SERVER['argv']
+        *  - Split args such as "wiki=enwiki" into two separate arg elements "wiki" and "enwiki"
+        */
+       private function forceFormatServerArgv() {
+               $argv = array();
+               foreach ( $_SERVER['argv'] as $key => $arg ) {
+                       if ( $key === 0 ) {
+                               $argv[0] = $arg;
+                       } elseif ( strstr( $arg, '=' ) ) {
+                               foreach ( explode( '=', $arg, 2 ) as $argPart ) {
+                                       $argv[] = $argPart;
+                               }
+                       } else {
+                               $argv[] = $arg;
+                       }
+               }
+               $_SERVER['argv'] = $argv;
+       }
+
 }
 
 $maintClass = 'PHPUnitMaintClass';
 require RUN_MAINTENANCE_IF_MAIN;
 
-if ( !class_exists( 'PHPUnit_Runner_Version' ) ) {
-       require_once 'PHPUnit/Runner/Version.php';
+// Prevent segfault when we have lots of unit tests (bug 62623)
+if ( version_compare( PHP_VERSION, '5.4.0', '<' ) ) {
+       register_shutdown_function( function () {
+               gc_collect_cycles();
+               gc_disable();
+       } );
 }
 
-if ( PHPUnit_Runner_Version::id() !== '@package_version@'
-       && version_compare( PHPUnit_Runner_Version::id(), '3.7.0', '<' )
-) {
-       die( 'PHPUnit 3.7.0 or later required, you have ' . PHPUnit_Runner_Version::id() . ".\n" );
+
+$ok = false;
+
+foreach ( array(
+       stream_resolve_include_path( 'phpunit.phar' ),
+       'PHPUnit/Runner/Version.php',
+       'PHPUnit/Autoload.php'
+) as $includePath ) {
+       @include_once $includePath;
+       if ( class_exists( 'PHPUnit_TextUI_Command' ) ) {
+               $ok = true;
+               break;
+       }
 }
 
-if ( !class_exists( 'PHPUnit_TextUI_Command' ) ) {
-       require_once 'PHPUnit/Autoload.php';
+if ( !$ok ) {
+       die( "Couldn't find a usable PHPUnit.\n" );
 }
 
-// Prevent segfault when we have lots of unit tests (bug 62623)
-if ( version_compare( PHP_VERSION, '5.4.0', '<' )
-       && version_compare( PHP_VERSION, '5.3.0', '>=' )
-) {
-       register_shutdown_function( function() {
-               gc_collect_cycles();
-               gc_disable();
-       } );
+$puVersion = PHPUnit_Runner_Version::id();
+if ( $puVersion !== '@package_version@' && version_compare( $puVersion, '3.7.0', '<' ) ) {
+       die( "PHPUnit 3.7.0 or later required; you have {$puVersion}.\n" );
 }
 
-MediaWikiPHPUnitCommand::main();
+PHPUnit_TextUI_Command::main();
index 12f147e..2bdc9c9 100644 (file)
@@ -74,13 +74,23 @@ class AutoLoaderTest extends MediaWikiTestCase {
                                )
                        /imx', $contents, $matches, PREG_SET_ORDER );
 
+                       $namespaceMatch = array();
+                       preg_match( '/
+                               ^ [\t ]*
+                                       namespace \s+
+                                               ([a-zA-Z0-9_]+(\\\\[a-zA-Z0-9_]+)*)
+                                       \s* ;
+                       /imx', $contents, $namespaceMatch );
+                       $fileNamespace = $namespaceMatch ? $namespaceMatch[1] . '\\' : '';
+
                        $classesInFile = array();
                        $aliasesInFile = array();
 
                        foreach ( $matches as $match ) {
                                if ( !empty( $match['class'] ) ) {
-                                       $actual[$match['class']] = $file;
-                                       $classesInFile[$match['class']] = true;
+                                       $class = $fileNamespace . $match['class'];
+                                       $actual[$class] = $file;
+                                       $classesInFile[$class] = true;
                                } else {
                                        $aliasesInFile[$match['alias']] = $match['original'];
                                }
index d7742a6..2396ea2 100644 (file)
@@ -37,10 +37,15 @@ class ResourcesTest extends MediaWikiTestCase {
                );
        }
 
-       public function testDependencies() {
+       /**
+        * Verify that nothing explicitly depends on the 'jquery' and 'mediawiki' modules.
+        * They are always loaded, depending on them is unsupported and leads to unexpected behaviour.
+        */
+       public function testIllegalDependencies() {
                $data = self::getAllModules();
                $illegalDeps = array( 'jquery', 'mediawiki' );
 
+               /** @var ResourceLoaderModule $module */
                foreach ( $data['modules'] as $moduleName => $module ) {
                        foreach ( $illegalDeps as $illegalDep ) {
                                $this->assertNotContains(
@@ -52,8 +57,56 @@ class ResourcesTest extends MediaWikiTestCase {
                }
        }
 
+       /**
+        * Verify that all modules specified as dependencies of other modules actually exist.
+        */
+       public function testMissingDependencies() {
+               $data = self::getAllModules();
+               $validDeps = array_keys( $data['modules'] );
+
+               /** @var ResourceLoaderModule $module */
+               foreach ( $data['modules'] as $moduleName => $module ) {
+                       foreach ( $module->getDependencies() as $dep ) {
+                               $this->assertContains(
+                                       $dep,
+                                       $validDeps,
+                                       "The module '$dep' required by '$moduleName' must exist"
+                               );
+                       }
+               }
+       }
+
+       /**
+        * Verify that all dependencies of all modules are always satisfiable with the 'targets' defined
+        * for the involved modules.
+        *
+        * Example: A depends on B. A has targets: mobile, desktop. B has targets: desktop. Therefore the
+        * dependency is sometimes unsatisfiable: it's impossible to load module A on mobile.
+        */
+       public function testUnsatisfiableDependencies() {
+               $data = self::getAllModules();
+               $validDeps = array_keys( $data['modules'] );
+
+               /** @var ResourceLoaderModule $module */
+               foreach ( $data['modules'] as $moduleName => $module ) {
+                       $moduleTargets = $module->getTargets();
+                       foreach ( $module->getDependencies() as $dep ) {
+                               $targets = $data['modules'][$dep]->getTargets();
+                               foreach ( $moduleTargets as $moduleTarget ) {
+                                       $this->assertContains(
+                                               $moduleTarget,
+                                               $targets,
+                                               "The module '$moduleName' must not have target '$moduleTarget' "
+                                                       . "because its dependency '$dep' does not have it"
+                                       );
+                               }
+                       }
+               }
+       }
+
        /**
         * Get all registered modules from ResouceLoader.
+        * @return array
         */
        protected static function getAllModules() {
                global $wgEnableJavaScriptTest;
@@ -115,7 +168,7 @@ class ResourcesTest extends MediaWikiTestCase {
                                                        $media,
                                                        $file,
                                                        // XXX: Wrapped in an object to keep it out of PHPUnit output
-                                                       (object) array( 'cssText' => $readStyleFile->invoke( $module, $file, $flip ) ),
+                                                       (object)array( 'cssText' => $readStyleFile->invoke( $module, $file, $flip ) ),
                                                );
                                        }
                                }
@@ -206,7 +259,7 @@ class ResourcesTest extends MediaWikiTestCase {
                                $cases[] = array(
                                        $method->invoke( $module, $file ),
                                        $moduleName,
-                                       $file,
+                                       ( $file instanceof ResourceLoaderFilePath ? $file->getPath() : $file ),
                                );
                        }
                }
index f5cd892..14461be 100644 (file)
@@ -58,6 +58,8 @@ class StructureTest extends MediaWikiTestCase {
 
        /**
         * Filter to remove testUnitTestFileNamesEndWithTest false positives.
+        * @param string $filename
+        * @return bool
         */
        public function filterSuites( $filename ) {
                return strpos( $filename, __DIR__ . '/../suites/' ) !== 0;
index b27337b..d4a7bd3 100644 (file)
@@ -62,7 +62,6 @@ class UploadFromUrlTestSuite extends PHPUnit_Framework_TestSuite {
                $messageMemc = wfGetMessageCacheStorage();
                $parserMemc = wfGetParserCacheStorage();
 
-               // $wgContLang = new StubContLang;
                $wgUser = new User;
                $context = new RequestContext;
                $wgLang = $context->getLanguage();
@@ -96,6 +95,7 @@ class UploadFromUrlTestSuite extends PHPUnit_Framework_TestSuite {
 
        /**
         * Remove the dummy uploads directory
+        * @param string $dir
         */
        private function teardownUploadDir( $dir ) {
                if ( $this->keepUploads ) {
index b2b5322..34007ed 100644 (file)
@@ -8,14 +8,14 @@ return array(
 
        'test.sinonjs' => array(
                'scripts' => array(
-                       'resources/lib/sinonjs/sinon-1.9.0.js',
+                       'resources/lib/sinonjs/sinon-1.10.3.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.9.0.js',
+                       // 'resources/lib/sinonjs/sinon-ie-1.10.3.js',
                ),
                'targets' => array( 'desktop', 'mobile' ),
        ),
index 461ab87..61ebbf8 100644 (file)
@@ -65,7 +65,7 @@ require __DIR__ . '/../../../maintenance/Maintenance.php';
 
 class GenerateJqueryMsgData extends Maintenance {
 
-       static $keyToTestArgs = array(
+       public static $keyToTestArgs = array(
                'undelete_short' => array(
                        array( 0 ),
                        array( 1 ),
index 50e89da..2eda8f1 100644 (file)
                                        // As a convenience feature, automatically restore warnings if they're
                                        // still suppressed by the end of the test.
                                        restoreWarnings();
+
+                                       // Check for incomplete animations/requests/etc and throw
+                                       // error if there are any.
+                                       if ( $.timers && $.timers.length !== 0 ) {
+                                               // Test may need to use fake timers, wait for animations or
+                                               // call $.fx.stop().
+                                               throw new Error( 'Unfinished animations: ' + $.timers.length );
+                                       }
+                                       if ( $.active !== undefined && $.active !== 0 ) {
+                                               // Test may need to use fake XHR, wait for requests or
+                                               // call abort().
+                                               throw new Error( 'Unfinished AJAX requests: ' + $.active );
+                                       }
                                }
                        };
                };
index 842817f..e8c5121 100644 (file)
                // Add two characters using scary black magic
                spanText = $span.text();
                d = findDivergenceIndex( origText, spanText );
-               spanTextNew = spanText.substr( 0, d ) + origText[d] + origText[d] + '...';
+               spanTextNew = spanText.slice( 0, d ) + origText[d] + origText[d] + '...';
 
                assert.gt( spanTextNew.length, spanText.length, 'Verify that the new span-length is indeed greater' );
 
                // Put this text in the span and verify it doesn't fit
                $span.text( spanTextNew );
-               // In IE6 width works like min-width, allow IE6's width to be "equal to"
-               if ( $.client.test( { 'msie': 6 }, $.client.profile(), true ) ) {
-                       assert.gtOrEq( $span.width(), $span.parent().width(), 'Fit is maximal (adding two characters makes it not fit any more) - IE6: Maybe equal to as well due to width behaving like min-width in IE6' );
-               } else {
-                       assert.gt( $span.width(), $span.parent().width(), 'Fit is maximal (adding two characters makes it not fit any more)' );
-               }
+               assert.gt( $span.width(), $span.parent().width(), 'Fit is maximal (adding two characters makes it not fit any more)' );
        } );
 
 }( jQuery ) );
index 9216ac9..92dad9f 100644 (file)
                                '</table>'
                );
                $table.tablesorter();
-               assert.equal( 0,
-                       $table.find( '#A2' ).prop( 'headerIndex' ),
-                       'A2 should be a sort header'
+               assert.equal( $table.find( '#A2' ).prop( 'headerIndex' ),
+                       undefined,
+                       'A2 should not be a sort header'
                );
-               assert.equal( 1, // should be 2
-                       $table.find( '#C1' ).prop( 'headerIndex' ),
-                       'C1 should be a sort header, but will sort the wrong column'
+               assert.equal( $table.find( '#C1' ).prop( 'headerIndex' ),
+                       2,
+                       'C1 should be a sort header'
+               );
+       } );
+
+       // bug 53527
+       QUnit.test( 'td cells in thead should not be taken into account for longest row calculation', 2, function ( assert ) {
+               var $table = $(
+                       '<table class="sortable">' +
+                               '<thead>' +
+                               '<tr><th id="A1">A1</th><th>B1</th><td id="C1">C1</td></tr>' +
+                               '<tr><th id="A2">A2</th><th>B2</th><th id="C2">C2</th></tr>' +
+                               '</thead>' +
+                               '</table>'
+               );
+               $table.tablesorter();
+               assert.equal( $table.find( '#C2' ).prop( 'headerIndex' ),
+                       2,
+                       'C2 should be a sort header'
+               );
+               assert.equal( $table.find( '#C1' ).prop( 'headerIndex' ),
+                       undefined,
+                       'C1 should not be a sort header'
                );
        } );
 
                        '</tbody></table>' );
 
                        $table.tablesorter();
-                       assert.equal( 2, $table.find( 'tr:eq(1) th:eq(1)').prop('headerIndex'), 'Incorrect index of sort header' );
+                       assert.equal( $table.find( 'tr:eq(1) th:eq(1)').prop('headerIndex'),
+                               2,
+                               'Incorrect index of sort header' );
                }
        );
 
index 2191c3b..56b0fa9 100644 (file)
 
                        $( '#qunit-fixture' ).append( $textarea );
 
-                       // This method is actually missing atm...
-                       //$textarea.textSelection( 'setContents', opt.before.text);
-
-                       // Won't work with the WikiEditor iframe?
-                       $textarea.val( opt.before.text );
+                       $textarea.textSelection( 'setContents', opt.before.text );
 
                        start = opt.before.start;
                        end = opt.before.end;
index bc4b253..906fd27 100644 (file)
@@ -40,7 +40,8 @@
                        'gender-msg-currentuser': '{{GENDER:|blue|pink|green}}',
 
                        'plural-msg': 'Found $1 {{PLURAL:$1|item|items}}',
-
+                       // See https://bugzilla.wikimedia.org/69993
+                       'plural-msg-explicit-forms-nested': 'Found {{PLURAL:$1|$1 results|0=no results in {{SITENAME}}|1=$1 result}}',
                        // Assume the grammar form grammar_case_foo is not valid in any language
                        'grammar-msg': 'Przeszukaj {{GRAMMAR:grammar_case_foo|{{SITENAME}}}}',
 
                );
        } );
 
-       QUnit.test( 'Plural', 3, function ( assert ) {
+       QUnit.test( 'Plural', 6, 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 ' + mw.config.get( 'wgSiteName' ), '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' );
        } );
 
        QUnit.test( 'Gender', 15, function ( assert ) {
        } );
 
 // Tests that {{-transformation vs. general parsing are done as requested
-       QUnit.test( 'Curly brace transformation', 14, function ( assert ) {
+       QUnit.test( 'Curly brace transformation', 16, function ( assert ) {
                var oldUserLang = mw.config.get( 'wgUserLanguage' );
 
                assertBothModes( assert, ['gender-msg', 'Bob', 'male'], 'Bob: blue', 'gender is resolved' );
                        'Foo <a href="http://example.com">bar</a>',
                        'External link message processed when format is \'parse\''
                );
+               assert.htmlEqual(
+                       formatParse( 'external-link-replace', $( '<i>' ) ),
+                       'Foo <i>bar</i>',
+                       'External link message processed as jQuery object when format is \'parse\''
+               );
+               assert.htmlEqual(
+                       formatParse( 'external-link-replace', function () {} ),
+                       'Foo <a href="#">bar</a>',
+                       'External link message processed as function when format is \'parse\''
+               );
 
                mw.config.set( 'wgUserLanguage', oldUserLang );
        } );
index 3bfabe4..16f90df 100644 (file)
                assert.equal( mw.language.getData( 'en', 'invalidkey' ), undefined, 'Getter setter test for mw.language with invalid key' );
        } );
 
+       QUnit.test( 'mw.language.commafy test', 9, function ( assert ) {
+               // Number grouping patterns are as per http://cldr.unicode.org/translation/number-patterns
+               assert.equal( mw.language.commafy( 1234.567, '###0.#####' ), '1234.567', 'Pattern with no digit grouping separator defined' );
+               assert.equal( mw.language.commafy( 123456789.567, '###0.#####' ), '123456789.567', 'Pattern with no digit grouping seperator defined, bigger decimal part' );
+               assert.equal( mw.language.commafy( 0.567, '###0.#####' ), '0.567', 'Decimal part 0' );
+               assert.equal( mw.language.commafy( '.567', '###0.#####' ), '0.567', 'Decimal part missing. replace with zero' );
+               assert.equal( mw.language.commafy( 1234, '##,#0.#####' ), '12,34', 'Pattern with no fractional part' );
+               assert.equal( mw.language.commafy( -1234.567, '###0.#####' ), '-1234.567', 'Negative number' );
+               assert.equal( mw.language.commafy( -1234.567, '#,###.00' ), '-1,234.56', 'Fractional part bigger than pattern.' );
+               assert.equal( mw.language.commafy( 123456789.567, '###,##0.00' ), '123,456,789.56', 'Decimal part as group of 3' );
+               assert.equal( mw.language.commafy( 123456789.567, '###,###,#0.00' ), '1,234,567,89.56', 'Decimal part as group of 3 and last one 2' );
+       } );
+
        function grammarTest( langCode, test ) {
                // The test works only if the content language is opt.language
                // because it requires [lang].js to be loaded.
                        grammarTest( langCode, test );
                }
        } );
+
+       QUnit.test( 'List to text test', 4, function ( assert ) {
+               assert.equal( mw.language.listToText( [] ), '', 'Blank list' );
+               assert.equal( mw.language.listToText( ['a'] ), 'a', 'Single item' );
+               assert.equal( mw.language.listToText( ['a', 'b'] ), 'a and b', 'Two items' );
+               assert.equal( mw.language.listToText( ['a', 'b', 'c'] ), 'a, b and c', 'More than two items' );
+       } );
 }( mediaWiki, jQuery ) );
index 9681330..7e0ee91 100644 (file)
@@ -32,9 +32,7 @@
 
        mw.loader.addSource(
                'testloader',
-               {
-                       loadScript: QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/load.mock.php' )
-               }
+               QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/load.mock.php' )
        );
 
        QUnit.test( 'Initial check', 8, function ( assert ) {
                // Confirm that mw.loader.load() works with protocol-relative URLs
                target = target.replace( /https?:/, '' );
 
-               assert.equal( target.substr( 0, 2 ), '//',
+               assert.equal( target.slice( 0, 2 ), '//',
                        'URL must be relative to test relative URLs!'
                );
 
index 4e26bdc..ed03418 100644 (file)
@@ -1,7 +1,6 @@
 /*global isCompatible: true */
 ( function ( $ ) {
        var testcases = {
-               // Supported: Compatible
                gradeA: [
                        // Chrome
                        'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.205 Safari/534.16',
                        'Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Kindle Fire Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Safari/533.1',
                        // Safari 5.0+
                        'Mozilla/5.0 (Macintosh; I; Intel Mac OS X 10_6_7; ru-ru) AppleWebKit/534.31+ (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1',
-                       // Opera 11+
-                       'Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10',
-                       // Internet Explorer 6+
-                       'Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1)',
-                       'Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.0; en-US)',
+                       // Opera 12+ (Presto-based)
+                       'Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00',
+                       'Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.17',
+                       // Opera 15+ (Chromium-based)
+                       'Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36 OPR/15.0.1147.153',
+                       'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36 OPR/16.0.1196.62',
+                       'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36 OPR/23.0.1522.75',
+                       // Internet Explorer 8+
                        'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; Media Center PC 4.0; SLCC1; .NET CLR 3.0.04320)',
                        'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)',
                        'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)',
                        // Android
                        'Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17'
                ],
-               // Supported: Uncompatible, serve basic content
-               gradeB: [
-                       // Internet Explorer < 6
+               gradeC: [
+                       // Internet Explorer < 8
                        'Mozilla/2.0 (compatible; MSIE 3.03; Windows 3.1)',
                        'Mozilla/4.0 (compatible; MSIE 4.01; Windows 95)',
                        'Mozilla/4.0 (compatible; MSIE 5.0; Windows 98;)',
                        'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
-                       // Firefox < 3.6
+                       'Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1)',
+                       'Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.0; en-US)',
+                       // Firefox < 3
                        'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.2) Gecko/20060308 Firefox/1.5.0.2',
                        'Mozilla/5.0 (X11; U; Linux i686; nl; rv:1.8.1.1) Gecko/20070311 Firefox/2.0.0.1',
+                       // Opera < 12
+                       'Mozilla/5.0 (Windows NT 5.0; U) Opera 7.54 [en]',
+                       'Opera/7.54 (Windows NT 5.0; U) [en]',
+                       'Mozilla/5.0 (Windows NT 5.1; U; en) Opera 8.0',
+                       'Opera/8.0 (X11; Linux i686; U; cs)',
+                       'Opera/9.00 (X11; Linux i686; U; de)',
+                       'Opera/9.62 (X11; Linux i686; U; en) Presto/2.1.1',
+                       'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.2.15 Version/10.00',
+                       'Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10',
+                       'Opera/9.80 (Windows NT 6.1; WOW64; U; pt) Presto/2.10.229 Version/11.62',
                        // BlackBerry < 6
                        'BlackBerry9300/5.0.0.716 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/133',
                        'BlackBerry7250/4.0.0 Profile/MIDP-2.0 Configuration/CLDC-1.1',
@@ -75,8 +88,7 @@
                        // Google Glass
                        'Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; Glass 1 Build/IMM76L; XE11) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
                ],
-               // No explicit support for or against these browsers, they're
-               // given a shot at Grade A at their own risk.
+               // No explicit support for or against these browsers, they're given a shot at Grade A.
                gradeX: [
                        // Firefox 3.6
                        'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3',
                );
        } );
 
-       QUnit.test( 'isCompatible( Grade B )', testcases.gradeB.length, function ( assert ) {
-               $.each( testcases.gradeB, function ( i, ua ) {
+       QUnit.test( 'isCompatible( Grade C )', testcases.gradeC.length, function ( assert ) {
+               $.each( testcases.gradeC, function ( i, ua ) {
                                assert.strictEqual( isCompatible( ua ), false, ua );
                        }
                );
index d2e7f6e..62dccbf 100644 (file)
  */
 interface ITestRecorder {
 
-       /** Called at beginning of the parser test run */
+       /**
+        * Called at beginning of the parser test run
+        */
        public function start();
 
-       /** Called after each test */
+       /**
+        * Called after each test
+        * @param string $test
+        * @param bool $result
+        */
        public function record( $test, $result );
 
-       /** Called before finishing the test run */
+       /**
+        * Called before finishing the test run
+        */
        public function report();
 
-       /** Called at the end of the parser test run */
+       /**
+        * Called at the end of the parser test run
+        */
        public function end();
 
 }
 
 class TestRecorder implements ITestRecorder {
-       var $parent;
-       var $term;
+       public $parent;
+       public $term;
 
        function __construct( $parent ) {
                $this->parent = $parent;
@@ -107,6 +117,7 @@ class DbTestPreviewer extends TestRecorder {
 
        /**
         * This should be called before the table prefix is changed
+        * @param TestRecorder $parent
         */
        function __construct( $parent ) {
                parent::__construct( $parent );
@@ -220,6 +231,9 @@ class DbTestPreviewer extends TestRecorder {
         * Returns a string giving information about when a test last had a status change.
         * Could help to track down when regressions were introduced, as distinct from tests
         * which have never passed (which are more change requests than regressions).
+        * @param string $testname
+        * @param string $after
+        * @return string
         */
        private function getTestStatusInfo( $testname, $after ) {
                // If we're looking at a test that has just been removed, then say when it first appeared.
@@ -295,7 +309,7 @@ class DbTestPreviewer extends TestRecorder {
 }
 
 class DbTestRecorder extends DbTestPreviewer {
-       var $version;
+       public $version;
 
        /**
         * Set up result recording; insert a record for the run with the date
@@ -318,7 +332,7 @@ class DbTestRecorder extends DbTestPreviewer {
                        array(
                                'tr_date' => $this->db->timestamp(),
                                'tr_mw_version' => $this->version,
-                               'tr_php_version' => phpversion(),
+                               'tr_php_version' => PHP_VERSION,
                                'tr_db_version' => $this->db->getServerVersion(),
                                'tr_uname' => php_uname()
                        ),
@@ -352,7 +366,11 @@ class DbTestRecorder extends DbTestPreviewer {
 class TestFileIterator implements Iterator {
        private $file;
        private $fh;
-       private $parserTest; /* An instance of ParserTest (parserTests.php) or MediaWikiParserTest (phpunit) */
+       /**
+        * @var ParserTest|MediaWikiParserTest An instance of ParserTest (parserTests.php)
+        *  or MediaWikiParserTest (phpunit)
+        */
+       private $parserTest;
        private $index = 0;
        private $test;
        private $section = null;
@@ -360,6 +378,10 @@ class TestFileIterator implements Iterator {
        private $sectionData = array();
        private $lineNum;
        private $eof;
+       # Create a fake parser tests which never run anything unless
+       # asked to do so. This will avoid running hooks for a disabled test
+       private $delayedParserTest;
+       private $nextSubTest = 0;
 
        function __construct( $file, $parserTest ) {
                $this->file = $file;
@@ -370,6 +392,7 @@ class TestFileIterator implements Iterator {
                }
 
                $this->parserTest = $parserTest;
+               $this->delayedParserTest = new DelayedParserTest();
 
                $this->lineNum = $this->index = 0;
        }
@@ -408,12 +431,73 @@ class TestFileIterator implements Iterator {
                return $this->eof != true;
        }
 
+       function setupCurrentTest() {
+               // "input" and "result" are old section names allowed
+               // for backwards-compatibility.
+               $input = $this->checkSection( array( 'wikitext', 'input' ), false );
+               $result = $this->checkSection( array( 'html/php', 'html/*', 'html', 'result' ), false );
+               // some tests have "with tidy" and "without tidy" variants
+               $tidy = $this->checkSection( array( 'html/php+tidy', 'html+tidy' ), false );
+               if ( $tidy != false ) {
+                       if ( $this->nextSubTest == 0 ) {
+                               if ( $result != false ) {
+                                       $this->nextSubTest = 1; // rerun non-tidy variant later
+                               }
+                               $result = $tidy;
+                       } else {
+                               $this->nextSubTest = 0; // go on to next test after this
+                               $tidy = false;
+                       }
+               }
+
+               if ( !isset( $this->sectionData['options'] ) ) {
+                       $this->sectionData['options'] = '';
+               }
+
+               if ( !isset( $this->sectionData['config'] ) ) {
+                       $this->sectionData['config'] = '';
+               }
+
+               $isDisabled = preg_match( '/\\bdisabled\\b/i', $this->sectionData['options'] ) && !$this->parserTest->runDisabled;
+               $isParsoidOnly = preg_match( '/\\bparsoid\\b/i', $this->sectionData['options'] ) && $result == 'html' && !$this->parserTest->runParsoid;
+               $isFiltered = !preg_match( "/" . $this->parserTest->regex . "/i", $this->sectionData['test'] );
+               if ( $input == false || $result == false || $isDisabled || $isParsoidOnly || $isFiltered ) {
+                       # disabled test
+                       return false;
+               }
+
+               # We are really going to run the test, run pending hooks and hooks function
+               wfDebug( __METHOD__ . " unleashing delayed test for: {$this->sectionData['test']}" );
+               $hooksResult = $this->delayedParserTest->unleash( $this->parserTest );
+               if ( !$hooksResult ) {
+                       # Some hook reported an issue. Abort.
+                       throw new MWException( "Problem running hook" );
+               }
+
+               $this->test = array(
+                       'test' => ParserTest::chomp( $this->sectionData['test'] ),
+                       'input' => ParserTest::chomp( $this->sectionData[$input] ),
+                       'result' => ParserTest::chomp( $this->sectionData[$result] ),
+                       'options' => ParserTest::chomp( $this->sectionData['options'] ),
+                       'config' => ParserTest::chomp( $this->sectionData['config'] ),
+               );
+               if ( $tidy != false ) {
+                       $this->test['options'] .= " tidy";
+               }
+               return true;
+       }
+
        function readNextTest() {
-               $this->clearSection();
+               # Run additional subtests of previous test
+               while ( $this->nextSubTest > 0 ) {
+                       if ( $this->setupCurrentTest() ) {
+                               return true;
+                       }
+               }
 
-               # Create a fake parser tests which never run anything unless
-               # asked to do so. This will avoid running hooks for a disabled test
-               $delayedParserTest = new DelayedParserTest();
+               $this->clearSection();
+               # Reset hooks for the delayed test object
+               $this->delayedParserTest->reset();
 
                while ( false !== ( $line = fgets( $this->fh ) ) ) {
                        $this->lineNum++;
@@ -426,7 +510,9 @@ class TestFileIterator implements Iterator {
                                        $this->checkSection( 'text' );
                                        $this->checkSection( 'article' );
 
-                                       $this->parserTest->addArticle( ParserTest::chomp( $this->sectionData['article'] ), $this->sectionData['text'], $this->lineNum );
+                                       $this->parserTest->addArticle(
+                                               ParserTest::chomp( $this->sectionData['article'] ),
+                                               $this->sectionData['text'], $this->lineNum );
 
                                        $this->clearSection();
 
@@ -440,7 +526,7 @@ class TestFileIterator implements Iterator {
                                                $line = trim( $line );
 
                                                if ( $line ) {
-                                                       $delayedParserTest->requireHook( $line );
+                                                       $this->delayedParserTest->requireHook( $line );
                                                }
                                        }
 
@@ -456,7 +542,7 @@ class TestFileIterator implements Iterator {
                                                $line = trim( $line );
 
                                                if ( $line ) {
-                                                       $delayedParserTest->requireFunctionHook( $line );
+                                                       $this->delayedParserTest->requireFunctionHook( $line );
                                                }
                                        }
 
@@ -483,54 +569,20 @@ class TestFileIterator implements Iterator {
 
                                if ( $this->section == 'end' ) {
                                        $this->checkSection( 'test' );
-                                       // "input" and "result" are old section names allowed
-                                       // for backwards-compatibility.
-                                       $input = $this->checkSection( array( 'wikitext', 'input' ), false );
-                                       $result = $this->checkSection( array( 'html/php', 'html/*', 'html', 'result' ), false );
-
-                                       if ( !isset( $this->sectionData['options'] ) ) {
-                                               $this->sectionData['options'] = '';
-                                       }
-
-                                       if ( !isset( $this->sectionData['config'] ) ) {
-                                               $this->sectionData['config'] = '';
-                                       }
-
-                                       if ( $input == false || $result == false ||
-                                               ( ( preg_match( '/\\bdisabled\\b/i', $this->sectionData['options'] ) && !$this->parserTest->runDisabled )
-                                               || ( preg_match( '/\\bparsoid\\b/i', $this->sectionData['options'] ) && $result != 'html/php' && !$this->parserTest->runParsoid )
-                                               || !preg_match( "/" . $this->parserTest->regex . "/i", $this->sectionData['test'] ) )
-                                       ) {
-                                               # disabled test
-                                               $this->clearSection();
-
-                                               # Forget any pending hooks call since test is disabled
-                                               $delayedParserTest->reset();
-
-                                               continue;
-                                       }
-
-                                       # We are really going to run the test, run pending hooks and hooks function
-                                       wfDebug( __METHOD__ . " unleashing delayed test for: {$this->sectionData['test']}" );
-                                       $hooksResult = $delayedParserTest->unleash( $this->parserTest );
-                                       if ( !$hooksResult ) {
-                                               # Some hook reported an issue. Abort.
-                                               return false;
-                                       }
-
-                                       $this->test = array(
-                                               'test' => ParserTest::chomp( $this->sectionData['test'] ),
-                                               'input' => ParserTest::chomp( $this->sectionData[ $input ] ),
-                                               'result' => ParserTest::chomp( $this->sectionData[ $result ] ),
-                                               'options' => ParserTest::chomp( $this->sectionData['options'] ),
-                                               'config' => ParserTest::chomp( $this->sectionData['config'] ),
-                                       );
-
-                                       return true;
+                                       do {
+                                               if ( $this->setupCurrentTest() ) {
+                                                       return true;
+                                               }
+                                       } while ( $this->nextSubTest > 0 );
+                                       # go on to next test (since this was disabled)
+                                       $this->clearSection();
+                                       $this->delayedParserTest->reset();
+                                       continue;
                                }
 
                                if ( isset( $this->sectionData[$this->section] ) ) {
-                                       throw new MWException( "duplicate section '$this->section' at line {$this->lineNum} of $this->file\n" );
+                                       throw new MWException( "duplicate section '$this->section' "
+                                               . "at line {$this->lineNum} of $this->file\n" );
                                }
 
                                $this->sectionData[$this->section] = '';
@@ -561,10 +613,11 @@ class TestFileIterator implements Iterator {
         * Throw an exception if it is not set, referencing current section
         * and adding the current file name and line number
         *
-        * @param string|array $token Expected token(s) that should have been
+        * @param string|array $tokens Expected token(s) that should have been
         * mentioned before closing this section
         * @param bool $fatal True iff an exception should be thrown if
         * the section is not found.
+        * @return bool|string
         */
        private function checkSection( $tokens, $fatal = true ) {
                if ( is_null( $this->section ) ) {
@@ -579,7 +632,7 @@ class TestFileIterator implements Iterator {
 
                $data = $this->sectionData;
                $tokens = array_filter( $tokens, function ( $token ) use ( $data ) {
-                       return isset( $data[ $token ] );
+                       return isset( $data[$token] );
                } );
 
                if ( count( $tokens ) == 0 ) {
@@ -605,7 +658,7 @@ class TestFileIterator implements Iterator {
                }
 
                $tokens = array_values( $tokens );
-               return $tokens[ 0 ];
+               return $tokens[0];
        }
 }
 
@@ -637,10 +690,12 @@ class DelayedParserTest {
         * Called whenever we actually want to run the hook.
         * Should be the case if we found the parserTest is not disabled
         * @param ParserTest|NewParserTest $parserTest
+        * @return bool
         */
        public function unleash( &$parserTest ) {
                if ( !( $parserTest instanceof ParserTest || $parserTest instanceof NewParserTest )     ) {
-                       throw new MWException( __METHOD__ . " must be passed an instance of ParserTest or NewParserTest classes\n" );
+                       throw new MWException( __METHOD__ . " must be passed an instance of ParserTest or "
+                               . "NewParserTest classes\n" );
                }
 
                # Trigger delayed hooks. Any failure will make us abort
@@ -692,7 +747,7 @@ class DelayedParserTest {
        /**
         * Similar to ParserTest object but does not run anything
         * Use unleash() to really execute the hook function
-        * @param string $fnHook
+        * @param string $hook
         */
        public function requireTransparentHook( $hook ) {
                $this->transparentHooks[] = $hook;
@@ -722,7 +777,7 @@ class DjVuSupport {
        }
 
        /**
-        * Returns if the DjVu tools are usable
+        * Returns true if the DjVu tools are usable
         *
         * @return bool
         */
@@ -735,3 +790,43 @@ class DjVuSupport {
                        && is_executable( $wgDjvuTxt );
        }
 }
+
+/**
+ * Initialize and detect the tidy support
+ */
+class TidySupport {
+       private $internalTidy;
+       private $externalTidy;
+
+       /**
+        * Determine if there is a usable tidy.
+        */
+       public function __construct() {
+               global $wgTidyBin;
+
+               $this->internalTidy = extension_loaded( 'tidy' ) &&
+                       class_exists( 'tidy' );
+
+               $this->externalTidy = is_executable( $wgTidyBin ) ||
+                       Installer::locateExecutableInDefaultPaths( array( $wgTidyBin ) )
+                       !== false;
+       }
+
+       /**
+        * Returns true if we should use internal tidy.
+        *
+        * @return bool
+        */
+       public function isInternal() {
+               return $this->internalTidy;
+       }
+
+       /**
+        * Returns true if tidy is usable
+        *
+        * @return bool
+        */
+       public function isEnabled() {
+               return $this->internalTidy || $this->externalTidy;
+       }
+}
index c0042c2..d8ed246 100644 (file)
--- a/thumb.php
+++ b/thumb.php
@@ -24,7 +24,7 @@
 define( 'MW_NO_OUTPUT_COMPRESSION', 1 );
 require __DIR__ . '/includes/WebStart.php';
 
-// Don't use fancy mime detection, just check the file extension for jpg/gif/png
+// Don't use fancy MIME detection, just check the file extension for jpg/gif/png
 $wgTrivialMimeDetection = true;
 
 if ( defined( 'THUMB_HANDLER' ) ) {
@@ -118,7 +118,7 @@ function wfStreamThumb( array $params ) {
        }
        if ( isset( $params['width'] ) && substr( $params['width'], -2 ) == 'px' ) {
                // strip the px (pixel) suffix, if found
-               $params['width'] = substr( $width, 0, strlen( $width ) - 2 );
+               $params['width'] = substr( $params['width'], 0, -2 );
        }
        if ( isset( $params['p'] ) ) {
                $params['page'] = $params['p'];
@@ -376,7 +376,7 @@ function wfGenerateThumbnail( File $file, array $params, $thumbName, $thumbPath
 
        $done = false;
        // Record failures on PHP fatals in addition to caching exceptions
-       register_shutdown_function( function() use ( &$done, $key ) {
+       register_shutdown_function( function () use ( &$done, $key ) {
                if ( !$done ) { // transform() gave a fatal
                        global $wgMemc;
                        // Randomize TTL to reduce stampedes
@@ -388,7 +388,8 @@ function wfGenerateThumbnail( File $file, array $params, $thumbName, $thumbPath
        $errorHtml = false;
 
        // guard thumbnail rendering with PoolCounter to avoid stampedes
-       // expensive files use a separate PoolCounter config so it is possible to set up a global limit on them
+       // expensive files use a separate PoolCounter config so it is possible
+       // to set up a global limit on them
        if ( $file->isExpensiveToThumbnail() ) {
                $poolCounterType = 'FileRenderExpensive';
        } else {
@@ -399,17 +400,17 @@ function wfGenerateThumbnail( File $file, array $params, $thumbName, $thumbPath
        try {
                $work = new PoolCounterWorkViaCallback( $poolCounterType, sha1( $file->getName() ),
                        array(
-                               'doWork' => function() use ( $file, $params ) {
+                               'doWork' => function () use ( $file, $params ) {
                                        return $file->transform( $params, File::RENDER_NOW );
                                },
-                               'getCachedWork' => function() use ( $file, $params, $thumbPath ) {
+                               'getCachedWork' => function () use ( $file, $params, $thumbPath ) {
                                        // If the worker that finished made this thumbnail then use it.
                                        // Otherwise, it probably made a different thumbnail for this file.
                                        return $file->getRepo()->fileExists( $thumbPath )
                                                ? $file->transform( $params, File::RENDER_NOW )
                                                : false; // retry once more in exclusive mode
                                },
-                               'fallback' => function() {
+                               'fallback' => function () {
                                        return wfMessage( 'generic-pool-error' )->parse();
                                },
                                'error' => function ( $status ) {
@@ -520,7 +521,8 @@ function wfExtractThumbRequestInfo( $thumbRel ) {
        $repo = RepoGroup::singleton()->getLocalRepo();
 
        $hashDirReg = $subdirReg = '';
-       for ( $i = 0; $i < $repo->getHashLevels(); $i++ ) {
+       $hashLevels = $repo->getHashLevels();
+       for ( $i = 0; $i < $hashLevels; $i++ ) {
                $subdirReg .= '[0-9a-f]';
                $hashDirReg .= "$subdirReg/";
        }
@@ -551,7 +553,7 @@ function wfExtractThumbRequestInfo( $thumbRel ) {
  * file handler.
  *
  * @param File $file File object for file in question
- * @param array $param Array of parameters so far
+ * @param array $params Array of parameters so far
  * @return array Parameters array with more parameters
  */
 function wfExtractThumbParams( $file, $params ) {
@@ -571,7 +573,7 @@ function wfExtractThumbParams( $file, $params ) {
                return $params; // valid thumbnail URL (via extension or config)
        }
 
-       // FIXME: Files in the temp zone don't set a mime type, which means
+       // FIXME: Files in the temp zone don't set a MIME type, which means
        // they don't have a handler. Which means we can't parse the param
        // string. However, not a big issue as what good is a param string
        // if you have no handler to make use of the param string and